opc-agent 4.0.44 → 4.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/ISSUE_TEMPLATE/bug_report.md +20 -20
- package/.github/ISSUE_TEMPLATE/feature_request.md +14 -14
- package/.github/PULL_REQUEST_TEMPLATE.md +13 -13
- package/CHANGELOG.md +48 -48
- package/CONTRIBUTING.md +36 -36
- package/README.zh-CN.md +497 -497
- package/dist/channels/wechat.js +6 -6
- package/dist/cli.js +2 -2
- package/dist/core/runtime.js +18 -0
- package/dist/deploy/index.js +56 -56
- package/dist/providers/index.js +39 -13
- package/dist/studio/server.js +211 -20
- package/dist/studio-ui/index.html +279 -24
- package/dist/ui/components.js +105 -105
- package/examples/README.md +22 -22
- package/examples/basic-agent.ts +90 -90
- package/examples/brain-integration.ts +71 -71
- package/examples/multi-channel.ts +74 -74
- package/fix-sidebar.mjs +188 -188
- package/install.ps1 +154 -154
- package/install.sh +164 -164
- package/package.json +1 -1
- package/scripts/install.ps1 +31 -31
- package/scripts/install.sh +40 -40
- package/serve-studio.js +13 -13
- package/serve-test.js +25 -25
- package/src/channels/dingtalk.ts +46 -46
- package/src/channels/email.ts +351 -351
- package/src/channels/feishu.ts +349 -349
- package/src/channels/googlechat.ts +42 -42
- package/src/channels/imessage.ts +31 -31
- package/src/channels/irc.ts +82 -82
- package/src/channels/line.ts +32 -32
- package/src/channels/matrix.ts +33 -33
- package/src/channels/mattermost.ts +57 -57
- package/src/channels/msteams.ts +32 -32
- package/src/channels/nostr.ts +32 -32
- package/src/channels/qq.ts +33 -33
- package/src/channels/signal.ts +32 -32
- package/src/channels/sms.ts +33 -33
- package/src/channels/telegram.ts +616 -616
- package/src/channels/twitch.ts +65 -65
- package/src/channels/voice-call.ts +100 -100
- package/src/channels/websocket.ts +399 -399
- package/src/channels/wechat.ts +329 -329
- package/src/channels/whatsapp.ts +32 -32
- package/src/cli/chat.ts +99 -99
- package/src/cli/setup.ts +314 -314
- package/src/cli.ts +2 -2
- package/src/core/agent.ts +476 -476
- package/src/core/api-server.ts +277 -277
- package/src/core/audio.ts +98 -98
- package/src/core/collaboration.ts +275 -275
- package/src/core/context-discovery.ts +85 -85
- package/src/core/context-refs.ts +140 -140
- package/src/core/gateway.ts +106 -106
- package/src/core/heartbeat.ts +51 -51
- package/src/core/hooks.ts +105 -105
- package/src/core/ide-bridge.ts +133 -133
- package/src/core/node-network.ts +86 -86
- package/src/core/profiles.ts +122 -122
- package/src/core/runtime.ts +18 -0
- package/src/core/scheduler.ts +187 -187
- package/src/core/session-manager.ts +137 -137
- package/src/core/subagent.ts +98 -98
- package/src/core/vision.ts +180 -180
- package/src/core/workflow-graph.ts +365 -365
- package/src/daemon.ts +96 -96
- package/src/deploy/index.ts +255 -255
- package/src/doctor.ts +156 -156
- package/src/eval/index.ts +211 -211
- package/src/eval/suites/basic.json +16 -16
- package/src/eval/suites/memory.json +12 -12
- package/src/eval/suites/safety.json +14 -14
- package/src/hub/brain-seed.ts +54 -54
- package/src/hub/client.ts +60 -60
- package/src/mcp/servers/calculator-mcp.ts +65 -65
- package/src/mcp/servers/crypto-mcp.ts +73 -73
- package/src/mcp/servers/database-mcp.ts +72 -72
- package/src/mcp/servers/datetime-mcp.ts +69 -69
- package/src/mcp/servers/filesystem.ts +66 -66
- package/src/mcp/servers/github-mcp.ts +58 -58
- package/src/mcp/servers/index.ts +63 -63
- package/src/mcp/servers/json-mcp.ts +102 -102
- package/src/mcp/servers/memory-mcp.ts +56 -56
- package/src/mcp/servers/regex-mcp.ts +53 -53
- package/src/mcp/servers/web-mcp.ts +49 -49
- package/src/memory/context-compressor.ts +189 -189
- package/src/memory/seed-loader.ts +212 -212
- package/src/memory/user-profiler.ts +215 -215
- package/src/plugins/content-filter.ts +23 -23
- package/src/plugins/logger.ts +18 -18
- package/src/plugins/rate-limiter.ts +38 -38
- package/src/protocols/a2a/client.ts +132 -132
- package/src/protocols/a2a/index.ts +8 -8
- package/src/protocols/a2a/server.ts +333 -333
- package/src/protocols/a2a/types.ts +88 -88
- package/src/protocols/a2a/utils.ts +50 -50
- package/src/protocols/agui/client.ts +83 -83
- package/src/protocols/agui/index.ts +4 -4
- package/src/protocols/agui/server.ts +218 -218
- package/src/protocols/agui/types.ts +153 -153
- package/src/protocols/index.ts +2 -2
- package/src/protocols/mcp/agent-tools.ts +134 -134
- package/src/protocols/mcp/index.ts +8 -8
- package/src/protocols/mcp/server.ts +262 -262
- package/src/protocols/mcp/types.ts +69 -69
- package/src/providers/index.ts +632 -608
- package/src/publish/index.ts +376 -376
- package/src/scheduler/cron-engine.ts +191 -191
- package/src/scheduler/index.ts +2 -2
- package/src/schema/oad.ts +217 -217
- package/src/security/approval.ts +131 -131
- package/src/security/approvals.ts +143 -143
- package/src/security/elevated.ts +105 -105
- package/src/security/guardrails.ts +248 -248
- package/src/security/index.ts +9 -9
- package/src/security/keys.ts +87 -87
- package/src/security/secrets.ts +129 -129
- package/src/skills/builtin/index.ts +408 -408
- package/src/skills/marketplace.ts +113 -113
- package/src/skills/types.ts +42 -42
- package/src/studio/server.ts +209 -22
- package/src/studio/templates-data.ts +178 -178
- package/src/studio-ui/index.html +279 -24
- package/src/telemetry/index.ts +324 -324
- package/src/tools/builtin/browser.ts +299 -299
- package/src/tools/builtin/datetime.ts +41 -41
- package/src/tools/builtin/file.ts +107 -107
- package/src/tools/builtin/home-assistant.ts +116 -116
- package/src/tools/builtin/rl-tools.ts +243 -243
- package/src/tools/builtin/shell.ts +43 -43
- package/src/tools/builtin/vision.ts +64 -64
- package/src/tools/builtin/web-search.ts +126 -126
- package/src/tools/builtin/web.ts +35 -35
- package/src/tools/document-processor.ts +213 -213
- package/src/tools/image-generator.ts +150 -150
- package/src/tools/integrations/calendar.ts +73 -73
- package/src/tools/integrations/code-exec.ts +39 -39
- package/src/tools/integrations/csv-analyzer.ts +92 -92
- package/src/tools/integrations/database.ts +44 -44
- package/src/tools/integrations/email-send.ts +76 -76
- package/src/tools/integrations/git-tool.ts +42 -42
- package/src/tools/integrations/github-tool.ts +76 -76
- package/src/tools/integrations/image-gen.ts +56 -56
- package/src/tools/integrations/index.ts +92 -92
- package/src/tools/integrations/jira.ts +83 -83
- package/src/tools/integrations/notion.ts +71 -71
- package/src/tools/integrations/npm-tool.ts +48 -48
- package/src/tools/integrations/pdf-reader.ts +58 -58
- package/src/tools/integrations/slack.ts +65 -65
- package/src/tools/integrations/summarizer.ts +49 -49
- package/src/tools/integrations/translator.ts +48 -48
- package/src/tools/integrations/trello.ts +60 -60
- package/src/tools/integrations/vector-search.ts +42 -42
- package/src/tools/integrations/web-scraper.ts +47 -47
- package/src/tools/integrations/web-search.ts +58 -58
- package/src/tools/integrations/webhook.ts +38 -38
- package/src/tools/mcp-client.ts +131 -131
- package/src/tools/web-scraper.ts +179 -179
- package/src/tools/web-search.ts +180 -180
- package/src/ui/components.ts +127 -127
- package/srv-out.txt +1 -1
- package/templates/ecommerce-assistant/README.md +45 -45
- package/templates/ecommerce-assistant/oad.yaml +47 -47
- package/templates/tech-support/README.md +43 -43
- package/templates/tech-support/oad.yaml +45 -45
- package/test-agent/Dockerfile +9 -9
- package/test-agent/README.md +50 -50
- package/test-agent/agent.yaml +23 -23
- package/test-agent/docker-compose.yml +11 -11
- package/test-agent/oad.yaml +31 -31
- package/test-agent/package-lock.json +1492 -1492
- package/test-agent/package.json +17 -17
- package/test-agent/src/index.ts +24 -24
- package/test-agent/src/skills/echo.ts +15 -15
- package/test-agent/tsconfig.json +24 -24
- package/test-full.js +43 -43
- package/test-sidebar.js +22 -22
- package/test-studio3.js +75 -75
- package/test-studio4.js +41 -41
- package/tests/a2a-protocol.test.ts +285 -285
- package/tests/agui-protocol.test.ts +246 -246
- package/tests/api-server.test.ts +148 -148
- package/tests/approvals.test.ts +89 -89
- package/tests/audio.test.ts +40 -40
- package/tests/brain-seed-extended.test.ts +490 -490
- package/tests/brain-seed.test.ts +239 -239
- package/tests/browser.test.ts +179 -179
- package/tests/channels/discord.test.ts +79 -79
- package/tests/channels/email.test.ts +148 -148
- package/tests/channels/feishu.test.ts +123 -123
- package/tests/channels/telegram.test.ts +129 -129
- package/tests/channels/websocket.test.ts +53 -53
- package/tests/channels/wechat.test.ts +170 -170
- package/tests/channels-extra.test.ts +45 -45
- package/tests/chat-cli.test.ts +160 -160
- package/tests/cli.test.ts +46 -46
- package/tests/context-compressor.test.ts +172 -172
- package/tests/context-refs.test.ts +121 -121
- package/tests/cron-engine.test.ts +101 -101
- package/tests/daemon.test.ts +135 -135
- package/tests/deepbrain-wire.test.ts +234 -234
- package/tests/deploy-and-dag.test.ts +196 -196
- package/tests/doctor.test.ts +38 -38
- package/tests/document-processor.test.ts +69 -69
- package/tests/e2e-nocode.test.ts +442 -442
- package/tests/elevated.test.ts +69 -69
- package/tests/eval.test.ts +173 -173
- package/tests/gateway.test.ts +63 -63
- package/tests/guardrails.test.ts +177 -177
- package/tests/home-assistant.test.ts +40 -40
- package/tests/hooks.test.ts +79 -79
- package/tests/ide-bridge.test.ts +38 -38
- package/tests/image-generator.test.ts +84 -84
- package/tests/init-role.test.ts +124 -124
- package/tests/integrations.test.ts +249 -249
- package/tests/mcp-client.test.ts +92 -92
- package/tests/mcp-server.test.ts +178 -178
- package/tests/mcp-servers.test.ts +260 -260
- package/tests/node-network.test.ts +74 -74
- package/tests/plugin-a2a-enhanced.test.ts +230 -230
- package/tests/profiles.test.ts +61 -61
- package/tests/publish.test.ts +231 -231
- package/tests/rl-tools.test.ts +93 -93
- package/tests/sandbox-manager.test.ts +46 -46
- package/tests/scheduler.test.ts +200 -200
- package/tests/secrets.test.ts +107 -107
- package/tests/security-enhanced.test.ts +233 -233
- package/tests/settings-api.test.ts +148 -148
- package/tests/setup.test.ts +73 -73
- package/tests/subagent.test.ts +193 -193
- package/tests/telegram-discord.test.ts +60 -60
- package/tests/telemetry.test.ts +186 -186
- package/tests/user-profiler.test.ts +169 -169
- package/tests/v090-features.test.ts +254 -254
- package/tests/vision.test.ts +61 -61
- package/tests/voice-call.test.ts +47 -47
- package/tests/voice-enhanced.test.ts +169 -169
- package/tests/voice-interaction.test.ts +38 -38
- package/tests/web-search.test.ts +155 -155
- package/tests/workflow-graph.test.ts +279 -279
- package/tutorial/customer-service-agent/README.md +612 -612
- package/tutorial/customer-service-agent/SOUL.md +26 -26
- package/tutorial/customer-service-agent/agent.yaml +63 -63
- package/tutorial/customer-service-agent/package.json +19 -19
- package/tutorial/customer-service-agent/src/index.ts +69 -69
- package/tutorial/customer-service-agent/src/skills/faq.ts +27 -27
- package/tutorial/customer-service-agent/src/skills/ticket.ts +22 -22
- package/tutorial/customer-service-agent/tsconfig.json +14 -14
|
@@ -1,212 +1,212 @@
|
|
|
1
|
-
import * as fs from 'fs';
|
|
2
|
-
import * as path from 'path';
|
|
3
|
-
|
|
4
|
-
export interface BrainSeedConfig {
|
|
5
|
-
seeds: string[];
|
|
6
|
-
autoSeed: boolean;
|
|
7
|
-
seedMarkerFile?: string;
|
|
8
|
-
evolve?: {
|
|
9
|
-
enabled: boolean;
|
|
10
|
-
direction: 'bottom-up' | 'top-down';
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface SeedPage {
|
|
15
|
-
slug: string;
|
|
16
|
-
content: string;
|
|
17
|
-
tier: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface SeedResult {
|
|
21
|
-
imported: number;
|
|
22
|
-
pages: string[];
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface PromotionCandidate {
|
|
26
|
-
slug: string;
|
|
27
|
-
content: string;
|
|
28
|
-
fromTier: string;
|
|
29
|
-
toTier: string;
|
|
30
|
-
confidence: number;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface PromotionResult {
|
|
34
|
-
candidates: PromotionCandidate[];
|
|
35
|
-
promoted: number;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export class BrainSeedLoader {
|
|
39
|
-
private markerFile: string;
|
|
40
|
-
|
|
41
|
-
constructor(private agentDir: string, private config: BrainSeedConfig) {
|
|
42
|
-
this.markerFile = config.seedMarkerFile
|
|
43
|
-
? path.resolve(agentDir, config.seedMarkerFile)
|
|
44
|
-
: path.resolve(agentDir, '.brain-seeded');
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async isSeeded(): Promise<boolean> {
|
|
48
|
-
return fs.existsSync(this.markerFile);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
async seedBrain(brain: any): Promise<SeedResult> {
|
|
52
|
-
const allPages: SeedPage[] = [];
|
|
53
|
-
|
|
54
|
-
for (const seedPath of this.config.seeds) {
|
|
55
|
-
const fullPath = path.resolve(this.agentDir, seedPath);
|
|
56
|
-
if (!fs.existsSync(fullPath)) continue;
|
|
57
|
-
|
|
58
|
-
const tier = this.inferTier(seedPath);
|
|
59
|
-
const pages = this.parseSeedFile(fullPath, tier);
|
|
60
|
-
allPages.push(...pages);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const importedSlugs: string[] = [];
|
|
64
|
-
for (const page of allPages) {
|
|
65
|
-
if (brain && typeof brain.store === 'function') {
|
|
66
|
-
await brain.store('brain-seeds', page.slug, page.content, {
|
|
67
|
-
tier: page.tier,
|
|
68
|
-
source: 'brain-seed',
|
|
69
|
-
});
|
|
70
|
-
} else if (brain && typeof brain.learn === 'function') {
|
|
71
|
-
await brain.learn(page.content, {
|
|
72
|
-
tags: ['brain-seed', page.tier],
|
|
73
|
-
slug: page.slug,
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
importedSlugs.push(page.slug);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return { imported: importedSlugs.length, pages: importedSlugs };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
async markSeeded(): Promise<void> {
|
|
83
|
-
const dir = path.dirname(this.markerFile);
|
|
84
|
-
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
85
|
-
fs.writeFileSync(this.markerFile, JSON.stringify({
|
|
86
|
-
seededAt: new Date().toISOString(),
|
|
87
|
-
seeds: this.config.seeds,
|
|
88
|
-
}, null, 2));
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
parseSeedFile(filePath: string, tier: string): SeedPage[] {
|
|
92
|
-
const content = fs.readFileSync(filePath, 'utf-8');
|
|
93
|
-
const pages: SeedPage[] = [];
|
|
94
|
-
const sections = content.split(/^## /m);
|
|
95
|
-
|
|
96
|
-
for (const section of sections) {
|
|
97
|
-
const trimmed = section.trim();
|
|
98
|
-
if (!trimmed) continue;
|
|
99
|
-
|
|
100
|
-
const newlineIdx = trimmed.indexOf('\n');
|
|
101
|
-
if (newlineIdx === -1 && sections.indexOf(section) === 0 && !content.trimStart().startsWith('## ')) {
|
|
102
|
-
// This is preamble before any ## heading — skip or treat as intro
|
|
103
|
-
continue;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
let title: string;
|
|
107
|
-
let body: string;
|
|
108
|
-
|
|
109
|
-
if (sections.indexOf(section) === 0 && !content.trimStart().startsWith('## ')) {
|
|
110
|
-
// Preamble (before first ##)
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (newlineIdx === -1) {
|
|
115
|
-
title = trimmed;
|
|
116
|
-
body = '';
|
|
117
|
-
} else {
|
|
118
|
-
title = trimmed.slice(0, newlineIdx).trim();
|
|
119
|
-
body = trimmed.slice(newlineIdx + 1).trim();
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const slug = `seed/${tier}/${this.slugify(title)}`;
|
|
123
|
-
pages.push({ slug, content: `## ${title}\n\n${body}`, tier });
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return pages;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
private inferTier(seedPath: string): string {
|
|
130
|
-
const basename = path.basename(seedPath, path.extname(seedPath)).toLowerCase();
|
|
131
|
-
if (basename.includes('industry')) return 'industry';
|
|
132
|
-
if (basename.includes('job')) return 'job';
|
|
133
|
-
if (basename.includes('workstation')) return 'workstation';
|
|
134
|
-
return 'workstation';
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
private slugify(text: string): string {
|
|
138
|
-
return text
|
|
139
|
-
.toLowerCase()
|
|
140
|
-
.replace(/[^a-z0-9\u4e00-\u9fff]+/g, '-')
|
|
141
|
-
.replace(/^-|-$/g, '');
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export class KnowledgeEvolver {
|
|
146
|
-
private tierOrder = ['workstation', 'job', 'industry'];
|
|
147
|
-
|
|
148
|
-
async checkPromotion(brain: any, options: {
|
|
149
|
-
minInteractions?: number;
|
|
150
|
-
confidenceThreshold?: number;
|
|
151
|
-
} = {}): Promise<PromotionResult> {
|
|
152
|
-
const minInteractions = options.minInteractions ?? 50;
|
|
153
|
-
const confidenceThreshold = options.confidenceThreshold ?? 0.8;
|
|
154
|
-
|
|
155
|
-
const result: PromotionResult = { candidates: [], promoted: 0 };
|
|
156
|
-
|
|
157
|
-
// Search for frequently referenced seed knowledge
|
|
158
|
-
if (!brain || typeof brain.search !== 'function') return result;
|
|
159
|
-
|
|
160
|
-
try {
|
|
161
|
-
const seedPages = await brain.search('brain-seeds', 'seed/', 100);
|
|
162
|
-
if (!Array.isArray(seedPages)) return result;
|
|
163
|
-
|
|
164
|
-
for (const page of seedPages) {
|
|
165
|
-
const meta = page.metadata || {};
|
|
166
|
-
const usageCount = meta.usageCount ?? 0;
|
|
167
|
-
const tier = meta.tier || 'workstation';
|
|
168
|
-
|
|
169
|
-
if (usageCount < minInteractions) continue;
|
|
170
|
-
|
|
171
|
-
const confidence = Math.min(usageCount / (minInteractions * 2), 1.0);
|
|
172
|
-
if (confidence < confidenceThreshold) continue;
|
|
173
|
-
|
|
174
|
-
const tierIdx = this.tierOrder.indexOf(tier);
|
|
175
|
-
if (tierIdx <= 0) continue; // already at highest tier or unknown
|
|
176
|
-
|
|
177
|
-
const toTier = this.tierOrder[tierIdx - 1];
|
|
178
|
-
result.candidates.push({
|
|
179
|
-
slug: page.id || page.slug,
|
|
180
|
-
content: page.content,
|
|
181
|
-
fromTier: tier,
|
|
182
|
-
toTier,
|
|
183
|
-
confidence,
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
} catch {
|
|
187
|
-
// Silent fail
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return result;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
async promoteToJob(brain: any, knowledge: string, jobSlug: string): Promise<void> {
|
|
194
|
-
if (brain && typeof brain.store === 'function') {
|
|
195
|
-
await brain.store('brain-seeds', jobSlug, knowledge, {
|
|
196
|
-
tier: 'job',
|
|
197
|
-
source: 'promotion',
|
|
198
|
-
promotedAt: new Date().toISOString(),
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
async promoteToIndustry(brain: any, knowledge: string, industrySlug: string): Promise<void> {
|
|
204
|
-
if (brain && typeof brain.store === 'function') {
|
|
205
|
-
await brain.store('brain-seeds', industrySlug, knowledge, {
|
|
206
|
-
tier: 'industry',
|
|
207
|
-
source: 'promotion',
|
|
208
|
-
promotedAt: new Date().toISOString(),
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
|
|
4
|
+
export interface BrainSeedConfig {
|
|
5
|
+
seeds: string[];
|
|
6
|
+
autoSeed: boolean;
|
|
7
|
+
seedMarkerFile?: string;
|
|
8
|
+
evolve?: {
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
direction: 'bottom-up' | 'top-down';
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface SeedPage {
|
|
15
|
+
slug: string;
|
|
16
|
+
content: string;
|
|
17
|
+
tier: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface SeedResult {
|
|
21
|
+
imported: number;
|
|
22
|
+
pages: string[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface PromotionCandidate {
|
|
26
|
+
slug: string;
|
|
27
|
+
content: string;
|
|
28
|
+
fromTier: string;
|
|
29
|
+
toTier: string;
|
|
30
|
+
confidence: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface PromotionResult {
|
|
34
|
+
candidates: PromotionCandidate[];
|
|
35
|
+
promoted: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export class BrainSeedLoader {
|
|
39
|
+
private markerFile: string;
|
|
40
|
+
|
|
41
|
+
constructor(private agentDir: string, private config: BrainSeedConfig) {
|
|
42
|
+
this.markerFile = config.seedMarkerFile
|
|
43
|
+
? path.resolve(agentDir, config.seedMarkerFile)
|
|
44
|
+
: path.resolve(agentDir, '.brain-seeded');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async isSeeded(): Promise<boolean> {
|
|
48
|
+
return fs.existsSync(this.markerFile);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async seedBrain(brain: any): Promise<SeedResult> {
|
|
52
|
+
const allPages: SeedPage[] = [];
|
|
53
|
+
|
|
54
|
+
for (const seedPath of this.config.seeds) {
|
|
55
|
+
const fullPath = path.resolve(this.agentDir, seedPath);
|
|
56
|
+
if (!fs.existsSync(fullPath)) continue;
|
|
57
|
+
|
|
58
|
+
const tier = this.inferTier(seedPath);
|
|
59
|
+
const pages = this.parseSeedFile(fullPath, tier);
|
|
60
|
+
allPages.push(...pages);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const importedSlugs: string[] = [];
|
|
64
|
+
for (const page of allPages) {
|
|
65
|
+
if (brain && typeof brain.store === 'function') {
|
|
66
|
+
await brain.store('brain-seeds', page.slug, page.content, {
|
|
67
|
+
tier: page.tier,
|
|
68
|
+
source: 'brain-seed',
|
|
69
|
+
});
|
|
70
|
+
} else if (brain && typeof brain.learn === 'function') {
|
|
71
|
+
await brain.learn(page.content, {
|
|
72
|
+
tags: ['brain-seed', page.tier],
|
|
73
|
+
slug: page.slug,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
importedSlugs.push(page.slug);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return { imported: importedSlugs.length, pages: importedSlugs };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async markSeeded(): Promise<void> {
|
|
83
|
+
const dir = path.dirname(this.markerFile);
|
|
84
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
85
|
+
fs.writeFileSync(this.markerFile, JSON.stringify({
|
|
86
|
+
seededAt: new Date().toISOString(),
|
|
87
|
+
seeds: this.config.seeds,
|
|
88
|
+
}, null, 2));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
parseSeedFile(filePath: string, tier: string): SeedPage[] {
|
|
92
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
93
|
+
const pages: SeedPage[] = [];
|
|
94
|
+
const sections = content.split(/^## /m);
|
|
95
|
+
|
|
96
|
+
for (const section of sections) {
|
|
97
|
+
const trimmed = section.trim();
|
|
98
|
+
if (!trimmed) continue;
|
|
99
|
+
|
|
100
|
+
const newlineIdx = trimmed.indexOf('\n');
|
|
101
|
+
if (newlineIdx === -1 && sections.indexOf(section) === 0 && !content.trimStart().startsWith('## ')) {
|
|
102
|
+
// This is preamble before any ## heading — skip or treat as intro
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
let title: string;
|
|
107
|
+
let body: string;
|
|
108
|
+
|
|
109
|
+
if (sections.indexOf(section) === 0 && !content.trimStart().startsWith('## ')) {
|
|
110
|
+
// Preamble (before first ##)
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (newlineIdx === -1) {
|
|
115
|
+
title = trimmed;
|
|
116
|
+
body = '';
|
|
117
|
+
} else {
|
|
118
|
+
title = trimmed.slice(0, newlineIdx).trim();
|
|
119
|
+
body = trimmed.slice(newlineIdx + 1).trim();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const slug = `seed/${tier}/${this.slugify(title)}`;
|
|
123
|
+
pages.push({ slug, content: `## ${title}\n\n${body}`, tier });
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return pages;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private inferTier(seedPath: string): string {
|
|
130
|
+
const basename = path.basename(seedPath, path.extname(seedPath)).toLowerCase();
|
|
131
|
+
if (basename.includes('industry')) return 'industry';
|
|
132
|
+
if (basename.includes('job')) return 'job';
|
|
133
|
+
if (basename.includes('workstation')) return 'workstation';
|
|
134
|
+
return 'workstation';
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private slugify(text: string): string {
|
|
138
|
+
return text
|
|
139
|
+
.toLowerCase()
|
|
140
|
+
.replace(/[^a-z0-9\u4e00-\u9fff]+/g, '-')
|
|
141
|
+
.replace(/^-|-$/g, '');
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export class KnowledgeEvolver {
|
|
146
|
+
private tierOrder = ['workstation', 'job', 'industry'];
|
|
147
|
+
|
|
148
|
+
async checkPromotion(brain: any, options: {
|
|
149
|
+
minInteractions?: number;
|
|
150
|
+
confidenceThreshold?: number;
|
|
151
|
+
} = {}): Promise<PromotionResult> {
|
|
152
|
+
const minInteractions = options.minInteractions ?? 50;
|
|
153
|
+
const confidenceThreshold = options.confidenceThreshold ?? 0.8;
|
|
154
|
+
|
|
155
|
+
const result: PromotionResult = { candidates: [], promoted: 0 };
|
|
156
|
+
|
|
157
|
+
// Search for frequently referenced seed knowledge
|
|
158
|
+
if (!brain || typeof brain.search !== 'function') return result;
|
|
159
|
+
|
|
160
|
+
try {
|
|
161
|
+
const seedPages = await brain.search('brain-seeds', 'seed/', 100);
|
|
162
|
+
if (!Array.isArray(seedPages)) return result;
|
|
163
|
+
|
|
164
|
+
for (const page of seedPages) {
|
|
165
|
+
const meta = page.metadata || {};
|
|
166
|
+
const usageCount = meta.usageCount ?? 0;
|
|
167
|
+
const tier = meta.tier || 'workstation';
|
|
168
|
+
|
|
169
|
+
if (usageCount < minInteractions) continue;
|
|
170
|
+
|
|
171
|
+
const confidence = Math.min(usageCount / (minInteractions * 2), 1.0);
|
|
172
|
+
if (confidence < confidenceThreshold) continue;
|
|
173
|
+
|
|
174
|
+
const tierIdx = this.tierOrder.indexOf(tier);
|
|
175
|
+
if (tierIdx <= 0) continue; // already at highest tier or unknown
|
|
176
|
+
|
|
177
|
+
const toTier = this.tierOrder[tierIdx - 1];
|
|
178
|
+
result.candidates.push({
|
|
179
|
+
slug: page.id || page.slug,
|
|
180
|
+
content: page.content,
|
|
181
|
+
fromTier: tier,
|
|
182
|
+
toTier,
|
|
183
|
+
confidence,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
} catch {
|
|
187
|
+
// Silent fail
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return result;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async promoteToJob(brain: any, knowledge: string, jobSlug: string): Promise<void> {
|
|
194
|
+
if (brain && typeof brain.store === 'function') {
|
|
195
|
+
await brain.store('brain-seeds', jobSlug, knowledge, {
|
|
196
|
+
tier: 'job',
|
|
197
|
+
source: 'promotion',
|
|
198
|
+
promotedAt: new Date().toISOString(),
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async promoteToIndustry(brain: any, knowledge: string, industrySlug: string): Promise<void> {
|
|
204
|
+
if (brain && typeof brain.store === 'function') {
|
|
205
|
+
await brain.store('brain-seeds', industrySlug, knowledge, {
|
|
206
|
+
tier: 'industry',
|
|
207
|
+
source: 'promotion',
|
|
208
|
+
promotedAt: new Date().toISOString(),
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|