@jaggerxtrm/specialists 3.3.2 → 3.3.3
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 +246 -214
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -8531,7 +8531,6 @@ var require_limitLength = __commonJS((exports) => {
|
|
|
8531
8531
|
var require_pattern = __commonJS((exports) => {
|
|
8532
8532
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8533
8533
|
var code_1 = require_code2();
|
|
8534
|
-
var util_1 = require_util();
|
|
8535
8534
|
var codegen_1 = require_codegen();
|
|
8536
8535
|
var error2 = {
|
|
8537
8536
|
message: ({ schemaCode }) => (0, codegen_1.str)`must match pattern "${schemaCode}"`,
|
|
@@ -8544,18 +8543,10 @@ var require_pattern = __commonJS((exports) => {
|
|
|
8544
8543
|
$data: true,
|
|
8545
8544
|
error: error2,
|
|
8546
8545
|
code(cxt) {
|
|
8547
|
-
const {
|
|
8546
|
+
const { data, $data, schema, schemaCode, it } = cxt;
|
|
8548
8547
|
const u = it.opts.unicodeRegExp ? "u" : "";
|
|
8549
|
-
|
|
8550
|
-
|
|
8551
|
-
const regExpCode = regExp.code === "new RegExp" ? (0, codegen_1._)`new RegExp` : (0, util_1.useFunc)(gen, regExp);
|
|
8552
|
-
const valid = gen.let("valid");
|
|
8553
|
-
gen.try(() => gen.assign(valid, (0, codegen_1._)`${regExpCode}(${schemaCode}, ${u}).test(${data})`), () => gen.assign(valid, false));
|
|
8554
|
-
cxt.fail$data((0, codegen_1._)`!${valid}`);
|
|
8555
|
-
} else {
|
|
8556
|
-
const regExp = (0, code_1.usePattern)(cxt, schema);
|
|
8557
|
-
cxt.fail$data((0, codegen_1._)`!${regExp}.test(${data})`);
|
|
8558
|
-
}
|
|
8548
|
+
const regExp = $data ? (0, codegen_1._)`(new RegExp(${schemaCode}, ${u}))` : (0, code_1.usePattern)(cxt, schema);
|
|
8549
|
+
cxt.fail$data((0, codegen_1._)`!${regExp}.test(${data})`);
|
|
8559
8550
|
}
|
|
8560
8551
|
};
|
|
8561
8552
|
exports.default = def;
|
|
@@ -18571,6 +18562,7 @@ var init_timeline_events = __esm(() => {
|
|
|
18571
18562
|
import {
|
|
18572
18563
|
closeSync,
|
|
18573
18564
|
existsSync as existsSync4,
|
|
18565
|
+
fsyncSync,
|
|
18574
18566
|
mkdirSync,
|
|
18575
18567
|
openSync,
|
|
18576
18568
|
readdirSync,
|
|
@@ -18727,7 +18719,9 @@ class Supervisor {
|
|
|
18727
18719
|
try {
|
|
18728
18720
|
writeSync(eventsFd, JSON.stringify(event) + `
|
|
18729
18721
|
`);
|
|
18730
|
-
} catch {
|
|
18722
|
+
} catch (err) {
|
|
18723
|
+
console.error(`[supervisor] Failed to write event: ${err?.message ?? err}`);
|
|
18724
|
+
}
|
|
18731
18725
|
};
|
|
18732
18726
|
appendTimelineEvent(createRunStartEvent(runOptions.name));
|
|
18733
18727
|
const fifoPath = join3(dir, "steer.pipe");
|
|
@@ -18846,6 +18840,9 @@ class Supervisor {
|
|
|
18846
18840
|
throw err;
|
|
18847
18841
|
} finally {
|
|
18848
18842
|
process.removeListener("SIGTERM", sigtermHandler);
|
|
18843
|
+
try {
|
|
18844
|
+
fsyncSync(eventsFd);
|
|
18845
|
+
} catch {}
|
|
18849
18846
|
closeSync(eventsFd);
|
|
18850
18847
|
try {
|
|
18851
18848
|
if (existsSync4(fifoPath))
|
|
@@ -19511,20 +19508,17 @@ var exports_run = {};
|
|
|
19511
19508
|
__export(exports_run, {
|
|
19512
19509
|
run: () => run7
|
|
19513
19510
|
});
|
|
19514
|
-
import { spawn as spawn2 } from "node:child_process";
|
|
19515
19511
|
import { join as join10 } from "node:path";
|
|
19516
19512
|
async function parseArgs4(argv) {
|
|
19517
19513
|
const name = argv[0];
|
|
19518
19514
|
if (!name || name.startsWith("--")) {
|
|
19519
|
-
console.error('Usage: specialists|sp run <name> [--prompt "..."] [--bead <id>] [--context-depth <n>] [--model <model>] [--no-beads] [--
|
|
19515
|
+
console.error('Usage: specialists|sp run <name> [--prompt "..."] [--bead <id>] [--context-depth <n>] [--model <model>] [--no-beads] [--keep-alive]');
|
|
19520
19516
|
process.exit(1);
|
|
19521
19517
|
}
|
|
19522
19518
|
let prompt = "";
|
|
19523
19519
|
let beadId;
|
|
19524
19520
|
let model;
|
|
19525
19521
|
let noBeads = false;
|
|
19526
|
-
let background = false;
|
|
19527
|
-
let follow = false;
|
|
19528
19522
|
let keepAlive = false;
|
|
19529
19523
|
let contextDepth = 1;
|
|
19530
19524
|
for (let i = 1;i < argv.length; i++) {
|
|
@@ -19549,14 +19543,6 @@ async function parseArgs4(argv) {
|
|
|
19549
19543
|
noBeads = true;
|
|
19550
19544
|
continue;
|
|
19551
19545
|
}
|
|
19552
|
-
if (token === "--background") {
|
|
19553
|
-
background = true;
|
|
19554
|
-
continue;
|
|
19555
|
-
}
|
|
19556
|
-
if (token === "--follow") {
|
|
19557
|
-
follow = true;
|
|
19558
|
-
continue;
|
|
19559
|
-
}
|
|
19560
19546
|
if (token === "--keep-alive") {
|
|
19561
19547
|
keepAlive = true;
|
|
19562
19548
|
continue;
|
|
@@ -19580,7 +19566,7 @@ async function parseArgs4(argv) {
|
|
|
19580
19566
|
console.error("Error: provide --prompt, pipe stdin, or use --bead <id>.");
|
|
19581
19567
|
process.exit(1);
|
|
19582
19568
|
}
|
|
19583
|
-
return { name, prompt, beadId, model, noBeads,
|
|
19569
|
+
return { name, prompt, beadId, model, noBeads, keepAlive, contextDepth };
|
|
19584
19570
|
}
|
|
19585
19571
|
async function run7() {
|
|
19586
19572
|
const args = await parseArgs4(process.argv.slice(3));
|
|
@@ -19615,57 +19601,6 @@ async function run7() {
|
|
|
19615
19601
|
circuitBreaker,
|
|
19616
19602
|
beadsClient
|
|
19617
19603
|
});
|
|
19618
|
-
if (args.background || args.follow) {
|
|
19619
|
-
const jobsDir = join10(process.cwd(), ".specialists", "jobs");
|
|
19620
|
-
const supervisor = new Supervisor({
|
|
19621
|
-
runner,
|
|
19622
|
-
runOptions: {
|
|
19623
|
-
name: args.name,
|
|
19624
|
-
prompt,
|
|
19625
|
-
variables,
|
|
19626
|
-
backendOverride: args.model,
|
|
19627
|
-
inputBeadId: args.beadId,
|
|
19628
|
-
keepAlive: args.keepAlive
|
|
19629
|
-
},
|
|
19630
|
-
jobsDir,
|
|
19631
|
-
beadsClient
|
|
19632
|
-
});
|
|
19633
|
-
let jobId;
|
|
19634
|
-
try {
|
|
19635
|
-
jobId = await supervisor.run();
|
|
19636
|
-
if (!args.follow) {
|
|
19637
|
-
process.stdout.write(`Job started: ${jobId}
|
|
19638
|
-
`);
|
|
19639
|
-
}
|
|
19640
|
-
} catch (err) {
|
|
19641
|
-
process.stderr.write(`Error: ${err?.message ?? err}
|
|
19642
|
-
`);
|
|
19643
|
-
process.exit(1);
|
|
19644
|
-
}
|
|
19645
|
-
if (args.follow) {
|
|
19646
|
-
await new Promise((resolve2, reject) => {
|
|
19647
|
-
const feed = spawn2("specialists", ["feed", "--job", jobId, "--follow"], {
|
|
19648
|
-
cwd: process.cwd(),
|
|
19649
|
-
stdio: "inherit"
|
|
19650
|
-
});
|
|
19651
|
-
feed.on("close", (code) => {
|
|
19652
|
-
if (code === 0) {
|
|
19653
|
-
resolve2();
|
|
19654
|
-
} else {
|
|
19655
|
-
reject(new Error(`Feed exited with code ${code}`));
|
|
19656
|
-
}
|
|
19657
|
-
});
|
|
19658
|
-
feed.on("error", (err) => {
|
|
19659
|
-
reject(err);
|
|
19660
|
-
});
|
|
19661
|
-
}).catch((err) => {
|
|
19662
|
-
process.stderr.write(`Error: ${err.message}
|
|
19663
|
-
`);
|
|
19664
|
-
process.exit(1);
|
|
19665
|
-
});
|
|
19666
|
-
}
|
|
19667
|
-
return;
|
|
19668
|
-
}
|
|
19669
19604
|
process.stderr.write(`
|
|
19670
19605
|
${bold5(`Running ${cyan3(args.name)}`)}
|
|
19671
19606
|
|
|
@@ -19717,7 +19652,6 @@ var init_run = __esm(() => {
|
|
|
19717
19652
|
init_runner();
|
|
19718
19653
|
init_hooks();
|
|
19719
19654
|
init_beads();
|
|
19720
|
-
init_supervisor();
|
|
19721
19655
|
});
|
|
19722
19656
|
|
|
19723
19657
|
// src/cli/format-helpers.ts
|
|
@@ -20058,6 +19992,9 @@ function readJobEvents(jobDir) {
|
|
|
20058
19992
|
events.sort(compareTimelineEvents);
|
|
20059
19993
|
return events;
|
|
20060
19994
|
}
|
|
19995
|
+
function readJobEventsById(jobsDir, jobId) {
|
|
19996
|
+
return readJobEvents(join13(jobsDir, jobId));
|
|
19997
|
+
}
|
|
20061
19998
|
function readAllJobEvents(jobsDir) {
|
|
20062
19999
|
if (!existsSync9(jobsDir))
|
|
20063
20000
|
return [];
|
|
@@ -20359,21 +20296,132 @@ var init_feed = __esm(() => {
|
|
|
20359
20296
|
init_format_helpers();
|
|
20360
20297
|
});
|
|
20361
20298
|
|
|
20299
|
+
// src/cli/poll.ts
|
|
20300
|
+
var exports_poll = {};
|
|
20301
|
+
__export(exports_poll, {
|
|
20302
|
+
run: () => run11
|
|
20303
|
+
});
|
|
20304
|
+
import { existsSync as existsSync11, readFileSync as readFileSync7 } from "node:fs";
|
|
20305
|
+
import { join as join15 } from "node:path";
|
|
20306
|
+
function parseArgs6(argv) {
|
|
20307
|
+
let jobId;
|
|
20308
|
+
let cursor = 0;
|
|
20309
|
+
let json = false;
|
|
20310
|
+
for (let i = 0;i < argv.length; i++) {
|
|
20311
|
+
if (argv[i] === "--cursor" && argv[i + 1]) {
|
|
20312
|
+
cursor = parseInt(argv[++i], 10);
|
|
20313
|
+
if (isNaN(cursor) || cursor < 0)
|
|
20314
|
+
cursor = 0;
|
|
20315
|
+
continue;
|
|
20316
|
+
}
|
|
20317
|
+
if (argv[i] === "--json") {
|
|
20318
|
+
json = true;
|
|
20319
|
+
continue;
|
|
20320
|
+
}
|
|
20321
|
+
if (!argv[i].startsWith("--")) {
|
|
20322
|
+
jobId = argv[i];
|
|
20323
|
+
}
|
|
20324
|
+
}
|
|
20325
|
+
if (!jobId) {
|
|
20326
|
+
console.error("Usage: specialists poll <job-id> [--cursor N] [--json]");
|
|
20327
|
+
process.exit(1);
|
|
20328
|
+
}
|
|
20329
|
+
return { jobId, cursor, json };
|
|
20330
|
+
}
|
|
20331
|
+
async function run11() {
|
|
20332
|
+
const { jobId, cursor, json } = parseArgs6(process.argv.slice(3));
|
|
20333
|
+
const jobsDir = join15(process.cwd(), ".specialists", "jobs");
|
|
20334
|
+
const jobDir = join15(jobsDir, jobId);
|
|
20335
|
+
if (!existsSync11(jobDir)) {
|
|
20336
|
+
const result2 = {
|
|
20337
|
+
job_id: jobId,
|
|
20338
|
+
status: "error",
|
|
20339
|
+
elapsed_ms: 0,
|
|
20340
|
+
cursor: 0,
|
|
20341
|
+
output: "",
|
|
20342
|
+
output_delta: "",
|
|
20343
|
+
events: [],
|
|
20344
|
+
error: `Job not found: ${jobId}`
|
|
20345
|
+
};
|
|
20346
|
+
console.log(JSON.stringify(result2));
|
|
20347
|
+
process.exit(1);
|
|
20348
|
+
}
|
|
20349
|
+
const statusPath = join15(jobDir, "status.json");
|
|
20350
|
+
let status = null;
|
|
20351
|
+
if (existsSync11(statusPath)) {
|
|
20352
|
+
try {
|
|
20353
|
+
status = JSON.parse(readFileSync7(statusPath, "utf-8"));
|
|
20354
|
+
} catch {}
|
|
20355
|
+
}
|
|
20356
|
+
const resultPath = join15(jobDir, "result.txt");
|
|
20357
|
+
let output = "";
|
|
20358
|
+
if (existsSync11(resultPath)) {
|
|
20359
|
+
try {
|
|
20360
|
+
output = readFileSync7(resultPath, "utf-8");
|
|
20361
|
+
} catch {}
|
|
20362
|
+
}
|
|
20363
|
+
const events = readJobEventsById(jobsDir, jobId);
|
|
20364
|
+
const newEvents = events.slice(cursor);
|
|
20365
|
+
const nextCursor = events.length;
|
|
20366
|
+
const startedAt = status?.started_at_ms ?? Date.now();
|
|
20367
|
+
const lastEvent = status?.last_event_at_ms ?? Date.now();
|
|
20368
|
+
const elapsedMs = status?.status === "done" || status?.status === "error" ? lastEvent - startedAt : Date.now() - startedAt;
|
|
20369
|
+
const result = {
|
|
20370
|
+
job_id: jobId,
|
|
20371
|
+
status: status?.status ?? "starting",
|
|
20372
|
+
elapsed_ms: elapsedMs,
|
|
20373
|
+
cursor: nextCursor,
|
|
20374
|
+
output: status?.status === "done" ? output : "",
|
|
20375
|
+
output_delta: "",
|
|
20376
|
+
events: newEvents,
|
|
20377
|
+
current_event: status?.current_event,
|
|
20378
|
+
current_tool: status?.current_tool,
|
|
20379
|
+
model: status?.model,
|
|
20380
|
+
backend: status?.backend,
|
|
20381
|
+
bead_id: status?.bead_id,
|
|
20382
|
+
error: status?.error
|
|
20383
|
+
};
|
|
20384
|
+
if (json) {
|
|
20385
|
+
console.log(JSON.stringify(result, null, 2));
|
|
20386
|
+
} else {
|
|
20387
|
+
console.log(`Job: ${jobId}`);
|
|
20388
|
+
console.log(`Status: ${result.status}`);
|
|
20389
|
+
console.log(`Elapsed: ${Math.round(result.elapsed_ms / 1000)}s`);
|
|
20390
|
+
if (result.model)
|
|
20391
|
+
console.log(`Model: ${result.backend}/${result.model}`);
|
|
20392
|
+
if (result.bead_id)
|
|
20393
|
+
console.log(`Bead: ${result.bead_id}`);
|
|
20394
|
+
if (result.current_tool)
|
|
20395
|
+
console.log(`Tool: ${result.current_tool}`);
|
|
20396
|
+
if (result.error)
|
|
20397
|
+
console.log(`Error: ${result.error}`);
|
|
20398
|
+
console.log(`Events: ${newEvents.length} new (cursor: ${cursor} → ${nextCursor})`);
|
|
20399
|
+
if (result.status === "done" && result.output) {
|
|
20400
|
+
console.log(`
|
|
20401
|
+
--- Output ---`);
|
|
20402
|
+
console.log(result.output.slice(0, 500) + (result.output.length > 500 ? "..." : ""));
|
|
20403
|
+
}
|
|
20404
|
+
}
|
|
20405
|
+
}
|
|
20406
|
+
var init_poll = __esm(() => {
|
|
20407
|
+
init_timeline_query();
|
|
20408
|
+
});
|
|
20409
|
+
|
|
20362
20410
|
// src/cli/steer.ts
|
|
20363
20411
|
var exports_steer = {};
|
|
20364
20412
|
__export(exports_steer, {
|
|
20365
|
-
run: () =>
|
|
20413
|
+
run: () => run12
|
|
20366
20414
|
});
|
|
20367
|
-
import { join as
|
|
20415
|
+
import { join as join16 } from "node:path";
|
|
20368
20416
|
import { writeFileSync as writeFileSync6 } from "node:fs";
|
|
20369
|
-
async function
|
|
20417
|
+
async function run12() {
|
|
20370
20418
|
const jobId = process.argv[3];
|
|
20371
20419
|
const message = process.argv[4];
|
|
20372
20420
|
if (!jobId || !message) {
|
|
20373
20421
|
console.error('Usage: specialists|sp steer <job-id> "<message>"');
|
|
20374
20422
|
process.exit(1);
|
|
20375
20423
|
}
|
|
20376
|
-
const jobsDir =
|
|
20424
|
+
const jobsDir = join16(process.cwd(), ".specialists", "jobs");
|
|
20377
20425
|
const supervisor = new Supervisor({ runner: null, runOptions: null, jobsDir });
|
|
20378
20426
|
const status = supervisor.readStatus(jobId);
|
|
20379
20427
|
if (!status) {
|
|
@@ -20412,18 +20460,18 @@ var init_steer = __esm(() => {
|
|
|
20412
20460
|
// src/cli/follow-up.ts
|
|
20413
20461
|
var exports_follow_up = {};
|
|
20414
20462
|
__export(exports_follow_up, {
|
|
20415
|
-
run: () =>
|
|
20463
|
+
run: () => run13
|
|
20416
20464
|
});
|
|
20417
|
-
import { join as
|
|
20465
|
+
import { join as join17 } from "node:path";
|
|
20418
20466
|
import { writeFileSync as writeFileSync7 } from "node:fs";
|
|
20419
|
-
async function
|
|
20467
|
+
async function run13() {
|
|
20420
20468
|
const jobId = process.argv[3];
|
|
20421
20469
|
const message = process.argv[4];
|
|
20422
20470
|
if (!jobId || !message) {
|
|
20423
20471
|
console.error('Usage: specialists|sp follow-up <job-id> "<message>"');
|
|
20424
20472
|
process.exit(1);
|
|
20425
20473
|
}
|
|
20426
|
-
const jobsDir =
|
|
20474
|
+
const jobsDir = join17(process.cwd(), ".specialists", "jobs");
|
|
20427
20475
|
const supervisor = new Supervisor({ runner: null, runOptions: null, jobsDir });
|
|
20428
20476
|
const status = supervisor.readStatus(jobId);
|
|
20429
20477
|
if (!status) {
|
|
@@ -20464,16 +20512,16 @@ var init_follow_up = __esm(() => {
|
|
|
20464
20512
|
// src/cli/stop.ts
|
|
20465
20513
|
var exports_stop = {};
|
|
20466
20514
|
__export(exports_stop, {
|
|
20467
|
-
run: () =>
|
|
20515
|
+
run: () => run14
|
|
20468
20516
|
});
|
|
20469
|
-
import { join as
|
|
20470
|
-
async function
|
|
20517
|
+
import { join as join18 } from "node:path";
|
|
20518
|
+
async function run14() {
|
|
20471
20519
|
const jobId = process.argv[3];
|
|
20472
20520
|
if (!jobId) {
|
|
20473
20521
|
console.error("Usage: specialists|sp stop <job-id>");
|
|
20474
20522
|
process.exit(1);
|
|
20475
20523
|
}
|
|
20476
|
-
const jobsDir =
|
|
20524
|
+
const jobsDir = join18(process.cwd(), ".specialists", "jobs");
|
|
20477
20525
|
const supervisor = new Supervisor({ runner: null, runOptions: null, jobsDir });
|
|
20478
20526
|
const status = supervisor.readStatus(jobId);
|
|
20479
20527
|
if (!status) {
|
|
@@ -20513,7 +20561,7 @@ var init_stop = __esm(() => {
|
|
|
20513
20561
|
// src/cli/quickstart.ts
|
|
20514
20562
|
var exports_quickstart = {};
|
|
20515
20563
|
__export(exports_quickstart, {
|
|
20516
|
-
run: () =>
|
|
20564
|
+
run: () => run15
|
|
20517
20565
|
});
|
|
20518
20566
|
function section2(title) {
|
|
20519
20567
|
const bar = "─".repeat(60);
|
|
@@ -20527,7 +20575,7 @@ function cmd2(s) {
|
|
|
20527
20575
|
function flag(s) {
|
|
20528
20576
|
return green10(s);
|
|
20529
20577
|
}
|
|
20530
|
-
async function
|
|
20578
|
+
async function run15() {
|
|
20531
20579
|
const lines = [
|
|
20532
20580
|
"",
|
|
20533
20581
|
bold7("specialists · Quick Start Guide"),
|
|
@@ -20744,11 +20792,11 @@ var bold7 = (s) => `\x1B[1m${s}\x1B[0m`, dim9 = (s) => `\x1B[2m${s}\x1B[0m`, yel
|
|
|
20744
20792
|
// src/cli/doctor.ts
|
|
20745
20793
|
var exports_doctor = {};
|
|
20746
20794
|
__export(exports_doctor, {
|
|
20747
|
-
run: () =>
|
|
20795
|
+
run: () => run16
|
|
20748
20796
|
});
|
|
20749
20797
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
20750
|
-
import { existsSync as
|
|
20751
|
-
import { join as
|
|
20798
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync3, readFileSync as readFileSync8, readdirSync as readdirSync4 } from "node:fs";
|
|
20799
|
+
import { join as join19 } from "node:path";
|
|
20752
20800
|
function ok3(msg) {
|
|
20753
20801
|
console.log(` ${green11("✓")} ${msg}`);
|
|
20754
20802
|
}
|
|
@@ -20777,10 +20825,10 @@ function isInstalled2(bin) {
|
|
|
20777
20825
|
return spawnSync7("which", [bin], { encoding: "utf8", timeout: 2000 }).status === 0;
|
|
20778
20826
|
}
|
|
20779
20827
|
function loadJson2(path) {
|
|
20780
|
-
if (!
|
|
20828
|
+
if (!existsSync12(path))
|
|
20781
20829
|
return null;
|
|
20782
20830
|
try {
|
|
20783
|
-
return JSON.parse(
|
|
20831
|
+
return JSON.parse(readFileSync8(path, "utf8"));
|
|
20784
20832
|
} catch {
|
|
20785
20833
|
return null;
|
|
20786
20834
|
}
|
|
@@ -20813,7 +20861,7 @@ function checkBd() {
|
|
|
20813
20861
|
return false;
|
|
20814
20862
|
}
|
|
20815
20863
|
ok3(`bd installed ${dim10(sp("bd", ["--version"]).stdout || "")}`);
|
|
20816
|
-
if (
|
|
20864
|
+
if (existsSync12(join19(CWD, ".beads")))
|
|
20817
20865
|
ok3(".beads/ present in project");
|
|
20818
20866
|
else
|
|
20819
20867
|
warn2(".beads/ not found in project");
|
|
@@ -20833,8 +20881,8 @@ function checkHooks() {
|
|
|
20833
20881
|
section3("Claude Code hooks (2 expected)");
|
|
20834
20882
|
let allPresent = true;
|
|
20835
20883
|
for (const name of HOOK_NAMES) {
|
|
20836
|
-
const dest =
|
|
20837
|
-
if (!
|
|
20884
|
+
const dest = join19(HOOKS_DIR, name);
|
|
20885
|
+
if (!existsSync12(dest)) {
|
|
20838
20886
|
fail2(`${name} ${red6("missing")}`);
|
|
20839
20887
|
fix("specialists install");
|
|
20840
20888
|
allPresent = false;
|
|
@@ -20878,18 +20926,18 @@ function checkMCP() {
|
|
|
20878
20926
|
}
|
|
20879
20927
|
function checkRuntimeDirs() {
|
|
20880
20928
|
section3(".specialists/ runtime directories");
|
|
20881
|
-
const rootDir =
|
|
20882
|
-
const jobsDir =
|
|
20883
|
-
const readyDir =
|
|
20929
|
+
const rootDir = join19(CWD, ".specialists");
|
|
20930
|
+
const jobsDir = join19(rootDir, "jobs");
|
|
20931
|
+
const readyDir = join19(rootDir, "ready");
|
|
20884
20932
|
let allOk = true;
|
|
20885
|
-
if (!
|
|
20933
|
+
if (!existsSync12(rootDir)) {
|
|
20886
20934
|
warn2(".specialists/ not found in current project");
|
|
20887
20935
|
fix("specialists init");
|
|
20888
20936
|
allOk = false;
|
|
20889
20937
|
} else {
|
|
20890
20938
|
ok3(".specialists/ present");
|
|
20891
20939
|
for (const [subDir, label] of [[jobsDir, "jobs"], [readyDir, "ready"]]) {
|
|
20892
|
-
if (!
|
|
20940
|
+
if (!existsSync12(subDir)) {
|
|
20893
20941
|
warn2(`.specialists/${label}/ missing — auto-creating`);
|
|
20894
20942
|
mkdirSync3(subDir, { recursive: true });
|
|
20895
20943
|
ok3(`.specialists/${label}/ created`);
|
|
@@ -20902,8 +20950,8 @@ function checkRuntimeDirs() {
|
|
|
20902
20950
|
}
|
|
20903
20951
|
function checkZombieJobs() {
|
|
20904
20952
|
section3("Background jobs");
|
|
20905
|
-
const jobsDir =
|
|
20906
|
-
if (!
|
|
20953
|
+
const jobsDir = join19(CWD, ".specialists", "jobs");
|
|
20954
|
+
if (!existsSync12(jobsDir)) {
|
|
20907
20955
|
hint("No .specialists/jobs/ — skipping");
|
|
20908
20956
|
return true;
|
|
20909
20957
|
}
|
|
@@ -20921,11 +20969,11 @@ function checkZombieJobs() {
|
|
|
20921
20969
|
let total = 0;
|
|
20922
20970
|
let running = 0;
|
|
20923
20971
|
for (const jobId of entries) {
|
|
20924
|
-
const statusPath =
|
|
20925
|
-
if (!
|
|
20972
|
+
const statusPath = join19(jobsDir, jobId, "status.json");
|
|
20973
|
+
if (!existsSync12(statusPath))
|
|
20926
20974
|
continue;
|
|
20927
20975
|
try {
|
|
20928
|
-
const status = JSON.parse(
|
|
20976
|
+
const status = JSON.parse(readFileSync8(statusPath, "utf8"));
|
|
20929
20977
|
total++;
|
|
20930
20978
|
if (status.status === "running" || status.status === "starting") {
|
|
20931
20979
|
const pid = status.pid;
|
|
@@ -20952,7 +21000,7 @@ function checkZombieJobs() {
|
|
|
20952
21000
|
}
|
|
20953
21001
|
return zombies === 0;
|
|
20954
21002
|
}
|
|
20955
|
-
async function
|
|
21003
|
+
async function run16() {
|
|
20956
21004
|
console.log(`
|
|
20957
21005
|
${bold8("specialists doctor")}
|
|
20958
21006
|
`);
|
|
@@ -20976,11 +21024,11 @@ ${bold8("specialists doctor")}
|
|
|
20976
21024
|
var bold8 = (s) => `\x1B[1m${s}\x1B[0m`, dim10 = (s) => `\x1B[2m${s}\x1B[0m`, green11 = (s) => `\x1B[32m${s}\x1B[0m`, yellow7 = (s) => `\x1B[33m${s}\x1B[0m`, red6 = (s) => `\x1B[31m${s}\x1B[0m`, CWD, CLAUDE_DIR, SPECIALISTS_DIR, HOOKS_DIR, SETTINGS_FILE, MCP_FILE2, HOOK_NAMES;
|
|
20977
21025
|
var init_doctor = __esm(() => {
|
|
20978
21026
|
CWD = process.cwd();
|
|
20979
|
-
CLAUDE_DIR =
|
|
20980
|
-
SPECIALISTS_DIR =
|
|
20981
|
-
HOOKS_DIR =
|
|
20982
|
-
SETTINGS_FILE =
|
|
20983
|
-
MCP_FILE2 =
|
|
21027
|
+
CLAUDE_DIR = join19(CWD, ".claude");
|
|
21028
|
+
SPECIALISTS_DIR = join19(CWD, ".specialists");
|
|
21029
|
+
HOOKS_DIR = join19(SPECIALISTS_DIR, "default", "hooks");
|
|
21030
|
+
SETTINGS_FILE = join19(CLAUDE_DIR, "settings.json");
|
|
21031
|
+
MCP_FILE2 = join19(CWD, ".mcp.json");
|
|
20984
21032
|
HOOK_NAMES = [
|
|
20985
21033
|
"specialists-complete.mjs",
|
|
20986
21034
|
"specialists-session-start.mjs"
|
|
@@ -20990,11 +21038,11 @@ var init_doctor = __esm(() => {
|
|
|
20990
21038
|
// src/cli/setup.ts
|
|
20991
21039
|
var exports_setup = {};
|
|
20992
21040
|
__export(exports_setup, {
|
|
20993
|
-
run: () =>
|
|
21041
|
+
run: () => run17
|
|
20994
21042
|
});
|
|
20995
|
-
import { existsSync as
|
|
21043
|
+
import { existsSync as existsSync13, readFileSync as readFileSync9, writeFileSync as writeFileSync8 } from "node:fs";
|
|
20996
21044
|
import { homedir as homedir3 } from "node:os";
|
|
20997
|
-
import { join as
|
|
21045
|
+
import { join as join20, resolve as resolve2 } from "node:path";
|
|
20998
21046
|
function ok4(msg) {
|
|
20999
21047
|
console.log(` ${green12("✓")} ${msg}`);
|
|
21000
21048
|
}
|
|
@@ -21004,15 +21052,15 @@ function skip2(msg) {
|
|
|
21004
21052
|
function resolveTarget(target) {
|
|
21005
21053
|
switch (target) {
|
|
21006
21054
|
case "global":
|
|
21007
|
-
return
|
|
21055
|
+
return join20(homedir3(), ".claude", "CLAUDE.md");
|
|
21008
21056
|
case "agents":
|
|
21009
|
-
return
|
|
21057
|
+
return join20(process.cwd(), "AGENTS.md");
|
|
21010
21058
|
case "project":
|
|
21011
21059
|
default:
|
|
21012
|
-
return
|
|
21060
|
+
return join20(process.cwd(), "CLAUDE.md");
|
|
21013
21061
|
}
|
|
21014
21062
|
}
|
|
21015
|
-
function
|
|
21063
|
+
function parseArgs7() {
|
|
21016
21064
|
const argv = process.argv.slice(3);
|
|
21017
21065
|
let target = "project";
|
|
21018
21066
|
let dryRun = false;
|
|
@@ -21037,8 +21085,8 @@ function parseArgs6() {
|
|
|
21037
21085
|
}
|
|
21038
21086
|
return { target, dryRun };
|
|
21039
21087
|
}
|
|
21040
|
-
async function
|
|
21041
|
-
const { target, dryRun } =
|
|
21088
|
+
async function run17() {
|
|
21089
|
+
const { target, dryRun } = parseArgs7();
|
|
21042
21090
|
const filePath = resolve2(resolveTarget(target));
|
|
21043
21091
|
const label = target === "global" ? "~/.claude/CLAUDE.md" : filePath.replace(process.cwd() + "/", "");
|
|
21044
21092
|
console.log(`
|
|
@@ -21046,8 +21094,8 @@ ${bold9("specialists setup")}
|
|
|
21046
21094
|
`);
|
|
21047
21095
|
console.log(` Target: ${yellow8(label)}${dryRun ? dim11(" (dry-run)") : ""}
|
|
21048
21096
|
`);
|
|
21049
|
-
if (
|
|
21050
|
-
const existing =
|
|
21097
|
+
if (existsSync13(filePath)) {
|
|
21098
|
+
const existing = readFileSync9(filePath, "utf8");
|
|
21051
21099
|
if (existing.includes(MARKER)) {
|
|
21052
21100
|
skip2(`${label} already contains Specialists Workflow section`);
|
|
21053
21101
|
console.log(`
|
|
@@ -21157,13 +21205,13 @@ var init_setup = () => {};
|
|
|
21157
21205
|
// src/cli/help.ts
|
|
21158
21206
|
var exports_help = {};
|
|
21159
21207
|
__export(exports_help, {
|
|
21160
|
-
run: () =>
|
|
21208
|
+
run: () => run18
|
|
21161
21209
|
});
|
|
21162
21210
|
function formatCommands(entries) {
|
|
21163
21211
|
const width = Math.max(...entries.map(([cmd3]) => cmd3.length));
|
|
21164
21212
|
return entries.map(([cmd3, desc]) => ` ${cmd3.padEnd(width)} ${desc}`);
|
|
21165
21213
|
}
|
|
21166
|
-
async function
|
|
21214
|
+
async function run18() {
|
|
21167
21215
|
const lines = [
|
|
21168
21216
|
"",
|
|
21169
21217
|
"Specialists lets you run project-scoped specialist agents with a bead-first workflow.",
|
|
@@ -21178,8 +21226,8 @@ async function run17() {
|
|
|
21178
21226
|
"",
|
|
21179
21227
|
" Tracked work (primary)",
|
|
21180
21228
|
' bd create "Task title" -t task -p 1 --json',
|
|
21181
|
-
" specialists run <name> --bead <id> [--context-depth N]
|
|
21182
|
-
" specialists
|
|
21229
|
+
" specialists run <name> --bead <id> [--context-depth N]",
|
|
21230
|
+
" specialists poll <job-id> --json # check status",
|
|
21183
21231
|
' bd close <id> --reason "Done"',
|
|
21184
21232
|
"",
|
|
21185
21233
|
" Ad-hoc work",
|
|
@@ -21190,7 +21238,11 @@ async function run17() {
|
|
|
21190
21238
|
" --prompt is for quick untracked work",
|
|
21191
21239
|
" --context-depth defaults to 1 with --bead",
|
|
21192
21240
|
" --no-beads does not disable bead reading",
|
|
21193
|
-
"
|
|
21241
|
+
"",
|
|
21242
|
+
" Background execution",
|
|
21243
|
+
" Use Claude Code's native backgrounding (run_in_background: true)",
|
|
21244
|
+
" or run in a separate terminal and poll with:",
|
|
21245
|
+
" specialists poll <job-id> --json",
|
|
21194
21246
|
"",
|
|
21195
21247
|
bold10("Core commands:"),
|
|
21196
21248
|
...formatCommands(CORE_COMMANDS),
|
|
@@ -21204,10 +21256,10 @@ async function run17() {
|
|
|
21204
21256
|
bold10("Examples:"),
|
|
21205
21257
|
" specialists init",
|
|
21206
21258
|
" specialists list",
|
|
21207
|
-
" specialists run bug-hunt --bead unitAI-123
|
|
21208
|
-
" specialists run sync-docs --follow # run + stream live output",
|
|
21259
|
+
" specialists run bug-hunt --bead unitAI-123",
|
|
21209
21260
|
' specialists run codebase-explorer --prompt "Map the CLI architecture"',
|
|
21210
|
-
" specialists
|
|
21261
|
+
" specialists poll abc123 --json # check job status",
|
|
21262
|
+
" specialists feed -f # stream all job events",
|
|
21211
21263
|
' specialists steer <job-id> "focus only on supervisor.ts"',
|
|
21212
21264
|
' specialists follow-up <job-id> "now write the fix"',
|
|
21213
21265
|
" specialists result <job-id>",
|
|
@@ -21215,10 +21267,11 @@ async function run17() {
|
|
|
21215
21267
|
bold10("More help:"),
|
|
21216
21268
|
" specialists quickstart Full guide and workflow reference",
|
|
21217
21269
|
" specialists run --help Run command details and flags",
|
|
21270
|
+
" specialists poll --help Job status polling details",
|
|
21218
21271
|
" specialists steer --help Mid-run steering details",
|
|
21219
21272
|
" specialists follow-up --help Multi-turn keep-alive details",
|
|
21220
21273
|
" specialists init --help Bootstrap behavior and workflow injection",
|
|
21221
|
-
" specialists feed --help
|
|
21274
|
+
" specialists feed --help Job event streaming details",
|
|
21222
21275
|
"",
|
|
21223
21276
|
dim12("Project model: specialists are project-only; user-scope discovery is deprecated."),
|
|
21224
21277
|
""
|
|
@@ -21233,10 +21286,11 @@ var init_help = __esm(() => {
|
|
|
21233
21286
|
["list", "List specialists in this project"],
|
|
21234
21287
|
["run", "Run a specialist with --bead for tracked work or --prompt for ad-hoc work"],
|
|
21235
21288
|
["feed", "Tail job events; use -f to follow all jobs"],
|
|
21236
|
-
["
|
|
21237
|
-
["
|
|
21289
|
+
["poll", "Machine-readable job status polling (for scripts/Claude Code)"],
|
|
21290
|
+
["result", "Print final output of a completed job"],
|
|
21291
|
+
["steer", "Send a mid-run message to a running job"],
|
|
21238
21292
|
["follow-up", "Send a next-turn prompt to a keep-alive session (retains full context)"],
|
|
21239
|
-
["stop", "Stop a running
|
|
21293
|
+
["stop", "Stop a running job"],
|
|
21240
21294
|
["status", "Show health, MCP state, and active jobs"],
|
|
21241
21295
|
["doctor", "Diagnose installation/runtime problems"],
|
|
21242
21296
|
["quickstart", "Full getting-started guide"],
|
|
@@ -27284,9 +27338,6 @@ class Protocol {
|
|
|
27284
27338
|
}
|
|
27285
27339
|
}
|
|
27286
27340
|
async connect(transport) {
|
|
27287
|
-
if (this._transport) {
|
|
27288
|
-
throw new Error("Already connected to a transport. Call close() before connecting to a new transport, or use a separate Protocol instance per connection.");
|
|
27289
|
-
}
|
|
27290
27341
|
this._transport = transport;
|
|
27291
27342
|
const _onclose = this.transport?.onclose;
|
|
27292
27343
|
this._transport.onclose = () => {
|
|
@@ -27319,10 +27370,6 @@ class Protocol {
|
|
|
27319
27370
|
this._progressHandlers.clear();
|
|
27320
27371
|
this._taskProgressTokens.clear();
|
|
27321
27372
|
this._pendingDebouncedNotifications.clear();
|
|
27322
|
-
for (const controller of this._requestHandlerAbortControllers.values()) {
|
|
27323
|
-
controller.abort();
|
|
27324
|
-
}
|
|
27325
|
-
this._requestHandlerAbortControllers.clear();
|
|
27326
27373
|
const error2 = McpError.fromError(ErrorCode.ConnectionClosed, "Connection closed");
|
|
27327
27374
|
this._transport = undefined;
|
|
27328
27375
|
this.onclose?.();
|
|
@@ -27373,8 +27420,6 @@ class Protocol {
|
|
|
27373
27420
|
sessionId: capturedTransport?.sessionId,
|
|
27374
27421
|
_meta: request.params?._meta,
|
|
27375
27422
|
sendNotification: async (notification) => {
|
|
27376
|
-
if (abortController.signal.aborted)
|
|
27377
|
-
return;
|
|
27378
27423
|
const notificationOptions = { relatedRequestId: request.id };
|
|
27379
27424
|
if (relatedTaskId) {
|
|
27380
27425
|
notificationOptions.relatedTask = { taskId: relatedTaskId };
|
|
@@ -27382,9 +27427,6 @@ class Protocol {
|
|
|
27382
27427
|
await this.notification(notification, notificationOptions);
|
|
27383
27428
|
},
|
|
27384
27429
|
sendRequest: async (r, resultSchema, options) => {
|
|
27385
|
-
if (abortController.signal.aborted) {
|
|
27386
|
-
throw new McpError(ErrorCode.ConnectionClosed, "Request was cancelled");
|
|
27387
|
-
}
|
|
27388
27430
|
const requestOptions = { ...options, relatedRequestId: request.id };
|
|
27389
27431
|
if (relatedTaskId && !requestOptions.relatedTask) {
|
|
27390
27432
|
requestOptions.relatedTask = { taskId: relatedTaskId };
|
|
@@ -27998,62 +28040,6 @@ class ExperimentalServerTasks {
|
|
|
27998
28040
|
requestStream(request, resultSchema, options) {
|
|
27999
28041
|
return this._server.requestStream(request, resultSchema, options);
|
|
28000
28042
|
}
|
|
28001
|
-
createMessageStream(params, options) {
|
|
28002
|
-
const clientCapabilities = this._server.getClientCapabilities();
|
|
28003
|
-
if ((params.tools || params.toolChoice) && !clientCapabilities?.sampling?.tools) {
|
|
28004
|
-
throw new Error("Client does not support sampling tools capability.");
|
|
28005
|
-
}
|
|
28006
|
-
if (params.messages.length > 0) {
|
|
28007
|
-
const lastMessage = params.messages[params.messages.length - 1];
|
|
28008
|
-
const lastContent = Array.isArray(lastMessage.content) ? lastMessage.content : [lastMessage.content];
|
|
28009
|
-
const hasToolResults = lastContent.some((c) => c.type === "tool_result");
|
|
28010
|
-
const previousMessage = params.messages.length > 1 ? params.messages[params.messages.length - 2] : undefined;
|
|
28011
|
-
const previousContent = previousMessage ? Array.isArray(previousMessage.content) ? previousMessage.content : [previousMessage.content] : [];
|
|
28012
|
-
const hasPreviousToolUse = previousContent.some((c) => c.type === "tool_use");
|
|
28013
|
-
if (hasToolResults) {
|
|
28014
|
-
if (lastContent.some((c) => c.type !== "tool_result")) {
|
|
28015
|
-
throw new Error("The last message must contain only tool_result content if any is present");
|
|
28016
|
-
}
|
|
28017
|
-
if (!hasPreviousToolUse) {
|
|
28018
|
-
throw new Error("tool_result blocks are not matching any tool_use from the previous message");
|
|
28019
|
-
}
|
|
28020
|
-
}
|
|
28021
|
-
if (hasPreviousToolUse) {
|
|
28022
|
-
const toolUseIds = new Set(previousContent.filter((c) => c.type === "tool_use").map((c) => c.id));
|
|
28023
|
-
const toolResultIds = new Set(lastContent.filter((c) => c.type === "tool_result").map((c) => c.toolUseId));
|
|
28024
|
-
if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every((id) => toolResultIds.has(id))) {
|
|
28025
|
-
throw new Error("ids of tool_result blocks and tool_use blocks from previous message do not match");
|
|
28026
|
-
}
|
|
28027
|
-
}
|
|
28028
|
-
}
|
|
28029
|
-
return this.requestStream({
|
|
28030
|
-
method: "sampling/createMessage",
|
|
28031
|
-
params
|
|
28032
|
-
}, CreateMessageResultSchema, options);
|
|
28033
|
-
}
|
|
28034
|
-
elicitInputStream(params, options) {
|
|
28035
|
-
const clientCapabilities = this._server.getClientCapabilities();
|
|
28036
|
-
const mode = params.mode ?? "form";
|
|
28037
|
-
switch (mode) {
|
|
28038
|
-
case "url": {
|
|
28039
|
-
if (!clientCapabilities?.elicitation?.url) {
|
|
28040
|
-
throw new Error("Client does not support url elicitation.");
|
|
28041
|
-
}
|
|
28042
|
-
break;
|
|
28043
|
-
}
|
|
28044
|
-
case "form": {
|
|
28045
|
-
if (!clientCapabilities?.elicitation?.form) {
|
|
28046
|
-
throw new Error("Client does not support form elicitation.");
|
|
28047
|
-
}
|
|
28048
|
-
break;
|
|
28049
|
-
}
|
|
28050
|
-
}
|
|
28051
|
-
const normalizedParams = mode === "form" && params.mode === undefined ? { ...params, mode: "form" } : params;
|
|
28052
|
-
return this.requestStream({
|
|
28053
|
-
method: "elicitation/create",
|
|
28054
|
-
params: normalizedParams
|
|
28055
|
-
}, ElicitResultSchema, options);
|
|
28056
|
-
}
|
|
28057
28043
|
async getTask(taskId, options) {
|
|
28058
28044
|
return this._server.getTask({ taskId }, options);
|
|
28059
28045
|
}
|
|
@@ -29293,7 +29279,7 @@ var next = process.argv[3];
|
|
|
29293
29279
|
function wantsHelp() {
|
|
29294
29280
|
return next === "--help" || next === "-h";
|
|
29295
29281
|
}
|
|
29296
|
-
async function
|
|
29282
|
+
async function run19() {
|
|
29297
29283
|
if (sub === "install") {
|
|
29298
29284
|
if (wantsHelp()) {
|
|
29299
29285
|
console.log([
|
|
@@ -29436,7 +29422,7 @@ async function run18() {
|
|
|
29436
29422
|
"",
|
|
29437
29423
|
"Usage: specialists run <name> [options]",
|
|
29438
29424
|
"",
|
|
29439
|
-
"Run a specialist
|
|
29425
|
+
"Run a specialist. Streams output to stdout until completion.",
|
|
29440
29426
|
"",
|
|
29441
29427
|
"Primary modes:",
|
|
29442
29428
|
" tracked: specialists run <name> --bead <id>",
|
|
@@ -29447,20 +29433,23 @@ async function run18() {
|
|
|
29447
29433
|
" --prompt <text> Ad-hoc prompt for untracked work",
|
|
29448
29434
|
" --context-depth <n> Dependency context depth when using --bead (default: 1)",
|
|
29449
29435
|
" --no-beads Do not create a new tracking bead (does not disable bead reading)",
|
|
29450
|
-
" --background Start async and return a job id",
|
|
29451
|
-
" --follow Run in background and stream output live",
|
|
29452
29436
|
" --model <model> Override the configured model for this run",
|
|
29437
|
+
" --keep-alive Keep session alive for follow-up prompts",
|
|
29453
29438
|
"",
|
|
29454
29439
|
"Examples:",
|
|
29455
29440
|
" specialists run bug-hunt --bead unitAI-55d",
|
|
29456
|
-
" specialists run bug-hunt --bead unitAI-55d --context-depth 2
|
|
29457
|
-
" specialists run sync-docs --follow",
|
|
29441
|
+
" specialists run bug-hunt --bead unitAI-55d --context-depth 2",
|
|
29458
29442
|
' specialists run code-review --prompt "Audit src/api.ts"',
|
|
29459
29443
|
" cat brief.md | specialists run report-generator",
|
|
29460
29444
|
"",
|
|
29461
29445
|
"Rules:",
|
|
29462
29446
|
" Use --bead for tracked work.",
|
|
29463
29447
|
" Use --prompt for quick ad-hoc work.",
|
|
29448
|
+
"",
|
|
29449
|
+
"Background execution:",
|
|
29450
|
+
" Use Claude Code's native backgrounding (run_in_background: true)",
|
|
29451
|
+
" or run in a separate terminal and poll with:",
|
|
29452
|
+
" specialists poll <job-id> --json",
|
|
29464
29453
|
""
|
|
29465
29454
|
].join(`
|
|
29466
29455
|
`));
|
|
@@ -29553,6 +29542,49 @@ async function run18() {
|
|
|
29553
29542
|
const { run: handler } = await Promise.resolve().then(() => (init_feed(), exports_feed));
|
|
29554
29543
|
return handler();
|
|
29555
29544
|
}
|
|
29545
|
+
if (sub === "poll") {
|
|
29546
|
+
if (wantsHelp()) {
|
|
29547
|
+
console.log([
|
|
29548
|
+
"",
|
|
29549
|
+
"Usage: specialists poll <job-id> [--cursor N] [--json]",
|
|
29550
|
+
"",
|
|
29551
|
+
"Machine-readable job status polling for scripts and Claude Code.",
|
|
29552
|
+
"Reads from .specialists/jobs/<id>/ files.",
|
|
29553
|
+
"",
|
|
29554
|
+
"Output (JSON mode):",
|
|
29555
|
+
" {",
|
|
29556
|
+
' "job_id": "abc123",',
|
|
29557
|
+
' "status": "running" | "done" | "error" | "waiting",',
|
|
29558
|
+
' "elapsed_ms": 45000,',
|
|
29559
|
+
' "cursor": 15,',
|
|
29560
|
+
' "events": [...], // new events since cursor',
|
|
29561
|
+
' "output": "...", // full output when done',
|
|
29562
|
+
' "model": "claude-sonnet-4-6",',
|
|
29563
|
+
' "bead_id": "unitAI-123"',
|
|
29564
|
+
" }",
|
|
29565
|
+
"",
|
|
29566
|
+
"Options:",
|
|
29567
|
+
" --cursor N Event index to start from (default: 0)",
|
|
29568
|
+
" --json Output as JSON (machine-readable)",
|
|
29569
|
+
"",
|
|
29570
|
+
"Examples:",
|
|
29571
|
+
" specialists poll abc123 --json",
|
|
29572
|
+
" specialists poll abc123 --cursor 5 --json",
|
|
29573
|
+
"",
|
|
29574
|
+
"Polling pattern in Claude Code:",
|
|
29575
|
+
" 1. Start job (blocks until done):",
|
|
29576
|
+
" specialists run planner --bead xtrm-p38n.1",
|
|
29577
|
+
" 2. Or use Claude Code native backgrounding",
|
|
29578
|
+
" 3. Poll for incremental status:",
|
|
29579
|
+
" specialists poll <job-id> --json",
|
|
29580
|
+
""
|
|
29581
|
+
].join(`
|
|
29582
|
+
`));
|
|
29583
|
+
return;
|
|
29584
|
+
}
|
|
29585
|
+
const { run: pollHandler } = await Promise.resolve().then(() => (init_poll(), exports_poll));
|
|
29586
|
+
return pollHandler();
|
|
29587
|
+
}
|
|
29556
29588
|
if (sub === "steer") {
|
|
29557
29589
|
if (wantsHelp()) {
|
|
29558
29590
|
console.log([
|
|
@@ -29707,7 +29739,7 @@ Run 'specialists help' to see available commands.`);
|
|
|
29707
29739
|
const server = new SpecialistsServer;
|
|
29708
29740
|
await server.start();
|
|
29709
29741
|
}
|
|
29710
|
-
|
|
29742
|
+
run19().catch((error2) => {
|
|
29711
29743
|
logger.error(`Fatal error: ${error2}`);
|
|
29712
29744
|
process.exit(1);
|
|
29713
29745
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jaggerxtrm/specialists",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.3",
|
|
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",
|