@brainervirus/workit-mcp 8.8.0 → 8.9.1
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 +155 -28
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -19403,6 +19403,38 @@ var isNewerVersion = (candidate, current) => {
|
|
|
19403
19403
|
return false;
|
|
19404
19404
|
};
|
|
19405
19405
|
var validId = (value) => /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(value);
|
|
19406
|
+
var readText = (file) => {
|
|
19407
|
+
try {
|
|
19408
|
+
return fs7.readFileSync(file, "utf8");
|
|
19409
|
+
} catch {
|
|
19410
|
+
return "";
|
|
19411
|
+
}
|
|
19412
|
+
};
|
|
19413
|
+
var REFLOG_LINE = /^[0-9a-f]+ ([0-9a-f]+) .* (\d+) [+-]\d{4}\t(.*)$/u;
|
|
19414
|
+
var branchStart = (location, branch, aliases) => {
|
|
19415
|
+
const first = readText(path6.join(path6.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
|
|
19416
|
+
`, 1)[0];
|
|
19417
|
+
const created = REFLOG_LINE.exec(first);
|
|
19418
|
+
const start = created && /^branch: Created from (\S+)$/u.exec(created[3])?.[1];
|
|
19419
|
+
if (!created || !start)
|
|
19420
|
+
return null;
|
|
19421
|
+
if (start !== "HEAD")
|
|
19422
|
+
return start;
|
|
19423
|
+
if (!location.git)
|
|
19424
|
+
return null;
|
|
19425
|
+
for (const line of readText(path6.join(location.git.gitDir, "logs", "HEAD")).split(`
|
|
19426
|
+
`)) {
|
|
19427
|
+
const entry = REFLOG_LINE.exec(line);
|
|
19428
|
+
const moved = entry && /^checkout: moving from (\S+) to (\S+)$/u.exec(entry[3]);
|
|
19429
|
+
const seconds = entry ? Number(entry[2]) - Number(created[2]) : -1;
|
|
19430
|
+
if (moved && entry[1] === created[1] && seconds >= 0 && seconds <= 1 && aliases.includes(moved[2]))
|
|
19431
|
+
return moved[1];
|
|
19432
|
+
}
|
|
19433
|
+
return null;
|
|
19434
|
+
};
|
|
19435
|
+
var refExists = (common, ref) => fs7.existsSync(path6.join(common, ref)) || readText(path6.join(common, "packed-refs")).includes(` ${ref}
|
|
19436
|
+
`);
|
|
19437
|
+
var origins = new Map;
|
|
19406
19438
|
var sameDirectoryIdentity = (left, right) => {
|
|
19407
19439
|
if (!path6.isAbsolute(left) || !path6.isAbsolute(right))
|
|
19408
19440
|
return false;
|
|
@@ -19655,6 +19687,66 @@ class TaskStore {
|
|
|
19655
19687
|
return bound;
|
|
19656
19688
|
return success(null, null, { key: key.data, bound: bound.data });
|
|
19657
19689
|
}
|
|
19690
|
+
taskForWorker(workerId) {
|
|
19691
|
+
if (typeof workerId !== "string" || !validId(workerId))
|
|
19692
|
+
return failure2("invalid_input", "needs a worker id: `workit worker cancel|report <workerId>`");
|
|
19693
|
+
const listed = this.listTaskIndex();
|
|
19694
|
+
if (!listed.ok)
|
|
19695
|
+
return listed;
|
|
19696
|
+
for (const entry of listed.data) {
|
|
19697
|
+
if (entry.status === "closed")
|
|
19698
|
+
continue;
|
|
19699
|
+
const loaded = this.load(entry.id);
|
|
19700
|
+
if (!loaded.ok)
|
|
19701
|
+
return loaded;
|
|
19702
|
+
if (loaded.data?.record.workers.some((worker) => worker.id === workerId))
|
|
19703
|
+
return success(null, null, entry.id);
|
|
19704
|
+
}
|
|
19705
|
+
return success(null, null, null);
|
|
19706
|
+
}
|
|
19707
|
+
originTaskEntry() {
|
|
19708
|
+
const key = this.currentKey();
|
|
19709
|
+
const location = this.location();
|
|
19710
|
+
const branch = key.ok ? key.data.branch : null;
|
|
19711
|
+
if (!branch || !location.ok)
|
|
19712
|
+
return success(null, null, null);
|
|
19713
|
+
const common = path6.dirname(location.data.dir);
|
|
19714
|
+
const heads = path6.join(common, "logs", "refs", "heads");
|
|
19715
|
+
const headLog = location.data.git ? path6.join(location.data.git.gitDir, "logs", "HEAD") : "";
|
|
19716
|
+
const signatures = [
|
|
19717
|
+
path6.join(heads, branch),
|
|
19718
|
+
headLog,
|
|
19719
|
+
heads,
|
|
19720
|
+
path6.join(common, "packed-refs")
|
|
19721
|
+
].map((file) => fileSignature(file) ?? "-");
|
|
19722
|
+
const slot = `${location.data.dir}\x00${headLog}\x00${branch}`;
|
|
19723
|
+
let resolved = origins.get(slot);
|
|
19724
|
+
if (resolved?.signature !== signatures.join("|")) {
|
|
19725
|
+
const renames = branchRenames(location.data);
|
|
19726
|
+
const aliases = [branch];
|
|
19727
|
+
for (const rename of renames.toReversed())
|
|
19728
|
+
if (rename.to === aliases.at(-1))
|
|
19729
|
+
aliases.push(rename.from);
|
|
19730
|
+
const start = branchStart(location.data, branch, aliases);
|
|
19731
|
+
const slash = start?.indexOf("/") ?? -1;
|
|
19732
|
+
const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(path6.join(common, "config")).includes(`[remote "${start.slice(0, slash)}"]`));
|
|
19733
|
+
const name = start && (remote ? start.slice(slash + 1) : start);
|
|
19734
|
+
resolved = {
|
|
19735
|
+
signature: signatures.join("|"),
|
|
19736
|
+
name: name && !aliases.includes(name) ? name : null,
|
|
19737
|
+
renames
|
|
19738
|
+
};
|
|
19739
|
+
origins.set(slot, resolved);
|
|
19740
|
+
}
|
|
19741
|
+
const entry = resolved.name ? this.openTasksForKey(resolved.name, resolved.renames) : null;
|
|
19742
|
+
if (entry && !entry.ok)
|
|
19743
|
+
return entry;
|
|
19744
|
+
return success(null, null, entry?.data[0] ? { origin: `branch ${resolved.name}`, entry: entry.data[0] } : null);
|
|
19745
|
+
}
|
|
19746
|
+
readStoreTask(taskId) {
|
|
19747
|
+
const loaded = this.load(taskId);
|
|
19748
|
+
return loaded.ok ? success(null, null, loaded.data?.record ?? null) : loaded;
|
|
19749
|
+
}
|
|
19658
19750
|
create(input, provenance, expectedWorkspaceRevision) {
|
|
19659
19751
|
const value = "intent" in input ? input : {
|
|
19660
19752
|
intent: input,
|
|
@@ -20324,12 +20416,12 @@ class TaskStore {
|
|
|
20324
20416
|
return 0;
|
|
20325
20417
|
}
|
|
20326
20418
|
}
|
|
20327
|
-
openTasksForKey(key) {
|
|
20419
|
+
openTasksForKey(key, known) {
|
|
20328
20420
|
const all = this.listStoreIndex();
|
|
20329
20421
|
if (!all.ok)
|
|
20330
20422
|
return all;
|
|
20331
|
-
const location = this.location();
|
|
20332
|
-
const renames = location
|
|
20423
|
+
const location = known ? null : this.location();
|
|
20424
|
+
const renames = known ?? (location?.ok ? branchRenames(location.data) : []);
|
|
20333
20425
|
return success(null, null, all.data.filter((entry) => entry.key !== null && entry.status !== "closed").filter((entry) => (renames.length ? followRenames(entry.key, entry.boundAt ?? entry.createdAt, renames) : entry.key) === key).toSorted(oldestFirst));
|
|
20334
20426
|
}
|
|
20335
20427
|
openTaskForKey(key) {
|
|
@@ -24415,38 +24507,45 @@ var compactReference = (ref) => {
|
|
|
24415
24507
|
};
|
|
24416
24508
|
return { kind: ref.kind };
|
|
24417
24509
|
};
|
|
24418
|
-
|
|
24419
|
-
const
|
|
24420
|
-
|
|
24421
|
-
|
|
24422
|
-
|
|
24423
|
-
|
|
24424
|
-
|
|
24425
|
-
|
|
24426
|
-
|
|
24427
|
-
|
|
24428
|
-
|
|
24429
|
-
|
|
24430
|
-
|
|
24431
|
-
|
|
24432
|
-
|
|
24433
|
-
|
|
24510
|
+
var newestDecisionFirst = (left, right) => {
|
|
24511
|
+
const leftAt = compactTimestamp(left.recordedAt);
|
|
24512
|
+
const rightAt = compactTimestamp(right.recordedAt);
|
|
24513
|
+
if (leftAt !== rightAt)
|
|
24514
|
+
return leftAt > rightAt ? -1 : 1;
|
|
24515
|
+
return left.id < right.id ? -1 : left.id > right.id ? 1 : 0;
|
|
24516
|
+
};
|
|
24517
|
+
var compactDecisions = (sources) => sources.flatMap((source) => source ? source.decisions.toSorted(newestDecisionFirst).map((entry) => ({
|
|
24518
|
+
id: entry.id,
|
|
24519
|
+
purpose: entry.data.purpose,
|
|
24520
|
+
status: entry.data.response,
|
|
24521
|
+
digest: entry.data.digest,
|
|
24522
|
+
choice: compactDecisionChoice(entry) || `task.inspect taskId=${source.taskId} view=full; decision=${entry.id}`,
|
|
24523
|
+
references: entry.data.binding.contentRefs.slice(0, 1).map(compactReference),
|
|
24524
|
+
origin: source.origin ?? undefined
|
|
24525
|
+
})) : []).slice(0, COMPACT_MAX_ITEMS);
|
|
24526
|
+
function compactTaskContext(view, inherited = null) {
|
|
24527
|
+
const decisions = compactDecisions([
|
|
24528
|
+
view && { origin: null, taskId: view.task.id, decisions: view.task.decisions },
|
|
24529
|
+
inherited
|
|
24530
|
+
]);
|
|
24531
|
+
const methods = view?.task.policy ? selectMethods(view.task.policy, view.capabilities).map((method) => ({
|
|
24434
24532
|
id: method.id,
|
|
24435
24533
|
assurance: method.assurance,
|
|
24436
24534
|
reason: compactText(method.reason, COMPACT_TEXT_BYTES) ?? ""
|
|
24437
24535
|
})) : [];
|
|
24536
|
+
const stale = view?.evidence.filter((entry) => entry.status === "stale").length;
|
|
24438
24537
|
const gaps = Array.from(new Set([
|
|
24439
|
-
...
|
|
24440
|
-
...view
|
|
24441
|
-
...view
|
|
24538
|
+
...stale ? [`stale evidence: ${stale}; workit task inspect --task ${view.task.id} --view full`] : [],
|
|
24539
|
+
...(view?.requirements ?? []).filter((entry) => entry.status !== "satisfied").map((entry) => entry.reason),
|
|
24540
|
+
...(view?.task.progress.blockers ?? []).map((entry) => entry.reason)
|
|
24442
24541
|
])).toSorted().slice(0, COMPACT_MAX_ITEMS).map((gap) => compactText(gap, COMPACT_TEXT_BYTES));
|
|
24443
24542
|
const context = {
|
|
24444
|
-
objective: compactText(view.task.intent.data.objective, COMPACT_TEXT_BYTES) ?? "",
|
|
24445
|
-
status: view
|
|
24543
|
+
objective: view ? compactText(view.task.intent.data.objective, COMPACT_TEXT_BYTES) ?? "" : "no task on this branch yet",
|
|
24544
|
+
status: view?.task.status ?? null,
|
|
24446
24545
|
decisions,
|
|
24447
24546
|
methods,
|
|
24448
24547
|
gaps,
|
|
24449
|
-
nextAction: compactText(view
|
|
24548
|
+
nextAction: compactText(view?.task.progress.nextAction ?? null, COMPACT_TEXT_BYTES)
|
|
24450
24549
|
};
|
|
24451
24550
|
let encoded = JSON.stringify(context);
|
|
24452
24551
|
while (compactBytes(encoded) > COMPACT_MAX_BYTES && (context.decisions.length || context.methods.length || context.gaps.length)) {
|
|
@@ -25051,6 +25150,13 @@ var TASK_SCOPED_ACTIONS = new Set([
|
|
|
25051
25150
|
"worker.cancel",
|
|
25052
25151
|
"state.export"
|
|
25053
25152
|
]);
|
|
25153
|
+
var WORKER_ADDRESSED_ACTIONS = new Set(["worker.cancel", "worker.report"]);
|
|
25154
|
+
var workerCommand = (taskId, request) => {
|
|
25155
|
+
const { action, workerId, reason, report } = request;
|
|
25156
|
+
const rest = JSON.stringify({ reason, report });
|
|
25157
|
+
const payload = rest === "{}" ? "" : ` --payload '${rest.replace(/'/gu, "'\\''")}'`;
|
|
25158
|
+
return `workit worker ${String(action)} ${String(workerId)} --task ${taskId}${payload}`;
|
|
25159
|
+
};
|
|
25054
25160
|
var CREATING_ACTIONS = new Set([
|
|
25055
25161
|
"task.revise",
|
|
25056
25162
|
"task.progress",
|
|
@@ -25301,6 +25407,17 @@ class WorkitCore {
|
|
|
25301
25407
|
const root = this.contextRootError();
|
|
25302
25408
|
if (!root.ok)
|
|
25303
25409
|
return root;
|
|
25410
|
+
const addressed = WORKER_ADDRESSED_ACTIONS.has(action);
|
|
25411
|
+
const workerId = addressed ? value.workerId : this.context.workerId ?? null;
|
|
25412
|
+
if (workerId !== null) {
|
|
25413
|
+
const owner = this.store.taskForWorker(workerId);
|
|
25414
|
+
if (!owner.ok)
|
|
25415
|
+
return owner;
|
|
25416
|
+
if (owner.data)
|
|
25417
|
+
return success(null, null, { ...request, taskId: owner.data });
|
|
25418
|
+
if (addressed)
|
|
25419
|
+
return failure2("not_found", `worker ${workerId} is on no open task; find its task with \`workit task status --all\`, then run \`${workerCommand("<task-id>", request)}\``);
|
|
25420
|
+
}
|
|
25304
25421
|
const create = CREATING_ACTIONS.has(action) && (this.context.workerId ?? null) === null;
|
|
25305
25422
|
const found = this.store.implicitTask({
|
|
25306
25423
|
provenance: provenance(this.context),
|
|
@@ -26007,7 +26124,9 @@ class WorkitCore {
|
|
|
26007
26124
|
if (!resolved.ok)
|
|
26008
26125
|
return resolved;
|
|
26009
26126
|
const value = resolved.data;
|
|
26010
|
-
|
|
26127
|
+
const result = this.retryOmittedRevisions(value, () => this.workerOnce(value));
|
|
26128
|
+
const { action, taskId } = value ?? {};
|
|
26129
|
+
return result.ok || request?.taskId !== undefined || typeof taskId !== "string" || !WORKER_ADDRESSED_ACTIONS.has(`worker.${String(action)}`) ? result : { ...result, error: `${result.error}; run \`${workerCommand(taskId, value)}\`` };
|
|
26011
26130
|
}
|
|
26012
26131
|
workerOnce(request) {
|
|
26013
26132
|
const root = this.contextRootError();
|
|
@@ -26212,10 +26331,18 @@ class WorkitCore {
|
|
|
26212
26331
|
requirements
|
|
26213
26332
|
});
|
|
26214
26333
|
}
|
|
26215
|
-
compactContext(taskId, freshness) {
|
|
26334
|
+
compactContext(taskId, freshness, origin = null) {
|
|
26216
26335
|
const root = this.contextRootError();
|
|
26217
26336
|
if (!root.ok)
|
|
26218
26337
|
return root;
|
|
26338
|
+
const base = origin && this.store.readStoreTask(origin.taskId);
|
|
26339
|
+
const inherited = base?.ok && base.data ? {
|
|
26340
|
+
origin: origin.origin,
|
|
26341
|
+
taskId: base.data.id,
|
|
26342
|
+
decisions: base.data.decisions.filter((entry) => entry.data.revoked === null)
|
|
26343
|
+
} : null;
|
|
26344
|
+
if (taskId === null)
|
|
26345
|
+
return success(null, null, inherited?.decisions.length ? compactTaskContext(null, inherited) : "");
|
|
26219
26346
|
const task = this.store.readTask(taskId);
|
|
26220
26347
|
if (!task.ok)
|
|
26221
26348
|
return task;
|
|
@@ -26225,7 +26352,7 @@ class WorkitCore {
|
|
|
26225
26352
|
const view = this.view(task.data, false, freshness ?? signalFreshness(this.store.root));
|
|
26226
26353
|
if (!view.ok)
|
|
26227
26354
|
return view;
|
|
26228
|
-
return success(view.revision, view.workspaceRevision, compactTaskContext(view.data));
|
|
26355
|
+
return success(view.revision, view.workspaceRevision, compactTaskContext(view.data, inherited));
|
|
26229
26356
|
}
|
|
26230
26357
|
view(task, capture = true, freshness = treeFreshness(this.store.root)) {
|
|
26231
26358
|
const workspace = this.store.readWorkspace();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-mcp",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.9.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit shared MCP transport for the eight task and policy operation families",
|
|
6
6
|
"keywords": [
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"build": "bun scripts/build.ts"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@brainervirus/workit-core": "^8.
|
|
45
|
+
"@brainervirus/workit-core": "^8.9.1",
|
|
46
46
|
"@modelcontextprotocol/sdk": "1.32.0",
|
|
47
47
|
"zod": "4.6.5"
|
|
48
48
|
},
|