@kognai/build 0.6.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.
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runSwarm = runSwarm;
4
+ /**
5
+ * swarm.ts — --swarm mode (TICKET-233 Phase 2).
6
+ *
7
+ * Delegates a decomposed goal to the FULL @kognai/orchestrator-core swarm
8
+ * (CEO planning · CTO governance gate · dual-supervisor review · reconciliation)
9
+ * instead of kognai-build's lighter in-process pipeline.
10
+ *
11
+ * The engine is repo-shaped: it reads the sprint from process.argv[2] and loads
12
+ * coding agents from ./agents/<name>/prompt.md (cwd-relative). So we scaffold a
13
+ * throwaway working dir (bundled coder agent + a synthesized human-sourced sprint),
14
+ * chdir into it, run the orchestrator, then collect the deliverables back out.
15
+ *
16
+ * Model routing still flows through the ModelRouter registered at boot
17
+ * (makeBuildRouter) — so --swarm honors --sovereign ($0 local) end to end,
18
+ * leadership included (the engine's callLLM/callAnthropicCached route through it).
19
+ */
20
+ const node_fs_1 = require("node:fs");
21
+ const node_path_1 = require("node:path");
22
+ const orchestrator_core_1 = require("@kognai/orchestrator-core");
23
+ const swarm_coder_prompt_1 = require("./swarm-coder-prompt");
24
+ /**
25
+ * Run a decomposed goal through the full orchestrator swarm.
26
+ * @param goal the original user goal (sprint title/description)
27
+ * @param tasks decomposed tasks (file + description), agent defaults to 'coder'
28
+ * @param outDir where to copy shipped deliverables
29
+ */
30
+ async function runSwarm(goal, tasks, outDir) {
31
+ const sid = Math.floor(Date.now() / 1000).toString(36).slice(-5);
32
+ const scaffold = (0, node_path_1.join)('/tmp', `kognai-swarm-${sid}`);
33
+ // 1. Scaffold: bundled coder agent so the engine has someone to dispatch to.
34
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(scaffold, 'agents', 'coder'), { recursive: true });
35
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(scaffold, 'agents', 'coder', 'prompt.md'), swarm_coder_prompt_1.SWARM_CODER_PROMPT);
36
+ // 2. Synthesize a human-sourced sprint (source:'human' → CTO gate auto-approves
37
+ // the builder's own goal rather than rejecting it as off-plan).
38
+ const sprint = {
39
+ sprint_id: `swarm-${sid}`,
40
+ title: goal,
41
+ description: goal,
42
+ source: 'human',
43
+ inputs: ['user goal'],
44
+ outputs: tasks.map((t) => t.file),
45
+ success_criteria: ['every task ships a complete, reviewed file'],
46
+ tasks: tasks.map((t, i) => ({
47
+ id: `swarm-${sid}-${i + 1}`,
48
+ title: t.file,
49
+ type: 'feature',
50
+ task_type: 'autonomous',
51
+ task_target: t.file,
52
+ agent: 'coder',
53
+ priority: 'medium',
54
+ // The engine's Phase 2 only executes tasks with status === 'pending'
55
+ // (orchestrate-engine: `if (task.status !== 'pending') continue`). Without
56
+ // this the whole leadership ceremony runs but the coder never fires.
57
+ status: 'pending',
58
+ deliverables: { code: [t.file], tests: [], docs: [] },
59
+ context: t.description,
60
+ })),
61
+ };
62
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(scaffold, 'sprint.json'), JSON.stringify(sprint, null, 2));
63
+ // 3. Run the orchestrator from inside the scaffold (cwd-relative ./agents +
64
+ // process.argv[2] sprint path). Restore cwd/argv afterward.
65
+ const prevCwd = process.cwd();
66
+ const prevArgv = process.argv.slice();
67
+ process.chdir(scaffold);
68
+ process.argv = [process.argv[0], process.argv[1], 'sprint.json'];
69
+ try {
70
+ await (0, orchestrator_core_1.runOrchestrator)({});
71
+ }
72
+ finally {
73
+ process.chdir(prevCwd);
74
+ process.argv = prevArgv;
75
+ }
76
+ // 4. Collect deliverables the swarm wrote (relative paths preserved).
77
+ const deliverables = [];
78
+ (0, node_fs_1.mkdirSync)(outDir, { recursive: true });
79
+ for (const t of tasks) {
80
+ const src = (0, node_path_1.join)(scaffold, t.file);
81
+ if ((0, node_fs_1.existsSync)(src)) {
82
+ const dst = (0, node_path_1.join)(outDir, t.file);
83
+ (0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(dst), { recursive: true });
84
+ (0, node_fs_1.cpSync)(src, dst);
85
+ deliverables.push(dst);
86
+ }
87
+ }
88
+ return { deliverables, total: tasks.length, scaffold };
89
+ }
@@ -0,0 +1,214 @@
1
+ "use strict";
2
+ /**
3
+ * Tool Layer Stub
4
+ *
5
+ * Phase 1 stub returning mock tool metadata for cost estimation and
6
+ * capability discovery. Phase 2 (TICKET-125) replaces TOOL_LAYER with
7
+ * a real provider registry backed by live cost-per-call data.
8
+ *
9
+ * Function signatures are stable across phases — callers (cost-estimator.ts,
10
+ * build planners, capability matchers) can rely on the API surface.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.TOOL_LAYER = void 0;
14
+ exports.getToolsByIds = getToolsByIds;
15
+ exports.listToolsByCategory = listToolsByCategory;
16
+ exports.estimateToolCost = estimateToolCost;
17
+ exports.TOOL_LAYER = [
18
+ // ── database ─────────────────────────────────────────────────────────────
19
+ {
20
+ id: 'postgres-encrypted',
21
+ name: 'PostgreSQL (Encrypted)',
22
+ provider: 'self-hosted',
23
+ category: 'database',
24
+ cost_per_call_usdc: 0,
25
+ description: 'Self-hosted Postgres with at-rest encryption and pgcrypto.',
26
+ },
27
+ {
28
+ id: 'redis-cache',
29
+ name: 'Redis Cache',
30
+ provider: 'self-hosted',
31
+ category: 'database',
32
+ cost_per_call_usdc: 0,
33
+ description: 'In-memory key-value store for caching and rate limiting.',
34
+ },
35
+ {
36
+ id: 'supabase',
37
+ name: 'Supabase Postgres',
38
+ provider: 'supabase',
39
+ category: 'database',
40
+ cost_per_call_usdc: 0.00005,
41
+ description: 'Managed Postgres with row-level security and realtime.',
42
+ },
43
+ // ── llm ──────────────────────────────────────────────────────────────────
44
+ {
45
+ id: 'anthropic-sonnet',
46
+ name: 'Anthropic Claude Sonnet',
47
+ provider: 'anthropic',
48
+ category: 'llm',
49
+ cost_per_call_usdc: 0.015,
50
+ description: 'Mid-tier reasoning LLM, ~1k token avg call.',
51
+ },
52
+ {
53
+ id: 'anthropic-haiku',
54
+ name: 'Anthropic Claude Haiku',
55
+ provider: 'anthropic',
56
+ category: 'llm',
57
+ cost_per_call_usdc: 0.0012,
58
+ description: 'Fast cheap LLM for classification and routing.',
59
+ },
60
+ {
61
+ id: 'qwen-plus',
62
+ name: 'Qwen Plus (Cloud)',
63
+ provider: 'alibaba',
64
+ category: 'llm',
65
+ cost_per_call_usdc: 0.0008,
66
+ description: 'Cloud-hosted Qwen Plus for general-purpose generation.',
67
+ },
68
+ {
69
+ id: 'ollama-local',
70
+ name: 'Ollama (Local)',
71
+ provider: 'self-hosted',
72
+ category: 'llm',
73
+ cost_per_call_usdc: 0,
74
+ description: 'Local LLM runtime (Qwen3, Llama, etc.) — zero per-call cost.',
75
+ },
76
+ // ── search ───────────────────────────────────────────────────────────────
77
+ {
78
+ id: 'tavily',
79
+ name: 'Tavily Search API',
80
+ provider: 'tavily',
81
+ category: 'search',
82
+ cost_per_call_usdc: 0.005,
83
+ description: 'LLM-optimized web search with snippet extraction.',
84
+ },
85
+ {
86
+ id: 'exa',
87
+ name: 'Exa Neural Search',
88
+ provider: 'exa',
89
+ category: 'search',
90
+ cost_per_call_usdc: 0.01,
91
+ description: 'Neural search over indexed web content.',
92
+ },
93
+ // ── payment ──────────────────────────────────────────────────────────────
94
+ {
95
+ id: 'x402-meter',
96
+ name: 'x402 Payment Meter',
97
+ provider: 'x402',
98
+ category: 'payment',
99
+ cost_per_call_usdc: 0.0001,
100
+ description: 'HTTP 402 micropayment metering for per-call billing.',
101
+ },
102
+ {
103
+ id: 'stripe-webhook',
104
+ name: 'Stripe Webhook Handler',
105
+ provider: 'stripe',
106
+ category: 'payment',
107
+ cost_per_call_usdc: 0,
108
+ description: 'Receive and verify Stripe webhook events (cost is in fees, not calls).',
109
+ },
110
+ // ── compliance ───────────────────────────────────────────────────────────
111
+ {
112
+ id: 'hipaa-bcc-checker',
113
+ name: 'HIPAA BAA/BCC Checker',
114
+ provider: 'self-hosted',
115
+ category: 'compliance',
116
+ cost_per_call_usdc: 0,
117
+ description: 'Verifies BAA coverage and BCC routing for PHI workflows.',
118
+ },
119
+ {
120
+ id: 'gdpr-data-mapper',
121
+ name: 'GDPR Data Mapper',
122
+ provider: 'self-hosted',
123
+ category: 'compliance',
124
+ cost_per_call_usdc: 0,
125
+ description: 'Tracks personal-data lineage for GDPR Article 30 records.',
126
+ },
127
+ // ── observability ────────────────────────────────────────────────────────
128
+ {
129
+ id: 'posthog',
130
+ name: 'PostHog Analytics',
131
+ provider: 'posthog',
132
+ category: 'observability',
133
+ cost_per_call_usdc: 0.00001,
134
+ description: 'Product analytics, session replay, and feature flags.',
135
+ },
136
+ {
137
+ id: 'datadog',
138
+ name: 'Datadog APM',
139
+ provider: 'datadog',
140
+ category: 'observability',
141
+ cost_per_call_usdc: 0.0002,
142
+ description: 'Application performance monitoring and log aggregation.',
143
+ },
144
+ {
145
+ id: 'sentry',
146
+ name: 'Sentry Error Tracking',
147
+ provider: 'sentry',
148
+ category: 'observability',
149
+ cost_per_call_usdc: 0.00005,
150
+ description: 'Error capture, stack traces, and release tracking.',
151
+ },
152
+ // ── identity ─────────────────────────────────────────────────────────────
153
+ {
154
+ id: 'erc-8004-resolver',
155
+ name: 'ERC-8004 Agent Resolver',
156
+ provider: 'self-hosted',
157
+ category: 'identity',
158
+ cost_per_call_usdc: 0,
159
+ description: 'Resolves on-chain agent identities per ERC-8004 spec.',
160
+ },
161
+ {
162
+ id: 'pact-mandate-verify',
163
+ name: 'PACT Mandate Verifier',
164
+ provider: 'self-hosted',
165
+ category: 'identity',
166
+ cost_per_call_usdc: 0,
167
+ description: 'Verifies PACT mandate signatures for delegated agent actions.',
168
+ },
169
+ ];
170
+ /**
171
+ * Internal index keyed by tool id for O(1) lookup.
172
+ * Rebuilt at module load; safe because TOOL_LAYER is a const literal.
173
+ */
174
+ const TOOL_INDEX = new Map(exports.TOOL_LAYER.map((tool) => [tool.id, tool]));
175
+ /**
176
+ * Resolve a list of tool ids to their entries.
177
+ * Unknown ids are silently dropped — callers needing strict validation
178
+ * should compare result length to input length.
179
+ */
180
+ function getToolsByIds(ids) {
181
+ const seen = new Set();
182
+ const out = [];
183
+ for (const id of ids) {
184
+ if (seen.has(id))
185
+ continue;
186
+ seen.add(id);
187
+ const tool = TOOL_INDEX.get(id);
188
+ if (tool)
189
+ out.push(tool);
190
+ }
191
+ return out;
192
+ }
193
+ /**
194
+ * List every tool in a given category.
195
+ * Returns empty array for unknown categories.
196
+ */
197
+ function listToolsByCategory(category) {
198
+ return exports.TOOL_LAYER.filter((tool) => tool.category === category);
199
+ }
200
+ /**
201
+ * Estimate total cost in USDC for invoking the given tools `expectedCalls` times each.
202
+ *
203
+ * Formula: sum(tool.cost_per_call_usdc for tool in resolved_tools) × expectedCalls
204
+ *
205
+ * Unknown tool ids contribute 0. Negative `expectedCalls` is clamped to 0.
206
+ */
207
+ function estimateToolCost(toolIds, expectedCalls) {
208
+ const calls = Math.max(0, expectedCalls);
209
+ if (calls === 0)
210
+ return 0;
211
+ const tools = getToolsByIds(toolIds);
212
+ const perCallSum = tools.reduce((acc, tool) => acc + tool.cost_per_call_usdc, 0);
213
+ return perCallSum * calls;
214
+ }
@@ -0,0 +1,249 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TOOL_LAYER = void 0;
4
+ exports.getToolsByIds = getToolsByIds;
5
+ exports.listToolsByCategory = listToolsByCategory;
6
+ exports.estimateToolCost = estimateToolCost;
7
+ exports.unknownToolIds = unknownToolIds;
8
+ /**
9
+ * Tool Layer (TICKET-125) — the registry of external capabilities agents call,
10
+ * with per-call cost metadata used for cost estimation + capability discovery.
11
+ *
12
+ * The curated catalog below is the base registry; a workspace extends or
13
+ * overrides it via `.kognai/tools.json` (merged at module load). Consumers:
14
+ * cost-estimator, build planners, capability matchers, and the mandate preview.
15
+ */
16
+ const registry_overrides_1 = require("./registry-overrides");
17
+ exports.TOOL_LAYER = [
18
+ // ── database ─────────────────────────────────────────────────────────────
19
+ {
20
+ id: 'postgres-encrypted',
21
+ name: 'PostgreSQL (Encrypted)',
22
+ provider: 'self-hosted',
23
+ category: 'database',
24
+ cost_per_call_usdc: 0,
25
+ description: 'Self-hosted Postgres with at-rest encryption and pgcrypto.',
26
+ },
27
+ {
28
+ id: 'redis-cache',
29
+ name: 'Redis Cache',
30
+ provider: 'self-hosted',
31
+ category: 'database',
32
+ cost_per_call_usdc: 0,
33
+ description: 'In-memory key-value store for caching and rate limiting.',
34
+ },
35
+ {
36
+ id: 'supabase',
37
+ name: 'Supabase Postgres',
38
+ provider: 'supabase',
39
+ category: 'database',
40
+ cost_per_call_usdc: 0.00005,
41
+ description: 'Managed Postgres with row-level security and realtime.',
42
+ },
43
+ // ── llm ──────────────────────────────────────────────────────────────────
44
+ {
45
+ id: 'anthropic-sonnet',
46
+ name: 'Anthropic Claude Sonnet',
47
+ provider: 'anthropic',
48
+ category: 'llm',
49
+ cost_per_call_usdc: 0.015,
50
+ description: 'Mid-tier reasoning LLM, ~1k token avg call.',
51
+ },
52
+ {
53
+ id: 'anthropic-haiku',
54
+ name: 'Anthropic Claude Haiku',
55
+ provider: 'anthropic',
56
+ category: 'llm',
57
+ cost_per_call_usdc: 0.0012,
58
+ description: 'Fast cheap LLM for classification and routing.',
59
+ },
60
+ {
61
+ id: 'qwen-plus',
62
+ name: 'Qwen Plus (Cloud)',
63
+ provider: 'alibaba',
64
+ category: 'llm',
65
+ cost_per_call_usdc: 0.0008,
66
+ description: 'Cloud-hosted Qwen Plus for general-purpose generation.',
67
+ },
68
+ {
69
+ id: 'ollama-local',
70
+ name: 'Ollama (Local)',
71
+ provider: 'self-hosted',
72
+ category: 'llm',
73
+ cost_per_call_usdc: 0,
74
+ description: 'Local LLM runtime (Qwen3, Llama, etc.) — zero per-call cost.',
75
+ },
76
+ // ── search ───────────────────────────────────────────────────────────────
77
+ {
78
+ id: 'tavily',
79
+ name: 'Tavily Search API',
80
+ provider: 'tavily',
81
+ category: 'search',
82
+ cost_per_call_usdc: 0.005,
83
+ description: 'LLM-optimized web search with snippet extraction.',
84
+ },
85
+ {
86
+ id: 'exa',
87
+ name: 'Exa Neural Search',
88
+ provider: 'exa',
89
+ category: 'search',
90
+ cost_per_call_usdc: 0.01,
91
+ description: 'Neural search over indexed web content.',
92
+ },
93
+ // ── payment ──────────────────────────────────────────────────────────────
94
+ {
95
+ id: 'x402-meter',
96
+ name: 'x402 Payment Meter',
97
+ provider: 'x402',
98
+ category: 'payment',
99
+ cost_per_call_usdc: 0.0001,
100
+ description: 'HTTP 402 micropayment metering for per-call billing.',
101
+ },
102
+ {
103
+ id: 'stripe-webhook',
104
+ name: 'Stripe Webhook Handler',
105
+ provider: 'stripe',
106
+ category: 'payment',
107
+ cost_per_call_usdc: 0,
108
+ description: 'Receive and verify Stripe webhook events (cost is in fees, not calls).',
109
+ },
110
+ // ── compliance ───────────────────────────────────────────────────────────
111
+ {
112
+ id: 'hipaa-bcc-checker',
113
+ name: 'HIPAA BAA/BCC Checker',
114
+ provider: 'self-hosted',
115
+ category: 'compliance',
116
+ cost_per_call_usdc: 0,
117
+ description: 'Verifies BAA coverage and BCC routing for PHI workflows.',
118
+ },
119
+ {
120
+ id: 'gdpr-data-mapper',
121
+ name: 'GDPR Data Mapper',
122
+ provider: 'self-hosted',
123
+ category: 'compliance',
124
+ cost_per_call_usdc: 0,
125
+ description: 'Tracks personal-data lineage for GDPR Article 30 records.',
126
+ },
127
+ // ── observability ────────────────────────────────────────────────────────
128
+ {
129
+ id: 'posthog',
130
+ name: 'PostHog Analytics',
131
+ provider: 'posthog',
132
+ category: 'observability',
133
+ cost_per_call_usdc: 0.00001,
134
+ description: 'Product analytics, session replay, and feature flags.',
135
+ },
136
+ {
137
+ id: 'datadog',
138
+ name: 'Datadog APM',
139
+ provider: 'datadog',
140
+ category: 'observability',
141
+ cost_per_call_usdc: 0.0002,
142
+ description: 'Application performance monitoring and log aggregation.',
143
+ },
144
+ {
145
+ id: 'sentry',
146
+ name: 'Sentry Error Tracking',
147
+ provider: 'sentry',
148
+ category: 'observability',
149
+ cost_per_call_usdc: 0.00005,
150
+ description: 'Error capture, stack traces, and release tracking.',
151
+ },
152
+ // ── identity ─────────────────────────────────────────────────────────────
153
+ {
154
+ id: 'erc-8004-resolver',
155
+ name: 'ERC-8004 Agent Resolver',
156
+ provider: 'self-hosted',
157
+ category: 'identity',
158
+ cost_per_call_usdc: 0,
159
+ description: 'Resolves on-chain agent identities per ERC-8004 spec.',
160
+ },
161
+ {
162
+ id: 'pact-mandate-verify',
163
+ name: 'PACT Mandate Verifier',
164
+ provider: 'self-hosted',
165
+ category: 'identity',
166
+ cost_per_call_usdc: 0,
167
+ description: 'Verifies PACT mandate signatures for delegated agent actions.',
168
+ },
169
+ // --- template-aligned capabilities (TICKET-233) ---
170
+ { id: "web-search", name: "Web Search", provider: "external", category: "research", cost_per_call_usdc: 0.002, description: "Web Search — capability used by kognai-build templates." },
171
+ { id: "pdf-reader", name: "Pdf Reader", provider: "external", category: "research", cost_per_call_usdc: 0.002, description: "Pdf Reader — capability used by kognai-build templates." },
172
+ { id: "citation-manager", name: "Citation Manager", provider: "external", category: "research", cost_per_call_usdc: 0.002, description: "Citation Manager — capability used by kognai-build templates." },
173
+ { id: "markdown-editor", name: "Markdown Editor", provider: "self-hosted", category: "content", cost_per_call_usdc: 0, description: "Markdown Editor — capability used by kognai-build templates." },
174
+ { id: "grammar-checker", name: "Grammar Checker", provider: "self-hosted", category: "content", cost_per_call_usdc: 0, description: "Grammar Checker — capability used by kognai-build templates." },
175
+ { id: "readability-scorer", name: "Readability Scorer", provider: "self-hosted", category: "content", cost_per_call_usdc: 0, description: "Readability Scorer — capability used by kognai-build templates." },
176
+ { id: "vite", name: "Vite", provider: "self-hosted", category: "build", cost_per_call_usdc: 0, description: "Vite — capability used by kognai-build templates." },
177
+ { id: "typescript-checker", name: "Typescript Checker", provider: "self-hosted", category: "build", cost_per_call_usdc: 0, description: "Typescript Checker — capability used by kognai-build templates." },
178
+ { id: "eslint", name: "Eslint", provider: "self-hosted", category: "build", cost_per_call_usdc: 0, description: "Eslint — capability used by kognai-build templates." },
179
+ { id: "slither", name: "Slither", provider: "self-hosted", category: "security", cost_per_call_usdc: 0, description: "Slither — capability used by kognai-build templates." },
180
+ { id: "foundry", name: "Foundry", provider: "self-hosted", category: "security", cost_per_call_usdc: 0, description: "Foundry — capability used by kognai-build templates." },
181
+ { id: "echidna-fuzzer", name: "Echidna Fuzzer", provider: "self-hosted", category: "security", cost_per_call_usdc: 0, description: "Echidna Fuzzer — capability used by kognai-build templates." },
182
+ { id: "audit-trail-emitter", name: "Audit Trail Emitter", provider: "self-hosted", category: "security", cost_per_call_usdc: 0, description: "Audit Trail Emitter — capability used by kognai-build templates." },
183
+ { id: "commander", name: "Commander", provider: "self-hosted", category: "build", cost_per_call_usdc: 0, description: "Commander — capability used by kognai-build templates." },
184
+ { id: "bash", name: "Bash", provider: "self-hosted", category: "build", cost_per_call_usdc: 0, description: "Bash — capability used by kognai-build templates." },
185
+ { id: "node-runtime", name: "Node Runtime", provider: "self-hosted", category: "build", cost_per_call_usdc: 0, description: "Node Runtime — capability used by kognai-build templates." },
186
+ { id: "airflow", name: "Airflow", provider: "self-hosted", category: "data", cost_per_call_usdc: 0, description: "Airflow — capability used by kognai-build templates." },
187
+ { id: "dbt", name: "Dbt", provider: "self-hosted", category: "data", cost_per_call_usdc: 0, description: "Dbt — capability used by kognai-build templates." },
188
+ { id: "great-expectations", name: "Great Expectations", provider: "self-hosted", category: "data", cost_per_call_usdc: 0, description: "Great Expectations — capability used by kognai-build templates." },
189
+ { id: "k6", name: "K6", provider: "self-hosted", category: "performance", cost_per_call_usdc: 0, description: "K6 — capability used by kognai-build templates." },
190
+ { id: "clinic-js", name: "Clinic Js", provider: "self-hosted", category: "performance", cost_per_call_usdc: 0, description: "Clinic Js — capability used by kognai-build templates." },
191
+ { id: "websocket-bench", name: "Websocket Bench", provider: "self-hosted", category: "performance", cost_per_call_usdc: 0, description: "Websocket Bench — capability used by kognai-build templates." },
192
+ { id: "hyperframes", name: "Hyperframes", provider: "self-hosted", category: "media", cost_per_call_usdc: 0, description: "Hyperframes — capability used by kognai-build templates." },
193
+ { id: "ffmpeg", name: "Ffmpeg", provider: "self-hosted", category: "media", cost_per_call_usdc: 0, description: "Ffmpeg — capability used by kognai-build templates." },
194
+ { id: "scorsese-renderer", name: "Scorsese Renderer", provider: "self-hosted", category: "media", cost_per_call_usdc: 0, description: "Scorsese Renderer — capability used by kognai-build templates." },
195
+ ];
196
+ // Merge optional workspace overrides (.kognai/tools.json) before the index is
197
+ // built — makes the registry real & extensible, not a frozen catalog.
198
+ (0, registry_overrides_1.applyRegistryOverrides)(exports.TOOL_LAYER, 'tools.json');
199
+ /**
200
+ * Internal index keyed by tool id for O(1) lookup.
201
+ * Rebuilt at module load over the merged registry.
202
+ */
203
+ const TOOL_INDEX = new Map(exports.TOOL_LAYER.map((tool) => [tool.id, tool]));
204
+ /**
205
+ * Resolve a list of tool ids to their entries.
206
+ * Unknown ids are silently dropped — callers needing strict validation
207
+ * should compare result length to input length.
208
+ */
209
+ function getToolsByIds(ids) {
210
+ const seen = new Set();
211
+ const out = [];
212
+ for (const id of ids) {
213
+ if (seen.has(id))
214
+ continue;
215
+ seen.add(id);
216
+ const tool = TOOL_INDEX.get(id);
217
+ if (tool)
218
+ out.push(tool);
219
+ }
220
+ return out;
221
+ }
222
+ /**
223
+ * List every tool in a given category.
224
+ * Returns empty array for unknown categories.
225
+ */
226
+ function listToolsByCategory(category) {
227
+ return exports.TOOL_LAYER.filter((tool) => tool.category === category);
228
+ }
229
+ /**
230
+ * Estimate total cost in USDC for invoking the given tools `expectedCalls` times each.
231
+ *
232
+ * Formula: sum(tool.cost_per_call_usdc for tool in resolved_tools) × expectedCalls
233
+ *
234
+ * Unknown tool ids contribute 0. Negative `expectedCalls` is clamped to 0.
235
+ */
236
+ function estimateToolCost(toolIds, expectedCalls) {
237
+ const calls = Math.max(0, expectedCalls);
238
+ if (calls === 0)
239
+ return 0;
240
+ const tools = getToolsByIds(toolIds);
241
+ const perCallSum = tools.reduce((acc, tool) => acc + tool.cost_per_call_usdc, 0);
242
+ return perCallSum * calls;
243
+ }
244
+ /** Return any tool ids not present in the registry (for template validation). */
245
+ function unknownToolIds(ids) {
246
+ if (!Array.isArray(ids))
247
+ return [];
248
+ return ids.filter((id) => !TOOL_INDEX.has(id));
249
+ }