@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.
Files changed (218) hide show
  1. package/README.md +82 -0
  2. package/package.json +36 -4
  3. package/pulse/app/activity/page.tsx +190 -0
  4. package/pulse/app/api/activity/route.ts +138 -0
  5. package/pulse/app/api/costs/route.ts +88 -0
  6. package/pulse/app/api/export/route.ts +77 -0
  7. package/pulse/app/api/history/route.ts +11 -0
  8. package/pulse/app/api/import/route.ts +31 -0
  9. package/pulse/app/api/memory/route.ts +52 -0
  10. package/pulse/app/api/plans/route.ts +9 -0
  11. package/pulse/app/api/projects/[slug]/route.ts +96 -0
  12. package/pulse/app/api/projects/route.ts +121 -0
  13. package/pulse/app/api/sessions/[id]/replay/route.ts +20 -0
  14. package/pulse/app/api/sessions/[id]/route.ts +31 -0
  15. package/pulse/app/api/sessions/route.ts +112 -0
  16. package/pulse/app/api/settings/route.ts +14 -0
  17. package/pulse/app/api/stats/route.ts +143 -0
  18. package/pulse/app/api/todos/route.ts +9 -0
  19. package/pulse/app/api/tools/route.ts +160 -0
  20. package/pulse/app/costs/page.tsx +179 -0
  21. package/pulse/app/export/page.tsx +465 -0
  22. package/pulse/app/favicon.ico +0 -0
  23. package/pulse/app/globals.css +263 -0
  24. package/pulse/app/help/page.tsx +142 -0
  25. package/pulse/app/history/page.tsx +157 -0
  26. package/pulse/app/layout.tsx +46 -0
  27. package/pulse/app/memory/page.tsx +365 -0
  28. package/pulse/app/overview-client.tsx +393 -0
  29. package/pulse/app/page.tsx +14 -0
  30. package/pulse/app/plans/page.tsx +308 -0
  31. package/pulse/app/projects/[slug]/page.tsx +390 -0
  32. package/pulse/app/projects/page.tsx +110 -0
  33. package/pulse/app/sessions/[id]/page.tsx +243 -0
  34. package/pulse/app/sessions/page.tsx +39 -0
  35. package/pulse/app/settings/page.tsx +188 -0
  36. package/pulse/app/todos/page.tsx +211 -0
  37. package/pulse/app/tools/page.tsx +249 -0
  38. package/pulse/cli.js +159 -0
  39. package/pulse/components/activity/day-of-week-chart.tsx +35 -0
  40. package/pulse/components/activity/streak-card.tsx +36 -0
  41. package/pulse/components/costs/cache-efficiency-panel.tsx +76 -0
  42. package/pulse/components/costs/cost-by-project-chart.tsx +48 -0
  43. package/pulse/components/costs/cost-over-time-chart.tsx +95 -0
  44. package/pulse/components/costs/model-token-table.tsx +60 -0
  45. package/pulse/components/global-search.tsx +193 -0
  46. package/pulse/components/keyboard-nav-provider.tsx +23 -0
  47. package/pulse/components/layout/bottom-nav.tsx +52 -0
  48. package/pulse/components/layout/client-layout.tsx +31 -0
  49. package/pulse/components/layout/sidebar-context.tsx +50 -0
  50. package/pulse/components/layout/sidebar.tsx +182 -0
  51. package/pulse/components/layout/top-bar.tsx +121 -0
  52. package/pulse/components/overview/activity-heatmap.tsx +107 -0
  53. package/pulse/components/overview/conversation-table.tsx +148 -0
  54. package/pulse/components/overview/model-breakdown-donut.tsx +95 -0
  55. package/pulse/components/overview/peak-hours-chart.tsx +87 -0
  56. package/pulse/components/overview/project-activity-donut.tsx +96 -0
  57. package/pulse/components/overview/stat-card.tsx +102 -0
  58. package/pulse/components/overview/usage-over-time-chart.tsx +166 -0
  59. package/pulse/components/projects/project-card.tsx +175 -0
  60. package/pulse/components/sessions/replay/assistant-markdown.tsx +94 -0
  61. package/pulse/components/sessions/replay/compaction-card.tsx +25 -0
  62. package/pulse/components/sessions/replay/session-sidebar.tsx +231 -0
  63. package/pulse/components/sessions/replay/token-accumulation-chart.tsx +98 -0
  64. package/pulse/components/sessions/replay/tool-call-badge.tsx +127 -0
  65. package/pulse/components/sessions/replay/turn-cards.tsx +220 -0
  66. package/pulse/components/sessions/replay/user-tool-result.tsx +158 -0
  67. package/pulse/components/sessions/session-badges.tsx +49 -0
  68. package/pulse/components/sessions/session-table.tsx +299 -0
  69. package/pulse/components/theme-provider.tsx +44 -0
  70. package/pulse/components/tools/feature-adoption-table.tsx +58 -0
  71. package/pulse/components/tools/mcp-server-panel.tsx +45 -0
  72. package/pulse/components/tools/tool-ranking-chart.tsx +57 -0
  73. package/pulse/components/tools/version-history-table.tsx +32 -0
  74. package/pulse/components/ui/alert.tsx +66 -0
  75. package/pulse/components/ui/badge.tsx +48 -0
  76. package/pulse/components/ui/breadcrumb.tsx +109 -0
  77. package/pulse/components/ui/button.tsx +64 -0
  78. package/pulse/components/ui/calendar.tsx +220 -0
  79. package/pulse/components/ui/card.tsx +92 -0
  80. package/pulse/components/ui/command.tsx +158 -0
  81. package/pulse/components/ui/dialog.tsx +158 -0
  82. package/pulse/components/ui/input.tsx +21 -0
  83. package/pulse/components/ui/popover.tsx +89 -0
  84. package/pulse/components/ui/progress.tsx +31 -0
  85. package/pulse/components/ui/select.tsx +190 -0
  86. package/pulse/components/ui/separator.tsx +28 -0
  87. package/pulse/components/ui/sheet.tsx +143 -0
  88. package/pulse/components/ui/skeleton.tsx +13 -0
  89. package/pulse/components/ui/table.tsx +116 -0
  90. package/pulse/components/ui/tabs.tsx +91 -0
  91. package/pulse/components/ui/tooltip.tsx +57 -0
  92. package/pulse/components/use-global-keyboard-nav.ts +79 -0
  93. package/pulse/components.json +23 -0
  94. package/pulse/eslint.config.mjs +18 -0
  95. package/pulse/lib/claude-reader.ts +594 -0
  96. package/pulse/lib/decode.ts +129 -0
  97. package/pulse/lib/pricing.ts +102 -0
  98. package/pulse/lib/replay-parser.ts +165 -0
  99. package/pulse/lib/tool-categories.ts +127 -0
  100. package/pulse/lib/utils.ts +6 -0
  101. package/pulse/next-env.d.ts +6 -0
  102. package/pulse/next.config.ts +16 -0
  103. package/pulse/package.json +45 -0
  104. package/pulse/postcss.config.mjs +7 -0
  105. package/pulse/public/activity.png +0 -0
  106. package/pulse/public/cc-lens.png +0 -0
  107. package/pulse/public/command-k.png +0 -0
  108. package/pulse/public/costs.png +0 -0
  109. package/pulse/public/dashboard-dark.png +0 -0
  110. package/pulse/public/dashboard-white.png +0 -0
  111. package/pulse/public/export.png +0 -0
  112. package/pulse/public/file.svg +1 -0
  113. package/pulse/public/globe.svg +1 -0
  114. package/pulse/public/next.svg +1 -0
  115. package/pulse/public/projects.png +0 -0
  116. package/pulse/public/session-chat.png +0 -0
  117. package/pulse/public/todos.png +0 -0
  118. package/pulse/public/tools.png +0 -0
  119. package/pulse/public/vercel.svg +1 -0
  120. package/pulse/public/window.svg +1 -0
  121. package/pulse/tsconfig.json +34 -0
  122. package/pulse/types/claude.ts +294 -0
  123. package/src/agents/loader.mjs +89 -0
  124. package/src/agents/parser.mjs +98 -0
  125. package/src/agents/teams.mjs +123 -0
  126. package/src/auth/oauth.mjs +220 -0
  127. package/src/auth/tarang-auth.mjs +277 -0
  128. package/src/config/cli-args.mjs +173 -0
  129. package/src/config/env.mjs +263 -0
  130. package/src/config/settings.mjs +132 -0
  131. package/src/context/ast-parser.mjs +298 -0
  132. package/src/context/bm25.mjs +85 -0
  133. package/src/context/retriever.mjs +270 -0
  134. package/src/context/skeleton.mjs +134 -0
  135. package/src/core/agent-loop.mjs +480 -0
  136. package/src/core/approval.mjs +273 -0
  137. package/src/core/backend-url.mjs +57 -0
  138. package/src/core/cache.mjs +105 -0
  139. package/src/core/callback-client.mjs +149 -0
  140. package/src/core/checkpoints.mjs +142 -0
  141. package/src/core/context-manager.mjs +198 -0
  142. package/src/core/headless.mjs +168 -0
  143. package/src/core/hooks-manager.mjs +87 -0
  144. package/src/core/jsonl-writer.mjs +351 -0
  145. package/src/core/local-agent.mjs +429 -0
  146. package/src/core/local-store.mjs +325 -0
  147. package/src/core/mode-selector.mjs +51 -0
  148. package/src/core/output-filter.mjs +177 -0
  149. package/src/core/paths.mjs +98 -0
  150. package/src/core/pricing.mjs +314 -0
  151. package/src/core/providers.mjs +219 -0
  152. package/src/core/rate-limiter.mjs +119 -0
  153. package/src/core/safety.mjs +200 -0
  154. package/src/core/scheduler.mjs +173 -0
  155. package/src/core/session-manager.mjs +317 -0
  156. package/src/core/session.mjs +143 -0
  157. package/src/core/settings-sync.mjs +85 -0
  158. package/src/core/stagnation.mjs +57 -0
  159. package/src/core/stream-client.mjs +367 -0
  160. package/src/core/streaming.mjs +182 -0
  161. package/src/core/system-prompt.mjs +135 -0
  162. package/src/core/tool-executor.mjs +725 -0
  163. package/src/hooks/engine.mjs +162 -0
  164. package/src/index.mjs +370 -0
  165. package/src/mcp/client.mjs +253 -0
  166. package/src/mcp/transport-shttp.mjs +130 -0
  167. package/src/mcp/transport-sse.mjs +131 -0
  168. package/src/mcp/transport-ws.mjs +134 -0
  169. package/src/permissions/checker.mjs +57 -0
  170. package/src/permissions/command-classifier.mjs +573 -0
  171. package/src/permissions/injection-check.mjs +60 -0
  172. package/src/permissions/path-check.mjs +102 -0
  173. package/src/permissions/prompt.mjs +73 -0
  174. package/src/permissions/sandbox.mjs +112 -0
  175. package/src/plugins/loader.mjs +138 -0
  176. package/src/skills/loader.mjs +147 -0
  177. package/src/skills/runner.mjs +55 -0
  178. package/src/telemetry/index.mjs +96 -0
  179. package/src/terminal/agents.mjs +177 -0
  180. package/src/terminal/analytics.mjs +292 -0
  181. package/src/terminal/ansi.mjs +421 -0
  182. package/src/terminal/main.mjs +150 -0
  183. package/src/terminal/repl.mjs +1484 -0
  184. package/src/terminal/tool-display.mjs +58 -0
  185. package/src/tools/agent.mjs +137 -0
  186. package/src/tools/ask-user.mjs +61 -0
  187. package/src/tools/bash.mjs +148 -0
  188. package/src/tools/cron-create.mjs +120 -0
  189. package/src/tools/cron-delete.mjs +49 -0
  190. package/src/tools/cron-list.mjs +37 -0
  191. package/src/tools/edit.mjs +82 -0
  192. package/src/tools/enter-worktree.mjs +69 -0
  193. package/src/tools/exit-worktree.mjs +57 -0
  194. package/src/tools/glob.mjs +117 -0
  195. package/src/tools/grep.mjs +129 -0
  196. package/src/tools/lint.mjs +71 -0
  197. package/src/tools/ls.mjs +58 -0
  198. package/src/tools/lsp.mjs +115 -0
  199. package/src/tools/multi-edit.mjs +94 -0
  200. package/src/tools/notebook-edit.mjs +96 -0
  201. package/src/tools/read-mcp-resource.mjs +57 -0
  202. package/src/tools/read.mjs +138 -0
  203. package/src/tools/registry.mjs +132 -0
  204. package/src/tools/remote-trigger.mjs +84 -0
  205. package/src/tools/send-message.mjs +64 -0
  206. package/src/tools/skill.mjs +52 -0
  207. package/src/tools/test-runner.mjs +49 -0
  208. package/src/tools/todo-write.mjs +68 -0
  209. package/src/tools/tool-search.mjs +77 -0
  210. package/src/tools/web-fetch.mjs +65 -0
  211. package/src/tools/web-search.mjs +89 -0
  212. package/src/tools/write.mjs +55 -0
  213. package/src/ui/banner.mjs +237 -0
  214. package/src/ui/commands.mjs +499 -0
  215. package/src/ui/formatter.mjs +379 -0
  216. package/src/ui/markdown.mjs +278 -0
  217. package/src/ui/slash-commands.mjs +258 -0
  218. package/index.js +0 -1
@@ -0,0 +1,258 @@
1
+ /**
2
+ * Slash Commands — T10: 14 commands for interactive REPL.
3
+ */
4
+
5
+ import { execSync } from 'node:child_process';
6
+ import * as fs from 'node:fs';
7
+ import * as path from 'node:path';
8
+ import { printGoodbye } from './banner.mjs';
9
+ import { ContextRetriever } from '../context/retriever.mjs';
10
+
11
+ export const COMMANDS = {
12
+ '/help': { description: 'Show available commands', handler: cmdHelp },
13
+ '/git': { description: 'Show git status', handler: cmdGit },
14
+ '/status': { description: 'Alias for /git', handler: cmdGit },
15
+ '/commit': { description: 'Interactive git commit', handler: cmdCommit },
16
+ '/diff': { description: 'Show git diff', handler: cmdDiff },
17
+ '/clear': { description: 'Clear conversation history', handler: cmdClear },
18
+ '/sessions': { description: 'List previous sessions', handler: cmdSessions },
19
+ '/exit': { description: 'Exit CLI', handler: cmdExit },
20
+ '/quit': { description: 'Alias for /exit', handler: cmdExit },
21
+ '/index': { description: 'Build/rebuild BM25 context index', handler: cmdIndex },
22
+ '/model': { description: 'Show current model', handler: cmdModel },
23
+ '/tokens': { description: 'Show token usage', handler: cmdTokens },
24
+ '/cost': { description: 'Show session cost', handler: cmdCost },
25
+ '/config': { description: 'Open settings in browser', handler: cmdConfig },
26
+ '/login': { description: 'Re-authenticate via browser', handler: cmdLogin },
27
+ '/refresh': { description: 'Reload credentials from disk', handler: cmdRefresh },
28
+ '/sync': { description: 'Sync settings from web', handler: cmdSync },
29
+ '/whoami': { description: 'Show logged-in user', handler: cmdWhoami },
30
+ };
31
+
32
+ function run(cmd) {
33
+ try {
34
+ return execSync(cmd, { encoding: 'utf-8', timeout: 15_000, stdio: ['pipe', 'pipe', 'pipe'] });
35
+ } catch (err) {
36
+ return err.stderr || err.stdout || err.message;
37
+ }
38
+ }
39
+
40
+ function cmdHelp(ctx) {
41
+ const BOLD = '\x1b[1m', CYAN = '\x1b[36m', DIM = '\x1b[2m', GREEN = '\x1b[32m', BLUE = '\x1b[34m', RESET = '\x1b[0m';
42
+
43
+ process.stderr.write(`\n${BLUE}┌──────────────────────────────────────────────┐${RESET}\n`);
44
+ process.stderr.write(`${BLUE}│${RESET} ${BOLD}Orca Help${RESET} ${BLUE}│${RESET}\n`);
45
+ process.stderr.write(`${BLUE}├──────────────────────────────────────────────┤${RESET}\n`);
46
+ process.stderr.write(`${BLUE}│${RESET} ${BLUE}│${RESET}\n`);
47
+ process.stderr.write(`${BLUE}│${RESET} ${BOLD}Commands:${RESET} ${BLUE}│${RESET}\n`);
48
+ for (const [name, { description }] of Object.entries(COMMANDS)) {
49
+ const line = ` ${CYAN}${name.padEnd(12)}${RESET} ${description}`;
50
+ process.stderr.write(`${BLUE}│${RESET}${line}${' '.repeat(Math.max(0, 44 - name.length - description.length))}${BLUE}│${RESET}\n`);
51
+ }
52
+ process.stderr.write(`${BLUE}│${RESET} ${BLUE}│${RESET}\n`);
53
+ process.stderr.write(`${BLUE}│${RESET} ${BOLD}Keyboard:${RESET} ${BLUE}│${RESET}\n`);
54
+ process.stderr.write(`${BLUE}│${RESET} ${BOLD}ESC${RESET}${DIM}=${RESET}cancel ${BOLD}SPACE${RESET}${DIM}=${RESET}pause ${BOLD}Ctrl+C${RESET}${DIM}=${RESET}exit ${BLUE}│${RESET}\n`);
55
+ process.stderr.write(`${BLUE}│${RESET} ${BLUE}│${RESET}\n`);
56
+ process.stderr.write(`${BLUE}│${RESET} ${BOLD}Tips:${RESET} ${BLUE}│${RESET}\n`);
57
+ process.stderr.write(`${BLUE}│${RESET} ${DIM}Type naturally: "add a login button"${RESET} ${BLUE}│${RESET}\n`);
58
+ process.stderr.write(`${BLUE}│${RESET} ${DIM}Reference files: "fix bug in src/main.py"${RESET} ${BLUE}│${RESET}\n`);
59
+ process.stderr.write(`${BLUE}│${RESET} ${DIM}Ask questions: "explain how auth works"${RESET} ${BLUE}│${RESET}\n`);
60
+ process.stderr.write(`${BLUE}│${RESET} ${BLUE}│${RESET}\n`);
61
+ process.stderr.write(`${BLUE}└──────────────────────────────────────────────┘${RESET}\n\n`);
62
+ }
63
+
64
+ function cmdGit() {
65
+ process.stdout.write(run('git status --short --branch') + '\n');
66
+ }
67
+
68
+ function cmdCommit(ctx) {
69
+ const status = run('git status --short');
70
+ if (!status.trim()) {
71
+ process.stderr.write('Nothing to commit.\n');
72
+ return;
73
+ }
74
+ process.stdout.write('\x1b[1mStaged changes:\x1b[0m\n');
75
+ process.stdout.write(run('git diff --cached --stat') || '(no staged changes)\n');
76
+ process.stdout.write('\n\x1b[1mUnstaged changes:\x1b[0m\n');
77
+ process.stdout.write(status + '\n');
78
+ process.stderr.write('\x1b[2mUse git add + git commit from shell to commit.\x1b[0m\n');
79
+ }
80
+
81
+ function cmdDiff() {
82
+ const diff = run('git diff --stat');
83
+ process.stdout.write(diff || '(no changes)\n');
84
+ }
85
+
86
+ function cmdClear(ctx) {
87
+ if (ctx.formatter) {
88
+ ctx.formatter.toolCalls = [];
89
+ ctx.formatter.toolCount = 0;
90
+ ctx.formatter.phases.clear();
91
+ ctx.formatter.changes = [];
92
+ }
93
+ process.stderr.write('Conversation cleared.\n');
94
+ }
95
+
96
+ function cmdSessions() {
97
+ const sessDir = path.join(process.cwd(), '.orca', 'sessions');
98
+ if (!fs.existsSync(sessDir)) {
99
+ process.stderr.write('No sessions found.\n');
100
+ return;
101
+ }
102
+ const files = fs.readdirSync(sessDir).filter(f => f.endsWith('.json')).sort().reverse().slice(0, 20);
103
+ if (files.length === 0) {
104
+ process.stderr.write('No sessions found.\n');
105
+ return;
106
+ }
107
+ process.stderr.write('\n\x1b[1mRecent Sessions:\x1b[0m\n');
108
+ for (const file of files) {
109
+ try {
110
+ const data = JSON.parse(fs.readFileSync(path.join(sessDir, file), 'utf-8'));
111
+ const date = file.replace('.json', '').replace(/T/g, ' ').replace(/-/g, ':').slice(0, 19);
112
+ const instr = (data.instruction || '').slice(0, 40);
113
+ const status = data.status || 'unknown';
114
+ process.stderr.write(` ${date} ${status.padEnd(10)} ${instr}\n`);
115
+ } catch {
116
+ process.stderr.write(` ${file} (unreadable)\n`);
117
+ }
118
+ }
119
+ process.stderr.write('\n');
120
+ }
121
+
122
+ function cmdExit() {
123
+ printGoodbye();
124
+ process.exit(0);
125
+ }
126
+
127
+ async function cmdIndex() {
128
+ const cwd = process.cwd();
129
+ process.stderr.write('\x1b[2mBuilding BM25 index...\x1b[0m\n');
130
+ try {
131
+ const retriever = new ContextRetriever(cwd);
132
+ const result = await retriever.buildIndex();
133
+ process.stderr.write(`\x1b[32m✓ Index built: ${result.fileCount} files, ${result.chunkCount} chunks\x1b[0m\n`);
134
+ process.stderr.write(`\x1b[2m Stored at: ${path.join(cwd, '.orca', 'index')}\x1b[0m\n`);
135
+ } catch (err) {
136
+ process.stderr.write(`\x1b[31mIndex build failed: ${err.message}\x1b[0m\n`);
137
+ }
138
+ }
139
+
140
+ function cmdModel(ctx) {
141
+ process.stderr.write(`Model: ${ctx.model || 'default (set by backend)'}\n`);
142
+ }
143
+
144
+ function cmdTokens(ctx) {
145
+ const t = ctx.formatter?.tokenCount || { input: 0, output: 0 };
146
+ process.stderr.write(`Tokens: ${t.input} input, ${t.output} output, ${t.input + t.output} total\n`);
147
+ }
148
+
149
+ function cmdCost(ctx) {
150
+ const t = ctx.formatter?.tokenCount || { input: 0, output: 0 };
151
+ // Rough estimate: Sonnet ~$3/$15 per MTok
152
+ const cost = (t.input * 3 + t.output * 15) / 1_000_000;
153
+ process.stderr.write(`Estimated cost: $${cost.toFixed(4)}\n`);
154
+ }
155
+
156
+ function cmdConfig(ctx) {
157
+ // Show local config summary
158
+ if (ctx.auth) ctx.auth.printConfig();
159
+
160
+ // Open settings in browser
161
+ import('../core/backend-url.mjs').then(({ resolveWebUrl }) => {
162
+ const webUrl = resolveWebUrl();
163
+ const settingsUrl = `${webUrl}/dashboard/settings?tab=providers&source=cli`;
164
+ process.stderr.write(`\x1b[36mOpening settings...\x1b[0m \x1b[2m${settingsUrl}\x1b[0m\n`);
165
+ const openCmd = process.platform === 'darwin' ? 'open' :
166
+ process.platform === 'win32' ? 'start' : 'xdg-open';
167
+ import('node:child_process').then(({ exec }) => {
168
+ exec(`${openCmd} "${settingsUrl}"`, () => {});
169
+ });
170
+ });
171
+ }
172
+
173
+ function cmdLogin(ctx) {
174
+ if (ctx.auth) {
175
+ process.stderr.write('\x1b[36mStarting login flow...\x1b[0m\n');
176
+ ctx.auth.login().then(() => {
177
+ process.stderr.write('\x1b[32m✓ Login successful!\x1b[0m\n');
178
+ }).catch((err) => {
179
+ process.stderr.write(`\x1b[31m✗ Login failed: ${err.message}\x1b[0m\n`);
180
+ });
181
+ }
182
+ }
183
+
184
+ function cmdRefresh(ctx) {
185
+ if (!ctx.auth) {
186
+ process.stderr.write('\x1b[31mNo auth module available.\x1b[0m\n');
187
+ return;
188
+ }
189
+ // Force re-read from ~/.orca/config.json
190
+ ctx.auth._config = null;
191
+ const creds = ctx.auth.loadCredentials();
192
+ const GREEN = '\x1b[32m', DIM = '\x1b[2m', CYAN = '\x1b[36m', RESET = '\x1b[0m';
193
+ process.stderr.write(`\n${GREEN}✓ Credentials reloaded${RESET}\n`);
194
+ process.stderr.write(` ${DIM}Auth:${RESET} ${creds.token ? 'logged in' : 'not logged in'}\n`);
195
+ process.stderr.write(` ${DIM}Gateway:${RESET} ${creds.gatewayType}\n`);
196
+ process.stderr.write(` ${DIM}Backend:${RESET} ${creds.backendUrl}\n`);
197
+ if (creds.models?.orchestrator) process.stderr.write(` ${DIM}Model:${RESET} ${creds.models.orchestrator}\n`);
198
+ process.stderr.write(`\n ${DIM}Next prompt will use updated credentials.${RESET}\n\n`);
199
+ }
200
+
201
+ function cmdSync(ctx) {
202
+ if (ctx.auth) {
203
+ process.stderr.write('\x1b[36mSyncing settings from web...\x1b[0m\n');
204
+ ctx.auth.syncSettings().then((remote) => {
205
+ process.stderr.write(`\x1b[32m✓ Synced:\x1b[0m gateway=${remote.gateway_type}`);
206
+ if (remote.models?.orchestrator) process.stderr.write(`, orchestrator=${remote.models.orchestrator}`);
207
+ if (remote.models?.reasoning) process.stderr.write(`, coding=${remote.models.reasoning}`);
208
+ process.stderr.write('\n');
209
+ }).catch((err) => {
210
+ process.stderr.write(`\x1b[31m✗ Sync failed: ${err.message}\x1b[0m\n`);
211
+ });
212
+ }
213
+ }
214
+
215
+ function cmdWhoami(ctx) {
216
+ if (!ctx.auth) {
217
+ process.stderr.write('\x1b[31mNot logged in.\x1b[0m\n');
218
+ return;
219
+ }
220
+ const creds = ctx.auth.loadCredentials();
221
+ if (!creds.token) {
222
+ process.stderr.write('\x1b[31mNot logged in. Run /login first.\x1b[0m\n');
223
+ return;
224
+ }
225
+ const backendUrl = creds.backendUrl;
226
+ process.stderr.write('\x1b[2mFetching user info...\x1b[0m\n');
227
+ fetch(`${backendUrl}/api/user/me`, {
228
+ headers: { 'Authorization': `Bearer ${creds.token}` },
229
+ }).then(r => {
230
+ if (!r.ok) throw new Error(`HTTP ${r.status}`);
231
+ return r.json();
232
+ }).then(data => {
233
+ const GREEN = '\x1b[32m', CYAN = '\x1b[36m', DIM = '\x1b[2m', RESET = '\x1b[0m';
234
+ process.stderr.write(`\n ${GREEN}✓${RESET} ${data.github_username || 'unknown'}\n`);
235
+ process.stderr.write(` ${DIM}Email:${RESET} ${data.email || 'n/a'}\n`);
236
+ process.stderr.write(` ${DIM}User ID:${RESET} ${data.id}\n`);
237
+ process.stderr.write(` ${DIM}Step:${RESET} ${data.onboarding_step || 'signed_up'}\n`);
238
+ process.stderr.write(` ${DIM}Role:${RESET} ${data.role || 'user'}\n\n`);
239
+ }).catch(err => {
240
+ process.stderr.write(`\x1b[31m✗ Failed: ${err.message}\x1b[0m\n`);
241
+ });
242
+ }
243
+
244
+ /**
245
+ * Execute a slash command if input starts with /.
246
+ * @returns {boolean} true if handled
247
+ */
248
+ export function handleSlashCommand(input, ctx) {
249
+ const parts = input.split(/\s+/);
250
+ const cmd = parts[0].toLowerCase();
251
+ const entry = COMMANDS[cmd];
252
+ if (!entry) {
253
+ process.stderr.write(`Unknown command: ${cmd}. Type /help for available commands.\n`);
254
+ return true;
255
+ }
256
+ entry.handler(ctx, parts.slice(1));
257
+ return true;
258
+ }
package/index.js DELETED
@@ -1 +0,0 @@
1
- module.exports = {};