@ycodium-ai/agent-dsh 0.2.2808 → 0.2.2834

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 +80 -66
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -23988,22 +23988,28 @@ function createAcpConnection(options) {
23988
23988
  options.readable.on("end", onEnd);
23989
23989
  options.readable.on("error", onError);
23990
23990
  options.writable.once("error", onWritableError);
23991
- const request = (async (method, params) => {
23991
+ const begin = (method, params) => {
23992
23992
  failIfClosed();
23993
23993
  const id = nextRequestId;
23994
23994
  nextRequestId += 1;
23995
23995
  const { promise: promise2, resolve: resolve2, reject } = Promise.withResolvers();
23996
23996
  pending.set(String(id), { method, resolve: resolve2, reject });
23997
23997
  const message = params === void 0 ? { jsonrpc: "2.0", id, method } : { jsonrpc: "2.0", id, method, params };
23998
- try {
23999
- await Promise.race([writeMessage(message), promise2]);
24000
- } catch (error62) {
24001
- if (pending.delete(String(id))) {
24002
- reject(error62);
23998
+ const written = Promise.race([writeMessage(message), promise2]).then(
23999
+ () => void 0,
24000
+ (error62) => {
24001
+ if (pending.delete(String(id))) {
24002
+ reject(error62);
24003
+ }
24004
+ throw error62;
24003
24005
  }
24004
- throw error62;
24005
- }
24006
- return promise2;
24006
+ );
24007
+ return { written, response: promise2 };
24008
+ };
24009
+ const request = (async (method, params) => {
24010
+ const { written, response } = begin(method, params);
24011
+ await written;
24012
+ return response;
24007
24013
  });
24008
24014
  const notify = async (method, params) => {
24009
24015
  failIfClosed();
@@ -24024,6 +24030,7 @@ function createAcpConnection(options) {
24024
24030
  const close = (error62) => shutdown(error62 ?? new AcpConnectionClosedError());
24025
24031
  return {
24026
24032
  request,
24033
+ begin,
24027
24034
  notify,
24028
24035
  awaitInboundIdle,
24029
24036
  close,
@@ -25381,6 +25388,13 @@ function modelSelectionStateFromSetup(setup) {
25381
25388
  };
25382
25389
  }
25383
25390
 
25391
+ // ../../packages/ycodium-acp-executor/src/user-input-pending.ts
25392
+ var userInputAnswerOptionId = (question, answers) => {
25393
+ const answer = answers[question.id];
25394
+ const selected = typeof answer === "string" ? answer : Array.isArray(answer) && answer.length === 1 && typeof answer[0] === "string" ? answer[0] : void 0;
25395
+ return selected !== void 0 && question.options.some((option) => option.id === selected) ? selected : void 0;
25396
+ };
25397
+
25384
25398
  // ../../packages/ycodium-acp-executor/src/vendor-hooks.ts
25385
25399
  var defaultVendorHooks = {
25386
25400
  completedStopReason: (response) => response.stopReason
@@ -25388,11 +25402,6 @@ var defaultVendorHooks = {
25388
25402
 
25389
25403
  // ../../packages/ycodium-acp-executor/src/executor.ts
25390
25404
  var DEFAULT_CANCEL_GRACE_MS = 5e3;
25391
- var userInputAnswerOptionId = (question, answers) => {
25392
- const answer = answers[question.id];
25393
- const selected = typeof answer === "string" ? answer : Array.isArray(answer) && answer.length === 1 && typeof answer[0] === "string" ? answer[0] : void 0;
25394
- return selected !== void 0 && question.options.some((option) => option.id === selected) ? selected : void 0;
25395
- };
25396
25405
  function defaultNowIso() {
25397
25406
  return (/* @__PURE__ */ new Date()).toISOString();
25398
25407
  }
@@ -26216,7 +26225,7 @@ function createAcpExecutor(options) {
26216
26225
  };
26217
26226
  const settleTurn = (input2) => {
26218
26227
  if (!isLive(input2.expectedGeneration)) {
26219
- return;
26228
+ return false;
26220
26229
  }
26221
26230
  if (!acpPromptSettlementBelongsToContext({
26222
26231
  liveAcpSessionId: sessionId ?? "",
@@ -26225,37 +26234,40 @@ function createAcpExecutor(options) {
26225
26234
  liveSessionActiveTurnId: activeTurnId,
26226
26235
  turnId: input2.turnId
26227
26236
  })) {
26228
- return;
26237
+ return false;
26229
26238
  }
26230
26239
  closeActiveAssistantSegment(input2.turnId);
26231
26240
  promptsInFlight = Math.max(0, promptsInFlight - 1);
26232
- if (promptsInFlight === 0 && activeTurnId === input2.turnId) {
26233
- activeTurnId = void 0;
26234
- if (status !== "disposed") {
26235
- status = "ready";
26236
- }
26237
- emit({
26238
- type: "turn.completed",
26239
- ...stamp(),
26240
- provider: options.provider,
26241
- threadId: options.threadId,
26242
- turnId: input2.turnId,
26243
- payload: {
26244
- state: input2.state,
26245
- stopReason: input2.stopReason
26246
- }
26247
- });
26248
- interruptedTurnIds.delete(input2.turnId);
26241
+ if (promptsInFlight !== 0 || activeTurnId !== input2.turnId) return false;
26242
+ activeTurnId = void 0;
26243
+ if (status !== "disposed") {
26244
+ status = "ready";
26249
26245
  }
26246
+ emit({
26247
+ type: "turn.completed",
26248
+ ...stamp(),
26249
+ provider: options.provider,
26250
+ threadId: options.threadId,
26251
+ turnId: input2.turnId,
26252
+ payload: {
26253
+ state: input2.state,
26254
+ stopReason: input2.stopReason,
26255
+ ...input2.errorMessage === void 0 ? {} : { errorMessage: input2.errorMessage }
26256
+ }
26257
+ });
26258
+ interruptedTurnIds.delete(input2.turnId);
26259
+ return true;
26250
26260
  };
26251
- const sendPromptRpc = async (sessionId2, promptParts) => {
26261
+ const sendPromptRpc = async (sessionId2, promptParts, onWritten) => {
26252
26262
  const settlementHooks = hooks.promptSettlement;
26253
26263
  const promptKey = settlementHooks === void 0 ? void 0 : randomId();
26254
- const promptRpc = connection.request("session/prompt", {
26264
+ const pending = connection.begin("session/prompt", {
26255
26265
  sessionId: sessionId2,
26256
26266
  prompt: promptParts,
26257
26267
  ...settlementHooks !== void 0 && promptKey !== void 0 ? settlementHooks.requestFields(promptKey) : {}
26258
26268
  });
26269
+ void pending.written.then(onWritten, () => void 0);
26270
+ const promptRpc = pending.response;
26259
26271
  if (settlementHooks === void 0 || promptKey === void 0) {
26260
26272
  return await promptRpc;
26261
26273
  } else {
@@ -26281,6 +26293,11 @@ function createAcpExecutor(options) {
26281
26293
  const prompt = async (input2) => {
26282
26294
  failIfDisposed();
26283
26295
  const started = requireStarted();
26296
+ const settle2 = (rest) => settleTurn({
26297
+ expectedGeneration: started.generation,
26298
+ expectedSessionId: started.sessionId,
26299
+ ...rest
26300
+ });
26284
26301
  let turnId;
26285
26302
  await threadMutex.acquire();
26286
26303
  try {
@@ -26308,13 +26325,7 @@ function createAcpExecutor(options) {
26308
26325
  try {
26309
26326
  failIfDisposed();
26310
26327
  if (interruptedTurnIds.has(turnId)) {
26311
- settleTurn({
26312
- expectedGeneration: started.generation,
26313
- expectedSessionId: started.sessionId,
26314
- turnId,
26315
- stopReason: "cancelled",
26316
- state: "cancelled"
26317
- });
26328
+ settle2({ turnId, stopReason: "cancelled", state: "cancelled" });
26318
26329
  return {
26319
26330
  threadId: options.threadId,
26320
26331
  turnId,
@@ -26328,12 +26339,24 @@ function createAcpExecutor(options) {
26328
26339
  expectedGeneration: started.generation
26329
26340
  });
26330
26341
  closeActiveAssistantSegment(turnId);
26342
+ let written = false;
26331
26343
  try {
26332
- response = await sendPromptRpc(started.sessionId, promptParts);
26344
+ response = await sendPromptRpc(started.sessionId, promptParts, () => {
26345
+ written = true;
26346
+ input2.onDispatched?.(turnId);
26347
+ });
26333
26348
  } catch (error62) {
26334
26349
  if (disposed) {
26335
26350
  throw new AcpExecutorDisposedError();
26336
26351
  }
26352
+ if (written && input2.onDispatched !== void 0 && !interruptedTurnIds.has(turnId)) {
26353
+ const errorMessage = error62 instanceof Error && error62.message.trim() || "ACP prompt failed";
26354
+ if (settle2({ turnId, stopReason: "error", state: "failed", errorMessage }))
26355
+ options.log?.warn?.("turn failed after dispatch", {
26356
+ threadId: options.threadId,
26357
+ failure: errorMessage
26358
+ });
26359
+ }
26337
26360
  throw error62;
26338
26361
  }
26339
26362
  await connection.awaitInboundIdle();
@@ -26364,13 +26387,7 @@ function createAcpExecutor(options) {
26364
26387
  }
26365
26388
  const finishPrompt = () => {
26366
26389
  if (interruptedTurnIds.has(settledTurnId)) {
26367
- settleTurn({
26368
- expectedGeneration: started.generation,
26369
- expectedSessionId: started.sessionId,
26370
- turnId: settledTurnId,
26371
- stopReason: "cancelled",
26372
- state: "cancelled"
26373
- });
26390
+ settle2({ turnId: settledTurnId, stopReason: "cancelled", state: "cancelled" });
26374
26391
  return {
26375
26392
  threadId: options.threadId,
26376
26393
  turnId: settledTurnId,
@@ -26393,9 +26410,7 @@ function createAcpExecutor(options) {
26393
26410
  }
26394
26411
  });
26395
26412
  }
26396
- settleTurn({
26397
- expectedGeneration: started.generation,
26398
- expectedSessionId: started.sessionId,
26413
+ settle2({
26399
26414
  turnId: settledTurnId,
26400
26415
  stopReason,
26401
26416
  state: response.stopReason === "cancelled" ? "cancelled" : "completed"
@@ -26653,6 +26668,17 @@ function createAcpExecutor(options) {
26653
26668
  };
26654
26669
  }
26655
26670
 
26671
+ // ../../packages/ycodium-acp-executor/src/prompt-dispatch.ts
26672
+ var dispatchAcpPrompt = (executor, input2) => {
26673
+ const { promise: dispatched, resolve: resolve2 } = Promise.withResolvers();
26674
+ const finished = executor.prompt({ ...input2, onDispatched: resolve2 });
26675
+ return Promise.race([
26676
+ dispatched.then((turnId) => ({ turnId })),
26677
+ // 写入之前就落定:成功(写入前被取消)带 turnId;拒绝原样交给调用方,那是起轮失败。
26678
+ finished.then((result) => ({ turnId: result.turnId }))
26679
+ ]);
26680
+ };
26681
+
26656
26682
  // ../../packages/ycodium-acp-executor/src/mcp-servers.ts
26657
26683
  function toAcpMcpServers(entries) {
26658
26684
  return (entries ?? []).map(
@@ -27429,26 +27455,14 @@ var createDshInstance = (config2, host) => {
27429
27455
  void booked.executor.cancel(input2.expectedTurnId).catch(() => void 0);
27430
27456
  };
27431
27457
  signal?.addEventListener("abort", onAbort);
27432
- booked.session = {
27433
- ...booked.session,
27434
- status: "running",
27435
- updatedAt: nowIso()
27436
- };
27437
27458
  try {
27438
27459
  const requestedModelId = modelIdFromSelection(input2.modelSelection);
27439
- const turn = await booked.executor.prompt({
27460
+ const turn = await dispatchAcpPrompt(booked.executor, {
27440
27461
  text: input2.input ?? "",
27441
27462
  ...input2.expectedTurnId === void 0 ? {} : { turnId: input2.expectedTurnId },
27442
27463
  ...requestedModelId === void 0 ? {} : { requestedModelId }
27443
27464
  });
27444
- await yieldTick();
27445
27465
  booked.turns.push({ id: turn.turnId, items: [] });
27446
- booked.session = {
27447
- ...booked.session,
27448
- status: "idle",
27449
- updatedAt: nowIso(),
27450
- ...booked.executor.modelId === void 0 ? {} : { model: booked.executor.modelId }
27451
- };
27452
27466
  return {
27453
27467
  threadId: input2.threadId,
27454
27468
  turnId: turn.turnId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ycodium-ai/agent-dsh",
3
- "version": "0.2.2808",
3
+ "version": "0.2.2834",
4
4
  "description": "DeepSeek Harness executor: dsh CLI over Agent Client Protocol stdio.",
5
5
  "keywords": [
6
6
  "ycodium",
@@ -21,8 +21,8 @@
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.2808",
25
- "ycodium-acp-executor": "0.2.2808",
24
+ "@ycodium-ai/plugin-api": "0.2.2834",
25
+ "ycodium-acp-executor": "0.2.2834",
26
26
  "ycodium-executor-testing": "0.0.0"
27
27
  },
28
28
  "ycodium": {