@soleri/cli 1.9.0 → 1.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/commands/agent.d.ts +8 -0
- package/dist/commands/agent.js +150 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/create.js +38 -6
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/install-knowledge.js +65 -3
- package/dist/commands/install-knowledge.js.map +1 -1
- package/dist/commands/install.d.ts +2 -0
- package/dist/commands/install.js +80 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/pack.d.ts +10 -0
- package/dist/commands/pack.js +512 -0
- package/dist/commands/pack.js.map +1 -0
- package/dist/commands/skills.d.ts +8 -0
- package/dist/commands/skills.js +167 -0
- package/dist/commands/skills.js.map +1 -0
- package/dist/commands/uninstall.d.ts +2 -0
- package/dist/commands/uninstall.js +74 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/hook-packs/installer.d.ts +0 -7
- package/dist/hook-packs/installer.js +1 -14
- package/dist/hook-packs/installer.js.map +1 -1
- package/dist/hook-packs/installer.ts +1 -18
- package/dist/hook-packs/registry.d.ts +2 -1
- package/dist/hook-packs/registry.ts +1 -1
- package/dist/main.js +40 -1
- package/dist/main.js.map +1 -1
- package/dist/prompts/archetypes.d.ts +1 -0
- package/dist/prompts/archetypes.js +177 -62
- package/dist/prompts/archetypes.js.map +1 -1
- package/dist/prompts/create-wizard.d.ts +3 -3
- package/dist/prompts/create-wizard.js +99 -50
- package/dist/prompts/create-wizard.js.map +1 -1
- package/dist/prompts/playbook.d.ts +8 -7
- package/dist/prompts/playbook.js +201 -15
- package/dist/prompts/playbook.js.map +1 -1
- package/dist/utils/checks.d.ts +0 -1
- package/dist/utils/checks.js +1 -1
- package/dist/utils/checks.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/archetypes.test.ts +84 -0
- package/src/__tests__/doctor.test.ts +2 -2
- package/src/__tests__/wizard-e2e.mjs +508 -0
- package/src/commands/agent.ts +181 -0
- package/src/commands/create.ts +152 -104
- package/src/commands/install-knowledge.ts +75 -4
- package/src/commands/install.ts +101 -0
- package/src/commands/pack.ts +585 -0
- package/src/commands/skills.ts +191 -0
- package/src/commands/uninstall.ts +93 -0
- package/src/hook-packs/installer.ts +1 -18
- package/src/hook-packs/registry.ts +1 -1
- package/src/main.ts +42 -1
- package/src/prompts/archetypes.ts +193 -62
- package/src/prompts/create-wizard.ts +117 -61
- package/src/prompts/playbook.ts +207 -21
- package/src/utils/checks.ts +1 -1
- package/code-reviewer/.claude/hookify.focus-ring-required.local.md +0 -21
- package/code-reviewer/.claude/hookify.no-ai-attribution.local.md +0 -18
- package/code-reviewer/.claude/hookify.no-any-types.local.md +0 -18
- package/code-reviewer/.claude/hookify.no-console-log.local.md +0 -21
- package/code-reviewer/.claude/hookify.no-important.local.md +0 -18
- package/code-reviewer/.claude/hookify.no-inline-styles.local.md +0 -21
- package/code-reviewer/.claude/hookify.semantic-html.local.md +0 -18
- package/code-reviewer/.claude/hookify.ux-touch-targets.local.md +0 -18
- package/code-reviewer/.mcp.json +0 -11
- package/code-reviewer/README.md +0 -346
- package/code-reviewer/package-lock.json +0 -4484
- package/code-reviewer/package.json +0 -45
- package/code-reviewer/scripts/copy-assets.js +0 -15
- package/code-reviewer/scripts/setup.sh +0 -130
- package/code-reviewer/skills/brainstorming/SKILL.md +0 -170
- package/code-reviewer/skills/code-patrol/SKILL.md +0 -176
- package/code-reviewer/skills/context-resume/SKILL.md +0 -143
- package/code-reviewer/skills/executing-plans/SKILL.md +0 -201
- package/code-reviewer/skills/fix-and-learn/SKILL.md +0 -164
- package/code-reviewer/skills/health-check/SKILL.md +0 -225
- package/code-reviewer/skills/second-opinion/SKILL.md +0 -142
- package/code-reviewer/skills/systematic-debugging/SKILL.md +0 -230
- package/code-reviewer/skills/verification-before-completion/SKILL.md +0 -170
- package/code-reviewer/skills/writing-plans/SKILL.md +0 -207
- package/code-reviewer/src/__tests__/facades.test.ts +0 -598
- package/code-reviewer/src/activation/activate.ts +0 -125
- package/code-reviewer/src/activation/claude-md-content.ts +0 -217
- package/code-reviewer/src/activation/inject-claude-md.ts +0 -113
- package/code-reviewer/src/extensions/index.ts +0 -47
- package/code-reviewer/src/extensions/ops/example.ts +0 -28
- package/code-reviewer/src/identity/persona.ts +0 -62
- package/code-reviewer/src/index.ts +0 -278
- package/code-reviewer/src/intelligence/data/architecture.json +0 -5
- package/code-reviewer/src/intelligence/data/code-review.json +0 -5
- package/code-reviewer/tsconfig.json +0 -30
- package/code-reviewer/vitest.config.ts +0 -23
|
@@ -1,278 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
|
-
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
5
|
-
import { dirname, join } from 'node:path';
|
|
6
|
-
import { fileURLToPath } from 'node:url';
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
createAgentRuntime,
|
|
10
|
-
createSemanticFacades,
|
|
11
|
-
createDomainFacades,
|
|
12
|
-
registerAllFacades,
|
|
13
|
-
seedDefaultPlaybooks,
|
|
14
|
-
wrapWithMiddleware,
|
|
15
|
-
} from '@soleri/core';
|
|
16
|
-
import type { OpDefinition, AgentExtensions } from '@soleri/core';
|
|
17
|
-
import { z } from 'zod';
|
|
18
|
-
import { PERSONA, getPersonaPrompt } from './identity/persona.js';
|
|
19
|
-
import { activateAgent, deactivateAgent } from './activation/activate.js';
|
|
20
|
-
import { injectClaudeMd, injectClaudeMdGlobal, hasAgentMarker } from './activation/inject-claude-md.js';
|
|
21
|
-
|
|
22
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
23
|
-
|
|
24
|
-
async function main(): Promise<void> {
|
|
25
|
-
// ─── Runtime — vault, brain, planner, curator, LLM, key pools ───
|
|
26
|
-
const runtime = createAgentRuntime({
|
|
27
|
-
agentId: 'code-reviewer',
|
|
28
|
-
dataDir: join(__dirname, 'intelligence', 'data'),
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
const tag = PERSONA.name.toLowerCase();
|
|
32
|
-
|
|
33
|
-
// Seed built-in playbooks (idempotent)
|
|
34
|
-
const seedResult = seedDefaultPlaybooks(runtime.vault);
|
|
35
|
-
if (seedResult.seeded > 0) {
|
|
36
|
-
console.error(`[${tag}] Seeded ${seedResult.seeded} built-in playbooks`);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const stats = runtime.vault.stats();
|
|
40
|
-
console.error(`[${tag}] Vault: ${stats.totalEntries} entries, Brain: ${runtime.brain.getVocabularySize()} terms`);
|
|
41
|
-
|
|
42
|
-
const llmAvail = runtime.llmClient.isAvailable();
|
|
43
|
-
console.error(`[${tag}] LLM: OpenAI ${llmAvail.openai ? 'available' : 'not configured'}, Anthropic ${llmAvail.anthropic ? 'available' : 'not configured'}`);
|
|
44
|
-
|
|
45
|
-
// ─── Agent-specific ops (reference persona + activation) ────────
|
|
46
|
-
const agentOps: OpDefinition[] = [
|
|
47
|
-
{
|
|
48
|
-
name: 'health',
|
|
49
|
-
description: 'Health check — vault status and agent info.',
|
|
50
|
-
auth: 'read',
|
|
51
|
-
handler: async () => {
|
|
52
|
-
const s = runtime.vault.stats();
|
|
53
|
-
return {
|
|
54
|
-
status: 'ok',
|
|
55
|
-
agent: { name: PERSONA.name, role: PERSONA.role },
|
|
56
|
-
vault: { entries: s.totalEntries, domains: Object.keys(s.byDomain) },
|
|
57
|
-
};
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
name: 'identity',
|
|
62
|
-
description: 'Get agent identity — name, role, principles. Uses IdentityManager with PERSONA fallback.',
|
|
63
|
-
auth: 'read',
|
|
64
|
-
handler: async () => {
|
|
65
|
-
const identity = runtime.identityManager.getIdentity('code-reviewer');
|
|
66
|
-
if (identity) return identity;
|
|
67
|
-
return PERSONA;
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
name: 'activate',
|
|
72
|
-
description: 'Activate agent persona — returns full context for Claude to adopt. Say "Hello, Code Reviewer!" to trigger.',
|
|
73
|
-
auth: 'read',
|
|
74
|
-
schema: z.object({
|
|
75
|
-
projectPath: z.string().optional().default('.'),
|
|
76
|
-
deactivate: z.boolean().optional(),
|
|
77
|
-
}),
|
|
78
|
-
handler: async (params) => {
|
|
79
|
-
if (params.deactivate) {
|
|
80
|
-
return deactivateAgent();
|
|
81
|
-
}
|
|
82
|
-
// Seed identity from PERSONA on first activation
|
|
83
|
-
if (!runtime.identityManager.getIdentity('code-reviewer')) {
|
|
84
|
-
runtime.identityManager.setIdentity('code-reviewer', {
|
|
85
|
-
name: PERSONA.name,
|
|
86
|
-
role: PERSONA.role,
|
|
87
|
-
description: PERSONA.description ?? '',
|
|
88
|
-
personality: PERSONA.principles ?? [],
|
|
89
|
-
changedBy: 'system',
|
|
90
|
-
changeReason: 'Initial identity seeded from PERSONA',
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
return activateAgent(runtime.vault, (params.projectPath as string) ?? '.', runtime.planner);
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
name: 'inject_claude_md',
|
|
98
|
-
description: 'Inject agent sections into CLAUDE.md — project-level or global (~/.claude/CLAUDE.md). Idempotent.',
|
|
99
|
-
auth: 'write',
|
|
100
|
-
schema: z.object({
|
|
101
|
-
projectPath: z.string().optional().default('.'),
|
|
102
|
-
global: z.boolean().optional().describe('If true, inject into ~/.claude/CLAUDE.md instead of project-level'),
|
|
103
|
-
}),
|
|
104
|
-
handler: async (params) => {
|
|
105
|
-
if (params.global) {
|
|
106
|
-
return injectClaudeMdGlobal();
|
|
107
|
-
}
|
|
108
|
-
return injectClaudeMd((params.projectPath as string) ?? '.');
|
|
109
|
-
},
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
name: 'setup',
|
|
113
|
-
description: 'Check setup status — CLAUDE.md configured? Vault has entries? What to do next?',
|
|
114
|
-
auth: 'read',
|
|
115
|
-
schema: z.object({
|
|
116
|
-
projectPath: z.string().optional().default('.'),
|
|
117
|
-
}),
|
|
118
|
-
handler: async (params) => {
|
|
119
|
-
const { existsSync } = await import('node:fs');
|
|
120
|
-
const { join: joinPath } = await import('node:path');
|
|
121
|
-
const { homedir } = await import('node:os');
|
|
122
|
-
const projectPath = (params.projectPath as string) ?? '.';
|
|
123
|
-
|
|
124
|
-
const projectClaudeMd = joinPath(projectPath, 'CLAUDE.md');
|
|
125
|
-
const globalClaudeMd = joinPath(homedir(), '.claude', 'CLAUDE.md');
|
|
126
|
-
|
|
127
|
-
const projectExists = existsSync(projectClaudeMd);
|
|
128
|
-
const projectHasAgent = hasAgentMarker(projectClaudeMd);
|
|
129
|
-
const globalExists = existsSync(globalClaudeMd);
|
|
130
|
-
const globalHasAgent = hasAgentMarker(globalClaudeMd);
|
|
131
|
-
|
|
132
|
-
const s = runtime.vault.stats();
|
|
133
|
-
|
|
134
|
-
const recommendations: string[] = [];
|
|
135
|
-
if (!globalHasAgent && !projectHasAgent) {
|
|
136
|
-
recommendations.push('No CLAUDE.md configured — run inject_claude_md with global: true for all projects, or without for this project');
|
|
137
|
-
} else if (!globalHasAgent) {
|
|
138
|
-
recommendations.push('Global ~/.claude/CLAUDE.md not configured — run inject_claude_md with global: true to enable in all projects');
|
|
139
|
-
}
|
|
140
|
-
if (s.totalEntries === 0) {
|
|
141
|
-
recommendations.push('Vault is empty — add intelligence data or capture knowledge via domain facades');
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Check hook status
|
|
145
|
-
const { readdirSync } = await import('node:fs');
|
|
146
|
-
const agentClaudeDir = joinPath(__dirname, '..', '.claude');
|
|
147
|
-
const globalClaudeDir = joinPath(homedir(), '.claude');
|
|
148
|
-
|
|
149
|
-
const hookStatus = { agent: [] as string[], global: [] as string[], missing: [] as string[] };
|
|
150
|
-
|
|
151
|
-
if (existsSync(agentClaudeDir)) {
|
|
152
|
-
try {
|
|
153
|
-
const agentHooks = readdirSync(agentClaudeDir)
|
|
154
|
-
.filter((f: string) => f.startsWith('hookify.') && f.endsWith('.local.md'))
|
|
155
|
-
.map((f: string) => f.replace('hookify.', '').replace('.local.md', ''));
|
|
156
|
-
hookStatus.agent = agentHooks;
|
|
157
|
-
|
|
158
|
-
for (const hook of agentHooks) {
|
|
159
|
-
if (existsSync(joinPath(globalClaudeDir, `hookify.${hook}.local.md`))) {
|
|
160
|
-
hookStatus.global.push(hook);
|
|
161
|
-
} else {
|
|
162
|
-
hookStatus.missing.push(hook);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
} catch {
|
|
166
|
-
// ignore read errors
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (hookStatus.missing.length > 0) {
|
|
171
|
-
recommendations.push(`${hookStatus.missing.length} hook(s) not installed globally — run scripts/setup.sh`);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (recommendations.length === 0) {
|
|
175
|
-
recommendations.push('Code Reviewer is fully set up and ready!');
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
return {
|
|
179
|
-
agent: { name: PERSONA.name, role: PERSONA.role },
|
|
180
|
-
claude_md: {
|
|
181
|
-
project: { exists: projectExists, has_agent_section: projectHasAgent },
|
|
182
|
-
global: { exists: globalExists, has_agent_section: globalHasAgent },
|
|
183
|
-
},
|
|
184
|
-
vault: { entries: s.totalEntries, domains: Object.keys(s.byDomain) },
|
|
185
|
-
hooks: hookStatus,
|
|
186
|
-
recommendations,
|
|
187
|
-
};
|
|
188
|
-
},
|
|
189
|
-
},
|
|
190
|
-
];
|
|
191
|
-
|
|
192
|
-
// ─── Assemble facades ──────────────────────────────────────────
|
|
193
|
-
const semanticFacades = createSemanticFacades(runtime, 'code-reviewer');
|
|
194
|
-
const agentFacade = {
|
|
195
|
-
name: 'code-reviewer_core',
|
|
196
|
-
description: 'Agent-specific operations — health, identity, activation, CLAUDE.md injection, setup.',
|
|
197
|
-
ops: agentOps,
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
const domainFacades = createDomainFacades(runtime, 'code-reviewer', ["code-review","architecture"]);
|
|
201
|
-
|
|
202
|
-
// ─── User extensions (auto-discovered from src/extensions/) ────
|
|
203
|
-
let extensions: AgentExtensions = {};
|
|
204
|
-
try {
|
|
205
|
-
const ext = await import('./extensions/index.js');
|
|
206
|
-
const loader = ext.default ?? (ext as Record<string, unknown>).loadExtensions;
|
|
207
|
-
if (typeof loader === 'function') {
|
|
208
|
-
extensions = loader(runtime);
|
|
209
|
-
} else if (typeof loader === 'object') {
|
|
210
|
-
extensions = loader;
|
|
211
|
-
}
|
|
212
|
-
if (extensions.ops?.length || extensions.facades?.length || extensions.middleware?.length) {
|
|
213
|
-
console.error(`[${tag}] Extensions loaded: ${extensions.ops?.length ?? 0} ops, ${extensions.facades?.length ?? 0} facades, ${extensions.middleware?.length ?? 0} middleware`);
|
|
214
|
-
}
|
|
215
|
-
} catch {
|
|
216
|
-
// No extensions directory or load error — run vanilla
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Merge user ops into agent facade
|
|
220
|
-
if (extensions.ops?.length) {
|
|
221
|
-
agentFacade.ops.push(...extensions.ops);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// Collect user facades
|
|
225
|
-
const userFacades = extensions.facades ?? [];
|
|
226
|
-
|
|
227
|
-
// Apply middleware to all facades
|
|
228
|
-
const allFacades = [...semanticFacades, agentFacade, ...domainFacades, ...userFacades];
|
|
229
|
-
if (extensions.middleware?.length) {
|
|
230
|
-
wrapWithMiddleware(allFacades, extensions.middleware);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// Lifecycle: onStartup
|
|
234
|
-
if (extensions.hooks?.onStartup) {
|
|
235
|
-
await extensions.hooks.onStartup(runtime);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// ─── MCP server ────────────────────────────────────────────────
|
|
239
|
-
const server = new McpServer({
|
|
240
|
-
name: 'code-reviewer-mcp',
|
|
241
|
-
version: '1.0.0',
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
server.prompt('persona', 'Get agent persona and principles', async () => ({
|
|
245
|
-
messages: [{ role: 'assistant' as const, content: { type: 'text' as const, text: getPersonaPrompt() } }],
|
|
246
|
-
}));
|
|
247
|
-
|
|
248
|
-
registerAllFacades(server, allFacades);
|
|
249
|
-
|
|
250
|
-
console.error(`[${tag}] ${PERSONA.name} — ${PERSONA.role}`);
|
|
251
|
-
console.error(`[${tag}] Registered ${allFacades.length} facades with ${allFacades.reduce((sum, f) => sum + f.ops.length, 0)} operations`);
|
|
252
|
-
|
|
253
|
-
// ─── Transport + shutdown ──────────────────────────────────────
|
|
254
|
-
const transport = new StdioServerTransport();
|
|
255
|
-
await server.connect(transport);
|
|
256
|
-
console.error(`[${tag}] Connected via stdio transport`);
|
|
257
|
-
console.error(`[${tag}] Say "Hello, ${PERSONA.name}!" to activate`);
|
|
258
|
-
|
|
259
|
-
const shutdown = async (): Promise<void> => {
|
|
260
|
-
console.error(`[${tag}] Shutting down...`);
|
|
261
|
-
if (extensions.hooks?.onShutdown) {
|
|
262
|
-
try {
|
|
263
|
-
await extensions.hooks.onShutdown(runtime);
|
|
264
|
-
} catch (err) {
|
|
265
|
-
console.error(`[${tag}] Extension shutdown error:`, err);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
runtime.close();
|
|
269
|
-
process.exit(0);
|
|
270
|
-
};
|
|
271
|
-
process.on('SIGTERM', shutdown);
|
|
272
|
-
process.on('SIGINT', shutdown);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
main().catch((err) => {
|
|
276
|
-
console.error('[code-reviewer] Fatal error:', err);
|
|
277
|
-
process.exit(1);
|
|
278
|
-
});
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "NodeNext",
|
|
5
|
-
"moduleResolution": "NodeNext",
|
|
6
|
-
"lib": [
|
|
7
|
-
"ES2022"
|
|
8
|
-
],
|
|
9
|
-
"outDir": "dist",
|
|
10
|
-
"rootDir": "src",
|
|
11
|
-
"strict": true,
|
|
12
|
-
"esModuleInterop": true,
|
|
13
|
-
"resolveJsonModule": true,
|
|
14
|
-
"declaration": true,
|
|
15
|
-
"declarationMap": true,
|
|
16
|
-
"sourceMap": true,
|
|
17
|
-
"forceConsistentCasingInFileNames": true,
|
|
18
|
-
"skipLibCheck": true,
|
|
19
|
-
"noEmitOnError": true
|
|
20
|
-
},
|
|
21
|
-
"include": [
|
|
22
|
-
"src/**/*.ts"
|
|
23
|
-
],
|
|
24
|
-
"exclude": [
|
|
25
|
-
"node_modules",
|
|
26
|
-
"dist",
|
|
27
|
-
"src/**/*.test.ts",
|
|
28
|
-
"src/__tests__/**"
|
|
29
|
-
]
|
|
30
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vitest/config';
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
test: {
|
|
5
|
-
environment: 'node',
|
|
6
|
-
pool: 'forks',
|
|
7
|
-
poolOptions: {
|
|
8
|
-
forks: {
|
|
9
|
-
singleFork: true,
|
|
10
|
-
maxForks: 2,
|
|
11
|
-
minForks: 1,
|
|
12
|
-
},
|
|
13
|
-
},
|
|
14
|
-
testTimeout: 30_000,
|
|
15
|
-
hookTimeout: 10_000,
|
|
16
|
-
teardownTimeout: 5_000,
|
|
17
|
-
coverage: {
|
|
18
|
-
provider: 'v8',
|
|
19
|
-
include: ['src/**/*.ts'],
|
|
20
|
-
exclude: ['src/**/*.test.ts', 'src/__tests__/**', 'src/index.ts'],
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
});
|