@cmmd-center/forge 0.13.8 → 0.13.9
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 +343 -51
- package/dist/bin.mjs +367 -75
- package/dist/client/assets/{DiffPanel-CBfeDIH3.js → DiffPanel-DTiRv6A3.js} +3 -3
- package/dist/client/assets/{DiffPanel.logic-CZdlskWf.js → DiffPanel.logic-BrHjYrbX.js} +2 -2
- package/dist/client/assets/{DiffPanelShell-BnSbIo9A.js → DiffPanelShell-CivZRVc4.js} +114 -114
- package/dist/client/assets/{DiffWorkerPoolProvider-DC4SN57K.js → DiffWorkerPoolProvider-Vm64F-i1.js} +8 -8
- package/dist/client/assets/{PullRequestCodePanel-DwjjRPkc.js → PullRequestCodePanel-DJPvOmkY.js} +3 -3
- package/dist/client/assets/{Virtualizer-ClYwoP30.js → Virtualizer-CJivXWYL.js} +2 -2
- package/dist/client/assets/{index-BE83u7Db.css → index-DTtOLoW6.css} +1 -1
- package/dist/client/assets/index-TdSTLuh4.js +154 -0
- package/dist/client/index.html +5 -5
- package/dist/forge-build.json +1 -1
- package/dist/{open-D8mGyWmt.mjs → open-FIgTDosf.mjs} +3 -3
- package/package.json +1 -1
- package/dist/client/assets/index-CZhTqk2p.js +0 -153
package/dist/bin.cjs
CHANGED
|
@@ -66289,7 +66289,7 @@ function normalizeNumberish(value) {
|
|
|
66289
66289
|
}
|
|
66290
66290
|
//#endregion
|
|
66291
66291
|
//#region package.json
|
|
66292
|
-
var version$1 = "0.13.
|
|
66292
|
+
var version$1 = "0.13.9";
|
|
66293
66293
|
//#endregion
|
|
66294
66294
|
//#region src/sentry.ts
|
|
66295
66295
|
const SERVER_APP_NAME = "forge-server";
|
|
@@ -88064,14 +88064,18 @@ function resolveRuntimeGitHubGrantAuthFromEnv(headers) {
|
|
|
88064
88064
|
}
|
|
88065
88065
|
function buildCmmdRuntimeGrantFetchRequest(auth, repoFullName) {
|
|
88066
88066
|
return {
|
|
88067
|
-
url: new URL(`/api/forge/runtimes/${encodeURIComponent(auth.runtimeId)}/
|
|
88067
|
+
url: new URL(`/api/forge/runtimes/${encodeURIComponent(auth.runtimeId)}/scm/credential`, resolveCommandAppUrl()).toString(),
|
|
88068
88068
|
init: {
|
|
88069
88069
|
method: "POST",
|
|
88070
88070
|
headers: {
|
|
88071
88071
|
Authorization: `Bearer ${auth.token}`,
|
|
88072
88072
|
"Content-Type": "application/json"
|
|
88073
88073
|
},
|
|
88074
|
-
body: JSON.stringify({
|
|
88074
|
+
body: JSON.stringify({
|
|
88075
|
+
provider: "github",
|
|
88076
|
+
host: "github.com",
|
|
88077
|
+
repository_path: repoFullName
|
|
88078
|
+
})
|
|
88075
88079
|
}
|
|
88076
88080
|
};
|
|
88077
88081
|
}
|
|
@@ -88533,10 +88537,19 @@ function fetchInstallationTokenForAuth(auth, repoFullName) {
|
|
|
88533
88537
|
ok: false,
|
|
88534
88538
|
...lastError
|
|
88535
88539
|
};
|
|
88536
|
-
if (tokenResp.ok)
|
|
88537
|
-
|
|
88538
|
-
token
|
|
88539
|
-
|
|
88540
|
+
if (tokenResp.ok) {
|
|
88541
|
+
const tokenData = yield* require_Schema$1.promise(() => tokenResp.json());
|
|
88542
|
+
const token = auth.kind === "cmmd-runtime-ticket" ? tokenData.credential : tokenData.token;
|
|
88543
|
+
if (typeof token === "string" && token.trim().length > 0) return {
|
|
88544
|
+
ok: true,
|
|
88545
|
+
token: token.trim()
|
|
88546
|
+
};
|
|
88547
|
+
return {
|
|
88548
|
+
ok: false,
|
|
88549
|
+
status: 502,
|
|
88550
|
+
error: "CMMD returned an invalid source-control credential response."
|
|
88551
|
+
};
|
|
88552
|
+
}
|
|
88540
88553
|
const err = yield* require_Schema$1.promise(() => tokenResp.json().catch(() => ({})));
|
|
88541
88554
|
lastError = {
|
|
88542
88555
|
status: tokenResp.status,
|
|
@@ -89458,23 +89471,38 @@ var GitHubBroker = class {
|
|
|
89458
89471
|
async cloneRepository(auth, input) {
|
|
89459
89472
|
const cloneInput = validateCloneInput(input);
|
|
89460
89473
|
if ("ok" in cloneInput) return cloneInput;
|
|
89461
|
-
|
|
89474
|
+
let { branch } = cloneInput;
|
|
89462
89475
|
const gitToken = await this.resolveInstallationToken(auth, input.repoFullName);
|
|
89463
89476
|
if (typeof gitToken !== "string") return gitToken;
|
|
89464
|
-
|
|
89477
|
+
try {
|
|
89478
|
+
await (0, node_fs_promises.mkdir)(input.destination);
|
|
89479
|
+
} catch (error) {
|
|
89480
|
+
if (isNodeErrorWithCode(error, "EEXIST")) return cloneDestinationExistsResult();
|
|
89481
|
+
return {
|
|
89482
|
+
ok: false,
|
|
89483
|
+
code: "GITHUB_CLONE_DESTINATION_CREATE_FAILED",
|
|
89484
|
+
error: "Could not create the clone destination."
|
|
89485
|
+
};
|
|
89486
|
+
}
|
|
89487
|
+
const initFailure = await this.runCloneGitStep(branch === null ? ["init", input.destination] : [
|
|
89465
89488
|
"init",
|
|
89466
89489
|
"-b",
|
|
89467
89490
|
branch,
|
|
89468
89491
|
input.destination
|
|
89469
89492
|
], "GITHUB_CLONE_INIT_FAILED", "Could not initialize the clone destination.");
|
|
89470
|
-
if (initFailure) return initFailure;
|
|
89493
|
+
if (initFailure) return removeFailedCloneDestination(input.destination, initFailure);
|
|
89471
89494
|
const configured = await this.configureProjectGitCredential({
|
|
89472
89495
|
cwd: input.destination,
|
|
89473
89496
|
repoFullName: input.repoFullName,
|
|
89474
89497
|
token: gitToken,
|
|
89475
89498
|
remoteMode: "add"
|
|
89476
89499
|
});
|
|
89477
|
-
if (!configured.ok) return configured;
|
|
89500
|
+
if (!configured.ok) return removeFailedCloneDestination(input.destination, configured);
|
|
89501
|
+
if (branch === null) {
|
|
89502
|
+
const defaultBranch = await this.resolveRemoteDefaultBranch(input.destination);
|
|
89503
|
+
if (typeof defaultBranch !== "string") return removeFailedCloneDestination(input.destination, defaultBranch);
|
|
89504
|
+
branch = defaultBranch;
|
|
89505
|
+
}
|
|
89478
89506
|
const fetchFailure = await this.runCloneGitStep([
|
|
89479
89507
|
"-C",
|
|
89480
89508
|
input.destination,
|
|
@@ -89484,7 +89512,7 @@ var GitHubBroker = class {
|
|
|
89484
89512
|
"origin",
|
|
89485
89513
|
branch
|
|
89486
89514
|
], "GITHUB_CLONE_FETCH_FAILED", "Could not fetch the requested repository branch.", { timeoutMs: 12e4 });
|
|
89487
|
-
if (fetchFailure) return fetchFailure;
|
|
89515
|
+
if (fetchFailure) return removeFailedCloneDestination(input.destination, fetchFailure);
|
|
89488
89516
|
const checkoutFailure = await this.runCloneGitStep([
|
|
89489
89517
|
"-C",
|
|
89490
89518
|
input.destination,
|
|
@@ -89493,7 +89521,7 @@ var GitHubBroker = class {
|
|
|
89493
89521
|
branch,
|
|
89494
89522
|
"FETCH_HEAD"
|
|
89495
89523
|
], "GITHUB_CLONE_CHECKOUT_FAILED", "Could not check out the requested repository branch.");
|
|
89496
|
-
if (checkoutFailure) return checkoutFailure;
|
|
89524
|
+
if (checkoutFailure) return removeFailedCloneDestination(input.destination, checkoutFailure);
|
|
89497
89525
|
return {
|
|
89498
89526
|
ok: true,
|
|
89499
89527
|
data: {
|
|
@@ -90103,9 +90131,9 @@ var GitHubBroker = class {
|
|
|
90103
90131
|
};
|
|
90104
90132
|
}
|
|
90105
90133
|
async resolveInstallationToken(auth, repoFullName) {
|
|
90106
|
-
const runtimeGrant = this.resolveRuntimeGrant();
|
|
90134
|
+
const runtimeGrant = this.resolveRuntimeGrant("scm");
|
|
90107
90135
|
if (runtimeGrant) {
|
|
90108
|
-
const token = await this.
|
|
90136
|
+
const token = await this.fetchRuntimeScmCredential(runtimeGrant, repoFullName);
|
|
90109
90137
|
if (!token.ok) return token;
|
|
90110
90138
|
return token.token ?? invalidInstallationTokenResult();
|
|
90111
90139
|
}
|
|
@@ -90488,7 +90516,7 @@ var GitHubBroker = class {
|
|
|
90488
90516
|
repoFullName
|
|
90489
90517
|
};
|
|
90490
90518
|
}
|
|
90491
|
-
resolveRuntimeGrant() {
|
|
90519
|
+
resolveRuntimeGrant(requiredScope = "github") {
|
|
90492
90520
|
if (this.runtimeRole !== "user-vm") return null;
|
|
90493
90521
|
const runtimeId = process.env.FORGE_CMMD_RUNTIME_ID?.trim();
|
|
90494
90522
|
if (!runtimeId) return null;
|
|
@@ -90498,7 +90526,7 @@ var GitHubBroker = class {
|
|
|
90498
90526
|
runtimeId,
|
|
90499
90527
|
machineId: identity.machineId,
|
|
90500
90528
|
credentialEpoch: identity.credentialEpoch,
|
|
90501
|
-
requiredScope
|
|
90529
|
+
requiredScope
|
|
90502
90530
|
});
|
|
90503
90531
|
return authority ? {
|
|
90504
90532
|
runtimeId,
|
|
@@ -90512,8 +90540,8 @@ var GitHubBroker = class {
|
|
|
90512
90540
|
token: legacyToken
|
|
90513
90541
|
} : null;
|
|
90514
90542
|
}
|
|
90515
|
-
runtimeGrantAuthContext() {
|
|
90516
|
-
const grant = this.resolveRuntimeGrant();
|
|
90543
|
+
runtimeGrantAuthContext(requiredScope = "github") {
|
|
90544
|
+
const grant = this.resolveRuntimeGrant(requiredScope);
|
|
90517
90545
|
if (grant === null) return null;
|
|
90518
90546
|
return {
|
|
90519
90547
|
sessionId: grant.sessionId ?? AuthSessionId.make(`cmmd-runtime:${grant.runtimeId}`),
|
|
@@ -90565,13 +90593,33 @@ var GitHubBroker = class {
|
|
|
90565
90593
|
};
|
|
90566
90594
|
}
|
|
90567
90595
|
async fetchRuntimeInstallationToken(grant, repoFullName) {
|
|
90568
|
-
|
|
90596
|
+
return this.fetchRuntimeCredential(grant, {
|
|
90597
|
+
url: makeUrl(this.commandAppUrl, `/api/forge/runtimes/${encodeURIComponent(grant.runtimeId)}/github/installation-token`),
|
|
90598
|
+
requestBody: { repo_full_name: repoFullName },
|
|
90599
|
+
responseField: "token",
|
|
90600
|
+
label: "GitHub installation token"
|
|
90601
|
+
});
|
|
90602
|
+
}
|
|
90603
|
+
async fetchRuntimeScmCredential(grant, repoFullName) {
|
|
90604
|
+
return this.fetchRuntimeCredential(grant, {
|
|
90605
|
+
url: makeUrl(this.commandAppUrl, `/api/forge/runtimes/${encodeURIComponent(grant.runtimeId)}/scm/credential`),
|
|
90606
|
+
requestBody: {
|
|
90607
|
+
provider: "github",
|
|
90608
|
+
host: "github.com",
|
|
90609
|
+
repository_path: repoFullName
|
|
90610
|
+
},
|
|
90611
|
+
responseField: "credential",
|
|
90612
|
+
label: "GitHub source-control credential"
|
|
90613
|
+
});
|
|
90614
|
+
}
|
|
90615
|
+
async fetchRuntimeCredential(grant, input) {
|
|
90616
|
+
const response = await this.fetchImpl(input.url, {
|
|
90569
90617
|
method: "POST",
|
|
90570
90618
|
headers: {
|
|
90571
90619
|
Authorization: `Bearer ${grant.token}`,
|
|
90572
90620
|
"Content-Type": "application/json"
|
|
90573
90621
|
},
|
|
90574
|
-
body: JSON.stringify(
|
|
90622
|
+
body: JSON.stringify(input.requestBody),
|
|
90575
90623
|
signal: AbortSignal.timeout(GITHUB_BROKER_REQUEST_TIMEOUT_MS)
|
|
90576
90624
|
});
|
|
90577
90625
|
const body = await parseResponseBody(response);
|
|
@@ -90580,10 +90628,10 @@ var GitHubBroker = class {
|
|
|
90580
90628
|
status: response.status,
|
|
90581
90629
|
code: response.status === 401 ? "GITHUB_AUTH_REQUIRED" : "GITHUB_BROKER_REQUEST_FAILED",
|
|
90582
90630
|
...response.status === 401 ? { userActionRequired: "connect_github" } : {},
|
|
90583
|
-
error: errorFromBody(body,
|
|
90631
|
+
error: errorFromBody(body, `${input.label} request failed with status ${response.status}.`),
|
|
90584
90632
|
data: body
|
|
90585
90633
|
};
|
|
90586
|
-
const token = typeof body === "object" && body !== null ? body.
|
|
90634
|
+
const token = typeof body === "object" && body !== null ? body[input.responseField] : null;
|
|
90587
90635
|
if (typeof token !== "string" || token.trim().length === 0) return invalidInstallationTokenResult();
|
|
90588
90636
|
return {
|
|
90589
90637
|
ok: true,
|
|
@@ -90602,6 +90650,25 @@ var GitHubBroker = class {
|
|
|
90602
90650
|
const branch = result.result.stdout.trim();
|
|
90603
90651
|
return branch.length > 0 ? branch : null;
|
|
90604
90652
|
}
|
|
90653
|
+
async resolveRemoteDefaultBranch(cwd) {
|
|
90654
|
+
const result = await this.runGit([
|
|
90655
|
+
"-C",
|
|
90656
|
+
cwd,
|
|
90657
|
+
"ls-remote",
|
|
90658
|
+
"--symref",
|
|
90659
|
+
"origin",
|
|
90660
|
+
"HEAD"
|
|
90661
|
+
], { allowNonZeroExit: true });
|
|
90662
|
+
if (!isGitRunResult(result)) return result;
|
|
90663
|
+
if (result.result.code !== 0) return gitCommandFailure("GITHUB_DEFAULT_BRANCH_LOOKUP_FAILED", result.result.stderr, "Could not determine the repository default branch.");
|
|
90664
|
+
const branch = /^ref:\s+refs\/heads\/([^\s]+)\s+HEAD$/m.exec(result.result.stdout)?.[1];
|
|
90665
|
+
if (branch === void 0) return {
|
|
90666
|
+
ok: false,
|
|
90667
|
+
code: "GITHUB_DEFAULT_BRANCH_RESPONSE_INVALID",
|
|
90668
|
+
error: "GitHub did not return a valid default branch for the repository."
|
|
90669
|
+
};
|
|
90670
|
+
return validateGitBranchName(branch) ?? branch;
|
|
90671
|
+
}
|
|
90605
90672
|
};
|
|
90606
90673
|
function isCmmdCloudRuntimeModeEnv() {
|
|
90607
90674
|
return process.env.FORGE_CMMD_RUNTIME_MODE === "true" || process.env.FORGE_CMMD_RUNTIME_MODE === "1";
|
|
@@ -90686,20 +90753,40 @@ function validateCloneDestination(destination) {
|
|
|
90686
90753
|
code: "GITHUB_CLONE_DESTINATION_INVALID",
|
|
90687
90754
|
error: "An absolute clone destination is required."
|
|
90688
90755
|
};
|
|
90689
|
-
if ((0, node_fs.existsSync)(destination)) return
|
|
90756
|
+
if ((0, node_fs.existsSync)(destination)) return cloneDestinationExistsResult();
|
|
90757
|
+
return null;
|
|
90758
|
+
}
|
|
90759
|
+
function cloneDestinationExistsResult() {
|
|
90760
|
+
return {
|
|
90690
90761
|
ok: false,
|
|
90691
90762
|
code: "GITHUB_CLONE_DESTINATION_EXISTS",
|
|
90692
90763
|
error: "Clone destination already exists; choose a new empty path."
|
|
90693
90764
|
};
|
|
90694
|
-
|
|
90765
|
+
}
|
|
90766
|
+
function isNodeErrorWithCode(error, code) {
|
|
90767
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
90768
|
+
}
|
|
90769
|
+
async function removeFailedCloneDestination(destination, failure) {
|
|
90770
|
+
try {
|
|
90771
|
+
await (0, node_fs_promises.rm)(destination, {
|
|
90772
|
+
recursive: true,
|
|
90773
|
+
force: true
|
|
90774
|
+
});
|
|
90775
|
+
return failure;
|
|
90776
|
+
} catch {
|
|
90777
|
+
return {
|
|
90778
|
+
...failure,
|
|
90779
|
+
error: `${failure.error ?? "Clone failed."} The incomplete clone destination could not be removed.`
|
|
90780
|
+
};
|
|
90781
|
+
}
|
|
90695
90782
|
}
|
|
90696
90783
|
function validateCloneInput(input) {
|
|
90697
90784
|
const repoFullNameValidation = validateRepoFullName(input.repoFullName);
|
|
90698
90785
|
if (repoFullNameValidation) return repoFullNameValidation;
|
|
90699
90786
|
const destinationValidation = validateCloneDestination(input.destination);
|
|
90700
90787
|
if (destinationValidation) return destinationValidation;
|
|
90701
|
-
const branch = input.branch?.trim() ||
|
|
90702
|
-
return validateGitBranchName(branch) ?? { branch };
|
|
90788
|
+
const branch = input.branch?.trim() || null;
|
|
90789
|
+
return branch === null ? { branch } : validateGitBranchName(branch) ?? { branch };
|
|
90703
90790
|
}
|
|
90704
90791
|
function validateGitBranchName(branch) {
|
|
90705
90792
|
if (branch.length === 0 || branch.startsWith("-") || Array.from(branch).some((character) => {
|
|
@@ -93872,6 +93959,17 @@ const admitNormalizedDispatchCommand = (command, admit) => require_Schema$1.unin
|
|
|
93872
93959
|
//#region src/orchestration/bootstrapCommandCoordinator.ts
|
|
93873
93960
|
const MAX_COMPLETED_COMMANDS_PER_ENGINE = 256;
|
|
93874
93961
|
const commandsByEngine = /* @__PURE__ */ new WeakMap();
|
|
93962
|
+
const sealBootstrapCommand = (engine, commandId) => {
|
|
93963
|
+
const entry = commandsByEngine.get(engine)?.get(commandId);
|
|
93964
|
+
if (entry) entry.cancellable = false;
|
|
93965
|
+
};
|
|
93966
|
+
const cancelBootstrapCommand = (engine, threadId) => require_Schema$1.promise(async () => {
|
|
93967
|
+
const entry = [...commandsByEngine.get(engine)?.values() ?? []].find((candidate) => candidate.threadId === threadId && !candidate.completed && candidate.cancellable);
|
|
93968
|
+
if (!entry) return false;
|
|
93969
|
+
entry.controller.abort();
|
|
93970
|
+
await entry.promise.catch(() => void 0);
|
|
93971
|
+
return true;
|
|
93972
|
+
});
|
|
93875
93973
|
const toBootstrapError = (error) => require_Schema$1.is(OrchestrationDispatchCommandError)(error) ? error : new OrchestrationDispatchCommandError({
|
|
93876
93974
|
message: error instanceof Error ? error.message : "Bootstrap command failed.",
|
|
93877
93975
|
cause: error
|
|
@@ -93891,7 +93989,7 @@ const pruneCompletedCommands = (commands) => {
|
|
|
93891
93989
|
* the registry to one server runtime, so reconnects share work while separate
|
|
93892
93990
|
* runtimes remain isolated.
|
|
93893
93991
|
*/
|
|
93894
|
-
const runBootstrapCommand = (engine, commandId, bootstrapEffect) => {
|
|
93992
|
+
const runBootstrapCommand = (engine, commandId, bootstrapEffect, threadId) => {
|
|
93895
93993
|
let commands = commandsByEngine.get(engine);
|
|
93896
93994
|
if (commands === void 0) {
|
|
93897
93995
|
commands = /* @__PURE__ */ new Map();
|
|
@@ -93904,16 +94002,21 @@ const runBootstrapCommand = (engine, commandId, bootstrapEffect) => {
|
|
|
93904
94002
|
});
|
|
93905
94003
|
pruneCompletedCommands(commands);
|
|
93906
94004
|
let entry;
|
|
93907
|
-
const
|
|
94005
|
+
const controller = new AbortController();
|
|
94006
|
+
const promise = Promise.resolve().then(() => require_Schema$1.runPromise(bootstrapEffect, { signal: controller.signal })).then((result) => {
|
|
93908
94007
|
entry.completed = true;
|
|
93909
94008
|
return result;
|
|
93910
94009
|
}, (error) => {
|
|
93911
|
-
|
|
94010
|
+
entry.completed = true;
|
|
94011
|
+
if (!controller.signal.aborted) commands.delete(commandId);
|
|
93912
94012
|
throw error;
|
|
93913
94013
|
});
|
|
93914
94014
|
entry = {
|
|
93915
94015
|
promise,
|
|
93916
|
-
completed: false
|
|
94016
|
+
completed: false,
|
|
94017
|
+
threadId,
|
|
94018
|
+
controller,
|
|
94019
|
+
cancellable: true
|
|
93917
94020
|
};
|
|
93918
94021
|
commands.set(commandId, entry);
|
|
93919
94022
|
return require_Schema$1.tryPromise({
|
|
@@ -93923,6 +94026,10 @@ const runBootstrapCommand = (engine, commandId, bootstrapEffect) => {
|
|
|
93923
94026
|
};
|
|
93924
94027
|
//#endregion
|
|
93925
94028
|
//#region src/orchestration/bootstrapDispatch.ts
|
|
94029
|
+
const interruptBootstrapTurnStart = (engine, command) => require_Schema$1.gen(function* () {
|
|
94030
|
+
if (yield* cancelBootstrapCommand(engine, command.threadId)) return { sequence: (yield* engine.getReadModel()).snapshotSequence };
|
|
94031
|
+
return yield* engine.dispatch(command);
|
|
94032
|
+
});
|
|
93926
94033
|
const MAX_BOOTSTRAP_OUTPUT_LINE_LENGTH = 1e3;
|
|
93927
94034
|
const toBootstrapDispatchCommandCauseError = (cause) => {
|
|
93928
94035
|
const error = require_Schema$1.squash(cause);
|
|
@@ -94009,6 +94116,7 @@ const prepareBootstrapWorktree = (input) => require_Schema$1.gen(function* () {
|
|
|
94009
94116
|
const requestedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
94010
94117
|
const baseBranchLabel = bootstrapWorktree.baseBranch ?? "<default>";
|
|
94011
94118
|
const requestedPayload = {
|
|
94119
|
+
turnRequestedAt: input.command.createdAt,
|
|
94012
94120
|
projectCwd: bootstrapWorktree.projectCwd,
|
|
94013
94121
|
baseBranch: bootstrapWorktree.baseBranch,
|
|
94014
94122
|
branch: bootstrapWorktree.branch,
|
|
@@ -94029,6 +94137,16 @@ const prepareBootstrapWorktree = (input) => require_Schema$1.gen(function* () {
|
|
|
94029
94137
|
branch: bootstrapWorktree.baseBranch,
|
|
94030
94138
|
newBranch: bootstrapWorktree.branch,
|
|
94031
94139
|
path: null,
|
|
94140
|
+
onStage: (update) => appendWorktreeActivity({
|
|
94141
|
+
orchestrationEngine: input.orchestrationEngine,
|
|
94142
|
+
threadId: input.command.threadId,
|
|
94143
|
+
commandId: CommandId.make(`server:worktree-stage:${input.command.commandId}:${crypto.randomUUID()}`),
|
|
94144
|
+
kind: "worktree.stage",
|
|
94145
|
+
summary: "Preparing worktree",
|
|
94146
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
94147
|
+
payload: update,
|
|
94148
|
+
tone: "info"
|
|
94149
|
+
}).pipe(require_Schema$1.asVoid, require_Schema$1.ignore),
|
|
94032
94150
|
progress: {
|
|
94033
94151
|
onStdoutLine: (line) => {
|
|
94034
94152
|
const detail = truncateBootstrapOutputLine(line);
|
|
@@ -94068,6 +94186,7 @@ const prepareBootstrapWorktree = (input) => require_Schema$1.gen(function* () {
|
|
|
94068
94186
|
}
|
|
94069
94187
|
}
|
|
94070
94188
|
}).pipe(require_Schema$1.catchCause((cause) => {
|
|
94189
|
+
if (require_Schema$1.hasInterruptsOnly(cause)) return require_Schema$1.failCause(cause);
|
|
94071
94190
|
const error = require_Schema$1.squash(cause);
|
|
94072
94191
|
const detail = error instanceof Error ? error.message : "Unknown worktree failure.";
|
|
94073
94192
|
return appendWorktreeActivity({
|
|
@@ -94194,7 +94313,16 @@ const dispatchBootstrapTurnStart = (input, command) => require_Schema$1.gen(func
|
|
|
94194
94313
|
worktreePath
|
|
94195
94314
|
}),
|
|
94196
94315
|
onSuccess: (setupResult) => {
|
|
94197
|
-
if (setupResult.status !== "started") return
|
|
94316
|
+
if (setupResult.status !== "started") return appendSetupScriptActivity({
|
|
94317
|
+
orchestrationEngine,
|
|
94318
|
+
threadId: command.threadId,
|
|
94319
|
+
commandId: bootstrapCommandId(command, "setup-script-skipped"),
|
|
94320
|
+
kind: "setup-script.skipped",
|
|
94321
|
+
summary: "No setup script configured",
|
|
94322
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
94323
|
+
payload: {},
|
|
94324
|
+
tone: "info"
|
|
94325
|
+
}).pipe(require_Schema$1.asVoid, require_Schema$1.ignore);
|
|
94198
94326
|
return recordSetupScriptStarted({
|
|
94199
94327
|
requestedAt,
|
|
94200
94328
|
worktreePath,
|
|
@@ -94224,13 +94352,33 @@ const dispatchBootstrapTurnStart = (input, command) => require_Schema$1.gen(func
|
|
|
94224
94352
|
targetProjectCwd = preparedWorktree.projectCwd;
|
|
94225
94353
|
}
|
|
94226
94354
|
yield* runSetupProgram();
|
|
94355
|
+
if (bootstrap?.prepareWorktree) yield* appendWorktreeActivity({
|
|
94356
|
+
orchestrationEngine,
|
|
94357
|
+
threadId: command.threadId,
|
|
94358
|
+
commandId: bootstrapCommandId(command, "launch-agent-starting"),
|
|
94359
|
+
kind: "launch.agent-starting",
|
|
94360
|
+
summary: "Starting agent",
|
|
94361
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
94362
|
+
payload: { setupRequested: bootstrap.runSetupScript === true },
|
|
94363
|
+
tone: "info"
|
|
94364
|
+
}).pipe(require_Schema$1.ignore);
|
|
94365
|
+
sealBootstrapCommand(orchestrationEngine, command.commandId);
|
|
94227
94366
|
return yield* orchestrationEngine.dispatch(finalTurnStartCommand);
|
|
94228
94367
|
});
|
|
94229
|
-
return yield* runBootstrapCommand(orchestrationEngine, command.commandId, bootstrapProgram.pipe(require_Schema$1.
|
|
94368
|
+
return yield* runBootstrapCommand(orchestrationEngine, command.commandId, bootstrapProgram.pipe(require_Schema$1.onInterrupt(() => appendWorktreeActivity({
|
|
94369
|
+
orchestrationEngine,
|
|
94370
|
+
threadId: command.threadId,
|
|
94371
|
+
commandId: bootstrapCommandId(command, "launch-cancelled"),
|
|
94372
|
+
kind: "launch.cancelled",
|
|
94373
|
+
summary: "Launch cancelled",
|
|
94374
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
94375
|
+
payload: {},
|
|
94376
|
+
tone: "info"
|
|
94377
|
+
}).pipe(require_Schema$1.ignore)), require_Schema$1.catchCause((cause) => {
|
|
94230
94378
|
const dispatchError = toBootstrapDispatchCommandCauseError(cause);
|
|
94231
94379
|
if (require_Schema$1.hasInterruptsOnly(cause)) return require_Schema$1.fail(dispatchError);
|
|
94232
94380
|
return cleanupCreatedThread().pipe(require_Schema$1.flatMap(() => require_Schema$1.fail(dispatchError)));
|
|
94233
|
-
})));
|
|
94381
|
+
})), command.threadId);
|
|
94234
94382
|
});
|
|
94235
94383
|
//#endregion
|
|
94236
94384
|
//#region src/orchestration/Services/OrchestrationEngine.ts
|
|
@@ -100946,6 +101094,7 @@ function emptyConfig(source, path) {
|
|
|
100946
101094
|
terminals: [],
|
|
100947
101095
|
systemPackages: [],
|
|
100948
101096
|
secrets: [],
|
|
101097
|
+
repositoryDependencies: [],
|
|
100949
101098
|
issues: []
|
|
100950
101099
|
};
|
|
100951
101100
|
}
|
|
@@ -101031,6 +101180,7 @@ function readConfigFile(source, path) {
|
|
|
101031
101180
|
terminals: terminalsFromValue(parsed.terminals),
|
|
101032
101181
|
systemPackages: stringArray(parsed.systemPackages ?? parsed.aptPackages ?? parsed.packages),
|
|
101033
101182
|
secrets: stringArray(parsed.secrets ?? parsed.envSecrets),
|
|
101183
|
+
repositoryDependencies: stringArray(parsed.repositoryDependencies),
|
|
101034
101184
|
issues: []
|
|
101035
101185
|
};
|
|
101036
101186
|
}
|
|
@@ -101443,6 +101593,7 @@ const EMPTY_WORKSPACE_ENVIRONMENT_CONFIG = {
|
|
|
101443
101593
|
terminals: [],
|
|
101444
101594
|
systemPackages: [],
|
|
101445
101595
|
secrets: [],
|
|
101596
|
+
repositoryDependencies: [],
|
|
101446
101597
|
issues: []
|
|
101447
101598
|
};
|
|
101448
101599
|
function buildCwdCheck(cwdExists) {
|
|
@@ -106250,7 +106401,7 @@ const makeWsRpcLayer = (currentSessionId, currentUserId) => WsRpcGroup.toLayer(r
|
|
|
106250
106401
|
git,
|
|
106251
106402
|
gitStatusBroadcaster,
|
|
106252
106403
|
projectSetupScriptRunner
|
|
106253
|
-
}, normalizedCommand) : orchestrationEngine.dispatch(normalizedCommand).pipe(require_Schema$1.mapError((cause) => toDispatchCommandError(cause, "Failed to dispatch orchestration command")));
|
|
106404
|
+
}, normalizedCommand) : (normalizedCommand.type === "thread.turn.interrupt" ? interruptBootstrapTurnStart(orchestrationEngine, normalizedCommand) : orchestrationEngine.dispatch(normalizedCommand)).pipe(require_Schema$1.mapError((cause) => toDispatchCommandError(cause, "Failed to dispatch orchestration command")));
|
|
106254
106405
|
return startup.enqueueCommand(dispatchEffect).pipe(require_Schema$1.mapError((cause) => toDispatchCommandError(cause, "Failed to dispatch orchestration command")));
|
|
106255
106406
|
};
|
|
106256
106407
|
const loadServerConfig = require_Schema$1.gen(function* () {
|
|
@@ -151620,6 +151771,86 @@ async function attestCodexLocalAccountIdentity(input) {
|
|
|
151620
151771
|
return identity;
|
|
151621
151772
|
}
|
|
151622
151773
|
//#endregion
|
|
151774
|
+
//#region src/workspace/workspaceRepositoryDependencies.ts
|
|
151775
|
+
function repositoryFullName(value) {
|
|
151776
|
+
return value.trim().match(/^(?:https?:\/\/)?github\.com\/([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+?)(?:\.git)?\/?$/i)?.[1] ?? null;
|
|
151777
|
+
}
|
|
151778
|
+
function dependencyDestination(cloudProjectsRoot, repoFullName) {
|
|
151779
|
+
const root = (0, node_path.resolve)(cloudProjectsRoot);
|
|
151780
|
+
const destination = (0, node_path.resolve)((0, node_path.join)(root, (0, node_path.basename)(repoFullName)));
|
|
151781
|
+
const pathFromRoot = (0, node_path.relative)(root, destination);
|
|
151782
|
+
if (pathFromRoot.startsWith("..") || pathFromRoot === "") throw new Error(`Repository dependency ${repoFullName} has an unsafe destination.`);
|
|
151783
|
+
return destination;
|
|
151784
|
+
}
|
|
151785
|
+
async function readOriginFromGit(destination) {
|
|
151786
|
+
const result = await runProcess("git", [
|
|
151787
|
+
"-C",
|
|
151788
|
+
destination,
|
|
151789
|
+
"remote",
|
|
151790
|
+
"get-url",
|
|
151791
|
+
"origin"
|
|
151792
|
+
], {
|
|
151793
|
+
allowNonZeroExit: true,
|
|
151794
|
+
timeoutMs: 1e4
|
|
151795
|
+
});
|
|
151796
|
+
return result.code === 0 ? result.stdout.trim() : null;
|
|
151797
|
+
}
|
|
151798
|
+
function resolveRepositoryDependencies(declarations, cloudProjectsRoot) {
|
|
151799
|
+
const destinations = /* @__PURE__ */ new Set();
|
|
151800
|
+
return declarations.map((declaration) => {
|
|
151801
|
+
const repoFullName = repositoryFullName(declaration);
|
|
151802
|
+
if (repoFullName === null) throw new Error(`Unsupported repository dependency: ${declaration}`);
|
|
151803
|
+
const destination = dependencyDestination(cloudProjectsRoot, repoFullName);
|
|
151804
|
+
if (destinations.has(destination)) throw new Error(`Repository dependencies collide at ${destination}.`);
|
|
151805
|
+
destinations.add(destination);
|
|
151806
|
+
return {
|
|
151807
|
+
repoFullName,
|
|
151808
|
+
destination
|
|
151809
|
+
};
|
|
151810
|
+
});
|
|
151811
|
+
}
|
|
151812
|
+
async function prepareRepositoryDependency(input) {
|
|
151813
|
+
const { repoFullName, destination } = input.dependency;
|
|
151814
|
+
if ((0, node_fs.existsSync)(destination)) {
|
|
151815
|
+
const origin = await input.readOrigin(destination);
|
|
151816
|
+
const existingRepo = origin === null ? null : parseRepoFullNameFromRemoteUrl(origin);
|
|
151817
|
+
if (existingRepo?.toLowerCase() !== repoFullName.toLowerCase()) throw new Error(`Repository dependency destination ${destination} contains ${existingRepo ?? "no GitHub repository"} instead of ${repoFullName}.`);
|
|
151818
|
+
return {
|
|
151819
|
+
repoFullName,
|
|
151820
|
+
destination,
|
|
151821
|
+
outcome: "existing"
|
|
151822
|
+
};
|
|
151823
|
+
}
|
|
151824
|
+
const result = await input.broker.cloneRepository(input.auth, {
|
|
151825
|
+
repoFullName,
|
|
151826
|
+
destination
|
|
151827
|
+
});
|
|
151828
|
+
if (!result.ok) throw new Error(`Could not prepare repository dependency ${repoFullName}: ${result.error ?? result.code ?? "clone failed"}`);
|
|
151829
|
+
return {
|
|
151830
|
+
repoFullName,
|
|
151831
|
+
destination,
|
|
151832
|
+
outcome: "cloned"
|
|
151833
|
+
};
|
|
151834
|
+
}
|
|
151835
|
+
async function prepareWorkspaceRepositoryDependencies(input) {
|
|
151836
|
+
if (!input.runtimeMode) return [];
|
|
151837
|
+
const dependencies = resolveWorkspaceEnvironmentConfig(input.cwd).repositoryDependencies;
|
|
151838
|
+
if (dependencies.length === 0) return [];
|
|
151839
|
+
const broker = input.broker ?? new GitHubBroker();
|
|
151840
|
+
const auth = broker.runtimeGrantAuthContext("scm");
|
|
151841
|
+
if (auth === null) throw new Error("Repository dependencies require an exact scoped runtime SCM grant.");
|
|
151842
|
+
const readOrigin = input.readOrigin ?? readOriginFromGit;
|
|
151843
|
+
const resolved = resolveRepositoryDependencies(dependencies, input.cloudProjectsRoot);
|
|
151844
|
+
const prepared = [];
|
|
151845
|
+
for (const dependency of resolved) prepared.push(await prepareRepositoryDependency({
|
|
151846
|
+
dependency,
|
|
151847
|
+
broker,
|
|
151848
|
+
auth,
|
|
151849
|
+
readOrigin
|
|
151850
|
+
}));
|
|
151851
|
+
return prepared;
|
|
151852
|
+
}
|
|
151853
|
+
//#endregion
|
|
151623
151854
|
//#region src/codexAppServerManager.ts
|
|
151624
151855
|
const CODEX_LOGIN_STATUS_TIMEOUT_MS = 5e3;
|
|
151625
151856
|
const CODEX_SKILLS_LIST_TIMEOUT_MS = 4e3;
|
|
@@ -151954,6 +152185,11 @@ var CodexAppServerManager = class extends node_events.EventEmitter {
|
|
|
151954
152185
|
let context;
|
|
151955
152186
|
try {
|
|
151956
152187
|
const resolvedCwd = input.cwd ?? process.cwd();
|
|
152188
|
+
await prepareWorkspaceRepositoryDependencies({
|
|
152189
|
+
cwd: resolvedCwd,
|
|
152190
|
+
cloudProjectsRoot: process.env.FORGE_CLOUD_PROJECTS_ROOT?.trim() || "/projects",
|
|
152191
|
+
runtimeMode: process.env.FORGE_CMMD_RUNTIME_MODE === "true"
|
|
152192
|
+
});
|
|
151957
152193
|
let workspacePreflightReport = runWorkspaceEnvironmentPreflight({
|
|
151958
152194
|
cwd: resolvedCwd,
|
|
151959
152195
|
env: process.env
|
|
@@ -217040,6 +217276,19 @@ const makeClaudeAdapter = require_Schema$1.fn("makeClaudeAdapter")(function* (op
|
|
|
217040
217276
|
const resumeState = readClaudeResumeState(input.resumeCursor);
|
|
217041
217277
|
const threadId = input.threadId;
|
|
217042
217278
|
const { existingResumeSessionId, newSessionId, sessionId } = yield* resolveClaudeStartSessionIds(resumeState);
|
|
217279
|
+
const workspaceCwd = input.cwd;
|
|
217280
|
+
if (workspaceCwd) yield* require_Schema$1.tryPromise({
|
|
217281
|
+
try: () => prepareWorkspaceRepositoryDependencies({
|
|
217282
|
+
cwd: workspaceCwd,
|
|
217283
|
+
cloudProjectsRoot: serverConfig.cloudProjectsRoot ?? "/projects",
|
|
217284
|
+
runtimeMode: serverConfig.forgeCmmdRuntimeMode === true
|
|
217285
|
+
}),
|
|
217286
|
+
catch: (cause) => new ProviderAdapterValidationError({
|
|
217287
|
+
provider: PROVIDER$11,
|
|
217288
|
+
operation: "startSession",
|
|
217289
|
+
issue: cause instanceof Error ? cause.message : "Could not prepare declared repository dependencies."
|
|
217290
|
+
})
|
|
217291
|
+
});
|
|
217043
217292
|
const runtimeContext = yield* require_Schema$1.context();
|
|
217044
217293
|
const runFork = require_Schema$1.runForkWith(runtimeContext);
|
|
217045
217294
|
const runPromise = require_Schema$1.runPromiseWith(runtimeContext);
|
|
@@ -233379,12 +233628,12 @@ const collectOutput = require_Schema$1.fn("collectOutput")(function* (input, str
|
|
|
233379
233628
|
let lineBuffer = "";
|
|
233380
233629
|
let truncated = false;
|
|
233381
233630
|
const emitCompleteLines = require_Schema$1.fn("emitCompleteLines")(function* (flush) {
|
|
233382
|
-
let newlineIndex = lineBuffer.
|
|
233631
|
+
let newlineIndex = lineBuffer.search(/[\r\n]/);
|
|
233383
233632
|
while (newlineIndex >= 0) {
|
|
233384
233633
|
const line = lineBuffer.slice(0, newlineIndex).replace(/\r$/, "");
|
|
233385
233634
|
lineBuffer = lineBuffer.slice(newlineIndex + 1);
|
|
233386
233635
|
if (line.length > 0 && onLine) yield* onLine(line);
|
|
233387
|
-
newlineIndex = lineBuffer.
|
|
233636
|
+
newlineIndex = lineBuffer.search(/[\r\n]/);
|
|
233388
233637
|
}
|
|
233389
233638
|
if (flush) {
|
|
233390
233639
|
const trailing = lineBuffer.replace(/\r$/, "");
|
|
@@ -233533,6 +233782,7 @@ const makeGitCore = require_Schema$1.fn("makeGitCore")(function* (options) {
|
|
|
233533
233782
|
operation,
|
|
233534
233783
|
cwd,
|
|
233535
233784
|
args,
|
|
233785
|
+
...options.env ? { env: options.env } : {},
|
|
233536
233786
|
...options.stdin !== void 0 ? { stdin: options.stdin } : {},
|
|
233537
233787
|
allowNonZeroExit: true,
|
|
233538
233788
|
...options.timeoutMs !== void 0 ? { timeoutMs: options.timeoutMs } : {},
|
|
@@ -234256,12 +234506,19 @@ const makeGitCore = require_Schema$1.fn("makeGitCore")(function* (options) {
|
|
|
234256
234506
|
};
|
|
234257
234507
|
});
|
|
234258
234508
|
const createWorktree = require_Schema$1.fn("createWorktree")(function* (input) {
|
|
234509
|
+
const report = (stage, status, detail) => input.onStage?.({
|
|
234510
|
+
stage,
|
|
234511
|
+
status,
|
|
234512
|
+
...detail ? { detail } : {}
|
|
234513
|
+
}) ?? require_Schema$1.void_;
|
|
234514
|
+
yield* report("resolve", "running");
|
|
234259
234515
|
const base = input.branch ?? (yield* resolveDefaultBaseBranch(input.cwd));
|
|
234260
234516
|
const startPoint = yield* resolveWorktreeStartPoint({
|
|
234261
234517
|
cwd: input.cwd,
|
|
234262
234518
|
base,
|
|
234263
234519
|
creatingNewBranch: input.newBranch !== void 0
|
|
234264
234520
|
});
|
|
234521
|
+
yield* report("resolve", "done", startPoint);
|
|
234265
234522
|
const targetBranch = input.newBranch ?? base;
|
|
234266
234523
|
const sanitizedBranch = targetBranch.replace(/\//g, "-");
|
|
234267
234524
|
const repoName = path.basename(input.cwd);
|
|
@@ -234273,7 +234530,10 @@ const makeGitCore = require_Schema$1.fn("makeGitCore")(function* (options) {
|
|
|
234273
234530
|
limit: 200
|
|
234274
234531
|
})).branches.find((branch) => branch.isRemote !== true && branch.name === targetBranch && branch.worktreePath !== null && node_path.default.resolve(branch.worktreePath) === canonicalWorktreePath);
|
|
234275
234532
|
if (existingBranch?.worktreePath) {
|
|
234533
|
+
yield* report("checkout", "skipped", "Existing worktree");
|
|
234534
|
+
yield* report("dependencies", "running");
|
|
234276
234535
|
yield* setupSharedWorktreeDependencies(input.cwd, existingBranch.worktreePath);
|
|
234536
|
+
yield* report("dependencies", "done");
|
|
234277
234537
|
return { worktree: {
|
|
234278
234538
|
path: worktreePath,
|
|
234279
234539
|
branch: targetBranch
|
|
@@ -234292,11 +234552,19 @@ const makeGitCore = require_Schema$1.fn("makeGitCore")(function* (options) {
|
|
|
234292
234552
|
worktreePath,
|
|
234293
234553
|
startPoint
|
|
234294
234554
|
];
|
|
234555
|
+
yield* report("checkout", "running");
|
|
234295
234556
|
yield* executeGit("GitCore.createWorktree", input.cwd, args, {
|
|
234296
234557
|
fallbackErrorMessage: "git worktree add failed",
|
|
234558
|
+
env: {
|
|
234559
|
+
GIT_PROGRESS_DELAY: "0",
|
|
234560
|
+
LC_ALL: "C"
|
|
234561
|
+
},
|
|
234297
234562
|
...input.progress ? { progress: input.progress } : {}
|
|
234298
234563
|
});
|
|
234564
|
+
yield* report("checkout", "done");
|
|
234565
|
+
yield* report("dependencies", "running");
|
|
234299
234566
|
yield* setupSharedWorktreeDependencies(input.cwd, worktreePath);
|
|
234567
|
+
yield* report("dependencies", "done");
|
|
234300
234568
|
return { worktree: {
|
|
234301
234569
|
path: worktreePath,
|
|
234302
234570
|
branch: targetBranch
|
|
@@ -297109,7 +297377,7 @@ function resolveBuildCommitFromEnv(env) {
|
|
|
297109
297377
|
* environment descriptor down instead of reporting an honest "unknown".
|
|
297110
297378
|
*/
|
|
297111
297379
|
function readBakedBuildCommit() {
|
|
297112
|
-
return "
|
|
297380
|
+
return "339f0da718657526651ad84cacb841446f1bb38b";
|
|
297113
297381
|
}
|
|
297114
297382
|
async function resolveServerBuildCommit(input) {
|
|
297115
297383
|
if (isFullCommitSha(input.baked)) return input.baked;
|
|
@@ -298935,6 +299203,10 @@ const AuthSessionRepositoryLive = require_Schema$1.effect(AuthSessionRepository,
|
|
|
298935
299203
|
const SIGNING_SECRET_NAME = "server-signing-key";
|
|
298936
299204
|
const DEFAULT_SESSION_TTL = require_Schema$1.days(30);
|
|
298937
299205
|
const DEFAULT_WEBSOCKET_TOKEN_TTL = require_Schema$1.minutes(5);
|
|
299206
|
+
const toSessionCredentialError = (message) => (cause) => new SessionCredentialError({
|
|
299207
|
+
message,
|
|
299208
|
+
cause
|
|
299209
|
+
});
|
|
298938
299210
|
const SessionClaims = require_Schema$1.Struct({
|
|
298939
299211
|
v: require_Schema$1.Literal(1),
|
|
298940
299212
|
kind: require_Schema$1.Literal("session"),
|
|
@@ -298991,10 +299263,6 @@ const makeSessionCredentialService = require_Schema$1.gen(function* () {
|
|
|
298991
299263
|
port: serverConfig.port,
|
|
298992
299264
|
host: serverConfig.host
|
|
298993
299265
|
});
|
|
298994
|
-
const toSessionCredentialError = (message) => (cause) => new SessionCredentialError({
|
|
298995
|
-
message,
|
|
298996
|
-
cause
|
|
298997
|
-
});
|
|
298998
299266
|
const emitUpsert = (clientSession) => require_Path.publish(changesPubSub, {
|
|
298999
299267
|
type: "clientUpserted",
|
|
299000
299268
|
clientSession
|
|
@@ -299155,15 +299423,28 @@ const makeSessionCredentialService = require_Schema$1.gen(function* () {
|
|
|
299155
299423
|
if (require_Schema$1.isSome(row)) {
|
|
299156
299424
|
if (row.value.revokedAt !== null) return yield* new SessionCredentialError({ message: "Websocket session revoked." });
|
|
299157
299425
|
if (row.value.expiresAt.epochMilliseconds <= now) return yield* new SessionCredentialError({ message: "Websocket session expired." });
|
|
299158
|
-
} else
|
|
299426
|
+
} else {
|
|
299427
|
+
const cloudOwnerSession = serverConfig.forgeCloudShellMode === true && claims.method === "proxy-asserted" && forgeCloudOwnerSessionExpiresAt(claims.sid) !== null;
|
|
299428
|
+
if (cloudOwnerSession && isExpiredForgeCloudOwnerSession(claims.sid, now)) return yield* new SessionCredentialError({ message: "Websocket session expired." });
|
|
299429
|
+
if (statelessCookieSessions && (claims.method === "browser-session-cookie" || cloudOwnerSession)) return {
|
|
299430
|
+
sessionId: claims.sid,
|
|
299431
|
+
token,
|
|
299432
|
+
method: claims.method,
|
|
299433
|
+
client: createDefaultClientMetadata(),
|
|
299434
|
+
expiresAt: require_Schema$1.makeUnsafe(claims.exp),
|
|
299435
|
+
subject: claims.sub,
|
|
299436
|
+
role: claims.role
|
|
299437
|
+
};
|
|
299438
|
+
return yield* new SessionCredentialError({ message: "Unknown websocket session." });
|
|
299439
|
+
}
|
|
299159
299440
|
return {
|
|
299160
299441
|
sessionId: claims.sid,
|
|
299161
299442
|
token,
|
|
299162
|
-
method:
|
|
299163
|
-
client:
|
|
299164
|
-
expiresAt:
|
|
299165
|
-
subject:
|
|
299166
|
-
role:
|
|
299443
|
+
method: row.value.method,
|
|
299444
|
+
client: toClientMetadata(row.value.client),
|
|
299445
|
+
expiresAt: row.value.expiresAt,
|
|
299446
|
+
subject: row.value.subject,
|
|
299447
|
+
role: row.value.role
|
|
299167
299448
|
};
|
|
299168
299449
|
}).pipe(require_Schema$1.mapError((cause) => cause instanceof SessionCredentialError ? cause : new SessionCredentialError({
|
|
299169
299450
|
message: "Failed to verify websocket token.",
|
|
@@ -299441,6 +299722,18 @@ function verifyForgeCloudOwnerCallbackAssertion(assertion, config) {
|
|
|
299441
299722
|
//#endregion
|
|
299442
299723
|
//#region src/auth/Layers/ServerAuth.ts
|
|
299443
299724
|
const AUTHORIZATION_PREFIX = "Bearer ";
|
|
299725
|
+
function classifyWebSocketTokenFailure(cause) {
|
|
299726
|
+
switch (cause.message) {
|
|
299727
|
+
case "Malformed websocket token.": return "malformed";
|
|
299728
|
+
case "Invalid websocket token signature.": return "invalid_signature";
|
|
299729
|
+
case "Invalid websocket token payload.": return "invalid_payload";
|
|
299730
|
+
case "Websocket token expired.": return "expired_token";
|
|
299731
|
+
case "Websocket session revoked.": return "revoked_parent_session";
|
|
299732
|
+
case "Websocket session expired.": return "expired_parent_session";
|
|
299733
|
+
case "Unknown websocket session.": return "unknown_parent_session";
|
|
299734
|
+
default: return "verification_failed";
|
|
299735
|
+
}
|
|
299736
|
+
}
|
|
299444
299737
|
function toBootstrapExchangeAuthError(cause) {
|
|
299445
299738
|
if (cause.status === 500) return new AuthError({
|
|
299446
299739
|
message: "Failed to validate bootstrap credential.",
|
|
@@ -299743,7 +300036,6 @@ const makeServerAuth = require_Schema$1.gen(function* () {
|
|
|
299743
300036
|
expiresAt: require_Schema$1.toUtc(issued.expiresAt)
|
|
299744
300037
|
})));
|
|
299745
300038
|
const authenticateWebSocketUpgrade = (request) => require_Schema$1.gen(function* () {
|
|
299746
|
-
if (serverConfig.forgeCloudShellMode === true) return yield* authenticateRequest(request);
|
|
299747
300039
|
if (serverConfig.forgeCmmdRuntimeMode) {
|
|
299748
300040
|
if (serverConfig.forgeCmmdAuthRuntime) {
|
|
299749
300041
|
const authConfig = readCmmdAuthRuntimeConfig(serverConfig);
|
|
@@ -299800,7 +300092,7 @@ const makeServerAuth = require_Schema$1.gen(function* () {
|
|
|
299800
300092
|
const requestUrl = require_HttpServer.toURL(request);
|
|
299801
300093
|
if (require_Schema$1.isSome(requestUrl)) {
|
|
299802
300094
|
const websocketToken = readWebSocketUpgradeToken(requestUrl.value.searchParams);
|
|
299803
|
-
if (websocketToken) return yield* sessions.verifyWebSocketToken(websocketToken).pipe(require_Schema$1.map((session) => ({
|
|
300095
|
+
if (websocketToken) return yield* sessions.verifyWebSocketToken(websocketToken).pipe(require_Schema$1.tapError((cause) => require_Schema$1.logWarning("Rejected websocket token.").pipe(require_Schema$1.annotateLogs({ category: classifyWebSocketTokenFailure(cause) }))), require_Schema$1.map((session) => ({
|
|
299804
300096
|
sessionId: session.sessionId,
|
|
299805
300097
|
subject: session.subject,
|
|
299806
300098
|
method: session.method,
|
|
@@ -305889,7 +306181,7 @@ const orchestrationDispatchRouteLayer = add$1("POST", "/api/orchestration/dispat
|
|
|
305889
306181
|
}).pipe(require_Schema$1.mapError((cause) => new OrchestrationDispatchCommandError({
|
|
305890
306182
|
message: "Failed to dispatch orchestration command.",
|
|
305891
306183
|
cause
|
|
305892
|
-
}))) : orchestrationEngine.dispatch(normalizedCommand).pipe(require_Schema$1.mapError((cause) => new OrchestrationDispatchCommandError({
|
|
306184
|
+
}))) : (normalizedCommand.type === "thread.turn.interrupt" ? interruptBootstrapTurnStart(orchestrationEngine, normalizedCommand) : orchestrationEngine.dispatch(normalizedCommand)).pipe(require_Schema$1.mapError((cause) => new OrchestrationDispatchCommandError({
|
|
305893
306185
|
message: "Failed to dispatch orchestration command.",
|
|
305894
306186
|
cause
|
|
305895
306187
|
})));
|