function Blend._observeChildren(O)if typeof(O)=="\073\110\115\116\097\110\099\101"then return Observable.new(function(z)z:Fire(O)return O end)end if ValueObject.isValueObject(O)then return Observable.new(function(z)local s=Maid.new()local function c()local c=O.Value if typeof(c)=="\073\110\115\116\097\110\099\101"then s._current=c z:Fire(c)return end local N=Blend._observeChildren(c)if N then s._current=nil local O=false local c c=N:Subscribe(function(O)z:Fire(O)end,function(...)z:Fail(...)end,function()O=true if s._current==c then s._current=nil end end)if O then if c then MaidTaskUtils.doCleanup(c)end else s._current=c end return end s._current=nil end s:GiveTask(O.Changed:Connect(c))c()return s end)end if Brio.isBrio(O)then return Observable.new(function(z)if O:IsDead()then return nil end local s=O:GetValue()if typeof(s)=="\073\110\115\116\097\110\099\101"then local c=O:ToMaid()c:GiveTask(s)z:Fire(s)return c end local c=Blend._observeChildren(s)if c then local s=O:ToMaid()s:GiveTask(c:Subscribe(function(O)z:Fire(O)end,function(...)z:Fail(...)end,function()s:DoCleaning()end))return s end warn(("\085\110\107\110\111\119\110 \116\121\112\101 \105\110 \098\114\105\111 \037\113"):format(typeof(s)))return nil end)end if Promise.isPromise(O)then O=Rx.fromPromise(O)end if Signal.isSignal(O)or typeof(O)=="\082\066\088\083\099\114\105\112\116\083\105\103\110\097\108"then O=Rx.fromSignal(O)end if Observable.isObservable(O)then return Observable.new(function(z)local s=Maid.new()s:GiveTask(O:Subscribe(function(O)if typeof(O)=="\073\110\115\116\097\110\099\101"then s:GiveTask(O)z:Fire(O)return end local c=Blend._observeChildren(O)if c then local O=Maid.new()O:GiveTask(c:Subscribe(function(O)z:Fire(O)end,function(...)O:DoCleaning()z:Fail(...)end,function()O:DoCleaning()end))O:GiveTask(function()s[O]=nil end)s[O]=O else warn(("\070\097\105\108\101\100 \116\111 \099\111\110\118\101\114\116 \037\113 \105\110\116\111 \099\104\105\108\100\114\101\110"):format(tostring(O)))end end,function(...)z:Fire(...)end,function() end))return s end)end if type(O)=="\116\097\098\108\101"and not getmetatable(O)then local z={}for O,s in pairs(O)do local c=Blend._observeChildren(s)if c then table.insert(z,c)else warn(("\070\097\105\108\101\100 \116\111 \099\111\110\118\101\114\116 \091\037\115\093 \037\113 \105\110\116\111 \099\104\105\108\100\114\101\110"):format(tostring(O),tostring(s)))end end if next(z)then return Rx.merge(z)else return nil end end return nil end

function Blend._observeChildren(value)
	if typeof(value) == "Instance" then
		-- Should be uncommon
		return Observable.new(function(sub)
			sub:Fire(value)
			-- don't complete, as this would clean everything up
			return value
		end)
	end

	if ValueObject.isValueObject(value) then
		return Observable.new(function(sub)
			local maid = Maid.new()

			-- Switch instead of emitting every value.
			local function update()
				local result = value.Value
				if typeof(result) == "Instance" then
					maid._current = result
					sub:Fire(result)
					return
				end

				local observe = Blend._observeChildren(result)
				if observe then
					maid._current = nil

					local doCleanup = false
					local cleanup
					cleanup = observe:Subscribe(function(inst)
						sub:Fire(inst)
					end, function(...)
						sub:Fail(...)
					end, function()
						-- incase of immediate execution
						doCleanup = true

						-- Do not pass complete through to the end
						if maid._current == cleanup then
							maid._current = nil
						end
					end)

					-- TODO: Complete when valueobject cleans up

					if doCleanup then
						if cleanup then
							MaidTaskUtils.doCleanup(cleanup)
						end
					else
						maid._current = cleanup
					end

					return
				end

				maid._current = nil
			end
			maid:GiveTask(value.Changed:Connect(update))
			update()

			return maid
		end)
	end

	if Brio.isBrio(value) then
		return Observable.new(function(sub)
			if value:IsDead() then
				return nil
			end

			local result = value:GetValue()
			if typeof(result) == "Instance" then
				local maid = value:ToMaid()
				maid:GiveTask(result)
				sub:Fire(result)

				return maid
			end

			local observe = Blend._observeChildren(result)
			if observe then
				local maid = value:ToMaid()

				-- Subscription is for lifetime of brio, so we do
				-- not need to specifically add these results to the maid, and
				-- risk memory leak of the maid with a lot of items in it.
				maid:GiveTask(observe:Subscribe(function(inst)
					sub:Fire(inst)
				end, function(...)
					sub:Fail(...)
				end, function()
					-- completion should not result more than maid cleaning up
					maid:DoCleaning()
				end))

				return maid
			end

			warn(("Unknown type in brio %q"):format(typeof(result)))
			return nil
		end)
	end

	-- Handle like observable
	if Promise.isPromise(value) then
		value = Rx.fromPromise(value)
	end

	-- Handle like observable
	if Signal.isSignal(value) or typeof(value) == "RBXScriptSignal" then
		value = Rx.fromSignal(value)
	end

	if Observable.isObservable(value) then
		return Observable.new(function(sub)
			local maid = Maid.new()

			maid:GiveTask(value:Subscribe(function(result)
				if typeof(result) == "Instance" then
					-- lifetime of subscription
					maid:GiveTask(result)
					sub:Fire(result)
					return
				end

				local observe = Blend._observeChildren(result)

				if observe then
					local innerMaid = Maid.new()

					-- Note: I think this still memory leaks
					innerMaid:GiveTask(observe:Subscribe(function(inst)
						sub:Fire(inst)
					end, function(...)
						innerMaid:DoCleaning()
						sub:Fail(...)
					end, function()
						innerMaid:DoCleaning()
					end))

					innerMaid:GiveTask(function()
						maid[innerMaid] = nil
					end)
					maid[innerMaid] = innerMaid
				else
					warn(("Failed to convert %q into children"):format(tostring(result)))
				end
			end, function(...)
				sub:Fire(...)
			end, function()
				-- Drop completion, other inner components may have completed.
			end))

			return maid
		end)
	end

	if type(value) == "table" and not getmetatable(value) then
		local observables = {}
		for key, item in pairs(value) do
			local observe = Blend._observeChildren(item)
			if observe then
				table.insert(observables, observe)
			else
				warn(("Failed to convert [%s] %q into children"):format(tostring(key), tostring(item)))
			end
		end

		if next(observables) then
			return Rx.merge(observables)
		else
			return nil
		end
	end

	return nil
end
