opc-agent 0.5.0 → 0.5.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/dist/channels/web.d.ts +6 -0
- package/dist/channels/web.js +146 -15
- package/dist/cli.js +274 -178
- package/dist/core/agent.d.ts +7 -1
- package/dist/core/agent.js +28 -3
- package/dist/core/runtime.d.ts +0 -3
- package/dist/core/runtime.js +23 -6
- package/dist/providers/index.d.ts +2 -5
- package/dist/providers/index.js +141 -18
- package/dist/schema/oad.d.ts +12 -12
- package/package.json +1 -1
- package/src/channels/web.ts +153 -20
- package/src/cli.ts +310 -202
- package/src/core/agent.ts +36 -3
- package/src/core/runtime.ts +24 -7
- package/src/providers/index.ts +161 -22
- package/tests/e2e.test.ts +134 -0
package/dist/cli.js
CHANGED
|
@@ -50,11 +50,11 @@ const content_writer_1 = require("./templates/content-writer");
|
|
|
50
50
|
const legal_assistant_1 = require("./templates/legal-assistant");
|
|
51
51
|
const financial_advisor_1 = require("./templates/financial-advisor");
|
|
52
52
|
const executive_assistant_1 = require("./templates/executive-assistant");
|
|
53
|
-
const customer_service_2 = require("./templates/customer-service");
|
|
54
53
|
const analytics_1 = require("./analytics");
|
|
55
54
|
const openclaw_1 = require("./deploy/openclaw");
|
|
56
55
|
const workflow_1 = require("./core/workflow");
|
|
57
56
|
const versioning_1 = require("./core/versioning");
|
|
57
|
+
const providers_1 = require("./providers");
|
|
58
58
|
const program = new commander_1.Command();
|
|
59
59
|
const color = {
|
|
60
60
|
green: (s) => `\x1b[32m${s}\x1b[0m`,
|
|
@@ -88,7 +88,7 @@ const TEMPLATES = {
|
|
|
88
88
|
'financial-advisor': { label: 'Financial Advisor - budget analysis + expense tracking + planning', factory: financial_advisor_1.createFinancialAdvisorConfig },
|
|
89
89
|
'executive-assistant': { label: 'Executive Assistant - calendar + email drafting + meeting prep', factory: executive_assistant_1.createExecutiveAssistantConfig },
|
|
90
90
|
};
|
|
91
|
-
async function
|
|
91
|
+
async function promptUser(question, defaultValue) {
|
|
92
92
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
93
93
|
const suffix = defaultValue ? ` ${color.dim(`(${defaultValue})`)}` : '';
|
|
94
94
|
return new Promise((resolve) => {
|
|
@@ -103,23 +103,24 @@ async function select(question, options) {
|
|
|
103
103
|
options.forEach((opt, i) => {
|
|
104
104
|
console.log(` ${color.cyan(`${i + 1})`)} ${opt.label}`);
|
|
105
105
|
});
|
|
106
|
-
const answer = await
|
|
106
|
+
const answer = await promptUser(`\nChoose ${color.dim('(1-' + options.length + ')')}`, '1');
|
|
107
107
|
const idx = parseInt(answer) - 1;
|
|
108
108
|
return options[Math.max(0, Math.min(idx, options.length - 1))].value;
|
|
109
109
|
}
|
|
110
110
|
program
|
|
111
111
|
.name('opc')
|
|
112
112
|
.description('OPC Agent - Open Agent Framework for business workstations')
|
|
113
|
-
.version('0.5.
|
|
113
|
+
.version('0.5.1');
|
|
114
|
+
// ── Init command ─────────────────────────────────────────────
|
|
114
115
|
program
|
|
115
116
|
.command('init')
|
|
116
|
-
.description('Initialize a new OPC agent project
|
|
117
|
+
.description('Initialize a new OPC agent project')
|
|
117
118
|
.argument('[name]', 'Project name')
|
|
118
119
|
.option('-t, --template <template>', 'Template to use')
|
|
119
120
|
.option('-y, --yes', 'Skip prompts, use defaults')
|
|
120
121
|
.action(async (nameArg, opts) => {
|
|
121
122
|
console.log(`\n${icon.rocket} ${color.bold('OPC Agent - Create New Project')}\n`);
|
|
122
|
-
const name = opts.yes ? (nameArg ?? 'my-agent') : (nameArg ?? await
|
|
123
|
+
const name = opts.yes ? (nameArg ?? 'my-agent') : (nameArg ?? await promptUser('Project name', 'my-agent'));
|
|
123
124
|
const template = opts.yes
|
|
124
125
|
? (opts.template ?? 'customer-service')
|
|
125
126
|
: (opts.template ?? await select('Select a template:', Object.entries(TEMPLATES).map(([value, { label }]) => ({ value, label }))));
|
|
@@ -132,27 +133,184 @@ program
|
|
|
132
133
|
const factory = TEMPLATES[template]?.factory ?? customer_service_1.createCustomerServiceConfig;
|
|
133
134
|
const config = factory();
|
|
134
135
|
config.metadata.name = name;
|
|
136
|
+
// Ensure web channel exists
|
|
137
|
+
if (!config.spec.channels.some((c) => c.type === 'web')) {
|
|
138
|
+
config.spec.channels.push({ type: 'web', port: 3000 });
|
|
139
|
+
}
|
|
135
140
|
fs.writeFileSync(path.join(dir, 'oad.yaml'), yaml.dump(config, { lineWidth: 120 }));
|
|
136
|
-
|
|
141
|
+
// .env.example
|
|
142
|
+
fs.writeFileSync(path.join(dir, '.env.example'), `# LLM API Configuration
|
|
143
|
+
OPC_LLM_API_KEY=your-api-key-here
|
|
144
|
+
OPC_LLM_BASE_URL=https://api.openai.com/v1
|
|
145
|
+
OPC_LLM_MODEL=gpt-4o-mini
|
|
146
|
+
|
|
147
|
+
# For DeepSeek:
|
|
148
|
+
# OPC_LLM_BASE_URL=https://api.deepseek.com/v1
|
|
149
|
+
# OPC_LLM_MODEL=deepseek-chat
|
|
150
|
+
|
|
151
|
+
# For local Ollama:
|
|
152
|
+
# OPC_LLM_BASE_URL=http://localhost:11434/v1
|
|
153
|
+
# OPC_LLM_MODEL=llama3
|
|
154
|
+
`);
|
|
155
|
+
// .env (copy of example)
|
|
156
|
+
fs.writeFileSync(path.join(dir, '.env'), `OPC_LLM_API_KEY=your-api-key-here
|
|
157
|
+
OPC_LLM_BASE_URL=https://api.openai.com/v1
|
|
158
|
+
OPC_LLM_MODEL=gpt-4o-mini
|
|
159
|
+
`);
|
|
160
|
+
// package.json
|
|
161
|
+
fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify({
|
|
162
|
+
name,
|
|
163
|
+
version: '1.0.0',
|
|
164
|
+
private: true,
|
|
165
|
+
scripts: {
|
|
166
|
+
start: 'opc run',
|
|
167
|
+
chat: 'opc chat',
|
|
168
|
+
},
|
|
169
|
+
dependencies: {
|
|
170
|
+
'opc-agent': '^0.5.0',
|
|
171
|
+
},
|
|
172
|
+
}, null, 2));
|
|
173
|
+
// .gitignore
|
|
174
|
+
fs.writeFileSync(path.join(dir, '.gitignore'), 'node_modules\n.env\n');
|
|
175
|
+
// README.md
|
|
176
|
+
fs.writeFileSync(path.join(dir, 'README.md'), `# ${name}
|
|
177
|
+
|
|
178
|
+
Created with [OPC Agent](https://github.com/Deepleaper/opc-agent) using the \`${template}\` template.
|
|
179
|
+
|
|
180
|
+
## Quick Start
|
|
181
|
+
|
|
182
|
+
1. **Set your API key:**
|
|
183
|
+
\`\`\`bash
|
|
184
|
+
# Edit .env and add your API key
|
|
185
|
+
cp .env.example .env
|
|
186
|
+
# Then edit .env with your actual key
|
|
187
|
+
\`\`\`
|
|
188
|
+
|
|
189
|
+
2. **Install dependencies:**
|
|
190
|
+
\`\`\`bash
|
|
191
|
+
npm install
|
|
192
|
+
\`\`\`
|
|
193
|
+
|
|
194
|
+
3. **Start the web server:**
|
|
195
|
+
\`\`\`bash
|
|
196
|
+
npx opc run
|
|
197
|
+
\`\`\`
|
|
198
|
+
|
|
199
|
+
4. **Open browser:** [http://localhost:3000](http://localhost:3000)
|
|
200
|
+
|
|
201
|
+
## CLI Chat
|
|
202
|
+
|
|
203
|
+
\`\`\`bash
|
|
204
|
+
npx opc chat
|
|
205
|
+
\`\`\`
|
|
206
|
+
|
|
207
|
+
## Configuration
|
|
208
|
+
|
|
209
|
+
Edit \`oad.yaml\` to customize your agent's personality, skills, and behavior.
|
|
210
|
+
`);
|
|
137
211
|
console.log(`\n${icon.success} Created agent project: ${color.bold(name + '/')}`);
|
|
138
|
-
console.log(` ${icon.file} oad.yaml
|
|
212
|
+
console.log(` ${icon.file} oad.yaml - Agent definition`);
|
|
213
|
+
console.log(` ${icon.file} package.json - Dependencies`);
|
|
214
|
+
console.log(` ${icon.file} .env.example - Environment template`);
|
|
215
|
+
console.log(` ${icon.file} .env - Environment config (edit this!)`);
|
|
216
|
+
console.log(` ${icon.file} .gitignore`);
|
|
139
217
|
console.log(` ${icon.file} README.md`);
|
|
140
218
|
console.log(`\n Template: ${color.cyan(template)}`);
|
|
141
|
-
console.log(`\n${color.
|
|
219
|
+
console.log(`\n${color.bold('Next steps:')}`);
|
|
220
|
+
console.log(` 1. cd ${name}`);
|
|
221
|
+
console.log(` 2. Edit .env — set your OPC_LLM_API_KEY`);
|
|
222
|
+
console.log(` 3. npm install`);
|
|
223
|
+
console.log(` 4. npx opc run`);
|
|
224
|
+
console.log(` 5. Open http://localhost:3000\n`);
|
|
142
225
|
});
|
|
226
|
+
// ── Chat command ─────────────────────────────────────────────
|
|
143
227
|
program
|
|
144
|
-
.command('
|
|
145
|
-
.description('
|
|
146
|
-
.
|
|
147
|
-
.
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
228
|
+
.command('chat')
|
|
229
|
+
.description('Interactive CLI chat with the agent')
|
|
230
|
+
.option('-f, --file <file>', 'OAD file', 'oad.yaml')
|
|
231
|
+
.action(async (opts) => {
|
|
232
|
+
// Load .env if present
|
|
233
|
+
loadDotEnv();
|
|
234
|
+
let systemPrompt = 'You are a helpful AI agent.';
|
|
235
|
+
let model;
|
|
236
|
+
try {
|
|
237
|
+
const raw = fs.readFileSync(opts.file, 'utf-8');
|
|
238
|
+
const config = yaml.load(raw);
|
|
239
|
+
if (config?.spec?.systemPrompt)
|
|
240
|
+
systemPrompt = config.spec.systemPrompt;
|
|
241
|
+
if (config?.spec?.model)
|
|
242
|
+
model = config.spec.model;
|
|
243
|
+
console.log(`\n${icon.gear} Loaded agent: ${color.bold(config?.metadata?.name ?? 'unknown')}`);
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
console.log(`\n${icon.info} No oad.yaml found, using defaults.`);
|
|
247
|
+
}
|
|
248
|
+
const provider = (0, providers_1.createProvider)('openai', model);
|
|
249
|
+
const history = [];
|
|
250
|
+
console.log(`${color.dim('Type your message. Press Ctrl+C to exit.')}\n`);
|
|
251
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
252
|
+
const ask = () => {
|
|
253
|
+
rl.question(color.cyan('You: '), async (input) => {
|
|
254
|
+
const text = input.trim();
|
|
255
|
+
if (!text) {
|
|
256
|
+
ask();
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
history.push({ role: 'user', content: text });
|
|
260
|
+
// Build messages for provider
|
|
261
|
+
const messages = history.map((m) => ({
|
|
262
|
+
id: 'x',
|
|
263
|
+
role: m.role,
|
|
264
|
+
content: m.content,
|
|
265
|
+
timestamp: Date.now(),
|
|
266
|
+
}));
|
|
267
|
+
process.stdout.write(color.green('Agent: '));
|
|
268
|
+
let full = '';
|
|
269
|
+
try {
|
|
270
|
+
for await (const chunk of provider.chatStream(messages, systemPrompt)) {
|
|
271
|
+
process.stdout.write(chunk);
|
|
272
|
+
full += chunk;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
catch (err) {
|
|
276
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
277
|
+
process.stdout.write(color.red(`\n[Error: ${msg}]`));
|
|
278
|
+
full = `[Error: ${msg}]`;
|
|
279
|
+
}
|
|
280
|
+
console.log('\n');
|
|
281
|
+
history.push({ role: 'assistant', content: full });
|
|
282
|
+
// Trim history if too long (keep last 40 messages)
|
|
283
|
+
if (history.length > 40) {
|
|
284
|
+
history.splice(0, history.length - 40);
|
|
285
|
+
}
|
|
286
|
+
ask();
|
|
287
|
+
});
|
|
288
|
+
};
|
|
289
|
+
rl.on('close', () => {
|
|
290
|
+
console.log(`\n${color.dim('Goodbye!')}`);
|
|
291
|
+
process.exit(0);
|
|
292
|
+
});
|
|
293
|
+
ask();
|
|
294
|
+
});
|
|
295
|
+
// ── Run command ──────────────────────────────────────────────
|
|
296
|
+
program
|
|
297
|
+
.command('run')
|
|
298
|
+
.description('Start agent with web server')
|
|
299
|
+
.option('-f, --file <file>', 'OAD file', 'oad.yaml')
|
|
300
|
+
.option('-p, --port <port>', 'Port override')
|
|
301
|
+
.action(async (opts) => {
|
|
302
|
+
loadDotEnv();
|
|
303
|
+
const runtime = new runtime_1.AgentRuntime();
|
|
304
|
+
await runtime.loadConfig(opts.file);
|
|
305
|
+
await runtime.initialize();
|
|
306
|
+
await runtime.start();
|
|
307
|
+
const agent = runtime.getAgent();
|
|
308
|
+
console.log(`\n${icon.rocket} Agent "${color.bold(agent?.name ?? 'unknown')}" is running.`);
|
|
309
|
+
console.log(` ${color.dim('Web UI:')} http://localhost:3000`);
|
|
310
|
+
console.log(` ${color.dim('API:')} POST http://localhost:3000/api/chat`);
|
|
311
|
+
console.log(`\n ${color.dim('Press Ctrl+C to stop.')}\n`);
|
|
155
312
|
});
|
|
313
|
+
// ── Info command ─────────────────────────────────────────────
|
|
156
314
|
program
|
|
157
315
|
.command('info')
|
|
158
316
|
.description('Show agent info from OAD')
|
|
@@ -167,22 +325,9 @@ program
|
|
|
167
325
|
console.log(` Name: ${color.cyan(m.name)}`);
|
|
168
326
|
console.log(` Version: ${m.version}`);
|
|
169
327
|
console.log(` Description: ${m.description ?? color.dim('(none)')}`);
|
|
170
|
-
console.log(` Author: ${m.author ?? color.dim('(none)')}`);
|
|
171
|
-
console.log(` License: ${m.license}`);
|
|
172
328
|
console.log(` Model: ${s.model}`);
|
|
173
|
-
console.log(`
|
|
174
|
-
console.log(`
|
|
175
|
-
console.log(` Skills: ${s.skills.map(sk => sk.name).join(', ') || color.dim('(none)')}`);
|
|
176
|
-
console.log(` Trust: ${s.dtv?.trust?.level ?? 'sandbox'}`);
|
|
177
|
-
console.log(` Streaming: ${s.streaming ? 'enabled' : 'disabled'}`);
|
|
178
|
-
console.log(` Locale: ${s.locale ?? 'en'}`);
|
|
179
|
-
if (s.room) {
|
|
180
|
-
console.log(` Room: ${s.room.name}`);
|
|
181
|
-
}
|
|
182
|
-
if (m.marketplace) {
|
|
183
|
-
console.log(` Category: ${m.marketplace.category ?? color.dim('(none)')}`);
|
|
184
|
-
console.log(` Pricing: ${m.marketplace.pricing ?? 'free'}`);
|
|
185
|
-
}
|
|
329
|
+
console.log(` Channels: ${s.channels.map((c) => c.type).join(', ') || color.dim('(none)')}`);
|
|
330
|
+
console.log(` Skills: ${s.skills.map((sk) => sk.name).join(', ') || color.dim('(none)')}`);
|
|
186
331
|
console.log();
|
|
187
332
|
}
|
|
188
333
|
catch (err) {
|
|
@@ -190,6 +335,7 @@ program
|
|
|
190
335
|
process.exit(1);
|
|
191
336
|
}
|
|
192
337
|
});
|
|
338
|
+
// ── Build command ────────────────────────────────────────────
|
|
193
339
|
program
|
|
194
340
|
.command('build')
|
|
195
341
|
.description('Validate OAD and compile')
|
|
@@ -205,48 +351,50 @@ program
|
|
|
205
351
|
process.exit(1);
|
|
206
352
|
}
|
|
207
353
|
});
|
|
354
|
+
// ── Create command ───────────────────────────────────────────
|
|
355
|
+
program
|
|
356
|
+
.command('create')
|
|
357
|
+
.description('Create an agent from a template')
|
|
358
|
+
.argument('<name>', 'Agent name')
|
|
359
|
+
.option('-t, --template <template>', 'Template', 'customer-service')
|
|
360
|
+
.action(async (name, opts) => {
|
|
361
|
+
const factory = TEMPLATES[opts.template]?.factory ?? customer_service_1.createCustomerServiceConfig;
|
|
362
|
+
const config = factory();
|
|
363
|
+
config.metadata.name = name;
|
|
364
|
+
const outFile = `${name}-oad.yaml`;
|
|
365
|
+
fs.writeFileSync(outFile, yaml.dump(config, { lineWidth: 120 }));
|
|
366
|
+
console.log(`${icon.success} Created ${color.bold(outFile)}`);
|
|
367
|
+
});
|
|
368
|
+
// ── Test command ─────────────────────────────────────────────
|
|
208
369
|
program
|
|
209
370
|
.command('test')
|
|
210
371
|
.description('Run agent in sandbox mode')
|
|
211
372
|
.option('-f, --file <file>', 'OAD file', 'oad.yaml')
|
|
212
373
|
.action(async (opts) => {
|
|
374
|
+
loadDotEnv();
|
|
213
375
|
console.log(`\n${icon.gear} Running agent in sandbox mode...`);
|
|
214
376
|
const runtime = new runtime_1.AgentRuntime();
|
|
215
377
|
await runtime.loadConfig(opts.file);
|
|
216
378
|
const agent = await runtime.initialize();
|
|
217
|
-
runtime.registerSkill(new customer_service_2.FAQSkill());
|
|
218
|
-
runtime.registerSkill(new customer_service_2.HandoffSkill());
|
|
219
379
|
console.log(`${icon.success} Agent "${color.bold(agent.name)}" initialized in sandbox.`);
|
|
220
380
|
console.log(` State: ${agent.state}`);
|
|
221
381
|
console.log(` Sending test message...`);
|
|
222
382
|
const response = await agent.handleMessage({
|
|
223
383
|
id: 'test_1',
|
|
224
384
|
role: 'user',
|
|
225
|
-
content: 'What
|
|
385
|
+
content: 'Hello! What can you help me with?',
|
|
226
386
|
timestamp: Date.now(),
|
|
227
387
|
});
|
|
228
|
-
console.log(` Response: ${response.content}`);
|
|
388
|
+
console.log(` Response: ${response.content.slice(0, 200)}`);
|
|
229
389
|
console.log(`${icon.success} Sandbox test passed.\n`);
|
|
230
390
|
});
|
|
231
|
-
|
|
232
|
-
.command('run')
|
|
233
|
-
.description('Start agent with channels')
|
|
234
|
-
.option('-f, --file <file>', 'OAD file', 'oad.yaml')
|
|
235
|
-
.action(async (opts) => {
|
|
236
|
-
const runtime = new runtime_1.AgentRuntime();
|
|
237
|
-
await runtime.loadConfig(opts.file);
|
|
238
|
-
await runtime.initialize();
|
|
239
|
-
runtime.registerSkill(new customer_service_2.FAQSkill());
|
|
240
|
-
runtime.registerSkill(new customer_service_2.HandoffSkill());
|
|
241
|
-
await runtime.start();
|
|
242
|
-
const agent = runtime.getAgent();
|
|
243
|
-
console.log(`\n${icon.rocket} Agent "${color.bold(agent?.name ?? 'unknown')}" is running.\n`);
|
|
244
|
-
});
|
|
391
|
+
// ── Dev command ──────────────────────────────────────────────
|
|
245
392
|
program
|
|
246
393
|
.command('dev')
|
|
247
394
|
.description('Hot-reload development mode')
|
|
248
395
|
.option('-f, --file <file>', 'OAD file', 'oad.yaml')
|
|
249
396
|
.action(async (opts) => {
|
|
397
|
+
loadDotEnv();
|
|
250
398
|
console.log(`\n${icon.gear} ${color.bold('Development mode')} - watching for changes...\n`);
|
|
251
399
|
let runtime = null;
|
|
252
400
|
const startAgent = async () => {
|
|
@@ -256,8 +404,6 @@ program
|
|
|
256
404
|
runtime = new runtime_1.AgentRuntime();
|
|
257
405
|
await runtime.loadConfig(opts.file);
|
|
258
406
|
await runtime.initialize();
|
|
259
|
-
runtime.registerSkill(new customer_service_2.FAQSkill());
|
|
260
|
-
runtime.registerSkill(new customer_service_2.HandoffSkill());
|
|
261
407
|
await runtime.start();
|
|
262
408
|
const agent = runtime.getAgent();
|
|
263
409
|
console.log(`${icon.success} Agent "${color.bold(agent?.name ?? 'unknown')}" restarted.`);
|
|
@@ -284,6 +430,7 @@ program
|
|
|
284
430
|
process.exit(0);
|
|
285
431
|
});
|
|
286
432
|
});
|
|
433
|
+
// ── Publish command ──────────────────────────────────────────
|
|
287
434
|
program
|
|
288
435
|
.command('publish')
|
|
289
436
|
.description('Validate and package for OPC Registry')
|
|
@@ -295,10 +442,6 @@ program
|
|
|
295
442
|
const trust = config.spec.dtv?.trust?.level ?? 'sandbox';
|
|
296
443
|
console.log(`\n${icon.package} Publishing: ${color.bold(config.metadata.name)} v${config.metadata.version}`);
|
|
297
444
|
console.log(` ${icon.success} OAD validation passed`);
|
|
298
|
-
console.log(` 🔐 Trust level: ${trust}`);
|
|
299
|
-
if (trust === 'sandbox') {
|
|
300
|
-
console.log(` ${icon.warn} Trust level is 'sandbox'. Upgrade for marketplace listing.`);
|
|
301
|
-
}
|
|
302
445
|
const manifest = {
|
|
303
446
|
name: config.metadata.name,
|
|
304
447
|
version: config.metadata.version,
|
|
@@ -306,11 +449,8 @@ program
|
|
|
306
449
|
author: config.metadata.author,
|
|
307
450
|
license: config.metadata.license,
|
|
308
451
|
trust,
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
tags: config.metadata.marketplace?.tags ?? [],
|
|
312
|
-
channels: config.spec.channels.map(c => c.type),
|
|
313
|
-
skills: config.spec.skills.map(s => s.name),
|
|
452
|
+
channels: config.spec.channels.map((c) => c.type),
|
|
453
|
+
skills: config.spec.skills.map((s) => s.name),
|
|
314
454
|
publishedAt: new Date().toISOString(),
|
|
315
455
|
};
|
|
316
456
|
fs.writeFileSync('opc-manifest.json', JSON.stringify(manifest, null, 2));
|
|
@@ -322,18 +462,7 @@ program
|
|
|
322
462
|
process.exit(1);
|
|
323
463
|
}
|
|
324
464
|
});
|
|
325
|
-
|
|
326
|
-
.command('search')
|
|
327
|
-
.description('Search OPC Registry for agents and skills')
|
|
328
|
-
.argument('<query>', 'Search query')
|
|
329
|
-
.action(async (query) => {
|
|
330
|
-
console.log(`\n${icon.search} Searching OPC Registry for "${color.bold(query)}"...`);
|
|
331
|
-
console.log(`\n🚧 OPC Registry coming soon!`);
|
|
332
|
-
console.log(` The marketplace is under development.`);
|
|
333
|
-
console.log(` Browse templates with: ${color.cyan('opc init --template <name>')}`);
|
|
334
|
-
console.log(`\n Available templates: ${Object.keys(TEMPLATES).map(t => color.cyan(t)).join(', ')}\n`);
|
|
335
|
-
});
|
|
336
|
-
// ── Deploy command ────────────────────────────────────────────
|
|
465
|
+
// ── Deploy command ───────────────────────────────────────────
|
|
337
466
|
program
|
|
338
467
|
.command('deploy')
|
|
339
468
|
.description('Deploy agent to a target runtime')
|
|
@@ -354,67 +483,27 @@ program
|
|
|
354
483
|
const defaultOutput = path.join(homeDir, '.openclaw', 'agents', agentId, 'workspace');
|
|
355
484
|
const outputDir = path.resolve(opts.output ?? defaultOutput);
|
|
356
485
|
console.log(`\n${icon.rocket} ${color.bold('Deploy to OpenClaw')}\n`);
|
|
357
|
-
console.log(` Agent: ${color.cyan(config.metadata.name)} v${config.metadata.version}`);
|
|
358
|
-
console.log(` Target: ${color.cyan('OpenClaw')}`);
|
|
359
|
-
console.log(` Output: ${color.dim(outputDir)}`);
|
|
360
486
|
const result = (0, openclaw_1.deployToOpenClaw)({ oad: config, outputDir, install: opts.install });
|
|
361
|
-
console.log(`\n${icon.success} Generated ${result.files.length} files
|
|
362
|
-
for (const f of result.files) {
|
|
363
|
-
console.log(` ${icon.file} ${f}`);
|
|
364
|
-
}
|
|
487
|
+
console.log(`\n${icon.success} Generated ${result.files.length} files.`);
|
|
365
488
|
if (result.installed) {
|
|
366
|
-
console.log(
|
|
367
|
-
console.log(`\n${color.dim('Next:')} Restart OpenClaw gateway to pick up the new agent.`);
|
|
368
|
-
console.log(` ${color.cyan('openclaw gateway restart')}\n`);
|
|
369
|
-
}
|
|
370
|
-
else if (opts.install) {
|
|
371
|
-
console.log(`\n${icon.warn} Could not auto-register. Add the agent manually to openclaw.json.`);
|
|
372
|
-
}
|
|
373
|
-
else {
|
|
374
|
-
console.log(`\n${color.dim('Next:')} Copy the output to your OpenClaw agents directory, or re-run with ${color.cyan('--install')}`);
|
|
375
|
-
console.log(` ${color.cyan(`opc deploy --target openclaw --install`)}\n`);
|
|
489
|
+
console.log(`${icon.success} Registered in OpenClaw config.`);
|
|
376
490
|
}
|
|
491
|
+
console.log();
|
|
377
492
|
}
|
|
378
493
|
catch (err) {
|
|
379
494
|
console.error(`${icon.error} Deploy failed:`, err instanceof Error ? err.message : err);
|
|
380
495
|
process.exit(1);
|
|
381
496
|
}
|
|
382
497
|
});
|
|
383
|
-
// ──
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
.
|
|
387
|
-
.
|
|
388
|
-
.action(() => {
|
|
389
|
-
console.log(`\n${icon.
|
|
390
|
-
console.log(
|
|
391
|
-
console.log(
|
|
392
|
-
});
|
|
393
|
-
toolCmd
|
|
394
|
-
.command('add')
|
|
395
|
-
.description('Add an MCP tool from registry')
|
|
396
|
-
.argument('<name>', 'Tool name')
|
|
397
|
-
.action((name) => {
|
|
398
|
-
console.log(`\n🚧 Tool registry coming soon!`);
|
|
399
|
-
console.log(` Would add tool: ${color.cyan(name)}\n`);
|
|
400
|
-
});
|
|
401
|
-
// ── Plugin commands ──────────────────────────────────────────
|
|
402
|
-
const pluginCmd = program.command('plugin').description('Manage plugins');
|
|
403
|
-
pluginCmd
|
|
404
|
-
.command('list')
|
|
405
|
-
.description('List installed plugins')
|
|
406
|
-
.action(() => {
|
|
407
|
-
console.log(`\n${icon.gear} ${color.bold('Installed Plugins')}\n`);
|
|
408
|
-
console.log(` ${color.dim('No plugins installed yet.')}`);
|
|
409
|
-
console.log(`\n Add plugins with: ${color.cyan('opc plugin add <name>')}\n`);
|
|
410
|
-
});
|
|
411
|
-
pluginCmd
|
|
412
|
-
.command('add')
|
|
413
|
-
.description('Add a plugin')
|
|
414
|
-
.argument('<name>', 'Plugin name')
|
|
415
|
-
.action((name) => {
|
|
416
|
-
console.log(`\n🚧 Plugin registry coming soon!`);
|
|
417
|
-
console.log(` Would add plugin: ${color.cyan(name)}\n`);
|
|
498
|
+
// ── Search command ───────────────────────────────────────────
|
|
499
|
+
program
|
|
500
|
+
.command('search')
|
|
501
|
+
.description('Search OPC Registry for agents and skills')
|
|
502
|
+
.argument('<query>', 'Search query')
|
|
503
|
+
.action(async (query) => {
|
|
504
|
+
console.log(`\n${icon.search} Searching OPC Registry for "${color.bold(query)}"...`);
|
|
505
|
+
console.log(`\n🚧 OPC Registry coming soon!`);
|
|
506
|
+
console.log(` Available templates: ${Object.keys(TEMPLATES).map(t => color.cyan(t)).join(', ')}\n`);
|
|
418
507
|
});
|
|
419
508
|
// ── Stats command ────────────────────────────────────────────
|
|
420
509
|
program
|
|
@@ -422,89 +511,96 @@ program
|
|
|
422
511
|
.description('Show agent analytics')
|
|
423
512
|
.action(() => {
|
|
424
513
|
const analytics = new analytics_1.Analytics();
|
|
425
|
-
// Show demo stats
|
|
426
514
|
const snap = analytics.getSnapshot();
|
|
427
515
|
console.log(`\n${icon.gear} ${color.bold('Agent Analytics')}\n`);
|
|
428
|
-
console.log(` Messages
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
console.log(`\n
|
|
516
|
+
console.log(` Messages: ${snap.messagesProcessed} | Errors: ${snap.errorCount} | Uptime: ${Math.round(snap.uptime / 1000)}s\n`);
|
|
517
|
+
});
|
|
518
|
+
// ── Tool commands ────────────────────────────────────────────
|
|
519
|
+
const toolCmd = program.command('tool').description('Manage MCP tools');
|
|
520
|
+
toolCmd.command('list').description('List MCP tools').action(() => {
|
|
521
|
+
console.log(`\n${icon.gear} No tools installed. Add with: ${color.cyan('opc tool add <name>')}\n`);
|
|
522
|
+
});
|
|
523
|
+
toolCmd.command('add').argument('<name>').action((name) => {
|
|
524
|
+
console.log(`🚧 Tool registry coming soon! Would add: ${color.cyan(name)}\n`);
|
|
434
525
|
});
|
|
435
|
-
//
|
|
526
|
+
// ── Workflow commands ────────────────────────────────────────
|
|
436
527
|
const workflowCmd = program.command('workflow').description('Manage workflows');
|
|
437
528
|
workflowCmd
|
|
438
529
|
.command('run')
|
|
439
|
-
.
|
|
440
|
-
.argument('<name>', 'Workflow name')
|
|
530
|
+
.argument('<name>')
|
|
441
531
|
.option('-f, --file <file>', 'OAD file', 'oad.yaml')
|
|
442
532
|
.action(async (name, opts) => {
|
|
443
|
-
console.log(`\n${icon.gear} Running workflow "${color.bold(name)}"...`);
|
|
444
533
|
const runtime = new runtime_1.AgentRuntime();
|
|
445
534
|
const config = await runtime.loadConfig(opts.file);
|
|
446
|
-
const
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
console.error(`${icon.error} Workflow "${name}" not found in OAD.`);
|
|
535
|
+
const wf = (config.spec.workflows ?? []).find((w) => w.name === name);
|
|
536
|
+
if (!wf) {
|
|
537
|
+
console.error(`Workflow "${name}" not found.`);
|
|
450
538
|
process.exit(1);
|
|
451
539
|
}
|
|
452
540
|
const engine = new workflow_1.WorkflowEngine();
|
|
453
|
-
engine.registerWorkflow(
|
|
454
|
-
console.log(`${icon.success} Workflow "${name}" loaded
|
|
455
|
-
console.log(`${color.dim(' Workflow execution requires a running agent context.')}\n`);
|
|
541
|
+
engine.registerWorkflow(wf);
|
|
542
|
+
console.log(`${icon.success} Workflow "${name}" loaded.\n`);
|
|
456
543
|
});
|
|
457
544
|
workflowCmd
|
|
458
545
|
.command('list')
|
|
459
|
-
.description('List workflows in OAD')
|
|
460
546
|
.option('-f, --file <file>', 'OAD file', 'oad.yaml')
|
|
461
547
|
.action(async (opts) => {
|
|
462
548
|
const runtime = new runtime_1.AgentRuntime();
|
|
463
549
|
const config = await runtime.loadConfig(opts.file);
|
|
464
|
-
const
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
}
|
|
469
|
-
else {
|
|
470
|
-
for (const wf of workflows) {
|
|
471
|
-
console.log(` ${color.cyan(wf.name)} - ${wf.description ?? color.dim('(no description)')}`);
|
|
472
|
-
}
|
|
473
|
-
console.log();
|
|
550
|
+
const wfs = config.spec.workflows ?? [];
|
|
551
|
+
if (wfs.length === 0) {
|
|
552
|
+
console.log('No workflows defined.');
|
|
553
|
+
return;
|
|
474
554
|
}
|
|
555
|
+
for (const wf of wfs)
|
|
556
|
+
console.log(` ${color.cyan(wf.name)}`);
|
|
475
557
|
});
|
|
476
|
-
//
|
|
477
|
-
const versionCmd = program.command('version').description('Manage agent versions');
|
|
478
|
-
versionCmd
|
|
479
|
-
.command('list')
|
|
480
|
-
.description('List saved versions')
|
|
481
|
-
.action(() => {
|
|
558
|
+
// ── Version commands ─────────────────────────────────────────
|
|
559
|
+
const versionCmd = program.command('version-mgmt').description('Manage agent versions');
|
|
560
|
+
versionCmd.command('list').action(() => {
|
|
482
561
|
const vm = new versioning_1.VersionManager();
|
|
483
562
|
const versions = vm.list();
|
|
484
|
-
console.log(`\n${icon.gear} ${color.bold('Agent Versions')}\n`);
|
|
485
563
|
if (versions.length === 0) {
|
|
486
|
-
console.log(
|
|
487
|
-
|
|
488
|
-
else {
|
|
489
|
-
for (const v of versions) {
|
|
490
|
-
console.log(` ${color.cyan(v.version)} - ${new Date(v.timestamp).toISOString()} ${v.description ?? ''}`);
|
|
491
|
-
}
|
|
492
|
-
console.log();
|
|
564
|
+
console.log('No versions saved.');
|
|
565
|
+
return;
|
|
493
566
|
}
|
|
567
|
+
for (const v of versions)
|
|
568
|
+
console.log(` ${color.cyan(v.version)} - ${new Date(v.timestamp).toISOString()}`);
|
|
494
569
|
});
|
|
495
|
-
versionCmd
|
|
496
|
-
.command('rollback')
|
|
497
|
-
.description('Rollback to a saved version')
|
|
498
|
-
.argument('<version>', 'Version to rollback to')
|
|
499
|
-
.action((version) => {
|
|
570
|
+
versionCmd.command('rollback').argument('<version>').action((version) => {
|
|
500
571
|
const vm = new versioning_1.VersionManager();
|
|
501
572
|
const oad = vm.rollback(version);
|
|
502
573
|
if (!oad) {
|
|
503
|
-
console.error(
|
|
574
|
+
console.error(`Version "${version}" not found.`);
|
|
504
575
|
process.exit(1);
|
|
505
576
|
}
|
|
506
577
|
fs.writeFileSync('oad.yaml', oad);
|
|
507
|
-
console.log(`${icon.success} Rolled back to
|
|
578
|
+
console.log(`${icon.success} Rolled back to ${version}.`);
|
|
508
579
|
});
|
|
580
|
+
// ── Helpers ──────────────────────────────────────────────────
|
|
581
|
+
function loadDotEnv() {
|
|
582
|
+
const envPath = path.resolve('.env');
|
|
583
|
+
if (!fs.existsSync(envPath))
|
|
584
|
+
return;
|
|
585
|
+
try {
|
|
586
|
+
const content = fs.readFileSync(envPath, 'utf-8');
|
|
587
|
+
for (const line of content.split('\n')) {
|
|
588
|
+
const trimmed = line.trim();
|
|
589
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
590
|
+
continue;
|
|
591
|
+
const eqIdx = trimmed.indexOf('=');
|
|
592
|
+
if (eqIdx === -1)
|
|
593
|
+
continue;
|
|
594
|
+
const key = trimmed.slice(0, eqIdx).trim();
|
|
595
|
+
const value = trimmed.slice(eqIdx + 1).trim();
|
|
596
|
+
if (!process.env[key]) {
|
|
597
|
+
process.env[key] = value;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
catch {
|
|
602
|
+
// ignore
|
|
603
|
+
}
|
|
604
|
+
}
|
|
509
605
|
program.parse();
|
|
510
606
|
//# sourceMappingURL=cli.js.map
|