infinicode 1.0.0 → 2.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.
Files changed (159) hide show
  1. package/.opencode/plugins/home-logo-animation.tsx +120 -0
  2. package/.opencode/plugins/routing-mode-display.tsx +135 -0
  3. package/.opencode/themes/infinibot-gold.json +222 -0
  4. package/.opencode/tui.json +8 -0
  5. package/README.md +564 -72
  6. package/dist/ascii-video-animation.d.ts +2 -0
  7. package/dist/ascii-video-animation.js +243 -0
  8. package/dist/cli.js +199 -50
  9. package/dist/commands/console.d.ts +6 -0
  10. package/dist/commands/console.js +111 -0
  11. package/dist/commands/kernel-setup.d.ts +3 -0
  12. package/dist/commands/kernel-setup.js +303 -0
  13. package/dist/commands/mcp.d.ts +14 -0
  14. package/dist/commands/mcp.js +100 -0
  15. package/dist/commands/mission.d.ts +16 -0
  16. package/dist/commands/mission.js +301 -0
  17. package/dist/commands/models.d.ts +3 -1
  18. package/dist/commands/models.js +111 -55
  19. package/dist/commands/providers.d.ts +6 -0
  20. package/dist/commands/providers.js +95 -0
  21. package/dist/commands/run.d.ts +2 -1
  22. package/dist/commands/run.js +349 -59
  23. package/dist/commands/serve.d.ts +20 -0
  24. package/dist/commands/serve.js +132 -0
  25. package/dist/commands/setup.d.ts +1 -1
  26. package/dist/commands/setup.js +77 -44
  27. package/dist/commands/status.d.ts +2 -1
  28. package/dist/commands/status.js +46 -30
  29. package/dist/commands/workers.d.ts +5 -0
  30. package/dist/commands/workers.js +103 -0
  31. package/dist/kernel/autonomy/goal-loop.d.ts +49 -0
  32. package/dist/kernel/autonomy/goal-loop.js +113 -0
  33. package/dist/kernel/autonomy/index.d.ts +8 -0
  34. package/dist/kernel/autonomy/index.js +7 -0
  35. package/dist/kernel/browser/browser-controller.d.ts +57 -0
  36. package/dist/kernel/browser/browser-controller.js +175 -0
  37. package/dist/kernel/checkpoint-engine.d.ts +17 -0
  38. package/dist/kernel/checkpoint-engine.js +128 -0
  39. package/dist/kernel/command-system.d.ts +37 -0
  40. package/dist/kernel/command-system.js +239 -0
  41. package/dist/kernel/config-schema.d.ts +57 -0
  42. package/dist/kernel/config-schema.js +36 -0
  43. package/dist/kernel/event-bus.d.ts +19 -0
  44. package/dist/kernel/event-bus.js +65 -0
  45. package/dist/kernel/federation/auto-update.d.ts +36 -0
  46. package/dist/kernel/federation/auto-update.js +57 -0
  47. package/dist/kernel/federation/compute-router.d.ts +27 -0
  48. package/dist/kernel/federation/compute-router.js +44 -0
  49. package/dist/kernel/federation/config-sync.d.ts +33 -0
  50. package/dist/kernel/federation/config-sync.js +37 -0
  51. package/dist/kernel/federation/discovery.d.ts +11 -0
  52. package/dist/kernel/federation/discovery.js +44 -0
  53. package/dist/kernel/federation/event-bridge.d.ts +30 -0
  54. package/dist/kernel/federation/event-bridge.js +61 -0
  55. package/dist/kernel/federation/federation-plugin.d.ts +24 -0
  56. package/dist/kernel/federation/federation-plugin.js +35 -0
  57. package/dist/kernel/federation/federation.d.ts +135 -0
  58. package/dist/kernel/federation/federation.js +378 -0
  59. package/dist/kernel/federation/index.d.ts +33 -0
  60. package/dist/kernel/federation/index.js +24 -0
  61. package/dist/kernel/federation/lan-discovery.d.ts +43 -0
  62. package/dist/kernel/federation/lan-discovery.js +135 -0
  63. package/dist/kernel/federation/moltfed-adapter.d.ts +30 -0
  64. package/dist/kernel/federation/moltfed-adapter.js +52 -0
  65. package/dist/kernel/federation/moltfed-connector.d.ts +98 -0
  66. package/dist/kernel/federation/moltfed-connector.js +193 -0
  67. package/dist/kernel/federation/node-identity.d.ts +19 -0
  68. package/dist/kernel/federation/node-identity.js +86 -0
  69. package/dist/kernel/federation/peer-mesh.d.ts +46 -0
  70. package/dist/kernel/federation/peer-mesh.js +117 -0
  71. package/dist/kernel/federation/protocol.d.ts +20 -0
  72. package/dist/kernel/federation/protocol.js +61 -0
  73. package/dist/kernel/federation/role-context.d.ts +5 -0
  74. package/dist/kernel/federation/role-context.js +45 -0
  75. package/dist/kernel/federation/telemetry.d.ts +21 -0
  76. package/dist/kernel/federation/telemetry.js +138 -0
  77. package/dist/kernel/federation/transport-http.d.ts +44 -0
  78. package/dist/kernel/federation/transport-http.js +207 -0
  79. package/dist/kernel/federation/types.d.ts +212 -0
  80. package/dist/kernel/federation/types.js +3 -0
  81. package/dist/kernel/free-providers.d.ts +28 -0
  82. package/dist/kernel/free-providers.js +162 -0
  83. package/dist/kernel/frontend-scoring.d.ts +21 -0
  84. package/dist/kernel/frontend-scoring.js +125 -0
  85. package/dist/kernel/index.d.ts +63 -0
  86. package/dist/kernel/index.js +45 -0
  87. package/dist/kernel/kernel.d.ts +75 -0
  88. package/dist/kernel/kernel.js +223 -0
  89. package/dist/kernel/logger.d.ts +18 -0
  90. package/dist/kernel/logger.js +26 -0
  91. package/dist/kernel/mcp/index.d.ts +9 -0
  92. package/dist/kernel/mcp/index.js +8 -0
  93. package/dist/kernel/mcp/mcp-server.d.ts +27 -0
  94. package/dist/kernel/mcp/mcp-server.js +178 -0
  95. package/dist/kernel/mission-engine.d.ts +42 -0
  96. package/dist/kernel/mission-engine.js +160 -0
  97. package/dist/kernel/orchestrator.d.ts +51 -0
  98. package/dist/kernel/orchestrator.js +226 -0
  99. package/dist/kernel/plugin-manager.d.ts +28 -0
  100. package/dist/kernel/plugin-manager.js +76 -0
  101. package/dist/kernel/plugins/browser-plugin.d.ts +22 -0
  102. package/dist/kernel/plugins/browser-plugin.js +34 -0
  103. package/dist/kernel/plugins/dashboard-plugin.d.ts +17 -0
  104. package/dist/kernel/plugins/dashboard-plugin.js +72 -0
  105. package/dist/kernel/plugins/discord-plugin.d.ts +11 -0
  106. package/dist/kernel/plugins/discord-plugin.js +35 -0
  107. package/dist/kernel/plugins/metrics-plugin.d.ts +33 -0
  108. package/dist/kernel/plugins/metrics-plugin.js +86 -0
  109. package/dist/kernel/plugins/search-plugin.d.ts +17 -0
  110. package/dist/kernel/plugins/search-plugin.js +20 -0
  111. package/dist/kernel/plugins/slack-plugin.d.ts +11 -0
  112. package/dist/kernel/plugins/slack-plugin.js +35 -0
  113. package/dist/kernel/plugins/telegram-plugin.d.ts +20 -0
  114. package/dist/kernel/plugins/telegram-plugin.js +122 -0
  115. package/dist/kernel/policies.d.ts +33 -0
  116. package/dist/kernel/policies.js +105 -0
  117. package/dist/kernel/provider-discovery.d.ts +41 -0
  118. package/dist/kernel/provider-discovery.js +179 -0
  119. package/dist/kernel/provider-manager.d.ts +38 -0
  120. package/dist/kernel/provider-manager.js +206 -0
  121. package/dist/kernel/provider-url.d.ts +18 -0
  122. package/dist/kernel/provider-url.js +45 -0
  123. package/dist/kernel/providers/gemini-provider.d.ts +43 -0
  124. package/dist/kernel/providers/gemini-provider.js +203 -0
  125. package/dist/kernel/providers/ollama-provider.d.ts +44 -0
  126. package/dist/kernel/providers/ollama-provider.js +241 -0
  127. package/dist/kernel/providers/openai-compatible-provider.d.ts +43 -0
  128. package/dist/kernel/providers/openai-compatible-provider.js +233 -0
  129. package/dist/kernel/recovery-manager.d.ts +38 -0
  130. package/dist/kernel/recovery-manager.js +156 -0
  131. package/dist/kernel/router.d.ts +44 -0
  132. package/dist/kernel/router.js +222 -0
  133. package/dist/kernel/sample-missions.d.ts +11 -0
  134. package/dist/kernel/sample-missions.js +132 -0
  135. package/dist/kernel/scheduler.d.ts +30 -0
  136. package/dist/kernel/scheduler.js +147 -0
  137. package/dist/kernel/sdk/harness-sdk.d.ts +37 -0
  138. package/dist/kernel/sdk/harness-sdk.js +48 -0
  139. package/dist/kernel/sdk/plugin-sdk.d.ts +27 -0
  140. package/dist/kernel/sdk/plugin-sdk.js +40 -0
  141. package/dist/kernel/search/search-controller.d.ts +32 -0
  142. package/dist/kernel/search/search-controller.js +141 -0
  143. package/dist/kernel/setup.d.ts +13 -0
  144. package/dist/kernel/setup.js +59 -0
  145. package/dist/kernel/types.d.ts +479 -0
  146. package/dist/kernel/types.js +7 -0
  147. package/dist/kernel/verification-engine.d.ts +33 -0
  148. package/dist/kernel/verification-engine.js +287 -0
  149. package/dist/kernel/worker-runtime.d.ts +66 -0
  150. package/dist/kernel/worker-runtime.js +261 -0
  151. package/dist/kernel/workers/browser-worker.d.ts +6 -0
  152. package/dist/kernel/workers/browser-worker.js +92 -0
  153. package/dist/kernel/workers/builtin-workers.d.ts +20 -0
  154. package/dist/kernel/workers/builtin-workers.js +120 -0
  155. package/dist/kernel/workers/research-worker.d.ts +5 -0
  156. package/dist/kernel/workers/research-worker.js +90 -0
  157. package/dist/prompt-ascii-video-animation.d.ts +2 -0
  158. package/dist/prompt-ascii-video-animation.js +243 -0
  159. package/package.json +43 -9
@@ -0,0 +1,223 @@
1
+ /**
2
+ * OpenKernel — Public Kernel API
3
+ *
4
+ * kernel.execute() / pause() / resume() / cancel() / status()
5
+ * kernel.subscribe() / registerWorker() / registerProvider()
6
+ * kernel.registerPlugin() / registerPolicy()
7
+ *
8
+ * This is the single entry point. Harnesses, CLIs, n8n, bots all go through here.
9
+ */
10
+ import { EventBus } from './event-bus.js';
11
+ import { ProviderManager } from './provider-manager.js';
12
+ import { CapabilityRouter } from './router.js';
13
+ import { WorkerRuntime } from './worker-runtime.js';
14
+ import { Scheduler } from './scheduler.js';
15
+ import { CheckpointEngine } from './checkpoint-engine.js';
16
+ import { MissionEngine } from './mission-engine.js';
17
+ import { Orchestrator } from './orchestrator.js';
18
+ import { PluginManager } from './plugin-manager.js';
19
+ import { PolicyEngine } from './policies.js';
20
+ import { VerificationEngine } from './verification-engine.js';
21
+ import { RecoveryManager } from './recovery-manager.js';
22
+ import { ConsoleLogger } from './logger.js';
23
+ import { ALL_BUILTIN_WORKERS } from './workers/builtin-workers.js';
24
+ import { KernelCommandRegistry } from './command-system.js';
25
+ export class Kernel {
26
+ eventBus;
27
+ providerManager;
28
+ router;
29
+ workerRuntime;
30
+ scheduler;
31
+ checkpoints;
32
+ missionEngine;
33
+ orchestrator;
34
+ plugins;
35
+ policies;
36
+ verification;
37
+ recovery;
38
+ logger;
39
+ /** Canonical OpenKernel slash-command surface (/status, /workers, /goal …). */
40
+ commands;
41
+ missions = new Map();
42
+ constructor(options = {}) {
43
+ this.logger = options.logger ?? new ConsoleLogger();
44
+ this.eventBus = new EventBus();
45
+ this.providerManager = new ProviderManager(this.eventBus, this.logger);
46
+ this.router = new CapabilityRouter(this.logger);
47
+ this.scheduler = new Scheduler(this.eventBus, this.logger);
48
+ this.checkpoints = new CheckpointEngine(this.eventBus, this.logger, options.storageDir);
49
+ this.policies = new PolicyEngine();
50
+ this.verification = new VerificationEngine({
51
+ eventBus: this.eventBus,
52
+ providerManager: this.providerManager,
53
+ logger: this.logger,
54
+ });
55
+ const workerCtx = {
56
+ eventBus: this.eventBus,
57
+ router: this.router,
58
+ providerManager: this.providerManager,
59
+ policies: this.policies,
60
+ logger: this.logger,
61
+ };
62
+ this.workerRuntime = new WorkerRuntime(workerCtx);
63
+ this.recovery = new RecoveryManager({
64
+ eventBus: this.eventBus,
65
+ providerManager: this.providerManager,
66
+ workerRuntime: this.workerRuntime,
67
+ router: this.router,
68
+ logger: this.logger,
69
+ });
70
+ this.missionEngine = new MissionEngine({
71
+ eventBus: this.eventBus,
72
+ scheduler: this.scheduler,
73
+ checkpoints: this.checkpoints,
74
+ policies: this.policies,
75
+ verification: this.verification,
76
+ logger: this.logger,
77
+ });
78
+ this.orchestrator = new Orchestrator({
79
+ eventBus: this.eventBus,
80
+ missionEngine: this.missionEngine,
81
+ scheduler: this.scheduler,
82
+ workerRuntime: this.workerRuntime,
83
+ checkpoints: this.checkpoints,
84
+ providerManager: this.providerManager,
85
+ router: this.router,
86
+ verification: this.verification,
87
+ recovery: this.recovery,
88
+ logger: this.logger,
89
+ });
90
+ this.plugins = new PluginManager(this.eventBus, this.logger);
91
+ this.commands = new KernelCommandRegistry(this);
92
+ if (options.loadBuiltinWorkers ?? true) {
93
+ for (const handler of ALL_BUILTIN_WORKERS) {
94
+ this.workerRuntime.registerHandler(handler);
95
+ }
96
+ }
97
+ }
98
+ async execute(input) {
99
+ const mission = this.missionEngine.create(input);
100
+ this.missions.set(mission.id, mission);
101
+ try {
102
+ await this.orchestrator.run(mission, input);
103
+ }
104
+ catch (err) {
105
+ const message = err instanceof Error ? err.message : String(err);
106
+ this.missionEngine.fail(mission, message);
107
+ throw err;
108
+ }
109
+ return mission;
110
+ }
111
+ async pause(missionId) {
112
+ const mission = this.missions.get(missionId);
113
+ if (!mission)
114
+ throw new Error(`Mission not found: ${missionId}`);
115
+ this.orchestrator.pauseMission(missionId);
116
+ this.missionEngine.pause(mission);
117
+ }
118
+ async resume(missionId) {
119
+ const mission = this.missions.get(missionId);
120
+ if (!mission)
121
+ throw new Error(`Mission not found: ${missionId}`);
122
+ this.orchestrator.resumeMission(missionId);
123
+ this.missionEngine.resume(mission);
124
+ // continue execution
125
+ await this.orchestrator.run(mission, {
126
+ description: mission.description,
127
+ goal: mission.goal,
128
+ });
129
+ return mission;
130
+ }
131
+ async cancel(missionId) {
132
+ const mission = this.missions.get(missionId);
133
+ if (!mission)
134
+ return;
135
+ this.orchestrator.cancelMission(missionId);
136
+ this.missionEngine.cancel(mission);
137
+ }
138
+ async status(missionId) {
139
+ const mission = this.missions.get(missionId);
140
+ if (!mission)
141
+ throw new Error(`Mission not found: ${missionId}`);
142
+ return mission.status;
143
+ }
144
+ /**
145
+ * Execute a canonical OpenKernel slash-command (e.g. "/status", "/goal build X").
146
+ * The same registry backs the CLI console and the notification plugins.
147
+ */
148
+ async command(input) {
149
+ return this.commands.execute(input);
150
+ }
151
+ /** Reset a mission's failed/skipped tasks and re-run them. */
152
+ async retry(missionId) {
153
+ const mission = this.missions.get(missionId);
154
+ if (!mission)
155
+ throw new Error(`Mission not found: ${missionId}`);
156
+ for (const task of mission.tasks) {
157
+ if (task.status === 'FAILED' || task.status === 'SKIPPED') {
158
+ task.status = 'PENDING';
159
+ task.attempts = 0;
160
+ task.error = undefined;
161
+ task.output = undefined;
162
+ task.startedAt = undefined;
163
+ task.completedAt = undefined;
164
+ }
165
+ }
166
+ this.orchestrator.resumeMission(missionId);
167
+ await this.orchestrator.run(mission, {
168
+ description: mission.description,
169
+ goal: mission.goal,
170
+ });
171
+ return mission;
172
+ }
173
+ subscribe(types, handler) {
174
+ return this.eventBus.on(types, handler);
175
+ }
176
+ subscribeAll(handler) {
177
+ return this.eventBus.onAll(handler);
178
+ }
179
+ registerWorker(definition) {
180
+ this.workerRuntime.registerWorker(definition);
181
+ }
182
+ registerProvider(providerId, provider) {
183
+ this.providerManager.register(providerId, provider);
184
+ }
185
+ async registerPlugin(plugin) {
186
+ await this.plugins.registerWithContext(plugin, this);
187
+ }
188
+ registerPolicy(policy) {
189
+ this.policies.register(policy);
190
+ }
191
+ /** Set the default policy used for routing when a mission doesn't specify one. */
192
+ setDefaultPolicy(name) {
193
+ this.workerRuntime.setDefaultPolicy(name);
194
+ }
195
+ getMission(missionId) {
196
+ return this.missions.get(missionId);
197
+ }
198
+ listMissions() {
199
+ return [...this.missions.values()];
200
+ }
201
+ /** Emit a NOTIFICATION event that plugins (Telegram/Discord/Slack) can consume. */
202
+ notify(message, missionId) {
203
+ this.eventBus.emit({
204
+ type: 'NOTIFICATION',
205
+ timestamp: Date.now(),
206
+ missionId,
207
+ data: { message },
208
+ });
209
+ }
210
+ listPlugins() {
211
+ return this.plugins.listPlugins();
212
+ }
213
+ getEventHistory() {
214
+ return this.eventBus.getHistory();
215
+ }
216
+ destroy() {
217
+ this.providerManager.destroy();
218
+ this.plugins.destroy();
219
+ }
220
+ }
221
+ export function createKernel(options) {
222
+ return new Kernel(options ?? {});
223
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * OpenKernel — Logger
3
+ */
4
+ import type { Logger } from './types.js';
5
+ export declare class ConsoleLogger implements Logger {
6
+ private prefix;
7
+ constructor(prefix?: string);
8
+ debug(message: string, ...args: unknown[]): void;
9
+ info(message: string, ...args: unknown[]): void;
10
+ warn(message: string, ...args: unknown[]): void;
11
+ error(message: string, ...args: unknown[]): void;
12
+ }
13
+ export declare class SilentLogger implements Logger {
14
+ debug(): void;
15
+ info(): void;
16
+ warn(): void;
17
+ error(): void;
18
+ }
@@ -0,0 +1,26 @@
1
+ export class ConsoleLogger {
2
+ prefix;
3
+ constructor(prefix = 'openkernel') {
4
+ this.prefix = prefix;
5
+ }
6
+ debug(message, ...args) {
7
+ if (process.env.OPENKERNEL_DEBUG === '1') {
8
+ console.debug(`[${this.prefix}] ${message}`, ...args);
9
+ }
10
+ }
11
+ info(message, ...args) {
12
+ console.log(`[${this.prefix}] ${message}`, ...args);
13
+ }
14
+ warn(message, ...args) {
15
+ console.warn(`[${this.prefix}] ${message}`, ...args);
16
+ }
17
+ error(message, ...args) {
18
+ console.error(`[${this.prefix}] ${message}`, ...args);
19
+ }
20
+ }
21
+ export class SilentLogger {
22
+ debug() { }
23
+ info() { }
24
+ warn() { }
25
+ error() { }
26
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * OpenKernel — MCP public API
3
+ *
4
+ * North-facing control surface: an MCP server exposing spawn/dispatch/command/
5
+ * role/voice/map tools over the federation mesh, so any MCP host drives the
6
+ * fleet with a standard protocol.
7
+ */
8
+ export { createMcpServer, serveMcpStdio } from './mcp-server.js';
9
+ export type { McpServerDeps } from './mcp-server.js';
@@ -0,0 +1,8 @@
1
+ /**
2
+ * OpenKernel — MCP public API
3
+ *
4
+ * North-facing control surface: an MCP server exposing spawn/dispatch/command/
5
+ * role/voice/map tools over the federation mesh, so any MCP host drives the
6
+ * fleet with a standard protocol.
7
+ */
8
+ export { createMcpServer, serveMcpStdio } from './mcp-server.js';
@@ -0,0 +1,27 @@
1
+ /**
2
+ * OpenKernel — MCP Server
3
+ *
4
+ * The north-facing control surface. Any MCP host (InfiniBot, Claude Code,
5
+ * Cursor…) connects over stdio and drives infinicode's mesh with standard MCP
6
+ * tools: spawn agents on devices, dispatch by capability, run commands, manage
7
+ * per-device role context, speak via voice, and get the live mesh map.
8
+ *
9
+ * Real-time activity/telemetry for harness animation is served over the
10
+ * federation SSE endpoint (returned by `stream_info`), keeping tool calls small
11
+ * and the animation feed lightweight — the same split InfiniBot uses.
12
+ */
13
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
14
+ import type { KernelLike, Logger } from '../types.js';
15
+ import type { Federation } from '../federation/index.js';
16
+ import type { GoalLoop } from '../autonomy/index.js';
17
+ export interface McpServerDeps {
18
+ kernel: KernelLike;
19
+ federation: Federation;
20
+ logger: Logger;
21
+ version: string;
22
+ /** Optional autonomy loop — enables the goal management tools when present. */
23
+ autonomy?: GoalLoop;
24
+ }
25
+ export declare function createMcpServer(deps: McpServerDeps): McpServer;
26
+ /** Start the MCP server over stdio (the transport MCP hosts spawn). */
27
+ export declare function serveMcpStdio(deps: McpServerDeps): Promise<McpServer>;
@@ -0,0 +1,178 @@
1
+ /**
2
+ * OpenKernel — MCP Server
3
+ *
4
+ * The north-facing control surface. Any MCP host (InfiniBot, Claude Code,
5
+ * Cursor…) connects over stdio and drives infinicode's mesh with standard MCP
6
+ * tools: spawn agents on devices, dispatch by capability, run commands, manage
7
+ * per-device role context, speak via voice, and get the live mesh map.
8
+ *
9
+ * Real-time activity/telemetry for harness animation is served over the
10
+ * federation SSE endpoint (returned by `stream_info`), keeping tool calls small
11
+ * and the animation feed lightweight — the same split InfiniBot uses.
12
+ */
13
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
14
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
15
+ import { z } from 'zod';
16
+ const text = (v) => ({
17
+ content: [{ type: 'text', text: typeof v === 'string' ? v : JSON.stringify(v, null, 2) }],
18
+ });
19
+ export function createMcpServer(deps) {
20
+ const { kernel, federation } = deps;
21
+ const server = new McpServer({ name: 'infinicode', version: deps.version });
22
+ // ── Mesh map + telemetry ───────────────────────────────────────────────────
23
+ server.registerTool('list_nodes', {
24
+ title: 'List mesh nodes',
25
+ description: 'All devices in the mesh with role, capabilities, connection state, and load.',
26
+ inputSchema: {},
27
+ }, async () => text(federation.nodeStatuses()));
28
+ server.registerTool('node_status', {
29
+ title: 'Node status',
30
+ description: 'One node\'s capabilities, commands, and latest hardware snapshot.',
31
+ inputSchema: { nodeId: z.string().describe('target node id') },
32
+ }, async ({ nodeId }) => {
33
+ const status = federation.nodeStatuses().find(s => s.nodeId === nodeId);
34
+ const peer = federation.peers().find(p => p.nodeId === nodeId);
35
+ return text({ status, hardware: peer?.hardware });
36
+ });
37
+ // ── Spawn + dispatch (parallel agents across devices, no SSH) ───────────────
38
+ server.registerTool('spawn_agent', {
39
+ title: 'Spawn agent on a device',
40
+ description: 'Hand a task to a device\'s local agent (by name or id). Non-blocking: returns a runId immediately — use follow_task to monitor. Pass wait:true to block until done (short tasks). Runs on the target with its persistent role.',
41
+ inputSchema: {
42
+ task: z.string().describe('what the agent should do'),
43
+ device: z.string().optional().describe('target device name or node id'),
44
+ capabilities: z.array(z.string()).optional().describe('required capabilities, e.g. ["coding"]'),
45
+ role: z.string().optional().describe('override the role context for this task'),
46
+ wait: z.boolean().optional().describe('block until the run finishes (default false)'),
47
+ },
48
+ }, async ({ task, device, capabilities, role, wait }) => {
49
+ const t = {
50
+ description: task.slice(0, 80),
51
+ prompt: task,
52
+ capabilities: (capabilities ?? []),
53
+ role,
54
+ };
55
+ const res = await federation.dispatch(t, { preferName: device, preferNodeId: device }, { wait });
56
+ if (!res)
57
+ return text({ ok: false, error: 'no capable device online for this task' });
58
+ return text({ ok: true, peerId: res.peerId, runId: res.runId, status: res.record.status, record: res.record });
59
+ });
60
+ server.registerTool('dispatch', {
61
+ title: 'Dispatch to best device',
62
+ description: 'Route a task to the best-fit device by capability + load (no device named). Non-blocking; returns a runId. Pass wait:true to block.',
63
+ inputSchema: {
64
+ task: z.string(),
65
+ capabilities: z.array(z.string()).optional(),
66
+ wait: z.boolean().optional(),
67
+ },
68
+ }, async ({ task, capabilities, wait }) => {
69
+ const res = await federation.dispatch({ description: task.slice(0, 80), prompt: task, capabilities: (capabilities ?? []) }, undefined, { wait });
70
+ return text(res ? { ok: true, peerId: res.peerId, runId: res.runId, status: res.record.status, record: res.record } : { ok: false, error: 'no capable device' });
71
+ });
72
+ server.registerTool('follow_task', {
73
+ title: 'Follow a run',
74
+ description: 'Get the current status + result of a dispatched run (by runId), plus recent activity frames for rendering.',
75
+ inputSchema: { runId: z.string() },
76
+ }, async ({ runId }) => {
77
+ const followed = await federation.followRun(runId);
78
+ if (!followed)
79
+ return text({ ok: false, error: 'unknown run' });
80
+ return text({ ok: true, record: followed.record, frames: followed.frames.length });
81
+ });
82
+ // ── Commands + lifecycle (local or targeted) ────────────────────────────────
83
+ server.registerTool('run_command', {
84
+ title: 'Run a slash command',
85
+ description: 'Run an OpenKernel slash command locally, or on a specific node.',
86
+ inputSchema: {
87
+ input: z.string().describe('e.g. "/status" or "/goal build X"'),
88
+ nodeId: z.string().optional().describe('target node; omit for local'),
89
+ },
90
+ }, async ({ input, nodeId }) => {
91
+ if (nodeId)
92
+ return text(await federation.runCommandOn(nodeId, input));
93
+ return text(await kernel.command(input));
94
+ });
95
+ // ── Role context (persistent per-device identity + architecture) ────────────
96
+ server.registerTool('get_role', {
97
+ title: 'Get device role',
98
+ description: 'Read a device\'s persistent role + server-architecture context.',
99
+ inputSchema: { nodeId: z.string().optional().describe('target node; omit for local') },
100
+ }, async ({ nodeId }) => text(nodeId ? await federation.getRoleOf(nodeId) : federation.getRole()));
101
+ server.registerTool('set_role', {
102
+ title: 'Set device role',
103
+ description: 'Persist a device\'s role + architecture so spawned agents are proactive and context-aware.',
104
+ inputSchema: {
105
+ role: z.string().describe('e.g. "RoboPanda"'),
106
+ architecture: z.string().optional().describe('this device\'s job + the wider system'),
107
+ nodeId: z.string().optional().describe('target node; omit for local'),
108
+ },
109
+ }, async ({ role, architecture, nodeId }) => {
110
+ const payload = { role, architecture };
111
+ return text(nodeId ? await federation.setRoleOf(nodeId, payload) : federation.setRole(payload));
112
+ });
113
+ // ── Voice (LiveKit intent — media plane handles TTS) ────────────────────────
114
+ server.registerTool('speak', {
115
+ title: 'Speak (voice mode)',
116
+ description: 'Emit a voice-mode response intent for the media plane (LiveKit/TTS) to speak in a room.',
117
+ inputSchema: {
118
+ text: z.string(),
119
+ room: z.string().optional().describe('LiveKit room / device to speak on'),
120
+ },
121
+ }, async ({ text: say, room }) => {
122
+ kernel.notify(`[voice${room ? ':' + room : ''}] ${say}`);
123
+ return text({ ok: true, spoken: say, room });
124
+ });
125
+ // ── Autonomy (proactive goals) — only if a goal loop is wired ───────────────
126
+ if (deps.autonomy) {
127
+ const auto = deps.autonomy;
128
+ server.registerTool('add_goal', {
129
+ title: 'Add a proactive goal',
130
+ description: 'Give this node a standing goal that runs unattended — every N seconds, after an idle period, or once. Runs with the device\'s role context.',
131
+ inputSchema: {
132
+ prompt: z.string().describe('the goal, e.g. "check camera feed for people and greet them"'),
133
+ everyMs: z.number().optional().describe('interval trigger: run every N ms'),
134
+ idleMs: z.number().optional().describe('idle trigger: run after N ms of no activity'),
135
+ once: z.boolean().optional().describe('run exactly once at start'),
136
+ capabilities: z.array(z.string()).optional(),
137
+ },
138
+ }, async ({ prompt, everyMs, idleMs, once, capabilities }) => {
139
+ const trigger = everyMs
140
+ ? { kind: 'interval', everyMs }
141
+ : idleMs
142
+ ? { kind: 'idle', afterMs: idleMs }
143
+ : { kind: 'once' };
144
+ void once; // 'once' is the default when no interval/idle given
145
+ const goal = auto.add({ prompt, capabilities: (capabilities ?? []), trigger });
146
+ return text({ ok: true, goalId: goal.id, trigger: goal.trigger });
147
+ });
148
+ server.registerTool('list_goals', {
149
+ title: 'List proactive goals',
150
+ description: 'All standing goals on this node with their triggers + run counts.',
151
+ inputSchema: {},
152
+ }, async () => text(auto.list().map(g => ({ id: g.id, prompt: g.prompt, trigger: g.trigger, runCount: g.runCount, enabled: g.enabled }))));
153
+ server.registerTool('remove_goal', {
154
+ title: 'Remove a proactive goal',
155
+ description: 'Stop and remove a standing goal by id.',
156
+ inputSchema: { goalId: z.string() },
157
+ }, async ({ goalId }) => text({ ok: auto.remove(goalId) }));
158
+ }
159
+ // ── Live activity stream (for harness animation / event rendering) ──────────
160
+ server.registerTool('stream_info', {
161
+ title: 'Activity stream info',
162
+ description: 'Where to connect for the live activity + telemetry feed (SSE), plus a snapshot of recent frames for immediate rendering.',
163
+ inputSchema: {},
164
+ }, async () => text({
165
+ sse: '/fed/stream',
166
+ note: 'Connect to any mesh node\'s /fed/stream for real-time frames (t=ev|hw|hb|nd|rt|log).',
167
+ recent: federation.recentFrames(40),
168
+ }));
169
+ return server;
170
+ }
171
+ /** Start the MCP server over stdio (the transport MCP hosts spawn). */
172
+ export async function serveMcpStdio(deps) {
173
+ const server = createMcpServer(deps);
174
+ const transport = new StdioServerTransport();
175
+ await server.connect(transport);
176
+ deps.logger.info('[mcp] stdio server connected');
177
+ return server;
178
+ }
@@ -0,0 +1,42 @@
1
+ import type { Logger, Mission, MissionInput } from './types.js';
2
+ import type { EventBus } from './event-bus.js';
3
+ import type { Scheduler } from './scheduler.js';
4
+ import type { CheckpointEngine } from './checkpoint-engine.js';
5
+ import type { PolicyEngine } from './policies.js';
6
+ import type { VerificationEngine } from './verification-engine.js';
7
+ export interface MissionEngineDeps {
8
+ eventBus: EventBus;
9
+ scheduler: Scheduler;
10
+ checkpoints: CheckpointEngine;
11
+ policies: PolicyEngine;
12
+ verification?: VerificationEngine;
13
+ logger: Logger;
14
+ }
15
+ export declare class MissionEngine {
16
+ private deps;
17
+ constructor(deps: MissionEngineDeps);
18
+ create(input: MissionInput): Mission;
19
+ plan(mission: Mission, input: MissionInput): Mission;
20
+ start(mission: Mission): Mission;
21
+ pause(mission: Mission): Mission;
22
+ resume(mission: Mission): Mission;
23
+ cancel(mission: Mission): Mission;
24
+ complete(mission: Mission): Mission;
25
+ /**
26
+ * Mission-level verification during the VERIFYING phase.
27
+ * Runs the Verification Engine pipeline for every completed task that
28
+ * has output, then completes the mission only if all checks pass (or
29
+ * verification is not strict). Returns the aggregated result.
30
+ */
31
+ verify(mission: Mission): Promise<{
32
+ passed: boolean;
33
+ summary: string;
34
+ }>;
35
+ fail(mission: Mission, error: string): Mission;
36
+ /**
37
+ * Resync mission state from a checkpoint (crash recovery).
38
+ */
39
+ restoreFromCheckpoint(mission: Mission): Mission;
40
+ private transition;
41
+ private emit;
42
+ }