@glodon-aiot/bot-client-sdk 3.25.1-alpha.7 → 3.26.0-alpha.4

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 (70) hide show
  1. package/README.md +543 -98
  2. package/dist/es/AgentSession.mjs +230 -165
  3. package/dist/es/BotClient.mjs +186 -136
  4. package/dist/es/Config.mjs +111 -26
  5. package/dist/es/Session.mjs +12 -0
  6. package/dist/es/api/index.mjs +42 -33
  7. package/dist/es/index.mjs +68 -9
  8. package/dist/es/localFiles/adapters/FileSystemAccessAdapter.mjs +174 -0
  9. package/dist/es/localFiles/adapters/HostBridgeAdapter.mjs +172 -0
  10. package/dist/es/localFiles/adapters/MemoryWorkspaceAdapter.mjs +162 -0
  11. package/dist/es/localFiles/adapters/WorkspaceFileAdapter.mjs +50 -0
  12. package/dist/es/localFiles/adapters/fsaTypes.mjs +9 -0
  13. package/dist/es/localFiles/constants.mjs +47 -0
  14. package/dist/es/localFiles/createLocalFilesPlugin.mjs +255 -0
  15. package/dist/es/localFiles/createLocalPythonPlugin.mjs +196 -0
  16. package/dist/es/localFiles/errors.mjs +57 -0
  17. package/dist/es/localFiles/host/connectHostBridge.mjs +50 -0
  18. package/dist/es/localFiles/host/protocol.mjs +26 -0
  19. package/dist/es/localFiles/limits.mjs +22 -0
  20. package/dist/es/localFiles/schemas.mjs +327 -0
  21. package/dist/es/localFiles/security/downloadUrlPolicy.mjs +39 -0
  22. package/dist/es/localFiles/security/glob.mjs +28 -0
  23. package/dist/es/localFiles/security/pathPolicy.mjs +59 -0
  24. package/dist/es/localFiles/security/sensitiveFiles.mjs +115 -0
  25. package/dist/es/localFiles/tools/readTools.mjs +333 -0
  26. package/dist/es/localFiles/tools/runtime.mjs +108 -0
  27. package/dist/es/localFiles/tools/transferTools.mjs +228 -0
  28. package/dist/es/localFiles/tools/writeTools.mjs +173 -0
  29. package/dist/es/localFiles/transfer/SessionFileTransfer.mjs +111 -0
  30. package/dist/es/localFiles/validate.mjs +66 -0
  31. package/dist/es/localFiles/workspace/LocalWorkspace.mjs +339 -0
  32. package/dist/es/localFiles/workspace/handleStore.mjs +79 -0
  33. package/dist/es/localFiles/workspace/watchDirectory.mjs +38 -0
  34. package/dist/es/package.json.mjs +7 -4
  35. package/dist/lib/index.js +9 -4
  36. package/dist/src/AgentSession.d.ts +9 -0
  37. package/dist/src/BotClient.d.ts +12 -2
  38. package/dist/src/Config.d.ts +22 -0
  39. package/dist/src/Session.d.ts +5 -1
  40. package/dist/src/api/index.d.ts +3 -1
  41. package/dist/src/index.d.ts +4 -2
  42. package/dist/src/localFiles/adapters/FileSystemAccessAdapter.d.ts +17 -0
  43. package/dist/src/localFiles/adapters/HostBridgeAdapter.d.ts +24 -0
  44. package/dist/src/localFiles/adapters/MemoryWorkspaceAdapter.d.ts +18 -0
  45. package/dist/src/localFiles/adapters/WorkspaceFileAdapter.d.ts +26 -0
  46. package/dist/src/localFiles/adapters/fsaTypes.d.ts +39 -0
  47. package/dist/src/localFiles/constants.d.ts +50 -0
  48. package/dist/src/localFiles/createLocalFilesPlugin.d.ts +11 -0
  49. package/dist/src/localFiles/createLocalPythonPlugin.d.ts +12 -0
  50. package/dist/src/localFiles/errors.d.ts +34 -0
  51. package/dist/src/localFiles/host/connectHostBridge.d.ts +6 -0
  52. package/dist/src/localFiles/host/protocol.d.ts +33 -0
  53. package/dist/src/localFiles/index.d.ts +21 -0
  54. package/dist/src/localFiles/limits.d.ts +3 -0
  55. package/dist/src/localFiles/schemas.d.ts +30 -0
  56. package/dist/src/localFiles/security/downloadUrlPolicy.d.ts +4 -0
  57. package/dist/src/localFiles/security/glob.d.ts +3 -0
  58. package/dist/src/localFiles/security/pathPolicy.d.ts +14 -0
  59. package/dist/src/localFiles/security/sensitiveFiles.d.ts +23 -0
  60. package/dist/src/localFiles/tools/readTools.d.ts +7 -0
  61. package/dist/src/localFiles/tools/runtime.d.ts +43 -0
  62. package/dist/src/localFiles/tools/transferTools.d.ts +4 -0
  63. package/dist/src/localFiles/tools/writeTools.d.ts +4 -0
  64. package/dist/src/localFiles/transfer/SessionFileTransfer.d.ts +40 -0
  65. package/dist/src/localFiles/types.d.ts +306 -0
  66. package/dist/src/localFiles/validate.d.ts +2 -0
  67. package/dist/src/localFiles/workspace/LocalWorkspace.d.ts +99 -0
  68. package/dist/src/localFiles/workspace/handleStore.d.ts +11 -0
  69. package/dist/src/localFiles/workspace/watchDirectory.d.ts +7 -0
  70. package/package.json +7 -4
@@ -0,0 +1,173 @@
1
+ var C = Object.defineProperty, $ = Object.defineProperties;
2
+ var k = Object.getOwnPropertyDescriptors;
3
+ var q = Object.getOwnPropertySymbols;
4
+ var v = Object.prototype.hasOwnProperty, z = Object.prototype.propertyIsEnumerable;
5
+ var A = (t, e, a) => e in t ? C(t, e, { enumerable: !0, configurable: !0, writable: !0, value: a }) : t[e] = a, H = (t, e) => {
6
+ for (var a in e || (e = {}))
7
+ v.call(e, a) && A(t, a, e[a]);
8
+ if (q)
9
+ for (var a of q(e))
10
+ z.call(e, a) && A(t, a, e[a]);
11
+ return t;
12
+ }, W = (t, e) => $(t, k(e));
13
+ var h = (t, e, a) => new Promise((r, n) => {
14
+ var s = (o) => {
15
+ try {
16
+ d(a.next(o));
17
+ } catch (c) {
18
+ n(c);
19
+ }
20
+ }, f = (o) => {
21
+ try {
22
+ d(a.throw(o));
23
+ } catch (c) {
24
+ n(c);
25
+ }
26
+ }, d = (o) => o.done ? r(o.value) : Promise.resolve(o.value).then(s, f);
27
+ d((a = a.apply(t, e)).next());
28
+ });
29
+ import { ToolError as l, ToolCode as w } from "../errors.mjs";
30
+ import { normalizeWorkspacePath as F, parentPath as N } from "../security/pathPolicy.mjs";
31
+ import { assertNotSensitive as D, hasUtf8Bom as P, decodeUtf8Strict as S, tooLarge as B, statOrNull as T, requireFile as _, readBytes as j, sha256 as O } from "./runtime.mjs";
32
+ const u = new Uint8Array([239, 187, 191]);
33
+ function y(t, e) {
34
+ return new l(w.Conflict, e, {
35
+ currentHash: t
36
+ });
37
+ }
38
+ function b(t, e) {
39
+ return h(this, null, function* () {
40
+ var n;
41
+ if (((n = (yield _(t.adapter, e)).size) != null ? n : 0) > t.limits.maxWriteBytes)
42
+ throw B(t.limits.maxWriteBytes, "目标文件");
43
+ const r = yield j(yield t.adapter.readFile(e));
44
+ return {
45
+ bytes: r,
46
+ hash: yield O(r)
47
+ };
48
+ });
49
+ }
50
+ function R(t, e, a) {
51
+ return h(this, null, function* () {
52
+ const {
53
+ hash: r
54
+ } = yield b(t, e);
55
+ if (r !== a)
56
+ throw y(r, "文件在确认期间已被修改,本次写入已取消。请重新读取后再修改。");
57
+ });
58
+ }
59
+ function m(t, e) {
60
+ const a = new TextEncoder().encode(t);
61
+ if (!e)
62
+ return a;
63
+ const r = new Uint8Array(u.byteLength + a.byteLength);
64
+ return r.set(u, 0), r.set(a, u.byteLength), r;
65
+ }
66
+ function M(t, e) {
67
+ let a = 0, r = t.indexOf(e);
68
+ for (; r >= 0; )
69
+ a++, r = t.indexOf(e, r + e.length);
70
+ return a;
71
+ }
72
+ function E(t, e) {
73
+ return !e || t.includes(`\r
74
+ `) ? t : t.replace(/\n/g, `\r
75
+ `);
76
+ }
77
+ function U(t, e, a, r = !1) {
78
+ return h(this, null, function* () {
79
+ return t.progress({
80
+ stage: "writing",
81
+ loaded: 0,
82
+ total: a.byteLength,
83
+ path: e
84
+ }), yield t.adapter.writeFile(e, a, {
85
+ createDirectories: r,
86
+ signal: t.signal
87
+ }), {
88
+ path: e,
89
+ hash: yield O(a),
90
+ size: a.byteLength
91
+ };
92
+ });
93
+ }
94
+ const Q = (t, e) => h(void 0, null, function* () {
95
+ const a = F(t.path);
96
+ if (D(e, a, "write"), !t.edits.length)
97
+ throw new l(w.BadRequest, "参数 edits 不能为空。");
98
+ const {
99
+ bytes: r,
100
+ hash: n
101
+ } = yield b(e, a);
102
+ if (n !== t.expectedHash)
103
+ throw y(n, "expectedHash 与文件当前内容不一致,请重新读取文件后再修改。");
104
+ const s = P(r), f = S(s ? r.subarray(3) : r), d = f.includes(`\r
105
+ `);
106
+ let o = f;
107
+ t.edits.forEach((i, p) => {
108
+ if (typeof (i == null ? void 0 : i.oldText) != "string" || !i.oldText || typeof i.newText != "string")
109
+ throw new l(w.BadRequest, `第 ${p + 1} 条修改无效:oldText 必须是非空字符串,newText 必须是字符串。`);
110
+ const x = E(i.oldText, d), L = E(i.newText, d), g = M(o, x);
111
+ if (g === 0)
112
+ throw new l(w.Conflict, `第 ${p + 1} 条修改的 oldText 在文件中不存在,请重新读取文件确认当前内容。`);
113
+ if (g > 1 && !i.replaceAll)
114
+ throw new l(w.BadRequest, `第 ${p + 1} 条修改的 oldText 在文件中出现了 ${g} 次,请补充上下文使其唯一,或设置 replaceAll。`);
115
+ o = i.replaceAll ? o.split(x).join(L) : o.replace(x, () => L);
116
+ });
117
+ const c = m(o, s);
118
+ if (c.byteLength > e.limits.maxWriteBytes)
119
+ throw B(e.limits.maxWriteBytes, "修改后的内容");
120
+ return yield e.requestApproval(a, {
121
+ type: "text",
122
+ before: f,
123
+ after: o,
124
+ created: !1
125
+ }), yield R(e, a, n), {
126
+ data: yield U(e, a, c)
127
+ };
128
+ }), V = (t, e) => h(void 0, null, function* () {
129
+ const a = F(t.path);
130
+ D(e, a, "write");
131
+ const r = yield T(e.adapter, a);
132
+ if ((r == null ? void 0 : r.kind) === "directory")
133
+ throw new l(w.BadRequest, "目标是目录,不能写入文件。");
134
+ let n, s;
135
+ if (r) {
136
+ const o = yield b(e, a);
137
+ if (s = o.hash, !t.expectedHash)
138
+ throw y(s, "目标文件已存在,覆盖前需要提供 expectedHash(可通过 read_file 或 stat_file 获取)。");
139
+ if (t.expectedHash !== s)
140
+ throw y(s, "expectedHash 与文件当前内容不一致,请重新读取文件后再写入。");
141
+ n = new TextDecoder("utf-8").decode(o.bytes);
142
+ } else if (!t.createDirectories) {
143
+ const o = N(a), c = o ? yield T(e.adapter, o) : {
144
+ kind: "directory"
145
+ };
146
+ if (!c)
147
+ throw new l(w.NotFound, "父目录不存在,可设置 createDirectories 自动创建。");
148
+ if (c.kind !== "directory")
149
+ throw new l(w.BadRequest, "父路径不是目录。");
150
+ }
151
+ const f = new TextEncoder().encode(t.content);
152
+ if (f.byteLength > e.limits.maxWriteBytes)
153
+ throw B(e.limits.maxWriteBytes, "写入内容");
154
+ if (yield e.requestApproval(a, {
155
+ type: "text",
156
+ before: n,
157
+ after: t.content,
158
+ created: !r
159
+ }), s)
160
+ yield R(e, a, s);
161
+ else if (yield T(e.adapter, a))
162
+ throw new l(w.Conflict, "目标文件在确认期间被创建,本次写入已取消。请重新检查后再写入。");
163
+ const d = yield U(e, a, f, t.createDirectories);
164
+ return {
165
+ data: W(H({}, d), {
166
+ created: !r
167
+ })
168
+ };
169
+ });
170
+ export {
171
+ Q as applyPatch,
172
+ V as writeFile
173
+ };
@@ -0,0 +1,111 @@
1
+ var h = (u, c, l) => new Promise((r, f) => {
2
+ var i = (e) => {
3
+ try {
4
+ t(l.next(e));
5
+ } catch (d) {
6
+ f(d);
7
+ }
8
+ }, a = (e) => {
9
+ try {
10
+ t(l.throw(e));
11
+ } catch (d) {
12
+ f(d);
13
+ }
14
+ }, t = (e) => e.done ? r(e.value) : Promise.resolve(e.value).then(i, a);
15
+ t((l = l.apply(u, c)).next());
16
+ });
17
+ import { ToolError as n, ToolCode as o } from "../errors.mjs";
18
+ function w() {
19
+ return new n(o.Internal, "平台文件服务请求失败,请稍后重试。");
20
+ }
21
+ function F(u, c = () => {
22
+ }) {
23
+ const l = () => {
24
+ const i = u();
25
+ if (!i)
26
+ throw w();
27
+ return i;
28
+ }, r = () => {
29
+ const i = c();
30
+ if (!i)
31
+ throw w();
32
+ return i;
33
+ };
34
+ return {
35
+ upload(i, a, t) {
36
+ return h(this, null, function* () {
37
+ if (!a.sessionId)
38
+ throw new n(o.BadRequest, "当前没有可用的会话,无法上传文件。");
39
+ try {
40
+ t == null || t({
41
+ loaded: 0,
42
+ total: i.size
43
+ });
44
+ const e = yield r().postFile(i, (d, p) => t == null ? void 0 : t({
45
+ loaded: d,
46
+ total: p
47
+ }));
48
+ if (!(e != null && e.id) || !e.url)
49
+ throw w();
50
+ return t == null || t({
51
+ loaded: i.size,
52
+ total: i.size
53
+ }), {
54
+ fileId: e.id,
55
+ url: e.url
56
+ };
57
+ } catch (e) {
58
+ throw e instanceof n ? e : w();
59
+ }
60
+ });
61
+ },
62
+ resolveDownload(i, a) {
63
+ return h(this, null, function* () {
64
+ if (i.type === "platformFile")
65
+ return I(r(), i.fileId);
66
+ if (!a.sessionId)
67
+ throw new n(o.BadRequest, "当前没有可用的会话,无法下载会话文件。");
68
+ let t;
69
+ try {
70
+ t = yield l().getApplicationIdSessionFile(a.applicationId, a.sessionId, i.fileId);
71
+ } catch (e) {
72
+ throw w();
73
+ }
74
+ if (!(t != null && t.url))
75
+ throw new n(o.NotFound, "会话文件不存在或暂不可下载。");
76
+ return {
77
+ url: t.url,
78
+ name: t.name,
79
+ size: t.size
80
+ };
81
+ });
82
+ }
83
+ };
84
+ }
85
+ function I(u, c) {
86
+ return h(this, null, function* () {
87
+ let l;
88
+ try {
89
+ l = yield u.getFile(c);
90
+ } catch (f) {
91
+ throw w();
92
+ }
93
+ if (!(l != null && l.url))
94
+ throw new n(o.NotFound, "平台文件不存在或暂不可下载。");
95
+ let r;
96
+ try {
97
+ r = new URL(l.url);
98
+ } catch (f) {
99
+ throw new n(o.Internal, "平台返回的下载地址无效。");
100
+ }
101
+ if (r.protocol !== "https:")
102
+ throw new n(o.Internal, "平台返回的下载地址无效。");
103
+ return {
104
+ url: l.url,
105
+ size: l.bytes
106
+ };
107
+ });
108
+ }
109
+ export {
110
+ F as createDefaultSessionFileTransfer
111
+ };
@@ -0,0 +1,66 @@
1
+ var j = Object.defineProperty, p = Object.defineProperties;
2
+ var x = Object.getOwnPropertyDescriptors;
3
+ var $ = Object.getOwnPropertySymbols;
4
+ var A = Object.prototype.hasOwnProperty, I = Object.prototype.propertyIsEnumerable;
5
+ var g = (i, r, n) => r in i ? j(i, r, { enumerable: !0, configurable: !0, writable: !0, value: n }) : i[r] = n, s = (i, r) => {
6
+ for (var n in r || (r = {}))
7
+ A.call(r, n) && g(i, n, r[n]);
8
+ if ($)
9
+ for (var n of $(r))
10
+ I.call(r, n) && g(i, n, r[n]);
11
+ return i;
12
+ }, c = (i, r) => p(i, x(r));
13
+ import { ToolError as O, ToolCode as w } from "./errors.mjs";
14
+ function t(i, r) {
15
+ throw new O(w.BadRequest, i ? `参数 ${i} ${r}` : `参数${r}`);
16
+ }
17
+ function N(i, r) {
18
+ return typeof i != "string" ? i : (r.type === "integer" || r.type === "number") && /^-?\d+(\.\d+)?$/.test(i.trim()) ? Number(i) : r.type === "boolean" && (i === "true" || i === "false") ? i === "true" : i;
19
+ }
20
+ function y(i, r, n) {
21
+ switch (i = N(i, r), r.type) {
22
+ case "string":
23
+ typeof i != "string" && t(n, "必须是字符串。"), r.minLength !== void 0 && i.length < r.minLength && t(n, "不能为空。");
24
+ break;
25
+ case "integer":
26
+ (typeof i != "number" || !Number.isInteger(i)) && t(n, "必须是整数。");
27
+ break;
28
+ case "number":
29
+ (typeof i != "number" || !Number.isFinite(i)) && t(n, "必须是数字。");
30
+ break;
31
+ case "boolean":
32
+ typeof i != "boolean" && t(n, "必须是布尔值。");
33
+ break;
34
+ case "array":
35
+ if (Array.isArray(i) || t(n, "必须是数组。"), r.minItems !== void 0 && i.length < r.minItems && t(n, "不能为空。"), r.items) {
36
+ const e = r.items;
37
+ return i.map((f, m) => y(f, e, `${n}[${m}]`));
38
+ }
39
+ break;
40
+ case "object":
41
+ return k(i, r, n);
42
+ }
43
+ return r.enum && !r.enum.includes(i) && t(n, `必须是 ${r.enum.join("、")} 之一。`), typeof i == "number" && (r.minimum !== void 0 && i < r.minimum && t(n, `不能小于 ${r.minimum}。`), r.maximum !== void 0 && i > r.maximum && t(n, `不能大于 ${r.maximum}。`)), i;
44
+ }
45
+ function k(i, r, n) {
46
+ var m, d;
47
+ (!i || typeof i != "object" || Array.isArray(i)) && t(n, "必须是对象。");
48
+ const e = i, f = {};
49
+ for (const o of (m = r.required) != null ? m : [])
50
+ (e[o] === void 0 || e[o] === null) && t(n ? `${n}.${o}` : o, "是必填项。");
51
+ for (const [o, b] of Object.entries((d = r.properties) != null ? d : {})) {
52
+ if (e[o] === void 0 || e[o] === null)
53
+ continue;
54
+ const u = n ? `${n}.${o}` : o;
55
+ f[o] = b.oneOf ? (y(e[o], c(s({}, b), {
56
+ oneOf: void 0
57
+ }), u), e[o]) : y(e[o], b, u);
58
+ }
59
+ return f;
60
+ }
61
+ function L(i, r) {
62
+ return k(i, r, "");
63
+ }
64
+ export {
65
+ L as validateToolInput
66
+ };
@@ -0,0 +1,339 @@
1
+ var _ = Object.defineProperty, k = Object.defineProperties;
2
+ var S = Object.getOwnPropertyDescriptors;
3
+ var w = Object.getOwnPropertySymbols;
4
+ var C = Object.prototype.hasOwnProperty, P = Object.prototype.propertyIsEnumerable;
5
+ var u = (r, e, t) => e in r ? _(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t, f = (r, e) => {
6
+ for (var t in e || (e = {}))
7
+ C.call(e, t) && u(r, t, e[t]);
8
+ if (w)
9
+ for (var t of w(e))
10
+ P.call(e, t) && u(r, t, e[t]);
11
+ return r;
12
+ }, A = (r, e) => k(r, S(e));
13
+ var s = (r, e, t) => (u(r, typeof e != "symbol" ? e + "" : e, t), t);
14
+ var o = (r, e, t) => new Promise((i, a) => {
15
+ var n = (l) => {
16
+ try {
17
+ c(t.next(l));
18
+ } catch (d) {
19
+ a(d);
20
+ }
21
+ }, h = (l) => {
22
+ try {
23
+ c(t.throw(l));
24
+ } catch (d) {
25
+ a(d);
26
+ }
27
+ }, c = (l) => l.done ? i(l.value) : Promise.resolve(l.value).then(n, h);
28
+ c((t = t.apply(r, e)).next());
29
+ });
30
+ import H from "../../EventBus.mjs";
31
+ import { FileSystemAccessAdapter as b } from "../adapters/FileSystemAccessAdapter.mjs";
32
+ import { getNativeDirectoryPicker as D } from "../adapters/fsaTypes.mjs";
33
+ import { LOCAL_FILES_FUNCTION_CODES as T } from "../constants.mjs";
34
+ import { getDownloadUrlAllowlist as F } from "../security/downloadUrlPolicy.mjs";
35
+ import { SensitiveFilePolicy as W } from "../security/sensitiveFiles.mjs";
36
+ import { resolveLimits as q } from "../limits.mjs";
37
+ import { createDefaultSessionFileTransfer as N } from "../transfer/SessionFileTransfer.mjs";
38
+ import { createMemoryStore as I } from "./handleStore.mjs";
39
+ import { watchDirectoryHandle as E } from "./watchDirectory.mjs";
40
+ const p = {
41
+ mode: "readwrite"
42
+ };
43
+ function K(r) {
44
+ const e = r.replace(/\\/g, "/").trim().replace(/^\.\/+/, "").replace(/\/+$/, "");
45
+ if (!e || e === ".")
46
+ return "";
47
+ if (e.startsWith("/") || e.includes(":") || e.includes("\0"))
48
+ return;
49
+ const t = e.split("/");
50
+ if (!t.some((i) => !i || i === "." || i === ".."))
51
+ return t.join("/");
52
+ }
53
+ function L(r) {
54
+ return !!r && typeof r == "object" && r.name === "AbortError";
55
+ }
56
+ class J {
57
+ constructor(e) {
58
+ s(this, "applicationId");
59
+ s(this, "limits");
60
+ s(this, "sensitive");
61
+ s(this, "downloadUrlAllowlist");
62
+ s(this, "allowWorkspaceWideTextSearch");
63
+ s(this, "transfer");
64
+ s(this, "fetch");
65
+ s(this, "store");
66
+ s(this, "picker");
67
+ s(this, "event", new H(!0));
68
+ s(this, "_status");
69
+ s(this, "_displayName");
70
+ s(this, "_adapter", null);
71
+ s(this, "pendingHandle", null);
72
+ s(this, "approvalHandler");
73
+ s(this, "activeCalls", 0);
74
+ s(this, "inflight", /* @__PURE__ */ new Set());
75
+ s(this, "_ready", Promise.resolve());
76
+ s(this, "stopWatching", () => {
77
+ });
78
+ s(this, "pendingChangePaths", /* @__PURE__ */ new Set());
79
+ s(this, "changeTimer");
80
+ s(this, "refreshAllVisible", !1);
81
+ var n, h, c, l, d, m, g, y, v;
82
+ const t = (n = e.config) != null ? n : {};
83
+ this.applicationId = e.applicationId, this.store = (h = e.store) != null ? h : I(), this.picker = e.picker === null ? void 0 : (c = e.picker) != null ? c : D(), this.limits = q(t.limits), this.sensitive = new W(t.sensitiveRulesAppend), this.downloadUrlAllowlist = F(t.downloadUrlAllowlistAppend), this.allowWorkspaceWideTextSearch = !!t.allowWorkspaceWideTextSearch, this.approvalHandler = t.onApprovalRequired;
84
+ const i = (l = e.transfer) != null ? l : N(() => {
85
+ });
86
+ this.transfer = {
87
+ upload: (m = (d = t.transfer) == null ? void 0 : d.upload) != null ? m : i.upload,
88
+ resolveDownload: (y = (g = t.transfer) == null ? void 0 : g.resolveDownload) != null ? y : i.resolveDownload
89
+ };
90
+ const a = (v = e.fetch) != null ? v : typeof fetch == "function" ? fetch : void 0;
91
+ this.fetch = a ? a.bind(globalThis) : () => Promise.reject(new Error("fetch is not available")), this._status = this.picker ? "none" : "unsupported";
92
+ }
93
+ // -------------------------------------------------------------------------
94
+ // 状态
95
+ // -------------------------------------------------------------------------
96
+ get status() {
97
+ return this._status;
98
+ }
99
+ /** 当前(或待恢复的)文件夹名,不含绝对路径。 */
100
+ get displayName() {
101
+ return this._displayName;
102
+ }
103
+ get isSupported() {
104
+ return !!this.picker;
105
+ }
106
+ /** 最近一次 restore() 完成前,工具调用会等待它。 */
107
+ get ready() {
108
+ return this._ready;
109
+ }
110
+ /** @internal 已授权时可用的 Adapter。 */
111
+ get adapter() {
112
+ return this._status === "granted" ? this._adapter : null;
113
+ }
114
+ get handleKey() {
115
+ return `workspace:${this.applicationId}`;
116
+ }
117
+ get disclosureKey() {
118
+ return `disclosure:${this.applicationId}`;
119
+ }
120
+ setStatus(e, t = this._displayName) {
121
+ e === this._status && t === this._displayName || (this._status = e, this._displayName = t, this.emit("workspace:changed", {
122
+ status: e,
123
+ displayName: t
124
+ }));
125
+ }
126
+ attachHandle(e) {
127
+ this.cancelFilesChanged(), this.pendingHandle = e, this._adapter = new b(e), this.setStatus("granted", e.name), this.unwatchDirectory(), this.stopWatching = E(e, (t) => this.notifyFilesChanged(t));
128
+ }
129
+ // -------------------------------------------------------------------------
130
+ // 授权
131
+ // -------------------------------------------------------------------------
132
+ /**
133
+ * 弹出目录选择框。必须在用户点击事件中调用。
134
+ * 用户取消时返回 false 且状态不变。
135
+ */
136
+ pick() {
137
+ if (!this.picker)
138
+ return Promise.resolve(!1);
139
+ let e;
140
+ try {
141
+ e = this.picker({
142
+ mode: "readwrite"
143
+ });
144
+ } catch (t) {
145
+ return Promise.reject(t);
146
+ }
147
+ return e.then((t) => o(this, null, function* () {
148
+ var a, n;
149
+ this.cancelAll();
150
+ const i = (n = yield (a = t.queryPermission) == null ? void 0 : a.call(t, p)) != null ? n : "granted";
151
+ return yield this.store.set(this.handleKey, {
152
+ handle: t,
153
+ displayName: t.name,
154
+ savedAt: Date.now()
155
+ }).catch(() => {
156
+ }), i === "denied" ? (this.pendingHandle = t, this._adapter = null, this.setStatus("denied", t.name), !1) : (this.attachHandle(t), !0);
157
+ }), (t) => {
158
+ if (L(t))
159
+ return !1;
160
+ throw t;
161
+ });
162
+ }
163
+ /** 读取上次的目录句柄并检查权限,不弹窗。 */
164
+ restore() {
165
+ return this._ready = this.doRestore(), this._ready;
166
+ }
167
+ doRestore() {
168
+ return o(this, null, function* () {
169
+ var i, a, n;
170
+ if (!this.picker) {
171
+ this._adapter || this.setStatus("unsupported");
172
+ return;
173
+ }
174
+ let e;
175
+ try {
176
+ e = yield this.store.get(this.handleKey);
177
+ } catch (h) {
178
+ e = void 0;
179
+ }
180
+ if (!(e != null && e.handle)) {
181
+ this.pendingHandle = null, this._adapter = null, this.setStatus("none", void 0);
182
+ return;
183
+ }
184
+ let t;
185
+ try {
186
+ t = (n = yield (a = (i = e.handle).queryPermission) == null ? void 0 : a.call(i, p)) != null ? n : "prompt";
187
+ } catch (h) {
188
+ t = "prompt";
189
+ }
190
+ t === "granted" ? this.attachHandle(e.handle) : (this.pendingHandle = e.handle, this._adapter = null, this.setStatus(t === "denied" ? "denied" : "prompt", e.displayName));
191
+ });
192
+ }
193
+ /** 对已保存的目录重新申请权限。必须在用户点击事件中调用。 */
194
+ requestPermission() {
195
+ const e = this.pendingHandle;
196
+ if (!(e != null && e.requestPermission))
197
+ return Promise.resolve(!1);
198
+ let t;
199
+ try {
200
+ t = e.requestPermission(p);
201
+ } catch (i) {
202
+ return Promise.reject(i);
203
+ }
204
+ return t.then((i) => i === "granted" ? (this.attachHandle(e), !0) : (this._adapter = null, this.setStatus(i === "denied" ? "denied" : "prompt", e.name), !1));
205
+ }
206
+ /** 断开工作区并删除持久化句柄。状态立即变为未授权,存储删除在其后完成。 */
207
+ clear() {
208
+ return o(this, null, function* () {
209
+ this.cancelAll(), this.cancelFilesChanged(), this.unwatchDirectory(), this.pendingHandle = null, this._adapter = null, this.setStatus(this.picker ? "none" : "unsupported", void 0), yield this.store.delete(this.handleKey).catch(() => {
210
+ });
211
+ });
212
+ }
213
+ /** 直接挂载一个 Adapter(测试或自定义后端),视为已授权。 */
214
+ attachAdapter(e, t = e.displayName) {
215
+ this.cancelAll(), this.cancelFilesChanged(), this.unwatchDirectory(), this.pendingHandle = null, this._adapter = e, this.setStatus("granted", t);
216
+ }
217
+ /**
218
+ * 通知目录树重读。`paths` 是相对工作区根的目录;省略时重读当前展开的全部目录。
219
+ * 短时间内的多次通知会合并成一次。
220
+ */
221
+ notifyFilesChanged(e) {
222
+ if (this._status === "granted") {
223
+ if (!e || e.length === 0)
224
+ this.refreshAllVisible = !0;
225
+ else
226
+ for (const t of e) {
227
+ const i = K(t);
228
+ i === void 0 ? this.refreshAllVisible = !0 : this.pendingChangePaths.add(i);
229
+ }
230
+ clearTimeout(this.changeTimer), this.changeTimer = setTimeout(() => this.flushFilesChanged(), 150);
231
+ }
232
+ }
233
+ /** @internal 工具执行中遇到权限错误时调用,重新检查并更新状态。 */
234
+ handlePermissionLost() {
235
+ return o(this, null, function* () {
236
+ const e = this.pendingHandle;
237
+ if (!(e != null && e.queryPermission))
238
+ return;
239
+ const t = yield e.queryPermission(p).catch(() => "prompt");
240
+ t !== "granted" && (this.cancelAll(), this.cancelFilesChanged(), this.unwatchDirectory(), this._adapter = null, this.setStatus(t === "denied" ? "denied" : "prompt", e.name));
241
+ });
242
+ }
243
+ // -------------------------------------------------------------------------
244
+ // 外发提示
245
+ // -------------------------------------------------------------------------
246
+ isDisclosureAcknowledged() {
247
+ return o(this, null, function* () {
248
+ try {
249
+ return !!(yield this.store.get(this.disclosureKey));
250
+ } catch (e) {
251
+ return !1;
252
+ }
253
+ });
254
+ }
255
+ acknowledgeDisclosure() {
256
+ return o(this, null, function* () {
257
+ yield this.store.set(this.disclosureKey, !0).catch(() => {
258
+ });
259
+ });
260
+ }
261
+ // -------------------------------------------------------------------------
262
+ // 确认、并发与取消
263
+ // -------------------------------------------------------------------------
264
+ setApprovalHandler(e) {
265
+ this.approvalHandler = e;
266
+ }
267
+ get hasApprovalHandler() {
268
+ return !!this.approvalHandler;
269
+ }
270
+ /** @internal */
271
+ getApprovalHandler() {
272
+ return this.approvalHandler;
273
+ }
274
+ /** @internal 占用一个并发名额;已满时返回 null。 */
275
+ acquireSlot() {
276
+ if (this.activeCalls >= this.limits.maxConcurrentRequests)
277
+ return null;
278
+ this.activeCalls++;
279
+ let e = !1;
280
+ return () => {
281
+ e || (e = !0, this.activeCalls--);
282
+ };
283
+ }
284
+ /** @internal 登记进行中的调用,更换或断开工作区时统一中止。 */
285
+ track(e) {
286
+ return this.inflight.add(e), () => this.inflight.delete(e);
287
+ }
288
+ /** 中止所有进行中的调用(含等待确认的请求)。 */
289
+ cancelAll() {
290
+ const e = Array.from(this.inflight);
291
+ this.inflight.clear(), e.forEach((t) => t.abort());
292
+ }
293
+ handshake() {
294
+ const e = Object.fromEntries(T.map((t) => [t, !0]));
295
+ return {
296
+ protocolVersion: "1.0",
297
+ capabilities: A(f({}, e), {
298
+ cancellation: !0,
299
+ atomicWrite: !0
300
+ }),
301
+ limits: f({}, this.limits)
302
+ };
303
+ }
304
+ // -------------------------------------------------------------------------
305
+ // 事件
306
+ // -------------------------------------------------------------------------
307
+ on(e, t) {
308
+ return this.event.on(e, t), () => this.off(e, t);
309
+ }
310
+ off(e, t) {
311
+ this.event.off(e, t);
312
+ }
313
+ unwatchDirectory() {
314
+ const e = this.stopWatching;
315
+ this.stopWatching = () => {
316
+ }, e();
317
+ }
318
+ cancelFilesChanged() {
319
+ clearTimeout(this.changeTimer), this.changeTimer = void 0, this.pendingChangePaths.clear(), this.refreshAllVisible = !1;
320
+ }
321
+ flushFilesChanged() {
322
+ this.changeTimer = void 0;
323
+ const e = this.refreshAllVisible, t = [...this.pendingChangePaths].sort((i, a) => i < a ? -1 : i > a ? 1 : 0);
324
+ this.pendingChangePaths.clear(), this.refreshAllVisible = !1, this._status === "granted" && this.emit("files:changed", {
325
+ paths: e ? [] : t
326
+ });
327
+ }
328
+ /** @internal */
329
+ emit(e, t) {
330
+ try {
331
+ this.event.emit(e, t);
332
+ } catch (i) {
333
+ console.error(`[LocalWorkspace] ${e} listener failed`, i);
334
+ }
335
+ }
336
+ }
337
+ export {
338
+ J as LocalWorkspace
339
+ };