@soleri/cli 7.0.0 → 8.1.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/package.json +2 -2
- package/src/commands/cognee.ts +16 -13
- package/src/commands/install.ts +69 -10
- package/src/utils/agent-context.ts +0 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soleri/cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.1.0",
|
|
4
4
|
"description": "Developer CLI for creating and managing Soleri AI agents.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@clack/prompts": "^1.0.0",
|
|
44
|
-
"@soleri/core": "^
|
|
44
|
+
"@soleri/core": "^8.0.0",
|
|
45
45
|
"@soleri/forge": "^5.0.0",
|
|
46
46
|
"commander": "^13.0.0"
|
|
47
47
|
},
|
package/src/commands/cognee.ts
CHANGED
|
@@ -8,7 +8,14 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { join } from 'node:path';
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
existsSync,
|
|
13
|
+
readFileSync,
|
|
14
|
+
writeFileSync,
|
|
15
|
+
mkdirSync,
|
|
16
|
+
copyFileSync,
|
|
17
|
+
unlinkSync,
|
|
18
|
+
} from 'node:fs';
|
|
12
19
|
import { homedir } from 'node:os';
|
|
13
20
|
import type { Command } from 'commander';
|
|
14
21
|
import * as p from '@clack/prompts';
|
|
@@ -77,7 +84,9 @@ export function registerCognee(program: Command): void {
|
|
|
77
84
|
copyFileSync(sourceCompose, targetCompose);
|
|
78
85
|
p.log.info(`Copied ${COGNEE_COMPOSE_FILE} to agent project`);
|
|
79
86
|
} else if (!existsSync(targetCompose)) {
|
|
80
|
-
p.log.warn(
|
|
87
|
+
p.log.warn(
|
|
88
|
+
`${COGNEE_COMPOSE_FILE} not found — create one manually or run Cognee externally`,
|
|
89
|
+
);
|
|
81
90
|
}
|
|
82
91
|
|
|
83
92
|
// 3. Update package.json
|
|
@@ -87,9 +96,9 @@ export function registerCognee(program: Command): void {
|
|
|
87
96
|
pkgChanged = true;
|
|
88
97
|
|
|
89
98
|
if (!pkg.scripts) pkg.scripts = {};
|
|
90
|
-
for (const [name,
|
|
99
|
+
for (const [name, script] of Object.entries(COGNEE_SCRIPTS)) {
|
|
91
100
|
if (!pkg.scripts[name]) {
|
|
92
|
-
pkg.scripts[name] =
|
|
101
|
+
pkg.scripts[name] = script;
|
|
93
102
|
pkgChanged = true;
|
|
94
103
|
}
|
|
95
104
|
}
|
|
@@ -295,9 +304,7 @@ export function registerCognee(program: Command): void {
|
|
|
295
304
|
|
|
296
305
|
// Check Docker Compose file
|
|
297
306
|
const composePath = join(ctx.agentPath, COGNEE_COMPOSE_FILE);
|
|
298
|
-
console.log(
|
|
299
|
-
` Docker Compose: ${existsSync(composePath) ? 'present' : 'missing'}`,
|
|
300
|
-
);
|
|
307
|
+
console.log(` Docker Compose: ${existsSync(composePath) ? 'present' : 'missing'}`);
|
|
301
308
|
|
|
302
309
|
// Check npm scripts
|
|
303
310
|
const hasScripts = Object.keys(COGNEE_SCRIPTS).every((s) => !!pkg.scripts?.[s]);
|
|
@@ -333,18 +340,14 @@ export function registerCognee(program: Command): void {
|
|
|
333
340
|
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
334
341
|
const res = await fetch(`${baseUrl}/`, { signal: controller.signal });
|
|
335
342
|
clearTimeout(timeout);
|
|
336
|
-
console.log(
|
|
337
|
-
` Sidecar: ${res.ok ? 'running' : `HTTP ${res.status}`} at ${baseUrl}`,
|
|
338
|
-
);
|
|
343
|
+
console.log(` Sidecar: ${res.ok ? 'running' : `HTTP ${res.status}`} at ${baseUrl}`);
|
|
339
344
|
} catch {
|
|
340
345
|
console.log(` Sidecar: not reachable at ${baseUrl}`);
|
|
341
346
|
}
|
|
342
347
|
|
|
343
348
|
// Overall status
|
|
344
349
|
const ready = enabled && existsSync(configPath);
|
|
345
|
-
console.log(
|
|
346
|
-
`\n Status: ${ready ? 'configured' : 'needs configuration'}`,
|
|
347
|
-
);
|
|
350
|
+
console.log(`\n Status: ${ready ? 'configured' : 'needs configuration'}`);
|
|
348
351
|
if (!existsSync(configPath)) {
|
|
349
352
|
console.log(' Next: Run `soleri cognee setup`');
|
|
350
353
|
} else {
|
package/src/commands/install.ts
CHANGED
|
@@ -85,7 +85,14 @@ function installCodex(agentId: string, agentDir: string, isFileTree: boolean): v
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
function installOpencode(agentId: string, agentDir: string, isFileTree: boolean): void {
|
|
88
|
-
|
|
88
|
+
// OpenCode uses ~/.config/opencode/opencode.json (not ~/.opencode.json)
|
|
89
|
+
// Config uses "mcp" (not "mcpServers"), type "local" (not "stdio"), command as array
|
|
90
|
+
const configDir = join(homedir(), '.config', 'opencode');
|
|
91
|
+
const configPath = join(configDir, 'opencode.json');
|
|
92
|
+
|
|
93
|
+
if (!existsSync(configDir)) {
|
|
94
|
+
mkdirSync(configDir, { recursive: true });
|
|
95
|
+
}
|
|
89
96
|
|
|
90
97
|
let config: Record<string, unknown> = {};
|
|
91
98
|
if (existsSync(configPath)) {
|
|
@@ -98,28 +105,77 @@ function installOpencode(agentId: string, agentDir: string, isFileTree: boolean)
|
|
|
98
105
|
}
|
|
99
106
|
}
|
|
100
107
|
|
|
101
|
-
if (!config.
|
|
102
|
-
config.
|
|
108
|
+
if (!config.mcp || typeof config.mcp !== 'object') {
|
|
109
|
+
config.mcp = {};
|
|
103
110
|
}
|
|
104
111
|
|
|
105
|
-
const servers = config.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
112
|
+
const servers = config.mcp as Record<string, unknown>;
|
|
113
|
+
if (isFileTree) {
|
|
114
|
+
servers[agentId] = {
|
|
115
|
+
type: 'local',
|
|
116
|
+
command: [
|
|
117
|
+
'node',
|
|
118
|
+
join(
|
|
119
|
+
agentDir,
|
|
120
|
+
'..',
|
|
121
|
+
'soleri',
|
|
122
|
+
'packages',
|
|
123
|
+
'core',
|
|
124
|
+
'dist',
|
|
125
|
+
'engine',
|
|
126
|
+
'bin',
|
|
127
|
+
'soleri-engine.js',
|
|
128
|
+
),
|
|
129
|
+
'--agent',
|
|
130
|
+
join(agentDir, 'agent.yaml'),
|
|
131
|
+
],
|
|
132
|
+
};
|
|
133
|
+
} else {
|
|
134
|
+
servers[agentId] = {
|
|
135
|
+
type: 'local',
|
|
136
|
+
command: ['node', join(agentDir, 'dist', 'index.js')],
|
|
137
|
+
};
|
|
138
|
+
}
|
|
109
139
|
|
|
110
140
|
writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', 'utf-8');
|
|
111
|
-
p.log.success(`Registered ${agentId} in ~/.opencode.json`);
|
|
141
|
+
p.log.success(`Registered ${agentId} in ~/.config/opencode/opencode.json`);
|
|
112
142
|
}
|
|
113
143
|
|
|
114
144
|
function escapeRegExp(s: string): string {
|
|
115
145
|
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
116
146
|
}
|
|
117
147
|
|
|
148
|
+
/**
|
|
149
|
+
* Create a global launcher script so the agent can be invoked by name from any directory.
|
|
150
|
+
* e.g., typing `ernesto` opens Claude Code with that agent's MCP config.
|
|
151
|
+
*/
|
|
152
|
+
function installLauncher(agentId: string, agentDir: string): void {
|
|
153
|
+
const binPath = join('/usr/local/bin', agentId);
|
|
154
|
+
|
|
155
|
+
const script = [
|
|
156
|
+
'#!/bin/bash',
|
|
157
|
+
`# ${agentId} — Soleri second brain launcher`,
|
|
158
|
+
`# Type "${agentId}" from any directory to open Claude Code with this agent`,
|
|
159
|
+
`exec claude --mcp-config ${join(agentDir, '.mcp.json')}`,
|
|
160
|
+
'',
|
|
161
|
+
].join('\n');
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
writeFileSync(binPath, script, { mode: 0o755 });
|
|
165
|
+
p.log.success(`Launcher created: type "${agentId}" from any directory to start`);
|
|
166
|
+
} catch {
|
|
167
|
+
p.log.warn(`Could not create launcher at ${binPath} (may need sudo)`);
|
|
168
|
+
p.log.info(
|
|
169
|
+
`To create manually: sudo bash -c 'cat > ${binPath} << "EOF"\\n#!/bin/bash\\nexec claude --mcp-config ${join(agentDir, '.mcp.json')}\\nEOF' && chmod +x ${binPath}`,
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
118
174
|
export function registerInstall(program: Command): void {
|
|
119
175
|
program
|
|
120
176
|
.command('install')
|
|
121
177
|
.argument('[dir]', 'Agent directory (defaults to cwd)')
|
|
122
|
-
.option('--target <target>', 'Registration target:
|
|
178
|
+
.option('--target <target>', 'Registration target: claude, opencode, codex, or all', 'claude')
|
|
123
179
|
.description('Register agent as MCP server in editor config')
|
|
124
180
|
.action(async (dir?: string, opts?: { target?: string }) => {
|
|
125
181
|
const resolvedDir = dir ? resolve(dir) : undefined;
|
|
@@ -130,7 +186,7 @@ export function registerInstall(program: Command): void {
|
|
|
130
186
|
process.exit(1);
|
|
131
187
|
}
|
|
132
188
|
|
|
133
|
-
const target = (opts?.target ?? '
|
|
189
|
+
const target = (opts?.target ?? 'claude') as Target;
|
|
134
190
|
const validTargets: Target[] = ['claude', 'codex', 'opencode', 'both', 'all'];
|
|
135
191
|
const isFileTree = ctx.format === 'filetree';
|
|
136
192
|
|
|
@@ -155,6 +211,9 @@ export function registerInstall(program: Command): void {
|
|
|
155
211
|
installOpencode(ctx.agentId, ctx.agentPath, isFileTree);
|
|
156
212
|
}
|
|
157
213
|
|
|
214
|
+
// Create global launcher script
|
|
215
|
+
installLauncher(ctx.agentId, ctx.agentPath);
|
|
216
|
+
|
|
158
217
|
p.log.info(`Agent ${ctx.agentId} is now available as an MCP server.`);
|
|
159
218
|
});
|
|
160
219
|
}
|
|
@@ -65,11 +65,3 @@ export function detectAgent(dir?: string): AgentContext | null {
|
|
|
65
65
|
return null;
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Detect a file-tree agent specifically (agent.yaml only).
|
|
71
|
-
*/
|
|
72
|
-
export function detectFileTreeAgent(dir?: string): AgentContext | null {
|
|
73
|
-
const ctx = detectAgent(dir);
|
|
74
|
-
return ctx?.format === 'filetree' ? ctx : null;
|
|
75
|
-
}
|