@cmmd-center/forge 0.13.73 → 0.13.74
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 +290 -27
- package/dist/bin.mjs +290 -27
- package/dist/client/assets/{DiffPanel-BEf3EXPK.js → DiffPanel-Bn53zJRq.js} +2 -2
- package/dist/client/assets/{DiffPanel.logic-Bw1O_6UU.js → DiffPanel.logic-DF8NdwcA.js} +2 -2
- package/dist/client/assets/{DiffPanelShell-BoAQcVta.js → DiffPanelShell-CTLS82pj.js} +3 -3
- package/dist/client/assets/{DiffWorkerPoolProvider-C5Ln-c7Y.js → DiffWorkerPoolProvider-kxyfllf9.js} +2 -2
- package/dist/client/assets/{PullRequestCodePanel-Bx3me2lj.js → PullRequestCodePanel-D0imQaMo.js} +2 -2
- package/dist/client/assets/{Virtualizer-B4jYnrUE.js → Virtualizer-DsHt9iaj.js} +2 -2
- package/dist/client/assets/{index-C2Y_gZoG.js → index-Bf50oKP5.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
|
@@ -65979,7 +65979,7 @@ function normalizeNumberish(value) {
|
|
|
65979
65979
|
}
|
|
65980
65980
|
//#endregion
|
|
65981
65981
|
//#region package.json
|
|
65982
|
-
var version$1 = "0.13.
|
|
65982
|
+
var version$1 = "0.13.74";
|
|
65983
65983
|
//#endregion
|
|
65984
65984
|
//#region src/sentry.ts
|
|
65985
65985
|
const SERVER_APP_NAME = "forge-server";
|
|
@@ -241209,17 +241209,30 @@ function isPromiseLike(value) {
|
|
|
241209
241209
|
* outlives the delete re-acquires the hold on its next tick; that was
|
|
241210
241210
|
* previously measured leaking 37 renewals over 18 minutes, pinning a sprite
|
|
241211
241211
|
* running — and billing — 33 minutes after its work had ended.
|
|
241212
|
-
* 2.
|
|
241213
|
-
*
|
|
241214
|
-
* hold for another full expiry window
|
|
241215
|
-
* awaits its heartbeat for the same reason.
|
|
241212
|
+
* 2. Cancellation must be CONFIRMED before the final DELETE is trusted. A PUT
|
|
241213
|
+
* already on the wire has to settle first, or the DELETE can land mid-PUT
|
|
241214
|
+
* and the PUT recreate the hold for another full expiry window; fly.io's
|
|
241215
|
+
* reference worker cancels and awaits its heartbeat for the same reason.
|
|
241216
|
+
* The join is bounded on the shutdown path
|
|
241217
|
+
* (SPRITE_TASK_HOLD_RELEASE_JOIN_TIMEOUT_MS) and the bound decides the
|
|
241218
|
+
* shape: every PUT settled within it, with no earlier PUT rejection left
|
|
241219
|
+
* unanswered by a clean refresh, confirms cancellation and one DELETE
|
|
241220
|
+
* finishes the hold; the bound firing first means cancellation cannot be
|
|
241221
|
+
* confirmed, so the release sweeps, DELETE, verify with a bounded GET, and
|
|
241222
|
+
* re-DELETE while the server still shows the hold, capped at
|
|
241223
|
+
* SPRITE_TASK_HOLD_SWEEP_ROUNDS rounds. Every hold gets at least one
|
|
241224
|
+
* DELETE, a resurrected hold is cleaned and swept again, and only a hold
|
|
241225
|
+
* positively present after the cap is reported unreleased at warn instead
|
|
241226
|
+
* of hanging SIGTERM open.
|
|
241216
241227
|
* 3. `release` can arrive while `acquire` is still awaiting its own PUT —
|
|
241217
241228
|
* `releaseAll` runs from runtime drain and the shutdown finalizer,
|
|
241218
241229
|
* concurrently with the provider event stream. The hold is registered before
|
|
241219
|
-
* that await (so a duplicate turn.started cannot double-acquire),
|
|
241220
|
-
*
|
|
241221
|
-
*
|
|
241222
|
-
*
|
|
241230
|
+
* that await (so a duplicate turn.started cannot double-acquire), and while
|
|
241231
|
+
* a release runs the hold stays mapped (joining, then deleting), so the
|
|
241232
|
+
* shutdown finalizer's bounded `releaseAll` can take a parked hold over;
|
|
241233
|
+
* `acquire` must then NOT install a refresher on the old hold, and a fresh
|
|
241234
|
+
* acquire replaces a released hold in the map. One refresher attached to a
|
|
241235
|
+
* hold no release path can reach would re-PUT every 60 s for the life of
|
|
241223
241236
|
* the process — an unbounded pin.
|
|
241224
241237
|
*
|
|
241225
241238
|
* All three are pinned by tests.
|
|
@@ -241243,6 +241256,30 @@ const SPRITE_TASK_HOLD_REFRESH_MS = 6e4;
|
|
|
241243
241256
|
*/
|
|
241244
241257
|
const SPRITE_TASK_HOLD_REQUEST_TIMEOUT_MS = 1e4;
|
|
241245
241258
|
/**
|
|
241259
|
+
* Shutdown bounds for the release the server finalizer issues. Both are one
|
|
241260
|
+
* request deadline. With a transport that honors its abort, every PUT still on
|
|
241261
|
+
* the wire settles within its own 10 s deadline, so a join sized at one
|
|
241262
|
+
* deadline always completes, cancellation is confirmed, and a single DELETE is
|
|
241263
|
+
* issued; the DELETE answers within its own deadline too.
|
|
241264
|
+
*
|
|
241265
|
+
* When the join bound fires, cancellation is unconfirmed and the release
|
|
241266
|
+
* sweeps: DELETE, verify with a bounded GET, and re-DELETE if the hold
|
|
241267
|
+
* survived, capped at SPRITE_TASK_HOLD_SWEEP_ROUNDS rounds. Worst case a
|
|
241268
|
+
* shutdown release costs join + 2 x (delete + verify), about 50 s, after
|
|
241269
|
+
* which the process exits and any hold left behind expires on its own within
|
|
241270
|
+
* 5 minutes. Drain passes no bounds. It keeps the full join, and its tick is
|
|
241271
|
+
* already capped by the heartbeat timeout.
|
|
241272
|
+
*/
|
|
241273
|
+
const SPRITE_TASK_HOLD_RELEASE_JOIN_TIMEOUT_MS = SPRITE_TASK_HOLD_REQUEST_TIMEOUT_MS;
|
|
241274
|
+
const SPRITE_TASK_HOLD_RELEASE_DELETE_TIMEOUT_MS = SPRITE_TASK_HOLD_REQUEST_TIMEOUT_MS;
|
|
241275
|
+
/**
|
|
241276
|
+
* How many delete-plus-verify rounds an unconfirmed release sweeps before it
|
|
241277
|
+
* gives up and reports the hold unreleased. Two is one retry past the first
|
|
241278
|
+
* delete: enough to clean a timed-out PUT that commits late, cheap enough
|
|
241279
|
+
* that a truly wedged socket cannot hold SIGTERM open much past a minute.
|
|
241280
|
+
*/
|
|
241281
|
+
const SPRITE_TASK_HOLD_SWEEP_ROUNDS = 2;
|
|
241282
|
+
/**
|
|
241246
241283
|
* Resolve the hold configuration from the process environment.
|
|
241247
241284
|
*
|
|
241248
241285
|
* Returns null on every runtime that is not a project sprite — desktop-local and
|
|
@@ -241264,6 +241301,20 @@ function resolveSpriteTaskHoldConfig(env = process.env) {
|
|
|
241264
241301
|
function spriteTaskHoldName(namePrefix, turnId) {
|
|
241265
241302
|
return `${namePrefix}${turnId}`;
|
|
241266
241303
|
}
|
|
241304
|
+
const noTimer = () => {};
|
|
241305
|
+
/**
|
|
241306
|
+
* Resolve with `promise`, but stop waiting after `timeoutMs`. Rejections pass
|
|
241307
|
+
* through untouched, and the caller decides what a timeout means. The
|
|
241308
|
+
* underlying operation keeps running either way.
|
|
241309
|
+
*/
|
|
241310
|
+
function boundedAwait(promise, timeoutMs) {
|
|
241311
|
+
if (timeoutMs === void 0) return promise;
|
|
241312
|
+
let clearTimer = noTimer;
|
|
241313
|
+
return Promise.race([promise, new Promise((resolve) => {
|
|
241314
|
+
const timer = setTimeout(resolve, timeoutMs);
|
|
241315
|
+
clearTimer = () => clearTimeout(timer);
|
|
241316
|
+
})]).finally(() => clearTimer());
|
|
241317
|
+
}
|
|
241267
241318
|
const DEFAULT_TIMER = {
|
|
241268
241319
|
setInterval: (handler, ms) => setInterval(handler, ms),
|
|
241269
241320
|
clearInterval: (handle) => {
|
|
@@ -241299,7 +241350,8 @@ var SpriteTaskHoldManager = class {
|
|
|
241299
241350
|
* whose turn may never start. When the budget is spent the hold releases itself.
|
|
241300
241351
|
*/
|
|
241301
241352
|
async acquire(turnId, threadId = null, options = {}) {
|
|
241302
|
-
|
|
241353
|
+
const existing = this.#holds.get(turnId);
|
|
241354
|
+
if (existing !== void 0 && !existing.released) return;
|
|
241303
241355
|
let refreshesLeft = options.maxRefreshes ?? Number.POSITIVE_INFINITY;
|
|
241304
241356
|
const name = spriteTaskHoldName(this.#config.namePrefix, turnId);
|
|
241305
241357
|
const hold = {
|
|
@@ -241307,15 +241359,21 @@ var SpriteTaskHoldManager = class {
|
|
|
241307
241359
|
threadId,
|
|
241308
241360
|
refresher: null,
|
|
241309
241361
|
inFlight: /* @__PURE__ */ new Set(),
|
|
241310
|
-
released: false
|
|
241362
|
+
released: false,
|
|
241363
|
+
phase: "idle",
|
|
241364
|
+
releaseAttempt: null,
|
|
241365
|
+
deletion: null,
|
|
241366
|
+
uncertainPut: false
|
|
241311
241367
|
};
|
|
241312
241368
|
this.#holds.set(turnId, hold);
|
|
241313
241369
|
const put = this.#transport.put(name, 300);
|
|
241314
|
-
const tracked = put.then(() =>
|
|
241370
|
+
const tracked = put.then(() => "succeeded", () => "failed");
|
|
241315
241371
|
hold.inFlight.add(tracked);
|
|
241316
241372
|
try {
|
|
241317
241373
|
await put;
|
|
241374
|
+
hold.uncertainPut = false;
|
|
241318
241375
|
} catch (cause) {
|
|
241376
|
+
hold.uncertainPut = true;
|
|
241319
241377
|
hold.inFlight.delete(tracked);
|
|
241320
241378
|
this.#onError(`failed to acquire sprite task hold for turn ${turnId}`, cause);
|
|
241321
241379
|
if (hold.released || this.#holds.get(turnId) !== hold) return;
|
|
@@ -241329,28 +241387,189 @@ var SpriteTaskHoldManager = class {
|
|
|
241329
241387
|
return;
|
|
241330
241388
|
}
|
|
241331
241389
|
refreshesLeft -= 1;
|
|
241332
|
-
const refresh = this.#transport.put(name, 300).
|
|
241390
|
+
const refresh = this.#transport.put(name, 300).then(() => {
|
|
241391
|
+
hold.uncertainPut = false;
|
|
241392
|
+
return "succeeded";
|
|
241393
|
+
}, (cause) => {
|
|
241394
|
+
hold.uncertainPut = true;
|
|
241395
|
+
this.#onError(`failed to refresh sprite task hold for turn ${turnId}`, cause);
|
|
241396
|
+
return "failed";
|
|
241397
|
+
});
|
|
241333
241398
|
hold.inFlight.add(refresh);
|
|
241334
241399
|
refresh.finally(() => hold.inFlight.delete(refresh));
|
|
241335
241400
|
}, SPRITE_TASK_HOLD_REFRESH_MS);
|
|
241336
241401
|
}
|
|
241337
|
-
|
|
241402
|
+
/**
|
|
241403
|
+
* Release one hold.
|
|
241404
|
+
*
|
|
241405
|
+
* Cancellation must be confirmed before a single DELETE is trusted: every
|
|
241406
|
+
* PUT on the wire has to settle successfully, or the DELETE can land mid-PUT
|
|
241407
|
+
* and the PUT re-create the hold behind it. With a join bound (shutdown),
|
|
241408
|
+
* PUTs that do not settle within the bound, or settle as rejections, make
|
|
241409
|
+
* the attempt sweep instead: DELETE, verify, re-DELETE while the server
|
|
241410
|
+
* still shows the hold, capped at two rounds. The fate outlives the PUT's
|
|
241411
|
+
* settlement: a PUT that rejected before the release began, with no
|
|
241412
|
+
* successful refresh after it, sweeps too. Without a bound (drain,
|
|
241413
|
+
* per-turn release) the join is patient and never gives up, though a PUT
|
|
241414
|
+
* that rejects still routes the release through the sweep.
|
|
241415
|
+
*
|
|
241416
|
+
* While an attempt runs, the hold stays in the map in its joining or
|
|
241417
|
+
* deleting phase, so shutdown can see it. A bounded (shutdown) caller takes
|
|
241418
|
+
* a parked hold over with its own bounded pass; a hold already in its
|
|
241419
|
+
* deleting phase is skipped, because its single deletion is already in
|
|
241420
|
+
* flight. Unbounded duplicate callers join the running attempt instead.
|
|
241421
|
+
*/
|
|
241422
|
+
async release(turnId, options = {}) {
|
|
241338
241423
|
const hold = this.#holds.get(turnId);
|
|
241339
|
-
if (!hold) return;
|
|
241424
|
+
if (!hold) return "released";
|
|
241425
|
+
if (hold.phase === "deleting") return "released";
|
|
241426
|
+
const bounded = options.joinTimeoutMs !== void 0;
|
|
241427
|
+
if (hold.releaseAttempt !== null) {
|
|
241428
|
+
if (!bounded) return hold.releaseAttempt;
|
|
241429
|
+
return this.#concludeRelease(hold, turnId, options);
|
|
241430
|
+
}
|
|
241340
241431
|
hold.released = true;
|
|
241341
241432
|
if (hold.refresher !== null) {
|
|
241342
241433
|
this.#timer.clearInterval(hold.refresher);
|
|
241343
241434
|
hold.refresher = null;
|
|
241344
241435
|
}
|
|
241345
|
-
|
|
241346
|
-
|
|
241436
|
+
hold.phase = "joining";
|
|
241437
|
+
const attempt = (async () => {
|
|
241438
|
+
const outcome = await this.#concludeRelease(hold, turnId, options);
|
|
241439
|
+
if (outcome === "unreleased") {
|
|
241440
|
+
hold.phase = "idle";
|
|
241441
|
+
this.#removeIfCurrent(turnId, hold);
|
|
241442
|
+
}
|
|
241443
|
+
return outcome;
|
|
241444
|
+
})();
|
|
241445
|
+
hold.releaseAttempt = attempt;
|
|
241347
241446
|
try {
|
|
241348
|
-
await
|
|
241447
|
+
return await attempt;
|
|
241448
|
+
} finally {
|
|
241449
|
+
if (hold.releaseAttempt === attempt) hold.releaseAttempt = null;
|
|
241450
|
+
}
|
|
241451
|
+
}
|
|
241452
|
+
/**
|
|
241453
|
+
* Drive one release attempt to its outcome. On the confirmed path (every
|
|
241454
|
+
* PUT on the wire settled within the join bound) a single DELETE finishes
|
|
241455
|
+
* the hold. On the unconfirmed path cancellation is unknown, so the hold
|
|
241456
|
+
* is swept: DELETE, verify, and re-DELETE while the server still shows it,
|
|
241457
|
+
* capped. Shared by the first attempt and a shutdown takeover: whichever
|
|
241458
|
+
* caller first reaches its verdict installs the hold's single deletion
|
|
241459
|
+
* promise and the rest join it, so the DELETE or sweep is issued once and
|
|
241460
|
+
* concurrent callers report the same outcome.
|
|
241461
|
+
*/
|
|
241462
|
+
async #concludeRelease(hold, turnId, options) {
|
|
241463
|
+
const verdict = await this.#confirmCancellation(hold, options.joinTimeoutMs);
|
|
241464
|
+
if (hold.deletion !== null) return hold.deletion;
|
|
241465
|
+
hold.phase = "deleting";
|
|
241466
|
+
const deletion = verdict === "confirmed" ? this.#deleteConfirmed(hold, turnId, options) : this.#sweepUnconfirmed(hold, turnId, options);
|
|
241467
|
+
hold.deletion = deletion;
|
|
241468
|
+
return deletion;
|
|
241469
|
+
}
|
|
241470
|
+
/**
|
|
241471
|
+
* The confirmed-path deletion: every PUT on the wire settled cleanly, so
|
|
241472
|
+
* one DELETE finishes the hold. A rejected DELETE is logged, never thrown;
|
|
241473
|
+
* the hold still leaves the map and expires on its own server-side.
|
|
241474
|
+
*/
|
|
241475
|
+
async #deleteConfirmed(hold, turnId, options) {
|
|
241476
|
+
await this.#issueDelete(hold, options.deleteTimeoutMs, turnId);
|
|
241477
|
+
this.#removeIfCurrent(turnId, hold);
|
|
241478
|
+
return "released";
|
|
241479
|
+
}
|
|
241480
|
+
/**
|
|
241481
|
+
* Best-effort cleanup for a hold whose cancellation is uncertain: the join
|
|
241482
|
+
* bound fired with a PUT unsettled, or a PUT rejected after possibly being
|
|
241483
|
+
* processed server-side. The hold is owed its delete either way. Each round
|
|
241484
|
+
* is a bounded DELETE followed by a bounded GET; a verify that still shows
|
|
241485
|
+
* the hold (the timed-out PUT committed after our delete, or the delete
|
|
241486
|
+
* never landed) triggers the next round. Verification is best-effort too:
|
|
241487
|
+
* "absent" proves cleanup, "unknown" proves nothing and cannot by itself
|
|
241488
|
+
* report the hold unreleased, so after the cap an unverifiable hold is
|
|
241489
|
+
* reported released-with-its-delete while a positively present one is
|
|
241490
|
+
* reported unreleased at warn. Either way the hold expires on its own
|
|
241491
|
+
* within 300 s. Only `#concludeRelease` starts this, after it has already
|
|
241492
|
+
* moved the hold into its deleting phase.
|
|
241493
|
+
*/
|
|
241494
|
+
async #sweepUnconfirmed(hold, turnId, options) {
|
|
241495
|
+
for (let round = 1; round <= SPRITE_TASK_HOLD_SWEEP_ROUNDS; round += 1) {
|
|
241496
|
+
await this.#issueDelete(hold, options.deleteTimeoutMs, turnId);
|
|
241497
|
+
const state = await this.#verifyHold(hold, options.deleteTimeoutMs, turnId);
|
|
241498
|
+
const last = round === SPRITE_TASK_HOLD_SWEEP_ROUNDS;
|
|
241499
|
+
if (state === "absent") {
|
|
241500
|
+
this.#removeIfCurrent(turnId, hold);
|
|
241501
|
+
return "released";
|
|
241502
|
+
}
|
|
241503
|
+
if (state === "present") {
|
|
241504
|
+
this.#onError(`sprite task hold for turn ${turnId} was still present after delete (sweep ${round}/${SPRITE_TASK_HOLD_SWEEP_ROUNDS})`, "a refresh PUT that ignored its abort appears to have committed after the delete");
|
|
241505
|
+
if (last) {
|
|
241506
|
+
this.#onError(`sprite task hold for turn ${turnId} was left unreleased: still present after ${SPRITE_TASK_HOLD_SWEEP_ROUNDS} delete+verify sweeps, expires on its own`, "hold survived the full shutdown sweep");
|
|
241507
|
+
this.#removeIfCurrent(turnId, hold);
|
|
241508
|
+
return "unreleased";
|
|
241509
|
+
}
|
|
241510
|
+
continue;
|
|
241511
|
+
}
|
|
241512
|
+
this.#onError(`sprite task hold for turn ${turnId} could not be verified after delete (sweep ${round}/${SPRITE_TASK_HOLD_SWEEP_ROUNDS})`, "hold state unverifiable");
|
|
241513
|
+
if (last) {
|
|
241514
|
+
this.#removeIfCurrent(turnId, hold);
|
|
241515
|
+
return "released";
|
|
241516
|
+
}
|
|
241517
|
+
}
|
|
241518
|
+
return "released";
|
|
241519
|
+
}
|
|
241520
|
+
/**
|
|
241521
|
+
* Ask the transport whether the hold still exists. No transport `get`, a
|
|
241522
|
+
* rejection, or a bound that fires all come back "unknown": the sweep has
|
|
241523
|
+
* no evidence, and never invents it.
|
|
241524
|
+
*/
|
|
241525
|
+
async #verifyHold(hold, timeoutMs, turnId) {
|
|
241526
|
+
const get = this.#transport.get;
|
|
241527
|
+
if (!get) return "unknown";
|
|
241528
|
+
try {
|
|
241529
|
+
return await boundedAwait(get(hold.name), timeoutMs);
|
|
241530
|
+
} catch (cause) {
|
|
241531
|
+
this.#onError(`failed to verify sprite task hold for turn ${turnId}`, cause);
|
|
241532
|
+
return "unknown";
|
|
241533
|
+
}
|
|
241534
|
+
}
|
|
241535
|
+
/**
|
|
241536
|
+
* Wait for every PUT on the wire to settle and report whether cancellation
|
|
241537
|
+
* is confirmed. Only a clean success confirms: a PUT that REJECTED is
|
|
241538
|
+
* uncertain, because the server may have processed the request before the
|
|
241539
|
+
* failure surfaced, and a DELETE trusted after it could be raced by the
|
|
241540
|
+
* hold it re-created. `inFlight` forgets each PUT once it settles, so a
|
|
241541
|
+
* rejection that settled before the release even started is read from
|
|
241542
|
+
* `uncertainPut` instead, and stays uncertain until some later PUT
|
|
241543
|
+
* succeeds. With no bound the wait is patient; unbounded callers
|
|
241544
|
+
* (drain, per-turn release) trade shutdown speed for the certainty.
|
|
241545
|
+
*/
|
|
241546
|
+
async #confirmCancellation(hold, timeoutMs) {
|
|
241547
|
+
if (hold.inFlight.size === 0) return hold.uncertainPut ? "uncertain" : "confirmed";
|
|
241548
|
+
const settled = Promise.all(hold.inFlight).then((fates) => fates.every((fate) => fate === "succeeded") && !hold.uncertainPut ? "confirmed" : "uncertain");
|
|
241549
|
+
if (timeoutMs === void 0) return settled;
|
|
241550
|
+
let clearTimer = noTimer;
|
|
241551
|
+
return Promise.race([settled, new Promise((resolve) => {
|
|
241552
|
+
const timer = setTimeout(() => resolve("uncertain"), timeoutMs);
|
|
241553
|
+
clearTimer = () => clearTimeout(timer);
|
|
241554
|
+
})]).finally(() => clearTimer());
|
|
241555
|
+
}
|
|
241556
|
+
/** Issue the DELETE, reporting (never throwing) a failure. */
|
|
241557
|
+
async #issueDelete(hold, deleteTimeoutMs, turnId) {
|
|
241558
|
+
try {
|
|
241559
|
+
await boundedAwait(this.#transport.delete(hold.name), deleteTimeoutMs);
|
|
241349
241560
|
} catch (cause) {
|
|
241350
241561
|
this.#onError(`failed to release sprite task hold for turn ${turnId}`, cause);
|
|
241351
241562
|
}
|
|
241352
241563
|
}
|
|
241353
241564
|
/**
|
|
241565
|
+
* Drop the map entry only if this attempt's hold still owns the id: a newer
|
|
241566
|
+
* acquire may have replaced it while the release was awaiting, and deleting
|
|
241567
|
+
* by key alone would evict the replacement.
|
|
241568
|
+
*/
|
|
241569
|
+
#removeIfCurrent(turnId, hold) {
|
|
241570
|
+
if (this.#holds.get(turnId) === hold) this.#holds.delete(turnId);
|
|
241571
|
+
}
|
|
241572
|
+
/**
|
|
241354
241573
|
* Release every hold belonging to one thread.
|
|
241355
241574
|
*
|
|
241356
241575
|
* `session.exited` names only the thread whose provider process died, and a
|
|
@@ -241365,9 +241584,22 @@ var SpriteTaskHoldManager = class {
|
|
|
241365
241584
|
/**
|
|
241366
241585
|
* Release everything. Runtime drain and server shutdown must call this, or a
|
|
241367
241586
|
* drained sprite keeps billing until each hold expires.
|
|
241587
|
+
*
|
|
241588
|
+
* Shutdown passes `SPRITE_TASK_HOLD_RELEASE_JOIN_TIMEOUT_MS` /
|
|
241589
|
+
* `SPRITE_TASK_HOLD_RELEASE_DELETE_TIMEOUT_MS` so a socket that never
|
|
241590
|
+
* settles cannot hang the process open past its own termination, and gets a
|
|
241591
|
+
* per-hold report back: every hold gets its DELETE, and only holds the
|
|
241592
|
+
* sweep still saw present after the full delete+verify cap come back
|
|
241593
|
+
* unreleased, left to their own 300 s expiry. Drain passes no bounds and
|
|
241594
|
+
* keeps the patient join.
|
|
241368
241595
|
*/
|
|
241369
|
-
async releaseAll() {
|
|
241370
|
-
|
|
241596
|
+
async releaseAll(options = {}) {
|
|
241597
|
+
const turnIds = [...this.#holds.keys()];
|
|
241598
|
+
const outcomes = await Promise.all(turnIds.map(async (turnId) => [turnId, await this.release(turnId, options)]));
|
|
241599
|
+
return {
|
|
241600
|
+
released: outcomes.filter(([, outcome]) => outcome === "released").map(([turnId]) => turnId),
|
|
241601
|
+
unreleased: outcomes.filter(([, outcome]) => outcome === "unreleased").map(([turnId]) => turnId)
|
|
241602
|
+
};
|
|
241371
241603
|
}
|
|
241372
241604
|
};
|
|
241373
241605
|
/**
|
|
@@ -241398,7 +241630,25 @@ function makeSpriteTaskHoldTransport(config, fetchImpl = fetch) {
|
|
|
241398
241630
|
headers: { "content-type": "application/json" },
|
|
241399
241631
|
body: JSON.stringify({ expire: `${expireSeconds}s` })
|
|
241400
241632
|
}),
|
|
241401
|
-
delete: (name) => call(`/${encodeURIComponent(name)}`, { method: "DELETE" })
|
|
241633
|
+
delete: (name) => call(`/${encodeURIComponent(name)}`, { method: "DELETE" }),
|
|
241634
|
+
get: async (name) => {
|
|
241635
|
+
const controller = new AbortController();
|
|
241636
|
+
const deadline = setTimeout(() => controller.abort(), SPRITE_TASK_HOLD_REQUEST_TIMEOUT_MS);
|
|
241637
|
+
try {
|
|
241638
|
+
const response = await fetchImpl(`http://sprite/v1/tasks/${encodeURIComponent(name)}`, {
|
|
241639
|
+
method: "GET",
|
|
241640
|
+
signal: controller.signal,
|
|
241641
|
+
unix: config.socketPath
|
|
241642
|
+
});
|
|
241643
|
+
if (response.ok) return "present";
|
|
241644
|
+
if (response.status === 404) return "absent";
|
|
241645
|
+
return "unknown";
|
|
241646
|
+
} catch {
|
|
241647
|
+
return "unknown";
|
|
241648
|
+
} finally {
|
|
241649
|
+
clearTimeout(deadline);
|
|
241650
|
+
}
|
|
241651
|
+
}
|
|
241402
241652
|
};
|
|
241403
241653
|
}
|
|
241404
241654
|
/**
|
|
@@ -285989,10 +286239,10 @@ const AgentBrowserManagerLive = effect(BrowserManager, gen(function* () {
|
|
|
285989
286239
|
mediaSourceFactory: displayCaptureRuntime.mediaSourceFactory,
|
|
285990
286240
|
taskHold: displayTaskHoldManager ? {
|
|
285991
286241
|
acquire: (holdId) => displayTaskHoldManager.acquire(holdId),
|
|
285992
|
-
release: (holdId) => displayTaskHoldManager.release(holdId)
|
|
286242
|
+
release: (holdId) => displayTaskHoldManager.release(holdId).then(() => {})
|
|
285993
286243
|
} : void 0
|
|
285994
286244
|
});
|
|
285995
|
-
yield* addFinalizer$2(() => promise(() => displayTaskHoldManager?.releaseAll() ?? Promise.resolve()));
|
|
286245
|
+
yield* addFinalizer$2(() => promise(() => displayTaskHoldManager?.releaseAll().then(() => {}) ?? Promise.resolve()));
|
|
285996
286246
|
const baseBackendOptions = displayCaptureRuntime.backendOptions;
|
|
285997
286247
|
const sessionInitialUrls = /* @__PURE__ */ new Map();
|
|
285998
286248
|
let runtimeBuild = null;
|
|
@@ -293932,6 +294182,19 @@ const SpriteTaskHoldReactorLive = effect(SpriteTaskHoldReactor, gen(function* ()
|
|
|
293932
294182
|
const manager = makeSpriteTaskHoldManager(process.env, (message, cause) => {
|
|
293933
294183
|
runFork(logWarning$1(message, { cause: cause instanceof Error ? cause.message : cause }));
|
|
293934
294184
|
});
|
|
294185
|
+
/**
|
|
294186
|
+
* Run a manager call, or nothing on runtimes that are not sprites. One
|
|
294187
|
+
* null-guard for every caller: the releaseAll service and the shutdown
|
|
294188
|
+
* finalizer alike.
|
|
294189
|
+
*/
|
|
294190
|
+
const onManager = (run) => promise(async () => {
|
|
294191
|
+
if (manager === null) return;
|
|
294192
|
+
await run(manager);
|
|
294193
|
+
});
|
|
294194
|
+
yield* addFinalizer$2(() => onManager((taskHolds) => taskHolds.releaseAll({
|
|
294195
|
+
joinTimeoutMs: SPRITE_TASK_HOLD_RELEASE_JOIN_TIMEOUT_MS,
|
|
294196
|
+
deleteTimeoutMs: SPRITE_TASK_HOLD_RELEASE_DELETE_TIMEOUT_MS
|
|
294197
|
+
})));
|
|
293935
294198
|
const launchCallers = /* @__PURE__ */ new Map();
|
|
293936
294199
|
const start = fn$1("start")(function* () {
|
|
293937
294200
|
if (manager === null) return;
|
|
@@ -293948,12 +294211,12 @@ const SpriteTaskHoldReactorLive = effect(SpriteTaskHoldReactor, gen(function* ()
|
|
|
293948
294211
|
if (event.type === "turn.completed") {
|
|
293949
294212
|
const turnId = event.turnId;
|
|
293950
294213
|
if (turnId === void 0) return void_$1;
|
|
293951
|
-
return promise(() => manager.release(String(turnId)));
|
|
294214
|
+
return promise(() => manager.release(String(turnId)).then(() => {}));
|
|
293952
294215
|
}
|
|
293953
294216
|
if (event.type === "turn.aborted") {
|
|
293954
294217
|
const turnId = event.turnId;
|
|
293955
294218
|
if (turnId === void 0) return void_$1;
|
|
293956
|
-
return promise(() => manager.release(String(turnId)));
|
|
294219
|
+
return promise(() => manager.release(String(turnId)).then(() => {}));
|
|
293957
294220
|
}
|
|
293958
294221
|
if (event.type === "session.exited") {
|
|
293959
294222
|
launchCallers.delete(String(event.threadId));
|
|
@@ -293980,7 +294243,7 @@ const SpriteTaskHoldReactorLive = effect(SpriteTaskHoldReactor, gen(function* ()
|
|
|
293980
294243
|
start,
|
|
293981
294244
|
holdLaunch,
|
|
293982
294245
|
releaseLaunch,
|
|
293983
|
-
releaseAll:
|
|
294246
|
+
releaseAll: onManager((taskHolds) => taskHolds.releaseAll())
|
|
293984
294247
|
};
|
|
293985
294248
|
}));
|
|
293986
294249
|
//#endregion
|
|
@@ -298094,7 +298357,7 @@ function resolveBuildCommitFromEnv(env) {
|
|
|
298094
298357
|
* environment descriptor down instead of reporting an honest "unknown".
|
|
298095
298358
|
*/
|
|
298096
298359
|
function readBakedBuildCommit() {
|
|
298097
|
-
return "
|
|
298360
|
+
return "d1c5c1c87c650d1d49b596cbbe4bcc3ff14c7bfe";
|
|
298098
298361
|
}
|
|
298099
298362
|
async function resolveServerBuildCommit(input) {
|
|
298100
298363
|
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{Al as a,Fn as o,Gc as s,Hr as c,Jc as l,Qr as u,Rr as d,Sr as f,Tn as p,Uc as m,Xr as h,_r as g,d as _,fn as v,fr as y,gr as b,i as x,is as S,jn as C,l as w,m as T,ms as E,n as D,qc as O,qt as k,r as A,u as j,za as M,zr as N}from"./DiffPanelShell-
|
|
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{Al as a,Fn as o,Gc as s,Hr as c,Jc as l,Qr as u,Rr as d,Sr as f,Tn as p,Uc as m,Xr as h,_r as g,d as _,fn as v,fr as y,gr as b,i as x,is as S,jn as C,l as w,m as T,ms as E,n as D,qc as O,qt as k,r as A,u as j,za as M,zr as N}from"./DiffPanelShell-CTLS82pj.js";import{hn as P}from"./CompositeItem-B_Qce_Zi.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-DsHt9iaj.js";import{Dn as q,at as J,it as ee}from"./src-IM0FnQax.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-DF8NdwcA.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,p=(0,X.useContext)(x),m=j(),h=(0,X.useRef)(null),g=_(n=>{if(n!=null){if(h.current!=null)throw Error(`useFileDiffInstance: An instance should not already exist when a node is created`);d==null?h.current=new re(Z({controlledSelection:f,hasCustomHeader:c,hasGutterRenderUtility:s,options:t}),l?void 0:p,!0):h.current=new pe(Z({controlledSelection:f,hasCustomHeader:c,hasGutterRenderUtility:s,options:t}),d,o,l?void 0:p,!0),h.current.hydrate({fileDiff:e,fileContainer:n,lineAnnotations:r,prerenderedHTML:a})}else{if(h.current==null)throw Error(`useFileDiffInstance: A FileDiff instance should exist when unmounting`);h.current.cleanUp(),h.current=null}});return me(()=>{let{current:n}=h;if(n==null)return;let a=Z({controlledSelection:f,hasCustomHeader:c,hasGutterRenderUtility:s,options:t}),o=a!==void 0&&!k(n.options,a);n.setOptions(a),n.render({forceRender:o,fileDiff:e,lineAnnotations:r}),i!==void 0&&n.setSelectedLines(i)}),me(()=>{if(u&&h.current!=null){if(m===void 0)throw Error(`FileDiff: EditContext is not attached`);let e=m(n??{});if(e==null)throw Error(`FileDiff: EditProvider.createEditor must return an editor instance`);try{return e.edit(h.current)}catch(t){throw e.cleanUp(),t}}},[u]),{ref:g,getHoveredLine:(0,X.useCallback)(()=>h.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:h=!1,edit:g=!1}){let{ref:_,getHoveredLine:y}=he({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: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 O({queryKey:M.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}=b(),a=g(),[c,l]=(0,X.useState)(`stacked`),[u,d]=(0,X.useState)(a.diffWordWrap),h=(0,X.useRef)(null),_=(0,X.useRef)(!1),v=Te(),{activeCwd:y,activeThread:x,bodyState:S,diffOpen:C,inferredCheckpointTurnCountByTurnId:w,orderedTurnDiffSummaries:T,renderableFiles:E,renderablePatch:D,selectedFilePath:O,selectedTurn:k,selectedTurnId:j}=Le(i),M,P;t[0]!==C||t[1]!==a.diffWordWrap?(M=()=>{C&&!_.current&&d(a.diffWordWrap),_.current=C},P=[C,a.diffWordWrap],t[0]=C,t[1]=a.diffWordWrap,t[2]=M,t[3]=P):(M=t[2],P=t[3]),(0,X.useEffect)(M,P);let F;t[4]===O?F=t[5]:(F=()=>{!O||!h.current||Array.from(h.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,X.useEffect)(F,I);let L;t[9]===y?L=t[10]:(L=e=>{let t=f();if(!t)return;let n=y?p(e,y):e;N(t,n).catch(ke)},t[9]=y,t[10]=L);let R=L,z;t[11]===x?z=t[12]:(z=e=>{x&&o.getState().openDiff(s(m(x.environmentId,x.id)),e)},t[11]=x,t[12]=z);let B=z,V;t[13]===x?V=t[14]:(V=()=>{x&&o.getState().openDiff(s(m(x.environmentId,x.id)))},t[13]=x,t[14]=V);let H=V,U;t[15]===v.remeasure?U=t[16]:(U=()=>{let e=window.requestAnimationFrame(v.remeasure);return()=>window.cancelAnimationFrame(e)},t[15]=v.remeasure,t[16]=U);let W;t[17]!==T||t[18]!==j||t[19]!==v.remeasure?(W=[T,j,v.remeasure],t[17]=T,t[18]=j,t[19]=v.remeasure,t[20]=W):W=t[20],(0,X.useEffect)(U,W),Ee(v.ref,k?.turnId??j);let G;t[21]!==c||t[22]!==u||t[23]!==w||t[24]!==T||t[25]!==B||t[26]!==H||t[27]!==k||t[28]!==j||t[29]!==a||t[30]!==v?(G=(0,Q.jsx)(Ae,{diffRenderMode:c,diffWordWrap:u,inferredCheckpointTurnCountByTurnId:w,orderedTurnDiffSummaries:T,selectTurn:B,selectWholeConversation:H,selectedTurn:k,selectedTurnId:j,setDiffRenderMode:l,setDiffWordWrap:d,settings:a,turnStrip:v}),t[21]=c,t[22]=u,t[23]=w,t[24]=T,t[25]=B,t[26]=H,t[27]=k,t[28]=j,t[29]=a,t[30]=v,t[31]=G):G=t[31];let K=G,q;t[32]!==S||t[33]!==c||t[34]!==u||t[35]!==R||t[36]!==E||t[37]!==D||t[38]!==i?(q=(0,Q.jsx)(je,{bodyState:S,diffRenderMode:c,diffWordWrap:u,openDiffFileInEditor:R,patchViewportRef:h,renderableFiles:E,renderablePatch:D,resolvedTheme:i}),t[32]=S,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)(A,{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:T(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=a(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),o=i.rightPanel===`diff`,s=n?.threadId??null,c,l;e[2]===n?l=e[3]:(l=C(n),e[2]=n,e[3]=l),c=l;let u=E(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 b=d(y),x;e[10]===b.data?x=e[11]:(x=z(b.data),e[10]=b.data,e[11]=x);let S=x,w;return e[12]!==g||e[13]!==u||e[14]!==s||e[15]!==o||e[16]!==i||e[17]!==S?(w={activeThread:u,activeThreadId:s,activeCwd:g,isGitRepo:S,diffSearch:i,diffOpen:o},e[12]=g,e[13]=u,e[14]=s,e[15]=o,e[16]=i,e[17]=S,e[18]=w):w=e[18],w}function Fe(e){return G(e)}function Ie(e){return h(e)}function Le(e){let{activeThread:t,activeThreadId:n,activeCwd:r,isGitRepo:i,diffSearch:a,diffOpen:o}=Pe(),{turnDiffSummaries:s,inferredCheckpointTurnCountByTurnId:c}=H(t),u=a.diffTurnId??null,d=u===null?null:a.diffFilePath??null,{activeCheckpointRange:f,conversationCacheScope:p,orderedTurnDiffSummaries:m,selectedTurn:h}=(0,X.useMemo)(()=>te({summaries:s,inferredCheckpointTurnCountByTurnId:c,selectedTurnId:u}),[c,u,s]),g=l(xe(we({environmentId:t?.environmentId,threadId:n,range:f,selectedTurnId:h?.turnId,conversationCacheScope:p,enabled:i}))),_=g.isLoading,v=Ce(g.error),y=g.data?.diff,b=typeof y==`string`&&y.trim().length===0,{emptyDiffMessage:x}=(0,X.useMemo)(()=>ae(h),[h]),S=(0,X.useMemo)(()=>ce(y,`diff-panel:${e}`),[e,y]),C=(0,X.useMemo)(()=>Ue(S),[S]);return{activeCwd:r,activeThread:t,bodyState:ue({hasActiveThread:!!t,isGitRepo:i,turnSummaryCount:m.length,checkpointDiffError:v,hasRenderablePatch:!!S,isLoadingCheckpointDiff:_,hasNoNetChanges:b,emptyDiffMessage:x}),diffOpen:o,inferredCheckpointTurnCountByTurnId:c,orderedTurnDiffSummaries:m,renderableFiles:C,renderablePatch:S,selectedFilePath:d,selectedTurn:h,selectedTurnId:u}}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)(D,{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:u,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 d;t[3]!==i||t[4]!==r?(d=()=>r.scrollBy(i?-180:ze),t[3]=i,t[4]=r,t[5]=d):d=t[5];let f=!a,p=`Scroll turn list ${n}`,m;t[6]===o?m=t[7]:(m=(0,Q.jsx)(o,{className:`size-3.5`}),t[6]=o,t[7]=m);let h;return t[8]!==l||t[9]!==d||t[10]!==f||t[11]!==p||t[12]!==m?(h=(0,Q.jsx)(`button`,{type:`button`,className:l,onClick:d,disabled:f,"aria-label":p,children:m}),t[8]=l,t[9]=d,t[10]=f,t[11]=p,t[12]=m,t[13]=h):h=t[13],h}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=y(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 g;t[15]!==u||t[16]!==h?(g=(0,Q.jsx)(`div`,{className:u,children:h}),t[15]=u,t[16]=h,t[17]=g):g=t[17];let _;return t[18]!==r||t[19]!==n.turnId||t[20]!==s||t[21]!==g?(_=(0,Q.jsx)(`button`,{type:`button`,className:`shrink-0 rounded-md`,onClick:s,title:c,"data-turn-chip-selected":r,children:g}),t[18]=r,t[19]=n.turnId,t[20]=s,t[21]=g,t[22]=_):_=t[22],_}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?S(e,{environmentId:n,projectId:r}):void 0,t[0]=n,t[1]=r,t[2]=i):i=t[2],E(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-Bn53zJRq.js.map
|