@opengsd/gsd-pi 1.0.2-dev.5961fbf → 1.0.2-dev.5f7864c

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 (223) hide show
  1. package/README.md +63 -12
  2. package/dist/onboarding.js +22 -3
  3. package/dist/resource-loader.d.ts +2 -0
  4. package/dist/resource-loader.js +18 -1
  5. package/dist/resources/.managed-resources-content-hash +1 -1
  6. package/dist/resources/extensions/context7/index.js +12 -2
  7. package/dist/resources/extensions/get-secrets-from-user.js +16 -16
  8. package/dist/resources/extensions/google-cli/index.js +30 -0
  9. package/dist/resources/extensions/google-cli/models.js +55 -0
  10. package/dist/resources/extensions/google-cli/package.json +11 -0
  11. package/dist/resources/extensions/google-cli/readiness.js +12 -0
  12. package/dist/resources/extensions/google-cli/stream-adapter.js +191 -0
  13. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  14. package/dist/resources/extensions/gsd/auto-start.js +232 -49
  15. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +4 -3
  16. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +17 -15
  17. package/dist/resources/extensions/gsd/closeout-recovery.js +7 -1
  18. package/dist/resources/extensions/gsd/commands/handlers/auto.js +9 -1
  19. package/dist/resources/extensions/gsd/commands-handlers.js +3 -0
  20. package/dist/resources/extensions/gsd/commands-usage.js +105 -1
  21. package/dist/resources/extensions/gsd/config-overlay.js +20 -14
  22. package/dist/resources/extensions/gsd/context-overlay.js +22 -16
  23. package/dist/resources/extensions/gsd/dashboard-overlay.js +10 -23
  24. package/dist/resources/extensions/gsd/doctor-providers.js +54 -24
  25. package/dist/resources/extensions/gsd/git-conflict-state.js +26 -1
  26. package/dist/resources/extensions/gsd/guided-flow.js +1 -1
  27. package/dist/resources/extensions/gsd/key-manager.js +45 -13
  28. package/dist/resources/extensions/gsd/notification-overlay.js +8 -9
  29. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +15 -13
  30. package/dist/resources/extensions/gsd/prompt-loader.js +2 -0
  31. package/dist/resources/extensions/gsd/prompts/discuss.md +4 -2
  32. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  33. package/dist/resources/extensions/gsd/queue-reorder-ui.js +28 -18
  34. package/dist/resources/extensions/gsd/tools/complete-task.js +9 -0
  35. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +40 -1
  36. package/dist/resources/extensions/gsd/tui/render-kit.js +51 -0
  37. package/dist/resources/extensions/gsd/vision-ask.js +22 -0
  38. package/dist/resources/extensions/gsd/visualizer-overlay.js +8 -36
  39. package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -3
  40. package/dist/resources/extensions/search-the-web/native-search.js +57 -8
  41. package/dist/resources/extensions/shared/confirm-ui.js +9 -6
  42. package/dist/resources/extensions/shared/dialog-frame.js +42 -0
  43. package/dist/resources/extensions/shared/interview-ui.js +42 -30
  44. package/dist/resources/extensions/shared/next-action-ui.js +6 -6
  45. package/dist/resources/shared/package-manager-detection.js +36 -0
  46. package/dist/update-check.d.ts +6 -2
  47. package/dist/update-check.js +7 -3
  48. package/dist/web/standalone/.next/BUILD_ID +1 -1
  49. package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
  50. package/dist/web/standalone/.next/build-manifest.json +2 -2
  51. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  52. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  53. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  54. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  55. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  56. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  57. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  58. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  59. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  60. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  61. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  62. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  63. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  64. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  65. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  66. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  67. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  68. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  69. package/dist/web/standalone/.next/server/app/index.html +1 -1
  70. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  75. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  76. package/dist/web/standalone/.next/server/app-paths-manifest.json +6 -6
  77. package/dist/web/standalone/.next/server/chunks/1834.js +2 -2
  78. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  79. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  80. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  81. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  82. package/package.json +1 -1
  83. package/packages/cloud-mcp-gateway/package.json +2 -2
  84. package/packages/contracts/package.json +1 -1
  85. package/packages/daemon/package.json +4 -4
  86. package/packages/gsd-agent-core/package.json +5 -5
  87. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts +12 -0
  88. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts.map +1 -0
  89. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js +45 -0
  90. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js.map +1 -0
  91. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts +3 -2
  92. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  93. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js +11 -11
  94. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js.map +1 -1
  95. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts +3 -3
  96. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  97. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js +13 -11
  98. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js.map +1 -1
  99. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts +3 -3
  100. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  101. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js +12 -10
  102. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js.map +1 -1
  103. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts +1 -0
  104. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts.map +1 -1
  105. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js +1 -0
  106. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js.map +1 -1
  107. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts +1 -1
  108. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  109. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js +2 -2
  110. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js.map +1 -1
  111. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts +6 -1
  112. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  113. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js +9 -6
  114. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  115. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
  116. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +0 -1
  117. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
  118. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts +3 -0
  119. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
  120. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +144 -2
  121. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
  122. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.d.ts.map +1 -1
  123. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js +2 -14
  124. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js.map +1 -1
  125. package/packages/gsd-agent-modes/package.json +7 -7
  126. package/packages/mcp-server/dist/workflow-tools.js +1 -1
  127. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  128. package/packages/mcp-server/package.json +3 -3
  129. package/packages/native/package.json +1 -1
  130. package/packages/pi-agent-core/dist/agent-loop.js +13 -13
  131. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  132. package/packages/pi-agent-core/package.json +1 -1
  133. package/packages/pi-ai/dist/models.generated.d.ts +57 -17
  134. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  135. package/packages/pi-ai/dist/models.generated.js +64 -28
  136. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  137. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  138. package/packages/pi-ai/dist/providers/anthropic.js +50 -0
  139. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  140. package/packages/pi-ai/dist/types.d.ts +2 -0
  141. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  142. package/packages/pi-ai/dist/types.js.map +1 -1
  143. package/packages/pi-ai/package.json +1 -1
  144. package/packages/pi-coding-agent/package.json +7 -7
  145. package/packages/pi-tui/package.json +1 -1
  146. package/packages/rpc-client/package.json +2 -2
  147. package/pkg/package.json +1 -1
  148. package/scripts/install/detect-existing.js +17 -3
  149. package/scripts/install/npm-global.js +103 -33
  150. package/scripts/install.js +1 -0
  151. package/src/resources/extensions/context7/index.ts +15 -2
  152. package/src/resources/extensions/get-secrets-from-user.ts +17 -16
  153. package/src/resources/extensions/google-cli/index.ts +34 -0
  154. package/src/resources/extensions/google-cli/models.ts +57 -0
  155. package/src/resources/extensions/google-cli/package.json +11 -0
  156. package/src/resources/extensions/google-cli/readiness.ts +15 -0
  157. package/src/resources/extensions/google-cli/stream-adapter.ts +245 -0
  158. package/src/resources/extensions/gsd/auto/session.ts +3 -0
  159. package/src/resources/extensions/gsd/auto-start.ts +307 -56
  160. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +4 -3
  161. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +22 -15
  162. package/src/resources/extensions/gsd/closeout-recovery.ts +6 -1
  163. package/src/resources/extensions/gsd/commands/handlers/auto.ts +9 -1
  164. package/src/resources/extensions/gsd/commands-handlers.ts +2 -0
  165. package/src/resources/extensions/gsd/commands-usage.ts +110 -5
  166. package/src/resources/extensions/gsd/config-overlay.ts +19 -16
  167. package/src/resources/extensions/gsd/context-overlay.ts +24 -19
  168. package/src/resources/extensions/gsd/dashboard-overlay.ts +14 -27
  169. package/src/resources/extensions/gsd/doctor-providers.ts +55 -27
  170. package/src/resources/extensions/gsd/git-conflict-state.ts +25 -1
  171. package/src/resources/extensions/gsd/guided-flow.ts +1 -1
  172. package/src/resources/extensions/gsd/key-manager.ts +57 -14
  173. package/src/resources/extensions/gsd/notification-overlay.ts +12 -11
  174. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +16 -12
  175. package/src/resources/extensions/gsd/prompt-loader.ts +2 -0
  176. package/src/resources/extensions/gsd/prompts/discuss.md +4 -2
  177. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  178. package/src/resources/extensions/gsd/queue-reorder-ui.ts +29 -20
  179. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +436 -0
  180. package/src/resources/extensions/gsd/tests/closeout-recovery.test.ts +15 -0
  181. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +31 -0
  182. package/src/resources/extensions/gsd/tests/commands-context.test.ts +5 -3
  183. package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +15 -2
  184. package/src/resources/extensions/gsd/tests/commands-usage.test.ts +97 -0
  185. package/src/resources/extensions/gsd/tests/context-chart.test.ts +9 -0
  186. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +25 -0
  187. package/src/resources/extensions/gsd/tests/discuss-prompt.test.ts +4 -2
  188. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +105 -0
  189. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +6 -0
  190. package/src/resources/extensions/gsd/tests/key-manager.test.ts +23 -4
  191. package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +6 -1
  192. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +70 -10
  193. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +7 -1
  194. package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +46 -0
  195. package/src/resources/extensions/gsd/tests/show-config-command.test.ts +4 -0
  196. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +13 -2
  197. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +24 -1
  198. package/src/resources/extensions/gsd/tests/tui-border-assertions.ts +28 -0
  199. package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +14 -0
  200. package/src/resources/extensions/gsd/tests/vision-ask.test.ts +23 -0
  201. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -1
  202. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +60 -0
  203. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +54 -0
  204. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +16 -1
  205. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +28 -0
  206. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +45 -1
  207. package/src/resources/extensions/gsd/tools/complete-task.ts +9 -0
  208. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +56 -4
  209. package/src/resources/extensions/gsd/tui/render-kit.ts +82 -0
  210. package/src/resources/extensions/gsd/vision-ask.ts +28 -0
  211. package/src/resources/extensions/gsd/visualizer-overlay.ts +12 -40
  212. package/src/resources/extensions/gsd/worktree-lifecycle.ts +37 -2
  213. package/src/resources/extensions/search-the-web/native-search.ts +60 -8
  214. package/src/resources/extensions/shared/confirm-ui.ts +8 -12
  215. package/src/resources/extensions/shared/dialog-frame.ts +71 -0
  216. package/src/resources/extensions/shared/interview-ui.ts +43 -42
  217. package/src/resources/extensions/shared/next-action-ui.ts +6 -6
  218. package/src/resources/extensions/shared/tests/confirm-ui.test.ts +57 -0
  219. package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +163 -0
  220. package/src/resources/extensions/shared/tests/next-action-ui-hasui.test.ts +55 -0
  221. package/src/resources/shared/package-manager-detection.ts +39 -0
  222. /package/dist/web/standalone/.next/static/{spUYLkQXoHJyxYOMH9VQy → IjxvcC7sl_MHNKXsUZrAy}/_buildManifest.js +0 -0
  223. /package/dist/web/standalone/.next/static/{spUYLkQXoHJyxYOMH9VQy → IjxvcC7sl_MHNKXsUZrAy}/_ssgManifest.js +0 -0
@@ -0,0 +1,57 @@
1
+ const ZERO_COST = {
2
+ input: 0,
3
+ output: 0,
4
+ cacheRead: 0,
5
+ cacheWrite: 0,
6
+ };
7
+
8
+ export const GOOGLE_GEMINI_CLI_MODELS = [
9
+ {
10
+ id: "gemini-2.5-flash",
11
+ name: "Gemini 2.5 Flash",
12
+ reasoning: true,
13
+ input: ["text" as const],
14
+ cost: ZERO_COST,
15
+ contextWindow: 1_000_000,
16
+ maxTokens: 65_536,
17
+ },
18
+ {
19
+ id: "gemini-2.5-pro",
20
+ name: "Gemini 2.5 Pro",
21
+ reasoning: true,
22
+ input: ["text" as const],
23
+ cost: ZERO_COST,
24
+ contextWindow: 1_000_000,
25
+ maxTokens: 65_536,
26
+ },
27
+ {
28
+ id: "gemini-3-flash-preview",
29
+ name: "Gemini 3 Flash Preview",
30
+ reasoning: true,
31
+ input: ["text" as const],
32
+ cost: ZERO_COST,
33
+ contextWindow: 1_000_000,
34
+ maxTokens: 65_536,
35
+ },
36
+ {
37
+ id: "gemini-3.1-pro-preview",
38
+ name: "Gemini 3.1 Pro Preview",
39
+ reasoning: true,
40
+ input: ["text" as const],
41
+ cost: ZERO_COST,
42
+ contextWindow: 1_000_000,
43
+ maxTokens: 65_536,
44
+ },
45
+ ];
46
+
47
+ export const GOOGLE_ANTIGRAVITY_MODELS = [
48
+ {
49
+ id: "default",
50
+ name: "Antigravity Default",
51
+ reasoning: true,
52
+ input: ["text" as const],
53
+ cost: ZERO_COST,
54
+ contextWindow: 1_000_000,
55
+ maxTokens: 65_536,
56
+ },
57
+ ];
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "@gsd/google-cli",
3
+ "private": true,
4
+ "version": "1.0.0",
5
+ "type": "module",
6
+ "pi": {
7
+ "extensions": [
8
+ "./index.ts"
9
+ ]
10
+ }
11
+ }
@@ -0,0 +1,15 @@
1
+ import { spawnSync } from "node:child_process";
2
+
3
+ function isCommandInPath(command: string): boolean {
4
+ const resolver = process.platform === "win32" ? "where" : "which";
5
+ const result = spawnSync(resolver, [command], { stdio: "ignore" });
6
+ return result.status === 0;
7
+ }
8
+
9
+ export function isGeminiCliReady(): boolean {
10
+ return isCommandInPath("gemini");
11
+ }
12
+
13
+ export function isAntigravityCliReady(): boolean {
14
+ return isCommandInPath("agy");
15
+ }
@@ -0,0 +1,245 @@
1
+ import { spawn } from "node:child_process";
2
+ import type {
3
+ Api,
4
+ AssistantMessage,
5
+ AssistantMessageEventStream,
6
+ Context,
7
+ Message,
8
+ Model,
9
+ SimpleStreamOptions,
10
+ TextContent,
11
+ } from "@gsd/pi-ai";
12
+ import { createAssistantMessageEventStream } from "@gsd/pi-ai";
13
+
14
+ const ZERO_USAGE = {
15
+ input: 0,
16
+ output: 0,
17
+ cacheRead: 0,
18
+ cacheWrite: 0,
19
+ totalTokens: 0,
20
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
21
+ };
22
+
23
+ type GoogleCliProviderId = "google-gemini-cli" | "google-antigravity";
24
+
25
+ interface CliRunResult {
26
+ stdout: string;
27
+ stderr: string;
28
+ code: number | null;
29
+ signal: NodeJS.Signals | null;
30
+ }
31
+
32
+ function textBlocks(content: (TextContent | { type: string })[]): string {
33
+ return content
34
+ .map((block) => block.type === "text" ? (block as TextContent).text : `[${block.type} omitted]`)
35
+ .join("\n");
36
+ }
37
+
38
+ function messageToText(message: Message): string {
39
+ if (message.role === "user") {
40
+ const content = typeof message.content === "string" ? message.content : textBlocks(message.content);
41
+ return `User:\n${content}`;
42
+ }
43
+
44
+ if (message.role === "assistant") {
45
+ const text = message.content
46
+ .map((block) => {
47
+ if (block.type === "text") return block.text;
48
+ if (block.type === "thinking") return `[thinking omitted]`;
49
+ if (block.type === "toolCall") return `[tool call: ${block.name}]`;
50
+ if (block.type === "serverToolUse") return `[server tool: ${block.name}]`;
51
+ if (block.type === "webSearchResult") return `[web search result omitted]`;
52
+ return `[${(block as { type: string }).type} omitted]`;
53
+ })
54
+ .join("\n");
55
+ return `Assistant:\n${text}`;
56
+ }
57
+
58
+ return `Tool result (${message.toolName}):\n${textBlocks(message.content)}`;
59
+ }
60
+
61
+ export function buildGoogleCliPrompt(context: Context): string {
62
+ const parts: string[] = [];
63
+
64
+ if (context.systemPrompt?.trim()) {
65
+ parts.push(`System instructions:\n${context.systemPrompt.trim()}`);
66
+ }
67
+
68
+ if (context.messages.length > 0) {
69
+ parts.push(context.messages.map(messageToText).join("\n\n"));
70
+ }
71
+
72
+ if (context.tools?.length) {
73
+ const names = context.tools.map((tool) => tool.name).join(", ");
74
+ parts.push(
75
+ `Available local GSD tools were not forwarded to this external CLI bridge. ` +
76
+ `If you need to act, use the CLI's own tools or ask the user to switch to a provider with native tool-call support. ` +
77
+ `Requested GSD tools: ${names}`,
78
+ );
79
+ }
80
+
81
+ return parts.join("\n\n").trim();
82
+ }
83
+
84
+ function buildAssistantMessage(
85
+ model: Model<Api>,
86
+ text: string,
87
+ stopReason: AssistantMessage["stopReason"] = "stop",
88
+ errorMessage?: string,
89
+ ): AssistantMessage {
90
+ return {
91
+ role: "assistant",
92
+ content: text ? [{ type: "text", text }] : [],
93
+ api: model.api,
94
+ provider: model.provider,
95
+ model: model.id,
96
+ usage: { ...ZERO_USAGE, cost: { ...ZERO_USAGE.cost } },
97
+ stopReason,
98
+ ...(errorMessage ? { errorMessage } : {}),
99
+ timestamp: Date.now(),
100
+ };
101
+ }
102
+
103
+ function extractGeminiJsonResponse(raw: string): string {
104
+ const trimmed = raw.trim();
105
+ if (!trimmed) return "";
106
+
107
+ try {
108
+ const parsed = JSON.parse(trimmed) as Record<string, unknown>;
109
+ for (const key of ["response", "text", "content", "message"]) {
110
+ const value = parsed[key];
111
+ if (typeof value === "string") return value;
112
+ }
113
+ return JSON.stringify(parsed, null, 2);
114
+ } catch {
115
+ return trimmed;
116
+ }
117
+ }
118
+
119
+ function commandForProvider(provider: GoogleCliProviderId): string {
120
+ return provider === "google-gemini-cli" ? "gemini" : "agy";
121
+ }
122
+
123
+ function argsForProvider(provider: GoogleCliProviderId, model: Model<Api>, prompt: string): string[] {
124
+ if (provider === "google-gemini-cli") {
125
+ const args = ["-p", prompt, "--output-format", "json"];
126
+ if (model.id !== "default") args.unshift("-m", model.id);
127
+ return args;
128
+ }
129
+
130
+ const args = ["-p", prompt];
131
+ if (model.id !== "default") args.unshift("-m", model.id);
132
+ return args;
133
+ }
134
+
135
+ export function buildGoogleCliSpawnInvocation(
136
+ command: string,
137
+ args: string[],
138
+ platform: NodeJS.Platform = process.platform,
139
+ ): { command: string; args: string[] } {
140
+ if (platform === "win32") {
141
+ return { command: "cmd", args: ["/c", command, ...args] };
142
+ }
143
+ return { command, args };
144
+ }
145
+
146
+ function runCli(command: string, args: string[], options?: SimpleStreamOptions): Promise<CliRunResult> {
147
+ return new Promise((resolve, reject) => {
148
+ const invocation = buildGoogleCliSpawnInvocation(command, args);
149
+ const child = spawn(invocation.command, invocation.args, {
150
+ cwd: options?.cwd || process.cwd(),
151
+ env: process.env,
152
+ stdio: ["ignore", "pipe", "pipe"],
153
+ });
154
+
155
+ let stdout = "";
156
+ let stderr = "";
157
+ let settled = false;
158
+
159
+ const settle = (fn: () => void) => {
160
+ if (settled) return;
161
+ settled = true;
162
+ options?.signal?.removeEventListener("abort", onAbort);
163
+ fn();
164
+ };
165
+
166
+ const onAbort = () => {
167
+ child.kill("SIGTERM");
168
+ settle(() => reject(new Error("Request was aborted")));
169
+ };
170
+
171
+ if (options?.signal?.aborted) {
172
+ onAbort();
173
+ return;
174
+ }
175
+ options?.signal?.addEventListener("abort", onAbort);
176
+
177
+ child.stdout.setEncoding("utf8");
178
+ child.stderr.setEncoding("utf8");
179
+ child.stdout.on("data", (chunk) => {
180
+ stdout += chunk;
181
+ });
182
+ child.stderr.on("data", (chunk) => {
183
+ stderr += chunk;
184
+ });
185
+
186
+ child.on("error", (error) => {
187
+ settle(() => reject(error));
188
+ });
189
+
190
+ child.on("close", (code, signal) => {
191
+ settle(() => resolve({ stdout, stderr, code, signal }));
192
+ });
193
+ });
194
+ }
195
+
196
+ function emitText(stream: AssistantMessageEventStream, message: AssistantMessage, text: string): void {
197
+ stream.push({ type: "start", partial: { ...message, content: [] } });
198
+ if (text) {
199
+ stream.push({ type: "text_start", contentIndex: 0, partial: message });
200
+ stream.push({ type: "text_delta", contentIndex: 0, delta: text, partial: message });
201
+ stream.push({ type: "text_end", contentIndex: 0, content: text, partial: message });
202
+ }
203
+ stream.push({ type: "done", reason: "stop", message });
204
+ stream.end(message);
205
+ }
206
+
207
+ function emitError(stream: AssistantMessageEventStream, model: Model<Api>, error: unknown): void {
208
+ const message = error instanceof Error ? error.message : String(error);
209
+ const output = buildAssistantMessage(model, "", "error", message);
210
+ stream.push({ type: "error", reason: "error", error: output });
211
+ stream.end(output);
212
+ }
213
+
214
+ export function streamViaGoogleCli(
215
+ model: Model<Api>,
216
+ context: Context,
217
+ options?: SimpleStreamOptions,
218
+ ): AssistantMessageEventStream {
219
+ const stream = createAssistantMessageEventStream();
220
+ const provider = model.provider as GoogleCliProviderId;
221
+
222
+ queueMicrotask(async () => {
223
+ try {
224
+ const prompt = buildGoogleCliPrompt(context);
225
+ const command = commandForProvider(provider);
226
+ const args = argsForProvider(provider, model, prompt);
227
+ const result = await runCli(command, args, options);
228
+
229
+ if (result.code !== 0) {
230
+ const detail = (result.stderr || result.stdout || `CLI exited with code ${result.code}`).trim();
231
+ throw new Error(detail);
232
+ }
233
+
234
+ const text = provider === "google-gemini-cli"
235
+ ? extractGeminiJsonResponse(result.stdout)
236
+ : result.stdout.trim();
237
+ const message = buildAssistantMessage(model, text);
238
+ emitText(stream, message, text);
239
+ } catch (error) {
240
+ emitError(stream, model, error);
241
+ }
242
+ });
243
+
244
+ return stream;
245
+ }
@@ -218,6 +218,8 @@ export class AutoSession {
218
218
  // ── Isolation degradation ────────────────────────────────────────────
219
219
  /** Set to true when worktree creation fails; prevents merge of nonexistent branch. */
220
220
  isolationDegraded = false;
221
+ /** Temporary recovery mode for stranded work adopted from physical git evidence. */
222
+ strandedRecoveryIsolationMode: "worktree" | "branch" | null = null;
221
223
  /** Project-root dirty snapshot captured before an isolated worktree unit runs. */
222
224
  rootWriteBaseline: RootDirtySnapshot | null = null;
223
225
 
@@ -382,6 +384,7 @@ export class AutoSession {
382
384
  this.lastGitActionFailure = null;
383
385
  this.lastGitActionStatus = null;
384
386
  this.isolationDegraded = false;
387
+ this.strandedRecoveryIsolationMode = null;
385
388
  this.rootWriteBaseline = null;
386
389
  this.milestoneMergedInPhases = false;
387
390
  this.milestoneStartShas = new Map();