@zeroroot-ai/zerocool-claude 0.5.2 → 0.6.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/.claude-plugin/plugin.json +2 -2
- package/.mcp.json +1 -1
- package/dist/hook-run.js +2 -0
- package/dist/hook.js +2 -0
- package/dist/index.d.ts +1 -7
- package/dist/index.js +8 -8
- package/dist/state.d.ts +13 -10
- package/dist/state.js +6 -13
- package/hooks/hooks.json +4 -4
- package/hooks/zerocool-claude-hook.mjs +32 -0
- package/package.json +5 -9
- package/dist/ambient.d.ts +0 -7
- package/dist/ambient.js +0 -18
- package/dist/build.d.ts +0 -32
- package/dist/build.js +0 -218
- package/dist/claude-run.d.ts +0 -46
- package/dist/claude-run.js +0 -118
- package/dist/cli.d.ts +0 -88
- package/dist/cli.js +0 -186
- package/dist/config.d.ts +0 -44
- package/dist/config.js +0 -53
- package/dist/mode.d.ts +0 -32
- package/dist/mode.js +0 -21
- package/dist/sandbox-run.d.ts +0 -26
- package/dist/sandbox-run.js +0 -42
- package/dist/sandbox.d.ts +0 -2
- package/dist/sandbox.js +0 -30
- package/dist/server.d.ts +0 -2
- package/dist/server.js +0 -34
- package/dist/session.d.ts +0 -34
- package/dist/session.js +0 -142
- package/dist/tls.d.ts +0 -1
- package/dist/tls.js +0 -19
- package/dist/tools/componentize.d.ts +0 -18
- package/dist/tools/componentize.js +0 -80
- package/dist/tools/delegate.d.ts +0 -4
- package/dist/tools/delegate.js +0 -108
- package/dist/tools/findings.d.ts +0 -24
- package/dist/tools/findings.js +0 -104
- package/dist/tools/gibson-tools.d.ts +0 -20
- package/dist/tools/gibson-tools.js +0 -89
- package/dist/tools/memory.d.ts +0 -14
- package/dist/tools/memory.js +0 -96
- package/dist/tools/result.d.ts +0 -5
- package/dist/tools/result.js +0 -8
- package/dist/tools/status.d.ts +0 -5
- package/dist/tools/status.js +0 -21
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { callGibsonTool, listGibsonPlugins, listGibsonTools, queryGibsonPlugin, } from "@zeroroot-ai/sdk";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
import { failure, text } from "./result.js";
|
|
4
|
-
/**
|
|
5
|
-
* Gibson tools and plugins as MCP tools (zerocool-plugins#9).
|
|
6
|
-
*
|
|
7
|
-
* Discovered tools register individually, one MCP tool per Gibson tool, named
|
|
8
|
-
* `gibson_<tool>`, so the model sees each with its own description. The
|
|
9
|
-
* catalog carries no JSON Schema, only a proto message type name, so a wrapper
|
|
10
|
-
* takes one free-form `input` object and names the expected type. A generic
|
|
11
|
-
* `gibson_call_tool` is always present: discovery is `Unimplemented` on some
|
|
12
|
-
* daemons (gibson#1186), and the operator may know a tool by name.
|
|
13
|
-
*/
|
|
14
|
-
export function toolKey(name) {
|
|
15
|
-
return `gibson_${name.replace(/[^a-zA-Z0-9_]/g, "_")}`;
|
|
16
|
-
}
|
|
17
|
-
function formatToolResult(name, result) {
|
|
18
|
-
if (result.error) {
|
|
19
|
-
return failure(`${name} failed`, `Gibson tool ${name} failed [${result.error.code}]: ${result.error.message}${result.error.retryable ? " (retryable)" : ""}`);
|
|
20
|
-
}
|
|
21
|
-
const body = typeof result.output === "string" ? result.output : JSON.stringify(result.output, null, 2);
|
|
22
|
-
return text(name, body ?? "(no output)");
|
|
23
|
-
}
|
|
24
|
-
export function registerDiscoveredTool(server, session, t) {
|
|
25
|
-
const schemaNote = t.inputMessageType ? ` Input must match the Gibson message type ${t.inputMessageType}.` : "";
|
|
26
|
-
server.registerTool(toolKey(t.name), {
|
|
27
|
-
description: `${t.description || `Gibson tool "${t.name}"`}${schemaNote} Runs through the Gibson harness (authorized and metered).`,
|
|
28
|
-
inputSchema: {
|
|
29
|
-
input: z.record(z.string(), z.any()).describe(`Input object for the ${t.name} tool.`),
|
|
30
|
-
timeout_ms: z.number().optional().describe("Per-call timeout in milliseconds."),
|
|
31
|
-
},
|
|
32
|
-
}, async (args) => formatToolResult(t.name, await callGibsonTool(session.clients.component, {
|
|
33
|
-
name: t.name,
|
|
34
|
-
input: args.input,
|
|
35
|
-
...(args.timeout_ms ? { timeoutMs: args.timeout_ms } : {}),
|
|
36
|
-
})));
|
|
37
|
-
}
|
|
38
|
-
/** Register the generic tools, then one tool per discovered Gibson tool. */
|
|
39
|
-
export async function registerGibsonTools(server, session) {
|
|
40
|
-
const component = session.clients.component;
|
|
41
|
-
server.registerTool("gibson_call_tool", {
|
|
42
|
-
description: "Invoke a Gibson tool by name through the harness. Use this when you know a tool's name " +
|
|
43
|
-
"but it is not in your tool list. Gibson tool discovery is not available on every daemon.",
|
|
44
|
-
inputSchema: {
|
|
45
|
-
name: z.string().describe("Registered Gibson tool name."),
|
|
46
|
-
input: z.record(z.string(), z.any()).describe("Input object matching the tool's input schema."),
|
|
47
|
-
timeout_ms: z.number().optional().describe("Per-call timeout in milliseconds."),
|
|
48
|
-
},
|
|
49
|
-
}, async (args) => formatToolResult(args.name, await callGibsonTool(component, { name: args.name, input: args.input, ...(args.timeout_ms ? { timeoutMs: args.timeout_ms } : {}) })));
|
|
50
|
-
server.registerTool("gibson_list_tools", {
|
|
51
|
-
description: "List the Gibson tools and plugins available to this tenant, with the input message type each tool expects.",
|
|
52
|
-
inputSchema: {},
|
|
53
|
-
}, async () => {
|
|
54
|
-
const [discovery, plugins] = await Promise.all([listGibsonTools(component), listGibsonPlugins(component).catch(() => [])]);
|
|
55
|
-
const lines = [];
|
|
56
|
-
if (discovery.unavailable)
|
|
57
|
-
lines.push(`Tool discovery is unavailable: ${discovery.unavailable}.`);
|
|
58
|
-
else if (discovery.tools.length === 0)
|
|
59
|
-
lines.push("No Gibson tools are registered for this tenant.");
|
|
60
|
-
else {
|
|
61
|
-
lines.push("Gibson tools:");
|
|
62
|
-
for (const t of discovery.tools) {
|
|
63
|
-
lines.push(`- ${t.name} (${t.version}): ${t.description || "no description"}`);
|
|
64
|
-
if (t.inputMessageType)
|
|
65
|
-
lines.push(` input: ${t.inputMessageType}`);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
if (plugins.length > 0) {
|
|
69
|
-
lines.push("", "Gibson plugins:");
|
|
70
|
-
for (const p of plugins)
|
|
71
|
-
lines.push(`- ${p.name} (${p.version}): ${p.description || "no description"}`);
|
|
72
|
-
}
|
|
73
|
-
return text("", lines.join("\n"));
|
|
74
|
-
});
|
|
75
|
-
server.registerTool("gibson_query_plugin", {
|
|
76
|
-
description: "Call a method on a tenant Gibson plugin (a connector or an integration) through the harness.",
|
|
77
|
-
inputSchema: {
|
|
78
|
-
plugin: z.string().describe("Plugin name."),
|
|
79
|
-
method: z.string().describe("Method name."),
|
|
80
|
-
params: z.record(z.string(), z.any()).optional().describe("Method parameters."),
|
|
81
|
-
},
|
|
82
|
-
}, async (args) => formatToolResult(`${args.plugin}.${args.method}`, await queryGibsonPlugin(component, { plugin: args.plugin, method: args.method, params: args.params ?? {} })));
|
|
83
|
-
const discovery = await listGibsonTools(component);
|
|
84
|
-
if (discovery.unavailable)
|
|
85
|
-
return { discovered: 0, note: discovery.unavailable };
|
|
86
|
-
for (const t of discovery.tools)
|
|
87
|
-
registerDiscoveredTool(server, session, t);
|
|
88
|
-
return { discovered: discovery.tools.length };
|
|
89
|
-
}
|
package/dist/tools/memory.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
import type { Gibson } from "../session.js";
|
|
3
|
-
/**
|
|
4
|
-
* Memory and knowledge (gibson#1593, decisions 9 and 10).
|
|
5
|
-
*
|
|
6
|
-
* `remember` is `Observe(MemoryObservation)`: the memory lands in the tenant
|
|
7
|
-
* World as a Timeline event and the projector writes the graph node. It exists
|
|
8
|
-
* only in the live posture, because the World is written under a mission.
|
|
9
|
-
*
|
|
10
|
-
* `recall` reads the graph. In the live posture it reads as the task, in the
|
|
11
|
-
* component posture as the component. The model decides when a lookup is worth
|
|
12
|
-
* a round trip, and the query it writes beats anything derived from the prompt.
|
|
13
|
-
*/
|
|
14
|
-
export declare function registerMemoryTools(server: McpServer, g: Gibson): void;
|
package/dist/tools/memory.js
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { formatKnowledgeForPrompt, isSeamUnavailable, remember, WorldEntityKind } from "@zeroroot-ai/sdk";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
import { failure, text } from "./result.js";
|
|
4
|
-
/**
|
|
5
|
-
* Memory and knowledge (gibson#1593, decisions 9 and 10).
|
|
6
|
-
*
|
|
7
|
-
* `remember` is `Observe(MemoryObservation)`: the memory lands in the tenant
|
|
8
|
-
* World as a Timeline event and the projector writes the graph node. It exists
|
|
9
|
-
* only in the live posture, because the World is written under a mission.
|
|
10
|
-
*
|
|
11
|
-
* `recall` reads the graph. In the live posture it reads as the task, in the
|
|
12
|
-
* component posture as the component. The model decides when a lookup is worth
|
|
13
|
-
* a round trip, and the query it writes beats anything derived from the prompt.
|
|
14
|
-
*/
|
|
15
|
-
export function registerMemoryTools(server, g) {
|
|
16
|
-
if (g.knowledge) {
|
|
17
|
-
const knowledge = g.knowledge;
|
|
18
|
-
server.registerTool("recall", {
|
|
19
|
-
description: "Search this tenant's Gibson knowledge graph for memories, prior findings, targets and " +
|
|
20
|
-
"security facts recorded by earlier sessions and runs. Use it before you start on an " +
|
|
21
|
-
"unfamiliar area, or to check whether something was already recorded.",
|
|
22
|
-
inputSchema: {
|
|
23
|
-
query: z.string().describe("What to look for, in natural language."),
|
|
24
|
-
limit: z.number().int().min(1).max(50).optional().describe("Maximum hits. Defaults to 10."),
|
|
25
|
-
node_types: z
|
|
26
|
-
.array(z.string())
|
|
27
|
-
.optional()
|
|
28
|
-
.describe('Restrict to node types, e.g. ["Observation"] for memories or ["Finding"].'),
|
|
29
|
-
},
|
|
30
|
-
}, async (args) => {
|
|
31
|
-
let hits;
|
|
32
|
-
try {
|
|
33
|
-
hits = await knowledge.query({
|
|
34
|
-
text: args.query,
|
|
35
|
-
topK: args.limit ?? 10,
|
|
36
|
-
...(args.node_types ? { nodeTypes: args.node_types } : {}),
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
catch (e) {
|
|
40
|
-
if (isSeamUnavailable(e)) {
|
|
41
|
-
return text("recall unavailable", "The Gibson knowledge graph is not available on this daemon (gibson#1186). Continue without prior context.");
|
|
42
|
-
}
|
|
43
|
-
return failure("recall failed", e.message);
|
|
44
|
-
}
|
|
45
|
-
if (hits.length === 0)
|
|
46
|
-
return text("no matches", `Nothing in the tenant graph matches "${args.query}".`);
|
|
47
|
-
return text(`${hits.length} match${hits.length === 1 ? "" : "es"}`, formatKnowledgeForPrompt(hits));
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
if (g.live) {
|
|
51
|
-
const harness = g.live.harness;
|
|
52
|
-
server.registerTool("remember", {
|
|
53
|
-
description: "Keep a fact for later sessions, in this tenant's Gibson knowledge graph. Use it for a " +
|
|
54
|
-
"convention, a decision, a layout fact or a gotcha you would want back next time. Not for " +
|
|
55
|
-
"progress notes. A security finding goes to submit_finding instead.",
|
|
56
|
-
inputSchema: {
|
|
57
|
-
text: z.string().describe("The fact, in one or two sentences."),
|
|
58
|
-
kind: z.string().optional().describe('A short category: "convention", "decision", "layout", "gotcha".'),
|
|
59
|
-
tags: z.array(z.string()).optional().describe("Lower-case labels that help recall."),
|
|
60
|
-
source_ref: z.string().optional().describe("Where it came from: a path, a URL, or a work id."),
|
|
61
|
-
},
|
|
62
|
-
}, async (args) => {
|
|
63
|
-
try {
|
|
64
|
-
await remember(harness, { text: args.text, kind: args.kind, tags: args.tags, sourceRef: args.source_ref });
|
|
65
|
-
}
|
|
66
|
-
catch (e) {
|
|
67
|
-
return failure("remember failed", e.message);
|
|
68
|
-
}
|
|
69
|
-
return text("remembered", `Recorded in the tenant graph under mission ${g.live.missionId}.`);
|
|
70
|
-
});
|
|
71
|
-
server.registerTool("world_view", {
|
|
72
|
-
description: "Read this mission's slice of the tenant World: the hosts, domains, credentials, accounts " +
|
|
73
|
-
"and findings the platform knows about the target. Pass handles from a previous call in " +
|
|
74
|
-
"focus to zoom into entities.",
|
|
75
|
-
inputSchema: {
|
|
76
|
-
focus: z.array(z.string()).optional().describe("Entity handles from an earlier world_view call."),
|
|
77
|
-
},
|
|
78
|
-
}, async (args) => {
|
|
79
|
-
try {
|
|
80
|
-
const res = await harness.client.worldView({ context: harness.context, focus: args.focus ?? [] });
|
|
81
|
-
if (res.error)
|
|
82
|
-
return failure("world_view refused", res.error.message);
|
|
83
|
-
if (res.entities.length === 0)
|
|
84
|
-
return text("empty slice", "The World holds nothing for this target yet.");
|
|
85
|
-
const lines = res.entities.map((e) => {
|
|
86
|
-
const attrs = Object.entries(e.attributes).map(([k, v]) => `${k}=${v}`).join(", ");
|
|
87
|
-
return `- [${e.handle}] ${WorldEntityKind[e.kind] ?? e.kind} ${e.label}${attrs ? ` (${attrs})` : ""}`;
|
|
88
|
-
});
|
|
89
|
-
return text(`${res.entities.length} entit${res.entities.length === 1 ? "y" : "ies"}${res.truncated ? " (truncated)" : ""}`, lines.join("\n"));
|
|
90
|
-
}
|
|
91
|
-
catch (e) {
|
|
92
|
-
return failure("world_view failed", e.message);
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
}
|
package/dist/tools/result.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
-
/** One text block. MCP has no title/metadata split, so the title leads the text. */
|
|
3
|
-
export declare function text(title: string, body: string, isError?: boolean): CallToolResult;
|
|
4
|
-
/** Error text for a failure the model can act on. */
|
|
5
|
-
export declare function failure(title: string, body: string): CallToolResult;
|
package/dist/tools/result.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/** One text block. MCP has no title/metadata split, so the title leads the text. */
|
|
2
|
-
export function text(title, body, isError = false) {
|
|
3
|
-
return { content: [{ type: "text", text: title ? `${title}\n\n${body}` : body }], ...(isError ? { isError } : {}) };
|
|
4
|
-
}
|
|
5
|
-
/** Error text for a failure the model can act on. */
|
|
6
|
-
export function failure(title, body) {
|
|
7
|
-
return text(title, body, true);
|
|
8
|
-
}
|
package/dist/tools/status.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
import type { Gibson } from "../session.js";
|
|
3
|
-
/** One tool that says what posture this session runs in and why. */
|
|
4
|
-
export declare function registerStatusTool(server: McpServer, current: () => Gibson): void;
|
|
5
|
-
export declare function describeGibson(g: Gibson): string;
|
package/dist/tools/status.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { text } from "./result.js";
|
|
2
|
-
/** One tool that says what posture this session runs in and why. */
|
|
3
|
-
export function registerStatusTool(server, current) {
|
|
4
|
-
server.registerTool("gibson_status", { description: "Show how this session is connected to Gibson: standalone, component, or a live mission, and what is missing if anything.", inputSchema: {} }, async () => text("", describeGibson(current())));
|
|
5
|
-
}
|
|
6
|
-
export function describeGibson(g) {
|
|
7
|
-
const lines = [`posture: ${g.mode}`, `agent: ${g.agentName}`];
|
|
8
|
-
if (g.session)
|
|
9
|
-
lines.push(`component_scope: ${g.session.componentScope}`, `instance: ${g.session.instance.current()}`);
|
|
10
|
-
if (g.live) {
|
|
11
|
-
const exp = g.live.harness.expiresAt();
|
|
12
|
-
lines.push(`mission: ${g.live.missionId}`, `work: ${g.live.workId}`, `grant expires: ${exp ? new Date(exp).toISOString() : "unknown"}`);
|
|
13
|
-
}
|
|
14
|
-
if (g.settings.platformURL)
|
|
15
|
-
lines.push(`platform: ${g.settings.platformURL}`);
|
|
16
|
-
if (g.settings.targetId)
|
|
17
|
-
lines.push(`target: ${g.settings.targetId}`);
|
|
18
|
-
if (g.reason)
|
|
19
|
-
lines.push(`note: ${g.reason}`);
|
|
20
|
-
return lines.join("\n");
|
|
21
|
-
}
|