@cmmd-center/forge 0.13.89 → 0.13.91
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/bin.cjs +377 -50
- package/dist/bin.mjs +398 -74
- package/dist/client/assets/{CanvasPanel-D9NzolmF.js → CanvasPanel-By1TNSCJ.js} +2 -2
- package/dist/client/assets/{CompositeItem-DU4kdAw6.js → CompositeItem-B4KFI6uM.js} +2 -2
- package/dist/client/assets/{DiffPanel-Dx1AY0mg.js → DiffPanel-BiNw2LQH.js} +2 -2
- package/dist/client/assets/{DiffPanel.logic-BiyBXIja.js → DiffPanel.logic-w5A538H2.js} +2 -2
- package/dist/client/assets/{DiffWorkerPoolProvider-jDqu6eJj.js → DiffWorkerPoolProvider-NwR6dTfX.js} +2 -2
- package/dist/client/assets/{PullRequestCodePanel-CqrN4lB_.js → PullRequestCodePanel-CkPd76Ea.js} +2 -2
- package/dist/client/assets/{Virtualizer-D-5QCW79.js → Virtualizer-BBvJHcYh.js} +2 -2
- package/dist/client/assets/{WorkerPoolContext-BxfSg7K_.js → WorkerPoolContext-BAaHKB2s.js} +3 -3
- package/dist/client/assets/{canvasStateStore-CBQkAlnK.js → canvasStateStore-DoXLRnB-.js} +2 -2
- package/dist/client/assets/{cmmdAuthRedirect-CCwq2L-I.js → cmmdAuthRedirect-Bx5ApJLL.js} +2 -2
- package/dist/client/assets/{index-BrOo-A0J.js → index-kD30f58L.js} +6 -6
- package/dist/client/assets/{popover-DJpPSHsy.js → popover-DlZTqPIV.js} +2 -2
- package/dist/client/assets/src-1F7f5y9L.js +3 -0
- package/dist/client/assets/{toggle-Bv2GfLGu.js → toggle-BwedUJ-z.js} +2 -2
- package/dist/client/index.html +10 -10
- package/dist/forge-build.json +1 -1
- package/dist/{open-yHTUkd2Y.mjs → open-2-reBrpv.mjs} +3 -3
- package/package.json +1 -1
- package/dist/client/assets/src-CF8xm6xH.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
|
|
26
|
+
import $U, { 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";
|
|
@@ -17793,6 +17793,7 @@ const OrchestrationThread = Struct({
|
|
|
17793
17793
|
parentThreadId: NullOr(ThreadId).pipe(withDecodingDefault(succeed(null))),
|
|
17794
17794
|
status: ThreadStatus.pipe(withDecodingDefault(succeed("idle"))),
|
|
17795
17795
|
workerRole: NullOr(WorkerRole).pipe(withDecodingDefault(succeed(null))),
|
|
17796
|
+
workSessionId: optionalKey(NullOr(String$1)),
|
|
17796
17797
|
pendingAutoCreatePrompt: optional$4(NullOr(AutoCreateTaskPrompt)).pipe(withDecodingDefault(succeed(null))),
|
|
17797
17798
|
goal: NullOr(TrimmedNonEmptyString).pipe(withDecodingDefault(succeed(null))),
|
|
17798
17799
|
titleRegeneration: NullOr(ThreadTitleRegeneration).pipe(withDecodingDefault(succeed(null))),
|
|
@@ -17940,6 +17941,15 @@ const ProjectDeleteCommand = Struct({
|
|
|
17940
17941
|
commandId: CommandId,
|
|
17941
17942
|
projectId: ProjectId
|
|
17942
17943
|
});
|
|
17944
|
+
/**
|
|
17945
|
+
* The CMMD Work Session id a command may carry (forge#3466 review, nit 9).
|
|
17946
|
+
* CMMD's capability broker requires 1 to 256 characters; bounding it here
|
|
17947
|
+
* rejects a malformed id at the door instead of letting decide-time code find
|
|
17948
|
+
* out. Command-only: the read model and its events keep decoding a plain
|
|
17949
|
+
* string so a row or a journaled event written before this bound existed
|
|
17950
|
+
* still loads.
|
|
17951
|
+
*/
|
|
17952
|
+
const CommandWorkSessionId = TrimmedNonEmptyString.check(isMaxLength(256));
|
|
17943
17953
|
const ThreadCreateCommand = Struct({
|
|
17944
17954
|
type: Literal("thread.create"),
|
|
17945
17955
|
commandId: CommandId,
|
|
@@ -17953,6 +17963,7 @@ const ThreadCreateCommand = Struct({
|
|
|
17953
17963
|
worktreePath: NullOr(TrimmedNonEmptyString),
|
|
17954
17964
|
anchorKind: optional$4(CmmdAnchorKind),
|
|
17955
17965
|
anchorCmmdId: optional$4(NullOr(String$1)),
|
|
17966
|
+
workSessionId: optional$4(NullOr(CommandWorkSessionId)),
|
|
17956
17967
|
goal: optional$4(NullOr(TrimmedNonEmptyString)),
|
|
17957
17968
|
linkedPullRequest: optional$4(NullOr(LinkedPullRequest)),
|
|
17958
17969
|
kind: optional$4(ThreadKind),
|
|
@@ -18062,7 +18073,8 @@ const ThreadTurnStartCommand = Struct({
|
|
|
18062
18073
|
anchorCmmdId: optional$4(NullOr(String$1)),
|
|
18063
18074
|
kind: optional$4(ThreadKind),
|
|
18064
18075
|
parentThreadId: optional$4(NullOr(ThreadId)),
|
|
18065
|
-
createdAt: IsoDateTime
|
|
18076
|
+
createdAt: IsoDateTime,
|
|
18077
|
+
workSessionId: optional$4(NullOr(CommandWorkSessionId))
|
|
18066
18078
|
});
|
|
18067
18079
|
const ClientThreadTurnStartCommand = Struct({
|
|
18068
18080
|
type: Literal("thread.turn.start"),
|
|
@@ -18085,7 +18097,8 @@ const ClientThreadTurnStartCommand = Struct({
|
|
|
18085
18097
|
anchorCmmdId: optional$4(NullOr(String$1)),
|
|
18086
18098
|
kind: optional$4(ThreadKind),
|
|
18087
18099
|
parentThreadId: optional$4(NullOr(ThreadId)),
|
|
18088
|
-
createdAt: IsoDateTime
|
|
18100
|
+
createdAt: IsoDateTime,
|
|
18101
|
+
workSessionId: optional$4(NullOr(CommandWorkSessionId))
|
|
18089
18102
|
});
|
|
18090
18103
|
const ThreadTurnInterruptCommand = Struct({
|
|
18091
18104
|
type: Literal("thread.turn.interrupt"),
|
|
@@ -18361,6 +18374,7 @@ const ThreadCreatedPayload$1 = Struct({
|
|
|
18361
18374
|
settledOverride: optional$4(SettledOverride),
|
|
18362
18375
|
anchorKind: CmmdAnchorKind.pipe(withDecodingDefault(succeed("scratch"))),
|
|
18363
18376
|
anchorCmmdId: NullOr(String$1).pipe(withDecodingDefault(succeed(null))),
|
|
18377
|
+
workSessionId: optionalKey(NullOr(String$1)),
|
|
18364
18378
|
goal: optionalKey(NullOr(TrimmedNonEmptyString)),
|
|
18365
18379
|
linkedPullRequest: optionalKey(NullOr(LinkedPullRequest)),
|
|
18366
18380
|
kind: ThreadKind.pipe(withDecodingDefault(succeed("master"))),
|
|
@@ -18402,6 +18416,7 @@ const ThreadMetaUpdatedPayload$1 = Struct({
|
|
|
18402
18416
|
status: optional$4(ThreadStatus),
|
|
18403
18417
|
parentThreadId: optional$4(NullOr(ThreadId)),
|
|
18404
18418
|
workerRole: optional$4(NullOr(WorkerRole)),
|
|
18419
|
+
workSessionId: optional$4(NullOr(String$1)),
|
|
18405
18420
|
goal: optional$4(NullOr(TrimmedNonEmptyString)),
|
|
18406
18421
|
linkedPullRequest: optional$4(NullOr(LinkedPullRequest)),
|
|
18407
18422
|
regenerateTitle: optional$4(Literal(true)),
|
|
@@ -50617,7 +50632,7 @@ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
|
|
|
50617
50632
|
const min = forceColor || 0;
|
|
50618
50633
|
if (env.TERM === "dumb") return min;
|
|
50619
50634
|
if (process$1.platform === "win32") {
|
|
50620
|
-
const osRelease =
|
|
50635
|
+
const osRelease = $U.release().split(".");
|
|
50621
50636
|
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
50622
50637
|
return 1;
|
|
50623
50638
|
}
|
|
@@ -53060,7 +53075,7 @@ var require_ProcessDetector = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
53060
53075
|
exports.processDetector = void 0;
|
|
53061
53076
|
const api_1 = (init_esm$1(), __toCommonJS(esm_exports$1));
|
|
53062
53077
|
const semconv_1 = require_semconv$1();
|
|
53063
|
-
const os$
|
|
53078
|
+
const os$3 = __require("os");
|
|
53064
53079
|
/**
|
|
53065
53080
|
* ProcessDetector will be used to detect the resources related current process running
|
|
53066
53081
|
* and being instrumented from the NodeJS Process module.
|
|
@@ -53082,7 +53097,7 @@ var require_ProcessDetector = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
53082
53097
|
};
|
|
53083
53098
|
if (process.argv.length > 1) attributes[semconv_1.ATTR_PROCESS_COMMAND] = process.argv[1];
|
|
53084
53099
|
try {
|
|
53085
|
-
const userInfo = os$
|
|
53100
|
+
const userInfo = os$3.userInfo();
|
|
53086
53101
|
attributes[semconv_1.ATTR_PROCESS_OWNER] = userInfo.username;
|
|
53087
53102
|
} catch (e) {
|
|
53088
53103
|
api_1.diag.debug(`error obtaining process owner: ${e}`);
|
|
@@ -66005,7 +66020,7 @@ function normalizeNumberish(value) {
|
|
|
66005
66020
|
}
|
|
66006
66021
|
//#endregion
|
|
66007
66022
|
//#region package.json
|
|
66008
|
-
var version$1 = "0.13.
|
|
66023
|
+
var version$1 = "0.13.91";
|
|
66009
66024
|
//#endregion
|
|
66010
66025
|
//#region src/sentry.ts
|
|
66011
66026
|
const SERVER_APP_NAME = "forge-server";
|
|
@@ -76051,7 +76066,7 @@ var require_node_gyp_build = /* @__PURE__ */ __commonJSMin(((exports, module) =>
|
|
|
76051
76066
|
var fs$6 = __require("fs");
|
|
76052
76067
|
var path$5 = __require("path");
|
|
76053
76068
|
var url$1 = __require("url");
|
|
76054
|
-
var os$
|
|
76069
|
+
var os$2 = __require("os");
|
|
76055
76070
|
var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
|
|
76056
76071
|
var vars = process.config && process.config.variables || {};
|
|
76057
76072
|
var prebuildsOnly = !!process.env.PREBUILDS_ONLY;
|
|
@@ -76059,8 +76074,8 @@ var require_node_gyp_build = /* @__PURE__ */ __commonJSMin(((exports, module) =>
|
|
|
76059
76074
|
var abi = versions.modules;
|
|
76060
76075
|
if (versions.deno || process.isBun) abi = "unsupported";
|
|
76061
76076
|
var runtime = isElectron() ? "electron" : isNwjs() ? "node-webkit" : "node";
|
|
76062
|
-
var arch = process.env.npm_config_arch || os$
|
|
76063
|
-
var platform = process.env.npm_config_platform || os$
|
|
76077
|
+
var arch = process.env.npm_config_arch || os$2.arch();
|
|
76078
|
+
var platform = process.env.npm_config_platform || os$2.platform();
|
|
76064
76079
|
var libc = process.env.LIBC || (isMusl(platform) ? "musl" : "glibc");
|
|
76065
76080
|
var armv = process.env.ARM_VERSION || (arch === "arm64" ? "8" : vars.arm_version) || "";
|
|
76066
76081
|
var uv = (versions.uv || "").split(".")[0];
|
|
@@ -87586,7 +87601,8 @@ const brokerScopes = new Set([
|
|
|
87586
87601
|
"github",
|
|
87587
87602
|
"provider",
|
|
87588
87603
|
"package",
|
|
87589
|
-
"scm"
|
|
87604
|
+
"scm",
|
|
87605
|
+
"sidekick"
|
|
87590
87606
|
]);
|
|
87591
87607
|
const defaultOwnerId = "interactive";
|
|
87592
87608
|
const authorities = /* @__PURE__ */ new Map();
|
|
@@ -87740,6 +87756,19 @@ function readRuntimeBrokerAuthorityForRuntime(input) {
|
|
|
87740
87756
|
}
|
|
87741
87757
|
//#endregion
|
|
87742
87758
|
//#region src/runtimeAuth/runtimeBrokerIdentity.ts
|
|
87759
|
+
/**
|
|
87760
|
+
* Whether this process is a CMMD-managed per-project cloud runtime (a
|
|
87761
|
+
* sprite), never a local Forge desktop or dev process. Shared by
|
|
87762
|
+
* `GitHubBroker.resolveRuntimeGrant` and
|
|
87763
|
+
* `cmmdWorkSessionCapabilityBroker.resolveWorkSessionSidekickRuntimeGrant`
|
|
87764
|
+
* (forge#3466 review, should-fix 4) so the two runtime-grant resolvers gate
|
|
87765
|
+
* on the same runtime-role signal instead of each inferring it separately.
|
|
87766
|
+
* Mirrors the env parsing `providerEgressToken.ts` and `ServerEnvironment.ts`
|
|
87767
|
+
* already use for the same signal.
|
|
87768
|
+
*/
|
|
87769
|
+
function isCmmdCloudRuntimeModeEnv() {
|
|
87770
|
+
return process.env.FORGE_CMMD_RUNTIME_MODE === "true" || process.env.FORGE_CMMD_RUNTIME_MODE === "1";
|
|
87771
|
+
}
|
|
87743
87772
|
function classifyRuntimeBrokerIdentity(input) {
|
|
87744
87773
|
const machineId = input.machineId?.trim();
|
|
87745
87774
|
const credentialEpoch = input.credentialEpoch;
|
|
@@ -90764,9 +90793,6 @@ var GitHubBroker = class {
|
|
|
90764
90793
|
return validateGitBranchName(branch) ?? branch;
|
|
90765
90794
|
}
|
|
90766
90795
|
};
|
|
90767
|
-
function isCmmdCloudRuntimeModeEnv() {
|
|
90768
|
-
return process.env.FORGE_CMMD_RUNTIME_MODE === "true" || process.env.FORGE_CMMD_RUNTIME_MODE === "1";
|
|
90769
|
-
}
|
|
90770
90796
|
function inferGitHubBrokerRuntimeRole() {
|
|
90771
90797
|
if (isCmmdCloudRuntimeModeEnv()) return "user-vm";
|
|
90772
90798
|
return "local";
|
|
@@ -93893,7 +93919,7 @@ const launchDetached = (launch) => gen(function* () {
|
|
|
93893
93919
|
});
|
|
93894
93920
|
const OpenLive = effect(Open, gen(function* () {
|
|
93895
93921
|
const open = yield* tryPromise({
|
|
93896
|
-
try: () => import("./open-
|
|
93922
|
+
try: () => import("./open-2-reBrpv.mjs"),
|
|
93897
93923
|
catch: (cause) => new OpenError$1({
|
|
93898
93924
|
message: "failed to load browser opener",
|
|
93899
93925
|
cause
|
|
@@ -115274,7 +115300,7 @@ const postgresSchemaStatements = [
|
|
|
115274
115300
|
"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 )",
|
|
115275
115301
|
"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 )",
|
|
115276
115302
|
"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)",
|
|
115277
|
-
"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)",
|
|
115303
|
+
"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)",
|
|
115278
115304
|
"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)",
|
|
115279
115305
|
"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)",
|
|
115280
115306
|
"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')",
|
|
@@ -115595,7 +115621,8 @@ const postgresUpgradeMigrations = new Map([
|
|
|
115595
115621
|
LIMIT 1
|
|
115596
115622
|
)
|
|
115597
115623
|
WHERE model_selection_json IS NULL`
|
|
115598
|
-
]]
|
|
115624
|
+
]],
|
|
115625
|
+
[77, [`ALTER TABLE projection_threads ADD COLUMN IF NOT EXISTS work_session_id TEXT`]]
|
|
115599
115626
|
]);
|
|
115600
115627
|
function requirePostgresUpgradeStatements(version) {
|
|
115601
115628
|
const statements = postgresUpgradeMigrations.get(version);
|
|
@@ -115621,15 +115648,15 @@ const runPostgresMigrations = fn$1("runPostgresMigrations")(function* () {
|
|
|
115621
115648
|
ORDER BY version DESC
|
|
115622
115649
|
LIMIT 1
|
|
115623
115650
|
`)[0]?.version ?? 0;
|
|
115624
|
-
if (currentVersion >
|
|
115651
|
+
if (currentVersion > 77) return yield* die$1(/* @__PURE__ */ new Error(`Forge Postgres schema ${currentVersion} is newer than server schema 77.`));
|
|
115625
115652
|
if (currentVersion === 0) {
|
|
115626
115653
|
for (const statement of postgresSchemaStatements) yield* sql.unsafe(statement);
|
|
115627
115654
|
yield* sql`
|
|
115628
115655
|
INSERT INTO forge_schema_migrations (version)
|
|
115629
|
-
VALUES (${
|
|
115656
|
+
VALUES (${77})
|
|
115630
115657
|
ON CONFLICT (version) DO NOTHING
|
|
115631
115658
|
`;
|
|
115632
|
-
} else for (let version = currentVersion + 1; version <=
|
|
115659
|
+
} else for (let version = currentVersion + 1; version <= 77; version += 1) {
|
|
115633
115660
|
const statements = yield* sync$1(() => requirePostgresUpgradeStatements(version));
|
|
115634
115661
|
for (const statement of statements) yield* sql.unsafe(statement);
|
|
115635
115662
|
yield* sql`
|
|
@@ -118413,6 +118440,18 @@ var _076_ProjectionTurnsModelSelection_default = gen(function* () {
|
|
|
118413
118440
|
`;
|
|
118414
118441
|
});
|
|
118415
118442
|
//#endregion
|
|
118443
|
+
//#region src/persistence/Migrations/077_ProjectionThreadWorkSessionId.ts
|
|
118444
|
+
/** Stores the CMMD Work Session id a kicked thread's root turn belongs to (forge#3466). */
|
|
118445
|
+
var _077_ProjectionThreadWorkSessionId_default = gen(function* () {
|
|
118446
|
+
const sql = yield* SqlClient;
|
|
118447
|
+
if (!(yield* sql`
|
|
118448
|
+
PRAGMA table_info(projection_threads)
|
|
118449
|
+
`).some((column) => column.name === "work_session_id")) yield* sql`
|
|
118450
|
+
ALTER TABLE projection_threads
|
|
118451
|
+
ADD COLUMN work_session_id TEXT
|
|
118452
|
+
`;
|
|
118453
|
+
});
|
|
118454
|
+
//#endregion
|
|
118416
118455
|
//#region src/persistence/Migrations.ts
|
|
118417
118456
|
/**
|
|
118418
118457
|
* MigrationsLive - Migration runner with inline loader
|
|
@@ -118813,6 +118852,11 @@ const migrationEntries = [
|
|
|
118813
118852
|
76,
|
|
118814
118853
|
"ProjectionTurnsModelSelection",
|
|
118815
118854
|
_076_ProjectionTurnsModelSelection_default
|
|
118855
|
+
],
|
|
118856
|
+
[
|
|
118857
|
+
77,
|
|
118858
|
+
"ProjectionThreadWorkSessionId",
|
|
118859
|
+
_077_ProjectionThreadWorkSessionId_default
|
|
118816
118860
|
]
|
|
118817
118861
|
];
|
|
118818
118862
|
const makeMigrationLoader = (throughId) => fromRecord(Object.fromEntries(migrationEntries.filter(([id]) => throughId === void 0 || id <= throughId).map(([id, name, migration]) => [`${id}_${name}`, migration])));
|
|
@@ -152169,10 +152213,10 @@ function getOpenAiProviderEgressProxyConfig(input) {
|
|
|
152169
152213
|
message: `Workspace OpenAI provider egress is configured, but OPENAI_BASE_URL does not point at ${OPENAI_PROVIDER_EGRESS_PATH}. Refusing to start Codex with a stale or raw OPENAI_API_KEY.`
|
|
152170
152214
|
};
|
|
152171
152215
|
}
|
|
152172
|
-
function configuredRuntimeMachineId() {
|
|
152216
|
+
function configuredRuntimeMachineId$1() {
|
|
152173
152217
|
return process.env.FORGE_CMMD_RUNTIME_MACHINE_ID?.trim() || null;
|
|
152174
152218
|
}
|
|
152175
|
-
function configuredRuntimeCredentialEpoch() {
|
|
152219
|
+
function configuredRuntimeCredentialEpoch$1() {
|
|
152176
152220
|
const raw = process.env.FORGE_CMMD_RUNTIME_CREDENTIAL_EPOCH?.trim();
|
|
152177
152221
|
return raw === void 0 ? void 0 : Number(raw);
|
|
152178
152222
|
}
|
|
@@ -152243,15 +152287,15 @@ function resolveBrokerTicketOutcome(input) {
|
|
|
152243
152287
|
function providerEgressRequiresOwnerSession() {
|
|
152244
152288
|
if (!canIssueCmmdRuntimeProviderEgressToken()) return false;
|
|
152245
152289
|
return classifyRuntimeBrokerIdentity({
|
|
152246
|
-
machineId: configuredRuntimeMachineId() ?? void 0,
|
|
152247
|
-
credentialEpoch: configuredRuntimeCredentialEpoch(),
|
|
152290
|
+
machineId: configuredRuntimeMachineId$1() ?? void 0,
|
|
152291
|
+
credentialEpoch: configuredRuntimeCredentialEpoch$1(),
|
|
152248
152292
|
brokerAuthorityMode: process.env.FORGE_CMMD_RUNTIME_BROKER_AUTHORITY_MODE
|
|
152249
152293
|
}).mode === "exact";
|
|
152250
152294
|
}
|
|
152251
152295
|
function runtimeProviderBrokerToken(input) {
|
|
152252
152296
|
const identity = classifyRuntimeBrokerIdentity({
|
|
152253
|
-
machineId: configuredRuntimeMachineId() ?? void 0,
|
|
152254
|
-
credentialEpoch: configuredRuntimeCredentialEpoch(),
|
|
152297
|
+
machineId: configuredRuntimeMachineId$1() ?? void 0,
|
|
152298
|
+
credentialEpoch: configuredRuntimeCredentialEpoch$1(),
|
|
152255
152299
|
brokerAuthorityMode: process.env.FORGE_CMMD_RUNTIME_BROKER_AUTHORITY_MODE
|
|
152256
152300
|
});
|
|
152257
152301
|
if (identity.mode !== "exact") return resolveBrokerTicketOutcome({
|
|
@@ -152366,7 +152410,8 @@ async function issueCmmdRuntimeProviderEgressCredential(input) {
|
|
|
152366
152410
|
body: JSON.stringify({
|
|
152367
152411
|
provider: input.provider,
|
|
152368
152412
|
...providerEgressModelBodyFields(input),
|
|
152369
|
-
...input.provider === "openai" && input.providerAccountId ? { provider_account_id: input.providerAccountId } : {}
|
|
152413
|
+
...input.provider === "openai" && input.providerAccountId ? { provider_account_id: input.providerAccountId } : {},
|
|
152414
|
+
...input.threadId ? { thread_id: input.threadId } : {}
|
|
152370
152415
|
})
|
|
152371
152416
|
});
|
|
152372
152417
|
if (!response.ok) throw new Error(await describeProviderTokenFailure(response));
|
|
@@ -152391,8 +152436,8 @@ function runtimeCredentialFromGrant(provider, payload, controlPlaneUrl) {
|
|
|
152391
152436
|
return deliveryBoundRuntimeCredential(provider, payload, controlPlaneUrl);
|
|
152392
152437
|
}
|
|
152393
152438
|
function deliveryBoundRuntimeCredential(provider, payload, controlPlaneUrl) {
|
|
152394
|
-
const runtimeMachineId = configuredRuntimeMachineId();
|
|
152395
|
-
const runtimeCredentialEpoch = configuredRuntimeCredentialEpoch();
|
|
152439
|
+
const runtimeMachineId = configuredRuntimeMachineId$1();
|
|
152440
|
+
const runtimeCredentialEpoch = configuredRuntimeCredentialEpoch$1();
|
|
152396
152441
|
if (!runtimeMachineId || runtimeCredentialEpoch === void 0) throw new Error("Provider proxy token response was missing exact runtime authority.");
|
|
152397
152442
|
const deliveryReceipt = parseProviderRuntimeDeliveryReceipt(payload.deliveryReceipt, {
|
|
152398
152443
|
provider,
|
|
@@ -191832,7 +191877,7 @@ var Vce = {
|
|
|
191832
191877
|
function Ve() {
|
|
191833
191878
|
return Vce;
|
|
191834
191879
|
}
|
|
191835
|
-
var Us =
|
|
191880
|
+
var Us = $U.homedir(), lk = $U.tmpdir(), { env: Vc } = process$1, Yce = (e) => {
|
|
191836
191881
|
let t = path.join(Us, "Library");
|
|
191837
191882
|
return {
|
|
191838
191883
|
data: path.join(t, "Application Support", e),
|
|
@@ -202032,12 +202077,12 @@ function qZ(e, t) {
|
|
|
202032
202077
|
}
|
|
202033
202078
|
return n;
|
|
202034
202079
|
}
|
|
202035
|
-
var os$
|
|
202080
|
+
var os$1 = "https://code.claude.com/docs/en", kKe = [
|
|
202036
202081
|
{
|
|
202037
202082
|
matches: (e) => e.path === "permissions.defaultMode" && e.code === "invalid_value",
|
|
202038
202083
|
tip: {
|
|
202039
202084
|
suggestion: "Valid modes: \"acceptEdits\" (ask before file changes), \"plan\" (analysis only), \"bypassPermissions\" (auto-accept all), or \"default\" (standard behavior)",
|
|
202040
|
-
docLink: `${os$
|
|
202085
|
+
docLink: `${os$1}/iam#permission-modes`
|
|
202041
202086
|
}
|
|
202042
202087
|
},
|
|
202043
202088
|
{
|
|
@@ -202052,7 +202097,7 @@ var os$2 = "https://code.claude.com/docs/en", kKe = [
|
|
|
202052
202097
|
matches: (e) => e.path.startsWith("env.") && e.code === "invalid_type",
|
|
202053
202098
|
tip: {
|
|
202054
202099
|
suggestion: "Environment variables must be strings. Wrap numbers and booleans in quotes. Example: \"DEBUG\": \"true\", \"PORT\": \"3000\"",
|
|
202055
|
-
docLink: `${os$
|
|
202100
|
+
docLink: `${os$1}/settings#environment-variables`
|
|
202056
202101
|
}
|
|
202057
202102
|
},
|
|
202058
202103
|
{
|
|
@@ -202063,14 +202108,14 @@ var os$2 = "https://code.claude.com/docs/en", kKe = [
|
|
|
202063
202108
|
matches: (e) => e.path.startsWith("hooks.") && e.code === "invalid_key",
|
|
202064
202109
|
tip: {
|
|
202065
202110
|
suggestion: "Not a recognized hook event. Common events: PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, SessionEnd, Stop. Check spelling and capitalization.",
|
|
202066
|
-
docLink: `${os$
|
|
202111
|
+
docLink: `${os$1}/hooks`
|
|
202067
202112
|
}
|
|
202068
202113
|
},
|
|
202069
202114
|
{
|
|
202070
202115
|
matches: (e) => /\.hooks\.\d+\.command$/.test(e.path) && e.code === "invalid_type" && e.received === "undefined",
|
|
202071
202116
|
tip: {
|
|
202072
202117
|
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\"}.",
|
|
202073
|
-
docLink: `${os$
|
|
202118
|
+
docLink: `${os$1}/hooks#exec-form-and-shell-form`
|
|
202074
202119
|
}
|
|
202075
202120
|
},
|
|
202076
202121
|
{
|
|
@@ -202085,7 +202130,7 @@ var os$2 = "https://code.claude.com/docs/en", kKe = [
|
|
|
202085
202130
|
matches: (e) => e.code === "unrecognized_keys",
|
|
202086
202131
|
tip: {
|
|
202087
202132
|
suggestion: "Check for typos or refer to the documentation for valid fields",
|
|
202088
|
-
docLink: `${os$
|
|
202133
|
+
docLink: `${os$1}/settings`
|
|
202089
202134
|
}
|
|
202090
202135
|
},
|
|
202091
202136
|
{
|
|
@@ -202100,13 +202145,13 @@ var os$2 = "https://code.claude.com/docs/en", kKe = [
|
|
|
202100
202145
|
matches: (e) => e.path === "permissions.additionalDirectories" && e.code === "invalid_type",
|
|
202101
202146
|
tip: {
|
|
202102
202147
|
suggestion: "Must be an array of directory paths. Example: [\"~/projects\", \"/tmp/workspace\"]. You can also use --add-dir flag or /add-dir command",
|
|
202103
|
-
docLink: `${os$
|
|
202148
|
+
docLink: `${os$1}/iam#working-directories`
|
|
202104
202149
|
}
|
|
202105
202150
|
}
|
|
202106
202151
|
], AKe = {
|
|
202107
|
-
permissions: `${os$
|
|
202108
|
-
env: `${os$
|
|
202109
|
-
hooks: `${os$
|
|
202152
|
+
permissions: `${os$1}/iam#configuring-permissions`,
|
|
202153
|
+
env: `${os$1}/settings#environment-variables`,
|
|
202154
|
+
hooks: `${os$1}/hooks`
|
|
202110
202155
|
};
|
|
202111
202156
|
function GZ(e) {
|
|
202112
202157
|
let t = kKe.find((r) => r.matches(e));
|
|
@@ -211534,7 +211579,7 @@ function createCodexCmmdSidekickDynamicToolHandler(session) {
|
|
|
211534
211579
|
//#region src/cmmdData/cmmdDelegatedToolCatalog.ts
|
|
211535
211580
|
const CATALOG_PATH = "/api/forge/context/sidekick/tools/catalog";
|
|
211536
211581
|
const EXECUTE_PATH = "/api/forge/context/sidekick/tools/execute";
|
|
211537
|
-
const AUTH_REQUIRED = {
|
|
211582
|
+
const AUTH_REQUIRED$1 = {
|
|
211538
211583
|
ok: false,
|
|
211539
211584
|
code: "CMMD_AUTH_REQUIRED"
|
|
211540
211585
|
};
|
|
@@ -211542,11 +211587,32 @@ function upstreamErrorCode(error) {
|
|
|
211542
211587
|
if (error && typeof error === "object" && "code" in error && typeof error.code === "string") return error.code;
|
|
211543
211588
|
return "CMMD_REST_ERROR";
|
|
211544
211589
|
}
|
|
211545
|
-
|
|
211590
|
+
/**
|
|
211591
|
+
* The Work Session lane, tried before the owner-JWT lane ever runs
|
|
211592
|
+
* (forge#3466 review, should-fix 3). A headless sprite's Work Session thread
|
|
211593
|
+
* never carries an owner JWT (CMMD ADR-015), so trying that lane first only
|
|
211594
|
+
* spends a lookup before falling through to the same broker call every time
|
|
211595
|
+
* — and on a sprite in runtime mode, the owner's browser and CMMD's kick
|
|
211596
|
+
* authenticate into the same synthetic session, so a resolved JWT there is
|
|
211597
|
+
* never legitimately this Work Session's own. Reading fresh on every call,
|
|
211598
|
+
* not once at construction, is what makes blocker 1's fix work: session
|
|
211599
|
+
* start, the ~30-second renewal, and a post-`capability_invalid` re-mint all
|
|
211600
|
+
* land here, so a Retry that rebinds the thread mid-session is picked up on
|
|
211601
|
+
* its very next mint instead of being stuck asking for the session that just
|
|
211602
|
+
* failed. Returns null (not a failure) for a person-started thread, which
|
|
211603
|
+
* supplies no `readWorkSessionId` and keeps today's owner lane byte for byte.
|
|
211604
|
+
*/
|
|
211605
|
+
async function resolveViaWorkSession(workSessionCapability, scope) {
|
|
211606
|
+
const workSessionId = workSessionCapability.readWorkSessionId ? await workSessionCapability.readWorkSessionId() : null;
|
|
211607
|
+
if (workSessionId === null) return null;
|
|
211608
|
+
return workSessionCapability.requestCapability ? workSessionCapability.requestCapability(workSessionId, scope.threadId) : AUTH_REQUIRED$1;
|
|
211609
|
+
}
|
|
211610
|
+
async function listCatalog(resolveJwt, workSessionCapability, scope) {
|
|
211611
|
+
const viaWorkSession = await resolveViaWorkSession(workSessionCapability, scope);
|
|
211612
|
+
if (viaWorkSession !== null) return viaWorkSession;
|
|
211546
211613
|
const sessionId = readThreadSessionId(scope.threadId);
|
|
211547
|
-
|
|
211548
|
-
|
|
211549
|
-
if (!jwt) return AUTH_REQUIRED;
|
|
211614
|
+
const jwt = sessionId ? await resolveJwt(sessionId) : null;
|
|
211615
|
+
if (!jwt) return AUTH_REQUIRED$1;
|
|
211550
211616
|
const body = { forgeThreadId: scope.threadId };
|
|
211551
211617
|
if (scope.projectId !== void 0) body["projectId"] = scope.projectId;
|
|
211552
211618
|
if (scope.forgeAgentId !== void 0) body["forgeAgentId"] = scope.forgeAgentId;
|
|
@@ -211596,9 +211662,9 @@ async function execute(request) {
|
|
|
211596
211662
|
};
|
|
211597
211663
|
}
|
|
211598
211664
|
}
|
|
211599
|
-
function createCmmdDelegatedToolCatalogClient(resolveJwt) {
|
|
211665
|
+
function createCmmdDelegatedToolCatalogClient(resolveJwt, workSessionCapability = {}) {
|
|
211600
211666
|
return {
|
|
211601
|
-
listCatalog: (scope) => listCatalog(resolveJwt, scope),
|
|
211667
|
+
listCatalog: (scope) => listCatalog(resolveJwt, workSessionCapability, scope),
|
|
211602
211668
|
execute
|
|
211603
211669
|
};
|
|
211604
211670
|
}
|
|
@@ -211653,9 +211719,144 @@ function createCmmdSidekickToolSession(client, scope) {
|
|
|
211653
211719
|
};
|
|
211654
211720
|
}
|
|
211655
211721
|
//#endregion
|
|
211722
|
+
//#region src/cmmdData/cmmdWorkSessionCapabilityBroker.ts
|
|
211723
|
+
/**
|
|
211724
|
+
* CMMD's Work Session Sidekick-capability broker client (forge#3466,
|
|
211725
|
+
* CMMD#5026).
|
|
211726
|
+
*
|
|
211727
|
+
* A headless sprite runs a Work Session's root thread with no owner JWT or
|
|
211728
|
+
* PAT: nobody signed in. `cmmdDelegatedToolCatalog.ts`'s owner-JWT lane falls
|
|
211729
|
+
* through to this one instead, presenting the runtime's OWN grant (never a
|
|
211730
|
+
* JWT, per CMMD ADR-015) plus the Work Session id CMMD stamped on the thread,
|
|
211731
|
+
* and getting back the same delegated Sidekick capability shape the owner
|
|
211732
|
+
* lane mints.
|
|
211733
|
+
*/
|
|
211734
|
+
const SIDEKICK_CAPABILITY_TIMEOUT_MS = 1e4;
|
|
211735
|
+
const AUTH_REQUIRED = {
|
|
211736
|
+
ok: false,
|
|
211737
|
+
code: "CMMD_AUTH_REQUIRED"
|
|
211738
|
+
};
|
|
211739
|
+
function configuredRuntimeMachineId() {
|
|
211740
|
+
return process.env.FORGE_CMMD_RUNTIME_MACHINE_ID?.trim() || void 0;
|
|
211741
|
+
}
|
|
211742
|
+
function configuredRuntimeCredentialEpoch() {
|
|
211743
|
+
const raw = process.env.FORGE_CMMD_RUNTIME_CREDENTIAL_EPOCH?.trim();
|
|
211744
|
+
return raw === void 0 ? void 0 : Number(raw);
|
|
211745
|
+
}
|
|
211746
|
+
/**
|
|
211747
|
+
* The runtime's own bearer for the "sidekick" broker scope.
|
|
211748
|
+
*
|
|
211749
|
+
* Follows the same exact-machine / legacy split as
|
|
211750
|
+
* `GitHubBroker.resolveRuntimeGrant`, including its `runtimeRole !== "user-vm"`
|
|
211751
|
+
* gate (forge#3466 review, should-fix 4, via the resolver both share:
|
|
211752
|
+
* `isCmmdCloudRuntimeModeEnv`): an exact-machine runtime presents whatever
|
|
211753
|
+
* ticket CMMD already delivered into the broker-authority cache for this
|
|
211754
|
+
* scope (an inbound request installs it as a side effect of authenticating;
|
|
211755
|
+
* CMMD's runtime ticket carries `sidekick` alongside `provider`/`github`/etc,
|
|
211756
|
+
* so it lands there the same way). A legacy runtime presents its one
|
|
211757
|
+
* portable grant token. A runtime with no id, an identity that is neither
|
|
211758
|
+
* exact nor legacy, or a role that isn't a managed CMMD cloud runtime at
|
|
211759
|
+
* all, has nothing to present — a local Forge with a stray
|
|
211760
|
+
* `FORGE_CMMD_RUNTIME_ID` left over from a legacy config must never present
|
|
211761
|
+
* its portable grant token as though it were a sprite.
|
|
211762
|
+
*/
|
|
211763
|
+
function resolveWorkSessionSidekickRuntimeGrant() {
|
|
211764
|
+
if (!isCmmdCloudRuntimeModeEnv()) return null;
|
|
211765
|
+
const runtimeId = process.env.FORGE_CMMD_RUNTIME_ID?.trim();
|
|
211766
|
+
if (!runtimeId) return null;
|
|
211767
|
+
const identity = classifyRuntimeBrokerIdentity({
|
|
211768
|
+
machineId: configuredRuntimeMachineId(),
|
|
211769
|
+
credentialEpoch: configuredRuntimeCredentialEpoch(),
|
|
211770
|
+
brokerAuthorityMode: process.env.FORGE_CMMD_RUNTIME_BROKER_AUTHORITY_MODE
|
|
211771
|
+
});
|
|
211772
|
+
if (identity.mode === "exact") {
|
|
211773
|
+
const authority = readRuntimeBrokerAuthorityForRuntime({
|
|
211774
|
+
runtimeId,
|
|
211775
|
+
machineId: identity.machineId,
|
|
211776
|
+
credentialEpoch: identity.credentialEpoch,
|
|
211777
|
+
requiredScope: "sidekick"
|
|
211778
|
+
});
|
|
211779
|
+
return authority ? {
|
|
211780
|
+
runtimeId,
|
|
211781
|
+
token: authority.token
|
|
211782
|
+
} : null;
|
|
211783
|
+
}
|
|
211784
|
+
if (identity.mode === "invalid") return null;
|
|
211785
|
+
const legacyToken = runtimeGrantToken();
|
|
211786
|
+
return legacyToken ? {
|
|
211787
|
+
runtimeId,
|
|
211788
|
+
token: legacyToken
|
|
211789
|
+
} : null;
|
|
211790
|
+
}
|
|
211791
|
+
function isRawSidekickCapabilityResponse(value) {
|
|
211792
|
+
if (typeof value !== "object" || value === null) return false;
|
|
211793
|
+
const record = value;
|
|
211794
|
+
return Array.isArray(record.tools) && typeof record.catalogVersion === "string" && typeof record.capabilitySessionId === "number" && typeof record.capabilityToken === "string" && typeof record.expiresAt === "string";
|
|
211795
|
+
}
|
|
211796
|
+
/**
|
|
211797
|
+
* Mints a Work Session Sidekick capability straight from CMMD, for a thread
|
|
211798
|
+
* whose owner JWT never resolved.
|
|
211799
|
+
*
|
|
211800
|
+
* The mint route answers a bare JSON body, never CMMD's forge-context
|
|
211801
|
+
* `{ data: ... }` envelope the owner-JWT catalog route uses, so this never
|
|
211802
|
+
* unwraps `.data`. Always resolves, never throws: a missing runtime grant, a
|
|
211803
|
+
* network failure, and a refusal from CMMD (the broker feature flag is off,
|
|
211804
|
+
* the Work Session ended, this runtime is not its starter, ...) all fold to
|
|
211805
|
+
* the same `CMMD_AUTH_REQUIRED` the owner-JWT lane already returns on any
|
|
211806
|
+
* auth failure, so callers need exactly one failure branch. The refusal's
|
|
211807
|
+
* own code is logged, not returned, so an operator can still tell the cases
|
|
211808
|
+
* apart.
|
|
211809
|
+
*/
|
|
211810
|
+
async function requestWorkSessionSidekickCapability(workSessionId, threadId, deps = {}) {
|
|
211811
|
+
const grant = (deps.resolveRuntimeGrant ?? resolveWorkSessionSidekickRuntimeGrant)();
|
|
211812
|
+
if (!grant) {
|
|
211813
|
+
console.warn(`[cmmd-work-session-capability] no runtime grant for the sidekick scope (thread ${threadId}, work session ${workSessionId})`);
|
|
211814
|
+
return AUTH_REQUIRED;
|
|
211815
|
+
}
|
|
211816
|
+
const fetchImpl = deps.fetch ?? fetch;
|
|
211817
|
+
const url = resolveCommandAppEndpoint(`/api/forge/runtimes/${encodeURIComponent(grant.runtimeId)}/sidekick-capability`);
|
|
211818
|
+
let response;
|
|
211819
|
+
try {
|
|
211820
|
+
response = await fetchImpl(url, {
|
|
211821
|
+
method: "POST",
|
|
211822
|
+
headers: {
|
|
211823
|
+
Authorization: `Bearer ${grant.token}`,
|
|
211824
|
+
"Content-Type": "application/json"
|
|
211825
|
+
},
|
|
211826
|
+
body: JSON.stringify({ workSessionId }),
|
|
211827
|
+
signal: AbortSignal.timeout(SIDEKICK_CAPABILITY_TIMEOUT_MS)
|
|
211828
|
+
});
|
|
211829
|
+
} catch (error) {
|
|
211830
|
+
console.warn("[cmmd-work-session-capability] broker request failed:", error instanceof Error ? error.message : String(error));
|
|
211831
|
+
return AUTH_REQUIRED;
|
|
211832
|
+
}
|
|
211833
|
+
if (!response.ok) {
|
|
211834
|
+
const body = await response.json().catch(() => null);
|
|
211835
|
+
const code = body && typeof body === "object" && typeof body.code === "string" ? body.code : `HTTP_${response.status}`;
|
|
211836
|
+
console.warn(`[cmmd-work-session-capability] broker refused the mint (${code})`);
|
|
211837
|
+
return AUTH_REQUIRED;
|
|
211838
|
+
}
|
|
211839
|
+
const data = await response.json().catch(() => null);
|
|
211840
|
+
if (!isRawSidekickCapabilityResponse(data)) {
|
|
211841
|
+
console.warn("[cmmd-work-session-capability] broker returned an unexpected mint response");
|
|
211842
|
+
return AUTH_REQUIRED;
|
|
211843
|
+
}
|
|
211844
|
+
return {
|
|
211845
|
+
ok: true,
|
|
211846
|
+
tools: data.tools,
|
|
211847
|
+
catalogVersion: data.catalogVersion,
|
|
211848
|
+
capabilitySessionId: data.capabilitySessionId,
|
|
211849
|
+
capabilityToken: data.capabilityToken,
|
|
211850
|
+
expiresAt: data.expiresAt
|
|
211851
|
+
};
|
|
211852
|
+
}
|
|
211853
|
+
//#endregion
|
|
211656
211854
|
//#region src/cmmdData/resolveCmmdSidekickToolCatalog.ts
|
|
211657
|
-
async function resolveCmmdSidekickToolCatalog(resolveJwt, threadId) {
|
|
211658
|
-
const session = createCmmdSidekickToolSession(createCmmdDelegatedToolCatalogClient(resolveJwt
|
|
211855
|
+
async function resolveCmmdSidekickToolCatalog(resolveJwt, threadId, options = {}) {
|
|
211856
|
+
const session = createCmmdSidekickToolSession(createCmmdDelegatedToolCatalogClient(resolveJwt, {
|
|
211857
|
+
...options.readWorkSessionId !== void 0 ? { readWorkSessionId: options.readWorkSessionId } : {},
|
|
211858
|
+
requestCapability: options.requestWorkSessionCapability ?? requestWorkSessionSidekickCapability
|
|
211859
|
+
}), { threadId });
|
|
211659
211860
|
const catalog = await session.getCatalog();
|
|
211660
211861
|
return {
|
|
211661
211862
|
session,
|
|
@@ -211674,6 +211875,33 @@ async function resolveCmmdSidekickJwt(input) {
|
|
|
211674
211875
|
...binding?.subject ? { subject: binding.subject } : {}
|
|
211675
211876
|
});
|
|
211676
211877
|
}
|
|
211878
|
+
const decodeWorkSessionIdRows = decodeUnknownEffect(ArraySchema(Struct({ workSessionId: NullOr(String$1) })));
|
|
211879
|
+
/**
|
|
211880
|
+
* Reads the CMMD Work Session id CMMD stamped on a thread's `thread.create`,
|
|
211881
|
+
* straight from the projected thread row (forge#3466). Null for a
|
|
211882
|
+
* person-started thread, for a thread projected before this field existed,
|
|
211883
|
+
* and for a thread id with no projected row at all.
|
|
211884
|
+
*
|
|
211885
|
+
* A minimal raw-SQL read against `projection_threads`, deliberately not
|
|
211886
|
+
* routed through `ProjectionThreadRepository`: the adapters that need this
|
|
211887
|
+
* (`ClaudeAdapter.ts`, `CodexAdapter.ts`) already capture only
|
|
211888
|
+
* `SqlClient.SqlClient` at session-build time (see `readThreadAuthSession`
|
|
211889
|
+
* in `GitHubAgentToolStore.ts` for the established pattern this follows), and
|
|
211890
|
+
* widening that capture to a second service for one column is not worth the
|
|
211891
|
+
* risk to every other call sharing it.
|
|
211892
|
+
*/
|
|
211893
|
+
function readThreadWorkSessionId(threadId) {
|
|
211894
|
+
return gen(function* () {
|
|
211895
|
+
return (yield* decodeWorkSessionIdRows(yield* (yield* SqlClient)`
|
|
211896
|
+
SELECT work_session_id AS "workSessionId"
|
|
211897
|
+
FROM projection_threads
|
|
211898
|
+
WHERE thread_id = ${threadId}
|
|
211899
|
+
LIMIT 1
|
|
211900
|
+
`))[0]?.workSessionId ?? null;
|
|
211901
|
+
}).pipe(tapError((error) => sync$1(() => {
|
|
211902
|
+
console.warn(`[cmmd-work-session-thread-lookup] failed to read work_session_id for thread ${threadId}:`, error instanceof Error ? error.message : String(error));
|
|
211903
|
+
})), orElseSucceed(() => null));
|
|
211904
|
+
}
|
|
211677
211905
|
//#endregion
|
|
211678
211906
|
//#region ../../packages/shared/src/computerUsePermission.ts
|
|
211679
211907
|
/**
|
|
@@ -213263,13 +213491,14 @@ const makeCodexAdapter = fn$1("makeCodexAdapter")(function* (options) {
|
|
|
213263
213491
|
const jwt = readCommandJwtForSession(binding.sessionId);
|
|
213264
213492
|
return jwt ? { jwt } : null;
|
|
213265
213493
|
} });
|
|
213494
|
+
const readCmmdWorkSessionId = () => runWithRuntimeContext(readThreadWorkSessionId(input.threadId));
|
|
213266
213495
|
const { session: cmmdSidekickToolSession, tools: cmmdSidekickTools } = yield* promise(() => resolveCmmdSidekickToolCatalog((sessionId) => resolveCmmdSidekickJwt({
|
|
213267
213496
|
threadId: input.threadId,
|
|
213268
213497
|
sessionId,
|
|
213269
213498
|
logPrefix: "codex-cmmd-sidekick",
|
|
213270
213499
|
readThreadAuth: (threadId) => runWithRuntimeContext(readThreadAuthSession(threadId)),
|
|
213271
213500
|
resolveJwt: (options) => runWithRuntimeContext(resolveCmmdJwtForSession(options))
|
|
213272
|
-
}), input.threadId));
|
|
213501
|
+
}), input.threadId, { readWorkSessionId: readCmmdWorkSessionId }));
|
|
213273
213502
|
const cmmdSidekickToolNames = new Set(cmmdSidekickTools.map((tool) => tool.name));
|
|
213274
213503
|
const devServerToolDeps = {
|
|
213275
213504
|
threadDevRuntime,
|
|
@@ -215381,6 +215610,21 @@ const SIGNIN_REQUIRED = {
|
|
|
215381
215610
|
action: "notify_human",
|
|
215382
215611
|
message: "Not signed in to CMMD for this session. Continue from repository evidence and tell the user to sign in to CMMD to enable project context."
|
|
215383
215612
|
};
|
|
215613
|
+
/**
|
|
215614
|
+
* Same failure as {@link SIGNIN_REQUIRED} (no CMMD sign-in exists for this
|
|
215615
|
+
* session), but for a headless Work Session runtime that was never going to
|
|
215616
|
+
* have one: nobody is present to sign in (CMMD ADR-015). Telling the agent
|
|
215617
|
+
* to ask a human to sign in is wrong there. When CMMD's Sidekick capability
|
|
215618
|
+
* broker minted delegated tools for this Work Session (forge#3466,
|
|
215619
|
+
* CMMD#5026), point at them instead of dead-ending.
|
|
215620
|
+
*/
|
|
215621
|
+
const WORK_SESSION_CONTEXT_VIA_DELEGATED_TOOLS = {
|
|
215622
|
+
ok: false,
|
|
215623
|
+
code: "signin_required",
|
|
215624
|
+
retryable: false,
|
|
215625
|
+
action: "skip",
|
|
215626
|
+
message: "No CMMD sign-in for this session, but this Work Session has delegated Sidekick tools. Call cmmd_get_agent_plan (or get_task) from cmmd-sidekick-tools for the task packet and current context, then continue from there."
|
|
215627
|
+
};
|
|
215384
215628
|
/** Map a thrown CMMD client error to a recoverable envelope. */
|
|
215385
215629
|
function errorEnvelope(err) {
|
|
215386
215630
|
if (isCmmdMcpAuthError$2(err)) return {
|
|
@@ -215443,12 +215687,13 @@ function projectIdToToolArg(projectId) {
|
|
|
215443
215687
|
* mutation arg. The `action` arg of CMMD's multiplexed tools is hardcoded to a
|
|
215444
215688
|
* read inside contextBuilder and never surfaced to the LLM.
|
|
215445
215689
|
*/
|
|
215446
|
-
function makeCmmdContextHandlers(resolvePat) {
|
|
215690
|
+
function makeCmmdContextHandlers(resolvePat, options = {}) {
|
|
215691
|
+
const noPatEnvelope = options.hasWorkSessionPacketTool ? WORK_SESSION_CONTEXT_VIA_DELEGATED_TOOLS : SIGNIN_REQUIRED;
|
|
215447
215692
|
return {
|
|
215448
215693
|
getCurrentContext: async () => {
|
|
215449
215694
|
try {
|
|
215450
215695
|
const pat = await resolvePat();
|
|
215451
|
-
if (!pat) return envelope(
|
|
215696
|
+
if (!pat) return envelope(noPatEnvelope);
|
|
215452
215697
|
const snapshot = await buildCurrentContextSnapshot(pat, {
|
|
215453
215698
|
maxCampaigns: 3,
|
|
215454
215699
|
maxProjects: 5,
|
|
@@ -215481,7 +215726,7 @@ function makeCmmdContextHandlers(resolvePat) {
|
|
|
215481
215726
|
message: "Provide a non-empty `query` to search the CMMD knowledge base."
|
|
215482
215727
|
});
|
|
215483
215728
|
const pat = await resolvePat();
|
|
215484
|
-
if (!pat) return envelope(
|
|
215729
|
+
if (!pat) return envelope(noPatEnvelope);
|
|
215485
215730
|
const effectiveLimit = clampLimit(limit, DEFAULT_BRAIN_LIMIT, MAX_BRAIN_LIMIT);
|
|
215486
215731
|
const result = await callCmmdTool$2(pat, "search_brain_documents", {
|
|
215487
215732
|
query: trimmedQuery,
|
|
@@ -215535,7 +215780,7 @@ function makeCmmdContextHandlers(resolvePat) {
|
|
|
215535
215780
|
message: "Provide a `projectId` (from cmmd_get_current_context data.projects[].id)."
|
|
215536
215781
|
});
|
|
215537
215782
|
const pat = await resolvePat();
|
|
215538
|
-
if (!pat) return envelope(
|
|
215783
|
+
if (!pat) return envelope(noPatEnvelope);
|
|
215539
215784
|
const result = await callCmmdTool$2(pat, "list_board_tasks", { project_id: projectIdToToolArg(trimmedId) });
|
|
215540
215785
|
if (result.isError) return envelope(isErrorEnvelope(result));
|
|
215541
215786
|
const text = extractMcpToolText$2(result);
|
|
@@ -215564,8 +215809,8 @@ function makeCmmdContextHandlers(resolvePat) {
|
|
|
215564
215809
|
* when the user is not authenticated with CMMD. Called per
|
|
215565
215810
|
* tool invocation so a mid-session token refresh is picked up.
|
|
215566
215811
|
*/
|
|
215567
|
-
function createCmmdContextMcpServer(threadId, resolvePat) {
|
|
215568
|
-
const handlers = makeCmmdContextHandlers(resolvePat);
|
|
215812
|
+
function createCmmdContextMcpServer(threadId, resolvePat, options = {}) {
|
|
215813
|
+
const handlers = makeCmmdContextHandlers(resolvePat, options);
|
|
215569
215814
|
return z1e({
|
|
215570
215815
|
name: "cmmd-context",
|
|
215571
215816
|
tools: [
|
|
@@ -216088,7 +216333,7 @@ function buildClaudeMcpServers(input) {
|
|
|
216088
216333
|
return {
|
|
216089
216334
|
"forge-browser": createBrowserMcpServer(input.browserManager, input.threadId, browserToolScope(input.browserToolEnvironmentId)),
|
|
216090
216335
|
"forge-dev-server": createDevServerMcpServer(input.devServerToolDeps, input.threadId),
|
|
216091
|
-
"cmmd-context": createCmmdContextMcpServer(input.threadId, input.resolveCmmdPat),
|
|
216336
|
+
"cmmd-context": createCmmdContextMcpServer(input.threadId, input.resolveCmmdPat, { hasWorkSessionPacketTool: input.hasWorkSessionPacketTool }),
|
|
216092
216337
|
[GITHUB_MCP_SERVER_NAME]: createGitHubMcpServer(input.runBrokeredGitHubTool, input.threadId, input.serverSettings),
|
|
216093
216338
|
...input.computerManager ? { [COMPUTER_MCP_SERVER_NAME]: createComputerMcpServer(input.computerManager, input.threadId) } : {},
|
|
216094
216339
|
...input.cmmdSidekickTools ? { "cmmd-sidekick-tools": createCmmdSidekickToolsMcpServer(input.cmmdSidekickTools.session, input.cmmdSidekickTools.tools) } : {},
|
|
@@ -216132,19 +216377,47 @@ function claudePermissionQueryOptions(permissionMode) {
|
|
|
216132
216377
|
function createClaudePromptStream(promptQueue) {
|
|
216133
216378
|
return fromQueue(promptQueue).pipe(filter$2((item) => item.type === "message"), map$7((item) => item.message), catchCause$1((cause) => hasInterruptsOnly(cause) ? empty$5 : failCause$5(cause)), toAsyncIterable);
|
|
216134
216379
|
}
|
|
216135
|
-
function createCmmdPatResolver(threadId) {
|
|
216380
|
+
function createCmmdPatResolver(threadId, readWorkSessionId) {
|
|
216136
216381
|
return async () => {
|
|
216382
|
+
if (await readWorkSessionId() !== null) return null;
|
|
216137
216383
|
const ownerSessionId = readThreadSessionId(threadId);
|
|
216138
216384
|
if (!ownerSessionId) return null;
|
|
216139
216385
|
return readCommandAccessTokenForSession(ownerSessionId);
|
|
216140
216386
|
};
|
|
216141
216387
|
}
|
|
216142
|
-
function resolveCmmdSidekickTools(resolveJwt, threadId) {
|
|
216143
|
-
return promise(() => resolveCmmdSidekickToolCatalog(resolveJwt, threadId)).pipe(map$3((resolved) => ({
|
|
216388
|
+
function resolveCmmdSidekickTools(resolveJwt, threadId, readWorkSessionId) {
|
|
216389
|
+
return promise(() => resolveCmmdSidekickToolCatalog(resolveJwt, threadId, { readWorkSessionId })).pipe(map$3((resolved) => ({
|
|
216144
216390
|
registration: resolved.tools.length > 0 ? resolved : null,
|
|
216145
216391
|
codewebMcpGrant: resolved.codewebMcp
|
|
216146
216392
|
})));
|
|
216147
216393
|
}
|
|
216394
|
+
/**
|
|
216395
|
+
* Name of the delegated tool that returns a Work Session's task packet
|
|
216396
|
+
* (CMMD's Agent Plan family, ADR-029). Forge's Sidekick capability broker
|
|
216397
|
+
* always mounts this for a Work Session (CMMD's `forge-surface.ts` curated
|
|
216398
|
+
* allowlist, verified 2026-09-26), so its presence in the granted catalog is
|
|
216399
|
+
* exactly "a Work Session capability exists for this thread". See
|
|
216400
|
+
* `cmmdContextMcpServer.ts`'s no-PAT branch (forge#3466).
|
|
216401
|
+
*/
|
|
216402
|
+
const WORK_SESSION_PACKET_TOOL_NAME = "cmmd_get_agent_plan";
|
|
216403
|
+
/**
|
|
216404
|
+
* Whether `cmmd-context`'s no-PAT branch should point at delegated tools
|
|
216405
|
+
* instead of asking the user to sign in (forge#3466 review, should-fix 5).
|
|
216406
|
+
*
|
|
216407
|
+
* Gating on `workSessionId !== null` alone, without a separate "which lane
|
|
216408
|
+
* minted this" tag, is sound because `cmmdDelegatedToolCatalog.ts`'s
|
|
216409
|
+
* `listCatalog` (should-fix 3) structurally never calls the owner-JWT lane
|
|
216410
|
+
* once a Work Session id is present — it returns straight from the broker
|
|
216411
|
+
* call or `AUTH_REQUIRED`. So a non-null `workSessionId` here can only ever
|
|
216412
|
+
* pair with a broker-minted registration. Before that reorder, the owner-JWT
|
|
216413
|
+
* catalog (the full, unnarrowed Sidekick catalog) also contains
|
|
216414
|
+
* `cmmd_get_agent_plan`, so checking the tool name alone told a
|
|
216415
|
+
* person-started thread with a resolved JWT but no PAT that it had Work
|
|
216416
|
+
* Session tools when it never did.
|
|
216417
|
+
*/
|
|
216418
|
+
function hasWorkSessionPacketTool(workSessionId, registration) {
|
|
216419
|
+
return workSessionId !== null && (registration?.tools.some((tool) => tool.name === WORK_SESSION_PACKET_TOOL_NAME) ?? false);
|
|
216420
|
+
}
|
|
216148
216421
|
function buildDevServerToolDeps(input) {
|
|
216149
216422
|
return {
|
|
216150
216423
|
threadDevRuntime: input.threadDevRuntime,
|
|
@@ -218320,7 +218593,8 @@ const makeClaudeAdapter = fn$1("makeClaudeAdapter")(function* (options) {
|
|
|
218320
218593
|
const runPromise = runPromiseWith(runtimeContext);
|
|
218321
218594
|
const browserToolEnvironmentId = yield* resolveBrowserToolEnvironmentId();
|
|
218322
218595
|
const computerManager = resolveComputerManager(serverConfig);
|
|
218323
|
-
const
|
|
218596
|
+
const readWorkSessionId = () => runWithSqlRuntimeContext(readThreadWorkSessionId(threadId));
|
|
218597
|
+
const resolveCmmdPat = createCmmdPatResolver(threadId, readWorkSessionId);
|
|
218324
218598
|
const resolveCmmdSidekickJwtForSession = (sessionId) => resolveCmmdSidekickJwt({
|
|
218325
218599
|
threadId,
|
|
218326
218600
|
sessionId,
|
|
@@ -218328,7 +218602,8 @@ const makeClaudeAdapter = fn$1("makeClaudeAdapter")(function* (options) {
|
|
|
218328
218602
|
readThreadAuth: (targetThreadId) => runWithSqlRuntimeContext(readThreadAuthSession(targetThreadId)),
|
|
218329
218603
|
resolveJwt: (options) => runWithSqlRuntimeContext(resolveCmmdJwtForSession(options))
|
|
218330
218604
|
});
|
|
218331
|
-
const
|
|
218605
|
+
const workSessionId = yield* promise(readWorkSessionId);
|
|
218606
|
+
const cmmdSidekickResolution = yield* resolveCmmdSidekickTools(resolveCmmdSidekickJwtForSession, threadId, readWorkSessionId);
|
|
218332
218607
|
const devServerToolDeps = buildDevServerToolDeps({
|
|
218333
218608
|
threadDevRuntime,
|
|
218334
218609
|
devTunnel,
|
|
@@ -218413,6 +218688,7 @@ const makeClaudeAdapter = fn$1("makeClaudeAdapter")(function* (options) {
|
|
|
218413
218688
|
resolveCmmdPat,
|
|
218414
218689
|
devServerToolDeps,
|
|
218415
218690
|
cmmdSidekickTools: cmmdSidekickResolution.registration,
|
|
218691
|
+
hasWorkSessionPacketTool: hasWorkSessionPacketTool(workSessionId, cmmdSidekickResolution.registration),
|
|
218416
218692
|
codewebMcpInjection,
|
|
218417
218693
|
runBrokeredGitHubTool,
|
|
218418
218694
|
serverSettings
|
|
@@ -270408,7 +270684,7 @@ var import_multicast_dns = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMi
|
|
|
270408
270684
|
var dgram = __require("dgram");
|
|
270409
270685
|
var thunky = require_thunky();
|
|
270410
270686
|
var events = __require("events");
|
|
270411
|
-
var os
|
|
270687
|
+
var os = __require("os");
|
|
270412
270688
|
var noop = function() {};
|
|
270413
270689
|
module.exports = function(opts) {
|
|
270414
270690
|
if (!opts) opts = {};
|
|
@@ -270539,14 +270815,14 @@ var import_multicast_dns = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMi
|
|
|
270539
270815
|
return that;
|
|
270540
270816
|
};
|
|
270541
270817
|
function defaultInterface() {
|
|
270542
|
-
var networks = os
|
|
270818
|
+
var networks = os.networkInterfaces();
|
|
270543
270819
|
var names = Object.keys(networks);
|
|
270544
270820
|
for (var i = 0; i < names.length; i++) {
|
|
270545
270821
|
var net = networks[names[i]];
|
|
270546
270822
|
for (var j = 0; j < net.length; j++) {
|
|
270547
270823
|
var iface = net[j];
|
|
270548
270824
|
if (isIPv4(iface.family) && !iface.internal) {
|
|
270549
|
-
if (os
|
|
270825
|
+
if (os.platform() === "darwin" && names[i] === "en0") return iface.address;
|
|
270550
270826
|
return "0.0.0.0";
|
|
270551
270827
|
}
|
|
270552
270828
|
}
|
|
@@ -270554,7 +270830,7 @@ var import_multicast_dns = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMi
|
|
|
270554
270830
|
return "127.0.0.1";
|
|
270555
270831
|
}
|
|
270556
270832
|
function allInterfaces() {
|
|
270557
|
-
var networks = os
|
|
270833
|
+
var networks = os.networkInterfaces();
|
|
270558
270834
|
var names = Object.keys(networks);
|
|
270559
270835
|
var res = [];
|
|
270560
270836
|
for (var i = 0; i < names.length; i++) {
|
|
@@ -287818,6 +288094,7 @@ const ProjectionThread = Struct({
|
|
|
287818
288094
|
parentThreadId: NullOr(ThreadId).pipe(withDecodingDefault(succeed(null))),
|
|
287819
288095
|
anchorKind: CmmdAnchorKind.pipe(withDecodingDefault(succeed("scratch"))),
|
|
287820
288096
|
anchorCmmdId: NullOr(String$1).pipe(withDecodingDefault(succeed(null))),
|
|
288097
|
+
workSessionId: optionalKey(NullOr(String$1)),
|
|
287821
288098
|
linkedPullRequest: optionalKey(NullOr(LinkedPullRequest)),
|
|
287822
288099
|
status: ThreadStatus.pipe(withDecodingDefault(succeed("idle"))),
|
|
287823
288100
|
workerRole: NullOr(WorkerRole).pipe(withDecodingDefault(succeed(null))),
|
|
@@ -298928,7 +299205,7 @@ function resolveBuildCommitFromEnv(env) {
|
|
|
298928
299205
|
* environment descriptor down instead of reporting an honest "unknown".
|
|
298929
299206
|
*/
|
|
298930
299207
|
function readBakedBuildCommit() {
|
|
298931
|
-
return "
|
|
299208
|
+
return "6a8d2900640fafdaeaeaf45ddfa1f1cf70c212d7";
|
|
298932
299209
|
}
|
|
298933
299210
|
async function resolveServerBuildCommit(input) {
|
|
298934
299211
|
if (isFullCommitSha(input.baked)) return input.baked;
|
|
@@ -302558,6 +302835,7 @@ const decideOrchestrationCommand = fn$1("decideOrchestrationCommand")(function*
|
|
|
302558
302835
|
updatedAt: command.createdAt,
|
|
302559
302836
|
anchorKind: anchor.anchorKind,
|
|
302560
302837
|
anchorCmmdId: anchor.anchorCmmdId,
|
|
302838
|
+
workSessionId: command.workSessionId ?? null,
|
|
302561
302839
|
goal: command.goal ?? null,
|
|
302562
302840
|
linkedPullRequest: command.linkedPullRequest ?? null,
|
|
302563
302841
|
kind,
|
|
@@ -302867,7 +303145,8 @@ const decideOrchestrationCommand = fn$1("decideOrchestrationCommand")(function*
|
|
|
302867
303145
|
const providerSwitchSelection = command.modelSelection !== void 0 && command.modelSelection.provider !== targetThread.modelSelection.provider ? command.modelSelection : void 0;
|
|
302868
303146
|
const accountSelection = turnAccountSelection(targetThread.modelSelection, command.modelSelection);
|
|
302869
303147
|
const turnModelSelection = providerSwitchSelection ?? accountSelection;
|
|
302870
|
-
|
|
303148
|
+
const shouldRebindWorkSession = command.workSessionId !== void 0 && command.workSessionId !== null && command.workSessionId !== targetThread.workSessionId;
|
|
303149
|
+
if (!shouldUpdateAnchor && !turnModelSelection && !shouldRebindWorkSession) return [userMessageEvent, turnStartRequestedEvent];
|
|
302871
303150
|
return [
|
|
302872
303151
|
{
|
|
302873
303152
|
...withEventBase({
|
|
@@ -302882,6 +303161,7 @@ const decideOrchestrationCommand = fn$1("decideOrchestrationCommand")(function*
|
|
|
302882
303161
|
anchorKind: nextAnchor.anchorKind,
|
|
302883
303162
|
anchorCmmdId: nextAnchor.anchorCmmdId,
|
|
302884
303163
|
...turnModelSelection ? { modelSelection: turnModelSelection } : {},
|
|
303164
|
+
...shouldRebindWorkSession ? { workSessionId: command.workSessionId } : {},
|
|
302885
303165
|
updatedAt: command.createdAt
|
|
302886
303166
|
}
|
|
302887
303167
|
},
|
|
@@ -303405,12 +303685,22 @@ function retainThreadActivitiesAfterRevert(activities, retainedTurnIds) {
|
|
|
303405
303685
|
function retainThreadProposedPlansAfterRevert(proposedPlans, retainedTurnIds) {
|
|
303406
303686
|
return proposedPlans.filter((proposedPlan) => proposedPlan.turnId === null || retainedTurnIds.has(proposedPlan.turnId));
|
|
303407
303687
|
}
|
|
303688
|
+
/**
|
|
303689
|
+
* Orders an unsequenced activity before a sequenced one, matching the SQL
|
|
303690
|
+
* projection's own `ORDER BY CASE WHEN sequence IS NULL THEN 0 ELSE 1 END
|
|
303691
|
+
* ASC, sequence ASC`. Zero means neither operand settles the order (both
|
|
303692
|
+
* missing, or both present and equal), so the caller falls back to a
|
|
303693
|
+
* timestamp/id tiebreak.
|
|
303694
|
+
*/
|
|
303695
|
+
function compareOptionalActivitySequence(left, right) {
|
|
303696
|
+
const leftHasSequence = left !== void 0;
|
|
303697
|
+
const rightHasSequence = right !== void 0;
|
|
303698
|
+
if (leftHasSequence !== rightHasSequence) return leftHasSequence ? 1 : -1;
|
|
303699
|
+
return leftHasSequence && rightHasSequence ? left - right : 0;
|
|
303700
|
+
}
|
|
303408
303701
|
function compareThreadActivities(left, right) {
|
|
303409
|
-
|
|
303410
|
-
|
|
303411
|
-
} else if (left.sequence !== void 0) return 1;
|
|
303412
|
-
else if (right.sequence !== void 0) return -1;
|
|
303413
|
-
return left.createdAt.localeCompare(right.createdAt) || left.id.localeCompare(right.id);
|
|
303702
|
+
const bySequence = compareOptionalActivitySequence(left.sequence, right.sequence);
|
|
303703
|
+
return bySequence !== 0 ? bySequence : left.createdAt.localeCompare(right.createdAt) || left.id.localeCompare(right.id);
|
|
303414
303704
|
}
|
|
303415
303705
|
function createEmptyReadModel(nowIso) {
|
|
303416
303706
|
return {
|
|
@@ -303441,6 +303731,7 @@ function projectEvent(model, event) {
|
|
|
303441
303731
|
worktreePath: payload.worktreePath,
|
|
303442
303732
|
anchorKind: payload.anchorKind,
|
|
303443
303733
|
anchorCmmdId: payload.anchorCmmdId,
|
|
303734
|
+
workSessionId: payload.workSessionId ?? null,
|
|
303444
303735
|
goal: payload.goal ?? null,
|
|
303445
303736
|
linkedPullRequest: payload.linkedPullRequest ?? null,
|
|
303446
303737
|
titleRegeneration: null,
|
|
@@ -303521,6 +303812,7 @@ function projectEvent(model, event) {
|
|
|
303521
303812
|
...payload.goal !== void 0 ? { goal: payload.goal } : {},
|
|
303522
303813
|
...payload.linkedPullRequest !== void 0 ? { linkedPullRequest: payload.linkedPullRequest } : {},
|
|
303523
303814
|
...payload.titleRegeneration !== void 0 ? { titleRegeneration: payload.titleRegeneration } : {},
|
|
303815
|
+
...payload.workSessionId !== void 0 ? { workSessionId: payload.workSessionId } : {},
|
|
303524
303816
|
updatedAt: payload.updatedAt
|
|
303525
303817
|
})
|
|
303526
303818
|
})));
|
|
@@ -304571,6 +304863,7 @@ const ProjectionThreadRepositoryLive = effect(ProjectionThreadRepository, gen(fu
|
|
|
304571
304863
|
parent_thread_id,
|
|
304572
304864
|
anchor_kind,
|
|
304573
304865
|
anchor_cmmd_id,
|
|
304866
|
+
work_session_id,
|
|
304574
304867
|
linked_pull_request_json,
|
|
304575
304868
|
status,
|
|
304576
304869
|
worker_role,
|
|
@@ -304603,6 +304896,7 @@ const ProjectionThreadRepositoryLive = effect(ProjectionThreadRepository, gen(fu
|
|
|
304603
304896
|
${row.parentThreadId},
|
|
304604
304897
|
${row.anchorKind},
|
|
304605
304898
|
${row.anchorCmmdId},
|
|
304899
|
+
${row.workSessionId ?? null},
|
|
304606
304900
|
${row.linkedPullRequest == null ? null : JSON.stringify(row.linkedPullRequest)},
|
|
304607
304901
|
${row.status},
|
|
304608
304902
|
${row.workerRole},
|
|
@@ -304635,6 +304929,7 @@ const ProjectionThreadRepositoryLive = effect(ProjectionThreadRepository, gen(fu
|
|
|
304635
304929
|
parent_thread_id = excluded.parent_thread_id,
|
|
304636
304930
|
anchor_kind = excluded.anchor_kind,
|
|
304637
304931
|
anchor_cmmd_id = excluded.anchor_cmmd_id,
|
|
304932
|
+
work_session_id = excluded.work_session_id,
|
|
304638
304933
|
linked_pull_request_json = excluded.linked_pull_request_json,
|
|
304639
304934
|
status = excluded.status,
|
|
304640
304935
|
worker_role = excluded.worker_role,
|
|
@@ -304672,6 +304967,7 @@ const ProjectionThreadRepositoryLive = effect(ProjectionThreadRepository, gen(fu
|
|
|
304672
304967
|
parent_thread_id AS "parentThreadId",
|
|
304673
304968
|
anchor_kind AS "anchorKind",
|
|
304674
304969
|
anchor_cmmd_id AS "anchorCmmdId",
|
|
304970
|
+
work_session_id AS "workSessionId",
|
|
304675
304971
|
linked_pull_request_json AS "linkedPullRequest",
|
|
304676
304972
|
status,
|
|
304677
304973
|
worker_role AS "workerRole",
|
|
@@ -304711,6 +305007,7 @@ const ProjectionThreadRepositoryLive = effect(ProjectionThreadRepository, gen(fu
|
|
|
304711
305007
|
parent_thread_id AS "parentThreadId",
|
|
304712
305008
|
anchor_kind AS "anchorKind",
|
|
304713
305009
|
anchor_cmmd_id AS "anchorCmmdId",
|
|
305010
|
+
work_session_id AS "workSessionId",
|
|
304714
305011
|
linked_pull_request_json AS "linkedPullRequest",
|
|
304715
305012
|
status,
|
|
304716
305013
|
worker_role AS "workerRole",
|
|
@@ -304892,6 +305189,14 @@ function collectThreadUserInputAttachmentRelativePaths(threadId, events) {
|
|
|
304892
305189
|
}
|
|
304893
305190
|
return relativePaths;
|
|
304894
305191
|
}
|
|
305192
|
+
/**
|
|
305193
|
+
* Coalesces an optional Work Session id to the persisted default. Top-level
|
|
305194
|
+
* so the `??` here does not count against `applyThreadsProjection`'s own
|
|
305195
|
+
* complexity budget. See forge#3466.
|
|
305196
|
+
*/
|
|
305197
|
+
function projectedWorkSessionId(workSessionId) {
|
|
305198
|
+
return workSessionId ?? null;
|
|
305199
|
+
}
|
|
304895
305200
|
const runAttachmentSideEffects = fn$1("runAttachmentSideEffects")(function* (sideEffects) {
|
|
304896
305201
|
const serverConfig = yield* service(ServerConfig);
|
|
304897
305202
|
const fileSystem = yield* service(FileSystem);
|
|
@@ -305054,6 +305359,7 @@ const OrchestrationProjectionPipelineLive = effect(OrchestrationProjectionPipeli
|
|
|
305054
305359
|
parentThreadId: event.payload.parentThreadId,
|
|
305055
305360
|
anchorKind: event.payload.anchorKind,
|
|
305056
305361
|
anchorCmmdId: event.payload.anchorCmmdId,
|
|
305362
|
+
workSessionId: projectedWorkSessionId(event.payload.workSessionId),
|
|
305057
305363
|
linkedPullRequest: event.payload.linkedPullRequest ?? null,
|
|
305058
305364
|
status: event.payload.status,
|
|
305059
305365
|
workerRole: event.payload.workerRole,
|
|
@@ -305091,6 +305397,7 @@ const OrchestrationProjectionPipelineLive = effect(OrchestrationProjectionPipeli
|
|
|
305091
305397
|
parentThreadId: thread.parentThreadId,
|
|
305092
305398
|
anchorKind: thread.anchorKind,
|
|
305093
305399
|
anchorCmmdId: thread.anchorCmmdId,
|
|
305400
|
+
workSessionId: projectedWorkSessionId(thread.workSessionId),
|
|
305094
305401
|
linkedPullRequest: thread.linkedPullRequest ?? null,
|
|
305095
305402
|
status: thread.status,
|
|
305096
305403
|
workerRole: thread.workerRole,
|
|
@@ -305159,6 +305466,7 @@ const OrchestrationProjectionPipelineLive = effect(OrchestrationProjectionPipeli
|
|
|
305159
305466
|
...event.payload.goal !== void 0 ? { goal: event.payload.goal } : {},
|
|
305160
305467
|
...event.payload.linkedPullRequest !== void 0 ? { linkedPullRequest: event.payload.linkedPullRequest } : {},
|
|
305161
305468
|
...event.payload.titleRegeneration !== void 0 ? { titleRegeneration: event.payload.titleRegeneration } : {},
|
|
305469
|
+
...event.payload.workSessionId !== void 0 ? { workSessionId: projectedWorkSessionId(event.payload.workSessionId) } : {},
|
|
305162
305470
|
updatedAt: event.payload.updatedAt
|
|
305163
305471
|
});
|
|
305164
305472
|
return;
|
|
@@ -306157,6 +306465,16 @@ function probeProjectAvailability(fs, workspaceRoot) {
|
|
|
306157
306465
|
function toPersistenceSqlOrDecodeError(sqlOperation, decodeOperation) {
|
|
306158
306466
|
return (cause) => isSchemaError(cause) ? toPersistenceDecodeError(decodeOperation)(cause) : toPersistenceSqlError(sqlOperation)(cause);
|
|
306159
306467
|
}
|
|
306468
|
+
/**
|
|
306469
|
+
* `{ workSessionId }` when the row carries one, an empty object when absent,
|
|
306470
|
+
* so the built thread's optionalKey field round-trips without ever getting
|
|
306471
|
+
* assigned an explicit `undefined` (exactOptionalPropertyTypes). Pulled out
|
|
306472
|
+
* of the two thread builders that call it so this file's already-flagged
|
|
306473
|
+
* high-complexity functions do not pick up the branch. See forge#3466.
|
|
306474
|
+
*/
|
|
306475
|
+
function workSessionIdField(workSessionId) {
|
|
306476
|
+
return workSessionId !== void 0 ? { workSessionId } : {};
|
|
306477
|
+
}
|
|
306160
306478
|
const OrchestrationInfrastructureLayerLive = mergeAll(effect(ProjectionSnapshotQuery, gen(function* () {
|
|
306161
306479
|
const sql = yield* SqlClient;
|
|
306162
306480
|
const repositoryIdentityResolver = yield* RepositoryIdentityResolver;
|
|
@@ -306209,6 +306527,7 @@ const OrchestrationInfrastructureLayerLive = mergeAll(effect(ProjectionSnapshotQ
|
|
|
306209
306527
|
parent_thread_id AS "parentThreadId",
|
|
306210
306528
|
anchor_kind AS "anchorKind",
|
|
306211
306529
|
anchor_cmmd_id AS "anchorCmmdId",
|
|
306530
|
+
work_session_id AS "workSessionId",
|
|
306212
306531
|
linked_pull_request_json AS "linkedPullRequest",
|
|
306213
306532
|
status,
|
|
306214
306533
|
worker_role AS "workerRole",
|
|
@@ -306247,6 +306566,7 @@ const OrchestrationInfrastructureLayerLive = mergeAll(effect(ProjectionSnapshotQ
|
|
|
306247
306566
|
parent_thread_id AS "parentThreadId",
|
|
306248
306567
|
anchor_kind AS "anchorKind",
|
|
306249
306568
|
anchor_cmmd_id AS "anchorCmmdId",
|
|
306569
|
+
work_session_id AS "workSessionId",
|
|
306250
306570
|
linked_pull_request_json AS "linkedPullRequest",
|
|
306251
306571
|
status,
|
|
306252
306572
|
worker_role AS "workerRole",
|
|
@@ -306351,6 +306671,7 @@ const OrchestrationInfrastructureLayerLive = mergeAll(effect(ProjectionSnapshotQ
|
|
|
306351
306671
|
parent_thread_id AS "parentThreadId",
|
|
306352
306672
|
anchor_kind AS "anchorKind",
|
|
306353
306673
|
anchor_cmmd_id AS "anchorCmmdId",
|
|
306674
|
+
work_session_id AS "workSessionId",
|
|
306354
306675
|
linked_pull_request_json AS "linkedPullRequest",
|
|
306355
306676
|
status,
|
|
306356
306677
|
worker_role AS "workerRole",
|
|
@@ -306683,6 +307004,7 @@ const OrchestrationInfrastructureLayerLive = mergeAll(effect(ProjectionSnapshotQ
|
|
|
306683
307004
|
parent_thread_id AS "parentThreadId",
|
|
306684
307005
|
anchor_kind AS "anchorKind",
|
|
306685
307006
|
anchor_cmmd_id AS "anchorCmmdId",
|
|
307007
|
+
work_session_id AS "workSessionId",
|
|
306686
307008
|
linked_pull_request_json AS "linkedPullRequest",
|
|
306687
307009
|
status,
|
|
306688
307010
|
worker_role AS "workerRole",
|
|
@@ -306995,6 +307317,7 @@ const OrchestrationInfrastructureLayerLive = mergeAll(effect(ProjectionSnapshotQ
|
|
|
306995
307317
|
session: sessionsByThread.get(row.threadId) ?? null,
|
|
306996
307318
|
anchorKind: row.anchorKind,
|
|
306997
307319
|
anchorCmmdId: row.anchorCmmdId,
|
|
307320
|
+
...workSessionIdField(row.workSessionId),
|
|
306998
307321
|
linkedPullRequest: row.linkedPullRequest,
|
|
306999
307322
|
kind: row.kind,
|
|
307000
307323
|
parentThreadId: row.parentThreadId,
|
|
@@ -307244,6 +307567,7 @@ const OrchestrationInfrastructureLayerLive = mergeAll(effect(ProjectionSnapshotQ
|
|
|
307244
307567
|
session: isSome(sessionRow) ? mapSessionRow(sessionRow.value) : null,
|
|
307245
307568
|
anchorKind: threadRow.value.anchorKind,
|
|
307246
307569
|
anchorCmmdId: threadRow.value.anchorCmmdId,
|
|
307570
|
+
...workSessionIdField(threadRow.value.workSessionId),
|
|
307247
307571
|
linkedPullRequest: threadRow.value.linkedPullRequest,
|
|
307248
307572
|
kind: threadRow.value.kind,
|
|
307249
307573
|
parentThreadId: threadRow.value.parentThreadId,
|
|
@@ -323577,7 +323901,7 @@ const connectLoginCommand = make$34("login", {
|
|
|
323577
323901
|
})).json();
|
|
323578
323902
|
},
|
|
323579
323903
|
openBrowser: async (url) => {
|
|
323580
|
-
const open = (await import("./open-
|
|
323904
|
+
const open = (await import("./open-2-reBrpv.mjs")).default;
|
|
323581
323905
|
await open(url);
|
|
323582
323906
|
return true;
|
|
323583
323907
|
},
|