@soleri/forge 5.9.0 → 5.10.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/lib.d.ts +1 -0
- package/dist/lib.js +1 -0
- package/dist/lib.js.map +1 -1
- package/dist/scaffolder.js +79 -239
- package/dist/scaffolder.js.map +1 -1
- package/dist/templates/entry-point.d.ts +1 -1
- package/dist/templates/entry-point.js +53 -10
- package/dist/templates/entry-point.js.map +1 -1
- package/dist/templates/extensions.d.ts +10 -0
- package/dist/templates/extensions.js +89 -0
- package/dist/templates/extensions.js.map +1 -0
- package/dist/templates/persona.js +27 -0
- package/dist/templates/persona.js.map +1 -1
- package/dist/templates/skills.d.ts +2 -0
- package/dist/templates/skills.js +10 -0
- package/dist/templates/skills.js.map +1 -1
- package/dist/templates/test-facades.js +228 -304
- package/dist/templates/test-facades.js.map +1 -1
- package/dist/types.d.ts +13 -2
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -1
- package/package.json +5 -1
- package/src/__tests__/extensions-scaffold.test.ts +63 -0
- package/src/__tests__/scaffolder.test.ts +9 -6
- package/src/lib.ts +1 -0
- package/src/scaffolder.ts +79 -240
- package/src/templates/entry-point.ts +53 -10
- package/src/templates/extensions.ts +91 -0
- package/src/templates/persona.ts +27 -0
- package/src/templates/skills.ts +11 -0
- package/src/templates/test-facades.ts +228 -304
- package/src/types.ts +8 -0
package/dist/types.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
/** Communication tone for the agent persona */
|
|
3
|
+
export const TONES = ['precise', 'mentor', 'pragmatic'];
|
|
2
4
|
/** Agent configuration — everything needed to scaffold */
|
|
3
5
|
export const AgentConfigSchema = z.object({
|
|
4
6
|
/** Agent identifier (kebab-case, used for directory and package name) */
|
|
@@ -13,11 +15,15 @@ export const AgentConfigSchema = z.object({
|
|
|
13
15
|
domains: z.array(z.string().min(1)).min(1).max(20),
|
|
14
16
|
/** Core principles the agent follows (3-7 recommended) */
|
|
15
17
|
principles: z.array(z.string()).min(1).max(10),
|
|
18
|
+
/** Communication tone: precise, mentor, or pragmatic */
|
|
19
|
+
tone: z.enum(TONES).optional().default('pragmatic'),
|
|
16
20
|
/** Greeting message when agent introduces itself (auto-generated if omitted) */
|
|
17
21
|
greeting: z.string().min(10).max(300).optional(),
|
|
18
22
|
/** Output directory (parent — agent dir will be created inside, defaults to cwd) */
|
|
19
23
|
outputDir: z.string().min(1).optional().default(process.cwd()),
|
|
20
24
|
/** Hook packs to install after scaffolding (optional) */
|
|
21
25
|
hookPacks: z.array(z.string()).optional(),
|
|
26
|
+
/** Skills to include (if omitted, all skills are included for backward compat) */
|
|
27
|
+
skills: z.array(z.string()).optional(),
|
|
22
28
|
});
|
|
23
29
|
//# sourceMappingURL=types.js.map
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,0DAA0D;AAC1D,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,yEAAyE;IACzE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,mBAAmB,EAAE,gDAAgD,CAAC;IAC3F,kCAAkC;IAClC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;IAC/B,gCAAgC;IAChC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IAChC,iDAAiD;IACjD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IACxC,0CAA0C;IAC1C,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;IAClD,0DAA0D;IAC1D,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;IAC9C,gFAAgF;IAChF,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IAChD,oFAAoF;IACpF,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;IAC9D,yDAAyD;IACzD,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,+CAA+C;AAC/C,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,SAAS,EAAE,QAAQ,EAAE,WAAW,CAAU,CAAC;AAGjE,0DAA0D;AAC1D,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,yEAAyE;IACzE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,mBAAmB,EAAE,gDAAgD,CAAC;IAC3F,kCAAkC;IAClC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;IAC/B,gCAAgC;IAChC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IAChC,iDAAiD;IACjD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IACxC,0CAA0C;IAC1C,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;IAClD,0DAA0D;IAC1D,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;IAC9C,wDAAwD;IACxD,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC;IACnD,gFAAgF;IAChF,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IAChD,oFAAoF;IACpF,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;IAC9D,yDAAyD;IACzD,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACzC,kFAAkF;IAClF,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CACvC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soleri/forge",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.10.0",
|
|
4
4
|
"description": "Scaffold AI agents that learn, remember, and grow with you.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -31,6 +31,10 @@
|
|
|
31
31
|
"./lib": {
|
|
32
32
|
"types": "./dist/lib.d.ts",
|
|
33
33
|
"import": "./dist/lib.js"
|
|
34
|
+
},
|
|
35
|
+
"./templates/extensions": {
|
|
36
|
+
"types": "./dist/templates/extensions.d.ts",
|
|
37
|
+
"import": "./dist/templates/extensions.js"
|
|
34
38
|
}
|
|
35
39
|
},
|
|
36
40
|
"publishConfig": {
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { describe, it, expect, afterEach } from 'vitest';
|
|
2
|
+
import { scaffold, previewScaffold } from '../scaffolder.js';
|
|
3
|
+
import { existsSync, readFileSync, rmSync } from 'node:fs';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { tmpdir } from 'node:os';
|
|
6
|
+
|
|
7
|
+
describe('scaffold extensions', () => {
|
|
8
|
+
const outputDir = join(tmpdir(), 'soleri-ext-test-' + Date.now());
|
|
9
|
+
const agentId = 'ext-test-agent';
|
|
10
|
+
const agentDir = join(outputDir, agentId);
|
|
11
|
+
|
|
12
|
+
afterEach(() => {
|
|
13
|
+
rmSync(outputDir, { recursive: true, force: true });
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('should create extensions directory with index and example op', () => {
|
|
17
|
+
scaffold({
|
|
18
|
+
id: agentId,
|
|
19
|
+
name: 'Extension Test',
|
|
20
|
+
role: 'Test agent',
|
|
21
|
+
description: 'Agent for testing extensions scaffold',
|
|
22
|
+
domains: ['testing'],
|
|
23
|
+
principles: ['Test everything'],
|
|
24
|
+
tone: 'pragmatic',
|
|
25
|
+
outputDir,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Extensions directory exists
|
|
29
|
+
expect(existsSync(join(agentDir, 'src', 'extensions', 'index.ts'))).toBe(true);
|
|
30
|
+
expect(existsSync(join(agentDir, 'src', 'extensions', 'ops', 'example.ts'))).toBe(true);
|
|
31
|
+
expect(existsSync(join(agentDir, 'src', 'extensions', 'facades'))).toBe(true);
|
|
32
|
+
expect(existsSync(join(agentDir, 'src', 'extensions', 'middleware'))).toBe(true);
|
|
33
|
+
|
|
34
|
+
// Extensions index references the agent ID
|
|
35
|
+
const indexContent = readFileSync(join(agentDir, 'src', 'extensions', 'index.ts'), 'utf-8');
|
|
36
|
+
expect(indexContent).toContain('ext-test-agent_core');
|
|
37
|
+
expect(indexContent).toContain('loadExtensions');
|
|
38
|
+
expect(indexContent).toContain('AgentExtensions');
|
|
39
|
+
|
|
40
|
+
// Entry point imports extensions
|
|
41
|
+
const entryPoint = readFileSync(join(agentDir, 'src', 'index.ts'), 'utf-8');
|
|
42
|
+
expect(entryPoint).toContain('wrapWithMiddleware');
|
|
43
|
+
expect(entryPoint).toContain('./extensions/index.js');
|
|
44
|
+
expect(entryPoint).toContain('AgentExtensions');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should include extensions in preview', () => {
|
|
48
|
+
const preview = previewScaffold({
|
|
49
|
+
id: agentId,
|
|
50
|
+
name: 'Extension Test',
|
|
51
|
+
role: 'Test agent',
|
|
52
|
+
description: 'Agent for testing extensions scaffold',
|
|
53
|
+
domains: ['testing'],
|
|
54
|
+
principles: ['Test everything'],
|
|
55
|
+
tone: 'pragmatic',
|
|
56
|
+
outputDir,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const extFile = preview.files.find((f) => f.path === 'src/extensions/');
|
|
60
|
+
expect(extFile).toBeDefined();
|
|
61
|
+
expect(extFile!.description).toContain('extension');
|
|
62
|
+
});
|
|
63
|
+
});
|
|
@@ -56,15 +56,18 @@ describe('Scaffolder', () => {
|
|
|
56
56
|
expect(paths).not.toContain('src/facades/data-pipelines.facade.ts');
|
|
57
57
|
|
|
58
58
|
// Should have domain facades + core facade in preview
|
|
59
|
-
expect(preview.facades).toHaveLength(
|
|
59
|
+
expect(preview.facades).toHaveLength(14); // 3 domains + 10 semantic + 1 agent core
|
|
60
60
|
expect(preview.facades[0].name).toBe('atlas_data_pipelines');
|
|
61
61
|
|
|
62
|
-
//
|
|
62
|
+
// Agent-specific facade has 5 ops
|
|
63
63
|
const coreFacade = preview.facades.find((f) => f.name === 'atlas_core')!;
|
|
64
|
-
expect(coreFacade.ops.length).toBe(
|
|
65
|
-
expect(coreFacade.ops).toContain('curator_status');
|
|
64
|
+
expect(coreFacade.ops.length).toBe(5);
|
|
66
65
|
expect(coreFacade.ops).toContain('health');
|
|
67
66
|
|
|
67
|
+
// Semantic facades cover the rest
|
|
68
|
+
const vaultFacade = preview.facades.find((f) => f.name === 'atlas_vault')!;
|
|
69
|
+
expect(vaultFacade).toBeDefined();
|
|
70
|
+
|
|
68
71
|
// Should NOT create any files
|
|
69
72
|
expect(existsSync(join(tempDir, 'atlas'))).toBe(false);
|
|
70
73
|
});
|
|
@@ -138,7 +141,7 @@ describe('Scaffolder', () => {
|
|
|
138
141
|
|
|
139
142
|
// v5.0 runtime factory pattern
|
|
140
143
|
expect(entry).toContain('createAgentRuntime');
|
|
141
|
-
expect(entry).toContain('
|
|
144
|
+
expect(entry).toContain('createSemanticFacades');
|
|
142
145
|
expect(entry).toContain('createDomainFacades');
|
|
143
146
|
expect(entry).toContain("from '@soleri/core'");
|
|
144
147
|
expect(entry).toContain("agentId: 'atlas'");
|
|
@@ -221,7 +224,7 @@ describe('Scaffolder', () => {
|
|
|
221
224
|
|
|
222
225
|
// Should use runtime factories from @soleri/core
|
|
223
226
|
expect(facadesTest).toContain('createAgentRuntime');
|
|
224
|
-
expect(facadesTest).toContain('
|
|
227
|
+
expect(facadesTest).toContain('createSemanticFacades');
|
|
225
228
|
expect(facadesTest).toContain('createDomainFacade');
|
|
226
229
|
expect(facadesTest).toContain("from '@soleri/core'");
|
|
227
230
|
|
package/src/lib.ts
CHANGED
package/src/scaffolder.ts
CHANGED
|
@@ -23,6 +23,7 @@ import { generateActivate } from './templates/activate.js';
|
|
|
23
23
|
import { generateReadme } from './templates/readme.js';
|
|
24
24
|
import { generateSetupScript } from './templates/setup-script.js';
|
|
25
25
|
import { generateSkills } from './templates/skills.js';
|
|
26
|
+
import { generateExtensionsIndex, generateExampleOp } from './templates/extensions.js';
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
29
|
* Preview what scaffold will create without writing anything.
|
|
@@ -42,7 +43,7 @@ export function previewScaffold(config: AgentConfig): ScaffoldPreview {
|
|
|
42
43
|
{
|
|
43
44
|
path: 'src/index.ts',
|
|
44
45
|
description:
|
|
45
|
-
'Entry point — thin shell using createAgentRuntime() +
|
|
46
|
+
'Entry point — thin shell using createAgentRuntime() + createSemanticFacades() from @soleri/core',
|
|
46
47
|
},
|
|
47
48
|
...config.domains.map((d) => ({
|
|
48
49
|
path: `src/intelligence/data/${d}.json`,
|
|
@@ -68,6 +69,10 @@ export function previewScaffold(config: AgentConfig): ScaffoldPreview {
|
|
|
68
69
|
path: 'src/__tests__/facades.test.ts',
|
|
69
70
|
description: `Facade integration tests — all ${config.domains.length + 1} facades`,
|
|
70
71
|
},
|
|
72
|
+
{
|
|
73
|
+
path: 'src/extensions/',
|
|
74
|
+
description: 'User extension directory — custom ops, facades, middleware, hooks',
|
|
75
|
+
},
|
|
71
76
|
{ path: '.mcp.json', description: 'MCP client config for connecting to this agent' },
|
|
72
77
|
{
|
|
73
78
|
path: 'README.md',
|
|
@@ -79,8 +84,9 @@ export function previewScaffold(config: AgentConfig): ScaffoldPreview {
|
|
|
79
84
|
},
|
|
80
85
|
{
|
|
81
86
|
path: 'skills/',
|
|
82
|
-
description:
|
|
83
|
-
|
|
87
|
+
description: config.skills?.length
|
|
88
|
+
? `${config.skills.length} selected skills`
|
|
89
|
+
: '17 built-in skills — TDD, debugging, planning, vault, brain, code patrol, retrospective, onboarding',
|
|
84
90
|
},
|
|
85
91
|
];
|
|
86
92
|
|
|
@@ -96,263 +102,90 @@ export function previewScaffold(config: AgentConfig): ScaffoldPreview {
|
|
|
96
102
|
name: `${config.id}_${d.replace(/-/g, '_')}`,
|
|
97
103
|
ops: ['get_patterns', 'search', 'get_entry', 'capture', 'remove'],
|
|
98
104
|
})),
|
|
105
|
+
// 10 semantic facades from createSemanticFacades()
|
|
99
106
|
{
|
|
100
|
-
name: `${config.id}
|
|
107
|
+
name: `${config.id}_vault`,
|
|
101
108
|
ops: [
|
|
102
|
-
// From createCoreOps() — 150 generic ops
|
|
103
109
|
'search',
|
|
104
110
|
'vault_stats',
|
|
105
111
|
'list_all',
|
|
106
|
-
'register',
|
|
107
|
-
'memory_search',
|
|
108
|
-
'memory_capture',
|
|
109
|
-
'memory_list',
|
|
110
|
-
'session_capture',
|
|
111
112
|
'export',
|
|
113
|
+
'capture_enriched',
|
|
114
|
+
'...vault-extra',
|
|
115
|
+
'...capture',
|
|
116
|
+
'...intake',
|
|
117
|
+
],
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: `${config.id}_plan`,
|
|
121
|
+
ops: [
|
|
112
122
|
'create_plan',
|
|
113
123
|
'get_plan',
|
|
114
124
|
'approve_plan',
|
|
115
125
|
'update_task',
|
|
116
126
|
'complete_plan',
|
|
127
|
+
'...planning-extra',
|
|
128
|
+
'...grading',
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
name: `${config.id}_brain`,
|
|
133
|
+
ops: [
|
|
117
134
|
'record_feedback',
|
|
118
135
|
'brain_feedback',
|
|
119
|
-
'brain_feedback_stats',
|
|
120
|
-
'rebuild_vocabulary',
|
|
121
136
|
'brain_stats',
|
|
122
137
|
'llm_status',
|
|
123
|
-
'brain_session_context',
|
|
124
138
|
'brain_strengths',
|
|
125
|
-
'
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
'
|
|
132
|
-
'
|
|
133
|
-
'
|
|
134
|
-
'
|
|
135
|
-
|
|
136
|
-
'
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
'cognee_config',
|
|
143
|
-
// LLM ops — 2
|
|
139
|
+
'...19 brain ops',
|
|
140
|
+
],
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: `${config.id}_memory`,
|
|
144
|
+
ops: [
|
|
145
|
+
'memory_search',
|
|
146
|
+
'memory_capture',
|
|
147
|
+
'memory_list',
|
|
148
|
+
'session_capture',
|
|
149
|
+
'...memory-extra',
|
|
150
|
+
'...cross-project',
|
|
151
|
+
],
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: `${config.id}_admin`,
|
|
155
|
+
ops: [
|
|
144
156
|
'llm_rotate',
|
|
145
157
|
'llm_call',
|
|
146
|
-
// Prompt ops — 2
|
|
147
158
|
'render_prompt',
|
|
148
159
|
'list_templates',
|
|
149
|
-
'
|
|
150
|
-
'
|
|
151
|
-
'curator_contradictions',
|
|
152
|
-
'curator_resolve_contradiction',
|
|
153
|
-
'curator_groom',
|
|
154
|
-
'curator_groom_all',
|
|
155
|
-
'curator_consolidate',
|
|
156
|
-
'curator_health_audit',
|
|
157
|
-
'get_identity',
|
|
158
|
-
'update_identity',
|
|
159
|
-
'add_guideline',
|
|
160
|
-
'remove_guideline',
|
|
161
|
-
'rollback_identity',
|
|
162
|
-
'route_intent',
|
|
163
|
-
'morph',
|
|
164
|
-
'get_behavior_rules',
|
|
165
|
-
// Governance ops — 5
|
|
166
|
-
'governance_policy',
|
|
167
|
-
'governance_proposals',
|
|
168
|
-
'governance_stats',
|
|
169
|
-
'governance_expire',
|
|
170
|
-
'governance_dashboard',
|
|
171
|
-
// Planning Extra ops — 22
|
|
172
|
-
'plan_iterate',
|
|
173
|
-
'plan_split',
|
|
174
|
-
'plan_reconcile',
|
|
175
|
-
'plan_complete_lifecycle',
|
|
176
|
-
'plan_dispatch',
|
|
177
|
-
'plan_review',
|
|
178
|
-
'plan_archive',
|
|
179
|
-
'plan_list_tasks',
|
|
180
|
-
'plan_stats',
|
|
181
|
-
// Planning evidence (#148)
|
|
182
|
-
'plan_submit_evidence',
|
|
183
|
-
'plan_verify_task',
|
|
184
|
-
'plan_verify_plan',
|
|
185
|
-
// Subagent dispatch (#149)
|
|
186
|
-
'plan_review_spec',
|
|
187
|
-
'plan_review_quality',
|
|
188
|
-
'plan_review_outcome',
|
|
189
|
-
// Brainstorm (#150)
|
|
190
|
-
'plan_brainstorm',
|
|
191
|
-
// Auto-reconcile (#151)
|
|
192
|
-
'plan_auto_reconcile',
|
|
193
|
-
// Validate plan (#152)
|
|
194
|
-
'plan_validate',
|
|
195
|
-
// Execution metrics + deliverables (#80, #83)
|
|
196
|
-
'plan_execution_metrics',
|
|
197
|
-
'plan_record_task_metrics',
|
|
198
|
-
'plan_submit_deliverable',
|
|
199
|
-
'plan_verify_deliverables',
|
|
200
|
-
// Memory Extra ops — 8
|
|
201
|
-
'memory_delete',
|
|
202
|
-
'memory_stats',
|
|
203
|
-
'memory_export',
|
|
204
|
-
'memory_import',
|
|
205
|
-
'memory_prune',
|
|
206
|
-
'memory_deduplicate',
|
|
207
|
-
'memory_topics',
|
|
208
|
-
'memory_by_project',
|
|
209
|
-
// Vault Extra ops — 12
|
|
210
|
-
'vault_get',
|
|
211
|
-
'vault_update',
|
|
212
|
-
'vault_remove',
|
|
213
|
-
'vault_bulk_add',
|
|
214
|
-
'vault_bulk_remove',
|
|
215
|
-
'vault_tags',
|
|
216
|
-
'vault_domains',
|
|
217
|
-
'vault_recent',
|
|
218
|
-
'vault_import',
|
|
219
|
-
'vault_seed',
|
|
220
|
-
'vault_backup',
|
|
221
|
-
'vault_age_report',
|
|
222
|
-
// Vault extra — seed canonical + knowledge lifecycle (5)
|
|
223
|
-
'vault_seed_canonical',
|
|
224
|
-
'knowledge_audit',
|
|
225
|
-
'knowledge_health',
|
|
226
|
-
'knowledge_merge',
|
|
227
|
-
'knowledge_reorganize',
|
|
228
|
-
// Bi-temporal vault ops (#89) — 3
|
|
229
|
-
'vault_set_temporal',
|
|
230
|
-
'vault_find_expiring',
|
|
231
|
-
'vault_find_expired',
|
|
232
|
-
// Vault archival (#86) — 3
|
|
233
|
-
'vault_archive',
|
|
234
|
-
'vault_restore',
|
|
235
|
-
'vault_optimize',
|
|
236
|
-
// Admin ops — 8
|
|
237
|
-
'admin_health',
|
|
238
|
-
'admin_tool_list',
|
|
239
|
-
'admin_config',
|
|
240
|
-
'admin_vault_size',
|
|
241
|
-
'admin_uptime',
|
|
242
|
-
'admin_version',
|
|
243
|
-
'admin_reset_cache',
|
|
244
|
-
'admin_diagnostic',
|
|
245
|
-
// Loop ops — 9
|
|
246
|
-
'loop_start',
|
|
247
|
-
'loop_iterate',
|
|
248
|
-
'loop_iterate_gate',
|
|
249
|
-
'loop_status',
|
|
250
|
-
'loop_cancel',
|
|
251
|
-
'loop_history',
|
|
252
|
-
'loop_is_active',
|
|
253
|
-
'loop_complete',
|
|
254
|
-
'loop_anomaly_check',
|
|
255
|
-
// Orchestrate ops — 5
|
|
256
|
-
'orchestrate_plan',
|
|
257
|
-
'orchestrate_execute',
|
|
258
|
-
'orchestrate_complete',
|
|
259
|
-
'orchestrate_status',
|
|
260
|
-
'orchestrate_quick_capture',
|
|
261
|
-
// Grading ops — 5
|
|
262
|
-
'plan_grade',
|
|
263
|
-
'plan_check_history',
|
|
264
|
-
'plan_latest_check',
|
|
265
|
-
'plan_meets_grade',
|
|
266
|
-
'plan_auto_improve',
|
|
267
|
-
// Capture ops — 4
|
|
268
|
-
'capture_knowledge',
|
|
269
|
-
'capture_quick',
|
|
270
|
-
'search_intelligent',
|
|
271
|
-
'search_feedback',
|
|
272
|
-
// Enriched capture (#154) — 1
|
|
273
|
-
'capture_enriched',
|
|
274
|
-
// Cognee graph (#156) — 3
|
|
275
|
-
'cognee_get_node',
|
|
276
|
-
'cognee_graph_stats',
|
|
277
|
-
'cognee_export_status',
|
|
278
|
-
// Cognee Sync ops — 3
|
|
279
|
-
'cognee_sync_status',
|
|
280
|
-
'cognee_sync_drain',
|
|
281
|
-
'cognee_sync_reconcile',
|
|
282
|
-
// Intake ops — 4
|
|
283
|
-
'intake_ingest_book',
|
|
284
|
-
'intake_process',
|
|
285
|
-
'intake_status',
|
|
286
|
-
'intake_preview',
|
|
287
|
-
// Admin Extra ops — 23
|
|
288
|
-
'admin_telemetry',
|
|
289
|
-
'admin_telemetry_recent',
|
|
290
|
-
'admin_telemetry_reset',
|
|
291
|
-
'admin_permissions',
|
|
292
|
-
'admin_vault_analytics',
|
|
293
|
-
'admin_search_insights',
|
|
294
|
-
'admin_module_status',
|
|
295
|
-
'admin_env',
|
|
296
|
-
'admin_gc',
|
|
297
|
-
'admin_export_config',
|
|
298
|
-
// Admin key pool (#157)
|
|
299
|
-
'admin_key_pool_status',
|
|
300
|
-
'admin_create_token',
|
|
301
|
-
'admin_revoke_token',
|
|
302
|
-
'admin_list_tokens',
|
|
303
|
-
// Admin accounts (#158)
|
|
304
|
-
'admin_add_account',
|
|
305
|
-
'admin_remove_account',
|
|
306
|
-
'admin_rotate_account',
|
|
307
|
-
'admin_list_accounts',
|
|
308
|
-
'admin_account_status',
|
|
309
|
-
// Admin plugins (#159)
|
|
310
|
-
'admin_list_plugins',
|
|
311
|
-
'admin_plugin_status',
|
|
312
|
-
// Admin instruction validation (#160)
|
|
313
|
-
'admin_validate_instructions',
|
|
314
|
-
// Hot reload (#63)
|
|
315
|
-
'admin_hot_reload',
|
|
316
|
-
// Admin persistence (#85) — 1
|
|
317
|
-
'admin_persistence_info',
|
|
318
|
-
// Curator Extra ops — 5
|
|
319
|
-
'curator_entry_history',
|
|
320
|
-
'curator_record_snapshot',
|
|
321
|
-
'curator_queue_stats',
|
|
322
|
-
'curator_enrich',
|
|
323
|
-
// Hybrid contradiction detection (#36) — 1
|
|
324
|
-
'curator_hybrid_contradictions',
|
|
325
|
-
// Project ops — 12
|
|
326
|
-
'project_get',
|
|
327
|
-
'project_list',
|
|
328
|
-
'project_unregister',
|
|
329
|
-
'project_get_rules',
|
|
330
|
-
'project_list_rules',
|
|
331
|
-
'project_add_rule',
|
|
332
|
-
'project_remove_rule',
|
|
333
|
-
'project_link',
|
|
334
|
-
'project_unlink',
|
|
335
|
-
'project_get_links',
|
|
336
|
-
'project_linked_projects',
|
|
337
|
-
'project_touch',
|
|
338
|
-
// Cross-project memory ops — 3
|
|
339
|
-
'memory_promote_to_global',
|
|
340
|
-
'memory_configure',
|
|
341
|
-
'memory_cross_project_search',
|
|
342
|
-
// Playbook ops — 5
|
|
343
|
-
'playbook_list',
|
|
344
|
-
'playbook_get',
|
|
345
|
-
'playbook_create',
|
|
346
|
-
'playbook_match',
|
|
347
|
-
'playbook_seed',
|
|
348
|
-
// Agent-specific ops — 5
|
|
349
|
-
'health',
|
|
350
|
-
'identity',
|
|
351
|
-
'activate',
|
|
352
|
-
'inject_claude_md',
|
|
353
|
-
'setup',
|
|
160
|
+
'...admin',
|
|
161
|
+
'...admin-extra',
|
|
354
162
|
],
|
|
355
163
|
},
|
|
164
|
+
{
|
|
165
|
+
name: `${config.id}_curator`,
|
|
166
|
+
ops: ['curator_status', 'curator_health_audit', '...8 curator ops', '...curator-extra'],
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: `${config.id}_loop`,
|
|
170
|
+
ops: ['loop_start', 'loop_iterate', 'loop_cancel', '...loop ops'],
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
name: `${config.id}_orchestrate`,
|
|
174
|
+
ops: ['register', '...orchestrate', '...project', '...playbook'],
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
name: `${config.id}_control`,
|
|
178
|
+
ops: ['get_identity', 'route_intent', 'governance_policy', '...control+governance ops'],
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
name: `${config.id}_cognee`,
|
|
182
|
+
ops: ['cognee_status', 'cognee_search', '...cognee ops', '...cognee-sync'],
|
|
183
|
+
},
|
|
184
|
+
// Agent-specific facade
|
|
185
|
+
{
|
|
186
|
+
name: `${config.id}_core`,
|
|
187
|
+
ops: ['health', 'identity', 'activate', 'inject_claude_md', 'setup'],
|
|
188
|
+
},
|
|
356
189
|
];
|
|
357
190
|
|
|
358
191
|
return {
|
|
@@ -399,6 +232,10 @@ export function scaffold(config: AgentConfig): ScaffoldResult {
|
|
|
399
232
|
'src/identity',
|
|
400
233
|
'src/activation',
|
|
401
234
|
'src/__tests__',
|
|
235
|
+
'src/extensions',
|
|
236
|
+
'src/extensions/ops',
|
|
237
|
+
'src/extensions/facades',
|
|
238
|
+
'src/extensions/middleware',
|
|
402
239
|
];
|
|
403
240
|
|
|
404
241
|
if (config.hookPacks?.length) {
|
|
@@ -444,6 +281,8 @@ export function scaffold(config: AgentConfig): ScaffoldResult {
|
|
|
444
281
|
['src/activation/activate.ts', generateActivate(config)],
|
|
445
282
|
['src/index.ts', generateEntryPoint(config)],
|
|
446
283
|
['src/__tests__/facades.test.ts', generateFacadesTest(config)],
|
|
284
|
+
['src/extensions/index.ts', generateExtensionsIndex(config)],
|
|
285
|
+
['src/extensions/ops/example.ts', generateExampleOp(config)],
|
|
447
286
|
];
|
|
448
287
|
|
|
449
288
|
// Empty intelligence data bundles (domain facades come from @soleri/core at runtime)
|
|
@@ -465,7 +304,7 @@ export function scaffold(config: AgentConfig): ScaffoldResult {
|
|
|
465
304
|
filesCreated.push(path);
|
|
466
305
|
}
|
|
467
306
|
|
|
468
|
-
const totalOps = config.domains.length * 5 +
|
|
307
|
+
const totalOps = config.domains.length * 5 + 214; // 5 per domain + 209 semantic + 5 agent-specific
|
|
469
308
|
|
|
470
309
|
// Auto-build: install dependencies and compile before registering MCP
|
|
471
310
|
let buildSuccess = false;
|
|
@@ -500,7 +339,7 @@ export function scaffold(config: AgentConfig): ScaffoldResult {
|
|
|
500
339
|
|
|
501
340
|
const summaryLines = [
|
|
502
341
|
`Created ${config.name} agent at ${agentDir}`,
|
|
503
|
-
`${config.domains.length +
|
|
342
|
+
`${config.domains.length + 11} facades with ${totalOps} operations`,
|
|
504
343
|
`${config.domains.length} empty knowledge domains ready for capture`,
|
|
505
344
|
`Intelligence layer (Brain) — TF-IDF scoring, auto-tagging, duplicate detection`,
|
|
506
345
|
`Activation system included — say "Hello, ${config.name}!" to activate`,
|
|
@@ -3,7 +3,7 @@ import type { AgentConfig } from '../types.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* Generate the main index.ts entry point for the agent.
|
|
5
5
|
*
|
|
6
|
-
* v5.0: Thin shell — delegates to createAgentRuntime(),
|
|
6
|
+
* v5.0: Thin shell — delegates to createAgentRuntime(), createSemanticFacades(),
|
|
7
7
|
* and createDomainFacades() from @soleri/core. Only agent-specific code
|
|
8
8
|
* (persona, activation) lives here.
|
|
9
9
|
*/
|
|
@@ -19,12 +19,13 @@ import { fileURLToPath } from 'node:url';
|
|
|
19
19
|
|
|
20
20
|
import {
|
|
21
21
|
createAgentRuntime,
|
|
22
|
-
|
|
22
|
+
createSemanticFacades,
|
|
23
23
|
createDomainFacades,
|
|
24
24
|
registerAllFacades,
|
|
25
25
|
seedDefaultPlaybooks,
|
|
26
|
+
wrapWithMiddleware,
|
|
26
27
|
} from '@soleri/core';
|
|
27
|
-
import type { OpDefinition } from '@soleri/core';
|
|
28
|
+
import type { OpDefinition, AgentExtensions } from '@soleri/core';
|
|
28
29
|
import { z } from 'zod';
|
|
29
30
|
import { PERSONA, getPersonaPrompt } from './identity/persona.js';
|
|
30
31
|
import { activateAgent, deactivateAgent } from './activation/activate.js';
|
|
@@ -201,15 +202,51 @@ async function main(): Promise<void> {
|
|
|
201
202
|
];
|
|
202
203
|
|
|
203
204
|
// ─── Assemble facades ──────────────────────────────────────────
|
|
204
|
-
const
|
|
205
|
-
const
|
|
205
|
+
const semanticFacades = createSemanticFacades(runtime, '${config.id}');
|
|
206
|
+
const agentFacade = {
|
|
206
207
|
name: '${config.id}_core',
|
|
207
|
-
description: '
|
|
208
|
-
ops:
|
|
208
|
+
description: 'Agent-specific operations — health, identity, activation, CLAUDE.md injection, setup.',
|
|
209
|
+
ops: agentOps,
|
|
209
210
|
};
|
|
210
211
|
|
|
211
212
|
const domainFacades = createDomainFacades(runtime, '${config.id}', ${domainsLiteral});
|
|
212
213
|
|
|
214
|
+
// ─── User extensions (auto-discovered from src/extensions/) ────
|
|
215
|
+
let extensions: AgentExtensions = {};
|
|
216
|
+
try {
|
|
217
|
+
const ext = await import('./extensions/index.js');
|
|
218
|
+
const loader = ext.default ?? (ext as Record<string, unknown>).loadExtensions;
|
|
219
|
+
if (typeof loader === 'function') {
|
|
220
|
+
extensions = loader(runtime);
|
|
221
|
+
} else if (typeof loader === 'object') {
|
|
222
|
+
extensions = loader;
|
|
223
|
+
}
|
|
224
|
+
if (extensions.ops?.length || extensions.facades?.length || extensions.middleware?.length) {
|
|
225
|
+
console.error(\`[\${tag}] Extensions loaded: \${extensions.ops?.length ?? 0} ops, \${extensions.facades?.length ?? 0} facades, \${extensions.middleware?.length ?? 0} middleware\`);
|
|
226
|
+
}
|
|
227
|
+
} catch {
|
|
228
|
+
// No extensions directory or load error — run vanilla
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Merge user ops into agent facade
|
|
232
|
+
if (extensions.ops?.length) {
|
|
233
|
+
agentFacade.ops.push(...extensions.ops);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Collect user facades
|
|
237
|
+
const userFacades = extensions.facades ?? [];
|
|
238
|
+
|
|
239
|
+
// Apply middleware to all facades
|
|
240
|
+
const allFacades = [...semanticFacades, agentFacade, ...domainFacades, ...userFacades];
|
|
241
|
+
if (extensions.middleware?.length) {
|
|
242
|
+
wrapWithMiddleware(allFacades, extensions.middleware);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Lifecycle: onStartup
|
|
246
|
+
if (extensions.hooks?.onStartup) {
|
|
247
|
+
await extensions.hooks.onStartup(runtime);
|
|
248
|
+
}
|
|
249
|
+
|
|
213
250
|
// ─── MCP server ────────────────────────────────────────────────
|
|
214
251
|
const server = new McpServer({
|
|
215
252
|
name: '${config.id}-mcp',
|
|
@@ -220,11 +257,10 @@ async function main(): Promise<void> {
|
|
|
220
257
|
messages: [{ role: 'assistant' as const, content: { type: 'text' as const, text: getPersonaPrompt() } }],
|
|
221
258
|
}));
|
|
222
259
|
|
|
223
|
-
|
|
224
|
-
registerAllFacades(server, facades);
|
|
260
|
+
registerAllFacades(server, allFacades);
|
|
225
261
|
|
|
226
262
|
console.error(\`[\${tag}] \${PERSONA.name} — \${PERSONA.role}\`);
|
|
227
|
-
console.error(\`[\${tag}] Registered \${
|
|
263
|
+
console.error(\`[\${tag}] Registered \${allFacades.length} facades with \${allFacades.reduce((sum, f) => sum + f.ops.length, 0)} operations\`);
|
|
228
264
|
|
|
229
265
|
// ─── Transport + shutdown ──────────────────────────────────────
|
|
230
266
|
const transport = new StdioServerTransport();
|
|
@@ -234,6 +270,13 @@ async function main(): Promise<void> {
|
|
|
234
270
|
|
|
235
271
|
const shutdown = async (): Promise<void> => {
|
|
236
272
|
console.error(\`[\${tag}] Shutting down...\`);
|
|
273
|
+
if (extensions.hooks?.onShutdown) {
|
|
274
|
+
try {
|
|
275
|
+
await extensions.hooks.onShutdown(runtime);
|
|
276
|
+
} catch (err) {
|
|
277
|
+
console.error(\`[\${tag}] Extension shutdown error:\`, err);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
237
280
|
runtime.close();
|
|
238
281
|
process.exit(0);
|
|
239
282
|
};
|