@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.mjs
CHANGED
|
@@ -22,7 +22,7 @@ import { createCipheriv, createDecipheriv, createHash, createHmac, createPublicK
|
|
|
22
22
|
import * as FS$1 from "node:fs";
|
|
23
23
|
import fs, { accessSync, chmodSync, constants, createReadStream, existsSync, mkdirSync, mkdtempSync, promises, readFile, readFileSync, readdir, readdirSync, realpathSync, rmSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
24
24
|
import * as NodeOS from "node:os";
|
|
25
|
-
import
|
|
25
|
+
import os, { homedir, networkInterfaces, tmpdir } from "node:os";
|
|
26
26
|
import * as Path$1 from "node:path";
|
|
27
27
|
import path, { basename, delimiter, dirname, extname, isAbsolute, join, posix, relative, resolve, sep } from "node:path";
|
|
28
28
|
import { pathToFileURL } from "node:url";
|
|
@@ -50614,7 +50614,7 @@ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
|
|
|
50614
50614
|
const min = forceColor || 0;
|
|
50615
50615
|
if (env.TERM === "dumb") return min;
|
|
50616
50616
|
if (process$1.platform === "win32") {
|
|
50617
|
-
const osRelease =
|
|
50617
|
+
const osRelease = os.release().split(".");
|
|
50618
50618
|
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
50619
50619
|
return 1;
|
|
50620
50620
|
}
|
|
@@ -53057,7 +53057,7 @@ var require_ProcessDetector = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
53057
53057
|
exports.processDetector = void 0;
|
|
53058
53058
|
const api_1 = (init_esm$1(), __toCommonJS(esm_exports$1));
|
|
53059
53059
|
const semconv_1 = require_semconv$1();
|
|
53060
|
-
const os$
|
|
53060
|
+
const os$4 = __require("os");
|
|
53061
53061
|
/**
|
|
53062
53062
|
* ProcessDetector will be used to detect the resources related current process running
|
|
53063
53063
|
* and being instrumented from the NodeJS Process module.
|
|
@@ -53079,7 +53079,7 @@ var require_ProcessDetector = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
53079
53079
|
};
|
|
53080
53080
|
if (process.argv.length > 1) attributes[semconv_1.ATTR_PROCESS_COMMAND] = process.argv[1];
|
|
53081
53081
|
try {
|
|
53082
|
-
const userInfo = os$
|
|
53082
|
+
const userInfo = os$4.userInfo();
|
|
53083
53083
|
attributes[semconv_1.ATTR_PROCESS_OWNER] = userInfo.username;
|
|
53084
53084
|
} catch (e) {
|
|
53085
53085
|
api_1.diag.debug(`error obtaining process owner: ${e}`);
|
|
@@ -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.9";
|
|
66006
66006
|
//#endregion
|
|
66007
66007
|
//#region src/sentry.ts
|
|
66008
66008
|
const SERVER_APP_NAME = "forge-server";
|
|
@@ -75215,7 +75215,7 @@ var require_node_gyp_build = /* @__PURE__ */ __commonJSMin(((exports, module) =>
|
|
|
75215
75215
|
var fs$6 = __require("fs");
|
|
75216
75216
|
var path$5 = __require("path");
|
|
75217
75217
|
var url$1 = __require("url");
|
|
75218
|
-
var os$
|
|
75218
|
+
var os$3 = __require("os");
|
|
75219
75219
|
var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
|
|
75220
75220
|
var vars = process.config && process.config.variables || {};
|
|
75221
75221
|
var prebuildsOnly = !!process.env.PREBUILDS_ONLY;
|
|
@@ -75223,8 +75223,8 @@ var require_node_gyp_build = /* @__PURE__ */ __commonJSMin(((exports, module) =>
|
|
|
75223
75223
|
var abi = versions.modules;
|
|
75224
75224
|
if (versions.deno || process.isBun) abi = "unsupported";
|
|
75225
75225
|
var runtime = isElectron() ? "electron" : isNwjs() ? "node-webkit" : "node";
|
|
75226
|
-
var arch = process.env.npm_config_arch || os$
|
|
75227
|
-
var platform = process.env.npm_config_platform || os$
|
|
75226
|
+
var arch = process.env.npm_config_arch || os$3.arch();
|
|
75227
|
+
var platform = process.env.npm_config_platform || os$3.platform();
|
|
75228
75228
|
var libc = process.env.LIBC || (isMusl(platform) ? "musl" : "glibc");
|
|
75229
75229
|
var armv = process.env.ARM_VERSION || (arch === "arm64" ? "8" : vars.arm_version) || "";
|
|
75230
75230
|
var uv = (versions.uv || "").split(".")[0];
|
|
@@ -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,9 +89785,9 @@ var GitHubBroker = class {
|
|
|
89757
89785
|
};
|
|
89758
89786
|
}
|
|
89759
89787
|
async resolveInstallationToken(auth, repoFullName) {
|
|
89760
|
-
const runtimeGrant = this.resolveRuntimeGrant();
|
|
89788
|
+
const runtimeGrant = this.resolveRuntimeGrant("scm");
|
|
89761
89789
|
if (runtimeGrant) {
|
|
89762
|
-
const token = await this.
|
|
89790
|
+
const token = await this.fetchRuntimeScmCredential(runtimeGrant, repoFullName);
|
|
89763
89791
|
if (!token.ok) return token;
|
|
89764
89792
|
return token.token ?? invalidInstallationTokenResult();
|
|
89765
89793
|
}
|
|
@@ -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,33 @@ 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 fetchRuntimeScmCredential(grant, repoFullName) {
|
|
90258
|
+
return this.fetchRuntimeCredential(grant, {
|
|
90259
|
+
url: makeUrl(this.commandAppUrl, `/api/forge/runtimes/${encodeURIComponent(grant.runtimeId)}/scm/credential`),
|
|
90260
|
+
requestBody: {
|
|
90261
|
+
provider: "github",
|
|
90262
|
+
host: "github.com",
|
|
90263
|
+
repository_path: repoFullName
|
|
90264
|
+
},
|
|
90265
|
+
responseField: "credential",
|
|
90266
|
+
label: "GitHub source-control credential"
|
|
90267
|
+
});
|
|
90268
|
+
}
|
|
90269
|
+
async fetchRuntimeCredential(grant, input) {
|
|
90270
|
+
const response = await this.fetchImpl(input.url, {
|
|
90223
90271
|
method: "POST",
|
|
90224
90272
|
headers: {
|
|
90225
90273
|
Authorization: `Bearer ${grant.token}`,
|
|
90226
90274
|
"Content-Type": "application/json"
|
|
90227
90275
|
},
|
|
90228
|
-
body: JSON.stringify(
|
|
90276
|
+
body: JSON.stringify(input.requestBody),
|
|
90229
90277
|
signal: AbortSignal.timeout(GITHUB_BROKER_REQUEST_TIMEOUT_MS)
|
|
90230
90278
|
});
|
|
90231
90279
|
const body = await parseResponseBody(response);
|
|
@@ -90234,10 +90282,10 @@ var GitHubBroker = class {
|
|
|
90234
90282
|
status: response.status,
|
|
90235
90283
|
code: response.status === 401 ? "GITHUB_AUTH_REQUIRED" : "GITHUB_BROKER_REQUEST_FAILED",
|
|
90236
90284
|
...response.status === 401 ? { userActionRequired: "connect_github" } : {},
|
|
90237
|
-
error: errorFromBody(body,
|
|
90285
|
+
error: errorFromBody(body, `${input.label} request failed with status ${response.status}.`),
|
|
90238
90286
|
data: body
|
|
90239
90287
|
};
|
|
90240
|
-
const token = typeof body === "object" && body !== null ? body.
|
|
90288
|
+
const token = typeof body === "object" && body !== null ? body[input.responseField] : null;
|
|
90241
90289
|
if (typeof token !== "string" || token.trim().length === 0) return invalidInstallationTokenResult();
|
|
90242
90290
|
return {
|
|
90243
90291
|
ok: true,
|
|
@@ -90256,6 +90304,25 @@ var GitHubBroker = class {
|
|
|
90256
90304
|
const branch = result.result.stdout.trim();
|
|
90257
90305
|
return branch.length > 0 ? branch : null;
|
|
90258
90306
|
}
|
|
90307
|
+
async resolveRemoteDefaultBranch(cwd) {
|
|
90308
|
+
const result = await this.runGit([
|
|
90309
|
+
"-C",
|
|
90310
|
+
cwd,
|
|
90311
|
+
"ls-remote",
|
|
90312
|
+
"--symref",
|
|
90313
|
+
"origin",
|
|
90314
|
+
"HEAD"
|
|
90315
|
+
], { allowNonZeroExit: true });
|
|
90316
|
+
if (!isGitRunResult(result)) return result;
|
|
90317
|
+
if (result.result.code !== 0) return gitCommandFailure("GITHUB_DEFAULT_BRANCH_LOOKUP_FAILED", result.result.stderr, "Could not determine the repository default branch.");
|
|
90318
|
+
const branch = /^ref:\s+refs\/heads\/([^\s]+)\s+HEAD$/m.exec(result.result.stdout)?.[1];
|
|
90319
|
+
if (branch === void 0) return {
|
|
90320
|
+
ok: false,
|
|
90321
|
+
code: "GITHUB_DEFAULT_BRANCH_RESPONSE_INVALID",
|
|
90322
|
+
error: "GitHub did not return a valid default branch for the repository."
|
|
90323
|
+
};
|
|
90324
|
+
return validateGitBranchName(branch) ?? branch;
|
|
90325
|
+
}
|
|
90259
90326
|
};
|
|
90260
90327
|
function isCmmdCloudRuntimeModeEnv() {
|
|
90261
90328
|
return process.env.FORGE_CMMD_RUNTIME_MODE === "true" || process.env.FORGE_CMMD_RUNTIME_MODE === "1";
|
|
@@ -90340,20 +90407,40 @@ function validateCloneDestination(destination) {
|
|
|
90340
90407
|
code: "GITHUB_CLONE_DESTINATION_INVALID",
|
|
90341
90408
|
error: "An absolute clone destination is required."
|
|
90342
90409
|
};
|
|
90343
|
-
if (existsSync(destination)) return
|
|
90410
|
+
if (existsSync(destination)) return cloneDestinationExistsResult();
|
|
90411
|
+
return null;
|
|
90412
|
+
}
|
|
90413
|
+
function cloneDestinationExistsResult() {
|
|
90414
|
+
return {
|
|
90344
90415
|
ok: false,
|
|
90345
90416
|
code: "GITHUB_CLONE_DESTINATION_EXISTS",
|
|
90346
90417
|
error: "Clone destination already exists; choose a new empty path."
|
|
90347
90418
|
};
|
|
90348
|
-
|
|
90419
|
+
}
|
|
90420
|
+
function isNodeErrorWithCode(error, code) {
|
|
90421
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
90422
|
+
}
|
|
90423
|
+
async function removeFailedCloneDestination(destination, failure) {
|
|
90424
|
+
try {
|
|
90425
|
+
await rm(destination, {
|
|
90426
|
+
recursive: true,
|
|
90427
|
+
force: true
|
|
90428
|
+
});
|
|
90429
|
+
return failure;
|
|
90430
|
+
} catch {
|
|
90431
|
+
return {
|
|
90432
|
+
...failure,
|
|
90433
|
+
error: `${failure.error ?? "Clone failed."} The incomplete clone destination could not be removed.`
|
|
90434
|
+
};
|
|
90435
|
+
}
|
|
90349
90436
|
}
|
|
90350
90437
|
function validateCloneInput(input) {
|
|
90351
90438
|
const repoFullNameValidation = validateRepoFullName(input.repoFullName);
|
|
90352
90439
|
if (repoFullNameValidation) return repoFullNameValidation;
|
|
90353
90440
|
const destinationValidation = validateCloneDestination(input.destination);
|
|
90354
90441
|
if (destinationValidation) return destinationValidation;
|
|
90355
|
-
const branch = input.branch?.trim() ||
|
|
90356
|
-
return validateGitBranchName(branch) ?? { branch };
|
|
90442
|
+
const branch = input.branch?.trim() || null;
|
|
90443
|
+
return branch === null ? { branch } : validateGitBranchName(branch) ?? { branch };
|
|
90357
90444
|
}
|
|
90358
90445
|
function validateGitBranchName(branch) {
|
|
90359
90446
|
if (branch.length === 0 || branch.startsWith("-") || Array.from(branch).some((character) => {
|
|
@@ -93331,7 +93418,7 @@ const launchDetached = (launch) => gen(function* () {
|
|
|
93331
93418
|
});
|
|
93332
93419
|
const OpenLive = effect(Open, gen(function* () {
|
|
93333
93420
|
const open = yield* tryPromise({
|
|
93334
|
-
try: () => import("./open-
|
|
93421
|
+
try: () => import("./open-FIgTDosf.mjs"),
|
|
93335
93422
|
catch: (cause) => new OpenError$1({
|
|
93336
93423
|
message: "failed to load browser opener",
|
|
93337
93424
|
cause
|
|
@@ -93518,6 +93605,17 @@ const admitNormalizedDispatchCommand = (command, admit) => uninterruptibleMask$1
|
|
|
93518
93605
|
//#region src/orchestration/bootstrapCommandCoordinator.ts
|
|
93519
93606
|
const MAX_COMPLETED_COMMANDS_PER_ENGINE = 256;
|
|
93520
93607
|
const commandsByEngine = /* @__PURE__ */ new WeakMap();
|
|
93608
|
+
const sealBootstrapCommand = (engine, commandId) => {
|
|
93609
|
+
const entry = commandsByEngine.get(engine)?.get(commandId);
|
|
93610
|
+
if (entry) entry.cancellable = false;
|
|
93611
|
+
};
|
|
93612
|
+
const cancelBootstrapCommand = (engine, threadId) => promise(async () => {
|
|
93613
|
+
const entry = [...commandsByEngine.get(engine)?.values() ?? []].find((candidate) => candidate.threadId === threadId && !candidate.completed && candidate.cancellable);
|
|
93614
|
+
if (!entry) return false;
|
|
93615
|
+
entry.controller.abort();
|
|
93616
|
+
await entry.promise.catch(() => void 0);
|
|
93617
|
+
return true;
|
|
93618
|
+
});
|
|
93521
93619
|
const toBootstrapError = (error) => is$1(OrchestrationDispatchCommandError)(error) ? error : new OrchestrationDispatchCommandError({
|
|
93522
93620
|
message: error instanceof Error ? error.message : "Bootstrap command failed.",
|
|
93523
93621
|
cause: error
|
|
@@ -93537,7 +93635,7 @@ const pruneCompletedCommands = (commands) => {
|
|
|
93537
93635
|
* the registry to one server runtime, so reconnects share work while separate
|
|
93538
93636
|
* runtimes remain isolated.
|
|
93539
93637
|
*/
|
|
93540
|
-
const runBootstrapCommand = (engine, commandId, bootstrapEffect) => {
|
|
93638
|
+
const runBootstrapCommand = (engine, commandId, bootstrapEffect, threadId) => {
|
|
93541
93639
|
let commands = commandsByEngine.get(engine);
|
|
93542
93640
|
if (commands === void 0) {
|
|
93543
93641
|
commands = /* @__PURE__ */ new Map();
|
|
@@ -93550,16 +93648,21 @@ const runBootstrapCommand = (engine, commandId, bootstrapEffect) => {
|
|
|
93550
93648
|
});
|
|
93551
93649
|
pruneCompletedCommands(commands);
|
|
93552
93650
|
let entry;
|
|
93553
|
-
const
|
|
93651
|
+
const controller = new AbortController();
|
|
93652
|
+
const promise = Promise.resolve().then(() => runPromise(bootstrapEffect, { signal: controller.signal })).then((result) => {
|
|
93554
93653
|
entry.completed = true;
|
|
93555
93654
|
return result;
|
|
93556
93655
|
}, (error) => {
|
|
93557
|
-
|
|
93656
|
+
entry.completed = true;
|
|
93657
|
+
if (!controller.signal.aborted) commands.delete(commandId);
|
|
93558
93658
|
throw error;
|
|
93559
93659
|
});
|
|
93560
93660
|
entry = {
|
|
93561
93661
|
promise,
|
|
93562
|
-
completed: false
|
|
93662
|
+
completed: false,
|
|
93663
|
+
threadId,
|
|
93664
|
+
controller,
|
|
93665
|
+
cancellable: true
|
|
93563
93666
|
};
|
|
93564
93667
|
commands.set(commandId, entry);
|
|
93565
93668
|
return tryPromise({
|
|
@@ -93569,6 +93672,10 @@ const runBootstrapCommand = (engine, commandId, bootstrapEffect) => {
|
|
|
93569
93672
|
};
|
|
93570
93673
|
//#endregion
|
|
93571
93674
|
//#region src/orchestration/bootstrapDispatch.ts
|
|
93675
|
+
const interruptBootstrapTurnStart = (engine, command) => gen(function* () {
|
|
93676
|
+
if (yield* cancelBootstrapCommand(engine, command.threadId)) return { sequence: (yield* engine.getReadModel()).snapshotSequence };
|
|
93677
|
+
return yield* engine.dispatch(command);
|
|
93678
|
+
});
|
|
93572
93679
|
const MAX_BOOTSTRAP_OUTPUT_LINE_LENGTH = 1e3;
|
|
93573
93680
|
const toBootstrapDispatchCommandCauseError = (cause) => {
|
|
93574
93681
|
const error = squash(cause);
|
|
@@ -93655,6 +93762,7 @@ const prepareBootstrapWorktree = (input) => gen(function* () {
|
|
|
93655
93762
|
const requestedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
93656
93763
|
const baseBranchLabel = bootstrapWorktree.baseBranch ?? "<default>";
|
|
93657
93764
|
const requestedPayload = {
|
|
93765
|
+
turnRequestedAt: input.command.createdAt,
|
|
93658
93766
|
projectCwd: bootstrapWorktree.projectCwd,
|
|
93659
93767
|
baseBranch: bootstrapWorktree.baseBranch,
|
|
93660
93768
|
branch: bootstrapWorktree.branch,
|
|
@@ -93675,6 +93783,16 @@ const prepareBootstrapWorktree = (input) => gen(function* () {
|
|
|
93675
93783
|
branch: bootstrapWorktree.baseBranch,
|
|
93676
93784
|
newBranch: bootstrapWorktree.branch,
|
|
93677
93785
|
path: null,
|
|
93786
|
+
onStage: (update) => appendWorktreeActivity({
|
|
93787
|
+
orchestrationEngine: input.orchestrationEngine,
|
|
93788
|
+
threadId: input.command.threadId,
|
|
93789
|
+
commandId: CommandId.make(`server:worktree-stage:${input.command.commandId}:${crypto.randomUUID()}`),
|
|
93790
|
+
kind: "worktree.stage",
|
|
93791
|
+
summary: "Preparing worktree",
|
|
93792
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
93793
|
+
payload: update,
|
|
93794
|
+
tone: "info"
|
|
93795
|
+
}).pipe(asVoid, ignore),
|
|
93678
93796
|
progress: {
|
|
93679
93797
|
onStdoutLine: (line) => {
|
|
93680
93798
|
const detail = truncateBootstrapOutputLine(line);
|
|
@@ -93714,6 +93832,7 @@ const prepareBootstrapWorktree = (input) => gen(function* () {
|
|
|
93714
93832
|
}
|
|
93715
93833
|
}
|
|
93716
93834
|
}).pipe(catchCause((cause) => {
|
|
93835
|
+
if (hasInterruptsOnly(cause)) return failCause$1(cause);
|
|
93717
93836
|
const error = squash(cause);
|
|
93718
93837
|
const detail = error instanceof Error ? error.message : "Unknown worktree failure.";
|
|
93719
93838
|
return appendWorktreeActivity({
|
|
@@ -93840,7 +93959,16 @@ const dispatchBootstrapTurnStart = (input, command) => gen(function* () {
|
|
|
93840
93959
|
worktreePath
|
|
93841
93960
|
}),
|
|
93842
93961
|
onSuccess: (setupResult) => {
|
|
93843
|
-
if (setupResult.status !== "started") return
|
|
93962
|
+
if (setupResult.status !== "started") return appendSetupScriptActivity({
|
|
93963
|
+
orchestrationEngine,
|
|
93964
|
+
threadId: command.threadId,
|
|
93965
|
+
commandId: bootstrapCommandId(command, "setup-script-skipped"),
|
|
93966
|
+
kind: "setup-script.skipped",
|
|
93967
|
+
summary: "No setup script configured",
|
|
93968
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
93969
|
+
payload: {},
|
|
93970
|
+
tone: "info"
|
|
93971
|
+
}).pipe(asVoid, ignore);
|
|
93844
93972
|
return recordSetupScriptStarted({
|
|
93845
93973
|
requestedAt,
|
|
93846
93974
|
worktreePath,
|
|
@@ -93870,13 +93998,33 @@ const dispatchBootstrapTurnStart = (input, command) => gen(function* () {
|
|
|
93870
93998
|
targetProjectCwd = preparedWorktree.projectCwd;
|
|
93871
93999
|
}
|
|
93872
94000
|
yield* runSetupProgram();
|
|
94001
|
+
if (bootstrap?.prepareWorktree) yield* appendWorktreeActivity({
|
|
94002
|
+
orchestrationEngine,
|
|
94003
|
+
threadId: command.threadId,
|
|
94004
|
+
commandId: bootstrapCommandId(command, "launch-agent-starting"),
|
|
94005
|
+
kind: "launch.agent-starting",
|
|
94006
|
+
summary: "Starting agent",
|
|
94007
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
94008
|
+
payload: { setupRequested: bootstrap.runSetupScript === true },
|
|
94009
|
+
tone: "info"
|
|
94010
|
+
}).pipe(ignore);
|
|
94011
|
+
sealBootstrapCommand(orchestrationEngine, command.commandId);
|
|
93873
94012
|
return yield* orchestrationEngine.dispatch(finalTurnStartCommand);
|
|
93874
94013
|
});
|
|
93875
|
-
return yield* runBootstrapCommand(orchestrationEngine, command.commandId, bootstrapProgram.pipe(
|
|
94014
|
+
return yield* runBootstrapCommand(orchestrationEngine, command.commandId, bootstrapProgram.pipe(onInterrupt(() => appendWorktreeActivity({
|
|
94015
|
+
orchestrationEngine,
|
|
94016
|
+
threadId: command.threadId,
|
|
94017
|
+
commandId: bootstrapCommandId(command, "launch-cancelled"),
|
|
94018
|
+
kind: "launch.cancelled",
|
|
94019
|
+
summary: "Launch cancelled",
|
|
94020
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
94021
|
+
payload: {},
|
|
94022
|
+
tone: "info"
|
|
94023
|
+
}).pipe(ignore)), catchCause((cause) => {
|
|
93876
94024
|
const dispatchError = toBootstrapDispatchCommandCauseError(cause);
|
|
93877
94025
|
if (hasInterruptsOnly(cause)) return fail(dispatchError);
|
|
93878
94026
|
return cleanupCreatedThread().pipe(flatMap(() => fail(dispatchError)));
|
|
93879
|
-
})));
|
|
94027
|
+
})), command.threadId);
|
|
93880
94028
|
});
|
|
93881
94029
|
//#endregion
|
|
93882
94030
|
//#region src/orchestration/Services/OrchestrationEngine.ts
|
|
@@ -100555,6 +100703,7 @@ function emptyConfig(source, path) {
|
|
|
100555
100703
|
terminals: [],
|
|
100556
100704
|
systemPackages: [],
|
|
100557
100705
|
secrets: [],
|
|
100706
|
+
repositoryDependencies: [],
|
|
100558
100707
|
issues: []
|
|
100559
100708
|
};
|
|
100560
100709
|
}
|
|
@@ -100640,6 +100789,7 @@ function readConfigFile(source, path) {
|
|
|
100640
100789
|
terminals: terminalsFromValue(parsed.terminals),
|
|
100641
100790
|
systemPackages: stringArray(parsed.systemPackages ?? parsed.aptPackages ?? parsed.packages),
|
|
100642
100791
|
secrets: stringArray(parsed.secrets ?? parsed.envSecrets),
|
|
100792
|
+
repositoryDependencies: stringArray(parsed.repositoryDependencies),
|
|
100643
100793
|
issues: []
|
|
100644
100794
|
};
|
|
100645
100795
|
}
|
|
@@ -101052,6 +101202,7 @@ const EMPTY_WORKSPACE_ENVIRONMENT_CONFIG = {
|
|
|
101052
101202
|
terminals: [],
|
|
101053
101203
|
systemPackages: [],
|
|
101054
101204
|
secrets: [],
|
|
101205
|
+
repositoryDependencies: [],
|
|
101055
101206
|
issues: []
|
|
101056
101207
|
};
|
|
101057
101208
|
function buildCwdCheck(cwdExists) {
|
|
@@ -105854,7 +106005,7 @@ const makeWsRpcLayer = (currentSessionId, currentUserId) => WsRpcGroup.toLayer(g
|
|
|
105854
106005
|
git,
|
|
105855
106006
|
gitStatusBroadcaster,
|
|
105856
106007
|
projectSetupScriptRunner
|
|
105857
|
-
}, normalizedCommand) : orchestrationEngine.dispatch(normalizedCommand).pipe(mapError((cause) => toDispatchCommandError(cause, "Failed to dispatch orchestration command")));
|
|
106008
|
+
}, normalizedCommand) : (normalizedCommand.type === "thread.turn.interrupt" ? interruptBootstrapTurnStart(orchestrationEngine, normalizedCommand) : orchestrationEngine.dispatch(normalizedCommand)).pipe(mapError((cause) => toDispatchCommandError(cause, "Failed to dispatch orchestration command")));
|
|
105858
106009
|
return startup.enqueueCommand(dispatchEffect).pipe(mapError((cause) => toDispatchCommandError(cause, "Failed to dispatch orchestration command")));
|
|
105859
106010
|
};
|
|
105860
106011
|
const loadServerConfig = gen(function* () {
|
|
@@ -151203,6 +151354,86 @@ async function attestCodexLocalAccountIdentity(input) {
|
|
|
151203
151354
|
return identity;
|
|
151204
151355
|
}
|
|
151205
151356
|
//#endregion
|
|
151357
|
+
//#region src/workspace/workspaceRepositoryDependencies.ts
|
|
151358
|
+
function repositoryFullName(value) {
|
|
151359
|
+
return value.trim().match(/^(?:https?:\/\/)?github\.com\/([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+?)(?:\.git)?\/?$/i)?.[1] ?? null;
|
|
151360
|
+
}
|
|
151361
|
+
function dependencyDestination(cloudProjectsRoot, repoFullName) {
|
|
151362
|
+
const root = resolve(cloudProjectsRoot);
|
|
151363
|
+
const destination = resolve(join(root, basename(repoFullName)));
|
|
151364
|
+
const pathFromRoot = relative(root, destination);
|
|
151365
|
+
if (pathFromRoot.startsWith("..") || pathFromRoot === "") throw new Error(`Repository dependency ${repoFullName} has an unsafe destination.`);
|
|
151366
|
+
return destination;
|
|
151367
|
+
}
|
|
151368
|
+
async function readOriginFromGit(destination) {
|
|
151369
|
+
const result = await runProcess("git", [
|
|
151370
|
+
"-C",
|
|
151371
|
+
destination,
|
|
151372
|
+
"remote",
|
|
151373
|
+
"get-url",
|
|
151374
|
+
"origin"
|
|
151375
|
+
], {
|
|
151376
|
+
allowNonZeroExit: true,
|
|
151377
|
+
timeoutMs: 1e4
|
|
151378
|
+
});
|
|
151379
|
+
return result.code === 0 ? result.stdout.trim() : null;
|
|
151380
|
+
}
|
|
151381
|
+
function resolveRepositoryDependencies(declarations, cloudProjectsRoot) {
|
|
151382
|
+
const destinations = /* @__PURE__ */ new Set();
|
|
151383
|
+
return declarations.map((declaration) => {
|
|
151384
|
+
const repoFullName = repositoryFullName(declaration);
|
|
151385
|
+
if (repoFullName === null) throw new Error(`Unsupported repository dependency: ${declaration}`);
|
|
151386
|
+
const destination = dependencyDestination(cloudProjectsRoot, repoFullName);
|
|
151387
|
+
if (destinations.has(destination)) throw new Error(`Repository dependencies collide at ${destination}.`);
|
|
151388
|
+
destinations.add(destination);
|
|
151389
|
+
return {
|
|
151390
|
+
repoFullName,
|
|
151391
|
+
destination
|
|
151392
|
+
};
|
|
151393
|
+
});
|
|
151394
|
+
}
|
|
151395
|
+
async function prepareRepositoryDependency(input) {
|
|
151396
|
+
const { repoFullName, destination } = input.dependency;
|
|
151397
|
+
if (existsSync(destination)) {
|
|
151398
|
+
const origin = await input.readOrigin(destination);
|
|
151399
|
+
const existingRepo = origin === null ? null : parseRepoFullNameFromRemoteUrl(origin);
|
|
151400
|
+
if (existingRepo?.toLowerCase() !== repoFullName.toLowerCase()) throw new Error(`Repository dependency destination ${destination} contains ${existingRepo ?? "no GitHub repository"} instead of ${repoFullName}.`);
|
|
151401
|
+
return {
|
|
151402
|
+
repoFullName,
|
|
151403
|
+
destination,
|
|
151404
|
+
outcome: "existing"
|
|
151405
|
+
};
|
|
151406
|
+
}
|
|
151407
|
+
const result = await input.broker.cloneRepository(input.auth, {
|
|
151408
|
+
repoFullName,
|
|
151409
|
+
destination
|
|
151410
|
+
});
|
|
151411
|
+
if (!result.ok) throw new Error(`Could not prepare repository dependency ${repoFullName}: ${result.error ?? result.code ?? "clone failed"}`);
|
|
151412
|
+
return {
|
|
151413
|
+
repoFullName,
|
|
151414
|
+
destination,
|
|
151415
|
+
outcome: "cloned"
|
|
151416
|
+
};
|
|
151417
|
+
}
|
|
151418
|
+
async function prepareWorkspaceRepositoryDependencies(input) {
|
|
151419
|
+
if (!input.runtimeMode) return [];
|
|
151420
|
+
const dependencies = resolveWorkspaceEnvironmentConfig(input.cwd).repositoryDependencies;
|
|
151421
|
+
if (dependencies.length === 0) return [];
|
|
151422
|
+
const broker = input.broker ?? new GitHubBroker();
|
|
151423
|
+
const auth = broker.runtimeGrantAuthContext("scm");
|
|
151424
|
+
if (auth === null) throw new Error("Repository dependencies require an exact scoped runtime SCM grant.");
|
|
151425
|
+
const readOrigin = input.readOrigin ?? readOriginFromGit;
|
|
151426
|
+
const resolved = resolveRepositoryDependencies(dependencies, input.cloudProjectsRoot);
|
|
151427
|
+
const prepared = [];
|
|
151428
|
+
for (const dependency of resolved) prepared.push(await prepareRepositoryDependency({
|
|
151429
|
+
dependency,
|
|
151430
|
+
broker,
|
|
151431
|
+
auth,
|
|
151432
|
+
readOrigin
|
|
151433
|
+
}));
|
|
151434
|
+
return prepared;
|
|
151435
|
+
}
|
|
151436
|
+
//#endregion
|
|
151206
151437
|
//#region src/codexAppServerManager.ts
|
|
151207
151438
|
const CODEX_LOGIN_STATUS_TIMEOUT_MS = 5e3;
|
|
151208
151439
|
const CODEX_SKILLS_LIST_TIMEOUT_MS = 4e3;
|
|
@@ -151537,6 +151768,11 @@ var CodexAppServerManager = class extends EventEmitter$1 {
|
|
|
151537
151768
|
let context;
|
|
151538
151769
|
try {
|
|
151539
151770
|
const resolvedCwd = input.cwd ?? process.cwd();
|
|
151771
|
+
await prepareWorkspaceRepositoryDependencies({
|
|
151772
|
+
cwd: resolvedCwd,
|
|
151773
|
+
cloudProjectsRoot: process.env.FORGE_CLOUD_PROJECTS_ROOT?.trim() || "/projects",
|
|
151774
|
+
runtimeMode: process.env.FORGE_CMMD_RUNTIME_MODE === "true"
|
|
151775
|
+
});
|
|
151540
151776
|
let workspacePreflightReport = runWorkspaceEnvironmentPreflight({
|
|
151541
151777
|
cwd: resolvedCwd,
|
|
151542
151778
|
env: process.env
|
|
@@ -190311,7 +190547,7 @@ var Vce = {
|
|
|
190311
190547
|
function Ve() {
|
|
190312
190548
|
return Vce;
|
|
190313
190549
|
}
|
|
190314
|
-
var Us =
|
|
190550
|
+
var Us = os.homedir(), lk = os.tmpdir(), { env: Vc } = process$1, Yce = (e) => {
|
|
190315
190551
|
let t = path.join(Us, "Library");
|
|
190316
190552
|
return {
|
|
190317
190553
|
data: path.join(t, "Application Support", e),
|
|
@@ -200511,12 +200747,12 @@ function qZ(e, t) {
|
|
|
200511
200747
|
}
|
|
200512
200748
|
return n;
|
|
200513
200749
|
}
|
|
200514
|
-
var os$
|
|
200750
|
+
var os$2 = "https://code.claude.com/docs/en", kKe = [
|
|
200515
200751
|
{
|
|
200516
200752
|
matches: (e) => e.path === "permissions.defaultMode" && e.code === "invalid_value",
|
|
200517
200753
|
tip: {
|
|
200518
200754
|
suggestion: "Valid modes: \"acceptEdits\" (ask before file changes), \"plan\" (analysis only), \"bypassPermissions\" (auto-accept all), or \"default\" (standard behavior)",
|
|
200519
|
-
docLink: `${os$
|
|
200755
|
+
docLink: `${os$2}/iam#permission-modes`
|
|
200520
200756
|
}
|
|
200521
200757
|
},
|
|
200522
200758
|
{
|
|
@@ -200531,7 +200767,7 @@ var os$1 = "https://code.claude.com/docs/en", kKe = [
|
|
|
200531
200767
|
matches: (e) => e.path.startsWith("env.") && e.code === "invalid_type",
|
|
200532
200768
|
tip: {
|
|
200533
200769
|
suggestion: "Environment variables must be strings. Wrap numbers and booleans in quotes. Example: \"DEBUG\": \"true\", \"PORT\": \"3000\"",
|
|
200534
|
-
docLink: `${os$
|
|
200770
|
+
docLink: `${os$2}/settings#environment-variables`
|
|
200535
200771
|
}
|
|
200536
200772
|
},
|
|
200537
200773
|
{
|
|
@@ -200542,14 +200778,14 @@ var os$1 = "https://code.claude.com/docs/en", kKe = [
|
|
|
200542
200778
|
matches: (e) => e.path.startsWith("hooks.") && e.code === "invalid_key",
|
|
200543
200779
|
tip: {
|
|
200544
200780
|
suggestion: "Not a recognized hook event. Common events: PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, SessionEnd, Stop. Check spelling and capitalization.",
|
|
200545
|
-
docLink: `${os$
|
|
200781
|
+
docLink: `${os$2}/hooks`
|
|
200546
200782
|
}
|
|
200547
200783
|
},
|
|
200548
200784
|
{
|
|
200549
200785
|
matches: (e) => /\.hooks\.\d+\.command$/.test(e.path) && e.code === "invalid_type" && e.received === "undefined",
|
|
200550
200786
|
tip: {
|
|
200551
200787
|
suggestion: "Command hooks require `command`. For exec form (no shell), set `command` to the executable and `args` to its arguments: {\"type\": \"command\", \"command\": \"echo\", \"args\": [\"hi\"]}. For shell form, set `command` to the full shell string: {\"type\": \"command\", \"command\": \"echo hi\"}.",
|
|
200552
|
-
docLink: `${os$
|
|
200788
|
+
docLink: `${os$2}/hooks#exec-form-and-shell-form`
|
|
200553
200789
|
}
|
|
200554
200790
|
},
|
|
200555
200791
|
{
|
|
@@ -200564,7 +200800,7 @@ var os$1 = "https://code.claude.com/docs/en", kKe = [
|
|
|
200564
200800
|
matches: (e) => e.code === "unrecognized_keys",
|
|
200565
200801
|
tip: {
|
|
200566
200802
|
suggestion: "Check for typos or refer to the documentation for valid fields",
|
|
200567
|
-
docLink: `${os$
|
|
200803
|
+
docLink: `${os$2}/settings`
|
|
200568
200804
|
}
|
|
200569
200805
|
},
|
|
200570
200806
|
{
|
|
@@ -200579,13 +200815,13 @@ var os$1 = "https://code.claude.com/docs/en", kKe = [
|
|
|
200579
200815
|
matches: (e) => e.path === "permissions.additionalDirectories" && e.code === "invalid_type",
|
|
200580
200816
|
tip: {
|
|
200581
200817
|
suggestion: "Must be an array of directory paths. Example: [\"~/projects\", \"/tmp/workspace\"]. You can also use --add-dir flag or /add-dir command",
|
|
200582
|
-
docLink: `${os$
|
|
200818
|
+
docLink: `${os$2}/iam#working-directories`
|
|
200583
200819
|
}
|
|
200584
200820
|
}
|
|
200585
200821
|
], AKe = {
|
|
200586
|
-
permissions: `${os$
|
|
200587
|
-
env: `${os$
|
|
200588
|
-
hooks: `${os$
|
|
200822
|
+
permissions: `${os$2}/iam#configuring-permissions`,
|
|
200823
|
+
env: `${os$2}/settings#environment-variables`,
|
|
200824
|
+
hooks: `${os$2}/hooks`
|
|
200589
200825
|
};
|
|
200590
200826
|
function GZ(e) {
|
|
200591
200827
|
let t = kKe.find((r) => r.matches(e));
|
|
@@ -216617,6 +216853,19 @@ const makeClaudeAdapter = fn$1("makeClaudeAdapter")(function* (options) {
|
|
|
216617
216853
|
const resumeState = readClaudeResumeState(input.resumeCursor);
|
|
216618
216854
|
const threadId = input.threadId;
|
|
216619
216855
|
const { existingResumeSessionId, newSessionId, sessionId } = yield* resolveClaudeStartSessionIds(resumeState);
|
|
216856
|
+
const workspaceCwd = input.cwd;
|
|
216857
|
+
if (workspaceCwd) yield* tryPromise({
|
|
216858
|
+
try: () => prepareWorkspaceRepositoryDependencies({
|
|
216859
|
+
cwd: workspaceCwd,
|
|
216860
|
+
cloudProjectsRoot: serverConfig.cloudProjectsRoot ?? "/projects",
|
|
216861
|
+
runtimeMode: serverConfig.forgeCmmdRuntimeMode === true
|
|
216862
|
+
}),
|
|
216863
|
+
catch: (cause) => new ProviderAdapterValidationError({
|
|
216864
|
+
provider: PROVIDER$11,
|
|
216865
|
+
operation: "startSession",
|
|
216866
|
+
issue: cause instanceof Error ? cause.message : "Could not prepare declared repository dependencies."
|
|
216867
|
+
})
|
|
216868
|
+
});
|
|
216620
216869
|
const runtimeContext = yield* context();
|
|
216621
216870
|
const runFork = runForkWith(runtimeContext);
|
|
216622
216871
|
const runPromise = runPromiseWith(runtimeContext);
|
|
@@ -232923,12 +233172,12 @@ const collectOutput = fn$1("collectOutput")(function* (input, stream, maxOutputB
|
|
|
232923
233172
|
let lineBuffer = "";
|
|
232924
233173
|
let truncated = false;
|
|
232925
233174
|
const emitCompleteLines = fn$1("emitCompleteLines")(function* (flush) {
|
|
232926
|
-
let newlineIndex = lineBuffer.
|
|
233175
|
+
let newlineIndex = lineBuffer.search(/[\r\n]/);
|
|
232927
233176
|
while (newlineIndex >= 0) {
|
|
232928
233177
|
const line = lineBuffer.slice(0, newlineIndex).replace(/\r$/, "");
|
|
232929
233178
|
lineBuffer = lineBuffer.slice(newlineIndex + 1);
|
|
232930
233179
|
if (line.length > 0 && onLine) yield* onLine(line);
|
|
232931
|
-
newlineIndex = lineBuffer.
|
|
233180
|
+
newlineIndex = lineBuffer.search(/[\r\n]/);
|
|
232932
233181
|
}
|
|
232933
233182
|
if (flush) {
|
|
232934
233183
|
const trailing = lineBuffer.replace(/\r$/, "");
|
|
@@ -233076,6 +233325,7 @@ const GitCoreLive = effect(GitCore, fn$1("makeGitCore")(function* (options) {
|
|
|
233076
233325
|
operation,
|
|
233077
233326
|
cwd,
|
|
233078
233327
|
args,
|
|
233328
|
+
...options.env ? { env: options.env } : {},
|
|
233079
233329
|
...options.stdin !== void 0 ? { stdin: options.stdin } : {},
|
|
233080
233330
|
allowNonZeroExit: true,
|
|
233081
233331
|
...options.timeoutMs !== void 0 ? { timeoutMs: options.timeoutMs } : {},
|
|
@@ -233797,12 +234047,19 @@ const GitCoreLive = effect(GitCore, fn$1("makeGitCore")(function* (options) {
|
|
|
233797
234047
|
};
|
|
233798
234048
|
});
|
|
233799
234049
|
const createWorktree = fn$1("createWorktree")(function* (input) {
|
|
234050
|
+
const report = (stage, status, detail) => input.onStage?.({
|
|
234051
|
+
stage,
|
|
234052
|
+
status,
|
|
234053
|
+
...detail ? { detail } : {}
|
|
234054
|
+
}) ?? void_$1;
|
|
234055
|
+
yield* report("resolve", "running");
|
|
233800
234056
|
const base = input.branch ?? (yield* resolveDefaultBaseBranch(input.cwd));
|
|
233801
234057
|
const startPoint = yield* resolveWorktreeStartPoint({
|
|
233802
234058
|
cwd: input.cwd,
|
|
233803
234059
|
base,
|
|
233804
234060
|
creatingNewBranch: input.newBranch !== void 0
|
|
233805
234061
|
});
|
|
234062
|
+
yield* report("resolve", "done", startPoint);
|
|
233806
234063
|
const targetBranch = input.newBranch ?? base;
|
|
233807
234064
|
const sanitizedBranch = targetBranch.replace(/\//g, "-");
|
|
233808
234065
|
const repoName = path$10.basename(input.cwd);
|
|
@@ -233814,7 +234071,10 @@ const GitCoreLive = effect(GitCore, fn$1("makeGitCore")(function* (options) {
|
|
|
233814
234071
|
limit: 200
|
|
233815
234072
|
})).branches.find((branch) => branch.isRemote !== true && branch.name === targetBranch && branch.worktreePath !== null && path.resolve(branch.worktreePath) === canonicalWorktreePath);
|
|
233816
234073
|
if (existingBranch?.worktreePath) {
|
|
234074
|
+
yield* report("checkout", "skipped", "Existing worktree");
|
|
234075
|
+
yield* report("dependencies", "running");
|
|
233817
234076
|
yield* setupSharedWorktreeDependencies(input.cwd, existingBranch.worktreePath);
|
|
234077
|
+
yield* report("dependencies", "done");
|
|
233818
234078
|
return { worktree: {
|
|
233819
234079
|
path: worktreePath,
|
|
233820
234080
|
branch: targetBranch
|
|
@@ -233833,11 +234093,19 @@ const GitCoreLive = effect(GitCore, fn$1("makeGitCore")(function* (options) {
|
|
|
233833
234093
|
worktreePath,
|
|
233834
234094
|
startPoint
|
|
233835
234095
|
];
|
|
234096
|
+
yield* report("checkout", "running");
|
|
233836
234097
|
yield* executeGit("GitCore.createWorktree", input.cwd, args, {
|
|
233837
234098
|
fallbackErrorMessage: "git worktree add failed",
|
|
234099
|
+
env: {
|
|
234100
|
+
GIT_PROGRESS_DELAY: "0",
|
|
234101
|
+
LC_ALL: "C"
|
|
234102
|
+
},
|
|
233838
234103
|
...input.progress ? { progress: input.progress } : {}
|
|
233839
234104
|
});
|
|
234105
|
+
yield* report("checkout", "done");
|
|
234106
|
+
yield* report("dependencies", "running");
|
|
233840
234107
|
yield* setupSharedWorktreeDependencies(input.cwd, worktreePath);
|
|
234108
|
+
yield* report("dependencies", "done");
|
|
233841
234109
|
return { worktree: {
|
|
233842
234110
|
path: worktreePath,
|
|
233843
234111
|
branch: targetBranch
|
|
@@ -267442,7 +267710,7 @@ var import_multicast_dns = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMi
|
|
|
267442
267710
|
var dgram = __require("dgram");
|
|
267443
267711
|
var thunky = require_thunky();
|
|
267444
267712
|
var events = __require("events");
|
|
267445
|
-
var os = __require("os");
|
|
267713
|
+
var os$1 = __require("os");
|
|
267446
267714
|
var noop = function() {};
|
|
267447
267715
|
module.exports = function(opts) {
|
|
267448
267716
|
if (!opts) opts = {};
|
|
@@ -267573,14 +267841,14 @@ var import_multicast_dns = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMi
|
|
|
267573
267841
|
return that;
|
|
267574
267842
|
};
|
|
267575
267843
|
function defaultInterface() {
|
|
267576
|
-
var networks = os.networkInterfaces();
|
|
267844
|
+
var networks = os$1.networkInterfaces();
|
|
267577
267845
|
var names = Object.keys(networks);
|
|
267578
267846
|
for (var i = 0; i < names.length; i++) {
|
|
267579
267847
|
var net = networks[names[i]];
|
|
267580
267848
|
for (var j = 0; j < net.length; j++) {
|
|
267581
267849
|
var iface = net[j];
|
|
267582
267850
|
if (isIPv4(iface.family) && !iface.internal) {
|
|
267583
|
-
if (os.platform() === "darwin" && names[i] === "en0") return iface.address;
|
|
267851
|
+
if (os$1.platform() === "darwin" && names[i] === "en0") return iface.address;
|
|
267584
267852
|
return "0.0.0.0";
|
|
267585
267853
|
}
|
|
267586
267854
|
}
|
|
@@ -267588,7 +267856,7 @@ var import_multicast_dns = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMi
|
|
|
267588
267856
|
return "127.0.0.1";
|
|
267589
267857
|
}
|
|
267590
267858
|
function allInterfaces() {
|
|
267591
|
-
var networks = os.networkInterfaces();
|
|
267859
|
+
var networks = os$1.networkInterfaces();
|
|
267592
267860
|
var names = Object.keys(networks);
|
|
267593
267861
|
var res = [];
|
|
267594
267862
|
for (var i = 0; i < names.length; i++) {
|
|
@@ -296549,7 +296817,7 @@ function resolveBuildCommitFromEnv(env) {
|
|
|
296549
296817
|
* environment descriptor down instead of reporting an honest "unknown".
|
|
296550
296818
|
*/
|
|
296551
296819
|
function readBakedBuildCommit() {
|
|
296552
|
-
return "
|
|
296820
|
+
return "339f0da718657526651ad84cacb841446f1bb38b";
|
|
296553
296821
|
}
|
|
296554
296822
|
async function resolveServerBuildCommit(input) {
|
|
296555
296823
|
if (isFullCommitSha(input.baked)) return input.baked;
|
|
@@ -298361,6 +298629,10 @@ const AuthSessionRepositoryLive = effect(AuthSessionRepository, gen(function* ()
|
|
|
298361
298629
|
const SIGNING_SECRET_NAME = "server-signing-key";
|
|
298362
298630
|
const DEFAULT_SESSION_TTL = days(30);
|
|
298363
298631
|
const DEFAULT_WEBSOCKET_TOKEN_TTL = minutes(5);
|
|
298632
|
+
const toSessionCredentialError = (message) => (cause) => new SessionCredentialError({
|
|
298633
|
+
message,
|
|
298634
|
+
cause
|
|
298635
|
+
});
|
|
298364
298636
|
const SessionClaims = Struct({
|
|
298365
298637
|
v: Literal(1),
|
|
298366
298638
|
kind: Literal("session"),
|
|
@@ -298417,10 +298689,6 @@ const SessionCredentialServiceLive = effect(SessionCredentialService, gen(functi
|
|
|
298417
298689
|
port: serverConfig.port,
|
|
298418
298690
|
host: serverConfig.host
|
|
298419
298691
|
});
|
|
298420
|
-
const toSessionCredentialError = (message) => (cause) => new SessionCredentialError({
|
|
298421
|
-
message,
|
|
298422
|
-
cause
|
|
298423
|
-
});
|
|
298424
298692
|
const emitUpsert = (clientSession) => publish(changesPubSub, {
|
|
298425
298693
|
type: "clientUpserted",
|
|
298426
298694
|
clientSession
|
|
@@ -298581,15 +298849,28 @@ const SessionCredentialServiceLive = effect(SessionCredentialService, gen(functi
|
|
|
298581
298849
|
if (isSome(row)) {
|
|
298582
298850
|
if (row.value.revokedAt !== null) return yield* new SessionCredentialError({ message: "Websocket session revoked." });
|
|
298583
298851
|
if (row.value.expiresAt.epochMilliseconds <= now) return yield* new SessionCredentialError({ message: "Websocket session expired." });
|
|
298584
|
-
} else
|
|
298852
|
+
} else {
|
|
298853
|
+
const cloudOwnerSession = serverConfig.forgeCloudShellMode === true && claims.method === "proxy-asserted" && forgeCloudOwnerSessionExpiresAt(claims.sid) !== null;
|
|
298854
|
+
if (cloudOwnerSession && isExpiredForgeCloudOwnerSession(claims.sid, now)) return yield* new SessionCredentialError({ message: "Websocket session expired." });
|
|
298855
|
+
if (statelessCookieSessions && (claims.method === "browser-session-cookie" || cloudOwnerSession)) return {
|
|
298856
|
+
sessionId: claims.sid,
|
|
298857
|
+
token,
|
|
298858
|
+
method: claims.method,
|
|
298859
|
+
client: createDefaultClientMetadata(),
|
|
298860
|
+
expiresAt: makeUnsafe$5(claims.exp),
|
|
298861
|
+
subject: claims.sub,
|
|
298862
|
+
role: claims.role
|
|
298863
|
+
};
|
|
298864
|
+
return yield* new SessionCredentialError({ message: "Unknown websocket session." });
|
|
298865
|
+
}
|
|
298585
298866
|
return {
|
|
298586
298867
|
sessionId: claims.sid,
|
|
298587
298868
|
token,
|
|
298588
|
-
method:
|
|
298589
|
-
client:
|
|
298590
|
-
expiresAt:
|
|
298591
|
-
subject:
|
|
298592
|
-
role:
|
|
298869
|
+
method: row.value.method,
|
|
298870
|
+
client: toClientMetadata(row.value.client),
|
|
298871
|
+
expiresAt: row.value.expiresAt,
|
|
298872
|
+
subject: row.value.subject,
|
|
298873
|
+
role: row.value.role
|
|
298593
298874
|
};
|
|
298594
298875
|
}).pipe(mapError((cause) => cause instanceof SessionCredentialError ? cause : new SessionCredentialError({
|
|
298595
298876
|
message: "Failed to verify websocket token.",
|
|
@@ -298866,6 +299147,18 @@ function verifyForgeCloudOwnerCallbackAssertion(assertion, config) {
|
|
|
298866
299147
|
//#endregion
|
|
298867
299148
|
//#region src/auth/Layers/ServerAuth.ts
|
|
298868
299149
|
const AUTHORIZATION_PREFIX = "Bearer ";
|
|
299150
|
+
function classifyWebSocketTokenFailure(cause) {
|
|
299151
|
+
switch (cause.message) {
|
|
299152
|
+
case "Malformed websocket token.": return "malformed";
|
|
299153
|
+
case "Invalid websocket token signature.": return "invalid_signature";
|
|
299154
|
+
case "Invalid websocket token payload.": return "invalid_payload";
|
|
299155
|
+
case "Websocket token expired.": return "expired_token";
|
|
299156
|
+
case "Websocket session revoked.": return "revoked_parent_session";
|
|
299157
|
+
case "Websocket session expired.": return "expired_parent_session";
|
|
299158
|
+
case "Unknown websocket session.": return "unknown_parent_session";
|
|
299159
|
+
default: return "verification_failed";
|
|
299160
|
+
}
|
|
299161
|
+
}
|
|
298869
299162
|
function toBootstrapExchangeAuthError(cause) {
|
|
298870
299163
|
if (cause.status === 500) return new AuthError({
|
|
298871
299164
|
message: "Failed to validate bootstrap credential.",
|
|
@@ -299168,7 +299461,6 @@ const ServerAuthLive = effect(ServerAuth, gen(function* () {
|
|
|
299168
299461
|
expiresAt: toUtc(issued.expiresAt)
|
|
299169
299462
|
})));
|
|
299170
299463
|
const authenticateWebSocketUpgrade = (request) => gen(function* () {
|
|
299171
|
-
if (serverConfig.forgeCloudShellMode === true) return yield* authenticateRequest(request);
|
|
299172
299464
|
if (serverConfig.forgeCmmdRuntimeMode) {
|
|
299173
299465
|
if (serverConfig.forgeCmmdAuthRuntime) {
|
|
299174
299466
|
const authConfig = readCmmdAuthRuntimeConfig(serverConfig);
|
|
@@ -299225,7 +299517,7 @@ const ServerAuthLive = effect(ServerAuth, gen(function* () {
|
|
|
299225
299517
|
const requestUrl = toURL(request);
|
|
299226
299518
|
if (isSome(requestUrl)) {
|
|
299227
299519
|
const websocketToken = readWebSocketUpgradeToken(requestUrl.value.searchParams);
|
|
299228
|
-
if (websocketToken) return yield* sessions.verifyWebSocketToken(websocketToken).pipe(map$3((session) => ({
|
|
299520
|
+
if (websocketToken) return yield* sessions.verifyWebSocketToken(websocketToken).pipe(tapError((cause) => logWarning$1("Rejected websocket token.").pipe(annotateLogs({ category: classifyWebSocketTokenFailure(cause) }))), map$3((session) => ({
|
|
299229
299521
|
sessionId: session.sessionId,
|
|
299230
299522
|
subject: session.subject,
|
|
299231
299523
|
method: session.method,
|
|
@@ -305264,7 +305556,7 @@ const orchestrationDispatchRouteLayer = add$1("POST", "/api/orchestration/dispat
|
|
|
305264
305556
|
}).pipe(mapError((cause) => new OrchestrationDispatchCommandError({
|
|
305265
305557
|
message: "Failed to dispatch orchestration command.",
|
|
305266
305558
|
cause
|
|
305267
|
-
}))) : orchestrationEngine.dispatch(normalizedCommand).pipe(mapError((cause) => new OrchestrationDispatchCommandError({
|
|
305559
|
+
}))) : (normalizedCommand.type === "thread.turn.interrupt" ? interruptBootstrapTurnStart(orchestrationEngine, normalizedCommand) : orchestrationEngine.dispatch(normalizedCommand)).pipe(mapError((cause) => new OrchestrationDispatchCommandError({
|
|
305268
305560
|
message: "Failed to dispatch orchestration command.",
|
|
305269
305561
|
cause
|
|
305270
305562
|
})));
|
|
@@ -320701,7 +320993,7 @@ const connectLoginCommand = make$34("login", {
|
|
|
320701
320993
|
})).json();
|
|
320702
320994
|
},
|
|
320703
320995
|
openBrowser: async (url) => {
|
|
320704
|
-
const open = (await import("./open-
|
|
320996
|
+
const open = (await import("./open-FIgTDosf.mjs")).default;
|
|
320705
320997
|
await open(url);
|
|
320706
320998
|
return true;
|
|
320707
320999
|
},
|