oroute-cli 0.1.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 (70) hide show
  1. package/dist/agent.d.ts +11 -0
  2. package/dist/agent.js +569 -0
  3. package/dist/agent.js.map +1 -0
  4. package/dist/commands.d.ts +24 -0
  5. package/dist/commands.js +173 -0
  6. package/dist/commands.js.map +1 -0
  7. package/dist/context.d.ts +13 -0
  8. package/dist/context.js +110 -0
  9. package/dist/context.js.map +1 -0
  10. package/dist/cost.d.ts +18 -0
  11. package/dist/cost.js +80 -0
  12. package/dist/cost.js.map +1 -0
  13. package/dist/history.d.ts +20 -0
  14. package/dist/history.js +49 -0
  15. package/dist/history.js.map +1 -0
  16. package/dist/hooks.d.ts +13 -0
  17. package/dist/hooks.js +101 -0
  18. package/dist/hooks.js.map +1 -0
  19. package/dist/index.d.ts +2 -0
  20. package/dist/index.js +475 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/markdown.d.ts +4 -0
  23. package/dist/markdown.js +126 -0
  24. package/dist/markdown.js.map +1 -0
  25. package/dist/memory.d.ts +27 -0
  26. package/dist/memory.js +208 -0
  27. package/dist/memory.js.map +1 -0
  28. package/dist/session.d.ts +43 -0
  29. package/dist/session.js +166 -0
  30. package/dist/session.js.map +1 -0
  31. package/dist/streaming.d.ts +27 -0
  32. package/dist/streaming.js +201 -0
  33. package/dist/streaming.js.map +1 -0
  34. package/dist/tools/editFile.d.ts +34 -0
  35. package/dist/tools/editFile.js +40 -0
  36. package/dist/tools/editFile.js.map +1 -0
  37. package/dist/tools/executeCommand.d.ts +32 -0
  38. package/dist/tools/executeCommand.js +75 -0
  39. package/dist/tools/executeCommand.js.map +1 -0
  40. package/dist/tools/glob.d.ts +24 -0
  41. package/dist/tools/glob.js +128 -0
  42. package/dist/tools/glob.js.map +1 -0
  43. package/dist/tools/index.d.ts +40 -0
  44. package/dist/tools/index.js +28 -0
  45. package/dist/tools/index.js.map +1 -0
  46. package/dist/tools/listDirectory.d.ts +23 -0
  47. package/dist/tools/listDirectory.js +57 -0
  48. package/dist/tools/listDirectory.js.map +1 -0
  49. package/dist/tools/notebook.d.ts +7 -0
  50. package/dist/tools/notebook.js +76 -0
  51. package/dist/tools/notebook.js.map +1 -0
  52. package/dist/tools/readFile.d.ts +28 -0
  53. package/dist/tools/readFile.js +40 -0
  54. package/dist/tools/readFile.js.map +1 -0
  55. package/dist/tools/readImage.d.ts +25 -0
  56. package/dist/tools/readImage.js +52 -0
  57. package/dist/tools/readImage.js.map +1 -0
  58. package/dist/tools/searchFiles.d.ts +33 -0
  59. package/dist/tools/searchFiles.js +95 -0
  60. package/dist/tools/searchFiles.js.map +1 -0
  61. package/dist/tools/writeFile.d.ts +30 -0
  62. package/dist/tools/writeFile.js +54 -0
  63. package/dist/tools/writeFile.js.map +1 -0
  64. package/dist/ui.d.ts +30 -0
  65. package/dist/ui.js +79 -0
  66. package/dist/ui.js.map +1 -0
  67. package/dist/update.d.ts +10 -0
  68. package/dist/update.js +93 -0
  69. package/dist/update.js.map +1 -0
  70. package/package.json +33 -0
@@ -0,0 +1,173 @@
1
+ /**
2
+ * A5: Slash Commands — handle user slash commands in the agent loop.
3
+ * B7: Session commands, C5: Memory commands
4
+ */
5
+ import * as fs from 'node:fs';
6
+ import * as path from 'node:path';
7
+ import { GREEN, GRAY, BOLD, RESET, WHITE, YELLOW } from './ui.js';
8
+ import { printCostSummary } from './cost.js';
9
+ import { compressHistory } from './history.js';
10
+ import { handleSaveCommand, printSessionList, handleResumeCommand } from './session.js';
11
+ import { handleRememberCommand, handleMemoriesCommand, handleForgetCommand } from './memory.js';
12
+ /** Known slash commands — anything else starting with / is NOT a command */
13
+ const KNOWN_COMMANDS = new Set([
14
+ '/help', '/clear', '/compact', '/model', '/cost', '/status',
15
+ '/cd', '/exit', '/quit', '/save', '/sessions', '/resume',
16
+ '/remember', '/memories', '/forget',
17
+ ]);
18
+ /** Handle a slash command, returns whether it was handled */
19
+ export function handleSlashCommand(input, ctx) {
20
+ if (!input.startsWith('/'))
21
+ return 'not_command';
22
+ const parts = input.split(/\s+/);
23
+ const cmd = parts[0].toLowerCase();
24
+ const arg = parts.slice(1).join(' ').trim();
25
+ // Only treat as command if it's a known slash command
26
+ // This prevents paths like /Users/... from being intercepted
27
+ if (!KNOWN_COMMANDS.has(cmd))
28
+ return 'not_command';
29
+ switch (cmd) {
30
+ case '/help':
31
+ printHelp();
32
+ return 'handled';
33
+ case '/clear':
34
+ ctx.setMessages([]);
35
+ console.log(`${GREEN} Conversation cleared.${RESET}`);
36
+ return 'handled';
37
+ case '/compact': {
38
+ const result = compressHistory(ctx.messages);
39
+ if (result.compressed) {
40
+ ctx.setMessages(result.messages);
41
+ console.log(`${GREEN} History compressed: ${ctx.messages.length} messages → ${result.messages.length} messages${RESET}`);
42
+ }
43
+ else {
44
+ console.log(`${GRAY} History is already compact (${ctx.messages.length} messages).${RESET}`);
45
+ }
46
+ return 'handled';
47
+ }
48
+ case '/model':
49
+ if (arg) {
50
+ ctx.setModel(arg);
51
+ console.log(`${GREEN} Model set to: ${arg}${RESET}`);
52
+ }
53
+ else {
54
+ console.log(`${WHITE} Current model: ${ctx.model}${RESET}`);
55
+ console.log(`${GRAY} Options: auto, anthropic/claude-sonnet-4-6, openai/gpt-4o, google/gemini-2.5-pro, etc.${RESET}`);
56
+ }
57
+ return 'handled';
58
+ case '/cost':
59
+ printCostSummary(ctx.stats);
60
+ return 'handled';
61
+ case '/status':
62
+ printStatus(ctx);
63
+ return 'handled';
64
+ case '/cd':
65
+ if (!arg) {
66
+ console.log(`${WHITE} Current directory: ${ctx.cwd}${RESET}`);
67
+ return 'handled';
68
+ }
69
+ return handleCd(arg, ctx);
70
+ // B7: Session commands
71
+ case '/save':
72
+ handleSaveCommand(arg, ctx.messages, ctx.stats, ctx.cwd);
73
+ return 'handled';
74
+ case '/sessions':
75
+ printSessionList();
76
+ return 'handled';
77
+ case '/resume': {
78
+ const loaded = handleResumeCommand(arg);
79
+ if (loaded) {
80
+ ctx.setMessages(loaded.messages);
81
+ ctx.setStats(loaded.stats);
82
+ if (loaded.cwd !== ctx.cwd && fs.existsSync(loaded.cwd)) {
83
+ process.chdir(loaded.cwd);
84
+ ctx.setCwd(loaded.cwd);
85
+ console.log(`${GRAY} Restored cwd: ${loaded.cwd}${RESET}`);
86
+ }
87
+ }
88
+ return 'handled';
89
+ }
90
+ // C5: Memory commands
91
+ case '/remember':
92
+ handleRememberCommand(arg);
93
+ return 'handled';
94
+ case '/memories':
95
+ handleMemoriesCommand();
96
+ return 'handled';
97
+ case '/forget':
98
+ handleForgetCommand(arg);
99
+ return 'handled';
100
+ case '/exit':
101
+ case '/quit':
102
+ return 'exit';
103
+ default:
104
+ console.log(`${YELLOW} Unknown command: ${cmd}. Type /help for available commands.${RESET}`);
105
+ return 'handled';
106
+ }
107
+ }
108
+ function printHelp() {
109
+ console.log();
110
+ console.log(`${BOLD} Available Commands${RESET}`);
111
+ console.log(`${GRAY} ${'─'.repeat(40)}${RESET}`);
112
+ console.log(`${GREEN} /help${RESET} Show this help`);
113
+ console.log(`${GREEN} /clear${RESET} Clear conversation history`);
114
+ console.log(`${GREEN} /compact${RESET} Compress conversation history`);
115
+ console.log(`${GREEN} /model [name]${RESET} Show or change model`);
116
+ console.log(`${GREEN} /cost${RESET} Show session token usage and cost`);
117
+ console.log(`${GREEN} /status${RESET} Show current project, model, cwd, API`);
118
+ console.log(`${GREEN} /cd [path]${RESET} Change working directory`);
119
+ console.log();
120
+ console.log(`${BOLD} Session Commands${RESET}`);
121
+ console.log(`${GRAY} ${'─'.repeat(40)}${RESET}`);
122
+ console.log(`${GREEN} /save [name]${RESET} Save current session`);
123
+ console.log(`${GREEN} /sessions${RESET} List saved sessions`);
124
+ console.log(`${GREEN} /resume [id]${RESET} Resume a saved session`);
125
+ console.log();
126
+ console.log(`${BOLD} Memory Commands${RESET}`);
127
+ console.log(`${GRAY} ${'─'.repeat(40)}${RESET}`);
128
+ console.log(`${GREEN} /remember <text>${RESET} Save a memory`);
129
+ console.log(`${GREEN} /memories${RESET} List all memories`);
130
+ console.log(`${GREEN} /forget <name>${RESET} Delete a memory`);
131
+ console.log();
132
+ console.log(`${GREEN} /exit${RESET} Exit CLI`);
133
+ console.log();
134
+ console.log(`${BOLD} Multi-line Input${RESET}`);
135
+ console.log(`${GRAY} Type ${WHITE}"""${GRAY} to start multi-line mode, type ${WHITE}"""${GRAY} again to send.${RESET}`);
136
+ console.log();
137
+ console.log(`${BOLD} Available Tools${RESET}`);
138
+ console.log(`${GRAY} ${'─'.repeat(40)}${RESET}`);
139
+ console.log(`${GREEN} read_file${RESET} Read file contents (.ipynb supported)`);
140
+ console.log(`${GREEN} write_file${RESET} Create or overwrite files`);
141
+ console.log(`${GREEN} edit_file${RESET} Replace text in a file`);
142
+ console.log(`${GREEN} list_directory${RESET} List directory tree`);
143
+ console.log(`${GREEN} search_files${RESET} Search for text patterns`);
144
+ console.log(`${GREEN} execute_command${RESET} Run shell commands`);
145
+ console.log(`${GREEN} glob${RESET} Find files by pattern`);
146
+ console.log(`${GREEN} read_image${RESET} Read image for analysis`);
147
+ console.log();
148
+ }
149
+ function printStatus(ctx) {
150
+ console.log();
151
+ console.log(`${BOLD} O'Route Agent Status${RESET}`);
152
+ console.log(`${GRAY} ${'─'.repeat(35)}${RESET}`);
153
+ console.log(`${WHITE} Model: ${ctx.model}${RESET}`);
154
+ console.log(`${WHITE} CWD: ${ctx.cwd}${RESET}`);
155
+ console.log(`${WHITE} API: ${ctx.apiUrl}${RESET}`);
156
+ console.log(`${WHITE} Key: ${ctx.apiKey.slice(0, 11)}...${RESET}`);
157
+ console.log(`${WHITE} Messages: ${ctx.messages.length}${RESET}`);
158
+ console.log(`${WHITE} Requests: ${ctx.stats.requests}${RESET}`);
159
+ console.log();
160
+ }
161
+ function handleCd(arg, ctx) {
162
+ const newDir = path.resolve(ctx.cwd, arg);
163
+ if (fs.existsSync(newDir) && fs.statSync(newDir).isDirectory()) {
164
+ process.chdir(newDir);
165
+ ctx.setCwd(newDir);
166
+ console.log(`${GREEN} Changed to: ${newDir}${RESET}`);
167
+ }
168
+ else {
169
+ console.log(`${YELLOW} Directory not found: ${newDir}${RESET}`);
170
+ }
171
+ return 'handled';
172
+ }
173
+ //# sourceMappingURL=commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ interface ProjectContext {
2
+ files: Array<{
3
+ name: string;
4
+ content: string;
5
+ }>;
6
+ gitBranch?: string;
7
+ gitStatus?: string;
8
+ }
9
+ /** Load project context from cwd */
10
+ export declare function loadProjectContext(cwd: string): ProjectContext;
11
+ /** Build context string for system prompt */
12
+ export declare function buildContextString(ctx: ProjectContext): string;
13
+ export {};
@@ -0,0 +1,110 @@
1
+ /**
2
+ * A2: Context Auto-Loading — read project context files and git info.
3
+ */
4
+ import * as fs from 'node:fs';
5
+ import * as path from 'node:path';
6
+ import { execSync } from 'node:child_process';
7
+ /** Maximum total chars for auto-loaded context */
8
+ const MAX_CONTEXT_CHARS = 2000;
9
+ /** Read a file safely, return empty string on failure */
10
+ function safeReadFile(filePath, maxChars = 800) {
11
+ try {
12
+ if (!fs.existsSync(filePath))
13
+ return '';
14
+ const content = fs.readFileSync(filePath, 'utf-8');
15
+ return content.length > maxChars ? content.slice(0, maxChars) + '\n...(truncated)' : content;
16
+ }
17
+ catch {
18
+ return '';
19
+ }
20
+ }
21
+ /** Extract relevant keys from package.json */
22
+ function extractPackageJson(filePath) {
23
+ try {
24
+ if (!fs.existsSync(filePath))
25
+ return '';
26
+ const raw = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
27
+ const extracted = {};
28
+ for (const key of ['name', 'description', 'scripts', 'dependencies']) {
29
+ if (raw[key] !== undefined)
30
+ extracted[key] = raw[key];
31
+ }
32
+ return JSON.stringify(extracted, null, 2);
33
+ }
34
+ catch {
35
+ return '';
36
+ }
37
+ }
38
+ /** Get git branch name */
39
+ function getGitBranch(cwd) {
40
+ try {
41
+ return execSync('git rev-parse --abbrev-ref HEAD 2>/dev/null', { cwd, encoding: 'utf-8' }).trim() || undefined;
42
+ }
43
+ catch {
44
+ return undefined;
45
+ }
46
+ }
47
+ /** Get git status summary */
48
+ function getGitStatusSummary(cwd) {
49
+ try {
50
+ const isGit = execSync('git rev-parse --is-inside-work-tree 2>/dev/null', { cwd, encoding: 'utf-8' }).trim();
51
+ if (isGit !== 'true')
52
+ return undefined;
53
+ const status = execSync('git status --short 2>/dev/null', { cwd, encoding: 'utf-8' }).trim();
54
+ if (!status)
55
+ return 'clean';
56
+ const lines = status.split('\n');
57
+ const modified = lines.filter(l => l.startsWith(' M') || l.startsWith('M ')).length;
58
+ const added = lines.filter(l => l.startsWith('A ') || l.startsWith('??')).length;
59
+ const deleted = lines.filter(l => l.startsWith(' D') || l.startsWith('D ')).length;
60
+ const parts = [];
61
+ if (modified > 0)
62
+ parts.push(`${modified} modified`);
63
+ if (added > 0)
64
+ parts.push(`${added} untracked/added`);
65
+ if (deleted > 0)
66
+ parts.push(`${deleted} deleted`);
67
+ return parts.join(', ') || 'clean';
68
+ }
69
+ catch {
70
+ return undefined;
71
+ }
72
+ }
73
+ /** Load project context from cwd */
74
+ export function loadProjectContext(cwd) {
75
+ const contextFiles = [];
76
+ // Context file candidates (priority order)
77
+ const candidates = [
78
+ { name: 'CLAUDE.md', loader: () => safeReadFile(path.join(cwd, 'CLAUDE.md')) },
79
+ { name: '.claude/CLAUDE.md', loader: () => safeReadFile(path.join(cwd, '.claude', 'CLAUDE.md')) },
80
+ { name: '.oroute.md', loader: () => safeReadFile(path.join(cwd, '.oroute.md')) },
81
+ { name: 'package.json', loader: () => extractPackageJson(path.join(cwd, 'package.json')) },
82
+ ];
83
+ let totalChars = 0;
84
+ for (const c of candidates) {
85
+ if (totalChars >= MAX_CONTEXT_CHARS)
86
+ break;
87
+ const content = c.loader();
88
+ if (!content)
89
+ continue;
90
+ const remaining = MAX_CONTEXT_CHARS - totalChars;
91
+ const trimmed = content.length > remaining ? content.slice(0, remaining) + '\n...(truncated)' : content;
92
+ contextFiles.push({ name: c.name, content: trimmed });
93
+ totalChars += trimmed.length;
94
+ }
95
+ const gitBranch = getGitBranch(cwd);
96
+ const gitStatus = getGitStatusSummary(cwd);
97
+ return { files: contextFiles, gitBranch, gitStatus };
98
+ }
99
+ /** Build context string for system prompt */
100
+ export function buildContextString(ctx) {
101
+ const parts = [];
102
+ if (ctx.gitBranch) {
103
+ parts.push(`Git branch: ${ctx.gitBranch}${ctx.gitStatus ? `, Status: ${ctx.gitStatus}` : ''}`);
104
+ }
105
+ for (const f of ctx.files) {
106
+ parts.push(`--- ${f.name} ---\n${f.content}`);
107
+ }
108
+ return parts.join('\n\n');
109
+ }
110
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
package/dist/cost.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ export interface SessionStats {
2
+ inputTokens: number;
3
+ outputTokens: number;
4
+ requests: number;
5
+ startTime: number;
6
+ providerCounts: Record<string, number>;
7
+ }
8
+ export declare function createSessionStats(): SessionStats;
9
+ export declare function updateStats(stats: SessionStats, usage: {
10
+ input_tokens: number;
11
+ output_tokens: number;
12
+ }, provider?: string): SessionStats;
13
+ /** Estimate cost in USD */
14
+ export declare function estimateCost(stats: SessionStats): number;
15
+ /** Print cost summary for /cost command */
16
+ export declare function printCostSummary(stats: SessionStats): void;
17
+ /** Print brief cost on exit */
18
+ export declare function printExitSummary(stats: SessionStats): void;
package/dist/cost.js ADDED
@@ -0,0 +1,80 @@
1
+ /**
2
+ * B6: Cost Tracking — track session usage and estimate costs.
3
+ */
4
+ import { GREEN, GRAY, BOLD, DIM, RESET, WHITE } from './ui.js';
5
+ /** Per-million-token pricing by provider (approximate USD) */
6
+ const PRICING = {
7
+ 'anthropic': { input: 3.0, output: 15.0 },
8
+ 'openai': { input: 2.5, output: 10.0 },
9
+ 'google': { input: 1.25, output: 5.0 },
10
+ 'qwen': { input: 0.5, output: 1.5 },
11
+ 'deepseek': { input: 0.27, output: 1.1 },
12
+ 'default': { input: 2.0, output: 8.0 },
13
+ };
14
+ export function createSessionStats() {
15
+ return {
16
+ inputTokens: 0,
17
+ outputTokens: 0,
18
+ requests: 0,
19
+ startTime: Date.now(),
20
+ providerCounts: {},
21
+ };
22
+ }
23
+ export function updateStats(stats, usage, provider) {
24
+ const providerKey = provider ?? 'default';
25
+ const newProviderCounts = { ...stats.providerCounts };
26
+ newProviderCounts[providerKey] = (newProviderCounts[providerKey] ?? 0) + 1;
27
+ return {
28
+ ...stats,
29
+ inputTokens: stats.inputTokens + usage.input_tokens,
30
+ outputTokens: stats.outputTokens + usage.output_tokens,
31
+ requests: stats.requests + 1,
32
+ startTime: stats.startTime,
33
+ providerCounts: newProviderCounts,
34
+ };
35
+ }
36
+ /** Estimate cost in USD */
37
+ export function estimateCost(stats) {
38
+ // Use default pricing (approximation)
39
+ const pricing = PRICING['default'];
40
+ const inputCost = (stats.inputTokens / 1_000_000) * pricing.input;
41
+ const outputCost = (stats.outputTokens / 1_000_000) * pricing.output;
42
+ return inputCost + outputCost;
43
+ }
44
+ /** Format duration in human-readable */
45
+ function formatDuration(ms) {
46
+ const seconds = Math.floor(ms / 1000);
47
+ if (seconds < 60)
48
+ return `${seconds}s`;
49
+ const minutes = Math.floor(seconds / 60);
50
+ const secs = seconds % 60;
51
+ return `${minutes}m ${secs}s`;
52
+ }
53
+ /** Print cost summary for /cost command */
54
+ export function printCostSummary(stats) {
55
+ const cost = estimateCost(stats);
56
+ const duration = formatDuration(Date.now() - stats.startTime);
57
+ console.log();
58
+ console.log(`${BOLD} Session Cost Summary${RESET}`);
59
+ console.log(`${GRAY} ${'─'.repeat(35)}${RESET}`);
60
+ console.log(`${WHITE} Requests: ${stats.requests}${RESET}`);
61
+ console.log(`${WHITE} Input tokens: ${stats.inputTokens.toLocaleString()}${RESET}`);
62
+ console.log(`${WHITE} Output tokens: ${stats.outputTokens.toLocaleString()}${RESET}`);
63
+ console.log(`${WHITE} Total tokens: ${(stats.inputTokens + stats.outputTokens).toLocaleString()}${RESET}`);
64
+ console.log(`${GREEN} Est. cost: $${cost.toFixed(4)}${RESET}`);
65
+ console.log(`${GRAY} Duration: ${duration}${RESET}`);
66
+ const providers = Object.entries(stats.providerCounts);
67
+ if (providers.length > 0) {
68
+ console.log(`${GRAY} Providers: ${providers.map(([p, c]) => `${p}(${c})`).join(', ')}${RESET}`);
69
+ }
70
+ console.log();
71
+ }
72
+ /** Print brief cost on exit */
73
+ export function printExitSummary(stats) {
74
+ if (stats.requests === 0)
75
+ return;
76
+ const cost = estimateCost(stats);
77
+ const duration = formatDuration(Date.now() - stats.startTime);
78
+ console.log(`${DIM} Session: ${stats.requests} requests, ${(stats.inputTokens + stats.outputTokens).toLocaleString()} tokens, ~$${cost.toFixed(4)}, ${duration}${RESET}`);
79
+ }
80
+ //# sourceMappingURL=cost.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost.js","sourceRoot":"","sources":["../src/cost.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * A4: History Compression — summarize old messages to stay within token limits.
3
+ */
4
+ interface Message {
5
+ role: string;
6
+ content: string | Array<{
7
+ type: string;
8
+ [key: string]: unknown;
9
+ }>;
10
+ }
11
+ /** Approximate token count from message content */
12
+ export declare function estimateTokens(messages: Message[]): number;
13
+ /** Token threshold above which we compress */
14
+ export declare const TOKEN_THRESHOLD = 6000;
15
+ /** Compress conversation history by summarizing old messages */
16
+ export declare function compressHistory(messages: Message[]): {
17
+ messages: Message[];
18
+ compressed: boolean;
19
+ };
20
+ export {};
@@ -0,0 +1,49 @@
1
+ /**
2
+ * A4: History Compression — summarize old messages to stay within token limits.
3
+ */
4
+ /** Approximate token count from message content */
5
+ export function estimateTokens(messages) {
6
+ return messages.reduce((sum, m) => {
7
+ const contentStr = typeof m.content === 'string' ? m.content : JSON.stringify(m.content);
8
+ return sum + Math.ceil(contentStr.length / 4);
9
+ }, 0);
10
+ }
11
+ /** Token threshold above which we compress */
12
+ export const TOKEN_THRESHOLD = 6000;
13
+ /** Number of recent messages to always keep */
14
+ const KEEP_RECENT = 4;
15
+ /** Compress conversation history by summarizing old messages */
16
+ export function compressHistory(messages) {
17
+ if (messages.length <= KEEP_RECENT + 1) {
18
+ return { messages, compressed: false };
19
+ }
20
+ const estimated = estimateTokens(messages);
21
+ if (estimated <= TOKEN_THRESHOLD) {
22
+ return { messages, compressed: false };
23
+ }
24
+ // Keep the last KEEP_RECENT messages
25
+ const recentMessages = messages.slice(-KEEP_RECENT);
26
+ const oldMessages = messages.slice(0, -KEEP_RECENT);
27
+ // Build a summary of old messages
28
+ const summaryParts = [];
29
+ for (const msg of oldMessages) {
30
+ const contentStr = typeof msg.content === 'string'
31
+ ? msg.content
32
+ : JSON.stringify(msg.content);
33
+ // Truncate individual messages in summary
34
+ const truncated = contentStr.length > 200
35
+ ? contentStr.slice(0, 200) + '...'
36
+ : contentStr;
37
+ summaryParts.push(`[${msg.role}]: ${truncated}`);
38
+ }
39
+ const summary = summaryParts.join('\n');
40
+ const summaryMessage = {
41
+ role: 'user',
42
+ content: `[Previous context summary — ${oldMessages.length} messages compressed]:\n${summary}`,
43
+ };
44
+ return {
45
+ messages: [summaryMessage, ...recentMessages],
46
+ compressed: true,
47
+ };
48
+ }
49
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.js","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,mDAAmD;AACnD,MAAM,UAAU,cAAc,CAAC,QAAmB;IAChD,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;QAChC,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QACzF,OAAO,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAChD,CAAC,EAAE,CAAC,CAAC,CAAC;AACR,CAAC;AAED,8CAA8C;AAC9C,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC;AAEpC,+CAA+C;AAC/C,MAAM,WAAW,GAAG,CAAC,CAAC;AAEtB,gEAAgE;AAChE,MAAM,UAAU,eAAe,CAAC,QAAmB;IACjD,IAAI,QAAQ,CAAC,MAAM,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QACvC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IACzC,CAAC;IAED,MAAM,SAAS,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC3C,IAAI,SAAS,IAAI,eAAe,EAAE,CAAC;QACjC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IACzC,CAAC;IAED,qCAAqC;IACrC,MAAM,cAAc,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,CAAC;IACpD,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC;IAEpD,kCAAkC;IAClC,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,MAAM,UAAU,GAAG,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;YAChD,CAAC,CAAC,GAAG,CAAC,OAAO;YACb,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAEhC,0CAA0C;QAC1C,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,GAAG,GAAG;YACvC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK;YAClC,CAAC,CAAC,UAAU,CAAC;QAEf,YAAY,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,MAAM,SAAS,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,cAAc,GAAY;QAC9B,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,+BAA+B,WAAW,CAAC,MAAM,2BAA2B,OAAO,EAAE;KAC/F,CAAC;IAEF,OAAO;QACL,QAAQ,EAAE,CAAC,cAAc,EAAE,GAAG,cAAc,CAAC;QAC7C,UAAU,EAAE,IAAI;KACjB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ interface Hook {
2
+ matcher: string;
3
+ command: string;
4
+ }
5
+ interface HooksConfig {
6
+ PreToolUse?: Hook[];
7
+ PostToolUse?: Hook[];
8
+ }
9
+ /** Load hooks configuration from .oroute/hooks.json or .claude/settings.json */
10
+ export declare function loadHooks(cwd: string): HooksConfig;
11
+ /** Run matching hooks for a given phase and tool */
12
+ export declare function runHooks(phase: 'PreToolUse' | 'PostToolUse', hooks: HooksConfig, toolName: string, toolInput: Record<string, unknown>, cwd: string): boolean;
13
+ export {};
package/dist/hooks.js ADDED
@@ -0,0 +1,101 @@
1
+ /**
2
+ * C3: Hooks System — run pre/post tool hooks (Claude Code compatible).
3
+ */
4
+ import * as fs from 'node:fs';
5
+ import * as path from 'node:path';
6
+ import { execSync } from 'node:child_process';
7
+ import { GRAY, YELLOW, DIM, RESET } from './ui.js';
8
+ const HOOK_TIMEOUT_MS = 5000;
9
+ /** Load hooks configuration from .oroute/hooks.json or .claude/settings.json */
10
+ export function loadHooks(cwd) {
11
+ // Try .oroute/hooks.json first
12
+ const orouteHooksPath = path.join(cwd, '.oroute', 'hooks.json');
13
+ const config = tryLoadJson(orouteHooksPath);
14
+ if (config)
15
+ return config;
16
+ // Try .claude/settings.json (Claude Code compatible)
17
+ const claudeSettingsPath = path.join(cwd, '.claude', 'settings.json');
18
+ const claudeSettings = tryLoadJson(claudeSettingsPath);
19
+ if (claudeSettings) {
20
+ const result = {};
21
+ if (Array.isArray(claudeSettings['PreToolUse'])) {
22
+ result.PreToolUse = claudeSettings['PreToolUse'];
23
+ }
24
+ if (Array.isArray(claudeSettings['PostToolUse'])) {
25
+ result.PostToolUse = claudeSettings['PostToolUse'];
26
+ }
27
+ if (result.PreToolUse || result.PostToolUse)
28
+ return result;
29
+ }
30
+ return {};
31
+ }
32
+ function tryLoadJson(filePath) {
33
+ try {
34
+ if (!fs.existsSync(filePath))
35
+ return null;
36
+ return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
37
+ }
38
+ catch {
39
+ return null;
40
+ }
41
+ }
42
+ /** Run matching hooks for a given phase and tool */
43
+ export function runHooks(phase, hooks, toolName, toolInput, cwd) {
44
+ const phaseHooks = hooks[phase];
45
+ if (!phaseHooks || phaseHooks.length === 0)
46
+ return true;
47
+ for (const hook of phaseHooks) {
48
+ const matchRegex = new RegExp(hook.matcher);
49
+ if (!matchRegex.test(toolName))
50
+ continue;
51
+ // Build environment variables for the hook
52
+ const filePath = extractFilePath(toolInput);
53
+ const env = {
54
+ ...process.env,
55
+ TOOL_NAME: toolName,
56
+ TOOL_INPUT: JSON.stringify(toolInput),
57
+ };
58
+ if (filePath) {
59
+ env['FILE_PATH'] = filePath;
60
+ }
61
+ try {
62
+ const command = substituteEnvVars(hook.command, env);
63
+ console.log(`${DIM} [${phase}] ${command}${RESET}`);
64
+ execSync(command, {
65
+ cwd,
66
+ timeout: HOOK_TIMEOUT_MS,
67
+ stdio: 'pipe',
68
+ env,
69
+ });
70
+ }
71
+ catch (err) {
72
+ if (phase === 'PreToolUse') {
73
+ const exitCode = err.status ?? 1;
74
+ if (exitCode !== 0) {
75
+ console.log(`${YELLOW} [${phase}] Hook failed (exit ${exitCode}), skipping tool.${RESET}`);
76
+ return false;
77
+ }
78
+ }
79
+ // PostToolUse hook failures are non-blocking
80
+ if (phase === 'PostToolUse') {
81
+ console.log(`${GRAY} [${phase}] Hook warning: ${err.message ?? 'unknown error'}${RESET}`);
82
+ }
83
+ }
84
+ }
85
+ return true;
86
+ }
87
+ /** Extract file path from tool input (if applicable) */
88
+ function extractFilePath(input) {
89
+ if (typeof input['path'] === 'string')
90
+ return input['path'];
91
+ if (typeof input['file_path'] === 'string')
92
+ return input['file_path'];
93
+ return null;
94
+ }
95
+ /** Substitute $VAR_NAME in command string with environment values */
96
+ function substituteEnvVars(command, env) {
97
+ return command.replace(/\$([A-Z_][A-Z0-9_]*)/g, (_match, varName) => {
98
+ return env[varName] ?? '';
99
+ });
100
+ }
101
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};