@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,333 @@
|
|
|
1
|
+
var H = (e, t) => {
|
|
2
|
+
if (t = Symbol[e])
|
|
3
|
+
return t;
|
|
4
|
+
throw Error("Symbol." + e + " is not defined");
|
|
5
|
+
};
|
|
6
|
+
var x = (e, t, s) => new Promise((o, r) => {
|
|
7
|
+
var i = (a) => {
|
|
8
|
+
try {
|
|
9
|
+
n(s.next(a));
|
|
10
|
+
} catch (l) {
|
|
11
|
+
r(l);
|
|
12
|
+
}
|
|
13
|
+
}, c = (a) => {
|
|
14
|
+
try {
|
|
15
|
+
n(s.throw(a));
|
|
16
|
+
} catch (l) {
|
|
17
|
+
r(l);
|
|
18
|
+
}
|
|
19
|
+
}, n = (a) => a.done ? o(a.value) : Promise.resolve(a.value).then(i, c);
|
|
20
|
+
n((s = s.apply(e, t)).next());
|
|
21
|
+
}), L = function(e, t) {
|
|
22
|
+
this[0] = e, this[1] = t;
|
|
23
|
+
}, A = (e, t, s) => {
|
|
24
|
+
var o = (c, n, a, l) => {
|
|
25
|
+
try {
|
|
26
|
+
var d = s[c](n), m = (n = d.value) instanceof L, u = d.done;
|
|
27
|
+
Promise.resolve(m ? n[0] : n).then((f) => m ? o(c === "return" ? c : "next", n[1] ? { done: f.done, value: f.value } : f, a, l) : a({ value: f, done: u })).catch((f) => o("throw", f, a, l));
|
|
28
|
+
} catch (f) {
|
|
29
|
+
l(f);
|
|
30
|
+
}
|
|
31
|
+
}, r = (c) => i[c] = (n) => new Promise((a, l) => o(c, n, a, l)), i = {};
|
|
32
|
+
return s = s.apply(e, t), i[Symbol.asyncIterator] = () => i, r("next"), r("throw"), r("return"), i;
|
|
33
|
+
};
|
|
34
|
+
var I = (e, t, s) => (t = e[H("asyncIterator")]) ? t.call(e) : (e = e[H("iterator")](), t = {}, s = (o, r) => (r = e[o]) && (t[o] = (i) => new Promise((c, n, a) => (i = r.call(e, i), a = i.done, Promise.resolve(i.value).then((l) => c({ value: l, done: a }), n)))), s("next"), s("return"), t);
|
|
35
|
+
import { TEXT_SEARCH_MAX_FILE_BYTES as $, LIST_DIRECTORY_MAX_LIMIT as J, LIST_DIRECTORY_DEFAULT_LIMIT as K, DEFAULT_IGNORED_DIRECTORIES as Q, SEARCH_MAX_DEPTH as P, SEARCH_DEFAULT_DEPTH as V, TEXT_SEARCH_MAX_LINE_CHARS as z, TEXT_SEARCH_MAX_CONTEXT_LINES as Z, TEXT_SEARCH_MAX_FILES as ee, DEFAULT_IGNORED_FILE_PATTERNS as te } from "../constants.mjs";
|
|
36
|
+
import { ToolError as T, ToolCode as R, throwIfAborted as X } from "../errors.mjs";
|
|
37
|
+
import { matchGlob as N } from "../security/glob.mjs";
|
|
38
|
+
import { normalizeWorkspacePath as M, joinPath as G } from "../security/pathPolicy.mjs";
|
|
39
|
+
import { assertNotSensitive as O, requireFile as ae, blobLooksBinary as se, readBytes as F, hasUtf8Bom as ne, utf8ByteLength as ie, sha256 as W, yieldToMain as U, looksBinary as oe } from "./runtime.mjs";
|
|
40
|
+
const re = new TextEncoder();
|
|
41
|
+
function y(e, t, s, o) {
|
|
42
|
+
return e === void 0 ? t : Math.min(Math.max(Math.trunc(e), s), o);
|
|
43
|
+
}
|
|
44
|
+
const Ee = (e, t) => x(void 0, null, function* () {
|
|
45
|
+
const s = M(e.path, {
|
|
46
|
+
allowRoot: !0
|
|
47
|
+
});
|
|
48
|
+
if ((yield t.adapter.stat(s)).kind !== "directory")
|
|
49
|
+
throw new T(R.BadRequest, "目标是文件,不是目录。");
|
|
50
|
+
const r = y(e.offset, 0, 0, Number.MAX_SAFE_INTEGER), i = y(e.limit, K, 1, J), c = yield t.adapter.listEntries(s, t.signal);
|
|
51
|
+
c.sort((a, l) => a.kind !== l.kind ? a.kind === "directory" ? -1 : 1 : a.name < l.name ? -1 : a.name > l.name ? 1 : 0);
|
|
52
|
+
const n = c.slice(r, r + i).map((a) => {
|
|
53
|
+
const l = G(s, a.name), d = {
|
|
54
|
+
name: a.name,
|
|
55
|
+
path: l,
|
|
56
|
+
kind: a.kind
|
|
57
|
+
};
|
|
58
|
+
return a.kind === "file" && (d.size = a.size, d.lastModified = a.lastModified, t.sensitive.isSensitive(l) && (d.sensitive = !0)), d;
|
|
59
|
+
});
|
|
60
|
+
return {
|
|
61
|
+
data: {
|
|
62
|
+
path: s,
|
|
63
|
+
entries: n,
|
|
64
|
+
total: c.length,
|
|
65
|
+
hasMore: r + n.length < c.length
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
function ce(e, t, s) {
|
|
70
|
+
return A(this, null, function* () {
|
|
71
|
+
var n;
|
|
72
|
+
const o = new TextDecoder(t), r = e.stream().getReader();
|
|
73
|
+
let i = "", c = !1;
|
|
74
|
+
try {
|
|
75
|
+
for (; ; ) {
|
|
76
|
+
X(s);
|
|
77
|
+
const {
|
|
78
|
+
done: a,
|
|
79
|
+
value: l
|
|
80
|
+
} = yield new L(r.read());
|
|
81
|
+
i += a ? o.decode() : o.decode(l, {
|
|
82
|
+
stream: !0
|
|
83
|
+
});
|
|
84
|
+
const d = i.split(`
|
|
85
|
+
`);
|
|
86
|
+
i = (n = d.pop()) != null ? n : "";
|
|
87
|
+
for (const m of d)
|
|
88
|
+
c = !0, yield m;
|
|
89
|
+
if (a)
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
} finally {
|
|
93
|
+
r.releaseLock();
|
|
94
|
+
}
|
|
95
|
+
(i || !c) && (yield i);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
const Te = (e, t) => x(void 0, null, function* () {
|
|
99
|
+
var w, h;
|
|
100
|
+
const s = M(e.path);
|
|
101
|
+
O(t, s, "read");
|
|
102
|
+
const o = yield ae(t.adapter, s), r = yield t.adapter.readFile(s), i = (w = o.size) != null ? w : r.size;
|
|
103
|
+
if (yield se(r))
|
|
104
|
+
throw new T(R.BadRequest, "这是二进制文件,不能按文本读取。可以使用 stat_file 查看信息,或使用 upload_file 上传到会话。");
|
|
105
|
+
const c = yield F(r.slice(0, 3)), n = ne(c) ? "utf-8" : (h = e.encoding) != null ? h : "utf-8", a = y(e.startLine, 1, 1, Number.MAX_SAFE_INTEGER), l = e.endLine === void 0 ? Number.MAX_SAFE_INTEGER : Math.max(Math.trunc(e.endLine), a), d = y(e.maxBytes, t.limits.maxReadBytes, 1, t.limits.maxReadBytes), m = i <= t.limits.maxTransferBytes, u = [];
|
|
106
|
+
let f = 0, p = 0, b = a - 1, g = !1, E = !1;
|
|
107
|
+
try {
|
|
108
|
+
for (var fe = I(ce(r, n, t.signal)), B, v, D; B = !(v = yield fe.next()).done; B = !1) {
|
|
109
|
+
const k = v.value;
|
|
110
|
+
p++;
|
|
111
|
+
const S = k.endsWith("\r") ? k.slice(0, -1) : k;
|
|
112
|
+
if (S !== k && (E = !0), p < a || p > l || g) {
|
|
113
|
+
if (!m && (g || p > l))
|
|
114
|
+
break;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
const q = ie(S) + (u.length ? 1 : 0);
|
|
118
|
+
if (f + q > d) {
|
|
119
|
+
if (g = !0, u.length || (u.push(le(S, d)), b = p), !m)
|
|
120
|
+
break;
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
u.push(S), f += q, b = p;
|
|
124
|
+
}
|
|
125
|
+
} catch (v) {
|
|
126
|
+
D = [v];
|
|
127
|
+
} finally {
|
|
128
|
+
try {
|
|
129
|
+
B && (v = fe.return) && (yield v.call(fe));
|
|
130
|
+
} finally {
|
|
131
|
+
if (D)
|
|
132
|
+
throw D[0];
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const _ = {
|
|
136
|
+
path: s,
|
|
137
|
+
content: u.join(`
|
|
138
|
+
`),
|
|
139
|
+
startLine: a,
|
|
140
|
+
endLine: Math.max(b, a - 1),
|
|
141
|
+
size: i,
|
|
142
|
+
encoding: n,
|
|
143
|
+
lineEnding: E ? "crlf" : "lf"
|
|
144
|
+
};
|
|
145
|
+
return m && (_.totalLines = p), i <= t.limits.maxWriteBytes && (_.hash = yield W(yield F(r))), {
|
|
146
|
+
data: _,
|
|
147
|
+
truncated: g || void 0
|
|
148
|
+
};
|
|
149
|
+
});
|
|
150
|
+
function le(e, t) {
|
|
151
|
+
const s = re.encode(e);
|
|
152
|
+
return s.byteLength <= t ? e : new TextDecoder().decode(s.slice(0, t)).replace(/\uFFFD$/, "");
|
|
153
|
+
}
|
|
154
|
+
const Re = (e, t) => x(void 0, null, function* () {
|
|
155
|
+
var i;
|
|
156
|
+
const s = M(e.path), o = yield t.adapter.stat(s), r = {
|
|
157
|
+
path: s,
|
|
158
|
+
kind: o.kind,
|
|
159
|
+
sensitive: o.kind === "file" && t.sensitive.isSensitive(s)
|
|
160
|
+
};
|
|
161
|
+
return o.kind === "file" && (r.size = o.size, r.lastModified = o.lastModified, e.includeHash && ((i = o.size) != null ? i : 0) <= t.limits.maxTransferBytes && (r.hash = yield W(yield F(yield t.adapter.readFile(s))))), {
|
|
162
|
+
data: r
|
|
163
|
+
};
|
|
164
|
+
});
|
|
165
|
+
function de(e) {
|
|
166
|
+
return te.some((t) => N(t, e));
|
|
167
|
+
}
|
|
168
|
+
function Y(e, t, s) {
|
|
169
|
+
return A(this, null, function* () {
|
|
170
|
+
const o = [{
|
|
171
|
+
path: t,
|
|
172
|
+
depth: 0
|
|
173
|
+
}];
|
|
174
|
+
let r = 0;
|
|
175
|
+
for (; o.length; ) {
|
|
176
|
+
const i = o.shift();
|
|
177
|
+
X(e.signal), ++r % 20 === 0 && (yield new L(U()));
|
|
178
|
+
const c = yield new L(e.adapter.listEntries(i.path, e.signal));
|
|
179
|
+
c.sort((n, a) => n.name < a.name ? -1 : n.name > a.name ? 1 : 0);
|
|
180
|
+
for (const n of c) {
|
|
181
|
+
const a = G(i.path, n.name);
|
|
182
|
+
if (n.kind === "directory") {
|
|
183
|
+
i.depth + 1 < s && !Q.includes(n.name) && o.push({
|
|
184
|
+
path: a,
|
|
185
|
+
depth: i.depth + 1
|
|
186
|
+
});
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
de(n.name) || e.sensitive.match(a, "search") || (yield {
|
|
190
|
+
path: a,
|
|
191
|
+
relativePath: t ? a.slice(t.length + 1) : a,
|
|
192
|
+
name: n.name,
|
|
193
|
+
size: n.size,
|
|
194
|
+
lastModified: n.lastModified
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
function j(e, t) {
|
|
201
|
+
return e.includes("/") ? N(e, t.relativePath) : N(e, t.name);
|
|
202
|
+
}
|
|
203
|
+
const _e = (e, t) => x(void 0, null, function* () {
|
|
204
|
+
const s = M(e.path, {
|
|
205
|
+
allowRoot: !0
|
|
206
|
+
});
|
|
207
|
+
if (!e.pattern.trim())
|
|
208
|
+
throw new T(R.BadRequest, "参数 pattern 不能为空。");
|
|
209
|
+
const o = e.pattern.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
210
|
+
if ((yield t.adapter.stat(s)).kind !== "directory")
|
|
211
|
+
throw new T(R.BadRequest, "参数 path 必须是目录。");
|
|
212
|
+
const i = y(e.maxDepth, V, 1, P), c = y(e.maxResults, t.limits.maxSearchResults, 1, t.limits.maxSearchResults), n = [];
|
|
213
|
+
let a = !1;
|
|
214
|
+
try {
|
|
215
|
+
for (var l = I(Y(t, s, i)), d, m, u; d = !(m = yield l.next()).done; d = !1) {
|
|
216
|
+
const f = m.value;
|
|
217
|
+
if (j(o, f)) {
|
|
218
|
+
if (n.length >= c) {
|
|
219
|
+
a = !0;
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
n.push({
|
|
223
|
+
path: f.path,
|
|
224
|
+
size: f.size,
|
|
225
|
+
lastModified: f.lastModified
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
} catch (m) {
|
|
230
|
+
u = [m];
|
|
231
|
+
} finally {
|
|
232
|
+
try {
|
|
233
|
+
d && (m = l.return) && (yield m.call(l));
|
|
234
|
+
} finally {
|
|
235
|
+
if (u)
|
|
236
|
+
throw u[0];
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return {
|
|
240
|
+
data: {
|
|
241
|
+
matches: n
|
|
242
|
+
},
|
|
243
|
+
truncated: a || void 0
|
|
244
|
+
};
|
|
245
|
+
});
|
|
246
|
+
function C(e, t) {
|
|
247
|
+
if (e.length <= z)
|
|
248
|
+
return e;
|
|
249
|
+
const s = Math.max(0, Math.min(t - 100, e.length - z));
|
|
250
|
+
return e.slice(s, s + z);
|
|
251
|
+
}
|
|
252
|
+
const xe = (e, t) => x(void 0, null, function* () {
|
|
253
|
+
var u;
|
|
254
|
+
const s = M(e.path, {
|
|
255
|
+
allowRoot: !0
|
|
256
|
+
});
|
|
257
|
+
if (!s && !t.allowWorkspaceWideTextSearch)
|
|
258
|
+
throw new T(R.BadRequest, "不支持在整个工作区内搜索文本,请把 path 缩小到具体的子目录或文件。");
|
|
259
|
+
if (e.isRegex)
|
|
260
|
+
throw new T(R.NotImplemented, "暂不支持正则搜索,请使用普通文本搜索。");
|
|
261
|
+
if (!e.query)
|
|
262
|
+
throw new T(R.BadRequest, "参数 query 不能为空。");
|
|
263
|
+
const o = e.caseSensitive === !0, r = o ? e.query : e.query.toLowerCase(), i = y(e.contextLines, 0, 0, Z), c = y(e.maxResults, t.limits.maxSearchResults, 1, t.limits.maxSearchResults), n = yield t.adapter.stat(s);
|
|
264
|
+
let a;
|
|
265
|
+
n.kind === "file" ? (O(t, s, "search"), a = function() {
|
|
266
|
+
return A(this, null, function* () {
|
|
267
|
+
yield {
|
|
268
|
+
path: s,
|
|
269
|
+
relativePath: s,
|
|
270
|
+
name: n.name,
|
|
271
|
+
size: n.size
|
|
272
|
+
};
|
|
273
|
+
});
|
|
274
|
+
}()) : a = Y(t, s, P);
|
|
275
|
+
const l = [];
|
|
276
|
+
let d = 0, m = !1;
|
|
277
|
+
e:
|
|
278
|
+
try {
|
|
279
|
+
for (var f = I(a), p, b, g; p = !(b = yield f.next()).done; p = !1) {
|
|
280
|
+
const E = b.value;
|
|
281
|
+
if (e.glob && !j(e.glob, E) || ((u = E.size) != null ? u : 0) > $)
|
|
282
|
+
continue;
|
|
283
|
+
if (d >= ee) {
|
|
284
|
+
m = !0;
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
d++, d % 20 === 0 && (yield U()), X(t.signal);
|
|
288
|
+
const _ = yield F(yield t.adapter.readFile(E.path));
|
|
289
|
+
if (oe(_))
|
|
290
|
+
continue;
|
|
291
|
+
const w = new TextDecoder("utf-8").decode(_).split(/\r?\n/);
|
|
292
|
+
for (let h = 0; h < w.length; h++) {
|
|
293
|
+
const B = (o ? w[h] : w[h].toLowerCase()).indexOf(r);
|
|
294
|
+
if (B < 0)
|
|
295
|
+
continue;
|
|
296
|
+
if (l.length >= c) {
|
|
297
|
+
m = !0;
|
|
298
|
+
break e;
|
|
299
|
+
}
|
|
300
|
+
const v = {
|
|
301
|
+
path: E.path,
|
|
302
|
+
line: h + 1,
|
|
303
|
+
column: B + 1,
|
|
304
|
+
text: C(w[h], B)
|
|
305
|
+
};
|
|
306
|
+
i && (v.before = w.slice(Math.max(0, h - i), h).map((D) => C(D, 0)), v.after = w.slice(h + 1, h + 1 + i).map((D) => C(D, 0))), l.push(v);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
} catch (b) {
|
|
310
|
+
g = [b];
|
|
311
|
+
} finally {
|
|
312
|
+
try {
|
|
313
|
+
p && (b = f.return) && (yield b.call(f));
|
|
314
|
+
} finally {
|
|
315
|
+
if (g)
|
|
316
|
+
throw g[0];
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return {
|
|
320
|
+
data: {
|
|
321
|
+
matches: l,
|
|
322
|
+
filesScanned: d
|
|
323
|
+
},
|
|
324
|
+
truncated: m || void 0
|
|
325
|
+
};
|
|
326
|
+
});
|
|
327
|
+
export {
|
|
328
|
+
Ee as listDirectory,
|
|
329
|
+
Te as readFile,
|
|
330
|
+
_e as searchFiles,
|
|
331
|
+
xe as searchText,
|
|
332
|
+
Re as statFile
|
|
333
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
var i = (t, e, r) => new Promise((n, s) => {
|
|
2
|
+
var l = (o) => {
|
|
3
|
+
try {
|
|
4
|
+
c(r.next(o));
|
|
5
|
+
} catch (f) {
|
|
6
|
+
s(f);
|
|
7
|
+
}
|
|
8
|
+
}, w = (o) => {
|
|
9
|
+
try {
|
|
10
|
+
c(r.throw(o));
|
|
11
|
+
} catch (f) {
|
|
12
|
+
s(f);
|
|
13
|
+
}
|
|
14
|
+
}, c = (o) => o.done ? n(o.value) : Promise.resolve(o.value).then(l, w);
|
|
15
|
+
c((r = r.apply(t, e)).next());
|
|
16
|
+
});
|
|
17
|
+
import { BINARY_SNIFF_BYTES as d } from "../constants.mjs";
|
|
18
|
+
import { SensitiveFilePolicy as h } from "../security/sensitiveFiles.mjs";
|
|
19
|
+
import { ToolError as u, ToolCode as a, toToolError as y } from "../errors.mjs";
|
|
20
|
+
function x(t, e, r) {
|
|
21
|
+
const n = t.sensitive.match(e, r);
|
|
22
|
+
if (n)
|
|
23
|
+
throw new u(a.Forbidden, h.reasonOf(n), {
|
|
24
|
+
reason: "sensitive_file",
|
|
25
|
+
ruleId: n.id
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function L(t, e) {
|
|
29
|
+
return i(this, null, function* () {
|
|
30
|
+
try {
|
|
31
|
+
return yield t.stat(e);
|
|
32
|
+
} catch (r) {
|
|
33
|
+
if (y(r).code === a.NotFound)
|
|
34
|
+
return null;
|
|
35
|
+
throw r;
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function $(t, e) {
|
|
40
|
+
return i(this, null, function* () {
|
|
41
|
+
const r = yield t.stat(e);
|
|
42
|
+
if (r.kind !== "file")
|
|
43
|
+
throw new u(a.BadRequest, "目标是目录,不是文件。");
|
|
44
|
+
return r;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function A(t) {
|
|
48
|
+
return i(this, null, function* () {
|
|
49
|
+
const e = yield crypto.subtle.digest("SHA-256", t);
|
|
50
|
+
return `sha256:${Array.from(new Uint8Array(e)).map((n) => n.toString(16).padStart(2, "0")).join("")}`;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
function m(t) {
|
|
54
|
+
return i(this, null, function* () {
|
|
55
|
+
return new Uint8Array(yield t.arrayBuffer());
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
function B(t) {
|
|
59
|
+
const e = Math.min(t.byteLength, d);
|
|
60
|
+
for (let r = 0; r < e; r++)
|
|
61
|
+
if (t[r] === 0)
|
|
62
|
+
return !0;
|
|
63
|
+
return !1;
|
|
64
|
+
}
|
|
65
|
+
function N(t) {
|
|
66
|
+
return i(this, null, function* () {
|
|
67
|
+
return B(yield m(t.slice(0, d)));
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function U(t) {
|
|
71
|
+
return t[0] === 239 && t[1] === 187 && t[2] === 191;
|
|
72
|
+
}
|
|
73
|
+
function v(t) {
|
|
74
|
+
try {
|
|
75
|
+
return new TextDecoder("utf-8", {
|
|
76
|
+
fatal: !0
|
|
77
|
+
}).decode(t);
|
|
78
|
+
} catch (e) {
|
|
79
|
+
throw new u(a.BadRequest, "文件不是 UTF-8 编码,暂不支持修改。");
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function E(t) {
|
|
83
|
+
return new TextEncoder().encode(t).byteLength;
|
|
84
|
+
}
|
|
85
|
+
function k() {
|
|
86
|
+
return new Promise((t) => setTimeout(t, 0));
|
|
87
|
+
}
|
|
88
|
+
function T(t) {
|
|
89
|
+
return t >= 1024 * 1024 ? `${(t / 1024 / 1024).toFixed(1)} MB` : t >= 1024 ? `${(t / 1024).toFixed(1)} KB` : `${t} B`;
|
|
90
|
+
}
|
|
91
|
+
function q(t, e = "文件") {
|
|
92
|
+
return new u(a.TooLarge, `${e}超过大小上限 ${T(t)}。`);
|
|
93
|
+
}
|
|
94
|
+
export {
|
|
95
|
+
x as assertNotSensitive,
|
|
96
|
+
N as blobLooksBinary,
|
|
97
|
+
v as decodeUtf8Strict,
|
|
98
|
+
T as describeSize,
|
|
99
|
+
U as hasUtf8Bom,
|
|
100
|
+
B as looksBinary,
|
|
101
|
+
m as readBytes,
|
|
102
|
+
$ as requireFile,
|
|
103
|
+
A as sha256,
|
|
104
|
+
L as statOrNull,
|
|
105
|
+
q as tooLarge,
|
|
106
|
+
E as utf8ByteLength,
|
|
107
|
+
k as yieldToMain
|
|
108
|
+
};
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
var b = (o, e, a) => new Promise((n, l) => {
|
|
2
|
+
var r = (t) => {
|
|
3
|
+
try {
|
|
4
|
+
i(a.next(t));
|
|
5
|
+
} catch (d) {
|
|
6
|
+
l(d);
|
|
7
|
+
}
|
|
8
|
+
}, s = (t) => {
|
|
9
|
+
try {
|
|
10
|
+
i(a.throw(t));
|
|
11
|
+
} catch (d) {
|
|
12
|
+
l(d);
|
|
13
|
+
}
|
|
14
|
+
}, i = (t) => t.done ? n(t.value) : Promise.resolve(t.value).then(r, s);
|
|
15
|
+
i((a = a.apply(o, e)).next());
|
|
16
|
+
}), B = function(o, e) {
|
|
17
|
+
this[0] = o, this[1] = e;
|
|
18
|
+
}, I = (o, e, a) => {
|
|
19
|
+
var n = (s, i, t, d) => {
|
|
20
|
+
try {
|
|
21
|
+
var h = a[s](i), p = (i = h.value) instanceof B, y = h.done;
|
|
22
|
+
Promise.resolve(p ? i[0] : i).then((c) => p ? n(s === "return" ? s : "next", i[1] ? { done: c.done, value: c.value } : c, t, d) : t({ value: c, done: y })).catch((c) => n("throw", c, t, d));
|
|
23
|
+
} catch (c) {
|
|
24
|
+
d(c);
|
|
25
|
+
}
|
|
26
|
+
}, l = (s) => r[s] = (i) => new Promise((t, d) => n(s, i, t, d)), r = {};
|
|
27
|
+
return a = a.apply(o, e), r[Symbol.asyncIterator] = () => r, l("next"), l("throw"), l("return"), r;
|
|
28
|
+
};
|
|
29
|
+
import { ToolError as w, ToolCode as f, throwIfAborted as v } from "../errors.mjs";
|
|
30
|
+
import { isDownloadUrlAllowedByList as q } from "../security/downloadUrlPolicy.mjs";
|
|
31
|
+
import { basename as L } from "../security/glob.mjs";
|
|
32
|
+
import { normalizeWorkspacePath as N } from "../security/pathPolicy.mjs";
|
|
33
|
+
import { assertNotSensitive as R, requireFile as U, tooLarge as F, statOrNull as k, sha256 as z, readBytes as C } from "./runtime.mjs";
|
|
34
|
+
function A() {
|
|
35
|
+
return new w(f.Forbidden, "下载地址不在允许范围内:只允许 https 协议且域名在白名单中的地址。", {
|
|
36
|
+
reason: "url_not_allowed"
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
const $ = (o, e) => b(void 0, null, function* () {
|
|
40
|
+
var p, y;
|
|
41
|
+
const a = N(o.path);
|
|
42
|
+
if (((p = o.target) != null ? p : "session") !== "session")
|
|
43
|
+
throw new w(f.NotImplemented, "目前只支持上传到当前会话(target: session)。");
|
|
44
|
+
R(e, a, "read");
|
|
45
|
+
const l = yield U(e.adapter, a), r = (y = l.size) != null ? y : 0;
|
|
46
|
+
if (r > e.limits.maxTransferBytes)
|
|
47
|
+
throw F(e.limits.maxTransferBytes);
|
|
48
|
+
const s = L(a);
|
|
49
|
+
yield e.requestApproval(a, {
|
|
50
|
+
type: "upload",
|
|
51
|
+
name: s,
|
|
52
|
+
size: r,
|
|
53
|
+
target: "session"
|
|
54
|
+
}), e.progress({
|
|
55
|
+
stage: "reading",
|
|
56
|
+
loaded: 0,
|
|
57
|
+
total: r,
|
|
58
|
+
path: a
|
|
59
|
+
});
|
|
60
|
+
const i = yield e.adapter.readFile(a);
|
|
61
|
+
v(e.signal);
|
|
62
|
+
const t = new File([i], s, {
|
|
63
|
+
type: o.mimeHint || i.type || "application/octet-stream",
|
|
64
|
+
lastModified: l.lastModified
|
|
65
|
+
}), {
|
|
66
|
+
fileId: d,
|
|
67
|
+
url: h
|
|
68
|
+
} = yield e.transfer.upload(t, e.context, ({
|
|
69
|
+
loaded: c,
|
|
70
|
+
total: u
|
|
71
|
+
}) => e.progress({
|
|
72
|
+
stage: "uploading",
|
|
73
|
+
loaded: c,
|
|
74
|
+
total: u,
|
|
75
|
+
path: a
|
|
76
|
+
}));
|
|
77
|
+
return v(e.signal), e.progress({
|
|
78
|
+
stage: "done",
|
|
79
|
+
loaded: r,
|
|
80
|
+
total: r,
|
|
81
|
+
path: a
|
|
82
|
+
}), {
|
|
83
|
+
data: {
|
|
84
|
+
fileId: d,
|
|
85
|
+
name: s,
|
|
86
|
+
size: r,
|
|
87
|
+
url: h
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
function P(o) {
|
|
92
|
+
const e = o;
|
|
93
|
+
if (!e || typeof e != "object")
|
|
94
|
+
throw new w(f.BadRequest, "缺少参数 source。");
|
|
95
|
+
if (e.type === "sessionFile" || e.type === "platformFile") {
|
|
96
|
+
if (typeof e.fileId != "string" || !e.fileId)
|
|
97
|
+
throw new w(f.BadRequest, "source.fileId 必须是非空字符串。");
|
|
98
|
+
return {
|
|
99
|
+
type: e.type,
|
|
100
|
+
fileId: e.fileId
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
if (e.type === "url") {
|
|
104
|
+
if (typeof e.url != "string" || !e.url)
|
|
105
|
+
throw new w(f.BadRequest, "source.url 必须是非空字符串。");
|
|
106
|
+
return {
|
|
107
|
+
type: "url",
|
|
108
|
+
url: e.url
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
throw new w(f.BadRequest, "source.type 必须是 sessionFile、platformFile 或 url 之一。");
|
|
112
|
+
}
|
|
113
|
+
function E(o) {
|
|
114
|
+
return o.type === "sessionFile" ? "会话文件" : o.type === "platformFile" ? "平台文件" : new URL(o.url).hostname;
|
|
115
|
+
}
|
|
116
|
+
function D(o, e, a, n, l) {
|
|
117
|
+
return I(this, null, function* () {
|
|
118
|
+
const r = o.getReader();
|
|
119
|
+
let s = 0;
|
|
120
|
+
try {
|
|
121
|
+
for (; ; ) {
|
|
122
|
+
v(e.signal);
|
|
123
|
+
const {
|
|
124
|
+
done: i,
|
|
125
|
+
value: t
|
|
126
|
+
} = yield new B(r.read());
|
|
127
|
+
if (i)
|
|
128
|
+
break;
|
|
129
|
+
if (s += t.byteLength, s > e.limits.maxTransferBytes)
|
|
130
|
+
throw F(e.limits.maxTransferBytes, "下载内容");
|
|
131
|
+
l.push(t), e.progress({
|
|
132
|
+
stage: "downloading",
|
|
133
|
+
loaded: s,
|
|
134
|
+
total: n,
|
|
135
|
+
path: a
|
|
136
|
+
}), yield t;
|
|
137
|
+
}
|
|
138
|
+
} finally {
|
|
139
|
+
r.cancel().catch(() => {
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
const G = (o, e) => b(void 0, null, function* () {
|
|
145
|
+
var x, T, m;
|
|
146
|
+
const a = N(o.destPath, {
|
|
147
|
+
field: "destPath"
|
|
148
|
+
}), n = P(o.source);
|
|
149
|
+
if (n.type === "url" && !q(n.url, e.downloadUrlAllowlist))
|
|
150
|
+
throw A();
|
|
151
|
+
R(e, a, "write");
|
|
152
|
+
const l = yield k(e.adapter, a);
|
|
153
|
+
if ((l == null ? void 0 : l.kind) === "directory")
|
|
154
|
+
throw new w(f.BadRequest, "目标是目录,不能写入文件。");
|
|
155
|
+
if (l && !o.overwrite)
|
|
156
|
+
throw new w(f.Conflict, "目标文件已存在。如需覆盖,请设置 overwrite: true。");
|
|
157
|
+
const r = () => b(void 0, null, function* () {
|
|
158
|
+
if (!l || !o.expectedHash)
|
|
159
|
+
return;
|
|
160
|
+
const g = yield z(yield C(yield e.adapter.readFile(a)));
|
|
161
|
+
if (g !== o.expectedHash)
|
|
162
|
+
throw new w(f.Conflict, "expectedHash 与目标文件当前内容不一致。", {
|
|
163
|
+
currentHash: g
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
yield r();
|
|
167
|
+
const s = n.type === "url" ? {
|
|
168
|
+
url: n.url
|
|
169
|
+
} : yield e.transfer.resolveDownload(n, e.context);
|
|
170
|
+
if (s.size !== void 0 && s.size > e.limits.maxTransferBytes)
|
|
171
|
+
throw F(e.limits.maxTransferBytes);
|
|
172
|
+
const i = {
|
|
173
|
+
type: "download",
|
|
174
|
+
source: {
|
|
175
|
+
type: n.type,
|
|
176
|
+
label: E(n)
|
|
177
|
+
},
|
|
178
|
+
name: (x = s.name) != null ? x : L(a),
|
|
179
|
+
size: s.size,
|
|
180
|
+
overwrite: !!l
|
|
181
|
+
};
|
|
182
|
+
yield e.requestApproval(a, i), yield r();
|
|
183
|
+
let t;
|
|
184
|
+
try {
|
|
185
|
+
t = yield e.fetch(s.url, {
|
|
186
|
+
headers: s.headers,
|
|
187
|
+
credentials: "omit",
|
|
188
|
+
redirect: "follow",
|
|
189
|
+
signal: e.signal
|
|
190
|
+
});
|
|
191
|
+
} catch (g) {
|
|
192
|
+
throw v(e.signal), new w(f.Internal, "下载失败,无法连接到文件地址。");
|
|
193
|
+
}
|
|
194
|
+
if (n.type === "url" && t.url && !q(t.url, e.downloadUrlAllowlist))
|
|
195
|
+
throw (T = t.body) == null || T.cancel().catch(() => {
|
|
196
|
+
}), A();
|
|
197
|
+
if (!t.ok || !t.body)
|
|
198
|
+
throw (m = t.body) == null || m.cancel().catch(() => {
|
|
199
|
+
}), new w(t.status === 404 ? f.NotFound : f.Internal, `下载失败(HTTP ${t.status})。`);
|
|
200
|
+
const d = Number(t.headers.get("content-length")), h = Number.isFinite(d) && d > 0 ? d : void 0;
|
|
201
|
+
if (h !== void 0 && h > e.limits.maxTransferBytes)
|
|
202
|
+
throw t.body.cancel().catch(() => {
|
|
203
|
+
}), F(e.limits.maxTransferBytes);
|
|
204
|
+
const p = [];
|
|
205
|
+
yield e.adapter.writeFile(a, D(t.body, e, a, h, p), {
|
|
206
|
+
signal: e.signal
|
|
207
|
+
});
|
|
208
|
+
const y = p.reduce((g, H) => g + H.byteLength, 0), c = new Uint8Array(y);
|
|
209
|
+
let u = 0;
|
|
210
|
+
return p.forEach((g) => {
|
|
211
|
+
c.set(g, u), u += g.byteLength;
|
|
212
|
+
}), e.progress({
|
|
213
|
+
stage: "done",
|
|
214
|
+
loaded: y,
|
|
215
|
+
total: y,
|
|
216
|
+
path: a
|
|
217
|
+
}), {
|
|
218
|
+
data: {
|
|
219
|
+
path: a,
|
|
220
|
+
size: y,
|
|
221
|
+
hash: yield z(c)
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
});
|
|
225
|
+
export {
|
|
226
|
+
G as downloadFile,
|
|
227
|
+
$ as uploadFile
|
|
228
|
+
};
|