opc-agent 1.4.0 → 1.4.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/CHANGELOG.md +69 -23
- package/CONTRIBUTING.md +60 -21
- package/README.md +358 -235
- package/README.zh-CN.md +415 -415
- package/dist/channels/slack.js +10 -93
- package/dist/channels/web.d.ts +0 -10
- package/dist/channels/web.js +2 -33
- package/dist/cli.js +60 -255
- package/dist/core/dashboard.d.ts +35 -0
- package/dist/core/dashboard.js +157 -0
- package/dist/core/fast-mode.d.ts +27 -0
- package/dist/core/fast-mode.js +59 -0
- package/dist/core/priority.d.ts +52 -0
- package/dist/core/priority.js +102 -0
- package/dist/core/runtime.d.ts +0 -4
- package/dist/core/runtime.js +0 -27
- package/dist/deploy/hermes.js +22 -22
- package/dist/deploy/openclaw.js +40 -31
- package/dist/index.d.ts +14 -3
- package/dist/index.js +20 -6
- package/dist/memory/cloud-storage.d.ts +40 -0
- package/dist/memory/cloud-storage.js +211 -0
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.js +1 -7
- package/dist/schema/oad.d.ts +2 -1
- package/dist/templates/code-reviewer.d.ts +8 -0
- package/dist/templates/code-reviewer.js +9 -5
- package/dist/templates/customer-service.d.ts +8 -0
- package/dist/templates/customer-service.js +6 -2
- package/dist/templates/data-analyst.d.ts +8 -0
- package/dist/templates/data-analyst.js +9 -5
- package/dist/templates/knowledge-base.d.ts +8 -0
- package/dist/templates/knowledge-base.js +6 -2
- package/dist/templates/sales-assistant.d.ts +8 -0
- package/dist/templates/sales-assistant.js +8 -4
- package/dist/templates/teacher.d.ts +8 -0
- package/dist/templates/teacher.js +10 -6
- package/docs/.vitepress/config.ts +103 -103
- package/docs/api/cli.md +48 -48
- package/docs/api/oad-schema.md +64 -64
- package/docs/api/sdk.md +80 -80
- package/docs/guide/concepts.md +51 -51
- package/docs/guide/configuration.md +79 -79
- package/docs/guide/deployment.md +42 -42
- package/docs/guide/getting-started.md +44 -44
- package/docs/guide/templates.md +28 -28
- package/docs/guide/testing.md +84 -84
- package/docs/index.md +27 -27
- package/docs/zh/api/cli.md +54 -54
- package/docs/zh/api/oad-schema.md +87 -87
- package/docs/zh/api/sdk.md +102 -102
- package/docs/zh/guide/concepts.md +104 -104
- package/docs/zh/guide/configuration.md +135 -135
- package/docs/zh/guide/deployment.md +81 -81
- package/docs/zh/guide/getting-started.md +82 -82
- package/docs/zh/guide/templates.md +84 -84
- package/docs/zh/guide/testing.md +88 -88
- package/docs/zh/index.md +27 -27
- package/examples/customer-service-demo/README.md +90 -90
- package/examples/customer-service-demo/oad.yaml +107 -107
- package/package.json +1 -1
- package/src/analytics/index.ts +66 -66
- package/src/channels/discord.ts +192 -192
- package/src/channels/email.ts +177 -177
- package/src/channels/feishu.ts +236 -236
- package/src/channels/index.ts +15 -15
- package/src/channels/slack.ts +160 -217
- package/src/channels/telegram.ts +90 -90
- package/src/channels/voice.ts +106 -106
- package/src/channels/web.ts +2 -38
- package/src/channels/webhook.ts +199 -199
- package/src/channels/websocket.ts +87 -87
- package/src/channels/wechat.ts +149 -149
- package/src/cli.ts +58 -282
- package/src/core/a2a.ts +143 -143
- package/src/core/agent.ts +152 -152
- package/src/core/analytics-engine.ts +186 -186
- package/src/core/auth.ts +57 -57
- package/src/core/cache.ts +141 -141
- package/src/core/compose.ts +77 -77
- package/src/core/config.ts +14 -14
- package/src/core/dashboard.ts +219 -0
- package/src/core/errors.ts +148 -148
- package/src/core/fast-mode.ts +75 -0
- package/src/core/hitl.ts +138 -138
- package/src/core/logger.ts +57 -57
- package/src/core/orchestrator.ts +215 -215
- package/src/core/performance.ts +187 -187
- package/src/core/priority.ts +140 -0
- package/src/core/rate-limiter.ts +128 -128
- package/src/core/room.ts +109 -109
- package/src/core/runtime.ts +152 -183
- package/src/core/sandbox.ts +101 -101
- package/src/core/security.ts +171 -171
- package/src/core/types.ts +68 -68
- package/src/core/versioning.ts +106 -106
- package/src/core/watch.ts +178 -178
- package/src/core/workflow.ts +235 -235
- package/src/deploy/hermes.ts +156 -156
- package/src/deploy/openclaw.ts +200 -190
- package/src/dtv/data.ts +29 -0
- package/src/dtv/trust.ts +43 -0
- package/src/dtv/value.ts +47 -0
- package/src/i18n/index.ts +216 -216
- package/src/index.ts +16 -3
- package/src/marketplace/index.ts +223 -0
- package/src/memory/cloud-storage.ts +217 -0
- package/src/memory/deepbrain.ts +108 -108
- package/src/memory/index.ts +34 -34
- package/src/plugins/index.ts +208 -208
- package/src/providers/index.ts +1 -9
- package/src/schema/oad.ts +155 -154
- package/src/skills/base.ts +16 -16
- package/src/skills/document.ts +100 -100
- package/src/skills/http.ts +35 -35
- package/src/skills/index.ts +27 -27
- package/src/skills/scheduler.ts +80 -80
- package/src/skills/webhook-trigger.ts +59 -59
- package/src/templates/code-reviewer.ts +34 -30
- package/src/templates/customer-service.ts +80 -76
- package/src/templates/data-analyst.ts +70 -66
- package/src/templates/executive-assistant.ts +71 -71
- package/src/templates/financial-advisor.ts +60 -60
- package/src/templates/knowledge-base.ts +31 -27
- package/src/templates/legal-assistant.ts +71 -71
- package/src/templates/sales-assistant.ts +79 -75
- package/src/templates/teacher.ts +79 -75
- package/src/testing/index.ts +181 -181
- package/src/tools/calculator.ts +73 -73
- package/src/tools/datetime.ts +149 -149
- package/src/tools/json-transform.ts +187 -187
- package/src/tools/mcp.ts +76 -76
- package/src/tools/text-analysis.ts +116 -116
- package/templates/Dockerfile +15 -15
- package/templates/code-reviewer/README.md +27 -27
- package/templates/code-reviewer/oad.yaml +41 -41
- package/templates/customer-service/README.md +22 -22
- package/templates/customer-service/oad.yaml +36 -36
- package/templates/docker-compose.yml +21 -21
- package/templates/ecommerce-assistant/README.md +45 -45
- package/templates/ecommerce-assistant/oad.yaml +47 -47
- package/templates/knowledge-base/README.md +28 -28
- package/templates/knowledge-base/oad.yaml +38 -38
- package/templates/sales-assistant/README.md +26 -26
- package/templates/sales-assistant/oad.yaml +43 -43
- package/templates/tech-support/README.md +43 -43
- package/templates/tech-support/oad.yaml +45 -45
- package/tests/a2a.test.ts +66 -66
- package/tests/agent.test.ts +72 -72
- package/tests/analytics.test.ts +50 -50
- package/tests/channel.test.ts +39 -39
- package/tests/e2e.test.ts +134 -134
- package/tests/errors.test.ts +83 -83
- package/tests/hitl.test.ts +71 -71
- package/tests/i18n.test.ts +41 -41
- package/tests/mcp.test.ts +54 -54
- package/tests/oad.test.ts +68 -68
- package/tests/performance.test.ts +115 -115
- package/tests/plugin.test.ts +74 -74
- package/tests/room.test.ts +106 -106
- package/tests/runtime.test.ts +42 -42
- package/tests/sandbox.test.ts +46 -46
- package/tests/security.test.ts +60 -60
- package/tests/templates.test.ts +77 -77
- package/tests/v070.test.ts +76 -76
- package/tests/versioning.test.ts +75 -75
- package/tests/voice.test.ts +61 -61
- package/tests/webhook.test.ts +29 -29
- package/tests/workflow.test.ts +143 -143
- package/tsconfig.json +19 -19
- package/vitest.config.ts +9 -9
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -20
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -14
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -13
- package/.github/workflows/ci.yml +0 -24
- package/dist/traces/index.d.ts +0 -49
- package/dist/traces/index.js +0 -102
- package/examples/README.md +0 -22
- package/examples/basic-agent.ts +0 -90
- package/examples/brain-integration.ts +0 -71
- package/examples/multi-channel.ts +0 -74
- package/src/traces/index.ts +0 -132
- package/test-agent/Dockerfile +0 -9
- package/test-agent/README.md +0 -50
- package/test-agent/agent.yaml +0 -23
- package/test-agent/docker-compose.yml +0 -11
- package/test-agent/oad.yaml +0 -31
- package/test-agent/package-lock.json +0 -1492
- package/test-agent/package.json +0 -18
- package/test-agent/src/index.ts +0 -24
- package/test-agent/src/skills/echo.ts +0 -15
- package/test-agent/tsconfig.json +0 -25
package/dist/channels/slack.js
CHANGED
|
@@ -1,37 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
3
|
exports.SlackChannel = void 0;
|
|
37
4
|
const index_1 = require("./index");
|
|
@@ -70,51 +37,9 @@ class SlackChannel extends index_1.BaseChannel {
|
|
|
70
37
|
}
|
|
71
38
|
/** Start Events API HTTP server */
|
|
72
39
|
async startEventsAPI() {
|
|
73
|
-
|
|
74
|
-
const port = this.config.port ?? 3001;
|
|
75
|
-
|
|
76
|
-
if (req.method !== 'POST') {
|
|
77
|
-
res.writeHead(404);
|
|
78
|
-
res.end();
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
const chunks = [];
|
|
82
|
-
for await (const chunk of req)
|
|
83
|
-
chunks.push(chunk);
|
|
84
|
-
const body = JSON.parse(Buffer.concat(chunks).toString());
|
|
85
|
-
// URL verification challenge
|
|
86
|
-
if (body.type === 'url_verification') {
|
|
87
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
88
|
-
res.end(JSON.stringify({ challenge: body.challenge }));
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
// Event callback
|
|
92
|
-
if (body.type === 'event_callback' && body.event) {
|
|
93
|
-
const event = body.event;
|
|
94
|
-
if (event.type === 'message' || event.type === 'app_mention') {
|
|
95
|
-
// Don't block the HTTP response
|
|
96
|
-
this.handleMessage(event).catch(() => { });
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
// Slash commands (form-urlencoded, but we handle JSON for simplicity)
|
|
100
|
-
if (req.url === '/slack/commands' && body.command) {
|
|
101
|
-
const reply = await this.handleSlashCommand({
|
|
102
|
-
command: body.command,
|
|
103
|
-
text: body.text ?? '',
|
|
104
|
-
userId: body.user_id,
|
|
105
|
-
channelId: body.channel_id,
|
|
106
|
-
triggerId: body.trigger_id,
|
|
107
|
-
});
|
|
108
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
109
|
-
res.end(JSON.stringify({ response_type: 'ephemeral', text: reply }));
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
res.writeHead(200);
|
|
113
|
-
res.end('ok');
|
|
114
|
-
});
|
|
115
|
-
server.listen(port, () => {
|
|
116
|
-
console.log(`[SlackChannel] Events API listening on port ${port}`);
|
|
117
|
-
});
|
|
40
|
+
// TODO: Implement with express or http
|
|
41
|
+
// const port = this.config.port ?? 3001;
|
|
42
|
+
// Listen for POST /slack/events and /slack/commands
|
|
118
43
|
}
|
|
119
44
|
/** Handle incoming Slack message */
|
|
120
45
|
async handleMessage(event) {
|
|
@@ -169,21 +94,13 @@ class SlackChannel extends index_1.BaseChannel {
|
|
|
169
94
|
}
|
|
170
95
|
/** Send a message to a Slack channel */
|
|
171
96
|
async sendMessage(channel, text, threadTs) {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
'Content-Type': 'application/json',
|
|
180
|
-
},
|
|
181
|
-
body: JSON.stringify(body),
|
|
182
|
-
});
|
|
183
|
-
const data = await res.json();
|
|
184
|
-
if (!data.ok) {
|
|
185
|
-
console.error(`[SlackChannel] chat.postMessage failed: ${data.error}`);
|
|
186
|
-
}
|
|
97
|
+
// TODO: Implement with @slack/web-api
|
|
98
|
+
// const { WebClient } = await import('@slack/web-api');
|
|
99
|
+
// const client = new WebClient(this.config.botToken);
|
|
100
|
+
// await client.chat.postMessage({ channel, text, thread_ts: threadTs });
|
|
101
|
+
void channel;
|
|
102
|
+
void text;
|
|
103
|
+
void threadTs;
|
|
187
104
|
}
|
|
188
105
|
}
|
|
189
106
|
exports.SlackChannel = SlackChannel;
|
package/dist/channels/web.d.ts
CHANGED
|
@@ -9,11 +9,6 @@ export declare class WebChannel extends BaseChannel {
|
|
|
9
9
|
private port;
|
|
10
10
|
private streamHandler;
|
|
11
11
|
private agentName;
|
|
12
|
-
private agentVersion;
|
|
13
|
-
private memoryType;
|
|
14
|
-
private skillNames;
|
|
15
|
-
private channelNames;
|
|
16
|
-
private analyticsProvider;
|
|
17
12
|
private currentProvider;
|
|
18
13
|
private stats;
|
|
19
14
|
private eventHandlers;
|
|
@@ -28,11 +23,6 @@ export declare class WebChannel extends BaseChannel {
|
|
|
28
23
|
trackSession(): void;
|
|
29
24
|
constructor(port?: number, authConfig?: AuthConfig);
|
|
30
25
|
setAgentName(name: string): void;
|
|
31
|
-
setAgentVersion(version: string): void;
|
|
32
|
-
setMemoryType(type: string): void;
|
|
33
|
-
setSkillNames(names: string[]): void;
|
|
34
|
-
setChannelNames(names: string[]): void;
|
|
35
|
-
setAnalyticsProvider(fn: () => any): void;
|
|
36
26
|
onStreamMessage(handler: (msg: Message, res: Response) => Promise<void>): void;
|
|
37
27
|
private setupRoutes;
|
|
38
28
|
start(): Promise<void>;
|
package/dist/channels/web.js
CHANGED
|
@@ -286,11 +286,6 @@ class WebChannel extends index_1.BaseChannel {
|
|
|
286
286
|
port;
|
|
287
287
|
streamHandler = null;
|
|
288
288
|
agentName = 'OPC Agent';
|
|
289
|
-
agentVersion = '1.0.0';
|
|
290
|
-
memoryType = 'in-memory';
|
|
291
|
-
skillNames = [];
|
|
292
|
-
channelNames = ['web'];
|
|
293
|
-
analyticsProvider = null;
|
|
294
289
|
currentProvider = 'openai';
|
|
295
290
|
stats = { sessions: 0, messages: 0, totalResponseMs: 0, tokenUsage: 0, knowledgeFiles: 0, startedAt: Date.now(), errors: 0 };
|
|
296
291
|
eventHandlers = new Map();
|
|
@@ -331,21 +326,6 @@ class WebChannel extends index_1.BaseChannel {
|
|
|
331
326
|
setAgentName(name) {
|
|
332
327
|
this.agentName = name;
|
|
333
328
|
}
|
|
334
|
-
setAgentVersion(version) {
|
|
335
|
-
this.agentVersion = version;
|
|
336
|
-
}
|
|
337
|
-
setMemoryType(type) {
|
|
338
|
-
this.memoryType = type;
|
|
339
|
-
}
|
|
340
|
-
setSkillNames(names) {
|
|
341
|
-
this.skillNames = names;
|
|
342
|
-
}
|
|
343
|
-
setChannelNames(names) {
|
|
344
|
-
this.channelNames = names;
|
|
345
|
-
}
|
|
346
|
-
setAnalyticsProvider(fn) {
|
|
347
|
-
this.analyticsProvider = fn;
|
|
348
|
-
}
|
|
349
329
|
onStreamMessage(handler) {
|
|
350
330
|
this.streamHandler = handler;
|
|
351
331
|
}
|
|
@@ -354,17 +334,7 @@ class WebChannel extends index_1.BaseChannel {
|
|
|
354
334
|
res.type('html').send(CHAT_HTML);
|
|
355
335
|
});
|
|
356
336
|
this.app.get('/health', (_req, res) => {
|
|
357
|
-
res.json({
|
|
358
|
-
status: 'ok',
|
|
359
|
-
agent: this.agentName,
|
|
360
|
-
version: this.agentVersion,
|
|
361
|
-
uptime: Date.now() - this.stats.startedAt,
|
|
362
|
-
memory: this.memoryType,
|
|
363
|
-
skills: this.skillNames,
|
|
364
|
-
channels: this.channelNames,
|
|
365
|
-
analytics: this.analyticsProvider ? this.analyticsProvider() : null,
|
|
366
|
-
timestamp: Date.now(),
|
|
367
|
-
});
|
|
337
|
+
res.json({ status: 'ok', timestamp: Date.now() });
|
|
368
338
|
});
|
|
369
339
|
this.app.get('/api/info', (_req, res) => {
|
|
370
340
|
res.json({ name: this.agentName });
|
|
@@ -438,8 +408,7 @@ class WebChannel extends index_1.BaseChannel {
|
|
|
438
408
|
res.type('html').send(DASHBOARD_HTML);
|
|
439
409
|
});
|
|
440
410
|
this.app.get('/api/dashboard', (_req, res) => {
|
|
441
|
-
|
|
442
|
-
res.json({ ...this.stats, analytics });
|
|
411
|
+
res.json(this.stats);
|
|
443
412
|
});
|
|
444
413
|
// --- Knowledge Base Upload ---
|
|
445
414
|
this.app.post('/api/kb/upload', async (req, res) => {
|
package/dist/cli.js
CHANGED
|
@@ -61,6 +61,7 @@ const workflow_1 = require("./core/workflow");
|
|
|
61
61
|
const versioning_1 = require("./core/versioning");
|
|
62
62
|
const providers_1 = require("./providers");
|
|
63
63
|
const knowledge_1 = require("./core/knowledge");
|
|
64
|
+
const marketplace_1 = require("./marketplace");
|
|
64
65
|
const program = new commander_1.Command();
|
|
65
66
|
const color = {
|
|
66
67
|
green: (s) => `\x1b[32m${s}\x1b[0m`,
|
|
@@ -118,7 +119,7 @@ async function select(question, options) {
|
|
|
118
119
|
program
|
|
119
120
|
.name('opc')
|
|
120
121
|
.description('OPC Agent - Open Agent Framework for business workstations')
|
|
121
|
-
.version('1.
|
|
122
|
+
.version('1.0.0');
|
|
122
123
|
// ── Init command ─────────────────────────────────────────────
|
|
123
124
|
program
|
|
124
125
|
.command('init')
|
|
@@ -138,7 +139,6 @@ program
|
|
|
138
139
|
process.exit(1);
|
|
139
140
|
}
|
|
140
141
|
fs.mkdirSync(dir, { recursive: true });
|
|
141
|
-
fs.mkdirSync(path.join(dir, 'src', 'skills'), { recursive: true });
|
|
142
142
|
const factory = TEMPLATES[template]?.factory ?? customer_service_1.createCustomerServiceConfig;
|
|
143
143
|
const config = factory();
|
|
144
144
|
config.metadata.name = name;
|
|
@@ -147,93 +147,6 @@ program
|
|
|
147
147
|
config.spec.channels.push({ type: 'web', port: 3000 });
|
|
148
148
|
}
|
|
149
149
|
fs.writeFileSync(path.join(dir, 'oad.yaml'), yaml.dump(config, { lineWidth: 120 }));
|
|
150
|
-
// agent.yaml — standalone OAD config for runtime usage
|
|
151
|
-
fs.writeFileSync(path.join(dir, 'agent.yaml'), `apiVersion: opc/v1
|
|
152
|
-
kind: Agent
|
|
153
|
-
metadata:
|
|
154
|
-
name: ${name}
|
|
155
|
-
version: 1.0.0
|
|
156
|
-
description: My AI Agent
|
|
157
|
-
spec:
|
|
158
|
-
model: qwen2.5
|
|
159
|
-
provider:
|
|
160
|
-
default: ollama
|
|
161
|
-
systemPrompt: |
|
|
162
|
-
You are a helpful AI assistant named ${name}.
|
|
163
|
-
Be concise, helpful, and friendly.
|
|
164
|
-
channels:
|
|
165
|
-
- type: web
|
|
166
|
-
port: 3000
|
|
167
|
-
memory:
|
|
168
|
-
shortTerm: true
|
|
169
|
-
longTerm:
|
|
170
|
-
provider: deepbrain
|
|
171
|
-
skills:
|
|
172
|
-
- name: echo
|
|
173
|
-
description: Echo test skill
|
|
174
|
-
`);
|
|
175
|
-
// src/index.ts — entry point
|
|
176
|
-
fs.writeFileSync(path.join(dir, 'src', 'index.ts'), `import { AgentRuntime } from 'opc-agent';
|
|
177
|
-
import { EchoSkill } from './skills/echo';
|
|
178
|
-
|
|
179
|
-
async function main() {
|
|
180
|
-
const runtime = new AgentRuntime();
|
|
181
|
-
|
|
182
|
-
// Load OAD config
|
|
183
|
-
await runtime.loadConfig('./agent.yaml');
|
|
184
|
-
|
|
185
|
-
// Initialize agent with channels, memory, etc.
|
|
186
|
-
const agent = await runtime.initialize();
|
|
187
|
-
|
|
188
|
-
// Register custom skills
|
|
189
|
-
runtime.registerSkill(new EchoSkill());
|
|
190
|
-
|
|
191
|
-
// Start serving
|
|
192
|
-
await runtime.start();
|
|
193
|
-
|
|
194
|
-
console.log('🤖 Agent is running!');
|
|
195
|
-
console.log(' Web UI: http://localhost:3000');
|
|
196
|
-
console.log(' Press Ctrl+C to stop');
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
main().catch(console.error);
|
|
200
|
-
`);
|
|
201
|
-
// src/skills/echo.ts — example skill
|
|
202
|
-
fs.writeFileSync(path.join(dir, 'src', 'skills', 'echo.ts'), `import { BaseSkill } from 'opc-agent';
|
|
203
|
-
import type { AgentContext, Message, SkillResult } from 'opc-agent';
|
|
204
|
-
|
|
205
|
-
export class EchoSkill extends BaseSkill {
|
|
206
|
-
name = 'echo';
|
|
207
|
-
description = 'Echo back the message (test skill)';
|
|
208
|
-
|
|
209
|
-
async execute(context: AgentContext, message: Message): Promise<SkillResult> {
|
|
210
|
-
if (message.content.toLowerCase().startsWith('/echo ')) {
|
|
211
|
-
const text = message.content.slice(6);
|
|
212
|
-
return this.match(\`🔊 Echo: \${text}\`);
|
|
213
|
-
}
|
|
214
|
-
return this.noMatch();
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
`);
|
|
218
|
-
// tsconfig.json
|
|
219
|
-
fs.writeFileSync(path.join(dir, 'tsconfig.json'), JSON.stringify({
|
|
220
|
-
compilerOptions: {
|
|
221
|
-
target: 'ES2022',
|
|
222
|
-
module: 'commonjs',
|
|
223
|
-
lib: ['ES2022'],
|
|
224
|
-
outDir: 'dist',
|
|
225
|
-
rootDir: 'src',
|
|
226
|
-
strict: true,
|
|
227
|
-
esModuleInterop: true,
|
|
228
|
-
skipLibCheck: true,
|
|
229
|
-
forceConsistentCasingInFileNames: true,
|
|
230
|
-
resolveJsonModule: true,
|
|
231
|
-
declaration: true,
|
|
232
|
-
sourceMap: true,
|
|
233
|
-
},
|
|
234
|
-
include: ['src/**/*'],
|
|
235
|
-
exclude: ['node_modules', 'dist'],
|
|
236
|
-
}, null, 2));
|
|
237
150
|
// .env.example
|
|
238
151
|
fs.writeFileSync(path.join(dir, '.env.example'), `# LLM API Configuration
|
|
239
152
|
OPC_LLM_API_KEY=your-api-key-here
|
|
@@ -244,9 +157,9 @@ OPC_LLM_MODEL=gpt-4o-mini
|
|
|
244
157
|
# OPC_LLM_BASE_URL=https://api.deepseek.com/v1
|
|
245
158
|
# OPC_LLM_MODEL=deepseek-chat
|
|
246
159
|
|
|
247
|
-
# For local Ollama
|
|
160
|
+
# For local Ollama:
|
|
248
161
|
# OPC_LLM_BASE_URL=http://localhost:11434/v1
|
|
249
|
-
# OPC_LLM_MODEL=
|
|
162
|
+
# OPC_LLM_MODEL=llama3
|
|
250
163
|
`);
|
|
251
164
|
// .env (copy of example)
|
|
252
165
|
fs.writeFileSync(path.join(dir, '.env'), `OPC_LLM_API_KEY=your-api-key-here
|
|
@@ -260,27 +173,20 @@ OPC_LLM_MODEL=gpt-4o-mini
|
|
|
260
173
|
private: true,
|
|
261
174
|
scripts: {
|
|
262
175
|
start: 'opc run',
|
|
263
|
-
dev: 'opc dev',
|
|
264
176
|
chat: 'opc chat',
|
|
265
|
-
build: 'tsc',
|
|
266
177
|
},
|
|
267
178
|
dependencies: {
|
|
268
|
-
'opc-agent': '^
|
|
269
|
-
},
|
|
270
|
-
devDependencies: {
|
|
271
|
-
typescript: '^5.5.0',
|
|
272
|
-
tsx: '^4.0.0',
|
|
179
|
+
'opc-agent': '^0.5.0',
|
|
273
180
|
},
|
|
274
181
|
}, null, 2));
|
|
275
182
|
// .gitignore
|
|
276
|
-
fs.writeFileSync(path.join(dir, '.gitignore'), 'node_modules\
|
|
183
|
+
fs.writeFileSync(path.join(dir, '.gitignore'), 'node_modules\n.env\n.opc-knowledge.json\ndata/\n');
|
|
277
184
|
// Dockerfile
|
|
278
185
|
fs.writeFileSync(path.join(dir, 'Dockerfile'), `FROM node:22-alpine
|
|
279
186
|
WORKDIR /app
|
|
280
187
|
COPY package.json package-lock.json* ./
|
|
281
188
|
RUN npm ci --production 2>/dev/null || npm install --production
|
|
282
|
-
COPY oad.yaml
|
|
283
|
-
COPY src/ ./src/
|
|
189
|
+
COPY oad.yaml .env* ./
|
|
284
190
|
COPY prompts/ ./prompts/ 2>/dev/null || true
|
|
285
191
|
EXPOSE 3000
|
|
286
192
|
CMD ["npx", "opc", "run"]
|
|
@@ -295,7 +201,7 @@ services:
|
|
|
295
201
|
env_file:
|
|
296
202
|
- .env
|
|
297
203
|
volumes:
|
|
298
|
-
- ./
|
|
204
|
+
- ./oad.yaml:/app/oad.yaml:ro
|
|
299
205
|
restart: unless-stopped
|
|
300
206
|
`);
|
|
301
207
|
// README.md
|
|
@@ -305,67 +211,51 @@ Created with [OPC Agent](https://github.com/Deepleaper/opc-agent) using the \`${
|
|
|
305
211
|
|
|
306
212
|
## Quick Start
|
|
307
213
|
|
|
308
|
-
1. **
|
|
214
|
+
1. **Set your API key:**
|
|
309
215
|
\`\`\`bash
|
|
310
|
-
|
|
216
|
+
# Edit .env and add your API key
|
|
217
|
+
cp .env.example .env
|
|
218
|
+
# Then edit .env with your actual key
|
|
311
219
|
\`\`\`
|
|
312
220
|
|
|
313
|
-
2. **
|
|
221
|
+
2. **Install dependencies:**
|
|
314
222
|
\`\`\`bash
|
|
315
|
-
|
|
316
|
-
ollama pull qwen2.5
|
|
317
|
-
npx tsx src/index.ts
|
|
223
|
+
npm install
|
|
318
224
|
\`\`\`
|
|
319
225
|
|
|
320
|
-
3. **
|
|
226
|
+
3. **Start the web server:**
|
|
321
227
|
\`\`\`bash
|
|
322
|
-
# Edit .env and set your API key
|
|
323
228
|
npx opc run
|
|
324
229
|
\`\`\`
|
|
325
230
|
|
|
326
231
|
4. **Open browser:** [http://localhost:3000](http://localhost:3000)
|
|
327
232
|
|
|
328
|
-
##
|
|
233
|
+
## CLI Chat
|
|
329
234
|
|
|
330
235
|
\`\`\`bash
|
|
331
|
-
npx opc
|
|
332
|
-
npx opc chat # CLI chat
|
|
333
|
-
\`\`\`
|
|
334
|
-
|
|
335
|
-
## Project Structure
|
|
336
|
-
|
|
337
|
-
\`\`\`
|
|
338
|
-
${name}/
|
|
339
|
-
├── agent.yaml # OAD agent config (used by src/index.ts)
|
|
340
|
-
├── oad.yaml # OAD config (used by opc CLI)
|
|
341
|
-
├── src/
|
|
342
|
-
│ ├── index.ts # Entry point
|
|
343
|
-
│ └── skills/
|
|
344
|
-
│ └── echo.ts # Example skill
|
|
345
|
-
├── package.json
|
|
346
|
-
└── tsconfig.json
|
|
236
|
+
npx opc chat
|
|
347
237
|
\`\`\`
|
|
348
238
|
|
|
349
239
|
## Configuration
|
|
350
240
|
|
|
351
|
-
Edit \`
|
|
241
|
+
Edit \`oad.yaml\` to customize your agent's personality, skills, and behavior.
|
|
352
242
|
`);
|
|
353
243
|
console.log(`\n${icon.success} Created agent project: ${color.bold(name + '/')}`);
|
|
354
|
-
console.log(` ${icon.file}
|
|
355
|
-
console.log(` ${icon.file}
|
|
356
|
-
console.log(` ${icon.file}
|
|
357
|
-
console.log(` ${icon.file}
|
|
358
|
-
console.log(` ${icon.file} tsconfig.json - TypeScript config`);
|
|
359
|
-
console.log(` ${icon.file} .env.example - Environment template`);
|
|
244
|
+
console.log(` ${icon.file} oad.yaml - Agent definition`);
|
|
245
|
+
console.log(` ${icon.file} package.json - Dependencies`);
|
|
246
|
+
console.log(` ${icon.file} .env.example - Environment template`);
|
|
247
|
+
console.log(` ${icon.file} .env - Environment config (edit this!)`);
|
|
360
248
|
console.log(` ${icon.file} .gitignore`);
|
|
361
249
|
console.log(` ${icon.file} Dockerfile`);
|
|
250
|
+
console.log(` ${icon.file} docker-compose.yml`);
|
|
362
251
|
console.log(` ${icon.file} README.md`);
|
|
363
252
|
console.log(`\n Template: ${color.cyan(template)}`);
|
|
364
253
|
console.log(`\n${color.bold('Next steps:')}`);
|
|
365
254
|
console.log(` 1. cd ${name}`);
|
|
366
|
-
console.log(` 2.
|
|
367
|
-
console.log(` 3.
|
|
368
|
-
console.log(` 4.
|
|
255
|
+
console.log(` 2. Edit .env — set your OPC_LLM_API_KEY`);
|
|
256
|
+
console.log(` 3. npm install`);
|
|
257
|
+
console.log(` 4. npx opc run`);
|
|
258
|
+
console.log(` 5. Open http://localhost:3000\n`);
|
|
369
259
|
});
|
|
370
260
|
// ── Chat command ─────────────────────────────────────────────
|
|
371
261
|
program
|
|
@@ -794,23 +684,51 @@ kbCmd.command('clear').action(() => {
|
|
|
794
684
|
kb.clear();
|
|
795
685
|
console.log(`${icon.success} Knowledge base cleared.`);
|
|
796
686
|
});
|
|
797
|
-
// 📦
|
|
687
|
+
// 📦 Marketplace commands ───────────────────────────────────
|
|
798
688
|
program
|
|
799
689
|
.command('publish')
|
|
800
690
|
.description('Package agent for distribution')
|
|
801
691
|
.option('-f, --file <file>', 'OAD file', 'oad.yaml')
|
|
802
692
|
.option('-o, --output <dir>', 'Output directory', '.')
|
|
803
693
|
.option('--include-kb', 'Include knowledge base')
|
|
804
|
-
.action(async () => {
|
|
805
|
-
|
|
694
|
+
.action(async (opts) => {
|
|
695
|
+
try {
|
|
696
|
+
console.log(`\n${icon.package} Packaging agent...\n`);
|
|
697
|
+
const result = await (0, marketplace_1.publishAgent)({
|
|
698
|
+
oadPath: opts.file,
|
|
699
|
+
outputDir: opts.output,
|
|
700
|
+
includeKnowledge: opts.includeKb,
|
|
701
|
+
});
|
|
702
|
+
console.log(`${icon.success} Published: ${color.bold(result.archivePath)}`);
|
|
703
|
+
console.log(` Name: ${result.manifest.name}`);
|
|
704
|
+
console.log(` Version: ${result.manifest.version}`);
|
|
705
|
+
console.log(` Files: ${result.manifest.files.length}`);
|
|
706
|
+
console.log();
|
|
707
|
+
}
|
|
708
|
+
catch (err) {
|
|
709
|
+
console.error(`${icon.error} Publish failed:`, err instanceof Error ? err.message : err);
|
|
710
|
+
process.exit(1);
|
|
711
|
+
}
|
|
806
712
|
});
|
|
807
713
|
program
|
|
808
714
|
.command('install')
|
|
809
715
|
.description('Install agent from package')
|
|
810
716
|
.argument('<source>', 'Package file path or URL')
|
|
811
717
|
.option('-d, --dir <dir>', 'Install directory')
|
|
812
|
-
.action(async () => {
|
|
813
|
-
|
|
718
|
+
.action(async (source, opts) => {
|
|
719
|
+
try {
|
|
720
|
+
console.log(`\n${icon.package} Installing agent from ${color.bold(source)}...\n`);
|
|
721
|
+
const result = await (0, marketplace_1.installAgent)({ source, targetDir: opts.dir });
|
|
722
|
+
console.log(`${icon.success} Installed: ${color.bold(result.manifest.name)} v${result.manifest.version}`);
|
|
723
|
+
console.log(` Directory: ${result.dir}`);
|
|
724
|
+
console.log(`\n${color.bold('Next steps:')}`);
|
|
725
|
+
console.log(` cd ${result.dir}`);
|
|
726
|
+
console.log(` opc run\n`);
|
|
727
|
+
}
|
|
728
|
+
catch (err) {
|
|
729
|
+
console.error(`${icon.error} Install failed:`, err instanceof Error ? err.message : err);
|
|
730
|
+
process.exit(1);
|
|
731
|
+
}
|
|
814
732
|
});
|
|
815
733
|
// 🔌 Plugin commands ────────────────────────────────────────
|
|
816
734
|
const pluginCmd = program.command('plugin').description('Manage plugins');
|
|
@@ -920,118 +838,5 @@ program
|
|
|
920
838
|
process.exit(1);
|
|
921
839
|
}
|
|
922
840
|
});
|
|
923
|
-
// ── Brain command ────────────────────────────────────────────
|
|
924
|
-
program
|
|
925
|
-
.command('brain')
|
|
926
|
-
.description('Show agent memory/brain status from DeepBrain')
|
|
927
|
-
.option('--url <url>', 'DeepBrain server URL', 'http://localhost:3333')
|
|
928
|
-
.action(async (opts) => {
|
|
929
|
-
console.log(`\n${icon.gear} ${color.bold('DeepBrain Status')} — ${color.dim(opts.url)}\n`);
|
|
930
|
-
try {
|
|
931
|
-
const res = await fetch(`${opts.url}/api/stats`);
|
|
932
|
-
if (!res.ok)
|
|
933
|
-
throw new Error(`HTTP ${res.status} ${res.statusText}`);
|
|
934
|
-
const stats = (await res.json());
|
|
935
|
-
const rows = [
|
|
936
|
-
['Total Pages', String(stats.totalPages ?? stats.pages ?? '-')],
|
|
937
|
-
['Total Chunks', String(stats.totalChunks ?? stats.chunks ?? '-')],
|
|
938
|
-
['Memory Tiers', String(stats.memoryTiers ?? stats.tiers ?? '-')],
|
|
939
|
-
['Index Size', stats.indexSize ?? '-'],
|
|
940
|
-
['Last Updated', stats.lastUpdated ?? stats.updatedAt ?? '-'],
|
|
941
|
-
];
|
|
942
|
-
const maxKey = Math.max(...rows.map(([k]) => k.length));
|
|
943
|
-
for (const [key, val] of rows) {
|
|
944
|
-
console.log(` ${color.cyan(key.padEnd(maxKey))} ${val}`);
|
|
945
|
-
}
|
|
946
|
-
console.log();
|
|
947
|
-
}
|
|
948
|
-
catch (err) {
|
|
949
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
950
|
-
if (msg.includes('ECONNREFUSED') || msg.includes('fetch failed')) {
|
|
951
|
-
console.log(` ${icon.warn} Cannot connect to DeepBrain at ${opts.url}`);
|
|
952
|
-
console.log(` ${color.dim('Is the server running? Start with: deepbrain serve')}\n`);
|
|
953
|
-
}
|
|
954
|
-
else {
|
|
955
|
-
console.error(` ${icon.error} ${msg}\n`);
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
|
-
});
|
|
959
|
-
// ── Logs command ─────────────────────────────────────────────
|
|
960
|
-
program
|
|
961
|
-
.command('logs')
|
|
962
|
-
.description('Show recent agent traces')
|
|
963
|
-
.option('-n, --limit <n>', 'Number of spans to show', '20')
|
|
964
|
-
.option('-f, --follow', 'Keep watching for new spans')
|
|
965
|
-
.action(async (opts) => {
|
|
966
|
-
const { TraceCollector } = await Promise.resolve().then(() => __importStar(require('./traces')));
|
|
967
|
-
const collector = new TraceCollector();
|
|
968
|
-
const limit = parseInt(opts.limit) || 20;
|
|
969
|
-
const printSpans = (spans) => {
|
|
970
|
-
const slice = spans.slice(-limit);
|
|
971
|
-
if (slice.length === 0) {
|
|
972
|
-
console.log(` ${icon.info} No traces yet. Interact with the agent to generate traces.`);
|
|
973
|
-
return;
|
|
974
|
-
}
|
|
975
|
-
for (const span of slice) {
|
|
976
|
-
const duration = span.endTime
|
|
977
|
-
? `${span.endTime.getTime() - span.startTime.getTime()}ms`
|
|
978
|
-
: 'ongoing';
|
|
979
|
-
const statusIcon = span.status === 'ok' ? icon.success : span.status === 'error' ? icon.error : color.dim('○');
|
|
980
|
-
const time = span.startTime.toLocaleTimeString();
|
|
981
|
-
console.log(` ${statusIcon} ${color.dim(time)} ${color.bold(span.name)} ${color.dim(duration)}`);
|
|
982
|
-
}
|
|
983
|
-
};
|
|
984
|
-
console.log(`\n${icon.gear} ${color.bold('Agent Traces')}\n`);
|
|
985
|
-
const spans = collector.getBufferedSpans();
|
|
986
|
-
printSpans(spans);
|
|
987
|
-
if (opts.follow) {
|
|
988
|
-
console.log(`\n ${color.dim('Watching for new traces... (Ctrl+C to stop)')}\n`);
|
|
989
|
-
let lastCount = spans.length;
|
|
990
|
-
const interval = setInterval(() => {
|
|
991
|
-
const current = collector.getBufferedSpans();
|
|
992
|
-
if (current.length > lastCount) {
|
|
993
|
-
const newSpans = current.slice(lastCount);
|
|
994
|
-
printSpans(newSpans);
|
|
995
|
-
lastCount = current.length;
|
|
996
|
-
}
|
|
997
|
-
}, 1000);
|
|
998
|
-
process.on('SIGINT', () => { clearInterval(interval); process.exit(0); });
|
|
999
|
-
}
|
|
1000
|
-
else {
|
|
1001
|
-
console.log();
|
|
1002
|
-
}
|
|
1003
|
-
});
|
|
1004
|
-
// ── Score command ────────────────────────────────────────────
|
|
1005
|
-
program
|
|
1006
|
-
.command('score')
|
|
1007
|
-
.description('Show agent performance score')
|
|
1008
|
-
.action(async () => {
|
|
1009
|
-
console.log(`\n${icon.gear} ${color.bold('Agent Performance Score')}\n`);
|
|
1010
|
-
try {
|
|
1011
|
-
const engine = new analytics_engine_1.AnalyticsEngine('.');
|
|
1012
|
-
const stats = engine.getStats();
|
|
1013
|
-
if (!stats || stats.totalMessages === 0) {
|
|
1014
|
-
console.log(` ${icon.info} No score data yet. Run the agent first.\n`);
|
|
1015
|
-
return;
|
|
1016
|
-
}
|
|
1017
|
-
const errorRate = stats.totalMessages > 0 ? (stats.totalErrors / stats.totalMessages) : 0;
|
|
1018
|
-
const rows = [
|
|
1019
|
-
['Total Messages', String(stats.totalMessages)],
|
|
1020
|
-
['Total LLM Calls', String(stats.totalLLMCalls)],
|
|
1021
|
-
['Total Tool Uses', String(stats.totalToolUses)],
|
|
1022
|
-
['Avg Response Time', `${stats.avgResponseTimeMs}ms`],
|
|
1023
|
-
['Error Rate', `${(errorRate * 100).toFixed(1)}%`],
|
|
1024
|
-
['Token Usage', `${stats.totalTokens.total} tokens (in: ${stats.totalTokens.input}, out: ${stats.totalTokens.output})`],
|
|
1025
|
-
];
|
|
1026
|
-
const maxKey = Math.max(...rows.map(([k]) => k.length));
|
|
1027
|
-
for (const [key, val] of rows) {
|
|
1028
|
-
console.log(` ${color.cyan(key.padEnd(maxKey))} ${val}`);
|
|
1029
|
-
}
|
|
1030
|
-
console.log();
|
|
1031
|
-
}
|
|
1032
|
-
catch {
|
|
1033
|
-
console.log(` ${icon.info} No score data yet. Run the agent first.\n`);
|
|
1034
|
-
}
|
|
1035
|
-
});
|
|
1036
841
|
program.parse();
|
|
1037
842
|
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface DashboardConfig {
|
|
2
|
+
/** Enable the dashboard (default: false) */
|
|
3
|
+
enabled: boolean;
|
|
4
|
+
/** HTTP port (default: 4100) */
|
|
5
|
+
port?: number;
|
|
6
|
+
/** Bind address (default: 127.0.0.1 for security) */
|
|
7
|
+
host?: string;
|
|
8
|
+
/** Enable CORS (default: false) */
|
|
9
|
+
cors?: boolean;
|
|
10
|
+
}
|
|
11
|
+
interface SessionSummary {
|
|
12
|
+
id: string;
|
|
13
|
+
channel: string;
|
|
14
|
+
messages: number;
|
|
15
|
+
lastActive: number;
|
|
16
|
+
status: 'active' | 'idle' | 'closed';
|
|
17
|
+
}
|
|
18
|
+
export declare class Dashboard {
|
|
19
|
+
private app;
|
|
20
|
+
private server;
|
|
21
|
+
private config;
|
|
22
|
+
private startTime;
|
|
23
|
+
private stats;
|
|
24
|
+
constructor(config: DashboardConfig);
|
|
25
|
+
private setupRoutes;
|
|
26
|
+
private getState;
|
|
27
|
+
trackSession(session: SessionSummary): void;
|
|
28
|
+
trackToolCall(toolName: string): void;
|
|
29
|
+
trackChannel(name: string, connected: boolean, messages?: number): void;
|
|
30
|
+
start(): Promise<void>;
|
|
31
|
+
stop(): Promise<void>;
|
|
32
|
+
private renderHTML;
|
|
33
|
+
}
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=dashboard.d.ts.map
|