@sift-wiki/cli 0.1.1 → 0.1.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/README.md +28 -16
- package/dist/bin/sift.js +357 -52
- package/package.json +11 -9
package/README.md
CHANGED
|
@@ -1,30 +1,42 @@
|
|
|
1
1
|
# Sift CLI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This repository is the public release mirror for `@sift-wiki/cli`.
|
|
4
|
+
|
|
5
|
+
The package installs the `sift` command:
|
|
4
6
|
|
|
5
7
|
```bash
|
|
6
8
|
npm install -g @sift-wiki/cli
|
|
9
|
+
sift login
|
|
10
|
+
sift doctor
|
|
7
11
|
```
|
|
8
12
|
|
|
9
|
-
|
|
10
|
-
npm trusted publishing is configured, a matching `cli-v<version>` tag has
|
|
11
|
-
published the package, and a post-publish global install smoke has passed. Repo
|
|
12
|
-
verification before that is:
|
|
13
|
+
For one-off use without a global install:
|
|
13
14
|
|
|
14
15
|
```bash
|
|
15
|
-
|
|
16
|
+
npx -y @sift-wiki/cli@latest auth status --json
|
|
17
|
+
npm exec --yes --package @sift-wiki/cli@latest -- sift auth status --json
|
|
16
18
|
```
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
## Release Shape
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
The private Sift monorepo builds the bundled CLI artifact. This public repo
|
|
23
|
+
contains only the files needed to publish the public npm package:
|
|
24
|
+
|
|
25
|
+
- `package.json`
|
|
26
|
+
- `README.md`
|
|
27
|
+
- `dist/bin/sift.js`
|
|
28
|
+
- `scripts/verify-release.mjs`
|
|
29
|
+
- `.github/workflows/publish-cli.yml`
|
|
30
|
+
|
|
31
|
+
The bundled `dist/bin/sift.js` is the same artifact npm users receive.
|
|
32
|
+
|
|
33
|
+
## Maintainer Release
|
|
25
34
|
|
|
26
|
-
|
|
27
|
-
|
|
35
|
+
1. Update `package.json` and `dist/bin/sift.js`.
|
|
36
|
+
2. Run `npm run verify`.
|
|
37
|
+
3. Commit and push to `main`.
|
|
38
|
+
4. Tag `cli-v<package-version>`.
|
|
39
|
+
5. Push the tag.
|
|
28
40
|
|
|
29
|
-
|
|
30
|
-
|
|
41
|
+
The tag workflow publishes through npm trusted publishing. It uses GitHub OIDC
|
|
42
|
+
and does not require an npm token secret.
|
package/dist/bin/sift.js
CHANGED
|
@@ -9,6 +9,75 @@ var __export = (target, all) => {
|
|
|
9
9
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
// ../tools/dist/gating.js
|
|
13
|
+
function isGatedTool(name) {
|
|
14
|
+
return !ungatedToolNames.has(name);
|
|
15
|
+
}
|
|
16
|
+
var UNGATED_TOOL_NAMES, ungatedToolNames;
|
|
17
|
+
var init_gating = __esm({
|
|
18
|
+
"../tools/dist/gating.js"() {
|
|
19
|
+
"use strict";
|
|
20
|
+
UNGATED_TOOL_NAMES = [
|
|
21
|
+
"contract.get",
|
|
22
|
+
"whoami",
|
|
23
|
+
"tools.list",
|
|
24
|
+
"tools.schema",
|
|
25
|
+
"tools.help",
|
|
26
|
+
"tools.search",
|
|
27
|
+
"brain.list",
|
|
28
|
+
"brain.use",
|
|
29
|
+
"scope.current"
|
|
30
|
+
];
|
|
31
|
+
ungatedToolNames = new Set(UNGATED_TOOL_NAMES);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// ../tools/dist/canvasTools.js
|
|
36
|
+
function canvasToolDefinitions(writeTool2) {
|
|
37
|
+
return [
|
|
38
|
+
writeTool2("canvas.create", "Create a canvas (a spatial board of live views and notes). Returns the canvas id; compose it with canvas.add_node.", {
|
|
39
|
+
title: { type: "string" },
|
|
40
|
+
intent: { type: "string" }
|
|
41
|
+
}, "sift canvas create --title 'This week'", { required: ["title"] }),
|
|
42
|
+
writeTool2("canvas.add_node", [
|
|
43
|
+
"Add one node to a canvas. Pick the most structured nodeType that fits; prose is the",
|
|
44
|
+
"last resort. nodeType: plan (title + tracks of {name, owners?, goal?, items:[{text,",
|
|
45
|
+
"who?, when?, done?}]} \u2014 roadmaps, weekly plans, agendas), metric (label + value,",
|
|
46
|
+
"optional delta {direction,magnitude,sentiment} \u2014 one number), chart (rows of",
|
|
47
|
+
"{label, value:number}, optional title \u2014 comparing numbers), kanban or checklist",
|
|
48
|
+
"(queryRef binding to a live workspace query), prose (markdown, optional title),",
|
|
49
|
+
"note (text \u2014 a short plain annotation, never primary content).",
|
|
50
|
+
"Content must come from brain data you actually read, never invented."
|
|
51
|
+
].join(" "), {
|
|
52
|
+
canvasId: { type: "string" },
|
|
53
|
+
nodeType: {
|
|
54
|
+
type: "string",
|
|
55
|
+
enum: ["plan", "metric", "chart", "kanban", "checklist", "prose", "note"]
|
|
56
|
+
},
|
|
57
|
+
text: { type: "string" },
|
|
58
|
+
markdown: { type: "string" },
|
|
59
|
+
title: { type: "string" },
|
|
60
|
+
timeframe: { type: "string" },
|
|
61
|
+
tracks: { type: "array", items: { type: "object" } },
|
|
62
|
+
label: { type: "string" },
|
|
63
|
+
value: { type: "string" },
|
|
64
|
+
delta: { type: "object" },
|
|
65
|
+
rows: { type: "array", items: { type: "object" } },
|
|
66
|
+
queryRef: { type: "string" },
|
|
67
|
+
position: { type: "object" }
|
|
68
|
+
}, "sift canvas add-node <canvas-id> --type metric", { required: ["canvasId", "nodeType"] }),
|
|
69
|
+
writeTool2("canvas.remove_node", "Remove a node or note from a canvas by id.", {
|
|
70
|
+
canvasId: { type: "string" },
|
|
71
|
+
nodeId: { type: "string" }
|
|
72
|
+
}, "sift canvas remove-node <canvas-id> <node-id>", { required: ["canvasId", "nodeId"] })
|
|
73
|
+
];
|
|
74
|
+
}
|
|
75
|
+
var init_canvasTools = __esm({
|
|
76
|
+
"../tools/dist/canvasTools.js"() {
|
|
77
|
+
"use strict";
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
12
81
|
// ../tools/dist/inputParsers.js
|
|
13
82
|
function parseCaptureFile(input) {
|
|
14
83
|
return {
|
|
@@ -247,7 +316,38 @@ var init_inputParsers = __esm({
|
|
|
247
316
|
|
|
248
317
|
// ../tools/dist/registry.js
|
|
249
318
|
function listToolDefinitions() {
|
|
250
|
-
return [...toolDefinitions];
|
|
319
|
+
return [...toolDefinitions, ...canvasToolDefinitions(writeTool)].map((tool) => isGatedTool(tool.name) ? withContractVersionProperty(tool) : tool);
|
|
320
|
+
}
|
|
321
|
+
function withContractVersionProperty(tool) {
|
|
322
|
+
return {
|
|
323
|
+
...tool,
|
|
324
|
+
inputSchema: {
|
|
325
|
+
...tool.inputSchema,
|
|
326
|
+
properties: {
|
|
327
|
+
...tool.inputSchema.properties,
|
|
328
|
+
contractVersion: {
|
|
329
|
+
type: "string",
|
|
330
|
+
description: "Echo the current Sift contract version from contract.get."
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
function isToolAuthorized(capabilities, tool) {
|
|
337
|
+
return tool.capability === NO_CAPABILITY || capabilities.includes(tool.capability);
|
|
338
|
+
}
|
|
339
|
+
function identityTool(name, summary, properties, cliExample, options) {
|
|
340
|
+
return defineTool({
|
|
341
|
+
name,
|
|
342
|
+
summary,
|
|
343
|
+
properties,
|
|
344
|
+
required: options.required ?? [],
|
|
345
|
+
capability: NO_CAPABILITY,
|
|
346
|
+
mutability: options.mutability,
|
|
347
|
+
transports: writeTransports,
|
|
348
|
+
cliExample,
|
|
349
|
+
hostedAgent: { available: false, ...options.hostedAgent }
|
|
350
|
+
});
|
|
251
351
|
}
|
|
252
352
|
function readTool(name, summary, properties, cliExample, options) {
|
|
253
353
|
return defineTool({
|
|
@@ -373,14 +473,18 @@ function tokenize(text) {
|
|
|
373
473
|
function stringProps(names) {
|
|
374
474
|
return Object.fromEntries(names.map((name) => [name, { type: "string" }]));
|
|
375
475
|
}
|
|
376
|
-
var readTransports, writeTransports, toolDefinitions;
|
|
476
|
+
var readTransports, writeTransports, NO_CAPABILITY, toolDefinitions;
|
|
377
477
|
var init_registry = __esm({
|
|
378
478
|
"../tools/dist/registry.js"() {
|
|
379
479
|
"use strict";
|
|
480
|
+
init_gating();
|
|
481
|
+
init_canvasTools();
|
|
380
482
|
init_inputParsers();
|
|
381
483
|
readTransports = ["cli", "hosted_mcp", "local_mcp"];
|
|
382
484
|
writeTransports = ["cli", "hosted_mcp", "local_mcp"];
|
|
485
|
+
NO_CAPABILITY = "none";
|
|
383
486
|
toolDefinitions = [
|
|
487
|
+
readTool("contract.get", "Fetch the Sift agent contract (kernel + workspace overlay) and the contractVersion to echo on every gated tool call. Call this before any other Sift work.", {}, "sift contract get"),
|
|
384
488
|
readTool("whoami", "Return principal, actor, scope, and capabilities.", {}, "sift whoami"),
|
|
385
489
|
readTool("brain.list", "List brains available to the current scope.", {}, "sift brain list"),
|
|
386
490
|
readTool("brain.use", "Select the current brain scope for subsequent operations.", stringProps(["brainId"]), "sift brain use <brain-id>"),
|
|
@@ -465,8 +569,15 @@ var init_registry = __esm({
|
|
|
465
569
|
evidenceIds: { type: "array", items: { type: "string" } },
|
|
466
570
|
visibility: { type: "array", items: { type: "string" } }
|
|
467
571
|
}, "sift task create", { required: ["title", "visibility"] }),
|
|
572
|
+
identityTool("agent.register", "Register the calling agent as a workspace agent worker acting for the token's owner; idempotent on (workspace, owner, normalized name) and never mutates token state.", {
|
|
573
|
+
name: { type: "string", maxLength: 80 },
|
|
574
|
+
description: { type: "string", maxLength: 280 },
|
|
575
|
+
kind: { type: "string" }
|
|
576
|
+
}, 'sift agent register --name "Claude Code" --description "Coding agent"', { required: ["name"], mutability: "write" }),
|
|
577
|
+
identityTool("agent.status", "Report the request's resolved agent identity (from the asserted agent name) or none.", {}, "sift agent status --json", { mutability: "read" }),
|
|
468
578
|
readTool("skill.resolve", "Resolve at most three advisory skill candidates for a task description, each with the skill record id, pinned active version id, title, and applicability summary, or an empty list.", { query: { type: "string" } }, "sift skill resolve 'draft the monthly investor update'", { required: ["query"] }),
|
|
469
|
-
readTool("skill.get", "Read a skill's pinned active version markdown body
|
|
579
|
+
readTool("skill.get", "Read a skill's pinned active version markdown body, version id, and bundle file paths by skill record id.", { skillId: { type: "string" } }, "sift skill get <skill-id>", { required: ["skillId"] }),
|
|
580
|
+
readTool("skill.file", "Read one of a skill's bundle files by path; fetch a file only when the skill body references it and the task needs that detail, using a path listed by skill.get.", { skillId: { type: "string" }, path: { type: "string" } }, "sift skill file <skill-id> examples/2026-05-29-good.md", { required: ["skillId", "path"] }),
|
|
470
581
|
writeTool("skill.exercise", "Report that a skill version informed an output on a surface; the report is an attribution claim only.", {
|
|
471
582
|
skillId: { type: "string" },
|
|
472
583
|
versionId: { type: "string" },
|
|
@@ -515,6 +626,7 @@ function executeWhoami(auth) {
|
|
|
515
626
|
return {
|
|
516
627
|
principal: { id: auth.principalId, type: auth.principalType },
|
|
517
628
|
actor: { id: auth.actorId, type: auth.actorType },
|
|
629
|
+
...auth.agent === void 0 ? {} : { agent: auth.agent },
|
|
518
630
|
scope: { workspaceId: auth.workspaceId, brainId: auth.brainId },
|
|
519
631
|
requestId: auth.requestId,
|
|
520
632
|
authPath: auth.authPath,
|
|
@@ -581,7 +693,7 @@ function executeToolsSearch(input, searchInput) {
|
|
|
581
693
|
function availableTools(input) {
|
|
582
694
|
const transport = input.transport ?? "local_mcp";
|
|
583
695
|
const availableNames = new Set(input.availableToolNames ?? IMPLEMENTED_TOOL_NAMES);
|
|
584
|
-
return listToolDefinitions().filter((tool) => availableNames.has(tool.name) && tool.transports.includes(transport) && input.auth.capabilities
|
|
696
|
+
return listToolDefinitions().filter((tool) => availableNames.has(tool.name) && tool.transports.includes(transport) && isToolAuthorized(input.auth.capabilities, tool));
|
|
585
697
|
}
|
|
586
698
|
function scoreTool(tool, intentTokens) {
|
|
587
699
|
const haystack = /* @__PURE__ */ new Set([
|
|
@@ -631,7 +743,9 @@ var init_discovery = __esm({
|
|
|
631
743
|
"evidence.get",
|
|
632
744
|
"graph.neighbors",
|
|
633
745
|
"event.list",
|
|
634
|
-
"audit.events"
|
|
746
|
+
"audit.events",
|
|
747
|
+
"agent.register",
|
|
748
|
+
"agent.status"
|
|
635
749
|
];
|
|
636
750
|
}
|
|
637
751
|
});
|
|
@@ -704,6 +818,26 @@ var init_captureTools = __esm({
|
|
|
704
818
|
}
|
|
705
819
|
});
|
|
706
820
|
|
|
821
|
+
// ../tools/dist/contractTools.js
|
|
822
|
+
function contractToolHandlers(input) {
|
|
823
|
+
return {
|
|
824
|
+
"contract.get": () => {
|
|
825
|
+
if (input.service.getContract === void 0) {
|
|
826
|
+
throw new Error("Tool 'contract.get' requires a runtime service contract.");
|
|
827
|
+
}
|
|
828
|
+
return input.service.getContract({ auth: input.auth });
|
|
829
|
+
}
|
|
830
|
+
};
|
|
831
|
+
}
|
|
832
|
+
function contractToolAvailability(service) {
|
|
833
|
+
return [[service.getContract !== void 0, ["contract.get"]]];
|
|
834
|
+
}
|
|
835
|
+
var init_contractTools = __esm({
|
|
836
|
+
"../tools/dist/contractTools.js"() {
|
|
837
|
+
"use strict";
|
|
838
|
+
}
|
|
839
|
+
});
|
|
840
|
+
|
|
707
841
|
// ../tools/dist/skillTools.js
|
|
708
842
|
function skillToolHandlers(input, toolInput) {
|
|
709
843
|
return {
|
|
@@ -723,6 +857,15 @@ function skillToolHandlers(input, toolInput) {
|
|
|
723
857
|
skillId: requireString(toolInput, "skillId")
|
|
724
858
|
});
|
|
725
859
|
},
|
|
860
|
+
"skill.file": () => {
|
|
861
|
+
if (input.service.getSkillFile === void 0)
|
|
862
|
+
throw missingSkillService("skill.file");
|
|
863
|
+
return input.service.getSkillFile({
|
|
864
|
+
auth: input.auth,
|
|
865
|
+
skillId: requireString(toolInput, "skillId"),
|
|
866
|
+
path: requireString(toolInput, "path")
|
|
867
|
+
});
|
|
868
|
+
},
|
|
726
869
|
"skill.exercise": () => {
|
|
727
870
|
if (input.service.recordSkillExercise === void 0) {
|
|
728
871
|
throw missingSkillService("skill.exercise");
|
|
@@ -743,6 +886,7 @@ function skillToolAvailability(service) {
|
|
|
743
886
|
return [
|
|
744
887
|
[service.resolveSkills !== void 0, ["skill.resolve"]],
|
|
745
888
|
[service.getSkill !== void 0, ["skill.get"]],
|
|
889
|
+
[service.getSkillFile !== void 0, ["skill.file"]],
|
|
746
890
|
[service.recordSkillExercise !== void 0, ["skill.exercise"]],
|
|
747
891
|
[service.teachSkill !== void 0, ["skill.teach"]]
|
|
748
892
|
];
|
|
@@ -805,6 +949,104 @@ var init_skillTools = __esm({
|
|
|
805
949
|
}
|
|
806
950
|
});
|
|
807
951
|
|
|
952
|
+
// ../tools/dist/agentIdentityTools.js
|
|
953
|
+
function agentIdentityToolHandlers(input, toolInput) {
|
|
954
|
+
return {
|
|
955
|
+
"agent.register": () => {
|
|
956
|
+
if (input.service.registerAgent === void 0) {
|
|
957
|
+
throw missingAgentIdentityService("agent.register");
|
|
958
|
+
}
|
|
959
|
+
return input.service.registerAgent({
|
|
960
|
+
auth: input.auth,
|
|
961
|
+
name: requireString(toolInput, "name"),
|
|
962
|
+
description: optionalString(toolInput, "description"),
|
|
963
|
+
kind: parseAgentKind(toolInput)
|
|
964
|
+
});
|
|
965
|
+
},
|
|
966
|
+
"agent.status": () => {
|
|
967
|
+
if (input.service.getAgentStatus === void 0) {
|
|
968
|
+
throw missingAgentIdentityService("agent.status");
|
|
969
|
+
}
|
|
970
|
+
return input.service.getAgentStatus({ auth: input.auth });
|
|
971
|
+
}
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
function agentIdentityToolAvailability(service) {
|
|
975
|
+
return [
|
|
976
|
+
[service.registerAgent !== void 0, ["agent.register"]],
|
|
977
|
+
[service.getAgentStatus !== void 0, ["agent.status"]]
|
|
978
|
+
];
|
|
979
|
+
}
|
|
980
|
+
function parseAgentKind(toolInput) {
|
|
981
|
+
const kind = optionalString(toolInput, "kind");
|
|
982
|
+
if (kind === void 0) {
|
|
983
|
+
return void 0;
|
|
984
|
+
}
|
|
985
|
+
if (kind !== "agent" && kind !== "service") {
|
|
986
|
+
throw new Error("kind must be 'agent' or 'service'.");
|
|
987
|
+
}
|
|
988
|
+
return kind;
|
|
989
|
+
}
|
|
990
|
+
function missingAgentIdentityService(toolName) {
|
|
991
|
+
return new Error(`Tool '${toolName}' requires a runtime service contract.`);
|
|
992
|
+
}
|
|
993
|
+
var init_agentIdentityTools = __esm({
|
|
994
|
+
"../tools/dist/agentIdentityTools.js"() {
|
|
995
|
+
"use strict";
|
|
996
|
+
init_inputParsers();
|
|
997
|
+
}
|
|
998
|
+
});
|
|
999
|
+
|
|
1000
|
+
// ../tools/dist/toolAvailability.js
|
|
1001
|
+
function runtimeAvailableToolNames(service) {
|
|
1002
|
+
const baseNames = [
|
|
1003
|
+
"whoami",
|
|
1004
|
+
"tools.list",
|
|
1005
|
+
"tools.schema",
|
|
1006
|
+
"tools.help",
|
|
1007
|
+
"tools.search",
|
|
1008
|
+
"brain.list",
|
|
1009
|
+
"brain.use",
|
|
1010
|
+
"scope.current",
|
|
1011
|
+
"capture.text",
|
|
1012
|
+
"capture.batch",
|
|
1013
|
+
"search.query",
|
|
1014
|
+
"context.assemble"
|
|
1015
|
+
];
|
|
1016
|
+
const optionalNames = [
|
|
1017
|
+
[service.ingestFile !== void 0, ["capture.file"]],
|
|
1018
|
+
[service.createDecision !== void 0, ["decision.create"]],
|
|
1019
|
+
[service.createTask !== void 0, ["task.create"]],
|
|
1020
|
+
...skillToolAvailability(service),
|
|
1021
|
+
...agentIdentityToolAvailability(service),
|
|
1022
|
+
...contractToolAvailability(service),
|
|
1023
|
+
[service.listSources !== void 0, ["source.list"]],
|
|
1024
|
+
[service.createSource !== void 0, ["source.create"]],
|
|
1025
|
+
[service.getSource !== void 0, ["source.get", "source.status"]],
|
|
1026
|
+
[service.getIngestionStatus !== void 0, ["ingestion.status"]],
|
|
1027
|
+
[service.listRecords !== void 0, ["record.list"]],
|
|
1028
|
+
[service.getRecord !== void 0, ["record.get"]],
|
|
1029
|
+
[service.createMarkdownRecord !== void 0, ["record.create_markdown"]],
|
|
1030
|
+
[service.patchRecordSection !== void 0, ["record.patch_section"]],
|
|
1031
|
+
[service.listRecordVersions !== void 0, ["record.versions"]],
|
|
1032
|
+
[service.listEvidence !== void 0, ["evidence.list"]],
|
|
1033
|
+
[service.getEvidence !== void 0, ["evidence.get"]],
|
|
1034
|
+
[service.listGraphNeighbors !== void 0, ["graph.neighbors"]],
|
|
1035
|
+
[service.listEvents !== void 0, ["event.list"]],
|
|
1036
|
+
[service.getContextProfile !== void 0, ["context.profile"]],
|
|
1037
|
+
[service.listAuditEvents !== void 0, ["audit.events"]]
|
|
1038
|
+
];
|
|
1039
|
+
return [...baseNames, ...optionalNames.flatMap(([enabled, names]) => enabled ? names : [])];
|
|
1040
|
+
}
|
|
1041
|
+
var init_toolAvailability = __esm({
|
|
1042
|
+
"../tools/dist/toolAvailability.js"() {
|
|
1043
|
+
"use strict";
|
|
1044
|
+
init_agentIdentityTools();
|
|
1045
|
+
init_contractTools();
|
|
1046
|
+
init_skillTools();
|
|
1047
|
+
}
|
|
1048
|
+
});
|
|
1049
|
+
|
|
808
1050
|
// ../tools/dist/toolLog.js
|
|
809
1051
|
function logToolCall(input) {
|
|
810
1052
|
input.onToolLog?.({
|
|
@@ -938,6 +1180,8 @@ function createToolHandlers(input, toolInput) {
|
|
|
938
1180
|
"decision.create": () => executeDecisionCreate(input, toolInput),
|
|
939
1181
|
"task.create": () => executeTaskCreate(input, toolInput),
|
|
940
1182
|
...skillToolHandlers(input, toolInput),
|
|
1183
|
+
...agentIdentityToolHandlers(input, toolInput),
|
|
1184
|
+
...contractToolHandlers(input),
|
|
941
1185
|
"source.list": () => executeSourceList(input),
|
|
942
1186
|
"source.create": () => executeSourceCreate(input, toolInput),
|
|
943
1187
|
"source.get": () => executeSourceRead(input, toolInput, "source.get"),
|
|
@@ -980,44 +1224,6 @@ function createToolHandlers(input, toolInput) {
|
|
|
980
1224
|
"audit.events": () => executeAuditEvents(input, toolInput)
|
|
981
1225
|
};
|
|
982
1226
|
}
|
|
983
|
-
function runtimeAvailableToolNames(service) {
|
|
984
|
-
const baseNames = [
|
|
985
|
-
"whoami",
|
|
986
|
-
"tools.list",
|
|
987
|
-
"tools.schema",
|
|
988
|
-
"tools.help",
|
|
989
|
-
"tools.search",
|
|
990
|
-
"brain.list",
|
|
991
|
-
"brain.use",
|
|
992
|
-
"scope.current",
|
|
993
|
-
"capture.text",
|
|
994
|
-
"capture.batch",
|
|
995
|
-
"search.query",
|
|
996
|
-
"context.assemble"
|
|
997
|
-
];
|
|
998
|
-
const optionalNames = [
|
|
999
|
-
[service.ingestFile !== void 0, ["capture.file"]],
|
|
1000
|
-
[service.createDecision !== void 0, ["decision.create"]],
|
|
1001
|
-
[service.createTask !== void 0, ["task.create"]],
|
|
1002
|
-
...skillToolAvailability(service),
|
|
1003
|
-
[service.listSources !== void 0, ["source.list"]],
|
|
1004
|
-
[service.createSource !== void 0, ["source.create"]],
|
|
1005
|
-
[service.getSource !== void 0, ["source.get", "source.status"]],
|
|
1006
|
-
[service.getIngestionStatus !== void 0, ["ingestion.status"]],
|
|
1007
|
-
[service.listRecords !== void 0, ["record.list"]],
|
|
1008
|
-
[service.getRecord !== void 0, ["record.get"]],
|
|
1009
|
-
[service.createMarkdownRecord !== void 0, ["record.create_markdown"]],
|
|
1010
|
-
[service.patchRecordSection !== void 0, ["record.patch_section"]],
|
|
1011
|
-
[service.listRecordVersions !== void 0, ["record.versions"]],
|
|
1012
|
-
[service.listEvidence !== void 0, ["evidence.list"]],
|
|
1013
|
-
[service.getEvidence !== void 0, ["evidence.get"]],
|
|
1014
|
-
[service.listGraphNeighbors !== void 0, ["graph.neighbors"]],
|
|
1015
|
-
[service.listEvents !== void 0, ["event.list"]],
|
|
1016
|
-
[service.getContextProfile !== void 0, ["context.profile"]],
|
|
1017
|
-
[service.listAuditEvents !== void 0, ["audit.events"]]
|
|
1018
|
-
];
|
|
1019
|
-
return [...baseNames, ...optionalNames.flatMap(([enabled, names]) => enabled ? names : [])];
|
|
1020
|
-
}
|
|
1021
1227
|
function missingService(toolName) {
|
|
1022
1228
|
return new Error(`Tool '${toolName}' requires a runtime service contract.`);
|
|
1023
1229
|
}
|
|
@@ -1144,7 +1350,10 @@ var init_executor = __esm({
|
|
|
1144
1350
|
init_discovery();
|
|
1145
1351
|
init_captureTools();
|
|
1146
1352
|
init_inputParsers();
|
|
1353
|
+
init_contractTools();
|
|
1147
1354
|
init_skillTools();
|
|
1355
|
+
init_agentIdentityTools();
|
|
1356
|
+
init_toolAvailability();
|
|
1148
1357
|
init_results();
|
|
1149
1358
|
init_toolLog();
|
|
1150
1359
|
}
|
|
@@ -1169,7 +1378,7 @@ function createCliCommandMetadata(filter) {
|
|
|
1169
1378
|
}
|
|
1170
1379
|
function availableTools2(filter) {
|
|
1171
1380
|
const availableNames = new Set(filter.toolNames ?? IMPLEMENTED_TOOL_NAMES);
|
|
1172
|
-
return listToolDefinitions().filter((tool) => availableNames.has(tool.name) && tool.transports.includes(filter.transport) && filter.capabilities
|
|
1381
|
+
return listToolDefinitions().filter((tool) => availableNames.has(tool.name) && tool.transports.includes(filter.transport) && isToolAuthorized(filter.capabilities, tool));
|
|
1173
1382
|
}
|
|
1174
1383
|
var init_generated = __esm({
|
|
1175
1384
|
"../tools/dist/generated.js"() {
|
|
@@ -1222,6 +1431,9 @@ function renderToolResult(result2) {
|
|
|
1222
1431
|
}
|
|
1223
1432
|
function classifyToolError(error) {
|
|
1224
1433
|
if (error instanceof Error) {
|
|
1434
|
+
if (error.message.startsWith("Sift contract required.")) {
|
|
1435
|
+
return "contract_required";
|
|
1436
|
+
}
|
|
1225
1437
|
if (isPermissionError2(error)) {
|
|
1226
1438
|
return "permission_denied";
|
|
1227
1439
|
}
|
|
@@ -1416,7 +1628,7 @@ async function dispatchRequest(method, params, adapter) {
|
|
|
1416
1628
|
protocolVersion: requested ?? MCP_PROTOCOL_VERSION,
|
|
1417
1629
|
capabilities: { tools: { listChanged: false } },
|
|
1418
1630
|
serverInfo: { name: "sift-local-mcp", version: "0.1.0" },
|
|
1419
|
-
instructions: "Use Sift tools to read and write the hosted canonical brain."
|
|
1631
|
+
instructions: "Call contract.get first and echo its contractVersion on every other Sift tool call. Use Sift tools to read and write the hosted canonical brain."
|
|
1420
1632
|
};
|
|
1421
1633
|
}
|
|
1422
1634
|
if (method === "ping")
|
|
@@ -1468,12 +1680,16 @@ var init_localMcpStdioServer = __esm({
|
|
|
1468
1680
|
var dist_exports = {};
|
|
1469
1681
|
__export(dist_exports, {
|
|
1470
1682
|
MCP_PROTOCOL_VERSION: () => MCP_PROTOCOL_VERSION,
|
|
1683
|
+
NO_CAPABILITY: () => NO_CAPABILITY,
|
|
1684
|
+
UNGATED_TOOL_NAMES: () => UNGATED_TOOL_NAMES,
|
|
1471
1685
|
createCliCommandMetadata: () => createCliCommandMetadata,
|
|
1472
1686
|
createHostedMcpEntrypoint: () => createHostedMcpEntrypoint,
|
|
1473
1687
|
createLocalMcpStdioServer: () => createLocalMcpStdioServer,
|
|
1474
1688
|
createMcpAdapter: () => createMcpAdapter,
|
|
1475
1689
|
createMcpToolSchemas: () => createMcpToolSchemas,
|
|
1476
1690
|
createRuntimeToolExecutor: () => createRuntimeToolExecutor,
|
|
1691
|
+
isGatedTool: () => isGatedTool,
|
|
1692
|
+
isToolAuthorized: () => isToolAuthorized,
|
|
1477
1693
|
listToolDefinitions: () => listToolDefinitions
|
|
1478
1694
|
});
|
|
1479
1695
|
var init_dist = __esm({
|
|
@@ -1484,6 +1700,7 @@ var init_dist = __esm({
|
|
|
1484
1700
|
init_hostedMcpEntrypoint();
|
|
1485
1701
|
init_localMcpStdioServer();
|
|
1486
1702
|
init_mcpAdapter();
|
|
1703
|
+
init_gating();
|
|
1487
1704
|
init_registry();
|
|
1488
1705
|
}
|
|
1489
1706
|
});
|
|
@@ -1720,6 +1937,9 @@ function fail(message) {
|
|
|
1720
1937
|
}
|
|
1721
1938
|
function classifyError(error) {
|
|
1722
1939
|
if (error instanceof Error) {
|
|
1940
|
+
if (error.message.startsWith("Sift contract required.")) {
|
|
1941
|
+
return "contract_required";
|
|
1942
|
+
}
|
|
1723
1943
|
if (isPermissionError(error)) {
|
|
1724
1944
|
return "permission_denied";
|
|
1725
1945
|
}
|
|
@@ -1768,6 +1988,41 @@ function addReceiptLine(lines, label, value) {
|
|
|
1768
1988
|
}
|
|
1769
1989
|
}
|
|
1770
1990
|
|
|
1991
|
+
// src/agentCommands.ts
|
|
1992
|
+
async function agentRegister(executor, assertedAgentName, rest, json) {
|
|
1993
|
+
if (executor === void 0) {
|
|
1994
|
+
return fail("No Sift API executor is configured for agent.register.");
|
|
1995
|
+
}
|
|
1996
|
+
const parsed = parseOptions(rest);
|
|
1997
|
+
const name = optionalOption(parsed, "name") ?? assertedAgentName;
|
|
1998
|
+
if (name === void 0 || name.trim().length === 0) {
|
|
1999
|
+
return fail("Missing agent name: pass --name or set SIFT_AGENT.");
|
|
2000
|
+
}
|
|
2001
|
+
const input = { name };
|
|
2002
|
+
const description = optionalOption(parsed, "description");
|
|
2003
|
+
if (description !== void 0) {
|
|
2004
|
+
input.description = description;
|
|
2005
|
+
}
|
|
2006
|
+
const kind = optionalOption(parsed, "kind");
|
|
2007
|
+
if (kind !== void 0) {
|
|
2008
|
+
input.kind = kind;
|
|
2009
|
+
}
|
|
2010
|
+
const result2 = await executor.execute("agent.register", input);
|
|
2011
|
+
return ok(json ? `${JSON.stringify(result2)}
|
|
2012
|
+
` : renderAgentRegisterResult(result2));
|
|
2013
|
+
}
|
|
2014
|
+
function renderAgentRegisterResult(result2) {
|
|
2015
|
+
if (typeof result2 !== "object" || result2 === null || !("agent" in result2)) {
|
|
2016
|
+
return `${JSON.stringify(result2)}
|
|
2017
|
+
`;
|
|
2018
|
+
}
|
|
2019
|
+
const { agent, created, reactivated } = result2;
|
|
2020
|
+
const verb = created === true ? "Registered" : reactivated === true ? "Reactivated" : "Already registered";
|
|
2021
|
+
const actsFor = agent.actsForDisplayName === void 0 ? "" : ` (acting for ${agent.actsForDisplayName})`;
|
|
2022
|
+
return `${verb} agent worker '${agent.name ?? "unknown"}'${actsFor}.
|
|
2023
|
+
`;
|
|
2024
|
+
}
|
|
2025
|
+
|
|
1771
2026
|
// src/auth/commandAdapter.ts
|
|
1772
2027
|
function isAuthCommand(commandKey) {
|
|
1773
2028
|
return commandKey === "login:" || commandKey === "auth:status" || commandKey === "logout:";
|
|
@@ -1791,6 +2046,7 @@ function authCommand(authCommands2, command, input) {
|
|
|
1791
2046
|
|
|
1792
2047
|
// src/capabilityGuard.ts
|
|
1793
2048
|
var commandCapabilities = {
|
|
2049
|
+
"contract:get": "record:read",
|
|
1794
2050
|
"whoami:": "record:read",
|
|
1795
2051
|
"brain:list": "record:read",
|
|
1796
2052
|
"brain:use": "record:read",
|
|
@@ -1838,6 +2094,35 @@ function validateCommandCapability(input) {
|
|
|
1838
2094
|
}
|
|
1839
2095
|
}
|
|
1840
2096
|
|
|
2097
|
+
// src/contractOption.ts
|
|
2098
|
+
function extractContractVersion(argv2) {
|
|
2099
|
+
const index = argv2.indexOf("--contract");
|
|
2100
|
+
if (index === -1) {
|
|
2101
|
+
return { argv: argv2 };
|
|
2102
|
+
}
|
|
2103
|
+
const value = argv2[index + 1];
|
|
2104
|
+
if (value === void 0 || value.trim().length === 0 || value.startsWith("--")) {
|
|
2105
|
+
return { argv: [...argv2.slice(0, index), ...argv2.slice(index + 1)] };
|
|
2106
|
+
}
|
|
2107
|
+
return {
|
|
2108
|
+
argv: [...argv2.slice(0, index), ...argv2.slice(index + 2)],
|
|
2109
|
+
contractVersion: value
|
|
2110
|
+
};
|
|
2111
|
+
}
|
|
2112
|
+
function applyContractOption(input) {
|
|
2113
|
+
const { argv: argv2, contractVersion } = extractContractVersion(input.argv);
|
|
2114
|
+
if (contractVersion === void 0 || input.executor === void 0) {
|
|
2115
|
+
return { ...input, argv: argv2 };
|
|
2116
|
+
}
|
|
2117
|
+
return { ...input, argv: argv2, executor: withContractVersion(input.executor, contractVersion) };
|
|
2118
|
+
}
|
|
2119
|
+
function withContractVersion(executor, contractVersion) {
|
|
2120
|
+
return {
|
|
2121
|
+
...executor,
|
|
2122
|
+
execute: (name, toolInput) => executor.execute(name, { ...toolInput, contractVersion })
|
|
2123
|
+
};
|
|
2124
|
+
}
|
|
2125
|
+
|
|
1841
2126
|
// src/doctor.ts
|
|
1842
2127
|
async function doctor(input) {
|
|
1843
2128
|
const checks = [
|
|
@@ -2008,6 +2293,7 @@ var knownTopLevelCommands = /* @__PURE__ */ new Set([
|
|
|
2008
2293
|
"brain",
|
|
2009
2294
|
"capture",
|
|
2010
2295
|
"context",
|
|
2296
|
+
"contract",
|
|
2011
2297
|
"decision",
|
|
2012
2298
|
"decide",
|
|
2013
2299
|
"doctor",
|
|
@@ -2360,7 +2646,8 @@ function createHostedApiExecutor(input) {
|
|
|
2360
2646
|
authorization: `Bearer ${input.token}`,
|
|
2361
2647
|
"content-type": "application/json",
|
|
2362
2648
|
"x-sift-brain-id": input.brainId,
|
|
2363
|
-
"x-sift-workspace-id": input.workspaceId
|
|
2649
|
+
"x-sift-workspace-id": input.workspaceId,
|
|
2650
|
+
...input.agentName === void 0 || input.agentName.trim().length === 0 ? {} : { "x-sift-agent-name": input.agentName.trim() }
|
|
2364
2651
|
},
|
|
2365
2652
|
body: JSON.stringify({ input: toolInput }, serializeJsonValue)
|
|
2366
2653
|
});
|
|
@@ -2403,7 +2690,8 @@ function errorMessage(parsed, status2) {
|
|
|
2403
2690
|
}
|
|
2404
2691
|
|
|
2405
2692
|
// src/index.ts
|
|
2406
|
-
async function runSiftCli(
|
|
2693
|
+
async function runSiftCli(rawInput) {
|
|
2694
|
+
const input = applyContractOption(rawInput);
|
|
2407
2695
|
const json = input.argv.includes("--json");
|
|
2408
2696
|
const args = input.argv.filter((arg) => arg !== "--json");
|
|
2409
2697
|
const [group, command, ...rest] = args;
|
|
@@ -2412,6 +2700,7 @@ async function runSiftCli(input) {
|
|
|
2412
2700
|
const commandKey = group === "login" ? "login:" : `${group ?? ""}:${command ?? ""}`;
|
|
2413
2701
|
const commandRest = group === "login" ? args.slice(1) : rest;
|
|
2414
2702
|
const handlers = {
|
|
2703
|
+
"contract:get": () => executeSimple2(rawInput.executor, "contract.get", {}, json),
|
|
2415
2704
|
"whoami:": () => executeSimple2(input.executor, "whoami", {}, json),
|
|
2416
2705
|
"brain:list": () => executeSimple2(input.executor, "brain.list", {}, json),
|
|
2417
2706
|
"brain:use": () => idTool({
|
|
@@ -2460,7 +2749,9 @@ async function runSiftCli(input) {
|
|
|
2460
2749
|
"audit:events": () => auditEvents(input.executor, rest, json),
|
|
2461
2750
|
"decision:create": () => createDecision(input.executor, rest, json),
|
|
2462
2751
|
"task:create": () => createTask(input.executor, rest, json),
|
|
2463
|
-
"
|
|
2752
|
+
"agent:register": () => agentRegister(input.executor, input.agentName, rest, json),
|
|
2753
|
+
"agent:status": () => executeSimple2(input.executor, "agent.status", {}, json),
|
|
2754
|
+
"mcp:serve": () => mcpServe(input.mcpServer, input.config, rawInput.executor, json),
|
|
2464
2755
|
"login:": () => authCommand(input.authCommands, "login", { rest: commandRest, json }),
|
|
2465
2756
|
"auth:status": () => authCommand(input.authCommands, "status", { json }),
|
|
2466
2757
|
"logout:": () => authCommand(input.authCommands, "logout", { json })
|
|
@@ -2515,8 +2806,7 @@ async function mcpServe(mcpServer, config2, executor, json) {
|
|
|
2515
2806
|
}
|
|
2516
2807
|
const result2 = await mcpServer.serve({ config: config2, executor, transport: "local_mcp" });
|
|
2517
2808
|
if (result2 === void 0) return ok("");
|
|
2518
|
-
return ok(
|
|
2519
|
-
` : `${JSON.stringify(result2)}
|
|
2809
|
+
return ok(`${JSON.stringify(result2)}
|
|
2520
2810
|
`);
|
|
2521
2811
|
}
|
|
2522
2812
|
function scopeCurrent(config2, json) {
|
|
@@ -3457,15 +3747,18 @@ var config = loadedAuth?.config ?? {
|
|
|
3457
3747
|
principalId: "",
|
|
3458
3748
|
capabilities: []
|
|
3459
3749
|
};
|
|
3750
|
+
var { argv, agentName } = extractAgentName(process.argv.slice(2), process.env.SIFT_AGENT);
|
|
3460
3751
|
var result = await runSiftCli({
|
|
3461
|
-
argv
|
|
3752
|
+
argv,
|
|
3462
3753
|
config,
|
|
3463
3754
|
readStdin,
|
|
3755
|
+
agentName,
|
|
3464
3756
|
executor: loadedAuth === void 0 ? void 0 : createHostedApiExecutor({
|
|
3465
3757
|
apiBaseUrl: loadedAuth.config.apiBaseUrl,
|
|
3466
3758
|
token: loadedAuth.token,
|
|
3467
3759
|
workspaceId: loadedAuth.config.workspaceId,
|
|
3468
|
-
brainId: loadedAuth.config.brainId
|
|
3760
|
+
brainId: loadedAuth.config.brainId,
|
|
3761
|
+
agentName
|
|
3469
3762
|
}),
|
|
3470
3763
|
authCommands,
|
|
3471
3764
|
mcpServer: {
|
|
@@ -3488,6 +3781,18 @@ var result = await runSiftCli({
|
|
|
3488
3781
|
process.stdout.write(result.stdout);
|
|
3489
3782
|
process.stderr.write(result.stderr);
|
|
3490
3783
|
process.exitCode = result.exitCode;
|
|
3784
|
+
function extractAgentName(args, envAgentName) {
|
|
3785
|
+
const flagIndex = args.indexOf("--as-agent");
|
|
3786
|
+
if (flagIndex !== -1 && args[flagIndex + 1] !== void 0) {
|
|
3787
|
+
const name = args[flagIndex + 1];
|
|
3788
|
+
return {
|
|
3789
|
+
argv: [...args.slice(0, flagIndex), ...args.slice(flagIndex + 2)],
|
|
3790
|
+
agentName: name
|
|
3791
|
+
};
|
|
3792
|
+
}
|
|
3793
|
+
const env = envAgentName?.trim();
|
|
3794
|
+
return { argv: args, agentName: env === void 0 || env.length === 0 ? void 0 : env };
|
|
3795
|
+
}
|
|
3491
3796
|
async function readStdin() {
|
|
3492
3797
|
const chunks = [];
|
|
3493
3798
|
for await (const chunk of process.stdin) {
|
package/package.json
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sift-wiki/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
|
+
"description": "Sift CLI release artifact.",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/goodnight000/sift-cli.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/goodnight000/sift-cli#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/goodnight000/sift-cli/issues"
|
|
14
|
+
},
|
|
6
15
|
"bin": {
|
|
7
16
|
"sift": "dist/bin/sift.js"
|
|
8
17
|
},
|
|
@@ -17,13 +26,6 @@
|
|
|
17
26
|
"access": "public"
|
|
18
27
|
},
|
|
19
28
|
"scripts": {
|
|
20
|
-
"
|
|
21
|
-
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
22
|
-
"pack:verify": "node ../../scripts/verify_cli_package.mjs"
|
|
23
|
-
},
|
|
24
|
-
"devDependencies": {
|
|
25
|
-
"@sift/api": "workspace:*",
|
|
26
|
-
"@sift/tools": "workspace:*",
|
|
27
|
-
"tsup": "8.5.1"
|
|
29
|
+
"verify": "node scripts/verify-release.mjs"
|
|
28
30
|
}
|
|
29
31
|
}
|