opc-agent 1.3.2 → 1.4.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.
Files changed (186) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +20 -0
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +14 -0
  3. package/.github/PULL_REQUEST_TEMPLATE.md +13 -0
  4. package/.github/workflows/ci.yml +24 -0
  5. package/CHANGELOG.md +23 -63
  6. package/CONTRIBUTING.md +21 -60
  7. package/README.md +235 -358
  8. package/README.zh-CN.md +415 -415
  9. package/dist/channels/slack.js +93 -10
  10. package/dist/channels/web.d.ts +10 -0
  11. package/dist/channels/web.js +33 -2
  12. package/dist/cli.js +255 -60
  13. package/dist/core/runtime.d.ts +4 -0
  14. package/dist/core/runtime.js +27 -0
  15. package/dist/deploy/hermes.js +22 -22
  16. package/dist/deploy/openclaw.js +31 -40
  17. package/dist/index.d.ts +3 -10
  18. package/dist/index.js +6 -15
  19. package/dist/providers/index.d.ts +1 -1
  20. package/dist/providers/index.js +7 -1
  21. package/dist/schema/oad.d.ts +1 -2
  22. package/dist/templates/code-reviewer.d.ts +0 -8
  23. package/dist/templates/code-reviewer.js +5 -9
  24. package/dist/templates/customer-service.d.ts +0 -8
  25. package/dist/templates/customer-service.js +2 -6
  26. package/dist/templates/data-analyst.d.ts +0 -8
  27. package/dist/templates/data-analyst.js +5 -9
  28. package/dist/templates/knowledge-base.d.ts +0 -8
  29. package/dist/templates/knowledge-base.js +2 -6
  30. package/dist/templates/sales-assistant.d.ts +0 -8
  31. package/dist/templates/sales-assistant.js +4 -8
  32. package/dist/templates/teacher.d.ts +0 -8
  33. package/dist/templates/teacher.js +6 -10
  34. package/dist/traces/index.d.ts +49 -0
  35. package/dist/traces/index.js +102 -0
  36. package/docs/.vitepress/config.ts +103 -103
  37. package/docs/api/cli.md +48 -48
  38. package/docs/api/oad-schema.md +64 -64
  39. package/docs/api/sdk.md +80 -80
  40. package/docs/guide/concepts.md +51 -51
  41. package/docs/guide/configuration.md +79 -79
  42. package/docs/guide/deployment.md +42 -42
  43. package/docs/guide/getting-started.md +44 -44
  44. package/docs/guide/templates.md +28 -28
  45. package/docs/guide/testing.md +84 -84
  46. package/docs/index.md +27 -27
  47. package/docs/zh/api/cli.md +54 -54
  48. package/docs/zh/api/oad-schema.md +87 -87
  49. package/docs/zh/api/sdk.md +102 -102
  50. package/docs/zh/guide/concepts.md +104 -104
  51. package/docs/zh/guide/configuration.md +135 -135
  52. package/docs/zh/guide/deployment.md +81 -81
  53. package/docs/zh/guide/getting-started.md +82 -82
  54. package/docs/zh/guide/templates.md +84 -84
  55. package/docs/zh/guide/testing.md +88 -88
  56. package/docs/zh/index.md +27 -27
  57. package/examples/README.md +22 -0
  58. package/examples/basic-agent.ts +90 -0
  59. package/examples/brain-integration.ts +71 -0
  60. package/examples/customer-service-demo/README.md +90 -90
  61. package/examples/customer-service-demo/oad.yaml +107 -107
  62. package/examples/multi-channel.ts +74 -0
  63. package/package.json +1 -1
  64. package/src/analytics/index.ts +66 -66
  65. package/src/channels/discord.ts +192 -192
  66. package/src/channels/email.ts +177 -177
  67. package/src/channels/feishu.ts +236 -236
  68. package/src/channels/index.ts +15 -15
  69. package/src/channels/slack.ts +217 -160
  70. package/src/channels/telegram.ts +90 -90
  71. package/src/channels/voice.ts +106 -106
  72. package/src/channels/web.ts +38 -2
  73. package/src/channels/webhook.ts +199 -199
  74. package/src/channels/websocket.ts +87 -87
  75. package/src/channels/wechat.ts +149 -149
  76. package/src/cli.ts +282 -58
  77. package/src/core/a2a.ts +143 -143
  78. package/src/core/agent.ts +152 -152
  79. package/src/core/analytics-engine.ts +186 -186
  80. package/src/core/auth.ts +57 -57
  81. package/src/core/cache.ts +141 -141
  82. package/src/core/compose.ts +77 -77
  83. package/src/core/config.ts +14 -14
  84. package/src/core/errors.ts +148 -148
  85. package/src/core/hitl.ts +138 -138
  86. package/src/core/logger.ts +57 -57
  87. package/src/core/orchestrator.ts +215 -215
  88. package/src/core/performance.ts +187 -187
  89. package/src/core/rate-limiter.ts +128 -128
  90. package/src/core/room.ts +109 -109
  91. package/src/core/runtime.ts +183 -152
  92. package/src/core/sandbox.ts +101 -101
  93. package/src/core/security.ts +171 -171
  94. package/src/core/types.ts +68 -68
  95. package/src/core/versioning.ts +106 -106
  96. package/src/core/watch.ts +178 -178
  97. package/src/core/workflow.ts +235 -235
  98. package/src/deploy/hermes.ts +156 -156
  99. package/src/deploy/openclaw.ts +190 -200
  100. package/src/i18n/index.ts +216 -216
  101. package/src/index.ts +3 -10
  102. package/src/memory/deepbrain.ts +108 -108
  103. package/src/memory/index.ts +34 -34
  104. package/src/plugins/index.ts +208 -208
  105. package/src/providers/index.ts +9 -1
  106. package/src/schema/oad.ts +154 -155
  107. package/src/skills/base.ts +16 -16
  108. package/src/skills/document.ts +100 -100
  109. package/src/skills/http.ts +35 -35
  110. package/src/skills/index.ts +27 -27
  111. package/src/skills/scheduler.ts +80 -80
  112. package/src/skills/webhook-trigger.ts +59 -59
  113. package/src/templates/code-reviewer.ts +30 -34
  114. package/src/templates/customer-service.ts +76 -80
  115. package/src/templates/data-analyst.ts +66 -70
  116. package/src/templates/executive-assistant.ts +71 -71
  117. package/src/templates/financial-advisor.ts +60 -60
  118. package/src/templates/knowledge-base.ts +27 -31
  119. package/src/templates/legal-assistant.ts +71 -71
  120. package/src/templates/sales-assistant.ts +75 -79
  121. package/src/templates/teacher.ts +75 -79
  122. package/src/testing/index.ts +181 -181
  123. package/src/tools/calculator.ts +73 -73
  124. package/src/tools/datetime.ts +149 -149
  125. package/src/tools/json-transform.ts +187 -187
  126. package/src/tools/mcp.ts +76 -76
  127. package/src/tools/text-analysis.ts +116 -116
  128. package/src/traces/index.ts +132 -0
  129. package/templates/Dockerfile +15 -15
  130. package/templates/code-reviewer/README.md +27 -27
  131. package/templates/code-reviewer/oad.yaml +41 -41
  132. package/templates/customer-service/README.md +22 -22
  133. package/templates/customer-service/oad.yaml +36 -36
  134. package/templates/docker-compose.yml +21 -21
  135. package/templates/ecommerce-assistant/README.md +45 -45
  136. package/templates/ecommerce-assistant/oad.yaml +47 -47
  137. package/templates/knowledge-base/README.md +28 -28
  138. package/templates/knowledge-base/oad.yaml +38 -38
  139. package/templates/sales-assistant/README.md +26 -26
  140. package/templates/sales-assistant/oad.yaml +43 -43
  141. package/templates/tech-support/README.md +43 -43
  142. package/templates/tech-support/oad.yaml +45 -45
  143. package/test-agent/Dockerfile +9 -0
  144. package/test-agent/README.md +50 -0
  145. package/test-agent/agent.yaml +23 -0
  146. package/test-agent/docker-compose.yml +11 -0
  147. package/test-agent/oad.yaml +31 -0
  148. package/test-agent/package-lock.json +1492 -0
  149. package/test-agent/package.json +18 -0
  150. package/test-agent/src/index.ts +24 -0
  151. package/test-agent/src/skills/echo.ts +15 -0
  152. package/test-agent/tsconfig.json +25 -0
  153. package/tests/a2a.test.ts +66 -66
  154. package/tests/agent.test.ts +72 -72
  155. package/tests/analytics.test.ts +50 -50
  156. package/tests/channel.test.ts +39 -39
  157. package/tests/e2e.test.ts +134 -134
  158. package/tests/errors.test.ts +83 -83
  159. package/tests/hitl.test.ts +71 -71
  160. package/tests/i18n.test.ts +41 -41
  161. package/tests/mcp.test.ts +54 -54
  162. package/tests/oad.test.ts +68 -68
  163. package/tests/performance.test.ts +115 -115
  164. package/tests/plugin.test.ts +74 -74
  165. package/tests/room.test.ts +106 -106
  166. package/tests/runtime.test.ts +42 -42
  167. package/tests/sandbox.test.ts +46 -46
  168. package/tests/security.test.ts +60 -60
  169. package/tests/templates.test.ts +77 -77
  170. package/tests/v070.test.ts +76 -76
  171. package/tests/versioning.test.ts +75 -75
  172. package/tests/voice.test.ts +61 -61
  173. package/tests/webhook.test.ts +29 -29
  174. package/tests/workflow.test.ts +143 -143
  175. package/tsconfig.json +19 -19
  176. package/vitest.config.ts +9 -9
  177. package/dist/core/dashboard.d.ts +0 -35
  178. package/dist/core/dashboard.js +0 -157
  179. package/dist/core/priority.d.ts +0 -52
  180. package/dist/core/priority.js +0 -102
  181. package/src/core/dashboard.ts +0 -219
  182. package/src/core/priority.ts +0 -140
  183. package/src/dtv/data.ts +0 -29
  184. package/src/dtv/trust.ts +0 -43
  185. package/src/dtv/value.ts +0 -47
  186. package/src/marketplace/index.ts +0 -223
package/src/cli.ts CHANGED
@@ -27,9 +27,9 @@ import { WorkflowEngine } from './core/workflow';
27
27
  import { VersionManager } from './core/versioning';
28
28
  import { createProvider } from './providers';
29
29
  import { KnowledgeBase } from './core/knowledge';
30
- import { publishAgent, installAgent } from './marketplace';
31
30
 
32
31
  import { PluginManager, createLoggingPlugin, createAnalyticsPlugin, createRateLimitPlugin } from './plugins';
32
+ import type { Span } from './traces';
33
33
 
34
34
  const program = new Command();
35
35
 
@@ -94,7 +94,7 @@ async function select(question: string, options: { value: string; label: string
94
94
  program
95
95
  .name('opc')
96
96
  .description('OPC Agent - Open Agent Framework for business workstations')
97
- .version('1.0.0');
97
+ .version('1.4.0');
98
98
 
99
99
  // ── Init command ─────────────────────────────────────────────
100
100
 
@@ -119,6 +119,8 @@ program
119
119
  }
120
120
 
121
121
  fs.mkdirSync(dir, { recursive: true });
122
+ fs.mkdirSync(path.join(dir, 'src', 'skills'), { recursive: true });
123
+
122
124
  const factory = TEMPLATES[template]?.factory ?? createCustomerServiceConfig;
123
125
  const config = factory();
124
126
  config.metadata.name = name;
@@ -130,6 +132,113 @@ program
130
132
 
131
133
  fs.writeFileSync(path.join(dir, 'oad.yaml'), yaml.dump(config, { lineWidth: 120 }));
132
134
 
135
+ // agent.yaml — standalone OAD config for runtime usage
136
+ fs.writeFileSync(
137
+ path.join(dir, 'agent.yaml'),
138
+ `apiVersion: opc/v1
139
+ kind: Agent
140
+ metadata:
141
+ name: ${name}
142
+ version: 1.0.0
143
+ description: My AI Agent
144
+ spec:
145
+ model: qwen2.5
146
+ provider:
147
+ default: ollama
148
+ systemPrompt: |
149
+ You are a helpful AI assistant named ${name}.
150
+ Be concise, helpful, and friendly.
151
+ channels:
152
+ - type: web
153
+ port: 3000
154
+ memory:
155
+ shortTerm: true
156
+ longTerm:
157
+ provider: deepbrain
158
+ skills:
159
+ - name: echo
160
+ description: Echo test skill
161
+ `,
162
+ );
163
+
164
+ // src/index.ts — entry point
165
+ fs.writeFileSync(
166
+ path.join(dir, 'src', 'index.ts'),
167
+ `import { AgentRuntime } from 'opc-agent';
168
+ import { EchoSkill } from './skills/echo';
169
+
170
+ async function main() {
171
+ const runtime = new AgentRuntime();
172
+
173
+ // Load OAD config
174
+ await runtime.loadConfig('./agent.yaml');
175
+
176
+ // Initialize agent with channels, memory, etc.
177
+ const agent = await runtime.initialize();
178
+
179
+ // Register custom skills
180
+ runtime.registerSkill(new EchoSkill());
181
+
182
+ // Start serving
183
+ await runtime.start();
184
+
185
+ console.log('🤖 Agent is running!');
186
+ console.log(' Web UI: http://localhost:3000');
187
+ console.log(' Press Ctrl+C to stop');
188
+ }
189
+
190
+ main().catch(console.error);
191
+ `,
192
+ );
193
+
194
+ // src/skills/echo.ts — example skill
195
+ fs.writeFileSync(
196
+ path.join(dir, 'src', 'skills', 'echo.ts'),
197
+ `import { BaseSkill } from 'opc-agent';
198
+ import type { AgentContext, Message, SkillResult } from 'opc-agent';
199
+
200
+ export class EchoSkill extends BaseSkill {
201
+ name = 'echo';
202
+ description = 'Echo back the message (test skill)';
203
+
204
+ async execute(context: AgentContext, message: Message): Promise<SkillResult> {
205
+ if (message.content.toLowerCase().startsWith('/echo ')) {
206
+ const text = message.content.slice(6);
207
+ return this.match(\`🔊 Echo: \${text}\`);
208
+ }
209
+ return this.noMatch();
210
+ }
211
+ }
212
+ `,
213
+ );
214
+
215
+ // tsconfig.json
216
+ fs.writeFileSync(
217
+ path.join(dir, 'tsconfig.json'),
218
+ JSON.stringify(
219
+ {
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
+ },
237
+ null,
238
+ 2,
239
+ ),
240
+ );
241
+
133
242
  // .env.example
134
243
  fs.writeFileSync(
135
244
  path.join(dir, '.env.example'),
@@ -142,9 +251,9 @@ OPC_LLM_MODEL=gpt-4o-mini
142
251
  # OPC_LLM_BASE_URL=https://api.deepseek.com/v1
143
252
  # OPC_LLM_MODEL=deepseek-chat
144
253
 
145
- # For local Ollama:
254
+ # For local Ollama (default in agent.yaml):
146
255
  # OPC_LLM_BASE_URL=http://localhost:11434/v1
147
- # OPC_LLM_MODEL=llama3
256
+ # OPC_LLM_MODEL=qwen2.5
148
257
  `,
149
258
  );
150
259
 
@@ -167,10 +276,16 @@ OPC_LLM_MODEL=gpt-4o-mini
167
276
  private: true,
168
277
  scripts: {
169
278
  start: 'opc run',
279
+ dev: 'opc dev',
170
280
  chat: 'opc chat',
281
+ build: 'tsc',
171
282
  },
172
283
  dependencies: {
173
- 'opc-agent': '^0.5.0',
284
+ 'opc-agent': '^1.3.0',
285
+ },
286
+ devDependencies: {
287
+ typescript: '^5.5.0',
288
+ tsx: '^4.0.0',
174
289
  },
175
290
  },
176
291
  null,
@@ -179,7 +294,7 @@ OPC_LLM_MODEL=gpt-4o-mini
179
294
  );
180
295
 
181
296
  // .gitignore
182
- fs.writeFileSync(path.join(dir, '.gitignore'), 'node_modules\n.env\n.opc-knowledge.json\ndata/\n');
297
+ fs.writeFileSync(path.join(dir, '.gitignore'), 'node_modules\ndist\n.env\n.opc-knowledge.json\ndata/\n');
183
298
 
184
299
  // Dockerfile
185
300
  fs.writeFileSync(
@@ -188,7 +303,8 @@ OPC_LLM_MODEL=gpt-4o-mini
188
303
  WORKDIR /app
189
304
  COPY package.json package-lock.json* ./
190
305
  RUN npm ci --production 2>/dev/null || npm install --production
191
- COPY oad.yaml .env* ./
306
+ COPY oad.yaml agent.yaml .env* ./
307
+ COPY src/ ./src/
192
308
  COPY prompts/ ./prompts/ 2>/dev/null || true
193
309
  EXPOSE 3000
194
310
  CMD ["npx", "opc", "run"]
@@ -207,7 +323,7 @@ services:
207
323
  env_file:
208
324
  - .env
209
325
  volumes:
210
- - ./oad.yaml:/app/oad.yaml:ro
326
+ - ./agent.yaml:/app/agent.yaml:ro
211
327
  restart: unless-stopped
212
328
  `,
213
329
  );
@@ -221,53 +337,69 @@ Created with [OPC Agent](https://github.com/Deepleaper/opc-agent) using the \`${
221
337
 
222
338
  ## Quick Start
223
339
 
224
- 1. **Set your API key:**
340
+ 1. **Install dependencies:**
225
341
  \`\`\`bash
226
- # Edit .env and add your API key
227
- cp .env.example .env
228
- # Then edit .env with your actual key
342
+ npm install
229
343
  \`\`\`
230
344
 
231
- 2. **Install dependencies:**
345
+ 2. **Run with Ollama (default):**
232
346
  \`\`\`bash
233
- npm install
347
+ # Make sure Ollama is running with qwen2.5 model
348
+ ollama pull qwen2.5
349
+ npx tsx src/index.ts
234
350
  \`\`\`
235
351
 
236
- 3. **Start the web server:**
352
+ 3. **Or use OpenAI/other providers:**
237
353
  \`\`\`bash
354
+ # Edit .env and set your API key
238
355
  npx opc run
239
356
  \`\`\`
240
357
 
241
358
  4. **Open browser:** [http://localhost:3000](http://localhost:3000)
242
359
 
243
- ## CLI Chat
360
+ ## Development
244
361
 
245
362
  \`\`\`bash
246
- npx opc chat
363
+ npx opc dev # Hot-reload mode
364
+ npx opc chat # CLI chat
365
+ \`\`\`
366
+
367
+ ## Project Structure
368
+
369
+ \`\`\`
370
+ ${name}/
371
+ ├── agent.yaml # OAD agent config (used by src/index.ts)
372
+ ├── oad.yaml # OAD config (used by opc CLI)
373
+ ├── src/
374
+ │ ├── index.ts # Entry point
375
+ │ └── skills/
376
+ │ └── echo.ts # Example skill
377
+ ├── package.json
378
+ └── tsconfig.json
247
379
  \`\`\`
248
380
 
249
381
  ## Configuration
250
382
 
251
- Edit \`oad.yaml\` to customize your agent's personality, skills, and behavior.
383
+ Edit \`agent.yaml\` to customize your agent's personality, skills, and behavior.
252
384
  `,
253
385
  );
254
386
 
255
387
  console.log(`\n${icon.success} Created agent project: ${color.bold(name + '/')}`);
256
- console.log(` ${icon.file} oad.yaml - Agent definition`);
257
- console.log(` ${icon.file} package.json - Dependencies`);
258
- console.log(` ${icon.file} .env.example - Environment template`);
259
- console.log(` ${icon.file} .env - Environment config (edit this!)`);
388
+ console.log(` ${icon.file} agent.yaml - Agent definition (OAD)`);
389
+ console.log(` ${icon.file} src/index.ts - Entry point`);
390
+ console.log(` ${icon.file} src/skills/echo.ts - Example skill`);
391
+ console.log(` ${icon.file} package.json - Dependencies`);
392
+ console.log(` ${icon.file} tsconfig.json - TypeScript config`);
393
+ console.log(` ${icon.file} .env.example - Environment template`);
260
394
  console.log(` ${icon.file} .gitignore`);
261
395
  console.log(` ${icon.file} Dockerfile`);
262
- console.log(` ${icon.file} docker-compose.yml`);
263
396
  console.log(` ${icon.file} README.md`);
264
397
  console.log(`\n Template: ${color.cyan(template)}`);
265
398
  console.log(`\n${color.bold('Next steps:')}`);
266
399
  console.log(` 1. cd ${name}`);
267
- console.log(` 2. Edit .env — set your OPC_LLM_API_KEY`);
268
- console.log(` 3. npm install`);
269
- console.log(` 4. npx opc run`);
270
- console.log(` 5. Open http://localhost:3000\n`);
400
+ console.log(` 2. npm install`);
401
+ console.log(` 3. npx tsx src/index.ts ${color.dim('# or: npx opc run')}`);
402
+ console.log(` 4. Open http://localhost:3000\n`);
271
403
  });
272
404
 
273
405
  // ── Chat command ─────────────────────────────────────────────
@@ -721,7 +853,7 @@ kbCmd.command('clear').action(() => {
721
853
  console.log(`${icon.success} Knowledge base cleared.`);
722
854
  });
723
855
 
724
- // 📦 Marketplace commands ───────────────────────────────────
856
+ // 📦 Package commands ───────────────────────────────────
725
857
 
726
858
  program
727
859
  .command('publish')
@@ -729,23 +861,8 @@ program
729
861
  .option('-f, --file <file>', 'OAD file', 'oad.yaml')
730
862
  .option('-o, --output <dir>', 'Output directory', '.')
731
863
  .option('--include-kb', 'Include knowledge base')
732
- .action(async (opts: { file: string; output: string; includeKb?: boolean }) => {
733
- try {
734
- console.log(`\n${icon.package} Packaging agent...\n`);
735
- const result = await publishAgent({
736
- oadPath: opts.file,
737
- outputDir: opts.output,
738
- includeKnowledge: opts.includeKb,
739
- });
740
- console.log(`${icon.success} Published: ${color.bold(result.archivePath)}`);
741
- console.log(` Name: ${result.manifest.name}`);
742
- console.log(` Version: ${result.manifest.version}`);
743
- console.log(` Files: ${result.manifest.files.length}`);
744
- console.log();
745
- } catch (err) {
746
- console.error(`${icon.error} Publish failed:`, err instanceof Error ? err.message : err);
747
- process.exit(1);
748
- }
864
+ .action(async () => {
865
+ console.log(`\n${icon.package} Agent packaging coming soon.\n`);
749
866
  });
750
867
 
751
868
  program
@@ -753,19 +870,8 @@ program
753
870
  .description('Install agent from package')
754
871
  .argument('<source>', 'Package file path or URL')
755
872
  .option('-d, --dir <dir>', 'Install directory')
756
- .action(async (source: string, opts: { dir?: string }) => {
757
- try {
758
- console.log(`\n${icon.package} Installing agent from ${color.bold(source)}...\n`);
759
- const result = await installAgent({ source, targetDir: opts.dir });
760
- console.log(`${icon.success} Installed: ${color.bold(result.manifest.name)} v${result.manifest.version}`);
761
- console.log(` Directory: ${result.dir}`);
762
- console.log(`\n${color.bold('Next steps:')}`);
763
- console.log(` cd ${result.dir}`);
764
- console.log(` opc run\n`);
765
- } catch (err) {
766
- console.error(`${icon.error} Install failed:`, err instanceof Error ? err.message : err);
767
- process.exit(1);
768
- }
873
+ .action(async () => {
874
+ console.log(`\n${icon.package} Agent install coming soon.\n`);
769
875
  });
770
876
 
771
877
  // 🔌 Plugin commands ────────────────────────────────────────
@@ -873,4 +979,122 @@ program
873
979
  }
874
980
  });
875
981
 
982
+ // ── Brain command ────────────────────────────────────────────
983
+
984
+ program
985
+ .command('brain')
986
+ .description('Show agent memory/brain status from DeepBrain')
987
+ .option('--url <url>', 'DeepBrain server URL', 'http://localhost:3333')
988
+ .action(async (opts: { url: string }) => {
989
+ console.log(`\n${icon.gear} ${color.bold('DeepBrain Status')} — ${color.dim(opts.url)}\n`);
990
+ try {
991
+ const res = await fetch(`${opts.url}/api/stats`);
992
+ if (!res.ok) throw new Error(`HTTP ${res.status} ${res.statusText}`);
993
+ const stats = (await res.json()) as Record<string, any>;
994
+ const rows: [string, string][] = [
995
+ ['Total Pages', String(stats.totalPages ?? stats.pages ?? '-')],
996
+ ['Total Chunks', String(stats.totalChunks ?? stats.chunks ?? '-')],
997
+ ['Memory Tiers', String(stats.memoryTiers ?? stats.tiers ?? '-')],
998
+ ['Index Size', stats.indexSize ?? '-'],
999
+ ['Last Updated', stats.lastUpdated ?? stats.updatedAt ?? '-'],
1000
+ ];
1001
+ const maxKey = Math.max(...rows.map(([k]) => k.length));
1002
+ for (const [key, val] of rows) {
1003
+ console.log(` ${color.cyan(key.padEnd(maxKey))} ${val}`);
1004
+ }
1005
+ console.log();
1006
+ } catch (err) {
1007
+ const msg = err instanceof Error ? err.message : String(err);
1008
+ if (msg.includes('ECONNREFUSED') || msg.includes('fetch failed')) {
1009
+ console.log(` ${icon.warn} Cannot connect to DeepBrain at ${opts.url}`);
1010
+ console.log(` ${color.dim('Is the server running? Start with: deepbrain serve')}\n`);
1011
+ } else {
1012
+ console.error(` ${icon.error} ${msg}\n`);
1013
+ }
1014
+ }
1015
+ });
1016
+
1017
+ // ── Logs command ─────────────────────────────────────────────
1018
+
1019
+ program
1020
+ .command('logs')
1021
+ .description('Show recent agent traces')
1022
+ .option('-n, --limit <n>', 'Number of spans to show', '20')
1023
+ .option('-f, --follow', 'Keep watching for new spans')
1024
+ .action(async (opts: { limit: string; follow?: boolean }) => {
1025
+ const { TraceCollector } = await import('./traces');
1026
+ const collector = new TraceCollector();
1027
+ const limit = parseInt(opts.limit) || 20;
1028
+
1029
+ const printSpans = (spans: readonly Span[]) => {
1030
+ const slice = spans.slice(-limit);
1031
+ if (slice.length === 0) {
1032
+ console.log(` ${icon.info} No traces yet. Interact with the agent to generate traces.`);
1033
+ return;
1034
+ }
1035
+ for (const span of slice) {
1036
+ const duration = span.endTime
1037
+ ? `${span.endTime.getTime() - span.startTime.getTime()}ms`
1038
+ : 'ongoing';
1039
+ const statusIcon = span.status === 'ok' ? icon.success : span.status === 'error' ? icon.error : color.dim('○');
1040
+ const time = span.startTime.toLocaleTimeString();
1041
+ console.log(` ${statusIcon} ${color.dim(time)} ${color.bold(span.name)} ${color.dim(duration)}`);
1042
+ }
1043
+ };
1044
+
1045
+ console.log(`\n${icon.gear} ${color.bold('Agent Traces')}\n`);
1046
+ const spans = collector.getBufferedSpans();
1047
+ printSpans(spans);
1048
+
1049
+ if (opts.follow) {
1050
+ console.log(`\n ${color.dim('Watching for new traces... (Ctrl+C to stop)')}\n`);
1051
+ let lastCount = spans.length;
1052
+ const interval = setInterval(() => {
1053
+ const current = collector.getBufferedSpans();
1054
+ if (current.length > lastCount) {
1055
+ const newSpans = current.slice(lastCount);
1056
+ printSpans(newSpans);
1057
+ lastCount = current.length;
1058
+ }
1059
+ }, 1000);
1060
+ process.on('SIGINT', () => { clearInterval(interval); process.exit(0); });
1061
+ } else {
1062
+ console.log();
1063
+ }
1064
+ });
1065
+
1066
+ // ── Score command ────────────────────────────────────────────
1067
+
1068
+ program
1069
+ .command('score')
1070
+ .description('Show agent performance score')
1071
+ .action(async () => {
1072
+ console.log(`\n${icon.gear} ${color.bold('Agent Performance Score')}\n`);
1073
+ try {
1074
+ const engine = new AnalyticsEngine('.');
1075
+ const stats = engine.getStats();
1076
+ if (!stats || stats.totalMessages === 0) {
1077
+ console.log(` ${icon.info} No score data yet. Run the agent first.\n`);
1078
+ return;
1079
+ }
1080
+ const errorRate = stats.totalMessages > 0 ? (stats.totalErrors / stats.totalMessages) : 0;
1081
+ const rows: [string, string][] = [
1082
+ ['Total Messages', String(stats.totalMessages)],
1083
+ ['Total LLM Calls', String(stats.totalLLMCalls)],
1084
+ ['Total Tool Uses', String(stats.totalToolUses)],
1085
+ ['Avg Response Time', `${stats.avgResponseTimeMs}ms`],
1086
+ ['Error Rate', `${(errorRate * 100).toFixed(1)}%`],
1087
+ ['Token Usage', `${stats.totalTokens.total} tokens (in: ${stats.totalTokens.input}, out: ${stats.totalTokens.output})`],
1088
+ ];
1089
+ const maxKey = Math.max(...rows.map(([k]) => k.length));
1090
+ for (const [key, val] of rows) {
1091
+ console.log(` ${color.cyan(key.padEnd(maxKey))} ${val}`);
1092
+ }
1093
+ console.log();
1094
+ } catch {
1095
+ console.log(` ${icon.info} No score data yet. Run the agent first.\n`);
1096
+ }
1097
+ });
1098
+
876
1099
  program.parse();
1100
+