@bahulam/code 0.1.6 → 0.1.8

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 (204) hide show
  1. package/LICENSE +1 -1
  2. package/NOTICE +6 -6
  3. package/README.md +11 -18
  4. package/package.json +11 -11
  5. package/src/agents/loader.mjs +1 -1
  6. package/src/agents/workflow_loader.mjs +2 -2
  7. package/src/auth/{tarang-auth.mjs → bahulam-auth.mjs} +4 -3
  8. package/src/commands/agent.mjs +3 -3
  9. package/src/commands/device.mjs +2 -2
  10. package/src/commands/pair.mjs +2 -2
  11. package/src/commands/remote.mjs +3 -3
  12. package/src/commands/workflow.mjs +5 -5
  13. package/src/config/env.mjs +9 -2
  14. package/src/config/memory-loader.mjs +1 -1
  15. package/src/config/model-catalog-default.json +4 -3
  16. package/src/config/model-catalog.mjs +2 -0
  17. package/src/config/settings.mjs +2 -2
  18. package/src/context/prose-chunker.mjs +162 -5
  19. package/src/core/agent-loop.mjs +17 -0
  20. package/src/core/attachments.mjs +66 -4
  21. package/src/core/backend-url.mjs +11 -12
  22. package/src/core/bundled-runtime.mjs +1 -1
  23. package/src/core/callback-client.mjs +1 -1
  24. package/src/core/headless.mjs +18 -4
  25. package/src/core/jsonl-writer.mjs +18 -18
  26. package/src/core/lint-resolver.mjs +472 -0
  27. package/src/core/local-agent.mjs +40 -8
  28. package/src/core/local-store.mjs +5 -1
  29. package/src/core/mode-selector.mjs +1 -1
  30. package/src/core/output-filter.mjs +22 -26
  31. package/src/core/pricing.mjs +10 -3
  32. package/src/core/project-artifacts.mjs +3 -3
  33. package/src/core/project-context-loader.mjs +9 -9
  34. package/src/core/settings-sync.mjs +1 -1
  35. package/src/core/stagnation.mjs +61 -1
  36. package/src/core/stream-client.mjs +13 -8
  37. package/src/core/system-prompt.mjs +2 -2
  38. package/src/core/tool-executor.mjs +178 -84
  39. package/src/daemon/http-dashboard.mjs +400 -0
  40. package/src/daemon/session-core.mjs +1 -0
  41. package/src/local-service/agent-relay.mjs +868 -0
  42. package/src/local-service/approval-bridge.mjs +222 -0
  43. package/src/local-service/browser.mjs +24 -0
  44. package/src/local-service/command.mjs +155 -0
  45. package/src/local-service/file-access.mjs +393 -0
  46. package/src/local-service/machine.mjs +86 -0
  47. package/src/local-service/paths.mjs +29 -0
  48. package/src/local-service/preview-converters.mjs +260 -0
  49. package/src/local-service/server.mjs +2644 -0
  50. package/src/local-service/session-store.mjs +221 -0
  51. package/src/mcp/client.mjs +4 -4
  52. package/src/onboarding/preflight.mjs +2 -2
  53. package/src/terminal/agents.mjs +2 -2
  54. package/src/terminal/analytics.mjs +2 -6
  55. package/src/terminal/ansi.mjs +11 -3
  56. package/src/terminal/main.mjs +43 -17
  57. package/src/terminal/model-catalog-display.mjs +111 -0
  58. package/src/terminal/repl-format.mjs +4 -1
  59. package/src/terminal/repl-model-form.mjs +81 -14
  60. package/src/terminal/repl-render.mjs +37 -7
  61. package/src/terminal/repl-resume.mjs +2 -2
  62. package/src/terminal/repl-state.mjs +12 -0
  63. package/src/terminal/repl.mjs +248 -70
  64. package/src/terminal/tool-display.mjs +32 -0
  65. package/src/terminal/watch-state.mjs +118 -0
  66. package/src/tools/agent.mjs +2 -2
  67. package/src/tools/analyze-image.mjs +158 -0
  68. package/src/tools/bash.mjs +11 -9
  69. package/src/tools/generate-image.mjs +411 -0
  70. package/src/tools/lint.mjs +24 -43
  71. package/src/tools/project-overview.mjs +12 -12
  72. package/src/tools/registry.mjs +4 -0
  73. package/src/ui/formatter.mjs +2 -2
  74. package/src/ui/icons.mjs +2 -0
  75. package/src/ui/input-dock.mjs +7 -7
  76. package/src/ui/palette.mjs +1 -1
  77. package/src/ui/slash-commands.mjs +4 -6
  78. package/src/ui/spinner.mjs +1 -1
  79. package/src/ui/term.mjs +2 -6
  80. package/src/ui/tool-card.mjs +81 -6
  81. package/pulse/app/activity/page.tsx +0 -190
  82. package/pulse/app/api/activity/route.ts +0 -138
  83. package/pulse/app/api/benchmark/route.ts +0 -113
  84. package/pulse/app/api/benchmarks/route.ts +0 -195
  85. package/pulse/app/api/costs/route.ts +0 -88
  86. package/pulse/app/api/export/route.ts +0 -77
  87. package/pulse/app/api/history/route.ts +0 -11
  88. package/pulse/app/api/import/route.ts +0 -31
  89. package/pulse/app/api/memory/route.ts +0 -50
  90. package/pulse/app/api/plans/route.ts +0 -9
  91. package/pulse/app/api/projects/[slug]/route.ts +0 -96
  92. package/pulse/app/api/projects/route.ts +0 -121
  93. package/pulse/app/api/sessions/[id]/replay/route.ts +0 -20
  94. package/pulse/app/api/sessions/[id]/route.ts +0 -31
  95. package/pulse/app/api/sessions/route.ts +0 -112
  96. package/pulse/app/api/settings/route.ts +0 -14
  97. package/pulse/app/api/stats/route.ts +0 -143
  98. package/pulse/app/api/todos/route.ts +0 -9
  99. package/pulse/app/api/tools/route.ts +0 -160
  100. package/pulse/app/benchmarks/page.tsx +0 -224
  101. package/pulse/app/costs/page.tsx +0 -179
  102. package/pulse/app/export/page.tsx +0 -465
  103. package/pulse/app/favicon.ico +0 -0
  104. package/pulse/app/globals.css +0 -263
  105. package/pulse/app/help/page.tsx +0 -143
  106. package/pulse/app/history/page.tsx +0 -157
  107. package/pulse/app/layout.tsx +0 -46
  108. package/pulse/app/memory/page.tsx +0 -365
  109. package/pulse/app/overview-client.tsx +0 -393
  110. package/pulse/app/page.tsx +0 -14
  111. package/pulse/app/plans/page.tsx +0 -308
  112. package/pulse/app/projects/[slug]/page.tsx +0 -390
  113. package/pulse/app/projects/page.tsx +0 -110
  114. package/pulse/app/sessions/[id]/page.tsx +0 -243
  115. package/pulse/app/sessions/page.tsx +0 -39
  116. package/pulse/app/settings/page.tsx +0 -188
  117. package/pulse/app/todos/page.tsx +0 -211
  118. package/pulse/app/tools/page.tsx +0 -249
  119. package/pulse/cli.js +0 -164
  120. package/pulse/components/activity/day-of-week-chart.tsx +0 -35
  121. package/pulse/components/activity/streak-card.tsx +0 -36
  122. package/pulse/components/costs/cache-efficiency-panel.tsx +0 -76
  123. package/pulse/components/costs/cost-by-project-chart.tsx +0 -48
  124. package/pulse/components/costs/cost-over-time-chart.tsx +0 -95
  125. package/pulse/components/costs/model-token-table.tsx +0 -60
  126. package/pulse/components/global-search.tsx +0 -193
  127. package/pulse/components/keyboard-nav-provider.tsx +0 -23
  128. package/pulse/components/layout/bottom-nav.tsx +0 -53
  129. package/pulse/components/layout/client-layout.tsx +0 -31
  130. package/pulse/components/layout/sidebar-context.tsx +0 -50
  131. package/pulse/components/layout/sidebar.tsx +0 -183
  132. package/pulse/components/layout/top-bar.tsx +0 -121
  133. package/pulse/components/overview/activity-heatmap.tsx +0 -107
  134. package/pulse/components/overview/conversation-table.tsx +0 -148
  135. package/pulse/components/overview/model-breakdown-donut.tsx +0 -95
  136. package/pulse/components/overview/peak-hours-chart.tsx +0 -87
  137. package/pulse/components/overview/project-activity-donut.tsx +0 -96
  138. package/pulse/components/overview/stat-card.tsx +0 -102
  139. package/pulse/components/overview/usage-over-time-chart.tsx +0 -166
  140. package/pulse/components/projects/project-card.tsx +0 -175
  141. package/pulse/components/sessions/replay/assistant-markdown.tsx +0 -94
  142. package/pulse/components/sessions/replay/compaction-card.tsx +0 -25
  143. package/pulse/components/sessions/replay/session-sidebar.tsx +0 -231
  144. package/pulse/components/sessions/replay/token-accumulation-chart.tsx +0 -98
  145. package/pulse/components/sessions/replay/tool-call-badge.tsx +0 -127
  146. package/pulse/components/sessions/replay/turn-cards.tsx +0 -220
  147. package/pulse/components/sessions/replay/user-tool-result.tsx +0 -158
  148. package/pulse/components/sessions/session-badges.tsx +0 -49
  149. package/pulse/components/sessions/session-table.tsx +0 -299
  150. package/pulse/components/theme-provider.tsx +0 -44
  151. package/pulse/components/tools/feature-adoption-table.tsx +0 -58
  152. package/pulse/components/tools/mcp-server-panel.tsx +0 -45
  153. package/pulse/components/tools/tool-ranking-chart.tsx +0 -57
  154. package/pulse/components/tools/version-history-table.tsx +0 -32
  155. package/pulse/components/ui/alert.tsx +0 -66
  156. package/pulse/components/ui/badge.tsx +0 -48
  157. package/pulse/components/ui/breadcrumb.tsx +0 -109
  158. package/pulse/components/ui/button.tsx +0 -64
  159. package/pulse/components/ui/calendar.tsx +0 -220
  160. package/pulse/components/ui/card.tsx +0 -92
  161. package/pulse/components/ui/command.tsx +0 -158
  162. package/pulse/components/ui/dialog.tsx +0 -158
  163. package/pulse/components/ui/input.tsx +0 -21
  164. package/pulse/components/ui/popover.tsx +0 -89
  165. package/pulse/components/ui/progress.tsx +0 -31
  166. package/pulse/components/ui/select.tsx +0 -190
  167. package/pulse/components/ui/separator.tsx +0 -28
  168. package/pulse/components/ui/sheet.tsx +0 -143
  169. package/pulse/components/ui/skeleton.tsx +0 -13
  170. package/pulse/components/ui/table.tsx +0 -116
  171. package/pulse/components/ui/tabs.tsx +0 -91
  172. package/pulse/components/ui/tooltip.tsx +0 -57
  173. package/pulse/components/use-global-keyboard-nav.ts +0 -79
  174. package/pulse/components.json +0 -23
  175. package/pulse/eslint.config.mjs +0 -18
  176. package/pulse/lib/bahulam-paths.ts +0 -23
  177. package/pulse/lib/claude-reader.ts +0 -592
  178. package/pulse/lib/decode.ts +0 -129
  179. package/pulse/lib/pricing.ts +0 -102
  180. package/pulse/lib/replay-parser.ts +0 -165
  181. package/pulse/lib/tool-categories.ts +0 -140
  182. package/pulse/lib/utils.ts +0 -6
  183. package/pulse/next-env.d.ts +0 -6
  184. package/pulse/next.config.ts +0 -16
  185. package/pulse/package.json +0 -45
  186. package/pulse/postcss.config.mjs +0 -7
  187. package/pulse/public/activity.png +0 -0
  188. package/pulse/public/cc-lens.png +0 -0
  189. package/pulse/public/command-k.png +0 -0
  190. package/pulse/public/costs.png +0 -0
  191. package/pulse/public/dashboard-dark.png +0 -0
  192. package/pulse/public/dashboard-white.png +0 -0
  193. package/pulse/public/export.png +0 -0
  194. package/pulse/public/file.svg +0 -1
  195. package/pulse/public/globe.svg +0 -1
  196. package/pulse/public/next.svg +0 -1
  197. package/pulse/public/projects.png +0 -0
  198. package/pulse/public/session-chat.png +0 -0
  199. package/pulse/public/todos.png +0 -0
  200. package/pulse/public/tools.png +0 -0
  201. package/pulse/public/vercel.svg +0 -1
  202. package/pulse/public/window.svg +0 -1
  203. package/pulse/tsconfig.json +0 -34
  204. package/pulse/types/claude.ts +0 -294
@@ -8,8 +8,15 @@
8
8
  * mode on, redraw in place with cursor-up + erase-down, restore on exit.
9
9
  */
10
10
 
11
- import { c } from './ansi.mjs';
11
+ import { c, stripAnsi } from './ansi.mjs';
12
12
  import { fitAnsiLine, writeOverlayFrame, eraseOverlayFrame } from './repl-format.mjs';
13
+ import {
14
+ cacheProfileLabel,
15
+ formatCategoryBadge,
16
+ isImageGenerationModel,
17
+ modelCategory,
18
+ modelDisplayCategory,
19
+ } from './model-catalog-display.mjs';
13
20
 
14
21
  const DEFAULT_SENTINEL = '__default__';
15
22
 
@@ -20,10 +27,33 @@ function creditBadge(row) {
20
27
  return `~${credits < 10 ? credits.toFixed(1) : String(Math.round(credits))} cr/M`;
21
28
  }
22
29
 
30
+ function formatTokenLimit(value, label) {
31
+ const n = Number(value);
32
+ if (!Number.isFinite(n) || n <= 0) return '';
33
+ if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1).replace(/\.0$/, '')}M ${label}`;
34
+ if (n >= 1_000) return `${Math.round(n / 1_000)}K ${label}`;
35
+ return `${Math.round(n)} ${label}`;
36
+ }
37
+
38
+ function optionRowsForRole(catalog, row) {
39
+ const curated = (catalog || []).filter(m => m?.harness_validated && m?.id);
40
+ const group = String(row?.optionGroup || 'text').toLowerCase();
41
+ if (group === 'image_analysis') {
42
+ return curated.filter(m => (
43
+ ['image', 'multimodal'].includes(modelCategory(m))
44
+ && !isImageGenerationModel(m)
45
+ ));
46
+ }
47
+ if (group === 'image_generation') {
48
+ return curated.filter(m => modelCategory(m) === 'image' && isImageGenerationModel(m));
49
+ }
50
+ return curated.filter(m => ['text', 'chat'].includes(modelCategory(m)));
51
+ }
52
+
23
53
  /**
24
54
  * @param {object} opts
25
55
  * @param {object|null} opts.rl readline instance to pause/resume
26
- * @param {Array} opts.roles [{ role, label, current, defaultLabel }]
56
+ * @param {Array} opts.roles [{ role, label, description, current, defaultLabel, optionGroup }]
27
57
  * @param {Array} opts.catalog raw /api/models rows (may be empty)
28
58
  * @param {Array} [opts.fallbackIds] model ids to cycle when no curated catalog
29
59
  * @param {string} [opts.unavailableNote] why the catalog is missing (shown in header)
@@ -33,25 +63,24 @@ export async function pickModelOverridesForm({ rl, roles, catalog, fallbackIds,
33
63
  if (!process.stdin.isTTY) return null;
34
64
  if (rl) rl.pause();
35
65
 
36
- const curated = (catalog || []).filter(m => m?.harness_validated && m?.id);
37
- const usingFallback = curated.length === 0;
38
- const optionIds = usingFallback
39
- ? [...new Set((fallbackIds || []).filter(Boolean))]
40
- : curated.map(m => m.id);
41
- const baseOptions = [DEFAULT_SENTINEL, ...optionIds];
42
- const byId = new Map(curated.map(m => [m.id, m]));
66
+ const catalogRows = (catalog || []).filter(m => m?.harness_validated && m?.id);
67
+ const usingFallback = catalogRows.length === 0;
68
+ const byId = new Map(catalogRows.map(m => [m.id, m]));
43
69
 
44
70
  // Per-row option list; a current override that isn't in the curated list
45
71
  // is appended so it stays visible and selectable.
46
72
  const rows = roles.map(r => {
47
- let opts = baseOptions;
73
+ const optionIds = usingFallback
74
+ ? [...new Set((fallbackIds || []).filter(Boolean))]
75
+ : optionRowsForRole(catalogRows, r).map(m => m.id);
76
+ let opts = [DEFAULT_SENTINEL, ...optionIds];
48
77
  let idx = 0;
49
78
  if (r.current) {
50
- const found = baseOptions.indexOf(r.current);
79
+ const found = opts.indexOf(r.current);
51
80
  if (found >= 0) {
52
81
  idx = found;
53
82
  } else {
54
- opts = [...baseOptions, r.current];
83
+ opts = [...opts, r.current];
55
84
  idx = opts.length - 1;
56
85
  }
57
86
  }
@@ -76,8 +105,38 @@ export async function pickModelOverridesForm({ rl, roles, catalog, fallbackIds,
76
105
  return `${c.brand(value)}${badge ? ` ${c.dim(badge)}` : ''}${flag}`;
77
106
  };
78
107
 
108
+ const valueDescription = (row) => {
109
+ const value = row.opts[row.idx];
110
+ if (value === DEFAULT_SENTINEL) {
111
+ return row.description || 'backend default for this role';
112
+ }
113
+ const meta = byId.get(value);
114
+ if (!meta) {
115
+ return usingFallback ? 'backend configured model' : 'custom override outside curated catalog';
116
+ }
117
+ const label = String(meta.label || '').trim();
118
+ const parts = [];
119
+ if (label && label !== value) parts.push(c.white(label));
120
+ if (meta.provider) parts.push(c.dim(String(meta.provider)));
121
+ const category = modelDisplayCategory(meta);
122
+ if (category) parts.push(formatCategoryBadge(category));
123
+ const context = formatTokenLimit(meta.context_length, 'ctx');
124
+ if (context) parts.push(c.dim(context));
125
+ const output = formatTokenLimit(meta.max_output, 'out');
126
+ if (output) parts.push(c.dim(output));
127
+ if (meta.supports_tools) parts.push(c.green('tools'));
128
+ if (meta.supports_reasoning) parts.push(c.yellow('reasoning'));
129
+ const cache = cacheProfileLabel(meta.cache_profile);
130
+ if (cache) parts.push(c.cyan(cache));
131
+ return parts.join(c.dim(' · '));
132
+ };
133
+
79
134
  const render = () => {
80
135
  const cols = Math.max(60, process.stderr.columns || 120);
136
+ const labelWidth = Math.min(
137
+ 18,
138
+ Math.max(14, ...rows.map(row => stripAnsi(String(row.label || row.role)).length)),
139
+ );
81
140
  const lines = [];
82
141
  lines.push(` ${c.bold('Models')} ${c.dim('· session overrides · curated platform catalog')}`);
83
142
  if (usingFallback) {
@@ -87,9 +146,17 @@ export async function pickModelOverridesForm({ rl, roles, catalog, fallbackIds,
87
146
  lines.push('');
88
147
  rows.forEach((row, i) => {
89
148
  const marker = i === cursor ? c.brand('▸') : ' ';
90
- const rawLabel = String(row.label || row.role).padEnd(14, ' ');
149
+ const rawLabel = String(row.label || row.role).padEnd(labelWidth, ' ');
91
150
  const label = i === cursor ? c.brand(rawLabel) : rawLabel;
92
- lines.push(fitAnsiLine(` ${marker} ${label} ${c.dim('‹')} ${valueLabel(row)} ${c.dim('›')}`, cols - 1));
151
+ const prefix = ` ${marker} ${label} ${c.dim('‹')} `;
152
+ const suffix = ` ${c.dim('›')}`;
153
+ const descText = valueDescription(row);
154
+ const descMaxCols = Math.max(0, Math.min(72, cols - stripAnsi(prefix + suffix).length - 24));
155
+ const desc = descText && descMaxCols > 12
156
+ ? ` ${fitAnsiLine(descText, descMaxCols)}`
157
+ : '';
158
+ const maxValueCols = Math.max(18, cols - stripAnsi(prefix + suffix + desc).length - 1);
159
+ lines.push(fitAnsiLine(`${prefix}${fitAnsiLine(valueLabel(row), maxValueCols)}${suffix}${desc}`, cols - 1));
93
160
  });
94
161
  lines.push('');
95
162
  lines.push(fitAnsiLine(` ${c.dim('↑↓ role · ←→ model · Enter apply · c defaults · Esc cancel')}`, cols - 1));
@@ -21,6 +21,7 @@ import { paint } from '../ui/palette.mjs';
21
21
  import { runtime, session } from './repl-state.mjs';
22
22
  import { fitAnsiLine } from './repl-format.mjs';
23
23
  import { exploreCategory, isExploreTool } from './repl-explore.mjs';
24
+ import { watchState } from './watch-state.mjs';
24
25
  import {
25
26
  clearPinnedStatus,
26
27
  drawPinnedStatus,
@@ -36,21 +37,50 @@ import * as queue from '../ui/render-queue.mjs';
36
37
  // Max inner-tool lines shown under the spinner during a sub-agent run.
37
38
  const SUB_AGENT_WINDOW_ROWS = 7;
38
39
 
40
+ function statusWidth() {
41
+ return Math.max(8, (process.stderr.columns || process.stdout.columns || 120) - 1);
42
+ }
43
+
44
+ function fitStatusLine(line) {
45
+ return fitAnsiLine(String(line ?? '').replace(/[\r\n]+/g, ' '), statusWidth());
46
+ }
47
+
48
+ function fitStatusLines(lines) {
49
+ return (Array.isArray(lines) ? lines : [lines]).map(fitStatusLine);
50
+ }
51
+
39
52
  function presentStatus(rendered) {
53
+ // Watch panel override: when active, render the watch panel entries as a
54
+ // multi-line status block instead of the normal spinner/status line.
55
+ if (watchState.active) {
56
+ const lines = watchState.visible();
57
+ if (lines.length) {
58
+ const fitted = fitStatusLines(lines);
59
+ if (queue.isActive()) {
60
+ queue.statusBlock(fitted);
61
+ } else if (isInputDockMounted()) {
62
+ drawPinnedStatus(fitted.join('\n'));
63
+ } else {
64
+ inPlace(fitted.join('\n'));
65
+ }
66
+ return;
67
+ }
68
+ }
69
+ const fitted = fitStatusLine(rendered);
40
70
  if (queue.isActive()) {
41
71
  const win = runtime.subAgentWindow;
42
72
  if (win?.active && win.lines.length) {
43
73
  queue.statusBlock([
44
- rendered,
45
- ...win.lines.slice(-SUB_AGENT_WINDOW_ROWS).map(l => ` ${c.dim(l)}`),
74
+ fitted,
75
+ ...fitStatusLines(win.lines.slice(-SUB_AGENT_WINDOW_ROWS).map(l => ` ${c.dim(l)}`)),
46
76
  ]);
47
77
  return;
48
78
  }
49
- queue.status(rendered);
79
+ queue.status(fitted);
50
80
  return;
51
81
  }
52
- if (isInputDockMounted()) { drawPinnedStatus(rendered); return; }
53
- inPlace(rendered);
82
+ if (isInputDockMounted()) { drawPinnedStatus(fitted); return; }
83
+ inPlace(fitted);
54
84
  }
55
85
 
56
86
  /** Push a line into the live sub-agent tool window (dedup consecutive). */
@@ -103,7 +133,7 @@ import { safeCwd } from './repl-utils.mjs';
103
133
  import { transcriptHeader, transcriptLine } from '../ui/transcript-block.mjs';
104
134
 
105
135
  export function blockSeparatorMode() {
106
- return String(process.env.KEPLER_BLOCK_SEPARATOR || 'space').toLowerCase();
136
+ return String(process.env.BAHULAM_BLOCK_SEPARATOR || 'space').toLowerCase();
107
137
  }
108
138
 
109
139
  export function renderBlockBoundary(nextBlock, { compactSame = false } = {}) {
@@ -361,7 +391,7 @@ export function renderToolResult(data, eventType = 'tool_result') {
361
391
 
362
392
  if (data._blocked) session.blockedOps++;
363
393
 
364
- const { text, tone: t } = summarizeResult(tool, data);
394
+ const { text, tone: t } = summarizeResult(tool, data, data.args || {});
365
395
  // Em dash reads more like prose than a system arrow.
366
396
  const arrow = shellResultTool(tool)
367
397
  ? `${paint.text.dim('result')} ${paint.text.dim('—')}`
@@ -33,7 +33,7 @@ import {
33
33
  writeOverlayFrame,
34
34
  eraseOverlayFrame,
35
35
  } from './repl-format.mjs';
36
- import { TarangStreamClient } from '../core/stream-client.mjs';
36
+ import { BahulamStreamClient } from '../core/stream-client.mjs';
37
37
  import { getRecentSessions, getSessionDetail, buildResumeHistory, combineResumeSummaries } from '../core/local-store.mjs';
38
38
  import { decideResumeMode, projectedTokensForChoice, formatTokens as formatCtxTokens } from '../core/resume-mode.mjs';
39
39
  import { applyCompactSummary, localCompactSummary, parseCompactTailCount, prepareCompactHistory } from '../core/compact-history.mjs';
@@ -504,7 +504,7 @@ export async function summarizeResumeTranscript({
504
504
  };
505
505
  }
506
506
  try {
507
- const client = new TarangStreamClient({
507
+ const client = new BahulamStreamClient({
508
508
  baseUrl: creds.backendUrl,
509
509
  token: creds.token,
510
510
  toolExecutor,
@@ -62,6 +62,10 @@ export const runtime = {
62
62
  // N lines under the spinner) instead of appending to the transcript.
63
63
  // Full detail stays on the recorded cards (/expand, /last, `d`).
64
64
  subAgentWindow: { active: false, lines: [] },
65
+
66
+ // PRD-092: Watch panel — toggled by /watch. When active, the spinner
67
+ // area renders a compact agent-activity summary instead of the spinner.
68
+ watchPanelActive: false,
65
69
  };
66
70
 
67
71
  // Full session state for the current CLI process. Set by the REPL loop
@@ -73,6 +77,13 @@ export const session = {
73
77
  startTime: Date.now(),
74
78
  inputTokens: 0,
75
79
  outputTokens: 0,
80
+ // Per-turn context indicator for the dock strip. Updated at each
81
+ // AGENT_COMPLETE from the backend's usage.total_input_tokens (the
82
+ // cumulative input the primary agent sent this turn across all its
83
+ // internal inferences). Rough proxy for "how big is the prompt right
84
+ // now" — approximates what the NEXT user turn will pay before any
85
+ // growth. Reset by /new.
86
+ lastTurnInputTokens: 0,
76
87
  toolCalls: 0, // primary-agent tool calls in the current turn
77
88
  subAgentToolCalls: 0,// forwarded internal sub-agent tool calls in the current turn
78
89
  totalToolCalls: 0, // across all turns
@@ -85,6 +96,7 @@ export const session = {
85
96
  user: null, // { github_username, email, role }
86
97
  model: null, // from backend user profile
87
98
  modelLimits: {}, // role -> {model, context_length, max_output, source}
99
+ subAgentModels: {}, // role -> model from backend session_info
88
100
  blockedOps: 0, // safety guardrail blocks
89
101
  delegations: [], // agent delegation events: { from, to, time }
90
102
  phases: [], // phase history: { name, time }