@ycodium-ai/agent-codex 0.2.3252 → 0.2.3265

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 +95 -19
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -439,7 +439,15 @@ var probeCodexAccount = (accountPath) => {
439
439
  import * as NodeProcess from "node:process";
440
440
  import {
441
441
  describeExecutorSpawnFailure,
442
- ExecutorSpawnRefusedError
442
+ ExecutorSpawnRefusedError as ExecutorSpawnRefusedError2,
443
+ raceAbort
444
+ } from "@ycodium-ai/plugin-api/executor";
445
+
446
+ // src/appServerLaunch.ts
447
+ import {
448
+ ExecutorSpawnAbortedError,
449
+ ExecutorSpawnRefusedError,
450
+ throwIfExecutorSpawnAborted
443
451
  } from "@ycodium-ai/plugin-api/executor";
444
452
 
445
453
  // src/connection.ts
@@ -661,8 +669,14 @@ function shouldCrushApiKeys(authMode) {
661
669
  }
662
670
 
663
671
  // src/appServerLaunch.ts
672
+ function throwIfCodexSpawnControlled(error) {
673
+ if (error instanceof ExecutorSpawnRefusedError || error instanceof ExecutorSpawnAbortedError) {
674
+ throw error;
675
+ }
676
+ }
664
677
  async function spawnCodexAppServer(input) {
665
678
  await materializeCodexShadowHome(input.layout, input.host.log);
679
+ throwIfExecutorSpawnAborted(input.signal);
666
680
  const env = input.env ?? buildCodexSpawnEnv({
667
681
  recipe: input.recipe,
668
682
  layout: input.layout,
@@ -674,11 +688,59 @@ async function spawnCodexAppServer(input) {
674
688
  args,
675
689
  owner: { bindingId: input.host.bindingId },
676
690
  ...input.cwd === void 0 ? {} : { cwd: input.cwd },
677
- ...input.env !== void 0 || Object.keys(env).length > 0 ? { env } : {}
691
+ ...input.env !== void 0 || Object.keys(env).length > 0 ? { env } : {},
692
+ ...input.signal === void 0 ? {} : { signal: input.signal }
678
693
  });
679
694
  return { handle, args };
680
695
  }
681
696
 
697
+ // src/cliVersion.ts
698
+ var CODEX_VERSION_TIMEOUT_MS = 15e3;
699
+ var VERSION_PATTERN = /(?<![\d.])(\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?)/;
700
+ async function collect(stream) {
701
+ const chunks = [];
702
+ for await (const chunk of stream) {
703
+ chunks.push(Buffer.from(chunk));
704
+ if (Buffer.concat(chunks).length > 64 * 1024) break;
705
+ }
706
+ return Buffer.concat(chunks).toString("utf8");
707
+ }
708
+ async function readCodexCliVersion(input) {
709
+ if (input.recipe.binaryPath.length === 0) return null;
710
+ let handle;
711
+ try {
712
+ handle = await input.host.process.spawn({
713
+ program: input.recipe.binaryPath,
714
+ args: ["--version"],
715
+ owner: { bindingId: input.host.bindingId }
716
+ });
717
+ } catch {
718
+ return null;
719
+ }
720
+ const collected = Promise.all([collect(handle.stdout), collect(handle.stderr), handle.exited]);
721
+ let timer;
722
+ const timeout = new Promise((resolve2) => {
723
+ timer = setTimeout(() => resolve2("timeout"), CODEX_VERSION_TIMEOUT_MS);
724
+ timer.unref?.();
725
+ });
726
+ try {
727
+ const settled = await Promise.race([collected, timeout]);
728
+ if (settled === "timeout") {
729
+ collected.catch(() => void 0);
730
+ return null;
731
+ }
732
+ const [stdout, stderr, exitCode] = settled;
733
+ if (exitCode !== 0) return null;
734
+ return VERSION_PATTERN.exec(`${stdout}
735
+ ${stderr}`)?.[1] ?? null;
736
+ } catch {
737
+ return null;
738
+ } finally {
739
+ if (timer !== void 0) clearTimeout(timer);
740
+ await handle.kill("SIGTERM").catch(() => void 0);
741
+ }
742
+ }
743
+
682
744
  // src/failureCategory.ts
683
745
  var codexProcessExitCategory = (session) => session !== void 0 && !session.stopRequested && typeof session.nativeThreadId === "string" && session.nativeThreadId.length > 0 ? "transport" : void 0;
684
746
 
@@ -5920,9 +5982,14 @@ var createCodexInstance = (config, host, attachments, cache) => {
5920
5982
  let version = null;
5921
5983
  try {
5922
5984
  try {
5923
- ({ handle } = await spawnCodexAppServer({ host, recipe, layout }));
5985
+ ({ handle } = await spawnCodexAppServer({
5986
+ host,
5987
+ recipe,
5988
+ layout,
5989
+ ...input.signal === void 0 ? {} : { signal: input.signal }
5990
+ }));
5924
5991
  } catch (error) {
5925
- if (error instanceof ExecutorSpawnRefusedError) throw error;
5992
+ throwIfCodexSpawnControlled(error);
5926
5993
  host.log.warn("codex binary could not be started", {
5927
5994
  program: recipe.binaryPath,
5928
5995
  error: error instanceof Error ? error.message : String(error)
@@ -5935,19 +6002,26 @@ var createCodexInstance = (config, host, attachments, cache) => {
5935
6002
  };
5936
6003
  }
5937
6004
  trackHandle(handle, `${recipe.binaryPath} (probe)`);
5938
- rpc = await createCodexRpcClient(handle, {
5939
- onNotification: () => void 0,
5940
- onServerRequest: () => void 0,
5941
- onStderrLine: () => void 0
5942
- });
5943
- version = codexVersionFromInitialize(
5944
- await rpc.request("initialize", CODEX_INITIALIZE_PARAMS)
6005
+ const spawned = handle;
6006
+ return await raceAbort(
6007
+ (async () => {
6008
+ rpc = await createCodexRpcClient(spawned, {
6009
+ onNotification: () => void 0,
6010
+ onServerRequest: () => void 0,
6011
+ onStderrLine: () => void 0
6012
+ });
6013
+ version = codexVersionFromInitialize(
6014
+ await rpc.request("initialize", CODEX_INITIALIZE_PARAMS)
6015
+ );
6016
+ await rpc.notify("initialized");
6017
+ const models = input.listModels ? await listCodexModels(rpc) : void 0;
6018
+ return { version, models, skills: await listCodexSkills(rpc), spawnFailed: null };
6019
+ })(),
6020
+ input.signal
5945
6021
  );
5946
- await rpc.notify("initialized");
5947
- const models = input.listModels ? await listCodexModels(rpc) : void 0;
5948
- return { version, models, skills: await listCodexSkills(rpc), spawnFailed: null };
5949
6022
  } catch (error) {
5950
- if (error instanceof ExecutorSpawnRefusedError) throw error;
6023
+ if (error instanceof ExecutorSpawnRefusedError2) throw error;
6024
+ if (input.signal?.aborted) throw error;
5951
6025
  return { version, models: void 0, skills: void 0, spawnFailed: null };
5952
6026
  } finally {
5953
6027
  await rpc?.close().catch(() => void 0);
@@ -5962,7 +6036,7 @@ var createCodexInstance = (config, host, attachments, cache) => {
5962
6036
  try {
5963
6037
  ({ handle } = await spawnCodexAppServer({ host, recipe, layout }));
5964
6038
  } catch (error) {
5965
- if (error instanceof ExecutorSpawnRefusedError) {
6039
+ if (error instanceof ExecutorSpawnRefusedError2) {
5966
6040
  const borrowed = [...threads.values()].find((entry) => !entry.closing);
5967
6041
  if (borrowed !== void 0) return await run(borrowed.rpc);
5968
6042
  }
@@ -6008,7 +6082,7 @@ var createCodexInstance = (config, host, attachments, cache) => {
6008
6082
  return booked.closing;
6009
6083
  };
6010
6084
  const instance = {
6011
- probe: async () => {
6085
+ probe: async (signal) => {
6012
6086
  if (recipe.binaryPath.length === 0) {
6013
6087
  return {
6014
6088
  installed: false,
@@ -6020,7 +6094,8 @@ var createCodexInstance = (config, host, attachments, cache) => {
6020
6094
  }
6021
6095
  const connectionError = codexApiConnectionError(recipe, recipe.environment);
6022
6096
  const { version, models, skills, spawnFailed } = await probeAppServer({
6023
- listModels: connectionError === null
6097
+ listModels: connectionError === null,
6098
+ ...signal === void 0 ? {} : { signal }
6024
6099
  });
6025
6100
  if (spawnFailed !== null) {
6026
6101
  return {
@@ -6054,6 +6129,7 @@ var createCodexInstance = (config, host, attachments, cache) => {
6054
6129
  ...CODEX_NATIVE_MODE_REPORT
6055
6130
  };
6056
6131
  },
6132
+ readCliVersion: () => readCodexCliVersion({ recipe, host }),
6057
6133
  // 有意不处理 input.readOnlyDirectories:codex 的沙箱只限制写入,读不受限,
6058
6134
  // 附件目录本来就能读,无需放行。
6059
6135
  startSession: async (input, signal) => {
@@ -6387,7 +6463,7 @@ var executors = [
6387
6463
  ];
6388
6464
  var index_default = definePlugin({
6389
6465
  id: "agent-codex",
6390
- apiVersion: 29,
6466
+ apiVersion: 31,
6391
6467
  executors,
6392
6468
  activate(ctx) {
6393
6469
  capturedAttachments = ctx.attachments;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ycodium-ai/agent-codex",
3
- "version": "0.2.3252",
3
+ "version": "0.2.3265",
4
4
  "description": "Codex executor: Codex CLI over the app-server JSON-RPC protocol.",
5
5
  "keywords": [
6
6
  "ycodium",
@@ -29,7 +29,7 @@
29
29
  "tailwindcss": "^4.0.0",
30
30
  "typescript": "~6.0.3",
31
31
  "vite-plus": "0.2.2",
32
- "@ycodium-ai/plugin-api": "0.2.3252",
32
+ "@ycodium-ai/plugin-api": "0.2.3265",
33
33
  "ycodium-executor-testing": "0.0.0"
34
34
  },
35
35
  "ycodium": {