praisonai 1.2.2 → 1.2.3

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 (160) hide show
  1. package/dist/agent/simple.js +1 -1
  2. package/dist/cli/commands/auto.d.ts +12 -0
  3. package/dist/cli/commands/auto.js +109 -0
  4. package/dist/cli/commands/autonomy.d.ts +5 -0
  5. package/dist/cli/commands/autonomy.js +152 -0
  6. package/dist/cli/commands/cache.d.ts +9 -0
  7. package/dist/cli/commands/cache.js +143 -0
  8. package/dist/cli/commands/chat.d.ts +14 -0
  9. package/dist/cli/commands/chat.js +127 -0
  10. package/dist/cli/commands/checkpoints.d.ts +5 -0
  11. package/dist/cli/commands/checkpoints.js +236 -0
  12. package/dist/cli/commands/context.d.ts +11 -0
  13. package/dist/cli/commands/context.js +182 -0
  14. package/dist/cli/commands/cost.d.ts +5 -0
  15. package/dist/cli/commands/cost.js +146 -0
  16. package/dist/cli/commands/db.d.ts +9 -0
  17. package/dist/cli/commands/db.js +149 -0
  18. package/dist/cli/commands/eval.d.ts +17 -0
  19. package/dist/cli/commands/eval.js +247 -0
  20. package/dist/cli/commands/external-agents.d.ts +5 -0
  21. package/dist/cli/commands/external-agents.js +169 -0
  22. package/dist/cli/commands/fast-context.d.ts +5 -0
  23. package/dist/cli/commands/fast-context.js +126 -0
  24. package/dist/cli/commands/flow.d.ts +5 -0
  25. package/dist/cli/commands/flow.js +141 -0
  26. package/dist/cli/commands/git.d.ts +5 -0
  27. package/dist/cli/commands/git.js +178 -0
  28. package/dist/cli/commands/graph-rag.d.ts +9 -0
  29. package/dist/cli/commands/graph-rag.js +131 -0
  30. package/dist/cli/commands/guardrail.d.ts +11 -0
  31. package/dist/cli/commands/guardrail.js +156 -0
  32. package/dist/cli/commands/handoff.d.ts +9 -0
  33. package/dist/cli/commands/handoff.js +133 -0
  34. package/dist/cli/commands/help.d.ts +8 -0
  35. package/dist/cli/commands/help.js +167 -0
  36. package/dist/cli/commands/image.d.ts +13 -0
  37. package/dist/cli/commands/image.js +192 -0
  38. package/dist/cli/commands/interactive.d.ts +6 -0
  39. package/dist/cli/commands/interactive.js +79 -0
  40. package/dist/cli/commands/jobs.d.ts +5 -0
  41. package/dist/cli/commands/jobs.js +282 -0
  42. package/dist/cli/commands/knowledge.d.ts +9 -0
  43. package/dist/cli/commands/knowledge.js +226 -0
  44. package/dist/cli/commands/mcp.d.ts +9 -0
  45. package/dist/cli/commands/mcp.js +243 -0
  46. package/dist/cli/commands/memory.d.ts +10 -0
  47. package/dist/cli/commands/memory.js +198 -0
  48. package/dist/cli/commands/n8n.d.ts +5 -0
  49. package/dist/cli/commands/n8n.js +137 -0
  50. package/dist/cli/commands/observability.d.ts +9 -0
  51. package/dist/cli/commands/observability.js +145 -0
  52. package/dist/cli/commands/planning.d.ts +9 -0
  53. package/dist/cli/commands/planning.js +167 -0
  54. package/dist/cli/commands/prompt-expand.d.ts +11 -0
  55. package/dist/cli/commands/prompt-expand.js +100 -0
  56. package/dist/cli/commands/providers.d.ts +9 -0
  57. package/dist/cli/commands/providers.js +98 -0
  58. package/dist/cli/commands/query-rewrite.d.ts +12 -0
  59. package/dist/cli/commands/query-rewrite.js +102 -0
  60. package/dist/cli/commands/repo-map.d.ts +5 -0
  61. package/dist/cli/commands/repo-map.js +151 -0
  62. package/dist/cli/commands/reranker.d.ts +10 -0
  63. package/dist/cli/commands/reranker.js +144 -0
  64. package/dist/cli/commands/research.d.ts +12 -0
  65. package/dist/cli/commands/research.js +108 -0
  66. package/dist/cli/commands/router.d.ts +11 -0
  67. package/dist/cli/commands/router.js +142 -0
  68. package/dist/cli/commands/run.d.ts +14 -0
  69. package/dist/cli/commands/run.js +111 -0
  70. package/dist/cli/commands/sandbox.d.ts +5 -0
  71. package/dist/cli/commands/sandbox.js +135 -0
  72. package/dist/cli/commands/scheduler.d.ts +5 -0
  73. package/dist/cli/commands/scheduler.js +260 -0
  74. package/dist/cli/commands/session.d.ts +9 -0
  75. package/dist/cli/commands/session.js +238 -0
  76. package/dist/cli/commands/skills.d.ts +9 -0
  77. package/dist/cli/commands/skills.js +256 -0
  78. package/dist/cli/commands/telemetry.d.ts +9 -0
  79. package/dist/cli/commands/telemetry.js +146 -0
  80. package/dist/cli/commands/tools.d.ts +9 -0
  81. package/dist/cli/commands/tools.js +172 -0
  82. package/dist/cli/commands/vector.d.ts +10 -0
  83. package/dist/cli/commands/vector.js +171 -0
  84. package/dist/cli/commands/version.d.ts +8 -0
  85. package/dist/cli/commands/version.js +68 -0
  86. package/dist/cli/commands/voice.d.ts +10 -0
  87. package/dist/cli/commands/voice.js +162 -0
  88. package/dist/cli/commands/workflow.d.ts +13 -0
  89. package/dist/cli/commands/workflow.js +184 -0
  90. package/dist/cli/config/index.d.ts +6 -0
  91. package/dist/cli/config/index.js +22 -0
  92. package/dist/cli/config/load.d.ts +20 -0
  93. package/dist/cli/config/load.js +229 -0
  94. package/dist/cli/config/resolve.d.ts +28 -0
  95. package/dist/cli/config/resolve.js +70 -0
  96. package/dist/cli/config/schema.d.ts +15 -0
  97. package/dist/cli/config/schema.js +65 -0
  98. package/dist/cli/features/autonomy-mode.d.ts +98 -0
  99. package/dist/cli/features/autonomy-mode.js +266 -0
  100. package/dist/cli/features/background-jobs.d.ts +155 -0
  101. package/dist/cli/features/background-jobs.js +416 -0
  102. package/dist/cli/features/checkpoints.d.ts +126 -0
  103. package/dist/cli/features/checkpoints.js +288 -0
  104. package/dist/cli/features/cost-tracker.d.ts +101 -0
  105. package/dist/cli/features/cost-tracker.js +212 -0
  106. package/dist/cli/features/external-agents.d.ts +115 -0
  107. package/dist/cli/features/external-agents.js +294 -0
  108. package/dist/cli/features/fast-context.d.ts +126 -0
  109. package/dist/cli/features/fast-context.js +310 -0
  110. package/dist/cli/features/flow-display.d.ts +100 -0
  111. package/dist/cli/features/flow-display.js +254 -0
  112. package/dist/cli/features/git-integration.d.ts +138 -0
  113. package/dist/cli/features/git-integration.js +374 -0
  114. package/dist/cli/features/index.d.ts +17 -0
  115. package/dist/cli/features/index.js +102 -0
  116. package/dist/cli/features/interactive-tui.d.ts +114 -0
  117. package/dist/cli/features/interactive-tui.js +326 -0
  118. package/dist/cli/features/n8n-integration.d.ts +108 -0
  119. package/dist/cli/features/n8n-integration.js +296 -0
  120. package/dist/cli/features/repo-map.d.ts +101 -0
  121. package/dist/cli/features/repo-map.js +350 -0
  122. package/dist/cli/features/sandbox-executor.d.ts +89 -0
  123. package/dist/cli/features/sandbox-executor.js +314 -0
  124. package/dist/cli/features/scheduler.d.ts +111 -0
  125. package/dist/cli/features/scheduler.js +298 -0
  126. package/dist/cli/features/slash-commands.d.ts +77 -0
  127. package/dist/cli/features/slash-commands.js +316 -0
  128. package/dist/cli/index.d.ts +19 -15
  129. package/dist/cli/index.js +163 -123
  130. package/dist/cli/output/errors.d.ts +32 -0
  131. package/dist/cli/output/errors.js +72 -0
  132. package/dist/cli/output/index.d.ts +6 -0
  133. package/dist/cli/output/index.js +22 -0
  134. package/dist/cli/output/json.d.ts +17 -0
  135. package/dist/cli/output/json.js +54 -0
  136. package/dist/cli/output/pretty.d.ts +21 -0
  137. package/dist/cli/output/pretty.js +106 -0
  138. package/dist/cli/runtime/env.d.ts +12 -0
  139. package/dist/cli/runtime/env.js +49 -0
  140. package/dist/cli/runtime/exit.d.ts +11 -0
  141. package/dist/cli/runtime/exit.js +49 -0
  142. package/dist/cli/runtime/index.d.ts +6 -0
  143. package/dist/cli/runtime/index.js +22 -0
  144. package/dist/cli/runtime/lazy.d.ts +18 -0
  145. package/dist/cli/runtime/lazy.js +85 -0
  146. package/dist/cli/spec/cli-spec.d.ts +87 -0
  147. package/dist/cli/spec/cli-spec.js +478 -0
  148. package/dist/cli/spec/index.d.ts +4 -0
  149. package/dist/cli/spec/index.js +20 -0
  150. package/dist/index.d.ts +4 -1
  151. package/dist/index.js +100 -7
  152. package/dist/memory/auto-memory.d.ts +136 -0
  153. package/dist/memory/auto-memory.js +301 -0
  154. package/dist/memory/file-memory.d.ts +88 -0
  155. package/dist/memory/file-memory.js +287 -0
  156. package/dist/memory/index.d.ts +2 -0
  157. package/dist/memory/index.js +11 -1
  158. package/dist/workflows/loop.d.ts +0 -0
  159. package/dist/workflows/loop.js +1 -0
  160. package/package.json +1 -1
@@ -0,0 +1,298 @@
1
+ "use strict";
2
+ /**
3
+ * Agent Scheduler - Cron-like scheduling for agent tasks
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.cronExpressions = exports.Scheduler = void 0;
7
+ exports.createScheduler = createScheduler;
8
+ /**
9
+ * Parse cron expression (simplified: minute hour day month weekday)
10
+ */
11
+ function parseCron(cron) {
12
+ const parts = cron.split(/\s+/);
13
+ if (parts.length !== 5) {
14
+ throw new Error('Invalid cron expression. Expected: minute hour day month weekday');
15
+ }
16
+ const parseField = (field, min, max) => {
17
+ if (field === '*') {
18
+ return Array.from({ length: max - min + 1 }, (_, i) => min + i);
19
+ }
20
+ if (field.includes('/')) {
21
+ const [, step] = field.split('/');
22
+ const stepNum = parseInt(step);
23
+ return Array.from({ length: Math.ceil((max - min + 1) / stepNum) }, (_, i) => min + i * stepNum);
24
+ }
25
+ if (field.includes(',')) {
26
+ return field.split(',').map(n => parseInt(n));
27
+ }
28
+ if (field.includes('-')) {
29
+ const [start, end] = field.split('-').map(n => parseInt(n));
30
+ return Array.from({ length: end - start + 1 }, (_, i) => start + i);
31
+ }
32
+ return [parseInt(field)];
33
+ };
34
+ return {
35
+ minute: parseField(parts[0], 0, 59),
36
+ hour: parseField(parts[1], 0, 23),
37
+ day: parseField(parts[2], 1, 31),
38
+ month: parseField(parts[3], 1, 12),
39
+ weekday: parseField(parts[4], 0, 6)
40
+ };
41
+ }
42
+ /**
43
+ * Get next run time from cron expression
44
+ */
45
+ function getNextCronRun(cron, from = new Date()) {
46
+ const parsed = parseCron(cron);
47
+ const next = new Date(from);
48
+ next.setSeconds(0);
49
+ next.setMilliseconds(0);
50
+ next.setMinutes(next.getMinutes() + 1);
51
+ for (let i = 0; i < 366 * 24 * 60; i++) { // Max 1 year search
52
+ const minute = next.getMinutes();
53
+ const hour = next.getHours();
54
+ const day = next.getDate();
55
+ const month = next.getMonth() + 1;
56
+ const weekday = next.getDay();
57
+ if (parsed.minute.includes(minute) &&
58
+ parsed.hour.includes(hour) &&
59
+ parsed.day.includes(day) &&
60
+ parsed.month.includes(month) &&
61
+ parsed.weekday.includes(weekday)) {
62
+ return next;
63
+ }
64
+ next.setMinutes(next.getMinutes() + 1);
65
+ }
66
+ throw new Error('Could not find next run time');
67
+ }
68
+ /**
69
+ * Scheduler class
70
+ */
71
+ class Scheduler {
72
+ constructor() {
73
+ this.tasks = new Map();
74
+ this.running = false;
75
+ this.stats = {
76
+ totalTasks: 0,
77
+ activeTasks: 0,
78
+ totalRuns: 0,
79
+ errors: 0
80
+ };
81
+ }
82
+ /**
83
+ * Add a scheduled task
84
+ */
85
+ add(config) {
86
+ const id = config.id || `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
87
+ const task = {
88
+ id,
89
+ name: config.name,
90
+ cron: config.cron,
91
+ interval: config.interval,
92
+ enabled: config.enabled ?? true,
93
+ runCount: 0,
94
+ maxRuns: config.maxRuns,
95
+ status: 'idle'
96
+ };
97
+ if (config.cron) {
98
+ task.nextRun = getNextCronRun(config.cron);
99
+ }
100
+ else if (config.interval) {
101
+ task.nextRun = new Date(Date.now() + config.interval);
102
+ }
103
+ this.tasks.set(id, { config, task });
104
+ this.stats.totalTasks++;
105
+ if (this.running && task.enabled) {
106
+ this.scheduleTask(id);
107
+ }
108
+ return id;
109
+ }
110
+ /**
111
+ * Remove a task
112
+ */
113
+ remove(id) {
114
+ const entry = this.tasks.get(id);
115
+ if (!entry)
116
+ return false;
117
+ if (entry.timer) {
118
+ clearTimeout(entry.timer);
119
+ }
120
+ this.tasks.delete(id);
121
+ this.stats.totalTasks--;
122
+ return true;
123
+ }
124
+ /**
125
+ * Enable a task
126
+ */
127
+ enable(id) {
128
+ const entry = this.tasks.get(id);
129
+ if (!entry)
130
+ return false;
131
+ entry.task.enabled = true;
132
+ if (this.running) {
133
+ this.scheduleTask(id);
134
+ }
135
+ return true;
136
+ }
137
+ /**
138
+ * Disable a task
139
+ */
140
+ disable(id) {
141
+ const entry = this.tasks.get(id);
142
+ if (!entry)
143
+ return false;
144
+ entry.task.enabled = false;
145
+ if (entry.timer) {
146
+ clearTimeout(entry.timer);
147
+ entry.timer = undefined;
148
+ }
149
+ return true;
150
+ }
151
+ /**
152
+ * Start the scheduler
153
+ */
154
+ start() {
155
+ if (this.running)
156
+ return;
157
+ this.running = true;
158
+ for (const [id, entry] of this.tasks) {
159
+ if (entry.task.enabled) {
160
+ this.scheduleTask(id);
161
+ }
162
+ }
163
+ }
164
+ /**
165
+ * Stop the scheduler
166
+ */
167
+ stop() {
168
+ this.running = false;
169
+ for (const entry of this.tasks.values()) {
170
+ if (entry.timer) {
171
+ clearTimeout(entry.timer);
172
+ entry.timer = undefined;
173
+ }
174
+ }
175
+ }
176
+ /**
177
+ * Schedule a task's next run
178
+ */
179
+ scheduleTask(id) {
180
+ const entry = this.tasks.get(id);
181
+ if (!entry || !entry.task.enabled || !this.running)
182
+ return;
183
+ // Check if max runs reached
184
+ if (entry.task.maxRuns && entry.task.runCount >= entry.task.maxRuns) {
185
+ entry.task.status = 'completed';
186
+ return;
187
+ }
188
+ let delay;
189
+ if (entry.config.cron) {
190
+ const nextRun = getNextCronRun(entry.config.cron);
191
+ entry.task.nextRun = nextRun;
192
+ delay = nextRun.getTime() - Date.now();
193
+ }
194
+ else if (entry.config.interval) {
195
+ entry.task.nextRun = new Date(Date.now() + entry.config.interval);
196
+ delay = entry.config.interval;
197
+ }
198
+ else {
199
+ return;
200
+ }
201
+ entry.timer = setTimeout(() => this.runTask(id), delay);
202
+ this.stats.activeTasks = Array.from(this.tasks.values()).filter(e => e.timer).length;
203
+ }
204
+ /**
205
+ * Run a task
206
+ */
207
+ async runTask(id) {
208
+ const entry = this.tasks.get(id);
209
+ if (!entry)
210
+ return;
211
+ entry.task.status = 'running';
212
+ entry.task.lastRun = new Date();
213
+ try {
214
+ const result = await entry.config.task();
215
+ entry.task.runCount++;
216
+ entry.task.status = 'idle';
217
+ entry.task.lastError = undefined;
218
+ this.stats.totalRuns++;
219
+ entry.config.onComplete?.(result);
220
+ }
221
+ catch (error) {
222
+ entry.task.status = 'error';
223
+ entry.task.lastError = error.message;
224
+ this.stats.errors++;
225
+ entry.config.onError?.(error);
226
+ }
227
+ // Schedule next run
228
+ this.scheduleTask(id);
229
+ }
230
+ /**
231
+ * Run a task immediately
232
+ */
233
+ async runNow(id) {
234
+ const entry = this.tasks.get(id);
235
+ if (!entry)
236
+ throw new Error(`Task ${id} not found`);
237
+ entry.task.status = 'running';
238
+ entry.task.lastRun = new Date();
239
+ try {
240
+ const result = await entry.config.task();
241
+ entry.task.runCount++;
242
+ entry.task.status = 'idle';
243
+ this.stats.totalRuns++;
244
+ return result;
245
+ }
246
+ catch (error) {
247
+ entry.task.status = 'error';
248
+ entry.task.lastError = error.message;
249
+ this.stats.errors++;
250
+ throw error;
251
+ }
252
+ }
253
+ /**
254
+ * Get task info
255
+ */
256
+ getTask(id) {
257
+ return this.tasks.get(id)?.task;
258
+ }
259
+ /**
260
+ * Get all tasks
261
+ */
262
+ getAllTasks() {
263
+ return Array.from(this.tasks.values()).map(e => e.task);
264
+ }
265
+ /**
266
+ * Get scheduler stats
267
+ */
268
+ getStats() {
269
+ return { ...this.stats };
270
+ }
271
+ /**
272
+ * Check if scheduler is running
273
+ */
274
+ isRunning() {
275
+ return this.running;
276
+ }
277
+ }
278
+ exports.Scheduler = Scheduler;
279
+ /**
280
+ * Create a scheduler instance
281
+ */
282
+ function createScheduler() {
283
+ return new Scheduler();
284
+ }
285
+ /**
286
+ * Helper to create common cron expressions
287
+ */
288
+ exports.cronExpressions = {
289
+ everyMinute: '* * * * *',
290
+ every5Minutes: '*/5 * * * *',
291
+ every15Minutes: '*/15 * * * *',
292
+ everyHour: '0 * * * *',
293
+ everyDay: '0 0 * * *',
294
+ everyWeek: '0 0 * * 0',
295
+ everyMonth: '0 0 1 * *',
296
+ weekdays: '0 9 * * 1-5',
297
+ weekends: '0 10 * * 0,6'
298
+ };
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Slash Commands - Interactive command system for CLI
3
+ * Supports /help, /cost, /clear, /model, /tokens, /plan, /undo, /diff, /commit, /exit, /settings, /map
4
+ */
5
+ export interface SlashCommand {
6
+ name: string;
7
+ aliases?: string[];
8
+ description: string;
9
+ usage?: string;
10
+ execute: (args: string[], context: SlashCommandContext) => Promise<SlashCommandResult>;
11
+ }
12
+ export interface SlashCommandContext {
13
+ sessionId?: string;
14
+ model?: string;
15
+ tokenCount?: number;
16
+ costTracker?: CostTracker;
17
+ history?: string[];
18
+ settings?: Record<string, any>;
19
+ onOutput?: (message: string) => void;
20
+ }
21
+ export interface SlashCommandResult {
22
+ success: boolean;
23
+ message?: string;
24
+ data?: any;
25
+ shouldExit?: boolean;
26
+ }
27
+ export interface CostTracker {
28
+ totalTokens: number;
29
+ totalCost: number;
30
+ requests: number;
31
+ addUsage(model: string, inputTokens: number, outputTokens: number, latencyMs?: number): any;
32
+ reset(): void;
33
+ getSummary(): string;
34
+ }
35
+ /**
36
+ * Slash Command Registry
37
+ */
38
+ declare class SlashCommandRegistry {
39
+ private commands;
40
+ private aliases;
41
+ constructor();
42
+ register(command: SlashCommand): void;
43
+ get(name: string): SlashCommand | undefined;
44
+ getAll(): SlashCommand[];
45
+ has(name: string): boolean;
46
+ }
47
+ export declare function getRegistry(): SlashCommandRegistry;
48
+ export declare function registerCommand(command: SlashCommand): void;
49
+ /**
50
+ * Parse slash command from input
51
+ */
52
+ export declare function parseSlashCommand(input: string): {
53
+ command: string;
54
+ args: string[];
55
+ } | null;
56
+ /**
57
+ * Execute a slash command
58
+ */
59
+ export declare function executeSlashCommand(input: string, context: SlashCommandContext): Promise<SlashCommandResult>;
60
+ /**
61
+ * Check if input is a slash command
62
+ */
63
+ export declare function isSlashCommand(input: string): boolean;
64
+ /**
65
+ * Slash Command Handler for CLI integration
66
+ */
67
+ export declare class SlashCommandHandler {
68
+ private context;
69
+ constructor(initialContext?: Partial<SlashCommandContext>);
70
+ handle(input: string): Promise<SlashCommandResult>;
71
+ isCommand(input: string): boolean;
72
+ getContext(): SlashCommandContext;
73
+ updateContext(updates: Partial<SlashCommandContext>): void;
74
+ registerCommand(command: SlashCommand): void;
75
+ }
76
+ export declare function createSlashCommandHandler(context?: Partial<SlashCommandContext>): SlashCommandHandler;
77
+ export {};
@@ -0,0 +1,316 @@
1
+ "use strict";
2
+ /**
3
+ * Slash Commands - Interactive command system for CLI
4
+ * Supports /help, /cost, /clear, /model, /tokens, /plan, /undo, /diff, /commit, /exit, /settings, /map
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.SlashCommandHandler = void 0;
8
+ exports.getRegistry = getRegistry;
9
+ exports.registerCommand = registerCommand;
10
+ exports.parseSlashCommand = parseSlashCommand;
11
+ exports.executeSlashCommand = executeSlashCommand;
12
+ exports.isSlashCommand = isSlashCommand;
13
+ exports.createSlashCommandHandler = createSlashCommandHandler;
14
+ /**
15
+ * Built-in slash commands
16
+ */
17
+ const BUILTIN_COMMANDS = [
18
+ {
19
+ name: 'help',
20
+ aliases: ['h', '?'],
21
+ description: 'Show available commands',
22
+ execute: async (_args, context) => {
23
+ const commands = getRegistry().getAll();
24
+ const lines = ['Available commands:', ''];
25
+ for (const cmd of commands) {
26
+ const aliases = cmd.aliases ? ` (${cmd.aliases.map(a => '/' + a).join(', ')})` : '';
27
+ lines.push(` /${cmd.name}${aliases} - ${cmd.description}`);
28
+ if (cmd.usage) {
29
+ lines.push(` Usage: ${cmd.usage}`);
30
+ }
31
+ }
32
+ context.onOutput?.(lines.join('\n'));
33
+ return { success: true, message: lines.join('\n') };
34
+ }
35
+ },
36
+ {
37
+ name: 'cost',
38
+ aliases: ['c'],
39
+ description: 'Show token usage and cost',
40
+ execute: async (_args, context) => {
41
+ if (!context.costTracker) {
42
+ return { success: false, message: 'Cost tracking not enabled' };
43
+ }
44
+ const summary = context.costTracker.getSummary();
45
+ context.onOutput?.(summary);
46
+ return { success: true, message: summary };
47
+ }
48
+ },
49
+ {
50
+ name: 'clear',
51
+ description: 'Clear conversation history',
52
+ execute: async (_args, context) => {
53
+ if (context.history) {
54
+ context.history.length = 0;
55
+ }
56
+ context.onOutput?.('Conversation cleared');
57
+ return { success: true, message: 'Conversation cleared' };
58
+ }
59
+ },
60
+ {
61
+ name: 'model',
62
+ aliases: ['m'],
63
+ description: 'Show or change the current model',
64
+ usage: '/model [model-name]',
65
+ execute: async (args, context) => {
66
+ if (args.length === 0) {
67
+ const msg = `Current model: ${context.model || 'default'}`;
68
+ context.onOutput?.(msg);
69
+ return { success: true, message: msg, data: { model: context.model } };
70
+ }
71
+ const newModel = args[0];
72
+ context.model = newModel;
73
+ const msg = `Model changed to: ${newModel}`;
74
+ context.onOutput?.(msg);
75
+ return { success: true, message: msg, data: { model: newModel } };
76
+ }
77
+ },
78
+ {
79
+ name: 'tokens',
80
+ aliases: ['t'],
81
+ description: 'Show token count for current session',
82
+ execute: async (_args, context) => {
83
+ const count = context.tokenCount || 0;
84
+ const msg = `Token count: ${count}`;
85
+ context.onOutput?.(msg);
86
+ return { success: true, message: msg, data: { tokens: count } };
87
+ }
88
+ },
89
+ {
90
+ name: 'plan',
91
+ aliases: ['p'],
92
+ description: 'Show or manage task plan',
93
+ usage: '/plan [add|remove|clear] [task]',
94
+ execute: async (args, context) => {
95
+ const plans = context.settings?.plans || [];
96
+ if (args.length === 0) {
97
+ if (plans.length === 0) {
98
+ context.onOutput?.('No plans set');
99
+ return { success: true, message: 'No plans set' };
100
+ }
101
+ const msg = ['Current plan:', ...plans.map((p, i) => ` ${i + 1}. ${p}`)].join('\n');
102
+ context.onOutput?.(msg);
103
+ return { success: true, message: msg, data: { plans } };
104
+ }
105
+ const action = args[0];
106
+ const task = args.slice(1).join(' ');
107
+ if (action === 'add' && task) {
108
+ plans.push(task);
109
+ context.settings = { ...context.settings, plans };
110
+ context.onOutput?.(`Added: ${task}`);
111
+ return { success: true, message: `Added: ${task}` };
112
+ }
113
+ if (action === 'remove' && task) {
114
+ const index = parseInt(task) - 1;
115
+ if (index >= 0 && index < plans.length) {
116
+ const removed = plans.splice(index, 1)[0];
117
+ context.settings = { ...context.settings, plans };
118
+ context.onOutput?.(`Removed: ${removed}`);
119
+ return { success: true, message: `Removed: ${removed}` };
120
+ }
121
+ }
122
+ if (action === 'clear') {
123
+ context.settings = { ...context.settings, plans: [] };
124
+ context.onOutput?.('Plans cleared');
125
+ return { success: true, message: 'Plans cleared' };
126
+ }
127
+ return { success: false, message: 'Invalid plan command' };
128
+ }
129
+ },
130
+ {
131
+ name: 'undo',
132
+ aliases: ['u'],
133
+ description: 'Undo last action',
134
+ execute: async (_args, context) => {
135
+ if (context.history && context.history.length > 0) {
136
+ const removed = context.history.pop();
137
+ context.onOutput?.(`Undone: ${removed?.substring(0, 50)}...`);
138
+ return { success: true, message: 'Last action undone' };
139
+ }
140
+ return { success: false, message: 'Nothing to undo' };
141
+ }
142
+ },
143
+ {
144
+ name: 'diff',
145
+ aliases: ['d'],
146
+ description: 'Show pending changes',
147
+ execute: async (_args, context) => {
148
+ const diff = context.settings?.pendingDiff || 'No pending changes';
149
+ context.onOutput?.(diff);
150
+ return { success: true, message: diff };
151
+ }
152
+ },
153
+ {
154
+ name: 'commit',
155
+ description: 'Commit pending changes',
156
+ execute: async (args, context) => {
157
+ const message = args.join(' ') || 'Auto-commit';
158
+ context.onOutput?.(`Committed with message: ${message}`);
159
+ context.settings = { ...context.settings, pendingDiff: null };
160
+ return { success: true, message: `Committed: ${message}` };
161
+ }
162
+ },
163
+ {
164
+ name: 'exit',
165
+ aliases: ['quit', 'q'],
166
+ description: 'Exit the session',
167
+ execute: async (_args, context) => {
168
+ context.onOutput?.('Goodbye!');
169
+ return { success: true, message: 'Exiting', shouldExit: true };
170
+ }
171
+ },
172
+ {
173
+ name: 'settings',
174
+ aliases: ['s'],
175
+ description: 'Show or modify settings',
176
+ usage: '/settings [key] [value]',
177
+ execute: async (args, context) => {
178
+ if (args.length === 0) {
179
+ const settings = JSON.stringify(context.settings || {}, null, 2);
180
+ context.onOutput?.(settings);
181
+ return { success: true, message: settings, data: context.settings };
182
+ }
183
+ if (args.length === 1) {
184
+ const value = context.settings?.[args[0]];
185
+ const msg = `${args[0]}: ${JSON.stringify(value)}`;
186
+ context.onOutput?.(msg);
187
+ return { success: true, message: msg, data: { [args[0]]: value } };
188
+ }
189
+ const [key, ...valueParts] = args;
190
+ let value = valueParts.join(' ');
191
+ try {
192
+ value = JSON.parse(value);
193
+ }
194
+ catch {
195
+ // Keep as string
196
+ }
197
+ context.settings = { ...context.settings, [key]: value };
198
+ context.onOutput?.(`Set ${key} = ${JSON.stringify(value)}`);
199
+ return { success: true, message: `Set ${key}` };
200
+ }
201
+ },
202
+ {
203
+ name: 'map',
204
+ description: 'Show repository map',
205
+ execute: async (_args, context) => {
206
+ const map = context.settings?.repoMap || 'Repository map not available. Run /map refresh to generate.';
207
+ context.onOutput?.(map);
208
+ return { success: true, message: map };
209
+ }
210
+ }
211
+ ];
212
+ /**
213
+ * Slash Command Registry
214
+ */
215
+ class SlashCommandRegistry {
216
+ constructor() {
217
+ this.commands = new Map();
218
+ this.aliases = new Map();
219
+ // Register built-in commands
220
+ for (const cmd of BUILTIN_COMMANDS) {
221
+ this.register(cmd);
222
+ }
223
+ }
224
+ register(command) {
225
+ this.commands.set(command.name, command);
226
+ if (command.aliases) {
227
+ for (const alias of command.aliases) {
228
+ this.aliases.set(alias, command.name);
229
+ }
230
+ }
231
+ }
232
+ get(name) {
233
+ const resolved = this.aliases.get(name) || name;
234
+ return this.commands.get(resolved);
235
+ }
236
+ getAll() {
237
+ return Array.from(this.commands.values());
238
+ }
239
+ has(name) {
240
+ return this.commands.has(name) || this.aliases.has(name);
241
+ }
242
+ }
243
+ let registry = null;
244
+ function getRegistry() {
245
+ if (!registry) {
246
+ registry = new SlashCommandRegistry();
247
+ }
248
+ return registry;
249
+ }
250
+ function registerCommand(command) {
251
+ getRegistry().register(command);
252
+ }
253
+ /**
254
+ * Parse slash command from input
255
+ */
256
+ function parseSlashCommand(input) {
257
+ const trimmed = input.trim();
258
+ if (!trimmed.startsWith('/')) {
259
+ return null;
260
+ }
261
+ const parts = trimmed.slice(1).split(/\s+/);
262
+ const command = parts[0].toLowerCase();
263
+ const args = parts.slice(1);
264
+ return { command, args };
265
+ }
266
+ /**
267
+ * Execute a slash command
268
+ */
269
+ async function executeSlashCommand(input, context) {
270
+ const parsed = parseSlashCommand(input);
271
+ if (!parsed) {
272
+ return { success: false, message: 'Not a slash command' };
273
+ }
274
+ const command = getRegistry().get(parsed.command);
275
+ if (!command) {
276
+ return { success: false, message: `Unknown command: /${parsed.command}` };
277
+ }
278
+ return command.execute(parsed.args, context);
279
+ }
280
+ /**
281
+ * Check if input is a slash command
282
+ */
283
+ function isSlashCommand(input) {
284
+ return input.trim().startsWith('/');
285
+ }
286
+ /**
287
+ * Slash Command Handler for CLI integration
288
+ */
289
+ class SlashCommandHandler {
290
+ constructor(initialContext = {}) {
291
+ this.context = {
292
+ history: [],
293
+ settings: {},
294
+ ...initialContext
295
+ };
296
+ }
297
+ async handle(input) {
298
+ return executeSlashCommand(input, this.context);
299
+ }
300
+ isCommand(input) {
301
+ return isSlashCommand(input);
302
+ }
303
+ getContext() {
304
+ return this.context;
305
+ }
306
+ updateContext(updates) {
307
+ this.context = { ...this.context, ...updates };
308
+ }
309
+ registerCommand(command) {
310
+ registerCommand(command);
311
+ }
312
+ }
313
+ exports.SlashCommandHandler = SlashCommandHandler;
314
+ function createSlashCommandHandler(context) {
315
+ return new SlashCommandHandler(context);
316
+ }