@soleri/cli 1.12.4 → 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/commands/add-pack.d.ts +2 -0
- package/dist/commands/add-pack.js +154 -0
- package/dist/commands/add-pack.js.map +1 -0
- package/dist/commands/agent.js +152 -3
- package/dist/commands/agent.js.map +1 -1
- package/dist/commands/cognee.d.ts +10 -0
- package/dist/commands/cognee.js +364 -0
- package/dist/commands/cognee.js.map +1 -0
- package/dist/commands/create.js +63 -5
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/dev.js +104 -17
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/install.js +70 -18
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/telegram.d.ts +10 -0
- package/dist/commands/telegram.js +423 -0
- package/dist/commands/telegram.js.map +1 -0
- package/dist/commands/uninstall.js +35 -6
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/main.js +6 -0
- package/dist/main.js.map +1 -1
- package/dist/prompts/create-wizard.js +87 -6
- package/dist/prompts/create-wizard.js.map +1 -1
- package/dist/prompts/playbook.js +1 -1
- package/dist/prompts/playbook.js.map +1 -1
- package/dist/utils/agent-context.d.ts +9 -2
- package/dist/utils/agent-context.js +32 -0
- package/dist/utils/agent-context.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/add-pack.ts +170 -0
- package/src/commands/agent.ts +174 -3
- package/src/commands/cognee.ts +416 -0
- package/src/commands/create.ts +90 -6
- package/src/commands/dev.ts +114 -18
- package/src/commands/install.ts +78 -19
- package/src/commands/telegram.ts +488 -0
- package/src/commands/uninstall.ts +41 -7
- package/src/main.ts +6 -0
- package/src/prompts/create-wizard.ts +93 -7
- package/src/prompts/playbook.ts +1 -1
- package/src/utils/agent-context.ts +39 -2
package/src/commands/create.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
AgentConfigSchema,
|
|
9
9
|
SETUP_TARGETS,
|
|
10
10
|
type SetupTarget,
|
|
11
|
+
scaffoldFileTree,
|
|
11
12
|
} from '@soleri/forge/lib';
|
|
12
13
|
import { runCreateWizard } from '../prompts/create-wizard.js';
|
|
13
14
|
import { listPacks } from '../hook-packs/registry.js';
|
|
@@ -21,9 +22,9 @@ function parseSetupTarget(value?: string): SetupTarget | undefined {
|
|
|
21
22
|
return undefined;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
function includesClaudeSetup(target: SetupTarget | undefined): boolean {
|
|
25
|
-
const resolved = target ?? '
|
|
26
|
-
return resolved === 'claude' || resolved === 'both';
|
|
25
|
+
function includesClaudeSetup(target: SetupTarget | string | undefined): boolean {
|
|
26
|
+
const resolved = target ?? 'opencode';
|
|
27
|
+
return resolved === 'claude' || resolved === 'both' || resolved === 'all';
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
export function registerCreate(program: Command): void {
|
|
@@ -36,9 +37,20 @@ export function registerCreate(program: Command): void {
|
|
|
36
37
|
`Setup target: ${SETUP_TARGETS.join(', ')} (default: claude)`,
|
|
37
38
|
)
|
|
38
39
|
.option('-y, --yes', 'Skip confirmation prompts (use with --config for fully non-interactive)')
|
|
40
|
+
.option('--filetree', 'Create a file-tree agent (v7 — no TypeScript, no build step)')
|
|
41
|
+
.option('--legacy', 'Create a legacy TypeScript agent (v6 — requires npm install + build)')
|
|
39
42
|
.description('Create a new Soleri agent')
|
|
40
43
|
.action(
|
|
41
|
-
async (
|
|
44
|
+
async (
|
|
45
|
+
name?: string,
|
|
46
|
+
opts?: {
|
|
47
|
+
config?: string;
|
|
48
|
+
yes?: boolean;
|
|
49
|
+
setupTarget?: string;
|
|
50
|
+
filetree?: boolean;
|
|
51
|
+
legacy?: boolean;
|
|
52
|
+
},
|
|
53
|
+
) => {
|
|
42
54
|
try {
|
|
43
55
|
let config;
|
|
44
56
|
|
|
@@ -81,6 +93,78 @@ export function registerCreate(program: Command): void {
|
|
|
81
93
|
if (setupTarget) {
|
|
82
94
|
config = { ...config, setupTarget };
|
|
83
95
|
}
|
|
96
|
+
// ─── File-tree agent (v7) ──────────────────────────────
|
|
97
|
+
// Default to filetree unless --legacy is explicitly passed
|
|
98
|
+
const useFileTree = opts?.filetree || !opts?.legacy;
|
|
99
|
+
|
|
100
|
+
if (useFileTree) {
|
|
101
|
+
// Convert to AgentYaml format
|
|
102
|
+
// Cast to Record to access fields that may exist on the parsed config
|
|
103
|
+
// but aren't in the strict AgentConfig type (model, cognee, vaults, domainPacks)
|
|
104
|
+
const raw = config as Record<string, unknown>;
|
|
105
|
+
const agentYamlInput = {
|
|
106
|
+
id: config.id,
|
|
107
|
+
name: config.name,
|
|
108
|
+
role: config.role,
|
|
109
|
+
description: config.description,
|
|
110
|
+
domains: config.domains,
|
|
111
|
+
principles: config.principles,
|
|
112
|
+
tone: config.tone,
|
|
113
|
+
greeting: config.greeting,
|
|
114
|
+
setup: {
|
|
115
|
+
target: config.setupTarget,
|
|
116
|
+
model: (raw.model as string) ?? 'claude-code-sonnet-4',
|
|
117
|
+
},
|
|
118
|
+
engine: {
|
|
119
|
+
cognee: (raw.cognee as boolean) ?? false,
|
|
120
|
+
},
|
|
121
|
+
vaults: raw.vaults as
|
|
122
|
+
| Array<{ name: string; path: string; priority?: number }>
|
|
123
|
+
| undefined,
|
|
124
|
+
packs: (
|
|
125
|
+
raw.domainPacks as
|
|
126
|
+
| Array<{ name: string; package: string; version?: string }>
|
|
127
|
+
| undefined
|
|
128
|
+
)?.map((dp) => ({
|
|
129
|
+
name: dp.name,
|
|
130
|
+
package: dp.package,
|
|
131
|
+
version: dp.version,
|
|
132
|
+
})),
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const outputDir = config.outputDir ?? process.cwd();
|
|
136
|
+
const nonInteractive = !!(opts?.yes || opts?.config);
|
|
137
|
+
|
|
138
|
+
if (!nonInteractive) {
|
|
139
|
+
p.log.info(
|
|
140
|
+
`Will create file-tree agent "${config.name}" in ${outputDir}/${config.id}`,
|
|
141
|
+
);
|
|
142
|
+
p.log.info(`Domains: ${config.domains.join(', ')}`);
|
|
143
|
+
p.log.info('No build step — agent is ready to use immediately.');
|
|
144
|
+
|
|
145
|
+
const confirmed = await p.confirm({ message: 'Create agent?' });
|
|
146
|
+
if (p.isCancel(confirmed) || !confirmed) {
|
|
147
|
+
p.outro('Cancelled.');
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const s = p.spinner();
|
|
153
|
+
s.start('Creating file-tree agent...');
|
|
154
|
+
const result = scaffoldFileTree(agentYamlInput, outputDir);
|
|
155
|
+
s.stop(result.success ? 'Agent created!' : 'Creation failed');
|
|
156
|
+
|
|
157
|
+
if (!result.success) {
|
|
158
|
+
p.log.error(result.summary);
|
|
159
|
+
process.exit(1);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
p.note(result.summary, 'Next steps');
|
|
163
|
+
p.outro('Done!');
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ─── Legacy TypeScript agent (v6) ─────────────────────
|
|
84
168
|
const claudeSetup = includesClaudeSetup(config.setupTarget);
|
|
85
169
|
|
|
86
170
|
const nonInteractive = !!(opts?.yes || opts?.config);
|
|
@@ -98,9 +182,9 @@ export function registerCreate(program: Command): void {
|
|
|
98
182
|
const available = listPacks().map((pk) => pk.name);
|
|
99
183
|
const unknown = selectedPacks.filter((pk) => !available.includes(pk));
|
|
100
184
|
if (unknown.length > 0) {
|
|
101
|
-
for (const
|
|
185
|
+
for (const packName of unknown) {
|
|
102
186
|
p.log.warn(
|
|
103
|
-
`Unknown hook pack "${
|
|
187
|
+
`Unknown hook pack "${packName}" — skipping. Available: ${available.join(', ')}`,
|
|
104
188
|
);
|
|
105
189
|
}
|
|
106
190
|
selectedPacks = selectedPacks.filter((pk) => available.includes(pk));
|
package/src/commands/dev.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
|
+
import { watch, writeFileSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
2
4
|
import type { Command } from 'commander';
|
|
3
5
|
import * as p from '@clack/prompts';
|
|
4
6
|
import { detectAgent } from '../utils/agent-context.js';
|
|
@@ -14,26 +16,120 @@ export function registerDev(program: Command): void {
|
|
|
14
16
|
process.exit(1);
|
|
15
17
|
}
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
if (ctx.format === 'filetree') {
|
|
20
|
+
// v7: File-tree agent — watch files and regenerate CLAUDE.md
|
|
21
|
+
runFileTreeDev(ctx.agentPath, ctx.agentId);
|
|
22
|
+
} else {
|
|
23
|
+
// Legacy: TypeScript agent — run via tsx
|
|
24
|
+
runLegacyDev(ctx.agentPath, ctx.agentId);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
18
28
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
29
|
+
function runFileTreeDev(agentPath: string, agentId: string): void {
|
|
30
|
+
p.log.info(`Starting ${agentId} in file-tree dev mode...`);
|
|
31
|
+
p.log.info('Starting Knowledge Engine + watching for file changes.');
|
|
32
|
+
p.log.info('CLAUDE.md will be regenerated automatically on changes.');
|
|
33
|
+
p.log.info('Press Ctrl+C to stop.\n');
|
|
24
34
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
35
|
+
regenerateClaudeMd(agentPath);
|
|
36
|
+
|
|
37
|
+
// Start the engine server
|
|
38
|
+
const engineBin = require.resolve('@soleri/core/dist/engine/bin/soleri-engine.js');
|
|
39
|
+
const engine = spawn('node', [engineBin, '--agent', join(agentPath, 'agent.yaml')], {
|
|
40
|
+
stdio: ['pipe', 'inherit', 'inherit'],
|
|
41
|
+
env: { ...process.env },
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
engine.on('error', (err) => {
|
|
45
|
+
p.log.error(`Engine failed to start: ${err.message}`);
|
|
46
|
+
p.log.info('Make sure @soleri/core is built: cd packages/core && npm run build');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Watch directories for changes
|
|
50
|
+
const watchPaths = [
|
|
51
|
+
join(agentPath, 'agent.yaml'),
|
|
52
|
+
join(agentPath, 'instructions'),
|
|
53
|
+
join(agentPath, 'workflows'),
|
|
54
|
+
join(agentPath, 'skills'),
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
let debounceTimer: ReturnType<typeof setTimeout> | null = null;
|
|
58
|
+
|
|
59
|
+
for (const watchPath of watchPaths) {
|
|
60
|
+
try {
|
|
61
|
+
watch(watchPath, { recursive: true }, (_event, filename) => {
|
|
62
|
+
// Ignore CLAUDE.md changes (we generate it)
|
|
63
|
+
if (filename === 'CLAUDE.md' || filename === 'AGENTS.md') return;
|
|
64
|
+
// Ignore _engine.md changes (we generate it)
|
|
65
|
+
if (filename === '_engine.md') return;
|
|
30
66
|
|
|
31
|
-
|
|
32
|
-
if (
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
67
|
+
// Debounce — regenerate at most once per 200ms
|
|
68
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
69
|
+
debounceTimer = setTimeout(() => {
|
|
70
|
+
const changedFile = filename ? ` (${filename})` : '';
|
|
71
|
+
p.log.info(`Change detected${changedFile} — regenerating CLAUDE.md`);
|
|
72
|
+
regenerateClaudeMd(agentPath);
|
|
73
|
+
}, 200);
|
|
37
74
|
});
|
|
38
|
-
}
|
|
75
|
+
} catch {
|
|
76
|
+
// Directory may not exist yet — that's OK
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Graceful shutdown — kill engine too
|
|
81
|
+
const shutdown = () => {
|
|
82
|
+
p.log.info('\nStopping dev mode...');
|
|
83
|
+
engine.kill();
|
|
84
|
+
process.exit(0);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
process.on('SIGINT', shutdown);
|
|
88
|
+
process.on('SIGTERM', shutdown);
|
|
89
|
+
|
|
90
|
+
engine.on('exit', (code) => {
|
|
91
|
+
if (code !== 0 && code !== null) {
|
|
92
|
+
p.log.error(`Engine exited with code ${code}`);
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function regenerateClaudeMd(agentPath: string): void {
|
|
99
|
+
try {
|
|
100
|
+
// Dynamic import to avoid loading forge at CLI startup
|
|
101
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
102
|
+
const { composeClaudeMd } = require('@soleri/forge/lib');
|
|
103
|
+
const { content } = composeClaudeMd(agentPath);
|
|
104
|
+
writeFileSync(join(agentPath, 'CLAUDE.md'), content, 'utf-8');
|
|
105
|
+
p.log.success('CLAUDE.md regenerated');
|
|
106
|
+
} catch (err) {
|
|
107
|
+
p.log.error(
|
|
108
|
+
`Failed to regenerate CLAUDE.md: ${err instanceof Error ? err.message : String(err)}`,
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function runLegacyDev(agentPath: string, agentId: string): void {
|
|
114
|
+
p.log.info(`Starting ${agentId} in dev mode...`);
|
|
115
|
+
|
|
116
|
+
const child = spawn('npx', ['tsx', 'src/index.ts'], {
|
|
117
|
+
cwd: agentPath,
|
|
118
|
+
stdio: 'inherit',
|
|
119
|
+
env: { ...process.env },
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
child.on('error', (err) => {
|
|
123
|
+
p.log.error(`Failed to start: ${err.message}`);
|
|
124
|
+
p.log.info('Make sure tsx is available: npm install -g tsx');
|
|
125
|
+
process.exit(1);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
child.on('exit', (code, signal) => {
|
|
129
|
+
if (signal) {
|
|
130
|
+
p.log.warn(`Process terminated by signal ${signal}`);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
process.exit(code ?? 0);
|
|
134
|
+
});
|
|
39
135
|
}
|
package/src/commands/install.ts
CHANGED
|
@@ -5,9 +5,28 @@ import { homedir } from 'node:os';
|
|
|
5
5
|
import * as p from '@clack/prompts';
|
|
6
6
|
import { detectAgent } from '../utils/agent-context.js';
|
|
7
7
|
|
|
8
|
-
type Target = 'claude' | 'codex' | 'both';
|
|
8
|
+
type Target = 'claude' | 'codex' | 'opencode' | 'both' | 'all';
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
/** MCP server entry for file-tree agents (uses npx @soleri/engine) */
|
|
11
|
+
function fileTreeMcpEntry(agentDir: string): Record<string, unknown> {
|
|
12
|
+
return {
|
|
13
|
+
type: 'stdio',
|
|
14
|
+
command: 'npx',
|
|
15
|
+
args: ['@soleri/engine', '--agent', join(agentDir, 'agent.yaml')],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** MCP server entry for legacy TypeScript agents (uses node dist/index.js) */
|
|
20
|
+
function legacyMcpEntry(agentDir: string): Record<string, unknown> {
|
|
21
|
+
return {
|
|
22
|
+
type: 'stdio',
|
|
23
|
+
command: 'node',
|
|
24
|
+
args: [join(agentDir, 'dist', 'index.js')],
|
|
25
|
+
env: {},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function installClaude(agentId: string, agentDir: string, isFileTree: boolean): void {
|
|
11
30
|
const configPath = join(homedir(), '.claude.json');
|
|
12
31
|
let config: Record<string, unknown> = {};
|
|
13
32
|
|
|
@@ -24,18 +43,15 @@ function installClaude(agentId: string, agentDir: string): void {
|
|
|
24
43
|
config.mcpServers = {};
|
|
25
44
|
}
|
|
26
45
|
|
|
27
|
-
(config.mcpServers as Record<string, unknown>)[agentId] =
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
args: [join(agentDir, 'dist', 'index.js')],
|
|
31
|
-
env: {},
|
|
32
|
-
};
|
|
46
|
+
(config.mcpServers as Record<string, unknown>)[agentId] = isFileTree
|
|
47
|
+
? fileTreeMcpEntry(agentDir)
|
|
48
|
+
: legacyMcpEntry(agentDir);
|
|
33
49
|
|
|
34
50
|
writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', 'utf-8');
|
|
35
51
|
p.log.success(`Registered ${agentId} in ~/.claude.json`);
|
|
36
52
|
}
|
|
37
53
|
|
|
38
|
-
function installCodex(agentId: string, agentDir: string): void {
|
|
54
|
+
function installCodex(agentId: string, agentDir: string, isFileTree: boolean): void {
|
|
39
55
|
const codexDir = join(homedir(), '.codex');
|
|
40
56
|
const configPath = join(codexDir, 'config.toml');
|
|
41
57
|
|
|
@@ -53,8 +69,14 @@ function installCodex(agentId: string, agentDir: string): void {
|
|
|
53
69
|
const sectionRegex = new RegExp(`\\[mcp_servers\\.${escapeRegExp(agentId)}\\][^\\[]*`, 's');
|
|
54
70
|
content = content.replace(sectionRegex, '').trim();
|
|
55
71
|
|
|
56
|
-
|
|
57
|
-
|
|
72
|
+
let section: string;
|
|
73
|
+
if (isFileTree) {
|
|
74
|
+
const agentYamlPath = join(agentDir, 'agent.yaml');
|
|
75
|
+
section = `\n\n${sectionHeader}\ncommand = "npx"\nargs = ["@soleri/engine", "--agent", "${agentYamlPath}"]\n`;
|
|
76
|
+
} else {
|
|
77
|
+
const entryPoint = join(agentDir, 'dist', 'index.js');
|
|
78
|
+
section = `\n\n${sectionHeader}\ncommand = "node"\nargs = ["${entryPoint}"]\n`;
|
|
79
|
+
}
|
|
58
80
|
|
|
59
81
|
content = content + section;
|
|
60
82
|
|
|
@@ -62,6 +84,33 @@ function installCodex(agentId: string, agentDir: string): void {
|
|
|
62
84
|
p.log.success(`Registered ${agentId} in ~/.codex/config.toml`);
|
|
63
85
|
}
|
|
64
86
|
|
|
87
|
+
function installOpencode(agentId: string, agentDir: string, isFileTree: boolean): void {
|
|
88
|
+
const configPath = join(homedir(), '.opencode.json');
|
|
89
|
+
|
|
90
|
+
let config: Record<string, unknown> = {};
|
|
91
|
+
if (existsSync(configPath)) {
|
|
92
|
+
try {
|
|
93
|
+
const raw = readFileSync(configPath, 'utf-8');
|
|
94
|
+
const stripped = raw.replace(/^\s*\/\/.*$/gm, '');
|
|
95
|
+
config = JSON.parse(stripped);
|
|
96
|
+
} catch {
|
|
97
|
+
config = {};
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (!config.mcpServers || typeof config.mcpServers !== 'object') {
|
|
102
|
+
config.mcpServers = {};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const servers = config.mcpServers as Record<string, unknown>;
|
|
106
|
+
servers[agentId] = isFileTree
|
|
107
|
+
? fileTreeMcpEntry(agentDir)
|
|
108
|
+
: { type: 'stdio', command: 'node', args: [join(agentDir, 'dist', 'index.js')] };
|
|
109
|
+
|
|
110
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', 'utf-8');
|
|
111
|
+
p.log.success(`Registered ${agentId} in ~/.opencode.json`);
|
|
112
|
+
}
|
|
113
|
+
|
|
65
114
|
function escapeRegExp(s: string): string {
|
|
66
115
|
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
67
116
|
}
|
|
@@ -70,7 +119,7 @@ export function registerInstall(program: Command): void {
|
|
|
70
119
|
program
|
|
71
120
|
.command('install')
|
|
72
121
|
.argument('[dir]', 'Agent directory (defaults to cwd)')
|
|
73
|
-
.option('--target <target>', 'Registration target: claude, codex, or
|
|
122
|
+
.option('--target <target>', 'Registration target: opencode, claude, codex, or all', 'opencode')
|
|
74
123
|
.description('Register agent as MCP server in editor config')
|
|
75
124
|
.action(async (dir?: string, opts?: { target?: string }) => {
|
|
76
125
|
const resolvedDir = dir ? resolve(dir) : undefined;
|
|
@@ -81,19 +130,29 @@ export function registerInstall(program: Command): void {
|
|
|
81
130
|
process.exit(1);
|
|
82
131
|
}
|
|
83
132
|
|
|
84
|
-
const target = (opts?.target ?? '
|
|
133
|
+
const target = (opts?.target ?? 'opencode') as Target;
|
|
134
|
+
const validTargets: Target[] = ['claude', 'codex', 'opencode', 'both', 'all'];
|
|
135
|
+
const isFileTree = ctx.format === 'filetree';
|
|
85
136
|
|
|
86
|
-
if (target
|
|
87
|
-
p.log.error(`Invalid target "${target}". Use:
|
|
137
|
+
if (!validTargets.includes(target)) {
|
|
138
|
+
p.log.error(`Invalid target "${target}". Use: ${validTargets.join(', ')}`);
|
|
88
139
|
process.exit(1);
|
|
89
140
|
}
|
|
90
141
|
|
|
91
|
-
if (
|
|
92
|
-
|
|
142
|
+
if (isFileTree) {
|
|
143
|
+
p.log.info(`Detected file-tree agent (v7) — registering via @soleri/engine`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (target === 'claude' || target === 'both' || target === 'all') {
|
|
147
|
+
installClaude(ctx.agentId, ctx.agentPath, isFileTree);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (target === 'codex' || target === 'both' || target === 'all') {
|
|
151
|
+
installCodex(ctx.agentId, ctx.agentPath, isFileTree);
|
|
93
152
|
}
|
|
94
153
|
|
|
95
|
-
if (target === '
|
|
96
|
-
|
|
154
|
+
if (target === 'opencode' || target === 'all') {
|
|
155
|
+
installOpencode(ctx.agentId, ctx.agentPath, isFileTree);
|
|
97
156
|
}
|
|
98
157
|
|
|
99
158
|
p.log.info(`Agent ${ctx.agentId} is now available as an MCP server.`);
|