@cydm/pie 1.0.30 → 1.0.32

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.
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  createAskUserCapability
4
- } from "../../../chunks/chunk-BOFCKEV5.js";
4
+ } from "../../../chunks/chunk-MPZSDREV.js";
5
5
  import "../../../chunks/chunk-4B42ZU4B.js";
6
6
  import "../../../chunks/chunk-64XJIKVK.js";
7
7
  import "../../../chunks/chunk-TG2EQLX2.js";
@@ -7,7 +7,7 @@ import {
7
7
  isPlanModeSafeCommand,
8
8
  markCompletedPlanSteps,
9
9
  restoreExecutionState
10
- } from "../../../chunks/chunk-BOFCKEV5.js";
10
+ } from "../../../chunks/chunk-MPZSDREV.js";
11
11
  import "../../../chunks/chunk-4B42ZU4B.js";
12
12
  import "../../../chunks/chunk-64XJIKVK.js";
13
13
  import "../../../chunks/chunk-TG2EQLX2.js";
@@ -1,11 +1,11 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  createCliHostCapabilities
4
- } from "../../../chunks/chunk-PLJQYVFC.js";
4
+ } from "../../../chunks/chunk-PJWPGKQK.js";
5
5
  import {
6
6
  createSharedFileSystemTools,
7
7
  createSubagentCapability
8
- } from "../../../chunks/chunk-BOFCKEV5.js";
8
+ } from "../../../chunks/chunk-MPZSDREV.js";
9
9
  import "../../../chunks/chunk-4B42ZU4B.js";
10
10
  import "../../../chunks/chunk-64XJIKVK.js";
11
11
  import "../../../chunks/chunk-TG2EQLX2.js";
@@ -7,7 +7,7 @@ import {
7
7
  executeManageTodoList,
8
8
  executionStateToTodos,
9
9
  restoreExecutionState
10
- } from "../../../chunks/chunk-BOFCKEV5.js";
10
+ } from "../../../chunks/chunk-MPZSDREV.js";
11
11
  import "../../../chunks/chunk-4B42ZU4B.js";
12
12
  import "../../../chunks/chunk-64XJIKVK.js";
13
13
  import "../../../chunks/chunk-TG2EQLX2.js";
@@ -4109,6 +4109,11 @@ var AgentSessionQueueDispatcher = class {
4109
4109
  if (this.options.getDisposed() || this.options.isStreaming() || this.options.isBlockedByRuntimePolicy()) {
4110
4110
  return false;
4111
4111
  }
4112
+ await this.options.agent.waitForIdle();
4113
+ if (this.options.getDisposed() || this.options.isStreaming() || this.options.isBlockedByRuntimePolicy()) {
4114
+ this.schedule(100);
4115
+ return false;
4116
+ }
4112
4117
  const queuedInput = this.options.queue.peek();
4113
4118
  if (!queuedInput) {
4114
4119
  return false;
@@ -8,7 +8,7 @@ import {
8
8
  createSharedWebSearchTool,
9
9
  interpretShellExit,
10
10
  requestInteraction
11
- } from "./chunk-BOFCKEV5.js";
11
+ } from "./chunk-MPZSDREV.js";
12
12
  import {
13
13
  Type
14
14
  } from "./chunk-64XJIKVK.js";
package/dist/cli.js CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  getThemesDir,
20
20
  migrateConfigFromAgentDir,
21
21
  truncateHeadTail
22
- } from "./chunks/chunk-PLJQYVFC.js";
22
+ } from "./chunks/chunk-PJWPGKQK.js";
23
23
  import {
24
24
  AGENTS_CONTEXT_FILE_NAME,
25
25
  AgentSessionController,
@@ -69,7 +69,7 @@ import {
69
69
  setExtensionEnabledInSettings,
70
70
  shouldPreserveExecutionStateForUserText,
71
71
  supersedeExecutionState
72
- } from "./chunks/chunk-BOFCKEV5.js";
72
+ } from "./chunks/chunk-MPZSDREV.js";
73
73
  import "./chunks/chunk-4B42ZU4B.js";
74
74
  import {
75
75
  Deref,
@@ -47140,7 +47140,7 @@ function createExtensionContext(extension, cwd, uiContext, abortFn, isIdleFn, ha
47140
47140
  path: cmdPath,
47141
47141
  hidden: command.hidden === true
47142
47142
  };
47143
- extension.commands.set(finalName, registeredCmd);
47143
+ extension.commands.set(cmdPath.join("/"), registeredCmd);
47144
47144
  commandTree.register(cmdPath, {
47145
47145
  description: command.description,
47146
47146
  handler: command.handler,
@@ -50616,26 +50616,32 @@ var Editor = class {
50616
50616
  return;
50617
50617
  }
50618
50618
  if (kb.matches(data, "selectConfirm")) {
50619
- const selected = this.autocompleteList.getSelectedItem();
50620
- if (selected && this.autocompleteProvider) {
50621
- this.pushUndoSnapshot();
50622
- this.lastAction = null;
50623
- const result = this.autocompleteProvider.applyCompletion(
50624
- this.state.lines,
50625
- this.state.cursorLine,
50626
- this.state.cursorCol,
50627
- selected,
50628
- this.autocompletePrefix
50629
- );
50630
- this.state.lines = result.lines;
50631
- this.state.cursorLine = result.cursorLine;
50632
- this.setCursorCol(result.cursorCol);
50633
- if (this.autocompletePrefix.startsWith("/")) {
50634
- this.cancelAutocomplete();
50635
- } else {
50636
- this.cancelAutocomplete();
50637
- if (this.onChange) this.onChange(this.getText());
50638
- return;
50619
+ const currentLine = this.state.lines[this.state.cursorLine] || "";
50620
+ const isBareSlashSubmit = this.state.lines.length === 1 && currentLine === "/" && this.state.cursorCol === 1;
50621
+ if (isBareSlashSubmit) {
50622
+ this.cancelAutocomplete();
50623
+ } else {
50624
+ const selected = this.autocompleteList.getSelectedItem();
50625
+ if (selected && this.autocompleteProvider) {
50626
+ this.pushUndoSnapshot();
50627
+ this.lastAction = null;
50628
+ const result = this.autocompleteProvider.applyCompletion(
50629
+ this.state.lines,
50630
+ this.state.cursorLine,
50631
+ this.state.cursorCol,
50632
+ selected,
50633
+ this.autocompletePrefix
50634
+ );
50635
+ this.state.lines = result.lines;
50636
+ this.state.cursorLine = result.cursorLine;
50637
+ this.setCursorCol(result.cursorCol);
50638
+ if (this.autocompletePrefix.startsWith("/")) {
50639
+ this.cancelAutocomplete();
50640
+ } else {
50641
+ this.cancelAutocomplete();
50642
+ if (this.onChange) this.onChange(this.getText());
50643
+ return;
50644
+ }
50639
50645
  }
50640
50646
  }
50641
50647
  }
@@ -60742,6 +60748,9 @@ var ExtensionEnablementSelectorComponent = class extends Container {
60742
60748
  getSettingsList() {
60743
60749
  return this.settingsList;
60744
60750
  }
60751
+ handleInput(data) {
60752
+ this.settingsList.handleInput(data);
60753
+ }
60745
60754
  };
60746
60755
 
60747
60756
  // src/commands/interactive-extensions-command.ts
@@ -60859,23 +60868,28 @@ function handleExtensionsCommand(host, args) {
60859
60868
  // src/slash-commands.ts
60860
60869
  var BUILTIN_SLASH_COMMANDS = [
60861
60870
  { name: "sessions/compact", description: "Summarize history and add a compact checkpoint to the session" },
60871
+ { name: "sessions/new", description: "Start a new session" },
60872
+ { name: "sessions/resume", description: "Resume a different session" },
60873
+ { name: "sessions/tree", description: "Navigate session tree" },
60874
+ { name: "sessions/info", description: "Show session info" },
60875
+ { name: "sessions/fork", description: "Fork from a message" },
60862
60876
  { name: "settings", description: "Open settings menu" },
60863
60877
  { name: "settings/extensions", description: "Manage extensions" },
60864
60878
  { name: "settings/help", description: "Show help information (keyboard shortcuts and commands)" },
60865
- { name: "settings/quit", description: "Exit Pie" },
60866
- { name: "model", description: "Select model (e.g., /model kimi-api/kimi-k2.5)" },
60867
- { name: "export", description: "Export session to HTML file" },
60868
- { name: "hotkeys", description: "Show all keyboard shortcuts" },
60869
- { name: "session", description: "Show session info and stats" },
60870
- { name: "resume", description: "Resume a different session" },
60871
- { name: "tree", description: "Navigate session tree" },
60872
- { name: "fork", description: "Create a new fork from a previous message" },
60873
- { name: "skills", description: "List available skills" },
60874
- { name: "skill", description: "Activate a skill (e.g., /skill code-review)" },
60875
- { name: "new", description: "Start a new session" },
60879
+ { name: "settings/hotkeys", description: "Show keyboard shortcuts" },
60880
+ { name: "settings/model", description: "Select AI model" },
60881
+ { name: "settings/theme", description: "Change theme" },
60882
+ { name: "settings/thinking", description: "Set thinking level" },
60883
+ { name: "settings/yolo", description: "Toggle or set YOLO mode" },
60876
60884
  { name: "settings/debugs/cache-test", description: "Run provider cache diagnostics with a dedicated 2-request probe" },
60877
60885
  { name: "settings/debugs/context", description: "Append a context summary to ~/.pie/logs/pie-cli.log" },
60878
- { name: "settings/debugs/package", description: "Append a package summary to ~/.pie/logs/pie-cli.log" }
60886
+ { name: "settings/debugs/package", description: "Append a package summary to ~/.pie/logs/pie-cli.log" },
60887
+ { name: "settings/quit", description: "Exit Pie" },
60888
+ { name: "skills", description: "Open skills menu" },
60889
+ { name: "skills/list", description: "List available skills" },
60890
+ { name: "skills/reload", description: "Reload skills from disk" },
60891
+ { name: "skills/use", description: "Use a skill" },
60892
+ { name: "tools/subagent", description: "Spawn subagents in parallel to handle tasks" }
60879
60893
  ];
60880
60894
 
60881
60895
  // src/commands/interactive-debug-commands.ts
@@ -63059,10 +63073,11 @@ var TITLE_SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\
63059
63073
  var TITLE_SPINNER_INTERVAL_MS = 80;
63060
63074
  var TITLE_WAITING_PREFIX = "\u23F8";
63061
63075
  var titleSpinnerTimers = /* @__PURE__ */ new WeakMap();
63076
+ var explicitSubmitLockHosts = /* @__PURE__ */ new WeakSet();
63062
63077
  var controllerBusyHosts = /* @__PURE__ */ new WeakSet();
63063
63078
  var waitingForUserHosts = /* @__PURE__ */ new WeakSet();
63064
63079
  function isHostBusy(host) {
63065
- return host.submitLock || controllerBusyHosts.has(host);
63080
+ return explicitSubmitLockHosts.has(host) || controllerBusyHosts.has(host);
63066
63081
  }
63067
63082
  function isWaitingForUser(host) {
63068
63083
  return waitingForUserHosts.has(host);
@@ -63119,10 +63134,17 @@ function syncTitleActivity(host) {
63119
63134
  host.updateTerminalTitle();
63120
63135
  }
63121
63136
  function setSubmitLock(host, locked) {
63122
- if (host.submitLock === locked) {
63137
+ const hadExplicitLock = explicitSubmitLockHosts.has(host);
63138
+ if (locked) {
63139
+ explicitSubmitLockHosts.add(host);
63140
+ } else {
63141
+ explicitSubmitLockHosts.delete(host);
63142
+ }
63143
+ const nextSubmitLock = explicitSubmitLockHosts.has(host) || controllerBusyHosts.has(host);
63144
+ if (hadExplicitLock === locked && host.submitLock === nextSubmitLock) {
63123
63145
  return;
63124
63146
  }
63125
- host.submitLock = locked;
63147
+ host.submitLock = nextSubmitLock;
63126
63148
  syncTitleActivity(host);
63127
63149
  }
63128
63150
  function setControllerBusy(host, busy) {
@@ -63135,6 +63157,7 @@ function setControllerBusy(host, busy) {
63135
63157
  } else {
63136
63158
  controllerBusyHosts.delete(host);
63137
63159
  }
63160
+ host.submitLock = explicitSubmitLockHosts.has(host) || controllerBusyHosts.has(host);
63138
63161
  syncTitleActivity(host);
63139
63162
  }
63140
63163
  function setWaitingForUser(host, waiting) {
@@ -63389,7 +63412,7 @@ function handleSkillsCommand(host) {
63389
63412
  }
63390
63413
  function handleSkillCommand(host, name) {
63391
63414
  if (!name) {
63392
- host.showError("Usage: /skill <name>");
63415
+ host.showError("Usage: /skills/skill:<name> <your request>");
63393
63416
  return;
63394
63417
  }
63395
63418
  const skill = host.skills.find((s) => s.name === name);
@@ -63626,13 +63649,15 @@ async function handleSkillsReload(host) {
63626
63649
  function showSettingsSelector(host) {
63627
63650
  host.showSelector((done) => {
63628
63651
  const currentModelId = host.options.model?.id || "unknown";
63652
+ const currentProvider = host.options.model?.provider || "unknown";
63653
+ const currentFullId = `${currentProvider}/${currentModelId}`;
63629
63654
  const availableModels = host.options.modelRegistry.listAvailableModels();
63630
63655
  const selector = new SettingsSelectorComponent(
63631
63656
  {
63632
63657
  thinkingLevel: host.thinkingLevel,
63633
63658
  currentTheme: getCurrentThemeName(),
63634
63659
  availableThemes: getAvailableThemes(),
63635
- currentModel: currentModelId,
63660
+ currentModel: currentFullId,
63636
63661
  availableModels,
63637
63662
  yoloMode: host.yoloMode
63638
63663
  },
@@ -63836,9 +63861,10 @@ function handleHotkeysCommand(host) {
63836
63861
  "",
63837
63862
  ...BUILTIN_SLASH_COMMANDS.map((cmd) => ` /${cmd.name.padEnd(12)} ${theme.fg("muted", cmd.description)}`),
63838
63863
  ...host.extensions.flatMap(
63839
- (ext) => Array.from(ext.commands.entries()).map(
63840
- ([name, cmd]) => ` /${name.padEnd(12)} ${theme.fg("muted", cmd.description)}${theme.fg("dim", " [ext]")}`
63841
- )
63864
+ (ext) => Array.from(ext.commands.values()).filter((cmd) => !cmd.hidden).map((cmd) => {
63865
+ const pathName = cmd.path?.join("/") ?? cmd.name;
63866
+ return ` /${pathName.padEnd(12)} ${theme.fg("muted", cmd.description)}${theme.fg("dim", " [ext]")}`;
63867
+ })
63842
63868
  )
63843
63869
  ];
63844
63870
  host.chatContainer.addChild(new Spacer(1));
@@ -64661,6 +64687,16 @@ function handleToolStart(host, event) {
64661
64687
  if (event.toolCallId) {
64662
64688
  const toolComponent = host.pendingTools.get(event.toolCallId);
64663
64689
  if (toolComponent) {
64690
+ toolComponent.updateArgs(event.args);
64691
+ } else {
64692
+ const newToolComponent = new ToolExecutionComponent(
64693
+ event.toolName,
64694
+ event.args,
64695
+ { expanded: host.toolOutputExpanded },
64696
+ host.ui
64697
+ );
64698
+ host.pendingTools.set(event.toolCallId, newToolComponent);
64699
+ host.chatContainer.addChild(newToolComponent);
64664
64700
  }
64665
64701
  }
64666
64702
  host.footer.setState({ lifecycleEvent: formatFooterLifecycleEvent(event) });
@@ -64739,6 +64775,12 @@ function handleMessageEnd(host, event) {
64739
64775
  }
64740
64776
 
64741
64777
  // src/input/interactive-input-pipeline.ts
64778
+ function shouldQueueUserInput(host) {
64779
+ return host.submitLock || (host.agentSessionController?.hasQueuedMessages ?? false);
64780
+ }
64781
+ function showBusyCommandStatus(host, command) {
64782
+ host.showStatus(`Wait for the current response to finish before running ${command}`);
64783
+ }
64742
64784
  function setupInteractiveEditorSubmitHandler(host) {
64743
64785
  host.editor.onSubmit = async (text) => {
64744
64786
  text = text.trim();
@@ -64747,7 +64789,7 @@ function setupInteractiveEditorSubmitHandler(host) {
64747
64789
  const skillText = text.slice("/skills/".length);
64748
64790
  const expanded = host.expandSkillCommand(skillText);
64749
64791
  if (expanded !== skillText) {
64750
- if (host.submitLock) {
64792
+ if (shouldQueueUserInput(host)) {
64751
64793
  host.queueMessage(expanded, "followUp", { deliverWhileStreaming: false });
64752
64794
  return;
64753
64795
  }
@@ -64778,8 +64820,8 @@ function setupInteractiveEditorSubmitHandler(host) {
64778
64820
  }
64779
64821
  if (text.startsWith("/tools/subagent")) {
64780
64822
  const args = text.slice("/tools/subagent".length).trim();
64781
- if (host.submitLock) {
64782
- host.queueMessage(text, "followUp", { deliverWhileStreaming: false });
64823
+ if (shouldQueueUserInput(host)) {
64824
+ showBusyCommandStatus(host, "/tools/subagent");
64783
64825
  return;
64784
64826
  }
64785
64827
  host.editor.setText("");
@@ -64793,12 +64835,12 @@ function setupInteractiveEditorSubmitHandler(host) {
64793
64835
  const firstPartSegments = firstPart.slice(1).split("/").filter(Boolean);
64794
64836
  const exactMatch = commandTree.find(firstPartSegments);
64795
64837
  if (exactMatch?.handler) {
64796
- if (host.submitLock) {
64838
+ if (shouldQueueUserInput(host)) {
64797
64839
  if (firstPart === "/sessions/compact") {
64798
64840
  host.showStatus("Wait for the current response to finish before compacting");
64799
64841
  return;
64800
64842
  }
64801
- host.queueMessage(text, "followUp", { deliverWhileStreaming: false });
64843
+ showBusyCommandStatus(host, firstPart);
64802
64844
  return;
64803
64845
  }
64804
64846
  host.editor.setText("");
@@ -64849,12 +64891,12 @@ function setupInteractiveEditorSubmitHandler(host) {
64849
64891
  }
64850
64892
  }
64851
64893
  if (node?.handler) {
64852
- if (host.submitLock) {
64894
+ if (shouldQueueUserInput(host)) {
64853
64895
  if (commandSegments.join("/") === "sessions/compact") {
64854
64896
  host.showStatus("Wait for the current response to finish before compacting");
64855
64897
  return;
64856
64898
  }
64857
- host.queueMessage(text, "followUp", { deliverWhileStreaming: false });
64899
+ showBusyCommandStatus(host, "/" + commandSegments.join("/"));
64858
64900
  return;
64859
64901
  }
64860
64902
  host.editor.setText("");
@@ -64894,8 +64936,8 @@ function setupInteractiveEditorSubmitHandler(host) {
64894
64936
  for (const ext of host.extensions) {
64895
64937
  for (const [name, command] of ext.commands) {
64896
64938
  if (command.path?.join("/") === fullPath) {
64897
- if (host.submitLock) {
64898
- host.queueMessage(text, "followUp", { deliverWhileStreaming: false });
64939
+ if (shouldQueueUserInput(host)) {
64940
+ showBusyCommandStatus(host, "/" + fullPath);
64899
64941
  return;
64900
64942
  }
64901
64943
  host.editor.setText("");
@@ -64949,7 +64991,7 @@ function setupInteractiveEditorSubmitHandler(host) {
64949
64991
  host.agentSessionController?.requestQueueDispatch();
64950
64992
  return;
64951
64993
  }
64952
- if (host.submitLock) {
64994
+ if (shouldQueueUserInput(host)) {
64953
64995
  host.queueMessage(text, "followUp", { deliverWhileStreaming: false });
64954
64996
  return;
64955
64997
  }
@@ -66820,7 +66862,11 @@ function queueMessage(host, text, mode, options = {}) {
66820
66862
  function handleFollowUp(host) {
66821
66863
  const text = host.editor.getText().trim();
66822
66864
  if (!text) return;
66823
- if (host.submitLock) {
66865
+ if (isCommandLikeInput(text)) {
66866
+ host.editor.onSubmit?.(text);
66867
+ return;
66868
+ }
66869
+ if (host.submitLock || (host.agentSessionController?.hasQueuedMessages ?? false)) {
66824
66870
  queueMessage(host, text, "followUp");
66825
66871
  } else if (host.editor.onSubmit) {
66826
66872
  void host.editor.onSubmit(text);
@@ -66830,6 +66876,9 @@ function truncate(text, maxLength) {
66830
66876
  if (text.length <= maxLength) return text;
66831
66877
  return text.slice(0, maxLength) + "...";
66832
66878
  }
66879
+ function isCommandLikeInput(text) {
66880
+ return text.startsWith("/") || text.startsWith("!!");
66881
+ }
66833
66882
 
66834
66883
  // src/components/footer.ts
66835
66884
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
@@ -67962,6 +68011,8 @@ function createInteractiveAgentSessionController(host) {
67962
68011
  }
67963
68012
  host.sessionTrace.completeTurn(event.message, false);
67964
68013
  host._semanticTurnIndex++;
68014
+ } else if (event.type === "turn_settled") {
68015
+ host.setControllerBusy(false);
67965
68016
  } else if (event.type === "turn_failed_terminal") {
67966
68017
  host.clearContinuationTimeout("turn_failed_terminal");
67967
68018
  if (event.message) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cydm/pie",
3
- "version": "1.0.30",
3
+ "version": "1.0.32",
4
4
  "description": "Pie AI Agent CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -20,7 +20,7 @@
20
20
  "posttest:offline": "node --test --import tsx test/remote-model-catalog.test.ts",
21
21
  "test:offline": "node --test --import tsx test/core-services.test.ts test/cli.test.ts test/cli-auto-compaction.test.ts test/execution-state-manager.test.ts test/queued-steer-execution-state.test.ts test/architecture-boundaries.test.ts test/attachment-resolver.test.ts test/kimi-attachment-extension.test.ts test/document-attachment-extension.test.ts test/auto-compact-overflow.test.ts test/hierarchical-command-system.test.ts test/extensions-enablement.test.ts test/message-queue-unit.test.ts test/evals-harness.test.ts test/session-trace.test.ts test/runtime-mode-context.test.ts test/tool-policy.test.ts test/retry-policy.test.ts test/yolo-command.test.ts test/footer-lifecycle.test.ts test/files-utils.test.ts test/source-size-guard.test.ts test/runtime-logger.test.ts test/release-readiness.test.ts test/package-artifacts.test.ts test/code-intel-typescript-provider.test.ts test/init-extension-contract.test.ts test/skills-runtime.test.ts test/cross-host-parity.test.ts test/tool-name-rendering.test.ts test/session-selector.test.ts test/terminal-title.test.ts test/tools-registry.test.ts test/system-prompt-contract.test.ts test/direct-bash.test.ts test/daily-agent-smoke.terminal.test.ts",
22
22
  "test:all": "npm run test:offline && npm run test:terminal:vitest",
23
- "test:terminal:vitest": "vitest run test/mention-file-select.terminal.test.ts test/tool-partial-display.terminal.test.ts test/viewport-position-final.test.ts",
23
+ "test:terminal:vitest": "vitest run test/mention-file-select.terminal.test.ts test/tool-partial-display.terminal.test.ts test/viewport-position-final.test.ts --no-file-parallelism",
24
24
  "test:todo-tui": "PIE_REAL_TODO_TUI=1 node --test --import tsx test/todo-closure.terminal.test.ts",
25
25
  "test:daily-tui": "npm run test:daily-tui:quick",
26
26
  "test:daily-tui:quick": "PIE_REAL_DAILY_TUI=1 PIE_DAILY_TUI_LEVEL=quick node --test --import tsx test/daily-agent-smoke.terminal.test.ts",