@ycodium-ai/agent-dsh 0.2.2126 → 0.2.2143

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 +111 -9
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -23721,6 +23721,7 @@ function createAcpConnection(options) {
23721
23721
  options.readable.off("data", onData);
23722
23722
  options.readable.off("end", onEnd);
23723
23723
  options.readable.off("error", onError);
23724
+ options.writable.off("error", onWritableError);
23724
23725
  try {
23725
23726
  await byteWriter.close();
23726
23727
  } catch {
@@ -23859,8 +23860,17 @@ function createAcpConnection(options) {
23859
23860
  endInboundBatch();
23860
23861
  }
23861
23862
  };
23863
+ const failInbound = (error62) => {
23864
+ if (closedError !== void 0) return;
23865
+ options.onInboundFailure?.(error62);
23866
+ void shutdown(
23867
+ new AcpConnectionClosedError(
23868
+ `ACP inbound handling failed: ${error62 instanceof Error ? error62.message : String(error62)}`
23869
+ )
23870
+ );
23871
+ };
23862
23872
  const enqueueInbound = (work) => {
23863
- inboundTail = inboundTail.then(work, work);
23873
+ inboundTail = inboundTail.then(work).catch(failInbound);
23864
23874
  };
23865
23875
  const onData = (chunk) => {
23866
23876
  if (closedError !== void 0) {
@@ -23910,9 +23920,15 @@ function createAcpConnection(options) {
23910
23920
  );
23911
23921
  });
23912
23922
  };
23923
+ const onWritableError = (error62) => {
23924
+ void shutdown(
23925
+ error62 instanceof Error ? error62 : new AcpConnectionClosedError("ACP output stream error")
23926
+ );
23927
+ };
23913
23928
  options.readable.on("data", onData);
23914
23929
  options.readable.on("end", onEnd);
23915
23930
  options.readable.on("error", onError);
23931
+ options.writable.once("error", onWritableError);
23916
23932
  const request = (async (method, params) => {
23917
23933
  failIfClosed();
23918
23934
  const id = nextRequestId;
@@ -23921,7 +23937,7 @@ function createAcpConnection(options) {
23921
23937
  pending.set(String(id), { method, resolve: resolve2, reject });
23922
23938
  const message = params === void 0 ? { jsonrpc: "2.0", id, method } : { jsonrpc: "2.0", id, method, params };
23923
23939
  try {
23924
- await writeMessage(message);
23940
+ await Promise.race([writeMessage(message), promise2]);
23925
23941
  } catch (error62) {
23926
23942
  if (pending.delete(String(id))) {
23927
23943
  reject(error62);
@@ -25704,6 +25720,12 @@ function createAcpExecutor(options) {
25704
25720
  const connection = createAcpConnection({
25705
25721
  readable: options.readable,
25706
25722
  writable: options.writable,
25723
+ onInboundFailure: (error62) => {
25724
+ options.log?.warn?.("acp connection closed: an inbound request could not be answered", {
25725
+ threadId: options.threadId,
25726
+ error: error62 instanceof Error ? error62.message : String(error62)
25727
+ });
25728
+ },
25707
25729
  onNotification: (notification) => {
25708
25730
  if (notification.method === "session/update") {
25709
25731
  handleSessionUpdate(notification.params);
@@ -26341,10 +26363,10 @@ function createAcpExecutor(options) {
26341
26363
  }
26342
26364
 
26343
26365
  // ../../packages/ycodium-acp-executor/src/probe.ts
26344
- function withProbeTimeout(promise2, timeoutMs, method) {
26366
+ function withProbeTimeout(promise2, timeoutMs, what) {
26345
26367
  return new Promise((resolve2, reject) => {
26346
26368
  const timer = setTimeout(() => {
26347
- reject(new Error(`ACP probe request '${method}' timed out after ${timeoutMs}ms`));
26369
+ reject(new Error(`${what} timed out after ${timeoutMs}ms`));
26348
26370
  }, timeoutMs);
26349
26371
  timer.unref?.();
26350
26372
  promise2.then(
@@ -26369,11 +26391,15 @@ async function openAcpProbeHandshake(input2) {
26369
26391
  const initializeResult = await withProbeTimeout(
26370
26392
  connection.request("initialize", acpInitializePayload(input2.clientInfo)),
26371
26393
  input2.requestTimeoutMs,
26372
- "initialize"
26394
+ "ACP probe request 'initialize'"
26373
26395
  );
26374
26396
  return {
26375
26397
  initializeResult,
26376
- request: (method, params) => withProbeTimeout(connection.request(method, params), input2.requestTimeoutMs, method),
26398
+ request: (method, params) => withProbeTimeout(
26399
+ connection.request(method, params),
26400
+ input2.requestTimeoutMs,
26401
+ `ACP probe request '${method}'`
26402
+ ),
26377
26403
  close: () => connection.close()
26378
26404
  };
26379
26405
  } catch (error62) {
@@ -26381,6 +26407,57 @@ async function openAcpProbeHandshake(input2) {
26381
26407
  throw error62;
26382
26408
  }
26383
26409
  }
26410
+ var CLI_VERSION_PATTERN = /(?<![\d.])(\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?)/;
26411
+ function parseCliVersion(output2) {
26412
+ return CLI_VERSION_PATTERN.exec(output2)?.[1] ?? null;
26413
+ }
26414
+ async function collectCappedText(stream, maxBytes) {
26415
+ const decoder = new TextDecoder();
26416
+ let text = "";
26417
+ let total = 0;
26418
+ for await (const chunk of stream) {
26419
+ total += chunk.byteLength;
26420
+ if (total <= maxBytes) text += decoder.decode(chunk, { stream: true });
26421
+ }
26422
+ return { text: text + decoder.decode(), overflowed: total > maxBytes };
26423
+ }
26424
+ async function collectProbeProcess(child, input2) {
26425
+ try {
26426
+ await child.closeStdin().catch(() => void 0);
26427
+ const [stdout, stderr, exitCode] = await withProbeTimeout(
26428
+ Promise.all([
26429
+ collectCappedText(child.stdout, input2.maxOutputBytes),
26430
+ collectCappedText(child.stderr, input2.maxOutputBytes),
26431
+ child.exited
26432
+ ]),
26433
+ input2.timeoutMs,
26434
+ input2.what
26435
+ );
26436
+ return { stdout: stdout.overflowed ? void 0 : stdout.text, stderr: stderr.text, exitCode };
26437
+ } finally {
26438
+ await child.kill("SIGTERM").catch(() => void 0);
26439
+ }
26440
+ }
26441
+ var MAX_VERSION_OUTPUT_BYTES = 64 * 1024;
26442
+ async function probeCliVersion(input2) {
26443
+ let child;
26444
+ try {
26445
+ child = await input2.spawn();
26446
+ } catch {
26447
+ return null;
26448
+ }
26449
+ try {
26450
+ const run = await collectProbeProcess(child, {
26451
+ timeoutMs: input2.timeoutMs,
26452
+ maxOutputBytes: MAX_VERSION_OUTPUT_BYTES,
26453
+ what: "--version"
26454
+ });
26455
+ if (run.exitCode !== 0) return null;
26456
+ return parseCliVersion(run.stdout ?? "") ?? parseCliVersion(run.stderr);
26457
+ } catch {
26458
+ return null;
26459
+ }
26460
+ }
26384
26461
 
26385
26462
  // src/config.ts
26386
26463
  var DSH_DEFAULT_LAUNCH_ARGS = "--profile acp";
@@ -26482,6 +26559,9 @@ function tokenizeLaunchArgs(value) {
26482
26559
  import * as NodeFS from "node:fs";
26483
26560
  import * as NodeOS2 from "node:os";
26484
26561
  import * as NodePath2 from "node:path";
26562
+ import {
26563
+ ExecutorSpawnRefusedError
26564
+ } from "@ycodium-ai/plugin-api/executor";
26485
26565
  import { nodeStreamsFromHandle } from "@ycodium-ai/plugin-api/process-stdin";
26486
26566
 
26487
26567
  // src/spawnEnv.ts
@@ -26540,6 +26620,10 @@ function resolveHomePath(value) {
26540
26620
  if (trimmed.length === 0) return "";
26541
26621
  return NodePath.resolve(expandHomePath(trimmed));
26542
26622
  }
26623
+ function dshContinuationKey(homePath) {
26624
+ const resolved = resolveHomePath(homePath);
26625
+ return `dsh:home:${resolved.length > 0 ? resolved : NodePath.join(NodeOS.homedir(), ".dsh")}`;
26626
+ }
26543
26627
  function buildSpawnEnv(recipe, resolvedHomePath, launchEnv = {}, nativeModeId) {
26544
26628
  const homeEnvVar = recipe.homeEnvVar.trim() || DSH_CARD.homeEnvVar;
26545
26629
  const homeInjection = resolvedHomePath.length > 0 && homeEnvVar.length > 0 ? { [homeEnvVar]: resolvedHomePath } : {};
@@ -26635,6 +26719,7 @@ async function probeDshModels(input2) {
26635
26719
  ...Object.keys(env).length > 0 ? { env } : {}
26636
26720
  });
26637
26721
  } catch (error62) {
26722
+ if (error62 instanceof ExecutorSpawnRefusedError) throw error62;
26638
26723
  return { kind: "not-started", detail: failureDetail(error62) };
26639
26724
  }
26640
26725
  let handshake;
@@ -26657,6 +26742,19 @@ async function probeDshModels(input2) {
26657
26742
  await handle.kill("SIGTERM").catch(() => void 0);
26658
26743
  }
26659
26744
  }
26745
+ async function probeDshVersion(input2) {
26746
+ const { recipe, host } = input2;
26747
+ const env = buildSpawnEnv(recipe, resolveHomePath(recipe.homePath));
26748
+ return probeCliVersion({
26749
+ spawn: () => host.process.spawn({
26750
+ program: recipe.binaryPath,
26751
+ args: ["--version"],
26752
+ owner: { bindingId: host.bindingId },
26753
+ ...Object.keys(env).length > 0 ? { env } : {}
26754
+ }),
26755
+ timeoutMs: PROBE_REQUEST_TIMEOUT_MS
26756
+ });
26757
+ }
26660
26758
 
26661
26759
  // src/dshInstance.ts
26662
26760
  var RESUME_SCHEMA_VERSION = 1;
@@ -26731,11 +26829,14 @@ var createDshInstance = (config2, host) => {
26731
26829
  detail: "DeepSeek Harness program path is not configured"
26732
26830
  };
26733
26831
  }
26734
- const outcome = await probeDshModels({ recipe, host });
26832
+ const [outcome, version2] = await Promise.all([
26833
+ probeDshModels({ recipe, host }),
26834
+ probeDshVersion({ recipe, host })
26835
+ ]);
26735
26836
  if (outcome.kind !== "answered") {
26736
26837
  return {
26737
26838
  installed: outcome.kind === "failed",
26738
- version: null,
26839
+ version: version2,
26739
26840
  readiness: "error",
26740
26841
  auth: { status: "unknown" },
26741
26842
  ...outcome.detail === void 0 ? {} : { detail: outcome.detail },
@@ -26745,7 +26846,7 @@ var createDshInstance = (config2, host) => {
26745
26846
  }
26746
26847
  return {
26747
26848
  installed: true,
26748
- version: null,
26849
+ version: version2,
26749
26850
  readiness: "ready",
26750
26851
  auth: { status: "unknown" },
26751
26852
  ...outcome.models === void 0 ? {} : { models: outcome.models },
@@ -26919,6 +27020,7 @@ var createDshInstance = (config2, host) => {
26919
27020
  return { threadId, turns: booked.turns };
26920
27021
  },
26921
27022
  events,
27023
+ continuationKey: dshContinuationKey(recipe.homePath),
26922
27024
  dispose: async () => {
26923
27025
  if (disposed) return;
26924
27026
  disposed = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ycodium-ai/agent-dsh",
3
- "version": "0.2.2126",
3
+ "version": "0.2.2143",
4
4
  "description": "DeepSeek Harness executor: dsh CLI over Agent Client Protocol stdio.",
5
5
  "keywords": [
6
6
  "ycodium",
@@ -20,8 +20,8 @@
20
20
  "@types/node": "24.12.4",
21
21
  "esbuild": "0.28.1",
22
22
  "vite-plus": "0.2.2",
23
+ "@ycodium-ai/plugin-api": "0.2.2143",
23
24
  "ycodium-acp-executor": "0.0.0",
24
- "@ycodium-ai/plugin-api": "0.2.2126",
25
25
  "ycodium-acp-protocol": "0.0.0"
26
26
  },
27
27
  "ycodium": {