agent-nuvira 3.5.1 → 3.5.2

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.
Files changed (108) hide show
  1. package/dist/cli/chat.d.ts +42 -0
  2. package/dist/cli/chat.d.ts.map +1 -1
  3. package/dist/cli/chat.js +240 -16
  4. package/dist/cli/chat.js.map +1 -1
  5. package/dist/cli/edit.d.ts.map +1 -1
  6. package/dist/cli/edit.js +3 -2
  7. package/dist/cli/edit.js.map +1 -1
  8. package/dist/cli/execute.d.ts.map +1 -1
  9. package/dist/cli/execute.js +10 -3
  10. package/dist/cli/execute.js.map +1 -1
  11. package/dist/cli/loop-executor.d.ts +16 -0
  12. package/dist/cli/loop-executor.d.ts.map +1 -1
  13. package/dist/cli/loop-executor.js +9 -0
  14. package/dist/cli/loop-executor.js.map +1 -1
  15. package/dist/cli/plan.d.ts.map +1 -1
  16. package/dist/cli/plan.js +18 -6
  17. package/dist/cli/plan.js.map +1 -1
  18. package/dist/cli/run.d.ts.map +1 -1
  19. package/dist/cli/run.js +23 -8
  20. package/dist/cli/run.js.map +1 -1
  21. package/dist/cli/ui/answer-view.d.ts +38 -0
  22. package/dist/cli/ui/answer-view.d.ts.map +1 -0
  23. package/dist/cli/ui/answer-view.js +72 -0
  24. package/dist/cli/ui/answer-view.js.map +1 -0
  25. package/dist/cli/ui/cards.d.ts +61 -0
  26. package/dist/cli/ui/cards.d.ts.map +1 -0
  27. package/dist/cli/ui/cards.js +141 -0
  28. package/dist/cli/ui/cards.js.map +1 -0
  29. package/dist/cli/ui/highlight.d.ts +32 -0
  30. package/dist/cli/ui/highlight.d.ts.map +1 -0
  31. package/dist/cli/ui/highlight.js +261 -0
  32. package/dist/cli/ui/highlight.js.map +1 -0
  33. package/dist/cli/ui/index.d.ts +21 -0
  34. package/dist/cli/ui/index.d.ts.map +1 -0
  35. package/dist/cli/ui/index.js +14 -0
  36. package/dist/cli/ui/index.js.map +1 -0
  37. package/dist/cli/ui/markdown.d.ts +90 -0
  38. package/dist/cli/ui/markdown.d.ts.map +1 -0
  39. package/dist/cli/ui/markdown.js +292 -0
  40. package/dist/cli/ui/markdown.js.map +1 -0
  41. package/dist/cli/ui/presenter.d.ts +147 -0
  42. package/dist/cli/ui/presenter.d.ts.map +1 -0
  43. package/dist/cli/ui/presenter.js +313 -0
  44. package/dist/cli/ui/presenter.js.map +1 -0
  45. package/dist/cli/ui/render.d.ts +52 -0
  46. package/dist/cli/ui/render.d.ts.map +1 -0
  47. package/dist/cli/ui/render.js +384 -0
  48. package/dist/cli/ui/render.js.map +1 -0
  49. package/dist/cli/ui/theme.d.ts +36 -0
  50. package/dist/cli/ui/theme.d.ts.map +1 -0
  51. package/dist/cli/ui/theme.js +92 -0
  52. package/dist/cli/ui/theme.js.map +1 -0
  53. package/dist/inference/model-entitlement.d.ts +10 -0
  54. package/dist/inference/model-entitlement.d.ts.map +1 -1
  55. package/dist/inference/model-entitlement.js +1 -1
  56. package/dist/inference/model-entitlement.js.map +1 -1
  57. package/dist/learning/auto-router.d.ts +10 -1
  58. package/dist/learning/auto-router.d.ts.map +1 -1
  59. package/dist/learning/auto-router.js +63 -11
  60. package/dist/learning/auto-router.js.map +1 -1
  61. package/dist/learning/reasoning-trace.d.ts +21 -1
  62. package/dist/learning/reasoning-trace.d.ts.map +1 -1
  63. package/dist/learning/reasoning-trace.js.map +1 -1
  64. package/dist/learning/resilient-call.d.ts.map +1 -1
  65. package/dist/learning/resilient-call.js +70 -4
  66. package/dist/learning/resilient-call.js.map +1 -1
  67. package/dist/tools/process-liveness.d.ts +227 -0
  68. package/dist/tools/process-liveness.d.ts.map +1 -0
  69. package/dist/tools/process-liveness.js +486 -0
  70. package/dist/tools/process-liveness.js.map +1 -0
  71. package/dist/tools/registry.d.ts.map +1 -1
  72. package/dist/tools/registry.js +4 -2
  73. package/dist/tools/registry.js.map +1 -1
  74. package/dist/tools/run-registry.d.ts +282 -0
  75. package/dist/tools/run-registry.d.ts.map +1 -0
  76. package/dist/tools/run-registry.js +544 -0
  77. package/dist/tools/run-registry.js.map +1 -0
  78. package/dist/tools/run-terminal.d.ts +100 -2
  79. package/dist/tools/run-terminal.d.ts.map +1 -1
  80. package/dist/tools/run-terminal.js +841 -67
  81. package/dist/tools/run-terminal.js.map +1 -1
  82. package/dist/tools/tool-loop.d.ts +46 -0
  83. package/dist/tools/tool-loop.d.ts.map +1 -1
  84. package/dist/tools/tool-loop.js +115 -2
  85. package/dist/tools/tool-loop.js.map +1 -1
  86. package/dist/web-dashboard/chat-console.d.ts +25 -0
  87. package/dist/web-dashboard/chat-console.d.ts.map +1 -1
  88. package/dist/web-dashboard/chat-console.js +16 -1
  89. package/dist/web-dashboard/chat-console.js.map +1 -1
  90. package/dist/web-dashboard/server.d.ts.map +1 -1
  91. package/dist/web-dashboard/server.js +7 -1
  92. package/dist/web-dashboard/server.js.map +1 -1
  93. package/dist/web-dashboard/src/types.d.ts +32 -1
  94. package/dist/web-dashboard/src/types.d.ts.map +1 -1
  95. package/dist/web-dashboard/task-registry.d.ts +98 -0
  96. package/dist/web-dashboard/task-registry.d.ts.map +1 -0
  97. package/dist/web-dashboard/task-registry.js +159 -0
  98. package/dist/web-dashboard/task-registry.js.map +1 -0
  99. package/dist/web-dashboard/task-runner.d.ts +155 -5
  100. package/dist/web-dashboard/task-runner.d.ts.map +1 -1
  101. package/dist/web-dashboard/task-runner.js +505 -14
  102. package/dist/web-dashboard/task-runner.js.map +1 -1
  103. package/package.json +1 -1
  104. package/src/web-dashboard/public/assets/index-DycGBWwy.js +236 -0
  105. package/src/web-dashboard/public/assets/index-DycGBWwy.js.map +1 -0
  106. package/src/web-dashboard/public/index.html +1 -1
  107. package/src/web-dashboard/public/assets/index-Bik91KJh.js +0 -236
  108. package/src/web-dashboard/public/assets/index-Bik91KJh.js.map +0 -1
@@ -0,0 +1,313 @@
1
+ /**
2
+ * Presenter — decides HOW a model answer reaches the terminal, and owns the
3
+ * streaming lifecycle.
4
+ *
5
+ * THE ONE RULE: rich rendering is a TTY-only affordance. Pipes, CI, `--json-events`
6
+ * and `NUVIRA_UI=plain` all keep the historical plain-text behaviour, so a
7
+ * script consuming stdout is never handed escape codes or reflowed borders.
8
+ * That mirrors the fallback `PipelineBoard` already implements for its board.
9
+ *
10
+ * STREAMING. `AnswerStream` mounts Ink while tokens arrive. Ink's frame is
11
+ * transient, so `finish()` UNMOUNTS Ink and writes the final frame with the ANSI
12
+ * renderer — the same "unmount then write the final frame" step the board uses.
13
+ * The answer therefore survives in the transcript instead of being erased.
14
+ */
15
+ import { createElement } from 'react';
16
+ import { render } from 'ink';
17
+ import { renderMarkdown, renderCard } from './render.js';
18
+ import { attachShellCards, gitDiffCard, toolCallCard } from './cards.js';
19
+ import { resolveTheme } from './theme.js';
20
+ import { LiveAnswer } from './answer-view.js';
21
+ import { isJsonLogMode } from '../../enterprise/log.js';
22
+ /** True when the rich presentation layer may be used for this stream. */
23
+ export function shouldUseRichUi(opts = {}) {
24
+ const env = opts.env ?? process.env;
25
+ if (isJsonLogMode())
26
+ return false;
27
+ const mode = (env.NUVIRA_UI || '').trim().toLowerCase();
28
+ if (mode === 'plain' || mode === 'text' || mode === 'off')
29
+ return false;
30
+ if (opts.tty !== undefined)
31
+ return opts.tty;
32
+ const stream = opts.stream ?? process.stdout;
33
+ return stream.isTTY === true;
34
+ }
35
+ function resolve(opts) {
36
+ const env = opts.env ?? process.env;
37
+ const stream = opts.stream ?? process.stdout;
38
+ const { name, theme } = resolveTheme(env);
39
+ const width = opts.width ?? stream.columns ?? 80;
40
+ const rich = shouldUseRichUi(opts);
41
+ const color = opts.color ?? (name !== 'none' && !('NO_COLOR' in env));
42
+ return { rich, theme: opts.theme ?? theme, themeName: name, width, color, stream };
43
+ }
44
+ /**
45
+ * Render a complete markdown answer to the string that would be printed.
46
+ *
47
+ * The non-rich path is a BYTE-IDENTICAL passthrough: a piped or CI consumer
48
+ * must receive exactly what it received before this layer existed, so the
49
+ * markdown is never rewritten on the way out.
50
+ */
51
+ export function renderAnswer(markdown, opts = {}) {
52
+ if (!markdown)
53
+ return '';
54
+ const r = resolve(opts);
55
+ if (!r.rich)
56
+ return markdown;
57
+ return renderMarkdown(markdown, { theme: r.theme, width: r.width, color: r.color });
58
+ }
59
+ /**
60
+ * Print a complete answer. Returns the written string so callers (and tests)
61
+ * can assert on exactly what a surface produced.
62
+ *
63
+ * The non-rich path deliberately goes through `console.log` when no stream was
64
+ * injected: that is the channel this CLI has always used for answers, and both
65
+ * the test suite and any log-capturing wrapper depend on it. Rich output is
66
+ * written straight to the stream because it is a composed frame, not a line.
67
+ */
68
+ export function presentAnswer(markdown, opts = {}) {
69
+ if (!markdown)
70
+ return '';
71
+ const r = resolve(opts);
72
+ if (!r.rich) {
73
+ if (opts.stream)
74
+ r.stream.write(markdown + (markdown.endsWith('\n') ? '' : '\n'));
75
+ else
76
+ console.log(markdown);
77
+ return markdown;
78
+ }
79
+ const out = renderMarkdown(markdown, { theme: r.theme, width: r.width, color: r.color });
80
+ r.stream.write(out + (out.endsWith('\n') ? '' : '\n'));
81
+ return out;
82
+ }
83
+ /** Print a structured card (tool call, shell, diff, plan). */
84
+ export function presentCard(card, opts = {}) {
85
+ const r = resolve(opts);
86
+ const out = renderCard(card, { theme: r.theme, width: r.width, color: r.color });
87
+ r.stream.write(out + '\n');
88
+ return out;
89
+ }
90
+ /**
91
+ * A card sink for a surface with NO live Ink frame (the `execute` loop arm).
92
+ *
93
+ * Cards are written straight to the transcript as they arrive — no pause/resume
94
+ * is needed because nothing else owns the terminal. The finished tool call is
95
+ * the one that gets a card; `started` is ignored because the outcome is what a
96
+ * reader needs and a card that is replaced a moment later is noise.
97
+ *
98
+ * Off a real terminal this is INERT (no overrides, nothing written), so a piped
99
+ * or CI `execute` keeps the exact bytes it produced before cards existed.
100
+ */
101
+ export function createCardSink(opts = {}) {
102
+ if (!shouldUseRichUi(opts))
103
+ return { overrides: {}, stop: () => { } };
104
+ const write = (card) => {
105
+ presentCard(card, opts);
106
+ };
107
+ return {
108
+ overrides: {
109
+ onToolCall: (phase, info) => {
110
+ if (phase === 'called')
111
+ write(toolCallCard(info));
112
+ },
113
+ onGitDiff: (payload) => write(gitDiffCard(payload)),
114
+ },
115
+ stop: attachShellCards(write),
116
+ };
117
+ }
118
+ /**
119
+ * Live-streaming answer view.
120
+ *
121
+ * Usage:
122
+ * const stream = new AnswerStream({ header: 'nuvira · groq/llama-3.3-70b' });
123
+ * stream.begin();
124
+ * // ... onToken: (t) => stream.append(t) ...
125
+ * const final = stream.finish();
126
+ */
127
+ export class AnswerStream {
128
+ r;
129
+ text = '';
130
+ meta;
131
+ ink = null;
132
+ flushTimer = null;
133
+ pending = false;
134
+ closed = false;
135
+ constructor(meta = {}, opts = {}) {
136
+ this.r = resolve(opts);
137
+ this.meta = meta;
138
+ }
139
+ /** Begin the live view (mounts Ink on a TTY; a no-op otherwise). */
140
+ begin(meta = {}) {
141
+ this.meta = { ...this.meta, ...meta };
142
+ if (this.r.rich)
143
+ this.mount();
144
+ return this;
145
+ }
146
+ /** Append streamed text. Safe to call with empty/undefined deltas. */
147
+ append(delta) {
148
+ if (delta)
149
+ this.text += delta;
150
+ this.scheduleFlush();
151
+ return this;
152
+ }
153
+ /** Replace the inline note (e.g. "thinking…" → "writing…"). */
154
+ setNote(note) {
155
+ this.meta = { ...this.meta, note };
156
+ this.scheduleFlush();
157
+ return this;
158
+ }
159
+ /**
160
+ * Discard the text accumulated so far.
161
+ *
162
+ * Needed because `onToken` fires for EVERY model call in the tool loop, not
163
+ * only the final answer: without this, the next step's answer would be
164
+ * appended onto the previous step's preamble.
165
+ */
166
+ reset() {
167
+ this.text = '';
168
+ this.scheduleFlush();
169
+ return this;
170
+ }
171
+ /** The text accumulated so far. */
172
+ get current() {
173
+ return this.text;
174
+ }
175
+ /**
176
+ * Suspend the live view so static output can be written below it.
177
+ *
178
+ * Ink owns the frame, so anything printed while it is mounted collides with
179
+ * the next repaint. Cards are archived output (they must survive), so the
180
+ * frame is unmounted, the card written, then the frame remounted — the same
181
+ * stop/start discipline `PipelineBoard` uses around interactive prompts.
182
+ */
183
+ pause() {
184
+ if (this.flushTimer) {
185
+ clearTimeout(this.flushTimer);
186
+ this.flushTimer = null;
187
+ this.pending = false;
188
+ }
189
+ if (this.ink) {
190
+ try {
191
+ this.ink.unmount();
192
+ }
193
+ catch {
194
+ /* best-effort */
195
+ }
196
+ this.ink = null;
197
+ }
198
+ return this;
199
+ }
200
+ /** Remount the live view after {@link pause} (no-op when nothing was mounted). */
201
+ resume() {
202
+ if (!this.r.rich || this.closed)
203
+ return this;
204
+ this.mount();
205
+ this.repaint();
206
+ return this;
207
+ }
208
+ /**
209
+ * Print a card into the transcript, above the live view.
210
+ *
211
+ * Rich terminals only: a piped or CI stream keeps the exact bytes it produced
212
+ * before cards existed, which is also why the card is not attempted at all
213
+ * when rich output is unavailable.
214
+ */
215
+ card(card) {
216
+ if (!this.r.rich)
217
+ return;
218
+ const wasMounted = this.ink !== null;
219
+ if (wasMounted)
220
+ this.pause();
221
+ const out = renderCard(card, { theme: this.r.theme, width: this.r.width, color: this.r.color });
222
+ this.r.stream.write(out + '\n');
223
+ if (wasMounted)
224
+ this.resume();
225
+ }
226
+ mount() {
227
+ try {
228
+ this.ink = render(this.element(), {
229
+ stdout: this.r.stream,
230
+ patchConsole: false,
231
+ // The CLI owns SIGINT (the REPL installs its own handler); letting Ink
232
+ // also grab Ctrl+C would race that handler and can exit the process.
233
+ exitOnCtrlC: false,
234
+ });
235
+ }
236
+ catch {
237
+ // Rendering must never break a turn — fall back to no live view.
238
+ this.ink = null;
239
+ }
240
+ }
241
+ element(note) {
242
+ return createElement(LiveAnswer, {
243
+ text: this.text,
244
+ theme: this.r.theme,
245
+ header: this.meta.header,
246
+ headerColor: this.meta.headerColor,
247
+ note: note ?? this.meta.note,
248
+ });
249
+ }
250
+ /** Coalesce high-frequency token updates into ~20fps repaints. */
251
+ scheduleFlush() {
252
+ if (!this.ink || this.closed)
253
+ return;
254
+ if (this.pending)
255
+ return;
256
+ this.pending = true;
257
+ this.flushTimer = setTimeout(() => {
258
+ this.pending = false;
259
+ this.flushTimer = null;
260
+ this.repaint();
261
+ }, 50);
262
+ this.flushTimer.unref?.();
263
+ }
264
+ repaint() {
265
+ if (!this.ink)
266
+ return;
267
+ try {
268
+ this.ink.rerender(this.element());
269
+ }
270
+ catch {
271
+ /* a repaint failure must not break the stream */
272
+ }
273
+ }
274
+ /**
275
+ * Finish the stream: unmount the transient Ink frame, then write the final
276
+ * archival frame. Returns the final rendered string.
277
+ *
278
+ * `archive: false` unmounts WITHOUT printing a frame. A caller that will
279
+ * print the authoritative answer itself (the REPL, which renders the final
280
+ * `answer.content` rather than the raw token stream) must use it, or the
281
+ * answer would be printed twice.
282
+ */
283
+ finish(opts = {}) {
284
+ const archive = opts.archive ?? true;
285
+ if (this.closed)
286
+ return '';
287
+ this.closed = true;
288
+ if (this.flushTimer) {
289
+ clearTimeout(this.flushTimer);
290
+ this.flushTimer = null;
291
+ }
292
+ if (this.ink) {
293
+ try {
294
+ this.ink.unmount();
295
+ }
296
+ catch {
297
+ /* best-effort */
298
+ }
299
+ this.ink = null;
300
+ }
301
+ if (!archive)
302
+ return '';
303
+ // The final frame is the archival output and is always printed. Non-rich
304
+ // streams get the raw markdown, byte-identical to the pre-layer behaviour.
305
+ const out = this.r.rich
306
+ ? renderMarkdown(this.text, { theme: this.r.theme, width: this.r.width, color: this.r.color })
307
+ : this.text;
308
+ if (out)
309
+ this.r.stream.write(out + (out.endsWith('\n') ? '' : '\n'));
310
+ return out;
311
+ }
312
+ }
313
+ //# sourceMappingURL=presenter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presenter.js","sourceRoot":"","sources":["../../../src/cli/ui/presenter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * ANSI renderer — turns the shared markdown AST into a styled terminal string.
3
+ *
4
+ * This is the workhorse for two paths:
5
+ * - the FINAL frame of a streamed answer (the presenter unmounts Ink, then
6
+ * writes this string, exactly as `PipelineBoard.finish()` writes its final
7
+ * frame — so the answer is not erased by Ink's unmount)
8
+ * - NON-TTY output (pipes, CI, `--json-events`), where Ink must not mount
9
+ *
10
+ * It is intentionally a PURE function of (blocks, options): no globals, no
11
+ * terminal probing. Width and colour are passed in, so tests assert on plain
12
+ * strings with `color: false`.
13
+ */
14
+ import { type Block } from './markdown.js';
15
+ import { type Theme, type ThemeRole } from './theme.js';
16
+ export interface RenderOptions {
17
+ theme?: Theme;
18
+ /** Terminal width (columns). Defaults to 80. */
19
+ width?: number;
20
+ /** Emit ANSI colour. Defaults to true (chalk still honours its own level). */
21
+ color?: boolean;
22
+ }
23
+ /** Visible width of a string: ANSI stripped, wide glyphs counted as two. */
24
+ export declare function visibleWidth(s: string): number;
25
+ /** Render the block AST to a string. */
26
+ export declare function renderBlocks(blocks: readonly Block[], opts?: RenderOptions): string;
27
+ /**
28
+ * A card body line. A bare string is rendered muted; the object form lets a
29
+ * caller colour one line — which is what makes a git diff readable (added /
30
+ * removed / hunk lines each take their own role).
31
+ */
32
+ export interface CardLine {
33
+ text: string;
34
+ role?: ThemeRole;
35
+ }
36
+ export interface CardOptions {
37
+ icon?: string;
38
+ title: string;
39
+ lines?: Array<string | CardLine>;
40
+ /** Accent role for the title. */
41
+ role?: ThemeRole;
42
+ }
43
+ /**
44
+ * A bordered card for structured events (tool call, shell, diff, plan).
45
+ *
46
+ * Kept separate from block rendering because a card is a single visual unit
47
+ * whose height is computable before it is placed in a live view.
48
+ */
49
+ export declare function renderCard(card: CardOptions, opts?: RenderOptions): string;
50
+ /** Render a markdown string to an ANSI string. */
51
+ export declare function renderMarkdown(md: string, opts?: RenderOptions): string;
52
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/cli/ui/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,EAAiB,KAAK,KAAK,EAA8B,MAAM,eAAe,CAAC;AACtF,OAAO,EAAc,KAAK,KAAK,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAGpE,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AASD,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAqB9C;AA0QD,wCAAwC;AACxC,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,EAAE,IAAI,GAAE,aAAkB,GAAG,MAAM,CAkDvF;AAED;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC;IACjC,iCAAiC;IACjC,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,GAAE,aAAkB,GAAG,MAAM,CAwB9E;AAeD,kDAAkD;AAClD,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,GAAE,aAAkB,GAAG,MAAM,CAE3E"}