@cmmd-center/forge 0.13.104 → 0.13.105

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 (21) hide show
  1. package/dist/bin.cjs +87 -11
  2. package/dist/bin.mjs +111 -35
  3. package/dist/client/assets/{CanvasPanel-tlS0QXvO.js → CanvasPanel-DUT9sMKg.js} +2 -2
  4. package/dist/client/assets/{CompositeItem-DCu1UyEF.js → CompositeItem-DYaCFJOM.js} +2 -2
  5. package/dist/client/assets/{DiffPanel-89ut3pmV.js → DiffPanel-39oCdRga.js} +2 -2
  6. package/dist/client/assets/{DiffPanel.logic-BjfUvx-E.js → DiffPanel.logic-tDue_WAk.js} +2 -2
  7. package/dist/client/assets/{DiffWorkerPoolProvider-CTEzb8Fm.js → DiffWorkerPoolProvider-vRqWW63d.js} +2 -2
  8. package/dist/client/assets/{PullRequestCodePanel-BonBT9Yf.js → PullRequestCodePanel-ptnd0PgJ.js} +2 -2
  9. package/dist/client/assets/{Virtualizer-CKmJ_jBK.js → Virtualizer-V9MT5-dt.js} +2 -2
  10. package/dist/client/assets/{WorkerPoolContext-Df1r2s84.js → WorkerPoolContext-DkzRaV5l.js} +3 -3
  11. package/dist/client/assets/{canvasStateStore-CDPIFPmE.js → canvasStateStore-Dk-UG8_D.js} +2 -2
  12. package/dist/client/assets/{cmmdAuthRedirect-DHcLFK1t.js → cmmdAuthRedirect-D9b4x37X.js} +2 -2
  13. package/dist/client/assets/{index-fKyHL662.js → index-Xjhbfluw.js} +6 -6
  14. package/dist/client/assets/{popover-DiRx-TPj.js → popover-BLN6-1Lv.js} +2 -2
  15. package/dist/client/assets/src-CP7pFzq9.js +3 -0
  16. package/dist/client/assets/{toggle-GakXma7U.js → toggle-D5P2us-a.js} +2 -2
  17. package/dist/client/index.html +10 -10
  18. package/dist/forge-build.json +1 -1
  19. package/dist/{open-2-reBrpv.mjs → open-yHTUkd2Y.mjs} +3 -3
  20. package/package.json +1 -1
  21. package/dist/client/assets/src-B-65kkmB.js +0 -3
package/dist/bin.mjs CHANGED
@@ -23,7 +23,7 @@ import { createCipheriv, createDecipheriv, createHash, createHmac, createPublicK
23
23
  import * as FS$1 from "node:fs";
24
24
  import fs, { accessSync, chmodSync, constants, createReadStream, existsSync, mkdirSync, mkdtempSync, promises, readFile, readFileSync, readdir, readdirSync, realpathSync, rmSync, statSync, unlinkSync, writeFileSync } from "node:fs";
25
25
  import * as NodeOS from "node:os";
26
- import $U, { homedir, networkInterfaces, tmpdir } from "node:os";
26
+ import os, { homedir, networkInterfaces, tmpdir } from "node:os";
27
27
  import * as Path$1 from "node:path";
28
28
  import path, { basename, delimiter, dirname, extname, isAbsolute, join, posix, relative, resolve, sep } from "node:path";
29
29
  import { pathToFileURL } from "node:url";
@@ -17794,6 +17794,7 @@ const OrchestrationThread = Struct({
17794
17794
  status: ThreadStatus.pipe(withDecodingDefault(succeed("idle"))),
17795
17795
  workerRole: NullOr(WorkerRole).pipe(withDecodingDefault(succeed(null))),
17796
17796
  workSessionId: optionalKey(NullOr(String$1)),
17797
+ workSessionBoundAt: optionalKey(NullOr(String$1)),
17797
17798
  pendingAutoCreatePrompt: optional$4(NullOr(AutoCreateTaskPrompt)).pipe(withDecodingDefault(succeed(null))),
17798
17799
  goal: NullOr(TrimmedNonEmptyString).pipe(withDecodingDefault(succeed(null))),
17799
17800
  titleRegeneration: NullOr(ThreadTitleRegeneration).pipe(withDecodingDefault(succeed(null))),
@@ -18375,6 +18376,7 @@ const ThreadCreatedPayload$1 = Struct({
18375
18376
  anchorKind: CmmdAnchorKind.pipe(withDecodingDefault(succeed("scratch"))),
18376
18377
  anchorCmmdId: NullOr(String$1).pipe(withDecodingDefault(succeed(null))),
18377
18378
  workSessionId: optionalKey(NullOr(String$1)),
18379
+ workSessionBoundAt: optionalKey(NullOr(String$1)),
18378
18380
  goal: optionalKey(NullOr(TrimmedNonEmptyString)),
18379
18381
  linkedPullRequest: optionalKey(NullOr(LinkedPullRequest)),
18380
18382
  kind: ThreadKind.pipe(withDecodingDefault(succeed("master"))),
@@ -18417,6 +18419,7 @@ const ThreadMetaUpdatedPayload$1 = Struct({
18417
18419
  parentThreadId: optional$4(NullOr(ThreadId)),
18418
18420
  workerRole: optional$4(NullOr(WorkerRole)),
18419
18421
  workSessionId: optional$4(NullOr(String$1)),
18422
+ workSessionBoundAt: optional$4(String$1),
18420
18423
  goal: optional$4(NullOr(TrimmedNonEmptyString)),
18421
18424
  linkedPullRequest: optional$4(NullOr(LinkedPullRequest)),
18422
18425
  regenerateTitle: optional$4(Literal(true)),
@@ -50653,7 +50656,7 @@ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
50653
50656
  const min = forceColor || 0;
50654
50657
  if (env.TERM === "dumb") return min;
50655
50658
  if (process$1.platform === "win32") {
50656
- const osRelease = $U.release().split(".");
50659
+ const osRelease = os.release().split(".");
50657
50660
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) return Number(osRelease[2]) >= 14931 ? 3 : 2;
50658
50661
  return 1;
50659
50662
  }
@@ -53096,7 +53099,7 @@ var require_ProcessDetector = /* @__PURE__ */ __commonJSMin(((exports) => {
53096
53099
  exports.processDetector = void 0;
53097
53100
  const api_1 = (init_esm$1(), __toCommonJS(esm_exports$1));
53098
53101
  const semconv_1 = require_semconv$1();
53099
- const os$3 = __require("os");
53102
+ const os$4 = __require("os");
53100
53103
  /**
53101
53104
  * ProcessDetector will be used to detect the resources related current process running
53102
53105
  * and being instrumented from the NodeJS Process module.
@@ -53118,7 +53121,7 @@ var require_ProcessDetector = /* @__PURE__ */ __commonJSMin(((exports) => {
53118
53121
  };
53119
53122
  if (process.argv.length > 1) attributes[semconv_1.ATTR_PROCESS_COMMAND] = process.argv[1];
53120
53123
  try {
53121
- const userInfo = os$3.userInfo();
53124
+ const userInfo = os$4.userInfo();
53122
53125
  attributes[semconv_1.ATTR_PROCESS_OWNER] = userInfo.username;
53123
53126
  } catch (e) {
53124
53127
  api_1.diag.debug(`error obtaining process owner: ${e}`);
@@ -66041,7 +66044,7 @@ function normalizeNumberish(value) {
66041
66044
  }
66042
66045
  //#endregion
66043
66046
  //#region package.json
66044
- var version$1 = "0.13.104";
66047
+ var version$1 = "0.13.105";
66045
66048
  //#endregion
66046
66049
  //#region src/sentry.ts
66047
66050
  const SERVER_APP_NAME = "forge-server";
@@ -76111,7 +76114,7 @@ var require_node_gyp_build = /* @__PURE__ */ __commonJSMin(((exports, module) =>
76111
76114
  var fs$6 = __require("fs");
76112
76115
  var path$5 = __require("path");
76113
76116
  var url$1 = __require("url");
76114
- var os$2 = __require("os");
76117
+ var os$3 = __require("os");
76115
76118
  var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
76116
76119
  var vars = process.config && process.config.variables || {};
76117
76120
  var prebuildsOnly = !!process.env.PREBUILDS_ONLY;
@@ -76119,8 +76122,8 @@ var require_node_gyp_build = /* @__PURE__ */ __commonJSMin(((exports, module) =>
76119
76122
  var abi = versions.modules;
76120
76123
  if (versions.deno || process.isBun) abi = "unsupported";
76121
76124
  var runtime = isElectron() ? "electron" : isNwjs() ? "node-webkit" : "node";
76122
- var arch = process.env.npm_config_arch || os$2.arch();
76123
- var platform = process.env.npm_config_platform || os$2.platform();
76125
+ var arch = process.env.npm_config_arch || os$3.arch();
76126
+ var platform = process.env.npm_config_platform || os$3.platform();
76124
76127
  var libc = process.env.LIBC || (isMusl(platform) ? "musl" : "glibc");
76125
76128
  var armv = process.env.ARM_VERSION || (arch === "arm64" ? "8" : vars.arm_version) || "";
76126
76129
  var uv = (versions.uv || "").split(".")[0];
@@ -93964,7 +93967,7 @@ const launchDetached = (launch) => gen(function* () {
93964
93967
  });
93965
93968
  const OpenLive = effect(Open, gen(function* () {
93966
93969
  const open = yield* tryPromise({
93967
- try: () => import("./open-2-reBrpv.mjs"),
93970
+ try: () => import("./open-yHTUkd2Y.mjs"),
93968
93971
  catch: (cause) => new OpenError$1({
93969
93972
  message: "failed to load browser opener",
93970
93973
  cause
@@ -115637,7 +115640,7 @@ const postgresSchemaStatements = [
115637
115640
  "CREATE TABLE IF NOT EXISTS checkpoint_diff_blobs (\n thread_id TEXT NOT NULL,\n from_turn_count INTEGER NOT NULL,\n to_turn_count INTEGER NOT NULL,\n diff TEXT NOT NULL,\n created_at TEXT NOT NULL,\n UNIQUE (thread_id, from_turn_count, to_turn_count)\n )",
115638
115641
  "CREATE TABLE IF NOT EXISTS provider_session_runtime (\n thread_id TEXT PRIMARY KEY,\n provider_name TEXT NOT NULL,\n adapter_key TEXT NOT NULL,\n runtime_mode TEXT NOT NULL DEFAULT 'full-access',\n status TEXT NOT NULL,\n last_seen_at TEXT NOT NULL,\n resume_cursor_json TEXT,\n runtime_payload_json TEXT\n )",
115639
115642
  "CREATE TABLE IF NOT EXISTS projection_projects (\n project_id TEXT PRIMARY KEY,\n title TEXT NOT NULL,\n workspace_root TEXT NOT NULL,\n scripts_json TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n deleted_at TEXT\n , default_model_selection_json TEXT, default_thread_env_mode TEXT, cmmd_registration_json TEXT)",
115640
- "CREATE TABLE IF NOT EXISTS projection_threads (\n thread_id TEXT PRIMARY KEY,\n project_id TEXT NOT NULL,\n title TEXT NOT NULL,\n branch TEXT,\n worktree_path TEXT,\n latest_turn_id TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n deleted_at TEXT\n , runtime_mode TEXT NOT NULL DEFAULT 'full-access', interaction_mode TEXT NOT NULL DEFAULT 'default', model_selection_json TEXT, archived_at TEXT, latest_user_message_at TEXT, pending_approval_count INTEGER NOT NULL DEFAULT 0, pending_user_input_count INTEGER NOT NULL DEFAULT 0, has_actionable_proposed_plan INTEGER NOT NULL DEFAULT 0, kind TEXT NOT NULL DEFAULT 'master', parent_thread_id TEXT, status TEXT NOT NULL DEFAULT 'idle', anchor_kind TEXT NOT NULL DEFAULT 'scratch', anchor_cmmd_id TEXT, worker_role TEXT DEFAULT NULL, goal TEXT, pending_auto_create_prompt_json TEXT, title_regeneration_json TEXT, rate_limit_status_json TEXT, linked_pull_request_json TEXT, settled_at TEXT, settled_override TEXT, work_session_id TEXT)",
115643
+ "CREATE TABLE IF NOT EXISTS projection_threads (\n thread_id TEXT PRIMARY KEY,\n project_id TEXT NOT NULL,\n title TEXT NOT NULL,\n branch TEXT,\n worktree_path TEXT,\n latest_turn_id TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n deleted_at TEXT\n , runtime_mode TEXT NOT NULL DEFAULT 'full-access', interaction_mode TEXT NOT NULL DEFAULT 'default', model_selection_json TEXT, archived_at TEXT, latest_user_message_at TEXT, pending_approval_count INTEGER NOT NULL DEFAULT 0, pending_user_input_count INTEGER NOT NULL DEFAULT 0, has_actionable_proposed_plan INTEGER NOT NULL DEFAULT 0, kind TEXT NOT NULL DEFAULT 'master', parent_thread_id TEXT, status TEXT NOT NULL DEFAULT 'idle', anchor_kind TEXT NOT NULL DEFAULT 'scratch', anchor_cmmd_id TEXT, worker_role TEXT DEFAULT NULL, goal TEXT, pending_auto_create_prompt_json TEXT, title_regeneration_json TEXT, rate_limit_status_json TEXT, linked_pull_request_json TEXT, settled_at TEXT, settled_override TEXT, work_session_id TEXT, work_session_bound_at TEXT)",
115641
115644
  "CREATE TABLE IF NOT EXISTS projection_thread_messages (\n message_id TEXT PRIMARY KEY,\n thread_id TEXT NOT NULL,\n turn_id TEXT,\n role TEXT NOT NULL,\n text TEXT NOT NULL,\n is_streaming INTEGER NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n , attachments_json TEXT)",
115642
115645
  "CREATE TABLE IF NOT EXISTS projection_thread_activities (\n activity_id TEXT PRIMARY KEY,\n thread_id TEXT NOT NULL,\n turn_id TEXT,\n tone TEXT NOT NULL,\n kind TEXT NOT NULL,\n summary TEXT NOT NULL,\n payload_json TEXT NOT NULL,\n created_at TEXT NOT NULL\n , sequence INTEGER)",
115643
115646
  "CREATE TABLE IF NOT EXISTS projection_thread_sessions (\n thread_id TEXT PRIMARY KEY,\n status TEXT NOT NULL,\n provider_name TEXT,\n provider_session_id TEXT,\n provider_thread_id TEXT,\n active_turn_id TEXT,\n last_error TEXT,\n updated_at TEXT NOT NULL\n , runtime_mode TEXT NOT NULL DEFAULT 'full-access')",
@@ -115959,7 +115962,8 @@ const postgresUpgradeMigrations = new Map([
115959
115962
  )
115960
115963
  WHERE model_selection_json IS NULL`
115961
115964
  ]],
115962
- [77, [`ALTER TABLE projection_threads ADD COLUMN IF NOT EXISTS work_session_id TEXT`]]
115965
+ [77, [`ALTER TABLE projection_threads ADD COLUMN IF NOT EXISTS work_session_id TEXT`]],
115966
+ [78, [`ALTER TABLE projection_threads ADD COLUMN IF NOT EXISTS work_session_bound_at TEXT`]]
115963
115967
  ]);
115964
115968
  function requirePostgresUpgradeStatements(version) {
115965
115969
  const statements = postgresUpgradeMigrations.get(version);
@@ -115985,15 +115989,15 @@ const runPostgresMigrations = fn$1("runPostgresMigrations")(function* () {
115985
115989
  ORDER BY version DESC
115986
115990
  LIMIT 1
115987
115991
  `)[0]?.version ?? 0;
115988
- if (currentVersion > 77) return yield* die$1(/* @__PURE__ */ new Error(`Forge Postgres schema ${currentVersion} is newer than server schema 77.`));
115992
+ if (currentVersion > 78) return yield* die$1(/* @__PURE__ */ new Error(`Forge Postgres schema ${currentVersion} is newer than server schema 78.`));
115989
115993
  if (currentVersion === 0) {
115990
115994
  for (const statement of postgresSchemaStatements) yield* sql.unsafe(statement);
115991
115995
  yield* sql`
115992
115996
  INSERT INTO forge_schema_migrations (version)
115993
- VALUES (${77})
115997
+ VALUES (${78})
115994
115998
  ON CONFLICT (version) DO NOTHING
115995
115999
  `;
115996
- } else for (let version = currentVersion + 1; version <= 77; version += 1) {
116000
+ } else for (let version = currentVersion + 1; version <= 78; version += 1) {
115997
116001
  const statements = yield* sync$1(() => requirePostgresUpgradeStatements(version));
115998
116002
  for (const statement of statements) yield* sql.unsafe(statement);
115999
116003
  yield* sql`
@@ -118789,6 +118793,18 @@ var _077_ProjectionThreadWorkSessionId_default = gen(function* () {
118789
118793
  `;
118790
118794
  });
118791
118795
  //#endregion
118796
+ //#region src/persistence/Migrations/078_ProjectionThreadWorkSessionBoundAt.ts
118797
+ /** Stores the timestamp of the last Work Session binding on a thread (forge#3597). */
118798
+ var _078_ProjectionThreadWorkSessionBoundAt_default = gen(function* () {
118799
+ const sql = yield* SqlClient;
118800
+ if (!(yield* sql`
118801
+ PRAGMA table_info(projection_threads)
118802
+ `).some((column) => column.name === "work_session_bound_at")) yield* sql`
118803
+ ALTER TABLE projection_threads
118804
+ ADD COLUMN work_session_bound_at TEXT
118805
+ `;
118806
+ });
118807
+ //#endregion
118792
118808
  //#region src/persistence/Migrations.ts
118793
118809
  /**
118794
118810
  * MigrationsLive - Migration runner with inline loader
@@ -119194,6 +119210,11 @@ const migrationEntries = [
119194
119210
  77,
119195
119211
  "ProjectionThreadWorkSessionId",
119196
119212
  _077_ProjectionThreadWorkSessionId_default
119213
+ ],
119214
+ [
119215
+ 78,
119216
+ "ProjectionThreadWorkSessionBoundAt",
119217
+ _078_ProjectionThreadWorkSessionBoundAt_default
119197
119218
  ]
119198
119219
  ];
119199
119220
  const makeMigrationLoader = (throughId) => fromRecord(Object.fromEntries(migrationEntries.filter(([id]) => throughId === void 0 || id <= throughId).map(([id, name, migration]) => [`${id}_${name}`, migration])));
@@ -192215,7 +192236,7 @@ var Vce = {
192215
192236
  function Ve() {
192216
192237
  return Vce;
192217
192238
  }
192218
- var Us = $U.homedir(), lk = $U.tmpdir(), { env: Vc } = process$1, Yce = (e) => {
192239
+ var Us = os.homedir(), lk = os.tmpdir(), { env: Vc } = process$1, Yce = (e) => {
192219
192240
  let t = path.join(Us, "Library");
192220
192241
  return {
192221
192242
  data: path.join(t, "Application Support", e),
@@ -202415,12 +202436,12 @@ function qZ(e, t) {
202415
202436
  }
202416
202437
  return n;
202417
202438
  }
202418
- var os$1 = "https://code.claude.com/docs/en", kKe = [
202439
+ var os$2 = "https://code.claude.com/docs/en", kKe = [
202419
202440
  {
202420
202441
  matches: (e) => e.path === "permissions.defaultMode" && e.code === "invalid_value",
202421
202442
  tip: {
202422
202443
  suggestion: "Valid modes: \"acceptEdits\" (ask before file changes), \"plan\" (analysis only), \"bypassPermissions\" (auto-accept all), or \"default\" (standard behavior)",
202423
- docLink: `${os$1}/iam#permission-modes`
202444
+ docLink: `${os$2}/iam#permission-modes`
202424
202445
  }
202425
202446
  },
202426
202447
  {
@@ -202435,7 +202456,7 @@ var os$1 = "https://code.claude.com/docs/en", kKe = [
202435
202456
  matches: (e) => e.path.startsWith("env.") && e.code === "invalid_type",
202436
202457
  tip: {
202437
202458
  suggestion: "Environment variables must be strings. Wrap numbers and booleans in quotes. Example: \"DEBUG\": \"true\", \"PORT\": \"3000\"",
202438
- docLink: `${os$1}/settings#environment-variables`
202459
+ docLink: `${os$2}/settings#environment-variables`
202439
202460
  }
202440
202461
  },
202441
202462
  {
@@ -202446,14 +202467,14 @@ var os$1 = "https://code.claude.com/docs/en", kKe = [
202446
202467
  matches: (e) => e.path.startsWith("hooks.") && e.code === "invalid_key",
202447
202468
  tip: {
202448
202469
  suggestion: "Not a recognized hook event. Common events: PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, SessionEnd, Stop. Check spelling and capitalization.",
202449
- docLink: `${os$1}/hooks`
202470
+ docLink: `${os$2}/hooks`
202450
202471
  }
202451
202472
  },
202452
202473
  {
202453
202474
  matches: (e) => /\.hooks\.\d+\.command$/.test(e.path) && e.code === "invalid_type" && e.received === "undefined",
202454
202475
  tip: {
202455
202476
  suggestion: "Command hooks require `command`. For exec form (no shell), set `command` to the executable and `args` to its arguments: {\"type\": \"command\", \"command\": \"echo\", \"args\": [\"hi\"]}. For shell form, set `command` to the full shell string: {\"type\": \"command\", \"command\": \"echo hi\"}.",
202456
- docLink: `${os$1}/hooks#exec-form-and-shell-form`
202477
+ docLink: `${os$2}/hooks#exec-form-and-shell-form`
202457
202478
  }
202458
202479
  },
202459
202480
  {
@@ -202468,7 +202489,7 @@ var os$1 = "https://code.claude.com/docs/en", kKe = [
202468
202489
  matches: (e) => e.code === "unrecognized_keys",
202469
202490
  tip: {
202470
202491
  suggestion: "Check for typos or refer to the documentation for valid fields",
202471
- docLink: `${os$1}/settings`
202492
+ docLink: `${os$2}/settings`
202472
202493
  }
202473
202494
  },
202474
202495
  {
@@ -202483,13 +202504,13 @@ var os$1 = "https://code.claude.com/docs/en", kKe = [
202483
202504
  matches: (e) => e.path === "permissions.additionalDirectories" && e.code === "invalid_type",
202484
202505
  tip: {
202485
202506
  suggestion: "Must be an array of directory paths. Example: [\"~/projects\", \"/tmp/workspace\"]. You can also use --add-dir flag or /add-dir command",
202486
- docLink: `${os$1}/iam#working-directories`
202507
+ docLink: `${os$2}/iam#working-directories`
202487
202508
  }
202488
202509
  }
202489
202510
  ], AKe = {
202490
- permissions: `${os$1}/iam#configuring-permissions`,
202491
- env: `${os$1}/settings#environment-variables`,
202492
- hooks: `${os$1}/hooks`
202511
+ permissions: `${os$2}/iam#configuring-permissions`,
202512
+ env: `${os$2}/settings#environment-variables`,
202513
+ hooks: `${os$2}/hooks`
202493
202514
  };
202494
202515
  function GZ(e) {
202495
202516
  let t = kKe.find((r) => r.matches(e));
@@ -271014,7 +271035,7 @@ var import_multicast_dns = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMi
271014
271035
  var dgram = __require("dgram");
271015
271036
  var thunky = require_thunky();
271016
271037
  var events = __require("events");
271017
- var os = __require("os");
271038
+ var os$1 = __require("os");
271018
271039
  var noop = function() {};
271019
271040
  module.exports = function(opts) {
271020
271041
  if (!opts) opts = {};
@@ -271145,14 +271166,14 @@ var import_multicast_dns = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMi
271145
271166
  return that;
271146
271167
  };
271147
271168
  function defaultInterface() {
271148
- var networks = os.networkInterfaces();
271169
+ var networks = os$1.networkInterfaces();
271149
271170
  var names = Object.keys(networks);
271150
271171
  for (var i = 0; i < names.length; i++) {
271151
271172
  var net = networks[names[i]];
271152
271173
  for (var j = 0; j < net.length; j++) {
271153
271174
  var iface = net[j];
271154
271175
  if (isIPv4(iface.family) && !iface.internal) {
271155
- if (os.platform() === "darwin" && names[i] === "en0") return iface.address;
271176
+ if (os$1.platform() === "darwin" && names[i] === "en0") return iface.address;
271156
271177
  return "0.0.0.0";
271157
271178
  }
271158
271179
  }
@@ -271160,7 +271181,7 @@ var import_multicast_dns = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMi
271160
271181
  return "127.0.0.1";
271161
271182
  }
271162
271183
  function allInterfaces() {
271163
- var networks = os.networkInterfaces();
271184
+ var networks = os$1.networkInterfaces();
271164
271185
  var names = Object.keys(networks);
271165
271186
  var res = [];
271166
271187
  for (var i = 0; i < names.length; i++) {
@@ -288425,6 +288446,7 @@ const ProjectionThread = Struct({
288425
288446
  anchorKind: CmmdAnchorKind.pipe(withDecodingDefault(succeed("scratch"))),
288426
288447
  anchorCmmdId: NullOr(String$1).pipe(withDecodingDefault(succeed(null))),
288427
288448
  workSessionId: optionalKey(NullOr(String$1)),
288449
+ workSessionBoundAt: optionalKey(NullOr(String$1)),
288428
288450
  linkedPullRequest: optionalKey(NullOr(LinkedPullRequest)),
288429
288451
  status: ThreadStatus.pipe(withDecodingDefault(succeed("idle"))),
288430
288452
  workerRole: NullOr(WorkerRole).pipe(withDecodingDefault(succeed(null))),
@@ -293179,6 +293201,15 @@ const ProviderCommandReactorLive = effect(ProviderCommandReactor, gen(function*
293179
293201
  * (FOR-2605).
293180
293202
  */
293181
293203
  const threadSessionAccountIds = /* @__PURE__ */ new Map();
293204
+ /**
293205
+ * The Work Session id each LIVE provider session was started for.
293206
+ *
293207
+ * A Retry creates a new Work Session B on a thread whose session ran for A.
293208
+ * The reactor sees `thread.workSessionId === B` while the session still holds
293209
+ * A's egress credential. Tracking the start-time value lets the reactor
293210
+ * detect the mismatch and restart, dropping A's cached token (forge#3597).
293211
+ */
293212
+ const threadSessionWorkSessionIds = /* @__PURE__ */ new Map();
293182
293213
  const appendProviderFailureActivity = (input) => orchestrationEngine.dispatch({
293183
293214
  type: "thread.activity.append",
293184
293215
  commandId: serverCommandId$2("provider-failure-activity"),
@@ -293247,6 +293278,7 @@ const ProviderCommandReactorLive = effect(ProviderCommandReactor, gen(function*
293247
293278
  runtimeMode: desiredRuntimeMode
293248
293279
  }), () => sync$1(() => {
293249
293280
  threadSessionAccountIds.set(threadId, readProviderAccountId(desiredModelSelection));
293281
+ threadSessionWorkSessionIds.set(threadId, thread.workSessionId ?? null);
293250
293282
  }));
293251
293283
  const bindSessionToThread = (session) => setThreadSession({
293252
293284
  threadId,
@@ -293285,7 +293317,18 @@ const ProviderCommandReactorLive = effect(ProviderCommandReactor, gen(function*
293285
293317
  const desiredAccountId = readProviderAccountId(desiredModelSelection);
293286
293318
  const activeAccountId = threadSessionAccountIds.get(threadId);
293287
293319
  const shouldRestartForAccountChange = threadSessionAccountIds.has(threadId) && activeAccountId !== desiredAccountId;
293288
- if (!runtimeModeChanged && !providerChanged && !shouldRestartForModelChange && !shouldRestartForModelSelectionChange && !shouldRestartForAccountChange) return existingSessionThreadId;
293320
+ /**
293321
+ * A Retry creates a new Work Session B on a thread whose session was
293322
+ * running for A. Once the projector applies the rebind event,
293323
+ * `thread.workSessionId` is B. The session's egress credential was
293324
+ * issued for A and CMMD rejects it with `session_ended` on the first
293325
+ * tool call. Restarting the session drops the cached credential so the
293326
+ * new session mints one bound to B (forge#3597).
293327
+ */
293328
+ const currentWorkSessionId = thread.workSessionId ?? null;
293329
+ const sessionWorkSessionId = threadSessionWorkSessionIds.get(threadId);
293330
+ const shouldRestartForWorkSessionChange = threadSessionWorkSessionIds.has(threadId) && sessionWorkSessionId !== currentWorkSessionId;
293331
+ if (!runtimeModeChanged && !providerChanged && !shouldRestartForModelChange && !shouldRestartForModelSelectionChange && !shouldRestartForAccountChange && !shouldRestartForWorkSessionChange) return existingSessionThreadId;
293289
293332
  const resumeCursor = providerChanged || shouldRestartForModelChange ? void 0 : activeSession?.resumeCursor ?? void 0;
293290
293333
  yield* logInfo("provider command reactor restarting provider session", {
293291
293334
  threadId,
@@ -293300,9 +293343,10 @@ const ProviderCommandReactorLive = effect(ProviderCommandReactor, gen(function*
293300
293343
  shouldRestartForModelChange,
293301
293344
  shouldRestartForModelSelectionChange,
293302
293345
  shouldRestartForAccountChange,
293346
+ shouldRestartForWorkSessionChange,
293303
293347
  hasResumeCursor: resumeCursor !== void 0
293304
293348
  });
293305
- if (shouldRestartForAccountChange || providerChanged) yield* providerService.stopSession({
293349
+ if (shouldRestartForAccountChange || shouldRestartForWorkSessionChange || providerChanged) yield* providerService.stopSession({
293306
293350
  threadId,
293307
293351
  preserveResumeState: true
293308
293352
  });
@@ -299744,7 +299788,7 @@ function resolveBuildCommitFromEnv(env) {
299744
299788
  * environment descriptor down instead of reporting an honest "unknown".
299745
299789
  */
299746
299790
  function readBakedBuildCommit() {
299747
- return "e2a39e58fa5d81fe19ff492769b0aba4ddc75c7f";
299791
+ return "52da43d14c8834d5585c39f2faed4463ed5c8132";
299748
299792
  }
299749
299793
  async function resolveServerBuildCommit(input) {
299750
299794
  if (isFullCommitSha(input.baked)) return input.baked;
@@ -303591,6 +303635,7 @@ const decideOrchestrationCommand = fn$1("decideOrchestrationCommand")(function*
303591
303635
  anchorKind: anchor.anchorKind,
303592
303636
  anchorCmmdId: anchor.anchorCmmdId,
303593
303637
  workSessionId: command.workSessionId ?? null,
303638
+ ...command.workSessionId != null ? { workSessionBoundAt: command.createdAt } : {},
303594
303639
  goal: command.goal ?? null,
303595
303640
  linkedPullRequest: command.linkedPullRequest ?? null,
303596
303641
  kind,
@@ -303900,8 +303945,13 @@ const decideOrchestrationCommand = fn$1("decideOrchestrationCommand")(function*
303900
303945
  const providerSwitchSelection = command.modelSelection !== void 0 && command.modelSelection.provider !== targetThread.modelSelection.provider ? command.modelSelection : void 0;
303901
303946
  const accountSelection = turnAccountSelection(targetThread.modelSelection, command.modelSelection);
303902
303947
  const turnModelSelection = providerSwitchSelection ?? accountSelection;
303948
+ if (command.workSessionId !== void 0 && command.workSessionId !== null && command.workSessionId !== targetThread.workSessionId && targetThread.workSessionBoundAt !== void 0 && targetThread.workSessionBoundAt !== null && command.createdAt <= targetThread.workSessionBoundAt) return yield* new OrchestrationCommandInvariantError({
303949
+ commandType: command.type,
303950
+ detail: `Stale Work Session rebind: kick for session ${String(command.workSessionId)} at ${command.createdAt} is not after workSessionBoundAt ${String(targetThread.workSessionBoundAt)} on thread ${command.threadId}. Thread stays bound to ${String(targetThread.workSessionId)}.`
303951
+ });
303903
303952
  const shouldRebindWorkSession = command.workSessionId !== void 0 && command.workSessionId !== null && command.workSessionId !== targetThread.workSessionId;
303904
- if (!shouldUpdateAnchor && !turnModelSelection && !shouldRebindWorkSession) return [userMessageEvent, turnStartRequestedEvent];
303953
+ const shouldAdvanceBoundTimestamp = !shouldRebindWorkSession && command.workSessionId !== void 0 && command.workSessionId !== null && command.workSessionId === targetThread.workSessionId && (targetThread.workSessionBoundAt === null || targetThread.workSessionBoundAt === void 0 || command.createdAt > targetThread.workSessionBoundAt);
303954
+ if (!shouldUpdateAnchor && !turnModelSelection && !shouldRebindWorkSession && !shouldAdvanceBoundTimestamp) return [userMessageEvent, turnStartRequestedEvent];
303905
303955
  return [
303906
303956
  {
303907
303957
  ...withEventBase({
@@ -303916,7 +303966,10 @@ const decideOrchestrationCommand = fn$1("decideOrchestrationCommand")(function*
303916
303966
  anchorKind: nextAnchor.anchorKind,
303917
303967
  anchorCmmdId: nextAnchor.anchorCmmdId,
303918
303968
  ...turnModelSelection ? { modelSelection: turnModelSelection } : {},
303919
- ...shouldRebindWorkSession ? { workSessionId: command.workSessionId } : {},
303969
+ ...shouldRebindWorkSession ? {
303970
+ workSessionId: command.workSessionId,
303971
+ workSessionBoundAt: command.createdAt
303972
+ } : shouldAdvanceBoundTimestamp ? { workSessionBoundAt: command.createdAt } : {},
303920
303973
  updatedAt: command.createdAt
303921
303974
  }
303922
303975
  },
@@ -304487,6 +304540,7 @@ function projectEvent(model, event) {
304487
304540
  anchorKind: payload.anchorKind,
304488
304541
  anchorCmmdId: payload.anchorCmmdId,
304489
304542
  workSessionId: payload.workSessionId ?? null,
304543
+ workSessionBoundAt: payload.workSessionBoundAt ?? null,
304490
304544
  goal: payload.goal ?? null,
304491
304545
  linkedPullRequest: payload.linkedPullRequest ?? null,
304492
304546
  titleRegeneration: null,
@@ -304568,6 +304622,7 @@ function projectEvent(model, event) {
304568
304622
  ...payload.linkedPullRequest !== void 0 ? { linkedPullRequest: payload.linkedPullRequest } : {},
304569
304623
  ...payload.titleRegeneration !== void 0 ? { titleRegeneration: payload.titleRegeneration } : {},
304570
304624
  ...payload.workSessionId !== void 0 ? { workSessionId: payload.workSessionId } : {},
304625
+ ...payload.workSessionBoundAt !== void 0 ? { workSessionBoundAt: payload.workSessionBoundAt } : {},
304571
304626
  updatedAt: payload.updatedAt
304572
304627
  })
304573
304628
  })));
@@ -305619,6 +305674,7 @@ const ProjectionThreadRepositoryLive = effect(ProjectionThreadRepository, gen(fu
305619
305674
  anchor_kind,
305620
305675
  anchor_cmmd_id,
305621
305676
  work_session_id,
305677
+ work_session_bound_at,
305622
305678
  linked_pull_request_json,
305623
305679
  status,
305624
305680
  worker_role,
@@ -305652,6 +305708,7 @@ const ProjectionThreadRepositoryLive = effect(ProjectionThreadRepository, gen(fu
305652
305708
  ${row.anchorKind},
305653
305709
  ${row.anchorCmmdId},
305654
305710
  ${row.workSessionId ?? null},
305711
+ ${row.workSessionBoundAt ?? null},
305655
305712
  ${row.linkedPullRequest == null ? null : JSON.stringify(row.linkedPullRequest)},
305656
305713
  ${row.status},
305657
305714
  ${row.workerRole},
@@ -305685,6 +305742,7 @@ const ProjectionThreadRepositoryLive = effect(ProjectionThreadRepository, gen(fu
305685
305742
  anchor_kind = excluded.anchor_kind,
305686
305743
  anchor_cmmd_id = excluded.anchor_cmmd_id,
305687
305744
  work_session_id = excluded.work_session_id,
305745
+ work_session_bound_at = excluded.work_session_bound_at,
305688
305746
  linked_pull_request_json = excluded.linked_pull_request_json,
305689
305747
  status = excluded.status,
305690
305748
  worker_role = excluded.worker_role,
@@ -305723,6 +305781,7 @@ const ProjectionThreadRepositoryLive = effect(ProjectionThreadRepository, gen(fu
305723
305781
  anchor_kind AS "anchorKind",
305724
305782
  anchor_cmmd_id AS "anchorCmmdId",
305725
305783
  work_session_id AS "workSessionId",
305784
+ work_session_bound_at AS "workSessionBoundAt",
305726
305785
  linked_pull_request_json AS "linkedPullRequest",
305727
305786
  status,
305728
305787
  worker_role AS "workerRole",
@@ -305763,6 +305822,7 @@ const ProjectionThreadRepositoryLive = effect(ProjectionThreadRepository, gen(fu
305763
305822
  anchor_kind AS "anchorKind",
305764
305823
  anchor_cmmd_id AS "anchorCmmdId",
305765
305824
  work_session_id AS "workSessionId",
305825
+ work_session_bound_at AS "workSessionBoundAt",
305766
305826
  linked_pull_request_json AS "linkedPullRequest",
305767
305827
  status,
305768
305828
  worker_role AS "workerRole",
@@ -306115,6 +306175,7 @@ const OrchestrationProjectionPipelineLive = effect(OrchestrationProjectionPipeli
306115
306175
  anchorKind: event.payload.anchorKind,
306116
306176
  anchorCmmdId: event.payload.anchorCmmdId,
306117
306177
  workSessionId: projectedWorkSessionId(event.payload.workSessionId),
306178
+ workSessionBoundAt: event.payload.workSessionBoundAt ?? null,
306118
306179
  linkedPullRequest: event.payload.linkedPullRequest ?? null,
306119
306180
  status: event.payload.status,
306120
306181
  workerRole: event.payload.workerRole,
@@ -306153,6 +306214,7 @@ const OrchestrationProjectionPipelineLive = effect(OrchestrationProjectionPipeli
306153
306214
  anchorKind: thread.anchorKind,
306154
306215
  anchorCmmdId: thread.anchorCmmdId,
306155
306216
  workSessionId: projectedWorkSessionId(thread.workSessionId),
306217
+ workSessionBoundAt: thread.workSessionBoundAt ?? null,
306156
306218
  linkedPullRequest: thread.linkedPullRequest ?? null,
306157
306219
  status: thread.status,
306158
306220
  workerRole: thread.workerRole,
@@ -306222,6 +306284,7 @@ const OrchestrationProjectionPipelineLive = effect(OrchestrationProjectionPipeli
306222
306284
  ...event.payload.linkedPullRequest !== void 0 ? { linkedPullRequest: event.payload.linkedPullRequest } : {},
306223
306285
  ...event.payload.titleRegeneration !== void 0 ? { titleRegeneration: event.payload.titleRegeneration } : {},
306224
306286
  ...event.payload.workSessionId !== void 0 ? { workSessionId: projectedWorkSessionId(event.payload.workSessionId) } : {},
306287
+ ...event.payload.workSessionBoundAt !== void 0 ? { workSessionBoundAt: event.payload.workSessionBoundAt } : {},
306225
306288
  updatedAt: event.payload.updatedAt
306226
306289
  });
306227
306290
  return;
@@ -307230,6 +307293,13 @@ function toPersistenceSqlOrDecodeError(sqlOperation, decodeOperation) {
307230
307293
  function workSessionIdField(workSessionId) {
307231
307294
  return workSessionId !== void 0 ? { workSessionId } : {};
307232
307295
  }
307296
+ /**
307297
+ * `{ workSessionBoundAt }` when the row carries one, an empty object when absent.
307298
+ * Mirrors `workSessionIdField` so `exactOptionalPropertyTypes` is satisfied. See forge#3611.
307299
+ */
307300
+ function workSessionBoundAtField(workSessionBoundAt) {
307301
+ return workSessionBoundAt !== void 0 ? { workSessionBoundAt } : {};
307302
+ }
307233
307303
  const OrchestrationInfrastructureLayerLive = mergeAll(effect(ProjectionSnapshotQuery, gen(function* () {
307234
307304
  const sql = yield* SqlClient;
307235
307305
  const repositoryIdentityResolver = yield* RepositoryIdentityResolver;
@@ -307283,6 +307353,7 @@ const OrchestrationInfrastructureLayerLive = mergeAll(effect(ProjectionSnapshotQ
307283
307353
  anchor_kind AS "anchorKind",
307284
307354
  anchor_cmmd_id AS "anchorCmmdId",
307285
307355
  work_session_id AS "workSessionId",
307356
+ work_session_bound_at AS "workSessionBoundAt",
307286
307357
  linked_pull_request_json AS "linkedPullRequest",
307287
307358
  status,
307288
307359
  worker_role AS "workerRole",
@@ -307322,6 +307393,7 @@ const OrchestrationInfrastructureLayerLive = mergeAll(effect(ProjectionSnapshotQ
307322
307393
  anchor_kind AS "anchorKind",
307323
307394
  anchor_cmmd_id AS "anchorCmmdId",
307324
307395
  work_session_id AS "workSessionId",
307396
+ work_session_bound_at AS "workSessionBoundAt",
307325
307397
  linked_pull_request_json AS "linkedPullRequest",
307326
307398
  status,
307327
307399
  worker_role AS "workerRole",
@@ -307427,6 +307499,7 @@ const OrchestrationInfrastructureLayerLive = mergeAll(effect(ProjectionSnapshotQ
307427
307499
  anchor_kind AS "anchorKind",
307428
307500
  anchor_cmmd_id AS "anchorCmmdId",
307429
307501
  work_session_id AS "workSessionId",
307502
+ work_session_bound_at AS "workSessionBoundAt",
307430
307503
  linked_pull_request_json AS "linkedPullRequest",
307431
307504
  status,
307432
307505
  worker_role AS "workerRole",
@@ -307760,6 +307833,7 @@ const OrchestrationInfrastructureLayerLive = mergeAll(effect(ProjectionSnapshotQ
307760
307833
  anchor_kind AS "anchorKind",
307761
307834
  anchor_cmmd_id AS "anchorCmmdId",
307762
307835
  work_session_id AS "workSessionId",
307836
+ work_session_bound_at AS "workSessionBoundAt",
307763
307837
  linked_pull_request_json AS "linkedPullRequest",
307764
307838
  status,
307765
307839
  worker_role AS "workerRole",
@@ -308073,6 +308147,7 @@ const OrchestrationInfrastructureLayerLive = mergeAll(effect(ProjectionSnapshotQ
308073
308147
  anchorKind: row.anchorKind,
308074
308148
  anchorCmmdId: row.anchorCmmdId,
308075
308149
  ...workSessionIdField(row.workSessionId),
308150
+ ...workSessionBoundAtField(row.workSessionBoundAt),
308076
308151
  linkedPullRequest: row.linkedPullRequest,
308077
308152
  kind: row.kind,
308078
308153
  parentThreadId: row.parentThreadId,
@@ -308323,6 +308398,7 @@ const OrchestrationInfrastructureLayerLive = mergeAll(effect(ProjectionSnapshotQ
308323
308398
  anchorKind: threadRow.value.anchorKind,
308324
308399
  anchorCmmdId: threadRow.value.anchorCmmdId,
308325
308400
  ...workSessionIdField(threadRow.value.workSessionId),
308401
+ ...workSessionBoundAtField(threadRow.value.workSessionBoundAt),
308326
308402
  linkedPullRequest: threadRow.value.linkedPullRequest,
308327
308403
  kind: threadRow.value.kind,
308328
308404
  parentThreadId: threadRow.value.parentThreadId,
@@ -324721,7 +324797,7 @@ const connectLoginCommand = make$33("login", {
324721
324797
  })).json();
324722
324798
  },
324723
324799
  openBrowser: async (url) => {
324724
- const open = (await import("./open-2-reBrpv.mjs")).default;
324800
+ const open = (await import("./open-yHTUkd2Y.mjs")).default;
324725
324801
  await open(url);
324726
324802
  return true;
324727
324803
  },