@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.
Files changed (96) hide show
  1. package/README.md +572 -98
  2. package/dist/es/AgentSession.mjs +230 -165
  3. package/dist/es/BotClient.mjs +186 -136
  4. package/dist/es/Config.mjs +89 -26
  5. package/dist/es/Session.mjs +12 -0
  6. package/dist/es/api/index.mjs +42 -33
  7. package/dist/es/builtinTools/browserRuntime/BrowserCommandRunner.mjs +201 -0
  8. package/dist/es/builtinTools/browserRuntime/PythonRunner.mjs +356 -0
  9. package/dist/es/builtinTools/browserRuntime/WorkspaceBashFs.mjs +350 -0
  10. package/dist/es/builtinTools/browserRuntime/assets.mjs +9 -0
  11. package/dist/es/builtinTools/browserRuntime/loadBash.mjs +17 -0
  12. package/dist/es/builtinTools/browserRuntime/pyodideRunner.py.mjs +96 -0
  13. package/dist/es/builtinTools/browserRuntime/pyodideWorker.mjs +242 -0
  14. package/dist/es/builtinTools/command.mjs +56 -0
  15. package/dist/es/builtinTools/constants.mjs +10 -0
  16. package/dist/es/builtinTools/createBuiltinToolsPlugin.mjs +236 -0
  17. package/dist/es/builtinTools/overview.mjs +77 -0
  18. package/dist/es/builtinTools/paths.mjs +63 -0
  19. package/dist/es/builtinTools/schemas.mjs +216 -0
  20. package/dist/es/builtinTools/tools.mjs +471 -0
  21. package/dist/es/index.mjs +69 -9
  22. package/dist/es/localFiles/adapters/FileSystemAccessAdapter.mjs +264 -0
  23. package/dist/es/localFiles/adapters/HostBridgeAdapter.mjs +233 -0
  24. package/dist/es/localFiles/adapters/MemoryWorkspaceAdapter.mjs +197 -0
  25. package/dist/es/localFiles/adapters/WorkspaceFileAdapter.mjs +54 -0
  26. package/dist/es/localFiles/adapters/fsaTypes.mjs +9 -0
  27. package/dist/es/localFiles/constants.mjs +47 -0
  28. package/dist/es/localFiles/createLocalFilesPlugin.mjs +255 -0
  29. package/dist/es/localFiles/errors.mjs +57 -0
  30. package/dist/es/localFiles/host/connectHostBridge.mjs +54 -0
  31. package/dist/es/localFiles/host/protocol.mjs +27 -0
  32. package/dist/es/localFiles/limits.mjs +22 -0
  33. package/dist/es/localFiles/schemas.mjs +312 -0
  34. package/dist/es/localFiles/security/downloadUrlPolicy.mjs +39 -0
  35. package/dist/es/localFiles/security/glob.mjs +28 -0
  36. package/dist/es/localFiles/security/pathPolicy.mjs +59 -0
  37. package/dist/es/localFiles/security/sensitiveFiles.mjs +115 -0
  38. package/dist/es/localFiles/tools/readTools.mjs +333 -0
  39. package/dist/es/localFiles/tools/runtime.mjs +108 -0
  40. package/dist/es/localFiles/tools/transferTools.mjs +228 -0
  41. package/dist/es/localFiles/tools/writeTools.mjs +173 -0
  42. package/dist/es/localFiles/transfer/SessionFileTransfer.mjs +111 -0
  43. package/dist/es/localFiles/validate.mjs +66 -0
  44. package/dist/es/localFiles/workspace/LocalWorkspace.mjs +358 -0
  45. package/dist/es/localFiles/workspace/handleStore.mjs +79 -0
  46. package/dist/es/localFiles/workspace/watchDirectory.mjs +38 -0
  47. package/dist/es/package.json.mjs +38 -29
  48. package/dist/lib/index.js +373 -5
  49. package/dist/src/AgentSession.d.ts +9 -0
  50. package/dist/src/BotClient.d.ts +12 -2
  51. package/dist/src/Config.d.ts +22 -0
  52. package/dist/src/Session.d.ts +5 -1
  53. package/dist/src/api/index.d.ts +3 -1
  54. package/dist/src/builtinTools/browserRuntime/BrowserCommandRunner.d.ts +26 -0
  55. package/dist/src/builtinTools/browserRuntime/PythonRunner.d.ts +67 -0
  56. package/dist/src/builtinTools/browserRuntime/WorkspaceBashFs.d.ts +51 -0
  57. package/dist/src/builtinTools/browserRuntime/assets.d.ts +13 -0
  58. package/dist/src/builtinTools/browserRuntime/loadBash.d.ts +3 -0
  59. package/dist/src/builtinTools/browserRuntime/pyodideWorker.d.ts +44 -0
  60. package/dist/src/builtinTools/command.d.ts +26 -0
  61. package/dist/src/builtinTools/constants.d.ts +17 -0
  62. package/dist/src/builtinTools/createBuiltinToolsPlugin.d.ts +11 -0
  63. package/dist/src/builtinTools/overview.d.ts +5 -0
  64. package/dist/src/builtinTools/paths.d.ts +15 -0
  65. package/dist/src/builtinTools/schemas.d.ts +3 -0
  66. package/dist/src/builtinTools/tools.d.ts +60 -0
  67. package/dist/src/index.d.ts +4 -2
  68. package/dist/src/localFiles/adapters/FileSystemAccessAdapter.d.ts +20 -0
  69. package/dist/src/localFiles/adapters/HostBridgeAdapter.d.ts +43 -0
  70. package/dist/src/localFiles/adapters/MemoryWorkspaceAdapter.d.ts +21 -0
  71. package/dist/src/localFiles/adapters/WorkspaceFileAdapter.d.ts +40 -0
  72. package/dist/src/localFiles/adapters/fsaTypes.d.ts +41 -0
  73. package/dist/src/localFiles/constants.d.ts +51 -0
  74. package/dist/src/localFiles/createLocalFilesPlugin.d.ts +11 -0
  75. package/dist/src/localFiles/createLocalPythonPlugin.d.ts +12 -0
  76. package/dist/src/localFiles/errors.d.ts +34 -0
  77. package/dist/src/localFiles/host/connectHostBridge.d.ts +6 -0
  78. package/dist/src/localFiles/host/protocol.d.ts +46 -0
  79. package/dist/src/localFiles/index.d.ts +22 -0
  80. package/dist/src/localFiles/limits.d.ts +3 -0
  81. package/dist/src/localFiles/schemas.d.ts +29 -0
  82. package/dist/src/localFiles/security/downloadUrlPolicy.d.ts +4 -0
  83. package/dist/src/localFiles/security/glob.d.ts +3 -0
  84. package/dist/src/localFiles/security/pathPolicy.d.ts +14 -0
  85. package/dist/src/localFiles/security/sensitiveFiles.d.ts +23 -0
  86. package/dist/src/localFiles/tools/readTools.d.ts +7 -0
  87. package/dist/src/localFiles/tools/runtime.d.ts +43 -0
  88. package/dist/src/localFiles/tools/transferTools.d.ts +4 -0
  89. package/dist/src/localFiles/tools/writeTools.d.ts +4 -0
  90. package/dist/src/localFiles/transfer/SessionFileTransfer.d.ts +40 -0
  91. package/dist/src/localFiles/types.d.ts +319 -0
  92. package/dist/src/localFiles/validate.d.ts +2 -0
  93. package/dist/src/localFiles/workspace/LocalWorkspace.d.ts +111 -0
  94. package/dist/src/localFiles/workspace/handleStore.d.ts +11 -0
  95. package/dist/src/localFiles/workspace/watchDirectory.d.ts +7 -0
  96. 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
+ };