@calliopelabs/cli 0.4.6 → 0.6.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 (112) hide show
  1. package/README.md +258 -105
  2. package/dist/branching.d.ts +56 -0
  3. package/dist/branching.d.ts.map +1 -0
  4. package/dist/branching.js +211 -0
  5. package/dist/branching.js.map +1 -0
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/cli.js +235 -2
  8. package/dist/cli.js.map +1 -1
  9. package/dist/completion.d.ts +75 -0
  10. package/dist/completion.d.ts.map +1 -0
  11. package/dist/completion.js +234 -0
  12. package/dist/completion.js.map +1 -0
  13. package/dist/config.d.ts +36 -0
  14. package/dist/config.d.ts.map +1 -1
  15. package/dist/config.js +90 -0
  16. package/dist/config.js.map +1 -1
  17. package/dist/diff.d.ts +73 -0
  18. package/dist/diff.d.ts.map +1 -0
  19. package/dist/diff.js +317 -0
  20. package/dist/diff.js.map +1 -0
  21. package/dist/errors.d.ts +41 -0
  22. package/dist/errors.d.ts.map +1 -0
  23. package/dist/errors.js +199 -0
  24. package/dist/errors.js.map +1 -0
  25. package/dist/file-watcher.d.ts +91 -0
  26. package/dist/file-watcher.d.ts.map +1 -0
  27. package/dist/file-watcher.js +269 -0
  28. package/dist/file-watcher.js.map +1 -0
  29. package/dist/files.d.ts +49 -0
  30. package/dist/files.d.ts.map +1 -0
  31. package/dist/files.js +191 -0
  32. package/dist/files.js.map +1 -0
  33. package/dist/fuzzy-search.d.ts +75 -0
  34. package/dist/fuzzy-search.d.ts.map +1 -0
  35. package/dist/fuzzy-search.js +240 -0
  36. package/dist/fuzzy-search.js.map +1 -0
  37. package/dist/hooks.d.ts +79 -0
  38. package/dist/hooks.d.ts.map +1 -0
  39. package/dist/hooks.js +271 -0
  40. package/dist/hooks.js.map +1 -0
  41. package/dist/keyboard.d.ts +57 -0
  42. package/dist/keyboard.d.ts.map +1 -0
  43. package/dist/keyboard.js +265 -0
  44. package/dist/keyboard.js.map +1 -0
  45. package/dist/markdown.d.ts +14 -0
  46. package/dist/markdown.d.ts.map +1 -0
  47. package/dist/markdown.js +248 -0
  48. package/dist/markdown.js.map +1 -0
  49. package/dist/mcp.d.ts +90 -0
  50. package/dist/mcp.d.ts.map +1 -0
  51. package/dist/mcp.js +290 -0
  52. package/dist/mcp.js.map +1 -0
  53. package/dist/memory.d.ts +104 -0
  54. package/dist/memory.d.ts.map +1 -0
  55. package/dist/memory.js +394 -0
  56. package/dist/memory.js.map +1 -0
  57. package/dist/model-router.d.ts +67 -0
  58. package/dist/model-router.d.ts.map +1 -0
  59. package/dist/model-router.js +289 -0
  60. package/dist/model-router.js.map +1 -0
  61. package/dist/parallel-tools.d.ts +51 -0
  62. package/dist/parallel-tools.d.ts.map +1 -0
  63. package/dist/parallel-tools.js +278 -0
  64. package/dist/parallel-tools.js.map +1 -0
  65. package/dist/project-config.d.ts +84 -0
  66. package/dist/project-config.d.ts.map +1 -0
  67. package/dist/project-config.js +250 -0
  68. package/dist/project-config.js.map +1 -0
  69. package/dist/providers.d.ts +10 -2
  70. package/dist/providers.d.ts.map +1 -1
  71. package/dist/providers.js +240 -38
  72. package/dist/providers.js.map +1 -1
  73. package/dist/risk.d.ts +31 -0
  74. package/dist/risk.d.ts.map +1 -0
  75. package/dist/risk.js +367 -0
  76. package/dist/risk.js.map +1 -0
  77. package/dist/sandbox.d.ts +49 -0
  78. package/dist/sandbox.d.ts.map +1 -0
  79. package/dist/sandbox.js +347 -0
  80. package/dist/sandbox.js.map +1 -0
  81. package/dist/skills.d.ts +71 -0
  82. package/dist/skills.d.ts.map +1 -0
  83. package/dist/skills.js +383 -0
  84. package/dist/skills.js.map +1 -0
  85. package/dist/storage.d.ts +139 -0
  86. package/dist/storage.d.ts.map +1 -0
  87. package/dist/storage.js +508 -0
  88. package/dist/storage.js.map +1 -0
  89. package/dist/streaming.d.ts +94 -0
  90. package/dist/streaming.d.ts.map +1 -0
  91. package/dist/streaming.js +305 -0
  92. package/dist/streaming.js.map +1 -0
  93. package/dist/summarization.d.ts +76 -0
  94. package/dist/summarization.d.ts.map +1 -0
  95. package/dist/summarization.js +242 -0
  96. package/dist/summarization.js.map +1 -0
  97. package/dist/themes.d.ts +110 -0
  98. package/dist/themes.d.ts.map +1 -0
  99. package/dist/themes.js +329 -0
  100. package/dist/themes.js.map +1 -0
  101. package/dist/tools.d.ts.map +1 -1
  102. package/dist/tools.js +335 -1
  103. package/dist/tools.js.map +1 -1
  104. package/dist/types.d.ts +56 -1
  105. package/dist/types.d.ts.map +1 -1
  106. package/dist/types.js +105 -0
  107. package/dist/types.js.map +1 -1
  108. package/dist/ui-cli.d.ts +9 -2
  109. package/dist/ui-cli.d.ts.map +1 -1
  110. package/dist/ui-cli.js +1315 -220
  111. package/dist/ui-cli.js.map +1 -1
  112. package/package.json +1 -1
@@ -0,0 +1,240 @@
1
+ /**
2
+ * Calliope CLI - Fuzzy File Search
3
+ *
4
+ * Fast fuzzy file finder with fzf-style matching.
5
+ */
6
+ import * as fs from 'fs';
7
+ import * as path from 'path';
8
+ // ============================================================================
9
+ // Default Ignore Patterns
10
+ // ============================================================================
11
+ const DEFAULT_IGNORE_DIRS = [
12
+ 'node_modules',
13
+ '.git',
14
+ '.svn',
15
+ '.hg',
16
+ 'dist',
17
+ 'build',
18
+ 'out',
19
+ '.next',
20
+ '.nuxt',
21
+ '__pycache__',
22
+ '.pytest_cache',
23
+ 'coverage',
24
+ '.nyc_output',
25
+ 'vendor',
26
+ 'target',
27
+ '.cargo',
28
+ ];
29
+ // ============================================================================
30
+ // File Scanning
31
+ // ============================================================================
32
+ /**
33
+ * Recursively get all files in directory
34
+ */
35
+ export function getAllFiles(dir, options = {}, basePath = dir) {
36
+ const files = [];
37
+ const excludeDirs = options.excludeDirs || DEFAULT_IGNORE_DIRS;
38
+ try {
39
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
40
+ for (const entry of entries) {
41
+ // Skip hidden files unless requested
42
+ if (!options.includeHidden && entry.name.startsWith('.')) {
43
+ continue;
44
+ }
45
+ const fullPath = path.join(dir, entry.name);
46
+ const relativePath = path.relative(basePath, fullPath);
47
+ if (entry.isDirectory()) {
48
+ // Skip excluded directories
49
+ if (excludeDirs.includes(entry.name)) {
50
+ continue;
51
+ }
52
+ files.push(...getAllFiles(fullPath, options, basePath));
53
+ }
54
+ else if (entry.isFile()) {
55
+ // Filter by extension if specified
56
+ if (options.extensions && options.extensions.length > 0) {
57
+ const ext = path.extname(entry.name).slice(1);
58
+ if (!options.extensions.includes(ext)) {
59
+ continue;
60
+ }
61
+ }
62
+ files.push(relativePath);
63
+ }
64
+ }
65
+ }
66
+ catch {
67
+ // Ignore permission errors
68
+ }
69
+ return files;
70
+ }
71
+ // ============================================================================
72
+ // Fuzzy Matching
73
+ // ============================================================================
74
+ /**
75
+ * Calculate fuzzy match score and positions
76
+ * Higher score = better match
77
+ */
78
+ export function fuzzyMatch(pattern, text, caseSensitive = false) {
79
+ const p = caseSensitive ? pattern : pattern.toLowerCase();
80
+ const t = caseSensitive ? text : text.toLowerCase();
81
+ if (p.length === 0)
82
+ return { score: 0, matches: [] };
83
+ if (p.length > t.length)
84
+ return null;
85
+ const matches = [];
86
+ let score = 0;
87
+ let patternIdx = 0;
88
+ let lastMatchEnd = -1;
89
+ let consecutiveBonus = 0;
90
+ for (let textIdx = 0; textIdx < t.length && patternIdx < p.length; textIdx++) {
91
+ if (t[textIdx] === p[patternIdx]) {
92
+ // Start new match or extend existing
93
+ if (textIdx === lastMatchEnd) {
94
+ // Consecutive match - extend and add bonus
95
+ matches[matches.length - 1][1] = textIdx + 1;
96
+ consecutiveBonus += 2;
97
+ }
98
+ else {
99
+ // New match segment
100
+ matches.push([textIdx, textIdx + 1]);
101
+ consecutiveBonus = 0;
102
+ }
103
+ // Scoring bonuses
104
+ let matchScore = 1 + consecutiveBonus;
105
+ // Bonus for matching at start
106
+ if (textIdx === 0)
107
+ matchScore += 5;
108
+ // Bonus for matching after separator
109
+ if (textIdx > 0 && (t[textIdx - 1] === '/' || t[textIdx - 1] === '-' || t[textIdx - 1] === '_' || t[textIdx - 1] === '.')) {
110
+ matchScore += 3;
111
+ }
112
+ // Bonus for matching uppercase in camelCase
113
+ if (text[textIdx] === text[textIdx].toUpperCase() && text[textIdx] !== text[textIdx].toLowerCase()) {
114
+ matchScore += 2;
115
+ }
116
+ score += matchScore;
117
+ lastMatchEnd = textIdx + 1;
118
+ patternIdx++;
119
+ }
120
+ }
121
+ // Did we match all pattern characters?
122
+ if (patternIdx !== p.length)
123
+ return null;
124
+ // Penalize longer strings (prefer shorter matches)
125
+ score -= t.length * 0.1;
126
+ // Bonus for exact match
127
+ if (p === t)
128
+ score += 10;
129
+ // Bonus for matching filename (last segment)
130
+ const filename = text.split('/').pop() || '';
131
+ if (filename.toLowerCase().includes(p)) {
132
+ score += 5;
133
+ }
134
+ return { score, matches };
135
+ }
136
+ // ============================================================================
137
+ // Search
138
+ // ============================================================================
139
+ /**
140
+ * Search files with fuzzy matching
141
+ */
142
+ export function searchFiles(dir, pattern, options = {}) {
143
+ const maxResults = options.maxResults || 50;
144
+ const files = getAllFiles(dir, options);
145
+ const results = [];
146
+ for (const relativePath of files) {
147
+ const match = fuzzyMatch(pattern, relativePath, options.caseSensitive);
148
+ if (match) {
149
+ results.push({
150
+ path: path.join(dir, relativePath),
151
+ relativePath,
152
+ score: match.score,
153
+ matches: match.matches,
154
+ });
155
+ }
156
+ }
157
+ // Sort by score (descending)
158
+ results.sort((a, b) => b.score - a.score);
159
+ return results.slice(0, maxResults);
160
+ }
161
+ /**
162
+ * Search with highlighting for display
163
+ */
164
+ export function searchWithHighlight(dir, pattern, options = {}) {
165
+ const results = searchFiles(dir, pattern, options);
166
+ return results.map(result => ({
167
+ path: result.path,
168
+ highlighted: highlightMatches(result.relativePath, result.matches),
169
+ score: result.score,
170
+ }));
171
+ }
172
+ /**
173
+ * Highlight matching segments in text
174
+ */
175
+ export function highlightMatches(text, matches, highlightStart = '\x1b[1;33m', // Bold yellow
176
+ highlightEnd = '\x1b[0m') {
177
+ if (matches.length === 0)
178
+ return text;
179
+ let result = '';
180
+ let lastEnd = 0;
181
+ for (const [start, end] of matches) {
182
+ result += text.slice(lastEnd, start);
183
+ result += highlightStart + text.slice(start, end) + highlightEnd;
184
+ lastEnd = end;
185
+ }
186
+ result += text.slice(lastEnd);
187
+ return result;
188
+ }
189
+ /**
190
+ * Create interactive search state
191
+ */
192
+ export function createSearchState(dir, options = {}) {
193
+ return {
194
+ query: '',
195
+ results: [],
196
+ selectedIndex: 0,
197
+ dir,
198
+ options,
199
+ };
200
+ }
201
+ /**
202
+ * Update search with new query
203
+ */
204
+ export function updateSearch(state, query) {
205
+ const results = query ? searchFiles(state.dir, query, state.options) : [];
206
+ return {
207
+ ...state,
208
+ query,
209
+ results,
210
+ selectedIndex: 0,
211
+ };
212
+ }
213
+ /**
214
+ * Move selection up
215
+ */
216
+ export function selectUp(state) {
217
+ return {
218
+ ...state,
219
+ selectedIndex: Math.max(0, state.selectedIndex - 1),
220
+ };
221
+ }
222
+ /**
223
+ * Move selection down
224
+ */
225
+ export function selectDown(state) {
226
+ return {
227
+ ...state,
228
+ selectedIndex: Math.min(state.results.length - 1, state.selectedIndex + 1),
229
+ };
230
+ }
231
+ /**
232
+ * Get selected result
233
+ */
234
+ export function getSelected(state) {
235
+ if (state.selectedIndex < 0 || state.selectedIndex >= state.results.length) {
236
+ return null;
237
+ }
238
+ return state.results[state.selectedIndex];
239
+ }
240
+ //# sourceMappingURL=fuzzy-search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fuzzy-search.js","sourceRoot":"","sources":["../src/fuzzy-search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Calliope CLI - Hooks System
3
+ *
4
+ * Pre/post hooks for tool execution, file changes, and events.
5
+ */
6
+ export type HookEvent = 'pre-tool' | 'post-tool' | 'pre-shell' | 'post-shell' | 'pre-write' | 'post-write' | 'pre-read' | 'session-start' | 'session-end' | 'error' | 'message';
7
+ export interface Hook {
8
+ id: string;
9
+ event: HookEvent;
10
+ name: string;
11
+ command: string;
12
+ enabled: boolean;
13
+ async: boolean;
14
+ timeout?: number;
15
+ condition?: string;
16
+ }
17
+ export interface HookContext {
18
+ event: HookEvent;
19
+ tool?: string;
20
+ toolArgs?: Record<string, unknown>;
21
+ toolResult?: string;
22
+ filePath?: string;
23
+ fileContent?: string;
24
+ command?: string;
25
+ exitCode?: number;
26
+ error?: string;
27
+ message?: string;
28
+ messageRole?: string;
29
+ }
30
+ export interface HookResult {
31
+ success: boolean;
32
+ output?: string;
33
+ error?: string;
34
+ blocked?: boolean;
35
+ }
36
+ /**
37
+ * Load hooks configuration
38
+ */
39
+ export declare function loadHooks(): Hook[];
40
+ /**
41
+ * Save hooks configuration
42
+ */
43
+ export declare function saveHooks(hooks: Hook[]): void;
44
+ /**
45
+ * Add a new hook
46
+ */
47
+ export declare function addHook(hook: Omit<Hook, 'id'>): Hook;
48
+ /**
49
+ * Remove a hook
50
+ */
51
+ export declare function removeHook(id: string): boolean;
52
+ /**
53
+ * Enable/disable a hook
54
+ */
55
+ export declare function toggleHook(id: string, enabled: boolean): boolean;
56
+ /**
57
+ * Get hooks for a specific event
58
+ */
59
+ export declare function getHooksForEvent(event: HookEvent): Hook[];
60
+ /**
61
+ * Execute hooks for an event
62
+ */
63
+ export declare function executeHooks(event: HookEvent, context: Partial<HookContext>): Promise<HookResult[]>;
64
+ /**
65
+ * Check if any hooks would block an operation
66
+ */
67
+ export declare function checkHooksAllow(event: HookEvent, context: Partial<HookContext>): Promise<{
68
+ allowed: boolean;
69
+ reason?: string;
70
+ }>;
71
+ /**
72
+ * Initialize default hooks
73
+ */
74
+ export declare function initDefaultHooks(): void;
75
+ /**
76
+ * List all hooks formatted for display
77
+ */
78
+ export declare function listHooksFormatted(): string;
79
+ //# sourceMappingURL=hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH,MAAM,MAAM,SAAS,GACjB,UAAU,GACV,WAAW,GACX,WAAW,GACX,YAAY,GACZ,WAAW,GACX,YAAY,GACZ,UAAU,GACV,eAAe,GACf,aAAa,GACb,OAAO,GACP,SAAS,CAAC;AAEd,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAeD;;GAEG;AACH,wBAAgB,SAAS,IAAI,IAAI,EAAE,CAUlC;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,CAG7C;AAMD;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,IAAI,CASpD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAO9C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAOhE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,EAAE,CAEzD;AAiFD;;GAEG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,GAC5B,OAAO,CAAC,UAAU,EAAE,CAAC,CAiDvB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,GAC5B,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAahD;AAMD;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAmCvC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAa3C"}
package/dist/hooks.js ADDED
@@ -0,0 +1,271 @@
1
+ /**
2
+ * Calliope CLI - Hooks System
3
+ *
4
+ * Pre/post hooks for tool execution, file changes, and events.
5
+ */
6
+ import * as fs from 'fs';
7
+ import * as path from 'path';
8
+ import * as os from 'os';
9
+ import { spawn } from 'child_process';
10
+ // ============================================================================
11
+ // Configuration
12
+ // ============================================================================
13
+ const HOOKS_DIR = path.join(os.homedir(), '.calliope-cli', 'hooks');
14
+ const HOOKS_FILE = path.join(HOOKS_DIR, 'hooks.json');
15
+ function ensureHooksDir() {
16
+ if (!fs.existsSync(HOOKS_DIR)) {
17
+ fs.mkdirSync(HOOKS_DIR, { recursive: true });
18
+ }
19
+ }
20
+ /**
21
+ * Load hooks configuration
22
+ */
23
+ export function loadHooks() {
24
+ ensureHooksDir();
25
+ if (!fs.existsSync(HOOKS_FILE)) {
26
+ return [];
27
+ }
28
+ try {
29
+ return JSON.parse(fs.readFileSync(HOOKS_FILE, 'utf-8'));
30
+ }
31
+ catch {
32
+ return [];
33
+ }
34
+ }
35
+ /**
36
+ * Save hooks configuration
37
+ */
38
+ export function saveHooks(hooks) {
39
+ ensureHooksDir();
40
+ fs.writeFileSync(HOOKS_FILE, JSON.stringify(hooks, null, 2));
41
+ }
42
+ // ============================================================================
43
+ // Hook Management
44
+ // ============================================================================
45
+ /**
46
+ * Add a new hook
47
+ */
48
+ export function addHook(hook) {
49
+ const hooks = loadHooks();
50
+ const newHook = {
51
+ ...hook,
52
+ id: `hook_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`,
53
+ };
54
+ hooks.push(newHook);
55
+ saveHooks(hooks);
56
+ return newHook;
57
+ }
58
+ /**
59
+ * Remove a hook
60
+ */
61
+ export function removeHook(id) {
62
+ const hooks = loadHooks();
63
+ const index = hooks.findIndex(h => h.id === id);
64
+ if (index === -1)
65
+ return false;
66
+ hooks.splice(index, 1);
67
+ saveHooks(hooks);
68
+ return true;
69
+ }
70
+ /**
71
+ * Enable/disable a hook
72
+ */
73
+ export function toggleHook(id, enabled) {
74
+ const hooks = loadHooks();
75
+ const hook = hooks.find(h => h.id === id);
76
+ if (!hook)
77
+ return false;
78
+ hook.enabled = enabled;
79
+ saveHooks(hooks);
80
+ return true;
81
+ }
82
+ /**
83
+ * Get hooks for a specific event
84
+ */
85
+ export function getHooksForEvent(event) {
86
+ return loadHooks().filter(h => h.enabled && h.event === event);
87
+ }
88
+ // ============================================================================
89
+ // Hook Execution
90
+ // ============================================================================
91
+ /**
92
+ * Run a hook command
93
+ */
94
+ async function runHookCommand(hook, context) {
95
+ return new Promise((resolve) => {
96
+ const timeout = hook.timeout || 10000;
97
+ // Build environment with context
98
+ const env = {
99
+ ...process.env,
100
+ CALLIOPE_EVENT: context.event,
101
+ CALLIOPE_TOOL: context.tool || '',
102
+ CALLIOPE_FILE: context.filePath || '',
103
+ CALLIOPE_COMMAND: context.command || '',
104
+ CALLIOPE_MESSAGE: context.message || '',
105
+ CALLIOPE_ERROR: context.error || '',
106
+ };
107
+ // For tool args, serialize to JSON
108
+ if (context.toolArgs) {
109
+ env.CALLIOPE_TOOL_ARGS = JSON.stringify(context.toolArgs);
110
+ }
111
+ const proc = spawn('sh', ['-c', hook.command], {
112
+ env,
113
+ stdio: ['pipe', 'pipe', 'pipe'],
114
+ timeout,
115
+ });
116
+ let stdout = '';
117
+ let stderr = '';
118
+ proc.stdout?.on('data', (data) => {
119
+ stdout += data.toString();
120
+ });
121
+ proc.stderr?.on('data', (data) => {
122
+ stderr += data.toString();
123
+ });
124
+ const timer = setTimeout(() => {
125
+ proc.kill();
126
+ resolve({
127
+ success: false,
128
+ error: 'Hook timed out',
129
+ });
130
+ }, timeout);
131
+ proc.on('close', (code) => {
132
+ clearTimeout(timer);
133
+ // Exit code 42 means "block the operation"
134
+ const blocked = code === 42;
135
+ resolve({
136
+ success: code === 0 || blocked,
137
+ output: stdout.trim(),
138
+ error: stderr.trim() || undefined,
139
+ blocked,
140
+ });
141
+ });
142
+ proc.on('error', (err) => {
143
+ clearTimeout(timer);
144
+ resolve({
145
+ success: false,
146
+ error: err.message,
147
+ });
148
+ });
149
+ });
150
+ }
151
+ /**
152
+ * Execute hooks for an event
153
+ */
154
+ export async function executeHooks(event, context) {
155
+ const hooks = getHooksForEvent(event);
156
+ const results = [];
157
+ const fullContext = { event, ...context };
158
+ for (const hook of hooks) {
159
+ // Check condition if specified
160
+ if (hook.condition) {
161
+ let matches = false;
162
+ // Tool name condition
163
+ if (context.tool && hook.condition.startsWith('tool:')) {
164
+ const toolPattern = hook.condition.slice(5);
165
+ matches = context.tool.includes(toolPattern);
166
+ }
167
+ // File pattern condition
168
+ else if (context.filePath && hook.condition.startsWith('file:')) {
169
+ const filePattern = hook.condition.slice(5);
170
+ matches = context.filePath.includes(filePattern);
171
+ }
172
+ // Command pattern condition
173
+ else if (context.command && hook.condition.startsWith('cmd:')) {
174
+ const cmdPattern = hook.condition.slice(4);
175
+ matches = context.command.includes(cmdPattern);
176
+ }
177
+ // Default: treat as general pattern
178
+ else {
179
+ matches = JSON.stringify(context).includes(hook.condition);
180
+ }
181
+ if (!matches)
182
+ continue;
183
+ }
184
+ if (hook.async) {
185
+ // Fire and forget
186
+ runHookCommand(hook, fullContext).catch(() => { });
187
+ results.push({ success: true });
188
+ }
189
+ else {
190
+ const result = await runHookCommand(hook, fullContext);
191
+ results.push(result);
192
+ // If hook blocks, stop executing more hooks
193
+ if (result.blocked) {
194
+ break;
195
+ }
196
+ }
197
+ }
198
+ return results;
199
+ }
200
+ /**
201
+ * Check if any hooks would block an operation
202
+ */
203
+ export async function checkHooksAllow(event, context) {
204
+ const results = await executeHooks(event, context);
205
+ for (const result of results) {
206
+ if (result.blocked) {
207
+ return {
208
+ allowed: false,
209
+ reason: result.output || result.error || 'Blocked by hook',
210
+ };
211
+ }
212
+ }
213
+ return { allowed: true };
214
+ }
215
+ // ============================================================================
216
+ // Built-in Hooks
217
+ // ============================================================================
218
+ /**
219
+ * Initialize default hooks
220
+ */
221
+ export function initDefaultHooks() {
222
+ const hooks = loadHooks();
223
+ if (hooks.length > 0)
224
+ return;
225
+ // Add some example hooks (disabled by default)
226
+ const defaults = [
227
+ {
228
+ event: 'post-shell',
229
+ name: 'Log dangerous commands',
230
+ command: 'echo "$CALLIOPE_COMMAND" >> ~/.calliope-cli/hooks/command-log.txt',
231
+ enabled: false,
232
+ async: true,
233
+ condition: 'cmd:rm -rf',
234
+ },
235
+ {
236
+ event: 'post-write',
237
+ name: 'Format on save',
238
+ command: 'prettier --write "$CALLIOPE_FILE" 2>/dev/null || true',
239
+ enabled: false,
240
+ async: true,
241
+ condition: 'file:.ts',
242
+ },
243
+ {
244
+ event: 'pre-shell',
245
+ name: 'Block sudo',
246
+ command: 'if echo "$CALLIOPE_COMMAND" | grep -q "^sudo"; then exit 42; fi',
247
+ enabled: false,
248
+ async: false,
249
+ condition: 'cmd:sudo',
250
+ },
251
+ ];
252
+ for (const hook of defaults) {
253
+ addHook(hook);
254
+ }
255
+ }
256
+ /**
257
+ * List all hooks formatted for display
258
+ */
259
+ export function listHooksFormatted() {
260
+ const hooks = loadHooks();
261
+ if (hooks.length === 0) {
262
+ return 'No hooks configured.';
263
+ }
264
+ const lines = hooks.map(h => {
265
+ const status = h.enabled ? '✓' : '✗';
266
+ const async = h.async ? '(async)' : '';
267
+ return `${status} [${h.event}] ${h.name} ${async}\n ${h.command}`;
268
+ });
269
+ return lines.join('\n\n');
270
+ }
271
+ //# 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,57 @@
1
+ /**
2
+ * Calliope CLI - Keyboard Shortcuts
3
+ *
4
+ * Vim-like keybindings and keyboard shortcuts.
5
+ */
6
+ export type KeyAction = 'submit' | 'cancel' | 'clear' | 'historyUp' | 'historyDown' | 'complete' | 'completeNext' | 'completePrev' | 'cursorLeft' | 'cursorRight' | 'cursorWordLeft' | 'cursorWordRight' | 'cursorHome' | 'cursorEnd' | 'deleteChar' | 'deleteWord' | 'deleteLine' | 'deleteToEnd' | 'paste' | 'copy' | 'undo' | 'redo' | 'newline' | 'escape' | 'toggleVimMode' | 'vimNormal' | 'vimInsert' | 'vimAppend' | 'vimDelete' | 'vimChange' | 'vimYank' | 'none';
7
+ export interface KeyBinding {
8
+ key: string;
9
+ ctrl?: boolean;
10
+ alt?: boolean;
11
+ shift?: boolean;
12
+ action: KeyAction;
13
+ description?: string;
14
+ }
15
+ export type VimMode = 'normal' | 'insert' | 'visual';
16
+ export interface KeyboardState {
17
+ vimMode: VimMode;
18
+ vimEnabled: boolean;
19
+ pendingKeys: string;
20
+ lastAction?: KeyAction;
21
+ }
22
+ /**
23
+ * Check if key event matches a binding
24
+ */
25
+ export declare function matchBinding(key: string, ctrl: boolean, alt: boolean, shift: boolean, bindings: KeyBinding[]): KeyBinding | null;
26
+ /**
27
+ * Get action for key event
28
+ */
29
+ export declare function getKeyAction(key: string, ctrl: boolean, alt: boolean, shift: boolean, state: KeyboardState): KeyAction;
30
+ /**
31
+ * Create initial keyboard state
32
+ */
33
+ export declare function createKeyboardState(vimEnabled?: boolean): KeyboardState;
34
+ /**
35
+ * Update state after action
36
+ */
37
+ export declare function updateState(state: KeyboardState, action: KeyAction): KeyboardState;
38
+ /**
39
+ * Toggle vim mode
40
+ */
41
+ export declare function toggleVimMode(state: KeyboardState): KeyboardState;
42
+ /**
43
+ * Process vim command key sequence
44
+ */
45
+ export declare function processVimCommand(state: KeyboardState, key: string): {
46
+ state: KeyboardState;
47
+ actions: KeyAction[];
48
+ };
49
+ /**
50
+ * Format keybinding for display
51
+ */
52
+ export declare function formatBinding(binding: KeyBinding): string;
53
+ /**
54
+ * Get all keybindings for display
55
+ */
56
+ export declare function getBindingsHelp(vimEnabled: boolean): string;
57
+ //# sourceMappingURL=keyboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../src/keyboard.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,MAAM,MAAM,SAAS,GACjB,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,WAAW,GACX,aAAa,GACb,UAAU,GACV,cAAc,GACd,cAAc,GACd,YAAY,GACZ,aAAa,GACb,gBAAgB,GAChB,iBAAiB,GACjB,YAAY,GACZ,WAAW,GACX,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,aAAa,GACb,OAAO,GACP,MAAM,GACN,MAAM,GACN,MAAM,GACN,SAAS,GACT,QAAQ,GACR,eAAe,GACf,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,SAAS,GACT,MAAM,CAAC;AAEX,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,SAAS,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAErD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,SAAS,CAAC;CACxB;AA+FD;;GAEG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,OAAO,EACb,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,UAAU,EAAE,GACrB,UAAU,GAAG,IAAI,CAUnB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,OAAO,EACb,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,aAAa,GACnB,SAAS,CAiBX;AAMD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,UAAQ,GAAG,aAAa,CAMrE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,GAAG,aAAa,CAiBlF;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,aAAa,CAOjE;AAMD;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,aAAa,EACpB,GAAG,EAAE,MAAM,GACV;IAAE,KAAK,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,SAAS,EAAE,CAAA;CAAE,CAkDhD;AAMD;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAOzD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,OAAO,GAAG,MAAM,CAqC3D"}