local debuggee = {}
local socket = require("socket.core")
local json
local handlers = {}
local sock
local directorySeperator = package.config:sub(1, 1)
local sourceBasePath = "."
local storedVariables = {}
local nextVarRef = 1
local baseDepth, breaker, sendEvent
local dumpCommunication = false
local ignoreFirstFrameInC = false
local debugTargetCo, redirectedPrintFunction, onError, addUserdataVar
local defaultOnError = function(e)
	print("****************************************************")
	print(e)
	print("****************************************************")
end
local function valueToString(value, depth)
	local str = ""
	depth = depth or 0
	local t = type(value)
	if t == "table" then
		str = str .. "{\n"
		for k, v in pairs(value) do
			str = str .. string.rep("  ", depth + 1) .. "[" .. valueToString(k) .. "]" .. " = " .. valueToString(v, depth + 1) .. ",\n"
		end
		str = str .. string.rep("  ", depth) .. "}"
	elseif t == "string" then
		str = str .. "\"" .. tostring(value) .. "\""
	else
		str = str .. tostring(value)
	end
	return str
end
local sethook = debug.sethook
debug.sethook = nil
local cocreate = coroutine.create
function coroutine.create(f)
	local c = cocreate(f)
	debuggee.addCoroutine(c)
	return c
end
local debug_getinfo = function(depth, what)
	if debugTargetCo then
		return debug.getinfo(debugTargetCo, depth, what)
	else
		return debug.getinfo(depth + 1, what)
	end
end
local debug_getlocal = function(depth, i)
	if debugTargetCo then
		return debug.getlocal(debugTargetCo, depth, i)
	else
		return debug.getlocal(depth + 1, i)
	end
end
local DO_TEST = false
local getMatchCount = function(a, b)
	local n = math.min(#a, #b)
	for i = 0, n - 1 do
		if a[#a - i] == b[#b - i] then
		else
			return i
		end
	end
	return n
end
if DO_TEST then
	assert(getMatchCount({
		"a",
		"b",
		"c"
	}, {
		"a",
		"b",
		"c"
	}) == 3)
	assert(getMatchCount({"b", "c"}, {
		"a",
		"b",
		"c"
	}) == 2)
	assert(getMatchCount({
		"a",
		"b",
		"c"
	}, {"b", "c"}) == 2)
	assert(getMatchCount({}, {
		"a",
		"b",
		"c"
	}) == 0)
	assert(getMatchCount({
		"a",
		"b",
		"c"
	}, {}) == 0)
	assert(getMatchCount({
		"a",
		"b",
		"c"
	}, {
		"a",
		"b",
		"c",
		"d"
	}) == 0)
end
local splitChunkName = function(s)
	if string.sub(s, 1, 1) == "@" then
		s = string.sub(s, 2)
	end
	local a = {}
	for word in string.gmatch(s, "[^/\\]+") do
		a[#a + 1] = string.lower(word)
	end
	return a
end
if DO_TEST then
	local a = splitChunkName("@.\\vscode-debuggee.lua")
	assert(#a == 2)
	assert(a[1] == ".")
	assert(a[2] == "vscode-debuggee.lua")
	local a = splitChunkName("@C:\\dev\\VSCodeLuaDebug\\debuggee/lua\\socket.lua")
	assert(#a == 6)
	assert(a[1] == "c:")
	assert(a[2] == "dev")
	assert(a[3] == "vscodeluadebug")
	assert(a[4] == "debuggee")
	assert(a[5] == "lua")
	assert(a[6] == "socket.lua")
	local a = splitChunkName("@main.lua")
	assert(#a == 1)
	assert(a[1] == "main.lua")
end
local Path = {}
function Path.isAbsolute(a)
	local firstChar = string.sub(a, 1, 1)
	if firstChar == "/" or firstChar == "\\" then
		return true
	end
	if string.match(a, "^%a%:[/\\]") then
		return true
	end
	return false
end
local np_pat1, np_pat2 = ("[^SEP:]+SEP%.%.SEP?"):gsub("SEP", directorySeperator), ("SEP+%.?SEP"):gsub("SEP", directorySeperator)
function Path.normpath(path)
	path = path:gsub("[/\\]", directorySeperator)
	if directorySeperator == "\\" then
		local unc = ("SEPSEP"):gsub("SEP", directorySeperator)
		if path:match("^" .. unc) then
			return unc .. Path.normpath(path:sub(3))
		end
	end
	local k
	repeat
		path, k = path:gsub(np_pat2, directorySeperator)
	until k == 0
	repeat
		path, k = path:gsub(np_pat1, "", 1)
	until k == 0
	if path == "" then
		path = "."
	end
	return path
end
function Path.concat(a, b)
	local lastChar = string.sub(a, #a, #a)
	if lastChar ~= "/" and lastChar ~= "\\" then
		a = a .. directorySeperator
	end
	if string.match(b, "^%.%\\") or string.match(b, "^%.%/") then
		b = string.sub(b, 3)
	end
	return a .. b
end
function Path.toAbsolute(base, sub)
	if Path.isAbsolute(sub) then
		return Path.normpath(sub)
	else
		return Path.normpath(Path.concat(base, sub))
	end
end
if DO_TEST then
	assert(Path.isAbsolute("c:\\asdf\\afsd"))
	assert(Path.isAbsolute("c:/asdf/afsd"))
	if directorySeperator == "\\" then
		assert(Path.toAbsolute("c:\\asdf", "fdsf") == "c:\\asdf\\fdsf")
		assert(Path.toAbsolute("c:\\asdf", ".\\fdsf") == "c:\\asdf\\fdsf")
		assert(Path.toAbsolute("c:\\asdf", "..\\fdsf") == "c:\\fdsf")
		assert(Path.toAbsolute("c:\\asdf", "c:\\fdsf") == "c:\\fdsf")
		assert(Path.toAbsolute("c:/asdf", "../fdsf") == "c:\\fdsf")
		assert(Path.toAbsolute("\\\\HOST\\asdf", "..\\fdsf") == "\\\\HOST\\fdsf")
	elseif directorySeperator == "/" then
		assert(Path.toAbsolute("/usr/bin/asdf", "fdsf") == "/usr/bin/asdf/fdsf")
		assert(Path.toAbsolute("/usr/bin/asdf", "./fdsf") == "/usr/bin/asdf/fdsf")
		assert(Path.toAbsolute("/usr/bin/asdf", "../fdsf") == "/usr/bin/fdsf")
		assert(Path.toAbsolute("/usr/bin/asdf", "/usr/bin/fdsf") == "/usr/bin/fdsf")
		assert(Path.toAbsolute("\\usr\\bin\\asdf", "..\\fdsf") == "/usr/bin/fdsf")
	end
end
local coroutineSet = {}
setmetatable(coroutineSet, {__mode = "v"})
local sendFully = function(str)
	local first = 1
	while first <= #str do
		local sent = sock:send(str, first)
		if sent and 0 < sent then
			first = first + sent
		else
			error("sock:send() returned < 0")
		end
	end
end
local logToDebugConsole = function(output, category)
	local dumpMsg = {
		event = "output",
		type = "event",
		body = {
			category = category or "console",
			output = output
		}
	}
	local dumpBody = json.encode(dumpMsg)
	sendFully("#" .. #dumpBody .. "\n" .. dumpBody)
end
local createHaltBreaker = function()
	local loadedChunkNameMap = {}
	for chunkname, _ in pairs(debug.getchunknames()) do
		loadedChunkNameMap[chunkname] = splitChunkName(chunkname)
	end
	local findMostSimilarChunkName = function(path)
		local splitedReqPath = splitChunkName(path)
		local maxMatchCount = 0
		local foundChunkName
		for chunkName, splitted in pairs(loadedChunkNameMap) do
			local count = getMatchCount(splitedReqPath, splitted)
			if maxMatchCount < count then
				maxMatchCount = count
				foundChunkName = chunkName
			end
		end
		return foundChunkName
	end
	local lineBreakCallback
	local updateCoroutineHook = function(c)
		if lineBreakCallback then
			sethook(c, lineBreakCallback, "l")
		else
			sethook(c)
		end
	end
	local sethalt = function(cname, ln)
		for i = ln, ln + 10 do
			if debug.sethalt(cname, i) then
				return i
			end
		end
		return nil
	end
	return {
		setBreakpoints = function(path, lines)
			local foundChunkName = findMostSimilarChunkName(path)
			local verifiedLines = {}
			if foundChunkName then
				debug.clearhalt(foundChunkName)
				for _, ln in ipairs(lines) do
					verifiedLines[ln] = sethalt(foundChunkName, ln)
				end
			end
			return verifiedLines
		end,
		setLineBreak = function(callback)
			if callback then
				sethook(callback, "l")
			else
				sethook()
			end
			lineBreakCallback = callback
			for cid, c in pairs(coroutineSet) do
				updateCoroutineHook(c)
			end
		end,
		coroutineAdded = function(c)
			updateCoroutineHook(c)
		end,
		stackOffset = {
			enterDebugLoop = 6,
			halt = 6,
			step = 4,
			stepDebugLoop = 6
		}
	}
end
local createPureBreaker = function()
	local lineBreakCallback
	local breakpointsPerPath = {}
	local chunknameToPathCache = {}
	local chunkNameToPath = function(chunkname)
		local cached = chunknameToPathCache[chunkname]
		if cached then
			return cached
		end
		local splitedReqPath = splitChunkName(chunkname)
		local maxMatchCount = 0
		local foundPath
		for path, _ in pairs(breakpointsPerPath) do
			local splitted = splitChunkName(path)
			local count = getMatchCount(splitedReqPath, splitted)
			if maxMatchCount < count then
				maxMatchCount = count
				foundPath = path
			end
		end
		if foundPath then
			chunknameToPathCache[chunkname] = foundPath
		end
		return foundPath
	end
	local entered = false
	local hookfunc = function()
		if entered then
			return false
		end
		entered = true
		if lineBreakCallback then
			lineBreakCallback()
		end
		local info = debug_getinfo(2, "Sl")
		if info then
			local path = chunkNameToPath(info.source)
			path = path and string.lower(path)
			local bpSet = breakpointsPerPath[path]
			if bpSet and bpSet[info.currentline] then
				_G.__halt__()
			end
		end
		entered = false
	end
	sethook(hookfunc, "l")
	return {
		setBreakpoints = function(path, lines)
			local t = {}
			local verifiedLines = {}
			for _, ln in ipairs(lines) do
				t[ln] = true
				verifiedLines[ln] = ln
			end
			path = path and string.lower(path)
			breakpointsPerPath[path] = t
			return verifiedLines
		end,
		setLineBreak = function(callback)
			lineBreakCallback = callback
		end,
		coroutineAdded = function(c)
			sethook(c, hookfunc, "l")
		end,
		stackOffset = {
			enterDebugLoop = 6,
			halt = 7,
			step = 4,
			stepDebugLoop = 7
		}
	}
end
local sendMessage = function(msg)
	local body = json.encode(msg)
	if dumpCommunication then
		logToDebugConsole("[SENDING] " .. valueToString(msg))
	end
	sendFully("#" .. #body .. "\n" .. body)
end
local recvMessage = function()
	local header = sock:receive("*l")
	if header == nil then
		return nil
	end
	if string.sub(header, 1, 1) ~= "#" then
		error("헤더 이상함:" .. header)
	end
	local bodySize = tonumber(header:sub(2))
	local body = sock:receive(bodySize)
	return json.decode(body)
end
local debugLoop = function()
	storedVariables = {}
	nextVarRef = 1
	while true do
		local msg = recvMessage()
		if msg then
			if dumpCommunication then
				logToDebugConsole("[RECEIVED] " .. valueToString(msg), "stderr")
			end
			local fn = handlers[msg.command]
			if not fn then
				goto lbl_38
			end
			do
				local rv = fn(msg)
				if rv == "CONTINUE" then
					break
				end
			end
			goto lbl_38
		else
			if redirectedPrintFunction then
				_G.print = redirectedPrintFunction
			end
			break
		end
		::lbl_38::
	end
	storedVariables = {}
	nextVarRef = 1
end
local sockArray = {}
function debuggee.start(jsonLib, config)
	json = jsonLib
	assert(jsonLib)
	config = config or {}
	local connectTimeout = config.connectTimeout or 5.0
	local controllerHost = config.controllerHost or "localhost"
	local controllerPort = config.controllerPort or 56789
	onError = config.onError or defaultOnError
	addUserdataVar = config.addUserdataVar or function()
		return
	end
	local redirectPrint = config.redirectPrint or false
	dumpCommunication = config.dumpCommunication or false
	ignoreFirstFrameInC = config.ignoreFirstFrameInC or false
	if not config.luaStyleLog then
		function valueToString(value)
			return json.encode(value)
		end
	end
	local breakerType
	if debug.sethalt then
		breaker = createHaltBreaker()
		breakerType = "halt"
	else
		breaker = createPureBreaker()
		breakerType = "pure"
	end
	local err
	sock, err = socket.tcp()
	if not sock then
		error(err)
	end
	sockArray = {sock}
	if sock.settimeout then
		sock:settimeout(connectTimeout)
	end
	local res, err = sock:connect(controllerHost, tostring(controllerPort))
	if not res then
		sock:close()
		sock = nil
		return false, breakerType
	end
	if sock.settimeout then
		sock:settimeout()
	end
	sock:setoption("tcp-nodelay", true)
	local initMessage = recvMessage()
	assert(initMessage and initMessage.command == "welcome")
	sourceBasePath = initMessage.sourceBasePath
	directorySeperator = initMessage.directorySeperator
	if redirectPrint then
		redirectedPrintFunction = _G.print
		function _G.print(...)
			local t = {
				n = select("#", ...),
				...
			}
			for i = 1, #t do
				t[i] = tostring(t[i])
			end
			sendEvent("output", {
				category = "stdout",
				output = table.concat(t, "\t") .. "\n"
			})
		end
	end
	debugLoop()
	return true, breakerType
end
function debuggee.poll()
	if not sock then
		return
	end
	while true do
		local r, w, e = socket.select(sockArray, nil, 0)
		if e == "timeout" then
			break
		end
		local msg = recvMessage()
		if msg then
			if dumpCommunication then
				logToDebugConsole("[POLL-RECEIVED] " .. valueToString(msg), "stderr")
			end
			if msg.command == "pause" then
				debuggee.enterDebugLoop(1)
				return
			end
			local fn = handlers[msg.command]
			if fn then
				local rv = fn(msg)
			else
			end
		else
			break
		end
	end
end
local getCoroutineId = function(c)
	local threadIdHex = string.sub(tostring(c), 9)
	return tonumber(threadIdHex, 16)
end
function debuggee.addCoroutine(c)
	local cid = getCoroutineId(c)
	coroutineSet[cid] = c
	breaker.coroutineAdded(c)
end
local sendSuccess = function(req, body)
	sendMessage({
		command = req.command,
		success = true,
		request_seq = req.seq,
		type = "response",
		body = body
	})
end
local sendFailure = function(req, msg)
	sendMessage({
		command = req.command,
		success = false,
		request_seq = req.seq,
		type = "response",
		message = msg
	})
end
function sendEvent(eventName, body)
	sendMessage({
		event = eventName,
		type = "event",
		body = body
	})
end
local currentThreadId = function()
	return 0
end
local startDebugLoop = function()
	sendEvent("stopped", {
		reason = "breakpoint",
		threadId = currentThreadId(),
		allThreadsStopped = true
	})
	local status, err = pcall(debugLoop)
	if not status then
		onError(err)
	end
end
function _G.__halt__()
	baseDepth = breaker.stackOffset.halt
	startDebugLoop()
end
function debuggee.enterDebugLoop(depthOrCo, what)
	if sock == nil then
		return false
	end
	if what then
		sendEvent("output", {category = "stderr", output = what})
	end
	if type(depthOrCo) == "thread" then
		baseDepth = 0
		debugTargetCo = depthOrCo
	elseif type(depthOrCo) == "table" then
		baseDepth = depthOrCo.depth or 0
		debugTargetCo = depthOrCo.co
	else
		baseDepth = (depthOrCo or 0) + breaker.stackOffset.enterDebugLoop
		debugTargetCo = nil
	end
	startDebugLoop()
	return true
end
function debuggee.print(category, ...)
	if sock == nil then
		return false
	end
	local t = {
		...
	}
	for i = 1, #t do
		t[i] = tostring(t[i])
	end
	local categoryVscodeConsole = "stdout"
	if category == "warning" then
		categoryVscodeConsole = "console"
	elseif category == "error" then
		categoryVscodeConsole = "stderr"
	elseif category == "log" then
		categoryVscodeConsole = "stdout"
	end
	sendEvent("output", {
		category = categoryVscodeConsole,
		output = table.concat(t, "\t") .. "\n"
	})
end
function handlers.setBreakpoints(req)
	local bpLines = {}
	for _, bp in ipairs(req.arguments.breakpoints) do
		bpLines[#bpLines + 1] = bp.line
	end
	local verifiedLines = breaker.setBreakpoints(req.arguments.source.path, bpLines)
	local breakpoints = {}
	for i, ln in ipairs(bpLines) do
		breakpoints[i] = {
			verified = verifiedLines[ln] ~= nil,
			line = verifiedLines[ln]
		}
	end
	sendSuccess(req, {breakpoints = breakpoints})
end
function handlers.configurationDone(req)
	sendSuccess(req, {})
	return "CONTINUE"
end
function handlers.threads(req)
	local c = coroutine.running()
	local mainThread = {
		id = currentThreadId(),
		name = c and tostring(c) or "main"
	}
	sendSuccess(req, {
		threads = {mainThread}
	})
end
function handlers.stackTrace(req)
	assert(req.arguments.threadId == 0)
	local stackFrames = {}
	local firstFrame = (req.arguments.startFrame or 0) + baseDepth
	local lastFrame = req.arguments.levels and req.arguments.levels ~= 0 and firstFrame + req.arguments.levels - 1 or 9999
	if ignoreFirstFrameInC then
		local info = debug_getinfo(firstFrame, "lnS")
		if info and info.what == "C" then
			firstFrame = firstFrame + 1
		end
	end
	for i = firstFrame, lastFrame do
		local info = debug_getinfo(i, "lnS")
		if info == nil then
			break
		end
		local src = info.source
		if string.sub(src, 1, 1) == "@" then
			src = string.sub(src, 2)
		end
		local name
		if info.name then
			name = info.name .. " (" .. (info.namewhat or "?") .. ")"
		else
			name = "?"
		end
		local sframe = {
			name = name,
			source = {
				name = nil,
				path = Path.toAbsolute(sourceBasePath, src)
			},
			column = 1,
			line = info.currentline or 1,
			id = i
		}
		stackFrames[#stackFrames + 1] = sframe
	end
	sendSuccess(req, {stackFrames = stackFrames})
end
local scopeTypes = {
	Locals = 1,
	Upvalues = 2,
	Globals = 3
}
function handlers.scopes(req)
	local depth = req.arguments.frameId
	local scopes = {}
	local addScope = function(name)
		scopes[#scopes + 1] = {
			name = name,
			expensive = false,
			variablesReference = depth * 1000000 + scopeTypes[name]
		}
	end
	addScope("Locals")
	addScope("Upvalues")
	addScope("Globals")
	sendSuccess(req, {scopes = scopes})
end
local registerVar = function(varNameCount, name_, value, noQuote)
	local ty = type(value)
	local name
	if type(name_) == "number" then
		name = "[" .. name_ .. "]"
	else
		name = tostring(name_)
	end
	if varNameCount[name] then
		varNameCount[name] = varNameCount[name] + 1
		name = name .. " (" .. varNameCount[name] .. ")"
	else
		varNameCount[name] = 1
	end
	local item = {name = name, type = ty}
	if ty == "string" and not noQuote then
		item.value = "\"" .. value .. "\""
	else
		item.value = tostring(value)
	end
	if ty == "table" or ty == "function" or ty == "userdata" then
		storedVariables[nextVarRef] = value
		item.variablesReference = nextVarRef
		nextVarRef = nextVarRef + 1
	else
		item.variablesReference = -1
	end
	return item
end
function handlers.variables(req)
	local varRef = req.arguments.variablesReference
	local variables = {}
	local varNameCount = {}
	local addVar = function(name, value, noQuote)
		variables[#variables + 1] = registerVar(varNameCount, name, value, noQuote)
	end
	if 1000000 <= varRef then
		local depth = math.floor(varRef / 1000000)
		local scopeType = varRef % 1000000
		if scopeType == scopeTypes.Locals then
			for i = 1, 9999 do
				local name, value = debug_getlocal(depth, i)
				if name == nil then
					break
				end
				addVar(name, value, nil)
			end
		elseif scopeType == scopeTypes.Upvalues then
			local info = debug_getinfo(depth, "f")
			if info and info.func then
				for i = 1, 9999 do
					local name, value = debug.getupvalue(info.func, i)
					if name == nil then
						break
					end
					addVar(name, value, nil)
				end
			end
		elseif scopeType == scopeTypes.Globals then
			for name, value in pairs(_G) do
				addVar(name, value)
			end
			table.sort(variables, function(a, b)
				return a.name < b.name
			end)
		end
	else
		local var = storedVariables[varRef]
		if type(var) == "table" then
			for k, v in pairs(var) do
				addVar(k, v)
			end
			table.sort(variables, function(a, b)
				local aNum, aMatched = string.gsub(a.name, "^%[(%d+)%]$", "%1")
				local bNum, bMatched = string.gsub(b.name, "^%[(%d+)%]$", "%1")
				if aMatched == 1 and bMatched == 1 then
					return tonumber(aNum) < tonumber(bNum)
				elseif aMatched == bMatched then
					return a.name < b.name
				else
					return aMatched < bMatched
				end
			end)
		elseif type(var) == "function" then
			local info = debug.getinfo(var, "S")
			addVar("(source)", tostring(info.short_src), true)
			addVar("(line)", info.linedefined)
			for i = 1, 9999 do
				local name, value = debug.getupvalue(var, i)
				if name == nil then
					break
				end
				addVar(name, value)
			end
		elseif type(var) == "userdata" then
			addUserdataVar(var, addVar)
		end
		local mt = getmetatable(var)
		if mt then
			addVar("(metatable)", mt)
		end
	end
	sendSuccess(req, {variables = variables})
end
function handlers.continue(req)
	sendSuccess(req, {})
	return "CONTINUE"
end
local stackHeight = function()
	for i = 1, 9999999 do
		if debug_getinfo(i, "") == nil then
			return i
		end
	end
end
local stepTargetHeight
local step = function()
	if stepTargetHeight == nil or stackHeight() <= stepTargetHeight then
		breaker.setLineBreak(nil)
		baseDepth = breaker.stackOffset.stepDebugLoop
		startDebugLoop()
	end
end
function handlers.next(req)
	stepTargetHeight = stackHeight() - breaker.stackOffset.step
	breaker.setLineBreak(step)
	sendSuccess(req, {})
	return "CONTINUE"
end
function handlers.stepIn(req)
	stepTargetHeight = nil
	breaker.setLineBreak(step)
	sendSuccess(req, {})
	return "CONTINUE"
end
function handlers.stepOut(req)
	stepTargetHeight = stackHeight() - (breaker.stackOffset.step + 1)
	breaker.setLineBreak(step)
	sendSuccess(req, {})
	return "CONTINUE"
end
function handlers.evaluate(req)
	local sourceCode = req.arguments.expression
	if string.sub(sourceCode, 1, 1) == "!" then
		sourceCode = string.sub(sourceCode, 2)
	else
		sourceCode = "return (" .. sourceCode .. ")"
	end
	local depth = req.arguments.frameId
	local tempG = {}
	local declared = {}
	local set = function(k, v)
		tempG[k] = v
		declared[k] = true
	end
	for name, value in pairs(_G) do
		set(name, value)
	end
	if depth then
		local info = debug_getinfo(depth, "f")
		if info and info.func then
			for i = 1, 9999 do
				local name, value = debug.getupvalue(info.func, i)
				if name == nil then
					break
				end
				set(name, value)
			end
		end
		for i = 1, 9999 do
			local name, value = debug_getlocal(depth, i)
			if name == nil then
				goto lbl_80
			end
			set(name, value)
		end
	else
	end
	::lbl_80::
	local mt = {
		__newindex = function()
			error("assignment not allowed", 2)
		end,
		__index = function(t, k)
			if not declared[k] then
				error("not declared", 2)
			end
		end
	}
	setmetatable(tempG, mt)
	local fn, err = (loadstring or load)(sourceCode, "X", nil, tempG)
	if fn == nil then
		sendFailure(req, string.gsub(err, "^%[string %\"X%\"%]%:%d+%: ", ""))
		return
	end
	if setfenv ~= nil then
		setfenv(fn, tempG)
	end
	local success, aux = pcall(fn)
	if not success then
		aux = aux or ""
		sendFailure(req, string.gsub(aux, "^%[string %\"X%\"%]%:%d+%: ", ""))
		return
	end
	local varNameCount = {}
	local item = registerVar(varNameCount, "", aux)
	sendSuccess(req, {
		result = item.value,
		type = item.type,
		variablesReference = item.variablesReference
	})
end
return debuggee
