@p4code/cli 0.2.15 → 0.2.17

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
@@ -33,6 +33,7 @@ import * as HttpApiMiddleware from "effect/unstable/httpapi/HttpApiMiddleware";
33
33
  import * as HttpServerRespondable$1 from "effect/unstable/http/HttpServerRespondable";
34
34
  import * as HttpServerResponse$1 from "effect/unstable/http/HttpServerResponse";
35
35
  import * as SchemaIssue from "effect/SchemaIssue";
36
+ import * as SchemaGetter from "effect/SchemaGetter";
36
37
  import * as Struct from "effect/Struct";
37
38
  import { Schema } from "effect";
38
39
  import * as Rpc from "effect/unstable/rpc/Rpc";
@@ -52,7 +53,6 @@ import * as PlatformError from "effect/PlatformError";
52
53
  import * as Migrator from "effect/unstable/sql/Migrator";
53
54
  import * as Cause from "effect/Cause";
54
55
  import * as Exit from "effect/Exit";
55
- import * as SchemaGetter from "effect/SchemaGetter";
56
56
  import * as Config from "effect/Config";
57
57
  import * as NodeReadline from "node:readline";
58
58
  import * as Clock from "effect/Clock";
@@ -238,7 +238,7 @@ const make$89 = () => {
238
238
  const layer$80 = Layer.sync(NetService, make$89);
239
239
  //#endregion
240
240
  //#region package.json
241
- var version = "0.2.15";
241
+ var version = "0.2.17";
242
242
  //#endregion
243
243
  //#region src/config.ts
244
244
  /**
@@ -1725,12 +1725,25 @@ const RuntimeMode = Schema$1.Literals([
1725
1725
  const DEFAULT_RUNTIME_MODE$2 = "full-access";
1726
1726
  const ProviderInteractionMode = Schema$1.Literals(["default", "plan"]);
1727
1727
  const DEFAULT_PROVIDER_INTERACTION_MODE = "default";
1728
- const CompressMode = Schema$1.Literals([
1728
+ const COMPRESS_MODE_VALUES = [
1729
1729
  "off",
1730
1730
  "lite",
1731
1731
  "full",
1732
- "ultra"
1733
- ]);
1732
+ "ultra",
1733
+ "wenyan"
1734
+ ];
1735
+ const CompressModeLiteral = Schema$1.Literals(COMPRESS_MODE_VALUES);
1736
+ /**
1737
+ * Tolerant on the wire: an unknown mode decodes to the default instead of
1738
+ * failing the whole payload, so a client one release behind keeps rendering
1739
+ * threads that use a mode it does not know yet. Encoding stays the strict
1740
+ * literal set. (Clients shipped before this tolerance still decode strictly;
1741
+ * adding a mode remains a breaking change for them.)
1742
+ */
1743
+ const CompressMode = Schema$1.String.pipe(Schema$1.decodeTo(CompressModeLiteral, {
1744
+ decode: SchemaGetter.transform((raw) => COMPRESS_MODE_VALUES.includes(raw) ? raw : "full"),
1745
+ encode: SchemaGetter.passthrough({ strict: false })
1746
+ }));
1734
1747
  const DEFAULT_COMPRESS_MODE = "full";
1735
1748
  const ProviderRequestKind = Schema$1.Literals([
1736
1749
  "command",
@@ -5633,6 +5646,7 @@ const ContextMenuItemSchema = Schema$1.Struct({
5633
5646
  destructive: Schema$1.optionalKey(Schema$1.Boolean),
5634
5647
  disabled: Schema$1.optionalKey(Schema$1.Boolean),
5635
5648
  header: Schema$1.optionalKey(Schema$1.Boolean),
5649
+ separator: Schema$1.optionalKey(Schema$1.Boolean),
5636
5650
  icon: Schema$1.optionalKey(Schema$1.String),
5637
5651
  children: Schema$1.optionalKey(Schema$1.Array(Schema$1.suspend(() => ContextMenuItemSchema)))
5638
5652
  });
@@ -7859,6 +7873,7 @@ const EnvironmentIdentificationMode = Schema$1.Literals([
7859
7873
  ]);
7860
7874
  const ClientSettingsSchema = Schema$1.Struct({
7861
7875
  autoOpenPlanSidebar: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(false))),
7876
+ composerControlsExpanded: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
7862
7877
  confirmThreadArchive: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(false))),
7863
7878
  confirmThreadDelete: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
7864
7879
  dismissedProviderUpdateNotificationKeys: Schema$1.Array(TrimmedNonEmptyString).pipe(Schema$1.withDecodingDefault(Effect.succeed([]))),
@@ -7873,6 +7888,7 @@ const ClientSettingsSchema = Schema$1.Struct({
7873
7888
  hiddenModels: Schema$1.Array(Schema$1.String).pipe(Schema$1.withDecodingDefault(Effect.succeed([]))),
7874
7889
  modelOrder: Schema$1.Array(Schema$1.String).pipe(Schema$1.withDecodingDefault(Effect.succeed([])))
7875
7890
  })).pipe(Schema$1.withDecodingDefault(Effect.succeed({}))),
7891
+ showBuildModeToggle: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(false))),
7876
7892
  sidebarAutoSettleAfterDays: Schema$1.NullOr(SidebarAutoSettleAfterDays).pipe(Schema$1.withDecodingDefault(Effect.succeed(3))),
7877
7893
  sidebarProjectGroupingMode: SidebarProjectGroupingMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_SIDEBAR_PROJECT_GROUPING_MODE))),
7878
7894
  sidebarProjectGroupingOverrides: Schema$1.Record(TrimmedNonEmptyString, SidebarProjectGroupingMode).pipe(Schema$1.withDecodingDefault(Effect.succeed({}))),
@@ -8295,6 +8311,7 @@ const ServerSettingsPatch = Schema$1.Struct({
8295
8311
  });
8296
8312
  Schema$1.Struct({
8297
8313
  autoOpenPlanSidebar: Schema$1.optionalKey(Schema$1.Boolean),
8314
+ composerControlsExpanded: Schema$1.optionalKey(Schema$1.Boolean),
8298
8315
  confirmThreadArchive: Schema$1.optionalKey(Schema$1.Boolean),
8299
8316
  confirmThreadDelete: Schema$1.optionalKey(Schema$1.Boolean),
8300
8317
  diffIgnoreWhitespace: Schema$1.optionalKey(Schema$1.Boolean),
@@ -8308,6 +8325,7 @@ Schema$1.Struct({
8308
8325
  hiddenModels: Schema$1.Array(Schema$1.String).pipe(Schema$1.withDecodingDefault(Effect.succeed([]))),
8309
8326
  modelOrder: Schema$1.Array(Schema$1.String).pipe(Schema$1.withDecodingDefault(Effect.succeed([])))
8310
8327
  }))),
8328
+ showBuildModeToggle: Schema$1.optionalKey(Schema$1.Boolean),
8311
8329
  sidebarAutoSettleAfterDays: Schema$1.optionalKey(Schema$1.NullOr(SidebarAutoSettleAfterDays)),
8312
8330
  sidebarProjectGroupingMode: Schema$1.optionalKey(SidebarProjectGroupingMode),
8313
8331
  sidebarProjectGroupingOverrides: Schema$1.optionalKey(Schema$1.Record(TrimmedNonEmptyString, SidebarProjectGroupingMode)),
@@ -21956,22 +21974,45 @@ Example - "Explain database connection pooling."
21956
21974
  "Pool reuses open DB connections. No new connection per request. Skips handshake overhead."`,
21957
21975
  ultra: `## Response compression: ultra
21958
21976
 
21959
- ${COMPRESS_SHARED_RULES}
21977
+ Active every response. A later style instruction replaces this block: obey the most recent one. Never name or announce the style.
21960
21978
 
21961
- ## Intensity: ultra
21979
+ Invariants, always:
21980
+ - Never drop not/never/no/only/except. Numbers, units, error strings, code, API and CLI names byte-exact. Code blocks untouched.
21981
+ - Destructive or irreversible requests (data deletion, prod mutations, force-push, secret exposure) always open with a labeled warning block in normal, complete sentences - even if asked to skip it. Format: "**Warning:** This permanently deletes all rows in \`users\` and cannot be undone." Same normal prose for genuine ambiguity and for anything persisted outside the chat (code, comments, commits, PR/issue text, docs, messages to third parties). Then resume.
21982
+ - Reply in the user's language; keep case/role markers where grammar needs them. No invented abbreviations, no -> arrows in prose.
21962
21983
 
21963
- Drop articles, fragments OK, short synonyms. Also strip conjunctions when cause-then-effect stays unambiguous. One word when one word is enough. State each fact once. Still no invented abbreviations (cfg/impl/req/res/fn/auth) and still no arrows (X -> Y): both measure as zero token saving and cost decode clarity. Code symbols, function names, API names, error strings: never touch.
21984
+ Intensity: minimum sufficient answer. No intro, no recap, no offers, no optional context. Each fact once, and named facts from the request stay named (say SQLite, not "an embedded database"). Fragments; drop articles and conjunctions. At most 3 lines unless the answer is code or a required warning. One word when one word answers. Stop the moment the request is satisfied.
21964
21985
 
21965
21986
  Example - "Why does my React component re-render?"
21966
- "Inline object prop, new ref, re-render. \`useMemo\`."
21987
+ "Inline object prop, new ref, re-render. \`useMemo\`."`,
21988
+ wenyan: `## Response compression: wenyan
21967
21989
 
21968
- Example - "Explain database connection pooling."
21969
- "Pool reuses open DB connections. No per-request handshake."`
21990
+ Active every response. A later style instruction replaces this block: obey the most recent one. Never name or announce the style.
21991
+
21992
+ Prose in Classical Chinese (文言文), maximally terse - this mode deliberately overrides the usual keep-the-user's-language rule for prose; the user chose it knowingly.
21993
+
21994
+ Invariants, always:
21995
+ - Code, code blocks, API names, CLI commands, file paths, identifiers, error strings: byte-exact, never translated. Numbers and units exact, always Arabic digits (3, never 三). Open the answer with an anchor line naming every user-supplied exact token verbatim - file paths, error strings, identifiers, numbers - then explain. Terseness never drops them; the anchor line does not count against the line budget.
21996
+ - Never drop or soften negations; 不/勿/非/未 carry them exactly.
21997
+ - Destructive or irreversible requests (data deletion, prod mutations, force-push, secret exposure) always open with a labeled warning block in the user's own language, in complete modern sentences - never Classical fragments - even if asked to skip it. Finish the warning, leave a blank line, then resume. Format: "**Warning:** This permanently deletes all rows in \`users\` and cannot be undone." Same normal prose in the user's language for genuine ambiguity and for anything persisted outside the chat (code, comments, commits, PR/issue text, docs, messages to third parties). Then resume.
21998
+
21999
+ Intensity: minimum sufficient answer. Each fact once; named facts stay named. At most 3 lines unless the answer is code or a required warning. Stop the moment the request is satisfied.
22000
+
22001
+ Example - "Why does my React component re-render?"
22002
+ "屬性每渲染新物、新參、再渲染。宜 \`useMemo\`。"`
21970
22003
  };
22004
+ /**
22005
+ * Concrete numeric constraints, not adjectives: the compress-mode measurements
22006
+ * found vague wording ("aim for fewer lines") recovers to baseline while hard
22007
+ * numbers hold across turns. The numbers step down by level so the modes stay
22008
+ * visibly distinct. Reminder position stays before the user's message - the
22009
+ * after-message placement measured 20% worse on Opus.
22010
+ */
21971
22011
  const COMPRESS_TURN_REMINDERS = {
21972
- lite: "[response style: compressed lite - no filler/hedging, full sentences; keep negations and numbers exact; code/commits/security text normal]",
21973
- full: "[response style: compressed full - terse fragments, drop articles/filler; keep negations and numbers exact; code/commits/security text normal]",
21974
- ultra: "[response style: compressed ultra - maximum terseness, one word when enough; keep negations and numbers exact; code/commits/security text normal]"
22012
+ lite: "[response style: compressed lite - no filler/hedging, full sentences, at most 20 lines unless the answer is code; keep negations and numbers exact; code/commits/security text normal]",
22013
+ full: "[response style: compressed full - terse fragments, drop articles/filler, at most 12 lines unless the answer is code; keep negations and numbers exact; code/commits/security text normal]",
22014
+ ultra: "[ultra: minimum sufficient tokens; no intro/recap/repeats; at most 3 lines unless the answer is code; exact negations/numbers/names; security/persisted text normal]",
22015
+ wenyan: "[wenyan: prose in maximally terse Classical Chinese; first line anchors every user-supplied path/error/number verbatim; at most 3 lines after the anchor unless the answer is code; security/persisted text normal prose in the user's language]"
21975
22016
  };
21976
22017
  /**
21977
22018
  * Sent when compression is switched off on a session that is still carrying a
@@ -63323,6 +63364,7 @@ function toRuntimePayloadFromSession(session, extra) {
63323
63364
  activeTurnId: session.activeTurnId ?? null,
63324
63365
  lastError: session.lastError ?? null,
63325
63366
  ...extra?.modelSelection !== void 0 ? { modelSelection: extra.modelSelection } : {},
63367
+ ...extra?.compressMode !== void 0 ? { compressMode: extra.compressMode } : {},
63326
63368
  ...extra?.lastRuntimeEvent !== void 0 ? { lastRuntimeEvent: extra.lastRuntimeEvent } : {},
63327
63369
  ...extra?.lastRuntimeEventAt !== void 0 ? { lastRuntimeEventAt: extra.lastRuntimeEventAt } : {}
63328
63370
  };
@@ -63332,6 +63374,18 @@ function readPersistedModelSelection(runtimePayload) {
63332
63374
  const raw = "modelSelection" in runtimePayload ? runtimePayload.modelSelection : void 0;
63333
63375
  return isModelSelection(raw) ? raw : void 0;
63334
63376
  }
63377
+ const PERSISTED_COMPRESS_MODES = /* @__PURE__ */ new Set([
63378
+ "off",
63379
+ "lite",
63380
+ "full",
63381
+ "ultra",
63382
+ "wenyan"
63383
+ ]);
63384
+ function readPersistedCompressMode(runtimePayload) {
63385
+ if (!runtimePayload || typeof runtimePayload !== "object" || Array.isArray(runtimePayload)) return;
63386
+ const raw = "compressMode" in runtimePayload ? runtimePayload.compressMode : void 0;
63387
+ return typeof raw === "string" && PERSISTED_COMPRESS_MODES.has(raw) ? raw : void 0;
63388
+ }
63335
63389
  function readPersistedCwd(runtimePayload) {
63336
63390
  if (!runtimePayload || typeof runtimePayload !== "object" || Array.isArray(runtimePayload)) return;
63337
63391
  const rawCwd = "cwd" in runtimePayload ? runtimePayload.cwd : void 0;
@@ -63437,6 +63491,7 @@ const makeProviderService = Effect.fn("makeProviderService")(function* (options)
63437
63491
  if (!hasResumeCursor) return yield* toValidationError(input.operation, `Cannot recover thread '${input.binding.threadId}' because no provider resume state is persisted.`);
63438
63492
  const persistedCwd = readPersistedCwd(input.binding.runtimePayload);
63439
63493
  const persistedModelSelection = readPersistedModelSelection(input.binding.runtimePayload);
63494
+ const persistedCompressMode = readPersistedCompressMode(input.binding.runtimePayload);
63440
63495
  yield* prepareMcpSession(input.binding.threadId, bindingInstanceId);
63441
63496
  const resumed = yield* adapter.startSession({
63442
63497
  threadId: input.binding.threadId,
@@ -63444,6 +63499,7 @@ const makeProviderService = Effect.fn("makeProviderService")(function* (options)
63444
63499
  providerInstanceId: bindingInstanceId,
63445
63500
  ...persistedCwd ? { cwd: persistedCwd } : {},
63446
63501
  ...persistedModelSelection ? { modelSelection: persistedModelSelection } : {},
63502
+ ...persistedCompressMode ? { compressMode: persistedCompressMode } : {},
63447
63503
  ...hasResumeCursor ? { resumeCursor: input.binding.resumeCursor } : {},
63448
63504
  runtimeMode: input.binding.runtimeMode ?? "full-access"
63449
63505
  }).pipe(Effect.onError(() => clearMcpSession(input.binding.threadId)));
@@ -63563,7 +63619,10 @@ const makeProviderService = Effect.fn("makeProviderService")(function* (options)
63563
63619
  threadId,
63564
63620
  currentInstanceId: resolvedInstanceId
63565
63621
  });
63566
- yield* upsertSessionBinding(sessionWithInstance, threadId, { modelSelection: input.modelSelection });
63622
+ yield* upsertSessionBinding(sessionWithInstance, threadId, {
63623
+ modelSelection: input.modelSelection,
63624
+ ...input.compressMode !== void 0 ? { compressMode: input.compressMode } : {}
63625
+ });
63567
63626
  yield* analytics.record("provider.session.started", {
63568
63627
  provider: sessionWithInstance.provider,
63569
63628
  runtimeMode: input.runtimeMode,
@@ -88091,6 +88150,9 @@ function buildCodexCollaborationMode(input) {
88091
88150
  }
88092
88151
  };
88093
88152
  }
88153
+ function isSameCollaborationMode(a, b) {
88154
+ return a.mode === b.mode && a.settings.model === b.settings.model && a.settings.reasoning_effort === b.settings.reasoning_effort && a.settings.developer_instructions === b.settings.developer_instructions;
88155
+ }
88094
88156
  function buildTurnStartParams(input) {
88095
88157
  const turnInput = [];
88096
88158
  if (input.prompt) turnInput.push({
@@ -88105,6 +88167,7 @@ function buildTurnStartParams(input) {
88105
88167
  ...input.model ? { model: input.model } : {},
88106
88168
  ...input.effort ? { effort: input.effort } : {}
88107
88169
  });
88170
+ const compressRulesetUndeliverable = input.compressMode !== void 0 && input.compressMode !== "off" && collaborationMode === void 0;
88108
88171
  return decodeCodexTurnStartParamsWithCollaborationMode({
88109
88172
  threadId: input.threadId,
88110
88173
  input: turnInput,
@@ -88115,7 +88178,11 @@ function buildTurnStartParams(input) {
88115
88178
  ...input.serviceTier ? { serviceTier: input.serviceTier } : {},
88116
88179
  ...input.effort ? { effort: input.effort } : {},
88117
88180
  ...collaborationMode ? { collaborationMode } : {}
88118
- }).pipe(Effect.mapError((cause) => CodexAppServerProtocolParseError.fromSchemaError("decode-request-payload", cause, { method: "turn/start" })));
88181
+ }).pipe(compressRulesetUndeliverable ? Effect.tap(() => Effect.logWarning("codex.turn.compress-ruleset-undeliverable", {
88182
+ threadId: input.threadId,
88183
+ compressMode: input.compressMode,
88184
+ reason: "no interaction mode on the turn, so no developer instructions were built"
88185
+ })) : (effect) => effect, Effect.mapError((cause) => CodexAppServerProtocolParseError.fromSchemaError("decode-request-payload", cause, { method: "turn/start" })));
88119
88186
  }
88120
88187
  function classifyCodexStderrLine(rawLine) {
88121
88188
  const line = rawLine.replaceAll(ANSI_ESCAPE_REGEX, "").trim();
@@ -88300,6 +88367,7 @@ const makeCodexSessionRuntime = (options) => Effect.gen(function* () {
88300
88367
  const approvalCorrelationsRef = yield* Ref.make(/* @__PURE__ */ new Map());
88301
88368
  const pendingUserInputsRef = yield* Ref.make(/* @__PURE__ */ new Map());
88302
88369
  const collabReceiverTurnsRef = yield* Ref.make(/* @__PURE__ */ new Map());
88370
+ const lastCollaborationModeRef = yield* Ref.make(null);
88303
88371
  const closedRef = yield* Ref.make(false);
88304
88372
  const resolvedHomePath = options.homePath ? expandHomePath$3(options.homePath) : void 0;
88305
88373
  const env = {
@@ -88608,6 +88676,7 @@ const makeCodexSessionRuntime = (options) => Effect.gen(function* () {
88608
88676
  updatedAt: yield* nowIso
88609
88677
  };
88610
88678
  yield* Ref.set(sessionRef, session);
88679
+ yield* Ref.set(lastCollaborationModeRef, null);
88611
88680
  yield* emitSessionEvent("session/ready", "Codex App Server session ready.");
88612
88681
  return session;
88613
88682
  });
@@ -88647,7 +88716,11 @@ const makeCodexSessionRuntime = (options) => Effect.gen(function* () {
88647
88716
  ...input.interactionMode ? { interactionMode: input.interactionMode } : {},
88648
88717
  ...input.compressMode ? { compressMode: input.compressMode } : {}
88649
88718
  });
88650
- const rawResponse = yield* client.raw.request("turn/start", params);
88719
+ const { collaborationMode: attachedCollaborationMode, ...paramsWithoutCollaboration } = params;
88720
+ const lastCollaborationMode = yield* Ref.get(lastCollaborationModeRef);
88721
+ const requestParams = attachedCollaborationMode !== void 0 && lastCollaborationMode !== null && isSameCollaborationMode(attachedCollaborationMode, lastCollaborationMode) ? paramsWithoutCollaboration : params;
88722
+ const rawResponse = yield* client.raw.request("turn/start", requestParams);
88723
+ if (attachedCollaborationMode !== void 0) yield* Ref.set(lastCollaborationModeRef, attachedCollaborationMode);
88651
88724
  const response = yield* decodeV2TurnStartResponse(rawResponse).pipe(Effect.mapError((error) => CodexAppServerProtocolParseError.fromSchemaError("decode-response-payload", error, { method: "turn/start" })));
88652
88725
  const turnId = TurnId.make(response.turn.id);
88653
88726
  yield* updateSession(sessionRef, {
@@ -103666,8 +103739,8 @@ function runtimeEventToActivities(event, taskTitle, compressMode) {
103666
103739
  payload: {
103667
103740
  taskId: event.payload.taskId,
103668
103741
  ...event.payload.description.trim().length > 0 ? { title: truncateDetail(event.payload.description, 120) } : {},
103669
- detail: truncateDetail(event.payload.summary ?? event.payload.description),
103670
- ...event.payload.summary ? { summary: truncateDetail(event.payload.summary) } : {},
103742
+ detail: event.payload.summary ?? event.payload.description,
103743
+ ...event.payload.summary ? { summary: event.payload.summary } : {},
103671
103744
  ...event.payload.lastToolName ? { lastToolName: event.payload.lastToolName } : {},
103672
103745
  ...event.payload.usage !== void 0 ? { usage: event.payload.usage } : {},
103673
103746
  ...event.payload.toolUseId ? { toolUseId: event.payload.toolUseId } : {},
@@ -103687,8 +103760,8 @@ function runtimeEventToActivities(event, taskTitle, compressMode) {
103687
103760
  status: event.payload.status,
103688
103761
  ...taskTitle ? { title: truncateDetail(taskTitle, 120) } : {},
103689
103762
  ...event.payload.summary ? {
103690
- summary: truncateDetail(event.payload.summary),
103691
- detail: truncateDetail(event.payload.summary)
103763
+ summary: event.payload.summary,
103764
+ detail: event.payload.summary
103692
103765
  } : {},
103693
103766
  ...event.payload.usage !== void 0 ? { usage: event.payload.usage } : {},
103694
103767
  ...event.payload.toolUseId ? { toolUseId: event.payload.toolUseId } : {}
@@ -105850,6 +105923,22 @@ const watcherPowers = (implementerThreadId) => `You can steer the builder:
105850
105923
  - thread_advise with interrupt: true cancels the builder's running turn before the advice lands. Reserve it for scope drift or work that is causing damage right now.
105851
105924
 
105852
105925
  Never call thread_watch_events repeatedly to wait for new activity, and never wait for the builder to respond: deliver your review and any advice, then end your turn. The server wakes you at the next turn boundary.`;
105926
+ /**
105927
+ * The delivery loop, restated in every review wake for the same reason the
105928
+ * powers are: the watcher has no system prompt and no reliable conversational
105929
+ * memory (compression, reconnects and restarts all truncate it), so the loop's
105930
+ * definition of done and its recovery procedure must arrive with each wake,
105931
+ * and the current phase must be derived from artifacts rather than remembered.
105932
+ */
105933
+ const deliveryProtocol = (implementerThreadId) => `You own the delivery loop. Code that looks correct and tested is not completion. The work is complete only when all of these hold, verified from artifacts - the builder thread's events, git state, and the pull request - never from memory:
105934
+
105935
+ 1. The changes are committed on a feature or fix branch with a conventional commit message, staged by explicit paths, and rebased onto latest main.
105936
+ 2. A pull request is open, and the builder reported the commit and the pull request URL.
105937
+ 3. The provider's global pr-reviewer subagent reviewed the branch or pull request, every confirmed finding was fixed, the affected checks re-ran green, and a follow-up review found no actionable findings.
105938
+
105939
+ When a review finds the code work done and you have no objections, but the conditions above are not yet met, use thread_advise (threadId ${implementerThreadId}) to instruct the builder to take the next delivery step: commit, rebase onto latest main, open the pull request, run the global pr-reviewer subagent against the branch or pull request, fix confirmed findings, re-run the affected checks, and repeat the review until it is clean. Then require the final report to state the commit and the pull request URL.
105940
+
105941
+ Never instruct a merge and never report the work as merged: merging stays with the user. To find the current loop phase after any restart or context loss, inspect the artifacts - git log and status in the workspace, the pull request if one exists, and the builder thread's recent events.`;
105853
105942
  const watcherPrompt = (input) => `${FUSION_REVIEW_PROMPT_PREFIX}
105854
105943
  Review builder thread ${input.implementerThreadId} after its accepted turn completion.
105855
105944
 
@@ -105863,6 +105952,8 @@ Give the user a concise status report after every review:
105863
105952
 
105864
105953
  ${watcherPowers(input.implementerThreadId)}
105865
105954
 
105955
+ ${deliveryProtocol(input.implementerThreadId)}
105956
+
105866
105957
  Mention blockers or unfinished work explicitly. Do not work silently. Do not return only ${FUSION_NO_OBJECTION_TEXT}.`;
105867
105958
  const gateKindDescription = (gate) => {
105868
105959
  switch (gate.kind) {
@@ -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{Ac as i,H as a,Mc as o,Q as s,Qt as c,Yc as ee,Z as l,Zi as u,aa as d,b as f,ct as p,da as te,dl as m,ea as ne,el as h,et as g,fa as _,gl as v,h as y,ia as b,jc as x,kc as re,ma as S,nn as C,nr as ie,ol as ae,pa as w,pr as T,sr as oe,ua as E,zl as D,zm as se,zt as O}from"./previewAssetResource-BEwdA2I3.js";import{t as k}from"./arrow-right-C_Eu_J71.js";import{a as ce,i as A,n as j,o as le,r as ue,s as de,t as M}from"./toggle-group-BZtpL0SP.js";import{F as fe,Fr as pe,I as me,J as he,L as ge,Lr as _e,Mr as ve,Nr as ye,R as N,Sr as be,Y as xe,_ as Se,at as Ce,cr as we,ct as Te,dr as Ee,fr as De,gr as Oe,h as ke,it as Ae,jr as je,lr as Me,lt as Ne,mr as Pe,oi as Fe,or as Ie,ot as Le,pr as Re,rt as ze,si as Be,sr as Ve,st as He,ur as Ue,zr as We}from"./index-BPZitrC3.js";import{a as P,n as Ge}from"./fileCommentAnnotations-Dh8Om-Nh.js";var Ke=o(`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 qe({threadRef:e,filePath:t,activeCwd:n,openInEditor:r,openFileSurface:i}){if(e){if(i){i(t);return}a.getState().openFile(e,t);return}r(n?y(t,n):t)}var I=r();function Je(e,t){let n=(0,I.c)(4),r=Oe(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(),Ye=[];function Xe(e){return(e.endSide??e.side)===`deletions`?`deletions`:`additions`}function R(e,t,n){let r=Xe(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 Ze(e){let t=(0,I.c)(50),{files:n,sectionId:r,sectionTitle:i,composerDraftTarget:a,options:o,viewerRef:s,className:c,renderHeaderPrefix:ee}=e,l=ie(et),u=ie(B),d;t[0]===a?d=t[1]:(d=e=>e.getComposerDraft(a)?.reviewComments??Ye,t[0]=a,t[1]=d);let f=ie(d),[p,te]=(0,F.useState)(null),[m,ne]=(0,F.useState)(null),h;t[2]===n?h=t[3]:(h=new Map(n.map($e)),t[2]=n,t[3]=h);let g=h,_;if(t[4]!==m||t[5]!==n||t[6]!==f||t[7]!==r){let e;t[9]!==m||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=T(t,n);return r?R(e,r,{id:n.id,kind:`comment`,range:r,rangeLabel:n.rangeLabel,text:n.text}):e},[]),s=m?.fileKey===i?[...o,m.annotation]:o;return{id:i,type:`diff`,fileDiff:t,annotations:s,collapsed:a,version:Ae(`${a?`1`:`0`}:${s.flatMap(z).join(`:`)}`)}},t[9]=m,t[10]=f,t[11]=r,t[12]=e):e=t[12],_=n.map(e),t[4]=m,t[5]=n,t[6]=f,t[7]=r,t[8]=_}else _=t[8];let v=_,y;t[13]!==a||t[14]!==m?.annotation||t[15]!==u?(y=e=>{te(null),m?.annotation.metadata.entries.some(t=>t.id===e)?ne(null):u(a,e)},t[13]=a,t[14]=m?.annotation,t[15]=u,t[16]=y):y=t[16];let b=y,x;t[17]!==l||t[18]!==a||t[19]!==m||t[20]!==g||t[21]!==r||t[22]!==i?(x=(e,t)=>{let n=m?.annotation.metadata.entries.find(t=>t.id===e),o=m?g.get(m.fileKey):void 0;if(!n||!o)return;let s=oe({id:n.id,sectionId:r,sectionTitle:i,filePath:o.filePath,fileDiff:o.fileDiff,range:n.range,text:t});s&&l(a,s),te(null),ne(null)},t[17]=l,t[18]=a,t[19]=m,t[20]=g,t[21]=r,t[22]=i,t[23]=x):x=t[23];let re=x,S;t[24]!==g||t[25]!==r||t[26]!==i?(S=(e,t)=>{if(!e)return;let n=t.item;if(n.type!==`diff`)return;let a=g.get(n.id);if(!a)return;let o=Ge(),s=oe({id:o,sectionId:r,sectionTitle:i,filePath:a.filePath,fileDiff:a.fileDiff,range:e,text:``});s&&ne({fileKey:n.id,annotation:{side:Xe(e),lineNumber:e.end,metadata:{entries:[{id:o,kind:`draft`,range:e,rangeLabel:s.rangeLabel,text:``}]}}})},t[24]=g,t[25]=r,t[26]=i,t[27]=S):S=t[27];let C=S,ae=m!==null,w;t[28]===s?w=t[29]:(w=s?{ref:s}:{},t[28]=s,t[29]=w);let E;t[30]===c?E=t[31]:(E=c?{className:c}:{},t[30]=c,t[31]=E);let D=!ae,se=!ae,O;t[32]!==C||t[33]!==o||t[34]!==se||t[35]!==D?(O={...o,enableGutterUtility:D,enableLineSelection:se,onLineSelectionEnd:C},t[32]=C,t[33]=o,t[34]=se,t[35]=D,t[36]=O):O=t[36];let k;t[37]===ee?k=t[38]:(k=e=>e.type===`diff`?ee(e.fileDiff,e.id,e.collapsed===!0):null,t[37]=ee,t[38]=k);let A;t[39]!==b||t[40]!==re?(A=e=>(0,L.jsx)(`div`,{className:`py-1`,children:e.metadata.entries.map(e=>(0,L.jsx)(P,{kind:e.kind,rangeLabel:e.rangeLabel,text:e.text,onCancel:()=>b(e.id),onComment:t=>re(e.id,t),onDelete:()=>b(e.id)},e.id))}),t[39]=b,t[40]=re,t[41]=A):A=t[41];let j;return t[42]!==v||t[43]!==p||t[44]!==O||t[45]!==k||t[46]!==A||t[47]!==w||t[48]!==E?(j=(0,L.jsx)(ce,{...w,...E,items:v,selectedLines:p,onSelectedLinesChange:te,options:O,renderHeaderPrefix:k,renderAnnotation:A}),t[42]=v,t[43]=p,t[44]=O,t[45]=k,t[46]=A,t[47]=w,t[48]=E,t[49]=j):j=t[49],j}function z(e){return e.metadata.entries.map(Qe)}function Qe(e){return`${e.id}:${e.rangeLabel}:${e.text}`}function $e(e){return[e.fileKey,e]}function B(e){return e.removeReviewComment}function et(e){return e.addReviewComment}function tt(e){return{diffPreview:h(e,{label:`environment-data:review:diff-preview`,tag:D.reviewGetDiffPreview,staleTimeMs:5e3})}}var nt=tt(C);function V(e){return e.remoteName&&e.name.startsWith(`${e.remoteName}/`)?e.name.slice(e.remoteName.length+1):e.name}function rt(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 it(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__`,at=new Set,ot=`
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{Ac as i,H as a,Mc as o,Q as s,Qt as c,Yc as ee,Z as l,Zi as u,aa as d,b as f,ct as p,da as te,dl as m,ea as ne,el as h,et as g,fa as _,gl as v,h as y,ia as b,jc as x,kc as re,ma as S,nn as C,nr as ie,ol as ae,pa as w,pr as T,sr as oe,ua as E,zl as D,zm as se,zt as O}from"./previewAssetResource-bmHagfYU.js";import{t as k}from"./arrow-right-DSU5D6Bb.js";import{a as ce,i as A,n as j,o as le,r as ue,s as de,t as M}from"./toggle-group-B_Cx35Ek.js";import{F as fe,Fr as pe,I as me,J as he,L as ge,Lr as _e,Mr as ve,Nr as ye,R as N,Sr as be,Y as xe,_ as Se,at as Ce,cr as we,ct as Te,dr as Ee,fr as De,gr as Oe,h as ke,it as Ae,jr as je,lr as Me,lt as Ne,mr as Pe,oi as Fe,or as Ie,ot as Le,pr as Re,rt as ze,si as Be,sr as Ve,st as He,ur as Ue,zr as We}from"./index-BBTuAu9J.js";import{a as P,n as Ge}from"./fileCommentAnnotations-DmPfXSsw.js";var Ke=o(`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 qe({threadRef:e,filePath:t,activeCwd:n,openInEditor:r,openFileSurface:i}){if(e){if(i){i(t);return}a.getState().openFile(e,t);return}r(n?y(t,n):t)}var I=r();function Je(e,t){let n=(0,I.c)(4),r=Oe(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(),Ye=[];function Xe(e){return(e.endSide??e.side)===`deletions`?`deletions`:`additions`}function R(e,t,n){let r=Xe(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 Ze(e){let t=(0,I.c)(50),{files:n,sectionId:r,sectionTitle:i,composerDraftTarget:a,options:o,viewerRef:s,className:c,renderHeaderPrefix:ee}=e,l=ie(et),u=ie(B),d;t[0]===a?d=t[1]:(d=e=>e.getComposerDraft(a)?.reviewComments??Ye,t[0]=a,t[1]=d);let f=ie(d),[p,te]=(0,F.useState)(null),[m,ne]=(0,F.useState)(null),h;t[2]===n?h=t[3]:(h=new Map(n.map($e)),t[2]=n,t[3]=h);let g=h,_;if(t[4]!==m||t[5]!==n||t[6]!==f||t[7]!==r){let e;t[9]!==m||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=T(t,n);return r?R(e,r,{id:n.id,kind:`comment`,range:r,rangeLabel:n.rangeLabel,text:n.text}):e},[]),s=m?.fileKey===i?[...o,m.annotation]:o;return{id:i,type:`diff`,fileDiff:t,annotations:s,collapsed:a,version:Ae(`${a?`1`:`0`}:${s.flatMap(z).join(`:`)}`)}},t[9]=m,t[10]=f,t[11]=r,t[12]=e):e=t[12],_=n.map(e),t[4]=m,t[5]=n,t[6]=f,t[7]=r,t[8]=_}else _=t[8];let v=_,y;t[13]!==a||t[14]!==m?.annotation||t[15]!==u?(y=e=>{te(null),m?.annotation.metadata.entries.some(t=>t.id===e)?ne(null):u(a,e)},t[13]=a,t[14]=m?.annotation,t[15]=u,t[16]=y):y=t[16];let b=y,x;t[17]!==l||t[18]!==a||t[19]!==m||t[20]!==g||t[21]!==r||t[22]!==i?(x=(e,t)=>{let n=m?.annotation.metadata.entries.find(t=>t.id===e),o=m?g.get(m.fileKey):void 0;if(!n||!o)return;let s=oe({id:n.id,sectionId:r,sectionTitle:i,filePath:o.filePath,fileDiff:o.fileDiff,range:n.range,text:t});s&&l(a,s),te(null),ne(null)},t[17]=l,t[18]=a,t[19]=m,t[20]=g,t[21]=r,t[22]=i,t[23]=x):x=t[23];let re=x,S;t[24]!==g||t[25]!==r||t[26]!==i?(S=(e,t)=>{if(!e)return;let n=t.item;if(n.type!==`diff`)return;let a=g.get(n.id);if(!a)return;let o=Ge(),s=oe({id:o,sectionId:r,sectionTitle:i,filePath:a.filePath,fileDiff:a.fileDiff,range:e,text:``});s&&ne({fileKey:n.id,annotation:{side:Xe(e),lineNumber:e.end,metadata:{entries:[{id:o,kind:`draft`,range:e,rangeLabel:s.rangeLabel,text:``}]}}})},t[24]=g,t[25]=r,t[26]=i,t[27]=S):S=t[27];let C=S,ae=m!==null,w;t[28]===s?w=t[29]:(w=s?{ref:s}:{},t[28]=s,t[29]=w);let E;t[30]===c?E=t[31]:(E=c?{className:c}:{},t[30]=c,t[31]=E);let D=!ae,se=!ae,O;t[32]!==C||t[33]!==o||t[34]!==se||t[35]!==D?(O={...o,enableGutterUtility:D,enableLineSelection:se,onLineSelectionEnd:C},t[32]=C,t[33]=o,t[34]=se,t[35]=D,t[36]=O):O=t[36];let k;t[37]===ee?k=t[38]:(k=e=>e.type===`diff`?ee(e.fileDiff,e.id,e.collapsed===!0):null,t[37]=ee,t[38]=k);let A;t[39]!==b||t[40]!==re?(A=e=>(0,L.jsx)(`div`,{className:`py-1`,children:e.metadata.entries.map(e=>(0,L.jsx)(P,{kind:e.kind,rangeLabel:e.rangeLabel,text:e.text,onCancel:()=>b(e.id),onComment:t=>re(e.id,t),onDelete:()=>b(e.id)},e.id))}),t[39]=b,t[40]=re,t[41]=A):A=t[41];let j;return t[42]!==v||t[43]!==p||t[44]!==O||t[45]!==k||t[46]!==A||t[47]!==w||t[48]!==E?(j=(0,L.jsx)(ce,{...w,...E,items:v,selectedLines:p,onSelectedLinesChange:te,options:O,renderHeaderPrefix:k,renderAnnotation:A}),t[42]=v,t[43]=p,t[44]=O,t[45]=k,t[46]=A,t[47]=w,t[48]=E,t[49]=j):j=t[49],j}function z(e){return e.metadata.entries.map(Qe)}function Qe(e){return`${e.id}:${e.rangeLabel}:${e.text}`}function $e(e){return[e.fileKey,e]}function B(e){return e.removeReviewComment}function et(e){return e.addReviewComment}function tt(e){return{diffPreview:h(e,{label:`environment-data:review:diff-preview`,tag:D.reviewGetDiffPreview,staleTimeMs:5e3})}}var nt=tt(C);function V(e){return e.remoteName&&e.name.startsWith(`${e.remoteName}/`)?e.name.slice(e.remoteName.length+1):e.name}function rt(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 it(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__`,at=new Set,ot=`
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}){let{resolvedTheme:r}=f(),a=pe(),[o]=(0,F.useState)(n),[h,y]=(0,F.useState)(`stacked`),[C,ie]=(0,F.useState)(a.wordWrap),[T,oe]=(0,F.useState)(a.diffIgnoreWhitespace),[D,ce]=(0,F.useState)(``),[Se,Oe]=(0,F.useState)(()=>({scopeKey:null,fileKeys:at})),Ae=(0,F.useRef)(null),P=se({strict:!1,select:e=>O(e)}),Ge=P?.threadId??null,I=ye(P),Ye=I?.projectId??null,Xe=ve(I&&Ye?{environmentId:I.environmentId,projectId:Ye}:null),R=I?.worktreePath??Xe?.workspaceRoot,z=ee(c.configValueAtom(I?.environmentId??null)),Qe=Pe(I?.environmentId??null,z?.availableEditors??[]),$e=p(I!=null&&R!=null?je.status({environmentId:I.environmentId,input:{cwd:R}}):null),B=N(e=>ge(e.byThreadKey,P,o===`unstaged`)),et=$e.data?.isRepo??!0,{turnDiffSummaries:tt,inferredCheckpointTurnCountByTurnId:V}=me(I),U=(0,F.useMemo)(()=>[...tt].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,tt]);(0,F.useEffect)(()=>{!P||B.kind!==`turn`||N.getState().reconcileTurnSelection(P,U.map(e=>e.turnId))},[B,U,P]);let W=B.kind===`turn`?B.turnId:null,G=B.kind===`unstaged`?`unstaged`:`branch`,K=B.kind===`branch`?B.baseRef:null,st=B.kind===`turn`?B.filePath:null,ct=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]),lt=U[0],ut=W===null?G===`unstaged`?`Working tree`:`Branch changes`:q?.turnId===lt?.turnId?`Latest turn`:`Turn ${J??`?`}`,dt=q?`turn:${q.turnId}`:G,Y=P?`${P.environmentId}:${P.threadId}:${dt}`:null,ft=Se.scopeKey===Y?Se.fileKeys:at,pt=q?`Turn ${J??`?`}`:G===`unstaged`?`Working tree`:`Branch changes`,mt=(0,F.useMemo)(()=>typeof J==`number`?{fromTurnCount:Math.max(0,J-1),toTurnCount:J}:null,[J]),ht=Je({environmentId:I?.environmentId??null,threadId:Ge,fromTurnCount:mt?.fromTurnCount??null,toTurnCount:mt?.toTurnCount??null,ignoreWhitespace:T,cacheScope:q?`turn:${q.turnId}`:null},{enabled:et&&q!==void 0}),gt=p(W===null&&I&&R?nt.diffPreview({environmentId:I.environmentId,input:{cwd:R,...K?{baseRef:K}:{},ignoreWhitespace:T}}):null),_t=W===null&&gt.error?.includes(`configured workspace root`)===!0&&z?.cwd!==void 0&&z.cwd!==R,vt=p(_t&&I&&z?nt.diffPreview({environmentId:I.environmentId,input:{cwd:z.cwd,...K?{baseRef:K}:{},ignoreWhitespace:T}}):null),X=_t?vt:gt,Z=X.data?.sources.find(e=>e.kind===(G===`unstaged`?`working-tree`:`branch-range`)),yt=p(W===null&&G===`branch`&&I&&X.data?.cwd?je.listRefs({environmentId:I.environmentId,input:{cwd:X.data.cwd,includeMatchingRemoteRefs:!0,refKind:`local`,...D.trim().length>0?{query:D.trim()}:{},limit:100}}):null),bt=p(W===null&&G===`branch`&&I&&X.data?.cwd?je.listRefs({environmentId:I.environmentId,input:{cwd:X.data.cwd,includeMatchingRemoteRefs:!0,refKind:`remote`,...D.trim().length>0?{query:D.trim()}:{},limit:100}}):null),xt=rt(yt.data?.refs.filter(e=>e.name!==Z?.headRef)??[],bt.data?.refs??[]),St=it(xt,D),Ct=e=>K&&K===e.remote?.name?K:e.local?.name??e.remote?.name??e.id,wt=[H,...xt.map(Ct)],Tt=[...D.trim().length===0?[H]:[],...St.map(Ct)],Et=Z?.diff,Dt=q?ht.data?.diff:Et,Ot=!q&&Z?.truncated===!0,kt=q?ht.isPending:X.isPending,At=q?ht.error:X.error,jt=typeof Dt==`string`&&Dt.trim().length===0,Q=(0,F.useMemo)(()=>He(Dt,`diff-panel:${r}`,{compactPartialHunkOffsets:W===null}),[r,Dt,W]),Mt=(0,F.useMemo)(()=>!Q||Q.kind!==`files`?[]:Q.files.toSorted((e,t)=>Ne(e).localeCompare(Ne(t),void 0,{numeric:!0,sensitivity:`base`})),[Q]),$=(0,F.useMemo)(()=>Mt.map(e=>{let t=ze(e);return{fileDiff:e,filePath:Ne(e),fileKey:t,collapsed:ft.has(t)}}),[ft,Mt]),Nt=(0,F.useMemo)(()=>$.map(e=>e.fileKey),[$]),Pt=ue(Nt,ft),Ft=(0,F.useMemo)(()=>Le(Mt),[Mt]);(0,F.useEffect)(()=>{if(!st)return;let e=$.find(e=>e.filePath===st);e&&Ae.current?.scrollTo({type:`item`,id:e.fileKey,align:`start`})},[$,st,ct]);let It=fe({threadRef:P,workspaceRoot:R??null}),Lt=(0,F.useCallback)(e=>{qe({threadRef:P,filePath:e,activeCwd:R,openFileSurface:It,openInEditor:e=>{(async()=>{let t=await Qe(e);t._tag===`Failure`&&!ae(t)&&console.warn(`Failed to open diff file in editor.`,{operation:`open-diff-file`,...P?{environmentId:P.environmentId,threadId:P.threadId}:{},...v(m(t))})})()}})},[R,It,Qe,P]),Rt=(0,F.useCallback)(e=>{Oe(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]),zt=(0,F.useCallback)(()=>{Oe(e=>{let t=e.scopeKey===Y?e.fileKeys:at;return{scopeKey:Y,fileKeys:A(Nt,t)}})},[Y,Nt]),Bt=e=>{P&&N.getState().selectTurn(P,e)},Vt=e=>{P&&N.getState().selectGitScope(P,e)},Ht=e=>{P&&N.getState().selectBranchBaseRef(P,e)};return(0,L.jsx)(xe,{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)(ne,{children:[(0,L.jsxs)(w,{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: ${ut}`,children:[(0,L.jsx)(`span`,{className:`truncate`,children:ut}),(0,L.jsx)(i,{className:`size-3.5 shrink-0 text-muted-foreground`})]}),(0,L.jsxs)(d,{align:`start`,className:`w-60`,children:[(0,L.jsx)(b,{className:W===null&&G===`unstaged`?`bg-foreground/[0.08]`:void 0,onClick:()=>Vt(`unstaged`),children:(0,L.jsx)(`span`,{children:`Working tree`})}),(0,L.jsx)(b,{className:W===null&&G===`branch`?`bg-foreground/[0.08]`:void 0,onClick:()=>Vt(`branch`),children:(0,L.jsx)(`span`,{children:`Branch changes`})}),(0,L.jsx)(b,{className:W!==null&&q?.turnId===lt?.turnId?`bg-foreground/[0.08]`:void 0,onClick:()=>{lt&&Bt(lt.turnId)},children:(0,L.jsx)(`span`,{children:`Latest turn`})}),(0,L.jsxs)(E,{children:[(0,L.jsx)(_,{children:`Turn`}),(0,L.jsx)(te,{className:`w-64`,children:U.map(e=>{let t=e.checkpointTurnCount??V[e.turnId]??`?`;return(0,L.jsxs)(b,{className:e.turnId===q?.turnId?`bg-foreground/[0.08]`:void 0,onClick:()=>Bt(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:be(e.completedAt,a.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)(k,{className:`size-3.5 shrink-0 opacity-70`}),(0,L.jsxs)(Ve,{items:wt,filteredItems:Tt,value:K??H,onOpenChange:e=>{e||ce(``)},onValueChange:e=>{e&&Ht(e===H?null:e)},children:[(0,L.jsxs)(Re,{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)(i,{className:`size-3.5 shrink-0 opacity-70`})]}),(0,L.jsxs)(De,{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)(We,{"aria-hidden":`true`,className:`pointer-events-none absolute top-1.5 left-0 size-4 shrink-0 text-muted-foreground/55`}),(0,L.jsx)(Me,{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=>ce(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)(we,{children:`No matching refs.`}),(0,L.jsxs)(Ee,{className:`max-h-64 min-w-0 overflow-x-hidden`,children:[(0,L.jsx)(Ue,{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`})}),xt.map(e=>{let t=Ct(e),n=e.local!==null&&e.remote!==null,r=e.remote?.name===t;return(0,L.jsx)(Ue,{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)(Ie,{"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&&Ht(n)}})}):e.remote?(0,L.jsx)(`span`,{className:`flex justify-end text-muted-foreground`,title:`Remote only`,children:(0,L.jsx)(x,{"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)(ke,{additions:Ft.additions,deletions:Ft.deletions,className:`mr-1 text-[11px]`,layout:`inline`}),$.length>0&&(0,L.jsxs)(l,{children:[(0,L.jsx)(g,{render:(0,L.jsx)(u,{type:`button`,size:`icon-xs`,variant:`outline`,"aria-label":Pt?`Expand all files`:`Collapse all files`,onClick:zt}),children:Pt?(0,L.jsx)(Fe,{className:`size-3`}):(0,L.jsx)(Be,{className:`size-3`})}),(0,L.jsx)(s,{side:`top`,children:Pt?`Expand all files`:`Collapse all files`})]}),(0,L.jsxs)(j,{className:`shrink-0`,variant:`outline`,size:`xs`,value:[h],onValueChange:e=>{let t=e[0];(t===`stacked`||t===`split`)&&y(t)},children:[(0,L.jsx)(M,{"aria-label":`Stacked diff view`,value:`stacked`,children:(0,L.jsx)(le,{className:`size-3`})}),(0,L.jsx)(M,{"aria-label":`Split diff view`,value:`split`,children:(0,L.jsx)(de,{className:`size-3`})})]}),(0,L.jsxs)(l,{children:[(0,L.jsx)(g,{render:(0,L.jsx)(M,{"aria-label":C?`Disable diff line wrapping`:`Enable diff line wrapping`,variant:`outline`,size:`xs`,pressed:C,onPressedChange:e=>{ie(!!e)}}),children:(0,L.jsx)(_e,{className:`size-3`})}),(0,L.jsx)(s,{side:`top`,children:C?`Disable line wrapping`:`Enable line wrapping`})]}),(0,L.jsxs)(l,{children:[(0,L.jsx)(g,{render:(0,L.jsx)(M,{"aria-label":T?`Show whitespace changes`:`Hide whitespace changes`,variant:`outline`,size:`xs`,pressed:T,onPressedChange:e=>{oe(!!e)}}),children:(0,L.jsx)(Ke,{className:`size-3`})}),(0,L.jsx)(s,{side:`top`,children:T?`Show whitespace changes`:`Hide whitespace changes`})]})]})]}),children:I?et?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:[Ot&&(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.`}),At&&!Q&&(0,L.jsx)(`div`,{className:`px-3`,children:(0,L.jsx)(`p`,{className:`mb-2 text-[11px] text-red-500/80`,children:At})}),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&&Lt(t)},children:(0,L.jsx)(Ze,{viewerRef:Ae,className:`diff-render-surface h-full min-h-0 overflow-auto`,files:$,sectionId:dt,sectionTitle:pt,composerDraftTarget:t,renderHeaderPrefix:(e,t,n)=>{let r=Ne(e);return(0,L.jsxs)(l,{children:[(0,L.jsx)(g,{render:(0,L.jsx)(`button`,{type:`button`,className:S(`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`,Ce(e)),"aria-label":n?`Expand ${r}`:`Collapse ${r}`,"aria-expanded":!n,onClick:e=>{e.stopPropagation(),Rt(t)}}),children:n?(0,L.jsx)(re,{className:`size-4`}):(0,L.jsx)(i,{className:`size-4`})}),(0,L.jsx)(s,{side:`top`,children:n?`Expand diff`:`Collapse diff`})]})},options:{diffStyle:h===`split`?`split`:`unified`,lineDiffType:`none`,overflow:C?`wrap`:`scroll`,theme:Te(r),themeType:r,unsafeCSS:ot,stickyHeaders:!0,itemMetrics:{diffHeaderHeight:33},layout:{paddingTop:0,paddingBottom:8,gap:8}}},Y??dt)}):(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:S(`max-h-[72vh] rounded-md border border-border/70 bg-background/70 p-3 font-mono text-[11px] leading-relaxed text-muted-foreground/90`,C?`overflow-auto whitespace-pre-wrap wrap-break-word`:`overflow-auto`),children:Q.text})]})}):kt?(0,L.jsx)(he,{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:jt?`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{Se as DiffWorkerPoolProvider,U as default};
98
- //# sourceMappingURL=DiffPanel-CS8LWBsp.js.map
98
+ //# sourceMappingURL=DiffPanel-4_108eR0.js.map