@glodon-aiot/bot-client-sdk 3.25.1-alpha.7 → 3.26.0-alpha.5
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 +572 -98
- package/dist/es/AgentSession.mjs +230 -165
- package/dist/es/BotClient.mjs +186 -136
- package/dist/es/Config.mjs +89 -26
- package/dist/es/Session.mjs +12 -0
- package/dist/es/api/index.mjs +42 -33
- package/dist/es/builtinTools/browserRuntime/BrowserCommandRunner.mjs +201 -0
- package/dist/es/builtinTools/browserRuntime/PythonRunner.mjs +356 -0
- package/dist/es/builtinTools/browserRuntime/WorkspaceBashFs.mjs +350 -0
- package/dist/es/builtinTools/browserRuntime/assets.mjs +9 -0
- package/dist/es/builtinTools/browserRuntime/loadBash.mjs +17 -0
- package/dist/es/builtinTools/browserRuntime/pyodideRunner.py.mjs +96 -0
- package/dist/es/builtinTools/browserRuntime/pyodideWorker.mjs +242 -0
- package/dist/es/builtinTools/command.mjs +56 -0
- package/dist/es/builtinTools/constants.mjs +10 -0
- package/dist/es/builtinTools/createBuiltinToolsPlugin.mjs +236 -0
- package/dist/es/builtinTools/overview.mjs +77 -0
- package/dist/es/builtinTools/paths.mjs +63 -0
- package/dist/es/builtinTools/schemas.mjs +216 -0
- package/dist/es/builtinTools/tools.mjs +471 -0
- package/dist/es/index.mjs +69 -9
- package/dist/es/localFiles/adapters/FileSystemAccessAdapter.mjs +264 -0
- package/dist/es/localFiles/adapters/HostBridgeAdapter.mjs +233 -0
- package/dist/es/localFiles/adapters/MemoryWorkspaceAdapter.mjs +197 -0
- package/dist/es/localFiles/adapters/WorkspaceFileAdapter.mjs +54 -0
- package/dist/es/localFiles/adapters/fsaTypes.mjs +9 -0
- package/dist/es/localFiles/constants.mjs +47 -0
- package/dist/es/localFiles/createLocalFilesPlugin.mjs +255 -0
- package/dist/es/localFiles/errors.mjs +57 -0
- package/dist/es/localFiles/host/connectHostBridge.mjs +54 -0
- package/dist/es/localFiles/host/protocol.mjs +27 -0
- package/dist/es/localFiles/limits.mjs +22 -0
- package/dist/es/localFiles/schemas.mjs +312 -0
- package/dist/es/localFiles/security/downloadUrlPolicy.mjs +39 -0
- package/dist/es/localFiles/security/glob.mjs +28 -0
- package/dist/es/localFiles/security/pathPolicy.mjs +59 -0
- package/dist/es/localFiles/security/sensitiveFiles.mjs +115 -0
- package/dist/es/localFiles/tools/readTools.mjs +333 -0
- package/dist/es/localFiles/tools/runtime.mjs +108 -0
- package/dist/es/localFiles/tools/transferTools.mjs +228 -0
- package/dist/es/localFiles/tools/writeTools.mjs +173 -0
- package/dist/es/localFiles/transfer/SessionFileTransfer.mjs +111 -0
- package/dist/es/localFiles/validate.mjs +66 -0
- package/dist/es/localFiles/workspace/LocalWorkspace.mjs +358 -0
- package/dist/es/localFiles/workspace/handleStore.mjs +79 -0
- package/dist/es/localFiles/workspace/watchDirectory.mjs +38 -0
- package/dist/es/package.json.mjs +38 -29
- package/dist/lib/index.js +373 -5
- package/dist/src/AgentSession.d.ts +9 -0
- package/dist/src/BotClient.d.ts +12 -2
- package/dist/src/Config.d.ts +22 -0
- package/dist/src/Session.d.ts +5 -1
- package/dist/src/api/index.d.ts +3 -1
- package/dist/src/builtinTools/browserRuntime/BrowserCommandRunner.d.ts +26 -0
- package/dist/src/builtinTools/browserRuntime/PythonRunner.d.ts +67 -0
- package/dist/src/builtinTools/browserRuntime/WorkspaceBashFs.d.ts +51 -0
- package/dist/src/builtinTools/browserRuntime/assets.d.ts +13 -0
- package/dist/src/builtinTools/browserRuntime/loadBash.d.ts +3 -0
- package/dist/src/builtinTools/browserRuntime/pyodideWorker.d.ts +44 -0
- package/dist/src/builtinTools/command.d.ts +26 -0
- package/dist/src/builtinTools/constants.d.ts +17 -0
- package/dist/src/builtinTools/createBuiltinToolsPlugin.d.ts +11 -0
- package/dist/src/builtinTools/overview.d.ts +5 -0
- package/dist/src/builtinTools/paths.d.ts +15 -0
- package/dist/src/builtinTools/schemas.d.ts +3 -0
- package/dist/src/builtinTools/tools.d.ts +60 -0
- package/dist/src/index.d.ts +4 -2
- package/dist/src/localFiles/adapters/FileSystemAccessAdapter.d.ts +20 -0
- package/dist/src/localFiles/adapters/HostBridgeAdapter.d.ts +43 -0
- package/dist/src/localFiles/adapters/MemoryWorkspaceAdapter.d.ts +21 -0
- package/dist/src/localFiles/adapters/WorkspaceFileAdapter.d.ts +40 -0
- package/dist/src/localFiles/adapters/fsaTypes.d.ts +41 -0
- package/dist/src/localFiles/constants.d.ts +51 -0
- package/dist/src/localFiles/createLocalFilesPlugin.d.ts +11 -0
- package/dist/src/localFiles/createLocalPythonPlugin.d.ts +12 -0
- package/dist/src/localFiles/errors.d.ts +34 -0
- package/dist/src/localFiles/host/connectHostBridge.d.ts +6 -0
- package/dist/src/localFiles/host/protocol.d.ts +46 -0
- package/dist/src/localFiles/index.d.ts +22 -0
- package/dist/src/localFiles/limits.d.ts +3 -0
- package/dist/src/localFiles/schemas.d.ts +29 -0
- package/dist/src/localFiles/security/downloadUrlPolicy.d.ts +4 -0
- package/dist/src/localFiles/security/glob.d.ts +3 -0
- package/dist/src/localFiles/security/pathPolicy.d.ts +14 -0
- package/dist/src/localFiles/security/sensitiveFiles.d.ts +23 -0
- package/dist/src/localFiles/tools/readTools.d.ts +7 -0
- package/dist/src/localFiles/tools/runtime.d.ts +43 -0
- package/dist/src/localFiles/tools/transferTools.d.ts +4 -0
- package/dist/src/localFiles/tools/writeTools.d.ts +4 -0
- package/dist/src/localFiles/transfer/SessionFileTransfer.d.ts +40 -0
- package/dist/src/localFiles/types.d.ts +319 -0
- package/dist/src/localFiles/validate.d.ts +2 -0
- package/dist/src/localFiles/workspace/LocalWorkspace.d.ts +111 -0
- package/dist/src/localFiles/workspace/handleStore.d.ts +11 -0
- package/dist/src/localFiles/workspace/watchDirectory.d.ts +7 -0
- package/package.json +13 -4
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
const e = `// Pyodide 专用 Worker。PythonRunner 用这份源码创建 Blob Module Worker,不经过集成方的打包器,
|
|
2
|
+
// 所以这里只能写浏览器直接能跑的 JS,不能有 import/export 语句和顶层 await。
|
|
3
|
+
//
|
|
4
|
+
// init { indexURL, packages, runner } → ready | failed { message }
|
|
5
|
+
// run { id, files, dirs, cwd, mode, target, argv, stdin } → result { id, exitCode, stdout, stderr, written, removed, createdDirs, removedDirs }
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const ROOTS = ['/workspace'];
|
|
9
|
+
const OUTPUT_LIMIT = 16 * 1024 * 1024;
|
|
10
|
+
|
|
11
|
+
let pyodide = null;
|
|
12
|
+
let runPython = null;
|
|
13
|
+
let sink = null;
|
|
14
|
+
|
|
15
|
+
/** Emscripten 的 ErrnoError 不是 Error,只带 errno 和 code。 */
|
|
16
|
+
function describe(error) {
|
|
17
|
+
if (error && error.message) return error.message;
|
|
18
|
+
if (error && (error.code || error.errno !== undefined)) return \`文件系统错误 \${error.code || \`errno \${error.errno}\`}\`;
|
|
19
|
+
return String(error);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function networkDenied(url) {
|
|
23
|
+
return new TypeError(\`浏览器里的 Python 不能访问网络:\${url}\`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** 只放行 indexURL 下的资源(Pyodide 自身和白名单 wheel),其余请求一律拒绝。 */
|
|
27
|
+
function guardNetwork(indexURL) {
|
|
28
|
+
const realFetch = globalThis.fetch ? globalThis.fetch.bind(globalThis) : null;
|
|
29
|
+
const resolve = (input) => {
|
|
30
|
+
const raw = typeof input === 'string' || input instanceof URL ? String(input) : input && input.url;
|
|
31
|
+
try {
|
|
32
|
+
return new URL(raw, indexURL).href;
|
|
33
|
+
} catch {
|
|
34
|
+
return String(raw);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
globalThis.fetch = (input, init) => {
|
|
38
|
+
const url = resolve(input);
|
|
39
|
+
if (!realFetch || !url.startsWith(indexURL)) return Promise.reject(networkDenied(url));
|
|
40
|
+
return realFetch(input, init);
|
|
41
|
+
};
|
|
42
|
+
for (const name of ['XMLHttpRequest', 'WebSocket', 'EventSource']) {
|
|
43
|
+
globalThis[name] = class {
|
|
44
|
+
constructor(url) {
|
|
45
|
+
throw networkDenied(url === undefined ? name : resolve(url));
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function collector() {
|
|
52
|
+
const decoder = new TextDecoder();
|
|
53
|
+
let text = '';
|
|
54
|
+
let size = 0;
|
|
55
|
+
let dropped = false;
|
|
56
|
+
return {
|
|
57
|
+
write(bytes) {
|
|
58
|
+
if (dropped || size + bytes.length > OUTPUT_LIMIT) {
|
|
59
|
+
dropped = true;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
size += bytes.length;
|
|
63
|
+
text += decoder.decode(bytes, { stream: true });
|
|
64
|
+
},
|
|
65
|
+
finish() {
|
|
66
|
+
return text + decoder.decode() + (dropped ? '\\n…输出超过 16 MB,后面的内容已丢弃\\n' : '');
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function init({ indexURL, packages, runner }) {
|
|
72
|
+
guardNetwork(indexURL);
|
|
73
|
+
const { loadPyodide } = await import(indexURL + 'pyodide.mjs');
|
|
74
|
+
pyodide = await loadPyodide({ indexURL, env: { HOME: '/home/pyodide', MPLBACKEND: 'Agg' } });
|
|
75
|
+
const stream = (name) => ({
|
|
76
|
+
write(bytes) {
|
|
77
|
+
if (sink) sink[name].write(bytes);
|
|
78
|
+
return bytes.length;
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
pyodide.setStdout(stream('stdout'));
|
|
82
|
+
pyodide.setStderr(stream('stderr'));
|
|
83
|
+
runPython = pyodide.runPython(runner, { globals: pyodide.toPy({ PACKAGES: packages }) });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function dirname(path) {
|
|
87
|
+
const index = path.lastIndexOf('/');
|
|
88
|
+
return index <= 0 ? '/' : path.slice(0, index);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** 主脚本、\`-c\` 代码,以及主脚本目录和 cwd 下的 .py 文件里出现的 import。 */
|
|
92
|
+
function sourcesToScan({ files, cwd, mode, target }) {
|
|
93
|
+
const decoder = new TextDecoder();
|
|
94
|
+
const sources = mode === 'c' ? [target] : [];
|
|
95
|
+
const dirs = new Set([cwd]);
|
|
96
|
+
if (mode === 'file') dirs.add(dirname(target));
|
|
97
|
+
for (const file of files) {
|
|
98
|
+
if (file.path.endsWith('.py') && (file.path === target || dirs.has(dirname(file.path)))) {
|
|
99
|
+
sources.push(decoder.decode(file.data));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return sources;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function loadPackages(sources, stderr) {
|
|
106
|
+
const encoder = new TextEncoder();
|
|
107
|
+
const report = (message) => stderr.write(encoder.encode(\`\${message}\\n\`));
|
|
108
|
+
for (const source of sources) {
|
|
109
|
+
try {
|
|
110
|
+
await pyodide.loadPackagesFromImports(source, { messageCallback() {}, errorCallback: report });
|
|
111
|
+
} catch (error) {
|
|
112
|
+
report(\`加载 Python 包失败:\${describe(error)}\`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function lstat(path) {
|
|
118
|
+
try {
|
|
119
|
+
return pyodide.FS.lstat(path);
|
|
120
|
+
} catch {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function removeTree(path) {
|
|
126
|
+
const { FS } = pyodide;
|
|
127
|
+
const stat = lstat(path);
|
|
128
|
+
if (!stat) return;
|
|
129
|
+
if (!FS.isDir(stat.mode)) {
|
|
130
|
+
FS.unlink(path);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
for (const name of FS.readdir(path)) {
|
|
134
|
+
if (name !== '.' && name !== '..') removeTree(\`\${path}/\${name}\`);
|
|
135
|
+
}
|
|
136
|
+
FS.rmdir(path);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function walk(path, files, dirs) {
|
|
140
|
+
const { FS } = pyodide;
|
|
141
|
+
for (const name of FS.readdir(path)) {
|
|
142
|
+
if (name === '.' || name === '..') continue;
|
|
143
|
+
const child = \`\${path}/\${name}\`;
|
|
144
|
+
const stat = lstat(child);
|
|
145
|
+
if (!stat) continue;
|
|
146
|
+
if (FS.isDir(stat.mode)) {
|
|
147
|
+
dirs.add(child);
|
|
148
|
+
walk(child, files, dirs);
|
|
149
|
+
} else if (FS.isFile(stat.mode)) {
|
|
150
|
+
files.set(child, FS.readFile(child));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function sameBytes(a, b) {
|
|
156
|
+
if (a.length !== b.length) return false;
|
|
157
|
+
for (let index = 0; index < a.length; index += 1) if (a[index] !== b[index]) return false;
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async function execute(message) {
|
|
162
|
+
const { FS } = pyodide;
|
|
163
|
+
const output = { stdout: collector(), stderr: collector() };
|
|
164
|
+
await loadPackages(sourcesToScan(message), output.stderr);
|
|
165
|
+
|
|
166
|
+
const before = new Map();
|
|
167
|
+
const beforeDirs = new Set(ROOTS);
|
|
168
|
+
// 上次运行停在某个根目录里时,Emscripten 不允许删除当前目录。
|
|
169
|
+
FS.chdir('/');
|
|
170
|
+
for (const root of ROOTS) {
|
|
171
|
+
removeTree(root);
|
|
172
|
+
FS.mkdirTree(root);
|
|
173
|
+
}
|
|
174
|
+
for (const dir of message.dirs) {
|
|
175
|
+
FS.mkdirTree(dir);
|
|
176
|
+
beforeDirs.add(dir);
|
|
177
|
+
}
|
|
178
|
+
for (const file of message.files) {
|
|
179
|
+
FS.mkdirTree(dirname(file.path));
|
|
180
|
+
FS.writeFile(file.path, file.data);
|
|
181
|
+
before.set(file.path, file.data);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
sink = output;
|
|
185
|
+
let exitCode;
|
|
186
|
+
const argv = pyodide.toPy(message.argv);
|
|
187
|
+
try {
|
|
188
|
+
exitCode = runPython(message.mode, message.target, argv, message.cwd, message.stdin);
|
|
189
|
+
} finally {
|
|
190
|
+
argv.destroy();
|
|
191
|
+
sink = null;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const after = new Map();
|
|
195
|
+
const afterDirs = new Set();
|
|
196
|
+
for (const root of ROOTS) if (lstat(root)) walk(root, after, afterDirs);
|
|
197
|
+
|
|
198
|
+
const written = [];
|
|
199
|
+
for (const [path, data] of after) {
|
|
200
|
+
const old = before.get(path);
|
|
201
|
+
if (!old || !sameBytes(old, data)) written.push({ path, data });
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
exitCode,
|
|
205
|
+
stdout: output.stdout.finish(),
|
|
206
|
+
stderr: output.stderr.finish(),
|
|
207
|
+
written,
|
|
208
|
+
removed: [...before.keys()].filter((path) => !after.has(path)),
|
|
209
|
+
createdDirs: [...afterDirs].filter((dir) => !beforeDirs.has(dir)),
|
|
210
|
+
removedDirs: [...beforeDirs].filter((dir) => !ROOTS.includes(dir) && !afterDirs.has(dir)),
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
self.onmessage = (event) => {
|
|
215
|
+
const message = event.data;
|
|
216
|
+
if (message.type === 'init') {
|
|
217
|
+
init(message).then(
|
|
218
|
+
() => self.postMessage({ type: 'ready' }),
|
|
219
|
+
(error) => self.postMessage({ type: 'failed', message: describe(error) })
|
|
220
|
+
);
|
|
221
|
+
} else if (message.type === 'run') {
|
|
222
|
+
execute(message).then(
|
|
223
|
+
(result) => self.postMessage({ type: 'result', id: message.id, ...result }),
|
|
224
|
+
(error) =>
|
|
225
|
+
self.postMessage({
|
|
226
|
+
type: 'result',
|
|
227
|
+
id: message.id,
|
|
228
|
+
exitCode: 1,
|
|
229
|
+
stdout: '',
|
|
230
|
+
stderr: \`Python 运行环境出错:\${describe(error)}\\n\`,
|
|
231
|
+
written: [],
|
|
232
|
+
removed: [],
|
|
233
|
+
createdDirs: [],
|
|
234
|
+
removedDirs: [],
|
|
235
|
+
})
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
`;
|
|
240
|
+
export {
|
|
241
|
+
e as default
|
|
242
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
var d = Object.defineProperty, l = Object.defineProperties;
|
|
2
|
+
var N = Object.getOwnPropertyDescriptors;
|
|
3
|
+
var s = Object.getOwnPropertySymbols;
|
|
4
|
+
var a = Object.prototype.hasOwnProperty, f = Object.prototype.propertyIsEnumerable;
|
|
5
|
+
var A = (e, n, t) => n in e ? d(e, n, { enumerable: !0, configurable: !0, writable: !0, value: t }) : e[n] = t, T = (e, n) => {
|
|
6
|
+
for (var t in n || (n = {}))
|
|
7
|
+
a.call(n, t) && A(e, t, n[t]);
|
|
8
|
+
if (s)
|
|
9
|
+
for (var t of s(n))
|
|
10
|
+
f.call(n, t) && A(e, t, n[t]);
|
|
11
|
+
return e;
|
|
12
|
+
}, _ = (e, n) => l(e, N(n));
|
|
13
|
+
var O = (e, n, t) => new Promise((u, o) => {
|
|
14
|
+
var U = (r) => {
|
|
15
|
+
try {
|
|
16
|
+
c(t.next(r));
|
|
17
|
+
} catch (i) {
|
|
18
|
+
o(i);
|
|
19
|
+
}
|
|
20
|
+
}, C = (r) => {
|
|
21
|
+
try {
|
|
22
|
+
c(t.throw(r));
|
|
23
|
+
} catch (i) {
|
|
24
|
+
o(i);
|
|
25
|
+
}
|
|
26
|
+
}, c = (r) => r.done ? u(r.value) : Promise.resolve(r.value).then(U, C);
|
|
27
|
+
c((t = t.apply(e, n)).next());
|
|
28
|
+
});
|
|
29
|
+
const R = 16e3, D = `
|
|
30
|
+
…输出已截断`;
|
|
31
|
+
function M(e) {
|
|
32
|
+
if (e.length <= 16e3)
|
|
33
|
+
return e;
|
|
34
|
+
let n = 16e3;
|
|
35
|
+
const t = e.charCodeAt(n - 1);
|
|
36
|
+
return t >= 55296 && t <= 56319 && (n -= 1), e.slice(0, n) + D;
|
|
37
|
+
}
|
|
38
|
+
function h(e) {
|
|
39
|
+
return {
|
|
40
|
+
exec(t) {
|
|
41
|
+
return O(this, null, function* () {
|
|
42
|
+
const u = yield e.exec(t);
|
|
43
|
+
return _(T({}, u), {
|
|
44
|
+
stdout: M(u.stdout),
|
|
45
|
+
stderr: M(u.stderr)
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export {
|
|
52
|
+
R as MAX_COMMAND_OUTPUT_CHARS,
|
|
53
|
+
D as OUTPUT_TRUNCATED_NOTE,
|
|
54
|
+
M as limitOutput,
|
|
55
|
+
h as withOutputLimit
|
|
56
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const _ = ["shell", "read_file", "write_file", "append_file", "run_file", "edit_file", "grep", "find", "load_skill", "read_skill_resource", "run_skill_script"], e = 81920, s = 81920, l = 2e4, i = ".", n = "/workspace", o = [".py", ".sh", ".js"];
|
|
2
|
+
export {
|
|
3
|
+
_ as BUILTIN_FUNCTION_CODES,
|
|
4
|
+
l as MAX_COMMAND_CHARS,
|
|
5
|
+
e as MAX_READ_BYTES,
|
|
6
|
+
s as MAX_WRITE_BYTES,
|
|
7
|
+
o as RUNNABLE_EXTENSIONS,
|
|
8
|
+
i as SHELL_CWD,
|
|
9
|
+
n as WORKSPACE_MOUNT
|
|
10
|
+
};
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
var G = Object.defineProperty, K = Object.defineProperties;
|
|
2
|
+
var W = Object.getOwnPropertyDescriptors;
|
|
3
|
+
var D = Object.getOwnPropertySymbols;
|
|
4
|
+
var X = Object.prototype.hasOwnProperty, Q = Object.prototype.propertyIsEnumerable;
|
|
5
|
+
var P = (e, t, o) => t in e ? G(e, t, { enumerable: !0, configurable: !0, writable: !0, value: o }) : e[t] = o, s = (e, t) => {
|
|
6
|
+
for (var o in t || (t = {}))
|
|
7
|
+
X.call(t, o) && P(e, o, t[o]);
|
|
8
|
+
if (D)
|
|
9
|
+
for (var o of D(t))
|
|
10
|
+
Q.call(t, o) && P(e, o, t[o]);
|
|
11
|
+
return e;
|
|
12
|
+
}, h = (e, t) => K(e, W(t));
|
|
13
|
+
var U = (e, t, o) => new Promise((l, u) => {
|
|
14
|
+
var m = (n) => {
|
|
15
|
+
try {
|
|
16
|
+
d(o.next(n));
|
|
17
|
+
} catch (r) {
|
|
18
|
+
u(r);
|
|
19
|
+
}
|
|
20
|
+
}, c = (n) => {
|
|
21
|
+
try {
|
|
22
|
+
d(o.throw(n));
|
|
23
|
+
} catch (r) {
|
|
24
|
+
u(r);
|
|
25
|
+
}
|
|
26
|
+
}, d = (n) => n.done ? l(n.value) : Promise.resolve(n.value).then(m, c);
|
|
27
|
+
d((o = o.apply(e, t)).next());
|
|
28
|
+
});
|
|
29
|
+
import { v4 as Y } from "uuid";
|
|
30
|
+
import Z from "../Logger.mjs";
|
|
31
|
+
import { HostBridgeAdapter as k } from "../localFiles/adapters/HostBridgeAdapter.mjs";
|
|
32
|
+
import { SANDBOX_PROTOCOL as ee } from "../localFiles/host/protocol.mjs";
|
|
33
|
+
import { cancelledError as w, workspaceNotGranted as te, ToolError as f, ToolCode as a, toToolError as oe } from "../localFiles/errors.mjs";
|
|
34
|
+
import { validateToolInput as ne } from "../localFiles/validate.mjs";
|
|
35
|
+
import { BrowserCommandRunner as re } from "./browserRuntime/BrowserCommandRunner.mjs";
|
|
36
|
+
import { withOutputLimit as E } from "./command.mjs";
|
|
37
|
+
import { BUILTIN_FUNCTION_CODES as ie, SHELL_CWD as se } from "./constants.mjs";
|
|
38
|
+
import { BUILTIN_TOOL_SCHEMAS as le } from "./schemas.mjs";
|
|
39
|
+
import { shell as ae, readFile as de, writeFile as ce, appendFile as ue, runFile as me, editFile as fe, grep as ge, find as he, loadSkill as _e, readSkillResource as be, runSkillScript as ye } from "./tools.mjs";
|
|
40
|
+
const Te = {
|
|
41
|
+
shell: ae,
|
|
42
|
+
read_file: de,
|
|
43
|
+
write_file: ce,
|
|
44
|
+
append_file: ue,
|
|
45
|
+
run_file: me,
|
|
46
|
+
edit_file: fe,
|
|
47
|
+
grep: ge,
|
|
48
|
+
find: he,
|
|
49
|
+
load_skill: _e,
|
|
50
|
+
read_skill_resource: be,
|
|
51
|
+
run_skill_script: ye
|
|
52
|
+
}, T = new Z("[BuiltinTools] "), H = /* @__PURE__ */ new Set(["shell", "run_file", "run_skill_script"]);
|
|
53
|
+
function we(e, t, o) {
|
|
54
|
+
var l, u;
|
|
55
|
+
if (e.commandRunner)
|
|
56
|
+
return E(e.commandRunner);
|
|
57
|
+
if (t instanceof k && t.capabilities.has("sandbox-exec")) {
|
|
58
|
+
if (t.canExec)
|
|
59
|
+
return E({
|
|
60
|
+
exec: (c) => t.exec(c)
|
|
61
|
+
});
|
|
62
|
+
const m = `${(l = t.sandboxVersion) != null ? l : ""}@${(u = t.sandboxProtocol) != null ? u : ""}`;
|
|
63
|
+
o.rejectedSandbox !== m && (o.rejectedSandbox = m, T.error("sandbox-protocol", {
|
|
64
|
+
sandboxVersion: t.sandboxVersion,
|
|
65
|
+
sandboxProtocol: t.sandboxProtocol,
|
|
66
|
+
supported: ee
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
if (e.browserRuntime.enabled)
|
|
70
|
+
return (o.adapter !== t || !o.runner) && (o.adapter = t, o.runner = E(new re({
|
|
71
|
+
adapter: t,
|
|
72
|
+
sensitive: e.sensitive,
|
|
73
|
+
moduleURL: e.browserRuntime.bashModuleURL,
|
|
74
|
+
pyodideIndexURL: e.browserRuntime.pyodideIndexURL
|
|
75
|
+
}))), o.runner;
|
|
76
|
+
}
|
|
77
|
+
function pe(e) {
|
|
78
|
+
if (typeof e != "string")
|
|
79
|
+
return e;
|
|
80
|
+
try {
|
|
81
|
+
return JSON.parse(e);
|
|
82
|
+
} catch (t) {
|
|
83
|
+
throw new f(a.BadRequest, "参数不是合法的 JSON 对象。");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function xe(e) {
|
|
87
|
+
const t = e instanceof DOMException ? e.name : "", o = e instanceof Error ? e.message : "";
|
|
88
|
+
if (t === "NotFoundError")
|
|
89
|
+
return new f(a.NotFound, "脚本或目录不存在。");
|
|
90
|
+
if (t === "SecurityError")
|
|
91
|
+
return new f(a.Forbidden, "命令路径不在工作区内。");
|
|
92
|
+
if (t === "AbortError")
|
|
93
|
+
return o.includes("超时") ? new f(a.Timeout, "命令运行超时,已中止。") : o.includes("已有") ? new f(a.TooManyRequests, "已有一个命令在运行。") : w();
|
|
94
|
+
if (t === "NotAllowedError")
|
|
95
|
+
return new f(a.NotImplemented, "当前环境不能执行命令或脚本,需要端侧宿主。");
|
|
96
|
+
}
|
|
97
|
+
function Ie(e) {
|
|
98
|
+
return new Promise((t, o) => {
|
|
99
|
+
e.aborted && o(w()), e.addEventListener("abort", () => o(w()), {
|
|
100
|
+
once: !0
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
function V(e, t = 160) {
|
|
105
|
+
return e.length > t ? `${e.slice(0, t)}…` : e;
|
|
106
|
+
}
|
|
107
|
+
function Oe(e) {
|
|
108
|
+
const t = {};
|
|
109
|
+
for (const o of ["path", "skill_name", "resource_name", "script_name", "pattern", "name"])
|
|
110
|
+
typeof e[o] == "string" && (t[o] = e[o]);
|
|
111
|
+
return typeof e.command == "string" && (t.command = V(e.command)), typeof e.start_line == "number" && (t.start_line = e.start_line), typeof e.end_line == "number" && (t.end_line = e.end_line), typeof e.content == "string" && (t.contentLength = e.content.length), typeof e.old_text == "string" && (t.oldTextLength = e.old_text.length), typeof e.new_text == "string" && (t.newTextLength = e.new_text.length), Array.isArray(e.args) && (t.argCount = e.args.length), t;
|
|
112
|
+
}
|
|
113
|
+
function Le(e) {
|
|
114
|
+
return s({
|
|
115
|
+
code: e.code,
|
|
116
|
+
message: e.message
|
|
117
|
+
}, e.data ? {
|
|
118
|
+
data: e.data
|
|
119
|
+
} : {});
|
|
120
|
+
}
|
|
121
|
+
function Ue({
|
|
122
|
+
pluginCode: e,
|
|
123
|
+
workspace: t
|
|
124
|
+
}) {
|
|
125
|
+
const o = /* @__PURE__ */ new Map(), l = {}, u = {};
|
|
126
|
+
return ie.forEach((m) => {
|
|
127
|
+
u[m] = (c, d, n) => {
|
|
128
|
+
let r = !1;
|
|
129
|
+
Se(t, o, l, m, c, (S) => {
|
|
130
|
+
if (!r) {
|
|
131
|
+
r = !0;
|
|
132
|
+
try {
|
|
133
|
+
d(S);
|
|
134
|
+
} catch (x) {
|
|
135
|
+
console.error("[BuiltinTools] callback failed", x);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}, h(s({}, n), {
|
|
139
|
+
pluginCode: e
|
|
140
|
+
}));
|
|
141
|
+
};
|
|
142
|
+
}), {
|
|
143
|
+
[e]: u
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
function Se(e, t, o, l, u, m, c) {
|
|
147
|
+
return U(this, null, function* () {
|
|
148
|
+
var N, F, M, A, q;
|
|
149
|
+
const d = {
|
|
150
|
+
requestId: c.requestId || Y(),
|
|
151
|
+
applicationId: c.applicationId || e.applicationId,
|
|
152
|
+
sessionId: c.sessionId || "",
|
|
153
|
+
pluginCode: c.pluginCode,
|
|
154
|
+
functionCode: l,
|
|
155
|
+
signal: c.signal
|
|
156
|
+
}, n = {
|
|
157
|
+
requestId: d.requestId,
|
|
158
|
+
sessionId: d.sessionId,
|
|
159
|
+
functionCode: l
|
|
160
|
+
}, r = new AbortController();
|
|
161
|
+
let p = !1;
|
|
162
|
+
const S = setTimeout(() => {
|
|
163
|
+
p = !0, r.abort();
|
|
164
|
+
}, e.limits.toolTimeoutMs), x = () => r.abort();
|
|
165
|
+
(N = d.signal) == null || N.addEventListener("abort", x, {
|
|
166
|
+
once: !0
|
|
167
|
+
}), (F = d.signal) != null && F.aborted && r.abort();
|
|
168
|
+
let b = null, y = null, I;
|
|
169
|
+
const R = Date.now();
|
|
170
|
+
try {
|
|
171
|
+
const O = pe(u), i = ne(O, le[l].parameters);
|
|
172
|
+
if (typeof i.path == "string" && (n.path = i.path), T.log("start", s(s({}, n), Oe(i))), yield e.ready, r.signal.aborted)
|
|
173
|
+
throw w();
|
|
174
|
+
const _ = e.adapter;
|
|
175
|
+
if (!_)
|
|
176
|
+
throw te();
|
|
177
|
+
if (b = e.acquireSlot(), !b)
|
|
178
|
+
throw new f(a.TooManyRequests, "同时进行的文件操作过多,请稍后重试。");
|
|
179
|
+
if (H.has(l) && (y = e.acquireCommand(), !y))
|
|
180
|
+
throw new f(a.TooManyRequests, "已有一个命令在运行,请等它结束后再试。");
|
|
181
|
+
I = e.track(r), e.emit("tool:start", s({}, n));
|
|
182
|
+
const v = d.sessionId || "default";
|
|
183
|
+
let g = t.get(v);
|
|
184
|
+
g || (g = {
|
|
185
|
+
cwd: se
|
|
186
|
+
}, t.set(v, g));
|
|
187
|
+
const $ = we(e, _, o), j = g.cwd, J = {
|
|
188
|
+
adapter: _,
|
|
189
|
+
runner: $,
|
|
190
|
+
signal: r.signal,
|
|
191
|
+
timeoutMs: e.limits.toolTimeoutMs,
|
|
192
|
+
shellCwd: g
|
|
193
|
+
}, L = yield Promise.race([Te[l](i, J), Ie(r.signal)]), B = {
|
|
194
|
+
code: a.Ok,
|
|
195
|
+
message: "ok",
|
|
196
|
+
data: L.data
|
|
197
|
+
};
|
|
198
|
+
L.truncated && (B.truncated = !0);
|
|
199
|
+
const z = Date.now() - R, C = L.data.exitCode;
|
|
200
|
+
T.log("finish", s(s(s(h(s({}, n), {
|
|
201
|
+
elapsedMs: z,
|
|
202
|
+
code: a.Ok
|
|
203
|
+
}), L.truncated ? {
|
|
204
|
+
truncated: !0
|
|
205
|
+
} : {}), typeof C == "number" ? {
|
|
206
|
+
exitCode: C
|
|
207
|
+
} : {}), l === "shell" ? {
|
|
208
|
+
cwd: g.cwd,
|
|
209
|
+
cwdChanged: g.cwd !== j
|
|
210
|
+
} : {})), e.emit("tool:finish", h(s({}, n), {
|
|
211
|
+
code: a.Ok
|
|
212
|
+
})), H.has(l) && e.notifyFilesChanged(), m(B);
|
|
213
|
+
} catch (O) {
|
|
214
|
+
let i = (M = xe(O)) != null ? M : oe(O);
|
|
215
|
+
p ? i = new f(a.Timeout, "操作超时,已中止。") : r.signal.aborted && i.code !== a.Cancelled && (i = w());
|
|
216
|
+
const _ = Date.now() - R;
|
|
217
|
+
i.code === a.Cancelled ? (T.log("cancelled", h(s({}, n), {
|
|
218
|
+
elapsedMs: _,
|
|
219
|
+
timedOut: p
|
|
220
|
+
})), e.emit("tool:cancelled", s({}, n))) : (T.error("error", h(s({}, n), {
|
|
221
|
+
elapsedMs: _,
|
|
222
|
+
code: i.code,
|
|
223
|
+
message: V(i.message, 300)
|
|
224
|
+
})), e.emit("tool:error", h(s({}, n), {
|
|
225
|
+
code: i.code,
|
|
226
|
+
message: i.message,
|
|
227
|
+
reason: (A = i.data) == null ? void 0 : A.reason
|
|
228
|
+
}))), m(Le(i));
|
|
229
|
+
} finally {
|
|
230
|
+
clearTimeout(S), (q = d.signal) == null || q.removeEventListener("abort", x), b == null || b(), y == null || y(), I == null || I();
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
export {
|
|
235
|
+
Ue as createBuiltinToolsPlugin
|
|
236
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
function c(r) {
|
|
2
|
+
return `预览:
|
|
3
|
+
${r.length > 500 ? r.slice(0, 500) : r}`;
|
|
4
|
+
}
|
|
5
|
+
function O(r) {
|
|
6
|
+
let n;
|
|
7
|
+
try {
|
|
8
|
+
n = JSON.parse(r);
|
|
9
|
+
} catch (e) {
|
|
10
|
+
return `JSON 无法完整解析。
|
|
11
|
+
${c(r)}`;
|
|
12
|
+
}
|
|
13
|
+
if (Array.isArray(n)) {
|
|
14
|
+
const e = n[0], t = e && typeof e == "object" && !Array.isArray(e) ? `元素字段:${Object.keys(e).slice(0, 20).join(", ") || "(无)"}。` : `元素类型:${e === null ? "null" : typeof e}。`;
|
|
15
|
+
return `JSON 数组,长度 ${n.length}。${t}
|
|
16
|
+
${c(r)}`;
|
|
17
|
+
}
|
|
18
|
+
if (n && typeof n == "object") {
|
|
19
|
+
const e = n, t = Object.keys(e), s = t.filter((i) => Array.isArray(e[i])).slice(0, 10).map((i) => `${i} (${e[i].length})`), o = s.length ? `数组字段:${s.join("、")}。` : "";
|
|
20
|
+
return `JSON 对象。字段:${t.slice(0, 40).join(", ") || "(无)"}。${o}
|
|
21
|
+
${c(r)}`;
|
|
22
|
+
}
|
|
23
|
+
return `JSON ${n === null ? "null" : typeof n}。
|
|
24
|
+
${c(r)}`;
|
|
25
|
+
}
|
|
26
|
+
function h(r, n) {
|
|
27
|
+
var a, p;
|
|
28
|
+
const e = r.match(/<([A-Za-z_][\w:.-]*)\b/), t = (a = e == null ? void 0 : e[1]) != null ? a : "未知", s = /* @__PURE__ */ new Map(), o = new RegExp("<([A-Za-z_][\\w:.-]*)\\b", "g");
|
|
29
|
+
let i, u = !1;
|
|
30
|
+
for (; i = o.exec(r); ) {
|
|
31
|
+
const l = i[1];
|
|
32
|
+
if (!u && l === t) {
|
|
33
|
+
u = !0;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (s.set(l, ((p = s.get(l)) != null ? p : 0) + 1), s.size > 30)
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
const f = Array.from(s.entries()).slice(0, 20).map(([l, v]) => `${l} (${v})`).join("、");
|
|
40
|
+
return `${n} 根元素 ${t}。直接或嵌套子元素:${f || "(无)"}。
|
|
41
|
+
${c(r)}`;
|
|
42
|
+
}
|
|
43
|
+
function g(r, n, e) {
|
|
44
|
+
var f;
|
|
45
|
+
const t = r.split(/\r?\n/).filter((a) => a.length > 0), s = (f = t[0]) != null ? f : "", o = s ? s.split(n).length : 0, i = Math.max(t.length - 1, 0), u = t.slice(0, 4).join(`
|
|
46
|
+
`);
|
|
47
|
+
return `${e},${o} 列,数据行 ${i}。表头:${s}
|
|
48
|
+
预览:
|
|
49
|
+
${u}`;
|
|
50
|
+
}
|
|
51
|
+
function j(r) {
|
|
52
|
+
const n = $(r);
|
|
53
|
+
return n === ".json" || n === ".xml" || n === ".svg" || n === ".csv" || n === ".tsv";
|
|
54
|
+
}
|
|
55
|
+
function m(r, n) {
|
|
56
|
+
const e = $(r);
|
|
57
|
+
return e === ".json" ? O(n) : e === ".svg" ? h(n, "SVG") : e === ".xml" ? h(n, "XML") : e === ".tsv" ? g(n, " ", "TSV") : e === ".csv" ? g(n, ",", "CSV") : c(n);
|
|
58
|
+
}
|
|
59
|
+
function $(r) {
|
|
60
|
+
var t;
|
|
61
|
+
const n = (t = r.split("/").pop()) != null ? t : "", e = n.lastIndexOf(".");
|
|
62
|
+
return e >= 0 ? n.slice(e).toLowerCase() : "";
|
|
63
|
+
}
|
|
64
|
+
const S = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp", ".ico", ".tif", ".tiff"]);
|
|
65
|
+
function w(r) {
|
|
66
|
+
return S.has($(r));
|
|
67
|
+
}
|
|
68
|
+
function A(r, n) {
|
|
69
|
+
return $(r) === ".pdf" ? !0 : !n || n.byteLength < 4 ? !1 : n[0] === 37 && n[1] === 80 && n[2] === 68 && n[3] === 70;
|
|
70
|
+
}
|
|
71
|
+
export {
|
|
72
|
+
$ as extensionOf,
|
|
73
|
+
w as isImagePath,
|
|
74
|
+
A as isPdf,
|
|
75
|
+
j as isStructuredPath,
|
|
76
|
+
m as structureOverview
|
|
77
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { ToolError as o, ToolCode as i } from "../localFiles/errors.mjs";
|
|
2
|
+
const l = ["input", "output", "uploads", "tmp"], h = "不要使用 input、output、uploads、tmp,也不要新建这些目录。请把文件直接放在工作区已有位置或根目录。", c = /(?:^|[\s'"=;|&<>`:])\/?(?:input|output|uploads|tmp)(?=\/|[\s'"=;|&<>`:]|$)/;
|
|
3
|
+
function d(t) {
|
|
4
|
+
return c.test(t);
|
|
5
|
+
}
|
|
6
|
+
function u(t) {
|
|
7
|
+
const n = t.split("/")[0];
|
|
8
|
+
return l.includes(n);
|
|
9
|
+
}
|
|
10
|
+
function r(t) {
|
|
11
|
+
throw new o(i.Forbidden, t, {
|
|
12
|
+
reason: "path_outside_workspace"
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
function f(t) {
|
|
16
|
+
if (typeof t != "string" || t.length === 0)
|
|
17
|
+
throw new o(i.BadRequest, "path 必须是工作区内绝对路径。");
|
|
18
|
+
(t.includes("\0") || t.includes("\\")) && r("路径不能包含反斜杠。");
|
|
19
|
+
const n = t.normalize("NFC").trim();
|
|
20
|
+
if (!n.startsWith("/"))
|
|
21
|
+
throw new o(i.BadRequest, "path 必须是工作区内绝对路径,例如 /说明.md。");
|
|
22
|
+
const e = n.split("/").filter((s) => s.length > 0);
|
|
23
|
+
if (e.some((s) => s === "." || s === "..") && r("路径不能包含 . 或 .. 。"), e.length > 0 && u(e[0]))
|
|
24
|
+
throw new o(i.BadRequest, h);
|
|
25
|
+
return e.join("/");
|
|
26
|
+
}
|
|
27
|
+
function a(t) {
|
|
28
|
+
return f(t);
|
|
29
|
+
}
|
|
30
|
+
function w(t) {
|
|
31
|
+
return f(t);
|
|
32
|
+
}
|
|
33
|
+
function R(t) {
|
|
34
|
+
return t ? `/${t}` : "/";
|
|
35
|
+
}
|
|
36
|
+
function S(t) {
|
|
37
|
+
if (t === ".")
|
|
38
|
+
return !0;
|
|
39
|
+
if (!t || t.startsWith("/") || t.includes("\\") || t.includes("\0"))
|
|
40
|
+
return !1;
|
|
41
|
+
const n = t.split("/").filter((e) => e.length > 0);
|
|
42
|
+
return n.length > 0 && n.every((e) => e !== "." && e !== "..") && !u(n[0]);
|
|
43
|
+
}
|
|
44
|
+
function g(t, n) {
|
|
45
|
+
if (!t || /[\\/\0]/.test(t) || t === "." || t === "..")
|
|
46
|
+
throw new o(i.BadRequest, "skill_name 必须是单个技能目录名。");
|
|
47
|
+
if (!n || n.startsWith("/") || n.includes("\\") || n.includes("\0"))
|
|
48
|
+
throw new o(i.BadRequest, "资源路径必须是技能目录内的相对路径。");
|
|
49
|
+
const e = n.split("/").filter((s) => s.length > 0);
|
|
50
|
+
return (e.length === 0 || e.some((s) => s === "." || s === "..")) && r("资源路径不能跳出技能目录。"), `skills/${t}/${e.join("/")}`;
|
|
51
|
+
}
|
|
52
|
+
export {
|
|
53
|
+
l as SYNTHETIC_DIRS,
|
|
54
|
+
h as SYNTHETIC_DIR_MESSAGE,
|
|
55
|
+
S as isSafeCwd,
|
|
56
|
+
u as isSyntheticCwd,
|
|
57
|
+
d as mentionsSyntheticDir,
|
|
58
|
+
a as resolveFilePath,
|
|
59
|
+
w as resolveRunPath,
|
|
60
|
+
f as resolveWorkspacePath,
|
|
61
|
+
g as skillRelative,
|
|
62
|
+
R as toVirtualPath
|
|
63
|
+
};
|