jinzd-ai-cli 0.4.234 → 0.4.236
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 +5 -5
- package/dist/{auth-FSTAKSYF.js → auth-PE3Z5OHS.js} +1 -1
- package/dist/{batch-T3FRX4B6.js → batch-HZI7QAE7.js} +2 -2
- package/dist/{chunk-AFT6VFMI.js → chunk-7VAE3I3D.js} +1 -1
- package/dist/{chunk-3KTSJ2EL.js → chunk-CGQARJMP.js} +1 -1
- package/dist/{chunk-ETJ5X6V7.js → chunk-MFWAL5S2.js} +1 -1
- package/dist/{chunk-6MJMHHRK.js → chunk-O4QYY6SF.js} +3 -3
- package/dist/{chunk-5DTEEWYC.js → chunk-QDP3NUPX.js} +3 -3
- package/dist/{chunk-JVKAL5Q3.js → chunk-RYQBBEMM.js} +33 -3
- package/dist/{chunk-E5RLXMSU.js → chunk-SBSWH2EG.js} +89 -56
- package/dist/{chunk-TAXIG7HH.js → chunk-SCFGLRB3.js} +1 -1
- package/dist/{chunk-II6RZRTF.js → chunk-T6EIBUKW.js} +115 -18
- package/dist/{chunk-5VPRZMZB.js → chunk-TT7YURG3.js} +3 -3
- package/dist/{chunk-L5PNAQ6O.js → chunk-VBAW4ZPY.js} +1 -1
- package/dist/{ci-GJ53GPLA.js → ci-FYLCHRN3.js} +4 -4
- package/dist/{ci-format-AXE4QCI6.js → ci-format-TH2ZTFKU.js} +2 -2
- package/dist/{constants-DC4EXFSB.js → constants-BF6YNKRW.js} +1 -1
- package/dist/{doctor-cli-HKREND6Q.js → doctor-cli-B6GE4BYJ.js} +4 -4
- package/dist/electron-server.js +312 -151
- package/dist/{hub-LTTKRGZC.js → hub-QBQCKEPE.js} +1 -1
- package/dist/index.js +2439 -2437
- package/dist/{pr-4VODJVRV.js → pr-KV2WK7SU.js} +4 -4
- package/dist/{run-tests-QR2PYR2P.js → run-tests-DI6WEYHX.js} +1 -1
- package/dist/{run-tests-G5BNTMWQ.js → run-tests-MEHC73SQ.js} +2 -2
- package/dist/{server-EO6VQHKL.js → server-ETIGAZX5.js} +4 -4
- package/dist/{server-64WZVZZN.js → server-KZAP5JN3.js} +34 -33
- package/dist/{task-orchestrator-4INCZMLT.js → task-orchestrator-WS724BUX.js} +4 -4
- package/dist/{usage-T3HFMNNV.js → usage-DHZR5PG7.js} +2 -2
- package/package.json +2 -4
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
CONFIG_DIR_NAME,
|
|
4
4
|
PLUGINS_DIR_NAME
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-CGQARJMP.js";
|
|
6
6
|
import {
|
|
7
7
|
atomicWriteFileSync
|
|
8
8
|
} from "./chunk-IW3Q7AE5.js";
|
|
@@ -121,8 +121,8 @@ function installFlushOnExit() {
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
// src/plugins/plugin-manager.ts
|
|
124
|
-
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readdirSync, readFileSync as readFileSync2, cpSync, rmSync, statSync } from "fs";
|
|
125
|
-
import { basename, dirname as dirname2, join as join2, resolve } from "path";
|
|
124
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readdirSync, readFileSync as readFileSync2, realpathSync, cpSync, rmSync, statSync } from "fs";
|
|
125
|
+
import { basename, dirname as dirname2, join as join2, relative, resolve, sep } from "path";
|
|
126
126
|
import { createHash } from "crypto";
|
|
127
127
|
import { z } from "zod";
|
|
128
128
|
var MANIFEST_RELATIVE = ".aicli-plugin/plugin.json";
|
|
@@ -192,20 +192,117 @@ function statePath(configDir) {
|
|
|
192
192
|
}
|
|
193
193
|
function loadState(configDir) {
|
|
194
194
|
const file = statePath(configDir);
|
|
195
|
-
if (!existsSync2(file)) return { version:
|
|
195
|
+
if (!existsSync2(file)) return { version: 2, plugins: [] };
|
|
196
196
|
try {
|
|
197
197
|
const parsed = JSON.parse(readFileSync2(file, "utf-8"));
|
|
198
|
-
|
|
198
|
+
const rawPlugins = Array.isArray(parsed.plugins) ? parsed.plugins : [];
|
|
199
|
+
return { version: 2, plugins: rawPlugins.map((p) => migrateEntry(p)) };
|
|
199
200
|
} catch {
|
|
200
|
-
return { version:
|
|
201
|
+
return { version: 2, plugins: [] };
|
|
201
202
|
}
|
|
202
203
|
}
|
|
204
|
+
function migrateEntry(entry) {
|
|
205
|
+
const name = String(entry.name ?? "");
|
|
206
|
+
const contentHash = typeof entry.contentHash === "string" ? entry.contentHash : void 0;
|
|
207
|
+
const legacyHash = typeof entry.hash === "string" ? entry.hash : void 0;
|
|
208
|
+
const trusted = contentHash ? entry.trusted === true : false;
|
|
209
|
+
return {
|
|
210
|
+
name,
|
|
211
|
+
enabled: entry.enabled === true,
|
|
212
|
+
trusted,
|
|
213
|
+
contentHash: contentHash ?? legacyHash,
|
|
214
|
+
installedAt: String(entry.installedAt ?? (/* @__PURE__ */ new Date(0)).toISOString()),
|
|
215
|
+
trustedAt: trusted && entry.trustedAt ? String(entry.trustedAt) : void 0,
|
|
216
|
+
enabledAt: entry.enabledAt ? String(entry.enabledAt) : void 0
|
|
217
|
+
};
|
|
218
|
+
}
|
|
203
219
|
function saveState(configDir, state2) {
|
|
204
220
|
mkdirSync2(pluginRoot(configDir), { recursive: true });
|
|
205
221
|
atomicWriteFileSync(statePath(configDir), JSON.stringify(state2, null, 2));
|
|
206
222
|
}
|
|
207
|
-
function
|
|
208
|
-
|
|
223
|
+
function normalizeForHash(buf) {
|
|
224
|
+
const str = buf.toString("utf-8").replaceAll("\r\n", "\n");
|
|
225
|
+
return Buffer.from(str, "utf-8");
|
|
226
|
+
}
|
|
227
|
+
function extractCommandPaths(command, pluginDir) {
|
|
228
|
+
const resolvedDir = resolve(pluginDir);
|
|
229
|
+
const refs = [];
|
|
230
|
+
for (const m of command.matchAll(/\$PLUGIN_DIR[\\/]([^"'\s]+)/g)) {
|
|
231
|
+
refs.push(m[1]);
|
|
232
|
+
}
|
|
233
|
+
for (const m of command.matchAll(/\$\{pluginDir\}[\\/]([^"'\s}]+)/g)) {
|
|
234
|
+
refs.push(m[1]);
|
|
235
|
+
}
|
|
236
|
+
for (const m of command.matchAll(/(?<=["'\s])(\.?[.\\/][^"'\s]+)/g)) {
|
|
237
|
+
refs.push(m[0]);
|
|
238
|
+
}
|
|
239
|
+
const seen = /* @__PURE__ */ new Set();
|
|
240
|
+
const valid = [];
|
|
241
|
+
for (const ref of refs) {
|
|
242
|
+
if (seen.has(ref)) continue;
|
|
243
|
+
seen.add(ref);
|
|
244
|
+
try {
|
|
245
|
+
const abs = resolve(resolvedDir, ref);
|
|
246
|
+
if (!abs.startsWith(resolvedDir + sep)) continue;
|
|
247
|
+
if (existsSync2(abs)) {
|
|
248
|
+
const real = realpathSync(abs);
|
|
249
|
+
if (!real.startsWith(resolvedDir + sep)) continue;
|
|
250
|
+
valid.push(relative(resolvedDir, real));
|
|
251
|
+
}
|
|
252
|
+
} catch {
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return valid;
|
|
256
|
+
}
|
|
257
|
+
function hashPluginContent(pluginDir, manifest) {
|
|
258
|
+
const resolvedDir = resolve(pluginDir);
|
|
259
|
+
const assetRels = /* @__PURE__ */ new Set(
|
|
260
|
+
[...manifest.skills, ...manifest.commands, ...manifest.agents]
|
|
261
|
+
);
|
|
262
|
+
for (const raw of Object.values(manifest.hooks?.events ?? {})) {
|
|
263
|
+
const items = Array.isArray(raw) ? raw : [raw];
|
|
264
|
+
for (const item of items) {
|
|
265
|
+
const cmd = typeof item === "string" ? item : item.command;
|
|
266
|
+
if (cmd) {
|
|
267
|
+
for (const p of extractCommandPaths(cmd, pluginDir)) assetRels.add(p);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
for (const server of Object.values(manifest.mcpServers ?? {})) {
|
|
272
|
+
for (const p of extractCommandPaths(server.command, pluginDir)) assetRels.add(p);
|
|
273
|
+
for (const arg of server.args ?? []) {
|
|
274
|
+
for (const p of extractCommandPaths(arg, pluginDir)) assetRels.add(p);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
const sorted = [...assetRels].sort();
|
|
278
|
+
const hasher = createHash("sha256");
|
|
279
|
+
const manifestPath = join2(resolvedDir, MANIFEST_RELATIVE);
|
|
280
|
+
hasher.update(normalizeForHash(readFileSync2(manifestPath)));
|
|
281
|
+
for (const rel of sorted) {
|
|
282
|
+
const abs = resolve(resolvedDir, rel);
|
|
283
|
+
if (!abs.startsWith(resolvedDir + sep)) {
|
|
284
|
+
throw new Error(`plugin asset escapes plugin dir: ${rel}`);
|
|
285
|
+
}
|
|
286
|
+
let realPath;
|
|
287
|
+
try {
|
|
288
|
+
realPath = realpathSync(abs);
|
|
289
|
+
} catch {
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
try {
|
|
293
|
+
if (statSync(realPath).isDirectory()) continue;
|
|
294
|
+
} catch {
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
if (!realPath.startsWith(resolvedDir + sep)) {
|
|
298
|
+
throw new Error(`plugin asset symlink escapes plugin dir: ${rel} \u2192 ${realPath}`);
|
|
299
|
+
}
|
|
300
|
+
hasher.update(normalizeForHash(readFileSync2(abs)));
|
|
301
|
+
}
|
|
302
|
+
return hasher.digest("hex");
|
|
303
|
+
}
|
|
304
|
+
function effectiveHash(entry) {
|
|
305
|
+
return entry.contentHash ?? entry.hash ?? "";
|
|
209
306
|
}
|
|
210
307
|
function readPluginManifest(manifestPath) {
|
|
211
308
|
return PluginManifestSchema.parse(JSON.parse(readFileSync2(manifestPath, "utf-8")));
|
|
@@ -226,19 +323,19 @@ function installPlugin(configDir, inputPath) {
|
|
|
226
323
|
if (existsSync2(targetDir)) rmSync(targetDir, { recursive: true, force: true });
|
|
227
324
|
cpSync(sourceDir, targetDir, { recursive: true });
|
|
228
325
|
const manifestPath = pluginManifestPath(targetDir);
|
|
229
|
-
const
|
|
326
|
+
const contentHash = hashPluginContent(targetDir, manifest);
|
|
230
327
|
const state2 = loadState(configDir);
|
|
231
328
|
const previous = state2.plugins.find((p) => p.name === manifest.name);
|
|
232
329
|
const next = {
|
|
233
330
|
name: manifest.name,
|
|
234
331
|
enabled: previous?.enabled ?? false,
|
|
235
332
|
trusted: false,
|
|
236
|
-
|
|
333
|
+
contentHash,
|
|
237
334
|
installedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
238
335
|
};
|
|
239
336
|
state2.plugins = [...state2.plugins.filter((p) => p.name !== manifest.name), next];
|
|
240
337
|
saveState(configDir, state2);
|
|
241
|
-
return { name: manifest.name, dir: targetDir, manifestPath, manifest, hash, enabled: next.enabled, trusted: false, valid: true };
|
|
338
|
+
return { name: manifest.name, dir: targetDir, manifestPath, manifest, hash: contentHash, enabled: next.enabled, trusted: false, valid: true };
|
|
242
339
|
}
|
|
243
340
|
function setPluginEnabled(configDir, name, enabled) {
|
|
244
341
|
const plugin = getInstalledPlugin(configDir, name);
|
|
@@ -248,10 +345,10 @@ function setPluginEnabled(configDir, name, enabled) {
|
|
|
248
345
|
name: plugin.name,
|
|
249
346
|
enabled: false,
|
|
250
347
|
trusted: false,
|
|
251
|
-
|
|
348
|
+
contentHash: plugin.hash,
|
|
252
349
|
installedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
253
350
|
};
|
|
254
|
-
const next = { ...current, enabled,
|
|
351
|
+
const next = { ...current, enabled, contentHash: plugin.hash, enabledAt: enabled ? (/* @__PURE__ */ new Date()).toISOString() : current.enabledAt };
|
|
255
352
|
state2.plugins = [...state2.plugins.filter((p) => p.name !== plugin.name), next];
|
|
256
353
|
saveState(configDir, state2);
|
|
257
354
|
return next;
|
|
@@ -264,10 +361,10 @@ function trustPlugin(configDir, name) {
|
|
|
264
361
|
name: plugin.name,
|
|
265
362
|
enabled: false,
|
|
266
363
|
trusted: false,
|
|
267
|
-
|
|
364
|
+
contentHash: plugin.hash,
|
|
268
365
|
installedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
269
366
|
};
|
|
270
|
-
const next = { ...current, trusted: true,
|
|
367
|
+
const next = { ...current, trusted: true, contentHash: plugin.hash, trustedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
271
368
|
state2.plugins = [...state2.plugins.filter((p) => p.name !== plugin.name), next];
|
|
272
369
|
saveState(configDir, state2);
|
|
273
370
|
return next;
|
|
@@ -295,15 +392,15 @@ function listInstalledPlugins(configDir) {
|
|
|
295
392
|
if (!existsSync2(manifestPath)) continue;
|
|
296
393
|
try {
|
|
297
394
|
const manifest = readPluginManifest(manifestPath);
|
|
298
|
-
const
|
|
395
|
+
const contentHash = hashPluginContent(dir, manifest);
|
|
299
396
|
const st = state2.plugins.find((p) => p.name === manifest.name);
|
|
300
|
-
const trusted = st?.trusted === true && st
|
|
397
|
+
const trusted = st?.trusted === true && effectiveHash(st) === contentHash;
|
|
301
398
|
out.push({
|
|
302
399
|
name: manifest.name,
|
|
303
400
|
dir,
|
|
304
401
|
manifestPath,
|
|
305
402
|
manifest,
|
|
306
|
-
hash,
|
|
403
|
+
hash: contentHash,
|
|
307
404
|
enabled: st?.enabled === true,
|
|
308
405
|
trusted,
|
|
309
406
|
valid: true
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
truncateForPersist
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SBSWH2EG.js";
|
|
5
5
|
import {
|
|
6
6
|
APP_NAME,
|
|
7
7
|
CONFIG_DIR_NAME,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
MCP_PROTOCOL_VERSION,
|
|
12
12
|
MCP_TOOL_PREFIX,
|
|
13
13
|
VERSION
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-CGQARJMP.js";
|
|
15
15
|
import {
|
|
16
16
|
atomicWriteFileSync
|
|
17
17
|
} from "./chunk-IW3Q7AE5.js";
|
|
@@ -1078,10 +1078,10 @@ function readGitDiff(options = {}) {
|
|
|
1078
1078
|
}
|
|
1079
1079
|
|
|
1080
1080
|
export {
|
|
1081
|
+
readGitDiff,
|
|
1081
1082
|
scanDirTree,
|
|
1082
1083
|
scanProject,
|
|
1083
1084
|
buildInitPrompt,
|
|
1084
|
-
readGitDiff,
|
|
1085
1085
|
parseSimpleYaml,
|
|
1086
1086
|
persistToolRound,
|
|
1087
1087
|
autoTrimSessionIfNeeded,
|
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
CI_COMMENT_MARKER,
|
|
4
4
|
countSeverity,
|
|
5
5
|
runCi
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-O4QYY6SF.js";
|
|
7
|
+
import "./chunk-SCFGLRB3.js";
|
|
8
8
|
import "./chunk-HLWUDRBO.js";
|
|
9
9
|
import "./chunk-QYQI7ZWK.js";
|
|
10
10
|
import "./chunk-O3XSFPYH.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-VBAW4ZPY.js";
|
|
12
12
|
import "./chunk-5ULLIOVC.js";
|
|
13
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-CGQARJMP.js";
|
|
14
14
|
import "./chunk-IW3Q7AE5.js";
|
|
15
15
|
export {
|
|
16
16
|
CI_COMMENT_MARKER,
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
import {
|
|
3
3
|
formatDoctorReport,
|
|
4
4
|
runDoctorCli
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-QDP3NUPX.js";
|
|
6
6
|
import "./chunk-QYQI7ZWK.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-T6EIBUKW.js";
|
|
8
8
|
import "./chunk-O3XSFPYH.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-VBAW4ZPY.js";
|
|
10
10
|
import "./chunk-5ULLIOVC.js";
|
|
11
11
|
import "./chunk-HOSJZMQS.js";
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-CGQARJMP.js";
|
|
13
13
|
import "./chunk-IW3Q7AE5.js";
|
|
14
14
|
export {
|
|
15
15
|
formatDoctorReport,
|