@game_ryo/lsji 0.1.0 → 0.3.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/package.json +15 -7
- package/src/cli.js +395 -62
- package/src/execution/budget/circuit-breaker.js +245 -0
- package/src/execution/budget/cost-tracker.js +387 -0
- package/src/execution/budget/index.js +63 -0
- package/src/execution/budget/token-counter.js +159 -0
- package/src/execution/engine.js +428 -0
- package/src/execution/hitl/approval-gate.js +210 -0
- package/src/execution/hitl/index.js +12 -0
- package/src/execution/hitl/notifier.js +151 -0
- package/src/execution/hitl/store.js +311 -0
- package/src/execution/idempotency.js +312 -0
- package/src/execution/index.js +14 -0
- package/src/index.js +80 -4
- package/src/llm/index.js +21 -0
- package/src/llm/llm-agent.js +357 -0
- package/src/llm/memory/conversation.js +271 -0
- package/src/llm/memory/episodic.js +312 -0
- package/src/llm/memory/index.js +12 -0
- package/src/llm/memory/semantic.js +324 -0
- package/src/llm/plugins/index.js +202 -0
- package/src/llm/prompt-manager.js +332 -0
- package/src/llm/providers/anthropic.js +250 -0
- package/src/llm/providers/base.js +116 -0
- package/src/llm/providers/local.js +163 -0
- package/src/llm/providers/openai.js +212 -0
- package/src/llm/tools/registry.js +342 -0
- package/src/server/index.js +416 -0
- package/src/server/ui/index.html +16 -0
- package/src/server/ui/package.json +19 -0
- package/src/server/ui/src/main.jsx +10 -0
- package/src/server/ui/src/styles.css +260 -0
- package/src/server/ui/vite.config.js +27 -0
- package/docs/README.md +0 -43
- package/docs/blog/2019-05-28-first-blog-post.mdx +0 -12
- package/docs/blog/2019-05-29-long-blog-post.mdx +0 -44
- package/docs/blog/2021-08-01-mdx-blog-post.mdx +0 -24
- package/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
- package/docs/blog/2021-08-26-welcome/index.mdx +0 -29
- package/docs/blog/authors.yml +0 -25
- package/docs/blog/tags.yml +0 -19
- package/docs/docs/api/agent.md +0 -151
- package/docs/docs/api/env.md +0 -133
- package/docs/docs/api/environments.md +0 -102
- package/docs/docs/api/qlearning.md +0 -138
- package/docs/docs/api/storage.md +0 -168
- package/docs/docs/architecture.md +0 -155
- package/docs/docs/cli.md +0 -210
- package/docs/docs/contributing.md +0 -162
- package/docs/docs/core-concepts.md +0 -152
- package/docs/docs/examples/advanced-training.md +0 -244
- package/docs/docs/examples/custom-environment.md +0 -198
- package/docs/docs/examples/custom-storage.md +0 -251
- package/docs/docs/getting-started.md +0 -91
- package/docs/docusaurus.config.ts +0 -149
- package/docs/package-lock.json +0 -19522
- package/docs/package.json +0 -49
- package/docs/sidebars.ts +0 -33
- package/docs/src/components/HomepageFeatures/index.tsx +0 -71
- package/docs/src/components/HomepageFeatures/styles.module.css +0 -11
- package/docs/src/css/custom.css +0 -79
- package/docs/src/pages/index.module.css +0 -23
- package/docs/src/pages/index.tsx +0 -44
- package/docs/src/pages/markdown-page.mdx +0 -7
- package/docs/static/.nojekyll +0 -0
- package/docs/static/img/docusaurus-social-card.jpg +0 -0
- package/docs/static/img/docusaurus.png +0 -0
- package/docs/static/img/favicon.ico +0 -0
- package/docs/static/img/logo.png +0 -0
- package/docs/static/img/undraw_docusaurus_mountain.svg +0 -171
- package/docs/static/img/undraw_docusaurus_react.svg +0 -170
- package/docs/static/img/undraw_docusaurus_tree.svg +0 -40
- package/docs/tsconfig.json +0 -12
- package/legacy/worker.js +0 -166
- package/legacy/wrangler.toml +0 -11
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LSJI Tool Plugin System
|
|
3
|
+
*
|
|
4
|
+
* Dynamic plugin loading for custom tools.
|
|
5
|
+
* Plugins are JavaScript modules that export tool definitions.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
import { dirname, resolve, join } from 'path';
|
|
10
|
+
import { readdir } from 'fs/promises';
|
|
11
|
+
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = dirname(__filename);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Plugin definition
|
|
17
|
+
* @typedef {Object} Plugin
|
|
18
|
+
* @property {string} name - Plugin name
|
|
19
|
+
* @property {string} version - Plugin version
|
|
20
|
+
* @property {Object} tools - Object mapping tool names to tool definitions
|
|
21
|
+
* @property {Function} [init] - Optional initialization function
|
|
22
|
+
* @property {Function} [cleanup] - Optional cleanup function
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Default plugin directories to scan
|
|
27
|
+
*/
|
|
28
|
+
const DEFAULT_PLUGIN_DIRS = [
|
|
29
|
+
resolve(process.cwd(), 'lsji-plugins'),
|
|
30
|
+
resolve(__dirname, '../../plugins'),
|
|
31
|
+
resolve(process.cwd(), '.lsji/plugins'),
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Load plugins from directory
|
|
36
|
+
* @param {string|string[]} pluginPaths - Paths to plugin directories or files
|
|
37
|
+
* @returns {Promise<Object>} Map of toolName -> toolDefinition
|
|
38
|
+
*/
|
|
39
|
+
export async function loadPlugins(pluginPaths = []) {
|
|
40
|
+
const allTools = {};
|
|
41
|
+
const dirs = [...DEFAULT_PLUGIN_DIRS, ...(Array.isArray(pluginPaths) ? pluginPaths : [pluginPaths])];
|
|
42
|
+
|
|
43
|
+
for (const dir of dirs) {
|
|
44
|
+
try {
|
|
45
|
+
const tools = await loadPluginDirectory(dir);
|
|
46
|
+
Object.assign(allTools, tools);
|
|
47
|
+
} catch (error) {
|
|
48
|
+
if (error.code !== 'ENOENT') {
|
|
49
|
+
console.warn(`Failed to load plugins from ${dir}:`, error.message);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return allTools;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Load all plugins from a directory
|
|
59
|
+
*/
|
|
60
|
+
async function loadPluginDirectory(dir) {
|
|
61
|
+
const tools = {};
|
|
62
|
+
|
|
63
|
+
let entries;
|
|
64
|
+
try {
|
|
65
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
66
|
+
} catch {
|
|
67
|
+
return tools;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
for (const entry of entries) {
|
|
71
|
+
if (!entry.isFile() || !entry.name.endsWith('.js')) continue;
|
|
72
|
+
|
|
73
|
+
const filePath = join(dir, entry.name);
|
|
74
|
+
try {
|
|
75
|
+
const plugin = await import(filePath);
|
|
76
|
+
const pluginModule = plugin.default || plugin;
|
|
77
|
+
|
|
78
|
+
if (pluginModule.tools) {
|
|
79
|
+
for (const [name, definition] of Object.entries(pluginModule.tools)) {
|
|
80
|
+
tools[name] = {
|
|
81
|
+
...definition,
|
|
82
|
+
plugin: pluginModule.name || entry.name.replace('.js', ''),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (pluginModule.init) {
|
|
88
|
+
await pluginModule.init();
|
|
89
|
+
}
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.warn(`Failed to load plugin ${filePath}:`, error.message);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return tools;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Create a plugin template
|
|
100
|
+
*/
|
|
101
|
+
export function createPluginTemplate(name) {
|
|
102
|
+
return `/**
|
|
103
|
+
* ${name} Plugin for LSJI
|
|
104
|
+
*
|
|
105
|
+
* Drop this file in lsji-plugins/ directory to enable.
|
|
106
|
+
*/
|
|
107
|
+
|
|
108
|
+
export default {
|
|
109
|
+
name: '${name}',
|
|
110
|
+
version: '1.0.0',
|
|
111
|
+
|
|
112
|
+
tools: {
|
|
113
|
+
${name}_example: {
|
|
114
|
+
name: '${name}_example',
|
|
115
|
+
description: 'Example tool from ${name} plugin',
|
|
116
|
+
category: 'plugin',
|
|
117
|
+
parameters: {
|
|
118
|
+
type: 'object',
|
|
119
|
+
properties: {
|
|
120
|
+
input: { type: 'string', description: 'Input parameter' },
|
|
121
|
+
},
|
|
122
|
+
required: ['input'],
|
|
123
|
+
},
|
|
124
|
+
requiresApproval: false,
|
|
125
|
+
idempotent: true,
|
|
126
|
+
async execute({ input }, context) {
|
|
127
|
+
return { result: \`Processed: \${input}\`, plugin: '${name}' };
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
async init() {
|
|
133
|
+
console.log('[${name}] Plugin initialized');
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
async cleanup() {
|
|
137
|
+
console.log('[${name}] Plugin cleaned up');
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
`;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Plugin registry for runtime management
|
|
145
|
+
*/
|
|
146
|
+
export class PluginRegistry {
|
|
147
|
+
constructor() {
|
|
148
|
+
this.plugins = new Map();
|
|
149
|
+
this.tools = new Map();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
register(plugin) {
|
|
153
|
+
if (!plugin.name || !plugin.tools) {
|
|
154
|
+
throw new Error('Plugin must have name and tools');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
this.plugins.set(plugin.name, plugin);
|
|
158
|
+
|
|
159
|
+
for (const [name, tool] of Object.entries(plugin.tools)) {
|
|
160
|
+
this.tools.set(name, { ...tool, plugin: plugin.name });
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (plugin.init) {
|
|
164
|
+
plugin.init();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async unregister(name) {
|
|
169
|
+
const plugin = this.plugins.get(name);
|
|
170
|
+
if (!plugin) return false;
|
|
171
|
+
|
|
172
|
+
if (plugin.cleanup) {
|
|
173
|
+
await plugin.cleanup();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
for (const toolName of Object.keys(plugin.tools)) {
|
|
177
|
+
this.tools.delete(toolName);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
this.plugins.delete(name);
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
getTools() {
|
|
185
|
+
return Object.fromEntries(this.tools);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
getPlugin(name) {
|
|
189
|
+
return this.plugins.get(name);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
listPlugins() {
|
|
193
|
+
return Array.from(this.plugins.values()).map(p => ({
|
|
194
|
+
name: p.name,
|
|
195
|
+
version: p.version,
|
|
196
|
+
toolCount: Object.keys(p.tools).length,
|
|
197
|
+
}));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Global registry
|
|
202
|
+
export const globalPluginRegistry = new PluginRegistry();
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages prompt templates with versioning and variable substitution.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createStorage } from '../index.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Prompt template
|
|
11
|
+
* @typedef {Object} PromptTemplate
|
|
12
|
+
* @property {string} name - Template name
|
|
13
|
+
* @property {string} version - Template version
|
|
14
|
+
* @property {string} template - Template string with {{variables}}
|
|
15
|
+
* @property {Array<string>} variables - Required variables
|
|
16
|
+
* @property {string} description - Template description
|
|
17
|
+
* @property {Date} createdAt
|
|
18
|
+
* @property {Date} updatedAt
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Prompt Manager - Template management with versioning
|
|
23
|
+
*/
|
|
24
|
+
export class PromptManager {
|
|
25
|
+
constructor({ storage } = {}) {
|
|
26
|
+
this.storage = storage;
|
|
27
|
+
this.templates = new Map(); // name -> { versions: Map<version, template> }
|
|
28
|
+
this.initialized = false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Initialize prompts table
|
|
33
|
+
*/
|
|
34
|
+
async initialize() {
|
|
35
|
+
if (this.initialized) return;
|
|
36
|
+
|
|
37
|
+
if (this.storage.db) {
|
|
38
|
+
await this.storage.db.exec(`
|
|
39
|
+
CREATE TABLE IF NOT EXISTS prompts (
|
|
40
|
+
name TEXT NOT NULL,
|
|
41
|
+
version TEXT NOT NULL,
|
|
42
|
+
template TEXT NOT NULL,
|
|
43
|
+
variables TEXT NOT NULL,
|
|
44
|
+
description TEXT,
|
|
45
|
+
created_at TEXT NOT NULL,
|
|
46
|
+
updated_at TEXT NOT NULL,
|
|
47
|
+
PRIMARY KEY (name, version)
|
|
48
|
+
)
|
|
49
|
+
`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
this.initialized = true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Register a prompt template
|
|
57
|
+
*/
|
|
58
|
+
async register(name, template, { version = '1.0.0', variables = [], description = '' } = {}) {
|
|
59
|
+
await this.initialize();
|
|
60
|
+
|
|
61
|
+
// Extract variables from template if not provided
|
|
62
|
+
const extractedVars = variables.length > 0 ? variables : this.extractVariables(template);
|
|
63
|
+
|
|
64
|
+
const prompt = {
|
|
65
|
+
name,
|
|
66
|
+
version,
|
|
67
|
+
template,
|
|
68
|
+
variables: extractedVars,
|
|
69
|
+
description,
|
|
70
|
+
createdAt: new Date().toISOString(),
|
|
71
|
+
updatedAt: new Date().toISOString(),
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// Store in memory
|
|
75
|
+
if (!this.templates.has(name)) {
|
|
76
|
+
this.templates.set(name, new Map());
|
|
77
|
+
}
|
|
78
|
+
this.templates.get(name).set(version, prompt);
|
|
79
|
+
|
|
80
|
+
// Persist
|
|
81
|
+
if (this.storage.db) {
|
|
82
|
+
await this.storage.db.run(
|
|
83
|
+
`INSERT OR REPLACE INTO prompts (name, version, template, variables, description, created_at, updated_at)
|
|
84
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
85
|
+
[name, version, template, JSON.stringify(extractedVars), description, prompt.createdAt, prompt.updatedAt]
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return prompt;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get a prompt template (latest version by default)
|
|
94
|
+
*/
|
|
95
|
+
async get(name, version = null) {
|
|
96
|
+
await this.initialize();
|
|
97
|
+
|
|
98
|
+
const versions = this.templates.get(name);
|
|
99
|
+
if (!versions) return null;
|
|
100
|
+
|
|
101
|
+
if (version) {
|
|
102
|
+
return versions.get(version) || null;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Get latest version
|
|
106
|
+
const sortedVersions = Array.from(versions.keys()).sort((a, b) => {
|
|
107
|
+
const parseVersion = v => v.split('.').map(Number);
|
|
108
|
+
const va = parseVersion(a);
|
|
109
|
+
const vb = parseVersion(b);
|
|
110
|
+
for (let i = 0; i < 3; i++) {
|
|
111
|
+
if (va[i] !== vb[i]) return vb[i] - va[i];
|
|
112
|
+
}
|
|
113
|
+
return 0;
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
return versions.get(sortedVersions[0]) || null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Get all versions of a prompt
|
|
121
|
+
*/
|
|
122
|
+
async getAllVersions(name) {
|
|
123
|
+
await this.initialize();
|
|
124
|
+
const versions = this.templates.get(name);
|
|
125
|
+
if (!versions) return [];
|
|
126
|
+
return Array.from(versions.values()).sort((a, b) =>
|
|
127
|
+
new Date(b.createdAt) - new Date(a.createdAt)
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Render a prompt with variables
|
|
133
|
+
*/
|
|
134
|
+
async render(name, variables, version = null) {
|
|
135
|
+
const prompt = await this.get(name, version);
|
|
136
|
+
if (!prompt) {
|
|
137
|
+
throw new Error(`Prompt not found: ${name}${version ? `@${version}` : ''}`);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Check required variables
|
|
141
|
+
for (const v of prompt.variables) {
|
|
142
|
+
if (!(v in variables)) {
|
|
143
|
+
throw new Error(`Missing required variable: ${v}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Substitute variables
|
|
148
|
+
let rendered = prompt.template;
|
|
149
|
+
for (const [key, value] of Object.entries(variables)) {
|
|
150
|
+
const placeholder = `{{${key}}}`;
|
|
151
|
+
rendered = rendered.replaceAll(placeholder, String(value));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return rendered;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Render multiple prompts (for system + user messages)
|
|
159
|
+
*/
|
|
160
|
+
async renderAll(prompts, variables) {
|
|
161
|
+
const results = [];
|
|
162
|
+
for (const { name, version, role = 'user' } of prompts) {
|
|
163
|
+
const content = await this.render(name, variables, version);
|
|
164
|
+
results.push({ role, content });
|
|
165
|
+
}
|
|
166
|
+
return results;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Extract variables from template
|
|
171
|
+
*/
|
|
172
|
+
extractVariables(template) {
|
|
173
|
+
const matches = template.match(/{{(\w+)}}/g);
|
|
174
|
+
if (!matches) return [];
|
|
175
|
+
return [...new Set(matches.map(m => m.slice(2, -2)))];
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* List all prompt names
|
|
180
|
+
*/
|
|
181
|
+
async list() {
|
|
182
|
+
await this.initialize();
|
|
183
|
+
return Array.from(this.templates.keys());
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Delete a prompt version
|
|
188
|
+
*/
|
|
189
|
+
async delete(name, version) {
|
|
190
|
+
await this.initialize();
|
|
191
|
+
|
|
192
|
+
const versions = this.templates.get(name);
|
|
193
|
+
if (!versions || !versions.has(version)) {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
versions.delete(version);
|
|
198
|
+
|
|
199
|
+
if (this.storage.db) {
|
|
200
|
+
await this.storage.db.run(
|
|
201
|
+
'DELETE FROM prompts WHERE name = ? AND version = ?',
|
|
202
|
+
[name, version]
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Load all prompts from storage
|
|
211
|
+
*/
|
|
212
|
+
async loadAll() {
|
|
213
|
+
await this.initialize();
|
|
214
|
+
|
|
215
|
+
if (this.storage.db) {
|
|
216
|
+
const rows = await this.storage.db.all('SELECT * FROM prompts');
|
|
217
|
+
for (const row of rows) {
|
|
218
|
+
if (!this.templates.has(row.name)) {
|
|
219
|
+
this.templates.set(row.name, new Map());
|
|
220
|
+
}
|
|
221
|
+
this.templates.get(row.name).set(row.version, {
|
|
222
|
+
name: row.name,
|
|
223
|
+
version: row.version,
|
|
224
|
+
template: row.template,
|
|
225
|
+
variables: JSON.parse(row.variables || '[]'),
|
|
226
|
+
description: row.description,
|
|
227
|
+
createdAt: row.created_at,
|
|
228
|
+
updatedAt: row.updated_at,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Built-in prompt templates
|
|
237
|
+
*/
|
|
238
|
+
export const BUILTIN_PROMPTS = {
|
|
239
|
+
'system:react': {
|
|
240
|
+
template: `You are an AI assistant that uses the ReAct pattern (Reasoning + Acting) to solve tasks.
|
|
241
|
+
|
|
242
|
+
You have access to the following tools:
|
|
243
|
+
{{tools}}
|
|
244
|
+
|
|
245
|
+
When you need to use a tool, respond with:
|
|
246
|
+
THOUGHT: Your reasoning about what to do next
|
|
247
|
+
ACTION: The tool name to use
|
|
248
|
+
ACTION_INPUT: The parameters for the tool
|
|
249
|
+
|
|
250
|
+
After the tool returns, you'll see:
|
|
251
|
+
OBSERVATION: The result
|
|
252
|
+
|
|
253
|
+
Continue this pattern until you can provide the final answer.
|
|
254
|
+
|
|
255
|
+
Current task: {{task}}`,
|
|
256
|
+
variables: ['tools', 'task'],
|
|
257
|
+
description: 'ReAct system prompt with tool definitions',
|
|
258
|
+
},
|
|
259
|
+
|
|
260
|
+
'system:planner': {
|
|
261
|
+
template: `You are a planning agent. Break down the task into a sequence of steps.
|
|
262
|
+
|
|
263
|
+
Task: {{task}}
|
|
264
|
+
|
|
265
|
+
Available tools: {{tools}}
|
|
266
|
+
|
|
267
|
+
Create a plan with numbered steps. Each step should specify:
|
|
268
|
+
1. What tool to use (if any)
|
|
269
|
+
2. What parameters to pass
|
|
270
|
+
3. What you expect to learn or achieve
|
|
271
|
+
|
|
272
|
+
Output as JSON:
|
|
273
|
+
{
|
|
274
|
+
"steps": [
|
|
275
|
+
{"step": 1, "tool": "tool_name", "params": {}, "description": "..."}
|
|
276
|
+
]
|
|
277
|
+
}`,
|
|
278
|
+
variables: ['task', 'tools'],
|
|
279
|
+
description: 'Planning agent prompt',
|
|
280
|
+
},
|
|
281
|
+
|
|
282
|
+
'system:code-reviewer': {
|
|
283
|
+
template: `You are an expert code reviewer. Analyze the provided code for:
|
|
284
|
+
- Bugs and logic errors
|
|
285
|
+
- Security vulnerabilities
|
|
286
|
+
- Performance issues
|
|
287
|
+
- Code style and best practices
|
|
288
|
+
- Test coverage gaps
|
|
289
|
+
|
|
290
|
+
Code to review:
|
|
291
|
+
{{code}}
|
|
292
|
+
|
|
293
|
+
Context: {{context}}
|
|
294
|
+
|
|
295
|
+
Provide your review in this format:
|
|
296
|
+
## Summary
|
|
297
|
+
Brief overall assessment
|
|
298
|
+
|
|
299
|
+
## Issues Found
|
|
300
|
+
- [Severity] File:Line - Description
|
|
301
|
+
|
|
302
|
+
## Suggestions
|
|
303
|
+
- Improvement suggestions
|
|
304
|
+
|
|
305
|
+
## Approved: true/false`,
|
|
306
|
+
variables: ['code', 'context'],
|
|
307
|
+
description: 'Code review prompt',
|
|
308
|
+
},
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Create prompt manager with built-in templates
|
|
313
|
+
*/
|
|
314
|
+
export async function createPromptManager(config = {}) {
|
|
315
|
+
const storage = await createStorage(
|
|
316
|
+
config.storage?.type || 'sqlite',
|
|
317
|
+
config.storage?.options || {}
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
const manager = new PromptManager({ storage });
|
|
321
|
+
await manager.initialize();
|
|
322
|
+
|
|
323
|
+
// Register built-in prompts
|
|
324
|
+
for (const [name, prompt] of Object.entries(BUILTIN_PROMPTS)) {
|
|
325
|
+
await manager.register(name, prompt.template, {
|
|
326
|
+
variables: prompt.variables,
|
|
327
|
+
description: prompt.description,
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
return manager;
|
|
332
|
+
}
|