zidane 5.4.3 → 5.5.0

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.
Files changed (76) hide show
  1. package/README.md +30 -1
  2. package/dist/{agent-Yu8uhpy-.d.ts → agent-CvImMxMQ.d.ts} +183 -3
  3. package/dist/agent-CvImMxMQ.d.ts.map +1 -0
  4. package/dist/chat.d.ts +93 -15
  5. package/dist/chat.d.ts.map +1 -1
  6. package/dist/chat.js +3 -2
  7. package/dist/contexts/docker.d.ts +1 -1
  8. package/dist/contexts-DhmMlT2W.js +472 -0
  9. package/dist/contexts-DhmMlT2W.js.map +1 -0
  10. package/dist/contexts.d.ts +3 -3
  11. package/dist/contexts.js +1 -1
  12. package/dist/{index-DklfxeYy.d.ts → index-B0uc2C5x.d.ts} +3 -3
  13. package/dist/{index-DklfxeYy.d.ts.map → index-B0uc2C5x.d.ts.map} +1 -1
  14. package/dist/{index-BiO_5Hm4.d.ts → index-CbS75MD3.d.ts} +2 -2
  15. package/dist/index-CbS75MD3.d.ts.map +1 -0
  16. package/dist/{index-j9tY28ah.d.ts → index-CtXksgqb.d.ts} +60 -4
  17. package/dist/index-CtXksgqb.d.ts.map +1 -0
  18. package/dist/index.d.ts +6 -6
  19. package/dist/index.js +8 -8
  20. package/dist/{interpolate-CmtjEyRJ.js → interpolate-BaaKaKzN.js} +2 -2
  21. package/dist/{interpolate-CmtjEyRJ.js.map → interpolate-BaaKaKzN.js.map} +1 -1
  22. package/dist/{login-DxyAERe1.js → login-iTy-0wYz.js} +2 -2
  23. package/dist/{login-DxyAERe1.js.map → login-iTy-0wYz.js.map} +1 -1
  24. package/dist/mcp.d.ts +1 -1
  25. package/dist/{presets-D9IbaI40.js → presets-h6UWhghO.js} +3 -2
  26. package/dist/presets-h6UWhghO.js.map +1 -0
  27. package/dist/presets.d.ts +2 -2
  28. package/dist/presets.js +1 -1
  29. package/dist/{providers-CEzRFYtS.js → providers-G0VBZK9j.js} +2 -2
  30. package/dist/{providers-CEzRFYtS.js.map → providers-G0VBZK9j.js.map} +1 -1
  31. package/dist/providers.d.ts +1 -1
  32. package/dist/providers.js +1 -1
  33. package/dist/session/sqlite.d.ts +1 -1
  34. package/dist/session/sqlite.d.ts.map +1 -1
  35. package/dist/session/sqlite.js +1 -0
  36. package/dist/session/sqlite.js.map +1 -1
  37. package/dist/{session-kwsNnOmt.js → session-CbkiJDlH.js} +2 -1
  38. package/dist/session-CbkiJDlH.js.map +1 -0
  39. package/dist/session.d.ts +1 -1
  40. package/dist/session.js +1 -1
  41. package/dist/skills.d.ts +2 -2
  42. package/dist/skills.js +1 -1
  43. package/dist/{tools-BK2vG9UX.js → tools-D_icxa-V.js} +668 -256
  44. package/dist/tools-D_icxa-V.js.map +1 -0
  45. package/dist/tools.d.ts +3 -3
  46. package/dist/tools.js +2 -2
  47. package/dist/{transcript-anchors-DnaBcJej.d.ts → transcript-anchors-3FFw2xuk.d.ts} +49 -10
  48. package/dist/transcript-anchors-3FFw2xuk.d.ts.map +1 -0
  49. package/dist/tui.d.ts +27 -5
  50. package/dist/tui.d.ts.map +1 -1
  51. package/dist/tui.js +239 -39
  52. package/dist/tui.js.map +1 -1
  53. package/dist/{turn-operations-OzKEOXul.js → turn-operations-CtgBlBHn.js} +178 -79
  54. package/dist/turn-operations-CtgBlBHn.js.map +1 -0
  55. package/dist/types-IcokUOyC.js.map +1 -1
  56. package/dist/types-KukEp-mi.d.ts +253 -0
  57. package/dist/types-KukEp-mi.d.ts.map +1 -0
  58. package/dist/types.d.ts +4 -4
  59. package/docs/ARCHITECTURE.md +21 -0
  60. package/docs/CHAT.md +3 -1
  61. package/docs/RUN_IN_BACKGROUND.md +612 -0
  62. package/docs/SKILL.md +59 -0
  63. package/docs/TUI.md +16 -2
  64. package/package.json +2 -2
  65. package/dist/agent-Yu8uhpy-.d.ts.map +0 -1
  66. package/dist/contexts-BwiHIr2w.js +0 -129
  67. package/dist/contexts-BwiHIr2w.js.map +0 -1
  68. package/dist/index-BiO_5Hm4.d.ts.map +0 -1
  69. package/dist/index-j9tY28ah.d.ts.map +0 -1
  70. package/dist/presets-D9IbaI40.js.map +0 -1
  71. package/dist/session-kwsNnOmt.js.map +0 -1
  72. package/dist/tools-BK2vG9UX.js.map +0 -1
  73. package/dist/transcript-anchors-DnaBcJej.d.ts.map +0 -1
  74. package/dist/turn-operations-OzKEOXul.js.map +0 -1
  75. package/dist/types-Ce78ds4h.d.ts +0 -88
  76. package/dist/types-Ce78ds4h.d.ts.map +0 -1
@@ -1,17 +1,17 @@
1
- import { a as multiEdit, c as grep, d as resolveOldString, f as styleReplacementForVia, i as readFile$1, l as glob, n as createSpawnTool, o as listFiles, r as shell, t as writeFile$1, u as edit } from "./tools-BK2vG9UX.js";
1
+ import { H as previewLine, R as fmtTokens, U as shortId, a as multiEdit, c as grep, d as resolveOldString, f as styleReplacementForVia, i as readFile$1, l as glob, n as createSpawnTool, o as listFiles, t as writeFile$1, u as edit, y as shell } from "./tools-D_icxa-V.js";
2
2
  import { s as errorMessage } from "./errors-CDwtPIMX.js";
3
3
  import { n as toolResultToText } from "./types-IcokUOyC.js";
4
4
  import { r as normalizeMcpServers } from "./mcp-CNUbvbsy.js";
5
- import { a as discoverSkills } from "./interpolate-CmtjEyRJ.js";
5
+ import { a as discoverSkills } from "./interpolate-BaaKaKzN.js";
6
6
  import { n as formatTokenUsage } from "./stats-DgOvY7wd.js";
7
- import { n as definePreset, t as composePresets } from "./presets-D9IbaI40.js";
8
- import { a as writeFileAtomic, i as anthropic, n as openai, r as cerebras, t as openrouter } from "./providers-CEzRFYtS.js";
7
+ import { n as definePreset, t as composePresets } from "./presets-h6UWhghO.js";
8
+ import { a as writeFileAtomic, i as anthropic, n as openai, r as cerebras, t as openrouter } from "./providers-G0VBZK9j.js";
9
+ import { dirname, isAbsolute, join, posix, relative, resolve, sep } from "node:path";
10
+ import { homedir } from "node:os";
9
11
  import { spawn } from "node:child_process";
12
+ import { existsSync, mkdirSync, readFileSync, statSync } from "node:fs";
10
13
  import { readdir, stat, writeFile } from "node:fs/promises";
11
- import { dirname, isAbsolute, join, posix, relative, resolve, sep } from "node:path";
12
14
  import { getModel, getModels } from "@mariozechner/pi-ai";
13
- import { existsSync, mkdirSync, readFileSync, statSync } from "node:fs";
14
- import { homedir } from "node:os";
15
15
  import { anthropicOAuthProvider, openaiCodexOAuthProvider } from "@mariozechner/pi-ai/oauth";
16
16
  import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
17
17
  import { jsx } from "react/jsx-runtime";
@@ -1889,7 +1889,7 @@ function scoreFiles(catalog, query, limit, formatPath) {
1889
1889
  return scored.slice(0, limit).map(({ entry, display }) => ({
1890
1890
  id: display,
1891
1891
  label: entry.name,
1892
- description: parentDir(display),
1892
+ description: parentDir(entry.path),
1893
1893
  insertText: `@${display} `,
1894
1894
  data: entry
1895
1895
  }));
@@ -3321,9 +3321,45 @@ function deriveSessionTitle(turns, metadata) {
3321
3321
  */
3322
3322
  function eventsFromTurns(turns, runs = []) {
3323
3323
  const runById = /* @__PURE__ */ new Map();
3324
- for (const run of runs) runById.set(run.id, run);
3324
+ for (const run of runs) if (!runById.has(run.id)) runById.set(run.id, run);
3325
+ const runStack = [];
3326
+ const pendingToolCallsPerRun = /* @__PURE__ */ new Map();
3327
+ for (const turn of turns) {
3328
+ const rid = turn.runId;
3329
+ if (!rid) continue;
3330
+ const idxInStack = runStack.indexOf(rid);
3331
+ if (idxInStack >= 0) runStack.length = idxInStack + 1;
3332
+ else {
3333
+ const top = runStack[runStack.length - 1];
3334
+ if (!(top !== void 0 && (pendingToolCallsPerRun.get(top)?.size ?? 0) > 0)) runStack.length = 0;
3335
+ runStack.push(rid);
3336
+ if (!runById.has(rid)) {
3337
+ const depth = runStack.length - 1;
3338
+ const parentRunId = depth > 0 ? runStack[depth - 1] : void 0;
3339
+ let inferredPrompt = "";
3340
+ if (turn.role === "user") {
3341
+ for (const block of turn.content) if (block.type === "text" && block.text.trim()) {
3342
+ inferredPrompt = block.text;
3343
+ break;
3344
+ }
3345
+ }
3346
+ runById.set(rid, {
3347
+ id: rid,
3348
+ startedAt: turn.createdAt,
3349
+ prompt: inferredPrompt,
3350
+ status: "completed",
3351
+ depth,
3352
+ ...parentRunId ? { parentRunId } : {}
3353
+ });
3354
+ }
3355
+ }
3356
+ const pending = pendingToolCallsPerRun.get(rid) ?? /* @__PURE__ */ new Set();
3357
+ for (const block of turn.content) if (block.type === "tool_call") pending.add(block.id);
3358
+ else if (block.type === "tool_result") pending.delete(block.callId);
3359
+ pendingToolCallsPerRun.set(rid, pending);
3360
+ }
3325
3361
  const childLabelByRunId = /* @__PURE__ */ new Map();
3326
- runs.filter((r) => (r.depth ?? 0) > 0).slice().sort((a, b) => a.startedAt - b.startedAt).forEach((r, i) => childLabelByRunId.set(r.id, `child-${i + 1}`));
3362
+ [...runById.values()].filter((r) => (r.depth ?? 0) > 0).sort((a, b) => a.startedAt - b.startedAt).forEach((r, i) => childLabelByRunId.set(r.id, `child-${i + 1}`));
3327
3363
  const labelFor = (runId) => childLabelByRunId.get(runId) ?? runId;
3328
3364
  const toolByCallId = /* @__PURE__ */ new Map();
3329
3365
  for (const turn of turns) {
@@ -3369,7 +3405,7 @@ function eventsFromTurns(turns, runs = []) {
3369
3405
  });
3370
3406
  };
3371
3407
  const pushSpawnStart = (run) => {
3372
- const taskPreview = run.prompt.length > 80 ? `${run.prompt.slice(0, 80)}…` : run.prompt;
3408
+ const taskPreview = previewLine(run.prompt, 80);
3373
3409
  events.push({
3374
3410
  kind: "spawn-start",
3375
3411
  text: taskPreview,
@@ -3399,6 +3435,11 @@ function eventsFromTurns(turns, runs = []) {
3399
3435
  };
3400
3436
  if (turn.role === "user") {
3401
3437
  for (const block of turn.content) if (block.type === "text" && block.text.trim()) {
3438
+ const taskEvent = parseTaskNotificationBlock(block.text, tag);
3439
+ if (taskEvent) {
3440
+ events.push(taskEvent);
3441
+ continue;
3442
+ }
3402
3443
  if (depth === 0) {
3403
3444
  if (lastDepthAtEmission === 0) events.push({
3404
3445
  kind: "separator",
@@ -3474,6 +3515,84 @@ function eventsFromTurns(turns, runs = []) {
3474
3515
  return events;
3475
3516
  }
3476
3517
  /** Shared formatter for the `↳ name(args)` line shown on tool calls. */
3518
+ /**
3519
+ * Pattern matching the leading `<task-notification>` shape that the
3520
+ * agent's notification-injection path produces (see
3521
+ * `renderTaskNotificationXml` in `src/agent.ts`). Anchored so a stray
3522
+ * notification-shaped phrase mid-prompt doesn't trigger a false-positive
3523
+ * detection — the model's wire format always starts the user-turn
3524
+ * content block with this exact opening tag.
3525
+ */
3526
+ const TASK_NOTIFICATION_RE = /^\s*<task-notification>([\s\S]*?)<\/task-notification>\s*$/;
3527
+ /**
3528
+ * Per-field extractors. Compiled once at module load (parsing happens
3529
+ * on every session replay, and a fresh `new RegExp` per pick burns
3530
+ * cycles for no reason).
3531
+ */
3532
+ const TASK_NOTIFICATION_FIELD_RES = {
3533
+ taskId: /<task-id>([\s\S]*?)<\/task-id>/,
3534
+ status: /<status>([\s\S]*?)<\/status>/,
3535
+ exitCode: /<exit-code>([\s\S]*?)<\/exit-code>/,
3536
+ command: /<command>([\s\S]*?)<\/command>/,
3537
+ outputFile: /<output-file>([\s\S]*?)<\/output-file>/,
3538
+ durationMs: /<duration-ms>([\s\S]*?)<\/duration-ms>/,
3539
+ summary: /<summary>([\s\S]*?)<\/summary>/
3540
+ };
3541
+ /**
3542
+ * Detect a `<task-notification>` text block on replay and convert it
3543
+ * into a structured `task-notification` StreamEvent so the TUI's banner
3544
+ * renderer can paint it cleanly. Returns `null` when the block isn't a
3545
+ * notification (the caller falls back to the normal user-prompt path).
3546
+ *
3547
+ * Reads every field DIRECTLY from its tag — does NOT parse `<summary>`
3548
+ * for the underlying data. The summary is a derived display string,
3549
+ * not a source of truth: changing its format (localization, signal in
3550
+ * the label, whatever) must NEVER break replay. Each field falls back
3551
+ * to a safe default so older transcripts pre-dating a tag addition
3552
+ * still render.
3553
+ */
3554
+ function parseTaskNotificationBlock(text, tag) {
3555
+ const m = text.match(TASK_NOTIFICATION_RE);
3556
+ if (!m) return null;
3557
+ const body = m[1];
3558
+ const pick = (re) => {
3559
+ const inner = body.match(re);
3560
+ return inner ? unescapeXml(inner[1].trim()) : void 0;
3561
+ };
3562
+ const taskId = pick(TASK_NOTIFICATION_FIELD_RES.taskId) ?? "?";
3563
+ const statusRaw = pick(TASK_NOTIFICATION_FIELD_RES.status) ?? "exited";
3564
+ const status = statusRaw === "killed" ? "killed" : "exited";
3565
+ const exitCode = Number.parseInt(pick(TASK_NOTIFICATION_FIELD_RES.exitCode) ?? "0", 10) || 0;
3566
+ const command = pick(TASK_NOTIFICATION_FIELD_RES.command) ?? "";
3567
+ const outputPath = pick(TASK_NOTIFICATION_FIELD_RES.outputFile) ?? "";
3568
+ const durationMs = Number.parseInt(pick(TASK_NOTIFICATION_FIELD_RES.durationMs) ?? "0", 10) || 0;
3569
+ return {
3570
+ kind: "task-notification",
3571
+ text: pick(TASK_NOTIFICATION_FIELD_RES.summary) ?? `${taskId} ${statusRaw}${exitCode ? ` ${exitCode}` : ""}`,
3572
+ task: {
3573
+ taskId,
3574
+ status,
3575
+ exitCode,
3576
+ outputPath,
3577
+ command,
3578
+ durationMs
3579
+ },
3580
+ turnId: tag.turnId,
3581
+ ...tag.childId !== void 0 ? { childId: tag.childId } : {},
3582
+ ...tag.depth !== void 0 ? { depth: tag.depth } : {}
3583
+ };
3584
+ }
3585
+ /**
3586
+ * Reverse of `escapeXml` for the small set of entities the writer
3587
+ * emits. Not a full HTML entity decoder — just enough to round-trip
3588
+ * `<` / `>` / `&` / quotes through persistence.
3589
+ *
3590
+ * `&amp;` MUST be replaced last, otherwise `&amp;lt;` becomes `&lt;`
3591
+ * then `<` (data corruption — silent double-decode).
3592
+ */
3593
+ function unescapeXml(s) {
3594
+ return s.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, "\"").replace(/&apos;/g, "'").replace(/&amp;/g, "&");
3595
+ }
3477
3596
  function toolCallPreview(name, input) {
3478
3597
  const args = JSON.stringify(input);
3479
3598
  return args && args !== "{}" ? `${name}(${args})` : name;
@@ -3606,7 +3725,8 @@ const MARGIN_TOP = {
3606
3725
  "markdown": 1,
3607
3726
  "spawn-start": 1,
3608
3727
  "spawn-end": 0,
3609
- "compact-summary": 1
3728
+ "compact-summary": 1,
3729
+ "task-notification": 1
3610
3730
  };
3611
3731
  const TOOL_KINDS = new Set(["tool", "tool-result"]);
3612
3732
  /**
@@ -3616,20 +3736,28 @@ const TOOL_KINDS = new Set(["tool", "tool-result"]);
3616
3736
  * - A `tool` / `tool-result` event right after another
3617
3737
  * `tool` / `tool-result` collapses to a tight list — call→result
3618
3738
  * pairs and back-to-back calls read as one logical block.
3619
- * - A parent-level event (`depth === 0`) right after a subagent event
3620
- * (`depth > 0`) collapses too. The subagent's `🌳` end marker
3621
- * already provides the separation; adding the event's default
3622
- * `marginTop` on top would produce the visible "line jump" between
3623
- * a subagent's outcome and the parent's follow-up.
3739
+ * - Consecutive `task-notification` banners stack tight a burst of
3740
+ * background-task completions reads as one log column rather than
3741
+ * scattered banners.
3742
+ *
3743
+ * NB: parent-level events (`depth === 0`) following a subagent block
3744
+ * (`depth > 0`) get their normal default margin. An earlier revision
3745
+ * collapsed this transition to 0 on the assumption that the subagent's
3746
+ * `🌳` end-marker provided enough visual separation — it didn't. A
3747
+ * 2-cell emoji on the same row as the close marker doesn't create a
3748
+ * vertical break, and in hide-subagent-output mode the SubagentBlock
3749
+ * box isn't rendered either, so the parent's follow-up markdown was
3750
+ * glued directly against the close line. Subagents should READ like
3751
+ * tool calls: open with breathing room, close tight inside, and open
3752
+ * a clean gap before the parent's next thought — that's the contract
3753
+ * the tool-call → markdown transition uses, mirrored here.
3624
3754
  *
3625
3755
  * Renderer-agnostic — TUI uses it as Yoga `marginTop`; a CSS host can
3626
3756
  * use the same number as the row's top margin in `em` / `rem`.
3627
3757
  */
3628
3758
  function marginTopFor(event, previous) {
3629
3759
  if (TOOL_KINDS.has(event.kind) && previous && TOOL_KINDS.has(previous.kind)) return 0;
3630
- const eventDepth = event.depth ?? 0;
3631
- const previousDepth = previous?.depth ?? 0;
3632
- if (eventDepth === 0 && previousDepth > 0) return 0;
3760
+ if (event.kind === "task-notification" && previous?.kind === "task-notification") return 0;
3633
3761
  return MARGIN_TOP[event.kind] ?? 0;
3634
3762
  }
3635
3763
  /**
@@ -5421,51 +5549,6 @@ function toEntries(paths, source, maxFiles) {
5421
5549
  return out;
5422
5550
  }
5423
5551
  //#endregion
5424
- //#region src/chat/format.ts
5425
- /** Compact token formatter — 12_415 → "12.4k", 1_234_567 → "1.23M". */
5426
- function fmtTokens(n) {
5427
- if (n < 1e3) return String(n);
5428
- if (n < 1e6) return `${(n / 1e3).toFixed(n < 1e4 ? 2 : 1)}k`;
5429
- return `${(n / 1e6).toFixed(2)}M`;
5430
- }
5431
- /** Compact relative-time formatter — "just now / 5m / 3h / 2d". */
5432
- function ageString(ts, now = Date.now()) {
5433
- const m = Math.floor((now - ts) / 6e4);
5434
- if (m < 1) return "just now";
5435
- if (m < 60) return `${m}m ago`;
5436
- const h = Math.floor(m / 60);
5437
- if (h < 24) return `${h}h ago`;
5438
- return `${Math.floor(h / 24)}d ago`;
5439
- }
5440
- /** Six-char short form of a session id for headers and lists. */
5441
- function shortId(id) {
5442
- return id.replace(/-/g, "").slice(0, 6);
5443
- }
5444
- /**
5445
- * Compact an absolute path for display: replace the user's `$HOME`
5446
- * prefix with `~` (so `/Users/yael/Code/zidane` → `~/Code/zidane`),
5447
- * and optionally left-truncate with an ellipsis when the result
5448
- * still exceeds `maxWidth` (so the path's *tail* — the part the user
5449
- * recognizes — stays visible: `…/zidane` rather than `/Users/yaeluil…`).
5450
- *
5451
- * `maxWidth` is the maximum *display width* in cells. Omit to skip
5452
- * truncation. Paths outside `$HOME` are returned verbatim modulo
5453
- * truncation. The ellipsis (`…`) counts as one cell.
5454
- *
5455
- * `home` overrides `os.homedir()` for tests; production callers leave
5456
- * it undefined and pay the cheap one-syscall lookup per call.
5457
- */
5458
- function compactPath(path, maxWidth, home) {
5459
- const h = home ?? homedir();
5460
- let display = path;
5461
- if (h) {
5462
- if (path === h) display = "~";
5463
- else if (path.startsWith(`${h}/`)) display = `~${path.slice(h.length)}`;
5464
- }
5465
- if (maxWidth !== void 0 && maxWidth > 1 && display.length > maxWidth) return `…${display.slice(display.length - maxWidth + 1)}`;
5466
- return display;
5467
- }
5468
- //#endregion
5469
5552
  //#region src/chat/generate-title.ts
5470
5553
  /** Hard cap on the result length. Anything longer is truncated client-side. */
5471
5554
  const TITLE_MAX_CHARS = 60;
@@ -6678,13 +6761,17 @@ async function runOAuthLogin(descriptor, options) {
6678
6761
  *
6679
6762
  * Rule:
6680
6763
  *
6681
- * - When the resolved target sits inside `cwd` → return a
6682
- * CWD-relative forward-slashed path (no `..` traversal).
6683
- * - Otherwise (target sits above `cwd`, or `cwd` is outside the
6684
- * project) return the absolute path. A `..`-laden relative
6685
- * form would be valid for the tools but harder to read AND
6686
- * surprises the user, whose mental model of `@` is "pick a
6687
- * file from the project view".
6764
+ * - File at `cwd` itself `.`.
6765
+ * - File under `cwd` (subtree) forward-slashed CWD-relative,
6766
+ * no `..`.
6767
+ * - File above `cwd` but still inside the project → CWD-relative
6768
+ * with `..` traversal (e.g. `../EDIT_THIS.md`). Shorter and more
6769
+ * scannable than absolute, and the agent's tools resolve both.
6770
+ * - File outside the project (input was passed absolute) → returned
6771
+ * verbatim. Inputs that arrive as project-root-relative strings
6772
+ * are always inside the project by construction, so this branch
6773
+ * only kicks in when a direct caller hands the function an
6774
+ * absolute target.
6688
6775
  *
6689
6776
  * Pure, no I/O, deterministic.
6690
6777
  */
@@ -6695,13 +6782,18 @@ async function runOAuthLogin(descriptor, options) {
6695
6782
  *
6696
6783
  * Inputs:
6697
6784
  * - `projectRelativePath` — forward-slashed, no leading slash. Returned
6698
- * verbatim when it's empty or already absolute (defensive).
6785
+ * verbatim when it's empty or already absolute (defensive — the
6786
+ * absolute-input branch is the de-facto "outside the project"
6787
+ * escape; the catalog itself never emits absolute paths).
6699
6788
  * - `projectRoot` — absolute path of the discovery anchor.
6700
6789
  * - `cwd` — absolute path of `process.cwd()` at the moment of
6701
6790
  * insertion.
6702
6791
  *
6703
- * Output is always either an absolute path OR a CWD-relative path with
6704
- * no `..` segments. Never a `..`-prefixed relative path.
6792
+ * Output is always either an absolute path (only when the input arrived
6793
+ * absolute) OR a CWD-relative path. The relative form may include
6794
+ * `../` segments when the target sits above `cwd` within the project,
6795
+ * which keeps cross-tree references short and scannable
6796
+ * (e.g. `../EDIT_THIS.md` instead of `/Users/.../zidane/EDIT_THIS.md`).
6705
6797
  */
6706
6798
  function formatPathForCwd(projectRelativePath, projectRoot, cwd) {
6707
6799
  if (projectRelativePath.length === 0) return projectRelativePath;
@@ -6711,7 +6803,6 @@ function formatPathForCwd(projectRelativePath, projectRoot, cwd) {
6711
6803
  if (target === here) return ".";
6712
6804
  const rel = relative(here, target);
6713
6805
  if (rel.length === 0) return ".";
6714
- if (rel === ".." || rel.startsWith(`..${sep}`) || rel.startsWith("../")) return target;
6715
6806
  return sep === "/" ? rel : rel.split(sep).join(posix.sep);
6716
6807
  }
6717
6808
  //#endregion
@@ -7872,13 +7963,21 @@ const TOOL_DISPLAY = {
7872
7963
  }
7873
7964
  },
7874
7965
  shell: {
7875
- displayName: "Shell",
7966
+ displayName: (input) => input?.run_in_background === true ? "Shell (background)" : "Shell",
7876
7967
  format: (input) => {
7877
7968
  const command = stringField(input, "command");
7878
7969
  if (!command) return null;
7879
7970
  return { target: truncate(command.trim(), 200) };
7880
7971
  }
7881
7972
  },
7973
+ shell_kill: {
7974
+ displayName: "Kill task",
7975
+ format: (input) => {
7976
+ const taskId = stringField(input, "task_id");
7977
+ if (!taskId) return null;
7978
+ return { target: taskId };
7979
+ }
7980
+ },
7882
7981
  edit: {
7883
7982
  displayName: "Edit",
7884
7983
  format: (input) => {
@@ -8246,6 +8345,6 @@ function countNeighbors(turnIds, turnId) {
8246
8345
  };
8247
8346
  }
8248
8347
  //#endregion
8249
- export { useMcpAuthDispatch as $, mergeReferences as $n, IDENTITY_PREFIX as $r, isTurnHighlighted as $t, getSafelist as A, rewriteMultiEditHeader as An, DEFAULT_AGENT_ID as Ar, clampFps as At, supportsOAuth as B, mergeKeybindings as Bn, TODO_WRITE_COUNTS_METADATA_KEY as Br, CATPPUCCIN_MOCHA as Bt, resolveSessionExportTarget as C, summarizeEditPayload as Cn, modelSupportsReasoning as Cr, shortId as Ct, useSafeModeQueue as D, mergeApprovalAndBodyOutcomes as Dn, piIdOf as Dr, SETTINGS_CHOICES as Dt, useSafeModeActions as E, maskToOutcomeKinds as En, openrouterDescriptor as Er, DEFAULT_SETTINGS as Et, suggestSafelistEntry as F, KEYBINDING_DEFS as Fn, singleAgentRegistry as Fr, resolveTheme as Ft, defaultMcpsConfigPaths as G, createSkillsCompletionProvider as Gn, pickActiveRunId as Gr, ConfigProvider as Gt, filterModelCatalog as H, readKeybindings as Hn, getArchivedTodosForRun as Hr, DiscoveryProvider as Ht, writeProjects as I, KEYBINDING_DEF_BY_ACTION as In, TODOREAD_TOOL as Ir, VAPORWAVE_THEME as It, projectUserPaths as J, createFilesCompletionProvider as Jn, setTodosForRun as Jr, EDIT_TOOL_NAMES as Jt, discoverProjectMcps as K, uniqueSkillNamesFromReferences as Kn, pruneTodosByRun as Kr, useConfig as Kt, splitPromptSegments as L, ensureKeybindingsFile as Ln, TODOS_METADATA_KEY as Lr, CATPPUCCIN_FRAPPE as Lt, matchesSafelistEntry as M, summarizeOutcomes as Mn, PLAN_AGENT as Mr, BUILTIN_THEMES as Mt, projectsFilePath as N, findGitRoot$1 as Nn, accentColor as Nr, DEFAULT_THEME as Nt, IMPLICITLY_SAFE_TOOLS as O, parseEditOutcomesFromResult as On, BUILD_AGENT as Or, SETTINGS_TOGGLES as Ot, readProjects as P, DEFAULT_KEYBINDINGS as Pn, resolveAgentId as Pr, resolveChipColor as Pt, McpAuthProvider as Q, findActiveTrigger as Qn, DOING_TASKS_DOCTRINE as Qr, isEditErrorResult as Qt, formatPathForCwd as R, keybindingsPath as Rn, TODOWRITE_TOOL as Rr, CATPPUCCIN_LATTE as Rt, renderSession as S, splitLines as Sn, getModelInfo as Sr, fmtTokens as St, SafeModeProvider as T, buildEditOutcomesAnnotation as Tn, openaiDescriptor as Tr, useEnabledToggleSet as Tt, indexOfEntry as U, stripJsonComments as Un, getTodosForRun as Ur, useDiscovery as Ut, buildModelCatalog as V, parseBindingSpec as Vn, createTodoTools as Vr, createDiscoverySlot as Vt, buildMcpServers as W, SKILLS_TRIGGER as Wn, isTodoTool as Wr, useDiscoveryOptional as Wt, mcpCredentialsPath as X, applyInsert as Xn, ACTIONS_WITH_CARE_DOCTRINE as Xr, deriveSessionTitle as Xt, createFileMcpCredentialStore as Y, uniqueFilesFromReferences as Yn, useActiveTodos as Yr, createStateStore as Yt, patchMcpCredential as Z, collectReferences as Zn, COMMUNICATION_DOCTRINE as Zr, eventsFromTurns as Zt, turnContextSize as _, computeInlineDiff as _n, anthropicDescriptor as _r, truncateTrailing as _t, computeTurnAnchors as a, TOKEN_DISCIPLINE_DOCTRINE as ai, saveState as an, bootTick as ar, InteractionsProvider as at, defaultSkillScanPaths as b, filetypeFromPath as bn, effectiveContextWindow as br, ageString as bt, formatToolCall as c, envSection as ci, sumRunCosts as cn, applyApiKeyEnv as cr, createInteractionTools as ct, useSelectStyle as d, toolResultText as dn, readProviderCredential as dr, pendingInteractionsFromTurns as dt, INTERACTION_GUIDANCE as ei, isVisible as en, useCompletion as er, useMcpAuthState as et, useSurfaces as f, turnSelectionOwnership as fn, removeProviderCredential as fr, serializeInteractionResponse as ft, finalizeStreamingMarkdownForOwner as g, buildUnifiedDiff as gn, OUTPUT_RESERVE_TOKENS as gr, hintsLength as gt, finalizeStreamingMarkdown as h, buildContextualDiff as hn, BUILTIN_PROVIDERS as hr, clipHintsToWidth as ht, turnAsText as i, SUBAGENT_GUIDANCE as ii, marginTopFor as in, bootProfileEnabled as ir, ASK_USER_TOOL as it, isOnSafelist as j, stripEditOutcomesAnnotation as jn, DEFAULT_PERSIST_EXCLUDE_TOOLS as jr, useSettings as jt, addToSafelist as k, resolveApprovalForPayload as kn, BUILTIN_AGENTS as kr, SettingsProvider as kt, ThemeProvider as l, titleFromTurns as ln, credentialsPath as lr, isInteractionTool as lt, useTheme as m, applyEditPayload as mn, writeCredentials as mr, useInteractionsQueue as mt, deleteTurnSafely as n, PLAN_MODE_DOCTRINE as ni, listSessionMeta as nn, buildLinearRamp as nr, reduceMcpAuth as nt, TOOL_DISPLAY as o, buildBuildSystem as oi, selectableTurnIds as on, shouldAutoCompact as or, PRESENT_PLAN_TOOL as ot, useSyntaxStyles as p, updateToolEventOutcomes as pn, setProviderCredential as pr, useInteractionsActions as pt, parseMcpsFile as q, FILES_TRIGGER as qn, selectActiveTodos as qr, resolveConfig as qt, truncateTurnsAt as r, PLAN_MODE_DOCTRINE_NO_PROMPTS as ri, loadState as rn, tryOpenBrowser as rr, splitMarkdownCodeBlocks as rt, displayNameFor as s, buildPlanSystem as si, stripSpawnTokensLine as sn, detectAuth as sr, buildResumedToolResultsTurn as st, countNeighbors as t, INTERACTION_GUIDANCE_NO_PROMPTS as ti, lastContextSizeFromTurns as tn, blendHsl as tr, getMcpAuthStatus as tt, useColors as u, toolCallPreview as un, readCredentials as ur, makeRequestInteraction as ut, useStreamBuffer as v, computeLineDiff as vn, cerebrasDescriptor as vr, cleanTitle as vt, writeSessionExport as w, tokenize as wn, modelsForDescriptor as wr, listProjectFiles as wt, discoverProjectSkills as x, previewEditPayload as xn, getContextWindow as xr, compactPath as xt, buildSkillsConfig as y, extractEditPayload as yn, credKeyOf as yr, generateSessionTitle as yt, runOAuthLogin as z, matchesBinding as zn, TODO_STATUS_GLYPHS as zr, CATPPUCCIN_MACCHIATO as zt };
8348
+ export { useMcpAuthDispatch as $, tryOpenBrowser as $n, PLAN_MODE_DOCTRINE_NO_PROMPTS as $r, loadState as $t, getSafelist as A, DEFAULT_KEYBINDINGS as An, resolveAgentId as Ar, resolveChipColor as At, supportsOAuth as B, SKILLS_TRIGGER as Bn, isTodoTool as Br, useDiscoveryOptional as Bt, resolveSessionExportTarget as C, mergeApprovalAndBodyOutcomes as Cn, piIdOf as Cr, SETTINGS_CHOICES as Ct, useSafeModeQueue as D, stripEditOutcomesAnnotation as Dn, DEFAULT_PERSIST_EXCLUDE_TOOLS as Dr, useSettings as Dt, useSafeModeActions as E, rewriteMultiEditHeader as En, DEFAULT_AGENT_ID as Er, clampFps as Et, suggestSafelistEntry as F, matchesBinding as Fn, TODO_STATUS_GLYPHS as Fr, CATPPUCCIN_MACCHIATO as Ft, defaultMcpsConfigPaths as G, uniqueFilesFromReferences as Gn, useActiveTodos as Gr, createStateStore as Gt, filterModelCatalog as H, uniqueSkillNamesFromReferences as Hn, pruneTodosByRun as Hr, useConfig as Ht, writeProjects as I, mergeKeybindings as In, TODO_WRITE_COUNTS_METADATA_KEY as Ir, CATPPUCCIN_MOCHA as It, projectUserPaths as J, findActiveTrigger as Jn, DOING_TASKS_DOCTRINE as Jr, isEditErrorResult as Jt, discoverProjectMcps as K, applyInsert as Kn, ACTIONS_WITH_CARE_DOCTRINE as Kr, deriveSessionTitle as Kt, splitPromptSegments as L, parseBindingSpec as Ln, createTodoTools as Lr, createDiscoverySlot as Lt, matchesSafelistEntry as M, KEYBINDING_DEF_BY_ACTION as Mn, TODOREAD_TOOL as Mr, VAPORWAVE_THEME as Mt, projectsFilePath as N, ensureKeybindingsFile as Nn, TODOS_METADATA_KEY as Nr, CATPPUCCIN_FRAPPE as Nt, IMPLICITLY_SAFE_TOOLS as O, summarizeOutcomes as On, PLAN_AGENT as Or, BUILTIN_THEMES as Ot, readProjects as P, keybindingsPath as Pn, TODOWRITE_TOOL as Pr, CATPPUCCIN_LATTE as Pt, McpAuthProvider as Q, buildLinearRamp as Qn, PLAN_MODE_DOCTRINE as Qr, listSessionMeta as Qt, formatPathForCwd as R, readKeybindings as Rn, getArchivedTodosForRun as Rr, DiscoveryProvider as Rt, renderSession as S, maskToOutcomeKinds as Sn, openrouterDescriptor as Sr, DEFAULT_SETTINGS as St, SafeModeProvider as T, resolveApprovalForPayload as Tn, BUILTIN_AGENTS as Tr, SettingsProvider as Tt, indexOfEntry as U, FILES_TRIGGER as Un, selectActiveTodos as Ur, resolveConfig as Ut, buildModelCatalog as V, createSkillsCompletionProvider as Vn, pickActiveRunId as Vr, ConfigProvider as Vt, buildMcpServers as W, createFilesCompletionProvider as Wn, setTodosForRun as Wr, EDIT_TOOL_NAMES as Wt, mcpCredentialsPath as X, useCompletion as Xn, INTERACTION_GUIDANCE as Xr, isVisible as Xt, createFileMcpCredentialStore as Y, mergeReferences as Yn, IDENTITY_PREFIX as Yr, isTurnHighlighted as Yt, patchMcpCredential as Z, blendHsl as Zn, INTERACTION_GUIDANCE_NO_PROMPTS as Zr, lastContextSizeFromTurns as Zt, turnContextSize as _, previewEditPayload as _n, getContextWindow as _r, truncateTrailing as _t, computeTurnAnchors as a, titleFromTurns as an, credentialsPath as ar, InteractionsProvider as at, defaultSkillScanPaths as b, tokenize as bn, modelsForDescriptor as br, listProjectFiles as bt, formatToolCall as c, turnSelectionOwnership as cn, removeProviderCredential as cr, createInteractionTools as ct, useSelectStyle as d, buildContextualDiff as dn, BUILTIN_PROVIDERS as dr, pendingInteractionsFromTurns as dt, SUBAGENT_GUIDANCE as ei, marginTopFor as en, bootProfileEnabled as er, useMcpAuthState as et, useSurfaces as f, buildUnifiedDiff as fn, OUTPUT_RESERVE_TOKENS as fr, serializeInteractionResponse as ft, finalizeStreamingMarkdownForOwner as g, filetypeFromPath as gn, effectiveContextWindow as gr, hintsLength as gt, finalizeStreamingMarkdown as h, extractEditPayload as hn, credKeyOf as hr, clipHintsToWidth as ht, turnAsText as i, envSection as ii, sumRunCosts as in, applyApiKeyEnv as ir, ASK_USER_TOOL as it, isOnSafelist as j, KEYBINDING_DEFS as jn, singleAgentRegistry as jr, resolveTheme as jt, addToSafelist as k, findGitRoot$1 as kn, accentColor as kr, DEFAULT_THEME as kt, ThemeProvider as l, updateToolEventOutcomes as ln, setProviderCredential as lr, isInteractionTool as lt, useTheme as m, computeLineDiff as mn, cerebrasDescriptor as mr, useInteractionsQueue as mt, deleteTurnSafely as n, buildBuildSystem as ni, selectableTurnIds as nn, shouldAutoCompact as nr, reduceMcpAuth as nt, TOOL_DISPLAY as o, toolCallPreview as on, readCredentials as or, PRESENT_PLAN_TOOL as ot, useSyntaxStyles as p, computeInlineDiff as pn, anthropicDescriptor as pr, useInteractionsActions as pt, parseMcpsFile as q, collectReferences as qn, COMMUNICATION_DOCTRINE as qr, eventsFromTurns as qt, truncateTurnsAt as r, buildPlanSystem as ri, stripSpawnTokensLine as rn, detectAuth as rr, splitMarkdownCodeBlocks as rt, displayNameFor as s, toolResultText as sn, readProviderCredential as sr, buildResumedToolResultsTurn as st, countNeighbors as t, TOKEN_DISCIPLINE_DOCTRINE as ti, saveState as tn, bootTick as tr, getMcpAuthStatus as tt, useColors as u, applyEditPayload as un, writeCredentials as ur, makeRequestInteraction as ut, useStreamBuffer as v, splitLines as vn, getModelInfo as vr, cleanTitle as vt, writeSessionExport as w, parseEditOutcomesFromResult as wn, BUILD_AGENT as wr, SETTINGS_TOGGLES as wt, discoverProjectSkills as x, buildEditOutcomesAnnotation as xn, openaiDescriptor as xr, useEnabledToggleSet as xt, buildSkillsConfig as y, summarizeEditPayload as yn, modelSupportsReasoning as yr, generateSessionTitle as yt, runOAuthLogin as z, stripJsonComments as zn, getTodosForRun as zr, useDiscovery as zt };
8250
8349
 
8251
- //# sourceMappingURL=turn-operations-OzKEOXul.js.map
8350
+ //# sourceMappingURL=turn-operations-CtgBlBHn.js.map