@cmmd-center/forge 0.10.5 → 0.10.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.cjs CHANGED
@@ -26340,7 +26340,7 @@ function acceptCmmdProjectPatchField(field, raw) {
26340
26340
  //#region ../../packages/contracts/src/cloud.ts
26341
26341
  /**
26342
26342
  * One entry returned by `GET /api/cloud/available-folders` — a candidate
26343
- * subdirectory of the managed runtime's `cloudProjectsRoot` (typically `/data/Projects`)
26343
+ * subdirectory of the managed runtime's `cloudProjectsRoot` (typically `/projects`)
26344
26344
  * that the SPA can offer in the cloud-mode "Register existing folder" picker.
26345
26345
  */
26346
26346
  const CloudAvailableFolder = require_Schema$1.Struct({
@@ -65378,7 +65378,7 @@ function normalizeNumberish(value) {
65378
65378
  }
65379
65379
  //#endregion
65380
65380
  //#region package.json
65381
- var version$1 = "0.10.5";
65381
+ var version$1 = "0.10.6";
65382
65382
  //#endregion
65383
65383
  //#region src/sentry.ts
65384
65384
  const SERVER_APP_NAME = "forge-server";
@@ -68163,6 +68163,15 @@ function parsePersistedServerObservabilitySettings(raw) {
68163
68163
  * @module ServerConfig
68164
68164
  */
68165
68165
  const DEFAULT_PORT = 13773;
68166
+ /**
68167
+ * Where a managed cloud runtime keeps the user's checkouts when
68168
+ * FORGE_CLOUD_PROJECTS_ROOT is not set. CMMD seeds every sprite checkout under
68169
+ * /projects (forge-guest-layout.ts on the CMMD side) and passes that value in
68170
+ * the Service env, so this default only matters for a server started without
68171
+ * it. It used to be a path under the Fly-era mounted volume; on a sprite the
68172
+ * two repos disagreed and every local-checkout turn was refused (FOR-36484).
68173
+ */
68174
+ const DEFAULT_CLOUD_PROJECTS_ROOT = "/projects";
68166
68175
  const RuntimeMode = require_Schema$1.Literals(["web", "desktop"]);
68167
68176
  require_Schema$1.Literals(["browser", "headless"]);
68168
68177
  const deriveServerPaths = require_Schema$1.fn(function* (baseDir, _devUrl, _mode) {
@@ -68288,7 +68297,7 @@ var ServerConfig = class ServerConfig extends require_Schema$1.Service()("forge/
68288
68297
  forgeCodexHomePath: void 0,
68289
68298
  forgeClaudeConfigPath: void 0,
68290
68299
  forgeApexBaseUrl: void 0,
68291
- cloudProjectsRoot: "/data/Projects",
68300
+ cloudProjectsRoot: DEFAULT_CLOUD_PROJECTS_ROOT,
68292
68301
  ...overrides
68293
68302
  };
68294
68303
  }));
@@ -97491,7 +97500,7 @@ const resolveAutoBootstrapWelcomeTargets = require_Schema$1.gen(function* () {
97491
97500
  /**
97492
97501
  * Cloud-mode project recovery — runs only on cloud execution runtimes.
97493
97502
  * Scans `cloudProjectsRoot` (default
97494
- * /data/Projects) for git-repo subdirectories and registers any not yet in
97503
+ * /projects) for git-repo subdirectories and registers any not yet in
97495
97504
  * the orchestration engine. This is the cloud-mode replacement for the
97496
97505
  * gated `autoBootstrapProjectFromCwd` path: managed runtimes whose volume
97497
97506
  * already holds cloned repos surface them in the sidebar after restart.
@@ -149780,13 +149789,40 @@ var CodexAppServerManager = class extends node_events.EventEmitter {
149780
149789
  if (!providerConversationId) return;
149781
149790
  return context.collabReceiverTurns.get(providerConversationId);
149782
149791
  }
149792
+ /**
149793
+ * The child threads one thread item says the turn spawned.
149794
+ *
149795
+ * Two item shapes name a child, and which one arrives depends on the Codex
149796
+ * build. `CollabAgentToolCallThreadItem` lists `receiverThreadIds`, which
149797
+ * "in case of spawn operation ... corresponds to the newly spawned agent".
149798
+ * `SubAgentActivityThreadItem` names a single `agentThreadId` and is what a
149799
+ * `spawn_agent` call reports on codex-cli 0.152/0.153: measured on the
149800
+ * packaged desktop on 2026-09-06, the spawn arrived as `SubAgentActivity`
149801
+ * (`kind: started`) and the only collab tool call that followed was the
149802
+ * `wait`, whose `receiverThreadIds` was empty. Reading only the collab item
149803
+ * left the child unmapped, so its spend was published as a second turn row
149804
+ * under the child's own turn id instead of a subagent row under the parent's.
149805
+ *
149806
+ * `SubAgentActivityThreadItem` has no `model` field, so a `completed` report
149807
+ * for a child a collab call already named must not blank the model out; the
149808
+ * caller's `model ?? known` merge is what keeps it.
149809
+ */
149810
+ readSpawnedThreadIds(item, itemType) {
149811
+ if (itemType === "subAgentActivity") {
149812
+ const agentThreadId = this.readString(item, "agentThreadId");
149813
+ return agentThreadId ? [agentThreadId] : [];
149814
+ }
149815
+ if (itemType !== "collabAgentToolCall") return [];
149816
+ return this.readArray(item, "receiverThreadIds")?.map((value) => typeof value === "string" ? value : null).filter((value) => value !== null) ?? [];
149817
+ }
149783
149818
  rememberCollabReceiverTurns(context, params, parentTurnId) {
149784
149819
  if (!parentTurnId) return;
149785
149820
  const payload = this.readObject(params);
149786
149821
  const item = this.readObject(payload, "item") ?? payload;
149787
- if ((this.readString(item, "type") ?? this.readString(item, "kind")) !== "collabAgentToolCall") return;
149822
+ const itemType = this.readString(item, "type") ?? this.readString(item, "kind");
149823
+ const receiverThreadIds = this.readSpawnedThreadIds(item, itemType);
149824
+ if (receiverThreadIds.length === 0) return;
149788
149825
  const model = this.readString(item, "model");
149789
- const receiverThreadIds = this.readArray(item, "receiverThreadIds")?.map((value) => typeof value === "string" ? value : null).filter((value) => value !== null) ?? [];
149790
149826
  for (const receiverThreadId of receiverThreadIds) {
149791
149827
  const known = context.collabReceiverTurns.get(receiverThreadId)?.model;
149792
149828
  const resolved = model ?? known;
@@ -149802,8 +149838,8 @@ var CodexAppServerManager = class extends node_events.EventEmitter {
149802
149838
  * Codex reports a child thread's tokens on the parent's own connection:
149803
149839
  * `ThreadTokenUsageUpdatedNotification` requires `threadId` and `turnId` and
149804
149840
  * names the child thread for a child, and `Thread.parentThreadId` is "only
149805
- * set if this thread is a subagent" (codex 0.144.6 app-server protocol
149806
- * schema). Every other child notification is suppressed so it cannot replace
149841
+ * set if this thread is a subagent" (still true of the codex-cli 0.153
149842
+ * app-server protocol schema). Every other child notification is suppressed so it cannot replace
149807
149843
  * the parent turn; this one is not, because the tokens belong on the ledger.
149808
149844
  * The method is Forge's own rather than the protocol's, because the payload
149809
149845
  * carries what the Usage row needs rather than what the notification held.
@@ -207599,11 +207635,14 @@ function mapCodexThreadTokenUsageEvent(event, canonicalThreadId, payload) {
207599
207635
  *
207600
207636
  * The source is the live app-server protocol, not a rollout read: Codex sends
207601
207637
  * `thread/tokenUsage/updated` for a child thread on the parent's own
207602
- * connection (0.144.6 schema: `ThreadTokenUsageUpdatedNotification` requires
207603
- * `threadId` and `turnId`, `Thread.parentThreadId` is set only for a subagent,
207604
- * and `CollabAgentToolCallThreadItem` names `receiverThreadIds` and the
207605
- * spawned agent's `model`), and `codexAppServerManager` already tracked those
207606
- * child threads to route their notifications onto the parent turn.
207638
+ * connection (`ThreadTokenUsageUpdatedNotification` requires `threadId` and
207639
+ * `turnId`, and `Thread.parentThreadId` is set only for a subagent), and
207640
+ * `codexAppServerManager` already tracked those child threads to route their
207641
+ * notifications onto the parent turn. It learns a child from whichever item
207642
+ * the running Codex build uses to announce a spawn: the
207643
+ * `receiverThreadIds` of a `CollabAgentToolCallThreadItem`, which also names
207644
+ * the spawned agent's `model`, or the `agentThreadId` of a
207645
+ * `SubAgentActivityThreadItem`, which names no model.
207607
207646
  *
207608
207647
  * The row carries no context-meter snapshot and no `turnUsage`: the parent's
207609
207648
  * own row is never re-summed with its children. It carries the call's delta
@@ -208490,7 +208529,8 @@ const CODE_BY_UPSTREAM_REASON$1 = {
208490
208529
  credential_expired_refreshing: "CREDENTIAL_EXPIRED_REFRESHING",
208491
208530
  credential_reconnect_required: "CREDENTIAL_RECONNECT_REQUIRED",
208492
208531
  credential_not_connected: "CREDENTIAL_RECONNECT_REQUIRED",
208493
- credential_generation_not_applied: "CREDENTIAL_GENERATION_NOT_APPLIED"
208532
+ credential_generation_not_applied: "CREDENTIAL_GENERATION_NOT_APPLIED",
208533
+ runtime_unavailable: "RUNTIME_UNAVAILABLE"
208494
208534
  };
208495
208535
  const CLAUDE_NATIVE_CREDENTIAL_UNUSABLE_COPY = "The delivered Claude credential is unavailable or unusable in this runtime.";
208496
208536
  /**
@@ -208553,10 +208593,17 @@ function claudeNativeCredentialUnusableMessage() {
208553
208593
  * CMMD writes this marker when it activates a personal Claude subscription
208554
208594
  * inside a running sprite. Activation always happens after boot, so a
208555
208595
  * boot-time env var alone cannot reflect it (FOR-36249).
208596
+ *
208597
+ * CMMD names the file in the Service env (FORGE_PERSONAL_CLAUDE_MARKER_PATH).
208598
+ * Without that, the marker sits directly under FORGE_HOME, which is the same
208599
+ * guest home CMMD derives every sprite path from. A server with neither has no
208600
+ * sprite home to look in, and a desktop never has a marker, so it reads none.
208556
208601
  */
208557
- const PERSONAL_CLAUDE_IN_VM_MARKER_PATH = "/data/.forge-personal-claude-in-vm";
208602
+ const PERSONAL_CLAUDE_IN_VM_MARKER_NAME = ".forge-personal-claude-in-vm";
208558
208603
  function markerPath(env) {
208559
- return env.FORGE_PERSONAL_CLAUDE_MARKER_PATH || PERSONAL_CLAUDE_IN_VM_MARKER_PATH;
208604
+ if (env.FORGE_PERSONAL_CLAUDE_MARKER_PATH) return env.FORGE_PERSONAL_CLAUDE_MARKER_PATH;
208605
+ if (env.FORGE_HOME) return (0, node_path.join)(env.FORGE_HOME, PERSONAL_CLAUDE_IN_VM_MARKER_NAME);
208606
+ return null;
208560
208607
  }
208561
208608
  /**
208562
208609
  * True when this runtime should offer the personal Claude subscription lane.
@@ -208569,8 +208616,10 @@ function markerPath(env) {
208569
208616
  */
208570
208617
  function personalClaudeInVmEnabled(env = process.env) {
208571
208618
  if (env.FORGE_PERSONAL_CLAUDE_IN_VM === "true") return true;
208619
+ const marker = markerPath(env);
208620
+ if (!marker) return false;
208572
208621
  try {
208573
- return (0, node_fs.existsSync)(markerPath(env));
208622
+ return (0, node_fs.existsSync)(marker);
208574
208623
  } catch {
208575
208624
  return false;
208576
208625
  }
@@ -227181,7 +227230,8 @@ const CLAUDE_READINESS_COPY = {
227181
227230
  failed: "Claude native runtime setup could not be applied. Reconnect Claude in Settings.",
227182
227231
  invalid: "Claude native runtime readiness is no longer valid. Reconnect Claude in Settings.",
227183
227232
  unavailable: "Claude native runtime readiness could not be verified.",
227184
- generationMismatch: "Claude native runtime generation does not match CMMD readiness."
227233
+ generationMismatch: "Claude native runtime generation does not match CMMD readiness.",
227234
+ environmentUnavailable: "This Environment is not running, so Claude cannot run on it. Restart the Environment, then try again."
227185
227235
  };
227186
227236
  var ClaudeRuntimeReadinessError = class extends Error {
227187
227237
  constructor(safeIssue, retryable = false, retryProfile = "default") {
@@ -227251,6 +227301,7 @@ async function withReadinessRetry(attempt) {
227251
227301
  */
227252
227302
  function readinessReasonIssue(readiness) {
227253
227303
  const code = claudeReadinessReasonCode(readiness.reason);
227304
+ if (code === "RUNTIME_UNAVAILABLE") return CLAUDE_READINESS_COPY.environmentUnavailable;
227254
227305
  if (code === "CREDENTIAL_RECONNECT_REQUIRED") return CLAUDE_READINESS_COPY.invalid;
227255
227306
  if (code === "CREDENTIAL_GENERATION_NOT_APPLIED") return CLAUDE_READINESS_COPY.applying;
227256
227307
  if (code !== "CREDENTIAL_EXPIRED_REFRESHING") return null;
@@ -227261,6 +227312,10 @@ function readinessReasonIssue(readiness) {
227261
227312
  function isCredentialRefreshInFlight(readiness) {
227262
227313
  return claudeReadinessReasonCode(readiness.reason) === "CREDENTIAL_EXPIRED_REFRESHING";
227263
227314
  }
227315
+ /** True when CMMD says the runtime itself cannot take a delivery (CMMD-36473). */
227316
+ function isRuntimeUnavailable(readiness) {
227317
+ return claudeReadinessReasonCode(readiness.reason) === "RUNTIME_UNAVAILABLE";
227318
+ }
227264
227319
  function readinessFailureIssue(readiness) {
227265
227320
  const reasonIssue = readinessReasonIssue(readiness);
227266
227321
  if (reasonIssue !== null) return reasonIssue;
@@ -227300,11 +227355,12 @@ function verifiedClaudeDeliveryBinding(readiness, authority) {
227300
227355
  function appliedClaudeGeneration(readiness) {
227301
227356
  if (readiness.connected !== true || readiness.deliveryStatus !== "applied" || readiness.nativeExecutable !== true || typeof readiness.generationId !== "string" || readiness.generationId.trim().length === 0) {
227302
227357
  const refreshing = isCredentialRefreshInFlight(readiness);
227303
- throw new ClaudeRuntimeReadinessError(readinessFailureIssue(readiness), refreshing || [
227358
+ const retryable = !isRuntimeUnavailable(readiness) && (refreshing || [
227304
227359
  "pending",
227305
227360
  "claimed",
227306
227361
  "activating"
227307
- ].includes(readiness.deliveryStatus), refreshing ? "credentialRefresh" : "default");
227362
+ ].includes(readiness.deliveryStatus));
227363
+ throw new ClaudeRuntimeReadinessError(readinessFailureIssue(readiness), retryable, refreshing ? "credentialRefresh" : "default");
227308
227364
  }
227309
227365
  return readiness.generationId;
227310
227366
  }
@@ -228462,15 +228518,15 @@ const collectOutput = require_Schema$1.fn("collectOutput")(function* (input, str
228462
228518
  /**
228463
228519
  * Adds a `safe.directory` exception to a git child environment.
228464
228520
  *
228465
- * Forge runs git against workspaces on a mounted volume (`/data/Projects/...` on
228466
- * Fly). A volume mount replaces the build-time ownership of its mountpoint, so a
228521
+ * Forge runs git against workspaces on a mounted volume (`<cloudProjectsRoot>/...`
228522
+ * on Fly). A volume mount replaces the build-time ownership of its mountpoint, so a
228467
228523
  * repository there can be owned by a uid other than the server's, and git then
228468
228524
  * refuses EVERY command against it with "detected dubious ownership" — the
228469
228525
  * FORGE-2T failure in `CheckpointStore.captureCheckpoint`.
228470
228526
  *
228471
228527
  * The exception has to be `*`, verified against git 2.43:
228472
228528
  * - git compares `safe.directory` entries literally, so a prefix such as
228473
- * `/data/Projects/*` does not match the repository at all.
228529
+ * `/projects/*` does not match the repository at all.
228474
228530
  * - the value must name the DISCOVERED REPOSITORY ROOT, which is an ancestor of
228475
228531
  * `cwd` whenever a command runs from a subdirectory. Resolving that root means
228476
228532
  * asking git, which is the command being refused.
@@ -291412,7 +291468,7 @@ const ServerLoggerLive = require_Schema$1.gen(function* () {
291412
291468
  * Observed live on a Forge Cloud sprite (2026-07-25): the browser opens
291413
291469
  * `wss://<sprite>.sprites.app/ws?routeKey=…&runtimeTicket=<JWT>`, and the HTTP
291414
291470
  * instrumentation records `url.full` / `url.query` verbatim. The ticket then
291415
- * lands in `/data/userdata/logs/server.trace.ndjson` at mode 644 — readable by
291471
+ * lands in `<FORGE_HOME>/userdata/logs/server.trace.ndjson` at mode 644 — readable by
291416
291472
  * the same user the agent runs as — and the URL also crosses fly.io's edge,
291417
291473
  * where infrastructure we do not control may log it.
291418
291474
  *
@@ -291709,7 +291765,7 @@ function resolveBuildCommitFromEnv(env) {
291709
291765
  * environment descriptor down instead of reporting an honest "unknown".
291710
291766
  */
291711
291767
  function readBakedBuildCommit() {
291712
- return "3a8f4c1280c7611f1850f146a6792e13b754bb4b";
291768
+ return "5f0060a9696edd41f61f06cbf24450a5994fed33";
291713
291769
  }
291714
291770
  async function resolveServerBuildCommit(input) {
291715
291771
  if (isFullCommitSha(input.baked)) return input.baked;
@@ -299761,16 +299817,6 @@ function describeDispatchCause(cause) {
299761
299817
  if (deepest === void 0 || deepest.length <= DISPATCH_CAUSE_DETAIL_LIMIT) return deepest;
299762
299818
  return `${deepest.slice(0, DISPATCH_CAUSE_DETAIL_LIMIT)}...`;
299763
299819
  }
299764
- /**
299765
- * Where automation-created projects live when the caller does not say.
299766
- *
299767
- * This is the documented default of the `cloudProjectsRoot` setting
299768
- * (FORGE_CLOUD_PROJECTS_ROOT, see cli.ts) and exists only for direct callers
299769
- * such as tests. Every HTTP route passes the CONFIGURED value instead: reading
299770
- * the default here is what made a runtime configured with any other root create
299771
- * its automation projects in a directory nothing else read.
299772
- */
299773
- const DEFAULT_CLOUD_PROJECTS_ROOT = "/data/Projects";
299774
299820
  const respondToOrchestrationHttpError = (error) => require_Schema$1.gen(function* () {
299775
299821
  if (error._tag === "OrchestrationGetSnapshotError") {
299776
299822
  yield* require_Schema$1.logError("orchestration http route failed", {
@@ -314748,7 +314794,7 @@ const resolveServerConfig = (flags, cliLogLevel, options) => require_Schema$1.ge
314748
314794
  forgeCodexHomePath: env.forgeCodexHomePath,
314749
314795
  forgeClaudeConfigPath: env.forgeClaudeConfigPath,
314750
314796
  forgeApexBaseUrl: env.forgeApexBaseUrl,
314751
- cloudProjectsRoot: env.cloudProjectsRoot ?? "/data/Projects"
314797
+ cloudProjectsRoot: env.cloudProjectsRoot ?? "/projects"
314752
314798
  };
314753
314799
  if (config.forgeCloudShellMode === true && (!config.forgeCloudOwnerAssertionPublicKey?.trim() || !config.forgeCloudOwnerAssertionKeyId?.trim())) return yield* require_Schema$1.die(/* @__PURE__ */ new Error("FORGE_CMMD_CLOUD_OWNER_ASSERTION_PUBLIC_KEY and FORGE_CMMD_CLOUD_OWNER_ASSERTION_KEY_ID are required in cloud-shell mode; runtime ticket keys are not accepted for Cloud owner assertions."));
314754
314800
  if (config.forgeCloudShellMode === true && !isEd25519PublicKey(config.forgeCloudOwnerAssertionPublicKey ?? "")) return yield* require_Schema$1.die(/* @__PURE__ */ new Error("FORGE_CMMD_CLOUD_OWNER_ASSERTION_PUBLIC_KEY must be a valid Ed25519 public key in cloud-shell mode."));
package/dist/bin.mjs CHANGED
@@ -65120,7 +65120,7 @@ function normalizeNumberish(value) {
65120
65120
  }
65121
65121
  //#endregion
65122
65122
  //#region package.json
65123
- var version$1 = "0.10.5";
65123
+ var version$1 = "0.10.6";
65124
65124
  //#endregion
65125
65125
  //#region src/sentry.ts
65126
65126
  const SERVER_APP_NAME = "forge-server";
@@ -67888,6 +67888,15 @@ function parsePersistedServerObservabilitySettings(raw) {
67888
67888
  * @module ServerConfig
67889
67889
  */
67890
67890
  const DEFAULT_PORT = 13773;
67891
+ /**
67892
+ * Where a managed cloud runtime keeps the user's checkouts when
67893
+ * FORGE_CLOUD_PROJECTS_ROOT is not set. CMMD seeds every sprite checkout under
67894
+ * /projects (forge-guest-layout.ts on the CMMD side) and passes that value in
67895
+ * the Service env, so this default only matters for a server started without
67896
+ * it. It used to be a path under the Fly-era mounted volume; on a sprite the
67897
+ * two repos disagreed and every local-checkout turn was refused (FOR-36484).
67898
+ */
67899
+ const DEFAULT_CLOUD_PROJECTS_ROOT = "/projects";
67891
67900
  const RuntimeMode = Literals(["web", "desktop"]);
67892
67901
  Literals(["browser", "headless"]);
67893
67902
  const deriveServerPaths = fn$1(function* (baseDir, _devUrl, _mode) {
@@ -68013,7 +68022,7 @@ var ServerConfig = class ServerConfig extends Service$1()("forge/config/ServerCo
68013
68022
  forgeCodexHomePath: void 0,
68014
68023
  forgeClaudeConfigPath: void 0,
68015
68024
  forgeApexBaseUrl: void 0,
68016
- cloudProjectsRoot: "/data/Projects",
68025
+ cloudProjectsRoot: DEFAULT_CLOUD_PROJECTS_ROOT,
68017
68026
  ...overrides
68018
68027
  };
68019
68028
  }));
@@ -97138,7 +97147,7 @@ const resolveAutoBootstrapWelcomeTargets = gen(function* () {
97138
97147
  /**
97139
97148
  * Cloud-mode project recovery — runs only on cloud execution runtimes.
97140
97149
  * Scans `cloudProjectsRoot` (default
97141
- * /data/Projects) for git-repo subdirectories and registers any not yet in
97150
+ * /projects) for git-repo subdirectories and registers any not yet in
97142
97151
  * the orchestration engine. This is the cloud-mode replacement for the
97143
97152
  * gated `autoBootstrapProjectFromCwd` path: managed runtimes whose volume
97144
97153
  * already holds cloned repos surface them in the sidebar after restart.
@@ -149397,13 +149406,40 @@ var CodexAppServerManager = class extends EventEmitter$1 {
149397
149406
  if (!providerConversationId) return;
149398
149407
  return context.collabReceiverTurns.get(providerConversationId);
149399
149408
  }
149409
+ /**
149410
+ * The child threads one thread item says the turn spawned.
149411
+ *
149412
+ * Two item shapes name a child, and which one arrives depends on the Codex
149413
+ * build. `CollabAgentToolCallThreadItem` lists `receiverThreadIds`, which
149414
+ * "in case of spawn operation ... corresponds to the newly spawned agent".
149415
+ * `SubAgentActivityThreadItem` names a single `agentThreadId` and is what a
149416
+ * `spawn_agent` call reports on codex-cli 0.152/0.153: measured on the
149417
+ * packaged desktop on 2026-09-06, the spawn arrived as `SubAgentActivity`
149418
+ * (`kind: started`) and the only collab tool call that followed was the
149419
+ * `wait`, whose `receiverThreadIds` was empty. Reading only the collab item
149420
+ * left the child unmapped, so its spend was published as a second turn row
149421
+ * under the child's own turn id instead of a subagent row under the parent's.
149422
+ *
149423
+ * `SubAgentActivityThreadItem` has no `model` field, so a `completed` report
149424
+ * for a child a collab call already named must not blank the model out; the
149425
+ * caller's `model ?? known` merge is what keeps it.
149426
+ */
149427
+ readSpawnedThreadIds(item, itemType) {
149428
+ if (itemType === "subAgentActivity") {
149429
+ const agentThreadId = this.readString(item, "agentThreadId");
149430
+ return agentThreadId ? [agentThreadId] : [];
149431
+ }
149432
+ if (itemType !== "collabAgentToolCall") return [];
149433
+ return this.readArray(item, "receiverThreadIds")?.map((value) => typeof value === "string" ? value : null).filter((value) => value !== null) ?? [];
149434
+ }
149400
149435
  rememberCollabReceiverTurns(context, params, parentTurnId) {
149401
149436
  if (!parentTurnId) return;
149402
149437
  const payload = this.readObject(params);
149403
149438
  const item = this.readObject(payload, "item") ?? payload;
149404
- if ((this.readString(item, "type") ?? this.readString(item, "kind")) !== "collabAgentToolCall") return;
149439
+ const itemType = this.readString(item, "type") ?? this.readString(item, "kind");
149440
+ const receiverThreadIds = this.readSpawnedThreadIds(item, itemType);
149441
+ if (receiverThreadIds.length === 0) return;
149405
149442
  const model = this.readString(item, "model");
149406
- const receiverThreadIds = this.readArray(item, "receiverThreadIds")?.map((value) => typeof value === "string" ? value : null).filter((value) => value !== null) ?? [];
149407
149443
  for (const receiverThreadId of receiverThreadIds) {
149408
149444
  const known = context.collabReceiverTurns.get(receiverThreadId)?.model;
149409
149445
  const resolved = model ?? known;
@@ -149419,8 +149455,8 @@ var CodexAppServerManager = class extends EventEmitter$1 {
149419
149455
  * Codex reports a child thread's tokens on the parent's own connection:
149420
149456
  * `ThreadTokenUsageUpdatedNotification` requires `threadId` and `turnId` and
149421
149457
  * names the child thread for a child, and `Thread.parentThreadId` is "only
149422
- * set if this thread is a subagent" (codex 0.144.6 app-server protocol
149423
- * schema). Every other child notification is suppressed so it cannot replace
149458
+ * set if this thread is a subagent" (still true of the codex-cli 0.153
149459
+ * app-server protocol schema). Every other child notification is suppressed so it cannot replace
149424
149460
  * the parent turn; this one is not, because the tokens belong on the ledger.
149425
149461
  * The method is Forge's own rather than the protocol's, because the payload
149426
149462
  * carries what the Usage row needs rather than what the notification held.
@@ -207216,11 +207252,14 @@ function mapCodexThreadTokenUsageEvent(event, canonicalThreadId, payload) {
207216
207252
  *
207217
207253
  * The source is the live app-server protocol, not a rollout read: Codex sends
207218
207254
  * `thread/tokenUsage/updated` for a child thread on the parent's own
207219
- * connection (0.144.6 schema: `ThreadTokenUsageUpdatedNotification` requires
207220
- * `threadId` and `turnId`, `Thread.parentThreadId` is set only for a subagent,
207221
- * and `CollabAgentToolCallThreadItem` names `receiverThreadIds` and the
207222
- * spawned agent's `model`), and `codexAppServerManager` already tracked those
207223
- * child threads to route their notifications onto the parent turn.
207255
+ * connection (`ThreadTokenUsageUpdatedNotification` requires `threadId` and
207256
+ * `turnId`, and `Thread.parentThreadId` is set only for a subagent), and
207257
+ * `codexAppServerManager` already tracked those child threads to route their
207258
+ * notifications onto the parent turn. It learns a child from whichever item
207259
+ * the running Codex build uses to announce a spawn: the
207260
+ * `receiverThreadIds` of a `CollabAgentToolCallThreadItem`, which also names
207261
+ * the spawned agent's `model`, or the `agentThreadId` of a
207262
+ * `SubAgentActivityThreadItem`, which names no model.
207224
207263
  *
207225
207264
  * The row carries no context-meter snapshot and no `turnUsage`: the parent's
207226
207265
  * own row is never re-summed with its children. It carries the call's delta
@@ -208102,7 +208141,8 @@ const CODE_BY_UPSTREAM_REASON$1 = {
208102
208141
  credential_expired_refreshing: "CREDENTIAL_EXPIRED_REFRESHING",
208103
208142
  credential_reconnect_required: "CREDENTIAL_RECONNECT_REQUIRED",
208104
208143
  credential_not_connected: "CREDENTIAL_RECONNECT_REQUIRED",
208105
- credential_generation_not_applied: "CREDENTIAL_GENERATION_NOT_APPLIED"
208144
+ credential_generation_not_applied: "CREDENTIAL_GENERATION_NOT_APPLIED",
208145
+ runtime_unavailable: "RUNTIME_UNAVAILABLE"
208106
208146
  };
208107
208147
  const CLAUDE_NATIVE_CREDENTIAL_UNUSABLE_COPY = "The delivered Claude credential is unavailable or unusable in this runtime.";
208108
208148
  /**
@@ -208165,10 +208205,17 @@ function claudeNativeCredentialUnusableMessage() {
208165
208205
  * CMMD writes this marker when it activates a personal Claude subscription
208166
208206
  * inside a running sprite. Activation always happens after boot, so a
208167
208207
  * boot-time env var alone cannot reflect it (FOR-36249).
208208
+ *
208209
+ * CMMD names the file in the Service env (FORGE_PERSONAL_CLAUDE_MARKER_PATH).
208210
+ * Without that, the marker sits directly under FORGE_HOME, which is the same
208211
+ * guest home CMMD derives every sprite path from. A server with neither has no
208212
+ * sprite home to look in, and a desktop never has a marker, so it reads none.
208168
208213
  */
208169
- const PERSONAL_CLAUDE_IN_VM_MARKER_PATH = "/data/.forge-personal-claude-in-vm";
208214
+ const PERSONAL_CLAUDE_IN_VM_MARKER_NAME = ".forge-personal-claude-in-vm";
208170
208215
  function markerPath(env) {
208171
- return env.FORGE_PERSONAL_CLAUDE_MARKER_PATH || PERSONAL_CLAUDE_IN_VM_MARKER_PATH;
208216
+ if (env.FORGE_PERSONAL_CLAUDE_MARKER_PATH) return env.FORGE_PERSONAL_CLAUDE_MARKER_PATH;
208217
+ if (env.FORGE_HOME) return join(env.FORGE_HOME, PERSONAL_CLAUDE_IN_VM_MARKER_NAME);
208218
+ return null;
208172
208219
  }
208173
208220
  /**
208174
208221
  * True when this runtime should offer the personal Claude subscription lane.
@@ -208181,8 +208228,10 @@ function markerPath(env) {
208181
208228
  */
208182
208229
  function personalClaudeInVmEnabled(env = process.env) {
208183
208230
  if (env.FORGE_PERSONAL_CLAUDE_IN_VM === "true") return true;
208231
+ const marker = markerPath(env);
208232
+ if (!marker) return false;
208184
208233
  try {
208185
- return existsSync(markerPath(env));
208234
+ return existsSync(marker);
208186
208235
  } catch {
208187
208236
  return false;
208188
208237
  }
@@ -226762,7 +226811,8 @@ const CLAUDE_READINESS_COPY = {
226762
226811
  failed: "Claude native runtime setup could not be applied. Reconnect Claude in Settings.",
226763
226812
  invalid: "Claude native runtime readiness is no longer valid. Reconnect Claude in Settings.",
226764
226813
  unavailable: "Claude native runtime readiness could not be verified.",
226765
- generationMismatch: "Claude native runtime generation does not match CMMD readiness."
226814
+ generationMismatch: "Claude native runtime generation does not match CMMD readiness.",
226815
+ environmentUnavailable: "This Environment is not running, so Claude cannot run on it. Restart the Environment, then try again."
226766
226816
  };
226767
226817
  var ClaudeRuntimeReadinessError = class extends Error {
226768
226818
  constructor(safeIssue, retryable = false, retryProfile = "default") {
@@ -226832,6 +226882,7 @@ async function withReadinessRetry(attempt) {
226832
226882
  */
226833
226883
  function readinessReasonIssue(readiness) {
226834
226884
  const code = claudeReadinessReasonCode(readiness.reason);
226885
+ if (code === "RUNTIME_UNAVAILABLE") return CLAUDE_READINESS_COPY.environmentUnavailable;
226835
226886
  if (code === "CREDENTIAL_RECONNECT_REQUIRED") return CLAUDE_READINESS_COPY.invalid;
226836
226887
  if (code === "CREDENTIAL_GENERATION_NOT_APPLIED") return CLAUDE_READINESS_COPY.applying;
226837
226888
  if (code !== "CREDENTIAL_EXPIRED_REFRESHING") return null;
@@ -226842,6 +226893,10 @@ function readinessReasonIssue(readiness) {
226842
226893
  function isCredentialRefreshInFlight(readiness) {
226843
226894
  return claudeReadinessReasonCode(readiness.reason) === "CREDENTIAL_EXPIRED_REFRESHING";
226844
226895
  }
226896
+ /** True when CMMD says the runtime itself cannot take a delivery (CMMD-36473). */
226897
+ function isRuntimeUnavailable(readiness) {
226898
+ return claudeReadinessReasonCode(readiness.reason) === "RUNTIME_UNAVAILABLE";
226899
+ }
226845
226900
  function readinessFailureIssue(readiness) {
226846
226901
  const reasonIssue = readinessReasonIssue(readiness);
226847
226902
  if (reasonIssue !== null) return reasonIssue;
@@ -226881,11 +226936,12 @@ function verifiedClaudeDeliveryBinding(readiness, authority) {
226881
226936
  function appliedClaudeGeneration(readiness) {
226882
226937
  if (readiness.connected !== true || readiness.deliveryStatus !== "applied" || readiness.nativeExecutable !== true || typeof readiness.generationId !== "string" || readiness.generationId.trim().length === 0) {
226883
226938
  const refreshing = isCredentialRefreshInFlight(readiness);
226884
- throw new ClaudeRuntimeReadinessError(readinessFailureIssue(readiness), refreshing || [
226939
+ const retryable = !isRuntimeUnavailable(readiness) && (refreshing || [
226885
226940
  "pending",
226886
226941
  "claimed",
226887
226942
  "activating"
226888
- ].includes(readiness.deliveryStatus), refreshing ? "credentialRefresh" : "default");
226943
+ ].includes(readiness.deliveryStatus));
226944
+ throw new ClaudeRuntimeReadinessError(readinessFailureIssue(readiness), retryable, refreshing ? "credentialRefresh" : "default");
226889
226945
  }
226890
226946
  return readiness.generationId;
226891
226947
  }
@@ -228039,15 +228095,15 @@ const collectOutput = fn$1("collectOutput")(function* (input, stream, maxOutputB
228039
228095
  /**
228040
228096
  * Adds a `safe.directory` exception to a git child environment.
228041
228097
  *
228042
- * Forge runs git against workspaces on a mounted volume (`/data/Projects/...` on
228043
- * Fly). A volume mount replaces the build-time ownership of its mountpoint, so a
228098
+ * Forge runs git against workspaces on a mounted volume (`<cloudProjectsRoot>/...`
228099
+ * on Fly). A volume mount replaces the build-time ownership of its mountpoint, so a
228044
228100
  * repository there can be owned by a uid other than the server's, and git then
228045
228101
  * refuses EVERY command against it with "detected dubious ownership" — the
228046
228102
  * FORGE-2T failure in `CheckpointStore.captureCheckpoint`.
228047
228103
  *
228048
228104
  * The exception has to be `*`, verified against git 2.43:
228049
228105
  * - git compares `safe.directory` entries literally, so a prefix such as
228050
- * `/data/Projects/*` does not match the repository at all.
228106
+ * `/projects/*` does not match the repository at all.
228051
228107
  * - the value must name the DISCOVERED REPOSITORY ROOT, which is an ancestor of
228052
228108
  * `cwd` whenever a command runs from a subdirectory. Resolving that root means
228053
228109
  * asking git, which is the command being refused.
@@ -290891,7 +290947,7 @@ const ServerLoggerLive = gen(function* () {
290891
290947
  * Observed live on a Forge Cloud sprite (2026-07-25): the browser opens
290892
290948
  * `wss://<sprite>.sprites.app/ws?routeKey=…&runtimeTicket=<JWT>`, and the HTTP
290893
290949
  * instrumentation records `url.full` / `url.query` verbatim. The ticket then
290894
- * lands in `/data/userdata/logs/server.trace.ndjson` at mode 644 — readable by
290950
+ * lands in `<FORGE_HOME>/userdata/logs/server.trace.ndjson` at mode 644 — readable by
290895
290951
  * the same user the agent runs as — and the URL also crosses fly.io's edge,
290896
290952
  * where infrastructure we do not control may log it.
290897
290953
  *
@@ -291183,7 +291239,7 @@ function resolveBuildCommitFromEnv(env) {
291183
291239
  * environment descriptor down instead of reporting an honest "unknown".
291184
291240
  */
291185
291241
  function readBakedBuildCommit() {
291186
- return "3a8f4c1280c7611f1850f146a6792e13b754bb4b";
291242
+ return "5f0060a9696edd41f61f06cbf24450a5994fed33";
291187
291243
  }
291188
291244
  async function resolveServerBuildCommit(input) {
291189
291245
  if (isFullCommitSha(input.baked)) return input.baked;
@@ -299172,16 +299228,6 @@ function describeDispatchCause(cause) {
299172
299228
  if (deepest === void 0 || deepest.length <= DISPATCH_CAUSE_DETAIL_LIMIT) return deepest;
299173
299229
  return `${deepest.slice(0, DISPATCH_CAUSE_DETAIL_LIMIT)}...`;
299174
299230
  }
299175
- /**
299176
- * Where automation-created projects live when the caller does not say.
299177
- *
299178
- * This is the documented default of the `cloudProjectsRoot` setting
299179
- * (FORGE_CLOUD_PROJECTS_ROOT, see cli.ts) and exists only for direct callers
299180
- * such as tests. Every HTTP route passes the CONFIGURED value instead: reading
299181
- * the default here is what made a runtime configured with any other root create
299182
- * its automation projects in a directory nothing else read.
299183
- */
299184
- const DEFAULT_CLOUD_PROJECTS_ROOT = "/data/Projects";
299185
299231
  const respondToOrchestrationHttpError = (error) => gen(function* () {
299186
299232
  if (error._tag === "OrchestrationGetSnapshotError") {
299187
299233
  yield* logError("orchestration http route failed", {
@@ -314093,7 +314139,7 @@ const resolveServerConfig = (flags, cliLogLevel, options) => gen(function* () {
314093
314139
  forgeCodexHomePath: env.forgeCodexHomePath,
314094
314140
  forgeClaudeConfigPath: env.forgeClaudeConfigPath,
314095
314141
  forgeApexBaseUrl: env.forgeApexBaseUrl,
314096
- cloudProjectsRoot: env.cloudProjectsRoot ?? "/data/Projects"
314142
+ cloudProjectsRoot: env.cloudProjectsRoot ?? "/projects"
314097
314143
  };
314098
314144
  if (config.forgeCloudShellMode === true && (!config.forgeCloudOwnerAssertionPublicKey?.trim() || !config.forgeCloudOwnerAssertionKeyId?.trim())) return yield* die$1(/* @__PURE__ */ new Error("FORGE_CMMD_CLOUD_OWNER_ASSERTION_PUBLIC_KEY and FORGE_CMMD_CLOUD_OWNER_ASSERTION_KEY_ID are required in cloud-shell mode; runtime ticket keys are not accepted for Cloud owner assertions."));
314099
314145
  if (config.forgeCloudShellMode === true && !isEd25519PublicKey(config.forgeCloudOwnerAssertionPublicKey ?? "")) return yield* die$1(/* @__PURE__ */ new Error("FORGE_CMMD_CLOUD_OWNER_ASSERTION_PUBLIC_KEY must be a valid Ed25519 public key in cloud-shell mode."));
@@ -1,4 +1,4 @@
1
- import{r as e}from"./rolldown-runtime-hePW80VL.js";import{Ba as t,Va as n,ki as r,za as i}from"./Stream-C4tOsbfQ.js";import{Bn as a,Dr as o,Ds as s,In as c,Kn as l,Mn as u,Ms as d,On as f,Sr as p,Ss as m,Ui as h,Ur as g,Xt as _,_ as v,ba as y,br as b,d as x,hn as S,i as C,js as w,ks as T,l as E,m as D,mc as O,n as k,qi as A,r as j,ra as M,u as N}from"./DiffPanelShell-h78vZ6dX.js";import{xn as P}from"./CompositeItem-Cj6_oAlz.js";import{a as F,c as I,f as L,i as R,l as z,m as B,n as V,o as H,p as U,r as W,s as G,t as K}from"./Virtualizer-CQJMsfKa.js";import{Cn as q,G as J,W as ee}from"./src-CtyKlVph.js";import{a as te,c as ne,d as re,h as ie,i as ae,l as oe,m as se,n as ce,o as Y,p as le,r as ue,s as de,t as fe,u as pe}from"./DiffPanel.logic-Cyp3p58B.js";var X=e(n(),1),me=typeof window>`u`?X.useEffect:X.useLayoutEffect;function he({fileDiff:e,options:t,editorOptions:n,lineAnnotations:r,selectedLines:i,prerenderedHTML:a,metrics:o,hasGutterRenderUtility:s,hasCustomHeader:c,disableWorkerPool:l,edit:u}){let d=V(),f=i!==void 0,p=(0,X.useContext)(C),m=N(),h=(0,X.useRef)(null),g=x(n=>{if(n!=null){if(h.current!=null)throw Error(`useFileDiffInstance: An instance should not already exist when a node is created`);d==null?h.current=new re(Z({controlledSelection:f,hasCustomHeader:c,hasGutterRenderUtility:s,options:t}),l?void 0:p,!0):h.current=new pe(Z({controlledSelection:f,hasCustomHeader:c,hasGutterRenderUtility:s,options:t}),d,o,l?void 0:p,!0),h.current.hydrate({fileDiff:e,fileContainer:n,lineAnnotations:r,prerenderedHTML:a})}else{if(h.current==null)throw Error(`useFileDiffInstance: A FileDiff instance should exist when unmounting`);h.current.cleanUp(),h.current=null}});return me(()=>{let{current:n}=h;if(n==null)return;let a=Z({controlledSelection:f,hasCustomHeader:c,hasGutterRenderUtility:s,options:t}),o=a!==void 0&&!_(n.options,a);n.setOptions(a),n.render({forceRender:o,fileDiff:e,lineAnnotations:r}),i!==void 0&&n.setSelectedLines(i)}),me(()=>{if(u&&h.current!=null){if(m===void 0)throw Error(`FileDiff: EditContext is not attached`);let e=m(n??{});if(e==null)throw Error(`FileDiff: EditProvider.createEditor must return an editor instance`);try{return e.edit(h.current)}catch(t){throw e.cleanUp(),t}}},[u]),{ref:g,getHoveredLine:(0,X.useCallback)(()=>h.current?.getHoveredLine(),[])}}function Z({options:e,controlledSelection:t,hasCustomHeader:n,hasGutterRenderUtility:r}){return t||r||n?{...e,controlledSelection:t,renderCustomHeader:n?E:e?.renderCustomHeader,renderGutterUtility:r?E:e?.renderGutterUtility}:e}var Q=t();function ge({fileDiff:e,options:t,editorOptions:n,metrics:r,lineAnnotations:i,selectedLines:a,className:o,style:s,prerenderedHTML:c,renderAnnotation:l,renderCustomHeader:u,renderHeaderPrefix:d,renderHeaderFilenameSuffix:f,renderHeaderMetadata:p,renderGutterUtility:m,disableWorkerPool:h=!1,edit:g=!1}){let{ref:_,getHoveredLine:v}=he({fileDiff:e,options:t,editorOptions:n,metrics:r,lineAnnotations:i,selectedLines:a,prerenderedHTML:c,hasGutterRenderUtility:m!=null,hasCustomHeader:u!=null,disableWorkerPool:h,edit:g});return(0,Q.jsx)(S,{ref:_,className:o,style:s,children:W(oe({fileDiff:e,renderCustomHeader:u,renderHeaderPrefix:d,renderHeaderFilenameSuffix:f,renderHeaderMetadata:p,renderAnnotation:l,renderGutterUtility:m,lineAnnotations:i,getHoveredLine:v}),c)})}var $=i();function _e(e){return e.fromTurnCount===0?q(ee)({threadId:e.threadId,toTurnCount:e.toTurnCount}).pipe(r(e=>({kind:`fullThreadDiff`,input:e}))):q(J)({threadId:e.threadId,fromTurnCount:e.fromTurnCount,toTurnCount:e.toTurnCount}).pipe(r(e=>({kind:`turnDiff`,input:e})))}function ve(e){return e instanceof Error?e.message:typeof e==`string`?e:``}function ye(e){let t=ve(e).trim();if(t.length===0)return`Failed to load checkpoint diff.`;let n=t.toLowerCase();if(n.includes(`not a git repository`))return`Turn diffs are unavailable because this project is not a git repository.`;if(n.includes(`checkpoint unavailable for thread`)||n.includes(`checkpoint invariant violation`)){let e=t.indexOf(`:`);if(e>=0){let n=t.slice(e+1).trim();if(n.length>0)return n}}return t}function be(e){let t=ve(e).toLowerCase();return t.includes(`exceeds current turn count`)||t.includes(`checkpoint is unavailable for turn`)||t.includes(`filesystem checkpoint is unavailable`)}function xe(e){let t=_e(e);return w({queryKey:h.checkpointDiff(e),queryFn:async({signal:n})=>{if(!e.environmentId||!e.threadId||t._tag===`None`)throw Error(`Checkpoint diff is unavailable.`);let r=l(e.environmentId);try{return t.value.kind===`fullThreadDiff`?await r.orchestration.getFullThreadDiff(t.value.input,{signal:n}):await r.orchestration.getTurnDiff(t.value.input,{signal:n})}catch(e){throw Error(ye(e),{cause:e})}},enabled:(e.enabled??!0)&&!!e.environmentId&&!!e.threadId&&t._tag===`Some`,staleTime:1/0,retry:(e,t)=>be(t)?e<12:e<3,retryDelay:(e,t)=>be(t)?Math.min(5e3,250*2**(e-1)):Math.min(1e3,100*2**(e-1))})}function Se(e){if(!(!e.canScrollLeft&&!e.canScrollRight))return{maskImage:`linear-gradient(to right, ${e.canScrollLeft?`transparent 24px, black 72px`:`black`}, ${e.canScrollRight?`black calc(100% - 72px), transparent calc(100% - 24px)`:`black`})`}}function Ce(e){return e instanceof Error?e.message:e?`Failed to load checkpoint diff.`:null}function we(e){return{environmentId:e.environmentId??null,threadId:e.threadId,fromTurnCount:e.range?.fromTurnCount??null,toTurnCount:e.range?.toTurnCount??null,cacheScope:e.selectedTurnId?`turn:${e.selectedTurnId}`:e.conversationCacheScope,enabled:e.enabled}}function Te(){let e=(0,$.c)(8),t=(0,X.useRef)(null),[n,r]=(0,X.useState)(!1),[i,a]=(0,X.useState)(!1),o;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(o=()=>{let e=t.current;if(!e){r(!1),a(!1);return}let n=de({scrollLeft:e.scrollLeft,scrollWidth:e.scrollWidth,clientWidth:e.clientWidth});r(n.canScrollLeft),a(n.canScrollRight)},e[0]=o):o=e[0];let s=o,c;e[1]===Symbol.for(`react.memo_cache_sentinel`)?(c=e=>{t.current?.scrollBy({left:e,behavior:`smooth`})},e[1]=c):c=e[1];let l=c,u;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(u=e=>{let n=t.current;n&&ne({scrollWidth:n.scrollWidth,clientWidth:n.clientWidth,deltaX:e.deltaX,deltaY:e.deltaY})&&(e.preventDefault(),n.scrollBy({left:e.deltaY,behavior:`auto`}))},e[2]=u):u=e[2];let d=u,f,p;e[3]===Symbol.for(`react.memo_cache_sentinel`)?(f=()=>{let e=t.current;if(!e)return;let n=window.requestAnimationFrame(s),r=()=>s();e.addEventListener(`scroll`,r,{passive:!0});let i=new ResizeObserver(()=>s());return i.observe(e),()=>{window.cancelAnimationFrame(n),e.removeEventListener(`scroll`,r),i.disconnect()}},p=[s],e[3]=f,e[4]=p):(f=e[3],p=e[4]),(0,X.useEffect)(f,p);let m;return e[5]!==n||e[6]!==i?(m={ref:t,canScrollLeft:n,canScrollRight:i,scrollBy:l,onWheel:d,remeasure:s},e[5]=n,e[6]=i,e[7]=m):m=e[7],m}function Ee(e,t){let n=(0,$.c)(5),r;n[0]===e.current?r=n[1]:(r=()=>{(e.current?.querySelector(`[data-turn-chip-selected='true']`))?.scrollIntoView({block:`nearest`,inline:`nearest`,behavior:`smooth`})},n[0]=e.current,n[1]=r);let i;n[2]!==e||n[3]!==t?(i=[e,t],n[2]=e,n[3]=t,n[4]=i):i=n[4],(0,X.useEffect)(r,i)}var De=`
1
+ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{Ba as t,Va as n,ki as r,za as i}from"./Stream-C4tOsbfQ.js";import{Bn as a,Dr as o,Ds as s,In as c,Kn as l,Mn as u,Ms as d,On as f,Sr as p,Ss as m,Ui as h,Ur as g,Xt as _,_ as v,ba as y,br as b,d as x,hn as S,i as C,js as w,ks as T,l as E,m as D,mc as O,n as k,qi as A,r as j,ra as M,u as N}from"./DiffPanelShell-AKUK0L-g.js";import{xn as P}from"./CompositeItem-Cj6_oAlz.js";import{a as F,c as I,f as L,i as R,l as z,m as B,n as V,o as H,p as U,r as W,s as G,t as K}from"./Virtualizer-BXpiamky.js";import{Cn as q,G as J,W as ee}from"./src-CtyKlVph.js";import{a as te,c as ne,d as re,h as ie,i as ae,l as oe,m as se,n as ce,o as Y,p as le,r as ue,s as de,t as fe,u as pe}from"./DiffPanel.logic-BiWRNb4k.js";var X=e(n(),1),me=typeof window>`u`?X.useEffect:X.useLayoutEffect;function he({fileDiff:e,options:t,editorOptions:n,lineAnnotations:r,selectedLines:i,prerenderedHTML:a,metrics:o,hasGutterRenderUtility:s,hasCustomHeader:c,disableWorkerPool:l,edit:u}){let d=V(),f=i!==void 0,p=(0,X.useContext)(C),m=N(),h=(0,X.useRef)(null),g=x(n=>{if(n!=null){if(h.current!=null)throw Error(`useFileDiffInstance: An instance should not already exist when a node is created`);d==null?h.current=new re(Z({controlledSelection:f,hasCustomHeader:c,hasGutterRenderUtility:s,options:t}),l?void 0:p,!0):h.current=new pe(Z({controlledSelection:f,hasCustomHeader:c,hasGutterRenderUtility:s,options:t}),d,o,l?void 0:p,!0),h.current.hydrate({fileDiff:e,fileContainer:n,lineAnnotations:r,prerenderedHTML:a})}else{if(h.current==null)throw Error(`useFileDiffInstance: A FileDiff instance should exist when unmounting`);h.current.cleanUp(),h.current=null}});return me(()=>{let{current:n}=h;if(n==null)return;let a=Z({controlledSelection:f,hasCustomHeader:c,hasGutterRenderUtility:s,options:t}),o=a!==void 0&&!_(n.options,a);n.setOptions(a),n.render({forceRender:o,fileDiff:e,lineAnnotations:r}),i!==void 0&&n.setSelectedLines(i)}),me(()=>{if(u&&h.current!=null){if(m===void 0)throw Error(`FileDiff: EditContext is not attached`);let e=m(n??{});if(e==null)throw Error(`FileDiff: EditProvider.createEditor must return an editor instance`);try{return e.edit(h.current)}catch(t){throw e.cleanUp(),t}}},[u]),{ref:g,getHoveredLine:(0,X.useCallback)(()=>h.current?.getHoveredLine(),[])}}function Z({options:e,controlledSelection:t,hasCustomHeader:n,hasGutterRenderUtility:r}){return t||r||n?{...e,controlledSelection:t,renderCustomHeader:n?E:e?.renderCustomHeader,renderGutterUtility:r?E:e?.renderGutterUtility}:e}var Q=t();function ge({fileDiff:e,options:t,editorOptions:n,metrics:r,lineAnnotations:i,selectedLines:a,className:o,style:s,prerenderedHTML:c,renderAnnotation:l,renderCustomHeader:u,renderHeaderPrefix:d,renderHeaderFilenameSuffix:f,renderHeaderMetadata:p,renderGutterUtility:m,disableWorkerPool:h=!1,edit:g=!1}){let{ref:_,getHoveredLine:v}=he({fileDiff:e,options:t,editorOptions:n,metrics:r,lineAnnotations:i,selectedLines:a,prerenderedHTML:c,hasGutterRenderUtility:m!=null,hasCustomHeader:u!=null,disableWorkerPool:h,edit:g});return(0,Q.jsx)(S,{ref:_,className:o,style:s,children:W(oe({fileDiff:e,renderCustomHeader:u,renderHeaderPrefix:d,renderHeaderFilenameSuffix:f,renderHeaderMetadata:p,renderAnnotation:l,renderGutterUtility:m,lineAnnotations:i,getHoveredLine:v}),c)})}var $=i();function _e(e){return e.fromTurnCount===0?q(ee)({threadId:e.threadId,toTurnCount:e.toTurnCount}).pipe(r(e=>({kind:`fullThreadDiff`,input:e}))):q(J)({threadId:e.threadId,fromTurnCount:e.fromTurnCount,toTurnCount:e.toTurnCount}).pipe(r(e=>({kind:`turnDiff`,input:e})))}function ve(e){return e instanceof Error?e.message:typeof e==`string`?e:``}function ye(e){let t=ve(e).trim();if(t.length===0)return`Failed to load checkpoint diff.`;let n=t.toLowerCase();if(n.includes(`not a git repository`))return`Turn diffs are unavailable because this project is not a git repository.`;if(n.includes(`checkpoint unavailable for thread`)||n.includes(`checkpoint invariant violation`)){let e=t.indexOf(`:`);if(e>=0){let n=t.slice(e+1).trim();if(n.length>0)return n}}return t}function be(e){let t=ve(e).toLowerCase();return t.includes(`exceeds current turn count`)||t.includes(`checkpoint is unavailable for turn`)||t.includes(`filesystem checkpoint is unavailable`)}function xe(e){let t=_e(e);return w({queryKey:h.checkpointDiff(e),queryFn:async({signal:n})=>{if(!e.environmentId||!e.threadId||t._tag===`None`)throw Error(`Checkpoint diff is unavailable.`);let r=l(e.environmentId);try{return t.value.kind===`fullThreadDiff`?await r.orchestration.getFullThreadDiff(t.value.input,{signal:n}):await r.orchestration.getTurnDiff(t.value.input,{signal:n})}catch(e){throw Error(ye(e),{cause:e})}},enabled:(e.enabled??!0)&&!!e.environmentId&&!!e.threadId&&t._tag===`Some`,staleTime:1/0,retry:(e,t)=>be(t)?e<12:e<3,retryDelay:(e,t)=>be(t)?Math.min(5e3,250*2**(e-1)):Math.min(1e3,100*2**(e-1))})}function Se(e){if(!(!e.canScrollLeft&&!e.canScrollRight))return{maskImage:`linear-gradient(to right, ${e.canScrollLeft?`transparent 24px, black 72px`:`black`}, ${e.canScrollRight?`black calc(100% - 72px), transparent calc(100% - 24px)`:`black`})`}}function Ce(e){return e instanceof Error?e.message:e?`Failed to load checkpoint diff.`:null}function we(e){return{environmentId:e.environmentId??null,threadId:e.threadId,fromTurnCount:e.range?.fromTurnCount??null,toTurnCount:e.range?.toTurnCount??null,cacheScope:e.selectedTurnId?`turn:${e.selectedTurnId}`:e.conversationCacheScope,enabled:e.enabled}}function Te(){let e=(0,$.c)(8),t=(0,X.useRef)(null),[n,r]=(0,X.useState)(!1),[i,a]=(0,X.useState)(!1),o;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(o=()=>{let e=t.current;if(!e){r(!1),a(!1);return}let n=de({scrollLeft:e.scrollLeft,scrollWidth:e.scrollWidth,clientWidth:e.clientWidth});r(n.canScrollLeft),a(n.canScrollRight)},e[0]=o):o=e[0];let s=o,c;e[1]===Symbol.for(`react.memo_cache_sentinel`)?(c=e=>{t.current?.scrollBy({left:e,behavior:`smooth`})},e[1]=c):c=e[1];let l=c,u;e[2]===Symbol.for(`react.memo_cache_sentinel`)?(u=e=>{let n=t.current;n&&ne({scrollWidth:n.scrollWidth,clientWidth:n.clientWidth,deltaX:e.deltaX,deltaY:e.deltaY})&&(e.preventDefault(),n.scrollBy({left:e.deltaY,behavior:`auto`}))},e[2]=u):u=e[2];let d=u,f,p;e[3]===Symbol.for(`react.memo_cache_sentinel`)?(f=()=>{let e=t.current;if(!e)return;let n=window.requestAnimationFrame(s),r=()=>s();e.addEventListener(`scroll`,r,{passive:!0});let i=new ResizeObserver(()=>s());return i.observe(e),()=>{window.cancelAnimationFrame(n),e.removeEventListener(`scroll`,r),i.disconnect()}},p=[s],e[3]=f,e[4]=p):(f=e[3],p=e[4]),(0,X.useEffect)(f,p);let m;return e[5]!==n||e[6]!==i?(m={ref:t,canScrollLeft:n,canScrollRight:i,scrollBy:l,onWheel:d,remeasure:s},e[5]=n,e[6]=i,e[7]=m):m=e[7],m}function Ee(e,t){let n=(0,$.c)(5),r;n[0]===e.current?r=n[1]:(r=()=>{(e.current?.querySelector(`[data-turn-chip-selected='true']`))?.scrollIntoView({block:`nearest`,inline:`nearest`,behavior:`smooth`})},n[0]=e.current,n[1]=r);let i;n[2]!==e||n[3]!==t?(i=[e,t],n[2]=e,n[3]=t,n[4]=i):i=n[4],(0,X.useEffect)(r,i)}var De=`
2
2
  [data-diffs-header],
3
3
  [data-diff],
4
4
  [data-file],
@@ -61,4 +61,4 @@ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{Ba as t,Va as n,ki as
61
61
  text-decoration-color: currentColor;
62
62
  }
63
63
  `;function Oe(e){let t=(0,$.c)(44),{mode:n}=e,r=n===void 0?`inline`:n,{resolvedTheme:i}=D(),c=p(),[l,d]=(0,X.useState)(`stacked`),[m,h]=(0,X.useState)(c.diffWordWrap),g=(0,X.useRef)(null),_=(0,X.useRef)(!1),v=Te(),{activeCwd:y,activeThread:b,bodyState:x,diffOpen:S,inferredCheckpointTurnCountByTurnId:C,orderedTurnDiffSummaries:w,renderableFiles:E,renderablePatch:O,selectedFilePath:k,selectedTurn:A,selectedTurnId:M}=Le(i),N,P;t[0]!==S||t[1]!==c.diffWordWrap?(N=()=>{S&&!_.current&&h(c.diffWordWrap),_.current=S},P=[S,c.diffWordWrap],t[0]=S,t[1]=c.diffWordWrap,t[2]=N,t[3]=P):(N=t[2],P=t[3]),(0,X.useEffect)(N,P);let F;t[4]===k?F=t[5]:(F=()=>{!k||!g.current||Array.from(g.current.querySelectorAll(`[data-diff-file-path]`)).find(e=>e.dataset.diffFilePath===k)?.scrollIntoView({block:`nearest`})},t[4]=k,t[5]=F);let I;t[6]!==E||t[7]!==k?(I=[k,E],t[6]=E,t[7]=k,t[8]=I):I=t[8],(0,X.useEffect)(F,I);let L;t[9]===y?L=t[10]:(L=e=>{let t=o();if(!t)return;let n=y?f(e,y):e;u(t,n).catch(ke)},t[9]=y,t[10]=L);let R=L,z;t[11]===b?z=t[12]:(z=e=>{b&&a.getState().openDiff(T(s(b.environmentId,b.id)),e)},t[11]=b,t[12]=z);let B=z,V;t[13]===b?V=t[14]:(V=()=>{b&&a.getState().openDiff(T(s(b.environmentId,b.id)))},t[13]=b,t[14]=V);let H=V,U;t[15]===v.remeasure?U=t[16]:(U=()=>{let e=window.requestAnimationFrame(v.remeasure);return()=>window.cancelAnimationFrame(e)},t[15]=v.remeasure,t[16]=U);let W;t[17]!==w||t[18]!==M||t[19]!==v.remeasure?(W=[w,M,v.remeasure],t[17]=w,t[18]=M,t[19]=v.remeasure,t[20]=W):W=t[20],(0,X.useEffect)(U,W),Ee(v.ref,A?.turnId??M);let G;t[21]!==l||t[22]!==m||t[23]!==C||t[24]!==w||t[25]!==B||t[26]!==H||t[27]!==A||t[28]!==M||t[29]!==c||t[30]!==v?(G=(0,Q.jsx)(Ae,{diffRenderMode:l,diffWordWrap:m,inferredCheckpointTurnCountByTurnId:C,orderedTurnDiffSummaries:w,selectTurn:B,selectWholeConversation:H,selectedTurn:A,selectedTurnId:M,setDiffRenderMode:d,setDiffWordWrap:h,settings:c,turnStrip:v}),t[21]=l,t[22]=m,t[23]=C,t[24]=w,t[25]=B,t[26]=H,t[27]=A,t[28]=M,t[29]=c,t[30]=v,t[31]=G):G=t[31];let K=G,q;t[32]!==x||t[33]!==l||t[34]!==m||t[35]!==R||t[36]!==E||t[37]!==O||t[38]!==i?(q=(0,Q.jsx)(je,{bodyState:x,diffRenderMode:l,diffWordWrap:m,openDiffFileInEditor:R,patchViewportRef:g,renderableFiles:E,renderablePatch:O,resolvedTheme:i}),t[32]=x,t[33]=l,t[34]=m,t[35]=R,t[36]=E,t[37]=O,t[38]=i,t[39]=q):q=t[39];let J;return t[40]!==K||t[41]!==r||t[42]!==q?(J=(0,Q.jsx)(j,{mode:r,header:K,children:q}),t[40]=K,t[41]=r,t[42]=q,t[43]=J):J=t[43],J}function ke(e){console.warn(`Failed to open diff file in editor.`,e)}function Ae(e){let t=(0,$.c)(59),{diffRenderMode:n,diffWordWrap:r,inferredCheckpointTurnCountByTurnId:i,orderedTurnDiffSummaries:a,selectTurn:o,selectWholeConversation:s,selectedTurn:c,selectedTurnId:l,setDiffRenderMode:u,setDiffWordWrap:d,settings:f,turnStrip:p}=e,m,h;t[0]===p?(m=t[1],h=t[2]):(m=(0,Q.jsx)(Be,{direction:`left`,strip:p}),h=(0,Q.jsx)(Be,{direction:`right`,strip:p}),t[0]=p,t[1]=m,t[2]=h);let g=p.ref,_;t[3]!==p.canScrollLeft||t[4]!==p.canScrollRight?(_=Se({canScrollLeft:p.canScrollLeft,canScrollRight:p.canScrollRight}),t[3]=p.canScrollLeft,t[4]=p.canScrollRight,t[5]=_):_=t[5];let v=p.onWheel,y=l===null,b=l===null?`border-border bg-accent text-accent-foreground`:`border-border/70 bg-background/70 text-muted-foreground/80 hover:border-border hover:text-foreground/80`,x;t[6]===b?x=t[7]:(x=P(`rounded-md border px-2 py-1 text-left transition-colors`,b),t[6]=b,t[7]=x);let S;t[8]===Symbol.for(`react.memo_cache_sentinel`)?(S=(0,Q.jsx)(`div`,{className:`text-[10px] leading-tight font-medium`,children:`All turns`}),t[8]=S):S=t[8];let C;t[9]===x?C=t[10]:(C=(0,Q.jsx)(`div`,{className:x,children:S}),t[9]=x,t[10]=C);let w;t[11]!==s||t[12]!==C||t[13]!==y?(w=(0,Q.jsx)(`button`,{type:`button`,className:`shrink-0 rounded-md`,onClick:s,"data-turn-chip-selected":y,children:C}),t[11]=s,t[12]=C,t[13]=y,t[14]=w):w=t[14];let T;if(t[15]!==i||t[16]!==a||t[17]!==o||t[18]!==c?.turnId||t[19]!==f){let e;t[21]!==i||t[22]!==o||t[23]!==c?.turnId||t[24]!==f?(e=e=>(0,Q.jsx)(Ve,{summary:e,selected:e.turnId===c?.turnId,turnCount:e.checkpointTurnCount??i[e.turnId],timestampFormat:f.timestampFormat,onSelect:o},e.turnId),t[21]=i,t[22]=o,t[23]=c?.turnId,t[24]=f,t[25]=e):e=t[25],T=a.map(e),t[15]=i,t[16]=a,t[17]=o,t[18]=c?.turnId,t[19]=f,t[20]=T}else T=t[20];let E;t[26]!==w||t[27]!==T||t[28]!==_||t[29]!==p.onWheel||t[30]!==p.ref?(E=(0,Q.jsxs)(`div`,{ref:g,className:`turn-chip-strip flex gap-1 overflow-x-auto px-8 py-0.5`,style:_,onWheel:v,children:[w,T]}),t[26]=w,t[27]=T,t[28]=_,t[29]=p.onWheel,t[30]=p.ref,t[31]=E):E=t[31];let D;t[32]!==m||t[33]!==E||t[34]!==h?(D=(0,Q.jsxs)(`div`,{className:`relative min-w-0 flex-1 [-webkit-app-region:no-drag]`,children:[m,h,E]}),t[32]=m,t[33]=E,t[34]=h,t[35]=D):D=t[35];let O;t[36]===n?O=t[37]:(O=[n],t[36]=n,t[37]=O);let k;t[38]===u?k=t[39]:(k=e=>{let t=e[0];(t===`stacked`||t===`split`)&&u(t)},t[38]=u,t[39]=k);let A;t[40]===Symbol.for(`react.memo_cache_sentinel`)?(A=(0,Q.jsx)(H,{"aria-label":`Stacked diff view`,value:`stacked`,children:(0,Q.jsx)(se,{className:`size-3`})}),t[40]=A):A=t[40];let j;t[41]===Symbol.for(`react.memo_cache_sentinel`)?(j=(0,Q.jsx)(H,{"aria-label":`Split diff view`,value:`split`,children:(0,Q.jsx)(ie,{className:`size-3`})}),t[41]=j):j=t[41];let M;t[42]!==O||t[43]!==k?(M=(0,Q.jsxs)(G,{className:`shrink-0`,variant:`outline`,size:`xs`,value:O,onValueChange:k,children:[A,j]}),t[42]=O,t[43]=k,t[44]=M):M=t[44];let N=r?`Disable diff line wrapping`:`Enable diff line wrapping`,F=r?`Disable line wrapping`:`Enable line wrapping`,I;t[45]===d?I=t[46]:(I=e=>{d(!!e)},t[45]=d,t[46]=I);let L;t[47]===Symbol.for(`react.memo_cache_sentinel`)?(L=(0,Q.jsx)(le,{className:`size-3`}),t[47]=L):L=t[47];let R;t[48]!==r||t[49]!==N||t[50]!==F||t[51]!==I?(R=(0,Q.jsx)(H,{"aria-label":N,title:F,variant:`outline`,size:`xs`,pressed:r,onPressedChange:I,children:L}),t[48]=r,t[49]=N,t[50]=F,t[51]=I,t[52]=R):R=t[52];let z;t[53]!==M||t[54]!==R?(z=(0,Q.jsxs)(`div`,{className:`flex shrink-0 items-center gap-1 [-webkit-app-region:no-drag]`,children:[M,R]}),t[53]=M,t[54]=R,t[55]=z):z=t[55];let B;return t[56]!==D||t[57]!==z?(B=(0,Q.jsxs)(Q.Fragment,{children:[D,z]}),t[56]=D,t[57]=z,t[58]=B):B=t[58],B}function je(e){let t=(0,$.c)(18),{bodyState:n,diffRenderMode:r,diffWordWrap:i,openDiffFileInEditor:a,patchViewportRef:o,renderableFiles:s,renderablePatch:c,resolvedTheme:l}=e;if(n.kind===`no-thread`){let e;return t[0]===Symbol.for(`react.memo_cache_sentinel`)?(e=(0,Q.jsx)(Ne,{children:`Select a thread to inspect turn diffs.`}),t[0]=e):e=t[0],e}if(n.kind===`not-git-repo`){let e;return t[1]===Symbol.for(`react.memo_cache_sentinel`)?(e=(0,Q.jsx)(Ne,{children:`Turn diffs are unavailable because this project is not a git repository.`}),t[1]=e):e=t[1],e}if(n.kind===`no-completed-turns`){let e;return t[2]===Symbol.for(`react.memo_cache_sentinel`)?(e=(0,Q.jsx)(Ne,{children:`No completed turns yet.`}),t[2]=e):e=t[2],e}let u;t[3]!==n.error||t[4]!==c?(u=n.error&&!c&&(0,Q.jsx)(`div`,{className:`px-3`,children:(0,Q.jsx)(`p`,{className:`mb-2 text-[11px] text-destructive-foreground`,children:n.error})}),t[3]=n.error,t[4]=c,t[5]=u):u=t[5];let d;t[6]!==n||t[7]!==r||t[8]!==i||t[9]!==a||t[10]!==s||t[11]!==c||t[12]!==l?(d=c?c.kind===`files`?(0,Q.jsx)(K,{className:`diff-render-surface h-full min-h-0 overflow-auto px-2 pb-2`,config:{overscrollSize:600,intersectionObserverMargin:1200},children:s.map(e=>{let t=Y(e),n=`${fe(e)}:${l}`;return(0,Q.jsx)(`div`,{"data-diff-file-path":t,className:`diff-render-file mb-2 rounded-md first:mt-2 last:mb-0`,onClickCapture:e=>{(e.nativeEvent.composedPath?.()??[]).some(Me)&&a(t)},children:(0,Q.jsx)(ge,{fileDiff:e,options:{diffStyle:r===`split`?`split`:`unified`,lineDiffType:`none`,overflow:i?`wrap`:`scroll`,theme:v(l),themeType:l,unsafeCSS:De}})},n)})}):(0,Q.jsx)(`div`,{className:`h-full overflow-auto p-2`,children:(0,Q.jsxs)(`div`,{className:`space-y-2`,children:[(0,Q.jsx)(`p`,{className:`text-[11px] text-muted-foreground/75`,children:c.reason}),(0,Q.jsx)(`pre`,{className:P(`max-h-[72vh] rounded-md border border-border/70 bg-background/70 p-3 font-mono text-[11px] leading-relaxed text-muted-foreground/90`,i?`overflow-auto whitespace-pre-wrap wrap-break-word`:`overflow-auto`),children:c.text})]})}):(0,Q.jsx)(Re,{bodyState:n}),t[6]=n,t[7]=r,t[8]=i,t[9]=a,t[10]=s,t[11]=c,t[12]=l,t[13]=d):d=t[13];let f;return t[14]!==o||t[15]!==u||t[16]!==d?(f=(0,Q.jsx)(Q.Fragment,{children:(0,Q.jsxs)(`div`,{ref:o,className:`diff-panel-viewport min-h-0 min-w-0 flex-1 overflow-hidden`,children:[u,d]})}),t[14]=o,t[15]=u,t[16]=d,t[17]=f):f=t[17],f}function Me(e){return e instanceof Element&&e.hasAttribute(`data-title`)}function Ne(e){let t=(0,$.c)(2),{children:n}=e,r;return t[0]===n?r=t[1]:(r=(0,Q.jsx)(`div`,{className:`flex flex-1 items-center justify-center px-5 text-center text-xs text-muted-foreground/70`,children:n}),t[0]=n,t[1]=r),r}function Pe(){let e=(0,$.c)(19),t;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={strict:!1,select:Ie},e[0]=t):t=e[0];let n=O(t),r;e[1]===Symbol.for(`react.memo_cache_sentinel`)?(r={strict:!1,select:Fe},e[1]=r):r=e[1];let i=B(r),a=i.rightPanel===`diff`,o=n?.threadId??null,s,l;e[2]===n?l=e[3]:(l=c(n),e[2]=n,e[3]=l),s=l;let u=M(s),d=He(u),f=u?.worktreePath,p=d?.cwd,m;e[4]!==f||e[5]!==p?(m=R({threadWorktreePath:f,projectCwd:p}),e[4]=f,e[5]=p,e[6]=m):m=e[6];let h=m,_=u?.environmentId??null,v=h??null,y;e[7]!==_||e[8]!==v?(y={environmentId:_,cwd:v},e[7]=_,e[8]=v,e[9]=y):y=e[9];let b=g(y),x;e[10]===b.data?x=e[11]:(x=F(b.data),e[10]=b.data,e[11]=x);let S=x,C;return e[12]!==h||e[13]!==u||e[14]!==o||e[15]!==a||e[16]!==i||e[17]!==S?(C={activeThread:u,activeThreadId:o,activeCwd:h,isGitRepo:S,diffSearch:i,diffOpen:a},e[12]=h,e[13]=u,e[14]=o,e[15]=a,e[16]=i,e[17]=S,e[18]=C):C=e[18],C}function Fe(e){return z(e)}function Ie(e){return y(e)}function Le(e){let{activeThread:t,activeThreadId:n,activeCwd:r,isGitRepo:i,diffSearch:a,diffOpen:o}=Pe(),{turnDiffSummaries:s,inferredCheckpointTurnCountByTurnId:c}=I(t),l=a.diffTurnId??null,u=l===null?null:a.diffFilePath??null,{activeCheckpointRange:f,conversationCacheScope:p,orderedTurnDiffSummaries:m,selectedTurn:h}=(0,X.useMemo)(()=>te({summaries:s,inferredCheckpointTurnCountByTurnId:c,selectedTurnId:l}),[c,l,s]),g=d(xe(we({environmentId:t?.environmentId,threadId:n,range:f,selectedTurnId:h?.turnId,conversationCacheScope:p,enabled:i}))),_=g.isLoading,v=Ce(g.error),y=g.data?.diff,b=typeof y==`string`&&y.trim().length===0,{emptyDiffMessage:x}=(0,X.useMemo)(()=>ae(h),[h]),S=(0,X.useMemo)(()=>ce(y,`diff-panel:${e}`),[e,y]),C=(0,X.useMemo)(()=>Ue(S),[S]);return{activeCwd:r,activeThread:t,bodyState:ue({hasActiveThread:!!t,isGitRepo:i,turnSummaryCount:m.length,checkpointDiffError:v,hasRenderablePatch:!!S,isLoadingCheckpointDiff:_,hasNoNetChanges:b,emptyDiffMessage:x}),diffOpen:o,inferredCheckpointTurnCountByTurnId:c,orderedTurnDiffSummaries:m,renderableFiles:C,renderablePatch:S,selectedFilePath:u,selectedTurn:h,selectedTurnId:l}}function Re(e){let t=(0,$.c)(4),{bodyState:n}=e;if(n.kind===`loading`){let e;return t[0]===Symbol.for(`react.memo_cache_sentinel`)?(e=(0,Q.jsx)(k,{label:`Loading checkpoint diff...`}),t[0]=e):e=t[0],e}let r;t[1]===Symbol.for(`react.memo_cache_sentinel`)?(r=(0,Q.jsx)(L,{className:`size-7 text-muted-foreground/25`}),t[1]=r):r=t[1];let i=n.kind===`empty`?n.message:`No diff is available for this range.`,a;return t[2]===i?a=t[3]:(a=(0,Q.jsxs)(`div`,{className:`flex h-full flex-col items-center justify-center gap-2 px-5 py-2 text-center`,children:[r,(0,Q.jsx)(`p`,{className:`text-xs text-muted-foreground/70`,children:i})]}),t[2]=i,t[3]=a),a}var ze=180;function Be(e){let t=(0,$.c)(14),{direction:n,strip:r}=e,i=n===`left`,a=i?r.canScrollLeft:r.canScrollRight,o=i?U:m,s=i?`left-0`:`right-0`,c=a?`border-border/70 hover:border-border hover:text-foreground`:`cursor-not-allowed border-border/40 text-muted-foreground/40`,l;t[0]!==s||t[1]!==c?(l=P(`absolute top-1/2 z-20 inline-flex size-6 -translate-y-1/2 items-center justify-center rounded-md border bg-background/90 text-muted-foreground transition-colors`,s,c),t[0]=s,t[1]=c,t[2]=l):l=t[2];let u;t[3]!==i||t[4]!==r?(u=()=>r.scrollBy(i?-180:ze),t[3]=i,t[4]=r,t[5]=u):u=t[5];let d=!a,f=`Scroll turn list ${n}`,p;t[6]===o?p=t[7]:(p=(0,Q.jsx)(o,{className:`size-3.5`}),t[6]=o,t[7]=p);let h;return t[8]!==l||t[9]!==u||t[10]!==d||t[11]!==f||t[12]!==p?(h=(0,Q.jsx)(`button`,{type:`button`,className:l,onClick:u,disabled:d,"aria-label":f,children:p}),t[8]=l,t[9]=u,t[10]=d,t[11]=f,t[12]=p,t[13]=h):h=t[13],h}function Ve(e){let t=(0,$.c)(23),{summary:n,selected:r,turnCount:i,timestampFormat:a,onSelect:o}=e,s;t[0]!==o||t[1]!==n.turnId?(s=()=>o(n.turnId),t[0]=o,t[1]=n.turnId,t[2]=s):s=t[2];let c=n.turnId,l=r?`border-border bg-accent text-accent-foreground`:`border-border/70 bg-background/70 text-muted-foreground/80 hover:border-border hover:text-foreground/80`,u;t[3]===l?u=t[4]:(u=P(`rounded-md border px-2 py-1 text-left transition-colors`,l),t[3]=l,t[4]=u);let d=i??`?`,f;t[5]===d?f=t[6]:(f=(0,Q.jsxs)(`span`,{className:`text-[10px] leading-tight font-medium`,children:[`Turn `,d]}),t[5]=d,t[6]=f);let p;t[7]!==n.completedAt||t[8]!==a?(p=b(n.completedAt,a),t[7]=n.completedAt,t[8]=a,t[9]=p):p=t[9];let m;t[10]===p?m=t[11]:(m=(0,Q.jsx)(`span`,{className:`text-[9px] leading-tight opacity-70`,children:p}),t[10]=p,t[11]=m);let h;t[12]!==f||t[13]!==m?(h=(0,Q.jsxs)(`div`,{className:`flex items-center gap-1`,children:[f,m]}),t[12]=f,t[13]=m,t[14]=h):h=t[14];let g;t[15]!==u||t[16]!==h?(g=(0,Q.jsx)(`div`,{className:u,children:h}),t[15]=u,t[16]=h,t[17]=g):g=t[17];let _;return t[18]!==r||t[19]!==n.turnId||t[20]!==s||t[21]!==g?(_=(0,Q.jsx)(`button`,{type:`button`,className:`shrink-0 rounded-md`,onClick:s,title:c,"data-turn-chip-selected":r,children:g}),t[18]=r,t[19]=n.turnId,t[20]=s,t[21]=g,t[22]=_):_=t[22],_}function He(e){let t=(0,$.c)(3),n=e?.environmentId,r=e?.projectId,i;return t[0]!==n||t[1]!==r?(i=e=>n&&r?A(e,{environmentId:n,projectId:r}):void 0,t[0]=n,t[1]=r,t[2]=i):i=t[2],M(i)}function Ue(e){return!e||e.kind!==`files`?[]:e.files.toSorted((e,t)=>Y(e).localeCompare(Y(t),void 0,{numeric:!0,sensitivity:`base`}))}export{Oe as default};
64
- //# sourceMappingURL=DiffPanel-CsMWXFsK.js.map
64
+ //# sourceMappingURL=DiffPanel-njtnlFro.js.map