@axplusb/kepler 0.0.1 → 1.0.0
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.
- package/README.md +82 -0
- package/package.json +36 -4
- package/pulse/app/activity/page.tsx +190 -0
- package/pulse/app/api/activity/route.ts +138 -0
- package/pulse/app/api/costs/route.ts +88 -0
- package/pulse/app/api/export/route.ts +77 -0
- package/pulse/app/api/history/route.ts +11 -0
- package/pulse/app/api/import/route.ts +31 -0
- package/pulse/app/api/memory/route.ts +52 -0
- package/pulse/app/api/plans/route.ts +9 -0
- package/pulse/app/api/projects/[slug]/route.ts +96 -0
- package/pulse/app/api/projects/route.ts +121 -0
- package/pulse/app/api/sessions/[id]/replay/route.ts +20 -0
- package/pulse/app/api/sessions/[id]/route.ts +31 -0
- package/pulse/app/api/sessions/route.ts +112 -0
- package/pulse/app/api/settings/route.ts +14 -0
- package/pulse/app/api/stats/route.ts +143 -0
- package/pulse/app/api/todos/route.ts +9 -0
- package/pulse/app/api/tools/route.ts +160 -0
- package/pulse/app/costs/page.tsx +179 -0
- package/pulse/app/export/page.tsx +465 -0
- package/pulse/app/favicon.ico +0 -0
- package/pulse/app/globals.css +263 -0
- package/pulse/app/help/page.tsx +142 -0
- package/pulse/app/history/page.tsx +157 -0
- package/pulse/app/layout.tsx +46 -0
- package/pulse/app/memory/page.tsx +365 -0
- package/pulse/app/overview-client.tsx +393 -0
- package/pulse/app/page.tsx +14 -0
- package/pulse/app/plans/page.tsx +308 -0
- package/pulse/app/projects/[slug]/page.tsx +390 -0
- package/pulse/app/projects/page.tsx +110 -0
- package/pulse/app/sessions/[id]/page.tsx +243 -0
- package/pulse/app/sessions/page.tsx +39 -0
- package/pulse/app/settings/page.tsx +188 -0
- package/pulse/app/todos/page.tsx +211 -0
- package/pulse/app/tools/page.tsx +249 -0
- package/pulse/cli.js +159 -0
- package/pulse/components/activity/day-of-week-chart.tsx +35 -0
- package/pulse/components/activity/streak-card.tsx +36 -0
- package/pulse/components/costs/cache-efficiency-panel.tsx +76 -0
- package/pulse/components/costs/cost-by-project-chart.tsx +48 -0
- package/pulse/components/costs/cost-over-time-chart.tsx +95 -0
- package/pulse/components/costs/model-token-table.tsx +60 -0
- package/pulse/components/global-search.tsx +193 -0
- package/pulse/components/keyboard-nav-provider.tsx +23 -0
- package/pulse/components/layout/bottom-nav.tsx +52 -0
- package/pulse/components/layout/client-layout.tsx +31 -0
- package/pulse/components/layout/sidebar-context.tsx +50 -0
- package/pulse/components/layout/sidebar.tsx +182 -0
- package/pulse/components/layout/top-bar.tsx +121 -0
- package/pulse/components/overview/activity-heatmap.tsx +107 -0
- package/pulse/components/overview/conversation-table.tsx +148 -0
- package/pulse/components/overview/model-breakdown-donut.tsx +95 -0
- package/pulse/components/overview/peak-hours-chart.tsx +87 -0
- package/pulse/components/overview/project-activity-donut.tsx +96 -0
- package/pulse/components/overview/stat-card.tsx +102 -0
- package/pulse/components/overview/usage-over-time-chart.tsx +166 -0
- package/pulse/components/projects/project-card.tsx +175 -0
- package/pulse/components/sessions/replay/assistant-markdown.tsx +94 -0
- package/pulse/components/sessions/replay/compaction-card.tsx +25 -0
- package/pulse/components/sessions/replay/session-sidebar.tsx +231 -0
- package/pulse/components/sessions/replay/token-accumulation-chart.tsx +98 -0
- package/pulse/components/sessions/replay/tool-call-badge.tsx +127 -0
- package/pulse/components/sessions/replay/turn-cards.tsx +220 -0
- package/pulse/components/sessions/replay/user-tool-result.tsx +158 -0
- package/pulse/components/sessions/session-badges.tsx +49 -0
- package/pulse/components/sessions/session-table.tsx +299 -0
- package/pulse/components/theme-provider.tsx +44 -0
- package/pulse/components/tools/feature-adoption-table.tsx +58 -0
- package/pulse/components/tools/mcp-server-panel.tsx +45 -0
- package/pulse/components/tools/tool-ranking-chart.tsx +57 -0
- package/pulse/components/tools/version-history-table.tsx +32 -0
- package/pulse/components/ui/alert.tsx +66 -0
- package/pulse/components/ui/badge.tsx +48 -0
- package/pulse/components/ui/breadcrumb.tsx +109 -0
- package/pulse/components/ui/button.tsx +64 -0
- package/pulse/components/ui/calendar.tsx +220 -0
- package/pulse/components/ui/card.tsx +92 -0
- package/pulse/components/ui/command.tsx +158 -0
- package/pulse/components/ui/dialog.tsx +158 -0
- package/pulse/components/ui/input.tsx +21 -0
- package/pulse/components/ui/popover.tsx +89 -0
- package/pulse/components/ui/progress.tsx +31 -0
- package/pulse/components/ui/select.tsx +190 -0
- package/pulse/components/ui/separator.tsx +28 -0
- package/pulse/components/ui/sheet.tsx +143 -0
- package/pulse/components/ui/skeleton.tsx +13 -0
- package/pulse/components/ui/table.tsx +116 -0
- package/pulse/components/ui/tabs.tsx +91 -0
- package/pulse/components/ui/tooltip.tsx +57 -0
- package/pulse/components/use-global-keyboard-nav.ts +79 -0
- package/pulse/components.json +23 -0
- package/pulse/eslint.config.mjs +18 -0
- package/pulse/lib/claude-reader.ts +594 -0
- package/pulse/lib/decode.ts +129 -0
- package/pulse/lib/pricing.ts +102 -0
- package/pulse/lib/replay-parser.ts +165 -0
- package/pulse/lib/tool-categories.ts +127 -0
- package/pulse/lib/utils.ts +6 -0
- package/pulse/next-env.d.ts +6 -0
- package/pulse/next.config.ts +16 -0
- package/pulse/package.json +45 -0
- package/pulse/postcss.config.mjs +7 -0
- package/pulse/public/activity.png +0 -0
- package/pulse/public/cc-lens.png +0 -0
- package/pulse/public/command-k.png +0 -0
- package/pulse/public/costs.png +0 -0
- package/pulse/public/dashboard-dark.png +0 -0
- package/pulse/public/dashboard-white.png +0 -0
- package/pulse/public/export.png +0 -0
- package/pulse/public/file.svg +1 -0
- package/pulse/public/globe.svg +1 -0
- package/pulse/public/next.svg +1 -0
- package/pulse/public/projects.png +0 -0
- package/pulse/public/session-chat.png +0 -0
- package/pulse/public/todos.png +0 -0
- package/pulse/public/tools.png +0 -0
- package/pulse/public/vercel.svg +1 -0
- package/pulse/public/window.svg +1 -0
- package/pulse/tsconfig.json +34 -0
- package/pulse/types/claude.ts +294 -0
- package/src/agents/loader.mjs +89 -0
- package/src/agents/parser.mjs +98 -0
- package/src/agents/teams.mjs +123 -0
- package/src/auth/oauth.mjs +220 -0
- package/src/auth/tarang-auth.mjs +277 -0
- package/src/config/cli-args.mjs +173 -0
- package/src/config/env.mjs +263 -0
- package/src/config/settings.mjs +132 -0
- package/src/context/ast-parser.mjs +298 -0
- package/src/context/bm25.mjs +85 -0
- package/src/context/retriever.mjs +270 -0
- package/src/context/skeleton.mjs +134 -0
- package/src/core/agent-loop.mjs +480 -0
- package/src/core/approval.mjs +273 -0
- package/src/core/backend-url.mjs +57 -0
- package/src/core/cache.mjs +105 -0
- package/src/core/callback-client.mjs +149 -0
- package/src/core/checkpoints.mjs +142 -0
- package/src/core/context-manager.mjs +198 -0
- package/src/core/headless.mjs +168 -0
- package/src/core/hooks-manager.mjs +87 -0
- package/src/core/jsonl-writer.mjs +351 -0
- package/src/core/local-agent.mjs +429 -0
- package/src/core/local-store.mjs +325 -0
- package/src/core/mode-selector.mjs +51 -0
- package/src/core/output-filter.mjs +177 -0
- package/src/core/paths.mjs +98 -0
- package/src/core/pricing.mjs +314 -0
- package/src/core/providers.mjs +219 -0
- package/src/core/rate-limiter.mjs +119 -0
- package/src/core/safety.mjs +200 -0
- package/src/core/scheduler.mjs +173 -0
- package/src/core/session-manager.mjs +317 -0
- package/src/core/session.mjs +143 -0
- package/src/core/settings-sync.mjs +85 -0
- package/src/core/stagnation.mjs +57 -0
- package/src/core/stream-client.mjs +367 -0
- package/src/core/streaming.mjs +182 -0
- package/src/core/system-prompt.mjs +135 -0
- package/src/core/tool-executor.mjs +725 -0
- package/src/hooks/engine.mjs +162 -0
- package/src/index.mjs +370 -0
- package/src/mcp/client.mjs +253 -0
- package/src/mcp/transport-shttp.mjs +130 -0
- package/src/mcp/transport-sse.mjs +131 -0
- package/src/mcp/transport-ws.mjs +134 -0
- package/src/permissions/checker.mjs +57 -0
- package/src/permissions/command-classifier.mjs +573 -0
- package/src/permissions/injection-check.mjs +60 -0
- package/src/permissions/path-check.mjs +102 -0
- package/src/permissions/prompt.mjs +73 -0
- package/src/permissions/sandbox.mjs +112 -0
- package/src/plugins/loader.mjs +138 -0
- package/src/skills/loader.mjs +147 -0
- package/src/skills/runner.mjs +55 -0
- package/src/telemetry/index.mjs +96 -0
- package/src/terminal/agents.mjs +177 -0
- package/src/terminal/analytics.mjs +292 -0
- package/src/terminal/ansi.mjs +421 -0
- package/src/terminal/main.mjs +150 -0
- package/src/terminal/repl.mjs +1484 -0
- package/src/terminal/tool-display.mjs +58 -0
- package/src/tools/agent.mjs +137 -0
- package/src/tools/ask-user.mjs +61 -0
- package/src/tools/bash.mjs +148 -0
- package/src/tools/cron-create.mjs +120 -0
- package/src/tools/cron-delete.mjs +49 -0
- package/src/tools/cron-list.mjs +37 -0
- package/src/tools/edit.mjs +82 -0
- package/src/tools/enter-worktree.mjs +69 -0
- package/src/tools/exit-worktree.mjs +57 -0
- package/src/tools/glob.mjs +117 -0
- package/src/tools/grep.mjs +129 -0
- package/src/tools/lint.mjs +71 -0
- package/src/tools/ls.mjs +58 -0
- package/src/tools/lsp.mjs +115 -0
- package/src/tools/multi-edit.mjs +94 -0
- package/src/tools/notebook-edit.mjs +96 -0
- package/src/tools/read-mcp-resource.mjs +57 -0
- package/src/tools/read.mjs +138 -0
- package/src/tools/registry.mjs +132 -0
- package/src/tools/remote-trigger.mjs +84 -0
- package/src/tools/send-message.mjs +64 -0
- package/src/tools/skill.mjs +52 -0
- package/src/tools/test-runner.mjs +49 -0
- package/src/tools/todo-write.mjs +68 -0
- package/src/tools/tool-search.mjs +77 -0
- package/src/tools/web-fetch.mjs +65 -0
- package/src/tools/web-search.mjs +89 -0
- package/src/tools/write.mjs +55 -0
- package/src/ui/banner.mjs +237 -0
- package/src/ui/commands.mjs +499 -0
- package/src/ui/formatter.mjs +379 -0
- package/src/ui/markdown.mjs +278 -0
- package/src/ui/slash-commands.mjs +258 -0
- package/index.js +0 -1
|
@@ -0,0 +1,263 @@
|
|
|
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
|
+
/* Orca accent colors */
|
|
90
|
+
--color-orca-cyan: #06b6d4;
|
|
91
|
+
--color-orca-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
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
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: 'orca', desc: 'Start interactive REPL' },
|
|
6
|
+
{ cmd: 'orca "instruction"', desc: 'Run a single instruction and exit' },
|
|
7
|
+
{ cmd: 'orca dashboard', desc: 'Open Orca Pulse analytics dashboard' },
|
|
8
|
+
{ cmd: 'orca sessions', desc: 'List recent local sessions' },
|
|
9
|
+
{ cmd: 'orca stats', desc: 'Show aggregate local session stats' },
|
|
10
|
+
{ cmd: 'orca history', desc: 'Show recent prompt history' },
|
|
11
|
+
{ cmd: 'orca login', desc: 'Sign in via browser' },
|
|
12
|
+
{ cmd: 'orca 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: 'ORCA_CONFIG_DIR', desc: 'Override config directory (default: ~/.orca)' },
|
|
42
|
+
{ name: 'TARANG_BACKEND_URL', desc: 'Override backend URL explicitly' },
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
const FEATURES = [
|
|
46
|
+
{ title: 'Multi-Agent Orchestration', desc: 'Primary agent spawns explore, plan, and review sub-agents for complex tasks.' },
|
|
47
|
+
{ title: 'Smart Tool Routing', desc: 'Write operations routed to CLI for local execution. Read tools run server-side.' },
|
|
48
|
+
{ title: 'Safety Guardrails', desc: 'Destructive commands (rm, delete) always require approval. Path validation on all file operations.' },
|
|
49
|
+
{ title: 'Local JSONL Analytics', desc: 'Every session is recorded to ~/.orca/ for offline analytics via Orca Pulse.' },
|
|
50
|
+
{ title: 'Conversation History', desc: 'Multi-turn conversations within a REPL session. Context preserved across turns.' },
|
|
51
|
+
{ title: 'BM25 Code Index', desc: 'Project files indexed on startup for fast semantic code search.' },
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
function CommandTable({ commands }: { commands: { cmd: string; desc: string }[] }) {
|
|
55
|
+
return (
|
|
56
|
+
<div className="space-y-1">
|
|
57
|
+
{commands.map(({ cmd, desc }) => (
|
|
58
|
+
<div key={cmd} className="flex items-start gap-4 py-1.5">
|
|
59
|
+
<code className="text-sm font-mono text-primary whitespace-nowrap shrink-0 min-w-[200px]">{cmd}</code>
|
|
60
|
+
<span className="text-sm text-muted-foreground">{desc}</span>
|
|
61
|
+
</div>
|
|
62
|
+
))}
|
|
63
|
+
</div>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export default function HelpPage() {
|
|
68
|
+
return (
|
|
69
|
+
<div className="flex flex-col min-h-screen">
|
|
70
|
+
<TopBar title="Help" subtitle="Orca CLI commands, shortcuts, and configuration" />
|
|
71
|
+
<div className="px-6 py-6 space-y-6">
|
|
72
|
+
|
|
73
|
+
<Card>
|
|
74
|
+
<CardHeader>
|
|
75
|
+
<CardTitle>CLI Commands</CardTitle>
|
|
76
|
+
</CardHeader>
|
|
77
|
+
<CardContent>
|
|
78
|
+
<CommandTable commands={CLI_COMMANDS} />
|
|
79
|
+
</CardContent>
|
|
80
|
+
</Card>
|
|
81
|
+
|
|
82
|
+
<Card>
|
|
83
|
+
<CardHeader>
|
|
84
|
+
<CardTitle>REPL Commands</CardTitle>
|
|
85
|
+
</CardHeader>
|
|
86
|
+
<CardContent>
|
|
87
|
+
<CommandTable commands={REPL_COMMANDS} />
|
|
88
|
+
</CardContent>
|
|
89
|
+
</Card>
|
|
90
|
+
|
|
91
|
+
<Card>
|
|
92
|
+
<CardHeader>
|
|
93
|
+
<CardTitle>Keyboard Shortcuts</CardTitle>
|
|
94
|
+
</CardHeader>
|
|
95
|
+
<CardContent>
|
|
96
|
+
<div className="space-y-1">
|
|
97
|
+
{KEYBOARD.map(({ key, desc }) => (
|
|
98
|
+
<div key={key} className="flex items-start gap-4 py-1.5">
|
|
99
|
+
<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>
|
|
100
|
+
<span className="text-sm text-muted-foreground">{desc}</span>
|
|
101
|
+
</div>
|
|
102
|
+
))}
|
|
103
|
+
</div>
|
|
104
|
+
</CardContent>
|
|
105
|
+
</Card>
|
|
106
|
+
|
|
107
|
+
<Card>
|
|
108
|
+
<CardHeader>
|
|
109
|
+
<CardTitle>Environment Variables</CardTitle>
|
|
110
|
+
</CardHeader>
|
|
111
|
+
<CardContent>
|
|
112
|
+
<div className="space-y-1">
|
|
113
|
+
{ENV_VARS.map(({ name, desc }) => (
|
|
114
|
+
<div key={name} className="flex items-start gap-4 py-1.5">
|
|
115
|
+
<code className="text-sm font-mono text-primary whitespace-nowrap shrink-0 min-w-[200px]">{name}</code>
|
|
116
|
+
<span className="text-sm text-muted-foreground">{desc}</span>
|
|
117
|
+
</div>
|
|
118
|
+
))}
|
|
119
|
+
</div>
|
|
120
|
+
</CardContent>
|
|
121
|
+
</Card>
|
|
122
|
+
|
|
123
|
+
<Card>
|
|
124
|
+
<CardHeader>
|
|
125
|
+
<CardTitle>Features</CardTitle>
|
|
126
|
+
</CardHeader>
|
|
127
|
+
<CardContent>
|
|
128
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
129
|
+
{FEATURES.map(({ title, desc }) => (
|
|
130
|
+
<div key={title} className="space-y-1">
|
|
131
|
+
<h4 className="text-sm font-semibold">{title}</h4>
|
|
132
|
+
<p className="text-sm text-muted-foreground">{desc}</p>
|
|
133
|
+
</div>
|
|
134
|
+
))}
|
|
135
|
+
</div>
|
|
136
|
+
</CardContent>
|
|
137
|
+
</Card>
|
|
138
|
+
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
)
|
|
142
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
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="~/.orca/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 ~/.orca/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
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
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: 'Orca Pulse',
|
|
24
|
+
description: 'Real-time analytics for your Orca AI 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
|
+
}
|