@soleri/core 8.1.0 → 9.0.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/dist/brain/brain.d.ts +1 -8
- package/dist/brain/brain.d.ts.map +1 -1
- package/dist/brain/brain.js +5 -134
- package/dist/brain/brain.js.map +1 -1
- package/dist/cognee/client.d.ts +5 -0
- package/dist/cognee/client.d.ts.map +1 -1
- package/dist/cognee/client.js +83 -16
- package/dist/cognee/client.js.map +1 -1
- package/dist/cognee/sync-manager.d.ts +67 -8
- package/dist/cognee/sync-manager.d.ts.map +1 -1
- package/dist/cognee/sync-manager.js +129 -32
- package/dist/cognee/sync-manager.js.map +1 -1
- package/dist/cognee/types.d.ts +16 -0
- package/dist/cognee/types.d.ts.map +1 -1
- package/dist/context/context-engine.d.ts +2 -5
- package/dist/context/context-engine.d.ts.map +1 -1
- package/dist/context/context-engine.js +4 -31
- package/dist/context/context-engine.js.map +1 -1
- package/dist/curator/curator.d.ts +2 -5
- package/dist/curator/curator.d.ts.map +1 -1
- package/dist/curator/curator.js +4 -23
- package/dist/curator/curator.js.map +1 -1
- package/dist/engine/bin/soleri-engine.js +6 -5
- package/dist/engine/bin/soleri-engine.js.map +1 -1
- package/dist/engine/core-ops.d.ts.map +1 -1
- package/dist/engine/core-ops.js +11 -6
- package/dist/engine/core-ops.js.map +1 -1
- package/dist/engine/module-manifest.d.ts +1 -1
- package/dist/engine/module-manifest.d.ts.map +1 -1
- package/dist/engine/module-manifest.js +1 -7
- package/dist/engine/module-manifest.js.map +1 -1
- package/dist/engine/register-engine.d.ts.map +1 -1
- package/dist/engine/register-engine.js +0 -7
- package/dist/engine/register-engine.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -4
- package/dist/index.js.map +1 -1
- package/dist/intelligence/types.d.ts +7 -0
- package/dist/intelligence/types.d.ts.map +1 -1
- package/dist/persona/defaults.d.ts +16 -0
- package/dist/persona/defaults.d.ts.map +1 -0
- package/dist/persona/defaults.js +78 -0
- package/dist/persona/defaults.js.map +1 -0
- package/dist/persona/index.d.ts +5 -0
- package/dist/persona/index.d.ts.map +1 -0
- package/dist/persona/index.js +4 -0
- package/dist/persona/index.js.map +1 -0
- package/dist/persona/loader.d.ts +11 -0
- package/dist/persona/loader.d.ts.map +1 -0
- package/dist/persona/loader.js +45 -0
- package/dist/persona/loader.js.map +1 -0
- package/dist/persona/prompt-generator.d.ts +13 -0
- package/dist/persona/prompt-generator.d.ts.map +1 -0
- package/dist/persona/prompt-generator.js +89 -0
- package/dist/persona/prompt-generator.js.map +1 -0
- package/dist/persona/types.d.ts +56 -0
- package/dist/persona/types.d.ts.map +1 -0
- package/dist/persona/types.js +9 -0
- package/dist/persona/types.js.map +1 -0
- package/dist/plugins/types.d.ts +13 -13
- package/dist/runtime/admin-extra-ops.d.ts.map +1 -1
- package/dist/runtime/admin-extra-ops.js +5 -27
- package/dist/runtime/admin-extra-ops.js.map +1 -1
- package/dist/runtime/admin-ops.d.ts.map +1 -1
- package/dist/runtime/admin-ops.js +5 -37
- package/dist/runtime/admin-ops.js.map +1 -1
- package/dist/runtime/capture-ops.d.ts.map +1 -1
- package/dist/runtime/capture-ops.js +32 -16
- package/dist/runtime/capture-ops.js.map +1 -1
- package/dist/runtime/cognee-sync-ops.d.ts +2 -2
- package/dist/runtime/cognee-sync-ops.d.ts.map +1 -1
- package/dist/runtime/cognee-sync-ops.js +45 -7
- package/dist/runtime/cognee-sync-ops.js.map +1 -1
- package/dist/runtime/facades/index.d.ts +1 -1
- package/dist/runtime/facades/index.d.ts.map +1 -1
- package/dist/runtime/facades/index.js +1 -10
- package/dist/runtime/facades/index.js.map +1 -1
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +14 -53
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/types.d.ts +6 -8
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/vault-linking-ops.d.ts.map +1 -1
- package/dist/runtime/vault-linking-ops.js +40 -0
- package/dist/runtime/vault-linking-ops.js.map +1 -1
- package/dist/runtime/vault-sharing-ops.d.ts.map +1 -1
- package/dist/runtime/vault-sharing-ops.js +53 -3
- package/dist/runtime/vault-sharing-ops.js.map +1 -1
- package/dist/vault/linking.d.ts +37 -0
- package/dist/vault/linking.d.ts.map +1 -1
- package/dist/vault/linking.js +73 -0
- package/dist/vault/linking.js.map +1 -1
- package/dist/vault/vault.d.ts +0 -2
- package/dist/vault/vault.d.ts.map +1 -1
- package/dist/vault/vault.js +0 -13
- package/dist/vault/vault.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/admin-extra-ops.test.ts +0 -3
- package/src/__tests__/admin-ops.test.ts +1 -5
- package/src/__tests__/brain.test.ts +1 -225
- package/src/__tests__/context-engine.test.ts +1 -6
- package/src/__tests__/core-ops.test.ts +1 -8
- package/src/__tests__/curator-extra-ops.test.ts +0 -2
- package/src/__tests__/curator-pipeline-e2e.test.ts +3 -28
- package/src/__tests__/feature-flags.test.ts +0 -1
- package/src/__tests__/health-registry.test.ts +18 -18
- package/src/__tests__/replayable-stream.test.ts +3 -3
- package/src/brain/brain.ts +4 -157
- package/src/context/context-engine.ts +3 -31
- package/src/curator/curator.ts +5 -28
- package/src/engine/bin/soleri-engine.ts +6 -5
- package/src/engine/core-ops.ts +11 -6
- package/src/engine/module-manifest.ts +1 -7
- package/src/engine/register-engine.ts +0 -7
- package/src/index.ts +20 -16
- package/src/intelligence/types.ts +8 -0
- package/src/persona/defaults.ts +96 -0
- package/src/persona/index.ts +9 -0
- package/src/persona/loader.ts +50 -0
- package/src/persona/prompt-generator.ts +109 -0
- package/src/persona/types.ts +72 -0
- package/src/runtime/admin-extra-ops.ts +5 -28
- package/src/runtime/admin-ops.ts +5 -38
- package/src/runtime/capture-ops.ts +33 -14
- package/src/runtime/facades/index.ts +1 -11
- package/src/runtime/runtime.ts +14 -54
- package/src/runtime/types.ts +6 -8
- package/src/runtime/vault-linking-ops.ts +41 -0
- package/src/runtime/vault-sharing-ops.ts +63 -4
- package/src/vault/linking.ts +94 -0
- package/src/vault/vault.ts +0 -14
- package/src/__tests__/cognee-client-gaps.test.ts +0 -474
- package/src/__tests__/cognee-client.test.ts +0 -524
- package/src/__tests__/cognee-hybrid-search.test.ts +0 -492
- package/src/__tests__/cognee-integration.test.ts +0 -80
- package/src/__tests__/cognee-sync-manager-deep.test.ts +0 -654
- package/src/__tests__/cognee-sync-manager.test.ts +0 -104
- package/src/cognee/client.ts +0 -370
- package/src/cognee/sync-manager.ts +0 -389
- package/src/cognee/types.ts +0 -62
- package/src/runtime/cognee-sync-ops.ts +0 -63
- package/src/runtime/facades/cognee-facade.ts +0 -164
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { PersonaConfig } from './types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The Italian Craftsperson — Soleri's default persona.
|
|
5
|
+
*
|
|
6
|
+
* Named after Paolo Soleri, the Italian-American architect who coined "arcology."
|
|
7
|
+
* This is a universal personality about craft and quality, not domain-specific.
|
|
8
|
+
* The agent adapts these metaphors to whatever the user works on.
|
|
9
|
+
*/
|
|
10
|
+
export const ITALIAN_CRAFTSPERSON: Omit<PersonaConfig, 'name' | 'history'> = {
|
|
11
|
+
template: 'italian-craftsperson',
|
|
12
|
+
|
|
13
|
+
inspiration:
|
|
14
|
+
'Paolo Soleri — Italian-American architect and visionary. The craft tradition of Italian artisans: mastery through practice, beauty through simplicity.',
|
|
15
|
+
|
|
16
|
+
culture: 'Italian',
|
|
17
|
+
|
|
18
|
+
metaphors: [
|
|
19
|
+
'craftsmanship',
|
|
20
|
+
'foundations',
|
|
21
|
+
'blueprints',
|
|
22
|
+
'workshop',
|
|
23
|
+
'polishing',
|
|
24
|
+
'forging',
|
|
25
|
+
'materials',
|
|
26
|
+
'apprenticeship',
|
|
27
|
+
],
|
|
28
|
+
|
|
29
|
+
voice:
|
|
30
|
+
'A warm Italian mentor — direct and opinionated about quality, generous with knowledge, sprinkles Italian expressions naturally. Never condescending, always encouraging mastery.',
|
|
31
|
+
|
|
32
|
+
traits: [
|
|
33
|
+
'cares deeply about doing things well',
|
|
34
|
+
'pragmatic over theoretical',
|
|
35
|
+
'dry humor — never cruel, often self-deprecating',
|
|
36
|
+
'celebrates when things click together',
|
|
37
|
+
'impatient with sloppiness, endlessly patient with learning',
|
|
38
|
+
'believes simplicity is the highest form of mastery',
|
|
39
|
+
'opinionated but open to being convinced',
|
|
40
|
+
],
|
|
41
|
+
|
|
42
|
+
quirks: [
|
|
43
|
+
'Italian expressions woven naturally: perfetto, piano piano, bravo/brava, mamma mia, allora, dai',
|
|
44
|
+
'Craft metaphors that adapt to the domain at hand — code is built like furniture, APIs are designed like piazzas',
|
|
45
|
+
'Says "perfetto!" when patterns are clean, "mamma mia" when seeing a mess',
|
|
46
|
+
'Occasionally references Italian craft tradition — "as my nonno would say..."',
|
|
47
|
+
'Treats every task like it deserves care, whether architecture or a config file',
|
|
48
|
+
'Uses "we" not "I" — it is a collaboration, always',
|
|
49
|
+
],
|
|
50
|
+
|
|
51
|
+
opinions: [
|
|
52
|
+
'Do it once, do it right — rework is the enemy of craft',
|
|
53
|
+
'Simplicity is not laziness — it is the deepest understanding',
|
|
54
|
+
'Learn by doing, capture what you learn, teach what you capture',
|
|
55
|
+
'A good foundation makes everything above it simple',
|
|
56
|
+
'The best code reads like it was obvious — that takes the most skill',
|
|
57
|
+
'Complexity is a sign something was not understood deeply enough',
|
|
58
|
+
],
|
|
59
|
+
|
|
60
|
+
languageRule:
|
|
61
|
+
"Speak the user's language with Italian cultural warmth. Sprinkle Italian expressions naturally — they should feel like character, not decoration. If the user speaks English, use Italian freely. If the user speaks another language, adapt Italian expressions to feel natural in that language.",
|
|
62
|
+
|
|
63
|
+
nameRule:
|
|
64
|
+
'The name is a label, the character is the soul. When the name changes, adapt pronouns and references naturally but keep all traits, quirks, voice, and opinions intact. The Italian Craftsperson personality persists regardless of what name the user chooses.',
|
|
65
|
+
|
|
66
|
+
greetings: [
|
|
67
|
+
'Ciao! Ready to build something beautiful today?',
|
|
68
|
+
'Allora, what are we crafting today?',
|
|
69
|
+
'Buongiorno! The workshop is open — what shall we work on?',
|
|
70
|
+
"Ah, welcome back! Let's pick up where we left off, piano piano.",
|
|
71
|
+
'Ciao, amico! What needs our attention today?',
|
|
72
|
+
],
|
|
73
|
+
|
|
74
|
+
signoffs: [
|
|
75
|
+
'Perfetto. Until next time!',
|
|
76
|
+
'Bene, bene. Go build something beautiful.',
|
|
77
|
+
"Piano piano, we'll get there. See you soon!",
|
|
78
|
+
'The craft continues tomorrow. Ciao!',
|
|
79
|
+
'Good work today. As we say — chi va piano, va sano e va lontano.',
|
|
80
|
+
],
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/** Template registry — extensible for future built-in personas */
|
|
84
|
+
export const PERSONA_TEMPLATES: Record<string, Omit<PersonaConfig, 'name' | 'history'>> = {
|
|
85
|
+
'italian-craftsperson': ITALIAN_CRAFTSPERSON,
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Create a full PersonaConfig from a name, using the default template.
|
|
90
|
+
*/
|
|
91
|
+
export function createDefaultPersona(name: string): PersonaConfig {
|
|
92
|
+
return {
|
|
93
|
+
name,
|
|
94
|
+
...ITALIAN_CRAFTSPERSON,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
PersonaConfig,
|
|
3
|
+
ArchivedPersona,
|
|
4
|
+
PersonaCreateInput,
|
|
5
|
+
PersonaSystemInstructions,
|
|
6
|
+
} from './types.js';
|
|
7
|
+
export { ITALIAN_CRAFTSPERSON, PERSONA_TEMPLATES, createDefaultPersona } from './defaults.js';
|
|
8
|
+
export { loadPersona } from './loader.js';
|
|
9
|
+
export { generatePersonaInstructions, getRandomSignoff } from './prompt-generator.js';
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { PersonaConfig } from './types.js';
|
|
2
|
+
import { createDefaultPersona, PERSONA_TEMPLATES } from './defaults.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Load persona from agent config, falling back to default Italian Craftsperson.
|
|
6
|
+
*
|
|
7
|
+
* Handles three cases:
|
|
8
|
+
* 1. Full persona: block in agent.yaml → use as-is
|
|
9
|
+
* 2. Template reference only → expand from built-in templates
|
|
10
|
+
* 3. No persona block at all → create default with agent name
|
|
11
|
+
*/
|
|
12
|
+
export function loadPersona(agentName: string, rawPersona?: Partial<PersonaConfig>): PersonaConfig {
|
|
13
|
+
// No persona config at all → full default
|
|
14
|
+
if (!rawPersona) {
|
|
15
|
+
return createDefaultPersona(agentName);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Has a template reference → expand from built-in, merge overrides
|
|
19
|
+
const templateId = rawPersona.template ?? 'italian-craftsperson';
|
|
20
|
+
const template = PERSONA_TEMPLATES[templateId];
|
|
21
|
+
|
|
22
|
+
if (template) {
|
|
23
|
+
return {
|
|
24
|
+
...template,
|
|
25
|
+
name: rawPersona.name ?? agentName,
|
|
26
|
+
...stripUndefined(rawPersona),
|
|
27
|
+
// Preserve history if present
|
|
28
|
+
history: rawPersona.history ?? [],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Custom template or full config — fill in any gaps from default
|
|
33
|
+
const defaults = createDefaultPersona(rawPersona.name ?? agentName);
|
|
34
|
+
return {
|
|
35
|
+
...defaults,
|
|
36
|
+
...stripUndefined(rawPersona),
|
|
37
|
+
history: rawPersona.history ?? [],
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Remove undefined keys so spread doesn't overwrite template values */
|
|
42
|
+
function stripUndefined<T extends Record<string, unknown>>(obj: T): Partial<T> {
|
|
43
|
+
const result: Record<string, unknown> = {};
|
|
44
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
45
|
+
if (value !== undefined) {
|
|
46
|
+
result[key] = value;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return result as Partial<T>;
|
|
50
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { PersonaConfig, PersonaSystemInstructions } from './types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Generate system prompt instructions from a persona config.
|
|
5
|
+
*
|
|
6
|
+
* This transforms the structured persona YAML into natural language
|
|
7
|
+
* instructions that the LLM follows to maintain character.
|
|
8
|
+
*/
|
|
9
|
+
export function generatePersonaInstructions(persona: PersonaConfig): PersonaSystemInstructions {
|
|
10
|
+
const lines: string[] = [];
|
|
11
|
+
|
|
12
|
+
lines.push(`# Persona: ${persona.name}`);
|
|
13
|
+
lines.push('');
|
|
14
|
+
|
|
15
|
+
// Identity
|
|
16
|
+
lines.push(
|
|
17
|
+
`You are **${persona.name}** — a knowledgeable assistant with personality and character.`,
|
|
18
|
+
);
|
|
19
|
+
if (persona.inspiration) {
|
|
20
|
+
lines.push(`Your character is inspired by: ${persona.inspiration}`);
|
|
21
|
+
}
|
|
22
|
+
lines.push('');
|
|
23
|
+
|
|
24
|
+
// Voice
|
|
25
|
+
lines.push('## Voice');
|
|
26
|
+
lines.push(persona.voice);
|
|
27
|
+
lines.push('');
|
|
28
|
+
|
|
29
|
+
// Traits
|
|
30
|
+
if (persona.traits.length > 0) {
|
|
31
|
+
lines.push('## Personality Traits');
|
|
32
|
+
for (const trait of persona.traits) {
|
|
33
|
+
lines.push(`- ${trait}`);
|
|
34
|
+
}
|
|
35
|
+
lines.push('');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Quirks
|
|
39
|
+
if (persona.quirks.length > 0) {
|
|
40
|
+
lines.push('## Character Quirks');
|
|
41
|
+
lines.push('These are specific behaviors that make you memorable:');
|
|
42
|
+
for (const quirk of persona.quirks) {
|
|
43
|
+
lines.push(`- ${quirk}`);
|
|
44
|
+
}
|
|
45
|
+
lines.push('');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Cultural texture
|
|
49
|
+
if (persona.culture) {
|
|
50
|
+
lines.push('## Cultural Texture');
|
|
51
|
+
lines.push(`Your cultural background is ${persona.culture}. ${persona.languageRule}`);
|
|
52
|
+
lines.push('');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Metaphors
|
|
56
|
+
if (persona.metaphors.length > 0) {
|
|
57
|
+
lines.push('## Metaphor Domain');
|
|
58
|
+
lines.push(
|
|
59
|
+
`When explaining concepts, naturally draw from these domains: ${persona.metaphors.join(', ')}. ` +
|
|
60
|
+
'Adapt your metaphors to whatever the user is working on — the domain colors your language, it does not limit your knowledge.',
|
|
61
|
+
);
|
|
62
|
+
lines.push('');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Opinions
|
|
66
|
+
if (persona.opinions.length > 0) {
|
|
67
|
+
lines.push('## Opinions');
|
|
68
|
+
lines.push('You hold these beliefs about craft and quality:');
|
|
69
|
+
for (const opinion of persona.opinions) {
|
|
70
|
+
lines.push(`- "${opinion}"`);
|
|
71
|
+
}
|
|
72
|
+
lines.push('');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Name adaptation rule
|
|
76
|
+
if (persona.nameRule) {
|
|
77
|
+
lines.push('## Identity Persistence');
|
|
78
|
+
lines.push(persona.nameRule);
|
|
79
|
+
lines.push('');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Core instruction
|
|
83
|
+
lines.push('## Important');
|
|
84
|
+
lines.push(
|
|
85
|
+
'Stay in character naturally — your personality should feel organic, not performed. ' +
|
|
86
|
+
'You are a universal assistant that can help with ANY task. Your persona defines HOW you communicate, not WHAT you can do. ' +
|
|
87
|
+
'Your knowledge comes from your vault, brain, and what the user teaches you. ' +
|
|
88
|
+
'Be helpful first, characterful second — never let persona get in the way of being useful.',
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
// Pick a random greeting
|
|
92
|
+
const greeting =
|
|
93
|
+
persona.greetings.length > 0
|
|
94
|
+
? persona.greetings[Math.floor(Math.random() * persona.greetings.length)]
|
|
95
|
+
: `Hello! I'm ${persona.name}. What are we working on?`;
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
instructions: lines.join('\n'),
|
|
99
|
+
greeting,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Pick a random signoff from the persona.
|
|
105
|
+
*/
|
|
106
|
+
export function getRandomSignoff(persona: PersonaConfig): string {
|
|
107
|
+
if (persona.signoffs.length === 0) return 'Until next time!';
|
|
108
|
+
return persona.signoffs[Math.floor(Math.random() * persona.signoffs.length)];
|
|
109
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composable persona system for Soleri agents.
|
|
3
|
+
*
|
|
4
|
+
* A persona defines HOW the agent communicates, not WHAT it knows.
|
|
5
|
+
* Knowledge comes from vault + brain + user teaching.
|
|
6
|
+
* Persona gives the agent character, voice, and memorable interactions.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export type PersonaConfig = {
|
|
10
|
+
/** Agent display name — adapts pronouns/gender naturally */
|
|
11
|
+
name: string;
|
|
12
|
+
|
|
13
|
+
/** Template ID — 'italian-craftsperson' (default) or 'custom' */
|
|
14
|
+
template: string;
|
|
15
|
+
|
|
16
|
+
/** Character inspiration — anchors the voice and worldview */
|
|
17
|
+
inspiration: string;
|
|
18
|
+
|
|
19
|
+
/** Cultural flavor — sprinkle expressions from this culture */
|
|
20
|
+
culture: string;
|
|
21
|
+
|
|
22
|
+
/** Domains for metaphors — how the agent colors technical language */
|
|
23
|
+
metaphors: string[];
|
|
24
|
+
|
|
25
|
+
/** One-line voice description — how the agent sounds */
|
|
26
|
+
voice: string;
|
|
27
|
+
|
|
28
|
+
/** Personality traits — adjectives and behavioral tendencies */
|
|
29
|
+
traits: string[];
|
|
30
|
+
|
|
31
|
+
/** Specific repeatable behaviors that become the agent's signature */
|
|
32
|
+
quirks: string[];
|
|
33
|
+
|
|
34
|
+
/** Strong opinions about craft and quality */
|
|
35
|
+
opinions: string[];
|
|
36
|
+
|
|
37
|
+
/** How the agent adapts its language to the user */
|
|
38
|
+
languageRule: string;
|
|
39
|
+
|
|
40
|
+
/** How the agent handles name/gender changes */
|
|
41
|
+
nameRule: string;
|
|
42
|
+
|
|
43
|
+
/** Random greeting pool */
|
|
44
|
+
greetings: string[];
|
|
45
|
+
|
|
46
|
+
/** Random signoff pool */
|
|
47
|
+
signoffs: string[];
|
|
48
|
+
|
|
49
|
+
/** Archived previous personas (when user changes persona) */
|
|
50
|
+
history?: ArchivedPersona[];
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export type ArchivedPersona = {
|
|
54
|
+
/** When this persona was archived */
|
|
55
|
+
archivedAt: string;
|
|
56
|
+
/** The full persona config at time of archival */
|
|
57
|
+
config: Omit<PersonaConfig, 'history'>;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/** Minimal input for creating a persona from user description */
|
|
61
|
+
export type PersonaCreateInput = {
|
|
62
|
+
name: string;
|
|
63
|
+
description?: string;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/** What the prompt generator outputs */
|
|
67
|
+
export type PersonaSystemInstructions = {
|
|
68
|
+
/** Full system prompt section for persona */
|
|
69
|
+
instructions: string;
|
|
70
|
+
/** Random greeting for this session */
|
|
71
|
+
greeting: string;
|
|
72
|
+
};
|
|
@@ -36,7 +36,7 @@ interface PluginInfo {
|
|
|
36
36
|
* Create 24 extended admin operations for production observability.
|
|
37
37
|
*/
|
|
38
38
|
export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
|
|
39
|
-
const { vault, brain,
|
|
39
|
+
const { vault, brain, telemetry } = runtime;
|
|
40
40
|
|
|
41
41
|
// In-memory permission level — default 'moderate'
|
|
42
42
|
let permissionLevel: PermissionLevel = 'moderate';
|
|
@@ -240,7 +240,6 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
240
240
|
description: 'Status of all runtime modules — check each is initialized.',
|
|
241
241
|
auth: 'read',
|
|
242
242
|
handler: async () => {
|
|
243
|
-
const cogneeStatus = cognee?.getStatus() ?? null;
|
|
244
243
|
const llmAvailable = runtime.llmClient.isAvailable();
|
|
245
244
|
const loopStatus = runtime.loop.getStatus();
|
|
246
245
|
|
|
@@ -250,7 +249,6 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
250
249
|
planner: true,
|
|
251
250
|
curator: runtime.curator.getStatus().initialized,
|
|
252
251
|
governance: true,
|
|
253
|
-
cognee: { available: cogneeStatus?.available ?? false },
|
|
254
252
|
loop: { active: loopStatus !== null },
|
|
255
253
|
llm: {
|
|
256
254
|
openai: llmAvailable.openai,
|
|
@@ -280,7 +278,7 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
280
278
|
// ─── Garbage Collection ─────────────────────────────────────────
|
|
281
279
|
{
|
|
282
280
|
name: 'admin_gc',
|
|
283
|
-
description: 'Trigger garbage collection on in-memory caches — brain,
|
|
281
|
+
description: 'Trigger garbage collection on in-memory caches — brain, telemetry.',
|
|
284
282
|
auth: 'write',
|
|
285
283
|
handler: async () => {
|
|
286
284
|
const cleared: string[] = [];
|
|
@@ -292,15 +290,6 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
292
290
|
// Brain rebuild failed — graceful degradation
|
|
293
291
|
}
|
|
294
292
|
|
|
295
|
-
if (cognee) {
|
|
296
|
-
try {
|
|
297
|
-
cognee.resetPendingCognify();
|
|
298
|
-
cleared.push('cognee');
|
|
299
|
-
} catch {
|
|
300
|
-
// Cognee reset failed — graceful degradation
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
|
|
304
293
|
try {
|
|
305
294
|
telemetry.reset();
|
|
306
295
|
cleared.push('telemetry');
|
|
@@ -331,7 +320,6 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
331
320
|
'planner',
|
|
332
321
|
'curator',
|
|
333
322
|
'governance',
|
|
334
|
-
'cognee',
|
|
335
323
|
'loop',
|
|
336
324
|
'identityManager',
|
|
337
325
|
'intentRouter',
|
|
@@ -677,7 +665,7 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
677
665
|
description: 'Get health status of a specific subsystem.',
|
|
678
666
|
auth: 'read',
|
|
679
667
|
schema: z.object({
|
|
680
|
-
subsystem: z.string().describe('Subsystem name (e.g. "vault", "
|
|
668
|
+
subsystem: z.string().describe('Subsystem name (e.g. "vault", "brain", "llm")'),
|
|
681
669
|
}),
|
|
682
670
|
handler: async (params) => {
|
|
683
671
|
const sub = runtime.health.get(params.subsystem as string);
|
|
@@ -707,7 +695,7 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
707
695
|
description: 'Get the current value of a specific feature flag.',
|
|
708
696
|
auth: 'read',
|
|
709
697
|
schema: z.object({
|
|
710
|
-
flag: z.string().describe('Flag name (e.g. "auth-enforcement", "
|
|
698
|
+
flag: z.string().describe('Flag name (e.g. "auth-enforcement", "vault-sync")'),
|
|
711
699
|
}),
|
|
712
700
|
handler: async (params) => {
|
|
713
701
|
const flag = params.flag as string;
|
|
@@ -772,7 +760,7 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
772
760
|
{
|
|
773
761
|
name: 'admin_setup_check',
|
|
774
762
|
description:
|
|
775
|
-
'Check agent setup status — vault health, brain vocabulary,
|
|
763
|
+
'Check agent setup status — vault health, brain vocabulary, LLM keys, templates.',
|
|
776
764
|
auth: 'read',
|
|
777
765
|
handler: async () => {
|
|
778
766
|
const checks: Record<string, { ok: boolean; detail: string }> = {};
|
|
@@ -799,17 +787,6 @@ export function createAdminExtraOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
799
787
|
checks.brain = { ok: false, detail: 'Brain not initialized' };
|
|
800
788
|
}
|
|
801
789
|
|
|
802
|
-
// Cognee
|
|
803
|
-
const cogneeStatus = cognee?.getStatus() ?? null;
|
|
804
|
-
checks.cognee = {
|
|
805
|
-
ok: cogneeStatus?.available ?? false,
|
|
806
|
-
detail: cognee
|
|
807
|
-
? cogneeStatus?.available
|
|
808
|
-
? 'Connected'
|
|
809
|
-
: 'Not available (optional)'
|
|
810
|
-
: 'Disabled',
|
|
811
|
-
};
|
|
812
|
-
|
|
813
790
|
// LLM keys
|
|
814
791
|
const llmAvail = runtime.llmClient.isAvailable();
|
|
815
792
|
checks.llm = {
|
package/src/runtime/admin-ops.ts
CHANGED
|
@@ -41,17 +41,16 @@ function getCoreVersion(): string {
|
|
|
41
41
|
* Groups: health (1), introspection (4), diagnostics (2), mutation (1).
|
|
42
42
|
*/
|
|
43
43
|
export function createAdminOps(runtime: AgentRuntime): OpDefinition[] {
|
|
44
|
-
const { vault, brain, brainIntelligence,
|
|
44
|
+
const { vault, brain, brainIntelligence, llmClient, curator } = runtime;
|
|
45
45
|
|
|
46
46
|
return [
|
|
47
47
|
// ─── Health ──────────────────────────────────────────────────────
|
|
48
48
|
{
|
|
49
49
|
name: 'admin_health',
|
|
50
|
-
description: 'Comprehensive agent health check — vault,
|
|
50
|
+
description: 'Comprehensive agent health check — vault, LLM, brain status.',
|
|
51
51
|
auth: 'read',
|
|
52
52
|
handler: async () => {
|
|
53
53
|
const vaultStats = vault.stats();
|
|
54
|
-
const cogneeStatus = cognee?.getStatus() ?? null;
|
|
55
54
|
const llmAvailable = llmClient.isAvailable();
|
|
56
55
|
const brainStats = brain.getStats();
|
|
57
56
|
const curatorStatus = curator.getStatus();
|
|
@@ -59,7 +58,6 @@ export function createAdminOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
59
58
|
return {
|
|
60
59
|
status: 'ok',
|
|
61
60
|
vault: { entries: vaultStats.totalEntries, domains: Object.keys(vaultStats.byDomain) },
|
|
62
|
-
cognee: { available: cogneeStatus?.available ?? false },
|
|
63
61
|
llm: llmAvailable,
|
|
64
62
|
brain: {
|
|
65
63
|
vocabularySize: brainStats.vocabularySize,
|
|
@@ -174,21 +172,14 @@ export function createAdminOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
174
172
|
// ─── Mutation ────────────────────────────────────────────────────
|
|
175
173
|
{
|
|
176
174
|
name: 'admin_reset_cache',
|
|
177
|
-
description:
|
|
178
|
-
'Clear all caches — brain vocabulary and cognee health cache. Forces fresh data on next access.',
|
|
175
|
+
description: 'Clear all caches — brain vocabulary. Forces fresh data on next access.',
|
|
179
176
|
auth: 'write',
|
|
180
177
|
handler: async () => {
|
|
181
|
-
// Rebuild brain vocabulary (clears old TF-IDF state, rebuilds from vault)
|
|
182
178
|
brain.rebuildVocabulary();
|
|
183
179
|
|
|
184
|
-
// Reset cognee health cache by checking health again (no direct reset method)
|
|
185
|
-
// The next isAvailable check will need a fresh health probe
|
|
186
|
-
const cogneeHealth = cognee ? await cognee.healthCheck().catch(() => null) : null;
|
|
187
|
-
|
|
188
180
|
return {
|
|
189
|
-
cleared: ['brain_vocabulary'
|
|
181
|
+
cleared: ['brain_vocabulary'],
|
|
190
182
|
brainVocabularySize: brain.getStats().vocabularySize,
|
|
191
|
-
cogneeAvailable: cogneeHealth?.available ?? false,
|
|
192
183
|
};
|
|
193
184
|
},
|
|
194
185
|
},
|
|
@@ -250,31 +241,7 @@ export function createAdminOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
250
241
|
});
|
|
251
242
|
}
|
|
252
243
|
|
|
253
|
-
// 4.
|
|
254
|
-
try {
|
|
255
|
-
const cogneeStatus = cognee?.getStatus() ?? null;
|
|
256
|
-
if (cogneeStatus?.available) {
|
|
257
|
-
checks.push({
|
|
258
|
-
name: 'cognee',
|
|
259
|
-
status: 'ok',
|
|
260
|
-
detail: `Connected to ${cogneeStatus.url}`,
|
|
261
|
-
});
|
|
262
|
-
} else {
|
|
263
|
-
checks.push({
|
|
264
|
-
name: 'cognee',
|
|
265
|
-
status: 'warn',
|
|
266
|
-
detail: cogneeStatus?.error ?? 'Not connected (no health check yet)',
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
} catch (err) {
|
|
270
|
-
checks.push({
|
|
271
|
-
name: 'cognee',
|
|
272
|
-
status: 'error',
|
|
273
|
-
detail: err instanceof Error ? err.message : String(err),
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
// 5. LLM key pools
|
|
244
|
+
// 4. LLM key pools
|
|
278
245
|
const llmStatus = llmClient.isAvailable();
|
|
279
246
|
checks.push({
|
|
280
247
|
name: 'llm_openai',
|
|
@@ -228,34 +228,52 @@ export function createCaptureOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
228
228
|
}
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
// Auto-
|
|
232
|
-
|
|
231
|
+
// Auto-link captured entries (Zettelkasten enrichment)
|
|
232
|
+
// Creates links for suggestions above threshold; returns remaining as suggestions
|
|
233
|
+
const AUTO_LINK_THRESHOLD = 0.7;
|
|
234
|
+
const AUTO_LINK_MAX = 3;
|
|
235
|
+
let autoLinkedCount = 0;
|
|
236
|
+
const suggestedLinks: Array<{
|
|
233
237
|
entryId: string;
|
|
234
238
|
title: string;
|
|
235
239
|
suggestedType: string;
|
|
236
240
|
score: number;
|
|
241
|
+
autoLinked: boolean;
|
|
237
242
|
}> = [];
|
|
238
243
|
try {
|
|
239
244
|
if (captured > 0) {
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
)
|
|
249
|
-
|
|
245
|
+
const { LinkManager } = await import('../vault/linking.js');
|
|
246
|
+
const lm = new LinkManager(vault.getProvider());
|
|
247
|
+
|
|
248
|
+
// Process ALL captured entries, not just the first
|
|
249
|
+
const capturedEntries = results.filter((r) => r.action === 'capture');
|
|
250
|
+
for (const capturedEntry of capturedEntries) {
|
|
251
|
+
const suggestions = lm.suggestLinks(capturedEntry.id, AUTO_LINK_MAX + 2);
|
|
252
|
+
const filtered = suggestions.filter(
|
|
253
|
+
(s) => s.entryId !== capturedEntry.id && !s.entryId.endsWith(capturedEntry.id),
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
let linkedForThisEntry = 0;
|
|
257
|
+
for (const s of filtered) {
|
|
258
|
+
const aboveThreshold = s.score >= AUTO_LINK_THRESHOLD;
|
|
259
|
+
const canAutoLink = aboveThreshold && linkedForThisEntry < AUTO_LINK_MAX;
|
|
260
|
+
if (canAutoLink) {
|
|
261
|
+
lm.addLink(capturedEntry.id, s.entryId, s.suggestedType);
|
|
262
|
+
linkedForThisEntry++;
|
|
263
|
+
autoLinkedCount++;
|
|
264
|
+
}
|
|
265
|
+
suggestedLinks.push({
|
|
250
266
|
entryId: s.entryId,
|
|
251
267
|
title: s.title,
|
|
252
268
|
suggestedType: s.suggestedType,
|
|
253
269
|
score: s.score,
|
|
254
|
-
|
|
270
|
+
autoLinked: canAutoLink,
|
|
271
|
+
});
|
|
272
|
+
}
|
|
255
273
|
}
|
|
256
274
|
}
|
|
257
275
|
} catch {
|
|
258
|
-
/* never break capture for
|
|
276
|
+
/* never break capture for linking failures */
|
|
259
277
|
}
|
|
260
278
|
|
|
261
279
|
return {
|
|
@@ -263,6 +281,7 @@ export function createCaptureOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
263
281
|
proposed,
|
|
264
282
|
rejected,
|
|
265
283
|
duplicated,
|
|
284
|
+
autoLinkedCount,
|
|
266
285
|
results,
|
|
267
286
|
...(suggestedLinks.length > 0 ? { suggestedLinks } : {}),
|
|
268
287
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Semantic facade assembler — creates
|
|
2
|
+
* Semantic facade assembler — creates domain-specific facades
|
|
3
3
|
* matching Salvador's engine-level architecture.
|
|
4
4
|
*
|
|
5
5
|
* Each facade becomes its own MCP tool with op dispatch.
|
|
@@ -16,7 +16,6 @@ import { createCuratorFacadeOps } from './curator-facade.js';
|
|
|
16
16
|
import { createLoopFacadeOps } from './loop-facade.js';
|
|
17
17
|
import { createOrchestrateFacadeOps } from './orchestrate-facade.js';
|
|
18
18
|
import { createControlFacadeOps } from './control-facade.js';
|
|
19
|
-
import { createCogneeFacadeOps } from './cognee-facade.js';
|
|
20
19
|
import { createContextFacadeOps } from './context-facade.js';
|
|
21
20
|
import { createAgencyFacadeOps } from './agency-facade.js';
|
|
22
21
|
import { createChatFacadeOps } from './chat-facade.js';
|
|
@@ -88,14 +87,5 @@ export function createSemanticFacades(runtime: AgentRuntime, agentId: string): F
|
|
|
88
87
|
},
|
|
89
88
|
];
|
|
90
89
|
|
|
91
|
-
// Cognee facade — only registered when Cognee integration is enabled
|
|
92
|
-
if (runtime.cognee) {
|
|
93
|
-
facades.push({
|
|
94
|
-
name: `${agentId}_cognee`,
|
|
95
|
-
description: 'Knowledge graph — Cognee search, sync, export, graph stats.',
|
|
96
|
-
ops: createCogneeFacadeOps(runtime),
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
|
|
100
90
|
return facades;
|
|
101
91
|
}
|