@ycodium-ai/agent-codex 0.2.3254 → 0.2.3269

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 +130 -20
  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
 
@@ -1800,6 +1862,29 @@ function toCanonicalUserInputAnswers(answers) {
1800
1862
  );
1801
1863
  }
1802
1864
 
1865
+ // src/windowsSandbox.ts
1866
+ function windowsSandboxWarnings(input) {
1867
+ const item = isRecord3(input.params) ? input.params["item"] : void 0;
1868
+ if (!isRecord3(item) || item["type"] !== "commandExecution" || item["source"] !== "unifiedExecStartup" || item["status"] !== "failed" || item["processId"] !== null || item["exitCode"] !== -1 || item["durationMs"] !== 0)
1869
+ return [];
1870
+ const output = item["aggregatedOutput"];
1871
+ if (typeof output !== "string" || !/^Failed to create unified exec process: (?:CreateProcessWithLogonW failed: \d+\b|orchestrator_helper_launch_canceled: ShellExecuteExW failed to launch setup helper: \d+\b)/.test(
1872
+ output
1873
+ ))
1874
+ return [];
1875
+ return [
1876
+ baseEvent({
1877
+ type: "runtime.warning",
1878
+ threadId: input.threadId,
1879
+ turnId: input.turnId,
1880
+ itemId: input.itemId,
1881
+ providerInstanceId: input.providerInstanceId,
1882
+ method: "item/completed",
1883
+ payload: { code: "codex-windows-sandbox", message: output, detail: output }
1884
+ })
1885
+ ];
1886
+ }
1887
+
1803
1888
  // src/usage/codexQuota.ts
1804
1889
  var asRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
1805
1890
  var asFiniteNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
@@ -2497,7 +2582,18 @@ function mapNotificationToEvents(input) {
2497
2582
  })
2498
2583
  ] : [];
2499
2584
  const asyncQuestions = canonical === "assistant_message" && itemId ? toAsyncQuestions(params) : void 0;
2500
- if (!asyncQuestions) return [completed, ...produced];
2585
+ if (!asyncQuestions)
2586
+ return [
2587
+ completed,
2588
+ ...produced,
2589
+ ...windowsSandboxWarnings({
2590
+ params,
2591
+ threadId,
2592
+ turnId,
2593
+ itemId,
2594
+ providerInstanceId
2595
+ })
2596
+ ];
2501
2597
  return [
2502
2598
  completed,
2503
2599
  baseEvent({
@@ -5920,9 +6016,14 @@ var createCodexInstance = (config, host, attachments, cache) => {
5920
6016
  let version = null;
5921
6017
  try {
5922
6018
  try {
5923
- ({ handle } = await spawnCodexAppServer({ host, recipe, layout }));
6019
+ ({ handle } = await spawnCodexAppServer({
6020
+ host,
6021
+ recipe,
6022
+ layout,
6023
+ ...input.signal === void 0 ? {} : { signal: input.signal }
6024
+ }));
5924
6025
  } catch (error) {
5925
- if (error instanceof ExecutorSpawnRefusedError) throw error;
6026
+ throwIfCodexSpawnControlled(error);
5926
6027
  host.log.warn("codex binary could not be started", {
5927
6028
  program: recipe.binaryPath,
5928
6029
  error: error instanceof Error ? error.message : String(error)
@@ -5935,19 +6036,26 @@ var createCodexInstance = (config, host, attachments, cache) => {
5935
6036
  };
5936
6037
  }
5937
6038
  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)
6039
+ const spawned = handle;
6040
+ return await raceAbort(
6041
+ (async () => {
6042
+ rpc = await createCodexRpcClient(spawned, {
6043
+ onNotification: () => void 0,
6044
+ onServerRequest: () => void 0,
6045
+ onStderrLine: () => void 0
6046
+ });
6047
+ version = codexVersionFromInitialize(
6048
+ await rpc.request("initialize", CODEX_INITIALIZE_PARAMS)
6049
+ );
6050
+ await rpc.notify("initialized");
6051
+ const models = input.listModels ? await listCodexModels(rpc) : void 0;
6052
+ return { version, models, skills: await listCodexSkills(rpc), spawnFailed: null };
6053
+ })(),
6054
+ input.signal
5945
6055
  );
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
6056
  } catch (error) {
5950
- if (error instanceof ExecutorSpawnRefusedError) throw error;
6057
+ if (error instanceof ExecutorSpawnRefusedError2) throw error;
6058
+ if (input.signal?.aborted) throw error;
5951
6059
  return { version, models: void 0, skills: void 0, spawnFailed: null };
5952
6060
  } finally {
5953
6061
  await rpc?.close().catch(() => void 0);
@@ -5962,7 +6070,7 @@ var createCodexInstance = (config, host, attachments, cache) => {
5962
6070
  try {
5963
6071
  ({ handle } = await spawnCodexAppServer({ host, recipe, layout }));
5964
6072
  } catch (error) {
5965
- if (error instanceof ExecutorSpawnRefusedError) {
6073
+ if (error instanceof ExecutorSpawnRefusedError2) {
5966
6074
  const borrowed = [...threads.values()].find((entry) => !entry.closing);
5967
6075
  if (borrowed !== void 0) return await run(borrowed.rpc);
5968
6076
  }
@@ -6008,7 +6116,7 @@ var createCodexInstance = (config, host, attachments, cache) => {
6008
6116
  return booked.closing;
6009
6117
  };
6010
6118
  const instance = {
6011
- probe: async () => {
6119
+ probe: async (signal) => {
6012
6120
  if (recipe.binaryPath.length === 0) {
6013
6121
  return {
6014
6122
  installed: false,
@@ -6020,7 +6128,8 @@ var createCodexInstance = (config, host, attachments, cache) => {
6020
6128
  }
6021
6129
  const connectionError = codexApiConnectionError(recipe, recipe.environment);
6022
6130
  const { version, models, skills, spawnFailed } = await probeAppServer({
6023
- listModels: connectionError === null
6131
+ listModels: connectionError === null,
6132
+ ...signal === void 0 ? {} : { signal }
6024
6133
  });
6025
6134
  if (spawnFailed !== null) {
6026
6135
  return {
@@ -6054,6 +6163,7 @@ var createCodexInstance = (config, host, attachments, cache) => {
6054
6163
  ...CODEX_NATIVE_MODE_REPORT
6055
6164
  };
6056
6165
  },
6166
+ readCliVersion: () => readCodexCliVersion({ recipe, host }),
6057
6167
  // 有意不处理 input.readOnlyDirectories:codex 的沙箱只限制写入,读不受限,
6058
6168
  // 附件目录本来就能读,无需放行。
6059
6169
  startSession: async (input, signal) => {
@@ -6387,7 +6497,7 @@ var executors = [
6387
6497
  ];
6388
6498
  var index_default = definePlugin({
6389
6499
  id: "agent-codex",
6390
- apiVersion: 30,
6500
+ apiVersion: 31,
6391
6501
  executors,
6392
6502
  activate(ctx) {
6393
6503
  capturedAttachments = ctx.attachments;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ycodium-ai/agent-codex",
3
- "version": "0.2.3254",
3
+ "version": "0.2.3269",
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.3254",
32
+ "@ycodium-ai/plugin-api": "0.2.0",
33
33
  "ycodium-executor-testing": "0.0.0"
34
34
  },
35
35
  "ycodium": {