gsd-pi 2.53.0 → 2.54.0-dev.16631ca

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 (200) hide show
  1. package/dist/cli.js +19 -19
  2. package/dist/headless-ui.d.ts +29 -3
  3. package/dist/headless-ui.js +221 -28
  4. package/dist/headless.d.ts +11 -0
  5. package/dist/headless.js +238 -41
  6. package/dist/resources/extensions/bg-shell/bg-shell-lifecycle.js +2 -2
  7. package/dist/resources/extensions/bg-shell/utilities.js +34 -5
  8. package/dist/resources/extensions/gsd/auto/phases.js +10 -1
  9. package/dist/resources/extensions/gsd/auto-dispatch.js +1 -1
  10. package/dist/resources/extensions/gsd/auto-model-selection.js +17 -1
  11. package/dist/resources/extensions/gsd/auto-prompts.js +9 -0
  12. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +18 -5
  13. package/dist/web/standalone/.next/BUILD_ID +1 -1
  14. package/dist/web/standalone/.next/app-path-routes-manifest.json +19 -19
  15. package/dist/web/standalone/.next/build-manifest.json +4 -4
  16. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  17. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  18. package/dist/web/standalone/.next/required-server-files.json +4 -4
  19. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  20. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  21. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  22. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  23. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  24. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  25. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  26. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  27. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  28. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  29. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  30. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  31. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  32. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  33. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  34. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  35. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  36. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  37. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  38. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  39. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  40. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  41. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  42. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  43. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  44. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  45. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  46. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  47. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  48. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  49. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  50. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  51. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  52. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  53. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  54. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  55. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  56. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  57. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  58. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  59. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  60. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  61. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  62. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  63. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  64. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  65. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  66. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  67. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  68. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  69. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  70. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  71. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  72. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  73. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  74. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  75. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  76. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  77. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  78. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  79. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  80. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  82. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  83. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  84. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  85. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  86. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  87. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  88. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  90. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  92. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  93. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  94. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  96. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  106. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  108. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  110. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  112. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/index.html +1 -1
  122. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  123. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  124. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  125. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  127. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/page.js +2 -2
  129. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app-paths-manifest.json +19 -19
  131. package/dist/web/standalone/.next/server/chunks/2229.js +2 -2
  132. package/dist/web/standalone/.next/server/chunks/7471.js +3 -3
  133. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/middleware.js +2 -2
  136. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  138. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  139. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  140. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  141. package/dist/web/standalone/.next/static/chunks/4024.82f2e2a838908338.js +9 -0
  142. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  143. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  144. package/dist/web/standalone/.next/static/chunks/app/page-b950e4e384cc62b3.js +1 -0
  145. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  146. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  147. package/dist/web/standalone/.next/static/chunks/{webpack-bca0e732db0dcec3.js → webpack-70adf6e3be5479ce.js} +1 -1
  148. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  149. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  150. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  151. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  152. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  153. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  154. package/dist/web/standalone/server.js +1 -1
  155. package/package.json +1 -1
  156. package/packages/mcp-server/README.md +6 -6
  157. package/packages/mcp-server/package.json +14 -4
  158. package/packages/mcp-server/src/cli.ts +1 -1
  159. package/packages/mcp-server/src/index.ts +1 -1
  160. package/packages/mcp-server/src/mcp-server.test.ts +2 -2
  161. package/packages/mcp-server/src/session-manager.ts +2 -2
  162. package/packages/mcp-server/src/types.ts +1 -1
  163. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +1 -1
  164. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  165. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  166. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts +2 -0
  167. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
  168. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +14 -2
  169. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
  170. package/packages/pi-coding-agent/package.json +1 -1
  171. package/packages/pi-coding-agent/src/core/model-registry.ts +1 -1
  172. package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +16 -2
  173. package/packages/rpc-client/README.md +125 -0
  174. package/packages/rpc-client/examples/basic-usage.ts +13 -0
  175. package/packages/rpc-client/package.json +17 -3
  176. package/packages/rpc-client/src/index.ts +10 -0
  177. package/packages/rpc-client/src/jsonl.ts +64 -0
  178. package/packages/rpc-client/src/rpc-client.test.ts +568 -0
  179. package/packages/rpc-client/src/rpc-client.ts +666 -0
  180. package/packages/rpc-client/src/rpc-types.ts +399 -0
  181. package/packages/rpc-client/tsconfig.examples.json +17 -0
  182. package/packages/rpc-client/tsconfig.json +24 -0
  183. package/pkg/package.json +1 -1
  184. package/src/resources/extensions/bg-shell/bg-shell-lifecycle.ts +2 -2
  185. package/src/resources/extensions/bg-shell/utilities.ts +39 -4
  186. package/src/resources/extensions/gsd/auto/phases.ts +14 -2
  187. package/src/resources/extensions/gsd/auto-dispatch.ts +1 -1
  188. package/src/resources/extensions/gsd/auto-model-selection.ts +21 -1
  189. package/src/resources/extensions/gsd/auto-prompts.ts +15 -0
  190. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +19 -6
  191. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +139 -0
  192. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +55 -0
  193. package/src/resources/extensions/gsd/tests/plan-milestone-queue-context.test.ts +48 -0
  194. package/src/resources/extensions/gsd/tests/register-extension-guard.test.ts +59 -0
  195. package/dist/web/standalone/.next/static/chunks/4024.87fd909ae0110f50.js +0 -9
  196. package/dist/web/standalone/.next/static/chunks/app/page-fbecd1237e2d6d1f.js +0 -1
  197. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  198. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  199. /package/dist/web/standalone/.next/static/{mWBOLPnUoeaTGiD-vhu5O → 8yiPxQ52ue_s6qdrrAxsH}/_buildManifest.js +0 -0
  200. /package/dist/web/standalone/.next/static/{mWBOLPnUoeaTGiD-vhu5O → 8yiPxQ52ue_s6qdrrAxsH}/_ssgManifest.js +0 -0
package/dist/cli.js CHANGED
@@ -103,19 +103,6 @@ const cliFlags = parseCliArgs(process.argv);
103
103
  const isPrintMode = cliFlags.print || cliFlags.mode !== undefined;
104
104
  // Early resource-skew check — must run before TTY gate so version mismatch
105
105
  // errors surface even in non-TTY environments.
106
- exitIfManagedResourcesAreNewer(agentDir);
107
- // Early TTY check — must come before heavy initialization to avoid dangling
108
- // handles that prevent process.exit() from completing promptly.
109
- const hasSubcommand = cliFlags.messages.length > 0;
110
- if (!process.stdin.isTTY && !isPrintMode && !hasSubcommand && !cliFlags.listModels && !cliFlags.web) {
111
- process.stderr.write('[gsd] Error: Interactive mode requires a terminal (TTY).\n');
112
- process.stderr.write('[gsd] Non-interactive alternatives:\n');
113
- process.stderr.write('[gsd] gsd --print "your message" Single-shot prompt\n');
114
- process.stderr.write('[gsd] gsd --mode rpc JSON-RPC over stdin/stdout\n');
115
- process.stderr.write('[gsd] gsd --mode mcp MCP server over stdin/stdout\n');
116
- process.stderr.write('[gsd] gsd --mode text "message" Text output mode\n');
117
- process.exit(1);
118
- }
119
106
  async function ensureRtkBootstrap() {
120
107
  if (ensureRtkBootstrap._done)
121
108
  return;
@@ -136,6 +123,25 @@ async function ensureRtkBootstrap() {
136
123
  process.stderr.write(`[gsd] Warning: RTK unavailable — continuing without shell-command compression (${rtkStatus.reason}).\n`);
137
124
  }
138
125
  }
126
+ // `gsd update` — update to the latest version via npm
127
+ if (cliFlags.messages[0] === 'update') {
128
+ const { runUpdate } = await import('./update-cmd.js');
129
+ await runUpdate();
130
+ process.exit(0);
131
+ }
132
+ exitIfManagedResourcesAreNewer(agentDir);
133
+ // Early TTY check — must come before heavy initialization to avoid dangling
134
+ // handles that prevent process.exit() from completing promptly.
135
+ const hasSubcommand = cliFlags.messages.length > 0;
136
+ if (!process.stdin.isTTY && !isPrintMode && !hasSubcommand && !cliFlags.listModels && !cliFlags.web) {
137
+ process.stderr.write('[gsd] Error: Interactive mode requires a terminal (TTY).\n');
138
+ process.stderr.write('[gsd] Non-interactive alternatives:\n');
139
+ process.stderr.write('[gsd] gsd --print "your message" Single-shot prompt\n');
140
+ process.stderr.write('[gsd] gsd --mode rpc JSON-RPC over stdin/stdout\n');
141
+ process.stderr.write('[gsd] gsd --mode mcp MCP server over stdin/stdout\n');
142
+ process.stderr.write('[gsd] gsd --mode text "message" Text output mode\n');
143
+ process.exit(1);
144
+ }
139
145
  // `gsd <subcommand> --help` — show subcommand-specific help
140
146
  const subcommand = cliFlags.messages[0];
141
147
  if (subcommand && process.argv.includes('--help')) {
@@ -162,12 +168,6 @@ if (cliFlags.messages[0] === 'config') {
162
168
  await runOnboarding(authStorage);
163
169
  process.exit(0);
164
170
  }
165
- // `gsd update` — update to the latest version via npm
166
- if (cliFlags.messages[0] === 'update') {
167
- const { runUpdate } = await import('./update-cmd.js');
168
- await runUpdate();
169
- process.exit(0);
170
- }
171
171
  // `gsd web stop [path|all]` — stop web server before anything else
172
172
  if (cliFlags.messages[0] === 'web' && cliFlags.messages[1] === 'stop') {
173
173
  const webFlags = parseWebCliArgs(process.argv);
@@ -18,6 +18,32 @@ interface ExtensionUIRequest {
18
18
  [key: string]: unknown;
19
19
  }
20
20
  export type { ExtensionUIRequest };
21
- export declare function handleExtensionUIRequest(event: ExtensionUIRequest, writeToStdin: (data: string) => void): void;
22
- export declare function formatProgress(event: Record<string, unknown>, verbose: boolean): string | null;
23
- export declare function startSupervisedStdinReader(stdinWriter: (data: string) => void, client: RpcClient, onResponse: (id: string) => void): () => void;
21
+ /** Context passed alongside an event for richer formatting. */
22
+ export interface ProgressContext {
23
+ verbose: boolean;
24
+ toolDuration?: number;
25
+ lastCost?: {
26
+ costUsd: number;
27
+ inputTokens: number;
28
+ outputTokens: number;
29
+ };
30
+ thinkingPreview?: string;
31
+ isError?: boolean;
32
+ }
33
+ /**
34
+ * Produce a short human-readable summary of tool arguments.
35
+ * Returns a string like "path/to/file.ts" or "grep pattern *.ts" — never the
36
+ * full JSON blob.
37
+ */
38
+ export declare function summarizeToolArgs(toolName: unknown, toolInput: unknown): string;
39
+ export declare function handleExtensionUIRequest(event: ExtensionUIRequest, client: RpcClient): void;
40
+ export declare function formatProgress(event: Record<string, unknown>, ctx: ProgressContext): string | null;
41
+ /**
42
+ * Format a thinking preview line from accumulated LLM text deltas.
43
+ */
44
+ export declare function formatThinkingLine(text: string): string;
45
+ /**
46
+ * Format a cost line (used for periodic cost updates in verbose mode).
47
+ */
48
+ export declare function formatCostLine(costUsd: number, inputTokens: number, outputTokens: number): string;
49
+ export declare function startSupervisedStdinReader(client: RpcClient, onResponse: (id: string) => void): () => void;
@@ -5,13 +5,107 @@
5
5
  * formats progress events for stderr output, and reads orchestrator
6
6
  * commands from stdin in supervised mode.
7
7
  */
8
- import { attachJsonlLineReader, serializeJsonLine } from '@gsd/pi-coding-agent';
8
+ import { attachJsonlLineReader } from '@gsd/pi-coding-agent';
9
+ // ---------------------------------------------------------------------------
10
+ // ANSI Color Helpers
11
+ // ---------------------------------------------------------------------------
12
+ const _c = {
13
+ reset: '\x1b[0m',
14
+ bold: '\x1b[1m',
15
+ dim: '\x1b[2m',
16
+ italic: '\x1b[3m',
17
+ red: '\x1b[31m',
18
+ green: '\x1b[32m',
19
+ yellow: '\x1b[33m',
20
+ cyan: '\x1b[36m',
21
+ gray: '\x1b[90m',
22
+ };
23
+ /** Build a no-op color map (all codes empty). */
24
+ function noColor() {
25
+ const nc = {};
26
+ for (const k of Object.keys(_c))
27
+ nc[k] = '';
28
+ return nc;
29
+ }
30
+ const colorsDisabled = !!process.env['NO_COLOR'] || !process.stderr.isTTY;
31
+ const c = colorsDisabled ? noColor() : _c;
32
+ // ---------------------------------------------------------------------------
33
+ // Tool-Arg Summarizer
34
+ // ---------------------------------------------------------------------------
35
+ /**
36
+ * Produce a short human-readable summary of tool arguments.
37
+ * Returns a string like "path/to/file.ts" or "grep pattern *.ts" — never the
38
+ * full JSON blob.
39
+ */
40
+ export function summarizeToolArgs(toolName, toolInput) {
41
+ const name = String(toolName ?? '');
42
+ const input = (toolInput && typeof toolInput === 'object') ? toolInput : {};
43
+ switch (name) {
44
+ case 'Read':
45
+ case 'read':
46
+ return shortPath(input.file_path) || '';
47
+ case 'Write':
48
+ case 'write':
49
+ return shortPath(input.file_path) || '';
50
+ case 'Edit':
51
+ case 'edit':
52
+ return shortPath(input.file_path) || '';
53
+ case 'Bash':
54
+ case 'bash': {
55
+ const cmd = String(input.command ?? '');
56
+ return cmd.length > 80 ? cmd.slice(0, 77) + '...' : cmd;
57
+ }
58
+ case 'Glob':
59
+ case 'glob':
60
+ return String(input.pattern ?? '');
61
+ case 'Grep':
62
+ case 'grep':
63
+ case 'Search':
64
+ case 'search': {
65
+ const pat = String(input.pattern ?? '');
66
+ const g = input.glob ? ` ${input.glob}` : '';
67
+ return `${pat}${g}`;
68
+ }
69
+ case 'Task':
70
+ case 'task': {
71
+ const desc = String(input.description ?? input.prompt ?? '');
72
+ return desc.length > 60 ? desc.slice(0, 57) + '...' : desc;
73
+ }
74
+ default: {
75
+ // Fallback: show first string-valued key up to 60 chars
76
+ for (const v of Object.values(input)) {
77
+ if (typeof v === 'string' && v.length > 0) {
78
+ return v.length > 60 ? v.slice(0, 57) + '...' : v;
79
+ }
80
+ }
81
+ return '';
82
+ }
83
+ }
84
+ }
85
+ function shortPath(p) {
86
+ if (typeof p !== 'string')
87
+ return '';
88
+ // Strip common CWD prefix to save space
89
+ const cwd = process.cwd();
90
+ if (p.startsWith(cwd + '/'))
91
+ return p.slice(cwd.length + 1);
92
+ // Strip /Users/*/Developer/ prefix
93
+ return p.replace(/^\/Users\/[^/]+\/Developer\//, '');
94
+ }
95
+ // ---------------------------------------------------------------------------
96
+ // Format Duration
97
+ // ---------------------------------------------------------------------------
98
+ function formatDuration(ms) {
99
+ if (ms < 1000)
100
+ return `${ms}ms`;
101
+ const s = (ms / 1000).toFixed(1);
102
+ return `${s}s`;
103
+ }
9
104
  // ---------------------------------------------------------------------------
10
105
  // Extension UI Auto-Responder
11
106
  // ---------------------------------------------------------------------------
12
- export function handleExtensionUIRequest(event, writeToStdin) {
107
+ export function handleExtensionUIRequest(event, client) {
13
108
  const { id, method } = event;
14
- let response;
15
109
  switch (method) {
16
110
  case 'select': {
17
111
  // Lock-guard prompts list "View status" first, but headless needs "Force start"
@@ -23,62 +117,156 @@ export function handleExtensionUIRequest(event, writeToStdin) {
23
117
  if (forceOption)
24
118
  selected = forceOption;
25
119
  }
26
- response = { type: 'extension_ui_response', id, value: selected };
120
+ client.sendUIResponse(id, { value: selected });
27
121
  break;
28
122
  }
29
123
  case 'confirm':
30
- response = { type: 'extension_ui_response', id, confirmed: true };
124
+ client.sendUIResponse(id, { confirmed: true });
31
125
  break;
32
126
  case 'input':
33
- response = { type: 'extension_ui_response', id, value: '' };
127
+ client.sendUIResponse(id, { value: '' });
34
128
  break;
35
129
  case 'editor':
36
- response = { type: 'extension_ui_response', id, value: event.prefill ?? '' };
130
+ client.sendUIResponse(id, { value: event.prefill ?? '' });
37
131
  break;
38
132
  case 'notify':
39
133
  case 'setStatus':
40
134
  case 'setWidget':
41
135
  case 'setTitle':
42
136
  case 'set_editor_text':
43
- response = { type: 'extension_ui_response', id, value: '' };
137
+ client.sendUIResponse(id, { value: '' });
44
138
  break;
45
139
  default:
46
140
  process.stderr.write(`[headless] Warning: unknown extension_ui_request method "${method}", cancelling\n`);
47
- response = { type: 'extension_ui_response', id, cancelled: true };
141
+ client.sendUIResponse(id, { cancelled: true });
48
142
  break;
49
143
  }
50
- writeToStdin(serializeJsonLine(response));
51
144
  }
52
145
  // ---------------------------------------------------------------------------
53
146
  // Progress Formatter
54
147
  // ---------------------------------------------------------------------------
55
- export function formatProgress(event, verbose) {
148
+ export function formatProgress(event, ctx) {
56
149
  const type = String(event.type ?? '');
150
+ // Emit accumulated thinking preview before tool calls
151
+ if (ctx.thinkingPreview) {
152
+ // thinkingPreview is handled by the caller in headless.ts — it prepends
153
+ // the thinking line before the current event's line. We return the thinking
154
+ // line as a prefix joined with newline.
155
+ }
57
156
  switch (type) {
58
- case 'tool_execution_start':
59
- if (verbose)
60
- return ` [tool] ${event.toolName ?? 'unknown'}`;
61
- return null;
157
+ case 'tool_execution_start': {
158
+ if (!ctx.verbose)
159
+ return null;
160
+ const name = String(event.toolName ?? 'unknown');
161
+ const args = summarizeToolArgs(event.toolName, event.args);
162
+ const argStr = args ? ` ${c.dim}${args}${c.reset}` : '';
163
+ return ` ${c.dim}[tool]${c.reset} ${name}${argStr}`;
164
+ }
165
+ case 'tool_execution_end': {
166
+ if (!ctx.verbose)
167
+ return null;
168
+ const name = String(event.toolName ?? 'unknown');
169
+ const durationStr = ctx.toolDuration != null ? ` ${c.dim}${formatDuration(ctx.toolDuration)}${c.reset}` : '';
170
+ if (ctx.isError) {
171
+ return ` ${c.red}[tool] ${name} error${c.reset}${durationStr}`;
172
+ }
173
+ return ` ${c.dim}[tool] ${name} done${c.reset}${durationStr}`;
174
+ }
62
175
  case 'agent_start':
63
- return '[agent] Session started';
64
- case 'agent_end':
65
- return '[agent] Session ended';
66
- case 'extension_ui_request':
67
- if (event.method === 'notify') {
68
- return `[gsd] ${event.message ?? ''}`;
176
+ return `${c.dim}[agent] Session started${c.reset}`;
177
+ case 'agent_end': {
178
+ let line = `${c.dim}[agent] Session ended${c.reset}`;
179
+ if (ctx.lastCost) {
180
+ const cost = `$${ctx.lastCost.costUsd.toFixed(4)}`;
181
+ const tokens = `${ctx.lastCost.inputTokens + ctx.lastCost.outputTokens} tokens`;
182
+ line += ` ${c.dim}(${cost}, ${tokens})${c.reset}`;
183
+ }
184
+ return line;
185
+ }
186
+ case 'extension_ui_request': {
187
+ const method = String(event.method ?? '');
188
+ if (method === 'notify') {
189
+ const msg = String(event.message ?? '');
190
+ if (!msg)
191
+ return null;
192
+ // Bold important notifications
193
+ const isImportant = /^(committed:|verification gate:|milestone|blocked:)/i.test(msg);
194
+ return isImportant
195
+ ? `${c.bold}[gsd] ${msg}${c.reset}`
196
+ : `[gsd] ${msg}`;
69
197
  }
70
- if (event.method === 'setStatus') {
71
- return `[status] ${event.message ?? ''}`;
198
+ if (method === 'setStatus') {
199
+ // Parse statusKey for phase transitions
200
+ const statusKey = String(event.statusKey ?? '');
201
+ const msg = String(event.message ?? '');
202
+ if (!statusKey && !msg)
203
+ return null; // suppress empty status lines
204
+ // Show meaningful phase transitions
205
+ if (statusKey) {
206
+ const label = parsePhaseLabel(statusKey, msg);
207
+ if (label)
208
+ return `${c.cyan}[phase] ${label}${c.reset}`;
209
+ }
210
+ // Fallback: show message if non-empty
211
+ if (msg)
212
+ return `${c.cyan}[phase] ${msg}${c.reset}`;
213
+ return null;
72
214
  }
73
215
  return null;
216
+ }
74
217
  default:
75
218
  return null;
76
219
  }
77
220
  }
221
+ /**
222
+ * Format a thinking preview line from accumulated LLM text deltas.
223
+ */
224
+ export function formatThinkingLine(text) {
225
+ const trimmed = text.replace(/\s+/g, ' ').trim();
226
+ const truncated = trimmed.length > 120 ? trimmed.slice(0, 117) + '...' : trimmed;
227
+ return `${c.dim}${c.italic}[thinking] ${truncated}${c.reset}`;
228
+ }
229
+ /**
230
+ * Format a cost line (used for periodic cost updates in verbose mode).
231
+ */
232
+ export function formatCostLine(costUsd, inputTokens, outputTokens) {
233
+ return `${c.dim}[cost] $${costUsd.toFixed(4)} (${inputTokens + outputTokens} tokens)${c.reset}`;
234
+ }
235
+ // ---------------------------------------------------------------------------
236
+ // Phase Label Parser
237
+ // ---------------------------------------------------------------------------
238
+ /**
239
+ * Parse a statusKey into a human-readable phase label.
240
+ * statusKey format varies but common patterns:
241
+ * "milestone:M1", "slice:S1.1", "task:T1.1.1", "phase:discuss", etc.
242
+ */
243
+ function parsePhaseLabel(statusKey, message) {
244
+ // Direct phase/milestone/slice/task keys
245
+ const parts = statusKey.split(':');
246
+ if (parts.length >= 2) {
247
+ const [kind, value] = parts;
248
+ switch (kind.toLowerCase()) {
249
+ case 'milestone':
250
+ return `Milestone ${value}${message ? ' -- ' + message : ''}`;
251
+ case 'slice':
252
+ return `Slice ${value}${message ? ' -- ' + message : ''}`;
253
+ case 'task':
254
+ return `Task ${value}${message ? ' -- ' + message : ''}`;
255
+ case 'phase':
256
+ return `Phase: ${value}${message ? ' -- ' + message : ''}`;
257
+ default:
258
+ return `${kind}: ${value}${message ? ' -- ' + message : ''}`;
259
+ }
260
+ }
261
+ // Single-word status keys with a message
262
+ if (message)
263
+ return `${statusKey}: ${message}`;
264
+ return statusKey || null;
265
+ }
78
266
  // ---------------------------------------------------------------------------
79
267
  // Supervised Stdin Reader
80
268
  // ---------------------------------------------------------------------------
81
- export function startSupervisedStdinReader(stdinWriter, client, onResponse) {
269
+ export function startSupervisedStdinReader(client, onResponse) {
82
270
  return attachJsonlLineReader(process.stdin, (line) => {
83
271
  let msg;
84
272
  try {
@@ -90,12 +278,17 @@ export function startSupervisedStdinReader(stdinWriter, client, onResponse) {
90
278
  }
91
279
  const type = String(msg.type ?? '');
92
280
  switch (type) {
93
- case 'extension_ui_response':
94
- stdinWriter(line + '\n');
95
- if (typeof msg.id === 'string') {
96
- onResponse(msg.id);
281
+ case 'extension_ui_response': {
282
+ const id = String(msg.id ?? '');
283
+ const value = msg.value !== undefined ? String(msg.value) : undefined;
284
+ const confirmed = typeof msg.confirmed === 'boolean' ? msg.confirmed : undefined;
285
+ const cancelled = typeof msg.cancelled === 'boolean' ? msg.cancelled : undefined;
286
+ client.sendUIResponse(id, { value, confirmed, cancelled });
287
+ if (id) {
288
+ onResponse(id);
97
289
  }
98
290
  break;
291
+ }
99
292
  case 'prompt':
100
293
  client.prompt(String(msg.message ?? ''));
101
294
  break;
@@ -11,6 +11,7 @@
11
11
  * 10 — blocked (command reported a blocker)
12
12
  * 11 — cancelled (SIGINT/SIGTERM received)
13
13
  */
14
+ import type { SessionInfo } from '@gsd/pi-coding-agent';
14
15
  import type { OutputFormat } from './headless-types.js';
15
16
  export interface HeadlessOptions {
16
17
  timeout: number;
@@ -31,5 +32,15 @@ export interface HeadlessOptions {
31
32
  resumeSession?: string;
32
33
  bare?: boolean;
33
34
  }
35
+ export interface ResumeSessionResult {
36
+ session?: SessionInfo;
37
+ error?: string;
38
+ }
39
+ /**
40
+ * Resolve a session prefix to a single session.
41
+ * Exact id match is preferred over prefix match.
42
+ * Returns `{ session }` on unique match or `{ error }` on 0/ambiguous matches.
43
+ */
44
+ export declare function resolveResumeSession(sessions: SessionInfo[], prefix: string): ResumeSessionResult;
34
45
  export declare function parseHeadlessArgs(argv: string[]): HeadlessOptions;
35
46
  export declare function runHeadless(options: HeadlessOptions): Promise<void>;