@travisennis/acai 0.0.1 → 0.0.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.
- package/README.md +3 -4
- package/dist/commands/health-command.d.ts +2 -0
- package/dist/commands/health-command.js +59 -0
- package/dist/commands/manager.js +2 -0
- package/dist/commands/paste-command.d.ts +1 -1
- package/dist/commands/paste-command.js +155 -11
- package/dist/commands/reset-command.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -1
- package/dist/models/openrouter-provider.d.ts +4 -1
- package/dist/models/openrouter-provider.js +46 -4
- package/dist/models/providers.d.ts +1 -1
- package/dist/prompts/manager.d.ts +1 -0
- package/dist/prompts/manager.js +10 -0
- package/dist/prompts.js +8 -6
- package/dist/repl.js +49 -26
- package/dist/terminal/formatting.d.ts +16 -5
- package/dist/terminal/formatting.js +40 -6
- package/dist/terminal/index.d.ts +1 -1
- package/dist/terminal/index.js +54 -14
- package/dist/terminal/markdown.js +0 -1
- package/dist/terminal/supports-color.d.ts +16 -0
- package/dist/terminal/supports-color.js +121 -0
- package/dist/terminal/supports-hyperlinks.d.ts +7 -0
- package/dist/terminal/supports-hyperlinks.js +98 -0
- package/dist/tools/bash.js +95 -117
- package/dist/tools/code-interpreter.js +11 -1
- package/dist/tools/command-validation.d.ts +7 -3
- package/dist/tools/command-validation.js +67 -23
- package/dist/tools/delete-file.d.ts +4 -1
- package/dist/tools/delete-file.js +47 -3
- package/dist/tools/git-utils.d.ts +6 -0
- package/dist/tools/git-utils.js +89 -12
- package/dist/tools/grep.d.ts +20 -0
- package/dist/tools/grep.js +128 -40
- package/dist/tools/index.d.ts +2 -18
- package/dist/tools/index.js +4 -18
- package/package.json +30 -20
- package/.acai/acai.json +0 -9
- package/.acai/prompts/add-openrouter-model.md +0 -13
- package/.acai/prompts/project-status.md +0 -4
- package/.acai/prompts/update-architecture-document.md +0 -9
- package/.acai/rules/learned-rules.md +0 -9
- package/.ai/docs/available-tools.txt +0 -3
- package/.ai/docs/cognitive_complexity_refactoring_progress.md +0 -65
- package/.ai/docs/deleted_tools.md +0 -168
- package/.ai/docs/deleted_tools_88ced9ef.md +0 -56
- package/.ai/docs/image-pasting.md +0 -46
- package/.ai/docs/initialize-app.md +0 -117
- package/.ai/docs/issue-4-plan.md +0 -44
- package/.ai/docs/marked-renderer-debug.md +0 -15
- package/.ai/docs/marked-renderer-refactor-plan.md +0 -64
- package/.ai/docs/memory-use-cases.md +0 -55
- package/.ai/docs/prompt-consistency.md +0 -31
- package/.ai/docs/refactoring-tools.md +0 -98
- package/.ai/docs/system-prompt-update.md +0 -174
- package/.ai/docs/system_prompt.txt +0 -210
- package/.ai/docs/tasks.md +0 -49
- package/.ai/plan.md +0 -131
- package/.ai/prompt.md +0 -1
- package/.ai/scripts/fetch_models.js +0 -27
- package/.ai/scripts/generateSystemPrompt.ts +0 -15
- package/.ai/scripts/list-tools.mjs +0 -4
- package/.ai/scripts/p5_geometric_shapes.js +0 -149
- package/.husky/commit-msg +0 -1
- package/.husky/pre-commit +0 -3
- package/.husky/pre-push +0 -1
- package/.ignore +0 -4
- package/AGENTS.md +0 -25
- package/ARCHITECTURE.md +0 -304
- package/TODO.md +0 -2
- package/biome.json +0 -61
- package/commitlint.config.js +0 -3
- package/dist/source/cli.d.ts +0 -19
- package/dist/source/cli.js +0 -116
- package/dist/source/commands/application-log-command.d.ts +0 -2
- package/dist/source/commands/application-log-command.js +0 -43
- package/dist/source/commands/clear-command.d.ts +0 -2
- package/dist/source/commands/clear-command.js +0 -12
- package/dist/source/commands/compact-command.d.ts +0 -2
- package/dist/source/commands/compact-command.js +0 -51
- package/dist/source/commands/copy-command.d.ts +0 -2
- package/dist/source/commands/copy-command.js +0 -51
- package/dist/source/commands/edit-command.d.ts +0 -2
- package/dist/source/commands/edit-command.js +0 -53
- package/dist/source/commands/edit-prompt-command.d.ts +0 -2
- package/dist/source/commands/edit-prompt-command.js +0 -25
- package/dist/source/commands/exit-command.d.ts +0 -2
- package/dist/source/commands/exit-command.js +0 -14
- package/dist/source/commands/files-command.d.ts +0 -2
- package/dist/source/commands/files-command.js +0 -63
- package/dist/source/commands/generate-rules-command.d.ts +0 -2
- package/dist/source/commands/generate-rules-command.js +0 -61
- package/dist/source/commands/help-command.d.ts +0 -2
- package/dist/source/commands/help-command.js +0 -19
- package/dist/source/commands/init-command.d.ts +0 -2
- package/dist/source/commands/init-command.js +0 -40
- package/dist/source/commands/last-log-command.d.ts +0 -2
- package/dist/source/commands/last-log-command.js +0 -76
- package/dist/source/commands/manager.d.ts +0 -22
- package/dist/source/commands/manager.js +0 -123
- package/dist/source/commands/model-command.d.ts +0 -2
- package/dist/source/commands/model-command.js +0 -84
- package/dist/source/commands/paste-command.d.ts +0 -2
- package/dist/source/commands/paste-command.js +0 -40
- package/dist/source/commands/prompt-command.d.ts +0 -2
- package/dist/source/commands/prompt-command.js +0 -111
- package/dist/source/commands/reset-command.d.ts +0 -2
- package/dist/source/commands/reset-command.js +0 -16
- package/dist/source/commands/rules-command.d.ts +0 -2
- package/dist/source/commands/rules-command.js +0 -68
- package/dist/source/commands/save-command.d.ts +0 -2
- package/dist/source/commands/save-command.js +0 -14
- package/dist/source/commands/types.d.ts +0 -26
- package/dist/source/commands/types.js +0 -1
- package/dist/source/commands/usage-command.d.ts +0 -2
- package/dist/source/commands/usage-command.js +0 -21
- package/dist/source/config.d.ts +0 -60
- package/dist/source/config.js +0 -193
- package/dist/source/conversation-analyzer.d.ts +0 -10
- package/dist/source/conversation-analyzer.js +0 -88
- package/dist/source/dedent.d.ts +0 -3
- package/dist/source/dedent.js +0 -38
- package/dist/source/formatting.d.ts +0 -17
- package/dist/source/formatting.js +0 -103
- package/dist/source/index.d.ts +0 -18
- package/dist/source/index.js +0 -213
- package/dist/source/logger.d.ts +0 -2
- package/dist/source/logger.js +0 -24
- package/dist/source/mentions.d.ts +0 -9
- package/dist/source/mentions.js +0 -182
- package/dist/source/messages.d.ts +0 -69
- package/dist/source/messages.js +0 -261
- package/dist/source/middleware/audit-message.d.ts +0 -5
- package/dist/source/middleware/audit-message.js +0 -95
- package/dist/source/middleware/index.d.ts +0 -2
- package/dist/source/middleware/index.js +0 -2
- package/dist/source/middleware/rate-limit.d.ts +0 -4
- package/dist/source/middleware/rate-limit.js +0 -17
- package/dist/source/models/ai-config.d.ts +0 -12
- package/dist/source/models/ai-config.js +0 -87
- package/dist/source/models/anthropic-provider.d.ts +0 -25
- package/dist/source/models/anthropic-provider.js +0 -184
- package/dist/source/models/deepseek-provider.d.ts +0 -20
- package/dist/source/models/deepseek-provider.js +0 -42
- package/dist/source/models/google-provider.d.ts +0 -19
- package/dist/source/models/google-provider.js +0 -56
- package/dist/source/models/manager.d.ts +0 -15
- package/dist/source/models/manager.js +0 -48
- package/dist/source/models/openai-provider.d.ts +0 -22
- package/dist/source/models/openai-provider.js +0 -70
- package/dist/source/models/openrouter-provider.d.ts +0 -36
- package/dist/source/models/openrouter-provider.js +0 -276
- package/dist/source/models/providers.d.ts +0 -33
- package/dist/source/models/providers.js +0 -116
- package/dist/source/models/xai-provider.d.ts +0 -20
- package/dist/source/models/xai-provider.js +0 -47
- package/dist/source/parsing.d.ts +0 -2
- package/dist/source/parsing.js +0 -18
- package/dist/source/prompts/manager.d.ts +0 -19
- package/dist/source/prompts/manager.js +0 -71
- package/dist/source/prompts.d.ts +0 -4
- package/dist/source/prompts.js +0 -158
- package/dist/source/repl-prompt.d.ts +0 -14
- package/dist/source/repl-prompt.js +0 -147
- package/dist/source/repl.d.ts +0 -27
- package/dist/source/repl.js +0 -431
- package/dist/source/terminal/formatting.d.ts +0 -37
- package/dist/source/terminal/formatting.js +0 -106
- package/dist/source/terminal/index.d.ts +0 -94
- package/dist/source/terminal/index.js +0 -420
- package/dist/source/terminal/markdown-utils.d.ts +0 -2
- package/dist/source/terminal/markdown-utils.js +0 -81
- package/dist/source/terminal/markdown.d.ts +0 -1
- package/dist/source/terminal/markdown.js +0 -111
- package/dist/source/terminal/types.d.ts +0 -71
- package/dist/source/terminal/types.js +0 -1
- package/dist/source/terminal-output.d.ts +0 -8
- package/dist/source/terminal-output.js +0 -213
- package/dist/source/terminal-output.test.d.ts +0 -8
- package/dist/source/terminal-output.test.js +0 -213
- package/dist/source/token-tracker.d.ts +0 -14
- package/dist/source/token-tracker.js +0 -53
- package/dist/source/token-utils.d.ts +0 -7
- package/dist/source/token-utils.js +0 -13
- package/dist/source/tools/agent.d.ts +0 -17
- package/dist/source/tools/agent.js +0 -87
- package/dist/source/tools/bash.d.ts +0 -19
- package/dist/source/tools/bash.js +0 -294
- package/dist/source/tools/code-interpreter.d.ts +0 -12
- package/dist/source/tools/code-interpreter.js +0 -131
- package/dist/source/tools/command-validation.d.ts +0 -8
- package/dist/source/tools/command-validation.js +0 -69
- package/dist/source/tools/delete-file.d.ts +0 -12
- package/dist/source/tools/delete-file.js +0 -56
- package/dist/source/tools/directory-tree.d.ts +0 -12
- package/dist/source/tools/directory-tree.js +0 -38
- package/dist/source/tools/edit-file.d.ts +0 -19
- package/dist/source/tools/edit-file.js +0 -107
- package/dist/source/tools/filesystem-utils.d.ts +0 -22
- package/dist/source/tools/filesystem-utils.js +0 -191
- package/dist/source/tools/git-utils.d.ts +0 -14
- package/dist/source/tools/git-utils.js +0 -64
- package/dist/source/tools/grep.d.ts +0 -17
- package/dist/source/tools/grep.js +0 -138
- package/dist/source/tools/index.d.ts +0 -161
- package/dist/source/tools/index.js +0 -209
- package/dist/source/tools/memory-read.d.ts +0 -13
- package/dist/source/tools/memory-read.js +0 -135
- package/dist/source/tools/memory-write.d.ts +0 -12
- package/dist/source/tools/memory-write.js +0 -83
- package/dist/source/tools/move-file.d.ts +0 -13
- package/dist/source/tools/move-file.js +0 -44
- package/dist/source/tools/read-file.d.ts +0 -17
- package/dist/source/tools/read-file.js +0 -86
- package/dist/source/tools/read-multiple-files.d.ts +0 -14
- package/dist/source/tools/read-multiple-files.js +0 -55
- package/dist/source/tools/save-file.d.ts +0 -17
- package/dist/source/tools/save-file.js +0 -98
- package/dist/source/tools/think.d.ts +0 -11
- package/dist/source/tools/think.js +0 -45
- package/dist/source/tools/types.d.ts +0 -29
- package/dist/source/tools/types.js +0 -14
- package/dist/source/tools/web-fetch.d.ts +0 -47
- package/dist/source/tools/web-fetch.js +0 -246
- package/dist/source/tools/web-search.d.ts +0 -13
- package/dist/source/tools/web-search.js +0 -80
- package/dist/source/utils/process.d.ts +0 -36
- package/dist/source/utils/process.js +0 -75
- package/dist/source/version.d.ts +0 -1
- package/dist/source/version.js +0 -21
- package/dist/terminal-output.d.ts +0 -8
- package/dist/terminal-output.js +0 -213
- package/dist/tools/memory-read.d.ts +0 -13
- package/dist/tools/memory-read.js +0 -135
- package/dist/tools/memory-write.d.ts +0 -12
- package/dist/tools/memory-write.js +0 -83
- package/knip.json +0 -5
- package/source/cli.ts +0 -172
- package/source/commands/application-log-command.ts +0 -53
- package/source/commands/clear-command.ts +0 -14
- package/source/commands/compact-command.ts +0 -64
- package/source/commands/copy-command.ts +0 -55
- package/source/commands/edit-command.ts +0 -63
- package/source/commands/edit-prompt-command.ts +0 -31
- package/source/commands/exit-command.ts +0 -18
- package/source/commands/files-command.ts +0 -85
- package/source/commands/generate-rules-command.ts +0 -82
- package/source/commands/help-command.ts +0 -27
- package/source/commands/init-command.ts +0 -48
- package/source/commands/last-log-command.ts +0 -88
- package/source/commands/manager.ts +0 -151
- package/source/commands/model-command.ts +0 -123
- package/source/commands/paste-command.ts +0 -62
- package/source/commands/prompt-command.ts +0 -150
- package/source/commands/reset-command.ts +0 -22
- package/source/commands/rules-command.ts +0 -76
- package/source/commands/save-command.ts +0 -20
- package/source/commands/types.ts +0 -28
- package/source/commands/usage-command.ts +0 -26
- package/source/config.ts +0 -223
- package/source/conversation-analyzer.ts +0 -115
- package/source/dedent.ts +0 -53
- package/source/formatting.ts +0 -132
- package/source/index.ts +0 -240
- package/source/logger.ts +0 -29
- package/source/mentions.ts +0 -227
- package/source/messages.ts +0 -360
- package/source/middleware/audit-message.ts +0 -133
- package/source/middleware/index.ts +0 -2
- package/source/middleware/rate-limit.ts +0 -24
- package/source/models/ai-config.ts +0 -109
- package/source/models/anthropic-provider.ts +0 -199
- package/source/models/deepseek-provider.ts +0 -53
- package/source/models/google-provider.ts +0 -68
- package/source/models/manager.ts +0 -84
- package/source/models/openai-provider.ts +0 -81
- package/source/models/openrouter-provider.ts +0 -288
- package/source/models/providers.ts +0 -197
- package/source/models/xai-provider.ts +0 -59
- package/source/parsing.ts +0 -20
- package/source/prompts/manager.ts +0 -90
- package/source/prompts.ts +0 -172
- package/source/repl-prompt.ts +0 -196
- package/source/repl.ts +0 -572
- package/source/terminal/formatting.ts +0 -121
- package/source/terminal/index.ts +0 -518
- package/source/terminal/markdown-utils.ts +0 -89
- package/source/terminal/markdown.ts +0 -155
- package/source/terminal/types.ts +0 -84
- package/source/terminal-output.test.ts +0 -266
- package/source/token-tracker.ts +0 -78
- package/source/token-utils.ts +0 -17
- package/source/tools/agent.ts +0 -107
- package/source/tools/bash.ts +0 -367
- package/source/tools/code-interpreter.ts +0 -172
- package/source/tools/command-validation.ts +0 -81
- package/source/tools/delete-file.ts +0 -71
- package/source/tools/directory-tree.ts +0 -54
- package/source/tools/edit-file.ts +0 -155
- package/source/tools/filesystem-utils.ts +0 -265
- package/source/tools/git-utils.ts +0 -70
- package/source/tools/grep.ts +0 -184
- package/source/tools/index.ts +0 -278
- package/source/tools/memory-read.ts +0 -174
- package/source/tools/memory-write.ts +0 -105
- package/source/tools/move-file.ts +0 -59
- package/source/tools/read-file.ts +0 -129
- package/source/tools/read-multiple-files.ts +0 -80
- package/source/tools/save-file.ts +0 -147
- package/source/tools/think.ts +0 -51
- package/source/tools/types.ts +0 -58
- package/source/tools/web-fetch.ts +0 -327
- package/source/tools/web-search.ts +0 -101
- package/source/utils/process.ts +0 -121
- package/source/version.ts +0 -21
- package/test/commands/copy-command.test.ts +0 -69
- package/test/config.test.ts +0 -200
- package/test/terminal/markdown-utils.test.ts +0 -124
- package/test/tools/bash-tool.test.ts +0 -58
- package/test/tools/code-interpreter.test.ts +0 -91
- package/test/tools/command-validation.test.ts +0 -48
- package/tsconfig.build.json +0 -9
- package/tsconfig.json +0 -30
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import { readdir, readFile } from "node:fs/promises";
|
|
2
|
-
import path, { basename } from "node:path";
|
|
3
|
-
import { processPrompt } from "../mentions.ts";
|
|
4
|
-
import type { CommandOptions, ReplCommand } from "./types.ts";
|
|
5
|
-
|
|
6
|
-
export const promptCommand = ({
|
|
7
|
-
terminal,
|
|
8
|
-
modelManager,
|
|
9
|
-
promptManager,
|
|
10
|
-
config,
|
|
11
|
-
}: CommandOptions): ReplCommand => {
|
|
12
|
-
return {
|
|
13
|
-
command: "/prompt",
|
|
14
|
-
description:
|
|
15
|
-
"Loads and executes prompts. Project prompts override user prompts with the same name.",
|
|
16
|
-
result: "use" as const,
|
|
17
|
-
getSubCommands: async (): Promise<string[]> => {
|
|
18
|
-
const getPromptNamesFromDir = async (
|
|
19
|
-
dirPath: string,
|
|
20
|
-
): Promise<string[]> => {
|
|
21
|
-
try {
|
|
22
|
-
const dirents = await readdir(dirPath, { withFileTypes: true });
|
|
23
|
-
return dirents
|
|
24
|
-
.filter((dirent) => dirent.isFile() && dirent.name.endsWith(".md"))
|
|
25
|
-
.map((dirent) => basename(dirent.name, ".md"));
|
|
26
|
-
} catch (error) {
|
|
27
|
-
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
|
28
|
-
return []; // Directory doesn't exist, return empty array
|
|
29
|
-
}
|
|
30
|
-
terminal.error(`Error reading prompts from ${dirPath}: ${error}`);
|
|
31
|
-
return []; // Return empty on other errors too, but log them
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const userPromptDir = config.app.ensurePathSync("prompts"); // User prompts are global (~/.acai/prompts)
|
|
36
|
-
const projectPromptDir = config.project.ensurePathSync("prompts"); // Project prompts are local (./.acai/prompts)
|
|
37
|
-
|
|
38
|
-
const userPrompts = await getPromptNamesFromDir(userPromptDir);
|
|
39
|
-
const projectPrompts = await getPromptNamesFromDir(projectPromptDir);
|
|
40
|
-
|
|
41
|
-
// Combine and deduplicate, with project prompts taking precedence
|
|
42
|
-
const allPrompts = new Set([...userPrompts, ...projectPrompts]);
|
|
43
|
-
return Array.from(allPrompts).sort();
|
|
44
|
-
},
|
|
45
|
-
execute: async (args: string[]) => {
|
|
46
|
-
const promptName = args?.[0];
|
|
47
|
-
if (!promptName) {
|
|
48
|
-
terminal.warn(
|
|
49
|
-
"Please provide a prompt name. Usage: /prompt <prompt-name> [input...]",
|
|
50
|
-
);
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Check for old format and provide helpful error
|
|
55
|
-
if (promptName.includes(":")) {
|
|
56
|
-
terminal.warn(
|
|
57
|
-
"The old format (user:name or project:name) is no longer supported. Use: /prompt <prompt-name> [input...]",
|
|
58
|
-
);
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
try {
|
|
63
|
-
const promptResult = await findPrompt(promptName, config);
|
|
64
|
-
|
|
65
|
-
if (!promptResult) {
|
|
66
|
-
terminal.error(
|
|
67
|
-
`Prompt not found: ${promptName}. Available prompts can be seen with tab completion.`,
|
|
68
|
-
);
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
let promptContent: string;
|
|
73
|
-
try {
|
|
74
|
-
promptContent = await readFile(promptResult.path, "utf8");
|
|
75
|
-
} catch (error) {
|
|
76
|
-
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
|
77
|
-
terminal.error(
|
|
78
|
-
`Prompt file not found: ${promptName} at ${promptResult.path}`,
|
|
79
|
-
);
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
throw error;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Combine remaining arguments into a single string for input
|
|
86
|
-
const inputArgs = args.slice(1);
|
|
87
|
-
const inputString = inputArgs.join(" ");
|
|
88
|
-
|
|
89
|
-
// Replace {{INPUT}} placeholder with the input string
|
|
90
|
-
if (promptContent.includes("{{INPUT}}")) {
|
|
91
|
-
promptContent = promptContent.replace(/{{INPUT}}/g, inputString);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
terminal.info(`Loaded ${promptResult.type} prompt: ${promptName}`);
|
|
95
|
-
if (inputArgs.length > 0) {
|
|
96
|
-
terminal.info(`Input: "${inputString}"`);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const processedPrompt = await processPrompt(promptContent, {
|
|
100
|
-
baseDir: process.cwd(),
|
|
101
|
-
model: modelManager.getModelMetadata("repl"),
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
for (const context of processedPrompt.context) {
|
|
105
|
-
promptManager.addContext(context);
|
|
106
|
-
}
|
|
107
|
-
promptManager.set(processedPrompt.message);
|
|
108
|
-
} catch (error) {
|
|
109
|
-
terminal.error(`Error loading prompt: ${(error as Error).message}`);
|
|
110
|
-
}
|
|
111
|
-
},
|
|
112
|
-
};
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
async function findPrompt(
|
|
116
|
-
promptName: string,
|
|
117
|
-
config: CommandOptions["config"],
|
|
118
|
-
): Promise<{ path: string; type: "project" | "user" } | null> {
|
|
119
|
-
// Check project prompts first (they take precedence)
|
|
120
|
-
const projectPath = path.join(
|
|
121
|
-
config.project.ensurePathSync("prompts"),
|
|
122
|
-
`${promptName}.md`,
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
try {
|
|
126
|
-
await readFile(projectPath, "utf8");
|
|
127
|
-
return { path: projectPath, type: "project" };
|
|
128
|
-
} catch (error) {
|
|
129
|
-
if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
130
|
-
throw error; // Re-throw non-file-not-found errors
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Check user prompts if not found in project
|
|
135
|
-
const userPath = path.join(
|
|
136
|
-
config.app.ensurePathSync("prompts"),
|
|
137
|
-
`${promptName}.md`,
|
|
138
|
-
);
|
|
139
|
-
|
|
140
|
-
try {
|
|
141
|
-
await readFile(userPath, "utf8");
|
|
142
|
-
return { path: userPath, type: "user" };
|
|
143
|
-
} catch (error) {
|
|
144
|
-
if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
145
|
-
throw error; // Re-throw non-file-not-found errors
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
return null; // Prompt not found in either location
|
|
150
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { CommandOptions, ReplCommand } from "./types.ts";
|
|
2
|
-
|
|
3
|
-
export const resetCommand = ({
|
|
4
|
-
terminal,
|
|
5
|
-
messageHistory,
|
|
6
|
-
}: CommandOptions): ReplCommand => {
|
|
7
|
-
return {
|
|
8
|
-
command: "/reset",
|
|
9
|
-
description: "Saves the chat history and then resets it.",
|
|
10
|
-
result: "continue" as const,
|
|
11
|
-
getSubCommands: () => Promise.resolve([]),
|
|
12
|
-
execute: async () => {
|
|
13
|
-
if (!messageHistory.isEmpty()) {
|
|
14
|
-
await messageHistory.save();
|
|
15
|
-
messageHistory.clear();
|
|
16
|
-
}
|
|
17
|
-
terminal.setTitle(`acai: ${process.cwd()}`);
|
|
18
|
-
|
|
19
|
-
terminal.clear();
|
|
20
|
-
},
|
|
21
|
-
};
|
|
22
|
-
};
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { editor } from "@inquirer/prompts";
|
|
2
|
-
import { config } from "../config.ts";
|
|
3
|
-
import type { CommandOptions, ReplCommand } from "./types.ts";
|
|
4
|
-
|
|
5
|
-
export const rulesCommand = ({ terminal }: CommandOptions): ReplCommand => {
|
|
6
|
-
return {
|
|
7
|
-
command: "/rules",
|
|
8
|
-
description:
|
|
9
|
-
"View, add, or edit rules. Usage: /rules [view|add <text>|edit]",
|
|
10
|
-
result: "continue" as const,
|
|
11
|
-
getSubCommands: () => Promise.resolve(["view", "add", "edit"]),
|
|
12
|
-
execute: async (args: string[]) => {
|
|
13
|
-
const subCommand = args[0] ?? "view"; // Default to 'view'
|
|
14
|
-
const commandArgs = args.slice(1).join(" ");
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
switch (subCommand) {
|
|
18
|
-
case "view": {
|
|
19
|
-
const currentContent = await config.readAgentsFile();
|
|
20
|
-
if (currentContent) {
|
|
21
|
-
terminal.writeln("--- Current Rules ---");
|
|
22
|
-
terminal.writeln(currentContent);
|
|
23
|
-
terminal.writeln("---------------------");
|
|
24
|
-
} else {
|
|
25
|
-
terminal.writeln(
|
|
26
|
-
"No rules defined yet. Use '/rules add' or '/rules edit'.",
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
break;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
case "add": {
|
|
33
|
-
const newMemory = commandArgs.trim();
|
|
34
|
-
if (!newMemory) {
|
|
35
|
-
terminal.error("Error: Memory text cannot be empty for 'add'.");
|
|
36
|
-
terminal.writeln("Usage: /memory add <new memory text>");
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
const currentContent = await config.readAgentsFile();
|
|
40
|
-
const updatedContent = currentContent
|
|
41
|
-
? `${currentContent.trim()}\n- ${newMemory}` // Ensure space after dash
|
|
42
|
-
: `- ${newMemory}`; // Start with dash if new file
|
|
43
|
-
await config.writeAgentsFile(updatedContent);
|
|
44
|
-
break;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
case "edit": {
|
|
48
|
-
const currentContent = await config.readAgentsFile();
|
|
49
|
-
const updatedContent = await editor({
|
|
50
|
-
message: "Edit rules:",
|
|
51
|
-
postfix: "md",
|
|
52
|
-
default: currentContent,
|
|
53
|
-
});
|
|
54
|
-
// Check if the user cancelled the edit (editor returns the original content)
|
|
55
|
-
// Or if the content is actually different
|
|
56
|
-
if (updatedContent !== currentContent) {
|
|
57
|
-
await config.writeAgentsFile(updatedContent);
|
|
58
|
-
} else {
|
|
59
|
-
terminal.writeln("Edit cancelled or no changes made.");
|
|
60
|
-
}
|
|
61
|
-
break;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
default:
|
|
65
|
-
terminal.writeln(
|
|
66
|
-
"Invalid subcommand. Usage: /rules [view|add <text>|edit]",
|
|
67
|
-
);
|
|
68
|
-
break;
|
|
69
|
-
}
|
|
70
|
-
} catch (_error) {
|
|
71
|
-
// Errors from read/write helpers are already logged
|
|
72
|
-
terminal.error("Failed to execute memory command.");
|
|
73
|
-
}
|
|
74
|
-
},
|
|
75
|
-
};
|
|
76
|
-
};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { CommandOptions, ReplCommand } from "./types.ts";
|
|
2
|
-
|
|
3
|
-
export const saveCommand = ({
|
|
4
|
-
messageHistory,
|
|
5
|
-
terminal,
|
|
6
|
-
}: CommandOptions): ReplCommand => {
|
|
7
|
-
return {
|
|
8
|
-
command: "/save",
|
|
9
|
-
description: "Saves the chat history.",
|
|
10
|
-
result: "continue" as const,
|
|
11
|
-
getSubCommands: () => Promise.resolve([]),
|
|
12
|
-
execute: async () => {
|
|
13
|
-
if (!messageHistory.isEmpty()) {
|
|
14
|
-
await messageHistory.save();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
terminal.info("Message history saved.");
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
};
|
package/source/commands/types.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { ConfigManager } from "../config.ts";
|
|
2
|
-
import type { MessageHistory } from "../messages.ts";
|
|
3
|
-
import type { ModelManager } from "../models/manager.ts";
|
|
4
|
-
import type { PromptManager } from "../prompts/manager.ts";
|
|
5
|
-
import type { Terminal } from "../terminal/index.ts";
|
|
6
|
-
import type { TokenTracker } from "../token-tracker.ts";
|
|
7
|
-
import type { TokenCounter } from "../token-utils.ts";
|
|
8
|
-
import type { Message } from "../tools/types.ts";
|
|
9
|
-
|
|
10
|
-
export interface ReplCommand {
|
|
11
|
-
command: string;
|
|
12
|
-
aliases?: string[];
|
|
13
|
-
description: string;
|
|
14
|
-
result: "break" | "continue" | "use";
|
|
15
|
-
getSubCommands: () => Promise<string[]>;
|
|
16
|
-
execute: (args: string[]) => Promise<void>;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface CommandOptions {
|
|
20
|
-
promptManager: PromptManager;
|
|
21
|
-
modelManager: ModelManager;
|
|
22
|
-
terminal: Terminal;
|
|
23
|
-
messageHistory: MessageHistory;
|
|
24
|
-
tokenTracker: TokenTracker;
|
|
25
|
-
config: ConfigManager;
|
|
26
|
-
tokenCounter: TokenCounter;
|
|
27
|
-
toolEvents: Map<string, Message[]>;
|
|
28
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import type { CommandOptions, ReplCommand } from "./types.ts";
|
|
2
|
-
|
|
3
|
-
export function usageCommand({
|
|
4
|
-
terminal,
|
|
5
|
-
tokenTracker,
|
|
6
|
-
}: CommandOptions): ReplCommand {
|
|
7
|
-
return {
|
|
8
|
-
command: "/usage",
|
|
9
|
-
description: "Show token usage breakdown",
|
|
10
|
-
result: "continue",
|
|
11
|
-
getSubCommands: () => Promise.resolve([]),
|
|
12
|
-
execute() {
|
|
13
|
-
const entries = Object.entries(tokenTracker.getUsageBreakdown());
|
|
14
|
-
if (entries.length === 0) {
|
|
15
|
-
terminal.info("No usage yet.");
|
|
16
|
-
} else {
|
|
17
|
-
terminal.table(entries, {
|
|
18
|
-
header: ["App", "Tokens"],
|
|
19
|
-
colWidths: [30, 70],
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return Promise.resolve();
|
|
24
|
-
},
|
|
25
|
-
};
|
|
26
|
-
}
|
package/source/config.ts
DELETED
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
import { mkdirSync } from "node:fs";
|
|
2
|
-
import fs from "node:fs/promises";
|
|
3
|
-
import { homedir } from "node:os";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { z } from "zod";
|
|
6
|
-
import { jsonParser } from "./parsing.ts";
|
|
7
|
-
|
|
8
|
-
export class DirectoryProvider {
|
|
9
|
-
private baseDir: string;
|
|
10
|
-
|
|
11
|
-
constructor(baseDir: string) {
|
|
12
|
-
this.baseDir = baseDir;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
getPath(subdir?: string): string {
|
|
16
|
-
return subdir ? path.join(this.baseDir, subdir) : this.baseDir;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Async-by-default: prefer non-blocking filesystem operations.
|
|
20
|
-
async ensurePath(subdir?: string): Promise<string> {
|
|
21
|
-
const dirPath = this.getPath(subdir);
|
|
22
|
-
await fs.mkdir(dirPath, { recursive: true });
|
|
23
|
-
return dirPath;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Synchronous helper for call-sites that require immediate directory availability.
|
|
27
|
-
ensurePathSync(subdir?: string): string {
|
|
28
|
-
const dirPath = this.getPath(subdir);
|
|
29
|
-
mkdirSync(dirPath, { recursive: true });
|
|
30
|
-
return dirPath;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export class ConfigManager {
|
|
35
|
-
readonly project: DirectoryProvider;
|
|
36
|
-
readonly app: DirectoryProvider;
|
|
37
|
-
|
|
38
|
-
constructor() {
|
|
39
|
-
this.project = new DirectoryProvider(path.join(process.cwd(), ".acai"));
|
|
40
|
-
this.app = new DirectoryProvider(path.join(homedir(), ".acai"));
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
private async _readConfig(
|
|
44
|
-
configPath: string,
|
|
45
|
-
): Promise<Partial<ProjectConfig>> {
|
|
46
|
-
try {
|
|
47
|
-
const data = await fs.readFile(configPath, "utf8");
|
|
48
|
-
return jsonParser(ProjectConfigSchema).parse(data);
|
|
49
|
-
} catch (error) {
|
|
50
|
-
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
|
51
|
-
return {};
|
|
52
|
-
}
|
|
53
|
-
throw error;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Project config helpers
|
|
58
|
-
async readProjectConfig(): Promise<ProjectConfig> {
|
|
59
|
-
const appConfigPath = path.join(this.app.getPath(), "acai.json");
|
|
60
|
-
const projectConfigPath = path.join(this.project.getPath(), "acai.json");
|
|
61
|
-
|
|
62
|
-
const appConfig = await this._readConfig(appConfigPath);
|
|
63
|
-
const projectConfig = await this._readConfig(projectConfigPath);
|
|
64
|
-
|
|
65
|
-
const mergedConfig = {
|
|
66
|
-
...appConfig,
|
|
67
|
-
...projectConfig,
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
return ProjectConfigSchema.parse(mergedConfig);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
async readAgentsFile(): Promise<string> {
|
|
74
|
-
const agentsPath = path.join(process.cwd(), "AGENTS.md");
|
|
75
|
-
try {
|
|
76
|
-
return await fs.readFile(agentsPath, "utf8");
|
|
77
|
-
} catch (error) {
|
|
78
|
-
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
|
79
|
-
return "";
|
|
80
|
-
}
|
|
81
|
-
throw error;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
async writeAgentsFile(rules: string): Promise<void> {
|
|
86
|
-
const agentsPath = path.join(process.cwd(), "AGENTS.md");
|
|
87
|
-
try {
|
|
88
|
-
return await fs.writeFile(agentsPath, rules, "utf8");
|
|
89
|
-
} catch (error) {
|
|
90
|
-
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
throw error;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
// Project-specific learned rules
|
|
97
|
-
async readProjectLearnedRulesFile(): Promise<string> {
|
|
98
|
-
const rulesPath = path.join(
|
|
99
|
-
this.project.getPath("rules"),
|
|
100
|
-
"learned-rules.md",
|
|
101
|
-
);
|
|
102
|
-
try {
|
|
103
|
-
return await fs.readFile(rulesPath, "utf8");
|
|
104
|
-
} catch (error) {
|
|
105
|
-
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
|
106
|
-
return "";
|
|
107
|
-
}
|
|
108
|
-
throw error;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
async writeProjectLearnedRulesFile(rules: string): Promise<void> {
|
|
113
|
-
const rulesDir = await this.project.ensurePath("rules");
|
|
114
|
-
const rulesPath = path.join(rulesDir, "learned-rules.md");
|
|
115
|
-
try {
|
|
116
|
-
return await fs.writeFile(rulesPath, rules, "utf8");
|
|
117
|
-
} catch (error) {
|
|
118
|
-
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
throw error;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// App-cached learned rules (used during conversation analysis)
|
|
126
|
-
async readCachedLearnedRulesFile(): Promise<string> {
|
|
127
|
-
const rulesPath = path.join(this.app.getPath("rules"), "learned-rules.md");
|
|
128
|
-
try {
|
|
129
|
-
return await fs.readFile(rulesPath, "utf8");
|
|
130
|
-
} catch (error) {
|
|
131
|
-
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
|
132
|
-
return "";
|
|
133
|
-
}
|
|
134
|
-
throw error;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
async writeCachedLearnedRulesFile(rules: string): Promise<void> {
|
|
139
|
-
const rulesDir = await this.app.ensurePath("rules");
|
|
140
|
-
const rulesPath = path.join(rulesDir, "learned-rules.md");
|
|
141
|
-
try {
|
|
142
|
-
return await fs.writeFile(rulesPath, rules, "utf8");
|
|
143
|
-
} catch (error) {
|
|
144
|
-
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
throw error;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// App config helpers
|
|
152
|
-
async readAppConfig(
|
|
153
|
-
configName: string,
|
|
154
|
-
): Promise<Record<PropertyKey, unknown>> {
|
|
155
|
-
const configPath = path.join(this.app.getPath(), `${configName}.json`);
|
|
156
|
-
try {
|
|
157
|
-
const data = await fs.readFile(configPath, "utf8");
|
|
158
|
-
return JSON.parse(data);
|
|
159
|
-
} catch (error) {
|
|
160
|
-
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
|
161
|
-
return {};
|
|
162
|
-
}
|
|
163
|
-
throw error;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
async ensureAppConfig(
|
|
168
|
-
configName: string,
|
|
169
|
-
): Promise<Record<PropertyKey, unknown>> {
|
|
170
|
-
const configPath = path.join(this.app.getPath(), `${configName}.json`);
|
|
171
|
-
|
|
172
|
-
try {
|
|
173
|
-
await fs.access(configPath);
|
|
174
|
-
return await this.readAppConfig(configName);
|
|
175
|
-
} catch {
|
|
176
|
-
// Create directory and default config if missing
|
|
177
|
-
await this.app.ensurePath();
|
|
178
|
-
|
|
179
|
-
const defaultConfig = {
|
|
180
|
-
logs: {
|
|
181
|
-
path: path.join(this.app.getPath(), "logs", "current.log"),
|
|
182
|
-
},
|
|
183
|
-
tools: {
|
|
184
|
-
maxTokens: 30000,
|
|
185
|
-
},
|
|
186
|
-
notify: true,
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
await fs.writeFile(configPath, JSON.stringify(defaultConfig, null, 2));
|
|
190
|
-
return defaultConfig;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
async writeAppConfig(
|
|
195
|
-
configName: string,
|
|
196
|
-
data: Record<PropertyKey, unknown>,
|
|
197
|
-
): Promise<void> {
|
|
198
|
-
await this.app.ensurePath();
|
|
199
|
-
const configPath = path.join(this.app.getPath(), `${configName}.json`);
|
|
200
|
-
await fs.writeFile(configPath, JSON.stringify(data, null, 2));
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Type definitions
|
|
205
|
-
const ProjectConfigSchema = z.object({
|
|
206
|
-
logs: z
|
|
207
|
-
.object({
|
|
208
|
-
path: z.string(),
|
|
209
|
-
})
|
|
210
|
-
.optional(),
|
|
211
|
-
tools: z
|
|
212
|
-
.object({
|
|
213
|
-
maxTokens: z.number().default(30000),
|
|
214
|
-
})
|
|
215
|
-
.optional()
|
|
216
|
-
.default({ maxTokens: 30000 }),
|
|
217
|
-
notify: z.boolean().optional().default(true),
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
export type ProjectConfig = z.infer<typeof ProjectConfigSchema>;
|
|
221
|
-
|
|
222
|
-
// Create a singleton instance
|
|
223
|
-
export const config = new ConfigManager();
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { generateText, type ModelMessage } from "ai";
|
|
2
|
-
import { config } from "./config.ts";
|
|
3
|
-
import { createUserMessage } from "./messages.ts";
|
|
4
|
-
import type { ModelManager } from "./models/manager.ts";
|
|
5
|
-
import { systemPrompt } from "./prompts.ts";
|
|
6
|
-
import type { Terminal } from "./terminal/index.ts";
|
|
7
|
-
import type { TokenTracker } from "./token-tracker.ts";
|
|
8
|
-
|
|
9
|
-
// Modified System Prompt
|
|
10
|
-
const system =
|
|
11
|
-
async () => `You are an expert analyst reviewing conversations between a coding agent and a software engineer. Your goal is to identify instances where the engineer corrected the agent's approach or understanding in a way that reveals a *generalizable principle* for improving the agent's future behavior across *different* tasks.
|
|
12
|
-
|
|
13
|
-
**Your Task:**
|
|
14
|
-
1. Analyze the conversation provided.
|
|
15
|
-
2. Identify significant corrections or redirections from the engineer. Ignore minor clarifications or task-specific adjustments.
|
|
16
|
-
3. For each significant correction, infer a *single, concise, broadly applicable, actionable rule* (starting with 'Always' or 'Never') that captures the underlying principle the agent should follow in the future.
|
|
17
|
-
4. Ensure the rule is general enough to be useful in various scenarios, not just the specific context of this conversation.
|
|
18
|
-
5. Provide a brief, illustrative quote or example from the conversation in parentheses after the rule.
|
|
19
|
-
6. List only the inferred rules in Markdown bullet points. Do not include explanations, summaries, or conversational filler.
|
|
20
|
-
|
|
21
|
-
**Crucially, AVOID generating rules that are:**
|
|
22
|
-
- Overly specific to the files, functions, or variables discussed (e.g., "Always check for null in the 'processUserData' function"). Instead, generalize (e.g., "Always validate data from external sources before processing").
|
|
23
|
-
- Merely restatements of the task requirements.
|
|
24
|
-
- Too narrow to be useful outside the immediate context.
|
|
25
|
-
- Related to minor typos or formatting preferences unless they represent a consistent pattern requested by the user.
|
|
26
|
-
|
|
27
|
-
**Good General Rule Examples:**
|
|
28
|
-
<examples>
|
|
29
|
-
- Always ask for clarification if the user's request is ambiguous.
|
|
30
|
-
- Never make assumptions about file paths without confirmation.
|
|
31
|
-
- Always follow the user's explicitly stated formatting preferences.
|
|
32
|
-
- Never provide incomplete code snippets without indicating they are partial.
|
|
33
|
-
- Always check for potential null or undefined values before accessing properties.
|
|
34
|
-
</examples>
|
|
35
|
-
|
|
36
|
-
**Bad Specific Rule Examples (Avoid These):**
|
|
37
|
-
<bad-examples>
|
|
38
|
-
- Always use 'const' instead of 'let' for the 'userId' variable in 'auth.ts'.
|
|
39
|
-
- Never forget to pass the 'config' object to the 'initializeDb' function.
|
|
40
|
-
- Always add a try-catch block around the 'api.fetchData()' call in 'dataService.ts'.
|
|
41
|
-
</bad-examples>
|
|
42
|
-
|
|
43
|
-
This is the original system prompt the agent operated under:
|
|
44
|
-
<systemPrompt>
|
|
45
|
-
${await systemPrompt()}
|
|
46
|
-
</systemPrompt>`;
|
|
47
|
-
|
|
48
|
-
export async function analyzeConversation({
|
|
49
|
-
modelManager,
|
|
50
|
-
messages,
|
|
51
|
-
tokenTracker,
|
|
52
|
-
}: {
|
|
53
|
-
modelManager: ModelManager;
|
|
54
|
-
messages: ModelMessage[];
|
|
55
|
-
terminal?: Terminal | undefined;
|
|
56
|
-
tokenTracker: TokenTracker;
|
|
57
|
-
}): Promise<string[]> {
|
|
58
|
-
const learnedRules = await config.readCachedLearnedRulesFile();
|
|
59
|
-
// Modified User Message within analyzeConversation
|
|
60
|
-
messages.push(
|
|
61
|
-
createUserMessage([
|
|
62
|
-
`Analyze this conversation based on the system instructions. Identify points where the user made significant corrections revealing general principles for agent improvement. Infer concise, broadly applicable rules (Always/Never) based *only* on these corrections.
|
|
63
|
-
|
|
64
|
-
**Key Requirements:**
|
|
65
|
-
- Focus on *generalizable* rules applicable to future, different tasks.
|
|
66
|
-
- Avoid rules tied to the specifics of *this* conversation.
|
|
67
|
-
- Ensure rules don't already exist in <existing-rules>.
|
|
68
|
-
- If no *new, general* rules can be inferred, return an empty list or response.
|
|
69
|
-
- Return *only* the Markdown list of rules, with no preamble or explanation.
|
|
70
|
-
|
|
71
|
-
<existing-rules>
|
|
72
|
-
${learnedRules}
|
|
73
|
-
</existing-rules>`,
|
|
74
|
-
]),
|
|
75
|
-
);
|
|
76
|
-
const { text, usage } = await generateText({
|
|
77
|
-
model: modelManager.getModel("conversation-analyzer"),
|
|
78
|
-
maxOutputTokens: 8192,
|
|
79
|
-
system: await system(),
|
|
80
|
-
messages: messages,
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
tokenTracker.trackUsage("conversation-analyzer", usage);
|
|
84
|
-
|
|
85
|
-
// Trim whitespace and check if the response is effectively empty or just whitespace
|
|
86
|
-
const potentialRulesText = text.trim();
|
|
87
|
-
|
|
88
|
-
// Basic check to prevent adding empty lines or just formatting
|
|
89
|
-
if (!potentialRulesText || potentialRulesText.length === 0) {
|
|
90
|
-
return []; // Return empty array if no valid rules generated
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Split into individual rules, filter out empty lines
|
|
94
|
-
const potentialRulesList = potentialRulesText
|
|
95
|
-
.split("\n")
|
|
96
|
-
.map((rule) => rule.trim())
|
|
97
|
-
.filter((rule) => rule.length > 0);
|
|
98
|
-
|
|
99
|
-
if (potentialRulesList.length === 0) {
|
|
100
|
-
return []; // Return empty array if splitting results in no rules
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Further validation could be added here (e.g., check if it starts with '- ', etc.)
|
|
104
|
-
// before writing to the file.
|
|
105
|
-
|
|
106
|
-
// Append only if there are non-empty potential rules
|
|
107
|
-
const updatedRules =
|
|
108
|
-
learnedRules.endsWith("\n") || learnedRules.length === 0
|
|
109
|
-
? `${learnedRules}${potentialRulesList.join("\n")}`
|
|
110
|
-
: `${learnedRules}\n${potentialRulesList.join("\n")}`;
|
|
111
|
-
|
|
112
|
-
await config.writeCachedLearnedRulesFile(updatedRules);
|
|
113
|
-
|
|
114
|
-
return potentialRulesList; // Return the list of rules that were added
|
|
115
|
-
}
|