@glodon-aiot/bot-client-sdk 3.25.1-alpha.6 → 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.
- package/README.md +543 -98
- package/dist/es/AgentSession.mjs +230 -165
- package/dist/es/BotClient.mjs +186 -136
- package/dist/es/Config.mjs +111 -26
- package/dist/es/Session.mjs +12 -0
- package/dist/es/api/index.mjs +42 -33
- package/dist/es/index.mjs +68 -9
- package/dist/es/localFiles/adapters/FileSystemAccessAdapter.mjs +174 -0
- package/dist/es/localFiles/adapters/HostBridgeAdapter.mjs +172 -0
- package/dist/es/localFiles/adapters/MemoryWorkspaceAdapter.mjs +162 -0
- package/dist/es/localFiles/adapters/WorkspaceFileAdapter.mjs +50 -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/createLocalPythonPlugin.mjs +196 -0
- package/dist/es/localFiles/errors.mjs +57 -0
- package/dist/es/localFiles/host/connectHostBridge.mjs +50 -0
- package/dist/es/localFiles/host/protocol.mjs +26 -0
- package/dist/es/localFiles/limits.mjs +22 -0
- package/dist/es/localFiles/schemas.mjs +327 -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 +339 -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 +7 -4
- package/dist/lib/index.js +9 -4
- 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/index.d.ts +4 -2
- package/dist/src/localFiles/adapters/FileSystemAccessAdapter.d.ts +17 -0
- package/dist/src/localFiles/adapters/HostBridgeAdapter.d.ts +24 -0
- package/dist/src/localFiles/adapters/MemoryWorkspaceAdapter.d.ts +18 -0
- package/dist/src/localFiles/adapters/WorkspaceFileAdapter.d.ts +26 -0
- package/dist/src/localFiles/adapters/fsaTypes.d.ts +39 -0
- package/dist/src/localFiles/constants.d.ts +50 -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 +33 -0
- package/dist/src/localFiles/index.d.ts +21 -0
- package/dist/src/localFiles/limits.d.ts +3 -0
- package/dist/src/localFiles/schemas.d.ts +30 -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 +306 -0
- package/dist/src/localFiles/validate.d.ts +2 -0
- package/dist/src/localFiles/workspace/LocalWorkspace.d.ts +99 -0
- package/dist/src/localFiles/workspace/handleStore.d.ts +11 -0
- package/dist/src/localFiles/workspace/watchDirectory.d.ts +7 -0
- 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
|
+
};
|