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,222 @@
1
+ const MODE_WEIGHTS = {
2
+ balanced: { capability: 2, benchmark: 2.0, reliability: 1, speed: 1.0, quota: 1, context: 1.0, cost: 1.0, localBonus: 0 },
3
+ quality: { capability: 2, benchmark: 3.5, reliability: 1, speed: 0.5, quota: 0.5, context: 1.5, cost: 0.2, localBonus: 0 },
4
+ // "fastest" = most capable model with the fastest API response. Prefers
5
+ // fast cloud inference (Groq etc.); local is only a fallback (localBonus < 0).
6
+ fastest: { capability: 2, benchmark: 1.5, reliability: 1, speed: 3.0, quota: 1, context: 0.5, cost: 0.5, localBonus: -3.0 },
7
+ 'free-first': { capability: 2, benchmark: 1.5, reliability: 1, speed: 1.0, quota: 1.5, context: 1.0, cost: 6.0, localBonus: 0.5 },
8
+ local: { capability: 2, benchmark: 2.0, reliability: 1, speed: 1.5, quota: 1, context: 1.0, cost: 1.5, localBonus: 2.0 },
9
+ privacy: { capability: 2, benchmark: 2.0, reliability: 1, speed: 1.0, quota: 1, context: 1.0, cost: 1.0, localBonus: 3.0 },
10
+ offline: { capability: 2, benchmark: 2.0, reliability: 1, speed: 1.5, quota: 1, context: 1.0, cost: 1.5, localBonus: 2.0 },
11
+ };
12
+ const DEFAULT_WEIGHTS = MODE_WEIGHTS.balanced;
13
+ /** Providers known for ultra-low-latency inference — favored in `fastest` mode. */
14
+ const FAST_API_PROVIDERS = new Set(['groq', 'cerebras', 'sambanova']);
15
+ export class CapabilityRouter {
16
+ logger;
17
+ constructor(logger) {
18
+ this.logger = logger;
19
+ }
20
+ async route(request) {
21
+ const candidates = this.scoreCandidates(request);
22
+ if (candidates.length === 0) {
23
+ this.logger.warn('No routing candidates available');
24
+ return null;
25
+ }
26
+ const best = candidates[0];
27
+ return {
28
+ providerId: best.providerId,
29
+ modelId: best.modelId,
30
+ score: best.score,
31
+ reason: best.reason,
32
+ };
33
+ }
34
+ rank(request) {
35
+ return this.scoreCandidates(request).map(c => ({
36
+ providerId: c.providerId,
37
+ modelId: c.modelId,
38
+ score: c.score,
39
+ reason: c.reason,
40
+ providerInfo: c.providerInfo,
41
+ benchmarkScore: c.benchmarkScore,
42
+ }));
43
+ }
44
+ scoreCandidates(request) {
45
+ const { capabilities, preferences, policy, availableProviders, availableModels } = request;
46
+ const mode = (policy.routing?.mode ?? 'balanced');
47
+ const weights = MODE_WEIGHTS[mode] ?? DEFAULT_WEIGHTS;
48
+ const needTokens = request.estimatedRequestTokens ?? 0;
49
+ const providerMap = new Map(availableProviders.map(p => [p.id, p]));
50
+ const blocked = new Set(policy.routing?.blockedProviders ?? []);
51
+ const preferred = new Set(policy.routing?.preferredProviders ?? []);
52
+ // The one locked mode: offline never leaves the local machine.
53
+ const localOnly = mode === 'offline';
54
+ const costPref = this.costPreferenceMultiplier(preferences.cost);
55
+ const speedPref = 0.5 + Math.min(1, (preferences.speed ?? 60) / 100); // ~0.9–1.5
56
+ const scored = [];
57
+ for (const model of availableModels) {
58
+ const provider = providerMap.get(model.providerId);
59
+ if (!provider || !provider.healthy)
60
+ continue;
61
+ if (blocked.has(provider.id))
62
+ continue;
63
+ if (localOnly && provider.type !== 'local')
64
+ continue;
65
+ const capScore = this.capabilityScore(model.capabilities, capabilities);
66
+ if (capScore === 0)
67
+ continue;
68
+ const benchmark = this.estimateBenchmark(model);
69
+ const benchScore = this.benchmarkScore(benchmark, preferences);
70
+ const reliability = provider.successRate ?? 0.9;
71
+ const speed = 1 - Math.min(1, (provider.latencyMs ?? 1000) / 5000);
72
+ const quota = provider.quotaRemaining !== undefined
73
+ ? Math.min(1, provider.quotaRemaining / 60)
74
+ : 0.5;
75
+ // Effective per-request budget: the tier's rate limit caps this well below
76
+ // the context window on free tiers (e.g. Groq free ≈ 12k TPM vs 128k ctx).
77
+ // Model-level cap wins; else the provider-tier TPM (from headers); else ctx.
78
+ const effectiveLimit = model.maxRequestTokens ?? provider.maxRequestTokens ?? model.contextLength;
79
+ const ctxScore = this.contextScore(effectiveLimit, preferences);
80
+ const costPenalty = this.costScore(model) * weights.cost * costPref;
81
+ const localBonus = provider.type === 'local' ? weights.localBonus : 0;
82
+ const preferredBonus = preferred.has(provider.id) ? 1 : 0;
83
+ // In fastest mode, reward providers with the fastest real inference APIs
84
+ // so a capable fast-cloud model beats local (which stays a fallback).
85
+ const fastApiBonus = mode === 'fastest' && FAST_API_PROVIDERS.has(provider.id) ? 1.5 : 0;
86
+ // Heavy penalty when the model can't fit the estimated request — keeps it
87
+ // as a last resort but routes to a capable model when one exists.
88
+ const capacityPenalty = needTokens > 0 && effectiveLimit < needTokens ? 6 : 0;
89
+ const score = capScore * weights.capability +
90
+ benchScore * weights.benchmark +
91
+ reliability * weights.reliability +
92
+ speed * weights.speed * speedPref +
93
+ quota * weights.quota +
94
+ ctxScore * weights.context +
95
+ localBonus +
96
+ preferredBonus +
97
+ fastApiBonus -
98
+ costPenalty -
99
+ capacityPenalty;
100
+ scored.push({
101
+ providerId: provider.id,
102
+ modelId: model.id,
103
+ score,
104
+ reason: this.buildReason(mode, capScore, benchmark, benchScore, speed, reliability, costPenalty, localBonus) +
105
+ (capacityPenalty ? ` cap<${needTokens}` : ''),
106
+ providerInfo: provider,
107
+ benchmarkScore: benchmark,
108
+ });
109
+ }
110
+ return scored.sort((a, b) => b.score - a.score);
111
+ }
112
+ capabilityScore(modelCaps, requested) {
113
+ if (requested.length === 0)
114
+ return 0.5;
115
+ let matched = 0;
116
+ for (const cap of requested) {
117
+ if (modelCaps.includes(cap))
118
+ matched++;
119
+ }
120
+ return matched / requested.length;
121
+ }
122
+ /**
123
+ * Reasoning/quality contribution in [0,1]. Honors the worker preference
124
+ * "reasoning >= N": a model that clears the bar gets full credit for its
125
+ * benchmark; one below the bar is proportionally discounted.
126
+ */
127
+ benchmarkScore(benchmark, prefs) {
128
+ const normalized = Math.max(0, Math.min(1, benchmark / 100));
129
+ if (!prefs.reasoning)
130
+ return normalized;
131
+ if (benchmark >= prefs.reasoning)
132
+ return normalized;
133
+ return normalized * (benchmark / prefs.reasoning);
134
+ }
135
+ /**
136
+ * Estimate a 0–100 reasoning/quality benchmark for a model. Uses an explicit
137
+ * `benchmarkScore` when the provider supplies one; otherwise infers it from
138
+ * parameter size, model family, and context length.
139
+ */
140
+ estimateBenchmark(model) {
141
+ if (typeof model.benchmarkScore === 'number') {
142
+ return Math.max(0, Math.min(100, model.benchmarkScore));
143
+ }
144
+ const text = `${model.id} ${model.name}`.toLowerCase();
145
+ const paramSize = this.parseParamSize(model, text);
146
+ let score;
147
+ if (paramSize >= 70)
148
+ score = 86;
149
+ else if (paramSize >= 30)
150
+ score = 80;
151
+ else if (paramSize >= 13)
152
+ score = 70;
153
+ else if (paramSize >= 7)
154
+ score = 60;
155
+ else if (paramSize >= 3)
156
+ score = 50;
157
+ else if (paramSize > 0)
158
+ score = 44;
159
+ else
160
+ score = 58; // unknown-size cloud model — assume mid-tier
161
+ // Frontier families punch above their parameter count.
162
+ if (/(gpt-4o|gpt-4\.1|gpt-5|gpt-oss|o[1-9]\b|claude|deepseek-?(r1|v3|v4)|gemini-[23]|gemini-1\.5-pro|llama-3\.3|llama-4|qwen2?\.5|qwen3|qwq|glm-[45]|nemotron|mistral-large|kimi|minimax|command-r-plus|ernie)/.test(text)) {
163
+ score = Math.max(score, 85);
164
+ }
165
+ // Small/fast variants are capable but not top-tier (avoid demoting MoE "air"
166
+ // or *-nano-VL flagships by matching only clear small-size markers).
167
+ if (/(\bmini\b|flash|instant|1\.5b|-3b\b|-7b\b|-8b\b|e4b|tiny|\bsmall\b)/.test(text)) {
168
+ score = Math.min(score, 74);
169
+ }
170
+ // Coding specialists get a small bump for their domain.
171
+ if (/(coder|code)/.test(text))
172
+ score += 3;
173
+ // Long context correlates with newer, stronger models.
174
+ if (model.contextLength >= 128_000)
175
+ score += 3;
176
+ else if (model.contextLength >= 64_000)
177
+ score += 1;
178
+ return Math.max(30, Math.min(95, Math.round(score)));
179
+ }
180
+ parseParamSize(model, text) {
181
+ const meta = model.metadata?.parameterSize;
182
+ if (typeof meta === 'string') {
183
+ const m = meta.match(/([\d.]+)\s*b/i);
184
+ if (m)
185
+ return parseFloat(m[1]);
186
+ }
187
+ // Match "70b", "8x7b", "3.8b" but not context markers like "128k".
188
+ const m = text.match(/(\d+(?:\.\d+)?)\s*x?\s*(\d+(?:\.\d+)?)?\s*b\b/);
189
+ if (m) {
190
+ const a = parseFloat(m[1]);
191
+ const b = m[2] ? parseFloat(m[2]) : undefined;
192
+ return b ? a * b : a; // 8x7b ≈ 56B
193
+ }
194
+ return 0;
195
+ }
196
+ contextScore(modelCtx, prefs) {
197
+ if (!prefs.contextLength)
198
+ return 0.5;
199
+ if (modelCtx >= prefs.contextLength)
200
+ return 1;
201
+ return modelCtx / prefs.contextLength;
202
+ }
203
+ costScore(model) {
204
+ const input = model.costPer1kTokens?.input ?? 0;
205
+ const output = model.costPer1kTokens?.output ?? 0;
206
+ return input + output;
207
+ }
208
+ costPreferenceMultiplier(cost) {
209
+ switch (cost) {
210
+ case 'free': return 2.0;
211
+ case 'low': return 1.3;
212
+ case 'high': return 0.6;
213
+ case 'medium':
214
+ default: return 1.0;
215
+ }
216
+ }
217
+ buildReason(mode, cap, benchmark, benchScore, speed, reliability, costPenalty, localBonus) {
218
+ return (`mode=${mode} cap=${cap.toFixed(2)} bench=${benchmark}(${benchScore.toFixed(2)}) ` +
219
+ `speed=${speed.toFixed(2)} rel=${reliability.toFixed(2)} cost=-${costPenalty.toFixed(2)}` +
220
+ (localBonus ? ` local+${localBonus.toFixed(1)}` : ''));
221
+ }
222
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Sample missions for the OpenKernel runtime.
3
+ *
4
+ * These illustrate the mission → objective → task → worker → provider flow.
5
+ * They can be executed via the `infinicode mission run` command or
6
+ * programmatically through the Kernel API.
7
+ */
8
+ import type { MissionInput } from '../kernel/index.js';
9
+ export declare const SAMPLE_MISSIONS: Record<string, MissionInput>;
10
+ export declare function getSampleMission(name: string): MissionInput | undefined;
11
+ export declare function listSampleMissions(): string[];
@@ -0,0 +1,132 @@
1
+ export const SAMPLE_MISSIONS = {
2
+ 'hello-code': {
3
+ name: 'hello-code',
4
+ description: 'Verify the kernel can route a coding task to a provider.',
5
+ goal: 'Generate a TypeScript function that reverses a string.',
6
+ policy: 'local-first',
7
+ tasks: [
8
+ {
9
+ description: 'Write a TypeScript function that reverses a string.',
10
+ capabilities: ['coding', 'reasoning'],
11
+ input: {
12
+ prompt: 'Write a TypeScript function `reverseString(s: string): string` that reverses its input. Include only the function and a one-line comment. No imports.',
13
+ },
14
+ },
15
+ ],
16
+ },
17
+ 'research-summary': {
18
+ name: 'research-summary',
19
+ description: 'Multi-task research mission with a dependency.',
20
+ goal: 'Produce a short research brief on local LLM inference.',
21
+ policy: 'balanced',
22
+ tasks: [
23
+ {
24
+ description: 'Summarize the benefits of local LLM inference.',
25
+ capabilities: ['summarize', 'reasoning'],
26
+ input: {
27
+ prompt: 'List the top 3 benefits of running LLMs locally versus using cloud APIs. Be concise.',
28
+ },
29
+ },
30
+ {
31
+ description: 'Draft a one-paragraph brief combining the benefits with a recommendation.',
32
+ capabilities: ['summarize', 'citations'],
33
+ dependencies: [],
34
+ input: {
35
+ prompt: 'Using the prior summary, write a single paragraph recommending local inference for a small team. Keep under 120 words.',
36
+ },
37
+ },
38
+ ],
39
+ },
40
+ 'review-code': {
41
+ name: 'review-code',
42
+ description: 'Run a review worker over a snippet.',
43
+ goal: 'Review a code snippet for bugs and style.',
44
+ policy: 'highest-quality',
45
+ tasks: [
46
+ {
47
+ description: 'Review this TypeScript snippet for bugs and style.',
48
+ capabilities: ['review', 'coding', 'reasoning'],
49
+ input: {
50
+ prompt: 'Review this code:\n\n```ts\nfunction add(a, b) { return a + b }\n```\n\nList concrete issues (bugs, types, naming) and suggested fixes. Be brief.',
51
+ },
52
+ },
53
+ ],
54
+ },
55
+ };
56
+ const FRONTEND_ARCHITECT_BRIEF = 'You are an elite frontend architect, design-systems engineer, motion designer, ' +
57
+ 'accessibility expert, and data-visualization engineer. Build production-grade, ' +
58
+ 'framework-independent UI using only HTML5, CSS3, and vanilla ES6+ JavaScript. ' +
59
+ 'Do NOT use React, Vue, Angular, Tailwind, Bootstrap, or jQuery. Use CSS custom ' +
60
+ 'properties for all design tokens, support runtime theme switching via ' +
61
+ '[data-theme], make every component reusable, responsive, animated (60fps), and ' +
62
+ 'accessible (semantic HTML, ARIA, :focus-visible, prefers-reduced-motion). ' +
63
+ 'No placeholders, no TODOs, no lorem ipsum — finish every section with real content. ' +
64
+ 'The aesthetic target is Apple × Linear × Stripe × Vercel with glassmorphism and a ' +
65
+ 'futuristic HUD feel. Output complete, self-contained code.';
66
+ // Acceptance criteria travel with each task as a "worker request"; the
67
+ // frontend-quality verifier scores against them and feeds fixes back on a miss.
68
+ SAMPLE_MISSIONS['frontend-platform'] = {
69
+ name: 'frontend-platform',
70
+ description: 'Build a production-grade, framework-independent frontend design system + component library.',
71
+ goal: 'Produce a reusable frontend platform (design tokens, themes, components, animation) at senior quality.',
72
+ policy: 'quality',
73
+ tasks: [
74
+ {
75
+ description: 'Design system foundation: tokens, themes, typography, spacing, elevation, glass, motion.',
76
+ capabilities: ['frontend', 'design', 'coding', 'reasoning'],
77
+ input: {
78
+ prompt: 'Build the foundation of the design system: a complete set of CSS custom-property design tokens ' +
79
+ '(colors, semantic colors, typography scale, spacing, radius, shadow/elevation, blur/glass, glow, ' +
80
+ 'motion timings, breakpoints) and at least 10 runtime themes via [data-theme] (Dark, Light, ' +
81
+ 'Cyberpunk, OLED, Glass, Purple Neon, Blue Neon, Green Matrix, Amber Terminal, High Contrast). ' +
82
+ 'Every value must be a token consumed with var(--…).',
83
+ context: {
84
+ systemPrompt: FRONTEND_ARCHITECT_BRIEF,
85
+ frontendAcceptance: {
86
+ threshold: 88, minThemes: 10, minTokens: 80,
87
+ requireDesignTokens: true, requireResponsive: true, noPlaceholders: true,
88
+ },
89
+ },
90
+ },
91
+ },
92
+ {
93
+ description: 'Component library: 120+ reusable, accessible, animated components with full states.',
94
+ capabilities: ['frontend', 'coding', 'accessibility', 'animation', 'reasoning'],
95
+ input: {
96
+ prompt: 'Build a reusable component library of at least 120 production-ready components (buttons, inputs, ' +
97
+ 'cards, navigation, command palette, modals, drawers, tabs, tables, data grid, charts host, toasts, ' +
98
+ 'tooltips, etc.). Each component: reusable class-based CSS, all states (hover/focus/active/disabled/' +
99
+ 'loading/error), keyboard navigation, ARIA, :focus-visible, and smooth animation. Vanilla JS only.',
100
+ context: {
101
+ systemPrompt: FRONTEND_ARCHITECT_BRIEF,
102
+ frontendAcceptance: {
103
+ threshold: 88, minComponents: 120, requireAccessibility: true,
104
+ requireAnimation: true, noPlaceholders: true,
105
+ },
106
+ },
107
+ },
108
+ },
109
+ {
110
+ description: 'Demo application built exclusively from the component library (AI OS / analytics dashboard).',
111
+ capabilities: ['frontend', 'coding', 'dataviz', 'animation', 'reasoning'],
112
+ input: {
113
+ prompt: 'Build a polished demo application (an AI Operating System dashboard) using ONLY reusable components ' +
114
+ 'and tokens from the library. Include a responsive dashboard layout, data visualizations, a command ' +
115
+ 'palette, a dock, and live-feeling microinteractions. Framework-independent, accessible, 60fps.',
116
+ context: {
117
+ systemPrompt: FRONTEND_ARCHITECT_BRIEF,
118
+ frontendAcceptance: {
119
+ threshold: 85, requireResponsive: true, requireAnimation: true,
120
+ requireAccessibility: true, noPlaceholders: true,
121
+ },
122
+ },
123
+ },
124
+ },
125
+ ],
126
+ };
127
+ export function getSampleMission(name) {
128
+ return SAMPLE_MISSIONS[name];
129
+ }
130
+ export function listSampleMissions() {
131
+ return Object.keys(SAMPLE_MISSIONS);
132
+ }
@@ -0,0 +1,30 @@
1
+ import type { Capability, Logger, Mission, MissionInput, Objective, Task, TaskInput } from './types.js';
2
+ import type { EventBus } from './event-bus.js';
3
+ export declare class Scheduler {
4
+ private eventBus;
5
+ private logger;
6
+ constructor(eventBus: EventBus, logger: Logger);
7
+ planMission(missionId: string, input: MissionInput): {
8
+ objectives: Objective[];
9
+ tasks: Task[];
10
+ };
11
+ createTask(missionId: string, objectiveId: string, description: string, capabilities: Capability[], dependencies: string[], input: TaskInput): Task;
12
+ /**
13
+ * Returns the next batch of tasks that are ready to execute:
14
+ * dependencies satisfied, not yet completed/failed/skipped.
15
+ */
16
+ nextReadyTasks(mission: Mission, maxBatch: number): Task[];
17
+ /**
18
+ * Topologically sorts tasks honoring dependency edges.
19
+ * Used for sequential mode.
20
+ */
21
+ topoSort(tasks: Task[]): Task[];
22
+ isMissionComplete(mission: Mission): boolean;
23
+ hasFailed(mission: Mission): boolean;
24
+ allObjectivesComplete(mission: Mission): boolean;
25
+ /**
26
+ * Marks an objective complete when all its tasks complete.
27
+ */
28
+ reconcileObjectives(mission: Mission): void;
29
+ private aggregateCapabilities;
30
+ }
@@ -0,0 +1,147 @@
1
+ /**
2
+ * OpenKernel — Scheduler
3
+ *
4
+ * Mission → Objectives → Tasks → Execution Queue → Workers
5
+ * Supports: sequential, parallel, dependency graphs
6
+ */
7
+ import { nanoid } from 'nanoid';
8
+ export class Scheduler {
9
+ eventBus;
10
+ logger;
11
+ constructor(eventBus, logger) {
12
+ this.eventBus = eventBus;
13
+ this.logger = logger;
14
+ }
15
+ planMission(missionId, input) {
16
+ const taskInputs = input.tasks ?? [];
17
+ const objectiveId = nanoid(10);
18
+ const tasks = [];
19
+ for (const ti of taskInputs) {
20
+ tasks.push(this.createTask(missionId, objectiveId, ti.description, ti.capabilities, ti.dependencies ?? [], ti.input));
21
+ }
22
+ const objective = {
23
+ id: objectiveId,
24
+ missionId,
25
+ description: input.goal,
26
+ capabilities: this.aggregateCapabilities(tasks),
27
+ acceptanceCriteria: [],
28
+ taskIds: tasks.map(t => t.id),
29
+ status: tasks.length > 0 ? 'PENDING' : 'COMPLETED',
30
+ createdAt: Date.now(),
31
+ };
32
+ this.logger.info(`Mission planned: ${missionId} with ${tasks.length} task(s) across 1 objective`);
33
+ return { objectives: [objective], tasks };
34
+ }
35
+ createTask(missionId, objectiveId, description, capabilities, dependencies, input) {
36
+ const id = nanoid(10);
37
+ const task = {
38
+ id,
39
+ objectiveId,
40
+ missionId,
41
+ description,
42
+ capabilities,
43
+ dependencies,
44
+ status: 'PENDING',
45
+ input,
46
+ attempts: 0,
47
+ maxAttempts: 3,
48
+ createdAt: Date.now(),
49
+ };
50
+ this.eventBus.emit({ type: 'TASK_QUEUED', timestamp: Date.now(), missionId, objectiveId, taskId: id, data: { description } });
51
+ return task;
52
+ }
53
+ /**
54
+ * Returns the next batch of tasks that are ready to execute:
55
+ * dependencies satisfied, not yet completed/failed/skipped.
56
+ */
57
+ nextReadyTasks(mission, maxBatch) {
58
+ const completed = new Set(mission.tasks.filter(t => t.status === 'COMPLETED').map(t => t.id));
59
+ const inFlight = new Set(mission.tasks.filter(t => t.status === 'RUNNING' || t.status === 'VERIFYING').map(t => t.id));
60
+ const ready = [];
61
+ const startedObjectives = new Set();
62
+ for (const task of mission.tasks) {
63
+ if (task.status !== 'PENDING' && task.status !== 'QUEUED')
64
+ continue;
65
+ if (inFlight.size >= maxBatch)
66
+ break;
67
+ const depsOk = task.dependencies.every(d => completed.has(d));
68
+ if (!depsOk)
69
+ continue;
70
+ ready.push(task);
71
+ inFlight.add(task.id);
72
+ if (!startedObjectives.has(task.objectiveId)) {
73
+ startedObjectives.add(task.objectiveId);
74
+ const objective = mission.objectives.find(o => o.id === task.objectiveId);
75
+ if (objective && objective.status === 'PENDING') {
76
+ objective.status = 'RUNNING';
77
+ this.eventBus.emit({
78
+ type: 'OBJECTIVE_STARTED',
79
+ timestamp: Date.now(),
80
+ missionId: mission.id,
81
+ objectiveId: objective.id,
82
+ data: { description: objective.description },
83
+ });
84
+ }
85
+ }
86
+ }
87
+ return ready;
88
+ }
89
+ /**
90
+ * Topologically sorts tasks honoring dependency edges.
91
+ * Used for sequential mode.
92
+ */
93
+ topoSort(tasks) {
94
+ const map = new Map(tasks.map(t => [t.id, t]));
95
+ const visited = new Set();
96
+ const result = [];
97
+ const visit = (task) => {
98
+ if (visited.has(task.id))
99
+ return;
100
+ visited.add(task.id);
101
+ for (const dep of task.dependencies) {
102
+ const depTask = map.get(dep);
103
+ if (depTask)
104
+ visit(depTask);
105
+ }
106
+ result.push(task);
107
+ };
108
+ for (const t of tasks)
109
+ visit(t);
110
+ return result;
111
+ }
112
+ isMissionComplete(mission) {
113
+ return mission.tasks.length > 0 && mission.tasks.every(t => t.status === 'COMPLETED' || t.status === 'SKIPPED');
114
+ }
115
+ hasFailed(mission) {
116
+ return mission.tasks.some(t => t.status === 'FAILED' && t.attempts >= t.maxAttempts);
117
+ }
118
+ allObjectivesComplete(mission) {
119
+ return mission.objectives.length > 0 && mission.objectives.every(o => o.status === 'COMPLETED');
120
+ }
121
+ /**
122
+ * Marks an objective complete when all its tasks complete.
123
+ */
124
+ reconcileObjectives(mission) {
125
+ for (const objective of mission.objectives) {
126
+ const objTasks = mission.tasks.filter(t => t.objectiveId === objective.id);
127
+ const allDone = objTasks.length > 0 && objTasks.every(t => t.status === 'COMPLETED' || t.status === 'SKIPPED');
128
+ if (allDone && objective.status !== 'COMPLETED') {
129
+ objective.status = 'COMPLETED';
130
+ objective.completedAt = Date.now();
131
+ this.eventBus.emit({
132
+ type: 'OBJECTIVE_COMPLETED',
133
+ timestamp: Date.now(),
134
+ missionId: mission.id,
135
+ objectiveId: objective.id,
136
+ });
137
+ }
138
+ }
139
+ }
140
+ aggregateCapabilities(tasks) {
141
+ const set = new Set();
142
+ for (const t of tasks)
143
+ for (const c of t.capabilities)
144
+ set.add(c);
145
+ return [...set];
146
+ }
147
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * OpenKernel — Harness SDK
3
+ *
4
+ * Helpers for harnesses to build MissionInput / MissionTaskInput without
5
+ * touching the kernel internals. A harness owns prompts, workflows,
6
+ * templates, agent design, memory strategy — it produces mission inputs;
7
+ * the kernel executes them.
8
+ *
9
+ * const input = mission('reverse-string', 'Produce a reverseString function')
10
+ * .description('Write a TypeScript string reverser')
11
+ * .policy('local-first')
12
+ * .task('Write the function', ['coding', 'reasoning'], { prompt: '...' })
13
+ * .task('Write tests', ['coding'], { prompt: '...' }, ['t1'])
14
+ * .build();
15
+ *
16
+ * const result = await kernel.execute(input);
17
+ */
18
+ import type { Capability, FrontendAcceptance, MissionInput, PolicyName, TaskInput, WorkspaceRef } from '../types.js';
19
+ export interface MissionBuilder {
20
+ description(d: string): this;
21
+ goal(g: string): this;
22
+ policy(p: PolicyName): this;
23
+ workspace(root: string, git?: WorkspaceRef['git']): this;
24
+ metadata(meta: Record<string, unknown>): this;
25
+ task(description: string, capabilities: Capability[], input: TaskInput, dependencies?: string[]): this;
26
+ build(): MissionInput;
27
+ }
28
+ export declare function mission(name: string, goal: string): MissionBuilder;
29
+ export declare function taskInput(prompt: string, context?: Record<string, unknown>): TaskInput;
30
+ export declare function browserTaskInput(prompt: string, actions: Array<Record<string, unknown>>, context?: Record<string, unknown>): TaskInput;
31
+ export declare function researchTaskInput(query: string, context?: Record<string, unknown>): TaskInput;
32
+ /**
33
+ * Build a frontend "worker request": the brief plus the acceptance criteria
34
+ * (quality bar + constraints) that the frontend-quality verifier enforces and
35
+ * feeds back on. Pair with capabilities `['frontend', 'coding', 'reasoning']`.
36
+ */
37
+ export declare function frontendTaskInput(prompt: string, acceptance?: FrontendAcceptance, context?: Record<string, unknown>): TaskInput;
@@ -0,0 +1,48 @@
1
+ export function mission(name, goal) {
2
+ let desc = '';
3
+ let goalStr = goal;
4
+ let policy;
5
+ let workspace;
6
+ let metadata;
7
+ const tasks = [];
8
+ const builder = {
9
+ description(d) { desc = d; return this; },
10
+ goal(g) { goalStr = g; return this; },
11
+ policy(p) { policy = p; return this; },
12
+ workspace(root, git) { workspace = { root, git }; return this; },
13
+ metadata(m) { metadata = m; return this; },
14
+ task(description, capabilities, input, dependencies) {
15
+ tasks.push({ description, capabilities, input, dependencies });
16
+ return this;
17
+ },
18
+ build() {
19
+ return {
20
+ name,
21
+ description: desc,
22
+ goal: goalStr,
23
+ policy,
24
+ workspace,
25
+ metadata,
26
+ tasks,
27
+ };
28
+ },
29
+ };
30
+ return builder;
31
+ }
32
+ export function taskInput(prompt, context) {
33
+ return { prompt, context };
34
+ }
35
+ export function browserTaskInput(prompt, actions, context) {
36
+ return { prompt, context: { ...context, actions } };
37
+ }
38
+ export function researchTaskInput(query, context) {
39
+ return { prompt: query, context: { ...context, query } };
40
+ }
41
+ /**
42
+ * Build a frontend "worker request": the brief plus the acceptance criteria
43
+ * (quality bar + constraints) that the frontend-quality verifier enforces and
44
+ * feeds back on. Pair with capabilities `['frontend', 'coding', 'reasoning']`.
45
+ */
46
+ export function frontendTaskInput(prompt, acceptance, context) {
47
+ return { prompt, context: { ...context, frontendAcceptance: acceptance ?? {} } };
48
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * OpenKernel — Plugin SDK
3
+ *
4
+ * Typed helpers for authoring plugins concisely. Provides a fluent
5
+ * PluginBuilder and a definePlugin() shortcut.
6
+ *
7
+ * const myPlugin = definePlugin('my-plugin')
8
+ * .version('1.0.0')
9
+ * .description('Does things')
10
+ * .subscribe(['MISSION_STARTED'], (e) => console.log(e))
11
+ * .command('greet', 'Greet someone', async (args) => console.log(args))
12
+ * .onRegister((kernel) => { ... })
13
+ * .onDestroy(() => { ... })
14
+ * .build();
15
+ */
16
+ import type { KernelEvent, KernelEventType, KernelLike, Plugin, PluginCommand, EventHandler } from '../types.js';
17
+ export interface PluginBuilder {
18
+ version(v: string): this;
19
+ description(d: string): this;
20
+ subscribe(types: KernelEventType[], handler: EventHandler): this;
21
+ command(name: string, description: string, handler: PluginCommand['handler']): this;
22
+ onRegister(fn: (kernel: KernelLike) => void | Promise<void>): this;
23
+ onDestroy(fn: () => void | Promise<void>): this;
24
+ onEvent(handler: (event: KernelEvent) => void | Promise<void>): this;
25
+ build(): Plugin;
26
+ }
27
+ export declare function definePlugin(name: string): PluginBuilder;