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.
- package/.opencode/plugins/home-logo-animation.tsx +120 -0
- package/.opencode/plugins/routing-mode-display.tsx +135 -0
- package/.opencode/themes/infinibot-gold.json +222 -0
- package/.opencode/tui.json +8 -0
- package/README.md +564 -72
- package/dist/ascii-video-animation.d.ts +2 -0
- package/dist/ascii-video-animation.js +243 -0
- package/dist/cli.js +199 -50
- package/dist/commands/console.d.ts +6 -0
- package/dist/commands/console.js +111 -0
- package/dist/commands/kernel-setup.d.ts +3 -0
- package/dist/commands/kernel-setup.js +303 -0
- package/dist/commands/mcp.d.ts +14 -0
- package/dist/commands/mcp.js +100 -0
- package/dist/commands/mission.d.ts +16 -0
- package/dist/commands/mission.js +301 -0
- package/dist/commands/models.d.ts +3 -1
- package/dist/commands/models.js +111 -55
- package/dist/commands/providers.d.ts +6 -0
- package/dist/commands/providers.js +95 -0
- package/dist/commands/run.d.ts +2 -1
- package/dist/commands/run.js +349 -59
- package/dist/commands/serve.d.ts +20 -0
- package/dist/commands/serve.js +132 -0
- package/dist/commands/setup.d.ts +1 -1
- package/dist/commands/setup.js +77 -44
- package/dist/commands/status.d.ts +2 -1
- package/dist/commands/status.js +46 -30
- package/dist/commands/workers.d.ts +5 -0
- package/dist/commands/workers.js +103 -0
- package/dist/kernel/autonomy/goal-loop.d.ts +49 -0
- package/dist/kernel/autonomy/goal-loop.js +113 -0
- package/dist/kernel/autonomy/index.d.ts +8 -0
- package/dist/kernel/autonomy/index.js +7 -0
- package/dist/kernel/browser/browser-controller.d.ts +57 -0
- package/dist/kernel/browser/browser-controller.js +175 -0
- package/dist/kernel/checkpoint-engine.d.ts +17 -0
- package/dist/kernel/checkpoint-engine.js +128 -0
- package/dist/kernel/command-system.d.ts +37 -0
- package/dist/kernel/command-system.js +239 -0
- package/dist/kernel/config-schema.d.ts +57 -0
- package/dist/kernel/config-schema.js +36 -0
- package/dist/kernel/event-bus.d.ts +19 -0
- package/dist/kernel/event-bus.js +65 -0
- package/dist/kernel/federation/auto-update.d.ts +36 -0
- package/dist/kernel/federation/auto-update.js +57 -0
- package/dist/kernel/federation/compute-router.d.ts +27 -0
- package/dist/kernel/federation/compute-router.js +44 -0
- package/dist/kernel/federation/config-sync.d.ts +33 -0
- package/dist/kernel/federation/config-sync.js +37 -0
- package/dist/kernel/federation/discovery.d.ts +11 -0
- package/dist/kernel/federation/discovery.js +44 -0
- package/dist/kernel/federation/event-bridge.d.ts +30 -0
- package/dist/kernel/federation/event-bridge.js +61 -0
- package/dist/kernel/federation/federation-plugin.d.ts +24 -0
- package/dist/kernel/federation/federation-plugin.js +35 -0
- package/dist/kernel/federation/federation.d.ts +135 -0
- package/dist/kernel/federation/federation.js +378 -0
- package/dist/kernel/federation/index.d.ts +33 -0
- package/dist/kernel/federation/index.js +24 -0
- package/dist/kernel/federation/lan-discovery.d.ts +43 -0
- package/dist/kernel/federation/lan-discovery.js +135 -0
- package/dist/kernel/federation/moltfed-adapter.d.ts +30 -0
- package/dist/kernel/federation/moltfed-adapter.js +52 -0
- package/dist/kernel/federation/moltfed-connector.d.ts +98 -0
- package/dist/kernel/federation/moltfed-connector.js +193 -0
- package/dist/kernel/federation/node-identity.d.ts +19 -0
- package/dist/kernel/federation/node-identity.js +86 -0
- package/dist/kernel/federation/peer-mesh.d.ts +46 -0
- package/dist/kernel/federation/peer-mesh.js +117 -0
- package/dist/kernel/federation/protocol.d.ts +20 -0
- package/dist/kernel/federation/protocol.js +61 -0
- package/dist/kernel/federation/role-context.d.ts +5 -0
- package/dist/kernel/federation/role-context.js +45 -0
- package/dist/kernel/federation/telemetry.d.ts +21 -0
- package/dist/kernel/federation/telemetry.js +138 -0
- package/dist/kernel/federation/transport-http.d.ts +44 -0
- package/dist/kernel/federation/transport-http.js +207 -0
- package/dist/kernel/federation/types.d.ts +212 -0
- package/dist/kernel/federation/types.js +3 -0
- package/dist/kernel/free-providers.d.ts +28 -0
- package/dist/kernel/free-providers.js +162 -0
- package/dist/kernel/frontend-scoring.d.ts +21 -0
- package/dist/kernel/frontend-scoring.js +125 -0
- package/dist/kernel/index.d.ts +63 -0
- package/dist/kernel/index.js +45 -0
- package/dist/kernel/kernel.d.ts +75 -0
- package/dist/kernel/kernel.js +223 -0
- package/dist/kernel/logger.d.ts +18 -0
- package/dist/kernel/logger.js +26 -0
- package/dist/kernel/mcp/index.d.ts +9 -0
- package/dist/kernel/mcp/index.js +8 -0
- package/dist/kernel/mcp/mcp-server.d.ts +27 -0
- package/dist/kernel/mcp/mcp-server.js +178 -0
- package/dist/kernel/mission-engine.d.ts +42 -0
- package/dist/kernel/mission-engine.js +160 -0
- package/dist/kernel/orchestrator.d.ts +51 -0
- package/dist/kernel/orchestrator.js +226 -0
- package/dist/kernel/plugin-manager.d.ts +28 -0
- package/dist/kernel/plugin-manager.js +76 -0
- package/dist/kernel/plugins/browser-plugin.d.ts +22 -0
- package/dist/kernel/plugins/browser-plugin.js +34 -0
- package/dist/kernel/plugins/dashboard-plugin.d.ts +17 -0
- package/dist/kernel/plugins/dashboard-plugin.js +72 -0
- package/dist/kernel/plugins/discord-plugin.d.ts +11 -0
- package/dist/kernel/plugins/discord-plugin.js +35 -0
- package/dist/kernel/plugins/metrics-plugin.d.ts +33 -0
- package/dist/kernel/plugins/metrics-plugin.js +86 -0
- package/dist/kernel/plugins/search-plugin.d.ts +17 -0
- package/dist/kernel/plugins/search-plugin.js +20 -0
- package/dist/kernel/plugins/slack-plugin.d.ts +11 -0
- package/dist/kernel/plugins/slack-plugin.js +35 -0
- package/dist/kernel/plugins/telegram-plugin.d.ts +20 -0
- package/dist/kernel/plugins/telegram-plugin.js +122 -0
- package/dist/kernel/policies.d.ts +33 -0
- package/dist/kernel/policies.js +105 -0
- package/dist/kernel/provider-discovery.d.ts +41 -0
- package/dist/kernel/provider-discovery.js +179 -0
- package/dist/kernel/provider-manager.d.ts +38 -0
- package/dist/kernel/provider-manager.js +206 -0
- package/dist/kernel/provider-url.d.ts +18 -0
- package/dist/kernel/provider-url.js +45 -0
- package/dist/kernel/providers/gemini-provider.d.ts +43 -0
- package/dist/kernel/providers/gemini-provider.js +203 -0
- package/dist/kernel/providers/ollama-provider.d.ts +44 -0
- package/dist/kernel/providers/ollama-provider.js +241 -0
- package/dist/kernel/providers/openai-compatible-provider.d.ts +43 -0
- package/dist/kernel/providers/openai-compatible-provider.js +233 -0
- package/dist/kernel/recovery-manager.d.ts +38 -0
- package/dist/kernel/recovery-manager.js +156 -0
- package/dist/kernel/router.d.ts +44 -0
- package/dist/kernel/router.js +222 -0
- package/dist/kernel/sample-missions.d.ts +11 -0
- package/dist/kernel/sample-missions.js +132 -0
- package/dist/kernel/scheduler.d.ts +30 -0
- package/dist/kernel/scheduler.js +147 -0
- package/dist/kernel/sdk/harness-sdk.d.ts +37 -0
- package/dist/kernel/sdk/harness-sdk.js +48 -0
- package/dist/kernel/sdk/plugin-sdk.d.ts +27 -0
- package/dist/kernel/sdk/plugin-sdk.js +40 -0
- package/dist/kernel/search/search-controller.d.ts +32 -0
- package/dist/kernel/search/search-controller.js +141 -0
- package/dist/kernel/setup.d.ts +13 -0
- package/dist/kernel/setup.js +59 -0
- package/dist/kernel/types.d.ts +479 -0
- package/dist/kernel/types.js +7 -0
- package/dist/kernel/verification-engine.d.ts +33 -0
- package/dist/kernel/verification-engine.js +287 -0
- package/dist/kernel/worker-runtime.d.ts +66 -0
- package/dist/kernel/worker-runtime.js +261 -0
- package/dist/kernel/workers/browser-worker.d.ts +6 -0
- package/dist/kernel/workers/browser-worker.js +92 -0
- package/dist/kernel/workers/builtin-workers.d.ts +20 -0
- package/dist/kernel/workers/builtin-workers.js +120 -0
- package/dist/kernel/workers/research-worker.d.ts +5 -0
- package/dist/kernel/workers/research-worker.js +90 -0
- package/dist/prompt-ascii-video-animation.d.ts +2 -0
- package/dist/prompt-ascii-video-animation.js +243 -0
- 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
|
-
|
|
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
|
|
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
|
|
71
|
-
.option('-m, --model <model>', '
|
|
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
|
-
|
|
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
|
-
.
|
|
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
|
-
//
|
|
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('
|
|
141
|
-
.
|
|
142
|
-
.
|
|
143
|
-
.action(async (
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
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
|
-
|
|
162
|
-
|
|
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
|
+
}
|