micro-models-agent 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +311 -0
- package/dist/agent/context.d.ts +18 -0
- package/dist/agent/context.d.ts.map +1 -0
- package/dist/agent/context.js +155 -0
- package/dist/agent/context.js.map +1 -0
- package/dist/agent/loop.d.ts +15 -0
- package/dist/agent/loop.d.ts.map +1 -0
- package/dist/agent/loop.js +575 -0
- package/dist/agent/loop.js.map +1 -0
- package/dist/agent/memory.d.ts +23 -0
- package/dist/agent/memory.d.ts.map +1 -0
- package/dist/agent/memory.js +244 -0
- package/dist/agent/memory.js.map +1 -0
- package/dist/agent/system-prompt.d.ts +3 -0
- package/dist/agent/system-prompt.d.ts.map +1 -0
- package/dist/agent/system-prompt.js +185 -0
- package/dist/agent/system-prompt.js.map +1 -0
- package/dist/blog-api/types/index.d.ts +2 -0
- package/dist/blog-api/types/index.d.ts.map +1 -0
- package/dist/blog-api/types/index.js +2 -0
- package/dist/blog-api/types/index.js.map +1 -0
- package/dist/cli/config.d.ts +3 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +25 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/model.d.ts +3 -0
- package/dist/cli/model.d.ts.map +1 -0
- package/dist/cli/model.js +144 -0
- package/dist/cli/model.js.map +1 -0
- package/dist/cli/provider.d.ts +3 -0
- package/dist/cli/provider.d.ts.map +1 -0
- package/dist/cli/provider.js +78 -0
- package/dist/cli/provider.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +88 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/config.d.ts +5 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +84 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/types.d.ts +38 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +2 -0
- package/dist/config/types.js.map +1 -0
- package/dist/file-loader.d.ts +12 -0
- package/dist/file-loader.d.ts.map +1 -0
- package/dist/file-loader.js +115 -0
- package/dist/file-loader.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer/cache.d.ts +27 -0
- package/dist/indexer/cache.d.ts.map +1 -0
- package/dist/indexer/cache.js +95 -0
- package/dist/indexer/cache.js.map +1 -0
- package/dist/indexer/code-index.d.ts +27 -0
- package/dist/indexer/code-index.d.ts.map +1 -0
- package/dist/indexer/code-index.js +197 -0
- package/dist/indexer/code-index.js.map +1 -0
- package/dist/indexer/project-map.d.ts +14 -0
- package/dist/indexer/project-map.d.ts.map +1 -0
- package/dist/indexer/project-map.js +157 -0
- package/dist/indexer/project-map.js.map +1 -0
- package/dist/llm/openai-compat.d.ts +11 -0
- package/dist/llm/openai-compat.d.ts.map +1 -0
- package/dist/llm/openai-compat.js +81 -0
- package/dist/llm/openai-compat.js.map +1 -0
- package/dist/llm/provider.d.ts +27 -0
- package/dist/llm/provider.d.ts.map +1 -0
- package/dist/llm/provider.js +2 -0
- package/dist/llm/provider.js.map +1 -0
- package/dist/llm/token-counter.d.ts +2 -0
- package/dist/llm/token-counter.d.ts.map +1 -0
- package/dist/llm/token-counter.js +24 -0
- package/dist/llm/token-counter.js.map +1 -0
- package/dist/repl/commands.d.ts +37 -0
- package/dist/repl/commands.d.ts.map +1 -0
- package/dist/repl/commands.js +433 -0
- package/dist/repl/commands.js.map +1 -0
- package/dist/repl/history.d.ts +19 -0
- package/dist/repl/history.d.ts.map +1 -0
- package/dist/repl/history.js +29 -0
- package/dist/repl/history.js.map +1 -0
- package/dist/repl/index.d.ts +5 -0
- package/dist/repl/index.d.ts.map +1 -0
- package/dist/repl/index.js +86 -0
- package/dist/repl/index.js.map +1 -0
- package/dist/repl.d.ts +5 -0
- package/dist/repl.d.ts.map +1 -0
- package/dist/repl.js +472 -0
- package/dist/repl.js.map +1 -0
- package/dist/session/store.d.ts +34 -0
- package/dist/session/store.d.ts.map +1 -0
- package/dist/session/store.js +115 -0
- package/dist/session/store.js.map +1 -0
- package/dist/skills/loader.d.ts +13 -0
- package/dist/skills/loader.d.ts.map +1 -0
- package/dist/skills/loader.js +122 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/styling/engine.d.ts +37 -0
- package/dist/styling/engine.d.ts.map +1 -0
- package/dist/styling/engine.js +136 -0
- package/dist/styling/engine.js.map +1 -0
- package/dist/styling/index.d.ts +7 -0
- package/dist/styling/index.d.ts.map +1 -0
- package/dist/styling/index.js +15 -0
- package/dist/styling/index.js.map +1 -0
- package/dist/styling/loader.d.ts +4 -0
- package/dist/styling/loader.d.ts.map +1 -0
- package/dist/styling/loader.js +78 -0
- package/dist/styling/loader.js.map +1 -0
- package/dist/styling/types.d.ts +46 -0
- package/dist/styling/types.d.ts.map +1 -0
- package/dist/styling/types.js +2 -0
- package/dist/styling/types.js.map +1 -0
- package/dist/tools/approve.d.ts +13 -0
- package/dist/tools/approve.d.ts.map +1 -0
- package/dist/tools/approve.js +32 -0
- package/dist/tools/approve.js.map +1 -0
- package/dist/tools/bash.d.ts +8 -0
- package/dist/tools/bash.d.ts.map +1 -0
- package/dist/tools/bash.js +186 -0
- package/dist/tools/bash.js.map +1 -0
- package/dist/tools/fs/copy-file.d.ts +5 -0
- package/dist/tools/fs/copy-file.d.ts.map +1 -0
- package/dist/tools/fs/copy-file.js +41 -0
- package/dist/tools/fs/copy-file.js.map +1 -0
- package/dist/tools/fs/create-dir.d.ts +5 -0
- package/dist/tools/fs/create-dir.d.ts.map +1 -0
- package/dist/tools/fs/create-dir.js +31 -0
- package/dist/tools/fs/create-dir.js.map +1 -0
- package/dist/tools/fs/delete-file.d.ts +5 -0
- package/dist/tools/fs/delete-file.d.ts.map +1 -0
- package/dist/tools/fs/delete-file.js +39 -0
- package/dist/tools/fs/delete-file.js.map +1 -0
- package/dist/tools/fs/edit-file.d.ts +5 -0
- package/dist/tools/fs/edit-file.d.ts.map +1 -0
- package/dist/tools/fs/edit-file.js +80 -0
- package/dist/tools/fs/edit-file.js.map +1 -0
- package/dist/tools/fs/file-info.d.ts +5 -0
- package/dist/tools/fs/file-info.d.ts.map +1 -0
- package/dist/tools/fs/file-info.js +37 -0
- package/dist/tools/fs/file-info.js.map +1 -0
- package/dist/tools/fs/glob-search.d.ts +5 -0
- package/dist/tools/fs/glob-search.d.ts.map +1 -0
- package/dist/tools/fs/glob-search.js +98 -0
- package/dist/tools/fs/glob-search.js.map +1 -0
- package/dist/tools/fs/grep-search.d.ts +5 -0
- package/dist/tools/fs/grep-search.d.ts.map +1 -0
- package/dist/tools/fs/grep-search.js +120 -0
- package/dist/tools/fs/grep-search.js.map +1 -0
- package/dist/tools/fs/list-dir.d.ts +5 -0
- package/dist/tools/fs/list-dir.d.ts.map +1 -0
- package/dist/tools/fs/list-dir.js +61 -0
- package/dist/tools/fs/list-dir.js.map +1 -0
- package/dist/tools/fs/move-file.d.ts +5 -0
- package/dist/tools/fs/move-file.d.ts.map +1 -0
- package/dist/tools/fs/move-file.js +41 -0
- package/dist/tools/fs/move-file.js.map +1 -0
- package/dist/tools/fs/path-utils.d.ts +30 -0
- package/dist/tools/fs/path-utils.d.ts.map +1 -0
- package/dist/tools/fs/path-utils.js +81 -0
- package/dist/tools/fs/path-utils.js.map +1 -0
- package/dist/tools/fs/read-file.d.ts +5 -0
- package/dist/tools/fs/read-file.d.ts.map +1 -0
- package/dist/tools/fs/read-file.js +51 -0
- package/dist/tools/fs/read-file.js.map +1 -0
- package/dist/tools/fs/tree.d.ts +5 -0
- package/dist/tools/fs/tree.d.ts.map +1 -0
- package/dist/tools/fs/tree.js +75 -0
- package/dist/tools/fs/tree.js.map +1 -0
- package/dist/tools/fs/types.d.ts +7 -0
- package/dist/tools/fs/types.d.ts.map +1 -0
- package/dist/tools/fs/types.js +9 -0
- package/dist/tools/fs/types.js.map +1 -0
- package/dist/tools/fs/write-file.d.ts +5 -0
- package/dist/tools/fs/write-file.d.ts.map +1 -0
- package/dist/tools/fs/write-file.js +58 -0
- package/dist/tools/fs/write-file.js.map +1 -0
- package/dist/tools/hooks.d.ts +15 -0
- package/dist/tools/hooks.d.ts.map +1 -0
- package/dist/tools/hooks.js +109 -0
- package/dist/tools/hooks.js.map +1 -0
- package/dist/tools/mcp.d.ts +22 -0
- package/dist/tools/mcp.d.ts.map +1 -0
- package/dist/tools/mcp.js +90 -0
- package/dist/tools/mcp.js.map +1 -0
- package/dist/tools/plan.d.ts +20 -0
- package/dist/tools/plan.d.ts.map +1 -0
- package/dist/tools/plan.js +86 -0
- package/dist/tools/plan.js.map +1 -0
- package/dist/tools/question.d.ts +17 -0
- package/dist/tools/question.d.ts.map +1 -0
- package/dist/tools/question.js +55 -0
- package/dist/tools/question.js.map +1 -0
- package/dist/tools/registry.d.ts +25 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +81 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/sanitizer.d.ts +7 -0
- package/dist/tools/sanitizer.d.ts.map +1 -0
- package/dist/tools/sanitizer.js +50 -0
- package/dist/tools/sanitizer.js.map +1 -0
- package/dist/tools/syntax-check.d.ts +16 -0
- package/dist/tools/syntax-check.d.ts.map +1 -0
- package/dist/tools/syntax-check.js +265 -0
- package/dist/tools/syntax-check.js.map +1 -0
- package/dist/tools/todo.d.ts +19 -0
- package/dist/tools/todo.d.ts.map +1 -0
- package/dist/tools/todo.js +102 -0
- package/dist/tools/todo.js.map +1 -0
- package/dist/ui/components/diff-view.d.ts +8 -0
- package/dist/ui/components/diff-view.d.ts.map +1 -0
- package/dist/ui/components/diff-view.js +25 -0
- package/dist/ui/components/diff-view.js.map +1 -0
- package/dist/ui/components/status-bar.d.ts +3 -0
- package/dist/ui/components/status-bar.d.ts.map +1 -0
- package/dist/ui/components/status-bar.js +14 -0
- package/dist/ui/components/status-bar.js.map +1 -0
- package/dist/ui/double-press.d.ts +9 -0
- package/dist/ui/double-press.d.ts.map +1 -0
- package/dist/ui/double-press.js +18 -0
- package/dist/ui/double-press.js.map +1 -0
- package/dist/ui/index.d.ts +4 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +7 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/opentui-renderer.d.ts +53 -0
- package/dist/ui/opentui-renderer.d.ts.map +1 -0
- package/dist/ui/opentui-renderer.js +463 -0
- package/dist/ui/opentui-renderer.js.map +1 -0
- package/dist/ui/readline-renderer.d.ts +30 -0
- package/dist/ui/readline-renderer.d.ts.map +1 -0
- package/dist/ui/readline-renderer.js +97 -0
- package/dist/ui/readline-renderer.js.map +1 -0
- package/dist/ui/renderer.d.ts +35 -0
- package/dist/ui/renderer.d.ts.map +1 -0
- package/dist/ui/renderer.js +2 -0
- package/dist/ui/renderer.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
export class OpenAICompat {
|
|
2
|
+
model;
|
|
3
|
+
contextWindow;
|
|
4
|
+
baseUrl;
|
|
5
|
+
apiKey;
|
|
6
|
+
constructor(baseUrl, model, contextWindow, apiKey = null) {
|
|
7
|
+
this.baseUrl = baseUrl.replace(/\/+$/, '');
|
|
8
|
+
this.model = model;
|
|
9
|
+
this.contextWindow = contextWindow;
|
|
10
|
+
this.apiKey = apiKey;
|
|
11
|
+
}
|
|
12
|
+
async *chat(messages, options) {
|
|
13
|
+
const body = {
|
|
14
|
+
model: this.model,
|
|
15
|
+
messages: messages.map(m => {
|
|
16
|
+
const msg = { role: m.role, content: m.content };
|
|
17
|
+
return msg;
|
|
18
|
+
}),
|
|
19
|
+
stream: true,
|
|
20
|
+
temperature: options?.temperature ?? 0.7,
|
|
21
|
+
max_tokens: options?.max_tokens ?? 4096,
|
|
22
|
+
};
|
|
23
|
+
if (options?.top_p !== undefined)
|
|
24
|
+
body.top_p = options.top_p;
|
|
25
|
+
if (options?.stop !== undefined)
|
|
26
|
+
body.stop = options.stop;
|
|
27
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
28
|
+
if (this.apiKey)
|
|
29
|
+
headers['Authorization'] = `Bearer ${this.apiKey}`;
|
|
30
|
+
const response = await fetch(`${this.baseUrl}/chat/completions`, {
|
|
31
|
+
method: 'POST',
|
|
32
|
+
headers,
|
|
33
|
+
body: JSON.stringify(body),
|
|
34
|
+
signal: options?.signal,
|
|
35
|
+
});
|
|
36
|
+
if (!response.ok) {
|
|
37
|
+
const err = await response.json().catch(() => ({}));
|
|
38
|
+
throw new Error(`API ${response.status}: ${err.error?.message ?? response.statusText}`);
|
|
39
|
+
}
|
|
40
|
+
const reader = response.body.getReader();
|
|
41
|
+
const decoder = new TextDecoder();
|
|
42
|
+
let buffer = '';
|
|
43
|
+
while (true) {
|
|
44
|
+
const { done, value } = await reader.read();
|
|
45
|
+
if (done)
|
|
46
|
+
break;
|
|
47
|
+
buffer += decoder.decode(value, { stream: true });
|
|
48
|
+
const lines = buffer.split('\n');
|
|
49
|
+
buffer = lines.pop() ?? '';
|
|
50
|
+
for (const line of lines) {
|
|
51
|
+
const trimmed = line.trim();
|
|
52
|
+
if (!trimmed || !trimmed.startsWith('data: '))
|
|
53
|
+
continue;
|
|
54
|
+
const data = trimmed.slice(6);
|
|
55
|
+
if (data === '[DONE]')
|
|
56
|
+
return;
|
|
57
|
+
try {
|
|
58
|
+
const parsed = JSON.parse(data);
|
|
59
|
+
const delta = parsed.choices?.[0]?.delta;
|
|
60
|
+
if (delta?.content) {
|
|
61
|
+
yield { content: delta.content, finish_reason: null };
|
|
62
|
+
}
|
|
63
|
+
else if (delta?.reasoning_content) {
|
|
64
|
+
// Thinking models: yield reasoning as content so it's visible
|
|
65
|
+
yield { content: delta.reasoning_content, finish_reason: null };
|
|
66
|
+
}
|
|
67
|
+
const finish = parsed.choices?.[0]?.finish_reason;
|
|
68
|
+
if (finish) {
|
|
69
|
+
yield { content: '', finish_reason: finish };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch { /* skip malformed chunk */ }
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async countTokens(text) {
|
|
77
|
+
const mod = await import('./token-counter.js');
|
|
78
|
+
return mod.countTokens(text);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=openai-compat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-compat.js","sourceRoot":"","sources":["../../src/llm/openai-compat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface LLMProvider {
|
|
2
|
+
chat(messages: ChatMessage[], options?: ChatOptions): AsyncIterable<Chunk>;
|
|
3
|
+
countTokens(text: string): Promise<number>;
|
|
4
|
+
model: string;
|
|
5
|
+
contextWindow: number;
|
|
6
|
+
}
|
|
7
|
+
export interface ChatMessage {
|
|
8
|
+
role: 'system' | 'user' | 'assistant' | 'tool';
|
|
9
|
+
content: string;
|
|
10
|
+
tool_call_id?: string;
|
|
11
|
+
name?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ChatOptions {
|
|
14
|
+
temperature?: number;
|
|
15
|
+
top_p?: number;
|
|
16
|
+
max_tokens?: number;
|
|
17
|
+
stop?: string[];
|
|
18
|
+
frequency_penalty?: number;
|
|
19
|
+
presence_penalty?: number;
|
|
20
|
+
seed?: number;
|
|
21
|
+
signal?: AbortSignal;
|
|
22
|
+
}
|
|
23
|
+
export interface Chunk {
|
|
24
|
+
content: string;
|
|
25
|
+
finish_reason?: 'stop' | 'length' | 'tool_calls' | null;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/llm/provider.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAC3E,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,YAAY,GAAG,IAAI,CAAC;CACzD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/llm/provider.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-counter.d.ts","sourceRoot":"","sources":["../../src/llm/token-counter.ts"],"names":[],"mappings":"AAYA,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAS/D"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
let tiktoken = null;
|
|
2
|
+
async function loadTiktoken() {
|
|
3
|
+
if (tiktoken)
|
|
4
|
+
return;
|
|
5
|
+
try {
|
|
6
|
+
const mod = await import('js-tiktoken');
|
|
7
|
+
tiktoken = mod;
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
tiktoken = null;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export async function countTokens(text) {
|
|
14
|
+
await loadTiktoken();
|
|
15
|
+
if (tiktoken?.encodingForModel) {
|
|
16
|
+
try {
|
|
17
|
+
const enc = tiktoken.encodingForModel('gpt-4');
|
|
18
|
+
return enc.encode(text).length;
|
|
19
|
+
}
|
|
20
|
+
catch { /* fall through */ }
|
|
21
|
+
}
|
|
22
|
+
return Math.ceil(text.length / 4);
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=token-counter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-counter.js","sourceRoot":"","sources":["../../src/llm/token-counter.ts"],"names":[],"mappings":"AAAA,IAAI,QAAQ,GAAQ,IAAI,CAAC;AAEzB,KAAK,UAAU,YAAY;IACzB,IAAI,QAAQ;QAAE,OAAO;IACrB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QACxC,QAAQ,GAAG,GAAG,CAAC;IACjB,CAAC;IAAC,MAAM,CAAC;QACP,QAAQ,GAAG,IAAI,CAAC;IAClB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY;IAC5C,MAAM,YAAY,EAAE,CAAC;IACrB,IAAI,QAAQ,EAAE,gBAAgB,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,QAAQ,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;YAC/C,OAAO,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { LLMProvider } from '../llm/provider.js';
|
|
2
|
+
import type { ToolRegistry } from '../tools/registry.js';
|
|
3
|
+
import type { OutputRenderer } from '../ui/renderer.js';
|
|
4
|
+
type SlashHandler = (args: string, context: CommandContext) => Promise<void> | void;
|
|
5
|
+
export interface CommandContext {
|
|
6
|
+
renderer: OutputRenderer;
|
|
7
|
+
provider: LLMProvider;
|
|
8
|
+
registry: ToolRegistry;
|
|
9
|
+
history: {
|
|
10
|
+
role: 'user' | 'assistant';
|
|
11
|
+
content: string;
|
|
12
|
+
}[];
|
|
13
|
+
conversationHistory: {
|
|
14
|
+
role: 'user' | 'assistant';
|
|
15
|
+
content: string;
|
|
16
|
+
}[];
|
|
17
|
+
modelLabel: string;
|
|
18
|
+
}
|
|
19
|
+
export interface SlashCommand {
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
handler: SlashHandler;
|
|
23
|
+
}
|
|
24
|
+
export declare function getSlashCommands(): SlashCommand[];
|
|
25
|
+
export declare function parseSlashCommand(line: string): {
|
|
26
|
+
cmd: string;
|
|
27
|
+
args: string;
|
|
28
|
+
} | null;
|
|
29
|
+
export declare function getWriteState(): {
|
|
30
|
+
path: string | null;
|
|
31
|
+
buffer: string[];
|
|
32
|
+
};
|
|
33
|
+
export declare function clearWriteState(): void;
|
|
34
|
+
export declare function isWriteMode(): boolean;
|
|
35
|
+
export declare function handleWriteLine(line: string, renderer: OutputRenderer): void;
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/repl/commands.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAOzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,KAAK,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAEpF,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,cAAc,CAAC;IACzB,QAAQ,EAAE,WAAW,CAAC;IACtB,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC3D,mBAAmB,EAAE;QAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACvE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,YAAY,CAAC;CACvB;AAED,wBAAgB,gBAAgB,IAAI,YAAY,EAAE,CAuBjD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAMpF;AAgED,wBAAgB,aAAa;;;EAAgE;AAC7F,wBAAgB,eAAe,SAAmD;AAClF,wBAAgB,WAAW,YAAyC;AAWpE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,CAc5E"}
|
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { globSync } from 'node:fs';
|
|
3
|
+
import { execSync } from 'node:child_process';
|
|
4
|
+
import { executeBash } from '../tools/bash.js';
|
|
5
|
+
import { runAgentLoop } from '../agent/loop.js';
|
|
6
|
+
import { loadMemory, saveMemory, searchMemory, loadAllMemory, ensureMemoryDir, removeMemoryEntry, exportMemory } from '../agent/memory.js';
|
|
7
|
+
import { listInstalledSkills } from '../skills/loader.js';
|
|
8
|
+
import { listSessions, loadSession, createNamedSession, createAutoSession, formatSessionList } from '../session/store.js';
|
|
9
|
+
import { rebuildCodeIndex, rebuildProjectMap, getOrBuildCodeIndex, getOrBuildProjectMap } from '../indexer/cache.js';
|
|
10
|
+
import { getTheme } from '../styling/index.js';
|
|
11
|
+
export function getSlashCommands() {
|
|
12
|
+
return [
|
|
13
|
+
{ name: 'exit', description: 'exit MMA', handler: cmdExit },
|
|
14
|
+
{ name: 'quit', description: 'exit MMA', handler: cmdExit },
|
|
15
|
+
{ name: 'help', description: 'show help', handler: cmdHelp },
|
|
16
|
+
{ name: 'bash', description: 'run shell command', handler: cmdBash },
|
|
17
|
+
{ name: 'read', description: 'display file', handler: cmdRead },
|
|
18
|
+
{ name: 'write', description: 'write file (end with EOF)', handler: cmdWrite },
|
|
19
|
+
{ name: 'edit', description: 'replace line in file', handler: cmdEdit },
|
|
20
|
+
{ name: 'find', description: 'find files by glob', handler: cmdFind },
|
|
21
|
+
{ name: 'search', description: 'search file contents', handler: cmdSearch },
|
|
22
|
+
{ name: 'git', description: 'git operations', handler: cmdGit },
|
|
23
|
+
{ name: 'memory', description: 'memory management', handler: cmdMemory },
|
|
24
|
+
{ name: 'skill', description: 'list skills', handler: cmdSkill },
|
|
25
|
+
{ name: 'sessions', description: 'list sessions', handler: cmdSessions },
|
|
26
|
+
{ name: 'resume', description: 'resume session', handler: cmdResume },
|
|
27
|
+
{ name: 'save', description: 'save session', handler: cmdSave },
|
|
28
|
+
{ name: 'clear', description: 'clear context', handler: cmdClear },
|
|
29
|
+
{ name: 'new', description: 'clear context', handler: cmdClear },
|
|
30
|
+
{ name: 'stop', description: 'stop agent loop', handler: cmdStop },
|
|
31
|
+
{ name: 'index', description: 'index management', handler: cmdIndex },
|
|
32
|
+
{ name: 'export', description: 'export session (normal or debug)', handler: cmdExport },
|
|
33
|
+
];
|
|
34
|
+
}
|
|
35
|
+
export function parseSlashCommand(line) {
|
|
36
|
+
if (!line.startsWith('/'))
|
|
37
|
+
return null;
|
|
38
|
+
const spaceIdx = line.indexOf(' ');
|
|
39
|
+
const cmd = spaceIdx === -1 ? line.slice(1) : line.slice(1, spaceIdx);
|
|
40
|
+
const args = spaceIdx === -1 ? '' : line.slice(spaceIdx + 1);
|
|
41
|
+
return { cmd, args };
|
|
42
|
+
}
|
|
43
|
+
function cmdExit(_args, ctx) {
|
|
44
|
+
if (ctx.conversationHistory.length > 0) {
|
|
45
|
+
createAutoSession(ctx.conversationHistory, ctx.modelLabel, process.cwd(), { totalTokens: 0, compactCount: 0 });
|
|
46
|
+
ctx.renderer.writeSuccess('Session auto-saved.');
|
|
47
|
+
}
|
|
48
|
+
ctx.renderer.writeDim('Bye!');
|
|
49
|
+
ctx.renderer.destroy();
|
|
50
|
+
}
|
|
51
|
+
function cmdHelp(_args, ctx) {
|
|
52
|
+
ctx.renderer.writeDim(`
|
|
53
|
+
/bash <cmd> — run shell command
|
|
54
|
+
/read <file> — display file with line numbers
|
|
55
|
+
/edit <file> <n> — replace line N in file with rest of args
|
|
56
|
+
/write <file> — write file (end with EOF on its own line)
|
|
57
|
+
/find <pattern> — find files by glob pattern
|
|
58
|
+
/search <pattern> — search file contents
|
|
59
|
+
/git <args> — git operations
|
|
60
|
+
/memory — show memory summary
|
|
61
|
+
/memory show <t> — show memory type content
|
|
62
|
+
/memory add <t> — add memory entry
|
|
63
|
+
/memory search <q> — search memory
|
|
64
|
+
/memory remove <t> <n> — remove entry N from type
|
|
65
|
+
/memory export — export memory to .mma/memory-export.md
|
|
66
|
+
/skill — list installed skills
|
|
67
|
+
/sessions — list saved sessions
|
|
68
|
+
/resume <id> — resume a session
|
|
69
|
+
/save [name] — save current session
|
|
70
|
+
/clear — clear context (new session)
|
|
71
|
+
/export [mode] — export session (normal or debug)
|
|
72
|
+
/index [cmd] — index status/rebuild/map
|
|
73
|
+
/stop — stop agent loop
|
|
74
|
+
/exit — exit MMA
|
|
75
|
+
`);
|
|
76
|
+
}
|
|
77
|
+
async function cmdBash(args, ctx) {
|
|
78
|
+
const result = await executeBash(args);
|
|
79
|
+
if (result.stdout)
|
|
80
|
+
ctx.renderer.write(result.stdout);
|
|
81
|
+
if (result.stderr)
|
|
82
|
+
ctx.renderer.writeError(result.stderr);
|
|
83
|
+
}
|
|
84
|
+
function cmdRead(args, ctx) {
|
|
85
|
+
try {
|
|
86
|
+
const content = readFileSync(args, 'utf-8');
|
|
87
|
+
const lines = content.split('\n');
|
|
88
|
+
const maxLines = 200;
|
|
89
|
+
ctx.renderer.writeNewline();
|
|
90
|
+
const shown = lines.slice(0, maxLines);
|
|
91
|
+
ctx.renderer.writeFileOutput(shown);
|
|
92
|
+
if (lines.length > maxLines) {
|
|
93
|
+
ctx.renderer.writeDim(` ... (${lines.length - maxLines} more lines)`);
|
|
94
|
+
}
|
|
95
|
+
ctx.renderer.writeNewline();
|
|
96
|
+
}
|
|
97
|
+
catch (e) {
|
|
98
|
+
ctx.renderer.writeError(e.message);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
let _currentWritePath = null;
|
|
102
|
+
let _writeBuffer = [];
|
|
103
|
+
export function getWriteState() { return { path: _currentWritePath, buffer: _writeBuffer }; }
|
|
104
|
+
export function clearWriteState() { _currentWritePath = null; _writeBuffer = []; }
|
|
105
|
+
export function isWriteMode() { return _currentWritePath !== null; }
|
|
106
|
+
function cmdWrite(args, ctx) {
|
|
107
|
+
if (!args) {
|
|
108
|
+
ctx.renderer.writeInfo(' Usage: /write <file> (then type content, end with EOF)');
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
_currentWritePath = args;
|
|
112
|
+
ctx.renderer.writeDim(' Type your content. End with EOF on its own line:');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
export function handleWriteLine(line, renderer) {
|
|
116
|
+
if (line.trim() === 'EOF') {
|
|
117
|
+
const theme = getTheme();
|
|
118
|
+
try {
|
|
119
|
+
writeFileSync(_currentWritePath, _writeBuffer.join('\n'), 'utf-8');
|
|
120
|
+
renderer.writeSuccess(`written to ${theme.filePath(_currentWritePath)}`);
|
|
121
|
+
}
|
|
122
|
+
catch (e) {
|
|
123
|
+
renderer.writeError(theme.error(e.message));
|
|
124
|
+
}
|
|
125
|
+
_currentWritePath = null;
|
|
126
|
+
_writeBuffer = [];
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
_writeBuffer.push(line);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function cmdEdit(args, ctx) {
|
|
133
|
+
const parts = args.split(/\s+/);
|
|
134
|
+
if (parts.length < 3) {
|
|
135
|
+
ctx.renderer.writeInfo(' Usage: /edit <file> <line> <new content>');
|
|
136
|
+
ctx.renderer.writeInfo(' Example: /edit src/index.ts 5 const x = 1;');
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const [filePath, lineStr, ...rest] = parts;
|
|
140
|
+
const lineNum = parseInt(lineStr, 10);
|
|
141
|
+
if (isNaN(lineNum) || lineNum < 1) {
|
|
142
|
+
ctx.renderer.writeDim(' Line number must be a positive integer');
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const newContent = rest.join(' ');
|
|
146
|
+
try {
|
|
147
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
148
|
+
const lines = content.split('\n');
|
|
149
|
+
if (lineNum > lines.length) {
|
|
150
|
+
ctx.renderer.writeWarning(` File has only ${lines.length} lines`);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
lines[lineNum - 1] = newContent;
|
|
154
|
+
writeFileSync(filePath, lines.join('\n'), 'utf-8');
|
|
155
|
+
const theme = getTheme();
|
|
156
|
+
ctx.renderer.writeSuccess(`Line ${lineNum} updated in ${theme.filePath(filePath)}`);
|
|
157
|
+
}
|
|
158
|
+
catch (e) {
|
|
159
|
+
ctx.renderer.writeError(e.message);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function cmdFind(args, ctx) {
|
|
163
|
+
try {
|
|
164
|
+
const IGNORE = ['node_modules', '.git', 'dist', '.mma', 'build', '__pycache__'];
|
|
165
|
+
const fixedPattern = args.includes('/') || args.includes('\\') ? args : `**/${args}`;
|
|
166
|
+
const results = globSync(fixedPattern).filter(f => !f.split(/[/\\]/).some(p => IGNORE.includes(p)));
|
|
167
|
+
if (results.length === 0) {
|
|
168
|
+
ctx.renderer.writeDim(' No matches');
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const theme = getTheme();
|
|
172
|
+
for (const f of results) {
|
|
173
|
+
ctx.renderer.writeLine(`${theme.indent}${theme.filePath(f)}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
catch (e) {
|
|
177
|
+
ctx.renderer.writeError(e.message);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function cmdSearch(args, ctx) {
|
|
181
|
+
try {
|
|
182
|
+
const result = execSync(`findstr /s /n /c:"${args}" *.ts *.js *.tsx *.jsx *.json *.md`, { encoding: 'utf-8', timeout: 10000 });
|
|
183
|
+
const lines = result.trim().split('\n').slice(0, 30);
|
|
184
|
+
if (lines.length === 0 || (lines.length === 1 && lines[0] === '')) {
|
|
185
|
+
ctx.renderer.writeDim(' No matches');
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
const theme = getTheme();
|
|
189
|
+
for (const line of lines) {
|
|
190
|
+
ctx.renderer.writeLine(`${theme.indent}${line}`);
|
|
191
|
+
}
|
|
192
|
+
if (result.trim().split('\n').length > 30) {
|
|
193
|
+
ctx.renderer.writeDim(` ... (${result.trim().split('\n').length - 30} more)`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
catch (e) {
|
|
197
|
+
if (e.status === 1) {
|
|
198
|
+
ctx.renderer.writeDim(' No matches');
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
ctx.renderer.writeError(e.message);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
async function cmdGit(args, ctx) {
|
|
206
|
+
const result = await executeBash(`git ${args}`);
|
|
207
|
+
if (result.stdout)
|
|
208
|
+
ctx.renderer.write(result.stdout);
|
|
209
|
+
if (result.stderr)
|
|
210
|
+
ctx.renderer.writeError(result.stderr);
|
|
211
|
+
}
|
|
212
|
+
function cmdMemory(args, ctx) {
|
|
213
|
+
ensureMemoryDir();
|
|
214
|
+
const theme = getTheme();
|
|
215
|
+
if (!args.trim()) {
|
|
216
|
+
const summary = loadAllMemory();
|
|
217
|
+
if (summary) {
|
|
218
|
+
ctx.renderer.writeLine(summary);
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
ctx.renderer.writeDim(' Project memory is empty. Use /memory add <type> <text>');
|
|
222
|
+
}
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
const parts = args.trim().split(/\s+/);
|
|
226
|
+
const subcommand = parts[0];
|
|
227
|
+
const rest = parts.slice(1);
|
|
228
|
+
const type = rest[0] || '';
|
|
229
|
+
const text = rest.slice(1).join(' ') || '';
|
|
230
|
+
switch (subcommand) {
|
|
231
|
+
case 'show': {
|
|
232
|
+
if (!type) {
|
|
233
|
+
ctx.renderer.writeInfo(' Usage: /memory show <type> (project|conventions|decisions|errors|history)');
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const content = loadMemory(type);
|
|
237
|
+
ctx.renderer.writeNewline();
|
|
238
|
+
ctx.renderer.writeLine(content);
|
|
239
|
+
ctx.renderer.writeNewline();
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
case 'add': {
|
|
243
|
+
if (!type || !text) {
|
|
244
|
+
ctx.renderer.writeInfo(' Usage: /memory add <type> <text>');
|
|
245
|
+
ctx.renderer.writeInfo(' Types: project, conventions, decisions, errors, history');
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
saveMemory(type, text.slice(0, 60), text);
|
|
249
|
+
ctx.renderer.writeSuccess(`Saved to .mma/memory/${type}.md`);
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
case 'search': {
|
|
253
|
+
if (!type) {
|
|
254
|
+
ctx.renderer.writeInfo(' Usage: /memory search <query>');
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const results = searchMemory(type);
|
|
258
|
+
if (results.length === 0) {
|
|
259
|
+
ctx.renderer.writeDim(' No matches');
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
ctx.renderer.writeInfo(` Found ${results.length} matches:`);
|
|
263
|
+
for (const r of results) {
|
|
264
|
+
ctx.renderer.writeLine(` [${r.type}] ${r.match}`);
|
|
265
|
+
}
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
case 'remove': {
|
|
269
|
+
if (!type) {
|
|
270
|
+
ctx.renderer.writeInfo(' Usage: /memory remove <type> <line-number>');
|
|
271
|
+
ctx.renderer.writeInfo(' First use /memory show <type> to see entries with line numbers.');
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
const lineNum = parseInt(text, 10);
|
|
275
|
+
if (isNaN(lineNum) || lineNum < 1) {
|
|
276
|
+
ctx.renderer.writeDim(' Line number must be a positive integer');
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
const removed = removeMemoryEntry(type, lineNum);
|
|
280
|
+
if (removed) {
|
|
281
|
+
ctx.renderer.writeSuccess(`Entry removed from ${type}.md`);
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
ctx.renderer.writeError(' Could not remove entry (line number out of range?)');
|
|
285
|
+
}
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
case 'export': {
|
|
289
|
+
const exported = exportMemory();
|
|
290
|
+
if (exported) {
|
|
291
|
+
ctx.renderer.writeSuccess(`Memory exported to ${exported}`);
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
ctx.renderer.writeDim(' No memory to export');
|
|
295
|
+
}
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
default: {
|
|
299
|
+
ctx.renderer.writeInfo(' Usage: /memory [show <type>|add <type> <text>|search <query>|remove <type> <line>|export]');
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
function cmdSkill(args, ctx) {
|
|
304
|
+
const subcmd = args.trim() || 'list';
|
|
305
|
+
switch (subcmd) {
|
|
306
|
+
case 'list': {
|
|
307
|
+
const skills = listInstalledSkills();
|
|
308
|
+
if (skills.length === 0) {
|
|
309
|
+
ctx.renderer.writeDim(' No skills installed.');
|
|
310
|
+
ctx.renderer.writeDim(' Skills are loaded from: ~/.mma/skills/, ~/.claude/skills/, .claude/skills/, .agents/skills/');
|
|
311
|
+
ctx.renderer.writeDim(' Reference skills in prompts with @skill-name');
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
ctx.renderer.writeInfo(` Installed skills (${skills.length}):`);
|
|
315
|
+
for (const s of skills) {
|
|
316
|
+
ctx.renderer.writeLine(` @${s}`);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
break;
|
|
320
|
+
}
|
|
321
|
+
default:
|
|
322
|
+
ctx.renderer.writeInfo(' Usage: /skill [list]');
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
function cmdSessions(_args, ctx) {
|
|
326
|
+
const sessions = listSessions();
|
|
327
|
+
ctx.renderer.writeLine(formatSessionList(sessions));
|
|
328
|
+
}
|
|
329
|
+
async function cmdResume(args, ctx) {
|
|
330
|
+
if (!args.trim()) {
|
|
331
|
+
ctx.renderer.writeInfo(' Usage: /resume <session-id>');
|
|
332
|
+
ctx.renderer.writeInfo(' Use /sessions to see available sessions.');
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
const session = loadSession(args.trim());
|
|
336
|
+
if (!session) {
|
|
337
|
+
ctx.renderer.writeError(` Session "${args.trim()}" not found.`);
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
ctx.renderer.writeInfo(`Resumed session: ${session.id} (${session.messages.length} messages)`);
|
|
341
|
+
ctx.renderer.writeDim(`Provider: ${session.provider}`);
|
|
342
|
+
ctx.renderer.writeNewline();
|
|
343
|
+
const lastUser = session.messages.filter(m => m.role === 'user').pop();
|
|
344
|
+
const prevMsgs = session.messages.filter(m => m.role !== 'system').map(m => ({ role: m.role, content: m.content }));
|
|
345
|
+
if (lastUser) {
|
|
346
|
+
const result = await runAgentLoop(ctx.provider, ctx.registry, lastUser.content, undefined, prevMsgs, ctx.renderer);
|
|
347
|
+
for (const msg of result.messages) {
|
|
348
|
+
if (msg.role !== 'system') {
|
|
349
|
+
ctx.history.push({ role: msg.role, content: msg.content });
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
function cmdSave(args, ctx) {
|
|
355
|
+
if (ctx.history.length === 0) {
|
|
356
|
+
ctx.renderer.writeDim(' No conversation to save.');
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
const name = args.trim() || '';
|
|
360
|
+
const providerLabel = `${ctx.provider.model}`;
|
|
361
|
+
const filePath = createNamedSession(name, ctx.history, providerLabel, process.cwd(), { totalTokens: 0, compactCount: 0 });
|
|
362
|
+
const id = filePath.split(/[/\\]/).pop()?.replace('.json', '') || '';
|
|
363
|
+
ctx.renderer.writeSuccess(`Session saved: ${id}${name ? ` (${name})` : ''}`);
|
|
364
|
+
}
|
|
365
|
+
function cmdClear(_args, ctx) {
|
|
366
|
+
ctx.history.length = 0;
|
|
367
|
+
ctx.renderer.writeInfo(' Context cleared. Starting new session.');
|
|
368
|
+
}
|
|
369
|
+
function cmdStop(_args, ctx) {
|
|
370
|
+
ctx.renderer.writeDim(' Stopping agent loop...');
|
|
371
|
+
ctx.renderer.destroy();
|
|
372
|
+
}
|
|
373
|
+
function cmdIndex(args, ctx) {
|
|
374
|
+
const subcmd = args.trim() || 'status';
|
|
375
|
+
switch (subcmd) {
|
|
376
|
+
case 'rebuild': {
|
|
377
|
+
ctx.renderer.writeInfo(' Rebuilding code index...');
|
|
378
|
+
const { formatted } = rebuildCodeIndex(process.cwd());
|
|
379
|
+
ctx.renderer.writeLine(formatted);
|
|
380
|
+
ctx.renderer.writeSuccess('Code index rebuilt');
|
|
381
|
+
break;
|
|
382
|
+
}
|
|
383
|
+
case 'map': {
|
|
384
|
+
ctx.renderer.writeInfo(' Rebuilding project map...');
|
|
385
|
+
const { formatted } = rebuildProjectMap(process.cwd());
|
|
386
|
+
ctx.renderer.writeLine(formatted);
|
|
387
|
+
ctx.renderer.writeSuccess('Project map rebuilt');
|
|
388
|
+
break;
|
|
389
|
+
}
|
|
390
|
+
case 'status': {
|
|
391
|
+
const { formatted: mapFormatted } = getOrBuildProjectMap(process.cwd());
|
|
392
|
+
const { formatted: idxFormatted } = getOrBuildCodeIndex(process.cwd());
|
|
393
|
+
ctx.renderer.writeLine(mapFormatted.split('\n').slice(0, 3).join('\n'));
|
|
394
|
+
ctx.renderer.writeNewline();
|
|
395
|
+
ctx.renderer.writeLine(idxFormatted.split('\n').slice(0, 3).join('\n'));
|
|
396
|
+
break;
|
|
397
|
+
}
|
|
398
|
+
default:
|
|
399
|
+
ctx.renderer.writeInfo(' Usage: /index [status|rebuild|map]');
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
function cmdExport(args, ctx) {
|
|
403
|
+
const mode = args.trim() || 'normal';
|
|
404
|
+
const history = ctx.conversationHistory;
|
|
405
|
+
if (history.length === 0) {
|
|
406
|
+
ctx.renderer.writeDim(' No conversation to export.');
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
let output = '';
|
|
410
|
+
if (mode === 'debug') {
|
|
411
|
+
output = `# Session Debug Export\n`;
|
|
412
|
+
output += `Model: ${ctx.modelLabel}\n`;
|
|
413
|
+
output += `Messages: ${history.length}\n`;
|
|
414
|
+
output += `---\n\n`;
|
|
415
|
+
for (const msg of history) {
|
|
416
|
+
const role = msg.role === 'user' ? '## User' : '## Assistant';
|
|
417
|
+
output += `${role}\n\`\`\`\n${msg.content}\n\`\`\`\n\n`;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
else {
|
|
421
|
+
output = `# Session Export\n`;
|
|
422
|
+
output += `Model: ${ctx.modelLabel}\n\n`;
|
|
423
|
+
for (const msg of history) {
|
|
424
|
+
const role = msg.role === 'user' ? '**You:**' : '**Assistant:**';
|
|
425
|
+
output += `${role} ${msg.content}\n\n`;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
const filename = `.mma/export-${Date.now()}.md`;
|
|
429
|
+
mkdirSync('.mma', { recursive: true });
|
|
430
|
+
writeFileSync(filename, output, 'utf-8');
|
|
431
|
+
ctx.renderer.writeSuccess(` Exported to ${filename}`);
|
|
432
|
+
}
|
|
433
|
+
//# sourceMappingURL=commands.js.map
|