@jaggerxtrm/specialists 2.1.10 → 2.1.11
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 +207 -8
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -17688,26 +17688,217 @@ var init_list = __esm(() => {
|
|
|
17688
17688
|
};
|
|
17689
17689
|
});
|
|
17690
17690
|
|
|
17691
|
+
// src/cli/init.ts
|
|
17692
|
+
var exports_init = {};
|
|
17693
|
+
__export(exports_init, {
|
|
17694
|
+
run: () => run4
|
|
17695
|
+
});
|
|
17696
|
+
import { existsSync as existsSync3, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
17697
|
+
import { join as join5 } from "node:path";
|
|
17698
|
+
function ok(msg) {
|
|
17699
|
+
console.log(` ${green("✓")} ${msg}`);
|
|
17700
|
+
}
|
|
17701
|
+
function skip(msg) {
|
|
17702
|
+
console.log(` ${yellow2("○")} ${msg}`);
|
|
17703
|
+
}
|
|
17704
|
+
async function run4() {
|
|
17705
|
+
const cwd = process.cwd();
|
|
17706
|
+
console.log(`
|
|
17707
|
+
${bold2("specialists init")}
|
|
17708
|
+
`);
|
|
17709
|
+
const specialistsDir = join5(cwd, "specialists");
|
|
17710
|
+
if (existsSync3(specialistsDir)) {
|
|
17711
|
+
skip("specialists/ already exists");
|
|
17712
|
+
} else {
|
|
17713
|
+
mkdirSync(specialistsDir, { recursive: true });
|
|
17714
|
+
ok("created specialists/");
|
|
17715
|
+
}
|
|
17716
|
+
const agentsPath = join5(cwd, "AGENTS.md");
|
|
17717
|
+
if (existsSync3(agentsPath)) {
|
|
17718
|
+
const existing = readFileSync(agentsPath, "utf-8");
|
|
17719
|
+
if (existing.includes(AGENTS_MARKER)) {
|
|
17720
|
+
skip("AGENTS.md already has Specialists section");
|
|
17721
|
+
} else {
|
|
17722
|
+
writeFileSync(agentsPath, existing.trimEnd() + `
|
|
17723
|
+
|
|
17724
|
+
` + AGENTS_BLOCK, "utf-8");
|
|
17725
|
+
ok("appended Specialists section to AGENTS.md");
|
|
17726
|
+
}
|
|
17727
|
+
} else {
|
|
17728
|
+
writeFileSync(agentsPath, AGENTS_BLOCK, "utf-8");
|
|
17729
|
+
ok("created AGENTS.md with Specialists section");
|
|
17730
|
+
}
|
|
17731
|
+
console.log(`
|
|
17732
|
+
${bold2("Done!")}
|
|
17733
|
+
`);
|
|
17734
|
+
console.log(` ${dim2("Next steps:")}`);
|
|
17735
|
+
console.log(` 1. Add your specialists to ${yellow2("specialists/")}`);
|
|
17736
|
+
console.log(` 2. Run ${yellow2("specialists list")} to verify they are discovered`);
|
|
17737
|
+
console.log(` 3. Restart Claude Code to pick up AGENTS.md changes
|
|
17738
|
+
`);
|
|
17739
|
+
}
|
|
17740
|
+
var bold2 = (s) => `\x1B[1m${s}\x1B[0m`, green = (s) => `\x1B[32m${s}\x1B[0m`, yellow2 = (s) => `\x1B[33m${s}\x1B[0m`, dim2 = (s) => `\x1B[2m${s}\x1B[0m`, AGENTS_BLOCK, AGENTS_MARKER = "## Specialists";
|
|
17741
|
+
var init_init = __esm(() => {
|
|
17742
|
+
AGENTS_BLOCK = `
|
|
17743
|
+
## Specialists
|
|
17744
|
+
|
|
17745
|
+
Call \`specialist_init\` at the start of every session to bootstrap context and
|
|
17746
|
+
see available specialists. Use \`use_specialist\` or \`start_specialist\` to
|
|
17747
|
+
delegate heavy tasks (code review, bug hunting, deep reasoning) to the right
|
|
17748
|
+
specialist without user intervention.
|
|
17749
|
+
`.trimStart();
|
|
17750
|
+
});
|
|
17751
|
+
|
|
17752
|
+
// src/cli/edit.ts
|
|
17753
|
+
var exports_edit = {};
|
|
17754
|
+
__export(exports_edit, {
|
|
17755
|
+
run: () => run5
|
|
17756
|
+
});
|
|
17757
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
17758
|
+
function parseArgs2(argv) {
|
|
17759
|
+
const name = argv[0];
|
|
17760
|
+
if (!name || name.startsWith("--")) {
|
|
17761
|
+
console.error("Usage: specialists edit <name> --<field> <value> [--dry-run]");
|
|
17762
|
+
console.error(` Fields: ${Object.keys(FIELD_MAP).join(", ")}`);
|
|
17763
|
+
process.exit(1);
|
|
17764
|
+
}
|
|
17765
|
+
let field;
|
|
17766
|
+
let value;
|
|
17767
|
+
let dryRun = false;
|
|
17768
|
+
let scope;
|
|
17769
|
+
for (let i = 1;i < argv.length; i++) {
|
|
17770
|
+
const token = argv[i];
|
|
17771
|
+
if (token === "--dry-run") {
|
|
17772
|
+
dryRun = true;
|
|
17773
|
+
continue;
|
|
17774
|
+
}
|
|
17775
|
+
if (token === "--scope") {
|
|
17776
|
+
const v = argv[++i];
|
|
17777
|
+
if (v !== "project" && v !== "user") {
|
|
17778
|
+
console.error(`Error: --scope must be "project" or "user", got: "${v ?? ""}"`);
|
|
17779
|
+
process.exit(1);
|
|
17780
|
+
}
|
|
17781
|
+
scope = v;
|
|
17782
|
+
continue;
|
|
17783
|
+
}
|
|
17784
|
+
if (token.startsWith("--") && !field) {
|
|
17785
|
+
field = token.slice(2);
|
|
17786
|
+
value = argv[++i];
|
|
17787
|
+
continue;
|
|
17788
|
+
}
|
|
17789
|
+
}
|
|
17790
|
+
if (!field || !FIELD_MAP[field]) {
|
|
17791
|
+
console.error(`Error: unknown or missing field. Valid fields: ${Object.keys(FIELD_MAP).join(", ")}`);
|
|
17792
|
+
process.exit(1);
|
|
17793
|
+
}
|
|
17794
|
+
if (value === undefined || value === "") {
|
|
17795
|
+
console.error(`Error: --${field} requires a value`);
|
|
17796
|
+
process.exit(1);
|
|
17797
|
+
}
|
|
17798
|
+
if (field === "permission" && !VALID_PERMISSIONS.includes(value)) {
|
|
17799
|
+
console.error(`Error: --permission must be one of: ${VALID_PERMISSIONS.join(", ")}`);
|
|
17800
|
+
process.exit(1);
|
|
17801
|
+
}
|
|
17802
|
+
if (field === "timeout" && !/^\d+$/.test(value)) {
|
|
17803
|
+
console.error("Error: --timeout must be a number (milliseconds)");
|
|
17804
|
+
process.exit(1);
|
|
17805
|
+
}
|
|
17806
|
+
return { name, field, value, dryRun, scope };
|
|
17807
|
+
}
|
|
17808
|
+
function setIn(doc2, path, value) {
|
|
17809
|
+
let node = doc2;
|
|
17810
|
+
for (let i = 0;i < path.length - 1; i++) {
|
|
17811
|
+
node = node.get(path[i], true);
|
|
17812
|
+
}
|
|
17813
|
+
const leaf = path[path.length - 1];
|
|
17814
|
+
if (Array.isArray(value)) {
|
|
17815
|
+
node.set(leaf, value);
|
|
17816
|
+
} else {
|
|
17817
|
+
node.set(leaf, value);
|
|
17818
|
+
}
|
|
17819
|
+
}
|
|
17820
|
+
async function run5() {
|
|
17821
|
+
const args = parseArgs2(process.argv.slice(3));
|
|
17822
|
+
const { name, field, value, dryRun, scope } = args;
|
|
17823
|
+
const loader = new SpecialistLoader;
|
|
17824
|
+
const all = await loader.list();
|
|
17825
|
+
const match = all.find((s) => s.name === name && (scope === undefined || s.scope === scope));
|
|
17826
|
+
if (!match) {
|
|
17827
|
+
const hint = scope ? ` (scope: ${scope})` : "";
|
|
17828
|
+
console.error(`Error: specialist "${name}" not found${hint}`);
|
|
17829
|
+
console.error(` Run ${yellow3("specialists list")} to see available specialists`);
|
|
17830
|
+
process.exit(1);
|
|
17831
|
+
}
|
|
17832
|
+
const raw = readFileSync2(match.filePath, "utf-8");
|
|
17833
|
+
const doc2 = $parseDocument(raw);
|
|
17834
|
+
const yamlPath = FIELD_MAP[field];
|
|
17835
|
+
let typedValue = value;
|
|
17836
|
+
if (field === "timeout") {
|
|
17837
|
+
typedValue = parseInt(value, 10);
|
|
17838
|
+
} else if (field === "tags") {
|
|
17839
|
+
typedValue = value.split(",").map((t) => t.trim()).filter(Boolean);
|
|
17840
|
+
}
|
|
17841
|
+
setIn(doc2, yamlPath, typedValue);
|
|
17842
|
+
const updated = doc2.toString();
|
|
17843
|
+
if (dryRun) {
|
|
17844
|
+
console.log(`
|
|
17845
|
+
${bold3(`[dry-run] ${match.filePath}`)}
|
|
17846
|
+
`);
|
|
17847
|
+
console.log(dim3("--- current"));
|
|
17848
|
+
console.log(dim3(`+++ updated`));
|
|
17849
|
+
const oldLines = raw.split(`
|
|
17850
|
+
`);
|
|
17851
|
+
const newLines = updated.split(`
|
|
17852
|
+
`);
|
|
17853
|
+
newLines.forEach((line, i) => {
|
|
17854
|
+
if (line !== oldLines[i]) {
|
|
17855
|
+
if (oldLines[i] !== undefined)
|
|
17856
|
+
console.log(dim3(`- ${oldLines[i]}`));
|
|
17857
|
+
console.log(green2(`+ ${line}`));
|
|
17858
|
+
}
|
|
17859
|
+
});
|
|
17860
|
+
console.log();
|
|
17861
|
+
return;
|
|
17862
|
+
}
|
|
17863
|
+
writeFileSync2(match.filePath, updated, "utf-8");
|
|
17864
|
+
const displayValue = field === "tags" ? `[${typedValue.join(", ")}]` : String(typedValue);
|
|
17865
|
+
console.log(`${green2("✓")} ${bold3(name)}: ${yellow3(field)} = ${displayValue}` + dim3(` (${match.filePath})`));
|
|
17866
|
+
}
|
|
17867
|
+
var bold3 = (s) => `\x1B[1m${s}\x1B[0m`, green2 = (s) => `\x1B[32m${s}\x1B[0m`, yellow3 = (s) => `\x1B[33m${s}\x1B[0m`, dim3 = (s) => `\x1B[2m${s}\x1B[0m`, FIELD_MAP, VALID_PERMISSIONS;
|
|
17868
|
+
var init_edit = __esm(() => {
|
|
17869
|
+
init_dist();
|
|
17870
|
+
init_loader();
|
|
17871
|
+
FIELD_MAP = {
|
|
17872
|
+
model: ["specialist", "execution", "model"],
|
|
17873
|
+
"fallback-model": ["specialist", "execution", "fallback_model"],
|
|
17874
|
+
description: ["specialist", "metadata", "description"],
|
|
17875
|
+
permission: ["specialist", "execution", "permission_required"],
|
|
17876
|
+
timeout: ["specialist", "execution", "timeout_ms"],
|
|
17877
|
+
tags: ["specialist", "metadata", "tags"]
|
|
17878
|
+
};
|
|
17879
|
+
VALID_PERMISSIONS = ["READ_ONLY", "LOW", "MEDIUM", "HIGH"];
|
|
17880
|
+
});
|
|
17881
|
+
|
|
17691
17882
|
// src/cli/help.ts
|
|
17692
17883
|
var exports_help = {};
|
|
17693
17884
|
__export(exports_help, {
|
|
17694
|
-
run: () =>
|
|
17885
|
+
run: () => run6
|
|
17695
17886
|
});
|
|
17696
|
-
async function
|
|
17887
|
+
async function run6() {
|
|
17697
17888
|
const lines = [
|
|
17698
17889
|
"",
|
|
17699
|
-
|
|
17890
|
+
bold4("specialists <command>"),
|
|
17700
17891
|
"",
|
|
17701
17892
|
"Commands:",
|
|
17702
|
-
...COMMANDS.map(([cmd, desc]) => ` ${cmd.padEnd(COL_WIDTH)} ${
|
|
17893
|
+
...COMMANDS.map(([cmd, desc]) => ` ${cmd.padEnd(COL_WIDTH)} ${dim4(desc)}`),
|
|
17703
17894
|
"",
|
|
17704
|
-
|
|
17895
|
+
dim4("Run 'specialists <command> --help' for command-specific options."),
|
|
17705
17896
|
""
|
|
17706
17897
|
];
|
|
17707
17898
|
console.log(lines.join(`
|
|
17708
17899
|
`));
|
|
17709
17900
|
}
|
|
17710
|
-
var
|
|
17901
|
+
var bold4 = (s) => `\x1B[1m${s}\x1B[0m`, dim4 = (s) => `\x1B[2m${s}\x1B[0m`, COMMANDS, COL_WIDTH;
|
|
17711
17902
|
var init_help = __esm(() => {
|
|
17712
17903
|
COMMANDS = [
|
|
17713
17904
|
["install", "Full-stack installer: pi, beads, dolt, MCP registration, hooks"],
|
|
@@ -26005,7 +26196,7 @@ class SpecialistsServer {
|
|
|
26005
26196
|
|
|
26006
26197
|
// src/index.ts
|
|
26007
26198
|
var sub = process.argv[2];
|
|
26008
|
-
async function
|
|
26199
|
+
async function run7() {
|
|
26009
26200
|
if (sub === "install") {
|
|
26010
26201
|
const { run: handler } = await Promise.resolve().then(() => (init_install(), exports_install));
|
|
26011
26202
|
return handler();
|
|
@@ -26018,6 +26209,14 @@ async function run5() {
|
|
|
26018
26209
|
const { run: handler } = await Promise.resolve().then(() => (init_list(), exports_list));
|
|
26019
26210
|
return handler();
|
|
26020
26211
|
}
|
|
26212
|
+
if (sub === "init") {
|
|
26213
|
+
const { run: handler } = await Promise.resolve().then(() => (init_init(), exports_init));
|
|
26214
|
+
return handler();
|
|
26215
|
+
}
|
|
26216
|
+
if (sub === "edit") {
|
|
26217
|
+
const { run: handler } = await Promise.resolve().then(() => (init_edit(), exports_edit));
|
|
26218
|
+
return handler();
|
|
26219
|
+
}
|
|
26021
26220
|
if (sub === "help" || sub === "--help" || sub === "-h") {
|
|
26022
26221
|
const { run: handler } = await Promise.resolve().then(() => (init_help(), exports_help));
|
|
26023
26222
|
return handler();
|
|
@@ -26026,7 +26225,7 @@ async function run5() {
|
|
|
26026
26225
|
const server = new SpecialistsServer;
|
|
26027
26226
|
await server.start();
|
|
26028
26227
|
}
|
|
26029
|
-
|
|
26228
|
+
run7().catch((error2) => {
|
|
26030
26229
|
logger.error(`Fatal error: ${error2}`);
|
|
26031
26230
|
process.exit(1);
|
|
26032
26231
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jaggerxtrm/specialists",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.11",
|
|
4
4
|
"description": "OmniSpecialist — 7-tool MCP orchestration layer powered by the Specialist System. Discover and execute .specialist.yaml files across project/user/system scopes via pi.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|