@cmmd-center/forge 0.10.7 → 0.10.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 +395 -324
- package/dist/bin.mjs +395 -324
- package/dist/client/assets/{DiffPanel-BqOO3dsl.js → DiffPanel-xCfkBV0D.js} +3 -3
- package/dist/client/assets/{DiffPanel.logic-Bzm8oiCr.js → DiffPanel.logic-BfOamVHM.js} +2 -2
- package/dist/client/assets/DiffPanelShell-B6MeDvYA.js +2531 -0
- package/dist/client/assets/{DiffWorkerPoolProvider-BsMgSHbg.js → DiffWorkerPoolProvider-C-r-Zusj.js} +9 -9
- package/dist/client/assets/{PullRequestCodePanel-DNrNrubs.js → PullRequestCodePanel-BSLzdOzf.js} +3 -3
- package/dist/client/assets/{Virtualizer-RRV_x18w.js → Virtualizer-4ILVlhCf.js} +2 -2
- package/dist/client/assets/{index-D22UpSjv.css → index-CUmbThfW.css} +1 -1
- package/dist/client/assets/index-CjhPsbaL.js +151 -0
- package/dist/client/index.html +13 -6
- package/dist/forge-build.json +1 -1
- package/package.json +1 -1
- package/dist/client/assets/DiffPanelShell-DVVw1mR3.js +0 -2531
- package/dist/client/assets/index-DCVtRkq1.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.10.
|
|
16523
|
+
const FORGE_RELEASE_VERSION = "0.10.6";
|
|
16524
16524
|
//#endregion
|
|
16525
16525
|
//#region ../../packages/shared/src/hostProcess.ts
|
|
16526
16526
|
/**
|
|
@@ -65121,7 +65121,7 @@ function normalizeNumberish(value) {
|
|
|
65121
65121
|
}
|
|
65122
65122
|
//#endregion
|
|
65123
65123
|
//#region package.json
|
|
65124
|
-
var version$1 = "0.10.
|
|
65124
|
+
var version$1 = "0.10.9";
|
|
65125
65125
|
//#endregion
|
|
65126
65126
|
//#region src/sentry.ts
|
|
65127
65127
|
const SERVER_APP_NAME = "forge-server";
|
|
@@ -93114,6 +93114,31 @@ function lifecycleIntentCommandId(runtimeId, threadId, requestedAt) {
|
|
|
93114
93114
|
return CommandId.make("lifecycle-intent:" + stableReplicaDigest(runtimeId, threadId, requestedAt));
|
|
93115
93115
|
}
|
|
93116
93116
|
//#endregion
|
|
93117
|
+
//#region src/runtimeReplication/replicaHydrationProjects.ts
|
|
93118
|
+
function activePathMatchedProjects(projects, index, summary) {
|
|
93119
|
+
return projects.filter((project) => project.deletedAt === null && (project.id === summary.projectId || index.runtime.workspaceRoot !== null && project.workspaceRoot === index.runtime.workspaceRoot));
|
|
93120
|
+
}
|
|
93121
|
+
const resolveRepositoryMatchedProjects = fn$1("resolveRepositoryMatchedProjects")(function* (projects, replicaRepositoryFullName, dependencies) {
|
|
93122
|
+
if (replicaRepositoryFullName === null) return [];
|
|
93123
|
+
return yield* filter$1(projects.filter((project) => project.deletedAt === null), (project) => dependencies.resolveProjectRepositoryFullName(project.workspaceRoot).pipe(map$3((repositoryFullName) => repositoryFullName?.toLowerCase() === replicaRepositoryFullName)), { concurrency: 1 });
|
|
93124
|
+
});
|
|
93125
|
+
const resolveLocalReplicaProjects = fn$1("resolveLocalReplicaProjects")(function* (projects, index, summary, dependencies) {
|
|
93126
|
+
const pathMatches = activePathMatchedProjects(projects, index, summary);
|
|
93127
|
+
if (pathMatches.length > 0) return {
|
|
93128
|
+
projects: pathMatches,
|
|
93129
|
+
repositoryRemapped: false
|
|
93130
|
+
};
|
|
93131
|
+
return {
|
|
93132
|
+
projects: yield* resolveRepositoryMatchedProjects(projects, index.runtime.githubRepoFullName?.toLowerCase() ?? null, dependencies),
|
|
93133
|
+
repositoryRemapped: true
|
|
93134
|
+
};
|
|
93135
|
+
});
|
|
93136
|
+
function replicaWorkspaceMatchesLocalProject(input) {
|
|
93137
|
+
if (input.detail.runtime.workspaceRoot === input.localProject.workspaceRoot) return true;
|
|
93138
|
+
const localRepository = input.localProjectRepositoryFullName?.toLowerCase() ?? null;
|
|
93139
|
+
return localRepository !== null && input.detail.runtime.githubRepoFullName?.toLowerCase() === localRepository && input.detail.project.githubRepoFullName?.toLowerCase() === localRepository;
|
|
93140
|
+
}
|
|
93141
|
+
//#endregion
|
|
93117
93142
|
//#region src/runtimeReplication/protocol.ts
|
|
93118
93143
|
const EMPTY_RUNTIME_THREAD_HEAD_HASH = "sha256:47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU";
|
|
93119
93144
|
const REPLICA_MESSAGE_ID_PREFIX = "replica-source-v1:";
|
|
@@ -93308,25 +93333,6 @@ function replicaSummaryMatchesDetail(summary, detail) {
|
|
|
93308
93333
|
[summary.lastActivityAt, detail.thread.lastActivityAt]
|
|
93309
93334
|
].every(([summaryValue, detailValue]) => summaryValue === detailValue);
|
|
93310
93335
|
}
|
|
93311
|
-
function replicaSummaryPayload(summary) {
|
|
93312
|
-
return {
|
|
93313
|
-
conversationId: summary.conversationId,
|
|
93314
|
-
project: {
|
|
93315
|
-
projectId: summary.projectId,
|
|
93316
|
-
title: summary.projectTitle,
|
|
93317
|
-
githubRepoFullName: summary.projectGithubRepoFullName,
|
|
93318
|
-
branch: summary.projectBranch
|
|
93319
|
-
},
|
|
93320
|
-
thread: {
|
|
93321
|
-
threadId: summary.threadId,
|
|
93322
|
-
title: summary.title,
|
|
93323
|
-
status: summary.status,
|
|
93324
|
-
model: summary.model,
|
|
93325
|
-
branch: summary.branch,
|
|
93326
|
-
lastActivityAt: summary.lastActivityAt
|
|
93327
|
-
}
|
|
93328
|
-
};
|
|
93329
|
-
}
|
|
93330
93336
|
function hasValidReplicaGeneration(runtimeId, threadId, generationId, threadStatus, sourceEvents) {
|
|
93331
93337
|
const streamKey = "thread:" + threadId;
|
|
93332
93338
|
const base = runtimeThreadGenerationId(runtimeId, streamKey);
|
|
@@ -93467,30 +93473,11 @@ function threadDates(events, fallback) {
|
|
|
93467
93473
|
updatedAt: events.at(-1).occurredAt
|
|
93468
93474
|
};
|
|
93469
93475
|
}
|
|
93470
|
-
function replicaWorkspaceMatchesLocalProject(input) {
|
|
93471
|
-
if (input.detail.runtime.workspaceRoot === input.localProject.workspaceRoot) return true;
|
|
93472
|
-
const localRepository = input.localProjectRepositoryFullName?.toLowerCase() ?? null;
|
|
93473
|
-
return localRepository !== null && input.detail.runtime.githubRepoFullName?.toLowerCase() === localRepository && input.detail.project.githubRepoFullName?.toLowerCase() === localRepository;
|
|
93474
|
-
}
|
|
93475
93476
|
function replicaToOrchestrationThread(input) {
|
|
93476
|
-
const
|
|
93477
|
-
data: {
|
|
93478
|
-
runtime: input.indexRuntimePayload,
|
|
93479
|
-
reachability: "unknown",
|
|
93480
|
-
threads: [input.summaryPayload],
|
|
93481
|
-
nextCursor: null
|
|
93482
|
-
},
|
|
93483
|
-
meta: {
|
|
93484
|
-
domain: "runtimeThreadIndex",
|
|
93485
|
-
version: "1.0",
|
|
93486
|
-
timestamp: input.hydratedAt
|
|
93487
|
-
}
|
|
93488
|
-
});
|
|
93477
|
+
const { indexRuntime, summary } = input;
|
|
93489
93478
|
const detail = decodeReplicaThreadDetail(input.replicaPayload);
|
|
93490
|
-
if (index === null) return null;
|
|
93491
|
-
const summary = index.threads[0];
|
|
93492
93479
|
const sourceEvents = detail?.events.map(replicaSourceEvent) ?? [];
|
|
93493
|
-
if (detail === null ||
|
|
93480
|
+
if (detail === null || indexRuntime.id !== input.expectedRuntimeId || detail.runtime.id !== input.expectedRuntimeId || !replicaRuntimeMatches(indexRuntime, detail.runtime) || !replicaSummaryMatchesDetail(summary, detail) || input.localProject.deletedAt !== null || input.localProject.defaultModelSelection === null || detail.runtime.workspaceRoot === null || !replicaWorkspaceMatchesLocalProject({
|
|
93494
93481
|
detail,
|
|
93495
93482
|
localProject: input.localProject,
|
|
93496
93483
|
localProjectRepositoryFullName: input.localProjectRepositoryFullName
|
|
@@ -93545,24 +93532,6 @@ function replicaHydrationFailure(detail, cause) {
|
|
|
93545
93532
|
//#endregion
|
|
93546
93533
|
//#region src/runtimeReplication/replicaHydration.ts
|
|
93547
93534
|
const REPLICA_INDEX_PAGE_SIZE$1 = 100;
|
|
93548
|
-
function activePathMatchedProjects(state, index, summary) {
|
|
93549
|
-
return state.initialModel.projects.filter((project) => project.deletedAt === null && (project.id === summary.projectId || index.runtime.workspaceRoot !== null && project.workspaceRoot === index.runtime.workspaceRoot));
|
|
93550
|
-
}
|
|
93551
|
-
const resolveRepositoryMatchedProjects = fn$1("resolveRepositoryMatchedProjects")(function* (state, replicaRepositoryFullName, dependencies) {
|
|
93552
|
-
if (replicaRepositoryFullName === null) return [];
|
|
93553
|
-
return yield* filter$1(state.initialModel.projects.filter((project) => project.deletedAt === null), (project) => dependencies.resolveProjectRepositoryFullName(project.workspaceRoot).pipe(map$3((repositoryFullName) => repositoryFullName?.toLowerCase() === replicaRepositoryFullName)), { concurrency: 1 });
|
|
93554
|
-
});
|
|
93555
|
-
const resolveLocalReplicaProjects = fn$1("resolveLocalReplicaProjects")(function* (state, index, summary, dependencies) {
|
|
93556
|
-
const pathMatches = activePathMatchedProjects(state, index, summary);
|
|
93557
|
-
if (pathMatches.length > 0) return {
|
|
93558
|
-
projects: pathMatches,
|
|
93559
|
-
repositoryRemapped: false
|
|
93560
|
-
};
|
|
93561
|
-
return {
|
|
93562
|
-
projects: yield* resolveRepositoryMatchedProjects(state, index.runtime.githubRepoFullName?.toLowerCase() ?? null, dependencies),
|
|
93563
|
-
repositoryRemapped: true
|
|
93564
|
-
};
|
|
93565
|
-
});
|
|
93566
93535
|
const readValidatedIndex = fn$1("readValidatedReplicaIndex")(function* (expectedRuntimeId, cursor, dependencies) {
|
|
93567
93536
|
const rawIndex = yield* dependencies.readIndex({
|
|
93568
93537
|
limit: REPLICA_INDEX_PAGE_SIZE$1,
|
|
@@ -93588,7 +93557,7 @@ const prepareReplicaSummary = fn$1("prepareReplicaSummary")(function* (expectedR
|
|
|
93588
93557
|
state.skippedQuarantined += 1;
|
|
93589
93558
|
return;
|
|
93590
93559
|
}
|
|
93591
|
-
const localResolution = yield* resolveLocalReplicaProjects(state, index, summary, dependencies);
|
|
93560
|
+
const localResolution = yield* resolveLocalReplicaProjects(state.initialModel.projects, index, summary, dependencies);
|
|
93592
93561
|
const localProjects = localResolution.projects;
|
|
93593
93562
|
if (localProjects.length !== 1) return yield* replicaHydrationFailure("replica project '" + summary.projectId + "' does not resolve to one active workspace");
|
|
93594
93563
|
const detail = yield* dependencies.readThread({ threadId: summary.threadId });
|
|
@@ -93599,8 +93568,8 @@ const prepareReplicaSummary = fn$1("prepareReplicaSummary")(function* (expectedR
|
|
|
93599
93568
|
localProject: localProjects[0],
|
|
93600
93569
|
localProjectRepositoryFullName: localResolution.repositoryRemapped ? index.runtime.githubRepoFullName : null,
|
|
93601
93570
|
replicaPayload: detail,
|
|
93602
|
-
|
|
93603
|
-
|
|
93571
|
+
indexRuntime: index.runtime,
|
|
93572
|
+
summary
|
|
93604
93573
|
});
|
|
93605
93574
|
if (candidate === null) return yield* replicaHydrationFailure("thread '" + summary.threadId + "' failed identity or generation checks");
|
|
93606
93575
|
state.prepared.push({
|
|
@@ -99472,6 +99441,316 @@ function claudeWriteToken(env = process.env) {
|
|
|
99472
99441
|
return accessor.read(env);
|
|
99473
99442
|
}
|
|
99474
99443
|
//#endregion
|
|
99444
|
+
//#region src/egress/providerDeliveryReceipt.ts
|
|
99445
|
+
const PROVIDER_ACCOUNT_IDENTITY$2 = /^pai_v1_[A-Za-z0-9_-]{43}$/;
|
|
99446
|
+
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
99447
|
+
const RFC3339$1 = /^(\d{4})-(\d{2})-(\d{2})T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/;
|
|
99448
|
+
const RECEIPT_KEYS = new Set([
|
|
99449
|
+
"receiptId",
|
|
99450
|
+
"runtimeId",
|
|
99451
|
+
"machineId",
|
|
99452
|
+
"credentialEpoch",
|
|
99453
|
+
"identity",
|
|
99454
|
+
"issuedAt",
|
|
99455
|
+
"expiresAt"
|
|
99456
|
+
]);
|
|
99457
|
+
const BINDING_KEYS = new Set([
|
|
99458
|
+
"runtimeId",
|
|
99459
|
+
"machineId",
|
|
99460
|
+
"credentialEpoch",
|
|
99461
|
+
"identity"
|
|
99462
|
+
]);
|
|
99463
|
+
const CODEX_IDENTITY_KEYS = new Set([
|
|
99464
|
+
"kind",
|
|
99465
|
+
"provider",
|
|
99466
|
+
"providerAccountIdentity"
|
|
99467
|
+
]);
|
|
99468
|
+
const CLAUDE_IDENTITY_KEYS = new Set([
|
|
99469
|
+
"kind",
|
|
99470
|
+
"provider",
|
|
99471
|
+
"credentialGenerationId"
|
|
99472
|
+
]);
|
|
99473
|
+
function isRecord$13(value) {
|
|
99474
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
99475
|
+
}
|
|
99476
|
+
function isStrictRfc3339DateTime(value) {
|
|
99477
|
+
if (typeof value !== "string") return false;
|
|
99478
|
+
const match = RFC3339$1.exec(value);
|
|
99479
|
+
if (!match || !Number.isFinite(Date.parse(value))) return false;
|
|
99480
|
+
const year = Number(match[1]);
|
|
99481
|
+
const month = Number(match[2]);
|
|
99482
|
+
const day = Number(match[3]);
|
|
99483
|
+
return month >= 1 && month <= 12 && day >= 1 && day <= daysInMonth$1(year, month);
|
|
99484
|
+
}
|
|
99485
|
+
function daysInMonth$1(year, month) {
|
|
99486
|
+
if (month === 2) return year % 400 === 0 || year % 4 === 0 && year % 100 !== 0 ? 29 : 28;
|
|
99487
|
+
return [
|
|
99488
|
+
4,
|
|
99489
|
+
6,
|
|
99490
|
+
9,
|
|
99491
|
+
11
|
|
99492
|
+
].includes(month) ? 30 : 31;
|
|
99493
|
+
}
|
|
99494
|
+
function hasExactKeys$2(value, keys) {
|
|
99495
|
+
return Object.keys(value).every((key) => keys.has(key)) && Object.keys(value).length === keys.size;
|
|
99496
|
+
}
|
|
99497
|
+
function parseDeliveryIdentity(value, provider) {
|
|
99498
|
+
if (!isRecord$13(value)) return null;
|
|
99499
|
+
if (provider === "openai") return parseCodexDeliveryIdentity(value);
|
|
99500
|
+
if (provider === "anthropic") return parseClaudeDeliveryIdentity(value);
|
|
99501
|
+
return null;
|
|
99502
|
+
}
|
|
99503
|
+
function parseCodexDeliveryIdentity(value) {
|
|
99504
|
+
if (!hasExactKeys$2(value, CODEX_IDENTITY_KEYS) || value.kind !== "provider_account" || value.provider !== "codex" || typeof value.providerAccountIdentity !== "string" || !PROVIDER_ACCOUNT_IDENTITY$2.test(value.providerAccountIdentity)) return null;
|
|
99505
|
+
return {
|
|
99506
|
+
kind: "provider_account",
|
|
99507
|
+
provider: "codex",
|
|
99508
|
+
providerAccountIdentity: value.providerAccountIdentity
|
|
99509
|
+
};
|
|
99510
|
+
}
|
|
99511
|
+
function parseClaudeDeliveryIdentity(value) {
|
|
99512
|
+
if (!hasExactKeys$2(value, CLAUDE_IDENTITY_KEYS) || value.kind !== "credential_generation" || value.provider !== "claude" || typeof value.credentialGenerationId !== "string" || !UUID.test(value.credentialGenerationId)) return null;
|
|
99513
|
+
return {
|
|
99514
|
+
kind: "credential_generation",
|
|
99515
|
+
provider: "claude",
|
|
99516
|
+
credentialGenerationId: value.credentialGenerationId
|
|
99517
|
+
};
|
|
99518
|
+
}
|
|
99519
|
+
function parseProviderRuntimeDeliveryReceipt(value, expected) {
|
|
99520
|
+
if (!isRecord$13(value) || !hasExactKeys$2(value, RECEIPT_KEYS)) return null;
|
|
99521
|
+
const identity = parseDeliveryIdentity(value.identity, expected.provider);
|
|
99522
|
+
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;
|
|
99523
|
+
return {
|
|
99524
|
+
receiptId: value.receiptId,
|
|
99525
|
+
runtimeId: expected.runtimeId,
|
|
99526
|
+
machineId: expected.machineId,
|
|
99527
|
+
credentialEpoch: expected.credentialEpoch,
|
|
99528
|
+
identity,
|
|
99529
|
+
issuedAt: value.issuedAt,
|
|
99530
|
+
expiresAt: value.expiresAt
|
|
99531
|
+
};
|
|
99532
|
+
}
|
|
99533
|
+
function providerDeliveryBindingFromReceipt(receipt) {
|
|
99534
|
+
return {
|
|
99535
|
+
runtimeId: receipt.runtimeId,
|
|
99536
|
+
machineId: receipt.machineId,
|
|
99537
|
+
credentialEpoch: receipt.credentialEpoch,
|
|
99538
|
+
identity: receipt.identity
|
|
99539
|
+
};
|
|
99540
|
+
}
|
|
99541
|
+
function readProviderDeliveryBinding(value) {
|
|
99542
|
+
if (!isRecord$13(value) || !hasExactKeys$2(value, BINDING_KEYS)) return null;
|
|
99543
|
+
const identityProvider = isRecord$13(value.identity) ? value.identity.provider : void 0;
|
|
99544
|
+
const tokenProvider = identityProvider === "codex" ? "openai" : identityProvider === "claude" ? "anthropic" : null;
|
|
99545
|
+
if (!tokenProvider) return null;
|
|
99546
|
+
const identity = parseDeliveryIdentity(value.identity, tokenProvider);
|
|
99547
|
+
if (!identity || typeof value.runtimeId !== "string" || value.runtimeId.length === 0 || typeof value.machineId !== "string" || value.machineId.length === 0 || !Number.isInteger(value.credentialEpoch) || value.credentialEpoch < 0) return null;
|
|
99548
|
+
return {
|
|
99549
|
+
runtimeId: value.runtimeId,
|
|
99550
|
+
machineId: value.machineId,
|
|
99551
|
+
credentialEpoch: value.credentialEpoch,
|
|
99552
|
+
identity
|
|
99553
|
+
};
|
|
99554
|
+
}
|
|
99555
|
+
function providerDeliveryBindingsEqual(left, right) {
|
|
99556
|
+
if (left.runtimeId !== right.runtimeId || left.machineId !== right.machineId || left.credentialEpoch !== right.credentialEpoch || left.identity.kind !== right.identity.kind || left.identity.provider !== right.identity.provider) return false;
|
|
99557
|
+
if (left.identity.kind === "provider_account" && right.identity.kind === "provider_account") return left.identity.providerAccountIdentity === right.identity.providerAccountIdentity;
|
|
99558
|
+
return left.identity.kind === "credential_generation" && right.identity.kind === "credential_generation" && left.identity.credentialGenerationId === right.identity.credentialGenerationId;
|
|
99559
|
+
}
|
|
99560
|
+
//#endregion
|
|
99561
|
+
//#region src/provider/claudeReadinessReason.ts
|
|
99562
|
+
/**
|
|
99563
|
+
* The reason literals Forge has copy for, confirmed against CMMD-36441's
|
|
99564
|
+
* readiness service. If the route renames one, the rename lands here as a
|
|
99565
|
+
* fall-through to the generic sentence, never as a wrong sentence.
|
|
99566
|
+
*
|
|
99567
|
+
* Reading the reason is what makes `stale` legible. CMMD-36441 answers
|
|
99568
|
+
* `credential_reconnect_required` on a `stale` answer that still reports
|
|
99569
|
+
* `connected: true`, and the older `credential_generation_not_applied` on a
|
|
99570
|
+
* `stale` answer that simply has not landed yet. Those want opposite
|
|
99571
|
+
* sentences, and both used to get "Reconnect Claude in Settings" because the
|
|
99572
|
+
* guard read only the delivery status.
|
|
99573
|
+
*/
|
|
99574
|
+
const CODE_BY_UPSTREAM_REASON$1 = {
|
|
99575
|
+
credential_expired_refreshing: "CREDENTIAL_EXPIRED_REFRESHING",
|
|
99576
|
+
credential_reconnect_required: "CREDENTIAL_RECONNECT_REQUIRED",
|
|
99577
|
+
credential_not_connected: "CREDENTIAL_RECONNECT_REQUIRED",
|
|
99578
|
+
credential_generation_not_applied: "CREDENTIAL_GENERATION_NOT_APPLIED",
|
|
99579
|
+
runtime_unavailable: "RUNTIME_UNAVAILABLE"
|
|
99580
|
+
};
|
|
99581
|
+
const CLAUDE_NATIVE_CREDENTIAL_UNUSABLE_COPY = "The delivered Claude credential is unavailable or unusable in this runtime.";
|
|
99582
|
+
/**
|
|
99583
|
+
* An ISO 8601 instant, with or without fractional seconds, UTC or offset.
|
|
99584
|
+
* Anchored to nothing on purpose: CMMD wraps the time in a sentence, and the
|
|
99585
|
+
* time is the only part of that sentence Forge repeats.
|
|
99586
|
+
*/
|
|
99587
|
+
const ISO_INSTANT_PATTERN = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})/;
|
|
99588
|
+
function claudeReadinessReasonCode(reason) {
|
|
99589
|
+
if (typeof reason !== "string" || !Object.hasOwn(CODE_BY_UPSTREAM_REASON$1, reason)) return null;
|
|
99590
|
+
return CODE_BY_UPSTREAM_REASON$1[reason] ?? null;
|
|
99591
|
+
}
|
|
99592
|
+
function expiredAtFromReadinessMessage(message) {
|
|
99593
|
+
if (typeof message !== "string") return null;
|
|
99594
|
+
return ISO_INSTANT_PATTERN.exec(message)?.[0] ?? null;
|
|
99595
|
+
}
|
|
99596
|
+
function claudeCredentialExpiredTurnCopy(expiredAt) {
|
|
99597
|
+
return `The delivered Claude credential expired at ${expiredAt}. CMMD is delivering a refreshed one, so retry this turn in a moment.`;
|
|
99598
|
+
}
|
|
99599
|
+
function claudeCredentialExpiredCardCopy(expiredAt) {
|
|
99600
|
+
return `The delivered Claude credential expired at ${expiredAt}. CMMD is delivering a refreshed one to this runtime.`;
|
|
99601
|
+
}
|
|
99602
|
+
/**
|
|
99603
|
+
* The last allowlisted readiness reason this process saw.
|
|
99604
|
+
*
|
|
99605
|
+
* A server process serves exactly one runtime, so one slot is the whole store.
|
|
99606
|
+
* It holds a reason code and a timestamp, never credential bytes. The provider
|
|
99607
|
+
* catalog reads a local credential file and cannot tell an expired snapshot
|
|
99608
|
+
* from a blank one, so without this the card can only offer the generic
|
|
99609
|
+
* sentence while the guard already knows better.
|
|
99610
|
+
*/
|
|
99611
|
+
let latestVerdict = null;
|
|
99612
|
+
/**
|
|
99613
|
+
* Remember, or clear, what the readiness answer said.
|
|
99614
|
+
*
|
|
99615
|
+
* An answer carrying no allowlisted reason clears the slot, which is what makes
|
|
99616
|
+
* the card go back to the generic sentence the moment CMMD applies a
|
|
99617
|
+
* credential: an applied answer carries no reason.
|
|
99618
|
+
*/
|
|
99619
|
+
function recordClaudeReadinessVerdict(readiness) {
|
|
99620
|
+
const code = claudeReadinessReasonCode(readiness.reason);
|
|
99621
|
+
latestVerdict = code === null ? null : {
|
|
99622
|
+
code,
|
|
99623
|
+
expiredAt: expiredAtFromReadinessMessage(readiness.lastErrorMessage)
|
|
99624
|
+
};
|
|
99625
|
+
}
|
|
99626
|
+
/**
|
|
99627
|
+
* What the provider status card says about a delivered credential it cannot
|
|
99628
|
+
* use. Names the expiry only when a readiness answer supplied the time; a
|
|
99629
|
+
* guessed time would be worse than the generic sentence.
|
|
99630
|
+
*/
|
|
99631
|
+
function claudeNativeCredentialUnusableMessage() {
|
|
99632
|
+
const verdict = latestVerdict;
|
|
99633
|
+
if (verdict?.code === "CREDENTIAL_EXPIRED_REFRESHING" && verdict.expiredAt !== null) return claudeCredentialExpiredCardCopy(verdict.expiredAt);
|
|
99634
|
+
return CLAUDE_NATIVE_CREDENTIAL_UNUSABLE_COPY;
|
|
99635
|
+
}
|
|
99636
|
+
//#endregion
|
|
99637
|
+
//#region src/provider/providerReadiness.ts
|
|
99638
|
+
const GENERATION_HASH_PATTERN$1 = /^[a-f0-9]{64}$/;
|
|
99639
|
+
const STILL_APPLYING_STATUSES = new Set([
|
|
99640
|
+
"pending",
|
|
99641
|
+
"claimed",
|
|
99642
|
+
"activating"
|
|
99643
|
+
]);
|
|
99644
|
+
const OAUTH_SECRET_FIELDS = ["accessToken", "refreshToken"];
|
|
99645
|
+
var ProviderReadinessFetchError = class extends Error {
|
|
99646
|
+
constructor(failure) {
|
|
99647
|
+
super(failure);
|
|
99648
|
+
this.failure = failure;
|
|
99649
|
+
this.name = "ProviderReadinessFetchError";
|
|
99650
|
+
}
|
|
99651
|
+
};
|
|
99652
|
+
async function queryProviderReadiness(input) {
|
|
99653
|
+
if (input.sprite !== null && input.environmentId !== input.sprite.environmentId) return {
|
|
99654
|
+
kind: "query_failed",
|
|
99655
|
+
failure: "wrong_environment"
|
|
99656
|
+
};
|
|
99657
|
+
if (input.provider !== "claudeAgent" || input.sprite === null) return {
|
|
99658
|
+
kind: "ready",
|
|
99659
|
+
binding: null
|
|
99660
|
+
};
|
|
99661
|
+
const sprite = input.sprite;
|
|
99662
|
+
if (!GENERATION_HASH_PATTERN$1.test(sprite.localGenerationHash)) return {
|
|
99663
|
+
kind: "not_ready",
|
|
99664
|
+
reason: "generation_mismatch"
|
|
99665
|
+
};
|
|
99666
|
+
let snapshot;
|
|
99667
|
+
try {
|
|
99668
|
+
snapshot = await input.claude.fetch(sprite.runtimeId);
|
|
99669
|
+
} catch (cause) {
|
|
99670
|
+
if (cause instanceof ProviderReadinessFetchError) return {
|
|
99671
|
+
kind: "query_failed",
|
|
99672
|
+
failure: cause.failure
|
|
99673
|
+
};
|
|
99674
|
+
return {
|
|
99675
|
+
kind: "query_failed",
|
|
99676
|
+
failure: "cmmd_unavailable"
|
|
99677
|
+
};
|
|
99678
|
+
}
|
|
99679
|
+
return classifyClaudeSnapshot(snapshot, sprite);
|
|
99680
|
+
}
|
|
99681
|
+
function isAppliedClaudeSnapshot(snapshot) {
|
|
99682
|
+
return snapshot.connected === true && snapshot.deliveryStatus === "applied" && snapshot.nativeExecutable === true && typeof snapshot.generationId === "string" && snapshot.generationId.trim().length > 0;
|
|
99683
|
+
}
|
|
99684
|
+
function classifyUnappliedClaudeSnapshot(snapshot) {
|
|
99685
|
+
const code = claudeReadinessReasonCode(snapshot.reason);
|
|
99686
|
+
if (code === "RUNTIME_UNAVAILABLE") return {
|
|
99687
|
+
kind: "not_ready",
|
|
99688
|
+
reason: "environment_unavailable"
|
|
99689
|
+
};
|
|
99690
|
+
if (code === "CREDENTIAL_EXPIRED_REFRESHING" || code === "CREDENTIAL_GENERATION_NOT_APPLIED") return {
|
|
99691
|
+
kind: "not_ready",
|
|
99692
|
+
reason: "still_applying"
|
|
99693
|
+
};
|
|
99694
|
+
if (code === "CREDENTIAL_RECONNECT_REQUIRED") return {
|
|
99695
|
+
kind: "not_ready",
|
|
99696
|
+
reason: "credential_unusable"
|
|
99697
|
+
};
|
|
99698
|
+
if (STILL_APPLYING_STATUSES.has(snapshot.deliveryStatus)) return {
|
|
99699
|
+
kind: "not_ready",
|
|
99700
|
+
reason: "still_applying"
|
|
99701
|
+
};
|
|
99702
|
+
if (snapshot.deliveryStatus === "failed") return {
|
|
99703
|
+
kind: "not_ready",
|
|
99704
|
+
reason: "apply_failed"
|
|
99705
|
+
};
|
|
99706
|
+
return {
|
|
99707
|
+
kind: "not_ready",
|
|
99708
|
+
reason: "credential_unusable"
|
|
99709
|
+
};
|
|
99710
|
+
}
|
|
99711
|
+
function classifyClaudeSnapshot(snapshot, sprite) {
|
|
99712
|
+
if (!isAppliedClaudeSnapshot(snapshot)) return classifyUnappliedClaudeSnapshot(snapshot);
|
|
99713
|
+
const generationId = snapshot.generationId.trim();
|
|
99714
|
+
if (createHash("sha256").update(generationId).digest("hex") !== sprite.localGenerationHash) return {
|
|
99715
|
+
kind: "not_ready",
|
|
99716
|
+
reason: "generation_mismatch"
|
|
99717
|
+
};
|
|
99718
|
+
const deliveryReceipt = parseProviderRuntimeDeliveryReceipt(snapshot.deliveryReceipt, {
|
|
99719
|
+
provider: "anthropic",
|
|
99720
|
+
runtimeId: sprite.runtimeId,
|
|
99721
|
+
machineId: sprite.machineId,
|
|
99722
|
+
credentialEpoch: sprite.credentialEpoch,
|
|
99723
|
+
expiresAt: snapshot.deliveryReceipt?.expiresAt ?? null
|
|
99724
|
+
});
|
|
99725
|
+
if (deliveryReceipt?.identity.kind !== "credential_generation" || deliveryReceipt.identity.credentialGenerationId !== generationId) return {
|
|
99726
|
+
kind: "not_ready",
|
|
99727
|
+
reason: "sprite_identity_drift"
|
|
99728
|
+
};
|
|
99729
|
+
return {
|
|
99730
|
+
kind: "ready",
|
|
99731
|
+
binding: providerDeliveryBindingFromReceipt(deliveryReceipt)
|
|
99732
|
+
};
|
|
99733
|
+
}
|
|
99734
|
+
/**
|
|
99735
|
+
* A Claude.ai subscription blob is usable when claudeAiOauth holds at least one
|
|
99736
|
+
* non-empty secret. Metadata without tokens is how production showed Connected
|
|
99737
|
+
* (max) for three days while every turn failed to refresh.
|
|
99738
|
+
*/
|
|
99739
|
+
function hasUsableClaudeCredentialBlob(credentialJson) {
|
|
99740
|
+
try {
|
|
99741
|
+
const parsed = JSON.parse(credentialJson);
|
|
99742
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return false;
|
|
99743
|
+
const oauth = parsed.claudeAiOauth;
|
|
99744
|
+
if (typeof oauth !== "object" || oauth === null || Array.isArray(oauth)) return false;
|
|
99745
|
+
return OAUTH_SECRET_FIELDS.some((field) => {
|
|
99746
|
+
const value = oauth[field];
|
|
99747
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
99748
|
+
});
|
|
99749
|
+
} catch {
|
|
99750
|
+
return false;
|
|
99751
|
+
}
|
|
99752
|
+
}
|
|
99753
|
+
//#endregion
|
|
99475
99754
|
//#region src/providerAuth/ClaudeDeviceAuth.ts
|
|
99476
99755
|
const AUTHORIZE_URL_PATTERN = /https:\/\/[^\s]*\/oauth\/authorize\?[^\s]+/u;
|
|
99477
99756
|
const ANSI_ESCAPE_PATTERN$1 = new RegExp(String.raw`\x1B\[[0-?]*[ -/]*[@-~]`, "gu");
|
|
@@ -99753,21 +100032,7 @@ function resolveLocalClaudeCredentialPath(homePath) {
|
|
|
99753
100032
|
* an API-key config. Claude Code stores the subscription OAuth under a
|
|
99754
100033
|
* `claudeAiOauth` object; require that marker. Mirrors CMMD's
|
|
99755
100034
|
* validateClaudeCredentialJson.
|
|
99756
|
-
|
|
99757
|
-
function isClaudeSubscriptionCredential(credentialJson) {
|
|
99758
|
-
try {
|
|
99759
|
-
const parsed = JSON.parse(credentialJson);
|
|
99760
|
-
if (typeof parsed !== "object" || parsed === null) return false;
|
|
99761
|
-
const oauth = parsed.claudeAiOauth;
|
|
99762
|
-
if (typeof oauth !== "object" || oauth === null) return false;
|
|
99763
|
-
return hasUsableOauthSecrets(oauth);
|
|
99764
|
-
} catch {
|
|
99765
|
-
return false;
|
|
99766
|
-
}
|
|
99767
|
-
}
|
|
99768
|
-
/** Either of these alone is enough to authenticate. */
|
|
99769
|
-
const OAUTH_SECRET_FIELDS = ["accessToken", "refreshToken"];
|
|
99770
|
-
/**
|
|
100035
|
+
*
|
|
99771
100036
|
* Require AT LEAST ONE usable token before uploading anything.
|
|
99772
100037
|
*
|
|
99773
100038
|
* This gate used to end at "claudeAiOauth is an object", and in production that
|
|
@@ -99794,11 +100059,8 @@ const OAUTH_SECRET_FIELDS = ["accessToken", "refreshToken"];
|
|
|
99794
100059
|
* schema Anthropic might ship, and fields they add, rename or drop around these
|
|
99795
100060
|
* two keep flowing through untouched.
|
|
99796
100061
|
*/
|
|
99797
|
-
function
|
|
99798
|
-
return
|
|
99799
|
-
const value = oauth[field];
|
|
99800
|
-
return typeof value === "string" && value.trim().length > 0;
|
|
99801
|
-
});
|
|
100062
|
+
function isClaudeSubscriptionCredential(credentialJson) {
|
|
100063
|
+
return hasUsableClaudeCredentialBlob(credentialJson);
|
|
99802
100064
|
}
|
|
99803
100065
|
const EMAIL_FIELD_NAMES = new Set([
|
|
99804
100066
|
"email",
|
|
@@ -146345,12 +146607,12 @@ function decodeProviderKind(providerName, operation) {
|
|
|
146345
146607
|
detail: `Unknown persisted provider '${providerName}'.`
|
|
146346
146608
|
}));
|
|
146347
146609
|
}
|
|
146348
|
-
function isRecord$
|
|
146610
|
+
function isRecord$12(value) {
|
|
146349
146611
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
146350
146612
|
}
|
|
146351
146613
|
function mergeRuntimePayload(existing, next) {
|
|
146352
146614
|
if (next === void 0) return existing ?? null;
|
|
146353
|
-
if (isRecord$
|
|
146615
|
+
if (isRecord$12(existing) && isRecord$12(next)) return {
|
|
146354
146616
|
...existing,
|
|
146355
146617
|
...next
|
|
146356
146618
|
};
|
|
@@ -147936,123 +148198,6 @@ function buildCodexCredentialModelScope(input) {
|
|
|
147936
148198
|
return providerEgressModelScope(input.selectedModel, catalog);
|
|
147937
148199
|
}
|
|
147938
148200
|
//#endregion
|
|
147939
|
-
//#region src/egress/providerDeliveryReceipt.ts
|
|
147940
|
-
const PROVIDER_ACCOUNT_IDENTITY$2 = /^pai_v1_[A-Za-z0-9_-]{43}$/;
|
|
147941
|
-
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
147942
|
-
const RFC3339$1 = /^(\d{4})-(\d{2})-(\d{2})T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/;
|
|
147943
|
-
const RECEIPT_KEYS = new Set([
|
|
147944
|
-
"receiptId",
|
|
147945
|
-
"runtimeId",
|
|
147946
|
-
"machineId",
|
|
147947
|
-
"credentialEpoch",
|
|
147948
|
-
"identity",
|
|
147949
|
-
"issuedAt",
|
|
147950
|
-
"expiresAt"
|
|
147951
|
-
]);
|
|
147952
|
-
const BINDING_KEYS = new Set([
|
|
147953
|
-
"runtimeId",
|
|
147954
|
-
"machineId",
|
|
147955
|
-
"credentialEpoch",
|
|
147956
|
-
"identity"
|
|
147957
|
-
]);
|
|
147958
|
-
const CODEX_IDENTITY_KEYS = new Set([
|
|
147959
|
-
"kind",
|
|
147960
|
-
"provider",
|
|
147961
|
-
"providerAccountIdentity"
|
|
147962
|
-
]);
|
|
147963
|
-
const CLAUDE_IDENTITY_KEYS = new Set([
|
|
147964
|
-
"kind",
|
|
147965
|
-
"provider",
|
|
147966
|
-
"credentialGenerationId"
|
|
147967
|
-
]);
|
|
147968
|
-
function isRecord$12(value) {
|
|
147969
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
147970
|
-
}
|
|
147971
|
-
function isStrictRfc3339DateTime(value) {
|
|
147972
|
-
if (typeof value !== "string") return false;
|
|
147973
|
-
const match = RFC3339$1.exec(value);
|
|
147974
|
-
if (!match || !Number.isFinite(Date.parse(value))) return false;
|
|
147975
|
-
const year = Number(match[1]);
|
|
147976
|
-
const month = Number(match[2]);
|
|
147977
|
-
const day = Number(match[3]);
|
|
147978
|
-
return month >= 1 && month <= 12 && day >= 1 && day <= daysInMonth$1(year, month);
|
|
147979
|
-
}
|
|
147980
|
-
function daysInMonth$1(year, month) {
|
|
147981
|
-
if (month === 2) return year % 400 === 0 || year % 4 === 0 && year % 100 !== 0 ? 29 : 28;
|
|
147982
|
-
return [
|
|
147983
|
-
4,
|
|
147984
|
-
6,
|
|
147985
|
-
9,
|
|
147986
|
-
11
|
|
147987
|
-
].includes(month) ? 30 : 31;
|
|
147988
|
-
}
|
|
147989
|
-
function hasExactKeys$2(value, keys) {
|
|
147990
|
-
return Object.keys(value).every((key) => keys.has(key)) && Object.keys(value).length === keys.size;
|
|
147991
|
-
}
|
|
147992
|
-
function parseDeliveryIdentity(value, provider) {
|
|
147993
|
-
if (!isRecord$12(value)) return null;
|
|
147994
|
-
if (provider === "openai") return parseCodexDeliveryIdentity(value);
|
|
147995
|
-
if (provider === "anthropic") return parseClaudeDeliveryIdentity(value);
|
|
147996
|
-
return null;
|
|
147997
|
-
}
|
|
147998
|
-
function parseCodexDeliveryIdentity(value) {
|
|
147999
|
-
if (!hasExactKeys$2(value, CODEX_IDENTITY_KEYS) || value.kind !== "provider_account" || value.provider !== "codex" || typeof value.providerAccountIdentity !== "string" || !PROVIDER_ACCOUNT_IDENTITY$2.test(value.providerAccountIdentity)) return null;
|
|
148000
|
-
return {
|
|
148001
|
-
kind: "provider_account",
|
|
148002
|
-
provider: "codex",
|
|
148003
|
-
providerAccountIdentity: value.providerAccountIdentity
|
|
148004
|
-
};
|
|
148005
|
-
}
|
|
148006
|
-
function parseClaudeDeliveryIdentity(value) {
|
|
148007
|
-
if (!hasExactKeys$2(value, CLAUDE_IDENTITY_KEYS) || value.kind !== "credential_generation" || value.provider !== "claude" || typeof value.credentialGenerationId !== "string" || !UUID.test(value.credentialGenerationId)) return null;
|
|
148008
|
-
return {
|
|
148009
|
-
kind: "credential_generation",
|
|
148010
|
-
provider: "claude",
|
|
148011
|
-
credentialGenerationId: value.credentialGenerationId
|
|
148012
|
-
};
|
|
148013
|
-
}
|
|
148014
|
-
function parseProviderRuntimeDeliveryReceipt(value, expected) {
|
|
148015
|
-
if (!isRecord$12(value) || !hasExactKeys$2(value, RECEIPT_KEYS)) return null;
|
|
148016
|
-
const identity = parseDeliveryIdentity(value.identity, expected.provider);
|
|
148017
|
-
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;
|
|
148018
|
-
return {
|
|
148019
|
-
receiptId: value.receiptId,
|
|
148020
|
-
runtimeId: expected.runtimeId,
|
|
148021
|
-
machineId: expected.machineId,
|
|
148022
|
-
credentialEpoch: expected.credentialEpoch,
|
|
148023
|
-
identity,
|
|
148024
|
-
issuedAt: value.issuedAt,
|
|
148025
|
-
expiresAt: value.expiresAt
|
|
148026
|
-
};
|
|
148027
|
-
}
|
|
148028
|
-
function providerDeliveryBindingFromReceipt(receipt) {
|
|
148029
|
-
return {
|
|
148030
|
-
runtimeId: receipt.runtimeId,
|
|
148031
|
-
machineId: receipt.machineId,
|
|
148032
|
-
credentialEpoch: receipt.credentialEpoch,
|
|
148033
|
-
identity: receipt.identity
|
|
148034
|
-
};
|
|
148035
|
-
}
|
|
148036
|
-
function readProviderDeliveryBinding(value) {
|
|
148037
|
-
if (!isRecord$12(value) || !hasExactKeys$2(value, BINDING_KEYS)) return null;
|
|
148038
|
-
const identityProvider = isRecord$12(value.identity) ? value.identity.provider : void 0;
|
|
148039
|
-
const tokenProvider = identityProvider === "codex" ? "openai" : identityProvider === "claude" ? "anthropic" : null;
|
|
148040
|
-
if (!tokenProvider) return null;
|
|
148041
|
-
const identity = parseDeliveryIdentity(value.identity, tokenProvider);
|
|
148042
|
-
if (!identity || typeof value.runtimeId !== "string" || value.runtimeId.length === 0 || typeof value.machineId !== "string" || value.machineId.length === 0 || !Number.isInteger(value.credentialEpoch) || value.credentialEpoch < 0) return null;
|
|
148043
|
-
return {
|
|
148044
|
-
runtimeId: value.runtimeId,
|
|
148045
|
-
machineId: value.machineId,
|
|
148046
|
-
credentialEpoch: value.credentialEpoch,
|
|
148047
|
-
identity
|
|
148048
|
-
};
|
|
148049
|
-
}
|
|
148050
|
-
function providerDeliveryBindingsEqual(left, right) {
|
|
148051
|
-
if (left.runtimeId !== right.runtimeId || left.machineId !== right.machineId || left.credentialEpoch !== right.credentialEpoch || left.identity.kind !== right.identity.kind || left.identity.provider !== right.identity.provider) return false;
|
|
148052
|
-
if (left.identity.kind === "provider_account" && right.identity.kind === "provider_account") return left.identity.providerAccountIdentity === right.identity.providerAccountIdentity;
|
|
148053
|
-
return left.identity.kind === "credential_generation" && right.identity.kind === "credential_generation" && left.identity.credentialGenerationId === right.identity.credentialGenerationId;
|
|
148054
|
-
}
|
|
148055
|
-
//#endregion
|
|
148056
148201
|
//#region src/egress/providerEgressToken.ts
|
|
148057
148202
|
var ProviderEgressTokenError = class extends TaggedError("ProviderEgressTokenError") {};
|
|
148058
148203
|
const PROVIDER_EGRESS_TOKEN_TIMEOUT_MS = 1e4;
|
|
@@ -206978,6 +207123,7 @@ function toCanonicalItemType(raw) {
|
|
|
206978
207123
|
if (type.includes("computer")) return "mcp_tool_call";
|
|
206979
207124
|
if (type.includes("mcp")) return "mcp_tool_call";
|
|
206980
207125
|
if (type.includes("dynamic tool")) return "dynamic_tool_call";
|
|
207126
|
+
if (type.includes("sub agent")) return "collab_agent_tool_call";
|
|
206981
207127
|
if (type.includes("collab")) return "collab_agent_tool_call";
|
|
206982
207128
|
if (type.includes("web search")) return "web_search";
|
|
206983
207129
|
if (type.includes("image")) return "image_view";
|
|
@@ -207042,6 +207188,21 @@ function itemDetail(item, payload) {
|
|
|
207042
207188
|
return trimmed;
|
|
207043
207189
|
}
|
|
207044
207190
|
}
|
|
207191
|
+
const SUB_AGENT_ACTIVITY_TITLE = "Subagent";
|
|
207192
|
+
/**
|
|
207193
|
+
* The text a subagent spawn shows in the timeline.
|
|
207194
|
+
*
|
|
207195
|
+
* A `SubAgentActivity` item carries only the agent path, the child thread id,
|
|
207196
|
+
* and whether the spawn started or completed. `itemDetail` reads none of those
|
|
207197
|
+
* fields, and both the started and the completed item arrive as `item/completed`,
|
|
207198
|
+
* so the lifecycle status cannot tell them apart either. Without this the row
|
|
207199
|
+
* renders as a bare title with no text under it. The app-server wire is
|
|
207200
|
+
* camelCase and the rollout file is snake_case, so read both.
|
|
207201
|
+
*/
|
|
207202
|
+
function subAgentActivityDetail(item) {
|
|
207203
|
+
const parts = [asString$2(item.agentPath)?.trim() || asString$2(item.agent_path)?.trim(), asString$2(item.kind)?.trim()].filter((part) => part !== void 0 && part.length > 0);
|
|
207204
|
+
return parts.length > 0 ? parts.join(" ") : void 0;
|
|
207205
|
+
}
|
|
207045
207206
|
function toRequestTypeFromMethod(method) {
|
|
207046
207207
|
switch (method) {
|
|
207047
207208
|
case "item/commandExecution/requestApproval": return "command_execution_approval";
|
|
@@ -207213,7 +207374,9 @@ function mapItemLifecycle(event, canonicalThreadId, lifecycle) {
|
|
|
207213
207374
|
if ((itemType === "mcp_tool_call" || itemType === "dynamic_tool_call") && (isBrowserToolName(source.name) || isBrowserToolName(source.toolName) || isBrowserToolName(source.method) || isBrowserToolName(payload?.toolName) || isBrowserToolName(payload?.method))) itemType = "browser_automation";
|
|
207214
207375
|
if ((itemType === "unknown" || itemType === "mcp_tool_call" || itemType === "dynamic_tool_call") && (isComputerToolName(source.name) || isComputerToolName(source.toolName) || isComputerToolName(source.method) || isComputerToolName(payload?.toolName) || isComputerToolName(payload?.method))) itemType = "mcp_tool_call";
|
|
207215
207376
|
if (itemType === "unknown" && lifecycle !== "item.updated") return;
|
|
207216
|
-
const
|
|
207377
|
+
const subAgentDetail = normalizeItemType(source.type).includes("sub agent") ? subAgentActivityDetail(source) : void 0;
|
|
207378
|
+
const detail = subAgentDetail ?? itemDetail(source, payload ?? {});
|
|
207379
|
+
const title = subAgentDetail ? SUB_AGENT_ACTIVITY_TITLE : itemTitle(itemType);
|
|
207217
207380
|
const status = lifecycle === "item.started" ? "inProgress" : lifecycle === "item.completed" ? "completed" : void 0;
|
|
207218
207381
|
return {
|
|
207219
207382
|
...runtimeEventBase(event, canonicalThreadId),
|
|
@@ -207221,7 +207384,7 @@ function mapItemLifecycle(event, canonicalThreadId, lifecycle) {
|
|
|
207221
207384
|
payload: {
|
|
207222
207385
|
itemType,
|
|
207223
207386
|
...status ? { status } : {},
|
|
207224
|
-
...
|
|
207387
|
+
...title ? { title } : {},
|
|
207225
207388
|
...detail ? { detail } : {},
|
|
207226
207389
|
...event.payload !== void 0 ? { data: event.payload } : {}
|
|
207227
207390
|
}
|
|
@@ -208377,82 +208540,6 @@ const makeProviderAuthProvenance = (input) => {
|
|
|
208377
208540
|
};
|
|
208378
208541
|
};
|
|
208379
208542
|
//#endregion
|
|
208380
|
-
//#region src/provider/claudeReadinessReason.ts
|
|
208381
|
-
/**
|
|
208382
|
-
* The reason literals Forge has copy for, confirmed against CMMD-36441's
|
|
208383
|
-
* readiness service. If the route renames one, the rename lands here as a
|
|
208384
|
-
* fall-through to the generic sentence, never as a wrong sentence.
|
|
208385
|
-
*
|
|
208386
|
-
* Reading the reason is what makes `stale` legible. CMMD-36441 answers
|
|
208387
|
-
* `credential_reconnect_required` on a `stale` answer that still reports
|
|
208388
|
-
* `connected: true`, and the older `credential_generation_not_applied` on a
|
|
208389
|
-
* `stale` answer that simply has not landed yet. Those want opposite
|
|
208390
|
-
* sentences, and both used to get "Reconnect Claude in Settings" because the
|
|
208391
|
-
* guard read only the delivery status.
|
|
208392
|
-
*/
|
|
208393
|
-
const CODE_BY_UPSTREAM_REASON$1 = {
|
|
208394
|
-
credential_expired_refreshing: "CREDENTIAL_EXPIRED_REFRESHING",
|
|
208395
|
-
credential_reconnect_required: "CREDENTIAL_RECONNECT_REQUIRED",
|
|
208396
|
-
credential_not_connected: "CREDENTIAL_RECONNECT_REQUIRED",
|
|
208397
|
-
credential_generation_not_applied: "CREDENTIAL_GENERATION_NOT_APPLIED",
|
|
208398
|
-
runtime_unavailable: "RUNTIME_UNAVAILABLE"
|
|
208399
|
-
};
|
|
208400
|
-
const CLAUDE_NATIVE_CREDENTIAL_UNUSABLE_COPY = "The delivered Claude credential is unavailable or unusable in this runtime.";
|
|
208401
|
-
/**
|
|
208402
|
-
* An ISO 8601 instant, with or without fractional seconds, UTC or offset.
|
|
208403
|
-
* Anchored to nothing on purpose: CMMD wraps the time in a sentence, and the
|
|
208404
|
-
* time is the only part of that sentence Forge repeats.
|
|
208405
|
-
*/
|
|
208406
|
-
const ISO_INSTANT_PATTERN = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})/;
|
|
208407
|
-
function claudeReadinessReasonCode(reason) {
|
|
208408
|
-
if (typeof reason !== "string" || !Object.hasOwn(CODE_BY_UPSTREAM_REASON$1, reason)) return null;
|
|
208409
|
-
return CODE_BY_UPSTREAM_REASON$1[reason] ?? null;
|
|
208410
|
-
}
|
|
208411
|
-
function expiredAtFromReadinessMessage(message) {
|
|
208412
|
-
if (typeof message !== "string") return null;
|
|
208413
|
-
return ISO_INSTANT_PATTERN.exec(message)?.[0] ?? null;
|
|
208414
|
-
}
|
|
208415
|
-
function claudeCredentialExpiredTurnCopy(expiredAt) {
|
|
208416
|
-
return `The delivered Claude credential expired at ${expiredAt}. CMMD is delivering a refreshed one, so retry this turn in a moment.`;
|
|
208417
|
-
}
|
|
208418
|
-
function claudeCredentialExpiredCardCopy(expiredAt) {
|
|
208419
|
-
return `The delivered Claude credential expired at ${expiredAt}. CMMD is delivering a refreshed one to this runtime.`;
|
|
208420
|
-
}
|
|
208421
|
-
/**
|
|
208422
|
-
* The last allowlisted readiness reason this process saw.
|
|
208423
|
-
*
|
|
208424
|
-
* A server process serves exactly one runtime, so one slot is the whole store.
|
|
208425
|
-
* It holds a reason code and a timestamp, never credential bytes. The provider
|
|
208426
|
-
* catalog reads a local credential file and cannot tell an expired snapshot
|
|
208427
|
-
* from a blank one, so without this the card can only offer the generic
|
|
208428
|
-
* sentence while the guard already knows better.
|
|
208429
|
-
*/
|
|
208430
|
-
let latestVerdict = null;
|
|
208431
|
-
/**
|
|
208432
|
-
* Remember, or clear, what the readiness answer said.
|
|
208433
|
-
*
|
|
208434
|
-
* An answer carrying no allowlisted reason clears the slot, which is what makes
|
|
208435
|
-
* the card go back to the generic sentence the moment CMMD applies a
|
|
208436
|
-
* credential: an applied answer carries no reason.
|
|
208437
|
-
*/
|
|
208438
|
-
function recordClaudeReadinessVerdict(readiness) {
|
|
208439
|
-
const code = claudeReadinessReasonCode(readiness.reason);
|
|
208440
|
-
latestVerdict = code === null ? null : {
|
|
208441
|
-
code,
|
|
208442
|
-
expiredAt: expiredAtFromReadinessMessage(readiness.lastErrorMessage)
|
|
208443
|
-
};
|
|
208444
|
-
}
|
|
208445
|
-
/**
|
|
208446
|
-
* What the provider status card says about a delivered credential it cannot
|
|
208447
|
-
* use. Names the expiry only when a readiness answer supplied the time; a
|
|
208448
|
-
* guessed time would be worse than the generic sentence.
|
|
208449
|
-
*/
|
|
208450
|
-
function claudeNativeCredentialUnusableMessage() {
|
|
208451
|
-
const verdict = latestVerdict;
|
|
208452
|
-
if (verdict?.code === "CREDENTIAL_EXPIRED_REFRESHING" && verdict.expiredAt !== null) return claudeCredentialExpiredCardCopy(verdict.expiredAt);
|
|
208453
|
-
return CLAUDE_NATIVE_CREDENTIAL_UNUSABLE_COPY;
|
|
208454
|
-
}
|
|
208455
|
-
//#endregion
|
|
208456
208543
|
//#region src/provider/personalClaudeInVm.ts
|
|
208457
208544
|
/**
|
|
208458
208545
|
* CMMD writes this marker when it activates a personal Claude subscription
|
|
@@ -208520,18 +208607,6 @@ function supportsFable51ClaudeCli(version) {
|
|
|
208520
208607
|
function modelsForClaudeCliVersion(models, version) {
|
|
208521
208608
|
return supportsFable51ClaudeCli(version) ? models : models.filter((model) => model.slug !== "claude-fable-5-1");
|
|
208522
208609
|
}
|
|
208523
|
-
function hasUsableNativeClaudeCredential(value) {
|
|
208524
|
-
try {
|
|
208525
|
-
const parsed = JSON.parse(value);
|
|
208526
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return false;
|
|
208527
|
-
const oauth = parsed.claudeAiOauth;
|
|
208528
|
-
if (typeof oauth !== "object" || oauth === null || Array.isArray(oauth)) return false;
|
|
208529
|
-
const record = oauth;
|
|
208530
|
-
return [record.accessToken, record.refreshToken].some((token) => typeof token === "string" && token.trim().length > 0);
|
|
208531
|
-
} catch {
|
|
208532
|
-
return false;
|
|
208533
|
-
}
|
|
208534
|
-
}
|
|
208535
208610
|
function getClaudeModelCapabilities(model) {
|
|
208536
208611
|
return getProviderModelCapabilities(PROVIDER$12, model) ?? DEFAULT_CLAUDE_MODEL_CAPABILITIES;
|
|
208537
208612
|
}
|
|
@@ -208984,7 +209059,7 @@ function claudeVersionProbeTimeoutProvider(input) {
|
|
|
208984
209059
|
const nativeClaudeProviderStatus = fn$1("nativeClaudeProviderStatus")(function* (input) {
|
|
208985
209060
|
const nativeConfigPath = input.configPath ?? join(homedir(), ".claude");
|
|
208986
209061
|
const nativeCredential = yield* tryPromise(() => readFile$1(join(nativeConfigPath, ".credentials.json"), "utf8")).pipe(option);
|
|
208987
|
-
const usable = isSome(nativeCredential) ?
|
|
209062
|
+
const usable = isSome(nativeCredential) ? hasUsableClaudeCredentialBlob(nativeCredential.value) : false;
|
|
208988
209063
|
return buildServerProvider({
|
|
208989
209064
|
provider: PROVIDER$12,
|
|
208990
209065
|
enabled: input.enabled,
|
|
@@ -227141,44 +227216,40 @@ function readinessFailureIssue(readiness) {
|
|
|
227141
227216
|
if (readiness.connected === false || readiness.deliveryStatus === "stale" || readiness.deliveryStatus === "not_connected") return CLAUDE_READINESS_COPY.invalid;
|
|
227142
227217
|
return CLAUDE_READINESS_COPY.unavailable;
|
|
227143
227218
|
}
|
|
227144
|
-
function generationHash(generationId) {
|
|
227145
|
-
return createHash("sha256").update(generationId).digest("hex");
|
|
227146
|
-
}
|
|
227147
227219
|
async function assertNativeClaudeRuntimeReady(input) {
|
|
227148
227220
|
if (!GENERATION_HASH_PATTERN.test(input.localGenerationHash)) throw new ClaudeRuntimeReadinessError(CLAUDE_READINESS_COPY.unavailable);
|
|
227221
|
+
const environmentId = EnvironmentId.make(`cmmd-runtime:${input.runtimeId}`);
|
|
227222
|
+
const sprite = {
|
|
227223
|
+
environmentId,
|
|
227224
|
+
runtimeId: input.runtimeId,
|
|
227225
|
+
machineId: input.machineId,
|
|
227226
|
+
credentialEpoch: input.credentialEpoch,
|
|
227227
|
+
localGenerationHash: input.localGenerationHash
|
|
227228
|
+
};
|
|
227149
227229
|
return await withReadinessRetry(async () => {
|
|
227150
227230
|
const readiness = decodeClaudeRuntimeReadiness(await input.fetchReadiness(input.runtimeId));
|
|
227151
227231
|
recordClaudeReadinessVerdict(readiness);
|
|
227152
|
-
return
|
|
227153
|
-
|
|
227154
|
-
|
|
227155
|
-
|
|
227156
|
-
|
|
227157
|
-
|
|
227158
|
-
const deliveryReceipt = parseProviderRuntimeDeliveryReceipt(readiness.deliveryReceipt, {
|
|
227159
|
-
provider: "anthropic",
|
|
227160
|
-
runtimeId: authority.runtimeId,
|
|
227161
|
-
machineId: authority.machineId,
|
|
227162
|
-
credentialEpoch: authority.credentialEpoch,
|
|
227163
|
-
expiresAt: readiness.deliveryReceipt?.expiresAt ?? null
|
|
227232
|
+
return bindingFromProviderReadiness(await queryProviderReadiness({
|
|
227233
|
+
environmentId,
|
|
227234
|
+
provider: "claudeAgent",
|
|
227235
|
+
sprite,
|
|
227236
|
+
claude: { fetch: async () => readiness }
|
|
227237
|
+
}), readiness);
|
|
227164
227238
|
});
|
|
227165
|
-
if (!isMatchingClaudeReceipt(deliveryReceipt, generationId)) throw new ClaudeRuntimeReadinessError(CLAUDE_READINESS_COPY.unavailable);
|
|
227166
|
-
return providerDeliveryBindingFromReceipt(deliveryReceipt);
|
|
227167
227239
|
}
|
|
227168
|
-
function
|
|
227169
|
-
if (
|
|
227170
|
-
|
|
227171
|
-
|
|
227172
|
-
"pending",
|
|
227173
|
-
"claimed",
|
|
227174
|
-
"activating"
|
|
227175
|
-
].includes(readiness.deliveryStatus));
|
|
227176
|
-
throw new ClaudeRuntimeReadinessError(readinessFailureIssue(readiness), retryable, refreshing ? "credentialRefresh" : "default");
|
|
227240
|
+
function bindingFromProviderReadiness(result, snapshot) {
|
|
227241
|
+
if (result.kind === "ready") {
|
|
227242
|
+
if (result.binding === null) throw new ClaudeRuntimeReadinessError(CLAUDE_READINESS_COPY.unavailable);
|
|
227243
|
+
return result.binding;
|
|
227177
227244
|
}
|
|
227178
|
-
|
|
227179
|
-
|
|
227180
|
-
|
|
227181
|
-
|
|
227245
|
+
if (result.kind === "query_failed") throw new ClaudeRuntimeReadinessError(CLAUDE_READINESS_COPY.unavailable);
|
|
227246
|
+
const refreshing = isCredentialRefreshInFlight(snapshot);
|
|
227247
|
+
const retryable = !isRuntimeUnavailable(snapshot) && (refreshing || [
|
|
227248
|
+
"pending",
|
|
227249
|
+
"claimed",
|
|
227250
|
+
"activating"
|
|
227251
|
+
].includes(snapshot.deliveryStatus));
|
|
227252
|
+
throw new ClaudeRuntimeReadinessError(result.reason === "generation_mismatch" ? CLAUDE_READINESS_COPY.generationMismatch : result.reason === "sprite_identity_drift" ? CLAUDE_READINESS_COPY.unavailable : readinessFailureIssue(snapshot), retryable, refreshing ? "credentialRefresh" : "default");
|
|
227182
227253
|
}
|
|
227183
227254
|
function readinessData(value) {
|
|
227184
227255
|
if (typeof value !== "object" || value === null || !("data" in value)) throw new ClaudeRuntimeReadinessError(CLAUDE_READINESS_COPY.unavailable);
|
|
@@ -291492,7 +291563,7 @@ function resolveBuildCommitFromEnv(env) {
|
|
|
291492
291563
|
* environment descriptor down instead of reporting an honest "unknown".
|
|
291493
291564
|
*/
|
|
291494
291565
|
function readBakedBuildCommit() {
|
|
291495
|
-
return "
|
|
291566
|
+
return "e94d1f3729cdbbc5b3f87cc2368279c7ef20aec8";
|
|
291496
291567
|
}
|
|
291497
291568
|
async function resolveServerBuildCommit(input) {
|
|
291498
291569
|
if (isFullCommitSha(input.baked)) return input.baked;
|