@ycodium-ai/agent-kimi 0.2.3236 → 0.2.3240

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 +147 -101
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -25136,6 +25136,83 @@ function createAcpConnection(options) {
25136
25136
  };
25137
25137
  }
25138
25138
 
25139
+ // ../../packages/ycodium-acp-executor/src/model-selection.ts
25140
+ function normalizeModelId(value) {
25141
+ return value?.trim() || void 0;
25142
+ }
25143
+ function modelSelectionStateFromSetup(setup) {
25144
+ const sessionModels = isRecord(setup.models) ? setup.models : void 0;
25145
+ const modelConfigId = extractModelConfigId(setup);
25146
+ const strategy = sessionModels === void 0 && modelConfigId !== void 0 ? "config-option" : "session/set_model";
25147
+ const modelConfigOption = modelConfigId === void 0 ? void 0 : findSessionConfigOption(setup.configOptions, modelConfigId);
25148
+ const configModel = modelConfigOption?.currentValue;
25149
+ const currentModelId = strategy === "config-option" ? typeof configModel === "string" ? normalizeModelId(configModel) : void 0 : typeof sessionModels?.["currentModelId"] === "string" ? normalizeModelId(sessionModels["currentModelId"]) : void 0;
25150
+ return {
25151
+ strategy,
25152
+ sessionModelsAdvertised: sessionModels !== void 0,
25153
+ modelConfigId,
25154
+ currentModelId,
25155
+ advertisedModelValues: strategy === "config-option" ? modelConfigOption === void 0 ? [] : collectSessionConfigOptionValues(modelConfigOption) : collectSessionModelIds(sessionModels),
25156
+ configOptions: setup.configOptions
25157
+ };
25158
+ }
25159
+
25160
+ // ../../packages/ycodium-acp-executor/src/mutex.ts
25161
+ var Mutex = class {
25162
+ locked = false;
25163
+ waiters = [];
25164
+ get isLocked() {
25165
+ return this.locked;
25166
+ }
25167
+ acquire() {
25168
+ if (!this.locked) {
25169
+ this.locked = true;
25170
+ return Promise.resolve();
25171
+ }
25172
+ return new Promise((resolve3) => {
25173
+ this.waiters.push(resolve3);
25174
+ });
25175
+ }
25176
+ tryAcquire() {
25177
+ if (this.locked) {
25178
+ return false;
25179
+ }
25180
+ this.locked = true;
25181
+ return true;
25182
+ }
25183
+ release() {
25184
+ const next = this.waiters.shift();
25185
+ if (next) {
25186
+ next();
25187
+ return;
25188
+ }
25189
+ this.locked = false;
25190
+ }
25191
+ async runExclusive(fn) {
25192
+ await this.acquire();
25193
+ try {
25194
+ return await fn();
25195
+ } finally {
25196
+ this.release();
25197
+ }
25198
+ }
25199
+ };
25200
+
25201
+ // ../../packages/ycodium-acp-executor/src/user-input-pending.ts
25202
+ var userInputAnswerOptionId = (question, answers) => {
25203
+ const answer = answers[question.id];
25204
+ const selected = typeof answer === "string" ? answer : Array.isArray(answer) && answer.length === 1 && typeof answer[0] === "string" ? answer[0] : void 0;
25205
+ return selected !== void 0 && question.options.some((option) => option.id === selected) ? selected : void 0;
25206
+ };
25207
+
25208
+ // ../../packages/ycodium-acp-executor/src/vendor-hooks.ts
25209
+ var defaultVendorHooks = {
25210
+ completedStopReason: (response) => response.stopReason
25211
+ };
25212
+
25213
+ // ../../packages/ycodium-acp-executor/src/executor/support.ts
25214
+ var DEFAULT_RESULT_DRAIN_TIMEOUT_MS = 2e3;
25215
+
25139
25216
  // ../../packages/ycodium-acp-executor/src/executor/lifecycle.ts
25140
25217
  function createExecutorLifecycle({
25141
25218
  failIfDisposed,
@@ -25278,16 +25355,30 @@ function createExecutorLifecycle({
25278
25355
  }
25279
25356
  };
25280
25357
  let disposing;
25281
- const dispose = () => {
25358
+ const dispose = (exitCode) => {
25282
25359
  if (disposing) return disposing;
25283
25360
  shared.disposing = true;
25284
- promptResults.stop();
25285
- settleAllApprovals("cancel");
25286
- settleAllUserInputs();
25287
- abortPendingSettlement("executor disposed");
25288
- notifyPromptSettled();
25289
- shared.abortLocalPrompt?.();
25290
25361
  disposing = (async () => {
25362
+ if (exitCode !== void 0) {
25363
+ let timer;
25364
+ await Promise.race([
25365
+ connection.closed.catch(() => void 0),
25366
+ new Promise((resolve3) => {
25367
+ timer = setTimeout(
25368
+ resolve3,
25369
+ options.resultDrainTimeoutMs ?? DEFAULT_RESULT_DRAIN_TIMEOUT_MS
25370
+ );
25371
+ })
25372
+ ]);
25373
+ clearTimeout(timer);
25374
+ await promptResults.wait(void 0, true);
25375
+ }
25376
+ promptResults.stop();
25377
+ settleAllApprovals("cancel");
25378
+ settleAllUserInputs();
25379
+ abortPendingSettlement("executor disposed");
25380
+ notifyPromptSettled();
25381
+ shared.abortLocalPrompt?.();
25291
25382
  promptResults.finishUnreceived();
25292
25383
  await promptResults.wait();
25293
25384
  emit({
@@ -25295,7 +25386,10 @@ function createExecutorLifecycle({
25295
25386
  ...stamp(),
25296
25387
  provider: options.provider,
25297
25388
  threadId: options.threadId,
25298
- payload: { reason: "disposed" }
25389
+ payload: exitCode === void 0 ? { reason: "disposed" } : {
25390
+ reason: exitCode === null ? "process exited without an exit code" : `process exited with code ${exitCode}`,
25391
+ exitKind: exitCode === 0 ? "graceful" : "error"
25392
+ }
25299
25393
  });
25300
25394
  shared.disposed = true;
25301
25395
  shared.generation += 1;
@@ -25390,11 +25484,6 @@ var acpPromptFailureCategory = (error62, input2) => {
25390
25484
  return error62 instanceof AcpConnectionClosedError ? acpTransportIfEstablished(input2.sessionEstablished, input2.disposed) : void 0;
25391
25485
  };
25392
25486
 
25393
- // ../../packages/ycodium-acp-executor/src/vendor-hooks.ts
25394
- var defaultVendorHooks = {
25395
- completedStopReason: (response) => response.stopReason
25396
- };
25397
-
25398
25487
  // ../../packages/ycodium-acp-executor/src/executor/prompt.ts
25399
25488
  function createExecutorPrompt({
25400
25489
  isLive,
@@ -25500,8 +25589,12 @@ function createExecutorPrompt({
25500
25589
  }
25501
25590
  }
25502
25591
  };
25503
- const prompt = async (input2) => {
25592
+ const failIfPromptUnavailable = () => {
25504
25593
  failIfDisposed();
25594
+ if (shared.connectionClosed) throw new AcpExecutorDisposedError();
25595
+ };
25596
+ const prompt = async (input2) => {
25597
+ failIfPromptUnavailable();
25505
25598
  const started = requireStarted();
25506
25599
  let record2;
25507
25600
  const settle2 = (rest) => settleTurn({
@@ -25513,7 +25606,7 @@ function createExecutorPrompt({
25513
25606
  let turnId;
25514
25607
  await threadMutex.acquire();
25515
25608
  try {
25516
- failIfDisposed();
25609
+ failIfPromptUnavailable();
25517
25610
  turnId = selectPromptTurnId(
25518
25611
  input2,
25519
25612
  shared.promptsInFlight > 0 ? shared.activeTurnId : void 0,
@@ -25622,7 +25715,7 @@ function createExecutorPrompt({
25622
25715
  sessionEstablished: shared.startResult !== void 0,
25623
25716
  disposed: shared.disposed
25624
25717
  });
25625
- if (written && input2.onDispatched !== void 0 && !interruptedTurnIds.has(turnId)) {
25718
+ if (!interruptedTurnIds.has(turnId)) {
25626
25719
  const errorMessage = error62 instanceof Error && error62.message.trim() || "ACP prompt failed";
25627
25720
  if (settle2({
25628
25721
  turnId,
@@ -25630,7 +25723,7 @@ function createExecutorPrompt({
25630
25723
  state: "failed",
25631
25724
  errorMessage,
25632
25725
  ...failureCategory === void 0 ? {} : { failureCategory }
25633
- }))
25726
+ }) && written && input2.onDispatched !== void 0)
25634
25727
  options.log?.warn?.("turn failed after dispatch", {
25635
25728
  threadId: options.threadId,
25636
25729
  failure: errorMessage
@@ -25731,9 +25824,9 @@ function createPromptResults({
25731
25824
  }
25732
25825
  }
25733
25826
  };
25734
- const wait = async (turnId) => {
25827
+ const wait = async (turnId, includeUnreceived = false) => {
25735
25828
  const claimed = [...prompts.values()].filter(
25736
- (record2) => !record2.finished && record2.response !== void 0 && (turnId === void 0 || record2.turnId === turnId)
25829
+ (record2) => !record2.finished && (includeUnreceived || record2.response !== void 0) && (turnId === void 0 || record2.turnId === turnId)
25737
25830
  );
25738
25831
  if (claimed.length === 0) return;
25739
25832
  let timer;
@@ -25741,7 +25834,10 @@ function createPromptResults({
25741
25834
  const drained = await Promise.race([
25742
25835
  Promise.all(claimed.map((record2) => record2.done)).then(() => true),
25743
25836
  new Promise((resolve3) => {
25744
- timer = setTimeout(() => resolve3(false), options.resultDrainTimeoutMs ?? 2e3);
25837
+ timer = setTimeout(
25838
+ () => resolve3(false),
25839
+ options.resultDrainTimeoutMs ?? DEFAULT_RESULT_DRAIN_TIMEOUT_MS
25840
+ );
25745
25841
  })
25746
25842
  ]);
25747
25843
  if (drained) return;
@@ -25765,13 +25861,6 @@ function createPromptResults({
25765
25861
  return { add, receive, reject, stop, complete, hasInterrupted, forget, wait, finishUnreceived };
25766
25862
  }
25767
25863
 
25768
- // ../../packages/ycodium-acp-executor/src/user-input-pending.ts
25769
- var userInputAnswerOptionId = (question, answers) => {
25770
- const answer = answers[question.id];
25771
- const selected = typeof answer === "string" ? answer : Array.isArray(answer) && answer.length === 1 && typeof answer[0] === "string" ? answer[0] : void 0;
25772
- return selected !== void 0 && question.options.some((option) => option.id === selected) ? selected : void 0;
25773
- };
25774
-
25775
25864
  // ../../packages/ycodium-acp-executor/src/executor/requests.ts
25776
25865
  function createExecutorRequests({
25777
25866
  emit,
@@ -26303,27 +26392,6 @@ function acpInitializePayload(clientInfo, overrides) {
26303
26392
  };
26304
26393
  }
26305
26394
 
26306
- // ../../packages/ycodium-acp-executor/src/model-selection.ts
26307
- function normalizeModelId(value) {
26308
- return value?.trim() || void 0;
26309
- }
26310
- function modelSelectionStateFromSetup(setup) {
26311
- const sessionModels = isRecord(setup.models) ? setup.models : void 0;
26312
- const modelConfigId = extractModelConfigId(setup);
26313
- const strategy = sessionModels === void 0 && modelConfigId !== void 0 ? "config-option" : "session/set_model";
26314
- const modelConfigOption = modelConfigId === void 0 ? void 0 : findSessionConfigOption(setup.configOptions, modelConfigId);
26315
- const configModel = modelConfigOption?.currentValue;
26316
- const currentModelId = strategy === "config-option" ? typeof configModel === "string" ? normalizeModelId(configModel) : void 0 : typeof sessionModels?.["currentModelId"] === "string" ? normalizeModelId(sessionModels["currentModelId"]) : void 0;
26317
- return {
26318
- strategy,
26319
- sessionModelsAdvertised: sessionModels !== void 0,
26320
- modelConfigId,
26321
- currentModelId,
26322
- advertisedModelValues: strategy === "config-option" ? modelConfigOption === void 0 ? [] : collectSessionConfigOptionValues(modelConfigOption) : collectSessionModelIds(sessionModels),
26323
- configOptions: setup.configOptions
26324
- };
26325
- }
26326
-
26327
26395
  // ../../packages/ycodium-acp-executor/src/runtime-mode.ts
26328
26396
  function isRecord5(value) {
26329
26397
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -26885,47 +26953,6 @@ function createExecutorUpdates({
26885
26953
  return { emitCompactionState, handleSessionUpdate };
26886
26954
  }
26887
26955
 
26888
- // ../../packages/ycodium-acp-executor/src/mutex.ts
26889
- var Mutex = class {
26890
- locked = false;
26891
- waiters = [];
26892
- get isLocked() {
26893
- return this.locked;
26894
- }
26895
- acquire() {
26896
- if (!this.locked) {
26897
- this.locked = true;
26898
- return Promise.resolve();
26899
- }
26900
- return new Promise((resolve3) => {
26901
- this.waiters.push(resolve3);
26902
- });
26903
- }
26904
- tryAcquire() {
26905
- if (this.locked) {
26906
- return false;
26907
- }
26908
- this.locked = true;
26909
- return true;
26910
- }
26911
- release() {
26912
- const next = this.waiters.shift();
26913
- if (next) {
26914
- next();
26915
- return;
26916
- }
26917
- this.locked = false;
26918
- }
26919
- async runExclusive(fn) {
26920
- await this.acquire();
26921
- try {
26922
- return await fn();
26923
- } finally {
26924
- this.release();
26925
- }
26926
- }
26927
- };
26928
-
26929
26956
  // ../../packages/ycodium-acp-executor/src/openCommands.ts
26930
26957
  function readOpenToolCalls(toolCalls, turnId) {
26931
26958
  const running = [];
@@ -27297,10 +27324,10 @@ function createAcpExecutor(options) {
27297
27324
  setNativeMode,
27298
27325
  compact,
27299
27326
  openToolCalls: () => readOpenToolCalls(toolCalls, shared.activeTurnId),
27300
- dispose: () => {
27327
+ dispose: (exitCode) => {
27301
27328
  disposeOnce ??= (async () => {
27302
27329
  try {
27303
- await disposeLifecycle();
27330
+ await disposeLifecycle(exitCode);
27304
27331
  } finally {
27305
27332
  await protocolLogSink?.close();
27306
27333
  }
@@ -27311,7 +27338,8 @@ function createAcpExecutor(options) {
27311
27338
  }
27312
27339
 
27313
27340
  // ../../packages/ycodium-acp-executor/src/session-registry.ts
27314
- function createAcpSessionRegistry(threads, stopBooked2) {
27341
+ function createAcpSessionRegistry(threads, stopBooked2, log) {
27342
+ const exits = /* @__PURE__ */ new WeakMap();
27315
27343
  const requireThread = (threadId) => {
27316
27344
  const booked = threads.get(threadId);
27317
27345
  if (!booked) throw new Error(`unknown thread ${threadId}`);
@@ -27320,7 +27348,8 @@ function createAcpSessionRegistry(threads, stopBooked2) {
27320
27348
  };
27321
27349
  const stopSession = (threadId, booked = threads.get(threadId)) => {
27322
27350
  if (!booked) return Promise.resolve();
27323
- booked.closing ??= Promise.resolve().then(() => stopBooked2(booked)).then(() => {
27351
+ const close = { exitCode: exits.get(booked), hasExited: () => exits.has(booked) };
27352
+ booked.closing ??= Promise.resolve().then(() => stopBooked2(booked, close)).then(() => {
27324
27353
  if (threads.get(threadId) === booked) threads.delete(threadId);
27325
27354
  }).catch((cause) => {
27326
27355
  if (threads.get(threadId) === booked) delete booked.closing;
@@ -27331,7 +27360,16 @@ function createAcpSessionRegistry(threads, stopBooked2) {
27331
27360
  const stopAll = () => Promise.all([...threads].map(([threadId, booked]) => stopSession(threadId, booked))).then(
27332
27361
  () => void 0
27333
27362
  );
27334
- return { requireThread, stopSession, stopAll };
27363
+ const registerSession = (threadId, booked) => {
27364
+ threads.set(threadId, booked);
27365
+ void booked.handle.exited.then(async (exitCode) => {
27366
+ exits.set(booked, exitCode);
27367
+ await stopSession(threadId, booked);
27368
+ }).catch((cause) => {
27369
+ log?.warn("ACP process exit cleanup failed", { threadId, error: String(cause) });
27370
+ });
27371
+ };
27372
+ return { requireThread, registerSession, stopSession, stopAll };
27335
27373
  }
27336
27374
 
27337
27375
  // ../../packages/ycodium-acp-executor/src/session-cleanup.ts
@@ -27344,8 +27382,11 @@ async function cleanupAcpSession(input2) {
27344
27382
  failures.push(new Error(`forwarding failed: ${String(cause)}`, { cause }));
27345
27383
  });
27346
27384
  for (const [step, cleanup] of [
27347
- ["executor.dispose", () => input2.executor.dispose()],
27348
- ["stopProcess", input2.stopProcess],
27385
+ ["executor.dispose", () => input2.executor.dispose(input2.processExit?.exitCode)],
27386
+ [
27387
+ "stopProcess",
27388
+ () => input2.processExit?.hasExited() ? Promise.resolve() : input2.stopProcess()
27389
+ ],
27349
27390
  ["forwarding", () => forwarding]
27350
27391
  ]) {
27351
27392
  try {
@@ -28457,11 +28498,12 @@ function kimiHooks(recipe) {
28457
28498
  readContextWindow: ({ sessionId }) => readKimiContextWindow({ homePath, acpSessionId: sessionId })
28458
28499
  };
28459
28500
  }
28460
- async function stopBooked(booked) {
28501
+ async function stopBooked(booked, processExit) {
28461
28502
  await cleanupAcpSession({
28462
28503
  executor: booked.executor,
28463
28504
  stopProcess: () => booked.handle.kill("SIGTERM"),
28464
- forwarding: booked.forwarding
28505
+ forwarding: booked.forwarding,
28506
+ processExit
28465
28507
  });
28466
28508
  }
28467
28509
  var createKimiInstance = (config2, host) => {
@@ -28470,7 +28512,11 @@ var createKimiInstance = (config2, host) => {
28470
28512
  const threads = /* @__PURE__ */ new Map();
28471
28513
  let disposed = false;
28472
28514
  const usageHome = kimiEffectiveHome(resolveHomePath(recipe), process.env[recipe.homeEnvVar]);
28473
- const { requireThread, stopSession, stopAll } = createAcpSessionRegistry(threads, stopBooked);
28515
+ const { requireThread, registerSession, stopSession, stopAll } = createAcpSessionRegistry(
28516
+ threads,
28517
+ stopBooked,
28518
+ host.log
28519
+ );
28474
28520
  const disposeOnce = createRetryableClose(async () => {
28475
28521
  await stopAll();
28476
28522
  events.close();
@@ -28641,7 +28687,7 @@ var createKimiInstance = (config2, host) => {
28641
28687
  ...started.modelId === void 0 ? {} : { model: started.modelId },
28642
28688
  ...input2.bindingGeneration === void 0 ? {} : { bindingGeneration: input2.bindingGeneration }
28643
28689
  };
28644
- threads.set(input2.threadId, {
28690
+ registerSession(input2.threadId, {
28645
28691
  session,
28646
28692
  turns: [],
28647
28693
  executor,
@@ -28778,7 +28824,7 @@ var executors = [
28778
28824
  ];
28779
28825
  var index_default = definePlugin({
28780
28826
  id: "agent-kimi",
28781
- apiVersion: 25,
28827
+ apiVersion: 26,
28782
28828
  executors,
28783
28829
  activate(ctx) {
28784
28830
  ctx.log.info("Kimi Code executor ready");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ycodium-ai/agent-kimi",
3
- "version": "0.2.3236",
3
+ "version": "0.2.3240",
4
4
  "description": "Kimi Code executor: runs `kimi acp` over Agent Client Protocol stdio.",
5
5
  "keywords": [
6
6
  "ycodium",
@@ -21,9 +21,9 @@
21
21
  "@types/node": "24.12.4",
22
22
  "esbuild": "0.28.1",
23
23
  "vite-plus": "0.2.2",
24
- "@ycodium-ai/plugin-api": "0.2.3236",
25
- "ycodium-acp-executor": "0.2.3236",
26
- "ycodium-executor-testing": "0.0.0"
24
+ "@ycodium-ai/plugin-api": "0.2.3240",
25
+ "ycodium-executor-testing": "0.0.0",
26
+ "ycodium-acp-executor": "0.2.3240"
27
27
  },
28
28
  "ycodium": {
29
29
  "plugin": "./dist/index.js",