@workflow-code/cli 0.2.4-20261010004.codex-cli-web → 0.2.4-20261011001.codex-cli-web

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.
package/dist/index.js CHANGED
@@ -24,7 +24,7 @@ async function main(argv = process.argv.slice(2)) {
24
24
  const prepared = prepareCliInvocation(argv);
25
25
  argv = prepared.argv;
26
26
  if (argv[0] === "web") {
27
- const webCli = await import("./web-KUC6BL6E.js");
27
+ const webCli = await import("./web-TJ2SME4G.js");
28
28
  return webCli.main(argv.slice(1));
29
29
  }
30
30
  if (argv[0] === "workspace") {
@@ -4183,10 +4183,13 @@ ${state.user?.avatarUrl ?? ""}`;
4183
4183
  try {
4184
4184
  if (this.token) {
4185
4185
  const session2 = await fetch("/api/session", { method: "POST", headers: { Authorization: `Bearer ${this.token}` }, signal: AbortSignal.timeout(1e4) });
4186
- if (!session2.ok) {
4186
+ if (session2.status === 401) {
4187
4187
  this.update("expired");
4188
4188
  return;
4189
4189
  }
4190
+ if (!session2.ok) {
4191
+ throw new Error("Cannot connect to the project.");
4192
+ }
4190
4193
  }
4191
4194
  const session = await fetch("/api/session", { headers: this.headers(), signal: AbortSignal.timeout(1e4) });
4192
4195
  if (session.status === 401) {
@@ -699,8 +699,29 @@ function createWebRuntime(projectDir, storageDir, connection) {
699
699
  return;
700
700
  }
701
701
  const auth = connection();
702
- const env = { ...process.env, WORKFLOW_RUNTIME_PLATFORM: "cli", WORKFLOW_SERVER_URL: auth?.serverUrl ?? "", WORKFLOW_SERVER_ADMIN_KEY: auth?.accessToken ?? "" };
703
- for (const key of ["TSX_TSCONFIG_PATH", "WORKFLOW_LOCAL_CORE_ROOT", "WORKFLOW_LOCAL_SHARED_ROOT", "WORKFLOW_LOCAL_SOURCE_MODE"]) {
702
+ if ((request.method === "run" || request.method === "resolve") && request.project?.requiresLogin && !auth) {
703
+ reject(new Error("Workflow Server login is not configured."));
704
+ return;
705
+ }
706
+ const env = {
707
+ ...process.env,
708
+ WORKFLOW_RUNTIME_PLATFORM: "cli",
709
+ WORKFLOW_SERVER_URL: auth?.serverUrl ?? "",
710
+ WORKFLOW_SERVER_ADMIN_KEY: auth?.accessToken ?? "",
711
+ WORKFLOW_SERVER_TOKEN: "",
712
+ WORKFLOW_LLM_SERVER_URL: auth?.serverUrl ?? "",
713
+ WORKFLOW_LLM_SERVER_TOKEN: auth?.accessToken ?? "",
714
+ WORKFLOW_CLI_AUTH_DIR: path.join(storageDir, "runtime-auth")
715
+ };
716
+ for (const key of [
717
+ "TSX_TSCONFIG_PATH",
718
+ "WORKFLOW_LOCAL_CORE_ROOT",
719
+ "WORKFLOW_LOCAL_SHARED_ROOT",
720
+ "WORKFLOW_LOCAL_SOURCE_MODE",
721
+ "WORKFLOW_DEVELOPER_ASSISTANT_HOST",
722
+ "WORKFLOW_DEVELOPER_ASSISTANT_WORKDIR",
723
+ "WORKFLOW_DEVELOPER_ASSISTANT_WORKSPACE_MANIFEST"
724
+ ]) {
704
725
  delete env[key];
705
726
  }
706
727
  if (env.NODE_OPTIONS) {
@@ -978,6 +999,7 @@ async function startWebServer(options) {
978
999
  let hostConnection = options.host?.connection;
979
1000
  let hostManaged = !!hostConnection;
980
1001
  let authEpoch = 0;
1002
+ let authCheck;
981
1003
  const sensitiveTokens = /* @__PURE__ */ new Set();
982
1004
  const runtime = options.runtime ?? createWebRuntime(projectDir, storageDir, () => connection);
983
1005
  let inspected;
@@ -1067,12 +1089,12 @@ async function startWebServer(options) {
1067
1089
  }
1068
1090
  });
1069
1091
  const refreshAuth = async (force = false) => {
1070
- if (passwordLogin || login) {
1092
+ if ((passwordLogin || login) && !force) {
1071
1093
  return;
1072
1094
  }
1073
- const epoch = ++authEpoch;
1095
+ const readingEpoch = authEpoch;
1074
1096
  const config = await readCliAuthConfig();
1075
- if (epoch !== authEpoch) {
1097
+ if (readingEpoch !== authEpoch) {
1076
1098
  return;
1077
1099
  }
1078
1100
  const serverUrl = hostManaged ? hostConnection?.serverUrl : process.env.WORKFLOW_SERVER_URL ?? config.serverUrl;
@@ -1082,31 +1104,44 @@ async function startWebServer(options) {
1082
1104
  }
1083
1105
  const identity = signedOut ? "" : `${serverUrl}
1084
1106
  ${token}`;
1085
- if (!force && identity === authIdentity && account.status !== "checking") {
1107
+ const expired = account.expiresAt && Date.parse(account.expiresAt) <= Date.now();
1108
+ if (!force && identity === authIdentity && account.status !== "error" && !expired) {
1086
1109
  return;
1087
1110
  }
1111
+ const epoch = ++authEpoch;
1112
+ authCheck?.abort();
1113
+ const check = authCheck = new AbortController();
1088
1114
  const changed = identity !== authIdentity;
1089
1115
  authIdentity = identity;
1090
- connection = !signedOut && serverUrl && token ? { serverUrl: serverUrl.replace(/\/+$/, ""), accessToken: token } : void 0;
1116
+ const candidate = !signedOut && serverUrl && token ? { serverUrl: serverUrl.replace(/\/+$/, ""), accessToken: token } : void 0;
1091
1117
  if (changed) {
1118
+ connection = void 0;
1092
1119
  authRevision++;
1093
1120
  parameterStates.clear();
1094
1121
  for (const session of controller.sessions) {
1095
1122
  controller.stop(session);
1096
1123
  }
1097
1124
  }
1098
- account = { status: connection ? "checking" : "signed-out", serverUrl: serverUrl || "http://localhost:7126", user: connection ? config.user ?? account.user : void 0, revision: account.revision + 1 };
1099
- if (connection) {
1125
+ account = { status: candidate ? "checking" : "signed-out", serverUrl: serverUrl || "http://localhost:7126", user: candidate ? changed ? hostManaged ? void 0 : config.user : account.user : void 0, revision: account.revision + 1 };
1126
+ if (candidate) {
1127
+ let unauthorized = false;
1100
1128
  try {
1101
- const response = await fetch(`${connection.serverUrl}/api/auth/me`, { headers: { Authorization: `Bearer ${connection.accessToken}` }, signal: AbortSignal.timeout(1e4), redirect: "error" });
1129
+ const response = await fetch(`${candidate.serverUrl}/api/auth/me`, { headers: { Authorization: `Bearer ${candidate.accessToken}` }, signal: AbortSignal.any([check.signal, AbortSignal.timeout(1e4)]), redirect: "error" });
1130
+ unauthorized = response.status === 401;
1102
1131
  const result = await response.json();
1103
1132
  if (epoch !== authEpoch) {
1104
1133
  return;
1105
1134
  }
1106
- if (!response.ok || result.errCode !== 0 || !result.data?.profile) {
1135
+ const profile = result.data?.profile;
1136
+ if (!response.ok || result.errCode !== 0 || typeof profile?.userId !== "string" || !profile.userId || typeof profile.email !== "string" || typeof profile.displayName !== "string") {
1107
1137
  throw new Error("Workflow login is invalid or expired.");
1108
1138
  }
1109
- account = { ...account, status: "authenticated", user: result.data.profile, expiresAt: result.data.principal?.expiresAt ?? config.expiresAt };
1139
+ if (!connection) {
1140
+ authRevision++;
1141
+ parameterStates.clear();
1142
+ }
1143
+ connection = candidate;
1144
+ account = { ...account, status: "authenticated", user: profile, expiresAt: result.data.principal?.expiresAt ?? config.expiresAt };
1110
1145
  } catch (error) {
1111
1146
  if (epoch !== authEpoch) {
1112
1147
  return;
@@ -1119,8 +1154,10 @@ ${token}`;
1119
1154
  controller.stop(session);
1120
1155
  }
1121
1156
  }
1122
- account = { ...account, status: "error", error: String(error.message) };
1157
+ account = { ...account, status: unauthorized ? "expired" : "error", error: String(error.message) };
1123
1158
  }
1159
+ } else {
1160
+ connection = void 0;
1124
1161
  }
1125
1162
  broadcast();
1126
1163
  };
@@ -1380,17 +1417,23 @@ ${token}`;
1380
1417
  account = { ...account, status: "checking" };
1381
1418
  broadcast();
1382
1419
  if (message.email !== void 0 || message.password !== void 0) {
1420
+ const epoch = ++authEpoch;
1383
1421
  passwordLogin = true;
1384
1422
  try {
1385
1423
  if (typeof message.email !== "string" || typeof message.password !== "string") {
1386
1424
  throw new Error("Invalid login credentials.");
1387
1425
  }
1388
1426
  await loginWebAccount(url.toString().replace(/\/+$/, ""), message.email, message.password);
1427
+ if (epoch !== authEpoch) {
1428
+ break;
1429
+ }
1389
1430
  hostManaged = false;
1390
1431
  hostConnection = void 0;
1391
1432
  } catch (error) {
1392
- account = { ...account, status: "error", error: String(error.message) };
1393
- broadcast();
1433
+ if (epoch === authEpoch) {
1434
+ account = { ...account, status: "error", error: String(error.message) };
1435
+ broadcast();
1436
+ }
1394
1437
  throw error;
1395
1438
  } finally {
1396
1439
  passwordLogin = false;
@@ -1434,7 +1477,9 @@ ${token}`;
1434
1477
  void (async () => {
1435
1478
  response.setHeader("X-Content-Type-Options", "nosniff");
1436
1479
  response.setHeader("Referrer-Policy", "no-referrer");
1437
- if (request.headers.host !== new URL(origin).host || request.headers.origin && request.headers.origin !== origin) {
1480
+ const host = new URL(`http://${request.headers.host ?? ""}`);
1481
+ const forwarded = !!options.host && ["127.0.0.1", "localhost", "[::1]"].includes(host.hostname) && !host.username && !host.password && host.pathname === "/" && !host.search && !host.hash;
1482
+ if (request.headers.host !== new URL(origin).host && !forwarded || request.headers.origin && request.headers.origin !== (forwarded ? host.origin : origin)) {
1438
1483
  json(response, 403, { message: "Invalid request origin." });
1439
1484
  return;
1440
1485
  }
@@ -1555,12 +1600,16 @@ ${token}`;
1555
1600
  project,
1556
1601
  controller,
1557
1602
  setHostConnection: async (value) => {
1603
+ authEpoch++;
1604
+ authCheck?.abort();
1558
1605
  hostConnection = value;
1559
1606
  hostManaged = true;
1560
1607
  signedOut = !value;
1561
1608
  await refreshAuth(true);
1562
1609
  },
1563
1610
  close: () => closing ??= (async () => {
1611
+ authEpoch++;
1612
+ authCheck?.abort();
1564
1613
  clearInterval(authPoll);
1565
1614
  if (broadcastTimer) {
1566
1615
  clearTimeout(broadcastTimer);
@@ -1712,7 +1761,11 @@ async function main(argv) {
1712
1761
  }
1713
1762
  const message = JSON.parse(line);
1714
1763
  if (message.type === "auth") {
1715
- await app.setHostConnection(parseHostConnection(message.connection));
1764
+ void app.setHostConnection(parseHostConnection(message.connection)).catch(() => {
1765
+ console.error("Workflow web host connection failed.");
1766
+ process.exitCode = 1;
1767
+ close();
1768
+ });
1716
1769
  } else if (message.type === "close") {
1717
1770
  break;
1718
1771
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workflow-code/cli",
3
- "version": "0.2.4-20261010004.codex-cli-web",
3
+ "version": "0.2.4-20261011001.codex-cli-web",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "workflow-code": "./dist/index.js"
@@ -37,14 +37,14 @@
37
37
  "workflow-code": "0.2.4-20260929001",
38
38
  "@workflow-code/auth-config": "0.1.0",
39
39
  "@workflow-code/execution-targets": "0.1.0",
40
- "@workflow-code/openai-responses": "0.1.0",
41
40
  "@workflow-code/i18n": "0.1.0",
42
- "@workflow-code/project-dependencies": "0.1.0",
41
+ "@workflow-code/openai-responses": "0.1.0",
43
42
  "@workflow-code/project-info": "0.1.0",
43
+ "@workflow-code/project-dependencies": "0.1.0",
44
44
  "@workflow-code/project-upload": "0.1.0",
45
- "@workflow-code/runtime-compatibility": "0.1.0",
46
45
  "@workflow-code/workflow-ids": "0.1.0",
47
- "@workflow-code/workflow-mcp": "0.1.0"
46
+ "@workflow-code/workflow-mcp": "0.1.0",
47
+ "@workflow-code/runtime-compatibility": "0.1.0"
48
48
  },
49
49
  "scripts": {
50
50
  "bootstrap": "node scripts/bootstrap.mjs",