nexrall-code 0.5.49 → 0.5.50
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/dist/index.js +705 -194
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1773,13 +1773,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1773
1773
|
* @param {string} source - expected values are default/config/env/cli/implied
|
|
1774
1774
|
* @return {Command} `this` command for chaining
|
|
1775
1775
|
*/
|
|
1776
|
-
setOptionValueWithSource(key, value,
|
|
1776
|
+
setOptionValueWithSource(key, value, source2) {
|
|
1777
1777
|
if (this._storeOptionsAsProperties) {
|
|
1778
1778
|
this[key] = value;
|
|
1779
1779
|
} else {
|
|
1780
1780
|
this._optionValues[key] = value;
|
|
1781
1781
|
}
|
|
1782
|
-
this._optionValueSources[key] =
|
|
1782
|
+
this._optionValueSources[key] = source2;
|
|
1783
1783
|
return this;
|
|
1784
1784
|
}
|
|
1785
1785
|
/**
|
|
@@ -1800,13 +1800,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1800
1800
|
* @return {string}
|
|
1801
1801
|
*/
|
|
1802
1802
|
getOptionValueSourceWithGlobals(key) {
|
|
1803
|
-
let
|
|
1803
|
+
let source2;
|
|
1804
1804
|
this._getCommandAndAncestors().forEach((cmd) => {
|
|
1805
1805
|
if (cmd.getOptionValueSource(key) !== void 0) {
|
|
1806
|
-
|
|
1806
|
+
source2 = cmd.getOptionValueSource(key);
|
|
1807
1807
|
}
|
|
1808
1808
|
});
|
|
1809
|
-
return
|
|
1809
|
+
return source2;
|
|
1810
1810
|
}
|
|
1811
1811
|
/**
|
|
1812
1812
|
* Get user arguments from implied or explicit arguments.
|
|
@@ -2615,8 +2615,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2615
2615
|
const getErrorMessage = (option2) => {
|
|
2616
2616
|
const bestOption = findBestOptionFromValue(option2);
|
|
2617
2617
|
const optionKey = bestOption.attributeName();
|
|
2618
|
-
const
|
|
2619
|
-
if (
|
|
2618
|
+
const source2 = this.getOptionValueSource(optionKey);
|
|
2619
|
+
if (source2 === "env") {
|
|
2620
2620
|
return `environment variable '${bestOption.envVar}'`;
|
|
2621
2621
|
}
|
|
2622
2622
|
return `option '${bestOption.flags}'`;
|
|
@@ -5998,10 +5998,10 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
5998
5998
|
return ctor;
|
|
5999
5999
|
}
|
|
6000
6000
|
const DOMException2 = getFromGlobal() || createPolyfill();
|
|
6001
|
-
function ReadableStreamPipeTo(
|
|
6002
|
-
const reader = AcquireReadableStreamDefaultReader(
|
|
6001
|
+
function ReadableStreamPipeTo(source2, dest, preventClose, preventAbort, preventCancel, signal) {
|
|
6002
|
+
const reader = AcquireReadableStreamDefaultReader(source2);
|
|
6003
6003
|
const writer = AcquireWritableStreamDefaultWriter(dest);
|
|
6004
|
-
|
|
6004
|
+
source2._disturbed = true;
|
|
6005
6005
|
let shuttingDown = false;
|
|
6006
6006
|
let currentWrite = promiseResolvedWith(void 0);
|
|
6007
6007
|
return newPromise((resolve3, reject) => {
|
|
@@ -6020,8 +6020,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
6020
6020
|
}
|
|
6021
6021
|
if (!preventCancel) {
|
|
6022
6022
|
actions.push(() => {
|
|
6023
|
-
if (
|
|
6024
|
-
return ReadableStreamCancel(
|
|
6023
|
+
if (source2._state === "readable") {
|
|
6024
|
+
return ReadableStreamCancel(source2, error);
|
|
6025
6025
|
}
|
|
6026
6026
|
return promiseResolvedWith(void 0);
|
|
6027
6027
|
});
|
|
@@ -6063,7 +6063,7 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
6063
6063
|
});
|
|
6064
6064
|
});
|
|
6065
6065
|
}
|
|
6066
|
-
isOrBecomesErrored(
|
|
6066
|
+
isOrBecomesErrored(source2, reader._closedPromise, (storedError) => {
|
|
6067
6067
|
if (!preventAbort) {
|
|
6068
6068
|
shutdownWithAction(() => WritableStreamAbort(dest, storedError), true, storedError);
|
|
6069
6069
|
} else {
|
|
@@ -6073,13 +6073,13 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
6073
6073
|
});
|
|
6074
6074
|
isOrBecomesErrored(dest, writer._closedPromise, (storedError) => {
|
|
6075
6075
|
if (!preventCancel) {
|
|
6076
|
-
shutdownWithAction(() => ReadableStreamCancel(
|
|
6076
|
+
shutdownWithAction(() => ReadableStreamCancel(source2, storedError), true, storedError);
|
|
6077
6077
|
} else {
|
|
6078
6078
|
shutdown(true, storedError);
|
|
6079
6079
|
}
|
|
6080
6080
|
return null;
|
|
6081
6081
|
});
|
|
6082
|
-
isOrBecomesClosed(
|
|
6082
|
+
isOrBecomesClosed(source2, reader._closedPromise, () => {
|
|
6083
6083
|
if (!preventClose) {
|
|
6084
6084
|
shutdownWithAction(() => WritableStreamDefaultWriterCloseWithErrorPropagation(writer));
|
|
6085
6085
|
} else {
|
|
@@ -6090,7 +6090,7 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
6090
6090
|
if (WritableStreamCloseQueuedOrInFlight(dest) || dest._state === "closed") {
|
|
6091
6091
|
const destClosed = new TypeError("the destination writable stream closed before all data could be piped to it");
|
|
6092
6092
|
if (!preventCancel) {
|
|
6093
|
-
shutdownWithAction(() => ReadableStreamCancel(
|
|
6093
|
+
shutdownWithAction(() => ReadableStreamCancel(source2, destClosed), true, destClosed);
|
|
6094
6094
|
} else {
|
|
6095
6095
|
shutdown(true, destClosed);
|
|
6096
6096
|
}
|
|
@@ -6726,11 +6726,11 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
6726
6726
|
function isReadableStreamLike(stream) {
|
|
6727
6727
|
return typeIsObject(stream) && typeof stream.getReader !== "undefined";
|
|
6728
6728
|
}
|
|
6729
|
-
function ReadableStreamFrom(
|
|
6730
|
-
if (isReadableStreamLike(
|
|
6731
|
-
return ReadableStreamFromDefaultReader(
|
|
6729
|
+
function ReadableStreamFrom(source2) {
|
|
6730
|
+
if (isReadableStreamLike(source2)) {
|
|
6731
|
+
return ReadableStreamFromDefaultReader(source2.getReader());
|
|
6732
6732
|
}
|
|
6733
|
-
return ReadableStreamFromIterable(
|
|
6733
|
+
return ReadableStreamFromIterable(source2);
|
|
6734
6734
|
}
|
|
6735
6735
|
function ReadableStreamFromIterable(asyncIterable) {
|
|
6736
6736
|
let stream;
|
|
@@ -6817,9 +6817,9 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
6817
6817
|
stream = CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, 0);
|
|
6818
6818
|
return stream;
|
|
6819
6819
|
}
|
|
6820
|
-
function convertUnderlyingDefaultOrByteSource(
|
|
6821
|
-
assertDictionary(
|
|
6822
|
-
const original =
|
|
6820
|
+
function convertUnderlyingDefaultOrByteSource(source2, context) {
|
|
6821
|
+
assertDictionary(source2, context);
|
|
6822
|
+
const original = source2;
|
|
6823
6823
|
const autoAllocateChunkSize = original === null || original === void 0 ? void 0 : original.autoAllocateChunkSize;
|
|
6824
6824
|
const cancel = original === null || original === void 0 ? void 0 : original.cancel;
|
|
6825
6825
|
const pull = original === null || original === void 0 ? void 0 : original.pull;
|
|
@@ -11201,6 +11201,8 @@ var require_plugins = __commonJS({
|
|
|
11201
11201
|
};
|
|
11202
11202
|
}();
|
|
11203
11203
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11204
|
+
exports.FILE_CANDIDATES = void 0;
|
|
11205
|
+
exports.resolvePluginFile = resolvePluginFile;
|
|
11204
11206
|
exports.loadPlugins = loadPlugins3;
|
|
11205
11207
|
exports.pluginAssetDirs = pluginAssetDirs;
|
|
11206
11208
|
exports.pluginHooks = pluginHooks;
|
|
@@ -11208,9 +11210,28 @@ var require_plugins = __commonJS({
|
|
|
11208
11210
|
var fs9 = __importStar(__require("fs"));
|
|
11209
11211
|
var path6 = __importStar(__require("path"));
|
|
11210
11212
|
var os6 = __importStar(__require("os"));
|
|
11213
|
+
exports.FILE_CANDIDATES = {
|
|
11214
|
+
manifest: ["plugin.json", path6.join(".claude-plugin", "plugin.json")],
|
|
11215
|
+
hooks: ["hooks.json", path6.join("hooks", "hooks.json")],
|
|
11216
|
+
mcp: ["mcp.json", ".mcp.json"]
|
|
11217
|
+
};
|
|
11218
|
+
function resolvePluginFile(dir, kind) {
|
|
11219
|
+
for (const rel of exports.FILE_CANDIDATES[kind]) {
|
|
11220
|
+
const full = path6.join(dir, rel);
|
|
11221
|
+
try {
|
|
11222
|
+
if (fs9.statSync(full).isFile())
|
|
11223
|
+
return full;
|
|
11224
|
+
} catch {
|
|
11225
|
+
}
|
|
11226
|
+
}
|
|
11227
|
+
return null;
|
|
11228
|
+
}
|
|
11211
11229
|
function readMeta(dir) {
|
|
11230
|
+
const file = resolvePluginFile(dir, "manifest");
|
|
11231
|
+
if (!file)
|
|
11232
|
+
return {};
|
|
11212
11233
|
try {
|
|
11213
|
-
const raw = fs9.readFileSync(
|
|
11234
|
+
const raw = fs9.readFileSync(file, "utf-8");
|
|
11214
11235
|
const j = JSON.parse(raw);
|
|
11215
11236
|
return {
|
|
11216
11237
|
name: typeof j.name === "string" ? j.name : void 0,
|
|
@@ -11263,8 +11284,11 @@ var require_plugins = __commonJS({
|
|
|
11263
11284
|
function pluginHooks(workDir) {
|
|
11264
11285
|
const merged = {};
|
|
11265
11286
|
for (const p of loadPlugins3(workDir)) {
|
|
11287
|
+
const file = resolvePluginFile(p.dir, "hooks");
|
|
11288
|
+
if (!file)
|
|
11289
|
+
continue;
|
|
11266
11290
|
try {
|
|
11267
|
-
const raw = fs9.readFileSync(
|
|
11291
|
+
const raw = fs9.readFileSync(file, "utf-8");
|
|
11268
11292
|
const j = JSON.parse(raw);
|
|
11269
11293
|
const hooks = j.hooks ?? j;
|
|
11270
11294
|
for (const [phase, entries] of Object.entries(hooks)) {
|
|
@@ -11280,8 +11304,11 @@ var require_plugins = __commonJS({
|
|
|
11280
11304
|
function pluginMcpServers(workDir) {
|
|
11281
11305
|
const merged = {};
|
|
11282
11306
|
for (const p of loadPlugins3(workDir)) {
|
|
11307
|
+
const file = resolvePluginFile(p.dir, "mcp");
|
|
11308
|
+
if (!file)
|
|
11309
|
+
continue;
|
|
11283
11310
|
try {
|
|
11284
|
-
const raw = fs9.readFileSync(
|
|
11311
|
+
const raw = fs9.readFileSync(file, "utf-8");
|
|
11285
11312
|
const j = JSON.parse(raw);
|
|
11286
11313
|
const servers = j.mcpServers ?? j;
|
|
11287
11314
|
for (const [name, cfg] of Object.entries(servers)) {
|
|
@@ -11400,7 +11427,7 @@ var require_loader = __commonJS({
|
|
|
11400
11427
|
}
|
|
11401
11428
|
return { meta, body: (m2[2] ?? "").trim() };
|
|
11402
11429
|
}
|
|
11403
|
-
function loadDir(dir,
|
|
11430
|
+
function loadDir(dir, source2, into) {
|
|
11404
11431
|
let files;
|
|
11405
11432
|
try {
|
|
11406
11433
|
files = fs9.readdirSync(dir).filter((f3) => f3.endsWith(".md"));
|
|
@@ -11414,7 +11441,7 @@ var require_loader = __commonJS({
|
|
|
11414
11441
|
const name = (meta.name || path6.basename(file, ".md")).trim().toLowerCase();
|
|
11415
11442
|
if (!name)
|
|
11416
11443
|
continue;
|
|
11417
|
-
if (
|
|
11444
|
+
if (source2 !== "project" && into.has(name))
|
|
11418
11445
|
continue;
|
|
11419
11446
|
const model = ["turbo", "pro", "ultra"].find((x2) => x2 === (meta.model ?? "").toLowerCase());
|
|
11420
11447
|
into.set(name, {
|
|
@@ -11423,7 +11450,7 @@ var require_loader = __commonJS({
|
|
|
11423
11450
|
model,
|
|
11424
11451
|
mode: meta.mode || void 0,
|
|
11425
11452
|
body,
|
|
11426
|
-
source
|
|
11453
|
+
source: source2
|
|
11427
11454
|
});
|
|
11428
11455
|
} catch {
|
|
11429
11456
|
}
|
|
@@ -11569,7 +11596,7 @@ var require_skills = __commonJS({
|
|
|
11569
11596
|
return false;
|
|
11570
11597
|
return fallback;
|
|
11571
11598
|
}
|
|
11572
|
-
function toSkill(meta, body, name,
|
|
11599
|
+
function toSkill(meta, body, name, source2, dir) {
|
|
11573
11600
|
const model = ["turbo", "pro", "ultra"].find((x2) => x2 === (meta.model ?? "").toLowerCase());
|
|
11574
11601
|
return {
|
|
11575
11602
|
name,
|
|
@@ -11577,13 +11604,13 @@ var require_skills = __commonJS({
|
|
|
11577
11604
|
model,
|
|
11578
11605
|
mode: meta.mode || void 0,
|
|
11579
11606
|
body,
|
|
11580
|
-
source,
|
|
11607
|
+
source: source2,
|
|
11581
11608
|
dir,
|
|
11582
11609
|
disableModelInvocation: parseBool(meta["disable-model-invocation"], false),
|
|
11583
11610
|
userInvocable: parseBool(meta["user-invocable"], true)
|
|
11584
11611
|
};
|
|
11585
11612
|
}
|
|
11586
|
-
function loadFlatCommandDir(dir,
|
|
11613
|
+
function loadFlatCommandDir(dir, source2, into) {
|
|
11587
11614
|
let files;
|
|
11588
11615
|
try {
|
|
11589
11616
|
files = fs9.readdirSync(dir).filter((f3) => f3.endsWith(".md"));
|
|
@@ -11597,14 +11624,14 @@ var require_skills = __commonJS({
|
|
|
11597
11624
|
const name = (meta.name || path6.basename(file, ".md")).trim().toLowerCase();
|
|
11598
11625
|
if (!name)
|
|
11599
11626
|
continue;
|
|
11600
|
-
if (
|
|
11627
|
+
if (source2 !== "project" && into.has(name))
|
|
11601
11628
|
continue;
|
|
11602
|
-
into.set(name, toSkill(meta, body, name,
|
|
11629
|
+
into.set(name, toSkill(meta, body, name, source2));
|
|
11603
11630
|
} catch {
|
|
11604
11631
|
}
|
|
11605
11632
|
}
|
|
11606
11633
|
}
|
|
11607
|
-
function loadSkillDir(root,
|
|
11634
|
+
function loadSkillDir(root, source2, into) {
|
|
11608
11635
|
let entries;
|
|
11609
11636
|
try {
|
|
11610
11637
|
entries = fs9.readdirSync(root, { withFileTypes: true });
|
|
@@ -11628,9 +11655,9 @@ var require_skills = __commonJS({
|
|
|
11628
11655
|
const name = (meta.name || entry.name).trim().toLowerCase();
|
|
11629
11656
|
if (!name)
|
|
11630
11657
|
continue;
|
|
11631
|
-
if (
|
|
11658
|
+
if (source2 !== "project" && into.has(name))
|
|
11632
11659
|
continue;
|
|
11633
|
-
into.set(name, toSkill(meta, body, name,
|
|
11660
|
+
into.set(name, toSkill(meta, body, name, source2, skillDir));
|
|
11634
11661
|
} catch {
|
|
11635
11662
|
}
|
|
11636
11663
|
}
|
|
@@ -12164,12 +12191,12 @@ var require_symbols = __commonJS({
|
|
|
12164
12191
|
return new Set(EXT_TO_LANG.keys());
|
|
12165
12192
|
}
|
|
12166
12193
|
var MAX_FILE_BYTES = 1024 * 1024;
|
|
12167
|
-
function extractSymbols(filePath,
|
|
12194
|
+
function extractSymbols(filePath, source2) {
|
|
12168
12195
|
const lang = EXT_TO_LANG.get(path6.extname(filePath).toLowerCase());
|
|
12169
12196
|
if (!lang)
|
|
12170
12197
|
return [];
|
|
12171
12198
|
const hits = [];
|
|
12172
|
-
const lines =
|
|
12199
|
+
const lines = source2.split("\n");
|
|
12173
12200
|
let inBlockComment = false;
|
|
12174
12201
|
for (let i2 = 0; i2 < lines.length; i2++) {
|
|
12175
12202
|
const trimmed = lines[i2].trim();
|
|
@@ -12206,21 +12233,21 @@ var require_symbols = __commonJS({
|
|
|
12206
12233
|
if (!rel)
|
|
12207
12234
|
return { error: "path is required" };
|
|
12208
12235
|
const abs = resolveIn(workDir, rel);
|
|
12209
|
-
let
|
|
12236
|
+
let source2;
|
|
12210
12237
|
try {
|
|
12211
12238
|
const st = fs9.statSync(abs);
|
|
12212
12239
|
if (!st.isFile())
|
|
12213
12240
|
return { error: `Not a file: ${rel}` };
|
|
12214
12241
|
if (st.size > MAX_FILE_BYTES)
|
|
12215
12242
|
return { error: `File too large for symbol scan (${Math.round(st.size / 1024)} KB > 1024 KB)` };
|
|
12216
|
-
|
|
12243
|
+
source2 = fs9.readFileSync(abs, "utf-8");
|
|
12217
12244
|
} catch (err) {
|
|
12218
12245
|
return { error: `Cannot read ${rel}: ${err.message}` };
|
|
12219
12246
|
}
|
|
12220
12247
|
if (!EXT_TO_LANG.has(path6.extname(abs).toLowerCase())) {
|
|
12221
12248
|
return { output: `No symbol support for ${path6.extname(abs) || "this file type"} (regex-based scanner). Use search_files instead.` };
|
|
12222
12249
|
}
|
|
12223
|
-
const hits = extractSymbols(abs,
|
|
12250
|
+
const hits = extractSymbols(abs, source2);
|
|
12224
12251
|
if (!hits.length)
|
|
12225
12252
|
return { output: `No symbols found in ${rel}.` };
|
|
12226
12253
|
const lines = hits.map((h2) => `${h2.kind.padEnd(10)} ${h2.name} (line ${h2.line})`);
|
|
@@ -12262,10 +12289,10 @@ ${lines.join("\n")}` };
|
|
|
12262
12289
|
const st = fs9.statSync(full);
|
|
12263
12290
|
if (st.size > MAX_FILE_BYTES)
|
|
12264
12291
|
continue;
|
|
12265
|
-
const
|
|
12266
|
-
if (!
|
|
12292
|
+
const source2 = fs9.readFileSync(full, "utf-8");
|
|
12293
|
+
if (!source2.toLowerCase().includes(q))
|
|
12267
12294
|
continue;
|
|
12268
|
-
for (const h2 of extractSymbols(full,
|
|
12295
|
+
for (const h2 of extractSymbols(full, source2)) {
|
|
12269
12296
|
if (h2.name.toLowerCase().includes(q)) {
|
|
12270
12297
|
results.push({ ...h2, file: path6.relative(root, full) });
|
|
12271
12298
|
if (results.length >= MAX_RESULTS)
|
|
@@ -12452,18 +12479,18 @@ var require_tsLangService = __commonJS({
|
|
|
12452
12479
|
return false;
|
|
12453
12480
|
}
|
|
12454
12481
|
}
|
|
12455
|
-
function posToOffset(
|
|
12456
|
-
const lines =
|
|
12482
|
+
function posToOffset(source2, line, character) {
|
|
12483
|
+
const lines = source2.split("\n");
|
|
12457
12484
|
let offset = 0;
|
|
12458
12485
|
for (let i2 = 0; i2 < line - 1 && i2 < lines.length; i2++)
|
|
12459
12486
|
offset += lines[i2].length + 1;
|
|
12460
12487
|
return offset + Math.max(0, character - 1);
|
|
12461
12488
|
}
|
|
12462
|
-
function offsetToPos(
|
|
12489
|
+
function offsetToPos(source2, offset) {
|
|
12463
12490
|
let line = 1;
|
|
12464
12491
|
let last = 0;
|
|
12465
|
-
for (let i2 = 0; i2 < offset && i2 <
|
|
12466
|
-
if (
|
|
12492
|
+
for (let i2 = 0; i2 < offset && i2 < source2.length; i2++) {
|
|
12493
|
+
if (source2[i2] === "\n") {
|
|
12467
12494
|
line++;
|
|
12468
12495
|
last = i2 + 1;
|
|
12469
12496
|
}
|
|
@@ -12480,8 +12507,8 @@ var require_tsLangService = __commonJS({
|
|
|
12480
12507
|
return null;
|
|
12481
12508
|
if (!ensureFile(svc, deps.filePath))
|
|
12482
12509
|
return { error: `Cannot read ${deps.filePath}` };
|
|
12483
|
-
const
|
|
12484
|
-
const offset = posToOffset(
|
|
12510
|
+
const source2 = svc.snapshots.get(deps.filePath) ?? "";
|
|
12511
|
+
const offset = posToOffset(source2, deps.line, deps.character);
|
|
12485
12512
|
let defs;
|
|
12486
12513
|
try {
|
|
12487
12514
|
defs = svc.service.getDefinitionAtPosition(deps.filePath, offset);
|
|
@@ -12504,8 +12531,8 @@ ${out.join("\n")}` };
|
|
|
12504
12531
|
return null;
|
|
12505
12532
|
if (!ensureFile(svc, deps.filePath))
|
|
12506
12533
|
return { error: `Cannot read ${deps.filePath}` };
|
|
12507
|
-
const
|
|
12508
|
-
const offset = posToOffset(
|
|
12534
|
+
const source2 = svc.snapshots.get(deps.filePath) ?? "";
|
|
12535
|
+
const offset = posToOffset(source2, deps.line, deps.character);
|
|
12509
12536
|
let refs;
|
|
12510
12537
|
try {
|
|
12511
12538
|
refs = svc.service.getReferencesAtPosition(deps.filePath, offset);
|
|
@@ -12532,8 +12559,8 @@ ${lines.join("\n")}` };
|
|
|
12532
12559
|
return null;
|
|
12533
12560
|
if (!ensureFile(svc, deps.filePath))
|
|
12534
12561
|
return { error: `Cannot read ${deps.filePath}` };
|
|
12535
|
-
const
|
|
12536
|
-
const offset = posToOffset(
|
|
12562
|
+
const source2 = svc.snapshots.get(deps.filePath) ?? "";
|
|
12563
|
+
const offset = posToOffset(source2, deps.line, deps.character);
|
|
12537
12564
|
let info;
|
|
12538
12565
|
try {
|
|
12539
12566
|
info = svc.service.getQuickInfoAtPosition(deps.filePath, offset);
|
|
@@ -13528,14 +13555,14 @@ ${globalCapMatches(output)}` : "";
|
|
|
13528
13555
|
}
|
|
13529
13556
|
}
|
|
13530
13557
|
async function moveFile(input, workDir) {
|
|
13531
|
-
const
|
|
13558
|
+
const source2 = typeof input.source === "string" ? input.source : "";
|
|
13532
13559
|
const dest = typeof input.dest === "string" ? input.dest : "";
|
|
13533
|
-
if (!
|
|
13560
|
+
if (!source2)
|
|
13534
13561
|
return { error: "Missing required parameter: source" };
|
|
13535
13562
|
if (!dest)
|
|
13536
13563
|
return { error: "Missing required parameter: dest" };
|
|
13537
13564
|
try {
|
|
13538
|
-
const resolvedSource = resolvePath(
|
|
13565
|
+
const resolvedSource = resolvePath(source2, workDir);
|
|
13539
13566
|
const resolvedDest = resolvePath(dest, workDir);
|
|
13540
13567
|
fs9.mkdirSync(path6.dirname(resolvedDest), { recursive: true });
|
|
13541
13568
|
try {
|
|
@@ -13680,14 +13707,14 @@ ${diff3}${xfile}${sec}` };
|
|
|
13680
13707
|
}
|
|
13681
13708
|
}
|
|
13682
13709
|
async function copyFile(input, workDir) {
|
|
13683
|
-
const
|
|
13710
|
+
const source2 = typeof input.source === "string" ? input.source : "";
|
|
13684
13711
|
const destination = typeof input.destination === "string" ? input.destination : "";
|
|
13685
|
-
if (!
|
|
13712
|
+
if (!source2)
|
|
13686
13713
|
return { error: "Missing required parameter: source" };
|
|
13687
13714
|
if (!destination)
|
|
13688
13715
|
return { error: "Missing required parameter: destination" };
|
|
13689
13716
|
try {
|
|
13690
|
-
const resolvedSrc = resolvePath(
|
|
13717
|
+
const resolvedSrc = resolvePath(source2, workDir);
|
|
13691
13718
|
const resolvedDest = resolvePath(destination, workDir);
|
|
13692
13719
|
if (fs9.existsSync(resolvedDest) && fs9.statSync(resolvedDest).isDirectory()) {
|
|
13693
13720
|
return { error: `Destination is a directory: ${resolvedDest}. Provide a full file path including the filename.` };
|
|
@@ -14133,7 +14160,7 @@ ${lines.join("\n")}`;
|
|
|
14133
14160
|
const editType = typeof input.edit_type === "string" ? input.edit_type : "";
|
|
14134
14161
|
const rawIdx = input.cell_index;
|
|
14135
14162
|
const cellIndex = typeof rawIdx === "number" ? Math.floor(rawIdx) : typeof rawIdx === "string" && rawIdx.trim() !== "" ? parseInt(rawIdx, 10) : -1;
|
|
14136
|
-
const
|
|
14163
|
+
const source2 = typeof input.source === "string" ? input.source : null;
|
|
14137
14164
|
const cellType = typeof input.cell_type === "string" ? input.cell_type : "code";
|
|
14138
14165
|
if (!filePath)
|
|
14139
14166
|
return { error: "Missing required parameter: path" };
|
|
@@ -14152,10 +14179,10 @@ ${lines.join("\n")}`;
|
|
|
14152
14179
|
if (editType === "replace") {
|
|
14153
14180
|
if (cellIndex < 0 || cellIndex >= n)
|
|
14154
14181
|
return { error: `cell_index ${cellIndex} out of range (0\u2013${n - 1})` };
|
|
14155
|
-
if (
|
|
14182
|
+
if (source2 === null)
|
|
14156
14183
|
return { error: "Missing required parameter: source (required for replace)" };
|
|
14157
14184
|
const cell = nb.cells[cellIndex];
|
|
14158
|
-
cell.source =
|
|
14185
|
+
cell.source = source2;
|
|
14159
14186
|
if (cell.cell_type === "code") {
|
|
14160
14187
|
cell.outputs = [];
|
|
14161
14188
|
cell.execution_count = null;
|
|
@@ -14170,12 +14197,12 @@ ${lines.join("\n")}`;
|
|
|
14170
14197
|
save();
|
|
14171
14198
|
return { output: `Deleted cell ${cellIndex} [${removed.cell_type}] from ${resolved}. Notebook now has ${nb.cells.length} cells.` };
|
|
14172
14199
|
}
|
|
14173
|
-
if (
|
|
14200
|
+
if (source2 === null)
|
|
14174
14201
|
return { error: "Missing required parameter: source (required for insert)" };
|
|
14175
14202
|
const insertAt = cellIndex >= 0 ? Math.min(cellIndex + 1, n) : n;
|
|
14176
14203
|
const newCell = {
|
|
14177
14204
|
cell_type: cellType,
|
|
14178
|
-
source,
|
|
14205
|
+
source: source2,
|
|
14179
14206
|
metadata: {},
|
|
14180
14207
|
...cellType === "code" ? { execution_count: null, outputs: [] } : {}
|
|
14181
14208
|
};
|
|
@@ -14542,7 +14569,10 @@ var require_agentTypes = __commonJS({
|
|
|
14542
14569
|
};
|
|
14543
14570
|
}();
|
|
14544
14571
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14545
|
-
exports.loadAgentTypes =
|
|
14572
|
+
exports.loadAgentTypes = loadAgentTypes;
|
|
14573
|
+
exports.loadAgentTypesWithWarnings = loadAgentTypesWithWarnings2;
|
|
14574
|
+
exports.knownToolNames = knownToolNames;
|
|
14575
|
+
exports.builtinAgents = builtinAgents;
|
|
14546
14576
|
exports.summariseAgents = summariseAgents;
|
|
14547
14577
|
exports.findAgentType = findAgentType;
|
|
14548
14578
|
var fs9 = __importStar(__require("fs"));
|
|
@@ -14557,9 +14587,17 @@ var require_agentTypes = __commonJS({
|
|
|
14557
14587
|
"list_directory",
|
|
14558
14588
|
"bash",
|
|
14559
14589
|
"bash_output",
|
|
14590
|
+
// kill_shell belongs next to bash_output: an agent that can start a background
|
|
14591
|
+
// process and poll it but never stop it leaks that process past its own
|
|
14592
|
+
// lifetime. Stopping a shell you started is not a write to the repo.
|
|
14593
|
+
"kill_shell",
|
|
14560
14594
|
"notebook_read",
|
|
14561
14595
|
"todo_write",
|
|
14562
14596
|
"todo_read",
|
|
14597
|
+
// Skills are reusable prompt playbooks, and loop.ts advertises the skills
|
|
14598
|
+
// catalogue to sub-agents at EVERY depth — so withholding the tool that loads
|
|
14599
|
+
// one meant showing every sub-agent a menu it could not order from.
|
|
14600
|
+
"use_skill",
|
|
14563
14601
|
// VS Code language server (ignored on the CLI)
|
|
14564
14602
|
"get_symbols",
|
|
14565
14603
|
"get_workspace_symbols",
|
|
@@ -14568,7 +14606,7 @@ var require_agentTypes = __commonJS({
|
|
|
14568
14606
|
"get_hover",
|
|
14569
14607
|
"get_diagnostics"
|
|
14570
14608
|
];
|
|
14571
|
-
var RESEARCH_TOOLS = [...READ_ONLY_TOOLS, "
|
|
14609
|
+
var RESEARCH_TOOLS = [...READ_ONLY_TOOLS, "fetch_url"];
|
|
14572
14610
|
var WRITE_TOOLS = [
|
|
14573
14611
|
...READ_ONLY_TOOLS,
|
|
14574
14612
|
"write_file",
|
|
@@ -14576,7 +14614,11 @@ var require_agentTypes = __commonJS({
|
|
|
14576
14614
|
"multi_edit",
|
|
14577
14615
|
"create_directory",
|
|
14578
14616
|
"move_file",
|
|
14579
|
-
"copy_file"
|
|
14617
|
+
"copy_file",
|
|
14618
|
+
// notebook_edit is a write tool like any other, and allowsTestOnlyWrite already
|
|
14619
|
+
// knows its shape (`source` is cell CONTENT, not a path). Omitting it just meant
|
|
14620
|
+
// test-writer silently could not touch notebooks.
|
|
14621
|
+
"notebook_edit"
|
|
14580
14622
|
];
|
|
14581
14623
|
var BUILTIN_AGENTS = [
|
|
14582
14624
|
{
|
|
@@ -14756,17 +14798,61 @@ var require_agentTypes = __commonJS({
|
|
|
14756
14798
|
].join("\n")
|
|
14757
14799
|
}
|
|
14758
14800
|
];
|
|
14801
|
+
var KNOWN_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
14802
|
+
"read_file",
|
|
14803
|
+
"write_file",
|
|
14804
|
+
"edit_file",
|
|
14805
|
+
"multi_edit",
|
|
14806
|
+
"list_directory",
|
|
14807
|
+
"create_directory",
|
|
14808
|
+
"move_file",
|
|
14809
|
+
"copy_file",
|
|
14810
|
+
"delete_file",
|
|
14811
|
+
"search_files",
|
|
14812
|
+
"glob",
|
|
14813
|
+
"bash",
|
|
14814
|
+
"bash_output",
|
|
14815
|
+
"kill_shell",
|
|
14816
|
+
"notebook_read",
|
|
14817
|
+
"notebook_edit",
|
|
14818
|
+
"todo_write",
|
|
14819
|
+
"todo_read",
|
|
14820
|
+
"memory_write",
|
|
14821
|
+
"memory_read",
|
|
14822
|
+
"use_skill",
|
|
14823
|
+
"fetch_url",
|
|
14824
|
+
"web_search",
|
|
14825
|
+
"generate_image",
|
|
14826
|
+
"stock_photo",
|
|
14827
|
+
"open_in_browser",
|
|
14828
|
+
"task",
|
|
14829
|
+
"get_symbols",
|
|
14830
|
+
"get_workspace_symbols",
|
|
14831
|
+
"find_references",
|
|
14832
|
+
"go_to_definition",
|
|
14833
|
+
"get_hover",
|
|
14834
|
+
"get_diagnostics"
|
|
14835
|
+
]);
|
|
14836
|
+
var KNOWN_META_KEYS = /* @__PURE__ */ new Set([
|
|
14837
|
+
"name",
|
|
14838
|
+
"description",
|
|
14839
|
+
"tools",
|
|
14840
|
+
"model",
|
|
14841
|
+
"test_files_only",
|
|
14842
|
+
"testfilesonly"
|
|
14843
|
+
]);
|
|
14844
|
+
var VALID_MODELS = ["turbo", "pro", "ultra"];
|
|
14759
14845
|
function parseFrontmatter(raw) {
|
|
14760
14846
|
const m2 = /^\s*---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/.exec(raw);
|
|
14761
14847
|
if (!m2)
|
|
14762
|
-
return { meta: {}, body: raw.trim() };
|
|
14848
|
+
return { meta: {}, body: raw.trim(), ok: false };
|
|
14763
14849
|
const meta = {};
|
|
14764
14850
|
for (const line of m2[1].split(/\r?\n/)) {
|
|
14765
14851
|
const kv = /^([A-Za-z0-9_-]+)\s*:\s*(.*)$/.exec(line.trim());
|
|
14766
14852
|
if (kv)
|
|
14767
14853
|
meta[kv[1].toLowerCase()] = kv[2].trim().replace(/^["']|["']$/g, "");
|
|
14768
14854
|
}
|
|
14769
|
-
return { meta, body: (m2[2] ?? "").trim() };
|
|
14855
|
+
return { meta, body: (m2[2] ?? "").trim(), ok: true };
|
|
14770
14856
|
}
|
|
14771
14857
|
function parseModel(v) {
|
|
14772
14858
|
const s2 = (v ?? "").toLowerCase();
|
|
@@ -14781,51 +14867,113 @@ var require_agentTypes = __commonJS({
|
|
|
14781
14867
|
const tools = v.replace(/^\[|\]$/g, "").split(/[,\s]+/).map((t2) => t2.trim()).filter(Boolean);
|
|
14782
14868
|
return tools.length ? tools : void 0;
|
|
14783
14869
|
}
|
|
14784
|
-
function loadDir(dir,
|
|
14870
|
+
function loadDir(dir, source2, into, warnings) {
|
|
14785
14871
|
let entries;
|
|
14786
14872
|
try {
|
|
14787
|
-
entries = fs9.readdirSync(dir
|
|
14873
|
+
entries = fs9.readdirSync(dir, { withFileTypes: true });
|
|
14788
14874
|
} catch {
|
|
14789
14875
|
return;
|
|
14790
14876
|
}
|
|
14791
|
-
for (const
|
|
14877
|
+
for (const entry of entries) {
|
|
14878
|
+
const full = path6.join(dir, entry.name);
|
|
14879
|
+
if (entry.isDirectory()) {
|
|
14880
|
+
loadDir(full, source2, into, warnings);
|
|
14881
|
+
continue;
|
|
14882
|
+
}
|
|
14883
|
+
if (!entry.name.endsWith(".md"))
|
|
14884
|
+
continue;
|
|
14885
|
+
let raw;
|
|
14792
14886
|
try {
|
|
14793
|
-
|
|
14794
|
-
|
|
14795
|
-
|
|
14796
|
-
|
|
14797
|
-
|
|
14798
|
-
|
|
14799
|
-
|
|
14800
|
-
|
|
14801
|
-
|
|
14802
|
-
|
|
14803
|
-
|
|
14804
|
-
|
|
14805
|
-
|
|
14806
|
-
|
|
14807
|
-
|
|
14808
|
-
|
|
14809
|
-
|
|
14810
|
-
|
|
14811
|
-
|
|
14887
|
+
raw = fs9.readFileSync(full, "utf-8");
|
|
14888
|
+
} catch (err) {
|
|
14889
|
+
warnings.push({ file: full, agent: path6.basename(entry.name, ".md"), message: `could not be read (${err.message}) \u2014 this agent was skipped` });
|
|
14890
|
+
continue;
|
|
14891
|
+
}
|
|
14892
|
+
const { meta, body, ok } = parseFrontmatter(raw);
|
|
14893
|
+
const name = (meta.name || path6.basename(entry.name, ".md")).trim();
|
|
14894
|
+
if (!name)
|
|
14895
|
+
continue;
|
|
14896
|
+
if (source2 !== "project" && into.has(name))
|
|
14897
|
+
continue;
|
|
14898
|
+
const tools = parseToolList(meta.tools);
|
|
14899
|
+
let effectiveTools = tools;
|
|
14900
|
+
if (!ok) {
|
|
14901
|
+
effectiveTools = READ_ONLY_TOOLS;
|
|
14902
|
+
warnings.push({
|
|
14903
|
+
file: full,
|
|
14904
|
+
agent: name,
|
|
14905
|
+
message: "has no valid YAML frontmatter (a `---` block must be the first thing in the file), so no tool allowlist could be read. Treating it as READ-ONLY. Add frontmatter with a `tools:` line to grant more."
|
|
14812
14906
|
});
|
|
14813
|
-
}
|
|
14907
|
+
} else {
|
|
14908
|
+
if (!meta.description) {
|
|
14909
|
+
warnings.push({
|
|
14910
|
+
file: full,
|
|
14911
|
+
agent: name,
|
|
14912
|
+
message: "has no `description:` \u2014 that text is the ONLY thing the model uses to decide when to delegate to this agent, so it will rarely be picked."
|
|
14913
|
+
});
|
|
14914
|
+
}
|
|
14915
|
+
if (meta.model !== void 0 && parseModel(meta.model) === void 0) {
|
|
14916
|
+
warnings.push({
|
|
14917
|
+
file: full,
|
|
14918
|
+
agent: name,
|
|
14919
|
+
message: `has model: "${meta.model}", which is not valid \u2014 use one of ${VALID_MODELS.join(", ")}, or omit the line to inherit the current session's model.`
|
|
14920
|
+
});
|
|
14921
|
+
}
|
|
14922
|
+
const unknown = (tools ?? []).filter((t2) => !KNOWN_TOOL_NAMES.has(t2) && !t2.includes("__"));
|
|
14923
|
+
if (unknown.length) {
|
|
14924
|
+
warnings.push({
|
|
14925
|
+
file: full,
|
|
14926
|
+
agent: name,
|
|
14927
|
+
message: `lists unknown tool name(s): ${unknown.join(", ")}. An allowlist only grants, so these silently do nothing and the agent cannot use them. Tool names are lower_snake_case (read_file, search_files, glob, bash).`
|
|
14928
|
+
});
|
|
14929
|
+
}
|
|
14930
|
+
const strayKeys = Object.keys(meta).filter((k) => !KNOWN_META_KEYS.has(k));
|
|
14931
|
+
if (strayKeys.length) {
|
|
14932
|
+
warnings.push({
|
|
14933
|
+
file: full,
|
|
14934
|
+
agent: name,
|
|
14935
|
+
message: `has unrecognised frontmatter key(s): ${strayKeys.join(", ")} \u2014 these are ignored.`
|
|
14936
|
+
});
|
|
14937
|
+
}
|
|
14938
|
+
if (!body) {
|
|
14939
|
+
warnings.push({
|
|
14940
|
+
file: full,
|
|
14941
|
+
agent: name,
|
|
14942
|
+
message: "has an empty body \u2014 the text below the frontmatter IS the agent's system prompt, so it currently has no instructions."
|
|
14943
|
+
});
|
|
14944
|
+
}
|
|
14814
14945
|
}
|
|
14946
|
+
into.set(name, {
|
|
14947
|
+
name,
|
|
14948
|
+
description: meta.description || `Custom ${name} agent`,
|
|
14949
|
+
tools: effectiveTools,
|
|
14950
|
+
model: parseModel(meta.model),
|
|
14951
|
+
prompt: body,
|
|
14952
|
+
source: source2,
|
|
14953
|
+
// Exposed to user/plugin definitions too — `test_files_only: true` (or
|
|
14954
|
+
// `testFilesOnly`) lets anyone build a test-writing agent that genuinely
|
|
14955
|
+
// cannot touch production source, rather than only the builtin getting
|
|
14956
|
+
// that guarantee.
|
|
14957
|
+
...parseBool(meta.test_files_only ?? meta.testfilesonly) ? { testFilesOnly: true } : {}
|
|
14958
|
+
});
|
|
14815
14959
|
}
|
|
14816
14960
|
}
|
|
14817
|
-
function
|
|
14961
|
+
function loadAgentTypes(workDir) {
|
|
14962
|
+
return loadAgentTypesWithWarnings2(workDir).types;
|
|
14963
|
+
}
|
|
14964
|
+
function loadAgentTypesWithWarnings2(workDir) {
|
|
14818
14965
|
const out = /* @__PURE__ */ new Map();
|
|
14819
|
-
|
|
14820
|
-
loadDir(path6.join(
|
|
14966
|
+
const warnings = [];
|
|
14967
|
+
loadDir(path6.join(workDir, ".nexrall", "agents"), "project", out, warnings);
|
|
14968
|
+
loadDir(path6.join(os6.homedir(), ".nexrall", "agents"), "global", out, warnings);
|
|
14821
14969
|
for (const dir of (0, index_1.pluginAssetDirs)(workDir, "agents"))
|
|
14822
|
-
loadDir(dir, "plugin", out);
|
|
14970
|
+
loadDir(dir, "plugin", out, warnings);
|
|
14823
14971
|
for (const agent of BUILTIN_AGENTS) {
|
|
14824
14972
|
if (!out.has(agent.name))
|
|
14825
14973
|
out.set(agent.name, agent);
|
|
14826
14974
|
}
|
|
14827
14975
|
const builtinOrder = new Map(BUILTIN_AGENTS.map((a, i2) => [a.name, i2]));
|
|
14828
|
-
|
|
14976
|
+
const types3 = [...out.values()].sort((a, b) => {
|
|
14829
14977
|
const ai = builtinOrder.get(a.name);
|
|
14830
14978
|
const bi = builtinOrder.get(b.name);
|
|
14831
14979
|
if (ai !== void 0 && bi !== void 0)
|
|
@@ -14836,6 +14984,13 @@ var require_agentTypes = __commonJS({
|
|
|
14836
14984
|
return 1;
|
|
14837
14985
|
return a.name.localeCompare(b.name);
|
|
14838
14986
|
});
|
|
14987
|
+
return { types: types3, warnings };
|
|
14988
|
+
}
|
|
14989
|
+
function knownToolNames() {
|
|
14990
|
+
return [...KNOWN_TOOL_NAMES].sort();
|
|
14991
|
+
}
|
|
14992
|
+
function builtinAgents() {
|
|
14993
|
+
return BUILTIN_AGENTS;
|
|
14839
14994
|
}
|
|
14840
14995
|
function summariseAgents(types3) {
|
|
14841
14996
|
if (!types3.length)
|
|
@@ -15255,7 +15410,7 @@ var require_loop = __commonJS({
|
|
|
15255
15410
|
};
|
|
15256
15411
|
}();
|
|
15257
15412
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15258
|
-
exports.VERIFY_CMD_RE = exports.WRITE_TOOL_NAMES = void 0;
|
|
15413
|
+
exports.VERIFY_CMD_RE = exports.WRITE_TOOL_NAMES = exports.ToolNotAllowedError = void 0;
|
|
15259
15414
|
exports.resolveMaxIterations = resolveMaxIterations;
|
|
15260
15415
|
exports.createLimiter = createLimiter;
|
|
15261
15416
|
exports.extractSubTaskText = extractSubTaskText;
|
|
@@ -15532,6 +15687,13 @@ var require_loop = __commonJS({
|
|
|
15532
15687
|
var _subTaskCounter = 0;
|
|
15533
15688
|
var SUBTASK_TIMEOUT_MS = Number(process.env.NEXRALL_SUBTASK_TIMEOUT_MS) > 0 ? Number(process.env.NEXRALL_SUBTASK_TIMEOUT_MS) : 10 * 60 * 1e3;
|
|
15534
15689
|
var SUBTASK_MAX = 48e3;
|
|
15690
|
+
var ToolNotAllowedError = class extends Error {
|
|
15691
|
+
constructor(message) {
|
|
15692
|
+
super(message);
|
|
15693
|
+
this.name = "ToolNotAllowedError";
|
|
15694
|
+
}
|
|
15695
|
+
};
|
|
15696
|
+
exports.ToolNotAllowedError = ToolNotAllowedError;
|
|
15535
15697
|
function sliceSafeEnd(s2, max) {
|
|
15536
15698
|
if (s2.length <= max)
|
|
15537
15699
|
return s2;
|
|
@@ -15595,10 +15757,18 @@ ${tail}`;
|
|
|
15595
15757
|
return { error: "Sub-agents cannot spawn further sub-agents. Do this work directly, or report back so the main agent can delegate it." };
|
|
15596
15758
|
}
|
|
15597
15759
|
const requestedType = typeof input.subagent_type === "string" ? input.subagent_type : "";
|
|
15598
|
-
|
|
15760
|
+
let agent = (0, agentTypes_1.findAgentType)(agentTypes, requestedType);
|
|
15761
|
+
let knownTypes = agentTypes;
|
|
15762
|
+
if (requestedType && !agent) {
|
|
15763
|
+
knownTypes = (0, agentTypes_1.loadAgentTypes)(options.workDir);
|
|
15764
|
+
agent = (0, agentTypes_1.findAgentType)(knownTypes, requestedType);
|
|
15765
|
+
}
|
|
15599
15766
|
if (requestedType && !agent) {
|
|
15600
|
-
const known =
|
|
15601
|
-
return {
|
|
15767
|
+
const known = knownTypes.map((a) => a.name).join(", ") || "(none defined)";
|
|
15768
|
+
return {
|
|
15769
|
+
error: `Unknown subagent_type "${requestedType}". Available types: ${known}.
|
|
15770
|
+
If you just created .nexrall/agents/` + requestedType + ".md, make sure the write finished in an EARLIER tool call than this one \u2014 a file written in the same batch may not be on disk yet."
|
|
15771
|
+
};
|
|
15602
15772
|
}
|
|
15603
15773
|
const subNexrallMd = agent ? `# Sub-agent role: ${agent.name}
|
|
15604
15774
|
${agent.prompt}` + (options.nexrallMd ? `
|
|
@@ -15608,10 +15778,12 @@ ${agent.prompt}` + (options.nexrallMd ? `
|
|
|
15608
15778
|
${options.nexrallMd}` : "") : options.nexrallMd;
|
|
15609
15779
|
const allowed = agent?.tools ? new Set(agent.tools) : null;
|
|
15610
15780
|
const gatedPermission = async (req) => {
|
|
15611
|
-
if (allowed && !allowed.has(req.tool))
|
|
15612
|
-
|
|
15613
|
-
|
|
15614
|
-
|
|
15781
|
+
if (allowed && !allowed.has(req.tool)) {
|
|
15782
|
+
throw new ToolNotAllowedError(`The "${agent.name}" sub-agent is not allowed to use \`${req.tool}\` \u2014 it is not in that agent's tool allowlist. This is a restriction of the agent definition, NOT a user decision: do not ask for approval, use one of the tools you do have, or report back that the task needs a different agent.`);
|
|
15783
|
+
}
|
|
15784
|
+
if (agent?.testFilesOnly && !allowsTestOnlyWrite(req.tool, req.input)) {
|
|
15785
|
+
throw new ToolNotAllowedError(`The "${agent.name}" sub-agent may only write to TEST files, so \`${req.tool}\` was refused for this path. Do not try to work around it: if production code must change, say so in your report instead.`);
|
|
15786
|
+
}
|
|
15615
15787
|
return options.requestPermission(req);
|
|
15616
15788
|
};
|
|
15617
15789
|
const subMessages = [
|
|
@@ -16297,13 +16469,16 @@ Continue the work from here.` }] });
|
|
|
16297
16469
|
}
|
|
16298
16470
|
const description = humanDescription(name, input);
|
|
16299
16471
|
let permitted;
|
|
16472
|
+
let deniedReason = null;
|
|
16300
16473
|
try {
|
|
16301
16474
|
permitted = await options.requestPermission({ tool: name, input, description });
|
|
16302
|
-
} catch {
|
|
16475
|
+
} catch (err) {
|
|
16303
16476
|
permitted = false;
|
|
16477
|
+
if (err instanceof ToolNotAllowedError)
|
|
16478
|
+
deniedReason = err.message;
|
|
16304
16479
|
}
|
|
16305
16480
|
if (!permitted) {
|
|
16306
|
-
result = { error: "Permission denied by user" };
|
|
16481
|
+
result = { error: deniedReason ?? "Permission denied by user" };
|
|
16307
16482
|
} else if (name === "task") {
|
|
16308
16483
|
result = depth === 0 ? await _subTaskLimit(() => runSubTask(input, options, agentTypes)) : await runSubTask(input, options, agentTypes);
|
|
16309
16484
|
} else {
|
|
@@ -17744,6 +17919,175 @@ var require_destructive = __commonJS({
|
|
|
17744
17919
|
}
|
|
17745
17920
|
});
|
|
17746
17921
|
|
|
17922
|
+
// ../core/dist/plugins/sources.js
|
|
17923
|
+
var require_sources = __commonJS({
|
|
17924
|
+
"../core/dist/plugins/sources.js"(exports) {
|
|
17925
|
+
"use strict";
|
|
17926
|
+
var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m2, k, k2) {
|
|
17927
|
+
if (k2 === void 0)
|
|
17928
|
+
k2 = k;
|
|
17929
|
+
var desc = Object.getOwnPropertyDescriptor(m2, k);
|
|
17930
|
+
if (!desc || ("get" in desc ? !m2.__esModule : desc.writable || desc.configurable)) {
|
|
17931
|
+
desc = { enumerable: true, get: function() {
|
|
17932
|
+
return m2[k];
|
|
17933
|
+
} };
|
|
17934
|
+
}
|
|
17935
|
+
Object.defineProperty(o, k2, desc);
|
|
17936
|
+
} : function(o, m2, k, k2) {
|
|
17937
|
+
if (k2 === void 0)
|
|
17938
|
+
k2 = k;
|
|
17939
|
+
o[k2] = m2[k];
|
|
17940
|
+
});
|
|
17941
|
+
var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? function(o, v) {
|
|
17942
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
17943
|
+
} : function(o, v) {
|
|
17944
|
+
o["default"] = v;
|
|
17945
|
+
});
|
|
17946
|
+
var __importStar = exports && exports.__importStar || /* @__PURE__ */ function() {
|
|
17947
|
+
var ownKeys = function(o) {
|
|
17948
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
17949
|
+
var ar = [];
|
|
17950
|
+
for (var k in o2)
|
|
17951
|
+
if (Object.prototype.hasOwnProperty.call(o2, k))
|
|
17952
|
+
ar[ar.length] = k;
|
|
17953
|
+
return ar;
|
|
17954
|
+
};
|
|
17955
|
+
return ownKeys(o);
|
|
17956
|
+
};
|
|
17957
|
+
return function(mod) {
|
|
17958
|
+
if (mod && mod.__esModule)
|
|
17959
|
+
return mod;
|
|
17960
|
+
var result = {};
|
|
17961
|
+
if (mod != null) {
|
|
17962
|
+
for (var k = ownKeys(mod), i2 = 0; i2 < k.length; i2++)
|
|
17963
|
+
if (k[i2] !== "default")
|
|
17964
|
+
__createBinding(result, mod, k[i2]);
|
|
17965
|
+
}
|
|
17966
|
+
__setModuleDefault(result, mod);
|
|
17967
|
+
return result;
|
|
17968
|
+
};
|
|
17969
|
+
}();
|
|
17970
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17971
|
+
exports.loadDeclaredSources = loadDeclaredSources2;
|
|
17972
|
+
exports.allowedSourcePatterns = allowedSourcePatterns2;
|
|
17973
|
+
exports.isSourceAllowed = isSourceAllowed2;
|
|
17974
|
+
exports.resolveSourceAlias = resolveSourceAlias2;
|
|
17975
|
+
exports.writeDeclaredSource = writeDeclaredSource2;
|
|
17976
|
+
exports.removeDeclaredSource = removeDeclaredSource2;
|
|
17977
|
+
exports.sourcesFileFor = sourcesFileFor2;
|
|
17978
|
+
var fs9 = __importStar(__require("fs"));
|
|
17979
|
+
var path6 = __importStar(__require("path"));
|
|
17980
|
+
var os6 = __importStar(__require("os"));
|
|
17981
|
+
function managedSettingsPath() {
|
|
17982
|
+
if (process.platform === "darwin")
|
|
17983
|
+
return "/Library/Application Support/Nexrall/managed-settings.json";
|
|
17984
|
+
if (process.platform === "win32")
|
|
17985
|
+
return path6.join(process.env.PROGRAMDATA ?? "C:\\ProgramData", "Nexrall", "managed-settings.json");
|
|
17986
|
+
return "/etc/nexrall/managed-settings.json";
|
|
17987
|
+
}
|
|
17988
|
+
function readJson(file) {
|
|
17989
|
+
try {
|
|
17990
|
+
return JSON.parse(fs9.readFileSync(file, "utf-8"));
|
|
17991
|
+
} catch {
|
|
17992
|
+
return null;
|
|
17993
|
+
}
|
|
17994
|
+
}
|
|
17995
|
+
var ALIAS_RE = /^[a-z0-9][\w.-]{0,63}$/i;
|
|
17996
|
+
function readSpec(value) {
|
|
17997
|
+
if (typeof value === "string")
|
|
17998
|
+
return value.trim() || null;
|
|
17999
|
+
if (value && typeof value === "object") {
|
|
18000
|
+
const v = value;
|
|
18001
|
+
const inner = v.source ?? v.repo ?? v.url;
|
|
18002
|
+
if (typeof inner === "string")
|
|
18003
|
+
return inner.trim() || null;
|
|
18004
|
+
if (inner && typeof inner === "object") {
|
|
18005
|
+
const deep = inner.repo ?? inner.url;
|
|
18006
|
+
if (typeof deep === "string")
|
|
18007
|
+
return deep.trim() || null;
|
|
18008
|
+
}
|
|
18009
|
+
}
|
|
18010
|
+
return null;
|
|
18011
|
+
}
|
|
18012
|
+
function collect(file, tier, into) {
|
|
18013
|
+
const obj = readJson(file);
|
|
18014
|
+
const raw = obj?.pluginSources;
|
|
18015
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
18016
|
+
return;
|
|
18017
|
+
for (const [name, value] of Object.entries(raw)) {
|
|
18018
|
+
if (!ALIAS_RE.test(name))
|
|
18019
|
+
continue;
|
|
18020
|
+
const spec = readSpec(value);
|
|
18021
|
+
if (!spec)
|
|
18022
|
+
continue;
|
|
18023
|
+
if (into.has(name))
|
|
18024
|
+
continue;
|
|
18025
|
+
into.set(name, { name, spec, tier, file });
|
|
18026
|
+
}
|
|
18027
|
+
}
|
|
18028
|
+
function loadDeclaredSources2(workDir, opts = {}) {
|
|
18029
|
+
const out = /* @__PURE__ */ new Map();
|
|
18030
|
+
collect(managedSettingsPath(), "managed", out);
|
|
18031
|
+
collect(path6.join(os6.homedir(), ".nexrall", "settings.json"), "user", out);
|
|
18032
|
+
if (opts.includeProject) {
|
|
18033
|
+
collect(path6.join(workDir, ".nexrall", "settings.json"), "project", out);
|
|
18034
|
+
collect(path6.join(workDir, ".nexrall", "settings.local.json"), "project", out);
|
|
18035
|
+
}
|
|
18036
|
+
return [...out.values()];
|
|
18037
|
+
}
|
|
18038
|
+
function allowedSourcePatterns2() {
|
|
18039
|
+
const obj = readJson(managedSettingsPath());
|
|
18040
|
+
const v = obj?.allowedPluginSources;
|
|
18041
|
+
if (!Array.isArray(v))
|
|
18042
|
+
return null;
|
|
18043
|
+
const pats = v.filter((x2) => typeof x2 === "string" && x2.trim().length > 0);
|
|
18044
|
+
return pats.length ? pats : null;
|
|
18045
|
+
}
|
|
18046
|
+
function isSourceAllowed2(spec, patterns = allowedSourcePatterns2()) {
|
|
18047
|
+
if (!patterns)
|
|
18048
|
+
return true;
|
|
18049
|
+
const cleaned = spec.trim().replace(/^https?:\/\/(?:www\.)?github\.com\//i, "").replace(/\.git$/, "");
|
|
18050
|
+
const base = cleaned.split("#")[0].split("/").slice(0, 2).join("/").toLowerCase();
|
|
18051
|
+
return patterns.some((p) => {
|
|
18052
|
+
const pat = p.trim().toLowerCase().replace(/^https?:\/\/(?:www\.)?github\.com\//i, "");
|
|
18053
|
+
if (pat === "*")
|
|
18054
|
+
return true;
|
|
18055
|
+
if (pat.endsWith("/*"))
|
|
18056
|
+
return base.startsWith(pat.slice(0, -1));
|
|
18057
|
+
return base === pat.split("#")[0].split("/").slice(0, 2).join("/");
|
|
18058
|
+
});
|
|
18059
|
+
}
|
|
18060
|
+
function resolveSourceAlias2(alias, workDir, opts = {}) {
|
|
18061
|
+
const want = alias.trim().toLowerCase();
|
|
18062
|
+
return loadDeclaredSources2(workDir, opts).find((s2) => s2.name.toLowerCase() === want) ?? null;
|
|
18063
|
+
}
|
|
18064
|
+
function writeDeclaredSource2(file, name, spec) {
|
|
18065
|
+
if (!ALIAS_RE.test(name)) {
|
|
18066
|
+
throw new Error(`Invalid source name "${name}". Use letters, numbers, dot, dash or underscore.`);
|
|
18067
|
+
}
|
|
18068
|
+
const obj = readJson(file) ?? {};
|
|
18069
|
+
const existing = obj.pluginSources && typeof obj.pluginSources === "object" && !Array.isArray(obj.pluginSources) ? obj.pluginSources : {};
|
|
18070
|
+
obj.pluginSources = { ...existing, [name]: spec };
|
|
18071
|
+
fs9.mkdirSync(path6.dirname(file), { recursive: true });
|
|
18072
|
+
fs9.writeFileSync(file, JSON.stringify(obj, null, 2) + "\n", "utf-8");
|
|
18073
|
+
}
|
|
18074
|
+
function removeDeclaredSource2(file, name) {
|
|
18075
|
+
const obj = readJson(file);
|
|
18076
|
+
if (!obj?.pluginSources || typeof obj.pluginSources !== "object")
|
|
18077
|
+
return false;
|
|
18078
|
+
const sources = obj.pluginSources;
|
|
18079
|
+
if (!(name in sources))
|
|
18080
|
+
return false;
|
|
18081
|
+
delete sources[name];
|
|
18082
|
+
fs9.writeFileSync(file, JSON.stringify(obj, null, 2) + "\n", "utf-8");
|
|
18083
|
+
return true;
|
|
18084
|
+
}
|
|
18085
|
+
function sourcesFileFor2(scope, workDir) {
|
|
18086
|
+
return scope === "user" ? path6.join(os6.homedir(), ".nexrall", "settings.json") : path6.join(workDir, ".nexrall", "settings.json");
|
|
18087
|
+
}
|
|
18088
|
+
}
|
|
18089
|
+
});
|
|
18090
|
+
|
|
17747
18091
|
// ../core/dist/plugins/installer.js
|
|
17748
18092
|
var require_installer = __commonJS({
|
|
17749
18093
|
"../core/dist/plugins/installer.js"(exports) {
|
|
@@ -17796,8 +18140,8 @@ var require_installer = __commonJS({
|
|
|
17796
18140
|
exports.searchRegistry = searchRegistry2;
|
|
17797
18141
|
exports.getRegistryPlugin = getRegistryPlugin2;
|
|
17798
18142
|
exports.reportInstall = reportInstall2;
|
|
17799
|
-
exports.parsePluginSource =
|
|
17800
|
-
exports.inspectPluginDir =
|
|
18143
|
+
exports.parsePluginSource = parsePluginSource2;
|
|
18144
|
+
exports.inspectPluginDir = inspectPluginDir2;
|
|
17801
18145
|
exports.installPlugin = installPlugin2;
|
|
17802
18146
|
exports.readReceipt = readReceipt2;
|
|
17803
18147
|
exports.removePlugin = removePlugin2;
|
|
@@ -17807,6 +18151,8 @@ var require_installer = __commonJS({
|
|
|
17807
18151
|
var os6 = __importStar(__require("os"));
|
|
17808
18152
|
var child_process_1 = __require("child_process");
|
|
17809
18153
|
var client_1 = require_client();
|
|
18154
|
+
var index_1 = require_plugins();
|
|
18155
|
+
var sources_1 = require_sources();
|
|
17810
18156
|
var RECEIPT_FILE = "_install.json";
|
|
17811
18157
|
async function searchRegistry2(query, limit = 50) {
|
|
17812
18158
|
const u = new URL(`${client_1.API_BASE}/api/code/plugins`);
|
|
@@ -17836,7 +18182,7 @@ var require_installer = __commonJS({
|
|
|
17836
18182
|
fetch(`${client_1.API_BASE}/api/code/plugins/${encodeURIComponent(name)}/installed`, { method: "POST" }).catch(() => {
|
|
17837
18183
|
});
|
|
17838
18184
|
}
|
|
17839
|
-
function
|
|
18185
|
+
function parsePluginSource2(spec) {
|
|
17840
18186
|
const raw = spec.trim();
|
|
17841
18187
|
if (!raw)
|
|
17842
18188
|
throw new Error("Empty plugin source.");
|
|
@@ -17883,29 +18229,45 @@ var require_installer = __commonJS({
|
|
|
17883
18229
|
return [];
|
|
17884
18230
|
}
|
|
17885
18231
|
}
|
|
17886
|
-
function
|
|
18232
|
+
function inspectPluginDir2(dir) {
|
|
17887
18233
|
let meta = {};
|
|
17888
|
-
|
|
17889
|
-
|
|
17890
|
-
|
|
17891
|
-
|
|
17892
|
-
|
|
17893
|
-
|
|
17894
|
-
|
|
17895
|
-
|
|
18234
|
+
const manifest = (0, index_1.resolvePluginFile)(dir, "manifest");
|
|
18235
|
+
if (manifest) {
|
|
18236
|
+
try {
|
|
18237
|
+
const j = JSON.parse(fs9.readFileSync(manifest, "utf-8"));
|
|
18238
|
+
meta = {
|
|
18239
|
+
name: typeof j.name === "string" ? j.name : void 0,
|
|
18240
|
+
version: typeof j.version === "string" ? j.version : void 0,
|
|
18241
|
+
description: typeof j.description === "string" ? j.description : void 0
|
|
18242
|
+
};
|
|
18243
|
+
} catch {
|
|
18244
|
+
}
|
|
17896
18245
|
}
|
|
17897
18246
|
return {
|
|
17898
18247
|
commands: listMd(path6.join(dir, "commands")),
|
|
17899
18248
|
agents: listMd(path6.join(dir, "agents")),
|
|
17900
|
-
hasHooks:
|
|
17901
|
-
hasMcp:
|
|
18249
|
+
hasHooks: (0, index_1.resolvePluginFile)(dir, "hooks") !== null,
|
|
18250
|
+
hasMcp: (0, index_1.resolvePluginFile)(dir, "mcp") !== null,
|
|
17902
18251
|
meta
|
|
17903
18252
|
};
|
|
17904
18253
|
}
|
|
17905
18254
|
function looksLikePlugin(dir) {
|
|
17906
|
-
const i2 =
|
|
18255
|
+
const i2 = inspectPluginDir2(dir);
|
|
17907
18256
|
return i2.commands.length > 0 || i2.agents.length > 0 || i2.hasHooks || i2.hasMcp || i2.meta.name !== void 0;
|
|
17908
18257
|
}
|
|
18258
|
+
async function resolveCommitSha(repo, ref) {
|
|
18259
|
+
try {
|
|
18260
|
+
const res = await fetch(`https://api.github.com/repos/${repo}/commits/${encodeURIComponent(ref || "HEAD")}`, {
|
|
18261
|
+
headers: { Accept: "application/vnd.github.sha", "User-Agent": "nexrall-code" }
|
|
18262
|
+
});
|
|
18263
|
+
if (!res.ok)
|
|
18264
|
+
return null;
|
|
18265
|
+
const sha = (await res.text()).trim();
|
|
18266
|
+
return /^[0-9a-f]{40}$/i.test(sha) ? sha : null;
|
|
18267
|
+
} catch {
|
|
18268
|
+
return null;
|
|
18269
|
+
}
|
|
18270
|
+
}
|
|
17909
18271
|
async function downloadTarball(repo, ref, destFile) {
|
|
17910
18272
|
const r2 = ref || "HEAD";
|
|
17911
18273
|
const url = `https://codeload.github.com/${repo}/tar.gz/${encodeURIComponent(r2)}`;
|
|
@@ -17956,28 +18318,33 @@ var require_installer = __commonJS({
|
|
|
17956
18318
|
return scope === "project" ? path6.join(workDir || process.cwd(), ".nexrall", "plugins") : path6.join(os6.homedir(), ".nexrall", "plugins");
|
|
17957
18319
|
}
|
|
17958
18320
|
async function installPlugin2(spec, opts = {}) {
|
|
17959
|
-
const
|
|
18321
|
+
const source2 = parsePluginSource2(spec);
|
|
17960
18322
|
const scope = opts.scope ?? "global";
|
|
18323
|
+
const patterns = (0, sources_1.allowedSourcePatterns)();
|
|
18324
|
+
if (patterns && source2.kind === "github" && !(0, sources_1.isSourceAllowed)(source2.raw, patterns)) {
|
|
18325
|
+
throw new Error(`Blocked by your organisation's policy: plugins may only be installed from ${patterns.join(", ")}.`);
|
|
18326
|
+
}
|
|
17961
18327
|
const tmpBase = fs9.mkdtempSync(path6.join(os6.tmpdir(), "nexrall-plugin-"));
|
|
17962
18328
|
try {
|
|
17963
18329
|
let repoRoot;
|
|
17964
|
-
if (
|
|
17965
|
-
if (!fs9.existsSync(
|
|
17966
|
-
throw new Error(`Local plugin path not found: ${
|
|
18330
|
+
if (source2.kind === "local") {
|
|
18331
|
+
if (!fs9.existsSync(source2.repo) || !fs9.statSync(source2.repo).isDirectory()) {
|
|
18332
|
+
throw new Error(`Local plugin path not found: ${source2.repo}`);
|
|
17967
18333
|
}
|
|
17968
|
-
repoRoot =
|
|
18334
|
+
repoRoot = source2.repo;
|
|
17969
18335
|
} else {
|
|
17970
18336
|
const tarFile = path6.join(tmpBase, "plugin.tar.gz");
|
|
17971
|
-
await downloadTarball(
|
|
18337
|
+
await downloadTarball(source2.repo, source2.ref, tarFile);
|
|
17972
18338
|
repoRoot = extractTarball(tarFile, path6.join(tmpBase, "x"));
|
|
17973
18339
|
}
|
|
17974
|
-
|
|
18340
|
+
const sha = source2.kind === "github" ? await resolveCommitSha(source2.repo, source2.ref) : null;
|
|
18341
|
+
let pluginRoot = source2.subdir ? path6.join(repoRoot, source2.subdir) : repoRoot;
|
|
17975
18342
|
pluginRoot = path6.resolve(pluginRoot);
|
|
17976
18343
|
if (!path6.resolve(pluginRoot).startsWith(path6.resolve(repoRoot))) {
|
|
17977
18344
|
throw new Error("Plugin subdirectory escapes the repository \u2014 refusing.");
|
|
17978
18345
|
}
|
|
17979
18346
|
if (!fs9.existsSync(pluginRoot) || !fs9.statSync(pluginRoot).isDirectory()) {
|
|
17980
|
-
throw new Error(`Subdirectory not found in repo: ${
|
|
18347
|
+
throw new Error(`Subdirectory not found in repo: ${source2.subdir}`);
|
|
17981
18348
|
}
|
|
17982
18349
|
if (!looksLikePlugin(pluginRoot)) {
|
|
17983
18350
|
const candidates = ["plugin", ".nexrall-plugin"].map((c) => path6.join(pluginRoot, c));
|
|
@@ -17988,12 +18355,16 @@ var require_installer = __commonJS({
|
|
|
17988
18355
|
throw new Error("No plugin found: expected plugin.json, commands/, agents/, hooks.json or mcp.json at the source root.");
|
|
17989
18356
|
}
|
|
17990
18357
|
}
|
|
17991
|
-
const inspection =
|
|
17992
|
-
const name = opts.name || inspection.meta.name || (
|
|
18358
|
+
const inspection = inspectPluginDir2(pluginRoot);
|
|
18359
|
+
const name = opts.name || inspection.meta.name || (source2.subdir ? path6.basename(source2.subdir) : void 0) || (source2.kind === "github" ? source2.repo.split("/")[1] : path6.basename(source2.repo));
|
|
17993
18360
|
if (!/^[\w.-]+$/.test(name))
|
|
17994
18361
|
throw new Error(`Invalid plugin name "${name}".`);
|
|
17995
18362
|
if (opts.confirm) {
|
|
17996
|
-
const ok = await opts.confirm(inspection, name
|
|
18363
|
+
const ok = await opts.confirm(inspection, name, {
|
|
18364
|
+
sha: sha ?? void 0,
|
|
18365
|
+
previousSha: opts._previousSha,
|
|
18366
|
+
isUpdate: Boolean(opts._previousSha) || Boolean(opts.force)
|
|
18367
|
+
});
|
|
17997
18368
|
if (!ok)
|
|
17998
18369
|
throw new Error("Installation cancelled.");
|
|
17999
18370
|
}
|
|
@@ -18006,14 +18377,15 @@ var require_installer = __commonJS({
|
|
|
18006
18377
|
}
|
|
18007
18378
|
copyPluginDir(pluginRoot, dest);
|
|
18008
18379
|
const receipt = {
|
|
18009
|
-
source:
|
|
18010
|
-
kind:
|
|
18011
|
-
ref:
|
|
18012
|
-
subdir:
|
|
18013
|
-
installedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
18380
|
+
source: source2.raw,
|
|
18381
|
+
kind: source2.kind,
|
|
18382
|
+
ref: source2.ref,
|
|
18383
|
+
subdir: source2.subdir,
|
|
18384
|
+
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
18385
|
+
...sha ? { sha } : {}
|
|
18014
18386
|
};
|
|
18015
18387
|
fs9.writeFileSync(path6.join(dest, RECEIPT_FILE), JSON.stringify(receipt, null, 2));
|
|
18016
|
-
return { name, dir: dest, scope, inspection };
|
|
18388
|
+
return { name, dir: dest, scope, inspection, sha: sha ?? void 0, previousSha: opts._previousSha };
|
|
18017
18389
|
} finally {
|
|
18018
18390
|
fs9.rmSync(tmpBase, { recursive: true, force: true });
|
|
18019
18391
|
}
|
|
@@ -18052,7 +18424,14 @@ var require_installer = __commonJS({
|
|
|
18052
18424
|
if (receipt.kind === "local") {
|
|
18053
18425
|
throw new Error(`Plugin "${name}" was installed from a local path \u2014 re-run 'nex plugin install ${receipt.source} --force'.`);
|
|
18054
18426
|
}
|
|
18055
|
-
return installPlugin2(receipt.source, {
|
|
18427
|
+
return installPlugin2(receipt.source, {
|
|
18428
|
+
scope: s2,
|
|
18429
|
+
workDir: opts.workDir,
|
|
18430
|
+
name,
|
|
18431
|
+
force: true,
|
|
18432
|
+
confirm: opts.confirm,
|
|
18433
|
+
_previousSha: receipt.sha
|
|
18434
|
+
});
|
|
18056
18435
|
}
|
|
18057
18436
|
throw new Error(`Plugin "${name}" is not installed.`);
|
|
18058
18437
|
}
|
|
@@ -18107,6 +18486,7 @@ var require_dist2 = __commonJS({
|
|
|
18107
18486
|
__exportStar(require_destructive(), exports);
|
|
18108
18487
|
__exportStar(require_plugins(), exports);
|
|
18109
18488
|
__exportStar(require_installer(), exports);
|
|
18489
|
+
__exportStar(require_sources(), exports);
|
|
18110
18490
|
}
|
|
18111
18491
|
});
|
|
18112
18492
|
|
|
@@ -20922,23 +21302,23 @@ var require_react_reconciler_production = __commonJS({
|
|
|
20922
21302
|
return "\nError generating stack: " + x2.message + "\n" + x2.stack;
|
|
20923
21303
|
}
|
|
20924
21304
|
}
|
|
20925
|
-
function createCapturedValueAtFiber(value,
|
|
21305
|
+
function createCapturedValueAtFiber(value, source2) {
|
|
20926
21306
|
if ("object" === typeof value && null !== value) {
|
|
20927
21307
|
var existing = CapturedStacks.get(value);
|
|
20928
21308
|
if (void 0 !== existing)
|
|
20929
21309
|
return existing;
|
|
20930
|
-
|
|
21310
|
+
source2 = {
|
|
20931
21311
|
value,
|
|
20932
|
-
source,
|
|
20933
|
-
stack: getStackByFiberInDevAndProd(
|
|
21312
|
+
source: source2,
|
|
21313
|
+
stack: getStackByFiberInDevAndProd(source2)
|
|
20934
21314
|
};
|
|
20935
|
-
CapturedStacks.set(value,
|
|
20936
|
-
return
|
|
21315
|
+
CapturedStacks.set(value, source2);
|
|
21316
|
+
return source2;
|
|
20937
21317
|
}
|
|
20938
21318
|
return {
|
|
20939
21319
|
value,
|
|
20940
|
-
source,
|
|
20941
|
-
stack: getStackByFiberInDevAndProd(
|
|
21320
|
+
source: source2,
|
|
21321
|
+
stack: getStackByFiberInDevAndProd(source2)
|
|
20942
21322
|
};
|
|
20943
21323
|
}
|
|
20944
21324
|
function pushTreeFork(workInProgress2, totalChildren) {
|
|
@@ -30110,23 +30490,23 @@ var require_react_reconciler_development = __commonJS({
|
|
|
30110
30490
|
function describeFunctionComponentFrameWithoutLineNumber(fn) {
|
|
30111
30491
|
return (fn = fn ? fn.displayName || fn.name : "") ? describeBuiltInComponentFrame(fn) : "";
|
|
30112
30492
|
}
|
|
30113
|
-
function createCapturedValueAtFiber(value,
|
|
30493
|
+
function createCapturedValueAtFiber(value, source2) {
|
|
30114
30494
|
if ("object" === typeof value && null !== value) {
|
|
30115
30495
|
var existing = CapturedStacks.get(value);
|
|
30116
30496
|
if (void 0 !== existing)
|
|
30117
30497
|
return existing;
|
|
30118
|
-
|
|
30498
|
+
source2 = {
|
|
30119
30499
|
value,
|
|
30120
|
-
source,
|
|
30121
|
-
stack: getStackByFiberInDevAndProd(
|
|
30500
|
+
source: source2,
|
|
30501
|
+
stack: getStackByFiberInDevAndProd(source2)
|
|
30122
30502
|
};
|
|
30123
|
-
CapturedStacks.set(value,
|
|
30124
|
-
return
|
|
30503
|
+
CapturedStacks.set(value, source2);
|
|
30504
|
+
return source2;
|
|
30125
30505
|
}
|
|
30126
30506
|
return {
|
|
30127
30507
|
value,
|
|
30128
|
-
source,
|
|
30129
|
-
stack: getStackByFiberInDevAndProd(
|
|
30508
|
+
source: source2,
|
|
30509
|
+
stack: getStackByFiberInDevAndProd(source2)
|
|
30130
30510
|
};
|
|
30131
30511
|
}
|
|
30132
30512
|
function pushTreeFork(workInProgress2, totalChildren) {
|
|
@@ -42684,9 +43064,9 @@ var require_buffer_util = __commonJS({
|
|
|
42684
43064
|
}
|
|
42685
43065
|
return target;
|
|
42686
43066
|
}
|
|
42687
|
-
function _mask(
|
|
43067
|
+
function _mask(source2, mask, output, offset, length) {
|
|
42688
43068
|
for (let i2 = 0; i2 < length; i2++) {
|
|
42689
|
-
output[offset + i2] =
|
|
43069
|
+
output[offset + i2] = source2[i2] ^ mask[i2 & 3];
|
|
42690
43070
|
}
|
|
42691
43071
|
}
|
|
42692
43072
|
function _unmask(buffer, mask) {
|
|
@@ -42725,11 +43105,11 @@ var require_buffer_util = __commonJS({
|
|
|
42725
43105
|
if (!process.env.WS_NO_BUFFER_UTIL) {
|
|
42726
43106
|
try {
|
|
42727
43107
|
const bufferUtil = __require("bufferutil");
|
|
42728
|
-
module.exports.mask = function(
|
|
43108
|
+
module.exports.mask = function(source2, mask, output, offset, length) {
|
|
42729
43109
|
if (length < 48)
|
|
42730
|
-
_mask(
|
|
43110
|
+
_mask(source2, mask, output, offset, length);
|
|
42731
43111
|
else
|
|
42732
|
-
bufferUtil.mask(
|
|
43112
|
+
bufferUtil.mask(source2, mask, output, offset, length);
|
|
42733
43113
|
};
|
|
42734
43114
|
module.exports.unmask = function(buffer, mask) {
|
|
42735
43115
|
if (buffer.length < 32)
|
|
@@ -49446,16 +49826,16 @@ var require_dist3 = __commonJS({
|
|
|
49446
49826
|
}
|
|
49447
49827
|
function _objectSpread(target) {
|
|
49448
49828
|
for (var i2 = 1; i2 < arguments.length; i2++) {
|
|
49449
|
-
var
|
|
49829
|
+
var source2 = arguments[i2] != null ? arguments[i2] : {};
|
|
49450
49830
|
if (i2 % 2) {
|
|
49451
|
-
ownKeys(Object(
|
|
49452
|
-
_defineProperty(target, key,
|
|
49831
|
+
ownKeys(Object(source2), true).forEach(function(key) {
|
|
49832
|
+
_defineProperty(target, key, source2[key]);
|
|
49453
49833
|
});
|
|
49454
49834
|
} else if (Object.getOwnPropertyDescriptors) {
|
|
49455
|
-
Object.defineProperties(target, Object.getOwnPropertyDescriptors(
|
|
49835
|
+
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source2));
|
|
49456
49836
|
} else {
|
|
49457
|
-
ownKeys(Object(
|
|
49458
|
-
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(
|
|
49837
|
+
ownKeys(Object(source2)).forEach(function(key) {
|
|
49838
|
+
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source2, key));
|
|
49459
49839
|
});
|
|
49460
49840
|
}
|
|
49461
49841
|
}
|
|
@@ -54175,6 +54555,16 @@ function trustGrantedByEnv() {
|
|
|
54175
54555
|
const v = process.env[TRUST_ENV_VAR];
|
|
54176
54556
|
return v === "1" || v === "true";
|
|
54177
54557
|
}
|
|
54558
|
+
function declaresPluginSources(dir) {
|
|
54559
|
+
try {
|
|
54560
|
+
const raw = fs5.readFileSync(path3.join(dir, ".nexrall", "settings.json"), "utf-8");
|
|
54561
|
+
const obj = JSON.parse(raw);
|
|
54562
|
+
const s2 = obj.pluginSources;
|
|
54563
|
+
return Boolean(s2 && typeof s2 === "object" && !Array.isArray(s2) && Object.keys(s2).length > 0);
|
|
54564
|
+
} catch {
|
|
54565
|
+
return false;
|
|
54566
|
+
}
|
|
54567
|
+
}
|
|
54178
54568
|
function detectTrustSignals(dir) {
|
|
54179
54569
|
const signals = [];
|
|
54180
54570
|
const exists = (...p) => {
|
|
@@ -54194,7 +54584,9 @@ function detectTrustSignals(dir) {
|
|
|
54194
54584
|
signals.push(".nexrall/permissions.json \u2014 pre-approved tool permissions");
|
|
54195
54585
|
}
|
|
54196
54586
|
if (exists(".nexrall", "settings.json")) {
|
|
54197
|
-
signals.push(
|
|
54587
|
+
signals.push(
|
|
54588
|
+
declaresPluginSources(dir) ? ".nexrall/settings.json \u2014 project settings, and declares plugin sources (aliases for remote plugin repos)" : ".nexrall/settings.json \u2014 project settings and permission rules"
|
|
54589
|
+
);
|
|
54198
54590
|
}
|
|
54199
54591
|
if (exists("nexrall.md")) {
|
|
54200
54592
|
signals.push("nexrall.md \u2014 project instructions added to the agent\u2019s prompt");
|
|
@@ -60703,15 +61095,15 @@ var generateLineNumbers = (line, around) => {
|
|
|
60703
61095
|
}
|
|
60704
61096
|
return lineNumbers;
|
|
60705
61097
|
};
|
|
60706
|
-
var codeExcerpt = (
|
|
61098
|
+
var codeExcerpt = (source2, line, options = {}) => {
|
|
60707
61099
|
var _a;
|
|
60708
|
-
if (typeof
|
|
61100
|
+
if (typeof source2 !== "string") {
|
|
60709
61101
|
throw new TypeError("Source code is missing.");
|
|
60710
61102
|
}
|
|
60711
61103
|
if (!line || line < 1) {
|
|
60712
61104
|
throw new TypeError("Line number must start from `1`.");
|
|
60713
61105
|
}
|
|
60714
|
-
const lines = dist_default3(
|
|
61106
|
+
const lines = dist_default3(source2).split(/\r?\n/);
|
|
60715
61107
|
if (line > lines.length) {
|
|
60716
61108
|
return;
|
|
60717
61109
|
}
|
|
@@ -63166,7 +63558,7 @@ var InkReadlineAdapter = class extends EventEmitter3 {
|
|
|
63166
63558
|
};
|
|
63167
63559
|
|
|
63168
63560
|
// src/commands/chat.ts
|
|
63169
|
-
var CLI_VERSION = "0.5.
|
|
63561
|
+
var CLI_VERSION = "0.5.50";
|
|
63170
63562
|
var MODEL_LABELS = {
|
|
63171
63563
|
turbo: "Nexrall Turbo",
|
|
63172
63564
|
pro: "Nexrall Pro",
|
|
@@ -63384,15 +63776,23 @@ function formatContextUsage(messages, modelAlias) {
|
|
|
63384
63776
|
return lines.join("\n");
|
|
63385
63777
|
}
|
|
63386
63778
|
function formatAgentsList(workDir) {
|
|
63387
|
-
const types3 = (0, import_code_core3.
|
|
63779
|
+
const { types: types3, warnings } = (0, import_code_core3.loadAgentTypesWithWarnings)(workDir);
|
|
63388
63780
|
if (!types3.length)
|
|
63389
63781
|
return source_default.dim(" No agent types found (this should not happen \u2014 builtins always register).");
|
|
63390
63782
|
const lines = types3.map((t2) => {
|
|
63391
|
-
const tools = t2.tools ? source_default.dim(` \u2014 tools: ${t2.tools.join(", ")}`) : source_default.dim(" \u2014
|
|
63783
|
+
const tools = t2.tools ? source_default.dim(` \u2014 tools: ${t2.tools.join(", ")}`) : source_default.dim(" \u2014 ALL tools (no allowlist)");
|
|
63392
63784
|
const model = t2.model ? source_default.dim(` \u2014 model: ${t2.model}`) : "";
|
|
63393
63785
|
const scope = source_default.dim(` (${t2.source})`);
|
|
63394
63786
|
return " " + source_default.cyan(t2.name.padEnd(16)) + source_default.white(t2.description) + scope + tools + model;
|
|
63395
63787
|
});
|
|
63788
|
+
if (warnings.length) {
|
|
63789
|
+
lines.push("");
|
|
63790
|
+
lines.push(" " + source_default.yellow.bold(`\u26A0 ${warnings.length} problem${warnings.length > 1 ? "s" : ""} in your agent definitions:`));
|
|
63791
|
+
for (const w of warnings) {
|
|
63792
|
+
lines.push(" " + source_default.yellow(`\u2022 ${w.agent}`) + source_default.dim(` \u2014 ${w.message}`));
|
|
63793
|
+
lines.push(" " + source_default.dim(w.file));
|
|
63794
|
+
}
|
|
63795
|
+
}
|
|
63396
63796
|
return lines.join("\n");
|
|
63397
63797
|
}
|
|
63398
63798
|
async function runTurn(messages, modelAlias, workDir, abortSignal, env3, nexrallMd, mode, effort, checkpointManager, onProgress) {
|
|
@@ -64509,11 +64909,23 @@ ${caption}` : `[Attached: ${rel}]`;
|
|
|
64509
64909
|
// src/commands/plugin.ts
|
|
64510
64910
|
var import_prompts = __toESM(require_prompts3(), 1);
|
|
64511
64911
|
var import_code_core4 = __toESM(require_dist2(), 1);
|
|
64512
|
-
function describeInspection(i2, name) {
|
|
64912
|
+
function describeInspection(i2, name, ctx) {
|
|
64513
64913
|
console.log();
|
|
64514
64914
|
console.log(source_default.bold(` Plugin: ${name}`) + (i2.meta.version ? source_default.dim(` v${i2.meta.version}`) : ""));
|
|
64515
64915
|
if (i2.meta.description)
|
|
64516
64916
|
console.log(source_default.dim(` ${i2.meta.description}`));
|
|
64917
|
+
if (ctx?.sha) {
|
|
64918
|
+
const short = (s2) => s2.slice(0, 7);
|
|
64919
|
+
if (ctx.previousSha && ctx.previousSha !== ctx.sha) {
|
|
64920
|
+
console.log(source_default.dim(" commit: ") + source_default.yellow(`${short(ctx.previousSha)} \u2192 ${short(ctx.sha)}`));
|
|
64921
|
+
} else if (ctx.previousSha === ctx.sha) {
|
|
64922
|
+
console.log(source_default.dim(` commit: ${short(ctx.sha)} (already up to date)`));
|
|
64923
|
+
} else {
|
|
64924
|
+
console.log(source_default.dim(` commit: ${short(ctx.sha)}`));
|
|
64925
|
+
}
|
|
64926
|
+
} else if (ctx?.isUpdate) {
|
|
64927
|
+
console.log(source_default.dim(" commit: unknown (could not reach the GitHub API)"));
|
|
64928
|
+
}
|
|
64517
64929
|
if (i2.commands.length)
|
|
64518
64930
|
console.log(` ${source_default.cyan("commands:")} ${i2.commands.map((c) => "/" + c).join(", ")}`);
|
|
64519
64931
|
if (i2.agents.length)
|
|
@@ -64523,10 +64935,16 @@ function describeInspection(i2, name) {
|
|
|
64523
64935
|
if (i2.hasMcp)
|
|
64524
64936
|
console.log(` ${source_default.yellow("mcp:")} yes`);
|
|
64525
64937
|
}
|
|
64526
|
-
async function confirmInstall(i2, name, autoYes) {
|
|
64527
|
-
describeInspection(i2, name);
|
|
64938
|
+
async function confirmInstall(i2, name, autoYes, ctx) {
|
|
64939
|
+
describeInspection(i2, name, ctx);
|
|
64528
64940
|
const dangerous = i2.hasHooks || i2.hasMcp;
|
|
64529
64941
|
if (dangerous) {
|
|
64942
|
+
if (ctx?.isUpdate) {
|
|
64943
|
+
console.log();
|
|
64944
|
+
console.log(source_default.red.bold(" \u26A0 THIS UPDATE SHIPS CODE EXECUTION"));
|
|
64945
|
+
console.log(source_default.red(" A version of this plugin you already trust is being replaced by one"));
|
|
64946
|
+
console.log(source_default.red(" that runs commands. Review the diff before continuing."));
|
|
64947
|
+
}
|
|
64530
64948
|
console.log();
|
|
64531
64949
|
console.log(source_default.red.bold(" \u26A0 SECURITY WARNING"));
|
|
64532
64950
|
if (i2.hasHooks) {
|
|
@@ -64562,35 +64980,43 @@ async function confirmInstall(i2, name, autoYes) {
|
|
|
64562
64980
|
async function pluginInstallCommand(spec, opts) {
|
|
64563
64981
|
const scope = opts.project ? "project" : "global";
|
|
64564
64982
|
try {
|
|
64565
|
-
let
|
|
64983
|
+
let source2 = spec;
|
|
64566
64984
|
let registryName;
|
|
64567
64985
|
const isShortName = /^[\w.-]+$/.test(spec.trim()) && !spec.includes("/");
|
|
64568
64986
|
if (isShortName) {
|
|
64987
|
+
const alias = (0, import_code_core4.resolveSourceAlias)(spec.trim(), process.cwd(), { includeProject: true });
|
|
64988
|
+
if (alias) {
|
|
64989
|
+
source2 = alias.spec;
|
|
64990
|
+
console.log(source_default.dim(` Source: ${alias.name} (${alias.tier}) \u2190 ${alias.spec}`));
|
|
64991
|
+
}
|
|
64992
|
+
}
|
|
64993
|
+
if (isShortName && source2 === spec) {
|
|
64569
64994
|
const entry = await (0, import_code_core4.getRegistryPlugin)(spec.trim()).catch(() => null);
|
|
64570
64995
|
if (entry) {
|
|
64571
|
-
|
|
64996
|
+
source2 = entry.source;
|
|
64572
64997
|
registryName = entry.name;
|
|
64573
64998
|
const badge = entry.official ? source_default.magenta(" [official]") : entry.verified ? source_default.green(" [verified]") : "";
|
|
64574
64999
|
console.log(source_default.dim(` Registry: ${entry.display_name}${badge} \u2190 ${entry.source}`));
|
|
64575
65000
|
} else {
|
|
64576
|
-
console.error(source_default.red(` \u2717 "${spec}" not
|
|
64577
|
-
console.error(source_default.dim(" Search:
|
|
64578
|
-
console.error(source_default.dim("
|
|
65001
|
+
console.error(source_default.red(` \u2717 "${spec}" is not a declared source or a registry plugin.`));
|
|
65002
|
+
console.error(source_default.dim(" Search: nex plugin search <keyword>"));
|
|
65003
|
+
console.error(source_default.dim(" From GitHub: nex plugin install owner/repo"));
|
|
65004
|
+
console.error(source_default.dim(" Declare it: nex plugin source add " + spec.trim() + " owner/repo"));
|
|
64579
65005
|
process.exitCode = 1;
|
|
64580
65006
|
return;
|
|
64581
65007
|
}
|
|
64582
65008
|
}
|
|
64583
|
-
const res = await (0, import_code_core4.installPlugin)(
|
|
65009
|
+
const res = await (0, import_code_core4.installPlugin)(source2, {
|
|
64584
65010
|
scope,
|
|
64585
65011
|
workDir: process.cwd(),
|
|
64586
65012
|
name: opts.name ?? registryName,
|
|
64587
65013
|
force: opts.force,
|
|
64588
|
-
confirm: (i2, name) => confirmInstall(i2, name, opts.yes === true)
|
|
65014
|
+
confirm: (i2, name, ctx) => confirmInstall(i2, name, opts.yes === true, ctx)
|
|
64589
65015
|
});
|
|
64590
65016
|
if (registryName)
|
|
64591
65017
|
(0, import_code_core4.reportInstall)(registryName);
|
|
64592
65018
|
console.log();
|
|
64593
|
-
console.log(source_default.green(` \u2713 Installed "${res.name}" (${res.scope}) \u2192 ${res.dir}`));
|
|
65019
|
+
console.log(source_default.green(` \u2713 Installed "${res.name}" (${res.scope}) \u2192 ${res.dir}`) + (res.sha ? source_default.dim(` @ ${res.sha.slice(0, 7)}`) : ""));
|
|
64594
65020
|
if (res.inspection.commands.length) {
|
|
64595
65021
|
console.log(source_default.dim(` Try: ${res.inspection.commands.map((c) => "/" + c).join(", ")}`));
|
|
64596
65022
|
}
|
|
@@ -64624,9 +65050,10 @@ async function pluginUpdateCommand(name, opts) {
|
|
|
64624
65050
|
try {
|
|
64625
65051
|
const res = await (0, import_code_core4.updatePlugin)(t2, {
|
|
64626
65052
|
workDir,
|
|
64627
|
-
confirm: (i2, n) => confirmInstall(i2, n, opts.yes === true)
|
|
65053
|
+
confirm: (i2, n, ctx) => confirmInstall(i2, n, opts.yes === true, ctx)
|
|
64628
65054
|
});
|
|
64629
|
-
|
|
65055
|
+
const moved = res.sha && res.previousSha && res.sha !== res.previousSha ? source_default.dim(` ${res.previousSha.slice(0, 7)} \u2192 ${res.sha.slice(0, 7)}`) : res.sha && res.previousSha === res.sha ? source_default.dim(" (unchanged)") : "";
|
|
65056
|
+
console.log(source_default.green(` \u2713 Updated "${res.name}"`) + moved);
|
|
64630
65057
|
} catch (err) {
|
|
64631
65058
|
console.error(source_default.red(` \u2717 ${t2}: ${err.message}`));
|
|
64632
65059
|
process.exitCode = 1;
|
|
@@ -64708,24 +65135,98 @@ function pluginListCommand() {
|
|
|
64708
65135
|
for (const p of plugins) {
|
|
64709
65136
|
const receipt = (0, import_code_core4.readReceipt)(p.dir);
|
|
64710
65137
|
const src = receipt ? source_default.dim(` \u2190 ${receipt.source}`) : source_default.dim(" (manual)");
|
|
65138
|
+
const at = receipt?.sha ? source_default.dim(` @ ${receipt.sha.slice(0, 7)}`) : "";
|
|
65139
|
+
const insp = (0, import_code_core4.inspectPluginDir)(p.dir);
|
|
65140
|
+
const runs = insp.hasHooks || insp.hasMcp ? source_default.yellow(` \u26A0 ${[insp.hasHooks && "hooks", insp.hasMcp && "mcp"].filter(Boolean).join("+")}`) : "";
|
|
64711
65141
|
console.log(
|
|
64712
|
-
" " + source_default.cyan(p.name.padEnd(24)) + source_default.dim(`${(p.version ?? "").padEnd(10)}${p.scope.padEnd(9)}`) + src
|
|
65142
|
+
" " + source_default.cyan(p.name.padEnd(24)) + source_default.dim(`${(p.version ?? "").padEnd(10)}${p.scope.padEnd(9)}`) + src + at + runs
|
|
64713
65143
|
);
|
|
64714
65144
|
}
|
|
64715
65145
|
console.log();
|
|
64716
65146
|
}
|
|
65147
|
+
function pluginSourceListCommand() {
|
|
65148
|
+
const workDir = process.cwd();
|
|
65149
|
+
const sources = (0, import_code_core4.loadDeclaredSources)(workDir, { includeProject: true });
|
|
65150
|
+
const patterns = (0, import_code_core4.allowedSourcePatterns)();
|
|
65151
|
+
if (patterns) {
|
|
65152
|
+
console.log();
|
|
65153
|
+
console.log(source_default.bold(" Organisation policy: ") + source_default.dim(`installs restricted to ${patterns.join(", ")}`));
|
|
65154
|
+
}
|
|
65155
|
+
if (!sources.length) {
|
|
65156
|
+
console.log(source_default.dim("\n No plugin sources declared."));
|
|
65157
|
+
console.log(source_default.dim(" Add one: nex plugin source add <alias> owner/repo"));
|
|
65158
|
+
console.log();
|
|
65159
|
+
return;
|
|
65160
|
+
}
|
|
65161
|
+
console.log();
|
|
65162
|
+
console.log(source_default.bold(" Declared plugin sources:"));
|
|
65163
|
+
for (const s2 of sources) {
|
|
65164
|
+
const tier = s2.tier === "project" ? source_default.yellow(s2.tier.padEnd(9)) : source_default.dim(s2.tier.padEnd(9));
|
|
65165
|
+
const blocked = !(0, import_code_core4.isSourceAllowed)(s2.spec, patterns) ? source_default.red(" \u2717 blocked by policy") : "";
|
|
65166
|
+
console.log(" " + source_default.cyan(s2.name.padEnd(20)) + tier + source_default.white(s2.spec) + blocked);
|
|
65167
|
+
}
|
|
65168
|
+
console.log();
|
|
65169
|
+
console.log(source_default.dim(" Install from one: nex plugin install <alias>"));
|
|
65170
|
+
console.log(source_default.dim(" Declaring a source does not install anything."));
|
|
65171
|
+
console.log();
|
|
65172
|
+
}
|
|
65173
|
+
function pluginSourceAddCommand(name, spec, opts) {
|
|
65174
|
+
try {
|
|
65175
|
+
(0, import_code_core4.parsePluginSource)(spec);
|
|
65176
|
+
const patterns = (0, import_code_core4.allowedSourcePatterns)();
|
|
65177
|
+
if (patterns && !(0, import_code_core4.isSourceAllowed)(spec, patterns)) {
|
|
65178
|
+
console.error(source_default.red(` \u2717 "${spec}" is not permitted by your organisation's policy.`));
|
|
65179
|
+
console.error(source_default.dim(` Allowed: ${patterns.join(", ")}`));
|
|
65180
|
+
process.exitCode = 1;
|
|
65181
|
+
return;
|
|
65182
|
+
}
|
|
65183
|
+
const scope = opts.project ? "project" : "user";
|
|
65184
|
+
const file = (0, import_code_core4.sourcesFileFor)(scope, process.cwd());
|
|
65185
|
+
(0, import_code_core4.writeDeclaredSource)(file, name, spec);
|
|
65186
|
+
console.log();
|
|
65187
|
+
console.log(source_default.green(` \u2713 Declared "${name}" \u2192 ${spec}`) + source_default.dim(` (${scope})`));
|
|
65188
|
+
console.log(source_default.dim(` ${file}`));
|
|
65189
|
+
console.log(source_default.dim(` Nothing installed yet \u2014 run: nex plugin install ${name}`));
|
|
65190
|
+
console.log();
|
|
65191
|
+
} catch (err) {
|
|
65192
|
+
console.error(source_default.red(` \u2717 ${err.message}`));
|
|
65193
|
+
process.exitCode = 1;
|
|
65194
|
+
}
|
|
65195
|
+
}
|
|
65196
|
+
function pluginSourceRemoveCommand(name, opts) {
|
|
65197
|
+
const workDir = process.cwd();
|
|
65198
|
+
const scope = opts.project ? "project" : "user";
|
|
65199
|
+
const file = (0, import_code_core4.sourcesFileFor)(scope, workDir);
|
|
65200
|
+
if ((0, import_code_core4.removeDeclaredSource)(file, name)) {
|
|
65201
|
+
console.log(source_default.green(` \u2713 Removed source "${name}" (${scope})`));
|
|
65202
|
+
console.log(source_default.dim(" Plugins already installed from it are untouched \u2014 remove them with nex plugin remove <name>"));
|
|
65203
|
+
return;
|
|
65204
|
+
}
|
|
65205
|
+
const found = (0, import_code_core4.resolveSourceAlias)(name, workDir, { includeProject: true });
|
|
65206
|
+
if (found) {
|
|
65207
|
+
console.error(source_default.red(` \u2717 "${name}" is declared in the ${found.tier} tier, not ${scope}.`));
|
|
65208
|
+
console.error(source_default.dim(` ${found.file}`));
|
|
65209
|
+
if (found.tier === "project")
|
|
65210
|
+
console.error(source_default.dim(" Retry with --project"));
|
|
65211
|
+
if (found.tier === "managed")
|
|
65212
|
+
console.error(source_default.dim(" Managed sources are set by your organisation and cannot be removed here."));
|
|
65213
|
+
} else {
|
|
65214
|
+
console.error(source_default.red(` \u2717 No source named "${name}".`));
|
|
65215
|
+
}
|
|
65216
|
+
process.exitCode = 1;
|
|
65217
|
+
}
|
|
64717
65218
|
|
|
64718
65219
|
// src/index.ts
|
|
64719
65220
|
var program2 = new Command();
|
|
64720
|
-
program2.name("nex").description("Nexrall Code \u2014 AI coding assistant (powered by Nexrall)").version("0.5.
|
|
65221
|
+
program2.name("nex").description("Nexrall Code \u2014 AI coding assistant (powered by Nexrall)").version("0.5.50").enablePositionalOptions();
|
|
64721
65222
|
program2.command("auth").description("Login to your Nexrall account").action(authCommand);
|
|
64722
65223
|
program2.command("logout").description("Log out of your Nexrall account").action(logoutCommand);
|
|
64723
65224
|
program2.command("update").description("Update nex to the latest version").option("-c, --check", "Check for updates without installing").option("-y, --yes", "Skip confirmation prompt").action(async (opts) => {
|
|
64724
65225
|
await updateCommand({ check: opts.check, yes: opts.yes });
|
|
64725
65226
|
});
|
|
64726
65227
|
var plugin = program2.command("plugin").description("Manage plugins (install from GitHub, list, update, remove)");
|
|
64727
|
-
plugin.command("install <source>").description("Install a plugin: registry name, owner/repo(#ref)(/subdir), GitHub URL, or local path").option("--project", "Install into ./.nexrall/plugins (default: ~/.nexrall/plugins)").option("--name <name>", "Override the installed plugin name").option("-f, --force", "Overwrite if already installed").option("-y, --yes", "Skip confirmation (still prompts for plugins with hooks/MCP)").action(async (
|
|
64728
|
-
await pluginInstallCommand(
|
|
65228
|
+
plugin.command("install <source>").description("Install a plugin: registry name, owner/repo(#ref)(/subdir), GitHub URL, or local path").option("--project", "Install into ./.nexrall/plugins (default: ~/.nexrall/plugins)").option("--name <name>", "Override the installed plugin name").option("-f, --force", "Overwrite if already installed").option("-y, --yes", "Skip confirmation (still prompts for plugins with hooks/MCP)").action(async (source2, opts) => {
|
|
65229
|
+
await pluginInstallCommand(source2, opts);
|
|
64729
65230
|
});
|
|
64730
65231
|
plugin.command("remove <name>").alias("uninstall").description("Remove an installed plugin").option("--project", "Only look in ./.nexrall/plugins").action((name, opts) => {
|
|
64731
65232
|
pluginRemoveCommand(name, opts);
|
|
@@ -64742,6 +65243,16 @@ plugin.command("search [query]").description("Search the Nexrall plugin registry
|
|
|
64742
65243
|
plugin.command("info <name>").description("Show registry details for a plugin").action(async (name) => {
|
|
64743
65244
|
await pluginInfoCommand(name);
|
|
64744
65245
|
});
|
|
65246
|
+
var source = plugin.command("source").description("Declare where plugins may be installed from (aliases for plugin repos)");
|
|
65247
|
+
source.command("list").alias("ls").description("List declared plugin sources").action(() => {
|
|
65248
|
+
pluginSourceListCommand();
|
|
65249
|
+
});
|
|
65250
|
+
source.command("add <name> <spec>").description("Declare a source: nex plugin source add acme acme/plugins").option("--project", "Write to ./.nexrall/settings.json so the team shares it (default: ~/.nexrall/settings.json)").action((name, spec, opts) => {
|
|
65251
|
+
pluginSourceAddCommand(name, spec, opts);
|
|
65252
|
+
});
|
|
65253
|
+
source.command("remove <name>").alias("rm").description("Remove a declared source (installed plugins are untouched)").option("--project", "Remove from ./.nexrall/settings.json").action((name, opts) => {
|
|
65254
|
+
pluginSourceRemoveCommand(name, opts);
|
|
65255
|
+
});
|
|
64745
65256
|
program2.command("sessions").description("List or delete saved chat sessions").option("-d, --delete <id>", "Delete a session by id").option("--clear-all", "Delete ALL saved sessions").action((opts) => {
|
|
64746
65257
|
if (opts.clearAll) {
|
|
64747
65258
|
const sessions2 = listSessions();
|