@p4code/cli 0.2.5 → 0.2.7

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
@@ -237,7 +237,7 @@ const make$87 = () => {
237
237
  const layer$79 = Layer.sync(NetService, make$87);
238
238
  //#endregion
239
239
  //#region package.json
240
- var version = "0.2.5";
240
+ var version = "0.2.7";
241
241
  //#endregion
242
242
  //#region src/config.ts
243
243
  /**
@@ -1914,6 +1914,12 @@ const OrchestrationLatestTurn = Schema$1.Struct({
1914
1914
  assistantMessageId: Schema$1.NullOr(MessageId),
1915
1915
  sourceProposedPlan: Schema$1.optional(SourceProposedPlanReference)
1916
1916
  });
1917
+ const OrchestrationTurnSummary = Schema$1.Struct({
1918
+ turnId: TurnId,
1919
+ state: OrchestrationLatestTurnState,
1920
+ startedAt: Schema$1.NullOr(IsoDateTime),
1921
+ completedAt: Schema$1.NullOr(IsoDateTime)
1922
+ });
1917
1923
  const OrchestrationThread = Schema$1.Struct({
1918
1924
  id: ThreadId,
1919
1925
  projectId: ProjectId,
@@ -1926,6 +1932,7 @@ const OrchestrationThread = Schema$1.Struct({
1926
1932
  branch: Schema$1.NullOr(TrimmedNonEmptyString),
1927
1933
  worktreePath: Schema$1.NullOr(TrimmedNonEmptyString),
1928
1934
  latestTurn: Schema$1.NullOr(OrchestrationLatestTurn),
1935
+ turns: Schema$1.optional(Schema$1.Array(OrchestrationTurnSummary)),
1929
1936
  createdAt: IsoDateTime,
1930
1937
  updatedAt: IsoDateTime,
1931
1938
  archivedAt: Schema$1.NullOr(IsoDateTime).pipe(Schema$1.withDecodingDefault(Effect.succeed(null))),
@@ -8925,10 +8932,13 @@ var ProjectListEntriesError = class extends Schema$1.TaggedErrorClass()("Project
8925
8932
  });
8926
8933
  }
8927
8934
  };
8928
- const ProjectReadFileInput = Schema$1.Struct({
8935
+ const ProjectReadFileInput = Schema$1.Union([Schema$1.Struct({
8929
8936
  cwd: TrimmedNonEmptyString,
8930
8937
  relativePath: TrimmedNonEmptyString.check(Schema$1.isMaxLength(PROJECT_READ_FILE_PATH_MAX_LENGTH))
8931
- });
8938
+ }), Schema$1.Struct({
8939
+ cwd: TrimmedNonEmptyString,
8940
+ absolutePath: TrimmedNonEmptyString.check(Schema$1.isMaxLength(PROJECT_READ_FILE_PATH_MAX_LENGTH))
8941
+ })]);
8932
8942
  const ProjectReadFileResult = Schema$1.Struct({
8933
8943
  relativePath: TrimmedNonEmptyString,
8934
8944
  contents: Schema$1.String,
@@ -8944,6 +8954,7 @@ const ProjectReadFileResult = Schema$1.Struct({
8944
8954
  const ProjectFileFailure = Schema$1.Literals([
8945
8955
  "workspace_path_outside_root",
8946
8956
  "resolved_path_outside_root",
8957
+ "path_not_found",
8947
8958
  "path_not_file",
8948
8959
  "operation_failed"
8949
8960
  ]);
@@ -8960,6 +8971,7 @@ const ProjectFileOperation = Schema$1.Literals([
8960
8971
  var ProjectReadFileError = class extends Schema$1.TaggedErrorClass()("ProjectReadFileError", {
8961
8972
  cwd: Schema$1.optional(TrimmedNonEmptyString),
8962
8973
  relativePath: Schema$1.optional(TrimmedNonEmptyString),
8974
+ absolutePath: Schema$1.optional(TrimmedNonEmptyString),
8963
8975
  failure: Schema$1.optional(ProjectFileFailure),
8964
8976
  resolvedPath: Schema$1.optional(TrimmedNonEmptyString),
8965
8977
  resolvedWorkspaceRoot: Schema$1.optional(TrimmedNonEmptyString),
@@ -8969,9 +8981,11 @@ var ProjectReadFileError = class extends Schema$1.TaggedErrorClass()("ProjectRea
8969
8981
  cause: Schema$1.optional(Schema$1.Defect())
8970
8982
  }) {
8971
8983
  constructor(props) {
8984
+ const requestedPath = props.absolutePath ?? props.relativePath ?? "unknown";
8985
+ const message = props.failure === "workspace_path_outside_root" || props.failure === "resolved_path_outside_root" ? `File '${requestedPath}' is outside workspace root '${props.cwd}'.` : props.failure === "path_not_found" ? `File '${requestedPath}' was not found.` : `Failed to read workspace file '${requestedPath}' in '${props.cwd}'.`;
8972
8986
  super({
8973
8987
  ...props,
8974
- message: decodedProjectErrorMessage(props) ?? `Failed to read workspace file '${props.relativePath}' in '${props.cwd}'.`
8988
+ message: decodedProjectErrorMessage(props) ?? message
8975
8989
  });
8976
8990
  }
8977
8991
  };
@@ -26869,6 +26883,13 @@ const ProjectionLatestTurnDbRowSchema = Schema$1.Struct({
26869
26883
  sourceProposedPlanThreadId: Schema$1.NullOr(ThreadId),
26870
26884
  sourceProposedPlanId: Schema$1.NullOr(OrchestrationProposedPlanId)
26871
26885
  });
26886
+ const ProjectionTurnSummaryDbRowSchema = Schema$1.Struct({
26887
+ threadId: ProjectionThread.fields.threadId,
26888
+ turnId: TurnId,
26889
+ state: Schema$1.String,
26890
+ startedAt: Schema$1.NullOr(IsoDateTime),
26891
+ completedAt: Schema$1.NullOr(IsoDateTime)
26892
+ });
26872
26893
  const ProjectionStateDbRowSchema = ProjectionState;
26873
26894
  const ProjectionCountsRowSchema = Schema$1.Struct({
26874
26895
  projectCount: Schema$1.Number,
@@ -26951,10 +26972,21 @@ function computeSnapshotSequence(stateRows) {
26951
26972
  }
26952
26973
  return Number.isFinite(minSequence) ? minSequence : 0;
26953
26974
  }
26975
+ function mapTurnState(state) {
26976
+ return state === "error" ? "error" : state === "interrupted" ? "interrupted" : state === "completed" ? "completed" : "running";
26977
+ }
26978
+ function mapTurnSummary(row) {
26979
+ return {
26980
+ turnId: row.turnId,
26981
+ state: mapTurnState(row.state),
26982
+ startedAt: row.startedAt,
26983
+ completedAt: row.completedAt
26984
+ };
26985
+ }
26954
26986
  function mapLatestTurn(row) {
26955
26987
  return {
26956
26988
  turnId: row.turnId,
26957
- state: row.state === "error" ? "error" : row.state === "interrupted" ? "interrupted" : row.state === "completed" ? "completed" : "running",
26989
+ state: mapTurnState(row.state),
26958
26990
  requestedAt: row.requestedAt,
26959
26991
  startedAt: row.startedAt,
26960
26992
  completedAt: row.completedAt,
@@ -27274,6 +27306,21 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
27274
27306
  FROM projection_turns
27275
27307
  WHERE checkpoint_turn_count IS NOT NULL
27276
27308
  ORDER BY thread_id ASC, checkpoint_turn_count ASC
27309
+ `
27310
+ });
27311
+ const listTurnSummaryRows = SqlSchema.findAll({
27312
+ Request: Schema$1.Void,
27313
+ Result: ProjectionTurnSummaryDbRowSchema,
27314
+ execute: () => sql`
27315
+ SELECT
27316
+ thread_id AS "threadId",
27317
+ turn_id AS "turnId",
27318
+ state,
27319
+ started_at AS "startedAt",
27320
+ completed_at AS "completedAt"
27321
+ FROM projection_turns
27322
+ WHERE turn_id IS NOT NULL
27323
+ ORDER BY thread_id ASC, requested_at ASC, turn_id ASC
27277
27324
  `
27278
27325
  });
27279
27326
  const listLatestTurnRows = SqlSchema.findAll({
@@ -27660,6 +27707,22 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
27660
27707
  WHERE thread_id = ${threadId}
27661
27708
  AND checkpoint_turn_count IS NOT NULL
27662
27709
  ORDER BY checkpoint_turn_count ASC
27710
+ `
27711
+ });
27712
+ const listTurnSummaryRowsByThread = SqlSchema.findAll({
27713
+ Request: ThreadIdLookupInput,
27714
+ Result: ProjectionTurnSummaryDbRowSchema,
27715
+ execute: ({ threadId }) => sql`
27716
+ SELECT
27717
+ thread_id AS "threadId",
27718
+ turn_id AS "turnId",
27719
+ state,
27720
+ started_at AS "startedAt",
27721
+ completed_at AS "completedAt"
27722
+ FROM projection_turns
27723
+ WHERE thread_id = ${threadId}
27724
+ AND turn_id IS NOT NULL
27725
+ ORDER BY requested_at ASC, turn_id ASC
27663
27726
  `
27664
27727
  });
27665
27728
  const getFullThreadDiffContextRow = SqlSchema.findOneOption({
@@ -27700,13 +27763,15 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
27700
27763
  listThreadActivityRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getSnapshot:listThreadActivities:query", "ProjectionSnapshotQuery.getSnapshot:listThreadActivities:decodeRows"))),
27701
27764
  listThreadSessionRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getSnapshot:listThreadSessions:query", "ProjectionSnapshotQuery.getSnapshot:listThreadSessions:decodeRows"))),
27702
27765
  listCheckpointRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getSnapshot:listCheckpoints:query", "ProjectionSnapshotQuery.getSnapshot:listCheckpoints:decodeRows"))),
27766
+ listTurnSummaryRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getSnapshot:listTurnSummaries:query", "ProjectionSnapshotQuery.getSnapshot:listTurnSummaries:decodeRows"))),
27703
27767
  listLatestTurnRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getSnapshot:listLatestTurns:query", "ProjectionSnapshotQuery.getSnapshot:listLatestTurns:decodeRows"))),
27704
27768
  listProjectionStateRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getSnapshot:listProjectionState:query", "ProjectionSnapshotQuery.getSnapshot:listProjectionState:decodeRows")))
27705
- ])).pipe(Effect.flatMap(([projectRows, threadRows, messageRows, proposedPlanRows, activityRows, sessionRows, checkpointRows, latestTurnRows, stateRows]) => Effect.gen(function* () {
27769
+ ])).pipe(Effect.flatMap(([projectRows, threadRows, messageRows, proposedPlanRows, activityRows, sessionRows, checkpointRows, turnRows, latestTurnRows, stateRows]) => Effect.gen(function* () {
27706
27770
  const messagesByThread = /* @__PURE__ */ new Map();
27707
27771
  const proposedPlansByThread = /* @__PURE__ */ new Map();
27708
27772
  const activitiesByThread = /* @__PURE__ */ new Map();
27709
27773
  const checkpointsByThread = /* @__PURE__ */ new Map();
27774
+ const turnsByThread = /* @__PURE__ */ new Map();
27710
27775
  const sessionsByThread = /* @__PURE__ */ new Map();
27711
27776
  const latestTurnByThread = /* @__PURE__ */ new Map();
27712
27777
  let updatedAt = null;
@@ -27771,23 +27836,17 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
27771
27836
  });
27772
27837
  checkpointsByThread.set(row.threadId, threadCheckpoints);
27773
27838
  }
27839
+ for (const row of turnRows) {
27840
+ const threadTurns = turnsByThread.get(row.threadId) ?? [];
27841
+ threadTurns.push(mapTurnSummary(row));
27842
+ turnsByThread.set(row.threadId, threadTurns);
27843
+ }
27774
27844
  for (const row of latestTurnRows) {
27775
27845
  updatedAt = maxIso(updatedAt, row.requestedAt);
27776
27846
  if (row.startedAt !== null) updatedAt = maxIso(updatedAt, row.startedAt);
27777
27847
  if (row.completedAt !== null) updatedAt = maxIso(updatedAt, row.completedAt);
27778
27848
  if (latestTurnByThread.has(row.threadId)) continue;
27779
- latestTurnByThread.set(row.threadId, {
27780
- turnId: row.turnId,
27781
- state: row.state === "error" ? "error" : row.state === "interrupted" ? "interrupted" : row.state === "completed" ? "completed" : "running",
27782
- requestedAt: row.requestedAt,
27783
- startedAt: row.startedAt,
27784
- completedAt: row.completedAt,
27785
- assistantMessageId: row.assistantMessageId,
27786
- ...row.sourceProposedPlanThreadId !== null && row.sourceProposedPlanId !== null ? { sourceProposedPlan: {
27787
- threadId: row.sourceProposedPlanThreadId,
27788
- planId: row.sourceProposedPlanId
27789
- } } : {}
27790
- });
27849
+ latestTurnByThread.set(row.threadId, mapLatestTurn(row));
27791
27850
  }
27792
27851
  for (const row of sessionRows) {
27793
27852
  updatedAt = maxIso(updatedAt, row.updatedAt);
@@ -27826,6 +27885,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
27826
27885
  branch: row.branch,
27827
27886
  worktreePath: row.worktreePath,
27828
27887
  latestTurn: latestTurnByThread.get(row.threadId) ?? null,
27888
+ turns: turnsByThread.get(row.threadId) ?? [],
27829
27889
  createdAt: row.createdAt,
27830
27890
  updatedAt: row.updatedAt,
27831
27891
  archivedAt: row.archivedAt,
@@ -28182,12 +28242,13 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
28182
28242
  });
28183
28243
  });
28184
28244
  const getThreadDetailById = (threadId) => Effect.gen(function* () {
28185
- const [threadRow, messageRows, proposedPlanRows, activityRows, checkpointRows, latestTurnRow, sessionRow] = yield* Effect.all([
28245
+ const [threadRow, messageRows, proposedPlanRows, activityRows, checkpointRows, turnRows, latestTurnRow, sessionRow] = yield* Effect.all([
28186
28246
  getActiveThreadRowById({ threadId }).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getThreadDetailById:getThread:query", "ProjectionSnapshotQuery.getThreadDetailById:getThread:decodeRow"))),
28187
28247
  listThreadMessageRowsByThread({ threadId }).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getThreadDetailById:listMessages:query", "ProjectionSnapshotQuery.getThreadDetailById:listMessages:decodeRows"))),
28188
28248
  listThreadProposedPlanRowsByThread({ threadId }).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getThreadDetailById:listPlans:query", "ProjectionSnapshotQuery.getThreadDetailById:listPlans:decodeRows"))),
28189
28249
  listThreadActivityRowsByThread({ threadId }).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getThreadDetailById:listActivities:query", "ProjectionSnapshotQuery.getThreadDetailById:listActivities:decodeRows"))),
28190
28250
  listCheckpointRowsByThread({ threadId }).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getThreadDetailById:listCheckpoints:query", "ProjectionSnapshotQuery.getThreadDetailById:listCheckpoints:decodeRows"))),
28251
+ listTurnSummaryRowsByThread({ threadId }).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getThreadDetailById:listTurnSummaries:query", "ProjectionSnapshotQuery.getThreadDetailById:listTurnSummaries:decodeRows"))),
28191
28252
  getLatestTurnRowByThread({ threadId }).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getThreadDetailById:getLatestTurn:query", "ProjectionSnapshotQuery.getThreadDetailById:getLatestTurn:decodeRow"))),
28192
28253
  getThreadSessionRowByThread({ threadId }).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getThreadDetailById:getSession:query", "ProjectionSnapshotQuery.getThreadDetailById:getSession:decodeRow")))
28193
28254
  ]);
@@ -28204,6 +28265,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
28204
28265
  branch: threadRow.value.branch,
28205
28266
  worktreePath: threadRow.value.worktreePath,
28206
28267
  latestTurn: Option.isSome(latestTurnRow) ? mapLatestTurn(latestTurnRow.value) : null,
28268
+ turns: turnRows.map(mapTurnSummary),
28207
28269
  createdAt: threadRow.value.createdAt,
28208
28270
  updatedAt: threadRow.value.updatedAt,
28209
28271
  archivedAt: threadRow.value.archivedAt,
@@ -40229,24 +40291,55 @@ const toTaskStoreError = (operation) => (cause) => Effect.logWarning("task store
40229
40291
  * still reading its stale snapshot. The row stays the single source of truth
40230
40292
  * and the agent reads it live over MCP.
40231
40293
  *
40232
- * Two instructions carry their weight. The agent is told its thread is already
40233
- * linked to the task, because otherwise its first useful move is to guess which
40234
- * board row it is on. And it is told to leave `status` alone: the server moved
40235
- * the task to `in_progress` when it started the thread, and where the work goes
40236
- * after that is the user's call — the same rule the scoping prompt follows, and
40237
- * the reason the board's columns still mean something.
40294
+ * The prompt owns the whole task lifecycle rather than merely pointing at the
40295
+ * row. It tells the agent how to orient safely, verify the acceptance criteria,
40296
+ * obtain a skeptical review, deliver repository changes through a pull request,
40297
+ * and leave the board in the state that matches the actual outcome.
40238
40298
  */
40239
40299
  const buildAutoPrompt = (task) => {
40240
40300
  const reference = task.readableId ?? task.taskId;
40241
- return `Picking up board task \`${reference}\`: ${task.title}
40301
+ return `Take ownership of board task \`${reference}\`: ${task.title}
40302
+
40303
+ Start with \`task_current\` (or \`task_get\` with \`${reference}\`). Read the current body, acceptance criteria, labels, priority, relationships, and existing evidence. This thread is already linked and the task is \`in_progress\`. The live row is the source of truth; re-read it before the final update.
40304
+
40305
+ Orient before acting. Read repository instructions and any skills or workflows the task names or clearly requires. Inspect the relevant code, documentation, state, recent history, and current checkout. Determine what is already complete and identify the exact remaining acceptance work.
40306
+
40307
+ Preserve unrelated changes. If the checkout is dirty, stale, on the wrong base, or otherwise unsafe for this task, create an isolated worktree from the appropriate current base. Never discard or overwrite work you do not own.
40308
+
40309
+ Execute the task end to end. Stay within its intent: no speculative features, unrelated refactors, or broad verification. Reuse valid existing evidence instead of repeating completed work without reason. Resolve routine in-scope problems autonomously.
40242
40310
 
40243
- Read the task first via \`task_current\` (or \`task_get\` with \`${reference}\`). Body, labels, project and priority live on the row, not in this message; the row may have changed since this thread started - the current row is the source of truth. Re-read it the same way whenever you need the fields again.
40311
+ If requirements are materially ambiguous, investigate available context first. Ask only when different interpretations would materially change the result. If a real environment, permission, or dependency blocker remains after safe task-relevant recovery, stop with the exact blocker and required next action rather than guessing.
40244
40312
 
40245
- This thread is already linked to the task, status In progress. Do the work.
40313
+ Verify the smallest sufficient proof against every acceptance criterion. Follow required skills exactly. Do not claim results you did not observe.
40246
40314
 
40247
- Record findings via \`task_update\` as you go - decisions made, constraints hit, things the task turned out to be wrong about. That is what makes the row worth reading afterwards. Leave \`status\` alone: moving work across the board is the user's call.
40315
+ Keep the task row useful through \`task_update\`, not as an activity diary. Record durable decisions, corrected assumptions, concise verification evidence, and blockers. Keep status current:
40248
40316
 
40249
- After reading the task, read the code it concerns. If it is specified too poorly to act on, say so and stop rather than guessing.`;
40317
+ - \`done\` only when every acceptance criterion is satisfied and no required work remains.
40318
+ - \`in_review\` when repository work is ready in a pull request or execution is complete but human review or a product decision remains.
40319
+ - \`in_progress\` when work or a blocker remains, with the exact outstanding item recorded.
40320
+ - Update related tasks only when the task requires it.
40321
+
40322
+ For repository-changing work, unless the live task or current user explicitly forbids pull-request delivery, this prompt authorizes you to create a task branch or isolated worktree, commit only your changes, push that branch, and open a pull request. Follow repository branch, commit, rebase, pull-request template, and evidence rules. Never commit directly to \`main\` or \`master\` unless the live task explicitly requires the repository's established direct-delivery workflow. Never force-push unless the current user explicitly authorizes it.
40323
+
40324
+ Before delivery or board completion, ask one bounded read-only sub-agent to review the task requirements, result, verification evidence, and complete diff when one exists. Its job is to find correctness defects, regressions, missed acceptance criteria, unsupported claims, and unnecessary scope. It must not edit files or spawn another agent. If no sub-agent mechanism is available, perform the same skeptical review yourself and record that limitation.
40325
+
40326
+ Validate every finding yourself. Fix real issues, reject false positives with a concrete reason, and rerun affected verification. If review fixes or conflict resolution materially change the diff, run one final bounded review pass.
40327
+
40328
+ Before opening the pull request:
40329
+
40330
+ - Re-read the live task and confirm every acceptance criterion.
40331
+ - Sync with the appropriate current base using the repository's required workflow.
40332
+ - Inspect the final diff and ensure it contains only task-owned changes.
40333
+ - Stage explicit paths and commit using repository conventions.
40334
+ - Push only the task branch.
40335
+ - Reuse an existing task pull request when appropriate; never create a duplicate.
40336
+ - Include the problem, solution, verification, required visual evidence, and task reference in the pull request.
40337
+
40338
+ Open a pull request only when the task produced repository changes. Verification, research, product-decision, and operational tasks with no diff should finish through evidence on the board instead. Do not delete files or mutate external systems unless the live task or current user explicitly authorizes that action.
40339
+
40340
+ After opening the pull request, append its URL and concise verification evidence to the task and move it to \`in_review\`. Leave it \`in_progress\` if implementation, verification, review findings, push, or pull-request creation remains blocked. Mark a no-pull-request task \`done\` only when all acceptance criteria are satisfied.
40341
+
40342
+ Finish by reporting the outcome, verification performed, sub-agent review outcome, pull-request URL when applicable, board status, and any remaining blocker.`;
40250
40343
  };
40251
40344
  /**
40252
40345
  * Render a task into the prompt that seeds its thread.
@@ -45544,15 +45637,24 @@ const make$40 = Effect.gen(function* () {
45544
45637
  const workspacePaths = yield* WorkspacePaths;
45545
45638
  const workspaceEntries = yield* WorkspaceEntries;
45546
45639
  const readFile = Effect.fn("WorkspaceFileSystem.readFile")(function* (input) {
45547
- const target = yield* workspacePaths.resolveRelativePathWithinRoot({
45640
+ const requestedPath = "absolutePath" in input ? input.absolutePath : input.relativePath;
45641
+ const isAbsoluteRead = "absolutePath" in input;
45642
+ const target = isAbsoluteRead ? {
45643
+ absolutePath: input.absolutePath,
45644
+ relativePath: input.absolutePath
45645
+ } : yield* workspacePaths.resolveRelativePathWithinRoot({
45548
45646
  workspaceRoot: input.cwd,
45549
45647
  relativePath: input.relativePath
45550
45648
  });
45551
- const realWorkspaceRoot = yield* Effect.tryPromise({
45649
+ if (isAbsoluteRead && !path.isAbsolute(target.absolutePath)) return yield* new WorkspacePathOutsideRootError({
45650
+ workspaceRoot: input.cwd,
45651
+ relativePath: requestedPath
45652
+ });
45653
+ const realWorkspaceRoot = isAbsoluteRead ? void 0 : yield* Effect.tryPromise({
45552
45654
  try: () => NodeFSP.realpath(input.cwd),
45553
45655
  catch: (cause) => new WorkspaceFileSystemOperationError({
45554
45656
  workspaceRoot: input.cwd,
45555
- relativePath: input.relativePath,
45657
+ relativePath: requestedPath,
45556
45658
  resolvedPath: target.absolutePath,
45557
45659
  operationPath: input.cwd,
45558
45660
  operation: "realpath-workspace-root",
@@ -45563,17 +45665,17 @@ const make$40 = Effect.gen(function* () {
45563
45665
  try: () => NodeFSP.realpath(target.absolutePath),
45564
45666
  catch: (cause) => new WorkspaceFileSystemOperationError({
45565
45667
  workspaceRoot: input.cwd,
45566
- relativePath: input.relativePath,
45668
+ relativePath: requestedPath,
45567
45669
  resolvedPath: target.absolutePath,
45568
45670
  operationPath: target.absolutePath,
45569
45671
  operation: "realpath-target",
45570
45672
  cause
45571
45673
  })
45572
45674
  });
45573
- const relativeRealPath = path.relative(realWorkspaceRoot, realTargetPath);
45574
- if (relativeRealPath.startsWith(`..${path.sep}`) || relativeRealPath === ".." || path.isAbsolute(relativeRealPath)) return yield* new WorkspaceFilePathEscapeError({
45675
+ const relativeRealPath = realWorkspaceRoot ? path.relative(realWorkspaceRoot, realTargetPath) : void 0;
45676
+ if (realWorkspaceRoot && relativeRealPath !== void 0 && (relativeRealPath.startsWith(`..${path.sep}`) || relativeRealPath === ".." || path.isAbsolute(relativeRealPath))) return yield* new WorkspaceFilePathEscapeError({
45575
45677
  workspaceRoot: input.cwd,
45576
- relativePath: input.relativePath,
45678
+ relativePath: requestedPath,
45577
45679
  resolvedWorkspaceRoot: realWorkspaceRoot,
45578
45680
  resolvedPath: realTargetPath
45579
45681
  });
@@ -45581,7 +45683,7 @@ const make$40 = Effect.gen(function* () {
45581
45683
  try: () => NodeFSP.open(realTargetPath, "r"),
45582
45684
  catch: (cause) => new WorkspaceFileSystemOperationError({
45583
45685
  workspaceRoot: input.cwd,
45584
- relativePath: input.relativePath,
45686
+ relativePath: requestedPath,
45585
45687
  resolvedPath: realTargetPath,
45586
45688
  operationPath: realTargetPath,
45587
45689
  operation: "open",
@@ -45592,7 +45694,7 @@ const make$40 = Effect.gen(function* () {
45592
45694
  try: () => handle.stat(),
45593
45695
  catch: (cause) => new WorkspaceFileSystemOperationError({
45594
45696
  workspaceRoot: input.cwd,
45595
- relativePath: input.relativePath,
45697
+ relativePath: requestedPath,
45596
45698
  resolvedPath: realTargetPath,
45597
45699
  operationPath: realTargetPath,
45598
45700
  operation: "stat",
@@ -45601,7 +45703,7 @@ const make$40 = Effect.gen(function* () {
45601
45703
  });
45602
45704
  if (!stat.isFile()) return yield* new WorkspacePathNotFileError({
45603
45705
  workspaceRoot: input.cwd,
45604
- relativePath: input.relativePath,
45706
+ relativePath: requestedPath,
45605
45707
  resolvedPath: realTargetPath
45606
45708
  });
45607
45709
  const bytesToRead = Math.min(stat.size, PROJECT_READ_FILE_MAX_BYTES);
@@ -45610,7 +45712,7 @@ const make$40 = Effect.gen(function* () {
45610
45712
  try: () => handle.read(buffer, 0, bytesToRead, 0),
45611
45713
  catch: (cause) => new WorkspaceFileSystemOperationError({
45612
45714
  workspaceRoot: input.cwd,
45613
- relativePath: input.relativePath,
45715
+ relativePath: requestedPath,
45614
45716
  resolvedPath: realTargetPath,
45615
45717
  operationPath: realTargetPath,
45616
45718
  operation: "read",
@@ -45636,7 +45738,7 @@ const make$40 = Effect.gen(function* () {
45636
45738
  try: () => handle.close(),
45637
45739
  catch: (cause) => new WorkspaceFileSystemOperationError({
45638
45740
  workspaceRoot: input.cwd,
45639
- relativePath: input.relativePath,
45741
+ relativePath: requestedPath,
45640
45742
  resolvedPath: realTargetPath,
45641
45743
  operationPath: realTargetPath,
45642
45744
  operation: "close",
@@ -59017,12 +59119,17 @@ function filesystemBrowseFailureContext(error) {
59017
59119
  function projectFileFailureContext(error) {
59018
59120
  switch (error._tag) {
59019
59121
  case "WorkspacePathOutsideRootError": return { failure: "workspace_path_outside_root" };
59020
- case "WorkspaceFileSystemOperationError": return {
59021
- failure: "operation_failed",
59022
- resolvedPath: error.resolvedPath,
59023
- operation: error.operation,
59024
- operationPath: error.operationPath
59025
- };
59122
+ case "WorkspaceFileSystemOperationError":
59123
+ if (error.operation === "realpath-target" && error.cause instanceof Error && "code" in error.cause && error.cause.code === "ENOENT") return {
59124
+ failure: "path_not_found",
59125
+ resolvedPath: error.resolvedPath
59126
+ };
59127
+ return {
59128
+ failure: "operation_failed",
59129
+ resolvedPath: error.resolvedPath,
59130
+ operation: error.operation,
59131
+ operationPath: error.operationPath
59132
+ };
59026
59133
  case "WorkspaceFilePathEscapeError": return {
59027
59134
  failure: "resolved_path_outside_root",
59028
59135
  resolvedPath: error.resolvedPath,
@@ -59235,6 +59342,7 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
59235
59342
  const serverSelfUpdate = yield* ServerSelfUpdate;
59236
59343
  const textGeneration = yield* TextGeneration;
59237
59344
  const config = yield* ServerConfig$1;
59345
+ const allowAbsoluteFileReads = config.mode === "desktop" && !isRemoteReachableHost(config.host);
59238
59346
  const lifecycleEvents = yield* ServerLifecycleEvents;
59239
59347
  const serverSettings = yield* ServerSettingsService;
59240
59348
  const hubLink = yield* HubLink;
@@ -59943,11 +60051,17 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
59943
60051
  ...projectEntriesFailureContext(cause),
59944
60052
  cause
59945
60053
  }))), { "rpc.aggregate": "workspace" }),
59946
- [WS_METHODS.projectsReadFile]: (input) => observeRpcEffect$1(WS_METHODS.projectsReadFile, workspaceFileSystem.readFile(input).pipe(Effect.mapError((cause) => new ProjectReadFileError({
59947
- ...input,
59948
- ...projectFileFailureContext(cause),
59949
- cause
59950
- }))), { "rpc.aggregate": "workspace" }),
60054
+ [WS_METHODS.projectsReadFile]: (input) => observeRpcEffect$1(WS_METHODS.projectsReadFile, Effect.gen(function* () {
60055
+ if ("absolutePath" in input && !allowAbsoluteFileReads) return yield* new ProjectReadFileError({
60056
+ ...input,
60057
+ failure: "workspace_path_outside_root"
60058
+ });
60059
+ return yield* workspaceFileSystem.readFile(input).pipe(Effect.mapError((cause) => new ProjectReadFileError({
60060
+ ...input,
60061
+ ...projectFileFailureContext(cause),
60062
+ cause
60063
+ })));
60064
+ }), { "rpc.aggregate": "workspace" }),
59951
60065
  [WS_METHODS.projectsWriteFile]: (input) => observeRpcEffect$1(WS_METHODS.projectsWriteFile, workspaceFileSystem.writeFile(input).pipe(Effect.mapError((cause) => new ProjectWriteFileError({
59952
60066
  cwd: input.cwd,
59953
60067
  relativePath: input.relativePath,
@@ -63736,6 +63850,14 @@ function isClaudeInterruptedCause(cause) {
63736
63850
  function resultErrorsText(result) {
63737
63851
  return "errors" in result && Array.isArray(result.errors) ? result.errors.join(" ").toLowerCase() : "";
63738
63852
  }
63853
+ const EDE_DIAGNOSTIC_PREFIX = "[ede_diagnostic]";
63854
+ const CLAUDE_PENDING_TOOL_FAILURE_MESSAGE = "Claude stopped while a tool call was still pending.";
63855
+ function resultErrorMessage(result) {
63856
+ if (result.subtype === "success") return;
63857
+ const userFacingError = result.errors.find((error) => !error.trimStart().startsWith(EDE_DIAGNOSTIC_PREFIX));
63858
+ if (userFacingError !== void 0) return userFacingError;
63859
+ return result.stop_reason === "tool_use" && result.errors.length > 0 ? CLAUDE_PENDING_TOOL_FAILURE_MESSAGE : void 0;
63860
+ }
63739
63861
  function isInterruptedResult(result) {
63740
63862
  const errors = resultErrorsText(result);
63741
63863
  if (errors.includes("interrupt")) return true;
@@ -65497,7 +65619,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
65497
65619
  const interruptRequested = context.interruptRequested;
65498
65620
  context.interruptRequested = false;
65499
65621
  const status = turnStatusFromResult(message, interruptRequested);
65500
- const errorMessage = message.subtype === "success" ? void 0 : message.errors[0];
65622
+ const errorMessage = resultErrorMessage(message);
65501
65623
  if (status === "failed") yield* emitRuntimeError(context, errorMessage ?? "Claude turn failed.");
65502
65624
  yield* completeTurn(context, status, errorMessage, message);
65503
65625
  yield* drainPendingTurns(context);
@@ -102358,7 +102480,7 @@ const make$2 = Effect.gen(function* () {
102358
102480
  const modelForTurn = sessionModelSwitch === "unsupported" && input.modelSelection === void 0 ? activeSession?.model !== void 0 ? {
102359
102481
  ...requestedModelSelection,
102360
102482
  model: activeSession.model
102361
- } : requestedModelSelection : input.modelSelection;
102483
+ } : requestedModelSelection : requestedModelSelection;
102362
102484
  const compressMode = thread.compressMode;
102363
102485
  const hasSessionLevelRuleset = activeSession?.provider === "claudeAgent" || activeSession?.provider === "codex";
102364
102486
  const rebuildsRulesetEachTurn = activeSession?.provider === "codex";
@@ -0,0 +1,98 @@
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{$i as i,Ac as a,Dc as o,Fm as s,H as c,Il as l,Oc as u,Q as d,Qc as f,Qt as p,Xi as ee,Z as m,b as h,ct as g,da as _,et as v,fa as y,fr as b,h as x,ia as S,il as C,kc as w,la as te,ll as ne,ml as re,nn as T,or as ie,pa as E,qc as D,ra as O,tr as k,ua as ae,zt as A}from"./previewAssetResource-Dft3CbJ7.js";import{t as j}from"./arrow-right-CRbaksgv.js";import{a as oe,i as M,n as se,o as ce,r as le,s as ue,t as de}from"./toggle-group-zyF6bciU.js";import{Ar as fe,F as pe,Fr as me,I as he,J as ge,L as _e,Lr as ve,Nr as ye,R as N,Y as be,_ as xe,ai as Se,ar as Ce,at as we,cr as Te,ct as Ee,dr as De,h as Oe,ii as ke,ir as Ae,it as je,jr as Me,kr as Ne,lr as Pe,lt as Fe,or as Ie,ot as Le,pr as Re,rr as ze,rt as Be,sr as Ve,st as He,ur as Ue,yr as We}from"./index-BHm1p-1y.js";import{a as P,n as Ge}from"./fileCommentAnnotations-Cnw7YeSF.js";var Ke=a(`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}c.getState().openFile(e,t);return}r(n?x(t,n):t)}var I=r();function Je(e,t){let n=(0,I.c)(4),r=Re(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:l}=e,u=k(et),d=k(B),f;t[0]===a?f=t[1]:(f=e=>e.getComposerDraft(a)?.reviewComments??Ye,t[0]=a,t[1]=f);let p=k(f),[ee,m]=(0,F.useState)(null),[h,g]=(0,F.useState)(null),_;t[2]===n?_=t[3]:(_=new Map(n.map($e)),t[2]=n,t[3]=_);let v=_,y;if(t[4]!==h||t[5]!==n||t[6]!==p||t[7]!==r){let e;t[9]!==h||t[10]!==p||t[11]!==r?(e=e=>{let{fileDiff:t,filePath:n,fileKey:i,collapsed:a}=e,o=p.filter(e=>e.sectionId===r&&e.filePath===n&&(e.fenceLanguage??`diff`)===`diff`).reduce((e,n)=>{let r=b(t,n);return r?R(e,r,{id:n.id,kind:`comment`,range:r,rangeLabel:n.rangeLabel,text:n.text}):e},[]),s=h?.fileKey===i?[...o,h.annotation]:o;return{id:i,type:`diff`,fileDiff:t,annotations:s,collapsed:a,version:je(`${a?`1`:`0`}:${s.flatMap(z).join(`:`)}`)}},t[9]=h,t[10]=p,t[11]=r,t[12]=e):e=t[12],y=n.map(e),t[4]=h,t[5]=n,t[6]=p,t[7]=r,t[8]=y}else y=t[8];let x=y,S;t[13]!==a||t[14]!==h?.annotation||t[15]!==d?(S=e=>{m(null),h?.annotation.metadata.entries.some(t=>t.id===e)?g(null):d(a,e)},t[13]=a,t[14]=h?.annotation,t[15]=d,t[16]=S):S=t[16];let C=S,w;t[17]!==u||t[18]!==a||t[19]!==h||t[20]!==v||t[21]!==r||t[22]!==i?(w=(e,t)=>{let n=h?.annotation.metadata.entries.find(t=>t.id===e),o=h?v.get(h.fileKey):void 0;if(!n||!o)return;let s=ie({id:n.id,sectionId:r,sectionTitle:i,filePath:o.filePath,fileDiff:o.fileDiff,range:n.range,text:t});s&&u(a,s),m(null),g(null)},t[17]=u,t[18]=a,t[19]=h,t[20]=v,t[21]=r,t[22]=i,t[23]=w):w=t[23];let te=w,ne;t[24]!==v||t[25]!==r||t[26]!==i?(ne=(e,t)=>{if(!e)return;let n=t.item;if(n.type!==`diff`)return;let a=v.get(n.id);if(!a)return;let o=Ge(),s=ie({id:o,sectionId:r,sectionTitle:i,filePath:a.filePath,fileDiff:a.fileDiff,range:e,text:``});s&&g({fileKey:n.id,annotation:{side:Xe(e),lineNumber:e.end,metadata:{entries:[{id:o,kind:`draft`,range:e,rangeLabel:s.rangeLabel,text:``}]}}})},t[24]=v,t[25]=r,t[26]=i,t[27]=ne):ne=t[27];let re=ne,T=h!==null,E;t[28]===s?E=t[29]:(E=s?{ref:s}:{},t[28]=s,t[29]=E);let D;t[30]===c?D=t[31]:(D=c?{className:c}:{},t[30]=c,t[31]=D);let O=!T,ae=!T,A;t[32]!==re||t[33]!==o||t[34]!==ae||t[35]!==O?(A={...o,enableGutterUtility:O,enableLineSelection:ae,onLineSelectionEnd:re},t[32]=re,t[33]=o,t[34]=ae,t[35]=O,t[36]=A):A=t[36];let j;t[37]===l?j=t[38]:(j=e=>e.type===`diff`?l(e.fileDiff,e.id,e.collapsed===!0):null,t[37]=l,t[38]=j);let M;t[39]!==C||t[40]!==te?(M=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:()=>C(e.id),onComment:t=>te(e.id,t),onDelete:()=>C(e.id)},e.id))}),t[39]=C,t[40]=te,t[41]=M):M=t[41];let se;return t[42]!==x||t[43]!==ee||t[44]!==A||t[45]!==j||t[46]!==M||t[47]!==E||t[48]!==D?(se=(0,L.jsx)(oe,{...E,...D,items:x,selectedLines:ee,onSelectedLinesChange:m,options:A,renderHeaderPrefix:j,renderAnnotation:M}),t[42]=x,t[43]=ee,t[44]=A,t[45]=j,t[46]=M,t[47]=E,t[48]=D,t[49]=se):se=t[49],se}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:f(e,{label:`environment-data:review:diff-preview`,tag:l.reviewGetDiffPreview,staleTimeMs:5e3})}}var nt=tt(T);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
+ [data-diffs-header],
3
+ [data-diff],
4
+ [data-file],
5
+ [data-error-wrapper],
6
+ [data-virtualizer-buffer] {
7
+ --diffs-header-font-family: var(--font-sans) !important;
8
+ --diffs-font-family: var(--font-mono) !important;
9
+ --diffs-bg: color-mix(in srgb, var(--card) 90%, var(--background)) !important;
10
+ --diffs-light-bg: color-mix(in srgb, var(--card) 90%, var(--background)) !important;
11
+ --diffs-dark-bg: color-mix(in srgb, var(--card) 90%, var(--background)) !important;
12
+ --diffs-token-light-bg: transparent;
13
+ --diffs-token-dark-bg: transparent;
14
+
15
+ --diffs-bg-context-override: color-mix(in srgb, var(--background) 97%, var(--foreground));
16
+ --diffs-bg-hover-override: color-mix(in srgb, var(--background) 94%, var(--foreground));
17
+ --diffs-bg-separator-override: color-mix(in srgb, var(--background) 95%, var(--foreground));
18
+ --diffs-bg-buffer-override: color-mix(in srgb, var(--background) 90%, var(--foreground));
19
+
20
+ --diffs-bg-addition-override: color-mix(in srgb, var(--background) 92%, var(--success));
21
+ --diffs-bg-addition-number-override: color-mix(in srgb, var(--background) 88%, var(--success));
22
+ --diffs-bg-addition-hover-override: color-mix(in srgb, var(--background) 85%, var(--success));
23
+ --diffs-bg-addition-emphasis-override: color-mix(in srgb, var(--background) 80%, var(--success));
24
+
25
+ --diffs-bg-deletion-override: color-mix(in srgb, var(--background) 92%, var(--destructive));
26
+ --diffs-bg-deletion-number-override: color-mix(in srgb, var(--background) 88%, var(--destructive));
27
+ --diffs-bg-deletion-hover-override: color-mix(in srgb, var(--background) 85%, var(--destructive));
28
+ --diffs-bg-deletion-emphasis-override: color-mix(
29
+ in srgb,
30
+ var(--background) 80%,
31
+ var(--destructive)
32
+ );
33
+
34
+ background-color: var(--diffs-bg) !important;
35
+ }
36
+
37
+ [data-file-info] {
38
+ background-color: color-mix(in srgb, var(--card) 94%, var(--foreground)) !important;
39
+ border-block-color: var(--border) !important;
40
+ color: var(--foreground) !important;
41
+ }
42
+
43
+ [data-diffs-header] {
44
+ position: sticky !important;
45
+ top: 0;
46
+ z-index: 4;
47
+ background-color: color-mix(in srgb, var(--card) 94%, var(--foreground)) !important;
48
+ border-bottom: 1px solid var(--border) !important;
49
+ align-items: center !important;
50
+ font-family: var(--font-sans) !important;
51
+ font-size: 12px !important;
52
+ line-height: 1 !important;
53
+ min-height: 32px !important;
54
+ padding-block: 6px !important;
55
+ }
56
+
57
+ [data-diffs-header] [data-header-content] {
58
+ align-items: center !important;
59
+ line-height: 1 !important;
60
+ }
61
+
62
+ [data-diffs-header] [data-metadata] {
63
+ align-items: center !important;
64
+ line-height: 1 !important;
65
+ font-variant-numeric: tabular-nums;
66
+ }
67
+
68
+ [data-diffs-header] [data-additions-count],
69
+ [data-diffs-header] [data-deletions-count] {
70
+ font-family: var(--font-mono) !important;
71
+ font-size: 11px !important;
72
+ font-variant-numeric: tabular-nums;
73
+ line-height: 1 !important;
74
+ }
75
+
76
+ [data-diffs-header] [data-change-icon],
77
+ [data-diffs-header] [data-rename-icon] {
78
+ display: block;
79
+ flex-shrink: 0;
80
+ }
81
+
82
+ [data-title] {
83
+ cursor: pointer;
84
+ transition:
85
+ color 120ms ease,
86
+ text-decoration-color 120ms ease;
87
+ text-decoration: underline;
88
+ text-decoration-color: transparent;
89
+ text-underline-offset: 2px;
90
+ font-family: var(--font-sans) !important;
91
+ }
92
+
93
+ [data-title]:hover {
94
+ color: color-mix(in srgb, var(--foreground) 84%, var(--primary)) !important;
95
+ text-decoration-color: currentColor;
96
+ }
97
+ `;function U({mode:e=`inline`,composerDraftTarget:t,initialGitScope:n}){let{resolvedTheme:r}=h(),a=ye(),[c]=(0,F.useState)(n),[l,f]=(0,F.useState)(`stacked`),[b,x]=(0,F.useState)(a.wordWrap),[T,ie]=(0,F.useState)(a.diffIgnoreWhitespace),[k,oe]=(0,F.useState)(``),[xe,je]=(0,F.useState)(()=>({scopeKey:null,fileKeys:at})),Re=(0,F.useRef)(null),P=s({strict:!1,select:e=>A(e)}),Ge=P?.threadId??null,I=Me(P),Ye=I?.projectId??null,Xe=fe(I&&Ye?{environmentId:I.environmentId,projectId:Ye}:null),R=I?.worktreePath??Xe?.workspaceRoot,z=D(p.configValueAtom(I?.environmentId??null)),Qe=De(I?.environmentId??null,z?.availableEditors??[]),$e=g(I!=null&&R!=null?Ne.status({environmentId:I.environmentId,input:{cwd:R}}):null),B=N(e=>_e(e.byThreadKey,P,c===`unstaged`)),et=$e.data?.isRepo??!0,{turnDiffSummaries:tt,inferredCheckpointTurnCountByTurnId:V}=he(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=xe.scopeKey===Y?xe.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=g(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=g(_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=g(W===null&&G===`branch`&&I&&X.data?.cwd?Ne.listRefs({environmentId:I.environmentId,input:{cwd:X.data.cwd,includeMatchingRemoteRefs:!0,refKind:`local`,...k.trim().length>0?{query:k.trim()}:{},limit:100}}):null),bt=g(W===null&&G===`branch`&&I&&X.data?.cwd?Ne.listRefs({environmentId:I.environmentId,input:{cwd:X.data.cwd,includeMatchingRemoteRefs:!0,refKind:`remote`,...k.trim().length>0?{query:k.trim()}:{},limit:100}}):null),xt=rt(yt.data?.refs.filter(e=>e.name!==Z?.headRef)??[],bt.data?.refs??[]),St=it(xt,k),Ct=e=>K&&K===e.remote?.name?K:e.local?.name??e.remote?.name??e.id,wt=[H,...xt.map(Ct)],Tt=[...k.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)=>Fe(e).localeCompare(Fe(t),void 0,{numeric:!0,sensitivity:`base`})),[Q]),$=(0,F.useMemo)(()=>Mt.map(e=>{let t=Be(e);return{fileDiff:e,filePath:Fe(e),fileKey:t,collapsed:ft.has(t)}}),[ft,Mt]),Nt=(0,F.useMemo)(()=>$.map(e=>e.fileKey),[$]),Pt=le(Nt,ft),Ft=(0,F.useMemo)(()=>Le(Mt),[Mt]);(0,F.useEffect)(()=>{if(!st)return;let e=$.find(e=>e.filePath===st);e&&Re.current?.scrollTo({type:`item`,id:e.fileKey,align:`start`})},[$,st,ct]);let It=pe({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`&&!C(t)&&console.warn(`Failed to open diff file in editor.`,{operation:`open-diff-file`,...P?{environmentId:P.environmentId,threadId:P.threadId}:{},...re(ne(t))})})()}})},[R,It,Qe,P]),Rt=(0,F.useCallback)(e=>{je(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)(()=>{je(e=>{let t=e.scopeKey===Y?e.fileKeys:at;return{scopeKey:Y,fileKeys:M(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)(be,{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)(i,{children:[(0,L.jsxs)(y,{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)(u,{className:`size-3.5 shrink-0 text-muted-foreground`})]}),(0,L.jsxs)(S,{align:`start`,className:`w-60`,children:[(0,L.jsx)(O,{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)(O,{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)(O,{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)(te,{children:[(0,L.jsx)(_,{children:`Turn`}),(0,L.jsx)(ae,{className:`w-64`,children:U.map(e=>{let t=e.checkpointTurnCount??V[e.turnId]??`?`;return(0,L.jsxs)(O,{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:We(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)(j,{className:`size-3.5 shrink-0 opacity-70`}),(0,L.jsxs)(Ae,{items:wt,filteredItems:Tt,value:K??H,onOpenChange:e=>{e||oe(``)},onValueChange:e=>{e&&Ht(e===H?null:e)},children:[(0,L.jsxs)(Ue,{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)(u,{className:`size-3.5 shrink-0 opacity-70`})]}),(0,L.jsxs)(Pe,{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)(ve,{"aria-hidden":`true`,className:`pointer-events-none absolute top-1.5 left-0 size-4 shrink-0 text-muted-foreground/55`}),(0,L.jsx)(Ie,{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:k,onChange:e=>oe(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)(Ce,{children:`No matching refs.`}),(0,L.jsxs)(Te,{className:`max-h-64 min-w-0 overflow-x-hidden`,children:[(0,L.jsx)(Ve,{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)(Ve,{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)(ze,{"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)(w,{"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)(Oe,{additions:Ft.additions,deletions:Ft.deletions,className:`mr-1 text-[11px]`,layout:`inline`}),$.length>0&&(0,L.jsxs)(m,{children:[(0,L.jsx)(v,{render:(0,L.jsx)(ee,{type:`button`,size:`icon-xs`,variant:`outline`,"aria-label":Pt?`Expand all files`:`Collapse all files`,onClick:zt}),children:Pt?(0,L.jsx)(ke,{className:`size-3`}):(0,L.jsx)(Se,{className:`size-3`})}),(0,L.jsx)(d,{side:`top`,children:Pt?`Expand all files`:`Collapse all files`})]}),(0,L.jsxs)(se,{className:`shrink-0`,variant:`outline`,size:`xs`,value:[l],onValueChange:e=>{let t=e[0];(t===`stacked`||t===`split`)&&f(t)},children:[(0,L.jsx)(de,{"aria-label":`Stacked diff view`,value:`stacked`,children:(0,L.jsx)(ce,{className:`size-3`})}),(0,L.jsx)(de,{"aria-label":`Split diff view`,value:`split`,children:(0,L.jsx)(ue,{className:`size-3`})})]}),(0,L.jsxs)(m,{children:[(0,L.jsx)(v,{render:(0,L.jsx)(de,{"aria-label":b?`Disable diff line wrapping`:`Enable diff line wrapping`,variant:`outline`,size:`xs`,pressed:b,onPressedChange:e=>{x(!!e)}}),children:(0,L.jsx)(me,{className:`size-3`})}),(0,L.jsx)(d,{side:`top`,children:b?`Disable line wrapping`:`Enable line wrapping`})]}),(0,L.jsxs)(m,{children:[(0,L.jsx)(v,{render:(0,L.jsx)(de,{"aria-label":T?`Show whitespace changes`:`Hide whitespace changes`,variant:`outline`,size:`xs`,pressed:T,onPressedChange:e=>{ie(!!e)}}),children:(0,L.jsx)(Ke,{className:`size-3`})}),(0,L.jsx)(d,{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:Re,className:`diff-render-surface h-full min-h-0 overflow-auto`,files:$,sectionId:dt,sectionTitle:pt,composerDraftTarget:t,renderHeaderPrefix:(e,t,n)=>{let r=Fe(e);return(0,L.jsxs)(m,{children:[(0,L.jsx)(v,{render:(0,L.jsx)(`button`,{type:`button`,className:E(`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`,we(e)),"aria-label":n?`Expand ${r}`:`Collapse ${r}`,"aria-expanded":!n,onClick:e=>{e.stopPropagation(),Rt(t)}}),children:n?(0,L.jsx)(o,{className:`size-4`}):(0,L.jsx)(u,{className:`size-4`})}),(0,L.jsx)(d,{side:`top`,children:n?`Expand diff`:`Collapse diff`})]})},options:{diffStyle:l===`split`?`split`:`unified`,lineDiffType:`none`,overflow:b?`wrap`:`scroll`,theme:Ee(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:E(`max-h-[72vh] rounded-md border border-border/70 bg-background/70 p-3 font-mono text-[11px] leading-relaxed text-muted-foreground/90`,b?`overflow-auto whitespace-pre-wrap wrap-break-word`:`overflow-auto`),children:Q.text})]})}):kt?(0,L.jsx)(ge,{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{xe as DiffWorkerPoolProvider,U as default};
98
+ //# sourceMappingURL=DiffPanel-BHB_7YUC.js.map