@ycodium-ai/agent-antigravity 0.2.3130 → 0.2.3168

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 (2) hide show
  1. package/dist/index.js +286 -123
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -1626,9 +1626,6 @@ function registerAntigravityAuthCommands(ctx) {
1626
1626
  // src/antigravityInstance.ts
1627
1627
  import * as NodeCrypto6 from "node:crypto";
1628
1628
 
1629
- // src/agentProcess.ts
1630
- import { nodeStreamsFromHandle } from "@ycodium-ai/plugin-api/process-stdin";
1631
-
1632
1629
  // ../../packages/ycodium-acp-executor/src/executor.ts
1633
1630
  import * as NodeCrypto from "node:crypto";
1634
1631
 
@@ -26478,7 +26475,10 @@ function createAcpConnection(options2) {
26478
26475
  }
26479
26476
  pending.delete(key);
26480
26477
  try {
26481
- options2.onResponse?.(waiter.method);
26478
+ options2.onResponse?.(
26479
+ waiter,
26480
+ Object.hasOwn(message, "error") ? { error: message["error"] } : { result: message["result"] }
26481
+ );
26482
26482
  } catch {
26483
26483
  }
26484
26484
  if (Object.hasOwn(message, "error")) {
@@ -26611,12 +26611,17 @@ function createAcpConnection(options2) {
26611
26611
  options2.readable.on("end", onEnd);
26612
26612
  options2.readable.on("error", onError);
26613
26613
  options2.writable.once("error", onWritableError);
26614
- const begin = (method, params) => {
26614
+ const begin = (method, params, promptId) => {
26615
26615
  failIfClosed();
26616
26616
  const id = nextRequestId;
26617
26617
  nextRequestId += 1;
26618
26618
  const { promise: promise2, resolve: resolve6, reject } = Promise.withResolvers();
26619
- pending.set(String(id), { method, resolve: resolve6, reject });
26619
+ pending.set(String(id), {
26620
+ method,
26621
+ ...promptId === void 0 ? {} : { promptId },
26622
+ resolve: resolve6,
26623
+ reject
26624
+ });
26620
26625
  const message = params === void 0 ? { jsonrpc: "2.0", id, method } : { jsonrpc: "2.0", id, method, params };
26621
26626
  const written = Promise.race([writeMessage(message), promise2]).then(
26622
26627
  () => void 0,
@@ -26686,12 +26691,14 @@ function createExecutorLifecycle({
26686
26691
  notifyPromptSettled,
26687
26692
  eventStream,
26688
26693
  onInputDead,
26689
- shared
26694
+ shared,
26695
+ promptResults
26690
26696
  }) {
26691
26697
  const cancel = async (turnId) => {
26692
26698
  failIfDisposed();
26693
26699
  const started = requireStarted();
26694
26700
  const targetTurnId = turnId ?? shared.activeTurnId;
26701
+ promptResults.stop(targetTurnId);
26695
26702
  if (targetTurnId !== void 0) {
26696
26703
  interruptedTurnIds.add(targetTurnId);
26697
26704
  }
@@ -26702,6 +26709,9 @@ function createExecutorLifecycle({
26702
26709
  if (shared.sessionId) {
26703
26710
  await connection.notify("session/cancel", { sessionId: shared.sessionId });
26704
26711
  }
26712
+ await promptResults.wait(targetTurnId);
26713
+ if (targetTurnId !== void 0 && shared.activeTurnId !== targetTurnId && !interruptedTurnIds.has(targetTurnId))
26714
+ return;
26705
26715
  const settled = await waitForPromptIdle(cancelGraceMs);
26706
26716
  if (!settled) {
26707
26717
  throw new AcpExecutorCancelTimeoutError();
@@ -26722,6 +26732,7 @@ function createExecutorLifecycle({
26722
26732
  payload: { state: "cancelled", stopReason: "cancelled" }
26723
26733
  });
26724
26734
  interruptedTurnIds.delete(targetTurnId);
26735
+ promptResults.forget(targetTurnId);
26725
26736
  }
26726
26737
  }
26727
26738
  }
@@ -26796,33 +26807,39 @@ function createExecutorLifecycle({
26796
26807
  if (!shared.disposed) emitSessionState("ready");
26797
26808
  }
26798
26809
  };
26799
- const dispose = async () => {
26800
- if (shared.disposed) {
26801
- return;
26802
- }
26810
+ let disposing;
26811
+ const dispose = () => {
26812
+ if (disposing) return disposing;
26813
+ shared.disposing = true;
26814
+ promptResults.stop();
26803
26815
  settleAllApprovals("cancel");
26804
26816
  settleAllUserInputs();
26805
26817
  abortPendingSettlement("executor disposed");
26806
26818
  notifyPromptSettled();
26807
26819
  shared.abortLocalPrompt?.();
26808
- emit({
26809
- type: "session.exited",
26810
- ...stamp(),
26811
- provider: options2.provider,
26812
- threadId: options2.threadId,
26813
- payload: { reason: "disposed" }
26814
- });
26815
- shared.disposed = true;
26816
- shared.generation += 1;
26817
- shared.status = "disposed";
26818
- eventStream.close();
26819
- options2.readable.off("end", onInputDead);
26820
- options2.readable.off("error", onInputDead);
26821
- options2.readable.pause();
26822
- if (!shared.connectionClosed) {
26823
- await connection.awaitInboundIdle().catch(() => void 0);
26824
- await connection.close().catch(() => void 0);
26825
- }
26820
+ disposing = (async () => {
26821
+ promptResults.finishUnreceived();
26822
+ await promptResults.wait();
26823
+ emit({
26824
+ type: "session.exited",
26825
+ ...stamp(),
26826
+ provider: options2.provider,
26827
+ threadId: options2.threadId,
26828
+ payload: { reason: "disposed" }
26829
+ });
26830
+ shared.disposed = true;
26831
+ shared.generation += 1;
26832
+ shared.status = "disposed";
26833
+ eventStream.close();
26834
+ options2.readable.off("end", onInputDead);
26835
+ options2.readable.off("error", onInputDead);
26836
+ options2.readable.pause();
26837
+ if (!shared.connectionClosed) {
26838
+ await connection.awaitInboundIdle().catch(() => void 0);
26839
+ await connection.close().catch(() => void 0);
26840
+ }
26841
+ })();
26842
+ return disposing;
26826
26843
  };
26827
26844
  return { cancel, compact, dispose };
26828
26845
  }
@@ -26926,12 +26943,14 @@ function createExecutorPrompt({
26926
26943
  promptMutex,
26927
26944
  applyRequestedModel,
26928
26945
  notifyPromptSettled,
26929
- shared
26946
+ shared,
26947
+ promptResults
26930
26948
  }) {
26931
26949
  const settleTurn = (input2) => {
26932
- if (!isLive(input2.expectedGeneration)) {
26950
+ if (!isLive(input2.expectedGeneration) || input2.record.finished) {
26933
26951
  return false;
26934
26952
  }
26953
+ promptResults.complete(input2.record);
26935
26954
  if (!acpPromptSettlementBelongsToContext({
26936
26955
  liveAcpSessionId: shared.sessionId ?? "",
26937
26956
  expectedAcpSessionId: input2.expectedSessionId,
@@ -26948,6 +26967,7 @@ function createExecutorPrompt({
26948
26967
  if (shared.status !== "disposed") {
26949
26968
  shared.status = "ready";
26950
26969
  }
26970
+ const interrupted = promptResults.hasInterrupted(input2.turnId);
26951
26971
  emit({
26952
26972
  type: "turn.completed",
26953
26973
  ...stamp(),
@@ -26955,30 +26975,44 @@ function createExecutorPrompt({
26955
26975
  threadId: options2.threadId,
26956
26976
  turnId: input2.turnId,
26957
26977
  payload: {
26958
- state: input2.state,
26959
- stopReason: input2.stopReason,
26978
+ state: interrupted ? "cancelled" : input2.state,
26979
+ stopReason: interrupted ? "cancelled" : input2.stopReason,
26960
26980
  ...input2.errorMessage === void 0 ? {} : { errorMessage: input2.errorMessage },
26961
26981
  ...input2.state === "failed" ? failureCategoryField(input2.failureCategory) : {}
26962
26982
  }
26963
26983
  });
26964
26984
  interruptedTurnIds.delete(input2.turnId);
26985
+ promptResults.forget(input2.turnId);
26965
26986
  return true;
26966
26987
  };
26967
- const sendPromptRpc = async (sessionId, promptParts, onWritten) => {
26988
+ const sendPromptRpc = async (sessionId, promptParts, onWritten, record2) => {
26968
26989
  const settlementHooks = hooks.promptSettlement;
26969
26990
  const promptKey = settlementHooks === void 0 ? void 0 : randomId();
26970
- const pending = connection.begin("session/prompt", {
26971
- sessionId,
26972
- prompt: promptParts,
26973
- ...settlementHooks !== void 0 && promptKey !== void 0 ? settlementHooks.requestFields(promptKey) : {}
26974
- });
26991
+ const pending = connection.begin(
26992
+ "session/prompt",
26993
+ {
26994
+ sessionId,
26995
+ prompt: promptParts,
26996
+ ...settlementHooks !== void 0 && promptKey !== void 0 ? settlementHooks.requestFields(promptKey) : {}
26997
+ },
26998
+ record2?.promptId
26999
+ );
26975
27000
  void pending.written.then(onWritten, () => void 0);
26976
27001
  const promptRpc = pending.response;
26977
27002
  if (settlementHooks === void 0 || promptKey === void 0) {
26978
27003
  return await promptRpc;
26979
27004
  } else {
26980
27005
  const { promise: early, resolve: settleEarly } = Promise.withResolvers();
26981
- shared.pendingSettlement = { promptKey, sessionId, settle: settleEarly };
27006
+ shared.pendingSettlement = {
27007
+ promptKey,
27008
+ sessionId,
27009
+ settle: settleEarly,
27010
+ ...record2 === void 0 ? {} : {
27011
+ onResponse: (response) => promptResults.receive(record2.promptId, response),
27012
+ onError: () => promptResults.reject(record2.promptId),
27013
+ hasResult: () => record2.response !== void 0
27014
+ }
27015
+ };
26982
27016
  try {
26983
27017
  const outcome = await Promise.race([
26984
27018
  promptRpc.then((value) => {
@@ -26999,9 +27033,11 @@ function createExecutorPrompt({
26999
27033
  const prompt = async (input2) => {
27000
27034
  failIfDisposed();
27001
27035
  const started = requireStarted();
27036
+ let record2;
27002
27037
  const settle2 = (rest) => settleTurn({
27003
27038
  expectedGeneration: started.generation,
27004
27039
  expectedSessionId: started.sessionId,
27040
+ record: record2,
27005
27041
  ...rest
27006
27042
  });
27007
27043
  let turnId;
@@ -27014,6 +27050,17 @@ function createExecutorPrompt({
27014
27050
  randomId
27015
27051
  );
27016
27052
  shared.promptsInFlight += 1;
27053
+ record2 = promptResults.add(
27054
+ {
27055
+ promptId: randomId(),
27056
+ sessionId: started.sessionId,
27057
+ generation: started.generation,
27058
+ turnId
27059
+ },
27060
+ () => {
27061
+ finishPrompt();
27062
+ }
27063
+ );
27017
27064
  shared.activeTurnId = turnId;
27018
27065
  shared.status = "running";
27019
27066
  if (shared.promptsInFlight === 1) {
@@ -27030,6 +27077,42 @@ function createExecutorPrompt({
27030
27077
  threadMutex.release();
27031
27078
  }
27032
27079
  const promptParts = input2.prompt ?? (input2.text !== void 0 ? [{ type: "text", text: input2.text }] : [{ type: "text", text: "" }]);
27080
+ let contextWindow;
27081
+ const finishPrompt = () => {
27082
+ if (!isLive(started.generation) || record2.finished) throw new AcpExecutorDisposedError();
27083
+ const response2 = record2.response;
27084
+ if (record2.interrupted || response2 === void 0) {
27085
+ settle2({ turnId, stopReason: "cancelled", state: "cancelled" });
27086
+ return { threadId: options2.threadId, turnId, stopReason: "cancelled" };
27087
+ }
27088
+ const stopReason = hooks.completedStopReason?.(response2) ?? response2.stopReason;
27089
+ if (contextWindow !== void 0) {
27090
+ emit({
27091
+ type: "thread.token-usage.updated",
27092
+ ...stamp(),
27093
+ provider: options2.provider,
27094
+ threadId: options2.threadId,
27095
+ turnId,
27096
+ payload: {
27097
+ usage: {
27098
+ usedTokens: contextWindow.usedTokens,
27099
+ ...contextWindow.maxTokens === void 0 ? {} : { maxTokens: contextWindow.maxTokens }
27100
+ }
27101
+ }
27102
+ });
27103
+ }
27104
+ settle2({
27105
+ turnId,
27106
+ stopReason,
27107
+ state: response2.stopReason === "cancelled" ? "cancelled" : "completed"
27108
+ });
27109
+ return {
27110
+ threadId: options2.threadId,
27111
+ turnId,
27112
+ stopReason,
27113
+ ...response2.usage !== void 0 && response2.usage !== null ? { usage: response2.usage } : {}
27114
+ };
27115
+ };
27033
27116
  await promptMutex.acquire();
27034
27117
  let response;
27035
27118
  try {
@@ -27044,6 +27127,7 @@ function createExecutorPrompt({
27044
27127
  expectedGeneration: started.generation
27045
27128
  });
27046
27129
  }
27130
+ failIfDisposed();
27047
27131
  if (isStale()) {
27048
27132
  settle2({ turnId, stopReason: "cancelled", state: "cancelled" });
27049
27133
  return { threadId: options2.threadId, turnId, stopReason: "cancelled" };
@@ -27051,10 +27135,15 @@ function createExecutorPrompt({
27051
27135
  closeActiveAssistantSegment(turnId);
27052
27136
  let written = false;
27053
27137
  try {
27054
- response = await sendPromptRpc(started.sessionId, promptParts, () => {
27055
- written = true;
27056
- input2.onDispatched?.(turnId);
27057
- });
27138
+ response = await sendPromptRpc(
27139
+ started.sessionId,
27140
+ promptParts,
27141
+ () => {
27142
+ written = true;
27143
+ input2.onDispatched?.(turnId);
27144
+ },
27145
+ record2
27146
+ );
27058
27147
  } catch (error62) {
27059
27148
  if (shared.disposed) {
27060
27149
  throw new AcpExecutorDisposedError();
@@ -27093,8 +27182,7 @@ function createExecutorPrompt({
27093
27182
  if (turnId === void 0) {
27094
27183
  throw new AcpExecutorError("internal", "ACP prompt settled without a turn id");
27095
27184
  }
27096
- const settledTurnId = turnId;
27097
- let contextWindow;
27185
+ if (record2.finished) throw new AcpExecutorDisposedError();
27098
27186
  if (hooks.readContextWindow !== void 0) {
27099
27187
  try {
27100
27188
  contextWindow = await hooks.readContextWindow({
@@ -27105,43 +27193,6 @@ function createExecutorPrompt({
27105
27193
  contextWindow = void 0;
27106
27194
  }
27107
27195
  }
27108
- const finishPrompt = () => {
27109
- if (interruptedTurnIds.has(settledTurnId)) {
27110
- settle2({ turnId: settledTurnId, stopReason: "cancelled", state: "cancelled" });
27111
- return {
27112
- threadId: options2.threadId,
27113
- turnId: settledTurnId,
27114
- stopReason: "cancelled"
27115
- };
27116
- }
27117
- const stopReason = hooks.completedStopReason?.(response) ?? response.stopReason;
27118
- if (contextWindow !== void 0) {
27119
- emit({
27120
- type: "thread.token-usage.updated",
27121
- ...stamp(),
27122
- provider: options2.provider,
27123
- threadId: options2.threadId,
27124
- turnId: settledTurnId,
27125
- payload: {
27126
- usage: {
27127
- usedTokens: contextWindow.usedTokens,
27128
- ...contextWindow.maxTokens === void 0 ? {} : { maxTokens: contextWindow.maxTokens }
27129
- }
27130
- }
27131
- });
27132
- }
27133
- settle2({
27134
- turnId: settledTurnId,
27135
- stopReason,
27136
- state: response.stopReason === "cancelled" ? "cancelled" : "completed"
27137
- });
27138
- return {
27139
- threadId: options2.threadId,
27140
- turnId: settledTurnId,
27141
- stopReason,
27142
- ...response.usage !== void 0 && response.usage !== null ? { usage: response.usage } : {}
27143
- };
27144
- };
27145
27196
  if (threadMutex.tryAcquire()) {
27146
27197
  try {
27147
27198
  return finishPrompt();
@@ -27159,6 +27210,91 @@ function createExecutorPrompt({
27159
27210
  return { sendPromptRpc, prompt };
27160
27211
  }
27161
27212
 
27213
+ // ../../packages/ycodium-acp-executor/src/executor/prompt-results.ts
27214
+ function createPromptResults({
27215
+ options: options2,
27216
+ shared
27217
+ }) {
27218
+ const prompts = /* @__PURE__ */ new Map();
27219
+ const add = (identity, finish) => {
27220
+ const { promise: done, resolve: resolve6 } = Promise.withResolvers();
27221
+ const record2 = {
27222
+ ...identity,
27223
+ finish,
27224
+ done,
27225
+ resolve: resolve6,
27226
+ rejected: false,
27227
+ interrupted: false,
27228
+ finished: false
27229
+ };
27230
+ prompts.set(record2.promptId, record2);
27231
+ return record2;
27232
+ };
27233
+ const receive = (promptId, response) => {
27234
+ const record2 = prompts.get(promptId);
27235
+ if (!record2 || record2.finished || record2.rejected || record2.response !== void 0) return;
27236
+ if (shared.disposed || shared.generation !== record2.generation || shared.sessionId !== record2.sessionId)
27237
+ return;
27238
+ record2.response = response;
27239
+ };
27240
+ const reject = (promptId) => {
27241
+ const record2 = prompts.get(promptId);
27242
+ if (record2 && record2.response === void 0) record2.rejected = true;
27243
+ };
27244
+ const stop = (turnId) => {
27245
+ for (const record2 of prompts.values()) {
27246
+ if (!record2.finished && (turnId === void 0 || record2.turnId === turnId) && record2.response === void 0) {
27247
+ record2.interrupted = true;
27248
+ }
27249
+ }
27250
+ };
27251
+ const complete = (record2) => {
27252
+ record2.finished = true;
27253
+ record2.resolve();
27254
+ };
27255
+ const hasInterrupted = (turnId) => [...prompts.values()].some((record2) => record2.turnId === turnId && record2.interrupted);
27256
+ const forget = (turnId) => {
27257
+ for (const [id, record2] of prompts) {
27258
+ if (record2.turnId === turnId) {
27259
+ complete(record2);
27260
+ prompts.delete(id);
27261
+ }
27262
+ }
27263
+ };
27264
+ const wait = async (turnId) => {
27265
+ const claimed = [...prompts.values()].filter(
27266
+ (record2) => !record2.finished && record2.response !== void 0 && (turnId === void 0 || record2.turnId === turnId)
27267
+ );
27268
+ if (claimed.length === 0) return;
27269
+ let timer;
27270
+ try {
27271
+ const drained = await Promise.race([
27272
+ Promise.all(claimed.map((record2) => record2.done)).then(() => true),
27273
+ new Promise((resolve6) => {
27274
+ timer = setTimeout(() => resolve6(false), options2.resultDrainTimeoutMs ?? 2e3);
27275
+ })
27276
+ ]);
27277
+ if (drained) return;
27278
+ options2.log?.warn?.("ACP result settlement timed out", { threadId: options2.threadId });
27279
+ for (const record2 of claimed) if (!record2.finished) record2.finish();
27280
+ } finally {
27281
+ clearTimeout(timer);
27282
+ }
27283
+ };
27284
+ const finishUnreceived = () => {
27285
+ const claimedTurns = new Set(
27286
+ [...prompts.values()].filter((record2) => !record2.finished && record2.response !== void 0).map((record2) => record2.turnId)
27287
+ );
27288
+ for (const record2 of prompts.values()) {
27289
+ if (!record2.finished && record2.response === void 0) {
27290
+ if (claimedTurns.has(record2.turnId)) record2.finish();
27291
+ else complete(record2);
27292
+ }
27293
+ }
27294
+ };
27295
+ return { add, receive, reject, stop, complete, hasInterrupted, forget, wait, finishUnreceived };
27296
+ }
27297
+
27162
27298
  // ../../packages/ycodium-acp-executor/src/user-input-pending.ts
27163
27299
  var userInputAnswerOptionId = (question, answers) => {
27164
27300
  const answer = answers[question.id];
@@ -27465,7 +27601,7 @@ function createExecutorRuntime({
27465
27601
  turnId: () => shared.activeTurnId
27466
27602
  });
27467
27603
  const failIfDisposed = () => {
27468
- if (shared.disposed) {
27604
+ if (shared.disposed || shared.disposing) {
27469
27605
  throw new AcpExecutorDisposedError();
27470
27606
  }
27471
27607
  };
@@ -28057,6 +28193,7 @@ function createExecutorSettlement({
28057
28193
  const abortPendingSettlement = (reason, failureCategory) => {
28058
28194
  const waiting = shared.pendingSettlement;
28059
28195
  if (waiting === void 0) return;
28196
+ if (waiting.hasResult?.()) return;
28060
28197
  shared.pendingSettlement = void 0;
28061
28198
  waiting.settle({
28062
28199
  error: withFailureCategory(
@@ -28078,6 +28215,7 @@ function createExecutorSettlement({
28078
28215
  shared.pendingSettlement = void 0;
28079
28216
  rememberSettledPromptKey(waiting.promptKey);
28080
28217
  if (signal.outcome === "error") {
28218
+ waiting.onError?.();
28081
28219
  waiting.settle({
28082
28220
  error: withFailureCategory(
28083
28221
  new AcpExecutorRequestError(
@@ -28088,8 +28226,10 @@ function createExecutorSettlement({
28088
28226
  )
28089
28227
  });
28090
28228
  } else {
28229
+ const response = { stopReason: signal.stopReason ?? "end_turn" };
28230
+ waiting.onResponse?.(response);
28091
28231
  waiting.settle({
28092
- response: { stopReason: signal.stopReason ?? "end_turn" }
28232
+ response
28093
28233
  });
28094
28234
  }
28095
28235
  return true;
@@ -28419,6 +28559,7 @@ function createAcpExecutor(options2) {
28419
28559
  const shared = {
28420
28560
  generation: 0,
28421
28561
  disposed: false,
28562
+ disposing: false,
28422
28563
  status: "idle",
28423
28564
  sessionId: void 0,
28424
28565
  modelSelectionState: {
@@ -28506,6 +28647,7 @@ function createAcpExecutor(options2) {
28506
28647
  shared
28507
28648
  });
28508
28649
  const { rememberSettledPromptKey, abortPendingSettlement, settleFromNotification } = createExecutorSettlement({ hooks, shared });
28650
+ const promptResults = createPromptResults({ options: options2, shared });
28509
28651
  const connection = createAcpConnection({
28510
28652
  readable: options2.readable,
28511
28653
  writable: options2.writable,
@@ -28516,8 +28658,12 @@ function createAcpExecutor(options2) {
28516
28658
  });
28517
28659
  },
28518
28660
  // 窗口在应答帧到达的那一刻同步收掉:应答之后的通知是真输出,不能再丢。
28519
- onResponse: (method) => {
28661
+ onResponse: ({ method, promptId }, outcome) => {
28520
28662
  if (method === "session/load") shared.sessionLoadInFlight = false;
28663
+ if (promptId !== void 0) {
28664
+ if ("result" in outcome) promptResults.receive(promptId, outcome.result);
28665
+ else promptResults.reject(promptId);
28666
+ }
28521
28667
  },
28522
28668
  onNotification: (notification) => {
28523
28669
  if (notification.method === "session/update") {
@@ -28582,6 +28728,7 @@ function createAcpExecutor(options2) {
28582
28728
  shared
28583
28729
  });
28584
28730
  const { sendPromptRpc, prompt } = createExecutorPrompt({
28731
+ promptResults,
28585
28732
  isLive,
28586
28733
  closeActiveAssistantSegment,
28587
28734
  emit,
@@ -28601,6 +28748,7 @@ function createAcpExecutor(options2) {
28601
28748
  shared
28602
28749
  });
28603
28750
  const { cancel, compact, dispose } = createExecutorLifecycle({
28751
+ promptResults,
28604
28752
  failIfDisposed,
28605
28753
  requireStarted,
28606
28754
  interruptedTurnIds,
@@ -28652,6 +28800,27 @@ function createAcpExecutor(options2) {
28652
28800
  };
28653
28801
  }
28654
28802
 
28803
+ // ../../packages/ycodium-acp-executor/src/session-registry.ts
28804
+ function createAcpSessionRegistry(threads, stopBooked) {
28805
+ const requireThread = (threadId) => {
28806
+ const booked = threads.get(threadId);
28807
+ if (!booked) throw new Error(`unknown thread ${threadId}`);
28808
+ if (booked.closing) throw new Error(`thread ${threadId} is closing`);
28809
+ return booked;
28810
+ };
28811
+ const stopSession = (threadId, booked = threads.get(threadId)) => {
28812
+ if (!booked) return Promise.resolve();
28813
+ booked.closing ??= Promise.resolve().then(() => stopBooked(booked)).then(() => {
28814
+ if (threads.get(threadId) === booked) threads.delete(threadId);
28815
+ });
28816
+ return booked.closing;
28817
+ };
28818
+ const stopAll = () => Promise.all([...threads].map(([threadId, booked]) => stopSession(threadId, booked))).then(
28819
+ () => void 0
28820
+ );
28821
+ return { requireThread, stopSession, stopAll };
28822
+ }
28823
+
28655
28824
  // ../../packages/ycodium-acp-executor/src/start-abort.ts
28656
28825
  function throwIfStartAborted(signal) {
28657
28826
  if (signal?.aborted) throw new Error("aborted");
@@ -28742,6 +28911,9 @@ function acpAgentVersion(initializeResult) {
28742
28911
  }
28743
28912
  var MAX_VERSION_OUTPUT_BYTES = 64 * 1024;
28744
28913
 
28914
+ // src/agentProcess.ts
28915
+ import { nodeStreamsFromHandle } from "@ycodium-ai/plugin-api/process-stdin";
28916
+
28745
28917
  // src/clock.ts
28746
28918
  var realAgentClock = {
28747
28919
  now: () => Date.now(),
@@ -30073,7 +30245,7 @@ function createAntigravitySession({
30073
30245
  threads,
30074
30246
  mutable,
30075
30247
  resolveInput,
30076
- stopBooked,
30248
+ stopSession,
30077
30249
  login,
30078
30250
  noteSession,
30079
30251
  recordCatalog,
@@ -30088,8 +30260,8 @@ function createAntigravitySession({
30088
30260
  if (cwd.trim() === "") throw new Error("workspace path missing");
30089
30261
  const existing = threads.get(input2.threadId);
30090
30262
  if (existing !== void 0) {
30091
- threads.delete(input2.threadId);
30092
- await stopBooked(existing);
30263
+ await stopSession(input2.threadId, existing);
30264
+ if (mutable.disposed) throw new Error("instance disposed");
30093
30265
  throwIfStartAborted(signal);
30094
30266
  }
30095
30267
  const lease = await deps.runtime.acquire(resolveInput);
@@ -30313,10 +30485,9 @@ import * as NodeCrypto4 from "node:crypto";
30313
30485
  function createAntigravityTurn({
30314
30486
  deps,
30315
30487
  events,
30316
- threads,
30317
30488
  mutable,
30318
30489
  requireThread,
30319
- stopBooked,
30490
+ stopSession,
30320
30491
  login,
30321
30492
  pushTaskEvents
30322
30493
  }) {
@@ -30353,8 +30524,7 @@ function createAntigravityTurn({
30353
30524
  ...base,
30354
30525
  payload: { state: "completed", stopReason: "end_turn" }
30355
30526
  });
30356
- threads.delete(input2.threadId);
30357
- await stopBooked(booked);
30527
+ await stopSession(input2.threadId, booked);
30358
30528
  return { threadId: input2.threadId, turnId };
30359
30529
  };
30360
30530
  return {
@@ -32162,6 +32332,7 @@ async function createAntigravityInstance(config2, host, deps) {
32162
32332
  const events = new EventBus();
32163
32333
  const threads = /* @__PURE__ */ new Map();
32164
32334
  const mutable = { disposed: false };
32335
+ let disposeTask;
32165
32336
  const unregister = deps.runtime.registerInstance({
32166
32337
  instanceId: host.instanceId,
32167
32338
  host,
@@ -32174,11 +32345,6 @@ async function createAntigravityInstance(config2, host, deps) {
32174
32345
  processEnv
32175
32346
  };
32176
32347
  const resolveExecutable = () => deps.runtime.resolve(resolveInput);
32177
- const requireThread = (threadId) => {
32178
- const booked = threads.get(threadId);
32179
- if (!booked) throw new Error(`unknown thread ${threadId}`);
32180
- return booked;
32181
- };
32182
32348
  const stopBooked = async (booked) => {
32183
32349
  for (const stopped of booked.background.finish()) events.push(stopped);
32184
32350
  await booked.executor.dispose().catch(() => void 0);
@@ -32190,6 +32356,7 @@ async function createAntigravityInstance(config2, host, deps) {
32190
32356
  });
32191
32357
  }
32192
32358
  };
32359
+ const { requireThread, stopSession, stopAll } = createAcpSessionRegistry(threads, stopBooked);
32193
32360
  const helpers = createAntigravityTextGeneration({
32194
32361
  host,
32195
32362
  profile: dirs.profile,
@@ -32205,8 +32372,10 @@ async function createAntigravityInstance(config2, host, deps) {
32205
32372
  });
32206
32373
  const stopAllSessions = async (keepThreadId) => {
32207
32374
  const targets = [...threads].filter(([threadId]) => threadId !== keepThreadId);
32208
- for (const [threadId] of targets) threads.delete(threadId);
32209
- await Promise.all([...targets.map(([, booked]) => stopBooked(booked)), helpers.stopRunning()]);
32375
+ await Promise.all([
32376
+ ...targets.map(([threadId, booked]) => stopSession(threadId, booked)),
32377
+ helpers.stopRunning()
32378
+ ]);
32210
32379
  };
32211
32380
  const login = createLoginController({
32212
32381
  host,
@@ -32304,7 +32473,7 @@ async function createAntigravityInstance(config2, host, deps) {
32304
32473
  threads,
32305
32474
  mutable,
32306
32475
  resolveInput,
32307
- stopBooked,
32476
+ stopSession,
32308
32477
  login,
32309
32478
  noteSession,
32310
32479
  recordCatalog,
@@ -32314,10 +32483,9 @@ async function createAntigravityInstance(config2, host, deps) {
32314
32483
  const turn = createAntigravityTurn({
32315
32484
  deps,
32316
32485
  events,
32317
- threads,
32318
32486
  mutable,
32319
32487
  requireThread,
32320
- stopBooked,
32488
+ stopSession,
32321
32489
  login,
32322
32490
  pushTaskEvents
32323
32491
  });
@@ -32364,11 +32532,10 @@ async function createAntigravityInstance(config2, host, deps) {
32364
32532
  sendTurn: turn.sendTurn,
32365
32533
  interruptTurn: async (threadId, turnId) => {
32366
32534
  const booked = threads.get(threadId);
32367
- if (booked === void 0) return;
32535
+ if (booked === void 0 || booked.closing) return;
32368
32536
  host.log.info("interrupt turn", { threadId, turnId });
32369
32537
  if (booked.session.status !== "running" && booked.background.hasPromoted()) {
32370
- threads.delete(threadId);
32371
- await stopBooked(booked);
32538
+ await stopSession(threadId, booked);
32372
32539
  return;
32373
32540
  }
32374
32541
  await booked.executor.cancel(turnId);
@@ -32400,12 +32567,7 @@ async function createAntigravityInstance(config2, host, deps) {
32400
32567
  };
32401
32568
  if (applied !== void 0) booked.appliedModeId = applied;
32402
32569
  },
32403
- stopSession: async (threadId) => {
32404
- const booked = threads.get(threadId);
32405
- if (booked === void 0) return;
32406
- threads.delete(threadId);
32407
- await stopBooked(booked);
32408
- },
32570
+ stopSession: (threadId) => stopSession(threadId),
32409
32571
  readThread: async (threadId) => {
32410
32572
  const booked = requireThread(threadId);
32411
32573
  return { threadId, turns: booked.turns };
@@ -32413,17 +32575,18 @@ async function createAntigravityInstance(config2, host, deps) {
32413
32575
  events,
32414
32576
  textGeneration: helpers.textGeneration,
32415
32577
  continuationKey: dirs.continuationKey,
32416
- dispose: async () => {
32417
- if (mutable.disposed) return;
32578
+ dispose: () => {
32579
+ if (disposeTask) return disposeTask;
32418
32580
  mutable.disposed = true;
32419
- unregisterLogin();
32420
- unsubscribeRuntime();
32421
- await login.dispose();
32422
- unregister();
32423
- const booked = [...threads.values()];
32424
- threads.clear();
32425
- await Promise.all([...booked.map((entry) => stopBooked(entry)), helpers.stopRunning()]);
32426
- events.close();
32581
+ disposeTask = (async () => {
32582
+ unregisterLogin();
32583
+ unsubscribeRuntime();
32584
+ await login.dispose();
32585
+ unregister();
32586
+ await Promise.all([stopAll(), helpers.stopRunning()]);
32587
+ events.close();
32588
+ })();
32589
+ return disposeTask;
32427
32590
  }
32428
32591
  };
32429
32592
  return instance;
@@ -33498,7 +33661,7 @@ var executors = [
33498
33661
  ];
33499
33662
  var index_default = definePlugin({
33500
33663
  id: "agent-antigravity",
33501
- apiVersion: 14,
33664
+ apiVersion: 16,
33502
33665
  executors,
33503
33666
  activate(ctx) {
33504
33667
  const runtime = createRuntimeManager({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ycodium-ai/agent-antigravity",
3
- "version": "0.2.3130",
3
+ "version": "0.2.3168",
4
4
  "description": "Google Antigravity executor: runs the Antigravity agent over Agent Client Protocol stdio.",
5
5
  "keywords": [
6
6
  "ycodium",
@@ -31,8 +31,8 @@
31
31
  "typescript": "~6.0.3",
32
32
  "vite-plus": "0.2.2",
33
33
  "yauzl": "^3.4.0",
34
- "@ycodium-ai/plugin-api": "0.2.3130",
35
- "ycodium-acp-executor": "0.2.3130",
34
+ "ycodium-acp-executor": "0.2.3168",
35
+ "@ycodium-ai/plugin-api": "0.2.3168",
36
36
  "ycodium-executor-testing": "0.0.0"
37
37
  },
38
38
  "ycodium": {