@soleri/forge 5.14.9 → 7.0.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/agent-schema.d.ts +323 -0
- package/dist/agent-schema.js +151 -0
- package/dist/agent-schema.js.map +1 -0
- package/dist/compose-claude-md.d.ts +24 -0
- package/dist/compose-claude-md.js +197 -0
- package/dist/compose-claude-md.js.map +1 -0
- package/dist/index.js +0 -0
- package/dist/lib.d.ts +12 -1
- package/dist/lib.js +10 -1
- package/dist/lib.js.map +1 -1
- package/dist/scaffold-filetree.d.ts +22 -0
- package/dist/scaffold-filetree.js +349 -0
- package/dist/scaffold-filetree.js.map +1 -0
- package/dist/scaffolder.js +261 -11
- package/dist/scaffolder.js.map +1 -1
- package/dist/templates/activate.d.ts +5 -2
- package/dist/templates/activate.js +136 -35
- package/dist/templates/activate.js.map +1 -1
- package/dist/templates/agents-md.d.ts +10 -1
- package/dist/templates/agents-md.js +76 -16
- package/dist/templates/agents-md.js.map +1 -1
- package/dist/templates/claude-md-template.js +25 -4
- package/dist/templates/claude-md-template.js.map +1 -1
- package/dist/templates/entry-point.js +84 -7
- package/dist/templates/entry-point.js.map +1 -1
- package/dist/templates/inject-claude-md.js +53 -0
- package/dist/templates/inject-claude-md.js.map +1 -1
- package/dist/templates/package-json.js +4 -1
- package/dist/templates/package-json.js.map +1 -1
- package/dist/templates/readme.js +4 -3
- package/dist/templates/readme.js.map +1 -1
- package/dist/templates/setup-script.js +109 -3
- package/dist/templates/setup-script.js.map +1 -1
- package/dist/templates/shared-rules.js +54 -17
- package/dist/templates/shared-rules.js.map +1 -1
- package/dist/templates/test-facades.js +151 -6
- package/dist/templates/test-facades.js.map +1 -1
- package/dist/types.d.ts +75 -10
- package/dist/types.js +40 -2
- package/dist/types.js.map +1 -1
- package/dist/utils/detect-domain-packs.d.ts +25 -0
- package/dist/utils/detect-domain-packs.js +104 -0
- package/dist/utils/detect-domain-packs.js.map +1 -0
- package/package.json +2 -1
- package/src/__tests__/detect-domain-packs.test.ts +178 -0
- package/src/__tests__/scaffold-filetree.test.ts +243 -0
- package/src/__tests__/scaffolder.test.ts +5 -3
- package/src/agent-schema.ts +184 -0
- package/src/compose-claude-md.ts +252 -0
- package/src/lib.ts +14 -1
- package/src/scaffold-filetree.ts +409 -0
- package/src/scaffolder.ts +299 -15
- package/src/templates/activate.ts +137 -39
- package/src/templates/agents-md.ts +78 -16
- package/src/templates/claude-md-template.ts +29 -4
- package/src/templates/entry-point.ts +91 -7
- package/src/templates/inject-claude-md.ts +53 -0
- package/src/templates/package-json.ts +4 -1
- package/src/templates/readme.ts +4 -3
- package/src/templates/setup-script.ts +110 -4
- package/src/templates/shared-rules.ts +55 -17
- package/src/templates/test-facades.ts +156 -6
- package/src/types.ts +45 -2
- package/src/utils/detect-domain-packs.ts +129 -0
- package/tsconfig.json +0 -1
- package/vitest.config.ts +1 -2
|
@@ -6,20 +6,28 @@ export function generateFacadesTest(config) {
|
|
|
6
6
|
const domainDescribes = config.domains
|
|
7
7
|
.map((d) => generateDomainDescribe(config.id, d))
|
|
8
8
|
.join('\n\n');
|
|
9
|
+
const hasDomainPacks = config.domainPacks && config.domainPacks.length > 0;
|
|
10
|
+
const domainPackDescribes = hasDomainPacks
|
|
11
|
+
? config.domainPacks.map((ref) => generateDomainPackDescribe(config.id, ref)).join('\n\n')
|
|
12
|
+
: '';
|
|
9
13
|
return `import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
10
14
|
import {
|
|
11
15
|
createAgentRuntime,
|
|
12
16
|
createSemanticFacades,
|
|
13
17
|
createDomainFacade,
|
|
18
|
+
createDomainFacades,${hasDomainPacks ? `\n loadDomainPacksFromConfig,` : ''}
|
|
14
19
|
} from '@soleri/core';
|
|
15
20
|
import type { AgentRuntime, IntelligenceEntry, OpDefinition, FacadeConfig } from '@soleri/core';
|
|
16
21
|
import { z } from 'zod';
|
|
17
22
|
import { mkdirSync, readFileSync, rmSync, writeFileSync, existsSync } from 'node:fs';
|
|
18
|
-
import { join } from 'node:path';
|
|
23
|
+
import { dirname, join } from 'node:path';
|
|
24
|
+
import { fileURLToPath } from 'node:url';
|
|
19
25
|
import { tmpdir } from 'node:os';
|
|
20
26
|
import { PERSONA } from '../identity/persona.js';
|
|
21
27
|
import { activateAgent, deactivateAgent } from '../activation/activate.js';
|
|
22
|
-
import { injectClaudeMd, injectClaudeMdGlobal, hasAgentMarker } from '../activation/inject-claude-md.js';
|
|
28
|
+
import { injectClaudeMd, injectClaudeMdGlobal, hasAgentMarker, injectAgentsMd, injectAgentsMdGlobal, hasAgentMarkerInAgentsMd } from '../activation/inject-claude-md.js';
|
|
29
|
+
|
|
30
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
23
31
|
|
|
24
32
|
function makeEntry(overrides: Partial<IntelligenceEntry> = {}): IntelligenceEntry {
|
|
25
33
|
return {
|
|
@@ -53,7 +61,7 @@ describe('Facades', () => {
|
|
|
53
61
|
});
|
|
54
62
|
|
|
55
63
|
${domainDescribes}
|
|
56
|
-
|
|
64
|
+
${domainPackDescribes ? `\n${domainPackDescribes}\n` : ''}
|
|
57
65
|
// ─── Semantic Facades ────────────────────────────────────────
|
|
58
66
|
describe('semantic facades', () => {
|
|
59
67
|
function buildSemanticFacades(): FacadeConfig[] {
|
|
@@ -100,6 +108,12 @@ ${domainDescribes}
|
|
|
100
108
|
expect(opNames).toContain('vault_import');
|
|
101
109
|
expect(opNames).toContain('capture_knowledge');
|
|
102
110
|
expect(opNames).toContain('intake_ingest_book');
|
|
111
|
+
// Zettelkasten linking ops
|
|
112
|
+
expect(opNames).toContain('link_entries');
|
|
113
|
+
expect(opNames).toContain('get_links');
|
|
114
|
+
expect(opNames).toContain('traverse');
|
|
115
|
+
expect(opNames).toContain('suggest_links');
|
|
116
|
+
expect(opNames).toContain('get_orphans');
|
|
103
117
|
});
|
|
104
118
|
|
|
105
119
|
it('search should query across all domains', async () => {
|
|
@@ -297,7 +311,7 @@ ${domainDescribes}
|
|
|
297
311
|
}),
|
|
298
312
|
handler: async (params) => {
|
|
299
313
|
if (params.deactivate) return deactivateAgent();
|
|
300
|
-
return activateAgent(runtime
|
|
314
|
+
return activateAgent(runtime, (params.projectPath as string) ?? '.');
|
|
301
315
|
},
|
|
302
316
|
},
|
|
303
317
|
{
|
|
@@ -313,6 +327,19 @@ ${domainDescribes}
|
|
|
313
327
|
return injectClaudeMd((params.projectPath as string) ?? '.');
|
|
314
328
|
},
|
|
315
329
|
},
|
|
330
|
+
{
|
|
331
|
+
name: 'inject_agents_md',
|
|
332
|
+
description: 'Inject AGENTS.md',
|
|
333
|
+
auth: 'write',
|
|
334
|
+
schema: z.object({
|
|
335
|
+
projectPath: z.string().optional().default('.'),
|
|
336
|
+
global: z.boolean().optional(),
|
|
337
|
+
}),
|
|
338
|
+
handler: async (params) => {
|
|
339
|
+
if (params.global) return injectAgentsMdGlobal();
|
|
340
|
+
return injectAgentsMd((params.projectPath as string) ?? '.');
|
|
341
|
+
},
|
|
342
|
+
},
|
|
316
343
|
{
|
|
317
344
|
name: 'setup',
|
|
318
345
|
description: 'Setup status',
|
|
@@ -386,6 +413,7 @@ ${domainDescribes}
|
|
|
386
413
|
expect(allOps).not.toContain('identity');
|
|
387
414
|
expect(allOps).not.toContain('activate');
|
|
388
415
|
expect(allOps).not.toContain('inject_claude_md');
|
|
416
|
+
expect(allOps).not.toContain('inject_agents_md');
|
|
389
417
|
expect(allOps).not.toContain('setup');
|
|
390
418
|
});
|
|
391
419
|
|
|
@@ -409,10 +437,10 @@ ${domainDescribes}
|
|
|
409
437
|
const activateOp = facade.ops.find((o) => o.name === 'activate')!;
|
|
410
438
|
const result = (await activateOp.handler({ projectPath: '/tmp/nonexistent-test' })) as {
|
|
411
439
|
activated: boolean;
|
|
412
|
-
|
|
440
|
+
origin: { name: string; role: string };
|
|
413
441
|
};
|
|
414
442
|
expect(result.activated).toBe(true);
|
|
415
|
-
expect(result.
|
|
443
|
+
expect(result.origin.name).toBe('${escapeQuotes(config.name)}');
|
|
416
444
|
});
|
|
417
445
|
|
|
418
446
|
it('activate with deactivate flag should return deactivation', async () => {
|
|
@@ -444,6 +472,27 @@ ${domainDescribes}
|
|
|
444
472
|
}
|
|
445
473
|
});
|
|
446
474
|
|
|
475
|
+
it('inject_agents_md should create AGENTS.md in temp dir', async () => {
|
|
476
|
+
const tempDir = join(tmpdir(), 'forge-inject-agents-test-' + Date.now());
|
|
477
|
+
mkdirSync(tempDir, { recursive: true });
|
|
478
|
+
try {
|
|
479
|
+
const facade = buildAgentFacade();
|
|
480
|
+
const injectOp = facade.ops.find((o) => o.name === 'inject_agents_md')!;
|
|
481
|
+
const result = (await injectOp.handler({ projectPath: tempDir })) as {
|
|
482
|
+
injected: boolean;
|
|
483
|
+
path: string;
|
|
484
|
+
action: string;
|
|
485
|
+
};
|
|
486
|
+
expect(result.injected).toBe(true);
|
|
487
|
+
expect(result.action).toBe('created');
|
|
488
|
+
expect(existsSync(result.path)).toBe(true);
|
|
489
|
+
const content = readFileSync(result.path, 'utf-8');
|
|
490
|
+
expect(content).toContain('${config.id}:mode');
|
|
491
|
+
} finally {
|
|
492
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
493
|
+
}
|
|
494
|
+
});
|
|
495
|
+
|
|
447
496
|
it('setup should return project and global CLAUDE.md status', async () => {
|
|
448
497
|
const facade = buildAgentFacade();
|
|
449
498
|
const setupOp = facade.ops.find((o) => o.name === 'setup')!;
|
|
@@ -459,6 +508,73 @@ ${domainDescribes}
|
|
|
459
508
|
expect(result.recommendations.length).toBeGreaterThan(0);
|
|
460
509
|
});
|
|
461
510
|
});
|
|
511
|
+
|
|
512
|
+
// ─── Capability Registry ───────────────────────────────────
|
|
513
|
+
describe('Capability Registry', () => {
|
|
514
|
+
it('should register and resolve capabilities', () => {
|
|
515
|
+
const { CapabilityRegistry } = require('@soleri/core');
|
|
516
|
+
const registry = new CapabilityRegistry();
|
|
517
|
+
|
|
518
|
+
// Register a test capability
|
|
519
|
+
const handlers = new Map();
|
|
520
|
+
handlers.set('test.hello', async () => ({ success: true, data: {}, produced: ['greeting'] }));
|
|
521
|
+
registry.registerPack(
|
|
522
|
+
'test-pack',
|
|
523
|
+
[{ id: 'test.hello', description: 'Test', provides: ['greeting'], requires: [] }],
|
|
524
|
+
handlers,
|
|
525
|
+
);
|
|
526
|
+
|
|
527
|
+
expect(registry.has('test.hello')).toBe(true);
|
|
528
|
+
expect(registry.has('test.missing')).toBe(false);
|
|
529
|
+
|
|
530
|
+
const resolved = registry.resolve('test.hello');
|
|
531
|
+
expect(resolved.available).toBe(true);
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
it('should track multiple capabilities from one pack', () => {
|
|
535
|
+
const { CapabilityRegistry } = require('@soleri/core');
|
|
536
|
+
const registry = new CapabilityRegistry();
|
|
537
|
+
|
|
538
|
+
const handlers = new Map();
|
|
539
|
+
handlers.set('test.alpha', async () => ({ success: true, data: {}, produced: ['a'] }));
|
|
540
|
+
handlers.set('test.beta', async () => ({ success: true, data: {}, produced: ['b'] }));
|
|
541
|
+
registry.registerPack(
|
|
542
|
+
'multi-pack',
|
|
543
|
+
[
|
|
544
|
+
{ id: 'test.alpha', description: 'Alpha', provides: ['a'], requires: [] },
|
|
545
|
+
{ id: 'test.beta', description: 'Beta', provides: ['b'], requires: [] },
|
|
546
|
+
],
|
|
547
|
+
handlers,
|
|
548
|
+
);
|
|
549
|
+
|
|
550
|
+
expect(registry.size).toBe(2);
|
|
551
|
+
expect(registry.has('test.alpha')).toBe(true);
|
|
552
|
+
expect(registry.has('test.beta')).toBe(true);
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
it('should report missing capabilities in flow validation', () => {
|
|
556
|
+
const { CapabilityRegistry } = require('@soleri/core');
|
|
557
|
+
const registry = new CapabilityRegistry();
|
|
558
|
+
|
|
559
|
+
const handlers = new Map();
|
|
560
|
+
handlers.set('vault.search', async () => ({ success: true, data: {}, produced: ['results'] }));
|
|
561
|
+
registry.registerPack(
|
|
562
|
+
'core',
|
|
563
|
+
[{ id: 'vault.search', description: 'Search vault', provides: ['results'], requires: [] }],
|
|
564
|
+
handlers,
|
|
565
|
+
);
|
|
566
|
+
|
|
567
|
+
const flow = {
|
|
568
|
+
steps: [
|
|
569
|
+
{ needs: ['vault.search', 'color.validate'] },
|
|
570
|
+
],
|
|
571
|
+
};
|
|
572
|
+
const validation = registry.validateFlow(flow);
|
|
573
|
+
expect(validation.valid).toBe(false);
|
|
574
|
+
expect(validation.available).toContain('vault.search');
|
|
575
|
+
expect(validation.missing).toContain('color.validate');
|
|
576
|
+
});
|
|
577
|
+
});
|
|
462
578
|
});
|
|
463
579
|
`;
|
|
464
580
|
}
|
|
@@ -538,6 +654,35 @@ function generateDomainDescribe(agentId, domain) {
|
|
|
538
654
|
});
|
|
539
655
|
});`;
|
|
540
656
|
}
|
|
657
|
+
function generateDomainPackDescribe(agentId, ref) {
|
|
658
|
+
return ` describe('domain pack: ${ref.name}', () => {
|
|
659
|
+
it('should load and validate the domain pack', async () => {
|
|
660
|
+
const packs = await loadDomainPacksFromConfig([${JSON.stringify(ref)}]);
|
|
661
|
+
expect(packs.length).toBe(1);
|
|
662
|
+
expect(packs[0].name).toBe('${ref.name}');
|
|
663
|
+
expect(packs[0].ops.length).toBeGreaterThan(0);
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
it('should register pack ops in domain facades', async () => {
|
|
667
|
+
const packs = await loadDomainPacksFromConfig([${JSON.stringify(ref)}]);
|
|
668
|
+
const facades = createDomainFacades(runtime, '${agentId}', ${JSON.stringify([ref.name])}, packs);
|
|
669
|
+
expect(facades.length).toBeGreaterThanOrEqual(1);
|
|
670
|
+
// Pack ops should be present
|
|
671
|
+
const allOps = facades.flatMap(f => f.ops.map(o => o.name));
|
|
672
|
+
expect(allOps.length).toBeGreaterThan(5); // More than standard 5
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
it('pack custom ops should be callable', async () => {
|
|
676
|
+
const packs = await loadDomainPacksFromConfig([${JSON.stringify(ref)}]);
|
|
677
|
+
const facades = createDomainFacades(runtime, '${agentId}', ${JSON.stringify([ref.name])}, packs);
|
|
678
|
+
const facade = facades[0];
|
|
679
|
+
// Test first custom op returns without error
|
|
680
|
+
const firstOp = facade.ops[0];
|
|
681
|
+
const result = await firstOp.handler({});
|
|
682
|
+
expect(result).toBeDefined();
|
|
683
|
+
});
|
|
684
|
+
});`;
|
|
685
|
+
}
|
|
541
686
|
function escapeQuotes(s) {
|
|
542
687
|
return s.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
|
543
688
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-facades.js","sourceRoot":"","sources":["../../src/templates/test-facades.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAmB;IACrD,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO;SACnC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;SAChD,IAAI,CAAC,MAAM,CAAC,CAAC;IAEhB,OAAO
|
|
1
|
+
{"version":3,"file":"test-facades.js","sourceRoot":"","sources":["../../src/templates/test-facades.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
/** Where to scaffold host/client integration setup. */
|
|
3
|
-
export declare const SETUP_TARGETS: readonly ["claude", "codex", "both"];
|
|
3
|
+
export declare const SETUP_TARGETS: readonly ["claude", "codex", "opencode", "both", "all"];
|
|
4
4
|
export type SetupTarget = (typeof SETUP_TARGETS)[number];
|
|
5
|
+
/** Available model presets for agent configuration */
|
|
6
|
+
export declare const MODEL_PRESETS: readonly ["claude-code-sonnet-4", "claude-code-opus-4", "claude-code-3.7-sonnet", "claude-code-3.5-haiku", "claude-4-sonnet", "claude-4-opus", "gpt-4.1", "gpt-4.1-mini", "gemini-2.5", "gemini-2.5-flash"];
|
|
5
7
|
/** Agent configuration — everything needed to scaffold */
|
|
6
8
|
export declare const AgentConfigSchema: z.ZodObject<{
|
|
7
9
|
/** Agent identifier (kebab-case, used for directory and package name) */
|
|
@@ -26,38 +28,101 @@ export declare const AgentConfigSchema: z.ZodObject<{
|
|
|
26
28
|
hookPacks: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
27
29
|
/** Skills to include (if omitted, all skills are included for backward compat) */
|
|
28
30
|
skills: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
31
|
+
/** Primary model for the coder agent */
|
|
32
|
+
model: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
29
33
|
/** AI client setup target: Claude Code, Codex, or both */
|
|
30
|
-
setupTarget: z.ZodDefault<z.ZodOptional<z.ZodEnum<["claude", "codex", "both"]>>>;
|
|
34
|
+
setupTarget: z.ZodDefault<z.ZodOptional<z.ZodEnum<["claude", "codex", "opencode", "both", "all"]>>>;
|
|
31
35
|
/** Enable Telegram transport scaffolding. Default: false. */
|
|
32
36
|
telegram: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
37
|
+
/** Enable Cognee vector search integration. Default: false. */
|
|
38
|
+
cognee: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
39
|
+
/** Domain packs — npm packages with custom ops, knowledge, rules, and skills. */
|
|
40
|
+
domainPacks: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
41
|
+
name: z.ZodString;
|
|
42
|
+
package: z.ZodString;
|
|
43
|
+
version: z.ZodOptional<z.ZodString>;
|
|
44
|
+
}, "strip", z.ZodTypeAny, {
|
|
45
|
+
name: string;
|
|
46
|
+
package: string;
|
|
47
|
+
version?: string | undefined;
|
|
48
|
+
}, {
|
|
49
|
+
name: string;
|
|
50
|
+
package: string;
|
|
51
|
+
version?: string | undefined;
|
|
52
|
+
}>, "many">>;
|
|
53
|
+
/** Vault connections — link to existing vaults instead of importing knowledge. */
|
|
54
|
+
vaults: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
55
|
+
/** Display name for this vault connection */
|
|
56
|
+
name: z.ZodString;
|
|
57
|
+
/** Absolute path to the vault SQLite database */
|
|
58
|
+
path: z.ZodString;
|
|
59
|
+
/** Search priority (0-1). Higher = results ranked higher. Default: 0.5 */
|
|
60
|
+
priority: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
61
|
+
}, "strip", z.ZodTypeAny, {
|
|
62
|
+
name: string;
|
|
63
|
+
path: string;
|
|
64
|
+
priority: number;
|
|
65
|
+
}, {
|
|
66
|
+
name: string;
|
|
67
|
+
path: string;
|
|
68
|
+
priority?: number | undefined;
|
|
69
|
+
}>, "many">>;
|
|
70
|
+
/** @deprecated Use vaults[] instead. Shorthand for a single shared vault at priority 0.6. */
|
|
71
|
+
sharedVaultPath: z.ZodOptional<z.ZodString>;
|
|
33
72
|
}, "strip", z.ZodTypeAny, {
|
|
34
|
-
id: string;
|
|
35
73
|
name: string;
|
|
36
|
-
|
|
74
|
+
cognee: boolean;
|
|
75
|
+
model: string;
|
|
76
|
+
id: string;
|
|
37
77
|
description: string;
|
|
78
|
+
role: string;
|
|
38
79
|
domains: string[];
|
|
39
80
|
principles: string[];
|
|
40
81
|
tone: "precise" | "mentor" | "pragmatic";
|
|
41
82
|
outputDir: string;
|
|
42
|
-
setupTarget: "claude" | "codex" | "both";
|
|
83
|
+
setupTarget: "claude" | "codex" | "opencode" | "both" | "all";
|
|
43
84
|
telegram: boolean;
|
|
44
85
|
greeting?: string | undefined;
|
|
45
|
-
|
|
86
|
+
vaults?: {
|
|
87
|
+
name: string;
|
|
88
|
+
path: string;
|
|
89
|
+
priority: number;
|
|
90
|
+
}[] | undefined;
|
|
46
91
|
skills?: string[] | undefined;
|
|
92
|
+
hookPacks?: string[] | undefined;
|
|
93
|
+
domainPacks?: {
|
|
94
|
+
name: string;
|
|
95
|
+
package: string;
|
|
96
|
+
version?: string | undefined;
|
|
97
|
+
}[] | undefined;
|
|
98
|
+
sharedVaultPath?: string | undefined;
|
|
47
99
|
}, {
|
|
48
|
-
id: string;
|
|
49
100
|
name: string;
|
|
50
|
-
|
|
101
|
+
id: string;
|
|
51
102
|
description: string;
|
|
103
|
+
role: string;
|
|
52
104
|
domains: string[];
|
|
53
105
|
principles: string[];
|
|
106
|
+
cognee?: boolean | undefined;
|
|
107
|
+
model?: string | undefined;
|
|
54
108
|
tone?: "precise" | "mentor" | "pragmatic" | undefined;
|
|
55
109
|
greeting?: string | undefined;
|
|
110
|
+
vaults?: {
|
|
111
|
+
name: string;
|
|
112
|
+
path: string;
|
|
113
|
+
priority?: number | undefined;
|
|
114
|
+
}[] | undefined;
|
|
115
|
+
skills?: string[] | undefined;
|
|
56
116
|
outputDir?: string | undefined;
|
|
57
117
|
hookPacks?: string[] | undefined;
|
|
58
|
-
|
|
59
|
-
setupTarget?: "claude" | "codex" | "both" | undefined;
|
|
118
|
+
setupTarget?: "claude" | "codex" | "opencode" | "both" | "all" | undefined;
|
|
60
119
|
telegram?: boolean | undefined;
|
|
120
|
+
domainPacks?: {
|
|
121
|
+
name: string;
|
|
122
|
+
package: string;
|
|
123
|
+
version?: string | undefined;
|
|
124
|
+
}[] | undefined;
|
|
125
|
+
sharedVaultPath?: string | undefined;
|
|
61
126
|
}>;
|
|
62
127
|
export type AgentConfig = z.infer<typeof AgentConfigSchema>;
|
|
63
128
|
/** Input type — fields with defaults are optional (use before Zod parsing) */
|
package/dist/types.js
CHANGED
|
@@ -2,7 +2,20 @@ import { z } from 'zod';
|
|
|
2
2
|
/** Communication tone for the agent persona */
|
|
3
3
|
const TONES = ['precise', 'mentor', 'pragmatic'];
|
|
4
4
|
/** Where to scaffold host/client integration setup. */
|
|
5
|
-
export const SETUP_TARGETS = ['claude', 'codex', 'both'];
|
|
5
|
+
export const SETUP_TARGETS = ['claude', 'codex', 'opencode', 'both', 'all'];
|
|
6
|
+
/** Available model presets for agent configuration */
|
|
7
|
+
export const MODEL_PRESETS = [
|
|
8
|
+
'claude-code-sonnet-4',
|
|
9
|
+
'claude-code-opus-4',
|
|
10
|
+
'claude-code-3.7-sonnet',
|
|
11
|
+
'claude-code-3.5-haiku',
|
|
12
|
+
'claude-4-sonnet',
|
|
13
|
+
'claude-4-opus',
|
|
14
|
+
'gpt-4.1',
|
|
15
|
+
'gpt-4.1-mini',
|
|
16
|
+
'gemini-2.5',
|
|
17
|
+
'gemini-2.5-flash',
|
|
18
|
+
];
|
|
6
19
|
/** Agent configuration — everything needed to scaffold */
|
|
7
20
|
export const AgentConfigSchema = z.object({
|
|
8
21
|
/** Agent identifier (kebab-case, used for directory and package name) */
|
|
@@ -27,9 +40,34 @@ export const AgentConfigSchema = z.object({
|
|
|
27
40
|
hookPacks: z.array(z.string()).optional(),
|
|
28
41
|
/** Skills to include (if omitted, all skills are included for backward compat) */
|
|
29
42
|
skills: z.array(z.string()).optional(),
|
|
43
|
+
/** Primary model for the coder agent */
|
|
44
|
+
model: z.string().optional().default('claude-code-sonnet-4'),
|
|
30
45
|
/** AI client setup target: Claude Code, Codex, or both */
|
|
31
|
-
setupTarget: z.enum(SETUP_TARGETS).optional().default('
|
|
46
|
+
setupTarget: z.enum(SETUP_TARGETS).optional().default('opencode'),
|
|
32
47
|
/** Enable Telegram transport scaffolding. Default: false. */
|
|
33
48
|
telegram: z.boolean().optional().default(false),
|
|
49
|
+
/** Enable Cognee vector search integration. Default: false. */
|
|
50
|
+
cognee: z.boolean().optional().default(false),
|
|
51
|
+
/** Domain packs — npm packages with custom ops, knowledge, rules, and skills. */
|
|
52
|
+
domainPacks: z
|
|
53
|
+
.array(z.object({
|
|
54
|
+
name: z.string(),
|
|
55
|
+
package: z.string(),
|
|
56
|
+
version: z.string().optional(),
|
|
57
|
+
}))
|
|
58
|
+
.optional(),
|
|
59
|
+
/** Vault connections — link to existing vaults instead of importing knowledge. */
|
|
60
|
+
vaults: z
|
|
61
|
+
.array(z.object({
|
|
62
|
+
/** Display name for this vault connection */
|
|
63
|
+
name: z.string(),
|
|
64
|
+
/** Absolute path to the vault SQLite database */
|
|
65
|
+
path: z.string(),
|
|
66
|
+
/** Search priority (0-1). Higher = results ranked higher. Default: 0.5 */
|
|
67
|
+
priority: z.number().min(0).max(1).optional().default(0.5),
|
|
68
|
+
}))
|
|
69
|
+
.optional(),
|
|
70
|
+
/** @deprecated Use vaults[] instead. Shorthand for a single shared vault at priority 0.6. */
|
|
71
|
+
sharedVaultPath: z.string().optional(),
|
|
34
72
|
});
|
|
35
73
|
//# 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,+CAA+C;AAC/C,MAAM,KAAK,GAAG,CAAC,SAAS,EAAE,QAAQ,EAAE,WAAW,CAAU,CAAC;AAE1D,uDAAuD;AACvD,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-detect installed @soleri/domain-* packages.
|
|
3
|
+
* Scans node_modules for packages matching the pattern.
|
|
4
|
+
*/
|
|
5
|
+
export interface DetectedDomainPack {
|
|
6
|
+
/** Display name (e.g., 'design') */
|
|
7
|
+
name: string;
|
|
8
|
+
/** npm package name (e.g., '@soleri/domain-design') */
|
|
9
|
+
package: string;
|
|
10
|
+
/** Installed version from package.json */
|
|
11
|
+
version: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Scan node_modules/@soleri/ for domain-* packages and return refs
|
|
15
|
+
* suitable for merging into AgentConfig.domainPacks.
|
|
16
|
+
*
|
|
17
|
+
* Walks up from basePath to find the nearest node_modules with @soleri scope.
|
|
18
|
+
* For each `domain-*` directory found, reads its package.json to extract
|
|
19
|
+
* name and version, then does a lightweight structural check (the package
|
|
20
|
+
* must export a default or named 'pack' with name, version, domains, ops fields).
|
|
21
|
+
*
|
|
22
|
+
* @param basePath - Directory to start searching from (typically config.outputDir)
|
|
23
|
+
* @returns Array of detected domain pack references
|
|
24
|
+
*/
|
|
25
|
+
export declare function detectInstalledDomainPacks(basePath: string): DetectedDomainPack[];
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-detect installed @soleri/domain-* packages.
|
|
3
|
+
* Scans node_modules for packages matching the pattern.
|
|
4
|
+
*/
|
|
5
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
/**
|
|
8
|
+
* Scan node_modules/@soleri/ for domain-* packages and return refs
|
|
9
|
+
* suitable for merging into AgentConfig.domainPacks.
|
|
10
|
+
*
|
|
11
|
+
* Walks up from basePath to find the nearest node_modules with @soleri scope.
|
|
12
|
+
* For each `domain-*` directory found, reads its package.json to extract
|
|
13
|
+
* name and version, then does a lightweight structural check (the package
|
|
14
|
+
* must export a default or named 'pack' with name, version, domains, ops fields).
|
|
15
|
+
*
|
|
16
|
+
* @param basePath - Directory to start searching from (typically config.outputDir)
|
|
17
|
+
* @returns Array of detected domain pack references
|
|
18
|
+
*/
|
|
19
|
+
export function detectInstalledDomainPacks(basePath) {
|
|
20
|
+
const results = [];
|
|
21
|
+
const soleriScope = findSoleriScope(basePath);
|
|
22
|
+
if (!soleriScope)
|
|
23
|
+
return results;
|
|
24
|
+
let entries;
|
|
25
|
+
try {
|
|
26
|
+
entries = readdirSync(soleriScope);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return results;
|
|
30
|
+
}
|
|
31
|
+
for (const entry of entries) {
|
|
32
|
+
if (!entry.startsWith('domain-'))
|
|
33
|
+
continue;
|
|
34
|
+
const packDir = join(soleriScope, entry);
|
|
35
|
+
const pkgJsonPath = join(packDir, 'package.json');
|
|
36
|
+
if (!existsSync(pkgJsonPath))
|
|
37
|
+
continue;
|
|
38
|
+
try {
|
|
39
|
+
const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
|
|
40
|
+
if (!pkg.name || !pkg.version)
|
|
41
|
+
continue;
|
|
42
|
+
// Lightweight structural check: look for an index/main file that
|
|
43
|
+
// would be importable. We don't actually import it (that would
|
|
44
|
+
// execute arbitrary code at scaffold time), but we verify the
|
|
45
|
+
// package looks like a domain pack by checking package.json keywords
|
|
46
|
+
// or the presence of expected exports.
|
|
47
|
+
if (looksLikeDomainPack(packDir, pkg)) {
|
|
48
|
+
const shortName = entry.replace(/^domain-/, '');
|
|
49
|
+
results.push({
|
|
50
|
+
name: shortName,
|
|
51
|
+
package: pkg.name,
|
|
52
|
+
version: pkg.version,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// Skip packages with invalid package.json
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return results;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Walk up from basePath to find node_modules/@soleri directory.
|
|
64
|
+
*/
|
|
65
|
+
function findSoleriScope(basePath) {
|
|
66
|
+
let current = basePath;
|
|
67
|
+
const seen = new Set();
|
|
68
|
+
while (current && !seen.has(current)) {
|
|
69
|
+
seen.add(current);
|
|
70
|
+
const candidate = join(current, 'node_modules', '@soleri');
|
|
71
|
+
if (existsSync(candidate)) {
|
|
72
|
+
return candidate;
|
|
73
|
+
}
|
|
74
|
+
const parent = join(current, '..');
|
|
75
|
+
if (parent === current)
|
|
76
|
+
break;
|
|
77
|
+
current = parent;
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Lightweight check that a package looks like a domain pack without importing it.
|
|
83
|
+
* Checks for:
|
|
84
|
+
* - A soleri-domain-pack keyword in package.json, OR
|
|
85
|
+
* - An entry point file that exists
|
|
86
|
+
*/
|
|
87
|
+
function looksLikeDomainPack(packDir, pkg) {
|
|
88
|
+
// Fast path: keyword-based detection
|
|
89
|
+
if (Array.isArray(pkg.keywords) && pkg.keywords.includes('soleri-domain-pack')) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
// Check that the package has an entry point (main or exports)
|
|
93
|
+
if (pkg.main) {
|
|
94
|
+
return existsSync(join(packDir, pkg.main));
|
|
95
|
+
}
|
|
96
|
+
// Check common entry points
|
|
97
|
+
for (const candidate of ['dist/index.js', 'index.js', 'dist/index.mjs']) {
|
|
98
|
+
if (existsSync(join(packDir, candidate))) {
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=detect-domain-packs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-domain-packs.js","sourceRoot":"","sources":["../../src/utils/detect-domain-packs.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soleri/forge",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0",
|
|
4
4
|
"description": "Scaffold AI agents that learn, remember, and grow with you.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
54
|
+
"yaml": "^2.8.2",
|
|
54
55
|
"zod": "^3.24.2"
|
|
55
56
|
},
|
|
56
57
|
"engines": {
|