@cmmd-center/forge 0.13.117 → 0.13.118
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 +246 -10
- package/dist/bin.mjs +249 -11
- package/dist/client/assets/{DiffPanel-C_nvkXx5.js → DiffPanel-DUNnxsQq.js} +2 -2
- package/dist/client/assets/{DiffPanel.logic-DxnURjwP.js → DiffPanel.logic-B5u-aRQa.js} +2 -2
- package/dist/client/assets/{DiffWorkerPoolProvider-BkGL_kpx.js → DiffWorkerPoolProvider-CACmXsZU.js} +2 -2
- package/dist/client/assets/{PullRequestCodePanel-6zxjVao1.js → PullRequestCodePanel-QgCd7SjY.js} +2 -2
- package/dist/client/assets/{Virtualizer-PGWR57wi.js → Virtualizer-DIbjvGwY.js} +2 -2
- package/dist/client/assets/{WorkerPoolContext-7Wt00bdA.js → WorkerPoolContext-DR8-tB5e.js} +3 -3
- package/dist/client/assets/{index-DiHek4NP.js → index-DbDT5T6P.js} +6 -6
- package/dist/client/index.html +4 -4
- package/dist/forge-build.json +1 -1
- package/package.json +1 -1
package/dist/bin.mjs
CHANGED
|
@@ -66046,7 +66046,7 @@ function normalizeNumberish(value) {
|
|
|
66046
66046
|
}
|
|
66047
66047
|
//#endregion
|
|
66048
66048
|
//#region package.json
|
|
66049
|
-
var version$1 = "0.13.
|
|
66049
|
+
var version$1 = "0.13.118";
|
|
66050
66050
|
//#endregion
|
|
66051
66051
|
//#region src/sentry.ts
|
|
66052
66052
|
const SERVER_APP_NAME = "forge-server";
|
|
@@ -95045,6 +95045,16 @@ var RuntimeReplicationClient = class extends Service$1()("forge/runtimeReplicati
|
|
|
95045
95045
|
* from the retry cap and registration can outlast the cap.
|
|
95046
95046
|
*/
|
|
95047
95047
|
const RUNTIME_NOT_REGISTERED_CODE = "RUNTIME_NOT_REGISTERED";
|
|
95048
|
+
/**
|
|
95049
|
+
* CMMD returned 409 THREAD_STREAM_PAYLOAD_CONFLICT or THREAD_STREAM_HEAD_MISMATCH:
|
|
95050
|
+
* its canonical history for a thread generation has diverged from the batch
|
|
95051
|
+
* Forge just sent (forge#3620). Exported so `processRuntimeReplicationOutboxItem`
|
|
95052
|
+
* can tell when a recorded `fail()` may have deferred the actual repair to a
|
|
95053
|
+
* full re-projection instead of finishing it inline -- see
|
|
95054
|
+
* `RuntimeReplicationOutbox.ts`'s `fail()`/`repairThreadStreamFromRemoteConflict`
|
|
95055
|
+
* for the repair itself.
|
|
95056
|
+
*/
|
|
95057
|
+
const THREAD_STREAM_REMOTE_CONFLICT_CODES = new Set(["THREAD_STREAM_PAYLOAD_CONFLICT", "THREAD_STREAM_HEAD_MISMATCH"]);
|
|
95048
95058
|
const retryableCodes = new Set([
|
|
95049
95059
|
"RUNTIME_NOT_READY",
|
|
95050
95060
|
"RUNTIME_THREAD_NOT_READY",
|
|
@@ -299844,7 +299854,7 @@ function resolveBuildCommitFromEnv(env) {
|
|
|
299844
299854
|
* environment descriptor down instead of reporting an honest "unknown".
|
|
299845
299855
|
*/
|
|
299846
299856
|
function readBakedBuildCommit() {
|
|
299847
|
-
return "
|
|
299857
|
+
return "1de5f431edc763d9146f9be86885d18e191ea9f7";
|
|
299848
299858
|
}
|
|
299849
299859
|
async function resolveServerBuildCommit(input) {
|
|
299850
299860
|
if (isFullCommitSha(input.baked)) return input.baked;
|
|
@@ -314118,6 +314128,33 @@ function applyPendingThreadArchives(input) {
|
|
|
314118
314128
|
}
|
|
314119
314129
|
//#endregion
|
|
314120
314130
|
//#region src/runtimeReplication/processOutboxItem.ts
|
|
314131
|
+
/** The thread id a `thread:<id>` outbox stream key was minted from. */
|
|
314132
|
+
function threadIdFromStreamKey(streamKey) {
|
|
314133
|
+
return ThreadId.make(streamKey.slice(7));
|
|
314134
|
+
}
|
|
314135
|
+
/**
|
|
314136
|
+
* Attempts `enqueueThread` gets for one outbox item before this gives up and
|
|
314137
|
+
* logs loudly. `dependencies.enqueueThread` is the closure RuntimeReplication.ts
|
|
314138
|
+
* builds for `processItem` specifically -- unlike the swallowing variant it
|
|
314139
|
+
* hands to the domain-event reactor and the 5-minute heartbeat (which retry
|
|
314140
|
+
* on their own cadence regardless), a Cause escaping this one is visible
|
|
314141
|
+
* here. Right after `fail()` parks a thread-events row under
|
|
314142
|
+
* THREAD_STREAM_REMOTE_CONFLICT_REPROJECTION_PENDING_CODE, this call is the
|
|
314143
|
+
* corrective re-projection that clears it; without a retry here, one failed
|
|
314144
|
+
* attempt left the row silently blocked until the next heartbeat, a later
|
|
314145
|
+
* domain event, or a manual retry (forge#3621 finding 2). A transient
|
|
314146
|
+
* failure gets a few immediate retries; one that survives them all is logged
|
|
314147
|
+
* loudly instead of disappearing.
|
|
314148
|
+
*/
|
|
314149
|
+
const ENQUEUE_THREAD_RETRY_ATTEMPTS = 3;
|
|
314150
|
+
function enqueueThreadWithBoundedRetry(enqueueThread, threadId, context, attemptsRemaining = ENQUEUE_THREAD_RETRY_ATTEMPTS) {
|
|
314151
|
+
return enqueueThread(threadId).pipe(catchCause((cause) => attemptsRemaining > 1 ? enqueueThreadWithBoundedRetry(enqueueThread, threadId, context, attemptsRemaining - 1) : logError("Runtime replication thread re-projection failed after retrying; it will run again on the next heartbeat, domain event, or manual retry.", {
|
|
314152
|
+
...context,
|
|
314153
|
+
threadId,
|
|
314154
|
+
cause,
|
|
314155
|
+
attempts: ENQUEUE_THREAD_RETRY_ATTEMPTS
|
|
314156
|
+
})));
|
|
314157
|
+
}
|
|
314121
314158
|
function publicationMetricAttributes(item, outcome, failure) {
|
|
314122
314159
|
return {
|
|
314123
314160
|
operation: item.operation,
|
|
@@ -314155,7 +314192,12 @@ function processRuntimeReplicationOutboxItem(item, dependencies) {
|
|
|
314155
314192
|
failureKind: failure.kind,
|
|
314156
314193
|
errorCode: failure.code
|
|
314157
314194
|
});
|
|
314195
|
+
return;
|
|
314158
314196
|
}
|
|
314197
|
+
if (item.operation === "thread-events" && THREAD_STREAM_REMOTE_CONFLICT_CODES.has(failure.code)) yield* enqueueThreadWithBoundedRetry(dependencies.enqueueThread, threadIdFromStreamKey(item.streamKey), {
|
|
314198
|
+
runtimeId: item.runtimeId,
|
|
314199
|
+
streamKey: item.streamKey
|
|
314200
|
+
});
|
|
314159
314201
|
});
|
|
314160
314202
|
return gen(function* () {
|
|
314161
314203
|
const payload = yield* sync$1(() => {
|
|
@@ -314196,7 +314238,10 @@ function processRuntimeReplicationOutboxItem(item, dependencies) {
|
|
|
314196
314238
|
return all([
|
|
314197
314239
|
increment(runtimeReplicationPublicationAttemptsTotal, publicationMetricAttributes(item, "success")),
|
|
314198
314240
|
update$3(withAttributes(runtimeReplicationPublicationLatency, metricAttributes({ operation: item.operation })), millis(publicationLatency)),
|
|
314199
|
-
item.operation === "thread-events" ? dependencies.enqueueThread(
|
|
314241
|
+
item.operation === "thread-events" ? enqueueThreadWithBoundedRetry(dependencies.enqueueThread, threadIdFromStreamKey(item.streamKey), {
|
|
314242
|
+
runtimeId: item.runtimeId,
|
|
314243
|
+
streamKey: item.streamKey
|
|
314244
|
+
}) : void_$1
|
|
314200
314245
|
]).pipe(asVoid);
|
|
314201
314246
|
}))
|
|
314202
314247
|
}));
|
|
@@ -314273,15 +314318,16 @@ const RuntimeReplicationLive = effect(RuntimeReplication, gen(function* () {
|
|
|
314273
314318
|
operation: "inventory",
|
|
314274
314319
|
payload
|
|
314275
314320
|
}) : void_$1;
|
|
314276
|
-
const
|
|
314321
|
+
const enqueueThreadUnsafe = (threadId) => runtimeId ? snapshots.getThreadDetailById(threadId).pipe(flatMap((thread) => isSome(thread) ? logTurnsMissingModelSelection(threadId, thread.value).pipe(andThen(outbox.enqueueThread({
|
|
314277
314322
|
runtimeId,
|
|
314278
314323
|
streamKey: `thread:${threadId}`,
|
|
314279
314324
|
events: serializeRuntimeThreadEvents(thread.value),
|
|
314280
314325
|
historyFinalized: thread.value.archivedAt != null
|
|
314281
|
-
}))) : outbox.remove(runtimeId, `thread:${threadId}`)),
|
|
314326
|
+
}))) : outbox.remove(runtimeId, `thread:${threadId}`)), orDie) : void_$1;
|
|
314327
|
+
const enqueueThread = (threadId) => enqueueThreadUnsafe(threadId).pipe(catchCause((cause) => logError("Runtime replication thread projection failed.", {
|
|
314282
314328
|
cause,
|
|
314283
314329
|
threadId
|
|
314284
|
-
})))
|
|
314330
|
+
})));
|
|
314285
314331
|
const projectEvent = (event) => runtimeId ? activeHourMeter.markAwake(runtimeId).pipe(andThen(all([snapshots.getShellSnapshot(), providerRegistry.getProviders])), flatMap(([snapshot, providers]) => {
|
|
314286
314332
|
const inventory = serializeRuntimeInventory(snapshot, providers);
|
|
314287
314333
|
const threadId = event.aggregateKind === "thread" ? ThreadId.make(event.aggregateId) : null;
|
|
@@ -314294,7 +314340,7 @@ const RuntimeReplicationLive = effect(RuntimeReplication, gen(function* () {
|
|
|
314294
314340
|
const processItem = (item) => processRuntimeReplicationOutboxItem(item, {
|
|
314295
314341
|
outbox,
|
|
314296
314342
|
client,
|
|
314297
|
-
enqueueThread
|
|
314343
|
+
enqueueThread: enqueueThreadUnsafe
|
|
314298
314344
|
});
|
|
314299
314345
|
const drain = outbox.claim(BATCH_SIZE).pipe(flatMap((items) => forEach(items, processItem, { concurrency: 1 })), catchCause((cause) => logError("Runtime replication outbox drain failed.", { cause })));
|
|
314300
314346
|
const start = () => {
|
|
@@ -314377,7 +314423,14 @@ const RuntimeReplicationLive = effect(RuntimeReplication, gen(function* () {
|
|
|
314377
314423
|
}), catchCause((cause) => logError("Runtime replication outbox diagnostics failed.", { cause })), repeat(spaced("30 seconds")), forkScoped)
|
|
314378
314424
|
]).pipe(asVoid);
|
|
314379
314425
|
};
|
|
314380
|
-
|
|
314426
|
+
const retryReprojectionPending = (streamKeys) => forEach(streamKeys, (streamKey) => enqueueThread(threadIdFromStreamKey(streamKey)), {
|
|
314427
|
+
concurrency: 1,
|
|
314428
|
+
discard: true
|
|
314429
|
+
});
|
|
314430
|
+
return RuntimeReplication.of({
|
|
314431
|
+
start,
|
|
314432
|
+
retryReprojectionPending
|
|
314433
|
+
});
|
|
314381
314434
|
}));
|
|
314382
314435
|
//#endregion
|
|
314383
314436
|
//#region src/runtimeReplication/activeHourProtocol.ts
|
|
@@ -314664,6 +314717,100 @@ const RUNTIME_REPLICATION_RETRY_EXHAUSTED_CODE = "RUNTIME_REPLICATION_RETRY_EXHA
|
|
|
314664
314717
|
* claims it; only `recover()` and the manual retry endpoint do.
|
|
314665
314718
|
*/
|
|
314666
314719
|
const THREAD_STREAM_PAYLOAD_HASH_MISMATCH_CODE = "THREAD_STREAM_PAYLOAD_HASH_MISMATCH";
|
|
314720
|
+
/**
|
|
314721
|
+
* CMMD returned 409 THREAD_STREAM_PAYLOAD_CONFLICT or THREAD_STREAM_HEAD_MISMATCH:
|
|
314722
|
+
* its canonical history for this generation has diverged from the batch Forge
|
|
314723
|
+
* just sent (forge#3620). The common trigger is CMMD's own reclaim job
|
|
314724
|
+
* replacing the Sprite (CMMD-Center/CMMD#5865) mid-turn, which wipes this
|
|
314725
|
+
* runtime's local `runtime_replication_streams` cursor; Forge then rebuilds a
|
|
314726
|
+
* batch from sequence 1 that CMMD, still holding the old generation's
|
|
314727
|
+
* acknowledged history, refuses. `fail()` recovers by starting a brand-new
|
|
314728
|
+
* repair generation from sequence 1 with an empty previous head -- the one
|
|
314729
|
+
* shape CMMD's `validateRuntimeThreadAppend` accepts unconditionally as a
|
|
314730
|
+
* reset -- rather than blocking the thread forever.
|
|
314731
|
+
*
|
|
314732
|
+
* The refused batch's own `events` are never safe to rebuild that repair from
|
|
314733
|
+
* directly, regardless of `fromSequence`. A batch is capped at `batchSize`
|
|
314734
|
+
* (500, see `buildRuntimeThreadBatch` in protocol.ts) and `isFinalBatch` is
|
|
314735
|
+
* computed relative to whatever array it was handed -- so re-running
|
|
314736
|
+
* `buildRuntimeThreadBatch` on a refused batch's own, already-truncated
|
|
314737
|
+
* `events` array makes an 800-event thread's 500-event suffix look like a
|
|
314738
|
+
* complete 500-event history all over again, `isFinalBatch: true` included.
|
|
314739
|
+
* CMMD accepts that as this generation's full canonical history on the reset
|
|
314740
|
+
* rule and events 501 onward are gone for good (CodeRabbit finding on
|
|
314741
|
+
* forge#3621, forge#3620 finding 1). This holds even at `fromSequence === 1`:
|
|
314742
|
+
* a fresh generation's very first batch is truncated exactly the same way
|
|
314743
|
+
* once the thread has more events than `batchSize`.
|
|
314744
|
+
*
|
|
314745
|
+
* `fail()` instead always resets the local cursor to a new repair generation
|
|
314746
|
+
* and parks the row blocked under
|
|
314747
|
+
* `THREAD_STREAM_REMOTE_CONFLICT_REPROJECTION_PENDING_CODE` until
|
|
314748
|
+
* `processRuntimeReplicationOutboxItem` re-derives the FULL thread history
|
|
314749
|
+
* through the same `enqueueThread` projection path the success path already
|
|
314750
|
+
* runs after every publish (see `processOutboxItem.ts`) and overwrites this
|
|
314751
|
+
* row with a correctly full batch. That re-projection reads the domain
|
|
314752
|
+
* model's complete event list, not a persisted batch's truncated `events`,
|
|
314753
|
+
* so it is safe to rebuild from no matter how many events the thread holds.
|
|
314754
|
+
*
|
|
314755
|
+
* The reset is bounded to one per distinct conflict, keyed on whether the
|
|
314756
|
+
* reset itself has made any progress: see `refusedResetIsStuck` below. The
|
|
314757
|
+
* re-projection failing to land promptly does not strand the row forever --
|
|
314758
|
+
* `processRuntimeReplicationOutboxItem` retries it a bounded number of times
|
|
314759
|
+
* before giving up for this cycle, the 5-minute replication heartbeat and any
|
|
314760
|
+
* later domain event on this thread call `enqueueThread` again regardless,
|
|
314761
|
+
* and the manual `/api/runtime-replication/retry` endpoint calls it directly
|
|
314762
|
+
* for rows parked under this code (see `RuntimeReplication.ts`'s
|
|
314763
|
+
* `retryReprojectionPending`).
|
|
314764
|
+
*/
|
|
314765
|
+
const THREAD_STREAM_REMOTE_CONFLICT_REPROJECTION_PENDING_CODE = "THREAD_STREAM_REMOTE_CONFLICT_REPROJECTION_PENDING";
|
|
314766
|
+
/**
|
|
314767
|
+
* Whether a refused batch is the exact canonical reset shape (`fromSequence
|
|
314768
|
+
* === 1`, empty previous head, deterministic content) under a generation the
|
|
314769
|
+
* local cursor already holds with zero acknowledged progress -- i.e. this
|
|
314770
|
+
* exact reset was already sent once and CMMD refused it again, which makes
|
|
314771
|
+
* it genuinely corrupt local history rather than a race to retry. Applies to
|
|
314772
|
+
* any non-base generation (both the `:repair:` suffix this file mints and
|
|
314773
|
+
* the `:final:` suffix `runtimeThreadFinalGenerationId` mints for an
|
|
314774
|
+
* archived thread's first post-transition batch -- both always start a fresh
|
|
314775
|
+
* generation at sequence 1 from an empty head the same way).
|
|
314776
|
+
*
|
|
314777
|
+
* The base generation is exempt unconditionally: its own first-sequence
|
|
314778
|
+
* conflict is the original, always-eligible incident trigger (Forge's local
|
|
314779
|
+
* cursor was wiped and it resent from scratch), not a repeat of an
|
|
314780
|
+
* already-attempted reset. A repair or final generation that already made
|
|
314781
|
+
* progress (`fromSequence > 1` under it) is exempt too -- CMMD acknowledged
|
|
314782
|
+
* it at least once, so a later refusal is a new, unrelated conflict and
|
|
314783
|
+
* earns its own fresh reset (forge#3620 finding 2); the bound must not key
|
|
314784
|
+
* on a generation id merely containing `:repair:`/`:final:`, or a thread
|
|
314785
|
+
* repaired once could never recover from a later, unrelated conflict.
|
|
314786
|
+
*/
|
|
314787
|
+
function refusedResetIsStuck(input) {
|
|
314788
|
+
if (input.refusedGenerationId === input.baseGenerationId) return false;
|
|
314789
|
+
if (input.refusedFromSequence !== 1) return false;
|
|
314790
|
+
return input.cursor === void 0 || input.cursor.generationId !== input.refusedGenerationId || input.cursor.acknowledgedSequence === 0;
|
|
314791
|
+
}
|
|
314792
|
+
/**
|
|
314793
|
+
* The generation id, starting sequence, and raw source events out of a
|
|
314794
|
+
* persisted thread batch, read straight off the JSON rather than through
|
|
314795
|
+
* `decodeThreadBatch` -- that schema only keeps `sequence`/`payloadHash` per
|
|
314796
|
+
* event, and a repair needs the full canonical fields to re-hash from
|
|
314797
|
+
* scratch. Extra fields (the old `sequence`/`payloadHash`) are harmless:
|
|
314798
|
+
* `buildRuntimeThreadBatch` overwrites both and its hasher reads only the
|
|
314799
|
+
* named canonical fields.
|
|
314800
|
+
*/
|
|
314801
|
+
function parseThreadBatchForRepair(payloadJson) {
|
|
314802
|
+
try {
|
|
314803
|
+
const parsed = JSON.parse(payloadJson);
|
|
314804
|
+
if (typeof parsed.generationId !== "string" || typeof parsed.fromSequence !== "number" || !Array.isArray(parsed.events)) return null;
|
|
314805
|
+
return {
|
|
314806
|
+
generationId: parsed.generationId,
|
|
314807
|
+
fromSequence: parsed.fromSequence,
|
|
314808
|
+
events: parsed.events
|
|
314809
|
+
};
|
|
314810
|
+
} catch {
|
|
314811
|
+
return null;
|
|
314812
|
+
}
|
|
314813
|
+
}
|
|
314667
314814
|
const STARTUP_RECOVERABLE_BLOCKED_CODES = [
|
|
314668
314815
|
...CLAIMABLE_BLOCKED_CODES,
|
|
314669
314816
|
"RUNTIME_NOT_READY",
|
|
@@ -314874,6 +315021,26 @@ const retryBlockedRuntimeReplicationOutbox = gen(function* () {
|
|
|
314874
315021
|
RETURNING stream_key AS "streamKey"
|
|
314875
315022
|
`).length;
|
|
314876
315023
|
}).pipe(orDie);
|
|
315024
|
+
/**
|
|
315025
|
+
* Thread streams parked under THREAD_STREAM_REMOTE_CONFLICT_REPROJECTION_PENDING_CODE,
|
|
315026
|
+
* for the manual `/api/runtime-replication/retry` endpoint. This code is deliberately
|
|
315027
|
+
* absent from MANUALLY_RECOVERABLE_BLOCKED_CODES: flipping the row back to `pending`
|
|
315028
|
+
* the way `retryBlockedRuntimeReplicationOutbox` does for other blocked codes would
|
|
315029
|
+
* requeue the same truncated payload `fail()` already refused, undoing the very repair
|
|
315030
|
+
* it just started. `http.ts`'s retry handler passes these to `RuntimeReplication`'s
|
|
315031
|
+
* `retryReprojectionPending`, which re-runs `enqueueThread` for each -- the same
|
|
315032
|
+
* corrective re-projection that already clears this code after every publish and after
|
|
315033
|
+
* every conflict (forge#3621 finding 2). No `runtimeId` filter, matching
|
|
315034
|
+
* `retryBlockedRuntimeReplicationOutbox` above: this outbox table belongs to one Forge
|
|
315035
|
+
* server.
|
|
315036
|
+
*/
|
|
315037
|
+
const readReprojectionPendingThreadStreamKeys = gen(function* () {
|
|
315038
|
+
return (yield* (yield* SqlClient)`
|
|
315039
|
+
SELECT stream_key AS "streamKey" FROM runtime_replication_outbox
|
|
315040
|
+
WHERE operation = 'thread-events' AND status = 'blocked'
|
|
315041
|
+
AND last_error_code = ${THREAD_STREAM_REMOTE_CONFLICT_REPROJECTION_PENDING_CODE}
|
|
315042
|
+
`).map((row) => row.streamKey);
|
|
315043
|
+
}).pipe(orDie);
|
|
314877
315044
|
const RuntimeReplicationOutboxLive = effect(RuntimeReplicationOutbox, gen(function* () {
|
|
314878
315045
|
const sql = yield* SqlClient;
|
|
314879
315046
|
const upsertPayload = (input) => {
|
|
@@ -315400,7 +315567,69 @@ const RuntimeReplicationOutboxLive = effect(RuntimeReplicationOutbox, gen(functi
|
|
|
315400
315567
|
discard: true
|
|
315401
315568
|
});
|
|
315402
315569
|
})).pipe(orDie);
|
|
315403
|
-
|
|
315570
|
+
/**
|
|
315571
|
+
* Recovers from a CMMD-reported thread stream conflict (see
|
|
315572
|
+
* THREAD_STREAM_REMOTE_CONFLICT_CODES). Returns `null` when this item is
|
|
315573
|
+
* not eligible (its payload does not decode, or `refusedResetIsStuck`
|
|
315574
|
+
* says the exact reset shape already failed once -- in which case the
|
|
315575
|
+
* caller falls back to blocking) and `false` when the row was superseded
|
|
315576
|
+
* before this could apply, mirroring `fail`'s own supersession signal.
|
|
315577
|
+
* Otherwise replaces the local cursor with a brand-new repair generation
|
|
315578
|
+
* from sequence 1, empty previous head -- the shape CMMD's reset rule
|
|
315579
|
+
* accepts unconditionally -- and parks the row blocked under
|
|
315580
|
+
* `THREAD_STREAM_REMOTE_CONFLICT_REPROJECTION_PENDING_CODE`, deferring the
|
|
315581
|
+
* actual rebuild to the caller's next full re-projection regardless of
|
|
315582
|
+
* `fromSequence` (see the big comment above
|
|
315583
|
+
* `THREAD_STREAM_REMOTE_CONFLICT_REPROJECTION_PENDING_CODE`): the refused
|
|
315584
|
+
* batch's own `events` are truncated at `batchSize` the same way whether
|
|
315585
|
+
* this was its first batch or its tenth, so rebuilding from them directly
|
|
315586
|
+
* can silently drop everything past the cap.
|
|
315587
|
+
*/
|
|
315588
|
+
const repairThreadStreamFromRemoteConflict = (item, failure) => gen(function* () {
|
|
315589
|
+
const parsedBatch = parseThreadBatchForRepair(item.payloadJson);
|
|
315590
|
+
if (!parsedBatch) return null;
|
|
315591
|
+
const baseGenerationId = runtimeThreadGenerationId(item.runtimeId, item.streamKey);
|
|
315592
|
+
const cursor = yield* readThreadCursor({
|
|
315593
|
+
runtimeId: item.runtimeId,
|
|
315594
|
+
streamKey: item.streamKey
|
|
315595
|
+
});
|
|
315596
|
+
if (refusedResetIsStuck({
|
|
315597
|
+
baseGenerationId,
|
|
315598
|
+
refusedGenerationId: parsedBatch.generationId,
|
|
315599
|
+
refusedFromSequence: parsedBatch.fromSequence,
|
|
315600
|
+
cursor
|
|
315601
|
+
})) return null;
|
|
315602
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
315603
|
+
const repairGenerationId = `${baseGenerationId}:repair:${Crypto.randomUUID()}`;
|
|
315604
|
+
const message = `Runtime replication conflict (${failure.code}) refused a thread-events batch; deferring to a full-history re-projection under a new repair generation.`;
|
|
315605
|
+
if (!(yield* sql.withTransaction(gen(function* () {
|
|
315606
|
+
if ((yield* sql`
|
|
315607
|
+
UPDATE runtime_replication_outbox SET
|
|
315608
|
+
status = 'blocked', next_attempt_at = '9999-12-31T23:59:59.999Z',
|
|
315609
|
+
last_error_code = ${"THREAD_STREAM_REMOTE_CONFLICT_REPROJECTION_PENDING"},
|
|
315610
|
+
last_error = ${message}, updated_at = ${now}
|
|
315611
|
+
WHERE runtime_id = ${item.runtimeId} AND stream_key = ${item.streamKey}
|
|
315612
|
+
AND payload_hash = ${item.payloadHash}
|
|
315613
|
+
RETURNING runtime_id AS "runtimeId"
|
|
315614
|
+
`).length !== 1) return false;
|
|
315615
|
+
yield* replaceThreadCursor({
|
|
315616
|
+
runtimeId: item.runtimeId,
|
|
315617
|
+
streamKey: item.streamKey,
|
|
315618
|
+
generationId: repairGenerationId,
|
|
315619
|
+
now
|
|
315620
|
+
});
|
|
315621
|
+
return true;
|
|
315622
|
+
})))) return false;
|
|
315623
|
+
yield* logWarning$1("Runtime replication deferred a thread-stream repair to a full re-projection after a remote conflict.", {
|
|
315624
|
+
runtimeId: item.runtimeId,
|
|
315625
|
+
streamKey: item.streamKey,
|
|
315626
|
+
errorCode: failure.code,
|
|
315627
|
+
previousGenerationId: parsedBatch.generationId,
|
|
315628
|
+
repairGenerationId
|
|
315629
|
+
});
|
|
315630
|
+
return true;
|
|
315631
|
+
}).pipe(orDie);
|
|
315632
|
+
const failGeneric = (item, failure) => {
|
|
315404
315633
|
const attempts = item.attemptCount + 1;
|
|
315405
315634
|
const exhausted = failure.kind === "retryable" && attempts >= 8 && failure.code !== "RUNTIME_NOT_REGISTERED";
|
|
315406
315635
|
const retryable = failure.kind === "retryable" && !exhausted;
|
|
@@ -315415,6 +315644,10 @@ const RuntimeReplicationOutboxLive = effect(RuntimeReplicationOutbox, gen(functi
|
|
|
315415
315644
|
RETURNING runtime_id AS "runtimeId"
|
|
315416
315645
|
`.pipe(map$3((rows) => rows.length === 1), orDie);
|
|
315417
315646
|
};
|
|
315647
|
+
const fail = (item, failure) => {
|
|
315648
|
+
if (item.operation !== "thread-events" || !THREAD_STREAM_REMOTE_CONFLICT_CODES.has(failure.code)) return failGeneric(item, failure);
|
|
315649
|
+
return repairThreadStreamFromRemoteConflict(item, failure).pipe(flatMap((repaired) => repaired === null ? failGeneric(item, failure) : succeed(repaired)));
|
|
315650
|
+
};
|
|
315418
315651
|
const retryBlocked = () => retryBlockedRuntimeReplicationOutbox.pipe(provideService(SqlClient, sql));
|
|
315419
315652
|
const recover = () => sql`
|
|
315420
315653
|
UPDATE runtime_replication_outbox SET status = 'pending',
|
|
@@ -315592,9 +315825,14 @@ const statusHandler = gen(function* () {
|
|
|
315592
315825
|
const retryHandler = gen(function* () {
|
|
315593
315826
|
const request = yield* HttpServerRequest;
|
|
315594
315827
|
yield* (yield* ServerAuth).authenticateHttpRequest(request);
|
|
315828
|
+
const replication = yield* serviceOption(RuntimeReplication);
|
|
315829
|
+
const requeued = yield* retryBlockedRuntimeReplicationOutbox;
|
|
315830
|
+
const reprojectionPendingStreamKeys = yield* readReprojectionPendingThreadStreamKeys;
|
|
315831
|
+
if (isSome(replication)) yield* replication.value.retryReprojectionPending(reprojectionPendingStreamKeys);
|
|
315832
|
+
const status = yield* readRuntimeReplicationOutboxStatus;
|
|
315595
315833
|
return jsonUnsafe({
|
|
315596
|
-
requeued:
|
|
315597
|
-
...responseFromStatus(
|
|
315834
|
+
requeued: requeued + (isSome(replication) ? reprojectionPendingStreamKeys.length : 0),
|
|
315835
|
+
...responseFromStatus(status)
|
|
315598
315836
|
});
|
|
315599
315837
|
}).pipe(catchTag("AuthError", respondToAuthError));
|
|
315600
315838
|
const runtimeReplicationStatusRouteLayer = mergeAll(add$1("GET", "/api/runtime-replication/status", statusHandler), add$1("POST", "/api/runtime-replication/retry", retryHandler));
|
|
@@ -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{Jn as a,Nn as o,Tn as s,Us as c,Vn as l,Wn as u,_l as d,ai as f,br as p,c as m,d as h,di as g,eu as _,fn as v,hl as y,kn as b,m as x,o as S,pi as C,pl as w,ps as T,qt as E,rs as D,s as O,t as k,tr as A,u as j,vl as M,zn 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{Jn as a,Nn as o,Tn as s,Us as c,Vn as l,Wn as u,_l as d,ai as f,br as p,c as m,d as h,di as g,eu as _,fn as v,hl as y,kn as b,m as x,o as S,pi as C,pl as w,ps as T,qt as E,rs as D,s as O,t as k,tr as A,u as j,vl as M,zn as N}from"./WorkerPoolContext-DR8-tB5e.js";import{sn as P}from"./CompositeItem-DNVaubQt.js";import{a as F,c as I,i as L,l as R,n as z,o as B,r as V,s as H,t as U,u as W}from"./Virtualizer-DIbjvGwY.js";import{On as G,at as K,ot as q}from"./src-BAHvoNAY.js";import"./cmmdAuthRedirect-BYBGztDm.js";import{a as J,c as ee,d as te,h as ne,i as re,l as ie,m as ae,n as oe,o as Y,p as se,r as ce,s as le,t as ue,u as de}from"./DiffPanel.logic-B5u-aRQa.js";import{n as fe,t as X}from"./toggle-group-Cqh7gA8I.js";var Z=e(i(),1),pe=typeof window>`u`?Z.useEffect:Z.useLayoutEffect;function me({fileDiff:e,options:t,editorOptions:n,lineAnnotations:r,selectedLines:i,prerenderedHTML:a,metrics:o,hasGutterRenderUtility:s,hasCustomHeader:c,disableWorkerPool:l,edit:u}){let d=z(),f=i!==void 0,p=(0,Z.useContext)(k),h=O(),g=(0,Z.useRef)(null),_=m(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 te(he({controlledSelection:f,hasCustomHeader:c,hasGutterRenderUtility:s,options:t}),l?void 0:p,!0):g.current=new de(he({controlledSelection:f,hasCustomHeader:c,hasGutterRenderUtility:s,options:t}),d,o,l?void 0:p,!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 pe(()=>{let{current:n}=g;if(n==null)return;let a=he({controlledSelection:f,hasCustomHeader:c,hasGutterRenderUtility:s,options:t}),o=a!==void 0&&!E(n.options,a);n.setOptions(a),n.render({forceRender:o,fileDiff:e,lineAnnotations:r}),i!==void 0&&n.setSelectedLines(i)}),pe(()=>{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,Z.useCallback)(()=>g.current?.getHoveredLine(),[])}}function he({options:e,controlledSelection:t,hasCustomHeader:n,hasGutterRenderUtility:r}){return t||r||n?{...e,controlledSelection:t,renderCustomHeader:n?S:e?.renderCustomHeader,renderGutterUtility:r?S: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:h=!1,edit:g=!1}){let{ref:_,getHoveredLine:y}=me({fileDiff:e,options:t,editorOptions:n,metrics:r,lineAnnotations:i,selectedLines:a,prerenderedHTML:c,hasGutterRenderUtility:m!=null,hasCustomHeader:u!=null,disableWorkerPool:h,edit:g});return(0,Q.jsx)(v,{ref:_,className:o,style:s,children:V(ie({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?G(K)({threadId:e.threadId,toTurnCount:e.toTurnCount}).pipe(n(e=>({kind:`fullThreadDiff`,input:e}))):G(q)({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 d({queryKey:c.checkpointDiff(e),queryFn:async({signal:n})=>{if(!e.environmentId||!e.threadId||t._tag===`None`)throw Error(`Checkpoint diff is unavailable.`);let r=f(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,Z.useRef)(null),[n,r]=(0,Z.useState)(!1),[i,a]=(0,Z.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=le({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&&ee({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,Z.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,Z.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}=o(),a=A(),[c,l]=(0,Z.useState)(`stacked`),[u,d]=(0,Z.useState)(a.diffWordWrap),f=(0,Z.useRef)(null),m=(0,Z.useRef)(!1),g=Te(),{activeCwd:_,activeThread:v,bodyState:x,diffOpen:S,inferredCheckpointTurnCountByTurnId:C,orderedTurnDiffSummaries:T,renderableFiles:E,renderablePatch:D,selectedFilePath:O,selectedTurn:k,selectedTurnId:j}=Le(i),M,P;t[0]!==S||t[1]!==a.diffWordWrap?(M=()=>{S&&!m.current&&d(a.diffWordWrap),m.current=S},P=[S,a.diffWordWrap],t[0]=S,t[1]=a.diffWordWrap,t[2]=M,t[3]=P):(M=t[2],P=t[3]),(0,Z.useEffect)(M,P);let F;t[4]===O?F=t[5]:(F=()=>{!O||!f.current||Array.from(f.current.querySelectorAll(`[data-diff-file-path]`)).find(e=>e.dataset.diffFilePath===O)?.scrollIntoView({block:`nearest`})},t[4]=O,t[5]=F);let I;t[6]!==E||t[7]!==O?(I=[O,E],t[6]=E,t[7]=O,t[8]=I):I=t[8],(0,Z.useEffect)(F,I);let L;t[9]===_?L=t[10]:(L=e=>{let t=N();if(!t)return;let n=_?s(e,_):e;b(t,n).catch(ke)},t[9]=_,t[10]=L);let R=L,z;t[11]===v?z=t[12]:(z=e=>{v&&p.getState().openDiff(y(w(v.environmentId,v.id)),e)},t[11]=v,t[12]=z);let B=z,V;t[13]===v?V=t[14]:(V=()=>{v&&p.getState().openDiff(y(w(v.environmentId,v.id)))},t[13]=v,t[14]=V);let H=V,U;t[15]===g.remeasure?U=t[16]:(U=()=>{let e=window.requestAnimationFrame(g.remeasure);return()=>window.cancelAnimationFrame(e)},t[15]=g.remeasure,t[16]=U);let W;t[17]!==T||t[18]!==j||t[19]!==g.remeasure?(W=[T,j,g.remeasure],t[17]=T,t[18]=j,t[19]=g.remeasure,t[20]=W):W=t[20],(0,Z.useEffect)(U,W),Ee(g.ref,k?.turnId??j);let G;t[21]!==c||t[22]!==u||t[23]!==C||t[24]!==T||t[25]!==B||t[26]!==H||t[27]!==k||t[28]!==j||t[29]!==a||t[30]!==g?(G=(0,Q.jsx)(Ae,{diffRenderMode:c,diffWordWrap:u,inferredCheckpointTurnCountByTurnId:C,orderedTurnDiffSummaries:T,selectTurn:B,selectWholeConversation:H,selectedTurn:k,selectedTurnId:j,setDiffRenderMode:l,setDiffWordWrap:d,settings:a,turnStrip:g}),t[21]=c,t[22]=u,t[23]=C,t[24]=T,t[25]=B,t[26]=H,t[27]=k,t[28]=j,t[29]=a,t[30]=g,t[31]=G):G=t[31];let K=G,q;t[32]!==x||t[33]!==c||t[34]!==u||t[35]!==R||t[36]!==E||t[37]!==D||t[38]!==i?(q=(0,Q.jsx)(je,{bodyState:x,diffRenderMode:c,diffWordWrap:u,openDiffFileInEditor:R,patchViewportRef:f,renderableFiles:E,renderablePatch:D,resolvedTheme:i}),t[32]=x,t[33]=c,t[34]=u,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)(h,{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)(X,{"aria-label":`Stacked diff view`,value:`stacked`,children:(0,Q.jsx)(ae,{className:`size-3`})}),t[40]=A):A=t[40];let j;t[41]===Symbol.for(`react.memo_cache_sentinel`)?(j=(0,Q.jsx)(X,{"aria-label":`Split diff view`,value:`split`,children:(0,Q.jsx)(ne,{className:`size-3`})}),t[41]=j):j=t[41];let M;t[42]!==O||t[43]!==k?(M=(0,Q.jsxs)(fe,{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`,F=r?`Disable line wrapping`:`Enable line wrapping`,I;t[45]===d?I=t[46]:(I=e=>{d(!!e)},t[45]=d,t[46]=I);let L;t[47]===Symbol.for(`react.memo_cache_sentinel`)?(L=(0,Q.jsx)(se,{className:`size-3`}),t[47]=L):L=t[47];let R;t[48]!==r||t[49]!==N||t[50]!==F||t[51]!==I?(R=(0,Q.jsx)(X,{"aria-label":N,title:F,variant:`outline`,size:`xs`,pressed:r,onPressedChange:I,children:L}),t[48]=r,t[49]=N,t[50]=F,t[51]=I,t[52]=R):R=t[52];let z;t[53]!==M||t[54]!==R?(z=(0,Q.jsxs)(`div`,{className:`flex shrink-0 items-center gap-1 [-webkit-app-region:no-drag]`,children:[M,R]}),t[53]=M,t[54]=R,t[55]=z):z=t[55];let B;return t[56]!==D||t[57]!==z?(B=(0,Q.jsxs)(Q.Fragment,{children:[D,z]}),t[56]=D,t[57]=z,t[58]=B):B=t[58],B}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)(U,{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=`${ue(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:x(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=_(t),r;e[1]===Symbol.for(`react.memo_cache_sentinel`)?(r={strict:!1,select:Fe},e[1]=r):r=e[1];let i=W(r),o=i.rightPanel===`diff`,s=n?.threadId??null,c,u;e[2]===n?u=e[3]:(u=a(n),e[2]=n,e[3]=u),c=u;let d=T(c),f=He(d),p=d?.worktreePath,m=f?.cwd,h;e[4]!==p||e[5]!==m?(h=B({threadWorktreePath:p,projectCwd:m}),e[4]=p,e[5]=m,e[6]=h):h=e[6];let g=h,v=d?.environmentId??null,y=g??null,b;e[7]!==v||e[8]!==y?(b={environmentId:v,cwd:y},e[7]=v,e[8]=y,e[9]=b):b=e[9];let x=l(b),S;e[10]===x.data?S=e[11]:(S=H(x.data),e[10]=x.data,e[11]=S);let C=S,w;return e[12]!==g||e[13]!==d||e[14]!==s||e[15]!==o||e[16]!==i||e[17]!==C?(w={activeThread:d,activeThreadId:s,activeCwd:g,isGitRepo:C,diffSearch:i,diffOpen:o},e[12]=g,e[13]=d,e[14]=s,e[15]=o,e[16]=i,e[17]=C,e[18]=w):w=e[18],w}function Fe(e){return F(e)}function Ie(e){return g(e)}function Le(e){let{activeThread:t,activeThreadId:n,activeCwd:r,isGitRepo:i,diffSearch:a,diffOpen:o}=Pe(),{turnDiffSummaries:s,inferredCheckpointTurnCountByTurnId:c}=L(t),l=a.diffTurnId??null,u=l===null?null:a.diffFilePath??null,{activeCheckpointRange:d,conversationCacheScope:f,orderedTurnDiffSummaries:p,selectedTurn:m}=(0,Z.useMemo)(()=>J({summaries:s,inferredCheckpointTurnCountByTurnId:c,selectedTurnId:l}),[c,l,s]),h=M(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,Z.useMemo)(()=>re(m),[m]),x=(0,Z.useMemo)(()=>oe(v,`diff-panel:${e}`),[e,v]),S=(0,Z.useMemo)(()=>Ue(x),[x]);return{activeCwd:r,activeThread:t,bodyState:ce({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)(j,{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)(I,{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?R:C,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`,d;t[3]===l?d=t[4]:(d=P(`rounded-md border px-2 py-1 text-left transition-colors`,l),t[3]=l,t[4]=d);let f=i??`?`,p;t[5]===f?p=t[6]:(p=(0,Q.jsxs)(`span`,{className:`text-[10px] leading-tight font-medium`,children:[`Turn `,f]}),t[5]=f,t[6]=p);let m;t[7]!==n.completedAt||t[8]!==a?(m=u(n.completedAt,a),t[7]=n.completedAt,t[8]=a,t[9]=m):m=t[9];let h;t[10]===m?h=t[11]:(h=(0,Q.jsx)(`span`,{className:`text-[9px] leading-tight opacity-70`,children:m}),t[10]=m,t[11]=h);let g;t[12]!==p||t[13]!==h?(g=(0,Q.jsxs)(`div`,{className:`flex items-center gap-1`,children:[p,h]}),t[12]=p,t[13]=h,t[14]=g):g=t[14];let _;t[15]!==d||t[16]!==g?(_=(0,Q.jsx)(`div`,{className:d,children:g}),t[15]=d,t[16]=g,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?D(e,{environmentId:n,projectId:r}):void 0,t[0]=n,t[1]=r,t[2]=i):i=t[2],T(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-DUNnxsQq.js.map
|