@code-yeongyu/senpi 2026.8.30-3 → 2026.8.31

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 (188) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +3 -0
  3. package/dist/core/agent-session.d.ts +26 -0
  4. package/dist/core/agent-session.d.ts.map +1 -1
  5. package/dist/core/agent-session.js +67 -0
  6. package/dist/core/agent-session.js.map +1 -1
  7. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.d.ts +9 -1
  8. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.d.ts.map +1 -1
  9. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.js +10 -3
  10. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.js.map +1 -1
  11. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts +1 -1
  12. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts.map +1 -1
  13. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js +4 -1
  14. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js.map +1 -1
  15. package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts +1 -0
  16. package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts.map +1 -1
  17. package/dist/core/extensions/builtin/compaction/speculative-summary.js +1 -0
  18. package/dist/core/extensions/builtin/compaction/speculative-summary.js.map +1 -1
  19. package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
  20. package/dist/core/extensions/builtin/compaction/speculative.js +14 -1
  21. package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
  22. package/dist/core/extensions/builtin/hooks/trust-state-json.d.ts +5 -0
  23. package/dist/core/extensions/builtin/hooks/trust-state-json.d.ts.map +1 -0
  24. package/dist/core/extensions/builtin/hooks/trust-state-json.js +76 -0
  25. package/dist/core/extensions/builtin/hooks/trust-state-json.js.map +1 -0
  26. package/dist/core/extensions/builtin/hooks/trust-storage.d.ts +7 -1
  27. package/dist/core/extensions/builtin/hooks/trust-storage.d.ts.map +1 -1
  28. package/dist/core/extensions/builtin/hooks/trust-storage.js +60 -8
  29. package/dist/core/extensions/builtin/hooks/trust-storage.js.map +1 -1
  30. package/dist/core/extensions/builtin/hooks/trust.d.ts +1 -2
  31. package/dist/core/extensions/builtin/hooks/trust.d.ts.map +1 -1
  32. package/dist/core/extensions/builtin/hooks/trust.js +1 -72
  33. package/dist/core/extensions/builtin/hooks/trust.js.map +1 -1
  34. package/dist/core/extensions/builtin/ttsr/index.d.ts.map +1 -1
  35. package/dist/core/extensions/builtin/ttsr/index.js +4 -0
  36. package/dist/core/extensions/builtin/ttsr/index.js.map +1 -1
  37. package/dist/core/extensions/builtin/ttsr/manager.d.ts +2 -0
  38. package/dist/core/extensions/builtin/ttsr/manager.d.ts.map +1 -1
  39. package/dist/core/extensions/builtin/ttsr/manager.js +28 -1
  40. package/dist/core/extensions/builtin/ttsr/manager.js.map +1 -1
  41. package/dist/core/extensions/runner.d.ts +5 -0
  42. package/dist/core/extensions/runner.d.ts.map +1 -1
  43. package/dist/core/extensions/runner.js +7 -0
  44. package/dist/core/extensions/runner.js.map +1 -1
  45. package/dist/core/retry-fallback/controller.d.ts +14 -0
  46. package/dist/core/retry-fallback/controller.d.ts.map +1 -1
  47. package/dist/core/retry-fallback/controller.js +33 -3
  48. package/dist/core/retry-fallback/controller.js.map +1 -1
  49. package/dist/core/retry-fallback/log.js +1 -1
  50. package/dist/core/retry-fallback/log.js.map +1 -1
  51. package/dist/core/session-activity.d.ts +47 -0
  52. package/dist/core/session-activity.d.ts.map +1 -0
  53. package/dist/core/session-activity.js +58 -0
  54. package/dist/core/session-activity.js.map +1 -0
  55. package/dist/core/session-manager.d.ts +8 -12
  56. package/dist/core/session-manager.d.ts.map +1 -1
  57. package/dist/core/session-manager.js +118 -7
  58. package/dist/core/session-manager.js.map +1 -1
  59. package/dist/core/session-resident-store.d.ts +8 -1
  60. package/dist/core/session-resident-store.d.ts.map +1 -1
  61. package/dist/core/session-resident-store.js +12 -5
  62. package/dist/core/session-resident-store.js.map +1 -1
  63. package/dist/modes/app-server/daemon.js +3 -3
  64. package/dist/modes/app-server/daemon.js.map +1 -1
  65. package/dist/modes/interactive/interactive-host-runtime.d.ts +3 -1
  66. package/dist/modes/interactive/interactive-host-runtime.d.ts.map +1 -1
  67. package/dist/modes/interactive/interactive-host-runtime.js +26 -4
  68. package/dist/modes/interactive/interactive-host-runtime.js.map +1 -1
  69. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  70. package/dist/modes/interactive/interactive-mode.js +24 -0
  71. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  72. package/dist/modes/rpc/connection-handler.d.ts +12 -5
  73. package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
  74. package/dist/modes/rpc/connection-handler.js +149 -12
  75. package/dist/modes/rpc/connection-handler.js.map +1 -1
  76. package/dist/modes/rpc/custom-capability.d.ts +1 -0
  77. package/dist/modes/rpc/custom-capability.d.ts.map +1 -1
  78. package/dist/modes/rpc/custom-capability.js +1 -0
  79. package/dist/modes/rpc/custom-capability.js.map +1 -1
  80. package/dist/modes/rpc/host-ensure.d.ts.map +1 -1
  81. package/dist/modes/rpc/host-ensure.js +3 -3
  82. package/dist/modes/rpc/host-ensure.js.map +1 -1
  83. package/dist/modes/rpc/host-lifecycle.d.ts +10 -0
  84. package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
  85. package/dist/modes/rpc/host-lifecycle.js +15 -2
  86. package/dist/modes/rpc/host-lifecycle.js.map +1 -1
  87. package/dist/modes/rpc/multi-session-host.d.ts +38 -0
  88. package/dist/modes/rpc/multi-session-host.d.ts.map +1 -1
  89. package/dist/modes/rpc/multi-session-host.js +55 -5
  90. package/dist/modes/rpc/multi-session-host.js.map +1 -1
  91. package/dist/modes/rpc/ownership-safe-lock.d.ts +14 -0
  92. package/dist/modes/rpc/ownership-safe-lock.d.ts.map +1 -0
  93. package/dist/modes/rpc/ownership-safe-lock.js +87 -0
  94. package/dist/modes/rpc/ownership-safe-lock.js.map +1 -0
  95. package/dist/modes/rpc/rpc-client.d.ts +1 -0
  96. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  97. package/dist/modes/rpc/rpc-client.js +3 -0
  98. package/dist/modes/rpc/rpc-client.js.map +1 -1
  99. package/dist/modes/rpc/rpc-types.d.ts +12 -1
  100. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  101. package/dist/modes/rpc/rpc-types.js +1 -0
  102. package/dist/modes/rpc/rpc-types.js.map +1 -1
  103. package/dist/modes/rpc/session-binding.d.ts +2 -1
  104. package/dist/modes/rpc/session-binding.d.ts.map +1 -1
  105. package/dist/modes/rpc/session-binding.js +1 -0
  106. package/dist/modes/rpc/session-binding.js.map +1 -1
  107. package/dist/modes/rpc/session-command-router.d.ts +54 -1
  108. package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
  109. package/dist/modes/rpc/session-command-router.js +174 -2
  110. package/dist/modes/rpc/session-command-router.js.map +1 -1
  111. package/dist/modes/rpc/session-event-writer.d.ts +18 -0
  112. package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
  113. package/dist/modes/rpc/session-event-writer.js +88 -8
  114. package/dist/modes/rpc/session-event-writer.js.map +1 -1
  115. package/dist/modes/rpc/session-registry.d.ts +11 -1
  116. package/dist/modes/rpc/session-registry.d.ts.map +1 -1
  117. package/dist/modes/rpc/session-registry.js +25 -0
  118. package/dist/modes/rpc/session-registry.js.map +1 -1
  119. package/dist/modes/rpc/widget-line-renderer.d.ts +17 -0
  120. package/dist/modes/rpc/widget-line-renderer.d.ts.map +1 -0
  121. package/dist/modes/rpc/widget-line-renderer.js +73 -0
  122. package/dist/modes/rpc/widget-line-renderer.js.map +1 -0
  123. package/dist/utils/fs-watch.d.ts.map +1 -1
  124. package/dist/utils/fs-watch.js +11 -2
  125. package/dist/utils/fs-watch.js.map +1 -1
  126. package/docs/app-server.md +2 -2
  127. package/docs/containerization.md +2 -2
  128. package/docs/development.md +7 -7
  129. package/docs/extensions.md +4 -4
  130. package/docs/grok-neo.md +1 -1
  131. package/docs/index.md +1 -1
  132. package/docs/packages.md +2 -2
  133. package/docs/quickstart.md +4 -4
  134. package/docs/release-guide.md +21 -21
  135. package/docs/rpc.md +59 -4
  136. package/docs/sdk.md +1 -1
  137. package/docs/skills.md +2 -2
  138. package/docs/terminal-tools.md +1 -1
  139. package/docs/termux.md +1 -1
  140. package/docs/tui.md +1 -1
  141. package/examples/AGENTS.md +1 -1
  142. package/examples/sdk/README.md +1 -1
  143. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +16 -0
  144. package/node_modules/@code-yeongyu/senpi-codemode/README.md +2 -2
  145. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  146. package/node_modules/@code-yeongyu/senpi-codemode/src/extension/skill-contribution.ts +71 -0
  147. package/node_modules/@code-yeongyu/senpi-codemode/src/index.ts +3 -1
  148. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/SKILL.md +44 -0
  149. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/breaking-changes.md +75 -0
  150. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/build.md +114 -0
  151. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/dev-tooling.md +34 -0
  152. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/http-networking.md +113 -0
  153. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/install.md +93 -0
  154. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/node-compat-platforms.md +36 -0
  155. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/performance.md +33 -0
  156. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/runtime-apis.md +156 -0
  157. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/security.md +52 -0
  158. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/test.md +103 -0
  159. package/node_modules/@earendil-works/pi-agent-core/README.md +3 -0
  160. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  161. package/node_modules/@earendil-works/pi-ai/README.md +6 -3
  162. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
  163. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +15 -0
  164. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
  165. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts +7 -0
  166. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts.map +1 -1
  167. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js +316 -2
  168. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js.map +1 -1
  169. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.d.ts +4 -0
  170. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.d.ts.map +1 -1
  171. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.js +23 -0
  172. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.js.map +1 -1
  173. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts +24 -0
  174. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
  175. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +20 -2
  176. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
  177. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  178. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  179. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  180. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  181. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  182. package/node_modules/@earendil-works/pi-telemetry/README.md +6 -3
  183. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  184. package/node_modules/@earendil-works/pi-tui/README.md +5 -4
  185. package/node_modules/@earendil-works/pi-tui/native/darwin/README.md +2 -2
  186. package/node_modules/@earendil-works/pi-tui/native/win32/README.md +2 -2
  187. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  188. package/package.json +7 -7
@@ -17,6 +17,7 @@
17
17
  import type { AgentAbortSource } from "../../core/agent-abort-provenance.ts";
18
18
  import type { AgentSession } from "../../core/agent-session.ts";
19
19
  import type { AgentSessionRuntime } from "../../core/agent-session-runtime.ts";
20
+ import { FooterDataProvider } from "../../core/footer-data-provider.ts";
20
21
  import type { RpcSessionState } from "./rpc-types.ts";
21
22
  /** Additive per-connection options. Absent = classic default (byte-identical). */
22
23
  export interface RpcConnectionOptions {
@@ -28,12 +29,17 @@ export interface RpcConnectionOptions {
28
29
  disposeRuntime?: boolean;
29
30
  /** Multi-session routing handle. Absent preserves classic wire output exactly. */
30
31
  sessionId?: string;
32
+ footerDataProviderFactory?: (session: AgentSession) => FooterDataProvider;
33
+ sharedWidth?: {
34
+ getWidth: () => number;
35
+ setWidth: (connectionId: string | undefined, width: number) => void;
36
+ clearWidth: (connectionId: string | undefined) => void;
37
+ setCapabilities?: (connectionId: string | undefined, capabilities: readonly string[]) => void;
38
+ hasRenderedComponents?: (sessionId: string) => boolean;
39
+ connectionId: () => string | undefined;
40
+ onChange?: () => void;
41
+ };
31
42
  }
32
- /**
33
- * The output side of a connection. `writeRaw` receives already-serialized JSONL
34
- * text (LF-terminated). `waitForBackpressure` lets the host apply flow control
35
- * (stdout drain in classic mode, or the transport's own `drain` signal).
36
- */
37
43
  export interface RpcConnectionSink {
38
44
  writeRaw(chunk: string): void;
39
45
  waitForBackpressure(): Promise<void>;
@@ -46,6 +52,7 @@ export interface RpcConnectionHandler {
46
52
  readonly ready: Promise<void>;
47
53
  /** Feed one inbound JSONL line (command or extension_ui_response). */
48
54
  handleInputLine(line: string): Promise<void>;
55
+ rerenderComponents(): void;
49
56
  /**
50
57
  * True once an extension requested shutdown via the shutdown handler. The
51
58
  * host polls this after each command and decides how to tear down.
@@ -1 +1 @@
1
- {"version":3,"file":"connection-handler.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/connection-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAOH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAqB,MAAM,6BAA6B,CAAC;AACnF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAyC/E,OAAO,KAAK,EAYX,eAAe,EAEf,MAAM,gBAAgB,CAAC;AAGxB,kFAAkF;AAClF,MAAM,WAAW,oBAAoB;IACpC,mFAAmF;IACnF,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,iFAAiF;IACjF,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,0DAA0D;IAC1D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,oBAAoB;IACpC;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,sEAAsE;IACtE,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C;;;OAGG;IACH,mBAAmB,IAAI,OAAO,CAAC;IAC/B,4EAA4E;IAC5E,gCAAgC,IAAI,IAAI,CAAC;IACzC,iFAAiF;IACjF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AA4BD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,EAAE,eAAe,CAAC,EAAE,gBAAgB,GAAG,eAAe,CAkD/G;AA4BD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACzC,WAAW,EAAE,mBAAmB,EAChC,IAAI,EAAE,iBAAiB,EACvB,OAAO,GAAE,oBAAyB,GAChC,oBAAoB,CAyvCtB"}
1
+ {"version":3,"file":"connection-handler.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/connection-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAOH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAqB,MAAM,6BAA6B,CAAC;AACnF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AA8B/E,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAaxE,OAAO,KAAK,EAYX,eAAe,EAEf,MAAM,gBAAgB,CAAC;AAKxB,kFAAkF;AAClF,MAAM,WAAW,oBAAoB;IACpC,mFAAmF;IACnF,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,iFAAiF;IACjF,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,0DAA0D;IAC1D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yBAAyB,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,kBAAkB,CAAC;IAC1E,WAAW,CAAC,EAAE;QACb,QAAQ,EAAE,MAAM,MAAM,CAAC;QACvB,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QACpE,UAAU,EAAE,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;QACvD,eAAe,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,EAAE,YAAY,EAAE,SAAS,MAAM,EAAE,KAAK,IAAI,CAAC;QAC9F,qBAAqB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;QACvD,YAAY,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;QACvC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;KACtB,CAAC;CACF;AAWD,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,oBAAoB;IACpC;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,sEAAsE;IACtE,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,kBAAkB,IAAI,IAAI,CAAC;IAC3B;;;OAGG;IACH,mBAAmB,IAAI,OAAO,CAAC;IAC/B,4EAA4E;IAC5E,gCAAgC,IAAI,IAAI,CAAC;IACzC,iFAAiF;IACjF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AA4BD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,EAAE,eAAe,CAAC,EAAE,gBAAgB,GAAG,eAAe,CAkD/G;AA4BD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACzC,WAAW,EAAE,mBAAmB,EAChC,IAAI,EAAE,iBAAiB,EACvB,OAAO,GAAE,oBAAyB,GAChC,oBAAoB,CAi3CtB"}
@@ -24,14 +24,25 @@ import { emitProviderAccountsChanged, subscribeProviderAccountEvents, } from "..
24
24
  import { CLAUDE_SDK_OAUTH_PROVIDER_ID } from "../../core/extensions/builtin/claude-sdk-oauth/account-management.js";
25
25
  import { isMcpControlInventoryChanged, MCP_CONTROL_INVENTORY_CHANGED_EVENT, MCP_CONTROL_INVENTORY_REQUEST_EVENT, } from "../../core/extensions/builtin/mcp/control-inventory.js";
26
26
  import { applyFastMode, resolveServiceTierMemoryModel, } from "../../core/extensions/builtin/service-tier.js";
27
+ import { FooterDataProvider } from "../../core/footer-data-provider.js";
27
28
  import { getSupportedThinkingLevels } from "../../core/thinking-levels.js";
28
29
  import { ProjectTrustStore } from "../../core/trust-manager.js";
29
30
  import { theme } from "../interactive/theme/theme.js";
30
- import { buildCustomUnsupportedRequest, DEFAULT_CUSTOM_EXTENSION_LABEL, EXTENSION_EVENTS_CAPABILITY, } from "./custom-capability.js";
31
+ import { buildCustomUnsupportedRequest, DEFAULT_CUSTOM_EXTENSION_LABEL, EXTENSION_EVENTS_CAPABILITY, RENDERED_COMPONENTS_CAPABILITY, } from "./custom-capability.js";
31
32
  import { createRpcEventOutputBuffer } from "./event-output-buffer.js";
32
33
  import { buildRpcCommandsForSession, createCommandsChangedEvent, rpcCommandListDigest } from "./rpc-command-surface.js";
33
34
  import { rpcCommandPayloadError, rpcCommandShapeError, rpcMessageLengthError } from "./rpc-input-validation.js";
35
+ import { RENDERED_COMPONENT_RECORD } from "./session-event-writer.js";
34
36
  import { SessionExtensionUiRequests } from "./session-extension-ui-requests.js";
37
+ import { createLiveComponentRenderer } from "./widget-line-renderer.js";
38
+ /**
39
+ * The output side of a connection. `writeRaw` receives already-serialized JSONL
40
+ * text (LF-terminated). `waitForBackpressure` lets the host apply flow control
41
+ * (stdout drain in classic mode, or the transport's own `drain` signal).
42
+ */
43
+ function createFooterDataProvider(session) {
44
+ return new FooterDataProvider(session.sessionManager.getCwd());
45
+ }
35
46
  function loadedExtensionName(path) {
36
47
  const synthetic = /^<(?:builtin|inline):([^>]+)>$/.exec(path);
37
48
  if (synthetic)
@@ -146,8 +157,28 @@ function loadedSurfacesFingerprint(session, extensions, mcpServers) {
146
157
  * wiring, and process exit are intentionally NOT done here.
147
158
  */
148
159
  export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
149
- const clientCapabilities = options.capabilities;
160
+ let clientCapabilities = options.capabilities;
150
161
  const routingSessionId = options.sessionId;
162
+ const clientWidth = () => options.sharedWidth?.getWidth() ?? 80;
163
+ const hasRenderedComponents = () => (options.sharedWidth?.hasRenderedComponents?.(routingSessionId ?? "") ?? false) ||
164
+ (clientCapabilities?.includes(RENDERED_COMPONENTS_CAPABILITY) ?? false);
165
+ const liveRenderers = new Map();
166
+ const retainedRendererFactories = new Map();
167
+ const footerProviders = new Map();
168
+ const disposeRenderer = (key) => {
169
+ liveRenderers.get(key)?.dispose();
170
+ liveRenderers.delete(key);
171
+ footerProviders.get(key)?.dispose();
172
+ footerProviders.delete(key);
173
+ };
174
+ const disposeAllRenderers = () => {
175
+ for (const renderer of liveRenderers.values())
176
+ renderer.dispose();
177
+ for (const provider of footerProviders.values())
178
+ provider.dispose();
179
+ liveRenderers.clear();
180
+ footerProviders.clear();
181
+ };
151
182
  // True only while THIS connection's own command drives a replacement; the issuer
152
183
  // already learns the new identity from its command response.
153
184
  let replacementIssuedHere = false;
@@ -328,6 +359,8 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
328
359
  // Hidden thinking label not supported in RPC mode - requires TUI message rendering access
329
360
  },
330
361
  setWidget(key, content, options) {
362
+ disposeRenderer(key);
363
+ retainedRendererFactories.delete(key);
331
364
  if (content === undefined || Array.isArray(content)) {
332
365
  output({
333
366
  type: "extension_ui_request",
@@ -339,18 +372,95 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
339
372
  });
340
373
  return;
341
374
  }
342
- // A component factory closes over live TUI/theme state and cannot cross
343
- // the RPC boundary. Never drop it silently: an opted-in client can show
344
- // the same explicit degradation notice used by ctx.ui.custom.
345
- const request = buildCustomUnsupportedRequest(clientCapabilities, "widget component");
346
- if (request)
347
- output(request);
375
+ retainedRendererFactories.set(key, () => {
376
+ const renderer = createLiveComponentRenderer({
377
+ factory: content,
378
+ getWidth: clientWidth,
379
+ emit: (widgetLines) => output({
380
+ type: "extension_ui_request",
381
+ id: crypto.randomUUID(),
382
+ method: "setWidget",
383
+ widgetKey: key,
384
+ widgetLines,
385
+ widgetPlacement: options?.placement,
386
+ [RENDERED_COMPONENT_RECORD]: true,
387
+ }),
388
+ });
389
+ if (renderer)
390
+ liveRenderers.set(key, renderer);
391
+ });
392
+ if (hasRenderedComponents())
393
+ retainedRendererFactories.get(key)();
348
394
  },
349
- setFooter(_factory) {
350
- // Custom footer not supported in RPC mode - requires TUI access
395
+ setFooter(factory) {
396
+ const key = "__footer__";
397
+ disposeRenderer(key);
398
+ retainedRendererFactories.delete(key);
399
+ if (factory === undefined) {
400
+ if (hasRenderedComponents())
401
+ output({
402
+ type: "extension_ui_request",
403
+ id: crypto.randomUUID(),
404
+ method: "setFooter",
405
+ widgetLines: undefined,
406
+ });
407
+ return;
408
+ }
409
+ retainedRendererFactories.set(key, () => {
410
+ const provider = options.footerDataProviderFactory?.(session) ?? createFooterDataProvider(session);
411
+ const renderer = createLiveComponentRenderer({
412
+ factory: factory,
413
+ factoryArgs: [provider],
414
+ getWidth: clientWidth,
415
+ emit: (widgetLines) => output({
416
+ type: "extension_ui_request",
417
+ id: crypto.randomUUID(),
418
+ method: "setFooter",
419
+ widgetLines,
420
+ [RENDERED_COMPONENT_RECORD]: true,
421
+ }),
422
+ });
423
+ if (renderer) {
424
+ liveRenderers.set(key, renderer);
425
+ footerProviders.set(key, provider);
426
+ }
427
+ else
428
+ provider.dispose();
429
+ });
430
+ if (hasRenderedComponents())
431
+ retainedRendererFactories.get(key)();
351
432
  },
352
- setHeader(_factory) {
353
- // Custom header not supported in RPC mode - requires TUI access
433
+ setHeader(factory) {
434
+ const key = "__header__";
435
+ disposeRenderer(key);
436
+ retainedRendererFactories.delete(key);
437
+ if (factory === undefined) {
438
+ if (hasRenderedComponents())
439
+ output({
440
+ type: "extension_ui_request",
441
+ id: crypto.randomUUID(),
442
+ method: "setHeader",
443
+ widgetLines: undefined,
444
+ });
445
+ return;
446
+ }
447
+ retainedRendererFactories.set(key, () => {
448
+ const renderer = createLiveComponentRenderer({
449
+ factory: factory,
450
+ getWidth: clientWidth,
451
+ emit: (widgetLines) => output({
452
+ type: "extension_ui_request",
453
+ id: crypto.randomUUID(),
454
+ method: "setHeader",
455
+ widgetLines,
456
+ [RENDERED_COMPONENT_RECORD]: true,
457
+ }),
458
+ });
459
+ if (renderer)
460
+ liveRenderers.set(key, renderer);
461
+ });
462
+ if (hasRenderedComponents())
463
+ retainedRendererFactories.get(key)();
354
464
  },
355
465
  setTitle(title) {
356
466
  // Fire and forget - host can implement terminal title control
@@ -811,6 +921,21 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
811
921
  // =================================================================
812
922
  // State
813
923
  // =================================================================
924
+ case "set_client_info":
925
+ if (options.sharedWidth && command.capabilities !== undefined) {
926
+ clientCapabilities = command.capabilities;
927
+ options.sharedWidth.setCapabilities?.(options.sharedWidth.connectionId(), command.capabilities);
928
+ }
929
+ if (Number.isFinite(command.width) && command.width > 0) {
930
+ if (options.sharedWidth) {
931
+ options.sharedWidth.setWidth(options.sharedWidth.connectionId(), command.width);
932
+ options.sharedWidth.onChange?.();
933
+ }
934
+ else
935
+ for (const renderer of liveRenderers.values())
936
+ renderer.rerender();
937
+ }
938
+ return success(id, "set_client_info");
814
939
  case "get_state":
815
940
  return success(id, "get_state", buildRpcSessionState(session, lastAbortSource));
816
941
  // =================================================================
@@ -1205,6 +1330,7 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
1205
1330
  }
1206
1331
  };
1207
1332
  const dispose = async () => {
1333
+ disposeAllRenderers();
1208
1334
  pendingExtensionRequests.close();
1209
1335
  unsubscribeProviderAccountEvents();
1210
1336
  unsubscribe?.();
@@ -1228,6 +1354,17 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
1228
1354
  await ready;
1229
1355
  await handleInputLine(line);
1230
1356
  },
1357
+ rerenderComponents() {
1358
+ if (!hasRenderedComponents()) {
1359
+ disposeAllRenderers();
1360
+ return;
1361
+ }
1362
+ for (const [key, createRenderer] of retainedRendererFactories)
1363
+ if (!liveRenderers.has(key))
1364
+ createRenderer();
1365
+ for (const renderer of liveRenderers.values())
1366
+ renderer.rerender();
1367
+ },
1231
1368
  isShutdownRequested() {
1232
1369
  return shutdownRequested;
1233
1370
  },