@honeybee-ai/incubator 1.1.0
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 +586 -0
- package/dashboard/dist/assets/index-DFb8p7xI.js +9 -0
- package/dashboard/dist/assets/index-RKiEoHEo.css +1 -0
- package/dashboard/dist/index.html +13 -0
- package/dist/agent/acp/claim-manager.d.ts +24 -0
- package/dist/agent/acp/claim-manager.js +64 -0
- package/dist/agent/acp/claim-manager.js.map +1 -0
- package/dist/agent/acp/direct-runtime.d.ts +90 -0
- package/dist/agent/acp/direct-runtime.js +364 -0
- package/dist/agent/acp/direct-runtime.js.map +1 -0
- package/dist/agent/acp/event-client.d.ts +20 -0
- package/dist/agent/acp/event-client.js +60 -0
- package/dist/agent/acp/event-client.js.map +1 -0
- package/dist/agent/acp/event-matcher.d.ts +13 -0
- package/dist/agent/acp/event-matcher.js +31 -0
- package/dist/agent/acp/event-matcher.js.map +1 -0
- package/dist/agent/acp/progress.d.ts +23 -0
- package/dist/agent/acp/progress.js +54 -0
- package/dist/agent/acp/progress.js.map +1 -0
- package/dist/agent/acp/runtime.d.ts +156 -0
- package/dist/agent/acp/runtime.js +337 -0
- package/dist/agent/acp/runtime.js.map +1 -0
- package/dist/agent/acp/ws-event-client.d.ts +64 -0
- package/dist/agent/acp/ws-event-client.js +263 -0
- package/dist/agent/acp/ws-event-client.js.map +1 -0
- package/dist/agent/agent.d.ts +60 -0
- package/dist/agent/agent.js +121 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/cli.d.ts +2 -0
- package/dist/agent/cli.js +311 -0
- package/dist/agent/cli.js.map +1 -0
- package/dist/agent/mcp-client.d.ts +37 -0
- package/dist/agent/mcp-client.js +92 -0
- package/dist/agent/mcp-client.js.map +1 -0
- package/dist/agent/mock-runner.d.ts +14 -0
- package/dist/agent/mock-runner.js +159 -0
- package/dist/agent/mock-runner.js.map +1 -0
- package/dist/agent/native-client.d.ts +18 -0
- package/dist/agent/native-client.js +42 -0
- package/dist/agent/native-client.js.map +1 -0
- package/dist/agent/prompt.d.ts +45 -0
- package/dist/agent/prompt.js +115 -0
- package/dist/agent/prompt.js.map +1 -0
- package/dist/agent/providers.d.ts +25 -0
- package/dist/agent/providers.js +696 -0
- package/dist/agent/providers.js.map +1 -0
- package/dist/agent/runner.d.ts +15 -0
- package/dist/agent/runner.js +625 -0
- package/dist/agent/runner.js.map +1 -0
- package/dist/agent/tool-client.d.ts +12 -0
- package/dist/agent/tool-client.js +2 -0
- package/dist/agent/tool-client.js.map +1 -0
- package/dist/agent/types.d.ts +116 -0
- package/dist/agent/types.js +2 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/agent-pool.d.ts +44 -0
- package/dist/agent-pool.js +228 -0
- package/dist/agent-pool.js.map +1 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +7 -0
- package/dist/bin.js.map +1 -0
- package/dist/bus.d.ts +24 -0
- package/dist/bus.js +79 -0
- package/dist/bus.js.map +1 -0
- package/dist/dances.d.ts +73 -0
- package/dist/dances.js +122 -0
- package/dist/dances.js.map +1 -0
- package/dist/guard.d.ts +52 -0
- package/dist/guard.js +210 -0
- package/dist/guard.js.map +1 -0
- package/dist/heartbeat.d.ts +41 -0
- package/dist/heartbeat.js +104 -0
- package/dist/heartbeat.js.map +1 -0
- package/dist/honeycomb.d.ts +63 -0
- package/dist/honeycomb.js +222 -0
- package/dist/honeycomb.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +601 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/config.d.ts +15 -0
- package/dist/integrations/config.js +62 -0
- package/dist/integrations/config.js.map +1 -0
- package/dist/integrations/index.d.ts +4 -0
- package/dist/integrations/index.js +4 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/integrations/loader.d.ts +8 -0
- package/dist/integrations/loader.js +27 -0
- package/dist/integrations/loader.js.map +1 -0
- package/dist/integrations/manager.d.ts +29 -0
- package/dist/integrations/manager.js +108 -0
- package/dist/integrations/manager.js.map +1 -0
- package/dist/log.d.ts +25 -0
- package/dist/log.js +67 -0
- package/dist/log.js.map +1 -0
- package/dist/namespaces.d.ts +28 -0
- package/dist/namespaces.js +100 -0
- package/dist/namespaces.js.map +1 -0
- package/dist/orchestrator.d.ts +119 -0
- package/dist/orchestrator.js +463 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/persistence.d.ts +7 -0
- package/dist/persistence.js +62 -0
- package/dist/persistence.js.map +1 -0
- package/dist/plugins/index.d.ts +2 -0
- package/dist/plugins/index.js +3 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/loader.d.ts +12 -0
- package/dist/plugins/loader.js +122 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/plugins/manager.d.ts +76 -0
- package/dist/plugins/manager.js +238 -0
- package/dist/plugins/manager.js.map +1 -0
- package/dist/propolis/guard.d.ts +23 -0
- package/dist/propolis/guard.js +49 -0
- package/dist/propolis/guard.js.map +1 -0
- package/dist/propolis/tools/types.d.ts +9 -0
- package/dist/propolis/tools/types.js +9 -0
- package/dist/propolis/tools/types.js.map +1 -0
- package/dist/rest.d.ts +4 -0
- package/dist/rest.js +962 -0
- package/dist/rest.js.map +1 -0
- package/dist/run-watcher.d.ts +20 -0
- package/dist/run-watcher.js +74 -0
- package/dist/run-watcher.js.map +1 -0
- package/dist/server.d.ts +17 -0
- package/dist/server.js +412 -0
- package/dist/server.js.map +1 -0
- package/dist/stores/backend.d.ts +15 -0
- package/dist/stores/backend.js +28 -0
- package/dist/stores/backend.js.map +1 -0
- package/dist/stores/claims.d.ts +14 -0
- package/dist/stores/claims.js +77 -0
- package/dist/stores/claims.js.map +1 -0
- package/dist/stores/conflicts.d.ts +10 -0
- package/dist/stores/conflicts.js +39 -0
- package/dist/stores/conflicts.js.map +1 -0
- package/dist/stores/control.d.ts +37 -0
- package/dist/stores/control.js +105 -0
- package/dist/stores/control.js.map +1 -0
- package/dist/stores/discoveries.d.ts +11 -0
- package/dist/stores/discoveries.js +45 -0
- package/dist/stores/discoveries.js.map +1 -0
- package/dist/stores/events.d.ts +14 -0
- package/dist/stores/events.js +42 -0
- package/dist/stores/events.js.map +1 -0
- package/dist/stores/help.d.ts +11 -0
- package/dist/stores/help.js +46 -0
- package/dist/stores/help.js.map +1 -0
- package/dist/stores/interfaces.d.ts +125 -0
- package/dist/stores/interfaces.js +2 -0
- package/dist/stores/interfaces.js.map +1 -0
- package/dist/stores/messages.d.ts +8 -0
- package/dist/stores/messages.js +29 -0
- package/dist/stores/messages.js.map +1 -0
- package/dist/stores/progress.d.ts +8 -0
- package/dist/stores/progress.js +21 -0
- package/dist/stores/progress.js.map +1 -0
- package/dist/stores/proposals.d.ts +11 -0
- package/dist/stores/proposals.js +46 -0
- package/dist/stores/proposals.js.map +1 -0
- package/dist/stores/redis/claims.d.ts +16 -0
- package/dist/stores/redis/claims.js +126 -0
- package/dist/stores/redis/claims.js.map +1 -0
- package/dist/stores/redis/db.d.ts +39 -0
- package/dist/stores/redis/db.js +34 -0
- package/dist/stores/redis/db.js.map +1 -0
- package/dist/stores/redis/discoveries.d.ts +13 -0
- package/dist/stores/redis/discoveries.js +54 -0
- package/dist/stores/redis/discoveries.js.map +1 -0
- package/dist/stores/redis/events.d.ts +17 -0
- package/dist/stores/redis/events.js +57 -0
- package/dist/stores/redis/events.js.map +1 -0
- package/dist/stores/redis/index.d.ts +3 -0
- package/dist/stores/redis/index.js +31 -0
- package/dist/stores/redis/index.js.map +1 -0
- package/dist/stores/redis/state.d.ts +14 -0
- package/dist/stores/redis/state.js +83 -0
- package/dist/stores/redis/state.js.map +1 -0
- package/dist/stores/reinforcements.d.ts +11 -0
- package/dist/stores/reinforcements.js +42 -0
- package/dist/stores/reinforcements.js.map +1 -0
- package/dist/stores/roles.d.ts +9 -0
- package/dist/stores/roles.js +22 -0
- package/dist/stores/roles.js.map +1 -0
- package/dist/stores/runs.d.ts +15 -0
- package/dist/stores/runs.js +50 -0
- package/dist/stores/runs.js.map +1 -0
- package/dist/stores/sqlite/claims.d.ts +17 -0
- package/dist/stores/sqlite/claims.js +121 -0
- package/dist/stores/sqlite/claims.js.map +1 -0
- package/dist/stores/sqlite/db.d.ts +16 -0
- package/dist/stores/sqlite/db.js +77 -0
- package/dist/stores/sqlite/db.js.map +1 -0
- package/dist/stores/sqlite/discoveries.d.ts +14 -0
- package/dist/stores/sqlite/discoveries.js +66 -0
- package/dist/stores/sqlite/discoveries.js.map +1 -0
- package/dist/stores/sqlite/events.d.ts +16 -0
- package/dist/stores/sqlite/events.js +75 -0
- package/dist/stores/sqlite/events.js.map +1 -0
- package/dist/stores/sqlite/index.d.ts +2 -0
- package/dist/stores/sqlite/index.js +33 -0
- package/dist/stores/sqlite/index.js.map +1 -0
- package/dist/stores/sqlite/state.d.ts +15 -0
- package/dist/stores/sqlite/state.js +99 -0
- package/dist/stores/sqlite/state.js.map +1 -0
- package/dist/stores/state.d.ts +11 -0
- package/dist/stores/state.js +67 -0
- package/dist/stores/state.js.map +1 -0
- package/dist/transports/broker.d.ts +20 -0
- package/dist/transports/broker.js +102 -0
- package/dist/transports/broker.js.map +1 -0
- package/dist/transports/index.d.ts +3 -0
- package/dist/transports/index.js +3 -0
- package/dist/transports/index.js.map +1 -0
- package/dist/transports/ipc.d.ts +26 -0
- package/dist/transports/ipc.js +93 -0
- package/dist/transports/ipc.js.map +1 -0
- package/dist/transports/types.d.ts +39 -0
- package/dist/transports/types.js +8 -0
- package/dist/transports/types.js.map +1 -0
- package/dist/types.d.ts +45 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +36 -0
- package/dist/utils.js.map +1 -0
- package/dist/waggle/client.d.ts +16 -0
- package/dist/waggle/client.js +28 -0
- package/dist/waggle/client.js.map +1 -0
- package/dist/waggle/compound.d.ts +22 -0
- package/dist/waggle/compound.js +194 -0
- package/dist/waggle/compound.js.map +1 -0
- package/dist/waggle/index.d.ts +25 -0
- package/dist/waggle/index.js +77 -0
- package/dist/waggle/index.js.map +1 -0
- package/dist/waggle/types.d.ts +54 -0
- package/dist/waggle/types.js +2 -0
- package/dist/waggle/types.js.map +1 -0
- package/dist/webhooks.d.ts +26 -0
- package/dist/webhooks.js +79 -0
- package/dist/webhooks.js.map +1 -0
- package/dist/ws.d.ts +33 -0
- package/dist/ws.js +195 -0
- package/dist/ws.js.map +1 -0
- package/package.json +122 -0
package/dist/dances.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dance file loader — loads JS modules whose exports become virtual tools.
|
|
3
|
+
* Runs entirely on the incubator (server-side).
|
|
4
|
+
*/
|
|
5
|
+
import type { ToolDef } from './agent/types.js';
|
|
6
|
+
export interface DanceToolDef {
|
|
7
|
+
description: string;
|
|
8
|
+
params: Record<string, {
|
|
9
|
+
type: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
}>;
|
|
12
|
+
handler: (ctx: DanceContext) => Promise<DanceResult>;
|
|
13
|
+
}
|
|
14
|
+
export interface DanceContext {
|
|
15
|
+
args: Record<string, unknown>;
|
|
16
|
+
state: Record<string, string>;
|
|
17
|
+
agent: {
|
|
18
|
+
role: string;
|
|
19
|
+
agentId: string;
|
|
20
|
+
};
|
|
21
|
+
acp: DanceAcpHelper;
|
|
22
|
+
}
|
|
23
|
+
export interface DanceAcpHelper {
|
|
24
|
+
publish(type: string, data?: unknown): Promise<void>;
|
|
25
|
+
claim(resource: string): Promise<string>;
|
|
26
|
+
release(resource: string): Promise<void>;
|
|
27
|
+
setState(key: string, value: string): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
export type DanceResult = {
|
|
30
|
+
result: unknown;
|
|
31
|
+
wait?: unknown;
|
|
32
|
+
} | {
|
|
33
|
+
error: string;
|
|
34
|
+
};
|
|
35
|
+
export interface InjectFn {
|
|
36
|
+
(ctx: {
|
|
37
|
+
state: Record<string, string>;
|
|
38
|
+
agent: {
|
|
39
|
+
role: string;
|
|
40
|
+
agentId: string;
|
|
41
|
+
};
|
|
42
|
+
}): string;
|
|
43
|
+
}
|
|
44
|
+
export interface DanceModule {
|
|
45
|
+
inject?: InjectFn;
|
|
46
|
+
tools: Map<string, DanceToolDef>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Load a dance file via dynamic import. Validates exports.
|
|
50
|
+
* Returns a DanceModule with optional inject and tool map.
|
|
51
|
+
*/
|
|
52
|
+
export declare function loadDances(filePath: string): Promise<DanceModule>;
|
|
53
|
+
/**
|
|
54
|
+
* Convert dance tool definitions to LLM ToolDef format.
|
|
55
|
+
*/
|
|
56
|
+
export declare function danceToolDefs(mod: DanceModule): ToolDef[];
|
|
57
|
+
/**
|
|
58
|
+
* Build an ACP helper that wraps incubator stores for use in dance handlers.
|
|
59
|
+
*/
|
|
60
|
+
export declare function buildAcpHelper(stores: {
|
|
61
|
+
publishEvent: (ns: string, type: string, data?: unknown, agentId?: string) => Promise<void>;
|
|
62
|
+
claimResource: (ns: string, resource: string, agentId: string, ttl?: number) => Promise<string>;
|
|
63
|
+
releaseResource: (ns: string, claimId: string) => Promise<void>;
|
|
64
|
+
setState: (ns: string, key: string, value: string) => Promise<void>;
|
|
65
|
+
}, namespace: string, agentId: string): DanceAcpHelper;
|
|
66
|
+
/**
|
|
67
|
+
* Execute a dance tool handler with full context.
|
|
68
|
+
*/
|
|
69
|
+
export declare function callDanceTool(mod: DanceModule, toolName: string, args: Record<string, unknown>, agentRole: string, agentId: string, getState: () => Promise<Record<string, string>>, acpHelper: DanceAcpHelper): Promise<DanceResult>;
|
|
70
|
+
/**
|
|
71
|
+
* Run inject for a specific agent. Returns formatted string or null if no inject.
|
|
72
|
+
*/
|
|
73
|
+
export declare function runInject(mod: DanceModule, state: Record<string, string>, agentRole: string, agentId: string): string | null;
|
package/dist/dances.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// ─── Loader ────────────────────────────────────────────────────
|
|
2
|
+
/**
|
|
3
|
+
* Load a dance file via dynamic import. Validates exports.
|
|
4
|
+
* Returns a DanceModule with optional inject and tool map.
|
|
5
|
+
*/
|
|
6
|
+
export async function loadDances(filePath) {
|
|
7
|
+
const mod = await import(filePath);
|
|
8
|
+
const tools = new Map();
|
|
9
|
+
let inject;
|
|
10
|
+
for (const [name, exp] of Object.entries(mod)) {
|
|
11
|
+
if (name === 'default')
|
|
12
|
+
continue; // skip default export
|
|
13
|
+
if (name === 'inject') {
|
|
14
|
+
if (typeof exp !== 'function') {
|
|
15
|
+
throw new Error(`Dance file: "inject" must be a function, got ${typeof exp}`);
|
|
16
|
+
}
|
|
17
|
+
inject = exp;
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
// Everything else is a tool
|
|
21
|
+
if (!exp || typeof exp !== 'object')
|
|
22
|
+
continue;
|
|
23
|
+
const tool = exp;
|
|
24
|
+
if (typeof tool.handler !== 'function') {
|
|
25
|
+
throw new Error(`Dance file: tool "${name}" must have a handler function`);
|
|
26
|
+
}
|
|
27
|
+
if (typeof tool.description !== 'string') {
|
|
28
|
+
throw new Error(`Dance file: tool "${name}" must have a description string`);
|
|
29
|
+
}
|
|
30
|
+
tools.set(name, {
|
|
31
|
+
description: tool.description,
|
|
32
|
+
params: tool.params ?? {},
|
|
33
|
+
handler: tool.handler,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return { inject, tools };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Convert dance tool definitions to LLM ToolDef format.
|
|
40
|
+
*/
|
|
41
|
+
export function danceToolDefs(mod) {
|
|
42
|
+
const defs = [];
|
|
43
|
+
for (const [name, tool] of mod.tools) {
|
|
44
|
+
const properties = {};
|
|
45
|
+
const required = [];
|
|
46
|
+
for (const [param, def] of Object.entries(tool.params)) {
|
|
47
|
+
properties[param] = {
|
|
48
|
+
type: def.type,
|
|
49
|
+
description: def.description ?? '',
|
|
50
|
+
};
|
|
51
|
+
required.push(param); // all params required by default
|
|
52
|
+
}
|
|
53
|
+
defs.push({
|
|
54
|
+
type: 'function',
|
|
55
|
+
function: {
|
|
56
|
+
name,
|
|
57
|
+
description: tool.description,
|
|
58
|
+
parameters: {
|
|
59
|
+
type: 'object',
|
|
60
|
+
properties,
|
|
61
|
+
required,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return defs;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Build an ACP helper that wraps incubator stores for use in dance handlers.
|
|
70
|
+
*/
|
|
71
|
+
export function buildAcpHelper(stores, namespace, agentId) {
|
|
72
|
+
return {
|
|
73
|
+
async publish(type, data) {
|
|
74
|
+
await stores.publishEvent(namespace, type, data, agentId);
|
|
75
|
+
},
|
|
76
|
+
async claim(resource) {
|
|
77
|
+
return stores.claimResource(namespace, resource, agentId);
|
|
78
|
+
},
|
|
79
|
+
async release(claimId) {
|
|
80
|
+
await stores.releaseResource(namespace, claimId);
|
|
81
|
+
},
|
|
82
|
+
async setState(key, value) {
|
|
83
|
+
await stores.setState(namespace, key, value);
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Execute a dance tool handler with full context.
|
|
89
|
+
*/
|
|
90
|
+
export async function callDanceTool(mod, toolName, args, agentRole, agentId, getState, acpHelper) {
|
|
91
|
+
const tool = mod.tools.get(toolName);
|
|
92
|
+
if (!tool) {
|
|
93
|
+
return { error: `Unknown dance tool: ${toolName}` };
|
|
94
|
+
}
|
|
95
|
+
const state = await getState();
|
|
96
|
+
const ctx = {
|
|
97
|
+
args,
|
|
98
|
+
state,
|
|
99
|
+
agent: { role: agentRole, agentId },
|
|
100
|
+
acp: acpHelper,
|
|
101
|
+
};
|
|
102
|
+
try {
|
|
103
|
+
return await tool.handler(ctx);
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
return { error: err instanceof Error ? err.message : String(err) };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Run inject for a specific agent. Returns formatted string or null if no inject.
|
|
111
|
+
*/
|
|
112
|
+
export function runInject(mod, state, agentRole, agentId) {
|
|
113
|
+
if (!mod.inject)
|
|
114
|
+
return null;
|
|
115
|
+
try {
|
|
116
|
+
return mod.inject({ state, agent: { role: agentRole, agentId } });
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
return `[inject error: ${err instanceof Error ? err.message : String(err)}]`;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=dances.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dances.js","sourceRoot":"","sources":["../src/dances.ts"],"names":[],"mappings":"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"}
|
package/dist/guard.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Stores } from './stores/interfaces.js';
|
|
2
|
+
interface ScanResult {
|
|
3
|
+
pass: boolean;
|
|
4
|
+
score: number;
|
|
5
|
+
action: 'PASS' | 'LOG' | 'WARN' | 'BLOCK';
|
|
6
|
+
findings: Array<{
|
|
7
|
+
category: string;
|
|
8
|
+
severity: string;
|
|
9
|
+
description: string;
|
|
10
|
+
}>;
|
|
11
|
+
summary: string;
|
|
12
|
+
}
|
|
13
|
+
export interface Guard {
|
|
14
|
+
scan(message: string): ScanResult;
|
|
15
|
+
}
|
|
16
|
+
export declare class CarapaceBlockedError extends Error {
|
|
17
|
+
readonly score: number;
|
|
18
|
+
readonly action: string;
|
|
19
|
+
readonly findings: ScanResult['findings'];
|
|
20
|
+
constructor(result: ScanResult);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Load carapace (CJS) from an ESM context via createRequire.
|
|
24
|
+
* Carapace uses __dirname + fs.readFileSync for pattern loading — cannot be ESM-imported.
|
|
25
|
+
*/
|
|
26
|
+
export declare function loadGuard(verbose?: boolean): Guard;
|
|
27
|
+
/**
|
|
28
|
+
* Concatenate text fields and run a single scan.
|
|
29
|
+
* Throws CarapaceBlockedError on BLOCK, logs on WARN.
|
|
30
|
+
*/
|
|
31
|
+
interface TelemetryLike {
|
|
32
|
+
record(type: string, meta: Record<string, unknown>): void;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Wrap store methods with Carapace scanning.
|
|
36
|
+
* Writes throw CarapaceBlockedError on BLOCK. Reads silently filter out poisoned entries.
|
|
37
|
+
* Internal system events bypass the guard.
|
|
38
|
+
*/
|
|
39
|
+
export declare function createGuardedStores(stores: Stores, guard: Guard, verbose?: boolean, telemetry?: TelemetryLike): Stores;
|
|
40
|
+
/**
|
|
41
|
+
* Scan a snapshot's entries on load. Returns counts of blocked items.
|
|
42
|
+
* Mutates the snapshot arrays in place, removing poisoned entries.
|
|
43
|
+
*/
|
|
44
|
+
export declare function scanSnapshot(snapshot: {
|
|
45
|
+
state: unknown[];
|
|
46
|
+
claims: unknown[];
|
|
47
|
+
events: unknown[];
|
|
48
|
+
discoveries: unknown[];
|
|
49
|
+
}, guard: Guard, verbose?: boolean, telemetry?: TelemetryLike): {
|
|
50
|
+
blocked: number;
|
|
51
|
+
};
|
|
52
|
+
export {};
|
package/dist/guard.js
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
export class CarapaceBlockedError extends Error {
|
|
3
|
+
score;
|
|
4
|
+
action;
|
|
5
|
+
findings;
|
|
6
|
+
constructor(result) {
|
|
7
|
+
super(`[carapace] Blocked: ${result.summary}`);
|
|
8
|
+
this.name = 'CarapaceBlockedError';
|
|
9
|
+
this.score = result.score;
|
|
10
|
+
this.action = result.action;
|
|
11
|
+
this.findings = result.findings;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Load carapace (CJS) from an ESM context via createRequire.
|
|
16
|
+
* Carapace uses __dirname + fs.readFileSync for pattern loading — cannot be ESM-imported.
|
|
17
|
+
*/
|
|
18
|
+
export function loadGuard(verbose) {
|
|
19
|
+
const require = createRequire(import.meta.url);
|
|
20
|
+
const mod = require('@honeybee-ai/carapace');
|
|
21
|
+
if (verbose) {
|
|
22
|
+
console.error('[incubator] carapace loaded');
|
|
23
|
+
}
|
|
24
|
+
return mod;
|
|
25
|
+
}
|
|
26
|
+
function scanFields(guard, fields, verbose, telemetry) {
|
|
27
|
+
const text = fields.filter(Boolean).join(' ');
|
|
28
|
+
if (!text)
|
|
29
|
+
return;
|
|
30
|
+
const result = guard.scan(text);
|
|
31
|
+
if (verbose && result.findings.length > 0) {
|
|
32
|
+
const ts = new Date().toISOString().slice(11, 23);
|
|
33
|
+
console.error(` ${ts} [carapace] score=${result.score} action=${result.action} findings=${result.findings.length}`);
|
|
34
|
+
}
|
|
35
|
+
if (result.action !== 'PASS' && telemetry) {
|
|
36
|
+
telemetry.record('guard_scan', {
|
|
37
|
+
action: result.action, score: result.score,
|
|
38
|
+
findingsCount: result.findings.length, side: 'write',
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
if (result.action === 'BLOCK') {
|
|
42
|
+
throw new CarapaceBlockedError(result);
|
|
43
|
+
}
|
|
44
|
+
if (result.action === 'WARN' && verbose) {
|
|
45
|
+
const ts = new Date().toISOString().slice(11, 23);
|
|
46
|
+
console.error(` ${ts} [carapace] WARN: ${result.summary}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Scan fields and return true if content is clean (PASS/LOG/WARN), false if BLOCK.
|
|
51
|
+
* Used for read-side filtering — poisoned data is silently dropped, not thrown.
|
|
52
|
+
*/
|
|
53
|
+
function isClean(guard, fields, verbose, telemetry) {
|
|
54
|
+
const text = fields.filter(Boolean).join(' ');
|
|
55
|
+
if (!text)
|
|
56
|
+
return true;
|
|
57
|
+
const result = guard.scan(text);
|
|
58
|
+
if (result.action === 'BLOCK') {
|
|
59
|
+
if (verbose) {
|
|
60
|
+
const ts = new Date().toISOString().slice(11, 23);
|
|
61
|
+
console.error(` ${ts} [carapace] READ BLOCKED: score=${result.score} — poisoned entry filtered out`);
|
|
62
|
+
}
|
|
63
|
+
telemetry?.record('guard_scan', {
|
|
64
|
+
action: 'BLOCK', score: result.score,
|
|
65
|
+
findingsCount: result.findings.length, side: 'read',
|
|
66
|
+
});
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
function stringify(v) {
|
|
72
|
+
if (typeof v === 'string')
|
|
73
|
+
return v;
|
|
74
|
+
if (v == null)
|
|
75
|
+
return '';
|
|
76
|
+
return JSON.stringify(v);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Wrap store methods with Carapace scanning.
|
|
80
|
+
* Writes throw CarapaceBlockedError on BLOCK. Reads silently filter out poisoned entries.
|
|
81
|
+
* Internal system events bypass the guard.
|
|
82
|
+
*/
|
|
83
|
+
export function createGuardedStores(stores, guard, verbose, telemetry) {
|
|
84
|
+
// ClaimStore and DiscoveryStore emit internal events like "claim.acquired" and
|
|
85
|
+
// "discovery.published" — these are system-generated and bypass the guard.
|
|
86
|
+
// We only guard user-facing methods.
|
|
87
|
+
return {
|
|
88
|
+
state: {
|
|
89
|
+
set: async (key, value, agentId, category, ttlMs) => {
|
|
90
|
+
scanFields(guard, [key, stringify(value), category], verbose, telemetry);
|
|
91
|
+
return stores.state.set(key, value, agentId, category, ttlMs);
|
|
92
|
+
},
|
|
93
|
+
get: async (key) => {
|
|
94
|
+
const entry = await stores.state.get(key);
|
|
95
|
+
if (!entry)
|
|
96
|
+
return null;
|
|
97
|
+
if (!isClean(guard, [entry.key, stringify(entry.value), entry.category], verbose, telemetry))
|
|
98
|
+
return null;
|
|
99
|
+
return entry;
|
|
100
|
+
},
|
|
101
|
+
delete: (key) => stores.state.delete(key),
|
|
102
|
+
query: async (pattern, category) => {
|
|
103
|
+
const entries = await stores.state.query(pattern, category);
|
|
104
|
+
return entries.filter(e => isClean(guard, [e.key, stringify(e.value), e.category], verbose, telemetry));
|
|
105
|
+
},
|
|
106
|
+
getAll: () => stores.state.getAll(),
|
|
107
|
+
load: (entries) => stores.state.load(entries),
|
|
108
|
+
},
|
|
109
|
+
events: {
|
|
110
|
+
publish: async (type, data, agentId) => {
|
|
111
|
+
scanFields(guard, [type, stringify(data)], verbose, telemetry);
|
|
112
|
+
return stores.events.publish(type, data, agentId);
|
|
113
|
+
},
|
|
114
|
+
getEvents: async (since, type) => {
|
|
115
|
+
const result = await stores.events.getEvents(since, type);
|
|
116
|
+
return {
|
|
117
|
+
events: result.events.filter(e => isClean(guard, [e.type, stringify(e.data)], verbose, telemetry)),
|
|
118
|
+
cursor: result.cursor,
|
|
119
|
+
};
|
|
120
|
+
},
|
|
121
|
+
getCursor: () => stores.events.getCursor(),
|
|
122
|
+
getAll: () => stores.events.getAll(),
|
|
123
|
+
load: (events, cursor) => stores.events.load(events, cursor),
|
|
124
|
+
},
|
|
125
|
+
claims: {
|
|
126
|
+
claim: async (resource, value, agentId, ttlMs) => {
|
|
127
|
+
scanFields(guard, [resource, value], verbose, telemetry);
|
|
128
|
+
return stores.claims.claim(resource, value, agentId, ttlMs);
|
|
129
|
+
},
|
|
130
|
+
release: (resource, agentId) => stores.claims.release(resource, agentId),
|
|
131
|
+
check: async (resource) => {
|
|
132
|
+
const claim = await stores.claims.check(resource);
|
|
133
|
+
if (!claim)
|
|
134
|
+
return null;
|
|
135
|
+
if (!isClean(guard, [claim.resource, claim.value], verbose, telemetry))
|
|
136
|
+
return null;
|
|
137
|
+
return claim;
|
|
138
|
+
},
|
|
139
|
+
list: async (pattern) => {
|
|
140
|
+
const claims = await stores.claims.list(pattern);
|
|
141
|
+
return claims.filter(c => isClean(guard, [c.resource, c.value], verbose, telemetry));
|
|
142
|
+
},
|
|
143
|
+
getAll: () => stores.claims.getAll(),
|
|
144
|
+
load: (claims) => stores.claims.load(claims),
|
|
145
|
+
},
|
|
146
|
+
discoveries: {
|
|
147
|
+
publish: async (topic, content, agentId, category) => {
|
|
148
|
+
scanFields(guard, [topic, content, category], verbose, telemetry);
|
|
149
|
+
return stores.discoveries.publish(topic, content, agentId, category);
|
|
150
|
+
},
|
|
151
|
+
search: async (query, category) => {
|
|
152
|
+
const discoveries = await stores.discoveries.search(query, category);
|
|
153
|
+
return discoveries.filter(d => isClean(guard, [d.topic, d.content, d.category], verbose, telemetry));
|
|
154
|
+
},
|
|
155
|
+
getAll: () => stores.discoveries.getAll(),
|
|
156
|
+
load: (discoveries) => stores.discoveries.load(discoveries),
|
|
157
|
+
},
|
|
158
|
+
messages: {
|
|
159
|
+
send: async (from, to, content, replyTo) => {
|
|
160
|
+
scanFields(guard, [content], verbose, telemetry);
|
|
161
|
+
return stores.messages.send(from, to, content, replyTo);
|
|
162
|
+
},
|
|
163
|
+
getFor: (agentId, since) => stores.messages.getFor(agentId, since),
|
|
164
|
+
getAll: () => stores.messages.getAll(),
|
|
165
|
+
},
|
|
166
|
+
help: {
|
|
167
|
+
request: async (agentId, problem, needsCapability, urgency) => {
|
|
168
|
+
scanFields(guard, [problem, needsCapability], verbose, telemetry);
|
|
169
|
+
return stores.help.request(agentId, problem, needsCapability, urgency);
|
|
170
|
+
},
|
|
171
|
+
claim: (requestId, agentId) => stores.help.claim(requestId, agentId),
|
|
172
|
+
resolve: (requestId, agentId) => stores.help.resolve(requestId, agentId),
|
|
173
|
+
list: (status) => stores.help.list(status),
|
|
174
|
+
},
|
|
175
|
+
progress: stores.progress,
|
|
176
|
+
conflicts: stores.conflicts,
|
|
177
|
+
roles: stores.roles,
|
|
178
|
+
proposals: stores.proposals,
|
|
179
|
+
reinforcements: stores.reinforcements,
|
|
180
|
+
control: stores.control,
|
|
181
|
+
runs: stores.runs,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Scan a snapshot's entries on load. Returns counts of blocked items.
|
|
186
|
+
* Mutates the snapshot arrays in place, removing poisoned entries.
|
|
187
|
+
*/
|
|
188
|
+
export function scanSnapshot(snapshot, guard, verbose, telemetry) {
|
|
189
|
+
let blocked = 0;
|
|
190
|
+
const scanAndFilter = (items, getFields) => {
|
|
191
|
+
return items.filter(item => {
|
|
192
|
+
if (isClean(guard, getFields(item), verbose, telemetry))
|
|
193
|
+
return true;
|
|
194
|
+
blocked++;
|
|
195
|
+
return false;
|
|
196
|
+
});
|
|
197
|
+
};
|
|
198
|
+
snapshot.state = scanAndFilter(snapshot.state, e => [e.key, stringify(e.value), e.category]);
|
|
199
|
+
snapshot.claims = scanAndFilter(snapshot.claims, c => [c.resource, c.value]);
|
|
200
|
+
snapshot.events = scanAndFilter(snapshot.events, e => [e.type, stringify(e.data)]);
|
|
201
|
+
snapshot.discoveries = scanAndFilter(snapshot.discoveries, d => [d.topic, d.content, d.category]);
|
|
202
|
+
if (blocked > 0) {
|
|
203
|
+
console.error(`[incubator] Carapace: ${blocked} poisoned entries removed from snapshot`);
|
|
204
|
+
telemetry?.record('guard_scan', {
|
|
205
|
+
action: 'BLOCK', side: 'snapshot', blockedCount: blocked,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
return { blocked };
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../src/guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Stores } from './stores/interfaces.js';
|
|
2
|
+
/** Heartbeat config from protocol governance (avoids spec version dependency) */
|
|
3
|
+
interface HeartbeatGovernance {
|
|
4
|
+
heartbeat?: {
|
|
5
|
+
stale_after_ms?: number;
|
|
6
|
+
dead_after_ms?: number;
|
|
7
|
+
auto_release_claims?: boolean;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export interface HeartbeatConfig {
|
|
11
|
+
stale_after_ms: number;
|
|
12
|
+
dead_after_ms: number;
|
|
13
|
+
auto_release_claims: boolean;
|
|
14
|
+
check_interval_ms: number;
|
|
15
|
+
}
|
|
16
|
+
export declare class HeartbeatMonitor {
|
|
17
|
+
private lastActivity;
|
|
18
|
+
private staleNotified;
|
|
19
|
+
private deadNotified;
|
|
20
|
+
private config;
|
|
21
|
+
private stores;
|
|
22
|
+
private timer;
|
|
23
|
+
constructor(stores: Stores, governance?: HeartbeatGovernance);
|
|
24
|
+
/** Record activity for an agent (called on every API request) */
|
|
25
|
+
touch(agentId: string): void;
|
|
26
|
+
/** Start the periodic check timer */
|
|
27
|
+
start(): void;
|
|
28
|
+
/** Stop the timer */
|
|
29
|
+
stop(): void;
|
|
30
|
+
/** Run a single check cycle (public for testing) */
|
|
31
|
+
check(): Promise<void>;
|
|
32
|
+
private handleStale;
|
|
33
|
+
private handleDeath;
|
|
34
|
+
/** Get all tracked agents and their status */
|
|
35
|
+
getStatus(): Array<{
|
|
36
|
+
agent: string;
|
|
37
|
+
lastActivity: number;
|
|
38
|
+
status: 'alive' | 'stale' | 'dead';
|
|
39
|
+
}>;
|
|
40
|
+
}
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
const DEFAULTS = {
|
|
2
|
+
stale_after_ms: 30000,
|
|
3
|
+
dead_after_ms: 60000,
|
|
4
|
+
auto_release_claims: true,
|
|
5
|
+
check_interval_ms: 10000,
|
|
6
|
+
};
|
|
7
|
+
export class HeartbeatMonitor {
|
|
8
|
+
lastActivity = new Map();
|
|
9
|
+
staleNotified = new Set();
|
|
10
|
+
deadNotified = new Set();
|
|
11
|
+
config;
|
|
12
|
+
stores;
|
|
13
|
+
timer = null;
|
|
14
|
+
constructor(stores, governance) {
|
|
15
|
+
this.stores = stores;
|
|
16
|
+
this.config = {
|
|
17
|
+
stale_after_ms: governance?.heartbeat?.stale_after_ms ?? DEFAULTS.stale_after_ms,
|
|
18
|
+
dead_after_ms: governance?.heartbeat?.dead_after_ms ?? DEFAULTS.dead_after_ms,
|
|
19
|
+
auto_release_claims: governance?.heartbeat?.auto_release_claims ?? DEFAULTS.auto_release_claims,
|
|
20
|
+
check_interval_ms: DEFAULTS.check_interval_ms,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/** Record activity for an agent (called on every API request) */
|
|
24
|
+
touch(agentId) {
|
|
25
|
+
this.lastActivity.set(agentId, Date.now());
|
|
26
|
+
// If agent was stale, clear stale notification (they came back)
|
|
27
|
+
this.staleNotified.delete(agentId);
|
|
28
|
+
this.deadNotified.delete(agentId);
|
|
29
|
+
}
|
|
30
|
+
/** Start the periodic check timer */
|
|
31
|
+
start() {
|
|
32
|
+
if (this.timer)
|
|
33
|
+
return;
|
|
34
|
+
this.timer = setInterval(() => this.check(), this.config.check_interval_ms);
|
|
35
|
+
}
|
|
36
|
+
/** Stop the timer */
|
|
37
|
+
stop() {
|
|
38
|
+
if (this.timer) {
|
|
39
|
+
clearInterval(this.timer);
|
|
40
|
+
this.timer = null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Run a single check cycle (public for testing) */
|
|
44
|
+
async check() {
|
|
45
|
+
const now = Date.now();
|
|
46
|
+
for (const [agentId, lastTime] of this.lastActivity) {
|
|
47
|
+
const elapsed = now - lastTime;
|
|
48
|
+
if (elapsed >= this.config.dead_after_ms && !this.deadNotified.has(agentId)) {
|
|
49
|
+
await this.handleDeath(agentId);
|
|
50
|
+
this.deadNotified.add(agentId);
|
|
51
|
+
}
|
|
52
|
+
else if (elapsed >= this.config.stale_after_ms && !this.staleNotified.has(agentId)) {
|
|
53
|
+
await this.handleStale(agentId);
|
|
54
|
+
this.staleNotified.add(agentId);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async handleStale(agentId) {
|
|
59
|
+
const assignment = await this.stores.roles.getByAgent(agentId);
|
|
60
|
+
await this.stores.events.publish('agent.stale', {
|
|
61
|
+
agent: agentId,
|
|
62
|
+
role: assignment?.role,
|
|
63
|
+
last_activity: new Date(this.lastActivity.get(agentId)).toISOString(),
|
|
64
|
+
}, 'server');
|
|
65
|
+
}
|
|
66
|
+
async handleDeath(agentId) {
|
|
67
|
+
const assignment = await this.stores.roles.getByAgent(agentId);
|
|
68
|
+
const releasedClaims = [];
|
|
69
|
+
if (this.config.auto_release_claims) {
|
|
70
|
+
const claims = await this.stores.claims.list();
|
|
71
|
+
for (const claim of claims) {
|
|
72
|
+
if (claim.owner === agentId) {
|
|
73
|
+
await this.stores.claims.release(claim.resource, agentId);
|
|
74
|
+
releasedClaims.push(claim.resource);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Remove role assignment
|
|
79
|
+
await this.stores.roles.remove(agentId);
|
|
80
|
+
await this.stores.events.publish('agent.died', {
|
|
81
|
+
agent: agentId,
|
|
82
|
+
role: assignment?.role,
|
|
83
|
+
released_claims: releasedClaims,
|
|
84
|
+
}, 'server');
|
|
85
|
+
// Clean up tracking
|
|
86
|
+
this.lastActivity.delete(agentId);
|
|
87
|
+
}
|
|
88
|
+
/** Get all tracked agents and their status */
|
|
89
|
+
getStatus() {
|
|
90
|
+
const now = Date.now();
|
|
91
|
+
const result = [];
|
|
92
|
+
for (const [agentId, lastTime] of this.lastActivity) {
|
|
93
|
+
const elapsed = now - lastTime;
|
|
94
|
+
let status = 'alive';
|
|
95
|
+
if (elapsed >= this.config.dead_after_ms)
|
|
96
|
+
status = 'dead';
|
|
97
|
+
else if (elapsed >= this.config.stale_after_ms)
|
|
98
|
+
status = 'stale';
|
|
99
|
+
result.push({ agent: agentId, lastActivity: lastTime, status });
|
|
100
|
+
}
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=heartbeat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../src/heartbeat.ts"],"names":[],"mappings":"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"}
|