okengine 0.1.4 → 0.2.1
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/AGENTS.md +1 -1
- package/README.md +48 -15
- package/docs/spec/{complete-example.md → example.md} +0 -1
- package/docs/spec/unified-theory.md +1 -1
- package/package.json +21 -8
- package/src/auth/index.ts +1 -0
- package/src/cli/dev.ts +3 -1
- package/src/cli/doc-drift.ts +54 -21
- package/src/client/index.ts +1 -0
- package/src/config/index.ts +1 -0
- package/src/console/index.ts +26 -13
- package/src/console/server/app.ts +44 -7
- package/src/console/server/flows.ts +2 -6
- package/src/console/server/index.ts +2 -1
- package/src/console/server/lazy-panels.test.ts +27 -0
- package/src/console/server/panel-load.ts +28 -0
- package/src/console/server/plugin.ts +1 -1
- package/src/console/server/plugins.ts +7 -6
- package/src/console/server/public-flows.ts +12 -0
- package/src/console/server/state.ts +159 -122
- package/src/console/server/store.ts +13 -10
- package/src/drivers/index.ts +2 -6
- package/src/drivers/vault-sops.ts +20 -1
- package/src/elements/ai.ts +1 -0
- package/src/elements/channel.ts +1 -0
- package/src/elements/clock.ts +1 -0
- package/src/elements/gate.ts +1 -0
- package/src/elements/signal.ts +1 -0
- package/src/elements/store.ts +1 -0
- package/src/elements/vault.ts +1 -0
- package/src/index.ts +9 -0
- package/src/kernel/app.ts +1 -1
- package/src/kernel/boot-bind/ai.ts +31 -0
- package/src/kernel/boot-bind/channel.ts +27 -0
- package/src/kernel/boot-bind/clock.ts +74 -0
- package/src/kernel/boot-bind/gate.ts +28 -0
- package/src/kernel/boot-bind/runs.ts +28 -0
- package/src/kernel/boot-bind/signal.ts +68 -0
- package/src/kernel/boot-bind/store.ts +47 -0
- package/src/kernel/boot-bind/vault.ts +36 -0
- package/src/kernel/boot.test.ts +85 -1
- package/src/kernel/boot.ts +250 -212
- package/src/kernel/index.ts +2 -0
- package/src/mcp/data.ts +1 -0
- package/src/mcp/docs-index.ts +252 -0
- package/src/mcp/docs-mcp.test.ts +176 -0
- package/src/mcp/docs-server.ts +233 -0
- package/src/mcp/docs-tools.ts +143 -0
- package/src/mcp/index.ts +30 -5
- package/src/mcp/protocol.ts +2 -1
- package/src/release/exports.test.ts +71 -0
- package/src/release/exports.ts +156 -0
- package/src/release/index.ts +21 -0
- package/src/release/limits.ts +9 -0
- package/src/release/measure.exports.test.ts +82 -0
- package/src/release/measure.ts +297 -14
- package/src/release/publish.ts +14 -3
- package/src/release/readme.test.ts +61 -0
- package/src/release/readme.ts +13 -0
- package/src/runs/index.ts +1 -0
- package/src/runtime/index.ts +1 -0
- package/src/runtime/security.test.ts +6 -1
- package/src/runtime/types.ts +6 -0
- package/src/test/create-test-app.ts +2 -0
- package/src/test/index.ts +1 -0
- package/src/console/ui/dist/assets/index-B71Yl_SS.js +0 -10
- package/src/console/ui/dist/assets/panel-access-Dd37LU2c.js +0 -64
- package/src/console/ui/dist/assets/panel-ai-CC7LR6-J.js +0 -1
- package/src/console/ui/dist/assets/panel-architecture-B5b3iKCz.js +0 -1
- package/src/console/ui/dist/assets/panel-channels-CeNjTKXp.js +0 -1
- package/src/console/ui/dist/assets/panel-clock-DgFTLoHV.js +0 -1
- package/src/console/ui/dist/assets/panel-diff-DxehccqB.js +0 -1
- package/src/console/ui/dist/assets/panel-flows-BtrVn-Eg.js +0 -45
- package/src/console/ui/dist/assets/panel-gates-Z9MKRGdH.js +0 -1
- package/src/console/ui/dist/assets/panel-overview-Bd48d9km.js +0 -1
- package/src/console/ui/dist/assets/panel-plugins-DWd0TowH.js +0 -1
- package/src/console/ui/dist/assets/panel-runs-BwsWqKeB.js +0 -1
- package/src/console/ui/dist/assets/panel-signals-9najbZY2.js +0 -1
- package/src/console/ui/dist/assets/panel-store-OHkP2pDp.js +0 -1
- package/src/console/ui/dist/assets/panel-traces-tn2JoY8U.js +0 -1
- package/src/console/ui/dist/assets/panel-vault-BbfWdox0.js +0 -1
- package/src/console/ui/dist/assets/rolldown-runtime-CNC7AqOf.js +0 -1
- package/src/console/ui/dist/assets/style-Cnl7WLya.css +0 -3
- package/src/console/ui/dist/index.html +0 -14
package/src/kernel/boot.ts
CHANGED
|
@@ -12,65 +12,48 @@
|
|
|
12
12
|
* 8. Caps — mint per-flow capability tokens from the Manifest / effects
|
|
13
13
|
* ```
|
|
14
14
|
*
|
|
15
|
+
* Element runtimes are loaded via `new URL("./boot-bind/"+name+".ts", …)` so
|
|
16
|
+
* unused binders stay out of the `oke()` bundle (semantic tree-shaking).
|
|
17
|
+
* Vault still loads whenever secrets are declared and lists every gap in one
|
|
18
|
+
* failure; capability minting uses flow effect refs only — no element modules.
|
|
19
|
+
*
|
|
15
20
|
* The scheduler reads the effective state from the Store after reconciliation,
|
|
16
21
|
* never the code directly (console §5).
|
|
17
22
|
*/
|
|
18
23
|
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
import type { ConfigEnv, OkeConfig } from "../config/index.ts";
|
|
25
|
+
import type {
|
|
26
|
+
AiRuntime,
|
|
27
|
+
CreateAiRuntimeOptions,
|
|
23
28
|
} from "../elements/ai.ts";
|
|
24
|
-
import {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
type CreateChannelRuntimeOptions,
|
|
29
|
+
import type {
|
|
30
|
+
ChannelRuntime,
|
|
31
|
+
CreateChannelRuntimeOptions,
|
|
28
32
|
} from "../elements/channel.ts";
|
|
29
|
-
import {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
createTestClockRuntime,
|
|
33
|
-
type ClockDecl,
|
|
34
|
-
type ClockRuntime,
|
|
33
|
+
import type {
|
|
34
|
+
ClockDecl,
|
|
35
|
+
ClockRuntime,
|
|
35
36
|
} from "../elements/clock.ts";
|
|
36
|
-
import {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
type GateRuntime,
|
|
37
|
+
import type {
|
|
38
|
+
GateDecl,
|
|
39
|
+
GateRuntime,
|
|
40
40
|
} from "../elements/gate.ts";
|
|
41
|
-
import {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
type SignalRuntime,
|
|
41
|
+
import type {
|
|
42
|
+
SignalDecl,
|
|
43
|
+
SignalRuntime,
|
|
45
44
|
} from "../elements/signal.ts";
|
|
46
|
-
import {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
type StoreRuntime,
|
|
45
|
+
import type {
|
|
46
|
+
StoreDecl,
|
|
47
|
+
StoreRuntime,
|
|
50
48
|
} from "../elements/store.ts";
|
|
51
|
-
import {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
type VaultSecretDecl,
|
|
49
|
+
import type {
|
|
50
|
+
CreateVaultRuntimeOptions,
|
|
51
|
+
VaultRuntime,
|
|
52
|
+
VaultSecretDecl,
|
|
56
53
|
} from "../elements/vault.ts";
|
|
57
|
-
import {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
memoryVaultDriver,
|
|
61
|
-
openConsoleChannel,
|
|
62
|
-
mockAiDriver,
|
|
63
|
-
} from "../drivers/index.ts";
|
|
64
|
-
import {
|
|
65
|
-
resolveDriverId,
|
|
66
|
-
type ConfigEnv,
|
|
67
|
-
type OkeConfig,
|
|
68
|
-
} from "../config/index.ts";
|
|
69
|
-
import {
|
|
70
|
-
createRunsRuntime,
|
|
71
|
-
memoryRunsDriver,
|
|
72
|
-
type CreateRunsRuntimeOptions,
|
|
73
|
-
type RunsRuntime,
|
|
54
|
+
import type {
|
|
55
|
+
CreateRunsRuntimeOptions,
|
|
56
|
+
RunsRuntime,
|
|
74
57
|
} from "../runs/index.ts";
|
|
75
58
|
import {
|
|
76
59
|
createCapabilityToken,
|
|
@@ -171,6 +154,88 @@ export interface BootResult {
|
|
|
171
154
|
close(): Promise<void>;
|
|
172
155
|
}
|
|
173
156
|
|
|
157
|
+
/** Which element runtimes a boot must construct / import. */
|
|
158
|
+
export interface ElementNeeds {
|
|
159
|
+
readonly vault: boolean;
|
|
160
|
+
readonly store: boolean;
|
|
161
|
+
readonly signal: boolean;
|
|
162
|
+
readonly clock: boolean;
|
|
163
|
+
readonly gate: boolean;
|
|
164
|
+
readonly channel: boolean;
|
|
165
|
+
readonly ai: boolean;
|
|
166
|
+
readonly runs: boolean;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Decide which element runtimes are required from BootOptions alone —
|
|
171
|
+
* declaration arrays, pre-built runtimes, flow effects, and bindings.
|
|
172
|
+
* Does not import any element runtime module.
|
|
173
|
+
*
|
|
174
|
+
* @param options - Boot declarations
|
|
175
|
+
*/
|
|
176
|
+
export function resolveElementNeeds(options: BootOptions): ElementNeeds {
|
|
177
|
+
const pre = options.elements ?? {};
|
|
178
|
+
let vault =
|
|
179
|
+
pre.vault !== undefined ||
|
|
180
|
+
(options.vault?.secrets ?? options.secrets ?? []).length > 0;
|
|
181
|
+
let store = pre.store !== undefined || (options.stores?.length ?? 0) > 0;
|
|
182
|
+
let signal = pre.signal !== undefined || (options.signals?.length ?? 0) > 0;
|
|
183
|
+
let clock = pre.clock !== undefined || (options.clocks?.length ?? 0) > 0;
|
|
184
|
+
let gate = pre.gate !== undefined || (options.gates?.length ?? 0) > 0;
|
|
185
|
+
let channel = pre.channel !== undefined || options.channel !== undefined;
|
|
186
|
+
let ai = pre.ai !== undefined || options.ai !== undefined;
|
|
187
|
+
let runs = pre.runs !== undefined || options.runs !== undefined;
|
|
188
|
+
|
|
189
|
+
const considerFlow = (f: AnyFlowDef): void => {
|
|
190
|
+
const e = f.effects;
|
|
191
|
+
if ((e?.reads?.length ?? 0) > 0 || (e?.writes?.length ?? 0) > 0) {
|
|
192
|
+
store = true;
|
|
193
|
+
}
|
|
194
|
+
if ((e?.emits?.length ?? 0) > 0) signal = true;
|
|
195
|
+
if ((e?.secrets?.length ?? 0) > 0) vault = true;
|
|
196
|
+
if ((e?.sends?.length ?? 0) > 0) channel = true;
|
|
197
|
+
if ((e?.asks?.length ?? 0) > 0) ai = true;
|
|
198
|
+
for (const t of f.triggers) {
|
|
199
|
+
if (t.kind === "every") clock = true;
|
|
200
|
+
if (t.kind === "signal") signal = true;
|
|
201
|
+
if (t.kind === "cdc") store = true;
|
|
202
|
+
if (t.kind === "http" && t.gates.length > 0) gate = true;
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
for (const f of options.flows ?? []) considerFlow(f);
|
|
207
|
+
for (const b of options.bindings ?? []) {
|
|
208
|
+
considerFlow(b.flow);
|
|
209
|
+
const t = b.trigger;
|
|
210
|
+
if (t.kind === "every") clock = true;
|
|
211
|
+
if (t.kind === "signal") signal = true;
|
|
212
|
+
if (t.kind === "cdc") store = true;
|
|
213
|
+
if (t.kind === "http" && t.gates.length > 0) gate = true;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// AI agents share the gate runtime for tool checks.
|
|
217
|
+
if (ai) gate = true;
|
|
218
|
+
if (
|
|
219
|
+
options.onSignal &&
|
|
220
|
+
(options.bindings ?? []).some((b) => b.trigger.kind === "signal")
|
|
221
|
+
) {
|
|
222
|
+
signal = true;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return { vault, store, signal, clock, gate, channel, ai, runs };
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Dynamically load a boot-bind module without pulling it into the bundler
|
|
230
|
+
* graph (expression `new URL` — Bun resolves at runtime).
|
|
231
|
+
*
|
|
232
|
+
* @param name - Binder file stem (`store`, `vault`, …)
|
|
233
|
+
*/
|
|
234
|
+
async function loadBind<T>(name: string): Promise<T> {
|
|
235
|
+
const url = new URL(`./boot-bind/${name}.ts`, import.meta.url);
|
|
236
|
+
return import(url.href) as Promise<T>;
|
|
237
|
+
}
|
|
238
|
+
|
|
174
239
|
/**
|
|
175
240
|
* Run the ordered boot sequence. Fails fast — a missing secret throws
|
|
176
241
|
* before store/signal/… open, so no request can be served.
|
|
@@ -183,204 +248,177 @@ export async function bootApplication(
|
|
|
183
248
|
const env: ConfigEnv = options.env ?? "dev";
|
|
184
249
|
const pre = options.elements ?? {};
|
|
185
250
|
const now = options.now ?? (() => Date.now());
|
|
251
|
+
const needs = resolveElementNeeds(options);
|
|
186
252
|
|
|
187
|
-
// 1. Vault
|
|
188
|
-
const vaultSecrets =
|
|
189
|
-
options.vault?.secrets ?? options.secrets ?? [];
|
|
253
|
+
// 1. Vault — module loads only when secrets (or a pre-built vault) exist.
|
|
190
254
|
let vault = pre.vault;
|
|
191
|
-
if (
|
|
192
|
-
vault
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
allowDevFallbacks:
|
|
201
|
-
options.vault?.allowDevFallbacks ?? env !== "prod",
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
if (vault && !vault.booted) {
|
|
205
|
-
await vault.boot();
|
|
255
|
+
if (needs.vault) {
|
|
256
|
+
if (!vault) {
|
|
257
|
+
const { bindVault } = await loadBind<
|
|
258
|
+
typeof import("./boot-bind/vault.ts")
|
|
259
|
+
>("vault");
|
|
260
|
+
vault = await bindVault(options, env);
|
|
261
|
+
} else if (!vault.booted) {
|
|
262
|
+
await vault.boot();
|
|
263
|
+
}
|
|
206
264
|
}
|
|
207
265
|
|
|
208
|
-
//
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
266
|
+
// Parallel-load remaining binders after Vault fail-fast.
|
|
267
|
+
const binderLoads: Promise<unknown>[] = [];
|
|
268
|
+
type StoreBind = typeof import("./boot-bind/store.ts");
|
|
269
|
+
type SignalBind = typeof import("./boot-bind/signal.ts");
|
|
270
|
+
type ClockBind = typeof import("./boot-bind/clock.ts");
|
|
271
|
+
type GateBind = typeof import("./boot-bind/gate.ts");
|
|
272
|
+
type ChannelBind = typeof import("./boot-bind/channel.ts");
|
|
273
|
+
type AiBind = typeof import("./boot-bind/ai.ts");
|
|
274
|
+
type RunsBind = typeof import("./boot-bind/runs.ts");
|
|
275
|
+
|
|
276
|
+
let storeBind: StoreBind | undefined;
|
|
277
|
+
let signalBind: SignalBind | undefined;
|
|
278
|
+
let clockBind: ClockBind | undefined;
|
|
279
|
+
let gateBind: GateBind | undefined;
|
|
280
|
+
let channelBind: ChannelBind | undefined;
|
|
281
|
+
let aiBind: AiBind | undefined;
|
|
282
|
+
let runsBind: RunsBind | undefined;
|
|
283
|
+
|
|
284
|
+
if (needs.store && !pre.store) {
|
|
285
|
+
binderLoads.push(
|
|
286
|
+
loadBind<StoreBind>("store").then((m) => {
|
|
287
|
+
storeBind = m;
|
|
288
|
+
}),
|
|
289
|
+
);
|
|
227
290
|
}
|
|
228
|
-
|
|
229
|
-
|
|
291
|
+
if (needs.signal && !pre.signal) {
|
|
292
|
+
binderLoads.push(
|
|
293
|
+
loadBind<SignalBind>("signal").then((m) => {
|
|
294
|
+
signalBind = m;
|
|
295
|
+
}),
|
|
296
|
+
);
|
|
230
297
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
void signalId;
|
|
238
|
-
signal = createSignalRuntime({
|
|
239
|
-
driver: memorySignalDriver,
|
|
240
|
-
now,
|
|
241
|
-
});
|
|
298
|
+
if (needs.clock) {
|
|
299
|
+
binderLoads.push(
|
|
300
|
+
loadBind<ClockBind>("clock").then((m) => {
|
|
301
|
+
clockBind = m;
|
|
302
|
+
}),
|
|
303
|
+
);
|
|
242
304
|
}
|
|
243
|
-
|
|
244
|
-
|
|
305
|
+
if (needs.gate && !pre.gate) {
|
|
306
|
+
binderLoads.push(
|
|
307
|
+
loadBind<GateBind>("gate").then((m) => {
|
|
308
|
+
gateBind = m;
|
|
309
|
+
}),
|
|
310
|
+
);
|
|
245
311
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
name: b.trigger.name,
|
|
253
|
-
delivery: "once",
|
|
254
|
-
retries: 3,
|
|
255
|
-
deadLetter: true,
|
|
256
|
-
optional: true,
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
}
|
|
312
|
+
if (needs.channel && !pre.channel) {
|
|
313
|
+
binderLoads.push(
|
|
314
|
+
loadBind<ChannelBind>("channel").then((m) => {
|
|
315
|
+
channelBind = m;
|
|
316
|
+
}),
|
|
317
|
+
);
|
|
260
318
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
if (b.trigger.kind !== "signal") continue;
|
|
268
|
-
const name = b.trigger.name;
|
|
269
|
-
if (seen.has(name)) continue;
|
|
270
|
-
seen.add(name);
|
|
271
|
-
await bus.subscribe(name, `oke:${name}`, async (msg) => {
|
|
272
|
-
await handler(name, msg.payload);
|
|
273
|
-
});
|
|
274
|
-
}
|
|
319
|
+
if (needs.ai && !pre.ai) {
|
|
320
|
+
binderLoads.push(
|
|
321
|
+
loadBind<AiBind>("ai").then((m) => {
|
|
322
|
+
aiBind = m;
|
|
323
|
+
}),
|
|
324
|
+
);
|
|
275
325
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
: createClockRuntime({ instanceId: options.instanceId, now });
|
|
326
|
+
if (
|
|
327
|
+
needs.runs &&
|
|
328
|
+
!pre.runs &&
|
|
329
|
+
!(options.runs && isRunsRuntime(options.runs))
|
|
330
|
+
) {
|
|
331
|
+
binderLoads.push(
|
|
332
|
+
loadBind<RunsBind>("runs").then((m) => {
|
|
333
|
+
runsBind = m;
|
|
334
|
+
}),
|
|
335
|
+
);
|
|
287
336
|
}
|
|
337
|
+
await Promise.all(binderLoads);
|
|
288
338
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
declareClock(b.trigger.interval, { every: b.trigger.interval }),
|
|
299
|
-
);
|
|
339
|
+
// 2. Store
|
|
340
|
+
let store = pre.store;
|
|
341
|
+
if (needs.store) {
|
|
342
|
+
if (!store) {
|
|
343
|
+
store = storeBind!.bindStore(options, env, now);
|
|
344
|
+
} else {
|
|
345
|
+
for (const decl of options.stores ?? []) {
|
|
346
|
+
store.register?.(decl);
|
|
347
|
+
}
|
|
300
348
|
}
|
|
301
349
|
}
|
|
302
|
-
for (const decl of clockDecls.values()) {
|
|
303
|
-
clock.register(decl);
|
|
304
|
-
}
|
|
305
|
-
await clock.reconcile();
|
|
306
350
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
351
|
+
// 3. Signals
|
|
352
|
+
let signal = pre.signal;
|
|
353
|
+
if (needs.signal) {
|
|
354
|
+
if (!signal) {
|
|
355
|
+
signal = await signalBind!.bindSignal(options, env, now);
|
|
356
|
+
} else {
|
|
357
|
+
// Pre-built: still register decls / start if needed.
|
|
358
|
+
for (const decl of options.signals ?? []) {
|
|
359
|
+
signal.register(decl);
|
|
360
|
+
}
|
|
361
|
+
if (!signal.bus) {
|
|
362
|
+
await signal.start();
|
|
363
|
+
}
|
|
313
364
|
}
|
|
314
365
|
}
|
|
315
366
|
|
|
316
|
-
//
|
|
317
|
-
|
|
318
|
-
const startScheduler =
|
|
319
|
-
options.startScheduler ?? (env !== "test");
|
|
367
|
+
// 4. Clocks + optional scheduler
|
|
368
|
+
let clock = pre.clock;
|
|
320
369
|
let schedulerTimer: ReturnType<typeof setInterval> | undefined;
|
|
321
|
-
if (
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
370
|
+
if (needs.clock) {
|
|
371
|
+
const bound = await clockBind!.bindClock(options, env, now, clock);
|
|
372
|
+
clock = bound.clock;
|
|
373
|
+
const startScheduler = options.startScheduler ?? env !== "test";
|
|
374
|
+
if (startScheduler) {
|
|
375
|
+
const period = options.schedulerIntervalMs ?? 1000;
|
|
376
|
+
const clockRt = clock;
|
|
377
|
+
schedulerTimer = setInterval(() => {
|
|
378
|
+
void clockRt.tick();
|
|
379
|
+
}, period);
|
|
380
|
+
schedulerTimer.unref?.();
|
|
381
|
+
}
|
|
328
382
|
}
|
|
329
383
|
|
|
330
|
-
// Gate
|
|
331
|
-
// pipeline and AI agents. Constructed before channel/AI bind.
|
|
384
|
+
// Gate (before AI)
|
|
332
385
|
let gate = pre.gate;
|
|
333
|
-
if (!gate) {
|
|
334
|
-
|
|
335
|
-
gate = createGateRuntime({
|
|
336
|
-
gates: options.gates ?? [],
|
|
337
|
-
kv: kvNs,
|
|
338
|
-
now,
|
|
339
|
-
});
|
|
386
|
+
if (needs.gate && !gate) {
|
|
387
|
+
gate = await gateBind!.bindGate(options, now);
|
|
340
388
|
}
|
|
341
389
|
|
|
342
|
-
// 5.
|
|
390
|
+
// 5. Channel
|
|
343
391
|
let channel = pre.channel;
|
|
344
|
-
if (!channel) {
|
|
345
|
-
channel =
|
|
346
|
-
...(options.channel ?? {}),
|
|
347
|
-
drivers: options.channel?.drivers ?? [openConsoleChannel()],
|
|
348
|
-
now,
|
|
349
|
-
});
|
|
392
|
+
if (needs.channel && !channel) {
|
|
393
|
+
channel = channelBind!.bindChannel(options, now);
|
|
350
394
|
}
|
|
351
395
|
|
|
352
|
-
// 6.
|
|
396
|
+
// 6. AI
|
|
353
397
|
let ai = pre.ai;
|
|
354
|
-
if (!ai) {
|
|
355
|
-
ai =
|
|
356
|
-
...(options.ai ?? {}),
|
|
357
|
-
defaultDriver: options.ai?.defaultDriver ?? mockAiDriver,
|
|
358
|
-
gates: options.ai?.gates ?? gate,
|
|
359
|
-
now,
|
|
360
|
-
});
|
|
398
|
+
if (needs.ai && !ai) {
|
|
399
|
+
ai = aiBind!.bindAi(options, gate, now);
|
|
361
400
|
}
|
|
362
401
|
|
|
363
|
-
// 7.
|
|
402
|
+
// 7. Runs
|
|
364
403
|
let runs = pre.runs;
|
|
365
|
-
if (
|
|
366
|
-
if (
|
|
367
|
-
runs
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
}
|
|
404
|
+
if (needs.runs) {
|
|
405
|
+
if (!runs) {
|
|
406
|
+
if (options.runs && isRunsRuntime(options.runs)) {
|
|
407
|
+
runs = options.runs;
|
|
408
|
+
if (!runs.store) await runs.open();
|
|
409
|
+
} else {
|
|
410
|
+
const runsOpts =
|
|
411
|
+
options.runs && !isRunsRuntime(options.runs)
|
|
412
|
+
? options.runs
|
|
413
|
+
: undefined;
|
|
414
|
+
runs = await runsBind!.bindRuns(runsOpts);
|
|
415
|
+
}
|
|
416
|
+
} else if (!runs.store) {
|
|
417
|
+
await runs.open();
|
|
377
418
|
}
|
|
378
419
|
}
|
|
379
|
-
if (runs && !runs.store) {
|
|
380
|
-
await runs.open();
|
|
381
|
-
}
|
|
382
420
|
|
|
383
|
-
// 8.
|
|
421
|
+
// 8. Caps — effect refs only; no element modules.
|
|
384
422
|
const capabilities = mintCapabilities(options.flows ?? []);
|
|
385
423
|
|
|
386
424
|
return {
|
package/src/kernel/index.ts
CHANGED