@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
@@ -1,263 +0,0 @@
1
- @import "tailwindcss";
2
- @import "tw-animate-css";
3
-
4
- @custom-variant dark (&:is(.dark *));
5
-
6
- @theme inline {
7
- @keyframes accordion-down {
8
- from { height: 0; }
9
- to { height: var(--radix-accordion-content-height, var(--accordion-panel-height, auto)); }
10
- }
11
- @keyframes accordion-up {
12
- from { height: var(--radix-accordion-content-height, var(--accordion-panel-height, auto)); }
13
- to { height: 0; }
14
- }
15
- }
16
-
17
- @custom-variant data-open {
18
- &:where([data-state="open"]), &:where([data-open]:not([data-open="false"])) { @slot; }
19
- }
20
- @custom-variant data-closed {
21
- &:where([data-state="closed"]), &:where([data-closed]:not([data-closed="false"])) { @slot; }
22
- }
23
- @custom-variant data-checked {
24
- &:where([data-state="checked"]), &:where([data-checked]:not([data-checked="false"])) { @slot; }
25
- }
26
- @custom-variant data-unchecked {
27
- &:where([data-state="unchecked"]), &:where([data-unchecked]:not([data-unchecked="false"])) { @slot; }
28
- }
29
- @custom-variant data-selected {
30
- &:where([data-selected="true"]) { @slot; }
31
- }
32
- @custom-variant data-disabled {
33
- &:where([data-disabled="true"]), &:where([data-disabled]:not([data-disabled="false"])) { @slot; }
34
- }
35
- @custom-variant data-active {
36
- &:where([data-state="active"]), &:where([data-active]:not([data-active="false"])) { @slot; }
37
- }
38
- @custom-variant data-horizontal {
39
- &:where([data-orientation="horizontal"]) { @slot; }
40
- }
41
- @custom-variant data-vertical {
42
- &:where([data-orientation="vertical"]) { @slot; }
43
- }
44
- @utility no-scrollbar {
45
- -ms-overflow-style: none;
46
- scrollbar-width: none;
47
- &::-webkit-scrollbar { display: none; }
48
- }
49
-
50
- @theme inline {
51
- --color-background: var(--background);
52
- --color-foreground: var(--foreground);
53
- --font-sans: var(--font-geist-mono);
54
- --font-mono: var(--font-geist-mono);
55
- --color-sidebar-ring: var(--sidebar-ring);
56
- --color-sidebar-border: var(--sidebar-border);
57
- --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
58
- --color-sidebar-accent: var(--sidebar-accent);
59
- --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
60
- --color-sidebar-primary: var(--sidebar-primary);
61
- --color-sidebar-foreground: var(--sidebar-foreground);
62
- --color-sidebar: var(--sidebar);
63
- --color-chart-5: var(--chart-5);
64
- --color-chart-4: var(--chart-4);
65
- --color-chart-3: var(--chart-3);
66
- --color-chart-2: var(--chart-2);
67
- --color-chart-1: var(--chart-1);
68
- --color-ring: var(--ring);
69
- --color-input: var(--input);
70
- --color-border: var(--border);
71
- --color-destructive: var(--destructive);
72
- --color-accent-foreground: var(--accent-foreground);
73
- --color-accent: var(--accent);
74
- --color-muted-foreground: var(--muted-foreground);
75
- --color-muted: var(--muted);
76
- --color-secondary-foreground: var(--secondary-foreground);
77
- --color-secondary: var(--secondary);
78
- --color-primary-foreground: var(--primary-foreground);
79
- --color-primary: var(--primary);
80
- --color-popover-foreground: var(--popover-foreground);
81
- --color-popover: var(--popover);
82
- --color-card-foreground: var(--card-foreground);
83
- --color-card: var(--card);
84
- --radius-sm: calc(var(--radius) - 4px);
85
- --radius-md: calc(var(--radius) - 2px);
86
- --radius-lg: var(--radius);
87
- --radius-xl: calc(var(--radius) + 4px);
88
-
89
- /* Bahulam accent colors */
90
- --color-bahulam-cyan: #06b6d4;
91
- --color-bahulam-cyan-light: #22d3ee;
92
- --color-terminal-cyan: #06b6d4;
93
- --color-terminal-green: #34d399;
94
- --color-terminal-amber: #f59e0b;
95
- --color-terminal-blue: var(--viz-sky, #1d4ed8);
96
- --color-terminal-purple: #a78bfa;
97
- --color-terminal-red: #f87171;
98
- --color-terminal-dim: #9ca3af;
99
- --color-terminal-surface: #0f1117;
100
- }
101
-
102
- /* ─── Light theme (default) — higher contrast, clearer surfaces ─────────── */
103
- :root {
104
- --radius: 0.375rem;
105
- /* Zinc-based neutrals: page vs cards vs chrome read as distinct layers */
106
- --background: #f4f4f5;
107
- --foreground: #18181b;
108
- --card: #ffffff;
109
- --card-foreground: #18181b;
110
- --popover: #ffffff;
111
- --popover-foreground: #18181b;
112
- --primary: #0891b2;
113
- --primary-foreground: #ffffff;
114
- --secondary: #e4e4e7;
115
- --secondary-foreground: #27272a;
116
- --muted: #ececee;
117
- --muted-foreground: #52525b;
118
- --accent: #e4e4e7;
119
- --accent-foreground: #18181b;
120
- --destructive: #dc2626;
121
- --border: #d4d4d8;
122
- /* Input border token: visible edge on white fields */
123
- --input: #d4d4d8;
124
- --ring: #0891b2;
125
- --viz-sky: #1d4ed8;
126
- /* Tool / category colors (light) — saturated, distinct; SVG uses solid fill (no color-mix) */
127
- --viz-tool-read: #1d4ed8;
128
- --viz-tool-write: #4338ca;
129
- --viz-tool-edit: #0891b2;
130
- --viz-tool-grep: #db2777;
131
- --viz-tool-glob: #0891b2;
132
- --viz-tool-file-io: #2563eb;
133
- --viz-tool-shell: #06b6d4;
134
- --viz-tool-agent: #7c3aed;
135
- --viz-tool-web: #15803d;
136
- --viz-tool-planning: #ca8a04;
137
- --viz-tool-todo: #e11d48;
138
- --viz-tool-skill: #0e7490;
139
- --viz-tool-mcp: #059669;
140
- --viz-tool-other: #64748b;
141
- --chart-1: #0891b2;
142
- --chart-2: #059669;
143
- --chart-3: var(--viz-sky);
144
- --chart-4: #7c3aed;
145
- --chart-5: #06b6d4;
146
- --sidebar: #fafafa;
147
- --sidebar-foreground: #3f3f46;
148
- --sidebar-primary: #0891b2;
149
- --sidebar-primary-foreground: #ffffff;
150
- --sidebar-accent: #e4e4e7;
151
- --sidebar-accent-foreground: #18181b;
152
- --sidebar-border: #d4d4d8;
153
- --sidebar-ring: #0891b2;
154
- }
155
-
156
- /* ─── Dark theme ─────────────────────────────────────────────────────────── */
157
- .dark {
158
- --background: #0f1117;
159
- --foreground: #e8eaed;
160
- --card: #171921;
161
- --card-foreground: #e8eaed;
162
- --popover: #171921;
163
- --popover-foreground: #e8eaed;
164
- --primary: #06b6d4;
165
- --primary-foreground: #0f1117;
166
- --secondary: #1e212b;
167
- --secondary-foreground: #d1d5db;
168
- --muted: #1e212b;
169
- --muted-foreground: #94a3b8;
170
- --accent: #1e212b;
171
- --accent-foreground: #e8eaed;
172
- --destructive: #f87171;
173
- --border: #262a36;
174
- --input: #1e212b;
175
- --ring: #06b6d4;
176
- --viz-sky: #60a5fa;
177
- --viz-tool-read: #60a5fa;
178
- --viz-tool-write: #a78bfa;
179
- --viz-tool-edit: #67e8f9;
180
- --viz-tool-grep: #f472b6;
181
- --viz-tool-glob: #22d3ee;
182
- --viz-tool-file-io: #818cf8;
183
- --viz-tool-shell: #22d3ee;
184
- --viz-tool-agent: #c4b5fd;
185
- --viz-tool-web: #6ee7b7;
186
- --viz-tool-planning: #fcd34d;
187
- --viz-tool-todo: #fb7185;
188
- --viz-tool-skill: #5eead4;
189
- --viz-tool-mcp: #86efac;
190
- --viz-tool-other: #94a3b8;
191
- --chart-1: #06b6d4;
192
- --chart-2: #34d399;
193
- --chart-3: var(--viz-sky);
194
- --chart-4: #a78bfa;
195
- --chart-5: #22d3ee;
196
- --sidebar: #0b0d12;
197
- --sidebar-foreground: #d1d5db;
198
- --sidebar-primary: #06b6d4;
199
- --sidebar-primary-foreground: #0f1117;
200
- --sidebar-accent: #1a1d26;
201
- --sidebar-accent-foreground: #e8eaed;
202
- --sidebar-border: #1a1d26;
203
- --sidebar-ring: #06b6d4;
204
- }
205
-
206
- @layer base {
207
- * {
208
- @apply border-border outline-ring/50;
209
- }
210
- body {
211
- @apply bg-background text-foreground;
212
- font-family: var(--font-geist-mono), "JetBrains Mono", "Fira Code", "Consolas", monospace;
213
- font-size: 15px;
214
- }
215
- }
216
-
217
- /* ─── Light mode: subtle depth on cards (matches cyan primary) ──────────── */
218
- :root:not(.dark) [data-slot="card"] {
219
- box-shadow:
220
- 0 1px 2px 0 rgba(24, 24, 27, 0.04),
221
- 0 4px 16px -2px rgba(6, 182, 212, 0.08),
222
- 0 0 0 1px rgba(24, 24, 27, 0.05);
223
- }
224
-
225
- /* ─── Scrollbar ──────────────────────────────────────────────────────────── */
226
- ::-webkit-scrollbar {
227
- width: 6px;
228
- height: 6px;
229
- }
230
- ::-webkit-scrollbar-track {
231
- background: var(--background);
232
- }
233
- ::-webkit-scrollbar-thumb {
234
- background: var(--border);
235
- border-radius: 3px;
236
- }
237
- ::-webkit-scrollbar-thumb:hover {
238
- background: var(--muted-foreground);
239
- }
240
-
241
- /* ─── Terminal glow utilities ────────────────────────────────────────────── */
242
- .glow-cyan {
243
- text-shadow: 0 0 10px rgba(6, 182, 212, 0.5);
244
- }
245
- .glow-green {
246
- text-shadow: 0 0 10px rgba(52, 211, 153, 0.5);
247
- }
248
-
249
- /* ─── Recharts overrides ─────────────────────────────────────────────────── */
250
- .recharts-tooltip-wrapper .recharts-default-tooltip {
251
- background: var(--card) !important;
252
- border: 1px solid var(--border) !important;
253
- border-radius: 6px !important;
254
- }
255
- .recharts-cartesian-grid-horizontal line,
256
- .recharts-cartesian-grid-vertical line {
257
- stroke: var(--border) !important;
258
- }
259
- .recharts-text {
260
- fill: var(--muted-foreground) !important;
261
- font-family: var(--font-geist-mono), monospace !important;
262
- font-size: 13px !important;
263
- }
@@ -1,143 +0,0 @@
1
- import { TopBar } from '@/components/layout/top-bar'
2
- import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
3
-
4
- const CLI_COMMANDS = [
5
- { cmd: 'bahulam-code', desc: 'Start interactive REPL' },
6
- { cmd: 'bahulam-code "instruction"', desc: 'Run a single instruction and exit' },
7
- { cmd: 'bahulam-code dashboard', desc: 'Open Bahulam Pulse analytics dashboard' },
8
- { cmd: 'bahulam-code sessions', desc: 'List recent local sessions' },
9
- { cmd: 'bahulam-code stats', desc: 'Show aggregate local session stats' },
10
- { cmd: 'bahulam-code history', desc: 'Show recent prompt history' },
11
- { cmd: 'bahulam-code login', desc: 'Sign in via browser' },
12
- { cmd: 'bahulam-code version', desc: 'Show version' },
13
- ]
14
-
15
- const REPL_COMMANDS = [
16
- { cmd: '/help', desc: 'Show available commands' },
17
- { cmd: '/stats', desc: 'Session metrics — tokens, cost, tools' },
18
- { cmd: '/cost', desc: 'Detailed cost breakdown by model' },
19
- { cmd: '/history', desc: 'Conversation history' },
20
- { cmd: '/clear', desc: 'Clear conversation history' },
21
- { cmd: '/safety', desc: 'Show safety guardrail status' },
22
- { cmd: '/revoke', desc: 'Revoke auto-approvals' },
23
- { cmd: '/explore <query>', desc: 'Spawn read-only codebase explorer' },
24
- { cmd: '/review <query>', desc: 'Spawn code review agent' },
25
- { cmd: '/architect <query>', desc: 'Spawn architecture planning agent' },
26
- { cmd: '/exit', desc: 'Exit the REPL' },
27
- ]
28
-
29
- const KEYBOARD = [
30
- { key: 'Esc', desc: 'Cancel current execution' },
31
- { key: 'Space', desc: 'Pause / resume execution' },
32
- { key: 'Ctrl+C', desc: 'Exit' },
33
- { key: 'Tab', desc: 'Autocomplete slash commands' },
34
- { key: 'Up/Down', desc: 'Navigate input history' },
35
- ]
36
-
37
- const ENV_VARS = [
38
- { name: 'TARANG_ENV', desc: 'Set backend environment (local, development, production)' },
39
- { name: 'ANTHROPIC_API_KEY', desc: 'Direct Anthropic API key for local mode' },
40
- { name: 'OPENROUTER_API_KEY', desc: 'OpenRouter API key' },
41
- { name: 'BAHULAM_CONFIG_DIR', desc: 'Override config directory (default: ~/.bahulam)' },
42
- { name: 'KEPLER_CONFIG_DIR', desc: 'Legacy config directory override' },
43
- { name: 'TARANG_BACKEND_URL', desc: 'Override backend URL explicitly' },
44
- ]
45
-
46
- const FEATURES = [
47
- { title: 'Multi-Agent Orchestration', desc: 'Primary agent spawns explore, plan, and review sub-agents for complex tasks.' },
48
- { title: 'Smart Tool Routing', desc: 'Write operations routed to CLI for local execution. Read tools run server-side.' },
49
- { title: 'Safety Guardrails', desc: 'Destructive commands (rm, delete) always require approval. Path validation on all file operations.' },
50
- { title: 'Local JSONL Analytics', desc: 'Every session is recorded to ~/.bahulam/ for offline analytics via Bahulam Pulse.' },
51
- { title: 'Conversation History', desc: 'Multi-turn conversations within a REPL session. Context preserved across turns.' },
52
- { title: 'BM25 Code Index', desc: 'Project files indexed on startup for fast semantic code search.' },
53
- ]
54
-
55
- function CommandTable({ commands }: { commands: { cmd: string; desc: string }[] }) {
56
- return (
57
- <div className="space-y-1">
58
- {commands.map(({ cmd, desc }) => (
59
- <div key={cmd} className="flex items-start gap-4 py-1.5">
60
- <code className="text-sm font-mono text-primary whitespace-nowrap shrink-0 min-w-[200px]">{cmd}</code>
61
- <span className="text-sm text-muted-foreground">{desc}</span>
62
- </div>
63
- ))}
64
- </div>
65
- )
66
- }
67
-
68
- export default function HelpPage() {
69
- return (
70
- <div className="flex flex-col min-h-screen">
71
- <TopBar title="Help" subtitle="Bahulam Code CLI commands, shortcuts, and configuration" />
72
- <div className="px-6 py-6 space-y-6">
73
-
74
- <Card>
75
- <CardHeader>
76
- <CardTitle>CLI Commands</CardTitle>
77
- </CardHeader>
78
- <CardContent>
79
- <CommandTable commands={CLI_COMMANDS} />
80
- </CardContent>
81
- </Card>
82
-
83
- <Card>
84
- <CardHeader>
85
- <CardTitle>REPL Commands</CardTitle>
86
- </CardHeader>
87
- <CardContent>
88
- <CommandTable commands={REPL_COMMANDS} />
89
- </CardContent>
90
- </Card>
91
-
92
- <Card>
93
- <CardHeader>
94
- <CardTitle>Keyboard Shortcuts</CardTitle>
95
- </CardHeader>
96
- <CardContent>
97
- <div className="space-y-1">
98
- {KEYBOARD.map(({ key, desc }) => (
99
- <div key={key} className="flex items-start gap-4 py-1.5">
100
- <kbd className="text-sm font-mono bg-muted px-2 py-0.5 rounded border border-border whitespace-nowrap shrink-0 min-w-[100px] text-center">{key}</kbd>
101
- <span className="text-sm text-muted-foreground">{desc}</span>
102
- </div>
103
- ))}
104
- </div>
105
- </CardContent>
106
- </Card>
107
-
108
- <Card>
109
- <CardHeader>
110
- <CardTitle>Environment Variables</CardTitle>
111
- </CardHeader>
112
- <CardContent>
113
- <div className="space-y-1">
114
- {ENV_VARS.map(({ name, desc }) => (
115
- <div key={name} className="flex items-start gap-4 py-1.5">
116
- <code className="text-sm font-mono text-primary whitespace-nowrap shrink-0 min-w-[200px]">{name}</code>
117
- <span className="text-sm text-muted-foreground">{desc}</span>
118
- </div>
119
- ))}
120
- </div>
121
- </CardContent>
122
- </Card>
123
-
124
- <Card>
125
- <CardHeader>
126
- <CardTitle>Features</CardTitle>
127
- </CardHeader>
128
- <CardContent>
129
- <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
130
- {FEATURES.map(({ title, desc }) => (
131
- <div key={title} className="space-y-1">
132
- <h4 className="text-sm font-semibold">{title}</h4>
133
- <p className="text-sm text-muted-foreground">{desc}</p>
134
- </div>
135
- ))}
136
- </div>
137
- </CardContent>
138
- </Card>
139
-
140
- </div>
141
- </div>
142
- )
143
- }
@@ -1,157 +0,0 @@
1
- 'use client'
2
-
3
- import { useState, useMemo } from 'react'
4
- import useSWR from 'swr'
5
- import { TopBar } from '@/components/layout/top-bar'
6
- import type { HistoryEntry } from '@/types/claude'
7
- import { Input } from '@/components/ui/input'
8
- import { Button } from '@/components/ui/button'
9
- import { Badge } from '@/components/ui/badge'
10
- import { Skeleton } from '@/components/ui/skeleton'
11
- import { Alert, AlertDescription } from '@/components/ui/alert'
12
- import { Search, AlertTriangle, ChevronLeft, ChevronRight } from 'lucide-react'
13
-
14
- const fetcher = (url: string) =>
15
- fetch(url).then(r => { if (!r.ok) throw new Error(`API error ${r.status}`); return r.json() })
16
-
17
- function formatTime(ts: number) {
18
- return new Date(ts).toLocaleString('en-US', {
19
- month: 'short', day: 'numeric', year: 'numeric',
20
- hour: 'numeric', minute: '2-digit',
21
- })
22
- }
23
-
24
- function projectName(p: string) {
25
- const parts = p.replace(/\\/g, '/').split('/')
26
- return parts[parts.length - 1] || p
27
- }
28
-
29
- const PAGE_SIZE = 50
30
-
31
- export default function HistoryPage() {
32
- const { data, error, isLoading } = useSWR<{ history: HistoryEntry[] }>(
33
- '/api/history?limit=2000', fetcher, { refreshInterval: 30_000 }
34
- )
35
- const [search, setSearch] = useState('')
36
- const [page, setPage] = useState(1)
37
-
38
- const entries = useMemo(() => {
39
- const all = [...(data?.history ?? [])].reverse()
40
- if (!search) return all
41
- const q = search.toLowerCase()
42
- return all.filter(e =>
43
- e.display?.toLowerCase().includes(q) ||
44
- e.project?.toLowerCase().includes(q)
45
- )
46
- }, [data, search])
47
-
48
- const totalPages = Math.ceil(entries.length / PAGE_SIZE)
49
- const pageEntries = entries.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE)
50
-
51
- function handleSearch(v: string) {
52
- setSearch(v)
53
- setPage(1)
54
- }
55
-
56
- return (
57
- <div className="flex flex-col min-h-screen">
58
- <TopBar title="History" subtitle="~/.bahulam/history.jsonl" />
59
- <div className="p-4 md:p-6 space-y-4">
60
-
61
- {error && (
62
- <Alert variant="destructive">
63
- <AlertTriangle className="h-4 w-4" />
64
- <AlertDescription>Error loading data: {String(error)}</AlertDescription>
65
- </Alert>
66
- )}
67
-
68
- {isLoading && (
69
- <div className="space-y-2">
70
- {Array.from({ length: 8 }).map((_, i) => <Skeleton key={i} className="h-14 rounded-lg" />)}
71
- </div>
72
- )}
73
-
74
- {data && (
75
- <>
76
- {/* Search + count */}
77
- <div className="flex flex-col sm:flex-row items-start sm:items-center gap-3">
78
- <div className="relative flex-1 w-full">
79
- <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" />
80
- <Input
81
- placeholder="Search commands…"
82
- value={search}
83
- onChange={e => handleSearch(e.target.value)}
84
- className="pl-9"
85
- />
86
- </div>
87
- <Badge variant="outline" className="whitespace-nowrap text-sm px-3 py-1.5">
88
- {entries.length.toLocaleString()} entries
89
- </Badge>
90
- </div>
91
-
92
- {pageEntries.length === 0 ? (
93
- <div className="text-center py-16 text-muted-foreground text-sm">
94
- {(data.history?.length ?? 0) === 0
95
- ? 'No history found in ~/.bahulam/history.jsonl'
96
- : 'No entries match your search.'}
97
- </div>
98
- ) : (
99
- <>
100
- <div className="space-y-1">
101
- {pageEntries.map((entry, i) => (
102
- <div
103
- key={i}
104
- className="border border-border rounded-lg bg-card px-4 py-3 hover:border-primary/30 transition-colors"
105
- >
106
- <p className="text-sm font-mono text-foreground leading-relaxed break-words">
107
- {entry.display || '—'}
108
- </p>
109
- <div className="flex flex-wrap items-center gap-2 mt-1.5">
110
- {entry.timestamp && (
111
- <span className="text-xs text-muted-foreground/60">
112
- {formatTime(entry.timestamp)}
113
- </span>
114
- )}
115
- {entry.project && (
116
- <Badge variant="secondary" className="text-xs font-mono">
117
- {projectName(entry.project)}
118
- </Badge>
119
- )}
120
- </div>
121
- </div>
122
- ))}
123
- </div>
124
-
125
- {totalPages > 1 && (
126
- <div className="flex items-center justify-center gap-2 pt-2">
127
- <Button
128
- variant="outline"
129
- size="sm"
130
- onClick={() => setPage(p => Math.max(1, p - 1))}
131
- disabled={page === 1}
132
- >
133
- <ChevronLeft className="w-4 h-4" />
134
- Prev
135
- </Button>
136
- <span className="text-sm text-muted-foreground tabular-nums">
137
- {page} / {totalPages}
138
- </span>
139
- <Button
140
- variant="outline"
141
- size="sm"
142
- onClick={() => setPage(p => Math.min(totalPages, p + 1))}
143
- disabled={page === totalPages}
144
- >
145
- Next
146
- <ChevronRight className="w-4 h-4" />
147
- </Button>
148
- </div>
149
- )}
150
- </>
151
- )}
152
- </>
153
- )}
154
- </div>
155
- </div>
156
- )
157
- }
@@ -1,46 +0,0 @@
1
- import type { Metadata } from 'next'
2
- import { Geist_Mono, Press_Start_2P } from 'next/font/google'
3
- import './globals.css'
4
- import { Sidebar } from '@/components/layout/sidebar'
5
- import { BottomNav } from '@/components/layout/bottom-nav'
6
- import { ThemeProvider } from '@/components/theme-provider'
7
- import { KeyboardNavProvider } from '@/components/keyboard-nav-provider'
8
- import { SidebarProvider } from '@/components/layout/sidebar-context'
9
- import { ClientLayout } from '@/components/layout/client-layout'
10
-
11
- const geistMono = Geist_Mono({
12
- variable: '--font-geist-mono',
13
- subsets: ['latin'],
14
- })
15
-
16
- const pressStart2P = Press_Start_2P({
17
- variable: '--font-press-start',
18
- weight: '400',
19
- subsets: ['latin'],
20
- })
21
-
22
- export const metadata: Metadata = {
23
- title: 'Bahulam Pulse',
24
- description: 'Real-time analytics for your Bahulam Code agent sessions',
25
- }
26
-
27
- export default function RootLayout({
28
- children,
29
- }: Readonly<{ children: React.ReactNode }>) {
30
- return (
31
- <html lang="en" suppressHydrationWarning>
32
- <body suppressHydrationWarning className={`${geistMono.variable} ${pressStart2P.variable} antialiased`}>
33
- <ThemeProvider>
34
- <SidebarProvider>
35
- <div className="flex min-h-screen">
36
- <Sidebar />
37
- <ClientLayout>{children}</ClientLayout>
38
- </div>
39
- <BottomNav />
40
- <KeyboardNavProvider />
41
- </SidebarProvider>
42
- </ThemeProvider>
43
- </body>
44
- </html>
45
- )
46
- }