@p4code/cli 0.5.14 → 0.5.15

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.mjs CHANGED
@@ -265,7 +265,7 @@ const make$120 = () => {
265
265
  const layer$122 = Layer.sync(NetService, make$120);
266
266
  //#endregion
267
267
  //#region package.json
268
- var version$1 = "0.5.14";
268
+ var version$1 = "0.5.15";
269
269
  //#endregion
270
270
  //#region src/config.ts
271
271
  /**
@@ -12885,11 +12885,11 @@ const ThreadWatchReviewResult = Schema$1.Struct({
12885
12885
  /**
12886
12886
  * How a review ended, from the supervisor's own account of it.
12887
12887
  *
12888
- * Four states rather than a boolean because they are acted on differently: a
12888
+ * Three states rather than a boolean because they are acted on differently: a
12889
12889
  * summary that arrived is evidence, a fallback is a working review that cost
12890
- * full context, a failure is a misconfiguration worth fixing, and a read with
12891
- * no report at all is the only one that cannot be told from a supervisor that
12892
- * simply never reported - which is why the absence has to be visible too.
12890
+ * full context, and a failure is a misconfiguration worth fixing. The fourth
12891
+ * state - a read no report ever answered - is not sayable here: only the
12892
+ * server can observe it, through `ThreadEvidenceActivityOutcome`.
12893
12893
  */
12894
12894
  const ThreadEvidenceReportOutcome = Schema$1.Literals([
12895
12895
  "summarized",
@@ -12942,19 +12942,50 @@ const ThreadEvidenceReportContext = Schema$1.Struct({
12942
12942
  maxTokens: Schema$1.NullOr(NonNegativeInt),
12943
12943
  capacityPercent: Schema$1.NullOr(Schema$1.Number)
12944
12944
  });
12945
+ /**
12946
+ * How the recorded row ended, which is the supervisor's three outcomes plus the
12947
+ * one only the server can state: the review closed with no report at all.
12948
+ *
12949
+ * `unreported` is never accepted from a tool call. The server writes it when a
12950
+ * supervisor turn ends over an evidence read that nothing answered, so the
12951
+ * absence survives outside a live client that could infer it from two rows.
12952
+ */
12953
+ const ThreadEvidenceActivityOutcome = Schema$1.Literals([
12954
+ "summarized",
12955
+ "fallback",
12956
+ "failed",
12957
+ "unreported"
12958
+ ]);
12959
+ /**
12960
+ * Server clock around one review, never the supervisor's own account of it.
12961
+ *
12962
+ * `readAt` is when the evidence-read row was recorded and `closedAt` when the
12963
+ * row that closes the review was: the report for a reported review, the turn
12964
+ * boundary for an unreported one.
12965
+ */
12966
+ const ThreadEvidenceReportTiming = Schema$1.Struct({
12967
+ readAt: IsoDateTime,
12968
+ closedAt: IsoDateTime,
12969
+ durationMs: NonNegativeInt
12970
+ });
12945
12971
  Schema$1.Struct({
12946
12972
  watchedThreadId: ThreadId,
12947
12973
  firstSequence: NonNegativeInt,
12948
12974
  lastSequence: NonNegativeInt,
12949
12975
  throughSequence: NonNegativeInt,
12950
- outcome: ThreadEvidenceReportOutcome,
12976
+ outcome: ThreadEvidenceActivityOutcome,
12951
12977
  summary: Schema$1.NullOr(Schema$1.String),
12952
12978
  /** True when a snapshot dropped the text of a superseded report. */
12953
12979
  summaryDropped: Schema$1.optionalKey(Schema$1.Boolean),
12954
12980
  model: Schema$1.NullOr(Schema$1.String),
12955
12981
  reason: Schema$1.NullOr(Schema$1.String),
12956
12982
  /** Null when no context-window row exists yet for the reporting thread. */
12957
- context: Schema$1.NullOr(ThreadEvidenceReportContext)
12983
+ context: Schema$1.NullOr(ThreadEvidenceReportContext),
12984
+ /**
12985
+ * Null when the evidence-read row behind this review is no longer readable,
12986
+ * and absent on rows stored before the server measured a review at all.
12987
+ */
12988
+ timing: Schema$1.optionalKey(Schema$1.NullOr(ThreadEvidenceReportTiming))
12958
12989
  });
12959
12990
  const ThreadEvidenceReportResult = Schema$1.Struct({
12960
12991
  recorded: Schema$1.Boolean,
@@ -41541,6 +41572,28 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
41541
41572
  detached_at AS "detachedAt"
41542
41573
  FROM thread_pairs
41543
41574
  ORDER BY created_at ASC, pair_id ASC
41575
+ `
41576
+ });
41577
+ const listActiveThreadPairRows = SqlSchema.findAll({
41578
+ Request: Schema$1.Void,
41579
+ Result: ProjectionThreadPairDbRowSchema,
41580
+ execute: () => sql`
41581
+ SELECT
41582
+ pair_id AS "id",
41583
+ implementer_thread_id AS "implementerThreadId",
41584
+ watcher_thread_id AS "watcherThreadId",
41585
+ last_reviewed_implementer_sequence AS "lastReviewedImplementerSequence",
41586
+ triaged_from_sequence AS "triagedFromSequence",
41587
+ activation_turn_id AS "activationTurnId",
41588
+ round_cap AS "roundCap",
41589
+ gate_timeout_ms AS "gateTimeoutMs",
41590
+ review_experiment_json AS "reviewExperiment",
41591
+ active_gate_json AS "activeGate",
41592
+ created_at AS "createdAt",
41593
+ detached_at AS "detachedAt"
41594
+ FROM thread_pairs
41595
+ WHERE detached_at IS NULL
41596
+ ORDER BY created_at ASC, pair_id ASC
41544
41597
  `
41545
41598
  });
41546
41599
  const LatestContextWindowRow = Schema$1.Struct({
@@ -41562,15 +41615,66 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
41562
41615
  LIMIT 1
41563
41616
  `
41564
41617
  });
41565
- const EvidenceReadContextRow = Schema$1.Struct({ usedTokensAtRead: Schema$1.Number });
41618
+ const EvidenceReadContextRow = Schema$1.Struct({
41619
+ usedTokensAtRead: Schema$1.NullOr(Schema$1.Number),
41620
+ readAt: Schema$1.String,
41621
+ afterSequence: Schema$1.NullOr(Schema$1.Number)
41622
+ });
41566
41623
  const getEvidenceReadContextRow = SqlSchema.findOneOption({
41567
41624
  Request: Schema$1.String,
41568
41625
  Result: EvidenceReadContextRow,
41569
41626
  execute: (activityId) => sql`
41570
- SELECT json_extract(payload_json, '$.usedTokensAtRead') AS "usedTokensAtRead"
41627
+ SELECT
41628
+ CASE
41629
+ WHEN json_extract(payload_json, '$.usedTokensAtRead') >= 0
41630
+ THEN json_extract(payload_json, '$.usedTokensAtRead')
41631
+ ELSE NULL
41632
+ END AS "usedTokensAtRead",
41633
+ created_at AS "readAt",
41634
+ json_extract(payload_json, '$.afterSequence') AS "afterSequence"
41571
41635
  FROM projection_thread_activities
41572
41636
  WHERE activity_id = ${activityId}
41573
- AND json_extract(payload_json, '$.usedTokensAtRead') >= 0
41637
+ LIMIT 1
41638
+ `
41639
+ });
41640
+ const LatestEvidenceReadRow = Schema$1.Struct({
41641
+ watchedThreadId: ThreadId,
41642
+ afterSequence: Schema$1.NullOr(Schema$1.Number),
41643
+ throughSequence: Schema$1.Number,
41644
+ readAt: Schema$1.String,
41645
+ hasReport: Schema$1.Number
41646
+ });
41647
+ /**
41648
+ * The newest evidence read on a thread, with whether a report answered it.
41649
+ *
41650
+ * Newest only: a supervisor that read again against a later bound superseded
41651
+ * the earlier read rather than leaving it unanswered, which is the same
41652
+ * pairing rule the client's own rows follow.
41653
+ */
41654
+ const getLatestEvidenceReadRow = SqlSchema.findOneOption({
41655
+ Request: ThreadId,
41656
+ Result: LatestEvidenceReadRow,
41657
+ execute: (threadId) => sql`
41658
+ SELECT
41659
+ json_extract(reads.payload_json, '$.watchedThreadId') AS "watchedThreadId",
41660
+ json_extract(reads.payload_json, '$.afterSequence') AS "afterSequence",
41661
+ json_extract(reads.payload_json, '$.throughSequence') AS "throughSequence",
41662
+ reads.created_at AS "readAt",
41663
+ EXISTS (
41664
+ SELECT 1
41665
+ FROM projection_thread_activities reports
41666
+ WHERE reports.thread_id = reads.thread_id
41667
+ AND reports.kind = 'fusion.evidence.summary'
41668
+ AND json_extract(reports.payload_json, '$.watchedThreadId')
41669
+ = json_extract(reads.payload_json, '$.watchedThreadId')
41670
+ AND json_extract(reports.payload_json, '$.throughSequence')
41671
+ = json_extract(reads.payload_json, '$.throughSequence')
41672
+ ) AS "hasReport"
41673
+ FROM projection_thread_activities reads
41674
+ WHERE reads.thread_id = ${threadId}
41675
+ AND reads.kind = 'fusion.evidence.read'
41676
+ AND json_extract(reads.payload_json, '$.throughSequence') >= 0
41677
+ ORDER BY reads.created_at DESC, reads.rowid DESC
41574
41678
  LIMIT 1
41575
41679
  `
41576
41680
  });
@@ -43362,8 +43466,16 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
43362
43466
  })) };
43363
43467
  });
43364
43468
  const getLatestThreadContextWindow = (threadId) => getLatestContextWindowRow(threadId).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getLatestThreadContextWindow:query", "ProjectionSnapshotQuery.getLatestThreadContextWindow:decodeRow")));
43365
- const getEvidenceReadContext = (activityId) => getEvidenceReadContextRow(activityId).pipe(Effect.map(Option.map((row) => row.usedTokensAtRead)), Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getEvidenceReadContext:query", "ProjectionSnapshotQuery.getEvidenceReadContext:decodeRow")));
43469
+ const getEvidenceReadContext = (activityId) => getEvidenceReadContextRow(activityId).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getEvidenceReadContext:query", "ProjectionSnapshotQuery.getEvidenceReadContext:decodeRow")));
43470
+ const getLatestEvidenceRead = (threadId) => getLatestEvidenceReadRow(threadId).pipe(Effect.map(Option.map((row) => ({
43471
+ watchedThreadId: row.watchedThreadId,
43472
+ afterSequence: row.afterSequence,
43473
+ throughSequence: row.throughSequence,
43474
+ readAt: row.readAt,
43475
+ hasReport: row.hasReport !== 0
43476
+ }))), Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getLatestEvidenceRead:query", "ProjectionSnapshotQuery.getLatestEvidenceRead:decodeRow")));
43366
43477
  const getThreadPairById = (pairId) => getThreadPairRow(pairId).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getThreadPairById:query", "ProjectionSnapshotQuery.getThreadPairById:decodeRow")));
43478
+ const getActiveThreadPairs = () => listActiveThreadPairRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getActiveThreadPairs:query", "ProjectionSnapshotQuery.getActiveThreadPairs:decodeRows")));
43367
43479
  const getThreadShellById = (threadId) => Effect.gen(function* () {
43368
43480
  const [threadRow, latestTurnRow, sessionRow] = yield* Effect.all([
43369
43481
  getActiveThreadRowById({ threadId }).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getThreadShellById:getThread:query", "ProjectionSnapshotQuery.getThreadShellById:getThread:decodeRow"))),
@@ -43584,6 +43696,8 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
43584
43696
  getThreadCheckpointContext,
43585
43697
  getFullThreadDiffContext,
43586
43698
  getThreadPairById,
43699
+ getActiveThreadPairs,
43700
+ getLatestEvidenceRead,
43587
43701
  getThreadShellById,
43588
43702
  getThreadDetailById,
43589
43703
  getHandoffContext,
@@ -59353,6 +59467,21 @@ function fusionRoleInstructionsFor(role, options) {
59353
59467
  const model = fusionSummarizerModelFor(options.provider, options.summarizerModelOverride);
59354
59468
  return `${FUSION_WATCHER_INSTRUCTIONS} ${FUSION_EVIDENCE_SUMMARY_INSTRUCTIONS} ${summarizerModelLine(model)}`;
59355
59469
  }
59470
+ /**
59471
+ * The closing duty, restated in the wake that asks for the review.
59472
+ *
59473
+ * The same duty is in the supervisor's role block, but a wake message spells
59474
+ * out the whole turn and a model follows the instruction it was just handed:
59475
+ * with the duty only in the session channel, this install recorded 58 evidence
59476
+ * reads and no reports at all. Stated here it travels the common provider
59477
+ * input path, so it reaches every provider whatever its session prompt does.
59478
+ */
59479
+ function fusionReviewClosingInstruction(input) {
59480
+ const close = `Then close this review with exactly one thread_evidence_report call: threadId ${input.implementerThreadId}, throughSequence ${input.throughSequence} - that exact number, never lastSequence and never the final page's nextAfterSequence, because the server pairs the report to the read by it - plus the first and last sequence you actually covered.`;
59481
+ return input.evidenceSummary ? `Read that evidence through one summarizer subagent against the same fixed throughSequence ${input.throughSequence} and review from what it returns. Fail open: if no subagent is available, the spawn errors, it times out, or what comes back is empty or cites no sequences, read the range yourself instead. Never skip or shorten the review because a summary was unavailable.
59482
+
59483
+ ${close} Outcome summarized with the subagent's exact returned text and the model it ran on, fallback when you read the range yourself, or failed when the summarizer could not run - with your reason in the last two cases. Report even when no summary ever arrived; an unreported review cannot be told from a supervisor that never tried. Never paste builder tool output into the report.` : `${close} Evidence summarization is off for this environment, so the outcome is fallback with the reason you read the range yourself. Never paste builder tool output into the report.`;
59484
+ }
59356
59485
  function fusionRoleReferenceLineFor(role) {
59357
59486
  return role === "implementer" ? FUSION_BUILDER_REFERENCE_LINE : FUSION_WATCHER_REFERENCE_LINE;
59358
59487
  }
@@ -134032,6 +134161,86 @@ const TypeSafeToolkitHandlersLive = TypeSafeToolkit.toLayer({ typesafe_ask: (inp
134032
134161
  }).pipe(Effect.mapError((error) => new TypeSafeAskFailedError({ reason: `TypeSafe: ${error.reason}` })));
134033
134162
  }) });
134034
134163
  //#endregion
134164
+ //#region src/orchestration/fusionEvidenceReport.ts
134165
+ /**
134166
+ * Shared shape of one Fusion review's evidence rows.
134167
+ *
134168
+ * Two writers close a review: the supervisor calling `thread_evidence_report`,
134169
+ * and the server itself when a supervisor turn ends over a read nothing
134170
+ * answered. Both key their row the same way and measure the same numbers from
134171
+ * the same recorded rows, so a reader cannot tell which writer it is looking at
134172
+ * apart from the outcome the row carries.
134173
+ *
134174
+ * @module fusionEvidenceReport
134175
+ */
134176
+ /**
134177
+ * One activity per review, not one per page.
134178
+ *
134179
+ * A supervisor pages a range with a fixed `throughSequence`, so keying the id
134180
+ * on the watched thread and that bound collapses a whole paged read into a
134181
+ * single row: the projector replaces an activity of the same id rather than
134182
+ * appending beside it.
134183
+ */
134184
+ const evidenceReadActivityId = (watchedThreadId, throughSequence) => EventId.make(`fusion-evidence:${watchedThreadId}:${throughSequence}`);
134185
+ /** One report per review, keyed like the read it reports on so a retry replaces. */
134186
+ const evidenceReportActivityId = (watchedThreadId, throughSequence) => EventId.make(`fusion-evidence-summary:${watchedThreadId}:${throughSequence}`);
134187
+ /**
134188
+ * Server clock across the review, from the two recorded rows that bracket it.
134189
+ *
134190
+ * An unparsable timestamp yields null rather than a zero, and a closing time
134191
+ * behind the read yields null as well: a negative duration is a clock problem,
134192
+ * not a review that took no time.
134193
+ */
134194
+ const evidenceTiming = (readAt, closedAt) => {
134195
+ const read = Date.parse(readAt);
134196
+ const closed = Date.parse(closedAt);
134197
+ if (Number.isNaN(read) || Number.isNaN(closed) || closed < read) return null;
134198
+ return {
134199
+ readAt,
134200
+ closedAt,
134201
+ durationMs: closed - read
134202
+ };
134203
+ };
134204
+ /**
134205
+ * The reporting thread's own context and elapsed time around the read it is
134206
+ * closing.
134207
+ *
134208
+ * `before` comes off the evidence-read activity rather than the closing row, so
134209
+ * the pair of numbers brackets the ingestion instead of describing only the
134210
+ * moment the supervisor got around to reporting. A thread with no
134211
+ * context-window row yet yields null rather than a zero that would read as a
134212
+ * real measurement.
134213
+ */
134214
+ const correlateEvidence = Effect.fn("fusionEvidenceReport.correlateEvidence")(function* (input) {
134215
+ const projections = yield* ProjectionSnapshotQuery;
134216
+ const latest = yield* projections.getLatestThreadContextWindow(input.readerThreadId).pipe(Effect.orElseSucceed(() => Option.none()));
134217
+ const read = yield* projections.getEvidenceReadContext(input.readActivityId).pipe(Effect.orElseSucceed(() => Option.none()));
134218
+ const timing = Option.match(read, {
134219
+ onNone: () => null,
134220
+ onSome: (row) => evidenceTiming(row.readAt, input.closedAt)
134221
+ });
134222
+ if (Option.isNone(latest)) return {
134223
+ context: null,
134224
+ timing
134225
+ };
134226
+ const usedTokensAfter = latest.value.usedTokens;
134227
+ const usedTokensBefore = Option.match(read, {
134228
+ onNone: () => null,
134229
+ onSome: (row) => row.usedTokensAtRead
134230
+ });
134231
+ const maxTokens = latest.value.maxTokens;
134232
+ return {
134233
+ context: {
134234
+ usedTokensBefore,
134235
+ usedTokensAfter,
134236
+ deltaTokens: usedTokensBefore === null ? null : usedTokensAfter - usedTokensBefore,
134237
+ maxTokens,
134238
+ capacityPercent: maxTokens === null || maxTokens <= 0 ? null : Math.round(usedTokensAfter / maxTokens * 1e3) / 10
134239
+ },
134240
+ timing
134241
+ };
134242
+ });
134243
+ //#endregion
134035
134244
  //#region src/mcp/toolkits/watch/tools.ts
134036
134245
  /**
134037
134246
  * Cross-thread by design, which is exactly why it is the most guarded tool in
@@ -134085,17 +134294,6 @@ const ThreadEvidenceReportTool = Tool.make("thread_evidence_report", {
134085
134294
  const WatchToolkit = Toolkit.make(ThreadWatchEventsTool, ThreadWatchReviewTool, ThreadEvidenceReportTool);
134086
134295
  //#endregion
134087
134296
  //#region src/mcp/toolkits/watch/handlers.ts
134088
- /**
134089
- * One activity per review, not one per page.
134090
- *
134091
- * A supervisor pages a range with a fixed `throughSequence`, so keying the id
134092
- * on the watched thread and that bound collapses a whole paged read into a
134093
- * single row: the projector replaces an activity of the same id rather than
134094
- * appending beside it.
134095
- */
134096
- const evidenceActivityId = (watchedThreadId, throughSequence) => EventId.make(`fusion-evidence:${watchedThreadId}:${throughSequence}`);
134097
- /** One report per review, keyed like the read it reports on so a retry replaces. */
134098
- const reportActivityId = (watchedThreadId, lastSequence) => EventId.make(`fusion-evidence-summary:${watchedThreadId}:${lastSequence}`);
134099
134297
  const MODEL_ID_MAX_CHARS = 120;
134100
134298
  /** Plain words, because the client capitalizes and renders them as the row heading. */
134101
134299
  const REPORT_HEADING = {
@@ -134110,27 +134308,37 @@ const REPORT_HEADING = {
134110
134308
  * for; losing the note that it happened is a smaller loss than losing the page,
134111
134309
  * so a rejected dispatch is logged and the page is returned anyway.
134112
134310
  */
134113
- const recordEvidenceRead = Effect.fn("mcp.watch.recordEvidenceRead")(function* (readerThreadId, page) {
134311
+ const recordEvidenceRead = Effect.fn("mcp.watch.recordEvidenceRead")(function* (readerThreadId, page, afterSequence) {
134114
134312
  const engine = yield* OrchestrationEngineService;
134115
134313
  const crypto = yield* Crypto.Crypto;
134116
134314
  const projections = yield* ProjectionSnapshotQuery;
134117
134315
  const createdAt = DateTime.formatIso(yield* DateTime.now);
134118
- const recorded = yield* projections.getEvidenceReadContext(evidenceActivityId(page.threadId, page.throughSequence)).pipe(Effect.orElseSucceed(() => Option.none()));
134119
- const usedTokensAtRead = Option.isSome(recorded) ? recorded.value : yield* projections.getLatestThreadContextWindow(readerThreadId).pipe(Effect.map(Option.map((row) => row.usedTokens)), Effect.orElseSucceed(() => Option.none()), Effect.map(Option.getOrNull));
134316
+ const recorded = yield* projections.getEvidenceReadContext(evidenceReadActivityId(page.threadId, page.throughSequence)).pipe(Effect.orElseSucceed(() => Option.none()));
134317
+ const opened = Option.isSome(recorded);
134318
+ const readCreatedAt = Option.match(recorded, {
134319
+ onNone: () => createdAt,
134320
+ onSome: (row) => row.readAt
134321
+ });
134322
+ const readAfterSequence = Option.match(recorded, {
134323
+ onNone: () => afterSequence,
134324
+ onSome: (row) => row.afterSequence ?? afterSequence
134325
+ });
134326
+ const usedTokensAtRead = opened ? Option.getOrNull(Option.map(recorded, (row) => row.usedTokensAtRead)) : yield* projections.getLatestThreadContextWindow(readerThreadId).pipe(Effect.map(Option.map((row) => row.usedTokens)), Effect.orElseSucceed(() => Option.none()), Effect.map(Option.getOrNull));
134120
134327
  yield* engine.dispatch({
134121
134328
  type: "thread.activity.append",
134122
134329
  commandId: CommandId.make(yield* crypto.randomUUIDv4.pipe(Effect.orDie)),
134123
134330
  threadId: readerThreadId,
134124
134331
  createdAt,
134125
134332
  activity: {
134126
- id: evidenceActivityId(page.threadId, page.throughSequence),
134127
- createdAt,
134333
+ id: evidenceReadActivityId(page.threadId, page.throughSequence),
134334
+ createdAt: readCreatedAt,
134128
134335
  tone: "info",
134129
134336
  kind: "fusion.evidence.read",
134130
134337
  summary: "Read builder evidence",
134131
134338
  turnId: null,
134132
134339
  payload: {
134133
134340
  watchedThreadId: page.threadId,
134341
+ afterSequence: readAfterSequence,
134134
134342
  throughSequence: page.throughSequence,
134135
134343
  nextAfterSequence: page.nextAfterSequence,
134136
134344
  hasMore: page.hasMore,
@@ -134150,30 +134358,6 @@ const clip = (value, limit) => {
134150
134358
  if (!trimmed) return null;
134151
134359
  return trimmed.length <= limit ? trimmed : `${trimmed.slice(0, limit)}…`;
134152
134360
  };
134153
- /**
134154
- * The reporting thread's own context around the read it is reporting on.
134155
- *
134156
- * `before` comes off the evidence-read activity rather than the report, so the
134157
- * pair of numbers brackets the ingestion instead of describing only the moment
134158
- * the supervisor got around to reporting. A thread with no context-window row
134159
- * yet yields null rather than a zero that would read as a real measurement.
134160
- */
134161
- const correlateContext = Effect.fn("mcp.watch.correlateContext")(function* (readerThreadId, readActivityId) {
134162
- const projections = yield* ProjectionSnapshotQuery;
134163
- const latest = yield* projections.getLatestThreadContextWindow(readerThreadId).pipe(Effect.orElseSucceed(() => Option.none()));
134164
- const before = yield* projections.getEvidenceReadContext(readActivityId).pipe(Effect.orElseSucceed(() => Option.none()));
134165
- if (Option.isNone(latest)) return null;
134166
- const usedTokensAfter = latest.value.usedTokens;
134167
- const usedTokensBefore = Option.getOrNull(before);
134168
- const maxTokens = latest.value.maxTokens;
134169
- return {
134170
- usedTokensBefore,
134171
- usedTokensAfter,
134172
- deltaTokens: usedTokensBefore === null ? null : usedTokensAfter - usedTokensBefore,
134173
- maxTokens,
134174
- capacityPercent: maxTokens === null || maxTokens <= 0 ? null : Math.round(usedTokensAfter / maxTokens * 1e3) / 10
134175
- };
134176
- });
134177
134361
  const WatchToolkitHandlersLive = WatchToolkit.toLayer({
134178
134362
  thread_watch_review: (input) => Effect.gen(function* () {
134179
134363
  const invocation = yield* requireWatchCapability(input.threadId);
@@ -134181,7 +134365,7 @@ const WatchToolkitHandlersLive = WatchToolkit.toLayer({
134181
134365
  threadId: input.threadId,
134182
134366
  detail: cause.message
134183
134367
  })));
134184
- yield* recordEvidenceRead(invocation.threadId, page);
134368
+ yield* recordEvidenceRead(invocation.threadId, page, input.afterSequence ?? 0);
134185
134369
  return page;
134186
134370
  }),
134187
134371
  thread_evidence_report: (input) => Effect.gen(function* () {
@@ -134189,7 +134373,11 @@ const WatchToolkitHandlersLive = WatchToolkit.toLayer({
134189
134373
  const engine = yield* OrchestrationEngineService;
134190
134374
  const crypto = yield* Crypto.Crypto;
134191
134375
  const createdAt = DateTime.formatIso(yield* DateTime.now);
134192
- const context = yield* correlateContext(invocation.threadId, evidenceActivityId(input.threadId, input.throughSequence));
134376
+ const { context, timing } = yield* correlateEvidence({
134377
+ readerThreadId: invocation.threadId,
134378
+ readActivityId: evidenceReadActivityId(input.threadId, input.throughSequence),
134379
+ closedAt: createdAt
134380
+ });
134193
134381
  const summary = clip(input.summary, THREAD_EVIDENCE_REPORT_MAX_CHARS);
134194
134382
  const reason = clip(input.reason, 500);
134195
134383
  const outcome = summary === null && input.outcome === "summarized" ? "failed" : input.outcome;
@@ -134200,7 +134388,7 @@ const WatchToolkitHandlersLive = WatchToolkit.toLayer({
134200
134388
  threadId: invocation.threadId,
134201
134389
  createdAt,
134202
134390
  activity: {
134203
- id: reportActivityId(input.threadId, input.throughSequence),
134391
+ id: evidenceReportActivityId(input.threadId, input.throughSequence),
134204
134392
  createdAt,
134205
134393
  tone: outcome === "failed" ? "error" : "info",
134206
134394
  kind: "fusion.evidence.summary",
@@ -134215,7 +134403,8 @@ const WatchToolkitHandlersLive = WatchToolkit.toLayer({
134215
134403
  summary,
134216
134404
  model: clip(input.model, MODEL_ID_MAX_CHARS),
134217
134405
  reason: reason ?? (outcome === "summarized" ? null : "the supervisor gave no reason"),
134218
- context
134406
+ context,
134407
+ timing
134219
134408
  }
134220
134409
  }
134221
134410
  }).pipe(Effect.as(true), Effect.catchCause((cause) => Effect.logWarning("could not record the supervisor's evidence report", {
@@ -139153,6 +139342,12 @@ ${FUSION_WATCHER_TOOL_INSTRUCTIONS}
139153
139342
 
139154
139343
  Call thread_watch_review, threadId ${input.implementerThreadId}, afterSequence ${input.afterSequence}, throughSequence ${input.throughSequence}. Continue with nextAfterSequence and the same throughSequence until hasMore is false, including empty pages. Apply message append/replace operations by identity across pages. Recover truncated or uncertain evidence with targeted thread_watch_events reads using its source sequence range. Inspect repo when useful.
139155
139344
 
139345
+ ${fusionReviewClosingInstruction({
139346
+ implementerThreadId: input.implementerThreadId,
139347
+ throughSequence: input.throughSequence,
139348
+ evidenceSummary: input.evidenceSummary
139349
+ })}
139350
+
139156
139351
  Always report concise:
139157
139352
 
139158
139353
  - Progress: work done; completeness.
@@ -139234,6 +139429,13 @@ const make$3 = Effect.gen(function* () {
139234
139429
  activePairs: (readModel.threadPairs ?? []).filter((pair) => pair.detachedAt === null)
139235
139430
  };
139236
139431
  });
139432
+ /**
139433
+ * Activity events arrive at provider streaming speed on every thread in the
139434
+ * install, and only a pair's own activities matter here. The pair table
139435
+ * alone answers that, so the hot path never decodes the whole command read
139436
+ * model; the rare branches that need threads read it themselves.
139437
+ */
139438
+ const readActivePairs = projectionSnapshotQuery.getActiveThreadPairs();
139237
139439
  const appendGateActivity = Effect.fn("FusionWatcherReactor.appendGateActivity")(function* (input) {
139238
139440
  yield* orchestrationEngine.dispatch({
139239
139441
  type: "thread.activity.append",
@@ -139488,10 +139690,18 @@ const make$3 = Effect.gen(function* () {
139488
139690
  const requestId = payload["requestId"];
139489
139691
  return typeof requestId === "string" && requestId.length > 0 ? requestId : void 0;
139490
139692
  };
139693
+ /** The only activity kinds this reactor reacts to; everything else returns first. */
139694
+ const FUSION_ACTIVITY_KINDS = /* @__PURE__ */ new Set([
139695
+ "provider.turn.start.failed",
139696
+ "approval.requested",
139697
+ "approval.resolved",
139698
+ "tool.completed"
139699
+ ]);
139491
139700
  const processActivityAppended = Effect.fn("FusionWatcherReactor.processActivityAppended")(function* (event) {
139492
139701
  if (event.sequence <= liveEventsAfterSequence) return;
139493
139702
  const activity = event.payload.activity;
139494
- const { activePairs } = yield* readPairs;
139703
+ if (!FUSION_ACTIVITY_KINDS.has(activity.kind)) return;
139704
+ const activePairs = yield* readActivePairs;
139495
139705
  const pairedThread = activePairs.find((candidate) => candidate.implementerThreadId === event.payload.threadId || candidate.watcherThreadId === event.payload.threadId);
139496
139706
  if (activity.kind === "provider.turn.start.failed" && pairedThread !== void 0) {
139497
139707
  yield* pausePairAfterProviderFailure({
@@ -139657,6 +139867,14 @@ const make$3 = Effect.gen(function* () {
139657
139867
  });
139658
139868
  });
139659
139869
  /**
139870
+ * Unreadable settings mean the shipped default, not off: a supervisor that
139871
+ * was told nothing about closing its review is the failure this line exists
139872
+ * to prevent.
139873
+ */
139874
+ const readEvidenceSummaryEnabled = Effect.gen(function* () {
139875
+ return (yield* serverSettings.getSettings.pipe(Effect.catchCause(() => Effect.succeed(null))))?.fusionEvidenceSummary ?? DEFAULT_FUSION_PROMPT_SETTINGS.evidenceSummary;
139876
+ });
139877
+ /**
139660
139878
  * The pre-filter's configuration, or null when it must not run at all.
139661
139879
  *
139662
139880
  * A settings read failure returns null rather than a default: an unreadable
@@ -139752,7 +139970,8 @@ const make$3 = Effect.gen(function* () {
139752
139970
  text: watcherPrompt({
139753
139971
  implementerThreadId: currentPair.implementerThreadId,
139754
139972
  afterSequence: currentPair.lastReviewedImplementerSequence,
139755
- throughSequence: completion.sequence
139973
+ throughSequence: completion.sequence,
139974
+ evidenceSummary: yield* readEvidenceSummaryEnabled
139756
139975
  }) + "\n\n" + fusionReviewPolicyInstructions(currentPair.reviewExperiment),
139757
139976
  attachments: []
139758
139977
  },
@@ -139820,6 +140039,53 @@ const make$3 = Effect.gen(function* () {
139820
140039
  yield* processReview(pair, completion, turn);
139821
140040
  }
139822
140041
  });
140042
+ /**
140043
+ * Closes a supervisor turn that read the builder's evidence and ended without
140044
+ * reporting on it.
140045
+ *
140046
+ * The row it writes is keyed exactly like the supervisor's own report, so a
140047
+ * later report replaces it rather than doubling it, and it carries the same
140048
+ * server-measured context and timing. Without it, a review that was never
140049
+ * reported is indistinguishable in stored history from one that was never
140050
+ * attempted.
140051
+ */
140052
+ const recordUnreportedEvidence = Effect.fn("FusionWatcherReactor.recordUnreportedEvidence")(function* (pair, completion) {
140053
+ const read = yield* projectionSnapshotQuery.getLatestEvidenceRead(pair.watcherThreadId).pipe(Effect.orElseSucceed(() => Option.none()));
140054
+ if (Option.isNone(read)) return;
140055
+ const latest = read.value;
140056
+ if (latest.hasReport || latest.watchedThreadId !== pair.implementerThreadId) return;
140057
+ const { context, timing } = yield* correlateEvidence({
140058
+ readerThreadId: pair.watcherThreadId,
140059
+ readActivityId: evidenceReadActivityId(latest.watchedThreadId, latest.throughSequence),
140060
+ closedAt: completion.occurredAt
140061
+ });
140062
+ yield* orchestrationEngine.dispatch({
140063
+ type: "thread.activity.append",
140064
+ commandId: CommandId.make(`server:fusion:${pair.id}:evidence-unreported:${latest.throughSequence}`),
140065
+ threadId: pair.watcherThreadId,
140066
+ createdAt: completion.occurredAt,
140067
+ activity: {
140068
+ id: evidenceReportActivityId(latest.watchedThreadId, latest.throughSequence),
140069
+ createdAt: completion.occurredAt,
140070
+ tone: "error",
140071
+ kind: "fusion.evidence.summary",
140072
+ summary: "Evidence never reported",
140073
+ turnId: null,
140074
+ payload: {
140075
+ watchedThreadId: latest.watchedThreadId,
140076
+ firstSequence: latest.afterSequence === null ? latest.throughSequence : Math.min(latest.afterSequence + 1, latest.throughSequence),
140077
+ lastSequence: latest.throughSequence,
140078
+ throughSequence: latest.throughSequence,
140079
+ outcome: "unreported",
140080
+ summary: null,
140081
+ model: null,
140082
+ reason: "the supervisor ended its turn without reporting on the evidence it read",
140083
+ context,
140084
+ timing
140085
+ }
140086
+ }
140087
+ });
140088
+ });
139823
140089
  const processCompletion = Effect.fn("FusionWatcherReactor.processCompletion")(function* (event) {
139824
140090
  const activePairs = ((yield* projectionSnapshotQuery.getCommandReadModel()).threadPairs ?? []).filter((pair) => pair.detachedAt === null);
139825
140091
  const failedPair = activePairs.find((pair) => pair.implementerThreadId === event.payload.threadId || pair.watcherThreadId === event.payload.threadId);
@@ -139834,6 +140100,11 @@ const make$3 = Effect.gen(function* () {
139834
140100
  return;
139835
140101
  }
139836
140102
  if (event.payload.state !== "completed") return;
140103
+ const watcherPair = activePairs.find((pair) => pair.watcherThreadId === event.payload.threadId);
140104
+ if (watcherPair !== void 0) yield* recordUnreportedEvidence(watcherPair, event).pipe(Effect.catchCause((cause) => Effect.logWarning("could not record an unreported Fusion evidence read", {
140105
+ pairId: watcherPair.id,
140106
+ cause: Cause.pretty(cause)
140107
+ })));
139837
140108
  const pairs = activePairs.filter((pair) => pair.implementerThreadId === event.payload.threadId && event.sequence > pair.lastReviewedImplementerSequence);
139838
140109
  yield* Effect.forEach(pairs, (pair) => catchUpPair(pair, event.sequence), {
139839
140110
  concurrency: 1,
@@ -1,4 +1,4 @@
1
- import{r as e}from"./rolldown-runtime-QTnfLwEv.js";import{n as t,r as n,t as r}from"./compiler-runtime-CLAvuQ-D.js";import{$l as i,Ba as a,Et as o,Fa as s,Ga as c,Il as l,Ja as ee,Ka as te,Ma as u,Rr as d,Ur as ne,Uu as f,Ya as p,Yr as re,_n as m,au as h,b as ie,dl as g,fl as _,gt as v,gu as ae,h as y,ht as b,ml as x,pl as oe,qa as S,st as C,uu as se,vt as w,xn as T,za as E}from"./previewAssetResource-DIMp8MLe.js";import{a as D,c as O,i as k,n as A,o as j,r as M,s as ce,t as N}from"./toggle-group-D5iDw8-4.js";import{A as le,Fr as ue,J as de,Lr as fe,M as P,Mr as pe,Nr as me,Rr as he,Y as ge,_ as _e,_r as ve,at as ye,cr as be,ct as xe,dr as Se,fr as Ce,h as we,hr as Te,it as Ee,j as De,jr as Oe,k as ke,lr as Ae,lt as je,oi as Me,or as Ne,ot as Pe,pr as Fe,rt as Ie,si as Le,sr as Re,st as ze,ur as Be,yr as Ve}from"./index-D_D9GtC6.js";import{a as He,n as Ue}from"./fileCommentAnnotations-PMEbyK4D.js";var We=x(`pilcrow`,[[`path`,{d:`M13 4v16`,key:`8vvj80`}],[`path`,{d:`M17 4v16`,key:`7dpous`}],[`path`,{d:`M19 4H9.5a4.5 4.5 0 0 0 0 9H13`,key:`sh4n9v`}]]),F=e(n(),1);function Ge({threadRef:e,filePath:t,activeCwd:n,openInEditor:r,openFileSurface:i}){if(e){if(i){i(t);return}C.getState().openFile(e,t);return}r(n?y(t,n):t)}var I=r();function Ke(e,t){let n=(0,I.c)(4),r=Te(e,t),i;return n[0]!==r.data||n[1]!==r.error||n[2]!==r.isPending?(i={data:r.data,error:r.error,isPending:r.isPending},n[0]=r.data,n[1]=r.error,n[2]=r.isPending,n[3]=i):i=n[3],i}var L=t(),qe=[];function Je(e){return(e.endSide??e.side)===`deletions`?`deletions`:`additions`}function R(e,t,n){let r=Je(t),i=e.findIndex(e=>e.side===r&&e.lineNumber===t.end);return i<0?[...e,{side:r,lineNumber:t.end,metadata:{entries:[n]}}]:e.map((e,t)=>t===i?{...e,metadata:{entries:[...e.metadata.entries,n]}}:e)}function Ye(e){let t=(0,I.c)(50),{files:n,sectionId:r,sectionTitle:i,composerDraftTarget:a,options:o,viewerRef:s,className:c,renderHeaderPrefix:l}=e,ee=d(Qe),te=d(B),u;t[0]===a?u=t[1]:(u=e=>e.getComposerDraft(a)?.reviewComments??qe,t[0]=a,t[1]=u);let f=d(u),[p,m]=(0,F.useState)(null),[h,ie]=(0,F.useState)(null),g;t[2]===n?g=t[3]:(g=new Map(n.map(Ze)),t[2]=n,t[3]=g);let _=g,v;if(t[4]!==h||t[5]!==n||t[6]!==f||t[7]!==r){let e;t[9]!==h||t[10]!==f||t[11]!==r?(e=e=>{let{fileDiff:t,filePath:n,fileKey:i,collapsed:a}=e,o=f.filter(e=>e.sectionId===r&&e.filePath===n&&(e.fenceLanguage??`diff`)===`diff`).reduce((e,n)=>{let r=re(t,n);return r?R(e,r,{id:n.id,kind:`comment`,range:r,rangeLabel:n.rangeLabel,text:n.text}):e},[]),s=h?.fileKey===i?[...o,h.annotation]:o;return{id:i,type:`diff`,fileDiff:t,annotations:s,collapsed:a,version:Ee(`${a?`1`:`0`}:${s.flatMap(z).join(`:`)}`)}},t[9]=h,t[10]=f,t[11]=r,t[12]=e):e=t[12],v=n.map(e),t[4]=h,t[5]=n,t[6]=f,t[7]=r,t[8]=v}else v=t[8];let ae=v,y;t[13]!==a||t[14]!==h?.annotation||t[15]!==te?(y=e=>{m(null),h?.annotation.metadata.entries.some(t=>t.id===e)?ie(null):te(a,e)},t[13]=a,t[14]=h?.annotation,t[15]=te,t[16]=y):y=t[16];let b=y,x;t[17]!==ee||t[18]!==a||t[19]!==h||t[20]!==_||t[21]!==r||t[22]!==i?(x=(e,t)=>{let n=h?.annotation.metadata.entries.find(t=>t.id===e),o=h?_.get(h.fileKey):void 0;if(!n||!o)return;let s=ne({id:n.id,sectionId:r,sectionTitle:i,filePath:o.filePath,fileDiff:o.fileDiff,range:n.range,text:t});s&&ee(a,s),m(null),ie(null)},t[17]=ee,t[18]=a,t[19]=h,t[20]=_,t[21]=r,t[22]=i,t[23]=x):x=t[23];let oe=x,S;t[24]!==_||t[25]!==r||t[26]!==i?(S=(e,t)=>{if(!e)return;let n=t.item;if(n.type!==`diff`)return;let a=_.get(n.id);if(!a)return;let o=Ue(),s=ne({id:o,sectionId:r,sectionTitle:i,filePath:a.filePath,fileDiff:a.fileDiff,range:e,text:``});s&&ie({fileKey:n.id,annotation:{side:Je(e),lineNumber:e.end,metadata:{entries:[{id:o,kind:`draft`,range:e,rangeLabel:s.rangeLabel,text:``}]}}})},t[24]=_,t[25]=r,t[26]=i,t[27]=S):S=t[27];let C=S,se=h!==null,w;t[28]===s?w=t[29]:(w=s?{ref:s}:{},t[28]=s,t[29]=w);let T;t[30]===c?T=t[31]:(T=c?{className:c}:{},t[30]=c,t[31]=T);let E=!se,O=!se,k;t[32]!==C||t[33]!==o||t[34]!==O||t[35]!==E?(k={...o,enableGutterUtility:E,enableLineSelection:O,onLineSelectionEnd:C},t[32]=C,t[33]=o,t[34]=O,t[35]=E,t[36]=k):k=t[36];let A;t[37]===l?A=t[38]:(A=e=>e.type===`diff`?l(e.fileDiff,e.id,e.collapsed===!0):null,t[37]=l,t[38]=A);let j;t[39]!==b||t[40]!==oe?(j=e=>(0,L.jsx)(`div`,{className:`py-1`,children:e.metadata.entries.map(e=>(0,L.jsx)(He,{kind:e.kind,rangeLabel:e.rangeLabel,text:e.text,onCancel:()=>b(e.id),onComment:t=>oe(e.id,t),onDelete:()=>b(e.id)},e.id))}),t[39]=b,t[40]=oe,t[41]=j):j=t[41];let M;return t[42]!==ae||t[43]!==p||t[44]!==k||t[45]!==A||t[46]!==j||t[47]!==w||t[48]!==T?(M=(0,L.jsx)(D,{...w,...T,items:ae,selectedLines:p,onSelectedLinesChange:m,options:k,renderHeaderPrefix:A,renderAnnotation:j}),t[42]=ae,t[43]=p,t[44]=k,t[45]=A,t[46]=j,t[47]=w,t[48]=T,t[49]=M):M=t[49],M}function z(e){return e.metadata.entries.map(Xe)}function Xe(e){return`${e.id}:${e.rangeLabel}:${e.text}`}function Ze(e){return[e.fileKey,e]}function B(e){return e.removeReviewComment}function Qe(e){return e.addReviewComment}function $e(e){return{diffPreview:i(e,{label:`environment-data:review:diff-preview`,tag:f.reviewGetDiffPreview,staleTimeMs:5e3})}}var et=$e(T);function V(e){return e.remoteName&&e.name.startsWith(`${e.remoteName}/`)?e.name.slice(e.remoteName.length+1):e.name}function tt(e,t){let n=new Set(t),r=e.map(e=>{let r=t.filter(t=>n.has(t)&&V(t)===e.name),i=r.find(e=>e.remoteName===`origin`)??r[0]??null;return i&&n.delete(i),{id:`local:${e.name}`,label:e.name,local:e,remote:i}}),i=t.filter(e=>n.has(e)).map(e=>({id:`remote:${e.name}`,label:e.name,local:null,remote:e}));return[...r,...i]}function nt(e,t){let n=t.trim().toLocaleLowerCase();return n.length===0?e:e.filter(e=>e.label.toLocaleLowerCase().includes(n)||e.local?.name.toLocaleLowerCase().includes(n)===!0||e.remote?.name.toLocaleLowerCase().includes(n)===!0)}var H=`__automatic_base_ref__`,rt=new Set,it=`
1
+ import{r as e}from"./rolldown-runtime-QTnfLwEv.js";import{n as t,r as n,t as r}from"./compiler-runtime-CLAvuQ-D.js";import{$l as i,Ba as a,Et as o,Fa as s,Ga as c,Il as l,Ja as ee,Ka as te,Ma as u,Rr as d,Ur as ne,Uu as f,Ya as p,Yr as re,_n as m,au as h,b as ie,dl as g,fl as _,gt as v,gu as ae,h as y,ht as b,ml as x,pl as oe,qa as S,st as C,uu as se,vt as w,xn as T,za as E}from"./previewAssetResource-CKOao7Zb.js";import{a as D,c as O,i as k,n as A,o as j,r as M,s as ce,t as N}from"./toggle-group-hqQeP7ri.js";import{A as le,Fr as ue,J as de,Lr as fe,M as P,Mr as pe,Nr as me,Rr as he,Y as ge,_ as _e,_r as ve,at as ye,cr as be,ct as xe,dr as Se,fr as Ce,h as we,hr as Te,it as Ee,j as De,jr as Oe,k as ke,lr as Ae,lt as je,oi as Me,or as Ne,ot as Pe,pr as Fe,rt as Ie,si as Le,sr as Re,st as ze,ur as Be,yr as Ve}from"./index-CL8KBlld.js";import{a as He,n as Ue}from"./fileCommentAnnotations-CoOCi5GC.js";var We=x(`pilcrow`,[[`path`,{d:`M13 4v16`,key:`8vvj80`}],[`path`,{d:`M17 4v16`,key:`7dpous`}],[`path`,{d:`M19 4H9.5a4.5 4.5 0 0 0 0 9H13`,key:`sh4n9v`}]]),F=e(n(),1);function Ge({threadRef:e,filePath:t,activeCwd:n,openInEditor:r,openFileSurface:i}){if(e){if(i){i(t);return}C.getState().openFile(e,t);return}r(n?y(t,n):t)}var I=r();function Ke(e,t){let n=(0,I.c)(4),r=Te(e,t),i;return n[0]!==r.data||n[1]!==r.error||n[2]!==r.isPending?(i={data:r.data,error:r.error,isPending:r.isPending},n[0]=r.data,n[1]=r.error,n[2]=r.isPending,n[3]=i):i=n[3],i}var L=t(),qe=[];function Je(e){return(e.endSide??e.side)===`deletions`?`deletions`:`additions`}function R(e,t,n){let r=Je(t),i=e.findIndex(e=>e.side===r&&e.lineNumber===t.end);return i<0?[...e,{side:r,lineNumber:t.end,metadata:{entries:[n]}}]:e.map((e,t)=>t===i?{...e,metadata:{entries:[...e.metadata.entries,n]}}:e)}function Ye(e){let t=(0,I.c)(50),{files:n,sectionId:r,sectionTitle:i,composerDraftTarget:a,options:o,viewerRef:s,className:c,renderHeaderPrefix:l}=e,ee=d(Qe),te=d(B),u;t[0]===a?u=t[1]:(u=e=>e.getComposerDraft(a)?.reviewComments??qe,t[0]=a,t[1]=u);let f=d(u),[p,m]=(0,F.useState)(null),[h,ie]=(0,F.useState)(null),g;t[2]===n?g=t[3]:(g=new Map(n.map(Ze)),t[2]=n,t[3]=g);let _=g,v;if(t[4]!==h||t[5]!==n||t[6]!==f||t[7]!==r){let e;t[9]!==h||t[10]!==f||t[11]!==r?(e=e=>{let{fileDiff:t,filePath:n,fileKey:i,collapsed:a}=e,o=f.filter(e=>e.sectionId===r&&e.filePath===n&&(e.fenceLanguage??`diff`)===`diff`).reduce((e,n)=>{let r=re(t,n);return r?R(e,r,{id:n.id,kind:`comment`,range:r,rangeLabel:n.rangeLabel,text:n.text}):e},[]),s=h?.fileKey===i?[...o,h.annotation]:o;return{id:i,type:`diff`,fileDiff:t,annotations:s,collapsed:a,version:Ee(`${a?`1`:`0`}:${s.flatMap(z).join(`:`)}`)}},t[9]=h,t[10]=f,t[11]=r,t[12]=e):e=t[12],v=n.map(e),t[4]=h,t[5]=n,t[6]=f,t[7]=r,t[8]=v}else v=t[8];let ae=v,y;t[13]!==a||t[14]!==h?.annotation||t[15]!==te?(y=e=>{m(null),h?.annotation.metadata.entries.some(t=>t.id===e)?ie(null):te(a,e)},t[13]=a,t[14]=h?.annotation,t[15]=te,t[16]=y):y=t[16];let b=y,x;t[17]!==ee||t[18]!==a||t[19]!==h||t[20]!==_||t[21]!==r||t[22]!==i?(x=(e,t)=>{let n=h?.annotation.metadata.entries.find(t=>t.id===e),o=h?_.get(h.fileKey):void 0;if(!n||!o)return;let s=ne({id:n.id,sectionId:r,sectionTitle:i,filePath:o.filePath,fileDiff:o.fileDiff,range:n.range,text:t});s&&ee(a,s),m(null),ie(null)},t[17]=ee,t[18]=a,t[19]=h,t[20]=_,t[21]=r,t[22]=i,t[23]=x):x=t[23];let oe=x,S;t[24]!==_||t[25]!==r||t[26]!==i?(S=(e,t)=>{if(!e)return;let n=t.item;if(n.type!==`diff`)return;let a=_.get(n.id);if(!a)return;let o=Ue(),s=ne({id:o,sectionId:r,sectionTitle:i,filePath:a.filePath,fileDiff:a.fileDiff,range:e,text:``});s&&ie({fileKey:n.id,annotation:{side:Je(e),lineNumber:e.end,metadata:{entries:[{id:o,kind:`draft`,range:e,rangeLabel:s.rangeLabel,text:``}]}}})},t[24]=_,t[25]=r,t[26]=i,t[27]=S):S=t[27];let C=S,se=h!==null,w;t[28]===s?w=t[29]:(w=s?{ref:s}:{},t[28]=s,t[29]=w);let T;t[30]===c?T=t[31]:(T=c?{className:c}:{},t[30]=c,t[31]=T);let E=!se,O=!se,k;t[32]!==C||t[33]!==o||t[34]!==O||t[35]!==E?(k={...o,enableGutterUtility:E,enableLineSelection:O,onLineSelectionEnd:C},t[32]=C,t[33]=o,t[34]=O,t[35]=E,t[36]=k):k=t[36];let A;t[37]===l?A=t[38]:(A=e=>e.type===`diff`?l(e.fileDiff,e.id,e.collapsed===!0):null,t[37]=l,t[38]=A);let j;t[39]!==b||t[40]!==oe?(j=e=>(0,L.jsx)(`div`,{className:`py-1`,children:e.metadata.entries.map(e=>(0,L.jsx)(He,{kind:e.kind,rangeLabel:e.rangeLabel,text:e.text,onCancel:()=>b(e.id),onComment:t=>oe(e.id,t),onDelete:()=>b(e.id)},e.id))}),t[39]=b,t[40]=oe,t[41]=j):j=t[41];let M;return t[42]!==ae||t[43]!==p||t[44]!==k||t[45]!==A||t[46]!==j||t[47]!==w||t[48]!==T?(M=(0,L.jsx)(D,{...w,...T,items:ae,selectedLines:p,onSelectedLinesChange:m,options:k,renderHeaderPrefix:A,renderAnnotation:j}),t[42]=ae,t[43]=p,t[44]=k,t[45]=A,t[46]=j,t[47]=w,t[48]=T,t[49]=M):M=t[49],M}function z(e){return e.metadata.entries.map(Xe)}function Xe(e){return`${e.id}:${e.rangeLabel}:${e.text}`}function Ze(e){return[e.fileKey,e]}function B(e){return e.removeReviewComment}function Qe(e){return e.addReviewComment}function $e(e){return{diffPreview:i(e,{label:`environment-data:review:diff-preview`,tag:f.reviewGetDiffPreview,staleTimeMs:5e3})}}var et=$e(T);function V(e){return e.remoteName&&e.name.startsWith(`${e.remoteName}/`)?e.name.slice(e.remoteName.length+1):e.name}function tt(e,t){let n=new Set(t),r=e.map(e=>{let r=t.filter(t=>n.has(t)&&V(t)===e.name),i=r.find(e=>e.remoteName===`origin`)??r[0]??null;return i&&n.delete(i),{id:`local:${e.name}`,label:e.name,local:e,remote:i}}),i=t.filter(e=>n.has(e)).map(e=>({id:`remote:${e.name}`,label:e.name,local:null,remote:e}));return[...r,...i]}function nt(e,t){let n=t.trim().toLocaleLowerCase();return n.length===0?e:e.filter(e=>e.label.toLocaleLowerCase().includes(n)||e.local?.name.toLocaleLowerCase().includes(n)===!0||e.remote?.name.toLocaleLowerCase().includes(n)===!0)}var H=`__automatic_base_ref__`,rt=new Set,it=`
2
2
  [data-diffs-header],
3
3
  [data-diff],
4
4
  [data-file],
@@ -95,4 +95,4 @@ import{r as e}from"./rolldown-runtime-QTnfLwEv.js";import{n as t,r as n,t as r}f
95
95
  text-decoration-color: currentColor;
96
96
  }
97
97
  `;function U({mode:e=`inline`,composerDraftTarget:t,initialGitScope:n,threadRef:r}){let{resolvedTheme:i}=ie(),d=ue(),[ne]=(0,F.useState)(n),[f,re]=(0,F.useState)(`stacked`),[y,x]=(0,F.useState)(d.wordWrap),[C,T]=(0,F.useState)(d.diffIgnoreWhitespace),[D,_e]=(0,F.useState)(``),[Te,Ee]=(0,F.useState)(()=>({scopeKey:null,fileKeys:rt})),He=(0,F.useRef)(null),Ue=r.threadId,I=me(r),qe=I?.projectId??null,Je=pe(I&&qe?{environmentId:I.environmentId,projectId:qe}:null),R=I?.worktreePath??Je?.workspaceRoot,z=l(m.configValueAtom(I?.environmentId??null)),Xe=ve(I?.environmentId??null,z?.availableEditors??[]),Ze=o(I!=null&&R!=null?Oe.status({environmentId:I.environmentId,input:{cwd:R}}):null),B=P(e=>De(e.byThreadKey,r,ne===`unstaged`)),Qe=Ze.data?.isRepo??!0,{turnDiffSummaries:$e,inferredCheckpointTurnCountByTurnId:V}=le(I),U=(0,F.useMemo)(()=>[...$e].toSorted((e,t)=>{let n=e.checkpointTurnCount??V[e.turnId]??0,r=t.checkpointTurnCount??V[t.turnId]??0;return n===r?t.completedAt.localeCompare(e.completedAt):r-n}),[V,$e]);(0,F.useEffect)(()=>{B.kind===`turn`&&P.getState().reconcileTurnSelection(r,U.map(e=>e.turnId))},[B,U,r]);let W=B.kind===`turn`?B.turnId:null,G=B.kind===`unstaged`?`unstaged`:`branch`,K=B.kind===`branch`?B.baseRef:null,at=B.kind===`turn`?B.filePath:null,ot=B.kind===`turn`?B.revealRequestId:0,q=W===null?void 0:U.find(e=>e.turnId===W)??U[0],J=q&&(q.checkpointTurnCount??V[q.turnId]),st=U[0],ct=W===null?G===`unstaged`?`Working tree`:`Branch changes`:q?.turnId===st?.turnId?`Latest turn`:`Turn ${J??`?`}`,lt=q?`turn:${q.turnId}`:G,Y=`${r.environmentId}:${r.threadId}:${lt}`,ut=Te.scopeKey===Y?Te.fileKeys:rt,dt=q?`Turn ${J??`?`}`:G===`unstaged`?`Working tree`:`Branch changes`,ft=(0,F.useMemo)(()=>typeof J==`number`?{fromTurnCount:Math.max(0,J-1),toTurnCount:J}:null,[J]),pt=Ke({environmentId:I?.environmentId??null,threadId:Ue,fromTurnCount:ft?.fromTurnCount??null,toTurnCount:ft?.toTurnCount??null,ignoreWhitespace:C,cacheScope:q?`turn:${q.turnId}`:null},{enabled:Qe&&q!==void 0}),mt=o(W===null&&I&&R?et.diffPreview({environmentId:I.environmentId,input:{cwd:R,...K?{baseRef:K}:{},ignoreWhitespace:C}}):null),ht=W===null&&mt.error?.includes(`configured workspace root`)===!0&&z?.cwd!==void 0&&z.cwd!==R,gt=o(ht&&I&&z?et.diffPreview({environmentId:I.environmentId,input:{cwd:z.cwd,...K?{baseRef:K}:{},ignoreWhitespace:C}}):null),X=ht?gt:mt,Z=X.data?.sources.find(e=>e.kind===(G===`unstaged`?`working-tree`:`branch-range`)),_t=o(W===null&&G===`branch`&&I&&X.data?.cwd?Oe.listRefs({environmentId:I.environmentId,input:{cwd:X.data.cwd,includeMatchingRemoteRefs:!0,refKind:`local`,...D.trim().length>0?{query:D.trim()}:{},limit:100}}):null),vt=o(W===null&&G===`branch`&&I&&X.data?.cwd?Oe.listRefs({environmentId:I.environmentId,input:{cwd:X.data.cwd,includeMatchingRemoteRefs:!0,refKind:`remote`,...D.trim().length>0?{query:D.trim()}:{},limit:100}}):null),yt=tt(_t.data?.refs.filter(e=>e.name!==Z?.headRef)??[],vt.data?.refs??[]),bt=nt(yt,D),xt=e=>K&&K===e.remote?.name?K:e.local?.name??e.remote?.name??e.id,St=[H,...yt.map(xt)],Ct=[...D.trim().length===0?[H]:[],...bt.map(xt)],wt=Z?.diff,Tt=q?pt.data?.diff:wt,Et=!q&&Z?.truncated===!0,Dt=q?pt.isPending:X.isPending,Ot=q?pt.error:X.error,kt=typeof Tt==`string`&&Tt.trim().length===0,Q=(0,F.useMemo)(()=>ze(Tt,`diff-panel:${i}`,{compactPartialHunkOffsets:W===null}),[i,Tt,W]),At=(0,F.useMemo)(()=>!Q||Q.kind!==`files`?[]:Q.files.toSorted((e,t)=>je(e).localeCompare(je(t),void 0,{numeric:!0,sensitivity:`base`})),[Q]),$=(0,F.useMemo)(()=>At.map(e=>{let t=Ie(e);return{fileDiff:e,filePath:je(e),fileKey:t,collapsed:ut.has(t)}}),[ut,At]),jt=(0,F.useMemo)(()=>$.map(e=>e.fileKey),[$]),Mt=M(jt,ut),Nt=(0,F.useMemo)(()=>Pe(At),[At]);(0,F.useEffect)(()=>{if(!at)return;let e=$.find(e=>e.filePath===at);e&&He.current?.scrollTo({type:`item`,id:e.fileKey,align:`start`})},[$,at,ot]);let Pt=ke({threadRef:r,workspaceRoot:R??null}),Ft=(0,F.useCallback)(e=>{Ge({threadRef:r,filePath:e,activeCwd:R,openFileSurface:Pt,openInEditor:e=>{(async()=>{let t=await Xe(e);t._tag===`Failure`&&!h(t)&&console.warn(`Failed to open diff file in editor.`,{operation:`open-diff-file`,environmentId:r.environmentId,threadId:r.threadId,...ae(se(t))})})()}})},[R,Pt,Xe,r]),It=(0,F.useCallback)(e=>{Ee(t=>{let n=new Set(t.scopeKey===Y?t.fileKeys:[]);return n.has(e)?n.delete(e):n.add(e),{scopeKey:Y,fileKeys:n}})},[Y]),Lt=(0,F.useCallback)(()=>{Ee(e=>{let t=e.scopeKey===Y?e.fileKeys:rt;return{scopeKey:Y,fileKeys:k(jt,t)}})},[Y,jt]),Rt=e=>{P.getState().selectTurn(r,e)},zt=e=>{P.getState().selectGitScope(r,e)},Bt=e=>{P.getState().selectBranchBaseRef(r,e)};return(0,L.jsx)(ge,{mode:e,header:(0,L.jsxs)(L.Fragment,{children:[(0,L.jsxs)(`div`,{className:`flex min-w-0 flex-1 items-center gap-3 [-webkit-app-region:no-drag]`,children:[(0,L.jsxs)(s,{children:[(0,L.jsxs)(ee,{className:`inline-flex h-6 max-w-full items-center gap-1 rounded-md bg-muted/70 px-2 text-xs font-medium text-foreground outline-none transition-colors hover:bg-muted focus-visible:ring-2 focus-visible:ring-ring`,"aria-label":`Diff scope: ${ct}`,children:[(0,L.jsx)(`span`,{className:`truncate`,children:ct}),(0,L.jsx)(_,{className:`size-3.5 shrink-0 text-muted-foreground`})]}),(0,L.jsxs)(a,{align:`start`,className:`w-60`,children:[(0,L.jsx)(E,{className:W===null&&G===`unstaged`?`bg-foreground/[0.08]`:void 0,onClick:()=>zt(`unstaged`),children:(0,L.jsx)(`span`,{children:`Working tree`})}),(0,L.jsx)(E,{className:W===null&&G===`branch`?`bg-foreground/[0.08]`:void 0,onClick:()=>zt(`branch`),children:(0,L.jsx)(`span`,{children:`Branch changes`})}),(0,L.jsx)(E,{className:W!==null&&q?.turnId===st?.turnId?`bg-foreground/[0.08]`:void 0,onClick:()=>{st&&Rt(st.turnId)},children:(0,L.jsx)(`span`,{children:`Latest turn`})}),(0,L.jsxs)(c,{children:[(0,L.jsx)(S,{children:`Turn`}),(0,L.jsx)(te,{className:`w-64`,children:U.map(e=>{let t=e.checkpointTurnCount??V[e.turnId]??`?`;return(0,L.jsxs)(E,{className:e.turnId===q?.turnId?`bg-foreground/[0.08]`:void 0,onClick:()=>Rt(e.turnId),children:[(0,L.jsxs)(`span`,{children:[`Turn `,t]}),(0,L.jsx)(`span`,{className:`ml-auto text-xs tabular-nums text-muted-foreground`,children:Ve(e.completedAt,d.timestampFormat)})]},e.turnId)})})]})]})]}),W===null&&G===`branch`&&Z?.baseRef&&(0,L.jsxs)(`div`,{className:`flex min-w-0 max-w-full items-center gap-2 overflow-hidden text-xs text-muted-foreground`,title:`${Z.headRef??`HEAD`} → ${Z.baseRef}`,"aria-label":`Comparing ${Z.headRef??`HEAD`} against ${Z.baseRef}`,children:[(0,L.jsx)(`span`,{className:`min-w-0 max-w-48 truncate`,children:Z.headRef??`HEAD`}),(0,L.jsx)(Le,{className:`size-3.5 shrink-0 opacity-70`}),(0,L.jsxs)(Ne,{items:St,filteredItems:Ct,value:K??H,onOpenChange:e=>{e||_e(``)},onValueChange:e=>{e&&Bt(e===H?null:e)},children:[(0,L.jsxs)(Ce,{className:`inline-flex min-w-0 max-w-48 items-center gap-1 overflow-hidden rounded-md px-1.5 py-1 outline-none transition-colors hover:bg-muted hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring`,"aria-label":`Change comparison target. Currently ${Z.baseRef}`,children:[(0,L.jsx)(`span`,{className:`min-w-0 truncate`,children:Z.baseRef}),(0,L.jsx)(_,{className:`size-3.5 shrink-0 opacity-70`})]}),(0,L.jsxs)(Se,{align:`start`,className:`w-72 min-w-0 max-w-[calc(100vw-1rem)] overflow-hidden [&>[data-slot=combobox-popup]]:min-w-0 [&>[data-slot=combobox-popup]]:overflow-hidden`,children:[(0,L.jsx)(`div`,{className:`min-w-0 shrink-0 px-3 pt-2.5`,children:(0,L.jsxs)(`div`,{className:`relative -translate-y-px border-b border-border/70 pb-1.5 transition-colors focus-within:border-ring`,children:[(0,L.jsx)(he,{"aria-hidden":`true`,className:`pointer-events-none absolute top-1.5 left-0 size-4 shrink-0 text-muted-foreground/55`}),(0,L.jsx)(be,{className:`[&_input]:h-6.5 [&_input]:ps-5 [&_input]:font-sans [&_input]:leading-6.5`,inputClassName:`rounded-none bg-transparent text-sm`,placeholder:`Search refs...`,showTrigger:!1,size:`sm`,unstyled:!0,value:D,onChange:e=>_e(e.target.value)})]})}),(0,L.jsxs)(`div`,{className:`grid shrink-0 grid-cols-[1rem_minmax(0,1fr)] items-center gap-2 border-b border-border/70 ps-3 pe-6.5 pt-2 pb-1.5 font-medium text-[10px] text-muted-foreground uppercase tracking-wide`,children:[(0,L.jsx)(`span`,{"aria-hidden":`true`}),(0,L.jsxs)(`div`,{className:`grid min-w-0 grid-cols-[minmax(0,1fr)_2rem] items-center`,children:[(0,L.jsx)(`span`,{children:`Branch`}),(0,L.jsx)(`span`,{className:`text-right`,children:`Remote`})]})]}),(0,L.jsx)(Re,{children:`No matching refs.`}),(0,L.jsxs)(Be,{className:`max-h-64 min-w-0 overflow-x-hidden`,children:[(0,L.jsx)(Ae,{className:`h-8 w-full min-w-0 grid-cols-[1rem_minmax(0,1fr)] py-0`,contentClassName:`w-full min-w-0 overflow-hidden`,value:H,children:(0,L.jsx)(`span`,{className:`block min-w-0 truncate`,children:`Automatic`})}),yt.map(e=>{let t=xt(e),n=e.local!==null&&e.remote!==null,r=e.remote?.name===t;return(0,L.jsx)(Ae,{className:`h-8 w-full min-w-0 grid-cols-[1rem_minmax(0,1fr)] py-0`,contentClassName:`w-full min-w-0 overflow-hidden`,value:t,children:(0,L.jsxs)(`div`,{className:`grid w-full min-w-0 grid-cols-[minmax(0,1fr)_2rem] items-center overflow-hidden`,children:[(0,L.jsx)(`span`,{className:`block min-w-0 truncate pe-2`,children:e.label}),n?(0,L.jsx)(`div`,{className:`flex justify-end`,onClick:e=>e.stopPropagation(),onPointerDown:e=>e.stopPropagation(),children:(0,L.jsx)(Fe,{"aria-label":`Use remote version of ${e.label}`,checked:r,className:`[--thumb-size:--spacing(3)]`,onCheckedChange:t=>{let n=t?e.remote?.name:e.local?.name;n&&Bt(n)}})}):e.remote?(0,L.jsx)(`span`,{className:`flex justify-end text-muted-foreground`,title:`Remote only`,children:(0,L.jsx)(oe,{"aria-hidden":`true`,className:`size-3`})}):null]})},e.id)})]})]})]})]})]}),(0,L.jsxs)(`div`,{className:`flex shrink-0 items-center gap-1 [-webkit-app-region:no-drag]`,children:[$.length>0&&(0,L.jsx)(we,{additions:Nt.additions,deletions:Nt.deletions,className:`mr-1 text-[11px]`,layout:`inline`}),$.length>0&&(0,L.jsxs)(b,{children:[(0,L.jsx)(w,{render:(0,L.jsx)(u,{type:`button`,size:`icon-xs`,variant:`outline`,"aria-label":Mt?`Expand all files`:`Collapse all files`,onClick:Lt}),children:Mt?(0,L.jsx)(Me,{className:`size-3`}):(0,L.jsx)(O,{className:`size-3`})}),(0,L.jsx)(v,{side:`top`,children:Mt?`Expand all files`:`Collapse all files`})]}),(0,L.jsxs)(A,{className:`shrink-0`,variant:`outline`,size:`xs`,value:[f],onValueChange:e=>{let t=e[0];(t===`stacked`||t===`split`)&&re(t)},children:[(0,L.jsx)(N,{"aria-label":`Stacked diff view`,value:`stacked`,children:(0,L.jsx)(j,{className:`size-3`})}),(0,L.jsx)(N,{"aria-label":`Split diff view`,value:`split`,children:(0,L.jsx)(ce,{className:`size-3`})})]}),(0,L.jsxs)(b,{children:[(0,L.jsx)(w,{render:(0,L.jsx)(N,{"aria-label":y?`Disable diff line wrapping`:`Enable diff line wrapping`,variant:`outline`,size:`xs`,pressed:y,onPressedChange:e=>{x(!!e)}}),children:(0,L.jsx)(fe,{className:`size-3`})}),(0,L.jsx)(v,{side:`top`,children:y?`Disable line wrapping`:`Enable line wrapping`})]}),(0,L.jsxs)(b,{children:[(0,L.jsx)(w,{render:(0,L.jsx)(N,{"aria-label":C?`Show whitespace changes`:`Hide whitespace changes`,variant:`outline`,size:`xs`,pressed:C,onPressedChange:e=>{T(!!e)}}),children:(0,L.jsx)(We,{className:`size-3`})}),(0,L.jsx)(v,{side:`top`,children:C?`Show whitespace changes`:`Hide whitespace changes`})]})]})]}),children:I?Qe?W!==null&&U.length===0?(0,L.jsx)(`div`,{className:`flex flex-1 items-center justify-center px-5 text-center text-xs text-muted-foreground/70`,children:`No completed turns yet.`}):(0,L.jsx)(L.Fragment,{children:(0,L.jsxs)(`div`,{className:`diff-panel-viewport flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden`,children:[Et&&(0,L.jsx)(`p`,{className:`shrink-0 border-b border-border/70 bg-muted/40 px-3 py-1.5 text-[11px] text-muted-foreground`,children:`This diff was truncated because it exceeded the preview limit. The changes shown are incomplete.`}),Ot&&!Q&&(0,L.jsx)(`div`,{className:`px-3`,children:(0,L.jsx)(`p`,{className:`mb-2 text-[11px] text-red-500/80`,children:Ot})}),Q?Q.kind===`files`?(0,L.jsx)(`div`,{className:`min-h-0 flex-1`,onClickCapture:e=>{let t=(e.nativeEvent.composedPath?.()??[]).find(e=>e instanceof HTMLElement&&e.hasAttribute(`data-title`))?.textContent?.trim();t&&Ft(t)},children:(0,L.jsx)(Ye,{viewerRef:He,className:`diff-render-surface h-full min-h-0 overflow-auto`,files:$,sectionId:lt,sectionTitle:dt,composerDraftTarget:t,renderHeaderPrefix:(e,t,n)=>{let r=je(e);return(0,L.jsxs)(b,{children:[(0,L.jsx)(w,{render:(0,L.jsx)(`button`,{type:`button`,className:p(`inline-flex size-5 shrink-0 cursor-pointer items-center justify-center rounded-sm border-0 bg-transparent p-0 transition-colors hover:bg-foreground/10 focus-visible:outline-hidden`,ye(e)),"aria-label":n?`Expand ${r}`:`Collapse ${r}`,"aria-expanded":!n,onClick:e=>{e.stopPropagation(),It(t)}}),children:n?(0,L.jsx)(g,{className:`size-4`}):(0,L.jsx)(_,{className:`size-4`})}),(0,L.jsx)(v,{side:`top`,children:n?`Expand diff`:`Collapse diff`})]})},options:{diffStyle:f===`split`?`split`:`unified`,lineDiffType:`none`,overflow:y?`wrap`:`scroll`,theme:xe(i),themeType:i,unsafeCSS:it,stickyHeaders:!0,itemMetrics:{diffHeaderHeight:33},layout:{paddingTop:0,paddingBottom:8,gap:8}}},Y??lt)}):(0,L.jsx)(`div`,{className:`min-h-0 flex-1 overflow-auto p-2`,children:(0,L.jsxs)(`div`,{className:`space-y-2`,children:[(0,L.jsx)(`p`,{className:`text-[11px] text-muted-foreground/75`,children:Q.reason}),(0,L.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`,y?`overflow-auto whitespace-pre-wrap wrap-break-word`:`overflow-auto`),children:Q.text})]})}):Dt?(0,L.jsx)(de,{label:q?`Loading checkpoint diff...`:G===`unstaged`?`Loading working tree diff...`:`Loading branch diff...`}):(0,L.jsx)(`div`,{className:`flex h-full items-center justify-center px-3 py-2 text-xs text-muted-foreground/70`,children:(0,L.jsx)(`p`,{children:kt?`No net changes in this selection.`:`No patch available for this selection.`})})]})}):(0,L.jsx)(`div`,{className:`flex flex-1 items-center justify-center px-5 text-center text-xs text-muted-foreground/70`,children:`Turn diffs are unavailable because this project is not a git repository.`}):(0,L.jsx)(`div`,{className:`flex flex-1 items-center justify-center px-5 text-center text-xs text-muted-foreground/70`,children:`Select a thread to inspect turn diffs.`})})}export{_e as DiffWorkerPoolProvider,U as default};
98
- //# sourceMappingURL=DiffPanel-Y_5Ia30d.js.map
98
+ //# sourceMappingURL=DiffPanel-BnLuM3jo.js.map