@soleri/cli 1.11.0 → 1.12.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/commands/agent.js +97 -1
- package/dist/commands/agent.js.map +1 -1
- package/dist/main.js +0 -0
- package/package.json +1 -1
- package/src/commands/agent.ts +110 -1
package/dist/commands/agent.js
CHANGED
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
* `soleri agent update` — OTA engine upgrade with migration support.
|
|
6
6
|
*/
|
|
7
7
|
import { join } from 'node:path';
|
|
8
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
8
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
9
9
|
import { execFileSync } from 'node:child_process';
|
|
10
10
|
import * as p from '@clack/prompts';
|
|
11
11
|
import { PackLockfile, checkNpmVersion, checkVersionCompat } from '@soleri/core';
|
|
12
|
+
import { generateClaudeMdTemplate } from '@soleri/forge/lib';
|
|
12
13
|
import { detectAgent } from '../utils/agent-context.js';
|
|
13
14
|
export function registerAgent(program) {
|
|
14
15
|
const agent = program.command('agent').description('Agent lifecycle management');
|
|
@@ -132,6 +133,37 @@ export function registerAgent(program) {
|
|
|
132
133
|
process.exit(1);
|
|
133
134
|
}
|
|
134
135
|
});
|
|
136
|
+
// ─── refresh ────────────────────────────────────────────────
|
|
137
|
+
agent
|
|
138
|
+
.command('refresh')
|
|
139
|
+
.option('--dry-run', 'Preview what would change without writing')
|
|
140
|
+
.description('Regenerate CLAUDE.md content from latest forge templates')
|
|
141
|
+
.action((opts) => {
|
|
142
|
+
const ctx = detectAgent();
|
|
143
|
+
if (!ctx) {
|
|
144
|
+
p.log.error('No agent project detected in current directory.');
|
|
145
|
+
process.exit(1);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
// Reconstruct AgentConfig from the existing agent
|
|
149
|
+
const config = readAgentConfig(ctx.agentPath, ctx.agentId);
|
|
150
|
+
if (!config) {
|
|
151
|
+
p.log.error('Could not read agent config from persona.ts and entry point.');
|
|
152
|
+
process.exit(1);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const targetPath = join(ctx.agentPath, 'src', 'activation', 'claude-md-content.ts');
|
|
156
|
+
const newContent = generateClaudeMdTemplate(config);
|
|
157
|
+
if (opts.dryRun) {
|
|
158
|
+
p.log.info(`Would regenerate: ${targetPath}`);
|
|
159
|
+
p.log.info(`Agent: ${config.name} (${config.domains.length} domains)`);
|
|
160
|
+
p.log.info(`Domains: ${config.domains.join(', ')}`);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
writeFileSync(targetPath, newContent, 'utf-8');
|
|
164
|
+
p.log.success(`Regenerated ${targetPath}`);
|
|
165
|
+
p.log.info('Run `npm run build` to compile, then re-inject CLAUDE.md.');
|
|
166
|
+
});
|
|
135
167
|
// ─── diff ───────────────────────────────────────────────────
|
|
136
168
|
agent
|
|
137
169
|
.command('diff')
|
|
@@ -147,4 +179,68 @@ export function registerAgent(program) {
|
|
|
147
179
|
p.log.info('Full template comparison will be added in a future release.');
|
|
148
180
|
});
|
|
149
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* Reconstruct an AgentConfig from an existing scaffolded agent.
|
|
184
|
+
*
|
|
185
|
+
* Reads persona from src/activation/persona.ts (PERSONA constant)
|
|
186
|
+
* and domains from src/index.ts (createDomainFacades call).
|
|
187
|
+
*/
|
|
188
|
+
function readAgentConfig(agentPath, agentId) {
|
|
189
|
+
// Read persona.ts source to extract PERSONA fields
|
|
190
|
+
// Try both locations: v6+ (src/identity/) and v5 (src/activation/)
|
|
191
|
+
const personaCandidates = [
|
|
192
|
+
join(agentPath, 'src', 'identity', 'persona.ts'),
|
|
193
|
+
join(agentPath, 'src', 'activation', 'persona.ts'),
|
|
194
|
+
];
|
|
195
|
+
const personaPath = personaCandidates.find((p) => existsSync(p));
|
|
196
|
+
if (!personaPath)
|
|
197
|
+
return null;
|
|
198
|
+
const personaSrc = readFileSync(personaPath, 'utf-8');
|
|
199
|
+
const name = extractStringField(personaSrc, 'name') ?? agentId;
|
|
200
|
+
const role = extractStringField(personaSrc, 'role') ?? '';
|
|
201
|
+
const description = extractStringField(personaSrc, 'description') ?? '';
|
|
202
|
+
const tone = extractStringField(personaSrc, 'tone') ?? 'pragmatic';
|
|
203
|
+
const greeting = extractStringField(personaSrc, 'greeting') ?? `Hello! I'm ${name}.`;
|
|
204
|
+
const principles = extractArrayField(personaSrc, 'principles');
|
|
205
|
+
// Read domains from entry point
|
|
206
|
+
const indexPath = join(agentPath, 'src', 'index.ts');
|
|
207
|
+
const domains = existsSync(indexPath) ? extractDomains(readFileSync(indexPath, 'utf-8')) : [];
|
|
208
|
+
// Read hookPacks from .claude/ if present
|
|
209
|
+
const hookPacks = [];
|
|
210
|
+
// Read package.json for outputDir
|
|
211
|
+
const pkg = JSON.parse(readFileSync(join(agentPath, 'package.json'), 'utf-8'));
|
|
212
|
+
return {
|
|
213
|
+
id: agentId,
|
|
214
|
+
name,
|
|
215
|
+
role,
|
|
216
|
+
description,
|
|
217
|
+
domains,
|
|
218
|
+
principles,
|
|
219
|
+
tone,
|
|
220
|
+
greeting,
|
|
221
|
+
outputDir: agentPath,
|
|
222
|
+
hookPacks,
|
|
223
|
+
setupTarget: pkg.soleri?.setupTarget ?? 'claude',
|
|
224
|
+
telegram: false,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
function extractStringField(src, field) {
|
|
228
|
+
const re = new RegExp(`${field}:\\s*'([^']*)'`);
|
|
229
|
+
const m = src.match(re);
|
|
230
|
+
return m ? m[1].replace(/\\'/g, "'") : undefined;
|
|
231
|
+
}
|
|
232
|
+
function extractArrayField(src, field) {
|
|
233
|
+
const re = new RegExp(`${field}:\\s*\\[([\\s\\S]*?)\\]`);
|
|
234
|
+
const m = src.match(re);
|
|
235
|
+
if (!m)
|
|
236
|
+
return [];
|
|
237
|
+
return [...m[1].matchAll(/'([^']*)'/g)].map((x) => x[1]);
|
|
238
|
+
}
|
|
239
|
+
function extractDomains(indexSrc) {
|
|
240
|
+
const m = indexSrc.match(/createDomainFacades\(runtime,\s*['"][^'"]+['"]\s*,\s*\[([\s\S]*?)\]\)/);
|
|
241
|
+
if (!m)
|
|
242
|
+
return [];
|
|
243
|
+
// Match both single and double quoted strings
|
|
244
|
+
return [...m[1].matchAll(/['"]([^'"]+)['"]/g)].map((x) => x[1]);
|
|
245
|
+
}
|
|
150
246
|
//# sourceMappingURL=agent.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/commands/agent.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/commands/agent.ts"],"names":[],"mappings":"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"}
|
package/dist/main.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
package/src/commands/agent.ts
CHANGED
|
@@ -6,11 +6,13 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { join } from 'node:path';
|
|
9
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
9
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
10
10
|
import { execFileSync } from 'node:child_process';
|
|
11
11
|
import type { Command } from 'commander';
|
|
12
12
|
import * as p from '@clack/prompts';
|
|
13
13
|
import { PackLockfile, checkNpmVersion, checkVersionCompat } from '@soleri/core';
|
|
14
|
+
import { generateClaudeMdTemplate } from '@soleri/forge/lib';
|
|
15
|
+
import type { AgentConfig } from '@soleri/forge/lib';
|
|
14
16
|
import { detectAgent } from '../utils/agent-context.js';
|
|
15
17
|
|
|
16
18
|
export function registerAgent(program: Command): void {
|
|
@@ -163,6 +165,42 @@ export function registerAgent(program: Command): void {
|
|
|
163
165
|
}
|
|
164
166
|
});
|
|
165
167
|
|
|
168
|
+
// ─── refresh ────────────────────────────────────────────────
|
|
169
|
+
agent
|
|
170
|
+
.command('refresh')
|
|
171
|
+
.option('--dry-run', 'Preview what would change without writing')
|
|
172
|
+
.description('Regenerate CLAUDE.md content from latest forge templates')
|
|
173
|
+
.action((opts: { dryRun?: boolean }) => {
|
|
174
|
+
const ctx = detectAgent();
|
|
175
|
+
if (!ctx) {
|
|
176
|
+
p.log.error('No agent project detected in current directory.');
|
|
177
|
+
process.exit(1);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Reconstruct AgentConfig from the existing agent
|
|
182
|
+
const config = readAgentConfig(ctx.agentPath, ctx.agentId);
|
|
183
|
+
if (!config) {
|
|
184
|
+
p.log.error('Could not read agent config from persona.ts and entry point.');
|
|
185
|
+
process.exit(1);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const targetPath = join(ctx.agentPath, 'src', 'activation', 'claude-md-content.ts');
|
|
190
|
+
const newContent = generateClaudeMdTemplate(config);
|
|
191
|
+
|
|
192
|
+
if (opts.dryRun) {
|
|
193
|
+
p.log.info(`Would regenerate: ${targetPath}`);
|
|
194
|
+
p.log.info(`Agent: ${config.name} (${config.domains.length} domains)`);
|
|
195
|
+
p.log.info(`Domains: ${config.domains.join(', ')}`);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
writeFileSync(targetPath, newContent, 'utf-8');
|
|
200
|
+
p.log.success(`Regenerated ${targetPath}`);
|
|
201
|
+
p.log.info('Run `npm run build` to compile, then re-inject CLAUDE.md.');
|
|
202
|
+
});
|
|
203
|
+
|
|
166
204
|
// ─── diff ───────────────────────────────────────────────────
|
|
167
205
|
agent
|
|
168
206
|
.command('diff')
|
|
@@ -179,3 +217,74 @@ export function registerAgent(program: Command): void {
|
|
|
179
217
|
p.log.info('Full template comparison will be added in a future release.');
|
|
180
218
|
});
|
|
181
219
|
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Reconstruct an AgentConfig from an existing scaffolded agent.
|
|
223
|
+
*
|
|
224
|
+
* Reads persona from src/activation/persona.ts (PERSONA constant)
|
|
225
|
+
* and domains from src/index.ts (createDomainFacades call).
|
|
226
|
+
*/
|
|
227
|
+
function readAgentConfig(agentPath: string, agentId: string): AgentConfig | null {
|
|
228
|
+
// Read persona.ts source to extract PERSONA fields
|
|
229
|
+
// Try both locations: v6+ (src/identity/) and v5 (src/activation/)
|
|
230
|
+
const personaCandidates = [
|
|
231
|
+
join(agentPath, 'src', 'identity', 'persona.ts'),
|
|
232
|
+
join(agentPath, 'src', 'activation', 'persona.ts'),
|
|
233
|
+
];
|
|
234
|
+
const personaPath = personaCandidates.find((p) => existsSync(p));
|
|
235
|
+
if (!personaPath) return null;
|
|
236
|
+
const personaSrc = readFileSync(personaPath, 'utf-8');
|
|
237
|
+
|
|
238
|
+
const name = extractStringField(personaSrc, 'name') ?? agentId;
|
|
239
|
+
const role = extractStringField(personaSrc, 'role') ?? '';
|
|
240
|
+
const description = extractStringField(personaSrc, 'description') ?? '';
|
|
241
|
+
const tone =
|
|
242
|
+
(extractStringField(personaSrc, 'tone') as 'precise' | 'mentor' | 'pragmatic') ?? 'pragmatic';
|
|
243
|
+
const greeting = extractStringField(personaSrc, 'greeting') ?? `Hello! I'm ${name}.`;
|
|
244
|
+
const principles = extractArrayField(personaSrc, 'principles');
|
|
245
|
+
|
|
246
|
+
// Read domains from entry point
|
|
247
|
+
const indexPath = join(agentPath, 'src', 'index.ts');
|
|
248
|
+
const domains = existsSync(indexPath) ? extractDomains(readFileSync(indexPath, 'utf-8')) : [];
|
|
249
|
+
|
|
250
|
+
// Read hookPacks from .claude/ if present
|
|
251
|
+
const hookPacks: string[] = [];
|
|
252
|
+
|
|
253
|
+
// Read package.json for outputDir
|
|
254
|
+
const pkg = JSON.parse(readFileSync(join(agentPath, 'package.json'), 'utf-8'));
|
|
255
|
+
|
|
256
|
+
return {
|
|
257
|
+
id: agentId,
|
|
258
|
+
name,
|
|
259
|
+
role,
|
|
260
|
+
description,
|
|
261
|
+
domains,
|
|
262
|
+
principles,
|
|
263
|
+
tone,
|
|
264
|
+
greeting,
|
|
265
|
+
outputDir: agentPath,
|
|
266
|
+
hookPacks,
|
|
267
|
+
setupTarget: pkg.soleri?.setupTarget ?? 'claude',
|
|
268
|
+
telegram: false,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function extractStringField(src: string, field: string): string | undefined {
|
|
273
|
+
const re = new RegExp(`${field}:\\s*'([^']*)'`);
|
|
274
|
+
const m = src.match(re);
|
|
275
|
+
return m ? m[1].replace(/\\'/g, "'") : undefined;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function extractArrayField(src: string, field: string): string[] {
|
|
279
|
+
const re = new RegExp(`${field}:\\s*\\[([\\s\\S]*?)\\]`);
|
|
280
|
+
const m = src.match(re);
|
|
281
|
+
if (!m) return [];
|
|
282
|
+
return [...m[1].matchAll(/'([^']*)'/g)].map((x) => x[1]);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function extractDomains(indexSrc: string): string[] {
|
|
286
|
+
const m = indexSrc.match(/createDomainFacades\(runtime,\s*['"][^'"]+['"]\s*,\s*\[([\s\S]*?)\]\)/);
|
|
287
|
+
if (!m) return [];
|
|
288
|
+
// Match both single and double quoted strings
|
|
289
|
+
return [...m[1].matchAll(/['"]([^'"]+)['"]/g)].map((x) => x[1]);
|
|
290
|
+
}
|