@dexto/tui 1.8.2 → 1.8.4

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,4 +1,4 @@
1
- import type { AgentEventMap, DextoAgent, EventListener, SessionMetadata, SkillManager } from '@dexto/core';
1
+ import type { AgentEventMap, DextoAgent, EventArgs, EventListener, SessionMetadata, SkillManager } from '@dexto/core';
2
2
  import type { CommandDefinition } from './interactive-commands/command-parser.js';
3
3
  export interface TuiAgentCapabilities {
4
4
  supportedCommands?: readonly string[];
@@ -47,7 +47,7 @@ export interface TuiAgentBackend extends Pick<DextoAgent, 'stream' | 'stop' | 'r
47
47
  on: <K extends keyof AgentEventMap>(event: K, listener: EventListener<AgentEventMap[K]>, options?: {
48
48
  signal?: AbortSignal;
49
49
  }) => void;
50
- emit: <K extends keyof AgentEventMap>(event: K, ...args: AgentEventMap[K] extends void ? [] : [AgentEventMap[K]]) => boolean;
50
+ emit: <K extends keyof AgentEventMap>(event: K, ...args: EventArgs<AgentEventMap[K]>) => boolean;
51
51
  logger: RootLogger;
52
52
  config: {
53
53
  agentId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"agent-backend.d.ts","sourceRoot":"","sources":["../src/agent-backend.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-backend.d.ts","sourceRoot":"","sources":["../src/agent-backend.ts"],"names":[],"mappings":"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"}
@@ -67,17 +67,15 @@ function useTokenCounter({ agent, isActive }) {
67
67
  "llm:response",
68
68
  (payload) => {
69
69
  const usage = payload.tokenUsage;
70
- if (usage) {
71
- const rawInputTokens = usage.inputTokens ?? 0;
72
- const cacheWriteTokens = usage.cacheWriteTokens ?? 0;
73
- const inputTokens = Math.max(0, rawInputTokens - cacheWriteTokens);
74
- if (inputTokens > 0) {
75
- setLastInputTokens(inputTokens);
76
- }
77
- const outputTokens = usage.outputTokens ?? 0;
78
- if (outputTokens > 0) {
79
- setCumulativeOutputTokens((prev) => prev + outputTokens);
80
- }
70
+ const rawInputTokens = usage.inputTokens ?? 0;
71
+ const cacheWriteTokens = usage.cacheWriteTokens ?? 0;
72
+ const inputTokens = Math.max(0, rawInputTokens - cacheWriteTokens);
73
+ if (inputTokens > 0) {
74
+ setLastInputTokens(inputTokens);
75
+ }
76
+ const outputTokens = usage.outputTokens ?? 0;
77
+ if (outputTokens > 0) {
78
+ setCumulativeOutputTokens((prev) => prev + outputTokens);
81
79
  }
82
80
  currentCharCountRef.current = 0;
83
81
  setCurrentSegmentEstimate(0);
@@ -1 +1 @@
1
- {"version":3,"file":"useTokenCounter.d.ts","sourceRoot":"","sources":["../../src/hooks/useTokenCounter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,WAAW,mBAAmB;IAChC,+CAA+C;IAC/C,KAAK,EAAE,eAAe,CAAC;IACvB,qEAAqE;IACrE,QAAQ,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IAC/B,yDAAyD;IACzD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qDAAqD;IACrD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,yDAAyD;IACzD,YAAY,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,gBAAgB,EAAE,OAAO,CAAC;IAC1B,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;CACrB;AAsBD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,mBAAmB,GAAG,kBAAkB,CA6F5F"}
1
+ {"version":3,"file":"useTokenCounter.d.ts","sourceRoot":"","sources":["../../src/hooks/useTokenCounter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,WAAW,mBAAmB;IAChC,+CAA+C;IAC/C,KAAK,EAAE,eAAe,CAAC;IACvB,qEAAqE;IACrE,QAAQ,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IAC/B,yDAAyD;IACzD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qDAAqD;IACrD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,yDAAyD;IACzD,YAAY,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,gBAAgB,EAAE,OAAO,CAAC;IAC1B,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;CACrB;AAsBD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,mBAAmB,GAAG,kBAAkB,CA2F5F"}
@@ -44,17 +44,15 @@ function useTokenCounter({ agent, isActive }) {
44
44
  "llm:response",
45
45
  (payload) => {
46
46
  const usage = payload.tokenUsage;
47
- if (usage) {
48
- const rawInputTokens = usage.inputTokens ?? 0;
49
- const cacheWriteTokens = usage.cacheWriteTokens ?? 0;
50
- const inputTokens = Math.max(0, rawInputTokens - cacheWriteTokens);
51
- if (inputTokens > 0) {
52
- setLastInputTokens(inputTokens);
53
- }
54
- const outputTokens = usage.outputTokens ?? 0;
55
- if (outputTokens > 0) {
56
- setCumulativeOutputTokens((prev) => prev + outputTokens);
57
- }
47
+ const rawInputTokens = usage.inputTokens ?? 0;
48
+ const cacheWriteTokens = usage.cacheWriteTokens ?? 0;
49
+ const inputTokens = Math.max(0, rawInputTokens - cacheWriteTokens);
50
+ if (inputTokens > 0) {
51
+ setLastInputTokens(inputTokens);
52
+ }
53
+ const outputTokens = usage.outputTokens ?? 0;
54
+ if (outputTokens > 0) {
55
+ setCumulativeOutputTokens((prev) => prev + outputTokens);
58
56
  }
59
57
  currentCharCountRef.current = 0;
60
58
  setCurrentSegmentEstimate(0);
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { DextoAgent, AgentEventMap, EventListener, SessionMetadata, SkillManager } from '@dexto/core';
2
+ import { DextoAgent, AgentEventMap, EventListener, EventArgs, SessionMetadata, SkillManager } from '@dexto/core';
3
3
  import { LLMProvider } from '@dexto/llm';
4
4
 
5
5
  /**
@@ -241,7 +241,7 @@ interface TuiAgentBackend extends Pick<DextoAgent, 'stream' | 'stop' | 'run' | '
241
241
  on: <K extends keyof AgentEventMap>(event: K, listener: EventListener<AgentEventMap[K]>, options?: {
242
242
  signal?: AbortSignal;
243
243
  }) => void;
244
- emit: <K extends keyof AgentEventMap>(event: K, ...args: AgentEventMap[K] extends void ? [] : [AgentEventMap[K]]) => boolean;
244
+ emit: <K extends keyof AgentEventMap>(event: K, ...args: EventArgs<AgentEventMap[K]>) => boolean;
245
245
  logger: RootLogger;
246
246
  config: {
247
247
  agentId: string;
@@ -90,9 +90,6 @@ function hasMeaningfulTokenUsageForAnalytics(tokenUsage, estimatedCost) {
90
90
  if (estimatedCost !== void 0) {
91
91
  return true;
92
92
  }
93
- if (!tokenUsage) {
94
- return false;
95
- }
96
93
  return (tokenUsage.inputTokens ?? 0) > 0 || (tokenUsage.outputTokens ?? 0) > 0 || (tokenUsage.reasoningTokens ?? 0) > 0 || (tokenUsage.cacheReadTokens ?? 0) > 0 || (tokenUsage.cacheWriteTokens ?? 0) > 0 || (tokenUsage.totalTokens ?? 0) > 0;
97
94
  }
98
95
  async function processStream(iterator, setters, options) {
@@ -378,20 +375,18 @@ async function processStream(iterator, setters, options) {
378
375
  if (!useStreaming) {
379
376
  setUi((prev) => ({ ...prev, isThinking: false }));
380
377
  }
381
- if (event.tokenUsage) {
382
- const rawInputTokens = event.tokenUsage.inputTokens ?? 0;
383
- const cacheWriteTokens = event.tokenUsage.cacheWriteTokens ?? 0;
384
- const inputTokens = Math.max(0, rawInputTokens - cacheWriteTokens);
385
- if (inputTokens > 0) {
386
- state.lastInputTokens = inputTokens;
387
- }
388
- if (event.tokenUsage.outputTokens) {
389
- state.cumulativeOutputTokens += event.tokenUsage.outputTokens;
390
- }
378
+ const rawInputTokens = event.tokenUsage.inputTokens ?? 0;
379
+ const cacheWriteTokens = event.tokenUsage.cacheWriteTokens ?? 0;
380
+ const inputTokens = Math.max(0, rawInputTokens - cacheWriteTokens);
381
+ if (inputTokens > 0) {
382
+ state.lastInputTokens = inputTokens;
383
+ }
384
+ if (event.tokenUsage.outputTokens) {
385
+ state.cumulativeOutputTokens += event.tokenUsage.outputTokens;
391
386
  }
392
387
  if (hasMeaningfulTokenUsageForAnalytics(event.tokenUsage, event.estimatedCost)) {
393
388
  let estimateAccuracyPercent;
394
- const actualInputTokens = event.tokenUsage?.inputTokens;
389
+ const actualInputTokens = event.tokenUsage.inputTokens;
395
390
  if (event.estimatedInputTokens !== void 0 && actualInputTokens) {
396
391
  const diff = event.estimatedInputTokens - actualInputTokens;
397
392
  estimateAccuracyPercent = Math.round(diff / actualInputTokens * 100);
@@ -403,12 +398,12 @@ async function processStream(iterator, setters, options) {
403
398
  model: event.model,
404
399
  reasoningVariant: event.reasoningVariant ?? void 0,
405
400
  reasoningBudgetTokens: event.reasoningBudgetTokens ?? void 0,
406
- inputTokens: event.tokenUsage?.inputTokens,
407
- outputTokens: event.tokenUsage?.outputTokens,
408
- reasoningTokens: event.tokenUsage?.reasoningTokens,
409
- totalTokens: event.tokenUsage?.totalTokens,
410
- cacheReadTokens: event.tokenUsage?.cacheReadTokens,
411
- cacheWriteTokens: event.tokenUsage?.cacheWriteTokens,
401
+ inputTokens: event.tokenUsage.inputTokens,
402
+ outputTokens: event.tokenUsage.outputTokens,
403
+ reasoningTokens: event.tokenUsage.reasoningTokens,
404
+ totalTokens: event.tokenUsage.totalTokens,
405
+ cacheReadTokens: event.tokenUsage.cacheReadTokens,
406
+ cacheWriteTokens: event.tokenUsage.cacheWriteTokens,
412
407
  estimatedCostUsd: event.estimatedCost,
413
408
  inputCostUsd: event.costBreakdown?.inputUsd,
414
409
  outputCostUsd: event.costBreakdown?.outputUsd,
@@ -457,6 +452,20 @@ async function processStream(iterator, setters, options) {
457
452
  state.textFinalizedBeforeTool = false;
458
453
  break;
459
454
  }
455
+ case "interaction:blocked": {
456
+ setUi((prev) => ({ ...prev, isThinking: false }));
457
+ setMessages((prev) => [
458
+ ...prev,
459
+ {
460
+ id: event.messageId,
461
+ role: "assistant",
462
+ content: event.content,
463
+ timestamp: /* @__PURE__ */ new Date(),
464
+ isStreaming: false
465
+ }
466
+ ]);
467
+ break;
468
+ }
460
469
  case "llm:tool-call": {
461
470
  if ((0, import_messageFormatting.shouldHideTool)(event.toolName)) {
462
471
  break;
@@ -1 +1 @@
1
- {"version":3,"file":"processStream.d.ts","sourceRoot":"","sources":["../../src/services/processStream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAuB,MAAM,aAAa,CAAC;AAGvE,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAc,MAAM,mBAAmB,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAoEvE;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,2DAA2D;IAC3D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7D,oFAAoF;IACpF,kBAAkB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACpE,iFAAiF;IACjF,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACnE,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,kEAAkE;IAClE,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,mBAAmB,EAAE,YAAY,CAAC,CAAC,CAAC;IAC3F,4CAA4C;IAC5C,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,aAAa,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC;IAC9F,2CAA2C;IAC3C,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,aAAa,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC;IAC/F,4DAA4D;IAC5D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1E,uDAAuD;IACvD,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;CAC7E;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,2FAA2F;IAC3F,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,2FAA2F;IAC3F,mBAAmB,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAC1C,wFAAwF;IACxF,oBAAoB,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAC3C,yDAAyD;IACzD,QAAQ,EAAE,IAAI,CAAC,OAAO,aAAa,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;IAC5D,8DAA8D;IAC9D,YAAY,CAAC,EAAE,OAAO,+BAA+B,EAAE,wBAAwB,CAAC;IAChF,kEAAkE;IAClE,QAAQ,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,mBAAmB,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;CAC3F;AAoDD;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CAC/B,QAAQ,EAAE,qBAAqB,CAAC,cAAc,CAAC,EAC/C,OAAO,EAAE,oBAAoB,EAC7B,OAAO,EAAE,oBAAoB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAwtCf"}
1
+ {"version":3,"file":"processStream.d.ts","sourceRoot":"","sources":["../../src/services/processStream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAuB,MAAM,aAAa,CAAC;AAGvE,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAc,MAAM,mBAAmB,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAoEvE;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,2DAA2D;IAC3D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7D,oFAAoF;IACpF,kBAAkB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACpE,iFAAiF;IACjF,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACnE,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,kEAAkE;IAClE,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,mBAAmB,EAAE,YAAY,CAAC,CAAC,CAAC;IAC3F,4CAA4C;IAC5C,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,aAAa,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC;IAC9F,2CAA2C;IAC3C,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,aAAa,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC;IAC/F,4DAA4D;IAC5D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1E,uDAAuD;IACvD,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;CAC7E;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,2FAA2F;IAC3F,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,2FAA2F;IAC3F,mBAAmB,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAC1C,wFAAwF;IACxF,oBAAoB,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAC3C,yDAAyD;IACzD,QAAQ,EAAE,IAAI,CAAC,OAAO,aAAa,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;IAC5D,8DAA8D;IAC9D,YAAY,CAAC,EAAE,OAAO,+BAA+B,EAAE,wBAAwB,CAAC;IAChF,kEAAkE;IAClE,QAAQ,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,mBAAmB,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;CAC3F;AAgDD;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CAC/B,QAAQ,EAAE,qBAAqB,CAAC,cAAc,CAAC,EAC/C,OAAO,EAAE,oBAAoB,EAC7B,OAAO,EAAE,oBAAoB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAsuCf"}
@@ -57,9 +57,6 @@ function hasMeaningfulTokenUsageForAnalytics(tokenUsage, estimatedCost) {
57
57
  if (estimatedCost !== void 0) {
58
58
  return true;
59
59
  }
60
- if (!tokenUsage) {
61
- return false;
62
- }
63
60
  return (tokenUsage.inputTokens ?? 0) > 0 || (tokenUsage.outputTokens ?? 0) > 0 || (tokenUsage.reasoningTokens ?? 0) > 0 || (tokenUsage.cacheReadTokens ?? 0) > 0 || (tokenUsage.cacheWriteTokens ?? 0) > 0 || (tokenUsage.totalTokens ?? 0) > 0;
64
61
  }
65
62
  async function processStream(iterator, setters, options) {
@@ -345,20 +342,18 @@ async function processStream(iterator, setters, options) {
345
342
  if (!useStreaming) {
346
343
  setUi((prev) => ({ ...prev, isThinking: false }));
347
344
  }
348
- if (event.tokenUsage) {
349
- const rawInputTokens = event.tokenUsage.inputTokens ?? 0;
350
- const cacheWriteTokens = event.tokenUsage.cacheWriteTokens ?? 0;
351
- const inputTokens = Math.max(0, rawInputTokens - cacheWriteTokens);
352
- if (inputTokens > 0) {
353
- state.lastInputTokens = inputTokens;
354
- }
355
- if (event.tokenUsage.outputTokens) {
356
- state.cumulativeOutputTokens += event.tokenUsage.outputTokens;
357
- }
345
+ const rawInputTokens = event.tokenUsage.inputTokens ?? 0;
346
+ const cacheWriteTokens = event.tokenUsage.cacheWriteTokens ?? 0;
347
+ const inputTokens = Math.max(0, rawInputTokens - cacheWriteTokens);
348
+ if (inputTokens > 0) {
349
+ state.lastInputTokens = inputTokens;
350
+ }
351
+ if (event.tokenUsage.outputTokens) {
352
+ state.cumulativeOutputTokens += event.tokenUsage.outputTokens;
358
353
  }
359
354
  if (hasMeaningfulTokenUsageForAnalytics(event.tokenUsage, event.estimatedCost)) {
360
355
  let estimateAccuracyPercent;
361
- const actualInputTokens = event.tokenUsage?.inputTokens;
356
+ const actualInputTokens = event.tokenUsage.inputTokens;
362
357
  if (event.estimatedInputTokens !== void 0 && actualInputTokens) {
363
358
  const diff = event.estimatedInputTokens - actualInputTokens;
364
359
  estimateAccuracyPercent = Math.round(diff / actualInputTokens * 100);
@@ -370,12 +365,12 @@ async function processStream(iterator, setters, options) {
370
365
  model: event.model,
371
366
  reasoningVariant: event.reasoningVariant ?? void 0,
372
367
  reasoningBudgetTokens: event.reasoningBudgetTokens ?? void 0,
373
- inputTokens: event.tokenUsage?.inputTokens,
374
- outputTokens: event.tokenUsage?.outputTokens,
375
- reasoningTokens: event.tokenUsage?.reasoningTokens,
376
- totalTokens: event.tokenUsage?.totalTokens,
377
- cacheReadTokens: event.tokenUsage?.cacheReadTokens,
378
- cacheWriteTokens: event.tokenUsage?.cacheWriteTokens,
368
+ inputTokens: event.tokenUsage.inputTokens,
369
+ outputTokens: event.tokenUsage.outputTokens,
370
+ reasoningTokens: event.tokenUsage.reasoningTokens,
371
+ totalTokens: event.tokenUsage.totalTokens,
372
+ cacheReadTokens: event.tokenUsage.cacheReadTokens,
373
+ cacheWriteTokens: event.tokenUsage.cacheWriteTokens,
379
374
  estimatedCostUsd: event.estimatedCost,
380
375
  inputCostUsd: event.costBreakdown?.inputUsd,
381
376
  outputCostUsd: event.costBreakdown?.outputUsd,
@@ -424,6 +419,20 @@ async function processStream(iterator, setters, options) {
424
419
  state.textFinalizedBeforeTool = false;
425
420
  break;
426
421
  }
422
+ case "interaction:blocked": {
423
+ setUi((prev) => ({ ...prev, isThinking: false }));
424
+ setMessages((prev) => [
425
+ ...prev,
426
+ {
427
+ id: event.messageId,
428
+ role: "assistant",
429
+ content: event.content,
430
+ timestamp: /* @__PURE__ */ new Date(),
431
+ isStreaming: false
432
+ }
433
+ ]);
434
+ break;
435
+ }
427
436
  case "llm:tool-call": {
428
437
  if (shouldHideTool(event.toolName)) {
429
438
  break;
@@ -25,6 +25,22 @@ async function* eventStream(events) {
25
25
  yield event;
26
26
  }
27
27
  }
28
+ function llmResponse(overrides) {
29
+ return {
30
+ name: "llm:response",
31
+ sessionId: "test-session",
32
+ content: "Hello",
33
+ provider: "openai",
34
+ model: "gpt-4",
35
+ finishReason: "stop",
36
+ tokenUsage: {
37
+ inputTokens: 1,
38
+ outputTokens: 1,
39
+ totalTokens: 2
40
+ },
41
+ ...overrides
42
+ };
43
+ }
28
44
  function createSetters({
29
45
  steerMessages: initialSteerMessages = [],
30
46
  queuedMessages: initialQueuedMessages = []
@@ -137,6 +153,38 @@ function createSetters({
137
153
  (0, import_vitest.expect)(getSteerMessages()).toEqual([]);
138
154
  (0, import_vitest.expect)(getQueuedMessages()).toEqual([followUp]);
139
155
  });
156
+ (0, import_vitest.it)("renders blocked interactions as final assistant messages", async () => {
157
+ const { getMessages, getUi, setters } = createSetters();
158
+ await (0, import_processStream.processStream)(
159
+ eventStream([
160
+ { name: "llm:thinking", sessionId: "test-session" },
161
+ {
162
+ name: "interaction:blocked",
163
+ sessionId: "test-session",
164
+ content: "Error: blocked by policy",
165
+ provider: "openai",
166
+ model: "gpt-4",
167
+ messageId: "blocked-message"
168
+ }
169
+ ]),
170
+ setters,
171
+ {
172
+ useStreaming: true,
173
+ autoApproveEditsRef: { current: false },
174
+ bypassPermissionsRef: { current: false },
175
+ eventBus: { emit: import_vitest.vi.fn() }
176
+ }
177
+ );
178
+ (0, import_vitest.expect)(getUi().isThinking).toBe(false);
179
+ (0, import_vitest.expect)(getMessages()).toEqual([
180
+ import_vitest.expect.objectContaining({
181
+ id: "blocked-message",
182
+ role: "assistant",
183
+ content: "Error: blocked by policy",
184
+ isStreaming: false
185
+ })
186
+ ]);
187
+ });
140
188
  (0, import_vitest.it)("attaches streamed reasoning chunks to the assistant message", async () => {
141
189
  const { getMessages, getPendingMessages, setters } = createSetters();
142
190
  const events = [
@@ -159,11 +207,9 @@ function createSetters({
159
207
  chunkType: "text",
160
208
  content: "Hello"
161
209
  },
162
- {
163
- name: "llm:response",
164
- sessionId: "test-session",
210
+ llmResponse({
165
211
  content: "Hello"
166
- },
212
+ }),
167
213
  {
168
214
  name: "run:complete",
169
215
  sessionId: "test-session",
@@ -202,11 +248,9 @@ function createSetters({
202
248
  chunkType: "text",
203
249
  content: longText
204
250
  },
205
- {
206
- name: "llm:response",
207
- sessionId: "test-session",
251
+ llmResponse({
208
252
  content: longText
209
- },
253
+ }),
210
254
  {
211
255
  name: "run:complete",
212
256
  sessionId: "test-session",
@@ -244,11 +288,9 @@ function createSetters({
244
288
  chunkType: "text",
245
289
  content: "Hello"
246
290
  },
247
- {
248
- name: "llm:response",
249
- sessionId: "test-session",
291
+ llmResponse({
250
292
  content: "Hello"
251
- },
293
+ }),
252
294
  {
253
295
  name: "run:complete",
254
296
  sessionId: "test-session",
@@ -286,12 +328,10 @@ function createSetters({
286
328
  callId: "call-1",
287
329
  args: {}
288
330
  },
289
- {
290
- name: "llm:response",
291
- sessionId: "test-session",
331
+ llmResponse({
292
332
  content: "Final",
293
333
  reasoning: "R"
294
- },
334
+ }),
295
335
  {
296
336
  name: "run:complete",
297
337
  sessionId: "test-session",
@@ -348,9 +388,7 @@ function createSetters({
348
388
  const { setters } = createSetters();
349
389
  const events = [
350
390
  { name: "llm:thinking", sessionId: "test-session" },
351
- {
352
- name: "llm:response",
353
- sessionId: "test-session",
391
+ llmResponse({
354
392
  content: "Priced response",
355
393
  provider: "openai",
356
394
  model: "gpt-4",
@@ -368,7 +406,7 @@ function createSetters({
368
406
  outputTokens: 20,
369
407
  totalTokens: 30
370
408
  }
371
- },
409
+ }),
372
410
  {
373
411
  name: "run:complete",
374
412
  sessionId: "test-session",
@@ -24,6 +24,22 @@ async function* eventStream(events) {
24
24
  yield event;
25
25
  }
26
26
  }
27
+ function llmResponse(overrides) {
28
+ return {
29
+ name: "llm:response",
30
+ sessionId: "test-session",
31
+ content: "Hello",
32
+ provider: "openai",
33
+ model: "gpt-4",
34
+ finishReason: "stop",
35
+ tokenUsage: {
36
+ inputTokens: 1,
37
+ outputTokens: 1,
38
+ totalTokens: 2
39
+ },
40
+ ...overrides
41
+ };
42
+ }
27
43
  function createSetters({
28
44
  steerMessages: initialSteerMessages = [],
29
45
  queuedMessages: initialQueuedMessages = []
@@ -136,6 +152,38 @@ describe("processStream (reasoning)", () => {
136
152
  expect(getSteerMessages()).toEqual([]);
137
153
  expect(getQueuedMessages()).toEqual([followUp]);
138
154
  });
155
+ it("renders blocked interactions as final assistant messages", async () => {
156
+ const { getMessages, getUi, setters } = createSetters();
157
+ await processStream(
158
+ eventStream([
159
+ { name: "llm:thinking", sessionId: "test-session" },
160
+ {
161
+ name: "interaction:blocked",
162
+ sessionId: "test-session",
163
+ content: "Error: blocked by policy",
164
+ provider: "openai",
165
+ model: "gpt-4",
166
+ messageId: "blocked-message"
167
+ }
168
+ ]),
169
+ setters,
170
+ {
171
+ useStreaming: true,
172
+ autoApproveEditsRef: { current: false },
173
+ bypassPermissionsRef: { current: false },
174
+ eventBus: { emit: vi.fn() }
175
+ }
176
+ );
177
+ expect(getUi().isThinking).toBe(false);
178
+ expect(getMessages()).toEqual([
179
+ expect.objectContaining({
180
+ id: "blocked-message",
181
+ role: "assistant",
182
+ content: "Error: blocked by policy",
183
+ isStreaming: false
184
+ })
185
+ ]);
186
+ });
139
187
  it("attaches streamed reasoning chunks to the assistant message", async () => {
140
188
  const { getMessages, getPendingMessages, setters } = createSetters();
141
189
  const events = [
@@ -158,11 +206,9 @@ describe("processStream (reasoning)", () => {
158
206
  chunkType: "text",
159
207
  content: "Hello"
160
208
  },
161
- {
162
- name: "llm:response",
163
- sessionId: "test-session",
209
+ llmResponse({
164
210
  content: "Hello"
165
- },
211
+ }),
166
212
  {
167
213
  name: "run:complete",
168
214
  sessionId: "test-session",
@@ -201,11 +247,9 @@ describe("processStream (reasoning)", () => {
201
247
  chunkType: "text",
202
248
  content: longText
203
249
  },
204
- {
205
- name: "llm:response",
206
- sessionId: "test-session",
250
+ llmResponse({
207
251
  content: longText
208
- },
252
+ }),
209
253
  {
210
254
  name: "run:complete",
211
255
  sessionId: "test-session",
@@ -243,11 +287,9 @@ describe("processStream (reasoning)", () => {
243
287
  chunkType: "text",
244
288
  content: "Hello"
245
289
  },
246
- {
247
- name: "llm:response",
248
- sessionId: "test-session",
290
+ llmResponse({
249
291
  content: "Hello"
250
- },
292
+ }),
251
293
  {
252
294
  name: "run:complete",
253
295
  sessionId: "test-session",
@@ -285,12 +327,10 @@ describe("processStream (reasoning)", () => {
285
327
  callId: "call-1",
286
328
  args: {}
287
329
  },
288
- {
289
- name: "llm:response",
290
- sessionId: "test-session",
330
+ llmResponse({
291
331
  content: "Final",
292
332
  reasoning: "R"
293
- },
333
+ }),
294
334
  {
295
335
  name: "run:complete",
296
336
  sessionId: "test-session",
@@ -347,9 +387,7 @@ describe("processStream (reasoning)", () => {
347
387
  const { setters } = createSetters();
348
388
  const events = [
349
389
  { name: "llm:thinking", sessionId: "test-session" },
350
- {
351
- name: "llm:response",
352
- sessionId: "test-session",
390
+ llmResponse({
353
391
  content: "Priced response",
354
392
  provider: "openai",
355
393
  model: "gpt-4",
@@ -367,7 +405,7 @@ describe("processStream (reasoning)", () => {
367
405
  outputTokens: 20,
368
406
  totalTokens: 30
369
407
  }
370
- },
408
+ }),
371
409
  {
372
410
  name: "run:complete",
373
411
  sessionId: "test-session",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dexto/tui",
3
- "version": "1.8.2",
3
+ "version": "1.8.4",
4
4
  "description": "Interactive terminal UI for Dexto CLI",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -28,10 +28,10 @@
28
28
  "string-width": "^8.1.0",
29
29
  "strip-ansi": "^7.1.2",
30
30
  "wrap-ansi": "^9.0.2",
31
- "@dexto/agent-management": "1.8.2",
32
- "@dexto/core": "1.8.2",
33
- "@dexto/llm": "1.8.2",
34
- "@dexto/registry": "1.8.2"
31
+ "@dexto/core": "1.8.4",
32
+ "@dexto/agent-management": "1.8.4",
33
+ "@dexto/llm": "1.8.4",
34
+ "@dexto/registry": "1.8.4"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/react": "^19.0.0",