agent-nuvira 3.5.0 → 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 (134) hide show
  1. package/README.md +13 -13
  2. package/dist/agent-sdk/src/scaffold.d.ts +1 -1
  3. package/dist/agent-sdk/src/scaffold.js +1 -1
  4. package/dist/cli/chat.d.ts +159 -6
  5. package/dist/cli/chat.d.ts.map +1 -1
  6. package/dist/cli/chat.js +583 -35
  7. package/dist/cli/chat.js.map +1 -1
  8. package/dist/cli/duties.d.ts +11 -0
  9. package/dist/cli/duties.d.ts.map +1 -1
  10. package/dist/cli/duties.js +31 -0
  11. package/dist/cli/duties.js.map +1 -1
  12. package/dist/cli/edit.d.ts.map +1 -1
  13. package/dist/cli/edit.js +3 -2
  14. package/dist/cli/edit.js.map +1 -1
  15. package/dist/cli/execute.d.ts.map +1 -1
  16. package/dist/cli/execute.js +10 -3
  17. package/dist/cli/execute.js.map +1 -1
  18. package/dist/cli/loop-executor.d.ts +16 -0
  19. package/dist/cli/loop-executor.d.ts.map +1 -1
  20. package/dist/cli/loop-executor.js +9 -0
  21. package/dist/cli/loop-executor.js.map +1 -1
  22. package/dist/cli/models.d.ts.map +1 -1
  23. package/dist/cli/models.js +55 -0
  24. package/dist/cli/models.js.map +1 -1
  25. package/dist/cli/plan.d.ts.map +1 -1
  26. package/dist/cli/plan.js +18 -6
  27. package/dist/cli/plan.js.map +1 -1
  28. package/dist/cli/run.d.ts.map +1 -1
  29. package/dist/cli/run.js +23 -8
  30. package/dist/cli/run.js.map +1 -1
  31. package/dist/cli/ui/answer-view.d.ts +38 -0
  32. package/dist/cli/ui/answer-view.d.ts.map +1 -0
  33. package/dist/cli/ui/answer-view.js +72 -0
  34. package/dist/cli/ui/answer-view.js.map +1 -0
  35. package/dist/cli/ui/cards.d.ts +61 -0
  36. package/dist/cli/ui/cards.d.ts.map +1 -0
  37. package/dist/cli/ui/cards.js +141 -0
  38. package/dist/cli/ui/cards.js.map +1 -0
  39. package/dist/cli/ui/highlight.d.ts +32 -0
  40. package/dist/cli/ui/highlight.d.ts.map +1 -0
  41. package/dist/cli/ui/highlight.js +261 -0
  42. package/dist/cli/ui/highlight.js.map +1 -0
  43. package/dist/cli/ui/index.d.ts +21 -0
  44. package/dist/cli/ui/index.d.ts.map +1 -0
  45. package/dist/cli/ui/index.js +14 -0
  46. package/dist/cli/ui/index.js.map +1 -0
  47. package/dist/cli/ui/markdown.d.ts +90 -0
  48. package/dist/cli/ui/markdown.d.ts.map +1 -0
  49. package/dist/cli/ui/markdown.js +292 -0
  50. package/dist/cli/ui/markdown.js.map +1 -0
  51. package/dist/cli/ui/presenter.d.ts +147 -0
  52. package/dist/cli/ui/presenter.d.ts.map +1 -0
  53. package/dist/cli/ui/presenter.js +313 -0
  54. package/dist/cli/ui/presenter.js.map +1 -0
  55. package/dist/cli/ui/render.d.ts +52 -0
  56. package/dist/cli/ui/render.d.ts.map +1 -0
  57. package/dist/cli/ui/render.js +384 -0
  58. package/dist/cli/ui/render.js.map +1 -0
  59. package/dist/cli/ui/theme.d.ts +36 -0
  60. package/dist/cli/ui/theme.d.ts.map +1 -0
  61. package/dist/cli/ui/theme.js +92 -0
  62. package/dist/cli/ui/theme.js.map +1 -0
  63. package/dist/inference/model-entitlement.d.ts +10 -0
  64. package/dist/inference/model-entitlement.d.ts.map +1 -1
  65. package/dist/inference/model-entitlement.js +1 -1
  66. package/dist/inference/model-entitlement.js.map +1 -1
  67. package/dist/learning/auto-router.d.ts +38 -1
  68. package/dist/learning/auto-router.d.ts.map +1 -1
  69. package/dist/learning/auto-router.js +139 -8
  70. package/dist/learning/auto-router.js.map +1 -1
  71. package/dist/learning/duty-lease.d.ts +163 -0
  72. package/dist/learning/duty-lease.d.ts.map +1 -0
  73. package/dist/learning/duty-lease.js +301 -0
  74. package/dist/learning/duty-lease.js.map +1 -0
  75. package/dist/learning/model-first-router.d.ts +14 -0
  76. package/dist/learning/model-first-router.d.ts.map +1 -1
  77. package/dist/learning/model-first-router.js +54 -17
  78. package/dist/learning/model-first-router.js.map +1 -1
  79. package/dist/learning/model-warmup.d.ts +92 -0
  80. package/dist/learning/model-warmup.d.ts.map +1 -1
  81. package/dist/learning/model-warmup.js +137 -2
  82. package/dist/learning/model-warmup.js.map +1 -1
  83. package/dist/learning/reasoning-trace.d.ts +21 -1
  84. package/dist/learning/reasoning-trace.d.ts.map +1 -1
  85. package/dist/learning/reasoning-trace.js.map +1 -1
  86. package/dist/learning/resilient-call.d.ts.map +1 -1
  87. package/dist/learning/resilient-call.js +70 -4
  88. package/dist/learning/resilient-call.js.map +1 -1
  89. package/dist/learning/retry-patience.d.ts +139 -0
  90. package/dist/learning/retry-patience.d.ts.map +1 -0
  91. package/dist/learning/retry-patience.js +169 -0
  92. package/dist/learning/retry-patience.js.map +1 -0
  93. package/dist/tools/process-liveness.d.ts +227 -0
  94. package/dist/tools/process-liveness.d.ts.map +1 -0
  95. package/dist/tools/process-liveness.js +486 -0
  96. package/dist/tools/process-liveness.js.map +1 -0
  97. package/dist/tools/registry.d.ts.map +1 -1
  98. package/dist/tools/registry.js +4 -2
  99. package/dist/tools/registry.js.map +1 -1
  100. package/dist/tools/run-registry.d.ts +282 -0
  101. package/dist/tools/run-registry.d.ts.map +1 -0
  102. package/dist/tools/run-registry.js +544 -0
  103. package/dist/tools/run-registry.js.map +1 -0
  104. package/dist/tools/run-terminal.d.ts +100 -2
  105. package/dist/tools/run-terminal.d.ts.map +1 -1
  106. package/dist/tools/run-terminal.js +841 -67
  107. package/dist/tools/run-terminal.js.map +1 -1
  108. package/dist/tools/tool-loop.d.ts +87 -3
  109. package/dist/tools/tool-loop.d.ts.map +1 -1
  110. package/dist/tools/tool-loop.js +375 -6
  111. package/dist/tools/tool-loop.js.map +1 -1
  112. package/dist/web-dashboard/chat-console.d.ts +25 -0
  113. package/dist/web-dashboard/chat-console.d.ts.map +1 -1
  114. package/dist/web-dashboard/chat-console.js +16 -1
  115. package/dist/web-dashboard/chat-console.js.map +1 -1
  116. package/dist/web-dashboard/server.d.ts.map +1 -1
  117. package/dist/web-dashboard/server.js +7 -1
  118. package/dist/web-dashboard/server.js.map +1 -1
  119. package/dist/web-dashboard/src/types.d.ts +32 -1
  120. package/dist/web-dashboard/src/types.d.ts.map +1 -1
  121. package/dist/web-dashboard/task-registry.d.ts +98 -0
  122. package/dist/web-dashboard/task-registry.d.ts.map +1 -0
  123. package/dist/web-dashboard/task-registry.js +159 -0
  124. package/dist/web-dashboard/task-registry.js.map +1 -0
  125. package/dist/web-dashboard/task-runner.d.ts +155 -5
  126. package/dist/web-dashboard/task-runner.d.ts.map +1 -1
  127. package/dist/web-dashboard/task-runner.js +505 -14
  128. package/dist/web-dashboard/task-runner.js.map +1 -1
  129. package/package.json +4 -1
  130. package/src/web-dashboard/public/assets/index-DycGBWwy.js +236 -0
  131. package/src/web-dashboard/public/assets/index-DycGBWwy.js.map +1 -0
  132. package/src/web-dashboard/public/index.html +1 -1
  133. package/src/web-dashboard/public/assets/index-yky0dw5e.js +0 -236
  134. package/src/web-dashboard/public/assets/index-yky0dw5e.js.map +0 -1
@@ -0,0 +1,21 @@
1
+ /**
2
+ * CLI presentation layer — markdown, syntax highlighting, cards and streaming.
3
+ *
4
+ * Consumers import from here, never from the individual modules, so the internal
5
+ * split (parser → renderers → presenter) can change without touching call sites.
6
+ */
7
+ export { DARK_THEME, LIGHT_THEME, resolveTheme } from './theme.js';
8
+ export type { Theme, ThemeRole, ThemeName } from './theme.js';
9
+ export { highlightCode, normalizeLang } from './highlight.js';
10
+ export type { Token, TokenKind, TokenizedCode } from './highlight.js';
11
+ export { parseMarkdown, parseInline, inlineText, blocksToPlainText } from './markdown.js';
12
+ export type { Block, Inline, Align, ListItem } from './markdown.js';
13
+ export { renderMarkdown, renderBlocks, renderCard, visibleWidth } from './render.js';
14
+ export type { RenderOptions, CardOptions, CardLine } from './render.js';
15
+ export { attachShellCards, diffLineRole, formatDuration, gitDiffCard, shellCard, toolCallCard, } from './cards.js';
16
+ export type { ShellEndPayload, ToolCallCardInfo } from './cards.js';
17
+ export { LiveAnswer } from './answer-view.js';
18
+ export type { LiveAnswerProps } from './answer-view.js';
19
+ export { AnswerStream, createCardSink, presentAnswer, presentCard, renderAnswer, shouldUseRichUi, } from './presenter.js';
20
+ export type { CardSinkOverrides, PresenterOptions, StreamMeta } from './presenter.js';
21
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACnE,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE9D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC9D,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEtE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC1F,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEpE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACrF,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAExE,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,WAAW,EACX,SAAS,EACT,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,EACL,YAAY,EACZ,cAAc,EACd,aAAa,EACb,WAAW,EACX,YAAY,EACZ,eAAe,GAChB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * CLI presentation layer — markdown, syntax highlighting, cards and streaming.
3
+ *
4
+ * Consumers import from here, never from the individual modules, so the internal
5
+ * split (parser → renderers → presenter) can change without touching call sites.
6
+ */
7
+ export { DARK_THEME, LIGHT_THEME, resolveTheme } from './theme.js';
8
+ export { highlightCode, normalizeLang } from './highlight.js';
9
+ export { parseMarkdown, parseInline, inlineText, blocksToPlainText } from './markdown.js';
10
+ export { renderMarkdown, renderBlocks, renderCard, visibleWidth } from './render.js';
11
+ export { attachShellCards, diffLineRole, formatDuration, gitDiffCard, shellCard, toolCallCard, } from './cards.js';
12
+ export { LiveAnswer } from './answer-view.js';
13
+ export { AnswerStream, createCardSink, presentAnswer, presentCard, renderAnswer, shouldUseRichUi, } from './presenter.js';
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAGnE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAG9D,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAG1F,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGrF,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,WAAW,EACX,SAAS,EACT,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,OAAO,EACL,YAAY,EACZ,cAAc,EACd,aAAa,EACb,WAAW,EACX,YAAY,EACZ,eAAe,GAChB,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Markdown → shared AST parser.
3
+ *
4
+ * ONE PARSE, TWO RENDERERS. The CLI needs to show a model's markdown reply both
5
+ * live (Ink) and as a final frame / non-TTY fallback (a plain ANSI string).
6
+ * Parsing twice would guarantee drift, so the parse lives here and each renderer
7
+ * is a pure consumer of {@link Block}[]:
8
+ *
9
+ * markdown.ts → Block[] → render.ts (ANSI string)
10
+ * → answer-view.tsx (Ink elements)
11
+ *
12
+ * A single AST also makes the behaviour testable without a terminal: assertions
13
+ * are made against the parsed structure, not against bytes of coloured output.
14
+ *
15
+ * SCOPE. This is a deliberately small subset — headings, paragraphs, fenced
16
+ * code, ordered/unordered (nested) lists, pipe tables, block quotes and rules,
17
+ * with inline strong/em/code/link. That is what coding-agent answers actually
18
+ * use; anything else degrades to a paragraph. It is not a CommonMark engine.
19
+ */
20
+ import { type TokenizedCode } from './highlight.js';
21
+ export type Inline = {
22
+ kind: 'text';
23
+ text: string;
24
+ } | {
25
+ kind: 'code';
26
+ text: string;
27
+ } | {
28
+ kind: 'strong';
29
+ children: Inline[];
30
+ } | {
31
+ kind: 'em';
32
+ children: Inline[];
33
+ } | {
34
+ kind: 'link';
35
+ text: string;
36
+ href: string;
37
+ };
38
+ export type Align = 'left' | 'center' | 'right' | null;
39
+ export interface ListItem {
40
+ inlines: Inline[];
41
+ /** Nesting depth (0 = top level), derived from leading indentation. */
42
+ depth: number;
43
+ /** Whether THIS item used an ordered marker (`1.`). */
44
+ ordered: boolean;
45
+ /** The item's own number when ordered (0 for a bullet). */
46
+ index: number;
47
+ }
48
+ export type Block = {
49
+ type: 'heading';
50
+ level: number;
51
+ inlines: Inline[];
52
+ } | {
53
+ type: 'paragraph';
54
+ inlines: Inline[];
55
+ } | {
56
+ type: 'code';
57
+ lang: string;
58
+ code: string;
59
+ tokens: TokenizedCode;
60
+ } | {
61
+ type: 'list';
62
+ ordered: boolean;
63
+ start: number;
64
+ items: ListItem[];
65
+ } | {
66
+ type: 'table';
67
+ header: Inline[][];
68
+ rows: Inline[][][];
69
+ align: Align[];
70
+ } | {
71
+ type: 'quote';
72
+ blocks: Block[];
73
+ } | {
74
+ type: 'hr';
75
+ };
76
+ /** Parse a markdown string into blocks. */
77
+ export declare function parseMarkdown(md: string): Block[];
78
+ /**
79
+ * Parse inline markdown into styled runs.
80
+ *
81
+ * Deliberately non-greedy and pragmatic: an unmatched marker such as a lone `*`
82
+ * or a `[` without `](…)` is emitted as literal text, never swallowed, so
83
+ * ordinary prose containing asterisks and brackets survives intact.
84
+ */
85
+ export declare function parseInline(text: string): Inline[];
86
+ /** Plain text of an inline run — used for measuring and for non-colour output. */
87
+ export declare function inlineText(inlines: readonly Inline[]): string;
88
+ /** Plain text of a block tree — a markdown-aware fallback when colour is off. */
89
+ export declare function blocksToPlainText(blocks: readonly Block[]): string;
90
+ //# sourceMappingURL=markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../../src/cli/ui/markdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEnE,MAAM,MAAM,MAAM,GACd;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,IAAI,CAAC;AAEvD,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,OAAO,EAAE,OAAO,CAAC;IACjB,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,KAAK,GACb;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,GACrD;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,aAAa,CAAA;CAAE,GACnE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,QAAQ,EAAE,CAAA;CAAE,GACpE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAAC,KAAK,EAAE,KAAK,EAAE,CAAA;CAAE,GACzE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,KAAK,EAAE,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC;AAUnB,2CAA2C;AAC3C,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,KAAK,EAAE,CAGjD;AA6JD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CA2DlD;AAED,kFAAkF;AAClF,wBAAgB,UAAU,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAe7D;AAED,iFAAiF;AACjF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,GAAG,MAAM,CAkClE"}
@@ -0,0 +1,292 @@
1
+ /**
2
+ * Markdown → shared AST parser.
3
+ *
4
+ * ONE PARSE, TWO RENDERERS. The CLI needs to show a model's markdown reply both
5
+ * live (Ink) and as a final frame / non-TTY fallback (a plain ANSI string).
6
+ * Parsing twice would guarantee drift, so the parse lives here and each renderer
7
+ * is a pure consumer of {@link Block}[]:
8
+ *
9
+ * markdown.ts → Block[] → render.ts (ANSI string)
10
+ * → answer-view.tsx (Ink elements)
11
+ *
12
+ * A single AST also makes the behaviour testable without a terminal: assertions
13
+ * are made against the parsed structure, not against bytes of coloured output.
14
+ *
15
+ * SCOPE. This is a deliberately small subset — headings, paragraphs, fenced
16
+ * code, ordered/unordered (nested) lists, pipe tables, block quotes and rules,
17
+ * with inline strong/em/code/link. That is what coding-agent answers actually
18
+ * use; anything else degrades to a paragraph. It is not a CommonMark engine.
19
+ */
20
+ import { highlightCode } from './highlight.js';
21
+ const FENCE_RE = /^\s*(`{3,}|~{3,})\s*([\w+#.-]*)\s*$/;
22
+ const HEADING_RE = /^(#{1,6})\s+(.*?)\s*#*\s*$/;
23
+ const HR_RE = /^\s*(?:-{3,}|\*{3,}|_{3,})\s*$/;
24
+ const BULLET_RE = /^(\s*)([-*+])\s+(.*)$/;
25
+ const ORDERED_RE = /^(\s*)(\d{1,9})[.)]\s+(.*)$/;
26
+ const QUOTE_RE = /^\s*>\s?(.*)$/;
27
+ const TABLE_SEP_RE = /^\s*\|?\s*:?-{1,}:?\s*(\|\s*:?-{1,}:?\s*)*\|?\s*$/;
28
+ /** Parse a markdown string into blocks. */
29
+ export function parseMarkdown(md) {
30
+ const lines = (md ?? '').replace(/\r\n/g, '\n').replace(/\r/g, '\n').split('\n');
31
+ return parseBlocks(lines);
32
+ }
33
+ function parseBlocks(lines) {
34
+ const blocks = [];
35
+ let i = 0;
36
+ while (i < lines.length) {
37
+ const line = lines[i];
38
+ // Blank
39
+ if (line.trim() === '') {
40
+ i++;
41
+ continue;
42
+ }
43
+ // Fenced code
44
+ const fence = FENCE_RE.exec(line);
45
+ if (fence) {
46
+ const marker = fence[1][0];
47
+ const lang = fence[2] || '';
48
+ const body = [];
49
+ i++;
50
+ while (i < lines.length) {
51
+ const closing = new RegExp(`^\\s*${marker === '`' ? '`' : '~'}{3,}\\s*$`);
52
+ if (closing.test(lines[i])) {
53
+ i++;
54
+ break;
55
+ }
56
+ body.push(lines[i]);
57
+ i++;
58
+ }
59
+ const code = body.join('\n');
60
+ blocks.push({ type: 'code', lang, code, tokens: highlightCode(code, lang) });
61
+ continue;
62
+ }
63
+ // Heading
64
+ const heading = HEADING_RE.exec(line);
65
+ if (heading && !line.trimStart().startsWith('>')) {
66
+ blocks.push({ type: 'heading', level: heading[1].length, inlines: parseInline(heading[2]) });
67
+ i++;
68
+ continue;
69
+ }
70
+ // Horizontal rule
71
+ if (HR_RE.test(line)) {
72
+ blocks.push({ type: 'hr' });
73
+ i++;
74
+ continue;
75
+ }
76
+ // Block quote
77
+ if (QUOTE_RE.test(line)) {
78
+ const inner = [];
79
+ while (i < lines.length && (QUOTE_RE.test(lines[i]) || lines[i].trim() === '')) {
80
+ if (lines[i].trim() === '') {
81
+ // A blank line ends the quote unless another '>' follows.
82
+ if (!QUOTE_RE.test(lines[i + 1] ?? ''))
83
+ break;
84
+ inner.push('');
85
+ }
86
+ else {
87
+ inner.push(QUOTE_RE.exec(lines[i])[1]);
88
+ }
89
+ i++;
90
+ }
91
+ blocks.push({ type: 'quote', blocks: parseBlocks(inner) });
92
+ continue;
93
+ }
94
+ // List (unordered or ordered)
95
+ if (BULLET_RE.test(line) || ORDERED_RE.test(line)) {
96
+ const ordered = ORDERED_RE.test(line) && !BULLET_RE.test(line);
97
+ const start = ordered ? Number(ORDERED_RE.exec(line)[2]) : 1;
98
+ const items = [];
99
+ while (i < lines.length) {
100
+ const bullet = BULLET_RE.exec(lines[i]);
101
+ const num = ORDERED_RE.exec(lines[i]);
102
+ if (!bullet && !num)
103
+ break;
104
+ const m = bullet ?? num;
105
+ const indent = m[1].length;
106
+ const isOrdered = !bullet;
107
+ items.push({
108
+ inlines: parseInline(m[3]),
109
+ depth: Math.min(4, Math.floor(indent / 2)),
110
+ ordered: isOrdered,
111
+ index: isOrdered ? Number(num[2]) : 0,
112
+ });
113
+ i++;
114
+ // Skip blank separator lines between items.
115
+ if (lines[i]?.trim() === '' && (BULLET_RE.test(lines[i + 1] ?? '') || ORDERED_RE.test(lines[i + 1] ?? ''))) {
116
+ i++;
117
+ }
118
+ }
119
+ blocks.push({ type: 'list', ordered, start, items });
120
+ continue;
121
+ }
122
+ // Table (a header row followed by a separator row)
123
+ if (line.includes('|') && TABLE_SEP_RE.test(lines[i + 1] ?? '')) {
124
+ const header = splitRow(line);
125
+ const align = parseAlign(lines[i + 1]);
126
+ const rows = [];
127
+ i += 2;
128
+ while (i < lines.length && lines[i].includes('|') && lines[i].trim() !== '') {
129
+ rows.push(splitRow(lines[i]));
130
+ i++;
131
+ }
132
+ blocks.push({ type: 'table', header, rows, align });
133
+ continue;
134
+ }
135
+ // Paragraph — consecutive non-blank, non-structural lines.
136
+ const para = [];
137
+ while (i < lines.length && lines[i].trim() !== '' && !isBlockStart(lines[i], lines[i + 1])) {
138
+ para.push(lines[i].trim());
139
+ i++;
140
+ }
141
+ if (para.length) {
142
+ blocks.push({ type: 'paragraph', inlines: parseInline(para.join(' ')) });
143
+ }
144
+ else {
145
+ // Defensive: never loop forever on an unexpected line.
146
+ i++;
147
+ }
148
+ }
149
+ return blocks;
150
+ }
151
+ function isBlockStart(line, next) {
152
+ return (FENCE_RE.test(line) ||
153
+ HEADING_RE.test(line) ||
154
+ HR_RE.test(line) ||
155
+ QUOTE_RE.test(line) ||
156
+ BULLET_RE.test(line) ||
157
+ ORDERED_RE.test(line) ||
158
+ (line.includes('|') && TABLE_SEP_RE.test(next ?? '')));
159
+ }
160
+ function splitRow(line) {
161
+ const trimmed = line.trim().replace(/^\|/, '').replace(/\|$/, '');
162
+ return trimmed.split('|').map((cell) => parseInline(cell.trim()));
163
+ }
164
+ function parseAlign(sep) {
165
+ const cells = sep.trim().replace(/^\|/, '').replace(/\|$/, '').split('|');
166
+ return cells.map((c) => {
167
+ const t = c.trim();
168
+ const left = t.startsWith(':');
169
+ const right = t.endsWith(':');
170
+ if (left && right)
171
+ return 'center';
172
+ if (right)
173
+ return 'right';
174
+ if (left)
175
+ return 'left';
176
+ return null;
177
+ });
178
+ }
179
+ /**
180
+ * Parse inline markdown into styled runs.
181
+ *
182
+ * Deliberately non-greedy and pragmatic: an unmatched marker such as a lone `*`
183
+ * or a `[` without `](…)` is emitted as literal text, never swallowed, so
184
+ * ordinary prose containing asterisks and brackets survives intact.
185
+ */
186
+ export function parseInline(text) {
187
+ const out = [];
188
+ let buf = '';
189
+ const flush = () => {
190
+ if (buf) {
191
+ out.push({ kind: 'text', text: buf });
192
+ buf = '';
193
+ }
194
+ };
195
+ let i = 0;
196
+ while (i < text.length) {
197
+ const rest = text.slice(i);
198
+ // Inline code — highest precedence, spans markers as literals.
199
+ if (text[i] === '`') {
200
+ const end = text.indexOf('`', i + 1);
201
+ if (end !== -1) {
202
+ flush();
203
+ out.push({ kind: 'code', text: text.slice(i + 1, end) });
204
+ i = end + 1;
205
+ continue;
206
+ }
207
+ }
208
+ // Strong: ** or __
209
+ const strong = /^(\*\*|__)([\s\S]+?)\1/.exec(rest);
210
+ if (strong) {
211
+ flush();
212
+ out.push({ kind: 'strong', children: parseInline(strong[2]) });
213
+ i += strong[0].length;
214
+ continue;
215
+ }
216
+ // Emphasis: * or _
217
+ const em = /^(\*|_)([^\s*_][\s\S]*?)\1/.exec(rest);
218
+ if (em) {
219
+ flush();
220
+ out.push({ kind: 'em', children: parseInline(em[2]) });
221
+ i += em[0].length;
222
+ continue;
223
+ }
224
+ // Link: [text](href)
225
+ const link = /^\[([^\]]*)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/.exec(rest);
226
+ if (link) {
227
+ flush();
228
+ out.push({ kind: 'link', text: link[1], href: link[2] });
229
+ i += link[0].length;
230
+ continue;
231
+ }
232
+ buf += text[i];
233
+ i++;
234
+ }
235
+ flush();
236
+ return out.length ? out : [{ kind: 'text', text }];
237
+ }
238
+ /** Plain text of an inline run — used for measuring and for non-colour output. */
239
+ export function inlineText(inlines) {
240
+ return inlines
241
+ .map((inl) => {
242
+ switch (inl.kind) {
243
+ case 'text':
244
+ case 'code':
245
+ return inl.text;
246
+ case 'link':
247
+ return inl.text;
248
+ case 'strong':
249
+ case 'em':
250
+ return inlineText(inl.children);
251
+ }
252
+ })
253
+ .join('');
254
+ }
255
+ /** Plain text of a block tree — a markdown-aware fallback when colour is off. */
256
+ export function blocksToPlainText(blocks) {
257
+ const lines = [];
258
+ for (const b of blocks) {
259
+ switch (b.type) {
260
+ case 'heading':
261
+ lines.push(inlineText(b.inlines), '');
262
+ break;
263
+ case 'paragraph':
264
+ lines.push(inlineText(b.inlines), '');
265
+ break;
266
+ case 'code':
267
+ lines.push(...b.code.split('\n'), '');
268
+ break;
269
+ case 'hr':
270
+ lines.push('', '');
271
+ break;
272
+ case 'quote':
273
+ lines.push(blocksToPlainText(b.blocks).trimEnd(), '');
274
+ break;
275
+ case 'list':
276
+ b.items.forEach((it, idx) => {
277
+ const bullet = it.ordered ? `${it.index || b.start + idx}. ` : '- ';
278
+ lines.push(' '.repeat(it.depth) + bullet + inlineText(it.inlines));
279
+ });
280
+ lines.push('');
281
+ break;
282
+ case 'table':
283
+ lines.push(b.header.map(inlineText).join(' | '));
284
+ for (const row of b.rows)
285
+ lines.push(row.map(inlineText).join(' | '));
286
+ lines.push('');
287
+ break;
288
+ }
289
+ }
290
+ return lines.join('\n').replace(/\n{3,}/g, '\n\n').replace(/\n+$/, '\n');
291
+ }
292
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../../src/cli/ui/markdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,147 @@
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 { type CardOptions } from './render.js';
16
+ import { type ToolCallCardInfo } from './cards.js';
17
+ import { type Theme, type ThemeRole } from './theme.js';
18
+ import type { GitDiffPayload } from '../../tools/git-tool.js';
19
+ export interface PresenterOptions {
20
+ stream?: NodeJS.WriteStream;
21
+ /** Force rich/plain instead of probing the stream. */
22
+ tty?: boolean;
23
+ theme?: Theme;
24
+ width?: number;
25
+ color?: boolean;
26
+ env?: NodeJS.ProcessEnv;
27
+ }
28
+ /** True when the rich presentation layer may be used for this stream. */
29
+ export declare function shouldUseRichUi(opts?: PresenterOptions): boolean;
30
+ /**
31
+ * Render a complete markdown answer to the string that would be printed.
32
+ *
33
+ * The non-rich path is a BYTE-IDENTICAL passthrough: a piped or CI consumer
34
+ * must receive exactly what it received before this layer existed, so the
35
+ * markdown is never rewritten on the way out.
36
+ */
37
+ export declare function renderAnswer(markdown: string, opts?: PresenterOptions): string;
38
+ /**
39
+ * Print a complete answer. Returns the written string so callers (and tests)
40
+ * can assert on exactly what a surface produced.
41
+ *
42
+ * The non-rich path deliberately goes through `console.log` when no stream was
43
+ * injected: that is the channel this CLI has always used for answers, and both
44
+ * the test suite and any log-capturing wrapper depend on it. Rich output is
45
+ * written straight to the stream because it is a composed frame, not a line.
46
+ */
47
+ export declare function presentAnswer(markdown: string, opts?: PresenterOptions): string;
48
+ /** Print a structured card (tool call, shell, diff, plan). */
49
+ export declare function presentCard(card: CardOptions, opts?: PresenterOptions): string;
50
+ /** The turn options a card sink supplies (shape-compatible with the chat and
51
+ * loop-executor `onToolCall` / `onGitDiff` seams). */
52
+ export interface CardSinkOverrides {
53
+ onToolCall?: (phase: 'started' | 'called', info: ToolCallCardInfo) => void;
54
+ onGitDiff?: (payload: GitDiffPayload) => void;
55
+ }
56
+ /**
57
+ * A card sink for a surface with NO live Ink frame (the `execute` loop arm).
58
+ *
59
+ * Cards are written straight to the transcript as they arrive — no pause/resume
60
+ * is needed because nothing else owns the terminal. The finished tool call is
61
+ * the one that gets a card; `started` is ignored because the outcome is what a
62
+ * reader needs and a card that is replaced a moment later is noise.
63
+ *
64
+ * Off a real terminal this is INERT (no overrides, nothing written), so a piped
65
+ * or CI `execute` keeps the exact bytes it produced before cards existed.
66
+ */
67
+ export declare function createCardSink(opts?: PresenterOptions): {
68
+ overrides: CardSinkOverrides;
69
+ stop: () => void;
70
+ };
71
+ export interface StreamMeta {
72
+ header?: string;
73
+ headerColor?: ThemeRole;
74
+ note?: string;
75
+ }
76
+ /**
77
+ * Live-streaming answer view.
78
+ *
79
+ * Usage:
80
+ * const stream = new AnswerStream({ header: 'nuvira · groq/llama-3.3-70b' });
81
+ * stream.begin();
82
+ * // ... onToken: (t) => stream.append(t) ...
83
+ * const final = stream.finish();
84
+ */
85
+ export declare class AnswerStream {
86
+ private readonly r;
87
+ private text;
88
+ private meta;
89
+ private ink;
90
+ private flushTimer;
91
+ private pending;
92
+ private closed;
93
+ constructor(meta?: StreamMeta, opts?: PresenterOptions);
94
+ /** Begin the live view (mounts Ink on a TTY; a no-op otherwise). */
95
+ begin(meta?: StreamMeta): this;
96
+ /** Append streamed text. Safe to call with empty/undefined deltas. */
97
+ append(delta: string | undefined): this;
98
+ /** Replace the inline note (e.g. "thinking…" → "writing…"). */
99
+ setNote(note: string | undefined): this;
100
+ /**
101
+ * Discard the text accumulated so far.
102
+ *
103
+ * Needed because `onToken` fires for EVERY model call in the tool loop, not
104
+ * only the final answer: without this, the next step's answer would be
105
+ * appended onto the previous step's preamble.
106
+ */
107
+ reset(): this;
108
+ /** The text accumulated so far. */
109
+ get current(): string;
110
+ /**
111
+ * Suspend the live view so static output can be written below it.
112
+ *
113
+ * Ink owns the frame, so anything printed while it is mounted collides with
114
+ * the next repaint. Cards are archived output (they must survive), so the
115
+ * frame is unmounted, the card written, then the frame remounted — the same
116
+ * stop/start discipline `PipelineBoard` uses around interactive prompts.
117
+ */
118
+ pause(): this;
119
+ /** Remount the live view after {@link pause} (no-op when nothing was mounted). */
120
+ resume(): this;
121
+ /**
122
+ * Print a card into the transcript, above the live view.
123
+ *
124
+ * Rich terminals only: a piped or CI stream keeps the exact bytes it produced
125
+ * before cards existed, which is also why the card is not attempted at all
126
+ * when rich output is unavailable.
127
+ */
128
+ card(card: CardOptions): void;
129
+ private mount;
130
+ private element;
131
+ /** Coalesce high-frequency token updates into ~20fps repaints. */
132
+ private scheduleFlush;
133
+ private repaint;
134
+ /**
135
+ * Finish the stream: unmount the transient Ink frame, then write the final
136
+ * archival frame. Returns the final rendered string.
137
+ *
138
+ * `archive: false` unmounts WITHOUT printing a frame. A caller that will
139
+ * print the authoritative answer itself (the REPL, which renders the final
140
+ * `answer.content` rather than the raw token stream) must use it, or the
141
+ * answer would be printed twice.
142
+ */
143
+ finish(opts?: {
144
+ archive?: boolean;
145
+ }): string;
146
+ }
147
+ //# sourceMappingURL=presenter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presenter.d.ts","sourceRoot":"","sources":["../../../src/cli/ui/presenter.ts"],"names":[],"mappings":"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"}