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
package/dist/cli.js CHANGED
@@ -5,24 +5,25 @@ import Conf from 'conf';
5
5
  import { setupMaster } from './commands/setup.js';
6
6
  import { runAgent } from './commands/run.js';
7
7
  import { showStatus } from './commands/status.js';
8
- import { listModels } from './commands/models.js';
9
- const VERSION = '1.0.0';
8
+ import { listModels, pullAllModels } from './commands/models.js';
9
+ import { missionRun, missionStatus, missionList, missionResume, missionCancel } from './commands/mission.js';
10
+ import { SAMPLE_MISSIONS } from './kernel/sample-missions.js';
11
+ import { kernelSetupWizard } from './commands/kernel-setup.js';
12
+ import { workersList, workersEdit, workersReset } from './commands/workers.js';
13
+ import { providersList, providersAdd, providersRemove, providersTest } from './commands/providers.js';
14
+ import { consoleRepl, consoleRun } from './commands/console.js';
15
+ import { serve } from './commands/serve.js';
16
+ import { mcpCommand } from './commands/mcp.js';
17
+ import { DEFAULT_CONFIG } from './kernel/config-schema.js';
18
+ const VERSION = '2.1.0';
10
19
  const config = new Conf({
11
20
  projectName: 'infinicode',
12
- defaults: {
13
- masterUrl: 'http://localhost:11434',
14
- defaultModel: 'qwen2.5-coder:14b',
15
- theme: 'infini'
16
- }
21
+ defaults: DEFAULT_CONFIG,
17
22
  });
18
23
  const program = new Command();
19
- console.log(chalk.cyan(`
20
- ⚡ ${chalk.bold('INFINICODE')} v${VERSION}
21
- ${chalk.dim('AI Coding Agent • Powered by Ollama')}
22
- `));
23
24
  program
24
25
  .name('infinicode')
25
- .description('AI coding agent powered by your local Ollama')
26
+ .description('AI coding agent powered by the OpenKernel execution runtime')
26
27
  .version(VERSION);
27
28
  // Quick connect command
28
29
  program
@@ -31,8 +32,10 @@ program
31
32
  .description('Quick connect to Ollama master (e.g., infinicode connect 192.168.1.100)')
32
33
  .option('-p, --port <port>', 'Ollama port', '11434')
33
34
  .option('-m, --model <model>', 'Default model', 'qwen2.5-coder:14b')
35
+ .option('--tailscale <host>', 'Tailscale fallback host/IP for the same Ollama master')
36
+ .option('--tailscale-port <port>', 'Tailscale fallback Ollama port')
34
37
  .action(async (masterIp, options) => {
35
- await setupMaster(masterIp, options.port, options.model, config);
38
+ await setupMaster(masterIp, options.port, options.model, config, options.tailscale, options.tailscalePort);
36
39
  });
37
40
  // Setup wizard
38
41
  program
@@ -59,25 +62,24 @@ program
59
62
  name: 'model',
60
63
  message: 'Default model:',
61
64
  default: 'qwen2.5-coder:14b'
65
+ },
66
+ {
67
+ type: 'input',
68
+ name: 'tailscaleIp',
69
+ message: 'Tailscale fallback IP/host (optional):',
70
+ default: ''
62
71
  }
63
72
  ]);
64
- await setupMaster(answers.masterIp, answers.port, answers.model, config);
73
+ await setupMaster(answers.masterIp, answers.port, answers.model, config, answers.tailscaleIp || undefined);
65
74
  });
66
- // Run the agent (main command)
75
+ // Run the agent (main command) — launches the infinicode TUI with the full provider pool
67
76
  program
68
77
  .command('run', { isDefault: true })
69
78
  .alias('r')
70
- .description('Start the coding agent')
71
- .option('-m, --model <model>', 'Model to use')
72
- .option('--no-tui', 'Disable TUI, use simple mode')
79
+ .description('Start the infinicode TUI (full provider pool: Ollama + cloud providers)')
80
+ .option('-m, --model <model>', 'Override the default model')
73
81
  .action(async (options) => {
74
- const masterUrl = config.get('masterUrl');
75
- const model = options.model || config.get('defaultModel');
76
- if (!masterUrl || masterUrl === 'http://localhost:11434') {
77
- console.log(chalk.yellow('\n⚠️ No master configured. Using localhost.'));
78
- console.log(chalk.dim(' Run: infinicode connect <master-ip>\n'));
79
- }
80
- await runAgent(masterUrl, model, options.tui !== false, config);
82
+ await runAgent(config.get('masterUrl'), options.model ?? config.get('defaultModel'), true, config);
81
83
  });
82
84
  // Status command
83
85
  program
@@ -91,7 +93,12 @@ program
91
93
  .command('models')
92
94
  .alias('m')
93
95
  .description('List available models on master')
94
- .action(async () => {
96
+ .option('--pull-all', 'Pull every model returned by the selected master')
97
+ .action(async (options) => {
98
+ if (options.pullAll) {
99
+ await pullAllModels(config);
100
+ return;
101
+ }
95
102
  await listModels(config);
96
103
  });
97
104
  // Config commands
@@ -135,32 +142,174 @@ program
135
142
  }
136
143
  console.log();
137
144
  });
138
- // Passthrough to opencode
145
+ // ── OpenKernel: mission command ──────────────────────────────────────────
146
+ const missionCmd = program
147
+ .command('mission')
148
+ .alias('k')
149
+ .description('OpenKernel mission-driven execution');
150
+ missionCmd
151
+ .command('run')
152
+ .description('Execute a mission through the kernel')
153
+ .option('-g, --goal <goal>', 'Mission goal (required unless --sample)')
154
+ .option('-n, --name <name>', 'Mission name')
155
+ .option('-d, --description <desc>', 'Mission description')
156
+ .option('-t, --task <desc...>', 'Task description (repeatable)')
157
+ .option('-c, --cap <caps...>', 'Capabilities per task (comma-separated, repeatable)')
158
+ .option('-p, --policy <policy>', 'Policy name (free-first, fastest, highest-quality, local-first, privacy-first, balanced, offline)')
159
+ .option('-s, --sample <name>', 'Run a built-in sample mission (overrides other options)')
160
+ .action(async (opts) => {
161
+ if (!opts.sample && !opts.goal) {
162
+ console.log(chalk.red('Error: --goal is required unless --sample is provided'));
163
+ process.exit(1);
164
+ }
165
+ await missionRun(config, { goal: opts.goal ?? '', ...opts });
166
+ });
167
+ missionCmd
168
+ .command('samples')
169
+ .description('List built-in sample missions')
170
+ .action(() => {
171
+ console.log(chalk.bold('\nSample Missions'));
172
+ console.log(chalk.dim('-'.repeat(40)));
173
+ for (const [name, m] of Object.entries(SAMPLE_MISSIONS)) {
174
+ console.log(` ${chalk.cyan(name)} ${chalk.dim(m.description)}`);
175
+ }
176
+ console.log();
177
+ });
178
+ missionCmd
179
+ .command('status <missionId>')
180
+ .description('Show mission status')
181
+ .action(async (missionId) => {
182
+ await missionStatus(config, missionId);
183
+ });
184
+ missionCmd
185
+ .command('list')
186
+ .description('List missions in this session')
187
+ .action(async () => {
188
+ await missionList(config);
189
+ });
190
+ missionCmd
191
+ .command('resume <missionId>')
192
+ .description('Resume a paused mission')
193
+ .action(async (missionId) => {
194
+ await missionResume(config, missionId);
195
+ });
196
+ missionCmd
197
+ .command('cancel <missionId>')
198
+ .description('Cancel a running mission')
199
+ .action(async (missionId) => {
200
+ await missionCancel(config, missionId);
201
+ });
202
+ // ── OpenKernel: friendly setup wizard ──────────────────────────────────────
139
203
  program
140
- .command('opencode [args...]')
141
- .description('Run opencode directly with Ollama config injected')
142
- .allowUnknownOption()
143
- .action(async (args) => {
144
- const { execa } = await import('execa');
145
- const masterUrl = config.get('masterUrl');
146
- process.env.LOCAL_ENDPOINT = `${masterUrl}/v1`;
147
- process.env.OPENCODE_CONFIG_CONTENT = JSON.stringify({
148
- providers: {
149
- anthropic: { disabled: true },
150
- openai: { disabled: true },
151
- gemini: { disabled: true },
152
- local: { apiKey: 'not-needed' }
153
- }
154
- });
155
- try {
156
- await execa('opencode', args, {
157
- stdio: 'inherit',
158
- env: process.env
159
- });
204
+ .command('kernel-setup')
205
+ .alias('ks')
206
+ .description('Friendly interactive setup wizard — providers + worker models + policy')
207
+ .action(async () => {
208
+ await kernelSetupWizard(config);
209
+ });
210
+ // ── OpenKernel: worker model preferences ──────────────────────────────────
211
+ const workersCmd = program
212
+ .command('workers')
213
+ .alias('w')
214
+ .description('View + edit per-worker model preferences');
215
+ workersCmd
216
+ .command('list', { isDefault: true })
217
+ .description('Show current worker model pins')
218
+ .action(async () => {
219
+ await workersList(config);
220
+ });
221
+ workersCmd
222
+ .command('edit')
223
+ .alias('e')
224
+ .description('Interactively pick a model for each worker type')
225
+ .action(async () => {
226
+ await workersEdit(config);
227
+ });
228
+ workersCmd
229
+ .command('reset')
230
+ .description('Clear all worker pins (router decides for every worker type)')
231
+ .action(async () => {
232
+ await workersReset(config);
233
+ });
234
+ // ── OpenKernel: providers ──────────────────────────────────────────────────
235
+ const providersCmd = program
236
+ .command('providers')
237
+ .alias('p')
238
+ .description('View + edit cloud provider credentials');
239
+ providersCmd
240
+ .command('list', { isDefault: true })
241
+ .description('List configured providers')
242
+ .action(async () => {
243
+ await providersList(config);
244
+ });
245
+ providersCmd
246
+ .command('add')
247
+ .description('Add a cloud provider (Groq, OpenRouter, GitHub, NVIDIA, HF, Gemini)')
248
+ .action(async () => {
249
+ await providersAdd(config);
250
+ });
251
+ providersCmd
252
+ .command('remove <id>')
253
+ .description('Remove a cloud provider')
254
+ .action(async (id) => {
255
+ await providersRemove(config, id);
256
+ });
257
+ providersCmd
258
+ .command('test [id]')
259
+ .description('Test connection to one or all providers')
260
+ .action(async (id) => {
261
+ await providersTest(config, id);
262
+ });
263
+ // ── OpenKernel: command console ────────────────────────────────────────────
264
+ program
265
+ .command('console [command...]')
266
+ .alias('x')
267
+ .description('Interactive OpenKernel command console (/status, /workers, /goal …). Pass a /command to run once and exit.')
268
+ .action(async (command) => {
269
+ const joined = (command ?? []).join(' ').trim();
270
+ if (joined) {
271
+ await consoleRun(config, joined);
160
272
  }
161
- catch (e) {
162
- if (e.exitCode)
163
- process.exit(e.exitCode);
273
+ else {
274
+ await consoleRepl(config);
164
275
  }
165
276
  });
277
+ // ── OpenKernel: federation mesh node ───────────────────────────────────────
278
+ program
279
+ .command('serve')
280
+ .description('Run this device as a federation mesh node (LAN + Tailscale)')
281
+ .option('--role <role>', 'node role: hub | peer | satellite | relay')
282
+ .option('--hub', 'shorthand for --role hub')
283
+ .option('--name <name>', 'friendly node name (defaults to hostname)')
284
+ .option('--port <port>', 'mesh listen port (default 47913)')
285
+ .option('--host <host>', 'bind host (default 0.0.0.0)')
286
+ .option('--token <token>', 'shared bearer token peers must present')
287
+ .option('--seed <url...>', 'peer base URL(s) to connect to on start')
288
+ .option('--auto-update', 'accept auto-updates announced by a hub/relay')
289
+ .option('--tailscale', 'auto-discover + connect peers over Tailscale')
290
+ .option('--lan', 'auto-discover + connect peers on the same LAN via UDP broadcast (no seed/Tailscale needed)')
291
+ .option('--lan-port <port>', 'UDP discovery port for --lan (default 47915)')
292
+ .option('--tag <tag>', 'only discover peers carrying this tag (Tailscale ACL tag or LAN beacon tag)')
293
+ .option('--gateway <url>', 'link to an InfiniBot gateway (ws://host:18789) — appear on its neural-mesh map')
294
+ .option('--gateway-token <token>', 'auth token for the InfiniBot gateway')
295
+ .option('--gateway-password <password>', 'auth password for the InfiniBot gateway')
296
+ .action(async (opts) => {
297
+ await serve(config, opts);
298
+ });
299
+ // ── OpenKernel: MCP control server (stdio) ─────────────────────────────────
300
+ program
301
+ .command('mcp')
302
+ .description('Run the MCP control server (stdio) + a mesh node — spawn/dispatch/role/voice/map tools for any MCP host')
303
+ .option('--role <role>', 'node role: hub | peer | satellite | relay')
304
+ .option('--name <name>', 'friendly node name')
305
+ .option('--mesh-port <port>', 'in-process mesh port (default: serve port + 1)')
306
+ .option('--token <token>', 'shared bearer token peers must present')
307
+ .option('--seed <url...>', 'peer base URL(s) to connect to on start')
308
+ .option('--tailscale', 'auto-discover + connect peers over Tailscale')
309
+ .option('--lan', 'auto-discover + connect peers on the same LAN via UDP broadcast (no seed/Tailscale needed)')
310
+ .option('--lan-port <port>', 'UDP discovery port for --lan (default 47915)')
311
+ .option('--tag <tag>', 'only discover peers carrying this tag (Tailscale ACL tag or LAN beacon tag)')
312
+ .action(async (opts) => {
313
+ await mcpCommand(config, opts);
314
+ });
166
315
  program.parse();
@@ -0,0 +1,6 @@
1
+ import type Conf from 'conf';
2
+ import type { InfinicodeConfig } from '../kernel/setup.js';
3
+ /** One-shot: run a single command against a fresh kernel and exit. */
4
+ export declare function consoleRun(config: Conf<InfinicodeConfig>, command: string): Promise<void>;
5
+ /** Interactive REPL over a persistent kernel. */
6
+ export declare function consoleRepl(config: Conf<InfinicodeConfig>): Promise<void>;
@@ -0,0 +1,111 @@
1
+ /**
2
+ * infinicode console — interactive OpenKernel command console.
3
+ *
4
+ * Exposes the canonical OpenKernel slash-command surface (/status, /workers,
5
+ * /logs, /pause, /resume, /retry, /models, /providers, /checkpoints, /goal …)
6
+ * over a live kernel. The SAME registry backs the notification plugins, so what
7
+ * you type here behaves identically to a Telegram/Discord command.
8
+ *
9
+ * infinicode console REPL (type /help)
10
+ * infinicode console /status one-shot dispatch, prints result, exits
11
+ * infinicode console /goal build X run a goal, print the result
12
+ */
13
+ import chalk from 'chalk';
14
+ import readline from 'node:readline';
15
+ import { buildKernelFromConfig } from '../kernel/setup.js';
16
+ import { SilentLogger } from '../kernel/index.js';
17
+ /** Commands whose output depends on provider health being probed first. */
18
+ const PROVIDER_DEPENDENT = new Set(['status', 'providers', 'p', 'models', 'm']);
19
+ /**
20
+ * Wait until every provider has been health-checked once (or a timeout).
21
+ * Health checks are kicked off at registration and run in the background, so a
22
+ * one-shot command would otherwise read a "0 healthy" snapshot before they land.
23
+ */
24
+ async function waitForProviders(kernel, timeoutMs = 3500) {
25
+ const start = Date.now();
26
+ const total = kernel.providerManager.listInfos().length;
27
+ while (Date.now() - start < timeoutMs) {
28
+ const checked = kernel.providerManager.listInfos().filter(p => p.lastCheckedAt).length;
29
+ if (total > 0 && checked >= total)
30
+ return;
31
+ await new Promise(r => setTimeout(r, 150));
32
+ }
33
+ }
34
+ function render(result) {
35
+ const mark = result.ok ? chalk.green('✔') : chalk.red('✖');
36
+ const body = result.text.split('\n');
37
+ console.log(`${mark} ${body[0] ?? ''}`);
38
+ for (const line of body.slice(1))
39
+ console.log(' ' + line);
40
+ }
41
+ /** One-shot: run a single command against a fresh kernel and exit. */
42
+ export async function consoleRun(config, command) {
43
+ const kernel = buildKernelFromConfig(config, { logger: new SilentLogger() });
44
+ try {
45
+ const name = command.trim().replace(/^\//, '').split(/\s+/)[0]?.toLowerCase();
46
+ if (name && PROVIDER_DEPENDENT.has(name))
47
+ await waitForProviders(kernel);
48
+ const result = await kernel.command(command);
49
+ render(result);
50
+ process.exitCode = result.ok ? 0 : 1;
51
+ }
52
+ finally {
53
+ kernel.destroy();
54
+ }
55
+ }
56
+ /** Interactive REPL over a persistent kernel. */
57
+ export async function consoleRepl(config) {
58
+ const kernel = buildKernelFromConfig(config, { logger: new SilentLogger() });
59
+ console.log(chalk.bold('\nOpenKernel Console'));
60
+ console.log(chalk.dim('Type a /command (e.g. /status, /goal build a todo app). /help lists all. Ctrl-C or /exit to quit.\n'));
61
+ // Mirror live kernel events dimmed above the prompt so long-running missions
62
+ // (/goal, /retry) stream progress instead of going silent.
63
+ const unsub = kernel.subscribeAll((event) => {
64
+ if (event.type === 'PROVIDER_HEALTH')
65
+ return;
66
+ const tag = event.taskId ? `${event.missionId}/${event.taskId}` : event.missionId ?? '';
67
+ process.stdout.write(chalk.dim(` · ${event.type}${tag ? ' ' + tag : ''}\n`));
68
+ });
69
+ const rl = readline.createInterface({
70
+ input: process.stdin,
71
+ output: process.stdout,
72
+ prompt: chalk.hex('#FFD86B')('openkernel› '),
73
+ });
74
+ const shutdown = () => {
75
+ unsub();
76
+ rl.close();
77
+ kernel.destroy();
78
+ };
79
+ // Process lines one at a time. Input is paused while a command runs so a
80
+ // fast paste (or piped stdin) can't race /exit ahead of a pending command.
81
+ let chain = Promise.resolve();
82
+ rl.prompt();
83
+ rl.on('line', (raw) => {
84
+ const input = raw.trim();
85
+ chain = chain.then(async () => {
86
+ if (!input)
87
+ return rl.prompt();
88
+ if (input === '/exit' || input === '/quit' || input === 'exit' || input === 'quit') {
89
+ shutdown();
90
+ return;
91
+ }
92
+ rl.pause();
93
+ try {
94
+ const result = await kernel.command(input);
95
+ render(result);
96
+ }
97
+ catch (err) {
98
+ console.log(chalk.red(`✖ ${err instanceof Error ? err.message : String(err)}`));
99
+ }
100
+ rl.resume();
101
+ rl.prompt();
102
+ });
103
+ });
104
+ rl.on('close', () => {
105
+ console.log(chalk.dim('\nbye.'));
106
+ process.exit(0);
107
+ });
108
+ await new Promise(() => {
109
+ /* keep process alive until rl closes */
110
+ });
111
+ }
@@ -0,0 +1,3 @@
1
+ import type Conf from 'conf';
2
+ import type { InfinicodeConfig } from '../kernel/config-schema.js';
3
+ export declare function kernelSetupWizard(config: Conf<InfinicodeConfig>): Promise<void>;