@code-yeongyu/senpi 2026.8.23 → 2026.8.24

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 (165) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/core/agent-abort-provenance.d.ts +5 -5
  3. package/dist/core/agent-abort-provenance.d.ts.map +1 -1
  4. package/dist/core/agent-abort-provenance.js +3 -0
  5. package/dist/core/agent-abort-provenance.js.map +1 -1
  6. package/dist/core/agent-session.d.ts +3 -0
  7. package/dist/core/agent-session.d.ts.map +1 -1
  8. package/dist/core/agent-session.js +4 -0
  9. package/dist/core/agent-session.js.map +1 -1
  10. package/dist/core/extensions/builtin/goal/agent-end-continuation.d.ts.map +1 -1
  11. package/dist/core/extensions/builtin/goal/agent-end-continuation.js +10 -0
  12. package/dist/core/extensions/builtin/goal/agent-end-continuation.js.map +1 -1
  13. package/dist/core/extensions/builtin/goal/continuation.d.ts +1 -1
  14. package/dist/core/extensions/builtin/goal/continuation.d.ts.map +1 -1
  15. package/dist/core/extensions/builtin/goal/continuation.js +1 -1
  16. package/dist/core/extensions/builtin/goal/continuation.js.map +1 -1
  17. package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -1
  18. package/dist/core/extensions/builtin/goal/index.js +0 -8
  19. package/dist/core/extensions/builtin/goal/index.js.map +1 -1
  20. package/dist/core/extensions/builtin/goal/monitor-continuation-types.d.ts +1 -0
  21. package/dist/core/extensions/builtin/goal/monitor-continuation-types.d.ts.map +1 -1
  22. package/dist/core/extensions/builtin/goal/monitor-continuation-types.js.map +1 -1
  23. package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts +2 -1
  24. package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts.map +1 -1
  25. package/dist/core/extensions/builtin/goal/monitor-continuation.js +31 -3
  26. package/dist/core/extensions/builtin/goal/monitor-continuation.js.map +1 -1
  27. package/dist/core/extensions/builtin/goal/wait-ticker.d.ts.map +1 -1
  28. package/dist/core/extensions/builtin/goal/wait-ticker.js +14 -9
  29. package/dist/core/extensions/builtin/goal/wait-ticker.js.map +1 -1
  30. package/dist/core/extensions/builtin/webfetch/webfetch/fetcher.d.ts.map +1 -1
  31. package/dist/core/extensions/builtin/webfetch/webfetch/fetcher.js +5 -23
  32. package/dist/core/extensions/builtin/webfetch/webfetch/fetcher.js.map +1 -1
  33. package/dist/core/extensions/builtin/webfetch/webfetch/response-body.d.ts +11 -0
  34. package/dist/core/extensions/builtin/webfetch/webfetch/response-body.d.ts.map +1 -0
  35. package/dist/core/extensions/builtin/webfetch/webfetch/response-body.js +54 -0
  36. package/dist/core/extensions/builtin/webfetch/webfetch/response-body.js.map +1 -0
  37. package/dist/core/tools/read.d.ts.map +1 -1
  38. package/dist/core/tools/read.js +5 -0
  39. package/dist/core/tools/read.js.map +1 -1
  40. package/dist/modes/interactive/aborted-error-label.d.ts +2 -1
  41. package/dist/modes/interactive/aborted-error-label.d.ts.map +1 -1
  42. package/dist/modes/interactive/aborted-error-label.js +20 -5
  43. package/dist/modes/interactive/aborted-error-label.js.map +1 -1
  44. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  45. package/dist/modes/interactive/interactive-mode.js +11 -3
  46. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  47. package/dist/modes/interactive/streaming-reveal.d.ts +8 -0
  48. package/dist/modes/interactive/streaming-reveal.d.ts.map +1 -1
  49. package/dist/modes/interactive/streaming-reveal.js +12 -0
  50. package/dist/modes/interactive/streaming-reveal.js.map +1 -1
  51. package/docs/AGENTS.md +3 -1
  52. package/examples/AGENTS.md +21 -6
  53. package/examples/extensions/AGENTS.md +50 -0
  54. package/node_modules/@anthropic-ai/claude-agent-sdk/bridge.mjs +90 -88
  55. package/node_modules/@anthropic-ai/claude-agent-sdk/browser-sdk.js +40 -40
  56. package/node_modules/@anthropic-ai/claude-agent-sdk/manifest.json +20 -21
  57. package/node_modules/@anthropic-ai/claude-agent-sdk/manifest.zst.json +24 -25
  58. package/node_modules/@anthropic-ai/claude-agent-sdk/package.json +2 -2
  59. package/node_modules/@anthropic-ai/claude-agent-sdk/sdk-tools.d.ts +102 -5
  60. package/node_modules/@anthropic-ai/claude-agent-sdk/sdk.d.ts +31 -15
  61. package/node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs +80 -78
  62. package/node_modules/@aws-sdk/client-bedrock-runtime/dist-cjs/index.js +1 -1
  63. package/node_modules/@aws-sdk/client-bedrock-runtime/package.json +13 -13
  64. package/node_modules/@aws-sdk/core/package.json +5 -5
  65. package/node_modules/@aws-sdk/credential-provider-env/package.json +5 -5
  66. package/node_modules/@aws-sdk/credential-provider-http/package.json +7 -7
  67. package/node_modules/@aws-sdk/credential-provider-ini/package.json +12 -12
  68. package/node_modules/@aws-sdk/credential-provider-login/package.json +6 -6
  69. package/node_modules/@aws-sdk/credential-provider-node/package.json +10 -10
  70. package/node_modules/@aws-sdk/credential-provider-process/package.json +5 -5
  71. package/node_modules/@aws-sdk/credential-provider-sso/package.json +7 -7
  72. package/node_modules/@aws-sdk/credential-provider-web-identity/package.json +6 -6
  73. package/node_modules/@aws-sdk/eventstream-handler-node/package.json +4 -4
  74. package/node_modules/@aws-sdk/middleware-eventstream/package.json +4 -4
  75. package/node_modules/@aws-sdk/middleware-websocket/package.json +6 -6
  76. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/cognito-identity/index.js +1 -1
  77. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/signin/index.js +1 -1
  78. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso/index.js +1 -1
  79. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso-oidc/index.js +1 -1
  80. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sts/index.js +1 -1
  81. package/node_modules/@aws-sdk/nested-clients/package.json +8 -8
  82. package/node_modules/@aws-sdk/signature-v4-multi-region/package.json +3 -3
  83. package/node_modules/@aws-sdk/token-providers/package.json +6 -6
  84. package/node_modules/@aws-sdk/types/package.json +2 -2
  85. package/node_modules/@aws-sdk/xml-builder/package.json +2 -2
  86. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +14 -0
  87. package/node_modules/@code-yeongyu/senpi-codemode/package.json +5 -5
  88. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/AGENTS.md +40 -0
  89. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/AGENTS.md +40 -0
  90. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-cell-manager.ts +1 -1
  91. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-cell-notification.ts +3 -8
  92. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-notification-queue.ts +2 -6
  93. package/node_modules/@earendil-works/pi-agent-core/package.json +4 -4
  94. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  95. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
  96. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opengateway.json +1 -1
  97. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  98. package/node_modules/@earendil-works/pi-ai/package.json +4 -4
  99. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  100. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  101. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
  102. package/node_modules/@earendil-works/pi-tui/dist/terminal.js +7 -4
  103. package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
  104. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  105. package/node_modules/@smithy/signature-v4/dist-cjs/index.js +19 -7
  106. package/node_modules/@smithy/signature-v4/dist-es/HeaderFormatter.js +4 -1
  107. package/node_modules/@smithy/signature-v4/dist-es/getCanonicalQuery.js +4 -1
  108. package/node_modules/@smithy/signature-v4/dist-es/getPayloadHash.js +4 -1
  109. package/node_modules/@smithy/signature-v4/dist-es/headerUtil.js +10 -3
  110. package/node_modules/@smithy/signature-v4/dist-es/moveHeadersToQuery.js +4 -1
  111. package/node_modules/@smithy/signature-v4/dist-es/prepareRequest.js +4 -1
  112. package/node_modules/@smithy/signature-v4/package.json +2 -2
  113. package/node_modules/typebox/build/format/email.mjs +1 -1
  114. package/node_modules/typebox/build/format/idna/idn-hostname.mjs +19 -1
  115. package/node_modules/typebox/build/format/json_pointer.d.mts +2 -2
  116. package/node_modules/typebox/build/format/json_pointer.mjs +2 -2
  117. package/node_modules/typebox/build/format/json_pointer_uri_fragment.d.mts +2 -2
  118. package/node_modules/typebox/build/format/json_pointer_uri_fragment.mjs +2 -2
  119. package/node_modules/typebox/build/format/relative_json_pointer.d.mts +2 -2
  120. package/node_modules/typebox/build/format/relative_json_pointer.mjs +2 -2
  121. package/node_modules/typebox/build/system/memory/assign.mjs +2 -1
  122. package/node_modules/typebox/build/system/memory/create.mjs +3 -4
  123. package/node_modules/typebox/build/system/memory/discard.mjs +2 -2
  124. package/node_modules/typebox/build/system/memory/freeze.d.mts +4 -0
  125. package/node_modules/typebox/build/system/memory/freeze.mjs +6 -0
  126. package/node_modules/typebox/build/system/memory/update.mjs +3 -2
  127. package/node_modules/typebox/package.json +1 -1
  128. package/package.json +36 -36
  129. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/LICENSE +0 -201
  130. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/README.md +0 -62
  131. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-cjs/index.js +0 -154
  132. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/constants.js +0 -2
  133. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/fromEnvSigningName.js +0 -16
  134. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/fromSso.js +0 -80
  135. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/fromStatic.js +0 -8
  136. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/getNewSsoOidcToken.js +0 -11
  137. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/getSsoOidcClient.js +0 -10
  138. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/index.js +0 -4
  139. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/nodeProvider.js +0 -5
  140. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/validateTokenExpiry.js +0 -7
  141. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/validateTokenKey.js +0 -7
  142. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/writeSSOTokenToFile.js +0 -8
  143. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/constants.d.ts +0 -8
  144. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/fromEnvSigningName.d.ts +0 -18
  145. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/fromSso.d.ts +0 -12
  146. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/fromStatic.d.ts +0 -9
  147. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/getNewSsoOidcToken.d.ts +0 -8
  148. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/getSsoOidcClient.d.ts +0 -7
  149. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/index.d.ts +0 -7
  150. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/nodeProvider.d.ts +0 -18
  151. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/constants.d.ts +0 -3
  152. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/fromEnvSigningName.d.ts +0 -8
  153. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/fromSso.d.ts +0 -10
  154. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/fromStatic.d.ts +0 -5
  155. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/getNewSsoOidcToken.d.ts +0 -9
  156. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/getSsoOidcClient.d.ts +0 -7
  157. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/index.d.ts +0 -7
  158. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/nodeProvider.d.ts +0 -3
  159. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/validateTokenExpiry.d.ts +0 -2
  160. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/validateTokenKey.d.ts +0 -1
  161. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/ts3.4/writeSSOTokenToFile.d.ts +0 -2
  162. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/validateTokenExpiry.d.ts +0 -5
  163. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/validateTokenKey.d.ts +0 -4
  164. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-types/writeSSOTokenToFile.d.ts +0 -5
  165. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/package.json +0 -69
@@ -15,6 +15,14 @@ export declare class StreamingRevealController {
15
15
  begin(component: StreamingRevealComponent, message: AssistantMessage): void;
16
16
  setTarget(message: AssistantMessage): void;
17
17
  resyncVisibility(): void;
18
+ /**
19
+ * True while this controller is the pacing writer for the given head message:
20
+ * smooth streaming is on, the head carries no toolCall block (those dump in
21
+ * full), and a component is still bound (before stop()). While true, callers
22
+ * must not overwrite the component's content, or the next reveal tick
23
+ * repaints a shorter prefix after their full write (dual-write flicker).
24
+ */
25
+ isPacingHead(message: AssistantMessage): boolean;
18
26
  stop(): void;
19
27
  }
20
28
  //# sourceMappingURL=streaming-reveal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"streaming-reveal.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/streaming-reveal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAWnF,cAAc,+BAA+B,CAAC;AAC9C,cAAc,8BAA8B,CAAC;AAE7C,KAAK,wBAAwB,GAAG,IAAI,CAAC,yBAAyB,EAAE,eAAe,CAAC,CAAC;AAEjF,MAAM,MAAM,gCAAgC,GAAG;IAC9C,QAAQ,CAAC,kBAAkB,EAAE,MAAM,OAAO,CAAC;IAC3C,QAAQ,CAAC,qBAAqB,EAAE,MAAM,MAAM,CAAC;IAC7C,QAAQ,CAAC,oBAAoB,EAAE,MAAM,OAAO,CAAC;IAC7C,QAAQ,CAAC,aAAa,EAAE,MAAM,IAAI,CAAC;CACnC,CAAC;AAEF,qBAAa,yBAAyB;;gBAqBzB,OAAO,EAAE,gCAAgC;IAOrD,KAAK,CAAC,SAAS,EAAE,wBAAwB,EAAE,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAa3E,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAiB1C,gBAAgB,IAAI,IAAI;IAOxB,IAAI,IAAI,IAAI;CAkGZ"}
1
+ {"version":3,"file":"streaming-reveal.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/streaming-reveal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAWnF,cAAc,+BAA+B,CAAC;AAC9C,cAAc,8BAA8B,CAAC;AAE7C,KAAK,wBAAwB,GAAG,IAAI,CAAC,yBAAyB,EAAE,eAAe,CAAC,CAAC;AAEjF,MAAM,MAAM,gCAAgC,GAAG;IAC9C,QAAQ,CAAC,kBAAkB,EAAE,MAAM,OAAO,CAAC;IAC3C,QAAQ,CAAC,qBAAqB,EAAE,MAAM,MAAM,CAAC;IAC7C,QAAQ,CAAC,oBAAoB,EAAE,MAAM,OAAO,CAAC;IAC7C,QAAQ,CAAC,aAAa,EAAE,MAAM,IAAI,CAAC;CACnC,CAAC;AAEF,qBAAa,yBAAyB;;gBAqBzB,OAAO,EAAE,gCAAgC;IAOrD,KAAK,CAAC,SAAS,EAAE,wBAAwB,EAAE,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAa3E,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAiB1C,gBAAgB,IAAI,IAAI;IAOxB;;;;;;OAMG;IACH,YAAY,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO;IAKhD,IAAI,IAAI,IAAI;CAkGZ"}
@@ -64,6 +64,18 @@ export class StreamingRevealController {
64
64
  this.#revealed = Math.min(this.#revealed, this.#visibleUnits(this.#target));
65
65
  this.#applyTarget();
66
66
  }
67
+ /**
68
+ * True while this controller is the pacing writer for the given head message:
69
+ * smooth streaming is on, the head carries no toolCall block (those dump in
70
+ * full), and a component is still bound (before stop()). While true, callers
71
+ * must not overwrite the component's content, or the next reveal tick
72
+ * repaints a shorter prefix after their full write (dual-write flicker).
73
+ */
74
+ isPacingHead(message) {
75
+ if (!this.#target || !this.#component)
76
+ return false;
77
+ return this.#getSmoothStreaming() && !message.content.some((block) => block.type === "toolCall");
78
+ }
67
79
  stop() {
68
80
  this.#stopTimer();
69
81
  this.#target = undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"streaming-reveal.js","sourceRoot":"","sources":["../../../src/modes/interactive/streaming-reveal.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage } from \"@earendil-works/pi-ai\";\nimport type { AssistantMessageComponent } from \"./components/assistant-message.ts\";\nimport { BlockUnitCounter, buildDisplayMessage, countVisibleUnits } from \"./streaming-reveal-content.ts\";\nimport {\n\tDEFAULT_SMOOTH_FPS,\n\tINITIAL_BUFFER_MS,\n\tMAX_SMOOTH_FPS,\n\tMIN_SMOOTH_FPS,\n\tnextStep,\n\tupdateArrivalRate,\n} from \"./streaming-reveal-pacing.ts\";\n\nexport * from \"./streaming-reveal-content.ts\";\nexport * from \"./streaming-reveal-pacing.ts\";\n\ntype StreamingRevealComponent = Pick<AssistantMessageComponent, \"updateContent\">;\n\nexport type StreamingRevealControllerOptions = {\n\treadonly getSmoothStreaming: () => boolean;\n\treadonly getSmoothStreamingFps: () => number;\n\treadonly getHideThinkingBlock: () => boolean;\n\treadonly requestRender: () => void;\n};\n\nexport class StreamingRevealController {\n\treadonly #getSmoothStreaming: () => boolean;\n\treadonly #getSmoothStreamingFps: () => number;\n\treadonly #getHideThinkingBlock: () => boolean;\n\treadonly #requestRender: () => void;\n\treadonly #unitCounter = new BlockUnitCounter();\n\treadonly #countOf = (index: number, text: string): number => this.#unitCounter.count(index, text);\n\treadonly #sliceOf = (index: number, text: string, units: number): string =>\n\t\tthis.#unitCounter.slice(index, text, units);\n\t#target: AssistantMessage | undefined;\n\t#component: StreamingRevealComponent | undefined;\n\t#timer: NodeJS.Timeout | undefined;\n\t#timerFps: number | undefined;\n\t#revealed = 0;\n\t#lastTickAt = 0;\n\t#firstBufferedAt: number | undefined;\n\t#lastTargetAt: number | undefined;\n\t#arrivalRate = 90;\n\t#stepCarry = 0;\n\t#hideThinkingBlock = false;\n\n\tconstructor(options: StreamingRevealControllerOptions) {\n\t\tthis.#getSmoothStreaming = options.getSmoothStreaming;\n\t\tthis.#getSmoothStreamingFps = options.getSmoothStreamingFps;\n\t\tthis.#getHideThinkingBlock = options.getHideThinkingBlock;\n\t\tthis.#requestRender = options.requestRender;\n\t}\n\n\tbegin(component: StreamingRevealComponent, message: AssistantMessage): void {\n\t\tthis.stop();\n\t\tthis.#component = component;\n\t\tthis.#target = message;\n\t\tthis.#hideThinkingBlock = this.#getHideThinkingBlock();\n\t\tif (this.#visibleUnits(message) > 0) {\n\t\t\tconst now = performance.now();\n\t\t\tthis.#firstBufferedAt = now;\n\t\t\tthis.#lastTargetAt = now;\n\t\t}\n\t\tthis.#applyTarget();\n\t}\n\n\tsetTarget(message: AssistantMessage): void {\n\t\tconst now = performance.now();\n\t\tconst previousUnits = this.#target ? this.#visibleUnits(this.#target) : 0;\n\t\tthis.#target = message;\n\t\tthis.#hideThinkingBlock = this.#getHideThinkingBlock();\n\t\tconst total = this.#visibleUnits(message);\n\t\tconst appended = Math.max(0, total - previousUnits);\n\t\tif (appended > 0) {\n\t\t\tif (this.#firstBufferedAt === undefined) this.#firstBufferedAt = now;\n\t\t\tif (this.#lastTargetAt !== undefined && now > this.#lastTargetAt) {\n\t\t\t\tthis.#arrivalRate = updateArrivalRate(this.#arrivalRate, appended, now - this.#lastTargetAt);\n\t\t\t}\n\t\t\tthis.#lastTargetAt = now;\n\t\t}\n\t\tif (this.#component) this.#applyTarget();\n\t}\n\n\tresyncVisibility(): void {\n\t\tif (!this.#target || !this.#component) return;\n\t\tthis.#hideThinkingBlock = this.#getHideThinkingBlock();\n\t\tthis.#revealed = Math.min(this.#revealed, this.#visibleUnits(this.#target));\n\t\tthis.#applyTarget();\n\t}\n\n\tstop(): void {\n\t\tthis.#stopTimer();\n\t\tthis.#target = undefined;\n\t\tthis.#component = undefined;\n\t\tthis.#revealed = 0;\n\t\tthis.#lastTickAt = 0;\n\t\tthis.#unitCounter.reset();\n\t\tthis.#firstBufferedAt = undefined;\n\t\tthis.#lastTargetAt = undefined;\n\t\tthis.#arrivalRate = 90;\n\t\tthis.#stepCarry = 0;\n\t}\n\n\t#applyTarget(): void {\n\t\tconst target = this.#target;\n\t\tconst component = this.#component;\n\t\tif (!target || !component) return;\n\t\tconst total = this.#visibleUnits(target);\n\t\tif (!this.#getSmoothStreaming() || target.content.some((block) => block.type === \"toolCall\")) {\n\t\t\tthis.#revealed = total;\n\t\t\tthis.#stepCarry = 0;\n\t\t\tthis.#stopTimer();\n\t\t\tcomponent.updateContent(target);\n\t\t\treturn;\n\t\t}\n\t\tthis.#revealed = Math.min(this.#revealed, total);\n\t\tthis.#renderCurrent();\n\t\tthis.#syncTimer(total);\n\t}\n\n\t#visibleUnits(message: AssistantMessage): number {\n\t\treturn countVisibleUnits(message, this.#hideThinkingBlock, this.#countOf);\n\t}\n\n\t#renderCurrent(): void {\n\t\tif (!this.#target || !this.#component) return;\n\t\tthis.#component.updateContent(\n\t\t\tbuildDisplayMessage(this.#target, this.#revealed, this.#hideThinkingBlock, this.#countOf, this.#sliceOf),\n\t\t);\n\t}\n\n\t#syncTimer(total: number): void {\n\t\tif (this.#revealed >= total) {\n\t\t\tthis.#stepCarry = 0;\n\t\t\tthis.#stopTimer();\n\t\t\treturn;\n\t\t}\n\t\tthis.#startTimer();\n\t}\n\n\t#startTimer(): void {\n\t\tconst configuredFps = this.#getSmoothStreamingFps();\n\t\tconst fps = Number.isFinite(configuredFps)\n\t\t\t? Math.min(MAX_SMOOTH_FPS, Math.max(MIN_SMOOTH_FPS, configuredFps))\n\t\t\t: DEFAULT_SMOOTH_FPS;\n\t\tif (this.#timer && this.#timerFps === fps) return;\n\t\tthis.#stopTimer();\n\t\tthis.#lastTickAt = performance.now();\n\t\tconst timer = setInterval(() => this.#tick(), 1000 / fps);\n\t\ttimer.unref();\n\t\tthis.#timer = timer;\n\t\tthis.#timerFps = fps;\n\t}\n\n\t#stopTimer(): void {\n\t\tif (this.#timer) clearInterval(this.#timer);\n\t\tthis.#timer = undefined;\n\t\tthis.#timerFps = undefined;\n\t}\n\n\t#tick(): void {\n\t\tconst target = this.#target;\n\t\tif (!target || !this.#component) {\n\t\t\tthis.stop();\n\t\t\treturn;\n\t\t}\n\t\tconst total = this.#visibleUnits(target);\n\t\tif (this.#revealed >= total) {\n\t\t\tthis.#stepCarry = 0;\n\t\t\tthis.#stopTimer();\n\t\t\treturn;\n\t\t}\n\t\tconst now = performance.now();\n\t\tconst dt = now - this.#lastTickAt;\n\t\tthis.#lastTickAt = now;\n\t\tif (this.#firstBufferedAt !== undefined && now - this.#firstBufferedAt < INITIAL_BUFFER_MS) return;\n\t\tthis.#stepCarry += nextStep(total - this.#revealed, dt, this.#arrivalRate);\n\t\tconst wholeStep = Math.floor(this.#stepCarry);\n\t\tif (wholeStep <= 0) return;\n\t\tthis.#stepCarry -= wholeStep;\n\t\tthis.#revealed = Math.min(total, this.#revealed + wholeStep);\n\t\tthis.#renderCurrent();\n\t\tthis.#requestRender();\n\t\tif (this.#revealed >= total) {\n\t\t\tthis.#stepCarry = 0;\n\t\t\tthis.#stopTimer();\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"streaming-reveal.js","sourceRoot":"","sources":["../../../src/modes/interactive/streaming-reveal.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage } from \"@earendil-works/pi-ai\";\nimport type { AssistantMessageComponent } from \"./components/assistant-message.ts\";\nimport { BlockUnitCounter, buildDisplayMessage, countVisibleUnits } from \"./streaming-reveal-content.ts\";\nimport {\n\tDEFAULT_SMOOTH_FPS,\n\tINITIAL_BUFFER_MS,\n\tMAX_SMOOTH_FPS,\n\tMIN_SMOOTH_FPS,\n\tnextStep,\n\tupdateArrivalRate,\n} from \"./streaming-reveal-pacing.ts\";\n\nexport * from \"./streaming-reveal-content.ts\";\nexport * from \"./streaming-reveal-pacing.ts\";\n\ntype StreamingRevealComponent = Pick<AssistantMessageComponent, \"updateContent\">;\n\nexport type StreamingRevealControllerOptions = {\n\treadonly getSmoothStreaming: () => boolean;\n\treadonly getSmoothStreamingFps: () => number;\n\treadonly getHideThinkingBlock: () => boolean;\n\treadonly requestRender: () => void;\n};\n\nexport class StreamingRevealController {\n\treadonly #getSmoothStreaming: () => boolean;\n\treadonly #getSmoothStreamingFps: () => number;\n\treadonly #getHideThinkingBlock: () => boolean;\n\treadonly #requestRender: () => void;\n\treadonly #unitCounter = new BlockUnitCounter();\n\treadonly #countOf = (index: number, text: string): number => this.#unitCounter.count(index, text);\n\treadonly #sliceOf = (index: number, text: string, units: number): string =>\n\t\tthis.#unitCounter.slice(index, text, units);\n\t#target: AssistantMessage | undefined;\n\t#component: StreamingRevealComponent | undefined;\n\t#timer: NodeJS.Timeout | undefined;\n\t#timerFps: number | undefined;\n\t#revealed = 0;\n\t#lastTickAt = 0;\n\t#firstBufferedAt: number | undefined;\n\t#lastTargetAt: number | undefined;\n\t#arrivalRate = 90;\n\t#stepCarry = 0;\n\t#hideThinkingBlock = false;\n\n\tconstructor(options: StreamingRevealControllerOptions) {\n\t\tthis.#getSmoothStreaming = options.getSmoothStreaming;\n\t\tthis.#getSmoothStreamingFps = options.getSmoothStreamingFps;\n\t\tthis.#getHideThinkingBlock = options.getHideThinkingBlock;\n\t\tthis.#requestRender = options.requestRender;\n\t}\n\n\tbegin(component: StreamingRevealComponent, message: AssistantMessage): void {\n\t\tthis.stop();\n\t\tthis.#component = component;\n\t\tthis.#target = message;\n\t\tthis.#hideThinkingBlock = this.#getHideThinkingBlock();\n\t\tif (this.#visibleUnits(message) > 0) {\n\t\t\tconst now = performance.now();\n\t\t\tthis.#firstBufferedAt = now;\n\t\t\tthis.#lastTargetAt = now;\n\t\t}\n\t\tthis.#applyTarget();\n\t}\n\n\tsetTarget(message: AssistantMessage): void {\n\t\tconst now = performance.now();\n\t\tconst previousUnits = this.#target ? this.#visibleUnits(this.#target) : 0;\n\t\tthis.#target = message;\n\t\tthis.#hideThinkingBlock = this.#getHideThinkingBlock();\n\t\tconst total = this.#visibleUnits(message);\n\t\tconst appended = Math.max(0, total - previousUnits);\n\t\tif (appended > 0) {\n\t\t\tif (this.#firstBufferedAt === undefined) this.#firstBufferedAt = now;\n\t\t\tif (this.#lastTargetAt !== undefined && now > this.#lastTargetAt) {\n\t\t\t\tthis.#arrivalRate = updateArrivalRate(this.#arrivalRate, appended, now - this.#lastTargetAt);\n\t\t\t}\n\t\t\tthis.#lastTargetAt = now;\n\t\t}\n\t\tif (this.#component) this.#applyTarget();\n\t}\n\n\tresyncVisibility(): void {\n\t\tif (!this.#target || !this.#component) return;\n\t\tthis.#hideThinkingBlock = this.#getHideThinkingBlock();\n\t\tthis.#revealed = Math.min(this.#revealed, this.#visibleUnits(this.#target));\n\t\tthis.#applyTarget();\n\t}\n\n\t/**\n\t * True while this controller is the pacing writer for the given head message:\n\t * smooth streaming is on, the head carries no toolCall block (those dump in\n\t * full), and a component is still bound (before stop()). While true, callers\n\t * must not overwrite the component's content, or the next reveal tick\n\t * repaints a shorter prefix after their full write (dual-write flicker).\n\t */\n\tisPacingHead(message: AssistantMessage): boolean {\n\t\tif (!this.#target || !this.#component) return false;\n\t\treturn this.#getSmoothStreaming() && !message.content.some((block) => block.type === \"toolCall\");\n\t}\n\n\tstop(): void {\n\t\tthis.#stopTimer();\n\t\tthis.#target = undefined;\n\t\tthis.#component = undefined;\n\t\tthis.#revealed = 0;\n\t\tthis.#lastTickAt = 0;\n\t\tthis.#unitCounter.reset();\n\t\tthis.#firstBufferedAt = undefined;\n\t\tthis.#lastTargetAt = undefined;\n\t\tthis.#arrivalRate = 90;\n\t\tthis.#stepCarry = 0;\n\t}\n\n\t#applyTarget(): void {\n\t\tconst target = this.#target;\n\t\tconst component = this.#component;\n\t\tif (!target || !component) return;\n\t\tconst total = this.#visibleUnits(target);\n\t\tif (!this.#getSmoothStreaming() || target.content.some((block) => block.type === \"toolCall\")) {\n\t\t\tthis.#revealed = total;\n\t\t\tthis.#stepCarry = 0;\n\t\t\tthis.#stopTimer();\n\t\t\tcomponent.updateContent(target);\n\t\t\treturn;\n\t\t}\n\t\tthis.#revealed = Math.min(this.#revealed, total);\n\t\tthis.#renderCurrent();\n\t\tthis.#syncTimer(total);\n\t}\n\n\t#visibleUnits(message: AssistantMessage): number {\n\t\treturn countVisibleUnits(message, this.#hideThinkingBlock, this.#countOf);\n\t}\n\n\t#renderCurrent(): void {\n\t\tif (!this.#target || !this.#component) return;\n\t\tthis.#component.updateContent(\n\t\t\tbuildDisplayMessage(this.#target, this.#revealed, this.#hideThinkingBlock, this.#countOf, this.#sliceOf),\n\t\t);\n\t}\n\n\t#syncTimer(total: number): void {\n\t\tif (this.#revealed >= total) {\n\t\t\tthis.#stepCarry = 0;\n\t\t\tthis.#stopTimer();\n\t\t\treturn;\n\t\t}\n\t\tthis.#startTimer();\n\t}\n\n\t#startTimer(): void {\n\t\tconst configuredFps = this.#getSmoothStreamingFps();\n\t\tconst fps = Number.isFinite(configuredFps)\n\t\t\t? Math.min(MAX_SMOOTH_FPS, Math.max(MIN_SMOOTH_FPS, configuredFps))\n\t\t\t: DEFAULT_SMOOTH_FPS;\n\t\tif (this.#timer && this.#timerFps === fps) return;\n\t\tthis.#stopTimer();\n\t\tthis.#lastTickAt = performance.now();\n\t\tconst timer = setInterval(() => this.#tick(), 1000 / fps);\n\t\ttimer.unref();\n\t\tthis.#timer = timer;\n\t\tthis.#timerFps = fps;\n\t}\n\n\t#stopTimer(): void {\n\t\tif (this.#timer) clearInterval(this.#timer);\n\t\tthis.#timer = undefined;\n\t\tthis.#timerFps = undefined;\n\t}\n\n\t#tick(): void {\n\t\tconst target = this.#target;\n\t\tif (!target || !this.#component) {\n\t\t\tthis.stop();\n\t\t\treturn;\n\t\t}\n\t\tconst total = this.#visibleUnits(target);\n\t\tif (this.#revealed >= total) {\n\t\t\tthis.#stepCarry = 0;\n\t\t\tthis.#stopTimer();\n\t\t\treturn;\n\t\t}\n\t\tconst now = performance.now();\n\t\tconst dt = now - this.#lastTickAt;\n\t\tthis.#lastTickAt = now;\n\t\tif (this.#firstBufferedAt !== undefined && now - this.#firstBufferedAt < INITIAL_BUFFER_MS) return;\n\t\tthis.#stepCarry += nextStep(total - this.#revealed, dt, this.#arrivalRate);\n\t\tconst wholeStep = Math.floor(this.#stepCarry);\n\t\tif (wholeStep <= 0) return;\n\t\tthis.#stepCarry -= wholeStep;\n\t\tthis.#revealed = Math.min(total, this.#revealed + wholeStep);\n\t\tthis.#renderCurrent();\n\t\tthis.#requestRender();\n\t\tif (this.#revealed >= total) {\n\t\t\tthis.#stepCarry = 0;\n\t\t\tthis.#stopTimer();\n\t\t}\n\t}\n}\n"]}
package/docs/AGENTS.md CHANGED
@@ -6,7 +6,7 @@ Public documentation for `@code-yeongyu/senpi`. Shipped inside the npm package:
6
6
  ## Navigation manifest
7
7
 
8
8
  `docs.json` has two top-level keys: `navigation` (ordered section and page list) and `redirects`.
9
- Page paths are relative to this directory.
9
+ Sections are `{ "title", "items": [{ "title", "path" }] }`; page paths are relative to this directory.
10
10
 
11
11
  - Every new `.md` file needs an entry in `docs.json` under `navigation`.
12
12
  - Renamed or moved pages need a `redirects` entry to avoid broken links.
@@ -29,6 +29,8 @@ These pages must track their implementation counterparts. Treat them as specs, n
29
29
  | `app-server.md` | `packages/coding-agent/src/modes/app-server/` |
30
30
  | `json.md` | JSONL wire format and record shapes |
31
31
  | `session-format.md` | Session file structure and field types |
32
+ | `extensions.md` | Public extension API in `src/core/extensions/`; largest page — API tables must match `types.ts` |
33
+ | `release-guide.md` | Release tooling; canonical check/build/test/lock command sequences |
32
34
 
33
35
  Preserve LF line endings and exact field names in these pages. Field spellings and JSONL record
34
36
  structures are asserted by tests; prose-only rewording can still break them.
@@ -5,16 +5,28 @@ Runnable examples for the public Senpi SDK and extension API. Examples are docum
5
5
  ## STRUCTURE
6
6
 
7
7
  ```text
8
- extensions/ Tools, commands, UI, providers, hooks, resources
9
- extensions/*/ Multi-file examples and nested private workspaces
10
- sdk/ Programmatic SDK usage
11
- rpc-extension-ui.ts RPC-compatible extension UI example
12
- extensions/kimi-deferred-tools.ts Deferred tool discovery/activation example
8
+ extensions/ Single-file extension catalog (70+ files) + multi-file dirs
9
+ extensions/*/ Multi-file examples; several are private nested workspaces
10
+ sdk/ Numbered SDK programs (01-minimal.ts ... 13-session-runtime.ts)
11
+ rpc-extension-ui.ts RPC-mode extension UI as standalone JSONL child process
13
12
  ```
14
13
 
14
+ ## WHERE TO LOOK
15
+
16
+ | Task | First choice |
17
+ |---|---|
18
+ | Tool/flag/command/shortcut registration | `extensions/tools.ts`, `commands.ts`, `dynamic-tools.ts` |
19
+ | Custom provider, OAuth, streaming | `extensions/custom-provider-anthropic/` |
20
+ | UI widgets, overlays, editors | `extensions/overlay-*.ts`, `modal-editor.ts`, `widget-placement.ts` |
21
+ | Session-entry persistence | `extensions/todo.ts`, `bookmark.ts`, `handoff.ts` |
22
+ | Safety guards | `extensions/permission-gate.ts`, `protected-paths.ts`, `sandbox/` |
23
+ | Full SDK composition | `sdk/12-full-control.ts`, `sdk/13-session-runtime.ts` |
24
+
25
+ Largest examples carry real complexity, not toy scope: `extensions/overlay-qa-tests.ts` (~1.5k LOC), `extensions/subagent/index.ts` (~1k), `extensions/tic-tac-toe.ts` (~1k), `extensions/custom-provider-anthropic/index.ts` (~600). See `extensions/AGENTS.md` for the catalog map.
26
+
15
27
  ## CONVENTIONS
16
28
 
17
- - Import public package surfaces such as `@code-yeongyu/senpi` and `@earendil-works/pi-ai`; do not reach into `packages/coding-agent/src/core/` internals.
29
+ - Import public package surfaces `@code-yeongyu/senpi` (newer alias), `@earendil-works/pi-coding-agent` (lower level), `@earendil-works/pi-ai`/`pi-tui` never `packages/coding-agent/src/core/` internals.
18
30
  - Keep examples small enough to teach one pattern, while preserving real error, cleanup, cancellation, and persistence behavior where relevant.
19
31
  - Extension factories have no top-level runtime side effects. Register work through the public `pi.*` API and lifecycle events.
20
32
  - New interactive examples should use configurable keybindings and themed TUI helpers. Existing demos may keep fixed controls when the control scheme is part of the example. Direct terminal writes belong only in examples explicitly teaching a terminal protocol; ordinary SDK examples may use normal stdout.
@@ -23,6 +35,9 @@ extensions/kimi-deferred-tools.ts Deferred tool discovery/activation example
23
35
  - Deferred-tool examples preserve the Kimi flow: expose search first, activate via `pi.setActiveTools()`, and register lifecycle work in `session_start`.
24
36
  - Stateful examples persist reconstructable state in session entries or tool-result details so fork/resume behavior remains valid.
25
37
  - Nested example packages are private workspaces with exact-pinned dependencies. Treat their manifests and lock impact as production dependency changes.
38
+ - Kebab-case filenames and slash-command names; camelCase named exports; one example per file default-exporting its extension factory.
39
+ - UI examples guard on `ctx.hasUI` and clean up timers/child processes on `session_shutdown`; stateful atomic tools (games, questionnaires) set `executionMode: "sequential"`.
40
+ - Tool schemas use TypeBox; handlers follow the `(toolCallId, params, signal, onUpdate, ctx)` shape.
26
41
 
27
42
  ## DOCUMENTATION CONTRACT
28
43
 
@@ -0,0 +1,50 @@
1
+ # packages/coding-agent/examples/extensions
2
+
3
+ Flat catalog of executable extension examples plus multi-file extension packages. Own file because it is the densest `pi.*` registration surface in the repo (score 14: 110+ files, 10 subdirs, heavy symbol/export density). Load any single file with `senpi -e <path>.ts`; per-example docs live in `README.md`.
4
+
5
+ ## STRUCTURE
6
+
7
+ ```text
8
+ *.ts Single-file examples, one pattern each (kebab-case)
9
+ subagent/ Subagent tool: single/parallel/chain dispatch (~1k LOC)
10
+ custom-provider-anthropic/ OAuth + Anthropic-compatible streaming provider
11
+ custom-provider-gitlab-duo/ Provider against GitLab Duo
12
+ gondolin/ Route built-in tools + `!` commands into a Gondolin micro-VM
13
+ sandbox/ OS-level sandboxing via @anthropic-ai/sandbox-runtime
14
+ plan-mode/ Read-only planning mode (generated instructions)
15
+ openai-codex-usage/ Codex usage tracking
16
+ dynamic-resources/ Dynamic resource examples
17
+ with-deps/ Extension with its own private dependency manifest
18
+ doom-overlay/ WASM Doom rendered as live overlay; doom/build/ is generated
19
+ ```
20
+
21
+ ## WHERE TO LOOK
22
+
23
+ | Task | First choice |
24
+ |---|---|
25
+ | Register tool/command/flag/shortcut/renderer | `tools.ts`, `commands.ts`, `dynamic-tools.ts`, `custom-header.ts` |
26
+ | Built-in tool override or rendering | `minimal-mode.ts`, `built-in-tool-renderer.ts` |
27
+ | Overlays, focus, geometry | `overlay-test.ts`, `overlay-qa-tests.ts`, `widget-placement.ts` |
28
+ | Provider auth/payload | `custom-provider-anthropic/`, `provider-payload.ts` |
29
+ | Persistent state via session entries | `todo.ts`, `tic-tac-toe.ts`, `bookmark.ts`, `handoff.ts` |
30
+ | Prompt/preset/config files | `preset.ts`, `prompt-customizer.ts`, `system-prompt-header.ts` |
31
+ | Games / keyboard input | `snake.ts`, `space-invaders.ts`, `tic-tac-toe.ts` |
32
+ | Deferred-tool activation (Kimi flow) | `kimi-deferred-tools.ts` |
33
+ | RPC/UI child process | `../rpc-extension-ui.ts`, `rpc-demo.ts` |
34
+
35
+ ## CONVENTIONS
36
+
37
+ - Event seams used across examples: `session_start`/`session_shutdown`, `turn_*`, `agent_*`, `before_agent_start`, `tool_call`/`tool_result`, `input`, `user_bash`, `model_select`.
38
+ - Presets read `~/.senpi/agent/presets.json` then `<cwd>/.senpi/presets.json`; project file wins. `provider-payload.ts` writes under `CONFIG_DIR_NAME`.
39
+ - `overlay-qa-tests.ts` is a runtime QA extension (many overlay commands, timers, spawned streaming processes), not a conventional test target.
40
+
41
+ ## ANTI-PATTERNS
42
+
43
+ - Custom tools MUST truncate output (`truncated-tool.ts` demonstrates ripgrep wrapping with 50KB/2000-line caps).
44
+ - Games never expose the user's cursor and never split a tool-call sequence across responses.
45
+ - Never leave timers or child processes alive past `session_shutdown`.
46
+ - Shell/process-delegating examples (`ssh.ts`, `interactive-shell.ts`, `inline-bash.ts`, `auto-commit-on-exit.ts`, `git-merge-and-resolve.ts`) cross trust boundaries; adopt deliberately, never as boilerplate.
47
+
48
+ ---
49
+
50
+ Parent: `examples/AGENTS.md` (import rules, factory discipline, validation).