debugsk 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +13 -10
- package/dist/cli.js.map +1 -1
- package/dist/index.js +13 -10
- package/dist/index.js.map +1 -1
- package/package.json +11 -11
- package/skills/code-debug-skill/SKILL.md +6 -2
- package/skills/code-debug-skill/assets/report-template.md +11 -11
- package/skills/code-debug-skill/references/logging-schema.md +8 -6
- package/LICENSE +0 -21
package/dist/cli.js
CHANGED
|
@@ -211,7 +211,6 @@ function findPackageJsonPath() {
|
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
// src/server.ts
|
|
214
|
-
var REQUIRED_FIELDS = ["timestamp", "message", "sessionId", "runId", "hypothesisId"];
|
|
215
214
|
var CORS_HEADERS = {
|
|
216
215
|
"Access-Control-Allow-Origin": "*",
|
|
217
216
|
"Access-Control-Allow-Methods": "GET,POST,OPTIONS",
|
|
@@ -263,23 +262,27 @@ async function startServer(options) {
|
|
|
263
262
|
respondJson(res, 400, { ok: false, error: "invalid_body" });
|
|
264
263
|
return;
|
|
265
264
|
}
|
|
266
|
-
const missing = REQUIRED_FIELDS.filter((field) => !(field in payload));
|
|
267
|
-
if (missing.length > 0) {
|
|
268
|
-
respondJson(res, 400, { ok: false, error: "missing_fields", missing });
|
|
269
|
-
return;
|
|
270
|
-
}
|
|
271
265
|
const event = payload;
|
|
272
|
-
const
|
|
273
|
-
const
|
|
274
|
-
const
|
|
275
|
-
|
|
266
|
+
const timestamp = "timestamp" in event ? event.timestamp : Date.now();
|
|
267
|
+
const message = "message" in event ? event.message : "";
|
|
268
|
+
const sessionId = "sessionId" in event ? String(event.sessionId) : "";
|
|
269
|
+
const runId = "runId" in event ? String(event.runId) : "";
|
|
270
|
+
const hypothesisId = "hypothesisId" in event ? String(event.hypothesisId) : "";
|
|
276
271
|
const enriched = {
|
|
272
|
+
timestamp,
|
|
273
|
+
message,
|
|
274
|
+
sessionId,
|
|
275
|
+
runId,
|
|
276
|
+
hypothesisId,
|
|
277
277
|
...event,
|
|
278
|
+
// Original values take precedence if present
|
|
278
279
|
_meta: {
|
|
279
280
|
streamId,
|
|
280
281
|
receivedAt: Date.now()
|
|
281
282
|
}
|
|
282
283
|
};
|
|
284
|
+
const logPath = getSessionLogPath(logsDir, sessionId, runId);
|
|
285
|
+
await import_promises2.default.mkdir(import_node_path3.default.dirname(logPath), { recursive: true });
|
|
283
286
|
await import_promises2.default.appendFile(logPath, `${JSON.stringify(enriched)}
|
|
284
287
|
`, "utf8");
|
|
285
288
|
if (options.idleTtlMs && options.idleTtlMs > 0) {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/constants.ts","../src/process.ts","../src/paths.ts","../src/runtime.ts","../src/server.ts","../src/net.ts","../src/version.ts"],"sourcesContent":["#!/usr/bin/env node\nimport fs from 'node:fs/promises'\nimport os from 'node:os'\nimport path from 'node:path'\nimport readline from 'node:readline/promises'\nimport minimist from 'minimist'\nimport {\n DEFAULT_BASE_PATH,\n DEFAULT_HOST,\n DEFAULT_LOGS_DIR,\n DEFAULT_MAX_BODY_KB,\n DEFAULT_PORT,\n} from './constants'\nimport { isProcessAlive, terminateProcess } from './process'\nimport { resolveLogsDir } from './paths'\nimport { RuntimeInfo, markStopped, readRuntime, removePid } from './runtime'\nimport { startServer } from './server'\n\nconst args = minimist(process.argv.slice(2), {\n boolean: ['json', 'force', 'help', 'user'],\n string: ['host', 'base-path', 'logs-dir', 'token'],\n alias: {\n h: 'help',\n u: 'user',\n },\n})\n\nconst primary = String(args._[0] ?? 'help')\nconst secondary = args._[1] ? String(args._[1]) : undefined\nconst scope = primary === 'server' || primary === 'codex' ? primary : 'server'\nconst command =\n scope === 'server' ? String(primary === 'server' ? secondary ?? 'help' : primary) : String(secondary ?? 'help')\n\nconst json = Boolean(args.json)\nconst SKILL_NAME = 'code-debug-skill'\n\nvoid main().catch((error) => {\n outputError(error instanceof Error ? error.message : 'unexpected_error')\n process.exitCode = 1\n})\n\nasync function main(): Promise<void> {\n if (args.help || command === 'help') {\n printHelp()\n return\n }\n\n if (scope === 'codex') {\n await handleCodex(command)\n return\n }\n\n switch (command) {\n case 'start':\n await handleStart()\n return\n case 'run':\n if (!process.env.DEBUGSK_CHILD) {\n outputError('use_start_command')\n return\n }\n await handleRun()\n return\n case 'status':\n await handleStatus()\n return\n case 'stop':\n await handleStop()\n return\n default:\n outputError(`unknown_command:${command}`)\n }\n}\n\nfunction getCommonOptions() {\n const host = String(args.host ?? DEFAULT_HOST)\n const port = parseNumber(args.port, DEFAULT_PORT) ?? DEFAULT_PORT\n const basePath = String(args['base-path'] ?? DEFAULT_BASE_PATH)\n const logsDir = args['logs-dir'] ? String(args['logs-dir']) : undefined\n const maxBodyKB = parseNumber(args['max-body-kb'], DEFAULT_MAX_BODY_KB) ?? DEFAULT_MAX_BODY_KB\n const token = args.token ? String(args.token) : undefined\n const idleTtlMs = parseNumber(args['idle-ttl-ms'], undefined)\n return { host, port, basePath, logsDir, maxBodyKB, token, idleTtlMs }\n}\n\nasync function handleStart(): Promise<void> {\n const { host, port, basePath, logsDir, maxBodyKB, token, idleTtlMs } = getCommonOptions()\n const cwd = process.cwd()\n const resolvedLogsDir = resolveLogsDir({ cwd, logsDir })\n const runtime = await readRuntime(resolvedLogsDir)\n\n if (runtime && !runtime.options) {\n outputLegacyRuntimeError()\n return\n }\n\n if (runtime && isProcessAlive(runtime.pid) && !args.force) {\n const payload = buildStartOutput(runtime, true)\n outputStart(payload)\n return\n }\n\n if (runtime && isProcessAlive(runtime.pid) && args.force) {\n await terminateProcess(runtime.pid, 3000)\n await markStopped(resolvedLogsDir)\n await removePid(resolvedLogsDir)\n }\n\n if (runtime && !isProcessAlive(runtime.pid)) {\n await markStopped(resolvedLogsDir)\n await removePid(resolvedLogsDir)\n }\n\n const spawnResult = await spawnBackground({\n host,\n port,\n basePath,\n logsDir,\n maxBodyKB,\n token,\n idleTtlMs,\n })\n\n const finalRuntime = await waitForRuntime(resolvedLogsDir, 5000)\n if (!finalRuntime) {\n outputError('start_failed')\n return\n }\n\n const ok = await waitForHealth(finalRuntime, 5000)\n if (!ok) {\n outputError('health_check_failed')\n return\n }\n\n const payload = buildStartOutput(finalRuntime, false, spawnResult?.pid)\n outputStart(payload)\n}\n\nasync function handleRun(): Promise<void> {\n const { host, port, basePath, logsDir, maxBodyKB, token, idleTtlMs } = getCommonOptions()\n const cwd = process.cwd()\n\n const started = await startServer({\n host,\n port,\n basePath,\n logsDir,\n maxBodyKB,\n token,\n idleTtlMs,\n cwd,\n })\n\n installSignalHandlers(started.logsDir, started.close)\n\n if (!json) {\n logInfo(`debugsk server listening at ${started.baseUrl}`)\n }\n}\n\nasync function handleStatus(): Promise<void> {\n const cwd = process.cwd()\n const logsDir = args['logs-dir'] ? String(args['logs-dir']) : undefined\n const resolvedLogsDir = resolveLogsDir({ cwd, logsDir })\n const runtime = await readRuntime(resolvedLogsDir)\n\n if (!runtime) {\n outputStatus({ ok: false, running: false, error: 'not_running' })\n return\n }\n if (!runtime.options) {\n outputLegacyRuntimeError()\n return\n }\n\n const running = isProcessAlive(runtime.pid)\n const payload = {\n ...runtime,\n running,\n }\n outputStatus(payload)\n}\n\nasync function handleStop(): Promise<void> {\n const cwd = process.cwd()\n const logsDir = args['logs-dir'] ? String(args['logs-dir']) : undefined\n const resolvedLogsDir = resolveLogsDir({ cwd, logsDir })\n const runtime = await readRuntime(resolvedLogsDir)\n\n if (!runtime) {\n outputStop({ ok: true, stopped: false, running: false })\n return\n }\n\n const stopped = await terminateProcess(runtime.pid, 3000)\n if (stopped) {\n await markStopped(resolvedLogsDir)\n await removePid(resolvedLogsDir)\n }\n\n outputStop({ ok: true, stopped, pid: runtime.pid })\n}\n\nasync function handleCodex(subcommand: string): Promise<void> {\n switch (subcommand) {\n case 'install':\n await codexInstall(false)\n return\n case 'update':\n await codexInstall(true)\n return\n case 'remove':\n await codexRemove()\n return\n default:\n outputError(`unknown_command:codex:${subcommand}`)\n }\n}\n\nasync function codexInstall(force: boolean): Promise<void> {\n const source = await resolveSkillSource()\n const { dest, scope } = await resolveCodexDest({ createIfMissing: true })\n const exists = await pathExists(dest)\n\n if (exists && !force) {\n outputError('codex_skill_already_installed')\n return\n }\n\n await ensureSafeDest(dest)\n if (exists) {\n await fs.rm(dest, { recursive: true, force: true })\n }\n\n await fs.mkdir(path.dirname(dest), { recursive: true })\n await fs.cp(source, dest, { recursive: true })\n\n outputJsonResult({\n ok: true,\n action: force ? 'update' : 'install',\n scope,\n dest,\n source,\n replaced: exists,\n })\n}\n\nasync function codexRemove(): Promise<void> {\n const { dest, scope, homeExists } = await resolveCodexDest({ createIfMissing: false })\n if (!homeExists) {\n outputJsonResult({\n ok: true,\n action: 'remove',\n scope,\n dest,\n removed: false,\n reason: 'codex_home_missing',\n })\n return\n }\n await ensureSafeDest(dest)\n const exists = await pathExists(dest)\n if (exists) {\n await fs.rm(dest, { recursive: true, force: true })\n }\n outputJsonResult({\n ok: true,\n action: 'remove',\n scope,\n dest,\n removed: exists,\n })\n}\n\nasync function resolveSkillSource(): Promise<string> {\n const packageRoot = path.resolve(__dirname, '..')\n const repoRoot = path.resolve(packageRoot, '..', '..')\n const repoSource = path.join(repoRoot, 'skills', SKILL_NAME)\n if (await pathExists(repoSource)) return repoSource\n const packaged = path.join(packageRoot, 'skills', SKILL_NAME)\n if (await pathExists(packaged)) return packaged\n throw new Error(`missing_skill_source:${SKILL_NAME}`)\n}\n\nasync function resolveCodexDest({\n createIfMissing,\n}: {\n createIfMissing: boolean\n}): Promise<{ dest: string; scope: 'user' | 'local'; homeExists: boolean }> {\n const useUser = Boolean(args.user)\n const scope: 'user' | 'local' = useUser ? 'user' : 'local'\n const codexHome = useUser ? path.join(os.homedir(), '.codex') : path.join(process.cwd(), '.codex')\n const exists = await pathExists(codexHome)\n if (!exists && createIfMissing) {\n await ensureCodexHome(codexHome, scope)\n }\n return { dest: path.join(codexHome, 'skills', SKILL_NAME), scope, homeExists: exists }\n}\n\nasync function ensureSafeDest(dest: string): Promise<void> {\n const resolved = path.resolve(dest)\n const root = path.parse(resolved).root\n if (resolved === root || resolved === os.homedir()) {\n throw new Error('unsafe_dest')\n }\n}\n\nasync function ensureCodexHome(codexHome: string, scope: 'user' | 'local'): Promise<void> {\n if (await pathExists(codexHome)) return\n if (!process.stdin.isTTY) {\n throw new Error('codex_home_missing')\n }\n const prompt = `Create ${codexHome} for ${scope} scope? [y/N]: `\n const approved = await confirmPrompt(prompt)\n if (!approved) {\n throw new Error('codex_home_missing')\n }\n await fs.mkdir(codexHome, { recursive: true })\n}\n\nasync function confirmPrompt(prompt: string): Promise<boolean> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stderr })\n const answer = await rl.question(prompt)\n rl.close()\n return /^y(es)?$/i.test(answer.trim())\n}\n\nasync function pathExists(target: string): Promise<boolean> {\n try {\n await fs.access(target)\n return true\n } catch {\n return false\n }\n}\n\nasync function spawnBackground(options: {\n host: string\n port: number\n basePath: string\n logsDir?: string\n maxBodyKB: number\n token?: string\n idleTtlMs?: number\n}): Promise<{ pid: number } | null> {\n const nodeArgs = [...process.execArgv, process.argv[1]]\n const cmdArgs = ['run']\n\n cmdArgs.push('--host', options.host)\n cmdArgs.push('--port', String(options.port))\n cmdArgs.push('--base-path', options.basePath)\n cmdArgs.push('--max-body-kb', String(options.maxBodyKB))\n if (options.logsDir) cmdArgs.push('--logs-dir', options.logsDir)\n if (options.token) cmdArgs.push('--token', options.token)\n if (options.idleTtlMs) cmdArgs.push('--idle-ttl-ms', String(options.idleTtlMs))\n\n const spawn = await import('node:child_process')\n const child = spawn.spawn(process.execPath, [...nodeArgs, ...cmdArgs], {\n detached: true,\n stdio: 'ignore',\n env: {\n ...process.env,\n DEBUGSK_CHILD: '1',\n },\n })\n child.unref()\n return child.pid ? { pid: child.pid } : null\n}\n\nasync function waitForRuntime(logsDir: string, timeoutMs: number): Promise<RuntimeInfo | null> {\n const start = Date.now()\n while (Date.now() - start < timeoutMs) {\n const runtime = await readRuntime(logsDir)\n if (runtime && runtime.pid) return runtime\n await sleep(100)\n }\n return null\n}\n\nasync function waitForHealth(runtime: RuntimeInfo, timeoutMs: number): Promise<boolean> {\n const url = new URL(runtime.server.endpoints.health, runtime.server.baseUrl)\n const start = Date.now()\n while (Date.now() - start < timeoutMs) {\n const ok = await checkHealth(url)\n if (ok) return true\n await sleep(100)\n }\n return false\n}\n\nasync function checkHealth(url: URL): Promise<boolean> {\n const http = await import('node:http')\n return new Promise((resolve) => {\n const req = http.get(url, (res) => {\n res.resume()\n resolve(res.statusCode === 200)\n })\n req.on('error', () => resolve(false))\n })\n}\n\nfunction buildStartOutput(runtime: RuntimeInfo, existing: boolean, spawnedPid?: number) {\n const ingestPath = runtime.server.endpoints.ingestTemplate\n const ingestUrl = new URL(ingestPath.replace('{streamId}', '{streamId}'), runtime.server.baseUrl)\n const snippetHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n }\n const tokenEnabled = runtime.options.tokenEnabled\n if (tokenEnabled) {\n snippetHeaders.Authorization = 'Bearer YOUR_TOKEN'\n }\n\n const jsFetch = `fetch(\"${ingestUrl.toString()}\",{method:\"POST\",headers:${JSON.stringify(\n snippetHeaders,\n )},body:JSON.stringify({...})}).catch(()=>{});`\n\n return {\n ok: true,\n version: runtime.version,\n pid: runtime.pid,\n cwd: runtime.cwd,\n logsDir: runtime.logsDir,\n server: {\n host: runtime.server.host,\n port: runtime.server.port,\n baseUrl: runtime.server.baseUrl,\n endpoints: runtime.server.endpoints,\n },\n snippets: {\n jsFetch,\n },\n existing,\n spawnedPid,\n }\n}\n\nfunction installSignalHandlers(logsDir: string, close: () => Promise<void>): void {\n const shutdown = async () => {\n await close()\n await markStopped(logsDir)\n await removePid(logsDir)\n process.exit(0)\n }\n\n process.on('SIGTERM', () => void shutdown())\n process.on('SIGINT', () => void shutdown())\n}\n\nfunction outputJson(payload: unknown): void {\n process.stdout.write(`${JSON.stringify(payload)}\\n`)\n}\n\nfunction outputJsonResult(payload: Record<string, unknown>): void {\n if (json) {\n outputJson(payload)\n return\n }\n const action = String(payload.action ?? 'result')\n const ok = payload.ok ? 'ok' : 'error'\n const dest = payload.dest ? `dest=${payload.dest}` : ''\n process.stdout.write(`${action} ${ok} ${dest}\\n`)\n}\n\nfunction outputError(message: string): void {\n if (json) {\n outputJson({ ok: false, error: message })\n } else {\n process.stderr.write(`${message}\\n`)\n }\n}\n\nfunction outputLegacyRuntimeError(): void {\n const error = 'legacy_runtime_incompatible'\n const hint = 'delete .logs/runtime.json or the entire .logs directory, then retry'\n if (json) {\n outputJson({ ok: false, error, hint })\n } else {\n process.stderr.write(`${error}: ${hint}\\n`)\n }\n}\n\nfunction logInfo(message: string): void {\n process.stderr.write(`${message}\\n`)\n}\n\nfunction outputStart(payload: Record<string, unknown>): void {\n if (json) {\n outputJson(payload)\n return\n }\n const server = payload.server as RuntimeInfo['server']\n const pid = payload.pid as number\n const logsDir = payload.logsDir as string\n process.stdout.write(\n `started pid=${pid} baseUrl=${server.baseUrl} logsDir=${logsDir}\\n`,\n )\n}\n\nfunction outputStatus(payload: Record<string, unknown>): void {\n if (json) {\n outputJson(payload)\n return\n }\n const running = payload.running ? 'running' : 'stopped'\n const pid = payload.pid ? `pid=${payload.pid}` : 'pid=unknown'\n process.stdout.write(`status ${running} ${pid}\\n`)\n}\n\nfunction outputStop(payload: Record<string, unknown>): void {\n if (json) {\n outputJson(payload)\n return\n }\n const stopped = payload.stopped ? 'stopped' : 'not-stopped'\n const pid = payload.pid ? `pid=${payload.pid}` : ''\n process.stdout.write(`stop ${stopped} ${pid}\\n`)\n}\n\nfunction printHelp(): void {\n const text = `debugsk\n\nUsage:\n server start --json Start server in background and print JSON\n server status --json Show server status\n server stop --json Stop background server\n\n codex install Install Codex skill (user scope)\n codex update Update Codex skill (user scope)\n codex remove Remove Codex skill (user scope)\n\nAliases:\n start/status/stop Same as \"server <command>\"\n\nOptions:\n --host (default ${DEFAULT_HOST})\n --port (default ${DEFAULT_PORT})\n --base-path (default ${DEFAULT_BASE_PATH})\n --logs-dir (default ${DEFAULT_LOGS_DIR})\n --max-body-kb (default ${DEFAULT_MAX_BODY_KB})\n --token (optional)\n --idle-ttl-ms (optional)\n --force (restart even if already running)\n --json (stdout JSON only)\n -u, --user (install Codex skill to user scope)\n`\n if (json) {\n outputJson({ ok: true, help: text })\n } else {\n process.stdout.write(`${text}\\n`)\n }\n}\n\nfunction parseNumber(value: unknown, fallback: number | undefined): number | undefined {\n if (value === undefined || value === null || value === '') {\n return fallback\n }\n const parsed = Number(value)\n if (Number.isFinite(parsed)) return parsed\n return fallback\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n","export const DEFAULT_HOST = '127.0.0.1'\nexport const DEFAULT_PORT = 7242\nexport const DEFAULT_BASE_PATH = '/'\nexport const DEFAULT_LOGS_DIR = '.logs'\nexport const DEFAULT_MAX_BODY_KB = 256\n","export function isProcessAlive(pid: number): boolean {\n if (!pid) return false\n try {\n process.kill(pid, 0)\n return true\n } catch (error) {\n const err = error as NodeJS.ErrnoException\n return err.code === 'EPERM'\n }\n}\n\nexport async function terminateProcess(pid: number, timeoutMs: number): Promise<boolean> {\n if (!isProcessAlive(pid)) return true\n try {\n process.kill(pid, 'SIGTERM')\n } catch (error) {\n const err = error as NodeJS.ErrnoException\n if (err.code === 'ESRCH') return true\n }\n\n const start = Date.now()\n while (Date.now() - start < timeoutMs) {\n if (!isProcessAlive(pid)) return true\n await sleep(100)\n }\n\n try {\n process.kill(pid, 'SIGKILL')\n } catch (error) {\n const err = error as NodeJS.ErrnoException\n if (err.code === 'ESRCH') return true\n }\n\n return !isProcessAlive(pid)\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n","import path from 'node:path'\nimport { DEFAULT_LOGS_DIR } from './constants'\n\ntype PathOptions = {\n cwd: string\n logsDir?: string\n}\n\nexport function resolveLogsDir({ cwd, logsDir }: PathOptions): string {\n const dir = logsDir && logsDir.length > 0 ? logsDir : DEFAULT_LOGS_DIR\n return path.resolve(cwd, dir)\n}\n\nexport function getRuntimeDir(logsDir: string): string {\n return logsDir\n}\n\nexport function getRuntimePath(logsDir: string): string {\n return path.join(getRuntimeDir(logsDir), 'runtime.json')\n}\n\nexport function getPidPath(logsDir: string): string {\n return path.join(getRuntimeDir(logsDir), 'server.pid')\n}\n\nexport function getSessionLogPath(\n logsDir: string,\n sessionId: string,\n runId: string,\n): string {\n const safeSession = sanitizePathSegment(sessionId)\n const safeRun = sanitizePathSegment(runId)\n return path.join(getRuntimeDir(logsDir), `${safeSession}-${safeRun}.jsonl`)\n}\n\nfunction sanitizePathSegment(value: string): string {\n return value.replace(/[\\\\/]/g, '_').replace(/\\.\\./g, '_').trim() || 'unknown'\n}\n","import fs from 'node:fs/promises'\nimport { getPidPath, getRuntimeDir, getRuntimePath } from './paths'\n\nexport type RuntimeInfo = {\n ok: boolean\n version: string\n pid: number\n cwd: string\n logsDir: string\n running: boolean\n server: {\n host: string\n port: number\n baseUrl: string\n basePath: string\n endpoints: {\n health: string\n ingestTemplate: string\n }\n }\n startedAt: string\n stoppedAt?: string\n options: {\n maxBodyKB: number\n tokenEnabled: boolean\n idleTtlMs?: number\n }\n}\n\nexport async function readRuntime(logsDir: string): Promise<RuntimeInfo | null> {\n try {\n const raw = await fs.readFile(getRuntimePath(logsDir), 'utf8')\n return JSON.parse(raw) as RuntimeInfo\n } catch {\n return null\n }\n}\n\nexport async function writeRuntime(logsDir: string, info: RuntimeInfo): Promise<void> {\n await fs.mkdir(getRuntimeDir(logsDir), { recursive: true })\n await fs.writeFile(getRuntimePath(logsDir), JSON.stringify(info, null, 2), 'utf8')\n}\n\nexport async function writePid(logsDir: string, pid: number): Promise<void> {\n await fs.mkdir(getRuntimeDir(logsDir), { recursive: true })\n await fs.writeFile(getPidPath(logsDir), String(pid), 'utf8')\n}\n\nexport async function removePid(logsDir: string): Promise<void> {\n try {\n await fs.unlink(getPidPath(logsDir))\n } catch {\n return\n }\n}\n\nexport async function markStopped(logsDir: string): Promise<void> {\n const current = await readRuntime(logsDir)\n if (!current) return\n const updated: RuntimeInfo = {\n ...current,\n running: false,\n stoppedAt: new Date().toISOString(),\n }\n await writeRuntime(logsDir, updated)\n}\n","import http from 'node:http'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { formatBaseUrl, resolvePort } from './net'\nimport { getSessionLogPath, resolveLogsDir } from './paths'\nimport { RuntimeInfo, markStopped, removePid, writePid, writeRuntime } from './runtime'\nimport { getPackageVersion } from './version'\n\nexport type StartOptions = {\n host: string\n port?: number\n basePath: string\n logsDir?: string\n maxBodyKB: number\n token?: string\n idleTtlMs?: number\n cwd: string\n}\n\nexport type StartedServer = {\n server: http.Server\n host: string\n port: number\n basePath: string\n baseUrl: string\n logsDir: string\n close: () => Promise<void>\n}\n\nconst REQUIRED_FIELDS = ['timestamp', 'message', 'sessionId', 'runId', 'hypothesisId'] as const\nconst CORS_HEADERS = {\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET,POST,OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Debug-Token',\n 'Access-Control-Max-Age': '86400',\n} as const\n\nexport async function startServer(options: StartOptions): Promise<StartedServer> {\n const logsDir = resolveLogsDir({ cwd: options.cwd, logsDir: options.logsDir })\n const host = options.host\n const basePath = normalizeBasePath(options.basePath)\n const port = await resolvePort(host, options.port)\n const baseUrl = formatBaseUrl(host, port)\n\n let idleTimer: NodeJS.Timeout | undefined\n const server = http.createServer(async (req, res) => {\n applyCorsHeaders(res)\n try {\n const url = new URL(req.url ?? '/', baseUrl)\n const normalizedPath = stripBasePath(url.pathname, basePath)\n\n if (normalizedPath == null) {\n respondJson(res, 404, { ok: false, error: 'not_found' })\n return\n }\n\n if (req.method === 'OPTIONS') {\n respondNoContent(res, 204)\n return\n }\n\n if (req.method === 'GET' && normalizedPath === '/health') {\n respondJson(res, 200, { ok: true })\n return\n }\n\n if (req.method === 'POST' && normalizedPath.startsWith('/ingest/')) {\n const streamId = decodeURIComponent(normalizedPath.replace('/ingest/', ''))\n if (!authorizeRequest(req, options.token)) {\n respondJson(res, 401, { ok: false, error: 'unauthorized' })\n return\n }\n\n let payload: unknown\n try {\n payload = await readJsonBody(req, options.maxBodyKB)\n } catch (error) {\n if (error instanceof BodyTooLargeError) {\n respondJson(res, 413, { ok: false, error: 'body_too_large' })\n return\n }\n respondJson(res, 400, { ok: false, error: 'invalid_json' })\n return\n }\n\n if (!payload || typeof payload !== 'object') {\n respondJson(res, 400, { ok: false, error: 'invalid_body' })\n return\n }\n\n const missing = REQUIRED_FIELDS.filter((field) => !(field in payload))\n if (missing.length > 0) {\n respondJson(res, 400, { ok: false, error: 'missing_fields', missing })\n return\n }\n\n const event = payload as Record<string, unknown>\n const sessionId = String(event.sessionId)\n const runId = String(event.runId)\n const logPath = getSessionLogPath(logsDir, sessionId, runId)\n await fs.mkdir(path.dirname(logPath), { recursive: true })\n\n const enriched = {\n ...event,\n _meta: {\n streamId,\n receivedAt: Date.now(),\n },\n }\n\n await fs.appendFile(logPath, `${JSON.stringify(enriched)}\\n`, 'utf8')\n\n if (options.idleTtlMs && options.idleTtlMs > 0) {\n resetIdleTimer(options.idleTtlMs)\n }\n\n respondJson(res, 200, { ok: true, written: true, path: logPath })\n return\n }\n\n respondJson(res, 404, { ok: false, error: 'not_found' })\n } catch {\n respondJson(res, 500, { ok: false, error: 'internal_error' })\n }\n })\n\n const close = async (): Promise<void> => {\n if (idleTimer) clearTimeout(idleTimer)\n await new Promise<void>((resolve, reject) => {\n server.close((err) => {\n if (err) reject(err)\n else resolve()\n })\n })\n }\n\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject)\n server.listen(port, host, () => resolve())\n })\n\n const runtime: RuntimeInfo = {\n ok: true,\n version: getPackageVersion(),\n pid: process.pid,\n cwd: options.cwd,\n logsDir,\n running: true,\n server: {\n host,\n port,\n baseUrl,\n basePath,\n endpoints: {\n health: `${basePath}/health`,\n ingestTemplate: `${basePath}/ingest/{streamId}`,\n },\n },\n startedAt: new Date().toISOString(),\n options: {\n maxBodyKB: options.maxBodyKB,\n tokenEnabled: Boolean(options.token),\n idleTtlMs: options.idleTtlMs,\n },\n }\n\n await writeRuntime(logsDir, runtime)\n await writePid(logsDir, process.pid)\n\n if (options.idleTtlMs && options.idleTtlMs > 0) {\n resetIdleTimer(options.idleTtlMs)\n }\n\n return { server, host, port, basePath, baseUrl, logsDir, close }\n\n function resetIdleTimer(ttl: number): void {\n if (idleTimer) clearTimeout(idleTimer)\n idleTimer = setTimeout(async () => {\n await close()\n await markStopped(logsDir)\n await removePid(logsDir)\n process.exit(0)\n }, ttl)\n }\n}\n\nfunction normalizeBasePath(basePath: string): string {\n if (!basePath || basePath === '/') return ''\n const trimmed = basePath.startsWith('/') ? basePath : `/${basePath}`\n return trimmed.endsWith('/') ? trimmed.slice(0, -1) : trimmed\n}\n\nfunction stripBasePath(pathname: string, basePath: string): string | null {\n if (!basePath) return pathname\n if (!pathname.startsWith(basePath)) return null\n const sliced = pathname.slice(basePath.length)\n return sliced.length === 0 ? '/' : sliced\n}\n\nfunction authorizeRequest(req: http.IncomingMessage, token?: string): boolean {\n if (!token) return true\n const authHeader = req.headers.authorization\n if (authHeader && authHeader === `Bearer ${token}`) return true\n const headerToken = req.headers['x-debug-token']\n if (typeof headerToken === 'string' && headerToken === token) return true\n return false\n}\n\nfunction respondJson(res: http.ServerResponse, status: number, payload: unknown): void {\n const data = JSON.stringify(payload)\n res.statusCode = status\n res.setHeader('Content-Type', 'application/json')\n res.setHeader('Content-Length', Buffer.byteLength(data))\n res.end(data)\n}\n\nfunction respondNoContent(res: http.ServerResponse, status: number): void {\n res.statusCode = status\n res.end()\n}\n\nfunction applyCorsHeaders(res: http.ServerResponse): void {\n for (const [key, value] of Object.entries(CORS_HEADERS)) {\n res.setHeader(key, value)\n }\n}\n\nclass BodyTooLargeError extends Error {}\n\nfunction readJsonBody(req: http.IncomingMessage, maxBodyKB: number): Promise<unknown> {\n const maxBytes = maxBodyKB * 1024\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = []\n let size = 0\n let finished = false\n\n req.on('data', (chunk) => {\n if (finished) return\n size += chunk.length\n if (size > maxBytes) {\n finished = true\n req.destroy()\n reject(new BodyTooLargeError())\n return\n }\n chunks.push(chunk)\n })\n\n req.on('end', () => {\n if (finished) return\n finished = true\n try {\n const raw = Buffer.concat(chunks).toString('utf8')\n resolve(raw.length === 0 ? {} : JSON.parse(raw))\n } catch (error) {\n reject(error)\n }\n })\n\n req.on('error', (error) => {\n if (finished) return\n finished = true\n reject(error)\n })\n })\n}\n","import net from 'node:net'\n\nexport async function resolvePort(host: string, port: number | undefined): Promise<number> {\n if (!port || port === 0) {\n return getRandomPort(host)\n }\n\n try {\n await checkPort(host, port)\n return port\n } catch {\n return getRandomPort(host)\n }\n}\n\nexport function formatBaseUrl(host: string, port: number): string {\n const needsBrackets = host.includes(':') && !host.startsWith('[')\n const safeHost = needsBrackets ? `[${host}]` : host\n return `http://${safeHost}:${port}`\n}\n\nfunction checkPort(host: string, port: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const server = net.createServer()\n server.once('error', (error) => {\n server.close()\n reject(error)\n })\n server.listen(port, host, () => {\n server.close(() => resolve())\n })\n })\n}\n\nfunction getRandomPort(host: string): Promise<number> {\n return new Promise((resolve, reject) => {\n const server = net.createServer()\n server.once('error', (error) => {\n server.close()\n reject(error)\n })\n server.listen(0, host, () => {\n const address = server.address()\n if (!address || typeof address === 'string') {\n server.close(() => reject(new Error('Failed to resolve port')))\n return\n }\n const selected = address.port\n server.close(() => resolve(selected))\n })\n })\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\n\nexport function getPackageVersion(): string {\n try {\n const pkgPath = findPackageJsonPath()\n const raw = fs.readFileSync(pkgPath, 'utf8')\n const data = JSON.parse(raw) as { version?: string }\n return data.version ?? '0.0.0'\n } catch {\n return '0.0.0'\n }\n}\n\nfunction findPackageJsonPath(): string {\n let current = path.resolve(__dirname)\n for (let i = 0; i < 5; i += 1) {\n const candidate = path.join(current, 'package.json')\n if (fs.existsSync(candidate)) return candidate\n current = path.dirname(current)\n }\n return path.join(process.cwd(), 'package.json')\n}\n"],"mappings":"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","names":["import_promises","import_node_path","path","fs","import_promises","import_node_path","net","import_node_path","fs","path","http","fs","path","minimist","payload","scope","fs","path","os","readline","sleep","http"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/constants.ts","../src/process.ts","../src/paths.ts","../src/runtime.ts","../src/server.ts","../src/net.ts","../src/version.ts"],"sourcesContent":["#!/usr/bin/env node\nimport fs from 'node:fs/promises'\nimport os from 'node:os'\nimport path from 'node:path'\nimport readline from 'node:readline/promises'\nimport minimist from 'minimist'\nimport {\n DEFAULT_BASE_PATH,\n DEFAULT_HOST,\n DEFAULT_LOGS_DIR,\n DEFAULT_MAX_BODY_KB,\n DEFAULT_PORT,\n} from './constants'\nimport { isProcessAlive, terminateProcess } from './process'\nimport { resolveLogsDir } from './paths'\nimport { RuntimeInfo, markStopped, readRuntime, removePid } from './runtime'\nimport { startServer } from './server'\n\nconst args = minimist(process.argv.slice(2), {\n boolean: ['json', 'force', 'help', 'user'],\n string: ['host', 'base-path', 'logs-dir', 'token'],\n alias: {\n h: 'help',\n u: 'user',\n },\n})\n\nconst primary = String(args._[0] ?? 'help')\nconst secondary = args._[1] ? String(args._[1]) : undefined\nconst scope = primary === 'server' || primary === 'codex' ? primary : 'server'\nconst command =\n scope === 'server' ? String(primary === 'server' ? secondary ?? 'help' : primary) : String(secondary ?? 'help')\n\nconst json = Boolean(args.json)\nconst SKILL_NAME = 'code-debug-skill'\n\nvoid main().catch((error) => {\n outputError(error instanceof Error ? error.message : 'unexpected_error')\n process.exitCode = 1\n})\n\nasync function main(): Promise<void> {\n if (args.help || command === 'help') {\n printHelp()\n return\n }\n\n if (scope === 'codex') {\n await handleCodex(command)\n return\n }\n\n switch (command) {\n case 'start':\n await handleStart()\n return\n case 'run':\n if (!process.env.DEBUGSK_CHILD) {\n outputError('use_start_command')\n return\n }\n await handleRun()\n return\n case 'status':\n await handleStatus()\n return\n case 'stop':\n await handleStop()\n return\n default:\n outputError(`unknown_command:${command}`)\n }\n}\n\nfunction getCommonOptions() {\n const host = String(args.host ?? DEFAULT_HOST)\n const port = parseNumber(args.port, DEFAULT_PORT) ?? DEFAULT_PORT\n const basePath = String(args['base-path'] ?? DEFAULT_BASE_PATH)\n const logsDir = args['logs-dir'] ? String(args['logs-dir']) : undefined\n const maxBodyKB = parseNumber(args['max-body-kb'], DEFAULT_MAX_BODY_KB) ?? DEFAULT_MAX_BODY_KB\n const token = args.token ? String(args.token) : undefined\n const idleTtlMs = parseNumber(args['idle-ttl-ms'], undefined)\n return { host, port, basePath, logsDir, maxBodyKB, token, idleTtlMs }\n}\n\nasync function handleStart(): Promise<void> {\n const { host, port, basePath, logsDir, maxBodyKB, token, idleTtlMs } = getCommonOptions()\n const cwd = process.cwd()\n const resolvedLogsDir = resolveLogsDir({ cwd, logsDir })\n const runtime = await readRuntime(resolvedLogsDir)\n\n if (runtime && !runtime.options) {\n outputLegacyRuntimeError()\n return\n }\n\n if (runtime && isProcessAlive(runtime.pid) && !args.force) {\n const payload = buildStartOutput(runtime, true)\n outputStart(payload)\n return\n }\n\n if (runtime && isProcessAlive(runtime.pid) && args.force) {\n await terminateProcess(runtime.pid, 3000)\n await markStopped(resolvedLogsDir)\n await removePid(resolvedLogsDir)\n }\n\n if (runtime && !isProcessAlive(runtime.pid)) {\n await markStopped(resolvedLogsDir)\n await removePid(resolvedLogsDir)\n }\n\n const spawnResult = await spawnBackground({\n host,\n port,\n basePath,\n logsDir,\n maxBodyKB,\n token,\n idleTtlMs,\n })\n\n const finalRuntime = await waitForRuntime(resolvedLogsDir, 5000)\n if (!finalRuntime) {\n outputError('start_failed')\n return\n }\n\n const ok = await waitForHealth(finalRuntime, 5000)\n if (!ok) {\n outputError('health_check_failed')\n return\n }\n\n const payload = buildStartOutput(finalRuntime, false, spawnResult?.pid)\n outputStart(payload)\n}\n\nasync function handleRun(): Promise<void> {\n const { host, port, basePath, logsDir, maxBodyKB, token, idleTtlMs } = getCommonOptions()\n const cwd = process.cwd()\n\n const started = await startServer({\n host,\n port,\n basePath,\n logsDir,\n maxBodyKB,\n token,\n idleTtlMs,\n cwd,\n })\n\n installSignalHandlers(started.logsDir, started.close)\n\n if (!json) {\n logInfo(`debugsk server listening at ${started.baseUrl}`)\n }\n}\n\nasync function handleStatus(): Promise<void> {\n const cwd = process.cwd()\n const logsDir = args['logs-dir'] ? String(args['logs-dir']) : undefined\n const resolvedLogsDir = resolveLogsDir({ cwd, logsDir })\n const runtime = await readRuntime(resolvedLogsDir)\n\n if (!runtime) {\n outputStatus({ ok: false, running: false, error: 'not_running' })\n return\n }\n if (!runtime.options) {\n outputLegacyRuntimeError()\n return\n }\n\n const running = isProcessAlive(runtime.pid)\n const payload = {\n ...runtime,\n running,\n }\n outputStatus(payload)\n}\n\nasync function handleStop(): Promise<void> {\n const cwd = process.cwd()\n const logsDir = args['logs-dir'] ? String(args['logs-dir']) : undefined\n const resolvedLogsDir = resolveLogsDir({ cwd, logsDir })\n const runtime = await readRuntime(resolvedLogsDir)\n\n if (!runtime) {\n outputStop({ ok: true, stopped: false, running: false })\n return\n }\n\n const stopped = await terminateProcess(runtime.pid, 3000)\n if (stopped) {\n await markStopped(resolvedLogsDir)\n await removePid(resolvedLogsDir)\n }\n\n outputStop({ ok: true, stopped, pid: runtime.pid })\n}\n\nasync function handleCodex(subcommand: string): Promise<void> {\n switch (subcommand) {\n case 'install':\n await codexInstall(false)\n return\n case 'update':\n await codexInstall(true)\n return\n case 'remove':\n await codexRemove()\n return\n default:\n outputError(`unknown_command:codex:${subcommand}`)\n }\n}\n\nasync function codexInstall(force: boolean): Promise<void> {\n const source = await resolveSkillSource()\n const { dest, scope } = await resolveCodexDest({ createIfMissing: true })\n const exists = await pathExists(dest)\n\n if (exists && !force) {\n outputError('codex_skill_already_installed')\n return\n }\n\n await ensureSafeDest(dest)\n if (exists) {\n await fs.rm(dest, { recursive: true, force: true })\n }\n\n await fs.mkdir(path.dirname(dest), { recursive: true })\n await fs.cp(source, dest, { recursive: true })\n\n outputJsonResult({\n ok: true,\n action: force ? 'update' : 'install',\n scope,\n dest,\n source,\n replaced: exists,\n })\n}\n\nasync function codexRemove(): Promise<void> {\n const { dest, scope, homeExists } = await resolveCodexDest({ createIfMissing: false })\n if (!homeExists) {\n outputJsonResult({\n ok: true,\n action: 'remove',\n scope,\n dest,\n removed: false,\n reason: 'codex_home_missing',\n })\n return\n }\n await ensureSafeDest(dest)\n const exists = await pathExists(dest)\n if (exists) {\n await fs.rm(dest, { recursive: true, force: true })\n }\n outputJsonResult({\n ok: true,\n action: 'remove',\n scope,\n dest,\n removed: exists,\n })\n}\n\nasync function resolveSkillSource(): Promise<string> {\n const packageRoot = path.resolve(__dirname, '..')\n const repoRoot = path.resolve(packageRoot, '..', '..')\n const repoSource = path.join(repoRoot, 'skills', SKILL_NAME)\n if (await pathExists(repoSource)) return repoSource\n const packaged = path.join(packageRoot, 'skills', SKILL_NAME)\n if (await pathExists(packaged)) return packaged\n throw new Error(`missing_skill_source:${SKILL_NAME}`)\n}\n\nasync function resolveCodexDest({\n createIfMissing,\n}: {\n createIfMissing: boolean\n}): Promise<{ dest: string; scope: 'user' | 'local'; homeExists: boolean }> {\n const useUser = Boolean(args.user)\n const scope: 'user' | 'local' = useUser ? 'user' : 'local'\n const codexHome = useUser ? path.join(os.homedir(), '.codex') : path.join(process.cwd(), '.codex')\n const exists = await pathExists(codexHome)\n if (!exists && createIfMissing) {\n await ensureCodexHome(codexHome, scope)\n }\n return { dest: path.join(codexHome, 'skills', SKILL_NAME), scope, homeExists: exists }\n}\n\nasync function ensureSafeDest(dest: string): Promise<void> {\n const resolved = path.resolve(dest)\n const root = path.parse(resolved).root\n if (resolved === root || resolved === os.homedir()) {\n throw new Error('unsafe_dest')\n }\n}\n\nasync function ensureCodexHome(codexHome: string, scope: 'user' | 'local'): Promise<void> {\n if (await pathExists(codexHome)) return\n if (!process.stdin.isTTY) {\n throw new Error('codex_home_missing')\n }\n const prompt = `Create ${codexHome} for ${scope} scope? [y/N]: `\n const approved = await confirmPrompt(prompt)\n if (!approved) {\n throw new Error('codex_home_missing')\n }\n await fs.mkdir(codexHome, { recursive: true })\n}\n\nasync function confirmPrompt(prompt: string): Promise<boolean> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stderr })\n const answer = await rl.question(prompt)\n rl.close()\n return /^y(es)?$/i.test(answer.trim())\n}\n\nasync function pathExists(target: string): Promise<boolean> {\n try {\n await fs.access(target)\n return true\n } catch {\n return false\n }\n}\n\nasync function spawnBackground(options: {\n host: string\n port: number\n basePath: string\n logsDir?: string\n maxBodyKB: number\n token?: string\n idleTtlMs?: number\n}): Promise<{ pid: number } | null> {\n const nodeArgs = [...process.execArgv, process.argv[1]]\n const cmdArgs = ['run']\n\n cmdArgs.push('--host', options.host)\n cmdArgs.push('--port', String(options.port))\n cmdArgs.push('--base-path', options.basePath)\n cmdArgs.push('--max-body-kb', String(options.maxBodyKB))\n if (options.logsDir) cmdArgs.push('--logs-dir', options.logsDir)\n if (options.token) cmdArgs.push('--token', options.token)\n if (options.idleTtlMs) cmdArgs.push('--idle-ttl-ms', String(options.idleTtlMs))\n\n const spawn = await import('node:child_process')\n const child = spawn.spawn(process.execPath, [...nodeArgs, ...cmdArgs], {\n detached: true,\n stdio: 'ignore',\n env: {\n ...process.env,\n DEBUGSK_CHILD: '1',\n },\n })\n child.unref()\n return child.pid ? { pid: child.pid } : null\n}\n\nasync function waitForRuntime(logsDir: string, timeoutMs: number): Promise<RuntimeInfo | null> {\n const start = Date.now()\n while (Date.now() - start < timeoutMs) {\n const runtime = await readRuntime(logsDir)\n if (runtime && runtime.pid) return runtime\n await sleep(100)\n }\n return null\n}\n\nasync function waitForHealth(runtime: RuntimeInfo, timeoutMs: number): Promise<boolean> {\n const url = new URL(runtime.server.endpoints.health, runtime.server.baseUrl)\n const start = Date.now()\n while (Date.now() - start < timeoutMs) {\n const ok = await checkHealth(url)\n if (ok) return true\n await sleep(100)\n }\n return false\n}\n\nasync function checkHealth(url: URL): Promise<boolean> {\n const http = await import('node:http')\n return new Promise((resolve) => {\n const req = http.get(url, (res) => {\n res.resume()\n resolve(res.statusCode === 200)\n })\n req.on('error', () => resolve(false))\n })\n}\n\nfunction buildStartOutput(runtime: RuntimeInfo, existing: boolean, spawnedPid?: number) {\n const ingestPath = runtime.server.endpoints.ingestTemplate\n const ingestUrl = new URL(ingestPath.replace('{streamId}', '{streamId}'), runtime.server.baseUrl)\n const snippetHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n }\n const tokenEnabled = runtime.options.tokenEnabled\n if (tokenEnabled) {\n snippetHeaders.Authorization = 'Bearer YOUR_TOKEN'\n }\n\n const jsFetch = `fetch(\"${ingestUrl.toString()}\",{method:\"POST\",headers:${JSON.stringify(\n snippetHeaders,\n )},body:JSON.stringify({...})}).catch(()=>{});`\n\n return {\n ok: true,\n version: runtime.version,\n pid: runtime.pid,\n cwd: runtime.cwd,\n logsDir: runtime.logsDir,\n server: {\n host: runtime.server.host,\n port: runtime.server.port,\n baseUrl: runtime.server.baseUrl,\n endpoints: runtime.server.endpoints,\n },\n snippets: {\n jsFetch,\n },\n existing,\n spawnedPid,\n }\n}\n\nfunction installSignalHandlers(logsDir: string, close: () => Promise<void>): void {\n const shutdown = async () => {\n await close()\n await markStopped(logsDir)\n await removePid(logsDir)\n process.exit(0)\n }\n\n process.on('SIGTERM', () => void shutdown())\n process.on('SIGINT', () => void shutdown())\n}\n\nfunction outputJson(payload: unknown): void {\n process.stdout.write(`${JSON.stringify(payload)}\\n`)\n}\n\nfunction outputJsonResult(payload: Record<string, unknown>): void {\n if (json) {\n outputJson(payload)\n return\n }\n const action = String(payload.action ?? 'result')\n const ok = payload.ok ? 'ok' : 'error'\n const dest = payload.dest ? `dest=${payload.dest}` : ''\n process.stdout.write(`${action} ${ok} ${dest}\\n`)\n}\n\nfunction outputError(message: string): void {\n if (json) {\n outputJson({ ok: false, error: message })\n } else {\n process.stderr.write(`${message}\\n`)\n }\n}\n\nfunction outputLegacyRuntimeError(): void {\n const error = 'legacy_runtime_incompatible'\n const hint = 'delete .logs/runtime.json or the entire .logs directory, then retry'\n if (json) {\n outputJson({ ok: false, error, hint })\n } else {\n process.stderr.write(`${error}: ${hint}\\n`)\n }\n}\n\nfunction logInfo(message: string): void {\n process.stderr.write(`${message}\\n`)\n}\n\nfunction outputStart(payload: Record<string, unknown>): void {\n if (json) {\n outputJson(payload)\n return\n }\n const server = payload.server as RuntimeInfo['server']\n const pid = payload.pid as number\n const logsDir = payload.logsDir as string\n process.stdout.write(\n `started pid=${pid} baseUrl=${server.baseUrl} logsDir=${logsDir}\\n`,\n )\n}\n\nfunction outputStatus(payload: Record<string, unknown>): void {\n if (json) {\n outputJson(payload)\n return\n }\n const running = payload.running ? 'running' : 'stopped'\n const pid = payload.pid ? `pid=${payload.pid}` : 'pid=unknown'\n process.stdout.write(`status ${running} ${pid}\\n`)\n}\n\nfunction outputStop(payload: Record<string, unknown>): void {\n if (json) {\n outputJson(payload)\n return\n }\n const stopped = payload.stopped ? 'stopped' : 'not-stopped'\n const pid = payload.pid ? `pid=${payload.pid}` : ''\n process.stdout.write(`stop ${stopped} ${pid}\\n`)\n}\n\nfunction printHelp(): void {\n const text = `debugsk\n\nUsage:\n server start --json Start server in background and print JSON\n server status --json Show server status\n server stop --json Stop background server\n\n codex install Install Codex skill (user scope)\n codex update Update Codex skill (user scope)\n codex remove Remove Codex skill (user scope)\n\nAliases:\n start/status/stop Same as \"server <command>\"\n\nOptions:\n --host (default ${DEFAULT_HOST})\n --port (default ${DEFAULT_PORT})\n --base-path (default ${DEFAULT_BASE_PATH})\n --logs-dir (default ${DEFAULT_LOGS_DIR})\n --max-body-kb (default ${DEFAULT_MAX_BODY_KB})\n --token (optional)\n --idle-ttl-ms (optional)\n --force (restart even if already running)\n --json (stdout JSON only)\n -u, --user (install Codex skill to user scope)\n`\n if (json) {\n outputJson({ ok: true, help: text })\n } else {\n process.stdout.write(`${text}\\n`)\n }\n}\n\nfunction parseNumber(value: unknown, fallback: number | undefined): number | undefined {\n if (value === undefined || value === null || value === '') {\n return fallback\n }\n const parsed = Number(value)\n if (Number.isFinite(parsed)) return parsed\n return fallback\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n","export const DEFAULT_HOST = '127.0.0.1'\nexport const DEFAULT_PORT = 7242\nexport const DEFAULT_BASE_PATH = '/'\nexport const DEFAULT_LOGS_DIR = '.logs'\nexport const DEFAULT_MAX_BODY_KB = 256\n","export function isProcessAlive(pid: number): boolean {\n if (!pid) return false\n try {\n process.kill(pid, 0)\n return true\n } catch (error) {\n const err = error as NodeJS.ErrnoException\n return err.code === 'EPERM'\n }\n}\n\nexport async function terminateProcess(pid: number, timeoutMs: number): Promise<boolean> {\n if (!isProcessAlive(pid)) return true\n try {\n process.kill(pid, 'SIGTERM')\n } catch (error) {\n const err = error as NodeJS.ErrnoException\n if (err.code === 'ESRCH') return true\n }\n\n const start = Date.now()\n while (Date.now() - start < timeoutMs) {\n if (!isProcessAlive(pid)) return true\n await sleep(100)\n }\n\n try {\n process.kill(pid, 'SIGKILL')\n } catch (error) {\n const err = error as NodeJS.ErrnoException\n if (err.code === 'ESRCH') return true\n }\n\n return !isProcessAlive(pid)\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n","import path from 'node:path'\nimport { DEFAULT_LOGS_DIR } from './constants'\n\ntype PathOptions = {\n cwd: string\n logsDir?: string\n}\n\nexport function resolveLogsDir({ cwd, logsDir }: PathOptions): string {\n const dir = logsDir && logsDir.length > 0 ? logsDir : DEFAULT_LOGS_DIR\n return path.resolve(cwd, dir)\n}\n\nexport function getRuntimeDir(logsDir: string): string {\n return logsDir\n}\n\nexport function getRuntimePath(logsDir: string): string {\n return path.join(getRuntimeDir(logsDir), 'runtime.json')\n}\n\nexport function getPidPath(logsDir: string): string {\n return path.join(getRuntimeDir(logsDir), 'server.pid')\n}\n\nexport function getSessionLogPath(\n logsDir: string,\n sessionId: string,\n runId: string,\n): string {\n const safeSession = sanitizePathSegment(sessionId)\n const safeRun = sanitizePathSegment(runId)\n return path.join(getRuntimeDir(logsDir), `${safeSession}-${safeRun}.jsonl`)\n}\n\nfunction sanitizePathSegment(value: string): string {\n return value.replace(/[\\\\/]/g, '_').replace(/\\.\\./g, '_').trim() || 'unknown'\n}\n","import fs from 'node:fs/promises'\nimport { getPidPath, getRuntimeDir, getRuntimePath } from './paths'\n\nexport type RuntimeInfo = {\n ok: boolean\n version: string\n pid: number\n cwd: string\n logsDir: string\n running: boolean\n server: {\n host: string\n port: number\n baseUrl: string\n basePath: string\n endpoints: {\n health: string\n ingestTemplate: string\n }\n }\n startedAt: string\n stoppedAt?: string\n options: {\n maxBodyKB: number\n tokenEnabled: boolean\n idleTtlMs?: number\n }\n}\n\nexport async function readRuntime(logsDir: string): Promise<RuntimeInfo | null> {\n try {\n const raw = await fs.readFile(getRuntimePath(logsDir), 'utf8')\n return JSON.parse(raw) as RuntimeInfo\n } catch {\n return null\n }\n}\n\nexport async function writeRuntime(logsDir: string, info: RuntimeInfo): Promise<void> {\n await fs.mkdir(getRuntimeDir(logsDir), { recursive: true })\n await fs.writeFile(getRuntimePath(logsDir), JSON.stringify(info, null, 2), 'utf8')\n}\n\nexport async function writePid(logsDir: string, pid: number): Promise<void> {\n await fs.mkdir(getRuntimeDir(logsDir), { recursive: true })\n await fs.writeFile(getPidPath(logsDir), String(pid), 'utf8')\n}\n\nexport async function removePid(logsDir: string): Promise<void> {\n try {\n await fs.unlink(getPidPath(logsDir))\n } catch {\n return\n }\n}\n\nexport async function markStopped(logsDir: string): Promise<void> {\n const current = await readRuntime(logsDir)\n if (!current) return\n const updated: RuntimeInfo = {\n ...current,\n running: false,\n stoppedAt: new Date().toISOString(),\n }\n await writeRuntime(logsDir, updated)\n}\n","import http from 'node:http'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { formatBaseUrl, resolvePort } from './net'\nimport { getSessionLogPath, resolveLogsDir } from './paths'\nimport { RuntimeInfo, markStopped, removePid, writePid, writeRuntime } from './runtime'\nimport { getPackageVersion } from './version'\n\nexport type StartOptions = {\n host: string\n port?: number\n basePath: string\n logsDir?: string\n maxBodyKB: number\n token?: string\n idleTtlMs?: number\n cwd: string\n}\n\nexport type StartedServer = {\n server: http.Server\n host: string\n port: number\n basePath: string\n baseUrl: string\n logsDir: string\n close: () => Promise<void>\n}\n\n// Note: While these fields should always be provided for proper investigation,\n// the server will use fallback values if missing to ensure no logs are lost.\nconst LOG_FIELDS = ['timestamp', 'message', 'sessionId', 'runId', 'hypothesisId'] as const\nconst CORS_HEADERS = {\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET,POST,OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Debug-Token',\n 'Access-Control-Max-Age': '86400',\n} as const\n\nexport async function startServer(options: StartOptions): Promise<StartedServer> {\n const logsDir = resolveLogsDir({ cwd: options.cwd, logsDir: options.logsDir })\n const host = options.host\n const basePath = normalizeBasePath(options.basePath)\n const port = await resolvePort(host, options.port)\n const baseUrl = formatBaseUrl(host, port)\n\n let idleTimer: NodeJS.Timeout | undefined\n const server = http.createServer(async (req, res) => {\n applyCorsHeaders(res)\n try {\n const url = new URL(req.url ?? '/', baseUrl)\n const normalizedPath = stripBasePath(url.pathname, basePath)\n\n if (normalizedPath == null) {\n respondJson(res, 404, { ok: false, error: 'not_found' })\n return\n }\n\n if (req.method === 'OPTIONS') {\n respondNoContent(res, 204)\n return\n }\n\n if (req.method === 'GET' && normalizedPath === '/health') {\n respondJson(res, 200, { ok: true })\n return\n }\n\n if (req.method === 'POST' && normalizedPath.startsWith('/ingest/')) {\n const streamId = decodeURIComponent(normalizedPath.replace('/ingest/', ''))\n if (!authorizeRequest(req, options.token)) {\n respondJson(res, 401, { ok: false, error: 'unauthorized' })\n return\n }\n\n let payload: unknown\n try {\n payload = await readJsonBody(req, options.maxBodyKB)\n } catch (error) {\n if (error instanceof BodyTooLargeError) {\n respondJson(res, 413, { ok: false, error: 'body_too_large' })\n return\n }\n respondJson(res, 400, { ok: false, error: 'invalid_json' })\n return\n }\n\n if (!payload || typeof payload !== 'object') {\n respondJson(res, 400, { ok: false, error: 'invalid_body' })\n return\n }\n\n const event = payload as Record<string, unknown>\n\n // Apply fallback values for missing fields to ensure no logs are lost\n const timestamp = 'timestamp' in event ? event.timestamp : Date.now()\n const message = 'message' in event ? event.message : ''\n const sessionId = 'sessionId' in event ? String(event.sessionId) : ''\n const runId = 'runId' in event ? String(event.runId) : ''\n const hypothesisId = 'hypothesisId' in event ? String(event.hypothesisId) : ''\n\n const enriched = {\n timestamp,\n message,\n sessionId,\n runId,\n hypothesisId,\n ...event, // Original values take precedence if present\n _meta: {\n streamId,\n receivedAt: Date.now(),\n },\n }\n const logPath = getSessionLogPath(logsDir, sessionId, runId)\n await fs.mkdir(path.dirname(logPath), { recursive: true })\n\n await fs.appendFile(logPath, `${JSON.stringify(enriched)}\\n`, 'utf8')\n\n if (options.idleTtlMs && options.idleTtlMs > 0) {\n resetIdleTimer(options.idleTtlMs)\n }\n\n respondJson(res, 200, { ok: true, written: true, path: logPath })\n return\n }\n\n respondJson(res, 404, { ok: false, error: 'not_found' })\n } catch {\n respondJson(res, 500, { ok: false, error: 'internal_error' })\n }\n })\n\n const close = async (): Promise<void> => {\n if (idleTimer) clearTimeout(idleTimer)\n await new Promise<void>((resolve, reject) => {\n server.close((err) => {\n if (err) reject(err)\n else resolve()\n })\n })\n }\n\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject)\n server.listen(port, host, () => resolve())\n })\n\n const runtime: RuntimeInfo = {\n ok: true,\n version: getPackageVersion(),\n pid: process.pid,\n cwd: options.cwd,\n logsDir,\n running: true,\n server: {\n host,\n port,\n baseUrl,\n basePath,\n endpoints: {\n health: `${basePath}/health`,\n ingestTemplate: `${basePath}/ingest/{streamId}`,\n },\n },\n startedAt: new Date().toISOString(),\n options: {\n maxBodyKB: options.maxBodyKB,\n tokenEnabled: Boolean(options.token),\n idleTtlMs: options.idleTtlMs,\n },\n }\n\n await writeRuntime(logsDir, runtime)\n await writePid(logsDir, process.pid)\n\n if (options.idleTtlMs && options.idleTtlMs > 0) {\n resetIdleTimer(options.idleTtlMs)\n }\n\n return { server, host, port, basePath, baseUrl, logsDir, close }\n\n function resetIdleTimer(ttl: number): void {\n if (idleTimer) clearTimeout(idleTimer)\n idleTimer = setTimeout(async () => {\n await close()\n await markStopped(logsDir)\n await removePid(logsDir)\n process.exit(0)\n }, ttl)\n }\n}\n\nfunction normalizeBasePath(basePath: string): string {\n if (!basePath || basePath === '/') return ''\n const trimmed = basePath.startsWith('/') ? basePath : `/${basePath}`\n return trimmed.endsWith('/') ? trimmed.slice(0, -1) : trimmed\n}\n\nfunction stripBasePath(pathname: string, basePath: string): string | null {\n if (!basePath) return pathname\n if (!pathname.startsWith(basePath)) return null\n const sliced = pathname.slice(basePath.length)\n return sliced.length === 0 ? '/' : sliced\n}\n\nfunction authorizeRequest(req: http.IncomingMessage, token?: string): boolean {\n if (!token) return true\n const authHeader = req.headers.authorization\n if (authHeader && authHeader === `Bearer ${token}`) return true\n const headerToken = req.headers['x-debug-token']\n if (typeof headerToken === 'string' && headerToken === token) return true\n return false\n}\n\nfunction respondJson(res: http.ServerResponse, status: number, payload: unknown): void {\n const data = JSON.stringify(payload)\n res.statusCode = status\n res.setHeader('Content-Type', 'application/json')\n res.setHeader('Content-Length', Buffer.byteLength(data))\n res.end(data)\n}\n\nfunction respondNoContent(res: http.ServerResponse, status: number): void {\n res.statusCode = status\n res.end()\n}\n\nfunction applyCorsHeaders(res: http.ServerResponse): void {\n for (const [key, value] of Object.entries(CORS_HEADERS)) {\n res.setHeader(key, value)\n }\n}\n\nclass BodyTooLargeError extends Error {}\n\nfunction readJsonBody(req: http.IncomingMessage, maxBodyKB: number): Promise<unknown> {\n const maxBytes = maxBodyKB * 1024\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = []\n let size = 0\n let finished = false\n\n req.on('data', (chunk) => {\n if (finished) return\n size += chunk.length\n if (size > maxBytes) {\n finished = true\n req.destroy()\n reject(new BodyTooLargeError())\n return\n }\n chunks.push(chunk)\n })\n\n req.on('end', () => {\n if (finished) return\n finished = true\n try {\n const raw = Buffer.concat(chunks).toString('utf8')\n resolve(raw.length === 0 ? {} : JSON.parse(raw))\n } catch (error) {\n reject(error)\n }\n })\n\n req.on('error', (error) => {\n if (finished) return\n finished = true\n reject(error)\n })\n })\n}\n","import net from 'node:net'\n\nexport async function resolvePort(host: string, port: number | undefined): Promise<number> {\n if (!port || port === 0) {\n return getRandomPort(host)\n }\n\n try {\n await checkPort(host, port)\n return port\n } catch {\n return getRandomPort(host)\n }\n}\n\nexport function formatBaseUrl(host: string, port: number): string {\n const needsBrackets = host.includes(':') && !host.startsWith('[')\n const safeHost = needsBrackets ? `[${host}]` : host\n return `http://${safeHost}:${port}`\n}\n\nfunction checkPort(host: string, port: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const server = net.createServer()\n server.once('error', (error) => {\n server.close()\n reject(error)\n })\n server.listen(port, host, () => {\n server.close(() => resolve())\n })\n })\n}\n\nfunction getRandomPort(host: string): Promise<number> {\n return new Promise((resolve, reject) => {\n const server = net.createServer()\n server.once('error', (error) => {\n server.close()\n reject(error)\n })\n server.listen(0, host, () => {\n const address = server.address()\n if (!address || typeof address === 'string') {\n server.close(() => reject(new Error('Failed to resolve port')))\n return\n }\n const selected = address.port\n server.close(() => resolve(selected))\n })\n })\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\n\nexport function getPackageVersion(): string {\n try {\n const pkgPath = findPackageJsonPath()\n const raw = fs.readFileSync(pkgPath, 'utf8')\n const data = JSON.parse(raw) as { version?: string }\n return data.version ?? '0.0.0'\n } catch {\n return '0.0.0'\n }\n}\n\nfunction findPackageJsonPath(): string {\n let current = path.resolve(__dirname)\n for (let i = 0; i < 5; i += 1) {\n const candidate = path.join(current, 'package.json')\n if (fs.existsSync(candidate)) return candidate\n current = path.dirname(current)\n }\n return path.join(process.cwd(), 'package.json')\n}\n"],"mappings":"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","names":["import_promises","import_node_path","path","fs","import_promises","import_node_path","net","import_node_path","fs","path","http","fs","path","minimist","payload","scope","fs","path","os","readline","sleep","http"]}
|
package/dist/index.js
CHANGED
|
@@ -186,7 +186,6 @@ function findPackageJsonPath() {
|
|
|
186
186
|
}
|
|
187
187
|
|
|
188
188
|
// src/server.ts
|
|
189
|
-
var REQUIRED_FIELDS = ["timestamp", "message", "sessionId", "runId", "hypothesisId"];
|
|
190
189
|
var CORS_HEADERS = {
|
|
191
190
|
"Access-Control-Allow-Origin": "*",
|
|
192
191
|
"Access-Control-Allow-Methods": "GET,POST,OPTIONS",
|
|
@@ -238,23 +237,27 @@ async function startServer(options) {
|
|
|
238
237
|
respondJson(res, 400, { ok: false, error: "invalid_body" });
|
|
239
238
|
return;
|
|
240
239
|
}
|
|
241
|
-
const missing = REQUIRED_FIELDS.filter((field) => !(field in payload));
|
|
242
|
-
if (missing.length > 0) {
|
|
243
|
-
respondJson(res, 400, { ok: false, error: "missing_fields", missing });
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
240
|
const event = payload;
|
|
247
|
-
const
|
|
248
|
-
const
|
|
249
|
-
const
|
|
250
|
-
|
|
241
|
+
const timestamp = "timestamp" in event ? event.timestamp : Date.now();
|
|
242
|
+
const message = "message" in event ? event.message : "";
|
|
243
|
+
const sessionId = "sessionId" in event ? String(event.sessionId) : "";
|
|
244
|
+
const runId = "runId" in event ? String(event.runId) : "";
|
|
245
|
+
const hypothesisId = "hypothesisId" in event ? String(event.hypothesisId) : "";
|
|
251
246
|
const enriched = {
|
|
247
|
+
timestamp,
|
|
248
|
+
message,
|
|
249
|
+
sessionId,
|
|
250
|
+
runId,
|
|
251
|
+
hypothesisId,
|
|
252
252
|
...event,
|
|
253
|
+
// Original values take precedence if present
|
|
253
254
|
_meta: {
|
|
254
255
|
streamId,
|
|
255
256
|
receivedAt: Date.now()
|
|
256
257
|
}
|
|
257
258
|
};
|
|
259
|
+
const logPath = getSessionLogPath(logsDir, sessionId, runId);
|
|
260
|
+
await import_promises2.default.mkdir(import_node_path3.default.dirname(logPath), { recursive: true });
|
|
258
261
|
await import_promises2.default.appendFile(logPath, `${JSON.stringify(enriched)}
|
|
259
262
|
`, "utf8");
|
|
260
263
|
if (options.idleTtlMs && options.idleTtlMs > 0) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/server.ts","../src/net.ts","../src/paths.ts","../src/constants.ts","../src/runtime.ts","../src/version.ts"],"sourcesContent":["export { startServer, type StartOptions, type StartedServer } from './server'\nexport {\n DEFAULT_BASE_PATH,\n DEFAULT_HOST,\n DEFAULT_LOGS_DIR,\n DEFAULT_MAX_BODY_KB,\n DEFAULT_PORT,\n} from './constants'\n","import http from 'node:http'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { formatBaseUrl, resolvePort } from './net'\nimport { getSessionLogPath, resolveLogsDir } from './paths'\nimport { RuntimeInfo, markStopped, removePid, writePid, writeRuntime } from './runtime'\nimport { getPackageVersion } from './version'\n\nexport type StartOptions = {\n host: string\n port?: number\n basePath: string\n logsDir?: string\n maxBodyKB: number\n token?: string\n idleTtlMs?: number\n cwd: string\n}\n\nexport type StartedServer = {\n server: http.Server\n host: string\n port: number\n basePath: string\n baseUrl: string\n logsDir: string\n close: () => Promise<void>\n}\n\nconst REQUIRED_FIELDS = ['timestamp', 'message', 'sessionId', 'runId', 'hypothesisId'] as const\nconst CORS_HEADERS = {\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET,POST,OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Debug-Token',\n 'Access-Control-Max-Age': '86400',\n} as const\n\nexport async function startServer(options: StartOptions): Promise<StartedServer> {\n const logsDir = resolveLogsDir({ cwd: options.cwd, logsDir: options.logsDir })\n const host = options.host\n const basePath = normalizeBasePath(options.basePath)\n const port = await resolvePort(host, options.port)\n const baseUrl = formatBaseUrl(host, port)\n\n let idleTimer: NodeJS.Timeout | undefined\n const server = http.createServer(async (req, res) => {\n applyCorsHeaders(res)\n try {\n const url = new URL(req.url ?? '/', baseUrl)\n const normalizedPath = stripBasePath(url.pathname, basePath)\n\n if (normalizedPath == null) {\n respondJson(res, 404, { ok: false, error: 'not_found' })\n return\n }\n\n if (req.method === 'OPTIONS') {\n respondNoContent(res, 204)\n return\n }\n\n if (req.method === 'GET' && normalizedPath === '/health') {\n respondJson(res, 200, { ok: true })\n return\n }\n\n if (req.method === 'POST' && normalizedPath.startsWith('/ingest/')) {\n const streamId = decodeURIComponent(normalizedPath.replace('/ingest/', ''))\n if (!authorizeRequest(req, options.token)) {\n respondJson(res, 401, { ok: false, error: 'unauthorized' })\n return\n }\n\n let payload: unknown\n try {\n payload = await readJsonBody(req, options.maxBodyKB)\n } catch (error) {\n if (error instanceof BodyTooLargeError) {\n respondJson(res, 413, { ok: false, error: 'body_too_large' })\n return\n }\n respondJson(res, 400, { ok: false, error: 'invalid_json' })\n return\n }\n\n if (!payload || typeof payload !== 'object') {\n respondJson(res, 400, { ok: false, error: 'invalid_body' })\n return\n }\n\n const missing = REQUIRED_FIELDS.filter((field) => !(field in payload))\n if (missing.length > 0) {\n respondJson(res, 400, { ok: false, error: 'missing_fields', missing })\n return\n }\n\n const event = payload as Record<string, unknown>\n const sessionId = String(event.sessionId)\n const runId = String(event.runId)\n const logPath = getSessionLogPath(logsDir, sessionId, runId)\n await fs.mkdir(path.dirname(logPath), { recursive: true })\n\n const enriched = {\n ...event,\n _meta: {\n streamId,\n receivedAt: Date.now(),\n },\n }\n\n await fs.appendFile(logPath, `${JSON.stringify(enriched)}\\n`, 'utf8')\n\n if (options.idleTtlMs && options.idleTtlMs > 0) {\n resetIdleTimer(options.idleTtlMs)\n }\n\n respondJson(res, 200, { ok: true, written: true, path: logPath })\n return\n }\n\n respondJson(res, 404, { ok: false, error: 'not_found' })\n } catch {\n respondJson(res, 500, { ok: false, error: 'internal_error' })\n }\n })\n\n const close = async (): Promise<void> => {\n if (idleTimer) clearTimeout(idleTimer)\n await new Promise<void>((resolve, reject) => {\n server.close((err) => {\n if (err) reject(err)\n else resolve()\n })\n })\n }\n\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject)\n server.listen(port, host, () => resolve())\n })\n\n const runtime: RuntimeInfo = {\n ok: true,\n version: getPackageVersion(),\n pid: process.pid,\n cwd: options.cwd,\n logsDir,\n running: true,\n server: {\n host,\n port,\n baseUrl,\n basePath,\n endpoints: {\n health: `${basePath}/health`,\n ingestTemplate: `${basePath}/ingest/{streamId}`,\n },\n },\n startedAt: new Date().toISOString(),\n options: {\n maxBodyKB: options.maxBodyKB,\n tokenEnabled: Boolean(options.token),\n idleTtlMs: options.idleTtlMs,\n },\n }\n\n await writeRuntime(logsDir, runtime)\n await writePid(logsDir, process.pid)\n\n if (options.idleTtlMs && options.idleTtlMs > 0) {\n resetIdleTimer(options.idleTtlMs)\n }\n\n return { server, host, port, basePath, baseUrl, logsDir, close }\n\n function resetIdleTimer(ttl: number): void {\n if (idleTimer) clearTimeout(idleTimer)\n idleTimer = setTimeout(async () => {\n await close()\n await markStopped(logsDir)\n await removePid(logsDir)\n process.exit(0)\n }, ttl)\n }\n}\n\nfunction normalizeBasePath(basePath: string): string {\n if (!basePath || basePath === '/') return ''\n const trimmed = basePath.startsWith('/') ? basePath : `/${basePath}`\n return trimmed.endsWith('/') ? trimmed.slice(0, -1) : trimmed\n}\n\nfunction stripBasePath(pathname: string, basePath: string): string | null {\n if (!basePath) return pathname\n if (!pathname.startsWith(basePath)) return null\n const sliced = pathname.slice(basePath.length)\n return sliced.length === 0 ? '/' : sliced\n}\n\nfunction authorizeRequest(req: http.IncomingMessage, token?: string): boolean {\n if (!token) return true\n const authHeader = req.headers.authorization\n if (authHeader && authHeader === `Bearer ${token}`) return true\n const headerToken = req.headers['x-debug-token']\n if (typeof headerToken === 'string' && headerToken === token) return true\n return false\n}\n\nfunction respondJson(res: http.ServerResponse, status: number, payload: unknown): void {\n const data = JSON.stringify(payload)\n res.statusCode = status\n res.setHeader('Content-Type', 'application/json')\n res.setHeader('Content-Length', Buffer.byteLength(data))\n res.end(data)\n}\n\nfunction respondNoContent(res: http.ServerResponse, status: number): void {\n res.statusCode = status\n res.end()\n}\n\nfunction applyCorsHeaders(res: http.ServerResponse): void {\n for (const [key, value] of Object.entries(CORS_HEADERS)) {\n res.setHeader(key, value)\n }\n}\n\nclass BodyTooLargeError extends Error {}\n\nfunction readJsonBody(req: http.IncomingMessage, maxBodyKB: number): Promise<unknown> {\n const maxBytes = maxBodyKB * 1024\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = []\n let size = 0\n let finished = false\n\n req.on('data', (chunk) => {\n if (finished) return\n size += chunk.length\n if (size > maxBytes) {\n finished = true\n req.destroy()\n reject(new BodyTooLargeError())\n return\n }\n chunks.push(chunk)\n })\n\n req.on('end', () => {\n if (finished) return\n finished = true\n try {\n const raw = Buffer.concat(chunks).toString('utf8')\n resolve(raw.length === 0 ? {} : JSON.parse(raw))\n } catch (error) {\n reject(error)\n }\n })\n\n req.on('error', (error) => {\n if (finished) return\n finished = true\n reject(error)\n })\n })\n}\n","import net from 'node:net'\n\nexport async function resolvePort(host: string, port: number | undefined): Promise<number> {\n if (!port || port === 0) {\n return getRandomPort(host)\n }\n\n try {\n await checkPort(host, port)\n return port\n } catch {\n return getRandomPort(host)\n }\n}\n\nexport function formatBaseUrl(host: string, port: number): string {\n const needsBrackets = host.includes(':') && !host.startsWith('[')\n const safeHost = needsBrackets ? `[${host}]` : host\n return `http://${safeHost}:${port}`\n}\n\nfunction checkPort(host: string, port: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const server = net.createServer()\n server.once('error', (error) => {\n server.close()\n reject(error)\n })\n server.listen(port, host, () => {\n server.close(() => resolve())\n })\n })\n}\n\nfunction getRandomPort(host: string): Promise<number> {\n return new Promise((resolve, reject) => {\n const server = net.createServer()\n server.once('error', (error) => {\n server.close()\n reject(error)\n })\n server.listen(0, host, () => {\n const address = server.address()\n if (!address || typeof address === 'string') {\n server.close(() => reject(new Error('Failed to resolve port')))\n return\n }\n const selected = address.port\n server.close(() => resolve(selected))\n })\n })\n}\n","import path from 'node:path'\nimport { DEFAULT_LOGS_DIR } from './constants'\n\ntype PathOptions = {\n cwd: string\n logsDir?: string\n}\n\nexport function resolveLogsDir({ cwd, logsDir }: PathOptions): string {\n const dir = logsDir && logsDir.length > 0 ? logsDir : DEFAULT_LOGS_DIR\n return path.resolve(cwd, dir)\n}\n\nexport function getRuntimeDir(logsDir: string): string {\n return logsDir\n}\n\nexport function getRuntimePath(logsDir: string): string {\n return path.join(getRuntimeDir(logsDir), 'runtime.json')\n}\n\nexport function getPidPath(logsDir: string): string {\n return path.join(getRuntimeDir(logsDir), 'server.pid')\n}\n\nexport function getSessionLogPath(\n logsDir: string,\n sessionId: string,\n runId: string,\n): string {\n const safeSession = sanitizePathSegment(sessionId)\n const safeRun = sanitizePathSegment(runId)\n return path.join(getRuntimeDir(logsDir), `${safeSession}-${safeRun}.jsonl`)\n}\n\nfunction sanitizePathSegment(value: string): string {\n return value.replace(/[\\\\/]/g, '_').replace(/\\.\\./g, '_').trim() || 'unknown'\n}\n","export const DEFAULT_HOST = '127.0.0.1'\nexport const DEFAULT_PORT = 7242\nexport const DEFAULT_BASE_PATH = '/'\nexport const DEFAULT_LOGS_DIR = '.logs'\nexport const DEFAULT_MAX_BODY_KB = 256\n","import fs from 'node:fs/promises'\nimport { getPidPath, getRuntimeDir, getRuntimePath } from './paths'\n\nexport type RuntimeInfo = {\n ok: boolean\n version: string\n pid: number\n cwd: string\n logsDir: string\n running: boolean\n server: {\n host: string\n port: number\n baseUrl: string\n basePath: string\n endpoints: {\n health: string\n ingestTemplate: string\n }\n }\n startedAt: string\n stoppedAt?: string\n options: {\n maxBodyKB: number\n tokenEnabled: boolean\n idleTtlMs?: number\n }\n}\n\nexport async function readRuntime(logsDir: string): Promise<RuntimeInfo | null> {\n try {\n const raw = await fs.readFile(getRuntimePath(logsDir), 'utf8')\n return JSON.parse(raw) as RuntimeInfo\n } catch {\n return null\n }\n}\n\nexport async function writeRuntime(logsDir: string, info: RuntimeInfo): Promise<void> {\n await fs.mkdir(getRuntimeDir(logsDir), { recursive: true })\n await fs.writeFile(getRuntimePath(logsDir), JSON.stringify(info, null, 2), 'utf8')\n}\n\nexport async function writePid(logsDir: string, pid: number): Promise<void> {\n await fs.mkdir(getRuntimeDir(logsDir), { recursive: true })\n await fs.writeFile(getPidPath(logsDir), String(pid), 'utf8')\n}\n\nexport async function removePid(logsDir: string): Promise<void> {\n try {\n await fs.unlink(getPidPath(logsDir))\n } catch {\n return\n }\n}\n\nexport async function markStopped(logsDir: string): Promise<void> {\n const current = await readRuntime(logsDir)\n if (!current) return\n const updated: RuntimeInfo = {\n ...current,\n running: false,\n stoppedAt: new Date().toISOString(),\n }\n await writeRuntime(logsDir, updated)\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\n\nexport function getPackageVersion(): string {\n try {\n const pkgPath = findPackageJsonPath()\n const raw = fs.readFileSync(pkgPath, 'utf8')\n const data = JSON.parse(raw) as { version?: string }\n return data.version ?? '0.0.0'\n } catch {\n return '0.0.0'\n }\n}\n\nfunction findPackageJsonPath(): string {\n let current = path.resolve(__dirname)\n for (let i = 0; i < 5; i += 1) {\n const candidate = path.join(current, 'package.json')\n if (fs.existsSync(candidate)) return candidate\n current = path.dirname(current)\n }\n return path.join(process.cwd(), 'package.json')\n}\n"],"mappings":"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","names":["import_promises","import_node_path","net","path","fs","import_node_path","fs","path","http","fs","path"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/server.ts","../src/net.ts","../src/paths.ts","../src/constants.ts","../src/runtime.ts","../src/version.ts"],"sourcesContent":["export { startServer, type StartOptions, type StartedServer } from './server'\nexport {\n DEFAULT_BASE_PATH,\n DEFAULT_HOST,\n DEFAULT_LOGS_DIR,\n DEFAULT_MAX_BODY_KB,\n DEFAULT_PORT,\n} from './constants'\n","import http from 'node:http'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { formatBaseUrl, resolvePort } from './net'\nimport { getSessionLogPath, resolveLogsDir } from './paths'\nimport { RuntimeInfo, markStopped, removePid, writePid, writeRuntime } from './runtime'\nimport { getPackageVersion } from './version'\n\nexport type StartOptions = {\n host: string\n port?: number\n basePath: string\n logsDir?: string\n maxBodyKB: number\n token?: string\n idleTtlMs?: number\n cwd: string\n}\n\nexport type StartedServer = {\n server: http.Server\n host: string\n port: number\n basePath: string\n baseUrl: string\n logsDir: string\n close: () => Promise<void>\n}\n\n// Note: While these fields should always be provided for proper investigation,\n// the server will use fallback values if missing to ensure no logs are lost.\nconst LOG_FIELDS = ['timestamp', 'message', 'sessionId', 'runId', 'hypothesisId'] as const\nconst CORS_HEADERS = {\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET,POST,OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Debug-Token',\n 'Access-Control-Max-Age': '86400',\n} as const\n\nexport async function startServer(options: StartOptions): Promise<StartedServer> {\n const logsDir = resolveLogsDir({ cwd: options.cwd, logsDir: options.logsDir })\n const host = options.host\n const basePath = normalizeBasePath(options.basePath)\n const port = await resolvePort(host, options.port)\n const baseUrl = formatBaseUrl(host, port)\n\n let idleTimer: NodeJS.Timeout | undefined\n const server = http.createServer(async (req, res) => {\n applyCorsHeaders(res)\n try {\n const url = new URL(req.url ?? '/', baseUrl)\n const normalizedPath = stripBasePath(url.pathname, basePath)\n\n if (normalizedPath == null) {\n respondJson(res, 404, { ok: false, error: 'not_found' })\n return\n }\n\n if (req.method === 'OPTIONS') {\n respondNoContent(res, 204)\n return\n }\n\n if (req.method === 'GET' && normalizedPath === '/health') {\n respondJson(res, 200, { ok: true })\n return\n }\n\n if (req.method === 'POST' && normalizedPath.startsWith('/ingest/')) {\n const streamId = decodeURIComponent(normalizedPath.replace('/ingest/', ''))\n if (!authorizeRequest(req, options.token)) {\n respondJson(res, 401, { ok: false, error: 'unauthorized' })\n return\n }\n\n let payload: unknown\n try {\n payload = await readJsonBody(req, options.maxBodyKB)\n } catch (error) {\n if (error instanceof BodyTooLargeError) {\n respondJson(res, 413, { ok: false, error: 'body_too_large' })\n return\n }\n respondJson(res, 400, { ok: false, error: 'invalid_json' })\n return\n }\n\n if (!payload || typeof payload !== 'object') {\n respondJson(res, 400, { ok: false, error: 'invalid_body' })\n return\n }\n\n const event = payload as Record<string, unknown>\n\n // Apply fallback values for missing fields to ensure no logs are lost\n const timestamp = 'timestamp' in event ? event.timestamp : Date.now()\n const message = 'message' in event ? event.message : ''\n const sessionId = 'sessionId' in event ? String(event.sessionId) : ''\n const runId = 'runId' in event ? String(event.runId) : ''\n const hypothesisId = 'hypothesisId' in event ? String(event.hypothesisId) : ''\n\n const enriched = {\n timestamp,\n message,\n sessionId,\n runId,\n hypothesisId,\n ...event, // Original values take precedence if present\n _meta: {\n streamId,\n receivedAt: Date.now(),\n },\n }\n const logPath = getSessionLogPath(logsDir, sessionId, runId)\n await fs.mkdir(path.dirname(logPath), { recursive: true })\n\n await fs.appendFile(logPath, `${JSON.stringify(enriched)}\\n`, 'utf8')\n\n if (options.idleTtlMs && options.idleTtlMs > 0) {\n resetIdleTimer(options.idleTtlMs)\n }\n\n respondJson(res, 200, { ok: true, written: true, path: logPath })\n return\n }\n\n respondJson(res, 404, { ok: false, error: 'not_found' })\n } catch {\n respondJson(res, 500, { ok: false, error: 'internal_error' })\n }\n })\n\n const close = async (): Promise<void> => {\n if (idleTimer) clearTimeout(idleTimer)\n await new Promise<void>((resolve, reject) => {\n server.close((err) => {\n if (err) reject(err)\n else resolve()\n })\n })\n }\n\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject)\n server.listen(port, host, () => resolve())\n })\n\n const runtime: RuntimeInfo = {\n ok: true,\n version: getPackageVersion(),\n pid: process.pid,\n cwd: options.cwd,\n logsDir,\n running: true,\n server: {\n host,\n port,\n baseUrl,\n basePath,\n endpoints: {\n health: `${basePath}/health`,\n ingestTemplate: `${basePath}/ingest/{streamId}`,\n },\n },\n startedAt: new Date().toISOString(),\n options: {\n maxBodyKB: options.maxBodyKB,\n tokenEnabled: Boolean(options.token),\n idleTtlMs: options.idleTtlMs,\n },\n }\n\n await writeRuntime(logsDir, runtime)\n await writePid(logsDir, process.pid)\n\n if (options.idleTtlMs && options.idleTtlMs > 0) {\n resetIdleTimer(options.idleTtlMs)\n }\n\n return { server, host, port, basePath, baseUrl, logsDir, close }\n\n function resetIdleTimer(ttl: number): void {\n if (idleTimer) clearTimeout(idleTimer)\n idleTimer = setTimeout(async () => {\n await close()\n await markStopped(logsDir)\n await removePid(logsDir)\n process.exit(0)\n }, ttl)\n }\n}\n\nfunction normalizeBasePath(basePath: string): string {\n if (!basePath || basePath === '/') return ''\n const trimmed = basePath.startsWith('/') ? basePath : `/${basePath}`\n return trimmed.endsWith('/') ? trimmed.slice(0, -1) : trimmed\n}\n\nfunction stripBasePath(pathname: string, basePath: string): string | null {\n if (!basePath) return pathname\n if (!pathname.startsWith(basePath)) return null\n const sliced = pathname.slice(basePath.length)\n return sliced.length === 0 ? '/' : sliced\n}\n\nfunction authorizeRequest(req: http.IncomingMessage, token?: string): boolean {\n if (!token) return true\n const authHeader = req.headers.authorization\n if (authHeader && authHeader === `Bearer ${token}`) return true\n const headerToken = req.headers['x-debug-token']\n if (typeof headerToken === 'string' && headerToken === token) return true\n return false\n}\n\nfunction respondJson(res: http.ServerResponse, status: number, payload: unknown): void {\n const data = JSON.stringify(payload)\n res.statusCode = status\n res.setHeader('Content-Type', 'application/json')\n res.setHeader('Content-Length', Buffer.byteLength(data))\n res.end(data)\n}\n\nfunction respondNoContent(res: http.ServerResponse, status: number): void {\n res.statusCode = status\n res.end()\n}\n\nfunction applyCorsHeaders(res: http.ServerResponse): void {\n for (const [key, value] of Object.entries(CORS_HEADERS)) {\n res.setHeader(key, value)\n }\n}\n\nclass BodyTooLargeError extends Error {}\n\nfunction readJsonBody(req: http.IncomingMessage, maxBodyKB: number): Promise<unknown> {\n const maxBytes = maxBodyKB * 1024\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = []\n let size = 0\n let finished = false\n\n req.on('data', (chunk) => {\n if (finished) return\n size += chunk.length\n if (size > maxBytes) {\n finished = true\n req.destroy()\n reject(new BodyTooLargeError())\n return\n }\n chunks.push(chunk)\n })\n\n req.on('end', () => {\n if (finished) return\n finished = true\n try {\n const raw = Buffer.concat(chunks).toString('utf8')\n resolve(raw.length === 0 ? {} : JSON.parse(raw))\n } catch (error) {\n reject(error)\n }\n })\n\n req.on('error', (error) => {\n if (finished) return\n finished = true\n reject(error)\n })\n })\n}\n","import net from 'node:net'\n\nexport async function resolvePort(host: string, port: number | undefined): Promise<number> {\n if (!port || port === 0) {\n return getRandomPort(host)\n }\n\n try {\n await checkPort(host, port)\n return port\n } catch {\n return getRandomPort(host)\n }\n}\n\nexport function formatBaseUrl(host: string, port: number): string {\n const needsBrackets = host.includes(':') && !host.startsWith('[')\n const safeHost = needsBrackets ? `[${host}]` : host\n return `http://${safeHost}:${port}`\n}\n\nfunction checkPort(host: string, port: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const server = net.createServer()\n server.once('error', (error) => {\n server.close()\n reject(error)\n })\n server.listen(port, host, () => {\n server.close(() => resolve())\n })\n })\n}\n\nfunction getRandomPort(host: string): Promise<number> {\n return new Promise((resolve, reject) => {\n const server = net.createServer()\n server.once('error', (error) => {\n server.close()\n reject(error)\n })\n server.listen(0, host, () => {\n const address = server.address()\n if (!address || typeof address === 'string') {\n server.close(() => reject(new Error('Failed to resolve port')))\n return\n }\n const selected = address.port\n server.close(() => resolve(selected))\n })\n })\n}\n","import path from 'node:path'\nimport { DEFAULT_LOGS_DIR } from './constants'\n\ntype PathOptions = {\n cwd: string\n logsDir?: string\n}\n\nexport function resolveLogsDir({ cwd, logsDir }: PathOptions): string {\n const dir = logsDir && logsDir.length > 0 ? logsDir : DEFAULT_LOGS_DIR\n return path.resolve(cwd, dir)\n}\n\nexport function getRuntimeDir(logsDir: string): string {\n return logsDir\n}\n\nexport function getRuntimePath(logsDir: string): string {\n return path.join(getRuntimeDir(logsDir), 'runtime.json')\n}\n\nexport function getPidPath(logsDir: string): string {\n return path.join(getRuntimeDir(logsDir), 'server.pid')\n}\n\nexport function getSessionLogPath(\n logsDir: string,\n sessionId: string,\n runId: string,\n): string {\n const safeSession = sanitizePathSegment(sessionId)\n const safeRun = sanitizePathSegment(runId)\n return path.join(getRuntimeDir(logsDir), `${safeSession}-${safeRun}.jsonl`)\n}\n\nfunction sanitizePathSegment(value: string): string {\n return value.replace(/[\\\\/]/g, '_').replace(/\\.\\./g, '_').trim() || 'unknown'\n}\n","export const DEFAULT_HOST = '127.0.0.1'\nexport const DEFAULT_PORT = 7242\nexport const DEFAULT_BASE_PATH = '/'\nexport const DEFAULT_LOGS_DIR = '.logs'\nexport const DEFAULT_MAX_BODY_KB = 256\n","import fs from 'node:fs/promises'\nimport { getPidPath, getRuntimeDir, getRuntimePath } from './paths'\n\nexport type RuntimeInfo = {\n ok: boolean\n version: string\n pid: number\n cwd: string\n logsDir: string\n running: boolean\n server: {\n host: string\n port: number\n baseUrl: string\n basePath: string\n endpoints: {\n health: string\n ingestTemplate: string\n }\n }\n startedAt: string\n stoppedAt?: string\n options: {\n maxBodyKB: number\n tokenEnabled: boolean\n idleTtlMs?: number\n }\n}\n\nexport async function readRuntime(logsDir: string): Promise<RuntimeInfo | null> {\n try {\n const raw = await fs.readFile(getRuntimePath(logsDir), 'utf8')\n return JSON.parse(raw) as RuntimeInfo\n } catch {\n return null\n }\n}\n\nexport async function writeRuntime(logsDir: string, info: RuntimeInfo): Promise<void> {\n await fs.mkdir(getRuntimeDir(logsDir), { recursive: true })\n await fs.writeFile(getRuntimePath(logsDir), JSON.stringify(info, null, 2), 'utf8')\n}\n\nexport async function writePid(logsDir: string, pid: number): Promise<void> {\n await fs.mkdir(getRuntimeDir(logsDir), { recursive: true })\n await fs.writeFile(getPidPath(logsDir), String(pid), 'utf8')\n}\n\nexport async function removePid(logsDir: string): Promise<void> {\n try {\n await fs.unlink(getPidPath(logsDir))\n } catch {\n return\n }\n}\n\nexport async function markStopped(logsDir: string): Promise<void> {\n const current = await readRuntime(logsDir)\n if (!current) return\n const updated: RuntimeInfo = {\n ...current,\n running: false,\n stoppedAt: new Date().toISOString(),\n }\n await writeRuntime(logsDir, updated)\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\n\nexport function getPackageVersion(): string {\n try {\n const pkgPath = findPackageJsonPath()\n const raw = fs.readFileSync(pkgPath, 'utf8')\n const data = JSON.parse(raw) as { version?: string }\n return data.version ?? '0.0.0'\n } catch {\n return '0.0.0'\n }\n}\n\nfunction findPackageJsonPath(): string {\n let current = path.resolve(__dirname)\n for (let i = 0; i < 5; i += 1) {\n const candidate = path.join(current, 'package.json')\n if (fs.existsSync(candidate)) return candidate\n current = path.dirname(current)\n }\n return path.join(process.cwd(), 'package.json')\n}\n"],"mappings":"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","names":["import_promises","import_node_path","net","path","fs","import_node_path","fs","path","http","fs","path"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "debugsk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Debug investigation CLI: server + Codex skill management for hypothesis-driven workflows.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"debugsk": "dist/cli.js"
|
|
@@ -11,6 +11,15 @@
|
|
|
11
11
|
"dist",
|
|
12
12
|
"skills"
|
|
13
13
|
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsup",
|
|
16
|
+
"dev": "tsup --watch",
|
|
17
|
+
"typecheck": "tsc --noEmit",
|
|
18
|
+
"lint": "eslint .",
|
|
19
|
+
"format": "prettier --check .",
|
|
20
|
+
"format:write": "prettier --write .",
|
|
21
|
+
"test": "vitest run"
|
|
22
|
+
},
|
|
14
23
|
"engines": {
|
|
15
24
|
"node": ">=18"
|
|
16
25
|
},
|
|
@@ -33,14 +42,5 @@
|
|
|
33
42
|
"tsx": "^4.19.2",
|
|
34
43
|
"typescript": "^5.6.3",
|
|
35
44
|
"vitest": "^3.0.4"
|
|
36
|
-
},
|
|
37
|
-
"scripts": {
|
|
38
|
-
"build": "tsup",
|
|
39
|
-
"dev": "tsup --watch",
|
|
40
|
-
"typecheck": "tsc --noEmit",
|
|
41
|
-
"lint": "eslint .",
|
|
42
|
-
"format": "prettier --check .",
|
|
43
|
-
"format:write": "prettier --write .",
|
|
44
|
-
"test": "vitest run"
|
|
45
45
|
}
|
|
46
|
-
}
|
|
46
|
+
}
|
|
@@ -14,7 +14,9 @@ description: Standardized, hypothesis-driven debug investigation workflow for un
|
|
|
14
14
|
- required instrumentation (what to measure or log).
|
|
15
15
|
- Prefer decisive signals over narratives. Do not ask for reproduction without a plan to capture evidence.
|
|
16
16
|
- Narrow with comparisons (fail vs pass) and a binary-search style approach when possible.
|
|
17
|
-
-
|
|
17
|
+
- Add debug instrumentation generously to capture decisive signals in a single reproduction run.
|
|
18
|
+
- Assume each reproduction is costly; instrument enough to narrow root cause without requiring additional runs.
|
|
19
|
+
- Never fix code speculatively. Confirm root cause with evidence before any production code change.
|
|
18
20
|
|
|
19
21
|
## Tool selection (what to use)
|
|
20
22
|
- Primary tool for new instrumentation: local HTTP ingest logger.
|
|
@@ -60,12 +62,14 @@ description: Standardized, hypothesis-driven debug investigation workflow for un
|
|
|
60
62
|
- Use native logs as reference alongside the added instrumentation.
|
|
61
63
|
- Logs must never throw, avoid secrets/PII, and be easy to remove.
|
|
62
64
|
- Record location, message, timestamp, and correlation fields in every event.
|
|
65
|
+
- **YOU MUST ALWAYS include all log fields (timestamp, message, sessionId, runId, hypothesisId, location) in every log event. Never omit any field.**
|
|
63
66
|
- Do not guard instrumentation behind environment flags. Write logs for the investigation, then remove them after completion.
|
|
64
67
|
- AI inserts instrumentation and provides the exact reproduction steps; the user performs the reproduction run and shares the resulting logs.
|
|
65
68
|
|
|
66
69
|
## User interaction rules
|
|
67
70
|
- When reproduction is required, provide exact steps, expected signals, and required artifacts.
|
|
68
71
|
- If reproduction is not possible, pivot to existing logs, metrics, traces, config diffs, or safe probes.
|
|
72
|
+
- After embedding debug code, explicitly ask the user whether to use a tunneling setup (e.g., ngrok/Cloudflare Tunnel) for external or mobile access; do not assume.
|
|
69
73
|
|
|
70
74
|
## Cleanup policy
|
|
71
75
|
- When the user confirms the issue is resolved or the investigation is closed, stop the debug server and delete all investigation logs (e.g., `.logs/`).
|
|
@@ -73,7 +77,7 @@ description: Standardized, hypothesis-driven debug investigation workflow for un
|
|
|
73
77
|
- If deletion could affect unrelated files, confirm the exact paths before removal.
|
|
74
78
|
|
|
75
79
|
## Reporting format
|
|
76
|
-
Use the template in `assets/report-template.md`.
|
|
80
|
+
Use the template in `assets/report-template.md`. Headings are bilingual (English / Japanese); write content in the user's language.
|
|
77
81
|
|
|
78
82
|
## References
|
|
79
83
|
- Use `references/logging-schema.md` when adding or validating instrumentation.
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
# Investigation Summary
|
|
2
|
-
- Impact
|
|
3
|
-
- Confidence
|
|
1
|
+
# Investigation Summary / 調査概要
|
|
2
|
+
- Impact / 影響:
|
|
3
|
+
- Confidence / 確信度:
|
|
4
4
|
|
|
5
|
-
# Facts (observed)
|
|
5
|
+
# Facts (observed) / 事実(観測結果)
|
|
6
6
|
|
|
7
|
-
# Hypotheses
|
|
7
|
+
# Hypotheses / 仮説
|
|
8
8
|
|
|
9
|
-
# Instrumentation Plan
|
|
9
|
+
# Instrumentation Plan / 計装計画
|
|
10
10
|
|
|
11
|
-
# Reproduction Checklist
|
|
11
|
+
# Reproduction Checklist / 再現手順
|
|
12
12
|
|
|
13
|
-
# Findings (log-backed)
|
|
13
|
+
# Findings (log-backed) / 発見事項(ログ根拠あり)
|
|
14
14
|
|
|
15
|
-
# Root Cause (if confirmed)
|
|
15
|
+
# Root Cause (if confirmed) / 根本原因(確定時)
|
|
16
16
|
|
|
17
|
-
# Next Actions (if not confirmed)
|
|
17
|
+
# Next Actions (if not confirmed) / 次のアクション(未確定時)
|
|
18
18
|
|
|
19
|
-
# Fix Plan + Tests
|
|
19
|
+
# Fix Plan + Tests / 修正計画 + テスト
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
Use this schema when instrumenting. Keep fields small, structured, and correlated.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
- `
|
|
9
|
-
- `
|
|
10
|
-
- `
|
|
5
|
+
**IMPORTANT: You MUST ALWAYS include all required fields when logging. Never omit any of them.**
|
|
6
|
+
|
|
7
|
+
## Required fields (MUST ALWAYS be specified)
|
|
8
|
+
- `timestamp`: ms epoch or ISO-8601 string — **ALWAYS include this**
|
|
9
|
+
- `message`: short, human-readable message — **ALWAYS include this**
|
|
10
|
+
- `sessionId`: investigation session identifier — **ALWAYS include this**
|
|
11
|
+
- `runId`: single reproduction run identifier — **ALWAYS include this**
|
|
12
|
+
- `hypothesisId`: hypothesis identifier (e.g. "H1") — **ALWAYS include this**
|
|
11
13
|
|
|
12
14
|
## Recommended fields
|
|
13
15
|
- `location`: file:line or function name
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 OSS Contributors
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|