@code-yeongyu/senpi 2026.11.6-2 → 2026.11.6-3

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 +30 -0
  2. package/dist/bundle/chunks/{bun-extension-importer-RCGPQTI2.js → bun-extension-importer-GQ6IKEXD.js} +2 -2
  3. package/dist/bundle/chunks/{chunk-QN2BHP3M.js → chunk-44BJPS5I.js} +1 -1
  4. package/dist/bundle/chunks/{chunk-C7OKUC7L.js → chunk-4BATXPB7.js} +1 -1
  5. package/dist/bundle/chunks/{chunk-RQ6CHXQ2.js → chunk-5LKB732P.js} +1 -1
  6. package/dist/bundle/chunks/{chunk-X5ZVYNOL.js → chunk-6CEDL5S2.js} +1 -1
  7. package/dist/bundle/chunks/{chunk-HLM46XEB.js → chunk-7DRWPZ3N.js} +1 -1
  8. package/dist/bundle/chunks/{chunk-7PSBD5KS.js → chunk-BASS47UD.js} +1 -1
  9. package/dist/bundle/chunks/{chunk-ECW7VBMB.js → chunk-CFEHJ4VU.js} +1 -1
  10. package/dist/bundle/chunks/{chunk-TIPKAMSS.js → chunk-EO2VPZ2K.js} +1 -1
  11. package/dist/bundle/chunks/{chunk-LNPAT22L.js → chunk-F5JLDCYD.js} +8 -7
  12. package/dist/bundle/chunks/{chunk-GSKCWXXG.js → chunk-JMQOLOC2.js} +1 -1
  13. package/dist/bundle/chunks/chunk-L7ZIS3MC.js +106 -0
  14. package/dist/bundle/chunks/{chunk-47PPZKPO.js → chunk-LM6DOWQH.js} +4 -4
  15. package/dist/bundle/chunks/chunk-LPYBKMPT.js +2 -0
  16. package/dist/bundle/chunks/{chunk-GNSMNSL7.js → chunk-LUZVGPQ7.js} +2 -2
  17. package/dist/bundle/chunks/{chunk-7III44PV.js → chunk-MJTCZUXS.js} +1 -1
  18. package/dist/bundle/chunks/{chunk-2FDW2LQL.js → chunk-SB6MXNO5.js} +1 -1
  19. package/dist/bundle/chunks/chunk-UODSYQ2D.js +2 -0
  20. package/dist/bundle/chunks/{chunk-D5MRJWUK.js → chunk-V2QAYGOK.js} +216 -224
  21. package/dist/bundle/chunks/{chunk-WGRKM3N6.js → chunk-X53PD4ZC.js} +1 -1
  22. package/dist/bundle/chunks/{cli-main-T74YJGIF.js → cli-main-RWHDZKTQ.js} +1 -1
  23. package/dist/bundle/chunks/{dispatch-BAK2YZKD.js → dispatch-VDIYSXQN.js} +1 -1
  24. package/dist/bundle/chunks/{hand-entry-AYRUGE2A.js → hand-entry-G5LYF62Q.js} +1 -1
  25. package/dist/bundle/chunks/{host-command-YRXZE4TV.js → host-command-I2JZ5JM7.js} +1 -1
  26. package/dist/bundle/chunks/{host-session-command-N7IN7ZDV.js → host-session-command-Y52NFPP2.js} +1 -1
  27. package/dist/bundle/chunks/interactive-mode-PA7DGVS6.js +2 -0
  28. package/dist/bundle/chunks/main-OBL6375C.js +2 -0
  29. package/dist/bundle/chunks/{multi-session-host-XSUJDHFZ.js → multi-session-host-NM6I5BWZ.js} +20 -17
  30. package/dist/bundle/chunks/{package-manager-cli-GLUNPQJU.js → package-manager-cli-GNRQ5MVR.js} +1 -1
  31. package/dist/bundle/chunks/{role-RRFFHZF5.js → role-F56BS2ZQ.js} +1 -1
  32. package/dist/bundle/chunks/rpc-mode-G4KIP7XS.js +2 -0
  33. package/dist/bundle/chunks/{run-attached-tui-W236SEOR.js → run-attached-tui-XTGPAGYM.js} +1 -1
  34. package/dist/bundle/chunks/{runtime-session-OBXYK4PI.js → runtime-session-VO3X4OE3.js} +1 -1
  35. package/dist/bundle/chunks/{schedule-command-B2EJTBOE.js → schedule-command-L4M3TSQ3.js} +1 -1
  36. package/dist/bundle/chunks/{session-control-endpoint-YIMLHGLG.js → session-control-endpoint-V46WMCDF.js} +1 -1
  37. package/dist/bundle/chunks/{session-picker-E6ZONUJB.js → session-picker-AG6KSR5A.js} +1 -1
  38. package/dist/bundle/chunks/session-worker.js +87 -83
  39. package/dist/bundle/cli.js +2 -2
  40. package/dist/bundle/index.js +1 -1
  41. package/dist/bundle/rpc-entry.js +1 -1
  42. package/dist/bundle/runtime-manifest.json +1 -1
  43. package/dist/core/agent-session-runtime.d.ts +2 -0
  44. package/dist/core/agent-session-runtime.js +9 -2
  45. package/dist/core/agent-session.d.ts +24 -3
  46. package/dist/core/agent-session.js +94 -28
  47. package/dist/core/credential-pool/rotation-slots.d.ts +3 -3
  48. package/dist/core/credential-pool/state-store.d.ts +1 -1
  49. package/dist/core/egress/hpke.d.ts +63 -0
  50. package/dist/core/egress/hpke.js +188 -0
  51. package/dist/core/egress/placement-claim.d.ts +69 -0
  52. package/dist/core/egress/placement-claim.js +115 -0
  53. package/dist/core/egress/pool-state.d.ts +18 -0
  54. package/dist/core/egress/pool-state.js +5 -0
  55. package/dist/core/egress/sealed-format.d.ts +101 -0
  56. package/dist/core/egress/sealed-format.js +174 -0
  57. package/dist/core/egress/wire.d.ts +226 -0
  58. package/dist/core/egress/wire.js +47 -0
  59. package/dist/core/extensions/builtin/ask-user/escape-residue.d.ts +50 -0
  60. package/dist/core/extensions/builtin/ask-user/escape-residue.js +113 -0
  61. package/dist/core/extensions/builtin/ask-user/extension.js +7 -1
  62. package/dist/core/extensions/builtin/ask-user/resume.js +2 -1
  63. package/dist/core/extensions/builtin/ask-user/tool.d.ts +3 -0
  64. package/dist/core/extensions/builtin/ask-user/tool.js +8 -0
  65. package/dist/core/extensions/builtin/goal/index.js +46 -0
  66. package/dist/core/extensions/builtin/goal/stop-pause.d.ts +1 -0
  67. package/dist/core/extensions/builtin/goal/stop-pause.js +4 -2
  68. package/dist/core/extensions/builtin/permission-system/index.js +10 -4
  69. package/dist/core/extensions/builtin/permission-system/preset-registry.d.ts +2 -0
  70. package/dist/core/extensions/builtin/permission-system/preset-registry.js +11 -0
  71. package/dist/core/extensions/builtin/permission-system/settings.d.ts +2 -0
  72. package/dist/core/extensions/builtin/permission-system/settings.js +10 -1
  73. package/dist/core/extensions/builtin/terminal/tools/bash.d.ts +1 -1
  74. package/dist/core/extensions/builtin/terminal/tools/bash.js +38 -9
  75. package/dist/core/extensions/builtin/terminal/tools/context.d.ts +3 -0
  76. package/dist/core/extensions/bun-extension-importer.js +4 -3
  77. package/dist/core/extensions/bun-extension-load-turns.d.ts +4 -0
  78. package/dist/core/extensions/bun-extension-load-turns.js +45 -0
  79. package/dist/core/extensions/bun-extension-registry.d.ts +1 -0
  80. package/dist/core/extensions/bun-extension-registry.js +19 -1
  81. package/dist/core/extensions/loader.js +5 -0
  82. package/dist/core/extensions/session-dialog-api.d.ts +5 -0
  83. package/dist/core/extensions/session-dialog-api.js +13 -0
  84. package/dist/core/extensions/types.d.ts +14 -1
  85. package/dist/core/permission-decision.d.ts +22 -0
  86. package/dist/core/permission-decision.js +53 -0
  87. package/dist/core/permission-mode.d.ts +56 -0
  88. package/dist/core/permission-mode.js +133 -0
  89. package/dist/core/retry-fallback/controller-types.d.ts +6 -0
  90. package/dist/core/retry-fallback/controller.d.ts +8 -0
  91. package/dist/core/retry-fallback/controller.js +31 -3
  92. package/dist/core/retry-fallback/unusable.d.ts +23 -1
  93. package/dist/core/retry-fallback/unusable.js +80 -1
  94. package/dist/core/retry-fallback/usage-limit.d.ts +1 -1
  95. package/dist/core/retry-fallback/usage-limit.js +6 -3
  96. package/dist/core/sdk.js +2 -0
  97. package/dist/core/session-log.js +1 -1
  98. package/dist/core/stall-warning.d.ts +41 -0
  99. package/dist/core/stall-warning.js +72 -0
  100. package/dist/core/turn-origin.d.ts +27 -0
  101. package/dist/core/turn-origin.js +54 -0
  102. package/dist/modes/rpc/client-input-handler.d.ts +2 -0
  103. package/dist/modes/rpc/client-input-handler.js +2 -0
  104. package/dist/modes/rpc/connection-handler.js +16 -5
  105. package/dist/modes/rpc/connection-roles.d.ts +6 -0
  106. package/dist/modes/rpc/connection-roles.js +13 -0
  107. package/dist/modes/rpc/delegated-drive-origin.d.ts +9 -0
  108. package/dist/modes/rpc/delegated-drive-origin.js +16 -0
  109. package/dist/modes/rpc/effect-commands.d.ts +6 -0
  110. package/dist/modes/rpc/host-bare-endpoint-registration.d.ts +7 -0
  111. package/dist/modes/rpc/host-bare-endpoint-registration.js +35 -0
  112. package/dist/modes/rpc/host-capabilities.d.ts +2 -0
  113. package/dist/modes/rpc/host-capabilities.js +3 -0
  114. package/dist/modes/rpc/host-handover-parked.d.ts +11 -0
  115. package/dist/modes/rpc/host-handover-parked.js +17 -0
  116. package/dist/modes/rpc/host-handover-reopen.js +18 -6
  117. package/dist/modes/rpc/host-handover-resident-writer.d.ts +16 -0
  118. package/dist/modes/rpc/host-handover-resident-writer.js +57 -0
  119. package/dist/modes/rpc/host-warm.d.ts +16 -1
  120. package/dist/modes/rpc/host-warm.js +33 -6
  121. package/dist/modes/rpc/method-classes-schema-session.d.ts +9 -0
  122. package/dist/modes/rpc/method-classes-schema-session.js +1 -0
  123. package/dist/modes/rpc/method-classes-schema.d.ts +9 -0
  124. package/dist/modes/rpc/method-classes.d.ts +1 -0
  125. package/dist/modes/rpc/method-classes.js +2 -0
  126. package/dist/modes/rpc/multi-session-host.js +6 -1
  127. package/dist/modes/rpc/permission-preset-command.d.ts +6 -0
  128. package/dist/modes/rpc/permission-preset-command.js +27 -0
  129. package/dist/modes/rpc/rpc-mutation-response-types.d.ts +7 -0
  130. package/dist/modes/rpc/rpc-session-command-types.d.ts +4 -0
  131. package/dist/modes/rpc/rpc-session-event-types.d.ts +5 -2
  132. package/dist/modes/rpc/rpc-session-state-types.d.ts +2 -1
  133. package/dist/modes/rpc/rpc-session-state.js +2 -0
  134. package/dist/modes/rpc/session-attachment-commands.js +3 -3
  135. package/dist/modes/rpc/session-event-writer-connections.js +1 -0
  136. package/dist/modes/rpc/session-event-writer.d.ts +1 -1
  137. package/dist/modes/rpc/session-registry-attach.d.ts +0 -9
  138. package/dist/modes/rpc/session-registry-attach.js +16 -3
  139. package/dist/modes/rpc/session-registry-types.d.ts +2 -0
  140. package/dist/modes/rpc/session-registry.d.ts +2 -0
  141. package/dist/modes/rpc/session-registry.js +16 -3
  142. package/dist/modes/rpc/session-router-close.js +43 -6
  143. package/dist/modes/rpc/session-router-context.js +2 -0
  144. package/dist/modes/rpc/session-router-occupancy.js +2 -11
  145. package/dist/modes/rpc/session-router-open-profile.js +4 -0
  146. package/dist/modes/rpc/session-router-open.d.ts +1 -1
  147. package/dist/modes/rpc/session-router-open.js +6 -17
  148. package/dist/modes/rpc/session-router-residency.d.ts +24 -0
  149. package/dist/modes/rpc/session-router-residency.js +90 -0
  150. package/dist/modes/rpc/session-router-routing.js +7 -1
  151. package/dist/modes/rpc/session-status.js +4 -1
  152. package/dist/modes/rpc/session-worker.js +4 -0
  153. package/dist/modes/rpc/worker-session-registry.js +5 -2
  154. package/docs/engine-socket/fixtures/admission-routes/h-legacy.json +1 -1
  155. package/docs/engine-socket/fixtures/rpc-inbound-samples.json +12 -2
  156. package/docs/extensions.md +12 -0
  157. package/docs/rpc.md +72 -12
  158. package/native/socket-secret/prebuilds/win32-arm64/senpi_socket_secret.win32-arm64.node +0 -0
  159. package/native/socket-secret/prebuilds/win32-x64/senpi_socket_secret.win32-x64.node +0 -0
  160. package/package.json +6 -6
  161. package/dist/bundle/chunks/chunk-C7HEEBFH.js +0 -2
  162. package/dist/bundle/chunks/chunk-XCMII2VQ.js +0 -98
  163. package/dist/bundle/chunks/interactive-mode-B5SQDLH7.js +0 -2
  164. package/dist/bundle/chunks/main-UQFVFCNY.js +0 -2
  165. package/dist/bundle/chunks/rpc-mode-JYN3E7P7.js +0 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # Changelog
2
2
 
3
+ ## [2026.11.6-3] - 2026-11-08
4
+
5
+ ### Breaking Changes
6
+
7
+ ### Added
8
+
9
+ - Sealed custody formats for hosted model-key custody (internal, no caller yet): HPKE P-256 key wraps and AES-256-GCM provider fields and config objects, each bound to an AAD the opener rebuilds and never stores ([#5886](https://github.com/code-yeongyu/senpi/pull/5886))
10
+ - A tool call stalled before it runs now leaves a trace: when its wait on the session's event queue or its `tool_call` hooks (the permission decision) outlives 30 s, or a bash spawn outlives 30 s (or the call's own shorter `timeout`), one warning naming the call goes to the session log, and the queue warning also names the entry the call waits behind. Nothing is aborted or delayed ([#6189](https://github.com/code-yeongyu/senpi/issues/6189))
11
+ - `set_permission_preset` RPC record (classic and multi-session, `set_permission_preset_v1`) and the permission-mode fields on `get_state` and the `open_session` reply; a client-named preset is recorded in the session file ([#6204](https://github.com/code-yeongyu/senpi/pull/6204))
12
+ - `pi.sessionDialog`, the `audience: "session"` dialog option and the `permission_preset_changed` event ([#6204](https://github.com/code-yeongyu/senpi/pull/6204))
13
+ - Brain-to-hand wire messages and the signed placement-claim verifier for hosted model-key custody; not wired to any command yet ([#6220](https://github.com/code-yeongyu/senpi/pull/6220))
14
+
15
+ ### Changed
16
+
17
+ - Work a remote device starts now asks for approval on a session with no client-named mode, and child sessions follow their live parent's mode; a local turn keeps the host default ([#6206](https://github.com/code-yeongyu/senpi/pull/6206))
18
+
19
+ ### Fixed
20
+
21
+ - A weekly usage limit that names no model family no longer marks every model on the provider spent: one request on another model family decides, and the refusal names both families when both are limited ([#5613](https://github.com/code-yeongyu/senpi/pull/5613))
22
+ - A goal paused by a Stop while the agent is idle now shows `Goal paused` and stops counting elapsed time; paused time no longer counts toward the goal ([#6173](https://github.com/code-yeongyu/senpi/pull/6173))
23
+ - An RPC socket host restores its `retain_on_disconnect` sessions after it restarts, whether it was killed or stopped cleanly and whether the session was idle or mid-turn: the next host on the same socket and agent dir lists them again with their durable id and transcript, so viewers re-attach instead of getting `session_not_found` (senpi#6190)
24
+ - A clean host stop parks a retained session (`session_parked { reason: "host_shutdown" }`) instead of closing it, and a turn the stop cuts short ends with `abortSource: "system"` and `abortCause: { kind: "host_shutdown" }` instead of a user abort (senpi#6190)
25
+ - A socket host started without `host ensure` (`--mode rpc --listen`, `--headless`) writes its `endpoint.json` registry record before it serves, so after `host gc` collected its dead endpoint during an outage the restarted host is listed again, instead of serving while relay discovery and `host status --all` find nothing ([#6195](https://github.com/code-yeongyu/senpi/pull/6195), part of #6190)
26
+ - `ask_user_question` / `request_user_input` refuse question text holding undecoded `\uXXXX` escapes once and ask the model to re-call with raw UTF-8 text; the re-call in a later turn opens as written with a warning, and parallel calls in one message are each refused once ([#6198](https://github.com/code-yeongyu/senpi/pull/6198))
27
+ - A multi-session host launched with a private-fd table answers a client's RPC auth handshake while its boot extension load runs, instead of timing out the first client (`RPC authentication timed out`) until the whole extension graph had compiled; an `open_session` that arrives during that load (or a warm of its working directory) now builds its runtime after it, waiting at most the close grace window ([#6200](https://github.com/code-yeongyu/senpi/pull/6200), fixes #6199)
28
+ - The terminal pipe fallback (used when the native PTY binding is unavailable) settles a session when its process exits, after a short drain of the output already written, instead of waiting for every process holding stdout or stderr to close. A command that left a process running (`cmd &`, a daemon, or the children of a shell killed from outside) no longer keeps its background terminal session, and the agent's `waiting_background` wait, open for that process's whole life. Settling does not kill those processes and does not put them out of reach: `kill_bash`, `TerminalSession.kill()`/`terminate()`, registry teardown and the registry's removal of exited sessions (capacity pruning, `sweepExited({ remove: true })`) still send TERM, then KILL after the grace, to the session's process group while it has members. The session forgets that group within about a second of it emptying, so an id the system later reuses is never signalled. The native PTY already settled when the shell exited ([#6203](https://github.com/code-yeongyu/senpi/pull/6203), part of #6201)
29
+ - An extension import (a tool child's module job included) no longer fails with "Extension generation N has been disposed" when its importer is garbage-collected between two module loads; the import keeps its graph alive until it settles ([#6210](https://github.com/code-yeongyu/senpi/pull/6210), fixes #6208)
30
+
31
+ ### Removed
32
+
3
33
  ## [2026.11.6-2] - 2026-11-07
4
34
 
5
35
  ### Breaking Changes
@@ -7,7 +7,7 @@ import{external_exports}from"./chunk-KUPQO7MC.js";import"./chunk-IKOFCODM.js";im
7
7
  `):f2,s2=b2}}function u(e,i2){if(a.rts(),!a.rt())return;let r2="",s2=e+1,f2=e+1,c2=a.te();for(;f2<i2;){let e2=t.charCodeAt(f2);if(e2===96)break;e2!==92?e2!==42?e2===36&&t.charCodeAt(f2+1)===123&&f2+2<=c2?(r2+=t.slice(s2,f2)+"*",f2=s2=c2,c2=a.rt()?a.te():-1):f2++:(r2+=t.slice(s2,f2)+"\\*",s2=++f2):f2+=2}return r2+t.slice(s2,f2)}function o(e,a2){(a2<1||e+a2>t.length)&&(k=e,h());let i2=0,r2=e+a2;for(let a3=e;a3<r2;a3++){let e2=t.charCodeAt(a3),r3=32|e2,s2=e2>=48&&e2<=57?e2-48:r3>=97&&r3<=102?r3-87:-1;s2===-1&&(k=a3,h()),i2=16*i2+s2}return i2}function h(){throw Object.assign(Error(`Parse error ${b}:${t.slice(0,k).split(`
8
8
  `).length}:${k-t.lastIndexOf(`
9
9
  `,k-1)}`),{idx:k})}import{readFileSync}from"node:fs";import{basename,dirname,extname,join,parse as parsePath}from"node:path";var commonJsByPath=new Map;function isCommonJsFile(path){let cached=commonJsByPath.get(path);if(cached!==void 0)return cached;let result=detect(path);return commonJsByPath.set(path,result),result}function isEsmByPackageType(path){let directory=dirname(path),{root}=parsePath(directory);for(;;){if(basename(directory)==="node_modules")return!1;let manifestPath=join(directory,"package.json"),manifest;try{manifest=readFileSync(manifestPath,"utf8")}catch(error){let code=error.code;if(code!=="ENOENT"&&code!=="ENOTDIR")throw error}if(manifest!==void 0)return JSON.parse(manifest).type==="module";if(directory===root)return!1;let parent=dirname(directory);if(parent===directory)return!1;directory=parent}}function detect(path){let extension=extname(path);if(extension===".cjs")return!0;if(extension===".mjs"||extension===".ts"||extension===".tsx"||extension===".mts"||extension===".js"&&isEsmByPackageType(path))return!1;try{let[,,,hasModuleSyntax]=parse(readFileSync(path,"utf8"),path);return!hasModuleSyntax}catch{return!1}}function parseImportClause(clause){let rest=clause.trim();if(rest==="")return;let defaultBinding,namespaceBinding,named=[],braceStart=rest.indexOf("{"),head=(braceStart>=0?rest.slice(0,braceStart):rest).trim().replace(/,$/,"").trim();if(head!==""){let namespace=/^\*\s+as\s+([A-Za-z_$][\w$]*)$/.exec(head);if(namespace?.[1]!==void 0)namespaceBinding=namespace[1];else if(/^[A-Za-z_$][\w$]*$/.test(head))defaultBinding=head;else return}if(braceStart>=0){let braceEnd=rest.lastIndexOf("}");if(braceEnd<braceStart)return;rest=rest.slice(braceStart+1,braceEnd);for(let raw of rest.split(",")){let entry=raw.trim();if(entry==="")continue;let aliased=/^(?:(["'])(.+?)\1|([A-Za-z_$][\w$]*))\s+as\s+([A-Za-z_$][\w$]*)$/.exec(entry);if(aliased){named.push({imported:aliased[2]??aliased[3]??"",local:aliased[4]??""});continue}if(/^[A-Za-z_$][\w$]*$/.test(entry)){named.push({imported:entry,local:entry});continue}return}}return{defaultBinding,namespaceBinding,named}}function rewriteCommonJsImport(clause,resolvedId,alias,attributes=""){let parsed=parseImportClause(clause);if(parsed===void 0)return`import ${JSON.stringify(resolvedId)}${attributes};`;let lines=[`import ${alias} from ${JSON.stringify(resolvedId)}${attributes};`];if(parsed.defaultBinding!==void 0&&lines.push(`const ${parsed.defaultBinding} = ${alias};`),parsed.namespaceBinding!==void 0&&lines.push(`const ${parsed.namespaceBinding} = ${alias};`),parsed.named.length>0){let pattern=parsed.named.map(({imported,local})=>{let key=/^[A-Za-z_$][\w$]*$/.test(imported)?imported:JSON.stringify(imported);return key===local?key:`${key}: ${local}`}).join(", ");lines.push(`const { ${pattern} } = ${alias};`)}return lines.join(" ")}var diagnosticSchema=external_exports.object({message:external_exports.string(),position:external_exports.object({line:external_exports.number(),column:external_exports.number()}).nullish()}),ExtensionSourceError=class extends Error{constructor(filename,cause){let diagnostics=external_exports.array(diagnosticSchema).parse(cause.errors).map(({message,position})=>({message,...position?{line:position.line,column:position.column}:{}}));super(diagnostics.map(item=>`${filename}${item.line===void 0?"":`:${item.line}:${item.column}`}: ${item.message}`).join(`
10
- `),{cause}),this.name="ExtensionSourceError",this.filename=filename,this.diagnostics=diagnostics}};import{createHash}from"node:crypto";import{mkdirSync,readdirSync,readFileSync as readFileSync2,renameSync,rmSync,statSync,writeFileSync}from"node:fs";import{join as join2}from"node:path";var MAX_ENTRY_AGE_MS=720*60*60*1e3,sha256=text=>createHash("sha256").update(text).digest("hex");function isPreparedSource(value){if(typeof value!="object"||value===null)return!1;let field=name=>typeof Reflect.get(value,name);return field("key")==="string"&&field("fingerprint")==="string"&&field("token")==="string"&&field("contents")==="string"&&field("commonJs")==="boolean"&&field("esmByType")==="boolean"&&Array.isArray(Reflect.get(value,"edges"))}function prune(directory){let cutoff=Date.now()-MAX_ENTRY_AGE_MS;for(let name of readdirSync(directory)){let path=join2(directory,name);statSync(path).mtimeMs<cutoff&&rmSync(path,{force:!0})}}function createPreparedSourceCache(directory,keyParts){let key=sha256(keyParts.join("\0")),entryPath=filename=>join2(directory,`${sha256(filename).slice(0,40)}.json`),pruned=!1;return{read(filename,fingerprint){let parsed;try{parsed=JSON.parse(readFileSync2(entryPath(filename),"utf8"))}catch{return}if(!(!isPreparedSource(parsed)||parsed.key!==key||parsed.fingerprint!==fingerprint))return parsed},write(filename,fingerprint,prepared){let target=entryPath(filename),temporary=`${target}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;try{mkdirSync(directory,{recursive:!0}),writeFileSync(temporary,JSON.stringify({...prepared,key,fingerprint})),renameSync(temporary,target),pruned||(pruned=!0,prune(directory))}catch{rmSync(temporary,{force:!0})}}}}import{existsSync}from"node:fs";import{dirname as dirname2,isAbsolute}from"node:path";import{fileURLToPath,pathToFileURL}from"node:url";var RUNTIME_METADATA=Symbol.for("senpi.extension.runtime.metadata");function publishRuntimeMetadata(value){globalThis[RUNTIME_METADATA]=value}var importModule=new Function("specifier","options","return import(specifier, options)"),extensionNamespace="senpi-extension",RUNTIME_SPECIFIER="runtime",runtimeModulePath=resolveRuntimeModulePath();function resolveRuntimeModulePath(){try{let candidate=fileURLToPath(new URL("./extension-runtime-module.js",import.meta.url));return existsSync(candidate)?candidate:void 0}catch{return}}function splitModuleId(id){let slash=id.indexOf("/");if(!(slash<=0||slash===id.length-1))return{generation:id.slice(0,slash),filename:decodeURIComponent(id.slice(slash+1))}}var graphs=new Map,collected=new FinalizationRegistry(generation=>graphs.delete(generation)),nextGeneration=0,installed=!1,pluginRegistrations=0,registeredHosts=new Set,ExtensionModuleIdError=class extends Error{constructor(id){super(`Extension module id is not "<generation>/<encoded filename>": ${id}`),this.name="ExtensionModuleIdError"}},ExtensionGenerationDisposedError=class extends Error{constructor(generation){super(`Extension generation ${generation} has been disposed`),this.name="ExtensionGenerationDisposedError",this.generation=generation}};function graphFor(generation){let graph=graphs.get(generation)?.deref();if(!graph)throw new ExtensionGenerationDisposedError(generation);return graph}function metadata(generation,filename){let resolvePath=specifier=>{let id=graphFor(generation).resolve(specifier,filename);return id.startsWith(`${extensionNamespace}:`)?decodeURIComponent(id.slice(id.indexOf("/")+1)):isAbsolute(id)?id:void 0},require2=Object.assign(specifier=>graphFor(generation).require(specifier,filename),{resolve:specifier=>resolvePath(specifier)??graphFor(generation).resolve(specifier,filename)});return{url:pathToFileURL(filename).href,path:filename,dir:dirname2(filename),filename,dirname:dirname2(filename),require:require2,commonJs:body=>graphFor(generation).evaluateCommonJs(filename,body),import:async(specifier,options)=>importModule(graphFor(generation).resolve(specifier,filename),options),resolve:specifier=>{let path=resolvePath(specifier);return path===void 0?graphFor(generation).resolve(specifier,filename):pathToFileURL(path).href}}}function installRegistry(virtualModules){let hosts=Object.entries(virtualModules).filter(([name])=>!registeredHosts.has(name));(!installed||hosts.length>0)&&(pluginRegistrations++,Bun.plugin({name:extensionNamespace,setup(builder){for(let[name,exports]of hosts)builder.module(name,()=>({exports,loader:"object"})),registeredHosts.add(name);installed||(publishRuntimeMetadata(metadata),builder.module(`${extensionNamespace}:${RUNTIME_SPECIFIER}`,()=>({exports:{metadata},loader:"object"})),builder.onResolve({filter:/.*/,namespace:extensionNamespace},({path})=>{if(path===RUNTIME_SPECIFIER)return runtimeModulePath===void 0?{path,namespace:extensionNamespace}:{path:runtimeModulePath,namespace:"file"};let parsed=splitModuleId(path);if(parsed===void 0)throw new ExtensionModuleIdError(path);return graphFor(parsed.generation),{path,namespace:extensionNamespace}}),builder.onLoad({filter:/.*/,namespace:extensionNamespace},({path})=>{let parsed=splitModuleId(path);if(parsed===void 0)throw new ExtensionModuleIdError(path);return graphFor(parsed.generation).load(parsed.filename)}),installed=!0)}}))}function registerExtensionGraph(graph,virtualModules){installRegistry(virtualModules);let generation=String(nextGeneration++);return graphs.set(generation,new WeakRef(graph)),collected.register(graph,generation,graph),{generation,dispose(){graphs.delete(generation),collected.unregister(graph)}}}function bunExtensionImporterStats(){return{generations:[...graphs.values()].filter(entry=>entry.deref()).length,plugins:pluginRegistrations}}function skipTrivia(source,index){let hasLineTerminator=!1;for(;index<source.length;){let char=source[index];if(char==="\r"||char===`
10
+ `),{cause}),this.name="ExtensionSourceError",this.filename=filename,this.diagnostics=diagnostics}};var queued=[],draining=!1,synchronousDepth=0;function drainOne(){queued.shift()?.(),queued.length>0?setImmediate(drainOne):draining=!1}function loadInTurn(load){return synchronousDepth>0?load():new Promise((resolve2,reject)=>{queued.push(()=>{try{resolve2(load())}catch(error){reject(error)}}),!draining&&(draining=!0,setImmediate(drainOne))})}function loadSynchronously(require2){synchronousDepth++;try{return require2()}finally{synchronousDepth--}}import{createHash}from"node:crypto";import{mkdirSync,readdirSync,readFileSync as readFileSync2,renameSync,rmSync,statSync,writeFileSync}from"node:fs";import{join as join2}from"node:path";var MAX_ENTRY_AGE_MS=720*60*60*1e3,sha256=text=>createHash("sha256").update(text).digest("hex");function isPreparedSource(value){if(typeof value!="object"||value===null)return!1;let field=name=>typeof Reflect.get(value,name);return field("key")==="string"&&field("fingerprint")==="string"&&field("token")==="string"&&field("contents")==="string"&&field("commonJs")==="boolean"&&field("esmByType")==="boolean"&&Array.isArray(Reflect.get(value,"edges"))}function prune(directory){let cutoff=Date.now()-MAX_ENTRY_AGE_MS;for(let name of readdirSync(directory)){let path=join2(directory,name);statSync(path).mtimeMs<cutoff&&rmSync(path,{force:!0})}}function createPreparedSourceCache(directory,keyParts){let key=sha256(keyParts.join("\0")),entryPath=filename=>join2(directory,`${sha256(filename).slice(0,40)}.json`),pruned=!1;return{read(filename,fingerprint){let parsed;try{parsed=JSON.parse(readFileSync2(entryPath(filename),"utf8"))}catch{return}if(!(!isPreparedSource(parsed)||parsed.key!==key||parsed.fingerprint!==fingerprint))return parsed},write(filename,fingerprint,prepared){let target=entryPath(filename),temporary=`${target}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;try{mkdirSync(directory,{recursive:!0}),writeFileSync(temporary,JSON.stringify({...prepared,key,fingerprint})),renameSync(temporary,target),pruned||(pruned=!0,prune(directory))}catch{rmSync(temporary,{force:!0})}}}}import{existsSync}from"node:fs";import{dirname as dirname2,isAbsolute}from"node:path";import{fileURLToPath,pathToFileURL}from"node:url";var RUNTIME_METADATA=Symbol.for("senpi.extension.runtime.metadata");function publishRuntimeMetadata(value){globalThis[RUNTIME_METADATA]=value}var importModule=new Function("specifier","options","return import(specifier, options)"),extensionNamespace="senpi-extension",RUNTIME_SPECIFIER="runtime",runtimeModulePath=resolveRuntimeModulePath();function resolveRuntimeModulePath(){try{let candidate=fileURLToPath(new URL("./extension-runtime-module.js",import.meta.url));return existsSync(candidate)?candidate:void 0}catch{return}}function splitModuleId(id){let slash=id.indexOf("/");if(!(slash<=0||slash===id.length-1))return{generation:id.slice(0,slash),filename:decodeURIComponent(id.slice(slash+1))}}var graphs=new Map,collected=new FinalizationRegistry(generation=>graphs.delete(generation)),importing=new Map,nextGeneration=0,installed=!1,pluginRegistrations=0,registeredHosts=new Set,ExtensionModuleIdError=class extends Error{constructor(id){super(`Extension module id is not "<generation>/<encoded filename>": ${id}`),this.name="ExtensionModuleIdError"}},ExtensionGenerationDisposedError=class extends Error{constructor(generation){super(`Extension generation ${generation} has been disposed`),this.name="ExtensionGenerationDisposedError",this.generation=generation}};function graphFor(generation){let graph=graphs.get(generation)?.deref();if(!graph)throw new ExtensionGenerationDisposedError(generation);return graph}function metadata(generation,filename){let resolvePath=specifier=>{let id=graphFor(generation).resolve(specifier,filename);return id.startsWith(`${extensionNamespace}:`)?decodeURIComponent(id.slice(id.indexOf("/")+1)):isAbsolute(id)?id:void 0},require2=Object.assign(specifier=>graphFor(generation).require(specifier,filename),{resolve:specifier=>resolvePath(specifier)??graphFor(generation).resolve(specifier,filename)});return{url:pathToFileURL(filename).href,path:filename,dir:dirname2(filename),filename,dirname:dirname2(filename),require:require2,commonJs:body=>graphFor(generation).evaluateCommonJs(filename,body),import:async(specifier,options)=>importModule(graphFor(generation).resolve(specifier,filename),options),resolve:specifier=>{let path=resolvePath(specifier);return path===void 0?graphFor(generation).resolve(specifier,filename):pathToFileURL(path).href}}}function installRegistry(virtualModules){let hosts=Object.entries(virtualModules).filter(([name])=>!registeredHosts.has(name));(!installed||hosts.length>0)&&(pluginRegistrations++,Bun.plugin({name:extensionNamespace,setup(builder){for(let[name,exports]of hosts)builder.module(name,()=>({exports,loader:"object"})),registeredHosts.add(name);installed||(publishRuntimeMetadata(metadata),builder.module(`${extensionNamespace}:${RUNTIME_SPECIFIER}`,()=>({exports:{metadata},loader:"object"})),builder.onResolve({filter:/.*/,namespace:extensionNamespace},({path})=>{if(path===RUNTIME_SPECIFIER)return runtimeModulePath===void 0?{path,namespace:extensionNamespace}:{path:runtimeModulePath,namespace:"file"};let parsed=splitModuleId(path);if(parsed===void 0)throw new ExtensionModuleIdError(path);return graphFor(parsed.generation),{path,namespace:extensionNamespace}}),builder.onLoad({filter:/.*/,namespace:extensionNamespace},({path})=>{let parsed=splitModuleId(path);if(parsed===void 0)throw new ExtensionModuleIdError(path);return loadInTurn(()=>graphFor(parsed.generation).load(parsed.filename))}),installed=!0)}}))}function registerExtensionGraph(graph,virtualModules){installRegistry(virtualModules);let generation=String(nextGeneration++);return graphs.set(generation,new WeakRef(graph)),collected.register(graph,generation,graph),{generation,async holdDuring(pending){importing.set(graph,(importing.get(graph)??0)+1);try{return await pending}finally{let remaining=(importing.get(graph)??1)-1;remaining===0?importing.delete(graph):importing.set(graph,remaining)}},dispose(){graphs.delete(generation),collected.unregister(graph)}}}function bunExtensionImporterStats(){return{generations:[...graphs.values()].filter(entry=>entry.deref()).length,plugins:pluginRegistrations}}function skipTrivia(source,index){let hasLineTerminator=!1;for(;index<source.length;){let char=source[index];if(char==="\r"||char===`
11
11
  `||char==="\u2028"||char==="\u2029"){hasLineTerminator=!0,index+=1;continue}if(char!==void 0&&/\s/u.test(char)){index+=1;continue}if(char==="/"&&source[index+1]==="/"){for(index+=2;index<source.length&&!/[\r\n\u2028\u2029]/u.test(source[index]??"");)index+=1;continue}if(char==="/"&&source[index+1]==="*"){for(index+=2;index<source.length;){let commentChar=source[index];if((commentChar==="\r"||commentChar===`
12
12
  `||commentChar==="\u2028"||commentChar==="\u2029")&&(hasLineTerminator=!0),commentChar==="*"&&source[index+1]==="/"){index+=2;break}index+=1}continue}break}return{index,hasLineTerminator}}function stringLiteralEnd(source,index){let quote=source[index];if(!(quote!=='"'&&quote!=="'"))for(index+=1;index<source.length;index+=1){let char=source[index];if(char==="\\"){index+=1,source[index]==="\r"&&source[index+1]===`
13
13
  `&&(index+=1);continue}if(char===quote)return index+1;if(char==="\r"||char===`
@@ -18,4 +18,4 @@ import{external_exports}from"./chunk-KUPQO7MC.js";import"./chunk-IKOFCODM.js";im
18
18
  //# sourceURL=${pathToFileURL2(filename).href}`;contents=[`const ${name}Body = Function(${JSON.stringify(name)}, "exports", "module", ${JSON.stringify(body)});`,`export default ${name}.commonJs(function (exports, module) {`,` return ${name}Body.call(this, ${name}, exports, module);`,"});"].join(`
19
19
  `)}return contents=`import { metadata as ${name}Factory } from "${extensionNamespace}:runtime"; // runtime ${runtimeModulePath===void 0?"virtual":encodeURI(runtimeModulePath)}
20
20
  const ${name} = ${name}Factory(${JSON.stringify(token)}, ${JSON.stringify(filename)});
21
- ${contents}`,{token,contents,commonJs:isCommonJs,esmByType,edges}},graph={assertActive,resolve(specifier,filename){return resolveTarget(specifier,filename).id},require(specifier,filename){let id=graph.resolve(specifier,filename),evaluating=commonJsModules.get(id);if(evaluating!==void 0)return evaluating.exports;let result=nativeRequire(id);return commonJs.has(id)?result.default:result},evaluateCommonJs(filename,body){assertActive();let id=moduleId(filename),module={exports:{}};commonJsModules.set(id,module);try{body.call(module.exports,module.exports,module)}catch(error){throw commonJsModules.delete(id),error}return module.exports},load(filename){assertActive();let existing=sources.get(filename);if(existing)return existing;let source=readFileSync3(filename,"utf8"),fingerprint=createHash2("sha256").update(source).digest("hex"),name="__senpiExtensionMeta";for(;source.includes(name)||filename.includes(name);)name+="_";let token=`${name}:generation`,esmByType=extname2(filename)===".js"&&isEsmByPackageType(filename),cached=preparedCache?.read(filename,fingerprint),ready=cached?.token===token&&cached.esmByType===esmByType&&edgesStillResolve(cached.edges,filename,token)?cached:void 0;ready===void 0&&(ready=prepare(source,filename,token,name,esmByType),preparedCache?.write(filename,fingerprint,ready)),ready.commonJs&&commonJs.add(moduleId(filename));let prepared={contents:ready.contents.replaceAll(token,registration.generation),loader:"js"};return sources.set(filename,prepared),fingerprints.set(filename,fingerprint),prepared}},registration=registerExtensionGraph(graph,virtualModules);return{async import(path,_options){assertActive();let absolute=realpathSync(resolve(path)),entry=statSync2(absolute).isDirectory()?realpathSync(Bun.resolveSync(absolute,absolute)):absolute,{id}=fileTarget(entry),factory=(await import(__rewriteRelativeImportExtension(id))).default;return typeof factory!="function"?factory:function(...args){return graph.assertActive(),factory.apply(this,args)}},async importNamespace(path){assertActive();let{id}=fileTarget(realpathSync(resolve(path)));return import(__rewriteRelativeImportExtension(id))},compiledSources(){return fingerprints},dispose(){active=!1,registration.dispose(),sources.clear(),fingerprints.clear(),commonJs.clear(),commonJsModules.clear()}}}export{bunExtensionImporterStats,createBunExtensionImporter};
21
+ ${contents}`,{token,contents,commonJs:isCommonJs,esmByType,edges}},graph={assertActive,resolve(specifier,filename){return resolveTarget(specifier,filename).id},require(specifier,filename){let id=graph.resolve(specifier,filename),evaluating=commonJsModules.get(id);if(evaluating!==void 0)return evaluating.exports;let result=loadSynchronously(()=>nativeRequire(id));return commonJs.has(id)?result.default:result},evaluateCommonJs(filename,body){assertActive();let id=moduleId(filename),module={exports:{}};commonJsModules.set(id,module);try{body.call(module.exports,module.exports,module)}catch(error){throw commonJsModules.delete(id),error}return module.exports},load(filename){assertActive();let existing=sources.get(filename);if(existing)return existing;let source=readFileSync3(filename,"utf8"),fingerprint=createHash2("sha256").update(source).digest("hex"),name="__senpiExtensionMeta";for(;source.includes(name)||filename.includes(name);)name+="_";let token=`${name}:generation`,esmByType=extname2(filename)===".js"&&isEsmByPackageType(filename),cached=preparedCache?.read(filename,fingerprint),ready=cached?.token===token&&cached.esmByType===esmByType&&edgesStillResolve(cached.edges,filename,token)?cached:void 0;ready===void 0&&(ready=prepare(source,filename,token,name,esmByType),preparedCache?.write(filename,fingerprint,ready)),ready.commonJs&&commonJs.add(moduleId(filename));let prepared={contents:ready.contents.replaceAll(token,registration.generation),loader:"js"};return sources.set(filename,prepared),fingerprints.set(filename,fingerprint),prepared}},registration=registerExtensionGraph(graph,virtualModules);return{async import(path,_options){assertActive();let absolute=realpathSync(resolve(path)),entry=statSync2(absolute).isDirectory()?realpathSync(Bun.resolveSync(absolute,absolute)):absolute,{id}=fileTarget(entry),factory=(await registration.holdDuring(import(__rewriteRelativeImportExtension(id)))).default;return typeof factory!="function"?factory:function(...args){return graph.assertActive(),factory.apply(this,args)}},async importNamespace(path){assertActive();let{id}=fileTarget(realpathSync(resolve(path)));return registration.holdDuring(import(__rewriteRelativeImportExtension(id)))},compiledSources(){return fingerprints},dispose(){active=!1,registration.dispose(),sources.clear(),fingerprints.clear(),commonJs.clear(),commonJsModules.clear()}}}export{bunExtensionImporterStats,createBunExtensionImporter};
@@ -1,2 +1,2 @@
1
1
  import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
2
- import{uptime as osUptimeSeconds}from"node:os";import{workerData}from"node:worker_threads";var BOOT_INSTANT_TOLERANCE_MS=12e4,wholeSeconds=ms=>Math.round(ms/1e3)*1e3;function processBootAtMs(now=Date.now){return wholeSeconds(now()-osUptimeSeconds()*1e3)}var floorToSecond=ms=>Math.floor(ms/1e3)*1e3,hostIdentity=workerData,OWN_START_AT_LOAD=typeof hostIdentity=="object"&&hostIdentity!==null&&"hostProcessStartedAtMs"in hostIdentity&&typeof hostIdentity.hostProcessStartedAtMs=="number"&&Number.isFinite(hostIdentity.hostProcessStartedAtMs)?hostIdentity.hostProcessStartedAtMs:floorToSecond(Date.now()-process.uptime()*1e3);function ownProcessStartedAtMs(now){return now===void 0?OWN_START_AT_LOAD:floorToSecond(now()-process.uptime()*1e3)}function sameBoot(bootAtMs,otherBootAtMs){return otherBootAtMs===void 0||!Number.isFinite(otherBootAtMs)?!1:Math.abs(bootAtMs-otherBootAtMs)<=BOOT_INSTANT_TOLERANCE_MS}export{processBootAtMs,ownProcessStartedAtMs,sameBoot};
2
+ import{uptime as osUptimeSeconds}from"node:os";import{workerData}from"node:worker_threads";var BOOT_INSTANT_TOLERANCE_MS=12e4,wholeSeconds=ms=>Math.round(ms/1e3)*1e3;function processBootAtMs(now=Date.now){return wholeSeconds(now()-osUptimeSeconds()*1e3)}var floorToSecond=ms=>Math.floor(ms/1e3)*1e3,hostIdentity=workerData,OWN_START_AT_LOAD=typeof hostIdentity=="object"&&hostIdentity!==null&&"hostProcessStartedAtMs"in hostIdentity&&typeof hostIdentity.hostProcessStartedAtMs=="number"&&Number.isFinite(hostIdentity.hostProcessStartedAtMs)?hostIdentity.hostProcessStartedAtMs:floorToSecond(Date.now()-process.uptime()*1e3);function ownProcessStartedAtMs(now){return now===void 0?OWN_START_AT_LOAD:floorToSecond(now()-process.uptime()*1e3)}function sameBoot(bootAtMs,otherBootAtMs){return otherBootAtMs===void 0||!Number.isFinite(otherBootAtMs)?!1:Math.abs(bootAtMs-otherBootAtMs)<=BOOT_INSTANT_TOLERANCE_MS}export{BOOT_INSTANT_TOLERANCE_MS,processBootAtMs,ownProcessStartedAtMs,sameBoot};
@@ -1,5 +1,5 @@
1
1
  import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
2
- import{DynamicBorder,getEditorTheme,keyDisplayText,keyHint,observeVisibleStderrWrites,rawKeyHint,restoreStderr,sharedMarkdownTheme,takeOverStderr,theme}from"./chunk-RQ6CHXQ2.js";import{userWordBlocks}from"./chunk-22YXCY7K.js";import{isWSL}from"./chunk-4GKU755E.js";import{usageLimitScope}from"./chunk-C7HEEBFH.js";import{signalSpawnedChild}from"./chunk-KLAX467B.js";import{appendHiddenTuiStdout}from"./chunk-MSDBBOB2.js";import{CURSOR_MARKER,Container,Editor,Input,Markdown,MouseRegion,ProcessTerminal,ScrollView,Spacer,Text,TuiAltScreen,TuiMainScreen,VStack,getKeybindings,getNativeClipboard,isWarpWslSession,matchesKey,nextRenderRevision,truncateToWidth,visibleWidth}from"./chunk-TMXRR3N7.js";import{redactSensitiveOutput}from"./chunk-BPNSOZ2C.js";import{SERVER_FALLBACK_ABORTED_DIAGNOSTIC}from"./chunk-Z6TEQEZO.js";import{ACCOUNT_LIMIT_NEXT_STEP_LEAD,describeProviderFailureForUser,stripTurnRetrySuppressionPrefix}from"./chunk-OKMHSVCA.js";import{getDebugLogPath,stripBom}from"./chunk-SODMQEHO.js";import{typebox_exports}from"./chunk-MIENF2YK.js";var CODEX_OPTION=typebox_exports.Object({label:typebox_exports.String({description:"User-facing label (1-5 words)."}),description:typebox_exports.String({description:"One short sentence explaining impact/tradeoff if selected."})},{additionalProperties:!1}),CODEX_QUESTION=typebox_exports.Object({id:typebox_exports.String({pattern:"^[a-z][a-z0-9]*(_[a-z0-9]+)*$",description:"Stable identifier for mapping answers (snake_case)."}),header:typebox_exports.String({minLength:1,maxLength:12,description:"Short header label shown in the UI (12 or fewer chars)."}),question:typebox_exports.String({minLength:1,description:"Single-sentence prompt shown to the user."}),options:typebox_exports.Array(CODEX_OPTION,{minItems:2,maxItems:3,description:'Provide 2-3 mutually exclusive choices. Put the recommended option first and suffix its label with "(Recommended)". Do not include an "Other" option in this list; the client will add a free-form "Other" option automatically.'}),multiSelect:typebox_exports.Optional(typebox_exports.Boolean({description:"Set to true to allow the user to select multiple options instead of just one."}))},{additionalProperties:!1}),CODEX_PARAMS=typebox_exports.Object({questions:typebox_exports.Array(CODEX_QUESTION,{minItems:1,maxItems:3,description:"Questions to show the user. Prefer 1 and do not exceed 3"}),wait_for_answer:typebox_exports.Boolean({description:"Set true to pause here until the user answers; set false to keep working and receive the answer later as a user message."}),required:typebox_exports.Optional(typebox_exports.Boolean({description:"Set true when the answer decides whether you take an action (for example, which of two irreversible paths to take, or whether to proceed): with no answer, that action is not taken."}))},{additionalProperties:!1}),CLAUDE_OPTION=typebox_exports.Object({label:typebox_exports.String({description:"The display text for this option that the user will see and select. Should be concise (1-5 words) and clearly describe the choice."}),description:typebox_exports.Optional(typebox_exports.String({description:"Explanation of what this option means or what will happen if chosen. Useful for providing context about trade-offs or implications."}))}),CLAUDE_QUESTION=typebox_exports.Object({question:typebox_exports.String({minLength:1,description:'The complete question to ask the user. Should be clear, specific, and end with a question mark. Example: "Which library should we use for date formatting?" If multiSelect is true, phrase it accordingly, e.g. "Which features do you want to enable?"'}),header:typebox_exports.String({minLength:1,maxLength:12,description:'Very short label displayed as a chip/tag (max 12 chars). Examples: "Auth method", "Library", "Approach".'}),options:typebox_exports.Optional(typebox_exports.Array(CLAUDE_OPTION,{minItems:2,maxItems:4,description:"The available choices for this question. Must have 2-4 options. Each option should be a distinct, mutually exclusive choice (unless multiSelect is enabled). There should be no Other option, that will be provided automatically."})),multiSelect:typebox_exports.Boolean({description:"Set to true to allow the user to select multiple options instead of just one. Use when choices are not mutually exclusive."})}),CLAUDE_PARAMS=typebox_exports.Object({questions:typebox_exports.Array(CLAUDE_QUESTION,{minItems:1,maxItems:4,description:"Questions to ask the user (1-4 questions)"}),waitForAnswer:typebox_exports.Boolean({description:"Set true to pause here until the user answers; set false to keep working and receive the answer later as a user message."}),required:typebox_exports.Optional(typebox_exports.Boolean({description:"Set true when the answer decides whether you take an action (for example, which of two irreversible paths to take, or whether to proceed): with no answer, that action is not taken."}))});var WAIT_FLAG_STEER_TEXT="This call omitted wait_for_answer (or waitForAnswer). Set true to pause here until the user answers, false to keep working and receive the answer later as a user message.",DEFAULT_ASK_USER_TIMEOUT_MS=1800*1e3,HEADER_MAX=12,SNAKE_CASE=/^[a-z][a-z0-9]*(_[a-z0-9]+)*$/,LIMITS={codex:{maxQuestions:3,minOptions:2,maxOptions:3,optionsRequired:!0},claude:{maxQuestions:4,minOptions:2,maxOptions:4,optionsRequired:!1}},AskUserSchemaError=class extends Error{constructor(message){super(message),this.name="AskUserSchemaError"}};function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function readWaitFlag(variant,args){let value=args[variant==="codex"?"wait_for_answer":"waitForAnswer"];if(typeof value!="boolean")throw new AskUserSchemaError(WAIT_FLAG_STEER_TEXT);return value}function parseOptions(raw,min,max,required,requireDescription){if(raw===void 0){if(required)throw new AskUserSchemaError(`options must contain ${min} to ${max} items`);return[]}if(!Array.isArray(raw))throw new AskUserSchemaError("options must be an array");if(raw.length<min||raw.length>max)throw new AskUserSchemaError(required?`options must contain ${min} to ${max} items`:`options must contain ${min} to ${max} items when present`);let options=[];for(let item of raw){if(!isRecord(item))throw new AskUserSchemaError("each option must be an object");let label=typeof item.label=="string"?item.label.trim():"";if(label.length===0)throw new AskUserSchemaError("option label must be non-empty");let description=typeof item.description=="string"?item.description.trim():void 0;if(requireDescription&&(description===void 0||description.length===0))throw new AskUserSchemaError("option description is required");options.push(description===void 0||description.length===0?{label}:{label,description})}return options}function parseQuestion(variant,raw,index){if(!isRecord(raw))throw new AskUserSchemaError("each question must be an object");let limits=LIMITS[variant],header=typeof raw.header=="string"?raw.header.trim():"";if(header.length===0)throw new AskUserSchemaError("header must be non-empty");if(header.length>HEADER_MAX)throw new AskUserSchemaError("header must be 12 or fewer characters");let question=typeof raw.question=="string"?raw.question.trim():"";if(question.length===0)throw new AskUserSchemaError("question must be non-empty");let options=parseOptions(raw.options,limits.minOptions,limits.maxOptions,limits.optionsRequired,variant==="codex"),id;if(variant==="claude")id=`q${index+1}`;else if(id=typeof raw.id=="string"?raw.id.trim():"",!SNAKE_CASE.test(id))throw new AskUserSchemaError("id must be snake_case");let multiSelect;if(variant==="claude"){if(typeof raw.multiSelect!="boolean")throw new AskUserSchemaError("multiSelect is required");multiSelect=raw.multiSelect}else multiSelect=raw.multiSelect===!0;return{id,header,question,options,multiSelect}}function toCanonical(variant,args,options){if(!isRecord(args))throw new AskUserSchemaError(WAIT_FLAG_STEER_TEXT);let waitForAnswer=readWaitFlag(variant,args);if(args.required!==void 0&&typeof args.required!="boolean")throw new AskUserSchemaError("required must be a boolean when present");let limits=LIMITS[variant];if(!Array.isArray(args.questions)||args.questions.length<1||args.questions.length>limits.maxQuestions)throw new AskUserSchemaError(`questions must contain 1 to ${limits.maxQuestions} items`);return{requestId:options?.requestId??crypto.randomUUID(),questions:args.questions.map((question,index)=>parseQuestion(variant,question,index)),waitForAnswer,timeoutMs:options?.timeoutMs??DEFAULT_ASK_USER_TIMEOUT_MS,...args.required===!0?{required:!0}:{}}}var INLINE_WORDS={comment:text=>text,typed:(_header,text)=>text},reference=label=>`(see [${label}] below)`;function separatedWords(requestId){let words=[],place=(base,text)=>{let taken=words.filter(word=>word.label===base||word.label.startsWith(`${base} (`)).length,label=taken===0?base:`${base} (${taken+1})`;return words.push({label,text}),reference(label)};return{words,comment:text=>place(`The user's comment for question ${requestId}`,text),typed:(header,text)=>place(`The user's answer to ${header} for question ${requestId}`,text)}}function resolveUserWordReferences(text,words){return words.reduce((resolved,word)=>resolved.split(reference(word.label)).join(word.text),text)}function readUserWordBlocks(content){let texts=content.flatMap(block=>block.type==="text"?[block.text]:[]);if(texts.length%2!==0)return;let words=[];for(let index=0;index<texts.length;index+=2){let label=/^\[(.+)\]$/s.exec(texts[index]??"")?.[1],text=texts[index+1];if(label===void 0||text===void 0)return;words.push({label,text})}return words}function headerFor(id,questions){return questions.find(question=>question.id===id)?.header??id}function questionTextFor(id,questions){return questions.find(question=>question.id===id)?.question??id}function typedText(answer){if(answer.selected.length>0)return;let text=answer.text?.trim();return text===void 0||text.length===0?void 0:text}function answerBody(answer,header,words=INLINE_WORDS,offered=[]){if(!answer)return;if(answer.selected.length>0)return answer.selected.join(", ");let text=typedText(answer);if(text!==void 0)return offered.some(option=>option.label===text)?text:words.typed(header,text)}function answeredLines(response,questions,words){let lines=[],seen=new Set;for(let question of questions){let body=answerBody(response.answers[question.id],question.header,words,question.options);body!==void 0&&(lines.push(`${question.header}: ${body}`),seen.add(question.id))}for(let[id,answer]of Object.entries(response.answers)){if(seen.has(id))continue;let header=headerFor(id,questions),body=answerBody(answer,header,words);body!==void 0&&lines.push(`${header}: ${body}`)}return lines}function unansweredLine(response,questions){let unanswered=response.unanswered.map(id=>headerFor(id,questions));return unanswered.length>0?[`Unanswered: ${unanswered.join(", ")}`]:[]}var CANCELLED_BY_USER="The user cancelled the question after answering part of it.",CANCELLED_AFTER_ANSWERS="The question was cancelled after part of it was answered.";function isCancelledWithAnswersLine(line){return line===CANCELLED_BY_USER||line===CANCELLED_AFTER_ANSWERS}function showsPartialAnswers(response){return response.status!=="cancelled"||response.cancelOrigin!=="user"&&response.cancelOrigin!=="ui_failure"?!1:Object.values(response.answers).some(answer=>answerBody(answer,"")!==void 0)}function selectedBlock(prefix,selected){return selected.length===1?[`${prefix} ${selected[0]}`]:[prefix,...selected]}var GATED_NO_ANSWER="No answer: do not take the action it gates. Keep that action pending and end the turn.";function formatGatedNoAnswer(response,questions,words,cancellationReason){let lines=[cancellationReason??(response.status==="timed_out"?`The user did not answer within ${Math.round((response.autoResolvedAfterMs??DEFAULT_ASK_USER_TIMEOUT_MS)/6e4)} minutes. (\uC0AC\uC6A9\uC790\uAC00 \uB2F5\uBCC0\uC744 \uC548\uD558\uACE0 timeout \uC73C\uB85C \uC885\uB8CC\uB428)`:response.status==="cancelled"?"The user dismissed the question.":response.status==="orphaned-after-restart"?"The pending question could not be resumed after a restart.":"This session has no user attached (subagent or headless).")],selected=answeredLines(response,questions,words);return selected.length>0&&lines.push(...selectedBlock("Before going idle the user had selected (not an answer):",selected)),lines.push(GATED_NO_ANSWER),lines.join(`
2
+ import{DynamicBorder,getEditorTheme,keyDisplayText,keyHint,observeVisibleStderrWrites,rawKeyHint,restoreStderr,sharedMarkdownTheme,takeOverStderr,theme}from"./chunk-5LKB732P.js";import{userWordBlocks}from"./chunk-22YXCY7K.js";import{isWSL}from"./chunk-4GKU755E.js";import{usageLimitScope}from"./chunk-UODSYQ2D.js";import{signalSpawnedChild}from"./chunk-KLAX467B.js";import{appendHiddenTuiStdout}from"./chunk-MSDBBOB2.js";import{CURSOR_MARKER,Container,Editor,Input,Markdown,MouseRegion,ProcessTerminal,ScrollView,Spacer,Text,TuiAltScreen,TuiMainScreen,VStack,getKeybindings,getNativeClipboard,isWarpWslSession,matchesKey,nextRenderRevision,truncateToWidth,visibleWidth}from"./chunk-TMXRR3N7.js";import{redactSensitiveOutput}from"./chunk-BPNSOZ2C.js";import{SERVER_FALLBACK_ABORTED_DIAGNOSTIC}from"./chunk-Z6TEQEZO.js";import{ACCOUNT_LIMIT_NEXT_STEP_LEAD,describeProviderFailureForUser,stripTurnRetrySuppressionPrefix}from"./chunk-OKMHSVCA.js";import{getDebugLogPath,stripBom}from"./chunk-SODMQEHO.js";import{typebox_exports}from"./chunk-MIENF2YK.js";var CODEX_OPTION=typebox_exports.Object({label:typebox_exports.String({description:"User-facing label (1-5 words)."}),description:typebox_exports.String({description:"One short sentence explaining impact/tradeoff if selected."})},{additionalProperties:!1}),CODEX_QUESTION=typebox_exports.Object({id:typebox_exports.String({pattern:"^[a-z][a-z0-9]*(_[a-z0-9]+)*$",description:"Stable identifier for mapping answers (snake_case)."}),header:typebox_exports.String({minLength:1,maxLength:12,description:"Short header label shown in the UI (12 or fewer chars)."}),question:typebox_exports.String({minLength:1,description:"Single-sentence prompt shown to the user."}),options:typebox_exports.Array(CODEX_OPTION,{minItems:2,maxItems:3,description:'Provide 2-3 mutually exclusive choices. Put the recommended option first and suffix its label with "(Recommended)". Do not include an "Other" option in this list; the client will add a free-form "Other" option automatically.'}),multiSelect:typebox_exports.Optional(typebox_exports.Boolean({description:"Set to true to allow the user to select multiple options instead of just one."}))},{additionalProperties:!1}),CODEX_PARAMS=typebox_exports.Object({questions:typebox_exports.Array(CODEX_QUESTION,{minItems:1,maxItems:3,description:"Questions to show the user. Prefer 1 and do not exceed 3"}),wait_for_answer:typebox_exports.Boolean({description:"Set true to pause here until the user answers; set false to keep working and receive the answer later as a user message."}),required:typebox_exports.Optional(typebox_exports.Boolean({description:"Set true when the answer decides whether you take an action (for example, which of two irreversible paths to take, or whether to proceed): with no answer, that action is not taken."}))},{additionalProperties:!1}),CLAUDE_OPTION=typebox_exports.Object({label:typebox_exports.String({description:"The display text for this option that the user will see and select. Should be concise (1-5 words) and clearly describe the choice."}),description:typebox_exports.Optional(typebox_exports.String({description:"Explanation of what this option means or what will happen if chosen. Useful for providing context about trade-offs or implications."}))}),CLAUDE_QUESTION=typebox_exports.Object({question:typebox_exports.String({minLength:1,description:'The complete question to ask the user. Should be clear, specific, and end with a question mark. Example: "Which library should we use for date formatting?" If multiSelect is true, phrase it accordingly, e.g. "Which features do you want to enable?"'}),header:typebox_exports.String({minLength:1,maxLength:12,description:'Very short label displayed as a chip/tag (max 12 chars). Examples: "Auth method", "Library", "Approach".'}),options:typebox_exports.Optional(typebox_exports.Array(CLAUDE_OPTION,{minItems:2,maxItems:4,description:"The available choices for this question. Must have 2-4 options. Each option should be a distinct, mutually exclusive choice (unless multiSelect is enabled). There should be no Other option, that will be provided automatically."})),multiSelect:typebox_exports.Boolean({description:"Set to true to allow the user to select multiple options instead of just one. Use when choices are not mutually exclusive."})}),CLAUDE_PARAMS=typebox_exports.Object({questions:typebox_exports.Array(CLAUDE_QUESTION,{minItems:1,maxItems:4,description:"Questions to ask the user (1-4 questions)"}),waitForAnswer:typebox_exports.Boolean({description:"Set true to pause here until the user answers; set false to keep working and receive the answer later as a user message."}),required:typebox_exports.Optional(typebox_exports.Boolean({description:"Set true when the answer decides whether you take an action (for example, which of two irreversible paths to take, or whether to proceed): with no answer, that action is not taken."}))});var WAIT_FLAG_STEER_TEXT="This call omitted wait_for_answer (or waitForAnswer). Set true to pause here until the user answers, false to keep working and receive the answer later as a user message.",DEFAULT_ASK_USER_TIMEOUT_MS=1800*1e3,HEADER_MAX=12,SNAKE_CASE=/^[a-z][a-z0-9]*(_[a-z0-9]+)*$/,LIMITS={codex:{maxQuestions:3,minOptions:2,maxOptions:3,optionsRequired:!0},claude:{maxQuestions:4,minOptions:2,maxOptions:4,optionsRequired:!1}},AskUserSchemaError=class extends Error{constructor(message){super(message),this.name="AskUserSchemaError"}};function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function readWaitFlag(variant,args){let value=args[variant==="codex"?"wait_for_answer":"waitForAnswer"];if(typeof value!="boolean")throw new AskUserSchemaError(WAIT_FLAG_STEER_TEXT);return value}function parseOptions(raw,min,max,required,requireDescription){if(raw===void 0){if(required)throw new AskUserSchemaError(`options must contain ${min} to ${max} items`);return[]}if(!Array.isArray(raw))throw new AskUserSchemaError("options must be an array");if(raw.length<min||raw.length>max)throw new AskUserSchemaError(required?`options must contain ${min} to ${max} items`:`options must contain ${min} to ${max} items when present`);let options=[];for(let item of raw){if(!isRecord(item))throw new AskUserSchemaError("each option must be an object");let label=typeof item.label=="string"?item.label.trim():"";if(label.length===0)throw new AskUserSchemaError("option label must be non-empty");let description=typeof item.description=="string"?item.description.trim():void 0;if(requireDescription&&(description===void 0||description.length===0))throw new AskUserSchemaError("option description is required");options.push(description===void 0||description.length===0?{label}:{label,description})}return options}function parseQuestion(variant,raw,index){if(!isRecord(raw))throw new AskUserSchemaError("each question must be an object");let limits=LIMITS[variant],header=typeof raw.header=="string"?raw.header.trim():"";if(header.length===0)throw new AskUserSchemaError("header must be non-empty");if(header.length>HEADER_MAX)throw new AskUserSchemaError("header must be 12 or fewer characters");let question=typeof raw.question=="string"?raw.question.trim():"";if(question.length===0)throw new AskUserSchemaError("question must be non-empty");let options=parseOptions(raw.options,limits.minOptions,limits.maxOptions,limits.optionsRequired,variant==="codex"),id;if(variant==="claude")id=`q${index+1}`;else if(id=typeof raw.id=="string"?raw.id.trim():"",!SNAKE_CASE.test(id))throw new AskUserSchemaError("id must be snake_case");let multiSelect;if(variant==="claude"){if(typeof raw.multiSelect!="boolean")throw new AskUserSchemaError("multiSelect is required");multiSelect=raw.multiSelect}else multiSelect=raw.multiSelect===!0;return{id,header,question,options,multiSelect}}function toCanonical(variant,args,options){if(!isRecord(args))throw new AskUserSchemaError(WAIT_FLAG_STEER_TEXT);let waitForAnswer=readWaitFlag(variant,args);if(args.required!==void 0&&typeof args.required!="boolean")throw new AskUserSchemaError("required must be a boolean when present");let limits=LIMITS[variant];if(!Array.isArray(args.questions)||args.questions.length<1||args.questions.length>limits.maxQuestions)throw new AskUserSchemaError(`questions must contain 1 to ${limits.maxQuestions} items`);return{requestId:options?.requestId??crypto.randomUUID(),questions:args.questions.map((question,index)=>parseQuestion(variant,question,index)),waitForAnswer,timeoutMs:options?.timeoutMs??DEFAULT_ASK_USER_TIMEOUT_MS,...args.required===!0?{required:!0}:{}}}var INLINE_WORDS={comment:text=>text,typed:(_header,text)=>text},reference=label=>`(see [${label}] below)`;function separatedWords(requestId){let words=[],place=(base,text)=>{let taken=words.filter(word=>word.label===base||word.label.startsWith(`${base} (`)).length,label=taken===0?base:`${base} (${taken+1})`;return words.push({label,text}),reference(label)};return{words,comment:text=>place(`The user's comment for question ${requestId}`,text),typed:(header,text)=>place(`The user's answer to ${header} for question ${requestId}`,text)}}function resolveUserWordReferences(text,words){return words.reduce((resolved,word)=>resolved.split(reference(word.label)).join(word.text),text)}function readUserWordBlocks(content){let texts=content.flatMap(block=>block.type==="text"?[block.text]:[]);if(texts.length%2!==0)return;let words=[];for(let index=0;index<texts.length;index+=2){let label=/^\[(.+)\]$/s.exec(texts[index]??"")?.[1],text=texts[index+1];if(label===void 0||text===void 0)return;words.push({label,text})}return words}function headerFor(id,questions){return questions.find(question=>question.id===id)?.header??id}function questionTextFor(id,questions){return questions.find(question=>question.id===id)?.question??id}function typedText(answer){if(answer.selected.length>0)return;let text=answer.text?.trim();return text===void 0||text.length===0?void 0:text}function answerBody(answer,header,words=INLINE_WORDS,offered=[]){if(!answer)return;if(answer.selected.length>0)return answer.selected.join(", ");let text=typedText(answer);if(text!==void 0)return offered.some(option=>option.label===text)?text:words.typed(header,text)}function answeredLines(response,questions,words){let lines=[],seen=new Set;for(let question of questions){let body=answerBody(response.answers[question.id],question.header,words,question.options);body!==void 0&&(lines.push(`${question.header}: ${body}`),seen.add(question.id))}for(let[id,answer]of Object.entries(response.answers)){if(seen.has(id))continue;let header=headerFor(id,questions),body=answerBody(answer,header,words);body!==void 0&&lines.push(`${header}: ${body}`)}return lines}function unansweredLine(response,questions){let unanswered=response.unanswered.map(id=>headerFor(id,questions));return unanswered.length>0?[`Unanswered: ${unanswered.join(", ")}`]:[]}var CANCELLED_BY_USER="The user cancelled the question after answering part of it.",CANCELLED_AFTER_ANSWERS="The question was cancelled after part of it was answered.";function isCancelledWithAnswersLine(line){return line===CANCELLED_BY_USER||line===CANCELLED_AFTER_ANSWERS}function showsPartialAnswers(response){return response.status!=="cancelled"||response.cancelOrigin!=="user"&&response.cancelOrigin!=="ui_failure"?!1:Object.values(response.answers).some(answer=>answerBody(answer,"")!==void 0)}function selectedBlock(prefix,selected){return selected.length===1?[`${prefix} ${selected[0]}`]:[prefix,...selected]}var GATED_NO_ANSWER="No answer: do not take the action it gates. Keep that action pending and end the turn.";function formatGatedNoAnswer(response,questions,words,cancellationReason){let lines=[cancellationReason??(response.status==="timed_out"?`The user did not answer within ${Math.round((response.autoResolvedAfterMs??DEFAULT_ASK_USER_TIMEOUT_MS)/6e4)} minutes. (\uC0AC\uC6A9\uC790\uAC00 \uB2F5\uBCC0\uC744 \uC548\uD558\uACE0 timeout \uC73C\uB85C \uC885\uB8CC\uB428)`:response.status==="cancelled"?"The user dismissed the question.":response.status==="orphaned-after-restart"?"The pending question could not be resumed after a restart.":"This session has no user attached (subagent or headless).")],selected=answeredLines(response,questions,words);return selected.length>0&&lines.push(...selectedBlock("Before going idle the user had selected (not an answer):",selected)),lines.push(GATED_NO_ANSWER),lines.join(`
3
3
  `)}function formatGatedCancellation(reason,response,requestId,questions){return formatGatedNoAnswer(response,questions,separatedWords(requestId),reason)}function formatBody(response,questions,words,required=!1){if(required&&response.status!=="answered"&&response.status!=="comment-submitted")return formatGatedNoAnswer(response,questions,words);switch(response.status){case"answered":return[...answeredLines(response,questions,words),...unansweredLine(response,questions)].join(`
4
4
  `);case"comment-submitted":{let comment=response.comment?.trim()??"";return[`The user responded: ${comment.length>0?words.comment(comment):""}`,...answeredLines(response,questions,words),...unansweredLine(response,questions)].join(`
5
5
  `)}case"timed_out":{let lines=[`The user did not answer within ${Math.round((response.autoResolvedAfterMs??DEFAULT_ASK_USER_TIMEOUT_MS)/6e4)} minutes. (\uC0AC\uC6A9\uC790\uAC00 \uB2F5\uBCC0\uC744 \uC548\uD558\uACE0 timeout \uC73C\uB85C \uC885\uB8CC\uB428)`],selected=answeredLines(response,questions,words);return selected.length>0&&lines.push(...selectedBlock("Before going idle the user had selected:",selected),...unansweredLine(response,questions)),lines.push("Continue the work to completion on your best judgment; do not ask this question again this turn."),lines.join(`