@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
package/dist/source/messages.js
DELETED
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
import EventEmitter from "node:events";
|
|
2
|
-
import { readdir, readFile, writeFile } from "node:fs/promises";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
import { isString } from "@travisennis/stdlib/typeguards";
|
|
5
|
-
import { generateText, } from "ai";
|
|
6
|
-
export function createUserMessage(contentItems, prompt) {
|
|
7
|
-
const messageParts = [];
|
|
8
|
-
// Process content items (images and pre-defined texts)
|
|
9
|
-
for (const item of contentItems) {
|
|
10
|
-
if (typeof item === "string") {
|
|
11
|
-
if (item.trim().length > 0) {
|
|
12
|
-
messageParts.push({ type: "text", text: item });
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
else if (item.type === "image") {
|
|
16
|
-
messageParts.push(item);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
// Add the main prompt text if provided
|
|
20
|
-
if (prompt && prompt.trim().length > 0) {
|
|
21
|
-
messageParts.push({ type: "text", text: prompt });
|
|
22
|
-
}
|
|
23
|
-
return {
|
|
24
|
-
role: "user",
|
|
25
|
-
content: messageParts,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
export function createAssistantMessage(content) {
|
|
29
|
-
return {
|
|
30
|
-
role: "assistant",
|
|
31
|
-
content: [
|
|
32
|
-
{
|
|
33
|
-
type: "text",
|
|
34
|
-
text: content,
|
|
35
|
-
},
|
|
36
|
-
],
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
export class MessageHistory extends EventEmitter {
|
|
40
|
-
history;
|
|
41
|
-
title;
|
|
42
|
-
createdAt;
|
|
43
|
-
updatedAt;
|
|
44
|
-
stateDir;
|
|
45
|
-
modelManager;
|
|
46
|
-
tokenTracker;
|
|
47
|
-
constructor({ stateDir, modelManager, tokenTracker, }) {
|
|
48
|
-
super();
|
|
49
|
-
this.history = [];
|
|
50
|
-
this.title = "";
|
|
51
|
-
this.createdAt = new Date();
|
|
52
|
-
this.updatedAt = new Date();
|
|
53
|
-
this.stateDir = stateDir;
|
|
54
|
-
this.modelManager = modelManager;
|
|
55
|
-
this.tokenTracker = tokenTracker;
|
|
56
|
-
}
|
|
57
|
-
validMessage(msg) {
|
|
58
|
-
// Filter out messages with empty content arrays
|
|
59
|
-
if (Array.isArray(msg.content) && msg.content.length === 0) {
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
// Filter out assistant messages with empty text fields
|
|
63
|
-
if (msg.role === "assistant" &&
|
|
64
|
-
Array.isArray(msg.content) &&
|
|
65
|
-
msg.content.length === 1 &&
|
|
66
|
-
msg.content[0]?.type === "text" &&
|
|
67
|
-
msg.content[0]?.text === "") {
|
|
68
|
-
return false;
|
|
69
|
-
}
|
|
70
|
-
return true;
|
|
71
|
-
}
|
|
72
|
-
get() {
|
|
73
|
-
return [...this.history].filter(this.validMessage);
|
|
74
|
-
}
|
|
75
|
-
clear() {
|
|
76
|
-
this.history.length = 0;
|
|
77
|
-
this.emit("clear-history");
|
|
78
|
-
}
|
|
79
|
-
appendUserMessage(msg) {
|
|
80
|
-
const now = new Date();
|
|
81
|
-
const msgObj = isString(msg) ? createUserMessage([], msg) : msg;
|
|
82
|
-
if (this.history.length === 0 &&
|
|
83
|
-
msgObj.content &&
|
|
84
|
-
msgObj.content.length > 0) {
|
|
85
|
-
const textPart = msgObj.content.at(-1);
|
|
86
|
-
if (textPart?.text && textPart.text.trim() !== "") {
|
|
87
|
-
this.generateTitle(textPart.text);
|
|
88
|
-
}
|
|
89
|
-
this.createdAt = now;
|
|
90
|
-
}
|
|
91
|
-
this.updatedAt = now;
|
|
92
|
-
this.history.push(msgObj);
|
|
93
|
-
}
|
|
94
|
-
appendAssistantMessage(msg) {
|
|
95
|
-
this.updatedAt = new Date();
|
|
96
|
-
const msgObj = isString(msg) ? createAssistantMessage(msg) : msg;
|
|
97
|
-
this.history.push(msgObj);
|
|
98
|
-
}
|
|
99
|
-
appendResponseMessages(responseMessages) {
|
|
100
|
-
this.updatedAt = new Date();
|
|
101
|
-
// Filter out messages with empty content arrays
|
|
102
|
-
const validMessages = responseMessages.filter(this.validMessage);
|
|
103
|
-
this.history.push(...validMessages);
|
|
104
|
-
}
|
|
105
|
-
isEmpty() {
|
|
106
|
-
return this.history.length === 0;
|
|
107
|
-
}
|
|
108
|
-
async save() {
|
|
109
|
-
const msgHistoryDir = this.stateDir;
|
|
110
|
-
const timestamp = new Date().toISOString().replace(/:/g, "-");
|
|
111
|
-
const fileName = `message-history-${timestamp}.json`;
|
|
112
|
-
const filePath = join(msgHistoryDir, fileName);
|
|
113
|
-
const output = {
|
|
114
|
-
title: this.title,
|
|
115
|
-
createdAt: this.createdAt,
|
|
116
|
-
updatedAt: this.updatedAt,
|
|
117
|
-
messages: this.history,
|
|
118
|
-
};
|
|
119
|
-
await writeFile(filePath, JSON.stringify(output, null, 2));
|
|
120
|
-
}
|
|
121
|
-
async generateTitle(message) {
|
|
122
|
-
// Skip title generation if message is empty
|
|
123
|
-
if (!message || message.trim() === "") {
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
const app = "title-conversation";
|
|
127
|
-
const systemPrompt = "You are an assistant who task is to analyze messages to generate a conversation topic that can be used as a conversation title. For each message, generate a 4-7 word title that captures the topic. Return only the title with no other text.\n\nExamples:\nMessage:\nHow do I implement authentication in my Express app?\nTitle: Express Authentication Implementation\n\nMessage:\nCan you help me debug this React component that isn't rendering correctly?\nTitle:React Component Rendering Debug";
|
|
128
|
-
try {
|
|
129
|
-
const { text, usage } = await generateText({
|
|
130
|
-
model: this.modelManager.getModel(app),
|
|
131
|
-
system: systemPrompt,
|
|
132
|
-
prompt: `Request:\n${message}\nTitle:`,
|
|
133
|
-
});
|
|
134
|
-
this.tokenTracker.trackUsage(app, usage);
|
|
135
|
-
if (text && text.split(" ").length < 10) {
|
|
136
|
-
this.title = text;
|
|
137
|
-
this.emit("update-title", this.title);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
catch (error) {
|
|
141
|
-
console.error(error);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
getFirstUserMessage() {
|
|
145
|
-
const firstUser = this.get().find((msg) => msg.role === "user");
|
|
146
|
-
return firstUser;
|
|
147
|
-
}
|
|
148
|
-
static async load(stateDir, count = 10) {
|
|
149
|
-
try {
|
|
150
|
-
const files = await readdir(stateDir);
|
|
151
|
-
const messageHistoryFiles = files
|
|
152
|
-
.filter((file) => file.startsWith("message-history-") && file.endsWith(".json"))
|
|
153
|
-
.sort((a, b) => {
|
|
154
|
-
// Extract timestamps and compare in reverse order (newest first)
|
|
155
|
-
const timeA = a.replace("message-history-", "").replace(".json", "");
|
|
156
|
-
const timeB = b.replace("message-history-", "").replace(".json", "");
|
|
157
|
-
return timeB.localeCompare(timeA); // Newest first
|
|
158
|
-
})
|
|
159
|
-
.slice(0, count); // Use the count parameter here
|
|
160
|
-
const fileReadPromises = messageHistoryFiles.map(async (fileName) => {
|
|
161
|
-
const filePath = join(stateDir, fileName);
|
|
162
|
-
try {
|
|
163
|
-
const content = await readFile(filePath, "utf-8");
|
|
164
|
-
const parsed = JSON.parse(content);
|
|
165
|
-
const result = parsed;
|
|
166
|
-
// Basic validation - ensure messages array exists
|
|
167
|
-
if (parsed && Array.isArray(parsed.messages)) {
|
|
168
|
-
// Convert date strings back to Date objects
|
|
169
|
-
result.createdAt = new Date(parsed.createdAt ?? 0);
|
|
170
|
-
result.updatedAt = new Date(parsed.updatedAt ?? 0);
|
|
171
|
-
return result;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
catch (error) {
|
|
175
|
-
console.error(`Error reading or parsing file ${filePath}:`, error);
|
|
176
|
-
}
|
|
177
|
-
return null; // Return null for failed reads/parses
|
|
178
|
-
});
|
|
179
|
-
const results = await Promise.all(fileReadPromises);
|
|
180
|
-
// Filter out null results (failed reads/parses)
|
|
181
|
-
//sort results by result.updatedAt which is a Date
|
|
182
|
-
return results
|
|
183
|
-
.filter((result) => result !== null)
|
|
184
|
-
.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
|
|
185
|
-
}
|
|
186
|
-
catch (error) {
|
|
187
|
-
// Handle cases where the directory might not exist or other readdir errors
|
|
188
|
-
if (error.code !== "ENOENT") {
|
|
189
|
-
console.error(`Error loading message history from ${stateDir}:`, error);
|
|
190
|
-
}
|
|
191
|
-
// Return empty array if directory doesn't exist or other read errors occur
|
|
192
|
-
return [];
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
// Method to restore state from a SavedMessageHistory object
|
|
196
|
-
restore(savedHistory) {
|
|
197
|
-
this.title = savedHistory.title;
|
|
198
|
-
// Ensure dates are Date objects, though load should handle this
|
|
199
|
-
this.createdAt =
|
|
200
|
-
typeof savedHistory.createdAt === "string"
|
|
201
|
-
? new Date(savedHistory.createdAt)
|
|
202
|
-
: savedHistory.createdAt;
|
|
203
|
-
this.updatedAt =
|
|
204
|
-
typeof savedHistory.updatedAt === "string"
|
|
205
|
-
? new Date(savedHistory.updatedAt)
|
|
206
|
-
: savedHistory.updatedAt;
|
|
207
|
-
this.history = [...savedHistory.messages]; // Use the correct internal property name and create a copy
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
/**
|
|
211
|
-
* Normalizes an array of messages for API consumption by:
|
|
212
|
-
* 1. Filtering out progress-type messages
|
|
213
|
-
* 2. Processing user and assistant messages
|
|
214
|
-
* 3. Handling tool results by either:
|
|
215
|
-
* - Adding them as new messages if they're the first tool result
|
|
216
|
-
* - Adding them as new messages if the previous message wasn't a tool result
|
|
217
|
-
* - Merging them with the previous message if it was also a tool result
|
|
218
|
-
*
|
|
219
|
-
* This consolidation of sequential tool results into a single message
|
|
220
|
-
* ensures proper formatting for API consumption while maintaining the
|
|
221
|
-
* logical flow of the conversation.
|
|
222
|
-
*
|
|
223
|
-
* @param messages - Array of messages to normalize
|
|
224
|
-
* @returns Normalized array of user and assistant messages ready for API
|
|
225
|
-
*/
|
|
226
|
-
export function normalizeMessagesForApi(messages) {
|
|
227
|
-
const result = [];
|
|
228
|
-
for (const message of messages) {
|
|
229
|
-
switch (message.role) {
|
|
230
|
-
case "user": {
|
|
231
|
-
result.push(message);
|
|
232
|
-
continue;
|
|
233
|
-
}
|
|
234
|
-
case "tool": {
|
|
235
|
-
// If the last message is not a tool result, add it to the result
|
|
236
|
-
const lastMessage = result.at(-1);
|
|
237
|
-
if (!lastMessage ||
|
|
238
|
-
lastMessage.role === "assistant" ||
|
|
239
|
-
!Array.isArray(lastMessage.content) ||
|
|
240
|
-
lastMessage.content[0]?.type !== "tool-result") {
|
|
241
|
-
result.push(message);
|
|
242
|
-
continue;
|
|
243
|
-
}
|
|
244
|
-
// Otherwise, merge the current message with the last message
|
|
245
|
-
result[result.indexOf(lastMessage)] = {
|
|
246
|
-
...lastMessage,
|
|
247
|
-
// biome-ignore lint/suspicious/noExplicitAny: can't figure out type
|
|
248
|
-
content: [...lastMessage.content, ...message.content], // #FIXME figure out what type this should be
|
|
249
|
-
};
|
|
250
|
-
continue;
|
|
251
|
-
}
|
|
252
|
-
case "assistant": {
|
|
253
|
-
result.push(message);
|
|
254
|
-
continue;
|
|
255
|
-
}
|
|
256
|
-
default:
|
|
257
|
-
continue;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
return result;
|
|
261
|
-
}
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
-
import { dirname, join } from "node:path";
|
|
3
|
-
/**
|
|
4
|
-
* Writes an audit record to the specified file, overwriting any existing content.
|
|
5
|
-
* Ensures the directory exists before writing.
|
|
6
|
-
*
|
|
7
|
-
* @param filePath - The path to the file where the audit record will be saved.
|
|
8
|
-
* @param content - The audit record object to write.
|
|
9
|
-
*/
|
|
10
|
-
const writeAuditRecord = async (app, filePath, content) => {
|
|
11
|
-
try {
|
|
12
|
-
const now = new Date();
|
|
13
|
-
const path = join(filePath, `${now.toISOString()}-${app}-message.json`);
|
|
14
|
-
// Ensure directory exists
|
|
15
|
-
await mkdir(dirname(path), { recursive: true });
|
|
16
|
-
await writeFile(path, `${JSON.stringify(content, null, 2)}`);
|
|
17
|
-
}
|
|
18
|
-
catch (error) {
|
|
19
|
-
console.error("Error writing audit file:", error);
|
|
20
|
-
throw error;
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
export const auditMessage = ({ filePath = "messages", app = "default", }) => {
|
|
24
|
-
const middleware = {
|
|
25
|
-
wrapGenerate: async ({ doGenerate, params, model }) => {
|
|
26
|
-
const result = await doGenerate();
|
|
27
|
-
const msg = {
|
|
28
|
-
model: model.modelId,
|
|
29
|
-
app,
|
|
30
|
-
messages: [...params.prompt].concat({
|
|
31
|
-
role: "assistant",
|
|
32
|
-
content: [
|
|
33
|
-
{
|
|
34
|
-
type: "text",
|
|
35
|
-
// biome-ignore lint/suspicious/noExplicitAny: work-around on type issue
|
|
36
|
-
text: result.text,
|
|
37
|
-
},
|
|
38
|
-
],
|
|
39
|
-
}),
|
|
40
|
-
usage: result.usage,
|
|
41
|
-
timestamp: Date.now(),
|
|
42
|
-
};
|
|
43
|
-
await writeAuditRecord(app, filePath, msg);
|
|
44
|
-
return result;
|
|
45
|
-
},
|
|
46
|
-
wrapStream: async ({ doStream, params, model }) => {
|
|
47
|
-
const { stream, ...rest } = await doStream();
|
|
48
|
-
let generatedText = "";
|
|
49
|
-
let usage = {
|
|
50
|
-
inputTokens: 0,
|
|
51
|
-
outputTokens: 0,
|
|
52
|
-
totalTokens: 0,
|
|
53
|
-
};
|
|
54
|
-
const transformStream = new TransformStream({
|
|
55
|
-
transform(chunk, controller) {
|
|
56
|
-
if (chunk.type === "text-delta") {
|
|
57
|
-
generatedText += chunk.delta;
|
|
58
|
-
}
|
|
59
|
-
if (chunk.type === "finish") {
|
|
60
|
-
usage = chunk.usage;
|
|
61
|
-
}
|
|
62
|
-
controller.enqueue(chunk);
|
|
63
|
-
},
|
|
64
|
-
async flush() {
|
|
65
|
-
const msg = {
|
|
66
|
-
model: model.modelId,
|
|
67
|
-
app,
|
|
68
|
-
messages: generatedText
|
|
69
|
-
? [
|
|
70
|
-
...params.prompt,
|
|
71
|
-
{
|
|
72
|
-
role: "assistant",
|
|
73
|
-
content: [
|
|
74
|
-
{
|
|
75
|
-
type: "text",
|
|
76
|
-
text: generatedText,
|
|
77
|
-
},
|
|
78
|
-
],
|
|
79
|
-
},
|
|
80
|
-
]
|
|
81
|
-
: [...params.prompt],
|
|
82
|
-
usage,
|
|
83
|
-
timestamp: Date.now(),
|
|
84
|
-
};
|
|
85
|
-
await writeAuditRecord(app, filePath, msg);
|
|
86
|
-
},
|
|
87
|
-
});
|
|
88
|
-
return {
|
|
89
|
-
stream: stream.pipeThrough(transformStream),
|
|
90
|
-
...rest,
|
|
91
|
-
};
|
|
92
|
-
},
|
|
93
|
-
};
|
|
94
|
-
return middleware;
|
|
95
|
-
};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import pThrottle from "p-throttle";
|
|
2
|
-
export const createRateLimitMiddleware = ({ requestsPerMinute, }) => {
|
|
3
|
-
const throttle = pThrottle({
|
|
4
|
-
limit: requestsPerMinute,
|
|
5
|
-
interval: 60 * 1000, // 1 minute
|
|
6
|
-
});
|
|
7
|
-
return {
|
|
8
|
-
wrapGenerate: ({ doGenerate }) => {
|
|
9
|
-
const throttledGenerate = throttle(doGenerate);
|
|
10
|
-
return Promise.resolve(throttledGenerate());
|
|
11
|
-
},
|
|
12
|
-
wrapStream: ({ doStream }) => {
|
|
13
|
-
const throttledStream = throttle(doStream);
|
|
14
|
-
return throttledStream();
|
|
15
|
-
},
|
|
16
|
-
};
|
|
17
|
-
};
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { SharedV2ProviderMetadata } from "@ai-sdk/provider";
|
|
2
|
-
import type { ModelMetadata } from "./providers.ts";
|
|
3
|
-
export declare class AiConfig {
|
|
4
|
-
private modelMetadata;
|
|
5
|
-
private prompt;
|
|
6
|
-
constructor({ modelMetadata, prompt, }: {
|
|
7
|
-
modelMetadata: ModelMetadata;
|
|
8
|
-
prompt: string;
|
|
9
|
-
});
|
|
10
|
-
getMaxTokens(): number;
|
|
11
|
-
getProviderOptions(): SharedV2ProviderMetadata;
|
|
12
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
const THINKING_TIERS = [
|
|
2
|
-
{
|
|
3
|
-
pattern: /\b(ultrathink|think super hard|think really hard|think intensely)\b/i,
|
|
4
|
-
budget: 31999,
|
|
5
|
-
effort: "high",
|
|
6
|
-
},
|
|
7
|
-
{
|
|
8
|
-
pattern: /\b(megathink|think (very )?hard|think (a lot|more|about it))\b/i,
|
|
9
|
-
budget: 10000,
|
|
10
|
-
effort: "medium",
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
pattern: /\bthink\b/i, // Catch-all for standalone "think"
|
|
14
|
-
budget: 4000,
|
|
15
|
-
effort: "low",
|
|
16
|
-
},
|
|
17
|
-
];
|
|
18
|
-
function calculateThinkingLevel(userInput) {
|
|
19
|
-
let tokenBudget = 0; // Default
|
|
20
|
-
let effort = "none";
|
|
21
|
-
for (const tier of THINKING_TIERS) {
|
|
22
|
-
if (tier.pattern.test(userInput)) {
|
|
23
|
-
tokenBudget = tier.budget;
|
|
24
|
-
effort = tier.effort;
|
|
25
|
-
break; // Use highest priority match
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return { tokenBudget, effort };
|
|
29
|
-
}
|
|
30
|
-
export class AiConfig {
|
|
31
|
-
modelMetadata;
|
|
32
|
-
prompt;
|
|
33
|
-
constructor({ modelMetadata, prompt, }) {
|
|
34
|
-
this.modelMetadata = modelMetadata;
|
|
35
|
-
this.prompt = prompt;
|
|
36
|
-
}
|
|
37
|
-
getMaxTokens() {
|
|
38
|
-
const modelConfig = this.modelMetadata;
|
|
39
|
-
const thinkingLevel = calculateThinkingLevel(this.prompt);
|
|
40
|
-
const maxTokens = modelConfig.provider === "anthropic" && modelConfig.supportsReasoning
|
|
41
|
-
? modelConfig.maxOutputTokens - thinkingLevel.tokenBudget
|
|
42
|
-
: modelConfig.maxOutputTokens;
|
|
43
|
-
return maxTokens;
|
|
44
|
-
}
|
|
45
|
-
getProviderOptions() {
|
|
46
|
-
const modelConfig = this.modelMetadata;
|
|
47
|
-
const thinkingLevel = calculateThinkingLevel(this.prompt);
|
|
48
|
-
if (modelConfig.supportsReasoning && thinkingLevel.effort !== "none") {
|
|
49
|
-
switch (modelConfig.provider) {
|
|
50
|
-
case "anthropic":
|
|
51
|
-
return {
|
|
52
|
-
anthropic: {
|
|
53
|
-
thinking: {
|
|
54
|
-
type: "enabled",
|
|
55
|
-
budgetTokens: thinkingLevel.tokenBudget,
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
};
|
|
59
|
-
case "openai":
|
|
60
|
-
return { openai: { reasoningEffort: thinkingLevel.effort } };
|
|
61
|
-
case "google": {
|
|
62
|
-
return {
|
|
63
|
-
google: {
|
|
64
|
-
thinkingConfig: {
|
|
65
|
-
thinkingBudget: thinkingLevel.tokenBudget,
|
|
66
|
-
},
|
|
67
|
-
},
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
case "openrouter": {
|
|
71
|
-
return {
|
|
72
|
-
openrouter: {
|
|
73
|
-
reasoning: {
|
|
74
|
-
enabled: true,
|
|
75
|
-
effort: thinkingLevel.effort,
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
default:
|
|
81
|
-
return {};
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
// If supportsReasoning is false, or no provider case matched
|
|
85
|
-
return {};
|
|
86
|
-
}
|
|
87
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { ModelMetadata } from "./providers.ts";
|
|
2
|
-
declare const anthropicModels: {
|
|
3
|
-
readonly opus: import("@ai-sdk/provider").LanguageModelV2;
|
|
4
|
-
readonly sonnet: import("@ai-sdk/provider").LanguageModelV2;
|
|
5
|
-
readonly sonnet37: import("@ai-sdk/provider").LanguageModelV2;
|
|
6
|
-
readonly "sonnet37-token-efficient-tools": import("@ai-sdk/provider").LanguageModelV2;
|
|
7
|
-
readonly "sonnet37-128k": import("@ai-sdk/provider").LanguageModelV2;
|
|
8
|
-
readonly sonnet35: import("@ai-sdk/provider").LanguageModelV2;
|
|
9
|
-
readonly haiku: import("@ai-sdk/provider").LanguageModelV2;
|
|
10
|
-
};
|
|
11
|
-
type ModelName = `anthropic:${keyof typeof anthropicModels}`;
|
|
12
|
-
export declare const anthropicModelNames: ModelName[];
|
|
13
|
-
export declare const anthropicProvider: {
|
|
14
|
-
anthropic: import("@ai-sdk/provider").ProviderV2 & {
|
|
15
|
-
languageModel(modelId: "opus" | "sonnet" | "sonnet37" | "sonnet37-token-efficient-tools" | "sonnet37-128k" | "sonnet35" | "haiku"): import("@ai-sdk/provider").LanguageModelV2;
|
|
16
|
-
textEmbeddingModel(modelId: string): import("@ai-sdk/provider").EmbeddingModelV2<string>;
|
|
17
|
-
imageModel(modelId: string): import("@ai-sdk/provider").ImageModelV2;
|
|
18
|
-
transcriptionModel(modelId: string): import("@ai-sdk/provider").TranscriptionModelV2;
|
|
19
|
-
speechModel(modelId: string): import("@ai-sdk/provider").SpeechModelV2;
|
|
20
|
-
};
|
|
21
|
-
};
|
|
22
|
-
export declare const anthropicModelRegistry: {
|
|
23
|
-
[K in ModelName]: ModelMetadata<ModelName>;
|
|
24
|
-
};
|
|
25
|
-
export {};
|