@cmmd-center/forge 0.13.90 → 0.13.92
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 +410 -63
- package/dist/bin.mjs +407 -63
- 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-D3VfL4MM.js → DiffPanel-C37SDXUs.js} +2 -2
- package/dist/client/assets/{DiffPanel.logic-CsIeMtPL.js → DiffPanel.logic-D7Qjzo8o.js} +2 -2
- package/dist/client/assets/{DiffWorkerPoolProvider-CXmnKCb1.js → DiffWorkerPoolProvider-B1C81-dL.js} +2 -2
- package/dist/client/assets/{PullRequestCodePanel-CXxGoEWK.js → PullRequestCodePanel-BLjOVvZc.js} +2 -2
- package/dist/client/assets/{Virtualizer-DN-C3hND.js → Virtualizer-Bi-1tOHj.js} +2 -2
- package/dist/client/assets/{WorkerPoolContext-DfUYmGn-.js → WorkerPoolContext-BwA1RAnm.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-C2WSp678.js → index-PlTOUnMB.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/package.json +1 -1
- package/dist/client/assets/src-CF8xm6xH.js +0 -3
package/dist/bin.cjs
CHANGED
|
@@ -17845,6 +17845,7 @@ const OrchestrationThread = require_Schema$1.Struct({
|
|
|
17845
17845
|
parentThreadId: require_Schema$1.NullOr(ThreadId).pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed(null))),
|
|
17846
17846
|
status: ThreadStatus.pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed("idle"))),
|
|
17847
17847
|
workerRole: require_Schema$1.NullOr(WorkerRole).pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed(null))),
|
|
17848
|
+
workSessionId: require_Schema$1.optionalKey(require_Schema$1.NullOr(require_Schema$1.String)),
|
|
17848
17849
|
pendingAutoCreatePrompt: require_Schema$1.optional(require_Schema$1.NullOr(AutoCreateTaskPrompt)).pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed(null))),
|
|
17849
17850
|
goal: require_Schema$1.NullOr(TrimmedNonEmptyString).pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed(null))),
|
|
17850
17851
|
titleRegeneration: require_Schema$1.NullOr(ThreadTitleRegeneration).pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed(null))),
|
|
@@ -18000,6 +18001,15 @@ const ProjectDeleteCommand = require_Schema$1.Struct({
|
|
|
18000
18001
|
commandId: CommandId,
|
|
18001
18002
|
projectId: ProjectId
|
|
18002
18003
|
});
|
|
18004
|
+
/**
|
|
18005
|
+
* The CMMD Work Session id a command may carry (forge#3466 review, nit 9).
|
|
18006
|
+
* CMMD's capability broker requires 1 to 256 characters; bounding it here
|
|
18007
|
+
* rejects a malformed id at the door instead of letting decide-time code find
|
|
18008
|
+
* out. Command-only: the read model and its events keep decoding a plain
|
|
18009
|
+
* string so a row or a journaled event written before this bound existed
|
|
18010
|
+
* still loads.
|
|
18011
|
+
*/
|
|
18012
|
+
const CommandWorkSessionId = TrimmedNonEmptyString.check(require_Schema$1.isMaxLength(256));
|
|
18003
18013
|
const ThreadCreateCommand = require_Schema$1.Struct({
|
|
18004
18014
|
type: require_Schema$1.Literal("thread.create"),
|
|
18005
18015
|
commandId: CommandId,
|
|
@@ -18013,6 +18023,7 @@ const ThreadCreateCommand = require_Schema$1.Struct({
|
|
|
18013
18023
|
worktreePath: require_Schema$1.NullOr(TrimmedNonEmptyString),
|
|
18014
18024
|
anchorKind: require_Schema$1.optional(CmmdAnchorKind),
|
|
18015
18025
|
anchorCmmdId: require_Schema$1.optional(require_Schema$1.NullOr(require_Schema$1.String)),
|
|
18026
|
+
workSessionId: require_Schema$1.optional(require_Schema$1.NullOr(CommandWorkSessionId)),
|
|
18016
18027
|
goal: require_Schema$1.optional(require_Schema$1.NullOr(TrimmedNonEmptyString)),
|
|
18017
18028
|
linkedPullRequest: require_Schema$1.optional(require_Schema$1.NullOr(LinkedPullRequest)),
|
|
18018
18029
|
kind: require_Schema$1.optional(ThreadKind),
|
|
@@ -18122,7 +18133,8 @@ const ThreadTurnStartCommand = require_Schema$1.Struct({
|
|
|
18122
18133
|
anchorCmmdId: require_Schema$1.optional(require_Schema$1.NullOr(require_Schema$1.String)),
|
|
18123
18134
|
kind: require_Schema$1.optional(ThreadKind),
|
|
18124
18135
|
parentThreadId: require_Schema$1.optional(require_Schema$1.NullOr(ThreadId)),
|
|
18125
|
-
createdAt: IsoDateTime
|
|
18136
|
+
createdAt: IsoDateTime,
|
|
18137
|
+
workSessionId: require_Schema$1.optional(require_Schema$1.NullOr(CommandWorkSessionId))
|
|
18126
18138
|
});
|
|
18127
18139
|
const ClientThreadTurnStartCommand = require_Schema$1.Struct({
|
|
18128
18140
|
type: require_Schema$1.Literal("thread.turn.start"),
|
|
@@ -18145,7 +18157,8 @@ const ClientThreadTurnStartCommand = require_Schema$1.Struct({
|
|
|
18145
18157
|
anchorCmmdId: require_Schema$1.optional(require_Schema$1.NullOr(require_Schema$1.String)),
|
|
18146
18158
|
kind: require_Schema$1.optional(ThreadKind),
|
|
18147
18159
|
parentThreadId: require_Schema$1.optional(require_Schema$1.NullOr(ThreadId)),
|
|
18148
|
-
createdAt: IsoDateTime
|
|
18160
|
+
createdAt: IsoDateTime,
|
|
18161
|
+
workSessionId: require_Schema$1.optional(require_Schema$1.NullOr(CommandWorkSessionId))
|
|
18149
18162
|
});
|
|
18150
18163
|
const ThreadTurnInterruptCommand = require_Schema$1.Struct({
|
|
18151
18164
|
type: require_Schema$1.Literal("thread.turn.interrupt"),
|
|
@@ -18441,6 +18454,7 @@ const ThreadCreatedPayload$1 = require_Schema$1.Struct({
|
|
|
18441
18454
|
settledOverride: require_Schema$1.optional(SettledOverride),
|
|
18442
18455
|
anchorKind: CmmdAnchorKind.pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed("scratch"))),
|
|
18443
18456
|
anchorCmmdId: require_Schema$1.NullOr(require_Schema$1.String).pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed(null))),
|
|
18457
|
+
workSessionId: require_Schema$1.optionalKey(require_Schema$1.NullOr(require_Schema$1.String)),
|
|
18444
18458
|
goal: require_Schema$1.optionalKey(require_Schema$1.NullOr(TrimmedNonEmptyString)),
|
|
18445
18459
|
linkedPullRequest: require_Schema$1.optionalKey(require_Schema$1.NullOr(LinkedPullRequest)),
|
|
18446
18460
|
kind: ThreadKind.pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed("master"))),
|
|
@@ -18482,6 +18496,7 @@ const ThreadMetaUpdatedPayload$1 = require_Schema$1.Struct({
|
|
|
18482
18496
|
status: require_Schema$1.optional(ThreadStatus),
|
|
18483
18497
|
parentThreadId: require_Schema$1.optional(require_Schema$1.NullOr(ThreadId)),
|
|
18484
18498
|
workerRole: require_Schema$1.optional(require_Schema$1.NullOr(WorkerRole)),
|
|
18499
|
+
workSessionId: require_Schema$1.optional(require_Schema$1.NullOr(require_Schema$1.String)),
|
|
18485
18500
|
goal: require_Schema$1.optional(require_Schema$1.NullOr(TrimmedNonEmptyString)),
|
|
18486
18501
|
linkedPullRequest: require_Schema$1.optional(require_Schema$1.NullOr(LinkedPullRequest)),
|
|
18487
18502
|
regenerateTitle: require_Schema$1.optional(require_Schema$1.Literal(true)),
|
|
@@ -66296,7 +66311,7 @@ function normalizeNumberish(value) {
|
|
|
66296
66311
|
}
|
|
66297
66312
|
//#endregion
|
|
66298
66313
|
//#region package.json
|
|
66299
|
-
var version$1 = "0.13.
|
|
66314
|
+
var version$1 = "0.13.92";
|
|
66300
66315
|
//#endregion
|
|
66301
66316
|
//#region src/sentry.ts
|
|
66302
66317
|
const SERVER_APP_NAME = "forge-server";
|
|
@@ -87937,7 +87952,8 @@ const brokerScopes = new Set([
|
|
|
87937
87952
|
"github",
|
|
87938
87953
|
"provider",
|
|
87939
87954
|
"package",
|
|
87940
|
-
"scm"
|
|
87955
|
+
"scm",
|
|
87956
|
+
"sidekick"
|
|
87941
87957
|
]);
|
|
87942
87958
|
const defaultOwnerId = "interactive";
|
|
87943
87959
|
const authorities = /* @__PURE__ */ new Map();
|
|
@@ -88091,6 +88107,19 @@ function readRuntimeBrokerAuthorityForRuntime(input) {
|
|
|
88091
88107
|
}
|
|
88092
88108
|
//#endregion
|
|
88093
88109
|
//#region src/runtimeAuth/runtimeBrokerIdentity.ts
|
|
88110
|
+
/**
|
|
88111
|
+
* Whether this process is a CMMD-managed per-project cloud runtime (a
|
|
88112
|
+
* sprite), never a local Forge desktop or dev process. Shared by
|
|
88113
|
+
* `GitHubBroker.resolveRuntimeGrant` and
|
|
88114
|
+
* `cmmdWorkSessionCapabilityBroker.resolveWorkSessionSidekickRuntimeGrant`
|
|
88115
|
+
* (forge#3466 review, should-fix 4) so the two runtime-grant resolvers gate
|
|
88116
|
+
* on the same runtime-role signal instead of each inferring it separately.
|
|
88117
|
+
* Mirrors the env parsing `providerEgressToken.ts` and `ServerEnvironment.ts`
|
|
88118
|
+
* already use for the same signal.
|
|
88119
|
+
*/
|
|
88120
|
+
function isCmmdCloudRuntimeModeEnv() {
|
|
88121
|
+
return process.env.FORGE_CMMD_RUNTIME_MODE === "true" || process.env.FORGE_CMMD_RUNTIME_MODE === "1";
|
|
88122
|
+
}
|
|
88094
88123
|
function classifyRuntimeBrokerIdentity(input) {
|
|
88095
88124
|
const machineId = input.machineId?.trim();
|
|
88096
88125
|
const credentialEpoch = input.credentialEpoch;
|
|
@@ -91115,9 +91144,6 @@ var GitHubBroker = class {
|
|
|
91115
91144
|
return validateGitBranchName(branch) ?? branch;
|
|
91116
91145
|
}
|
|
91117
91146
|
};
|
|
91118
|
-
function isCmmdCloudRuntimeModeEnv() {
|
|
91119
|
-
return process.env.FORGE_CMMD_RUNTIME_MODE === "true" || process.env.FORGE_CMMD_RUNTIME_MODE === "1";
|
|
91120
|
-
}
|
|
91121
91147
|
function inferGitHubBrokerRuntimeRole() {
|
|
91122
91148
|
if (isCmmdCloudRuntimeModeEnv()) return "user-vm";
|
|
91123
91149
|
return "local";
|
|
@@ -115686,7 +115712,7 @@ const postgresSchemaStatements = [
|
|
|
115686
115712
|
"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 )",
|
|
115687
115713
|
"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 )",
|
|
115688
115714
|
"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)",
|
|
115689
|
-
"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)",
|
|
115715
|
+
"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)",
|
|
115690
115716
|
"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)",
|
|
115691
115717
|
"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)",
|
|
115692
115718
|
"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')",
|
|
@@ -116007,7 +116033,8 @@ const postgresUpgradeMigrations = new Map([
|
|
|
116007
116033
|
LIMIT 1
|
|
116008
116034
|
)
|
|
116009
116035
|
WHERE model_selection_json IS NULL`
|
|
116010
|
-
]]
|
|
116036
|
+
]],
|
|
116037
|
+
[77, [`ALTER TABLE projection_threads ADD COLUMN IF NOT EXISTS work_session_id TEXT`]]
|
|
116011
116038
|
]);
|
|
116012
116039
|
function requirePostgresUpgradeStatements(version) {
|
|
116013
116040
|
const statements = postgresUpgradeMigrations.get(version);
|
|
@@ -116033,15 +116060,15 @@ const runPostgresMigrations = require_Schema$1.fn("runPostgresMigrations")(funct
|
|
|
116033
116060
|
ORDER BY version DESC
|
|
116034
116061
|
LIMIT 1
|
|
116035
116062
|
`)[0]?.version ?? 0;
|
|
116036
|
-
if (currentVersion >
|
|
116063
|
+
if (currentVersion > 77) return yield* require_Schema$1.die(/* @__PURE__ */ new Error(`Forge Postgres schema ${currentVersion} is newer than server schema 77.`));
|
|
116037
116064
|
if (currentVersion === 0) {
|
|
116038
116065
|
for (const statement of postgresSchemaStatements) yield* sql.unsafe(statement);
|
|
116039
116066
|
yield* sql`
|
|
116040
116067
|
INSERT INTO forge_schema_migrations (version)
|
|
116041
|
-
VALUES (${
|
|
116068
|
+
VALUES (${77})
|
|
116042
116069
|
ON CONFLICT (version) DO NOTHING
|
|
116043
116070
|
`;
|
|
116044
|
-
} else for (let version = currentVersion + 1; version <=
|
|
116071
|
+
} else for (let version = currentVersion + 1; version <= 77; version += 1) {
|
|
116045
116072
|
const statements = yield* require_Schema$1.sync(() => requirePostgresUpgradeStatements(version));
|
|
116046
116073
|
for (const statement of statements) yield* sql.unsafe(statement);
|
|
116047
116074
|
yield* sql`
|
|
@@ -118826,6 +118853,18 @@ var _076_ProjectionTurnsModelSelection_default = require_Schema$1.gen(function*
|
|
|
118826
118853
|
`;
|
|
118827
118854
|
});
|
|
118828
118855
|
//#endregion
|
|
118856
|
+
//#region src/persistence/Migrations/077_ProjectionThreadWorkSessionId.ts
|
|
118857
|
+
/** Stores the CMMD Work Session id a kicked thread's root turn belongs to (forge#3466). */
|
|
118858
|
+
var _077_ProjectionThreadWorkSessionId_default = require_Schema$1.gen(function* () {
|
|
118859
|
+
const sql = yield* require_SqlError.SqlClient;
|
|
118860
|
+
if (!(yield* sql`
|
|
118861
|
+
PRAGMA table_info(projection_threads)
|
|
118862
|
+
`).some((column) => column.name === "work_session_id")) yield* sql`
|
|
118863
|
+
ALTER TABLE projection_threads
|
|
118864
|
+
ADD COLUMN work_session_id TEXT
|
|
118865
|
+
`;
|
|
118866
|
+
});
|
|
118867
|
+
//#endregion
|
|
118829
118868
|
//#region src/persistence/Migrations.ts
|
|
118830
118869
|
/**
|
|
118831
118870
|
* MigrationsLive - Migration runner with inline loader
|
|
@@ -119226,6 +119265,11 @@ const migrationEntries = [
|
|
|
119226
119265
|
76,
|
|
119227
119266
|
"ProjectionTurnsModelSelection",
|
|
119228
119267
|
_076_ProjectionTurnsModelSelection_default
|
|
119268
|
+
],
|
|
119269
|
+
[
|
|
119270
|
+
77,
|
|
119271
|
+
"ProjectionThreadWorkSessionId",
|
|
119272
|
+
_077_ProjectionThreadWorkSessionId_default
|
|
119229
119273
|
]
|
|
119230
119274
|
];
|
|
119231
119275
|
const makeMigrationLoader = (throughId) => fromRecord(Object.fromEntries(migrationEntries.filter(([id]) => throughId === void 0 || id <= throughId).map(([id, name, migration]) => [`${id}_${name}`, migration])));
|
|
@@ -152591,10 +152635,10 @@ function getOpenAiProviderEgressProxyConfig(input) {
|
|
|
152591
152635
|
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.`
|
|
152592
152636
|
};
|
|
152593
152637
|
}
|
|
152594
|
-
function configuredRuntimeMachineId() {
|
|
152638
|
+
function configuredRuntimeMachineId$1() {
|
|
152595
152639
|
return process.env.FORGE_CMMD_RUNTIME_MACHINE_ID?.trim() || null;
|
|
152596
152640
|
}
|
|
152597
|
-
function configuredRuntimeCredentialEpoch() {
|
|
152641
|
+
function configuredRuntimeCredentialEpoch$1() {
|
|
152598
152642
|
const raw = process.env.FORGE_CMMD_RUNTIME_CREDENTIAL_EPOCH?.trim();
|
|
152599
152643
|
return raw === void 0 ? void 0 : Number(raw);
|
|
152600
152644
|
}
|
|
@@ -152665,15 +152709,15 @@ function resolveBrokerTicketOutcome(input) {
|
|
|
152665
152709
|
function providerEgressRequiresOwnerSession() {
|
|
152666
152710
|
if (!canIssueCmmdRuntimeProviderEgressToken()) return false;
|
|
152667
152711
|
return classifyRuntimeBrokerIdentity({
|
|
152668
|
-
machineId: configuredRuntimeMachineId() ?? void 0,
|
|
152669
|
-
credentialEpoch: configuredRuntimeCredentialEpoch(),
|
|
152712
|
+
machineId: configuredRuntimeMachineId$1() ?? void 0,
|
|
152713
|
+
credentialEpoch: configuredRuntimeCredentialEpoch$1(),
|
|
152670
152714
|
brokerAuthorityMode: process.env.FORGE_CMMD_RUNTIME_BROKER_AUTHORITY_MODE
|
|
152671
152715
|
}).mode === "exact";
|
|
152672
152716
|
}
|
|
152673
152717
|
function runtimeProviderBrokerToken(input) {
|
|
152674
152718
|
const identity = classifyRuntimeBrokerIdentity({
|
|
152675
|
-
machineId: configuredRuntimeMachineId() ?? void 0,
|
|
152676
|
-
credentialEpoch: configuredRuntimeCredentialEpoch(),
|
|
152719
|
+
machineId: configuredRuntimeMachineId$1() ?? void 0,
|
|
152720
|
+
credentialEpoch: configuredRuntimeCredentialEpoch$1(),
|
|
152677
152721
|
brokerAuthorityMode: process.env.FORGE_CMMD_RUNTIME_BROKER_AUTHORITY_MODE
|
|
152678
152722
|
});
|
|
152679
152723
|
if (identity.mode !== "exact") return resolveBrokerTicketOutcome({
|
|
@@ -152814,8 +152858,8 @@ function runtimeCredentialFromGrant(provider, payload, controlPlaneUrl) {
|
|
|
152814
152858
|
return deliveryBoundRuntimeCredential(provider, payload, controlPlaneUrl);
|
|
152815
152859
|
}
|
|
152816
152860
|
function deliveryBoundRuntimeCredential(provider, payload, controlPlaneUrl) {
|
|
152817
|
-
const runtimeMachineId = configuredRuntimeMachineId();
|
|
152818
|
-
const runtimeCredentialEpoch = configuredRuntimeCredentialEpoch();
|
|
152861
|
+
const runtimeMachineId = configuredRuntimeMachineId$1();
|
|
152862
|
+
const runtimeCredentialEpoch = configuredRuntimeCredentialEpoch$1();
|
|
152819
152863
|
if (!runtimeMachineId || runtimeCredentialEpoch === void 0) throw new Error("Provider proxy token response was missing exact runtime authority.");
|
|
152820
152864
|
const deliveryReceipt = parseProviderRuntimeDeliveryReceipt(payload.deliveryReceipt, {
|
|
152821
152865
|
provider,
|
|
@@ -211957,7 +212001,7 @@ function createCodexCmmdSidekickDynamicToolHandler(session) {
|
|
|
211957
212001
|
//#region src/cmmdData/cmmdDelegatedToolCatalog.ts
|
|
211958
212002
|
const CATALOG_PATH = "/api/forge/context/sidekick/tools/catalog";
|
|
211959
212003
|
const EXECUTE_PATH = "/api/forge/context/sidekick/tools/execute";
|
|
211960
|
-
const AUTH_REQUIRED = {
|
|
212004
|
+
const AUTH_REQUIRED$1 = {
|
|
211961
212005
|
ok: false,
|
|
211962
212006
|
code: "CMMD_AUTH_REQUIRED"
|
|
211963
212007
|
};
|
|
@@ -211965,11 +212009,32 @@ function upstreamErrorCode(error) {
|
|
|
211965
212009
|
if (error && typeof error === "object" && "code" in error && typeof error.code === "string") return error.code;
|
|
211966
212010
|
return "CMMD_REST_ERROR";
|
|
211967
212011
|
}
|
|
211968
|
-
|
|
212012
|
+
/**
|
|
212013
|
+
* The Work Session lane, tried before the owner-JWT lane ever runs
|
|
212014
|
+
* (forge#3466 review, should-fix 3). A headless sprite's Work Session thread
|
|
212015
|
+
* never carries an owner JWT (CMMD ADR-015), so trying that lane first only
|
|
212016
|
+
* spends a lookup before falling through to the same broker call every time
|
|
212017
|
+
* — and on a sprite in runtime mode, the owner's browser and CMMD's kick
|
|
212018
|
+
* authenticate into the same synthetic session, so a resolved JWT there is
|
|
212019
|
+
* never legitimately this Work Session's own. Reading fresh on every call,
|
|
212020
|
+
* not once at construction, is what makes blocker 1's fix work: session
|
|
212021
|
+
* start, the ~30-second renewal, and a post-`capability_invalid` re-mint all
|
|
212022
|
+
* land here, so a Retry that rebinds the thread mid-session is picked up on
|
|
212023
|
+
* its very next mint instead of being stuck asking for the session that just
|
|
212024
|
+
* failed. Returns null (not a failure) for a person-started thread, which
|
|
212025
|
+
* supplies no `readWorkSessionId` and keeps today's owner lane byte for byte.
|
|
212026
|
+
*/
|
|
212027
|
+
async function resolveViaWorkSession(workSessionCapability, scope) {
|
|
212028
|
+
const workSessionId = workSessionCapability.readWorkSessionId ? await workSessionCapability.readWorkSessionId() : null;
|
|
212029
|
+
if (workSessionId === null) return null;
|
|
212030
|
+
return workSessionCapability.requestCapability ? workSessionCapability.requestCapability(workSessionId, scope.threadId) : AUTH_REQUIRED$1;
|
|
212031
|
+
}
|
|
212032
|
+
async function listCatalog(resolveJwt, workSessionCapability, scope) {
|
|
212033
|
+
const viaWorkSession = await resolveViaWorkSession(workSessionCapability, scope);
|
|
212034
|
+
if (viaWorkSession !== null) return viaWorkSession;
|
|
211969
212035
|
const sessionId = readThreadSessionId(scope.threadId);
|
|
211970
|
-
|
|
211971
|
-
|
|
211972
|
-
if (!jwt) return AUTH_REQUIRED;
|
|
212036
|
+
const jwt = sessionId ? await resolveJwt(sessionId) : null;
|
|
212037
|
+
if (!jwt) return AUTH_REQUIRED$1;
|
|
211973
212038
|
const body = { forgeThreadId: scope.threadId };
|
|
211974
212039
|
if (scope.projectId !== void 0) body["projectId"] = scope.projectId;
|
|
211975
212040
|
if (scope.forgeAgentId !== void 0) body["forgeAgentId"] = scope.forgeAgentId;
|
|
@@ -212019,9 +212084,9 @@ async function execute(request) {
|
|
|
212019
212084
|
};
|
|
212020
212085
|
}
|
|
212021
212086
|
}
|
|
212022
|
-
function createCmmdDelegatedToolCatalogClient(resolveJwt) {
|
|
212087
|
+
function createCmmdDelegatedToolCatalogClient(resolveJwt, workSessionCapability = {}) {
|
|
212023
212088
|
return {
|
|
212024
|
-
listCatalog: (scope) => listCatalog(resolveJwt, scope),
|
|
212089
|
+
listCatalog: (scope) => listCatalog(resolveJwt, workSessionCapability, scope),
|
|
212025
212090
|
execute
|
|
212026
212091
|
};
|
|
212027
212092
|
}
|
|
@@ -212076,9 +212141,144 @@ function createCmmdSidekickToolSession(client, scope) {
|
|
|
212076
212141
|
};
|
|
212077
212142
|
}
|
|
212078
212143
|
//#endregion
|
|
212144
|
+
//#region src/cmmdData/cmmdWorkSessionCapabilityBroker.ts
|
|
212145
|
+
/**
|
|
212146
|
+
* CMMD's Work Session Sidekick-capability broker client (forge#3466,
|
|
212147
|
+
* CMMD#5026).
|
|
212148
|
+
*
|
|
212149
|
+
* A headless sprite runs a Work Session's root thread with no owner JWT or
|
|
212150
|
+
* PAT: nobody signed in. `cmmdDelegatedToolCatalog.ts`'s owner-JWT lane falls
|
|
212151
|
+
* through to this one instead, presenting the runtime's OWN grant (never a
|
|
212152
|
+
* JWT, per CMMD ADR-015) plus the Work Session id CMMD stamped on the thread,
|
|
212153
|
+
* and getting back the same delegated Sidekick capability shape the owner
|
|
212154
|
+
* lane mints.
|
|
212155
|
+
*/
|
|
212156
|
+
const SIDEKICK_CAPABILITY_TIMEOUT_MS = 1e4;
|
|
212157
|
+
const AUTH_REQUIRED = {
|
|
212158
|
+
ok: false,
|
|
212159
|
+
code: "CMMD_AUTH_REQUIRED"
|
|
212160
|
+
};
|
|
212161
|
+
function configuredRuntimeMachineId() {
|
|
212162
|
+
return process.env.FORGE_CMMD_RUNTIME_MACHINE_ID?.trim() || void 0;
|
|
212163
|
+
}
|
|
212164
|
+
function configuredRuntimeCredentialEpoch() {
|
|
212165
|
+
const raw = process.env.FORGE_CMMD_RUNTIME_CREDENTIAL_EPOCH?.trim();
|
|
212166
|
+
return raw === void 0 ? void 0 : Number(raw);
|
|
212167
|
+
}
|
|
212168
|
+
/**
|
|
212169
|
+
* The runtime's own bearer for the "sidekick" broker scope.
|
|
212170
|
+
*
|
|
212171
|
+
* Follows the same exact-machine / legacy split as
|
|
212172
|
+
* `GitHubBroker.resolveRuntimeGrant`, including its `runtimeRole !== "user-vm"`
|
|
212173
|
+
* gate (forge#3466 review, should-fix 4, via the resolver both share:
|
|
212174
|
+
* `isCmmdCloudRuntimeModeEnv`): an exact-machine runtime presents whatever
|
|
212175
|
+
* ticket CMMD already delivered into the broker-authority cache for this
|
|
212176
|
+
* scope (an inbound request installs it as a side effect of authenticating;
|
|
212177
|
+
* CMMD's runtime ticket carries `sidekick` alongside `provider`/`github`/etc,
|
|
212178
|
+
* so it lands there the same way). A legacy runtime presents its one
|
|
212179
|
+
* portable grant token. A runtime with no id, an identity that is neither
|
|
212180
|
+
* exact nor legacy, or a role that isn't a managed CMMD cloud runtime at
|
|
212181
|
+
* all, has nothing to present — a local Forge with a stray
|
|
212182
|
+
* `FORGE_CMMD_RUNTIME_ID` left over from a legacy config must never present
|
|
212183
|
+
* its portable grant token as though it were a sprite.
|
|
212184
|
+
*/
|
|
212185
|
+
function resolveWorkSessionSidekickRuntimeGrant() {
|
|
212186
|
+
if (!isCmmdCloudRuntimeModeEnv()) return null;
|
|
212187
|
+
const runtimeId = process.env.FORGE_CMMD_RUNTIME_ID?.trim();
|
|
212188
|
+
if (!runtimeId) return null;
|
|
212189
|
+
const identity = classifyRuntimeBrokerIdentity({
|
|
212190
|
+
machineId: configuredRuntimeMachineId(),
|
|
212191
|
+
credentialEpoch: configuredRuntimeCredentialEpoch(),
|
|
212192
|
+
brokerAuthorityMode: process.env.FORGE_CMMD_RUNTIME_BROKER_AUTHORITY_MODE
|
|
212193
|
+
});
|
|
212194
|
+
if (identity.mode === "exact") {
|
|
212195
|
+
const authority = readRuntimeBrokerAuthorityForRuntime({
|
|
212196
|
+
runtimeId,
|
|
212197
|
+
machineId: identity.machineId,
|
|
212198
|
+
credentialEpoch: identity.credentialEpoch,
|
|
212199
|
+
requiredScope: "sidekick"
|
|
212200
|
+
});
|
|
212201
|
+
return authority ? {
|
|
212202
|
+
runtimeId,
|
|
212203
|
+
token: authority.token
|
|
212204
|
+
} : null;
|
|
212205
|
+
}
|
|
212206
|
+
if (identity.mode === "invalid") return null;
|
|
212207
|
+
const legacyToken = require_runtimeControlAuthority.runtimeGrantToken();
|
|
212208
|
+
return legacyToken ? {
|
|
212209
|
+
runtimeId,
|
|
212210
|
+
token: legacyToken
|
|
212211
|
+
} : null;
|
|
212212
|
+
}
|
|
212213
|
+
function isRawSidekickCapabilityResponse(value) {
|
|
212214
|
+
if (typeof value !== "object" || value === null) return false;
|
|
212215
|
+
const record = value;
|
|
212216
|
+
return Array.isArray(record.tools) && typeof record.catalogVersion === "string" && typeof record.capabilitySessionId === "number" && typeof record.capabilityToken === "string" && typeof record.expiresAt === "string";
|
|
212217
|
+
}
|
|
212218
|
+
/**
|
|
212219
|
+
* Mints a Work Session Sidekick capability straight from CMMD, for a thread
|
|
212220
|
+
* whose owner JWT never resolved.
|
|
212221
|
+
*
|
|
212222
|
+
* The mint route answers a bare JSON body, never CMMD's forge-context
|
|
212223
|
+
* `{ data: ... }` envelope the owner-JWT catalog route uses, so this never
|
|
212224
|
+
* unwraps `.data`. Always resolves, never throws: a missing runtime grant, a
|
|
212225
|
+
* network failure, and a refusal from CMMD (the broker feature flag is off,
|
|
212226
|
+
* the Work Session ended, this runtime is not its starter, ...) all fold to
|
|
212227
|
+
* the same `CMMD_AUTH_REQUIRED` the owner-JWT lane already returns on any
|
|
212228
|
+
* auth failure, so callers need exactly one failure branch. The refusal's
|
|
212229
|
+
* own code is logged, not returned, so an operator can still tell the cases
|
|
212230
|
+
* apart.
|
|
212231
|
+
*/
|
|
212232
|
+
async function requestWorkSessionSidekickCapability(workSessionId, threadId, deps = {}) {
|
|
212233
|
+
const grant = (deps.resolveRuntimeGrant ?? resolveWorkSessionSidekickRuntimeGrant)();
|
|
212234
|
+
if (!grant) {
|
|
212235
|
+
console.warn(`[cmmd-work-session-capability] no runtime grant for the sidekick scope (thread ${threadId}, work session ${workSessionId})`);
|
|
212236
|
+
return AUTH_REQUIRED;
|
|
212237
|
+
}
|
|
212238
|
+
const fetchImpl = deps.fetch ?? fetch;
|
|
212239
|
+
const url = resolveCommandAppEndpoint(`/api/forge/runtimes/${encodeURIComponent(grant.runtimeId)}/sidekick-capability`);
|
|
212240
|
+
let response;
|
|
212241
|
+
try {
|
|
212242
|
+
response = await fetchImpl(url, {
|
|
212243
|
+
method: "POST",
|
|
212244
|
+
headers: {
|
|
212245
|
+
Authorization: `Bearer ${grant.token}`,
|
|
212246
|
+
"Content-Type": "application/json"
|
|
212247
|
+
},
|
|
212248
|
+
body: JSON.stringify({ workSessionId }),
|
|
212249
|
+
signal: AbortSignal.timeout(SIDEKICK_CAPABILITY_TIMEOUT_MS)
|
|
212250
|
+
});
|
|
212251
|
+
} catch (error) {
|
|
212252
|
+
console.warn("[cmmd-work-session-capability] broker request failed:", error instanceof Error ? error.message : String(error));
|
|
212253
|
+
return AUTH_REQUIRED;
|
|
212254
|
+
}
|
|
212255
|
+
if (!response.ok) {
|
|
212256
|
+
const body = await response.json().catch(() => null);
|
|
212257
|
+
const code = body && typeof body === "object" && typeof body.code === "string" ? body.code : `HTTP_${response.status}`;
|
|
212258
|
+
console.warn(`[cmmd-work-session-capability] broker refused the mint (${code})`);
|
|
212259
|
+
return AUTH_REQUIRED;
|
|
212260
|
+
}
|
|
212261
|
+
const data = await response.json().catch(() => null);
|
|
212262
|
+
if (!isRawSidekickCapabilityResponse(data)) {
|
|
212263
|
+
console.warn("[cmmd-work-session-capability] broker returned an unexpected mint response");
|
|
212264
|
+
return AUTH_REQUIRED;
|
|
212265
|
+
}
|
|
212266
|
+
return {
|
|
212267
|
+
ok: true,
|
|
212268
|
+
tools: data.tools,
|
|
212269
|
+
catalogVersion: data.catalogVersion,
|
|
212270
|
+
capabilitySessionId: data.capabilitySessionId,
|
|
212271
|
+
capabilityToken: data.capabilityToken,
|
|
212272
|
+
expiresAt: data.expiresAt
|
|
212273
|
+
};
|
|
212274
|
+
}
|
|
212275
|
+
//#endregion
|
|
212079
212276
|
//#region src/cmmdData/resolveCmmdSidekickToolCatalog.ts
|
|
212080
|
-
async function resolveCmmdSidekickToolCatalog(resolveJwt, threadId) {
|
|
212081
|
-
const session = createCmmdSidekickToolSession(createCmmdDelegatedToolCatalogClient(resolveJwt
|
|
212277
|
+
async function resolveCmmdSidekickToolCatalog(resolveJwt, threadId, options = {}) {
|
|
212278
|
+
const session = createCmmdSidekickToolSession(createCmmdDelegatedToolCatalogClient(resolveJwt, {
|
|
212279
|
+
...options.readWorkSessionId !== void 0 ? { readWorkSessionId: options.readWorkSessionId } : {},
|
|
212280
|
+
requestCapability: options.requestWorkSessionCapability ?? requestWorkSessionSidekickCapability
|
|
212281
|
+
}), { threadId });
|
|
212082
212282
|
const catalog = await session.getCatalog();
|
|
212083
212283
|
return {
|
|
212084
212284
|
session,
|
|
@@ -212098,6 +212298,36 @@ async function resolveCmmdSidekickJwt(input) {
|
|
|
212098
212298
|
});
|
|
212099
212299
|
}
|
|
212100
212300
|
//#endregion
|
|
212301
|
+
//#region src/cmmdData/cmmdWorkSessionThreadLookup.ts
|
|
212302
|
+
const WorkSessionIdRow = require_Schema$1.Struct({ workSessionId: require_Schema$1.NullOr(require_Schema$1.String) });
|
|
212303
|
+
const decodeWorkSessionIdRows = require_Schema$1.decodeUnknownEffect(require_Schema$1.ArraySchema(WorkSessionIdRow));
|
|
212304
|
+
/**
|
|
212305
|
+
* Reads the CMMD Work Session id CMMD stamped on a thread's `thread.create`,
|
|
212306
|
+
* straight from the projected thread row (forge#3466). Null for a
|
|
212307
|
+
* person-started thread, for a thread projected before this field existed,
|
|
212308
|
+
* and for a thread id with no projected row at all.
|
|
212309
|
+
*
|
|
212310
|
+
* A minimal raw-SQL read against `projection_threads`, deliberately not
|
|
212311
|
+
* routed through `ProjectionThreadRepository`: the adapters that need this
|
|
212312
|
+
* (`ClaudeAdapter.ts`, `CodexAdapter.ts`) already capture only
|
|
212313
|
+
* `SqlClient.SqlClient` at session-build time (see `readThreadAuthSession`
|
|
212314
|
+
* in `GitHubAgentToolStore.ts` for the established pattern this follows), and
|
|
212315
|
+
* widening that capture to a second service for one column is not worth the
|
|
212316
|
+
* risk to every other call sharing it.
|
|
212317
|
+
*/
|
|
212318
|
+
function readThreadWorkSessionId(threadId) {
|
|
212319
|
+
return require_Schema$1.gen(function* () {
|
|
212320
|
+
return (yield* decodeWorkSessionIdRows(yield* (yield* require_SqlError.SqlClient)`
|
|
212321
|
+
SELECT work_session_id AS "workSessionId"
|
|
212322
|
+
FROM projection_threads
|
|
212323
|
+
WHERE thread_id = ${threadId}
|
|
212324
|
+
LIMIT 1
|
|
212325
|
+
`))[0]?.workSessionId ?? null;
|
|
212326
|
+
}).pipe(require_Schema$1.tapError((error) => require_Schema$1.sync(() => {
|
|
212327
|
+
console.warn(`[cmmd-work-session-thread-lookup] failed to read work_session_id for thread ${threadId}:`, error instanceof Error ? error.message : String(error));
|
|
212328
|
+
})), require_Schema$1.orElseSucceed(() => null));
|
|
212329
|
+
}
|
|
212330
|
+
//#endregion
|
|
212101
212331
|
//#region ../../packages/shared/src/computerUsePermission.ts
|
|
212102
212332
|
/**
|
|
212103
212333
|
* Single source of truth for the computer-use permission default.
|
|
@@ -213688,13 +213918,14 @@ const makeCodexAdapter = require_Schema$1.fn("makeCodexAdapter")(function* (opti
|
|
|
213688
213918
|
const jwt = readCommandJwtForSession(binding.sessionId);
|
|
213689
213919
|
return jwt ? { jwt } : null;
|
|
213690
213920
|
} });
|
|
213921
|
+
const readCmmdWorkSessionId = () => runWithRuntimeContext(readThreadWorkSessionId(input.threadId));
|
|
213691
213922
|
const { session: cmmdSidekickToolSession, tools: cmmdSidekickTools } = yield* require_Schema$1.promise(() => resolveCmmdSidekickToolCatalog((sessionId) => resolveCmmdSidekickJwt({
|
|
213692
213923
|
threadId: input.threadId,
|
|
213693
213924
|
sessionId,
|
|
213694
213925
|
logPrefix: "codex-cmmd-sidekick",
|
|
213695
213926
|
readThreadAuth: (threadId) => runWithRuntimeContext(readThreadAuthSession(threadId)),
|
|
213696
213927
|
resolveJwt: (options) => runWithRuntimeContext(resolveCmmdJwtForSession(options))
|
|
213697
|
-
}), input.threadId));
|
|
213928
|
+
}), input.threadId, { readWorkSessionId: readCmmdWorkSessionId }));
|
|
213698
213929
|
const cmmdSidekickToolNames = new Set(cmmdSidekickTools.map((tool) => tool.name));
|
|
213699
213930
|
const devServerToolDeps = {
|
|
213700
213931
|
threadDevRuntime,
|
|
@@ -215809,6 +216040,21 @@ const SIGNIN_REQUIRED = {
|
|
|
215809
216040
|
action: "notify_human",
|
|
215810
216041
|
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."
|
|
215811
216042
|
};
|
|
216043
|
+
/**
|
|
216044
|
+
* Same failure as {@link SIGNIN_REQUIRED} (no CMMD sign-in exists for this
|
|
216045
|
+
* session), but for a headless Work Session runtime that was never going to
|
|
216046
|
+
* have one: nobody is present to sign in (CMMD ADR-015). Telling the agent
|
|
216047
|
+
* to ask a human to sign in is wrong there. When CMMD's Sidekick capability
|
|
216048
|
+
* broker minted delegated tools for this Work Session (forge#3466,
|
|
216049
|
+
* CMMD#5026), point at them instead of dead-ending.
|
|
216050
|
+
*/
|
|
216051
|
+
const WORK_SESSION_CONTEXT_VIA_DELEGATED_TOOLS = {
|
|
216052
|
+
ok: false,
|
|
216053
|
+
code: "signin_required",
|
|
216054
|
+
retryable: false,
|
|
216055
|
+
action: "skip",
|
|
216056
|
+
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."
|
|
216057
|
+
};
|
|
215812
216058
|
/** Map a thrown CMMD client error to a recoverable envelope. */
|
|
215813
216059
|
function errorEnvelope(err) {
|
|
215814
216060
|
if (isCmmdMcpAuthError$2(err)) return {
|
|
@@ -215871,12 +216117,13 @@ function projectIdToToolArg(projectId) {
|
|
|
215871
216117
|
* mutation arg. The `action` arg of CMMD's multiplexed tools is hardcoded to a
|
|
215872
216118
|
* read inside contextBuilder and never surfaced to the LLM.
|
|
215873
216119
|
*/
|
|
215874
|
-
function makeCmmdContextHandlers(resolvePat) {
|
|
216120
|
+
function makeCmmdContextHandlers(resolvePat, options = {}) {
|
|
216121
|
+
const noPatEnvelope = options.hasWorkSessionPacketTool ? WORK_SESSION_CONTEXT_VIA_DELEGATED_TOOLS : SIGNIN_REQUIRED;
|
|
215875
216122
|
return {
|
|
215876
216123
|
getCurrentContext: async () => {
|
|
215877
216124
|
try {
|
|
215878
216125
|
const pat = await resolvePat();
|
|
215879
|
-
if (!pat) return envelope(
|
|
216126
|
+
if (!pat) return envelope(noPatEnvelope);
|
|
215880
216127
|
const snapshot = await buildCurrentContextSnapshot(pat, {
|
|
215881
216128
|
maxCampaigns: 3,
|
|
215882
216129
|
maxProjects: 5,
|
|
@@ -215909,7 +216156,7 @@ function makeCmmdContextHandlers(resolvePat) {
|
|
|
215909
216156
|
message: "Provide a non-empty `query` to search the CMMD knowledge base."
|
|
215910
216157
|
});
|
|
215911
216158
|
const pat = await resolvePat();
|
|
215912
|
-
if (!pat) return envelope(
|
|
216159
|
+
if (!pat) return envelope(noPatEnvelope);
|
|
215913
216160
|
const effectiveLimit = clampLimit(limit, DEFAULT_BRAIN_LIMIT, MAX_BRAIN_LIMIT);
|
|
215914
216161
|
const result = await callCmmdTool$2(pat, "search_brain_documents", {
|
|
215915
216162
|
query: trimmedQuery,
|
|
@@ -215963,7 +216210,7 @@ function makeCmmdContextHandlers(resolvePat) {
|
|
|
215963
216210
|
message: "Provide a `projectId` (from cmmd_get_current_context data.projects[].id)."
|
|
215964
216211
|
});
|
|
215965
216212
|
const pat = await resolvePat();
|
|
215966
|
-
if (!pat) return envelope(
|
|
216213
|
+
if (!pat) return envelope(noPatEnvelope);
|
|
215967
216214
|
const result = await callCmmdTool$2(pat, "list_board_tasks", { project_id: projectIdToToolArg(trimmedId) });
|
|
215968
216215
|
if (result.isError) return envelope(isErrorEnvelope(result));
|
|
215969
216216
|
const text = extractMcpToolText$2(result);
|
|
@@ -215992,8 +216239,8 @@ function makeCmmdContextHandlers(resolvePat) {
|
|
|
215992
216239
|
* when the user is not authenticated with CMMD. Called per
|
|
215993
216240
|
* tool invocation so a mid-session token refresh is picked up.
|
|
215994
216241
|
*/
|
|
215995
|
-
function createCmmdContextMcpServer(threadId, resolvePat) {
|
|
215996
|
-
const handlers = makeCmmdContextHandlers(resolvePat);
|
|
216242
|
+
function createCmmdContextMcpServer(threadId, resolvePat, options = {}) {
|
|
216243
|
+
const handlers = makeCmmdContextHandlers(resolvePat, options);
|
|
215997
216244
|
return z1e({
|
|
215998
216245
|
name: "cmmd-context",
|
|
215999
216246
|
tools: [
|
|
@@ -216516,7 +216763,7 @@ function buildClaudeMcpServers(input) {
|
|
|
216516
216763
|
return {
|
|
216517
216764
|
"forge-browser": createBrowserMcpServer(input.browserManager, input.threadId, browserToolScope(input.browserToolEnvironmentId)),
|
|
216518
216765
|
"forge-dev-server": createDevServerMcpServer(input.devServerToolDeps, input.threadId),
|
|
216519
|
-
"cmmd-context": createCmmdContextMcpServer(input.threadId, input.resolveCmmdPat),
|
|
216766
|
+
"cmmd-context": createCmmdContextMcpServer(input.threadId, input.resolveCmmdPat, { hasWorkSessionPacketTool: input.hasWorkSessionPacketTool }),
|
|
216520
216767
|
[GITHUB_MCP_SERVER_NAME]: createGitHubMcpServer(input.runBrokeredGitHubTool, input.threadId, input.serverSettings),
|
|
216521
216768
|
...input.computerManager ? { [COMPUTER_MCP_SERVER_NAME]: createComputerMcpServer(input.computerManager, input.threadId) } : {},
|
|
216522
216769
|
...input.cmmdSidekickTools ? { "cmmd-sidekick-tools": createCmmdSidekickToolsMcpServer(input.cmmdSidekickTools.session, input.cmmdSidekickTools.tools) } : {},
|
|
@@ -216560,19 +216807,47 @@ function claudePermissionQueryOptions(permissionMode) {
|
|
|
216560
216807
|
function createClaudePromptStream(promptQueue) {
|
|
216561
216808
|
return require_Path.fromQueue(promptQueue).pipe(require_Path.filter((item) => item.type === "message"), require_Path.map((item) => item.message), require_Path.catchCause((cause) => require_Schema$1.hasInterruptsOnly(cause) ? require_Path.empty : require_Path.failCause(cause)), require_Path.toAsyncIterable);
|
|
216562
216809
|
}
|
|
216563
|
-
function createCmmdPatResolver(threadId) {
|
|
216810
|
+
function createCmmdPatResolver(threadId, readWorkSessionId) {
|
|
216564
216811
|
return async () => {
|
|
216812
|
+
if (await readWorkSessionId() !== null) return null;
|
|
216565
216813
|
const ownerSessionId = readThreadSessionId(threadId);
|
|
216566
216814
|
if (!ownerSessionId) return null;
|
|
216567
216815
|
return readCommandAccessTokenForSession(ownerSessionId);
|
|
216568
216816
|
};
|
|
216569
216817
|
}
|
|
216570
|
-
function resolveCmmdSidekickTools(resolveJwt, threadId) {
|
|
216571
|
-
return require_Schema$1.promise(() => resolveCmmdSidekickToolCatalog(resolveJwt, threadId)).pipe(require_Schema$1.map((resolved) => ({
|
|
216818
|
+
function resolveCmmdSidekickTools(resolveJwt, threadId, readWorkSessionId) {
|
|
216819
|
+
return require_Schema$1.promise(() => resolveCmmdSidekickToolCatalog(resolveJwt, threadId, { readWorkSessionId })).pipe(require_Schema$1.map((resolved) => ({
|
|
216572
216820
|
registration: resolved.tools.length > 0 ? resolved : null,
|
|
216573
216821
|
codewebMcpGrant: resolved.codewebMcp
|
|
216574
216822
|
})));
|
|
216575
216823
|
}
|
|
216824
|
+
/**
|
|
216825
|
+
* Name of the delegated tool that returns a Work Session's task packet
|
|
216826
|
+
* (CMMD's Agent Plan family, ADR-029). Forge's Sidekick capability broker
|
|
216827
|
+
* always mounts this for a Work Session (CMMD's `forge-surface.ts` curated
|
|
216828
|
+
* allowlist, verified 2026-09-26), so its presence in the granted catalog is
|
|
216829
|
+
* exactly "a Work Session capability exists for this thread". See
|
|
216830
|
+
* `cmmdContextMcpServer.ts`'s no-PAT branch (forge#3466).
|
|
216831
|
+
*/
|
|
216832
|
+
const WORK_SESSION_PACKET_TOOL_NAME = "cmmd_get_agent_plan";
|
|
216833
|
+
/**
|
|
216834
|
+
* Whether `cmmd-context`'s no-PAT branch should point at delegated tools
|
|
216835
|
+
* instead of asking the user to sign in (forge#3466 review, should-fix 5).
|
|
216836
|
+
*
|
|
216837
|
+
* Gating on `workSessionId !== null` alone, without a separate "which lane
|
|
216838
|
+
* minted this" tag, is sound because `cmmdDelegatedToolCatalog.ts`'s
|
|
216839
|
+
* `listCatalog` (should-fix 3) structurally never calls the owner-JWT lane
|
|
216840
|
+
* once a Work Session id is present — it returns straight from the broker
|
|
216841
|
+
* call or `AUTH_REQUIRED`. So a non-null `workSessionId` here can only ever
|
|
216842
|
+
* pair with a broker-minted registration. Before that reorder, the owner-JWT
|
|
216843
|
+
* catalog (the full, unnarrowed Sidekick catalog) also contains
|
|
216844
|
+
* `cmmd_get_agent_plan`, so checking the tool name alone told a
|
|
216845
|
+
* person-started thread with a resolved JWT but no PAT that it had Work
|
|
216846
|
+
* Session tools when it never did.
|
|
216847
|
+
*/
|
|
216848
|
+
function hasWorkSessionPacketTool(workSessionId, registration) {
|
|
216849
|
+
return workSessionId !== null && (registration?.tools.some((tool) => tool.name === WORK_SESSION_PACKET_TOOL_NAME) ?? false);
|
|
216850
|
+
}
|
|
216576
216851
|
function buildDevServerToolDeps(input) {
|
|
216577
216852
|
return {
|
|
216578
216853
|
threadDevRuntime: input.threadDevRuntime,
|
|
@@ -218749,7 +219024,8 @@ const makeClaudeAdapter = require_Schema$1.fn("makeClaudeAdapter")(function* (op
|
|
|
218749
219024
|
const runPromise = require_Schema$1.runPromiseWith(runtimeContext);
|
|
218750
219025
|
const browserToolEnvironmentId = yield* resolveBrowserToolEnvironmentId();
|
|
218751
219026
|
const computerManager = resolveComputerManager(serverConfig);
|
|
218752
|
-
const
|
|
219027
|
+
const readWorkSessionId = () => runWithSqlRuntimeContext(readThreadWorkSessionId(threadId));
|
|
219028
|
+
const resolveCmmdPat = createCmmdPatResolver(threadId, readWorkSessionId);
|
|
218753
219029
|
const resolveCmmdSidekickJwtForSession = (sessionId) => resolveCmmdSidekickJwt({
|
|
218754
219030
|
threadId,
|
|
218755
219031
|
sessionId,
|
|
@@ -218757,7 +219033,8 @@ const makeClaudeAdapter = require_Schema$1.fn("makeClaudeAdapter")(function* (op
|
|
|
218757
219033
|
readThreadAuth: (targetThreadId) => runWithSqlRuntimeContext(readThreadAuthSession(targetThreadId)),
|
|
218758
219034
|
resolveJwt: (options) => runWithSqlRuntimeContext(resolveCmmdJwtForSession(options))
|
|
218759
219035
|
});
|
|
218760
|
-
const
|
|
219036
|
+
const workSessionId = yield* require_Schema$1.promise(readWorkSessionId);
|
|
219037
|
+
const cmmdSidekickResolution = yield* resolveCmmdSidekickTools(resolveCmmdSidekickJwtForSession, threadId, readWorkSessionId);
|
|
218761
219038
|
const devServerToolDeps = buildDevServerToolDeps({
|
|
218762
219039
|
threadDevRuntime,
|
|
218763
219040
|
devTunnel,
|
|
@@ -218842,6 +219119,7 @@ const makeClaudeAdapter = require_Schema$1.fn("makeClaudeAdapter")(function* (op
|
|
|
218842
219119
|
resolveCmmdPat,
|
|
218843
219120
|
devServerToolDeps,
|
|
218844
219121
|
cmmdSidekickTools: cmmdSidekickResolution.registration,
|
|
219122
|
+
hasWorkSessionPacketTool: hasWorkSessionPacketTool(workSessionId, cmmdSidekickResolution.registration),
|
|
218845
219123
|
codewebMcpInjection,
|
|
218846
219124
|
runBrokeredGitHubTool,
|
|
218847
219125
|
serverSettings
|
|
@@ -288305,6 +288583,7 @@ const ProjectionThread = require_Schema$1.Struct({
|
|
|
288305
288583
|
parentThreadId: require_Schema$1.NullOr(ThreadId).pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed(null))),
|
|
288306
288584
|
anchorKind: CmmdAnchorKind.pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed("scratch"))),
|
|
288307
288585
|
anchorCmmdId: require_Schema$1.NullOr(require_Schema$1.String).pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed(null))),
|
|
288586
|
+
workSessionId: require_Schema$1.optionalKey(require_Schema$1.NullOr(require_Schema$1.String)),
|
|
288308
288587
|
linkedPullRequest: require_Schema$1.optionalKey(require_Schema$1.NullOr(LinkedPullRequest)),
|
|
288309
288588
|
status: ThreadStatus.pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed("idle"))),
|
|
288310
288589
|
workerRole: require_Schema$1.NullOr(WorkerRole).pipe(require_Schema$1.withDecodingDefault(require_Schema$1.succeed(null))),
|
|
@@ -299479,7 +299758,7 @@ function resolveBuildCommitFromEnv(env) {
|
|
|
299479
299758
|
* environment descriptor down instead of reporting an honest "unknown".
|
|
299480
299759
|
*/
|
|
299481
299760
|
function readBakedBuildCommit() {
|
|
299482
|
-
return "
|
|
299761
|
+
return "00cc2d653acc035bf8de4ed64006a9af5c4d6362";
|
|
299483
299762
|
}
|
|
299484
299763
|
async function resolveServerBuildCommit(input) {
|
|
299485
299764
|
if (isFullCommitSha(input.baked)) return input.baked;
|
|
@@ -303129,6 +303408,7 @@ const decideOrchestrationCommand = require_Schema$1.fn("decideOrchestrationComma
|
|
|
303129
303408
|
updatedAt: command.createdAt,
|
|
303130
303409
|
anchorKind: anchor.anchorKind,
|
|
303131
303410
|
anchorCmmdId: anchor.anchorCmmdId,
|
|
303411
|
+
workSessionId: command.workSessionId ?? null,
|
|
303132
303412
|
goal: command.goal ?? null,
|
|
303133
303413
|
linkedPullRequest: command.linkedPullRequest ?? null,
|
|
303134
303414
|
kind,
|
|
@@ -303438,7 +303718,8 @@ const decideOrchestrationCommand = require_Schema$1.fn("decideOrchestrationComma
|
|
|
303438
303718
|
const providerSwitchSelection = command.modelSelection !== void 0 && command.modelSelection.provider !== targetThread.modelSelection.provider ? command.modelSelection : void 0;
|
|
303439
303719
|
const accountSelection = turnAccountSelection(targetThread.modelSelection, command.modelSelection);
|
|
303440
303720
|
const turnModelSelection = providerSwitchSelection ?? accountSelection;
|
|
303441
|
-
|
|
303721
|
+
const shouldRebindWorkSession = command.workSessionId !== void 0 && command.workSessionId !== null && command.workSessionId !== targetThread.workSessionId;
|
|
303722
|
+
if (!shouldUpdateAnchor && !turnModelSelection && !shouldRebindWorkSession) return [userMessageEvent, turnStartRequestedEvent];
|
|
303442
303723
|
return [
|
|
303443
303724
|
{
|
|
303444
303725
|
...withEventBase({
|
|
@@ -303453,6 +303734,7 @@ const decideOrchestrationCommand = require_Schema$1.fn("decideOrchestrationComma
|
|
|
303453
303734
|
anchorKind: nextAnchor.anchorKind,
|
|
303454
303735
|
anchorCmmdId: nextAnchor.anchorCmmdId,
|
|
303455
303736
|
...turnModelSelection ? { modelSelection: turnModelSelection } : {},
|
|
303737
|
+
...shouldRebindWorkSession ? { workSessionId: command.workSessionId } : {},
|
|
303456
303738
|
updatedAt: command.createdAt
|
|
303457
303739
|
}
|
|
303458
303740
|
},
|
|
@@ -303976,12 +304258,22 @@ function retainThreadActivitiesAfterRevert(activities, retainedTurnIds) {
|
|
|
303976
304258
|
function retainThreadProposedPlansAfterRevert(proposedPlans, retainedTurnIds) {
|
|
303977
304259
|
return proposedPlans.filter((proposedPlan) => proposedPlan.turnId === null || retainedTurnIds.has(proposedPlan.turnId));
|
|
303978
304260
|
}
|
|
304261
|
+
/**
|
|
304262
|
+
* Orders an unsequenced activity before a sequenced one, matching the SQL
|
|
304263
|
+
* projection's own `ORDER BY CASE WHEN sequence IS NULL THEN 0 ELSE 1 END
|
|
304264
|
+
* ASC, sequence ASC`. Zero means neither operand settles the order (both
|
|
304265
|
+
* missing, or both present and equal), so the caller falls back to a
|
|
304266
|
+
* timestamp/id tiebreak.
|
|
304267
|
+
*/
|
|
304268
|
+
function compareOptionalActivitySequence(left, right) {
|
|
304269
|
+
const leftHasSequence = left !== void 0;
|
|
304270
|
+
const rightHasSequence = right !== void 0;
|
|
304271
|
+
if (leftHasSequence !== rightHasSequence) return leftHasSequence ? 1 : -1;
|
|
304272
|
+
return leftHasSequence && rightHasSequence ? left - right : 0;
|
|
304273
|
+
}
|
|
303979
304274
|
function compareThreadActivities(left, right) {
|
|
303980
|
-
|
|
303981
|
-
|
|
303982
|
-
} else if (left.sequence !== void 0) return 1;
|
|
303983
|
-
else if (right.sequence !== void 0) return -1;
|
|
303984
|
-
return left.createdAt.localeCompare(right.createdAt) || left.id.localeCompare(right.id);
|
|
304275
|
+
const bySequence = compareOptionalActivitySequence(left.sequence, right.sequence);
|
|
304276
|
+
return bySequence !== 0 ? bySequence : left.createdAt.localeCompare(right.createdAt) || left.id.localeCompare(right.id);
|
|
303985
304277
|
}
|
|
303986
304278
|
function createEmptyReadModel(nowIso) {
|
|
303987
304279
|
return {
|
|
@@ -304012,6 +304304,7 @@ function projectEvent(model, event) {
|
|
|
304012
304304
|
worktreePath: payload.worktreePath,
|
|
304013
304305
|
anchorKind: payload.anchorKind,
|
|
304014
304306
|
anchorCmmdId: payload.anchorCmmdId,
|
|
304307
|
+
workSessionId: payload.workSessionId ?? null,
|
|
304015
304308
|
goal: payload.goal ?? null,
|
|
304016
304309
|
linkedPullRequest: payload.linkedPullRequest ?? null,
|
|
304017
304310
|
titleRegeneration: null,
|
|
@@ -304092,6 +304385,7 @@ function projectEvent(model, event) {
|
|
|
304092
304385
|
...payload.goal !== void 0 ? { goal: payload.goal } : {},
|
|
304093
304386
|
...payload.linkedPullRequest !== void 0 ? { linkedPullRequest: payload.linkedPullRequest } : {},
|
|
304094
304387
|
...payload.titleRegeneration !== void 0 ? { titleRegeneration: payload.titleRegeneration } : {},
|
|
304388
|
+
...payload.workSessionId !== void 0 ? { workSessionId: payload.workSessionId } : {},
|
|
304095
304389
|
updatedAt: payload.updatedAt
|
|
304096
304390
|
})
|
|
304097
304391
|
})));
|
|
@@ -305156,6 +305450,7 @@ const makeProjectionThreadRepository = require_Schema$1.gen(function* () {
|
|
|
305156
305450
|
parent_thread_id,
|
|
305157
305451
|
anchor_kind,
|
|
305158
305452
|
anchor_cmmd_id,
|
|
305453
|
+
work_session_id,
|
|
305159
305454
|
linked_pull_request_json,
|
|
305160
305455
|
status,
|
|
305161
305456
|
worker_role,
|
|
@@ -305188,6 +305483,7 @@ const makeProjectionThreadRepository = require_Schema$1.gen(function* () {
|
|
|
305188
305483
|
${row.parentThreadId},
|
|
305189
305484
|
${row.anchorKind},
|
|
305190
305485
|
${row.anchorCmmdId},
|
|
305486
|
+
${row.workSessionId ?? null},
|
|
305191
305487
|
${row.linkedPullRequest == null ? null : JSON.stringify(row.linkedPullRequest)},
|
|
305192
305488
|
${row.status},
|
|
305193
305489
|
${row.workerRole},
|
|
@@ -305220,6 +305516,7 @@ const makeProjectionThreadRepository = require_Schema$1.gen(function* () {
|
|
|
305220
305516
|
parent_thread_id = excluded.parent_thread_id,
|
|
305221
305517
|
anchor_kind = excluded.anchor_kind,
|
|
305222
305518
|
anchor_cmmd_id = excluded.anchor_cmmd_id,
|
|
305519
|
+
work_session_id = excluded.work_session_id,
|
|
305223
305520
|
linked_pull_request_json = excluded.linked_pull_request_json,
|
|
305224
305521
|
status = excluded.status,
|
|
305225
305522
|
worker_role = excluded.worker_role,
|
|
@@ -305257,6 +305554,7 @@ const makeProjectionThreadRepository = require_Schema$1.gen(function* () {
|
|
|
305257
305554
|
parent_thread_id AS "parentThreadId",
|
|
305258
305555
|
anchor_kind AS "anchorKind",
|
|
305259
305556
|
anchor_cmmd_id AS "anchorCmmdId",
|
|
305557
|
+
work_session_id AS "workSessionId",
|
|
305260
305558
|
linked_pull_request_json AS "linkedPullRequest",
|
|
305261
305559
|
status,
|
|
305262
305560
|
worker_role AS "workerRole",
|
|
@@ -305296,6 +305594,7 @@ const makeProjectionThreadRepository = require_Schema$1.gen(function* () {
|
|
|
305296
305594
|
parent_thread_id AS "parentThreadId",
|
|
305297
305595
|
anchor_kind AS "anchorKind",
|
|
305298
305596
|
anchor_cmmd_id AS "anchorCmmdId",
|
|
305597
|
+
work_session_id AS "workSessionId",
|
|
305299
305598
|
linked_pull_request_json AS "linkedPullRequest",
|
|
305300
305599
|
status,
|
|
305301
305600
|
worker_role AS "workerRole",
|
|
@@ -305478,6 +305777,14 @@ function collectThreadUserInputAttachmentRelativePaths(threadId, events) {
|
|
|
305478
305777
|
}
|
|
305479
305778
|
return relativePaths;
|
|
305480
305779
|
}
|
|
305780
|
+
/**
|
|
305781
|
+
* Coalesces an optional Work Session id to the persisted default. Top-level
|
|
305782
|
+
* so the `??` here does not count against `applyThreadsProjection`'s own
|
|
305783
|
+
* complexity budget. See forge#3466.
|
|
305784
|
+
*/
|
|
305785
|
+
function projectedWorkSessionId(workSessionId) {
|
|
305786
|
+
return workSessionId ?? null;
|
|
305787
|
+
}
|
|
305481
305788
|
const runAttachmentSideEffects = require_Schema$1.fn("runAttachmentSideEffects")(function* (sideEffects) {
|
|
305482
305789
|
const serverConfig = yield* require_Schema$1.service(ServerConfig);
|
|
305483
305790
|
const fileSystem = yield* require_Schema$1.service(require_Path.FileSystem);
|
|
@@ -305643,6 +305950,7 @@ const makeOrchestrationProjectionPipeline = require_Schema$1.fn("makeOrchestrati
|
|
|
305643
305950
|
parentThreadId: event.payload.parentThreadId,
|
|
305644
305951
|
anchorKind: event.payload.anchorKind,
|
|
305645
305952
|
anchorCmmdId: event.payload.anchorCmmdId,
|
|
305953
|
+
workSessionId: projectedWorkSessionId(event.payload.workSessionId),
|
|
305646
305954
|
linkedPullRequest: event.payload.linkedPullRequest ?? null,
|
|
305647
305955
|
status: event.payload.status,
|
|
305648
305956
|
workerRole: event.payload.workerRole,
|
|
@@ -305681,6 +305989,7 @@ const makeOrchestrationProjectionPipeline = require_Schema$1.fn("makeOrchestrati
|
|
|
305681
305989
|
parentThreadId: thread.parentThreadId,
|
|
305682
305990
|
anchorKind: thread.anchorKind,
|
|
305683
305991
|
anchorCmmdId: thread.anchorCmmdId,
|
|
305992
|
+
workSessionId: projectedWorkSessionId(thread.workSessionId),
|
|
305684
305993
|
linkedPullRequest: thread.linkedPullRequest ?? null,
|
|
305685
305994
|
status: thread.status,
|
|
305686
305995
|
workerRole: thread.workerRole,
|
|
@@ -305749,6 +306058,7 @@ const makeOrchestrationProjectionPipeline = require_Schema$1.fn("makeOrchestrati
|
|
|
305749
306058
|
...event.payload.goal !== void 0 ? { goal: event.payload.goal } : {},
|
|
305750
306059
|
...event.payload.linkedPullRequest !== void 0 ? { linkedPullRequest: event.payload.linkedPullRequest } : {},
|
|
305751
306060
|
...event.payload.titleRegeneration !== void 0 ? { titleRegeneration: event.payload.titleRegeneration } : {},
|
|
306061
|
+
...event.payload.workSessionId !== void 0 ? { workSessionId: projectedWorkSessionId(event.payload.workSessionId) } : {},
|
|
305752
306062
|
updatedAt: event.payload.updatedAt
|
|
305753
306063
|
});
|
|
305754
306064
|
return;
|
|
@@ -306749,6 +307059,16 @@ function probeProjectAvailability(fs, workspaceRoot) {
|
|
|
306749
307059
|
function toPersistenceSqlOrDecodeError(sqlOperation, decodeOperation) {
|
|
306750
307060
|
return (cause) => require_Schema$1.isSchemaError(cause) ? toPersistenceDecodeError(decodeOperation)(cause) : toPersistenceSqlError(sqlOperation)(cause);
|
|
306751
307061
|
}
|
|
307062
|
+
/**
|
|
307063
|
+
* `{ workSessionId }` when the row carries one, an empty object when absent,
|
|
307064
|
+
* so the built thread's optionalKey field round-trips without ever getting
|
|
307065
|
+
* assigned an explicit `undefined` (exactOptionalPropertyTypes). Pulled out
|
|
307066
|
+
* of the two thread builders that call it so this file's already-flagged
|
|
307067
|
+
* high-complexity functions do not pick up the branch. See forge#3466.
|
|
307068
|
+
*/
|
|
307069
|
+
function workSessionIdField(workSessionId) {
|
|
307070
|
+
return workSessionId !== void 0 ? { workSessionId } : {};
|
|
307071
|
+
}
|
|
306752
307072
|
const makeProjectionSnapshotQuery = require_Schema$1.gen(function* () {
|
|
306753
307073
|
const sql = yield* require_SqlError.SqlClient;
|
|
306754
307074
|
const repositoryIdentityResolver = yield* RepositoryIdentityResolver;
|
|
@@ -306801,6 +307121,7 @@ const makeProjectionSnapshotQuery = require_Schema$1.gen(function* () {
|
|
|
306801
307121
|
parent_thread_id AS "parentThreadId",
|
|
306802
307122
|
anchor_kind AS "anchorKind",
|
|
306803
307123
|
anchor_cmmd_id AS "anchorCmmdId",
|
|
307124
|
+
work_session_id AS "workSessionId",
|
|
306804
307125
|
linked_pull_request_json AS "linkedPullRequest",
|
|
306805
307126
|
status,
|
|
306806
307127
|
worker_role AS "workerRole",
|
|
@@ -306839,6 +307160,7 @@ const makeProjectionSnapshotQuery = require_Schema$1.gen(function* () {
|
|
|
306839
307160
|
parent_thread_id AS "parentThreadId",
|
|
306840
307161
|
anchor_kind AS "anchorKind",
|
|
306841
307162
|
anchor_cmmd_id AS "anchorCmmdId",
|
|
307163
|
+
work_session_id AS "workSessionId",
|
|
306842
307164
|
linked_pull_request_json AS "linkedPullRequest",
|
|
306843
307165
|
status,
|
|
306844
307166
|
worker_role AS "workerRole",
|
|
@@ -306943,6 +307265,7 @@ const makeProjectionSnapshotQuery = require_Schema$1.gen(function* () {
|
|
|
306943
307265
|
parent_thread_id AS "parentThreadId",
|
|
306944
307266
|
anchor_kind AS "anchorKind",
|
|
306945
307267
|
anchor_cmmd_id AS "anchorCmmdId",
|
|
307268
|
+
work_session_id AS "workSessionId",
|
|
306946
307269
|
linked_pull_request_json AS "linkedPullRequest",
|
|
306947
307270
|
status,
|
|
306948
307271
|
worker_role AS "workerRole",
|
|
@@ -307275,6 +307598,7 @@ const makeProjectionSnapshotQuery = require_Schema$1.gen(function* () {
|
|
|
307275
307598
|
parent_thread_id AS "parentThreadId",
|
|
307276
307599
|
anchor_kind AS "anchorKind",
|
|
307277
307600
|
anchor_cmmd_id AS "anchorCmmdId",
|
|
307601
|
+
work_session_id AS "workSessionId",
|
|
307278
307602
|
linked_pull_request_json AS "linkedPullRequest",
|
|
307279
307603
|
status,
|
|
307280
307604
|
worker_role AS "workerRole",
|
|
@@ -307587,6 +307911,7 @@ const makeProjectionSnapshotQuery = require_Schema$1.gen(function* () {
|
|
|
307587
307911
|
session: sessionsByThread.get(row.threadId) ?? null,
|
|
307588
307912
|
anchorKind: row.anchorKind,
|
|
307589
307913
|
anchorCmmdId: row.anchorCmmdId,
|
|
307914
|
+
...workSessionIdField(row.workSessionId),
|
|
307590
307915
|
linkedPullRequest: row.linkedPullRequest,
|
|
307591
307916
|
kind: row.kind,
|
|
307592
307917
|
parentThreadId: row.parentThreadId,
|
|
@@ -307836,6 +308161,7 @@ const makeProjectionSnapshotQuery = require_Schema$1.gen(function* () {
|
|
|
307836
308161
|
session: require_Schema$1.isSome(sessionRow) ? mapSessionRow(sessionRow.value) : null,
|
|
307837
308162
|
anchorKind: threadRow.value.anchorKind,
|
|
307838
308163
|
anchorCmmdId: threadRow.value.anchorCmmdId,
|
|
308164
|
+
...workSessionIdField(threadRow.value.workSessionId),
|
|
307839
308165
|
linkedPullRequest: threadRow.value.linkedPullRequest,
|
|
307840
308166
|
kind: threadRow.value.kind,
|
|
307841
308167
|
parentThreadId: threadRow.value.parentThreadId,
|
|
@@ -322947,6 +323273,11 @@ try {
|
|
|
322947
323273
|
}
|
|
322948
323274
|
}
|
|
322949
323275
|
`;
|
|
323276
|
+
const toReading = (result) => ({
|
|
323277
|
+
result,
|
|
323278
|
+
probedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
323279
|
+
});
|
|
323280
|
+
const MAX_LINGERING_PROBES = 2;
|
|
322950
323281
|
function createRuntimeFilesystemHealthRoute(input) {
|
|
322951
323282
|
return require_Schema$1.unwrap(require_Schema$1.gen(function* () {
|
|
322952
323283
|
let child = null;
|
|
@@ -322954,15 +323285,19 @@ function createRuntimeFilesystemHealthRoute(input) {
|
|
|
322954
323285
|
let cached = null;
|
|
322955
323286
|
let closed = false;
|
|
322956
323287
|
let shutdown = null;
|
|
323288
|
+
const lingering = /* @__PURE__ */ new Set();
|
|
322957
323289
|
yield* require_Schema$1.addFinalizer(() => require_Schema$1.sync(() => {
|
|
322958
323290
|
closed = true;
|
|
322959
323291
|
shutdown?.();
|
|
322960
323292
|
}));
|
|
322961
323293
|
const probe = () => {
|
|
322962
|
-
if (closed) return Promise.resolve("unavailable");
|
|
323294
|
+
if (closed) return Promise.resolve(toReading("unavailable"));
|
|
322963
323295
|
if (pending) return pending;
|
|
322964
|
-
if (cached && performance.now() < cached.expiresAt) return Promise.resolve(cached.
|
|
322965
|
-
if (
|
|
323296
|
+
if (cached && performance.now() < cached.expiresAt) return Promise.resolve(cached.reading);
|
|
323297
|
+
if (lingering.size >= MAX_LINGERING_PROBES) return Promise.resolve({
|
|
323298
|
+
...toReading("timeout"),
|
|
323299
|
+
lingeringProbes: lingering.size
|
|
323300
|
+
});
|
|
322966
323301
|
pending = new Promise((resolve) => {
|
|
322967
323302
|
const current = (0, node_child_process.spawn)(process.execPath, [
|
|
322968
323303
|
"--eval",
|
|
@@ -322976,46 +323311,58 @@ function createRuntimeFilesystemHealthRoute(input) {
|
|
|
322976
323311
|
current.unref();
|
|
322977
323312
|
const timer = setTimeout(() => {
|
|
322978
323313
|
current.kill("SIGKILL");
|
|
322979
|
-
|
|
323314
|
+
lingering.add(current);
|
|
323315
|
+
if (child === current) {
|
|
323316
|
+
child = null;
|
|
323317
|
+
shutdown = null;
|
|
323318
|
+
}
|
|
323319
|
+
resolve(toReading("timeout"));
|
|
322980
323320
|
}, input.timeoutMs ?? 3e3);
|
|
322981
323321
|
shutdown = () => {
|
|
322982
323322
|
clearTimeout(timer);
|
|
322983
323323
|
current.kill("SIGKILL");
|
|
322984
|
-
resolve("unavailable");
|
|
323324
|
+
resolve(toReading("unavailable"));
|
|
322985
323325
|
};
|
|
322986
323326
|
current.once("error", () => {
|
|
322987
323327
|
clearTimeout(timer);
|
|
323328
|
+
lingering.delete(current);
|
|
322988
323329
|
if (!current.pid && child === current) {
|
|
322989
323330
|
child = null;
|
|
322990
323331
|
shutdown = null;
|
|
322991
323332
|
}
|
|
322992
|
-
resolve("unavailable");
|
|
323333
|
+
resolve(toReading("unavailable"));
|
|
322993
323334
|
});
|
|
322994
323335
|
current.once("exit", (code) => {
|
|
322995
323336
|
clearTimeout(timer);
|
|
323337
|
+
lingering.delete(current);
|
|
322996
323338
|
if (child === current) {
|
|
322997
323339
|
child = null;
|
|
322998
323340
|
shutdown = null;
|
|
322999
323341
|
}
|
|
323000
|
-
resolve(code === 0 ? "healthy" : "io_error");
|
|
323342
|
+
resolve(toReading(code === 0 ? "healthy" : "io_error"));
|
|
323001
323343
|
});
|
|
323002
|
-
}).catch(() => "unavailable").then((
|
|
323344
|
+
}).catch(() => toReading("unavailable")).then((settled) => {
|
|
323003
323345
|
pending = null;
|
|
323004
|
-
cached = {
|
|
323005
|
-
|
|
323346
|
+
if (settled.result === "healthy") cached = {
|
|
323347
|
+
reading: settled,
|
|
323006
323348
|
expiresAt: performance.now() + (input.cacheMs ?? 1e4)
|
|
323007
323349
|
};
|
|
323008
|
-
return
|
|
323350
|
+
return settled;
|
|
323009
323351
|
});
|
|
323010
323352
|
return pending;
|
|
323011
323353
|
};
|
|
323012
323354
|
return add$1("GET", "/api/runtime/filesystem-health", require_Schema$1.gen(function* () {
|
|
323013
|
-
const
|
|
323014
|
-
const healthy = result === "healthy";
|
|
323355
|
+
const outcome = yield* require_Schema$1.promise(probe);
|
|
323356
|
+
const healthy = outcome.result === "healthy";
|
|
323015
323357
|
return require_HttpServer.jsonUnsafe({
|
|
323016
323358
|
service: "cmmd-forge-runtime",
|
|
323017
323359
|
filesystem: healthy ? "healthy" : "unhealthy",
|
|
323018
|
-
|
|
323360
|
+
probedAt: outcome.probedAt,
|
|
323361
|
+
uptimeSeconds: process.uptime(),
|
|
323362
|
+
...healthy ? {} : {
|
|
323363
|
+
reason: outcome.result,
|
|
323364
|
+
...outcome.lingeringProbes === void 0 ? {} : { lingeringProbes: outcome.lingeringProbes }
|
|
323365
|
+
}
|
|
323019
323366
|
}, {
|
|
323020
323367
|
status: healthy ? 200 : 503,
|
|
323021
323368
|
headers: { "cache-control": "no-store" }
|