gm-skill 2.0.2025 → 2.0.2027
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/AGENTS.md +7 -11
- package/bin/bootstrap.js +1 -1
- package/bin/install.js +31 -9
- package/bin/plugkit-slim.wasm.sha256 +1 -1
- package/bin/plugkit.version +1 -1
- package/bin/plugkit.wasm.sha256 +1 -1
- package/gm-plugkit/bootstrap.js +35 -152
- package/gm-plugkit/cli.js +31 -168
- package/gm-plugkit/package.json +3 -5
- package/gm-plugkit/plugkit-slim.wasm.sha256 +1 -1
- package/gm-plugkit/plugkit.version +1 -1
- package/gm.json +2 -2
- package/package.json +1 -3
- package/skills/gm/SKILL.md +4 -4
- package/gm-plugkit/plugkit-wasm-wrapper.js +0 -4939
- package/gm-plugkit/wrapper/cdp-eval.js +0 -123
- package/gm-plugkit/wrapper/fs-atomic.js +0 -26
- package/gm-plugkit/wrapper/kv-store.js +0 -81
- package/gm-plugkit/wrapper/task-manager.js +0 -272
- package/gm-plugkit/wrapper/wasi-shim.js +0 -377
- package/gm-plugkit/wrapper/wasm-bridge.js +0 -71
|
@@ -1,377 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import crypto from 'crypto';
|
|
4
|
-
|
|
5
|
-
function wasiFilesystemRootFor(gmToolsRoot) {
|
|
6
|
-
const projectSlug = crypto.createHash('sha256')
|
|
7
|
-
.update(String(process.env.CLAUDE_PROJECT_DIR || process.cwd()).toLowerCase().replace(/\\/g, '/'))
|
|
8
|
-
.digest('hex').slice(0, 16);
|
|
9
|
-
return path.join(gmToolsRoot, 'wasi-fs', projectSlug);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function makeWasiResolvePath(wasiFilesystemRoot) {
|
|
13
|
-
return function wasiResolvePath(relPath) {
|
|
14
|
-
const rel = String(relPath || '').replace(/\\/g, '/').replace(/^\/+/, '');
|
|
15
|
-
const resolved = path.resolve(wasiFilesystemRoot, rel);
|
|
16
|
-
const rootResolved = path.resolve(wasiFilesystemRoot) + path.sep;
|
|
17
|
-
if (resolved !== path.resolve(wasiFilesystemRoot) && !resolved.startsWith(rootResolved)) {
|
|
18
|
-
throw new Error(`wasi-path-traversal-refused: ${relPath} escapes ${wasiFilesystemRoot}`);
|
|
19
|
-
}
|
|
20
|
-
return resolved;
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function createWasiShim(instanceRef, ctx) {
|
|
25
|
-
const { wasiFilesystemRoot, wasiOpenFiles, wasiNextFdRef, wasmAbortFlag, spoolDirForSentinel, currentVerbContextRef } = ctx;
|
|
26
|
-
const wasiResolvePath = makeWasiResolvePath(wasiFilesystemRoot);
|
|
27
|
-
const getMemory = () => instanceRef.value.exports.memory.buffer;
|
|
28
|
-
const shim = {
|
|
29
|
-
proc_exit: (code) => {
|
|
30
|
-
wasmAbortFlag.aborted = true;
|
|
31
|
-
wasmAbortFlag.code = code;
|
|
32
|
-
try {
|
|
33
|
-
const spoolDir = spoolDirForSentinel();
|
|
34
|
-
fs.mkdirSync(spoolDir, { recursive: true });
|
|
35
|
-
fs.writeFileSync(path.join(spoolDir, '.wasm-abort.json'), JSON.stringify({
|
|
36
|
-
ts: Date.now(),
|
|
37
|
-
exit_code: code,
|
|
38
|
-
verb_in_flight: currentVerbContextRef.value,
|
|
39
|
-
}));
|
|
40
|
-
} catch (_) {}
|
|
41
|
-
try { console.error(`[plugkit-wasm] wasm proc_exit(${code}) intercepted; throwing to abort current verb without killing watcher`); } catch (_) {}
|
|
42
|
-
throw new Error(`wasm proc_exit(${code}) during verb ${currentVerbContextRef.value && currentVerbContextRef.value.verb}`);
|
|
43
|
-
},
|
|
44
|
-
fd_write: (fd, iovs_ptr, iovs_len, nwritten_ptr) => {
|
|
45
|
-
try {
|
|
46
|
-
const buf = getMemory();
|
|
47
|
-
const dv = new DataView(buf);
|
|
48
|
-
const chunks = [];
|
|
49
|
-
let total = 0;
|
|
50
|
-
const iovsBase = iovs_ptr >>> 0; // >>>0: high-bit iovs pointer is negative in JS -> getUint32 would throw
|
|
51
|
-
for (let i = 0; i < iovs_len; i++) {
|
|
52
|
-
const base = iovsBase + i * 8;
|
|
53
|
-
const ptr = dv.getUint32(base, true);
|
|
54
|
-
const len = dv.getUint32(base + 4, true);
|
|
55
|
-
if (len > 0 && ptr + len <= buf.byteLength) {
|
|
56
|
-
chunks.push(new Uint8Array(buf, ptr, len).slice());
|
|
57
|
-
total += len;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
const merged = new Uint8Array(total);
|
|
61
|
-
let off = 0;
|
|
62
|
-
for (const c of chunks) { merged.set(c, off); off += c.length; }
|
|
63
|
-
const text = new TextDecoder('utf-8').decode(merged);
|
|
64
|
-
if (fd === 2) process.stderr.write(text);
|
|
65
|
-
else process.stdout.write(text);
|
|
66
|
-
new DataView(getMemory()).setUint32(nwritten_ptr, total, true);
|
|
67
|
-
return 0;
|
|
68
|
-
} catch (e) {
|
|
69
|
-
return 28;
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
random_get: (buf_ptr, buf_len) => {
|
|
73
|
-
try {
|
|
74
|
-
crypto.randomFillSync(new Uint8Array(getMemory(), buf_ptr >>> 0, buf_len >>> 0)); // >>>0: high-bit ptr is negative in JS
|
|
75
|
-
return 0;
|
|
76
|
-
} catch (e) {
|
|
77
|
-
return 28;
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
clock_time_get: (clock_id, precision, time_ptr) => {
|
|
81
|
-
try {
|
|
82
|
-
const ns = BigInt(Date.now()) * 1000000n;
|
|
83
|
-
new DataView(getMemory()).setBigUint64(time_ptr >>> 0, ns, true); // >>>0: high-bit ptr is negative in JS
|
|
84
|
-
return 0;
|
|
85
|
-
} catch (e) {
|
|
86
|
-
return 28;
|
|
87
|
-
}
|
|
88
|
-
},
|
|
89
|
-
environ_get: () => 0,
|
|
90
|
-
environ_sizes_get: () => 0,
|
|
91
|
-
fd_prestat_get: (fd, buf_ptr) => {
|
|
92
|
-
if (fd !== 3) return 8;
|
|
93
|
-
try {
|
|
94
|
-
const dv = new DataView(getMemory());
|
|
95
|
-
dv.setUint8(buf_ptr, 0);
|
|
96
|
-
dv.setUint32(buf_ptr + 4, 1, true);
|
|
97
|
-
return 0;
|
|
98
|
-
} catch (e) { return 8; }
|
|
99
|
-
},
|
|
100
|
-
fd_prestat_dir_name: (fd, path_ptr, path_len) => {
|
|
101
|
-
if (fd !== 3) return 8;
|
|
102
|
-
try {
|
|
103
|
-
const buf = getMemory();
|
|
104
|
-
new Uint8Array(buf, path_ptr >>> 0, Math.min(path_len, 1)).set([0x2e]);
|
|
105
|
-
return 0;
|
|
106
|
-
} catch (e) { return 8; }
|
|
107
|
-
},
|
|
108
|
-
fd_close: (fd) => {
|
|
109
|
-
const entry = wasiOpenFiles.get(fd);
|
|
110
|
-
if (!entry) return 0;
|
|
111
|
-
try { fs.closeSync(entry.nodeFd); } catch (_) {}
|
|
112
|
-
wasiOpenFiles.delete(fd);
|
|
113
|
-
return 0;
|
|
114
|
-
},
|
|
115
|
-
fd_fdstat_get: (fd, stat_ptr) => {
|
|
116
|
-
try {
|
|
117
|
-
const dv = new DataView(getMemory());
|
|
118
|
-
const entry = wasiOpenFiles.get(fd);
|
|
119
|
-
dv.setUint8(stat_ptr, entry ? 4 : 0);
|
|
120
|
-
dv.setUint8(stat_ptr + 1, 0);
|
|
121
|
-
dv.setBigUint64(stat_ptr + 8, 0xffffffffffffffffn, true);
|
|
122
|
-
dv.setBigUint64(stat_ptr + 16, 0xffffffffffffffffn, true);
|
|
123
|
-
return 0;
|
|
124
|
-
} catch (e) { return 8; }
|
|
125
|
-
},
|
|
126
|
-
fd_fdstat_set_flags: () => 0,
|
|
127
|
-
fd_filestat_get: (fd, buf_ptr) => {
|
|
128
|
-
const entry = wasiOpenFiles.get(fd);
|
|
129
|
-
if (!entry) { if (process.env.PLUGKIT_DEBUG) console.error(`[plugkit-wasm] fd_filestat_get FAILED: no entry for fd=${fd}`); return 8; }
|
|
130
|
-
try {
|
|
131
|
-
const st = fs.fstatSync(entry.nodeFd);
|
|
132
|
-
const dv = new DataView(getMemory());
|
|
133
|
-
dv.setBigUint64(buf_ptr, 0n, true);
|
|
134
|
-
dv.setBigUint64(buf_ptr + 8, 0n, true);
|
|
135
|
-
dv.setUint8(buf_ptr + 16, 4);
|
|
136
|
-
dv.setBigUint64(buf_ptr + 24, 1n, true);
|
|
137
|
-
dv.setBigUint64(buf_ptr + 32, BigInt(st.size), true);
|
|
138
|
-
dv.setBigUint64(buf_ptr + 40, BigInt(Math.floor(st.atimeMs * 1e6)), true);
|
|
139
|
-
dv.setBigUint64(buf_ptr + 48, BigInt(Math.floor(st.mtimeMs * 1e6)), true);
|
|
140
|
-
dv.setBigUint64(buf_ptr + 56, BigInt(Math.floor(st.ctimeMs * 1e6)), true);
|
|
141
|
-
return 0;
|
|
142
|
-
} catch (e) { if (process.env.PLUGKIT_DEBUG) console.error(`[plugkit-wasm] fd_filestat_get FAILED: ${e && e.message}`); return 8; }
|
|
143
|
-
},
|
|
144
|
-
fd_seek: (fd, offset64, whence, newoffset_ptr) => {
|
|
145
|
-
const entry = wasiOpenFiles.get(fd);
|
|
146
|
-
if (!entry) { try { new DataView(getMemory()).setBigUint64(newoffset_ptr, 0n, true); } catch (_) {} return 8; }
|
|
147
|
-
try {
|
|
148
|
-
const offset = BigInt.asIntN(64, BigInt(offset64));
|
|
149
|
-
let base;
|
|
150
|
-
if (whence === 0) base = 0n;
|
|
151
|
-
else if (whence === 1) base = BigInt(entry.pos);
|
|
152
|
-
else base = BigInt(fs.fstatSync(entry.nodeFd).size);
|
|
153
|
-
const next = base + offset;
|
|
154
|
-
entry.pos = Number(next < 0n ? 0n : next);
|
|
155
|
-
new DataView(getMemory()).setBigUint64(newoffset_ptr, BigInt(entry.pos), true);
|
|
156
|
-
return 0;
|
|
157
|
-
} catch (e) { if (process.env.PLUGKIT_DEBUG) console.error(`[plugkit-wasm] fd_seek FAILED: ${e && e.message}`); return 8; }
|
|
158
|
-
},
|
|
159
|
-
fd_read: (fd, iovs_ptr, iovs_len, nread_ptr) => {
|
|
160
|
-
const entry = wasiOpenFiles.get(fd);
|
|
161
|
-
if (!entry) { try { new DataView(getMemory()).setUint32(nread_ptr, 0, true); } catch (_) {} return 8; }
|
|
162
|
-
try {
|
|
163
|
-
const buf = getMemory();
|
|
164
|
-
const dv = new DataView(buf);
|
|
165
|
-
let total = 0;
|
|
166
|
-
const iovsBase = iovs_ptr >>> 0;
|
|
167
|
-
for (let i = 0; i < iovs_len; i++) {
|
|
168
|
-
const base = iovsBase + i * 8;
|
|
169
|
-
const ptr = dv.getUint32(base, true) >>> 0;
|
|
170
|
-
const len = dv.getUint32(base + 4, true) >>> 0;
|
|
171
|
-
if (len === 0) continue;
|
|
172
|
-
const dest = Buffer.from(buf, ptr, len);
|
|
173
|
-
const n = fs.readSync(entry.nodeFd, dest, 0, len, entry.pos);
|
|
174
|
-
entry.pos += n;
|
|
175
|
-
total += n;
|
|
176
|
-
if (n < len) break;
|
|
177
|
-
}
|
|
178
|
-
dv.setUint32(nread_ptr, total, true);
|
|
179
|
-
return 0;
|
|
180
|
-
} catch (e) { return 8; }
|
|
181
|
-
},
|
|
182
|
-
fd_pread: (fd, iovs_ptr, iovs_len, offset64, nread_ptr) => {
|
|
183
|
-
const entry = wasiOpenFiles.get(fd);
|
|
184
|
-
if (!entry) { try { new DataView(getMemory()).setUint32(nread_ptr, 0, true); } catch (_) {} return 8; }
|
|
185
|
-
try {
|
|
186
|
-
const offset = Number(BigInt.asUintN(64, BigInt(offset64)));
|
|
187
|
-
const buf = getMemory();
|
|
188
|
-
const dv = new DataView(buf);
|
|
189
|
-
let total = 0;
|
|
190
|
-
const iovsBase = iovs_ptr >>> 0;
|
|
191
|
-
let pos = offset;
|
|
192
|
-
for (let i = 0; i < iovs_len; i++) {
|
|
193
|
-
const base = iovsBase + i * 8;
|
|
194
|
-
const ptr = dv.getUint32(base, true) >>> 0;
|
|
195
|
-
const len = dv.getUint32(base + 4, true) >>> 0;
|
|
196
|
-
if (len === 0) continue;
|
|
197
|
-
const dest = Buffer.from(buf, ptr, len);
|
|
198
|
-
const n = fs.readSync(entry.nodeFd, dest, 0, len, pos);
|
|
199
|
-
pos += n;
|
|
200
|
-
total += n;
|
|
201
|
-
if (n < len) break;
|
|
202
|
-
}
|
|
203
|
-
dv.setUint32(nread_ptr, total, true);
|
|
204
|
-
return 0;
|
|
205
|
-
} catch (e) { if (process.env.PLUGKIT_DEBUG) console.error(`[plugkit-wasm] fd_pread FAILED: ${e && e.message}`); return 8; }
|
|
206
|
-
},
|
|
207
|
-
fd_pwrite: (fd, iovs_ptr, iovs_len, offset64, nwritten_ptr) => {
|
|
208
|
-
const entry = wasiOpenFiles.get(fd);
|
|
209
|
-
if (!entry) { try { new DataView(getMemory()).setUint32(nwritten_ptr, 0, true); } catch (_) {} return 8; }
|
|
210
|
-
try {
|
|
211
|
-
const offset = Number(BigInt.asUintN(64, BigInt(offset64)));
|
|
212
|
-
const buf = getMemory();
|
|
213
|
-
const dv = new DataView(buf);
|
|
214
|
-
let total = 0;
|
|
215
|
-
const iovsBase = iovs_ptr >>> 0;
|
|
216
|
-
let pos = offset;
|
|
217
|
-
for (let i = 0; i < iovs_len; i++) {
|
|
218
|
-
const base = iovsBase + i * 8;
|
|
219
|
-
const ptr = dv.getUint32(base, true) >>> 0;
|
|
220
|
-
const len = dv.getUint32(base + 4, true) >>> 0;
|
|
221
|
-
if (len === 0) continue;
|
|
222
|
-
const src = Buffer.from(buf, ptr, len);
|
|
223
|
-
const n = fs.writeSync(entry.nodeFd, src, 0, len, pos);
|
|
224
|
-
pos += n;
|
|
225
|
-
total += n;
|
|
226
|
-
}
|
|
227
|
-
dv.setUint32(nwritten_ptr, total, true);
|
|
228
|
-
return 0;
|
|
229
|
-
} catch (e) { if (process.env.PLUGKIT_DEBUG) console.error(`[plugkit-wasm] fd_pwrite FAILED: ${e && e.message}`); return 8; }
|
|
230
|
-
},
|
|
231
|
-
fd_sync: (fd) => {
|
|
232
|
-
const entry = wasiOpenFiles.get(fd);
|
|
233
|
-
if (!entry) return 8;
|
|
234
|
-
try { fs.fsyncSync(entry.nodeFd); return 0; } catch (e) { if (process.env.PLUGKIT_DEBUG) console.error(`[plugkit-wasm] fd_sync FAILED: ${e && e.message}`); return 8; }
|
|
235
|
-
},
|
|
236
|
-
fd_datasync: (fd) => {
|
|
237
|
-
const entry = wasiOpenFiles.get(fd);
|
|
238
|
-
if (!entry) return 8;
|
|
239
|
-
try { fs.fdatasyncSync(entry.nodeFd); return 0; } catch (e) { return 8; }
|
|
240
|
-
},
|
|
241
|
-
fd_filestat_set_size: (fd, size64) => {
|
|
242
|
-
const entry = wasiOpenFiles.get(fd);
|
|
243
|
-
if (!entry) return 8;
|
|
244
|
-
try {
|
|
245
|
-
const size = Number(BigInt.asUintN(64, BigInt(size64)));
|
|
246
|
-
fs.ftruncateSync(entry.nodeFd, size);
|
|
247
|
-
return 0;
|
|
248
|
-
} catch (e) { if (process.env.PLUGKIT_DEBUG) console.error(`[plugkit-wasm] fd_filestat_set_size FAILED: ${e && e.message}`); return 8; }
|
|
249
|
-
},
|
|
250
|
-
path_create_directory: (_dirfd, path_ptr, path_len) => {
|
|
251
|
-
try {
|
|
252
|
-
const buf = getMemory();
|
|
253
|
-
const relPath = new TextDecoder('utf-8').decode(new Uint8Array(buf, path_ptr >>> 0, path_len >>> 0));
|
|
254
|
-
const absPath = wasiResolvePath(relPath);
|
|
255
|
-
fs.mkdirSync(absPath, { recursive: true });
|
|
256
|
-
return 0;
|
|
257
|
-
} catch (e) {
|
|
258
|
-
if (process.env.PLUGKIT_DEBUG) console.error(`[plugkit-wasm] path_create_directory FAILED: ${e && e.message}`);
|
|
259
|
-
return e && e.code === 'EEXIST' ? 0 : 8;
|
|
260
|
-
}
|
|
261
|
-
},
|
|
262
|
-
path_unlink_file: (_dirfd, path_ptr, path_len) => {
|
|
263
|
-
try {
|
|
264
|
-
const buf = getMemory();
|
|
265
|
-
const relPath = new TextDecoder('utf-8').decode(new Uint8Array(buf, path_ptr >>> 0, path_len >>> 0));
|
|
266
|
-
const absPath = wasiResolvePath(relPath);
|
|
267
|
-
fs.unlinkSync(absPath);
|
|
268
|
-
return 0;
|
|
269
|
-
} catch (e) {
|
|
270
|
-
return e && e.code === 'ENOENT' ? 44 : 8;
|
|
271
|
-
}
|
|
272
|
-
},
|
|
273
|
-
path_remove_directory: (_dirfd, path_ptr, path_len) => {
|
|
274
|
-
try {
|
|
275
|
-
const buf = getMemory();
|
|
276
|
-
const relPath = new TextDecoder('utf-8').decode(new Uint8Array(buf, path_ptr >>> 0, path_len >>> 0));
|
|
277
|
-
const absPath = wasiResolvePath(relPath);
|
|
278
|
-
fs.rmdirSync(absPath);
|
|
279
|
-
return 0;
|
|
280
|
-
} catch (e) {
|
|
281
|
-
if (e && e.code === 'ENOENT') return 44;
|
|
282
|
-
if (e && e.code === 'ENOTEMPTY') return 55;
|
|
283
|
-
return 8;
|
|
284
|
-
}
|
|
285
|
-
},
|
|
286
|
-
path_filestat_set_times: (_dirfd, _flags, path_ptr, path_len, atim64, mtim64, fst_flags) => {
|
|
287
|
-
try {
|
|
288
|
-
const buf = getMemory();
|
|
289
|
-
const relPath = new TextDecoder('utf-8').decode(new Uint8Array(buf, path_ptr >>> 0, path_len >>> 0));
|
|
290
|
-
const absPath = wasiResolvePath(relPath);
|
|
291
|
-
const FILESTAT_SET_ATIM = 0x1, FILESTAT_SET_ATIM_NOW = 0x2, FILESTAT_SET_MTIM = 0x4, FILESTAT_SET_MTIM_NOW = 0x8;
|
|
292
|
-
const st = fs.statSync(absPath);
|
|
293
|
-
const nowMs = Date.now();
|
|
294
|
-
let atimeMs = st.atimeMs;
|
|
295
|
-
let mtimeMs = st.mtimeMs;
|
|
296
|
-
if (fst_flags & FILESTAT_SET_ATIM_NOW) atimeMs = nowMs;
|
|
297
|
-
else if (fst_flags & FILESTAT_SET_ATIM) atimeMs = Number(BigInt.asUintN(64, BigInt(atim64))) / 1e6;
|
|
298
|
-
if (fst_flags & FILESTAT_SET_MTIM_NOW) mtimeMs = nowMs;
|
|
299
|
-
else if (fst_flags & FILESTAT_SET_MTIM) mtimeMs = Number(BigInt.asUintN(64, BigInt(mtim64))) / 1e6;
|
|
300
|
-
fs.utimesSync(absPath, atimeMs / 1000, mtimeMs / 1000);
|
|
301
|
-
return 0;
|
|
302
|
-
} catch (e) {
|
|
303
|
-
if (process.env.PLUGKIT_DEBUG) console.error(`[plugkit-wasm] path_filestat_set_times FAILED: ${e && e.message}`);
|
|
304
|
-
return e && e.code === 'ENOENT' ? 44 : 8;
|
|
305
|
-
}
|
|
306
|
-
},
|
|
307
|
-
path_open: (_dirfd, _dirflags, path_ptr, path_len, oflags, _rights_base, _rights_inherit, fdflags, opened_fd_ptr) => {
|
|
308
|
-
try {
|
|
309
|
-
const buf = getMemory();
|
|
310
|
-
const relPath = new TextDecoder('utf-8').decode(new Uint8Array(buf, path_ptr >>> 0, path_len >>> 0));
|
|
311
|
-
const absPath = wasiResolvePath(relPath);
|
|
312
|
-
fs.mkdirSync(path.dirname(absPath), { recursive: true });
|
|
313
|
-
const OFLAGS_CREAT = 1, OFLAGS_EXCL = 2, OFLAGS_TRUNC = 8;
|
|
314
|
-
let nodeFlags = 'r+';
|
|
315
|
-
const creat = (oflags & OFLAGS_CREAT) !== 0;
|
|
316
|
-
const excl = (oflags & OFLAGS_EXCL) !== 0;
|
|
317
|
-
const trunc = (oflags & OFLAGS_TRUNC) !== 0;
|
|
318
|
-
if (excl && creat) nodeFlags = 'wx+';
|
|
319
|
-
else if (trunc) nodeFlags = 'w+';
|
|
320
|
-
else if (creat) nodeFlags = fs.existsSync(absPath) ? 'r+' : 'w+';
|
|
321
|
-
else nodeFlags = 'r+';
|
|
322
|
-
if (process.env.PLUGKIT_DEBUG) console.error(`[plugkit-wasm] path_open: rel=${relPath} abs=${absPath} oflags=${oflags} nodeFlags=${nodeFlags}`);
|
|
323
|
-
const nodeFd = fs.openSync(absPath, nodeFlags);
|
|
324
|
-
const wasiFd = wasiNextFdRef.value++;
|
|
325
|
-
wasiOpenFiles.set(wasiFd, { nodeFd, pos: 0, path: absPath });
|
|
326
|
-
new DataView(buf).setUint32(opened_fd_ptr, wasiFd, true);
|
|
327
|
-
return 0;
|
|
328
|
-
} catch (e) {
|
|
329
|
-
if (process.env.PLUGKIT_DEBUG) console.error(`[plugkit-wasm] path_open FAILED: ${e && e.message}`);
|
|
330
|
-
return e && /ENOENT/.test(e.code || '') ? 44 : 8;
|
|
331
|
-
}
|
|
332
|
-
},
|
|
333
|
-
path_filestat_get: (_dirfd, _flags, path_ptr, path_len, buf_ptr) => {
|
|
334
|
-
try {
|
|
335
|
-
const buf = getMemory();
|
|
336
|
-
const relPath = new TextDecoder('utf-8').decode(new Uint8Array(buf, path_ptr >>> 0, path_len >>> 0));
|
|
337
|
-
const absPath = wasiResolvePath(relPath);
|
|
338
|
-
const st = fs.statSync(absPath);
|
|
339
|
-
const dv = new DataView(buf);
|
|
340
|
-
dv.setBigUint64(buf_ptr, 0n, true);
|
|
341
|
-
dv.setBigUint64(buf_ptr + 8, 0n, true);
|
|
342
|
-
dv.setUint8(buf_ptr + 16, st.isDirectory() ? 3 : 4);
|
|
343
|
-
dv.setBigUint64(buf_ptr + 24, 1n, true);
|
|
344
|
-
dv.setBigUint64(buf_ptr + 32, BigInt(st.size), true);
|
|
345
|
-
dv.setBigUint64(buf_ptr + 40, BigInt(Math.floor(st.atimeMs * 1e6)), true);
|
|
346
|
-
dv.setBigUint64(buf_ptr + 48, BigInt(Math.floor(st.mtimeMs * 1e6)), true);
|
|
347
|
-
dv.setBigUint64(buf_ptr + 56, BigInt(Math.floor(st.ctimeMs * 1e6)), true);
|
|
348
|
-
return 0;
|
|
349
|
-
} catch (e) {
|
|
350
|
-
return e && /ENOENT/.test(e.code || '') ? 44 : 8;
|
|
351
|
-
}
|
|
352
|
-
},
|
|
353
|
-
poll_oneoff: () => 0,
|
|
354
|
-
sched_yield: () => 0,
|
|
355
|
-
};
|
|
356
|
-
if (process.env.PLUGKIT_DEBUG_WASI) {
|
|
357
|
-
for (const k of Object.keys(shim)) {
|
|
358
|
-
const orig = shim[k];
|
|
359
|
-
shim[k] = (...args) => {
|
|
360
|
-
const r = orig(...args);
|
|
361
|
-
try { console.error(`[plugkit-wasm] wasi.${k}(${args.map(a => typeof a === 'bigint' ? a.toString() : a).join(',')}) -> ${r}`); } catch (_) {}
|
|
362
|
-
return r;
|
|
363
|
-
};
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
return new Proxy(shim, {
|
|
367
|
-
get(target, prop) {
|
|
368
|
-
if (prop in target) return target[prop];
|
|
369
|
-
return (...args) => {
|
|
370
|
-
console.error(`[plugkit-wasm] unimplemented WASI call: ${String(prop)} args=${args.length}`);
|
|
371
|
-
return 8;
|
|
372
|
-
};
|
|
373
|
-
}
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
export { wasiFilesystemRootFor, makeWasiResolvePath, createWasiShim };
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
function guardWasmRange(buffer, ptr, len, where) {
|
|
2
|
-
const total = buffer.byteLength;
|
|
3
|
-
if (!Number.isInteger(ptr) || !Number.isInteger(len) || ptr < 0 || len < 0 || ptr + len > total) {
|
|
4
|
-
throw new Error(`wasm-memory-read-out-of-bounds at ${where}: ptr=${ptr} len=${len} buffer=${total} -- corrupt (ptr,len) from wasm, refusing the read instead of crashing the dispatch loop`);
|
|
5
|
-
}
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function decodeWasmResult(instance, result, where) {
|
|
9
|
-
const u = BigInt.asUintN(64, BigInt(result));
|
|
10
|
-
const ptr = Number(u & 0xffffffffn);
|
|
11
|
-
const len = Number(u >> 32n);
|
|
12
|
-
if (ptr === 0 || len === 0) return '';
|
|
13
|
-
const buffer = instance.exports.memory.buffer;
|
|
14
|
-
guardWasmRange(buffer, ptr, len, where);
|
|
15
|
-
const out = new TextDecoder().decode(new Uint8Array(buffer, ptr, len));
|
|
16
|
-
try { instance.exports.plugkit_free(ptr, len); } catch (_) {}
|
|
17
|
-
return out;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function writeWasmInput(instance, bytes, where) {
|
|
21
|
-
if (bytes.length === 0) return 0;
|
|
22
|
-
const ptr = instance.exports.plugkit_alloc(bytes.length) >>> 0;
|
|
23
|
-
if (ptr === 0) throw new Error(`wasm-alloc-failed at ${where}: plugkit_alloc returned 0 (wasm OOM)`);
|
|
24
|
-
guardWasmRange(instance.exports.memory.buffer, ptr, bytes.length, `${where}:writeWasmInput`);
|
|
25
|
-
new Uint8Array(instance.exports.memory.buffer, ptr, bytes.length).set(bytes);
|
|
26
|
-
return ptr;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function readWasmBytes(instance, ptr, len) {
|
|
30
|
-
if (ptr === 0 || len === 0) return new Uint8Array(0);
|
|
31
|
-
const buffer = instance.exports.memory.buffer;
|
|
32
|
-
guardWasmRange(buffer, ptr, len, 'readWasmBytes');
|
|
33
|
-
return new Uint8Array(buffer, ptr, len).slice();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function readWasmStr(instance, ptr, len) {
|
|
37
|
-
if (ptr === 0 || len === 0) return '';
|
|
38
|
-
const buffer = instance.exports.memory.buffer;
|
|
39
|
-
guardWasmRange(buffer, ptr, len, 'readWasmStr');
|
|
40
|
-
const bytes = new Uint8Array(buffer, ptr, len);
|
|
41
|
-
return new TextDecoder('utf-8').decode(bytes);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function writeWasmBytes(instance, bytes) {
|
|
45
|
-
if (bytes.length === 0) return 0n;
|
|
46
|
-
const ptr = instance.exports.plugkit_alloc(bytes.length) >>> 0;
|
|
47
|
-
if (ptr === 0) return 0n;
|
|
48
|
-
guardWasmRange(instance.exports.memory.buffer, ptr, bytes.length, 'writeWasmBytes');
|
|
49
|
-
new Uint8Array(instance.exports.memory.buffer, ptr, bytes.length).set(bytes);
|
|
50
|
-
return (BigInt(ptr) & 0xffffffffn) | (BigInt(bytes.length) << 32n);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function writeWasmStr(instance, str) {
|
|
54
|
-
if (!str) return 0n;
|
|
55
|
-
return writeWasmBytes(instance, new TextEncoder().encode(str));
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function writeWasmJson(instance, value) {
|
|
59
|
-
return writeWasmStr(instance, JSON.stringify(value));
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export {
|
|
63
|
-
guardWasmRange,
|
|
64
|
-
decodeWasmResult,
|
|
65
|
-
writeWasmInput,
|
|
66
|
-
readWasmBytes,
|
|
67
|
-
readWasmStr,
|
|
68
|
-
writeWasmBytes,
|
|
69
|
-
writeWasmStr,
|
|
70
|
-
writeWasmJson,
|
|
71
|
-
};
|