opc-agent 1.1.0 → 1.1.2
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 +51 -51
- package/CONTRIBUTING.md +75 -75
- package/README.md +341 -101
- package/README.zh-CN.md +382 -55
- package/dist/channels/web.js +256 -256
- package/dist/cli.js +1 -32
- package/dist/deploy/hermes.js +22 -22
- package/dist/deploy/openclaw.js +31 -31
- package/dist/i18n/index.js +60 -9
- package/dist/templates/code-reviewer.js +5 -5
- package/dist/templates/customer-service.js +2 -2
- package/dist/templates/data-analyst.js +5 -5
- package/dist/templates/knowledge-base.js +2 -2
- package/dist/templates/sales-assistant.js +4 -4
- package/dist/templates/teacher.js +6 -6
- package/docs/.vitepress/config.ts +103 -92
- 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 -0
- package/docs/zh/api/oad-schema.md +87 -3
- package/docs/zh/api/sdk.md +102 -0
- package/docs/zh/guide/concepts.md +104 -28
- package/docs/zh/guide/configuration.md +135 -39
- package/docs/zh/guide/deployment.md +81 -3
- package/docs/zh/guide/getting-started.md +82 -58
- package/docs/zh/guide/templates.md +84 -22
- package/docs/zh/guide/testing.md +88 -18
- 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 -160
- package/src/channels/telegram.ts +90 -90
- package/src/channels/voice.ts +106 -106
- package/src/channels/web.ts +596 -596
- 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 +1 -35
- 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/errors.ts +148 -148
- package/src/core/hitl.ts +138 -138
- package/src/core/knowledge.ts +210 -210
- package/src/core/logger.ts +57 -57
- package/src/core/orchestrator.ts +215 -215
- package/src/core/performance.ts +187 -187
- package/src/core/rate-limiter.ts +128 -128
- package/src/core/room.ts +109 -109
- package/src/core/runtime.ts +152 -152
- 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 -200
- package/src/dtv/data.ts +29 -29
- package/src/dtv/trust.ts +43 -43
- package/src/dtv/value.ts +47 -47
- package/src/i18n/index.ts +216 -165
- package/src/index.ts +110 -110
- package/src/marketplace/index.ts +223 -223
- 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 +183 -183
- package/src/schema/oad.ts +155 -155
- 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 -34
- package/src/templates/customer-service.ts +80 -80
- package/src/templates/data-analyst.ts +70 -70
- package/src/templates/executive-assistant.ts +71 -71
- package/src/templates/financial-advisor.ts +60 -60
- package/src/templates/knowledge-base.ts +31 -31
- package/src/templates/legal-assistant.ts +71 -71
- package/src/templates/sales-assistant.ts +79 -79
- package/src/templates/teacher.ts +79 -79
- 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/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/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/src/deploy/openclaw.ts
CHANGED
|
@@ -1,200 +1,200 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OpenClaw Deployer - Convert OAD → OpenClaw agent workspace
|
|
3
|
-
*/
|
|
4
|
-
import * as fs from 'fs';
|
|
5
|
-
import * as path from 'path';
|
|
6
|
-
import type { OADDocument } from '../schema/oad';
|
|
7
|
-
|
|
8
|
-
export interface DeployOptions {
|
|
9
|
-
oad: OADDocument;
|
|
10
|
-
outputDir: string;
|
|
11
|
-
install?: boolean; // also register in openclaw.json
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface DeployResult {
|
|
15
|
-
outputDir: string;
|
|
16
|
-
files: string[];
|
|
17
|
-
installed: boolean;
|
|
18
|
-
configPath?: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function generateIdentityMd(oad: OADDocument): string {
|
|
22
|
-
const m = oad.metadata;
|
|
23
|
-
return `# IDENTITY.md
|
|
24
|
-
|
|
25
|
-
- **Name:** ${m.name}
|
|
26
|
-
- **Version:** ${m.version}
|
|
27
|
-
- **Description:** ${m.description ?? 'An AI agent'}
|
|
28
|
-
- **Author:** ${m.author ?? 'Unknown'}
|
|
29
|
-
- **License:** ${m.license}
|
|
30
|
-
`;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function generateSoulMd(oad: OADDocument): string {
|
|
34
|
-
const prompt = oad.spec.systemPrompt ?? 'You are a helpful AI assistant.';
|
|
35
|
-
return `# SOUL.md - ${oad.metadata.name}
|
|
36
|
-
|
|
37
|
-
## System Prompt
|
|
38
|
-
|
|
39
|
-
${prompt}
|
|
40
|
-
|
|
41
|
-
## Model Configuration
|
|
42
|
-
|
|
43
|
-
- **Model:** ${oad.spec.model}
|
|
44
|
-
- **Provider:** ${oad.spec.provider?.default ?? 'deepseek'}
|
|
45
|
-
`;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function generateAgentsMd(oad: OADDocument): string {
|
|
49
|
-
const skills = oad.spec.skills;
|
|
50
|
-
const memory = oad.spec.memory;
|
|
51
|
-
const dtv = oad.spec.dtv;
|
|
52
|
-
|
|
53
|
-
let md = `# AGENTS.md - ${oad.metadata.name}\n\n`;
|
|
54
|
-
|
|
55
|
-
// Skills
|
|
56
|
-
md += `## Skills\n\n`;
|
|
57
|
-
if (skills.length === 0) {
|
|
58
|
-
md += `No skills configured.\n\n`;
|
|
59
|
-
} else {
|
|
60
|
-
for (const sk of skills) {
|
|
61
|
-
md += `### ${sk.name}\n`;
|
|
62
|
-
if (sk.description) md += `${sk.description}\n`;
|
|
63
|
-
if (sk.config) md += `\nConfig:\n\`\`\`json\n${JSON.stringify(sk.config, null, 2)}\n\`\`\`\n`;
|
|
64
|
-
md += `\n`;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Memory
|
|
69
|
-
md += `## Memory\n\n`;
|
|
70
|
-
if (memory) {
|
|
71
|
-
md += `- Short-term: ${memory.shortTerm ? 'enabled' : 'disabled'}\n`;
|
|
72
|
-
const lt = memory.longTerm;
|
|
73
|
-
if (typeof lt === 'object' && lt) {
|
|
74
|
-
md += `- Long-term: ${lt.provider} (collection: ${lt.collection ?? 'default'})\n`;
|
|
75
|
-
} else {
|
|
76
|
-
md += `- Long-term: ${lt ? 'enabled' : 'disabled'}\n`;
|
|
77
|
-
}
|
|
78
|
-
} else {
|
|
79
|
-
md += `Default memory settings.\n`;
|
|
80
|
-
}
|
|
81
|
-
md += `\n`;
|
|
82
|
-
|
|
83
|
-
// DTV
|
|
84
|
-
if (dtv) {
|
|
85
|
-
md += `## Trust & Value\n\n`;
|
|
86
|
-
md += `- Trust Level: ${dtv.trust?.level ?? 'sandbox'}\n`;
|
|
87
|
-
if (dtv.value?.metrics?.length) {
|
|
88
|
-
md += `- Metrics: ${dtv.value.metrics.join(', ')}\n`;
|
|
89
|
-
}
|
|
90
|
-
md += `\n`;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return md;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function generateUserMd(oad: OADDocument): string {
|
|
97
|
-
return `# USER.md
|
|
98
|
-
|
|
99
|
-
- **Name:** (your name)
|
|
100
|
-
- **Role:** User
|
|
101
|
-
- **Notes:** Configure this file with your preferences for ${oad.metadata.name}.
|
|
102
|
-
`;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function generateMemoryMd(oad: OADDocument): string {
|
|
106
|
-
return `# MEMORY.md - ${oad.metadata.name}
|
|
107
|
-
|
|
108
|
-
## Persistent Knowledge
|
|
109
|
-
|
|
110
|
-
(Agent will store learned information here)
|
|
111
|
-
|
|
112
|
-
## User Preferences
|
|
113
|
-
|
|
114
|
-
(Discovered user preferences will be noted here)
|
|
115
|
-
`;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function generateOpenClawConfig(oad: OADDocument, agentDir: string): Record<string, any> {
|
|
119
|
-
const channels = oad.spec.channels;
|
|
120
|
-
const channelConfig: Record<string, any> = {};
|
|
121
|
-
|
|
122
|
-
for (const ch of channels) {
|
|
123
|
-
if (ch.type === 'telegram') {
|
|
124
|
-
channelConfig.telegram = {
|
|
125
|
-
enabled: true,
|
|
126
|
-
note: 'Configure bot token in OpenClaw gateway settings',
|
|
127
|
-
};
|
|
128
|
-
} else if (ch.type === 'web' || ch.type === 'websocket') {
|
|
129
|
-
channelConfig.web = { enabled: true, port: ch.port ?? 3000 };
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
return {
|
|
134
|
-
name: oad.metadata.name,
|
|
135
|
-
workspace: agentDir,
|
|
136
|
-
channels: channelConfig,
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
export function deployToOpenClaw(options: DeployOptions): DeployResult {
|
|
141
|
-
const { oad, outputDir, install } = options;
|
|
142
|
-
const files: string[] = [];
|
|
143
|
-
|
|
144
|
-
// Create output directory
|
|
145
|
-
fs.mkdirSync(outputDir, { recursive: true });
|
|
146
|
-
|
|
147
|
-
// Generate all workspace files
|
|
148
|
-
const fileMap: Record<string, string> = {
|
|
149
|
-
'IDENTITY.md': generateIdentityMd(oad),
|
|
150
|
-
'SOUL.md': generateSoulMd(oad),
|
|
151
|
-
'AGENTS.md': generateAgentsMd(oad),
|
|
152
|
-
'USER.md': generateUserMd(oad),
|
|
153
|
-
'MEMORY.md': generateMemoryMd(oad),
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
for (const [name, content] of Object.entries(fileMap)) {
|
|
157
|
-
const filePath = path.join(outputDir, name);
|
|
158
|
-
fs.writeFileSync(filePath, content, 'utf-8');
|
|
159
|
-
files.push(name);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Generate suggested channel config
|
|
163
|
-
const channelSuggestion = generateOpenClawConfig(oad, outputDir);
|
|
164
|
-
const configNote = path.join(outputDir, 'openclaw-config-suggestion.json');
|
|
165
|
-
fs.writeFileSync(configNote, JSON.stringify(channelSuggestion, null, 2), 'utf-8');
|
|
166
|
-
files.push('openclaw-config-suggestion.json');
|
|
167
|
-
|
|
168
|
-
const result: DeployResult = { outputDir, files, installed: false };
|
|
169
|
-
|
|
170
|
-
// Install mode: register in openclaw.json
|
|
171
|
-
if (install) {
|
|
172
|
-
const homeDir = process.env.HOME || process.env.USERPROFILE || '';
|
|
173
|
-
const configPath = path.join(homeDir, '.openclaw', 'openclaw.json');
|
|
174
|
-
|
|
175
|
-
if (fs.existsSync(configPath)) {
|
|
176
|
-
try {
|
|
177
|
-
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
178
|
-
if (!config.agents) config.agents = {};
|
|
179
|
-
|
|
180
|
-
const agentId = oad.metadata.name.toLowerCase().replace(/[^a-z0-9-]/g, '-');
|
|
181
|
-
config.agents[agentId] = {
|
|
182
|
-
workspace: outputDir,
|
|
183
|
-
description: oad.metadata.description ?? '',
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
187
|
-
result.installed = true;
|
|
188
|
-
result.configPath = configPath;
|
|
189
|
-
} catch (err) {
|
|
190
|
-
// Config exists but couldn't be updated - not fatal
|
|
191
|
-
console.error(`Warning: Could not update ${configPath}:`, err);
|
|
192
|
-
}
|
|
193
|
-
} else {
|
|
194
|
-
console.error(`Warning: OpenClaw config not found at ${configPath}`);
|
|
195
|
-
console.error(`Run 'openclaw init' first, then re-run with --install`);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
return result;
|
|
200
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* OpenClaw Deployer - Convert OAD → OpenClaw agent workspace
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from 'fs';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import type { OADDocument } from '../schema/oad';
|
|
7
|
+
|
|
8
|
+
export interface DeployOptions {
|
|
9
|
+
oad: OADDocument;
|
|
10
|
+
outputDir: string;
|
|
11
|
+
install?: boolean; // also register in openclaw.json
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface DeployResult {
|
|
15
|
+
outputDir: string;
|
|
16
|
+
files: string[];
|
|
17
|
+
installed: boolean;
|
|
18
|
+
configPath?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function generateIdentityMd(oad: OADDocument): string {
|
|
22
|
+
const m = oad.metadata;
|
|
23
|
+
return `# IDENTITY.md
|
|
24
|
+
|
|
25
|
+
- **Name:** ${m.name}
|
|
26
|
+
- **Version:** ${m.version}
|
|
27
|
+
- **Description:** ${m.description ?? 'An AI agent'}
|
|
28
|
+
- **Author:** ${m.author ?? 'Unknown'}
|
|
29
|
+
- **License:** ${m.license}
|
|
30
|
+
`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function generateSoulMd(oad: OADDocument): string {
|
|
34
|
+
const prompt = oad.spec.systemPrompt ?? 'You are a helpful AI assistant.';
|
|
35
|
+
return `# SOUL.md - ${oad.metadata.name}
|
|
36
|
+
|
|
37
|
+
## System Prompt
|
|
38
|
+
|
|
39
|
+
${prompt}
|
|
40
|
+
|
|
41
|
+
## Model Configuration
|
|
42
|
+
|
|
43
|
+
- **Model:** ${oad.spec.model}
|
|
44
|
+
- **Provider:** ${oad.spec.provider?.default ?? 'deepseek'}
|
|
45
|
+
`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function generateAgentsMd(oad: OADDocument): string {
|
|
49
|
+
const skills = oad.spec.skills;
|
|
50
|
+
const memory = oad.spec.memory;
|
|
51
|
+
const dtv = oad.spec.dtv;
|
|
52
|
+
|
|
53
|
+
let md = `# AGENTS.md - ${oad.metadata.name}\n\n`;
|
|
54
|
+
|
|
55
|
+
// Skills
|
|
56
|
+
md += `## Skills\n\n`;
|
|
57
|
+
if (skills.length === 0) {
|
|
58
|
+
md += `No skills configured.\n\n`;
|
|
59
|
+
} else {
|
|
60
|
+
for (const sk of skills) {
|
|
61
|
+
md += `### ${sk.name}\n`;
|
|
62
|
+
if (sk.description) md += `${sk.description}\n`;
|
|
63
|
+
if (sk.config) md += `\nConfig:\n\`\`\`json\n${JSON.stringify(sk.config, null, 2)}\n\`\`\`\n`;
|
|
64
|
+
md += `\n`;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Memory
|
|
69
|
+
md += `## Memory\n\n`;
|
|
70
|
+
if (memory) {
|
|
71
|
+
md += `- Short-term: ${memory.shortTerm ? 'enabled' : 'disabled'}\n`;
|
|
72
|
+
const lt = memory.longTerm;
|
|
73
|
+
if (typeof lt === 'object' && lt) {
|
|
74
|
+
md += `- Long-term: ${lt.provider} (collection: ${lt.collection ?? 'default'})\n`;
|
|
75
|
+
} else {
|
|
76
|
+
md += `- Long-term: ${lt ? 'enabled' : 'disabled'}\n`;
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
md += `Default memory settings.\n`;
|
|
80
|
+
}
|
|
81
|
+
md += `\n`;
|
|
82
|
+
|
|
83
|
+
// DTV
|
|
84
|
+
if (dtv) {
|
|
85
|
+
md += `## Trust & Value\n\n`;
|
|
86
|
+
md += `- Trust Level: ${dtv.trust?.level ?? 'sandbox'}\n`;
|
|
87
|
+
if (dtv.value?.metrics?.length) {
|
|
88
|
+
md += `- Metrics: ${dtv.value.metrics.join(', ')}\n`;
|
|
89
|
+
}
|
|
90
|
+
md += `\n`;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return md;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function generateUserMd(oad: OADDocument): string {
|
|
97
|
+
return `# USER.md
|
|
98
|
+
|
|
99
|
+
- **Name:** (your name)
|
|
100
|
+
- **Role:** User
|
|
101
|
+
- **Notes:** Configure this file with your preferences for ${oad.metadata.name}.
|
|
102
|
+
`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function generateMemoryMd(oad: OADDocument): string {
|
|
106
|
+
return `# MEMORY.md - ${oad.metadata.name}
|
|
107
|
+
|
|
108
|
+
## Persistent Knowledge
|
|
109
|
+
|
|
110
|
+
(Agent will store learned information here)
|
|
111
|
+
|
|
112
|
+
## User Preferences
|
|
113
|
+
|
|
114
|
+
(Discovered user preferences will be noted here)
|
|
115
|
+
`;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function generateOpenClawConfig(oad: OADDocument, agentDir: string): Record<string, any> {
|
|
119
|
+
const channels = oad.spec.channels;
|
|
120
|
+
const channelConfig: Record<string, any> = {};
|
|
121
|
+
|
|
122
|
+
for (const ch of channels) {
|
|
123
|
+
if (ch.type === 'telegram') {
|
|
124
|
+
channelConfig.telegram = {
|
|
125
|
+
enabled: true,
|
|
126
|
+
note: 'Configure bot token in OpenClaw gateway settings',
|
|
127
|
+
};
|
|
128
|
+
} else if (ch.type === 'web' || ch.type === 'websocket') {
|
|
129
|
+
channelConfig.web = { enabled: true, port: ch.port ?? 3000 };
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
name: oad.metadata.name,
|
|
135
|
+
workspace: agentDir,
|
|
136
|
+
channels: channelConfig,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function deployToOpenClaw(options: DeployOptions): DeployResult {
|
|
141
|
+
const { oad, outputDir, install } = options;
|
|
142
|
+
const files: string[] = [];
|
|
143
|
+
|
|
144
|
+
// Create output directory
|
|
145
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
146
|
+
|
|
147
|
+
// Generate all workspace files
|
|
148
|
+
const fileMap: Record<string, string> = {
|
|
149
|
+
'IDENTITY.md': generateIdentityMd(oad),
|
|
150
|
+
'SOUL.md': generateSoulMd(oad),
|
|
151
|
+
'AGENTS.md': generateAgentsMd(oad),
|
|
152
|
+
'USER.md': generateUserMd(oad),
|
|
153
|
+
'MEMORY.md': generateMemoryMd(oad),
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
for (const [name, content] of Object.entries(fileMap)) {
|
|
157
|
+
const filePath = path.join(outputDir, name);
|
|
158
|
+
fs.writeFileSync(filePath, content, 'utf-8');
|
|
159
|
+
files.push(name);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Generate suggested channel config
|
|
163
|
+
const channelSuggestion = generateOpenClawConfig(oad, outputDir);
|
|
164
|
+
const configNote = path.join(outputDir, 'openclaw-config-suggestion.json');
|
|
165
|
+
fs.writeFileSync(configNote, JSON.stringify(channelSuggestion, null, 2), 'utf-8');
|
|
166
|
+
files.push('openclaw-config-suggestion.json');
|
|
167
|
+
|
|
168
|
+
const result: DeployResult = { outputDir, files, installed: false };
|
|
169
|
+
|
|
170
|
+
// Install mode: register in openclaw.json
|
|
171
|
+
if (install) {
|
|
172
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || '';
|
|
173
|
+
const configPath = path.join(homeDir, '.openclaw', 'openclaw.json');
|
|
174
|
+
|
|
175
|
+
if (fs.existsSync(configPath)) {
|
|
176
|
+
try {
|
|
177
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
178
|
+
if (!config.agents) config.agents = {};
|
|
179
|
+
|
|
180
|
+
const agentId = oad.metadata.name.toLowerCase().replace(/[^a-z0-9-]/g, '-');
|
|
181
|
+
config.agents[agentId] = {
|
|
182
|
+
workspace: outputDir,
|
|
183
|
+
description: oad.metadata.description ?? '',
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
187
|
+
result.installed = true;
|
|
188
|
+
result.configPath = configPath;
|
|
189
|
+
} catch (err) {
|
|
190
|
+
// Config exists but couldn't be updated - not fatal
|
|
191
|
+
console.error(`Warning: Could not update ${configPath}:`, err);
|
|
192
|
+
}
|
|
193
|
+
} else {
|
|
194
|
+
console.error(`Warning: OpenClaw config not found at ${configPath}`);
|
|
195
|
+
console.error(`Run 'openclaw init' first, then re-run with --install`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return result;
|
|
200
|
+
}
|
package/src/dtv/data.ts
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
export interface DataSource {
|
|
2
|
-
readonly name: string;
|
|
3
|
-
readonly type: string;
|
|
4
|
-
read(key: string): Promise<unknown>;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* MRGConfig reader — read-only data layer for agents.
|
|
9
|
-
* Agents can read business data but cannot modify source systems.
|
|
10
|
-
*/
|
|
11
|
-
export class MRGConfigReader implements DataSource {
|
|
12
|
-
readonly name = 'mrg-config';
|
|
13
|
-
readonly type = 'config';
|
|
14
|
-
private data: Map<string, unknown>;
|
|
15
|
-
|
|
16
|
-
constructor(initial?: Record<string, unknown>) {
|
|
17
|
-
this.data = new Map(Object.entries(initial ?? {}));
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async read(key: string): Promise<unknown> {
|
|
21
|
-
return this.data.get(key);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
load(data: Record<string, unknown>): void {
|
|
25
|
-
for (const [k, v] of Object.entries(data)) {
|
|
26
|
-
this.data.set(k, v);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
1
|
+
export interface DataSource {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
readonly type: string;
|
|
4
|
+
read(key: string): Promise<unknown>;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* MRGConfig reader — read-only data layer for agents.
|
|
9
|
+
* Agents can read business data but cannot modify source systems.
|
|
10
|
+
*/
|
|
11
|
+
export class MRGConfigReader implements DataSource {
|
|
12
|
+
readonly name = 'mrg-config';
|
|
13
|
+
readonly type = 'config';
|
|
14
|
+
private data: Map<string, unknown>;
|
|
15
|
+
|
|
16
|
+
constructor(initial?: Record<string, unknown>) {
|
|
17
|
+
this.data = new Map(Object.entries(initial ?? {}));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async read(key: string): Promise<unknown> {
|
|
21
|
+
return this.data.get(key);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
load(data: Record<string, unknown>): void {
|
|
25
|
+
for (const [k, v] of Object.entries(data)) {
|
|
26
|
+
this.data.set(k, v);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
package/src/dtv/trust.ts
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
import type { TrustLevelType } from '../schema/oad';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Trust levels: sandbox → verified → certified → listed
|
|
5
|
-
*
|
|
6
|
-
* - sandbox: No network, no file system, limited capabilities
|
|
7
|
-
* - verified: Identity verified, basic capabilities
|
|
8
|
-
* - certified: Passed security audit, full capabilities
|
|
9
|
-
* - listed: Published in OPC marketplace
|
|
10
|
-
*/
|
|
11
|
-
export class TrustManager {
|
|
12
|
-
private level: TrustLevelType;
|
|
13
|
-
|
|
14
|
-
constructor(level: TrustLevelType = 'sandbox') {
|
|
15
|
-
this.level = level;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
getLevel(): TrustLevelType {
|
|
19
|
-
return this.level;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
canAccessNetwork(): boolean {
|
|
23
|
-
return this.level !== 'sandbox';
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
canAccessFileSystem(): boolean {
|
|
27
|
-
return this.level === 'certified' || this.level === 'listed';
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
canPublish(): boolean {
|
|
31
|
-
return this.level === 'listed';
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
upgrade(to: TrustLevelType): void {
|
|
35
|
-
const order: TrustLevelType[] = ['sandbox', 'verified', 'certified', 'listed'];
|
|
36
|
-
const currentIdx = order.indexOf(this.level);
|
|
37
|
-
const targetIdx = order.indexOf(to);
|
|
38
|
-
if (targetIdx <= currentIdx) {
|
|
39
|
-
throw new Error(`Cannot downgrade trust from ${this.level} to ${to}`);
|
|
40
|
-
}
|
|
41
|
-
this.level = to;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
1
|
+
import type { TrustLevelType } from '../schema/oad';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Trust levels: sandbox → verified → certified → listed
|
|
5
|
+
*
|
|
6
|
+
* - sandbox: No network, no file system, limited capabilities
|
|
7
|
+
* - verified: Identity verified, basic capabilities
|
|
8
|
+
* - certified: Passed security audit, full capabilities
|
|
9
|
+
* - listed: Published in OPC marketplace
|
|
10
|
+
*/
|
|
11
|
+
export class TrustManager {
|
|
12
|
+
private level: TrustLevelType;
|
|
13
|
+
|
|
14
|
+
constructor(level: TrustLevelType = 'sandbox') {
|
|
15
|
+
this.level = level;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
getLevel(): TrustLevelType {
|
|
19
|
+
return this.level;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
canAccessNetwork(): boolean {
|
|
23
|
+
return this.level !== 'sandbox';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
canAccessFileSystem(): boolean {
|
|
27
|
+
return this.level === 'certified' || this.level === 'listed';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
canPublish(): boolean {
|
|
31
|
+
return this.level === 'listed';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
upgrade(to: TrustLevelType): void {
|
|
35
|
+
const order: TrustLevelType[] = ['sandbox', 'verified', 'certified', 'listed'];
|
|
36
|
+
const currentIdx = order.indexOf(this.level);
|
|
37
|
+
const targetIdx = order.indexOf(to);
|
|
38
|
+
if (targetIdx <= currentIdx) {
|
|
39
|
+
throw new Error(`Cannot downgrade trust from ${this.level} to ${to}`);
|
|
40
|
+
}
|
|
41
|
+
this.level = to;
|
|
42
|
+
}
|
|
43
|
+
}
|
package/src/dtv/value.ts
CHANGED
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Value tracking — metrics and ROI for agent operations.
|
|
3
|
-
*/
|
|
4
|
-
export interface ValueMetric {
|
|
5
|
-
name: string;
|
|
6
|
-
value: number;
|
|
7
|
-
unit: string;
|
|
8
|
-
timestamp: number;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export class ValueTracker {
|
|
12
|
-
private metrics: Map<string, ValueMetric[]> = new Map();
|
|
13
|
-
private trackedNames: Set<string>;
|
|
14
|
-
|
|
15
|
-
constructor(metricNames: string[] = []) {
|
|
16
|
-
this.trackedNames = new Set(metricNames);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
record(name: string, value: number, unit: string = ''): void {
|
|
20
|
-
if (!this.metrics.has(name)) {
|
|
21
|
-
this.metrics.set(name, []);
|
|
22
|
-
}
|
|
23
|
-
this.metrics.get(name)!.push({ name, value, unit, timestamp: Date.now() });
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
getMetrics(name: string): ValueMetric[] {
|
|
27
|
-
return this.metrics.get(name) ?? [];
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
getAverage(name: string): number {
|
|
31
|
-
const m = this.getMetrics(name);
|
|
32
|
-
if (m.length === 0) return 0;
|
|
33
|
-
return m.reduce((sum, v) => sum + v.value, 0) / m.length;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
getSummary(): Record<string, { count: number; average: number; last: number }> {
|
|
37
|
-
const result: Record<string, { count: number; average: number; last: number }> = {};
|
|
38
|
-
for (const [name, values] of this.metrics) {
|
|
39
|
-
result[name] = {
|
|
40
|
-
count: values.length,
|
|
41
|
-
average: this.getAverage(name),
|
|
42
|
-
last: values[values.length - 1]?.value ?? 0,
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
return result;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Value tracking — metrics and ROI for agent operations.
|
|
3
|
+
*/
|
|
4
|
+
export interface ValueMetric {
|
|
5
|
+
name: string;
|
|
6
|
+
value: number;
|
|
7
|
+
unit: string;
|
|
8
|
+
timestamp: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class ValueTracker {
|
|
12
|
+
private metrics: Map<string, ValueMetric[]> = new Map();
|
|
13
|
+
private trackedNames: Set<string>;
|
|
14
|
+
|
|
15
|
+
constructor(metricNames: string[] = []) {
|
|
16
|
+
this.trackedNames = new Set(metricNames);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
record(name: string, value: number, unit: string = ''): void {
|
|
20
|
+
if (!this.metrics.has(name)) {
|
|
21
|
+
this.metrics.set(name, []);
|
|
22
|
+
}
|
|
23
|
+
this.metrics.get(name)!.push({ name, value, unit, timestamp: Date.now() });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
getMetrics(name: string): ValueMetric[] {
|
|
27
|
+
return this.metrics.get(name) ?? [];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
getAverage(name: string): number {
|
|
31
|
+
const m = this.getMetrics(name);
|
|
32
|
+
if (m.length === 0) return 0;
|
|
33
|
+
return m.reduce((sum, v) => sum + v.value, 0) / m.length;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
getSummary(): Record<string, { count: number; average: number; last: number }> {
|
|
37
|
+
const result: Record<string, { count: number; average: number; last: number }> = {};
|
|
38
|
+
for (const [name, values] of this.metrics) {
|
|
39
|
+
result[name] = {
|
|
40
|
+
count: values.length,
|
|
41
|
+
average: this.getAverage(name),
|
|
42
|
+
last: values[values.length - 1]?.value ?? 0,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
}
|