opc-agent 3.0.1 → 4.0.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/README.md +404 -74
- package/README.zh-CN.md +82 -0
- package/dist/channels/dingtalk.d.ts +17 -0
- package/dist/channels/dingtalk.js +38 -0
- package/dist/channels/googlechat.d.ts +14 -0
- package/dist/channels/googlechat.js +37 -0
- package/dist/channels/imessage.d.ts +13 -0
- package/dist/channels/imessage.js +28 -0
- package/dist/channels/irc.d.ts +20 -0
- package/dist/channels/irc.js +71 -0
- package/dist/channels/line.d.ts +14 -0
- package/dist/channels/line.js +28 -0
- package/dist/channels/matrix.d.ts +15 -0
- package/dist/channels/matrix.js +28 -0
- package/dist/channels/mattermost.d.ts +18 -0
- package/dist/channels/mattermost.js +49 -0
- package/dist/channels/msteams.d.ts +14 -0
- package/dist/channels/msteams.js +28 -0
- package/dist/channels/nostr.d.ts +14 -0
- package/dist/channels/nostr.js +28 -0
- package/dist/channels/qq.d.ts +15 -0
- package/dist/channels/qq.js +28 -0
- package/dist/channels/signal.d.ts +14 -0
- package/dist/channels/signal.js +28 -0
- package/dist/channels/sms.d.ts +15 -0
- package/dist/channels/sms.js +28 -0
- package/dist/channels/twitch.d.ts +17 -0
- package/dist/channels/twitch.js +59 -0
- package/dist/channels/voice-call.d.ts +27 -0
- package/dist/channels/voice-call.js +82 -0
- package/dist/channels/whatsapp.d.ts +14 -0
- package/dist/channels/whatsapp.js +28 -0
- package/dist/cli/chat.d.ts +2 -0
- package/dist/cli/chat.js +134 -0
- package/dist/cli/setup.d.ts +4 -0
- package/dist/cli/setup.js +303 -0
- package/dist/cli.js +142 -6
- package/dist/core/api-server.d.ts +25 -0
- package/dist/core/api-server.js +286 -0
- package/dist/core/audio.d.ts +50 -0
- package/dist/core/audio.js +68 -0
- package/dist/core/context-discovery.d.ts +16 -0
- package/dist/core/context-discovery.js +107 -0
- package/dist/core/context-refs.d.ts +29 -0
- package/dist/core/context-refs.js +162 -0
- package/dist/core/gateway.d.ts +53 -0
- package/dist/core/gateway.js +80 -0
- package/dist/core/heartbeat.d.ts +19 -0
- package/dist/core/heartbeat.js +50 -0
- package/dist/core/hooks.d.ts +28 -0
- package/dist/core/hooks.js +82 -0
- package/dist/core/ide-bridge.d.ts +53 -0
- package/dist/core/ide-bridge.js +97 -0
- package/dist/core/node-network.d.ts +23 -0
- package/dist/core/node-network.js +77 -0
- package/dist/core/profiles.d.ts +27 -0
- package/dist/core/profiles.js +131 -0
- package/dist/core/sandbox.d.ts +25 -0
- package/dist/core/sandbox.js +84 -1
- package/dist/core/session-manager.d.ts +33 -0
- package/dist/core/session-manager.js +157 -0
- package/dist/core/vision.d.ts +45 -0
- package/dist/core/vision.js +177 -0
- package/dist/hub/brain-seed.d.ts +14 -0
- package/dist/hub/brain-seed.js +77 -0
- package/dist/hub/client.d.ts +25 -0
- package/dist/hub/client.js +44 -0
- package/dist/index.d.ts +66 -1
- package/dist/index.js +95 -3
- package/dist/memory/context-compressor.d.ts +43 -0
- package/dist/memory/context-compressor.js +167 -0
- package/dist/memory/index.d.ts +4 -0
- package/dist/memory/index.js +5 -1
- package/dist/memory/user-profiler.d.ts +50 -0
- package/dist/memory/user-profiler.js +201 -0
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.js +54 -1
- package/dist/scheduler/cron-engine.d.ts +41 -0
- package/dist/scheduler/cron-engine.js +200 -0
- package/dist/scheduler/index.d.ts +3 -0
- package/dist/scheduler/index.js +7 -0
- package/dist/schema/oad.d.ts +12 -12
- package/dist/security/approvals.d.ts +53 -0
- package/dist/security/approvals.js +115 -0
- package/dist/security/elevated.d.ts +41 -0
- package/dist/security/elevated.js +89 -0
- package/dist/security/index.d.ts +6 -0
- package/dist/security/index.js +7 -1
- package/dist/security/secrets.d.ts +34 -0
- package/dist/security/secrets.js +115 -0
- package/dist/skills/builtin/index.d.ts +6 -0
- package/dist/skills/builtin/index.js +402 -0
- package/dist/skills/marketplace.d.ts +30 -0
- package/dist/skills/marketplace.js +142 -0
- package/dist/skills/types.d.ts +34 -0
- package/dist/skills/types.js +16 -0
- package/dist/studio/server.d.ts +25 -0
- package/dist/studio/server.js +780 -0
- package/dist/studio/templates-data.d.ts +21 -0
- package/dist/studio/templates-data.js +148 -0
- package/dist/studio-ui/index.html +2502 -1073
- package/dist/tools/builtin/browser.d.ts +47 -0
- package/dist/tools/builtin/browser.js +284 -0
- package/dist/tools/builtin/home-assistant.d.ts +12 -0
- package/dist/tools/builtin/home-assistant.js +126 -0
- package/dist/tools/builtin/index.d.ts +7 -1
- package/dist/tools/builtin/index.js +23 -2
- package/dist/tools/builtin/rl-tools.d.ts +13 -0
- package/dist/tools/builtin/rl-tools.js +228 -0
- package/dist/tools/builtin/vision.d.ts +6 -0
- package/dist/tools/builtin/vision.js +61 -0
- package/dist/tools/builtin/web-search.d.ts +9 -0
- package/dist/tools/builtin/web-search.js +150 -0
- package/dist/tools/document-processor.d.ts +39 -0
- package/dist/tools/document-processor.js +188 -0
- package/dist/tools/image-generator.d.ts +42 -0
- package/dist/tools/image-generator.js +136 -0
- package/dist/tools/web-scraper.d.ts +20 -0
- package/dist/tools/web-scraper.js +148 -0
- package/dist/tools/web-search.d.ts +51 -0
- package/dist/tools/web-search.js +152 -0
- package/install.ps1 +154 -0
- package/install.sh +164 -0
- package/package.json +63 -52
- package/src/channels/dingtalk.ts +46 -0
- package/src/channels/googlechat.ts +42 -0
- package/src/channels/imessage.ts +32 -0
- package/src/channels/irc.ts +82 -0
- package/src/channels/line.ts +33 -0
- package/src/channels/matrix.ts +34 -0
- package/src/channels/mattermost.ts +57 -0
- package/src/channels/msteams.ts +33 -0
- package/src/channels/nostr.ts +33 -0
- package/src/channels/qq.ts +34 -0
- package/src/channels/signal.ts +33 -0
- package/src/channels/sms.ts +34 -0
- package/src/channels/twitch.ts +65 -0
- package/src/channels/voice-call.ts +100 -0
- package/src/channels/whatsapp.ts +33 -0
- package/src/cli/chat.ts +99 -0
- package/src/cli/setup.ts +314 -0
- package/src/cli.ts +148 -6
- package/src/core/api-server.ts +277 -0
- package/src/core/audio.ts +98 -0
- package/src/core/context-discovery.ts +85 -0
- package/src/core/context-refs.ts +140 -0
- package/src/core/gateway.ts +106 -0
- package/src/core/heartbeat.ts +51 -0
- package/src/core/hooks.ts +105 -0
- package/src/core/ide-bridge.ts +133 -0
- package/src/core/node-network.ts +86 -0
- package/src/core/profiles.ts +122 -0
- package/src/core/sandbox.ts +100 -0
- package/src/core/session-manager.ts +137 -0
- package/src/core/vision.ts +180 -0
- package/src/hub/brain-seed.ts +54 -0
- package/src/hub/client.ts +60 -0
- package/src/index.ts +86 -1
- package/src/memory/context-compressor.ts +189 -0
- package/src/memory/index.ts +4 -0
- package/src/memory/user-profiler.ts +215 -0
- package/src/providers/index.ts +64 -1
- package/src/scheduler/cron-engine.ts +191 -0
- package/src/scheduler/index.ts +2 -0
- package/src/security/approvals.ts +143 -0
- package/src/security/elevated.ts +105 -0
- package/src/security/index.ts +6 -0
- package/src/security/secrets.ts +129 -0
- package/src/skills/builtin/index.ts +408 -0
- package/src/skills/marketplace.ts +113 -0
- package/src/skills/types.ts +42 -0
- package/src/studio/server.ts +1591 -791
- package/src/studio/templates-data.ts +178 -0
- package/src/studio-ui/index.html +2502 -1073
- package/src/tools/builtin/browser.ts +299 -0
- package/src/tools/builtin/home-assistant.ts +116 -0
- package/src/tools/builtin/index.ts +37 -28
- package/src/tools/builtin/rl-tools.ts +243 -0
- package/src/tools/builtin/vision.ts +64 -0
- package/src/tools/builtin/web-search.ts +126 -0
- package/src/tools/document-processor.ts +213 -0
- package/src/tools/image-generator.ts +150 -0
- package/src/tools/web-scraper.ts +179 -0
- package/src/tools/web-search.ts +180 -0
- package/tests/api-server.test.ts +148 -0
- package/tests/approvals.test.ts +89 -0
- package/tests/audio.test.ts +40 -0
- package/tests/browser.test.ts +179 -0
- package/tests/builtin-tools.test.ts +83 -83
- package/tests/channels-extra.test.ts +45 -0
- package/tests/context-compressor.test.ts +172 -0
- package/tests/context-refs.test.ts +121 -0
- package/tests/cron-engine.test.ts +101 -0
- package/tests/document-processor.test.ts +69 -0
- package/tests/e2e-nocode.test.ts +442 -0
- package/tests/elevated.test.ts +69 -0
- package/tests/gateway.test.ts +63 -71
- package/tests/home-assistant.test.ts +40 -0
- package/tests/hooks.test.ts +79 -0
- package/tests/ide-bridge.test.ts +38 -0
- package/tests/image-generator.test.ts +84 -0
- package/tests/node-network.test.ts +74 -0
- package/tests/profiles.test.ts +61 -0
- package/tests/rl-tools.test.ts +93 -0
- package/tests/sandbox-manager.test.ts +46 -0
- package/tests/secrets.test.ts +107 -0
- package/tests/settings-api.test.ts +148 -0
- package/tests/setup.test.ts +73 -0
- package/tests/studio.test.ts +402 -229
- package/tests/tools/builtin-extended.test.ts +138 -138
- package/tests/user-profiler.test.ts +169 -0
- package/tests/v090-features.test.ts +254 -0
- package/tests/vision.test.ts +61 -0
- package/tests/voice-call.test.ts +47 -0
- package/tests/voice-interaction.test.ts +38 -0
- package/tests/web-search.test.ts +155 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rlTools = exports.rlResetEpisode = exports.rlGetStatistics = exports.rlUpdatePolicy = exports.rlExplorationSuggest = exports.rlRewardSignal = exports.rlGenerateTrainingData = exports.rlCompareStrategies = exports.rlGetBestStrategy = exports.rlEvaluateOutcome = exports.rlRecordTrajectory = void 0;
|
|
4
|
+
const trajectories = [];
|
|
5
|
+
const policies = new Map();
|
|
6
|
+
let currentEpisode = null;
|
|
7
|
+
function getOrCreateEpisode(taskType) {
|
|
8
|
+
if (!currentEpisode || currentEpisode.taskType !== taskType) {
|
|
9
|
+
currentEpisode = {
|
|
10
|
+
id: `ep_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
|
|
11
|
+
taskType,
|
|
12
|
+
actions: [],
|
|
13
|
+
totalReward: 0,
|
|
14
|
+
};
|
|
15
|
+
trajectories.push(currentEpisode);
|
|
16
|
+
}
|
|
17
|
+
return currentEpisode;
|
|
18
|
+
}
|
|
19
|
+
exports.rlRecordTrajectory = {
|
|
20
|
+
name: 'rl_record_trajectory',
|
|
21
|
+
description: 'Record action sequences and outcomes for RL training',
|
|
22
|
+
inputSchema: {
|
|
23
|
+
type: 'object',
|
|
24
|
+
properties: {
|
|
25
|
+
taskType: { type: 'string' },
|
|
26
|
+
action: { type: 'string' },
|
|
27
|
+
outcome: { type: 'string', enum: ['success', 'partial', 'failure'] },
|
|
28
|
+
},
|
|
29
|
+
required: ['taskType', 'action'],
|
|
30
|
+
},
|
|
31
|
+
async execute(input) {
|
|
32
|
+
const ep = getOrCreateEpisode(input.taskType);
|
|
33
|
+
ep.actions.push({ action: input.action, timestamp: Date.now() });
|
|
34
|
+
if (input.outcome)
|
|
35
|
+
ep.outcome = input.outcome;
|
|
36
|
+
return { content: JSON.stringify({ episodeId: ep.id, actionsRecorded: ep.actions.length }) };
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
exports.rlEvaluateOutcome = {
|
|
40
|
+
name: 'rl_evaluate_outcome',
|
|
41
|
+
description: "Score an action's outcome (success/partial/failure)",
|
|
42
|
+
inputSchema: {
|
|
43
|
+
type: 'object',
|
|
44
|
+
properties: {
|
|
45
|
+
episodeId: { type: 'string' },
|
|
46
|
+
outcome: { type: 'string', enum: ['success', 'partial', 'failure'] },
|
|
47
|
+
},
|
|
48
|
+
required: ['outcome'],
|
|
49
|
+
},
|
|
50
|
+
async execute(input) {
|
|
51
|
+
const ep = input.episodeId
|
|
52
|
+
? trajectories.find(t => t.id === input.episodeId)
|
|
53
|
+
: currentEpisode;
|
|
54
|
+
if (!ep)
|
|
55
|
+
return { content: 'No active episode found', isError: true };
|
|
56
|
+
ep.outcome = input.outcome;
|
|
57
|
+
const score = ep.outcome === 'success' ? 1 : ep.outcome === 'partial' ? 0.5 : 0;
|
|
58
|
+
return { content: JSON.stringify({ episodeId: ep.id, outcome: ep.outcome, score }) };
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
exports.rlGetBestStrategy = {
|
|
62
|
+
name: 'rl_get_best_strategy',
|
|
63
|
+
description: 'Retrieve best-performing strategy for a task type',
|
|
64
|
+
inputSchema: {
|
|
65
|
+
type: 'object',
|
|
66
|
+
properties: { taskType: { type: 'string' } },
|
|
67
|
+
required: ['taskType'],
|
|
68
|
+
},
|
|
69
|
+
async execute(input) {
|
|
70
|
+
const taskType = input.taskType;
|
|
71
|
+
const relevant = trajectories.filter(t => t.taskType === taskType && t.outcome === 'success');
|
|
72
|
+
if (relevant.length === 0)
|
|
73
|
+
return { content: JSON.stringify({ strategy: null, message: 'No successful strategies found' }) };
|
|
74
|
+
const best = relevant.reduce((a, b) => a.totalReward >= b.totalReward ? a : b);
|
|
75
|
+
return { content: JSON.stringify({ strategy: best.actions.map(a => a.action), totalReward: best.totalReward }) };
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
exports.rlCompareStrategies = {
|
|
79
|
+
name: 'rl_compare_strategies',
|
|
80
|
+
description: 'Compare multiple strategies by success rate',
|
|
81
|
+
inputSchema: {
|
|
82
|
+
type: 'object',
|
|
83
|
+
properties: { taskType: { type: 'string' } },
|
|
84
|
+
required: ['taskType'],
|
|
85
|
+
},
|
|
86
|
+
async execute(input) {
|
|
87
|
+
const taskType = input.taskType;
|
|
88
|
+
const relevant = trajectories.filter(t => t.taskType === taskType && t.outcome);
|
|
89
|
+
const total = relevant.length;
|
|
90
|
+
const successes = relevant.filter(t => t.outcome === 'success').length;
|
|
91
|
+
const partials = relevant.filter(t => t.outcome === 'partial').length;
|
|
92
|
+
const failures = relevant.filter(t => t.outcome === 'failure').length;
|
|
93
|
+
return {
|
|
94
|
+
content: JSON.stringify({
|
|
95
|
+
taskType, total, successRate: total ? successes / total : 0,
|
|
96
|
+
breakdown: { successes, partials, failures },
|
|
97
|
+
}),
|
|
98
|
+
};
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
exports.rlGenerateTrainingData = {
|
|
102
|
+
name: 'rl_generate_training_data',
|
|
103
|
+
description: 'Export trajectories as fine-tuning JSONL',
|
|
104
|
+
inputSchema: {
|
|
105
|
+
type: 'object',
|
|
106
|
+
properties: { taskType: { type: 'string' }, minReward: { type: 'number' } },
|
|
107
|
+
},
|
|
108
|
+
async execute(input) {
|
|
109
|
+
let data = trajectories;
|
|
110
|
+
if (input.taskType)
|
|
111
|
+
data = data.filter(t => t.taskType === input.taskType);
|
|
112
|
+
if (input.minReward != null)
|
|
113
|
+
data = data.filter(t => t.totalReward >= input.minReward);
|
|
114
|
+
const jsonl = data.map(t => JSON.stringify({
|
|
115
|
+
messages: [
|
|
116
|
+
{ role: 'system', content: `Task: ${t.taskType}` },
|
|
117
|
+
...t.actions.map(a => ({ role: 'assistant', content: a.action })),
|
|
118
|
+
],
|
|
119
|
+
outcome: t.outcome,
|
|
120
|
+
reward: t.totalReward,
|
|
121
|
+
})).join('\n');
|
|
122
|
+
return { content: jsonl || '(no data)' };
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
exports.rlRewardSignal = {
|
|
126
|
+
name: 'rl_reward_signal',
|
|
127
|
+
description: 'Record positive/negative reward for last action',
|
|
128
|
+
inputSchema: {
|
|
129
|
+
type: 'object',
|
|
130
|
+
properties: { reward: { type: 'number' }, reason: { type: 'string' } },
|
|
131
|
+
required: ['reward'],
|
|
132
|
+
},
|
|
133
|
+
async execute(input) {
|
|
134
|
+
if (!currentEpisode || currentEpisode.actions.length === 0) {
|
|
135
|
+
return { content: 'No current episode or actions to reward', isError: true };
|
|
136
|
+
}
|
|
137
|
+
const lastAction = currentEpisode.actions[currentEpisode.actions.length - 1];
|
|
138
|
+
lastAction.reward = input.reward;
|
|
139
|
+
currentEpisode.totalReward += input.reward;
|
|
140
|
+
return { content: JSON.stringify({ action: lastAction.action, reward: input.reward, totalReward: currentEpisode.totalReward }) };
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
exports.rlExplorationSuggest = {
|
|
144
|
+
name: 'rl_exploration_suggest',
|
|
145
|
+
description: 'Suggest alternative approaches (exploration)',
|
|
146
|
+
inputSchema: {
|
|
147
|
+
type: 'object',
|
|
148
|
+
properties: { taskType: { type: 'string' }, currentAction: { type: 'string' } },
|
|
149
|
+
required: ['taskType'],
|
|
150
|
+
},
|
|
151
|
+
async execute(input) {
|
|
152
|
+
const taskType = input.taskType;
|
|
153
|
+
const allActions = new Set();
|
|
154
|
+
trajectories.filter(t => t.taskType === taskType).forEach(t => t.actions.forEach(a => allActions.add(a.action)));
|
|
155
|
+
const suggestions = Array.from(allActions).filter(a => a !== input.currentAction).slice(0, 5);
|
|
156
|
+
if (suggestions.length === 0) {
|
|
157
|
+
return { content: JSON.stringify({ suggestions: [], message: 'No alternative actions found. Try a completely new approach.' }) };
|
|
158
|
+
}
|
|
159
|
+
return { content: JSON.stringify({ suggestions }) };
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
exports.rlUpdatePolicy = {
|
|
163
|
+
name: 'rl_update_policy',
|
|
164
|
+
description: "Update agent's action preferences based on rewards",
|
|
165
|
+
inputSchema: {
|
|
166
|
+
type: 'object',
|
|
167
|
+
properties: { taskType: { type: 'string' }, action: { type: 'string' }, weight: { type: 'number' } },
|
|
168
|
+
required: ['taskType', 'action', 'weight'],
|
|
169
|
+
},
|
|
170
|
+
async execute(input) {
|
|
171
|
+
const taskType = input.taskType;
|
|
172
|
+
let policy = policies.get(taskType);
|
|
173
|
+
if (!policy) {
|
|
174
|
+
policy = { taskType, preferredActions: [], weights: {} };
|
|
175
|
+
policies.set(taskType, policy);
|
|
176
|
+
}
|
|
177
|
+
const action = input.action;
|
|
178
|
+
policy.weights[action] = (policy.weights[action] || 0) + input.weight;
|
|
179
|
+
policy.preferredActions = Object.entries(policy.weights)
|
|
180
|
+
.sort(([, a], [, b]) => b - a)
|
|
181
|
+
.map(([k]) => k);
|
|
182
|
+
return { content: JSON.stringify({ taskType, preferredActions: policy.preferredActions.slice(0, 5), weights: policy.weights }) };
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
exports.rlGetStatistics = {
|
|
186
|
+
name: 'rl_get_statistics',
|
|
187
|
+
description: 'Get success/failure stats by task type',
|
|
188
|
+
inputSchema: {
|
|
189
|
+
type: 'object',
|
|
190
|
+
properties: { taskType: { type: 'string' } },
|
|
191
|
+
},
|
|
192
|
+
async execute(input) {
|
|
193
|
+
let data = trajectories;
|
|
194
|
+
if (input.taskType)
|
|
195
|
+
data = data.filter(t => t.taskType === input.taskType);
|
|
196
|
+
const stats = {};
|
|
197
|
+
for (const t of data) {
|
|
198
|
+
if (!stats[t.taskType])
|
|
199
|
+
stats[t.taskType] = { total: 0, success: 0, partial: 0, failure: 0, avgReward: 0 };
|
|
200
|
+
const s = stats[t.taskType];
|
|
201
|
+
s.total++;
|
|
202
|
+
if (t.outcome === 'success')
|
|
203
|
+
s.success++;
|
|
204
|
+
else if (t.outcome === 'partial')
|
|
205
|
+
s.partial++;
|
|
206
|
+
else if (t.outcome === 'failure')
|
|
207
|
+
s.failure++;
|
|
208
|
+
s.avgReward = (s.avgReward * (s.total - 1) + t.totalReward) / s.total;
|
|
209
|
+
}
|
|
210
|
+
return { content: JSON.stringify(stats) };
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
exports.rlResetEpisode = {
|
|
214
|
+
name: 'rl_reset_episode',
|
|
215
|
+
description: 'Clear current episode state',
|
|
216
|
+
inputSchema: { type: 'object', properties: {} },
|
|
217
|
+
async execute() {
|
|
218
|
+
const had = currentEpisode != null;
|
|
219
|
+
currentEpisode = null;
|
|
220
|
+
return { content: JSON.stringify({ reset: true, hadActiveEpisode: had }) };
|
|
221
|
+
},
|
|
222
|
+
};
|
|
223
|
+
exports.rlTools = [
|
|
224
|
+
exports.rlRecordTrajectory, exports.rlEvaluateOutcome, exports.rlGetBestStrategy, exports.rlCompareStrategies,
|
|
225
|
+
exports.rlGenerateTrainingData, exports.rlRewardSignal, exports.rlExplorationSuggest, exports.rlUpdatePolicy,
|
|
226
|
+
exports.rlGetStatistics, exports.rlResetEpisode,
|
|
227
|
+
];
|
|
228
|
+
//# sourceMappingURL=rl-tools.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { MCPTool } from '../mcp';
|
|
2
|
+
export declare const visionAnalyzeTool: MCPTool;
|
|
3
|
+
export declare const visionExtractTextTool: MCPTool;
|
|
4
|
+
export declare const visionCompareTool: MCPTool;
|
|
5
|
+
export declare const visionTools: MCPTool[];
|
|
6
|
+
//# sourceMappingURL=vision.d.ts.map
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.visionTools = exports.visionCompareTool = exports.visionExtractTextTool = exports.visionAnalyzeTool = void 0;
|
|
4
|
+
const vision_1 = require("../../core/vision");
|
|
5
|
+
const manager = new vision_1.VisionManager();
|
|
6
|
+
exports.visionAnalyzeTool = {
|
|
7
|
+
name: 'vision_analyze',
|
|
8
|
+
description: 'Analyze an image using vision AI. Provide image as URL or base64.',
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
image_url: { type: 'string', description: 'URL of the image to analyze' },
|
|
13
|
+
image_base64: { type: 'string', description: 'Base64-encoded image data' },
|
|
14
|
+
prompt: { type: 'string', description: 'Optional prompt for analysis' },
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
async execute(input) {
|
|
18
|
+
const imgInput = input.image_url
|
|
19
|
+
? { type: 'url', data: input.image_url }
|
|
20
|
+
: { type: 'base64', data: input.image_base64 };
|
|
21
|
+
const result = await manager.analyze(imgInput, input.prompt);
|
|
22
|
+
return { content: JSON.stringify(result) };
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
exports.visionExtractTextTool = {
|
|
26
|
+
name: 'vision_extract_text',
|
|
27
|
+
description: 'Extract text (OCR) from an image.',
|
|
28
|
+
inputSchema: {
|
|
29
|
+
type: 'object',
|
|
30
|
+
properties: {
|
|
31
|
+
image_url: { type: 'string', description: 'URL of the image' },
|
|
32
|
+
image_base64: { type: 'string', description: 'Base64-encoded image data' },
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
async execute(input) {
|
|
36
|
+
const imgInput = input.image_url
|
|
37
|
+
? { type: 'url', data: input.image_url }
|
|
38
|
+
: { type: 'base64', data: input.image_base64 };
|
|
39
|
+
const text = await manager.extractText(imgInput);
|
|
40
|
+
return { content: text };
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
exports.visionCompareTool = {
|
|
44
|
+
name: 'vision_compare',
|
|
45
|
+
description: 'Compare multiple images.',
|
|
46
|
+
inputSchema: {
|
|
47
|
+
type: 'object',
|
|
48
|
+
properties: {
|
|
49
|
+
image_urls: { type: 'array', items: { type: 'string' }, description: 'URLs of images to compare' },
|
|
50
|
+
prompt: { type: 'string', description: 'Optional comparison prompt' },
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
async execute(input) {
|
|
54
|
+
const urls = input.image_urls;
|
|
55
|
+
const images = urls.map(url => ({ type: 'url', data: url }));
|
|
56
|
+
const result = await manager.compareImages(images, input.prompt);
|
|
57
|
+
return { content: result };
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
exports.visionTools = [exports.visionAnalyzeTool, exports.visionExtractTextTool, exports.visionCompareTool];
|
|
61
|
+
//# sourceMappingURL=vision.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Web Search & Read Built-in Tools - v0.10.0
|
|
3
|
+
* Registers web_search and web_read as agent-callable tools.
|
|
4
|
+
*/
|
|
5
|
+
import type { MCPTool } from '../mcp';
|
|
6
|
+
export declare const webSearchTool: MCPTool;
|
|
7
|
+
export declare const webReadTool: MCPTool;
|
|
8
|
+
export declare const webSearchTools: MCPTool[];
|
|
9
|
+
//# sourceMappingURL=web-search.d.ts.map
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Web Search & Read Built-in Tools - v0.10.0
|
|
4
|
+
* Registers web_search and web_read as agent-callable tools.
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.webSearchTools = exports.webReadTool = exports.webSearchTool = void 0;
|
|
41
|
+
const web_search_1 = require("../web-search");
|
|
42
|
+
const web_scraper_1 = require("../web-scraper");
|
|
43
|
+
const fs_1 = require("fs");
|
|
44
|
+
const path_1 = require("path");
|
|
45
|
+
const os = __importStar(require("os"));
|
|
46
|
+
function loadSearchConfig() {
|
|
47
|
+
try {
|
|
48
|
+
const cfgPath = (0, path_1.join)(os.homedir(), '.opc', 'config.json');
|
|
49
|
+
if ((0, fs_1.existsSync)(cfgPath)) {
|
|
50
|
+
const cfg = JSON.parse((0, fs_1.readFileSync)(cfgPath, 'utf-8'));
|
|
51
|
+
if (cfg.webSearch) {
|
|
52
|
+
return { ...web_search_1.DEFAULT_SEARCH_CONFIG, ...cfg.webSearch };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch { /* ignore */ }
|
|
57
|
+
return web_search_1.DEFAULT_SEARCH_CONFIG;
|
|
58
|
+
}
|
|
59
|
+
exports.webSearchTool = {
|
|
60
|
+
name: 'web_search',
|
|
61
|
+
description: 'Search the internet for information. Returns titles, URLs, and snippets from search results. Use when you need current information or facts you\'re unsure about.',
|
|
62
|
+
inputSchema: {
|
|
63
|
+
type: 'object',
|
|
64
|
+
properties: {
|
|
65
|
+
query: {
|
|
66
|
+
type: 'string',
|
|
67
|
+
description: 'Search query string',
|
|
68
|
+
},
|
|
69
|
+
maxResults: {
|
|
70
|
+
type: 'number',
|
|
71
|
+
description: 'Maximum number of results to return (default: 5)',
|
|
72
|
+
},
|
|
73
|
+
engine: {
|
|
74
|
+
type: 'string',
|
|
75
|
+
enum: ['duckduckgo', 'brave', 'searxng', 'google'],
|
|
76
|
+
description: 'Search engine to use (default: configured engine)',
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
required: ['query'],
|
|
80
|
+
},
|
|
81
|
+
async execute(input) {
|
|
82
|
+
const query = String(input.query ?? '');
|
|
83
|
+
if (!query.trim()) {
|
|
84
|
+
return { content: 'Error: empty search query', isError: true };
|
|
85
|
+
}
|
|
86
|
+
const config = loadSearchConfig();
|
|
87
|
+
if (!config.enabled) {
|
|
88
|
+
return { content: 'Web search is disabled in settings.', isError: true };
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
const results = await (0, web_search_1.webSearch)(query, config, {
|
|
92
|
+
maxResults: input.maxResults || 5,
|
|
93
|
+
engine: input.engine,
|
|
94
|
+
});
|
|
95
|
+
if (results.length === 0) {
|
|
96
|
+
return { content: `No results found for: ${query}` };
|
|
97
|
+
}
|
|
98
|
+
const formatted = results.map((r, i) => `${i + 1}. **${r.title}**\n ${r.url}\n ${r.snippet}`).join('\n\n');
|
|
99
|
+
return {
|
|
100
|
+
content: `Search results for "${query}":\n\n${formatted}`,
|
|
101
|
+
metadata: { resultCount: results.length, query },
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
return {
|
|
106
|
+
content: `Search error: ${err instanceof Error ? err.message : String(err)}`,
|
|
107
|
+
isError: true,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
exports.webReadTool = {
|
|
113
|
+
name: 'web_read',
|
|
114
|
+
description: 'Read and extract the main content from a web page URL. Returns clean markdown text. Use to get detailed information from a specific page.',
|
|
115
|
+
inputSchema: {
|
|
116
|
+
type: 'object',
|
|
117
|
+
properties: {
|
|
118
|
+
url: {
|
|
119
|
+
type: 'string',
|
|
120
|
+
description: 'URL of the web page to read',
|
|
121
|
+
},
|
|
122
|
+
maxLength: {
|
|
123
|
+
type: 'number',
|
|
124
|
+
description: 'Maximum content length in characters (default: 5000)',
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
required: ['url'],
|
|
128
|
+
},
|
|
129
|
+
async execute(input) {
|
|
130
|
+
const url = String(input.url ?? '');
|
|
131
|
+
if (!url.trim()) {
|
|
132
|
+
return { content: 'Error: empty URL', isError: true };
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
const result = await (0, web_scraper_1.scrapeUrl)(url, input.maxLength || 5000);
|
|
136
|
+
return {
|
|
137
|
+
content: `# ${result.title}\n\nSource: ${result.url}\nWords: ${result.wordCount}\n\n---\n\n${result.content}`,
|
|
138
|
+
metadata: { title: result.title, url: result.url, wordCount: result.wordCount },
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
return {
|
|
143
|
+
content: `Scrape error: ${err instanceof Error ? err.message : String(err)}`,
|
|
144
|
+
isError: true,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
exports.webSearchTools = [exports.webSearchTool, exports.webReadTool];
|
|
150
|
+
//# sourceMappingURL=web-search.js.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Document Processor - Parse and chunk documents for knowledge learning
|
|
3
|
+
* Supports: PDF, TXT, MD, DOCX, CSV, JSON
|
|
4
|
+
*/
|
|
5
|
+
export interface DocumentChunk {
|
|
6
|
+
title: string;
|
|
7
|
+
content: string;
|
|
8
|
+
metadata: {
|
|
9
|
+
source: string;
|
|
10
|
+
format: string;
|
|
11
|
+
chunkIndex: number;
|
|
12
|
+
totalChunks?: number;
|
|
13
|
+
page?: number;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export interface ProcessedDocument {
|
|
17
|
+
id: string;
|
|
18
|
+
filename: string;
|
|
19
|
+
format: string;
|
|
20
|
+
size: number;
|
|
21
|
+
chunks: DocumentChunk[];
|
|
22
|
+
processedAt: string;
|
|
23
|
+
}
|
|
24
|
+
export declare class DocumentProcessor {
|
|
25
|
+
/**
|
|
26
|
+
* Process a file buffer into chunks
|
|
27
|
+
*/
|
|
28
|
+
process(buffer: Buffer, filename: string): Promise<ProcessedDocument>;
|
|
29
|
+
private parsePDF;
|
|
30
|
+
private parseDOCX;
|
|
31
|
+
private parseCSV;
|
|
32
|
+
private parseCSVLine;
|
|
33
|
+
private parseJSON;
|
|
34
|
+
/**
|
|
35
|
+
* Smart chunking: split by headings/paragraphs, respecting size limits
|
|
36
|
+
*/
|
|
37
|
+
private chunkText;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=document-processor.d.ts.map
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Document Processor - Parse and chunk documents for knowledge learning
|
|
4
|
+
* Supports: PDF, TXT, MD, DOCX, CSV, JSON
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.DocumentProcessor = void 0;
|
|
8
|
+
const MAX_FILE_SIZE = 50 * 1024 * 1024; // 50MB
|
|
9
|
+
const CHUNK_TARGET_CHARS = 2000; // ~500 tokens
|
|
10
|
+
const CHUNK_MAX_CHARS = 4000; // ~1000 tokens
|
|
11
|
+
class DocumentProcessor {
|
|
12
|
+
/**
|
|
13
|
+
* Process a file buffer into chunks
|
|
14
|
+
*/
|
|
15
|
+
async process(buffer, filename) {
|
|
16
|
+
if (buffer.length > MAX_FILE_SIZE) {
|
|
17
|
+
throw new Error(`File too large: ${(buffer.length / 1024 / 1024).toFixed(1)}MB (max 50MB)`);
|
|
18
|
+
}
|
|
19
|
+
const ext = filename.split('.').pop()?.toLowerCase() || '';
|
|
20
|
+
let rawText;
|
|
21
|
+
switch (ext) {
|
|
22
|
+
case 'pdf':
|
|
23
|
+
rawText = await this.parsePDF(buffer);
|
|
24
|
+
break;
|
|
25
|
+
case 'docx':
|
|
26
|
+
rawText = await this.parseDOCX(buffer);
|
|
27
|
+
break;
|
|
28
|
+
case 'csv':
|
|
29
|
+
rawText = this.parseCSV(buffer.toString('utf-8'));
|
|
30
|
+
break;
|
|
31
|
+
case 'json':
|
|
32
|
+
rawText = this.parseJSON(buffer.toString('utf-8'));
|
|
33
|
+
break;
|
|
34
|
+
case 'txt':
|
|
35
|
+
case 'md':
|
|
36
|
+
case 'markdown':
|
|
37
|
+
rawText = buffer.toString('utf-8');
|
|
38
|
+
break;
|
|
39
|
+
default:
|
|
40
|
+
// Try as plain text
|
|
41
|
+
rawText = buffer.toString('utf-8');
|
|
42
|
+
}
|
|
43
|
+
const chunks = this.chunkText(rawText, filename, ext);
|
|
44
|
+
return {
|
|
45
|
+
id: `doc-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
46
|
+
filename,
|
|
47
|
+
format: ext,
|
|
48
|
+
size: buffer.length,
|
|
49
|
+
chunks,
|
|
50
|
+
processedAt: new Date().toISOString(),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
async parsePDF(buffer) {
|
|
54
|
+
try {
|
|
55
|
+
const pdfParse = require('pdf-parse');
|
|
56
|
+
const data = await pdfParse(buffer);
|
|
57
|
+
return data.text || '';
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
throw new Error(`PDF parse failed: ${e.message}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async parseDOCX(buffer) {
|
|
64
|
+
try {
|
|
65
|
+
const mammoth = require('mammoth');
|
|
66
|
+
const result = await mammoth.extractRawText({ buffer });
|
|
67
|
+
return result.value || '';
|
|
68
|
+
}
|
|
69
|
+
catch (e) {
|
|
70
|
+
throw new Error(`DOCX parse failed: ${e.message}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
parseCSV(text) {
|
|
74
|
+
const lines = text.split('\n').filter(l => l.trim());
|
|
75
|
+
if (lines.length === 0)
|
|
76
|
+
return '';
|
|
77
|
+
const headers = lines[0].split(',').map(h => h.trim().replace(/^"|"$/g, ''));
|
|
78
|
+
const rows = lines.slice(1);
|
|
79
|
+
// Convert CSV to readable text
|
|
80
|
+
return rows.map((row, i) => {
|
|
81
|
+
const values = this.parseCSVLine(row);
|
|
82
|
+
const pairs = headers.map((h, j) => `${h}: ${values[j] || ''}`);
|
|
83
|
+
return `Record ${i + 1}:\n${pairs.join('\n')}`;
|
|
84
|
+
}).join('\n\n');
|
|
85
|
+
}
|
|
86
|
+
parseCSVLine(line) {
|
|
87
|
+
const result = [];
|
|
88
|
+
let current = '';
|
|
89
|
+
let inQuotes = false;
|
|
90
|
+
for (const ch of line) {
|
|
91
|
+
if (ch === '"') {
|
|
92
|
+
inQuotes = !inQuotes;
|
|
93
|
+
}
|
|
94
|
+
else if (ch === ',' && !inQuotes) {
|
|
95
|
+
result.push(current.trim());
|
|
96
|
+
current = '';
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
current += ch;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
result.push(current.trim());
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
parseJSON(text) {
|
|
106
|
+
try {
|
|
107
|
+
const data = JSON.parse(text);
|
|
108
|
+
if (Array.isArray(data)) {
|
|
109
|
+
return data.map((item, i) => `Item ${i + 1}:\n${JSON.stringify(item, null, 2)}`).join('\n\n');
|
|
110
|
+
}
|
|
111
|
+
return JSON.stringify(data, null, 2);
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return text;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Smart chunking: split by headings/paragraphs, respecting size limits
|
|
119
|
+
*/
|
|
120
|
+
chunkText(text, filename, format) {
|
|
121
|
+
if (!text.trim())
|
|
122
|
+
return [];
|
|
123
|
+
// Split by markdown headings or double newlines
|
|
124
|
+
const sections = text.split(/\n(?=#{1,3}\s)|(?:\n\s*\n)/).filter(s => s.trim());
|
|
125
|
+
const chunks = [];
|
|
126
|
+
let currentChunk = '';
|
|
127
|
+
let currentTitle = filename;
|
|
128
|
+
for (const section of sections) {
|
|
129
|
+
const headingMatch = section.match(/^(#{1,3})\s+(.+)/);
|
|
130
|
+
if (headingMatch) {
|
|
131
|
+
currentTitle = headingMatch[2].trim();
|
|
132
|
+
}
|
|
133
|
+
if (currentChunk.length + section.length > CHUNK_MAX_CHARS && currentChunk.length > 0) {
|
|
134
|
+
chunks.push({
|
|
135
|
+
title: currentTitle,
|
|
136
|
+
content: currentChunk.trim(),
|
|
137
|
+
metadata: { source: filename, format, chunkIndex: chunks.length },
|
|
138
|
+
});
|
|
139
|
+
currentChunk = '';
|
|
140
|
+
}
|
|
141
|
+
currentChunk += section + '\n\n';
|
|
142
|
+
if (currentChunk.length >= CHUNK_TARGET_CHARS) {
|
|
143
|
+
chunks.push({
|
|
144
|
+
title: currentTitle,
|
|
145
|
+
content: currentChunk.trim(),
|
|
146
|
+
metadata: { source: filename, format, chunkIndex: chunks.length },
|
|
147
|
+
});
|
|
148
|
+
currentChunk = '';
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (currentChunk.trim()) {
|
|
152
|
+
chunks.push({
|
|
153
|
+
title: currentTitle,
|
|
154
|
+
content: currentChunk.trim(),
|
|
155
|
+
metadata: { source: filename, format, chunkIndex: chunks.length },
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
// If we got no chunks from section splitting (e.g. dense text), force-split
|
|
159
|
+
if (chunks.length === 0 && text.trim()) {
|
|
160
|
+
const words = text.split(/\s+/);
|
|
161
|
+
let buf = '';
|
|
162
|
+
for (const w of words) {
|
|
163
|
+
if (buf.length + w.length + 1 > CHUNK_MAX_CHARS && buf) {
|
|
164
|
+
chunks.push({
|
|
165
|
+
title: filename,
|
|
166
|
+
content: buf.trim(),
|
|
167
|
+
metadata: { source: filename, format, chunkIndex: chunks.length },
|
|
168
|
+
});
|
|
169
|
+
buf = '';
|
|
170
|
+
}
|
|
171
|
+
buf += w + ' ';
|
|
172
|
+
}
|
|
173
|
+
if (buf.trim()) {
|
|
174
|
+
chunks.push({
|
|
175
|
+
title: filename,
|
|
176
|
+
content: buf.trim(),
|
|
177
|
+
metadata: { source: filename, format, chunkIndex: chunks.length },
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// Set totalChunks
|
|
182
|
+
for (const c of chunks)
|
|
183
|
+
c.metadata.totalChunks = chunks.length;
|
|
184
|
+
return chunks;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
exports.DocumentProcessor = DocumentProcessor;
|
|
188
|
+
//# sourceMappingURL=document-processor.js.map
|