@wrongstack/tui 0.270.0 → 0.272.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -268,7 +268,7 @@ interface RunTuiOptions {
268
268
  /** Snapshot of keyed providers + their model lists for the `/model` picker. Async — the catalog fetch may need to hit disk/network. */
269
269
  getPickableProviders?: (() => Promise<ProviderOption[]>) | undefined;
270
270
  /** Apply a (provider, model) pair after the picker confirms. Returns an error string on failure. */
271
- switchProviderAndModel?: ((providerId: string, modelId: string) => string | null) | undefined;
271
+ switchProviderAndModel?: ((providerId: string, modelId: string) => string | null | Promise<string | null>) | undefined;
272
272
  /** Apply an autonomy mode after the picker confirms. Returns an error string on failure. */
273
273
  switchAutonomy?: ((mode: 'off' | 'suggest' | 'auto' | 'eternal' | 'eternal-parallel') => string | null) | undefined;
274
274
  /**
package/dist/index.js CHANGED
@@ -8258,6 +8258,29 @@ function useSubagentEvents(events, dispatch, setActiveMaxContext) {
8258
8258
  const offCtxPct = events.on("subagent.ctx_pct", (e) => {
8259
8259
  dispatch({ type: "fleetCtxPct", id: e.subagentId, load: e.load, tokens: e.tokens, maxContext: e.maxContext });
8260
8260
  });
8261
+ const offAgentTimeline = events.on("agent.timeline.message", (e) => {
8262
+ const l = lbl(e.subagentId, e.agentName);
8263
+ const iconMap = {
8264
+ text: "\u{1F4AC}",
8265
+ // 💬
8266
+ tool_use: "\u{1F527}",
8267
+ // 🔧
8268
+ error: "\u274C",
8269
+ // ❌
8270
+ status: "\u{1F4AC}"
8271
+ // 💬
8272
+ };
8273
+ const icon = iconMap[e.kind] ?? "\u25CF";
8274
+ const toolSuffix = e.toolName ? ` [${e.toolName}]` : "";
8275
+ const text = `#${e.iteration}${toolSuffix} ${e.content.slice(0, 200)}`;
8276
+ dispatch({ type: "addEntry", entry: { kind: "subagent", agentLabel: l.label, agentColor: l.color, icon, text } });
8277
+ });
8278
+ const offAgentStatus = events.on("agent.status_changed", (e) => {
8279
+ const l = lbl(e.subagentId, e.agentName);
8280
+ const icon = e.status === "spawned" || e.status === "running" ? "\u25B6" : e.status === "completed" ? "\u2713" : e.status === "failed" || e.status === "timeout" ? "\u2717" : "\u2299";
8281
+ const text = e.summary ? `${e.status}: ${e.summary.slice(0, 160)}` : e.status;
8282
+ dispatch({ type: "addEntry", entry: { kind: "subagent", agentLabel: l.label, agentColor: l.color, icon, text } });
8283
+ });
8261
8284
  const offConcurrencyChanged = events.on("concurrency.changed", (e) => {
8262
8285
  const { n } = e;
8263
8286
  if (typeof n === "number" && n > 0) {
@@ -8287,6 +8310,8 @@ function useSubagentEvents(events, dispatch, setActiveMaxContext) {
8287
8310
  offLeaderCtxPct();
8288
8311
  offLeaderMaxContext();
8289
8312
  offTool();
8313
+ offAgentTimeline();
8314
+ offAgentStatus();
8290
8315
  };
8291
8316
  }, [events, dispatch, setActiveMaxContext, lbl]);
8292
8317
  }
@@ -10350,6 +10375,7 @@ function App({
10350
10375
  enhanceEnabled = true,
10351
10376
  enhanceController,
10352
10377
  enhanceDelayMs = 15e3,
10378
+ getEnhancerReasoning,
10353
10379
  getYolo,
10354
10380
  getAutonomy,
10355
10381
  getEternalEngine,
@@ -12559,7 +12585,7 @@ function App({
12559
12585
  const providerId = state.modelPicker.pickedProviderId;
12560
12586
  const modelId = state.modelPicker.filteredOptions[state.modelPicker.selected];
12561
12587
  if (!providerId || !modelId) return;
12562
- const err = switchProviderAndModel?.(providerId, modelId);
12588
+ const err = await switchProviderAndModel?.(providerId, modelId);
12563
12589
  if (err) {
12564
12590
  dispatch({ type: "modelPickerHint", text: err });
12565
12591
  return;
@@ -14057,6 +14083,7 @@ ${content}
14057
14083
  enhanceAbortRef.current = ac;
14058
14084
  let result = null;
14059
14085
  let enhanceErr = null;
14086
+ const enhanceReasoning = getEnhancerReasoning?.();
14060
14087
  try {
14061
14088
  result = await enhanceUserPrompt({
14062
14089
  provider: agent.ctx.provider,
@@ -14068,7 +14095,8 @@ ${content}
14068
14095
  },
14069
14096
  // Feed recent conversation so follow-ups ("do the same", "that file")
14070
14097
  // resolve against context instead of being refined blind.
14071
- history: recentTextTurns(agent.ctx.messages)
14098
+ history: recentTextTurns(agent.ctx.messages),
14099
+ ...enhanceReasoning ? { reasoning: enhanceReasoning } : {}
14072
14100
  });
14073
14101
  } finally {
14074
14102
  enhanceAbortRef.current = null;
@@ -14831,10 +14859,37 @@ async function runTui(opts) {
14831
14859
  } catch {
14832
14860
  }
14833
14861
  };
14862
+ const RAPID_EXIT_WINDOW_MS = 2e3;
14863
+ const RAPID_EXIT_THRESHOLD = 3;
14864
+ let ctrlCPressTimestamps = [];
14865
+ const forceExitViaRapidCtrlC = () => {
14866
+ detachListeners();
14867
+ unregisterTuiClient();
14868
+ stdout.write(BRACKETED_PASTE_OFF);
14869
+ stdout.write(MOUSE_OFF);
14870
+ process.exit(130);
14871
+ };
14834
14872
  const signals = ["SIGTERM", "SIGHUP", "SIGINT"];
14835
14873
  const signalHandler = () => cleanup();
14836
14874
  const exitHandler = () => cleanup();
14837
- for (const s2 of signals) process.on(s2, signalHandler);
14875
+ const sigintHandler = () => {
14876
+ const now = Date.now();
14877
+ ctrlCPressTimestamps = ctrlCPressTimestamps.filter((t) => now - t < RAPID_EXIT_WINDOW_MS);
14878
+ ctrlCPressTimestamps.push(now);
14879
+ if (ctrlCPressTimestamps.length >= RAPID_EXIT_THRESHOLD) {
14880
+ ctrlCPressTimestamps = [];
14881
+ forceExitViaRapidCtrlC();
14882
+ return;
14883
+ }
14884
+ cleanup();
14885
+ };
14886
+ process.on("SIGINT", sigintHandler);
14887
+ for (const s2 of ["SIGTERM", "SIGHUP"]) {
14888
+ try {
14889
+ process.on(s2, signalHandler);
14890
+ } catch {
14891
+ }
14892
+ }
14838
14893
  process.on("exit", exitHandler);
14839
14894
  const detachListeners = () => {
14840
14895
  for (const s2 of signals) process.off(s2, signalHandler);