@cmmd-center/forge 0.13.8 → 0.13.10
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 +330 -50
- package/dist/bin.mjs +330 -50
- package/dist/client/assets/{DiffPanel-CBfeDIH3.js → DiffPanel-aGVgMMDS.js} +3 -3
- package/dist/client/assets/{DiffPanel.logic-CZdlskWf.js → DiffPanel.logic-CAL295cZ.js} +2 -2
- package/dist/client/assets/{DiffPanelShell-BnSbIo9A.js → DiffPanelShell-BLRSawDM.js} +114 -114
- package/dist/client/assets/{DiffWorkerPoolProvider-DC4SN57K.js → DiffWorkerPoolProvider-tqcKyIAF.js} +9 -9
- package/dist/client/assets/PullRequestCodePanel-CYLmbiv7.js +5 -0
- package/dist/client/assets/{Virtualizer-ClYwoP30.js → Virtualizer-NYdNfon2.js} +2 -2
- package/dist/client/assets/index-Bx4rqeUi.css +1 -0
- package/dist/client/assets/{index-CZhTqk2p.js → index-fNpsmaLQ.js} +61 -60
- package/dist/client/index.html +5 -5
- package/dist/forge-build.json +1 -1
- package/package.json +1 -1
- package/dist/client/assets/PullRequestCodePanel-DwjjRPkc.js +0 -5
- package/dist/client/assets/index-BE83u7Db.css +0 -1
package/dist/bin.mjs
CHANGED
|
@@ -66002,7 +66002,7 @@ function normalizeNumberish(value) {
|
|
|
66002
66002
|
}
|
|
66003
66003
|
//#endregion
|
|
66004
66004
|
//#region package.json
|
|
66005
|
-
var version$1 = "0.13.
|
|
66005
|
+
var version$1 = "0.13.10";
|
|
66006
66006
|
//#endregion
|
|
66007
66007
|
//#region src/sentry.ts
|
|
66008
66008
|
const SERVER_APP_NAME = "forge-server";
|
|
@@ -87718,14 +87718,18 @@ function resolveRuntimeGitHubGrantAuthFromEnv(headers) {
|
|
|
87718
87718
|
}
|
|
87719
87719
|
function buildCmmdRuntimeGrantFetchRequest(auth, repoFullName) {
|
|
87720
87720
|
return {
|
|
87721
|
-
url: new URL(`/api/forge/runtimes/${encodeURIComponent(auth.runtimeId)}/
|
|
87721
|
+
url: new URL(`/api/forge/runtimes/${encodeURIComponent(auth.runtimeId)}/scm/credential`, resolveCommandAppUrl()).toString(),
|
|
87722
87722
|
init: {
|
|
87723
87723
|
method: "POST",
|
|
87724
87724
|
headers: {
|
|
87725
87725
|
Authorization: `Bearer ${auth.token}`,
|
|
87726
87726
|
"Content-Type": "application/json"
|
|
87727
87727
|
},
|
|
87728
|
-
body: JSON.stringify({
|
|
87728
|
+
body: JSON.stringify({
|
|
87729
|
+
provider: "github",
|
|
87730
|
+
host: "github.com",
|
|
87731
|
+
repository_path: repoFullName
|
|
87732
|
+
})
|
|
87729
87733
|
}
|
|
87730
87734
|
};
|
|
87731
87735
|
}
|
|
@@ -88187,10 +88191,19 @@ function fetchInstallationTokenForAuth(auth, repoFullName) {
|
|
|
88187
88191
|
ok: false,
|
|
88188
88192
|
...lastError
|
|
88189
88193
|
};
|
|
88190
|
-
if (tokenResp.ok)
|
|
88191
|
-
|
|
88192
|
-
token
|
|
88193
|
-
|
|
88194
|
+
if (tokenResp.ok) {
|
|
88195
|
+
const tokenData = yield* promise(() => tokenResp.json());
|
|
88196
|
+
const token = auth.kind === "cmmd-runtime-ticket" ? tokenData.credential : tokenData.token;
|
|
88197
|
+
if (typeof token === "string" && token.trim().length > 0) return {
|
|
88198
|
+
ok: true,
|
|
88199
|
+
token: token.trim()
|
|
88200
|
+
};
|
|
88201
|
+
return {
|
|
88202
|
+
ok: false,
|
|
88203
|
+
status: 502,
|
|
88204
|
+
error: "CMMD returned an invalid source-control credential response."
|
|
88205
|
+
};
|
|
88206
|
+
}
|
|
88194
88207
|
const err = yield* promise(() => tokenResp.json().catch(() => ({})));
|
|
88195
88208
|
lastError = {
|
|
88196
88209
|
status: tokenResp.status,
|
|
@@ -89112,23 +89125,38 @@ var GitHubBroker = class {
|
|
|
89112
89125
|
async cloneRepository(auth, input) {
|
|
89113
89126
|
const cloneInput = validateCloneInput(input);
|
|
89114
89127
|
if ("ok" in cloneInput) return cloneInput;
|
|
89115
|
-
|
|
89128
|
+
let { branch } = cloneInput;
|
|
89116
89129
|
const gitToken = await this.resolveInstallationToken(auth, input.repoFullName);
|
|
89117
89130
|
if (typeof gitToken !== "string") return gitToken;
|
|
89118
|
-
|
|
89131
|
+
try {
|
|
89132
|
+
await mkdir(input.destination);
|
|
89133
|
+
} catch (error) {
|
|
89134
|
+
if (isNodeErrorWithCode(error, "EEXIST")) return cloneDestinationExistsResult();
|
|
89135
|
+
return {
|
|
89136
|
+
ok: false,
|
|
89137
|
+
code: "GITHUB_CLONE_DESTINATION_CREATE_FAILED",
|
|
89138
|
+
error: "Could not create the clone destination."
|
|
89139
|
+
};
|
|
89140
|
+
}
|
|
89141
|
+
const initFailure = await this.runCloneGitStep(branch === null ? ["init", input.destination] : [
|
|
89119
89142
|
"init",
|
|
89120
89143
|
"-b",
|
|
89121
89144
|
branch,
|
|
89122
89145
|
input.destination
|
|
89123
89146
|
], "GITHUB_CLONE_INIT_FAILED", "Could not initialize the clone destination.");
|
|
89124
|
-
if (initFailure) return initFailure;
|
|
89147
|
+
if (initFailure) return removeFailedCloneDestination(input.destination, initFailure);
|
|
89125
89148
|
const configured = await this.configureProjectGitCredential({
|
|
89126
89149
|
cwd: input.destination,
|
|
89127
89150
|
repoFullName: input.repoFullName,
|
|
89128
89151
|
token: gitToken,
|
|
89129
89152
|
remoteMode: "add"
|
|
89130
89153
|
});
|
|
89131
|
-
if (!configured.ok) return configured;
|
|
89154
|
+
if (!configured.ok) return removeFailedCloneDestination(input.destination, configured);
|
|
89155
|
+
if (branch === null) {
|
|
89156
|
+
const defaultBranch = await this.resolveRemoteDefaultBranch(input.destination);
|
|
89157
|
+
if (typeof defaultBranch !== "string") return removeFailedCloneDestination(input.destination, defaultBranch);
|
|
89158
|
+
branch = defaultBranch;
|
|
89159
|
+
}
|
|
89132
89160
|
const fetchFailure = await this.runCloneGitStep([
|
|
89133
89161
|
"-C",
|
|
89134
89162
|
input.destination,
|
|
@@ -89138,7 +89166,7 @@ var GitHubBroker = class {
|
|
|
89138
89166
|
"origin",
|
|
89139
89167
|
branch
|
|
89140
89168
|
], "GITHUB_CLONE_FETCH_FAILED", "Could not fetch the requested repository branch.", { timeoutMs: 12e4 });
|
|
89141
|
-
if (fetchFailure) return fetchFailure;
|
|
89169
|
+
if (fetchFailure) return removeFailedCloneDestination(input.destination, fetchFailure);
|
|
89142
89170
|
const checkoutFailure = await this.runCloneGitStep([
|
|
89143
89171
|
"-C",
|
|
89144
89172
|
input.destination,
|
|
@@ -89147,7 +89175,7 @@ var GitHubBroker = class {
|
|
|
89147
89175
|
branch,
|
|
89148
89176
|
"FETCH_HEAD"
|
|
89149
89177
|
], "GITHUB_CLONE_CHECKOUT_FAILED", "Could not check out the requested repository branch.");
|
|
89150
|
-
if (checkoutFailure) return checkoutFailure;
|
|
89178
|
+
if (checkoutFailure) return removeFailedCloneDestination(input.destination, checkoutFailure);
|
|
89151
89179
|
return {
|
|
89152
89180
|
ok: true,
|
|
89153
89181
|
data: {
|
|
@@ -89757,7 +89785,7 @@ var GitHubBroker = class {
|
|
|
89757
89785
|
};
|
|
89758
89786
|
}
|
|
89759
89787
|
async resolveInstallationToken(auth, repoFullName) {
|
|
89760
|
-
const runtimeGrant = this.resolveRuntimeGrant();
|
|
89788
|
+
const runtimeGrant = this.resolveRuntimeGrant("github");
|
|
89761
89789
|
if (runtimeGrant) {
|
|
89762
89790
|
const token = await this.fetchRuntimeInstallationToken(runtimeGrant, repoFullName);
|
|
89763
89791
|
if (!token.ok) return token;
|
|
@@ -90142,7 +90170,7 @@ var GitHubBroker = class {
|
|
|
90142
90170
|
repoFullName
|
|
90143
90171
|
};
|
|
90144
90172
|
}
|
|
90145
|
-
resolveRuntimeGrant() {
|
|
90173
|
+
resolveRuntimeGrant(requiredScope = "github") {
|
|
90146
90174
|
if (this.runtimeRole !== "user-vm") return null;
|
|
90147
90175
|
const runtimeId = process.env.FORGE_CMMD_RUNTIME_ID?.trim();
|
|
90148
90176
|
if (!runtimeId) return null;
|
|
@@ -90152,7 +90180,7 @@ var GitHubBroker = class {
|
|
|
90152
90180
|
runtimeId,
|
|
90153
90181
|
machineId: identity.machineId,
|
|
90154
90182
|
credentialEpoch: identity.credentialEpoch,
|
|
90155
|
-
requiredScope
|
|
90183
|
+
requiredScope
|
|
90156
90184
|
});
|
|
90157
90185
|
return authority ? {
|
|
90158
90186
|
runtimeId,
|
|
@@ -90166,8 +90194,8 @@ var GitHubBroker = class {
|
|
|
90166
90194
|
token: legacyToken
|
|
90167
90195
|
} : null;
|
|
90168
90196
|
}
|
|
90169
|
-
runtimeGrantAuthContext() {
|
|
90170
|
-
const grant = this.resolveRuntimeGrant();
|
|
90197
|
+
runtimeGrantAuthContext(requiredScope = "github") {
|
|
90198
|
+
const grant = this.resolveRuntimeGrant(requiredScope);
|
|
90171
90199
|
if (grant === null) return null;
|
|
90172
90200
|
return {
|
|
90173
90201
|
sessionId: grant.sessionId ?? AuthSessionId.make(`cmmd-runtime:${grant.runtimeId}`),
|
|
@@ -90219,13 +90247,21 @@ var GitHubBroker = class {
|
|
|
90219
90247
|
};
|
|
90220
90248
|
}
|
|
90221
90249
|
async fetchRuntimeInstallationToken(grant, repoFullName) {
|
|
90222
|
-
|
|
90250
|
+
return this.fetchRuntimeCredential(grant, {
|
|
90251
|
+
url: makeUrl(this.commandAppUrl, `/api/forge/runtimes/${encodeURIComponent(grant.runtimeId)}/github/installation-token`),
|
|
90252
|
+
requestBody: { repo_full_name: repoFullName },
|
|
90253
|
+
responseField: "token",
|
|
90254
|
+
label: "GitHub installation token"
|
|
90255
|
+
});
|
|
90256
|
+
}
|
|
90257
|
+
async fetchRuntimeCredential(grant, input) {
|
|
90258
|
+
const response = await this.fetchImpl(input.url, {
|
|
90223
90259
|
method: "POST",
|
|
90224
90260
|
headers: {
|
|
90225
90261
|
Authorization: `Bearer ${grant.token}`,
|
|
90226
90262
|
"Content-Type": "application/json"
|
|
90227
90263
|
},
|
|
90228
|
-
body: JSON.stringify(
|
|
90264
|
+
body: JSON.stringify(input.requestBody),
|
|
90229
90265
|
signal: AbortSignal.timeout(GITHUB_BROKER_REQUEST_TIMEOUT_MS)
|
|
90230
90266
|
});
|
|
90231
90267
|
const body = await parseResponseBody(response);
|
|
@@ -90234,10 +90270,10 @@ var GitHubBroker = class {
|
|
|
90234
90270
|
status: response.status,
|
|
90235
90271
|
code: response.status === 401 ? "GITHUB_AUTH_REQUIRED" : "GITHUB_BROKER_REQUEST_FAILED",
|
|
90236
90272
|
...response.status === 401 ? { userActionRequired: "connect_github" } : {},
|
|
90237
|
-
error: errorFromBody(body,
|
|
90273
|
+
error: errorFromBody(body, `${input.label} request failed with status ${response.status}.`),
|
|
90238
90274
|
data: body
|
|
90239
90275
|
};
|
|
90240
|
-
const token = typeof body === "object" && body !== null ? body.
|
|
90276
|
+
const token = typeof body === "object" && body !== null ? body[input.responseField] : null;
|
|
90241
90277
|
if (typeof token !== "string" || token.trim().length === 0) return invalidInstallationTokenResult();
|
|
90242
90278
|
return {
|
|
90243
90279
|
ok: true,
|
|
@@ -90256,6 +90292,25 @@ var GitHubBroker = class {
|
|
|
90256
90292
|
const branch = result.result.stdout.trim();
|
|
90257
90293
|
return branch.length > 0 ? branch : null;
|
|
90258
90294
|
}
|
|
90295
|
+
async resolveRemoteDefaultBranch(cwd) {
|
|
90296
|
+
const result = await this.runGit([
|
|
90297
|
+
"-C",
|
|
90298
|
+
cwd,
|
|
90299
|
+
"ls-remote",
|
|
90300
|
+
"--symref",
|
|
90301
|
+
"origin",
|
|
90302
|
+
"HEAD"
|
|
90303
|
+
], { allowNonZeroExit: true });
|
|
90304
|
+
if (!isGitRunResult(result)) return result;
|
|
90305
|
+
if (result.result.code !== 0) return gitCommandFailure("GITHUB_DEFAULT_BRANCH_LOOKUP_FAILED", result.result.stderr, "Could not determine the repository default branch.");
|
|
90306
|
+
const branch = /^ref:\s+refs\/heads\/([^\s]+)\s+HEAD$/m.exec(result.result.stdout)?.[1];
|
|
90307
|
+
if (branch === void 0) return {
|
|
90308
|
+
ok: false,
|
|
90309
|
+
code: "GITHUB_DEFAULT_BRANCH_RESPONSE_INVALID",
|
|
90310
|
+
error: "GitHub did not return a valid default branch for the repository."
|
|
90311
|
+
};
|
|
90312
|
+
return validateGitBranchName(branch) ?? branch;
|
|
90313
|
+
}
|
|
90259
90314
|
};
|
|
90260
90315
|
function isCmmdCloudRuntimeModeEnv() {
|
|
90261
90316
|
return process.env.FORGE_CMMD_RUNTIME_MODE === "true" || process.env.FORGE_CMMD_RUNTIME_MODE === "1";
|
|
@@ -90340,20 +90395,40 @@ function validateCloneDestination(destination) {
|
|
|
90340
90395
|
code: "GITHUB_CLONE_DESTINATION_INVALID",
|
|
90341
90396
|
error: "An absolute clone destination is required."
|
|
90342
90397
|
};
|
|
90343
|
-
if (existsSync(destination)) return
|
|
90398
|
+
if (existsSync(destination)) return cloneDestinationExistsResult();
|
|
90399
|
+
return null;
|
|
90400
|
+
}
|
|
90401
|
+
function cloneDestinationExistsResult() {
|
|
90402
|
+
return {
|
|
90344
90403
|
ok: false,
|
|
90345
90404
|
code: "GITHUB_CLONE_DESTINATION_EXISTS",
|
|
90346
90405
|
error: "Clone destination already exists; choose a new empty path."
|
|
90347
90406
|
};
|
|
90348
|
-
|
|
90407
|
+
}
|
|
90408
|
+
function isNodeErrorWithCode(error, code) {
|
|
90409
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
90410
|
+
}
|
|
90411
|
+
async function removeFailedCloneDestination(destination, failure) {
|
|
90412
|
+
try {
|
|
90413
|
+
await rm(destination, {
|
|
90414
|
+
recursive: true,
|
|
90415
|
+
force: true
|
|
90416
|
+
});
|
|
90417
|
+
return failure;
|
|
90418
|
+
} catch {
|
|
90419
|
+
return {
|
|
90420
|
+
...failure,
|
|
90421
|
+
error: `${failure.error ?? "Clone failed."} The incomplete clone destination could not be removed.`
|
|
90422
|
+
};
|
|
90423
|
+
}
|
|
90349
90424
|
}
|
|
90350
90425
|
function validateCloneInput(input) {
|
|
90351
90426
|
const repoFullNameValidation = validateRepoFullName(input.repoFullName);
|
|
90352
90427
|
if (repoFullNameValidation) return repoFullNameValidation;
|
|
90353
90428
|
const destinationValidation = validateCloneDestination(input.destination);
|
|
90354
90429
|
if (destinationValidation) return destinationValidation;
|
|
90355
|
-
const branch = input.branch?.trim() ||
|
|
90356
|
-
return validateGitBranchName(branch) ?? { branch };
|
|
90430
|
+
const branch = input.branch?.trim() || null;
|
|
90431
|
+
return branch === null ? { branch } : validateGitBranchName(branch) ?? { branch };
|
|
90357
90432
|
}
|
|
90358
90433
|
function validateGitBranchName(branch) {
|
|
90359
90434
|
if (branch.length === 0 || branch.startsWith("-") || Array.from(branch).some((character) => {
|
|
@@ -93518,6 +93593,17 @@ const admitNormalizedDispatchCommand = (command, admit) => uninterruptibleMask$1
|
|
|
93518
93593
|
//#region src/orchestration/bootstrapCommandCoordinator.ts
|
|
93519
93594
|
const MAX_COMPLETED_COMMANDS_PER_ENGINE = 256;
|
|
93520
93595
|
const commandsByEngine = /* @__PURE__ */ new WeakMap();
|
|
93596
|
+
const sealBootstrapCommand = (engine, commandId) => {
|
|
93597
|
+
const entry = commandsByEngine.get(engine)?.get(commandId);
|
|
93598
|
+
if (entry) entry.cancellable = false;
|
|
93599
|
+
};
|
|
93600
|
+
const cancelBootstrapCommand = (engine, threadId) => promise(async () => {
|
|
93601
|
+
const entry = [...commandsByEngine.get(engine)?.values() ?? []].find((candidate) => candidate.threadId === threadId && !candidate.completed && candidate.cancellable);
|
|
93602
|
+
if (!entry) return false;
|
|
93603
|
+
entry.controller.abort();
|
|
93604
|
+
await entry.promise.catch(() => void 0);
|
|
93605
|
+
return true;
|
|
93606
|
+
});
|
|
93521
93607
|
const toBootstrapError = (error) => is$1(OrchestrationDispatchCommandError)(error) ? error : new OrchestrationDispatchCommandError({
|
|
93522
93608
|
message: error instanceof Error ? error.message : "Bootstrap command failed.",
|
|
93523
93609
|
cause: error
|
|
@@ -93537,7 +93623,7 @@ const pruneCompletedCommands = (commands) => {
|
|
|
93537
93623
|
* the registry to one server runtime, so reconnects share work while separate
|
|
93538
93624
|
* runtimes remain isolated.
|
|
93539
93625
|
*/
|
|
93540
|
-
const runBootstrapCommand = (engine, commandId, bootstrapEffect) => {
|
|
93626
|
+
const runBootstrapCommand = (engine, commandId, bootstrapEffect, threadId) => {
|
|
93541
93627
|
let commands = commandsByEngine.get(engine);
|
|
93542
93628
|
if (commands === void 0) {
|
|
93543
93629
|
commands = /* @__PURE__ */ new Map();
|
|
@@ -93550,16 +93636,21 @@ const runBootstrapCommand = (engine, commandId, bootstrapEffect) => {
|
|
|
93550
93636
|
});
|
|
93551
93637
|
pruneCompletedCommands(commands);
|
|
93552
93638
|
let entry;
|
|
93553
|
-
const
|
|
93639
|
+
const controller = new AbortController();
|
|
93640
|
+
const promise = Promise.resolve().then(() => runPromise(bootstrapEffect, { signal: controller.signal })).then((result) => {
|
|
93554
93641
|
entry.completed = true;
|
|
93555
93642
|
return result;
|
|
93556
93643
|
}, (error) => {
|
|
93557
|
-
|
|
93644
|
+
entry.completed = true;
|
|
93645
|
+
if (!controller.signal.aborted) commands.delete(commandId);
|
|
93558
93646
|
throw error;
|
|
93559
93647
|
});
|
|
93560
93648
|
entry = {
|
|
93561
93649
|
promise,
|
|
93562
|
-
completed: false
|
|
93650
|
+
completed: false,
|
|
93651
|
+
threadId,
|
|
93652
|
+
controller,
|
|
93653
|
+
cancellable: true
|
|
93563
93654
|
};
|
|
93564
93655
|
commands.set(commandId, entry);
|
|
93565
93656
|
return tryPromise({
|
|
@@ -93569,6 +93660,10 @@ const runBootstrapCommand = (engine, commandId, bootstrapEffect) => {
|
|
|
93569
93660
|
};
|
|
93570
93661
|
//#endregion
|
|
93571
93662
|
//#region src/orchestration/bootstrapDispatch.ts
|
|
93663
|
+
const interruptBootstrapTurnStart = (engine, command) => gen(function* () {
|
|
93664
|
+
if (yield* cancelBootstrapCommand(engine, command.threadId)) return { sequence: (yield* engine.getReadModel()).snapshotSequence };
|
|
93665
|
+
return yield* engine.dispatch(command);
|
|
93666
|
+
});
|
|
93572
93667
|
const MAX_BOOTSTRAP_OUTPUT_LINE_LENGTH = 1e3;
|
|
93573
93668
|
const toBootstrapDispatchCommandCauseError = (cause) => {
|
|
93574
93669
|
const error = squash(cause);
|
|
@@ -93655,6 +93750,7 @@ const prepareBootstrapWorktree = (input) => gen(function* () {
|
|
|
93655
93750
|
const requestedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
93656
93751
|
const baseBranchLabel = bootstrapWorktree.baseBranch ?? "<default>";
|
|
93657
93752
|
const requestedPayload = {
|
|
93753
|
+
turnRequestedAt: input.command.createdAt,
|
|
93658
93754
|
projectCwd: bootstrapWorktree.projectCwd,
|
|
93659
93755
|
baseBranch: bootstrapWorktree.baseBranch,
|
|
93660
93756
|
branch: bootstrapWorktree.branch,
|
|
@@ -93675,6 +93771,16 @@ const prepareBootstrapWorktree = (input) => gen(function* () {
|
|
|
93675
93771
|
branch: bootstrapWorktree.baseBranch,
|
|
93676
93772
|
newBranch: bootstrapWorktree.branch,
|
|
93677
93773
|
path: null,
|
|
93774
|
+
onStage: (update) => appendWorktreeActivity({
|
|
93775
|
+
orchestrationEngine: input.orchestrationEngine,
|
|
93776
|
+
threadId: input.command.threadId,
|
|
93777
|
+
commandId: CommandId.make(`server:worktree-stage:${input.command.commandId}:${crypto.randomUUID()}`),
|
|
93778
|
+
kind: "worktree.stage",
|
|
93779
|
+
summary: "Preparing worktree",
|
|
93780
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
93781
|
+
payload: update,
|
|
93782
|
+
tone: "info"
|
|
93783
|
+
}).pipe(asVoid, ignore),
|
|
93678
93784
|
progress: {
|
|
93679
93785
|
onStdoutLine: (line) => {
|
|
93680
93786
|
const detail = truncateBootstrapOutputLine(line);
|
|
@@ -93714,6 +93820,7 @@ const prepareBootstrapWorktree = (input) => gen(function* () {
|
|
|
93714
93820
|
}
|
|
93715
93821
|
}
|
|
93716
93822
|
}).pipe(catchCause((cause) => {
|
|
93823
|
+
if (hasInterruptsOnly(cause)) return failCause$1(cause);
|
|
93717
93824
|
const error = squash(cause);
|
|
93718
93825
|
const detail = error instanceof Error ? error.message : "Unknown worktree failure.";
|
|
93719
93826
|
return appendWorktreeActivity({
|
|
@@ -93840,7 +93947,16 @@ const dispatchBootstrapTurnStart = (input, command) => gen(function* () {
|
|
|
93840
93947
|
worktreePath
|
|
93841
93948
|
}),
|
|
93842
93949
|
onSuccess: (setupResult) => {
|
|
93843
|
-
if (setupResult.status !== "started") return
|
|
93950
|
+
if (setupResult.status !== "started") return appendSetupScriptActivity({
|
|
93951
|
+
orchestrationEngine,
|
|
93952
|
+
threadId: command.threadId,
|
|
93953
|
+
commandId: bootstrapCommandId(command, "setup-script-skipped"),
|
|
93954
|
+
kind: "setup-script.skipped",
|
|
93955
|
+
summary: "No setup script configured",
|
|
93956
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
93957
|
+
payload: {},
|
|
93958
|
+
tone: "info"
|
|
93959
|
+
}).pipe(asVoid, ignore);
|
|
93844
93960
|
return recordSetupScriptStarted({
|
|
93845
93961
|
requestedAt,
|
|
93846
93962
|
worktreePath,
|
|
@@ -93870,13 +93986,33 @@ const dispatchBootstrapTurnStart = (input, command) => gen(function* () {
|
|
|
93870
93986
|
targetProjectCwd = preparedWorktree.projectCwd;
|
|
93871
93987
|
}
|
|
93872
93988
|
yield* runSetupProgram();
|
|
93989
|
+
if (bootstrap?.prepareWorktree) yield* appendWorktreeActivity({
|
|
93990
|
+
orchestrationEngine,
|
|
93991
|
+
threadId: command.threadId,
|
|
93992
|
+
commandId: bootstrapCommandId(command, "launch-agent-starting"),
|
|
93993
|
+
kind: "launch.agent-starting",
|
|
93994
|
+
summary: "Starting agent",
|
|
93995
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
93996
|
+
payload: { setupRequested: bootstrap.runSetupScript === true },
|
|
93997
|
+
tone: "info"
|
|
93998
|
+
}).pipe(ignore);
|
|
93999
|
+
sealBootstrapCommand(orchestrationEngine, command.commandId);
|
|
93873
94000
|
return yield* orchestrationEngine.dispatch(finalTurnStartCommand);
|
|
93874
94001
|
});
|
|
93875
|
-
return yield* runBootstrapCommand(orchestrationEngine, command.commandId, bootstrapProgram.pipe(
|
|
94002
|
+
return yield* runBootstrapCommand(orchestrationEngine, command.commandId, bootstrapProgram.pipe(onInterrupt(() => appendWorktreeActivity({
|
|
94003
|
+
orchestrationEngine,
|
|
94004
|
+
threadId: command.threadId,
|
|
94005
|
+
commandId: bootstrapCommandId(command, "launch-cancelled"),
|
|
94006
|
+
kind: "launch.cancelled",
|
|
94007
|
+
summary: "Launch cancelled",
|
|
94008
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
94009
|
+
payload: {},
|
|
94010
|
+
tone: "info"
|
|
94011
|
+
}).pipe(ignore)), catchCause((cause) => {
|
|
93876
94012
|
const dispatchError = toBootstrapDispatchCommandCauseError(cause);
|
|
93877
94013
|
if (hasInterruptsOnly(cause)) return fail(dispatchError);
|
|
93878
94014
|
return cleanupCreatedThread().pipe(flatMap(() => fail(dispatchError)));
|
|
93879
|
-
})));
|
|
94015
|
+
})), command.threadId);
|
|
93880
94016
|
});
|
|
93881
94017
|
//#endregion
|
|
93882
94018
|
//#region src/orchestration/Services/OrchestrationEngine.ts
|
|
@@ -100555,6 +100691,7 @@ function emptyConfig(source, path) {
|
|
|
100555
100691
|
terminals: [],
|
|
100556
100692
|
systemPackages: [],
|
|
100557
100693
|
secrets: [],
|
|
100694
|
+
repositoryDependencies: [],
|
|
100558
100695
|
issues: []
|
|
100559
100696
|
};
|
|
100560
100697
|
}
|
|
@@ -100640,6 +100777,7 @@ function readConfigFile(source, path) {
|
|
|
100640
100777
|
terminals: terminalsFromValue(parsed.terminals),
|
|
100641
100778
|
systemPackages: stringArray(parsed.systemPackages ?? parsed.aptPackages ?? parsed.packages),
|
|
100642
100779
|
secrets: stringArray(parsed.secrets ?? parsed.envSecrets),
|
|
100780
|
+
repositoryDependencies: stringArray(parsed.repositoryDependencies),
|
|
100643
100781
|
issues: []
|
|
100644
100782
|
};
|
|
100645
100783
|
}
|
|
@@ -101052,6 +101190,7 @@ const EMPTY_WORKSPACE_ENVIRONMENT_CONFIG = {
|
|
|
101052
101190
|
terminals: [],
|
|
101053
101191
|
systemPackages: [],
|
|
101054
101192
|
secrets: [],
|
|
101193
|
+
repositoryDependencies: [],
|
|
101055
101194
|
issues: []
|
|
101056
101195
|
};
|
|
101057
101196
|
function buildCwdCheck(cwdExists) {
|
|
@@ -105854,7 +105993,7 @@ const makeWsRpcLayer = (currentSessionId, currentUserId) => WsRpcGroup.toLayer(g
|
|
|
105854
105993
|
git,
|
|
105855
105994
|
gitStatusBroadcaster,
|
|
105856
105995
|
projectSetupScriptRunner
|
|
105857
|
-
}, normalizedCommand) : orchestrationEngine.dispatch(normalizedCommand).pipe(mapError((cause) => toDispatchCommandError(cause, "Failed to dispatch orchestration command")));
|
|
105996
|
+
}, normalizedCommand) : (normalizedCommand.type === "thread.turn.interrupt" ? interruptBootstrapTurnStart(orchestrationEngine, normalizedCommand) : orchestrationEngine.dispatch(normalizedCommand)).pipe(mapError((cause) => toDispatchCommandError(cause, "Failed to dispatch orchestration command")));
|
|
105858
105997
|
return startup.enqueueCommand(dispatchEffect).pipe(mapError((cause) => toDispatchCommandError(cause, "Failed to dispatch orchestration command")));
|
|
105859
105998
|
};
|
|
105860
105999
|
const loadServerConfig = gen(function* () {
|
|
@@ -151203,6 +151342,86 @@ async function attestCodexLocalAccountIdentity(input) {
|
|
|
151203
151342
|
return identity;
|
|
151204
151343
|
}
|
|
151205
151344
|
//#endregion
|
|
151345
|
+
//#region src/workspace/workspaceRepositoryDependencies.ts
|
|
151346
|
+
function repositoryFullName(value) {
|
|
151347
|
+
return value.trim().match(/^(?:https?:\/\/)?github\.com\/([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+?)(?:\.git)?\/?$/i)?.[1] ?? null;
|
|
151348
|
+
}
|
|
151349
|
+
function dependencyDestination(cloudProjectsRoot, repoFullName) {
|
|
151350
|
+
const root = resolve(cloudProjectsRoot);
|
|
151351
|
+
const destination = resolve(join(root, basename(repoFullName)));
|
|
151352
|
+
const pathFromRoot = relative(root, destination);
|
|
151353
|
+
if (pathFromRoot.startsWith("..") || pathFromRoot === "") throw new Error(`Repository dependency ${repoFullName} has an unsafe destination.`);
|
|
151354
|
+
return destination;
|
|
151355
|
+
}
|
|
151356
|
+
async function readOriginFromGit(destination) {
|
|
151357
|
+
const result = await runProcess("git", [
|
|
151358
|
+
"-C",
|
|
151359
|
+
destination,
|
|
151360
|
+
"remote",
|
|
151361
|
+
"get-url",
|
|
151362
|
+
"origin"
|
|
151363
|
+
], {
|
|
151364
|
+
allowNonZeroExit: true,
|
|
151365
|
+
timeoutMs: 1e4
|
|
151366
|
+
});
|
|
151367
|
+
return result.code === 0 ? result.stdout.trim() : null;
|
|
151368
|
+
}
|
|
151369
|
+
function resolveRepositoryDependencies(declarations, cloudProjectsRoot) {
|
|
151370
|
+
const destinations = /* @__PURE__ */ new Set();
|
|
151371
|
+
return declarations.map((declaration) => {
|
|
151372
|
+
const repoFullName = repositoryFullName(declaration);
|
|
151373
|
+
if (repoFullName === null) throw new Error(`Unsupported repository dependency: ${declaration}`);
|
|
151374
|
+
const destination = dependencyDestination(cloudProjectsRoot, repoFullName);
|
|
151375
|
+
if (destinations.has(destination)) throw new Error(`Repository dependencies collide at ${destination}.`);
|
|
151376
|
+
destinations.add(destination);
|
|
151377
|
+
return {
|
|
151378
|
+
repoFullName,
|
|
151379
|
+
destination
|
|
151380
|
+
};
|
|
151381
|
+
});
|
|
151382
|
+
}
|
|
151383
|
+
async function prepareRepositoryDependency(input) {
|
|
151384
|
+
const { repoFullName, destination } = input.dependency;
|
|
151385
|
+
if (existsSync(destination)) {
|
|
151386
|
+
const origin = await input.readOrigin(destination);
|
|
151387
|
+
const existingRepo = origin === null ? null : parseRepoFullNameFromRemoteUrl(origin);
|
|
151388
|
+
if (existingRepo?.toLowerCase() !== repoFullName.toLowerCase()) throw new Error(`Repository dependency destination ${destination} contains ${existingRepo ?? "no GitHub repository"} instead of ${repoFullName}.`);
|
|
151389
|
+
return {
|
|
151390
|
+
repoFullName,
|
|
151391
|
+
destination,
|
|
151392
|
+
outcome: "existing"
|
|
151393
|
+
};
|
|
151394
|
+
}
|
|
151395
|
+
const result = await input.broker.cloneRepository(input.auth, {
|
|
151396
|
+
repoFullName,
|
|
151397
|
+
destination
|
|
151398
|
+
});
|
|
151399
|
+
if (!result.ok) throw new Error(`Could not prepare repository dependency ${repoFullName}: ${result.error ?? result.code ?? "clone failed"}`);
|
|
151400
|
+
return {
|
|
151401
|
+
repoFullName,
|
|
151402
|
+
destination,
|
|
151403
|
+
outcome: "cloned"
|
|
151404
|
+
};
|
|
151405
|
+
}
|
|
151406
|
+
async function prepareWorkspaceRepositoryDependencies(input) {
|
|
151407
|
+
if (!input.runtimeMode) return [];
|
|
151408
|
+
const dependencies = resolveWorkspaceEnvironmentConfig(input.cwd).repositoryDependencies;
|
|
151409
|
+
if (dependencies.length === 0) return [];
|
|
151410
|
+
const broker = input.broker ?? new GitHubBroker();
|
|
151411
|
+
const auth = broker.runtimeGrantAuthContext("github");
|
|
151412
|
+
if (auth === null) throw new Error("Repository dependencies require an exact scoped runtime GitHub grant.");
|
|
151413
|
+
const readOrigin = input.readOrigin ?? readOriginFromGit;
|
|
151414
|
+
const resolved = resolveRepositoryDependencies(dependencies, input.cloudProjectsRoot);
|
|
151415
|
+
const prepared = [];
|
|
151416
|
+
for (const dependency of resolved) prepared.push(await prepareRepositoryDependency({
|
|
151417
|
+
dependency,
|
|
151418
|
+
broker,
|
|
151419
|
+
auth,
|
|
151420
|
+
readOrigin
|
|
151421
|
+
}));
|
|
151422
|
+
return prepared;
|
|
151423
|
+
}
|
|
151424
|
+
//#endregion
|
|
151206
151425
|
//#region src/codexAppServerManager.ts
|
|
151207
151426
|
const CODEX_LOGIN_STATUS_TIMEOUT_MS = 5e3;
|
|
151208
151427
|
const CODEX_SKILLS_LIST_TIMEOUT_MS = 4e3;
|
|
@@ -151537,6 +151756,11 @@ var CodexAppServerManager = class extends EventEmitter$1 {
|
|
|
151537
151756
|
let context;
|
|
151538
151757
|
try {
|
|
151539
151758
|
const resolvedCwd = input.cwd ?? process.cwd();
|
|
151759
|
+
await prepareWorkspaceRepositoryDependencies({
|
|
151760
|
+
cwd: resolvedCwd,
|
|
151761
|
+
cloudProjectsRoot: process.env.FORGE_CLOUD_PROJECTS_ROOT?.trim() || "/projects",
|
|
151762
|
+
runtimeMode: process.env.FORGE_CMMD_RUNTIME_MODE === "true"
|
|
151763
|
+
});
|
|
151540
151764
|
let workspacePreflightReport = runWorkspaceEnvironmentPreflight({
|
|
151541
151765
|
cwd: resolvedCwd,
|
|
151542
151766
|
env: process.env
|
|
@@ -216617,6 +216841,19 @@ const makeClaudeAdapter = fn$1("makeClaudeAdapter")(function* (options) {
|
|
|
216617
216841
|
const resumeState = readClaudeResumeState(input.resumeCursor);
|
|
216618
216842
|
const threadId = input.threadId;
|
|
216619
216843
|
const { existingResumeSessionId, newSessionId, sessionId } = yield* resolveClaudeStartSessionIds(resumeState);
|
|
216844
|
+
const workspaceCwd = input.cwd;
|
|
216845
|
+
if (workspaceCwd) yield* tryPromise({
|
|
216846
|
+
try: () => prepareWorkspaceRepositoryDependencies({
|
|
216847
|
+
cwd: workspaceCwd,
|
|
216848
|
+
cloudProjectsRoot: serverConfig.cloudProjectsRoot ?? "/projects",
|
|
216849
|
+
runtimeMode: serverConfig.forgeCmmdRuntimeMode === true
|
|
216850
|
+
}),
|
|
216851
|
+
catch: (cause) => new ProviderAdapterValidationError({
|
|
216852
|
+
provider: PROVIDER$11,
|
|
216853
|
+
operation: "startSession",
|
|
216854
|
+
issue: cause instanceof Error ? cause.message : "Could not prepare declared repository dependencies."
|
|
216855
|
+
})
|
|
216856
|
+
});
|
|
216620
216857
|
const runtimeContext = yield* context();
|
|
216621
216858
|
const runFork = runForkWith(runtimeContext);
|
|
216622
216859
|
const runPromise = runPromiseWith(runtimeContext);
|
|
@@ -232923,12 +233160,12 @@ const collectOutput = fn$1("collectOutput")(function* (input, stream, maxOutputB
|
|
|
232923
233160
|
let lineBuffer = "";
|
|
232924
233161
|
let truncated = false;
|
|
232925
233162
|
const emitCompleteLines = fn$1("emitCompleteLines")(function* (flush) {
|
|
232926
|
-
let newlineIndex = lineBuffer.
|
|
233163
|
+
let newlineIndex = lineBuffer.search(/[\r\n]/);
|
|
232927
233164
|
while (newlineIndex >= 0) {
|
|
232928
233165
|
const line = lineBuffer.slice(0, newlineIndex).replace(/\r$/, "");
|
|
232929
233166
|
lineBuffer = lineBuffer.slice(newlineIndex + 1);
|
|
232930
233167
|
if (line.length > 0 && onLine) yield* onLine(line);
|
|
232931
|
-
newlineIndex = lineBuffer.
|
|
233168
|
+
newlineIndex = lineBuffer.search(/[\r\n]/);
|
|
232932
233169
|
}
|
|
232933
233170
|
if (flush) {
|
|
232934
233171
|
const trailing = lineBuffer.replace(/\r$/, "");
|
|
@@ -233076,6 +233313,7 @@ const GitCoreLive = effect(GitCore, fn$1("makeGitCore")(function* (options) {
|
|
|
233076
233313
|
operation,
|
|
233077
233314
|
cwd,
|
|
233078
233315
|
args,
|
|
233316
|
+
...options.env ? { env: options.env } : {},
|
|
233079
233317
|
...options.stdin !== void 0 ? { stdin: options.stdin } : {},
|
|
233080
233318
|
allowNonZeroExit: true,
|
|
233081
233319
|
...options.timeoutMs !== void 0 ? { timeoutMs: options.timeoutMs } : {},
|
|
@@ -233797,12 +234035,19 @@ const GitCoreLive = effect(GitCore, fn$1("makeGitCore")(function* (options) {
|
|
|
233797
234035
|
};
|
|
233798
234036
|
});
|
|
233799
234037
|
const createWorktree = fn$1("createWorktree")(function* (input) {
|
|
234038
|
+
const report = (stage, status, detail) => input.onStage?.({
|
|
234039
|
+
stage,
|
|
234040
|
+
status,
|
|
234041
|
+
...detail ? { detail } : {}
|
|
234042
|
+
}) ?? void_$1;
|
|
234043
|
+
yield* report("resolve", "running");
|
|
233800
234044
|
const base = input.branch ?? (yield* resolveDefaultBaseBranch(input.cwd));
|
|
233801
234045
|
const startPoint = yield* resolveWorktreeStartPoint({
|
|
233802
234046
|
cwd: input.cwd,
|
|
233803
234047
|
base,
|
|
233804
234048
|
creatingNewBranch: input.newBranch !== void 0
|
|
233805
234049
|
});
|
|
234050
|
+
yield* report("resolve", "done", startPoint);
|
|
233806
234051
|
const targetBranch = input.newBranch ?? base;
|
|
233807
234052
|
const sanitizedBranch = targetBranch.replace(/\//g, "-");
|
|
233808
234053
|
const repoName = path$10.basename(input.cwd);
|
|
@@ -233814,7 +234059,10 @@ const GitCoreLive = effect(GitCore, fn$1("makeGitCore")(function* (options) {
|
|
|
233814
234059
|
limit: 200
|
|
233815
234060
|
})).branches.find((branch) => branch.isRemote !== true && branch.name === targetBranch && branch.worktreePath !== null && path.resolve(branch.worktreePath) === canonicalWorktreePath);
|
|
233816
234061
|
if (existingBranch?.worktreePath) {
|
|
234062
|
+
yield* report("checkout", "skipped", "Existing worktree");
|
|
234063
|
+
yield* report("dependencies", "running");
|
|
233817
234064
|
yield* setupSharedWorktreeDependencies(input.cwd, existingBranch.worktreePath);
|
|
234065
|
+
yield* report("dependencies", "done");
|
|
233818
234066
|
return { worktree: {
|
|
233819
234067
|
path: worktreePath,
|
|
233820
234068
|
branch: targetBranch
|
|
@@ -233833,11 +234081,19 @@ const GitCoreLive = effect(GitCore, fn$1("makeGitCore")(function* (options) {
|
|
|
233833
234081
|
worktreePath,
|
|
233834
234082
|
startPoint
|
|
233835
234083
|
];
|
|
234084
|
+
yield* report("checkout", "running");
|
|
233836
234085
|
yield* executeGit("GitCore.createWorktree", input.cwd, args, {
|
|
233837
234086
|
fallbackErrorMessage: "git worktree add failed",
|
|
234087
|
+
env: {
|
|
234088
|
+
GIT_PROGRESS_DELAY: "0",
|
|
234089
|
+
LC_ALL: "C"
|
|
234090
|
+
},
|
|
233838
234091
|
...input.progress ? { progress: input.progress } : {}
|
|
233839
234092
|
});
|
|
234093
|
+
yield* report("checkout", "done");
|
|
234094
|
+
yield* report("dependencies", "running");
|
|
233840
234095
|
yield* setupSharedWorktreeDependencies(input.cwd, worktreePath);
|
|
234096
|
+
yield* report("dependencies", "done");
|
|
233841
234097
|
return { worktree: {
|
|
233842
234098
|
path: worktreePath,
|
|
233843
234099
|
branch: targetBranch
|
|
@@ -296549,7 +296805,7 @@ function resolveBuildCommitFromEnv(env) {
|
|
|
296549
296805
|
* environment descriptor down instead of reporting an honest "unknown".
|
|
296550
296806
|
*/
|
|
296551
296807
|
function readBakedBuildCommit() {
|
|
296552
|
-
return "
|
|
296808
|
+
return "d9a524e82e63dd163e8f06083c14b5913b6fdf88";
|
|
296553
296809
|
}
|
|
296554
296810
|
async function resolveServerBuildCommit(input) {
|
|
296555
296811
|
if (isFullCommitSha(input.baked)) return input.baked;
|
|
@@ -298361,6 +298617,10 @@ const AuthSessionRepositoryLive = effect(AuthSessionRepository, gen(function* ()
|
|
|
298361
298617
|
const SIGNING_SECRET_NAME = "server-signing-key";
|
|
298362
298618
|
const DEFAULT_SESSION_TTL = days(30);
|
|
298363
298619
|
const DEFAULT_WEBSOCKET_TOKEN_TTL = minutes(5);
|
|
298620
|
+
const toSessionCredentialError = (message) => (cause) => new SessionCredentialError({
|
|
298621
|
+
message,
|
|
298622
|
+
cause
|
|
298623
|
+
});
|
|
298364
298624
|
const SessionClaims = Struct({
|
|
298365
298625
|
v: Literal(1),
|
|
298366
298626
|
kind: Literal("session"),
|
|
@@ -298417,10 +298677,6 @@ const SessionCredentialServiceLive = effect(SessionCredentialService, gen(functi
|
|
|
298417
298677
|
port: serverConfig.port,
|
|
298418
298678
|
host: serverConfig.host
|
|
298419
298679
|
});
|
|
298420
|
-
const toSessionCredentialError = (message) => (cause) => new SessionCredentialError({
|
|
298421
|
-
message,
|
|
298422
|
-
cause
|
|
298423
|
-
});
|
|
298424
298680
|
const emitUpsert = (clientSession) => publish(changesPubSub, {
|
|
298425
298681
|
type: "clientUpserted",
|
|
298426
298682
|
clientSession
|
|
@@ -298581,15 +298837,28 @@ const SessionCredentialServiceLive = effect(SessionCredentialService, gen(functi
|
|
|
298581
298837
|
if (isSome(row)) {
|
|
298582
298838
|
if (row.value.revokedAt !== null) return yield* new SessionCredentialError({ message: "Websocket session revoked." });
|
|
298583
298839
|
if (row.value.expiresAt.epochMilliseconds <= now) return yield* new SessionCredentialError({ message: "Websocket session expired." });
|
|
298584
|
-
} else
|
|
298840
|
+
} else {
|
|
298841
|
+
const cloudOwnerSession = serverConfig.forgeCloudShellMode === true && claims.method === "proxy-asserted" && forgeCloudOwnerSessionExpiresAt(claims.sid) !== null;
|
|
298842
|
+
if (cloudOwnerSession && isExpiredForgeCloudOwnerSession(claims.sid, now)) return yield* new SessionCredentialError({ message: "Websocket session expired." });
|
|
298843
|
+
if (statelessCookieSessions && (claims.method === "browser-session-cookie" || cloudOwnerSession)) return {
|
|
298844
|
+
sessionId: claims.sid,
|
|
298845
|
+
token,
|
|
298846
|
+
method: claims.method,
|
|
298847
|
+
client: createDefaultClientMetadata(),
|
|
298848
|
+
expiresAt: makeUnsafe$5(claims.exp),
|
|
298849
|
+
subject: claims.sub,
|
|
298850
|
+
role: claims.role
|
|
298851
|
+
};
|
|
298852
|
+
return yield* new SessionCredentialError({ message: "Unknown websocket session." });
|
|
298853
|
+
}
|
|
298585
298854
|
return {
|
|
298586
298855
|
sessionId: claims.sid,
|
|
298587
298856
|
token,
|
|
298588
|
-
method:
|
|
298589
|
-
client:
|
|
298590
|
-
expiresAt:
|
|
298591
|
-
subject:
|
|
298592
|
-
role:
|
|
298857
|
+
method: row.value.method,
|
|
298858
|
+
client: toClientMetadata(row.value.client),
|
|
298859
|
+
expiresAt: row.value.expiresAt,
|
|
298860
|
+
subject: row.value.subject,
|
|
298861
|
+
role: row.value.role
|
|
298593
298862
|
};
|
|
298594
298863
|
}).pipe(mapError((cause) => cause instanceof SessionCredentialError ? cause : new SessionCredentialError({
|
|
298595
298864
|
message: "Failed to verify websocket token.",
|
|
@@ -298866,6 +299135,18 @@ function verifyForgeCloudOwnerCallbackAssertion(assertion, config) {
|
|
|
298866
299135
|
//#endregion
|
|
298867
299136
|
//#region src/auth/Layers/ServerAuth.ts
|
|
298868
299137
|
const AUTHORIZATION_PREFIX = "Bearer ";
|
|
299138
|
+
function classifyWebSocketTokenFailure(cause) {
|
|
299139
|
+
switch (cause.message) {
|
|
299140
|
+
case "Malformed websocket token.": return "malformed";
|
|
299141
|
+
case "Invalid websocket token signature.": return "invalid_signature";
|
|
299142
|
+
case "Invalid websocket token payload.": return "invalid_payload";
|
|
299143
|
+
case "Websocket token expired.": return "expired_token";
|
|
299144
|
+
case "Websocket session revoked.": return "revoked_parent_session";
|
|
299145
|
+
case "Websocket session expired.": return "expired_parent_session";
|
|
299146
|
+
case "Unknown websocket session.": return "unknown_parent_session";
|
|
299147
|
+
default: return "verification_failed";
|
|
299148
|
+
}
|
|
299149
|
+
}
|
|
298869
299150
|
function toBootstrapExchangeAuthError(cause) {
|
|
298870
299151
|
if (cause.status === 500) return new AuthError({
|
|
298871
299152
|
message: "Failed to validate bootstrap credential.",
|
|
@@ -299168,7 +299449,6 @@ const ServerAuthLive = effect(ServerAuth, gen(function* () {
|
|
|
299168
299449
|
expiresAt: toUtc(issued.expiresAt)
|
|
299169
299450
|
})));
|
|
299170
299451
|
const authenticateWebSocketUpgrade = (request) => gen(function* () {
|
|
299171
|
-
if (serverConfig.forgeCloudShellMode === true) return yield* authenticateRequest(request);
|
|
299172
299452
|
if (serverConfig.forgeCmmdRuntimeMode) {
|
|
299173
299453
|
if (serverConfig.forgeCmmdAuthRuntime) {
|
|
299174
299454
|
const authConfig = readCmmdAuthRuntimeConfig(serverConfig);
|
|
@@ -299225,7 +299505,7 @@ const ServerAuthLive = effect(ServerAuth, gen(function* () {
|
|
|
299225
299505
|
const requestUrl = toURL(request);
|
|
299226
299506
|
if (isSome(requestUrl)) {
|
|
299227
299507
|
const websocketToken = readWebSocketUpgradeToken(requestUrl.value.searchParams);
|
|
299228
|
-
if (websocketToken) return yield* sessions.verifyWebSocketToken(websocketToken).pipe(map$3((session) => ({
|
|
299508
|
+
if (websocketToken) return yield* sessions.verifyWebSocketToken(websocketToken).pipe(tapError((cause) => logWarning$1("Rejected websocket token.").pipe(annotateLogs({ category: classifyWebSocketTokenFailure(cause) }))), map$3((session) => ({
|
|
299229
299509
|
sessionId: session.sessionId,
|
|
299230
299510
|
subject: session.subject,
|
|
299231
299511
|
method: session.method,
|
|
@@ -305264,7 +305544,7 @@ const orchestrationDispatchRouteLayer = add$1("POST", "/api/orchestration/dispat
|
|
|
305264
305544
|
}).pipe(mapError((cause) => new OrchestrationDispatchCommandError({
|
|
305265
305545
|
message: "Failed to dispatch orchestration command.",
|
|
305266
305546
|
cause
|
|
305267
|
-
}))) : orchestrationEngine.dispatch(normalizedCommand).pipe(mapError((cause) => new OrchestrationDispatchCommandError({
|
|
305547
|
+
}))) : (normalizedCommand.type === "thread.turn.interrupt" ? interruptBootstrapTurnStart(orchestrationEngine, normalizedCommand) : orchestrationEngine.dispatch(normalizedCommand)).pipe(mapError((cause) => new OrchestrationDispatchCommandError({
|
|
305268
305548
|
message: "Failed to dispatch orchestration command.",
|
|
305269
305549
|
cause
|
|
305270
305550
|
})));
|