@cmmd-center/forge 0.13.0 → 0.13.1
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 +409 -134
- package/dist/bin.mjs +409 -134
- package/dist/client/assets/{CanvasPanel-BUdwnabz.js → CanvasPanel-BrVen-8G.js} +2 -2
- package/dist/client/assets/{CompositeItem-BxaZQRyb.js → CompositeItem-BNZfMUvm.js} +2 -2
- package/dist/client/assets/{DiffPanel-BOLibNHF.js → DiffPanel-tnITsSoL.js} +2 -2
- package/dist/client/assets/{DiffPanel.logic-BrRjlJeM.js → DiffPanel.logic-Ce-amvoZ.js} +2 -2
- package/dist/client/assets/{DiffPanelShell-CgycIPfE.js → DiffPanelShell-C14W3dyR.js} +3 -3
- package/dist/client/assets/{DiffWorkerPoolProvider-jWJpEXVo.js → DiffWorkerPoolProvider-BmseZYiJ.js} +2 -2
- package/dist/client/assets/{PullRequestCodePanel-BW7XdaG8.js → PullRequestCodePanel-A_x1n0YN.js} +2 -2
- package/dist/client/assets/{Virtualizer-qjNwH1hl.js → Virtualizer-CU3LnU6A.js} +2 -2
- package/dist/client/assets/{canvasStateStore-DDwjZ3AG.js → canvasStateStore-DN5mPB5B.js} +2 -2
- package/dist/client/assets/{cmmdAuthRedirect-CPfIOB5Y.js → cmmdAuthRedirect-sqR8W6vY.js} +2 -2
- package/dist/client/assets/index-DUeDfPMN.js +151 -0
- package/dist/client/assets/{src-dZ5rHSKC.js → src-CFqnisEM.js} +2 -2
- package/dist/client/assets/{toggle-Bn-2EZmB.js → toggle-CLUqZXdO.js} +2 -2
- package/dist/client/assets/{useTriggerFocusGuards-DRINKzwL.js → useTriggerFocusGuards-CaUimC-O.js} +2 -2
- package/dist/client/index.html +10 -10
- package/dist/forge-build.json +1 -1
- package/package.json +1 -1
- package/dist/client/assets/index-9clxg-cN.js +0 -151
package/dist/bin.mjs
CHANGED
|
@@ -16520,7 +16520,7 @@ function makeNetServiceShape(createServer = Net.createServer) {
|
|
|
16520
16520
|
}
|
|
16521
16521
|
//#endregion
|
|
16522
16522
|
//#region ../../packages/shared/src/releaseInfo.generated.ts
|
|
16523
|
-
const FORGE_RELEASE_VERSION = "0.13.
|
|
16523
|
+
const FORGE_RELEASE_VERSION = "0.13.1";
|
|
16524
16524
|
//#endregion
|
|
16525
16525
|
//#region ../../packages/shared/src/hostProcess.ts
|
|
16526
16526
|
/**
|
|
@@ -22464,6 +22464,27 @@ const ProviderUnavailableDetail = Literals([
|
|
|
22464
22464
|
"delivery-pending",
|
|
22465
22465
|
"reconnect-required"
|
|
22466
22466
|
]);
|
|
22467
|
+
/**
|
|
22468
|
+
* Whether the provider CLI honours the credential-directory variable, as this
|
|
22469
|
+
* Environment's probe found. `inconclusive` is a probe that ran and could not
|
|
22470
|
+
* tell. It is not `unsupported`, and it is never reported as `supported`. The
|
|
22471
|
+
* members are CMMD's `forgeRuntimeInventoryCredentialDirectoryAnswers`.
|
|
22472
|
+
*/
|
|
22473
|
+
const ProviderCredentialDirectoryAnswer = Literals([
|
|
22474
|
+
"supported",
|
|
22475
|
+
"unsupported",
|
|
22476
|
+
"inconclusive"
|
|
22477
|
+
]);
|
|
22478
|
+
/**
|
|
22479
|
+
* Which Credential Store the provider CLI uses on this Environment: its file,
|
|
22480
|
+
* the operating system's store, or `unknown` when it cannot be read the way
|
|
22481
|
+
* the CLI reads it. The members are CMMD's `forgeRuntimeInventoryCredentialStores`.
|
|
22482
|
+
*/
|
|
22483
|
+
const ProviderCredentialStore = Literals([
|
|
22484
|
+
"file",
|
|
22485
|
+
"os",
|
|
22486
|
+
"unknown"
|
|
22487
|
+
]);
|
|
22467
22488
|
const ServerProviderModel = Struct({
|
|
22468
22489
|
slug: TrimmedNonEmptyString,
|
|
22469
22490
|
name: TrimmedNonEmptyString,
|
|
@@ -22500,6 +22521,8 @@ const ServerProvider = Struct({
|
|
|
22500
22521
|
availability: optional$4(ProviderAvailability),
|
|
22501
22522
|
unavailableReason: optional$4(ProviderUnavailableReason),
|
|
22502
22523
|
unavailableDetail: optional$4(ProviderUnavailableDetail),
|
|
22524
|
+
credentialDirectory: optional$4(ProviderCredentialDirectoryAnswer),
|
|
22525
|
+
credentialStore: optional$4(ProviderCredentialStore),
|
|
22503
22526
|
slashCommands: ArraySchema(ServerProviderSlashCommand).pipe(withDecodingDefault(succeed([]))),
|
|
22504
22527
|
skills: ArraySchema(ServerProviderSkill).pipe(withDecodingDefault(succeed([])))
|
|
22505
22528
|
});
|
|
@@ -26447,12 +26470,12 @@ function encodeCmmdRuntimeThreadWorkspaceMetadata(workspace) {
|
|
|
26447
26470
|
}
|
|
26448
26471
|
//#endregion
|
|
26449
26472
|
//#region ../../packages/contracts/src/cmmdRuntimeToolActivity.ts
|
|
26450
|
-
function isRecord$
|
|
26473
|
+
function isRecord$23(value) {
|
|
26451
26474
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
26452
26475
|
}
|
|
26453
26476
|
function encodeCmmdRuntimeToolActivityPayload(kind, payload) {
|
|
26454
26477
|
return {
|
|
26455
|
-
...isRecord$
|
|
26478
|
+
...isRecord$23(payload) ? payload : { sourcePayload: payload },
|
|
26456
26479
|
forgeToolActivity: {
|
|
26457
26480
|
schemaVersion: 1,
|
|
26458
26481
|
source: "native",
|
|
@@ -30444,13 +30467,13 @@ async function completePendingDesktopRelayIdentityRotation(input) {
|
|
|
30444
30467
|
}
|
|
30445
30468
|
//#endregion
|
|
30446
30469
|
//#region ../../packages/relay-host/src/internal/desktopRelayJws.ts
|
|
30447
|
-
function isRecord$
|
|
30470
|
+
function isRecord$22(value) {
|
|
30448
30471
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
30449
30472
|
}
|
|
30450
30473
|
function decodeBase64UrlJson$1(value) {
|
|
30451
30474
|
try {
|
|
30452
30475
|
const decoded = JSON.parse(Buffer.from(value, "base64url").toString("utf8"));
|
|
30453
|
-
return isRecord$
|
|
30476
|
+
return isRecord$22(decoded) ? decoded : null;
|
|
30454
30477
|
} catch {
|
|
30455
30478
|
return null;
|
|
30456
30479
|
}
|
|
@@ -30604,11 +30627,11 @@ var DesktopRelayControlPlaneError = class extends Error {
|
|
|
30604
30627
|
this.name = "DesktopRelayControlPlaneError";
|
|
30605
30628
|
}
|
|
30606
30629
|
};
|
|
30607
|
-
function isRecord$
|
|
30630
|
+
function isRecord$21(value) {
|
|
30608
30631
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
30609
30632
|
}
|
|
30610
30633
|
function parseErrorPayload(value) {
|
|
30611
|
-
return isRecord$
|
|
30634
|
+
return isRecord$21(value) ? value : {};
|
|
30612
30635
|
}
|
|
30613
30636
|
function messageFromErrorPayload(payload, fallback) {
|
|
30614
30637
|
return typeof payload.error === "string" && payload.error.trim().length > 0 ? payload.error.trim() : fallback;
|
|
@@ -30706,7 +30729,7 @@ async function postControlPlane(input) {
|
|
|
30706
30729
|
const errorPayload = parseErrorPayload(payload);
|
|
30707
30730
|
throw new DesktopRelayControlPlaneError(typeof errorPayload.code === "string" && errorPayload.code.trim().length > 0 ? errorPayload.code.trim() : `CMMD_HTTP_${response.status}`, messageFromErrorPayload(errorPayload, `CMMD relay request failed (${response.status}).`), response.status === 408 || response.status === 429 || response.status >= 500);
|
|
30708
30731
|
}
|
|
30709
|
-
if (!isRecord$
|
|
30732
|
+
if (!isRecord$21(payload) || !("data" in payload)) throw new DesktopRelayControlPlaneError("CONTROL_PLANE_INVALID_RESPONSE", "CMMD returned an invalid Forge relay response.", false);
|
|
30710
30733
|
return payload.data;
|
|
30711
30734
|
}
|
|
30712
30735
|
function resolveRegisteredDevice(input) {
|
|
@@ -65559,7 +65582,7 @@ function normalizeNumberish(value) {
|
|
|
65559
65582
|
}
|
|
65560
65583
|
//#endregion
|
|
65561
65584
|
//#region package.json
|
|
65562
|
-
var version$1 = "0.13.
|
|
65585
|
+
var version$1 = "0.13.1";
|
|
65563
65586
|
//#endregion
|
|
65564
65587
|
//#region src/sentry.ts
|
|
65565
65588
|
const SERVER_APP_NAME = "forge-server";
|
|
@@ -71101,12 +71124,12 @@ function resolveDesktopRelayControlPlaneTarget(path, configuredRuntimeId) {
|
|
|
71101
71124
|
code: "RELAY_OPERATION_DENIED"
|
|
71102
71125
|
};
|
|
71103
71126
|
}
|
|
71104
|
-
function isRecord$
|
|
71127
|
+
function isRecord$20(value) {
|
|
71105
71128
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
71106
71129
|
}
|
|
71107
71130
|
function relayControlPlaneBodyMatchesRuntime(path, body, configuredRuntimeId) {
|
|
71108
71131
|
if (path !== "/api/forge/context/devices/register") return true;
|
|
71109
|
-
if (!isRecord$
|
|
71132
|
+
if (!isRecord$20(body) || !isRecord$20(body.runtime)) return false;
|
|
71110
71133
|
return body.runtime.runtimeId === configuredRuntimeId;
|
|
71111
71134
|
}
|
|
71112
71135
|
/** Matches the client id `connect login` used, so CMMD accepts the refresh. */
|
|
@@ -71121,7 +71144,7 @@ function forbiddenResponse() {
|
|
|
71121
71144
|
return errorResponse(403, "RELAY_BRIDGE_FORBIDDEN", "Desktop relay bridge access denied.");
|
|
71122
71145
|
}
|
|
71123
71146
|
function relayProxyErrorResponse(error) {
|
|
71124
|
-
if (error instanceof CmmdProxyRequestError && isRecord$
|
|
71147
|
+
if (error instanceof CmmdProxyRequestError && isRecord$20(error.body)) {
|
|
71125
71148
|
const code = typeof error.body.code === "string" ? error.body.code : error.code;
|
|
71126
71149
|
const message = typeof error.body.error === "string" ? error.body.error : error.detail;
|
|
71127
71150
|
return errorResponse(error.status >= 500 ? 502 : error.status, code, message ?? "CMMD relay coordination failed.");
|
|
@@ -93427,7 +93450,7 @@ const REPLICA_THREAD_STATUSES = [
|
|
|
93427
93450
|
];
|
|
93428
93451
|
//#endregion
|
|
93429
93452
|
//#region src/runtimeReplication/replicaDecodeModel.ts
|
|
93430
|
-
function isRecord$
|
|
93453
|
+
function isRecord$19(value) {
|
|
93431
93454
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
93432
93455
|
}
|
|
93433
93456
|
function isNonBlankString(value) {
|
|
@@ -93447,7 +93470,7 @@ function nullableInteger(value) {
|
|
|
93447
93470
|
return value === null || typeof value === "number" && Number.isSafeInteger(value);
|
|
93448
93471
|
}
|
|
93449
93472
|
function unwrapEnvelope(payload, expectedDomain) {
|
|
93450
|
-
if (!isRecord$
|
|
93473
|
+
if (!isRecord$19(payload) || !isRecord$19(payload.meta) || !isRecord$19(payload.data)) return null;
|
|
93451
93474
|
const { domain, timestamp, version } = payload.meta;
|
|
93452
93475
|
if (!isNonBlankString(domain) || expectedDomain !== void 0 && domain !== expectedDomain || version !== "1.0" || !isIsoDateTime(timestamp)) return null;
|
|
93453
93476
|
return payload.data;
|
|
@@ -93460,12 +93483,12 @@ function hasValidRuntimeIdentity(value) {
|
|
|
93460
93483
|
].includes(String(value.runtimeKind)) && typeof value.displayName === "string" && typeof value.status === "string";
|
|
93461
93484
|
}
|
|
93462
93485
|
function decodeRuntime$1(value) {
|
|
93463
|
-
if (!isRecord$
|
|
93464
|
-
if (!nullableString(value.endpointUrl) || value.endpointUrl !== null && !URL.canParse(value.endpointUrl) || !nullableInteger(value.deviceId) || !nullableString(value.workspaceRoot) || !nullableString(value.githubRepoFullName) || !(value.lastSeenAt === null || isIsoDateTime(value.lastSeenAt)) || !(value.metadata === null || isRecord$
|
|
93486
|
+
if (!isRecord$19(value) || !hasValidRuntimeIdentity(value)) return null;
|
|
93487
|
+
if (!nullableString(value.endpointUrl) || value.endpointUrl !== null && !URL.canParse(value.endpointUrl) || !nullableInteger(value.deviceId) || !nullableString(value.workspaceRoot) || !nullableString(value.githubRepoFullName) || !(value.lastSeenAt === null || isIsoDateTime(value.lastSeenAt)) || !(value.metadata === null || isRecord$19(value.metadata))) return null;
|
|
93465
93488
|
return value;
|
|
93466
93489
|
}
|
|
93467
93490
|
function decodeProject(value) {
|
|
93468
|
-
if (!isRecord$
|
|
93491
|
+
if (!isRecord$19(value) || !isNonBlankString(value.projectId) || typeof value.title !== "string" || !nullableString(value.githubRepoFullName) || !nullableString(value.branch)) return null;
|
|
93469
93492
|
return {
|
|
93470
93493
|
projectId: value.projectId,
|
|
93471
93494
|
title: value.title,
|
|
@@ -93474,11 +93497,11 @@ function decodeProject(value) {
|
|
|
93474
93497
|
};
|
|
93475
93498
|
}
|
|
93476
93499
|
function decodeThread$1(value) {
|
|
93477
|
-
if (!isRecord$
|
|
93500
|
+
if (!isRecord$19(value) || !isNonBlankString(value.threadId) || typeof value.title !== "string" || !isReplicaThreadStatus(value.status) || !nullableString(value.model) || !nullableString(value.branch) || !(value.lastActivityAt === null || isIsoDateTime(value.lastActivityAt))) return null;
|
|
93478
93501
|
return value;
|
|
93479
93502
|
}
|
|
93480
93503
|
function decodeSummary(value) {
|
|
93481
|
-
if (!isRecord$
|
|
93504
|
+
if (!isRecord$19(value) || !nullableString(value.conversationId)) return null;
|
|
93482
93505
|
const project = decodeProject(value.project);
|
|
93483
93506
|
const thread = decodeThread$1(value.thread);
|
|
93484
93507
|
return project === null || thread === null ? null : {
|
|
@@ -93589,7 +93612,7 @@ function isNonNegativeInt(value) {
|
|
|
93589
93612
|
/** `usage` is null for an Unreported turn, otherwise exactly the five buckets. */
|
|
93590
93613
|
function isValidTurnUsageTokens(value) {
|
|
93591
93614
|
if (value === null) return true;
|
|
93592
|
-
if (!isRecord$
|
|
93615
|
+
if (!isRecord$19(value)) return false;
|
|
93593
93616
|
return turnUsageTokenKeys.every((key) => isNonNegativeInt(value[key])) && Object.keys(value).every((key) => turnUsageTokenKeys.includes(key));
|
|
93594
93617
|
}
|
|
93595
93618
|
/** The row itself: no text, no status, and the turn it belongs to. */
|
|
@@ -93598,7 +93621,7 @@ function hasValidTurnUsageEnvelope(value) {
|
|
|
93598
93621
|
}
|
|
93599
93622
|
/** What the row records: who ran it, what it spent, and what it says of itself. */
|
|
93600
93623
|
function hasValidTurnUsageRecord(payload) {
|
|
93601
|
-
return isRecord$
|
|
93624
|
+
return isRecord$19(payload) && isNonBlankString(payload.provider) && isNonBlankString(payload.model) && "usage" in payload && isValidTurnUsageTokens(payload.usage) && hasValidTurnUsageAttribution(payload);
|
|
93602
93625
|
}
|
|
93603
93626
|
/** A turn_usage row: no text, no status, and its record in `payload`. */
|
|
93604
93627
|
function hasValidTurnUsagePayload(value) {
|
|
@@ -93635,7 +93658,7 @@ function hasValidEventPayload(value) {
|
|
|
93635
93658
|
return isNonBlankString(value.text) && value.status === null;
|
|
93636
93659
|
}
|
|
93637
93660
|
function decodeEvent$1(value) {
|
|
93638
|
-
if (!isRecord$
|
|
93661
|
+
if (!isRecord$19(value) || !hasValidEventFields(value) || !hasValidEventPayload(value)) return null;
|
|
93639
93662
|
return value;
|
|
93640
93663
|
}
|
|
93641
93664
|
function decodeEvents(data) {
|
|
@@ -93656,11 +93679,11 @@ function decodeReplicaThreadDetail(payload) {
|
|
|
93656
93679
|
const thread = decodeThread$1(data.thread);
|
|
93657
93680
|
const reachability = decodeReachability(data.reachability);
|
|
93658
93681
|
const events = decodeEvents(data);
|
|
93659
|
-
if (runtime === null || project === null || thread === null || reachability === null || events === null || !isRecord$
|
|
93682
|
+
if (runtime === null || project === null || thread === null || reachability === null || events === null || !isRecord$19(data.execution) || typeof data.execution.available !== "boolean" || ![
|
|
93660
93683
|
null,
|
|
93661
93684
|
"runtime_offline",
|
|
93662
93685
|
"runtime_unavailable"
|
|
93663
|
-
].includes(data.execution.reason) || (data.execution.available ? data.execution.reason !== null : data.execution.reason === null) || !isRecord$
|
|
93686
|
+
].includes(data.execution.reason) || (data.execution.available ? data.execution.reason !== null : data.execution.reason === null) || !isRecord$19(data.replication) || data.replication.protocolVersion !== 2 || !isNonBlankString(data.replication.generationId) || !Number.isSafeInteger(data.replication.acknowledgedSequence) || Number(data.replication.acknowledgedSequence) < 0 || !isNonBlankString(data.replication.headHash)) return null;
|
|
93664
93687
|
return {
|
|
93665
93688
|
conversationId: data.conversationId,
|
|
93666
93689
|
runtime,
|
|
@@ -94580,7 +94603,7 @@ function resolveRuntimeReplicationRuntimeId(config) {
|
|
|
94580
94603
|
}
|
|
94581
94604
|
//#endregion
|
|
94582
94605
|
//#region src/usage/providerTokenBuckets.ts
|
|
94583
|
-
function isRecord$
|
|
94606
|
+
function isRecord$18(value) {
|
|
94584
94607
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
94585
94608
|
}
|
|
94586
94609
|
function count(record, ...keys) {
|
|
@@ -94601,7 +94624,7 @@ function reportedOrNull(tokens) {
|
|
|
94601
94624
|
* the app server sends camelCase.
|
|
94602
94625
|
*/
|
|
94603
94626
|
function codexTokenBuckets(value) {
|
|
94604
|
-
if (!isRecord$
|
|
94627
|
+
if (!isRecord$18(value)) return null;
|
|
94605
94628
|
const inputTokens = count(value, "input_tokens", "inputTokens");
|
|
94606
94629
|
const cachedInputTokens = count(value, "cached_input_tokens", "cachedInputTokens");
|
|
94607
94630
|
const cacheCreationTokens = count(value, "cache_write_input_tokens", "cacheWriteInputTokens");
|
|
@@ -94620,7 +94643,7 @@ function codexTokenBuckets(value) {
|
|
|
94620
94643
|
* tokens into output and does not break them out, so reasoning stays zero.
|
|
94621
94644
|
*/
|
|
94622
94645
|
function claudeTokenBuckets(value) {
|
|
94623
|
-
if (!isRecord$
|
|
94646
|
+
if (!isRecord$18(value)) return null;
|
|
94624
94647
|
return reportedOrNull({
|
|
94625
94648
|
uncachedInputTokens: count(value, "input_tokens", "inputTokens"),
|
|
94626
94649
|
cachedInputTokens: count(value, "cache_read_input_tokens", "cacheReadInputTokens"),
|
|
@@ -95514,6 +95537,20 @@ function publishedAvailability(provider) {
|
|
|
95514
95537
|
...detail === void 0 ? {} : { unavailableDetail: detail }
|
|
95515
95538
|
};
|
|
95516
95539
|
}
|
|
95540
|
+
/**
|
|
95541
|
+
* What the Claude CLI said about its credentials, beside the version it said
|
|
95542
|
+
* it for. CMMD keeps each Claude version's answers, so these go on the Claude
|
|
95543
|
+
* entry only. Each is copied only when the snapshot has an answer: absent means
|
|
95544
|
+
* the runtime has not answered yet, and inventing a value would hide that.
|
|
95545
|
+
*/
|
|
95546
|
+
function claudeCredentialAnswersToPublish(provider) {
|
|
95547
|
+
if (provider.provider !== "claudeAgent") return {};
|
|
95548
|
+
const { credentialDirectory, credentialStore } = provider;
|
|
95549
|
+
return {
|
|
95550
|
+
...credentialDirectory === void 0 ? {} : { credentialDirectory },
|
|
95551
|
+
...credentialStore === void 0 ? {} : { credentialStore }
|
|
95552
|
+
};
|
|
95553
|
+
}
|
|
95517
95554
|
function serializeProvider(provider) {
|
|
95518
95555
|
const models = [];
|
|
95519
95556
|
for (const model of provider.models) {
|
|
@@ -95526,7 +95563,8 @@ function serializeProvider(provider) {
|
|
|
95526
95563
|
models,
|
|
95527
95564
|
...publishedAvailability(provider),
|
|
95528
95565
|
version: cappedText(provider.version, VERSION_MAX_LENGTH),
|
|
95529
|
-
binaryPath: cappedText(provider.auth.provenance?.binaryPath, BINARY_PATH_MAX_LENGTH)
|
|
95566
|
+
binaryPath: cappedText(provider.auth.provenance?.binaryPath, BINARY_PATH_MAX_LENGTH),
|
|
95567
|
+
...claudeCredentialAnswersToPublish(provider)
|
|
95530
95568
|
};
|
|
95531
95569
|
}
|
|
95532
95570
|
function serializeProviderCatalog(providers) {
|
|
@@ -95547,7 +95585,7 @@ const replicaTurnStatuses = new Set([
|
|
|
95547
95585
|
"cancelled",
|
|
95548
95586
|
"interrupted"
|
|
95549
95587
|
]);
|
|
95550
|
-
function isRecord$
|
|
95588
|
+
function isRecord$17(value) {
|
|
95551
95589
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
95552
95590
|
}
|
|
95553
95591
|
function replicaSourceSequence(value) {
|
|
@@ -95560,7 +95598,7 @@ function replicaSourceTurn(sourceTurnId) {
|
|
|
95560
95598
|
return typeof sourceTurnId === "string" && sourceTurnId.length > 0 ? { turnId: sourceTurnId } : {};
|
|
95561
95599
|
}
|
|
95562
95600
|
function replicaActivitySource(activity) {
|
|
95563
|
-
if (!activity.kind.startsWith("replica.") || !isRecord$
|
|
95601
|
+
if (!activity.kind.startsWith("replica.") || !isRecord$17(activity.payload)) return null;
|
|
95564
95602
|
const sourceSequence = replicaSourceSequence(activity.sequence);
|
|
95565
95603
|
const eventId = replicaSourceEventId(activity.payload.sourceEventId);
|
|
95566
95604
|
if (sourceSequence === null || eventId === null) return null;
|
|
@@ -95573,7 +95611,7 @@ function replicaActivitySource(activity) {
|
|
|
95573
95611
|
}
|
|
95574
95612
|
function replicaSummaryEvent(activity, source) {
|
|
95575
95613
|
if (activity.kind !== "replica.activity_summary" && activity.kind !== "replica.error_summary") return null;
|
|
95576
|
-
const sourceText = isRecord$
|
|
95614
|
+
const sourceText = isRecord$17(activity.payload) ? activity.payload.text : null;
|
|
95577
95615
|
return {
|
|
95578
95616
|
sourceSequence: source.sourceSequence,
|
|
95579
95617
|
event: {
|
|
@@ -95586,7 +95624,7 @@ function replicaSummaryEvent(activity, source) {
|
|
|
95586
95624
|
};
|
|
95587
95625
|
}
|
|
95588
95626
|
function replicaTurnEvent(activity, source) {
|
|
95589
|
-
const status = isRecord$
|
|
95627
|
+
const status = isRecord$17(activity.payload) ? activity.payload.status : null;
|
|
95590
95628
|
if (activity.kind !== "replica.turn_status" || !replicaTurnStatuses.has(status)) return null;
|
|
95591
95629
|
return {
|
|
95592
95630
|
sourceSequence: source.sourceSequence,
|
|
@@ -95600,7 +95638,7 @@ function replicaTurnEvent(activity, source) {
|
|
|
95600
95638
|
};
|
|
95601
95639
|
}
|
|
95602
95640
|
function replicaToolCallEvent(activity, source) {
|
|
95603
|
-
if (activity.kind !== "replica.tool_call" || !isRecord$
|
|
95641
|
+
if (activity.kind !== "replica.tool_call" || !isRecord$17(activity.payload)) return null;
|
|
95604
95642
|
const sourceText = activity.payload.text;
|
|
95605
95643
|
const status = activity.payload.status;
|
|
95606
95644
|
if (typeof sourceText !== "string" || typeof status !== "string") return null;
|
|
@@ -95618,9 +95656,9 @@ function replicaToolCallEvent(activity, source) {
|
|
|
95618
95656
|
};
|
|
95619
95657
|
}
|
|
95620
95658
|
function replicaTurnUsageEvent(activity, source) {
|
|
95621
|
-
if (activity.kind !== "replica.turn_usage" || !isRecord$
|
|
95659
|
+
if (activity.kind !== "replica.turn_usage" || !isRecord$17(activity.payload)) return null;
|
|
95622
95660
|
const usage = activity.payload.payload;
|
|
95623
|
-
if (!("turnId" in source.turn) || !isRecord$
|
|
95661
|
+
if (!("turnId" in source.turn) || !isRecord$17(usage)) return null;
|
|
95624
95662
|
const provider = usage.provider;
|
|
95625
95663
|
const model = usage.model;
|
|
95626
95664
|
if (typeof provider !== "string" || typeof model !== "string" || !("usage" in usage)) return null;
|
|
@@ -96432,9 +96470,9 @@ function isUsageSessionLookupRuntimeNotFound(error) {
|
|
|
96432
96470
|
async function isRuntimeNotFoundResponse(response) {
|
|
96433
96471
|
if (response.status !== 404) return false;
|
|
96434
96472
|
const body = await response.json().catch(() => null);
|
|
96435
|
-
return isRecord$
|
|
96473
|
+
return isRecord$16(body) && body["code"] === "RUNTIME_NOT_FOUND";
|
|
96436
96474
|
}
|
|
96437
|
-
function isRecord$
|
|
96475
|
+
function isRecord$16(value) {
|
|
96438
96476
|
return typeof value === "object" && value !== null;
|
|
96439
96477
|
}
|
|
96440
96478
|
/**
|
|
@@ -96446,11 +96484,11 @@ function isRecord$15(value) {
|
|
|
96446
96484
|
* no count on the page saying so.
|
|
96447
96485
|
*/
|
|
96448
96486
|
function decodeHeldSessions(body) {
|
|
96449
|
-
const held = isRecord$
|
|
96487
|
+
const held = isRecord$16(body) && isRecord$16(body["data"]) ? body["data"]["held"] : void 0;
|
|
96450
96488
|
if (!Array.isArray(held)) throw new Error("The usage session lookup returned an invalid body.");
|
|
96451
96489
|
return held.map((row) => {
|
|
96452
|
-
const providerSessionId = isRecord$
|
|
96453
|
-
const runtimeId = isRecord$
|
|
96490
|
+
const providerSessionId = isRecord$16(row) ? row["providerSessionId"] : void 0;
|
|
96491
|
+
const runtimeId = isRecord$16(row) ? row["runtimeId"] : void 0;
|
|
96454
96492
|
if (typeof providerSessionId !== "string" || typeof runtimeId !== "string") throw new Error("The usage session lookup returned an invalid held row.");
|
|
96455
96493
|
return {
|
|
96456
96494
|
providerSessionId,
|
|
@@ -99241,7 +99279,7 @@ function emptyConfig(source, path) {
|
|
|
99241
99279
|
issues: []
|
|
99242
99280
|
};
|
|
99243
99281
|
}
|
|
99244
|
-
function isRecord$
|
|
99282
|
+
function isRecord$15(value) {
|
|
99245
99283
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
99246
99284
|
}
|
|
99247
99285
|
function stringArray(value) {
|
|
@@ -99269,7 +99307,7 @@ function terminalsFromValue(value) {
|
|
|
99269
99307
|
name: `Terminal ${index + 1}`,
|
|
99270
99308
|
command: terminal.trim()
|
|
99271
99309
|
}];
|
|
99272
|
-
if (!isRecord$
|
|
99310
|
+
if (!isRecord$15(terminal)) return [];
|
|
99273
99311
|
const command = typeof terminal.command === "string" ? terminal.command.trim() : "";
|
|
99274
99312
|
if (!command) return [];
|
|
99275
99313
|
return [{
|
|
@@ -99308,7 +99346,7 @@ function readConfigFile(source, path) {
|
|
|
99308
99346
|
}]
|
|
99309
99347
|
};
|
|
99310
99348
|
}
|
|
99311
|
-
if (!isRecord$
|
|
99349
|
+
if (!isRecord$15(parsed)) return {
|
|
99312
99350
|
...emptyConfig(source, path),
|
|
99313
99351
|
issues: [{
|
|
99314
99352
|
severity: "blocked",
|
|
@@ -100451,7 +100489,7 @@ const CLAUDE_IDENTITY_KEYS = new Set([
|
|
|
100451
100489
|
"credentialGenerationId"
|
|
100452
100490
|
]);
|
|
100453
100491
|
const CLAUDE_IDENTITY_OPTIONAL_KEYS = new Set(["providerAccountIdentity"]);
|
|
100454
|
-
function isRecord$
|
|
100492
|
+
function isRecord$14(value) {
|
|
100455
100493
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
100456
100494
|
}
|
|
100457
100495
|
function isStrictRfc3339DateTime(value) {
|
|
@@ -100480,7 +100518,7 @@ function hasAllowedKeys(value, required, optional) {
|
|
|
100480
100518
|
return keys.every((key) => required.has(key) || optional.has(key)) && [...required].every((key) => keys.includes(key));
|
|
100481
100519
|
}
|
|
100482
100520
|
function parseDeliveryIdentity(value, provider) {
|
|
100483
|
-
if (!isRecord$
|
|
100521
|
+
if (!isRecord$14(value)) return null;
|
|
100484
100522
|
if (provider === "openai") return parseCodexDeliveryIdentity(value);
|
|
100485
100523
|
if (provider === "anthropic") return parseClaudeDeliveryIdentity(value);
|
|
100486
100524
|
return null;
|
|
@@ -100515,7 +100553,7 @@ function parseClaudeDeliveryIdentity(value) {
|
|
|
100515
100553
|
};
|
|
100516
100554
|
}
|
|
100517
100555
|
function parseProviderRuntimeDeliveryReceipt(value, expected) {
|
|
100518
|
-
if (!isRecord$
|
|
100556
|
+
if (!isRecord$14(value) || !hasExactKeys$2(value, RECEIPT_KEYS)) return null;
|
|
100519
100557
|
const identity = parseDeliveryIdentity(value.identity, expected.provider);
|
|
100520
100558
|
if (!identity || typeof value.receiptId !== "string" || value.receiptId.length === 0 || value.receiptId.length > 256 || value.runtimeId !== expected.runtimeId || value.machineId !== expected.machineId || value.credentialEpoch !== expected.credentialEpoch || !Number.isInteger(value.credentialEpoch) || value.credentialEpoch < 0 || !isStrictRfc3339DateTime(value.issuedAt) || value.expiresAt !== expected.expiresAt || value.expiresAt !== null && !isStrictRfc3339DateTime(value.expiresAt)) return null;
|
|
100521
100559
|
return {
|
|
@@ -100537,8 +100575,8 @@ function providerDeliveryBindingFromReceipt(receipt) {
|
|
|
100537
100575
|
};
|
|
100538
100576
|
}
|
|
100539
100577
|
function readProviderDeliveryBinding(value) {
|
|
100540
|
-
if (!isRecord$
|
|
100541
|
-
const identityProvider = isRecord$
|
|
100578
|
+
if (!isRecord$14(value) || !hasExactKeys$2(value, BINDING_KEYS)) return null;
|
|
100579
|
+
const identityProvider = isRecord$14(value.identity) ? value.identity.provider : void 0;
|
|
100542
100580
|
const tokenProvider = identityProvider === "codex" ? "openai" : identityProvider === "claude" ? "anthropic" : null;
|
|
100543
100581
|
if (!tokenProvider) return null;
|
|
100544
100582
|
const identity = parseDeliveryIdentity(value.identity, tokenProvider);
|
|
@@ -147804,12 +147842,12 @@ function decodeProviderKind(providerName, operation) {
|
|
|
147804
147842
|
detail: `Unknown persisted provider '${providerName}'.`
|
|
147805
147843
|
}));
|
|
147806
147844
|
}
|
|
147807
|
-
function isRecord$
|
|
147845
|
+
function isRecord$13(value) {
|
|
147808
147846
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
147809
147847
|
}
|
|
147810
147848
|
function mergeRuntimePayload(existing, next) {
|
|
147811
147849
|
if (next === void 0) return existing ?? null;
|
|
147812
|
-
if (isRecord$
|
|
147850
|
+
if (isRecord$13(existing) && isRecord$13(next)) return {
|
|
147813
147851
|
...existing,
|
|
147814
147852
|
...next
|
|
147815
147853
|
};
|
|
@@ -149773,7 +149811,7 @@ const PAGINATION_KEYS = new Set([
|
|
|
149773
149811
|
"total",
|
|
149774
149812
|
"hasMore"
|
|
149775
149813
|
]);
|
|
149776
|
-
function isRecord$
|
|
149814
|
+
function isRecord$12(value) {
|
|
149777
149815
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
149778
149816
|
}
|
|
149779
149817
|
function hasOnlyKeys(value, allowed) {
|
|
@@ -149786,17 +149824,17 @@ function isRfc3339(value) {
|
|
|
149786
149824
|
return typeof value === "string" && RFC3339.test(value) && Number.isFinite(Date.parse(value));
|
|
149787
149825
|
}
|
|
149788
149826
|
function isEnvelopeMeta(value) {
|
|
149789
|
-
if (!isRecord$
|
|
149827
|
+
if (!isRecord$12(value) || !hasExactKeys$1(value, META_KEYS)) return false;
|
|
149790
149828
|
return typeof value.domain === "string" && value.domain.length > 0 && isRfc3339(value.timestamp) && typeof value.version === "string" && value.version.length > 0;
|
|
149791
149829
|
}
|
|
149792
149830
|
function isPagination(value) {
|
|
149793
|
-
if (!isRecord$
|
|
149831
|
+
if (!isRecord$12(value) || !hasExactKeys$1(value, PAGINATION_KEYS)) return false;
|
|
149794
149832
|
return Number.isInteger(value.page) && value.page >= 0 && Number.isInteger(value.limit) && value.limit >= 0 && Number.isInteger(value.total) && value.total >= 0 && typeof value.hasMore === "boolean";
|
|
149795
149833
|
}
|
|
149796
149834
|
function readLocalProviderAccountId(authJson) {
|
|
149797
149835
|
try {
|
|
149798
149836
|
const value = JSON.parse(authJson);
|
|
149799
|
-
if (!isRecord$
|
|
149837
|
+
if (!isRecord$12(value) || value.auth_mode !== "chatgpt" || !isRecord$12(value.tokens)) return null;
|
|
149800
149838
|
const providerAccountId = value.tokens.account_id;
|
|
149801
149839
|
if (typeof providerAccountId !== "string") return null;
|
|
149802
149840
|
const normalized = providerAccountId.trim();
|
|
@@ -149809,13 +149847,13 @@ function resolveLocalAuthJsonPath(homePath) {
|
|
|
149809
149847
|
return join(homePath?.trim() || process.env.CODEX_HOME?.trim() || join(homedir(), ".codex"), "auth.json");
|
|
149810
149848
|
}
|
|
149811
149849
|
function parseCodexAccountIdentityEnvelope(value) {
|
|
149812
|
-
if (!isRecord$
|
|
149850
|
+
if (!isRecord$12(value) || !hasOnlyKeys(value, ENVELOPE_KEYS)) return null;
|
|
149813
149851
|
if (!("data" in value) || !("meta" in value) || !isEnvelopeMeta(value.meta)) return null;
|
|
149814
149852
|
if (value.pagination !== void 0 && !isPagination(value.pagination)) return null;
|
|
149815
149853
|
return readCodexAccountIdentity(value.data);
|
|
149816
149854
|
}
|
|
149817
149855
|
function readCodexAccountIdentity(value) {
|
|
149818
|
-
if (!isRecord$
|
|
149856
|
+
if (!isRecord$12(value) || !hasExactKeys$1(value, IDENTITY_KEYS)) return null;
|
|
149819
149857
|
if (value.kind !== "provider_account" || value.provider !== "codex" || typeof value.providerAccountIdentity !== "string" || !PROVIDER_ACCOUNT_IDENTITY$1.test(value.providerAccountIdentity)) return null;
|
|
149820
149858
|
return {
|
|
149821
149859
|
kind: "provider_account",
|
|
@@ -210998,10 +211036,16 @@ function claudeSubscriptionChildEnv(processEnv, credentialDirectory) {
|
|
|
210998
211036
|
* environment with `claudeSubscriptionChildEnv`, the same builder as the turn's
|
|
210999
211037
|
* personal-subscription branch.
|
|
211000
211038
|
*
|
|
211001
|
-
* `claude auth status`
|
|
211002
|
-
*
|
|
211039
|
+
* `claude auth status` sends no prompt and leaves `.credentials.json`
|
|
211040
|
+
* byte-identical, so probing spends no subscription usage. For Team and
|
|
211041
|
+
* Enterprise accounts the CLI's `auth` preAction schedules a remote-settings
|
|
211042
|
+
* fetch it never awaits, and the command exits before that fetch runs (see the
|
|
211043
|
+
* 2026-09-10 amendment to `docs/adr/cmmd-is-the-only-claude-credential-renewer.md`).
|
|
211003
211044
|
* It prints JSON on stdout and exits 1 when logged out, so the exit code is not
|
|
211004
211045
|
* a failure signal and the `loggedIn` field is what gets read.
|
|
211046
|
+
*
|
|
211047
|
+
* Each answer a probe reaches is also kept in `claudeCredentialDirectoryAnswers`
|
|
211048
|
+
* so the provider check can publish it without probing.
|
|
211005
211049
|
*/
|
|
211006
211050
|
const execFileAsync$3 = promisify$1(execFile);
|
|
211007
211051
|
const AUTH_STATUS_ARGS = ["auth", "status"];
|
|
@@ -211018,8 +211062,7 @@ const PROBE_DIRECTORY_PREFIX = "forge-claude-capability-";
|
|
|
211018
211062
|
const VERSION_PATTERN = /\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?/;
|
|
211019
211063
|
function makeClaudeCredentialDirectoryProbe(deps) {
|
|
211020
211064
|
const answers = /* @__PURE__ */ new Map();
|
|
211021
|
-
const
|
|
211022
|
-
const version = await readVersionSafely(deps);
|
|
211065
|
+
const answerFor = (version) => {
|
|
211023
211066
|
if (version === null) return runProbe(deps);
|
|
211024
211067
|
const cached = answers.get(version);
|
|
211025
211068
|
if (cached) return cached;
|
|
@@ -211030,10 +211073,47 @@ function makeClaudeCredentialDirectoryProbe(deps) {
|
|
|
211030
211073
|
};
|
|
211031
211074
|
pending.then((result) => {
|
|
211032
211075
|
if (result === "inconclusive") forget();
|
|
211033
|
-
|
|
211076
|
+
deps.onAnswer?.(version, result);
|
|
211077
|
+
}, () => {
|
|
211078
|
+
forget();
|
|
211079
|
+
deps.onAnswer?.(version, "inconclusive");
|
|
211080
|
+
});
|
|
211034
211081
|
return pending;
|
|
211035
211082
|
};
|
|
211036
|
-
return { support:
|
|
211083
|
+
return { support: inconclusiveOnFailure(async () => answerFor(await readVersionSafely(deps))) };
|
|
211084
|
+
}
|
|
211085
|
+
/**
|
|
211086
|
+
* The one place a probe failure is handled. A missing binary, a timeout or a
|
|
211087
|
+
* directory that cannot be made all mean the probe could not tell.
|
|
211088
|
+
*/
|
|
211089
|
+
function inconclusiveOnFailure(run) {
|
|
211090
|
+
return tryPromise(run).pipe(orElseSucceed(() => "inconclusive"));
|
|
211091
|
+
}
|
|
211092
|
+
const keyOf = (binaryPath, version) => JSON.stringify([binaryPath, version]);
|
|
211093
|
+
function makeClaudeCredentialDirectoryAnswers() {
|
|
211094
|
+
const answers = /* @__PURE__ */ new Map();
|
|
211095
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
211096
|
+
return {
|
|
211097
|
+
record: (binaryPath, version, answer) => {
|
|
211098
|
+
const key = keyOf(binaryPath, version);
|
|
211099
|
+
if (answers.get(key) === answer) return;
|
|
211100
|
+
answers.set(key, answer);
|
|
211101
|
+
for (const listener of listeners) listener();
|
|
211102
|
+
},
|
|
211103
|
+
answerFor: (binaryPath, version) => answers.get(keyOf(binaryPath, version)),
|
|
211104
|
+
subscribe: (listener) => {
|
|
211105
|
+
listeners.add(listener);
|
|
211106
|
+
return () => {
|
|
211107
|
+
listeners.delete(listener);
|
|
211108
|
+
};
|
|
211109
|
+
}
|
|
211110
|
+
};
|
|
211111
|
+
}
|
|
211112
|
+
/** Every answer a turn-time probe in this process has reached. */
|
|
211113
|
+
const claudeCredentialDirectoryAnswers = makeClaudeCredentialDirectoryAnswers();
|
|
211114
|
+
/** The version in `claude --version` output, the key a probe answer is kept under. */
|
|
211115
|
+
function claudeVersionFromOutput(stdout) {
|
|
211116
|
+
return VERSION_PATTERN.exec(stdout)?.[0] ?? null;
|
|
211037
211117
|
}
|
|
211038
211118
|
/**
|
|
211039
211119
|
* One probe per binary path for the life of the process. A conclusive answer is
|
|
@@ -211058,7 +211138,12 @@ function claudeCredentialDirectoryProbeFor(binaryPath) {
|
|
|
211058
211138
|
if (!binaryPath) return INCONCLUSIVE_PROBE;
|
|
211059
211139
|
const existing = probesByBinaryPath.get(binaryPath);
|
|
211060
211140
|
if (existing) return existing;
|
|
211061
|
-
const probe = makeClaudeCredentialDirectoryProbe(
|
|
211141
|
+
const probe = makeClaudeCredentialDirectoryProbe({
|
|
211142
|
+
...claudeCredentialDirectoryProbeDeps(binaryPath),
|
|
211143
|
+
onAnswer: (version, answer) => {
|
|
211144
|
+
claudeCredentialDirectoryAnswers.record(binaryPath, version, answer);
|
|
211145
|
+
}
|
|
211146
|
+
});
|
|
211062
211147
|
probesByBinaryPath.set(binaryPath, probe);
|
|
211063
211148
|
return probe;
|
|
211064
211149
|
}
|
|
@@ -211069,7 +211154,7 @@ function claudeCredentialDirectoryProbeDeps(binaryPath, options = {}) {
|
|
|
211069
211154
|
runAuthStatus: ({ credentialDirectory }) => run(AUTH_STATUS_ARGS, credentialDirectory),
|
|
211070
211155
|
readBinaryVersion: async () => {
|
|
211071
211156
|
const { stdout } = await run(VERSION_ARGS, null);
|
|
211072
|
-
return
|
|
211157
|
+
return claudeVersionFromOutput(stdout);
|
|
211073
211158
|
},
|
|
211074
211159
|
makeProbeDirectory: () => mkdtemp(join(tmpdir(), PROBE_DIRECTORY_PREFIX)),
|
|
211075
211160
|
removeProbeDirectory: (directory) => rm(directory, {
|
|
@@ -211235,6 +211320,171 @@ const makeProviderAuthProvenance = (input) => {
|
|
|
211235
211320
|
};
|
|
211236
211321
|
};
|
|
211237
211322
|
//#endregion
|
|
211323
|
+
//#region src/provider/claudeCredentialStore.ts
|
|
211324
|
+
/**
|
|
211325
|
+
* Which Credential Store the Claude CLI uses on this machine, read the way the
|
|
211326
|
+
* CLI reads it.
|
|
211327
|
+
*
|
|
211328
|
+
* The CLI has two stores, `.credentials.json` in the credential directory and
|
|
211329
|
+
* the operating system's own, and no platform check picks between them. It
|
|
211330
|
+
* takes the OS store when `CLAUDE_CODE_FORCE_WINDOWS_CREDMAN` is `1`, and
|
|
211331
|
+
* otherwise when the remote flag it caches in its config file,
|
|
211332
|
+
* `cachedGrowthBookFeatures.tengu_windows_credman`, is `true`. That file is a
|
|
211333
|
+
* legacy `.config.json` in the config directory when one exists, and
|
|
211334
|
+
* `.claude.json` otherwise. Read from Claude Code 2.1.265 in #3086.
|
|
211335
|
+
*
|
|
211336
|
+
* The CLI takes the file when it cannot find, read or parse the config, and so
|
|
211337
|
+
* does this. A config that parses to JSON `null` reads `file` as well: the CLI
|
|
211338
|
+
* reads a property off the parsed value, which throws on `null`, and it falls
|
|
211339
|
+
* back to the file store on that throw. Any other config that parses but
|
|
211340
|
+
* carries no boolean flag also means the file to the CLI, but it is the shape a
|
|
211341
|
+
* moved key leaves, so this reads `unknown` rather than guess.
|
|
211342
|
+
*
|
|
211343
|
+
* Linux with no session bus has no secret service, so the OS store fails its
|
|
211344
|
+
* own check and the CLI falls back to the file whatever the flag says. Every
|
|
211345
|
+
* Sprite is that case, and it reads `file` without opening the config. Linux
|
|
211346
|
+
* with a session bus is `unknown` when the OS store is selected, because only
|
|
211347
|
+
* the secret service knows whether it would answer.
|
|
211348
|
+
* See `docs/adr/delivery-clears-the-os-credential-store-first.md`.
|
|
211349
|
+
*
|
|
211350
|
+
* Two things in 2.1.265 this does not follow. The CLI puts its OAuth name
|
|
211351
|
+
* suffix, `F$()` in that bundle, into the config name. The suffix is empty in a
|
|
211352
|
+
* production build and `-custom-oauth` with `CLAUDE_CODE_CUSTOM_OAUTH_URL` set,
|
|
211353
|
+
* so the config is then `.claude-custom-oauth.json` instead of `.claude.json`.
|
|
211354
|
+
* And `primeWindowsCredManBackendEnabled` can set the choice before the file is
|
|
211355
|
+
* read, but only with a v5 storage backend, and `tryCreateV5Backend` returns
|
|
211356
|
+
* nothing in that build, so it never does.
|
|
211357
|
+
*/
|
|
211358
|
+
const CLAUDE_FORCE_OS_CREDENTIAL_STORE_ENV = "CLAUDE_CODE_FORCE_WINDOWS_CREDMAN";
|
|
211359
|
+
const CACHED_FEATURES_KEY = "cachedGrowthBookFeatures";
|
|
211360
|
+
const OS_STORE_FLAG_KEY = "tengu_windows_credman";
|
|
211361
|
+
function readClaudeCredentialStore(input) {
|
|
211362
|
+
if (input.platform === "linux" && !hasSessionBus(input)) return "file";
|
|
211363
|
+
const selectsOsStore = cliSelectsOsStore(input);
|
|
211364
|
+
if (selectsOsStore === null) return "unknown";
|
|
211365
|
+
if (!selectsOsStore) return "file";
|
|
211366
|
+
return input.platform === "darwin" || input.platform === "win32" ? "os" : "unknown";
|
|
211367
|
+
}
|
|
211368
|
+
/** The same read against this machine's home directory and disk. */
|
|
211369
|
+
const readClaudeCredentialStoreFromDisk = (context) => {
|
|
211370
|
+
let homeDirectory;
|
|
211371
|
+
try {
|
|
211372
|
+
homeDirectory = homedir();
|
|
211373
|
+
} catch {
|
|
211374
|
+
homeDirectory = null;
|
|
211375
|
+
}
|
|
211376
|
+
return readClaudeCredentialStore({
|
|
211377
|
+
...context,
|
|
211378
|
+
homeDirectory: homeDirectory ?? "",
|
|
211379
|
+
fileExists: homeDirectory === null ? () => false : existsSync,
|
|
211380
|
+
readFile: (path) => {
|
|
211381
|
+
if (homeDirectory === null) throw new Error("no home directory");
|
|
211382
|
+
return readFileSync(path, "utf8");
|
|
211383
|
+
}
|
|
211384
|
+
});
|
|
211385
|
+
};
|
|
211386
|
+
/** True, false, or null when a parsed config does not say. */
|
|
211387
|
+
function cliSelectsOsStore(input) {
|
|
211388
|
+
if (input.env[CLAUDE_FORCE_OS_CREDENTIAL_STORE_ENV] === "1") return true;
|
|
211389
|
+
const config = readConfig(input);
|
|
211390
|
+
if (config === null) return false;
|
|
211391
|
+
const features = isRecord$11(config.parsed) ? config.parsed[CACHED_FEATURES_KEY] : void 0;
|
|
211392
|
+
const flag = isRecord$11(features) ? features[OS_STORE_FLAG_KEY] : void 0;
|
|
211393
|
+
return typeof flag === "boolean" ? flag : null;
|
|
211394
|
+
}
|
|
211395
|
+
/**
|
|
211396
|
+
* The parsed config, or null wherever the CLI's own read throws and it falls
|
|
211397
|
+
* back to the file store: a file that is missing, unreadable or not JSON, and a
|
|
211398
|
+
* config that parses to JSON `null`, because the CLI reads a property off it.
|
|
211399
|
+
*/
|
|
211400
|
+
function readConfig(input) {
|
|
211401
|
+
try {
|
|
211402
|
+
const parsed = JSON.parse(input.readFile(cachedFlagFile(input)));
|
|
211403
|
+
return parsed === null ? null : { parsed };
|
|
211404
|
+
} catch {
|
|
211405
|
+
return null;
|
|
211406
|
+
}
|
|
211407
|
+
}
|
|
211408
|
+
function cachedFlagFile(input) {
|
|
211409
|
+
const configured = input.configDirectory?.trim();
|
|
211410
|
+
const legacy = join(configured || join(input.homeDirectory, ".claude"), ".config.json");
|
|
211411
|
+
if (input.fileExists(legacy)) return legacy;
|
|
211412
|
+
return join(configured || input.homeDirectory, ".claude.json");
|
|
211413
|
+
}
|
|
211414
|
+
/** libsecret reaches the secret service over the session bus, so no bus means no OS store. */
|
|
211415
|
+
function hasSessionBus(input) {
|
|
211416
|
+
if (input.env.DBUS_SESSION_BUS_ADDRESS?.trim()) return true;
|
|
211417
|
+
const runtimeDirectory = input.env.XDG_RUNTIME_DIR?.trim();
|
|
211418
|
+
return runtimeDirectory ? input.fileExists(join(runtimeDirectory, "bus")) : false;
|
|
211419
|
+
}
|
|
211420
|
+
function isRecord$11(value) {
|
|
211421
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
211422
|
+
}
|
|
211423
|
+
//#endregion
|
|
211424
|
+
//#region src/provider/claudeCredentialAnswers.ts
|
|
211425
|
+
/**
|
|
211426
|
+
* The live resolver. The credential-directory answer is whatever the turn-time
|
|
211427
|
+
* probe last reached for this binary path and version, so the published answer
|
|
211428
|
+
* and the one that gated a turn are the same. Until a turn has probed, or with
|
|
211429
|
+
* no version to look it up by, the field stays absent.
|
|
211430
|
+
*/
|
|
211431
|
+
function makeClaudeCredentialAnswersResolver(options) {
|
|
211432
|
+
const readCredentialStore = options.readCredentialStore ?? readClaudeCredentialStoreFromDisk;
|
|
211433
|
+
return (input) => gen(function* () {
|
|
211434
|
+
const platform = yield* HostProcessPlatform;
|
|
211435
|
+
const credentialStore = yield* sync$1(() => readCredentialStore({
|
|
211436
|
+
env: options.env ?? process.env,
|
|
211437
|
+
platform,
|
|
211438
|
+
configDirectory: input.configDirectory
|
|
211439
|
+
}));
|
|
211440
|
+
const credentialDirectory = input.version === null ? void 0 : options.credentialDirectoryAnswers.answerFor(input.binaryPath, input.version);
|
|
211441
|
+
return credentialDirectory === void 0 ? { credentialStore } : {
|
|
211442
|
+
credentialStore,
|
|
211443
|
+
credentialDirectory
|
|
211444
|
+
};
|
|
211445
|
+
});
|
|
211446
|
+
}
|
|
211447
|
+
//#endregion
|
|
211448
|
+
//#region src/runtimeDrain/supervisedRepeat.ts
|
|
211449
|
+
/**
|
|
211450
|
+
* Runs `work` on a fixed schedule, forever, and RESTARTS the schedule itself
|
|
211451
|
+
* if it ever dies for any reason other than this scope closing.
|
|
211452
|
+
*
|
|
211453
|
+
* `Effect.repeat(work, Schedule.spaced(interval)).pipe(Effect.forkScoped)`
|
|
211454
|
+
* alone has no restart path. `work` catching its own errors only protects
|
|
211455
|
+
* the TICK: an interrupt that lands while `Effect.repeat` is asleep between
|
|
211456
|
+
* ticks — which, at any non-trivial interval, is nearly this loop's entire
|
|
211457
|
+
* life — happens outside anything `work` wraps, and kills that one fiber
|
|
211458
|
+
* outright with nothing logged, because nothing was running to log from.
|
|
211459
|
+
* The process this runs in can otherwise be perfectly healthy while the
|
|
211460
|
+
* schedule is silently, permanently dead.
|
|
211461
|
+
*
|
|
211462
|
+
* This runs the schedule on its own child fiber, raced against an explicit
|
|
211463
|
+
* shutdown signal fired by a finalizer registered in this scope. Only that
|
|
211464
|
+
* signal stops the loop for good; any other death of the schedule fiber —
|
|
211465
|
+
* whatever causes it, defect or interrupt — logs and restarts it. `work`
|
|
211466
|
+
* itself must still handle its own EXPECTED failures (this only supervises
|
|
211467
|
+
* the schedule, and treats every death of it as unexpected).
|
|
211468
|
+
*/
|
|
211469
|
+
function runSupervisedRepeat(input) {
|
|
211470
|
+
return gen(function* () {
|
|
211471
|
+
const shutdownSignal = yield* make$39();
|
|
211472
|
+
yield* addFinalizer$2(() => succeed$3(shutdownSignal, void 0));
|
|
211473
|
+
let firstAttempt = true;
|
|
211474
|
+
while (true) {
|
|
211475
|
+
if (!firstAttempt) yield* sleep$4(input.interval);
|
|
211476
|
+
firstAttempt = false;
|
|
211477
|
+
const scheduleFiber = yield* forkChild(repeat(input.work, spaced(input.interval)));
|
|
211478
|
+
const outcome = yield* race(await_(scheduleFiber), _await(shutdownSignal).pipe(as$3("shutdown")));
|
|
211479
|
+
if (outcome === "shutdown") {
|
|
211480
|
+
yield* interrupt$4(scheduleFiber);
|
|
211481
|
+
return;
|
|
211482
|
+
}
|
|
211483
|
+
yield* logError(`${input.label} died unexpectedly — restarting`, { cause: isFailure(outcome) ? pretty(outcome.cause) : "unknown exit" });
|
|
211484
|
+
}
|
|
211485
|
+
});
|
|
211486
|
+
}
|
|
211487
|
+
//#endregion
|
|
211238
211488
|
//#region src/provider/Layers/ClaudeProvider.ts
|
|
211239
211489
|
function endpointProfileDisplayNames(settings) {
|
|
211240
211490
|
return Object.fromEntries(settings.endpointProfiles.filter((p) => p.displayName).map((p) => [p.slug, p.displayName]));
|
|
@@ -211736,7 +211986,21 @@ const nativeClaudeProviderStatus = fn$1("nativeClaudeProviderStatus")(function*
|
|
|
211736
211986
|
}
|
|
211737
211987
|
});
|
|
211738
211988
|
});
|
|
211739
|
-
|
|
211989
|
+
/**
|
|
211990
|
+
* Adds what the CLI said about its credentials. Every check where
|
|
211991
|
+
* `claude --version` ran and exited 0 reaches here, including one whose
|
|
211992
|
+
* version did not parse; that one has no key to look a probe answer up by, so
|
|
211993
|
+
* only the store is added.
|
|
211994
|
+
*/
|
|
211995
|
+
function withClaudeCredentialAnswers(provider, resolve, input) {
|
|
211996
|
+
if (!resolve) return succeed(provider);
|
|
211997
|
+
return resolve(input).pipe(map$3((answers) => ({
|
|
211998
|
+
...provider,
|
|
211999
|
+
...answers
|
|
212000
|
+
})));
|
|
212001
|
+
}
|
|
212002
|
+
const checkClaudeProviderStatus = fn$1("checkClaudeProviderStatus")(function* (resolvers = {}) {
|
|
212003
|
+
const { resolveSubscriptionType, resolveSlashCommands, resolveModels, resolveCredentialAnswers } = resolvers;
|
|
211740
212004
|
const config = getOrElse(yield* serviceOption(ServerConfig), () => ({
|
|
211741
212005
|
...DEFAULT_PROVIDER_AUTH_CONFIG,
|
|
211742
212006
|
forgeClaudeConfigPath: void 0
|
|
@@ -211808,19 +212072,24 @@ const checkClaudeProviderStatus = fn$1("checkClaudeProviderStatus")(function* (r
|
|
|
211808
212072
|
});
|
|
211809
212073
|
}
|
|
211810
212074
|
const executableFallbackModels = modelsForClaudeCliVersion(fallbackModels, parsedVersion);
|
|
211811
|
-
|
|
212075
|
+
const credentialAnswersInput = {
|
|
212076
|
+
binaryPath: claudeSettings.binaryPath,
|
|
212077
|
+
version: claudeVersionFromOutput(version.stdout),
|
|
212078
|
+
configDirectory: effectiveConfigPath
|
|
212079
|
+
};
|
|
212080
|
+
if (personalClaudeInVmEnabled()) return yield* withClaudeCredentialAnswers(yield* nativeClaudeProviderStatus({
|
|
211812
212081
|
enabled: claudeSettings.enabled,
|
|
211813
212082
|
checkedAt,
|
|
211814
212083
|
version: parsedVersion,
|
|
211815
212084
|
configPath: effectiveConfigPath,
|
|
211816
212085
|
models: executableFallbackModels,
|
|
211817
212086
|
provenance
|
|
211818
|
-
});
|
|
212087
|
+
}), resolveCredentialAnswers, credentialAnswersInput);
|
|
211819
212088
|
const capabilitiesProbeInput = claudeCapabilitiesProbeInput(claudeSettings.binaryPath, effectiveConfigPath);
|
|
211820
212089
|
const discovery = yield* resolveClaudeDiscovery(capabilitiesProbeInput, resolveSlashCommands, resolveModels);
|
|
211821
212090
|
const models = modelsForClaudeCliVersion(providerModelsFromSettings(resolveClaudeProviderModels(discovery.models), PROVIDER$12, claudeSettings.customModels, DEFAULT_CLAUDE_MODEL_CAPABILITIES, endpointProfileDisplayNames(claudeSettings)), parsedVersion);
|
|
211822
212091
|
const authProbe = yield* runClaudeCommand(["auth", "status"]).pipe(timeoutOption(DEFAULT_TIMEOUT_MS$3), result);
|
|
211823
|
-
return buildClaudeProviderFromAuthProbe({
|
|
212092
|
+
return yield* withClaudeCredentialAnswers(buildClaudeProviderFromAuthProbe({
|
|
211824
212093
|
authProbe,
|
|
211825
212094
|
authMetadata: yield* resolveClaudeAuthMetadata(authProbe, capabilitiesProbeInput, resolveSubscriptionType),
|
|
211826
212095
|
checkedAt,
|
|
@@ -211829,7 +212098,7 @@ const checkClaudeProviderStatus = fn$1("checkClaudeProviderStatus")(function* (r
|
|
|
211829
212098
|
slashCommands: discovery.slashCommands,
|
|
211830
212099
|
parsedVersion,
|
|
211831
212100
|
provenance
|
|
211832
|
-
});
|
|
212101
|
+
}), resolveCredentialAnswers, credentialAnswersInput);
|
|
211833
212102
|
});
|
|
211834
212103
|
const makePendingClaudeProvider = (claudeSettings) => {
|
|
211835
212104
|
const checkedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -211861,30 +212130,76 @@ const makePendingClaudeProvider = (claudeSettings) => {
|
|
|
211861
212130
|
}
|
|
211862
212131
|
});
|
|
211863
212132
|
};
|
|
211864
|
-
|
|
211865
|
-
|
|
211866
|
-
|
|
211867
|
-
|
|
211868
|
-
|
|
211869
|
-
|
|
211870
|
-
|
|
211871
|
-
|
|
211872
|
-
|
|
211873
|
-
|
|
211874
|
-
|
|
211875
|
-
|
|
211876
|
-
|
|
211877
|
-
|
|
211878
|
-
|
|
211879
|
-
|
|
211880
|
-
|
|
211881
|
-
|
|
211882
|
-
|
|
211883
|
-
|
|
211884
|
-
|
|
211885
|
-
|
|
211886
|
-
});
|
|
211887
|
-
}));
|
|
212133
|
+
/**
|
|
212134
|
+
* A refresh can wait behind a check that already holds the provider's refresh
|
|
212135
|
+
* permit before running its own, so it gets two check budgets.
|
|
212136
|
+
*/
|
|
212137
|
+
const CREDENTIAL_ANSWER_REFRESH_TIMEOUT_MS = 2 * (CLAUDE_VERSION_PROBE_TIMEOUT_MS + CAPABILITIES_PROBE_TIMEOUT_MS$1 + DEFAULT_TIMEOUT_MS$3);
|
|
212138
|
+
/** The gap after each answer refresh, and the pause before a restart. */
|
|
212139
|
+
const CREDENTIAL_ANSWER_REFRESH_SPACING = seconds(1);
|
|
212140
|
+
/**
|
|
212141
|
+
* Reruns the check when a probe reaches a new or changed answer, so the
|
|
212142
|
+
* inventory carries it without waiting for the next scheduled check. Answers
|
|
212143
|
+
* that arrive during a refresh collapse into one more refresh.
|
|
212144
|
+
*
|
|
212145
|
+
* A refresh that fails, dies or outlives its timeout is logged, and the loop
|
|
212146
|
+
* goes back to waiting for the next answer. The timeout interrupts the check,
|
|
212147
|
+
* which hands back the refresh permit. `runSupervisedRepeat` restarts the loop
|
|
212148
|
+
* after any interrupt that does not come from the scope closing; closing the
|
|
212149
|
+
* scope stops it and drops the subscription.
|
|
212150
|
+
*/
|
|
212151
|
+
const refreshOnNewCredentialDirectoryAnswer = fn$1("refreshOnNewCredentialDirectoryAnswer")(function* (credentialDirectoryAnswers, refresh) {
|
|
212152
|
+
const changed = yield* sliding(1);
|
|
212153
|
+
yield* acquireRelease(sync$1(() => credentialDirectoryAnswers.subscribe(() => {
|
|
212154
|
+
offerUnsafe(changed, void 0);
|
|
212155
|
+
})), (unsubscribe) => sync$1(unsubscribe));
|
|
212156
|
+
const refreshOnce = refresh.pipe(timeout$1(CREDENTIAL_ANSWER_REFRESH_TIMEOUT_MS), asVoid, catchCause((cause) => hasInterruptsOnly(cause) ? interrupt$1 : logWarning$1("Claude refresh for a new credential-directory answer failed", { cause: pretty(cause) })));
|
|
212157
|
+
yield* forkScoped(runSupervisedRepeat({
|
|
212158
|
+
label: "Claude credential-directory answer refresh",
|
|
212159
|
+
work: take$1(changed).pipe(andThen(refreshOnce)),
|
|
212160
|
+
interval: CREDENTIAL_ANSWER_REFRESH_SPACING
|
|
212161
|
+
}));
|
|
212162
|
+
});
|
|
212163
|
+
/** The Claude provider. Tests hand in their own answers and store read. */
|
|
212164
|
+
function makeClaudeProviderLive(options = {}) {
|
|
212165
|
+
const credentialDirectoryAnswers = options.credentialDirectoryAnswers ?? claudeCredentialDirectoryAnswers;
|
|
212166
|
+
const resolveCredentialAnswers = makeClaudeCredentialAnswersResolver({
|
|
212167
|
+
...options,
|
|
212168
|
+
credentialDirectoryAnswers
|
|
212169
|
+
});
|
|
212170
|
+
return effect(ClaudeProvider, gen(function* () {
|
|
212171
|
+
const serverSettings = yield* ServerSettingsService;
|
|
212172
|
+
const spawner = yield* ChildProcessSpawner;
|
|
212173
|
+
const subscriptionProbeCache = yield* make$51({
|
|
212174
|
+
capacity: 4,
|
|
212175
|
+
timeToLive: minutes(5),
|
|
212176
|
+
lookup: (key) => {
|
|
212177
|
+
const [binaryPath, configPath] = JSON.parse(key);
|
|
212178
|
+
return probeClaudeCapabilities({
|
|
212179
|
+
binaryPath,
|
|
212180
|
+
...configPath ? { configPath } : {}
|
|
212181
|
+
});
|
|
212182
|
+
}
|
|
212183
|
+
});
|
|
212184
|
+
const getDiscovery = (input) => get$8(subscriptionProbeCache, JSON.stringify([input.binaryPath, input.configPath]));
|
|
212185
|
+
const checkProvider = checkClaudeProviderStatus({
|
|
212186
|
+
resolveSubscriptionType: (input) => getDiscovery(input).pipe(map$3((probe) => probe?.subscriptionType)),
|
|
212187
|
+
resolveSlashCommands: (input) => getDiscovery(input).pipe(map$3((probe) => probe?.slashCommands)),
|
|
212188
|
+
resolveModels: (input) => getDiscovery(input).pipe(map$3((probe) => probe?.models)),
|
|
212189
|
+
resolveCredentialAnswers
|
|
212190
|
+
}).pipe(provideService(ServerSettingsService, serverSettings), provideService(ChildProcessSpawner, spawner));
|
|
212191
|
+
const provider = yield* makeManagedServerProvider({
|
|
212192
|
+
getSettings: serverSettings.getSettings.pipe(map$3((settings) => settings.providers.claudeAgent), orDie),
|
|
212193
|
+
streamSettings: serverSettings.streamChanges.pipe(map$7((settings) => settings.providers.claudeAgent)),
|
|
212194
|
+
haveSettingsChanged: (previous, next) => !equals(previous, next),
|
|
212195
|
+
initialSnapshot: makePendingClaudeProvider,
|
|
212196
|
+
checkProvider
|
|
212197
|
+
});
|
|
212198
|
+
yield* refreshOnNewCredentialDirectoryAnswer(credentialDirectoryAnswers, provider.refresh);
|
|
212199
|
+
return provider;
|
|
212200
|
+
}));
|
|
212201
|
+
}
|
|
212202
|
+
const ClaudeProviderLive = makeClaudeProviderLive();
|
|
211888
212203
|
//#endregion
|
|
211889
212204
|
//#region src/provider/Services/ClaudeAdapter.ts
|
|
211890
212205
|
/**
|
|
@@ -287039,46 +287354,6 @@ const makeRuntimeDrainState = gen(function* () {
|
|
|
287039
287354
|
var RuntimeDrainState = class extends Service$1()("forge/runtimeDrain/RuntimeDrainState") {};
|
|
287040
287355
|
const RuntimeDrainStateLive = effect(RuntimeDrainState, makeRuntimeDrainState);
|
|
287041
287356
|
//#endregion
|
|
287042
|
-
//#region src/runtimeDrain/supervisedRepeat.ts
|
|
287043
|
-
/**
|
|
287044
|
-
* Runs `work` on a fixed schedule, forever, and RESTARTS the schedule itself
|
|
287045
|
-
* if it ever dies for any reason other than this scope closing.
|
|
287046
|
-
*
|
|
287047
|
-
* `Effect.repeat(work, Schedule.spaced(interval)).pipe(Effect.forkScoped)`
|
|
287048
|
-
* alone has no restart path. `work` catching its own errors only protects
|
|
287049
|
-
* the TICK: an interrupt that lands while `Effect.repeat` is asleep between
|
|
287050
|
-
* ticks — which, at any non-trivial interval, is nearly this loop's entire
|
|
287051
|
-
* life — happens outside anything `work` wraps, and kills that one fiber
|
|
287052
|
-
* outright with nothing logged, because nothing was running to log from.
|
|
287053
|
-
* The process this runs in can otherwise be perfectly healthy while the
|
|
287054
|
-
* schedule is silently, permanently dead.
|
|
287055
|
-
*
|
|
287056
|
-
* This runs the schedule on its own child fiber, raced against an explicit
|
|
287057
|
-
* shutdown signal fired by a finalizer registered in this scope. Only that
|
|
287058
|
-
* signal stops the loop for good; any other death of the schedule fiber —
|
|
287059
|
-
* whatever causes it, defect or interrupt — logs and restarts it. `work`
|
|
287060
|
-
* itself must still handle its own EXPECTED failures (this only supervises
|
|
287061
|
-
* the schedule, and treats every death of it as unexpected).
|
|
287062
|
-
*/
|
|
287063
|
-
function runSupervisedRepeat(input) {
|
|
287064
|
-
return gen(function* () {
|
|
287065
|
-
const shutdownSignal = yield* make$39();
|
|
287066
|
-
yield* addFinalizer$2(() => succeed$3(shutdownSignal, void 0));
|
|
287067
|
-
let firstAttempt = true;
|
|
287068
|
-
while (true) {
|
|
287069
|
-
if (!firstAttempt) yield* sleep$4(input.interval);
|
|
287070
|
-
firstAttempt = false;
|
|
287071
|
-
const scheduleFiber = yield* forkChild(repeat(input.work, spaced(input.interval)));
|
|
287072
|
-
const outcome = yield* race(await_(scheduleFiber), _await(shutdownSignal).pipe(as$3("shutdown")));
|
|
287073
|
-
if (outcome === "shutdown") {
|
|
287074
|
-
yield* interrupt$4(scheduleFiber);
|
|
287075
|
-
return;
|
|
287076
|
-
}
|
|
287077
|
-
yield* logError(`${input.label} died unexpectedly — restarting`, { cause: isFailure(outcome) ? pretty(outcome.cause) : "unknown exit" });
|
|
287078
|
-
}
|
|
287079
|
-
});
|
|
287080
|
-
}
|
|
287081
|
-
//#endregion
|
|
287082
287357
|
//#region src/runtimeDrain/RuntimeDrainReporter.ts
|
|
287083
287358
|
const HEARTBEAT_INTERVAL = seconds(30);
|
|
287084
287359
|
const HEARTBEAT_TICK_TIMEOUT = seconds(60);
|
|
@@ -294449,7 +294724,7 @@ function resolveBuildCommitFromEnv(env) {
|
|
|
294449
294724
|
* environment descriptor down instead of reporting an honest "unknown".
|
|
294450
294725
|
*/
|
|
294451
294726
|
function readBakedBuildCommit() {
|
|
294452
|
-
return "
|
|
294727
|
+
return "9243995fc67ca68aa610fabccbf48bba35a5ffd1";
|
|
294453
294728
|
}
|
|
294454
294729
|
async function resolveServerBuildCommit(input) {
|
|
294455
294730
|
if (isFullCommitSha(input.baked)) return input.baked;
|