@cmmd-center/forge 0.13.96 → 0.13.98
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 +307 -131
- package/dist/bin.mjs +307 -131
- package/dist/client/assets/{DiffPanel-CQF1ISJz.js → DiffPanel-BXrpBBfH.js} +2 -2
- package/dist/client/assets/{DiffPanel.logic-ZO6qepWo.js → DiffPanel.logic-DifBpfCt.js} +2 -2
- package/dist/client/assets/{DiffWorkerPoolProvider-B7F6vAh9.js → DiffWorkerPoolProvider-CeIkRxNR.js} +2 -2
- package/dist/client/assets/{PullRequestCodePanel-B93y-X1L.js → PullRequestCodePanel-DzqRqaHT.js} +2 -2
- package/dist/client/assets/{Virtualizer-BtFYmUB0.js → Virtualizer-DYODAvp9.js} +2 -2
- package/dist/client/assets/{WorkerPoolContext-VAp-zZQ5.js → WorkerPoolContext-G1u5WJw4.js} +62 -62
- package/dist/client/assets/{index-BhdZllxU.js → index-DdsEGQ7q.js} +59 -59
- package/dist/client/index.html +4 -4
- package/dist/forge-build.json +1 -1
- package/package.json +1 -1
package/dist/bin.mjs
CHANGED
|
@@ -66041,7 +66041,7 @@ function normalizeNumberish(value) {
|
|
|
66041
66041
|
}
|
|
66042
66042
|
//#endregion
|
|
66043
66043
|
//#region package.json
|
|
66044
|
-
var version$1 = "0.13.
|
|
66044
|
+
var version$1 = "0.13.98";
|
|
66045
66045
|
//#endregion
|
|
66046
66046
|
//#region src/sentry.ts
|
|
66047
66047
|
const SERVER_APP_NAME = "forge-server";
|
|
@@ -98014,6 +98014,119 @@ function providerAuthFailureMessage(message, provider, env = process.env) {
|
|
|
98014
98014
|
}).message;
|
|
98015
98015
|
}
|
|
98016
98016
|
//#endregion
|
|
98017
|
+
//#region ../../packages/shared/src/publicProviderCopy.ts
|
|
98018
|
+
const PUBLIC_PROVIDER_LEAK_PATTERNS = [
|
|
98019
|
+
/\bDeepSeek\b/i,
|
|
98020
|
+
/\bKimi\b/i,
|
|
98021
|
+
/\bMoonshot\b/i,
|
|
98022
|
+
/\bdeepseek[-._a-z0-9]*\b/i,
|
|
98023
|
+
/\bkimi[-._a-z0-9]*\b/i,
|
|
98024
|
+
/\bmoonshot[-._a-z0-9]*\b/i,
|
|
98025
|
+
/\bAPEX_API_KEY\b/,
|
|
98026
|
+
/\bDEEPSEEK_API_KEY\b/,
|
|
98027
|
+
/\bKIMI_API_KEY\b/,
|
|
98028
|
+
/\bOPENAI_API_KEY\b/,
|
|
98029
|
+
/\bANTHROPIC_API_KEY\b/,
|
|
98030
|
+
/\bCURSOR_API_KEY\b/,
|
|
98031
|
+
/\bOPENCODE_API_KEY\b/,
|
|
98032
|
+
/\bforge_proxy_[A-Za-z0-9._-]+\b/,
|
|
98033
|
+
/\bProviderValidationError\b/,
|
|
98034
|
+
/\/forge-server\/node_modules\//,
|
|
98035
|
+
/https?:\/\/[^\s'"<>)]*\/api\/provider-egress\/[^\s'"<>)]*/i,
|
|
98036
|
+
/https?:\/\/[^\s'"<>)]*(?:apex|deepseek|moonshot|kimi)[^\s'"<>)]*/i
|
|
98037
|
+
];
|
|
98038
|
+
const DEFAULT_PUBLIC_PROVIDER_ERROR = "CMMD is temporarily unavailable. Check the workspace AI connection and retry.";
|
|
98039
|
+
function isProviderRateOrQuotaError(message) {
|
|
98040
|
+
if (!message) return false;
|
|
98041
|
+
const normalized = message.toLowerCase();
|
|
98042
|
+
return /\b(rate[\s-]?limit|too\s+many\s+requests|usage[ _-]limit|usage_limit_reached|quota|insufficient_quota)\b/.test(normalized) || /\b429\b/.test(normalized);
|
|
98043
|
+
}
|
|
98044
|
+
function providerLifecycleOrAccountCopy(message) {
|
|
98045
|
+
if (/\bbound to provider account\b/.test(message) && /\bcannot use provider account\b/.test(message)) return "Forge could not switch this conversation to the selected AI account. Retry the account switch.";
|
|
98046
|
+
if (/\bforge_runtime_repairing\b/.test(message) || /\bthis turn was interrupted because the environment is being repaired\b/.test(message)) return "This turn was interrupted because the environment is being repaired. Retry after the repair finishes.";
|
|
98047
|
+
if (/\bforge_runtime_stopped\b/.test(message) || /\bthis turn was interrupted because the environment was stopped\b/.test(message)) return "This turn was interrupted because the environment was stopped. Start the environment and retry.";
|
|
98048
|
+
return null;
|
|
98049
|
+
}
|
|
98050
|
+
/**
|
|
98051
|
+
* Infer a SAFE, clearer failure category from a (possibly leaky) provider error.
|
|
98052
|
+
*
|
|
98053
|
+
* Returns a canned, user-facing message — it never echoes the raw input, so it
|
|
98054
|
+
* is safe to use even when the source message contains provider internals.
|
|
98055
|
+
* Used to give actionable feedback ("model isn't available", "rate-limited",
|
|
98056
|
+
* "auth failed") instead of the blanket "CMMD is temporarily unavailable."
|
|
98057
|
+
* Returns null when no category can be confidently inferred.
|
|
98058
|
+
*/
|
|
98059
|
+
function categorizePublicProviderError(message) {
|
|
98060
|
+
if (!message) return null;
|
|
98061
|
+
const m = message.toLowerCase();
|
|
98062
|
+
const lifecycleOrAccountCopy = providerLifecycleOrAccountCopy(m);
|
|
98063
|
+
if (lifecycleOrAccountCopy !== null) return lifecycleOrAccountCopy;
|
|
98064
|
+
if (/\bforge_provider_model_not_allowed\b/.test(m) || /\bnot\s+scoped\s+to\s+the\s+requested\s+model\b/.test(m)) return "The workspace AI credential does not cover the model this turn asked for. Retry, or pick that model for the thread.";
|
|
98065
|
+
if (/\bmodel\b[\s\S]*\b(not\s+(found|available|supported)|does\s+not\s+exist|unsupported|invalid|unknown)\b/.test(m) || /\b(unsupported|unknown|invalid)\b[\s\S]*\bmodel\b/.test(m) || /\b(model_not_found|invalid_model|model_not_supported)\b/.test(m)) return "The selected model isn't available right now. Pick a different model and retry.";
|
|
98066
|
+
if (isProviderRateOrQuotaError(m)) return "The AI service is rate-limited or out of quota. Wait a moment and retry.";
|
|
98067
|
+
if (/_credential_reconnect_required\b/.test(m)) return "The workspace AI credential needs to be reconnected. Reconnect it in Settings > Providers, then retry.";
|
|
98068
|
+
if (/\b(unauthorized|forbidden|authentication\s+(failed|error|required)|invalid\s+api\s+key|expired\s+(token|credential))\b/.test(m) || /\b40[13]\b/.test(m)) return "Workspace AI authentication failed. Reconnect the workspace and retry.";
|
|
98069
|
+
if (/\b(timed?\s*out|timeout|overloaded|service\s+unavailable)\b/.test(m) || /\b50[234]\b/.test(m)) return "The AI service is temporarily overloaded. Retry in a moment.";
|
|
98070
|
+
return null;
|
|
98071
|
+
}
|
|
98072
|
+
function containsPublicProviderLeak(message) {
|
|
98073
|
+
if (!message) return false;
|
|
98074
|
+
return PUBLIC_PROVIDER_LEAK_PATTERNS.some((pattern) => pattern.test(message));
|
|
98075
|
+
}
|
|
98076
|
+
function sanitizePublicProviderText(message, options = {}) {
|
|
98077
|
+
if (message === void 0 || message === null) return null;
|
|
98078
|
+
const trimmed = message.trim();
|
|
98079
|
+
if (trimmed.length === 0) return null;
|
|
98080
|
+
if (!containsPublicProviderLeak(trimmed)) return trimmed;
|
|
98081
|
+
return categorizePublicProviderError(trimmed) ?? options.fallback ?? "CMMD is temporarily unavailable. Check the workspace AI connection and retry.";
|
|
98082
|
+
}
|
|
98083
|
+
//#endregion
|
|
98084
|
+
//#region src/orchestration/providerRetryableFailure.ts
|
|
98085
|
+
/**
|
|
98086
|
+
* Classifies a provider turn-start failure as a retryable rate-limit or
|
|
98087
|
+
* transient-availability failure (429/503), a terminal failure that names why
|
|
98088
|
+
* it will never clear on its own, or unrecognized (null).
|
|
98089
|
+
*
|
|
98090
|
+
* CMMD-Center/forge#3558: a 429 from CMMD's provider egress used to leave no
|
|
98091
|
+
* trace at all, because nothing in the turn-start path recognized it as a
|
|
98092
|
+
* distinct, retryable failure. `ProviderCommandReactor` uses this to decide
|
|
98093
|
+
* whether to retry a turn start with backoff, and to name the provider,
|
|
98094
|
+
* status and Retry-After in the `provider.turn.start.failed` activity CMMD's
|
|
98095
|
+
* watchdog reads once retries are exhausted.
|
|
98096
|
+
*
|
|
98097
|
+
* Reuses `isProviderRateOrQuotaError` (the same predicate the public-copy
|
|
98098
|
+
* sanitizer uses to recognize a rate-limit message) rather than restating its
|
|
98099
|
+
* word list here.
|
|
98100
|
+
*/
|
|
98101
|
+
const SERVICE_UNAVAILABLE_PATTERN = /\b(503|service\s+unavailable)\b/i;
|
|
98102
|
+
const RATE_LIMITED_PAST_TENSE_PATTERN = /\brate[\s-]?limit(?:ed|ing)?\b/i;
|
|
98103
|
+
const QUOTA_OR_USAGE_LIMIT_PATTERN = /\b(usage[ _-]limit|usage_limit_reached|quota|insufficient_quota)\b/i;
|
|
98104
|
+
const EXPLICIT_429_PATTERN = /\b429\b/;
|
|
98105
|
+
const RETRY_AFTER_SECONDS_PATTERN = /retry-after[^0-9]{0,10}(\d+)|(?:try again|retry)\s+in\s+(\d+)\s*(?:s\b|sec(?:onds?)?\b)?/i;
|
|
98106
|
+
function parseRetryAfterSeconds(detail) {
|
|
98107
|
+
const match = detail.match(RETRY_AFTER_SECONDS_PATTERN);
|
|
98108
|
+
if (!match) return null;
|
|
98109
|
+
const raw = match[1] ?? match[2];
|
|
98110
|
+
const seconds = raw ? Number(raw) : NaN;
|
|
98111
|
+
return Number.isFinite(seconds) ? seconds : null;
|
|
98112
|
+
}
|
|
98113
|
+
function classifyRetryableProviderFailure(detail) {
|
|
98114
|
+
if (!detail || detail.trim().length === 0) return null;
|
|
98115
|
+
if (QUOTA_OR_USAGE_LIMIT_PATTERN.test(detail) && !EXPLICIT_429_PATTERN.test(detail)) return {
|
|
98116
|
+
kind: "terminal",
|
|
98117
|
+
reason: "quota",
|
|
98118
|
+
message: detail
|
|
98119
|
+
};
|
|
98120
|
+
const isRateLimited = isProviderRateOrQuotaError(detail) || RATE_LIMITED_PAST_TENSE_PATTERN.test(detail);
|
|
98121
|
+
const isUnavailable = SERVICE_UNAVAILABLE_PATTERN.test(detail);
|
|
98122
|
+
if (!isRateLimited && !isUnavailable) return null;
|
|
98123
|
+
return {
|
|
98124
|
+
kind: "retryable",
|
|
98125
|
+
status: isRateLimited ? 429 : 503,
|
|
98126
|
+
retryAfterSeconds: parseRetryAfterSeconds(detail)
|
|
98127
|
+
};
|
|
98128
|
+
}
|
|
98129
|
+
//#endregion
|
|
98017
98130
|
//#region src/orchestration/turnFailureReason.ts
|
|
98018
98131
|
/**
|
|
98019
98132
|
* Machine-readable reasons for a turn that failed before it produced any
|
|
@@ -98047,6 +98160,31 @@ function classifyProviderTurnStartFailureReason(detail) {
|
|
|
98047
98160
|
message
|
|
98048
98161
|
};
|
|
98049
98162
|
}
|
|
98163
|
+
/**
|
|
98164
|
+
* Classifies a turn that ended mid-flight, after it had already started
|
|
98165
|
+
* (CMMD-Center/forge#3562 piece A): a `runtime.error` that reached CMMD as
|
|
98166
|
+
* `error_summary`, now also read into a `turn_status: failed` reason.
|
|
98167
|
+
*
|
|
98168
|
+
* `provider_turn_failed` is the code CMMD's own error_summary heuristic
|
|
98169
|
+
* already assigns this class of failure
|
|
98170
|
+
* (`shared/forge-work-session-failure-reasons.ts`), so a Forge-sent
|
|
98171
|
+
* `turn_status` carrying it lines up with what CMMD already infers instead
|
|
98172
|
+
* of teaching it a new code for the common case. `provider_usage_limit`
|
|
98173
|
+
* reuses the same wording `classifyRetryableProviderFailure` already treats
|
|
98174
|
+
* as a wall that will not clear by retrying (CMMD-Center/forge#3558): a
|
|
98175
|
+
* usage-limit message inside a turn that already ended is worth naming
|
|
98176
|
+
* specifically, even without the fuller upstream port (see the piece A PR's
|
|
98177
|
+
* follow-up issue) that would stop Codex from retrying against that wall in
|
|
98178
|
+
* the first place.
|
|
98179
|
+
*/
|
|
98180
|
+
function classifyMidTurnFailureReason(detail) {
|
|
98181
|
+
const message = detail && detail.trim().length > 0 ? detail : "The runtime reported an error while this run was in progress.";
|
|
98182
|
+
const classified = classifyRetryableProviderFailure(detail);
|
|
98183
|
+
return {
|
|
98184
|
+
code: classified?.kind === "terminal" && classified.reason === "quota" ? "provider_usage_limit" : "provider_turn_failed",
|
|
98185
|
+
message
|
|
98186
|
+
};
|
|
98187
|
+
}
|
|
98050
98188
|
function checkpointTimeoutReason(detail) {
|
|
98051
98189
|
return {
|
|
98052
98190
|
code: "checkpoint_timeout",
|
|
@@ -98181,6 +98319,108 @@ function serializeReplicaMessage(message) {
|
|
|
98181
98319
|
};
|
|
98182
98320
|
}
|
|
98183
98321
|
//#endregion
|
|
98322
|
+
//#region src/orchestration/turnTerminalStatus.ts
|
|
98323
|
+
/**
|
|
98324
|
+
* Shared vocabulary between the reactor that records how a turn ended
|
|
98325
|
+
* (`Layers/CheckpointReactor.ts`, on the provider's own `turn.completed`
|
|
98326
|
+
* event) and the serializer that turns that record into CMMD's `turn_status`
|
|
98327
|
+
* terminal event (`runtimeReplication/turnTerminalStatusSerializer.ts`).
|
|
98328
|
+
* CMMD-Center/forge#3562 piece A, CMMD-Center/CMMD#5822.
|
|
98329
|
+
*/
|
|
98330
|
+
/** The activity kind this durable record uses. Never sent to CMMD as-is: the
|
|
98331
|
+
* serializer reads it and emits the wire `turn_status` event instead. */
|
|
98332
|
+
const TURN_TERMINAL_STATUS_ACTIVITY_KIND = "turn.terminal-status";
|
|
98333
|
+
/**
|
|
98334
|
+
* CMMD's three-way outcome from the provider's own four-way `turn.completed`
|
|
98335
|
+
* state. `cancelled` and `interrupted` both read as `interrupted`: neither
|
|
98336
|
+
* the provider wording nor CMMD's Work Session UI distinguishes an
|
|
98337
|
+
* operator-cancelled turn from one the provider gave up on mid-flight.
|
|
98338
|
+
*/
|
|
98339
|
+
function turnTerminalOutcomeFromRuntimeState(state) {
|
|
98340
|
+
if (state === "failed") return "failed";
|
|
98341
|
+
if (state === "completed") return "completed";
|
|
98342
|
+
return "interrupted";
|
|
98343
|
+
}
|
|
98344
|
+
/**
|
|
98345
|
+
* Deterministic activity id for a turn's terminal record: never
|
|
98346
|
+
* `crypto.randomUUID()`. The projector replaces an activity by id
|
|
98347
|
+
* (`thread.activity-appended`), so a redelivered `turn.completed` for the
|
|
98348
|
+
* same turn lands on the same row instead of adding a second one, and the
|
|
98349
|
+
* serializer's own `eventId` (`activity:<id>`) inherits the same guarantee.
|
|
98350
|
+
*/
|
|
98351
|
+
function turnTerminalStatusActivityId(turnId) {
|
|
98352
|
+
return `turn-terminal:${turnId}`;
|
|
98353
|
+
}
|
|
98354
|
+
//#endregion
|
|
98355
|
+
//#region src/runtimeReplication/eventFormatting.ts
|
|
98356
|
+
/**
|
|
98357
|
+
* Small formatting helpers shared by every source `serializer.ts` folds into
|
|
98358
|
+
* a thread's replicated event list. Kept in their own module, with no
|
|
98359
|
+
* dependency on `serializer.ts` itself, so a narrower serializer (such as
|
|
98360
|
+
* `turnTerminalStatusSerializer.ts`) can reuse them without creating an
|
|
98361
|
+
* import cycle back into the file that assembles the full event list.
|
|
98362
|
+
*/
|
|
98363
|
+
function text(value, max) {
|
|
98364
|
+
const normalized = value.trim();
|
|
98365
|
+
return normalized ? normalized.slice(0, max) : null;
|
|
98366
|
+
}
|
|
98367
|
+
function canonicalRuntimeEventTimestamp(value) {
|
|
98368
|
+
let timestamp = new Date(value);
|
|
98369
|
+
if (Number.isNaN(timestamp.getTime())) {
|
|
98370
|
+
const legacyBsdNanoseconds = value.match(/^(.*:\d{2})\.\d+NZ$/);
|
|
98371
|
+
timestamp = new Date(legacyBsdNanoseconds ? `${legacyBsdNanoseconds[1]}Z` : value);
|
|
98372
|
+
}
|
|
98373
|
+
if (Number.isNaN(timestamp.getTime())) throw new Error(`Invalid runtime event timestamp: ${value}`);
|
|
98374
|
+
return timestamp.toISOString();
|
|
98375
|
+
}
|
|
98376
|
+
//#endregion
|
|
98377
|
+
//#region src/runtimeReplication/turnTerminalStatusSerializer.ts
|
|
98378
|
+
function outcomeOf(payload) {
|
|
98379
|
+
if (!payload || typeof payload !== "object") return null;
|
|
98380
|
+
const outcome = payload.outcome;
|
|
98381
|
+
return outcome === "completed" || outcome === "interrupted" || outcome === "failed" ? outcome : null;
|
|
98382
|
+
}
|
|
98383
|
+
function errorMessageOf(payload) {
|
|
98384
|
+
if (!payload || typeof payload !== "object") return null;
|
|
98385
|
+
const message = payload.errorMessage;
|
|
98386
|
+
return typeof message === "string" && message.trim().length > 0 ? message : null;
|
|
98387
|
+
}
|
|
98388
|
+
/**
|
|
98389
|
+
* Turns the one durable activity `Layers/CheckpointReactor.ts` records when a
|
|
98390
|
+
* turn ends into CMMD's `turn_status` terminal event (CMMD-Center/forge#3562
|
|
98391
|
+
* piece A, CMMD-Center/CMMD#5822): `completed`, `interrupted`, or `failed`
|
|
98392
|
+
* with a structured `reason`. `error_summary` (`serializeFailureActivity` in
|
|
98393
|
+
* `serializer.ts`) keeps replicating separately for a mid-turn failure; this
|
|
98394
|
+
* is added next to it, never instead of it.
|
|
98395
|
+
*
|
|
98396
|
+
* The activity's own id is deterministic (`turn-terminal:<turnId>`,
|
|
98397
|
+
* `turnTerminalStatusActivityId`), so this event's `eventId` -- built from
|
|
98398
|
+
* that id the same way every other activity-sourced event on this thread is
|
|
98399
|
+
* (`activity:<id>`) -- can never collide with a second, different terminal
|
|
98400
|
+
* status for the same turn: there is exactly one activity row to read it
|
|
98401
|
+
* from, and the reactor that writes that row never overwrites it once set.
|
|
98402
|
+
*/
|
|
98403
|
+
function serializeTurnTerminalStatusActivity(activity) {
|
|
98404
|
+
if (activity.kind !== "turn.terminal-status" || !activity.turnId) return null;
|
|
98405
|
+
const outcome = outcomeOf(activity.payload);
|
|
98406
|
+
if (outcome === null) return null;
|
|
98407
|
+
const reason = outcome === "failed" ? classifyMidTurnFailureReason(errorMessageOf(activity.payload)) : null;
|
|
98408
|
+
return {
|
|
98409
|
+
sourceSequence: null,
|
|
98410
|
+
event: {
|
|
98411
|
+
eventId: `activity:${activity.id}`,
|
|
98412
|
+
occurredAt: canonicalRuntimeEventTimestamp(activity.createdAt),
|
|
98413
|
+
turnId: activity.turnId,
|
|
98414
|
+
kind: "turn_status",
|
|
98415
|
+
status: outcome,
|
|
98416
|
+
...reason ? { reason: {
|
|
98417
|
+
code: reason.code,
|
|
98418
|
+
message: text(reason.message, 2e3) ?? reason.message
|
|
98419
|
+
} } : {}
|
|
98420
|
+
}
|
|
98421
|
+
};
|
|
98422
|
+
}
|
|
98423
|
+
//#endregion
|
|
98184
98424
|
//#region src/runtimeReplication/serializer.ts
|
|
98185
98425
|
function threadStatus(thread) {
|
|
98186
98426
|
if (thread.archivedAt) return "archived";
|
|
@@ -98247,19 +98487,6 @@ function serializeRuntimeInventory(snapshot, providerInventory) {
|
|
|
98247
98487
|
...providerInventory === void 0 ? {} : { providers: serializeProviderCatalog(providerInventory) }
|
|
98248
98488
|
};
|
|
98249
98489
|
}
|
|
98250
|
-
function text(value, max) {
|
|
98251
|
-
const normalized = value.trim();
|
|
98252
|
-
return normalized ? normalized.slice(0, max) : null;
|
|
98253
|
-
}
|
|
98254
|
-
function canonicalRuntimeEventTimestamp(value) {
|
|
98255
|
-
let timestamp = new Date(value);
|
|
98256
|
-
if (Number.isNaN(timestamp.getTime())) {
|
|
98257
|
-
const legacyBsdNanoseconds = value.match(/^(.*:\d{2})\.\d+NZ$/);
|
|
98258
|
-
timestamp = new Date(legacyBsdNanoseconds ? `${legacyBsdNanoseconds[1]}Z` : value);
|
|
98259
|
-
}
|
|
98260
|
-
if (Number.isNaN(timestamp.getTime())) throw new Error(`Invalid runtime event timestamp: ${value}`);
|
|
98261
|
-
return timestamp.toISOString();
|
|
98262
|
-
}
|
|
98263
98490
|
/** Spread onto an event: present only when the projection knows the turn. */
|
|
98264
98491
|
function eventTurn(turnId) {
|
|
98265
98492
|
return turnId ? { turnId } : {};
|
|
@@ -98564,10 +98791,13 @@ function foldReportedUsage(reported) {
|
|
|
98564
98791
|
* model, so a mid-thread switch used to republish a finished turn as a second
|
|
98565
98792
|
* row for spend that happened once (FOR-36388, fixed in FOR-36438).
|
|
98566
98793
|
*/
|
|
98567
|
-
/** Turns named on this thread's own rows; hydrated replica rows carry no local
|
|
98794
|
+
/** Turns named on this thread's own rows; hydrated replica rows carry no local
|
|
98795
|
+
* turn, and the terminal-status activity (CMMD-Center/forge#3562 piece A) is
|
|
98796
|
+
* a wire-protocol source in its own right, not a Usage signal, so it is
|
|
98797
|
+
* excluded the same way a `replica.*` activity is. */
|
|
98568
98798
|
function localTurnIds(thread) {
|
|
98569
98799
|
const fromMessages = thread.messages.filter((message) => !message.streaming).map((message) => message.turnId);
|
|
98570
|
-
const fromActivities = thread.activities.filter((activity) => !activity.kind.startsWith("replica.")).map((activity) => activity.turnId);
|
|
98800
|
+
const fromActivities = thread.activities.filter((activity) => !activity.kind.startsWith("replica.") && activity.kind !== "turn.terminal-status").map((activity) => activity.turnId);
|
|
98571
98801
|
const turnIds = /* @__PURE__ */ new Set();
|
|
98572
98802
|
for (const turnId of [...fromMessages, ...fromActivities]) if (turnId) turnIds.add(turnId);
|
|
98573
98803
|
return turnIds;
|
|
@@ -98577,8 +98807,12 @@ function settledTurnIds(thread) {
|
|
|
98577
98807
|
if (thread.latestTurn?.state === "running") turnIds.delete(thread.latestTurn.turnId);
|
|
98578
98808
|
return turnIds;
|
|
98579
98809
|
}
|
|
98810
|
+
/** A turn's own activities for Usage derivation, excluding the terminal-status
|
|
98811
|
+
* activity: that record's own `createdAt` (the turn's very end) must never
|
|
98812
|
+
* shift `turnLatestAt`, or an already-acknowledged usage row would rehash
|
|
98813
|
+
* the moment a turn that used to have no terminal activity gains one. */
|
|
98580
98814
|
function turnActivities(thread, turnId) {
|
|
98581
|
-
return thread.activities.filter((activity) => activity.turnId === turnId).toSorted((left, right) => left.createdAt.localeCompare(right.createdAt) || left.id.localeCompare(right.id));
|
|
98815
|
+
return thread.activities.filter((activity) => activity.turnId === turnId && activity.kind !== "turn.terminal-status").toSorted((left, right) => left.createdAt.localeCompare(right.createdAt) || left.id.localeCompare(right.id));
|
|
98582
98816
|
}
|
|
98583
98817
|
/** The last thing that happened in the turn: what the Recorded turn is stamped with. */
|
|
98584
98818
|
function turnLatestAt(thread, turnId, activities) {
|
|
@@ -98787,6 +99021,10 @@ function serializeRuntimeThreadEvents(thread) {
|
|
|
98787
99021
|
const event = serializePlanActivity(activity);
|
|
98788
99022
|
return event === null ? [] : [event];
|
|
98789
99023
|
});
|
|
99024
|
+
const turnTerminalStatuses = thread.activities.flatMap((activity) => {
|
|
99025
|
+
const event = serializeTurnTerminalStatusActivity(activity);
|
|
99026
|
+
return event === null ? [] : [event];
|
|
99027
|
+
});
|
|
98790
99028
|
const recordedTurns = serializeRecordedTurns(thread);
|
|
98791
99029
|
const textGenerations = serializeTextGenerations(thread);
|
|
98792
99030
|
const priorEvents = [
|
|
@@ -98796,6 +99034,7 @@ function serializeRuntimeThreadEvents(thread) {
|
|
|
98796
99034
|
...worktreeLaunchActivities,
|
|
98797
99035
|
...planActivities,
|
|
98798
99036
|
...failureActivities,
|
|
99037
|
+
...turnTerminalStatuses,
|
|
98799
99038
|
...recordedTurns,
|
|
98800
99039
|
...textGenerations
|
|
98801
99040
|
];
|
|
@@ -213749,73 +213988,6 @@ const makeCodexAdapter = fn$1("makeCodexAdapter")(function* (options) {
|
|
|
213749
213988
|
function makeCodexAdapterLive(options) {
|
|
213750
213989
|
return effect(CodexAdapter, makeCodexAdapter(options));
|
|
213751
213990
|
}
|
|
213752
|
-
//#endregion
|
|
213753
|
-
//#region ../../packages/shared/src/publicProviderCopy.ts
|
|
213754
|
-
const PUBLIC_PROVIDER_LEAK_PATTERNS = [
|
|
213755
|
-
/\bDeepSeek\b/i,
|
|
213756
|
-
/\bKimi\b/i,
|
|
213757
|
-
/\bMoonshot\b/i,
|
|
213758
|
-
/\bdeepseek[-._a-z0-9]*\b/i,
|
|
213759
|
-
/\bkimi[-._a-z0-9]*\b/i,
|
|
213760
|
-
/\bmoonshot[-._a-z0-9]*\b/i,
|
|
213761
|
-
/\bAPEX_API_KEY\b/,
|
|
213762
|
-
/\bDEEPSEEK_API_KEY\b/,
|
|
213763
|
-
/\bKIMI_API_KEY\b/,
|
|
213764
|
-
/\bOPENAI_API_KEY\b/,
|
|
213765
|
-
/\bANTHROPIC_API_KEY\b/,
|
|
213766
|
-
/\bCURSOR_API_KEY\b/,
|
|
213767
|
-
/\bOPENCODE_API_KEY\b/,
|
|
213768
|
-
/\bforge_proxy_[A-Za-z0-9._-]+\b/,
|
|
213769
|
-
/\bProviderValidationError\b/,
|
|
213770
|
-
/\/forge-server\/node_modules\//,
|
|
213771
|
-
/https?:\/\/[^\s'"<>)]*\/api\/provider-egress\/[^\s'"<>)]*/i,
|
|
213772
|
-
/https?:\/\/[^\s'"<>)]*(?:apex|deepseek|moonshot|kimi)[^\s'"<>)]*/i
|
|
213773
|
-
];
|
|
213774
|
-
const DEFAULT_PUBLIC_PROVIDER_ERROR = "CMMD is temporarily unavailable. Check the workspace AI connection and retry.";
|
|
213775
|
-
function isProviderRateOrQuotaError(message) {
|
|
213776
|
-
if (!message) return false;
|
|
213777
|
-
const normalized = message.toLowerCase();
|
|
213778
|
-
return /\b(rate[\s-]?limit|too\s+many\s+requests|usage[ _-]limit|usage_limit_reached|quota|insufficient_quota)\b/.test(normalized) || /\b429\b/.test(normalized);
|
|
213779
|
-
}
|
|
213780
|
-
function providerLifecycleOrAccountCopy(message) {
|
|
213781
|
-
if (/\bbound to provider account\b/.test(message) && /\bcannot use provider account\b/.test(message)) return "Forge could not switch this conversation to the selected AI account. Retry the account switch.";
|
|
213782
|
-
if (/\bforge_runtime_repairing\b/.test(message) || /\bthis turn was interrupted because the environment is being repaired\b/.test(message)) return "This turn was interrupted because the environment is being repaired. Retry after the repair finishes.";
|
|
213783
|
-
if (/\bforge_runtime_stopped\b/.test(message) || /\bthis turn was interrupted because the environment was stopped\b/.test(message)) return "This turn was interrupted because the environment was stopped. Start the environment and retry.";
|
|
213784
|
-
return null;
|
|
213785
|
-
}
|
|
213786
|
-
/**
|
|
213787
|
-
* Infer a SAFE, clearer failure category from a (possibly leaky) provider error.
|
|
213788
|
-
*
|
|
213789
|
-
* Returns a canned, user-facing message — it never echoes the raw input, so it
|
|
213790
|
-
* is safe to use even when the source message contains provider internals.
|
|
213791
|
-
* Used to give actionable feedback ("model isn't available", "rate-limited",
|
|
213792
|
-
* "auth failed") instead of the blanket "CMMD is temporarily unavailable."
|
|
213793
|
-
* Returns null when no category can be confidently inferred.
|
|
213794
|
-
*/
|
|
213795
|
-
function categorizePublicProviderError(message) {
|
|
213796
|
-
if (!message) return null;
|
|
213797
|
-
const m = message.toLowerCase();
|
|
213798
|
-
const lifecycleOrAccountCopy = providerLifecycleOrAccountCopy(m);
|
|
213799
|
-
if (lifecycleOrAccountCopy !== null) return lifecycleOrAccountCopy;
|
|
213800
|
-
if (/\bforge_provider_model_not_allowed\b/.test(m) || /\bnot\s+scoped\s+to\s+the\s+requested\s+model\b/.test(m)) return "The workspace AI credential does not cover the model this turn asked for. Retry, or pick that model for the thread.";
|
|
213801
|
-
if (/\bmodel\b[\s\S]*\b(not\s+(found|available|supported)|does\s+not\s+exist|unsupported|invalid|unknown)\b/.test(m) || /\b(unsupported|unknown|invalid)\b[\s\S]*\bmodel\b/.test(m) || /\b(model_not_found|invalid_model|model_not_supported)\b/.test(m)) return "The selected model isn't available right now. Pick a different model and retry.";
|
|
213802
|
-
if (isProviderRateOrQuotaError(m)) return "The AI service is rate-limited or out of quota. Wait a moment and retry.";
|
|
213803
|
-
if (/_credential_reconnect_required\b/.test(m)) return "The workspace AI credential needs to be reconnected. Reconnect it in Settings > Providers, then retry.";
|
|
213804
|
-
if (/\b(unauthorized|forbidden|authentication\s+(failed|error|required)|invalid\s+api\s+key|expired\s+(token|credential))\b/.test(m) || /\b40[13]\b/.test(m)) return "Workspace AI authentication failed. Reconnect the workspace and retry.";
|
|
213805
|
-
if (/\b(timed?\s*out|timeout|overloaded|service\s+unavailable)\b/.test(m) || /\b50[234]\b/.test(m)) return "The AI service is temporarily overloaded. Retry in a moment.";
|
|
213806
|
-
return null;
|
|
213807
|
-
}
|
|
213808
|
-
function containsPublicProviderLeak(message) {
|
|
213809
|
-
if (!message) return false;
|
|
213810
|
-
return PUBLIC_PROVIDER_LEAK_PATTERNS.some((pattern) => pattern.test(message));
|
|
213811
|
-
}
|
|
213812
|
-
function sanitizePublicProviderText(message, options = {}) {
|
|
213813
|
-
if (message === void 0 || message === null) return null;
|
|
213814
|
-
const trimmed = message.trim();
|
|
213815
|
-
if (trimmed.length === 0) return null;
|
|
213816
|
-
if (!containsPublicProviderLeak(trimmed)) return trimmed;
|
|
213817
|
-
return categorizePublicProviderError(trimmed) ?? options.fallback ?? "CMMD is temporarily unavailable. Check the workspace AI connection and retry.";
|
|
213818
|
-
}
|
|
213819
213991
|
function resolveApexBaseUrl(settings, config) {
|
|
213820
213992
|
return config?.forgeApexBaseUrl || settings.baseUrl || "https://apex.cmmd.ai";
|
|
213821
213993
|
}
|
|
@@ -292518,52 +292690,6 @@ function applyThreadGoalPreamble(goal, input) {
|
|
|
292518
292690
|
return trimmedInput.length > 0 ? `${preamble}\n\n${trimmedInput}` : preamble;
|
|
292519
292691
|
}
|
|
292520
292692
|
//#endregion
|
|
292521
|
-
//#region src/orchestration/providerRetryableFailure.ts
|
|
292522
|
-
/**
|
|
292523
|
-
* Classifies a provider turn-start failure as a retryable rate-limit or
|
|
292524
|
-
* transient-availability failure (429/503), a terminal failure that names why
|
|
292525
|
-
* it will never clear on its own, or unrecognized (null).
|
|
292526
|
-
*
|
|
292527
|
-
* CMMD-Center/forge#3558: a 429 from CMMD's provider egress used to leave no
|
|
292528
|
-
* trace at all, because nothing in the turn-start path recognized it as a
|
|
292529
|
-
* distinct, retryable failure. `ProviderCommandReactor` uses this to decide
|
|
292530
|
-
* whether to retry a turn start with backoff, and to name the provider,
|
|
292531
|
-
* status and Retry-After in the `provider.turn.start.failed` activity CMMD's
|
|
292532
|
-
* watchdog reads once retries are exhausted.
|
|
292533
|
-
*
|
|
292534
|
-
* Reuses `isProviderRateOrQuotaError` (the same predicate the public-copy
|
|
292535
|
-
* sanitizer uses to recognize a rate-limit message) rather than restating its
|
|
292536
|
-
* word list here.
|
|
292537
|
-
*/
|
|
292538
|
-
const SERVICE_UNAVAILABLE_PATTERN = /\b(503|service\s+unavailable)\b/i;
|
|
292539
|
-
const RATE_LIMITED_PAST_TENSE_PATTERN = /\brate[\s-]?limit(?:ed|ing)?\b/i;
|
|
292540
|
-
const QUOTA_OR_USAGE_LIMIT_PATTERN = /\b(usage[ _-]limit|usage_limit_reached|quota|insufficient_quota)\b/i;
|
|
292541
|
-
const EXPLICIT_429_PATTERN = /\b429\b/;
|
|
292542
|
-
const RETRY_AFTER_SECONDS_PATTERN = /retry-after[^0-9]{0,10}(\d+)|(?:try again|retry)\s+in\s+(\d+)\s*(?:s\b|sec(?:onds?)?\b)?/i;
|
|
292543
|
-
function parseRetryAfterSeconds(detail) {
|
|
292544
|
-
const match = detail.match(RETRY_AFTER_SECONDS_PATTERN);
|
|
292545
|
-
if (!match) return null;
|
|
292546
|
-
const raw = match[1] ?? match[2];
|
|
292547
|
-
const seconds = raw ? Number(raw) : NaN;
|
|
292548
|
-
return Number.isFinite(seconds) ? seconds : null;
|
|
292549
|
-
}
|
|
292550
|
-
function classifyRetryableProviderFailure(detail) {
|
|
292551
|
-
if (!detail || detail.trim().length === 0) return null;
|
|
292552
|
-
if (QUOTA_OR_USAGE_LIMIT_PATTERN.test(detail) && !EXPLICIT_429_PATTERN.test(detail)) return {
|
|
292553
|
-
kind: "terminal",
|
|
292554
|
-
reason: "quota",
|
|
292555
|
-
message: detail
|
|
292556
|
-
};
|
|
292557
|
-
const isRateLimited = isProviderRateOrQuotaError(detail) || RATE_LIMITED_PAST_TENSE_PATTERN.test(detail);
|
|
292558
|
-
const isUnavailable = SERVICE_UNAVAILABLE_PATTERN.test(detail);
|
|
292559
|
-
if (!isRateLimited && !isUnavailable) return null;
|
|
292560
|
-
return {
|
|
292561
|
-
kind: "retryable",
|
|
292562
|
-
status: isRateLimited ? 429 : 503,
|
|
292563
|
-
retryAfterSeconds: parseRetryAfterSeconds(detail)
|
|
292564
|
-
};
|
|
292565
|
-
}
|
|
292566
|
-
//#endregion
|
|
292567
292693
|
//#region src/orchestration/Layers/ProviderCommandReactor.ts
|
|
292568
292694
|
function toNonEmptyProviderInput(value) {
|
|
292569
292695
|
const normalized = value?.trim();
|
|
@@ -294739,12 +294865,62 @@ const CheckpointReactorLive = effect(CheckpointReactor, gen(function* () {
|
|
|
294739
294865
|
createdAt: input.createdAt
|
|
294740
294866
|
});
|
|
294741
294867
|
});
|
|
294868
|
+
/**
|
|
294869
|
+
* The one durable, deterministic-id activity that records how a turn ended
|
|
294870
|
+
* (CMMD-Center/forge#3562 piece A, CMMD-Center/CMMD#5822): `completed`,
|
|
294871
|
+
* `interrupted` (an abort or a provider cancellation), or `failed` with the
|
|
294872
|
+
* provider's own error message. Recorded here, ahead of every
|
|
294873
|
+
* checkpoint-specific early return below, so it fires for every turn
|
|
294874
|
+
* regardless of whether this workspace can capture a git checkpoint at
|
|
294875
|
+
* all -- unlike a checkpoint, this never depends on `resolveCheckpointCwd`.
|
|
294876
|
+
*
|
|
294877
|
+
* The activity id is derived from the turn id, never `crypto.randomUUID()`,
|
|
294878
|
+
* so a redelivered `turn.completed` for the same turn replaces the same
|
|
294879
|
+
* row rather than adding a second one. The guard below additionally
|
|
294880
|
+
* refuses to touch a turn that already has one: first write wins, so a
|
|
294881
|
+
* later, different signal for the same turn can never overwrite an
|
|
294882
|
+
* outcome CMMD may already have acknowledged.
|
|
294883
|
+
*
|
|
294884
|
+
* Deriving the wire `turn_status` event from a new activity recorded at
|
|
294885
|
+
* the moment the turn actually ends -- not from `thread.latestTurn` or
|
|
294886
|
+
* `thread.checkpoints`, both of which already hold outcomes for turns that
|
|
294887
|
+
* settled before this shipped -- is deliberate: those would insert a brand
|
|
294888
|
+
* new event into history CMMD already acknowledged for every existing
|
|
294889
|
+
* thread, which `RuntimeThreadHistoryConflict` exists specifically to
|
|
294890
|
+
* reject (CMMD-Center/forge#3497). A turn that settled before this shipped
|
|
294891
|
+
* gets no terminal event; only a turn that ends after it does.
|
|
294892
|
+
*/
|
|
294893
|
+
const recordTurnTerminalStatus = fn$1("recordTurnTerminalStatus")(function* (event, thread, turnId) {
|
|
294894
|
+
const activityId = turnTerminalStatusActivityId(turnId);
|
|
294895
|
+
if (thread.activities.some((activity) => activity.id === activityId)) return;
|
|
294896
|
+
const outcome = turnTerminalOutcomeFromRuntimeState(event.payload.state);
|
|
294897
|
+
const recordedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
294898
|
+
yield* orchestrationEngine.dispatch({
|
|
294899
|
+
type: "thread.activity.append",
|
|
294900
|
+
commandId: serverCommandId$1("turn-terminal-status"),
|
|
294901
|
+
threadId: event.threadId,
|
|
294902
|
+
activity: {
|
|
294903
|
+
id: EventId.make(activityId),
|
|
294904
|
+
tone: outcome === "failed" ? "error" : "info",
|
|
294905
|
+
kind: TURN_TERMINAL_STATUS_ACTIVITY_KIND,
|
|
294906
|
+
summary: `Turn ${outcome}`,
|
|
294907
|
+
payload: {
|
|
294908
|
+
outcome,
|
|
294909
|
+
...outcome === "failed" && event.payload.errorMessage ? { errorMessage: event.payload.errorMessage } : {}
|
|
294910
|
+
},
|
|
294911
|
+
turnId,
|
|
294912
|
+
createdAt: recordedAt
|
|
294913
|
+
},
|
|
294914
|
+
createdAt: recordedAt
|
|
294915
|
+
});
|
|
294916
|
+
});
|
|
294742
294917
|
const captureCheckpointFromTurnCompletion = fn$1("captureCheckpointFromTurnCompletion")(function* (event) {
|
|
294743
294918
|
const turnId = toTurnId(event.turnId);
|
|
294744
294919
|
if (!turnId) return;
|
|
294745
294920
|
const readModel = yield* orchestrationEngine.getReadModel();
|
|
294746
294921
|
const thread = readModel.threads.find((entry) => entry.id === event.threadId);
|
|
294747
294922
|
if (!thread) return;
|
|
294923
|
+
yield* recordTurnTerminalStatus(event, thread, turnId);
|
|
294748
294924
|
if (thread.session?.activeTurnId && !sameId(thread.session.activeTurnId, turnId)) return;
|
|
294749
294925
|
if (thread.checkpoints.some((checkpoint) => checkpoint.turnId === turnId && checkpoint.status !== "missing")) return;
|
|
294750
294926
|
const checkpointCwd = yield* resolveCheckpointCwd({
|
|
@@ -299501,7 +299677,7 @@ function resolveBuildCommitFromEnv(env) {
|
|
|
299501
299677
|
* environment descriptor down instead of reporting an honest "unknown".
|
|
299502
299678
|
*/
|
|
299503
299679
|
function readBakedBuildCommit() {
|
|
299504
|
-
return "
|
|
299680
|
+
return "af7d46dcc7bdd81e6994e3590d9fca779411f1c4";
|
|
299505
299681
|
}
|
|
299506
299682
|
async function resolveServerBuildCommit(input) {
|
|
299507
299683
|
if (isFullCommitSha(input.baked)) return input.baked;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{Ha as t,Mi as n,Ua as r,Wa as i}from"./Stream-mUTFnSY9.js";import{Fn as a,Gr as o,Hl as s,Jr as c,Or as l,Tn as u,Wr as d,al as f,c as p,d as m,fn as h,fr as g,gr as _,hr as v,ii as y,jn as b,js as x,m as S,ni as C,o as w,ol as T,qo as E,qt as D,rl as O,rs as k,s as A,t as j,tl as M,u as N}from"./WorkerPoolContext-
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{Ha as t,Mi as n,Ua as r,Wa as i}from"./Stream-mUTFnSY9.js";import{Fn as a,Gr as o,Hl as s,Jr as c,Or as l,Tn as u,Wr as d,al as f,c as p,d as m,fn as h,fr as g,gr as _,hr as v,ii as y,jn as b,js as x,m as S,ni as C,o as w,ol as T,qo as E,qt as D,rl as O,rs as k,s as A,t as j,tl as M,u as N}from"./WorkerPoolContext-G1u5WJw4.js";import{hn as P}from"./CompositeItem-DNkNENOR.js";import{a as F,c as I,f as L,i as R,l as z,m as B,n as V,o as H,p as U,r as W,s as G,t as K}from"./Virtualizer-DYODAvp9.js";import{Dn as q,at as J,it as ee}from"./src-DFTFXdyK.js";import"./cmmdAuthRedirect-DCgS12fq.js";import{a as te,c as ne,d as re,h as ie,i as ae,l as oe,m as se,n as ce,o as Y,p as le,r as ue,s as de,t as fe,u as pe}from"./DiffPanel.logic-DifBpfCt.js";var X=e(i(),1),me=typeof window>`u`?X.useEffect:X.useLayoutEffect;function he({fileDiff:e,options:t,editorOptions:n,lineAnnotations:r,selectedLines:i,prerenderedHTML:a,metrics:o,hasGutterRenderUtility:s,hasCustomHeader:c,disableWorkerPool:l,edit:u}){let d=V(),f=i!==void 0,m=(0,X.useContext)(j),h=A(),g=(0,X.useRef)(null),_=p(n=>{if(n!=null){if(g.current!=null)throw Error(`useFileDiffInstance: An instance should not already exist when a node is created`);d==null?g.current=new re(Z({controlledSelection:f,hasCustomHeader:c,hasGutterRenderUtility:s,options:t}),l?void 0:m,!0):g.current=new pe(Z({controlledSelection:f,hasCustomHeader:c,hasGutterRenderUtility:s,options:t}),d,o,l?void 0:m,!0),g.current.hydrate({fileDiff:e,fileContainer:n,lineAnnotations:r,prerenderedHTML:a})}else{if(g.current==null)throw Error(`useFileDiffInstance: A FileDiff instance should exist when unmounting`);g.current.cleanUp(),g.current=null}});return me(()=>{let{current:n}=g;if(n==null)return;let a=Z({controlledSelection:f,hasCustomHeader:c,hasGutterRenderUtility:s,options:t}),o=a!==void 0&&!D(n.options,a);n.setOptions(a),n.render({forceRender:o,fileDiff:e,lineAnnotations:r}),i!==void 0&&n.setSelectedLines(i)}),me(()=>{if(u&&g.current!=null){if(h===void 0)throw Error(`FileDiff: EditContext is not attached`);let e=h(n??{});if(e==null)throw Error(`FileDiff: EditProvider.createEditor must return an editor instance`);try{return e.edit(g.current)}catch(t){throw e.cleanUp(),t}}},[u]),{ref:_,getHoveredLine:(0,X.useCallback)(()=>g.current?.getHoveredLine(),[])}}function Z({options:e,controlledSelection:t,hasCustomHeader:n,hasGutterRenderUtility:r}){return t||r||n?{...e,controlledSelection:t,renderCustomHeader:n?w:e?.renderCustomHeader,renderGutterUtility:r?w:e?.renderGutterUtility}:e}var Q=r();function ge({fileDiff:e,options:t,editorOptions:n,metrics:r,lineAnnotations:i,selectedLines:a,className:o,style:s,prerenderedHTML:c,renderAnnotation:l,renderCustomHeader:u,renderHeaderPrefix:d,renderHeaderFilenameSuffix:f,renderHeaderMetadata:p,renderGutterUtility:m,disableWorkerPool:g=!1,edit:_=!1}){let{ref:v,getHoveredLine:y}=he({fileDiff:e,options:t,editorOptions:n,metrics:r,lineAnnotations:i,selectedLines:a,prerenderedHTML:c,hasGutterRenderUtility:m!=null,hasCustomHeader:u!=null,disableWorkerPool:g,edit:_});return(0,Q.jsx)(h,{ref:v,className:o,style:s,children:W(oe({fileDiff:e,renderCustomHeader:u,renderHeaderPrefix:d,renderHeaderFilenameSuffix:f,renderHeaderMetadata:p,renderAnnotation:l,renderGutterUtility:m,lineAnnotations:i,getHoveredLine:y}),c)})}var $=t();function _e(e){return e.fromTurnCount===0?q(ee)({threadId:e.threadId,toTurnCount:e.toTurnCount}).pipe(n(e=>({kind:`fullThreadDiff`,input:e}))):q(J)({threadId:e.threadId,fromTurnCount:e.fromTurnCount,toTurnCount:e.toTurnCount}).pipe(n(e=>({kind:`turnDiff`,input:e})))}function ve(e){return e instanceof Error?e.message:typeof e==`string`?e:``}function ye(e){let t=ve(e).trim();if(t.length===0)return`Failed to load checkpoint diff.`;let n=t.toLowerCase();if(n.includes(`not a git repository`))return`Turn diffs are unavailable because this project is not a git repository.`;if(n.includes(`checkpoint unavailable for thread`)||n.includes(`checkpoint invariant violation`)){let e=t.indexOf(`:`);if(e>=0){let n=t.slice(e+1).trim();if(n.length>0)return n}}return t}function be(e){let t=ve(e).toLowerCase();return t.includes(`exceeds current turn count`)||t.includes(`checkpoint is unavailable for turn`)||t.includes(`filesystem checkpoint is unavailable`)}function xe(e){let t=_e(e);return f({queryKey:x.checkpointDiff(e),queryFn:async({signal:n})=>{if(!e.environmentId||!e.threadId||t._tag===`None`)throw Error(`Checkpoint diff is unavailable.`);let r=c(e.environmentId);try{return t.value.kind===`fullThreadDiff`?await r.orchestration.getFullThreadDiff(t.value.input,{signal:n}):await r.orchestration.getTurnDiff(t.value.input,{signal:n})}catch(e){throw Error(ye(e),{cause:e})}},enabled:(e.enabled??!0)&&!!e.environmentId&&!!e.threadId&&t._tag===`Some`,staleTime:1/0,retry:(e,t)=>be(t)?e<12:e<3,retryDelay:(e,t)=>be(t)?Math.min(5e3,250*2**(e-1)):Math.min(1e3,100*2**(e-1))})}function Se(e){if(!(!e.canScrollLeft&&!e.canScrollRight))return{maskImage:`linear-gradient(to right, ${e.canScrollLeft?`transparent 24px, black 72px`:`black`}, ${e.canScrollRight?`black calc(100% - 72px), transparent calc(100% - 24px)`:`black`})`}}function Ce(e){return e instanceof Error?e.message:e?`Failed to load checkpoint diff.`:null}function we(e){return{environmentId:e.environmentId??null,threadId:e.threadId,fromTurnCount:e.range?.fromTurnCount??null,toTurnCount:e.range?.toTurnCount??null,cacheScope:e.selectedTurnId?`turn:${e.selectedTurnId}`:e.conversationCacheScope,enabled:e.enabled}}function Te(){let e=(0,$.c)(8),t=(0,X.useRef)(null),[n,r]=(0,X.useState)(!1),[i,a]=(0,X.useState)(!1),o;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(o=()=>{let e=t.current;if(!e){r(!1),a(!1);return}let n=de({scrollLeft:e.scrollLeft,scrollWidth:e.scrollWidth,clientWidth:e.clientWidth});r(n.canScrollLeft),a(n.canScrollRight)},e[0]=o):o=e[0];let s=o,c;e[1]===Symbol.for(`react.memo_cache_sentinel`)?(c=e=>{t.current?.scrollBy({left:e,behavior:`smooth`})},e[1]=c):c=e[1];let l=c,u;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(u=e=>{let n=t.current;n&&ne({scrollWidth:n.scrollWidth,clientWidth:n.clientWidth,deltaX:e.deltaX,deltaY:e.deltaY})&&(e.preventDefault(),n.scrollBy({left:e.deltaY,behavior:`auto`}))},e[2]=u):u=e[2];let d=u,f,p;e[3]===Symbol.for(`react.memo_cache_sentinel`)?(f=()=>{let e=t.current;if(!e)return;let n=window.requestAnimationFrame(s),r=()=>s();e.addEventListener(`scroll`,r,{passive:!0});let i=new ResizeObserver(()=>s());return i.observe(e),()=>{window.cancelAnimationFrame(n),e.removeEventListener(`scroll`,r),i.disconnect()}},p=[s],e[3]=f,e[4]=p):(f=e[3],p=e[4]),(0,X.useEffect)(f,p);let m;return e[5]!==n||e[6]!==i?(m={ref:t,canScrollLeft:n,canScrollRight:i,scrollBy:l,onWheel:d,remeasure:s},e[5]=n,e[6]=i,e[7]=m):m=e[7],m}function Ee(e,t){let n=(0,$.c)(5),r;n[0]===e.current?r=n[1]:(r=()=>{(e.current?.querySelector(`[data-turn-chip-selected='true']`))?.scrollIntoView({block:`nearest`,inline:`nearest`,behavior:`smooth`})},n[0]=e.current,n[1]=r);let i;n[2]!==e||n[3]!==t?(i=[e,t],n[2]=e,n[3]=t,n[4]=i):i=n[4],(0,X.useEffect)(r,i)}var De=`
|
|
2
2
|
[data-diffs-header],
|
|
3
3
|
[data-diff],
|
|
4
4
|
[data-file],
|
|
@@ -61,4 +61,4 @@ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{Ha as t,Mi as n,Ua as
|
|
|
61
61
|
text-decoration-color: currentColor;
|
|
62
62
|
}
|
|
63
63
|
`;function Oe(e){let t=(0,$.c)(44),{mode:n}=e,r=n===void 0?`inline`:n,{resolvedTheme:i}=v(),s=_(),[c,d]=(0,X.useState)(`stacked`),[f,p]=(0,X.useState)(s.diffWordWrap),h=(0,X.useRef)(null),g=(0,X.useRef)(!1),y=Te(),{activeCwd:b,activeThread:x,bodyState:S,diffOpen:C,inferredCheckpointTurnCountByTurnId:w,orderedTurnDiffSummaries:T,renderableFiles:E,renderablePatch:D,selectedFilePath:k,selectedTurn:A,selectedTurnId:j}=Le(i),N,P;t[0]!==C||t[1]!==s.diffWordWrap?(N=()=>{C&&!g.current&&p(s.diffWordWrap),g.current=C},P=[C,s.diffWordWrap],t[0]=C,t[1]=s.diffWordWrap,t[2]=N,t[3]=P):(N=t[2],P=t[3]),(0,X.useEffect)(N,P);let F;t[4]===k?F=t[5]:(F=()=>{!k||!h.current||Array.from(h.current.querySelectorAll(`[data-diff-file-path]`)).find(e=>e.dataset.diffFilePath===k)?.scrollIntoView({block:`nearest`})},t[4]=k,t[5]=F);let I;t[6]!==E||t[7]!==k?(I=[k,E],t[6]=E,t[7]=k,t[8]=I):I=t[8],(0,X.useEffect)(F,I);let L;t[9]===b?L=t[10]:(L=e=>{let t=l();if(!t)return;let n=b?u(e,b):e;o(t,n).catch(ke)},t[9]=b,t[10]=L);let R=L,z;t[11]===x?z=t[12]:(z=e=>{x&&a.getState().openDiff(O(M(x.environmentId,x.id)),e)},t[11]=x,t[12]=z);let B=z,V;t[13]===x?V=t[14]:(V=()=>{x&&a.getState().openDiff(O(M(x.environmentId,x.id)))},t[13]=x,t[14]=V);let H=V,U;t[15]===y.remeasure?U=t[16]:(U=()=>{let e=window.requestAnimationFrame(y.remeasure);return()=>window.cancelAnimationFrame(e)},t[15]=y.remeasure,t[16]=U);let W;t[17]!==T||t[18]!==j||t[19]!==y.remeasure?(W=[T,j,y.remeasure],t[17]=T,t[18]=j,t[19]=y.remeasure,t[20]=W):W=t[20],(0,X.useEffect)(U,W),Ee(y.ref,A?.turnId??j);let G;t[21]!==c||t[22]!==f||t[23]!==w||t[24]!==T||t[25]!==B||t[26]!==H||t[27]!==A||t[28]!==j||t[29]!==s||t[30]!==y?(G=(0,Q.jsx)(Ae,{diffRenderMode:c,diffWordWrap:f,inferredCheckpointTurnCountByTurnId:w,orderedTurnDiffSummaries:T,selectTurn:B,selectWholeConversation:H,selectedTurn:A,selectedTurnId:j,setDiffRenderMode:d,setDiffWordWrap:p,settings:s,turnStrip:y}),t[21]=c,t[22]=f,t[23]=w,t[24]=T,t[25]=B,t[26]=H,t[27]=A,t[28]=j,t[29]=s,t[30]=y,t[31]=G):G=t[31];let K=G,q;t[32]!==S||t[33]!==c||t[34]!==f||t[35]!==R||t[36]!==E||t[37]!==D||t[38]!==i?(q=(0,Q.jsx)(je,{bodyState:S,diffRenderMode:c,diffWordWrap:f,openDiffFileInEditor:R,patchViewportRef:h,renderableFiles:E,renderablePatch:D,resolvedTheme:i}),t[32]=S,t[33]=c,t[34]=f,t[35]=R,t[36]=E,t[37]=D,t[38]=i,t[39]=q):q=t[39];let J;return t[40]!==K||t[41]!==r||t[42]!==q?(J=(0,Q.jsx)(m,{mode:r,header:K,children:q}),t[40]=K,t[41]=r,t[42]=q,t[43]=J):J=t[43],J}function ke(e){console.warn(`Failed to open diff file in editor.`,e)}function Ae(e){let t=(0,$.c)(59),{diffRenderMode:n,diffWordWrap:r,inferredCheckpointTurnCountByTurnId:i,orderedTurnDiffSummaries:a,selectTurn:o,selectWholeConversation:s,selectedTurn:c,selectedTurnId:l,setDiffRenderMode:u,setDiffWordWrap:d,settings:f,turnStrip:p}=e,m,h;t[0]===p?(m=t[1],h=t[2]):(m=(0,Q.jsx)(Be,{direction:`left`,strip:p}),h=(0,Q.jsx)(Be,{direction:`right`,strip:p}),t[0]=p,t[1]=m,t[2]=h);let g=p.ref,_;t[3]!==p.canScrollLeft||t[4]!==p.canScrollRight?(_=Se({canScrollLeft:p.canScrollLeft,canScrollRight:p.canScrollRight}),t[3]=p.canScrollLeft,t[4]=p.canScrollRight,t[5]=_):_=t[5];let v=p.onWheel,y=l===null,b=l===null?`border-border bg-accent text-accent-foreground`:`border-border/70 bg-background/70 text-muted-foreground/80 hover:border-border hover:text-foreground/80`,x;t[6]===b?x=t[7]:(x=P(`rounded-md border px-2 py-1 text-left transition-colors`,b),t[6]=b,t[7]=x);let S;t[8]===Symbol.for(`react.memo_cache_sentinel`)?(S=(0,Q.jsx)(`div`,{className:`text-[10px] leading-tight font-medium`,children:`All turns`}),t[8]=S):S=t[8];let C;t[9]===x?C=t[10]:(C=(0,Q.jsx)(`div`,{className:x,children:S}),t[9]=x,t[10]=C);let w;t[11]!==s||t[12]!==C||t[13]!==y?(w=(0,Q.jsx)(`button`,{type:`button`,className:`shrink-0 rounded-md`,onClick:s,"data-turn-chip-selected":y,children:C}),t[11]=s,t[12]=C,t[13]=y,t[14]=w):w=t[14];let T;if(t[15]!==i||t[16]!==a||t[17]!==o||t[18]!==c?.turnId||t[19]!==f){let e;t[21]!==i||t[22]!==o||t[23]!==c?.turnId||t[24]!==f?(e=e=>(0,Q.jsx)(Ve,{summary:e,selected:e.turnId===c?.turnId,turnCount:e.checkpointTurnCount??i[e.turnId],timestampFormat:f.timestampFormat,onSelect:o},e.turnId),t[21]=i,t[22]=o,t[23]=c?.turnId,t[24]=f,t[25]=e):e=t[25],T=a.map(e),t[15]=i,t[16]=a,t[17]=o,t[18]=c?.turnId,t[19]=f,t[20]=T}else T=t[20];let E;t[26]!==w||t[27]!==T||t[28]!==_||t[29]!==p.onWheel||t[30]!==p.ref?(E=(0,Q.jsxs)(`div`,{ref:g,className:`turn-chip-strip flex gap-1 overflow-x-auto px-8 py-0.5`,style:_,onWheel:v,children:[w,T]}),t[26]=w,t[27]=T,t[28]=_,t[29]=p.onWheel,t[30]=p.ref,t[31]=E):E=t[31];let D;t[32]!==m||t[33]!==E||t[34]!==h?(D=(0,Q.jsxs)(`div`,{className:`relative min-w-0 flex-1 [-webkit-app-region:no-drag]`,children:[m,h,E]}),t[32]=m,t[33]=E,t[34]=h,t[35]=D):D=t[35];let O;t[36]===n?O=t[37]:(O=[n],t[36]=n,t[37]=O);let k;t[38]===u?k=t[39]:(k=e=>{let t=e[0];(t===`stacked`||t===`split`)&&u(t)},t[38]=u,t[39]=k);let A;t[40]===Symbol.for(`react.memo_cache_sentinel`)?(A=(0,Q.jsx)(R,{"aria-label":`Stacked diff view`,value:`stacked`,children:(0,Q.jsx)(se,{className:`size-3`})}),t[40]=A):A=t[40];let j;t[41]===Symbol.for(`react.memo_cache_sentinel`)?(j=(0,Q.jsx)(R,{"aria-label":`Split diff view`,value:`split`,children:(0,Q.jsx)(ie,{className:`size-3`})}),t[41]=j):j=t[41];let M;t[42]!==O||t[43]!==k?(M=(0,Q.jsxs)(F,{className:`shrink-0`,variant:`outline`,size:`xs`,value:O,onValueChange:k,children:[A,j]}),t[42]=O,t[43]=k,t[44]=M):M=t[44];let N=r?`Disable diff line wrapping`:`Enable diff line wrapping`,I=r?`Disable line wrapping`:`Enable line wrapping`,L;t[45]===d?L=t[46]:(L=e=>{d(!!e)},t[45]=d,t[46]=L);let z;t[47]===Symbol.for(`react.memo_cache_sentinel`)?(z=(0,Q.jsx)(le,{className:`size-3`}),t[47]=z):z=t[47];let B;t[48]!==r||t[49]!==N||t[50]!==I||t[51]!==L?(B=(0,Q.jsx)(R,{"aria-label":N,title:I,variant:`outline`,size:`xs`,pressed:r,onPressedChange:L,children:z}),t[48]=r,t[49]=N,t[50]=I,t[51]=L,t[52]=B):B=t[52];let V;t[53]!==M||t[54]!==B?(V=(0,Q.jsxs)(`div`,{className:`flex shrink-0 items-center gap-1 [-webkit-app-region:no-drag]`,children:[M,B]}),t[53]=M,t[54]=B,t[55]=V):V=t[55];let H;return t[56]!==D||t[57]!==V?(H=(0,Q.jsxs)(Q.Fragment,{children:[D,V]}),t[56]=D,t[57]=V,t[58]=H):H=t[58],H}function je(e){let t=(0,$.c)(18),{bodyState:n,diffRenderMode:r,diffWordWrap:i,openDiffFileInEditor:a,patchViewportRef:o,renderableFiles:s,renderablePatch:c,resolvedTheme:l}=e;if(n.kind===`no-thread`){let e;return t[0]===Symbol.for(`react.memo_cache_sentinel`)?(e=(0,Q.jsx)(Ne,{children:`Select a thread to inspect turn diffs.`}),t[0]=e):e=t[0],e}if(n.kind===`not-git-repo`){let e;return t[1]===Symbol.for(`react.memo_cache_sentinel`)?(e=(0,Q.jsx)(Ne,{children:`Turn diffs are unavailable because this project is not a git repository.`}),t[1]=e):e=t[1],e}if(n.kind===`no-completed-turns`){let e;return t[2]===Symbol.for(`react.memo_cache_sentinel`)?(e=(0,Q.jsx)(Ne,{children:`No completed turns yet.`}),t[2]=e):e=t[2],e}let u;t[3]!==n.error||t[4]!==c?(u=n.error&&!c&&(0,Q.jsx)(`div`,{className:`px-3`,children:(0,Q.jsx)(`p`,{className:`mb-2 text-[11px] text-destructive-foreground`,children:n.error})}),t[3]=n.error,t[4]=c,t[5]=u):u=t[5];let d;t[6]!==n||t[7]!==r||t[8]!==i||t[9]!==a||t[10]!==s||t[11]!==c||t[12]!==l?(d=c?c.kind===`files`?(0,Q.jsx)(K,{className:`diff-render-surface h-full min-h-0 overflow-auto px-2 pb-2`,config:{overscrollSize:600,intersectionObserverMargin:1200},children:s.map(e=>{let t=Y(e),n=`${fe(e)}:${l}`;return(0,Q.jsx)(`div`,{"data-diff-file-path":t,className:`diff-render-file mb-2 rounded-md first:mt-2 last:mb-0`,onClickCapture:e=>{(e.nativeEvent.composedPath?.()??[]).some(Me)&&a(t)},children:(0,Q.jsx)(ge,{fileDiff:e,options:{diffStyle:r===`split`?`split`:`unified`,lineDiffType:`none`,overflow:i?`wrap`:`scroll`,theme:S(l),themeType:l,unsafeCSS:De}})},n)})}):(0,Q.jsx)(`div`,{className:`h-full overflow-auto p-2`,children:(0,Q.jsxs)(`div`,{className:`space-y-2`,children:[(0,Q.jsx)(`p`,{className:`text-[11px] text-muted-foreground/75`,children:c.reason}),(0,Q.jsx)(`pre`,{className:P(`max-h-[72vh] rounded-md border border-border/70 bg-background/70 p-3 font-mono text-[11px] leading-relaxed text-muted-foreground/90`,i?`overflow-auto whitespace-pre-wrap wrap-break-word`:`overflow-auto`),children:c.text})]})}):(0,Q.jsx)(Re,{bodyState:n}),t[6]=n,t[7]=r,t[8]=i,t[9]=a,t[10]=s,t[11]=c,t[12]=l,t[13]=d):d=t[13];let f;return t[14]!==o||t[15]!==u||t[16]!==d?(f=(0,Q.jsx)(Q.Fragment,{children:(0,Q.jsxs)(`div`,{ref:o,className:`diff-panel-viewport min-h-0 min-w-0 flex-1 overflow-hidden`,children:[u,d]})}),t[14]=o,t[15]=u,t[16]=d,t[17]=f):f=t[17],f}function Me(e){return e instanceof Element&&e.hasAttribute(`data-title`)}function Ne(e){let t=(0,$.c)(2),{children:n}=e,r;return t[0]===n?r=t[1]:(r=(0,Q.jsx)(`div`,{className:`flex flex-1 items-center justify-center px-5 text-center text-xs text-muted-foreground/70`,children:n}),t[0]=n,t[1]=r),r}function Pe(){let e=(0,$.c)(19),t;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={strict:!1,select:Ie},e[0]=t):t=e[0];let n=s(t),r;e[1]===Symbol.for(`react.memo_cache_sentinel`)?(r={strict:!1,select:Fe},e[1]=r):r=e[1];let i=B(r),a=i.rightPanel===`diff`,o=n?.threadId??null,c,l;e[2]===n?l=e[3]:(l=b(n),e[2]=n,e[3]=l),c=l;let u=k(c),f=He(u),p=u?.worktreePath,m=f?.cwd,h;e[4]!==p||e[5]!==m?(h=I({threadWorktreePath:p,projectCwd:m}),e[4]=p,e[5]=m,e[6]=h):h=e[6];let g=h,_=u?.environmentId??null,v=g??null,y;e[7]!==_||e[8]!==v?(y={environmentId:_,cwd:v},e[7]=_,e[8]=v,e[9]=y):y=e[9];let x=d(y),S;e[10]===x.data?S=e[11]:(S=z(x.data),e[10]=x.data,e[11]=S);let C=S,w;return e[12]!==g||e[13]!==u||e[14]!==o||e[15]!==a||e[16]!==i||e[17]!==C?(w={activeThread:u,activeThreadId:o,activeCwd:g,isGitRepo:C,diffSearch:i,diffOpen:a},e[12]=g,e[13]=u,e[14]=o,e[15]=a,e[16]=i,e[17]=C,e[18]=w):w=e[18],w}function Fe(e){return G(e)}function Ie(e){return C(e)}function Le(e){let{activeThread:t,activeThreadId:n,activeCwd:r,isGitRepo:i,diffSearch:a,diffOpen:o}=Pe(),{turnDiffSummaries:s,inferredCheckpointTurnCountByTurnId:c}=H(t),l=a.diffTurnId??null,u=l===null?null:a.diffFilePath??null,{activeCheckpointRange:d,conversationCacheScope:f,orderedTurnDiffSummaries:p,selectedTurn:m}=(0,X.useMemo)(()=>te({summaries:s,inferredCheckpointTurnCountByTurnId:c,selectedTurnId:l}),[c,l,s]),h=T(xe(we({environmentId:t?.environmentId,threadId:n,range:d,selectedTurnId:m?.turnId,conversationCacheScope:f,enabled:i}))),g=h.isLoading,_=Ce(h.error),v=h.data?.diff,y=typeof v==`string`&&v.trim().length===0,{emptyDiffMessage:b}=(0,X.useMemo)(()=>ae(m),[m]),x=(0,X.useMemo)(()=>ce(v,`diff-panel:${e}`),[e,v]),S=(0,X.useMemo)(()=>Ue(x),[x]);return{activeCwd:r,activeThread:t,bodyState:ue({hasActiveThread:!!t,isGitRepo:i,turnSummaryCount:p.length,checkpointDiffError:_,hasRenderablePatch:!!x,isLoadingCheckpointDiff:g,hasNoNetChanges:y,emptyDiffMessage:b}),diffOpen:o,inferredCheckpointTurnCountByTurnId:c,orderedTurnDiffSummaries:p,renderableFiles:S,renderablePatch:x,selectedFilePath:u,selectedTurn:m,selectedTurnId:l}}function Re(e){let t=(0,$.c)(4),{bodyState:n}=e;if(n.kind===`loading`){let e;return t[0]===Symbol.for(`react.memo_cache_sentinel`)?(e=(0,Q.jsx)(N,{label:`Loading checkpoint diff...`}),t[0]=e):e=t[0],e}let r;t[1]===Symbol.for(`react.memo_cache_sentinel`)?(r=(0,Q.jsx)(L,{className:`size-7 text-muted-foreground/25`}),t[1]=r):r=t[1];let i=n.kind===`empty`?n.message:`No diff is available for this range.`,a;return t[2]===i?a=t[3]:(a=(0,Q.jsxs)(`div`,{className:`flex h-full flex-col items-center justify-center gap-2 px-5 py-2 text-center`,children:[r,(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground/70`,children:i})]}),t[2]=i,t[3]=a),a}var ze=180;function Be(e){let t=(0,$.c)(14),{direction:n,strip:r}=e,i=n===`left`,a=i?r.canScrollLeft:r.canScrollRight,o=i?U:y,s=i?`left-0`:`right-0`,c=a?`border-border/70 hover:border-border hover:text-foreground`:`cursor-not-allowed border-border/40 text-muted-foreground/40`,l;t[0]!==s||t[1]!==c?(l=P(`absolute top-1/2 z-20 inline-flex size-6 -translate-y-1/2 items-center justify-center rounded-md border bg-background/90 text-muted-foreground transition-colors`,s,c),t[0]=s,t[1]=c,t[2]=l):l=t[2];let u;t[3]!==i||t[4]!==r?(u=()=>r.scrollBy(i?-180:ze),t[3]=i,t[4]=r,t[5]=u):u=t[5];let d=!a,f=`Scroll turn list ${n}`,p;t[6]===o?p=t[7]:(p=(0,Q.jsx)(o,{className:`size-3.5`}),t[6]=o,t[7]=p);let m;return t[8]!==l||t[9]!==u||t[10]!==d||t[11]!==f||t[12]!==p?(m=(0,Q.jsx)(`button`,{type:`button`,className:l,onClick:u,disabled:d,"aria-label":f,children:p}),t[8]=l,t[9]=u,t[10]=d,t[11]=f,t[12]=p,t[13]=m):m=t[13],m}function Ve(e){let t=(0,$.c)(23),{summary:n,selected:r,turnCount:i,timestampFormat:a,onSelect:o}=e,s;t[0]!==o||t[1]!==n.turnId?(s=()=>o(n.turnId),t[0]=o,t[1]=n.turnId,t[2]=s):s=t[2];let c=n.turnId,l=r?`border-border bg-accent text-accent-foreground`:`border-border/70 bg-background/70 text-muted-foreground/80 hover:border-border hover:text-foreground/80`,u;t[3]===l?u=t[4]:(u=P(`rounded-md border px-2 py-1 text-left transition-colors`,l),t[3]=l,t[4]=u);let d=i??`?`,f;t[5]===d?f=t[6]:(f=(0,Q.jsxs)(`span`,{className:`text-[10px] leading-tight font-medium`,children:[`Turn `,d]}),t[5]=d,t[6]=f);let p;t[7]!==n.completedAt||t[8]!==a?(p=g(n.completedAt,a),t[7]=n.completedAt,t[8]=a,t[9]=p):p=t[9];let m;t[10]===p?m=t[11]:(m=(0,Q.jsx)(`span`,{className:`text-[9px] leading-tight opacity-70`,children:p}),t[10]=p,t[11]=m);let h;t[12]!==f||t[13]!==m?(h=(0,Q.jsxs)(`div`,{className:`flex items-center gap-1`,children:[f,m]}),t[12]=f,t[13]=m,t[14]=h):h=t[14];let _;t[15]!==u||t[16]!==h?(_=(0,Q.jsx)(`div`,{className:u,children:h}),t[15]=u,t[16]=h,t[17]=_):_=t[17];let v;return t[18]!==r||t[19]!==n.turnId||t[20]!==s||t[21]!==_?(v=(0,Q.jsx)(`button`,{type:`button`,className:`shrink-0 rounded-md`,onClick:s,title:c,"data-turn-chip-selected":r,children:_}),t[18]=r,t[19]=n.turnId,t[20]=s,t[21]=_,t[22]=v):v=t[22],v}function He(e){let t=(0,$.c)(3),n=e?.environmentId,r=e?.projectId,i;return t[0]!==n||t[1]!==r?(i=e=>n&&r?E(e,{environmentId:n,projectId:r}):void 0,t[0]=n,t[1]=r,t[2]=i):i=t[2],k(i)}function Ue(e){return!e||e.kind!==`files`?[]:e.files.toSorted((e,t)=>Y(e).localeCompare(Y(t),void 0,{numeric:!0,sensitivity:`base`}))}export{Oe as default};
|
|
64
|
-
//# sourceMappingURL=DiffPanel-
|
|
64
|
+
//# sourceMappingURL=DiffPanel-BXrpBBfH.js.map
|