@drisp/cli 0.5.23 → 0.5.26

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/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import "./chunk-HXBCZAP7.js";
3
3
  import {
4
4
  rotateGatewayToken
5
- } from "./chunk-MRAM6EYI.js";
5
+ } from "./chunk-4NX4WFPB.js";
6
6
  import {
7
7
  CREDENTIAL_SOURCES_TRIED,
8
8
  EXEC_EXIT_CODE,
@@ -10,6 +10,7 @@ import {
10
10
  GatewayUnreachableError,
11
11
  IndexedTimeline,
12
12
  PORTABLE_PROVIDER_ENV_VARS,
13
+ attachRuntimeEventLoop,
13
14
  bootstrapRuntimeConfig,
14
15
  buildApiKeyHelperSettings,
15
16
  buildPostByToolUseId,
@@ -26,7 +27,6 @@ import {
26
27
  createRelayQuestionCallback,
27
28
  createRuntime,
28
29
  createSessionStore,
29
- createWsClientTransport,
30
30
  credentialHelperKey,
31
31
  cursorToVisualPosition,
32
32
  daemonStatePaths,
@@ -48,8 +48,6 @@ import {
48
48
  getMostRecentAthenaSession,
49
49
  getSessionMeta,
50
50
  hintGlyphs,
51
- ingestRuntimeDecision,
52
- ingestRuntimeEvent,
53
51
  isBashToolResponse,
54
52
  isCommandPrefix,
55
53
  isScopedPermissionsRequest,
@@ -62,6 +60,7 @@ import {
62
60
  makeSkippedProbe,
63
61
  mergeFeedItems,
64
62
  messageGlyphs,
63
+ parseFrontmatter,
65
64
  parseToolName,
66
65
  probeSkipReason,
67
66
  processRegistry,
@@ -75,6 +74,7 @@ import {
75
74
  renderInputLines,
76
75
  resolveClaudeBinary,
77
76
  resolveClaudeSettingsSurfacePaths,
77
+ resolveEffectiveCapabilities,
78
78
  resolveHarnessAdapter,
79
79
  resolveHookForwarderCommand,
80
80
  resolveRuntimeAuthOverlay,
@@ -87,6 +87,7 @@ import {
87
87
  sessionsDir,
88
88
  sliceAnsi,
89
89
  spaces,
90
+ startDashboardDecisionDrain,
90
91
  startSessionBridge,
91
92
  stringWidth,
92
93
  stripAnsi,
@@ -95,13 +96,13 @@ import {
95
96
  visualPositionToOffset,
96
97
  wrapText,
97
98
  writeAttachmentMirror,
98
- writeGatewayClientConfig,
99
- wsClientOptionsForEndpoint
100
- } from "./chunk-EC67PEFT.js";
99
+ writeGatewayClientConfig
100
+ } from "./chunk-YZ7RCBKO.js";
101
101
  import {
102
102
  generateId as generateId2
103
- } from "./chunk-BTKQ67RE.js";
103
+ } from "./chunk-QYB6N2OT.js";
104
104
  import {
105
+ createWsClientTransport,
105
106
  dashboardClientConfigPath,
106
107
  disableTelemetry,
107
108
  initTelemetry,
@@ -120,8 +121,9 @@ import {
120
121
  trackSetupCompleted,
121
122
  trackTelemetryOptedOut,
122
123
  writeDashboardClientConfig,
123
- writeGatewayTrace
124
- } from "./chunk-BTY7MYYT.js";
124
+ writeGatewayTrace,
125
+ wsClientOptionsForEndpoint
126
+ } from "./chunk-3U37HT4T.js";
125
127
  import {
126
128
  McpOptionsStep,
127
129
  StepSelector,
@@ -158,20 +160,20 @@ import {
158
160
  useWorkflowSessionController,
159
161
  writeGlobalConfig,
160
162
  writeProjectConfig
161
- } from "./chunk-JHSADKDJ.js";
163
+ } from "./chunk-73V7GXV6.js";
162
164
 
163
165
  // src/app/entry/cli.tsx
164
166
  import { render } from "ink";
165
167
  import meow from "meow";
166
- import fs9 from "fs";
168
+ import fs10 from "fs";
167
169
  import { createRequire as createRequire2 } from "module";
168
170
  import os7 from "os";
169
- import path9 from "path";
171
+ import path10 from "path";
170
172
  import { fileURLToPath as fileURLToPath3 } from "url";
171
173
 
172
174
  // src/app/shell/AppShell.tsx
173
175
  import process6 from "process";
174
- import React9, {
176
+ import React8, {
175
177
  Profiler,
176
178
  useState as useState18,
177
179
  useCallback as useCallback19,
@@ -179,7 +181,7 @@ import React9, {
179
181
  useEffect as useEffect14,
180
182
  useMemo as useMemo17
181
183
  } from "react";
182
- import { Box as Box19, Text as Text25, useApp, useInput as useInput17, useStdout as useStdout9 } from "ink";
184
+ import { Box as Box18, Text as Text24, useApp, useInput as useInput17, useStdout as useStdout9 } from "ink";
183
185
 
184
186
  // src/ui/components/PermissionDialog.tsx
185
187
  import { useCallback, useMemo } from "react";
@@ -1741,20 +1743,14 @@ function useFeed(runtime, messages = [], initialAllowedTools, sessionStore, opti
1741
1743
  dashboardDecisionInboxRef.current = createDashboardDecisionInbox();
1742
1744
  }
1743
1745
  const inbox = dashboardDecisionInboxRef.current;
1744
- const applyPending = () => {
1745
- const rows = inbox.pendingForSession({ athenaSessionId, limit: 25 });
1746
- for (const row of rows) {
1747
- runtime.sendDecision(row.requestId, row.decision);
1748
- inbox.markConsumed({ id: row.id });
1749
- }
1750
- };
1751
- applyPending();
1752
- const interval = setInterval(
1753
- applyPending,
1754
- options?.dashboardDecisionPollIntervalMs ?? 1e3
1755
- );
1746
+ const drain = startDashboardDecisionDrain({
1747
+ runtime,
1748
+ inbox,
1749
+ athenaSessionId,
1750
+ ...options?.dashboardDecisionPollIntervalMs !== void 0 ? { pollIntervalMs: options.dashboardDecisionPollIntervalMs } : {}
1751
+ });
1756
1752
  return () => {
1757
- clearInterval(interval);
1753
+ drain.stop();
1758
1754
  };
1759
1755
  }, [
1760
1756
  runtime,
@@ -1943,43 +1939,47 @@ function useFeed(runtime, messages = [], initialAllowedTools, sessionStore, opti
1943
1939
  ...options?.relayQuestion ? { relayQuestion: options.relayQuestion } : {},
1944
1940
  signal: abortRef.current.signal
1945
1941
  };
1946
- const unsub = runtime.onEvent((runtimeEvent) => {
1947
- const parentCycleId = getActivePerfCycleId();
1948
- const cycleId = startPerfCycle(`feed:${runtimeEvent.kind}`, {
1949
- parent_cycle_id: parentCycleId ?? void 0,
1950
- runtime_event_id: runtimeEvent.id,
1951
- runtime_kind: runtimeEvent.kind,
1952
- hook_name: runtimeEvent.hookName,
1953
- tool_name: runtimeEvent.toolName
1954
- });
1955
- logPerfEvent("feed.runtime_event", {
1956
- cycle_id: cycleId ?? void 0,
1957
- runtime_event_id: runtimeEvent.id,
1958
- runtime_kind: runtimeEvent.kind,
1959
- hook_name: runtimeEvent.hookName,
1960
- tool_name: runtimeEvent.toolName
1961
- });
1962
- const doneCause = startPerfStage("cause.start", {
1963
- source: "runtime.event",
1964
- runtime_kind: runtimeEvent.kind
1965
- });
1966
- try {
1942
+ const loop = attachRuntimeEventLoop({
1943
+ runtime,
1944
+ ingest: () => ({
1945
+ mapper: mapperRef.current,
1946
+ store: sessionStoreRef.current,
1947
+ controllerCallbacks
1948
+ }),
1949
+ wrapEvent: (runtimeEvent, run) => {
1950
+ const parentCycleId = getActivePerfCycleId();
1951
+ const cycleId = startPerfCycle(`feed:${runtimeEvent.kind}`, {
1952
+ parent_cycle_id: parentCycleId ?? void 0,
1953
+ runtime_event_id: runtimeEvent.id,
1954
+ runtime_kind: runtimeEvent.kind,
1955
+ hook_name: runtimeEvent.hookName,
1956
+ tool_name: runtimeEvent.toolName
1957
+ });
1958
+ logPerfEvent("feed.runtime_event", {
1959
+ cycle_id: cycleId ?? void 0,
1960
+ runtime_event_id: runtimeEvent.id,
1961
+ runtime_kind: runtimeEvent.kind,
1962
+ hook_name: runtimeEvent.hookName,
1963
+ tool_name: runtimeEvent.toolName
1964
+ });
1965
+ const doneCause = startPerfStage("cause.start", {
1966
+ source: "runtime.event",
1967
+ runtime_kind: runtimeEvent.kind
1968
+ });
1969
+ try {
1970
+ run();
1971
+ } finally {
1972
+ doneCause();
1973
+ }
1974
+ },
1975
+ onEventReceived: (runtimeEvent) => {
1967
1976
  if (options?.relayPermission && runtimeEvent.kind === "permission.request") {
1968
1977
  writeGatewayTrace(
1969
1978
  `useFeed permission event relay-enabled id=${runtimeEvent.id} tool=${runtimeEvent.toolName ?? ""}`
1970
1979
  );
1971
1980
  }
1972
- const { feedEvents: newFeedEvents, decision } = ingestRuntimeEvent(
1973
- runtimeEvent,
1974
- {
1975
- mapper: mapperRef.current,
1976
- store: sessionStoreRef.current,
1977
- controllerCallbacks
1978
- }
1979
- );
1980
- if (decision) {
1981
- runtime.sendDecision(runtimeEvent.id, decision);
1982
- }
1981
+ },
1982
+ emitEventFeed: (newFeedEvents, runtimeEvent) => {
1983
1983
  if (!abortRef.current.signal.aborted && newFeedEvents.length > 0) {
1984
1984
  for (const fe of newFeedEvents) {
1985
1985
  if (fe.kind === "permission.decision" && fe.cause?.hook_request_id) {
@@ -1989,12 +1989,8 @@ function useFeed(runtime, messages = [], initialAllowedTools, sessionStore, opti
1989
1989
  feedStoreRef.current.pushEvents(newFeedEvents);
1990
1990
  publishDashboardFeedEvents(newFeedEvents, runtimeEvent);
1991
1991
  }
1992
- } finally {
1993
- doneCause();
1994
- }
1995
- });
1996
- const unsubDecision = runtime.onDecision(
1997
- (eventId, decision) => {
1992
+ },
1993
+ wrapDecision: (eventId, decision, run) => {
1998
1994
  const parentCycleId = getActivePerfCycleId();
1999
1995
  const cycleId = startPerfCycle("feed:decision", {
2000
1996
  parent_cycle_id: parentCycleId ?? void 0,
@@ -2013,31 +2009,31 @@ function useFeed(runtime, messages = [], initialAllowedTools, sessionStore, opti
2013
2009
  decision_source: decision.source
2014
2010
  });
2015
2011
  try {
2016
- if (abortRef.current.signal.aborted) return;
2017
- if (decision.intent?.kind === "question_answer" || decision.source === "timeout") {
2018
- dequeueQuestion(eventId);
2019
- }
2020
- const feedEvent = ingestRuntimeDecision(eventId, decision, {
2021
- mapper: mapperRef.current,
2022
- store: sessionStoreRef.current
2023
- });
2024
- if (feedEvent) {
2025
- feedStoreRef.current.pushEvents([feedEvent]);
2026
- publishDashboardFeedEvents([feedEvent]);
2027
- if (feedEvent.kind === "permission.decision" && feedEvent.cause?.hook_request_id) {
2028
- dequeuePermission(feedEvent.cause.hook_request_id);
2029
- }
2030
- }
2012
+ run();
2031
2013
  } finally {
2032
2014
  doneCause();
2033
2015
  }
2016
+ },
2017
+ skipDecision: () => abortRef.current.signal.aborted,
2018
+ beforeDecisionIngest: (eventId, decision) => {
2019
+ if (decision.intent?.kind === "question_answer" || decision.source === "timeout") {
2020
+ dequeueQuestion(eventId);
2021
+ }
2022
+ },
2023
+ emitDecisionFeed: (feedEvent) => {
2024
+ if (feedEvent) {
2025
+ feedStoreRef.current.pushEvents([feedEvent]);
2026
+ publishDashboardFeedEvents([feedEvent]);
2027
+ if (feedEvent.kind === "permission.decision" && feedEvent.cause?.hook_request_id) {
2028
+ dequeuePermission(feedEvent.cause.hook_request_id);
2029
+ }
2030
+ }
2034
2031
  }
2035
- );
2032
+ });
2036
2033
  refreshRuntimeStatus(true);
2037
2034
  return () => {
2038
2035
  abortRef.current.abort();
2039
- unsub();
2040
- unsubDecision();
2036
+ loop.stop();
2041
2037
  };
2042
2038
  }, [
2043
2039
  runtime,
@@ -2307,6 +2303,7 @@ function useHeaderMetrics(events) {
2307
2303
  return cachedRef.current;
2308
2304
  }
2309
2305
  let modelName = null;
2306
+ let effortLevel = null;
2310
2307
  let sessionStartTime = null;
2311
2308
  let toolCallCount = 0;
2312
2309
  let permissionsAllowed = 0;
@@ -2323,6 +2320,9 @@ function useHeaderMetrics(events) {
2323
2320
  modelName = event.data.model;
2324
2321
  }
2325
2322
  }
2323
+ if (typeof event.effort_level === "string") {
2324
+ effortLevel = event.effort_level;
2325
+ }
2326
2326
  if (event.kind === "agent.message" && typeof event.data.model === "string") {
2327
2327
  modelName = event.data.model;
2328
2328
  }
@@ -2375,6 +2375,7 @@ function useHeaderMetrics(events) {
2375
2375
  );
2376
2376
  const result = {
2377
2377
  modelName,
2378
+ effortLevel,
2378
2379
  toolCallCount,
2379
2380
  totalToolCallCount: toolCallCount + subagentToolTotal,
2380
2381
  subagentCount: subagentMap.size,
@@ -4443,6 +4444,8 @@ function getClipboardCommand() {
4443
4444
 
4444
4445
  // src/core/feed/defaultRender.ts
4445
4446
  var DEFAULT_RENDER = /* @__PURE__ */ new Set([
4447
+ "prompt.expansion",
4448
+ "tool.batch",
4446
4449
  "compact.post",
4447
4450
  "task.created",
4448
4451
  "cwd.changed",
@@ -4708,14 +4711,14 @@ function extractWebSearch(_input, response) {
4708
4711
  return { type: "text", content: extractTextContent(response), maxLines: 10 };
4709
4712
  }
4710
4713
  function extractNotebookEdit(input, _response) {
4711
- const path10 = typeof input["notebook_path"] === "string" ? input["notebook_path"] : "";
4714
+ const path11 = typeof input["notebook_path"] === "string" ? input["notebook_path"] : "";
4712
4715
  const mode = typeof input["edit_mode"] === "string" ? input["edit_mode"] : "replace";
4713
4716
  const source = typeof input["new_source"] === "string" ? input["new_source"] : "";
4714
- if (!source) return { type: "text", content: `${mode} cell in ${path10}` };
4717
+ if (!source) return { type: "text", content: `${mode} cell in ${path11}` };
4715
4718
  return {
4716
4719
  type: "code",
4717
4720
  content: source,
4718
- language: detectLanguage(path10),
4721
+ language: detectLanguage(path11),
4719
4722
  maxLines: 10
4720
4723
  };
4721
4724
  }
@@ -5239,10 +5242,10 @@ function extractToolSubject(toolName, toolInput) {
5239
5242
  const parts = [];
5240
5243
  const pattern = str(input, "pattern");
5241
5244
  const glob = str(input, "glob");
5242
- const path10 = str(input, "path");
5245
+ const path11 = str(input, "path");
5243
5246
  if (pattern) parts.push(`"${pattern}"`);
5244
5247
  if (glob) parts.push(glob);
5245
- if (path10) parts.push(`in ${path10}`);
5248
+ if (path11) parts.push(`in ${path11}`);
5246
5249
  return parts.length > 0 ? parts.join(" ") : void 0;
5247
5250
  }
5248
5251
  case "Skill":
@@ -5500,9 +5503,11 @@ function renderDetailLines(event, width, pairedPostEvent, theme = darkTheme) {
5500
5503
  case "setup":
5501
5504
  case "unknown.hook":
5502
5505
  case "todo.add":
5506
+ case "tool.batch":
5503
5507
  case "todo.update":
5504
5508
  case "todo.done":
5505
5509
  case "teammate.idle":
5510
+ case "prompt.expansion":
5506
5511
  case "task.created":
5507
5512
  case "task.completed":
5508
5513
  case "config.change":
@@ -6118,13 +6123,11 @@ function buildBodyLines({
6118
6123
  }
6119
6124
 
6120
6125
  // src/ui/components/FeedGrid.tsx
6121
- import React7 from "react";
6122
- import { Text as Text15 } from "ink";
6126
+ import React6 from "react";
6127
+ import { Text as Text14 } from "ink";
6123
6128
 
6124
6129
  // src/ui/components/FeedRow.tsx
6125
6130
  import { performance as performance2 } from "perf_hooks";
6126
- import React3 from "react";
6127
- import { Box as Box9, Text as Text12 } from "ink";
6128
6131
 
6129
6132
  // src/core/feed/cellFormatters.ts
6130
6133
  function isLifecycleOp(op) {
@@ -6338,7 +6341,6 @@ function formatDetails(opts) {
6338
6341
  }
6339
6342
 
6340
6343
  // src/ui/components/FeedRow.tsx
6341
- import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
6342
6344
  var ROW_LINE_CACHE_MAX_VARIANTS = 16;
6343
6345
  var ROW_LINE_CACHE_MAX_ENTRIES = 2e3;
6344
6346
  var rowLineCache = /* @__PURE__ */ new Map();
@@ -6555,40 +6557,11 @@ function formatFeedRowLine({
6555
6557
  logVisibleRowFormat(performance2.now() - startedAt);
6556
6558
  }
6557
6559
  }
6558
- function FeedRowImpl({
6559
- entry,
6560
- cols,
6561
- focused,
6562
- expanded,
6563
- matched,
6564
- ascii,
6565
- theme
6566
- }) {
6567
- const parts = lineParts({
6568
- entry,
6569
- cols,
6570
- focused,
6571
- expanded,
6572
- matched,
6573
- ascii,
6574
- theme
6575
- });
6576
- return /* @__PURE__ */ jsxs10(Fragment4, { children: [
6577
- /* @__PURE__ */ jsx11(Box9, { width: 1, flexShrink: 0, children: /* @__PURE__ */ jsx11(Text12, { wrap: "truncate-end", children: parts.gutter }) }),
6578
- /* @__PURE__ */ jsx11(Box9, { width: 5, flexShrink: 0, children: /* @__PURE__ */ jsx11(Text12, { wrap: "truncate-end", children: parts.time }) }),
6579
- /* @__PURE__ */ jsx11(Box9, { width: cols.gapW, flexShrink: 0 }),
6580
- /* @__PURE__ */ jsx11(Box9, { width: cols.toolW, flexShrink: 0, children: /* @__PURE__ */ jsx11(Text12, { wrap: "truncate-end", children: parts.tool }) }),
6581
- /* @__PURE__ */ jsx11(Box9, { width: cols.gapW, flexShrink: 0 }),
6582
- /* @__PURE__ */ jsx11(Box9, { width: cols.detailsW, flexShrink: 0, children: /* @__PURE__ */ jsx11(Text12, { wrap: "truncate-end", children: parts.detail }) }),
6583
- /* @__PURE__ */ jsx11(Box9, { flexGrow: 1, flexShrink: 1 })
6584
- ] });
6585
- }
6586
- var FeedRow = React3.memo(FeedRowImpl);
6587
6560
 
6588
6561
  // src/ui/components/FeedHeader.tsx
6589
- import React4 from "react";
6590
- import { Box as Box10, Text as Text13 } from "ink";
6591
- import { Fragment as Fragment5, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
6562
+ import React3 from "react";
6563
+ import { Box as Box9, Text as Text12 } from "ink";
6564
+ import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
6592
6565
  function formatFeedHeaderLine(cols, theme, innerWidth) {
6593
6566
  const headerColor = theme.feed.headerLabel;
6594
6567
  const style = (s) => source_default.hex(headerColor)(s);
@@ -6603,17 +6576,17 @@ function formatFeedHeaderLine(cols, theme, innerWidth) {
6603
6576
  function FeedHeaderImpl({ cols, theme }) {
6604
6577
  const headerColor = theme.feed.headerLabel;
6605
6578
  const style = (s) => source_default.hex(headerColor)(s);
6606
- return /* @__PURE__ */ jsxs11(Fragment5, { children: [
6607
- /* @__PURE__ */ jsx12(Box10, { width: 1, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text13, { children: " " }) }),
6608
- /* @__PURE__ */ jsx12(Box10, { width: 5, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text13, { wrap: "truncate-end", children: style(fit("TIME", 5)) }) }),
6609
- /* @__PURE__ */ jsx12(Box10, { width: cols.gapW, flexShrink: 0 }),
6610
- /* @__PURE__ */ jsx12(Box10, { width: cols.toolW, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text13, { wrap: "truncate-end", children: style(fit("ACTION", cols.toolW)) }) }),
6611
- /* @__PURE__ */ jsx12(Box10, { width: cols.gapW, flexShrink: 0 }),
6612
- /* @__PURE__ */ jsx12(Box10, { width: cols.detailsW, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text13, { wrap: "truncate-end", children: style(fit("DETAILS", cols.detailsW)) }) }),
6613
- /* @__PURE__ */ jsx12(Box10, { flexGrow: 1, flexShrink: 1 })
6579
+ return /* @__PURE__ */ jsxs10(Fragment4, { children: [
6580
+ /* @__PURE__ */ jsx11(Box9, { width: 1, flexShrink: 0, children: /* @__PURE__ */ jsx11(Text12, { children: " " }) }),
6581
+ /* @__PURE__ */ jsx11(Box9, { width: 5, flexShrink: 0, children: /* @__PURE__ */ jsx11(Text12, { wrap: "truncate-end", children: style(fit("TIME", 5)) }) }),
6582
+ /* @__PURE__ */ jsx11(Box9, { width: cols.gapW, flexShrink: 0 }),
6583
+ /* @__PURE__ */ jsx11(Box9, { width: cols.toolW, flexShrink: 0, children: /* @__PURE__ */ jsx11(Text12, { wrap: "truncate-end", children: style(fit("ACTION", cols.toolW)) }) }),
6584
+ /* @__PURE__ */ jsx11(Box9, { width: cols.gapW, flexShrink: 0 }),
6585
+ /* @__PURE__ */ jsx11(Box9, { width: cols.detailsW, flexShrink: 0, children: /* @__PURE__ */ jsx11(Text12, { wrap: "truncate-end", children: style(fit("DETAILS", cols.detailsW)) }) }),
6586
+ /* @__PURE__ */ jsx11(Box9, { flexGrow: 1, flexShrink: 1 })
6614
6587
  ] });
6615
6588
  }
6616
- var FeedHeader = React4.memo(FeedHeaderImpl);
6589
+ var FeedHeader = React3.memo(FeedHeaderImpl);
6617
6590
 
6618
6591
  // src/ui/components/rowCache.ts
6619
6592
  var DEFAULT_MAX_SIZE = 100;
@@ -6880,11 +6853,11 @@ function buildFeedSurface(params) {
6880
6853
  }
6881
6854
 
6882
6855
  // src/ui/components/FeedSurface.tsx
6883
- import React6 from "react";
6884
- import { Text as Text14 } from "ink";
6856
+ import React5 from "react";
6857
+ import { Text as Text13 } from "ink";
6885
6858
 
6886
6859
  // src/ui/components/IncrementalFeedSurface.tsx
6887
- import React5 from "react";
6860
+ import React4 from "react";
6888
6861
 
6889
6862
  // src/ui/components/feedSurfaceDiff.ts
6890
6863
  function diffFeedSurface(prev, next) {
@@ -6947,19 +6920,19 @@ function IncrementalFeedSurfaceImpl({
6947
6920
  feedStartCol,
6948
6921
  stdout = process.stdout
6949
6922
  }) {
6950
- const prevLinesRef = React5.useRef([]);
6951
- const prevFeedStartRowRef = React5.useRef(feedStartRow);
6952
- const prevFeedStartColRef = React5.useRef(feedStartCol);
6953
- const prevLineWidthRef = React5.useRef(surface.lineWidth);
6954
- const feedStartRowRef = React5.useRef(feedStartRow);
6955
- const feedStartColRef = React5.useRef(feedStartCol);
6956
- const lineWidthRef = React5.useRef(surface.lineWidth);
6957
- const stdoutRef = React5.useRef(stdout);
6923
+ const prevLinesRef = React4.useRef([]);
6924
+ const prevFeedStartRowRef = React4.useRef(feedStartRow);
6925
+ const prevFeedStartColRef = React4.useRef(feedStartCol);
6926
+ const prevLineWidthRef = React4.useRef(surface.lineWidth);
6927
+ const feedStartRowRef = React4.useRef(feedStartRow);
6928
+ const feedStartColRef = React4.useRef(feedStartCol);
6929
+ const lineWidthRef = React4.useRef(surface.lineWidth);
6930
+ const stdoutRef = React4.useRef(stdout);
6958
6931
  feedStartRowRef.current = feedStartRow;
6959
6932
  feedStartColRef.current = feedStartCol;
6960
6933
  lineWidthRef.current = surface.lineWidth;
6961
6934
  stdoutRef.current = stdout;
6962
- React5.useEffect(() => {
6935
+ React4.useEffect(() => {
6963
6936
  const prevLines = prevLinesRef.current;
6964
6937
  const nextLines = surface.allLines;
6965
6938
  const prevStartRow = prevFeedStartRowRef.current;
@@ -7016,7 +6989,7 @@ function IncrementalFeedSurfaceImpl({
7016
6989
  linesCleared: result.linesCleared
7017
6990
  });
7018
6991
  }, [surface, feedStartRow, feedStartCol, stdout]);
7019
- React5.useEffect(() => {
6992
+ React4.useEffect(() => {
7020
6993
  return () => {
7021
6994
  if (prevLinesRef.current.length > 0) {
7022
6995
  paintFeedSurface(
@@ -7032,10 +7005,10 @@ function IncrementalFeedSurfaceImpl({
7032
7005
  }, []);
7033
7006
  return null;
7034
7007
  }
7035
- var IncrementalFeedSurface = React5.memo(IncrementalFeedSurfaceImpl);
7008
+ var IncrementalFeedSurface = React4.memo(IncrementalFeedSurfaceImpl);
7036
7009
 
7037
7010
  // src/ui/components/FeedSurface.tsx
7038
- import { jsx as jsx13 } from "react/jsx-runtime";
7011
+ import { jsx as jsx12 } from "react/jsx-runtime";
7039
7012
  var VALID_BACKENDS = /* @__PURE__ */ new Set([
7040
7013
  "ink-full",
7041
7014
  "incremental"
@@ -7057,7 +7030,7 @@ function FeedSurfaceImpl({
7057
7030
  }) {
7058
7031
  const backend = resolveFeedBackend(backendProp);
7059
7032
  if (backend === "incremental") {
7060
- return /* @__PURE__ */ jsx13(
7033
+ return /* @__PURE__ */ jsx12(
7061
7034
  IncrementalFeedSurface,
7062
7035
  {
7063
7036
  surface,
@@ -7067,15 +7040,15 @@ function FeedSurfaceImpl({
7067
7040
  }
7068
7041
  );
7069
7042
  }
7070
- return /* @__PURE__ */ jsx13(InkFullFeedSurface, { surface, backend });
7043
+ return /* @__PURE__ */ jsx12(InkFullFeedSurface, { surface, backend });
7071
7044
  }
7072
7045
  function InkFullFeedSurface({
7073
7046
  surface,
7074
7047
  backend
7075
7048
  }) {
7076
- const output = React6.useMemo(() => surface.allLines.join("\n"), [surface]);
7077
- const prevLinesRef = React6.useRef(0);
7078
- React6.useEffect(() => {
7049
+ const output = React5.useMemo(() => surface.allLines.join("\n"), [surface]);
7050
+ const prevLinesRef = React5.useRef(0);
7051
+ React5.useEffect(() => {
7079
7052
  const linesRendered = surface.allLines.length;
7080
7053
  const prevLines = prevLinesRef.current;
7081
7054
  prevLinesRef.current = linesRendered;
@@ -7089,12 +7062,12 @@ function InkFullFeedSurface({
7089
7062
  linesCleared
7090
7063
  });
7091
7064
  }, [surface, backend]);
7092
- return /* @__PURE__ */ jsx13(Text14, { children: output });
7065
+ return /* @__PURE__ */ jsx12(Text13, { children: output });
7093
7066
  }
7094
- var FeedSurfaceView = React6.memo(FeedSurfaceImpl);
7067
+ var FeedSurfaceView = React5.memo(FeedSurfaceImpl);
7095
7068
 
7096
7069
  // src/ui/components/FeedGrid.tsx
7097
- import { Fragment as Fragment6, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
7070
+ import { Fragment as Fragment5, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
7098
7071
  function FeedGridImpl({
7099
7072
  feedHeaderRows,
7100
7073
  feedContentRows,
@@ -7114,16 +7087,16 @@ function FeedGridImpl({
7114
7087
  }) {
7115
7088
  const backend = resolveFeedBackend(backendProp);
7116
7089
  const isIncremental = backend === "incremental";
7117
- const rowCacheRef = React7.useRef(new RowCache());
7118
- const prevGlobalsRef = React7.useRef({ innerWidth, ascii, theme, cols });
7119
- React7.useEffect(() => {
7090
+ const rowCacheRef = React6.useRef(new RowCache());
7091
+ const prevGlobalsRef = React6.useRef({ innerWidth, ascii, theme, cols });
7092
+ React6.useEffect(() => {
7120
7093
  const prev = prevGlobalsRef.current;
7121
7094
  if (prev.innerWidth !== innerWidth || prev.ascii !== ascii || prev.theme !== theme || prev.cols !== cols) {
7122
7095
  rowCacheRef.current.bumpGeneration();
7123
7096
  prevGlobalsRef.current = { innerWidth, ascii, theme, cols };
7124
7097
  }
7125
7098
  }, [innerWidth, ascii, theme, cols]);
7126
- const surface = React7.useMemo(
7099
+ const surface = React6.useMemo(
7127
7100
  () => buildFeedSurface({
7128
7101
  feedHeaderRows,
7129
7102
  feedContentRows,
@@ -7155,7 +7128,7 @@ function FeedGridImpl({
7155
7128
  ]
7156
7129
  );
7157
7130
  const { visibleContentRows } = surface;
7158
- const visibleRowSignatures = React7.useMemo(() => {
7131
+ const visibleRowSignatures = React6.useMemo(() => {
7159
7132
  const signatures = [];
7160
7133
  if (visibleContentRows <= 0) return signatures;
7161
7134
  for (let offset = 0; offset < visibleContentRows; offset++) {
@@ -7184,8 +7157,8 @@ function FeedGridImpl({
7184
7157
  feedCursor,
7185
7158
  searchMatchSet
7186
7159
  ]);
7187
- const prevViewportRef = React7.useRef(null);
7188
- React7.useEffect(() => {
7160
+ const prevViewportRef = React6.useRef(null);
7161
+ React6.useEffect(() => {
7189
7162
  const previous = prevViewportRef.current;
7190
7163
  const current = {
7191
7164
  signatures: visibleRowSignatures,
@@ -7229,9 +7202,9 @@ function FeedGridImpl({
7229
7202
  if (isIncremental) {
7230
7203
  const totalFeedRows = feedHeaderRows + feedContentRows;
7231
7204
  const placeholderLines = "\n".repeat(Math.max(0, totalFeedRows - 1));
7232
- return /* @__PURE__ */ jsxs12(Fragment6, { children: [
7233
- /* @__PURE__ */ jsx14(Text15, { children: placeholderLines }),
7234
- /* @__PURE__ */ jsx14(
7205
+ return /* @__PURE__ */ jsxs11(Fragment5, { children: [
7206
+ /* @__PURE__ */ jsx13(Text14, { children: placeholderLines }),
7207
+ /* @__PURE__ */ jsx13(
7235
7208
  FeedSurfaceView,
7236
7209
  {
7237
7210
  surface,
@@ -7242,7 +7215,7 @@ function FeedGridImpl({
7242
7215
  )
7243
7216
  ] });
7244
7217
  }
7245
- return /* @__PURE__ */ jsx14(
7218
+ return /* @__PURE__ */ jsx13(
7246
7219
  FeedSurfaceView,
7247
7220
  {
7248
7221
  surface,
@@ -7251,11 +7224,11 @@ function FeedGridImpl({
7251
7224
  }
7252
7225
  );
7253
7226
  }
7254
- var FeedGrid = React7.memo(FeedGridImpl);
7227
+ var FeedGrid = React6.memo(FeedGridImpl);
7255
7228
 
7256
7229
  // src/ui/components/MessagePanel.tsx
7257
- import React8, { useMemo as useMemo11 } from "react";
7258
- import { Text as Text16 } from "ink";
7230
+ import React7, { useMemo as useMemo11 } from "react";
7231
+ import { Text as Text15 } from "ink";
7259
7232
 
7260
7233
  // src/core/feed/panelFilter.ts
7261
7234
  var USER_TAGS = /* @__PURE__ */ new Set(["msg.user", "prompt"]);
@@ -7303,7 +7276,7 @@ function messageText(entry) {
7303
7276
  }
7304
7277
 
7305
7278
  // src/ui/components/MessagePanel.tsx
7306
- import { jsx as jsx15 } from "react/jsx-runtime";
7279
+ import { jsx as jsx14 } from "react/jsx-runtime";
7307
7280
  var INDICATOR_OVERHEAD = 2;
7308
7281
  function buildRenderedLines(entries, width, theme) {
7309
7282
  const contentWidth2 = width - INDICATOR_OVERHEAD;
@@ -7438,9 +7411,9 @@ function MessagePanelImpl(props) {
7438
7411
  ),
7439
7412
  [wrapped, contentRows, viewportStart, style, width, messageCursorIndex]
7440
7413
  );
7441
- return /* @__PURE__ */ jsx15(Text16, { children: lines.join("\n") });
7414
+ return /* @__PURE__ */ jsx14(Text15, { children: lines.join("\n") });
7442
7415
  }
7443
- var MessagePanel = React8.memo(MessagePanelImpl);
7416
+ var MessagePanel = React7.memo(MessagePanelImpl);
7444
7417
 
7445
7418
  // src/ui/hooks/useFeedColumns.ts
7446
7419
  import { useMemo as useMemo12, useRef as useRef12 } from "react";
@@ -7652,6 +7625,7 @@ function buildHeaderModel(input) {
7652
7625
  workflow: workflowRef ?? "default",
7653
7626
  harness: detectHarness(input.harness),
7654
7627
  model_name: input.modelName ?? null,
7628
+ effort_level: input.effortLevel ?? null,
7655
7629
  context: { used: input.contextUsed ?? null, max: input.contextMax ?? null },
7656
7630
  total_tokens: input.totalTokens ?? null,
7657
7631
  token_label: codexHarness ? "Billable" : "Tokens",
@@ -7860,7 +7834,8 @@ function renderHeaderLines(model, width, hasColor, theme) {
7860
7834
  const sidText = `${sidLabel}${sidValue}${style(sidScope, palette.label)}`;
7861
7835
  const wfText = `${style("Workflow: ", palette.label)}${style(model.workflow, palette.value)}`;
7862
7836
  const harnessText = `${style("Harness: ", palette.label)}${style(model.harness, palette.value)}`;
7863
- const modelText = `${style("Model: ", palette.label)}${style(formatModelName(model.model_name), palette.value)}`;
7837
+ const effortSuffix = model.effort_level ? style(` with ${model.effort_level} effort`, palette.label) : "";
7838
+ const modelText = `${style("Model: ", palette.label)}${style(formatModelName(model.model_name), palette.value)}${effortSuffix}`;
7864
7839
  const tokenLabel = model.token_label ?? "Tokens";
7865
7840
  const runLabel = model.run_label ?? "Runs";
7866
7841
  const leftTokens = [
@@ -7988,8 +7963,8 @@ function executeCommand(command, args, ctx) {
7988
7963
 
7989
7964
  // src/ui/components/SessionPicker.tsx
7990
7965
  import { useState as useState11 } from "react";
7991
- import { Box as Box11, Text as Text17, useInput as useInput12, useStdout as useStdout5 } from "ink";
7992
- import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
7966
+ import { Box as Box10, Text as Text16, useInput as useInput12, useStdout as useStdout5 } from "ink";
7967
+ import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
7993
7968
  var PICKER_CHROME_ROWS = 5;
7994
7969
  var ROWS_PER_SESSION = 3;
7995
7970
  function resolveVisibleCount(terminalRows) {
@@ -8031,13 +8006,13 @@ function SessionPicker({
8031
8006
  }
8032
8007
  });
8033
8008
  if (loading) {
8034
- return /* @__PURE__ */ jsxs13(Box11, { flexDirection: "column", padding: 1, children: [
8035
- /* @__PURE__ */ jsx16(Box11, { marginBottom: 1, children: /* @__PURE__ */ jsx16(Text17, { bold: true, color: theme.accent, children: "Sessions" }) }),
8036
- /* @__PURE__ */ jsx16(Text17, { dimColor: true, children: "Loading sessions\u2026" })
8009
+ return /* @__PURE__ */ jsxs12(Box10, { flexDirection: "column", padding: 1, children: [
8010
+ /* @__PURE__ */ jsx15(Box10, { marginBottom: 1, children: /* @__PURE__ */ jsx15(Text16, { bold: true, color: theme.accent, children: "Sessions" }) }),
8011
+ /* @__PURE__ */ jsx15(Text16, { dimColor: true, children: "Loading sessions\u2026" })
8037
8012
  ] });
8038
8013
  }
8039
8014
  if (sessions.length === 0) {
8040
- return /* @__PURE__ */ jsx16(Box11, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx16(Text17, { dimColor: true, children: "No previous sessions found." }) });
8015
+ return /* @__PURE__ */ jsx15(Box10, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx15(Text16, { dimColor: true, children: "No previous sessions found." }) });
8041
8016
  }
8042
8017
  const scrollStart = Math.max(
8043
8018
  0,
@@ -8047,8 +8022,8 @@ function SessionPicker({
8047
8022
  )
8048
8023
  );
8049
8024
  const visible = sessions.slice(scrollStart, scrollStart + visibleCount);
8050
- return /* @__PURE__ */ jsxs13(Box11, { flexDirection: "column", padding: 1, children: [
8051
- /* @__PURE__ */ jsx16(Box11, { marginBottom: 1, children: /* @__PURE__ */ jsx16(Text17, { bold: true, color: theme.accent, children: "Sessions" }) }),
8025
+ return /* @__PURE__ */ jsxs12(Box10, { flexDirection: "column", padding: 1, children: [
8026
+ /* @__PURE__ */ jsx15(Box10, { marginBottom: 1, children: /* @__PURE__ */ jsx15(Text16, { bold: true, color: theme.accent, children: "Sessions" }) }),
8052
8027
  visible.map((session, vi) => {
8053
8028
  const realIndex = scrollStart + vi;
8054
8029
  const isFocused = realIndex === focusIndex;
@@ -8060,23 +8035,23 @@ function SessionPicker({
8060
8035
  const meta = `${shortId}${branch} \xB7 ${time}${msgs}`;
8061
8036
  const titleRaw = session.summary || session.firstPrompt || `Session ${shortId}`;
8062
8037
  const title = compactText(titleRaw.replace(/\n/g, " ").trim(), 60);
8063
- return /* @__PURE__ */ jsxs13(
8064
- Box11,
8038
+ return /* @__PURE__ */ jsxs12(
8039
+ Box10,
8065
8040
  {
8066
8041
  flexDirection: "column",
8067
8042
  marginBottom: vi === visible.length - 1 ? 0 : 1,
8068
8043
  children: [
8069
- /* @__PURE__ */ jsx16(Box11, { children: /* @__PURE__ */ jsxs13(Text17, { color: isFocused ? "cyan" : void 0, bold: isFocused, children: [
8044
+ /* @__PURE__ */ jsx15(Box10, { children: /* @__PURE__ */ jsxs12(Text16, { color: isFocused ? "cyan" : void 0, bold: isFocused, children: [
8070
8045
  isFocused ? "\u276F " : " ",
8071
8046
  title
8072
8047
  ] }) }),
8073
- /* @__PURE__ */ jsx16(Box11, { paddingLeft: 2, children: /* @__PURE__ */ jsx16(Text17, { dimColor: true, children: meta }) })
8048
+ /* @__PURE__ */ jsx15(Box10, { paddingLeft: 2, children: /* @__PURE__ */ jsx15(Text16, { dimColor: true, children: meta }) })
8074
8049
  ]
8075
8050
  },
8076
8051
  session.sessionId
8077
8052
  );
8078
8053
  }),
8079
- /* @__PURE__ */ jsx16(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx16(Text17, { dimColor: true, children: "\u2191/\u2193 Navigate \xB7 Enter Select \xB7 Esc Cancel" }) })
8054
+ /* @__PURE__ */ jsx15(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx15(Text16, { dimColor: true, children: "\u2191/\u2193 Navigate \xB7 Enter Select \xB7 Esc Cancel" }) })
8080
8055
  ] });
8081
8056
  }
8082
8057
 
@@ -8097,7 +8072,7 @@ function renderYankLines(entry, width, theme) {
8097
8072
 
8098
8073
  // src/setup/SetupWizard.tsx
8099
8074
  import { useState as useState14, useCallback as useCallback15, useEffect as useEffect10, useRef as useRef13 } from "react";
8100
- import { Box as Box16, Text as Text22, useInput as useInput13 } from "ink";
8075
+ import { Box as Box15, Text as Text21, useInput as useInput13 } from "ink";
8101
8076
 
8102
8077
  // src/setup/useSetupState.ts
8103
8078
  import { useState as useState12, useCallback as useCallback13 } from "react";
@@ -8131,14 +8106,14 @@ function useSetupState() {
8131
8106
  }
8132
8107
 
8133
8108
  // src/setup/steps/ThemeStep.tsx
8134
- import { Box as Box12, Text as Text18 } from "ink";
8135
- import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
8109
+ import { Box as Box11, Text as Text17 } from "ink";
8110
+ import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
8136
8111
  function ThemeStep({ onComplete, onPreview }) {
8137
8112
  const theme = useTheme();
8138
- return /* @__PURE__ */ jsxs14(Box12, { flexDirection: "column", children: [
8139
- /* @__PURE__ */ jsx17(Text18, { bold: true, color: theme.accent, children: "Choose your display theme" }),
8140
- /* @__PURE__ */ jsx17(Text18, { color: theme.textMuted, children: "This applies immediately after setup completes." }),
8141
- /* @__PURE__ */ jsx17(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx17(
8113
+ return /* @__PURE__ */ jsxs13(Box11, { flexDirection: "column", children: [
8114
+ /* @__PURE__ */ jsx16(Text17, { bold: true, color: theme.accent, children: "Choose your display theme" }),
8115
+ /* @__PURE__ */ jsx16(Text17, { color: theme.textMuted, children: "This applies immediately after setup completes." }),
8116
+ /* @__PURE__ */ jsx16(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx16(
8142
8117
  StepSelector,
8143
8118
  {
8144
8119
  options: [
@@ -8168,8 +8143,8 @@ function ThemeStep({ onComplete, onPreview }) {
8168
8143
 
8169
8144
  // src/setup/steps/HarnessStep.tsx
8170
8145
  import { useState as useState13, useCallback as useCallback14 } from "react";
8171
- import { Box as Box13, Text as Text19 } from "ink";
8172
- import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
8146
+ import { Box as Box12, Text as Text18 } from "ink";
8147
+ import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
8173
8148
  function HarnessStep({ onComplete, onError }) {
8174
8149
  const theme = useTheme();
8175
8150
  const capabilities = listHarnessCapabilities();
@@ -8180,7 +8155,7 @@ function HarnessStep({ onComplete, onError }) {
8180
8155
  (check) => {
8181
8156
  const glyph = check.status === "pass" ? "\u2713" : check.status === "fail" ? "\u2717" : "!";
8182
8157
  const color = check.status === "pass" ? theme.status.success : check.status === "fail" ? theme.status.error : theme.status.warning;
8183
- return /* @__PURE__ */ jsx18(Text19, { color, children: `${glyph} ${check.label}: ${check.message}` }, check.label);
8158
+ return /* @__PURE__ */ jsx17(Text18, { color, children: `${glyph} ${check.label}: ${check.message}` }, check.label);
8184
8159
  },
8185
8160
  [theme.status.error, theme.status.success, theme.status.warning]
8186
8161
  );
@@ -8212,10 +8187,10 @@ function HarnessStep({ onComplete, onError }) {
8212
8187
  },
8213
8188
  [capabilities, onComplete, onError]
8214
8189
  );
8215
- return /* @__PURE__ */ jsxs15(Box13, { flexDirection: "column", children: [
8216
- /* @__PURE__ */ jsx18(Text19, { bold: true, color: theme.accent, children: "Select harness" }),
8217
- /* @__PURE__ */ jsx18(Text19, { color: theme.textMuted, children: "Choose your coding harness. You can skip this step with S." }),
8218
- status === "selecting" && /* @__PURE__ */ jsx18(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx18(
8190
+ return /* @__PURE__ */ jsxs14(Box12, { flexDirection: "column", children: [
8191
+ /* @__PURE__ */ jsx17(Text18, { bold: true, color: theme.accent, children: "Select harness" }),
8192
+ /* @__PURE__ */ jsx17(Text18, { color: theme.textMuted, children: "Choose your coding harness. You can skip this step with S." }),
8193
+ status === "selecting" && /* @__PURE__ */ jsx17(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx17(
8219
8194
  StepSelector,
8220
8195
  {
8221
8196
  options: capabilities.map((capability, index) => ({
@@ -8227,22 +8202,22 @@ function HarnessStep({ onComplete, onError }) {
8227
8202
  onSelect: (value) => handleSelect(value)
8228
8203
  }
8229
8204
  ) }),
8230
- (status === "verifying" || status === "success" || status === "error") && /* @__PURE__ */ jsxs15(Box13, { flexDirection: "column", marginTop: 1, children: [
8231
- /* @__PURE__ */ jsx18(
8205
+ (status === "verifying" || status === "success" || status === "error") && /* @__PURE__ */ jsxs14(Box12, { flexDirection: "column", marginTop: 1, children: [
8206
+ /* @__PURE__ */ jsx17(
8232
8207
  StepStatus,
8233
8208
  {
8234
8209
  status,
8235
8210
  message: message || "Verifying harness..."
8236
8211
  }
8237
8212
  ),
8238
- checks.length > 0 && /* @__PURE__ */ jsx18(Box13, { flexDirection: "column", marginTop: 1, children: checks.map(renderCheckLine) })
8213
+ checks.length > 0 && /* @__PURE__ */ jsx17(Box12, { flexDirection: "column", marginTop: 1, children: checks.map(renderCheckLine) })
8239
8214
  ] })
8240
8215
  ] });
8241
8216
  }
8242
8217
 
8243
8218
  // src/setup/components/WizardFrame.tsx
8244
- import { Box as Box14, Text as Text20, useStdout as useStdout6 } from "ink";
8245
- import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
8219
+ import { Box as Box13, Text as Text19, useStdout as useStdout6 } from "ink";
8220
+ import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
8246
8221
  var MAX_WIDTH = 60;
8247
8222
  function WizardFrame({ title, header, footer, children }) {
8248
8223
  const theme = useTheme();
@@ -8256,25 +8231,25 @@ function WizardFrame({ title, header, footer, children }) {
8256
8231
  const topLine = `${g["frame.topLeft"]}${h.repeat(3)}${titlePadded}${h.repeat(topFillCount)}${g["frame.topRight"]}`;
8257
8232
  const teeLine = `${g["frame.teeLeft"]}${h.repeat(frameWidth - 2)}${g["frame.teeRight"]}`;
8258
8233
  const bottomLine = `${g["frame.bottomLeft"]}${h.repeat(frameWidth - 2)}${g["frame.bottomRight"]}`;
8259
- return /* @__PURE__ */ jsxs16(Box14, { flexDirection: "column", paddingX: 1, children: [
8260
- /* @__PURE__ */ jsx19(Text20, { color: theme.accent, children: topLine }),
8261
- /* @__PURE__ */ jsx19(Box14, { flexDirection: "column", paddingX: 1, paddingY: 1, children: header }),
8262
- /* @__PURE__ */ jsx19(Text20, { color: theme.accent, children: teeLine }),
8263
- /* @__PURE__ */ jsx19(Box14, { flexDirection: "column", paddingX: 1, paddingY: 1, children }),
8264
- /* @__PURE__ */ jsx19(Text20, { color: theme.accent, children: teeLine }),
8265
- /* @__PURE__ */ jsx19(Box14, { paddingX: 1, children: footer }),
8266
- /* @__PURE__ */ jsx19(Text20, { color: theme.accent, children: bottomLine })
8234
+ return /* @__PURE__ */ jsxs15(Box13, { flexDirection: "column", paddingX: 1, children: [
8235
+ /* @__PURE__ */ jsx18(Text19, { color: theme.accent, children: topLine }),
8236
+ /* @__PURE__ */ jsx18(Box13, { flexDirection: "column", paddingX: 1, paddingY: 1, children: header }),
8237
+ /* @__PURE__ */ jsx18(Text19, { color: theme.accent, children: teeLine }),
8238
+ /* @__PURE__ */ jsx18(Box13, { flexDirection: "column", paddingX: 1, paddingY: 1, children }),
8239
+ /* @__PURE__ */ jsx18(Text19, { color: theme.accent, children: teeLine }),
8240
+ /* @__PURE__ */ jsx18(Box13, { paddingX: 1, children: footer }),
8241
+ /* @__PURE__ */ jsx18(Text19, { color: theme.accent, children: bottomLine })
8267
8242
  ] });
8268
8243
  }
8269
8244
 
8270
8245
  // src/setup/components/WizardHints.tsx
8271
- import { Box as Box15, Text as Text21 } from "ink";
8272
- import { jsx as jsx20 } from "react/jsx-runtime";
8246
+ import { Box as Box14, Text as Text20 } from "ink";
8247
+ import { jsx as jsx19 } from "react/jsx-runtime";
8273
8248
  function WizardHints({ stepState, stepIndex }) {
8274
8249
  const theme = useTheme();
8275
8250
  const g = getGlyphs();
8276
8251
  if (stepState === "verifying" || stepState === "success") {
8277
- return /* @__PURE__ */ jsx20(Box15, {});
8252
+ return /* @__PURE__ */ jsx19(Box14, {});
8278
8253
  }
8279
8254
  const hints = [];
8280
8255
  if (stepState === "error") {
@@ -8286,7 +8261,7 @@ function WizardHints({ stepState, stepIndex }) {
8286
8261
  if (stepIndex > 0) hints.push(`${g["hint.escape"]} back`);
8287
8262
  hints.push("s skip");
8288
8263
  }
8289
- return /* @__PURE__ */ jsx20(Box15, { children: /* @__PURE__ */ jsx20(Text21, { color: theme.textMuted, children: hints.join(" ") }) });
8264
+ return /* @__PURE__ */ jsx19(Box14, { children: /* @__PURE__ */ jsx19(Text20, { color: theme.textMuted, children: hints.join(" ") }) });
8290
8265
  }
8291
8266
 
8292
8267
  // src/infra/telemetry/identity.ts
@@ -8296,7 +8271,7 @@ function generateDeviceId() {
8296
8271
  }
8297
8272
 
8298
8273
  // src/setup/SetupWizard.tsx
8299
- import { Fragment as Fragment7, jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
8274
+ import { Fragment as Fragment6, jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
8300
8275
  var STEP_SUMMARIES = [
8301
8276
  { label: "Theme", summarize: (r) => r.theme },
8302
8277
  { label: "Harness", summarize: (r) => r.harness ?? "skipped" }
@@ -8417,12 +8392,12 @@ function SetupWizard({ onComplete, onThemePreview }) {
8417
8392
  }
8418
8393
  }
8419
8394
  }, [isComplete, result, onComplete, writeRetryCount]);
8420
- return /* @__PURE__ */ jsxs17(
8395
+ return /* @__PURE__ */ jsxs16(
8421
8396
  WizardFrame,
8422
8397
  {
8423
8398
  title: "ATHENA SETUP",
8424
- header: /* @__PURE__ */ jsx21(Text22, { color: theme.textMuted, children: "Configure your defaults in under a minute." }),
8425
- footer: /* @__PURE__ */ jsx21(
8399
+ header: /* @__PURE__ */ jsx20(Text21, { color: theme.textMuted, children: "Configure your defaults in under a minute." }),
8400
+ footer: /* @__PURE__ */ jsx20(
8426
8401
  WizardHints,
8427
8402
  {
8428
8403
  stepState: isComplete ? writeError ? "error" : "verifying" : stepState,
@@ -8433,21 +8408,21 @@ function SetupWizard({ onComplete, onThemePreview }) {
8433
8408
  STEP_SUMMARIES.slice(
8434
8409
  0,
8435
8410
  isComplete ? STEP_SUMMARIES.length : stepIndex
8436
- ).map((step, i) => /* @__PURE__ */ jsxs17(Text22, { color: theme.status.success, children: [
8411
+ ).map((step, i) => /* @__PURE__ */ jsxs16(Text21, { color: theme.status.success, children: [
8437
8412
  getGlyphs()["todo.done"],
8438
8413
  " ",
8439
8414
  step.label,
8440
8415
  " \xB7 ",
8441
8416
  step.summarize(result)
8442
8417
  ] }, i)),
8443
- stepIndex === 0 && !isComplete && /* @__PURE__ */ jsx21(
8418
+ stepIndex === 0 && !isComplete && /* @__PURE__ */ jsx20(
8444
8419
  ThemeStep,
8445
8420
  {
8446
8421
  onComplete: handleThemeComplete,
8447
8422
  onPreview: handleThemePreview
8448
8423
  }
8449
8424
  ),
8450
- stepIndex === 1 && !isComplete && /* @__PURE__ */ jsx21(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx21(
8425
+ stepIndex === 1 && !isComplete && /* @__PURE__ */ jsx20(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx20(
8451
8426
  HarnessStep,
8452
8427
  {
8453
8428
  onComplete: handleHarnessComplete,
@@ -8455,11 +8430,11 @@ function SetupWizard({ onComplete, onThemePreview }) {
8455
8430
  },
8456
8431
  retryCount
8457
8432
  ) }),
8458
- stepState === "error" && !isComplete && /* @__PURE__ */ jsx21(Text22, { color: theme.status.error, children: "Press r to retry this step." }),
8459
- isComplete && !writeError && /* @__PURE__ */ jsx21(StepStatus, { status: "verifying", message: "Saving setup..." }),
8460
- isComplete && writeError && /* @__PURE__ */ jsxs17(Fragment7, { children: [
8461
- /* @__PURE__ */ jsx21(StepStatus, { status: "error", message: writeError }),
8462
- /* @__PURE__ */ jsx21(Text22, { color: theme.textMuted, children: "Press r to retry saving." })
8433
+ stepState === "error" && !isComplete && /* @__PURE__ */ jsx20(Text21, { color: theme.status.error, children: "Press r to retry this step." }),
8434
+ isComplete && !writeError && /* @__PURE__ */ jsx20(StepStatus, { status: "verifying", message: "Saving setup..." }),
8435
+ isComplete && writeError && /* @__PURE__ */ jsxs16(Fragment6, { children: [
8436
+ /* @__PURE__ */ jsx20(StepStatus, { status: "error", message: writeError }),
8437
+ /* @__PURE__ */ jsx20(Text21, { color: theme.textMuted, children: "Press r to retry saving." })
8463
8438
  ] })
8464
8439
  ]
8465
8440
  }
@@ -8468,7 +8443,7 @@ function SetupWizard({ onComplete, onThemePreview }) {
8468
8443
 
8469
8444
  // src/app/workflow/WorkflowPicker.tsx
8470
8445
  import { useState as useState15, useCallback as useCallback16, useEffect as useEffect11 } from "react";
8471
- import { Box as Box17, Text as Text23, useInput as useInput14, useStdout as useStdout7 } from "ink";
8446
+ import { Box as Box16, Text as Text22, useInput as useInput14, useStdout as useStdout7 } from "ink";
8472
8447
 
8473
8448
  // src/core/workflows/workflowOptions.ts
8474
8449
  import fs3 from "fs";
@@ -8532,7 +8507,7 @@ function loadWorkflowOptions() {
8532
8507
  }
8533
8508
 
8534
8509
  // src/app/workflow/WorkflowPicker.tsx
8535
- import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
8510
+ import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
8536
8511
  var DEFAULT_WORKFLOW_OPTION = {
8537
8512
  label: "default",
8538
8513
  value: "default",
@@ -8628,22 +8603,22 @@ function WorkflowPicker({
8628
8603
  } else if (phase.type === "error") {
8629
8604
  hints.push("r retry");
8630
8605
  }
8631
- return /* @__PURE__ */ jsx22(
8632
- Box17,
8606
+ return /* @__PURE__ */ jsx21(
8607
+ Box16,
8633
8608
  {
8634
8609
  flexDirection: "column",
8635
8610
  alignItems: "center",
8636
8611
  justifyContent: "center",
8637
8612
  height: rows,
8638
- children: /* @__PURE__ */ jsx22(Box17, { width: frameWidth + 4, children: /* @__PURE__ */ jsxs18(
8613
+ children: /* @__PURE__ */ jsx21(Box16, { width: frameWidth + 4, children: /* @__PURE__ */ jsxs17(
8639
8614
  WizardFrame,
8640
8615
  {
8641
8616
  title: "WORKFLOW",
8642
- header: /* @__PURE__ */ jsx22(Text23, { color: theme.textMuted, children: "Choose a workflow for this project." }),
8643
- footer: /* @__PURE__ */ jsx22(Text23, { color: theme.textMuted, children: hints.join(" ") }),
8617
+ header: /* @__PURE__ */ jsx21(Text22, { color: theme.textMuted, children: "Choose a workflow for this project." }),
8618
+ footer: /* @__PURE__ */ jsx21(Text22, { color: theme.textMuted, children: hints.join(" ") }),
8644
8619
  children: [
8645
- phase.type === "loading" && /* @__PURE__ */ jsx22(StepStatus, { status: "verifying", message: "Loading workflows..." }),
8646
- phase.type === "selecting" && /* @__PURE__ */ jsx22(
8620
+ phase.type === "loading" && /* @__PURE__ */ jsx21(StepStatus, { status: "verifying", message: "Loading workflows..." }),
8621
+ phase.type === "selecting" && /* @__PURE__ */ jsx21(
8647
8622
  StepSelector,
8648
8623
  {
8649
8624
  options: phase.options,
@@ -8651,15 +8626,15 @@ function WorkflowPicker({
8651
8626
  gap: 1
8652
8627
  }
8653
8628
  ),
8654
- phase.type === "installing" && /* @__PURE__ */ jsx22(StepStatus, { status: "verifying", message: "Installing workflow..." }),
8655
- phase.type === "mcp-options" && /* @__PURE__ */ jsx22(
8629
+ phase.type === "installing" && /* @__PURE__ */ jsx21(StepStatus, { status: "verifying", message: "Installing workflow..." }),
8630
+ phase.type === "mcp-options" && /* @__PURE__ */ jsx21(
8656
8631
  McpOptionsStep,
8657
8632
  {
8658
8633
  servers: phase.servers,
8659
8634
  onComplete: handleMcpComplete
8660
8635
  }
8661
8636
  ),
8662
- phase.type === "error" && /* @__PURE__ */ jsx22(Text23, { color: theme.status.error, children: phase.message })
8637
+ phase.type === "error" && /* @__PURE__ */ jsx21(Text22, { color: theme.status.error, children: phase.message })
8663
8638
  ]
8664
8639
  }
8665
8640
  ) })
@@ -8669,58 +8644,8 @@ function WorkflowPicker({
8669
8644
 
8670
8645
  // src/app/modelPreferences/ModelPicker.tsx
8671
8646
  import { useState as useState16, useEffect as useEffect12, useCallback as useCallback17 } from "react";
8672
- import { Box as Box18, Text as Text24, useInput as useInput15, useStdout as useStdout8 } from "ink";
8673
-
8674
- // src/app/modelPreferences/listAvailableModels.ts
8675
- var CLAUDE_MODEL_OPTIONS = [
8676
- {
8677
- value: "sonnet",
8678
- label: "Sonnet",
8679
- description: "Balanced default for day-to-day coding work."
8680
- },
8681
- {
8682
- value: "opus",
8683
- label: "Opus",
8684
- description: "Stronger reasoning for complex architecture and debugging."
8685
- },
8686
- {
8687
- value: "haiku",
8688
- label: "Haiku",
8689
- description: "Fastest option for lighter tasks."
8690
- },
8691
- {
8692
- value: "opusplan",
8693
- label: "OpusPlan",
8694
- description: "Uses Opus for planning and Sonnet for execution."
8695
- }
8696
- ];
8697
- function isCodexRuntimeWithModels(runtime) {
8698
- return Boolean(runtime && "listModels" in runtime);
8699
- }
8700
- async function listAvailableModels(input) {
8701
- switch (input.harness) {
8702
- case "claude-code":
8703
- return CLAUDE_MODEL_OPTIONS;
8704
- case "openai-codex": {
8705
- if (!isCodexRuntimeWithModels(input.runtime)) {
8706
- throw new Error("Codex runtime is not available");
8707
- }
8708
- const models = await input.runtime.listModels();
8709
- return models.map((model) => ({
8710
- value: model.model,
8711
- label: model.displayName,
8712
- description: model.description,
8713
- isDefault: model.isDefault
8714
- }));
8715
- }
8716
- case "opencode":
8717
- default:
8718
- return [];
8719
- }
8720
- }
8721
-
8722
- // src/app/modelPreferences/ModelPicker.tsx
8723
- import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
8647
+ import { Box as Box17, Text as Text23, useInput as useInput15, useStdout as useStdout8 } from "ink";
8648
+ import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
8724
8649
  function ModelPicker({
8725
8650
  projectDir,
8726
8651
  rows,
@@ -8738,7 +8663,7 @@ function ModelPicker({
8738
8663
  const loadModels = useCallback17(() => {
8739
8664
  setPhase({ type: "loading" });
8740
8665
  setTimeout(() => {
8741
- void listAvailableModels({ harness, runtime }).then((options) => {
8666
+ void resolveHarnessAdapter(harness).listModels(runtime).then((options) => {
8742
8667
  if (options.length === 0) {
8743
8668
  setPhase({
8744
8669
  type: "error",
@@ -8786,28 +8711,28 @@ function ModelPicker({
8786
8711
  hints.push("r retry");
8787
8712
  if (onClose) hints.push(`${g["hint.escape"]} close`);
8788
8713
  }
8789
- return /* @__PURE__ */ jsx23(
8790
- Box18,
8714
+ return /* @__PURE__ */ jsx22(
8715
+ Box17,
8791
8716
  {
8792
8717
  flexDirection: "column",
8793
8718
  alignItems: "center",
8794
8719
  justifyContent: "center",
8795
8720
  height: rows,
8796
- children: /* @__PURE__ */ jsx23(Box18, { width: frameWidth + 4, children: /* @__PURE__ */ jsxs19(
8721
+ children: /* @__PURE__ */ jsx22(Box17, { width: frameWidth + 4, children: /* @__PURE__ */ jsxs18(
8797
8722
  WizardFrame,
8798
8723
  {
8799
8724
  title: "MODEL",
8800
- header: /* @__PURE__ */ jsxs19(Box18, { flexDirection: "column", children: [
8801
- /* @__PURE__ */ jsx23(Text24, { color: theme.textMuted, children: "Choose the preferred model for this project." }),
8802
- currentModelName ? /* @__PURE__ */ jsxs19(Text24, { color: theme.textMuted, children: [
8725
+ header: /* @__PURE__ */ jsxs18(Box17, { flexDirection: "column", children: [
8726
+ /* @__PURE__ */ jsx22(Text23, { color: theme.textMuted, children: "Choose the preferred model for this project." }),
8727
+ currentModelName ? /* @__PURE__ */ jsxs18(Text23, { color: theme.textMuted, children: [
8803
8728
  "Current: ",
8804
8729
  currentModelName
8805
8730
  ] }) : null
8806
8731
  ] }),
8807
- footer: /* @__PURE__ */ jsx23(Text24, { color: theme.textMuted, children: hints.join(" ") }),
8732
+ footer: /* @__PURE__ */ jsx22(Text23, { color: theme.textMuted, children: hints.join(" ") }),
8808
8733
  children: [
8809
- phase.type === "loading" && /* @__PURE__ */ jsx23(StepStatus, { status: "verifying", message: "Loading models..." }),
8810
- phase.type === "selecting" && /* @__PURE__ */ jsx23(
8734
+ phase.type === "loading" && /* @__PURE__ */ jsx22(StepStatus, { status: "verifying", message: "Loading models..." }),
8735
+ phase.type === "selecting" && /* @__PURE__ */ jsx22(
8811
8736
  StepSelector,
8812
8737
  {
8813
8738
  options: phase.options.map((option) => ({
@@ -8820,14 +8745,14 @@ function ModelPicker({
8820
8745
  gap: 1
8821
8746
  }
8822
8747
  ),
8823
- phase.type === "saving" && /* @__PURE__ */ jsx23(
8748
+ phase.type === "saving" && /* @__PURE__ */ jsx22(
8824
8749
  StepStatus,
8825
8750
  {
8826
8751
  status: "verifying",
8827
8752
  message: `Saving model preference (${phase.model})...`
8828
8753
  }
8829
8754
  ),
8830
- phase.type === "error" && /* @__PURE__ */ jsx23(Text24, { color: theme.status.error, children: phase.message })
8755
+ phase.type === "error" && /* @__PURE__ */ jsx22(Text23, { color: theme.status.error, children: phase.message })
8831
8756
  ]
8832
8757
  }
8833
8758
  ) })
@@ -9636,7 +9561,7 @@ function toSessionPickerEntries(sessions) {
9636
9561
 
9637
9562
  // src/app/shell/startupDiagnostics.ts
9638
9563
  function shouldTrackStartupDiagnostics(harness) {
9639
- return harness === "claude-code";
9564
+ return resolveHarnessAdapter(harness).capabilities.emitsStartupDiagnostics;
9640
9565
  }
9641
9566
  function createPendingStartupDiagnosticsEvent(args) {
9642
9567
  return {
@@ -9673,6 +9598,20 @@ function deriveStartupTimeoutFailure(args) {
9673
9598
  };
9674
9599
  }
9675
9600
 
9601
+ // src/app/shell/resolveAllowedTools.ts
9602
+ var BASELINE_ALLOWED_TOOLS = ["mcp__*"];
9603
+ function resolveAllowedTools(harness, allowedTools) {
9604
+ const extras = [
9605
+ ...BASELINE_ALLOWED_TOOLS,
9606
+ ...resolveHarnessAdapter(harness).capabilities.extraAllowedTools
9607
+ ];
9608
+ const merged = [...allowedTools ?? []];
9609
+ for (const tool of extras) {
9610
+ if (!merged.includes(tool)) merged.push(tool);
9611
+ }
9612
+ return merged;
9613
+ }
9614
+
9676
9615
  // src/app/shell/channelDispatchCompletion.ts
9677
9616
  function findChannelDispatchReply(feedEvents, afterFeedEventCount) {
9678
9617
  return feedEvents.slice(afterFeedEventCount).reverse().find(
@@ -9712,7 +9651,7 @@ function buildSessionTelemetrySummary(carry, metrics) {
9712
9651
  }
9713
9652
 
9714
9653
  // src/app/shell/AppShell.tsx
9715
- import { Fragment as Fragment8, jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
9654
+ import { Fragment as Fragment7, jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
9716
9655
  var EMPTY_SESSION_METRICS = {
9717
9656
  modelName: null,
9718
9657
  toolCallCount: 0,
@@ -9741,21 +9680,21 @@ function PermissionErrorFallback({ onDeny }) {
9741
9680
  useInput17((_input, key) => {
9742
9681
  if (key.escape) onDeny();
9743
9682
  });
9744
- return /* @__PURE__ */ jsx24(Text25, { color: theme.status.error, children: "[Permission dialog error -- press Escape to deny and continue]" });
9683
+ return /* @__PURE__ */ jsx23(Text24, { color: theme.status.error, children: "[Permission dialog error -- press Escape to deny and continue]" });
9745
9684
  }
9746
9685
  function QuestionErrorFallback({ onSkip }) {
9747
9686
  const theme = useTheme();
9748
9687
  useInput17((_input, key) => {
9749
9688
  if (key.escape) onSkip();
9750
9689
  });
9751
- return /* @__PURE__ */ jsx24(Text25, { color: theme.status.error, children: "[Question dialog error -- press Escape to skip and continue]" });
9690
+ return /* @__PURE__ */ jsx23(Text24, { color: theme.status.error, children: "[Question dialog error -- press Escape to skip and continue]" });
9752
9691
  }
9753
9692
  function DiagnosticsConsentErrorFallback({ onDismiss }) {
9754
9693
  const theme = useTheme();
9755
9694
  useInput17((_input, key) => {
9756
9695
  if (key.escape) onDismiss();
9757
9696
  });
9758
- return /* @__PURE__ */ jsx24(Text25, { color: theme.status.error, children: "[Diagnostics consent dialog error -- press Escape to dismiss]" });
9697
+ return /* @__PURE__ */ jsx23(Text24, { color: theme.status.error, children: "[Diagnostics consent dialog error -- press Escape to dismiss]" });
9759
9698
  }
9760
9699
  var STARTUP_HANDSHAKE_TIMEOUT_MS = 2500;
9761
9700
  function AppContent({
@@ -10799,6 +10738,7 @@ function AppContent({
10799
10738
  sessionTotal: sessionScope.total,
10800
10739
  harness,
10801
10740
  modelName: metrics.modelName ?? modelName,
10741
+ effortLevel: metrics.effortLevel ?? null,
10802
10742
  errorReason: startupFailure?.message
10803
10743
  });
10804
10744
  return renderHeaderLines(headerModel, innerWidth, hasColor, theme)[0];
@@ -10823,6 +10763,7 @@ function AppContent({
10823
10763
  harness,
10824
10764
  modelName,
10825
10765
  metrics.modelName,
10766
+ metrics.effortLevel,
10826
10767
  startupFailure?.message,
10827
10768
  innerWidth,
10828
10769
  hasColor,
@@ -10872,27 +10813,27 @@ function AppContent({
10872
10813
  [withBorderEdges, frameLine]
10873
10814
  );
10874
10815
  if (pagerActive) {
10875
- return /* @__PURE__ */ jsx24(Box19, {});
10816
+ return /* @__PURE__ */ jsx23(Box18, {});
10876
10817
  }
10877
- return /* @__PURE__ */ jsxs20(Box19, { flexDirection: "column", width: frameWidth, children: [
10878
- /* @__PURE__ */ jsx24(
10818
+ return /* @__PURE__ */ jsxs19(Box18, { flexDirection: "column", width: frameWidth, children: [
10819
+ /* @__PURE__ */ jsx23(
10879
10820
  MaybeProfiler,
10880
10821
  {
10881
10822
  enabled: perfEnabled,
10882
10823
  id: "app.main.header-frame",
10883
10824
  onRender: handleSectionProfilerRender,
10884
- children: /* @__PURE__ */ jsx24(Text25, { children: `${border(topBorder)}
10825
+ children: /* @__PURE__ */ jsx23(Text24, { children: `${border(topBorder)}
10885
10826
  ${withBorderEdges(frameLine(headerLine1))}
10886
10827
  ${border(sectionBorder)}` })
10887
10828
  }
10888
10829
  ),
10889
- /* @__PURE__ */ jsx24(
10830
+ /* @__PURE__ */ jsx23(
10890
10831
  MaybeProfiler,
10891
10832
  {
10892
10833
  enabled: perfEnabled,
10893
10834
  id: "app.main.todo-header",
10894
10835
  onRender: handleSectionProfilerRender,
10895
- children: /* @__PURE__ */ jsx24(
10836
+ children: /* @__PURE__ */ jsx23(
10896
10837
  TodoHeaderSection,
10897
10838
  {
10898
10839
  actualTodoRows,
@@ -10910,13 +10851,13 @@ ${border(sectionBorder)}` })
10910
10851
  )
10911
10852
  }
10912
10853
  ),
10913
- /* @__PURE__ */ jsx24(
10854
+ /* @__PURE__ */ jsx23(
10914
10855
  MaybeProfiler,
10915
10856
  {
10916
10857
  enabled: perfEnabled,
10917
10858
  id: "app.main.body-prefix",
10918
10859
  onRender: handleSectionProfilerRender,
10919
- children: /* @__PURE__ */ jsx24(
10860
+ children: /* @__PURE__ */ jsx23(
10920
10861
  TodoBodySection,
10921
10862
  {
10922
10863
  innerWidth,
@@ -10943,13 +10884,13 @@ ${border(sectionBorder)}` })
10943
10884
  )
10944
10885
  }
10945
10886
  ),
10946
- /* @__PURE__ */ jsx24(
10887
+ /* @__PURE__ */ jsx23(
10947
10888
  MaybeProfiler,
10948
10889
  {
10949
10890
  enabled: perfEnabled,
10950
10891
  id: "app.main.feed",
10951
10892
  onRender: handleSectionProfilerRender,
10952
- children: workflowPickerVisible ? /* @__PURE__ */ jsx24(
10893
+ children: workflowPickerVisible ? /* @__PURE__ */ jsx23(
10953
10894
  WorkflowPicker,
10954
10895
  {
10955
10896
  projectDir,
@@ -10960,7 +10901,7 @@ ${border(sectionBorder)}` })
10960
10901
  onWorkflowSelected(name);
10961
10902
  }
10962
10903
  }
10963
- ) : modelPickerVisible ? /* @__PURE__ */ jsx24(
10904
+ ) : modelPickerVisible ? /* @__PURE__ */ jsx23(
10964
10905
  ModelPicker,
10965
10906
  {
10966
10907
  projectDir,
@@ -10974,8 +10915,8 @@ ${border(sectionBorder)}` })
10974
10915
  onModelSelected(selectedModel);
10975
10916
  }
10976
10917
  }
10977
- ) : splitMode ? /* @__PURE__ */ jsxs20(Box19, { flexDirection: "row", children: [
10978
- /* @__PURE__ */ jsx24(Box19, { width: messagePanelWidth + 1, flexShrink: 0, children: /* @__PURE__ */ jsx24(
10918
+ ) : splitMode ? /* @__PURE__ */ jsxs19(Box18, { flexDirection: "row", children: [
10919
+ /* @__PURE__ */ jsx23(Box18, { width: messagePanelWidth + 1, flexShrink: 0, children: /* @__PURE__ */ jsx23(
10979
10920
  MessagePanel,
10980
10921
  {
10981
10922
  entries: messageEntries,
@@ -10987,7 +10928,7 @@ ${border(sectionBorder)}` })
10987
10928
  borderColor: theme.border
10988
10929
  }
10989
10930
  ) }),
10990
- /* @__PURE__ */ jsx24(Box19, { flexGrow: 1, children: /* @__PURE__ */ jsx24(
10931
+ /* @__PURE__ */ jsx23(Box18, { flexGrow: 1, children: /* @__PURE__ */ jsx23(
10991
10932
  FeedGrid,
10992
10933
  {
10993
10934
  feedHeaderRows,
@@ -11007,7 +10948,7 @@ ${border(sectionBorder)}` })
11007
10948
  onboarding: feedOnboarding
11008
10949
  }
11009
10950
  ) })
11010
- ] }) : /* @__PURE__ */ jsx24(
10951
+ ] }) : /* @__PURE__ */ jsx23(
11011
10952
  FeedGrid,
11012
10953
  {
11013
10954
  feedHeaderRows,
@@ -11029,13 +10970,13 @@ ${border(sectionBorder)}` })
11029
10970
  )
11030
10971
  }
11031
10972
  ),
11032
- /* @__PURE__ */ jsx24(
10973
+ /* @__PURE__ */ jsx23(
11033
10974
  MaybeProfiler,
11034
10975
  {
11035
10976
  enabled: perfEnabled,
11036
10977
  id: "app.main.input",
11037
10978
  onRender: handleSectionProfilerRender,
11038
- children: /* @__PURE__ */ jsx24(
10979
+ children: /* @__PURE__ */ jsx23(
11039
10980
  InputSection,
11040
10981
  {
11041
10982
  innerWidth,
@@ -11065,13 +11006,13 @@ ${border(sectionBorder)}` })
11065
11006
  )
11066
11007
  }
11067
11008
  ),
11068
- /* @__PURE__ */ jsx24(
11009
+ /* @__PURE__ */ jsx23(
11069
11010
  MaybeProfiler,
11070
11011
  {
11071
11012
  enabled: perfEnabled,
11072
11013
  id: "app.main.footer",
11073
11014
  onRender: handleSectionProfilerRender,
11074
- children: /* @__PURE__ */ jsx24(
11015
+ children: /* @__PURE__ */ jsx23(
11075
11016
  FooterSection,
11076
11017
  {
11077
11018
  frameFooterHelp: frame.footerHelp,
@@ -11082,22 +11023,22 @@ ${border(sectionBorder)}` })
11082
11023
  )
11083
11024
  }
11084
11025
  ),
11085
- /* @__PURE__ */ jsx24(
11026
+ /* @__PURE__ */ jsx23(
11086
11027
  MaybeProfiler,
11087
11028
  {
11088
11029
  enabled: perfEnabled,
11089
11030
  id: "app.main.diagnostics-dialog",
11090
11031
  onRender: handleSectionProfilerRender,
11091
- children: /* @__PURE__ */ jsx24(Fragment8, { children: pendingStartupDiagnostics && /* @__PURE__ */ jsx24(
11032
+ children: /* @__PURE__ */ jsx23(Fragment7, { children: pendingStartupDiagnostics && /* @__PURE__ */ jsx23(
11092
11033
  ErrorBoundary,
11093
11034
  {
11094
- fallback: /* @__PURE__ */ jsx24(
11035
+ fallback: /* @__PURE__ */ jsx23(
11095
11036
  DiagnosticsConsentErrorFallback,
11096
11037
  {
11097
11038
  onDismiss: () => setPendingStartupDiagnostics(null)
11098
11039
  }
11099
11040
  ),
11100
- children: /* @__PURE__ */ jsx24(
11041
+ children: /* @__PURE__ */ jsx23(
11101
11042
  DiagnosticsConsentDialog,
11102
11043
  {
11103
11044
  harnessLabel,
@@ -11108,22 +11049,22 @@ ${border(sectionBorder)}` })
11108
11049
  ) })
11109
11050
  }
11110
11051
  ),
11111
- /* @__PURE__ */ jsx24(
11052
+ /* @__PURE__ */ jsx23(
11112
11053
  MaybeProfiler,
11113
11054
  {
11114
11055
  enabled: perfEnabled,
11115
11056
  id: "app.main.permission-dialog",
11116
11057
  onRender: handleSectionProfilerRender,
11117
- children: /* @__PURE__ */ jsx24(Fragment8, { children: appMode.type === "permission" && currentPermissionRequest && /* @__PURE__ */ jsx24(
11058
+ children: /* @__PURE__ */ jsx23(Fragment7, { children: appMode.type === "permission" && currentPermissionRequest && /* @__PURE__ */ jsx23(
11118
11059
  ErrorBoundary,
11119
11060
  {
11120
- fallback: /* @__PURE__ */ jsx24(
11061
+ fallback: /* @__PURE__ */ jsx23(
11121
11062
  PermissionErrorFallback,
11122
11063
  {
11123
11064
  onDeny: () => handlePermissionDecision("deny")
11124
11065
  }
11125
11066
  ),
11126
- children: /* @__PURE__ */ jsx24(
11067
+ children: /* @__PURE__ */ jsx23(
11127
11068
  PermissionDialog,
11128
11069
  {
11129
11070
  request: currentPermissionRequest,
@@ -11135,17 +11076,17 @@ ${border(sectionBorder)}` })
11135
11076
  ) })
11136
11077
  }
11137
11078
  ),
11138
- /* @__PURE__ */ jsx24(
11079
+ /* @__PURE__ */ jsx23(
11139
11080
  MaybeProfiler,
11140
11081
  {
11141
11082
  enabled: perfEnabled,
11142
11083
  id: "app.main.question-dialog",
11143
11084
  onRender: handleSectionProfilerRender,
11144
- children: /* @__PURE__ */ jsx24(Fragment8, { children: appMode.type === "question" && currentQuestionRequest && /* @__PURE__ */ jsx24(
11085
+ children: /* @__PURE__ */ jsx23(Fragment7, { children: appMode.type === "question" && currentQuestionRequest && /* @__PURE__ */ jsx23(
11145
11086
  ErrorBoundary,
11146
11087
  {
11147
- fallback: /* @__PURE__ */ jsx24(QuestionErrorFallback, { onSkip: handleQuestionSkip }),
11148
- children: /* @__PURE__ */ jsx24(
11088
+ fallback: /* @__PURE__ */ jsx23(QuestionErrorFallback, { onSkip: handleQuestionSkip }),
11089
+ children: /* @__PURE__ */ jsx23(
11149
11090
  QuestionDialog,
11150
11091
  {
11151
11092
  request: currentQuestionRequest,
@@ -11166,10 +11107,10 @@ function MaybeProfiler({
11166
11107
  onRender,
11167
11108
  children
11168
11109
  }) {
11169
- if (!enabled) return /* @__PURE__ */ jsx24(Fragment8, { children });
11170
- return /* @__PURE__ */ jsx24(Profiler, { id, onRender, children });
11110
+ if (!enabled) return /* @__PURE__ */ jsx23(Fragment7, { children });
11111
+ return /* @__PURE__ */ jsx23(Profiler, { id, onRender, children });
11171
11112
  }
11172
- var TodoHeaderSection = React9.memo(function TodoHeaderSection2({
11113
+ var TodoHeaderSection = React8.memo(function TodoHeaderSection2({
11173
11114
  actualTodoRows,
11174
11115
  innerWidth,
11175
11116
  useAscii,
@@ -11208,9 +11149,9 @@ var TodoHeaderSection = React9.memo(function TodoHeaderSection2({
11208
11149
  theme
11209
11150
  ]
11210
11151
  );
11211
- return /* @__PURE__ */ jsx24(Fragment8, { children: todoHeaderLine !== null && /* @__PURE__ */ jsx24(Text25, { children: withBorderEdges(frameLine(todoHeaderLine)) }, "todo-header") });
11152
+ return /* @__PURE__ */ jsx23(Fragment7, { children: todoHeaderLine !== null && /* @__PURE__ */ jsx23(Text24, { children: withBorderEdges(frameLine(todoHeaderLine)) }, "todo-header") });
11212
11153
  });
11213
- var TodoBodySection = React9.memo(function TodoBodySection2({
11154
+ var TodoBodySection = React8.memo(function TodoBodySection2({
11214
11155
  innerWidth,
11215
11156
  actualTodoRows,
11216
11157
  todoScroll,
@@ -11297,9 +11238,9 @@ var TodoBodySection = React9.memo(function TodoBodySection2({
11297
11238
  ]
11298
11239
  );
11299
11240
  if (output === null) return null;
11300
- return /* @__PURE__ */ jsx24(Text25, { children: output });
11241
+ return /* @__PURE__ */ jsx23(Text24, { children: output });
11301
11242
  });
11302
- var FooterSection = React9.memo(function FooterSection2({
11243
+ var FooterSection = React8.memo(function FooterSection2({
11303
11244
  frameFooterHelp,
11304
11245
  toastMessage,
11305
11246
  hintTextColor,
@@ -11311,9 +11252,9 @@ var FooterSection = React9.memo(function FooterSection2({
11311
11252
  return fit(hint, innerWidth);
11312
11253
  }, [frameFooterHelp, toastMessage, hintTextColor, innerWidth]);
11313
11254
  if (output === null) return null;
11314
- return /* @__PURE__ */ jsx24(Text25, { children: output });
11255
+ return /* @__PURE__ */ jsx23(Text24, { children: output });
11315
11256
  });
11316
- var InputSection = React9.memo(function InputSection2({
11257
+ var InputSection = React8.memo(function InputSection2({
11317
11258
  innerWidth,
11318
11259
  useAscii,
11319
11260
  borderColor,
@@ -11338,7 +11279,7 @@ var InputSection = React9.memo(function InputSection2({
11338
11279
  topBorder,
11339
11280
  bottomBorder
11340
11281
  }) {
11341
- return /* @__PURE__ */ jsx24(
11282
+ return /* @__PURE__ */ jsx23(
11342
11283
  ShellInput2,
11343
11284
  {
11344
11285
  ref: inputRef,
@@ -11547,13 +11488,13 @@ function App({
11547
11488
  refreshRuntime();
11548
11489
  }, [refreshRuntime]);
11549
11490
  if (phase.type === "setup") {
11550
- return /* @__PURE__ */ jsx24(
11491
+ return /* @__PURE__ */ jsx23(
11551
11492
  MaybeProfiler,
11552
11493
  {
11553
11494
  enabled: perfEnabled,
11554
11495
  id: "app.setup",
11555
11496
  onRender: handleProfilerRender,
11556
- children: /* @__PURE__ */ jsx24(ThemeProvider, { value: activeTheme, children: /* @__PURE__ */ jsx24(
11497
+ children: /* @__PURE__ */ jsx23(ThemeProvider, { value: activeTheme, children: /* @__PURE__ */ jsx23(
11557
11498
  SetupWizard,
11558
11499
  {
11559
11500
  onThemePreview: (themeName) => {
@@ -11566,17 +11507,17 @@ function App({
11566
11507
  );
11567
11508
  }
11568
11509
  if (phase.type === "session-select") {
11569
- return /* @__PURE__ */ jsx24(
11510
+ return /* @__PURE__ */ jsx23(
11570
11511
  MaybeProfiler,
11571
11512
  {
11572
11513
  enabled: perfEnabled,
11573
11514
  id: "app.session-select",
11574
11515
  onRender: handleProfilerRender,
11575
- children: /* @__PURE__ */ jsx24(
11516
+ children: /* @__PURE__ */ jsx23(
11576
11517
  ErrorBoundary,
11577
11518
  {
11578
- fallback: /* @__PURE__ */ jsx24(Text25, { color: "red", children: "[Session picker error -- starting new session]" }),
11579
- children: /* @__PURE__ */ jsx24(
11519
+ fallback: /* @__PURE__ */ jsx23(Text24, { color: "red", children: "[Session picker error -- starting new session]" }),
11520
+ children: /* @__PURE__ */ jsx23(
11580
11521
  SessionPicker,
11581
11522
  {
11582
11523
  sessions,
@@ -11590,7 +11531,7 @@ function App({
11590
11531
  }
11591
11532
  );
11592
11533
  }
11593
- return /* @__PURE__ */ jsx24(ThemeProvider, { value: activeTheme, children: /* @__PURE__ */ jsx24(
11534
+ return /* @__PURE__ */ jsx23(ThemeProvider, { value: activeTheme, children: /* @__PURE__ */ jsx23(
11594
11535
  HookProvider,
11595
11536
  {
11596
11537
  projectDir,
@@ -11603,7 +11544,7 @@ function App({
11603
11544
  ),
11604
11545
  athenaSessionId,
11605
11546
  ...attachmentId !== void 0 ? { attachmentId } : {},
11606
- children: /* @__PURE__ */ jsx24(
11547
+ children: /* @__PURE__ */ jsx23(
11607
11548
  AppContent,
11608
11549
  {
11609
11550
  projectDir,
@@ -11639,15 +11580,6 @@ function App({
11639
11580
  }
11640
11581
  ) });
11641
11582
  }
11642
- function resolveAllowedTools(harness, allowedTools) {
11643
- const extras = harness === "openai-codex" ? ["mcp__*", "Permissions", "Bash", "Edit"] : ["mcp__*"];
11644
- const base = allowedTools ?? [];
11645
- const merged = [...base];
11646
- for (const tool of extras) {
11647
- if (!merged.includes(tool)) merged.push(tool);
11648
- }
11649
- return merged;
11650
- }
11651
11583
  function usePerfRenderLog(enabled, id) {
11652
11584
  const renderCountRef = useRef16(0);
11653
11585
  renderCountRef.current += 1;
@@ -11943,44 +11875,62 @@ function shouldShowSetup({
11943
11875
  }
11944
11876
 
11945
11877
  // src/app/entry/execCommand.ts
11878
+ import crypto2 from "crypto";
11879
+
11880
+ // src/app/entry/resumeResolution.ts
11946
11881
  import crypto from "crypto";
11947
- function isValidTimeout(timeoutMs) {
11948
- if (timeoutMs === void 0) return true;
11949
- return Number.isFinite(timeoutMs) && timeoutMs > 0;
11950
- }
11951
- function resolveContinueFlag(input) {
11952
- if (input.continueFlag === void 0) {
11882
+ function resolveResumeTarget(input) {
11883
+ const createSessionId = input.createSessionId ?? crypto.randomUUID;
11884
+ const getSessionMetaFn = input.getSessionMetaFn ?? getSessionMeta;
11885
+ const getMostRecentSessionFn = input.getMostRecentSessionFn ?? getMostRecentAthenaSession;
11886
+ const { request } = input;
11887
+ if (request.kind === "fresh") {
11953
11888
  return {
11954
- athenaSessionId: input.createSessionId(),
11889
+ athenaSessionId: createSessionId(),
11955
11890
  adapterResumeSessionId: void 0
11956
11891
  };
11957
11892
  }
11958
- if (input.continueFlag === "") {
11959
- const recent = input.getMostRecentSessionFn(input.projectDir);
11960
- if (!recent) {
11961
- input.logError(
11962
- "Error: --continue was provided but no previous Athena sessions exist for this project."
11963
- );
11893
+ if (request.kind === "explicit") {
11894
+ const meta = getSessionMetaFn(request.sessionId);
11895
+ if (!meta) {
11896
+ input.logError(input.messages.unknownExplicit(request.sessionId));
11964
11897
  return void 0;
11965
11898
  }
11966
11899
  return {
11967
- athenaSessionId: recent.id,
11968
- adapterResumeSessionId: recent.adapterSessionIds.at(-1)
11900
+ athenaSessionId: meta.id,
11901
+ adapterResumeSessionId: meta.adapterSessionIds.at(-1)
11969
11902
  };
11970
11903
  }
11971
- const meta = input.getSessionMetaFn(input.continueFlag);
11972
- if (!meta) {
11973
- input.logError(`Error: Unknown Athena session ID: ${input.continueFlag}`);
11904
+ const recent = getMostRecentSessionFn(input.projectDir);
11905
+ if (!recent) {
11906
+ input.logError(input.messages.missingRecent);
11907
+ if (input.missingRecentPolicy === "fresh") {
11908
+ return {
11909
+ athenaSessionId: createSessionId(),
11910
+ adapterResumeSessionId: void 0
11911
+ };
11912
+ }
11974
11913
  return void 0;
11975
11914
  }
11976
11915
  return {
11977
- athenaSessionId: meta.id,
11978
- adapterResumeSessionId: meta.adapterSessionIds.at(-1)
11916
+ athenaSessionId: recent.id,
11917
+ adapterResumeSessionId: recent.adapterSessionIds.at(-1)
11979
11918
  };
11980
11919
  }
11920
+
11921
+ // src/app/entry/execCommand.ts
11922
+ function isValidTimeout(timeoutMs) {
11923
+ if (timeoutMs === void 0) return true;
11924
+ return Number.isFinite(timeoutMs) && timeoutMs > 0;
11925
+ }
11926
+ function continueFlagToRequest(continueFlag) {
11927
+ if (continueFlag === void 0) return { kind: "fresh" };
11928
+ if (continueFlag === "") return { kind: "most-recent" };
11929
+ return { kind: "explicit", sessionId: continueFlag };
11930
+ }
11981
11931
  async function runExecCommand(input, deps = {}) {
11982
11932
  const logError = deps.logError ?? console.error;
11983
- const createSessionId = deps.createSessionId ?? crypto.randomUUID;
11933
+ const createSessionId = deps.createSessionId ?? crypto2.randomUUID;
11984
11934
  const runExecFn = deps.runExecFn ?? runExec;
11985
11935
  const getMostRecentSessionFn = deps.getMostRecentSessionFn ?? getMostRecentAthenaSession;
11986
11936
  const getSessionMetaFn = deps.getSessionMetaFn ?? getSessionMeta;
@@ -11994,9 +11944,17 @@ async function runExecCommand(input, deps = {}) {
11994
11944
  }
11995
11945
  let continueResolution;
11996
11946
  try {
11997
- continueResolution = resolveContinueFlag({
11947
+ continueResolution = resolveResumeTarget({
11998
11948
  projectDir: input.projectDir,
11999
- continueFlag: input.flags.continueFlag,
11949
+ request: continueFlagToRequest(input.flags.continueFlag),
11950
+ // Headless exec treats a missing resume target as a hard error rather
11951
+ // than silently starting fresh, so a resume request that finds nothing
11952
+ // exits non-zero for callers/scripts.
11953
+ missingRecentPolicy: "error",
11954
+ messages: {
11955
+ unknownExplicit: (sessionId) => `Error: Unknown Athena session ID: ${sessionId}`,
11956
+ missingRecent: "Error: --continue was provided but no previous Athena sessions exist for this project."
11957
+ },
12000
11958
  createSessionId,
12001
11959
  getMostRecentSessionFn,
12002
11960
  getSessionMetaFn,
@@ -12026,49 +11984,61 @@ async function runExecCommand(input, deps = {}) {
12026
11984
  outputLastMessagePath: input.flags.outputLastMessage,
12027
11985
  ephemeral: input.flags.ephemeral,
12028
11986
  timeoutMs: input.flags.timeoutMs,
12029
- channels: input.flags.channels
11987
+ channels: input.flags.channels,
11988
+ // Reporting-only summary: strip to name + source layer so secret-bearing
11989
+ // MCP env/command/args and skill paths never reach the startup notice or
11990
+ // the exec.started event (R3).
11991
+ personalCapabilities: {
11992
+ mcpServers: input.runtimeConfig.personalMcpServers.map((server) => ({
11993
+ name: server.name,
11994
+ sourceLayer: server.sourceLayer
11995
+ })),
11996
+ skills: input.runtimeConfig.personalSkills.map((skill) => ({
11997
+ name: skill.name,
11998
+ sourceLayer: skill.sourceLayer
11999
+ }))
12000
+ },
12001
+ // Same strip for shadowed (conflicting) capabilities — name + source
12002
+ // layer only, never the personal MCP env/command/args or skill path (R7).
12003
+ capabilityConflicts: {
12004
+ mcpServers: input.runtimeConfig.capabilityConflicts.mcpServers.map(
12005
+ (server) => ({
12006
+ name: server.name,
12007
+ sourceLayer: server.sourceLayer
12008
+ })
12009
+ ),
12010
+ skills: input.runtimeConfig.capabilityConflicts.skills.map((skill) => ({
12011
+ name: skill.name,
12012
+ sourceLayer: skill.sourceLayer
12013
+ }))
12014
+ }
12030
12015
  });
12031
12016
  return result.exitCode;
12032
12017
  }
12033
12018
 
12034
12019
  // src/app/entry/interactiveSession.ts
12035
- import crypto2 from "crypto";
12036
12020
  function resolveInteractiveSession(input) {
12037
- const logError = input.logError ?? console.error;
12038
- const createSessionId = input.createSessionId ?? crypto2.randomUUID;
12039
- const getSessionMetaFn = input.getSessionMetaFn ?? getSessionMeta;
12040
- const getMostRecentSessionFn = input.getMostRecentSessionFn ?? getMostRecentAthenaSession;
12041
- if (input.resumeSessionId) {
12042
- const meta = getSessionMetaFn(input.resumeSessionId);
12043
- if (!meta) {
12044
- logError(
12045
- `Unknown session ID: ${input.resumeSessionId}
12046
- Use 'athena-flow sessions' to choose an available session.`
12047
- );
12048
- return void 0;
12049
- }
12050
- return {
12051
- athenaSessionId: meta.id,
12052
- initialSessionId: meta.adapterSessionIds.at(-1)
12053
- };
12054
- }
12055
- if (input.resumeMostRecent) {
12056
- const recent = getMostRecentSessionFn(input.projectDir);
12057
- if (!recent) {
12058
- logError("No previous sessions found. Starting new session.");
12059
- return {
12060
- athenaSessionId: createSessionId(),
12061
- initialSessionId: void 0
12062
- };
12063
- }
12064
- return {
12065
- athenaSessionId: recent.id,
12066
- initialSessionId: recent.adapterSessionIds.at(-1)
12067
- };
12068
- }
12021
+ const request = input.resumeSessionId ? { kind: "explicit", sessionId: input.resumeSessionId } : input.resumeMostRecent ? { kind: "most-recent" } : { kind: "fresh" };
12022
+ const target = resolveResumeTarget({
12023
+ projectDir: input.projectDir,
12024
+ request,
12025
+ // Interactive falls back to a fresh session when resume-most-recent finds
12026
+ // no history — the terminal stays usable rather than exiting.
12027
+ missingRecentPolicy: "fresh",
12028
+ messages: {
12029
+ unknownExplicit: (sessionId) => `Unknown session ID: ${sessionId}
12030
+ Use 'athena-flow sessions' to choose an available session.`,
12031
+ missingRecent: "No previous sessions found. Starting new session."
12032
+ },
12033
+ logError: input.logError ?? console.error,
12034
+ ...input.createSessionId ? { createSessionId: input.createSessionId } : {},
12035
+ ...input.getSessionMetaFn ? { getSessionMetaFn: input.getSessionMetaFn } : {},
12036
+ ...input.getMostRecentSessionFn ? { getMostRecentSessionFn: input.getMostRecentSessionFn } : {}
12037
+ });
12038
+ if (!target) return void 0;
12069
12039
  return {
12070
- athenaSessionId: createSessionId(),
12071
- initialSessionId: void 0
12040
+ athenaSessionId: target.athenaSessionId,
12041
+ initialSessionId: target.adapterResumeSessionId
12072
12042
  };
12073
12043
  }
12074
12044
 
@@ -12338,6 +12308,27 @@ function runWorkflowCommand(input, deps = {}) {
12338
12308
  ` note: project config overrides global at ${projectConfigPath(input.projectDir)}`
12339
12309
  );
12340
12310
  }
12311
+ const { mcpServers, skills } = resolveEffectiveCapabilities({
12312
+ globalConfig,
12313
+ projectConfig
12314
+ });
12315
+ if (mcpServers.length === 0 && skills.length === 0) {
12316
+ logOut("Personal capabilities: none configured");
12317
+ } else {
12318
+ logOut("Personal capabilities:");
12319
+ if (mcpServers.length > 0) {
12320
+ logOut(" MCP servers:");
12321
+ for (const server of mcpServers) {
12322
+ logOut(` ${server.name} [${server.sourceLayer}]`);
12323
+ }
12324
+ }
12325
+ if (skills.length > 0) {
12326
+ logOut(" Skills:");
12327
+ for (const skill of skills) {
12328
+ logOut(` ${skill.name} [${skill.sourceLayer}]`);
12329
+ }
12330
+ }
12331
+ }
12341
12332
  return 0;
12342
12333
  }
12343
12334
  default:
@@ -12346,6 +12337,343 @@ function runWorkflowCommand(input, deps = {}) {
12346
12337
  }
12347
12338
  }
12348
12339
 
12340
+ // src/app/entry/mcpCommand.ts
12341
+ function parseArgs(args, context) {
12342
+ let project = false;
12343
+ let global = false;
12344
+ const env2 = [];
12345
+ const positional = [];
12346
+ for (let i = 0; i < args.length; i++) {
12347
+ const arg = args[i];
12348
+ if (arg === "--project") {
12349
+ project = true;
12350
+ } else if (arg === "--global") {
12351
+ global = true;
12352
+ } else if (arg === "--env") {
12353
+ const value = args[i + 1];
12354
+ if (value === void 0) {
12355
+ return { error: `mcp ${context}: --env requires a KEY=VALUE argument` };
12356
+ }
12357
+ env2.push(value);
12358
+ i++;
12359
+ } else if (arg.startsWith("--")) {
12360
+ return { error: `Unknown flag for mcp ${context}: ${arg}` };
12361
+ } else {
12362
+ positional.push(arg);
12363
+ }
12364
+ }
12365
+ if (project && global) {
12366
+ return {
12367
+ error: `mcp ${context}: --project and --global are mutually exclusive`
12368
+ };
12369
+ }
12370
+ return { project, global, env: env2, positional };
12371
+ }
12372
+ function parseEnv(entries) {
12373
+ const env2 = {};
12374
+ for (const entry of entries) {
12375
+ const eq = entry.indexOf("=");
12376
+ if (eq <= 0) {
12377
+ return { error: `Invalid --env value (expected KEY=VALUE): ${entry}` };
12378
+ }
12379
+ env2[entry.slice(0, eq)] = entry.slice(eq + 1);
12380
+ }
12381
+ return env2;
12382
+ }
12383
+ function runMcpCommand(input, deps = {}) {
12384
+ const readGlobal = deps.readGlobalConfig ?? readGlobalConfig;
12385
+ const readProject = deps.readProjectConfig ?? readConfig;
12386
+ const writeGlobal = deps.writeGlobalConfig ?? writeGlobalConfig;
12387
+ const writeProject = deps.writeProjectConfig ?? writeProjectConfig;
12388
+ const logError = deps.logError ?? console.error;
12389
+ const logOut = deps.logOut ?? console.log;
12390
+ const { subcommand } = input;
12391
+ if (subcommand === "add") {
12392
+ const parsed = parseArgs(input.subcommandArgs, "add");
12393
+ if ("error" in parsed) {
12394
+ logError(parsed.error);
12395
+ return 1;
12396
+ }
12397
+ const name = parsed.positional[0];
12398
+ if (!name) {
12399
+ logError("mcp add: missing server name");
12400
+ return 1;
12401
+ }
12402
+ const [command, ...args] = input.serverCommandTokens;
12403
+ if (!command) {
12404
+ logError(
12405
+ `mcp add: missing server command. Usage: mcp add ${name} -- <command> [args...]`
12406
+ );
12407
+ return 1;
12408
+ }
12409
+ const envResult = parseEnv(parsed.env);
12410
+ if ("error" in envResult) {
12411
+ logError(envResult.error);
12412
+ return 1;
12413
+ }
12414
+ const server = { command };
12415
+ if (args.length > 0) {
12416
+ server.args = args;
12417
+ }
12418
+ if (Object.keys(envResult).length > 0) {
12419
+ server.env = envResult;
12420
+ }
12421
+ const layer = parsed.project ? "project" : "global";
12422
+ const existing = (layer === "project" ? readProject(input.projectDir).mcpServers : readGlobal().mcpServers) ?? {};
12423
+ const overwriting = name in existing;
12424
+ const merged = { ...existing, [name]: server };
12425
+ if (layer === "project") {
12426
+ writeProject(input.projectDir, { mcpServers: merged });
12427
+ } else {
12428
+ writeGlobal({ mcpServers: merged });
12429
+ }
12430
+ logOut(
12431
+ `${overwriting ? "Overwrote" : "Added"} personal MCP server '${name}' [${layer}]`
12432
+ );
12433
+ return 0;
12434
+ }
12435
+ if (subcommand === "list") {
12436
+ const parsed = parseArgs(input.subcommandArgs, "list");
12437
+ if ("error" in parsed) {
12438
+ logError(parsed.error);
12439
+ return 1;
12440
+ }
12441
+ const listSingleLayer = (servers, label) => {
12442
+ const names = Object.keys(servers);
12443
+ if (names.length === 0) {
12444
+ logOut(`No personal MCP servers configured (${label}).`);
12445
+ return;
12446
+ }
12447
+ logOut(`Personal MCP servers (${label}):`);
12448
+ for (const name of names) {
12449
+ logOut(` ${name} ${servers[name].command}`);
12450
+ }
12451
+ };
12452
+ if (parsed.global) {
12453
+ listSingleLayer(readGlobal().mcpServers ?? {}, "global");
12454
+ return 0;
12455
+ }
12456
+ if (parsed.project) {
12457
+ listSingleLayer(
12458
+ readProject(input.projectDir).mcpServers ?? {},
12459
+ "project"
12460
+ );
12461
+ return 0;
12462
+ }
12463
+ const { mcpServers } = resolveEffectiveCapabilities({
12464
+ globalConfig: readGlobal(),
12465
+ projectConfig: readProject(input.projectDir)
12466
+ });
12467
+ if (mcpServers.length === 0) {
12468
+ logOut("No personal MCP servers configured.");
12469
+ return 0;
12470
+ }
12471
+ logOut("Personal MCP servers (effective):");
12472
+ for (const server of mcpServers) {
12473
+ logOut(` ${server.name} ${server.command} [${server.sourceLayer}]`);
12474
+ }
12475
+ return 0;
12476
+ }
12477
+ if (subcommand === "remove") {
12478
+ const parsed = parseArgs(input.subcommandArgs, "remove");
12479
+ if ("error" in parsed) {
12480
+ logError(parsed.error);
12481
+ return 1;
12482
+ }
12483
+ const name = parsed.positional[0];
12484
+ if (!name) {
12485
+ logError("mcp remove: missing server name");
12486
+ return 1;
12487
+ }
12488
+ const layer = parsed.project ? "project" : "global";
12489
+ const existing = (layer === "project" ? readProject(input.projectDir).mcpServers : readGlobal().mcpServers) ?? {};
12490
+ if (!(name in existing)) {
12491
+ logError(
12492
+ `mcp remove: no personal MCP server '${name}' found in ${layer} config`
12493
+ );
12494
+ return 1;
12495
+ }
12496
+ const next = { ...existing };
12497
+ delete next[name];
12498
+ if (layer === "project") {
12499
+ writeProject(input.projectDir, { mcpServers: next });
12500
+ } else {
12501
+ writeGlobal({ mcpServers: next });
12502
+ }
12503
+ logOut(`Removed personal MCP server '${name}' [${layer}]`);
12504
+ return 0;
12505
+ }
12506
+ logError(`Unknown mcp subcommand: ${subcommand}`);
12507
+ return 1;
12508
+ }
12509
+
12510
+ // src/app/entry/skillCommand.ts
12511
+ import fs4 from "fs";
12512
+ import path4 from "path";
12513
+ function resolvePersonalSkill(ref, projectDir) {
12514
+ const absPath = path4.isAbsolute(ref) ? ref : path4.resolve(projectDir, ref);
12515
+ if (!fs4.existsSync(absPath)) {
12516
+ return { error: `skill install: path not found: ${ref}` };
12517
+ }
12518
+ let skillDir;
12519
+ let skillMdPath;
12520
+ if (fs4.statSync(absPath).isDirectory()) {
12521
+ skillDir = absPath;
12522
+ skillMdPath = path4.join(absPath, "SKILL.md");
12523
+ } else if (path4.basename(absPath) === "SKILL.md") {
12524
+ skillDir = path4.dirname(absPath);
12525
+ skillMdPath = absPath;
12526
+ } else {
12527
+ return {
12528
+ error: `skill install: expected a directory containing SKILL.md or a SKILL.md file: ${ref}`
12529
+ };
12530
+ }
12531
+ if (!fs4.existsSync(skillMdPath)) {
12532
+ return { error: `skill install: no SKILL.md found at ${skillDir}` };
12533
+ }
12534
+ try {
12535
+ const { frontmatter } = parseFrontmatter(
12536
+ fs4.readFileSync(skillMdPath, "utf-8")
12537
+ );
12538
+ return { name: frontmatter.name, source: ref, path: skillDir };
12539
+ } catch (error) {
12540
+ const message = error instanceof Error ? error.message : String(error);
12541
+ return { error: `skill install: invalid SKILL.md (${message})` };
12542
+ }
12543
+ }
12544
+ function parseArgs2(args, context) {
12545
+ let project = false;
12546
+ let global = false;
12547
+ const positional = [];
12548
+ for (const arg of args) {
12549
+ if (arg === "--project") {
12550
+ project = true;
12551
+ } else if (arg === "--global") {
12552
+ global = true;
12553
+ } else if (arg.startsWith("--")) {
12554
+ return { error: `Unknown flag for skill ${context}: ${arg}` };
12555
+ } else {
12556
+ positional.push(arg);
12557
+ }
12558
+ }
12559
+ if (project && global) {
12560
+ return {
12561
+ error: `skill ${context}: --project and --global are mutually exclusive`
12562
+ };
12563
+ }
12564
+ return { project, global, positional };
12565
+ }
12566
+ function runSkillCommand(input, deps = {}) {
12567
+ const readGlobal = deps.readGlobalConfig ?? readGlobalConfig;
12568
+ const readProject = deps.readProjectConfig ?? readConfig;
12569
+ const writeGlobal = deps.writeGlobalConfig ?? writeGlobalConfig;
12570
+ const writeProject = deps.writeProjectConfig ?? writeProjectConfig;
12571
+ const resolveSkill = deps.resolveSkill ?? resolvePersonalSkill;
12572
+ const logError = deps.logError ?? console.error;
12573
+ const logOut = deps.logOut ?? console.log;
12574
+ const { subcommand } = input;
12575
+ if (subcommand === "install") {
12576
+ const parsed = parseArgs2(input.subcommandArgs, "install");
12577
+ if ("error" in parsed) {
12578
+ logError(parsed.error);
12579
+ return 1;
12580
+ }
12581
+ const ref = parsed.positional[0];
12582
+ if (!ref) {
12583
+ logError(
12584
+ "skill install: missing skill path. Usage: skill install <path>"
12585
+ );
12586
+ return 1;
12587
+ }
12588
+ const resolved = resolveSkill(ref, input.projectDir);
12589
+ if ("error" in resolved) {
12590
+ logError(resolved.error);
12591
+ return 1;
12592
+ }
12593
+ const layer = parsed.project ? "project" : "global";
12594
+ const existing = (layer === "project" ? readProject(input.projectDir).skills : readGlobal().skills) ?? [];
12595
+ const overwriting = existing.some((s) => s.name === resolved.name);
12596
+ const next = [...existing.filter((s) => s.name !== resolved.name), resolved];
12597
+ if (layer === "project") {
12598
+ writeProject(input.projectDir, { skills: next });
12599
+ } else {
12600
+ writeGlobal({ skills: next });
12601
+ }
12602
+ logOut(
12603
+ `${overwriting ? "Reinstalled" : "Installed"} personal skill '${resolved.name}' [${layer}]`
12604
+ );
12605
+ return 0;
12606
+ }
12607
+ if (subcommand === "list") {
12608
+ const parsed = parseArgs2(input.subcommandArgs, "list");
12609
+ if ("error" in parsed) {
12610
+ logError(parsed.error);
12611
+ return 1;
12612
+ }
12613
+ const listSingleLayer = (skills2, label) => {
12614
+ if (skills2.length === 0) {
12615
+ logOut(`No personal skills configured (${label}).`);
12616
+ return;
12617
+ }
12618
+ logOut(`Personal skills (${label}):`);
12619
+ for (const skill of skills2) {
12620
+ logOut(` ${skill.name} ${skill.source}`);
12621
+ }
12622
+ };
12623
+ if (parsed.global) {
12624
+ listSingleLayer(readGlobal().skills ?? [], "global");
12625
+ return 0;
12626
+ }
12627
+ if (parsed.project) {
12628
+ listSingleLayer(readProject(input.projectDir).skills ?? [], "project");
12629
+ return 0;
12630
+ }
12631
+ const { skills } = resolveEffectiveCapabilities({
12632
+ globalConfig: readGlobal(),
12633
+ projectConfig: readProject(input.projectDir)
12634
+ });
12635
+ if (skills.length === 0) {
12636
+ logOut("No personal skills configured.");
12637
+ return 0;
12638
+ }
12639
+ logOut("Personal skills (effective):");
12640
+ for (const skill of skills) {
12641
+ logOut(` ${skill.name} ${skill.source} [${skill.sourceLayer}]`);
12642
+ }
12643
+ return 0;
12644
+ }
12645
+ if (subcommand === "remove") {
12646
+ const parsed = parseArgs2(input.subcommandArgs, "remove");
12647
+ if ("error" in parsed) {
12648
+ logError(parsed.error);
12649
+ return 1;
12650
+ }
12651
+ const target = parsed.positional[0];
12652
+ if (!target) {
12653
+ logError("skill remove: missing skill name or source");
12654
+ return 1;
12655
+ }
12656
+ const layer = parsed.project ? "project" : "global";
12657
+ const existing = (layer === "project" ? readProject(input.projectDir).skills : readGlobal().skills) ?? [];
12658
+ const next = existing.filter((s) => s.name !== target && s.source !== target);
12659
+ if (next.length === existing.length) {
12660
+ logError(
12661
+ `skill remove: no personal skill '${target}' found in ${layer} config`
12662
+ );
12663
+ return 1;
12664
+ }
12665
+ if (layer === "project") {
12666
+ writeProject(input.projectDir, { skills: next });
12667
+ } else {
12668
+ writeGlobal({ skills: next });
12669
+ }
12670
+ logOut(`Removed personal skill '${target}' [${layer}]`);
12671
+ return 0;
12672
+ }
12673
+ logError(`Unknown skill subcommand: ${subcommand}`);
12674
+ return 1;
12675
+ }
12676
+
12349
12677
  // src/app/entry/marketplaceCommand.ts
12350
12678
  var DEFAULT_MARKETPLACE_SLUG3 = "lespaceman/athena-workflow-marketplace";
12351
12679
  var USAGE2 = `Usage: athena-flow marketplace <subcommand>
@@ -12461,9 +12789,9 @@ Default: ${DEFAULT_MARKETPLACE_SLUG3}`
12461
12789
  }
12462
12790
 
12463
12791
  // src/app/entry/channelCommand.ts
12464
- import fs4 from "fs";
12792
+ import fs5 from "fs";
12465
12793
  import os3 from "os";
12466
- import path4 from "path";
12794
+ import path5 from "path";
12467
12795
  var USAGE3 = `Usage: athena-flow channel telegram configure --bot-token <token> --user-id <id> [--chat-id <id>]
12468
12796
 
12469
12797
  Configures ~/.config/athena/channels/telegram.json and enables telegram in the global channels list.`;
@@ -12474,16 +12802,16 @@ function parseTelegramId(flagName, value) {
12474
12802
  return Number(value);
12475
12803
  }
12476
12804
  function writeTelegramChannelConfig(config) {
12477
- const dir = path4.join(os3.homedir(), ".config", "athena", "channels");
12478
- const configPath = path4.join(dir, "telegram.json");
12479
- fs4.mkdirSync(dir, { recursive: true, mode: 448 });
12480
- fs4.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", {
12805
+ const dir = path5.join(os3.homedir(), ".config", "athena", "channels");
12806
+ const configPath = path5.join(dir, "telegram.json");
12807
+ fs5.mkdirSync(dir, { recursive: true, mode: 448 });
12808
+ fs5.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", {
12481
12809
  encoding: "utf-8",
12482
12810
  mode: 384
12483
12811
  });
12484
12812
  if (process.platform !== "win32") {
12485
- fs4.chmodSync(dir, 448);
12486
- fs4.chmodSync(configPath, 384);
12813
+ fs5.chmodSync(dir, 448);
12814
+ fs5.chmodSync(configPath, 384);
12487
12815
  }
12488
12816
  }
12489
12817
  function runChannelCommand(input, deps = {}) {
@@ -12530,22 +12858,22 @@ function runChannelCommand(input, deps = {}) {
12530
12858
  // src/app/entry/dashboardCommand.ts
12531
12859
  import crypto3 from "crypto";
12532
12860
  import { spawn } from "child_process";
12533
- import fs6 from "fs";
12861
+ import fs7 from "fs";
12534
12862
  import { createRequire } from "module";
12535
12863
  import os5 from "os";
12536
- import path6 from "path";
12864
+ import path7 from "path";
12537
12865
  import { fileURLToPath } from "url";
12538
12866
 
12539
12867
  // src/infra/daemon/serviceUnit.ts
12540
- import fs5 from "fs";
12868
+ import fs6 from "fs";
12541
12869
  import os4 from "os";
12542
- import path5 from "path";
12870
+ import path6 from "path";
12543
12871
  function installServiceUnit(options) {
12544
12872
  const platform = options.platform ?? process.platform;
12545
12873
  const env2 = options.env ?? process.env;
12546
12874
  const home = env2["HOME"] ?? os4.homedir();
12547
12875
  if (platform === "darwin") {
12548
- const target = options.targetPath ?? path5.join(home, "Library", "LaunchAgents", "ai.drisp.daemon.plist");
12876
+ const target = options.targetPath ?? path6.join(home, "Library", "LaunchAgents", "ai.drisp.daemon.plist");
12549
12877
  const paths = daemonStatePaths(env2);
12550
12878
  const plist = renderLaunchdPlist({
12551
12879
  label: "ai.drisp.daemon",
@@ -12565,7 +12893,7 @@ function installServiceUnit(options) {
12565
12893
  };
12566
12894
  }
12567
12895
  if (platform === "linux") {
12568
- const target = options.targetPath ?? path5.join(home, ".config", "systemd", "user", "drisp-daemon.service");
12896
+ const target = options.targetPath ?? path6.join(home, ".config", "systemd", "user", "drisp-daemon.service");
12569
12897
  const unit = renderSystemdUnit({
12570
12898
  description: "Drisp dashboard runtime daemon",
12571
12899
  nodeBinary: options.nodeBinary,
@@ -12587,16 +12915,16 @@ function installServiceUnit(options) {
12587
12915
  };
12588
12916
  }
12589
12917
  function writeIfChanged(target, content) {
12590
- const dir = path5.dirname(target);
12591
- fs5.mkdirSync(dir, { recursive: true, mode: 448 });
12918
+ const dir = path6.dirname(target);
12919
+ fs6.mkdirSync(dir, { recursive: true, mode: 448 });
12592
12920
  let existing = null;
12593
12921
  try {
12594
- existing = fs5.readFileSync(target, "utf-8");
12922
+ existing = fs6.readFileSync(target, "utf-8");
12595
12923
  } catch (err) {
12596
12924
  if (err.code !== "ENOENT") throw err;
12597
12925
  }
12598
12926
  if (existing === content) return;
12599
- fs5.writeFileSync(target, content, { mode: 384 });
12927
+ fs6.writeFileSync(target, content, { mode: 384 });
12600
12928
  }
12601
12929
  function renderLaunchdPlist(input) {
12602
12930
  const argv = [input.nodeBinary, input.daemonEntry].map((s) => ` <string>${escapeXml(s)}</string>`).join("\n");
@@ -12697,7 +13025,7 @@ var cachedVersion = null;
12697
13025
  function readPackageVersion() {
12698
13026
  if (cachedVersion !== null) return cachedVersion;
12699
13027
  try {
12700
- const injected = "0.5.23";
13028
+ const injected = "0.5.26";
12701
13029
  if (typeof injected === "string" && injected.length > 0) {
12702
13030
  cachedVersion = injected;
12703
13031
  return cachedVersion;
@@ -13684,11 +14012,11 @@ function resolveDaemonEntry() {
13684
14012
  return null;
13685
14013
  }
13686
14014
  const candidates = [
13687
- path6.join(path6.dirname(here), "dashboard-daemon.js"),
14015
+ path7.join(path7.dirname(here), "dashboard-daemon.js"),
13688
14016
  // When invoked via `npm run start`, `here` may be the unbundled source
13689
14017
  // path. Walk up until we hit a `dist/` sibling.
13690
- path6.join(
13691
- path6.dirname(here),
14018
+ path7.join(
14019
+ path7.dirname(here),
13692
14020
  "..",
13693
14021
  "..",
13694
14022
  "..",
@@ -13698,7 +14026,7 @@ function resolveDaemonEntry() {
13698
14026
  ];
13699
14027
  for (const candidate of candidates) {
13700
14028
  try {
13701
- fs6.accessSync(candidate, fs6.constants.R_OK);
14029
+ fs7.accessSync(candidate, fs7.constants.R_OK);
13702
14030
  return candidate;
13703
14031
  } catch {
13704
14032
  }
@@ -13883,14 +14211,14 @@ async function defaultTailDaemonLog(opts) {
13883
14211
  let stream2 = null;
13884
14212
  let watcher = null;
13885
14213
  try {
13886
- const stat = fs6.statSync(paths.logPath);
14214
+ const stat = fs7.statSync(paths.logPath);
13887
14215
  const size = stat.size;
13888
14216
  const buf = Buffer.alloc(Math.min(size, opts.tail * 1024));
13889
- const fd = fs6.openSync(paths.logPath, "r");
14217
+ const fd = fs7.openSync(paths.logPath, "r");
13890
14218
  try {
13891
- fs6.readSync(fd, buf, 0, buf.length, Math.max(0, size - buf.length));
14219
+ fs7.readSync(fd, buf, 0, buf.length, Math.max(0, size - buf.length));
13892
14220
  } finally {
13893
- fs6.closeSync(fd);
14221
+ fs7.closeSync(fd);
13894
14222
  }
13895
14223
  const lines = buf.toString("utf-8").split("\n").filter((l) => l.length > 0);
13896
14224
  const tail = lines.slice(-opts.tail);
@@ -13908,22 +14236,22 @@ async function defaultTailDaemonLog(opts) {
13908
14236
  }
13909
14237
  throw err;
13910
14238
  }
13911
- let position = fs6.statSync(paths.logPath).size;
14239
+ let position = fs7.statSync(paths.logPath).size;
13912
14240
  return await new Promise((resolve) => {
13913
14241
  let pollTimer = null;
13914
14242
  const drain = () => {
13915
14243
  try {
13916
- const stat = fs6.statSync(paths.logPath);
14244
+ const stat = fs7.statSync(paths.logPath);
13917
14245
  if (stat.size < position) {
13918
14246
  position = 0;
13919
14247
  }
13920
14248
  if (stat.size > position) {
13921
- const fd = fs6.openSync(paths.logPath, "r");
14249
+ const fd = fs7.openSync(paths.logPath, "r");
13922
14250
  const buf = Buffer.alloc(stat.size - position);
13923
14251
  try {
13924
- fs6.readSync(fd, buf, 0, buf.length, position);
14252
+ fs7.readSync(fd, buf, 0, buf.length, position);
13925
14253
  } finally {
13926
- fs6.closeSync(fd);
14254
+ fs7.closeSync(fd);
13927
14255
  }
13928
14256
  position = stat.size;
13929
14257
  process.stdout.write(buf);
@@ -13938,7 +14266,7 @@ async function defaultTailDaemonLog(opts) {
13938
14266
  }
13939
14267
  };
13940
14268
  try {
13941
- watcher = fs6.watch(paths.logPath, { persistent: true }, () => {
14269
+ watcher = fs7.watch(paths.logPath, { persistent: true }, () => {
13942
14270
  drain();
13943
14271
  });
13944
14272
  } catch {
@@ -14142,8 +14470,8 @@ function parsePairedRunner(raw) {
14142
14470
 
14143
14471
  // src/app/entry/gatewayCommand.ts
14144
14472
  import { spawn as spawn2 } from "child_process";
14145
- import fs7 from "fs";
14146
- import path7 from "path";
14473
+ import fs8 from "fs";
14474
+ import path8 from "path";
14147
14475
  import { fileURLToPath as fileURLToPath2 } from "url";
14148
14476
  var USAGE5 = `Usage: athena-flow gateway <subcommand> [--json]
14149
14477
 
@@ -14162,12 +14490,12 @@ Subcommands:
14162
14490
  reload-channels Reload channel sidecars without restarting the daemon.
14163
14491
  `;
14164
14492
  function defaultResolveDaemonEntry() {
14165
- const here = path7.dirname(fileURLToPath2(import.meta.url));
14166
- return path7.resolve(here, "athena-gateway.js");
14493
+ const here = path8.dirname(fileURLToPath2(import.meta.url));
14494
+ return path8.resolve(here, "athena-gateway.js");
14167
14495
  }
14168
14496
  function readToken(tokenPath) {
14169
14497
  try {
14170
- return fs7.readFileSync(tokenPath, "utf-8").trim();
14498
+ return fs8.readFileSync(tokenPath, "utf-8").trim();
14171
14499
  } catch (err) {
14172
14500
  const code = err.code;
14173
14501
  if (code === "ENOENT") {
@@ -14517,9 +14845,9 @@ import process7 from "process";
14517
14845
 
14518
14846
  // src/harnesses/claude/system/doctorEnvironment.ts
14519
14847
  import { execFileSync } from "child_process";
14520
- import * as fs8 from "fs";
14848
+ import * as fs9 from "fs";
14521
14849
  import * as os6 from "os";
14522
- import * as path8 from "path";
14850
+ import * as path9 from "path";
14523
14851
  var MANAGED_POLICY_KEYS = [
14524
14852
  "forceLoginMethod",
14525
14853
  "forceLoginOrgUUID",
@@ -14623,8 +14951,8 @@ function collectEnvironment(options = {}) {
14623
14951
  const detectVersion = options.detectClaudeVersionFn ?? detectClaudeVersion;
14624
14952
  const runAuthStatus = options.runClaudeAuthStatusFn ?? runClaudeAuthStatus;
14625
14953
  const resolveForwarder = options.resolveHookForwarderCommandFn ?? resolveHookForwarderCommand;
14626
- const statFn = options.statFn ?? ((p) => fs8.statSync(p));
14627
- const readFileFn = options.readFileFn ?? ((p) => fs8.readFileSync(p, "utf8"));
14954
+ const statFn = options.statFn ?? ((p) => fs9.statSync(p));
14955
+ const readFileFn = options.readFileFn ?? ((p) => fs9.readFileSync(p, "utf8"));
14628
14956
  const settingsPaths = resolveClaudeSettingsSurfacePaths(
14629
14957
  homeDir,
14630
14958
  cwd,
@@ -14669,7 +14997,7 @@ function collectEnvironment(options = {}) {
14669
14997
  });
14670
14998
  let globalConfigPresent = false;
14671
14999
  try {
14672
- statFn(path8.join(homeDir, ".claude.json"));
15000
+ statFn(path9.join(homeDir, ".claude.json"));
14673
15001
  globalConfigPresent = true;
14674
15002
  } catch {
14675
15003
  globalConfigPresent = false;
@@ -15078,15 +15406,15 @@ async function runDoctorCommand(options) {
15078
15406
  }
15079
15407
 
15080
15408
  // src/app/entry/cli.tsx
15081
- import { jsx as jsx25 } from "react/jsx-runtime";
15409
+ import { jsx as jsx24 } from "react/jsx-runtime";
15082
15410
  function resolvePackageJsonPath(entryUrl) {
15083
- let currentDir = path9.dirname(fileURLToPath3(entryUrl));
15411
+ let currentDir = path10.dirname(fileURLToPath3(entryUrl));
15084
15412
  for (; ; ) {
15085
- const candidatePath = path9.join(currentDir, "package.json");
15086
- if (fs9.existsSync(candidatePath)) {
15413
+ const candidatePath = path10.join(currentDir, "package.json");
15414
+ if (fs10.existsSync(candidatePath)) {
15087
15415
  return candidatePath;
15088
15416
  }
15089
- const parentDir = path9.dirname(currentDir);
15417
+ const parentDir = path10.dirname(currentDir);
15090
15418
  if (parentDir === currentDir) {
15091
15419
  throw new Error("Could not locate package.json for CLI metadata.");
15092
15420
  }
@@ -15101,6 +15429,8 @@ var KNOWN_COMMANDS = /* @__PURE__ */ new Set([
15101
15429
  "resume",
15102
15430
  "exec",
15103
15431
  "workflow",
15432
+ "mcp",
15433
+ "skill",
15104
15434
  "marketplace",
15105
15435
  "channel",
15106
15436
  "gateway",
@@ -15177,6 +15507,38 @@ function printExecDryRunSummary(runtimeConfig, context) {
15177
15507
  lines.push(
15178
15508
  ` plugin mcp config: ${runtimeConfig.pluginMcpConfig ?? "<none>"}`
15179
15509
  );
15510
+ const mcpLabel = "personal mcp servers:";
15511
+ const skillLabel = "personal skills:";
15512
+ const personalLabelWidth = mcpLabel.length;
15513
+ lines.push(" personal capabilities:");
15514
+ if (runtimeConfig.personalMcpServers.length === 0) {
15515
+ lines.push(` ${mcpLabel.padEnd(personalLabelWidth)} <none>`);
15516
+ } else {
15517
+ lines.push(` ${mcpLabel}`);
15518
+ for (const server of runtimeConfig.personalMcpServers) {
15519
+ lines.push(` - ${server.name} [${server.sourceLayer}]`);
15520
+ }
15521
+ }
15522
+ if (runtimeConfig.personalSkills.length === 0) {
15523
+ lines.push(` ${skillLabel.padEnd(personalLabelWidth)} <none>`);
15524
+ } else {
15525
+ lines.push(` ${skillLabel}`);
15526
+ for (const skill of runtimeConfig.personalSkills) {
15527
+ lines.push(` - ${skill.name} [${skill.sourceLayer}]`);
15528
+ }
15529
+ }
15530
+ const { mcpServers: conflictMcp, skills: conflictSkills } = runtimeConfig.capabilityConflicts;
15531
+ if (conflictMcp.length === 0 && conflictSkills.length === 0) {
15532
+ lines.push(" conflicts (shadowed by workflow plugin): <none>");
15533
+ } else {
15534
+ lines.push(" conflicts (shadowed by workflow plugin):");
15535
+ for (const server of conflictMcp) {
15536
+ lines.push(` - ${server.name} [${server.sourceLayer}]`);
15537
+ }
15538
+ for (const skill of conflictSkills) {
15539
+ lines.push(` - ${skill.name} [${skill.sourceLayer}]`);
15540
+ }
15541
+ }
15180
15542
  for (const line of lines) {
15181
15543
  console.log(line);
15182
15544
  }
@@ -15207,6 +15569,8 @@ var cli = meow(
15207
15569
  resume [sessionId] Resume most recent (or specified) session
15208
15570
  exec "<prompt>" Run non-interactively (CI/script mode)
15209
15571
  workflow <sub> Manage workflows (install, list, search, remove, upgrade, use)
15572
+ mcp <sub> Manage personal MCP servers (add, remove, list)
15573
+ skill <sub> Manage personal skills (install, remove, list)
15210
15574
  marketplace <sub> Manage marketplace sources (add, refresh, remove, list)
15211
15575
  channel <sub> Manage external channels
15212
15576
  dashboard <sub> Manage dashboard pairing and runtime daemon (pair, status, daemon, unpair)
@@ -15389,6 +15753,10 @@ var cli = meow(
15389
15753
  type: "boolean",
15390
15754
  default: false
15391
15755
  },
15756
+ env: {
15757
+ type: "string",
15758
+ isMultiple: true
15759
+ },
15392
15760
  printApiKey: {
15393
15761
  type: "boolean",
15394
15762
  default: false
@@ -15400,7 +15768,7 @@ var cli = meow(
15400
15768
  }
15401
15769
  );
15402
15770
  async function main() {
15403
- const projectDir = path9.resolve(cli.flags.projectDir);
15771
+ const projectDir = path10.resolve(cli.flags.projectDir);
15404
15772
  const [command, ...commandArgs] = cli.input;
15405
15773
  if (command && !KNOWN_COMMANDS.has(command)) {
15406
15774
  console.error(
@@ -15444,9 +15812,9 @@ Available commands: ${[...KNOWN_COMMANDS].join(", ")}`
15444
15812
  await exitWith(1);
15445
15813
  return;
15446
15814
  }
15447
- const { default: WorkflowInstallWizard } = await import("./WorkflowInstallWizard-CCCUR6KA.js");
15815
+ const { default: WorkflowInstallWizard } = await import("./WorkflowInstallWizard-5FENJHBW.js");
15448
15816
  const { waitUntilExit } = render(
15449
- /* @__PURE__ */ jsx25(
15817
+ /* @__PURE__ */ jsx24(
15450
15818
  WorkflowInstallWizard,
15451
15819
  {
15452
15820
  source: resolvedSource,
@@ -15465,6 +15833,40 @@ Available commands: ${[...KNOWN_COMMANDS].join(", ")}`
15465
15833
  );
15466
15834
  return;
15467
15835
  }
15836
+ if (command === "mcp") {
15837
+ const rawArgs = process.argv.slice(2);
15838
+ const dashIdx = rawArgs.indexOf("--");
15839
+ const serverCommandTokens = dashIdx >= 0 ? rawArgs.slice(dashIdx + 1) : [];
15840
+ const cleanArgs = serverCommandTokens.length > 0 ? commandArgs.slice(0, commandArgs.length - serverCommandTokens.length) : commandArgs;
15841
+ const [subcommand = "", ...subcommandArgs] = cleanArgs;
15842
+ if (cli.flags.project) subcommandArgs.push("--project");
15843
+ if (cli.flags.global) subcommandArgs.push("--global");
15844
+ for (const entry of cli.flags.env ?? []) {
15845
+ subcommandArgs.push("--env", entry);
15846
+ }
15847
+ await exitWith(
15848
+ runMcpCommand({
15849
+ subcommand,
15850
+ subcommandArgs,
15851
+ serverCommandTokens,
15852
+ projectDir
15853
+ })
15854
+ );
15855
+ return;
15856
+ }
15857
+ if (command === "skill") {
15858
+ const [subcommand = "", ...subcommandArgs] = commandArgs;
15859
+ if (cli.flags.project) subcommandArgs.push("--project");
15860
+ if (cli.flags.global) subcommandArgs.push("--global");
15861
+ await exitWith(
15862
+ runSkillCommand({
15863
+ subcommand,
15864
+ subcommandArgs,
15865
+ projectDir
15866
+ })
15867
+ );
15868
+ return;
15869
+ }
15468
15870
  if (command === "marketplace") {
15469
15871
  const [subcommand = "", ...subcommandArgs] = commandArgs;
15470
15872
  await exitWith(runMarketplaceCommand({ subcommand, subcommandArgs }));
@@ -15591,8 +15993,8 @@ Available commands: ${[...KNOWN_COMMANDS].join(", ")}`
15591
15993
  const showSetup = command === "exec" ? false : shouldShowSetup({
15592
15994
  cliInput: cli.input,
15593
15995
  setupComplete: globalConfig.setupComplete,
15594
- globalConfigExists: fs9.existsSync(
15595
- path9.join(os7.homedir(), ".config", "athena", "config.json")
15996
+ globalConfigExists: fs10.existsSync(
15997
+ path10.join(os7.homedir(), ".config", "athena", "config.json")
15596
15998
  )
15597
15999
  });
15598
16000
  let runtimeConfig;
@@ -15685,7 +16087,7 @@ Available commands: ${[...KNOWN_COMMANDS].join(", ")}`
15685
16087
  const { athenaSessionId, initialSessionId } = interactiveSession;
15686
16088
  const instanceId = process.pid;
15687
16089
  render(
15688
- /* @__PURE__ */ jsx25(
16090
+ /* @__PURE__ */ jsx24(
15689
16091
  App,
15690
16092
  {
15691
16093
  projectDir,