@drisp/cli 0.5.18 → 0.5.20

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.
@@ -8,7 +8,7 @@ import {
8
8
  installWorkflowPlugins,
9
9
  resolveWorkflow,
10
10
  writeGlobalConfig
11
- } from "./chunk-ISU54GPM.js";
11
+ } from "./chunk-FLS4B7JS.js";
12
12
 
13
13
  // src/setup/steps/WorkflowInstallWizard.tsx
14
14
  import { useState, useEffect, useCallback, useRef } from "react";
@@ -92,4 +92,4 @@ function WorkflowInstallWizard({ source, onDone }) {
92
92
  export {
93
93
  WorkflowInstallWizard as default
94
94
  };
95
- //# sourceMappingURL=WorkflowInstallWizard-IUMUXPKI.js.map
95
+ //# sourceMappingURL=WorkflowInstallWizard-KP7AEBPQ.js.map
@@ -2440,7 +2440,7 @@ var cachedVersion = null;
2440
2440
  function readVersion() {
2441
2441
  if (cachedVersion !== null) return cachedVersion;
2442
2442
  try {
2443
- const injected = "0.5.18";
2443
+ const injected = "0.5.20";
2444
2444
  if (typeof injected === "string" && injected.length > 0) {
2445
2445
  cachedVersion = injected;
2446
2446
  return cachedVersion;
@@ -34,7 +34,7 @@ import {
34
34
  resolveWorkflow,
35
35
  resolveWorkflowInstall,
36
36
  resolveWorkflowPlugins
37
- } from "./chunk-ISU54GPM.js";
37
+ } from "./chunk-FLS4B7JS.js";
38
38
 
39
39
  // src/infra/daemon/stateDir.ts
40
40
  import fs from "fs";
@@ -11776,18 +11776,6 @@ function resolveVerb(toolName, parsed) {
11776
11776
  }
11777
11777
 
11778
11778
  // src/core/feed/timeline.ts
11779
- function opCategory(op) {
11780
- const dot = op.indexOf(".");
11781
- return dot >= 0 ? op.slice(0, dot) : op;
11782
- }
11783
- function computeDuplicateActors(entries) {
11784
- for (let i = 0; i < entries.length; i++) {
11785
- const prev = i > 0 ? entries[i - 1] : void 0;
11786
- const sameActor = prev !== void 0 && entries[i].actorId === prev.actorId;
11787
- const isBreak = prev !== void 0 && opCategory(entries[i].opTag) !== opCategory(prev.opTag);
11788
- entries[i].duplicateActor = sameActor && !isBreak;
11789
- }
11790
- }
11791
11779
  function stripMarkdownInline(text) {
11792
11780
  return text.replace(/#{1,6}\s+/g, "").replace(/\*\*(.+?)\*\*/g, "$1").replace(/__(.+?)__/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/`(.+?)`/g, "$1").replace(/~~(.+?)~~/g, "$1");
11793
11781
  }
@@ -13393,8 +13381,7 @@ function buildMessageEntry(item, activeRunId, messageCounter) {
13393
13381
  ${details}`,
13394
13382
  error: false,
13395
13383
  expandable: details.length > 120,
13396
- details,
13397
- duplicateActor: false
13384
+ details
13398
13385
  };
13399
13386
  }
13400
13387
  function shouldSkipEvent(event, verbose) {
@@ -13456,8 +13443,7 @@ function buildEventEntry(event, subagentTypes, pairedPost) {
13456
13443
  expandable: isEventExpandable(event),
13457
13444
  details: "",
13458
13445
  feedEvent: event,
13459
- pairedPostEvent: pairedPost,
13460
- duplicateActor: false
13446
+ pairedPostEvent: pairedPost
13461
13447
  };
13462
13448
  }
13463
13449
  function maybeBuildEventEntry(event, subagentTypes, postByToolUseId, verbose) {
@@ -13480,23 +13466,6 @@ function rememberPendingEntry(pendingEntryIndexByToolUseId, entry, index) {
13480
13466
  }
13481
13467
  pendingEntryIndexByToolUseId.set(event.data.tool_use_id, index);
13482
13468
  }
13483
- function recomputeDuplicateActorAt(entries, index) {
13484
- const entry = entries[index];
13485
- if (index === 0) {
13486
- entry.duplicateActor = false;
13487
- return;
13488
- }
13489
- const prev = entries[index - 1];
13490
- const sameActor = entry.actorId === prev.actorId;
13491
- const isBreak = opCategory(entry.opTag) !== opCategory(prev.opTag);
13492
- entry.duplicateActor = sameActor && !isBreak;
13493
- }
13494
- function recomputeDuplicateActorsAround(entries, index) {
13495
- recomputeDuplicateActorAt(entries, index);
13496
- if (index + 1 < entries.length) {
13497
- recomputeDuplicateActorAt(entries, index + 1);
13498
- }
13499
- }
13500
13469
  function sameFeedItemPrefix(previous, next) {
13501
13470
  if (next.length < previous.length) return false;
13502
13471
  for (let i = 0; i < previous.length; i++) {
@@ -13551,7 +13520,6 @@ function buildTimelineCache(feedItems, feedEvents, postByToolUseId, verbose) {
13551
13520
  activeRunId = void 0;
13552
13521
  }
13553
13522
  }
13554
- computeDuplicateActors(entries);
13555
13523
  return {
13556
13524
  feedItems,
13557
13525
  feedEvents,
@@ -13577,10 +13545,7 @@ function appendTimelineCache(previous, feedItems, feedEvents, postByToolUseId) {
13577
13545
  let messageCounter = previous.messageCounter;
13578
13546
  for (const item of feedItems.slice(previous.feedItems.length)) {
13579
13547
  if (item.type === "message") {
13580
- const index = entries.push(
13581
- buildMessageEntry(item.data, activeRunId, messageCounter++)
13582
- ) - 1;
13583
- recomputeDuplicateActorsAround(entries, index);
13548
+ entries.push(buildMessageEntry(item.data, activeRunId, messageCounter++));
13584
13549
  continue;
13585
13550
  }
13586
13551
  const event = item.data;
@@ -13601,7 +13566,6 @@ function appendTimelineCache(previous, feedItems, feedEvents, postByToolUseId) {
13601
13566
  if (event.kind === "tool.post" || event.kind === "tool.failure") {
13602
13567
  pendingEntryIndexByToolUseId.delete(resolvedToolUseId);
13603
13568
  }
13604
- recomputeDuplicateActorsAround(entries, pendingIndex);
13605
13569
  }
13606
13570
  }
13607
13571
  continue;
@@ -13614,7 +13578,6 @@ function appendTimelineCache(previous, feedItems, feedEvents, postByToolUseId) {
13614
13578
  );
13615
13579
  if (entry) {
13616
13580
  const index = entries.push(entry) - 1;
13617
- recomputeDuplicateActorsAround(entries, index);
13618
13581
  rememberPendingEntry(pendingEntryIndexByToolUseId, entry, index);
13619
13582
  }
13620
13583
  if (event.kind === "run.end") {
@@ -18274,4 +18237,4 @@ export {
18274
18237
  startUdsServer,
18275
18238
  sendUdsRequest
18276
18239
  };
18277
- //# sourceMappingURL=chunk-TYTYZDXL.js.map
18240
+ //# sourceMappingURL=chunk-3PA63KQW.js.map
@@ -1687,7 +1687,7 @@ import fs10 from "fs";
1687
1687
  import path8 from "path";
1688
1688
 
1689
1689
  // src/core/workflows/stateMachine.md
1690
- var stateMachine_default = "# Stateless Turn Protocol\n\nYou run in a stateless loop. Each Turn is a fresh process with no memory of prior Turns. **The tracker file is your only continuity** \u2014 read it, work, write it. Assume interruption: the runner may kill a long Turn, your context may collapse under tool output, you may hit token limits mid-task. Anything not in the tracker is gone.\n\n## First action, every Turn\n\n1. Read the tracker at the configured path (default: `.athena/<session_id>/tracker.md`). The runner provides the session ID \u2014 do not invent one.\n2. If the tracker contains `<!-- TRACKER_SKELETON -->` \u2192 this is Turn 1, run [**Orient**](#orient-turn-1).\n3. Otherwise \u2192 this is a continuation, run [**Execute**](#execute-turn-2) from where the tracker says, not from the start of the flow.\n\nReading first prevents two failure modes that waste whole Turns: redoing work already done, or contradicting decisions a prior Turn made.\n\n## Tracker contract\n\nThe tracker must always answer four questions:\n\n1. What are we trying to accomplish?\n2. What has been done?\n3. What's left?\n4. What should the next Turn do first?\n\nA future Turn has no other context. If something isn't here, it doesn't exist. Section headings may vary by workflow, but these four answers must be explicit and easy to find.\n\n### Terminal markers\n\nDefault markers (workflows may override \u2014 use the markers configured for the active workflow):\n\n- `<!-- WORKFLOW_COMPLETE -->` \u2014 all work done and verified\n- `<!-- WORKFLOW_BLOCKED -->` or `<!-- WORKFLOW_BLOCKED: reason -->` \u2014 cannot proceed without external intervention\n\nRules:\n\n- Only the last non-empty line of the tracker is authoritative. Marker-like text in notes, examples, or quoted instructions earlier in the file is ignored.\n- The runner trusts markers unconditionally. A premature marker ends the loop with no automatic recovery \u2014 write one only when its criteria are fully met.\n- Include a concrete reason after `WORKFLOW_BLOCKED:` whenever possible; the bare form is still valid.\n\n## Phases\n\n### Orient (Turn 1)\n\n1. **Replace the skeleton immediately**, before any domain work. Even a three-line tracker (goal + \"orienting\") protects you if the Turn dies during setup.\n2. Run the workflow's orientation steps. These vary by domain \u2014 a test-writing workflow explores the product in a browser; a migration workflow audits the schema. The workflow defines what orientation means.\n3. Refine the tracker into a granular plan. Each task a concrete, verifiable unit of work, including verification steps (running checks, reviewing output) \u2014 not just implementation. Vague tasks (\"write tests\") cannot be meaningfully resumed by a future Turn that has no idea what they mean here.\n4. Record concrete observations \u2014 what you actually saw, not what you assumed. Wrong assumptions burn entire future Turns on rework.\n5. **Single-Turn requests still go through this phase.** If the entire request is satisfied in one Turn, write a minimal tracker (what was asked, what was done, the outcome) and append `<!-- WORKFLOW_COMPLETE -->`. Leaving the skeleton in place causes the runner to classify the Turn as a failure.\n\n### Execute (Turn 2+)\n\n- Work from where the tracker says, in the workflow's prescribed sequence. Not every Turn covers every step.\n- If the workflow defines a skill table, **load the relevant skill before each activity**. Skills carry the implementation detail (scaffolding steps, locator rules, anti-patterns, code templates) that this protocol intentionally doesn't repeat.\n- Delegate heavy exploration or generation to subagents via the Task tool. Pass file paths, conventions, and concrete output expectations; tell them which skill to load. Respect the workflow's **delegation constraints** \u2014 some operations must run in the main agent because their output is proof, or because the main agent needs to interpret results in context.\n- Run quality gates in order. Do not skip \u2014 they exist because skipping cascades into rework. On a failing verdict, address the issues and re-run before proceeding. Respect the workflow's **retry limits**: repeated failure usually signals a deeper issue another retry won't fix.\n\n### End\n\n1. Tracker reflects all progress, discoveries, and blockers.\n2. Tracker says clearly what the next Turn should do first.\n3. If all work is verified: append the completion marker.\n4. If an unrecoverable blocker prevents progress: append the blocked marker, with a reason if you have one.\n\n## When to write the tracker\n\nWrite on **concrete triggers**, not on a vague sense of \"meaningful progress.\" The right cadence sits between every-tool-call (noisy log, wastes tokens) and end-of-Turn (everything lost if you die mid-task).\n\n- **Discrete unit done** \u2014 file written, fix applied, test run, gate passed. Reflect the new reality before starting the next unit.\n- **Insight learned** \u2014 API quirk, config field that turned out to matter, dead end ruled out, decision between two approaches. Insights are tracker-worthy even when no code changed; rediscovering them costs the next Turn a full re-exploration. The tracker is a knowledge ledger, not just a task log.\n- **About to do something risky or long-running** \u2014 subagent dispatch, long build, flaky external call, large refactor. Write _first_, then act. If the operation kills your Turn, only what's on disk survives.\n- **Plan changed** \u2014 task resequenced, new task surfaced, planned task no longer needed. Stale plans poison continuation Turns.\n- **You haven't written in a while** \u2014 if you can't remember the last update, you've gone too long. A short defensive update (\"doing X, last completed Y, next is Z\") beats nothing.\n\nEach update covers: what changed (work or knowledge), what's now next, and any caveat the next Turn needs. Don't transcribe tool calls \u2014 the tracker is a contract with your future self, not a replay log.\n\nThe cost of one extra tracker update is a few tokens. The cost of dying without one is a whole wasted Turn. Bias toward writing.\n\n## Task UI projection\n\nThe tracker is the durable source of truth. Your harness's task tools are a Turn-scoped UI projection of the same plan, shown to the user in their CLI widget. They do not survive process exit.\n\n{{TASK_TOOL_INSTRUCTIONS}}\n\n- **Turn 1, after orientation:** project the tracker's task plan into the task tools.\n- **Turn 2+, after reading the tracker:** recreate the projection from the tracker; do not assume task IDs from prior Turns still exist.\n- **During work:** update both \u2014 the task tools for immediate UI feedback, the tracker for persistence \u2014 in the same working phase.\n\n## Turn bounding\n\nEach fresh Turn starts with a clean context window and a compact tracker \u2014 effectively self-compaction. As you work, context fills with tool outputs and intermediate state. The longer you run, the more attention is spread across tokens that are no longer relevant, degrading precision on the work that matters now.\n\nWork a bounded chunk per Turn. Ending early and letting the next Turn pick up from a clean tracker is almost always better than pushing through with a heavy context. Natural checkpoints:\n\n- After a quality gate\n- After crossing multiple phases (explored \u2192 planned \u2192 wrote specs) \u2014 stop before pushing into the next\n- When your context is visibly heavy with tool output from earlier work\n\n## Quick reference\n\n- [ ] Read the tracker before doing anything else\n- [ ] Replace the skeleton immediately, even for single-Turn requests\n- [ ] Update on concrete triggers \u2014 unit done, insight learned, risky op pending, plan changed\n- [ ] Project the tracker plan into task tools at Turn start; keep both in sync as work lands\n- [ ] Load the workflow's skill before each activity\n- [ ] Run quality gates in order; respect delegation constraints and retry limits\n- [ ] Write the completion marker only when all work is verified\n- [ ] Checkpoint and end before context goes stale\n";
1690
+ var stateMachine_default = "# Stateless Turn Protocol\n\nYou run in a stateless loop. Each Turn is a fresh process with no memory of prior Turns. **The tracker file is your only continuity** \u2014 read it, work, write it. Assume interruption: the runner may kill a long Turn, your context may collapse under tool output, you may hit token limits mid-task. Anything not in the tracker is gone.\n\n## First action, every Turn\n\n1. Read the tracker at the configured path (default: `.athena/<session_id>/tracker.md`). The runner provides the session ID \u2014 do not invent one.\n2. If the tracker contains `<!-- TRACKER_SKELETON -->` \u2192 this is Turn 1, run [**Orient**](#orient-turn-1).\n3. Otherwise \u2192 this is a continuation, run [**Execute**](#execute-turn-2) from where the tracker says, not from the start of the flow.\n\nReading first prevents two failure modes that waste whole Turns: redoing work already done, or contradicting decisions a prior Turn made.\n\n## Tracker contract\n\nThe tracker must always answer four questions:\n\n1. What are we trying to accomplish?\n2. What has been done?\n3. What's left?\n4. What should the next Turn do first?\n\nA future Turn has no other context. If something isn't here, it doesn't exist. Section headings may vary by workflow, but these four answers must be explicit and easy to find.\n\n### Terminal markers\n\nDefault markers (workflows may override \u2014 use the markers configured for the active workflow):\n\n- `<!-- WORKFLOW_COMPLETE -->` \u2014 all work done and verified\n- `<!-- WORKFLOW_BLOCKED -->` or `<!-- WORKFLOW_BLOCKED: reason -->` \u2014 cannot proceed without external intervention\n\nRules:\n\n- Only the last non-empty line of the tracker is authoritative. Marker-like text in notes, examples, or quoted instructions earlier in the file is ignored.\n- The runner trusts markers unconditionally. A premature marker ends the loop with no automatic recovery \u2014 write one only when its criteria are fully met.\n- Include a concrete reason after `WORKFLOW_BLOCKED:` whenever possible; the bare form is still valid.\n\n## Phases\n\n### Orient (Turn 1)\n\n1. **Replace the skeleton immediately**, before any domain work. Even a three-line tracker (goal + \"orienting\") protects you if the Turn dies during setup.\n2. Identify and load the applicable workflow skills before doing domain work. If a workflow, plugin, or local skill table names a relevant skill, read it fully and follow it. Do not assume you already know the workflow's conventions, tool sequence, quality gates, or implementation details.\n3. Use a dedicated git worktree for repository-changing work. If you are not already inside a task-specific worktree, create or enter one before editing files, record its branch/path in the tracker, and continue there. Skip this only when the workflow explicitly forbids it or the task is read-only.\n4. Run the workflow's orientation steps exactly as written. These vary by domain \u2014 a test-writing workflow explores the product in a browser; a migration workflow audits the schema. The workflow defines what orientation means. Do not skip, reorder, reinterpret, or replace workflow steps with a generic approach unless the workflow explicitly allows it or the tracker records a concrete blocker that makes the written step impossible.\n5. Refine the tracker into a granular plan. Each task a concrete, verifiable unit of work, including verification steps (running checks, reviewing output) \u2014 not just implementation. Vague tasks (\"write tests\") cannot be meaningfully resumed by a future Turn that has no idea what they mean here.\n6. Record concrete observations \u2014 what you actually saw, not what you assumed. Wrong assumptions burn entire future Turns on rework.\n7. **Single-Turn requests still go through this phase.** If the entire request is satisfied in one Turn, write a minimal tracker (what was asked, what was done, the outcome) and append `<!-- WORKFLOW_COMPLETE -->`. Leaving the skeleton in place causes the runner to classify the Turn as a failure.\n\n### Execute (Turn 2+)\n\n- Work from where the tracker says, in the workflow's prescribed sequence. Not every Turn covers every step.\n- Be strict with workflow steps. Before starting each unit, identify the next required workflow step from the workflow document and tracker, follow it as written, and record completion or blockers against that step. Do not substitute your own process, collapse separate gates into one, or advance past an unchecked step.\n- Be strict with skills. Before each new activity, check the workflow, plugin metadata, local skill table, and tracker for relevant skills. Load the appropriate skill first, read it completely, and follow its instructions. If no skill applies, record that explicitly in the tracker before proceeding. Skills carry the implementation detail (scaffolding steps, locator rules, anti-patterns, code templates) that this protocol intentionally doesn't repeat.\n- Keep repository work inside the recorded git worktree. If a continuation Turn starts outside the recorded worktree, enter it before editing. If no worktree is recorded and edits are still required, create or enter one before proceeding.\n- Delegate heavy exploration or generation to subagents via the Task tool. Pass file paths, conventions, and concrete output expectations; tell them which skill to load. Respect the workflow's **delegation constraints** \u2014 some operations must run in the main agent because their output is proof, or because the main agent needs to interpret results in context.\n- Run quality gates in order. Do not skip \u2014 they exist because skipping cascades into rework. On a failing verdict, address the issues and re-run before proceeding. Respect the workflow's **retry limits**: repeated failure usually signals a deeper issue another retry won't fix.\n\n### End\n\n1. Tracker reflects all progress, discoveries, and blockers.\n2. Tracker says clearly what the next Turn should do first.\n3. If all work is verified: append the completion marker.\n4. If an unrecoverable blocker prevents progress: append the blocked marker, with a reason if you have one.\n\n## When to write the tracker\n\nWrite on **concrete triggers**, not on a vague sense of \"meaningful progress.\" The right cadence sits between every-tool-call (noisy log, wastes tokens) and end-of-Turn (everything lost if you die mid-task).\n\n- **Discrete unit done** \u2014 file written, fix applied, test run, gate passed. Reflect the new reality before starting the next unit.\n- **Insight learned** \u2014 API quirk, config field that turned out to matter, dead end ruled out, decision between two approaches. Insights are tracker-worthy even when no code changed; rediscovering them costs the next Turn a full re-exploration. The tracker is a knowledge ledger, not just a task log.\n- **About to do something risky or long-running** \u2014 subagent dispatch, long build, flaky external call, large refactor. Write _first_, then act. If the operation kills your Turn, only what's on disk survives.\n- **Plan changed** \u2014 task resequenced, new task surfaced, planned task no longer needed. Stale plans poison continuation Turns.\n- **You haven't written in a while** \u2014 if you can't remember the last update, you've gone too long. A short defensive update (\"doing X, last completed Y, next is Z\") beats nothing.\n\nEach update covers: what changed (work or knowledge), what's now next, and any caveat the next Turn needs. Don't transcribe tool calls \u2014 the tracker is a contract with your future self, not a replay log.\n\nThe cost of one extra tracker update is a few tokens. The cost of dying without one is a whole wasted Turn. Bias toward writing.\n\n## Task UI projection\n\nThe tracker is the durable source of truth. Your harness's task tools are a Turn-scoped UI projection of the same plan, shown to the user in their CLI widget. They do not survive process exit.\n\n{{TASK_TOOL_INSTRUCTIONS}}\n\n- **Turn 1, after orientation:** project the tracker's task plan into the task tools.\n- **Turn 2+, after reading the tracker:** recreate the projection from the tracker; do not assume task IDs from prior Turns still exist.\n- **During work:** update both \u2014 the task tools for immediate UI feedback, the tracker for persistence \u2014 in the same working phase.\n\n## Turn bounding\n\nEach fresh Turn starts with a clean context window and a compact tracker \u2014 effectively self-compaction. As you work, context fills with tool outputs and intermediate state. The longer you run, the more attention is spread across tokens that are no longer relevant, degrading precision on the work that matters now.\n\nWork a bounded chunk per Turn. Ending early and letting the next Turn pick up from a clean tracker is almost always better than pushing through with a heavy context. Natural checkpoints:\n\n- After a quality gate\n- After crossing multiple phases (explored \u2192 planned \u2192 wrote specs) \u2014 stop before pushing into the next\n- When your context is visibly heavy with tool output from earlier work\n\n## Quick reference\n\n- [ ] Read the tracker before doing anything else\n- [ ] Replace the skeleton immediately, even for single-Turn requests\n- [ ] Update on concrete triggers \u2014 unit done, insight learned, risky op pending, plan changed\n- [ ] Project the tracker plan into task tools at Turn start; keep both in sync as work lands\n- [ ] Follow the workflow steps as written; do not skip, reorder, or substitute your own process\n- [ ] Load the appropriate skill before each activity; do not rely on assumed knowledge\n- [ ] Use and record a dedicated git worktree for repository-changing work\n- [ ] Run quality gates in order; respect delegation constraints and retry limits\n- [ ] Write the completion marker only when all work is verified\n- [ ] Checkpoint and end before context goes stale\n";
1691
1691
 
1692
1692
  // src/core/workflows/stateMachine.ts
1693
1693
  function buildTaskToolInstructions(harness) {
@@ -2237,4 +2237,4 @@ export {
2237
2237
  compileWorkflowPlan,
2238
2238
  collectMcpServersWithOptions
2239
2239
  };
2240
- //# sourceMappingURL=chunk-ISU54GPM.js.map
2240
+ //# sourceMappingURL=chunk-FLS4B7JS.js.map
package/dist/cli.js CHANGED
@@ -97,7 +97,7 @@ import {
97
97
  writeAttachmentMirror,
98
98
  writeGatewayClientConfig,
99
99
  wsClientOptionsForEndpoint
100
- } from "./chunk-TYTYZDXL.js";
100
+ } from "./chunk-3PA63KQW.js";
101
101
  import {
102
102
  generateId as generateId2
103
103
  } from "./chunk-BTKQ67RE.js";
@@ -157,7 +157,7 @@ import {
157
157
  useWorkflowSessionController,
158
158
  writeGlobalConfig,
159
159
  writeProjectConfig
160
- } from "./chunk-ISU54GPM.js";
160
+ } from "./chunk-FLS4B7JS.js";
161
161
 
162
162
  // src/app/entry/cli.tsx
163
163
  import { render } from "ink";
@@ -4339,7 +4339,7 @@ import { useRef as useRef10 } from "react";
4339
4339
  var HEADER_ROWS = 1;
4340
4340
  var FRAME_BORDER_ROWS = 4;
4341
4341
  var RUN_OVERLAY_MAX_ROWS = 6;
4342
- var MESSAGE_PANEL_RATIO = 0.5;
4342
+ var MESSAGE_PANEL_RATIO = 0.65;
4343
4343
  function useLayout({
4344
4344
  terminalRows,
4345
4345
  terminalWidth,
@@ -6195,14 +6195,6 @@ function formatTime(ts, contentWidth2, theme) {
6195
6195
  const clock = formatClock(ts);
6196
6196
  return source_default.hex(theme.textMuted)(fit(clock, contentWidth2));
6197
6197
  }
6198
- function formatActor(actor, duplicate, contentWidth2, theme, _actorId) {
6199
- if (contentWidth2 <= 0) return "";
6200
- if (duplicate) {
6201
- const text = fit("\xB7", contentWidth2);
6202
- return source_default.hex(theme.textMuted)(text);
6203
- }
6204
- return source_default.hex(theme.textMuted)(fit(actor, contentWidth2));
6205
- }
6206
6198
  function formatTool(toolColumn, contentWidth2, theme, options) {
6207
6199
  if (contentWidth2 <= 0) return "";
6208
6200
  if (!toolColumn) return fit("", contentWidth2);
@@ -6220,14 +6212,6 @@ function formatTool(toolColumn, contentWidth2, theme, options) {
6220
6212
  const pill = source_default.bgHex(palette.bg).hex(palette.fg)(` ${label} `);
6221
6213
  return `${pill}${trailingPad}`;
6222
6214
  }
6223
- function formatResult(outcome, outcomeZero, isError, contentWidth2, theme) {
6224
- if (contentWidth2 <= 0) return "";
6225
- if (!outcome) return fit("", contentWidth2);
6226
- const fitted = fit(outcome.trim(), contentWidth2);
6227
- if (isError) return source_default.hex(theme.status.error)(fitted);
6228
- if (outcomeZero) return source_default.hex(theme.status.warning)(fitted);
6229
- return source_default.hex(theme.textMuted)(fitted);
6230
- }
6231
6215
  function buildDetailsPrefix(mode, toolColumn, actorStr, theme) {
6232
6216
  if (mode === "full") return { text: "", length: 0 };
6233
6217
  let prefix = "";
@@ -6240,19 +6224,21 @@ function buildDetailsPrefix(mode, toolColumn, actorStr, theme) {
6240
6224
  if (!prefix) return { text: "", length: 0 };
6241
6225
  return { text: prefix, length: stripAnsi(prefix).length };
6242
6226
  }
6243
- function renderSegments(segments, summary, width, theme, opTag) {
6227
+ function renderSegments(segments, summary, width, theme, opTag, error = false) {
6244
6228
  if (width <= 0) return "";
6245
6229
  const normalizePathPrefix = (text) => text.replace(/(^|\s)(?:\u2026\/|\.{3}\/)/g, "$1/");
6246
6230
  if (segments.length === 0) {
6247
- return fit(normalizePathPrefix(summary), width);
6231
+ const fitted = fit(normalizePathPrefix(summary), width);
6232
+ return error ? source_default.hex(theme.status.error)(fitted) : fitted;
6248
6233
  }
6249
6234
  const isAgentMsg = opTag === "agent.msg";
6250
6235
  const isSubReturn = opTag === "sub.stop";
6251
6236
  const isLifecycle = isLifecycleOp(opTag);
6252
6237
  const baseColor = isAgentMsg ? theme.status.info : isLifecycle || isSubReturn ? theme.textMuted : theme.text;
6253
- const shouldDim = isAgentMsg || isLifecycle;
6238
+ const shouldDim = !error && (isAgentMsg || isLifecycle);
6254
6239
  const hasFilename = segments.some((seg) => seg.role === "filename");
6255
6240
  const roleColor = (role) => {
6241
+ if (error) return theme.status.error;
6256
6242
  switch (role) {
6257
6243
  case "verb":
6258
6244
  return baseColor;
@@ -6282,8 +6268,9 @@ function renderSegments(segments, summary, width, theme, opTag) {
6282
6268
  }
6283
6269
  return result;
6284
6270
  }
6285
- function renderOutcome(outcome, outcomeZero, theme) {
6271
+ function renderOutcome(outcome, outcomeZero, theme, error = false) {
6286
6272
  if (!outcome) return void 0;
6273
+ if (error) return source_default.hex(theme.status.error)(outcome);
6287
6274
  if (outcomeZero) return source_default.hex(theme.status.warning)(outcome);
6288
6275
  return source_default.hex(theme.textMuted)(outcome);
6289
6276
  }
@@ -6298,14 +6285,15 @@ function formatDetails(opts) {
6298
6285
  actorStr,
6299
6286
  contentWidth: contentWidth2,
6300
6287
  theme,
6301
- opTag
6288
+ opTag,
6289
+ error = false
6302
6290
  } = opts;
6303
6291
  const prefix = buildDetailsPrefix(mode, toolColumn, actorStr, theme);
6304
6292
  const innerWidth = Math.max(0, contentWidth2 - prefix.length);
6305
- const outcomeStr = renderOutcome(outcome, outcomeZero, theme);
6293
+ const outcomeStr = renderOutcome(outcome, outcomeZero, theme, error);
6306
6294
  const outcomeClean = outcomeStr ? stripAnsi(outcomeStr) : void 0;
6307
6295
  if (!outcomeStr || innerWidth <= 0) {
6308
- return prefix.text + renderSegments(segments, summary, innerWidth, theme, opTag);
6296
+ return prefix.text + renderSegments(segments, summary, innerWidth, theme, opTag, error);
6309
6297
  }
6310
6298
  const outcomeLen = outcomeClean.length;
6311
6299
  const targetBudget = innerWidth - outcomeLen - 2;
@@ -6315,7 +6303,8 @@ function formatDetails(opts) {
6315
6303
  summary,
6316
6304
  Math.max(0, innerWidth - outcomeLen - 2),
6317
6305
  theme,
6318
- opTag
6306
+ opTag,
6307
+ error
6319
6308
  );
6320
6309
  const segClean2 = stripAnsi(segStr2).trimEnd();
6321
6310
  const padNeeded2 = innerWidth - segClean2.length - outcomeLen;
@@ -6324,9 +6313,16 @@ function formatDetails(opts) {
6324
6313
  segClean2 + pad2 + stripAnsi(outcomeStr),
6325
6314
  innerWidth
6326
6315
  );
6327
- return prefix.text + truncated;
6316
+ return prefix.text + (error ? source_default.hex(theme.status.error)(truncated) : truncated);
6328
6317
  }
6329
- const segStr = renderSegments(segments, summary, targetBudget, theme, opTag);
6318
+ const segStr = renderSegments(
6319
+ segments,
6320
+ summary,
6321
+ targetBudget,
6322
+ theme,
6323
+ opTag,
6324
+ error
6325
+ );
6330
6326
  const segClean = stripAnsi(segStr);
6331
6327
  const padNeeded = innerWidth - segClean.length - outcomeLen;
6332
6328
  const pad = padNeeded > 0 ? " ".repeat(padNeeded) : " ";
@@ -6431,7 +6427,6 @@ function buildLineCacheKey({
6431
6427
  focused,
6432
6428
  expanded,
6433
6429
  matched,
6434
- isDuplicateActor,
6435
6430
  ascii,
6436
6431
  theme,
6437
6432
  innerWidth
@@ -6440,13 +6435,10 @@ function buildLineCacheKey({
6440
6435
  innerWidth,
6441
6436
  cols.toolW,
6442
6437
  cols.detailsW,
6443
- cols.resultW,
6444
6438
  cols.gapW,
6445
- cols.detailsResultGapW,
6446
6439
  focused ? 1 : 0,
6447
6440
  expanded ? 1 : 0,
6448
6441
  matched ? 1 : 0,
6449
- isDuplicateActor ? 1 : 0,
6450
6442
  ascii ? 1 : 0,
6451
6443
  entry.expandable ? 1 : 0,
6452
6444
  entry.error ? 1 : 0,
@@ -6463,12 +6455,12 @@ function lineParts({
6463
6455
  focused,
6464
6456
  expanded: _expanded,
6465
6457
  matched,
6466
- isDuplicateActor,
6467
6458
  ascii,
6468
6459
  theme
6469
6460
  }) {
6470
6461
  const isUserBorder = entry.opTag === "prompt" || entry.opTag === "msg.user";
6471
- const rowTextOverrideColor = focused ? theme.text : void 0;
6462
+ const errorActive = entry.error && !focused;
6463
+ const rowTextOverrideColor = focused ? theme.text : entry.error ? theme.status.error : void 0;
6472
6464
  const isToolRow = entry.opTag.startsWith("tool.") || entry.opTag === "perm.req";
6473
6465
  const isSubagentRow = entry.opTag === "sub.start" || entry.opTag === "sub.stop";
6474
6466
  const syntheticLabel = entry.toolColumn.length === 0 ? defaultEventPillLabel(entry.opTag) : void 0;
@@ -6486,18 +6478,20 @@ function lineParts({
6486
6478
  }
6487
6479
  return resolveToolPillCategoryForLabel(toolText);
6488
6480
  })();
6489
- const gutter = formatGutter({
6490
- focused,
6491
- matched,
6492
- isUserBorder,
6493
- ascii,
6494
- theme
6495
- });
6496
- const time = cell(formatTime(entry.ts, 5, theme), rowTextOverrideColor);
6497
- const actor = cell(
6498
- formatActor(entry.actor, isDuplicateActor, 10, theme, entry.actorId),
6499
- rowTextOverrideColor
6481
+ const gutter = cell(
6482
+ formatGutter({
6483
+ focused,
6484
+ matched,
6485
+ isUserBorder,
6486
+ ascii,
6487
+ theme
6488
+ }),
6489
+ // Tint the gutter red on an errored row, but never stomp a meaningful
6490
+ // glyph: focus keeps its accent border, and a search-match / user-border
6491
+ // gutter keeps its own signal color.
6492
+ errorActive && !matched && !isUserBorder ? theme.status.error : void 0
6500
6493
  );
6494
+ const time = cell(formatTime(entry.ts, 5, theme), rowTextOverrideColor);
6501
6495
  const tool = formatTool(toolText, cols.toolW, theme, {
6502
6496
  pill: isToolRow || isSubagentRow || hasSyntheticPill,
6503
6497
  category: toolCategory
@@ -6506,25 +6500,19 @@ function lineParts({
6506
6500
  const detail = formatDetails({
6507
6501
  segments: detailSummaryInfo.segments,
6508
6502
  summary: detailSummaryInfo.summary,
6503
+ outcome: entry.summaryOutcome,
6504
+ outcomeZero: entry.summaryOutcomeZero,
6505
+ error: errorActive,
6509
6506
  mode: "full",
6510
6507
  contentWidth: cols.detailsW,
6511
6508
  theme,
6512
6509
  opTag: entry.opTag
6513
6510
  });
6514
- const result = formatResult(
6515
- entry.summaryOutcome,
6516
- entry.summaryOutcomeZero,
6517
- entry.error,
6518
- cols.resultW,
6519
- theme
6520
- );
6521
6511
  return {
6522
6512
  gutter,
6523
6513
  time,
6524
- actor,
6525
6514
  tool,
6526
- detail,
6527
- result
6515
+ detail
6528
6516
  };
6529
6517
  }
6530
6518
  function formatFeedRowLine({
@@ -6539,12 +6527,9 @@ function formatFeedRowLine({
6539
6527
  if (cached !== void 0) return cached;
6540
6528
  const parts = lineParts(props);
6541
6529
  const {
6542
- cols: { gapW, detailsResultGapW, resultW }
6530
+ cols: { gapW }
6543
6531
  } = props;
6544
- let line = parts.gutter + parts.time + spaces(gapW) + parts.actor + spaces(gapW) + parts.tool + spaces(gapW) + parts.detail;
6545
- if (resultW > 0) {
6546
- line += spaces(detailsResultGapW) + parts.result;
6547
- }
6532
+ const line = parts.gutter + parts.time + spaces(gapW) + parts.tool + spaces(gapW) + parts.detail;
6548
6533
  const formatted = fitAnsi(line, innerWidth);
6549
6534
  const focusedFormatted = props.focused ? fitAnsi(
6550
6535
  source_default.bgHex(props.theme.feed.focusBackground)(formatted),
@@ -6568,7 +6553,6 @@ function FeedRowImpl({
6568
6553
  focused,
6569
6554
  expanded,
6570
6555
  matched,
6571
- isDuplicateActor,
6572
6556
  ascii,
6573
6557
  theme
6574
6558
  }) {
@@ -6578,7 +6562,6 @@ function FeedRowImpl({
6578
6562
  focused,
6579
6563
  expanded,
6580
6564
  matched,
6581
- isDuplicateActor,
6582
6565
  ascii,
6583
6566
  theme
6584
6567
  });
@@ -6586,15 +6569,9 @@ function FeedRowImpl({
6586
6569
  /* @__PURE__ */ jsx11(Box9, { width: 1, flexShrink: 0, children: /* @__PURE__ */ jsx11(Text12, { wrap: "truncate-end", children: parts.gutter }) }),
6587
6570
  /* @__PURE__ */ jsx11(Box9, { width: 5, flexShrink: 0, children: /* @__PURE__ */ jsx11(Text12, { wrap: "truncate-end", children: parts.time }) }),
6588
6571
  /* @__PURE__ */ jsx11(Box9, { width: cols.gapW, flexShrink: 0 }),
6589
- /* @__PURE__ */ jsx11(Box9, { width: 10, flexShrink: 0, children: /* @__PURE__ */ jsx11(Text12, { wrap: "truncate-end", children: parts.actor }) }),
6590
- /* @__PURE__ */ jsx11(Box9, { width: cols.gapW, flexShrink: 0 }),
6591
6572
  /* @__PURE__ */ jsx11(Box9, { width: cols.toolW, flexShrink: 0, children: /* @__PURE__ */ jsx11(Text12, { wrap: "truncate-end", children: parts.tool }) }),
6592
6573
  /* @__PURE__ */ jsx11(Box9, { width: cols.gapW, flexShrink: 0 }),
6593
6574
  /* @__PURE__ */ jsx11(Box9, { width: cols.detailsW, flexShrink: 0, children: /* @__PURE__ */ jsx11(Text12, { wrap: "truncate-end", children: parts.detail }) }),
6594
- cols.resultW > 0 && /* @__PURE__ */ jsxs10(Fragment4, { children: [
6595
- /* @__PURE__ */ jsx11(Box9, { width: cols.detailsResultGapW, flexShrink: 0 }),
6596
- /* @__PURE__ */ jsx11(Box9, { width: cols.resultW, flexShrink: 0, children: /* @__PURE__ */ jsx11(Text12, { wrap: "truncate-end", children: parts.result }) })
6597
- ] }),
6598
6575
  /* @__PURE__ */ jsx11(Box9, { flexGrow: 1, flexShrink: 1 })
6599
6576
  ] });
6600
6577
  }
@@ -6610,15 +6587,9 @@ function formatFeedHeaderLine(cols, theme, innerWidth) {
6610
6587
  let line = " ";
6611
6588
  line += style(fit("TIME", 5));
6612
6589
  line += " ".repeat(cols.gapW);
6613
- line += style(fit("ACTOR", 10));
6614
- line += " ".repeat(cols.gapW);
6615
6590
  line += style(fit("ACTION", cols.toolW));
6616
6591
  line += " ".repeat(cols.gapW);
6617
6592
  line += style(fit("DETAILS", cols.detailsW));
6618
- if (cols.resultW > 0) {
6619
- line += " ".repeat(cols.detailsResultGapW);
6620
- line += style(fit("RESULT", cols.resultW));
6621
- }
6622
6593
  return fitAnsi(line, innerWidth);
6623
6594
  }
6624
6595
  function FeedHeaderImpl({ cols, theme }) {
@@ -6628,15 +6599,9 @@ function FeedHeaderImpl({ cols, theme }) {
6628
6599
  /* @__PURE__ */ jsx12(Box10, { width: 1, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text13, { children: " " }) }),
6629
6600
  /* @__PURE__ */ jsx12(Box10, { width: 5, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text13, { wrap: "truncate-end", children: style(fit("TIME", 5)) }) }),
6630
6601
  /* @__PURE__ */ jsx12(Box10, { width: cols.gapW, flexShrink: 0 }),
6631
- /* @__PURE__ */ jsx12(Box10, { width: 10, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text13, { wrap: "truncate-end", children: style(fit("ACTOR", 10)) }) }),
6632
- /* @__PURE__ */ jsx12(Box10, { width: cols.gapW, flexShrink: 0 }),
6633
6602
  /* @__PURE__ */ jsx12(Box10, { width: cols.toolW, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text13, { wrap: "truncate-end", children: style(fit("ACTION", cols.toolW)) }) }),
6634
6603
  /* @__PURE__ */ jsx12(Box10, { width: cols.gapW, flexShrink: 0 }),
6635
6604
  /* @__PURE__ */ jsx12(Box10, { width: cols.detailsW, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text13, { wrap: "truncate-end", children: style(fit("DETAILS", cols.detailsW)) }) }),
6636
- cols.resultW > 0 && /* @__PURE__ */ jsxs11(Fragment5, { children: [
6637
- /* @__PURE__ */ jsx12(Box10, { width: cols.detailsResultGapW, flexShrink: 0 }),
6638
- /* @__PURE__ */ jsx12(Box10, { width: cols.resultW, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text13, { wrap: "truncate-end", children: style(fit("RESULT", cols.resultW)) }) })
6639
- ] }),
6640
6605
  /* @__PURE__ */ jsx12(Box10, { flexGrow: 1, flexShrink: 1 })
6641
6606
  ] });
6642
6607
  }
@@ -6754,7 +6719,6 @@ function formatRow(entry, idx, feedCursor, focusMode, matched, ascii, theme, inn
6754
6719
  focused: isFocused,
6755
6720
  expanded: false,
6756
6721
  matched,
6757
- isDuplicateActor: entry.duplicateActor,
6758
6722
  ascii,
6759
6723
  theme,
6760
6724
  innerWidth
@@ -7198,7 +7162,6 @@ function FeedGridImpl({
7198
7162
  entry.summary,
7199
7163
  entry.summaryOutcome ?? "",
7200
7164
  entry.error ? "error" : "ok",
7201
- entry.duplicateActor ? "dup" : "solo",
7202
7165
  focusMode === "feed" && idx === feedCursor ? "focused" : "plain",
7203
7166
  searchMatchSet.has(idx) ? "matched" : "unmatched"
7204
7167
  ].join("|")
@@ -7474,50 +7437,36 @@ var MessagePanel = React8.memo(MessagePanelImpl);
7474
7437
  // src/ui/hooks/useFeedColumns.ts
7475
7438
  import { useMemo as useMemo12, useRef as useRef12 } from "react";
7476
7439
  function areFeedColumnsEqual(left, right) {
7477
- return left.toolW === right.toolW && left.detailsW === right.detailsW && left.resultW === right.resultW && left.gapW === right.gapW && left.detailsResultGapW === right.detailsResultGapW;
7440
+ return left.toolW === right.toolW && left.detailsW === right.detailsW && left.gapW === right.gapW;
7478
7441
  }
7479
7442
  var GUTTER_W = 1;
7480
7443
  var TIME_W = 5;
7481
- var ACTOR_W = 10;
7482
- var SUFFIX_W = 0;
7483
- var BASE_FIXED = GUTTER_W + TIME_W + ACTOR_W + SUFFIX_W;
7484
- var GAP_COUNT = 3;
7444
+ var BASE_FIXED = GUTTER_W + TIME_W;
7445
+ var GAP_COUNT = 2;
7485
7446
  function computeFeedColumns(entries, innerWidth) {
7486
7447
  let maxToolLen = 0;
7487
- let maxResultLen = 0;
7488
7448
  for (const e of entries) {
7489
7449
  const len = e.toolColumn.length;
7490
7450
  if (len > maxToolLen) maxToolLen = len;
7491
- const outcomeLen = (e.summaryOutcome ?? "").length;
7492
- if (outcomeLen > maxResultLen) maxResultLen = outcomeLen;
7493
7451
  }
7494
7452
  const gapW = innerWidth >= 120 ? 2 : 1;
7495
7453
  const toolW = Math.min(24, Math.max(12, maxToolLen + 4));
7496
- const resultMaxW = innerWidth >= 240 ? 48 : innerWidth >= 220 ? 42 : innerWidth >= 180 ? 34 : innerWidth >= 140 ? 26 : 18;
7497
- const resultW = maxResultLen > 0 ? Math.min(resultMaxW, Math.max(8, maxResultLen)) : 0;
7498
- const detailsResultGapW = resultW > 0 ? Math.max(2, gapW) : 0;
7499
- const fixedWithoutDetails = BASE_FIXED + toolW + (resultW > 0 ? resultW : 0) + GAP_COUNT * gapW + detailsResultGapW;
7454
+ const fixedWithoutDetails = BASE_FIXED + toolW + GAP_COUNT * gapW;
7500
7455
  const availableForDetails = Math.max(0, innerWidth - fixedWithoutDetails);
7501
7456
  return {
7502
7457
  toolW,
7503
7458
  detailsW: availableForDetails,
7504
- resultW,
7505
- gapW,
7506
- detailsResultGapW
7459
+ gapW
7507
7460
  };
7508
7461
  }
7509
7462
  function stabilizeFeedColumns(previous, next, innerWidth) {
7510
7463
  const gapW = Math.max(previous.gapW, next.gapW);
7511
7464
  const toolW = Math.max(previous.toolW, next.toolW);
7512
- const resultW = Math.max(previous.resultW, next.resultW);
7513
- const detailsResultGapW = resultW > 0 ? Math.max(previous.detailsResultGapW, next.detailsResultGapW, 2) : 0;
7514
- const fixedWithoutDetails = BASE_FIXED + toolW + (resultW > 0 ? resultW : 0) + GAP_COUNT * gapW + detailsResultGapW;
7465
+ const fixedWithoutDetails = BASE_FIXED + toolW + GAP_COUNT * gapW;
7515
7466
  const stabilized = {
7516
7467
  toolW,
7517
7468
  detailsW: Math.max(0, innerWidth - fixedWithoutDetails),
7518
- resultW,
7519
- gapW,
7520
- detailsResultGapW
7469
+ gapW
7521
7470
  };
7522
7471
  return areFeedColumnsEqual(previous, stabilized) ? previous : stabilized;
7523
7472
  }
@@ -12655,7 +12604,7 @@ var cachedVersion = null;
12655
12604
  function readPackageVersion() {
12656
12605
  if (cachedVersion !== null) return cachedVersion;
12657
12606
  try {
12658
- const injected = "0.5.18";
12607
+ const injected = "0.5.20";
12659
12608
  if (typeof injected === "string" && injected.length > 0) {
12660
12609
  cachedVersion = injected;
12661
12610
  return cachedVersion;
@@ -15402,7 +15351,7 @@ Available commands: ${[...KNOWN_COMMANDS].join(", ")}`
15402
15351
  await exitWith(1);
15403
15352
  return;
15404
15353
  }
15405
- const { default: WorkflowInstallWizard } = await import("./WorkflowInstallWizard-IUMUXPKI.js");
15354
+ const { default: WorkflowInstallWizard } = await import("./WorkflowInstallWizard-KP7AEBPQ.js");
15406
15355
  const { waitUntilExit } = render(
15407
15356
  /* @__PURE__ */ jsx25(
15408
15357
  WorkflowInstallWizard,
@@ -3,13 +3,13 @@ import {
3
3
  ensureDaemonStateDir,
4
4
  runDashboardRuntimeDaemon,
5
5
  startUdsServer
6
- } from "./chunk-TYTYZDXL.js";
6
+ } from "./chunk-3PA63KQW.js";
7
7
  import "./chunk-BTKQ67RE.js";
8
8
  import {
9
9
  readDashboardClientConfig,
10
10
  refreshDashboardAccessToken
11
11
  } from "./chunk-BTY7MYYT.js";
12
- import "./chunk-ISU54GPM.js";
12
+ import "./chunk-FLS4B7JS.js";
13
13
 
14
14
  // src/infra/daemon/logFile.ts
15
15
  import fs from "fs";
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "hooks",
18
18
  "dashboard"
19
19
  ],
20
- "version": "0.5.18",
20
+ "version": "0.5.20",
21
21
  "license": "MIT",
22
22
  "bin": {
23
23
  "athena": "dist/cli.js",