jiva-core 0.2.2 → 0.3.1
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/.dockerignore +53 -0
- package/.gcloudignore +49 -0
- package/CONTRIBUTING.md +92 -0
- package/Dockerfile +63 -0
- package/LICENSE +21 -0
- package/README.md +248 -102
- package/cloud-run-deploy.yaml +135 -0
- package/cloud-run.yaml +135 -0
- package/cloud-run.yaml.template +143 -0
- package/deploy.sh +107 -0
- package/dist/core/agent-spawner.d.ts +89 -0
- package/dist/core/agent-spawner.d.ts.map +1 -0
- package/dist/core/agent-spawner.js +195 -0
- package/dist/core/agent-spawner.js.map +1 -0
- package/dist/core/client-agent.d.ts +82 -0
- package/dist/core/client-agent.d.ts.map +1 -0
- package/dist/core/client-agent.js +406 -0
- package/dist/core/client-agent.js.map +1 -0
- package/dist/core/config.d.ts +59 -10
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +19 -2
- package/dist/core/config.js.map +1 -1
- package/dist/core/conversation-manager.d.ts +10 -18
- package/dist/core/conversation-manager.d.ts.map +1 -1
- package/dist/core/conversation-manager.js +28 -60
- package/dist/core/conversation-manager.js.map +1 -1
- package/dist/core/dual-agent.d.ts +24 -3
- package/dist/core/dual-agent.d.ts.map +1 -1
- package/dist/core/dual-agent.js +112 -19
- package/dist/core/dual-agent.js.map +1 -1
- package/dist/core/manager-agent.d.ts +3 -1
- package/dist/core/manager-agent.d.ts.map +1 -1
- package/dist/core/manager-agent.js +66 -14
- package/dist/core/manager-agent.js.map +1 -1
- package/dist/core/worker-agent.d.ts +15 -1
- package/dist/core/worker-agent.d.ts.map +1 -1
- package/dist/core/worker-agent.js +244 -11
- package/dist/core/worker-agent.js.map +1 -1
- package/dist/core/workspace.d.ts +5 -0
- package/dist/core/workspace.d.ts.map +1 -1
- package/dist/core/workspace.js +47 -7
- package/dist/core/workspace.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces/cli/index.js +376 -44
- package/dist/interfaces/cli/index.js.map +1 -1
- package/dist/interfaces/cli/repl.d.ts.map +1 -1
- package/dist/interfaces/cli/repl.js +6 -0
- package/dist/interfaces/cli/repl.js.map +1 -1
- package/dist/interfaces/http/index.d.ts +22 -0
- package/dist/interfaces/http/index.d.ts.map +1 -0
- package/dist/interfaces/http/index.js +135 -0
- package/dist/interfaces/http/index.js.map +1 -0
- package/dist/interfaces/http/middleware/auth.d.ts +32 -0
- package/dist/interfaces/http/middleware/auth.d.ts.map +1 -0
- package/dist/interfaces/http/middleware/auth.js +176 -0
- package/dist/interfaces/http/middleware/auth.js.map +1 -0
- package/dist/interfaces/http/routes/chat.d.ts +7 -0
- package/dist/interfaces/http/routes/chat.d.ts.map +1 -0
- package/dist/interfaces/http/routes/chat.js +144 -0
- package/dist/interfaces/http/routes/chat.js.map +1 -0
- package/dist/interfaces/http/routes/health.d.ts +6 -0
- package/dist/interfaces/http/routes/health.d.ts.map +1 -0
- package/dist/interfaces/http/routes/health.js +25 -0
- package/dist/interfaces/http/routes/health.js.map +1 -0
- package/dist/interfaces/http/routes/session.d.ts +7 -0
- package/dist/interfaces/http/routes/session.d.ts.map +1 -0
- package/dist/interfaces/http/routes/session.js +114 -0
- package/dist/interfaces/http/routes/session.js.map +1 -0
- package/dist/interfaces/http/session-manager.d.ts +76 -0
- package/dist/interfaces/http/session-manager.d.ts.map +1 -0
- package/dist/interfaces/http/session-manager.js +339 -0
- package/dist/interfaces/http/session-manager.js.map +1 -0
- package/dist/interfaces/http/websocket-handler.d.ts +18 -0
- package/dist/interfaces/http/websocket-handler.d.ts.map +1 -0
- package/dist/interfaces/http/websocket-handler.js +146 -0
- package/dist/interfaces/http/websocket-handler.js.map +1 -0
- package/dist/mcp/client.d.ts +11 -2
- package/dist/mcp/client.d.ts.map +1 -1
- package/dist/mcp/client.js +44 -19
- package/dist/mcp/client.js.map +1 -1
- package/dist/mcp/server-manager.d.ts +1 -1
- package/dist/mcp/server-manager.d.ts.map +1 -1
- package/dist/mcp/server-manager.js +12 -2
- package/dist/mcp/server-manager.js.map +1 -1
- package/dist/personas/index.d.ts +13 -0
- package/dist/personas/index.d.ts.map +1 -0
- package/dist/personas/index.js +13 -0
- package/dist/personas/index.js.map +1 -0
- package/dist/personas/persona-loader.d.ts +30 -0
- package/dist/personas/persona-loader.d.ts.map +1 -0
- package/dist/personas/persona-loader.js +246 -0
- package/dist/personas/persona-loader.js.map +1 -0
- package/dist/personas/persona-manager.d.ts +82 -0
- package/dist/personas/persona-manager.d.ts.map +1 -0
- package/dist/personas/persona-manager.js +211 -0
- package/dist/personas/persona-manager.js.map +1 -0
- package/dist/personas/skill-loader.d.ts +35 -0
- package/dist/personas/skill-loader.d.ts.map +1 -0
- package/dist/personas/skill-loader.js +144 -0
- package/dist/personas/skill-loader.js.map +1 -0
- package/dist/personas/skill-packager.d.ts +25 -0
- package/dist/personas/skill-packager.d.ts.map +1 -0
- package/dist/personas/skill-packager.js +233 -0
- package/dist/personas/skill-packager.js.map +1 -0
- package/dist/personas/types.d.ts +134 -0
- package/dist/personas/types.d.ts.map +1 -0
- package/dist/personas/types.js +7 -0
- package/dist/personas/types.js.map +1 -0
- package/dist/personas/validator.d.ts +22 -0
- package/dist/personas/validator.d.ts.map +1 -0
- package/dist/personas/validator.js +144 -0
- package/dist/personas/validator.js.map +1 -0
- package/dist/storage/factory.d.ts +51 -0
- package/dist/storage/factory.d.ts.map +1 -0
- package/dist/storage/factory.js +154 -0
- package/dist/storage/factory.js.map +1 -0
- package/dist/storage/gcp-bucket-provider.d.ts +59 -0
- package/dist/storage/gcp-bucket-provider.d.ts.map +1 -0
- package/dist/storage/gcp-bucket-provider.js +275 -0
- package/dist/storage/gcp-bucket-provider.js.map +1 -0
- package/dist/storage/index.d.ts +33 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +37 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/local-provider.d.ts +36 -0
- package/dist/storage/local-provider.d.ts.map +1 -0
- package/dist/storage/local-provider.js +219 -0
- package/dist/storage/local-provider.js.map +1 -0
- package/dist/storage/provider.d.ts +137 -0
- package/dist/storage/provider.d.ts.map +1 -0
- package/dist/storage/provider.js +136 -0
- package/dist/storage/provider.js.map +1 -0
- package/dist/storage/types.d.ts +78 -0
- package/dist/storage/types.d.ts.map +1 -0
- package/dist/storage/types.js +14 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/utils/orchestration-logger.d.ts +36 -0
- package/dist/utils/orchestration-logger.d.ts.map +1 -0
- package/dist/utils/orchestration-logger.js +224 -0
- package/dist/utils/orchestration-logger.js.map +1 -0
- package/jiva-new-demo.gif +0 -0
- package/package.json +30 -2
- package/.fluen/cache/state.json +0 -7
- package/actions/action_registry.py +0 -75
- package/actions/python_coder.py +0 -470
- package/api/main.py +0 -269
- package/downloaded_image.avif +0 -0
- package/downloads/snipping_tool.avif +0 -0
- package/image.avif +0 -0
- package/ms_image.avif +0 -0
- package/screenshot.png +0 -0
- package/snipping_tool.avif +0 -0
- package/tmp_image.avif +0 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persona (Plugin) loader - discovers and loads complete personas
|
|
3
|
+
* Handles skills, commands, agents, hooks, and MCP server configurations
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from 'fs/promises';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
import * as os from 'os';
|
|
8
|
+
import { discoverSkills } from './skill-loader.js';
|
|
9
|
+
import { logger } from '../utils/logger.js';
|
|
10
|
+
/**
|
|
11
|
+
* Default persona search paths (user-level and project-level)
|
|
12
|
+
*/
|
|
13
|
+
export function getDefaultPersonaPaths() {
|
|
14
|
+
const home = os.homedir();
|
|
15
|
+
return [
|
|
16
|
+
path.join(home, '.jiva', 'personas'), // User-level
|
|
17
|
+
path.join(process.cwd(), '.jiva', 'personas'), // Project-level
|
|
18
|
+
];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Find the plugin manifest file (checks both .jiva-plugin and .claude-plugin)
|
|
22
|
+
*/
|
|
23
|
+
async function findPluginManifest(personaPath) {
|
|
24
|
+
// Prefer .jiva-plugin but fall back to .claude-plugin for compatibility
|
|
25
|
+
const jivaManifest = path.join(personaPath, '.jiva-plugin', 'plugin.json');
|
|
26
|
+
const claudeManifest = path.join(personaPath, '.claude-plugin', 'plugin.json');
|
|
27
|
+
try {
|
|
28
|
+
await fs.access(jivaManifest);
|
|
29
|
+
return jivaManifest;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// Fall back to .claude-plugin
|
|
33
|
+
await fs.access(claudeManifest);
|
|
34
|
+
return claudeManifest;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Load persona manifest from .jiva-plugin/plugin.json or .claude-plugin/plugin.json
|
|
39
|
+
*/
|
|
40
|
+
export async function loadPersonaManifest(manifestPath) {
|
|
41
|
+
try {
|
|
42
|
+
const content = await fs.readFile(manifestPath, 'utf-8');
|
|
43
|
+
const manifest = JSON.parse(content);
|
|
44
|
+
// Validate required fields
|
|
45
|
+
if (!manifest.name) {
|
|
46
|
+
throw new Error('Persona manifest missing required field: name');
|
|
47
|
+
}
|
|
48
|
+
if (!manifest.description) {
|
|
49
|
+
throw new Error('Persona manifest missing required field: description');
|
|
50
|
+
}
|
|
51
|
+
if (!manifest.version) {
|
|
52
|
+
throw new Error('Persona manifest missing required field: version');
|
|
53
|
+
}
|
|
54
|
+
return manifest;
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
if (error.code === 'ENOENT') {
|
|
58
|
+
throw new Error(`Persona manifest not found at ${manifestPath}`);
|
|
59
|
+
}
|
|
60
|
+
if (error instanceof SyntaxError) {
|
|
61
|
+
throw new Error(`Invalid JSON in persona manifest ${manifestPath}: ${error.message}`);
|
|
62
|
+
}
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Discover commands in a persona's commands/ directory
|
|
68
|
+
*/
|
|
69
|
+
async function discoverCommands(personaPath) {
|
|
70
|
+
const commandsDir = path.join(personaPath, 'commands');
|
|
71
|
+
const commands = [];
|
|
72
|
+
try {
|
|
73
|
+
const entries = await fs.readdir(commandsDir, { withFileTypes: true });
|
|
74
|
+
for (const entry of entries) {
|
|
75
|
+
if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
76
|
+
const commandName = entry.name.replace('.md', '');
|
|
77
|
+
commands.push({
|
|
78
|
+
name: commandName,
|
|
79
|
+
path: path.join(commandsDir, entry.name),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
if (error.code !== 'ENOENT') {
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return commands;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Discover agents in a persona's agents/ directory
|
|
93
|
+
*/
|
|
94
|
+
async function discoverAgents(personaPath) {
|
|
95
|
+
const agentsDir = path.join(personaPath, 'agents');
|
|
96
|
+
const agents = [];
|
|
97
|
+
try {
|
|
98
|
+
const entries = await fs.readdir(agentsDir, { withFileTypes: true });
|
|
99
|
+
for (const entry of entries) {
|
|
100
|
+
if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
101
|
+
const agentName = entry.name.replace('.md', '');
|
|
102
|
+
agents.push({
|
|
103
|
+
name: agentName,
|
|
104
|
+
path: path.join(agentsDir, entry.name),
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
if (error.code !== 'ENOENT') {
|
|
111
|
+
throw error;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return agents;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Load hooks from a persona's hooks/hooks.json
|
|
118
|
+
*/
|
|
119
|
+
async function loadHooks(personaPath) {
|
|
120
|
+
const hooksFile = path.join(personaPath, 'hooks', 'hooks.json');
|
|
121
|
+
try {
|
|
122
|
+
const content = await fs.readFile(hooksFile, 'utf-8');
|
|
123
|
+
const hooksData = JSON.parse(content);
|
|
124
|
+
if (!Array.isArray(hooksData)) {
|
|
125
|
+
throw new Error('hooks.json must contain an array of hook definitions');
|
|
126
|
+
}
|
|
127
|
+
return hooksData;
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
if (error.code === 'ENOENT') {
|
|
131
|
+
return []; // No hooks file - that's ok
|
|
132
|
+
}
|
|
133
|
+
throw error;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Load MCP server configurations from a persona's .mcp.json
|
|
138
|
+
*/
|
|
139
|
+
async function loadMCPServers(personaPath) {
|
|
140
|
+
const mcpFile = path.join(personaPath, '.mcp.json');
|
|
141
|
+
try {
|
|
142
|
+
const content = await fs.readFile(mcpFile, 'utf-8');
|
|
143
|
+
const mcpData = JSON.parse(content);
|
|
144
|
+
// Support both { "mcpServers": {...} } and direct {...} formats
|
|
145
|
+
if (mcpData.mcpServers) {
|
|
146
|
+
logger.debug(`Loaded ${Object.keys(mcpData.mcpServers).length} MCP servers from ${mcpFile}`);
|
|
147
|
+
return mcpData.mcpServers;
|
|
148
|
+
}
|
|
149
|
+
logger.debug(`Loaded ${Object.keys(mcpData).length} MCP servers from ${mcpFile}`);
|
|
150
|
+
return mcpData;
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
if (error.code === 'ENOENT') {
|
|
154
|
+
logger.debug(`No MCP config file at ${mcpFile}`);
|
|
155
|
+
return {}; // No MCP config - that's ok
|
|
156
|
+
}
|
|
157
|
+
logger.error(`Error loading MCP servers from ${mcpFile}: ${error}`);
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Load a single persona from its directory
|
|
163
|
+
*/
|
|
164
|
+
export async function loadPersona(personaPath) {
|
|
165
|
+
const manifestPath = await findPluginManifest(personaPath);
|
|
166
|
+
const manifest = await loadPersonaManifest(manifestPath);
|
|
167
|
+
// Discover all components
|
|
168
|
+
const [skills, commands, agents, hooks, mcpServers] = await Promise.all([
|
|
169
|
+
discoverSkills(path.join(personaPath, 'skills'), manifest.name),
|
|
170
|
+
discoverCommands(personaPath),
|
|
171
|
+
discoverAgents(personaPath),
|
|
172
|
+
loadHooks(personaPath),
|
|
173
|
+
loadMCPServers(personaPath),
|
|
174
|
+
]);
|
|
175
|
+
const mcpServerCount = Object.keys(mcpServers).length;
|
|
176
|
+
logger.info(`Loaded persona: ${manifest.name} v${manifest.version} ` +
|
|
177
|
+
`(${skills.length} skills, ${commands.length} commands, ${agents.length} agents, ` +
|
|
178
|
+
`${hooks.length} hooks, ${mcpServerCount} MCP servers)`);
|
|
179
|
+
return {
|
|
180
|
+
manifest,
|
|
181
|
+
path: personaPath,
|
|
182
|
+
skills,
|
|
183
|
+
commands,
|
|
184
|
+
agents,
|
|
185
|
+
hooks,
|
|
186
|
+
mcpServers,
|
|
187
|
+
active: false,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Discover all personas in a directory
|
|
192
|
+
*/
|
|
193
|
+
export async function discoverPersonasInPath(basePath) {
|
|
194
|
+
const personas = [];
|
|
195
|
+
try {
|
|
196
|
+
const entries = await fs.readdir(basePath, { withFileTypes: true });
|
|
197
|
+
for (const entry of entries) {
|
|
198
|
+
if (!entry.isDirectory())
|
|
199
|
+
continue;
|
|
200
|
+
const personaPath = path.join(basePath, entry.name);
|
|
201
|
+
try {
|
|
202
|
+
// Check if this is a valid persona directory (has plugin manifest)
|
|
203
|
+
await findPluginManifest(personaPath);
|
|
204
|
+
const persona = await loadPersona(personaPath);
|
|
205
|
+
personas.push(persona);
|
|
206
|
+
}
|
|
207
|
+
catch (error) {
|
|
208
|
+
// Skip invalid persona directories
|
|
209
|
+
logger.debug(`Skipping ${personaPath}: ${error instanceof Error ? error.message : error}`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
if (error.code === 'ENOENT') {
|
|
215
|
+
// Directory doesn't exist - that's ok
|
|
216
|
+
return [];
|
|
217
|
+
}
|
|
218
|
+
throw error;
|
|
219
|
+
}
|
|
220
|
+
return personas;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Discover all personas from default search paths
|
|
224
|
+
*/
|
|
225
|
+
export async function discoverAllPersonas(additionalPaths = []) {
|
|
226
|
+
const searchPaths = [...getDefaultPersonaPaths(), ...additionalPaths];
|
|
227
|
+
const allPersonas = [];
|
|
228
|
+
const personaMap = new Map();
|
|
229
|
+
// Scan all paths, later sources override earlier ones
|
|
230
|
+
for (const searchPath of searchPaths) {
|
|
231
|
+
const personas = await discoverPersonasInPath(searchPath);
|
|
232
|
+
for (const persona of personas) {
|
|
233
|
+
personaMap.set(persona.manifest.name, persona);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
allPersonas.push(...personaMap.values());
|
|
237
|
+
logger.info(`Discovered ${allPersonas.length} personas from ${searchPaths.length} search paths`);
|
|
238
|
+
return allPersonas;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Find a persona by name from discovered personas
|
|
242
|
+
*/
|
|
243
|
+
export function findPersona(personas, name) {
|
|
244
|
+
return personas.find((p) => p.manifest.name === name);
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=persona-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persona-loader.js","sourceRoot":"","sources":["../../src/personas/persona-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persona Manager - Central controller for persona lifecycle and skill routing
|
|
3
|
+
* Handles discovery, activation, and integration with the agent system
|
|
4
|
+
*/
|
|
5
|
+
import { Persona, Skill } from './types.js';
|
|
6
|
+
export declare class PersonaManager {
|
|
7
|
+
private personas;
|
|
8
|
+
private activePersona;
|
|
9
|
+
private additionalSearchPaths;
|
|
10
|
+
private configManager;
|
|
11
|
+
constructor(additionalPaths?: string[]);
|
|
12
|
+
/**
|
|
13
|
+
* Initialize the persona manager by discovering all available personas
|
|
14
|
+
*/
|
|
15
|
+
initialize(): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Refresh persona list (re-scan directories)
|
|
18
|
+
*/
|
|
19
|
+
refresh(): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Get all discovered personas
|
|
22
|
+
*/
|
|
23
|
+
getPersonas(): Persona[];
|
|
24
|
+
/**
|
|
25
|
+
* Get the currently active persona
|
|
26
|
+
*/
|
|
27
|
+
getActivePersona(): Persona | null;
|
|
28
|
+
/**
|
|
29
|
+
* Activate a persona by name
|
|
30
|
+
*/
|
|
31
|
+
activatePersona(name: string): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Deactivate the current persona
|
|
34
|
+
*/
|
|
35
|
+
deactivatePersona(): void;
|
|
36
|
+
/**
|
|
37
|
+
* Get all skills from the active persona (L1 metadata only)
|
|
38
|
+
*/
|
|
39
|
+
getActiveSkills(): Skill[];
|
|
40
|
+
/**
|
|
41
|
+
* Get all skills from all personas (for global skill search)
|
|
42
|
+
*/
|
|
43
|
+
getAllSkills(): Skill[];
|
|
44
|
+
/**
|
|
45
|
+
* Find a skill by name in the active persona
|
|
46
|
+
*/
|
|
47
|
+
findSkill(skillName: string): Skill | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Load L2 content for a skill (called by agent when skill is selected)
|
|
50
|
+
*/
|
|
51
|
+
loadSkill(skillName: string): Promise<Skill | null>;
|
|
52
|
+
/**
|
|
53
|
+
* Generate the <available_skills> XML block for agent system prompt
|
|
54
|
+
* This is L1 - just metadata for routing
|
|
55
|
+
*/
|
|
56
|
+
generateSkillsPromptBlock(): string;
|
|
57
|
+
/**
|
|
58
|
+
* Generate persona context for system prompt
|
|
59
|
+
*/
|
|
60
|
+
generatePersonaPromptBlock(): string;
|
|
61
|
+
/**
|
|
62
|
+
* Get full system prompt addition (persona + skills)
|
|
63
|
+
*/
|
|
64
|
+
getSystemPromptAddition(): string;
|
|
65
|
+
/**
|
|
66
|
+
* Check if a persona is installed
|
|
67
|
+
*/
|
|
68
|
+
hasPersona(name: string): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Get persona info by name
|
|
71
|
+
*/
|
|
72
|
+
getPersona(name: string): Persona | undefined;
|
|
73
|
+
/**
|
|
74
|
+
* Get MCP servers from active persona
|
|
75
|
+
*/
|
|
76
|
+
getPersonaMCPServers(): Record<string, any>;
|
|
77
|
+
/**
|
|
78
|
+
* Escape XML special characters
|
|
79
|
+
*/
|
|
80
|
+
private escapeXml;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=persona-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persona-manager.d.ts","sourceRoot":"","sources":["../../src/personas/persona-manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAU5C,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,aAAa,CAAwB;IAC7C,OAAO,CAAC,qBAAqB,CAAgB;IAC7C,OAAO,CAAC,aAAa,CAAgB;gBAEzB,eAAe,GAAE,MAAM,EAAO;IAK1C;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA0BjC;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B;;OAEG;IACH,WAAW,IAAI,OAAO,EAAE;IAIxB;;OAEG;IACH,gBAAgB,IAAI,OAAO,GAAG,IAAI;IAIlC;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IA4BtC;;OAEG;IACH,iBAAiB,IAAI,IAAI;IASzB;;OAEG;IACH,eAAe,IAAI,KAAK,EAAE;IAI1B;;OAEG;IACH,YAAY,IAAI,KAAK,EAAE;IAIvB;;OAEG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS;IAI/C;;OAEG;IACG,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAgBzD;;;OAGG;IACH,yBAAyB,IAAI,MAAM;IAsBnC;;OAEG;IACH,0BAA0B,IAAI,MAAM;IAgBpC;;OAEG;IACH,uBAAuB,IAAI,MAAM;IAmBjC;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIjC;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAI7C;;OAEG;IACH,oBAAoB,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAI3C;;OAEG;IACH,OAAO,CAAC,SAAS;CAQlB"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persona Manager - Central controller for persona lifecycle and skill routing
|
|
3
|
+
* Handles discovery, activation, and integration with the agent system
|
|
4
|
+
*/
|
|
5
|
+
import { discoverAllPersonas, findPersona, getDefaultPersonaPaths, } from './persona-loader.js';
|
|
6
|
+
import { loadSkillContent } from './skill-loader.js';
|
|
7
|
+
import { logger } from '../utils/logger.js';
|
|
8
|
+
import { ConfigManager } from '../core/config.js';
|
|
9
|
+
export class PersonaManager {
|
|
10
|
+
personas = [];
|
|
11
|
+
activePersona = null;
|
|
12
|
+
additionalSearchPaths = [];
|
|
13
|
+
configManager;
|
|
14
|
+
constructor(additionalPaths = []) {
|
|
15
|
+
this.additionalSearchPaths = additionalPaths;
|
|
16
|
+
this.configManager = ConfigManager.getInstance();
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Initialize the persona manager by discovering all available personas
|
|
20
|
+
*/
|
|
21
|
+
async initialize() {
|
|
22
|
+
logger.info('Initializing Persona Manager...');
|
|
23
|
+
this.personas = await discoverAllPersonas(this.additionalSearchPaths);
|
|
24
|
+
if (this.personas.length === 0) {
|
|
25
|
+
logger.info('No personas found in search paths:', getDefaultPersonaPaths());
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
logger.info(`Initialized with ${this.personas.length} personas:`, this.personas.map((p) => p.manifest.name).join(', '));
|
|
29
|
+
// Restore active persona from config
|
|
30
|
+
const savedPersonaName = this.configManager.getActivePersona();
|
|
31
|
+
if (savedPersonaName) {
|
|
32
|
+
const success = this.activatePersona(savedPersonaName);
|
|
33
|
+
if (success) {
|
|
34
|
+
logger.info(`Restored active persona: ${savedPersonaName}`);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
logger.warn(`Saved persona '${savedPersonaName}' not found, clearing config`);
|
|
38
|
+
this.configManager.setActivePersona(null);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Refresh persona list (re-scan directories)
|
|
45
|
+
*/
|
|
46
|
+
async refresh() {
|
|
47
|
+
await this.initialize();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get all discovered personas
|
|
51
|
+
*/
|
|
52
|
+
getPersonas() {
|
|
53
|
+
return this.personas;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get the currently active persona
|
|
57
|
+
*/
|
|
58
|
+
getActivePersona() {
|
|
59
|
+
return this.activePersona;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Activate a persona by name
|
|
63
|
+
*/
|
|
64
|
+
activatePersona(name) {
|
|
65
|
+
const persona = findPersona(this.personas, name);
|
|
66
|
+
if (!persona) {
|
|
67
|
+
logger.warn(`Persona not found: ${name}`);
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
// Deactivate current persona if any
|
|
71
|
+
if (this.activePersona) {
|
|
72
|
+
this.activePersona.active = false;
|
|
73
|
+
}
|
|
74
|
+
this.activePersona = persona;
|
|
75
|
+
persona.active = true;
|
|
76
|
+
// Persist to config
|
|
77
|
+
this.configManager.setActivePersona(persona.manifest.name);
|
|
78
|
+
const mcpServerCount = persona.mcpServers ? Object.keys(persona.mcpServers).length : 0;
|
|
79
|
+
logger.info(`Activated persona: ${persona.manifest.name} ` +
|
|
80
|
+
`(${persona.skills.length} skills, ${mcpServerCount} MCP servers)`);
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Deactivate the current persona
|
|
85
|
+
*/
|
|
86
|
+
deactivatePersona() {
|
|
87
|
+
if (this.activePersona) {
|
|
88
|
+
this.activePersona.active = false;
|
|
89
|
+
logger.info(`Deactivated persona: ${this.activePersona.manifest.name}`);
|
|
90
|
+
this.activePersona = null;
|
|
91
|
+
this.configManager.setActivePersona(null);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Get all skills from the active persona (L1 metadata only)
|
|
96
|
+
*/
|
|
97
|
+
getActiveSkills() {
|
|
98
|
+
return this.activePersona?.skills || [];
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get all skills from all personas (for global skill search)
|
|
102
|
+
*/
|
|
103
|
+
getAllSkills() {
|
|
104
|
+
return this.personas.flatMap((p) => p.skills);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Find a skill by name in the active persona
|
|
108
|
+
*/
|
|
109
|
+
findSkill(skillName) {
|
|
110
|
+
return this.activePersona?.skills.find((s) => s.metadata.name === skillName);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Load L2 content for a skill (called by agent when skill is selected)
|
|
114
|
+
*/
|
|
115
|
+
async loadSkill(skillName) {
|
|
116
|
+
const skill = this.findSkill(skillName);
|
|
117
|
+
if (!skill) {
|
|
118
|
+
logger.warn(`Skill not found: ${skillName}`);
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
if (!skill.loaded) {
|
|
122
|
+
await loadSkillContent(skill);
|
|
123
|
+
logger.info(`Loaded skill content: ${skill.personaName}:${skill.metadata.name}`);
|
|
124
|
+
}
|
|
125
|
+
return skill;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Generate the <available_skills> XML block for agent system prompt
|
|
129
|
+
* This is L1 - just metadata for routing
|
|
130
|
+
*/
|
|
131
|
+
generateSkillsPromptBlock() {
|
|
132
|
+
const skills = this.getActiveSkills();
|
|
133
|
+
if (skills.length === 0) {
|
|
134
|
+
return '';
|
|
135
|
+
}
|
|
136
|
+
const skillsXml = skills
|
|
137
|
+
.map((skill) => `<skill>
|
|
138
|
+
<name>${this.escapeXml(skill.metadata.name)}</name>
|
|
139
|
+
<description>${this.escapeXml(skill.metadata.description)}</description>
|
|
140
|
+
<location>${this.escapeXml(skill.path)}/SKILL.md</location>
|
|
141
|
+
</skill>`)
|
|
142
|
+
.join('\n');
|
|
143
|
+
return `<available_skills>
|
|
144
|
+
${skillsXml}
|
|
145
|
+
</available_skills>`;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Generate persona context for system prompt
|
|
149
|
+
*/
|
|
150
|
+
generatePersonaPromptBlock() {
|
|
151
|
+
if (!this.activePersona) {
|
|
152
|
+
return '';
|
|
153
|
+
}
|
|
154
|
+
const persona = this.activePersona;
|
|
155
|
+
return `<active_persona>
|
|
156
|
+
<name>${this.escapeXml(persona.manifest.name)}</name>
|
|
157
|
+
<description>${this.escapeXml(persona.manifest.description)}</description>
|
|
158
|
+
<version>${persona.manifest.version}</version>
|
|
159
|
+
<skills_count>${persona.skills.length}</skills_count>
|
|
160
|
+
<commands_count>${persona.commands.length}</commands_count>
|
|
161
|
+
</active_persona>`;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Get full system prompt addition (persona + skills)
|
|
165
|
+
*/
|
|
166
|
+
getSystemPromptAddition() {
|
|
167
|
+
if (!this.activePersona) {
|
|
168
|
+
return '';
|
|
169
|
+
}
|
|
170
|
+
const personaBlock = this.generatePersonaPromptBlock();
|
|
171
|
+
const skillsBlock = this.generateSkillsPromptBlock();
|
|
172
|
+
if (!skillsBlock) {
|
|
173
|
+
return personaBlock;
|
|
174
|
+
}
|
|
175
|
+
return `${personaBlock}
|
|
176
|
+
|
|
177
|
+
${skillsBlock}
|
|
178
|
+
|
|
179
|
+
When a user's request matches a skill description, read that skill's SKILL.md file using the view tool to get detailed instructions. Skills use progressive disclosure - only load what you need when you need it.`;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Check if a persona is installed
|
|
183
|
+
*/
|
|
184
|
+
hasPersona(name) {
|
|
185
|
+
return this.personas.some((p) => p.manifest.name === name);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Get persona info by name
|
|
189
|
+
*/
|
|
190
|
+
getPersona(name) {
|
|
191
|
+
return findPersona(this.personas, name);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Get MCP servers from active persona
|
|
195
|
+
*/
|
|
196
|
+
getPersonaMCPServers() {
|
|
197
|
+
return this.activePersona?.mcpServers || {};
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Escape XML special characters
|
|
201
|
+
*/
|
|
202
|
+
escapeXml(text) {
|
|
203
|
+
return text
|
|
204
|
+
.replace(/&/g, '&')
|
|
205
|
+
.replace(/</g, '<')
|
|
206
|
+
.replace(/>/g, '>')
|
|
207
|
+
.replace(/"/g, '"')
|
|
208
|
+
.replace(/'/g, ''');
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=persona-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persona-manager.js","sourceRoot":"","sources":["../../src/personas/persona-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill loader - parses SKILL.md files with YAML frontmatter
|
|
3
|
+
* Implements progressive disclosure: L1 (metadata) → L2 (body) → L3 (references)
|
|
4
|
+
*/
|
|
5
|
+
import { Skill, SkillMetadata } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Parse SKILL.md file and extract frontmatter + body
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseSkillFile(filePath: string): Promise<{
|
|
10
|
+
metadata: SkillMetadata;
|
|
11
|
+
body: string;
|
|
12
|
+
fullContent: string;
|
|
13
|
+
}>;
|
|
14
|
+
/**
|
|
15
|
+
* Discover all skills in a directory (L1 only - metadata)
|
|
16
|
+
* Each subdirectory with a SKILL.md is a skill
|
|
17
|
+
*/
|
|
18
|
+
export declare function discoverSkills(skillsDir: string, personaName: string): Promise<Skill[]>;
|
|
19
|
+
/**
|
|
20
|
+
* Load L2 (full SKILL.md body) for a skill
|
|
21
|
+
*/
|
|
22
|
+
export declare function loadSkillContent(skill: Skill): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Get path to a skill resource (L3 - references, scripts, assets)
|
|
25
|
+
*/
|
|
26
|
+
export declare function getSkillResourcePath(skill: Skill, resourceType: 'scripts' | 'references' | 'assets', filename: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Check if a skill has a specific resource
|
|
29
|
+
*/
|
|
30
|
+
export declare function hasSkillResource(skill: Skill, resourceType: 'scripts' | 'references' | 'assets', filename: string): Promise<boolean>;
|
|
31
|
+
/**
|
|
32
|
+
* List all resources of a type in a skill
|
|
33
|
+
*/
|
|
34
|
+
export declare function listSkillResources(skill: Skill, resourceType: 'scripts' | 'references' | 'assets'): Promise<string[]>;
|
|
35
|
+
//# sourceMappingURL=skill-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-loader.d.ts","sourceRoot":"","sources":["../../src/personas/skill-loader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAWlD;;GAEG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,QAAQ,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAiDzE;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,KAAK,EAAE,CAAC,CAyClB;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAUlE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,GAAG,YAAY,GAAG,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE9H;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,SAAS,GAAG,YAAY,GAAG,QAAQ,EACjD,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC,CAQlB;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,SAAS,GAAG,YAAY,GAAG,QAAQ,GAChD,OAAO,CAAC,MAAM,EAAE,CAAC,CAWnB"}
|