@ycodium-ai/agent-codex 0.2.3272 → 0.2.3306

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 +274 -139
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -440,7 +440,7 @@ import * as NodeProcess from "node:process";
440
440
  import {
441
441
  describeExecutorSpawnFailure,
442
442
  ExecutorSpawnRefusedError as ExecutorSpawnRefusedError2,
443
- raceAbort
443
+ raceAbort as raceAbort2
444
444
  } from "@ycodium-ai/plugin-api/executor";
445
445
 
446
446
  // src/appServerLaunch.ts
@@ -563,6 +563,9 @@ function tokenizeLaunchArgs(value) {
563
563
  if (current || quoted) tokens.push(current);
564
564
  return tokens;
565
565
  }
566
+ function encodeQuotedArgs(args) {
567
+ return args.map((arg) => `"${arg.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`).join(" ");
568
+ }
566
569
  function codexExecLaunchArgs(launchArgs) {
567
570
  const args = tokenizeLaunchArgs(launchArgs ?? "");
568
571
  const execArgs = [];
@@ -646,6 +649,9 @@ function codexSpawnArgs(recipe, layout) {
646
649
  if (!needsOverrides) return tokenizeLaunchArgs(recipe.launchArgs);
647
650
  return connectionArgv(recipe, layout);
648
651
  }
652
+ function encodeCodexConnectionArgs(recipe, layout) {
653
+ return encodeQuotedArgs(connectionArgv(recipe, layout));
654
+ }
649
655
  var CRUSHED_API_KEYS = {
650
656
  OPENAI_API_KEY: void 0,
651
657
  CODEX_API_KEY: void 0
@@ -1161,28 +1167,25 @@ async function createCodexRpcClient(handle, handlers) {
1161
1167
  const settled = new Promise((resolve2, reject) => {
1162
1168
  pending.set(id, { resolve: resolve2, reject, method });
1163
1169
  });
1170
+ const limit = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
1171
+ let timer;
1172
+ const timedOut = new Promise((_, reject) => {
1173
+ if (limit > 0)
1174
+ timer = setTimeout(
1175
+ () => reject(new Error(`codex app-server ${method} timed out after ${String(limit)}ms`)),
1176
+ limit
1177
+ );
1178
+ });
1164
1179
  try {
1165
1180
  await Promise.race([
1166
1181
  writeLine({ id, method, ...params === void 0 ? {} : { params } }),
1167
- settled
1182
+ settled,
1183
+ timedOut
1168
1184
  ]);
1185
+ return await Promise.race([settled, timedOut]);
1169
1186
  } catch (error) {
1170
1187
  pending.delete(id);
1171
1188
  throw error;
1172
- }
1173
- const limit = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
1174
- if (limit <= 0) return await settled;
1175
- let timer;
1176
- try {
1177
- return await Promise.race([
1178
- settled,
1179
- new Promise((_, reject) => {
1180
- timer = setTimeout(() => {
1181
- pending.delete(id);
1182
- reject(new Error(`codex app-server ${method} timed out after ${String(limit)}ms`));
1183
- }, limit);
1184
- })
1185
- ]);
1186
1189
  } finally {
1187
1190
  if (timer !== void 0) clearTimeout(timer);
1188
1191
  }
@@ -4707,11 +4710,50 @@ var codexWorkspaceInventory = async (rpc, cwd) => {
4707
4710
  return { skills, watchPaths: codexWorkspaceWatchPaths(cwd, skills) };
4708
4711
  };
4709
4712
 
4713
+ // src/signIn.ts
4714
+ import { raceAbort } from "@ycodium-ai/plugin-api/executor";
4715
+
4716
+ // src/signInLifecycle.ts
4717
+ function signInLifetime(signal) {
4718
+ const controller = new AbortController();
4719
+ const abort = () => controller.abort(signal?.reason);
4720
+ signal?.addEventListener("abort", abort, { once: true });
4721
+ if (signal?.aborted) abort();
4722
+ const timer = setTimeout(
4723
+ () => controller.abort(new Error("Codex sign-in timed out")),
4724
+ 10 * 6e4
4725
+ );
4726
+ timer.unref?.();
4727
+ return {
4728
+ signal: controller.signal,
4729
+ close: () => {
4730
+ clearTimeout(timer);
4731
+ signal?.removeEventListener("abort", abort);
4732
+ controller.abort(new Error("Codex sign-in cancelled"));
4733
+ }
4734
+ };
4735
+ }
4736
+
4710
4737
  // src/signIn.ts
4711
4738
  var DEVICE_CODE_URL = /https?:\/\/\S+/;
4712
4739
  var DEVICE_CODE_VALUE = /\b([A-Z0-9]{4,}(?:-[A-Z0-9]{4,})+)\b/;
4713
4740
  var deviceCodeUrl = (output) => DEVICE_CODE_URL.exec(output)?.[0];
4714
4741
  var deviceCodeValue = (output) => DEVICE_CODE_VALUE.exec(output)?.[1];
4742
+ async function closeSignInRpc(rpc, host, handle) {
4743
+ await Promise.all([
4744
+ rpc.close({
4745
+ drainTimeoutMs: 5e3,
4746
+ onDrainTimeout: () => host.log.warn("Codex sign-in output did not close after termination")
4747
+ }),
4748
+ handle.exited
4749
+ ]);
4750
+ }
4751
+ function closeOperation(operations, operation) {
4752
+ return operation.closing ??= Promise.resolve().then(operation.close).finally(() => {
4753
+ if (operations.get(operation.operationId) === operation)
4754
+ operations.delete(operation.operationId);
4755
+ });
4756
+ }
4715
4757
  async function collectText(stream, into) {
4716
4758
  const decoder = new TextDecoder();
4717
4759
  for await (const chunk of stream) {
@@ -4738,96 +4780,158 @@ async function startCodexSignIn(input) {
4738
4780
  }
4739
4781
  const isolatedHome = accountHomeFromLayout(input.layout);
4740
4782
  const env = nativeLoginSpawnEnv(input.processEnv, isolatedHome);
4783
+ const loginRecipe = { ...input.recipe, authMode: "chatgpt" };
4741
4784
  const owner = { bindingId: input.host.bindingId };
4742
- const tryAppServer = async () => {
4743
- const { handle: handle2 } = await spawnCodexAppServer({
4744
- host: input.host,
4745
- recipe: input.recipe,
4746
- layout: input.layout,
4747
- args: tokenizeLaunchArgs(input.recipe.launchArgs),
4748
- env
4749
- });
4750
- let completed;
4751
- const rpc = await createCodexRpcClient(handle2, {
4752
- onNotification: (notification) => {
4753
- if (notification.method !== "account/login/completed") return;
4754
- const params = isRecord3(notification.params) ? notification.params : {};
4755
- const loginId = asString(params["loginId"]);
4756
- completed = loginId ? { loginId } : {};
4757
- },
4758
- onServerRequest: () => void 0,
4759
- onStderrLine: () => void 0
4760
- });
4761
- try {
4762
- await rpc.request("initialize", CODEX_INITIALIZE_PARAMS);
4763
- await rpc.notify("initialized");
4764
- const started = await rpc.request("account/login/start", { type: "chatgptDeviceCode" });
4765
- if (!isRecord3(started) || asString(started["type"]) !== "chatgptDeviceCode") {
4766
- await rpc.close();
4767
- return void 0;
4768
- }
4769
- const userCode2 = asString(started["userCode"]) ?? asString(started["user_code"]) ?? void 0;
4770
- const verificationUrl2 = asString(started["verificationUrl"]) ?? asString(started["verification_uri"]) ?? asString(started["url"]) ?? void 0;
4771
- const operationId2 = `codex-login-${Date.now()}`;
4772
- return {
4773
- operation: {
4774
- operationId: operationId2,
4775
- handle: handle2,
4776
- close: async () => {
4777
- void completed;
4778
- await rpc.close();
4779
- }
4785
+ const lifetime = signInLifetime(input.signal);
4786
+ try {
4787
+ const tryAppServer = async () => {
4788
+ const { handle: handle2 } = await spawnCodexAppServer({
4789
+ host: input.host,
4790
+ recipe: loginRecipe,
4791
+ layout: input.layout,
4792
+ env,
4793
+ signal: lifetime.signal
4794
+ });
4795
+ const completion = Promise.withResolvers();
4796
+ let expectedLoginId;
4797
+ const earlyCompletions = [];
4798
+ const receiveCompletion = (result) => {
4799
+ if (expectedLoginId === void 0) earlyCompletions.push(result);
4800
+ else if (expectedLoginId === null || result.loginId === expectedLoginId)
4801
+ completion.resolve(result);
4802
+ };
4803
+ const rpc = await createCodexRpcClient(handle2, {
4804
+ onNotification: (notification) => {
4805
+ if (notification.method !== "account/login/completed") return;
4806
+ const params = isRecord3(notification.params) ? notification.params : {};
4807
+ const loginId = asString(params["loginId"]);
4808
+ receiveCompletion({
4809
+ loginId,
4810
+ success: params["success"] === true,
4811
+ error: asString(params["error"])
4812
+ });
4780
4813
  },
4781
- ...userCode2 ? { userCode: userCode2 } : {},
4782
- ...verificationUrl2 ? { verificationUrl: verificationUrl2 } : {}
4814
+ onServerRequest: () => void 0,
4815
+ onStderrLine: () => void 0
4816
+ });
4817
+ const close = async () => {
4818
+ lifetime.close();
4819
+ await closeSignInRpc(rpc, input.host, handle2);
4783
4820
  };
4784
- } catch {
4785
- await rpc.close().catch(() => void 0);
4786
- return void 0;
4787
- }
4788
- };
4789
- const appServer = await tryAppServer();
4790
- if (appServer) return appServer;
4791
- const handle = await input.host.process.spawn({
4792
- program: input.recipe.binaryPath,
4793
- args: [...codexExecLaunchArgs(input.recipe.launchArgs), ...CODEX_CARD.deviceCodeSignInArgs],
4794
- owner,
4795
- env
4796
- });
4797
- const stdout = { text: "" };
4798
- const stderr = { text: "" };
4799
- void collectText(handle.stdout, stdout);
4800
- void collectText(handle.stderr, stderr);
4801
- const deadline = Date.now() + 3e3;
4802
- while (Date.now() < deadline) {
4803
- const combined2 = `${stdout.text}
4821
+ const abort = () => {
4822
+ void closeSignInRpc(rpc, input.host, handle2).catch(() => void 0);
4823
+ };
4824
+ lifetime.signal.addEventListener("abort", abort, { once: true });
4825
+ if (lifetime.signal.aborted) abort();
4826
+ try {
4827
+ await raceAbort(rpc.request("initialize", CODEX_INITIALIZE_PARAMS), lifetime.signal);
4828
+ await raceAbort(rpc.notify("initialized"), lifetime.signal);
4829
+ const started = await raceAbort(
4830
+ rpc.request("account/login/start", { type: "chatgptDeviceCode" }),
4831
+ lifetime.signal
4832
+ );
4833
+ if (!isRecord3(started) || asString(started["type"]) !== "chatgptDeviceCode") {
4834
+ await closeSignInRpc(rpc, input.host, handle2);
4835
+ return void 0;
4836
+ }
4837
+ const userCode2 = asString(started["userCode"]) ?? asString(started["user_code"]) ?? void 0;
4838
+ const verificationUrl2 = asString(started["verificationUrl"]) ?? asString(started["verification_uri"]) ?? asString(started["url"]) ?? void 0;
4839
+ const operationId2 = `codex-login-${Date.now()}`;
4840
+ expectedLoginId = asString(started["loginId"]);
4841
+ for (const result of earlyCompletions) receiveCompletion(result);
4842
+ earlyCompletions.length = 0;
4843
+ const completed2 = raceAbort(
4844
+ Promise.race([
4845
+ completion.promise.then((result) => {
4846
+ if (!result.success) throw new Error(result.error ?? "Codex sign-in failed");
4847
+ }),
4848
+ handle2.exited.then(() => {
4849
+ throw new Error("Codex exited before sign-in completed");
4850
+ })
4851
+ ]),
4852
+ lifetime.signal
4853
+ );
4854
+ void completed2.catch(() => void 0);
4855
+ return {
4856
+ operation: {
4857
+ operationId: operationId2,
4858
+ handle: handle2,
4859
+ completed: completed2,
4860
+ close: async () => {
4861
+ lifetime.signal.removeEventListener("abort", abort);
4862
+ await close();
4863
+ }
4864
+ },
4865
+ ...userCode2 ? { userCode: userCode2 } : {},
4866
+ ...verificationUrl2 ? { verificationUrl: verificationUrl2 } : {}
4867
+ };
4868
+ } catch (error) {
4869
+ await closeSignInRpc(rpc, input.host, handle2).catch(() => void 0);
4870
+ if (lifetime.signal.aborted) throw error;
4871
+ return void 0;
4872
+ }
4873
+ };
4874
+ const appServer = await tryAppServer();
4875
+ if (appServer) return appServer;
4876
+ const handle = await input.host.process.spawn({
4877
+ program: input.recipe.binaryPath,
4878
+ args: [
4879
+ ...codexExecLaunchArgs(encodeCodexConnectionArgs(loginRecipe, input.layout)),
4880
+ ...CODEX_CARD.deviceCodeSignInArgs
4881
+ ],
4882
+ owner,
4883
+ env,
4884
+ signal: lifetime.signal
4885
+ });
4886
+ const stdout = { text: "" };
4887
+ const stderr = { text: "" };
4888
+ void collectText(handle.stdout, stdout);
4889
+ void collectText(handle.stderr, stderr);
4890
+ const deadline = Date.now() + 3e3;
4891
+ while (Date.now() < deadline) {
4892
+ const combined2 = `${stdout.text}
4804
4893
  ${stderr.text}`;
4805
- if (deviceCodeUrl(combined2) && deviceCodeValue(combined2)) break;
4806
- await new Promise((resolve2) => setTimeout(resolve2, 50));
4807
- }
4808
- const combined = `${stdout.text}
4894
+ if (deviceCodeUrl(combined2) && deviceCodeValue(combined2)) break;
4895
+ await new Promise((resolve2) => setTimeout(resolve2, 50));
4896
+ }
4897
+ const combined = `${stdout.text}
4809
4898
  ${stderr.text}`;
4810
- const operationId = `codex-login-${Date.now()}`;
4811
- const userCode = deviceCodeValue(combined);
4812
- const verificationUrl = deviceCodeUrl(combined);
4813
- return {
4814
- operation: {
4815
- operationId,
4816
- handle,
4817
- close: async () => {
4818
- try {
4819
- await handle.closeStdin();
4820
- } catch {
4821
- }
4822
- try {
4823
- await handle.kill("SIGTERM");
4824
- } catch {
4899
+ const operationId = `codex-login-${Date.now()}`;
4900
+ const userCode = deviceCodeValue(combined);
4901
+ const verificationUrl = deviceCodeUrl(combined);
4902
+ const completed = raceAbort(
4903
+ handle.exited.then((code) => {
4904
+ if (code !== 0)
4905
+ throw new Error(stderr.text.trim() || `Codex sign-in exited with code ${String(code)}`);
4906
+ }),
4907
+ lifetime.signal
4908
+ );
4909
+ void completed.catch(() => void 0);
4910
+ return {
4911
+ operation: {
4912
+ operationId,
4913
+ handle,
4914
+ completed,
4915
+ close: async () => {
4916
+ lifetime.close();
4917
+ try {
4918
+ await handle.closeStdin();
4919
+ } catch {
4920
+ }
4921
+ try {
4922
+ await handle.kill("SIGTERM");
4923
+ await handle.exited;
4924
+ } catch {
4925
+ }
4825
4926
  }
4826
- }
4827
- },
4828
- ...userCode ? { userCode } : {},
4829
- ...verificationUrl ? { verificationUrl } : {}
4830
- };
4927
+ },
4928
+ ...userCode ? { userCode } : {},
4929
+ ...verificationUrl ? { verificationUrl } : {}
4930
+ };
4931
+ } catch (error) {
4932
+ lifetime.close();
4933
+ throw error;
4934
+ }
4831
4935
  }
4832
4936
  async function verifyCodexSignIn(input) {
4833
4937
  const home = accountHomeFromLayout(input.layout);
@@ -4844,16 +4948,21 @@ async function verifyCodexSignIn(input) {
4844
4948
  const env = nativeLoginSpawnEnv(input.processEnv, home);
4845
4949
  const { handle } = await spawnCodexAppServer({
4846
4950
  host: input.host,
4847
- recipe: input.recipe,
4951
+ recipe: { ...input.recipe, authMode: "chatgpt" },
4848
4952
  layout: input.layout,
4849
- args: tokenizeLaunchArgs(input.recipe.launchArgs),
4850
- env
4953
+ env,
4954
+ ...input.signal === void 0 ? {} : { signal: input.signal }
4851
4955
  });
4852
4956
  const rpc = await createCodexRpcClient(handle, {
4853
4957
  onNotification: () => void 0,
4854
4958
  onServerRequest: () => void 0,
4855
4959
  onStderrLine: () => void 0
4856
4960
  });
4961
+ const abort = () => {
4962
+ void closeSignInRpc(rpc, input.host, handle).catch(() => void 0);
4963
+ };
4964
+ input.signal?.addEventListener("abort", abort, { once: true });
4965
+ if (input.signal?.aborted) abort();
4857
4966
  let version = null;
4858
4967
  try {
4859
4968
  version = codexVersionFromInitialize(
@@ -4861,7 +4970,8 @@ async function verifyCodexSignIn(input) {
4861
4970
  );
4862
4971
  await rpc.notify("initialized");
4863
4972
  const account = await rpc.request("account/read", { refreshToken: true }, 15e3);
4864
- const type = isRecord3(account) ? asString(account["type"]) : null;
4973
+ const details = isRecord3(account) && isRecord3(account["account"]) ? account["account"] : account;
4974
+ const type = isRecord3(details) ? asString(details["type"]) : null;
4865
4975
  if (type !== "chatgpt") {
4866
4976
  return {
4867
4977
  installed: true,
@@ -4876,7 +4986,11 @@ async function verifyCodexSignIn(input) {
4876
4986
  installed: true,
4877
4987
  version,
4878
4988
  readiness: "ready",
4879
- auth,
4989
+ auth: {
4990
+ ...auth,
4991
+ status: "authenticated",
4992
+ ...isRecord3(details) && asString(details["email"]) ? { email: asString(details["email"]) } : {}
4993
+ },
4880
4994
  ...models === void 0 ? {} : { models },
4881
4995
  ...CODEX_NATIVE_MODE_REPORT
4882
4996
  };
@@ -4889,9 +5003,52 @@ async function verifyCodexSignIn(input) {
4889
5003
  ...CODEX_NATIVE_MODE_REPORT
4890
5004
  };
4891
5005
  } finally {
4892
- await rpc.close().catch(() => void 0);
5006
+ input.signal?.removeEventListener("abort", abort);
5007
+ await closeSignInRpc(rpc, input.host, handle).catch(() => void 0);
5008
+ }
5009
+ }
5010
+ async function verifyCodexSignInOperation(input) {
5011
+ const operation = input.operations.values().next().value;
5012
+ try {
5013
+ if (operation) await raceAbort(operation.completed, input.signal);
5014
+ return await verifyCodexSignIn(input);
5015
+ } finally {
5016
+ if (operation) {
5017
+ await closeOperation(input.operations, operation);
5018
+ }
4893
5019
  }
4894
5020
  }
5021
+ function makeCodexSignIn(input) {
5022
+ const current = (signal) => ({
5023
+ host: input.host,
5024
+ recipe: input.recipe(),
5025
+ layout: input.layout(),
5026
+ processEnv: process.env,
5027
+ ...signal === void 0 ? {} : { signal }
5028
+ });
5029
+ return {
5030
+ start: async (signal) => {
5031
+ const started = await startCodexSignIn(current(signal));
5032
+ if (signal?.aborted || input.isDisposed()) {
5033
+ await started.operation.close();
5034
+ throw new Error("Codex sign-in cancelled");
5035
+ }
5036
+ input.operations.set(started.operation.operationId, started.operation);
5037
+ input.onStarted(started.operation);
5038
+ return {
5039
+ operationId: started.operation.operationId,
5040
+ ...started.userCode === void 0 ? {} : { userCode: started.userCode },
5041
+ ...started.verificationUrl === void 0 ? {} : { verificationUrl: started.verificationUrl }
5042
+ };
5043
+ },
5044
+ cancel: async (operationId) => {
5045
+ const operation = input.operations.get(operationId);
5046
+ if (operation === void 0) return;
5047
+ await closeOperation(input.operations, operation);
5048
+ },
5049
+ verify: (signal) => verifyCodexSignInOperation({ ...current(signal), operations: input.operations })
5050
+ };
5051
+ }
4895
5052
 
4896
5053
  // src/turnSummaryPrompt.ts
4897
5054
  function buildTurnSummaryPrompt(raw) {
@@ -6037,7 +6194,7 @@ var createCodexInstance = (config, host, attachments, cache) => {
6037
6194
  }
6038
6195
  trackHandle(handle, `${recipe.binaryPath} (probe)`);
6039
6196
  const spawned = handle;
6040
- return await raceAbort(
6197
+ return await raceAbort2(
6041
6198
  (async () => {
6042
6199
  rpc = await createCodexRpcClient(spawned, {
6043
6200
  onNotification: () => void 0,
@@ -6309,9 +6466,8 @@ var createCodexInstance = (config, host, attachments, cache) => {
6309
6466
  );
6310
6467
  disposeTask = (async () => {
6311
6468
  const operations = [...signInOperations.values()];
6312
- signInOperations.clear();
6313
6469
  for (const operation of operations) {
6314
- await operation.close().catch(() => void 0);
6470
+ await instance.signIn.cancel(operation.operationId).catch(() => void 0);
6315
6471
  }
6316
6472
  for (const result of await closing) {
6317
6473
  if (result.status === "rejected") throw result.reason;
@@ -6398,35 +6554,14 @@ var createCodexInstance = (config, host, attachments, cache) => {
6398
6554
  }
6399
6555
  }
6400
6556
  },
6401
- signIn: {
6402
- start: async () => {
6403
- const started = await startCodexSignIn({
6404
- host,
6405
- recipe,
6406
- layout: layoutFor(recipe),
6407
- processEnv: process.env
6408
- });
6409
- signInOperations.set(started.operation.operationId, started.operation);
6410
- trackHandle(started.operation.handle, "codex login --device-auth");
6411
- return {
6412
- operationId: started.operation.operationId,
6413
- ...started.userCode === void 0 ? {} : { userCode: started.userCode },
6414
- ...started.verificationUrl === void 0 ? {} : { verificationUrl: started.verificationUrl }
6415
- };
6416
- },
6417
- cancel: async (operationId) => {
6418
- const operation = signInOperations.get(operationId);
6419
- if (operation === void 0) return;
6420
- signInOperations.delete(operationId);
6421
- await operation.close().catch(() => void 0);
6422
- },
6423
- verify: async () => verifyCodexSignIn({
6424
- host,
6425
- recipe,
6426
- layout: layoutFor(recipe),
6427
- processEnv: process.env
6428
- })
6429
- },
6557
+ signIn: makeCodexSignIn({
6558
+ host,
6559
+ recipe: () => recipe,
6560
+ layout: () => layoutFor(recipe),
6561
+ operations: signInOperations,
6562
+ isDisposed: () => disposed,
6563
+ onStarted: (operation) => trackHandle(operation.handle, "codex login --device-auth")
6564
+ }),
6430
6565
  mcpOAuth: {
6431
6566
  start: async (input) => {
6432
6567
  const started = await startCodexMcpOAuth({
@@ -6497,7 +6632,7 @@ var executors = [
6497
6632
  ];
6498
6633
  var index_default = definePlugin({
6499
6634
  id: "agent-codex",
6500
- apiVersion: 32,
6635
+ apiVersion: 34,
6501
6636
  executors,
6502
6637
  activate(ctx) {
6503
6638
  capturedAttachments = ctx.attachments;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ycodium-ai/agent-codex",
3
- "version": "0.2.3272",
3
+ "version": "0.2.3306",
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.3272",
32
+ "@ycodium-ai/plugin-api": "0.2.3306",
33
33
  "ycodium-executor-testing": "0.0.0"
34
34
  },
35
35
  "ycodium": {