agentx-sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +561 -0
- package/dist/agent.d.ts +105 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +690 -0
- package/dist/agent.js.map +1 -0
- package/dist/config/config.d.ts +346 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +93 -0
- package/dist/config/config.js.map +1 -0
- package/dist/contracts/entities/agent-event.d.ts +97 -0
- package/dist/contracts/entities/agent-event.d.ts.map +1 -0
- package/dist/contracts/entities/agent-event.js +2 -0
- package/dist/contracts/entities/agent-event.js.map +1 -0
- package/dist/contracts/entities/agent-skill.d.ts +59 -0
- package/dist/contracts/entities/agent-skill.d.ts.map +1 -0
- package/dist/contracts/entities/agent-skill.js +2 -0
- package/dist/contracts/entities/agent-skill.js.map +1 -0
- package/dist/contracts/entities/agent-tool.d.ts +42 -0
- package/dist/contracts/entities/agent-tool.d.ts.map +1 -0
- package/dist/contracts/entities/agent-tool.js +2 -0
- package/dist/contracts/entities/agent-tool.js.map +1 -0
- package/dist/contracts/entities/chat-message.d.ts +13 -0
- package/dist/contracts/entities/chat-message.d.ts.map +1 -0
- package/dist/contracts/entities/chat-message.js +2 -0
- package/dist/contracts/entities/chat-message.js.map +1 -0
- package/dist/contracts/entities/content-part.d.ts +16 -0
- package/dist/contracts/entities/content-part.d.ts.map +1 -0
- package/dist/contracts/entities/content-part.js +2 -0
- package/dist/contracts/entities/content-part.js.map +1 -0
- package/dist/contracts/entities/execution-context.d.ts +9 -0
- package/dist/contracts/entities/execution-context.d.ts.map +1 -0
- package/dist/contracts/entities/execution-context.js +2 -0
- package/dist/contracts/entities/execution-context.js.map +1 -0
- package/dist/contracts/entities/index.d.ts +11 -0
- package/dist/contracts/entities/index.d.ts.map +1 -0
- package/dist/contracts/entities/index.js +2 -0
- package/dist/contracts/entities/index.js.map +1 -0
- package/dist/contracts/entities/knowledge.d.ts +21 -0
- package/dist/contracts/entities/knowledge.d.ts.map +1 -0
- package/dist/contracts/entities/knowledge.js +2 -0
- package/dist/contracts/entities/knowledge.js.map +1 -0
- package/dist/contracts/entities/stores.d.ts +18 -0
- package/dist/contracts/entities/stores.d.ts.map +1 -0
- package/dist/contracts/entities/stores.js +2 -0
- package/dist/contracts/entities/stores.js.map +1 -0
- package/dist/contracts/entities/token-usage.d.ts +7 -0
- package/dist/contracts/entities/token-usage.d.ts.map +1 -0
- package/dist/contracts/entities/token-usage.js +2 -0
- package/dist/contracts/entities/token-usage.js.map +1 -0
- package/dist/contracts/entities/tool-call.d.ts +16 -0
- package/dist/contracts/entities/tool-call.d.ts.map +1 -0
- package/dist/contracts/entities/tool-call.js +2 -0
- package/dist/contracts/entities/tool-call.js.map +1 -0
- package/dist/contracts/enums/index.d.ts +21 -0
- package/dist/contracts/enums/index.d.ts.map +1 -0
- package/dist/contracts/enums/index.js +8 -0
- package/dist/contracts/enums/index.js.map +1 -0
- package/dist/contracts/index.d.ts +3 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +3 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/core/compaction/autocompact.d.ts +18 -0
- package/dist/core/compaction/autocompact.d.ts.map +1 -0
- package/dist/core/compaction/autocompact.js +68 -0
- package/dist/core/compaction/autocompact.js.map +1 -0
- package/dist/core/compaction/microcompact.d.ts +20 -0
- package/dist/core/compaction/microcompact.d.ts.map +1 -0
- package/dist/core/compaction/microcompact.js +38 -0
- package/dist/core/compaction/microcompact.js.map +1 -0
- package/dist/core/compaction/snip-compact.d.ts +22 -0
- package/dist/core/compaction/snip-compact.d.ts.map +1 -0
- package/dist/core/compaction/snip-compact.js +61 -0
- package/dist/core/compaction/snip-compact.js.map +1 -0
- package/dist/core/compaction/tool-result-budget.d.ts +24 -0
- package/dist/core/compaction/tool-result-budget.d.ts.map +1 -0
- package/dist/core/compaction/tool-result-budget.js +67 -0
- package/dist/core/compaction/tool-result-budget.js.map +1 -0
- package/dist/core/context-analysis.d.ts +24 -0
- package/dist/core/context-analysis.d.ts.map +1 -0
- package/dist/core/context-analysis.js +37 -0
- package/dist/core/context-analysis.js.map +1 -0
- package/dist/core/context-builder.d.ts +25 -0
- package/dist/core/context-builder.d.ts.map +1 -0
- package/dist/core/context-builder.js +108 -0
- package/dist/core/context-builder.js.map +1 -0
- package/dist/core/conversation-manager.d.ts +19 -0
- package/dist/core/conversation-manager.d.ts.map +1 -0
- package/dist/core/conversation-manager.js +62 -0
- package/dist/core/conversation-manager.js.map +1 -0
- package/dist/core/execution-context.d.ts +6 -0
- package/dist/core/execution-context.d.ts.map +1 -0
- package/dist/core/execution-context.js +14 -0
- package/dist/core/execution-context.js.map +1 -0
- package/dist/core/loop-deps.d.ts +15 -0
- package/dist/core/loop-deps.d.ts.map +1 -0
- package/dist/core/loop-deps.js +8 -0
- package/dist/core/loop-deps.js.map +1 -0
- package/dist/core/loop-types.d.ts +34 -0
- package/dist/core/loop-types.d.ts.map +1 -0
- package/dist/core/loop-types.js +15 -0
- package/dist/core/loop-types.js.map +1 -0
- package/dist/core/message-normalize.d.ts +18 -0
- package/dist/core/message-normalize.d.ts.map +1 -0
- package/dist/core/message-normalize.js +69 -0
- package/dist/core/message-normalize.js.map +1 -0
- package/dist/core/prompt-builders.d.ts +36 -0
- package/dist/core/prompt-builders.d.ts.map +1 -0
- package/dist/core/prompt-builders.js +89 -0
- package/dist/core/prompt-builders.js.map +1 -0
- package/dist/core/prompt-cache.d.ts +25 -0
- package/dist/core/prompt-cache.d.ts.map +1 -0
- package/dist/core/prompt-cache.js +34 -0
- package/dist/core/prompt-cache.js.map +1 -0
- package/dist/core/react-loop.d.ts +43 -0
- package/dist/core/react-loop.d.ts.map +1 -0
- package/dist/core/react-loop.js +403 -0
- package/dist/core/react-loop.js.map +1 -0
- package/dist/core/stop-hooks.d.ts +18 -0
- package/dist/core/stop-hooks.d.ts.map +1 -0
- package/dist/core/stop-hooks.js +18 -0
- package/dist/core/stop-hooks.js.map +1 -0
- package/dist/core/stream-emitter.d.ts +24 -0
- package/dist/core/stream-emitter.d.ts.map +1 -0
- package/dist/core/stream-emitter.js +65 -0
- package/dist/core/stream-emitter.js.map +1 -0
- package/dist/core/streaming-tool-executor.d.ts +54 -0
- package/dist/core/streaming-tool-executor.d.ts.map +1 -0
- package/dist/core/streaming-tool-executor.js +164 -0
- package/dist/core/streaming-tool-executor.js.map +1 -0
- package/dist/core/turn-end-hooks.d.ts +39 -0
- package/dist/core/turn-end-hooks.d.ts.map +1 -0
- package/dist/core/turn-end-hooks.js +36 -0
- package/dist/core/turn-end-hooks.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/knowledge/chunking.d.ts +9 -0
- package/dist/knowledge/chunking.d.ts.map +1 -0
- package/dist/knowledge/chunking.js +49 -0
- package/dist/knowledge/chunking.js.map +1 -0
- package/dist/knowledge/embedding-service.d.ts +16 -0
- package/dist/knowledge/embedding-service.d.ts.map +1 -0
- package/dist/knowledge/embedding-service.js +43 -0
- package/dist/knowledge/embedding-service.js.map +1 -0
- package/dist/knowledge/knowledge-manager.d.ts +33 -0
- package/dist/knowledge/knowledge-manager.d.ts.map +1 -0
- package/dist/knowledge/knowledge-manager.js +62 -0
- package/dist/knowledge/knowledge-manager.js.map +1 -0
- package/dist/knowledge/sqlite-vector-store.d.ts +16 -0
- package/dist/knowledge/sqlite-vector-store.d.ts.map +1 -0
- package/dist/knowledge/sqlite-vector-store.js +56 -0
- package/dist/knowledge/sqlite-vector-store.js.map +1 -0
- package/dist/knowledge/vector-store.d.ts +2 -0
- package/dist/knowledge/vector-store.d.ts.map +1 -0
- package/dist/knowledge/vector-store.js +2 -0
- package/dist/knowledge/vector-store.js.map +1 -0
- package/dist/llm/errors.d.ts +15 -0
- package/dist/llm/errors.d.ts.map +1 -0
- package/dist/llm/errors.js +39 -0
- package/dist/llm/errors.js.map +1 -0
- package/dist/llm/message-types.d.ts +80 -0
- package/dist/llm/message-types.d.ts.map +1 -0
- package/dist/llm/message-types.js +2 -0
- package/dist/llm/message-types.js.map +1 -0
- package/dist/llm/openrouter-client.d.ts +18 -0
- package/dist/llm/openrouter-client.d.ts.map +1 -0
- package/dist/llm/openrouter-client.js +215 -0
- package/dist/llm/openrouter-client.js.map +1 -0
- package/dist/llm/reasoning.d.ts +10 -0
- package/dist/llm/reasoning.d.ts.map +1 -0
- package/dist/llm/reasoning.js +18 -0
- package/dist/llm/reasoning.js.map +1 -0
- package/dist/memory/file-memory-system.d.ts +98 -0
- package/dist/memory/file-memory-system.d.ts.map +1 -0
- package/dist/memory/file-memory-system.js +310 -0
- package/dist/memory/file-memory-system.js.map +1 -0
- package/dist/memory/memory-age.d.ts +22 -0
- package/dist/memory/memory-age.d.ts.map +1 -0
- package/dist/memory/memory-age.js +44 -0
- package/dist/memory/memory-age.js.map +1 -0
- package/dist/memory/memory-extractor.d.ts +56 -0
- package/dist/memory/memory-extractor.d.ts.map +1 -0
- package/dist/memory/memory-extractor.js +91 -0
- package/dist/memory/memory-extractor.js.map +1 -0
- package/dist/memory/memory-paths.d.ts +45 -0
- package/dist/memory/memory-paths.d.ts.map +1 -0
- package/dist/memory/memory-paths.js +121 -0
- package/dist/memory/memory-paths.js.map +1 -0
- package/dist/memory/memory-prompts.d.ts +41 -0
- package/dist/memory/memory-prompts.d.ts.map +1 -0
- package/dist/memory/memory-prompts.js +279 -0
- package/dist/memory/memory-prompts.js.map +1 -0
- package/dist/memory/memory-relevance.d.ts +16 -0
- package/dist/memory/memory-relevance.d.ts.map +1 -0
- package/dist/memory/memory-relevance.js +46 -0
- package/dist/memory/memory-relevance.js.map +1 -0
- package/dist/memory/memory-scanner.d.ts +22 -0
- package/dist/memory/memory-scanner.d.ts.map +1 -0
- package/dist/memory/memory-scanner.js +99 -0
- package/dist/memory/memory-scanner.js.map +1 -0
- package/dist/memory/memory-tools.d.ts +16 -0
- package/dist/memory/memory-tools.d.ts.map +1 -0
- package/dist/memory/memory-tools.js +196 -0
- package/dist/memory/memory-tools.js.map +1 -0
- package/dist/memory/memory-types.d.ts +47 -0
- package/dist/memory/memory-types.d.ts.map +1 -0
- package/dist/memory/memory-types.js +24 -0
- package/dist/memory/memory-types.js.map +1 -0
- package/dist/skills/skill-args.d.ts +23 -0
- package/dist/skills/skill-args.d.ts.map +1 -0
- package/dist/skills/skill-args.js +77 -0
- package/dist/skills/skill-args.js.map +1 -0
- package/dist/skills/skill-glob.d.ts +24 -0
- package/dist/skills/skill-glob.d.ts.map +1 -0
- package/dist/skills/skill-glob.js +60 -0
- package/dist/skills/skill-glob.js.map +1 -0
- package/dist/skills/skill-loader.d.ts +49 -0
- package/dist/skills/skill-loader.d.ts.map +1 -0
- package/dist/skills/skill-loader.js +197 -0
- package/dist/skills/skill-loader.js.map +1 -0
- package/dist/skills/skill-manager.d.ts +83 -0
- package/dist/skills/skill-manager.d.ts.map +1 -0
- package/dist/skills/skill-manager.js +338 -0
- package/dist/skills/skill-manager.js.map +1 -0
- package/dist/storage/sqlite-conversation-store.d.ts +15 -0
- package/dist/storage/sqlite-conversation-store.d.ts.map +1 -0
- package/dist/storage/sqlite-conversation-store.js +45 -0
- package/dist/storage/sqlite-conversation-store.js.map +1 -0
- package/dist/storage/sqlite-database.d.ts +14 -0
- package/dist/storage/sqlite-database.d.ts.map +1 -0
- package/dist/storage/sqlite-database.js +95 -0
- package/dist/storage/sqlite-database.js.map +1 -0
- package/dist/tools/builtin/ask-user.d.ts +7 -0
- package/dist/tools/builtin/ask-user.d.ts.map +1 -0
- package/dist/tools/builtin/ask-user.js +23 -0
- package/dist/tools/builtin/ask-user.js.map +1 -0
- package/dist/tools/builtin/bash.d.ts +3 -0
- package/dist/tools/builtin/bash.d.ts.map +1 -0
- package/dist/tools/builtin/bash.js +54 -0
- package/dist/tools/builtin/bash.js.map +1 -0
- package/dist/tools/builtin/file-edit.d.ts +3 -0
- package/dist/tools/builtin/file-edit.d.ts.map +1 -0
- package/dist/tools/builtin/file-edit.js +50 -0
- package/dist/tools/builtin/file-edit.js.map +1 -0
- package/dist/tools/builtin/file-read.d.ts +3 -0
- package/dist/tools/builtin/file-read.d.ts.map +1 -0
- package/dist/tools/builtin/file-read.js +47 -0
- package/dist/tools/builtin/file-read.js.map +1 -0
- package/dist/tools/builtin/file-write.d.ts +3 -0
- package/dist/tools/builtin/file-write.d.ts.map +1 -0
- package/dist/tools/builtin/file-write.js +29 -0
- package/dist/tools/builtin/file-write.js.map +1 -0
- package/dist/tools/builtin/glob.d.ts +3 -0
- package/dist/tools/builtin/glob.d.ts.map +1 -0
- package/dist/tools/builtin/glob.js +67 -0
- package/dist/tools/builtin/glob.js.map +1 -0
- package/dist/tools/builtin/grep.d.ts +3 -0
- package/dist/tools/builtin/grep.d.ts.map +1 -0
- package/dist/tools/builtin/grep.js +94 -0
- package/dist/tools/builtin/grep.js.map +1 -0
- package/dist/tools/builtin/index.d.ts +49 -0
- package/dist/tools/builtin/index.d.ts.map +1 -0
- package/dist/tools/builtin/index.js +65 -0
- package/dist/tools/builtin/index.js.map +1 -0
- package/dist/tools/builtin/web-fetch.d.ts +3 -0
- package/dist/tools/builtin/web-fetch.d.ts.map +1 -0
- package/dist/tools/builtin/web-fetch.js +56 -0
- package/dist/tools/builtin/web-fetch.js.map +1 -0
- package/dist/tools/json-schema-to-zod.d.ts +30 -0
- package/dist/tools/json-schema-to-zod.d.ts.map +1 -0
- package/dist/tools/json-schema-to-zod.js +123 -0
- package/dist/tools/json-schema-to-zod.js.map +1 -0
- package/dist/tools/mcp-adapter.d.ts +80 -0
- package/dist/tools/mcp-adapter.d.ts.map +1 -0
- package/dist/tools/mcp-adapter.js +326 -0
- package/dist/tools/mcp-adapter.js.map +1 -0
- package/dist/tools/skill-tool.d.ts +41 -0
- package/dist/tools/skill-tool.d.ts.map +1 -0
- package/dist/tools/skill-tool.js +149 -0
- package/dist/tools/skill-tool.js.map +1 -0
- package/dist/tools/sql/index.d.ts +4 -0
- package/dist/tools/sql/index.d.ts.map +1 -0
- package/dist/tools/sql/index.js +2 -0
- package/dist/tools/sql/index.js.map +1 -0
- package/dist/tools/sql/sql-query-def.d.ts +22 -0
- package/dist/tools/sql/sql-query-def.d.ts.map +1 -0
- package/dist/tools/sql/sql-query-def.js +2 -0
- package/dist/tools/sql/sql-query-def.js.map +1 -0
- package/dist/tools/sql/sql-tool-factory.d.ts +28 -0
- package/dist/tools/sql/sql-tool-factory.d.ts.map +1 -0
- package/dist/tools/sql/sql-tool-factory.js +136 -0
- package/dist/tools/sql/sql-tool-factory.js.map +1 -0
- package/dist/tools/tool-executor.d.ts +67 -0
- package/dist/tools/tool-executor.d.ts.map +1 -0
- package/dist/tools/tool-executor.js +232 -0
- package/dist/tools/tool-executor.js.map +1 -0
- package/dist/utils/cache.d.ts +22 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +61 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/logger.d.ts +15 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +46 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/model-context.d.ts +14 -0
- package/dist/utils/model-context.d.ts.map +1 -0
- package/dist/utils/model-context.js +52 -0
- package/dist/utils/model-context.js.map +1 -0
- package/dist/utils/retry.d.ts +13 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +41 -0
- package/dist/utils/retry.js.map +1 -0
- package/dist/utils/token-counter.d.ts +6 -0
- package/dist/utils/token-counter.d.ts.map +1 -0
- package/dist/utils/token-counter.js +19 -0
- package/dist/utils/token-counter.js.map +1 -0
- package/package.json +43 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import { scanSkillFiles } from './skill-loader.js';
|
|
2
|
+
import { substituteArgs } from './skill-args.js';
|
|
3
|
+
import { matchAnyGlob } from './skill-glob.js';
|
|
4
|
+
const MAX_LISTING_DESC_CHARS = 250;
|
|
5
|
+
/**
|
|
6
|
+
* Registers skills, matches them against user input, manages conditional
|
|
7
|
+
* activation, and provides budget-aware skill listings for model discovery.
|
|
8
|
+
*
|
|
9
|
+
* Matching hierarchy: prefix > alias > custom match() > semantic similarity.
|
|
10
|
+
*/
|
|
11
|
+
export class SkillManager {
|
|
12
|
+
/** All registered skills (unconditional — always eligible for matching) */
|
|
13
|
+
skills = new Map();
|
|
14
|
+
/** Skills with `paths` — waiting for file touch to activate */
|
|
15
|
+
conditionalSkills = new Map();
|
|
16
|
+
/** Skills activated via path matching (moved from conditionalSkills) */
|
|
17
|
+
activatedSkills = new Map();
|
|
18
|
+
/** Tracks which skills have been invoked in this session */
|
|
19
|
+
invokedSkills = new Set();
|
|
20
|
+
/** Sticky skill sessions per thread — outer key: threadId, inner key: skillName */
|
|
21
|
+
stickySessions = new Map();
|
|
22
|
+
embeddingService;
|
|
23
|
+
maxActiveSkills;
|
|
24
|
+
constructor(options) {
|
|
25
|
+
this.embeddingService = options?.embeddingService;
|
|
26
|
+
this.maxActiveSkills = options?.maxActiveSkills ?? 3;
|
|
27
|
+
}
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Registration
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
register(skill) {
|
|
32
|
+
if (skill.paths && skill.paths.length > 0) {
|
|
33
|
+
this.conditionalSkills.set(skill.name, skill);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
this.skills.set(skill.name, skill);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
unregister(name) {
|
|
40
|
+
return this.skills.delete(name)
|
|
41
|
+
|| this.conditionalSkills.delete(name)
|
|
42
|
+
|| this.activatedSkills.delete(name);
|
|
43
|
+
}
|
|
44
|
+
/** All skills (unconditional + activated conditional) */
|
|
45
|
+
listSkills() {
|
|
46
|
+
return [...this.skills.values(), ...this.activatedSkills.values()];
|
|
47
|
+
}
|
|
48
|
+
/** All skills including pending conditional ones */
|
|
49
|
+
listAllSkills() {
|
|
50
|
+
return [
|
|
51
|
+
...this.skills.values(),
|
|
52
|
+
...this.activatedSkills.values(),
|
|
53
|
+
...this.conditionalSkills.values(),
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// File-based loading
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
/**
|
|
60
|
+
* Load skills from a directory containing SKILL.md files.
|
|
61
|
+
* Returns the number of skills loaded.
|
|
62
|
+
*/
|
|
63
|
+
async loadFromDirectory(dir) {
|
|
64
|
+
const skills = await scanSkillFiles(dir);
|
|
65
|
+
for (const skill of skills) {
|
|
66
|
+
this.register(skill);
|
|
67
|
+
}
|
|
68
|
+
return skills.length;
|
|
69
|
+
}
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
// Conditional path activation
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
/**
|
|
74
|
+
* Activate conditional skills whose `paths` match any of the given file paths.
|
|
75
|
+
* Returns the names of newly activated skills.
|
|
76
|
+
*/
|
|
77
|
+
activateForPaths(filePaths) {
|
|
78
|
+
const activated = [];
|
|
79
|
+
for (const [name, skill] of this.conditionalSkills) {
|
|
80
|
+
if (!skill.paths)
|
|
81
|
+
continue;
|
|
82
|
+
const matched = filePaths.some(fp => matchAnyGlob(skill.paths, fp));
|
|
83
|
+
if (matched) {
|
|
84
|
+
this.activatedSkills.set(name, skill);
|
|
85
|
+
this.conditionalSkills.delete(name);
|
|
86
|
+
activated.push(name);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return activated;
|
|
90
|
+
}
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
// Matching
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
/**
|
|
95
|
+
* Matches skills against input. Returns top skills sorted by priority.
|
|
96
|
+
*/
|
|
97
|
+
async match(input, context) {
|
|
98
|
+
const matches = [];
|
|
99
|
+
const matchedNames = new Set();
|
|
100
|
+
const eligible = this.getEligibleSkills();
|
|
101
|
+
// 0. Sticky sessions — re-inject skills that are active for this thread
|
|
102
|
+
const threadSessions = this.stickySessions.get(context.threadId);
|
|
103
|
+
if (threadSessions) {
|
|
104
|
+
for (const [skillName, session] of threadSessions) {
|
|
105
|
+
if (session.turnsRemaining <= 0) {
|
|
106
|
+
threadSessions.delete(skillName);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const skill = this.skills.get(skillName) ?? this.activatedSkills.get(skillName);
|
|
110
|
+
if (skill) {
|
|
111
|
+
matches.push({ skill, matchType: 'sticky', score: 0.9 });
|
|
112
|
+
matchedNames.add(skillName);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Clean up empty thread entry
|
|
116
|
+
if (threadSessions.size === 0) {
|
|
117
|
+
this.stickySessions.delete(context.threadId);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
for (const skill of eligible) {
|
|
121
|
+
if (matchedNames.has(skill.name))
|
|
122
|
+
continue;
|
|
123
|
+
// 1. Prefix match (highest priority)
|
|
124
|
+
if (skill.triggerPrefix && input.startsWith(skill.triggerPrefix)) {
|
|
125
|
+
matches.push({ skill, matchType: 'prefix', score: 1.0 });
|
|
126
|
+
matchedNames.add(skill.name);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
// 2. Alias match
|
|
130
|
+
if (skill.aliases) {
|
|
131
|
+
const matched = skill.aliases.some(alias => {
|
|
132
|
+
const prefix = alias.startsWith('/') ? alias : `/${alias}`;
|
|
133
|
+
return input.startsWith(prefix);
|
|
134
|
+
});
|
|
135
|
+
if (matched) {
|
|
136
|
+
matches.push({ skill, matchType: 'alias', score: 0.95 });
|
|
137
|
+
matchedNames.add(skill.name);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// 3. Custom match function
|
|
142
|
+
if (skill.match && skill.match(input, { threadId: context.threadId, recentMessages: 0 })) {
|
|
143
|
+
matches.push({ skill, matchType: 'custom', score: 0.8 });
|
|
144
|
+
matchedNames.add(skill.name);
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// 4. Semantic match — only if no prefix/alias/custom/sticky matches found
|
|
149
|
+
// and there are skills that lack explicit matchers
|
|
150
|
+
if (this.embeddingService && matches.length === 0 && this.hasSkillsNeedingSemantic(eligible)) {
|
|
151
|
+
const semanticMatches = await this.semanticMatch(input, eligible);
|
|
152
|
+
matches.push(...semanticMatches);
|
|
153
|
+
}
|
|
154
|
+
// Sort: exclusive first, then by match type priority, then by skill.priority
|
|
155
|
+
const sorted = matches.sort((a, b) => {
|
|
156
|
+
if (a.skill.exclusive && !b.skill.exclusive)
|
|
157
|
+
return -1;
|
|
158
|
+
if (!a.skill.exclusive && b.skill.exclusive)
|
|
159
|
+
return 1;
|
|
160
|
+
const typeOrder = { prefix: 4, sticky: 3.5, alias: 3, custom: 2, semantic: 1 };
|
|
161
|
+
const typeDiff = (typeOrder[b.matchType] ?? 0) - (typeOrder[a.matchType] ?? 0);
|
|
162
|
+
if (typeDiff !== 0)
|
|
163
|
+
return typeDiff;
|
|
164
|
+
return (b.skill.priority ?? 0) - (a.skill.priority ?? 0);
|
|
165
|
+
});
|
|
166
|
+
// Activate sticky sessions for newly matched skills and decrement turn counters
|
|
167
|
+
for (const match of sorted) {
|
|
168
|
+
if (match.skill.sticky) {
|
|
169
|
+
this.activateStickySession(context.threadId, match.skill);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
this.decrementStickySessions(context.threadId);
|
|
173
|
+
// If exclusive skill matched, return only it
|
|
174
|
+
if (sorted[0]?.skill.exclusive) {
|
|
175
|
+
return [sorted[0].skill];
|
|
176
|
+
}
|
|
177
|
+
return sorted.slice(0, this.maxActiveSkills).map(m => m.skill);
|
|
178
|
+
}
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
// Dynamic prompt resolution
|
|
181
|
+
// ---------------------------------------------------------------------------
|
|
182
|
+
/**
|
|
183
|
+
* Resolve the final instructions for a matched skill.
|
|
184
|
+
* If `getPrompt` exists, calls it with args and context.
|
|
185
|
+
* Otherwise uses static `instructions` with argument substitution.
|
|
186
|
+
*/
|
|
187
|
+
async resolveInstructions(skill, args, context) {
|
|
188
|
+
if (skill.getPrompt) {
|
|
189
|
+
return skill.getPrompt(args, context);
|
|
190
|
+
}
|
|
191
|
+
// Static instructions with optional substitution
|
|
192
|
+
if (skill.argNames && skill.argNames.length > 0) {
|
|
193
|
+
return substituteArgs(skill.instructions, args, skill.argNames, {
|
|
194
|
+
SKILL_DIR: context.skillDir ?? skill.skillDir ?? '',
|
|
195
|
+
THREAD_ID: context.threadId,
|
|
196
|
+
TRACE_ID: context.traceId,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
return skill.instructions;
|
|
200
|
+
}
|
|
201
|
+
// ---------------------------------------------------------------------------
|
|
202
|
+
// Budget-aware listing for model discovery
|
|
203
|
+
// ---------------------------------------------------------------------------
|
|
204
|
+
/**
|
|
205
|
+
* Build a formatted listing of available skills for model context.
|
|
206
|
+
* Truncates to fit within the given character budget.
|
|
207
|
+
*/
|
|
208
|
+
buildSkillListing(budgetChars) {
|
|
209
|
+
const eligible = this.getEligibleSkills()
|
|
210
|
+
.filter(s => s.modelInvocable !== false);
|
|
211
|
+
if (eligible.length === 0)
|
|
212
|
+
return '';
|
|
213
|
+
const lines = [];
|
|
214
|
+
let usedChars = 0;
|
|
215
|
+
for (const skill of eligible) {
|
|
216
|
+
const prefix = skill.triggerPrefix
|
|
217
|
+
? skill.triggerPrefix
|
|
218
|
+
: `/${skill.name}`;
|
|
219
|
+
let line = `- ${prefix}: ${skill.description}`;
|
|
220
|
+
if (skill.whenToUse) {
|
|
221
|
+
line += ` — ${skill.whenToUse}`;
|
|
222
|
+
}
|
|
223
|
+
// Truncate individual entry
|
|
224
|
+
if (line.length > MAX_LISTING_DESC_CHARS) {
|
|
225
|
+
line = line.slice(0, MAX_LISTING_DESC_CHARS - 3) + '...';
|
|
226
|
+
}
|
|
227
|
+
if (usedChars + line.length > budgetChars)
|
|
228
|
+
break;
|
|
229
|
+
lines.push(line);
|
|
230
|
+
usedChars += line.length + 1; // +1 for newline
|
|
231
|
+
}
|
|
232
|
+
return lines.join('\n');
|
|
233
|
+
}
|
|
234
|
+
// ---------------------------------------------------------------------------
|
|
235
|
+
// Invocation tracking
|
|
236
|
+
// ---------------------------------------------------------------------------
|
|
237
|
+
markInvoked(name) {
|
|
238
|
+
this.invokedSkills.add(name);
|
|
239
|
+
}
|
|
240
|
+
getInvokedSkills() {
|
|
241
|
+
return [...this.invokedSkills];
|
|
242
|
+
}
|
|
243
|
+
// ---------------------------------------------------------------------------
|
|
244
|
+
// Sticky session management
|
|
245
|
+
// ---------------------------------------------------------------------------
|
|
246
|
+
/** Remove a single sticky skill from a thread */
|
|
247
|
+
clearStickySkill(threadId, skillName) {
|
|
248
|
+
this.stickySessions.get(threadId)?.delete(skillName);
|
|
249
|
+
}
|
|
250
|
+
/** Remove all sticky skills for a thread (e.g. on clearHistory) */
|
|
251
|
+
clearStickySkills(threadId) {
|
|
252
|
+
this.stickySessions.delete(threadId);
|
|
253
|
+
}
|
|
254
|
+
/** Remove all sticky sessions across all threads (e.g. on destroy) */
|
|
255
|
+
clearAllStickySessions() {
|
|
256
|
+
this.stickySessions.clear();
|
|
257
|
+
}
|
|
258
|
+
// ---------------------------------------------------------------------------
|
|
259
|
+
// Private helpers
|
|
260
|
+
// ---------------------------------------------------------------------------
|
|
261
|
+
activateStickySession(threadId, skill) {
|
|
262
|
+
if (!this.stickySessions.has(threadId)) {
|
|
263
|
+
this.stickySessions.set(threadId, new Map());
|
|
264
|
+
}
|
|
265
|
+
const sessions = this.stickySessions.get(threadId);
|
|
266
|
+
// Don't reset an existing session (first activation wins)
|
|
267
|
+
if (!sessions.has(skill.name)) {
|
|
268
|
+
sessions.set(skill.name, {
|
|
269
|
+
skillName: skill.name,
|
|
270
|
+
activatedAt: Date.now(),
|
|
271
|
+
turnsRemaining: skill.sticky === true ? Infinity : skill.sticky,
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
decrementStickySessions(threadId) {
|
|
276
|
+
const sessions = this.stickySessions.get(threadId);
|
|
277
|
+
if (!sessions)
|
|
278
|
+
return;
|
|
279
|
+
for (const session of sessions.values()) {
|
|
280
|
+
if (session.turnsRemaining !== Infinity) {
|
|
281
|
+
session.turnsRemaining--;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/** Get all skills eligible for matching (unconditional + activated) */
|
|
286
|
+
getEligibleSkills() {
|
|
287
|
+
const eligible = [];
|
|
288
|
+
for (const skill of this.skills.values()) {
|
|
289
|
+
if (skill.isEnabled && !skill.isEnabled())
|
|
290
|
+
continue;
|
|
291
|
+
eligible.push(skill);
|
|
292
|
+
}
|
|
293
|
+
for (const skill of this.activatedSkills.values()) {
|
|
294
|
+
if (skill.isEnabled && !skill.isEnabled())
|
|
295
|
+
continue;
|
|
296
|
+
eligible.push(skill);
|
|
297
|
+
}
|
|
298
|
+
return eligible;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Returns true if any eligible skill lacks both triggerPrefix, aliases, and match(),
|
|
302
|
+
* meaning it can only be activated via semantic matching.
|
|
303
|
+
*/
|
|
304
|
+
hasSkillsNeedingSemantic(eligible) {
|
|
305
|
+
return eligible.some(s => !s.triggerPrefix && !s.aliases?.length && !s.match);
|
|
306
|
+
}
|
|
307
|
+
async semanticMatch(input, eligible) {
|
|
308
|
+
if (!this.embeddingService)
|
|
309
|
+
return [];
|
|
310
|
+
const inputEmbedding = await this.embeddingService.embedSingle(input);
|
|
311
|
+
const results = [];
|
|
312
|
+
for (const skill of eligible) {
|
|
313
|
+
// Only semantic-match skills that lack explicit matchers
|
|
314
|
+
if (skill.triggerPrefix || skill.aliases?.length || skill.match)
|
|
315
|
+
continue;
|
|
316
|
+
const text = skill.whenToUse
|
|
317
|
+
? `${skill.description}. ${skill.whenToUse}`
|
|
318
|
+
: skill.description;
|
|
319
|
+
const skillEmbedding = await this.embeddingService.embedSingle(text);
|
|
320
|
+
const score = cosineSimilarity(inputEmbedding, skillEmbedding);
|
|
321
|
+
if (score > 0.7) {
|
|
322
|
+
results.push({ skill, matchType: 'semantic', score });
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return results;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
function cosineSimilarity(a, b) {
|
|
329
|
+
let dot = 0, normA = 0, normB = 0;
|
|
330
|
+
for (let i = 0; i < a.length; i++) {
|
|
331
|
+
dot += a[i] * b[i];
|
|
332
|
+
normA += a[i] * a[i];
|
|
333
|
+
normB += b[i] * b[i];
|
|
334
|
+
}
|
|
335
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
336
|
+
return denom === 0 ? 0 : dot / denom;
|
|
337
|
+
}
|
|
338
|
+
//# sourceMappingURL=skill-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-manager.js","sourceRoot":"","sources":["../../src/skills/skill-manager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAe/C,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAEnC;;;;;GAKG;AACH,MAAM,OAAO,YAAY;IACvB,2EAA2E;IAC1D,MAAM,GAAG,IAAI,GAAG,EAAsB,CAAC;IACxD,+DAA+D;IAC9C,iBAAiB,GAAG,IAAI,GAAG,EAAsB,CAAC;IACnE,wEAAwE;IACvD,eAAe,GAAG,IAAI,GAAG,EAAsB,CAAC;IACjE,4DAA4D;IAC3C,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;IACnD,mFAAmF;IAClE,cAAc,GAAG,IAAI,GAAG,EAAsC,CAAC;IAE/D,gBAAgB,CAAoB;IACpC,eAAe,CAAS;IAEzC,YAAY,OAA2E;QACrF,IAAI,CAAC,gBAAgB,GAAG,OAAO,EAAE,gBAAgB,CAAC;QAClD,IAAI,CAAC,eAAe,GAAG,OAAO,EAAE,eAAe,IAAI,CAAC,CAAC;IACvD,CAAC;IAED,8EAA8E;IAC9E,eAAe;IACf,8EAA8E;IAE9E,QAAQ,CAAC,KAAiB;QACxB,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1C,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAED,UAAU,CAAC,IAAY;QACrB,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;eAC1B,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC;eACnC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,yDAAyD;IACzD,UAAU;QACR,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,oDAAoD;IACpD,aAAa;QACX,OAAO;YACL,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;YACvB,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE;YAChC,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE;SACnC,CAAC;IACJ,CAAC;IAED,8EAA8E;IAC9E,qBAAqB;IACrB,8EAA8E;IAE9E;;;OAGG;IACH,KAAK,CAAC,iBAAiB,CAAC,GAAW;QACjC,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,GAAG,CAAC,CAAC;QACzC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,CAAC;IACvB,CAAC;IAED,8EAA8E;IAC9E,8BAA8B;IAC9B,8EAA8E;IAE9E;;;OAGG;IACH,gBAAgB,CAAC,SAAmB;QAClC,MAAM,SAAS,GAAa,EAAE,CAAC;QAE/B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACnD,IAAI,CAAC,KAAK,CAAC,KAAK;gBAAE,SAAS;YAC3B,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,KAAM,EAAE,EAAE,CAAC,CAAC,CAAC;YACrE,IAAI,OAAO,EAAE,CAAC;gBACZ,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBACtC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACpC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,8EAA8E;IAC9E,WAAW;IACX,8EAA8E;IAE9E;;OAEG;IACH,KAAK,CAAC,KAAK,CAAC,KAAa,EAAE,OAA6B;QACtD,MAAM,OAAO,GAAuB,EAAE,CAAC;QACvC,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAE1C,wEAAwE;QACxE,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACjE,IAAI,cAAc,EAAE,CAAC;YACnB,KAAK,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,cAAc,EAAE,CAAC;gBAClD,IAAI,OAAO,CAAC,cAAc,IAAI,CAAC,EAAE,CAAC;oBAChC,cAAc,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;oBACjC,SAAS;gBACX,CAAC;gBACD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBAChF,IAAI,KAAK,EAAE,CAAC;oBACV,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;oBACzD,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC;YACD,8BAA8B;YAC9B,IAAI,cAAc,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBAC9B,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;YAC7B,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;gBAAE,SAAS;YAE3C,qCAAqC;YACrC,IAAI,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC;gBACjE,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;gBACzD,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC7B,SAAS;YACX,CAAC;YAED,iBAAiB;YACjB,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;gBAClB,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;oBACzC,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC;oBAC3D,OAAO,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;gBAClC,CAAC,CAAC,CAAC;gBACH,IAAI,OAAO,EAAE,CAAC;oBACZ,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;oBACzD,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAC7B,SAAS;gBACX,CAAC;YACH,CAAC;YAED,2BAA2B;YAC3B,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;gBACzF,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;gBACzD,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC7B,SAAS;YACX,CAAC;QACH,CAAC;QAED,0EAA0E;QAC1E,sDAAsD;QACtD,IAAI,IAAI,CAAC,gBAAgB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,wBAAwB,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7F,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YAClE,OAAO,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,CAAC;QACnC,CAAC;QAED,6EAA6E;QAC7E,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACnC,IAAI,CAAC,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS;gBAAE,OAAO,CAAC,CAAC,CAAC;YACvD,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC,KAAK,CAAC,SAAS;gBAAE,OAAO,CAAC,CAAC;YAEtD,MAAM,SAAS,GAA2B,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;YACvG,MAAM,QAAQ,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;YAC/E,IAAI,QAAQ,KAAK,CAAC;gBAAE,OAAO,QAAQ,CAAC;YAEpC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;QAEH,gFAAgF;QAChF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;gBACvB,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;QACD,IAAI,CAAC,uBAAuB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAE/C,6CAA6C;QAC7C,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC;YAC/B,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QAED,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACjE,CAAC;IAED,8EAA8E;IAC9E,4BAA4B;IAC5B,8EAA8E;IAE9E;;;;OAIG;IACH,KAAK,CAAC,mBAAmB,CACvB,KAAiB,EACjB,IAAY,EACZ,OAA2B;QAE3B,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACxC,CAAC;QAED,iDAAiD;QACjD,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChD,OAAO,cAAc,CAAC,KAAK,CAAC,YAAY,EAAE,IAAI,EAAE,KAAK,CAAC,QAAQ,EAAE;gBAC9D,SAAS,EAAE,OAAO,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,IAAI,EAAE;gBACnD,SAAS,EAAE,OAAO,CAAC,QAAQ;gBAC3B,QAAQ,EAAE,OAAO,CAAC,OAAO;aAC1B,CAAC,CAAC;QACL,CAAC;QAED,OAAO,KAAK,CAAC,YAAY,CAAC;IAC5B,CAAC;IAED,8EAA8E;IAC9E,2CAA2C;IAC3C,8EAA8E;IAE9E;;;OAGG;IACH,iBAAiB,CAAC,WAAmB;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,EAAE;aACtC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,KAAK,KAAK,CAAC,CAAC;QAE3C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAErC,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,SAAS,GAAG,CAAC,CAAC;QAElB,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,KAAK,CAAC,aAAa;gBAChC,CAAC,CAAC,KAAK,CAAC,aAAa;gBACrB,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YAErB,IAAI,IAAI,GAAG,KAAK,MAAM,KAAK,KAAK,CAAC,WAAW,EAAE,CAAC;YAC/C,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;gBACpB,IAAI,IAAI,MAAM,KAAK,CAAC,SAAS,EAAE,CAAC;YAClC,CAAC;YAED,4BAA4B;YAC5B,IAAI,IAAI,CAAC,MAAM,GAAG,sBAAsB,EAAE,CAAC;gBACzC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,sBAAsB,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;YAC3D,CAAC;YAED,IAAI,SAAS,GAAG,IAAI,CAAC,MAAM,GAAG,WAAW;gBAAE,MAAM;YACjD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjB,SAAS,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,iBAAiB;QACjD,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,8EAA8E;IAC9E,sBAAsB;IACtB,8EAA8E;IAE9E,WAAW,CAAC,IAAY;QACtB,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,gBAAgB;QACd,OAAO,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;IACjC,CAAC;IAED,8EAA8E;IAC9E,4BAA4B;IAC5B,8EAA8E;IAE9E,iDAAiD;IACjD,gBAAgB,CAAC,QAAgB,EAAE,SAAiB;QAClD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IACvD,CAAC;IAED,mEAAmE;IACnE,iBAAiB,CAAC,QAAgB;QAChC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;IAED,sEAAsE;IACtE,sBAAsB;QACpB,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;IAC9B,CAAC;IAED,8EAA8E;IAC9E,kBAAkB;IAClB,8EAA8E;IAEtE,qBAAqB,CAAC,QAAgB,EAAE,KAAiB;QAC/D,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC;QACpD,0DAA0D;QAC1D,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE;gBACvB,SAAS,EAAE,KAAK,CAAC,IAAI;gBACrB,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;gBACvB,cAAc,EAAE,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAE,KAAK,CAAC,MAAiB;aAC5E,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAEO,uBAAuB,CAAC,QAAgB;QAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACnD,IAAI,CAAC,QAAQ;YAAE,OAAO;QACtB,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YACxC,IAAI,OAAO,CAAC,cAAc,KAAK,QAAQ,EAAE,CAAC;gBACxC,OAAO,CAAC,cAAc,EAAE,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;IAED,uEAAuE;IAC/D,iBAAiB;QACvB,MAAM,QAAQ,GAAiB,EAAE,CAAC;QAClC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;YACzC,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;gBAAE,SAAS;YACpD,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,EAAE,CAAC;YAClD,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;gBAAE,SAAS;YACpD,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;OAGG;IACK,wBAAwB,CAAC,QAAsB;QACrD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAChF,CAAC;IAEO,KAAK,CAAC,aAAa,CACzB,KAAa,EACb,QAAsB;QAEtB,IAAI,CAAC,IAAI,CAAC,gBAAgB;YAAE,OAAO,EAAE,CAAC;QAEtC,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACtE,MAAM,OAAO,GAAuB,EAAE,CAAC;QAEvC,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;YAC7B,yDAAyD;YACzD,IAAI,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,OAAO,EAAE,MAAM,IAAI,KAAK,CAAC,KAAK;gBAAE,SAAS;YAE1E,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS;gBAC1B,CAAC,CAAC,GAAG,KAAK,CAAC,WAAW,KAAK,KAAK,CAAC,SAAS,EAAE;gBAC5C,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC;YACtB,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YACrE,MAAM,KAAK,GAAG,gBAAgB,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;YAE/D,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;gBAChB,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AAED,SAAS,gBAAgB,CAAC,CAAe,EAAE,CAAe;IACxD,IAAI,GAAG,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC;IAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAE,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;QACrB,KAAK,IAAI,CAAC,CAAC,CAAC,CAAE,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;QACvB,KAAK,IAAI,CAAC,CAAC,CAAC,CAAE,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;IACzB,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClD,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ConversationStore } from '../contracts/entities/stores.js';
|
|
2
|
+
import type { ChatMessage } from '../contracts/entities/chat-message.js';
|
|
3
|
+
import type { SQLiteDatabase } from './sqlite-database.js';
|
|
4
|
+
/**
|
|
5
|
+
* SQLite implementation of ConversationStore.
|
|
6
|
+
*/
|
|
7
|
+
export declare class SQLiteConversationStore implements ConversationStore {
|
|
8
|
+
private readonly database;
|
|
9
|
+
constructor(database: SQLiteDatabase);
|
|
10
|
+
appendMessage(message: ChatMessage, threadId: string): void;
|
|
11
|
+
listThread(threadId: string): ChatMessage[];
|
|
12
|
+
listPinned(threadId: string): ChatMessage[];
|
|
13
|
+
clearThread(threadId: string): void;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=sqlite-conversation-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-conversation-store.d.ts","sourceRoot":"","sources":["../../src/storage/sqlite-conversation-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D;;GAEG;AACH,qBAAa,uBAAwB,YAAW,iBAAiB;IAC/D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiB;gBAE9B,QAAQ,EAAE,cAAc;IAIpC,aAAa,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAe3D,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,EAAE;IAO3C,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,EAAE;IAO3C,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;CAGpC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite implementation of ConversationStore.
|
|
3
|
+
*/
|
|
4
|
+
export class SQLiteConversationStore {
|
|
5
|
+
database;
|
|
6
|
+
constructor(database) {
|
|
7
|
+
this.database = database;
|
|
8
|
+
}
|
|
9
|
+
appendMessage(message, threadId) {
|
|
10
|
+
this.database.db.prepare(`
|
|
11
|
+
INSERT INTO conversations (thread_id, role, content, tool_calls, tool_call_id, pinned, created_at)
|
|
12
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
13
|
+
`).run(threadId, message.role, typeof message.content === 'string' ? message.content : JSON.stringify(message.content), message.toolCalls ? JSON.stringify(message.toolCalls) : null, message.toolCallId ?? null, message.pinned ? 1 : 0, message.createdAt);
|
|
14
|
+
}
|
|
15
|
+
listThread(threadId) {
|
|
16
|
+
const rows = this.database.db.prepare('SELECT * FROM conversations WHERE thread_id = ? ORDER BY created_at ASC').all(threadId);
|
|
17
|
+
return rows.map(rowToMessage);
|
|
18
|
+
}
|
|
19
|
+
listPinned(threadId) {
|
|
20
|
+
const rows = this.database.db.prepare('SELECT * FROM conversations WHERE thread_id = ? AND pinned = 1 ORDER BY created_at ASC').all(threadId);
|
|
21
|
+
return rows.map(rowToMessage);
|
|
22
|
+
}
|
|
23
|
+
clearThread(threadId) {
|
|
24
|
+
this.database.db.prepare('DELETE FROM conversations WHERE thread_id = ?').run(threadId);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function rowToMessage(row) {
|
|
28
|
+
let content;
|
|
29
|
+
try {
|
|
30
|
+
const parsed = JSON.parse(row.content);
|
|
31
|
+
content = Array.isArray(parsed) ? parsed : row.content;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
content = row.content;
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
role: row.role,
|
|
38
|
+
content: content,
|
|
39
|
+
toolCalls: row.tool_calls ? JSON.parse(row.tool_calls) : undefined,
|
|
40
|
+
toolCallId: row.tool_call_id ?? undefined,
|
|
41
|
+
pinned: row.pinned === 1,
|
|
42
|
+
createdAt: row.created_at,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=sqlite-conversation-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-conversation-store.js","sourceRoot":"","sources":["../../src/storage/sqlite-conversation-store.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,OAAO,uBAAuB;IACjB,QAAQ,CAAiB;IAE1C,YAAY,QAAwB;QAClC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,aAAa,CAAC,OAAoB,EAAE,QAAgB;QAClD,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC;;;KAGxB,CAAC,CAAC,GAAG,CACJ,QAAQ,EACR,OAAO,CAAC,IAAI,EACZ,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,EACvF,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAC5D,OAAO,CAAC,UAAU,IAAI,IAAI,EAC1B,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACtB,OAAO,CAAC,SAAS,CAClB,CAAC;IACJ,CAAC;IAED,UAAU,CAAC,QAAgB;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,CACnC,yEAAyE,CAC1E,CAAC,GAAG,CAAC,QAAQ,CAAsB,CAAC;QACrC,OAAO,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAChC,CAAC;IAED,UAAU,CAAC,QAAgB;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,CACnC,wFAAwF,CACzF,CAAC,GAAG,CAAC,QAAQ,CAAsB,CAAC;QACrC,OAAO,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAChC,CAAC;IAED,WAAW,CAAC,QAAgB;QAC1B,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC,+CAA+C,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC1F,CAAC;CACF;AAED,SAAS,YAAY,CAAC,GAAoB;IACxC,IAAI,OAAqF,CAAC;IAC1F,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACvC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;IACxB,CAAC;IAED,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,IAA2B;QACrC,OAAO,EAAE,OAAiC;QAC1C,SAAS,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS;QAClE,UAAU,EAAE,GAAG,CAAC,YAAY,IAAI,SAAS;QACzC,MAAM,EAAE,GAAG,CAAC,MAAM,KAAK,CAAC;QACxB,SAAS,EAAE,GAAG,CAAC,UAAU;KAC1B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type BetterSqlite3 from 'better-sqlite3';
|
|
2
|
+
/**
|
|
3
|
+
* Centralized SQLite wrapper with auto-create tables, migrations, and WAL mode.
|
|
4
|
+
*/
|
|
5
|
+
export declare class SQLiteDatabase {
|
|
6
|
+
private _db;
|
|
7
|
+
private readonly path;
|
|
8
|
+
constructor(path: string);
|
|
9
|
+
get db(): BetterSqlite3.Database;
|
|
10
|
+
initialize(): void;
|
|
11
|
+
close(): void;
|
|
12
|
+
private migrateV1;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=sqlite-database.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-database.d.ts","sourceRoot":"","sources":["../../src/storage/sqlite-database.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAEhD;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,GAAG,CAAuC;IAClD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;gBAElB,IAAI,EAAE,MAAM;IAIxB,IAAI,EAAE,IAAI,aAAa,CAAC,QAAQ,CAG/B;IAED,UAAU,IAAI,IAAI;IAiBlB,KAAK,IAAI,IAAI;IAOb,OAAO,CAAC,SAAS;CA+DlB"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { mkdirSync } from 'node:fs';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
import Database from 'better-sqlite3';
|
|
4
|
+
/**
|
|
5
|
+
* Centralized SQLite wrapper with auto-create tables, migrations, and WAL mode.
|
|
6
|
+
*/
|
|
7
|
+
export class SQLiteDatabase {
|
|
8
|
+
_db = null;
|
|
9
|
+
path;
|
|
10
|
+
constructor(path) {
|
|
11
|
+
this.path = path;
|
|
12
|
+
}
|
|
13
|
+
get db() {
|
|
14
|
+
if (!this._db)
|
|
15
|
+
throw new Error('Database not initialized. Call initialize() first.');
|
|
16
|
+
return this._db;
|
|
17
|
+
}
|
|
18
|
+
initialize() {
|
|
19
|
+
if (this._db)
|
|
20
|
+
return;
|
|
21
|
+
// Auto-create parent directory for file-based databases
|
|
22
|
+
if (this.path !== ':memory:') {
|
|
23
|
+
mkdirSync(dirname(this.path), { recursive: true });
|
|
24
|
+
}
|
|
25
|
+
this._db = new Database(this.path);
|
|
26
|
+
// Enable WAL mode for concurrent reads
|
|
27
|
+
this._db.pragma('journal_mode = WAL');
|
|
28
|
+
this._db.pragma('synchronous = NORMAL');
|
|
29
|
+
this.migrateV1();
|
|
30
|
+
}
|
|
31
|
+
close() {
|
|
32
|
+
if (this._db) {
|
|
33
|
+
this._db.close();
|
|
34
|
+
this._db = null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
migrateV1() {
|
|
38
|
+
const db = this.db;
|
|
39
|
+
db.exec(`
|
|
40
|
+
CREATE TABLE IF NOT EXISTS memories (
|
|
41
|
+
id TEXT PRIMARY KEY,
|
|
42
|
+
content TEXT NOT NULL,
|
|
43
|
+
scope TEXT NOT NULL,
|
|
44
|
+
category TEXT NOT NULL,
|
|
45
|
+
confidence REAL NOT NULL DEFAULT 0.8,
|
|
46
|
+
access_count INTEGER NOT NULL DEFAULT 0,
|
|
47
|
+
source TEXT NOT NULL DEFAULT 'extracted',
|
|
48
|
+
thread_id TEXT,
|
|
49
|
+
embedding BLOB,
|
|
50
|
+
created_at INTEGER NOT NULL,
|
|
51
|
+
last_accessed_at INTEGER NOT NULL
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
CREATE INDEX IF NOT EXISTS idx_memories_scope ON memories(scope);
|
|
55
|
+
CREATE INDEX IF NOT EXISTS idx_memories_thread ON memories(thread_id);
|
|
56
|
+
CREATE INDEX IF NOT EXISTS idx_memories_confidence ON memories(confidence);
|
|
57
|
+
`);
|
|
58
|
+
// FTS5 virtual table for full-text search
|
|
59
|
+
// Check if already exists (FTS5 tables don't support IF NOT EXISTS in all versions)
|
|
60
|
+
const ftsExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='memories_fts'").get();
|
|
61
|
+
if (!ftsExists) {
|
|
62
|
+
db.exec(`
|
|
63
|
+
CREATE VIRTUAL TABLE memories_fts USING fts5(
|
|
64
|
+
content,
|
|
65
|
+
content=memories,
|
|
66
|
+
content_rowid=rowid
|
|
67
|
+
);
|
|
68
|
+
`);
|
|
69
|
+
}
|
|
70
|
+
db.exec(`
|
|
71
|
+
CREATE TABLE IF NOT EXISTS vectors (
|
|
72
|
+
id TEXT PRIMARY KEY,
|
|
73
|
+
content TEXT NOT NULL,
|
|
74
|
+
embedding BLOB NOT NULL,
|
|
75
|
+
metadata TEXT,
|
|
76
|
+
created_at INTEGER NOT NULL
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
CREATE TABLE IF NOT EXISTS conversations (
|
|
80
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
81
|
+
thread_id TEXT NOT NULL,
|
|
82
|
+
role TEXT NOT NULL,
|
|
83
|
+
content TEXT NOT NULL,
|
|
84
|
+
tool_calls TEXT,
|
|
85
|
+
tool_call_id TEXT,
|
|
86
|
+
pinned INTEGER NOT NULL DEFAULT 0,
|
|
87
|
+
created_at INTEGER NOT NULL
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
CREATE INDEX IF NOT EXISTS idx_conversations_thread ON conversations(thread_id, created_at);
|
|
91
|
+
CREATE INDEX IF NOT EXISTS idx_conversations_pinned ON conversations(thread_id, pinned);
|
|
92
|
+
`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=sqlite-database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-database.js","sourceRoot":"","sources":["../../src/storage/sqlite-database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAGtC;;GAEG;AACH,MAAM,OAAO,cAAc;IACjB,GAAG,GAAkC,IAAI,CAAC;IACjC,IAAI,CAAS;IAE9B,YAAY,IAAY;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,IAAI,EAAE;QACJ,IAAI,CAAC,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACrF,OAAO,IAAI,CAAC,GAAG,CAAC;IAClB,CAAC;IAED,UAAU;QACR,IAAI,IAAI,CAAC,GAAG;YAAE,OAAO;QAErB,wDAAwD;QACxD,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC7B,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,CAAC,GAAG,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEnC,uCAAuC;QACvC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACtC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;QAExC,IAAI,CAAC,SAAS,EAAE,CAAC;IACnB,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;YACjB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;QAClB,CAAC;IACH,CAAC;IAEO,SAAS;QACf,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;QAEnB,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;KAkBP,CAAC,CAAC;QAEH,0CAA0C;QAC1C,oFAAoF;QACpF,MAAM,SAAS,GAAG,EAAE,CAAC,OAAO,CAC1B,2EAA2E,CAC5E,CAAC,GAAG,EAAE,CAAC;QAER,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,EAAE,CAAC,IAAI,CAAC;;;;;;OAMP,CAAC,CAAC;QACL,CAAC;QAED,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;KAsBP,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AgentTool } from '../../contracts/entities/agent-tool.js';
|
|
2
|
+
export interface AskUserOptions {
|
|
3
|
+
/** Callback invoked when the model asks a question. Consumer implements this. */
|
|
4
|
+
onAsk: (question: string, options?: string[]) => Promise<string>;
|
|
5
|
+
}
|
|
6
|
+
export declare function createAskUserTool(opts: AskUserOptions): AgentTool;
|
|
7
|
+
//# sourceMappingURL=ask-user.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ask-user.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/ask-user.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAC;AAOxE,MAAM,WAAW,cAAc;IAC7B,iFAAiF;IACjF,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAClE;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,cAAc,GAAG,SAAS,CAiBjE"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const AskUserParams = z.object({
|
|
3
|
+
question: z.string().describe('Question to ask the user'),
|
|
4
|
+
options: z.array(z.string()).optional().describe('Optional multiple-choice options'),
|
|
5
|
+
});
|
|
6
|
+
export function createAskUserTool(opts) {
|
|
7
|
+
return {
|
|
8
|
+
name: 'AskUser',
|
|
9
|
+
description: 'Ask the user a question and wait for their response. Use when you need clarification or confirmation.',
|
|
10
|
+
parameters: AskUserParams,
|
|
11
|
+
async execute(rawArgs) {
|
|
12
|
+
const { question, options } = rawArgs;
|
|
13
|
+
try {
|
|
14
|
+
const answer = await opts.onAsk(question, options);
|
|
15
|
+
return `User responded: ${answer}`;
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
return { content: `Failed to get user response: ${error.message}`, isError: true };
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=ask-user.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ask-user.js","sourceRoot":"","sources":["../../../src/tools/builtin/ask-user.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;IACzD,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;CACrF,CAAC,CAAC;AAOH,MAAM,UAAU,iBAAiB,CAAC,IAAoB;IACpD,OAAO;QACL,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,uGAAuG;QACpH,UAAU,EAAE,aAAa;QAEzB,KAAK,CAAC,OAAO,CAAC,OAAgB;YAC5B,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAwC,CAAC;YAEvE,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACnD,OAAO,mBAAmB,MAAM,EAAE,CAAC;YACrC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,EAAE,OAAO,EAAE,gCAAiC,KAAe,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAChG,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/bash.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAC;AAUxE,wBAAgB,cAAc,IAAI,SAAS,CA4C1C"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { exec } from 'node:child_process';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
const DEFAULT_TIMEOUT = 120_000;
|
|
4
|
+
const MAX_OUTPUT = 500_000; // 500KB
|
|
5
|
+
const BashParams = z.object({
|
|
6
|
+
command: z.string().describe('Shell command to execute'),
|
|
7
|
+
timeout: z.number().optional().describe('Timeout in milliseconds. Default: 120000 (2 minutes).'),
|
|
8
|
+
});
|
|
9
|
+
export function createBashTool() {
|
|
10
|
+
return {
|
|
11
|
+
name: 'Bash',
|
|
12
|
+
description: 'Execute a shell command and return stdout/stderr.',
|
|
13
|
+
parameters: BashParams,
|
|
14
|
+
isDestructive: true, // conservative — commands can have side effects
|
|
15
|
+
timeoutMs: DEFAULT_TIMEOUT,
|
|
16
|
+
async execute(rawArgs, signal) {
|
|
17
|
+
const { command, timeout } = rawArgs;
|
|
18
|
+
const effectiveTimeout = timeout ?? DEFAULT_TIMEOUT;
|
|
19
|
+
return new Promise((resolve) => {
|
|
20
|
+
exec(command, {
|
|
21
|
+
timeout: effectiveTimeout,
|
|
22
|
+
maxBuffer: MAX_OUTPUT,
|
|
23
|
+
shell: process.env.SHELL || '/bin/sh',
|
|
24
|
+
signal,
|
|
25
|
+
}, (error, stdout, stderr) => {
|
|
26
|
+
const out = stdout?.slice(0, MAX_OUTPUT) ?? '';
|
|
27
|
+
const err = stderr?.slice(0, MAX_OUTPUT) ?? '';
|
|
28
|
+
if (error) {
|
|
29
|
+
const exitCode = error.code ?? 'unknown';
|
|
30
|
+
const parts = [];
|
|
31
|
+
if (out)
|
|
32
|
+
parts.push(out);
|
|
33
|
+
if (err)
|
|
34
|
+
parts.push(err);
|
|
35
|
+
if (!out && !err)
|
|
36
|
+
parts.push(error.message);
|
|
37
|
+
parts.push(`\nExit code: ${exitCode}`);
|
|
38
|
+
resolve({ content: parts.join('\n'), isError: true });
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const parts = [];
|
|
42
|
+
if (out)
|
|
43
|
+
parts.push(out);
|
|
44
|
+
if (err)
|
|
45
|
+
parts.push(`[stderr]\n${err}`);
|
|
46
|
+
if (!out && !err)
|
|
47
|
+
parts.push('(no output)');
|
|
48
|
+
resolve(parts.join('\n'));
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=bash.js.map
|