@travisennis/acai 0.0.5 → 0.0.6
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 +4 -2
- package/dist/agent/index.d.ts +119 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +406 -0
- package/dist/agent/manual-loop.d.ts +41 -0
- package/dist/agent/manual-loop.d.ts.map +1 -0
- package/dist/agent/manual-loop.js +278 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +27 -33
- package/dist/commands/add-directory-command.d.ts +3 -0
- package/dist/commands/add-directory-command.d.ts.map +1 -0
- package/dist/commands/add-directory-command.js +85 -0
- package/dist/commands/application-log-command.d.ts.map +1 -1
- package/dist/commands/application-log-command.js +34 -0
- package/dist/commands/clear-command.d.ts.map +1 -1
- package/dist/commands/clear-command.js +8 -0
- package/dist/commands/compact-command.d.ts.map +1 -1
- package/dist/commands/compact-command.js +15 -2
- package/dist/commands/context-command.d.ts +3 -0
- package/dist/commands/context-command.d.ts.map +1 -0
- package/dist/commands/context-command.js +183 -0
- package/dist/commands/copy-command.d.ts.map +1 -1
- package/dist/commands/copy-command.js +28 -0
- package/dist/commands/edit-command.d.ts.map +1 -1
- package/dist/commands/edit-command.js +33 -0
- package/dist/commands/edit-prompt-command.d.ts.map +1 -1
- package/dist/commands/edit-prompt-command.js +28 -0
- package/dist/commands/exit-command.d.ts.map +1 -1
- package/dist/commands/exit-command.js +20 -0
- package/dist/commands/files-command.d.ts.map +1 -1
- package/dist/commands/files-command.js +57 -0
- package/dist/commands/generate-rules-command.d.ts.map +1 -1
- package/dist/commands/generate-rules-command.js +311 -1
- package/dist/commands/handoff-command.d.ts +3 -0
- package/dist/commands/handoff-command.d.ts.map +1 -0
- package/dist/commands/handoff-command.js +202 -0
- package/dist/commands/health-command.d.ts.map +1 -1
- package/dist/commands/health-command.js +119 -2
- package/dist/commands/help-command.d.ts.map +1 -1
- package/dist/commands/help-command.js +28 -0
- package/dist/commands/history-command.d.ts +3 -0
- package/dist/commands/history-command.d.ts.map +1 -0
- package/dist/commands/history-command.js +534 -0
- package/dist/commands/init-command.d.ts +1 -1
- package/dist/commands/init-command.d.ts.map +1 -1
- package/dist/commands/init-command.js +55 -18
- package/dist/commands/last-log-command.d.ts.map +1 -1
- package/dist/commands/last-log-command.js +27 -0
- package/dist/commands/list-directories-command.d.ts +3 -0
- package/dist/commands/list-directories-command.d.ts.map +1 -0
- package/dist/commands/list-directories-command.js +48 -0
- package/dist/commands/list-tools-command.d.ts.map +1 -1
- package/dist/commands/list-tools-command.js +66 -3
- package/dist/commands/manager.d.ts +15 -3
- package/dist/commands/manager.d.ts.map +1 -1
- package/dist/commands/manager.js +86 -26
- package/dist/commands/model-command.d.ts +22 -0
- package/dist/commands/model-command.d.ts.map +1 -1
- package/dist/commands/model-command.js +256 -0
- package/dist/commands/paste-command.d.ts.map +1 -1
- package/dist/commands/paste-command.js +92 -0
- package/dist/commands/pickup-command.d.ts +3 -0
- package/dist/commands/pickup-command.d.ts.map +1 -0
- package/dist/commands/pickup-command.js +161 -0
- package/dist/commands/prompt-command.d.ts +1 -1
- package/dist/commands/prompt-command.d.ts.map +1 -1
- package/dist/commands/prompt-command.js +117 -2
- package/dist/commands/remove-directory-command.d.ts +3 -0
- package/dist/commands/remove-directory-command.d.ts.map +1 -0
- package/dist/commands/remove-directory-command.js +87 -0
- package/dist/commands/reset-command.d.ts +1 -1
- package/dist/commands/reset-command.d.ts.map +1 -1
- package/dist/commands/reset-command.js +13 -2
- package/dist/commands/rules-command.d.ts.map +1 -1
- package/dist/commands/rules-command.js +65 -0
- package/dist/commands/save-command.d.ts.map +1 -1
- package/dist/commands/save-command.js +12 -0
- package/dist/commands/shell-command.d.ts.map +1 -1
- package/dist/commands/shell-command.js +68 -0
- package/dist/commands/types.d.ts +9 -4
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/commands/usage-command.d.ts.map +1 -1
- package/dist/commands/usage-command.js +22 -0
- package/dist/config.d.ts +6 -7
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +23 -29
- package/dist/formatting.d.ts +108 -0
- package/dist/formatting.d.ts.map +1 -1
- package/dist/formatting.js +147 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +140 -38
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +47 -18
- package/dist/mentions.d.ts +2 -1
- package/dist/mentions.d.ts.map +1 -1
- package/dist/mentions.js +16 -1
- package/dist/messages.d.ts +8 -0
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +56 -19
- package/dist/middleware/cache.d.ts +3 -0
- package/dist/middleware/cache.d.ts.map +1 -0
- package/dist/middleware/cache.js +53 -0
- package/dist/middleware/index.d.ts +1 -0
- package/dist/middleware/index.d.ts.map +1 -1
- package/dist/middleware/index.js +1 -0
- package/dist/models/ai-config.d.ts +4 -2
- package/dist/models/ai-config.d.ts.map +1 -1
- package/dist/models/ai-config.js +12 -2
- package/dist/models/anthropic-provider.d.ts.map +1 -1
- package/dist/models/anthropic-provider.js +3 -60
- package/dist/models/manager.d.ts +2 -1
- package/dist/models/manager.d.ts.map +1 -1
- package/dist/models/manager.js +26 -2
- package/dist/models/openrouter-provider.d.ts +7 -14
- package/dist/models/openrouter-provider.d.ts.map +1 -1
- package/dist/models/openrouter-provider.js +114 -169
- package/dist/models/providers.d.ts +1 -1
- package/dist/models/providers.d.ts.map +1 -1
- package/dist/prompts.d.ts +1 -0
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +53 -4
- package/dist/repl/display-tool-messages.d.ts +1 -1
- package/dist/repl/display-tool-messages.d.ts.map +1 -1
- package/dist/repl/display-tool-messages.js +47 -44
- package/dist/repl/get-prompt-header.d.ts.map +1 -1
- package/dist/repl/get-prompt-header.js +1 -30
- package/dist/repl/project-status-line.d.ts +2 -0
- package/dist/repl/project-status-line.d.ts.map +1 -0
- package/dist/repl/project-status-line.js +31 -0
- package/dist/repl/prompt.d.ts +21 -0
- package/dist/repl/prompt.d.ts.map +1 -0
- package/dist/{repl-prompt.js → repl/prompt.js} +119 -22
- package/dist/repl/tool-call-repair.d.ts.map +1 -1
- package/dist/repl/tool-call-repair.js +8 -4
- package/dist/repl-new.d.ts +53 -0
- package/dist/repl-new.d.ts.map +1 -0
- package/dist/repl-new.js +374 -0
- package/dist/repl.d.ts +3 -5
- package/dist/repl.d.ts.map +1 -1
- package/dist/repl.js +74 -166
- package/dist/terminal/checkbox-prompt.d.ts.map +1 -1
- package/dist/terminal/checkbox-prompt.js +10 -4
- package/dist/terminal/index.d.ts +7 -0
- package/dist/terminal/index.d.ts.map +1 -1
- package/dist/terminal/index.js +94 -0
- package/dist/terminal/input-prompt.d.ts +2 -1
- package/dist/terminal/input-prompt.d.ts.map +1 -1
- package/dist/terminal/markdown.js +3 -0
- package/dist/terminal/search-prompt.d.ts.map +1 -1
- package/dist/terminal/search-prompt.js +11 -10
- package/dist/terminal/select-prompt.d.ts +2 -2
- package/dist/terminal/select-prompt.d.ts.map +1 -1
- package/dist/terminal/select-prompt.js +47 -39
- package/dist/tokens/threshold.d.ts +35 -0
- package/dist/tokens/threshold.d.ts.map +1 -0
- package/dist/tokens/threshold.js +85 -0
- package/dist/tools/advanced-edit-file.d.ts +69 -0
- package/dist/tools/advanced-edit-file.d.ts.map +1 -0
- package/dist/tools/advanced-edit-file.js +281 -0
- package/dist/tools/agent.d.ts +16 -5
- package/dist/tools/agent.d.ts.map +1 -1
- package/dist/tools/agent.js +71 -58
- package/dist/tools/bash-utils.d.ts +1 -1
- package/dist/tools/bash-utils.d.ts.map +1 -1
- package/dist/tools/bash-utils.js +14 -6
- package/dist/tools/bash.d.ts +21 -12
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +88 -135
- package/dist/tools/code-interpreter.d.ts +21 -9
- package/dist/tools/code-interpreter.d.ts.map +1 -1
- package/dist/tools/code-interpreter.js +138 -137
- package/dist/tools/delete-file.d.ts +17 -10
- package/dist/tools/delete-file.d.ts.map +1 -1
- package/dist/tools/delete-file.js +51 -95
- package/dist/tools/directory-tree.d.ts +17 -6
- package/dist/tools/directory-tree.d.ts.map +1 -1
- package/dist/tools/directory-tree.js +47 -49
- package/dist/tools/dynamic-tool-loader.d.ts +18 -8
- package/dist/tools/dynamic-tool-loader.d.ts.map +1 -1
- package/dist/tools/dynamic-tool-loader.js +121 -129
- package/dist/tools/dynamic-tool-parser.d.ts +1 -0
- package/dist/tools/dynamic-tool-parser.d.ts.map +1 -1
- package/dist/tools/dynamic-tool-parser.js +1 -0
- package/dist/tools/edit-file.d.ts +35 -15
- package/dist/tools/edit-file.d.ts.map +1 -1
- package/dist/tools/edit-file.js +112 -112
- package/dist/tools/filesystem-utils.d.ts +2 -1
- package/dist/tools/filesystem-utils.d.ts.map +1 -1
- package/dist/tools/filesystem-utils.js +31 -17
- package/dist/tools/glob.d.ts +36 -0
- package/dist/tools/glob.d.ts.map +1 -0
- package/dist/tools/glob.js +143 -0
- package/dist/tools/grep.d.ts +73 -12
- package/dist/tools/grep.d.ts.map +1 -1
- package/dist/tools/grep.js +413 -168
- package/dist/tools/index.d.ts +204 -124
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +242 -135
- package/dist/tools/llm-edit-fixer.d.ts +25 -0
- package/dist/tools/llm-edit-fixer.d.ts.map +1 -0
- package/dist/tools/llm-edit-fixer.js +150 -0
- package/dist/tools/move-file.d.ts +19 -7
- package/dist/tools/move-file.d.ts.map +1 -1
- package/dist/tools/move-file.js +40 -33
- package/dist/tools/read-file.d.ts +47 -9
- package/dist/tools/read-file.d.ts.map +1 -1
- package/dist/tools/read-file.js +74 -69
- package/dist/tools/read-multiple-files.d.ts +17 -6
- package/dist/tools/read-multiple-files.d.ts.map +1 -1
- package/dist/tools/read-multiple-files.js +76 -73
- package/dist/tools/save-file.d.ts +45 -12
- package/dist/tools/save-file.d.ts.map +1 -1
- package/dist/tools/save-file.js +58 -101
- package/dist/tools/think.d.ts +15 -7
- package/dist/tools/think.d.ts.map +1 -1
- package/dist/tools/think.js +30 -22
- package/dist/tools/types.d.ts +4 -10
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js +9 -0
- package/dist/tools/utils.d.ts +14 -0
- package/dist/tools/utils.d.ts.map +1 -0
- package/dist/tools/utils.js +16 -0
- package/dist/tools/web-fetch.d.ts +11 -4
- package/dist/tools/web-fetch.d.ts.map +1 -1
- package/dist/tools/web-fetch.js +39 -38
- package/dist/tools/web-search.d.ts +15 -6
- package/dist/tools/web-search.d.ts.map +1 -1
- package/dist/tools/web-search.js +50 -32
- package/dist/tui/autocomplete.d.ts +44 -0
- package/dist/tui/autocomplete.d.ts.map +1 -0
- package/dist/tui/autocomplete.js +466 -0
- package/dist/tui/components/assistant-message.d.ts +18 -0
- package/dist/tui/components/assistant-message.d.ts.map +1 -0
- package/dist/tui/components/assistant-message.js +29 -0
- package/dist/tui/components/editor.d.ts +51 -0
- package/dist/tui/components/editor.d.ts.map +1 -0
- package/dist/tui/components/editor.js +758 -0
- package/dist/tui/components/footer.d.ts +24 -0
- package/dist/tui/components/footer.d.ts.map +1 -0
- package/dist/tui/components/footer.js +197 -0
- package/dist/tui/components/input.d.ts +14 -0
- package/dist/tui/components/input.d.ts.map +1 -0
- package/dist/tui/components/input.js +122 -0
- package/dist/tui/components/loader.d.ts +19 -0
- package/dist/tui/components/loader.d.ts.map +1 -0
- package/dist/tui/components/loader.js +45 -0
- package/dist/tui/components/markdown.d.ts +103 -0
- package/dist/tui/components/markdown.d.ts.map +1 -0
- package/dist/tui/components/markdown.js +533 -0
- package/dist/tui/components/modal.d.ts +40 -0
- package/dist/tui/components/modal.d.ts.map +1 -0
- package/dist/tui/components/modal.js +292 -0
- package/dist/tui/components/prompt-status.d.ts +16 -0
- package/dist/tui/components/prompt-status.d.ts.map +1 -0
- package/dist/tui/components/prompt-status.js +21 -0
- package/dist/tui/components/select-list.d.ts +22 -0
- package/dist/tui/components/select-list.d.ts.map +1 -0
- package/dist/tui/components/select-list.js +143 -0
- package/dist/tui/components/spacer.d.ts +16 -0
- package/dist/tui/components/spacer.d.ts.map +1 -0
- package/dist/tui/components/spacer.js +27 -0
- package/dist/tui/components/text.d.ts +26 -0
- package/dist/tui/components/text.d.ts.map +1 -0
- package/dist/tui/components/text.js +143 -0
- package/dist/tui/components/thinking-block.d.ts +14 -0
- package/dist/tui/components/thinking-block.d.ts.map +1 -0
- package/dist/tui/components/thinking-block.js +30 -0
- package/dist/tui/components/tool-execution.d.ts +17 -0
- package/dist/tui/components/tool-execution.d.ts.map +1 -0
- package/dist/tui/components/tool-execution.js +153 -0
- package/dist/tui/components/user-message.d.ts +9 -0
- package/dist/tui/components/user-message.d.ts.map +1 -0
- package/dist/tui/components/user-message.js +21 -0
- package/dist/tui/components/welcome.d.ts +6 -0
- package/dist/tui/components/welcome.d.ts.map +1 -0
- package/dist/tui/components/welcome.js +30 -0
- package/dist/tui/index.d.ts +14 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +18 -0
- package/dist/tui/terminal.d.ts +37 -0
- package/dist/tui/terminal.d.ts.map +1 -0
- package/dist/tui/terminal.js +104 -0
- package/dist/tui/tui.d.ts +67 -0
- package/dist/tui/tui.d.ts.map +1 -0
- package/dist/tui/tui.js +184 -0
- package/dist/tui/utils.d.ts +19 -0
- package/dist/tui/utils.d.ts.map +1 -0
- package/dist/tui/utils.js +31 -0
- package/dist/utils/generators.d.ts +3 -0
- package/dist/utils/generators.d.ts.map +1 -0
- package/dist/utils/generators.js +25 -0
- package/dist/utils/iterables.d.ts +2 -0
- package/dist/utils/iterables.d.ts.map +1 -0
- package/dist/utils/iterables.js +6 -0
- package/package.json +16 -16
- package/dist/conversation-analyzer.d.ts +0 -11
- package/dist/conversation-analyzer.d.ts.map +0 -1
- package/dist/conversation-analyzer.js +0 -88
- package/dist/repl-prompt.d.ts +0 -15
- package/dist/repl-prompt.d.ts.map +0 -1
- package/dist/tokens/manage-output.d.ts +0 -34
- package/dist/tokens/manage-output.d.ts.map +0 -1
- package/dist/tokens/manage-output.js +0 -44
- package/dist/tool-executor.d.ts +0 -28
- package/dist/tool-executor.d.ts.map +0 -1
- package/dist/tool-executor.js +0 -74
- package/dist/tools/file-editing-utils.d.ts +0 -2
- package/dist/tools/file-editing-utils.d.ts.map +0 -1
- package/dist/tools/file-editing-utils.js +0 -135
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import { text } from "node:stream/consumers";
|
|
|
3
3
|
import { parseArgs } from "node:util";
|
|
4
4
|
import { asyncTry } from "@travisennis/stdlib/try";
|
|
5
5
|
import { isDefined } from "@travisennis/stdlib/typeguards";
|
|
6
|
+
import { Agent } from "./agent/index.js";
|
|
6
7
|
import { Cli } from "./cli.js";
|
|
7
8
|
import { CommandManager } from "./commands/manager.js";
|
|
8
9
|
import { config } from "./config.js";
|
|
@@ -11,40 +12,53 @@ import { MessageHistory } from "./messages.js";
|
|
|
11
12
|
import { ModelManager } from "./models/manager.js";
|
|
12
13
|
import { isSupportedModel } from "./models/providers.js";
|
|
13
14
|
import { PromptManager } from "./prompts/manager.js";
|
|
15
|
+
import { systemPrompt } from "./prompts.js";
|
|
14
16
|
import { Repl } from "./repl.js";
|
|
17
|
+
import { NewRepl } from "./repl-new.js";
|
|
15
18
|
import { initTerminal } from "./terminal/index.js";
|
|
16
19
|
import { select } from "./terminal/select-prompt.js";
|
|
17
20
|
import { TokenCounter } from "./tokens/counter.js";
|
|
18
21
|
import { TokenTracker } from "./tokens/tracker.js";
|
|
19
|
-
import {
|
|
22
|
+
import { initAgents, initTools } from "./tools/index.js";
|
|
20
23
|
import { getPackageVersion } from "./version.js";
|
|
24
|
+
// Create workspace context from CLI arguments
|
|
25
|
+
export function createWorkspaceContext(addDirArgs = []) {
|
|
26
|
+
const primaryDir = process.cwd();
|
|
27
|
+
const allowedDirs = [primaryDir, ...addDirArgs];
|
|
28
|
+
// Remove duplicates while preserving order
|
|
29
|
+
const uniqueDirs = allowedDirs.filter((dir, index, array) => array.indexOf(dir) === index);
|
|
30
|
+
return {
|
|
31
|
+
primaryDir,
|
|
32
|
+
allowedDirs: uniqueDirs,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
21
35
|
const helpText = `
|
|
22
36
|
Usage
|
|
23
37
|
$ acai <input>
|
|
24
38
|
|
|
25
39
|
Options
|
|
26
40
|
--model, -m Sets the model to use
|
|
27
|
-
--prompt, -p Sets the prompt
|
|
28
|
-
--oneshot, -o Run once and exit
|
|
41
|
+
--prompt, -p Sets the prompt (runs in CLI mode)
|
|
29
42
|
--continue Load the most recent conversation
|
|
30
43
|
--resume Select a recent conversation to resume
|
|
31
|
-
--
|
|
44
|
+
--add-dir Add additional working directory (can be used multiple times)
|
|
45
|
+
--new-repl
|
|
32
46
|
--help, -h Show help
|
|
33
47
|
--version, -v Show version
|
|
34
48
|
|
|
35
49
|
Examples
|
|
36
50
|
$ acai --model anthopric:sonnet
|
|
37
51
|
$ acai -p "initial prompt"
|
|
38
|
-
$ acai -
|
|
52
|
+
$ acai --add-dir /path/to/project1 --add-dir /path/to/project2
|
|
39
53
|
`;
|
|
40
54
|
const parsed = parseArgs({
|
|
41
55
|
options: {
|
|
42
56
|
model: { type: "string", short: "m" },
|
|
43
57
|
prompt: { type: "string", short: "p" },
|
|
44
|
-
oneshot: { type: "boolean", short: "o", default: false },
|
|
45
58
|
continue: { type: "boolean", default: false },
|
|
46
59
|
resume: { type: "boolean", default: false },
|
|
47
|
-
|
|
60
|
+
"add-dir": { type: "string", multiple: true },
|
|
61
|
+
"new-repl": { type: "boolean" },
|
|
48
62
|
help: { type: "boolean", short: "h" },
|
|
49
63
|
version: { type: "boolean", short: "v" },
|
|
50
64
|
},
|
|
@@ -52,6 +66,8 @@ const parsed = parseArgs({
|
|
|
52
66
|
});
|
|
53
67
|
const flags = parsed.values;
|
|
54
68
|
const input = parsed.positionals;
|
|
69
|
+
// Create workspace context from CLI arguments
|
|
70
|
+
const workspace = createWorkspaceContext(flags["add-dir"]);
|
|
55
71
|
/**
|
|
56
72
|
* Global error handler function.
|
|
57
73
|
* @param {Error} error - The error to be handled.
|
|
@@ -78,10 +94,6 @@ async function main() {
|
|
|
78
94
|
process.exit(1);
|
|
79
95
|
}
|
|
80
96
|
const hasContinueOrResume = flags.continue === true || flags.resume === true;
|
|
81
|
-
if (hasContinueOrResume && flags.oneshot === true) {
|
|
82
|
-
console.error("Cannot use --continue or --resume with --oneshot.");
|
|
83
|
-
process.exit(1);
|
|
84
|
-
}
|
|
85
97
|
// --- Determine Initial Prompt (potential conflict) ---
|
|
86
98
|
const positionalPrompt = input.at(0);
|
|
87
99
|
let stdInPrompt;
|
|
@@ -105,10 +117,10 @@ async function main() {
|
|
|
105
117
|
process.exit(1);
|
|
106
118
|
}
|
|
107
119
|
const terminal = initTerminal();
|
|
108
|
-
terminal.setTitle(`acai: ${
|
|
120
|
+
terminal.setTitle(`acai: ${workspace.primaryDir}`);
|
|
109
121
|
const chosenModel = isSupportedModel(flags.model)
|
|
110
122
|
? flags.model
|
|
111
|
-
: "openrouter:glm-4.
|
|
123
|
+
: "openrouter:glm-4.6";
|
|
112
124
|
const modelManager = new ModelManager({
|
|
113
125
|
stateDir: await appDir.ensurePath("audit"),
|
|
114
126
|
});
|
|
@@ -119,7 +131,9 @@ async function main() {
|
|
|
119
131
|
modelManager.setModel("tool-repair", "openai:gpt-4.1");
|
|
120
132
|
modelManager.setModel("conversation-analyzer", "openrouter:gemini-flash25");
|
|
121
133
|
modelManager.setModel("init-project", chosenModel);
|
|
122
|
-
modelManager.setModel("task-agent", "openrouter:
|
|
134
|
+
modelManager.setModel("task-agent", "openrouter:gpt-5-mini");
|
|
135
|
+
modelManager.setModel("handoff-agent", chosenModel);
|
|
136
|
+
modelManager.setModel("edit-fix", "openrouter:gemini-flash25");
|
|
123
137
|
const tokenTracker = new TokenTracker();
|
|
124
138
|
const tokenCounter = new TokenCounter();
|
|
125
139
|
const messageHistory = new MessageHistory({
|
|
@@ -144,31 +158,44 @@ async function main() {
|
|
|
144
158
|
else if (flags.resume === true) {
|
|
145
159
|
const histories = await MessageHistory.load(messageHistoryDir, 10);
|
|
146
160
|
if (histories.length > 0) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
+
try {
|
|
162
|
+
const choice = await select({
|
|
163
|
+
message: "Select a conversation to resume:",
|
|
164
|
+
choices: histories.map((h, index) => ({
|
|
165
|
+
name: `${index + 1}: ${h.title} (${h.updatedAt.toLocaleString()})`,
|
|
166
|
+
value: index,
|
|
167
|
+
description: `${h.messages.length} messages`,
|
|
168
|
+
})),
|
|
169
|
+
});
|
|
170
|
+
const selectedHistory = histories.at(choice);
|
|
171
|
+
if (selectedHistory) {
|
|
172
|
+
messageHistory.restore(selectedHistory);
|
|
173
|
+
logger.info(`Resuming conversation: ${selectedHistory.title}`);
|
|
174
|
+
// Set terminal title after restoring
|
|
175
|
+
terminal.setTitle(selectedHistory.title || `acai: ${process.cwd()}`);
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
// This case should theoretically not happen if choice is valid
|
|
179
|
+
logger.error("Selected history index out of bounds.");
|
|
180
|
+
}
|
|
161
181
|
}
|
|
162
|
-
|
|
163
|
-
//
|
|
164
|
-
|
|
182
|
+
catch (error) {
|
|
183
|
+
// Handle Ctrl-C cancellation
|
|
184
|
+
if (error instanceof Error &&
|
|
185
|
+
"isCanceled" in error &&
|
|
186
|
+
error.isCanceled === true) {
|
|
187
|
+
logger.info("Resume selection cancelled.");
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
// Re-throw other errors
|
|
191
|
+
throw error;
|
|
192
|
+
}
|
|
165
193
|
}
|
|
166
194
|
}
|
|
167
195
|
else {
|
|
168
196
|
logger.info("No previous conversations found to resume.");
|
|
169
197
|
}
|
|
170
198
|
}
|
|
171
|
-
const toolExecutor = new ToolExecutor(flags.autoAcceptAll === true);
|
|
172
199
|
// --- Setup Prompt Manager (only if not continuing/resuming) ---
|
|
173
200
|
const promptManager = new PromptManager(tokenCounter);
|
|
174
201
|
if (!hasContinueOrResume && isDefined(initialPromptInput)) {
|
|
@@ -177,7 +204,6 @@ async function main() {
|
|
|
177
204
|
if (stdInPrompt) {
|
|
178
205
|
promptManager.addContext(stdInPrompt);
|
|
179
206
|
}
|
|
180
|
-
const toolEvents = new Map();
|
|
181
207
|
const promptHistory = [];
|
|
182
208
|
const commands = new CommandManager({
|
|
183
209
|
promptManager,
|
|
@@ -187,12 +213,11 @@ async function main() {
|
|
|
187
213
|
tokenTracker,
|
|
188
214
|
config,
|
|
189
215
|
tokenCounter,
|
|
190
|
-
toolExecutor,
|
|
191
|
-
toolEvents,
|
|
192
216
|
promptHistory,
|
|
217
|
+
workspace,
|
|
193
218
|
});
|
|
194
219
|
await commands.initializeCommmands();
|
|
195
|
-
if (
|
|
220
|
+
if (isDefined(initialPromptInput)) {
|
|
196
221
|
const cliProcess = new Cli({
|
|
197
222
|
promptManager,
|
|
198
223
|
config: appConfig,
|
|
@@ -200,9 +225,87 @@ async function main() {
|
|
|
200
225
|
modelManager,
|
|
201
226
|
tokenTracker,
|
|
202
227
|
tokenCounter,
|
|
228
|
+
workspace,
|
|
203
229
|
});
|
|
204
230
|
return (await asyncTry(cliProcess.run())).recover(handleError);
|
|
205
231
|
}
|
|
232
|
+
const agent = new Agent({
|
|
233
|
+
messageHistory,
|
|
234
|
+
modelManager,
|
|
235
|
+
tokenTracker,
|
|
236
|
+
});
|
|
237
|
+
if (flags["new-repl"]) {
|
|
238
|
+
const repl = new NewRepl({
|
|
239
|
+
agent,
|
|
240
|
+
promptManager,
|
|
241
|
+
terminal,
|
|
242
|
+
config: appConfig,
|
|
243
|
+
messageHistory,
|
|
244
|
+
modelManager,
|
|
245
|
+
tokenTracker,
|
|
246
|
+
commands,
|
|
247
|
+
tokenCounter,
|
|
248
|
+
promptHistory,
|
|
249
|
+
workspace,
|
|
250
|
+
});
|
|
251
|
+
// Initialize TUI
|
|
252
|
+
await repl.init();
|
|
253
|
+
messageHistory.on("clear-history", () => {
|
|
254
|
+
logger.info("Resetting agent state.");
|
|
255
|
+
agent.resetState();
|
|
256
|
+
repl.rerender();
|
|
257
|
+
});
|
|
258
|
+
// Set interrupt callback
|
|
259
|
+
repl.setInterruptCallback(() => {
|
|
260
|
+
agent.abort();
|
|
261
|
+
});
|
|
262
|
+
// Render any existing messages (from --continue mode)
|
|
263
|
+
// repl.renderInitialMessages(agent.state);
|
|
264
|
+
// Initialize tools once outside the loop - all models support tool calling
|
|
265
|
+
const coreTools = await initTools({
|
|
266
|
+
tokenCounter,
|
|
267
|
+
workspace,
|
|
268
|
+
modelManager,
|
|
269
|
+
tokenTracker,
|
|
270
|
+
});
|
|
271
|
+
const agentTools = await initAgents({
|
|
272
|
+
terminal,
|
|
273
|
+
modelManager,
|
|
274
|
+
tokenTracker,
|
|
275
|
+
tokenCounter,
|
|
276
|
+
workspace,
|
|
277
|
+
});
|
|
278
|
+
const completeToolDefs = {
|
|
279
|
+
...coreTools.toolDefs,
|
|
280
|
+
...agentTools.toolDefs,
|
|
281
|
+
};
|
|
282
|
+
const tools = {
|
|
283
|
+
toolDefs: completeToolDefs,
|
|
284
|
+
executors: new Map([...coreTools.executors, ...agentTools.executors]),
|
|
285
|
+
};
|
|
286
|
+
// Interactive loop
|
|
287
|
+
while (true) {
|
|
288
|
+
const userInput = await repl.getUserInput();
|
|
289
|
+
// Process the message - agent.prompt will add user message and trigger state updates
|
|
290
|
+
try {
|
|
291
|
+
const results = agent.run({
|
|
292
|
+
systemPrompt: await systemPrompt(),
|
|
293
|
+
input: userInput,
|
|
294
|
+
toolDefs: tools.toolDefs,
|
|
295
|
+
executors: tools.executors,
|
|
296
|
+
abortSignal: agent.abortSignal,
|
|
297
|
+
});
|
|
298
|
+
for await (const result of results) {
|
|
299
|
+
repl.handle(result, agent.state);
|
|
300
|
+
}
|
|
301
|
+
messageHistory.save();
|
|
302
|
+
}
|
|
303
|
+
catch (_error) {
|
|
304
|
+
// Display error in the TUI by adding an error message to the chat
|
|
305
|
+
// repl.showError((error as Error).message || "Unknown error occurred");
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
206
309
|
const repl = new Repl({
|
|
207
310
|
promptManager,
|
|
208
311
|
terminal,
|
|
@@ -212,9 +315,8 @@ async function main() {
|
|
|
212
315
|
tokenTracker,
|
|
213
316
|
commands,
|
|
214
317
|
tokenCounter,
|
|
215
|
-
toolEvents,
|
|
216
|
-
toolExecutor,
|
|
217
318
|
promptHistory,
|
|
319
|
+
workspace,
|
|
218
320
|
showLastMessage: hasContinueOrResume
|
|
219
321
|
? !!(messageHistory.get() && messageHistory.get().length > 0)
|
|
220
322
|
: false,
|
package/dist/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../source/logger.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../source/logger.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,MAAM,CAAC;AAwDxB,eAAO,MAAM,MAAM,6BAIjB,CAAC"}
|
package/dist/logger.js
CHANGED
|
@@ -1,24 +1,53 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
import pino from "pino";
|
|
3
3
|
import { config } from "./config.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
// Create a lazy logger factory that only initializes when first used
|
|
5
|
+
let loggerInstance = null;
|
|
6
|
+
function createLogger() {
|
|
7
|
+
// Check if we're running in code interpreter context
|
|
8
|
+
// Try multiple detection methods:
|
|
9
|
+
// 1. Environment variable (primary method)
|
|
10
|
+
// 2. Check if we're running with Node.js permissions (fallback)
|
|
11
|
+
const isCodeInterpreter = process.env["ACAI_CODE_INTERPRETER"] === "true" ||
|
|
12
|
+
(typeof process.permission !== "undefined" &&
|
|
13
|
+
process.permission.has !== undefined);
|
|
14
|
+
if (isCodeInterpreter) {
|
|
15
|
+
// In code interpreter context, use a no-op logger to avoid noise in script output
|
|
16
|
+
return pino({
|
|
17
|
+
level: "silent", // Completely disable logging
|
|
18
|
+
enabled: false, // Disable the logger entirely
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
// Normal file-based logging
|
|
22
|
+
return pino({
|
|
23
|
+
level: process.env["LOG_LEVEL"] ?? "debug",
|
|
24
|
+
formatters: {
|
|
25
|
+
level: (label) => {
|
|
26
|
+
return { level: label.toUpperCase() };
|
|
27
|
+
},
|
|
12
28
|
},
|
|
13
|
-
|
|
14
|
-
},
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
29
|
+
timestamp: pino.stdTimeFunctions.isoTime,
|
|
30
|
+
}, pino.transport({
|
|
31
|
+
target: "pino-roll",
|
|
32
|
+
options: {
|
|
33
|
+
file: join(config.app.ensurePathSync("logs"), "acai.log"),
|
|
34
|
+
size: "10m",
|
|
35
|
+
symlink: true,
|
|
36
|
+
limit: {
|
|
37
|
+
count: 3,
|
|
38
|
+
},
|
|
39
|
+
mkdir: true,
|
|
21
40
|
},
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
function getLogger() {
|
|
44
|
+
if (!loggerInstance) {
|
|
45
|
+
loggerInstance = createLogger();
|
|
46
|
+
}
|
|
47
|
+
return loggerInstance;
|
|
48
|
+
}
|
|
49
|
+
export const logger = new Proxy({}, {
|
|
50
|
+
get(_target, prop) {
|
|
51
|
+
return getLogger()[prop];
|
|
22
52
|
},
|
|
23
|
-
|
|
24
|
-
}, transport);
|
|
53
|
+
});
|
package/dist/mentions.d.ts
CHANGED
|
@@ -3,9 +3,10 @@ import type { ContextItem } from "./prompts/manager.ts";
|
|
|
3
3
|
export declare class PromptError extends Error {
|
|
4
4
|
constructor(message: string, cause?: Error);
|
|
5
5
|
}
|
|
6
|
-
export declare function processPrompt(message: string, { baseDir, model }: {
|
|
6
|
+
export declare function processPrompt(message: string, { baseDir, model, pasteStore, }: {
|
|
7
7
|
baseDir: string;
|
|
8
8
|
model: ModelMetadata;
|
|
9
|
+
pasteStore?: Map<number, string>;
|
|
9
10
|
}): Promise<{
|
|
10
11
|
message: string;
|
|
11
12
|
context: ContextItem[];
|
package/dist/mentions.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mentions.d.ts","sourceRoot":"","sources":["../source/mentions.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAsBxD,qBAAa,WAAY,SAAQ,KAAK;gBACxB,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAI3C;AA+JD,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,
|
|
1
|
+
{"version":3,"file":"mentions.d.ts","sourceRoot":"","sources":["../source/mentions.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAsBxD,qBAAa,WAAY,SAAQ,KAAK;gBACxB,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAI3C;AA+JD,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,EACE,OAAO,EACP,KAAK,EACL,UAAU,GACX,EAAE;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,aAAa,CAAC;IACrB,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,GACA,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,WAAW,EAAE,CAAA;CAAE,CAAC,CA8GtD"}
|
package/dist/mentions.js
CHANGED
|
@@ -137,7 +137,7 @@ async function processUrlCommand(context) {
|
|
|
137
137
|
};
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
|
-
export async function processPrompt(message, { baseDir, model }) {
|
|
140
|
+
export async function processPrompt(message, { baseDir, model, pasteStore, }) {
|
|
141
141
|
const fileRegex = /@([^\s@]+(?:\.[\w\d]+))/g;
|
|
142
142
|
const urlRegex = /@(https?:\/\/[^\s]+)/g;
|
|
143
143
|
const shellRegex = /!`([^`]+)`/g;
|
|
@@ -171,6 +171,21 @@ export async function processPrompt(message, { baseDir, model }) {
|
|
|
171
171
|
}
|
|
172
172
|
}
|
|
173
173
|
let processedMessage = message;
|
|
174
|
+
// Process paste placeholders
|
|
175
|
+
if (pasteStore && pasteStore.size > 0) {
|
|
176
|
+
const pasteRegex = /\[Paste #(\d+), (\d+) characters\]/g;
|
|
177
|
+
let match = pasteRegex.exec(processedMessage);
|
|
178
|
+
while (match !== null) {
|
|
179
|
+
const pasteId = Number.parseInt(match[1], 10);
|
|
180
|
+
const pasteContent = pasteStore.get(pasteId);
|
|
181
|
+
if (pasteContent) {
|
|
182
|
+
processedMessage = processedMessage.replace(match[0], pasteContent);
|
|
183
|
+
// Reset regex lastIndex since we modified the string
|
|
184
|
+
pasteRegex.lastIndex = 0;
|
|
185
|
+
}
|
|
186
|
+
match = pasteRegex.exec(processedMessage);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
174
189
|
// Process shell commands
|
|
175
190
|
for (const match of shellMatches) {
|
|
176
191
|
const command = match[1];
|
package/dist/messages.d.ts
CHANGED
|
@@ -11,6 +11,9 @@ It can be either an assistant message or a tool message.
|
|
|
11
11
|
*/
|
|
12
12
|
type ResponseMessage = AssistantModelMessage | ToolModelMessage;
|
|
13
13
|
type SavedMessageHistory = {
|
|
14
|
+
project: string;
|
|
15
|
+
sessionId: string;
|
|
16
|
+
modelId: string;
|
|
14
17
|
title: string;
|
|
15
18
|
createdAt: Date;
|
|
16
19
|
updatedAt: Date;
|
|
@@ -22,6 +25,8 @@ interface MessageHistoryEvents {
|
|
|
22
25
|
}
|
|
23
26
|
export declare class MessageHistory extends EventEmitter<MessageHistoryEvents> {
|
|
24
27
|
private history;
|
|
28
|
+
private sessionId;
|
|
29
|
+
private modelId;
|
|
25
30
|
private title;
|
|
26
31
|
private createdAt;
|
|
27
32
|
private updatedAt;
|
|
@@ -33,6 +38,7 @@ export declare class MessageHistory extends EventEmitter<MessageHistoryEvents> {
|
|
|
33
38
|
modelManager: ModelManager;
|
|
34
39
|
tokenTracker: TokenTracker;
|
|
35
40
|
});
|
|
41
|
+
create(modelId: string): void;
|
|
36
42
|
private validMessage;
|
|
37
43
|
get(): ModelMessage[];
|
|
38
44
|
clear(): void;
|
|
@@ -40,11 +46,13 @@ export declare class MessageHistory extends EventEmitter<MessageHistoryEvents> {
|
|
|
40
46
|
appendUserMessage(msg: UserModelMessage): void;
|
|
41
47
|
appendAssistantMessage(msg: string): void;
|
|
42
48
|
appendAssistantMessage(msg: AssistantModelMessage): void;
|
|
49
|
+
appendToolMessages(toolResultMessages: ToolModelMessage[]): void;
|
|
43
50
|
appendResponseMessages(responseMessages: ResponseMessage[]): void;
|
|
44
51
|
isEmpty(): boolean;
|
|
45
52
|
save(): Promise<void>;
|
|
46
53
|
private generateTitle;
|
|
47
54
|
getFirstUserMessage(): UserModelMessage | undefined;
|
|
55
|
+
getLastUserMessage(): UserModelMessage | undefined;
|
|
48
56
|
/**
|
|
49
57
|
* Extracts the last message from the conversation history for display purposes.
|
|
50
58
|
* Prioritizes assistant messages, falls back to user messages if no assistant messages exist.
|
package/dist/messages.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../source/messages.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../source/messages.ts"],"names":[],"mappings":"AACA,OAAO,YAAY,MAAM,aAAa,CAAC;AAIvC,OAAO,EACL,KAAK,qBAAqB,EAE1B,KAAK,SAAS,EAAE,kBAAkB;AAClC,KAAK,YAAY,EAEjB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACtB,MAAM,IAAI,CAAC;AACZ,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,SAAS,CAAC;AAExD,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,sBAAsB,EAAE,EACtC,MAAM,CAAC,EAAE,MAAM,GACd,gBAAgB,CAuBlB;AAcD;;;GAGG;AACH,KAAK,eAAe,GAAG,qBAAqB,GAAG,gBAAgB,CAAC;AAEhE,KAAK,mBAAmB,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B,CAAC;AAUF,UAAU,oBAAoB;IAC5B,cAAc,EAAE,CAAC,MAAM,CAAC,CAAC;IACzB,eAAe,EAAE,EAAE,CAAC;CACrB;AAED,qBAAa,cAAe,SAAQ,YAAY,CAAC,oBAAoB,CAAC;IACpE,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,SAAS,CAAO;IACxB,OAAO,CAAC,SAAS,CAAO;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,YAAY,CAAe;gBAEvB,EACV,QAAQ,EACR,YAAY,EACZ,YAAY,GACb,EAAE;QACD,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,YAAY,CAAC;QAC3B,YAAY,EAAE,YAAY,CAAC;KAC5B;IAaD,MAAM,CAAC,OAAO,EAAE,MAAM;IAStB,OAAO,CAAC,YAAY;IAoBpB,GAAG;IAIH,KAAK;IAKL,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IACpC,iBAAiB,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI;IAmB9C,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IACzC,sBAAsB,CAAC,GAAG,EAAE,qBAAqB,GAAG,IAAI;IAOxD,kBAAkB,CAAC,kBAAkB,EAAE,gBAAgB,EAAE;IAKzD,sBAAsB,CAAC,gBAAgB,EAAE,eAAe,EAAE;IAO1D,OAAO;IAID,IAAI;YAoBI,aAAa;IA6B3B,mBAAmB,IAAI,gBAAgB,GAAG,SAAS;IAOnD,kBAAkB,IAAI,gBAAgB,GAAG,SAAS;IAOlD;;;OAGG;IACH,cAAc,IAAI,MAAM,GAAG,IAAI;WA2ClB,IAAI,CACf,QAAQ,EAAE,MAAM,EAChB,KAAK,SAAK,GACT,OAAO,CAAC,mBAAmB,EAAE,CAAC;IA6EjC,OAAO,CAAC,YAAY,EAAE,mBAAmB,GAAG,IAAI;CAajD"}
|
package/dist/messages.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
1
2
|
import EventEmitter from "node:events";
|
|
2
|
-
import { readdir, readFile, writeFile } from "node:fs/promises";
|
|
3
|
-
import { join } from "node:path";
|
|
3
|
+
import { readdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
4
|
+
import { basename, join } from "node:path";
|
|
4
5
|
import { isString } from "@travisennis/stdlib/typeguards";
|
|
5
6
|
import { generateText, } from "ai";
|
|
6
7
|
export function createUserMessage(contentItems, prompt) {
|
|
@@ -38,6 +39,8 @@ function createAssistantMessage(content) {
|
|
|
38
39
|
}
|
|
39
40
|
export class MessageHistory extends EventEmitter {
|
|
40
41
|
history;
|
|
42
|
+
sessionId;
|
|
43
|
+
modelId;
|
|
41
44
|
title;
|
|
42
45
|
createdAt;
|
|
43
46
|
updatedAt;
|
|
@@ -47,6 +50,8 @@ export class MessageHistory extends EventEmitter {
|
|
|
47
50
|
constructor({ stateDir, modelManager, tokenTracker, }) {
|
|
48
51
|
super();
|
|
49
52
|
this.history = [];
|
|
53
|
+
this.sessionId = randomUUID();
|
|
54
|
+
this.modelId = "";
|
|
50
55
|
this.title = "";
|
|
51
56
|
this.createdAt = new Date();
|
|
52
57
|
this.updatedAt = new Date();
|
|
@@ -54,6 +59,14 @@ export class MessageHistory extends EventEmitter {
|
|
|
54
59
|
this.modelManager = modelManager;
|
|
55
60
|
this.tokenTracker = tokenTracker;
|
|
56
61
|
}
|
|
62
|
+
create(modelId) {
|
|
63
|
+
this.clear();
|
|
64
|
+
this.modelId = modelId;
|
|
65
|
+
this.sessionId = randomUUID();
|
|
66
|
+
this.title = "";
|
|
67
|
+
this.createdAt = new Date();
|
|
68
|
+
this.updatedAt = new Date();
|
|
69
|
+
}
|
|
57
70
|
validMessage(msg) {
|
|
58
71
|
// Filter out messages with empty content arrays
|
|
59
72
|
if (Array.isArray(msg.content) && msg.content.length === 0) {
|
|
@@ -96,6 +109,10 @@ export class MessageHistory extends EventEmitter {
|
|
|
96
109
|
const msgObj = isString(msg) ? createAssistantMessage(msg) : msg;
|
|
97
110
|
this.history.push(msgObj);
|
|
98
111
|
}
|
|
112
|
+
appendToolMessages(toolResultMessages) {
|
|
113
|
+
this.updatedAt = new Date();
|
|
114
|
+
this.history.push(...toolResultMessages);
|
|
115
|
+
}
|
|
99
116
|
appendResponseMessages(responseMessages) {
|
|
100
117
|
this.updatedAt = new Date();
|
|
101
118
|
// Filter out messages with empty content arrays
|
|
@@ -107,10 +124,13 @@ export class MessageHistory extends EventEmitter {
|
|
|
107
124
|
}
|
|
108
125
|
async save() {
|
|
109
126
|
const msgHistoryDir = this.stateDir;
|
|
110
|
-
const
|
|
111
|
-
const fileName = `message-history-${timestamp}.json`;
|
|
127
|
+
const fileName = `message-history-${this.sessionId}.json`;
|
|
112
128
|
const filePath = join(msgHistoryDir, fileName);
|
|
129
|
+
const project = basename(process.cwd());
|
|
113
130
|
const output = {
|
|
131
|
+
project,
|
|
132
|
+
sessionId: this.sessionId,
|
|
133
|
+
modelId: this.modelId,
|
|
114
134
|
title: this.title,
|
|
115
135
|
createdAt: this.createdAt,
|
|
116
136
|
updatedAt: this.updatedAt,
|
|
@@ -129,6 +149,7 @@ export class MessageHistory extends EventEmitter {
|
|
|
129
149
|
const { text, usage } = await generateText({
|
|
130
150
|
model: this.modelManager.getModel(app),
|
|
131
151
|
system: systemPrompt,
|
|
152
|
+
maxOutputTokens: 100,
|
|
132
153
|
prompt: `Request:\n${message}\nTitle:`,
|
|
133
154
|
});
|
|
134
155
|
this.tokenTracker.trackUsage(app, usage);
|
|
@@ -145,6 +166,10 @@ export class MessageHistory extends EventEmitter {
|
|
|
145
166
|
const firstUser = this.get().find((msg) => msg.role === "user");
|
|
146
167
|
return firstUser;
|
|
147
168
|
}
|
|
169
|
+
getLastUserMessage() {
|
|
170
|
+
const userMsg = this.history.findLast((value) => value.role === "user");
|
|
171
|
+
return userMsg;
|
|
172
|
+
}
|
|
148
173
|
/**
|
|
149
174
|
* Extracts the last message from the conversation history for display purposes.
|
|
150
175
|
* Prioritizes assistant messages, falls back to user messages if no assistant messages exist.
|
|
@@ -180,16 +205,31 @@ export class MessageHistory extends EventEmitter {
|
|
|
180
205
|
static async load(stateDir, count = 10) {
|
|
181
206
|
try {
|
|
182
207
|
const files = await readdir(stateDir);
|
|
183
|
-
const messageHistoryFiles = files
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
208
|
+
const messageHistoryFiles = files.filter((file) => file.startsWith("message-history-") && file.endsWith(".json"));
|
|
209
|
+
// Get file stats and sort by modification time (newest first)
|
|
210
|
+
const fileStatsPromises = messageHistoryFiles.map(async (fileName) => {
|
|
211
|
+
const filePath = join(stateDir, fileName);
|
|
212
|
+
try {
|
|
213
|
+
const fileStat = await stat(filePath);
|
|
214
|
+
return {
|
|
215
|
+
fileName,
|
|
216
|
+
filePath,
|
|
217
|
+
modifiedTime: fileStat.mtime,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
console.error(`Error getting stats for file ${filePath}:`, error);
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
const fileStats = await Promise.all(fileStatsPromises);
|
|
226
|
+
// Filter out null results and sort by modification time (newest first)
|
|
227
|
+
const sortedFiles = fileStats
|
|
228
|
+
.filter((stat) => stat !== null)
|
|
229
|
+
.sort((a, b) => b.modifiedTime.getTime() - a.modifiedTime.getTime())
|
|
230
|
+
.slice(0, count)
|
|
231
|
+
.map((stat) => stat.fileName);
|
|
232
|
+
const fileReadPromises = sortedFiles.map(async (fileName) => {
|
|
193
233
|
const filePath = join(stateDir, fileName);
|
|
194
234
|
try {
|
|
195
235
|
const content = await readFile(filePath, "utf-8");
|
|
@@ -209,11 +249,8 @@ export class MessageHistory extends EventEmitter {
|
|
|
209
249
|
return null; // Return null for failed reads/parses
|
|
210
250
|
});
|
|
211
251
|
const results = await Promise.all(fileReadPromises);
|
|
212
|
-
// Filter out null results (
|
|
213
|
-
|
|
214
|
-
return results
|
|
215
|
-
.filter((result) => result !== null)
|
|
216
|
-
.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
|
|
252
|
+
// Filter out null results and return them (already sorted by file modification time)
|
|
253
|
+
return results.filter((result) => result !== null);
|
|
217
254
|
}
|
|
218
255
|
catch (error) {
|
|
219
256
|
// Handle cases where the directory might not exist or other readdir errors
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../source/middleware/cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EAE1B,MAAM,kBAAkB,CAAC;AAsB1B,eAAO,MAAM,eAAe,EAAE,yBAyC7B,CAAC"}
|