@avocadostudio-ai/orchestrator-core 0.1.0 → 0.2.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 (61) hide show
  1. package/dist/agent/sites-agent-context.js +3 -2
  2. package/dist/agent/sites-agent-shared.js +1 -0
  3. package/dist/chat/anthropic-planner.js +3 -3
  4. package/dist/chat/chat-pipeline.js +122 -20
  5. package/dist/chat/gemini-planner.js +3 -3
  6. package/dist/chat/planner.js +7 -5
  7. package/dist/chat/prompts.js +6 -1
  8. package/dist/cms/adapter.d.ts +159 -1
  9. package/dist/cms/adapter.js +19 -1
  10. package/dist/cms/bootstrap.d.ts +46 -1
  11. package/dist/cms/bootstrap.js +126 -2
  12. package/dist/cms/index.d.ts +3 -2
  13. package/dist/cms/index.js +2 -1
  14. package/dist/errors.d.ts +9 -1
  15. package/dist/handler/auth.d.ts +79 -0
  16. package/dist/handler/auth.js +113 -0
  17. package/dist/handler/create-orchestrator.d.ts +205 -0
  18. package/dist/handler/create-orchestrator.js +1599 -0
  19. package/dist/http/access-tokens.d.ts +58 -0
  20. package/dist/http/access-tokens.js +161 -0
  21. package/dist/http/audio-actions.d.ts +121 -0
  22. package/dist/http/audio-actions.js +248 -0
  23. package/dist/http/blocks-actions.d.ts +31 -0
  24. package/dist/http/blocks-actions.js +31 -0
  25. package/dist/http/draft-provenance.d.ts +68 -0
  26. package/dist/http/draft-provenance.js +101 -0
  27. package/dist/http/history-actions.d.ts +58 -0
  28. package/dist/http/history-actions.js +169 -0
  29. package/dist/http/image-generate-actions.d.ts +268 -0
  30. package/dist/http/image-generate-actions.js +546 -0
  31. package/dist/http/ops-actions.d.ts +51 -0
  32. package/dist/http/ops-actions.js +79 -0
  33. package/dist/http/publish-actions.d.ts +153 -0
  34. package/dist/http/publish-actions.js +323 -0
  35. package/dist/http/restore-actions.d.ts +67 -0
  36. package/dist/http/restore-actions.js +145 -0
  37. package/dist/http/screenshot-actions.d.ts +108 -0
  38. package/dist/http/screenshot-actions.js +181 -0
  39. package/dist/http/session-actions.d.ts +35 -0
  40. package/dist/http/session-actions.js +98 -0
  41. package/dist/http/telemetry-feedback-actions.d.ts +53 -0
  42. package/dist/http/telemetry-feedback-actions.js +68 -0
  43. package/dist/http/unsplash-actions.d.ts +64 -0
  44. package/dist/http/unsplash-actions.js +81 -0
  45. package/dist/http/variations-actions.d.ts +102 -0
  46. package/dist/http/variations-actions.js +104 -0
  47. package/dist/index.d.ts +4 -1
  48. package/dist/index.js +21 -1
  49. package/dist/nlp/deterministic-planner-refs.d.ts +1 -1
  50. package/dist/nlp/deterministic-planner-suggestions.d.ts +10 -0
  51. package/dist/nlp/deterministic-planner-suggestions.js +37 -11
  52. package/dist/nlp/plan-normalizer.js +18 -2
  53. package/dist/ops/ops-engine.js +219 -14
  54. package/dist/state/session-state.d.ts +56 -1
  55. package/dist/state/session-state.js +92 -6
  56. package/dist/state/sqlite-store-singleton.d.ts +22 -0
  57. package/dist/state/sqlite-store-singleton.js +49 -1
  58. package/dist/state/sqlite-store.d.ts +5 -0
  59. package/dist/state/sqlite-store.js +125 -2
  60. package/dist/telemetry/chat-telemetry.js +6 -1
  61. package/package.json +12 -16
@@ -1,6 +1,128 @@
1
+ import { createRequire } from "node:module";
1
2
  import { mkdirSync } from "node:fs";
2
- import { dirname, resolve } from "node:path";
3
- import Database from "better-sqlite3";
3
+ import { dirname, join, resolve } from "node:path";
4
+ /*
5
+ * `better-sqlite3` is loaded at runtime, through a specifier no bundler can read.
6
+ *
7
+ * A static `import Database from "better-sqlite3"` is correct for the standalone
8
+ * Fastify server and wrong for every library-mode consumer. `createOrchestrator()`
9
+ * is mounted inside the integrator's own Next app, so their bundler traces this
10
+ * module and tries to pack a native `.node` binding. What comes out the other side
11
+ * is not a constructor, and the failure surfaces far from here: PBA logged
12
+ * `Failed to open orchestrator SQLite store { err: "Cannot read properties of
13
+ * undefined (reading 'indexOf')" }` once at boot and then a persist error on every
14
+ * single write, while `/ops` kept answering `status: "applied"`. Draft edits lived
15
+ * in one module instance and vanished on the next reload, silently re-seeded from
16
+ * the CMS.
17
+ *
18
+ * `createRequire` gives us Node's own resolver — including the native binding
19
+ * lookup that a bundle cannot reproduce — and the specifier is assembled at
20
+ * runtime so static analysis has nothing to follow. It stays synchronous, which is
21
+ * what lets `getStore()` keep its signature and all eight call sites stay as they
22
+ * are. The alternative, telling every integrator to add `better-sqlite3` to
23
+ * `serverExternalPackages`, pushes our dependency's shape into their config and
24
+ * fails closed only if they read the docs.
25
+ */
26
+ const SQLITE_SPECIFIER = ["better", "sqlite3"].join("-");
27
+ let cachedCtor = null;
28
+ /*
29
+ * How the native module is reached, and why it takes three attempts.
30
+ *
31
+ * A Next server bundle is hostile to every ordinary route in:
32
+ * - `require` is not defined — the emitted chunk is ESM.
33
+ * - `node:module` is stubbed, so an imported `createRequire` is `undefined`.
34
+ * - webpack special-cases the literal `createRequire(import.meta.url)` idiom
35
+ * and swaps in its own shim, which resolves against the bundle rather than
36
+ * the host and answers "Cannot find module" for a package that is installed.
37
+ *
38
+ * What survives is a dynamic `import()` whose specifier the bundler cannot read,
39
+ * built with `new Function` — the same technique `screenshot-actions.ts` uses to
40
+ * keep Playwright out of a consumer's bundle. It is async, which is why the
41
+ * driver is preloaded at boot (`preloadSqliteDriver`, awaited by
42
+ * `loadStateFromDisk`) rather than resolved lazily inside the constructor: that
43
+ * keeps `getStore()` synchronous and all eight of its call sites unchanged.
44
+ *
45
+ * The synchronous paths stay as fallbacks for the standalone server and for
46
+ * tests, which run this file as real ESM under tsx where `createRequire` is
47
+ * Node's own.
48
+ */
49
+ const runtimeImport = new Function("specifier", "return import(specifier)");
50
+ function asCtor(loaded) {
51
+ if (typeof loaded === "function")
52
+ return loaded;
53
+ const candidate = loaded?.default;
54
+ return typeof candidate === "function" ? candidate : null;
55
+ }
56
+ /**
57
+ * Resolve and cache the driver. Awaited once at startup; safe to call again.
58
+ * Throws with every attempt's failure when the module cannot be reached at all.
59
+ */
60
+ export async function preloadSqliteDriver() {
61
+ if (cachedCtor)
62
+ return;
63
+ const failures = [];
64
+ try {
65
+ const ctor = asCtor(await runtimeImport(SQLITE_SPECIFIER));
66
+ if (ctor) {
67
+ cachedCtor = ctor;
68
+ return;
69
+ }
70
+ failures.push("dynamic import: resolved to a namespace with no constructor");
71
+ }
72
+ catch (err) {
73
+ failures.push(`dynamic import: ${err instanceof Error ? err.message : String(err)}`);
74
+ }
75
+ try {
76
+ loadDatabaseCtorSync();
77
+ return;
78
+ }
79
+ catch (err) {
80
+ failures.push(err instanceof Error ? err.message : String(err));
81
+ }
82
+ throw new Error(driverError(failures));
83
+ }
84
+ function driverError(failures) {
85
+ return (`Could not load better-sqlite3 (${failures.join("; ")}). The orchestrator keeps ` +
86
+ "draft pages, undo stacks and the version log in SQLite; without it every edit " +
87
+ "is in-memory only and is lost on restart. Install it in the app that mounts " +
88
+ "createOrchestrator(): `npm install better-sqlite3`. A workspace link to " +
89
+ "orchestrator-core is not enough — a native module has to be resolvable from " +
90
+ "the host's own node_modules.");
91
+ }
92
+ function loadDatabaseCtorSync() {
93
+ if (cachedCtor)
94
+ return cachedCtor;
95
+ const failures = [];
96
+ const attempts = [
97
+ {
98
+ name: "createRequire(import.meta.url)",
99
+ load: () => createRequire(import.meta.url)(SQLITE_SPECIFIER)
100
+ },
101
+ {
102
+ // A plain path, not a file URL: `node:url` is stubbed in a bundle too, so
103
+ // `pathToFileURL` there is `undefined`. `createRequire` takes a filename.
104
+ name: "createRequire(cwd)",
105
+ load: () => createRequire(join(process.cwd(), "noop.js"))(SQLITE_SPECIFIER)
106
+ }
107
+ ];
108
+ for (const attempt of attempts) {
109
+ try {
110
+ const ctor = asCtor(attempt.load());
111
+ if (ctor) {
112
+ cachedCtor = ctor;
113
+ return ctor;
114
+ }
115
+ failures.push(`${attempt.name}: no constructor`);
116
+ }
117
+ catch (err) {
118
+ failures.push(`${attempt.name}: ${err instanceof Error ? err.message : String(err)}`);
119
+ }
120
+ }
121
+ throw new Error(driverError(failures));
122
+ }
123
+ function loadDatabaseCtor() {
124
+ return cachedCtor ?? loadDatabaseCtorSync();
125
+ }
4
126
  // ---------------------------------------------------------------------------
5
127
  // Caps (mirrors limits used by in-memory state)
6
128
  // ---------------------------------------------------------------------------
@@ -99,6 +221,7 @@ export class SqliteStore {
99
221
  if (file !== ":memory:") {
100
222
  mkdirSync(dirname(resolve(file)), { recursive: true });
101
223
  }
224
+ const Database = loadDatabaseCtor();
102
225
  this.db = new Database(file);
103
226
  this.db.pragma("foreign_keys = ON");
104
227
  if (useWal) {
@@ -174,7 +174,12 @@ export function createChatTelemetryStore(args) {
174
174
  "planning_exhausted",
175
175
  "planning_refusal",
176
176
  "planning_incomplete",
177
- "planning_missing"
177
+ "planning_missing",
178
+ // An `edit_plan` that carried no operations. It answers 200 and reads as
179
+ // success to the user, which is exactly why it has to count as a failure
180
+ // here — otherwise the one outcome nobody can see from the UI is also
181
+ // invisible in the numbers.
182
+ "empty_edit_plan"
178
183
  ]);
179
184
  const failures = recent.filter((row) => row.phase === "result" && row.outcome && failureOutcomes.has(row.outcome));
180
185
  const success = recent.filter((row) => row.phase === "result" && row.outcome === "applied");
package/package.json CHANGED
@@ -1,24 +1,18 @@
1
1
  {
2
2
  "name": "@avocadostudio-ai/orchestrator-core",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./package.json": "./package.json",
7
7
  ".": {
8
8
  "types": "./dist/index.d.ts",
9
- "import": "./dist/index.js"
9
+ "import": "./dist/index.js",
10
+ "default": "./dist/index.js"
10
11
  },
11
12
  "./cms": {
12
13
  "types": "./dist/cms/index.d.ts",
13
- "import": "./dist/cms/index.js"
14
- },
15
- "./*.js": {
16
- "types": "./dist/*.d.ts",
17
- "import": "./dist/*.js"
18
- },
19
- "./*": {
20
- "types": "./dist/*.d.ts",
21
- "import": "./dist/*.js"
14
+ "import": "./dist/cms/index.js",
15
+ "default": "./dist/cms/index.js"
22
16
  }
23
17
  },
24
18
  "dependencies": {
@@ -29,15 +23,16 @@
29
23
  "openai": "^4.87.1",
30
24
  "sharp": "^0.34.5",
31
25
  "zod": "^4.3.6",
32
- "@avocadostudio-ai/shared": "0.1.0",
33
- "@avocadostudio-ai/migration-sdk": "0.1.0"
26
+ "@avocadostudio-ai/migration-sdk": "0.2.0",
27
+ "@avocadostudio-ai/shared": "0.2.0"
34
28
  },
35
29
  "devDependencies": {
30
+ "@google/genai": "^1.46.0",
36
31
  "@types/better-sqlite3": "^7.6.13",
37
32
  "@types/node": "^22.13.10",
38
- "typescript": "^5.7.3",
39
33
  "googleapis": "^171.4.0",
40
- "@google/genai": "^1.46.0"
34
+ "tsx": "^4.21.0",
35
+ "typescript": "^5.7.3"
41
36
  },
42
37
  "main": "dist/index.js",
43
38
  "types": "dist/index.d.ts",
@@ -73,6 +68,7 @@
73
68
  },
74
69
  "scripts": {
75
70
  "typecheck": "tsc --noEmit",
76
- "build": "tsc -p tsconfig.build.json && node ./scripts/copy-assets.mjs"
71
+ "build": "tsc -p tsconfig.build.json && node ./scripts/copy-assets.mjs",
72
+ "test": "NODE_ENV=test node ../../scripts/run-tests.mjs"
77
73
  }
78
74
  }