@code-yeongyu/senpi 2026.9.28-5 → 2026.9.28-7

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.
Files changed (156) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/bundle/chunks/{anthropic-messages-GG4ZKS6A.js → anthropic-messages-QOQJCY3F.js} +1 -1
  3. package/dist/bundle/chunks/{app-server-command-3AJWPHKJ.js → app-server-command-OUTRKHMK.js} +8 -8
  4. package/dist/bundle/chunks/{chunk-XYGXUFMG.js → chunk-3HCYHGK2.js} +1 -1
  5. package/dist/bundle/chunks/{chunk-EXUI5D5V.js → chunk-56COAYOU.js} +9 -9
  6. package/dist/bundle/chunks/{chunk-MMHQLGF2.js → chunk-AIM2YESB.js} +1 -1
  7. package/dist/bundle/chunks/{chunk-4BDFNRBE.js → chunk-B32PXL7U.js} +1 -1
  8. package/dist/bundle/chunks/chunk-CEMOA3TF.js +2 -0
  9. package/dist/bundle/chunks/{chunk-XNIX26QC.js → chunk-DB2X7SOZ.js} +2 -2
  10. package/dist/bundle/chunks/chunk-E5F5SVZF.js +5 -0
  11. package/dist/bundle/chunks/{chunk-OHJLQ7BY.js → chunk-F2YU5BZG.js} +1 -1
  12. package/dist/bundle/chunks/{chunk-BQGVC47Y.js → chunk-FILEUW2D.js} +1 -1
  13. package/dist/bundle/chunks/{chunk-JGRPPPHS.js → chunk-JASECXGC.js} +1 -1
  14. package/dist/bundle/chunks/{chunk-YLIS5N3W.js → chunk-JK5LVAOU.js} +1 -1
  15. package/dist/bundle/chunks/{chunk-KDZAVHA7.js → chunk-L4OOEWAT.js} +2 -2
  16. package/dist/bundle/chunks/{chunk-Z5NVK72W.js → chunk-LM2UMEX6.js} +1 -1
  17. package/dist/bundle/chunks/{chunk-C5I2LUOI.js → chunk-SQUUL72H.js} +1 -1
  18. package/dist/bundle/chunks/{chunk-LEAJXPT2.js → chunk-TOCWAEQB.js} +1 -1
  19. package/dist/bundle/chunks/{chunk-YEMM3LPR.js → chunk-VW3QZSX3.js} +1 -1
  20. package/dist/bundle/chunks/{chunk-7SFG425F.js → chunk-Y4CH7LYI.js} +2 -2
  21. package/dist/bundle/chunks/chunk-YJUO37UX.js +2 -0
  22. package/dist/bundle/chunks/{cli-main-NUSBF3HE.js → cli-main-26P4V2BK.js} +1 -1
  23. package/dist/bundle/chunks/github-copilot.js +1 -1
  24. package/dist/bundle/chunks/{help-fast-path-A4S4KOQ6.js → help-fast-path-BOMUI7U3.js} +1 -1
  25. package/dist/bundle/chunks/{host-command-D2CHSATG.js → host-command-ZVXNTXMN.js} +1 -1
  26. package/dist/bundle/chunks/host-lifecycle-MPLSJ5NB.js +3 -0
  27. package/dist/bundle/chunks/host-lifecycle.js +3 -3
  28. package/dist/bundle/chunks/{interactive-host-runtime-AAK47HIV.js → interactive-host-runtime-Q5EORM6B.js} +1 -1
  29. package/dist/bundle/chunks/{interactive-mode-LSTD6EUQ.js → interactive-mode-OVSKUTVC.js} +1 -1
  30. package/dist/bundle/chunks/{list-tips-S4U7TKER.js → list-tips-ARO4HRVK.js} +1 -1
  31. package/dist/bundle/chunks/{multi-session-host-5WNZ7XRV.js → multi-session-host-LJNXZRFA.js} +7 -7
  32. package/dist/bundle/chunks/{openai-completions-DVEOAQK4.js → openai-completions-BHE6TMUP.js} +1 -1
  33. package/dist/bundle/chunks/{openai-responses-7H2ADNW4.js → openai-responses-OGQ5QORF.js} +1 -1
  34. package/dist/bundle/chunks/{package-manager-cli-3HZYQYVX.js → package-manager-cli-MJCRY2JU.js} +1 -1
  35. package/dist/bundle/chunks/{rotation-stream-F36RJ6VP.js → rotation-stream-Q2EVDMUU.js} +1 -1
  36. package/dist/bundle/chunks/{rpc-mode-GMPBEVSL.js → rpc-mode-LY4HAZ5G.js} +1 -1
  37. package/dist/bundle/chunks/{schedule-command-BYWZGYOJ.js → schedule-command-3ANAEUY6.js} +1 -1
  38. package/dist/bundle/chunks/{session-picker-6VU2F5VF.js → session-picker-DRM7AGPY.js} +1 -1
  39. package/dist/bundle/chunks/session-worker.js +37 -37
  40. package/dist/bundle/cli.js +1 -1
  41. package/dist/bundle/index.js +1 -1
  42. package/dist/bundle/rpc-entry.js +1 -1
  43. package/dist/cli/args.js +2 -2
  44. package/dist/cli/args.js.map +1 -1
  45. package/dist/core/extensions/builtin/btw/index.d.ts.map +1 -1
  46. package/dist/core/extensions/builtin/btw/index.js +3 -1
  47. package/dist/core/extensions/builtin/btw/index.js.map +1 -1
  48. package/dist/core/extensions/builtin/prompt-preset/presets.d.ts.map +1 -1
  49. package/dist/core/extensions/builtin/prompt-preset/presets.js +2 -1
  50. package/dist/core/extensions/builtin/prompt-preset/presets.js.map +1 -1
  51. package/dist/core/extensions/builtin/websearch/websearch/native.d.ts +1 -0
  52. package/dist/core/extensions/builtin/websearch/websearch/native.d.ts.map +1 -1
  53. package/dist/core/extensions/builtin/websearch/websearch/native.js +8 -1
  54. package/dist/core/extensions/builtin/websearch/websearch/native.js.map +1 -1
  55. package/dist/main.d.ts +2 -2
  56. package/dist/main.d.ts.map +1 -1
  57. package/dist/main.js +25 -6
  58. package/dist/main.js.map +1 -1
  59. package/dist/modes/app-server/cli-args.d.ts +3 -0
  60. package/dist/modes/app-server/cli-args.d.ts.map +1 -1
  61. package/dist/modes/app-server/cli-args.js +25 -4
  62. package/dist/modes/app-server/cli-args.js.map +1 -1
  63. package/dist/modes/app-server/daemon/probe.d.ts +1 -0
  64. package/dist/modes/app-server/daemon/probe.d.ts.map +1 -1
  65. package/dist/modes/app-server/daemon/probe.js +4 -1
  66. package/dist/modes/app-server/daemon/probe.js.map +1 -1
  67. package/dist/modes/app-server/daemon/spawn.d.ts +26 -0
  68. package/dist/modes/app-server/daemon/spawn.d.ts.map +1 -0
  69. package/dist/modes/app-server/daemon/spawn.js +112 -0
  70. package/dist/modes/app-server/daemon/spawn.js.map +1 -0
  71. package/dist/modes/app-server/daemon.d.ts.map +1 -1
  72. package/dist/modes/app-server/daemon.js +14 -112
  73. package/dist/modes/app-server/daemon.js.map +1 -1
  74. package/dist/modes/app-server/extension-paths.d.ts +7 -0
  75. package/dist/modes/app-server/extension-paths.d.ts.map +1 -0
  76. package/dist/modes/app-server/extension-paths.js +10 -0
  77. package/dist/modes/app-server/extension-paths.js.map +1 -0
  78. package/dist/modes/app-server/index.d.ts.map +1 -1
  79. package/dist/modes/app-server/index.js +4 -1
  80. package/dist/modes/app-server/index.js.map +1 -1
  81. package/dist/modes/app-server/runtime.d.ts +5 -1
  82. package/dist/modes/app-server/runtime.d.ts.map +1 -1
  83. package/dist/modes/app-server/runtime.js +19 -3
  84. package/dist/modes/app-server/runtime.js.map +1 -1
  85. package/dist/modes/interactive/tips/catalog/computer-tips.js +1 -1
  86. package/dist/modes/interactive/tips/catalog/computer-tips.js.map +1 -1
  87. package/dist/modes/rpc/custom-capability.d.ts +5 -0
  88. package/dist/modes/rpc/custom-capability.d.ts.map +1 -1
  89. package/dist/modes/rpc/custom-capability.js +5 -0
  90. package/dist/modes/rpc/custom-capability.js.map +1 -1
  91. package/dist/modes/rpc/host-identity-env.d.ts +20 -0
  92. package/dist/modes/rpc/host-identity-env.d.ts.map +1 -0
  93. package/dist/modes/rpc/host-identity-env.js +20 -0
  94. package/dist/modes/rpc/host-identity-env.js.map +1 -0
  95. package/dist/modes/rpc/host-lifecycle.js +1 -1
  96. package/dist/modes/rpc/host-lifecycle.js.map +1 -1
  97. package/dist/modes/rpc/host-observe-request.d.ts +2 -0
  98. package/dist/modes/rpc/host-observe-request.d.ts.map +1 -1
  99. package/dist/modes/rpc/host-observe-request.js +4 -0
  100. package/dist/modes/rpc/host-observe-request.js.map +1 -1
  101. package/dist/modes/rpc/host-spawn-environment.js +1 -1
  102. package/dist/modes/rpc/host-spawn-environment.js.map +1 -1
  103. package/dist/modes/rpc/host-warm.d.ts +57 -0
  104. package/dist/modes/rpc/host-warm.d.ts.map +1 -0
  105. package/dist/modes/rpc/host-warm.js +125 -0
  106. package/dist/modes/rpc/host-warm.js.map +1 -0
  107. package/dist/modes/rpc/protocol-identity.d.ts +2 -11
  108. package/dist/modes/rpc/protocol-identity.d.ts.map +1 -1
  109. package/dist/modes/rpc/protocol-identity.js +2 -11
  110. package/dist/modes/rpc/protocol-identity.js.map +1 -1
  111. package/dist/modes/rpc/rpc-types.d.ts +24 -1
  112. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  113. package/dist/modes/rpc/rpc-types.js +2 -0
  114. package/dist/modes/rpc/rpc-types.js.map +1 -1
  115. package/dist/modes/rpc/session-command-router.d.ts +1 -1
  116. package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
  117. package/dist/modes/rpc/session-command-router.js +12 -1
  118. package/dist/modes/rpc/session-command-router.js.map +1 -1
  119. package/dist/modes/rpc/session-registry.d.ts +6 -2
  120. package/dist/modes/rpc/session-registry.d.ts.map +1 -1
  121. package/dist/modes/rpc/session-registry.js +6 -0
  122. package/dist/modes/rpc/session-registry.js.map +1 -1
  123. package/docs/app-server-daemon.md +1 -1
  124. package/docs/app-server.md +3 -0
  125. package/docs/rpc.md +48 -2
  126. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +24 -0
  127. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  128. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  129. package/node_modules/@earendil-works/pi-ai/dist/api/github-copilot-endpoint.d.ts +19 -0
  130. package/node_modules/@earendil-works/pi-ai/dist/api/github-copilot-endpoint.d.ts.map +1 -0
  131. package/node_modules/@earendil-works/pi-ai/dist/api/github-copilot-endpoint.js +48 -0
  132. package/node_modules/@earendil-works/pi-ai/dist/api/github-copilot-endpoint.js.map +1 -0
  133. package/node_modules/@earendil-works/pi-ai/dist/api/github-copilot-errors.d.ts.map +1 -1
  134. package/node_modules/@earendil-works/pi-ai/dist/api/github-copilot-errors.js +3 -0
  135. package/node_modules/@earendil-works/pi-ai/dist/api/github-copilot-errors.js.map +1 -1
  136. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot.d.ts.map +1 -1
  137. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot.js +18 -36
  138. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot.js.map +1 -1
  139. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  140. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  141. package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.d.ts +5 -3
  142. package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.d.ts.map +1 -1
  143. package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.js +6 -5
  144. package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.js.map +1 -1
  145. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.d.ts.map +1 -1
  146. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.js +15 -1
  147. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.js.map +1 -1
  148. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  149. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  150. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  151. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  152. package/package.json +7 -7
  153. package/dist/bundle/chunks/chunk-A4UMPXQF.js +0 -2
  154. package/dist/bundle/chunks/chunk-HH3KJDWA.js +0 -2
  155. package/dist/bundle/chunks/chunk-XPJLBOWV.js +0 -5
  156. package/dist/bundle/chunks/host-lifecycle-S7O5K62Z.js +0 -3
@@ -1 +1 @@
1
- {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../../src/modes/app-server/daemon.ts"],"names":[],"mappings":"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","sourcesContent":["import { type ChildProcess, spawn } from \"node:child_process\";\nimport { mkdir, open, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { getAgentDir } from \"../../config.ts\";\nimport { acquireOwnershipSafeLock } from \"../rpc/ownership-safe-lock.ts\";\nimport { inspectAppServerListenOccupancy } from \"./daemon/occupancy.ts\";\nimport {\n\tcleanupState,\n\tpollProbe,\n\tprobeListen,\n\treadSettings,\n\trunningOutput,\n\trunningUnmanagedOutput,\n} from \"./daemon/probe.ts\";\nimport {\n\ttype DaemonPidFile,\n\tparseDaemonPidFile,\n\tprocessMatchesPidFile,\n\treadProcessStartTime,\n\tstopValidatedPid,\n\twaitForGone,\n\twaitForStartTime,\n} from \"./daemon/process.ts\";\nimport type { AppServerDaemonCommandOptions, AppServerListen } from \"./index.ts\";\n\nexport interface DaemonPaths {\n\treadonly dir: string;\n\treadonly pidFile: string;\n\treadonly lockFile: string;\n\treadonly settingsFile: string;\n\treadonly stderrLog: string;\n\treadonly tokenFile: string;\n}\n\ntype DaemonOutput = Readonly<Record<string, string | number | undefined>>;\n\ntype SpawnedDaemon = {\n\treadonly pid: number;\n\treadonly exited: Promise<DaemonExit>;\n};\n\ntype DaemonExit =\n\t| { readonly kind: \"error\"; readonly error: Error }\n\t| { readonly kind: \"exit\"; readonly code: number | null; readonly signal: NodeJS.Signals | null };\n\ntype DaemonReadiness =\n\t| { readonly kind: \"ready\"; readonly version: string }\n\t| { readonly kind: \"timed-out\" }\n\t| { readonly kind: \"exited\"; readonly exit: DaemonExit };\n\nconst lockOptions = { retries: { retries: 100, minTimeout: 20, maxTimeout: 100 } } as const;\n\nexport function createDaemonPaths(agentDir = getAgentDir()): DaemonPaths {\n\tconst dir = join(agentDir, \"app-server-daemon\");\n\treturn {\n\t\tdir,\n\t\tpidFile: join(dir, \"app-server.pid\"),\n\t\tlockFile: join(dir, \"daemon.lock\"),\n\t\tsettingsFile: join(dir, \"settings.json\"),\n\t\tstderrLog: join(dir, \"stderr.log\"),\n\t\ttokenFile: join(agentDir, \"app-server\", \"ws-token\"),\n\t};\n}\n\nexport async function withDaemonStateLock<T>(paths: DaemonPaths, task: () => Promise<T>): Promise<T> {\n\tawait mkdir(paths.dir, { recursive: true });\n\tconst release = await acquireOwnershipSafeLock(paths.lockFile, lockOptions);\n\ttry {\n\t\treturn await task();\n\t} finally {\n\t\tawait release();\n\t}\n}\n\nexport async function runAppServerDaemonCommand(options: AppServerDaemonCommandOptions): Promise<void> {\n\tconst paths = createDaemonPaths();\n\tconst output = await withDaemonStateLock(paths, async () => {\n\t\ttry {\n\t\t\treturn await runLockedDaemonCommand(options, paths);\n\t\t} catch (error: unknown) {\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn { status: \"error\", message: error instanceof Error ? error.message : String(error) };\n\t\t}\n\t});\n\tprocess.stdout.write(`${JSON.stringify(output)}\\n`);\n}\n\nasync function runLockedDaemonCommand(\n\toptions: AppServerDaemonCommandOptions,\n\tpaths: DaemonPaths,\n): Promise<DaemonOutput> {\n\tconst settings = await readSettings(paths);\n\tconst listen = options.verb === \"start\" ? options.listen : (settings?.listen ?? options.listen);\n\tswitch (options.verb) {\n\t\tcase \"start\":\n\t\t\treturn startDaemon(paths, listen);\n\t\tcase \"stop\":\n\t\t\treturn stopDaemon(paths, listen);\n\t\tcase \"status\":\n\t\t\treturn statusDaemon(paths, listen);\n\t\tcase \"restart\": {\n\t\t\tconst restartListen = settings?.listen ?? options.listen;\n\t\t\tawait stopDaemon(paths, restartListen);\n\t\t\treturn startDaemon(paths, restartListen);\n\t\t}\n\t}\n}\n\nasync function startDaemon(paths: DaemonPaths, listen: AppServerListen): Promise<DaemonOutput> {\n\tconst occupancy = await inspectAppServerListenOccupancy(paths, listen);\n\tif (occupancy.kind === \"app-server\") {\n\t\tconst pidFile = await readPidFile(paths);\n\t\tconst pid = pidFile && (await processMatchesPidFile(pidFile)) ? pidFile.pid : undefined;\n\t\tif (pid !== undefined) return runningOutput(\"already-running\", pid, listen, occupancy.version);\n\t\treturn { status: \"already-running\", listen: listen.url, version: occupancy.version };\n\t}\n\tconst pidFile = await readPidFile(paths);\n\tif (pidFile && (await processMatchesPidFile(pidFile))) {\n\t\tconst lateProbe = await pollProbe(paths, listen, 10_000);\n\t\tif (lateProbe) return runningOutput(\"already-running\", pidFile.pid, listen, lateProbe);\n\t\tthrow new Error(`managed daemon pid ${pidFile.pid} did not answer initialize`);\n\t}\n\tconst spawned = await spawnDaemon(paths, listen);\n\tconst readiness = await waitForDaemonReady(paths, listen, spawned.exited);\n\tif (readiness.kind === \"ready\") {\n\t\treturn { status: \"started\", pid: spawned.pid, listen: listen.url };\n\t}\n\tawait stopValidatedPid(\n\t\t{ pid: spawned.pid, processStartTime: (await readProcessStartTime(spawned.pid)) ?? \"\" },\n\t\t\"SIGTERM\",\n\t);\n\tconst message =\n\t\treadiness.kind === \"exited\"\n\t\t\t? `spawned daemon ${describeDaemonExit(readiness.exit)} before answering initialize`\n\t\t\t: \"spawned daemon did not answer initialize within 10s\";\n\tconst diagnostic = await appendDaemonStderr(paths, message);\n\tawait cleanupState(paths, listen);\n\tthrow new Error(diagnostic);\n}\n\nasync function stopDaemon(paths: DaemonPaths, listen: AppServerListen): Promise<DaemonOutput> {\n\tconst pidFile = await readPidFile(paths);\n\tif (!pidFile) {\n\t\tif (!(await probeListen(paths, listen, 2_000))) await cleanupState(paths, listen);\n\t\treturn { status: \"not-running\" };\n\t}\n\tif (!(await processMatchesPidFile(pidFile))) {\n\t\tawait cleanupState(paths, listen);\n\t\treturn { status: \"not-running\" };\n\t}\n\tawait stopValidatedPid(pidFile, \"SIGTERM\");\n\tif (await processMatchesPidFile(pidFile)) {\n\t\tawait stopValidatedPid(pidFile, \"SIGKILL\");\n\t}\n\tawait waitForGone(pidFile, 10_000);\n\tawait cleanupState(paths, listen);\n\treturn { status: \"stopped\" };\n}\n\nasync function statusDaemon(paths: DaemonPaths, listen: AppServerListen): Promise<DaemonOutput> {\n\tconst probe = await probeListen(paths, listen, 2_000);\n\tconst pidFile = await readPidFile(paths);\n\tconst pidMatches = pidFile ? await processMatchesPidFile(pidFile) : false;\n\tif (probe && pidFile && pidMatches) return runningOutput(\"running\", pidFile.pid, listen, probe);\n\tif (probe) return runningUnmanagedOutput(listen, probe);\n\tif (pidFile && !pidMatches) await cleanupState(paths, listen);\n\treturn { status: \"not-running\" };\n}\n\nasync function spawnDaemon(paths: DaemonPaths, listen: AppServerListen): Promise<SpawnedDaemon> {\n\tconst stderr = await open(paths.stderrLog, \"w\");\n\ttry {\n\t\tconst daemonExec = process.versions.bun\n\t\t\t? process.env.npm_node_execpath && !/[/\\\\]bun(?:$|[/\\\\])/.test(process.env.npm_node_execpath)\n\t\t\t\t? process.env.npm_node_execpath\n\t\t\t\t: \"/opt/homebrew/bin/node\"\n\t\t\t: process.execPath;\n\t\tconst child = spawn(\n\t\t\tdaemonExec,\n\t\t\t[\n\t\t\t\t...(process.versions.bun ? [] : process.execArgv),\n\t\t\t\tresolveCliMainPath(),\n\t\t\t\t\"app-server\",\n\t\t\t\t\"--listen\",\n\t\t\t\tlisten.url,\n\t\t\t],\n\t\t\t{\n\t\t\t\tdetached: true,\n\t\t\t\twindowsHide: true,\n\t\t\t\tenv: { ...process.env, SENPI_RUNTIME: \"node\" },\n\t\t\t\tstdio: [\"ignore\", \"ignore\", stderr.fd],\n\t\t\t},\n\t\t);\n\t\tconst exited = observeDaemonExit(child);\n\t\tconst pid = child.pid;\n\t\tif (pid === undefined) throw new Error(\"failed to spawn daemon process\");\n\t\tlet startTime: string;\n\t\ttry {\n\t\t\tconst observed = await Promise.race([\n\t\t\t\twaitForStartTime(pid, 10_000),\n\t\t\t\texited.then(() => {\n\t\t\t\t\tthrow new Error(`spawned daemon ${pid} exited before its start time could be read`);\n\t\t\t\t}),\n\t\t\t]);\n\t\t\t// UNKNOWN identity on a live daemon means the probe was starved, not that startup failed.\n\t\t\t// The per-attempt win32 probe budget is 1s, which a loaded runner exceeds every time, so\n\t\t\t// take one unhurried read before treating an unreadable identity as a startup error.\n\t\t\tconst resolved =\n\t\t\t\tobserved ?? (await readProcessStartTime(pid, process.platform, 15_000).catch(() => undefined));\n\t\t\tif (resolved === undefined) {\n\t\t\t\tthrow new Error(`spawned daemon ${pid} started but its process identity stayed unreadable`);\n\t\t\t}\n\t\t\tstartTime = resolved;\n\t\t} catch (error: unknown) {\n\t\t\t// Keep the handle owned until registration succeeds. This terminates the\n\t\t\t// exact child even when start-time acquisition fails, without a raw PID.\n\t\t\tif (child.exitCode === null && child.signalCode === null) {\n\t\t\t\ttry {\n\t\t\t\t\tchild.kill(\"SIGTERM\");\n\t\t\t\t} catch {}\n\t\t\t\tawait Promise.race([exited, delay(2_000)]);\n\t\t\t\tif (child.exitCode === null && child.signalCode === null) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tchild.kill(\"SIGKILL\");\n\t\t\t\t\t} catch {}\n\t\t\t\t}\n\t\t\t}\n\t\t\tawait cleanupState(paths, listen);\n\t\t\tthrow error;\n\t\t}\n\t\ttry {\n\t\t\tawait writeFile(paths.pidFile, `${JSON.stringify({ pid, processStartTime: startTime })}\\n`, { mode: 0o600 });\n\t\t\tawait writeFile(paths.settingsFile, `${JSON.stringify({ listen })}\\n`, { mode: 0o600 });\n\t\t} catch (error: unknown) {\n\t\t\t// Registration is the ownership hand-off point. Until both files exist,\n\t\t\t// retain the exact ChildProcess handle and terminate it on any write\n\t\t\t// failure so a partial registration can never leave an unmanaged daemon.\n\t\t\tif (child.exitCode === null && child.signalCode === null) {\n\t\t\t\ttry {\n\t\t\t\t\tchild.kill(\"SIGTERM\");\n\t\t\t\t} catch {}\n\t\t\t\tawait Promise.race([exited, delay(2_000)]);\n\t\t\t\tif (child.exitCode === null && child.signalCode === null) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tchild.kill(\"SIGKILL\");\n\t\t\t\t\t} catch (killError: unknown) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`failed to terminate daemon after registration failure: ${killError instanceof Error ? killError.message : String(killError)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (!(await Promise.race([exited.then(() => true), delay(2_000).then(() => false)]))) {\n\t\t\t\t\t\tthrow new Error(`daemon ${pid} remained alive after SIGKILL during registration failure`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tawait cleanupState(paths, { ...listen, ...(listen.kind === \"unix\" ? { path: undefined } : {}) });\n\t\t\tthrow error;\n\t\t}\n\t\tchild.unref();\n\t\treturn { pid, exited };\n\t} finally {\n\t\tawait stderr.close();\n\t}\n}\n\nasync function waitForDaemonReady(\n\tpaths: DaemonPaths,\n\tlisten: AppServerListen,\n\texited: Promise<DaemonExit>,\n): Promise<DaemonReadiness> {\n\tconst controller = new AbortController();\n\ttry {\n\t\tconst probe = pollProbe(paths, listen, 10_000, controller.signal).then(\n\t\t\t(version): DaemonReadiness => (version ? { kind: \"ready\", version } : { kind: \"timed-out\" }),\n\t\t);\n\t\tconst childExit = exited.then((exit): DaemonReadiness => ({ kind: \"exited\", exit }));\n\t\treturn await Promise.race([probe, childExit]);\n\t} finally {\n\t\tcontroller.abort();\n\t}\n}\n\nfunction delay(ms: number): Promise<void> {\n\treturn new Promise((resolveDelay) => setTimeout(resolveDelay, ms));\n}\n\nfunction observeDaemonExit(child: ChildProcess): Promise<DaemonExit> {\n\treturn new Promise((resolveExit) => {\n\t\tchild.once(\"error\", (error) => resolveExit({ kind: \"error\", error }));\n\t\tchild.once(\"exit\", (code, signal) => resolveExit({ kind: \"exit\", code, signal }));\n\t});\n}\n\nfunction describeDaemonExit(exit: DaemonExit): string {\n\tif (exit.kind === \"error\") return `failed to launch (${exit.error.message})`;\n\tif (exit.signal) return `was terminated by ${exit.signal}`;\n\treturn `exited with code ${exit.code ?? \"unknown\"}`;\n}\n\nasync function appendDaemonStderr(paths: DaemonPaths, message: string): Promise<string> {\n\ttry {\n\t\tconst stderr = (await readFile(paths.stderrLog, \"utf8\")).trim();\n\t\treturn stderr ? `${message}\\n${stderr}` : message;\n\t} catch (error: unknown) {\n\t\tif (isNodeErrorCode(error, \"ENOENT\")) return message;\n\t\tthrow error;\n\t}\n}\n\nasync function readPidFile(paths: DaemonPaths): Promise<DaemonPidFile | undefined> {\n\ttry {\n\t\treturn parseDaemonPidFile(await readFile(paths.pidFile, \"utf8\"));\n\t} catch (error: unknown) {\n\t\tif (isNodeErrorCode(error, \"ENOENT\")) return undefined;\n\t\tthrow error;\n\t}\n}\n\nfunction resolveCliMainPath(): string {\n\tconst modulePath = fileURLToPath(import.meta.url);\n\tconst extension = modulePath.endsWith(\".ts\") ? \".ts\" : \".js\";\n\treturn resolve(dirname(modulePath), \"..\", \"..\", `cli-main${extension}`);\n}\n\nfunction isNodeErrorCode(error: unknown, code: string): boolean {\n\treturn error instanceof Error && \"code\" in error && error.code === code;\n}\n"]}
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../../src/modes/app-server/daemon.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir, readFile } from \"node:fs/promises\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { getAgentDir } from \"../../config.ts\";\nimport { acquireOwnershipSafeLock } from \"../rpc/ownership-safe-lock.ts\";\nimport { inspectAppServerListenOccupancy } from \"./daemon/occupancy.ts\";\nimport {\n\tcleanupState,\n\tpollProbe,\n\tprobeListen,\n\treadSettings,\n\trunningOutput,\n\trunningUnmanagedOutput,\n} from \"./daemon/probe.ts\";\nimport {\n\ttype DaemonPidFile,\n\tparseDaemonPidFile,\n\tprocessMatchesPidFile,\n\treadProcessStartTime,\n\tstopValidatedPid,\n\twaitForGone,\n} from \"./daemon/process.ts\";\nimport { type DaemonExit, type DaemonLaunchIntent, spawnDaemon } from \"./daemon/spawn.ts\";\nimport { resolveAppServerExtensionPaths } from \"./extension-paths.ts\";\nimport type { AppServerDaemonCommandOptions, AppServerListen } from \"./index.ts\";\n\nexport interface DaemonPaths {\n\treadonly dir: string;\n\treadonly pidFile: string;\n\treadonly lockFile: string;\n\treadonly settingsFile: string;\n\treadonly stderrLog: string;\n\treadonly tokenFile: string;\n}\n\ntype DaemonOutput = Readonly<Record<string, string | number | undefined>>;\n\ntype DaemonReadiness =\n\t| { readonly kind: \"ready\"; readonly version: string }\n\t| { readonly kind: \"timed-out\" }\n\t| { readonly kind: \"exited\"; readonly exit: DaemonExit };\n\nconst lockOptions = { retries: { retries: 100, minTimeout: 20, maxTimeout: 100 } } as const;\n\nexport function createDaemonPaths(agentDir = getAgentDir()): DaemonPaths {\n\tconst dir = join(agentDir, \"app-server-daemon\");\n\treturn {\n\t\tdir,\n\t\tpidFile: join(dir, \"app-server.pid\"),\n\t\tlockFile: join(dir, \"daemon.lock\"),\n\t\tsettingsFile: join(dir, \"settings.json\"),\n\t\tstderrLog: join(dir, \"stderr.log\"),\n\t\ttokenFile: join(agentDir, \"app-server\", \"ws-token\"),\n\t};\n}\n\nexport async function withDaemonStateLock<T>(paths: DaemonPaths, task: () => Promise<T>): Promise<T> {\n\tawait mkdir(paths.dir, { recursive: true });\n\tconst release = await acquireOwnershipSafeLock(paths.lockFile, lockOptions);\n\ttry {\n\t\treturn await task();\n\t} finally {\n\t\tawait release();\n\t}\n}\n\nexport async function runAppServerDaemonCommand(options: AppServerDaemonCommandOptions): Promise<void> {\n\tconst paths = createDaemonPaths();\n\tconst output = await withDaemonStateLock(paths, async () => {\n\t\ttry {\n\t\t\treturn await runLockedDaemonCommand(options, paths);\n\t\t} catch (error: unknown) {\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn { status: \"error\", message: error instanceof Error ? error.message : String(error) };\n\t\t}\n\t});\n\tprocess.stdout.write(`${JSON.stringify(output)}\\n`);\n}\n\nasync function runLockedDaemonCommand(\n\toptions: AppServerDaemonCommandOptions,\n\tpaths: DaemonPaths,\n): Promise<DaemonOutput> {\n\tconst settings = await readSettings(paths);\n\tconst listen = options.verb === \"start\" ? options.listen : (settings?.listen ?? options.listen);\n\tconst extensions = resolveAppServerExtensionPaths(options.extensions);\n\tswitch (options.verb) {\n\t\tcase \"start\":\n\t\t\treturn startDaemon(paths, { listen, extensions });\n\t\tcase \"stop\":\n\t\t\treturn stopDaemon(paths, listen);\n\t\tcase \"status\":\n\t\t\treturn statusDaemon(paths, listen);\n\t\tcase \"restart\": {\n\t\t\t// Like the listener, a restart relaunches what was recorded; explicit extensions replace it.\n\t\t\tconst restartListen = settings?.listen ?? options.listen;\n\t\t\tawait stopDaemon(paths, restartListen);\n\t\t\treturn startDaemon(paths, {\n\t\t\t\tlisten: restartListen,\n\t\t\t\textensions: extensions.length > 0 ? extensions : (settings?.extensions ?? []),\n\t\t\t});\n\t\t}\n\t}\n}\n\nasync function startDaemon(paths: DaemonPaths, intent: DaemonLaunchIntent): Promise<DaemonOutput> {\n\tconst { listen } = intent;\n\tconst occupancy = await inspectAppServerListenOccupancy(paths, listen);\n\tif (occupancy.kind === \"app-server\") {\n\t\tconst pidFile = await readPidFile(paths);\n\t\tconst pid = pidFile && (await processMatchesPidFile(pidFile)) ? pidFile.pid : undefined;\n\t\tif (pid !== undefined) return runningOutput(\"already-running\", pid, listen, occupancy.version);\n\t\treturn { status: \"already-running\", listen: listen.url, version: occupancy.version };\n\t}\n\tconst pidFile = await readPidFile(paths);\n\tif (pidFile && (await processMatchesPidFile(pidFile))) {\n\t\tconst lateProbe = await pollProbe(paths, listen, 10_000);\n\t\tif (lateProbe) return runningOutput(\"already-running\", pidFile.pid, listen, lateProbe);\n\t\tthrow new Error(`managed daemon pid ${pidFile.pid} did not answer initialize`);\n\t}\n\tconst spawned = await spawnDaemon(paths, intent, resolveCliMainPath());\n\tconst readiness = await waitForDaemonReady(paths, listen, spawned.exited);\n\tif (readiness.kind === \"ready\") {\n\t\treturn { status: \"started\", pid: spawned.pid, listen: listen.url };\n\t}\n\tawait stopValidatedPid(\n\t\t{ pid: spawned.pid, processStartTime: (await readProcessStartTime(spawned.pid)) ?? \"\" },\n\t\t\"SIGTERM\",\n\t);\n\tconst message =\n\t\treadiness.kind === \"exited\"\n\t\t\t? `spawned daemon ${describeDaemonExit(readiness.exit)} before answering initialize`\n\t\t\t: \"spawned daemon did not answer initialize within 10s\";\n\tconst diagnostic = await appendDaemonStderr(paths, message);\n\tawait cleanupState(paths, listen);\n\tthrow new Error(diagnostic);\n}\n\nasync function stopDaemon(paths: DaemonPaths, listen: AppServerListen): Promise<DaemonOutput> {\n\tconst pidFile = await readPidFile(paths);\n\tif (!pidFile) {\n\t\tif (!(await probeListen(paths, listen, 2_000))) await cleanupState(paths, listen);\n\t\treturn { status: \"not-running\" };\n\t}\n\tif (!(await processMatchesPidFile(pidFile))) {\n\t\tawait cleanupState(paths, listen);\n\t\treturn { status: \"not-running\" };\n\t}\n\tawait stopValidatedPid(pidFile, \"SIGTERM\");\n\tif (await processMatchesPidFile(pidFile)) {\n\t\tawait stopValidatedPid(pidFile, \"SIGKILL\");\n\t}\n\tawait waitForGone(pidFile, 10_000);\n\tawait cleanupState(paths, listen);\n\treturn { status: \"stopped\" };\n}\n\nasync function statusDaemon(paths: DaemonPaths, listen: AppServerListen): Promise<DaemonOutput> {\n\tconst probe = await probeListen(paths, listen, 2_000);\n\tconst pidFile = await readPidFile(paths);\n\tconst pidMatches = pidFile ? await processMatchesPidFile(pidFile) : false;\n\tif (probe && pidFile && pidMatches) return runningOutput(\"running\", pidFile.pid, listen, probe);\n\tif (probe) return runningUnmanagedOutput(listen, probe);\n\tif (pidFile && !pidMatches) await cleanupState(paths, listen);\n\treturn { status: \"not-running\" };\n}\n\nasync function waitForDaemonReady(\n\tpaths: DaemonPaths,\n\tlisten: AppServerListen,\n\texited: Promise<DaemonExit>,\n): Promise<DaemonReadiness> {\n\tconst controller = new AbortController();\n\ttry {\n\t\tconst probe = pollProbe(paths, listen, 10_000, controller.signal).then(\n\t\t\t(version): DaemonReadiness => (version ? { kind: \"ready\", version } : { kind: \"timed-out\" }),\n\t\t);\n\t\tconst childExit = exited.then((exit): DaemonReadiness => ({ kind: \"exited\", exit }));\n\t\treturn await Promise.race([probe, childExit]);\n\t} finally {\n\t\tcontroller.abort();\n\t}\n}\n\nfunction describeDaemonExit(exit: DaemonExit): string {\n\tif (exit.kind === \"error\") return `failed to launch (${exit.error.message})`;\n\tif (exit.signal) return `was terminated by ${exit.signal}`;\n\treturn `exited with code ${exit.code ?? \"unknown\"}`;\n}\n\nasync function appendDaemonStderr(paths: DaemonPaths, message: string): Promise<string> {\n\ttry {\n\t\tconst stderr = (await readFile(paths.stderrLog, \"utf8\")).trim();\n\t\treturn stderr ? `${message}\\n${stderr}` : message;\n\t} catch (error: unknown) {\n\t\tif (isNodeErrorCode(error, \"ENOENT\")) return message;\n\t\tthrow error;\n\t}\n}\n\nasync function readPidFile(paths: DaemonPaths): Promise<DaemonPidFile | undefined> {\n\ttry {\n\t\treturn parseDaemonPidFile(await readFile(paths.pidFile, \"utf8\"));\n\t} catch (error: unknown) {\n\t\tif (isNodeErrorCode(error, \"ENOENT\")) return undefined;\n\t\tthrow error;\n\t}\n}\n\nfunction resolveCliMainPath(): string {\n\tconst modulePath = fileURLToPath(import.meta.url);\n\tconst extension = modulePath.endsWith(\".ts\") ? \".ts\" : \".js\";\n\treturn resolve(dirname(modulePath), \"..\", \"..\", `cli-main${extension}`);\n}\n\nfunction isNodeErrorCode(error: unknown, code: string): boolean {\n\treturn error instanceof Error && \"code\" in error && error.code === code;\n}\n"]}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Local `--extension` paths are resolved against the invoking cwd, the same rule the global flag
3
+ * follows, so a daemon child or a later thread cwd never reinterprets them. Package sources such
4
+ * as `npm:` or git URLs pass through for the package manager to resolve.
5
+ */
6
+ export declare function resolveAppServerExtensionPaths(extensions: readonly string[], cwd?: string): string[];
7
+ //# sourceMappingURL=extension-paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-paths.d.ts","sourceRoot":"","sources":["../../../src/modes/app-server/extension-paths.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,SAAgB,GAAG,MAAM,EAAE,CAE3G"}
@@ -0,0 +1,10 @@
1
+ import { isLocalPath, resolvePath } from "../../utils/paths.js";
2
+ /**
3
+ * Local `--extension` paths are resolved against the invoking cwd, the same rule the global flag
4
+ * follows, so a daemon child or a later thread cwd never reinterprets them. Package sources such
5
+ * as `npm:` or git URLs pass through for the package manager to resolve.
6
+ */
7
+ export function resolveAppServerExtensionPaths(extensions, cwd = process.cwd()) {
8
+ return extensions.map((value) => (isLocalPath(value) ? resolvePath(value, cwd) : value));
9
+ }
10
+ //# sourceMappingURL=extension-paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-paths.js","sourceRoot":"","sources":["../../../src/modes/app-server/extension-paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEhE;;;;GAIG;AACH,MAAM,UAAU,8BAA8B,CAAC,UAA6B,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAChG,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AAC1F,CAAC","sourcesContent":["import { isLocalPath, resolvePath } from \"../../utils/paths.ts\";\n\n/**\n * Local `--extension` paths are resolved against the invoking cwd, the same rule the global flag\n * follows, so a daemon child or a later thread cwd never reinterprets them. Package sources such\n * as `npm:` or git URLs pass through for the package manager to resolve.\n */\nexport function resolveAppServerExtensionPaths(extensions: readonly string[], cwd = process.cwd()): string[] {\n\treturn extensions.map((value) => (isLocalPath(value) ? resolvePath(value, cwd) : value));\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modes/app-server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,KAAK,6BAA6B,EAClC,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,MAAM,eAAe,CAAC;AAUvB,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EACN,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,KAAK,6BAA6B,EAClC,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,oBAAoB,EACpB,qBAAqB,GACrB,CAAC;AAEF,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuEnF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modes/app-server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,KAAK,6BAA6B,EAClC,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,MAAM,eAAe,CAAC;AAWvB,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EACN,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,KAAK,6BAA6B,EAClC,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,oBAAoB,EACpB,qBAAqB,GACrB,CAAC;AAEF,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyEnF"}
@@ -1,4 +1,5 @@
1
1
  import { APP_SERVER_LISTEN_USAGE, formatAppServerUsage, parseAppServerCliArgs, } from "./cli-args.js";
2
+ import { resolveAppServerExtensionPaths } from "./extension-paths.js";
2
3
  import { createAppServerRuntime } from "./runtime.js";
3
4
  import { startStdioTransport } from "./transports/stdio.js";
4
5
  import { startAppServerUnixSocketListener } from "./transports/unix-socket.js";
@@ -29,7 +30,9 @@ export async function runAppServerMode(options) {
29
30
  };
30
31
  process.on("SIGINT", handleSignal);
31
32
  process.on("SIGTERM", handleSignal);
32
- const runtime = createAppServerRuntime(requestShutdown);
33
+ const runtime = createAppServerRuntime(requestShutdown, {
34
+ extensionPaths: resolveAppServerExtensionPaths(options.extensions),
35
+ });
33
36
  let stdio;
34
37
  let unix;
35
38
  let websocket;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modes/app-server/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tAPP_SERVER_LISTEN_USAGE,\n\ttype AppServerCliArgs,\n\ttype AppServerDaemonCommandOptions,\n\ttype AppServerDaemonVerb,\n\ttype AppServerListen,\n\ttype AppServerModeOptions,\n\ttype AppServerUsageError,\n\ttype AppServerWsAuth,\n\tformatAppServerUsage,\n\tparseAppServerCliArgs,\n} from \"./cli-args.ts\";\nimport { type AppServerRuntime, createAppServerRuntime } from \"./runtime.ts\";\nimport { type StdioTransport, startStdioTransport } from \"./transports/stdio.ts\";\nimport { startAppServerUnixSocketListener, type UnixSocketListenerHandle } from \"./transports/unix-socket.ts\";\nimport {\n\tstartAppServerWebSocketListener,\n\ttype WebSocketListenerAuth,\n\ttype WebSocketListenerHandle,\n} from \"./transports/websocket.ts\";\n\nexport { runAppServerDaemonCommand } from \"./daemon.ts\";\nexport { createAppServerRuntime } from \"./runtime.ts\";\nexport {\n\tAPP_SERVER_LISTEN_USAGE,\n\ttype AppServerCliArgs,\n\ttype AppServerDaemonCommandOptions,\n\ttype AppServerDaemonVerb,\n\ttype AppServerListen,\n\ttype AppServerModeOptions,\n\ttype AppServerUsageError,\n\ttype AppServerWsAuth,\n\tformatAppServerUsage,\n\tparseAppServerCliArgs,\n};\n\nexport async function runAppServerMode(options: AppServerModeOptions): Promise<void> {\n\tlet shutdownRequested = false;\n\tlet forceExit = false;\n\tlet resolveShutdown: (reason: string) => void = () => {};\n\tconst shutdownSignal = new Promise<string>((resolve) => {\n\t\tresolveShutdown = resolve;\n\t});\n\n\tconst requestShutdown = (reason: string): void => {\n\t\tif (shutdownRequested) {\n\t\t\tif (!forceExit) {\n\t\t\t\tforceExit = true;\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tshutdownRequested = true;\n\t\tresolveShutdown(reason);\n\t};\n\n\tconst handleSignal = (signal: NodeJS.Signals): void => {\n\t\trequestShutdown(signal);\n\t};\n\n\tprocess.on(\"SIGINT\", handleSignal);\n\tprocess.on(\"SIGTERM\", handleSignal);\n\n\tconst runtime = createAppServerRuntime(requestShutdown);\n\tlet stdio: StdioTransport | undefined;\n\tlet unix: UnixSocketListenerHandle | undefined;\n\tlet websocket: WebSocketListenerHandle | undefined;\n\ttry {\n\t\tif (options.listen.kind === \"stdio\") {\n\t\t\tstdio = startStdioTransport({\n\t\t\t\tcore: runtime.core,\n\t\t\t\tonShutdown: requestShutdown,\n\t\t\t});\n\t\t\tprocess.stderr.write(\"senpi app-server listening on stdio://\\n\");\n\t\t} else if (options.listen.kind === \"ws\") {\n\t\t\twebsocket = await startAppServerWebSocketListener({\n\t\t\t\tcore: runtime.core,\n\t\t\t\thost: options.listen.host,\n\t\t\t\tport: options.listen.port,\n\t\t\t\tauth: toWebSocketAuth(options.wsAuth),\n\t\t\t});\n\t\t\tprocess.stderr.write(`senpi app-server listening on ws://${websocket.host}:${websocket.port}\\n`);\n\t\t\tprocess.stderr.write(`readyz http://127.0.0.1:${websocket.port}/readyz\\n`);\n\t\t\tif (websocket.tokenFile) {\n\t\t\t\tprocess.stderr.write(`token ${websocket.tokenFile}\\n`);\n\t\t\t}\n\t\t} else {\n\t\t\tunix = await startAppServerUnixSocketListener({\n\t\t\t\tcore: runtime.core,\n\t\t\t\tsocketPath: options.listen.path,\n\t\t\t\tauth: toWebSocketAuth(options.wsAuth),\n\t\t\t});\n\t\t\tprocess.stderr.write(`senpi app-server listening on unix://${unix.socketPath}\\n`);\n\t\t\tif (unix.tokenFile) {\n\t\t\t\tprocess.stderr.write(`token ${unix.tokenFile}\\n`);\n\t\t\t}\n\t\t}\n\n\t\tconst reason = await shutdownSignal;\n\t\tawait withShutdownDeadline(interruptActiveTurns(runtime), 5_000);\n\t\tawait withShutdownDeadline(shutdownTransports({ stdio, unix, websocket, reason }), 5_000);\n\t\tprocess.exitCode = 0;\n\t} finally {\n\t\truntime.dispose();\n\t\tprocess.off(\"SIGINT\", handleSignal);\n\t\tprocess.off(\"SIGTERM\", handleSignal);\n\t}\n}\n\nfunction toWebSocketAuth(auth: AppServerWsAuth | undefined): WebSocketListenerAuth | undefined {\n\tif (!auth) {\n\t\treturn undefined;\n\t}\n\tif (auth.kind === \"off\") {\n\t\treturn { kind: \"off\" };\n\t}\n\treturn { kind: \"token-file\", path: auth.path };\n}\n\nasync function shutdownTransports(options: {\n\treadonly stdio: StdioTransport | undefined;\n\treadonly unix: UnixSocketListenerHandle | undefined;\n\treadonly websocket: WebSocketListenerHandle | undefined;\n\treadonly reason: string;\n}): Promise<void> {\n\tawait options.stdio?.drain();\n\tawait options.stdio?.close(options.reason);\n\tawait options.unix?.close();\n\tawait options.websocket?.close();\n}\n\nasync function interruptActiveTurns(runtime: AppServerRuntime): Promise<void> {\n\tconst interrupts = runtime.threads.listLoaded().map(async (thread) => {\n\t\tconst entry = runtime.threads.getLoadedThread(thread.id);\n\t\tconst activeTurn = entry.activeTurn;\n\t\tif (!activeTurn) {\n\t\t\treturn;\n\t\t}\n\t\tawait runtime.turns.interruptTurn({ threadId: thread.id, turnId: activeTurn.turnId });\n\t});\n\tawait Promise.all(interrupts);\n}\n\nfunction withShutdownDeadline(task: Promise<void>, timeoutMs: number): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst timeout = setTimeout(() => {\n\t\t\treject(new Error(`app-server shutdown exceeded ${timeoutMs}ms`));\n\t\t}, timeoutMs);\n\t\ttask.then(\n\t\t\t() => {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t\tresolve();\n\t\t\t},\n\t\t\t(error: unknown) => {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t\treject(error);\n\t\t\t},\n\t\t);\n\t});\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modes/app-server/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tAPP_SERVER_LISTEN_USAGE,\n\ttype AppServerCliArgs,\n\ttype AppServerDaemonCommandOptions,\n\ttype AppServerDaemonVerb,\n\ttype AppServerListen,\n\ttype AppServerModeOptions,\n\ttype AppServerUsageError,\n\ttype AppServerWsAuth,\n\tformatAppServerUsage,\n\tparseAppServerCliArgs,\n} from \"./cli-args.ts\";\nimport { resolveAppServerExtensionPaths } from \"./extension-paths.ts\";\nimport { type AppServerRuntime, createAppServerRuntime } from \"./runtime.ts\";\nimport { type StdioTransport, startStdioTransport } from \"./transports/stdio.ts\";\nimport { startAppServerUnixSocketListener, type UnixSocketListenerHandle } from \"./transports/unix-socket.ts\";\nimport {\n\tstartAppServerWebSocketListener,\n\ttype WebSocketListenerAuth,\n\ttype WebSocketListenerHandle,\n} from \"./transports/websocket.ts\";\n\nexport { runAppServerDaemonCommand } from \"./daemon.ts\";\nexport { createAppServerRuntime } from \"./runtime.ts\";\nexport {\n\tAPP_SERVER_LISTEN_USAGE,\n\ttype AppServerCliArgs,\n\ttype AppServerDaemonCommandOptions,\n\ttype AppServerDaemonVerb,\n\ttype AppServerListen,\n\ttype AppServerModeOptions,\n\ttype AppServerUsageError,\n\ttype AppServerWsAuth,\n\tformatAppServerUsage,\n\tparseAppServerCliArgs,\n};\n\nexport async function runAppServerMode(options: AppServerModeOptions): Promise<void> {\n\tlet shutdownRequested = false;\n\tlet forceExit = false;\n\tlet resolveShutdown: (reason: string) => void = () => {};\n\tconst shutdownSignal = new Promise<string>((resolve) => {\n\t\tresolveShutdown = resolve;\n\t});\n\n\tconst requestShutdown = (reason: string): void => {\n\t\tif (shutdownRequested) {\n\t\t\tif (!forceExit) {\n\t\t\t\tforceExit = true;\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tshutdownRequested = true;\n\t\tresolveShutdown(reason);\n\t};\n\n\tconst handleSignal = (signal: NodeJS.Signals): void => {\n\t\trequestShutdown(signal);\n\t};\n\n\tprocess.on(\"SIGINT\", handleSignal);\n\tprocess.on(\"SIGTERM\", handleSignal);\n\n\tconst runtime = createAppServerRuntime(requestShutdown, {\n\t\textensionPaths: resolveAppServerExtensionPaths(options.extensions),\n\t});\n\tlet stdio: StdioTransport | undefined;\n\tlet unix: UnixSocketListenerHandle | undefined;\n\tlet websocket: WebSocketListenerHandle | undefined;\n\ttry {\n\t\tif (options.listen.kind === \"stdio\") {\n\t\t\tstdio = startStdioTransport({\n\t\t\t\tcore: runtime.core,\n\t\t\t\tonShutdown: requestShutdown,\n\t\t\t});\n\t\t\tprocess.stderr.write(\"senpi app-server listening on stdio://\\n\");\n\t\t} else if (options.listen.kind === \"ws\") {\n\t\t\twebsocket = await startAppServerWebSocketListener({\n\t\t\t\tcore: runtime.core,\n\t\t\t\thost: options.listen.host,\n\t\t\t\tport: options.listen.port,\n\t\t\t\tauth: toWebSocketAuth(options.wsAuth),\n\t\t\t});\n\t\t\tprocess.stderr.write(`senpi app-server listening on ws://${websocket.host}:${websocket.port}\\n`);\n\t\t\tprocess.stderr.write(`readyz http://127.0.0.1:${websocket.port}/readyz\\n`);\n\t\t\tif (websocket.tokenFile) {\n\t\t\t\tprocess.stderr.write(`token ${websocket.tokenFile}\\n`);\n\t\t\t}\n\t\t} else {\n\t\t\tunix = await startAppServerUnixSocketListener({\n\t\t\t\tcore: runtime.core,\n\t\t\t\tsocketPath: options.listen.path,\n\t\t\t\tauth: toWebSocketAuth(options.wsAuth),\n\t\t\t});\n\t\t\tprocess.stderr.write(`senpi app-server listening on unix://${unix.socketPath}\\n`);\n\t\t\tif (unix.tokenFile) {\n\t\t\t\tprocess.stderr.write(`token ${unix.tokenFile}\\n`);\n\t\t\t}\n\t\t}\n\n\t\tconst reason = await shutdownSignal;\n\t\tawait withShutdownDeadline(interruptActiveTurns(runtime), 5_000);\n\t\tawait withShutdownDeadline(shutdownTransports({ stdio, unix, websocket, reason }), 5_000);\n\t\tprocess.exitCode = 0;\n\t} finally {\n\t\truntime.dispose();\n\t\tprocess.off(\"SIGINT\", handleSignal);\n\t\tprocess.off(\"SIGTERM\", handleSignal);\n\t}\n}\n\nfunction toWebSocketAuth(auth: AppServerWsAuth | undefined): WebSocketListenerAuth | undefined {\n\tif (!auth) {\n\t\treturn undefined;\n\t}\n\tif (auth.kind === \"off\") {\n\t\treturn { kind: \"off\" };\n\t}\n\treturn { kind: \"token-file\", path: auth.path };\n}\n\nasync function shutdownTransports(options: {\n\treadonly stdio: StdioTransport | undefined;\n\treadonly unix: UnixSocketListenerHandle | undefined;\n\treadonly websocket: WebSocketListenerHandle | undefined;\n\treadonly reason: string;\n}): Promise<void> {\n\tawait options.stdio?.drain();\n\tawait options.stdio?.close(options.reason);\n\tawait options.unix?.close();\n\tawait options.websocket?.close();\n}\n\nasync function interruptActiveTurns(runtime: AppServerRuntime): Promise<void> {\n\tconst interrupts = runtime.threads.listLoaded().map(async (thread) => {\n\t\tconst entry = runtime.threads.getLoadedThread(thread.id);\n\t\tconst activeTurn = entry.activeTurn;\n\t\tif (!activeTurn) {\n\t\t\treturn;\n\t\t}\n\t\tawait runtime.turns.interruptTurn({ threadId: thread.id, turnId: activeTurn.turnId });\n\t});\n\tawait Promise.all(interrupts);\n}\n\nfunction withShutdownDeadline(task: Promise<void>, timeoutMs: number): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst timeout = setTimeout(() => {\n\t\t\treject(new Error(`app-server shutdown exceeded ${timeoutMs}ms`));\n\t\t}, timeoutMs);\n\t\ttask.then(\n\t\t\t() => {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t\tresolve();\n\t\t\t},\n\t\t\t(error: unknown) => {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t\treject(error);\n\t\t\t},\n\t\t);\n\t});\n}\n"]}
@@ -9,5 +9,9 @@ export type AppServerRuntime = {
9
9
  readonly turns: TurnEngineApi;
10
10
  readonly dispose: () => void;
11
11
  };
12
- export declare function createAppServerRuntime(requestShutdown: (reason: string) => void): AppServerRuntime;
12
+ export interface AppServerRuntimeOptions {
13
+ /** Resolved `--extension` sources, loaded into every thread session and every skills/list loader. */
14
+ readonly extensionPaths?: readonly string[];
15
+ }
16
+ export declare function createAppServerRuntime(requestShutdown: (reason: string) => void, runtimeOptions?: AppServerRuntimeOptions): AppServerRuntime;
13
17
  //# sourceMappingURL=runtime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/modes/app-server/runtime.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAM1D,OAAO,EAAoD,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACzG,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAU1E,MAAM,MAAM,gBAAgB,GAAG;IAC9B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC7B,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,gBAAgB,CAsGlG"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/modes/app-server/runtime.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAM1D,OAAO,EAAoD,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACzG,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAU1E,MAAM,MAAM,gBAAgB,GAAG;IAC9B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC7B,CAAC;AAEF,MAAM,WAAW,uBAAuB;IACvC,qGAAqG;IACrG,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5C;AAED,wBAAgB,sBAAsB,CACrC,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,EACzC,cAAc,GAAE,uBAA4B,GAC1C,gBAAgB,CA8GlB"}
@@ -2,6 +2,7 @@ import { ENV_SESSION_DIR, getAgentDir } from "../../config.js";
2
2
  import { getMcpService } from "../../core/extensions/builtin/mcp/service.js";
3
3
  import { DefaultResourceLoader } from "../../core/resource-loader.js";
4
4
  import { createAgentSession } from "../../core/sdk.js";
5
+ import { SettingsManager } from "../../core/settings-manager.js";
5
6
  import { createRegistry, registerExtensionRequestMethod } from "./rpc/registry.js";
6
7
  import { registerFuzzyFileSearchMethods } from "./search/fuzzy-search-methods.js";
7
8
  import { FuzzyFileSearchService } from "./search/fuzzy-search-service.js";
@@ -16,7 +17,8 @@ import { ThreadNotFoundError, ThreadRegistry } from "./threads/registry.js";
16
17
  import { TurnLog } from "./threads/turn-log.js";
17
18
  import { createTurnEngine } from "./threads/turns.js";
18
19
  import { createModeTurnStore, createRoutedServerCore, registerLoadedThreadObjectListHandler, turnInterruptParams, turnStartParams, turnSteerParams, } from "./turn-adapter.js";
19
- export function createAppServerRuntime(requestShutdown) {
20
+ export function createAppServerRuntime(requestShutdown, runtimeOptions = {}) {
21
+ const additionalExtensionPaths = [...(runtimeOptions.extensionPaths ?? [])];
20
22
  const notifications = new NotificationRouter();
21
23
  const registry = createRegistry();
22
24
  const fuzzySearch = new FuzzyFileSearchService({
@@ -49,7 +51,7 @@ export function createAppServerRuntime(requestShutdown) {
49
51
  threads = new ThreadRegistry({
50
52
  agentDir: getAgentDir(),
51
53
  sessionDir: process.env[ENV_SESSION_DIR],
52
- createSession: (options) => createBoundAppServerSession(options, approvals, notifications, requestShutdown, userInput, (threadId) => {
54
+ createSession: async (options) => createBoundAppServerSession(await withExtensionPaths(options, additionalExtensionPaths), approvals, notifications, requestShutdown, userInput, (threadId) => {
53
55
  try {
54
56
  return threads.getLoadedThread(threadId).activeTurn?.turnId ?? "turn-user-input";
55
57
  }
@@ -74,7 +76,7 @@ export function createAppServerRuntime(requestShutdown) {
74
76
  serverCwd: process.cwd(),
75
77
  threads,
76
78
  resourceLoaderFactory: async (cwd) => {
77
- const loader = new DefaultResourceLoader({ cwd, agentDir: getAgentDir() });
79
+ const loader = new DefaultResourceLoader({ cwd, agentDir: getAgentDir(), additionalExtensionPaths });
78
80
  await loader.reload();
79
81
  return loader;
80
82
  },
@@ -113,6 +115,20 @@ export function createAppServerRuntime(requestShutdown) {
113
115
  },
114
116
  };
115
117
  }
118
+ /**
119
+ * A session's default resource loader only discovers settings and agent-dir extensions, so explicit
120
+ * paths need a loader of their own, built the way `createAgentSession` builds its default one.
121
+ */
122
+ async function withExtensionPaths(options, additionalExtensionPaths) {
123
+ if (additionalExtensionPaths.length === 0 || options.resourceLoader)
124
+ return options;
125
+ const cwd = options.cwd ?? options.sessionManager?.getCwd() ?? process.cwd();
126
+ const agentDir = options.agentDir ?? getAgentDir();
127
+ const settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);
128
+ const resourceLoader = new DefaultResourceLoader({ cwd, agentDir, settingsManager, additionalExtensionPaths });
129
+ await resourceLoader.reload();
130
+ return { ...options, settingsManager, resourceLoader };
131
+ }
116
132
  async function createBoundAppServerSession(options, approvals, notifications, requestShutdown, userInput, getTurnId) {
117
133
  const result = await createAgentSession(options);
118
134
  const threadId = result.session.sessionId;
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/modes/app-server/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { ENV_SESSION_DIR, getAgentDir } from \"../../config.ts\";\nimport { getMcpService } from \"../../core/extensions/builtin/mcp/service.ts\";\nimport { DefaultResourceLoader } from \"../../core/resource-loader.ts\";\nimport { type CreateAgentSessionOptions, createAgentSession } from \"../../core/sdk.ts\";\nimport type { RpcNotification } from \"./rpc/envelope.ts\";\nimport { createRegistry, type MethodRegistry, registerExtensionRequestMethod } from \"./rpc/registry.ts\";\nimport { registerFuzzyFileSearchMethods } from \"./search/fuzzy-search-methods.ts\";\nimport { FuzzyFileSearchService } from \"./search/fuzzy-search-service.ts\";\nimport { ApprovalBridge, createAppServerUIContext } from \"./server/approvals.ts\";\nimport { NotificationRouter, type RouterOutboundMessage } from \"./server/notifications.ts\";\nimport type { ServerCore } from \"./server/server-core.ts\";\nimport { registerAppServerSkillMethods } from \"./server/skills.ts\";\nimport { UserInputBridge } from \"./server/user-input-bridge.ts\";\nimport { connectionId } from \"./threads/handler-params.ts\";\nimport { registerThreadLifecycleHandlers, type ThreadLifecycleController } from \"./threads/handlers.ts\";\nimport { createMcpWireStatusAdapter, createProcessMcpWireStatusAdapter } from \"./threads/mcp-wire-status.ts\";\nimport { type AppServerSessionResult, ThreadNotFoundError, ThreadRegistry } from \"./threads/registry.ts\";\nimport { TurnLog } from \"./threads/turn-log.ts\";\nimport { createTurnEngine, type TurnEngineApi } from \"./threads/turns.ts\";\nimport {\n\tcreateModeTurnStore,\n\tcreateRoutedServerCore,\n\tregisterLoadedThreadObjectListHandler,\n\tturnInterruptParams,\n\tturnStartParams,\n\tturnSteerParams,\n} from \"./turn-adapter.ts\";\n\nexport type AppServerRuntime = {\n\treadonly core: ServerCore;\n\treadonly threads: ThreadRegistry;\n\treadonly turnLog: TurnLog;\n\treadonly turns: TurnEngineApi;\n\treadonly dispose: () => void;\n};\n\nexport function createAppServerRuntime(requestShutdown: (reason: string) => void): AppServerRuntime {\n\tconst notifications = new NotificationRouter();\n\tconst registry = createRegistry();\n\tconst fuzzySearch = new FuzzyFileSearchService({\n\t\tbroadcast: (notification) => notifications.broadcast(notification),\n\t});\n\tregisterFuzzyFileSearchMethods(registry, fuzzySearch);\n\tlet threads: ThreadRegistry;\n\tconst processMcpWireStatusAdapter = createProcessMcpWireStatusAdapter({\n\t\tagentDir: getAgentDir(),\n\t\tcwd: process.cwd(),\n\t\tenv: process.env,\n\t});\n\tconst sendToSubscribers = (threadId: string, message: RouterOutboundMessage): number => {\n\t\tlet subscriberCount = 0;\n\t\ttry {\n\t\t\tsubscriberCount = threads.getLoadedThread(threadId).subscribers.size;\n\t\t} catch (error: unknown) {\n\t\t\tif (error instanceof ThreadNotFoundError) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tnotifications.toThread(threadId, message);\n\t\treturn subscriberCount;\n\t};\n\tconst approvals = new ApprovalBridge(sendToSubscribers);\n\tconst userInput = new UserInputBridge(sendToSubscribers);\n\tlet lifecycle: ThreadLifecycleController | undefined;\n\tthreads = new ThreadRegistry({\n\t\tagentDir: getAgentDir(),\n\t\tsessionDir: process.env[ENV_SESSION_DIR],\n\t\tcreateSession: (options) =>\n\t\t\tcreateBoundAppServerSession(options, approvals, notifications, requestShutdown, userInput, (threadId) => {\n\t\t\t\ttry {\n\t\t\t\t\treturn threads.getLoadedThread(threadId).activeTurn?.turnId ?? \"turn-user-input\";\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (error instanceof ThreadNotFoundError) return \"turn-user-input\";\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}),\n\t\tmcpWireStatusAdapter: processMcpWireStatusAdapter,\n\t});\n\tregisterExtensionRequestMethod(registry, (threadId) => threads.getLoadedThread(threadId).session);\n\tconst core = createRoutedServerCore(\n\t\tregistry,\n\t\tnotifications,\n\t\tapprovals,\n\t\t(threadId) => {\n\t\t\tlifecycle?.scheduleIdleUnloadForThread(threadId);\n\t\t},\n\t\t{\n\t\t\tcodexHome: getAgentDir(),\n\t\t\tserverCwd: process.cwd(),\n\t\t\tthreads,\n\t\t},\n\t\tuserInput,\n\t);\n\tregisterAppServerSkillMethods(registry, {\n\t\tagentDir: getAgentDir(),\n\t\tserverCwd: process.cwd(),\n\t\tthreads,\n\t\tresourceLoaderFactory: async (cwd) => {\n\t\t\tconst loader = new DefaultResourceLoader({ cwd, agentDir: getAgentDir() });\n\t\t\tawait loader.reload();\n\t\t\treturn loader;\n\t\t},\n\t});\n\tconst turnLog = new TurnLog();\n\tconst turns = createTurnEngine({\n\t\tstore: createModeTurnStore(threads),\n\t\tturnLog,\n\t\temitToThread: (threadId, notification) => notifications.toThread(threadId, notification),\n\t\tbroadcast: (notification) => notifications.broadcast(notification),\n\t});\n\tregisterTurnHandlers(registry, turns, core);\n\n\tlifecycle = registerThreadLifecycleHandlers(registry, {\n\t\tthreads,\n\t\tturnLog,\n\t\tnotifications,\n\t\tdeferUntilResponded: (connectionId, action) => core.deferUntilResponded(connectionId, action),\n\t\tobserveThread: (threadId) => turns.observeThread(threadId),\n\t\tidleUnloadMinutes: 30,\n\t\treplayPendingApprovals: (threadId) => {\n\t\t\tapprovals.replayPendingForThread(threadId);\n\t\t\tuserInput.replayPendingForThread(threadId);\n\t\t},\n\t});\n\tregisterLoadedThreadObjectListHandler(registry, threads);\n\n\treturn {\n\t\tcore,\n\t\tthreads,\n\t\tturnLog,\n\t\tturns,\n\t\tdispose: () => {\n\t\t\tfor (const thread of threads.listLoaded()) userInput.cancelPendingForThread(thread.id);\n\t\t\tfuzzySearch.dispose();\n\t\t\tlifecycle?.dispose();\n\t\t},\n\t};\n}\n\nasync function createBoundAppServerSession(\n\toptions: CreateAgentSessionOptions,\n\tapprovals: ApprovalBridge,\n\tnotifications: NotificationRouter,\n\trequestShutdown: (reason: string) => void,\n\tuserInput: UserInputBridge,\n\tgetTurnId: (threadId: string) => string,\n): Promise<AppServerSessionResult> {\n\tconst result = await createAgentSession(options);\n\tconst threadId = result.session.sessionId;\n\tconst initialNotifications: RpcNotification[] = [];\n\tlet bindingExtensions = true;\n\tresult.session.extensionRunner.onRpcEvent(({ name, data }) => {\n\t\tconst notification = {\n\t\t\tmethod: \"extension_event\",\n\t\t\tparams: { type: \"extension_event\", name, data, threadId },\n\t\t};\n\t\tif (bindingExtensions) {\n\t\t\tinitialNotifications.push(notification);\n\t\t\treturn;\n\t\t}\n\t\tnotifications.toThread(threadId, notification);\n\t});\n\tawait result.session.bindExtensions({\n\t\tuiContext: createAppServerUIContext(approvals, threadId, userInput, () => getTurnId(threadId)),\n\t\tmode: \"app-server\",\n\t\tshutdownHandler: () => requestShutdown(\"extension shutdown\"),\n\t\tonError: (error) => {\n\t\t\tnotifications.toThread(threadId, { method: \"error\", params: error });\n\t\t},\n\t});\n\tbindingExtensions = false;\n\t// The MCP service captures this session's attach state under its session id.\n\t// Convert that captured state into a session-owned adapter before the entry is\n\t// registered; later requests never consult the service-global lifecycle view.\n\tconst mcpService = getMcpService();\n\tconst mcpWireStatusAdapter = createMcpWireStatusAdapter(mcpService.getWireStatusSnapshot(threadId));\n\t// Attach is started by session_start but no longer awaited by it, so the snapshot above is\n\t// empty whenever a server is still booting. Take later inventories by subscription rather\n\t// than by reading the service per request, which stays within this adapter's contract.\n\tmcpWireStatusAdapter.bindLiveUpdates(\n\t\tmcpService.onWireStatusChanged((sessionId, snapshot) => {\n\t\t\tif (sessionId === threadId) mcpWireStatusAdapter.update(snapshot);\n\t\t}),\n\t);\n\tresult.session.subscribe((event) => {\n\t\tif (event.type === \"agent_end\") {\n\t\t\tapprovals.cancelPendingForThread(threadId);\n\t\t\tuserInput.cancelPendingForThread(threadId);\n\t\t}\n\t});\n\treturn { ...result, initialNotifications, mcpWireStatusAdapter };\n}\n\nfunction registerTurnHandlers(registry: MethodRegistry, turns: TurnEngineApi, core: ServerCore): void {\n\tconst deferForResponse = async <T>(\n\t\tconnection: Parameters<MethodRegistry[\"dispatch\"]>[0],\n\t\trun: (defer: (action: () => void) => boolean) => Promise<T>,\n\t): Promise<T> => {\n\t\tconst actions: Array<() => void> = [];\n\t\tconst result = await run((action) => {\n\t\t\tactions.push(action);\n\t\t\treturn true;\n\t\t});\n\t\tfor (const action of actions) core.deferUntilResponded(connectionId(connection), action);\n\t\treturn result;\n\t};\n\tregistry.register(\"turn/start\", {\n\t\tscope: \"thread\",\n\t\thandler: (context) =>\n\t\t\tdeferForResponse(context.connection, (defer) => turns.startTurn(turnStartParams(context.request), defer)),\n\t});\n\tregistry.register(\"turn/steer\", {\n\t\tscope: \"thread\",\n\t\thandler: (context) => turns.steerTurn(turnSteerParams(context.request)),\n\t});\n\tregistry.register(\"turn/interrupt\", {\n\t\tscope: \"thread\",\n\t\thandler: (context) =>\n\t\t\tdeferForResponse(context.connection, (defer) =>\n\t\t\t\tturns.interruptTurn(turnInterruptParams(context.request), defer),\n\t\t\t),\n\t});\n}\n"]}
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/modes/app-server/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { ENV_SESSION_DIR, getAgentDir } from \"../../config.ts\";\nimport { getMcpService } from \"../../core/extensions/builtin/mcp/service.ts\";\nimport { DefaultResourceLoader } from \"../../core/resource-loader.ts\";\nimport { type CreateAgentSessionOptions, createAgentSession } from \"../../core/sdk.ts\";\nimport { SettingsManager } from \"../../core/settings-manager.ts\";\nimport type { RpcNotification } from \"./rpc/envelope.ts\";\nimport { createRegistry, type MethodRegistry, registerExtensionRequestMethod } from \"./rpc/registry.ts\";\nimport { registerFuzzyFileSearchMethods } from \"./search/fuzzy-search-methods.ts\";\nimport { FuzzyFileSearchService } from \"./search/fuzzy-search-service.ts\";\nimport { ApprovalBridge, createAppServerUIContext } from \"./server/approvals.ts\";\nimport { NotificationRouter, type RouterOutboundMessage } from \"./server/notifications.ts\";\nimport type { ServerCore } from \"./server/server-core.ts\";\nimport { registerAppServerSkillMethods } from \"./server/skills.ts\";\nimport { UserInputBridge } from \"./server/user-input-bridge.ts\";\nimport { connectionId } from \"./threads/handler-params.ts\";\nimport { registerThreadLifecycleHandlers, type ThreadLifecycleController } from \"./threads/handlers.ts\";\nimport { createMcpWireStatusAdapter, createProcessMcpWireStatusAdapter } from \"./threads/mcp-wire-status.ts\";\nimport { type AppServerSessionResult, ThreadNotFoundError, ThreadRegistry } from \"./threads/registry.ts\";\nimport { TurnLog } from \"./threads/turn-log.ts\";\nimport { createTurnEngine, type TurnEngineApi } from \"./threads/turns.ts\";\nimport {\n\tcreateModeTurnStore,\n\tcreateRoutedServerCore,\n\tregisterLoadedThreadObjectListHandler,\n\tturnInterruptParams,\n\tturnStartParams,\n\tturnSteerParams,\n} from \"./turn-adapter.ts\";\n\nexport type AppServerRuntime = {\n\treadonly core: ServerCore;\n\treadonly threads: ThreadRegistry;\n\treadonly turnLog: TurnLog;\n\treadonly turns: TurnEngineApi;\n\treadonly dispose: () => void;\n};\n\nexport interface AppServerRuntimeOptions {\n\t/** Resolved `--extension` sources, loaded into every thread session and every skills/list loader. */\n\treadonly extensionPaths?: readonly string[];\n}\n\nexport function createAppServerRuntime(\n\trequestShutdown: (reason: string) => void,\n\truntimeOptions: AppServerRuntimeOptions = {},\n): AppServerRuntime {\n\tconst additionalExtensionPaths = [...(runtimeOptions.extensionPaths ?? [])];\n\tconst notifications = new NotificationRouter();\n\tconst registry = createRegistry();\n\tconst fuzzySearch = new FuzzyFileSearchService({\n\t\tbroadcast: (notification) => notifications.broadcast(notification),\n\t});\n\tregisterFuzzyFileSearchMethods(registry, fuzzySearch);\n\tlet threads: ThreadRegistry;\n\tconst processMcpWireStatusAdapter = createProcessMcpWireStatusAdapter({\n\t\tagentDir: getAgentDir(),\n\t\tcwd: process.cwd(),\n\t\tenv: process.env,\n\t});\n\tconst sendToSubscribers = (threadId: string, message: RouterOutboundMessage): number => {\n\t\tlet subscriberCount = 0;\n\t\ttry {\n\t\t\tsubscriberCount = threads.getLoadedThread(threadId).subscribers.size;\n\t\t} catch (error: unknown) {\n\t\t\tif (error instanceof ThreadNotFoundError) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tnotifications.toThread(threadId, message);\n\t\treturn subscriberCount;\n\t};\n\tconst approvals = new ApprovalBridge(sendToSubscribers);\n\tconst userInput = new UserInputBridge(sendToSubscribers);\n\tlet lifecycle: ThreadLifecycleController | undefined;\n\tthreads = new ThreadRegistry({\n\t\tagentDir: getAgentDir(),\n\t\tsessionDir: process.env[ENV_SESSION_DIR],\n\t\tcreateSession: async (options) =>\n\t\t\tcreateBoundAppServerSession(\n\t\t\t\tawait withExtensionPaths(options, additionalExtensionPaths),\n\t\t\t\tapprovals,\n\t\t\t\tnotifications,\n\t\t\t\trequestShutdown,\n\t\t\t\tuserInput,\n\t\t\t\t(threadId) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn threads.getLoadedThread(threadId).activeTurn?.turnId ?? \"turn-user-input\";\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (error instanceof ThreadNotFoundError) return \"turn-user-input\";\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t),\n\t\tmcpWireStatusAdapter: processMcpWireStatusAdapter,\n\t});\n\tregisterExtensionRequestMethod(registry, (threadId) => threads.getLoadedThread(threadId).session);\n\tconst core = createRoutedServerCore(\n\t\tregistry,\n\t\tnotifications,\n\t\tapprovals,\n\t\t(threadId) => {\n\t\t\tlifecycle?.scheduleIdleUnloadForThread(threadId);\n\t\t},\n\t\t{\n\t\t\tcodexHome: getAgentDir(),\n\t\t\tserverCwd: process.cwd(),\n\t\t\tthreads,\n\t\t},\n\t\tuserInput,\n\t);\n\tregisterAppServerSkillMethods(registry, {\n\t\tagentDir: getAgentDir(),\n\t\tserverCwd: process.cwd(),\n\t\tthreads,\n\t\tresourceLoaderFactory: async (cwd) => {\n\t\t\tconst loader = new DefaultResourceLoader({ cwd, agentDir: getAgentDir(), additionalExtensionPaths });\n\t\t\tawait loader.reload();\n\t\t\treturn loader;\n\t\t},\n\t});\n\tconst turnLog = new TurnLog();\n\tconst turns = createTurnEngine({\n\t\tstore: createModeTurnStore(threads),\n\t\tturnLog,\n\t\temitToThread: (threadId, notification) => notifications.toThread(threadId, notification),\n\t\tbroadcast: (notification) => notifications.broadcast(notification),\n\t});\n\tregisterTurnHandlers(registry, turns, core);\n\n\tlifecycle = registerThreadLifecycleHandlers(registry, {\n\t\tthreads,\n\t\tturnLog,\n\t\tnotifications,\n\t\tdeferUntilResponded: (connectionId, action) => core.deferUntilResponded(connectionId, action),\n\t\tobserveThread: (threadId) => turns.observeThread(threadId),\n\t\tidleUnloadMinutes: 30,\n\t\treplayPendingApprovals: (threadId) => {\n\t\t\tapprovals.replayPendingForThread(threadId);\n\t\t\tuserInput.replayPendingForThread(threadId);\n\t\t},\n\t});\n\tregisterLoadedThreadObjectListHandler(registry, threads);\n\n\treturn {\n\t\tcore,\n\t\tthreads,\n\t\tturnLog,\n\t\tturns,\n\t\tdispose: () => {\n\t\t\tfor (const thread of threads.listLoaded()) userInput.cancelPendingForThread(thread.id);\n\t\t\tfuzzySearch.dispose();\n\t\t\tlifecycle?.dispose();\n\t\t},\n\t};\n}\n\n/**\n * A session's default resource loader only discovers settings and agent-dir extensions, so explicit\n * paths need a loader of their own, built the way `createAgentSession` builds its default one.\n */\nasync function withExtensionPaths(\n\toptions: CreateAgentSessionOptions,\n\tadditionalExtensionPaths: string[],\n): Promise<CreateAgentSessionOptions> {\n\tif (additionalExtensionPaths.length === 0 || options.resourceLoader) return options;\n\tconst cwd = options.cwd ?? options.sessionManager?.getCwd() ?? process.cwd();\n\tconst agentDir = options.agentDir ?? getAgentDir();\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\tconst resourceLoader = new DefaultResourceLoader({ cwd, agentDir, settingsManager, additionalExtensionPaths });\n\tawait resourceLoader.reload();\n\treturn { ...options, settingsManager, resourceLoader };\n}\n\nasync function createBoundAppServerSession(\n\toptions: CreateAgentSessionOptions,\n\tapprovals: ApprovalBridge,\n\tnotifications: NotificationRouter,\n\trequestShutdown: (reason: string) => void,\n\tuserInput: UserInputBridge,\n\tgetTurnId: (threadId: string) => string,\n): Promise<AppServerSessionResult> {\n\tconst result = await createAgentSession(options);\n\tconst threadId = result.session.sessionId;\n\tconst initialNotifications: RpcNotification[] = [];\n\tlet bindingExtensions = true;\n\tresult.session.extensionRunner.onRpcEvent(({ name, data }) => {\n\t\tconst notification = {\n\t\t\tmethod: \"extension_event\",\n\t\t\tparams: { type: \"extension_event\", name, data, threadId },\n\t\t};\n\t\tif (bindingExtensions) {\n\t\t\tinitialNotifications.push(notification);\n\t\t\treturn;\n\t\t}\n\t\tnotifications.toThread(threadId, notification);\n\t});\n\tawait result.session.bindExtensions({\n\t\tuiContext: createAppServerUIContext(approvals, threadId, userInput, () => getTurnId(threadId)),\n\t\tmode: \"app-server\",\n\t\tshutdownHandler: () => requestShutdown(\"extension shutdown\"),\n\t\tonError: (error) => {\n\t\t\tnotifications.toThread(threadId, { method: \"error\", params: error });\n\t\t},\n\t});\n\tbindingExtensions = false;\n\t// The MCP service captures this session's attach state under its session id.\n\t// Convert that captured state into a session-owned adapter before the entry is\n\t// registered; later requests never consult the service-global lifecycle view.\n\tconst mcpService = getMcpService();\n\tconst mcpWireStatusAdapter = createMcpWireStatusAdapter(mcpService.getWireStatusSnapshot(threadId));\n\t// Attach is started by session_start but no longer awaited by it, so the snapshot above is\n\t// empty whenever a server is still booting. Take later inventories by subscription rather\n\t// than by reading the service per request, which stays within this adapter's contract.\n\tmcpWireStatusAdapter.bindLiveUpdates(\n\t\tmcpService.onWireStatusChanged((sessionId, snapshot) => {\n\t\t\tif (sessionId === threadId) mcpWireStatusAdapter.update(snapshot);\n\t\t}),\n\t);\n\tresult.session.subscribe((event) => {\n\t\tif (event.type === \"agent_end\") {\n\t\t\tapprovals.cancelPendingForThread(threadId);\n\t\t\tuserInput.cancelPendingForThread(threadId);\n\t\t}\n\t});\n\treturn { ...result, initialNotifications, mcpWireStatusAdapter };\n}\n\nfunction registerTurnHandlers(registry: MethodRegistry, turns: TurnEngineApi, core: ServerCore): void {\n\tconst deferForResponse = async <T>(\n\t\tconnection: Parameters<MethodRegistry[\"dispatch\"]>[0],\n\t\trun: (defer: (action: () => void) => boolean) => Promise<T>,\n\t): Promise<T> => {\n\t\tconst actions: Array<() => void> = [];\n\t\tconst result = await run((action) => {\n\t\t\tactions.push(action);\n\t\t\treturn true;\n\t\t});\n\t\tfor (const action of actions) core.deferUntilResponded(connectionId(connection), action);\n\t\treturn result;\n\t};\n\tregistry.register(\"turn/start\", {\n\t\tscope: \"thread\",\n\t\thandler: (context) =>\n\t\t\tdeferForResponse(context.connection, (defer) => turns.startTurn(turnStartParams(context.request), defer)),\n\t});\n\tregistry.register(\"turn/steer\", {\n\t\tscope: \"thread\",\n\t\thandler: (context) => turns.steerTurn(turnSteerParams(context.request)),\n\t});\n\tregistry.register(\"turn/interrupt\", {\n\t\tscope: \"thread\",\n\t\thandler: (context) =>\n\t\t\tdeferForResponse(context.connection, (defer) =>\n\t\t\t\tturns.interruptTurn(turnInterruptParams(context.request), defer),\n\t\t\t),\n\t});\n}\n"]}
@@ -6,7 +6,7 @@ export const COMPUTER_TIPS = [
6
6
  id: "computer.what-it-is",
7
7
  bindings: [],
8
8
  requiresCommand: "computer",
9
- render: () => "Your agent can use native apps too: screenshots, windows, clicks and typing. Run /computer to see whether this machine is ready.",
9
+ render: () => "Experimental: your agent can use native apps too: screenshots, windows, clicks and typing. Run /computer to see whether this machine is ready.",
10
10
  },
11
11
  {
12
12
  id: "computer.stop-chord",
@@ -1 +1 @@
1
- {"version":3,"file":"computer-tips.js","sourceRoot":"","sources":["../../../../../src/modes/interactive/tips/catalog/computer-tips.ts"],"names":[],"mappings":"AAEA,SAAS,SAAS;IACjB,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,uBAAuB,CAAC;AAClG,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG;IAC5B;QACC,EAAE,EAAE,qBAAqB;QACzB,QAAQ,EAAE,EAAE;QACZ,eAAe,EAAE,UAAU;QAC3B,MAAM,EAAE,GAAG,EAAE,CACZ,kIAAkI;KACnI;IACD;QACC,EAAE,EAAE,qBAAqB;QACzB,QAAQ,EAAE,EAAE;QACZ,eAAe,EAAE,UAAU;QAC3B,MAAM,EAAE,GAAG,EAAE,CACZ,SAAS,SAAS,EAAE,qHAAqH;KAC1I;IACD;QACC,EAAE,EAAE,2BAA2B;QAC/B,QAAQ,EAAE,EAAE;QACZ,eAAe,EAAE,UAAU;QAC3B,MAAM,EAAE,GAAG,EAAE,CACZ,iJAAiJ;KAClJ;IACD;QACC,EAAE,EAAE,0BAA0B;QAC9B,QAAQ,EAAE,EAAE;QACZ,eAAe,EAAE,UAAU;QAC3B,MAAM,EAAE,GAAG,EAAE,CACZ,kKAAkK;KACnK;IACD;QACC,EAAE,EAAE,sBAAsB;QAC1B,QAAQ,EAAE,EAAE;QACZ,eAAe,EAAE,UAAU;QAC3B,MAAM,EAAE,GAAG,EAAE,CACZ,2IAA2I;KAC5I;CACkC,CAAC","sourcesContent":["import type { TipDefinition } from \"./types.ts\";\n\nfunction stopChord(): string {\n\treturn process.platform === \"darwin\" ? \"Control+Option+Command+Escape\" : \"Ctrl+Alt+Shift+Escape\";\n}\n\nexport const COMPUTER_TIPS = [\n\t{\n\t\tid: \"computer.what-it-is\",\n\t\tbindings: [],\n\t\trequiresCommand: \"computer\",\n\t\trender: () =>\n\t\t\t\"Your agent can use native apps too: screenshots, windows, clicks and typing. Run /computer to see whether this machine is ready.\",\n\t},\n\t{\n\t\tid: \"computer.stop-chord\",\n\t\tbindings: [],\n\t\trequiresCommand: \"computer\",\n\t\trender: () =>\n\t\t\t`Press ${stopChord()} at any moment to stop computer input. It stays stopped until you run /computer resume; the agent cannot resume it.`,\n\t},\n\t{\n\t\tid: \"computer.background-input\",\n\t\tbindings: [],\n\t\trequiresCommand: \"computer\",\n\t\trender: () =>\n\t\t\t\"Computer use clicks and types into the target app in the background, so your frontmost app, keyboard focus and cursor stay where you left them.\",\n\t},\n\t{\n\t\tid: \"computer.look-dont-touch\",\n\t\tbindings: [],\n\t\trequiresCommand: \"computer\",\n\t\trender: () =>\n\t\t\t\"Want the agent to look but not touch? Start with --permission computer:exec=deny: screenshots and accessibility reads still work, clicks and typing are refused.\",\n\t},\n\t{\n\t\tid: \"computer.permissions\",\n\t\tbindings: [],\n\t\trequiresCommand: \"computer\",\n\t\trender: () =>\n\t\t\t\"On macOS, computer use needs Screen Recording and Accessibility for the app you launch from. /computer status shows which one is missing.\",\n\t},\n] satisfies readonly TipDefinition[];\n"]}
1
+ {"version":3,"file":"computer-tips.js","sourceRoot":"","sources":["../../../../../src/modes/interactive/tips/catalog/computer-tips.ts"],"names":[],"mappings":"AAEA,SAAS,SAAS;IACjB,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,uBAAuB,CAAC;AAClG,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG;IAC5B;QACC,EAAE,EAAE,qBAAqB;QACzB,QAAQ,EAAE,EAAE;QACZ,eAAe,EAAE,UAAU;QAC3B,MAAM,EAAE,GAAG,EAAE,CACZ,gJAAgJ;KACjJ;IACD;QACC,EAAE,EAAE,qBAAqB;QACzB,QAAQ,EAAE,EAAE;QACZ,eAAe,EAAE,UAAU;QAC3B,MAAM,EAAE,GAAG,EAAE,CACZ,SAAS,SAAS,EAAE,qHAAqH;KAC1I;IACD;QACC,EAAE,EAAE,2BAA2B;QAC/B,QAAQ,EAAE,EAAE;QACZ,eAAe,EAAE,UAAU;QAC3B,MAAM,EAAE,GAAG,EAAE,CACZ,iJAAiJ;KAClJ;IACD;QACC,EAAE,EAAE,0BAA0B;QAC9B,QAAQ,EAAE,EAAE;QACZ,eAAe,EAAE,UAAU;QAC3B,MAAM,EAAE,GAAG,EAAE,CACZ,kKAAkK;KACnK;IACD;QACC,EAAE,EAAE,sBAAsB;QAC1B,QAAQ,EAAE,EAAE;QACZ,eAAe,EAAE,UAAU;QAC3B,MAAM,EAAE,GAAG,EAAE,CACZ,2IAA2I;KAC5I;CACkC,CAAC","sourcesContent":["import type { TipDefinition } from \"./types.ts\";\n\nfunction stopChord(): string {\n\treturn process.platform === \"darwin\" ? \"Control+Option+Command+Escape\" : \"Ctrl+Alt+Shift+Escape\";\n}\n\nexport const COMPUTER_TIPS = [\n\t{\n\t\tid: \"computer.what-it-is\",\n\t\tbindings: [],\n\t\trequiresCommand: \"computer\",\n\t\trender: () =>\n\t\t\t\"Experimental: your agent can use native apps too: screenshots, windows, clicks and typing. Run /computer to see whether this machine is ready.\",\n\t},\n\t{\n\t\tid: \"computer.stop-chord\",\n\t\tbindings: [],\n\t\trequiresCommand: \"computer\",\n\t\trender: () =>\n\t\t\t`Press ${stopChord()} at any moment to stop computer input. It stays stopped until you run /computer resume; the agent cannot resume it.`,\n\t},\n\t{\n\t\tid: \"computer.background-input\",\n\t\tbindings: [],\n\t\trequiresCommand: \"computer\",\n\t\trender: () =>\n\t\t\t\"Computer use clicks and types into the target app in the background, so your frontmost app, keyboard focus and cursor stay where you left them.\",\n\t},\n\t{\n\t\tid: \"computer.look-dont-touch\",\n\t\tbindings: [],\n\t\trequiresCommand: \"computer\",\n\t\trender: () =>\n\t\t\t\"Want the agent to look but not touch? Start with --permission computer:exec=deny: screenshots and accessibility reads still work, clicks and typing are refused.\",\n\t},\n\t{\n\t\tid: \"computer.permissions\",\n\t\tbindings: [],\n\t\trequiresCommand: \"computer\",\n\t\trender: () =>\n\t\t\t\"On macOS, computer use needs Screen Recording and Accessibility for the app you launch from. /computer status shows which one is missing.\",\n\t},\n] satisfies readonly TipDefinition[];\n"]}
@@ -48,6 +48,11 @@ export declare const SESSION_KIND_CAPABILITY = "session_kind";
48
48
  * into or out of engine-side titling independently of `--auto-title-sessions`.
49
49
  */
50
50
  export declare const AUTO_TITLE_PER_SESSION_CAPABILITY = "auto_title_per_session";
51
+ /**
52
+ * HOST capability: this host answers `warm` (senpi#2314) - it loads what the next `open_session` for a
53
+ * cwd, kind and context needs without opening a session. Advertised only by an in-process runtime.
54
+ */
55
+ export declare const WARM_CAPABILITY = "warm";
51
56
  /**
52
57
  * HOST capability: this host honors `open_session.durableSessionId`, so a caller that already
53
58
  * owns a stable record id for the conversation can CREATE the session under that id and keep
@@ -1 +1 @@
1
- {"version":3,"file":"custom-capability.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/custom-capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAE5D,oFAAoF;AACpF,eAAO,MAAM,6BAA6B,uBAAuB,CAAC;AAClE,eAAO,MAAM,2BAA2B,qBAAqB,CAAC;AAC9D,eAAO,MAAM,8BAA8B,wBAAwB,CAAC;AACpE,eAAO,MAAM,8BAA8B,wBAAwB,CAAC;AACpE;;;GAGG;AACH,eAAO,MAAM,6BAA6B,uBAAuB,CAAC;AAClE,iGAAiG;AACjG,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAE9C;;;;GAIG;AACH,eAAO,MAAM,+BAA+B,yBAAyB,CAAC;AAEtE;;;GAGG;AACH,eAAO,MAAM,0BAA0B,oBAAoB,CAAC;AAE5D;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,iBAAiB,CAAC;AAEtD;;;GAGG;AACH,eAAO,MAAM,iCAAiC,2BAA2B,CAAC;AAE1E;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,uBAAuB,CAAC;AAElE;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,kCAAkC,CAAC;AAE3E,4EAA4E;AAC5E,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAM3E;AAED,6EAA6E;AAC7E,eAAO,MAAM,8BAA8B,wBAAwB,CAAC;AAEpE;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC5C,YAAY,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EAC3C,aAAa,EAAE,MAAM,GACnB,qBAAqB,GAAG,SAAS,CAWnC"}
1
+ {"version":3,"file":"custom-capability.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/custom-capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAE5D,oFAAoF;AACpF,eAAO,MAAM,6BAA6B,uBAAuB,CAAC;AAClE,eAAO,MAAM,2BAA2B,qBAAqB,CAAC;AAC9D,eAAO,MAAM,8BAA8B,wBAAwB,CAAC;AACpE,eAAO,MAAM,8BAA8B,wBAAwB,CAAC;AACpE;;;GAGG;AACH,eAAO,MAAM,6BAA6B,uBAAuB,CAAC;AAClE,iGAAiG;AACjG,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAE9C;;;;GAIG;AACH,eAAO,MAAM,+BAA+B,yBAAyB,CAAC;AAEtE;;;GAGG;AACH,eAAO,MAAM,0BAA0B,oBAAoB,CAAC;AAE5D;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,iBAAiB,CAAC;AAEtD;;;GAGG;AACH,eAAO,MAAM,iCAAiC,2BAA2B,CAAC;AAE1E;;;GAGG;AACH,eAAO,MAAM,eAAe,SAAS,CAAC;AAEtC;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,uBAAuB,CAAC;AAElE;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,kCAAkC,CAAC;AAE3E,4EAA4E;AAC5E,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAM3E;AAED,6EAA6E;AAC7E,eAAO,MAAM,8BAA8B,wBAAwB,CAAC;AAEpE;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC5C,YAAY,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EAC3C,aAAa,EAAE,MAAM,GACnB,qBAAqB,GAAG,SAAS,CAWnC"}
@@ -48,6 +48,11 @@ export const SESSION_KIND_CAPABILITY = "session_kind";
48
48
  * into or out of engine-side titling independently of `--auto-title-sessions`.
49
49
  */
50
50
  export const AUTO_TITLE_PER_SESSION_CAPABILITY = "auto_title_per_session";
51
+ /**
52
+ * HOST capability: this host answers `warm` (senpi#2314) - it loads what the next `open_session` for a
53
+ * cwd, kind and context needs without opening a session. Advertised only by an in-process runtime.
54
+ */
55
+ export const WARM_CAPABILITY = "warm";
51
56
  /**
52
57
  * HOST capability: this host honors `open_session.durableSessionId`, so a caller that already
53
58
  * owns a stable record id for the conversation can CREATE the session under that id and keep
@@ -1 +1 @@
1
- {"version":3,"file":"custom-capability.js","sourceRoot":"","sources":["../../../src/modes/rpc/custom-capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AAGtC,oFAAoF;AACpF,MAAM,CAAC,MAAM,6BAA6B,GAAG,oBAAoB,CAAC;AAClE,MAAM,CAAC,MAAM,2BAA2B,GAAG,kBAAkB,CAAC;AAC9D,MAAM,CAAC,MAAM,8BAA8B,GAAG,qBAAqB,CAAC;AACpE,MAAM,CAAC,MAAM,8BAA8B,GAAG,qBAAqB,CAAC;AACpE;;;GAGG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,oBAAoB,CAAC;AAClE,iGAAiG;AACjG,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAC;AAE9C;;;;GAIG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAG,sBAAsB,CAAC;AAEtE;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,iBAAiB,CAAC;AAE5D;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,cAAc,CAAC;AAEtD;;;GAGG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAAG,wBAAwB,CAAC;AAE1E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,oBAAoB,CAAC;AAElE;;;;GAIG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,+BAA+B,CAAC;AAE3E,4EAA4E;AAC5E,MAAM,UAAU,uBAAuB,CAAC,KAAyB;IAChE,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,OAAO,KAAK;SACV,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACrC,CAAC;AAED,6EAA6E;AAC7E,MAAM,CAAC,MAAM,8BAA8B,GAAG,qBAAqB,CAAC;AAEpE;;;;;;GAMG;AACH,MAAM,UAAU,6BAA6B,CAC5C,YAA2C,EAC3C,aAAqB;IAErB,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,6BAA6B,CAAC,EAAE,CAAC;QAC5D,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,EAAE,IAAI,8BAA8B,CAAC;IACpE,OAAO;QACN,IAAI,EAAE,sBAAsB;QAC5B,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;QACvB,MAAM,EAAE,oBAAoB;QAC5B,aAAa,EAAE,IAAI;KACnB,CAAC;AACH,CAAC","sourcesContent":["/**\n * The `custom_unsupported` capability gate (plan tasks 13/14).\n *\n * In RPC mode `ctx.ui.custom` cannot render a third-party component — there is no\n * TUI to render it FROM. Historically it returned `undefined` synchronously with\n * NO wire message, so a default RPC client saw nothing at all. A client that\n * can present a native \"this extension UI requires the classic TUI\" notice opts\n * in via a capability flag.\n *\n * This gate is a PURE function so the additive-only guarantee is unit-provable:\n * only a client that advertised the `custom_unsupported` capability gets the\n * additive `extension_ui_request{method:\"custom_unsupported\"}` notice; every\n * other (default) client gets `undefined` — byte-identical to the prior\n * behavior, no extra bytes on the wire.\n */\n\nimport * as crypto from \"node:crypto\";\nimport type { RpcExtensionUIRequest } from \"./rpc-types.ts\";\n\n/** The capability string a client sends in its handshake to opt into the notice. */\nexport const CUSTOM_UNSUPPORTED_CAPABILITY = \"custom_unsupported\";\nexport const EXTENSION_EVENTS_CAPABILITY = \"extension_events\";\nexport const RENDERED_COMPONENTS_CAPABILITY = \"rendered_components\";\nexport const AUTO_TITLE_SESSIONS_CAPABILITY = \"auto_title_sessions\";\n/**\n * Opt-in: the host replaces inline image bytes inside tool results with `image_ref`\n * placeholders for this connection; the client fetches a block on demand with `get_media`.\n */\nexport const MEDIA_PLACEHOLDERS_CAPABILITY = \"media_placeholders\";\n/** Opt-in: the client can present a multi-question `extension_ui_request{method:\"question\"}`. */\nexport const QUESTION_CAPABILITY = \"question\";\n\n/**\n * HOST capability (advertised in `get_protocol_info`, never sent by a client):\n * this host honors `open_session.retain_on_disconnect`, so a session opened with\n * that flag survives its last client's disconnect instead of being closed with it.\n */\nexport const RETAIN_ON_DISCONNECT_CAPABILITY = \"retain_on_disconnect\";\n\n/**\n * HOST capability: this host accepts `open_session.context`, hands it to that session's\n * extensions as `pi.sessionContext`, and republishes it on `list_sessions { include_workers: true }`.\n */\nexport const SESSION_CONTEXT_CAPABILITY = \"session_context\";\n\n/**\n * HOST capability: this host accepts `open_session.kind`, publishes `kind` on every\n * `list_sessions` row, hides `worker` rows unless `include_workers` is set, and keeps a\n * worker session's lifecycle records on the connections attached to it.\n */\nexport const SESSION_KIND_CAPABILITY = \"session_kind\";\n\n/**\n * HOST capability: this host honors `open_session.auto_title`, so a session can opt\n * into or out of engine-side titling independently of `--auto-title-sessions`.\n */\nexport const AUTO_TITLE_PER_SESSION_CAPABILITY = \"auto_title_per_session\";\n\n/**\n * HOST capability: this host honors `open_session.durableSessionId`, so a caller that already\n * owns a stable record id for the conversation can CREATE the session under that id and keep\n * one identity instead of maintaining a mapping. Ignored on resume, where the session file's\n * header id stays authoritative.\n */\nexport const DURABLE_SESSION_ID_CAPABILITY = \"durable_session_id\";\n\n/**\n * Env var carrying client capabilities to a single-connection stdio RPC host\n * (comma-separated). A launcher may set it from a client handshake; a plain\n * stdio client leaves it unset and sees byte-identical default behavior.\n */\nexport const RPC_CLIENT_CAPABILITIES_ENV = \"SENPI_RPC_CLIENT_CAPABILITIES\";\n\n/** Parse the comma-separated capabilities env value into a trimmed list. */\nexport function parseClientCapabilities(value: string | undefined): string[] {\n\tif (!value) return [];\n\treturn value\n\t\t.split(\",\")\n\t\t.map((part) => part.trim())\n\t\t.filter((part) => part.length > 0);\n}\n\n/** Fallback label when the calling extension's name cannot be determined. */\nexport const DEFAULT_CUSTOM_EXTENSION_LABEL = \"custom UI component\";\n\n/**\n * Build the additive `custom_unsupported` request for a `ctx.ui.custom` call, or\n * `undefined` when the client did not opt in.\n *\n * Returning `undefined` is the load-bearing default-client path: the caller must\n * emit NOTHING in that case, preserving the exact prior wire behavior.\n */\nexport function buildCustomUnsupportedRequest(\n\tcapabilities: readonly string[] | undefined,\n\textensionName: string,\n): RpcExtensionUIRequest | undefined {\n\tif (!capabilities?.includes(CUSTOM_UNSUPPORTED_CAPABILITY)) {\n\t\treturn undefined;\n\t}\n\tconst name = extensionName.trim() || DEFAULT_CUSTOM_EXTENSION_LABEL;\n\treturn {\n\t\ttype: \"extension_ui_request\",\n\t\tid: crypto.randomUUID(),\n\t\tmethod: \"custom_unsupported\",\n\t\textensionName: name,\n\t};\n}\n"]}
1
+ {"version":3,"file":"custom-capability.js","sourceRoot":"","sources":["../../../src/modes/rpc/custom-capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AAGtC,oFAAoF;AACpF,MAAM,CAAC,MAAM,6BAA6B,GAAG,oBAAoB,CAAC;AAClE,MAAM,CAAC,MAAM,2BAA2B,GAAG,kBAAkB,CAAC;AAC9D,MAAM,CAAC,MAAM,8BAA8B,GAAG,qBAAqB,CAAC;AACpE,MAAM,CAAC,MAAM,8BAA8B,GAAG,qBAAqB,CAAC;AACpE;;;GAGG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,oBAAoB,CAAC;AAClE,iGAAiG;AACjG,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAC;AAE9C;;;;GAIG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAG,sBAAsB,CAAC;AAEtE;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,iBAAiB,CAAC;AAE5D;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,cAAc,CAAC;AAEtD;;;GAGG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAAG,wBAAwB,CAAC;AAE1E;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC;AAEtC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,oBAAoB,CAAC;AAElE;;;;GAIG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,+BAA+B,CAAC;AAE3E,4EAA4E;AAC5E,MAAM,UAAU,uBAAuB,CAAC,KAAyB;IAChE,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,OAAO,KAAK;SACV,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACrC,CAAC;AAED,6EAA6E;AAC7E,MAAM,CAAC,MAAM,8BAA8B,GAAG,qBAAqB,CAAC;AAEpE;;;;;;GAMG;AACH,MAAM,UAAU,6BAA6B,CAC5C,YAA2C,EAC3C,aAAqB;IAErB,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,6BAA6B,CAAC,EAAE,CAAC;QAC5D,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,EAAE,IAAI,8BAA8B,CAAC;IACpE,OAAO;QACN,IAAI,EAAE,sBAAsB;QAC5B,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;QACvB,MAAM,EAAE,oBAAoB;QAC5B,aAAa,EAAE,IAAI;KACnB,CAAC;AACH,CAAC","sourcesContent":["/**\n * The `custom_unsupported` capability gate (plan tasks 13/14).\n *\n * In RPC mode `ctx.ui.custom` cannot render a third-party component — there is no\n * TUI to render it FROM. Historically it returned `undefined` synchronously with\n * NO wire message, so a default RPC client saw nothing at all. A client that\n * can present a native \"this extension UI requires the classic TUI\" notice opts\n * in via a capability flag.\n *\n * This gate is a PURE function so the additive-only guarantee is unit-provable:\n * only a client that advertised the `custom_unsupported` capability gets the\n * additive `extension_ui_request{method:\"custom_unsupported\"}` notice; every\n * other (default) client gets `undefined` — byte-identical to the prior\n * behavior, no extra bytes on the wire.\n */\n\nimport * as crypto from \"node:crypto\";\nimport type { RpcExtensionUIRequest } from \"./rpc-types.ts\";\n\n/** The capability string a client sends in its handshake to opt into the notice. */\nexport const CUSTOM_UNSUPPORTED_CAPABILITY = \"custom_unsupported\";\nexport const EXTENSION_EVENTS_CAPABILITY = \"extension_events\";\nexport const RENDERED_COMPONENTS_CAPABILITY = \"rendered_components\";\nexport const AUTO_TITLE_SESSIONS_CAPABILITY = \"auto_title_sessions\";\n/**\n * Opt-in: the host replaces inline image bytes inside tool results with `image_ref`\n * placeholders for this connection; the client fetches a block on demand with `get_media`.\n */\nexport const MEDIA_PLACEHOLDERS_CAPABILITY = \"media_placeholders\";\n/** Opt-in: the client can present a multi-question `extension_ui_request{method:\"question\"}`. */\nexport const QUESTION_CAPABILITY = \"question\";\n\n/**\n * HOST capability (advertised in `get_protocol_info`, never sent by a client):\n * this host honors `open_session.retain_on_disconnect`, so a session opened with\n * that flag survives its last client's disconnect instead of being closed with it.\n */\nexport const RETAIN_ON_DISCONNECT_CAPABILITY = \"retain_on_disconnect\";\n\n/**\n * HOST capability: this host accepts `open_session.context`, hands it to that session's\n * extensions as `pi.sessionContext`, and republishes it on `list_sessions { include_workers: true }`.\n */\nexport const SESSION_CONTEXT_CAPABILITY = \"session_context\";\n\n/**\n * HOST capability: this host accepts `open_session.kind`, publishes `kind` on every\n * `list_sessions` row, hides `worker` rows unless `include_workers` is set, and keeps a\n * worker session's lifecycle records on the connections attached to it.\n */\nexport const SESSION_KIND_CAPABILITY = \"session_kind\";\n\n/**\n * HOST capability: this host honors `open_session.auto_title`, so a session can opt\n * into or out of engine-side titling independently of `--auto-title-sessions`.\n */\nexport const AUTO_TITLE_PER_SESSION_CAPABILITY = \"auto_title_per_session\";\n\n/**\n * HOST capability: this host answers `warm` (senpi#2314) - it loads what the next `open_session` for a\n * cwd, kind and context needs without opening a session. Advertised only by an in-process runtime.\n */\nexport const WARM_CAPABILITY = \"warm\";\n\n/**\n * HOST capability: this host honors `open_session.durableSessionId`, so a caller that already\n * owns a stable record id for the conversation can CREATE the session under that id and keep\n * one identity instead of maintaining a mapping. Ignored on resume, where the session file's\n * header id stays authoritative.\n */\nexport const DURABLE_SESSION_ID_CAPABILITY = \"durable_session_id\";\n\n/**\n * Env var carrying client capabilities to a single-connection stdio RPC host\n * (comma-separated). A launcher may set it from a client handshake; a plain\n * stdio client leaves it unset and sees byte-identical default behavior.\n */\nexport const RPC_CLIENT_CAPABILITIES_ENV = \"SENPI_RPC_CLIENT_CAPABILITIES\";\n\n/** Parse the comma-separated capabilities env value into a trimmed list. */\nexport function parseClientCapabilities(value: string | undefined): string[] {\n\tif (!value) return [];\n\treturn value\n\t\t.split(\",\")\n\t\t.map((part) => part.trim())\n\t\t.filter((part) => part.length > 0);\n}\n\n/** Fallback label when the calling extension's name cannot be determined. */\nexport const DEFAULT_CUSTOM_EXTENSION_LABEL = \"custom UI component\";\n\n/**\n * Build the additive `custom_unsupported` request for a `ctx.ui.custom` call, or\n * `undefined` when the client did not opt in.\n *\n * Returning `undefined` is the load-bearing default-client path: the caller must\n * emit NOTHING in that case, preserving the exact prior wire behavior.\n */\nexport function buildCustomUnsupportedRequest(\n\tcapabilities: readonly string[] | undefined,\n\textensionName: string,\n): RpcExtensionUIRequest | undefined {\n\tif (!capabilities?.includes(CUSTOM_UNSUPPORTED_CAPABILITY)) {\n\t\treturn undefined;\n\t}\n\tconst name = extensionName.trim() || DEFAULT_CUSTOM_EXTENSION_LABEL;\n\treturn {\n\t\ttype: \"extension_ui_request\",\n\t\tid: crypto.randomUUID(),\n\t\tmethod: \"custom_unsupported\",\n\t\textensionName: name,\n\t};\n}\n"]}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The environment names an ensure uses to hand a spawned host its identity.
3
+ *
4
+ * They live in their own dependency-free module because the lifecycle supervisor needs them and
5
+ * nothing else from `protocol-identity.ts`, whose launch-profile parsing imports the CLI argument
6
+ * parser and, through it, the whole provider catalog. A supervisor runs once per task shard and
7
+ * Desktop thread host, so that graph was resident in every one of them.
8
+ */
9
+ /**
10
+ * Generation of this host within its daemon directory, handed to it by the ensure call
11
+ * that spawned it (the daemon settings travel to the host through its environment).
12
+ * Absent - a bare host nobody ensured - is generation 0.
13
+ */
14
+ export declare const HOST_GENERATION_ENV = "SENPI_RPC_HOST_GENERATION";
15
+ /**
16
+ * Identity of the host being spawned, chosen by the ensure that spawns it so the daemon directory
17
+ * can hold that generation's state before the process exists. A host nobody ensured names itself.
18
+ */
19
+ export declare const HOST_INSTANCE_ID_ENV = "SENPI_RPC_HOST_INSTANCE_ID";
20
+ //# sourceMappingURL=host-identity-env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-identity-env.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/host-identity-env.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,8BAA8B,CAAC;AAE/D;;;GAGG;AACH,eAAO,MAAM,oBAAoB,+BAA+B,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The environment names an ensure uses to hand a spawned host its identity.
3
+ *
4
+ * They live in their own dependency-free module because the lifecycle supervisor needs them and
5
+ * nothing else from `protocol-identity.ts`, whose launch-profile parsing imports the CLI argument
6
+ * parser and, through it, the whole provider catalog. A supervisor runs once per task shard and
7
+ * Desktop thread host, so that graph was resident in every one of them.
8
+ */
9
+ /**
10
+ * Generation of this host within its daemon directory, handed to it by the ensure call
11
+ * that spawned it (the daemon settings travel to the host through its environment).
12
+ * Absent - a bare host nobody ensured - is generation 0.
13
+ */
14
+ export const HOST_GENERATION_ENV = "SENPI_RPC_HOST_GENERATION";
15
+ /**
16
+ * Identity of the host being spawned, chosen by the ensure that spawns it so the daemon directory
17
+ * can hold that generation's state before the process exists. A host nobody ensured names itself.
18
+ */
19
+ export const HOST_INSTANCE_ID_ENV = "SENPI_RPC_HOST_INSTANCE_ID";
20
+ //# sourceMappingURL=host-identity-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-identity-env.js","sourceRoot":"","sources":["../../../src/modes/rpc/host-identity-env.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,2BAA2B,CAAC;AAE/D;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,4BAA4B,CAAC","sourcesContent":["/**\n * The environment names an ensure uses to hand a spawned host its identity.\n *\n * They live in their own dependency-free module because the lifecycle supervisor needs them and\n * nothing else from `protocol-identity.ts`, whose launch-profile parsing imports the CLI argument\n * parser and, through it, the whole provider catalog. A supervisor runs once per task shard and\n * Desktop thread host, so that graph was resident in every one of them.\n */\n\n/**\n * Generation of this host within its daemon directory, handed to it by the ensure call\n * that spawned it (the daemon settings travel to the host through its environment).\n * Absent - a bare host nobody ensured - is generation 0.\n */\nexport const HOST_GENERATION_ENV = \"SENPI_RPC_HOST_GENERATION\";\n\n/**\n * Identity of the host being spawned, chosen by the ensure that spawns it so the daemon directory\n * can hold that generation's state before the process exists. A host nobody ensured names itself.\n */\nexport const HOST_INSTANCE_ID_ENV = \"SENPI_RPC_HOST_INSTANCE_ID\";\n"]}
@@ -61,11 +61,11 @@ export { DEFAULT_HANDOFF_GRACE_MS, DEFAULT_HOST_IDLE_EXIT_MS, HANDOFF_GRACE_MS_E
61
61
  import { hostCrashCleanupPaths } from "./host-cleanup-paths.js";
62
62
  import { createHostDaemonPaths, generationPaths, HOST_DAEMON_DIR_ENV } from "./host-daemon-paths.js";
63
63
  import { releaseGeneration } from "./host-daemon-registration.js";
64
+ import { HOST_INSTANCE_ID_ENV } from "./host-identity-env.js";
64
65
  import { watchForSupersession } from "./host-supersession.js";
65
66
  import { HOST_CLEANUP_PATHS_ENV, HOST_PUBLIC_SOCKET_ENV, HOST_SCRATCH_DIR_ENV, HOST_WATCH_FD_ENV, HOST_WATCH_PPID_ENV, } from "./host-watchdog.js";
66
67
  import { attachJsonlLineReader, MAX_RPC_LINE_CHARACTERS } from "./jsonl.js";
67
68
  import { activeTurnsForIdleDecision, createObserverLink } from "./observer-link.js";
68
- import { HOST_INSTANCE_ID_ENV } from "./protocol-identity.js";
69
69
  import { MAX_SOCKET_PATH_BYTES, PUBLIC_SOCKET_IDENTITY_FILE, shieldSocketDuringClose, statSocketIdentity, unlinkOwnedSocket, writeSocketIdentityFile, } from "./socket-ownership.js";
70
70
  import { authenticateSocket, createSocketSecret, ensureSocketSecret, resolveSocketTransportAddress, SOCKET_SECRET_FILE_ENV, sendSocketHandshake, socketSecretPath, } from "./socket-transport.js";
71
71
  const CHILD_STOP_TIMEOUT_MS = 5_000;