@code-yeongyu/senpi 2026.5.29-4 → 2026.6.2

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 (121) hide show
  1. package/CHANGELOG.md +41 -1
  2. package/README.md +8 -2
  3. package/dist/cli/args.d.ts +1 -0
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +13 -0
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +9 -1
  9. package/dist/config.js.map +1 -1
  10. package/dist/core/agent-session.d.ts +5 -1
  11. package/dist/core/agent-session.d.ts.map +1 -1
  12. package/dist/core/agent-session.js +18 -2
  13. package/dist/core/agent-session.js.map +1 -1
  14. package/dist/core/compaction/branch-summarization.d.ts +3 -1
  15. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  16. package/dist/core/compaction/branch-summarization.js +9 -3
  17. package/dist/core/compaction/branch-summarization.js.map +1 -1
  18. package/dist/core/extensions/index.d.ts +1 -1
  19. package/dist/core/extensions/index.d.ts.map +1 -1
  20. package/dist/core/extensions/index.js.map +1 -1
  21. package/dist/core/extensions/runner.d.ts +4 -2
  22. package/dist/core/extensions/runner.d.ts.map +1 -1
  23. package/dist/core/extensions/runner.js +13 -1
  24. package/dist/core/extensions/runner.js.map +1 -1
  25. package/dist/core/extensions/types.d.ts +7 -1
  26. package/dist/core/extensions/types.d.ts.map +1 -1
  27. package/dist/core/extensions/types.js.map +1 -1
  28. package/dist/core/footer-data-provider.d.ts +2 -0
  29. package/dist/core/footer-data-provider.d.ts.map +1 -1
  30. package/dist/core/footer-data-provider.js +29 -1
  31. package/dist/core/footer-data-provider.js.map +1 -1
  32. package/dist/core/model-resolver.d.ts.map +1 -1
  33. package/dist/core/model-resolver.js +1 -0
  34. package/dist/core/model-resolver.js.map +1 -1
  35. package/dist/core/provider-attribution.d.ts +4 -0
  36. package/dist/core/provider-attribution.d.ts.map +1 -0
  37. package/dist/core/provider-attribution.js +73 -0
  38. package/dist/core/provider-attribution.js.map +1 -0
  39. package/dist/core/provider-display-names.d.ts.map +1 -1
  40. package/dist/core/provider-display-names.js +1 -0
  41. package/dist/core/provider-display-names.js.map +1 -1
  42. package/dist/core/sdk.d.ts.map +1 -1
  43. package/dist/core/sdk.js +8 -34
  44. package/dist/core/sdk.js.map +1 -1
  45. package/dist/core/session-manager.d.ts.map +1 -1
  46. package/dist/core/session-manager.js +92 -68
  47. package/dist/core/session-manager.js.map +1 -1
  48. package/dist/core/tools/edit.d.ts.map +1 -1
  49. package/dist/core/tools/edit.js +7 -10
  50. package/dist/core/tools/edit.js.map +1 -1
  51. package/dist/core/tools/find.d.ts.map +1 -1
  52. package/dist/core/tools/find.js.map +1 -1
  53. package/dist/core/tools/grep.d.ts.map +1 -1
  54. package/dist/core/tools/grep.js.map +1 -1
  55. package/dist/core/tools/ls.d.ts.map +1 -1
  56. package/dist/core/tools/ls.js +5 -7
  57. package/dist/core/tools/ls.js.map +1 -1
  58. package/dist/core/tools/read.d.ts.map +1 -1
  59. package/dist/core/tools/read.js +6 -7
  60. package/dist/core/tools/read.js.map +1 -1
  61. package/dist/core/tools/render-utils.d.ts +5 -2
  62. package/dist/core/tools/render-utils.d.ts.map +1 -1
  63. package/dist/core/tools/render-utils.js +17 -1
  64. package/dist/core/tools/render-utils.js.map +1 -1
  65. package/dist/core/tools/write.d.ts.map +1 -1
  66. package/dist/core/tools/write.js +5 -6
  67. package/dist/core/tools/write.js.map +1 -1
  68. package/dist/index.d.ts +2 -0
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +2 -0
  71. package/dist/index.js.map +1 -1
  72. package/dist/main.d.ts.map +1 -1
  73. package/dist/main.js +8 -0
  74. package/dist/main.js.map +1 -1
  75. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  76. package/dist/modes/interactive/components/tool-execution.js +25 -1
  77. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  78. package/dist/modes/interactive/interactive-mode.d.ts +3 -0
  79. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  80. package/dist/modes/interactive/interactive-mode.js +39 -0
  81. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  82. package/dist/modes/print-mode.d.ts.map +1 -1
  83. package/dist/modes/print-mode.js +1 -0
  84. package/dist/modes/print-mode.js.map +1 -1
  85. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  86. package/dist/modes/rpc/rpc-mode.js +1 -0
  87. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  88. package/docs/extensions.md +35 -11
  89. package/docs/providers.md +2 -0
  90. package/docs/quickstart.md +1 -0
  91. package/docs/rpc.md +3 -2
  92. package/docs/session-format.md +1 -1
  93. package/docs/sessions.md +8 -0
  94. package/docs/settings.md +1 -1
  95. package/docs/terminal-setup.md +2 -0
  96. package/docs/tui.md +12 -3
  97. package/docs/usage.md +6 -1
  98. package/examples/extensions/custom-header.ts +1 -1
  99. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  100. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  101. package/examples/extensions/custom-provider-gitlab-duo/index.ts +53 -2
  102. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  103. package/examples/extensions/doom-overlay/index.ts +1 -1
  104. package/examples/extensions/handoff.ts +1 -1
  105. package/examples/extensions/interactive-shell.ts +1 -1
  106. package/examples/extensions/overlay-qa-tests.ts +152 -81
  107. package/examples/extensions/qna.ts +1 -1
  108. package/examples/extensions/question.ts +1 -1
  109. package/examples/extensions/questionnaire.ts +1 -1
  110. package/examples/extensions/sandbox/package-lock.json +2 -2
  111. package/examples/extensions/sandbox/package.json +1 -1
  112. package/examples/extensions/snake.ts +1 -1
  113. package/examples/extensions/space-invaders.ts +1 -1
  114. package/examples/extensions/summarize.ts +1 -1
  115. package/examples/extensions/tic-tac-toe.ts +1 -1
  116. package/examples/extensions/todo.ts +1 -1
  117. package/examples/extensions/tools.ts +5 -0
  118. package/examples/extensions/with-deps/package-lock.json +2 -2
  119. package/examples/extensions/with-deps/package.json +1 -1
  120. package/npm-shrinkwrap.json +12 -12
  121. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"print-mode.d.ts","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAoB,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAK5E;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,yEAAyE;IACzE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,wDAAwD;IACxD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8CAA8C;IAC9C,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,mBAAmB,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiI/G","sourcesContent":["/**\n * Print mode (single-shot): Send prompts, output result, exit.\n *\n * Used for:\n * - `pi -p \"prompt\"` - text output\n * - `senpi --mode json \"prompt\"` - JSON event stream\n */\n\nimport type { AssistantMessage, ImageContent } from \"@earendil-works/pi-ai\";\nimport type { AgentSessionRuntime } from \"../core/agent-session-runtime.ts\";\nimport { flushRawStdout, writeRawStdout } from \"../core/output-guard.ts\";\nimport { killTrackedDetachedChildren } from \"../utils/shell.ts\";\nimport { formatProviderNativeBody, formatProviderNativeSummary } from \"./provider-native-rendering.ts\";\n\n/**\n * Options for print mode.\n */\nexport interface PrintModeOptions {\n\t/** Output mode: \"text\" for final response only, \"json\" for all events */\n\tmode: \"text\" | \"json\";\n\t/** Array of additional prompts to send after initialMessage */\n\tmessages?: string[];\n\t/** First message to send (may contain @file content) */\n\tinitialMessage?: string;\n\t/** Images to attach to the initial message */\n\tinitialImages?: ImageContent[];\n}\n\n/**\n * Run in print (single-shot) mode.\n * Sends prompts to the agent and outputs the result.\n */\nexport async function runPrintMode(runtimeHost: AgentSessionRuntime, options: PrintModeOptions): Promise<number> {\n\tconst { mode, messages = [], initialMessage, initialImages } = options;\n\tlet exitCode = 0;\n\tlet session = runtimeHost.session;\n\tlet unsubscribe: (() => void) | undefined;\n\tlet disposed = false;\n\tconst signalCleanupHandlers: Array<() => void> = [];\n\n\tconst disposeRuntime = async (): Promise<void> => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tunsubscribe?.();\n\t\tawait runtimeHost.dispose();\n\t};\n\n\tconst registerSignalHandlers = (): void => {\n\t\tconst signals: NodeJS.Signals[] = [\"SIGTERM\"];\n\t\tif (process.platform !== \"win32\") {\n\t\t\tsignals.push(\"SIGHUP\");\n\t\t}\n\n\t\tfor (const signal of signals) {\n\t\t\tconst handler = () => {\n\t\t\t\tkillTrackedDetachedChildren();\n\t\t\t\tvoid disposeRuntime().finally(() => {\n\t\t\t\t\tprocess.exit(signal === \"SIGHUP\" ? 129 : 143);\n\t\t\t\t});\n\t\t\t};\n\t\t\tprocess.on(signal, handler);\n\t\t\tsignalCleanupHandlers.push(() => process.off(signal, handler));\n\t\t}\n\t};\n\n\tregisterSignalHandlers();\n\n\truntimeHost.setRebindSession(async () => {\n\t\tawait rebindSession();\n\t});\n\n\tconst rebindSession = async (): Promise<void> => {\n\t\tsession = runtimeHost.session;\n\t\tawait session.bindExtensions({\n\t\t\tcommandContextActions: {\n\t\t\t\twaitForIdle: () => session.agent.waitForIdle(),\n\t\t\t\tnewSession: async (newSessionOptions) => runtimeHost.newSession(newSessionOptions),\n\t\t\t\tfork: async (entryId, forkOptions) => {\n\t\t\t\t\tconst result = await runtimeHost.fork(entryId, forkOptions);\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tnavigateTree: async (targetId, navigateOptions) => {\n\t\t\t\t\tconst result = await session.navigateTree(targetId, {\n\t\t\t\t\t\tsummarize: navigateOptions?.summarize,\n\t\t\t\t\t\tcustomInstructions: navigateOptions?.customInstructions,\n\t\t\t\t\t\treplaceInstructions: navigateOptions?.replaceInstructions,\n\t\t\t\t\t\tlabel: navigateOptions?.label,\n\t\t\t\t\t});\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tswitchSession: async (sessionPath, switchOptions) => {\n\t\t\t\t\treturn runtimeHost.switchSession(sessionPath, switchOptions);\n\t\t\t\t},\n\t\t\t\treload: async () => {\n\t\t\t\t\tawait session.reload();\n\t\t\t\t},\n\t\t\t},\n\t\t\tonError: (err) => {\n\t\t\t\tconsole.error(`Extension error (${err.extensionPath}): ${err.error}`);\n\t\t\t},\n\t\t});\n\n\t\tunsubscribe?.();\n\t\tunsubscribe = session.subscribe((event) => {\n\t\t\tif (mode === \"json\") {\n\t\t\t\twriteRawStdout(`${JSON.stringify(event)}\\n`);\n\t\t\t}\n\t\t});\n\t};\n\n\ttry {\n\t\tif (mode === \"json\") {\n\t\t\tconst header = session.sessionManager.getHeader();\n\t\t\tif (header) {\n\t\t\t\twriteRawStdout(`${JSON.stringify(header)}\\n`);\n\t\t\t}\n\t\t}\n\n\t\tawait rebindSession();\n\n\t\tif (initialMessage) {\n\t\t\tawait session.prompt(initialMessage, { images: initialImages });\n\t\t}\n\n\t\tfor (const message of messages) {\n\t\t\tawait session.prompt(message);\n\t\t}\n\n\t\tif (mode === \"text\") {\n\t\t\tconst state = session.state;\n\t\t\tconst lastMessage = state.messages[state.messages.length - 1];\n\n\t\t\tif (lastMessage?.role === \"assistant\") {\n\t\t\t\tconst assistantMsg = lastMessage as AssistantMessage;\n\t\t\t\tif (assistantMsg.stopReason === \"error\" || assistantMsg.stopReason === \"aborted\") {\n\t\t\t\t\tconsole.error(assistantMsg.errorMessage || `Request ${assistantMsg.stopReason}`);\n\t\t\t\t\texitCode = 1;\n\t\t\t\t} else {\n\t\t\t\t\tfor (const content of assistantMsg.content) {\n\t\t\t\t\t\tif (content.type === \"text\") {\n\t\t\t\t\t\t\twriteRawStdout(`${content.text}\\n`);\n\t\t\t\t\t\t} else if (content.type === \"providerNative\") {\n\t\t\t\t\t\t\twriteRawStdout(`${formatProviderNativeSummary(assistantMsg, content, false)}\\n`);\n\t\t\t\t\t\t\twriteRawStdout(`${formatProviderNativeBody(content, false)}\\n`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn exitCode;\n\t} catch (error: unknown) {\n\t\tconsole.error(error instanceof Error ? error.message : String(error));\n\t\treturn 1;\n\t} finally {\n\t\tfor (const cleanup of signalCleanupHandlers) {\n\t\t\tcleanup();\n\t\t}\n\t\tawait disposeRuntime();\n\t\tawait flushRawStdout();\n\t}\n}\n"]}
1
+ {"version":3,"file":"print-mode.d.ts","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAoB,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAK5E;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,yEAAyE;IACzE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,wDAAwD;IACxD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8CAA8C;IAC9C,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,mBAAmB,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAkI/G","sourcesContent":["/**\n * Print mode (single-shot): Send prompts, output result, exit.\n *\n * Used for:\n * - `pi -p \"prompt\"` - text output\n * - `senpi --mode json \"prompt\"` - JSON event stream\n */\n\nimport type { AssistantMessage, ImageContent } from \"@earendil-works/pi-ai\";\nimport type { AgentSessionRuntime } from \"../core/agent-session-runtime.ts\";\nimport { flushRawStdout, writeRawStdout } from \"../core/output-guard.ts\";\nimport { killTrackedDetachedChildren } from \"../utils/shell.ts\";\nimport { formatProviderNativeBody, formatProviderNativeSummary } from \"./provider-native-rendering.ts\";\n\n/**\n * Options for print mode.\n */\nexport interface PrintModeOptions {\n\t/** Output mode: \"text\" for final response only, \"json\" for all events */\n\tmode: \"text\" | \"json\";\n\t/** Array of additional prompts to send after initialMessage */\n\tmessages?: string[];\n\t/** First message to send (may contain @file content) */\n\tinitialMessage?: string;\n\t/** Images to attach to the initial message */\n\tinitialImages?: ImageContent[];\n}\n\n/**\n * Run in print (single-shot) mode.\n * Sends prompts to the agent and outputs the result.\n */\nexport async function runPrintMode(runtimeHost: AgentSessionRuntime, options: PrintModeOptions): Promise<number> {\n\tconst { mode, messages = [], initialMessage, initialImages } = options;\n\tlet exitCode = 0;\n\tlet session = runtimeHost.session;\n\tlet unsubscribe: (() => void) | undefined;\n\tlet disposed = false;\n\tconst signalCleanupHandlers: Array<() => void> = [];\n\n\tconst disposeRuntime = async (): Promise<void> => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tunsubscribe?.();\n\t\tawait runtimeHost.dispose();\n\t};\n\n\tconst registerSignalHandlers = (): void => {\n\t\tconst signals: NodeJS.Signals[] = [\"SIGTERM\"];\n\t\tif (process.platform !== \"win32\") {\n\t\t\tsignals.push(\"SIGHUP\");\n\t\t}\n\n\t\tfor (const signal of signals) {\n\t\t\tconst handler = () => {\n\t\t\t\tkillTrackedDetachedChildren();\n\t\t\t\tvoid disposeRuntime().finally(() => {\n\t\t\t\t\tprocess.exit(signal === \"SIGHUP\" ? 129 : 143);\n\t\t\t\t});\n\t\t\t};\n\t\t\tprocess.on(signal, handler);\n\t\t\tsignalCleanupHandlers.push(() => process.off(signal, handler));\n\t\t}\n\t};\n\n\tregisterSignalHandlers();\n\n\truntimeHost.setRebindSession(async () => {\n\t\tawait rebindSession();\n\t});\n\n\tconst rebindSession = async (): Promise<void> => {\n\t\tsession = runtimeHost.session;\n\t\tawait session.bindExtensions({\n\t\t\tmode: mode === \"json\" ? \"json\" : \"print\",\n\t\t\tcommandContextActions: {\n\t\t\t\twaitForIdle: () => session.agent.waitForIdle(),\n\t\t\t\tnewSession: async (newSessionOptions) => runtimeHost.newSession(newSessionOptions),\n\t\t\t\tfork: async (entryId, forkOptions) => {\n\t\t\t\t\tconst result = await runtimeHost.fork(entryId, forkOptions);\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tnavigateTree: async (targetId, navigateOptions) => {\n\t\t\t\t\tconst result = await session.navigateTree(targetId, {\n\t\t\t\t\t\tsummarize: navigateOptions?.summarize,\n\t\t\t\t\t\tcustomInstructions: navigateOptions?.customInstructions,\n\t\t\t\t\t\treplaceInstructions: navigateOptions?.replaceInstructions,\n\t\t\t\t\t\tlabel: navigateOptions?.label,\n\t\t\t\t\t});\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tswitchSession: async (sessionPath, switchOptions) => {\n\t\t\t\t\treturn runtimeHost.switchSession(sessionPath, switchOptions);\n\t\t\t\t},\n\t\t\t\treload: async () => {\n\t\t\t\t\tawait session.reload();\n\t\t\t\t},\n\t\t\t},\n\t\t\tonError: (err) => {\n\t\t\t\tconsole.error(`Extension error (${err.extensionPath}): ${err.error}`);\n\t\t\t},\n\t\t});\n\n\t\tunsubscribe?.();\n\t\tunsubscribe = session.subscribe((event) => {\n\t\t\tif (mode === \"json\") {\n\t\t\t\twriteRawStdout(`${JSON.stringify(event)}\\n`);\n\t\t\t}\n\t\t});\n\t};\n\n\ttry {\n\t\tif (mode === \"json\") {\n\t\t\tconst header = session.sessionManager.getHeader();\n\t\t\tif (header) {\n\t\t\t\twriteRawStdout(`${JSON.stringify(header)}\\n`);\n\t\t\t}\n\t\t}\n\n\t\tawait rebindSession();\n\n\t\tif (initialMessage) {\n\t\t\tawait session.prompt(initialMessage, { images: initialImages });\n\t\t}\n\n\t\tfor (const message of messages) {\n\t\t\tawait session.prompt(message);\n\t\t}\n\n\t\tif (mode === \"text\") {\n\t\t\tconst state = session.state;\n\t\t\tconst lastMessage = state.messages[state.messages.length - 1];\n\n\t\t\tif (lastMessage?.role === \"assistant\") {\n\t\t\t\tconst assistantMsg = lastMessage as AssistantMessage;\n\t\t\t\tif (assistantMsg.stopReason === \"error\" || assistantMsg.stopReason === \"aborted\") {\n\t\t\t\t\tconsole.error(assistantMsg.errorMessage || `Request ${assistantMsg.stopReason}`);\n\t\t\t\t\texitCode = 1;\n\t\t\t\t} else {\n\t\t\t\t\tfor (const content of assistantMsg.content) {\n\t\t\t\t\t\tif (content.type === \"text\") {\n\t\t\t\t\t\t\twriteRawStdout(`${content.text}\\n`);\n\t\t\t\t\t\t} else if (content.type === \"providerNative\") {\n\t\t\t\t\t\t\twriteRawStdout(`${formatProviderNativeSummary(assistantMsg, content, false)}\\n`);\n\t\t\t\t\t\t\twriteRawStdout(`${formatProviderNativeBody(content, false)}\\n`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn exitCode;\n\t} catch (error: unknown) {\n\t\tconsole.error(error instanceof Error ? error.message : String(error));\n\t\treturn 1;\n\t} finally {\n\t\tfor (const cleanup of signalCleanupHandlers) {\n\t\t\tcleanup();\n\t\t}\n\t\tawait disposeRuntime();\n\t\tawait flushRawStdout();\n\t}\n}\n"]}
@@ -49,6 +49,7 @@ export async function runPrintMode(runtimeHost, options) {
49
49
  const rebindSession = async () => {
50
50
  session = runtimeHost.session;
51
51
  await session.bindExtensions({
52
+ mode: mode === "json" ? "json" : "print",
52
53
  commandContextActions: {
53
54
  waitForIdle: () => session.agent.waitForIdle(),
54
55
  newSession: async (newSessionOptions) => runtimeHost.newSession(newSessionOptions),
@@ -1 +1 @@
1
- {"version":3,"file":"print-mode.js","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Print mode (single-shot): Send prompts, output result, exit.\n *\n * Used for:\n * - `pi -p \"prompt\"` - text output\n * - `senpi --mode json \"prompt\"` - JSON event stream\n */\n\nimport type { AssistantMessage, ImageContent } from \"@earendil-works/pi-ai\";\nimport type { AgentSessionRuntime } from \"../core/agent-session-runtime.ts\";\nimport { flushRawStdout, writeRawStdout } from \"../core/output-guard.ts\";\nimport { killTrackedDetachedChildren } from \"../utils/shell.ts\";\nimport { formatProviderNativeBody, formatProviderNativeSummary } from \"./provider-native-rendering.ts\";\n\n/**\n * Options for print mode.\n */\nexport interface PrintModeOptions {\n\t/** Output mode: \"text\" for final response only, \"json\" for all events */\n\tmode: \"text\" | \"json\";\n\t/** Array of additional prompts to send after initialMessage */\n\tmessages?: string[];\n\t/** First message to send (may contain @file content) */\n\tinitialMessage?: string;\n\t/** Images to attach to the initial message */\n\tinitialImages?: ImageContent[];\n}\n\n/**\n * Run in print (single-shot) mode.\n * Sends prompts to the agent and outputs the result.\n */\nexport async function runPrintMode(runtimeHost: AgentSessionRuntime, options: PrintModeOptions): Promise<number> {\n\tconst { mode, messages = [], initialMessage, initialImages } = options;\n\tlet exitCode = 0;\n\tlet session = runtimeHost.session;\n\tlet unsubscribe: (() => void) | undefined;\n\tlet disposed = false;\n\tconst signalCleanupHandlers: Array<() => void> = [];\n\n\tconst disposeRuntime = async (): Promise<void> => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tunsubscribe?.();\n\t\tawait runtimeHost.dispose();\n\t};\n\n\tconst registerSignalHandlers = (): void => {\n\t\tconst signals: NodeJS.Signals[] = [\"SIGTERM\"];\n\t\tif (process.platform !== \"win32\") {\n\t\t\tsignals.push(\"SIGHUP\");\n\t\t}\n\n\t\tfor (const signal of signals) {\n\t\t\tconst handler = () => {\n\t\t\t\tkillTrackedDetachedChildren();\n\t\t\t\tvoid disposeRuntime().finally(() => {\n\t\t\t\t\tprocess.exit(signal === \"SIGHUP\" ? 129 : 143);\n\t\t\t\t});\n\t\t\t};\n\t\t\tprocess.on(signal, handler);\n\t\t\tsignalCleanupHandlers.push(() => process.off(signal, handler));\n\t\t}\n\t};\n\n\tregisterSignalHandlers();\n\n\truntimeHost.setRebindSession(async () => {\n\t\tawait rebindSession();\n\t});\n\n\tconst rebindSession = async (): Promise<void> => {\n\t\tsession = runtimeHost.session;\n\t\tawait session.bindExtensions({\n\t\t\tcommandContextActions: {\n\t\t\t\twaitForIdle: () => session.agent.waitForIdle(),\n\t\t\t\tnewSession: async (newSessionOptions) => runtimeHost.newSession(newSessionOptions),\n\t\t\t\tfork: async (entryId, forkOptions) => {\n\t\t\t\t\tconst result = await runtimeHost.fork(entryId, forkOptions);\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tnavigateTree: async (targetId, navigateOptions) => {\n\t\t\t\t\tconst result = await session.navigateTree(targetId, {\n\t\t\t\t\t\tsummarize: navigateOptions?.summarize,\n\t\t\t\t\t\tcustomInstructions: navigateOptions?.customInstructions,\n\t\t\t\t\t\treplaceInstructions: navigateOptions?.replaceInstructions,\n\t\t\t\t\t\tlabel: navigateOptions?.label,\n\t\t\t\t\t});\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tswitchSession: async (sessionPath, switchOptions) => {\n\t\t\t\t\treturn runtimeHost.switchSession(sessionPath, switchOptions);\n\t\t\t\t},\n\t\t\t\treload: async () => {\n\t\t\t\t\tawait session.reload();\n\t\t\t\t},\n\t\t\t},\n\t\t\tonError: (err) => {\n\t\t\t\tconsole.error(`Extension error (${err.extensionPath}): ${err.error}`);\n\t\t\t},\n\t\t});\n\n\t\tunsubscribe?.();\n\t\tunsubscribe = session.subscribe((event) => {\n\t\t\tif (mode === \"json\") {\n\t\t\t\twriteRawStdout(`${JSON.stringify(event)}\\n`);\n\t\t\t}\n\t\t});\n\t};\n\n\ttry {\n\t\tif (mode === \"json\") {\n\t\t\tconst header = session.sessionManager.getHeader();\n\t\t\tif (header) {\n\t\t\t\twriteRawStdout(`${JSON.stringify(header)}\\n`);\n\t\t\t}\n\t\t}\n\n\t\tawait rebindSession();\n\n\t\tif (initialMessage) {\n\t\t\tawait session.prompt(initialMessage, { images: initialImages });\n\t\t}\n\n\t\tfor (const message of messages) {\n\t\t\tawait session.prompt(message);\n\t\t}\n\n\t\tif (mode === \"text\") {\n\t\t\tconst state = session.state;\n\t\t\tconst lastMessage = state.messages[state.messages.length - 1];\n\n\t\t\tif (lastMessage?.role === \"assistant\") {\n\t\t\t\tconst assistantMsg = lastMessage as AssistantMessage;\n\t\t\t\tif (assistantMsg.stopReason === \"error\" || assistantMsg.stopReason === \"aborted\") {\n\t\t\t\t\tconsole.error(assistantMsg.errorMessage || `Request ${assistantMsg.stopReason}`);\n\t\t\t\t\texitCode = 1;\n\t\t\t\t} else {\n\t\t\t\t\tfor (const content of assistantMsg.content) {\n\t\t\t\t\t\tif (content.type === \"text\") {\n\t\t\t\t\t\t\twriteRawStdout(`${content.text}\\n`);\n\t\t\t\t\t\t} else if (content.type === \"providerNative\") {\n\t\t\t\t\t\t\twriteRawStdout(`${formatProviderNativeSummary(assistantMsg, content, false)}\\n`);\n\t\t\t\t\t\t\twriteRawStdout(`${formatProviderNativeBody(content, false)}\\n`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn exitCode;\n\t} catch (error: unknown) {\n\t\tconsole.error(error instanceof Error ? error.message : String(error));\n\t\treturn 1;\n\t} finally {\n\t\tfor (const cleanup of signalCleanupHandlers) {\n\t\t\tcleanup();\n\t\t}\n\t\tawait disposeRuntime();\n\t\tawait flushRawStdout();\n\t}\n}\n"]}
1
+ {"version":3,"file":"print-mode.js","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Print mode (single-shot): Send prompts, output result, exit.\n *\n * Used for:\n * - `pi -p \"prompt\"` - text output\n * - `senpi --mode json \"prompt\"` - JSON event stream\n */\n\nimport type { AssistantMessage, ImageContent } from \"@earendil-works/pi-ai\";\nimport type { AgentSessionRuntime } from \"../core/agent-session-runtime.ts\";\nimport { flushRawStdout, writeRawStdout } from \"../core/output-guard.ts\";\nimport { killTrackedDetachedChildren } from \"../utils/shell.ts\";\nimport { formatProviderNativeBody, formatProviderNativeSummary } from \"./provider-native-rendering.ts\";\n\n/**\n * Options for print mode.\n */\nexport interface PrintModeOptions {\n\t/** Output mode: \"text\" for final response only, \"json\" for all events */\n\tmode: \"text\" | \"json\";\n\t/** Array of additional prompts to send after initialMessage */\n\tmessages?: string[];\n\t/** First message to send (may contain @file content) */\n\tinitialMessage?: string;\n\t/** Images to attach to the initial message */\n\tinitialImages?: ImageContent[];\n}\n\n/**\n * Run in print (single-shot) mode.\n * Sends prompts to the agent and outputs the result.\n */\nexport async function runPrintMode(runtimeHost: AgentSessionRuntime, options: PrintModeOptions): Promise<number> {\n\tconst { mode, messages = [], initialMessage, initialImages } = options;\n\tlet exitCode = 0;\n\tlet session = runtimeHost.session;\n\tlet unsubscribe: (() => void) | undefined;\n\tlet disposed = false;\n\tconst signalCleanupHandlers: Array<() => void> = [];\n\n\tconst disposeRuntime = async (): Promise<void> => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tunsubscribe?.();\n\t\tawait runtimeHost.dispose();\n\t};\n\n\tconst registerSignalHandlers = (): void => {\n\t\tconst signals: NodeJS.Signals[] = [\"SIGTERM\"];\n\t\tif (process.platform !== \"win32\") {\n\t\t\tsignals.push(\"SIGHUP\");\n\t\t}\n\n\t\tfor (const signal of signals) {\n\t\t\tconst handler = () => {\n\t\t\t\tkillTrackedDetachedChildren();\n\t\t\t\tvoid disposeRuntime().finally(() => {\n\t\t\t\t\tprocess.exit(signal === \"SIGHUP\" ? 129 : 143);\n\t\t\t\t});\n\t\t\t};\n\t\t\tprocess.on(signal, handler);\n\t\t\tsignalCleanupHandlers.push(() => process.off(signal, handler));\n\t\t}\n\t};\n\n\tregisterSignalHandlers();\n\n\truntimeHost.setRebindSession(async () => {\n\t\tawait rebindSession();\n\t});\n\n\tconst rebindSession = async (): Promise<void> => {\n\t\tsession = runtimeHost.session;\n\t\tawait session.bindExtensions({\n\t\t\tmode: mode === \"json\" ? \"json\" : \"print\",\n\t\t\tcommandContextActions: {\n\t\t\t\twaitForIdle: () => session.agent.waitForIdle(),\n\t\t\t\tnewSession: async (newSessionOptions) => runtimeHost.newSession(newSessionOptions),\n\t\t\t\tfork: async (entryId, forkOptions) => {\n\t\t\t\t\tconst result = await runtimeHost.fork(entryId, forkOptions);\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tnavigateTree: async (targetId, navigateOptions) => {\n\t\t\t\t\tconst result = await session.navigateTree(targetId, {\n\t\t\t\t\t\tsummarize: navigateOptions?.summarize,\n\t\t\t\t\t\tcustomInstructions: navigateOptions?.customInstructions,\n\t\t\t\t\t\treplaceInstructions: navigateOptions?.replaceInstructions,\n\t\t\t\t\t\tlabel: navigateOptions?.label,\n\t\t\t\t\t});\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tswitchSession: async (sessionPath, switchOptions) => {\n\t\t\t\t\treturn runtimeHost.switchSession(sessionPath, switchOptions);\n\t\t\t\t},\n\t\t\t\treload: async () => {\n\t\t\t\t\tawait session.reload();\n\t\t\t\t},\n\t\t\t},\n\t\t\tonError: (err) => {\n\t\t\t\tconsole.error(`Extension error (${err.extensionPath}): ${err.error}`);\n\t\t\t},\n\t\t});\n\n\t\tunsubscribe?.();\n\t\tunsubscribe = session.subscribe((event) => {\n\t\t\tif (mode === \"json\") {\n\t\t\t\twriteRawStdout(`${JSON.stringify(event)}\\n`);\n\t\t\t}\n\t\t});\n\t};\n\n\ttry {\n\t\tif (mode === \"json\") {\n\t\t\tconst header = session.sessionManager.getHeader();\n\t\t\tif (header) {\n\t\t\t\twriteRawStdout(`${JSON.stringify(header)}\\n`);\n\t\t\t}\n\t\t}\n\n\t\tawait rebindSession();\n\n\t\tif (initialMessage) {\n\t\t\tawait session.prompt(initialMessage, { images: initialImages });\n\t\t}\n\n\t\tfor (const message of messages) {\n\t\t\tawait session.prompt(message);\n\t\t}\n\n\t\tif (mode === \"text\") {\n\t\t\tconst state = session.state;\n\t\t\tconst lastMessage = state.messages[state.messages.length - 1];\n\n\t\t\tif (lastMessage?.role === \"assistant\") {\n\t\t\t\tconst assistantMsg = lastMessage as AssistantMessage;\n\t\t\t\tif (assistantMsg.stopReason === \"error\" || assistantMsg.stopReason === \"aborted\") {\n\t\t\t\t\tconsole.error(assistantMsg.errorMessage || `Request ${assistantMsg.stopReason}`);\n\t\t\t\t\texitCode = 1;\n\t\t\t\t} else {\n\t\t\t\t\tfor (const content of assistantMsg.content) {\n\t\t\t\t\t\tif (content.type === \"text\") {\n\t\t\t\t\t\t\twriteRawStdout(`${content.text}\\n`);\n\t\t\t\t\t\t} else if (content.type === \"providerNative\") {\n\t\t\t\t\t\t\twriteRawStdout(`${formatProviderNativeSummary(assistantMsg, content, false)}\\n`);\n\t\t\t\t\t\t\twriteRawStdout(`${formatProviderNativeBody(content, false)}\\n`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn exitCode;\n\t} catch (error: unknown) {\n\t\tconsole.error(error instanceof Error ? error.message : String(error));\n\t\treturn 1;\n\t} finally {\n\t\tfor (const cleanup of signalCleanupHandlers) {\n\t\t\tcleanup();\n\t\t}\n\t\tawait disposeRuntime();\n\t\tawait flushRawStdout();\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"rpc-mode.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/rpc-mode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AA0B/E,YAAY,EACX,UAAU,EACV,qBAAqB,EACrB,sBAAsB,EACtB,WAAW,EACX,eAAe,GACf,MAAM,gBAAgB,CAAC;AAExB;;;GAGG;AACH,wBAAsB,UAAU,CAAC,WAAW,EAAE,mBAAmB,GAAG,OAAO,CAAC,KAAK,CAAC,CAgtBjF","sourcesContent":["/**\n * RPC mode: Headless operation with JSON stdin/stdout protocol.\n *\n * Used for embedding the agent in other applications.\n * Receives commands as JSON on stdin, outputs events and responses as JSON on stdout.\n *\n * Protocol:\n * - Commands: JSON objects with `type` field, optional `id` for correlation\n * - Responses: JSON objects with `type: \"response\"`, `command`, `success`, and optional `data`/`error`\n * - Events: AgentSessionEvent objects streamed as they occur\n * - Extension UI: Extension UI requests are emitted, client responds with extension_ui_response\n */\n\nimport * as crypto from \"node:crypto\";\nimport type { AgentSessionRuntime } from \"../../core/agent-session-runtime.ts\";\nimport type {\n\tExtensionUIContext,\n\tExtensionUIDialogOptions,\n\tExtensionWidgetOptions,\n\tWorkingIndicatorOptions,\n} from \"../../core/extensions/index.ts\";\nimport {\n\tflushRawStdout,\n\ttakeOverStdout,\n\twaitForRawStdoutBackpressure,\n\twriteRawStdout,\n} from \"../../core/output-guard.ts\";\nimport { killTrackedDetachedChildren } from \"../../utils/shell.ts\";\nimport { type Theme, theme } from \"../interactive/theme/theme.ts\";\nimport { attachJsonlLineReader, serializeJsonLine } from \"./jsonl.ts\";\nimport type {\n\tRpcCommand,\n\tRpcExtensionUIRequest,\n\tRpcExtensionUIResponse,\n\tRpcResponse,\n\tRpcSessionState,\n\tRpcSlashCommand,\n} from \"./rpc-types.ts\";\n\n// Re-export types for consumers\nexport type {\n\tRpcCommand,\n\tRpcExtensionUIRequest,\n\tRpcExtensionUIResponse,\n\tRpcResponse,\n\tRpcSessionState,\n} from \"./rpc-types.ts\";\n\n/**\n * Run in RPC mode.\n * Listens for JSON commands on stdin, outputs events and responses on stdout.\n */\nexport async function runRpcMode(runtimeHost: AgentSessionRuntime): Promise<never> {\n\ttakeOverStdout();\n\tlet session = runtimeHost.session;\n\tlet unsubscribe: (() => void) | undefined;\n\tlet unsubscribeBackpressure: (() => void) | undefined;\n\n\tconst output = (obj: RpcResponse | RpcExtensionUIRequest | object) => {\n\t\twriteRawStdout(serializeJsonLine(obj));\n\t};\n\n\tconst success = <T extends RpcCommand[\"type\"]>(\n\t\tid: string | undefined,\n\t\tcommand: T,\n\t\tdata?: object | null,\n\t): RpcResponse => {\n\t\tif (data === undefined) {\n\t\t\treturn { id, type: \"response\", command, success: true } as RpcResponse;\n\t\t}\n\t\treturn { id, type: \"response\", command, success: true, data } as RpcResponse;\n\t};\n\n\tconst error = (id: string | undefined, command: string, message: string): RpcResponse => {\n\t\treturn { id, type: \"response\", command, success: false, error: message };\n\t};\n\n\t// Pending extension UI requests waiting for response\n\tconst pendingExtensionRequests = new Map<\n\t\tstring,\n\t\t{ resolve: (value: any) => void; reject: (error: Error) => void }\n\t>();\n\n\t// Shutdown request flag\n\tlet shutdownRequested = false;\n\tlet shuttingDown = false;\n\tconst signalCleanupHandlers: Array<() => void> = [];\n\n\t/** Helper for dialog methods with signal/timeout support */\n\tfunction createDialogPromise<T>(\n\t\topts: ExtensionUIDialogOptions | undefined,\n\t\tdefaultValue: T,\n\t\trequest: Record<string, unknown>,\n\t\tparseResponse: (response: RpcExtensionUIResponse) => T,\n\t): Promise<T> {\n\t\tif (opts?.signal?.aborted) return Promise.resolve(defaultValue);\n\n\t\tconst id = crypto.randomUUID();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n\t\t\tconst cleanup = () => {\n\t\t\t\tif (timeoutId) clearTimeout(timeoutId);\n\t\t\t\topts?.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\tpendingExtensionRequests.delete(id);\n\t\t\t};\n\n\t\t\tconst onAbort = () => {\n\t\t\t\tcleanup();\n\t\t\t\tresolve(defaultValue);\n\t\t\t};\n\t\t\topts?.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\t\t\tif (opts?.timeout) {\n\t\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\t\tcleanup();\n\t\t\t\t\tresolve(defaultValue);\n\t\t\t\t}, opts.timeout);\n\t\t\t}\n\n\t\t\tpendingExtensionRequests.set(id, {\n\t\t\t\tresolve: (response: RpcExtensionUIResponse) => {\n\t\t\t\t\tcleanup();\n\t\t\t\t\tresolve(parseResponse(response));\n\t\t\t\t},\n\t\t\t\treject,\n\t\t\t});\n\t\t\toutput({ type: \"extension_ui_request\", id, ...request } as RpcExtensionUIRequest);\n\t\t});\n\t}\n\n\t/**\n\t * Create an extension UI context that uses the RPC protocol.\n\t */\n\tconst createExtensionUIContext = (): ExtensionUIContext => ({\n\t\tselect: (title, options, opts) =>\n\t\t\tcreateDialogPromise(opts, undefined, { method: \"select\", title, options, timeout: opts?.timeout }, (r) =>\n\t\t\t\t\"cancelled\" in r && r.cancelled ? undefined : \"value\" in r ? r.value : undefined,\n\t\t\t),\n\n\t\tconfirm: (title, message, opts) =>\n\t\t\tcreateDialogPromise(opts, false, { method: \"confirm\", title, message, timeout: opts?.timeout }, (r) =>\n\t\t\t\t\"cancelled\" in r && r.cancelled ? false : \"confirmed\" in r ? r.confirmed : false,\n\t\t\t),\n\n\t\tinput: (title, placeholder, opts) =>\n\t\t\tcreateDialogPromise(opts, undefined, { method: \"input\", title, placeholder, timeout: opts?.timeout }, (r) =>\n\t\t\t\t\"cancelled\" in r && r.cancelled ? undefined : \"value\" in r ? r.value : undefined,\n\t\t\t),\n\n\t\tnotify(message: string, type?: \"info\" | \"warning\" | \"error\"): void {\n\t\t\t// Fire and forget - no response needed\n\t\t\toutput({\n\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tmethod: \"notify\",\n\t\t\t\tmessage,\n\t\t\t\tnotifyType: type,\n\t\t\t} as RpcExtensionUIRequest);\n\t\t},\n\n\t\tonTerminalInput(): () => void {\n\t\t\t// Raw terminal input not supported in RPC mode\n\t\t\treturn () => {};\n\t\t},\n\n\t\tsetStatus(key: string, text: string | undefined): void {\n\t\t\t// Fire and forget - no response needed\n\t\t\toutput({\n\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tmethod: \"setStatus\",\n\t\t\t\tstatusKey: key,\n\t\t\t\tstatusText: text,\n\t\t\t} as RpcExtensionUIRequest);\n\t\t},\n\n\t\tsetWorkingMessage(_message?: string): void {\n\t\t\t// Working message not supported in RPC mode - requires TUI loader access\n\t\t},\n\n\t\tsetWorkingVisible(_visible: boolean): void {\n\t\t\t// Working visibility not supported in RPC mode - requires TUI loader access\n\t\t},\n\n\t\tsetWorkingIndicator(_options?: WorkingIndicatorOptions): void {\n\t\t\t// Working indicator customization not supported in RPC mode - requires TUI loader access\n\t\t},\n\n\t\tsetHiddenThinkingLabel(_label?: string): void {\n\t\t\t// Hidden thinking label not supported in RPC mode - requires TUI message rendering access\n\t\t},\n\n\t\tsetWidget(key: string, content: unknown, options?: ExtensionWidgetOptions): void {\n\t\t\t// Only support string arrays in RPC mode - factory functions are ignored\n\t\t\tif (content === undefined || Array.isArray(content)) {\n\t\t\t\toutput({\n\t\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\t\tmethod: \"setWidget\",\n\t\t\t\t\twidgetKey: key,\n\t\t\t\t\twidgetLines: content as string[] | undefined,\n\t\t\t\t\twidgetPlacement: options?.placement,\n\t\t\t\t} as RpcExtensionUIRequest);\n\t\t\t}\n\t\t\t// Component factories are not supported in RPC mode - would need TUI access\n\t\t},\n\n\t\tsetFooter(_factory: unknown): void {\n\t\t\t// Custom footer not supported in RPC mode - requires TUI access\n\t\t},\n\n\t\tsetHeader(_factory: unknown): void {\n\t\t\t// Custom header not supported in RPC mode - requires TUI access\n\t\t},\n\n\t\tsetTitle(title: string): void {\n\t\t\t// Fire and forget - host can implement terminal title control\n\t\t\toutput({\n\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tmethod: \"setTitle\",\n\t\t\t\ttitle,\n\t\t\t} as RpcExtensionUIRequest);\n\t\t},\n\n\t\tasync custom() {\n\t\t\t// Custom UI not supported in RPC mode\n\t\t\treturn undefined as never;\n\t\t},\n\n\t\tpasteToEditor(text: string): void {\n\t\t\t// Paste handling not supported in RPC mode - falls back to setEditorText\n\t\t\tthis.setEditorText(text);\n\t\t},\n\n\t\tsetEditorText(text: string): void {\n\t\t\t// Fire and forget - host can implement editor control\n\t\t\toutput({\n\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tmethod: \"set_editor_text\",\n\t\t\t\ttext,\n\t\t\t} as RpcExtensionUIRequest);\n\t\t},\n\n\t\tgetEditorText(): string {\n\t\t\t// Synchronous method can't wait for RPC response\n\t\t\t// Host should track editor state locally if needed\n\t\t\treturn \"\";\n\t\t},\n\n\t\tasync editor(title: string, prefill?: string): Promise<string | undefined> {\n\t\t\tconst id = crypto.randomUUID();\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tpendingExtensionRequests.set(id, {\n\t\t\t\t\tresolve: (response: RpcExtensionUIResponse) => {\n\t\t\t\t\t\tif (\"cancelled\" in response && response.cancelled) {\n\t\t\t\t\t\t\tresolve(undefined);\n\t\t\t\t\t\t} else if (\"value\" in response) {\n\t\t\t\t\t\t\tresolve(response.value);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresolve(undefined);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\treject,\n\t\t\t\t});\n\t\t\t\toutput({ type: \"extension_ui_request\", id, method: \"editor\", title, prefill } as RpcExtensionUIRequest);\n\t\t\t});\n\t\t},\n\n\t\taddAutocompleteProvider(): void {\n\t\t\t// Autocomplete provider composition is not supported in RPC mode\n\t\t},\n\n\t\tsetEditorComponent(): void {\n\t\t\t// Custom editor components not supported in RPC mode\n\t\t},\n\n\t\tgetEditorComponent() {\n\t\t\t// Custom editor components not supported in RPC mode\n\t\t\treturn undefined;\n\t\t},\n\n\t\tget theme() {\n\t\t\treturn theme;\n\t\t},\n\n\t\tgetAllThemes() {\n\t\t\treturn [];\n\t\t},\n\n\t\tgetTheme(_name: string) {\n\t\t\treturn undefined;\n\t\t},\n\n\t\tsetTheme(_theme: string | Theme) {\n\t\t\t// Theme switching not supported in RPC mode\n\t\t\treturn { success: false, error: \"Theme switching not supported in RPC mode\" };\n\t\t},\n\n\t\tgetToolsExpanded() {\n\t\t\t// Tool expansion not supported in RPC mode - no TUI\n\t\t\treturn false;\n\t\t},\n\n\t\tsetToolsExpanded(_expanded: boolean) {\n\t\t\t// Tool expansion not supported in RPC mode - no TUI\n\t\t},\n\t});\n\n\truntimeHost.setRebindSession(async () => {\n\t\tawait rebindSession();\n\t});\n\n\tconst rebindSession = async (): Promise<void> => {\n\t\tsession = runtimeHost.session;\n\t\tawait session.bindExtensions({\n\t\t\tuiContext: createExtensionUIContext(),\n\t\t\tcommandContextActions: {\n\t\t\t\twaitForIdle: () => session.agent.waitForIdle(),\n\t\t\t\tnewSession: async (options) => runtimeHost.newSession(options),\n\t\t\t\tfork: async (entryId, forkOptions) => {\n\t\t\t\t\tconst result = await runtimeHost.fork(entryId, forkOptions);\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tnavigateTree: async (targetId, options) => {\n\t\t\t\t\tconst result = await session.navigateTree(targetId, {\n\t\t\t\t\t\tsummarize: options?.summarize,\n\t\t\t\t\t\tcustomInstructions: options?.customInstructions,\n\t\t\t\t\t\treplaceInstructions: options?.replaceInstructions,\n\t\t\t\t\t\tlabel: options?.label,\n\t\t\t\t\t});\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tswitchSession: async (sessionPath, options) => {\n\t\t\t\t\treturn runtimeHost.switchSession(sessionPath, options);\n\t\t\t\t},\n\t\t\t\treload: async () => {\n\t\t\t\t\tawait session.reload();\n\t\t\t\t},\n\t\t\t},\n\t\t\tshutdownHandler: () => {\n\t\t\t\tshutdownRequested = true;\n\t\t\t},\n\t\t\tonError: (err) => {\n\t\t\t\toutput({ type: \"extension_error\", extensionPath: err.extensionPath, event: err.event, error: err.error });\n\t\t\t},\n\t\t});\n\n\t\tunsubscribe?.();\n\t\tunsubscribeBackpressure?.();\n\t\tunsubscribe = session.subscribe((event) => {\n\t\t\toutput(event);\n\t\t});\n\t\tunsubscribeBackpressure = session.agent.subscribe(async () => {\n\t\t\tawait waitForRawStdoutBackpressure();\n\t\t});\n\t};\n\n\tconst registerSignalHandlers = (): void => {\n\t\tconst signals: NodeJS.Signals[] = [\"SIGTERM\"];\n\t\tif (process.platform !== \"win32\") {\n\t\t\tsignals.push(\"SIGHUP\");\n\t\t}\n\n\t\tfor (const signal of signals) {\n\t\t\tconst handler = () => {\n\t\t\t\tkillTrackedDetachedChildren();\n\t\t\t\tvoid shutdown(signal === \"SIGHUP\" ? 129 : 143, signal);\n\t\t\t};\n\t\t\tprocess.on(signal, handler);\n\t\t\tsignalCleanupHandlers.push(() => process.off(signal, handler));\n\t\t}\n\t};\n\n\tawait rebindSession();\n\tregisterSignalHandlers();\n\n\t// Handle a single command\n\tconst handleCommand = async (command: RpcCommand): Promise<RpcResponse | undefined> => {\n\t\tconst id = command.id;\n\n\t\tswitch (command.type) {\n\t\t\t// =================================================================\n\t\t\t// Prompting\n\t\t\t// =================================================================\n\n\t\t\tcase \"prompt\": {\n\t\t\t\t// Start prompt handling immediately, but emit the authoritative response only after\n\t\t\t\t// prompt preflight succeeds. Queued and immediately handled prompts also count as success.\n\t\t\t\tlet preflightSucceeded = false;\n\t\t\t\tvoid session\n\t\t\t\t\t.prompt(command.message, {\n\t\t\t\t\t\timages: command.images,\n\t\t\t\t\t\tstreamingBehavior: command.streamingBehavior,\n\t\t\t\t\t\tsource: \"rpc\",\n\t\t\t\t\t\tpreflightResult: (didSucceed) => {\n\t\t\t\t\t\t\tif (didSucceed) {\n\t\t\t\t\t\t\t\tpreflightSucceeded = true;\n\t\t\t\t\t\t\t\toutput(success(id, \"prompt\"));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t\t.catch((e) => {\n\t\t\t\t\t\tif (!preflightSucceeded) {\n\t\t\t\t\t\t\toutput(error(id, \"prompt\", e.message));\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tcase \"steer\": {\n\t\t\t\tawait session.steer(command.message, command.images);\n\t\t\t\treturn success(id, \"steer\");\n\t\t\t}\n\n\t\t\tcase \"follow_up\": {\n\t\t\t\tawait session.followUp(command.message, command.images);\n\t\t\t\treturn success(id, \"follow_up\");\n\t\t\t}\n\n\t\t\tcase \"abort\": {\n\t\t\t\tawait session.abort();\n\t\t\t\treturn success(id, \"abort\");\n\t\t\t}\n\n\t\t\tcase \"new_session\": {\n\t\t\t\tconst options = command.parentSession ? { parentSession: command.parentSession } : undefined;\n\t\t\t\tconst result = await runtimeHost.newSession(options);\n\t\t\t\tif (!result.cancelled) {\n\t\t\t\t\tawait rebindSession();\n\t\t\t\t}\n\t\t\t\treturn success(id, \"new_session\", result);\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// State\n\t\t\t// =================================================================\n\n\t\t\tcase \"get_state\": {\n\t\t\t\tconst state: RpcSessionState = {\n\t\t\t\t\tmodel: session.model,\n\t\t\t\t\tthinkingLevel: session.thinkingLevel,\n\t\t\t\t\tisStreaming: session.isStreaming,\n\t\t\t\t\tisCompacting: session.isCompacting,\n\t\t\t\t\tsteeringMode: session.steeringMode,\n\t\t\t\t\tfollowUpMode: session.followUpMode,\n\t\t\t\t\tsessionFile: session.sessionFile,\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tsessionName: session.sessionName,\n\t\t\t\t\tautoCompactionEnabled: session.autoCompactionEnabled,\n\t\t\t\t\tmessageCount: session.messages.length,\n\t\t\t\t\tpendingMessageCount: session.pendingMessageCount,\n\t\t\t\t};\n\t\t\t\treturn success(id, \"get_state\", state);\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Model\n\t\t\t// =================================================================\n\n\t\t\tcase \"set_model\": {\n\t\t\t\tconst models = await session.modelRegistry.getAvailable();\n\t\t\t\tconst model = models.find((m) => m.provider === command.provider && m.id === command.modelId);\n\t\t\t\tif (!model) {\n\t\t\t\t\treturn error(id, \"set_model\", `Model not found: ${command.provider}/${command.modelId}`);\n\t\t\t\t}\n\t\t\t\tawait session.setModel(model);\n\t\t\t\treturn success(id, \"set_model\", model);\n\t\t\t}\n\n\t\t\tcase \"cycle_model\": {\n\t\t\t\tconst result = await session.cycleModel();\n\t\t\t\tif (!result) {\n\t\t\t\t\treturn success(id, \"cycle_model\", null);\n\t\t\t\t}\n\t\t\t\treturn success(id, \"cycle_model\", result);\n\t\t\t}\n\n\t\t\tcase \"get_available_models\": {\n\t\t\t\tconst models = await session.modelRegistry.getAvailable();\n\t\t\t\treturn success(id, \"get_available_models\", { models });\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Thinking\n\t\t\t// =================================================================\n\n\t\t\tcase \"set_thinking_level\": {\n\t\t\t\tsession.setThinkingLevel(command.level);\n\t\t\t\treturn success(id, \"set_thinking_level\");\n\t\t\t}\n\n\t\t\tcase \"cycle_thinking_level\": {\n\t\t\t\tconst level = session.cycleThinkingLevel();\n\t\t\t\tif (!level) {\n\t\t\t\t\treturn success(id, \"cycle_thinking_level\", null);\n\t\t\t\t}\n\t\t\t\treturn success(id, \"cycle_thinking_level\", { level });\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Queue Modes\n\t\t\t// =================================================================\n\n\t\t\tcase \"set_steering_mode\": {\n\t\t\t\tsession.setSteeringMode(command.mode);\n\t\t\t\treturn success(id, \"set_steering_mode\");\n\t\t\t}\n\n\t\t\tcase \"set_follow_up_mode\": {\n\t\t\t\tsession.setFollowUpMode(command.mode);\n\t\t\t\treturn success(id, \"set_follow_up_mode\");\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Compaction\n\t\t\t// =================================================================\n\n\t\t\tcase \"compact\": {\n\t\t\t\tconst result = await session.compact(command.customInstructions);\n\t\t\t\treturn success(id, \"compact\", result);\n\t\t\t}\n\n\t\t\tcase \"set_auto_compaction\": {\n\t\t\t\tsession.setAutoCompactionEnabled(command.enabled);\n\t\t\t\treturn success(id, \"set_auto_compaction\");\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Retry\n\t\t\t// =================================================================\n\n\t\t\tcase \"set_auto_retry\": {\n\t\t\t\tsession.setAutoRetryEnabled(command.enabled);\n\t\t\t\treturn success(id, \"set_auto_retry\");\n\t\t\t}\n\n\t\t\tcase \"abort_retry\": {\n\t\t\t\tsession.abortRetry();\n\t\t\t\treturn success(id, \"abort_retry\");\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Bash\n\t\t\t// =================================================================\n\n\t\t\tcase \"bash\": {\n\t\t\t\tconst result = await session.executeBash(command.command, undefined, {\n\t\t\t\t\texcludeFromContext: command.excludeFromContext,\n\t\t\t\t});\n\t\t\t\treturn success(id, \"bash\", result);\n\t\t\t}\n\n\t\t\tcase \"abort_bash\": {\n\t\t\t\tsession.abortBash();\n\t\t\t\treturn success(id, \"abort_bash\");\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Session\n\t\t\t// =================================================================\n\n\t\t\tcase \"get_session_stats\": {\n\t\t\t\tconst stats = session.getSessionStats();\n\t\t\t\treturn success(id, \"get_session_stats\", stats);\n\t\t\t}\n\n\t\t\tcase \"export_html\": {\n\t\t\t\tconst path = await session.exportToHtml(command.outputPath);\n\t\t\t\treturn success(id, \"export_html\", { path });\n\t\t\t}\n\n\t\t\tcase \"switch_session\": {\n\t\t\t\tconst result = await runtimeHost.switchSession(command.sessionPath);\n\t\t\t\tif (!result.cancelled) {\n\t\t\t\t\tawait rebindSession();\n\t\t\t\t}\n\t\t\t\treturn success(id, \"switch_session\", result);\n\t\t\t}\n\n\t\t\tcase \"fork\": {\n\t\t\t\tconst result = await runtimeHost.fork(command.entryId);\n\t\t\t\tif (!result.cancelled) {\n\t\t\t\t\tawait rebindSession();\n\t\t\t\t}\n\t\t\t\treturn success(id, \"fork\", { text: result.selectedText, cancelled: result.cancelled });\n\t\t\t}\n\n\t\t\tcase \"clone\": {\n\t\t\t\tconst leafId = session.sessionManager.getLeafId();\n\t\t\t\tif (!leafId) {\n\t\t\t\t\treturn error(id, \"clone\", \"Cannot clone session: no current entry selected\");\n\t\t\t\t}\n\t\t\t\tconst result = await runtimeHost.fork(leafId, { position: \"at\" });\n\t\t\t\tif (!result.cancelled) {\n\t\t\t\t\tawait rebindSession();\n\t\t\t\t}\n\t\t\t\treturn success(id, \"clone\", { cancelled: result.cancelled });\n\t\t\t}\n\n\t\t\tcase \"get_fork_messages\": {\n\t\t\t\tconst messages = session.getUserMessagesForForking();\n\t\t\t\treturn success(id, \"get_fork_messages\", { messages });\n\t\t\t}\n\n\t\t\tcase \"get_last_assistant_text\": {\n\t\t\t\tconst text = session.getLastAssistantText();\n\t\t\t\treturn success(id, \"get_last_assistant_text\", { text });\n\t\t\t}\n\n\t\t\tcase \"set_session_name\": {\n\t\t\t\tconst name = command.name.trim();\n\t\t\t\tif (!name) {\n\t\t\t\t\treturn error(id, \"set_session_name\", \"Session name cannot be empty\");\n\t\t\t\t}\n\t\t\t\tsession.setSessionName(name);\n\t\t\t\treturn success(id, \"set_session_name\");\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Messages\n\t\t\t// =================================================================\n\n\t\t\tcase \"get_messages\": {\n\t\t\t\treturn success(id, \"get_messages\", { messages: session.messages });\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Commands (available for invocation via prompt)\n\t\t\t// =================================================================\n\n\t\t\tcase \"get_commands\": {\n\t\t\t\tconst commands: RpcSlashCommand[] = [];\n\n\t\t\t\tfor (const command of session.extensionRunner.getRegisteredCommands()) {\n\t\t\t\t\tcommands.push({\n\t\t\t\t\t\tname: command.invocationName,\n\t\t\t\t\t\tdescription: command.description,\n\t\t\t\t\t\tsource: \"extension\",\n\t\t\t\t\t\tsourceInfo: command.sourceInfo,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tfor (const template of session.promptTemplates) {\n\t\t\t\t\tcommands.push({\n\t\t\t\t\t\tname: template.name,\n\t\t\t\t\t\tdescription: template.description,\n\t\t\t\t\t\tsource: \"prompt\",\n\t\t\t\t\t\tsourceInfo: template.sourceInfo,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tfor (const skill of session.resourceLoader.getSkills().skills) {\n\t\t\t\t\tcommands.push({\n\t\t\t\t\t\tname: `skill:${skill.name}`,\n\t\t\t\t\t\tdescription: skill.description,\n\t\t\t\t\t\tsource: \"skill\",\n\t\t\t\t\t\tsourceInfo: skill.sourceInfo,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\treturn success(id, \"get_commands\", { commands });\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst unknownCommand = command as { type: string };\n\t\t\t\treturn error(undefined, unknownCommand.type, `Unknown command: ${unknownCommand.type}`);\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Check if shutdown was requested and perform shutdown if so.\n\t * Called after handling each command when waiting for the next command.\n\t */\n\tlet detachInput = () => {};\n\n\tasync function shutdown(exitCode = 0, signal?: NodeJS.Signals): Promise<never> {\n\t\tif (shuttingDown) {\n\t\t\tprocess.exit(exitCode);\n\t\t}\n\t\tshuttingDown = true;\n\t\tfor (const cleanup of signalCleanupHandlers) {\n\t\t\tcleanup();\n\t\t}\n\t\tunsubscribe?.();\n\t\tunsubscribeBackpressure?.();\n\t\tawait runtimeHost.dispose();\n\t\tdetachInput();\n\t\tprocess.stdin.pause();\n\t\tif (signal !== \"SIGTERM\") {\n\t\t\tawait flushRawStdout();\n\t\t}\n\t\tprocess.exit(exitCode);\n\t}\n\n\tasync function checkShutdownRequested(): Promise<void> {\n\t\tif (!shutdownRequested) return;\n\t\tawait shutdown();\n\t}\n\n\tconst handleInputLine = async (line: string) => {\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(line);\n\t\t} catch (parseError: unknown) {\n\t\t\toutput(\n\t\t\t\terror(\n\t\t\t\t\tundefined,\n\t\t\t\t\t\"parse\",\n\t\t\t\t\t`Failed to parse command: ${parseError instanceof Error ? parseError.message : String(parseError)}`,\n\t\t\t\t),\n\t\t\t);\n\t\t\tawait waitForRawStdoutBackpressure();\n\t\t\treturn;\n\t\t}\n\n\t\t// Handle extension UI responses\n\t\tif (\n\t\t\ttypeof parsed === \"object\" &&\n\t\t\tparsed !== null &&\n\t\t\t\"type\" in parsed &&\n\t\t\tparsed.type === \"extension_ui_response\"\n\t\t) {\n\t\t\tconst response = parsed as RpcExtensionUIResponse;\n\t\t\tconst pending = pendingExtensionRequests.get(response.id);\n\t\t\tif (pending) {\n\t\t\t\tpendingExtensionRequests.delete(response.id);\n\t\t\t\tpending.resolve(response);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst command = parsed as RpcCommand;\n\t\ttry {\n\t\t\tconst response = await handleCommand(command);\n\t\t\tif (response) {\n\t\t\t\toutput(response);\n\t\t\t\tawait waitForRawStdoutBackpressure();\n\t\t\t}\n\t\t\tawait checkShutdownRequested();\n\t\t} catch (commandError: unknown) {\n\t\t\toutput(\n\t\t\t\terror(\n\t\t\t\t\tcommand.id,\n\t\t\t\t\tcommand.type,\n\t\t\t\t\tcommandError instanceof Error ? commandError.message : String(commandError),\n\t\t\t\t),\n\t\t\t);\n\t\t\tawait waitForRawStdoutBackpressure();\n\t\t}\n\t};\n\n\tconst onInputEnd = () => {\n\t\tvoid shutdown();\n\t};\n\tprocess.stdin.on(\"end\", onInputEnd);\n\n\tdetachInput = (() => {\n\t\tconst detachJsonl = attachJsonlLineReader(process.stdin, (line) => {\n\t\t\tvoid handleInputLine(line);\n\t\t});\n\t\treturn () => {\n\t\t\tdetachJsonl();\n\t\t\tprocess.stdin.off(\"end\", onInputEnd);\n\t\t};\n\t})();\n\n\t// Keep process alive forever\n\treturn new Promise(() => {});\n}\n"]}
1
+ {"version":3,"file":"rpc-mode.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/rpc-mode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AA0B/E,YAAY,EACX,UAAU,EACV,qBAAqB,EACrB,sBAAsB,EACtB,WAAW,EACX,eAAe,GACf,MAAM,gBAAgB,CAAC;AAExB;;;GAGG;AACH,wBAAsB,UAAU,CAAC,WAAW,EAAE,mBAAmB,GAAG,OAAO,CAAC,KAAK,CAAC,CAitBjF","sourcesContent":["/**\n * RPC mode: Headless operation with JSON stdin/stdout protocol.\n *\n * Used for embedding the agent in other applications.\n * Receives commands as JSON on stdin, outputs events and responses as JSON on stdout.\n *\n * Protocol:\n * - Commands: JSON objects with `type` field, optional `id` for correlation\n * - Responses: JSON objects with `type: \"response\"`, `command`, `success`, and optional `data`/`error`\n * - Events: AgentSessionEvent objects streamed as they occur\n * - Extension UI: Extension UI requests are emitted, client responds with extension_ui_response\n */\n\nimport * as crypto from \"node:crypto\";\nimport type { AgentSessionRuntime } from \"../../core/agent-session-runtime.ts\";\nimport type {\n\tExtensionUIContext,\n\tExtensionUIDialogOptions,\n\tExtensionWidgetOptions,\n\tWorkingIndicatorOptions,\n} from \"../../core/extensions/index.ts\";\nimport {\n\tflushRawStdout,\n\ttakeOverStdout,\n\twaitForRawStdoutBackpressure,\n\twriteRawStdout,\n} from \"../../core/output-guard.ts\";\nimport { killTrackedDetachedChildren } from \"../../utils/shell.ts\";\nimport { type Theme, theme } from \"../interactive/theme/theme.ts\";\nimport { attachJsonlLineReader, serializeJsonLine } from \"./jsonl.ts\";\nimport type {\n\tRpcCommand,\n\tRpcExtensionUIRequest,\n\tRpcExtensionUIResponse,\n\tRpcResponse,\n\tRpcSessionState,\n\tRpcSlashCommand,\n} from \"./rpc-types.ts\";\n\n// Re-export types for consumers\nexport type {\n\tRpcCommand,\n\tRpcExtensionUIRequest,\n\tRpcExtensionUIResponse,\n\tRpcResponse,\n\tRpcSessionState,\n} from \"./rpc-types.ts\";\n\n/**\n * Run in RPC mode.\n * Listens for JSON commands on stdin, outputs events and responses on stdout.\n */\nexport async function runRpcMode(runtimeHost: AgentSessionRuntime): Promise<never> {\n\ttakeOverStdout();\n\tlet session = runtimeHost.session;\n\tlet unsubscribe: (() => void) | undefined;\n\tlet unsubscribeBackpressure: (() => void) | undefined;\n\n\tconst output = (obj: RpcResponse | RpcExtensionUIRequest | object) => {\n\t\twriteRawStdout(serializeJsonLine(obj));\n\t};\n\n\tconst success = <T extends RpcCommand[\"type\"]>(\n\t\tid: string | undefined,\n\t\tcommand: T,\n\t\tdata?: object | null,\n\t): RpcResponse => {\n\t\tif (data === undefined) {\n\t\t\treturn { id, type: \"response\", command, success: true } as RpcResponse;\n\t\t}\n\t\treturn { id, type: \"response\", command, success: true, data } as RpcResponse;\n\t};\n\n\tconst error = (id: string | undefined, command: string, message: string): RpcResponse => {\n\t\treturn { id, type: \"response\", command, success: false, error: message };\n\t};\n\n\t// Pending extension UI requests waiting for response\n\tconst pendingExtensionRequests = new Map<\n\t\tstring,\n\t\t{ resolve: (value: any) => void; reject: (error: Error) => void }\n\t>();\n\n\t// Shutdown request flag\n\tlet shutdownRequested = false;\n\tlet shuttingDown = false;\n\tconst signalCleanupHandlers: Array<() => void> = [];\n\n\t/** Helper for dialog methods with signal/timeout support */\n\tfunction createDialogPromise<T>(\n\t\topts: ExtensionUIDialogOptions | undefined,\n\t\tdefaultValue: T,\n\t\trequest: Record<string, unknown>,\n\t\tparseResponse: (response: RpcExtensionUIResponse) => T,\n\t): Promise<T> {\n\t\tif (opts?.signal?.aborted) return Promise.resolve(defaultValue);\n\n\t\tconst id = crypto.randomUUID();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n\t\t\tconst cleanup = () => {\n\t\t\t\tif (timeoutId) clearTimeout(timeoutId);\n\t\t\t\topts?.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\tpendingExtensionRequests.delete(id);\n\t\t\t};\n\n\t\t\tconst onAbort = () => {\n\t\t\t\tcleanup();\n\t\t\t\tresolve(defaultValue);\n\t\t\t};\n\t\t\topts?.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\t\t\tif (opts?.timeout) {\n\t\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\t\tcleanup();\n\t\t\t\t\tresolve(defaultValue);\n\t\t\t\t}, opts.timeout);\n\t\t\t}\n\n\t\t\tpendingExtensionRequests.set(id, {\n\t\t\t\tresolve: (response: RpcExtensionUIResponse) => {\n\t\t\t\t\tcleanup();\n\t\t\t\t\tresolve(parseResponse(response));\n\t\t\t\t},\n\t\t\t\treject,\n\t\t\t});\n\t\t\toutput({ type: \"extension_ui_request\", id, ...request } as RpcExtensionUIRequest);\n\t\t});\n\t}\n\n\t/**\n\t * Create an extension UI context that uses the RPC protocol.\n\t */\n\tconst createExtensionUIContext = (): ExtensionUIContext => ({\n\t\tselect: (title, options, opts) =>\n\t\t\tcreateDialogPromise(opts, undefined, { method: \"select\", title, options, timeout: opts?.timeout }, (r) =>\n\t\t\t\t\"cancelled\" in r && r.cancelled ? undefined : \"value\" in r ? r.value : undefined,\n\t\t\t),\n\n\t\tconfirm: (title, message, opts) =>\n\t\t\tcreateDialogPromise(opts, false, { method: \"confirm\", title, message, timeout: opts?.timeout }, (r) =>\n\t\t\t\t\"cancelled\" in r && r.cancelled ? false : \"confirmed\" in r ? r.confirmed : false,\n\t\t\t),\n\n\t\tinput: (title, placeholder, opts) =>\n\t\t\tcreateDialogPromise(opts, undefined, { method: \"input\", title, placeholder, timeout: opts?.timeout }, (r) =>\n\t\t\t\t\"cancelled\" in r && r.cancelled ? undefined : \"value\" in r ? r.value : undefined,\n\t\t\t),\n\n\t\tnotify(message: string, type?: \"info\" | \"warning\" | \"error\"): void {\n\t\t\t// Fire and forget - no response needed\n\t\t\toutput({\n\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tmethod: \"notify\",\n\t\t\t\tmessage,\n\t\t\t\tnotifyType: type,\n\t\t\t} as RpcExtensionUIRequest);\n\t\t},\n\n\t\tonTerminalInput(): () => void {\n\t\t\t// Raw terminal input not supported in RPC mode\n\t\t\treturn () => {};\n\t\t},\n\n\t\tsetStatus(key: string, text: string | undefined): void {\n\t\t\t// Fire and forget - no response needed\n\t\t\toutput({\n\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tmethod: \"setStatus\",\n\t\t\t\tstatusKey: key,\n\t\t\t\tstatusText: text,\n\t\t\t} as RpcExtensionUIRequest);\n\t\t},\n\n\t\tsetWorkingMessage(_message?: string): void {\n\t\t\t// Working message not supported in RPC mode - requires TUI loader access\n\t\t},\n\n\t\tsetWorkingVisible(_visible: boolean): void {\n\t\t\t// Working visibility not supported in RPC mode - requires TUI loader access\n\t\t},\n\n\t\tsetWorkingIndicator(_options?: WorkingIndicatorOptions): void {\n\t\t\t// Working indicator customization not supported in RPC mode - requires TUI loader access\n\t\t},\n\n\t\tsetHiddenThinkingLabel(_label?: string): void {\n\t\t\t// Hidden thinking label not supported in RPC mode - requires TUI message rendering access\n\t\t},\n\n\t\tsetWidget(key: string, content: unknown, options?: ExtensionWidgetOptions): void {\n\t\t\t// Only support string arrays in RPC mode - factory functions are ignored\n\t\t\tif (content === undefined || Array.isArray(content)) {\n\t\t\t\toutput({\n\t\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\t\tmethod: \"setWidget\",\n\t\t\t\t\twidgetKey: key,\n\t\t\t\t\twidgetLines: content as string[] | undefined,\n\t\t\t\t\twidgetPlacement: options?.placement,\n\t\t\t\t} as RpcExtensionUIRequest);\n\t\t\t}\n\t\t\t// Component factories are not supported in RPC mode - would need TUI access\n\t\t},\n\n\t\tsetFooter(_factory: unknown): void {\n\t\t\t// Custom footer not supported in RPC mode - requires TUI access\n\t\t},\n\n\t\tsetHeader(_factory: unknown): void {\n\t\t\t// Custom header not supported in RPC mode - requires TUI access\n\t\t},\n\n\t\tsetTitle(title: string): void {\n\t\t\t// Fire and forget - host can implement terminal title control\n\t\t\toutput({\n\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tmethod: \"setTitle\",\n\t\t\t\ttitle,\n\t\t\t} as RpcExtensionUIRequest);\n\t\t},\n\n\t\tasync custom() {\n\t\t\t// Custom UI not supported in RPC mode\n\t\t\treturn undefined as never;\n\t\t},\n\n\t\tpasteToEditor(text: string): void {\n\t\t\t// Paste handling not supported in RPC mode - falls back to setEditorText\n\t\t\tthis.setEditorText(text);\n\t\t},\n\n\t\tsetEditorText(text: string): void {\n\t\t\t// Fire and forget - host can implement editor control\n\t\t\toutput({\n\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tmethod: \"set_editor_text\",\n\t\t\t\ttext,\n\t\t\t} as RpcExtensionUIRequest);\n\t\t},\n\n\t\tgetEditorText(): string {\n\t\t\t// Synchronous method can't wait for RPC response\n\t\t\t// Host should track editor state locally if needed\n\t\t\treturn \"\";\n\t\t},\n\n\t\tasync editor(title: string, prefill?: string): Promise<string | undefined> {\n\t\t\tconst id = crypto.randomUUID();\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tpendingExtensionRequests.set(id, {\n\t\t\t\t\tresolve: (response: RpcExtensionUIResponse) => {\n\t\t\t\t\t\tif (\"cancelled\" in response && response.cancelled) {\n\t\t\t\t\t\t\tresolve(undefined);\n\t\t\t\t\t\t} else if (\"value\" in response) {\n\t\t\t\t\t\t\tresolve(response.value);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresolve(undefined);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\treject,\n\t\t\t\t});\n\t\t\t\toutput({ type: \"extension_ui_request\", id, method: \"editor\", title, prefill } as RpcExtensionUIRequest);\n\t\t\t});\n\t\t},\n\n\t\taddAutocompleteProvider(): void {\n\t\t\t// Autocomplete provider composition is not supported in RPC mode\n\t\t},\n\n\t\tsetEditorComponent(): void {\n\t\t\t// Custom editor components not supported in RPC mode\n\t\t},\n\n\t\tgetEditorComponent() {\n\t\t\t// Custom editor components not supported in RPC mode\n\t\t\treturn undefined;\n\t\t},\n\n\t\tget theme() {\n\t\t\treturn theme;\n\t\t},\n\n\t\tgetAllThemes() {\n\t\t\treturn [];\n\t\t},\n\n\t\tgetTheme(_name: string) {\n\t\t\treturn undefined;\n\t\t},\n\n\t\tsetTheme(_theme: string | Theme) {\n\t\t\t// Theme switching not supported in RPC mode\n\t\t\treturn { success: false, error: \"Theme switching not supported in RPC mode\" };\n\t\t},\n\n\t\tgetToolsExpanded() {\n\t\t\t// Tool expansion not supported in RPC mode - no TUI\n\t\t\treturn false;\n\t\t},\n\n\t\tsetToolsExpanded(_expanded: boolean) {\n\t\t\t// Tool expansion not supported in RPC mode - no TUI\n\t\t},\n\t});\n\n\truntimeHost.setRebindSession(async () => {\n\t\tawait rebindSession();\n\t});\n\n\tconst rebindSession = async (): Promise<void> => {\n\t\tsession = runtimeHost.session;\n\t\tawait session.bindExtensions({\n\t\t\tuiContext: createExtensionUIContext(),\n\t\t\tmode: \"rpc\",\n\t\t\tcommandContextActions: {\n\t\t\t\twaitForIdle: () => session.agent.waitForIdle(),\n\t\t\t\tnewSession: async (options) => runtimeHost.newSession(options),\n\t\t\t\tfork: async (entryId, forkOptions) => {\n\t\t\t\t\tconst result = await runtimeHost.fork(entryId, forkOptions);\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tnavigateTree: async (targetId, options) => {\n\t\t\t\t\tconst result = await session.navigateTree(targetId, {\n\t\t\t\t\t\tsummarize: options?.summarize,\n\t\t\t\t\t\tcustomInstructions: options?.customInstructions,\n\t\t\t\t\t\treplaceInstructions: options?.replaceInstructions,\n\t\t\t\t\t\tlabel: options?.label,\n\t\t\t\t\t});\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tswitchSession: async (sessionPath, options) => {\n\t\t\t\t\treturn runtimeHost.switchSession(sessionPath, options);\n\t\t\t\t},\n\t\t\t\treload: async () => {\n\t\t\t\t\tawait session.reload();\n\t\t\t\t},\n\t\t\t},\n\t\t\tshutdownHandler: () => {\n\t\t\t\tshutdownRequested = true;\n\t\t\t},\n\t\t\tonError: (err) => {\n\t\t\t\toutput({ type: \"extension_error\", extensionPath: err.extensionPath, event: err.event, error: err.error });\n\t\t\t},\n\t\t});\n\n\t\tunsubscribe?.();\n\t\tunsubscribeBackpressure?.();\n\t\tunsubscribe = session.subscribe((event) => {\n\t\t\toutput(event);\n\t\t});\n\t\tunsubscribeBackpressure = session.agent.subscribe(async () => {\n\t\t\tawait waitForRawStdoutBackpressure();\n\t\t});\n\t};\n\n\tconst registerSignalHandlers = (): void => {\n\t\tconst signals: NodeJS.Signals[] = [\"SIGTERM\"];\n\t\tif (process.platform !== \"win32\") {\n\t\t\tsignals.push(\"SIGHUP\");\n\t\t}\n\n\t\tfor (const signal of signals) {\n\t\t\tconst handler = () => {\n\t\t\t\tkillTrackedDetachedChildren();\n\t\t\t\tvoid shutdown(signal === \"SIGHUP\" ? 129 : 143, signal);\n\t\t\t};\n\t\t\tprocess.on(signal, handler);\n\t\t\tsignalCleanupHandlers.push(() => process.off(signal, handler));\n\t\t}\n\t};\n\n\tawait rebindSession();\n\tregisterSignalHandlers();\n\n\t// Handle a single command\n\tconst handleCommand = async (command: RpcCommand): Promise<RpcResponse | undefined> => {\n\t\tconst id = command.id;\n\n\t\tswitch (command.type) {\n\t\t\t// =================================================================\n\t\t\t// Prompting\n\t\t\t// =================================================================\n\n\t\t\tcase \"prompt\": {\n\t\t\t\t// Start prompt handling immediately, but emit the authoritative response only after\n\t\t\t\t// prompt preflight succeeds. Queued and immediately handled prompts also count as success.\n\t\t\t\tlet preflightSucceeded = false;\n\t\t\t\tvoid session\n\t\t\t\t\t.prompt(command.message, {\n\t\t\t\t\t\timages: command.images,\n\t\t\t\t\t\tstreamingBehavior: command.streamingBehavior,\n\t\t\t\t\t\tsource: \"rpc\",\n\t\t\t\t\t\tpreflightResult: (didSucceed) => {\n\t\t\t\t\t\t\tif (didSucceed) {\n\t\t\t\t\t\t\t\tpreflightSucceeded = true;\n\t\t\t\t\t\t\t\toutput(success(id, \"prompt\"));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t\t.catch((e) => {\n\t\t\t\t\t\tif (!preflightSucceeded) {\n\t\t\t\t\t\t\toutput(error(id, \"prompt\", e.message));\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tcase \"steer\": {\n\t\t\t\tawait session.steer(command.message, command.images);\n\t\t\t\treturn success(id, \"steer\");\n\t\t\t}\n\n\t\t\tcase \"follow_up\": {\n\t\t\t\tawait session.followUp(command.message, command.images);\n\t\t\t\treturn success(id, \"follow_up\");\n\t\t\t}\n\n\t\t\tcase \"abort\": {\n\t\t\t\tawait session.abort();\n\t\t\t\treturn success(id, \"abort\");\n\t\t\t}\n\n\t\t\tcase \"new_session\": {\n\t\t\t\tconst options = command.parentSession ? { parentSession: command.parentSession } : undefined;\n\t\t\t\tconst result = await runtimeHost.newSession(options);\n\t\t\t\tif (!result.cancelled) {\n\t\t\t\t\tawait rebindSession();\n\t\t\t\t}\n\t\t\t\treturn success(id, \"new_session\", result);\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// State\n\t\t\t// =================================================================\n\n\t\t\tcase \"get_state\": {\n\t\t\t\tconst state: RpcSessionState = {\n\t\t\t\t\tmodel: session.model,\n\t\t\t\t\tthinkingLevel: session.thinkingLevel,\n\t\t\t\t\tisStreaming: session.isStreaming,\n\t\t\t\t\tisCompacting: session.isCompacting,\n\t\t\t\t\tsteeringMode: session.steeringMode,\n\t\t\t\t\tfollowUpMode: session.followUpMode,\n\t\t\t\t\tsessionFile: session.sessionFile,\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tsessionName: session.sessionName,\n\t\t\t\t\tautoCompactionEnabled: session.autoCompactionEnabled,\n\t\t\t\t\tmessageCount: session.messages.length,\n\t\t\t\t\tpendingMessageCount: session.pendingMessageCount,\n\t\t\t\t};\n\t\t\t\treturn success(id, \"get_state\", state);\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Model\n\t\t\t// =================================================================\n\n\t\t\tcase \"set_model\": {\n\t\t\t\tconst models = await session.modelRegistry.getAvailable();\n\t\t\t\tconst model = models.find((m) => m.provider === command.provider && m.id === command.modelId);\n\t\t\t\tif (!model) {\n\t\t\t\t\treturn error(id, \"set_model\", `Model not found: ${command.provider}/${command.modelId}`);\n\t\t\t\t}\n\t\t\t\tawait session.setModel(model);\n\t\t\t\treturn success(id, \"set_model\", model);\n\t\t\t}\n\n\t\t\tcase \"cycle_model\": {\n\t\t\t\tconst result = await session.cycleModel();\n\t\t\t\tif (!result) {\n\t\t\t\t\treturn success(id, \"cycle_model\", null);\n\t\t\t\t}\n\t\t\t\treturn success(id, \"cycle_model\", result);\n\t\t\t}\n\n\t\t\tcase \"get_available_models\": {\n\t\t\t\tconst models = await session.modelRegistry.getAvailable();\n\t\t\t\treturn success(id, \"get_available_models\", { models });\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Thinking\n\t\t\t// =================================================================\n\n\t\t\tcase \"set_thinking_level\": {\n\t\t\t\tsession.setThinkingLevel(command.level);\n\t\t\t\treturn success(id, \"set_thinking_level\");\n\t\t\t}\n\n\t\t\tcase \"cycle_thinking_level\": {\n\t\t\t\tconst level = session.cycleThinkingLevel();\n\t\t\t\tif (!level) {\n\t\t\t\t\treturn success(id, \"cycle_thinking_level\", null);\n\t\t\t\t}\n\t\t\t\treturn success(id, \"cycle_thinking_level\", { level });\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Queue Modes\n\t\t\t// =================================================================\n\n\t\t\tcase \"set_steering_mode\": {\n\t\t\t\tsession.setSteeringMode(command.mode);\n\t\t\t\treturn success(id, \"set_steering_mode\");\n\t\t\t}\n\n\t\t\tcase \"set_follow_up_mode\": {\n\t\t\t\tsession.setFollowUpMode(command.mode);\n\t\t\t\treturn success(id, \"set_follow_up_mode\");\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Compaction\n\t\t\t// =================================================================\n\n\t\t\tcase \"compact\": {\n\t\t\t\tconst result = await session.compact(command.customInstructions);\n\t\t\t\treturn success(id, \"compact\", result);\n\t\t\t}\n\n\t\t\tcase \"set_auto_compaction\": {\n\t\t\t\tsession.setAutoCompactionEnabled(command.enabled);\n\t\t\t\treturn success(id, \"set_auto_compaction\");\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Retry\n\t\t\t// =================================================================\n\n\t\t\tcase \"set_auto_retry\": {\n\t\t\t\tsession.setAutoRetryEnabled(command.enabled);\n\t\t\t\treturn success(id, \"set_auto_retry\");\n\t\t\t}\n\n\t\t\tcase \"abort_retry\": {\n\t\t\t\tsession.abortRetry();\n\t\t\t\treturn success(id, \"abort_retry\");\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Bash\n\t\t\t// =================================================================\n\n\t\t\tcase \"bash\": {\n\t\t\t\tconst result = await session.executeBash(command.command, undefined, {\n\t\t\t\t\texcludeFromContext: command.excludeFromContext,\n\t\t\t\t});\n\t\t\t\treturn success(id, \"bash\", result);\n\t\t\t}\n\n\t\t\tcase \"abort_bash\": {\n\t\t\t\tsession.abortBash();\n\t\t\t\treturn success(id, \"abort_bash\");\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Session\n\t\t\t// =================================================================\n\n\t\t\tcase \"get_session_stats\": {\n\t\t\t\tconst stats = session.getSessionStats();\n\t\t\t\treturn success(id, \"get_session_stats\", stats);\n\t\t\t}\n\n\t\t\tcase \"export_html\": {\n\t\t\t\tconst path = await session.exportToHtml(command.outputPath);\n\t\t\t\treturn success(id, \"export_html\", { path });\n\t\t\t}\n\n\t\t\tcase \"switch_session\": {\n\t\t\t\tconst result = await runtimeHost.switchSession(command.sessionPath);\n\t\t\t\tif (!result.cancelled) {\n\t\t\t\t\tawait rebindSession();\n\t\t\t\t}\n\t\t\t\treturn success(id, \"switch_session\", result);\n\t\t\t}\n\n\t\t\tcase \"fork\": {\n\t\t\t\tconst result = await runtimeHost.fork(command.entryId);\n\t\t\t\tif (!result.cancelled) {\n\t\t\t\t\tawait rebindSession();\n\t\t\t\t}\n\t\t\t\treturn success(id, \"fork\", { text: result.selectedText, cancelled: result.cancelled });\n\t\t\t}\n\n\t\t\tcase \"clone\": {\n\t\t\t\tconst leafId = session.sessionManager.getLeafId();\n\t\t\t\tif (!leafId) {\n\t\t\t\t\treturn error(id, \"clone\", \"Cannot clone session: no current entry selected\");\n\t\t\t\t}\n\t\t\t\tconst result = await runtimeHost.fork(leafId, { position: \"at\" });\n\t\t\t\tif (!result.cancelled) {\n\t\t\t\t\tawait rebindSession();\n\t\t\t\t}\n\t\t\t\treturn success(id, \"clone\", { cancelled: result.cancelled });\n\t\t\t}\n\n\t\t\tcase \"get_fork_messages\": {\n\t\t\t\tconst messages = session.getUserMessagesForForking();\n\t\t\t\treturn success(id, \"get_fork_messages\", { messages });\n\t\t\t}\n\n\t\t\tcase \"get_last_assistant_text\": {\n\t\t\t\tconst text = session.getLastAssistantText();\n\t\t\t\treturn success(id, \"get_last_assistant_text\", { text });\n\t\t\t}\n\n\t\t\tcase \"set_session_name\": {\n\t\t\t\tconst name = command.name.trim();\n\t\t\t\tif (!name) {\n\t\t\t\t\treturn error(id, \"set_session_name\", \"Session name cannot be empty\");\n\t\t\t\t}\n\t\t\t\tsession.setSessionName(name);\n\t\t\t\treturn success(id, \"set_session_name\");\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Messages\n\t\t\t// =================================================================\n\n\t\t\tcase \"get_messages\": {\n\t\t\t\treturn success(id, \"get_messages\", { messages: session.messages });\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Commands (available for invocation via prompt)\n\t\t\t// =================================================================\n\n\t\t\tcase \"get_commands\": {\n\t\t\t\tconst commands: RpcSlashCommand[] = [];\n\n\t\t\t\tfor (const command of session.extensionRunner.getRegisteredCommands()) {\n\t\t\t\t\tcommands.push({\n\t\t\t\t\t\tname: command.invocationName,\n\t\t\t\t\t\tdescription: command.description,\n\t\t\t\t\t\tsource: \"extension\",\n\t\t\t\t\t\tsourceInfo: command.sourceInfo,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tfor (const template of session.promptTemplates) {\n\t\t\t\t\tcommands.push({\n\t\t\t\t\t\tname: template.name,\n\t\t\t\t\t\tdescription: template.description,\n\t\t\t\t\t\tsource: \"prompt\",\n\t\t\t\t\t\tsourceInfo: template.sourceInfo,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tfor (const skill of session.resourceLoader.getSkills().skills) {\n\t\t\t\t\tcommands.push({\n\t\t\t\t\t\tname: `skill:${skill.name}`,\n\t\t\t\t\t\tdescription: skill.description,\n\t\t\t\t\t\tsource: \"skill\",\n\t\t\t\t\t\tsourceInfo: skill.sourceInfo,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\treturn success(id, \"get_commands\", { commands });\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst unknownCommand = command as { type: string };\n\t\t\t\treturn error(undefined, unknownCommand.type, `Unknown command: ${unknownCommand.type}`);\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Check if shutdown was requested and perform shutdown if so.\n\t * Called after handling each command when waiting for the next command.\n\t */\n\tlet detachInput = () => {};\n\n\tasync function shutdown(exitCode = 0, signal?: NodeJS.Signals): Promise<never> {\n\t\tif (shuttingDown) {\n\t\t\tprocess.exit(exitCode);\n\t\t}\n\t\tshuttingDown = true;\n\t\tfor (const cleanup of signalCleanupHandlers) {\n\t\t\tcleanup();\n\t\t}\n\t\tunsubscribe?.();\n\t\tunsubscribeBackpressure?.();\n\t\tawait runtimeHost.dispose();\n\t\tdetachInput();\n\t\tprocess.stdin.pause();\n\t\tif (signal !== \"SIGTERM\") {\n\t\t\tawait flushRawStdout();\n\t\t}\n\t\tprocess.exit(exitCode);\n\t}\n\n\tasync function checkShutdownRequested(): Promise<void> {\n\t\tif (!shutdownRequested) return;\n\t\tawait shutdown();\n\t}\n\n\tconst handleInputLine = async (line: string) => {\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(line);\n\t\t} catch (parseError: unknown) {\n\t\t\toutput(\n\t\t\t\terror(\n\t\t\t\t\tundefined,\n\t\t\t\t\t\"parse\",\n\t\t\t\t\t`Failed to parse command: ${parseError instanceof Error ? parseError.message : String(parseError)}`,\n\t\t\t\t),\n\t\t\t);\n\t\t\tawait waitForRawStdoutBackpressure();\n\t\t\treturn;\n\t\t}\n\n\t\t// Handle extension UI responses\n\t\tif (\n\t\t\ttypeof parsed === \"object\" &&\n\t\t\tparsed !== null &&\n\t\t\t\"type\" in parsed &&\n\t\t\tparsed.type === \"extension_ui_response\"\n\t\t) {\n\t\t\tconst response = parsed as RpcExtensionUIResponse;\n\t\t\tconst pending = pendingExtensionRequests.get(response.id);\n\t\t\tif (pending) {\n\t\t\t\tpendingExtensionRequests.delete(response.id);\n\t\t\t\tpending.resolve(response);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst command = parsed as RpcCommand;\n\t\ttry {\n\t\t\tconst response = await handleCommand(command);\n\t\t\tif (response) {\n\t\t\t\toutput(response);\n\t\t\t\tawait waitForRawStdoutBackpressure();\n\t\t\t}\n\t\t\tawait checkShutdownRequested();\n\t\t} catch (commandError: unknown) {\n\t\t\toutput(\n\t\t\t\terror(\n\t\t\t\t\tcommand.id,\n\t\t\t\t\tcommand.type,\n\t\t\t\t\tcommandError instanceof Error ? commandError.message : String(commandError),\n\t\t\t\t),\n\t\t\t);\n\t\t\tawait waitForRawStdoutBackpressure();\n\t\t}\n\t};\n\n\tconst onInputEnd = () => {\n\t\tvoid shutdown();\n\t};\n\tprocess.stdin.on(\"end\", onInputEnd);\n\n\tdetachInput = (() => {\n\t\tconst detachJsonl = attachJsonlLineReader(process.stdin, (line) => {\n\t\t\tvoid handleInputLine(line);\n\t\t});\n\t\treturn () => {\n\t\t\tdetachJsonl();\n\t\t\tprocess.stdin.off(\"end\", onInputEnd);\n\t\t};\n\t})();\n\n\t// Keep process alive forever\n\treturn new Promise(() => {});\n}\n"]}
@@ -228,6 +228,7 @@ export async function runRpcMode(runtimeHost) {
228
228
  session = runtimeHost.session;
229
229
  await session.bindExtensions({
230
230
  uiContext: createExtensionUIContext(),
231
+ mode: "rpc",
231
232
  commandContextActions: {
232
233
  waitForIdle: () => session.agent.waitForIdle(),
233
234
  newSession: async (options) => runtimeHost.newSession(options),
@@ -1 +1 @@
1
- {"version":3,"file":"rpc-mode.js","sourceRoot":"","sources":["../../../src/modes/rpc/rpc-mode.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * RPC mode: Headless operation with JSON stdin/stdout protocol.\n *\n * Used for embedding the agent in other applications.\n * Receives commands as JSON on stdin, outputs events and responses as JSON on stdout.\n *\n * Protocol:\n * - Commands: JSON objects with `type` field, optional `id` for correlation\n * - Responses: JSON objects with `type: \"response\"`, `command`, `success`, and optional `data`/`error`\n * - Events: AgentSessionEvent objects streamed as they occur\n * - Extension UI: Extension UI requests are emitted, client responds with extension_ui_response\n */\n\nimport * as crypto from \"node:crypto\";\nimport type { AgentSessionRuntime } from \"../../core/agent-session-runtime.ts\";\nimport type {\n\tExtensionUIContext,\n\tExtensionUIDialogOptions,\n\tExtensionWidgetOptions,\n\tWorkingIndicatorOptions,\n} from \"../../core/extensions/index.ts\";\nimport {\n\tflushRawStdout,\n\ttakeOverStdout,\n\twaitForRawStdoutBackpressure,\n\twriteRawStdout,\n} from \"../../core/output-guard.ts\";\nimport { killTrackedDetachedChildren } from \"../../utils/shell.ts\";\nimport { type Theme, theme } from \"../interactive/theme/theme.ts\";\nimport { attachJsonlLineReader, serializeJsonLine } from \"./jsonl.ts\";\nimport type {\n\tRpcCommand,\n\tRpcExtensionUIRequest,\n\tRpcExtensionUIResponse,\n\tRpcResponse,\n\tRpcSessionState,\n\tRpcSlashCommand,\n} from \"./rpc-types.ts\";\n\n// Re-export types for consumers\nexport type {\n\tRpcCommand,\n\tRpcExtensionUIRequest,\n\tRpcExtensionUIResponse,\n\tRpcResponse,\n\tRpcSessionState,\n} from \"./rpc-types.ts\";\n\n/**\n * Run in RPC mode.\n * Listens for JSON commands on stdin, outputs events and responses on stdout.\n */\nexport async function runRpcMode(runtimeHost: AgentSessionRuntime): Promise<never> {\n\ttakeOverStdout();\n\tlet session = runtimeHost.session;\n\tlet unsubscribe: (() => void) | undefined;\n\tlet unsubscribeBackpressure: (() => void) | undefined;\n\n\tconst output = (obj: RpcResponse | RpcExtensionUIRequest | object) => {\n\t\twriteRawStdout(serializeJsonLine(obj));\n\t};\n\n\tconst success = <T extends RpcCommand[\"type\"]>(\n\t\tid: string | undefined,\n\t\tcommand: T,\n\t\tdata?: object | null,\n\t): RpcResponse => {\n\t\tif (data === undefined) {\n\t\t\treturn { id, type: \"response\", command, success: true } as RpcResponse;\n\t\t}\n\t\treturn { id, type: \"response\", command, success: true, data } as RpcResponse;\n\t};\n\n\tconst error = (id: string | undefined, command: string, message: string): RpcResponse => {\n\t\treturn { id, type: \"response\", command, success: false, error: message };\n\t};\n\n\t// Pending extension UI requests waiting for response\n\tconst pendingExtensionRequests = new Map<\n\t\tstring,\n\t\t{ resolve: (value: any) => void; reject: (error: Error) => void }\n\t>();\n\n\t// Shutdown request flag\n\tlet shutdownRequested = false;\n\tlet shuttingDown = false;\n\tconst signalCleanupHandlers: Array<() => void> = [];\n\n\t/** Helper for dialog methods with signal/timeout support */\n\tfunction createDialogPromise<T>(\n\t\topts: ExtensionUIDialogOptions | undefined,\n\t\tdefaultValue: T,\n\t\trequest: Record<string, unknown>,\n\t\tparseResponse: (response: RpcExtensionUIResponse) => T,\n\t): Promise<T> {\n\t\tif (opts?.signal?.aborted) return Promise.resolve(defaultValue);\n\n\t\tconst id = crypto.randomUUID();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n\t\t\tconst cleanup = () => {\n\t\t\t\tif (timeoutId) clearTimeout(timeoutId);\n\t\t\t\topts?.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\tpendingExtensionRequests.delete(id);\n\t\t\t};\n\n\t\t\tconst onAbort = () => {\n\t\t\t\tcleanup();\n\t\t\t\tresolve(defaultValue);\n\t\t\t};\n\t\t\topts?.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\t\t\tif (opts?.timeout) {\n\t\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\t\tcleanup();\n\t\t\t\t\tresolve(defaultValue);\n\t\t\t\t}, opts.timeout);\n\t\t\t}\n\n\t\t\tpendingExtensionRequests.set(id, {\n\t\t\t\tresolve: (response: RpcExtensionUIResponse) => {\n\t\t\t\t\tcleanup();\n\t\t\t\t\tresolve(parseResponse(response));\n\t\t\t\t},\n\t\t\t\treject,\n\t\t\t});\n\t\t\toutput({ type: \"extension_ui_request\", id, ...request } as RpcExtensionUIRequest);\n\t\t});\n\t}\n\n\t/**\n\t * Create an extension UI context that uses the RPC protocol.\n\t */\n\tconst createExtensionUIContext = (): ExtensionUIContext => ({\n\t\tselect: (title, options, opts) =>\n\t\t\tcreateDialogPromise(opts, undefined, { method: \"select\", title, options, timeout: opts?.timeout }, (r) =>\n\t\t\t\t\"cancelled\" in r && r.cancelled ? undefined : \"value\" in r ? r.value : undefined,\n\t\t\t),\n\n\t\tconfirm: (title, message, opts) =>\n\t\t\tcreateDialogPromise(opts, false, { method: \"confirm\", title, message, timeout: opts?.timeout }, (r) =>\n\t\t\t\t\"cancelled\" in r && r.cancelled ? false : \"confirmed\" in r ? r.confirmed : false,\n\t\t\t),\n\n\t\tinput: (title, placeholder, opts) =>\n\t\t\tcreateDialogPromise(opts, undefined, { method: \"input\", title, placeholder, timeout: opts?.timeout }, (r) =>\n\t\t\t\t\"cancelled\" in r && r.cancelled ? undefined : \"value\" in r ? r.value : undefined,\n\t\t\t),\n\n\t\tnotify(message: string, type?: \"info\" | \"warning\" | \"error\"): void {\n\t\t\t// Fire and forget - no response needed\n\t\t\toutput({\n\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tmethod: \"notify\",\n\t\t\t\tmessage,\n\t\t\t\tnotifyType: type,\n\t\t\t} as RpcExtensionUIRequest);\n\t\t},\n\n\t\tonTerminalInput(): () => void {\n\t\t\t// Raw terminal input not supported in RPC mode\n\t\t\treturn () => {};\n\t\t},\n\n\t\tsetStatus(key: string, text: string | undefined): void {\n\t\t\t// Fire and forget - no response needed\n\t\t\toutput({\n\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tmethod: \"setStatus\",\n\t\t\t\tstatusKey: key,\n\t\t\t\tstatusText: text,\n\t\t\t} as RpcExtensionUIRequest);\n\t\t},\n\n\t\tsetWorkingMessage(_message?: string): void {\n\t\t\t// Working message not supported in RPC mode - requires TUI loader access\n\t\t},\n\n\t\tsetWorkingVisible(_visible: boolean): void {\n\t\t\t// Working visibility not supported in RPC mode - requires TUI loader access\n\t\t},\n\n\t\tsetWorkingIndicator(_options?: WorkingIndicatorOptions): void {\n\t\t\t// Working indicator customization not supported in RPC mode - requires TUI loader access\n\t\t},\n\n\t\tsetHiddenThinkingLabel(_label?: string): void {\n\t\t\t// Hidden thinking label not supported in RPC mode - requires TUI message rendering access\n\t\t},\n\n\t\tsetWidget(key: string, content: unknown, options?: ExtensionWidgetOptions): void {\n\t\t\t// Only support string arrays in RPC mode - factory functions are ignored\n\t\t\tif (content === undefined || Array.isArray(content)) {\n\t\t\t\toutput({\n\t\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\t\tmethod: \"setWidget\",\n\t\t\t\t\twidgetKey: key,\n\t\t\t\t\twidgetLines: content as string[] | undefined,\n\t\t\t\t\twidgetPlacement: options?.placement,\n\t\t\t\t} as RpcExtensionUIRequest);\n\t\t\t}\n\t\t\t// Component factories are not supported in RPC mode - would need TUI access\n\t\t},\n\n\t\tsetFooter(_factory: unknown): void {\n\t\t\t// Custom footer not supported in RPC mode - requires TUI access\n\t\t},\n\n\t\tsetHeader(_factory: unknown): void {\n\t\t\t// Custom header not supported in RPC mode - requires TUI access\n\t\t},\n\n\t\tsetTitle(title: string): void {\n\t\t\t// Fire and forget - host can implement terminal title control\n\t\t\toutput({\n\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tmethod: \"setTitle\",\n\t\t\t\ttitle,\n\t\t\t} as RpcExtensionUIRequest);\n\t\t},\n\n\t\tasync custom() {\n\t\t\t// Custom UI not supported in RPC mode\n\t\t\treturn undefined as never;\n\t\t},\n\n\t\tpasteToEditor(text: string): void {\n\t\t\t// Paste handling not supported in RPC mode - falls back to setEditorText\n\t\t\tthis.setEditorText(text);\n\t\t},\n\n\t\tsetEditorText(text: string): void {\n\t\t\t// Fire and forget - host can implement editor control\n\t\t\toutput({\n\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tmethod: \"set_editor_text\",\n\t\t\t\ttext,\n\t\t\t} as RpcExtensionUIRequest);\n\t\t},\n\n\t\tgetEditorText(): string {\n\t\t\t// Synchronous method can't wait for RPC response\n\t\t\t// Host should track editor state locally if needed\n\t\t\treturn \"\";\n\t\t},\n\n\t\tasync editor(title: string, prefill?: string): Promise<string | undefined> {\n\t\t\tconst id = crypto.randomUUID();\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tpendingExtensionRequests.set(id, {\n\t\t\t\t\tresolve: (response: RpcExtensionUIResponse) => {\n\t\t\t\t\t\tif (\"cancelled\" in response && response.cancelled) {\n\t\t\t\t\t\t\tresolve(undefined);\n\t\t\t\t\t\t} else if (\"value\" in response) {\n\t\t\t\t\t\t\tresolve(response.value);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresolve(undefined);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\treject,\n\t\t\t\t});\n\t\t\t\toutput({ type: \"extension_ui_request\", id, method: \"editor\", title, prefill } as RpcExtensionUIRequest);\n\t\t\t});\n\t\t},\n\n\t\taddAutocompleteProvider(): void {\n\t\t\t// Autocomplete provider composition is not supported in RPC mode\n\t\t},\n\n\t\tsetEditorComponent(): void {\n\t\t\t// Custom editor components not supported in RPC mode\n\t\t},\n\n\t\tgetEditorComponent() {\n\t\t\t// Custom editor components not supported in RPC mode\n\t\t\treturn undefined;\n\t\t},\n\n\t\tget theme() {\n\t\t\treturn theme;\n\t\t},\n\n\t\tgetAllThemes() {\n\t\t\treturn [];\n\t\t},\n\n\t\tgetTheme(_name: string) {\n\t\t\treturn undefined;\n\t\t},\n\n\t\tsetTheme(_theme: string | Theme) {\n\t\t\t// Theme switching not supported in RPC mode\n\t\t\treturn { success: false, error: \"Theme switching not supported in RPC mode\" };\n\t\t},\n\n\t\tgetToolsExpanded() {\n\t\t\t// Tool expansion not supported in RPC mode - no TUI\n\t\t\treturn false;\n\t\t},\n\n\t\tsetToolsExpanded(_expanded: boolean) {\n\t\t\t// Tool expansion not supported in RPC mode - no TUI\n\t\t},\n\t});\n\n\truntimeHost.setRebindSession(async () => {\n\t\tawait rebindSession();\n\t});\n\n\tconst rebindSession = async (): Promise<void> => {\n\t\tsession = runtimeHost.session;\n\t\tawait session.bindExtensions({\n\t\t\tuiContext: createExtensionUIContext(),\n\t\t\tcommandContextActions: {\n\t\t\t\twaitForIdle: () => session.agent.waitForIdle(),\n\t\t\t\tnewSession: async (options) => runtimeHost.newSession(options),\n\t\t\t\tfork: async (entryId, forkOptions) => {\n\t\t\t\t\tconst result = await runtimeHost.fork(entryId, forkOptions);\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tnavigateTree: async (targetId, options) => {\n\t\t\t\t\tconst result = await session.navigateTree(targetId, {\n\t\t\t\t\t\tsummarize: options?.summarize,\n\t\t\t\t\t\tcustomInstructions: options?.customInstructions,\n\t\t\t\t\t\treplaceInstructions: options?.replaceInstructions,\n\t\t\t\t\t\tlabel: options?.label,\n\t\t\t\t\t});\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tswitchSession: async (sessionPath, options) => {\n\t\t\t\t\treturn runtimeHost.switchSession(sessionPath, options);\n\t\t\t\t},\n\t\t\t\treload: async () => {\n\t\t\t\t\tawait session.reload();\n\t\t\t\t},\n\t\t\t},\n\t\t\tshutdownHandler: () => {\n\t\t\t\tshutdownRequested = true;\n\t\t\t},\n\t\t\tonError: (err) => {\n\t\t\t\toutput({ type: \"extension_error\", extensionPath: err.extensionPath, event: err.event, error: err.error });\n\t\t\t},\n\t\t});\n\n\t\tunsubscribe?.();\n\t\tunsubscribeBackpressure?.();\n\t\tunsubscribe = session.subscribe((event) => {\n\t\t\toutput(event);\n\t\t});\n\t\tunsubscribeBackpressure = session.agent.subscribe(async () => {\n\t\t\tawait waitForRawStdoutBackpressure();\n\t\t});\n\t};\n\n\tconst registerSignalHandlers = (): void => {\n\t\tconst signals: NodeJS.Signals[] = [\"SIGTERM\"];\n\t\tif (process.platform !== \"win32\") {\n\t\t\tsignals.push(\"SIGHUP\");\n\t\t}\n\n\t\tfor (const signal of signals) {\n\t\t\tconst handler = () => {\n\t\t\t\tkillTrackedDetachedChildren();\n\t\t\t\tvoid shutdown(signal === \"SIGHUP\" ? 129 : 143, signal);\n\t\t\t};\n\t\t\tprocess.on(signal, handler);\n\t\t\tsignalCleanupHandlers.push(() => process.off(signal, handler));\n\t\t}\n\t};\n\n\tawait rebindSession();\n\tregisterSignalHandlers();\n\n\t// Handle a single command\n\tconst handleCommand = async (command: RpcCommand): Promise<RpcResponse | undefined> => {\n\t\tconst id = command.id;\n\n\t\tswitch (command.type) {\n\t\t\t// =================================================================\n\t\t\t// Prompting\n\t\t\t// =================================================================\n\n\t\t\tcase \"prompt\": {\n\t\t\t\t// Start prompt handling immediately, but emit the authoritative response only after\n\t\t\t\t// prompt preflight succeeds. Queued and immediately handled prompts also count as success.\n\t\t\t\tlet preflightSucceeded = false;\n\t\t\t\tvoid session\n\t\t\t\t\t.prompt(command.message, {\n\t\t\t\t\t\timages: command.images,\n\t\t\t\t\t\tstreamingBehavior: command.streamingBehavior,\n\t\t\t\t\t\tsource: \"rpc\",\n\t\t\t\t\t\tpreflightResult: (didSucceed) => {\n\t\t\t\t\t\t\tif (didSucceed) {\n\t\t\t\t\t\t\t\tpreflightSucceeded = true;\n\t\t\t\t\t\t\t\toutput(success(id, \"prompt\"));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t\t.catch((e) => {\n\t\t\t\t\t\tif (!preflightSucceeded) {\n\t\t\t\t\t\t\toutput(error(id, \"prompt\", e.message));\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tcase \"steer\": {\n\t\t\t\tawait session.steer(command.message, command.images);\n\t\t\t\treturn success(id, \"steer\");\n\t\t\t}\n\n\t\t\tcase \"follow_up\": {\n\t\t\t\tawait session.followUp(command.message, command.images);\n\t\t\t\treturn success(id, \"follow_up\");\n\t\t\t}\n\n\t\t\tcase \"abort\": {\n\t\t\t\tawait session.abort();\n\t\t\t\treturn success(id, \"abort\");\n\t\t\t}\n\n\t\t\tcase \"new_session\": {\n\t\t\t\tconst options = command.parentSession ? { parentSession: command.parentSession } : undefined;\n\t\t\t\tconst result = await runtimeHost.newSession(options);\n\t\t\t\tif (!result.cancelled) {\n\t\t\t\t\tawait rebindSession();\n\t\t\t\t}\n\t\t\t\treturn success(id, \"new_session\", result);\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// State\n\t\t\t// =================================================================\n\n\t\t\tcase \"get_state\": {\n\t\t\t\tconst state: RpcSessionState = {\n\t\t\t\t\tmodel: session.model,\n\t\t\t\t\tthinkingLevel: session.thinkingLevel,\n\t\t\t\t\tisStreaming: session.isStreaming,\n\t\t\t\t\tisCompacting: session.isCompacting,\n\t\t\t\t\tsteeringMode: session.steeringMode,\n\t\t\t\t\tfollowUpMode: session.followUpMode,\n\t\t\t\t\tsessionFile: session.sessionFile,\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tsessionName: session.sessionName,\n\t\t\t\t\tautoCompactionEnabled: session.autoCompactionEnabled,\n\t\t\t\t\tmessageCount: session.messages.length,\n\t\t\t\t\tpendingMessageCount: session.pendingMessageCount,\n\t\t\t\t};\n\t\t\t\treturn success(id, \"get_state\", state);\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Model\n\t\t\t// =================================================================\n\n\t\t\tcase \"set_model\": {\n\t\t\t\tconst models = await session.modelRegistry.getAvailable();\n\t\t\t\tconst model = models.find((m) => m.provider === command.provider && m.id === command.modelId);\n\t\t\t\tif (!model) {\n\t\t\t\t\treturn error(id, \"set_model\", `Model not found: ${command.provider}/${command.modelId}`);\n\t\t\t\t}\n\t\t\t\tawait session.setModel(model);\n\t\t\t\treturn success(id, \"set_model\", model);\n\t\t\t}\n\n\t\t\tcase \"cycle_model\": {\n\t\t\t\tconst result = await session.cycleModel();\n\t\t\t\tif (!result) {\n\t\t\t\t\treturn success(id, \"cycle_model\", null);\n\t\t\t\t}\n\t\t\t\treturn success(id, \"cycle_model\", result);\n\t\t\t}\n\n\t\t\tcase \"get_available_models\": {\n\t\t\t\tconst models = await session.modelRegistry.getAvailable();\n\t\t\t\treturn success(id, \"get_available_models\", { models });\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Thinking\n\t\t\t// =================================================================\n\n\t\t\tcase \"set_thinking_level\": {\n\t\t\t\tsession.setThinkingLevel(command.level);\n\t\t\t\treturn success(id, \"set_thinking_level\");\n\t\t\t}\n\n\t\t\tcase \"cycle_thinking_level\": {\n\t\t\t\tconst level = session.cycleThinkingLevel();\n\t\t\t\tif (!level) {\n\t\t\t\t\treturn success(id, \"cycle_thinking_level\", null);\n\t\t\t\t}\n\t\t\t\treturn success(id, \"cycle_thinking_level\", { level });\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Queue Modes\n\t\t\t// =================================================================\n\n\t\t\tcase \"set_steering_mode\": {\n\t\t\t\tsession.setSteeringMode(command.mode);\n\t\t\t\treturn success(id, \"set_steering_mode\");\n\t\t\t}\n\n\t\t\tcase \"set_follow_up_mode\": {\n\t\t\t\tsession.setFollowUpMode(command.mode);\n\t\t\t\treturn success(id, \"set_follow_up_mode\");\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Compaction\n\t\t\t// =================================================================\n\n\t\t\tcase \"compact\": {\n\t\t\t\tconst result = await session.compact(command.customInstructions);\n\t\t\t\treturn success(id, \"compact\", result);\n\t\t\t}\n\n\t\t\tcase \"set_auto_compaction\": {\n\t\t\t\tsession.setAutoCompactionEnabled(command.enabled);\n\t\t\t\treturn success(id, \"set_auto_compaction\");\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Retry\n\t\t\t// =================================================================\n\n\t\t\tcase \"set_auto_retry\": {\n\t\t\t\tsession.setAutoRetryEnabled(command.enabled);\n\t\t\t\treturn success(id, \"set_auto_retry\");\n\t\t\t}\n\n\t\t\tcase \"abort_retry\": {\n\t\t\t\tsession.abortRetry();\n\t\t\t\treturn success(id, \"abort_retry\");\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Bash\n\t\t\t// =================================================================\n\n\t\t\tcase \"bash\": {\n\t\t\t\tconst result = await session.executeBash(command.command, undefined, {\n\t\t\t\t\texcludeFromContext: command.excludeFromContext,\n\t\t\t\t});\n\t\t\t\treturn success(id, \"bash\", result);\n\t\t\t}\n\n\t\t\tcase \"abort_bash\": {\n\t\t\t\tsession.abortBash();\n\t\t\t\treturn success(id, \"abort_bash\");\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Session\n\t\t\t// =================================================================\n\n\t\t\tcase \"get_session_stats\": {\n\t\t\t\tconst stats = session.getSessionStats();\n\t\t\t\treturn success(id, \"get_session_stats\", stats);\n\t\t\t}\n\n\t\t\tcase \"export_html\": {\n\t\t\t\tconst path = await session.exportToHtml(command.outputPath);\n\t\t\t\treturn success(id, \"export_html\", { path });\n\t\t\t}\n\n\t\t\tcase \"switch_session\": {\n\t\t\t\tconst result = await runtimeHost.switchSession(command.sessionPath);\n\t\t\t\tif (!result.cancelled) {\n\t\t\t\t\tawait rebindSession();\n\t\t\t\t}\n\t\t\t\treturn success(id, \"switch_session\", result);\n\t\t\t}\n\n\t\t\tcase \"fork\": {\n\t\t\t\tconst result = await runtimeHost.fork(command.entryId);\n\t\t\t\tif (!result.cancelled) {\n\t\t\t\t\tawait rebindSession();\n\t\t\t\t}\n\t\t\t\treturn success(id, \"fork\", { text: result.selectedText, cancelled: result.cancelled });\n\t\t\t}\n\n\t\t\tcase \"clone\": {\n\t\t\t\tconst leafId = session.sessionManager.getLeafId();\n\t\t\t\tif (!leafId) {\n\t\t\t\t\treturn error(id, \"clone\", \"Cannot clone session: no current entry selected\");\n\t\t\t\t}\n\t\t\t\tconst result = await runtimeHost.fork(leafId, { position: \"at\" });\n\t\t\t\tif (!result.cancelled) {\n\t\t\t\t\tawait rebindSession();\n\t\t\t\t}\n\t\t\t\treturn success(id, \"clone\", { cancelled: result.cancelled });\n\t\t\t}\n\n\t\t\tcase \"get_fork_messages\": {\n\t\t\t\tconst messages = session.getUserMessagesForForking();\n\t\t\t\treturn success(id, \"get_fork_messages\", { messages });\n\t\t\t}\n\n\t\t\tcase \"get_last_assistant_text\": {\n\t\t\t\tconst text = session.getLastAssistantText();\n\t\t\t\treturn success(id, \"get_last_assistant_text\", { text });\n\t\t\t}\n\n\t\t\tcase \"set_session_name\": {\n\t\t\t\tconst name = command.name.trim();\n\t\t\t\tif (!name) {\n\t\t\t\t\treturn error(id, \"set_session_name\", \"Session name cannot be empty\");\n\t\t\t\t}\n\t\t\t\tsession.setSessionName(name);\n\t\t\t\treturn success(id, \"set_session_name\");\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Messages\n\t\t\t// =================================================================\n\n\t\t\tcase \"get_messages\": {\n\t\t\t\treturn success(id, \"get_messages\", { messages: session.messages });\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Commands (available for invocation via prompt)\n\t\t\t// =================================================================\n\n\t\t\tcase \"get_commands\": {\n\t\t\t\tconst commands: RpcSlashCommand[] = [];\n\n\t\t\t\tfor (const command of session.extensionRunner.getRegisteredCommands()) {\n\t\t\t\t\tcommands.push({\n\t\t\t\t\t\tname: command.invocationName,\n\t\t\t\t\t\tdescription: command.description,\n\t\t\t\t\t\tsource: \"extension\",\n\t\t\t\t\t\tsourceInfo: command.sourceInfo,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tfor (const template of session.promptTemplates) {\n\t\t\t\t\tcommands.push({\n\t\t\t\t\t\tname: template.name,\n\t\t\t\t\t\tdescription: template.description,\n\t\t\t\t\t\tsource: \"prompt\",\n\t\t\t\t\t\tsourceInfo: template.sourceInfo,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tfor (const skill of session.resourceLoader.getSkills().skills) {\n\t\t\t\t\tcommands.push({\n\t\t\t\t\t\tname: `skill:${skill.name}`,\n\t\t\t\t\t\tdescription: skill.description,\n\t\t\t\t\t\tsource: \"skill\",\n\t\t\t\t\t\tsourceInfo: skill.sourceInfo,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\treturn success(id, \"get_commands\", { commands });\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst unknownCommand = command as { type: string };\n\t\t\t\treturn error(undefined, unknownCommand.type, `Unknown command: ${unknownCommand.type}`);\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Check if shutdown was requested and perform shutdown if so.\n\t * Called after handling each command when waiting for the next command.\n\t */\n\tlet detachInput = () => {};\n\n\tasync function shutdown(exitCode = 0, signal?: NodeJS.Signals): Promise<never> {\n\t\tif (shuttingDown) {\n\t\t\tprocess.exit(exitCode);\n\t\t}\n\t\tshuttingDown = true;\n\t\tfor (const cleanup of signalCleanupHandlers) {\n\t\t\tcleanup();\n\t\t}\n\t\tunsubscribe?.();\n\t\tunsubscribeBackpressure?.();\n\t\tawait runtimeHost.dispose();\n\t\tdetachInput();\n\t\tprocess.stdin.pause();\n\t\tif (signal !== \"SIGTERM\") {\n\t\t\tawait flushRawStdout();\n\t\t}\n\t\tprocess.exit(exitCode);\n\t}\n\n\tasync function checkShutdownRequested(): Promise<void> {\n\t\tif (!shutdownRequested) return;\n\t\tawait shutdown();\n\t}\n\n\tconst handleInputLine = async (line: string) => {\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(line);\n\t\t} catch (parseError: unknown) {\n\t\t\toutput(\n\t\t\t\terror(\n\t\t\t\t\tundefined,\n\t\t\t\t\t\"parse\",\n\t\t\t\t\t`Failed to parse command: ${parseError instanceof Error ? parseError.message : String(parseError)}`,\n\t\t\t\t),\n\t\t\t);\n\t\t\tawait waitForRawStdoutBackpressure();\n\t\t\treturn;\n\t\t}\n\n\t\t// Handle extension UI responses\n\t\tif (\n\t\t\ttypeof parsed === \"object\" &&\n\t\t\tparsed !== null &&\n\t\t\t\"type\" in parsed &&\n\t\t\tparsed.type === \"extension_ui_response\"\n\t\t) {\n\t\t\tconst response = parsed as RpcExtensionUIResponse;\n\t\t\tconst pending = pendingExtensionRequests.get(response.id);\n\t\t\tif (pending) {\n\t\t\t\tpendingExtensionRequests.delete(response.id);\n\t\t\t\tpending.resolve(response);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst command = parsed as RpcCommand;\n\t\ttry {\n\t\t\tconst response = await handleCommand(command);\n\t\t\tif (response) {\n\t\t\t\toutput(response);\n\t\t\t\tawait waitForRawStdoutBackpressure();\n\t\t\t}\n\t\t\tawait checkShutdownRequested();\n\t\t} catch (commandError: unknown) {\n\t\t\toutput(\n\t\t\t\terror(\n\t\t\t\t\tcommand.id,\n\t\t\t\t\tcommand.type,\n\t\t\t\t\tcommandError instanceof Error ? commandError.message : String(commandError),\n\t\t\t\t),\n\t\t\t);\n\t\t\tawait waitForRawStdoutBackpressure();\n\t\t}\n\t};\n\n\tconst onInputEnd = () => {\n\t\tvoid shutdown();\n\t};\n\tprocess.stdin.on(\"end\", onInputEnd);\n\n\tdetachInput = (() => {\n\t\tconst detachJsonl = attachJsonlLineReader(process.stdin, (line) => {\n\t\t\tvoid handleInputLine(line);\n\t\t});\n\t\treturn () => {\n\t\t\tdetachJsonl();\n\t\t\tprocess.stdin.off(\"end\", onInputEnd);\n\t\t};\n\t})();\n\n\t// Keep process alive forever\n\treturn new Promise(() => {});\n}\n"]}
1
+ {"version":3,"file":"rpc-mode.js","sourceRoot":"","sources":["../../../src/modes/rpc/rpc-mode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AAQtC,OAAO,EACN,cAAc,EACd,cAAc,EACd,4BAA4B,EAC5B,cAAc,GACd,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAc,KAAK,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAmBtE;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,WAAgC,EAAkB;IAClF,cAAc,EAAE,CAAC;IACjB,IAAI,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC;IAClC,IAAI,WAAqC,CAAC;IAC1C,IAAI,uBAAiD,CAAC;IAEtD,MAAM,MAAM,GAAG,CAAC,GAAiD,EAAE,EAAE,CAAC;QACrE,cAAc,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC;IAAA,CACvC,CAAC;IAEF,MAAM,OAAO,GAAG,CACf,EAAsB,EACtB,OAAU,EACV,IAAoB,EACN,EAAE,CAAC;QACjB,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAiB,CAAC;QACxE,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAiB,CAAC;IAAA,CAC7E,CAAC;IAEF,MAAM,KAAK,GAAG,CAAC,EAAsB,EAAE,OAAe,EAAE,OAAe,EAAe,EAAE,CAAC;QACxF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IAAA,CACzE,CAAC;IAEF,qDAAqD;IACrD,MAAM,wBAAwB,GAAG,IAAI,GAAG,EAGrC,CAAC;IAEJ,wBAAwB;IACxB,IAAI,iBAAiB,GAAG,KAAK,CAAC;IAC9B,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,MAAM,qBAAqB,GAAsB,EAAE,CAAC;IAEpD,4DAA4D;IAC5D,SAAS,mBAAmB,CAC3B,IAA0C,EAC1C,YAAe,EACf,OAAgC,EAChC,aAAsD,EACzC;QACb,IAAI,IAAI,EAAE,MAAM,EAAE,OAAO;YAAE,OAAO,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAEhE,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;QAC/B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC;YACvC,IAAI,SAAoD,CAAC;YAEzD,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC;gBACrB,IAAI,SAAS;oBAAE,YAAY,CAAC,SAAS,CAAC,CAAC;gBACvC,IAAI,EAAE,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBACpD,wBAAwB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAAA,CACpC,CAAC;YAEF,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC;gBACrB,OAAO,EAAE,CAAC;gBACV,OAAO,CAAC,YAAY,CAAC,CAAC;YAAA,CACtB,CAAC;YACF,IAAI,EAAE,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAEjE,IAAI,IAAI,EAAE,OAAO,EAAE,CAAC;gBACnB,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC;oBAC5B,OAAO,EAAE,CAAC;oBACV,OAAO,CAAC,YAAY,CAAC,CAAC;gBAAA,CACtB,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YAClB,CAAC;YAED,wBAAwB,CAAC,GAAG,CAAC,EAAE,EAAE;gBAChC,OAAO,EAAE,CAAC,QAAgC,EAAE,EAAE,CAAC;oBAC9C,OAAO,EAAE,CAAC;oBACV,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAAA,CACjC;gBACD,MAAM;aACN,CAAC,CAAC;YACH,MAAM,CAAC,EAAE,IAAI,EAAE,sBAAsB,EAAE,EAAE,EAAE,GAAG,OAAO,EAA2B,CAAC,CAAC;QAAA,CAClF,CAAC,CAAC;IAAA,CACH;IAED;;OAEG;IACH,MAAM,wBAAwB,GAAG,GAAuB,EAAE,CAAC,CAAC;QAC3D,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAChC,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CACxG,WAAW,IAAI,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAChF;QAEF,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CACjC,mBAAmB,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CACrG,WAAW,IAAI,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAChF;QAEF,KAAK,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,CACnC,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAC3G,WAAW,IAAI,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAChF;QAEF,MAAM,CAAC,OAAe,EAAE,IAAmC,EAAQ;YAClE,uCAAuC;YACvC,MAAM,CAAC;gBACN,IAAI,EAAE,sBAAsB;gBAC5B,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;gBACvB,MAAM,EAAE,QAAQ;gBAChB,OAAO;gBACP,UAAU,EAAE,IAAI;aACS,CAAC,CAAC;QAAA,CAC5B;QAED,eAAe,GAAe;YAC7B,+CAA+C;YAC/C,OAAO,GAAG,EAAE,CAAC,EAAC,CAAC,CAAC;QAAA,CAChB;QAED,SAAS,CAAC,GAAW,EAAE,IAAwB,EAAQ;YACtD,uCAAuC;YACvC,MAAM,CAAC;gBACN,IAAI,EAAE,sBAAsB;gBAC5B,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;gBACvB,MAAM,EAAE,WAAW;gBACnB,SAAS,EAAE,GAAG;gBACd,UAAU,EAAE,IAAI;aACS,CAAC,CAAC;QAAA,CAC5B;QAED,iBAAiB,CAAC,QAAiB,EAAQ;YAC1C,yEAAyE;QAD9B,CAE3C;QAED,iBAAiB,CAAC,QAAiB,EAAQ;YAC1C,4EAA4E;QADjC,CAE3C;QAED,mBAAmB,CAAC,QAAkC,EAAQ;YAC7D,yFAAyF;QAD3B,CAE9D;QAED,sBAAsB,CAAC,MAAe,EAAQ;YAC7C,0FAA0F;QAD5C,CAE9C;QAED,SAAS,CAAC,GAAW,EAAE,OAAgB,EAAE,OAAgC,EAAQ;YAChF,yEAAyE;YACzE,IAAI,OAAO,KAAK,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBACrD,MAAM,CAAC;oBACN,IAAI,EAAE,sBAAsB;oBAC5B,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;oBACvB,MAAM,EAAE,WAAW;oBACnB,SAAS,EAAE,GAAG;oBACd,WAAW,EAAE,OAA+B;oBAC5C,eAAe,EAAE,OAAO,EAAE,SAAS;iBACV,CAAC,CAAC;YAC7B,CAAC;YACD,4EAA4E;QAD3E,CAED;QAED,SAAS,CAAC,QAAiB,EAAQ;YAClC,gEAAgE;QAD7B,CAEnC;QAED,SAAS,CAAC,QAAiB,EAAQ;YAClC,gEAAgE;QAD7B,CAEnC;QAED,QAAQ,CAAC,KAAa,EAAQ;YAC7B,8DAA8D;YAC9D,MAAM,CAAC;gBACN,IAAI,EAAE,sBAAsB;gBAC5B,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;gBACvB,MAAM,EAAE,UAAU;gBAClB,KAAK;aACoB,CAAC,CAAC;QAAA,CAC5B;QAED,KAAK,CAAC,MAAM,GAAG;YACd,sCAAsC;YACtC,OAAO,SAAkB,CAAC;QAAA,CAC1B;QAED,aAAa,CAAC,IAAY,EAAQ;YACjC,yEAAyE;YACzE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAAA,CACzB;QAED,aAAa,CAAC,IAAY,EAAQ;YACjC,sDAAsD;YACtD,MAAM,CAAC;gBACN,IAAI,EAAE,sBAAsB;gBAC5B,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;gBACvB,MAAM,EAAE,iBAAiB;gBACzB,IAAI;aACqB,CAAC,CAAC;QAAA,CAC5B;QAED,aAAa,GAAW;YACvB,iDAAiD;YACjD,mDAAmD;YACnD,OAAO,EAAE,CAAC;QAAA,CACV;QAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,OAAgB,EAA+B;YAC1E,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;YAC/B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC;gBACvC,wBAAwB,CAAC,GAAG,CAAC,EAAE,EAAE;oBAChC,OAAO,EAAE,CAAC,QAAgC,EAAE,EAAE,CAAC;wBAC9C,IAAI,WAAW,IAAI,QAAQ,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;4BACnD,OAAO,CAAC,SAAS,CAAC,CAAC;wBACpB,CAAC;6BAAM,IAAI,OAAO,IAAI,QAAQ,EAAE,CAAC;4BAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;wBACzB,CAAC;6BAAM,CAAC;4BACP,OAAO,CAAC,SAAS,CAAC,CAAC;wBACpB,CAAC;oBAAA,CACD;oBACD,MAAM;iBACN,CAAC,CAAC;gBACH,MAAM,CAAC,EAAE,IAAI,EAAE,sBAAsB,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAA2B,CAAC,CAAC;YAAA,CACxG,CAAC,CAAC;QAAA,CACH;QAED,uBAAuB,GAAS;YAC/B,iEAAiE;QADjC,CAEhC;QAED,kBAAkB,GAAS;YAC1B,qDAAqD;QAD1B,CAE3B;QAED,kBAAkB,GAAG;YACpB,qDAAqD;YACrD,OAAO,SAAS,CAAC;QAAA,CACjB;QAED,IAAI,KAAK,GAAG;YACX,OAAO,KAAK,CAAC;QAAA,CACb;QAED,YAAY,GAAG;YACd,OAAO,EAAE,CAAC;QAAA,CACV;QAED,QAAQ,CAAC,KAAa,EAAE;YACvB,OAAO,SAAS,CAAC;QAAA,CACjB;QAED,QAAQ,CAAC,MAAsB,EAAE;YAChC,4CAA4C;YAC5C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,2CAA2C,EAAE,CAAC;QAAA,CAC9E;QAED,gBAAgB,GAAG;YAClB,oDAAoD;YACpD,OAAO,KAAK,CAAC;QAAA,CACb;QAED,gBAAgB,CAAC,SAAkB,EAAE;YACpC,oDAAoD;QADf,CAErC;KACD,CAAC,CAAC;IAEH,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,EAAE,CAAC;QACxC,MAAM,aAAa,EAAE,CAAC;IAAA,CACtB,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,KAAK,IAAmB,EAAE,CAAC;QAChD,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC;QAC9B,MAAM,OAAO,CAAC,cAAc,CAAC;YAC5B,SAAS,EAAE,wBAAwB,EAAE;YACrC,IAAI,EAAE,KAAK;YACX,qBAAqB,EAAE;gBACtB,WAAW,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE;gBAC9C,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC;gBAC9D,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,CAAC;oBACrC,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;oBAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;gBAAA,CACvC;gBACD,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC;oBAC1C,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,QAAQ,EAAE;wBACnD,SAAS,EAAE,OAAO,EAAE,SAAS;wBAC7B,kBAAkB,EAAE,OAAO,EAAE,kBAAkB;wBAC/C,mBAAmB,EAAE,OAAO,EAAE,mBAAmB;wBACjD,KAAK,EAAE,OAAO,EAAE,KAAK;qBACrB,CAAC,CAAC;oBACH,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;gBAAA,CACvC;gBACD,aAAa,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;oBAC9C,OAAO,WAAW,CAAC,aAAa,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;gBAAA,CACvD;gBACD,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC;oBACnB,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC;gBAAA,CACvB;aACD;YACD,eAAe,EAAE,GAAG,EAAE,CAAC;gBACtB,iBAAiB,GAAG,IAAI,CAAC;YAAA,CACzB;YACD,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC;gBACjB,MAAM,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,aAAa,EAAE,GAAG,CAAC,aAAa,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;YAAA,CAC1G;SACD,CAAC,CAAC;QAEH,WAAW,EAAE,EAAE,CAAC;QAChB,uBAAuB,EAAE,EAAE,CAAC;QAC5B,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;YAC1C,MAAM,CAAC,KAAK,CAAC,CAAC;QAAA,CACd,CAAC,CAAC;QACH,uBAAuB,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE,CAAC;YAC7D,MAAM,4BAA4B,EAAE,CAAC;QAAA,CACrC,CAAC,CAAC;IAAA,CACH,CAAC;IAEF,MAAM,sBAAsB,GAAG,GAAS,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAqB,CAAC,SAAS,CAAC,CAAC;QAC9C,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YAClC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxB,CAAC;QAED,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC;gBACrB,2BAA2B,EAAE,CAAC;gBAC9B,KAAK,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAAA,CACvD,CAAC;YACF,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAC5B,qBAAqB,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;QAChE,CAAC;IAAA,CACD,CAAC;IAEF,MAAM,aAAa,EAAE,CAAC;IACtB,sBAAsB,EAAE,CAAC;IAEzB,0BAA0B;IAC1B,MAAM,aAAa,GAAG,KAAK,EAAE,OAAmB,EAAoC,EAAE,CAAC;QACtF,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC;QAEtB,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;YACtB,oEAAoE;YACpE,YAAY;YACZ,oEAAoE;YAEpE,KAAK,QAAQ,EAAE,CAAC;gBACf,oFAAoF;gBACpF,2FAA2F;gBAC3F,IAAI,kBAAkB,GAAG,KAAK,CAAC;gBAC/B,KAAK,OAAO;qBACV,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE;oBACxB,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;oBAC5C,MAAM,EAAE,KAAK;oBACb,eAAe,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC;wBAChC,IAAI,UAAU,EAAE,CAAC;4BAChB,kBAAkB,GAAG,IAAI,CAAC;4BAC1B,MAAM,CAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;wBAC/B,CAAC;oBAAA,CACD;iBACD,CAAC;qBACD,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;oBACb,IAAI,CAAC,kBAAkB,EAAE,CAAC;wBACzB,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;oBACxC,CAAC;gBAAA,CACD,CAAC,CAAC;gBACJ,OAAO,SAAS,CAAC;YAClB,CAAC;YAED,KAAK,OAAO,EAAE,CAAC;gBACd,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;gBACrD,OAAO,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;YAC7B,CAAC;YAED,KAAK,WAAW,EAAE,CAAC;gBAClB,MAAM,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;gBACxD,OAAO,OAAO,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;YACjC,CAAC;YAED,KAAK,OAAO,EAAE,CAAC;gBACd,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;gBACtB,OAAO,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;YAC7B,CAAC;YAED,KAAK,aAAa,EAAE,CAAC;gBACpB,MAAM,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC7F,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;gBACrD,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;oBACvB,MAAM,aAAa,EAAE,CAAC;gBACvB,CAAC;gBACD,OAAO,OAAO,CAAC,EAAE,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;YAC3C,CAAC;YAED,oEAAoE;YACpE,QAAQ;YACR,oEAAoE;YAEpE,KAAK,WAAW,EAAE,CAAC;gBAClB,MAAM,KAAK,GAAoB;oBAC9B,KAAK,EAAE,OAAO,CAAC,KAAK;oBACpB,aAAa,EAAE,OAAO,CAAC,aAAa;oBACpC,WAAW,EAAE,OAAO,CAAC,WAAW;oBAChC,YAAY,EAAE,OAAO,CAAC,YAAY;oBAClC,YAAY,EAAE,OAAO,CAAC,YAAY;oBAClC,YAAY,EAAE,OAAO,CAAC,YAAY;oBAClC,WAAW,EAAE,OAAO,CAAC,WAAW;oBAChC,SAAS,EAAE,OAAO,CAAC,SAAS;oBAC5B,WAAW,EAAE,OAAO,CAAC,WAAW;oBAChC,qBAAqB,EAAE,OAAO,CAAC,qBAAqB;oBACpD,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM;oBACrC,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;iBAChD,CAAC;gBACF,OAAO,OAAO,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;YACxC,CAAC;YAED,oEAAoE;YACpE,QAAQ;YACR,oEAAoE;YAEpE,KAAK,WAAW,EAAE,CAAC;gBAClB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,YAAY,EAAE,CAAC;gBAC1D,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;gBAC9F,IAAI,CAAC,KAAK,EAAE,CAAC;oBACZ,OAAO,KAAK,CAAC,EAAE,EAAE,WAAW,EAAE,oBAAoB,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC1F,CAAC;gBACD,MAAM,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAC9B,OAAO,OAAO,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;YACxC,CAAC;YAED,KAAK,aAAa,EAAE,CAAC;gBACpB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC;gBAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;oBACb,OAAO,OAAO,CAAC,EAAE,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;gBACzC,CAAC;gBACD,OAAO,OAAO,CAAC,EAAE,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;YAC3C,CAAC;YAED,KAAK,sBAAsB,EAAE,CAAC;gBAC7B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,YAAY,EAAE,CAAC;gBAC1D,OAAO,OAAO,CAAC,EAAE,EAAE,sBAAsB,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YACxD,CAAC;YAED,oEAAoE;YACpE,WAAW;YACX,oEAAoE;YAEpE,KAAK,oBAAoB,EAAE,CAAC;gBAC3B,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;gBACxC,OAAO,OAAO,CAAC,EAAE,EAAE,oBAAoB,CAAC,CAAC;YAC1C,CAAC;YAED,KAAK,sBAAsB,EAAE,CAAC;gBAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;gBAC3C,IAAI,CAAC,KAAK,EAAE,CAAC;oBACZ,OAAO,OAAO,CAAC,EAAE,EAAE,sBAAsB,EAAE,IAAI,CAAC,CAAC;gBAClD,CAAC;gBACD,OAAO,OAAO,CAAC,EAAE,EAAE,sBAAsB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YACvD,CAAC;YAED,oEAAoE;YACpE,cAAc;YACd,oEAAoE;YAEpE,KAAK,mBAAmB,EAAE,CAAC;gBAC1B,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBACtC,OAAO,OAAO,CAAC,EAAE,EAAE,mBAAmB,CAAC,CAAC;YACzC,CAAC;YAED,KAAK,oBAAoB,EAAE,CAAC;gBAC3B,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBACtC,OAAO,OAAO,CAAC,EAAE,EAAE,oBAAoB,CAAC,CAAC;YAC1C,CAAC;YAED,oEAAoE;YACpE,aAAa;YACb,oEAAoE;YAEpE,KAAK,SAAS,EAAE,CAAC;gBAChB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;gBACjE,OAAO,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;YACvC,CAAC;YAED,KAAK,qBAAqB,EAAE,CAAC;gBAC5B,OAAO,CAAC,wBAAwB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBAClD,OAAO,OAAO,CAAC,EAAE,EAAE,qBAAqB,CAAC,CAAC;YAC3C,CAAC;YAED,oEAAoE;YACpE,QAAQ;YACR,oEAAoE;YAEpE,KAAK,gBAAgB,EAAE,CAAC;gBACvB,OAAO,CAAC,mBAAmB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBAC7C,OAAO,OAAO,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;YACtC,CAAC;YAED,KAAK,aAAa,EAAE,CAAC;gBACpB,OAAO,CAAC,UAAU,EAAE,CAAC;gBACrB,OAAO,OAAO,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;YACnC,CAAC;YAED,oEAAoE;YACpE,OAAO;YACP,oEAAoE;YAEpE,KAAK,MAAM,EAAE,CAAC;gBACb,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,EAAE;oBACpE,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;iBAC9C,CAAC,CAAC;gBACH,OAAO,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YACpC,CAAC;YAED,KAAK,YAAY,EAAE,CAAC;gBACnB,OAAO,CAAC,SAAS,EAAE,CAAC;gBACpB,OAAO,OAAO,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;YAClC,CAAC;YAED,oEAAoE;YACpE,UAAU;YACV,oEAAoE;YAEpE,KAAK,mBAAmB,EAAE,CAAC;gBAC1B,MAAM,KAAK,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;gBACxC,OAAO,OAAO,CAAC,EAAE,EAAE,mBAAmB,EAAE,KAAK,CAAC,CAAC;YAChD,CAAC;YAED,KAAK,aAAa,EAAE,CAAC;gBACpB,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;gBAC5D,OAAO,OAAO,CAAC,EAAE,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YAC7C,CAAC;YAED,KAAK,gBAAgB,EAAE,CAAC;gBACvB,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;gBACpE,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;oBACvB,MAAM,aAAa,EAAE,CAAC;gBACvB,CAAC;gBACD,OAAO,OAAO,CAAC,EAAE,EAAE,gBAAgB,EAAE,MAAM,CAAC,CAAC;YAC9C,CAAC;YAED,KAAK,MAAM,EAAE,CAAC;gBACb,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBACvD,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;oBACvB,MAAM,aAAa,EAAE,CAAC;gBACvB,CAAC;gBACD,OAAO,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,YAAY,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;YACxF,CAAC;YAED,KAAK,OAAO,EAAE,CAAC;gBACd,MAAM,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;gBAClD,IAAI,CAAC,MAAM,EAAE,CAAC;oBACb,OAAO,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,iDAAiD,CAAC,CAAC;gBAC9E,CAAC;gBACD,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;gBAClE,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;oBACvB,MAAM,aAAa,EAAE,CAAC;gBACvB,CAAC;gBACD,OAAO,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;YAC9D,CAAC;YAED,KAAK,mBAAmB,EAAE,CAAC;gBAC1B,MAAM,QAAQ,GAAG,OAAO,CAAC,yBAAyB,EAAE,CAAC;gBACrD,OAAO,OAAO,CAAC,EAAE,EAAE,mBAAmB,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;YACvD,CAAC;YAED,KAAK,yBAAyB,EAAE,CAAC;gBAChC,MAAM,IAAI,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC;gBAC5C,OAAO,OAAO,CAAC,EAAE,EAAE,yBAAyB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YACzD,CAAC;YAED,KAAK,kBAAkB,EAAE,CAAC;gBACzB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACjC,IAAI,CAAC,IAAI,EAAE,CAAC;oBACX,OAAO,KAAK,CAAC,EAAE,EAAE,kBAAkB,EAAE,8BAA8B,CAAC,CAAC;gBACtE,CAAC;gBACD,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;gBAC7B,OAAO,OAAO,CAAC,EAAE,EAAE,kBAAkB,CAAC,CAAC;YACxC,CAAC;YAED,oEAAoE;YACpE,WAAW;YACX,oEAAoE;YAEpE,KAAK,cAAc,EAAE,CAAC;gBACrB,OAAO,OAAO,CAAC,EAAE,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;YACpE,CAAC;YAED,oEAAoE;YACpE,iDAAiD;YACjD,oEAAoE;YAEpE,KAAK,cAAc,EAAE,CAAC;gBACrB,MAAM,QAAQ,GAAsB,EAAE,CAAC;gBAEvC,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,eAAe,CAAC,qBAAqB,EAAE,EAAE,CAAC;oBACvE,QAAQ,CAAC,IAAI,CAAC;wBACb,IAAI,EAAE,OAAO,CAAC,cAAc;wBAC5B,WAAW,EAAE,OAAO,CAAC,WAAW;wBAChC,MAAM,EAAE,WAAW;wBACnB,UAAU,EAAE,OAAO,CAAC,UAAU;qBAC9B,CAAC,CAAC;gBACJ,CAAC;gBAED,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;oBAChD,QAAQ,CAAC,IAAI,CAAC;wBACb,IAAI,EAAE,QAAQ,CAAC,IAAI;wBACnB,WAAW,EAAE,QAAQ,CAAC,WAAW;wBACjC,MAAM,EAAE,QAAQ;wBAChB,UAAU,EAAE,QAAQ,CAAC,UAAU;qBAC/B,CAAC,CAAC;gBACJ,CAAC;gBAED,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,CAAC;oBAC/D,QAAQ,CAAC,IAAI,CAAC;wBACb,IAAI,EAAE,SAAS,KAAK,CAAC,IAAI,EAAE;wBAC3B,WAAW,EAAE,KAAK,CAAC,WAAW;wBAC9B,MAAM,EAAE,OAAO;wBACf,UAAU,EAAE,KAAK,CAAC,UAAU;qBAC5B,CAAC,CAAC;gBACJ,CAAC;gBAED,OAAO,OAAO,CAAC,EAAE,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;YAClD,CAAC;YAED,SAAS,CAAC;gBACT,MAAM,cAAc,GAAG,OAA2B,CAAC;gBACnD,OAAO,KAAK,CAAC,SAAS,EAAE,cAAc,CAAC,IAAI,EAAE,oBAAoB,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC;YACzF,CAAC;QACF,CAAC;IAAA,CACD,CAAC;IAEF;;;OAGG;IACH,IAAI,WAAW,GAAG,GAAG,EAAE,CAAC,EAAC,CAAC,CAAC;IAE3B,KAAK,UAAU,QAAQ,CAAC,QAAQ,GAAG,CAAC,EAAE,MAAuB,EAAkB;QAC9E,IAAI,YAAY,EAAE,CAAC;YAClB,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxB,CAAC;QACD,YAAY,GAAG,IAAI,CAAC;QACpB,KAAK,MAAM,OAAO,IAAI,qBAAqB,EAAE,CAAC;YAC7C,OAAO,EAAE,CAAC;QACX,CAAC;QACD,WAAW,EAAE,EAAE,CAAC;QAChB,uBAAuB,EAAE,EAAE,CAAC;QAC5B,MAAM,WAAW,CAAC,OAAO,EAAE,CAAC;QAC5B,WAAW,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACtB,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,cAAc,EAAE,CAAC;QACxB,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAAA,CACvB;IAED,KAAK,UAAU,sBAAsB,GAAkB;QACtD,IAAI,CAAC,iBAAiB;YAAE,OAAO;QAC/B,MAAM,QAAQ,EAAE,CAAC;IAAA,CACjB;IAED,MAAM,eAAe,GAAG,KAAK,EAAE,IAAY,EAAE,EAAE,CAAC;QAC/C,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACJ,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;QAAC,OAAO,UAAmB,EAAE,CAAC;YAC9B,MAAM,CACL,KAAK,CACJ,SAAS,EACT,OAAO,EACP,4BAA4B,UAAU,YAAY,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CACnG,CACD,CAAC;YACF,MAAM,4BAA4B,EAAE,CAAC;YACrC,OAAO;QACR,CAAC;QAED,gCAAgC;QAChC,IACC,OAAO,MAAM,KAAK,QAAQ;YAC1B,MAAM,KAAK,IAAI;YACf,MAAM,IAAI,MAAM;YAChB,MAAM,CAAC,IAAI,KAAK,uBAAuB,EACtC,CAAC;YACF,MAAM,QAAQ,GAAG,MAAgC,CAAC;YAClD,MAAM,OAAO,GAAG,wBAAwB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YAC1D,IAAI,OAAO,EAAE,CAAC;gBACb,wBAAwB,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBAC7C,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC3B,CAAC;YACD,OAAO;QACR,CAAC;QAED,MAAM,OAAO,GAAG,MAAoB,CAAC;QACrC,IAAI,CAAC;YACJ,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;YAC9C,IAAI,QAAQ,EAAE,CAAC;gBACd,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACjB,MAAM,4BAA4B,EAAE,CAAC;YACtC,CAAC;YACD,MAAM,sBAAsB,EAAE,CAAC;QAChC,CAAC;QAAC,OAAO,YAAqB,EAAE,CAAC;YAChC,MAAM,CACL,KAAK,CACJ,OAAO,CAAC,EAAE,EACV,OAAO,CAAC,IAAI,EACZ,YAAY,YAAY,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAC3E,CACD,CAAC;YACF,MAAM,4BAA4B,EAAE,CAAC;QACtC,CAAC;IAAA,CACD,CAAC;IAEF,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC;QACxB,KAAK,QAAQ,EAAE,CAAC;IAAA,CAChB,CAAC;IACF,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IAEpC,WAAW,GAAG,CAAC,GAAG,EAAE,CAAC;QACpB,MAAM,WAAW,GAAG,qBAAqB,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;YAClE,KAAK,eAAe,CAAC,IAAI,CAAC,CAAC;QAAA,CAC3B,CAAC,CAAC;QACH,OAAO,GAAG,EAAE,CAAC;YACZ,WAAW,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAAA,CACrC,CAAC;IAAA,CACF,CAAC,EAAE,CAAC;IAEL,6BAA6B;IAC7B,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,EAAC,CAAC,CAAC,CAAC;AAAA,CAC7B","sourcesContent":["/**\n * RPC mode: Headless operation with JSON stdin/stdout protocol.\n *\n * Used for embedding the agent in other applications.\n * Receives commands as JSON on stdin, outputs events and responses as JSON on stdout.\n *\n * Protocol:\n * - Commands: JSON objects with `type` field, optional `id` for correlation\n * - Responses: JSON objects with `type: \"response\"`, `command`, `success`, and optional `data`/`error`\n * - Events: AgentSessionEvent objects streamed as they occur\n * - Extension UI: Extension UI requests are emitted, client responds with extension_ui_response\n */\n\nimport * as crypto from \"node:crypto\";\nimport type { AgentSessionRuntime } from \"../../core/agent-session-runtime.ts\";\nimport type {\n\tExtensionUIContext,\n\tExtensionUIDialogOptions,\n\tExtensionWidgetOptions,\n\tWorkingIndicatorOptions,\n} from \"../../core/extensions/index.ts\";\nimport {\n\tflushRawStdout,\n\ttakeOverStdout,\n\twaitForRawStdoutBackpressure,\n\twriteRawStdout,\n} from \"../../core/output-guard.ts\";\nimport { killTrackedDetachedChildren } from \"../../utils/shell.ts\";\nimport { type Theme, theme } from \"../interactive/theme/theme.ts\";\nimport { attachJsonlLineReader, serializeJsonLine } from \"./jsonl.ts\";\nimport type {\n\tRpcCommand,\n\tRpcExtensionUIRequest,\n\tRpcExtensionUIResponse,\n\tRpcResponse,\n\tRpcSessionState,\n\tRpcSlashCommand,\n} from \"./rpc-types.ts\";\n\n// Re-export types for consumers\nexport type {\n\tRpcCommand,\n\tRpcExtensionUIRequest,\n\tRpcExtensionUIResponse,\n\tRpcResponse,\n\tRpcSessionState,\n} from \"./rpc-types.ts\";\n\n/**\n * Run in RPC mode.\n * Listens for JSON commands on stdin, outputs events and responses on stdout.\n */\nexport async function runRpcMode(runtimeHost: AgentSessionRuntime): Promise<never> {\n\ttakeOverStdout();\n\tlet session = runtimeHost.session;\n\tlet unsubscribe: (() => void) | undefined;\n\tlet unsubscribeBackpressure: (() => void) | undefined;\n\n\tconst output = (obj: RpcResponse | RpcExtensionUIRequest | object) => {\n\t\twriteRawStdout(serializeJsonLine(obj));\n\t};\n\n\tconst success = <T extends RpcCommand[\"type\"]>(\n\t\tid: string | undefined,\n\t\tcommand: T,\n\t\tdata?: object | null,\n\t): RpcResponse => {\n\t\tif (data === undefined) {\n\t\t\treturn { id, type: \"response\", command, success: true } as RpcResponse;\n\t\t}\n\t\treturn { id, type: \"response\", command, success: true, data } as RpcResponse;\n\t};\n\n\tconst error = (id: string | undefined, command: string, message: string): RpcResponse => {\n\t\treturn { id, type: \"response\", command, success: false, error: message };\n\t};\n\n\t// Pending extension UI requests waiting for response\n\tconst pendingExtensionRequests = new Map<\n\t\tstring,\n\t\t{ resolve: (value: any) => void; reject: (error: Error) => void }\n\t>();\n\n\t// Shutdown request flag\n\tlet shutdownRequested = false;\n\tlet shuttingDown = false;\n\tconst signalCleanupHandlers: Array<() => void> = [];\n\n\t/** Helper for dialog methods with signal/timeout support */\n\tfunction createDialogPromise<T>(\n\t\topts: ExtensionUIDialogOptions | undefined,\n\t\tdefaultValue: T,\n\t\trequest: Record<string, unknown>,\n\t\tparseResponse: (response: RpcExtensionUIResponse) => T,\n\t): Promise<T> {\n\t\tif (opts?.signal?.aborted) return Promise.resolve(defaultValue);\n\n\t\tconst id = crypto.randomUUID();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n\t\t\tconst cleanup = () => {\n\t\t\t\tif (timeoutId) clearTimeout(timeoutId);\n\t\t\t\topts?.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\tpendingExtensionRequests.delete(id);\n\t\t\t};\n\n\t\t\tconst onAbort = () => {\n\t\t\t\tcleanup();\n\t\t\t\tresolve(defaultValue);\n\t\t\t};\n\t\t\topts?.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\t\t\tif (opts?.timeout) {\n\t\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\t\tcleanup();\n\t\t\t\t\tresolve(defaultValue);\n\t\t\t\t}, opts.timeout);\n\t\t\t}\n\n\t\t\tpendingExtensionRequests.set(id, {\n\t\t\t\tresolve: (response: RpcExtensionUIResponse) => {\n\t\t\t\t\tcleanup();\n\t\t\t\t\tresolve(parseResponse(response));\n\t\t\t\t},\n\t\t\t\treject,\n\t\t\t});\n\t\t\toutput({ type: \"extension_ui_request\", id, ...request } as RpcExtensionUIRequest);\n\t\t});\n\t}\n\n\t/**\n\t * Create an extension UI context that uses the RPC protocol.\n\t */\n\tconst createExtensionUIContext = (): ExtensionUIContext => ({\n\t\tselect: (title, options, opts) =>\n\t\t\tcreateDialogPromise(opts, undefined, { method: \"select\", title, options, timeout: opts?.timeout }, (r) =>\n\t\t\t\t\"cancelled\" in r && r.cancelled ? undefined : \"value\" in r ? r.value : undefined,\n\t\t\t),\n\n\t\tconfirm: (title, message, opts) =>\n\t\t\tcreateDialogPromise(opts, false, { method: \"confirm\", title, message, timeout: opts?.timeout }, (r) =>\n\t\t\t\t\"cancelled\" in r && r.cancelled ? false : \"confirmed\" in r ? r.confirmed : false,\n\t\t\t),\n\n\t\tinput: (title, placeholder, opts) =>\n\t\t\tcreateDialogPromise(opts, undefined, { method: \"input\", title, placeholder, timeout: opts?.timeout }, (r) =>\n\t\t\t\t\"cancelled\" in r && r.cancelled ? undefined : \"value\" in r ? r.value : undefined,\n\t\t\t),\n\n\t\tnotify(message: string, type?: \"info\" | \"warning\" | \"error\"): void {\n\t\t\t// Fire and forget - no response needed\n\t\t\toutput({\n\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tmethod: \"notify\",\n\t\t\t\tmessage,\n\t\t\t\tnotifyType: type,\n\t\t\t} as RpcExtensionUIRequest);\n\t\t},\n\n\t\tonTerminalInput(): () => void {\n\t\t\t// Raw terminal input not supported in RPC mode\n\t\t\treturn () => {};\n\t\t},\n\n\t\tsetStatus(key: string, text: string | undefined): void {\n\t\t\t// Fire and forget - no response needed\n\t\t\toutput({\n\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tmethod: \"setStatus\",\n\t\t\t\tstatusKey: key,\n\t\t\t\tstatusText: text,\n\t\t\t} as RpcExtensionUIRequest);\n\t\t},\n\n\t\tsetWorkingMessage(_message?: string): void {\n\t\t\t// Working message not supported in RPC mode - requires TUI loader access\n\t\t},\n\n\t\tsetWorkingVisible(_visible: boolean): void {\n\t\t\t// Working visibility not supported in RPC mode - requires TUI loader access\n\t\t},\n\n\t\tsetWorkingIndicator(_options?: WorkingIndicatorOptions): void {\n\t\t\t// Working indicator customization not supported in RPC mode - requires TUI loader access\n\t\t},\n\n\t\tsetHiddenThinkingLabel(_label?: string): void {\n\t\t\t// Hidden thinking label not supported in RPC mode - requires TUI message rendering access\n\t\t},\n\n\t\tsetWidget(key: string, content: unknown, options?: ExtensionWidgetOptions): void {\n\t\t\t// Only support string arrays in RPC mode - factory functions are ignored\n\t\t\tif (content === undefined || Array.isArray(content)) {\n\t\t\t\toutput({\n\t\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\t\tmethod: \"setWidget\",\n\t\t\t\t\twidgetKey: key,\n\t\t\t\t\twidgetLines: content as string[] | undefined,\n\t\t\t\t\twidgetPlacement: options?.placement,\n\t\t\t\t} as RpcExtensionUIRequest);\n\t\t\t}\n\t\t\t// Component factories are not supported in RPC mode - would need TUI access\n\t\t},\n\n\t\tsetFooter(_factory: unknown): void {\n\t\t\t// Custom footer not supported in RPC mode - requires TUI access\n\t\t},\n\n\t\tsetHeader(_factory: unknown): void {\n\t\t\t// Custom header not supported in RPC mode - requires TUI access\n\t\t},\n\n\t\tsetTitle(title: string): void {\n\t\t\t// Fire and forget - host can implement terminal title control\n\t\t\toutput({\n\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tmethod: \"setTitle\",\n\t\t\t\ttitle,\n\t\t\t} as RpcExtensionUIRequest);\n\t\t},\n\n\t\tasync custom() {\n\t\t\t// Custom UI not supported in RPC mode\n\t\t\treturn undefined as never;\n\t\t},\n\n\t\tpasteToEditor(text: string): void {\n\t\t\t// Paste handling not supported in RPC mode - falls back to setEditorText\n\t\t\tthis.setEditorText(text);\n\t\t},\n\n\t\tsetEditorText(text: string): void {\n\t\t\t// Fire and forget - host can implement editor control\n\t\t\toutput({\n\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\tmethod: \"set_editor_text\",\n\t\t\t\ttext,\n\t\t\t} as RpcExtensionUIRequest);\n\t\t},\n\n\t\tgetEditorText(): string {\n\t\t\t// Synchronous method can't wait for RPC response\n\t\t\t// Host should track editor state locally if needed\n\t\t\treturn \"\";\n\t\t},\n\n\t\tasync editor(title: string, prefill?: string): Promise<string | undefined> {\n\t\t\tconst id = crypto.randomUUID();\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tpendingExtensionRequests.set(id, {\n\t\t\t\t\tresolve: (response: RpcExtensionUIResponse) => {\n\t\t\t\t\t\tif (\"cancelled\" in response && response.cancelled) {\n\t\t\t\t\t\t\tresolve(undefined);\n\t\t\t\t\t\t} else if (\"value\" in response) {\n\t\t\t\t\t\t\tresolve(response.value);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresolve(undefined);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\treject,\n\t\t\t\t});\n\t\t\t\toutput({ type: \"extension_ui_request\", id, method: \"editor\", title, prefill } as RpcExtensionUIRequest);\n\t\t\t});\n\t\t},\n\n\t\taddAutocompleteProvider(): void {\n\t\t\t// Autocomplete provider composition is not supported in RPC mode\n\t\t},\n\n\t\tsetEditorComponent(): void {\n\t\t\t// Custom editor components not supported in RPC mode\n\t\t},\n\n\t\tgetEditorComponent() {\n\t\t\t// Custom editor components not supported in RPC mode\n\t\t\treturn undefined;\n\t\t},\n\n\t\tget theme() {\n\t\t\treturn theme;\n\t\t},\n\n\t\tgetAllThemes() {\n\t\t\treturn [];\n\t\t},\n\n\t\tgetTheme(_name: string) {\n\t\t\treturn undefined;\n\t\t},\n\n\t\tsetTheme(_theme: string | Theme) {\n\t\t\t// Theme switching not supported in RPC mode\n\t\t\treturn { success: false, error: \"Theme switching not supported in RPC mode\" };\n\t\t},\n\n\t\tgetToolsExpanded() {\n\t\t\t// Tool expansion not supported in RPC mode - no TUI\n\t\t\treturn false;\n\t\t},\n\n\t\tsetToolsExpanded(_expanded: boolean) {\n\t\t\t// Tool expansion not supported in RPC mode - no TUI\n\t\t},\n\t});\n\n\truntimeHost.setRebindSession(async () => {\n\t\tawait rebindSession();\n\t});\n\n\tconst rebindSession = async (): Promise<void> => {\n\t\tsession = runtimeHost.session;\n\t\tawait session.bindExtensions({\n\t\t\tuiContext: createExtensionUIContext(),\n\t\t\tmode: \"rpc\",\n\t\t\tcommandContextActions: {\n\t\t\t\twaitForIdle: () => session.agent.waitForIdle(),\n\t\t\t\tnewSession: async (options) => runtimeHost.newSession(options),\n\t\t\t\tfork: async (entryId, forkOptions) => {\n\t\t\t\t\tconst result = await runtimeHost.fork(entryId, forkOptions);\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tnavigateTree: async (targetId, options) => {\n\t\t\t\t\tconst result = await session.navigateTree(targetId, {\n\t\t\t\t\t\tsummarize: options?.summarize,\n\t\t\t\t\t\tcustomInstructions: options?.customInstructions,\n\t\t\t\t\t\treplaceInstructions: options?.replaceInstructions,\n\t\t\t\t\t\tlabel: options?.label,\n\t\t\t\t\t});\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tswitchSession: async (sessionPath, options) => {\n\t\t\t\t\treturn runtimeHost.switchSession(sessionPath, options);\n\t\t\t\t},\n\t\t\t\treload: async () => {\n\t\t\t\t\tawait session.reload();\n\t\t\t\t},\n\t\t\t},\n\t\t\tshutdownHandler: () => {\n\t\t\t\tshutdownRequested = true;\n\t\t\t},\n\t\t\tonError: (err) => {\n\t\t\t\toutput({ type: \"extension_error\", extensionPath: err.extensionPath, event: err.event, error: err.error });\n\t\t\t},\n\t\t});\n\n\t\tunsubscribe?.();\n\t\tunsubscribeBackpressure?.();\n\t\tunsubscribe = session.subscribe((event) => {\n\t\t\toutput(event);\n\t\t});\n\t\tunsubscribeBackpressure = session.agent.subscribe(async () => {\n\t\t\tawait waitForRawStdoutBackpressure();\n\t\t});\n\t};\n\n\tconst registerSignalHandlers = (): void => {\n\t\tconst signals: NodeJS.Signals[] = [\"SIGTERM\"];\n\t\tif (process.platform !== \"win32\") {\n\t\t\tsignals.push(\"SIGHUP\");\n\t\t}\n\n\t\tfor (const signal of signals) {\n\t\t\tconst handler = () => {\n\t\t\t\tkillTrackedDetachedChildren();\n\t\t\t\tvoid shutdown(signal === \"SIGHUP\" ? 129 : 143, signal);\n\t\t\t};\n\t\t\tprocess.on(signal, handler);\n\t\t\tsignalCleanupHandlers.push(() => process.off(signal, handler));\n\t\t}\n\t};\n\n\tawait rebindSession();\n\tregisterSignalHandlers();\n\n\t// Handle a single command\n\tconst handleCommand = async (command: RpcCommand): Promise<RpcResponse | undefined> => {\n\t\tconst id = command.id;\n\n\t\tswitch (command.type) {\n\t\t\t// =================================================================\n\t\t\t// Prompting\n\t\t\t// =================================================================\n\n\t\t\tcase \"prompt\": {\n\t\t\t\t// Start prompt handling immediately, but emit the authoritative response only after\n\t\t\t\t// prompt preflight succeeds. Queued and immediately handled prompts also count as success.\n\t\t\t\tlet preflightSucceeded = false;\n\t\t\t\tvoid session\n\t\t\t\t\t.prompt(command.message, {\n\t\t\t\t\t\timages: command.images,\n\t\t\t\t\t\tstreamingBehavior: command.streamingBehavior,\n\t\t\t\t\t\tsource: \"rpc\",\n\t\t\t\t\t\tpreflightResult: (didSucceed) => {\n\t\t\t\t\t\t\tif (didSucceed) {\n\t\t\t\t\t\t\t\tpreflightSucceeded = true;\n\t\t\t\t\t\t\t\toutput(success(id, \"prompt\"));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t\t.catch((e) => {\n\t\t\t\t\t\tif (!preflightSucceeded) {\n\t\t\t\t\t\t\toutput(error(id, \"prompt\", e.message));\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tcase \"steer\": {\n\t\t\t\tawait session.steer(command.message, command.images);\n\t\t\t\treturn success(id, \"steer\");\n\t\t\t}\n\n\t\t\tcase \"follow_up\": {\n\t\t\t\tawait session.followUp(command.message, command.images);\n\t\t\t\treturn success(id, \"follow_up\");\n\t\t\t}\n\n\t\t\tcase \"abort\": {\n\t\t\t\tawait session.abort();\n\t\t\t\treturn success(id, \"abort\");\n\t\t\t}\n\n\t\t\tcase \"new_session\": {\n\t\t\t\tconst options = command.parentSession ? { parentSession: command.parentSession } : undefined;\n\t\t\t\tconst result = await runtimeHost.newSession(options);\n\t\t\t\tif (!result.cancelled) {\n\t\t\t\t\tawait rebindSession();\n\t\t\t\t}\n\t\t\t\treturn success(id, \"new_session\", result);\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// State\n\t\t\t// =================================================================\n\n\t\t\tcase \"get_state\": {\n\t\t\t\tconst state: RpcSessionState = {\n\t\t\t\t\tmodel: session.model,\n\t\t\t\t\tthinkingLevel: session.thinkingLevel,\n\t\t\t\t\tisStreaming: session.isStreaming,\n\t\t\t\t\tisCompacting: session.isCompacting,\n\t\t\t\t\tsteeringMode: session.steeringMode,\n\t\t\t\t\tfollowUpMode: session.followUpMode,\n\t\t\t\t\tsessionFile: session.sessionFile,\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tsessionName: session.sessionName,\n\t\t\t\t\tautoCompactionEnabled: session.autoCompactionEnabled,\n\t\t\t\t\tmessageCount: session.messages.length,\n\t\t\t\t\tpendingMessageCount: session.pendingMessageCount,\n\t\t\t\t};\n\t\t\t\treturn success(id, \"get_state\", state);\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Model\n\t\t\t// =================================================================\n\n\t\t\tcase \"set_model\": {\n\t\t\t\tconst models = await session.modelRegistry.getAvailable();\n\t\t\t\tconst model = models.find((m) => m.provider === command.provider && m.id === command.modelId);\n\t\t\t\tif (!model) {\n\t\t\t\t\treturn error(id, \"set_model\", `Model not found: ${command.provider}/${command.modelId}`);\n\t\t\t\t}\n\t\t\t\tawait session.setModel(model);\n\t\t\t\treturn success(id, \"set_model\", model);\n\t\t\t}\n\n\t\t\tcase \"cycle_model\": {\n\t\t\t\tconst result = await session.cycleModel();\n\t\t\t\tif (!result) {\n\t\t\t\t\treturn success(id, \"cycle_model\", null);\n\t\t\t\t}\n\t\t\t\treturn success(id, \"cycle_model\", result);\n\t\t\t}\n\n\t\t\tcase \"get_available_models\": {\n\t\t\t\tconst models = await session.modelRegistry.getAvailable();\n\t\t\t\treturn success(id, \"get_available_models\", { models });\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Thinking\n\t\t\t// =================================================================\n\n\t\t\tcase \"set_thinking_level\": {\n\t\t\t\tsession.setThinkingLevel(command.level);\n\t\t\t\treturn success(id, \"set_thinking_level\");\n\t\t\t}\n\n\t\t\tcase \"cycle_thinking_level\": {\n\t\t\t\tconst level = session.cycleThinkingLevel();\n\t\t\t\tif (!level) {\n\t\t\t\t\treturn success(id, \"cycle_thinking_level\", null);\n\t\t\t\t}\n\t\t\t\treturn success(id, \"cycle_thinking_level\", { level });\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Queue Modes\n\t\t\t// =================================================================\n\n\t\t\tcase \"set_steering_mode\": {\n\t\t\t\tsession.setSteeringMode(command.mode);\n\t\t\t\treturn success(id, \"set_steering_mode\");\n\t\t\t}\n\n\t\t\tcase \"set_follow_up_mode\": {\n\t\t\t\tsession.setFollowUpMode(command.mode);\n\t\t\t\treturn success(id, \"set_follow_up_mode\");\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Compaction\n\t\t\t// =================================================================\n\n\t\t\tcase \"compact\": {\n\t\t\t\tconst result = await session.compact(command.customInstructions);\n\t\t\t\treturn success(id, \"compact\", result);\n\t\t\t}\n\n\t\t\tcase \"set_auto_compaction\": {\n\t\t\t\tsession.setAutoCompactionEnabled(command.enabled);\n\t\t\t\treturn success(id, \"set_auto_compaction\");\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Retry\n\t\t\t// =================================================================\n\n\t\t\tcase \"set_auto_retry\": {\n\t\t\t\tsession.setAutoRetryEnabled(command.enabled);\n\t\t\t\treturn success(id, \"set_auto_retry\");\n\t\t\t}\n\n\t\t\tcase \"abort_retry\": {\n\t\t\t\tsession.abortRetry();\n\t\t\t\treturn success(id, \"abort_retry\");\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Bash\n\t\t\t// =================================================================\n\n\t\t\tcase \"bash\": {\n\t\t\t\tconst result = await session.executeBash(command.command, undefined, {\n\t\t\t\t\texcludeFromContext: command.excludeFromContext,\n\t\t\t\t});\n\t\t\t\treturn success(id, \"bash\", result);\n\t\t\t}\n\n\t\t\tcase \"abort_bash\": {\n\t\t\t\tsession.abortBash();\n\t\t\t\treturn success(id, \"abort_bash\");\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Session\n\t\t\t// =================================================================\n\n\t\t\tcase \"get_session_stats\": {\n\t\t\t\tconst stats = session.getSessionStats();\n\t\t\t\treturn success(id, \"get_session_stats\", stats);\n\t\t\t}\n\n\t\t\tcase \"export_html\": {\n\t\t\t\tconst path = await session.exportToHtml(command.outputPath);\n\t\t\t\treturn success(id, \"export_html\", { path });\n\t\t\t}\n\n\t\t\tcase \"switch_session\": {\n\t\t\t\tconst result = await runtimeHost.switchSession(command.sessionPath);\n\t\t\t\tif (!result.cancelled) {\n\t\t\t\t\tawait rebindSession();\n\t\t\t\t}\n\t\t\t\treturn success(id, \"switch_session\", result);\n\t\t\t}\n\n\t\t\tcase \"fork\": {\n\t\t\t\tconst result = await runtimeHost.fork(command.entryId);\n\t\t\t\tif (!result.cancelled) {\n\t\t\t\t\tawait rebindSession();\n\t\t\t\t}\n\t\t\t\treturn success(id, \"fork\", { text: result.selectedText, cancelled: result.cancelled });\n\t\t\t}\n\n\t\t\tcase \"clone\": {\n\t\t\t\tconst leafId = session.sessionManager.getLeafId();\n\t\t\t\tif (!leafId) {\n\t\t\t\t\treturn error(id, \"clone\", \"Cannot clone session: no current entry selected\");\n\t\t\t\t}\n\t\t\t\tconst result = await runtimeHost.fork(leafId, { position: \"at\" });\n\t\t\t\tif (!result.cancelled) {\n\t\t\t\t\tawait rebindSession();\n\t\t\t\t}\n\t\t\t\treturn success(id, \"clone\", { cancelled: result.cancelled });\n\t\t\t}\n\n\t\t\tcase \"get_fork_messages\": {\n\t\t\t\tconst messages = session.getUserMessagesForForking();\n\t\t\t\treturn success(id, \"get_fork_messages\", { messages });\n\t\t\t}\n\n\t\t\tcase \"get_last_assistant_text\": {\n\t\t\t\tconst text = session.getLastAssistantText();\n\t\t\t\treturn success(id, \"get_last_assistant_text\", { text });\n\t\t\t}\n\n\t\t\tcase \"set_session_name\": {\n\t\t\t\tconst name = command.name.trim();\n\t\t\t\tif (!name) {\n\t\t\t\t\treturn error(id, \"set_session_name\", \"Session name cannot be empty\");\n\t\t\t\t}\n\t\t\t\tsession.setSessionName(name);\n\t\t\t\treturn success(id, \"set_session_name\");\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Messages\n\t\t\t// =================================================================\n\n\t\t\tcase \"get_messages\": {\n\t\t\t\treturn success(id, \"get_messages\", { messages: session.messages });\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Commands (available for invocation via prompt)\n\t\t\t// =================================================================\n\n\t\t\tcase \"get_commands\": {\n\t\t\t\tconst commands: RpcSlashCommand[] = [];\n\n\t\t\t\tfor (const command of session.extensionRunner.getRegisteredCommands()) {\n\t\t\t\t\tcommands.push({\n\t\t\t\t\t\tname: command.invocationName,\n\t\t\t\t\t\tdescription: command.description,\n\t\t\t\t\t\tsource: \"extension\",\n\t\t\t\t\t\tsourceInfo: command.sourceInfo,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tfor (const template of session.promptTemplates) {\n\t\t\t\t\tcommands.push({\n\t\t\t\t\t\tname: template.name,\n\t\t\t\t\t\tdescription: template.description,\n\t\t\t\t\t\tsource: \"prompt\",\n\t\t\t\t\t\tsourceInfo: template.sourceInfo,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tfor (const skill of session.resourceLoader.getSkills().skills) {\n\t\t\t\t\tcommands.push({\n\t\t\t\t\t\tname: `skill:${skill.name}`,\n\t\t\t\t\t\tdescription: skill.description,\n\t\t\t\t\t\tsource: \"skill\",\n\t\t\t\t\t\tsourceInfo: skill.sourceInfo,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\treturn success(id, \"get_commands\", { commands });\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst unknownCommand = command as { type: string };\n\t\t\t\treturn error(undefined, unknownCommand.type, `Unknown command: ${unknownCommand.type}`);\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Check if shutdown was requested and perform shutdown if so.\n\t * Called after handling each command when waiting for the next command.\n\t */\n\tlet detachInput = () => {};\n\n\tasync function shutdown(exitCode = 0, signal?: NodeJS.Signals): Promise<never> {\n\t\tif (shuttingDown) {\n\t\t\tprocess.exit(exitCode);\n\t\t}\n\t\tshuttingDown = true;\n\t\tfor (const cleanup of signalCleanupHandlers) {\n\t\t\tcleanup();\n\t\t}\n\t\tunsubscribe?.();\n\t\tunsubscribeBackpressure?.();\n\t\tawait runtimeHost.dispose();\n\t\tdetachInput();\n\t\tprocess.stdin.pause();\n\t\tif (signal !== \"SIGTERM\") {\n\t\t\tawait flushRawStdout();\n\t\t}\n\t\tprocess.exit(exitCode);\n\t}\n\n\tasync function checkShutdownRequested(): Promise<void> {\n\t\tif (!shutdownRequested) return;\n\t\tawait shutdown();\n\t}\n\n\tconst handleInputLine = async (line: string) => {\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(line);\n\t\t} catch (parseError: unknown) {\n\t\t\toutput(\n\t\t\t\terror(\n\t\t\t\t\tundefined,\n\t\t\t\t\t\"parse\",\n\t\t\t\t\t`Failed to parse command: ${parseError instanceof Error ? parseError.message : String(parseError)}`,\n\t\t\t\t),\n\t\t\t);\n\t\t\tawait waitForRawStdoutBackpressure();\n\t\t\treturn;\n\t\t}\n\n\t\t// Handle extension UI responses\n\t\tif (\n\t\t\ttypeof parsed === \"object\" &&\n\t\t\tparsed !== null &&\n\t\t\t\"type\" in parsed &&\n\t\t\tparsed.type === \"extension_ui_response\"\n\t\t) {\n\t\t\tconst response = parsed as RpcExtensionUIResponse;\n\t\t\tconst pending = pendingExtensionRequests.get(response.id);\n\t\t\tif (pending) {\n\t\t\t\tpendingExtensionRequests.delete(response.id);\n\t\t\t\tpending.resolve(response);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst command = parsed as RpcCommand;\n\t\ttry {\n\t\t\tconst response = await handleCommand(command);\n\t\t\tif (response) {\n\t\t\t\toutput(response);\n\t\t\t\tawait waitForRawStdoutBackpressure();\n\t\t\t}\n\t\t\tawait checkShutdownRequested();\n\t\t} catch (commandError: unknown) {\n\t\t\toutput(\n\t\t\t\terror(\n\t\t\t\t\tcommand.id,\n\t\t\t\t\tcommand.type,\n\t\t\t\t\tcommandError instanceof Error ? commandError.message : String(commandError),\n\t\t\t\t),\n\t\t\t);\n\t\t\tawait waitForRawStdoutBackpressure();\n\t\t}\n\t};\n\n\tconst onInputEnd = () => {\n\t\tvoid shutdown();\n\t};\n\tprocess.stdin.on(\"end\", onInputEnd);\n\n\tdetachInput = (() => {\n\t\tconst detachJsonl = attachJsonlLineReader(process.stdin, (line) => {\n\t\t\tvoid handleInputLine(line);\n\t\t});\n\t\treturn () => {\n\t\t\tdetachJsonl();\n\t\t\tprocess.stdin.off(\"end\", onInputEnd);\n\t\t};\n\t})();\n\n\t// Keep process alive forever\n\treturn new Promise(() => {});\n}\n"]}
@@ -860,9 +860,13 @@ All handlers receive `ctx: ExtensionContext`.
860
860
 
861
861
  UI methods for user interaction. See [Custom UI](#custom-ui) for full details.
862
862
 
863
+ ### ctx.mode
864
+
865
+ Current run mode: `"tui"`, `"rpc"`, `"json"`, or `"print"`. Use `ctx.mode === "tui"` to guard terminal-only features such as `custom()`, component factories, terminal input, and direct TUI rendering.
866
+
863
867
  ### ctx.hasUI
864
868
 
865
- `false` in print mode (`-p`) and JSON mode. `true` in interactive and RPC mode. In RPC mode, dialog methods (`select`, `confirm`, `input`, `editor`) work via the extension UI sub-protocol, and fire-and-forget methods (`notify`, `setStatus`, `setWidget`, `setTitle`, `setEditorText`) emit requests to the client. Some TUI-specific methods are no-ops or return defaults (see [rpc.md](rpc.md#extension-ui-protocol)).
869
+ `true` in TUI and RPC modes. `false` in print mode (`-p`) and JSON mode. Use this to guard dialog methods (`select`, `confirm`, `input`, `editor`) and fire-and-forget methods (`notify`, `setStatus`, `setWidget`, `setTitle`, `setEditorText`) that work in both TUI and RPC modes. In RPC mode, some TUI-specific methods are no-ops or return defaults (see [rpc.md](rpc.md#extension-ui-protocol)).
866
870
 
867
871
  ### ctx.cwd
868
872
 
@@ -978,6 +982,19 @@ pi.on("before_agent_start", (event, ctx) => {
978
982
 
979
983
  Command handlers receive `ExtensionCommandContext`, which extends `ExtensionContext` with session control methods. These are only available in commands because they can deadlock if called from event handlers.
980
984
 
985
+ ### ctx.getSystemPromptOptions()
986
+
987
+ Returns the base inputs Pi currently uses to build the system prompt.
988
+
989
+ ```typescript
990
+ const options = ctx.getSystemPromptOptions();
991
+ const contextPaths = options.contextFiles?.map((file) => file.path) ?? [];
992
+ ```
993
+
994
+ This has the same shape and mutability as `before_agent_start` `event.systemPromptOptions`: custom prompt, active tools, tool snippets, prompt guidelines, appended system prompt text, cwd, loaded context files, and loaded skills. It may include full context file contents, so treat it as sensitive extension-local data and avoid exposing it through command lists, logs, or autocomplete metadata.
995
+
996
+ This reports the current base prompt inputs. It does not include per-turn `before_agent_start` chained system-prompt changes, later `context` event message mutations, or `before_provider_request` payload rewrites.
997
+
981
998
  ### ctx.waitForIdle()
982
999
 
983
1000
  Wait for the agent to finish streaming:
@@ -2371,7 +2388,7 @@ const result = await ctx.ui.custom<string | null>(
2371
2388
  );
2372
2389
  ```
2373
2390
 
2374
- For advanced positioning (anchors, margins, percentages, responsive visibility), pass `overlayOptions`. Use `onHandle` to control visibility programmatically:
2391
+ For advanced positioning (anchors, margins, percentages, responsive visibility), pass `overlayOptions`. Use `onHandle` to control focus or visibility programmatically:
2375
2392
 
2376
2393
  ```typescript
2377
2394
  const result = await ctx.ui.custom<string | null>(
@@ -2379,12 +2396,19 @@ const result = await ctx.ui.custom<string | null>(
2379
2396
  {
2380
2397
  overlay: true,
2381
2398
  overlayOptions: { anchor: "top-right", width: "50%", margin: 2 },
2382
- onHandle: (handle) => { /* handle.setHidden(true/false) */ }
2399
+ onHandle: (handle) => {
2400
+ handle.focus(); // focus this overlay and bring it to the visual front
2401
+ // handle.unfocus({ target: editorComponent }); // release input to a specific component
2402
+ // handle.setHidden(true/false); // toggle visibility
2403
+ // handle.hide(); // permanently remove
2404
+ }
2383
2405
  }
2384
2406
  );
2385
2407
  ```
2386
2408
 
2387
- See [tui.md](tui.md) for the full `OverlayOptions` API and [overlay-qa-tests.ts](../examples/extensions/overlay-qa-tests.ts) for examples.
2409
+ A focused visible overlay can reclaim input after temporary non-overlay custom UI closes. If you intentionally want another component to keep input while the overlay stays visible, call `handle.unfocus({ target })`. Passing `{ target: null }` releases the overlay without focusing another component.
2410
+
2411
+ See [tui.md](tui.md) for the full `OverlayOptions` and `OverlayHandle` API and [overlay-qa-tests.ts](../examples/extensions/overlay-qa-tests.ts) for examples.
2388
2412
 
2389
2413
  ### Custom Editor
2390
2414
 
@@ -2509,14 +2533,14 @@ const highlighted = highlightCode(code, lang, theme);
2509
2533
 
2510
2534
  ## Mode Behavior
2511
2535
 
2512
- | Mode | UI Methods | Notes |
2513
- |------|-----------|-------|
2514
- | Interactive | Full TUI | Normal operation |
2515
- | RPC (`--mode rpc`) | JSON protocol | Host handles UI, see [rpc.md](rpc.md) |
2516
- | JSON (`--mode json`) | No-op | Event stream to stdout, see [json.md](json.md) |
2517
- | Print (`-p`) | No-op | Extensions run but can't prompt |
2536
+ | Mode | `ctx.mode` | `ctx.hasUI` | Notes |
2537
+ |------|------------|-------------|-------|
2538
+ | Interactive | `"tui"` | `true` | Full TUI with terminal rendering |
2539
+ | RPC (`--mode rpc`) | `"rpc"` | `true` | Dialogs and notifications via JSON protocol; `custom()` returns `undefined`. See [rpc.md](rpc.md) |
2540
+ | JSON (`--mode json`) | `"json"` | `false` | Event stream to stdout; UI methods are no-ops |
2541
+ | Print (`-p`) | `"print"` | `false` | Extensions run but can't prompt |
2518
2542
 
2519
- In non-interactive modes, check `ctx.hasUI` before using UI methods.
2543
+ Use `ctx.mode === "tui"` before TUI-specific features (`custom()`, component factories, terminal input). Use `ctx.hasUI` before dialog and notification methods that work in both TUI and RPC modes.
2520
2544
 
2521
2545
  ## Examples Reference
2522
2546
 
package/docs/providers.md CHANGED
@@ -52,6 +52,7 @@ pi
52
52
  | Azure OpenAI Responses | `AZURE_OPENAI_API_KEY` | `azure-openai-responses` |
53
53
  | OpenAI | `OPENAI_API_KEY` | `openai` |
54
54
  | DeepSeek | `DEEPSEEK_API_KEY` | `deepseek` |
55
+ | NVIDIA NIM | `NVIDIA_API_KEY` | `nvidia` |
55
56
  | Google Gemini | `GEMINI_API_KEY` | `google` |
56
57
  | Mistral | `MISTRAL_API_KEY` | `mistral` |
57
58
  | Groq | `GROQ_API_KEY` | `groq` |
@@ -86,6 +87,7 @@ Store credentials in `~/.senpi/agent/auth.json`:
86
87
  "anthropic": { "type": "api_key", "key": "sk-ant-..." },
87
88
  "openai": { "type": "api_key", "key": "sk-..." },
88
89
  "deepseek": { "type": "api_key", "key": "sk-..." },
90
+ "nvidia": { "type": "api_key", "key": "nvapi-..." },
89
91
  "google": { "type": "api_key", "key": "..." },
90
92
  "opencode": { "type": "api_key", "key": "..." },
91
93
  "opencode-go": { "type": "api_key", "key": "..." },
@@ -134,6 +134,7 @@ Sessions are saved automatically:
134
134
  ```bash
135
135
  senpi -c # Continue most recent session
136
136
  senpi -r # Browse previous sessions
137
+ senpi --name "my task" # Set session display name at startup
137
138
  senpi --session <path|id> # Open a specific session
138
139
  ```
139
140
 
package/docs/rpc.md CHANGED
@@ -13,6 +13,7 @@ pi --mode rpc [options]
13
13
  Common options:
14
14
  - `--provider <name>`: Set the LLM provider (anthropic, openai, google, etc.)
15
15
  - `--model <pattern>`: Model pattern or ID (supports `provider/id` and optional `:<thinking>`)
16
+ - `--name <name>` / `-n <name>`: Set the session display name at startup
16
17
  - `--no-session`: Disable session persistence
17
18
  - `--session-dir <path>`: Custom session storage directory
18
19
 
@@ -694,7 +695,7 @@ Response:
694
695
  }
695
696
  ```
696
697
 
697
- The current session name is available via `get_state` in the `sessionName` field.
698
+ The current session name is available via `get_state` in the `sessionName` field. To set the initial name when starting RPC mode, pass `--name <name>` or `-n <name>` to the `pi --mode rpc` process.
698
699
 
699
700
  ### Commands
700
701
 
@@ -1002,7 +1003,7 @@ Some `ExtensionUIContext` methods are not supported or degraded in RPC mode beca
1002
1003
  - `getTheme()` returns `undefined`
1003
1004
  - `setTheme()` returns `{ success: false, error: "..." }`
1004
1005
 
1005
- Note: `ctx.hasUI` is `true` in RPC mode because the dialog and fire-and-forget methods are functional via the extension UI sub-protocol.
1006
+ Note: `ctx.mode` is `"rpc"` and `ctx.hasUI` is `true` in RPC mode because the dialog and fire-and-forget methods are functional via the extension UI sub-protocol. Use `ctx.mode === "tui"` to guard TUI-specific features like `custom()` that require a real terminal.
1006
1007
 
1007
1008
  ### Extension UI Requests (stdout)
1008
1009