@brainervirus/workit-mcp 8.14.0 → 8.14.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 +49 -9
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -16611,6 +16611,8 @@ var text = string2().check((ctx) => {
|
|
|
16611
16611
|
ctx.issues.push({ code: "custom", input: ctx.value, message: "invalid Unicode", path: [] });
|
|
16612
16612
|
});
|
|
16613
16613
|
var id = text.regex(uuidPattern, "expected lowercase UUID");
|
|
16614
|
+
var idRefPattern = /^[0-9a-f][0-9a-f-]{7,35}$/;
|
|
16615
|
+
var idRef = text.regex(idRefPattern, "expected a UUID or an id prefix of 8+ characters");
|
|
16614
16616
|
var digest = text.regex(digestPattern, "expected lowercase SHA-256 digest");
|
|
16615
16617
|
var revision = text.regex(uuidPattern, "expected UUID revision");
|
|
16616
16618
|
var validUtc = (value) => {
|
|
@@ -16988,7 +16990,7 @@ var workerReportSchema = object2({
|
|
|
16988
16990
|
outcome: _enum(["completed", "failed", "cancelled"]),
|
|
16989
16991
|
summary: text,
|
|
16990
16992
|
evidenceIds: array(id),
|
|
16991
|
-
findingIds: array(
|
|
16993
|
+
findingIds: array(idRef)
|
|
16992
16994
|
}).strict();
|
|
16993
16995
|
var workerSchema = object2({
|
|
16994
16996
|
assignment: assignmentSchema,
|
|
@@ -17234,7 +17236,7 @@ var findingOperations = {
|
|
|
17234
17236
|
action: literal("resolve"),
|
|
17235
17237
|
...taskId,
|
|
17236
17238
|
expectedRevision: revision.optional(),
|
|
17237
|
-
findingId:
|
|
17239
|
+
findingId: idRef,
|
|
17238
17240
|
disposition: _enum(["open", "fixed", "dismissed", "deferred"]),
|
|
17239
17241
|
reason: text,
|
|
17240
17242
|
evidenceIds: array(id),
|
|
@@ -17275,7 +17277,7 @@ var workerOperations = {
|
|
|
17275
17277
|
...taskId,
|
|
17276
17278
|
expectedRevision: revision.optional(),
|
|
17277
17279
|
expectedWorkspaceRevision: revision.optional(),
|
|
17278
|
-
workerId:
|
|
17280
|
+
workerId: idRef,
|
|
17279
17281
|
report: workerReportSchema
|
|
17280
17282
|
}),
|
|
17281
17283
|
cancel: operation({
|
|
@@ -17283,7 +17285,7 @@ var workerOperations = {
|
|
|
17283
17285
|
...taskId,
|
|
17284
17286
|
...revisions,
|
|
17285
17287
|
expectedWorkspaceRevision: revision.optional(),
|
|
17286
|
-
workerId:
|
|
17288
|
+
workerId: idRef,
|
|
17287
17289
|
reason: text
|
|
17288
17290
|
})
|
|
17289
17291
|
};
|
|
@@ -17333,6 +17335,16 @@ var success = (revisionValue, workspaceRevisionValue, data) => ({
|
|
|
17333
17335
|
data
|
|
17334
17336
|
});
|
|
17335
17337
|
var failure2 = (code, error, details = {}) => ({ ok: false, schemaVersion: 1, code, error, details });
|
|
17338
|
+
function resolveIdRef(kind, ref, ids) {
|
|
17339
|
+
if (ids.includes(ref))
|
|
17340
|
+
return success(null, null, ref);
|
|
17341
|
+
const matches = ids.filter((candidate) => candidate.startsWith(ref));
|
|
17342
|
+
if (matches.length === 1)
|
|
17343
|
+
return success(null, null, matches[0]);
|
|
17344
|
+
if (matches.length === 0)
|
|
17345
|
+
return failure2("not_found", `${kind} not found`);
|
|
17346
|
+
return failure2("invalid_input", `${kind} prefix ${ref} is ambiguous; candidates: ${matches.join(", ")}`);
|
|
17347
|
+
}
|
|
17336
17348
|
function parseOperation(family, input) {
|
|
17337
17349
|
if (typeof input === "object" && input !== null && "schemaVersion" in input && input.schemaVersion !== SCHEMA_VERSION)
|
|
17338
17350
|
return failure2("unsupported_version", "unsupported schema version", { operation: family });
|
|
@@ -19851,20 +19863,26 @@ class TaskStore {
|
|
|
19851
19863
|
return success(null, null, { key: key.data, bound: bound.data });
|
|
19852
19864
|
}
|
|
19853
19865
|
taskForWorker(workerId) {
|
|
19854
|
-
if (typeof workerId !== "string" || !
|
|
19866
|
+
if (typeof workerId !== "string" || !idRefPattern.test(workerId))
|
|
19855
19867
|
return failure2("invalid_input", "needs a worker id: `workit worker cancel|report <workerId>`");
|
|
19856
19868
|
const listed = this.listTaskIndex();
|
|
19857
19869
|
if (!listed.ok)
|
|
19858
19870
|
return listed;
|
|
19871
|
+
const owners = new Map;
|
|
19859
19872
|
for (const entry of listed.data) {
|
|
19860
19873
|
if (entry.status === "closed")
|
|
19861
19874
|
continue;
|
|
19862
19875
|
const loaded = this.load(entry.id);
|
|
19863
19876
|
if (!loaded.ok)
|
|
19864
19877
|
return loaded;
|
|
19865
|
-
|
|
19866
|
-
|
|
19878
|
+
for (const worker of loaded.data?.record.workers ?? [])
|
|
19879
|
+
owners.set(worker.id, entry.id);
|
|
19867
19880
|
}
|
|
19881
|
+
const resolved = resolveIdRef("worker", workerId, [...owners.keys()]);
|
|
19882
|
+
if (resolved.ok)
|
|
19883
|
+
return success(null, null, owners.get(resolved.data) ?? null);
|
|
19884
|
+
if (resolved.code !== "not_found")
|
|
19885
|
+
return resolved;
|
|
19868
19886
|
return success(null, null, null);
|
|
19869
19887
|
}
|
|
19870
19888
|
originTaskEntry() {
|
|
@@ -25582,6 +25600,8 @@ var TASK_SCOPED_ACTIONS = new Set([
|
|
|
25582
25600
|
"worker.cancel",
|
|
25583
25601
|
"state.export"
|
|
25584
25602
|
]);
|
|
25603
|
+
var ONLY_OWN_REPORT = "workers can submit only their own report";
|
|
25604
|
+
var NO_HELPER_CONTROL = "helpers cannot cancel or control workers";
|
|
25585
25605
|
var WORKER_ADDRESSED_ACTIONS = new Set(["worker.cancel", "worker.report"]);
|
|
25586
25606
|
var workerCommand = (taskId, request) => {
|
|
25587
25607
|
const { action, workerId, reason, report } = request;
|
|
@@ -26479,6 +26499,10 @@ class WorkitCore {
|
|
|
26479
26499
|
}
|
|
26480
26500
|
if (helper?.ok)
|
|
26481
26501
|
return failure2("permission_denied", "helpers cannot resolve findings");
|
|
26502
|
+
const findingRef = resolveIdRef("finding", input.findingId, task.data.findings.map((entry) => entry.id));
|
|
26503
|
+
if (!findingRef.ok)
|
|
26504
|
+
return findingRef;
|
|
26505
|
+
input.findingId = findingRef.data;
|
|
26482
26506
|
const finding = task.data.findings.find((entry) => entry.id === input.findingId);
|
|
26483
26507
|
if (!finding)
|
|
26484
26508
|
return failure2("not_found", "finding not found");
|
|
@@ -26630,15 +26654,31 @@ class WorkitCore {
|
|
|
26630
26654
|
return changed;
|
|
26631
26655
|
return success(changed.data.task.revision, changed.data.workspace.revision, changed.data.task.workers.at(-1));
|
|
26632
26656
|
}
|
|
26657
|
+
const workerRef = resolveIdRef("worker", input.workerId, helperId === null ? task.data.workers.map((candidate) => candidate.id) : [helperId]);
|
|
26658
|
+
if (!workerRef.ok)
|
|
26659
|
+
return helperId === null ? workerRef : failure2("permission_denied", input.action === "report" ? ONLY_OWN_REPORT : NO_HELPER_CONTROL);
|
|
26660
|
+
input.workerId = workerRef.data;
|
|
26633
26661
|
const entry = task.data.workers.find((candidate) => candidate.id === input.workerId);
|
|
26634
26662
|
if (!entry)
|
|
26635
26663
|
return failure2("not_found", "worker not found");
|
|
26636
26664
|
if (input.action === "report") {
|
|
26637
26665
|
if (helperId === null || helperId !== input.workerId)
|
|
26638
|
-
return failure2("permission_denied",
|
|
26666
|
+
return failure2("permission_denied", ONLY_OWN_REPORT);
|
|
26639
26667
|
const helper = this.helperEntry(task.data, true, true);
|
|
26640
26668
|
if (!helper.ok)
|
|
26641
26669
|
return helper;
|
|
26670
|
+
const ownFindings = task.data.findings.filter((candidate) => candidate.provenance.workerId === helperId).map((candidate) => candidate.id);
|
|
26671
|
+
const reported = [];
|
|
26672
|
+
for (const findingRef of input.report.findingIds) {
|
|
26673
|
+
const found = resolveIdRef("finding", findingRef, ownFindings);
|
|
26674
|
+
if (found.ok)
|
|
26675
|
+
reported.push(found.data);
|
|
26676
|
+
else if (found.code === "not_found")
|
|
26677
|
+
reported.push(findingRef);
|
|
26678
|
+
else
|
|
26679
|
+
return found;
|
|
26680
|
+
}
|
|
26681
|
+
input.report.findingIds = reported;
|
|
26642
26682
|
const evidence = task.data.evidence.filter((candidate) => input.report.evidenceIds.includes(candidate.id));
|
|
26643
26683
|
const findings = task.data.findings.filter((candidate) => input.report.findingIds.includes(candidate.id));
|
|
26644
26684
|
if (evidence.length !== input.report.evidenceIds.length || findings.length !== input.report.findingIds.length)
|
|
@@ -26666,7 +26706,7 @@ class WorkitCore {
|
|
|
26666
26706
|
return updated ? success(changed.data.task.revision, changed.data.workspace.revision, updated) : failure2("recovery_required", "worker disappeared during report");
|
|
26667
26707
|
}
|
|
26668
26708
|
if (helperId !== null)
|
|
26669
|
-
return failure2("permission_denied",
|
|
26709
|
+
return failure2("permission_denied", NO_HELPER_CONTROL);
|
|
26670
26710
|
if (task.data.status === "closed")
|
|
26671
26711
|
return failure2("invalid_transition", "closed task cannot cancel workers");
|
|
26672
26712
|
if (entry.data.state === "stopped") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-mcp",
|
|
3
|
-
"version": "8.14.
|
|
3
|
+
"version": "8.14.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.14.
|
|
45
|
+
"@brainervirus/workit-core": "^8.14.1",
|
|
46
46
|
"@modelcontextprotocol/sdk": "1.32.0",
|
|
47
47
|
"zod": "4.6.5"
|
|
48
48
|
},
|