ds-harness-remote 0.4.26 → 0.5.0

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/README.md +6 -6
  2. package/dist/acp/adapter.d.ts +19 -0
  3. package/dist/acp/adapter.d.ts.map +1 -0
  4. package/dist/acp/adapter.js +14 -0
  5. package/dist/acp/adapter.js.map +1 -0
  6. package/dist/acp/adapters/antigravity/executor.d.ts +20 -0
  7. package/dist/acp/adapters/antigravity/executor.d.ts.map +1 -0
  8. package/dist/acp/adapters/antigravity/executor.js +99 -0
  9. package/dist/acp/adapters/antigravity/executor.js.map +1 -0
  10. package/dist/acp/adapters/antigravity/image-store.d.ts +9 -0
  11. package/dist/acp/adapters/antigravity/image-store.d.ts.map +1 -0
  12. package/dist/acp/adapters/antigravity/image-store.js +116 -0
  13. package/dist/acp/adapters/antigravity/image-store.js.map +1 -0
  14. package/dist/acp/adapters/antigravity/index.d.ts +5 -0
  15. package/dist/acp/adapters/antigravity/index.d.ts.map +1 -0
  16. package/dist/acp/adapters/antigravity/index.js +5 -0
  17. package/dist/acp/adapters/antigravity/index.js.map +1 -0
  18. package/dist/acp/adapters/antigravity/models.d.ts +35 -0
  19. package/dist/acp/adapters/antigravity/models.d.ts.map +1 -0
  20. package/dist/acp/adapters/antigravity/models.js +59 -0
  21. package/dist/acp/adapters/antigravity/models.js.map +1 -0
  22. package/dist/acp/adapters/antigravity/service.d.ts +35 -0
  23. package/dist/acp/adapters/antigravity/service.d.ts.map +1 -0
  24. package/dist/acp/adapters/antigravity/service.js +67 -0
  25. package/dist/acp/adapters/antigravity/service.js.map +1 -0
  26. package/dist/acp/adapters/antigravity/transcript-loader.d.ts +21 -0
  27. package/dist/acp/adapters/antigravity/transcript-loader.d.ts.map +1 -0
  28. package/dist/acp/adapters/antigravity/transcript-loader.js +356 -0
  29. package/dist/acp/adapters/antigravity/transcript-loader.js.map +1 -0
  30. package/dist/acp/adapters/antigravity/transcript-watcher.d.ts +28 -0
  31. package/dist/acp/adapters/antigravity/transcript-watcher.d.ts.map +1 -0
  32. package/dist/acp/adapters/antigravity/transcript-watcher.js +157 -0
  33. package/dist/acp/adapters/antigravity/transcript-watcher.js.map +1 -0
  34. package/dist/acp/adapters/antigravity/types.d.ts +56 -0
  35. package/dist/acp/adapters/antigravity/types.d.ts.map +1 -0
  36. package/dist/acp/adapters/antigravity/types.js +2 -0
  37. package/dist/acp/adapters/antigravity/types.js.map +1 -0
  38. package/dist/acp/adapters/antigravity-process.d.ts +69 -0
  39. package/dist/acp/adapters/antigravity-process.d.ts.map +1 -0
  40. package/dist/acp/adapters/antigravity-process.js +566 -0
  41. package/dist/acp/adapters/antigravity-process.js.map +1 -0
  42. package/dist/acp/adapters/antigravity.d.ts +8 -0
  43. package/dist/acp/adapters/antigravity.d.ts.map +1 -0
  44. package/dist/acp/adapters/antigravity.js +9 -0
  45. package/dist/acp/adapters/antigravity.js.map +1 -0
  46. package/dist/acp/adapters/cursor-process.d.ts +75 -0
  47. package/dist/acp/adapters/cursor-process.d.ts.map +1 -0
  48. package/dist/acp/adapters/cursor-process.js +273 -0
  49. package/dist/acp/adapters/cursor-process.js.map +1 -0
  50. package/dist/acp/adapters/cursor.d.ts +8 -0
  51. package/dist/acp/adapters/cursor.d.ts.map +1 -0
  52. package/dist/acp/adapters/cursor.js +8 -0
  53. package/dist/acp/adapters/cursor.js.map +1 -0
  54. package/dist/acp/gateway.d.ts +108 -0
  55. package/dist/acp/gateway.d.ts.map +1 -0
  56. package/dist/acp/gateway.js +1040 -0
  57. package/dist/acp/gateway.js.map +1 -0
  58. package/dist/acp/image-content.d.ts +19 -0
  59. package/dist/acp/image-content.d.ts.map +1 -0
  60. package/dist/acp/image-content.js +76 -0
  61. package/dist/acp/image-content.js.map +1 -0
  62. package/dist/acp/method-policy.d.ts +239 -0
  63. package/dist/acp/method-policy.d.ts.map +1 -0
  64. package/dist/acp/method-policy.js +102 -0
  65. package/dist/acp/method-policy.js.map +1 -0
  66. package/dist/acp/peer-bridge.d.ts +59 -0
  67. package/dist/acp/peer-bridge.d.ts.map +1 -0
  68. package/dist/acp/peer-bridge.js +367 -0
  69. package/dist/acp/peer-bridge.js.map +1 -0
  70. package/dist/acp/virtual-harness.d.ts +181 -0
  71. package/dist/acp/virtual-harness.d.ts.map +1 -0
  72. package/dist/acp/virtual-harness.js +1556 -0
  73. package/dist/acp/virtual-harness.js.map +1 -0
  74. package/dist/acp/workspace-tools.d.ts +13 -0
  75. package/dist/acp/workspace-tools.d.ts.map +1 -0
  76. package/dist/acp/workspace-tools.js +46 -0
  77. package/dist/acp/workspace-tools.js.map +1 -0
  78. package/dist/acp.d.ts.map +1 -1
  79. package/dist/acp.js +1 -0
  80. package/dist/acp.js.map +1 -1
  81. package/dist/api-proxy-switch.d.ts +2 -0
  82. package/dist/api-proxy-switch.d.ts.map +1 -1
  83. package/dist/api-proxy-switch.js +9 -0
  84. package/dist/api-proxy-switch.js.map +1 -1
  85. package/dist/cli.d.ts.map +1 -1
  86. package/dist/cli.js +4 -3
  87. package/dist/cli.js.map +1 -1
  88. package/dist/client-runtime.d.ts +25 -1
  89. package/dist/client-runtime.d.ts.map +1 -1
  90. package/dist/client-runtime.js +222 -8
  91. package/dist/client-runtime.js.map +1 -1
  92. package/dist/client.github.js +327 -190
  93. package/dist/client.js +327 -190
  94. package/dist/client.js.map +1 -1
  95. package/dist/codex/domain.d.ts +4 -1
  96. package/dist/codex/domain.d.ts.map +1 -1
  97. package/dist/codex/domain.js +54 -4
  98. package/dist/codex/domain.js.map +1 -1
  99. package/dist/codex/virtual-harness.d.ts.map +1 -1
  100. package/dist/codex/virtual-harness.js +3 -0
  101. package/dist/codex/virtual-harness.js.map +1 -1
  102. package/dist/codex-workspace-bridge.d.ts +7 -105
  103. package/dist/codex-workspace-bridge.d.ts.map +1 -1
  104. package/dist/codex-workspace-bridge.js +10 -498
  105. package/dist/codex-workspace-bridge.js.map +1 -1
  106. package/dist/config.d.ts +28 -10
  107. package/dist/config.d.ts.map +1 -1
  108. package/dist/config.js +49 -5
  109. package/dist/config.js.map +1 -1
  110. package/dist/connection-controller.d.ts.map +1 -1
  111. package/dist/connection-controller.js +7 -4
  112. package/dist/connection-controller.js.map +1 -1
  113. package/dist/control-runtime.d.ts +1 -0
  114. package/dist/control-runtime.d.ts.map +1 -1
  115. package/dist/control-runtime.js +65 -10
  116. package/dist/control-runtime.js.map +1 -1
  117. package/dist/harness-version.d.ts.map +1 -1
  118. package/dist/harness-version.js +16 -3
  119. package/dist/harness-version.js.map +1 -1
  120. package/dist/index.d.ts +4 -0
  121. package/dist/index.d.ts.map +1 -1
  122. package/dist/index.js +13197 -8204
  123. package/dist/index.js.map +4 -4
  124. package/dist/loopback-host.d.ts +2 -2
  125. package/dist/loopback-host.d.ts.map +1 -1
  126. package/dist/loopback-host.js +41 -16
  127. package/dist/loopback-host.js.map +1 -1
  128. package/dist/remote-typert-gateway.d.ts.map +1 -1
  129. package/dist/remote-typert-gateway.js +7 -4
  130. package/dist/remote-typert-gateway.js.map +1 -1
  131. package/dist/rpc-router.d.ts +6 -5
  132. package/dist/rpc-router.d.ts.map +1 -1
  133. package/dist/rpc-router.js +49 -18
  134. package/dist/rpc-router.js.map +1 -1
  135. package/dist/server-api.d.ts +2 -0
  136. package/dist/server-api.d.ts.map +1 -1
  137. package/dist/server-api.js +5 -0
  138. package/dist/server-api.js.map +1 -1
  139. package/dist/server-connection.d.ts.map +1 -1
  140. package/dist/server-connection.js +15 -0
  141. package/dist/server-connection.js.map +1 -1
  142. package/dist/service.d.ts +30 -1
  143. package/dist/service.d.ts.map +1 -1
  144. package/dist/service.js +114 -12
  145. package/dist/service.js.map +1 -1
  146. package/dist/session-format-compat.d.ts +1 -0
  147. package/dist/session-format-compat.d.ts.map +1 -1
  148. package/dist/session-format-compat.js +14 -0
  149. package/dist/session-format-compat.js.map +1 -1
  150. package/dist/tui-command.js +2 -0
  151. package/dist/tui-command.js.map +1 -1
  152. package/dist/typert-gateway-switch.d.ts +2 -0
  153. package/dist/typert-gateway-switch.d.ts.map +1 -1
  154. package/dist/typert-gateway-switch.js +16 -0
  155. package/dist/typert-gateway-switch.js.map +1 -1
  156. package/dist/version.d.ts +1 -1
  157. package/dist/version.d.ts.map +1 -1
  158. package/dist/version.js +1 -1
  159. package/dist/version.js.map +1 -1
  160. package/dist/workspace-bridge.d.ts +117 -0
  161. package/dist/workspace-bridge.d.ts.map +1 -0
  162. package/dist/workspace-bridge.js +512 -0
  163. package/dist/workspace-bridge.js.map +1 -0
  164. package/dsh-plugin.json +1 -1
  165. package/package.json +1 -1
@@ -0,0 +1,69 @@
1
+ import { type AgyCatalog } from './antigravity/models.js';
2
+ import { type ChildProcessWithoutNullStreams } from 'node:child_process';
3
+ import type { SafeLogger } from '../../logging.js';
4
+ import type { CursorAcpInboundHandler, CursorAcpLike, CursorAcpUnavailableHandler } from './cursor-process.js';
5
+ export type SpawnAntigravityAcp = (binary: string, args: string[], cwd?: string) => ChildProcessWithoutNullStreams;
6
+ export declare class AntigravityAcpError extends Error {
7
+ readonly code: string;
8
+ constructor(code: string, message: string, options?: ErrorOptions);
9
+ }
10
+ export declare function resolveAntigravityBinary(preferred?: string): string;
11
+ export interface AntigravityAcpClientOptions {
12
+ skipPermissions?: boolean;
13
+ conversationId?: string;
14
+ /** Internal process bound to one conversation. */
15
+ sessionWorker?: boolean;
16
+ cwd?: string;
17
+ args?: string[];
18
+ readModels?: () => Promise<AgyCatalog>;
19
+ }
20
+ /**
21
+ * Host-local stdio client for Google Antigravity CLI (`agy --input-format stream-json --output-format stream-json`).
22
+ * Maps Antigravity's stream-json NDJSON events to the standard Agent ACP gateway protocol.
23
+ */
24
+ export declare class AntigravityAcpClient implements CursorAcpLike {
25
+ private readonly binary;
26
+ private readonly logger?;
27
+ private readonly spawnAcp;
28
+ private process?;
29
+ private readonly inboundHandlers;
30
+ private readonly unavailableHandlers;
31
+ private watcher?;
32
+ private stdoutBuffer;
33
+ private stderrBytes;
34
+ private ready;
35
+ private closed;
36
+ private startPromise?;
37
+ private activeConversationId?;
38
+ private readonly skipPermissions;
39
+ private readonly sessionWorker;
40
+ private initialConversationClaimed;
41
+ private readonly sessions;
42
+ private spare?;
43
+ private spareCwd?;
44
+ private readonly args;
45
+ private readonly cwd;
46
+ private readonly readModels;
47
+ private readonly selections;
48
+ private readonly selecting;
49
+ private currentPromptPending?;
50
+ constructor(binary?: string, logger?: SafeLogger | undefined, spawnAcp?: SpawnAntigravityAcp, options?: AntigravityAcpClientOptions);
51
+ start(): Promise<void>;
52
+ isReady(): boolean;
53
+ private prepareSession;
54
+ private warmNextSession;
55
+ prewarmSession(cwd: string): void;
56
+ call(method: string, params: unknown, timeoutMs?: number): Promise<unknown>;
57
+ respond(_id: string | number, _result: unknown): Promise<void>;
58
+ respondError(_id: string | number, _code: number, _message: string): Promise<void>;
59
+ onInbound(handler: CursorAcpInboundHandler): () => void;
60
+ onUnavailable(handler: CursorAcpUnavailableHandler): () => void;
61
+ close(): Promise<void>;
62
+ private startOnce;
63
+ private sendPrompt;
64
+ private consumeStdout;
65
+ private handleAgyEvent;
66
+ private emitNotification;
67
+ private notifyUnavailable;
68
+ }
69
+ //# sourceMappingURL=antigravity-process.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"antigravity-process.d.ts","sourceRoot":"","sources":["../../../src/acp/adapters/antigravity-process.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,566 @@
1
+ import { readAgyModels, cachedAgyModels, agySelectionArgs } from './antigravity/models.js';
2
+ import { prepareAgyImageDirectory, stageAgyImages, agyImagePrompt } from './antigravity/image-store.js';
3
+ import { parseAcpImage } from '../image-content.js';
4
+ import { spawn } from 'node:child_process';
5
+ import { Buffer } from 'node:buffer';
6
+ import { existsSync } from 'node:fs';
7
+ import { TranscriptWatcher } from './antigravity/transcript-watcher.js';
8
+ const ACP_REQUEST_TIMEOUT_MS = 60_000;
9
+ const ACP_PROMPT_TIMEOUT_MS = 10 * 60_000;
10
+ const ACP_START_TIMEOUT_MS = 20_000;
11
+ const MAX_STDERR_CAPTURE_BYTES = 4 * 1024;
12
+ export class AntigravityAcpError extends Error {
13
+ code;
14
+ constructor(code, message, options) {
15
+ super(message, options);
16
+ this.code = code;
17
+ this.name = 'AntigravityAcpError';
18
+ }
19
+ }
20
+ export function resolveAntigravityBinary(preferred) {
21
+ if (preferred && preferred.trim() !== '' && preferred !== 'agent' && preferred !== 'cursor') {
22
+ return preferred.trim();
23
+ }
24
+ const defaultLocal = '/var/lib/dsh/.local/bin/agy';
25
+ if (existsSync(defaultLocal)) {
26
+ return defaultLocal;
27
+ }
28
+ return 'agy';
29
+ }
30
+ /**
31
+ * Host-local stdio client for Google Antigravity CLI (`agy --input-format stream-json --output-format stream-json`).
32
+ * Maps Antigravity's stream-json NDJSON events to the standard Agent ACP gateway protocol.
33
+ */
34
+ export class AntigravityAcpClient {
35
+ binary;
36
+ logger;
37
+ spawnAcp;
38
+ process;
39
+ inboundHandlers = new Set();
40
+ unavailableHandlers = new Set();
41
+ watcher;
42
+ stdoutBuffer = Buffer.alloc(0);
43
+ stderrBytes = 0;
44
+ ready = false;
45
+ closed = false;
46
+ startPromise;
47
+ activeConversationId;
48
+ skipPermissions;
49
+ sessionWorker;
50
+ initialConversationClaimed = false;
51
+ sessions = new Map();
52
+ spare;
53
+ spareCwd;
54
+ args;
55
+ cwd;
56
+ readModels;
57
+ selections = new Map();
58
+ selecting = new Set();
59
+ currentPromptPending;
60
+ constructor(binary = 'agy', logger, spawnAcp = (bin, args, cwd) => spawn(bin, args, {
61
+ cwd,
62
+ stdio: ['pipe', 'pipe', 'pipe'],
63
+ windowsHide: true,
64
+ env: process.env,
65
+ }), options = {}) {
66
+ this.binary = binary;
67
+ this.logger = logger;
68
+ this.spawnAcp = spawnAcp;
69
+ const loadModels = options.readModels ?? (() => readAgyModels(resolveAntigravityBinary(this.binary)));
70
+ this.readModels = options.sessionWorker ? loadModels : cachedAgyModels(loadModels);
71
+ this.args = options.args ?? ['--input-format', 'stream-json', '--output-format', 'stream-json'];
72
+ this.cwd = options.cwd ?? process.cwd();
73
+ this.sessionWorker = options.sessionWorker === true;
74
+ this.initialConversationClaimed = options.conversationId !== undefined;
75
+ this.skipPermissions = options.skipPermissions === true;
76
+ this.activeConversationId = options.conversationId;
77
+ }
78
+ start() {
79
+ if (this.closed)
80
+ return Promise.reject(new AntigravityAcpError('ANTIGRAVITY_CLOSED', 'The Antigravity domain is closed.'));
81
+ if (this.ready)
82
+ return Promise.resolve();
83
+ this.startPromise ??= this.startOnce().finally(() => { this.startPromise = undefined; });
84
+ return this.startPromise;
85
+ }
86
+ isReady() { return this.ready; }
87
+ prepareSession(conversationId, cwd = this.cwd, selectionArgs) {
88
+ if (this.closed)
89
+ return Promise.reject(new AntigravityAcpError('ANTIGRAVITY_CLOSED', 'The Antigravity domain is closed.'));
90
+ const worker = new AntigravityAcpClient(this.binary, this.logger, this.spawnAcp, {
91
+ args: selectionArgs ? [...withoutSelectionArgs(this.args), ...selectionArgs] : this.args,
92
+ readModels: this.readModels,
93
+ skipPermissions: this.skipPermissions,
94
+ sessionWorker: true,
95
+ cwd,
96
+ ...(conversationId === undefined ? {} : { conversationId }),
97
+ });
98
+ worker.onInbound(frame => { for (const handler of this.inboundHandlers)
99
+ handler(frame); });
100
+ return worker.start().then(async () => {
101
+ if (this.closed) {
102
+ await worker.close();
103
+ throw new AntigravityAcpError('ANTIGRAVITY_CLOSED', 'The Antigravity domain is closed.');
104
+ }
105
+ if (!worker.activeConversationId || (conversationId !== undefined && worker.activeConversationId !== conversationId)) {
106
+ await worker.close();
107
+ throw new AntigravityAcpError('SESSION_MISMATCH', 'Antigravity initialized the wrong conversation.');
108
+ }
109
+ return worker;
110
+ }).catch(async (error) => { await worker.close(); throw error; });
111
+ }
112
+ warmNextSession(cwd = this.cwd) {
113
+ if (this.sessionWorker || this.closed || this.spare !== undefined)
114
+ return;
115
+ const spare = this.prepareSession(undefined, cwd);
116
+ this.spareCwd = cwd;
117
+ this.spare = spare;
118
+ // Observe startup failures even when nobody has requested the spare yet.
119
+ void spare.catch(() => { if (this.spare === spare)
120
+ this.spare = undefined; });
121
+ }
122
+ prewarmSession(cwd) {
123
+ if (this.sessionWorker || this.closed || (this.spare !== undefined && this.spareCwd === cwd))
124
+ return;
125
+ const previous = this.spare;
126
+ this.spare = undefined;
127
+ if (previous !== undefined)
128
+ void previous.then(worker => worker.close()).catch(() => undefined);
129
+ this.warmNextSession(cwd);
130
+ }
131
+ async call(method, params, timeoutMs) {
132
+ if (!this.ready)
133
+ throw new AntigravityAcpError('ANTIGRAVITY_UNAVAILABLE', 'Antigravity ACP is not ready.');
134
+ if (method === 'initialize') {
135
+ return {
136
+ protocolVersion: 1,
137
+ capabilities: {
138
+ loadSession: true,
139
+ promptTypes: ['text', 'image'],
140
+ },
141
+ agentInfo: {
142
+ name: 'antigravity',
143
+ version: '1.2.16',
144
+ },
145
+ backend: 'antigravity',
146
+ };
147
+ }
148
+ if (method === 'session/new') {
149
+ if (this.currentPromptPending)
150
+ throw new AntigravityAcpError('PROMPT_IN_PROGRESS', 'A prompt is in progress.');
151
+ const cwd = typeof params?.cwd === 'string' ? params.cwd : this.cwd;
152
+ if (!this.initialConversationClaimed && this.activeConversationId !== undefined && cwd === this.cwd) {
153
+ this.initialConversationClaimed = true;
154
+ this.warmNextSession(cwd);
155
+ return { sessionId: this.activeConversationId };
156
+ }
157
+ const cached = this.spare;
158
+ const pending = cached !== undefined && this.spareCwd === cwd ? cached : this.prepareSession(undefined, cwd);
159
+ if (cached !== undefined && this.spareCwd !== cwd)
160
+ void cached.then(worker => worker.close()).catch(() => undefined);
161
+ this.spare = undefined;
162
+ const worker = await pending;
163
+ const sessionId = worker.activeConversationId;
164
+ if (sessionId === this.activeConversationId || this.sessions.has(sessionId)) {
165
+ await worker.close();
166
+ throw new AntigravityAcpError('SESSION_MISMATCH', 'Antigravity reused an existing conversation for session/new.');
167
+ }
168
+ this.sessions.set(sessionId, worker);
169
+ this.warmNextSession(cwd);
170
+ return { sessionId };
171
+ }
172
+ if (method === 'dsh/sessionModels') {
173
+ const sessionId = String(params.sessionId);
174
+ const catalog = await this.readModels();
175
+ return { current: this.selections.get(sessionId) ?? { provider: 'antigravity', model: 'host-settings' },
176
+ routable: true, groups: catalog.groups, failures: [] };
177
+ }
178
+ if (method === 'dsh/selectModel') {
179
+ const p = params;
180
+ if (this.selecting.has(p.sessionId))
181
+ throw new AntigravityAcpError('PROMPT_IN_PROGRESS', 'A model change is already in progress.');
182
+ const current = this.sessions.get(p.sessionId) ?? (p.sessionId === this.activeConversationId ? this : undefined);
183
+ if (!current && !p.cwd)
184
+ throw new AntigravityAcpError('SESSION_MISMATCH', 'Load the conversation before selecting its model.');
185
+ if (current?.currentPromptPending)
186
+ throw new AntigravityAcpError('PROMPT_IN_PROGRESS', 'Stop the reply before changing its model.');
187
+ this.selecting.add(p.sessionId);
188
+ try {
189
+ const chosen = agySelectionArgs(await this.readModels(), p.model, p.reasoningEffort);
190
+ const previous = this.selections.get(p.sessionId);
191
+ if (current?.isReady() && previous?.model === chosen.selection.model
192
+ && previous.reasoningEffort === chosen.selection.reasoningEffort)
193
+ return { selected: previous };
194
+ // Resume the same conversation with real CLI flags. Keep the old process usable on startup failure.
195
+ const replacement = await this.prepareSession(p.sessionId, current?.cwd ?? p.cwd, chosen.args);
196
+ if (current?.currentPromptPending) {
197
+ await replacement.close();
198
+ throw new AntigravityAcpError('PROMPT_IN_PROGRESS', 'A reply started during model selection.');
199
+ }
200
+ this.sessions.set(p.sessionId, replacement);
201
+ this.selections.set(p.sessionId, chosen.selection);
202
+ replacement.selections.set(p.sessionId, chosen.selection);
203
+ if (current && current !== this)
204
+ await current.close();
205
+ else if (current === this) {
206
+ this.watcher?.stop();
207
+ this.watcher = undefined;
208
+ const child = this.process;
209
+ this.process = undefined;
210
+ child?.stdout.removeAllListeners('data');
211
+ if (child && !child.killed)
212
+ child.kill('SIGTERM');
213
+ }
214
+ this.emitNotification('session/update', { sessionId: p.sessionId, update: { sessionUpdate: 'model_selection', selected: chosen.selection } });
215
+ return { selected: chosen.selection };
216
+ }
217
+ finally {
218
+ this.selecting.delete(p.sessionId);
219
+ }
220
+ }
221
+ const sessionId = typeof params?.sessionId === 'string'
222
+ ? params.sessionId : undefined;
223
+ if (sessionId !== undefined && this.selecting.has(sessionId))
224
+ throw new AntigravityAcpError('PROMPT_IN_PROGRESS', 'A model change is in progress.');
225
+ if (!this.sessionWorker && sessionId !== undefined && (sessionId !== this.activeConversationId || this.sessions.has(sessionId))) {
226
+ let worker = this.sessions.get(sessionId);
227
+ if (worker === undefined) {
228
+ worker = await this.prepareSession(sessionId, typeof params.cwd === 'string' ? params.cwd : this.cwd);
229
+ this.sessions.set(sessionId, worker);
230
+ }
231
+ return worker.call(method, params, timeoutMs);
232
+ }
233
+ if (method === 'session/load') {
234
+ if (sessionId !== this.activeConversationId)
235
+ throw new AntigravityAcpError('SESSION_MISMATCH', 'The process is bound to another conversation.');
236
+ return { sessionId };
237
+ }
238
+ if (method === 'session/cancel') {
239
+ if (this.currentPromptPending) {
240
+ clearTimeout(this.currentPromptPending.timer);
241
+ const pending = this.currentPromptPending;
242
+ this.currentPromptPending = undefined;
243
+ pending.resolve({ stopReason: 'cancelled' });
244
+ }
245
+ return { cancelled: true };
246
+ }
247
+ if (method === 'session/prompt') {
248
+ const p = params;
249
+ let promptText = p.prompt.filter(item => item.type === 'text').map(item => item.text ?? '').join('\n');
250
+ const images = p.prompt.filter(item => item.type === 'image').map(parseAcpImage);
251
+ if (images.length > 0) {
252
+ if (images.length > 4)
253
+ throw new AntigravityAcpError('INVALID_MESSAGE', 'Too many AGY image attachments.');
254
+ if (this.currentPromptPending)
255
+ throw new AntigravityAcpError('PROMPT_IN_PROGRESS', 'Another prompt is already in progress.');
256
+ const paths = await stageAgyImages(p.sessionId, images);
257
+ promptText = agyImagePrompt(promptText, paths);
258
+ }
259
+ return this.sendPrompt(p.sessionId, promptText, timeoutMs ?? ACP_PROMPT_TIMEOUT_MS);
260
+ }
261
+ throw new AntigravityAcpError('METHOD_NOT_SUPPORTED', `Method ${method} is not supported by Antigravity ACP adapter.`);
262
+ }
263
+ async respond(_id, _result) {
264
+ // Currently auto-approved or handled via session permissions
265
+ }
266
+ async respondError(_id, _code, _message) {
267
+ // Currently auto-approved or handled via session permissions
268
+ }
269
+ onInbound(handler) {
270
+ this.inboundHandlers.add(handler);
271
+ return () => this.inboundHandlers.delete(handler);
272
+ }
273
+ onUnavailable(handler) {
274
+ this.unavailableHandlers.add(handler);
275
+ return () => this.unavailableHandlers.delete(handler);
276
+ }
277
+ async close() {
278
+ if (this.closed)
279
+ return;
280
+ this.closed = true;
281
+ const spare = this.spare;
282
+ this.spare = undefined;
283
+ void spare?.then(worker => worker.close()).catch(() => undefined);
284
+ await Promise.all([...this.sessions.values()].map(worker => worker.close()));
285
+ this.sessions.clear();
286
+ this.ready = false;
287
+ if (this.watcher) {
288
+ this.watcher.stop();
289
+ this.watcher = undefined;
290
+ }
291
+ if (this.currentPromptPending) {
292
+ clearTimeout(this.currentPromptPending.timer);
293
+ this.currentPromptPending.reject(new AntigravityAcpError('ANTIGRAVITY_CLOSED', 'Antigravity ACP was closed.'));
294
+ this.currentPromptPending = undefined;
295
+ }
296
+ const child = this.process;
297
+ this.process = undefined;
298
+ if (child === undefined || child.exitCode !== null || child.killed)
299
+ return;
300
+ await new Promise(resolve => {
301
+ const timer = setTimeout(() => {
302
+ child.kill('SIGKILL');
303
+ resolve();
304
+ }, 2_000);
305
+ timer.unref?.();
306
+ child.once('exit', () => {
307
+ clearTimeout(timer);
308
+ resolve();
309
+ });
310
+ child.kill('SIGTERM');
311
+ });
312
+ }
313
+ async startOnce() {
314
+ if (this.process !== undefined) {
315
+ throw new AntigravityAcpError('ANTIGRAVITY_STARTING', 'Antigravity ACP is already starting.');
316
+ }
317
+ const bin = resolveAntigravityBinary(this.binary);
318
+ const imageDirectory = await prepareAgyImageDirectory();
319
+ if (this.closed)
320
+ throw new AntigravityAcpError('ANTIGRAVITY_CLOSED', 'The Antigravity domain is closed.');
321
+ const args = [...this.args, '--add-dir', imageDirectory];
322
+ if (this.activeConversationId) {
323
+ args.push('--conversation', this.activeConversationId);
324
+ }
325
+ if (this.skipPermissions) {
326
+ args.push('--dangerously-skip-permissions');
327
+ }
328
+ const child = this.spawnAcp(bin, args, this.cwd);
329
+ this.process = child;
330
+ this.stdoutBuffer = Buffer.alloc(0);
331
+ this.stderrBytes = 0;
332
+ let initResolved = false;
333
+ let rejectInit;
334
+ const initPromise = new Promise((resolve, reject) => {
335
+ rejectInit = reject;
336
+ const timer = setTimeout(() => {
337
+ if (!initResolved) {
338
+ reject(new AntigravityAcpError('ANTIGRAVITY_INIT_TIMEOUT', 'Timed out waiting for Antigravity init event.'));
339
+ }
340
+ }, ACP_START_TIMEOUT_MS);
341
+ timer.unref?.();
342
+ const checkInit = (chunk) => {
343
+ this.consumeStdout(chunk, (event) => {
344
+ if (event.event === 'init') {
345
+ initResolved = true;
346
+ clearTimeout(timer);
347
+ const conversationId = event.conversation_id;
348
+ if (typeof conversationId === 'string') {
349
+ this.activeConversationId = conversationId;
350
+ this.watcher = new TranscriptWatcher(conversationId);
351
+ this.watcher.start();
352
+ }
353
+ resolve();
354
+ }
355
+ });
356
+ };
357
+ child.stdout.on('data', chunk => {
358
+ if (!initResolved) {
359
+ checkInit(Buffer.from(chunk));
360
+ }
361
+ else {
362
+ this.consumeStdout(Buffer.from(chunk));
363
+ }
364
+ });
365
+ });
366
+ child.stderr.on('data', chunk => {
367
+ this.stderrBytes = Math.min(MAX_STDERR_CAPTURE_BYTES, this.stderrBytes + Buffer.byteLength(chunk));
368
+ });
369
+ child.on('error', error => {
370
+ if (this.process !== child)
371
+ return;
372
+ this.ready = false;
373
+ if (!initResolved) {
374
+ rejectInit?.(new AntigravityAcpError('ANTIGRAVITY_BINARY_UNAVAILABLE', 'Failed to start the Antigravity CLI.', { cause: error }));
375
+ }
376
+ if (!this.closed) {
377
+ this.logger?.warn('Antigravity binary error', { message: error.message });
378
+ this.notifyUnavailable('ANTIGRAVITY_BINARY_UNAVAILABLE');
379
+ }
380
+ });
381
+ child.on('exit', (code, signal) => {
382
+ if (this.process !== child)
383
+ return;
384
+ this.process = undefined;
385
+ this.ready = false;
386
+ if (!initResolved) {
387
+ rejectInit?.(new AntigravityAcpError('ANTIGRAVITY_EXITED', 'Antigravity exited before initialization.'));
388
+ }
389
+ if (this.currentPromptPending) {
390
+ clearTimeout(this.currentPromptPending.timer);
391
+ this.currentPromptPending.reject(new AntigravityAcpError('ANTIGRAVITY_EXITED', 'Antigravity exited unexpectedly.'));
392
+ this.currentPromptPending = undefined;
393
+ }
394
+ if (!this.closed) {
395
+ this.logger?.warn('Antigravity process exited', { code: code ?? 'none', signal: signal ?? 'none' });
396
+ this.notifyUnavailable('ANTIGRAVITY_EXITED');
397
+ }
398
+ });
399
+ try {
400
+ await initPromise;
401
+ this.ready = true;
402
+ this.warmNextSession();
403
+ this.logger?.info('Antigravity ACP ready', { conversationId: this.activeConversationId });
404
+ }
405
+ catch (err) {
406
+ child.kill('SIGTERM');
407
+ throw err;
408
+ }
409
+ }
410
+ sendPrompt(sessionId, promptText, timeoutMs) {
411
+ if (this.currentPromptPending) {
412
+ throw new AntigravityAcpError('PROMPT_IN_PROGRESS', 'Another prompt is already in progress.');
413
+ }
414
+ const selected = this.selections.get(sessionId);
415
+ if (selected)
416
+ this.emitNotification('session/update', { sessionId, update: { sessionUpdate: 'model_selection', selected } });
417
+ return new Promise((resolve, reject) => {
418
+ const timer = setTimeout(() => {
419
+ if (this.currentPromptPending) {
420
+ this.currentPromptPending = undefined;
421
+ reject(new AntigravityAcpError('ANTIGRAVITY_REQUEST_TIMEOUT', 'Antigravity turn timed out.'));
422
+ }
423
+ }, timeoutMs);
424
+ timer.unref?.();
425
+ this.currentPromptPending = { sessionId, resolve, reject, timer };
426
+ const payload = {
427
+ event: 'user',
428
+ message: { content: promptText },
429
+ };
430
+ const data = Buffer.from(`${JSON.stringify(payload)}\n`, 'utf8');
431
+ this.process?.stdin.write(data);
432
+ });
433
+ }
434
+ consumeStdout(chunk, onRawEvent) {
435
+ this.stdoutBuffer = Buffer.concat([this.stdoutBuffer, chunk]);
436
+ while (true) {
437
+ const newlineIndex = this.stdoutBuffer.indexOf(0x0a);
438
+ if (newlineIndex === -1)
439
+ break;
440
+ const line = this.stdoutBuffer.subarray(0, newlineIndex).toString('utf8').trim();
441
+ this.stdoutBuffer = this.stdoutBuffer.subarray(newlineIndex + 1);
442
+ if (line === '')
443
+ continue;
444
+ try {
445
+ const parsed = JSON.parse(line);
446
+ if (onRawEvent) {
447
+ onRawEvent(parsed);
448
+ }
449
+ this.handleAgyEvent(parsed);
450
+ }
451
+ catch (err) {
452
+ this.logger?.debug('Failed to parse agy stdout line', { code: 'INVALID_AGY_STREAM_EVENT' });
453
+ }
454
+ }
455
+ }
456
+ handleAgyEvent(event) {
457
+ const eventName = event.event;
458
+ const current = this.currentPromptPending;
459
+ const sessionId = current?.sessionId ?? this.activeConversationId ?? 'default';
460
+ if (eventName === 'step_update' && typeof event.step_update === 'object' && event.step_update !== null) {
461
+ const step = event.step_update;
462
+ const stepType = step.step_type;
463
+ if (stepType === 'agent_response' && typeof step.text_delta === 'string') {
464
+ this.emitNotification('session/update', {
465
+ sessionId,
466
+ update: {
467
+ sessionUpdate: 'agent_message_chunk',
468
+ text: step.text_delta,
469
+ },
470
+ });
471
+ }
472
+ else if (stepType === 'thought' || stepType === 'reasoning') {
473
+ const text = typeof step.text_delta === 'string'
474
+ ? step.text_delta
475
+ : typeof step.thought === 'string'
476
+ ? step.thought
477
+ : typeof step.reasoning === 'string'
478
+ ? step.reasoning
479
+ : undefined;
480
+ if (text) {
481
+ this.emitNotification('session/update', {
482
+ sessionId,
483
+ update: {
484
+ sessionUpdate: 'agent_thought_chunk',
485
+ text,
486
+ },
487
+ });
488
+ }
489
+ }
490
+ else if (stepType === 'tool') {
491
+ const toolInfo = step.tool_info ?? {};
492
+ const toolName = typeof step.tool_name === 'string' ? step.tool_name : toolInfo.name ?? 'tool';
493
+ const callId = String(step.step_index ?? Date.now());
494
+ if (step.state === 'ACTIVE') {
495
+ this.emitNotification('session/update', {
496
+ sessionId,
497
+ update: {
498
+ sessionUpdate: 'tool_call',
499
+ callId,
500
+ name: toolName,
501
+ parameters: toolInfo.parameters ?? {},
502
+ },
503
+ });
504
+ }
505
+ else if (step.state === 'DONE') {
506
+ this.emitNotification('session/update', {
507
+ sessionId,
508
+ update: {
509
+ sessionUpdate: 'tool_call_update',
510
+ callId,
511
+ output: typeof toolInfo.output === 'string' ? toolInfo.output : JSON.stringify(toolInfo.output ?? ''),
512
+ },
513
+ });
514
+ }
515
+ }
516
+ }
517
+ else if (eventName === 'result' && typeof event.result === 'object' && event.result !== null) {
518
+ const result = event.result;
519
+ if (current) {
520
+ clearTimeout(current.timer);
521
+ this.currentPromptPending = undefined;
522
+ if (result.status === 'ERROR') {
523
+ current.reject(new AntigravityAcpError('ANTIGRAVITY_TURN_FAILED', String(result.error ?? 'Execution error')));
524
+ }
525
+ else {
526
+ current.resolve({ stopReason: 'end_turn', response: result.response });
527
+ }
528
+ }
529
+ }
530
+ }
531
+ emitNotification(method, params) {
532
+ const notification = { kind: 'notification', method, params };
533
+ for (const handler of this.inboundHandlers) {
534
+ try {
535
+ handler(notification);
536
+ }
537
+ catch (err) {
538
+ this.logger?.warn('Error in inbound ACP handler', { error: String(err) });
539
+ }
540
+ }
541
+ }
542
+ notifyUnavailable(code) {
543
+ for (const handler of this.unavailableHandlers) {
544
+ try {
545
+ handler(code);
546
+ }
547
+ catch (err) {
548
+ this.logger?.warn('Error in unavailable ACP handler', { error: String(err) });
549
+ }
550
+ }
551
+ }
552
+ }
553
+ function withoutSelectionArgs(args) {
554
+ const filtered = [];
555
+ for (let i = 0; i < args.length; i++) {
556
+ if (args[i] === '--model' || args[i] === '--effort') {
557
+ i++;
558
+ continue;
559
+ }
560
+ if (args[i].startsWith('--model=') || args[i].startsWith('--effort='))
561
+ continue;
562
+ filtered.push(args[i]);
563
+ }
564
+ return filtered;
565
+ }
566
+ //# sourceMappingURL=antigravity-process.js.map