@soleri/core 8.0.0 → 8.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/dist/brain/knowledge-synthesizer.d.ts.map +1 -1
- package/dist/brain/knowledge-synthesizer.js +0 -2
- package/dist/brain/knowledge-synthesizer.js.map +1 -1
- package/dist/curator/classifier.d.ts.map +1 -1
- package/dist/curator/classifier.js +0 -2
- package/dist/curator/classifier.js.map +1 -1
- package/dist/curator/quality-gate.d.ts.map +1 -1
- package/dist/curator/quality-gate.js +0 -2
- package/dist/curator/quality-gate.js.map +1 -1
- package/dist/domain-packs/index.d.ts +0 -3
- package/dist/domain-packs/index.d.ts.map +1 -1
- package/dist/domain-packs/index.js +0 -3
- package/dist/domain-packs/index.js.map +1 -1
- package/dist/domain-packs/loader.d.ts.map +1 -1
- package/dist/domain-packs/loader.js +20 -4
- package/dist/domain-packs/loader.js.map +1 -1
- package/dist/domain-packs/pack-runtime.d.ts +5 -5
- package/dist/domain-packs/pack-runtime.d.ts.map +1 -1
- package/dist/domain-packs/pack-runtime.js +2 -2
- package/dist/domain-packs/pack-runtime.js.map +1 -1
- package/dist/domain-packs/types.d.ts +8 -2
- package/dist/domain-packs/types.d.ts.map +1 -1
- package/dist/domain-packs/types.js.map +1 -1
- package/dist/engine/bin/soleri-engine.js +12 -2
- package/dist/engine/bin/soleri-engine.js.map +1 -1
- package/dist/engine/index.d.ts +2 -0
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +1 -0
- package/dist/engine/index.js.map +1 -1
- package/dist/engine/module-manifest.d.ts +28 -0
- package/dist/engine/module-manifest.d.ts.map +1 -0
- package/dist/engine/module-manifest.js +85 -0
- package/dist/engine/module-manifest.js.map +1 -0
- package/dist/engine/register-engine.d.ts +19 -0
- package/dist/engine/register-engine.d.ts.map +1 -1
- package/dist/engine/register-engine.js +15 -2
- package/dist/engine/register-engine.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/intake/content-classifier.d.ts.map +1 -1
- package/dist/intake/content-classifier.js +0 -2
- package/dist/intake/content-classifier.js.map +1 -1
- package/dist/llm/llm-client.d.ts.map +1 -1
- package/dist/llm/llm-client.js +8 -4
- package/dist/llm/llm-client.js.map +1 -1
- package/dist/llm/oauth-discovery.d.ts +0 -8
- package/dist/llm/oauth-discovery.d.ts.map +1 -1
- package/dist/llm/oauth-discovery.js +0 -19
- package/dist/llm/oauth-discovery.js.map +1 -1
- package/dist/llm/types.d.ts +4 -2
- package/dist/llm/types.d.ts.map +1 -1
- package/dist/packs/pack-installer.d.ts +2 -1
- package/dist/packs/pack-installer.d.ts.map +1 -1
- package/dist/packs/pack-installer.js +10 -1
- package/dist/packs/pack-installer.js.map +1 -1
- package/dist/persistence/index.d.ts +0 -1
- package/dist/persistence/index.d.ts.map +1 -1
- package/dist/persistence/index.js +0 -1
- package/dist/persistence/index.js.map +1 -1
- package/dist/persistence/types.d.ts +2 -6
- package/dist/persistence/types.d.ts.map +1 -1
- package/dist/plugins/index.d.ts +4 -0
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js +4 -0
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/plugin-registry.d.ts +4 -0
- package/dist/plugins/plugin-registry.d.ts.map +1 -1
- package/dist/plugins/plugin-registry.js +4 -0
- package/dist/plugins/plugin-registry.js.map +1 -1
- package/dist/plugins/types.d.ts +32 -27
- package/dist/plugins/types.d.ts.map +1 -1
- package/dist/plugins/types.js +6 -3
- package/dist/plugins/types.js.map +1 -1
- package/dist/runtime/claude-md-helpers.d.ts +0 -9
- package/dist/runtime/claude-md-helpers.d.ts.map +1 -1
- package/dist/runtime/claude-md-helpers.js +1 -14
- package/dist/runtime/claude-md-helpers.js.map +1 -1
- package/dist/runtime/facades/admin-facade.d.ts.map +1 -1
- package/dist/runtime/facades/admin-facade.js +1 -2
- package/dist/runtime/facades/admin-facade.js.map +1 -1
- package/dist/runtime/pack-ops.d.ts +3 -0
- package/dist/runtime/pack-ops.d.ts.map +1 -1
- package/dist/runtime/pack-ops.js +18 -1
- package/dist/runtime/pack-ops.js.map +1 -1
- package/dist/runtime/plugin-ops.d.ts.map +1 -1
- package/dist/runtime/plugin-ops.js +3 -0
- package/dist/runtime/plugin-ops.js.map +1 -1
- package/dist/runtime/session-briefing.d.ts.map +1 -1
- package/dist/runtime/session-briefing.js +14 -0
- package/dist/runtime/session-briefing.js.map +1 -1
- package/dist/runtime/vault-linking-ops.d.ts.map +1 -1
- package/dist/runtime/vault-linking-ops.js +2 -4
- package/dist/runtime/vault-linking-ops.js.map +1 -1
- package/dist/vault/vault.d.ts +9 -0
- package/dist/vault/vault.d.ts.map +1 -1
- package/dist/vault/vault.js +22 -0
- package/dist/vault/vault.js.map +1 -1
- package/package.json +6 -4
- package/src/__tests__/curator-pipeline-e2e.test.ts +187 -0
- package/src/__tests__/module-manifest-drift.test.ts +59 -0
- package/src/brain/knowledge-synthesizer.ts +0 -2
- package/src/curator/classifier.ts +0 -2
- package/src/curator/quality-gate.ts +0 -2
- package/src/domain-packs/index.ts +0 -6
- package/src/domain-packs/loader.ts +25 -5
- package/src/domain-packs/pack-runtime.ts +6 -6
- package/src/domain-packs/types.ts +8 -2
- package/src/engine/bin/soleri-engine.ts +17 -2
- package/src/engine/index.ts +2 -0
- package/src/engine/module-manifest.ts +99 -0
- package/src/engine/register-engine.ts +21 -2
- package/src/index.ts +0 -1
- package/src/intake/content-classifier.ts +0 -2
- package/src/llm/llm-client.ts +12 -6
- package/src/llm/oauth-discovery.ts +0 -18
- package/src/llm/types.ts +4 -2
- package/src/packs/pack-installer.ts +16 -1
- package/src/persistence/index.ts +0 -1
- package/src/persistence/types.ts +2 -6
- package/src/plugins/index.ts +4 -0
- package/src/plugins/plugin-registry.ts +6 -1
- package/src/plugins/types.ts +10 -5
- package/src/runtime/claude-md-helpers.ts +1 -19
- package/src/runtime/facades/admin-facade.ts +1 -2
- package/src/runtime/pack-ops.ts +26 -1
- package/src/runtime/plugin-ops.ts +3 -0
- package/src/runtime/session-briefing.ts +14 -0
- package/src/runtime/vault-linking-ops.ts +2 -4
- package/src/vault/vault.ts +26 -0
- package/src/__tests__/postgres-provider.test.ts +0 -116
- package/src/health/doctor-checks.ts +0 -115
- package/src/persistence/postgres-provider.ts +0 -310
|
@@ -14,7 +14,7 @@ import type { Vault } from '../vault/vault.js';
|
|
|
14
14
|
*/
|
|
15
15
|
export interface PackProjectContext {
|
|
16
16
|
id: string;
|
|
17
|
-
name
|
|
17
|
+
name?: string;
|
|
18
18
|
path: string;
|
|
19
19
|
colors?: {
|
|
20
20
|
[scale: string]: {
|
|
@@ -49,7 +49,7 @@ export interface PackRuntime {
|
|
|
49
49
|
getProject(projectId: string): PackProjectContext | undefined;
|
|
50
50
|
|
|
51
51
|
/** List all registered projects */
|
|
52
|
-
listProjects(): Array<{ id: string; name
|
|
52
|
+
listProjects(): Array<{ id: string; name?: string; path: string }>;
|
|
53
53
|
|
|
54
54
|
/** Create a session check (for tool chaining) */
|
|
55
55
|
createCheck(type: string, data: Record<string, unknown>): string;
|
|
@@ -70,8 +70,8 @@ export interface PackRuntime {
|
|
|
70
70
|
export function createPackRuntime(runtime: {
|
|
71
71
|
vault: Vault;
|
|
72
72
|
projectRegistry: {
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
get(id: string): PackProjectContext | null;
|
|
74
|
+
list(): Array<{ id: string; name?: string; path: string }>;
|
|
75
75
|
};
|
|
76
76
|
sessionStore?: {
|
|
77
77
|
createCheck(type: string, data: Record<string, unknown>): string;
|
|
@@ -81,8 +81,8 @@ export function createPackRuntime(runtime: {
|
|
|
81
81
|
}): PackRuntime {
|
|
82
82
|
return {
|
|
83
83
|
vault: runtime.vault,
|
|
84
|
-
getProject: (id) => runtime.projectRegistry.
|
|
85
|
-
listProjects: () => runtime.projectRegistry.
|
|
84
|
+
getProject: (id) => runtime.projectRegistry.get(id) ?? undefined,
|
|
85
|
+
listProjects: () => runtime.projectRegistry.list(),
|
|
86
86
|
createCheck: (type, data) => {
|
|
87
87
|
if (!runtime.sessionStore) throw new Error('Session store not available');
|
|
88
88
|
return runtime.sessionStore.createCheck(type, data);
|
|
@@ -93,8 +93,14 @@ export interface DomainPack {
|
|
|
93
93
|
requires?: string[];
|
|
94
94
|
/** Called after pack is installed (one-time setup). */
|
|
95
95
|
onInstall?: (runtime: AgentRuntime) => Promise<void>;
|
|
96
|
-
/**
|
|
97
|
-
|
|
96
|
+
/**
|
|
97
|
+
* Called each time the agent starts (runtime initialization).
|
|
98
|
+
*
|
|
99
|
+
* Receives `PackRuntime` (narrowed interface with vault, projects, session checks).
|
|
100
|
+
* The full `AgentRuntime` is passed as second argument for backwards compatibility
|
|
101
|
+
* but is deprecated — packs should only use `PackRuntime`.
|
|
102
|
+
*/
|
|
103
|
+
onActivate?: (packRuntime: PackRuntime, runtime?: AgentRuntime) => Promise<void>;
|
|
98
104
|
}
|
|
99
105
|
|
|
100
106
|
// ---------------------------------------------------------------------------
|
|
@@ -117,6 +117,14 @@ async function main(): Promise<void> {
|
|
|
117
117
|
// 6. Seed default playbooks
|
|
118
118
|
seedDefaultPlaybooks(runtime.vault);
|
|
119
119
|
|
|
120
|
+
// Log vault stats for first-run visibility
|
|
121
|
+
const vaultStats = runtime.vault.stats();
|
|
122
|
+
console.error(
|
|
123
|
+
`${tag} Vault: ${vaultStats.totalEntries} entries (${Object.entries(vaultStats.byType ?? {})
|
|
124
|
+
.map(([t, n]) => `${n} ${t}`)
|
|
125
|
+
.join(', ')})`,
|
|
126
|
+
);
|
|
127
|
+
|
|
120
128
|
// 7. Load domain packs
|
|
121
129
|
const packs = (config.packs ?? []) as Array<{ name: string; package: string; version?: string }>;
|
|
122
130
|
const loadedPacks: Array<{ name: string; facades?: Array<{ name: string; ops: unknown[] }> }> =
|
|
@@ -129,9 +137,12 @@ async function main(): Promise<void> {
|
|
|
129
137
|
const manifests = await loadDomainPacksFromConfig(refs);
|
|
130
138
|
|
|
131
139
|
// Packs activate sequentially — order may matter for dependencies
|
|
140
|
+
const { createPackRuntime } = await import('../../domain-packs/pack-runtime.js');
|
|
141
|
+
const narrowedRuntime = createPackRuntime(runtime);
|
|
142
|
+
|
|
132
143
|
for (const manifest of manifests) {
|
|
133
144
|
if (manifest.onActivate) {
|
|
134
|
-
await manifest.onActivate(runtime); // eslint-disable-line no-await-in-loop
|
|
145
|
+
await manifest.onActivate(narrowedRuntime, runtime); // eslint-disable-line no-await-in-loop
|
|
135
146
|
}
|
|
136
147
|
loadedPacks.push(manifest);
|
|
137
148
|
console.error(`${tag} Domain pack: ${manifest.name}`);
|
|
@@ -178,7 +189,7 @@ async function main(): Promise<void> {
|
|
|
178
189
|
}));
|
|
179
190
|
|
|
180
191
|
// 12. Register all engine tools
|
|
181
|
-
const { tools, totalOps } = registerEngine(server, runtime, {
|
|
192
|
+
const { tools, totalOps, registerTool } = registerEngine(server, runtime, {
|
|
182
193
|
agentId,
|
|
183
194
|
coreOps,
|
|
184
195
|
domains: identity.domains,
|
|
@@ -195,6 +206,10 @@ async function main(): Promise<void> {
|
|
|
195
206
|
|
|
196
207
|
console.error(`${tag} Registered ${tools.length} tools (${totalOps} ops)`);
|
|
197
208
|
|
|
209
|
+
// Enable hot reload for post-boot pack/plugin installation
|
|
210
|
+
const { setHotRegister } = await import('../../runtime/pack-ops.js');
|
|
211
|
+
setHotRegister(registerTool);
|
|
212
|
+
|
|
198
213
|
// 13. Connect stdio transport
|
|
199
214
|
const transport = new StdioServerTransport();
|
|
200
215
|
await server.connect(transport);
|
package/src/engine/index.ts
CHANGED
|
@@ -17,3 +17,5 @@ export { registerEngine } from './register-engine.js';
|
|
|
17
17
|
export type { EngineRegistrationOptions, EngineRegistrationResult } from './register-engine.js';
|
|
18
18
|
export { createCoreOps } from './core-ops.js';
|
|
19
19
|
export type { AgentIdentityConfig } from './core-ops.js';
|
|
20
|
+
export { ENGINE_MODULE_MANIFEST, CORE_KEY_OPS } from './module-manifest.js';
|
|
21
|
+
export type { ModuleManifestEntry } from './module-manifest.js';
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Soleri Engine Module Manifest
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for engine module names, descriptions, and key ops.
|
|
5
|
+
* Used by register-engine.ts at runtime and by @soleri/forge for template generation.
|
|
6
|
+
*
|
|
7
|
+
* This file is intentionally dependency-free so it can be imported by any package.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export interface ModuleManifestEntry {
|
|
11
|
+
/** Suffix for tool name: {agentId}_{suffix} */
|
|
12
|
+
suffix: string;
|
|
13
|
+
/** Human-readable description */
|
|
14
|
+
description: string;
|
|
15
|
+
/** Representative ops shown in placeholder tables (max 4) */
|
|
16
|
+
keyOps: string[];
|
|
17
|
+
/** If true, module requires a runtime condition to register */
|
|
18
|
+
conditional?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Canonical list of engine modules.
|
|
23
|
+
* Order here determines order in generated tool tables.
|
|
24
|
+
*/
|
|
25
|
+
export const ENGINE_MODULE_MANIFEST: ModuleManifestEntry[] = [
|
|
26
|
+
{
|
|
27
|
+
suffix: 'vault',
|
|
28
|
+
description: 'Knowledge management — search, CRUD, import/export, intake, archival.',
|
|
29
|
+
keyOps: ['search_intelligent', 'capture_knowledge', 'capture_quick'],
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
suffix: 'plan',
|
|
33
|
+
description: 'Plan lifecycle — create, approve, execute, reconcile, complete, grading.',
|
|
34
|
+
keyOps: ['create_plan', 'approve_plan', 'plan_split', 'plan_reconcile'],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
suffix: 'brain',
|
|
38
|
+
description: 'Learning system — intelligence pipeline, strengths, feedback, sessions.',
|
|
39
|
+
keyOps: ['recommend', 'strengths', 'feedback'],
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
suffix: 'memory',
|
|
43
|
+
description: 'Session & cross-project memory — capture, search, dedup, promote.',
|
|
44
|
+
keyOps: ['memory_search', 'memory_capture', 'session_capture'],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
suffix: 'admin',
|
|
48
|
+
description: 'Infrastructure — health, config, telemetry, tokens, LLM, prompts.',
|
|
49
|
+
keyOps: ['admin_health', 'admin_tool_list', 'admin_diagnostic'],
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
suffix: 'curator',
|
|
53
|
+
description: 'Quality — duplicate detection, contradictions, grooming, health audit.',
|
|
54
|
+
keyOps: ['curator_groom', 'curator_status', 'curator_health'],
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
suffix: 'loop',
|
|
58
|
+
description: 'Iterative validation loops — start, iterate, cancel, complete, history.',
|
|
59
|
+
keyOps: ['loop_start', 'loop_status', 'loop_cancel'],
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
suffix: 'orchestrate',
|
|
63
|
+
description:
|
|
64
|
+
'Execution orchestration — project registration, playbooks, plan/execute/complete.',
|
|
65
|
+
keyOps: ['orchestrate_plan', 'orchestrate_execute', 'orchestrate_complete'],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
suffix: 'control',
|
|
69
|
+
description: 'Agent behavior — identity, intent routing, morphing, guidelines, governance.',
|
|
70
|
+
keyOps: ['route_intent', 'morph', 'get_behavior_rules'],
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
suffix: 'context',
|
|
74
|
+
description: 'Context analysis — entity extraction, knowledge retrieval, confidence scoring.',
|
|
75
|
+
keyOps: ['context_extract_entities', 'context_retrieve_knowledge', 'context_analyze'],
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
suffix: 'agency',
|
|
79
|
+
description: 'Proactive intelligence — file watching, pattern surfacing, warnings.',
|
|
80
|
+
keyOps: ['agency_scan_file', 'agency_surface_patterns', 'agency_warnings'],
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
suffix: 'chat',
|
|
84
|
+
description: 'Chat transport — session management, response chunking, authentication.',
|
|
85
|
+
keyOps: ['chat_send', 'chat_history', 'chat_session'],
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
suffix: 'cognee',
|
|
89
|
+
description: 'Knowledge graph — Cognee search, sync, export, graph stats.',
|
|
90
|
+
keyOps: ['cognee_search', 'cognee_add', 'cognee_cognify'],
|
|
91
|
+
conditional: true,
|
|
92
|
+
},
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
/** Core facade ops (always present, not in ENGINE_MODULES) */
|
|
96
|
+
export const CORE_KEY_OPS = ['health', 'identity', 'register', 'activate'];
|
|
97
|
+
|
|
98
|
+
/** Engine major version — used for compatibility checks against domain packs. */
|
|
99
|
+
export const ENGINE_MAJOR_VERSION = 8;
|
|
@@ -60,6 +60,12 @@ export interface EngineRegistrationResult {
|
|
|
60
60
|
tools: string[];
|
|
61
61
|
/** Total op count across all tools */
|
|
62
62
|
totalOps: number;
|
|
63
|
+
/**
|
|
64
|
+
* Register a new MCP tool at runtime (hot reload).
|
|
65
|
+
* Call this after installing a pack or activating a plugin post-boot.
|
|
66
|
+
* Automatically notifies connected clients via sendToolListChanged().
|
|
67
|
+
*/
|
|
68
|
+
registerTool: (toolName: string, description: string, ops: OpDefinition[]) => void;
|
|
63
69
|
}
|
|
64
70
|
|
|
65
71
|
// ─── Module Definition ────────────────────────────────────────────────
|
|
@@ -75,7 +81,8 @@ interface ModuleDef {
|
|
|
75
81
|
condition?: (runtime: AgentRuntime) => boolean;
|
|
76
82
|
}
|
|
77
83
|
|
|
78
|
-
|
|
84
|
+
/** @internal Exported for drift testing — do not use outside engine */
|
|
85
|
+
export const ENGINE_MODULES: ModuleDef[] = [
|
|
79
86
|
{
|
|
80
87
|
suffix: 'vault',
|
|
81
88
|
description: 'Knowledge management — search, CRUD, import/export, intake, archival.',
|
|
@@ -233,7 +240,19 @@ export function registerEngine(
|
|
|
233
240
|
}
|
|
234
241
|
}
|
|
235
242
|
|
|
236
|
-
|
|
243
|
+
const registerTool = (toolName: string, description: string, ops: OpDefinition[]) => {
|
|
244
|
+
registerModuleTool(server, toolName, description, ops, authPolicy);
|
|
245
|
+
registeredTools.push(toolName);
|
|
246
|
+
totalOps += ops.length;
|
|
247
|
+
// Notify connected clients that tool list changed
|
|
248
|
+
try {
|
|
249
|
+
(server as unknown as { sendToolListChanged?: () => void }).sendToolListChanged?.();
|
|
250
|
+
} catch {
|
|
251
|
+
// Server may not support notifications yet — safe to ignore
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
return { tools: registeredTools, totalOps, registerTool };
|
|
237
256
|
}
|
|
238
257
|
|
|
239
258
|
// ─── Tool Registration (No Factory) ──────────────────────────────────
|
package/src/index.ts
CHANGED
|
@@ -541,7 +541,6 @@ export type {
|
|
|
541
541
|
|
|
542
542
|
// ─── Persistence ───────────────────────────────────────────────────────
|
|
543
543
|
export { SQLitePersistenceProvider } from './persistence/index.js';
|
|
544
|
-
export { PostgresPersistenceProvider, translateSql } from './persistence/index.js';
|
|
545
544
|
export type {
|
|
546
545
|
PersistenceProvider,
|
|
547
546
|
PersistenceParams,
|
package/src/llm/llm-client.ts
CHANGED
|
@@ -160,6 +160,8 @@ interface AnthropicClient {
|
|
|
160
160
|
};
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
type ResolvedLLMOptions = LLMCallOptions & { model: string; provider: 'openai' | 'anthropic' };
|
|
164
|
+
|
|
163
165
|
export class LLMClient {
|
|
164
166
|
private openaiKeyPool: KeyPool;
|
|
165
167
|
private anthropicKeyPool: KeyPool;
|
|
@@ -181,11 +183,15 @@ export class LLMClient {
|
|
|
181
183
|
|
|
182
184
|
async complete(options: LLMCallOptions): Promise<LLMCallResult> {
|
|
183
185
|
const routed = this.router.resolve(options.caller, options.task, options.model);
|
|
184
|
-
const
|
|
186
|
+
const resolved: ResolvedLLMOptions = {
|
|
187
|
+
...options,
|
|
188
|
+
model: options.model ?? routed.model,
|
|
189
|
+
provider: options.provider ?? routed.provider,
|
|
190
|
+
};
|
|
185
191
|
|
|
186
|
-
return
|
|
187
|
-
? this.callAnthropic(
|
|
188
|
-
: this.callOpenAI(
|
|
192
|
+
return resolved.provider === 'anthropic'
|
|
193
|
+
? this.callAnthropic(resolved)
|
|
194
|
+
: this.callOpenAI(resolved);
|
|
189
195
|
}
|
|
190
196
|
|
|
191
197
|
isAvailable(): { openai: boolean; anthropic: boolean } {
|
|
@@ -203,7 +209,7 @@ export class LLMClient {
|
|
|
203
209
|
// OPENAI
|
|
204
210
|
// ===========================================================================
|
|
205
211
|
|
|
206
|
-
private async callOpenAI(options:
|
|
212
|
+
private async callOpenAI(options: ResolvedLLMOptions): Promise<LLMCallResult> {
|
|
207
213
|
const keyPool = this.openaiKeyPool.hasKeys ? this.openaiKeyPool : null;
|
|
208
214
|
|
|
209
215
|
if (!keyPool) {
|
|
@@ -275,7 +281,7 @@ export class LLMClient {
|
|
|
275
281
|
// ANTHROPIC
|
|
276
282
|
// ===========================================================================
|
|
277
283
|
|
|
278
|
-
private async callAnthropic(options:
|
|
284
|
+
private async callAnthropic(options: ResolvedLLMOptions): Promise<LLMCallResult> {
|
|
279
285
|
const client = await this.getAnthropicClient();
|
|
280
286
|
if (!client) {
|
|
281
287
|
throw new LLMError('Anthropic API key not configured', { retryable: false });
|
|
@@ -43,24 +43,6 @@ export function discoverAnthropicToken(): string | null {
|
|
|
43
43
|
return token;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
/**
|
|
47
|
-
* Clear the cached token (for testing or rotation).
|
|
48
|
-
*/
|
|
49
|
-
export function resetTokenCache(): void {
|
|
50
|
-
cachedToken = null;
|
|
51
|
-
cacheTimestamp = 0;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Get discovery source info (for diagnostics).
|
|
56
|
-
*/
|
|
57
|
-
export function getTokenSource(): string {
|
|
58
|
-
if (process.env.ANTHROPIC_API_KEY) return 'env:ANTHROPIC_API_KEY';
|
|
59
|
-
if (tryCredentialsFile()) return 'file:credentials';
|
|
60
|
-
if (tryPlatformKeychain()) return `keychain:${platform()}`;
|
|
61
|
-
return 'none';
|
|
62
|
-
}
|
|
63
|
-
|
|
64
46
|
// ─── Discovery Methods ───────────────────────────────────────────────
|
|
65
47
|
|
|
66
48
|
function tryEnvVar(): string | null {
|
package/src/llm/types.ts
CHANGED
|
@@ -43,8 +43,10 @@ export class LLMError extends Error {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
export interface LLMCallOptions {
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
/** Provider override. If omitted, the model router selects based on caller/task. */
|
|
47
|
+
provider?: 'openai' | 'anthropic';
|
|
48
|
+
/** Model override. If omitted, the model router selects based on caller/task. */
|
|
49
|
+
model?: string;
|
|
48
50
|
systemPrompt: string;
|
|
49
51
|
userPrompt: string;
|
|
50
52
|
temperature?: number;
|
|
@@ -21,6 +21,7 @@ import { loadIntelligenceData } from '../intelligence/loader.js';
|
|
|
21
21
|
import type { Vault } from '../vault/vault.js';
|
|
22
22
|
import type { PluginRegistry } from '../plugins/plugin-registry.js';
|
|
23
23
|
import type { PluginContext } from '../plugins/types.js';
|
|
24
|
+
import type { PackRuntime } from '../domain-packs/pack-runtime.js';
|
|
24
25
|
|
|
25
26
|
const MANIFEST_FILENAME = 'soleri-pack.json';
|
|
26
27
|
|
|
@@ -108,7 +109,11 @@ export class PackInstaller {
|
|
|
108
109
|
/**
|
|
109
110
|
* Install a knowledge pack from a directory.
|
|
110
111
|
*/
|
|
111
|
-
async install(
|
|
112
|
+
async install(
|
|
113
|
+
packDir: string,
|
|
114
|
+
runtimeCtx?: unknown,
|
|
115
|
+
packRuntime?: PackRuntime,
|
|
116
|
+
): Promise<InstallResult> {
|
|
112
117
|
// Validate first
|
|
113
118
|
const validation = this.validate(packDir);
|
|
114
119
|
if (!validation.valid || !validation.manifest) {
|
|
@@ -174,6 +179,16 @@ export class PackInstaller {
|
|
|
174
179
|
}
|
|
175
180
|
|
|
176
181
|
const ctx: PluginContext = {
|
|
182
|
+
packRuntime:
|
|
183
|
+
packRuntime ??
|
|
184
|
+
({
|
|
185
|
+
vault: {},
|
|
186
|
+
getProject: () => undefined,
|
|
187
|
+
listProjects: () => [],
|
|
188
|
+
createCheck: () => '',
|
|
189
|
+
validateCheck: () => null,
|
|
190
|
+
validateAndConsume: () => null,
|
|
191
|
+
} as unknown as PackRuntime),
|
|
177
192
|
runtime: runtimeCtx ?? {},
|
|
178
193
|
manifest: pluginLoaded.manifest,
|
|
179
194
|
directory: packDir,
|
package/src/persistence/index.ts
CHANGED
package/src/persistence/types.ts
CHANGED
|
@@ -35,7 +35,7 @@ export interface PersistenceProvider {
|
|
|
35
35
|
transaction<T>(fn: () => T): T;
|
|
36
36
|
|
|
37
37
|
/** Identifies the backend engine. */
|
|
38
|
-
readonly backend: 'sqlite'
|
|
38
|
+
readonly backend: 'sqlite';
|
|
39
39
|
|
|
40
40
|
/** Full-text search abstraction. */
|
|
41
41
|
ftsSearch<T = Record<string, unknown>>(
|
|
@@ -52,12 +52,8 @@ export interface PersistenceProvider {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
export interface PersistenceConfig {
|
|
55
|
-
type: 'sqlite'
|
|
55
|
+
type: 'sqlite';
|
|
56
56
|
path: string;
|
|
57
|
-
/** PostgreSQL connection string. */
|
|
58
|
-
connectionString?: string;
|
|
59
|
-
/** PostgreSQL pool size. */
|
|
60
|
-
poolSize?: number;
|
|
61
57
|
}
|
|
62
58
|
|
|
63
59
|
export interface FtsSearchOptions {
|
package/src/plugins/index.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Plugin System — Barrel Exports
|
|
3
|
+
*
|
|
4
|
+
* @deprecated Prefer knowledge packs (soleri-pack.json) for new extensions.
|
|
5
|
+
* The plugin system is maintained for backwards compatibility and is used
|
|
6
|
+
* internally by the pack installer for facade registration.
|
|
3
7
|
*/
|
|
4
8
|
|
|
5
9
|
export {
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Plugin Registry — tracks loaded plugins and their lifecycle.
|
|
3
3
|
*
|
|
4
|
+
* @deprecated The plugin system is superseded by knowledge packs (`soleri-pack.json`).
|
|
5
|
+
* This registry is still used internally by the pack installer to register facades,
|
|
6
|
+
* but new extensions should use the pack system directly.
|
|
7
|
+
*
|
|
4
8
|
* Not a singleton — lives on AgentRuntime for testability.
|
|
5
9
|
* Lifecycle: load → register → activate → (deactivate | error)
|
|
6
10
|
*/
|
|
@@ -161,7 +165,8 @@ export class PluginRegistry {
|
|
|
161
165
|
throw new Error(`Plugin module "${moduleFile}" must export createFacades(ctx)`);
|
|
162
166
|
} catch (e) {
|
|
163
167
|
throw new Error(
|
|
164
|
-
`Failed to load plugin module "${moduleFile}": ${e instanceof Error ? e.message : String(e)}`,
|
|
168
|
+
`Failed to load plugin module "${moduleFile}": ${e instanceof Error ? e.message : String(e)}`,
|
|
169
|
+
{ cause: e },
|
|
165
170
|
);
|
|
166
171
|
}
|
|
167
172
|
}
|
package/src/plugins/types.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Plugin System — Types & Manifest Schema
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* @deprecated Prefer knowledge packs (`soleri-pack.json`) over plugins (`soleri-plugin.json`).
|
|
5
|
+
* Knowledge packs are a superset of plugins — they support facades, vault entries, skills,
|
|
6
|
+
* hooks, and capability declarations. Plugins only support facades and intelligence entries.
|
|
7
|
+
*
|
|
8
|
+
* This module is maintained for backwards compatibility. New extensions should use
|
|
9
|
+
* the pack system in `../packs/`. See docs/architecture/extension-tiers.md.
|
|
7
10
|
*/
|
|
8
11
|
|
|
9
12
|
import { z } from 'zod';
|
|
@@ -101,8 +104,10 @@ export type PluginFacadeBuilder = (ctx: PluginContext) => FacadeConfig[];
|
|
|
101
104
|
* Context passed to plugin facade builders during activation.
|
|
102
105
|
*/
|
|
103
106
|
export interface PluginContext {
|
|
104
|
-
/**
|
|
105
|
-
|
|
107
|
+
/** Narrowed runtime — vault, projects, session checks. Preferred over full runtime. */
|
|
108
|
+
packRuntime: import('../domain-packs/pack-runtime.js').PackRuntime;
|
|
109
|
+
/** @deprecated Full agent runtime. Use packRuntime instead — only vault, projects, and session checks are guaranteed. */
|
|
110
|
+
runtime: unknown;
|
|
106
111
|
/** The plugin's own manifest */
|
|
107
112
|
manifest: PluginManifest;
|
|
108
113
|
/** The plugin's directory on disk */
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import type { AgentRuntimeConfig } from './types.js';
|
|
12
|
-
import type { OpDefinition } from '../facades/types.js';
|
|
13
12
|
|
|
14
13
|
// ─── Types ────────────────────────────────────────────────────────────
|
|
15
14
|
|
|
@@ -198,7 +197,7 @@ const ENGINE_RULES_END = '<!-- /soleri:engine-rules -->';
|
|
|
198
197
|
/**
|
|
199
198
|
* Check if engine rules are present in content.
|
|
200
199
|
*/
|
|
201
|
-
|
|
200
|
+
function hasEngineRules(content: string): boolean {
|
|
202
201
|
return content.includes(ENGINE_RULES_START) && content.includes(ENGINE_RULES_END);
|
|
203
202
|
}
|
|
204
203
|
|
|
@@ -217,20 +216,3 @@ export function injectEngineRulesBlock(content: string, engineRulesContent: stri
|
|
|
217
216
|
// Append
|
|
218
217
|
return content.trimEnd() + '\n\n' + engineRulesContent + '\n';
|
|
219
218
|
}
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Extract facade summaries from an ops array (for tools table generation).
|
|
223
|
-
*/
|
|
224
|
-
export function extractFacadeSummaries(
|
|
225
|
-
agentId: string,
|
|
226
|
-
opsMap: Map<string, OpDefinition[]>,
|
|
227
|
-
): FacadeSummary[] {
|
|
228
|
-
const summaries: FacadeSummary[] = [];
|
|
229
|
-
for (const [suffix, ops] of opsMap) {
|
|
230
|
-
summaries.push({
|
|
231
|
-
name: `${agentId}_${suffix}`,
|
|
232
|
-
ops: ops.map((o) => o.name),
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
return summaries;
|
|
236
|
-
}
|
|
@@ -58,8 +58,7 @@ export function createAdminFacadeOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
58
58
|
}),
|
|
59
59
|
handler: async (params) => {
|
|
60
60
|
return llmClient.complete({
|
|
61
|
-
|
|
62
|
-
model: (params.model as string) ?? '',
|
|
61
|
+
model: (params.model as string) || undefined,
|
|
63
62
|
systemPrompt: params.systemPrompt as string,
|
|
64
63
|
userPrompt: params.userPrompt as string,
|
|
65
64
|
temperature: params.temperature as number | undefined,
|
package/src/runtime/pack-ops.ts
CHANGED
|
@@ -8,6 +8,16 @@ import { z } from 'zod';
|
|
|
8
8
|
import type { OpDefinition } from '../facades/types.js';
|
|
9
9
|
import type { AgentRuntime } from './types.js';
|
|
10
10
|
|
|
11
|
+
export type HotRegisterTool = (toolName: string, description: string, ops: OpDefinition[]) => void;
|
|
12
|
+
|
|
13
|
+
/** Mutable slot — set after engine registration to enable hot reload. */
|
|
14
|
+
let _hotRegister: HotRegisterTool | null = null;
|
|
15
|
+
|
|
16
|
+
/** Set the hot-register callback after registerEngine() completes. */
|
|
17
|
+
export function setHotRegister(fn: HotRegisterTool): void {
|
|
18
|
+
_hotRegister = fn;
|
|
19
|
+
}
|
|
20
|
+
|
|
11
21
|
export function createPackOps(runtime: AgentRuntime): OpDefinition[] {
|
|
12
22
|
const { packInstaller } = runtime;
|
|
13
23
|
|
|
@@ -36,7 +46,22 @@ export function createPackOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
36
46
|
packDir: z.string().describe('Path to the knowledge pack directory.'),
|
|
37
47
|
}),
|
|
38
48
|
handler: async (params) => {
|
|
39
|
-
|
|
49
|
+
const result = await packInstaller.install(params.packDir as string, runtime);
|
|
50
|
+
// Hot register facades as MCP tools if callback available
|
|
51
|
+
if (_hotRegister && result.installed && result.facades > 0) {
|
|
52
|
+
const plugin = runtime.pluginRegistry.get(result.id);
|
|
53
|
+
if (plugin?.facades) {
|
|
54
|
+
for (const facade of plugin.facades) {
|
|
55
|
+
_hotRegister(
|
|
56
|
+
`${runtime.config.agentId}_${facade.name}`,
|
|
57
|
+
facade.description,
|
|
58
|
+
facade.ops,
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
(result as unknown as Record<string, unknown>).hotReloaded = true;
|
|
63
|
+
}
|
|
64
|
+
return result;
|
|
40
65
|
},
|
|
41
66
|
},
|
|
42
67
|
|
|
@@ -8,6 +8,7 @@ import { z } from 'zod';
|
|
|
8
8
|
import type { OpDefinition } from '../facades/types.js';
|
|
9
9
|
import type { AgentRuntime } from './types.js';
|
|
10
10
|
import { loadPlugins, validateDependencies, sortByDependencies } from '../plugins/index.js';
|
|
11
|
+
import { createPackRuntime } from '../domain-packs/pack-runtime.js';
|
|
11
12
|
|
|
12
13
|
export function createPluginOps(runtime: AgentRuntime, opSink?: OpDefinition[]): OpDefinition[] {
|
|
13
14
|
const { pluginRegistry, config } = runtime;
|
|
@@ -157,6 +158,7 @@ export function createPluginOps(runtime: AgentRuntime, opSink?: OpDefinition[]):
|
|
|
157
158
|
if (!plugin) return { error: `Plugin not found: ${pluginId}` };
|
|
158
159
|
|
|
159
160
|
const result = await pluginRegistry.activate(pluginId, {
|
|
161
|
+
packRuntime: createPackRuntime(runtime),
|
|
160
162
|
runtime,
|
|
161
163
|
manifest: plugin.manifest,
|
|
162
164
|
directory: plugin.directory,
|
|
@@ -179,6 +181,7 @@ export function createPluginOps(runtime: AgentRuntime, opSink?: OpDefinition[]):
|
|
|
179
181
|
const results = await Promise.all(
|
|
180
182
|
pending.map(async (plugin) => {
|
|
181
183
|
const activated = await pluginRegistry.activate(plugin.id, {
|
|
184
|
+
packRuntime: createPackRuntime(runtime),
|
|
182
185
|
runtime,
|
|
183
186
|
manifest: plugin.manifest,
|
|
184
187
|
directory: plugin.directory,
|
|
@@ -42,6 +42,20 @@ export function createSessionBriefingOps(runtime: AgentRuntime): OpDefinition[]
|
|
|
42
42
|
const sections: BriefingSection[] = [];
|
|
43
43
|
let dataPoints = 0;
|
|
44
44
|
|
|
45
|
+
// 0. Day-one welcome (vault has few non-playbook entries)
|
|
46
|
+
try {
|
|
47
|
+
const stats = vault.stats();
|
|
48
|
+
const nonPlaybook = stats.totalEntries - (stats.byType?.playbook ?? 0);
|
|
49
|
+
if (nonPlaybook < 10) {
|
|
50
|
+
sections.push({
|
|
51
|
+
label: 'Welcome',
|
|
52
|
+
content: `Vault has ${nonPlaybook} knowledge entries. Capture patterns as you work — the brain learns from every session. Use op:capture_knowledge to persist insights.`,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
} catch {
|
|
56
|
+
// Vault stats unavailable — skip
|
|
57
|
+
}
|
|
58
|
+
|
|
45
59
|
// 1. Last session
|
|
46
60
|
try {
|
|
47
61
|
const sessions = brainIntelligence.listSessions({ limit: 1, active: false });
|
|
@@ -328,13 +328,11 @@ export function createVaultLinkingOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
328
328
|
|
|
329
329
|
try {
|
|
330
330
|
const result = await llmClient.complete({
|
|
331
|
-
provider: llmClient.isAvailable().anthropic ? 'anthropic' : 'openai',
|
|
332
|
-
model: llmClient.isAvailable().anthropic ? 'claude-sonnet-4-20250514' : 'gpt-4o-mini',
|
|
333
331
|
systemPrompt: EVAL_SYSTEM_PROMPT,
|
|
334
332
|
userPrompt: pairsText,
|
|
335
333
|
maxTokens: 2000,
|
|
336
|
-
caller: '
|
|
337
|
-
task: '
|
|
334
|
+
caller: 'vault-linking',
|
|
335
|
+
task: 'evaluate-links',
|
|
338
336
|
});
|
|
339
337
|
llmCalls++;
|
|
340
338
|
|