@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.
- 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,50 @@
|
|
|
1
|
+
var p = (n, e) => {
|
|
2
|
+
if (e = Symbol[n])
|
|
3
|
+
return e;
|
|
4
|
+
throw Error("Symbol." + n + " is not defined");
|
|
5
|
+
};
|
|
6
|
+
var a = function(n, e) {
|
|
7
|
+
this[0] = n, this[1] = e;
|
|
8
|
+
}, s = (n, e, l) => {
|
|
9
|
+
var d = (t, f, r, c) => {
|
|
10
|
+
try {
|
|
11
|
+
var x = l[t](f), E = (f = x.value) instanceof a, g = x.done;
|
|
12
|
+
Promise.resolve(E ? f[0] : f).then((y) => E ? d(t === "return" ? t : "next", f[1] ? { done: y.done, value: y.value } : y, r, c) : r({ value: y, done: g })).catch((y) => d("throw", y, r, c));
|
|
13
|
+
} catch (y) {
|
|
14
|
+
c(y);
|
|
15
|
+
}
|
|
16
|
+
}, o = (t) => i[t] = (f) => new Promise((r, c) => d(t, f, r, c)), i = {};
|
|
17
|
+
return l = l.apply(n, e), i[Symbol.asyncIterator] = () => i, o("next"), o("throw"), o("return"), i;
|
|
18
|
+
}, w = (n) => {
|
|
19
|
+
var e = n[p("asyncIterator")], l = !1, d, o = {};
|
|
20
|
+
return e == null ? (e = n[p("iterator")](), d = (i) => o[i] = (t) => e[i](t)) : (e = e.call(n), d = (i) => o[i] = (t) => {
|
|
21
|
+
if (l) {
|
|
22
|
+
if (l = !1, i === "throw")
|
|
23
|
+
throw t;
|
|
24
|
+
return t;
|
|
25
|
+
}
|
|
26
|
+
return l = !0, {
|
|
27
|
+
done: !1,
|
|
28
|
+
value: new a(new Promise((f) => {
|
|
29
|
+
var r = e[i](t);
|
|
30
|
+
if (!(r instanceof Object))
|
|
31
|
+
throw TypeError("Object expected");
|
|
32
|
+
f(r);
|
|
33
|
+
}), 1)
|
|
34
|
+
};
|
|
35
|
+
}), o[p("iterator")] = () => o, d("next"), "throw" in e ? d("throw") : o.throw = (i) => {
|
|
36
|
+
throw i;
|
|
37
|
+
}, "return" in e && d("return"), o;
|
|
38
|
+
};
|
|
39
|
+
function k(n, e = n) {
|
|
40
|
+
return new DOMException(e, n);
|
|
41
|
+
}
|
|
42
|
+
function A(n) {
|
|
43
|
+
return s(this, null, function* () {
|
|
44
|
+
typeof n == "string" ? yield new TextEncoder().encode(n) : n instanceof Uint8Array ? yield n : yield* w(n);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
export {
|
|
48
|
+
k as domError,
|
|
49
|
+
A as toChunks
|
|
50
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
const s = ["list_directory", "read_file", "stat_file", "search_files", "search_text", "apply_patch", "write_file", "upload_file", "download_file"], _ = "buildin_tools", t = {
|
|
2
|
+
dev: _,
|
|
3
|
+
test: _,
|
|
4
|
+
prod: _,
|
|
5
|
+
local: _
|
|
6
|
+
}, E = t, c = "run_python", I = t, n = 2e4, O = 12e4, L = 16, S = "current-workspace", o = 1024, e = 1024 * 1024, T = 50, A = Object.freeze({
|
|
7
|
+
maxReadBytes: 1 * e,
|
|
8
|
+
maxWriteBytes: 5 * e,
|
|
9
|
+
maxSearchResults: 200,
|
|
10
|
+
maxConcurrentRequests: 4,
|
|
11
|
+
maxTransferBytes: T * e,
|
|
12
|
+
toolTimeoutMs: 3e4,
|
|
13
|
+
searchTimeoutMs: 6e4,
|
|
14
|
+
transferTimeoutMs: 10 * 6e4,
|
|
15
|
+
approvalTimeoutMs: 5 * 6e4
|
|
16
|
+
}), N = 200, C = 1e3, a = 8, l = 16, R = 2e3, r = 1 * e, i = 500, D = 3, F = 8 * o, M = Object.freeze(["glodon.com"]), U = Object.freeze([".git", "node_modules", ".svn", ".idea", ".vscode"]), d = Object.freeze(["~$*", ".~lock*", "*.tmp"]), f = ["apply_patch", "write_file", "upload_file", "download_file"], p = ["search_files", "search_text"], H = ["upload_file", "download_file"];
|
|
17
|
+
export {
|
|
18
|
+
F as BINARY_SNIFF_BYTES,
|
|
19
|
+
_ as BUILTIN_TOOLS_PLUGIN_CODE,
|
|
20
|
+
t as BUILTIN_TOOLS_PLUGIN_CODES,
|
|
21
|
+
M as DEFAULT_DOWNLOAD_URL_ALLOWLIST,
|
|
22
|
+
U as DEFAULT_IGNORED_DIRECTORIES,
|
|
23
|
+
d as DEFAULT_IGNORED_FILE_PATTERNS,
|
|
24
|
+
A as DEFAULT_LIMITS,
|
|
25
|
+
o as KiB,
|
|
26
|
+
N as LIST_DIRECTORY_DEFAULT_LIMIT,
|
|
27
|
+
C as LIST_DIRECTORY_MAX_LIMIT,
|
|
28
|
+
s as LOCAL_FILES_FUNCTION_CODES,
|
|
29
|
+
E as LOCAL_FILES_PLUGIN_CODES,
|
|
30
|
+
c as LOCAL_PYTHON_FUNCTION_CODE,
|
|
31
|
+
I as LOCAL_PYTHON_PLUGIN_CODES,
|
|
32
|
+
e as MiB,
|
|
33
|
+
n as PYTHON_DEFAULT_TIMEOUT_MS,
|
|
34
|
+
L as PYTHON_MAX_ARGS,
|
|
35
|
+
O as PYTHON_MAX_TIMEOUT_MS,
|
|
36
|
+
a as SEARCH_DEFAULT_DEPTH,
|
|
37
|
+
p as SEARCH_FUNCTION_CODES,
|
|
38
|
+
l as SEARCH_MAX_DEPTH,
|
|
39
|
+
D as TEXT_SEARCH_MAX_CONTEXT_LINES,
|
|
40
|
+
R as TEXT_SEARCH_MAX_FILES,
|
|
41
|
+
r as TEXT_SEARCH_MAX_FILE_BYTES,
|
|
42
|
+
i as TEXT_SEARCH_MAX_LINE_CHARS,
|
|
43
|
+
T as TRANSFER_FILE_SIZE_LIMIT_MB,
|
|
44
|
+
H as TRANSFER_FUNCTION_CODES,
|
|
45
|
+
S as WORKSPACE_GRANT_ID,
|
|
46
|
+
f as WRITE_FUNCTION_CODES
|
|
47
|
+
};
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
var J = Object.defineProperty, B = Object.defineProperties;
|
|
2
|
+
var K = Object.getOwnPropertyDescriptors;
|
|
3
|
+
var G = Object.getOwnPropertySymbols;
|
|
4
|
+
var z = Object.prototype.hasOwnProperty, Q = Object.prototype.propertyIsEnumerable;
|
|
5
|
+
var E = (e, t, r) => t in e ? J(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r, u = (e, t) => {
|
|
6
|
+
for (var r in t || (t = {}))
|
|
7
|
+
z.call(t, r) && E(e, r, t[r]);
|
|
8
|
+
if (G)
|
|
9
|
+
for (var r of G(t))
|
|
10
|
+
Q.call(t, r) && E(e, r, t[r]);
|
|
11
|
+
return e;
|
|
12
|
+
}, f = (e, t) => B(e, K(t));
|
|
13
|
+
var _ = (e, t, r) => (E(e, typeof t != "symbol" ? t + "" : t, r), r);
|
|
14
|
+
var F = (e, t, r) => new Promise((d, s) => {
|
|
15
|
+
var o = (a) => {
|
|
16
|
+
try {
|
|
17
|
+
i(r.next(a));
|
|
18
|
+
} catch (c) {
|
|
19
|
+
s(c);
|
|
20
|
+
}
|
|
21
|
+
}, n = (a) => {
|
|
22
|
+
try {
|
|
23
|
+
i(r.throw(a));
|
|
24
|
+
} catch (c) {
|
|
25
|
+
s(c);
|
|
26
|
+
}
|
|
27
|
+
}, i = (a) => a.done ? d(a.value) : Promise.resolve(a.value).then(o, n);
|
|
28
|
+
i((r = r.apply(e, t)).next());
|
|
29
|
+
});
|
|
30
|
+
import { v4 as U } from "uuid";
|
|
31
|
+
import { LOCAL_FILES_FUNCTION_CODES as V, TRANSFER_FUNCTION_CODES as X, SEARCH_FUNCTION_CODES as Y, WORKSPACE_GRANT_ID as Z } from "./constants.mjs";
|
|
32
|
+
import { cancelledError as g, workspaceNotGranted as $, ToolError as h, ToolCode as m, toToolError as k } from "./errors.mjs";
|
|
33
|
+
import { LOCAL_FILE_TOOL_SCHEMAS as ee } from "./schemas.mjs";
|
|
34
|
+
import { assertGrantId as te } from "./security/pathPolicy.mjs";
|
|
35
|
+
import { listDirectory as re, readFile as ie, statFile as ae, searchFiles as oe, searchText as ne } from "./tools/readTools.mjs";
|
|
36
|
+
import { uploadFile as se, downloadFile as le } from "./tools/transferTools.mjs";
|
|
37
|
+
import { applyPatch as de, writeFile as ce } from "./tools/writeTools.mjs";
|
|
38
|
+
import { validateToolInput as ue } from "./validate.mjs";
|
|
39
|
+
const me = {
|
|
40
|
+
list_directory: re,
|
|
41
|
+
read_file: ie,
|
|
42
|
+
stat_file: ae,
|
|
43
|
+
search_files: oe,
|
|
44
|
+
search_text: ne,
|
|
45
|
+
apply_patch: de,
|
|
46
|
+
write_file: ce,
|
|
47
|
+
upload_file: se,
|
|
48
|
+
download_file: le
|
|
49
|
+
};
|
|
50
|
+
class he {
|
|
51
|
+
constructor(t, r) {
|
|
52
|
+
_(this, "remaining");
|
|
53
|
+
_(this, "startedAt", 0);
|
|
54
|
+
_(this, "handle");
|
|
55
|
+
this.onTimeout = r, this.remaining = t;
|
|
56
|
+
}
|
|
57
|
+
resume() {
|
|
58
|
+
this.handle !== void 0 || this.remaining <= 0 || (this.startedAt = Date.now(), this.handle = setTimeout(() => {
|
|
59
|
+
this.handle = void 0, this.remaining = 0, this.onTimeout();
|
|
60
|
+
}, this.remaining));
|
|
61
|
+
}
|
|
62
|
+
pause() {
|
|
63
|
+
this.handle !== void 0 && (clearTimeout(this.handle), this.handle = void 0, this.remaining -= Date.now() - this.startedAt);
|
|
64
|
+
}
|
|
65
|
+
clear() {
|
|
66
|
+
this.pause(), this.remaining = 0;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function fe(e, t) {
|
|
70
|
+
return X.includes(t) ? e.limits.transferTimeoutMs : Y.includes(t) ? e.limits.searchTimeoutMs : e.limits.toolTimeoutMs;
|
|
71
|
+
}
|
|
72
|
+
function ge(e) {
|
|
73
|
+
if (typeof e != "string")
|
|
74
|
+
return e;
|
|
75
|
+
try {
|
|
76
|
+
return JSON.parse(e);
|
|
77
|
+
} catch (t) {
|
|
78
|
+
throw new h(m.BadRequest, "参数不是合法的 JSON 对象。");
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function pe(e) {
|
|
82
|
+
if (!e || typeof e != "object" || Array.isArray(e))
|
|
83
|
+
return;
|
|
84
|
+
const t = e;
|
|
85
|
+
return (t.grantId === void 0 || t.grantId === null || t.grantId === "") && (t.grantId = Z), t.grantId;
|
|
86
|
+
}
|
|
87
|
+
function W(e) {
|
|
88
|
+
return new Promise((t, r) => {
|
|
89
|
+
e.aborted && r(g()), e.addEventListener("abort", () => r(g()), {
|
|
90
|
+
once: !0
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
function ve(e) {
|
|
95
|
+
return u({
|
|
96
|
+
code: e.code,
|
|
97
|
+
message: e.message
|
|
98
|
+
}, e.data ? {
|
|
99
|
+
data: e.data
|
|
100
|
+
} : {});
|
|
101
|
+
}
|
|
102
|
+
function Ie(e, t, r, d, s) {
|
|
103
|
+
return F(this, null, function* () {
|
|
104
|
+
var N, S, q, P, C, D, R, x;
|
|
105
|
+
const o = {
|
|
106
|
+
requestId: s.requestId || U(),
|
|
107
|
+
applicationId: s.applicationId || e.applicationId,
|
|
108
|
+
sessionId: s.sessionId || "",
|
|
109
|
+
pluginCode: s.pluginCode,
|
|
110
|
+
functionCode: t,
|
|
111
|
+
signal: s.signal
|
|
112
|
+
}, n = {
|
|
113
|
+
requestId: o.requestId,
|
|
114
|
+
sessionId: o.sessionId,
|
|
115
|
+
functionCode: t
|
|
116
|
+
}, i = new AbortController();
|
|
117
|
+
let a = !1;
|
|
118
|
+
const c = new he(fe(e, t), () => {
|
|
119
|
+
a = !0, i.abort();
|
|
120
|
+
}), v = () => i.abort();
|
|
121
|
+
(N = o.signal) == null || N.addEventListener("abort", v, {
|
|
122
|
+
once: !0
|
|
123
|
+
}), (S = o.signal) != null && S.aborted && i.abort();
|
|
124
|
+
let p = null, I, L = !1;
|
|
125
|
+
try {
|
|
126
|
+
const b = ge(r), l = pe(b);
|
|
127
|
+
l != null && te(l);
|
|
128
|
+
const w = ue(b, ee[t].parameters), M = (q = w.path) != null ? q : w.destPath;
|
|
129
|
+
if (typeof M == "string" && (n.path = M), yield e.ready, i.signal.aborted)
|
|
130
|
+
throw g();
|
|
131
|
+
const y = e.adapter;
|
|
132
|
+
if (!y)
|
|
133
|
+
throw $();
|
|
134
|
+
if (p = e.acquireSlot(), !p)
|
|
135
|
+
throw new h(m.TooManyRequests, "同时进行的文件操作过多,请稍后重试。");
|
|
136
|
+
I = e.track(i), L = !0, e.emit("tool:start", u({}, n)), c.resume();
|
|
137
|
+
const H = {
|
|
138
|
+
adapter: y,
|
|
139
|
+
workspaceName: (P = e.displayName) != null ? P : y.displayName,
|
|
140
|
+
limits: e.limits,
|
|
141
|
+
sensitive: e.sensitive,
|
|
142
|
+
downloadUrlAllowlist: e.downloadUrlAllowlist,
|
|
143
|
+
allowWorkspaceWideTextSearch: e.allowWorkspaceWideTextSearch,
|
|
144
|
+
transfer: e.transfer,
|
|
145
|
+
fetch: e.fetch,
|
|
146
|
+
context: f(u({}, o), {
|
|
147
|
+
signal: i.signal
|
|
148
|
+
}),
|
|
149
|
+
signal: i.signal,
|
|
150
|
+
requestApproval: (O, j) => be(e, {
|
|
151
|
+
approvalPath: O,
|
|
152
|
+
preview: j,
|
|
153
|
+
context: o,
|
|
154
|
+
functionCode: t,
|
|
155
|
+
signal: i.signal,
|
|
156
|
+
timer: c,
|
|
157
|
+
base: n
|
|
158
|
+
}),
|
|
159
|
+
progress: (O) => e.emit("tool:progress", u(u({}, n), O))
|
|
160
|
+
}, T = yield Promise.race([me[t](w, H), W(i.signal)]), A = {
|
|
161
|
+
code: m.Ok,
|
|
162
|
+
message: "ok",
|
|
163
|
+
data: T.data
|
|
164
|
+
};
|
|
165
|
+
T.truncated && (A.truncated = !0), (C = T.warnings) != null && C.length && (A.warnings = T.warnings), e.emit("tool:finish", f(u({}, n), {
|
|
166
|
+
code: m.Ok
|
|
167
|
+
})), d(A);
|
|
168
|
+
} catch (b) {
|
|
169
|
+
let l = k(b);
|
|
170
|
+
a ? l = new h(m.Timeout, "操作超时,已中止。") : i.signal.aborted && l.code !== m.Cancelled && (l = g()), ((D = l.data) == null ? void 0 : D.reason) === "workspace_not_granted" && L && e.handlePermissionLost(), l.code === m.Cancelled ? e.emit("tool:cancelled", u({}, n)) : e.emit("tool:error", f(u({}, n), {
|
|
171
|
+
code: l.code,
|
|
172
|
+
message: l.message,
|
|
173
|
+
reason: (R = l.data) == null ? void 0 : R.reason
|
|
174
|
+
})), d(ve(l));
|
|
175
|
+
} finally {
|
|
176
|
+
c.clear(), (x = o.signal) == null || x.removeEventListener("abort", v), p == null || p(), I == null || I();
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
function be(e, t) {
|
|
181
|
+
return F(this, null, function* () {
|
|
182
|
+
var i;
|
|
183
|
+
const r = e.getApprovalHandler();
|
|
184
|
+
if (!r)
|
|
185
|
+
throw new h(m.Forbidden, "当前环境未提供操作确认能力,无法执行写入或传输操作。", {
|
|
186
|
+
reason: "approval_unavailable"
|
|
187
|
+
});
|
|
188
|
+
if (t.signal.aborted)
|
|
189
|
+
throw g();
|
|
190
|
+
const d = new AbortController(), s = () => d.abort();
|
|
191
|
+
t.signal.addEventListener("abort", s, {
|
|
192
|
+
once: !0
|
|
193
|
+
});
|
|
194
|
+
const o = {
|
|
195
|
+
id: U(),
|
|
196
|
+
requestId: t.context.requestId,
|
|
197
|
+
sessionId: t.context.sessionId,
|
|
198
|
+
functionCode: t.functionCode,
|
|
199
|
+
path: t.approvalPath,
|
|
200
|
+
workspaceName: (i = e.displayName) != null ? i : "",
|
|
201
|
+
preview: t.preview,
|
|
202
|
+
signal: d.signal
|
|
203
|
+
};
|
|
204
|
+
t.timer.pause(), e.emit("tool:approval-required", f(u({}, t.base), {
|
|
205
|
+
path: t.approvalPath,
|
|
206
|
+
approvalId: o.id
|
|
207
|
+
}));
|
|
208
|
+
let n;
|
|
209
|
+
try {
|
|
210
|
+
const a = yield Promise.race([Promise.resolve().then(() => r(o)), W(d.signal), new Promise((c) => {
|
|
211
|
+
n = setTimeout(() => c(!1), e.limits.approvalTimeoutMs);
|
|
212
|
+
})]);
|
|
213
|
+
if (t.signal.aborted)
|
|
214
|
+
throw g();
|
|
215
|
+
if (a !== !0)
|
|
216
|
+
throw new h(m.Forbidden, "用户拒绝了本次操作。", {
|
|
217
|
+
reason: "user_rejected"
|
|
218
|
+
});
|
|
219
|
+
} catch (a) {
|
|
220
|
+
throw a instanceof h ? a : new h(m.Forbidden, "操作确认失败,已取消本次操作。", {
|
|
221
|
+
reason: "user_rejected"
|
|
222
|
+
});
|
|
223
|
+
} finally {
|
|
224
|
+
clearTimeout(n), t.signal.removeEventListener("abort", s), d.abort(), t.timer.resume();
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
function Se({
|
|
229
|
+
pluginCode: e,
|
|
230
|
+
workspace: t
|
|
231
|
+
}) {
|
|
232
|
+
const r = {};
|
|
233
|
+
return V.forEach((d) => {
|
|
234
|
+
r[d] = (s, o, n) => {
|
|
235
|
+
let i = !1;
|
|
236
|
+
Ie(t, d, s, (c) => {
|
|
237
|
+
if (!i) {
|
|
238
|
+
i = !0;
|
|
239
|
+
try {
|
|
240
|
+
o(c);
|
|
241
|
+
} catch (v) {
|
|
242
|
+
console.error("[LocalFiles] callback failed", v);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}, f(u({}, n), {
|
|
246
|
+
pluginCode: e
|
|
247
|
+
}));
|
|
248
|
+
};
|
|
249
|
+
}), {
|
|
250
|
+
[e]: r
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
export {
|
|
254
|
+
Se as createLocalFilesPlugin
|
|
255
|
+
};
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
var b = (r, i, a) => new Promise((m, c) => {
|
|
2
|
+
var d = (t) => {
|
|
3
|
+
try {
|
|
4
|
+
u(a.next(t));
|
|
5
|
+
} catch (s) {
|
|
6
|
+
c(s);
|
|
7
|
+
}
|
|
8
|
+
}, e = (t) => {
|
|
9
|
+
try {
|
|
10
|
+
u(a.throw(t));
|
|
11
|
+
} catch (s) {
|
|
12
|
+
c(s);
|
|
13
|
+
}
|
|
14
|
+
}, u = (t) => t.done ? m(t.value) : Promise.resolve(t.value).then(d, e);
|
|
15
|
+
u((a = a.apply(r, i)).next());
|
|
16
|
+
});
|
|
17
|
+
import { v4 as _ } from "uuid";
|
|
18
|
+
import { HostBridgeAdapter as P } from "./adapters/HostBridgeAdapter.mjs";
|
|
19
|
+
import { LOCAL_PYTHON_FUNCTION_CODE as T, WORKSPACE_GRANT_ID as A, PYTHON_MAX_ARGS as R, PYTHON_DEFAULT_TIMEOUT_MS as L } from "./constants.mjs";
|
|
20
|
+
import { ToolError as o, ToolCode as n, cancelledError as w, workspaceNotGranted as O, toToolError as q } from "./errors.mjs";
|
|
21
|
+
import { assertGrantId as F, normalizeWorkspacePath as M } from "./security/pathPolicy.mjs";
|
|
22
|
+
import { validateToolInput as C } from "./validate.mjs";
|
|
23
|
+
const S = /^[\p{L}\p{N}_./:@=+\-,]+$/u, B = {
|
|
24
|
+
type: "object",
|
|
25
|
+
required: ["grantId", "path"],
|
|
26
|
+
properties: {
|
|
27
|
+
grantId: {
|
|
28
|
+
type: "string",
|
|
29
|
+
enum: [A]
|
|
30
|
+
},
|
|
31
|
+
path: {
|
|
32
|
+
type: "string",
|
|
33
|
+
minLength: 1
|
|
34
|
+
},
|
|
35
|
+
args: {
|
|
36
|
+
type: "array",
|
|
37
|
+
items: {
|
|
38
|
+
type: "string",
|
|
39
|
+
minLength: 1
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
timeoutMs: {
|
|
43
|
+
type: "integer",
|
|
44
|
+
minimum: 1e3,
|
|
45
|
+
maximum: 12e4
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
function G(r) {
|
|
50
|
+
const i = r instanceof DOMException ? r.name : "", a = r instanceof Error ? r.message : "";
|
|
51
|
+
switch (i) {
|
|
52
|
+
case "NotFoundError":
|
|
53
|
+
return new o(n.NotFound, "脚本不存在。");
|
|
54
|
+
case "TypeMismatchError":
|
|
55
|
+
return new o(n.BadRequest, "只能运行 .py 文件。");
|
|
56
|
+
case "SecurityError":
|
|
57
|
+
return new o(n.BadRequest, "脚本路径不合法。");
|
|
58
|
+
case "AbortError":
|
|
59
|
+
return a.includes("已有") ? new o(n.TooManyRequests, "已有一个脚本在沙箱里运行。") : new o(n.Timeout, "脚本运行超时,已中止。");
|
|
60
|
+
default:
|
|
61
|
+
return new o(n.NotImplemented, "当前环境不能运行本地脚本。");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function j(r, i, a, m, c) {
|
|
65
|
+
return b(this, null, function* () {
|
|
66
|
+
if (!i)
|
|
67
|
+
throw new o(n.Forbidden, "当前环境未提供脚本运行确认,无法执行。", {
|
|
68
|
+
reason: "approval_unavailable"
|
|
69
|
+
});
|
|
70
|
+
if (c.aborted)
|
|
71
|
+
throw w();
|
|
72
|
+
const d = new AbortController(), e = () => d.abort();
|
|
73
|
+
c.addEventListener("abort", e, {
|
|
74
|
+
once: !0
|
|
75
|
+
});
|
|
76
|
+
let u;
|
|
77
|
+
try {
|
|
78
|
+
const t = yield Promise.race([Promise.resolve().then(() => {
|
|
79
|
+
var s;
|
|
80
|
+
return i({
|
|
81
|
+
requestId: m.requestId,
|
|
82
|
+
sessionId: m.sessionId,
|
|
83
|
+
path: a.path,
|
|
84
|
+
args: a.args,
|
|
85
|
+
workspaceName: (s = r.displayName) != null ? s : "",
|
|
86
|
+
signal: d.signal
|
|
87
|
+
});
|
|
88
|
+
}), new Promise((s) => {
|
|
89
|
+
u = setTimeout(() => s(!1), r.limits.approvalTimeoutMs);
|
|
90
|
+
})]);
|
|
91
|
+
if (c.aborted)
|
|
92
|
+
throw w();
|
|
93
|
+
if (t !== !0)
|
|
94
|
+
throw new o(n.Forbidden, "用户拒绝了本次脚本运行。", {
|
|
95
|
+
reason: "user_rejected"
|
|
96
|
+
});
|
|
97
|
+
} catch (t) {
|
|
98
|
+
throw t instanceof o ? t : new o(n.Forbidden, "脚本运行确认失败,已取消本次运行。", {
|
|
99
|
+
reason: "user_rejected"
|
|
100
|
+
});
|
|
101
|
+
} finally {
|
|
102
|
+
clearTimeout(u), c.removeEventListener("abort", e), d.abort();
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
function D(r, i, a, m, c) {
|
|
107
|
+
return b(this, null, function* () {
|
|
108
|
+
var u, t, s, g;
|
|
109
|
+
const d = new AbortController(), e = () => d.abort();
|
|
110
|
+
(u = m.signal) == null || u.addEventListener("abort", e);
|
|
111
|
+
try {
|
|
112
|
+
const l = typeof i == "string" ? JSON.parse(i) : i;
|
|
113
|
+
if (l && typeof l == "object" && !Array.isArray(l)) {
|
|
114
|
+
const h = l;
|
|
115
|
+
(h.grantId === void 0 || h.grantId === null || h.grantId === "") && (h.grantId = A);
|
|
116
|
+
}
|
|
117
|
+
const f = C(l, B);
|
|
118
|
+
F(f.grantId);
|
|
119
|
+
const p = M(f.path);
|
|
120
|
+
if (!p.toLowerCase().endsWith(".py"))
|
|
121
|
+
throw new o(n.BadRequest, "只能运行工程内已有的 .py 文件。");
|
|
122
|
+
const y = (t = f.args) != null ? t : [];
|
|
123
|
+
if (y.length > R || y.some((h) => !S.test(h)))
|
|
124
|
+
throw new o(n.BadRequest, "脚本参数不合法。每个参数单独填写,不能包含空格或 shell 语法。");
|
|
125
|
+
const E = r.sensitive.match(p, "read");
|
|
126
|
+
if (E)
|
|
127
|
+
throw new o(n.Forbidden, "该脚本被列为敏感文件,不能运行。", {
|
|
128
|
+
reason: "sensitive_file",
|
|
129
|
+
ruleId: E.id
|
|
130
|
+
});
|
|
131
|
+
if (yield r.ready, d.signal.aborted)
|
|
132
|
+
throw w();
|
|
133
|
+
const I = r.adapter;
|
|
134
|
+
if (!I)
|
|
135
|
+
throw O();
|
|
136
|
+
if (!(I instanceof P))
|
|
137
|
+
throw new o(n.NotImplemented, "当前环境不能运行本地脚本。");
|
|
138
|
+
yield j(r, c, {
|
|
139
|
+
path: p,
|
|
140
|
+
args: y
|
|
141
|
+
}, m, d.signal);
|
|
142
|
+
const v = yield I.runPython(p, y, (s = f.timeoutMs) != null ? s : L, d.signal);
|
|
143
|
+
r.notifyFilesChanged();
|
|
144
|
+
const N = {
|
|
145
|
+
code: n.Ok,
|
|
146
|
+
message: "ok",
|
|
147
|
+
data: v
|
|
148
|
+
};
|
|
149
|
+
a(N);
|
|
150
|
+
} catch (l) {
|
|
151
|
+
const f = d.signal.aborted ? w() : l instanceof SyntaxError ? new o(n.BadRequest, "参数不是合法的 JSON 对象。") : l instanceof o ? l : G(l), p = q(f);
|
|
152
|
+
a({
|
|
153
|
+
code: p.code,
|
|
154
|
+
message: p.message,
|
|
155
|
+
data: p.data
|
|
156
|
+
});
|
|
157
|
+
} finally {
|
|
158
|
+
(g = m.signal) == null || g.removeEventListener("abort", e);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
function X({
|
|
163
|
+
pluginCode: r,
|
|
164
|
+
workspace: i,
|
|
165
|
+
onApprovalRequired: a
|
|
166
|
+
}) {
|
|
167
|
+
const m = (c, d, e) => {
|
|
168
|
+
var s, g, l;
|
|
169
|
+
let u = !1;
|
|
170
|
+
D(i, c, (f) => {
|
|
171
|
+
if (!u) {
|
|
172
|
+
u = !0;
|
|
173
|
+
try {
|
|
174
|
+
d(f);
|
|
175
|
+
} catch (p) {
|
|
176
|
+
console.error("[LocalPython] callback failed", p);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}, {
|
|
180
|
+
requestId: (s = e == null ? void 0 : e.requestId) != null ? s : _(),
|
|
181
|
+
applicationId: (g = e == null ? void 0 : e.applicationId) != null ? g : i.applicationId,
|
|
182
|
+
sessionId: (l = e == null ? void 0 : e.sessionId) != null ? l : "",
|
|
183
|
+
pluginCode: r,
|
|
184
|
+
functionCode: T,
|
|
185
|
+
signal: e == null ? void 0 : e.signal
|
|
186
|
+
}, a);
|
|
187
|
+
};
|
|
188
|
+
return {
|
|
189
|
+
[r]: {
|
|
190
|
+
[T]: m
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
export {
|
|
195
|
+
X as createLocalPythonPlugin
|
|
196
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
var i = Object.defineProperty;
|
|
2
|
+
var E = (r, t, e) => t in r ? i(r, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[t] = e;
|
|
3
|
+
var a = (r, t, e) => (E(r, typeof t != "symbol" ? t + "" : t, e), e);
|
|
4
|
+
var f = /* @__PURE__ */ ((r) => (r[r.Ok = 0] = "Ok", r[r.BadRequest = 400] = "BadRequest", r[r.Forbidden = 403] = "Forbidden", r[r.NotFound = 404] = "NotFound", r[r.Timeout = 408] = "Timeout", r[r.Conflict = 409] = "Conflict", r[r.TooLarge = 413] = "TooLarge", r[r.TooManyRequests = 429] = "TooManyRequests", r[r.Cancelled = 499] = "Cancelled", r[r.Internal = 500] = "Internal", r[r.NotImplemented = 501] = "NotImplemented", r))(f || {});
|
|
5
|
+
class n extends Error {
|
|
6
|
+
constructor(e, u, s) {
|
|
7
|
+
super(u);
|
|
8
|
+
a(this, "code");
|
|
9
|
+
a(this, "data");
|
|
10
|
+
this.name = "ToolError", this.code = e, this.data = s;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
const w = "尚未授权工作文件夹,请先在助手中选择或恢复访问工作文件夹。";
|
|
14
|
+
function m() {
|
|
15
|
+
return new n(403, w, {
|
|
16
|
+
reason: "workspace_not_granted"
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function c() {
|
|
20
|
+
return new n(499, "操作已取消。");
|
|
21
|
+
}
|
|
22
|
+
function N(r) {
|
|
23
|
+
if (r != null && r.aborted)
|
|
24
|
+
throw c();
|
|
25
|
+
}
|
|
26
|
+
function o(r) {
|
|
27
|
+
if (r instanceof n)
|
|
28
|
+
return r;
|
|
29
|
+
switch (r && typeof r == "object" && "name" in r ? String(r.name) : "") {
|
|
30
|
+
case "NotFoundError":
|
|
31
|
+
return new n(404, "文件或目录不存在。");
|
|
32
|
+
case "TypeMismatchError":
|
|
33
|
+
return new n(400, "路径类型不匹配:目标是目录而不是文件,或路径中的某一段不是目录。");
|
|
34
|
+
case "NotAllowedError":
|
|
35
|
+
case "SecurityError":
|
|
36
|
+
return m();
|
|
37
|
+
case "AbortError":
|
|
38
|
+
return c();
|
|
39
|
+
case "NoModificationAllowedError":
|
|
40
|
+
case "InvalidModificationError":
|
|
41
|
+
case "InvalidStateError":
|
|
42
|
+
return new n(403, "文件当前不可写,可能正被其他程序占用或为只读。");
|
|
43
|
+
case "QuotaExceededError":
|
|
44
|
+
return new n(413, "磁盘空间不足或超出写入配额。");
|
|
45
|
+
default:
|
|
46
|
+
return new n(500, "本地文件操作失败,请稍后重试。");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export {
|
|
50
|
+
f as ToolCode,
|
|
51
|
+
n as ToolError,
|
|
52
|
+
w as WORKSPACE_NOT_GRANTED_MESSAGE,
|
|
53
|
+
c as cancelledError,
|
|
54
|
+
N as throwIfAborted,
|
|
55
|
+
o as toToolError,
|
|
56
|
+
m as workspaceNotGranted
|
|
57
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { HostBridgeAdapter as f } from "../adapters/HostBridgeAdapter.mjs";
|
|
2
|
+
import { getHostWebView as m, HOST_CHANNEL as g, parseHostMessage as y } from "./protocol.mjs";
|
|
3
|
+
let t;
|
|
4
|
+
function c(s) {
|
|
5
|
+
t == null || t(), t = void 0;
|
|
6
|
+
const i = m();
|
|
7
|
+
if (!i)
|
|
8
|
+
return () => {
|
|
9
|
+
};
|
|
10
|
+
const n = new f(i), d = (p) => {
|
|
11
|
+
const e = y(p.data);
|
|
12
|
+
if (e) {
|
|
13
|
+
if (e.type === "workspace") {
|
|
14
|
+
const r = e.granted === !0, o = typeof e.displayName == "string" ? e.displayName : "";
|
|
15
|
+
r ? (n.displayName = o || "工程目录", (s.status !== "granted" || s.displayName !== n.displayName) && s.attachAdapter(n, n.displayName)) : s.status === "granted" && s.clear();
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (e.type === "fs-changed") {
|
|
19
|
+
const r = Array.isArray(e.paths) ? e.paths.filter((o) => typeof o == "string") : [];
|
|
20
|
+
s.notifyFilesChanged(r);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
typeof e.id == "string" && n.settle({
|
|
24
|
+
channel: g,
|
|
25
|
+
id: e.id,
|
|
26
|
+
ok: e.ok !== !1,
|
|
27
|
+
name: typeof e.name == "string" ? e.name : void 0,
|
|
28
|
+
entries: e.entries,
|
|
29
|
+
entry: e.entry,
|
|
30
|
+
contentBase64: typeof e.contentBase64 == "string" ? e.contentBase64 : void 0,
|
|
31
|
+
exitCode: typeof e.exitCode == "number" ? e.exitCode : void 0,
|
|
32
|
+
timedOut: e.timedOut === !0,
|
|
33
|
+
stdout: typeof e.stdout == "string" ? e.stdout : void 0,
|
|
34
|
+
stderr: typeof e.stderr == "string" ? e.stderr : void 0,
|
|
35
|
+
message: typeof e.message == "string" ? e.message : void 0
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
i.addEventListener("message", d), i.postMessage({
|
|
40
|
+
channel: g,
|
|
41
|
+
type: "hello"
|
|
42
|
+
});
|
|
43
|
+
const a = () => {
|
|
44
|
+
i.removeEventListener("message", d), t === a && (t = void 0);
|
|
45
|
+
};
|
|
46
|
+
return t = a, a;
|
|
47
|
+
}
|
|
48
|
+
export {
|
|
49
|
+
c as connectHostBridge
|
|
50
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const n = "glodon-workspace";
|
|
2
|
+
function i(t) {
|
|
3
|
+
let e = t;
|
|
4
|
+
if (typeof e == "string")
|
|
5
|
+
try {
|
|
6
|
+
e = JSON.parse(e);
|
|
7
|
+
} catch (r) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
if (!e || typeof e != "object")
|
|
11
|
+
return;
|
|
12
|
+
const o = e;
|
|
13
|
+
if (o.channel === n)
|
|
14
|
+
return o;
|
|
15
|
+
}
|
|
16
|
+
function s() {
|
|
17
|
+
var e;
|
|
18
|
+
const t = (e = globalThis.chrome) == null ? void 0 : e.webview;
|
|
19
|
+
if (!(!t || typeof t.postMessage != "function" || typeof t.addEventListener != "function"))
|
|
20
|
+
return t;
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
n as HOST_CHANNEL,
|
|
24
|
+
s as getHostWebView,
|
|
25
|
+
i as parseHostMessage
|
|
26
|
+
};
|