okengine 0.11.0 → 0.11.2

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 (68) hide show
  1. package/package.json +1 -1
  2. package/site/content/docs/elements/ai.mdx +22 -1
  3. package/site/content/docs/elements/store.mdx +3 -1
  4. package/site/content/docs/elements/vault.mdx +19 -11
  5. package/site/content/docs/get-started/installation.mdx +7 -1
  6. package/site/content/docs/recipes/llama-cpp.mdx +10 -9
  7. package/site/content/docs/reference/cli.md +6 -2
  8. package/site/content/docs/reference/environment-variables.mdx +9 -9
  9. package/src/cli/ai-setup/ai-setup.test.ts +3 -1
  10. package/src/cli/ai-setup/apply.ts +61 -1
  11. package/src/cli/ask-seed.test.ts +4 -3
  12. package/src/cli/ask-seed.ts +5 -6
  13. package/src/cli/client-add.test.ts +2 -1
  14. package/src/cli/dev.test.ts +116 -0
  15. package/src/cli/dev.ts +107 -18
  16. package/src/cli/project-state.test.ts +50 -0
  17. package/src/cli/project-state.ts +123 -0
  18. package/src/cli/vault-cmd.test.ts +47 -18
  19. package/src/cli/vault-cmd.ts +2 -1
  20. package/src/compiler/extract.ts +12 -1
  21. package/src/console/server/console.test.ts +3 -1
  22. package/src/console/server/operator-db.test.ts +48 -17
  23. package/src/console/server/operator-db.ts +5 -1
  24. package/src/docker/derive.ts +24 -3
  25. package/src/docker/docker.test.ts +4 -2
  26. package/src/docker/index.ts +1 -0
  27. package/src/docker/recipes/index.ts +1 -0
  28. package/src/docker/recipes/llama-cpp.ts +20 -4
  29. package/src/drivers/ai-openai-compatible.ts +15 -3
  30. package/src/drivers/vault-builtin.test.ts +50 -42
  31. package/src/elements/ai/declare.ts +73 -3
  32. package/src/elements/ai/errors.test.ts +35 -0
  33. package/src/elements/ai/errors.ts +139 -0
  34. package/src/elements/ai/eval.ts +26 -1
  35. package/src/elements/ai/runtime.ts +140 -80
  36. package/src/elements/ai/tools.test.ts +1 -1
  37. package/src/elements/ai.test.ts +99 -2
  38. package/src/elements/ai.ts +11 -1
  39. package/src/elements/gate/config.ts +13 -3
  40. package/src/elements/gate/declare.ts +1 -1
  41. package/src/elements/gate/strategies.ts +2 -12
  42. package/src/elements/index.ts +2 -0
  43. package/src/elements/store/index-boot.test.ts +23 -6
  44. package/src/elements/store/resource.test.ts +38 -19
  45. package/src/elements/store/sql-session.test.ts +55 -58
  46. package/src/elements/vault/builtin-adapter.test.ts +115 -58
  47. package/src/elements/vault/builtin-adapter.ts +241 -47
  48. package/src/elements/vault/chaos-child.ts +424 -0
  49. package/src/elements/vault/chaos.test.ts +651 -0
  50. package/src/elements/vault/resilience.ts +6 -1
  51. package/src/elements/vault/security-checklist.test.ts +10 -8
  52. package/src/elements/vault/storage.ts +130 -27
  53. package/src/elements/vault/test-helpers.ts +368 -0
  54. package/src/elements/vault.ts +6 -0
  55. package/src/index.ts +2 -0
  56. package/src/kernel/app-auth.ts +98 -0
  57. package/src/kernel/app.ts +120 -78
  58. package/src/kernel/auto-registry.test.ts +52 -1
  59. package/src/kernel/boot.test.ts +4 -18
  60. package/src/kernel/element-registries.ts +19 -4
  61. package/src/kernel/errors.ts +3 -3
  62. package/src/kernel/fx.test.ts +25 -0
  63. package/src/kernel/fx.ts +4 -1
  64. package/src/manifest/types.ts +4 -0
  65. package/src/release/build-lib.ts +3 -0
  66. package/src/shared/lazy-src.ts +79 -0
  67. package/src/test/create-test-app.ts +16 -11
  68. package/src/test/reset-element-registries.ts +17 -9
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Sync-load package-local modules that Bun.build leaves as runtime requires
3
+ * (not inlined). Bun `src/` first; published `dist/` chunks for `"import"`.
4
+ *
5
+ * Uses Bun APIs (`import.meta.dir`, `import.meta.require`) and try/catch load
6
+ * instead of exists()+require — Bun’s preferred pattern (the exists syscall
7
+ * is an extra round trip).
8
+ */
9
+
10
+ import { dirname, join } from "node:path";
11
+
12
+ let cachedRoot: string | undefined;
13
+
14
+ /**
15
+ * Try a sync `import.meta.require`; return `undefined` only when the file is missing.
16
+ *
17
+ * @typeParam T - Module namespace shape
18
+ * @param path - Absolute module path
19
+ */
20
+ function tryRequire<T>(path: string): T | undefined {
21
+ try {
22
+ return import.meta.require(path) as T;
23
+ } catch (err) {
24
+ const code =
25
+ err !== null && typeof err === "object" && "code" in err
26
+ ? String((err as { code?: unknown }).code)
27
+ : undefined;
28
+ if (
29
+ code === "MODULE_NOT_FOUND" ||
30
+ code === "ENOENT" ||
31
+ (err instanceof Error && /Cannot find module|ENOENT/i.test(err.message))
32
+ ) {
33
+ return undefined;
34
+ }
35
+ throw err;
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Walk up from this module to the okengine package root (`package.json` name).
41
+ */
42
+ export function okengineRoot(): string {
43
+ if (cachedRoot) return cachedRoot;
44
+ let dir = import.meta.dir;
45
+ for (let i = 0; i < 12; i++) {
46
+ const pkg = tryRequire<{ name?: string }>(join(dir, "package.json"));
47
+ if (pkg?.name === "okengine") {
48
+ cachedRoot = dir;
49
+ return dir;
50
+ }
51
+ const parent = dirname(dir);
52
+ if (parent === dir) break;
53
+ dir = parent;
54
+ }
55
+ throw new Error("okengine: package root not found from " + import.meta.dir);
56
+ }
57
+
58
+ /**
59
+ * Synchronously load `src/<rel>.ts` (Bun) or published `dist/<distName>.js`.
60
+ *
61
+ * @typeParam T - Module namespace shape
62
+ * @param relSrc - Path under `src/` without extension (e.g. `auth/config`)
63
+ * @param distName - Filename under `dist/` without extension (e.g. `auth-config`)
64
+ */
65
+ export function requirePackageModule<T>(relSrc: string, distName: string): T {
66
+ const root = okengineRoot();
67
+ const srcPath = join(root, "src", `${relSrc}.ts`);
68
+ const distPath = join(root, "dist", `${distName}.js`);
69
+ // Bun native TS — prefer source so local `oke` / tests stay on one graph.
70
+ if (typeof Bun !== "undefined") {
71
+ const fromSrc = tryRequire<T>(srcPath);
72
+ if (fromSrc !== undefined) return fromSrc;
73
+ }
74
+ const fromDist = tryRequire<T>(distPath);
75
+ if (fromDist !== undefined) return fromDist;
76
+ const fallback = tryRequire<T>(srcPath);
77
+ if (fallback !== undefined) return fallback;
78
+ throw new Error(`okengine: missing lazy module src/${relSrc}.ts or dist/${distName}.js`);
79
+ }
@@ -14,9 +14,6 @@
14
14
  * ```
15
15
  */
16
16
 
17
- import { mkdtemp, rm } from "node:fs/promises";
18
- import { tmpdir } from "node:os";
19
- import { join } from "node:path";
20
17
  import {
21
18
  createMockAiDriver,
22
19
  createChannelInbox,
@@ -215,15 +212,26 @@ export async function createTestApp<App extends OkeApp>(
215
212
  return out;
216
213
  };
217
214
 
218
- // Unique on-disk PGLite datadir per harness `memory://` is not reliably
219
- // isolated across boots in one worker (IF NOT EXISTS / row leaks).
220
- const prevPgliteUrl = process.env.OKE_PGLITE_URL;
221
- const pgliteDir = await mkdtemp(join(tmpdir(), "oke-pglite-"));
222
- process.env.OKE_PGLITE_URL = pgliteDir;
215
+ // Harness contract is in-process memory SQL (same as vault/channel/ai/runs).
216
+ // Global `STORE_SQL_DEFAULTS.test` is PGLite for real app boots do not inherit
217
+ // that here, or every insert pays cold WASM+pgvector init (~seconds). Dialects
218
+ // that need PGLite pass `boot.config.drivers.store.sql` explicitly.
219
+ const bootConfig = options.boot?.config;
220
+ const config = {
221
+ ...(bootConfig ?? {}),
222
+ drivers: {
223
+ ...(bootConfig?.drivers ?? {}),
224
+ store: {
225
+ ...(bootConfig?.drivers?.store ?? {}),
226
+ sql: bootConfig?.drivers?.store?.sql ?? { test: "memory" },
227
+ },
228
+ },
229
+ };
223
230
 
224
231
  await app.boot({
225
232
  ...(options.boot ?? {}),
226
233
  env: "test",
234
+ config,
227
235
  // Test-only opt-out (honoured because env is "test" below). Production
228
236
  // boots never skip posture via this flag.
229
237
  unguardedHttp: options.boot?.unguardedHttp ?? appOpts.gate?.unguardedHttp ?? "allow",
@@ -331,9 +339,6 @@ export async function createTestApp<App extends OkeApp>(
331
339
  },
332
340
  async close() {
333
341
  await app.bootResult?.close();
334
- if (prevPgliteUrl === undefined) delete process.env.OKE_PGLITE_URL;
335
- else process.env.OKE_PGLITE_URL = prevPgliteUrl;
336
- await rm(pgliteDir, { recursive: true, force: true }).catch(() => undefined);
337
342
  },
338
343
  };
339
344
 
@@ -1,22 +1,26 @@
1
1
  /**
2
2
  * Global safety net for the `store.sql` / `store.files` / `vault.secret` /
3
- * `signal()` / `channel.<medium>().template()` auto-registries
4
- * (`src/kernel/element-registries.ts`).
3
+ * `signal()` / `channel.<medium>().template()` / `ai.model`·prompt·embed·agent
4
+ * auto-registries (`src/kernel/element-registries.ts`).
5
5
  *
6
6
  * Unlike `on()` bindings — created almost exclusively to wire a real app —
7
- * these four factories are called throughout the suite as bare value
8
- * constructors, completely unrelated to booting an app (hundreds of call
9
- * sites across `src/elements/*.test.ts`). Since the registries are plain
10
- * module-level arrays shared by every test file in one `bun test` process,
11
- * leaving cleanup to per-file discipline (the convention `on.ts` relies on —
12
- * see `resetBindings()` / `registry: "ignore"`) would let stray decls from
13
- * one file silently reach a default-registry `oke()` call in a completely
7
+ * these factories are called throughout the suite as bare value constructors,
8
+ * completely unrelated to booting an app (hundreds of call sites across
9
+ * `src/elements/*.test.ts`). Since the registries are plain module-level
10
+ * arrays shared by every test file in one `bun test` process, leaving cleanup
11
+ * to per-file discipline (the convention `on.ts` relies on — see
12
+ * `resetBindings()` / `registry: "ignore"`) would let stray decls from one
13
+ * file silently reach a default-registry `oke()` call in a completely
14
14
  * unrelated file. Reset after every test, globally, via `bunfig.toml`
15
15
  * `[test].preload`.
16
16
  */
17
17
 
18
18
  import { afterEach } from "bun:test";
19
19
  import {
20
+ aiAgentRegistry,
21
+ aiEmbedRegistry,
22
+ aiModelRegistry,
23
+ aiPromptRegistry,
20
24
  channelTemplateRegistry,
21
25
  requiredEnvRegistry,
22
26
  secretRegistry,
@@ -30,4 +34,8 @@ afterEach(() => {
30
34
  requiredEnvRegistry.length = 0;
31
35
  signalRegistry.length = 0;
32
36
  channelTemplateRegistry.length = 0;
37
+ aiModelRegistry.length = 0;
38
+ aiPromptRegistry.length = 0;
39
+ aiEmbedRegistry.length = 0;
40
+ aiAgentRegistry.length = 0;
33
41
  });