opc-agent 1.3.1 → 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.
- package/.github/ISSUE_TEMPLATE/bug_report.md +20 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +14 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +13 -0
- package/CHANGELOG.md +23 -57
- package/CONTRIBUTING.md +36 -75
- package/dist/channels/slack.js +93 -10
- package/dist/channels/web.d.ts +10 -0
- package/dist/channels/web.js +33 -2
- package/dist/cli.js +137 -26
- package/dist/core/runtime.d.ts +4 -0
- package/dist/core/runtime.js +27 -0
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.js +7 -1
- package/examples/README.md +22 -0
- package/examples/basic-agent.ts +90 -0
- package/examples/brain-integration.ts +71 -0
- package/examples/multi-channel.ts +74 -0
- package/package.json +1 -1
- package/src/channels/slack.ts +67 -10
- package/src/channels/web.ts +38 -2
- package/src/cli.ts +158 -26
- package/src/core/runtime.ts +31 -0
- package/src/providers/index.ts +9 -1
- package/test-agent/Dockerfile +9 -0
- package/test-agent/README.md +50 -0
- package/test-agent/agent.yaml +23 -0
- package/test-agent/docker-compose.yml +11 -0
- package/test-agent/oad.yaml +31 -0
- package/test-agent/package-lock.json +1492 -0
- package/test-agent/package.json +18 -0
- package/test-agent/src/index.ts +24 -0
- package/test-agent/src/skills/echo.ts +15 -0
- package/test-agent/tsconfig.json +25 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug Report
|
|
3
|
+
about: Report a bug
|
|
4
|
+
labels: bug
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
**Describe the bug**
|
|
8
|
+
A clear description of the bug.
|
|
9
|
+
|
|
10
|
+
**To Reproduce**
|
|
11
|
+
Steps to reproduce:
|
|
12
|
+
1. ...
|
|
13
|
+
|
|
14
|
+
**Expected behavior**
|
|
15
|
+
What you expected to happen.
|
|
16
|
+
|
|
17
|
+
**Environment**
|
|
18
|
+
- OS:
|
|
19
|
+
- Node.js:
|
|
20
|
+
- Package version:
|
package/CHANGELOG.md
CHANGED
|
@@ -1,57 +1,23 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
- **Sales Assistant Template**: Product Q&A, lead capture, appointment booking.
|
|
25
|
-
- **Knowledge Base Template**: RAG with DeepBrain for answering from company docs.
|
|
26
|
-
- **Code Reviewer Template**: Bug detection, style checking, severity ratings.
|
|
27
|
-
- **Skill Marketplace Stub**: `opc publish` validates OAD and generates manifest. `opc search` placeholder.
|
|
28
|
-
- **OAD Marketplace Fields**: `pricing` (free/freemium/paid/enterprise) and `tags` in marketplace config.
|
|
29
|
-
- **Context Size Guard**: Auto-truncate tool outputs exceeding 5000 characters.
|
|
30
|
-
- **Conversation History Limit**: Configurable limit (default 50 messages).
|
|
31
|
-
- **Graceful Shutdown**: Handles SIGINT/SIGTERM with cleanup.
|
|
32
|
-
- **Structured Logging**: Logger with debug/info/warn/error levels.
|
|
33
|
-
- **Interactive CLI Init**: `opc init` with prompts and template selection.
|
|
34
|
-
- **Dev Mode**: `opc dev` watches files and hot-reloads agent on changes.
|
|
35
|
-
- **Agent Info Command**: `opc info` displays agent details from OAD.
|
|
36
|
-
- **Colorful CLI Output**: Status indicators and colored text throughout CLI.
|
|
37
|
-
- **CONTRIBUTING.md**: Contribution guidelines.
|
|
38
|
-
- **CHANGELOG.md**: This file.
|
|
39
|
-
|
|
40
|
-
### Changed
|
|
41
|
-
- OAD `memory.longTerm` now accepts boolean or object with provider config.
|
|
42
|
-
- OAD `channels.type` now includes `telegram`.
|
|
43
|
-
- CLI version bumped to 0.2.0.
|
|
44
|
-
|
|
45
|
-
## [0.1.0] - 2026-04-14
|
|
46
|
-
|
|
47
|
-
### Added
|
|
48
|
-
- Initial release
|
|
49
|
-
- BaseAgent with lifecycle management
|
|
50
|
-
- AgentRuntime for config-driven setup
|
|
51
|
-
- OAD Schema v1 with Zod validation
|
|
52
|
-
- Web channel (Express)
|
|
53
|
-
- InMemoryStore
|
|
54
|
-
- Skill system (BaseSkill, SkillRegistry)
|
|
55
|
-
- DTV framework (Trust, Value, Data)
|
|
56
|
-
- Customer Service template
|
|
57
|
-
- CLI: init, create, build, test, run, publish
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.4.0 (2026-04-18)
|
|
4
|
+
- feat: wire Analytics into AgentRuntime (message timing, skill usage, error tracking)
|
|
5
|
+
- feat: expose analytics snapshot on /health and /api/dashboard endpoints
|
|
6
|
+
- feat: enhanced /health endpoint with agent name, version, uptime, memory type, skills, channels
|
|
7
|
+
- feat: Slack channel — real Events API webhook server + chat.postMessage via fetch
|
|
8
|
+
- feat: WebChannel metadata setters (version, memory type, skills, channels, analytics provider)
|
|
9
|
+
- feat: AgentRuntime.getAnalytics() and getConfig() accessors
|
|
10
|
+
|
|
11
|
+
## 1.3.1 (2026-04-17)
|
|
12
|
+
- fix: remove residual DTV/marketplace references
|
|
13
|
+
- fix: duplicate WatchPattern export
|
|
14
|
+
|
|
15
|
+
## 1.3.0 (2026-04-17)
|
|
16
|
+
- feat: Traces collection (OpenTelemetry-style)
|
|
17
|
+
- feat: DeepBrain exporter
|
|
18
|
+
- feat: brain/logs/score CLI commands
|
|
19
|
+
|
|
20
|
+
## 1.2.0
|
|
21
|
+
- Initial public release
|
|
22
|
+
- 11 channels, plugins, analytics
|
|
23
|
+
- Declarative OAD configuration
|
package/CONTRIBUTING.md
CHANGED
|
@@ -1,75 +1,36 @@
|
|
|
1
|
-
# Contributing
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
## Getting Started
|
|
6
|
-
|
|
7
|
-
1. Fork the
|
|
8
|
-
2. Clone your fork
|
|
9
|
-
3. Install dependencies: `npm install`
|
|
10
|
-
4. Create a branch: `git checkout -b
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
├── skills/ # BaseSkill, SkillRegistry
|
|
38
|
-
├── templates/ # Agent templates
|
|
39
|
-
├── dtv/ # Data, Trust, Value framework
|
|
40
|
-
├── cli.ts # CLI entry point
|
|
41
|
-
└── index.ts # Public API exports
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
## Guidelines
|
|
45
|
-
|
|
46
|
-
- **TypeScript**: All code must be TypeScript with strict mode
|
|
47
|
-
- **Tests**: Add tests for new features in `tests/`
|
|
48
|
-
- **Commits**: Use conventional commits (`feat:`, `fix:`, `docs:`, etc.)
|
|
49
|
-
- **OAD Compatibility**: Changes to OAD schema must be backward-compatible
|
|
50
|
-
- **No Breaking Changes** without major version bump
|
|
51
|
-
|
|
52
|
-
## Adding a Template
|
|
53
|
-
|
|
54
|
-
1. Create `src/templates/my-template.ts` with config factory function
|
|
55
|
-
2. Create `templates/my-template/oad.yaml` and `README.md`
|
|
56
|
-
3. Register in `src/cli.ts` TEMPLATES map
|
|
57
|
-
4. Add tests
|
|
58
|
-
|
|
59
|
-
## Adding a Channel
|
|
60
|
-
|
|
61
|
-
1. Create `src/channels/my-channel.ts` extending `BaseChannel`
|
|
62
|
-
2. Add channel type to OAD schema in `src/schema/oad.ts`
|
|
63
|
-
3. Wire up in `src/core/runtime.ts`
|
|
64
|
-
4. Export from `src/index.ts`
|
|
65
|
-
|
|
66
|
-
## Pull Requests
|
|
67
|
-
|
|
68
|
-
1. Ensure all tests pass: `npm test`
|
|
69
|
-
2. Ensure types check: `npm run lint`
|
|
70
|
-
3. Write a clear PR description
|
|
71
|
-
4. Reference any related issues
|
|
72
|
-
|
|
73
|
-
## License
|
|
74
|
-
|
|
75
|
-
By contributing, you agree that your contributions will be licensed under Apache-2.0.
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in contributing!
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
1. Fork the repo
|
|
8
|
+
2. Clone your fork
|
|
9
|
+
3. Install dependencies: `npm install`
|
|
10
|
+
4. Create a branch: `git checkout -b feat/my-feature`
|
|
11
|
+
5. Make your changes
|
|
12
|
+
6. Run tests: `npm test`
|
|
13
|
+
7. Commit: `git commit -m "feat: description"`
|
|
14
|
+
8. Push and open a PR
|
|
15
|
+
|
|
16
|
+
## Commit Convention
|
|
17
|
+
|
|
18
|
+
- `feat:` New feature
|
|
19
|
+
- `fix:` Bug fix
|
|
20
|
+
- `docs:` Documentation
|
|
21
|
+
- `test:` Tests
|
|
22
|
+
- `refactor:` Refactoring
|
|
23
|
+
- `chore:` Build/tooling
|
|
24
|
+
|
|
25
|
+
## Code Style
|
|
26
|
+
|
|
27
|
+
- TypeScript
|
|
28
|
+
- Run `npm run lint` before committing (if available)
|
|
29
|
+
|
|
30
|
+
## Questions?
|
|
31
|
+
|
|
32
|
+
Open a Discussion or Issue.
|
|
33
|
+
|
|
34
|
+
## License
|
|
35
|
+
|
|
36
|
+
By contributing, you agree that your contributions will be licensed under Apache-2.0.
|
package/dist/channels/slack.js
CHANGED
|
@@ -1,4 +1,37 @@
|
|
|
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
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.SlackChannel = void 0;
|
|
4
37
|
const index_1 = require("./index");
|
|
@@ -37,9 +70,51 @@ class SlackChannel extends index_1.BaseChannel {
|
|
|
37
70
|
}
|
|
38
71
|
/** Start Events API HTTP server */
|
|
39
72
|
async startEventsAPI() {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
73
|
+
const http = await Promise.resolve().then(() => __importStar(require('http')));
|
|
74
|
+
const port = this.config.port ?? 3001;
|
|
75
|
+
const server = http.createServer(async (req, res) => {
|
|
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
|
+
});
|
|
43
118
|
}
|
|
44
119
|
/** Handle incoming Slack message */
|
|
45
120
|
async handleMessage(event) {
|
|
@@ -94,13 +169,21 @@ class SlackChannel extends index_1.BaseChannel {
|
|
|
94
169
|
}
|
|
95
170
|
/** Send a message to a Slack channel */
|
|
96
171
|
async sendMessage(channel, text, threadTs) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
172
|
+
const body = { channel, text };
|
|
173
|
+
if (threadTs)
|
|
174
|
+
body.thread_ts = threadTs;
|
|
175
|
+
const res = await fetch('https://slack.com/api/chat.postMessage', {
|
|
176
|
+
method: 'POST',
|
|
177
|
+
headers: {
|
|
178
|
+
'Authorization': `Bearer ${this.config.botToken}`,
|
|
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
|
+
}
|
|
104
187
|
}
|
|
105
188
|
}
|
|
106
189
|
exports.SlackChannel = SlackChannel;
|
package/dist/channels/web.d.ts
CHANGED
|
@@ -9,6 +9,11 @@ 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;
|
|
12
17
|
private currentProvider;
|
|
13
18
|
private stats;
|
|
14
19
|
private eventHandlers;
|
|
@@ -23,6 +28,11 @@ export declare class WebChannel extends BaseChannel {
|
|
|
23
28
|
trackSession(): void;
|
|
24
29
|
constructor(port?: number, authConfig?: AuthConfig);
|
|
25
30
|
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;
|
|
26
36
|
onStreamMessage(handler: (msg: Message, res: Response) => Promise<void>): void;
|
|
27
37
|
private setupRoutes;
|
|
28
38
|
start(): Promise<void>;
|
package/dist/channels/web.js
CHANGED
|
@@ -286,6 +286,11 @@ 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;
|
|
289
294
|
currentProvider = 'openai';
|
|
290
295
|
stats = { sessions: 0, messages: 0, totalResponseMs: 0, tokenUsage: 0, knowledgeFiles: 0, startedAt: Date.now(), errors: 0 };
|
|
291
296
|
eventHandlers = new Map();
|
|
@@ -326,6 +331,21 @@ class WebChannel extends index_1.BaseChannel {
|
|
|
326
331
|
setAgentName(name) {
|
|
327
332
|
this.agentName = name;
|
|
328
333
|
}
|
|
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
|
+
}
|
|
329
349
|
onStreamMessage(handler) {
|
|
330
350
|
this.streamHandler = handler;
|
|
331
351
|
}
|
|
@@ -334,7 +354,17 @@ class WebChannel extends index_1.BaseChannel {
|
|
|
334
354
|
res.type('html').send(CHAT_HTML);
|
|
335
355
|
});
|
|
336
356
|
this.app.get('/health', (_req, res) => {
|
|
337
|
-
res.json({
|
|
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
|
+
});
|
|
338
368
|
});
|
|
339
369
|
this.app.get('/api/info', (_req, res) => {
|
|
340
370
|
res.json({ name: this.agentName });
|
|
@@ -408,7 +438,8 @@ class WebChannel extends index_1.BaseChannel {
|
|
|
408
438
|
res.type('html').send(DASHBOARD_HTML);
|
|
409
439
|
});
|
|
410
440
|
this.app.get('/api/dashboard', (_req, res) => {
|
|
411
|
-
|
|
441
|
+
const analytics = this.analyticsProvider ? this.analyticsProvider() : null;
|
|
442
|
+
res.json({ ...this.stats, analytics });
|
|
412
443
|
});
|
|
413
444
|
// --- Knowledge Base Upload ---
|
|
414
445
|
this.app.post('/api/kb/upload', async (req, res) => {
|