@ycodium-ai/agent-grok 0.2.3478 → 0.2.3502

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 +93 -80
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -27722,19 +27722,28 @@ function toAcpMcpServers(entries) {
27722
27722
  }
27723
27723
 
27724
27724
  // ../../packages/ycodium-acp-executor/src/probe.ts
27725
- function withProbeTimeout(promise2, timeoutMs, what) {
27725
+ function withProbeTimeout(promise2, timeoutMs, what, signal) {
27726
+ signal?.throwIfAborted();
27726
27727
  return new Promise((resolve2, reject) => {
27728
+ const onAbort = () => {
27729
+ clearTimeout(timer);
27730
+ reject(signal?.reason ?? new Error("aborted"));
27731
+ };
27727
27732
  const timer = setTimeout(() => {
27733
+ signal?.removeEventListener("abort", onAbort);
27728
27734
  reject(new Error(`${what} timed out after ${timeoutMs}ms`));
27729
27735
  }, timeoutMs);
27730
27736
  timer.unref?.();
27737
+ signal?.addEventListener("abort", onAbort, { once: true });
27731
27738
  promise2.then(
27732
27739
  (value) => {
27733
27740
  clearTimeout(timer);
27741
+ signal?.removeEventListener("abort", onAbort);
27734
27742
  resolve2(value);
27735
27743
  },
27736
27744
  (error62) => {
27737
27745
  clearTimeout(timer);
27746
+ signal?.removeEventListener("abort", onAbort);
27738
27747
  reject(error62 instanceof Error ? error62 : new Error(String(error62)));
27739
27748
  }
27740
27749
  );
@@ -27750,14 +27759,16 @@ async function openAcpProbeHandshake(input2) {
27750
27759
  const initializeResult = await withProbeTimeout(
27751
27760
  connection.request("initialize", acpInitializePayload(input2.clientInfo)),
27752
27761
  input2.requestTimeoutMs,
27753
- "ACP probe request 'initialize'"
27762
+ "ACP probe request 'initialize'",
27763
+ input2.signal
27754
27764
  );
27755
27765
  return {
27756
27766
  initializeResult,
27757
27767
  request: (method, params) => withProbeTimeout(
27758
27768
  connection.request(method, params),
27759
27769
  input2.requestTimeoutMs,
27760
- `ACP probe request '${method}'`
27770
+ `ACP probe request '${method}'`,
27771
+ input2.signal
27761
27772
  ),
27762
27773
  close: () => connection.close()
27763
27774
  };
@@ -27781,42 +27792,50 @@ async function collectCappedText(stream, maxBytes) {
27781
27792
  return { text: text3 + decoder.decode(), overflowed: total > maxBytes };
27782
27793
  }
27783
27794
  async function collectProbeProcess(child, input2) {
27795
+ const stdinClosed = Promise.resolve().then(() => child.closeStdin());
27796
+ const stdout = collectCappedText(child.stdout, input2.maxOutputBytes);
27797
+ const stderr = collectCappedText(child.stderr, input2.maxOutputBytes);
27798
+ const tasks = [stdinClosed, stdout, stderr, child.exited];
27799
+ let result;
27800
+ let bodyFailed = false;
27801
+ let bodyError;
27784
27802
  try {
27785
- await child.closeStdin().catch(() => void 0);
27786
- const [stdout, stderr, exitCode] = await withProbeTimeout(
27787
- Promise.all([
27788
- collectCappedText(child.stdout, input2.maxOutputBytes),
27789
- collectCappedText(child.stderr, input2.maxOutputBytes),
27790
- child.exited
27791
- ]),
27803
+ const [, out, err, exitCode] = await withProbeTimeout(
27804
+ Promise.all(tasks),
27792
27805
  input2.timeoutMs,
27793
- input2.what
27806
+ input2.what,
27807
+ input2.signal
27794
27808
  );
27795
- return { stdout: stdout.overflowed ? void 0 : stdout.text, stderr: stderr.text, exitCode };
27796
- } finally {
27797
- await child.kill("SIGTERM").catch(() => void 0);
27798
- }
27799
- }
27800
- var MAX_VERSION_OUTPUT_BYTES = 64 * 1024;
27801
- async function probeCliVersion(input2) {
27802
- let child;
27803
- try {
27804
- child = await input2.spawn();
27805
- } catch {
27806
- return null;
27809
+ result = { stdout: out.overflowed ? void 0 : out.text, stderr: err.text, exitCode };
27810
+ } catch (error62) {
27811
+ bodyFailed = true;
27812
+ bodyError = error62;
27807
27813
  }
27814
+ const term = Promise.resolve().then(() => child.kill("SIGTERM"));
27815
+ void term.catch(() => void 0);
27816
+ const cleanup = (async () => {
27817
+ try {
27818
+ await withProbeTimeout(child.exited, 250, `${input2.what} termination grace`);
27819
+ } catch {
27820
+ await child.kill("SIGKILL");
27821
+ }
27822
+ const settled = await Promise.allSettled([term, ...tasks]);
27823
+ const termination = settled[0];
27824
+ if (termination?.status === "rejected") throw termination.reason;
27825
+ })();
27808
27826
  try {
27809
- const run = await collectProbeProcess(child, {
27810
- timeoutMs: input2.timeoutMs,
27811
- maxOutputBytes: MAX_VERSION_OUTPUT_BYTES,
27812
- what: "--version"
27813
- });
27814
- if (run.exitCode !== 0) return null;
27815
- return parseCliVersion(run.stdout ?? "") ?? parseCliVersion(run.stderr);
27816
- } catch {
27817
- return null;
27827
+ await withProbeTimeout(cleanup, input2.cleanupTimeoutMs ?? 5e3, `${input2.what} cleanup`);
27828
+ } catch (cleanupError) {
27829
+ throw new AggregateError(
27830
+ bodyFailed ? [bodyError, cleanupError] : [cleanupError],
27831
+ `${input2.what} cleanup failed`,
27832
+ { cause: cleanupError }
27833
+ );
27818
27834
  }
27835
+ if (bodyFailed) throw bodyError;
27836
+ return result;
27819
27837
  }
27838
+ var MAX_VERSION_OUTPUT_BYTES = 64 * 1024;
27820
27839
 
27821
27840
  // src/config.ts
27822
27841
  var GROK_DEFAULT_LAUNCH_ARGS = "agent stdio";
@@ -29098,6 +29117,10 @@ function grokOpenCommands(session) {
29098
29117
  }
29099
29118
 
29100
29119
  // src/modelCacheRefresh.ts
29120
+ import {
29121
+ runProcessOperation as runProcessOperation2,
29122
+ OperationCleanupError as OperationCleanupError2
29123
+ } from "@ycodium-ai/plugin-api/process-operation";
29101
29124
  import * as NodeFS4 from "node:fs";
29102
29125
  import * as NodePath7 from "node:path";
29103
29126
  import {
@@ -29107,6 +29130,10 @@ import {
29107
29130
  } from "@ycodium-ai/plugin-api/executor";
29108
29131
 
29109
29132
  // src/probeModels.ts
29133
+ import {
29134
+ runProcessOperation,
29135
+ OperationCleanupError
29136
+ } from "@ycodium-ai/plugin-api/process-operation";
29110
29137
  import {
29111
29138
  describeExecutorSpawnFailure,
29112
29139
  ExecutorSpawnAbortedError,
@@ -29166,16 +29193,22 @@ async function probeGrokModels(input2) {
29166
29193
  }
29167
29194
  async function probeGrokVersion(input2) {
29168
29195
  const { recipe, host, env, signal } = input2;
29169
- return probeCliVersion({
29170
- spawn: () => host.process.spawn({
29196
+ try {
29197
+ const run = await runProcessOperation(host, {
29171
29198
  program: recipe.binaryPath,
29172
29199
  args: ["--version"],
29173
29200
  owner: { bindingId: host.bindingId },
29174
29201
  ...Object.keys(env).length > 0 ? { env } : {},
29175
- ...signal === void 0 ? {} : { signal }
29176
- }),
29177
- timeoutMs: PROBE_REQUEST_TIMEOUT_MS
29178
- });
29202
+ signal,
29203
+ timeoutMs: PROBE_REQUEST_TIMEOUT_MS,
29204
+ maxOutputBytes: 64 * 1024
29205
+ });
29206
+ if (run.exitCode !== 0) return null;
29207
+ return parseCliVersion(run.stdout) ?? parseCliVersion(run.stderr);
29208
+ } catch (error62) {
29209
+ if (error62 instanceof OperationCleanupError || signal?.aborted) throw error62;
29210
+ return null;
29211
+ }
29179
29212
  }
29180
29213
 
29181
29214
  // src/modelCacheRefresh.ts
@@ -29198,58 +29231,33 @@ function grokModelCacheNeedsRefresh(input2) {
29198
29231
  if (input2.nowMs - input2.cacheMtimeMs > GROK_MODEL_CACHE_MAX_AGE_MS) return true;
29199
29232
  return input2.lastSeenCliVersion !== null && input2.cliVersion !== null && input2.cliVersion !== input2.lastSeenCliVersion;
29200
29233
  }
29201
- async function drain(stream) {
29202
- for await (const chunk of stream) {
29203
- void chunk;
29204
- }
29205
- }
29206
29234
  async function runGrokModelsCommand(input2) {
29207
29235
  const { recipe, host, env } = input2;
29208
29236
  throwIfExecutorSpawnAborted(input2.signal);
29209
- let handle;
29210
29237
  try {
29211
- handle = await host.process.spawn({
29238
+ const run = await runProcessOperation2(host, {
29212
29239
  program: recipe.binaryPath,
29213
29240
  args: ["models"],
29214
29241
  cwd: process.cwd(),
29215
29242
  owner: { bindingId: host.bindingId },
29216
29243
  ...Object.keys(env).length > 0 ? { env } : {},
29217
- ...input2.signal === void 0 ? {} : { signal: input2.signal }
29218
- });
29219
- } catch (error62) {
29220
- if (error62 instanceof ExecutorSpawnAbortedError2) throw error62;
29221
- host.log.warn("grok models could not be started; keeping the previous model list", {
29222
- detail: error62 instanceof ExecutorSpawnRefusedError2 ? "process limit" : String(error62)
29244
+ signal: input2.signal,
29245
+ timeoutMs: GROK_MODELS_COMMAND_TIMEOUT_MS
29223
29246
  });
29224
- return false;
29225
- }
29226
- const finished = Promise.all([drain(handle.stdout), drain(handle.stderr), handle.exited]).then(
29227
- ([, , code]) => code
29228
- );
29229
- let timer;
29230
- const timeout = new Promise((resolve2) => {
29231
- timer = setTimeout(() => resolve2("timeout"), GROK_MODELS_COMMAND_TIMEOUT_MS);
29232
- timer.unref?.();
29233
- });
29234
- try {
29235
- const outcome = await Promise.race([finished, timeout]);
29236
- if (outcome === "timeout") {
29237
- finished.catch(() => void 0);
29238
- host.log.warn("grok models timed out; keeping the previous model list", {
29239
- timeoutMs: GROK_MODELS_COMMAND_TIMEOUT_MS
29240
- });
29241
- return false;
29242
- }
29243
- if (outcome !== 0) {
29247
+ if (run.exitCode !== 0) {
29244
29248
  host.log.warn("grok models exited non-zero; keeping the previous model list", {
29245
- exitCode: outcome
29249
+ exitCode: run.exitCode
29246
29250
  });
29247
29251
  return false;
29248
29252
  }
29249
29253
  return true;
29250
- } finally {
29251
- if (timer !== void 0) clearTimeout(timer);
29252
- await handle.kill("SIGTERM").catch(() => void 0);
29254
+ } catch (error62) {
29255
+ if (error62 instanceof ExecutorSpawnAbortedError2 || error62 instanceof OperationCleanupError2 || input2.signal?.aborted)
29256
+ throw error62;
29257
+ host.log.warn("grok models failed; keeping the previous model list", {
29258
+ detail: error62 instanceof ExecutorSpawnRefusedError2 ? "process limit" : String(error62)
29259
+ });
29260
+ return false;
29253
29261
  }
29254
29262
  }
29255
29263
  var modelsCommandSlots = /* @__PURE__ */ new Map();
@@ -29295,7 +29303,7 @@ function createGrokModelCatalog(input2) {
29295
29303
  };
29296
29304
  const refreshModelCatalog = async (request) => {
29297
29305
  try {
29298
- const cliVersion = request.cliVersion !== void 0 ? request.cliVersion : await readCliVersion();
29306
+ const cliVersion = request.cliVersion !== void 0 ? request.cliVersion : await readCliVersion(request.signal);
29299
29307
  if (!request.force && skipUnforced) {
29300
29308
  skipUnforced = false;
29301
29309
  if (cliVersion !== null) lastSeenCliVersion = cliVersion;
@@ -29327,7 +29335,8 @@ function createGrokModelCatalog(input2) {
29327
29335
  throw new Error("grok models failed");
29328
29336
  }
29329
29337
  } catch (error62) {
29330
- if (error62 instanceof ExecutorSpawnAbortedError2) throw error62;
29338
+ if (error62 instanceof ExecutorSpawnAbortedError2 || error62 instanceof OperationCleanupError2 || request.signal?.aborted)
29339
+ throw error62;
29331
29340
  if (request.surfaceErrors === true) throw error62;
29332
29341
  input2.host.log.warn("grok model cache refresh failed; keeping the previous model list", {
29333
29342
  detail: error62 instanceof Error ? error62.message : String(error62)
@@ -29506,8 +29515,12 @@ var createGrokInstance = (config2, host) => {
29506
29515
  const signIn = makeGrokSignIn({ host, recipe, probe, isDisposed: () => disposed });
29507
29516
  const instance = {
29508
29517
  probe,
29509
- readCliVersion: () => modelCatalog.readCliVersion(),
29510
- refreshModelCatalog: ({ force }) => modelCatalog.refreshModelCatalog({ force, armProbeSkip: force }),
29518
+ readCliVersion: (signal) => modelCatalog.readCliVersion(signal),
29519
+ refreshModelCatalog: ({ force, signal }) => modelCatalog.refreshModelCatalog({
29520
+ force,
29521
+ armProbeSkip: force,
29522
+ ...signal === void 0 ? {} : { signal }
29523
+ }),
29511
29524
  // 项目里的技能:探测在 home 下跑 inspect 只看得到整机的;这里在项目目录里再跑一次。
29512
29525
  workspaceInventory: ({ cwd }) => {
29513
29526
  if (recipe.binaryPath.length === 0) {
@@ -29806,7 +29819,7 @@ var executors = [
29806
29819
  ];
29807
29820
  var index_default = definePlugin({
29808
29821
  id: "agent-grok",
29809
- apiVersion: 39,
29822
+ apiVersion: 41,
29810
29823
  executors,
29811
29824
  activate(ctx) {
29812
29825
  ctx.log.info("grok executor ready");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ycodium-ai/agent-grok",
3
- "version": "0.2.3478",
3
+ "version": "0.2.3502",
4
4
  "description": "Grok executor: grok 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.3478",
25
- "ycodium-acp-executor": "0.2.3478",
24
+ "@ycodium-ai/plugin-api": "0.2.3502",
25
+ "ycodium-acp-executor": "0.2.3502",
26
26
  "ycodium-executor-testing": "0.0.0"
27
27
  },
28
28
  "ycodium": {