@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
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate the extensions manifest (src/extensions/index.ts).
|
|
3
|
+
* This is the user's entry point for customization.
|
|
4
|
+
*/
|
|
5
|
+
export function generateExtensionsIndex(config) {
|
|
6
|
+
return `/**
|
|
7
|
+
* ${config.name} — Custom Extensions
|
|
8
|
+
*
|
|
9
|
+
* Add your custom ops, facades, middleware, and lifecycle hooks here.
|
|
10
|
+
* This file is auto-discovered by the agent entry point at startup.
|
|
11
|
+
*
|
|
12
|
+
* Core ops from @soleri/core are never modified — your extensions are
|
|
13
|
+
* additive (new ops, new facades) or decorative (middleware).
|
|
14
|
+
*
|
|
15
|
+
* See: https://soleri.dev/docs/extending
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { AgentExtensions, AgentRuntime } from '@soleri/core';
|
|
19
|
+
|
|
20
|
+
// Import your custom ops, facades, and middleware here:
|
|
21
|
+
// import { myCustomOp } from './ops/my-custom-op.js';
|
|
22
|
+
// import { myFacade } from './facades/my-facade.js';
|
|
23
|
+
// import { auditLogger } from './middleware/audit-logger.js';
|
|
24
|
+
|
|
25
|
+
export default function loadExtensions(runtime: AgentRuntime): AgentExtensions {
|
|
26
|
+
return {
|
|
27
|
+
// ── Custom ops (merged into ${config.id}_core facade) ──────────
|
|
28
|
+
// ops: [
|
|
29
|
+
// myCustomOp(runtime),
|
|
30
|
+
// ],
|
|
31
|
+
|
|
32
|
+
// ── Custom facades (registered as separate MCP tools) ──────────
|
|
33
|
+
// facades: [
|
|
34
|
+
// myFacade(runtime),
|
|
35
|
+
// ],
|
|
36
|
+
|
|
37
|
+
// ── Middleware (wraps ALL ops across ALL facades) ───────────────
|
|
38
|
+
// middleware: [
|
|
39
|
+
// auditLogger,
|
|
40
|
+
// ],
|
|
41
|
+
|
|
42
|
+
// ── Lifecycle hooks ────────────────────────────────────────────
|
|
43
|
+
// hooks: {
|
|
44
|
+
// onStartup: async (rt) => {
|
|
45
|
+
// console.error('[${config.id}] Custom startup logic');
|
|
46
|
+
// },
|
|
47
|
+
// onShutdown: async (rt) => {
|
|
48
|
+
// console.error('[${config.id}] Custom shutdown logic');
|
|
49
|
+
// },
|
|
50
|
+
// },
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
`;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Generate an example custom op file.
|
|
57
|
+
*/
|
|
58
|
+
export function generateExampleOp(config) {
|
|
59
|
+
return `/**
|
|
60
|
+
* Example custom op — add your own logic here.
|
|
61
|
+
*
|
|
62
|
+
* Custom ops are merged into the ${config.id}_core facade alongside
|
|
63
|
+
* the built-in ops from @soleri/core. They have full access
|
|
64
|
+
* to the agent runtime (vault, brain, planner, etc.).
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
import { z } from 'zod';
|
|
68
|
+
import type { OpDefinition, AgentRuntime } from '@soleri/core';
|
|
69
|
+
|
|
70
|
+
export function createExampleOp(runtime: AgentRuntime): OpDefinition {
|
|
71
|
+
return {
|
|
72
|
+
name: 'example',
|
|
73
|
+
description: 'Example custom op — replace with your own logic.',
|
|
74
|
+
auth: 'read',
|
|
75
|
+
schema: z.object({
|
|
76
|
+
message: z.string().optional().describe('Optional message'),
|
|
77
|
+
}),
|
|
78
|
+
handler: async (params) => {
|
|
79
|
+
const stats = runtime.vault.stats();
|
|
80
|
+
return {
|
|
81
|
+
message: params.message ?? 'Hello from custom extension!',
|
|
82
|
+
vaultEntries: stats.totalEntries,
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
`;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=extensions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extensions.js","sourceRoot":"","sources":["../../src/templates/extensions.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAmB;IACzD,OAAO;KACJ,MAAM,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;oCAoBoB,MAAM,CAAC,EAAE;;;;;;;;;;;;;;;;;;6BAkBhB,MAAM,CAAC,EAAE;;;6BAGT,MAAM,CAAC,EAAE;;;;;CAKrC,CAAC;AACF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAmB;IACnD,OAAO;;;oCAG2B,MAAM,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;CAyB5C,CAAC;AACF,CAAC"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
export function generatePersona(config) {
|
|
2
2
|
const principleLines = config.principles.map((p) => ` '${escapeQuotes(p)}',`).join('\n');
|
|
3
|
+
const tone = config.tone ?? 'pragmatic';
|
|
3
4
|
return `export interface AgentPersona {
|
|
4
5
|
name: string;
|
|
5
6
|
role: string;
|
|
6
7
|
description: string;
|
|
7
8
|
principles: string[];
|
|
9
|
+
tone: 'precise' | 'mentor' | 'pragmatic';
|
|
8
10
|
greeting: string;
|
|
9
11
|
}
|
|
10
12
|
|
|
@@ -15,10 +17,33 @@ export const PERSONA: AgentPersona = {
|
|
|
15
17
|
principles: [
|
|
16
18
|
${principleLines}
|
|
17
19
|
],
|
|
20
|
+
tone: '${tone}',
|
|
18
21
|
greeting: '${escapeQuotes(config.greeting ?? `Hello! I'm ${config.name}.`)}',
|
|
19
22
|
};
|
|
20
23
|
|
|
24
|
+
const TONE_INSTRUCTIONS: Record<string, string[]> = {
|
|
25
|
+
precise: [
|
|
26
|
+
'Communication style: precise',
|
|
27
|
+
'- Be direct and factual with minimal commentary',
|
|
28
|
+
'- Lead with the conclusion, then support it',
|
|
29
|
+
'- Omit caveats unless they change the recommendation',
|
|
30
|
+
],
|
|
31
|
+
mentor: [
|
|
32
|
+
'Communication style: mentor',
|
|
33
|
+
'- Explain the "why" behind every suggestion',
|
|
34
|
+
'- Use examples to illustrate concepts',
|
|
35
|
+
'- Guide the user to understand, not just follow instructions',
|
|
36
|
+
],
|
|
37
|
+
pragmatic: [
|
|
38
|
+
'Communication style: pragmatic',
|
|
39
|
+
'- Focus on actionable outcomes',
|
|
40
|
+
'- Balance thoroughness with brevity',
|
|
41
|
+
'- Prioritize what matters most for the current context',
|
|
42
|
+
],
|
|
43
|
+
};
|
|
44
|
+
|
|
21
45
|
export function getPersonaPrompt(): string {
|
|
46
|
+
const toneLines = TONE_INSTRUCTIONS[PERSONA.tone] ?? TONE_INSTRUCTIONS.pragmatic;
|
|
22
47
|
return [
|
|
23
48
|
\`You are \${PERSONA.name}, a \${PERSONA.role}.\`,
|
|
24
49
|
'',
|
|
@@ -27,6 +52,8 @@ export function getPersonaPrompt(): string {
|
|
|
27
52
|
'Core principles:',
|
|
28
53
|
...PERSONA.principles.map((p) => \`- \${p}\`),
|
|
29
54
|
'',
|
|
55
|
+
...toneLines,
|
|
56
|
+
'',
|
|
30
57
|
'When advising:',
|
|
31
58
|
'- Reference specific patterns from the knowledge vault',
|
|
32
59
|
'- Provide concrete examples, not just theory',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persona.js","sourceRoot":"","sources":["../../src/templates/persona.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,eAAe,CAAC,MAAmB;IACjD,MAAM,cAAc,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"persona.js","sourceRoot":"","sources":["../../src/templates/persona.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,eAAe,CAAC,MAAmB;IACjD,MAAM,cAAc,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5F,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,WAAW,CAAC;IAExC,OAAO;;;;;;;;;;WAUE,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC;WACzB,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC;kBAClB,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC;;EAEhD,cAAc;;WAEL,IAAI;eACA,YAAY,CAAC,MAAM,CAAC,QAAQ,IAAI,cAAc,MAAM,CAAC,IAAI,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2C3E,CAAC;AACF,CAAC;AAED,SAAS,YAAY,CAAC,CAAS;IAC7B,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACvD,CAAC"}
|
|
@@ -3,6 +3,8 @@ import type { AgentConfig } from '../types.js';
|
|
|
3
3
|
* Generate skill files for the scaffolded agent.
|
|
4
4
|
* Returns [relativePath, content] tuples for each skill.
|
|
5
5
|
*
|
|
6
|
+
* - If config.skills is set, only those skills are included.
|
|
7
|
+
* - If config.skills is undefined/empty, all skills are included (backward compat).
|
|
6
8
|
* - Superpowers-adapted skills (MIT): copied as-is
|
|
7
9
|
* - Engine-adapted skills: YOUR_AGENT_core → {config.id}_core
|
|
8
10
|
*/
|
package/dist/templates/skills.js
CHANGED
|
@@ -27,6 +27,8 @@ const AGENT_SPECIFIC_SKILLS = new Set([
|
|
|
27
27
|
* Generate skill files for the scaffolded agent.
|
|
28
28
|
* Returns [relativePath, content] tuples for each skill.
|
|
29
29
|
*
|
|
30
|
+
* - If config.skills is set, only those skills are included.
|
|
31
|
+
* - If config.skills is undefined/empty, all skills are included (backward compat).
|
|
30
32
|
* - Superpowers-adapted skills (MIT): copied as-is
|
|
31
33
|
* - Engine-adapted skills: YOUR_AGENT_core → {config.id}_core
|
|
32
34
|
*/
|
|
@@ -39,8 +41,16 @@ export function generateSkills(config) {
|
|
|
39
41
|
catch {
|
|
40
42
|
return files;
|
|
41
43
|
}
|
|
44
|
+
// If skills array is present, filter to only those skills.
|
|
45
|
+
// undefined = include all (backward compat), [] = include none.
|
|
46
|
+
const allowedSkills = config.skills
|
|
47
|
+
? new Set(config.skills)
|
|
48
|
+
: null; // null = include all (backward compat)
|
|
42
49
|
for (const file of skillFiles) {
|
|
43
50
|
const skillName = file.replace('.md', '');
|
|
51
|
+
if (allowedSkills && !allowedSkills.has(skillName)) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
44
54
|
let content = readFileSync(join(SKILLS_DIR, file), 'utf-8');
|
|
45
55
|
if (AGENT_SPECIFIC_SKILLS.has(skillName)) {
|
|
46
56
|
content = content.replace(/YOUR_AGENT_core/g, `${config.id}_core`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/templates/skills.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;AAEnD,wFAAwF;AACxF,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC;IACpC,eAAe;IACf,eAAe;IACf,aAAa;IACb,gBAAgB;IAChB,iBAAiB;IACjB,eAAe;IACf,cAAc;IACd,mBAAmB;IACnB,YAAY;IACZ,eAAe;IACf,gBAAgB;IAChB,sBAAsB;IACtB,yBAAyB;IACzB,eAAe;IACf,iBAAiB;IACjB,gCAAgC;IAChC,eAAe;CAChB,CAAC,CAAC;AAEH
|
|
1
|
+
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/templates/skills.ts"],"names":[],"mappings":"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"}
|