opc-agent 0.3.0 → 0.5.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 (53) hide show
  1. package/README.md +20 -0
  2. package/dist/channels/voice.d.ts +43 -0
  3. package/dist/channels/voice.js +67 -0
  4. package/dist/channels/webhook.d.ts +40 -0
  5. package/dist/channels/webhook.js +193 -0
  6. package/dist/cli.js +143 -13
  7. package/dist/core/a2a.d.ts +46 -0
  8. package/dist/core/a2a.js +99 -0
  9. package/dist/core/hitl.d.ts +41 -0
  10. package/dist/core/hitl.js +100 -0
  11. package/dist/core/performance.d.ts +50 -0
  12. package/dist/core/performance.js +148 -0
  13. package/dist/core/versioning.d.ts +29 -0
  14. package/dist/core/versioning.js +114 -0
  15. package/dist/core/workflow.d.ts +59 -0
  16. package/dist/core/workflow.js +174 -0
  17. package/dist/deploy/openclaw.d.ts +14 -0
  18. package/dist/deploy/openclaw.js +208 -0
  19. package/dist/index.d.ts +13 -0
  20. package/dist/index.js +18 -1
  21. package/dist/schema/oad.d.ts +352 -15
  22. package/dist/schema/oad.js +41 -2
  23. package/dist/templates/executive-assistant.d.ts +20 -0
  24. package/dist/templates/executive-assistant.js +70 -0
  25. package/dist/templates/financial-advisor.d.ts +15 -0
  26. package/dist/templates/financial-advisor.js +60 -0
  27. package/dist/templates/legal-assistant.d.ts +15 -0
  28. package/dist/templates/legal-assistant.js +70 -0
  29. package/examples/customer-service-demo/README.md +90 -0
  30. package/examples/customer-service-demo/oad.yaml +107 -0
  31. package/package.json +46 -46
  32. package/src/channels/voice.ts +106 -0
  33. package/src/channels/webhook.ts +199 -0
  34. package/src/cli.ts +524 -384
  35. package/src/core/a2a.ts +143 -0
  36. package/src/core/hitl.ts +138 -0
  37. package/src/core/performance.ts +187 -0
  38. package/src/core/versioning.ts +106 -0
  39. package/src/core/workflow.ts +235 -0
  40. package/src/deploy/openclaw.ts +200 -0
  41. package/src/index.ts +15 -0
  42. package/src/schema/oad.ts +45 -1
  43. package/src/templates/executive-assistant.ts +71 -0
  44. package/src/templates/financial-advisor.ts +60 -0
  45. package/src/templates/legal-assistant.ts +71 -0
  46. package/tests/a2a.test.ts +66 -0
  47. package/tests/hitl.test.ts +71 -0
  48. package/tests/performance.test.ts +115 -0
  49. package/tests/templates.test.ts +77 -0
  50. package/tests/versioning.test.ts +75 -0
  51. package/tests/voice.test.ts +61 -0
  52. package/tests/webhook.test.ts +29 -0
  53. package/tests/workflow.test.ts +143 -0
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WorkflowEngine = void 0;
4
+ const events_1 = require("events");
5
+ const logger_1 = require("./logger");
6
+ // ── Workflow Engine ─────────────────────────────────────────
7
+ class WorkflowEngine extends events_1.EventEmitter {
8
+ workflows = new Map();
9
+ skills = new Map();
10
+ agents = new Map();
11
+ logger = new logger_1.Logger('workflow');
12
+ registerWorkflow(workflow) {
13
+ this.workflows.set(workflow.name, workflow);
14
+ this.logger.info('Workflow registered', { name: workflow.name, steps: workflow.steps.length });
15
+ }
16
+ unregisterWorkflow(name) {
17
+ this.workflows.delete(name);
18
+ }
19
+ getWorkflow(name) {
20
+ return this.workflows.get(name);
21
+ }
22
+ listWorkflows() {
23
+ return Array.from(this.workflows.values());
24
+ }
25
+ registerSkill(skill) {
26
+ this.skills.set(skill.name, skill);
27
+ }
28
+ registerAgent(agent) {
29
+ this.agents.set(agent.name, agent);
30
+ }
31
+ async run(name, context, input) {
32
+ const workflow = this.workflows.get(name);
33
+ if (!workflow)
34
+ throw new Error(`Workflow "${name}" not found`);
35
+ const startTime = Date.now();
36
+ const results = [];
37
+ let failed = false;
38
+ this.emit('workflow:start', { name, input });
39
+ try {
40
+ await this.executeSteps(workflow.steps, context, input ?? '', results, workflow.onError ?? 'stop');
41
+ }
42
+ catch (err) {
43
+ failed = true;
44
+ this.logger.error('Workflow failed', { name, error: err.message });
45
+ }
46
+ const result = {
47
+ workflow: name,
48
+ status: failed ? 'failed' : results.some(r => r.status === 'error') ? 'partial' : 'completed',
49
+ steps: results,
50
+ totalDurationMs: Date.now() - startTime,
51
+ };
52
+ this.emit('workflow:end', result);
53
+ return result;
54
+ }
55
+ async executeSteps(steps, context, input, results, onError) {
56
+ let currentInput = input;
57
+ for (const step of steps) {
58
+ const stepStart = Date.now();
59
+ try {
60
+ if (step.type === 'parallel' && step.parallel) {
61
+ const parallelResults = await Promise.all(step.parallel.map(s => this.executeSingleStep(s, context, currentInput)));
62
+ const combined = parallelResults.map(r => r.output ?? '').join('\n');
63
+ for (const r of parallelResults)
64
+ results.push(r);
65
+ currentInput = combined;
66
+ }
67
+ else if (step.type === 'condition' && step.branches) {
68
+ const conditionMet = this.evaluateCondition(step.condition ?? '', currentInput, context);
69
+ const branch = conditionMet ? step.branches.if : (step.branches.else ?? []);
70
+ results.push({
71
+ stepId: step.id,
72
+ status: 'success',
73
+ output: `condition=${conditionMet}`,
74
+ durationMs: Date.now() - stepStart,
75
+ });
76
+ currentInput = await this.executeSteps(branch, context, currentInput, results, onError);
77
+ }
78
+ else {
79
+ const result = await this.executeSingleStep(step, context, currentInput);
80
+ results.push(result);
81
+ if (result.status === 'success' && result.output) {
82
+ currentInput = result.output;
83
+ }
84
+ if (result.status === 'error' && onError === 'stop') {
85
+ throw new Error(`Step "${step.id}" failed: ${result.error}`);
86
+ }
87
+ }
88
+ }
89
+ catch (err) {
90
+ if (onError === 'stop')
91
+ throw err;
92
+ // skip: continue
93
+ }
94
+ }
95
+ return currentInput;
96
+ }
97
+ async executeSingleStep(step, context, input) {
98
+ const startTime = Date.now();
99
+ let retries = step.retries ?? 0;
100
+ while (true) {
101
+ try {
102
+ const output = await this.executeStepAction(step, context, input);
103
+ return {
104
+ stepId: step.id,
105
+ status: 'success',
106
+ output,
107
+ durationMs: Date.now() - startTime,
108
+ };
109
+ }
110
+ catch (err) {
111
+ if (retries > 0) {
112
+ retries--;
113
+ continue;
114
+ }
115
+ return {
116
+ stepId: step.id,
117
+ status: 'error',
118
+ error: err.message,
119
+ durationMs: Date.now() - startTime,
120
+ };
121
+ }
122
+ }
123
+ }
124
+ async executeStepAction(step, context, input) {
125
+ const message = {
126
+ id: `wf_${step.id}_${Date.now()}`,
127
+ role: 'user',
128
+ content: input,
129
+ timestamp: Date.now(),
130
+ metadata: { workflowStep: step.id },
131
+ };
132
+ switch (step.type) {
133
+ case 'skill': {
134
+ const skill = this.skills.get(step.name);
135
+ if (!skill)
136
+ throw new Error(`Skill "${step.name}" not found`);
137
+ const result = await skill.execute(context, message);
138
+ return result.response ?? '';
139
+ }
140
+ case 'agent': {
141
+ const agent = this.agents.get(step.name);
142
+ if (!agent)
143
+ throw new Error(`Agent "${step.name}" not found`);
144
+ const response = await agent.handleMessage(message);
145
+ return response.content;
146
+ }
147
+ case 'tool': {
148
+ // Tools are executed via config callback
149
+ const toolFn = step.config?.handler;
150
+ if (toolFn)
151
+ return await toolFn(input);
152
+ return `[tool:${step.name}] executed`;
153
+ }
154
+ default:
155
+ return input;
156
+ }
157
+ }
158
+ evaluateCondition(condition, input, _context) {
159
+ // Simple condition evaluator: supports "contains:keyword", "length>N", "true", "false"
160
+ if (condition === 'true')
161
+ return true;
162
+ if (condition === 'false')
163
+ return false;
164
+ if (condition.startsWith('contains:')) {
165
+ return input.toLowerCase().includes(condition.slice(9).toLowerCase());
166
+ }
167
+ if (condition.startsWith('length>')) {
168
+ return input.length > parseInt(condition.slice(7), 10);
169
+ }
170
+ return !!condition;
171
+ }
172
+ }
173
+ exports.WorkflowEngine = WorkflowEngine;
174
+ //# sourceMappingURL=workflow.js.map
@@ -0,0 +1,14 @@
1
+ import type { OADDocument } from '../schema/oad';
2
+ export interface DeployOptions {
3
+ oad: OADDocument;
4
+ outputDir: string;
5
+ install?: boolean;
6
+ }
7
+ export interface DeployResult {
8
+ outputDir: string;
9
+ files: string[];
10
+ installed: boolean;
11
+ configPath?: string;
12
+ }
13
+ export declare function deployToOpenClaw(options: DeployOptions): DeployResult;
14
+ //# sourceMappingURL=openclaw.d.ts.map
@@ -0,0 +1,208 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.deployToOpenClaw = deployToOpenClaw;
37
+ /**
38
+ * OpenClaw Deployer - Convert OAD → OpenClaw agent workspace
39
+ */
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ function generateIdentityMd(oad) {
43
+ const m = oad.metadata;
44
+ return `# IDENTITY.md
45
+
46
+ - **Name:** ${m.name}
47
+ - **Version:** ${m.version}
48
+ - **Description:** ${m.description ?? 'An AI agent'}
49
+ - **Author:** ${m.author ?? 'Unknown'}
50
+ - **License:** ${m.license}
51
+ `;
52
+ }
53
+ function generateSoulMd(oad) {
54
+ const prompt = oad.spec.systemPrompt ?? 'You are a helpful AI assistant.';
55
+ return `# SOUL.md - ${oad.metadata.name}
56
+
57
+ ## System Prompt
58
+
59
+ ${prompt}
60
+
61
+ ## Model Configuration
62
+
63
+ - **Model:** ${oad.spec.model}
64
+ - **Provider:** ${oad.spec.provider?.default ?? 'deepseek'}
65
+ `;
66
+ }
67
+ function generateAgentsMd(oad) {
68
+ const skills = oad.spec.skills;
69
+ const memory = oad.spec.memory;
70
+ const dtv = oad.spec.dtv;
71
+ let md = `# AGENTS.md - ${oad.metadata.name}\n\n`;
72
+ // Skills
73
+ md += `## Skills\n\n`;
74
+ if (skills.length === 0) {
75
+ md += `No skills configured.\n\n`;
76
+ }
77
+ else {
78
+ for (const sk of skills) {
79
+ md += `### ${sk.name}\n`;
80
+ if (sk.description)
81
+ md += `${sk.description}\n`;
82
+ if (sk.config)
83
+ md += `\nConfig:\n\`\`\`json\n${JSON.stringify(sk.config, null, 2)}\n\`\`\`\n`;
84
+ md += `\n`;
85
+ }
86
+ }
87
+ // Memory
88
+ md += `## Memory\n\n`;
89
+ if (memory) {
90
+ md += `- Short-term: ${memory.shortTerm ? 'enabled' : 'disabled'}\n`;
91
+ const lt = memory.longTerm;
92
+ if (typeof lt === 'object' && lt) {
93
+ md += `- Long-term: ${lt.provider} (collection: ${lt.collection ?? 'default'})\n`;
94
+ }
95
+ else {
96
+ md += `- Long-term: ${lt ? 'enabled' : 'disabled'}\n`;
97
+ }
98
+ }
99
+ else {
100
+ md += `Default memory settings.\n`;
101
+ }
102
+ md += `\n`;
103
+ // DTV
104
+ if (dtv) {
105
+ md += `## Trust & Value\n\n`;
106
+ md += `- Trust Level: ${dtv.trust?.level ?? 'sandbox'}\n`;
107
+ if (dtv.value?.metrics?.length) {
108
+ md += `- Metrics: ${dtv.value.metrics.join(', ')}\n`;
109
+ }
110
+ md += `\n`;
111
+ }
112
+ return md;
113
+ }
114
+ function generateUserMd(oad) {
115
+ return `# USER.md
116
+
117
+ - **Name:** (your name)
118
+ - **Role:** User
119
+ - **Notes:** Configure this file with your preferences for ${oad.metadata.name}.
120
+ `;
121
+ }
122
+ function generateMemoryMd(oad) {
123
+ return `# MEMORY.md - ${oad.metadata.name}
124
+
125
+ ## Persistent Knowledge
126
+
127
+ (Agent will store learned information here)
128
+
129
+ ## User Preferences
130
+
131
+ (Discovered user preferences will be noted here)
132
+ `;
133
+ }
134
+ function generateOpenClawConfig(oad, agentDir) {
135
+ const channels = oad.spec.channels;
136
+ const channelConfig = {};
137
+ for (const ch of channels) {
138
+ if (ch.type === 'telegram') {
139
+ channelConfig.telegram = {
140
+ enabled: true,
141
+ note: 'Configure bot token in OpenClaw gateway settings',
142
+ };
143
+ }
144
+ else if (ch.type === 'web' || ch.type === 'websocket') {
145
+ channelConfig.web = { enabled: true, port: ch.port ?? 3000 };
146
+ }
147
+ }
148
+ return {
149
+ name: oad.metadata.name,
150
+ workspace: agentDir,
151
+ channels: channelConfig,
152
+ };
153
+ }
154
+ function deployToOpenClaw(options) {
155
+ const { oad, outputDir, install } = options;
156
+ const files = [];
157
+ // Create output directory
158
+ fs.mkdirSync(outputDir, { recursive: true });
159
+ // Generate all workspace files
160
+ const fileMap = {
161
+ 'IDENTITY.md': generateIdentityMd(oad),
162
+ 'SOUL.md': generateSoulMd(oad),
163
+ 'AGENTS.md': generateAgentsMd(oad),
164
+ 'USER.md': generateUserMd(oad),
165
+ 'MEMORY.md': generateMemoryMd(oad),
166
+ };
167
+ for (const [name, content] of Object.entries(fileMap)) {
168
+ const filePath = path.join(outputDir, name);
169
+ fs.writeFileSync(filePath, content, 'utf-8');
170
+ files.push(name);
171
+ }
172
+ // Generate suggested channel config
173
+ const channelSuggestion = generateOpenClawConfig(oad, outputDir);
174
+ const configNote = path.join(outputDir, 'openclaw-config-suggestion.json');
175
+ fs.writeFileSync(configNote, JSON.stringify(channelSuggestion, null, 2), 'utf-8');
176
+ files.push('openclaw-config-suggestion.json');
177
+ const result = { outputDir, files, installed: false };
178
+ // Install mode: register in openclaw.json
179
+ if (install) {
180
+ const homeDir = process.env.HOME || process.env.USERPROFILE || '';
181
+ const configPath = path.join(homeDir, '.openclaw', 'openclaw.json');
182
+ if (fs.existsSync(configPath)) {
183
+ try {
184
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
185
+ if (!config.agents)
186
+ config.agents = {};
187
+ const agentId = oad.metadata.name.toLowerCase().replace(/[^a-z0-9-]/g, '-');
188
+ config.agents[agentId] = {
189
+ workspace: outputDir,
190
+ description: oad.metadata.description ?? '',
191
+ };
192
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
193
+ result.installed = true;
194
+ result.configPath = configPath;
195
+ }
196
+ catch (err) {
197
+ // Config exists but couldn't be updated - not fatal
198
+ console.error(`Warning: Could not update ${configPath}:`, err);
199
+ }
200
+ }
201
+ else {
202
+ console.error(`Warning: OpenClaw config not found at ${configPath}`);
203
+ console.error(`Run 'openclaw init' first, then re-run with --install`);
204
+ }
205
+ }
206
+ return result;
207
+ }
208
+ //# sourceMappingURL=openclaw.js.map
package/dist/index.d.ts CHANGED
@@ -26,6 +26,19 @@ export type { IPlugin, PluginHooks } from './plugins';
26
26
  export { Sandbox } from './core/sandbox';
27
27
  export type { SandboxConfig, SandboxRestrictions } from './core/sandbox';
28
28
  export { Analytics } from './analytics';
29
+ export { WorkflowEngine } from './core/workflow';
30
+ export type { WorkflowDefinition, WorkflowStep, WorkflowResult, StepResult } from './core/workflow';
31
+ export { AgentRegistry } from './core/a2a';
32
+ export type { A2ARequest, A2AResponse, AgentCapability, AgentRegistration } from './core/a2a';
33
+ export { HITLManager } from './core/hitl';
34
+ export type { ApprovalRequest, ApprovalResponse, HITLConfig } from './core/hitl';
35
+ export { VoiceChannel } from './channels/voice';
36
+ export type { VoiceChannelConfig, STTProvider, TTSProvider } from './channels/voice';
37
+ export { WebhookChannel } from './channels/webhook';
38
+ export type { WebhookConfig, WebhookPayload } from './channels/webhook';
39
+ export { VersionManager } from './core/versioning';
40
+ export type { VersionEntry, Migration } from './core/versioning';
41
+ export { ConnectionPool, RequestBatcher, LazyLoader } from './core/performance';
29
42
  export type { AnalyticsSnapshot } from './analytics';
30
43
  export { t, setLocale, getLocale, detectLocale, addMessages } from './i18n';
31
44
  export type { Locale } from './i18n';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.addMessages = exports.detectLocale = exports.getLocale = exports.setLocale = exports.t = exports.Analytics = exports.Sandbox = exports.PluginManager = exports.createMCPTool = exports.MCPToolRegistry = exports.Room = exports.SUPPORTED_PROVIDERS = exports.createProvider = exports.MRGConfigReader = exports.ValueTracker = exports.TrustManager = exports.DeepBrainMemoryStore = exports.InMemoryStore = exports.SkillRegistry = exports.BaseSkill = exports.WebSocketChannel = exports.TelegramChannel = exports.WebChannel = exports.BaseChannel = exports.OADSchema = exports.validateOAD = exports.loadOAD = exports.Logger = exports.truncateOutput = exports.AgentRuntime = exports.BaseAgent = void 0;
3
+ exports.addMessages = exports.detectLocale = exports.getLocale = exports.setLocale = exports.t = exports.LazyLoader = exports.RequestBatcher = exports.ConnectionPool = exports.VersionManager = exports.WebhookChannel = exports.VoiceChannel = exports.HITLManager = exports.AgentRegistry = exports.WorkflowEngine = exports.Analytics = exports.Sandbox = exports.PluginManager = exports.createMCPTool = exports.MCPToolRegistry = exports.Room = exports.SUPPORTED_PROVIDERS = exports.createProvider = exports.MRGConfigReader = exports.ValueTracker = exports.TrustManager = exports.DeepBrainMemoryStore = exports.InMemoryStore = exports.SkillRegistry = exports.BaseSkill = exports.WebSocketChannel = exports.TelegramChannel = exports.WebChannel = exports.BaseChannel = exports.OADSchema = exports.validateOAD = exports.loadOAD = exports.Logger = exports.truncateOutput = exports.AgentRuntime = exports.BaseAgent = void 0;
4
4
  // OPC Agent — Open Agent Framework
5
5
  var agent_1 = require("./core/agent");
6
6
  Object.defineProperty(exports, "BaseAgent", { enumerable: true, get: function () { return agent_1.BaseAgent; } });
@@ -51,6 +51,23 @@ var sandbox_1 = require("./core/sandbox");
51
51
  Object.defineProperty(exports, "Sandbox", { enumerable: true, get: function () { return sandbox_1.Sandbox; } });
52
52
  var analytics_1 = require("./analytics");
53
53
  Object.defineProperty(exports, "Analytics", { enumerable: true, get: function () { return analytics_1.Analytics; } });
54
+ // v0.4.0 modules
55
+ var workflow_1 = require("./core/workflow");
56
+ Object.defineProperty(exports, "WorkflowEngine", { enumerable: true, get: function () { return workflow_1.WorkflowEngine; } });
57
+ var a2a_1 = require("./core/a2a");
58
+ Object.defineProperty(exports, "AgentRegistry", { enumerable: true, get: function () { return a2a_1.AgentRegistry; } });
59
+ var hitl_1 = require("./core/hitl");
60
+ Object.defineProperty(exports, "HITLManager", { enumerable: true, get: function () { return hitl_1.HITLManager; } });
61
+ var voice_1 = require("./channels/voice");
62
+ Object.defineProperty(exports, "VoiceChannel", { enumerable: true, get: function () { return voice_1.VoiceChannel; } });
63
+ var webhook_1 = require("./channels/webhook");
64
+ Object.defineProperty(exports, "WebhookChannel", { enumerable: true, get: function () { return webhook_1.WebhookChannel; } });
65
+ var versioning_1 = require("./core/versioning");
66
+ Object.defineProperty(exports, "VersionManager", { enumerable: true, get: function () { return versioning_1.VersionManager; } });
67
+ var performance_1 = require("./core/performance");
68
+ Object.defineProperty(exports, "ConnectionPool", { enumerable: true, get: function () { return performance_1.ConnectionPool; } });
69
+ Object.defineProperty(exports, "RequestBatcher", { enumerable: true, get: function () { return performance_1.RequestBatcher; } });
70
+ Object.defineProperty(exports, "LazyLoader", { enumerable: true, get: function () { return performance_1.LazyLoader; } });
54
71
  var i18n_1 = require("./i18n");
55
72
  Object.defineProperty(exports, "t", { enumerable: true, get: function () { return i18n_1.t; } });
56
73
  Object.defineProperty(exports, "setLocale", { enumerable: true, get: function () { return i18n_1.setLocale; } });