robrain 2.4.4 → 2.4.6

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 (60) hide show
  1. package/dist/commands/check.d.ts +2 -0
  2. package/dist/commands/check.d.ts.map +1 -0
  3. package/dist/commands/check.js +73 -0
  4. package/dist/commands/check.js.map +1 -0
  5. package/dist/commands/doctor.d.ts.map +1 -1
  6. package/dist/commands/doctor.js +41 -5
  7. package/dist/commands/doctor.js.map +1 -1
  8. package/dist/commands/export-memory.js +1 -1
  9. package/dist/commands/export-memory.js.map +1 -1
  10. package/dist/commands/init-project.d.ts +2 -0
  11. package/dist/commands/init-project.d.ts.map +1 -1
  12. package/dist/commands/init-project.js +71 -12
  13. package/dist/commands/init-project.js.map +1 -1
  14. package/dist/commands/inject.js +1 -1
  15. package/dist/commands/inject.js.map +1 -1
  16. package/dist/commands/install.d.ts.map +1 -1
  17. package/dist/commands/install.js +36 -8
  18. package/dist/commands/install.js.map +1 -1
  19. package/dist/commands/review.js +2 -2
  20. package/dist/commands/review.js.map +1 -1
  21. package/dist/commands/synth.d.ts.map +1 -1
  22. package/dist/commands/synth.js +48 -8
  23. package/dist/commands/synth.js.map +1 -1
  24. package/dist/commands/up.d.ts +3 -3
  25. package/dist/commands/up.d.ts.map +1 -1
  26. package/dist/commands/up.js +4 -3
  27. package/dist/commands/up.js.map +1 -1
  28. package/dist/commands/up.test.js +3 -0
  29. package/dist/commands/up.test.js.map +1 -1
  30. package/dist/index.js +13 -3
  31. package/dist/index.js.map +1 -1
  32. package/dist/lib/editor.codex.test.js +47 -1
  33. package/dist/lib/editor.codex.test.js.map +1 -1
  34. package/dist/lib/editor.d.ts +40 -4
  35. package/dist/lib/editor.d.ts.map +1 -1
  36. package/dist/lib/editor.js +112 -28
  37. package/dist/lib/editor.js.map +1 -1
  38. package/dist/lib/editor.stale-block.test.d.ts +2 -0
  39. package/dist/lib/editor.stale-block.test.d.ts.map +1 -0
  40. package/dist/lib/editor.stale-block.test.js +61 -0
  41. package/dist/lib/editor.stale-block.test.js.map +1 -0
  42. package/dist/lib/load-env.d.ts +8 -0
  43. package/dist/lib/load-env.d.ts.map +1 -1
  44. package/dist/lib/load-env.js +25 -4
  45. package/dist/lib/load-env.js.map +1 -1
  46. package/dist/lib/synthesis-bundle.d.ts +24 -0
  47. package/dist/lib/synthesis-bundle.d.ts.map +1 -0
  48. package/dist/lib/synthesis-bundle.js +52 -0
  49. package/dist/lib/synthesis-bundle.js.map +1 -0
  50. package/dist/lib/synthesis-bundle.test.d.ts +2 -0
  51. package/dist/lib/synthesis-bundle.test.d.ts.map +1 -0
  52. package/dist/lib/synthesis-bundle.test.js +61 -0
  53. package/dist/lib/synthesis-bundle.test.js.map +1 -0
  54. package/package.json +2 -2
  55. package/scripts/vendor-synthesis.mjs +32 -0
  56. package/scripts/verify-publish-tarball.mjs +21 -0
  57. package/vendor/sensing-mcp/dist/index.js +8 -7
  58. package/vendor/sensing-mcp/package.json +1 -1
  59. package/vendor/synthesis/dist/index.js +17382 -0
  60. package/vendor/synthesis/package.json +7 -0
@@ -2,10 +2,14 @@
2
2
  // Empty-string shell vars (`ANTHROPIC_API_KEY=`) block naive dotenv — treat them as unset so `.env` fills in.
3
3
  import { createRequire } from 'node:module';
4
4
  import { existsSync, readFileSync } from 'node:fs';
5
+ import { homedir } from 'node:os';
5
6
  import { dirname, join } from 'node:path';
6
7
  import { fileURLToPath } from 'node:url';
7
- /** `dotenv.parse` via CJS resolver — avoids NodeNext interop typing issues. */
8
- const dotenvParse = createRequire(import.meta.url)('dotenv');
8
+ let dotenvModule;
9
+ function dotenvParse() {
10
+ dotenvModule ??= createRequire(import.meta.url)('dotenv');
11
+ return dotenvModule;
12
+ }
9
13
  /** Paths checked in order; earlier paths win per key when merging into process.env. */
10
14
  function candidateEnvPaths(repoRoot) {
11
15
  const paths = [];
@@ -24,7 +28,7 @@ function isUnsetOrEmptyShell(v) {
24
28
  /** Apply each key from a `.env` file only when the current process.env value is unset or empty. */
25
29
  function mergeEnvFromFile(path) {
26
30
  const raw = readFileSync(path);
27
- const parsed = dotenvParse.parse(raw);
31
+ const parsed = dotenvParse().parse(raw);
28
32
  for (const [key, value] of Object.entries(parsed)) {
29
33
  if (!isUnsetOrEmptyShell(process.env[key]))
30
34
  continue;
@@ -38,6 +42,23 @@ export function loadCliEnv(repoRoot) {
38
42
  mergeEnvFromFile(path);
39
43
  }
40
44
  }
45
+ /**
46
+ * `robrain up` writes the host-side DATABASE_URL (+ provider keys) into
47
+ * ~/.robrain/stack/.env. Fill vars still unset/empty in `env` from it so
48
+ * no-clone flows (`robrain up` then `robrain synth`) work without exporting
49
+ * anything. Shell exports and repo/cwd `.env` keep priority — loadCliEnv
50
+ * runs first and this only fills the gaps.
51
+ */
52
+ export function applyStackEnvFallback(env, stackEnvPath = join(homedir(), '.robrain', 'stack', '.env')) {
53
+ if (!existsSync(stackEnvPath))
54
+ return;
55
+ const parsed = dotenvParse().parse(readFileSync(stackEnvPath));
56
+ for (const [key, value] of Object.entries(parsed)) {
57
+ if (!isUnsetOrEmptyShell(env[key]) || value === '')
58
+ continue;
59
+ env[key] = value;
60
+ }
61
+ }
41
62
  /**
42
63
  * When running the CLI from a git checkout (e.g. `node packages/cli/bin/robrain.js`),
43
64
  * find that checkout's root so repo `.env` matches `pnpm docker:up` / docker-compose.
@@ -71,7 +92,7 @@ export function readDotenvKey(repoRoot, key) {
71
92
  const path = join(repoRoot, '.env');
72
93
  if (!existsSync(path))
73
94
  return undefined;
74
- const parsed = dotenvParse.parse(readFileSync(path));
95
+ const parsed = dotenvParse().parse(readFileSync(path));
75
96
  const v = parsed[key];
76
97
  if (v === undefined || String(v).trim() === '')
77
98
  return undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"load-env.js","sourceRoot":"","sources":["../../src/lib/load-env.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"load-env.js","sourceRoot":"","sources":["../../src/lib/load-env.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export declare class SynthesisResolveError extends Error {
2
+ name: string;
3
+ }
4
+ export interface ResolvedSynthesis {
5
+ /** Path to the built synthesis entrypoint (dist/index.js). */
6
+ entry: string;
7
+ /** Set when running from a repo checkout — used as the child cwd so Synthesis finds the checkout's `.env`. */
8
+ repoRoot?: string;
9
+ }
10
+ export interface ResolveSynthesisOptions {
11
+ /** Override for tests; defaults to two levels above dist/lib. */
12
+ cliRoot?: string;
13
+ /** Checkout root override for tests: `null` forces "no checkout found". */
14
+ checkoutRoot?: string | null;
15
+ }
16
+ /**
17
+ * Locate the built synthesis entrypoint, first match wins:
18
+ * 1. ROBRAIN_REPO → <repo>/packages/synthesis/dist/index.js
19
+ * 2. robrain checkout → same, when the CLI itself runs from one (or cwd is one)
20
+ * 3. vendored bundle → <cli-root>/vendor/synthesis/dist/index.js (published tarball)
21
+ * Throws SynthesisResolveError with a remediation message.
22
+ */
23
+ export declare function resolveSynthesisEntry(env?: NodeJS.ProcessEnv, opts?: ResolveSynthesisOptions): ResolvedSynthesis;
24
+ //# sourceMappingURL=synthesis-bundle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"synthesis-bundle.d.ts","sourceRoot":"","sources":["../../src/lib/synthesis-bundle.ts"],"names":[],"mappings":"AAYA,qBAAa,qBAAsB,SAAQ,KAAK;IACrC,IAAI,SAA0B;CACxC;AAED,MAAM,WAAW,iBAAiB;IAChC,8DAA8D;IAC9D,KAAK,EAAE,MAAM,CAAA;IACb,8GAA8G;IAC9G,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,uBAAuB;IACtC,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC7B;AAkBD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,IAAI,GAAE,uBAA4B,GACjC,iBAAiB,CAwBnB"}
@@ -0,0 +1,52 @@
1
+ // packages/cli/src/lib/synthesis-bundle.ts
2
+ // Locate the built @robrain/synthesis bundle shipped with this CLI.
3
+ // Published tarballs carry it under vendor/; checkouts resolve packages/synthesis.
4
+ //
5
+ // Node-builtins only — verify-publish-tarball.mjs imports this from a bare
6
+ // extracted tarball with no node_modules (same constraint as mcp-bundle.ts).
7
+ import { existsSync } from 'fs';
8
+ import { dirname, join, resolve } from 'path';
9
+ import { fileURLToPath } from 'url';
10
+ import { inferLocalRobrainMonorepoRoot, inferRobrainMonorepoRootFromCwd } from './load-env.js';
11
+ export class SynthesisResolveError extends Error {
12
+ name = 'SynthesisResolveError';
13
+ }
14
+ function builtEntryOrThrow(repoRoot) {
15
+ const pkgDir = join(repoRoot, 'packages', 'synthesis');
16
+ if (!existsSync(pkgDir)) {
17
+ throw new SynthesisResolveError(`${repoRoot} does not look like a robrain checkout — packages/synthesis not found.`);
18
+ }
19
+ const entry = join(pkgDir, 'dist', 'index.js');
20
+ if (!existsSync(entry)) {
21
+ throw new SynthesisResolveError(`synthesis is not built in ${repoRoot} — from the repo root run: pnpm install && pnpm --filter @robrain/synthesis build`);
22
+ }
23
+ return entry;
24
+ }
25
+ /**
26
+ * Locate the built synthesis entrypoint, first match wins:
27
+ * 1. ROBRAIN_REPO → <repo>/packages/synthesis/dist/index.js
28
+ * 2. robrain checkout → same, when the CLI itself runs from one (or cwd is one)
29
+ * 3. vendored bundle → <cli-root>/vendor/synthesis/dist/index.js (published tarball)
30
+ * Throws SynthesisResolveError with a remediation message.
31
+ */
32
+ export function resolveSynthesisEntry(env = process.env, opts = {}) {
33
+ const envRoot = env.ROBRAIN_REPO?.trim();
34
+ if (envRoot) {
35
+ const repoRoot = resolve(envRoot);
36
+ return { entry: builtEntryOrThrow(repoRoot), repoRoot };
37
+ }
38
+ const checkoutRoot = opts.checkoutRoot !== undefined
39
+ ? opts.checkoutRoot
40
+ : inferLocalRobrainMonorepoRoot() ?? inferRobrainMonorepoRootFromCwd();
41
+ if (checkoutRoot) {
42
+ return { entry: builtEntryOrThrow(checkoutRoot), repoRoot: checkoutRoot };
43
+ }
44
+ const cliRoot = opts.cliRoot ?? join(dirname(fileURLToPath(import.meta.url)), '..', '..');
45
+ const vendored = join(cliRoot, 'vendor', 'synthesis', 'dist', 'index.js');
46
+ if (existsSync(vendored)) {
47
+ return { entry: vendored };
48
+ }
49
+ throw new SynthesisResolveError('could not find the Synthesis bundle. Update the CLI (npx robrain@latest synth) — ' +
50
+ 'older versions only ship Synthesis inside the repo — or point ROBRAIN_REPO at a robrain checkout.');
51
+ }
52
+ //# sourceMappingURL=synthesis-bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"synthesis-bundle.js","sourceRoot":"","sources":["../../src/lib/synthesis-bundle.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,oEAAoE;AACpE,mFAAmF;AACnF,EAAE;AACF,2EAA2E;AAC3E,6EAA6E;AAE7E,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAA;AAC/B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAA;AACnC,OAAO,EAAE,6BAA6B,EAAE,+BAA+B,EAAE,MAAM,eAAe,CAAA;AAE9F,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IACrC,IAAI,GAAG,uBAAuB,CAAA;CACxC;AAgBD,SAAS,iBAAiB,CAAC,QAAgB;IACzC,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,WAAW,CAAC,CAAA;IACtD,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,qBAAqB,CAC7B,GAAG,QAAQ,wEAAwE,CACpF,CAAA;IACH,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,CAAA;IAC9C,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,qBAAqB,CAC7B,6BAA6B,QAAQ,mFAAmF,CACzH,CAAA;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAAyB,OAAO,CAAC,GAAG,EACpC,OAAgC,EAAE;IAElC,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,EAAE,IAAI,EAAE,CAAA;IACxC,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;QACjC,OAAO,EAAE,KAAK,EAAE,iBAAiB,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAA;IACzD,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,KAAK,SAAS;QAClD,CAAC,CAAC,IAAI,CAAC,YAAY;QACnB,CAAC,CAAC,6BAA6B,EAAE,IAAI,+BAA+B,EAAE,CAAA;IACxE,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,EAAE,KAAK,EAAE,iBAAiB,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAA;IAC3E,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;IACzF,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,CAAA;IACzE,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAA;IAC5B,CAAC;IAED,MAAM,IAAI,qBAAqB,CAC7B,mFAAmF;QACnF,mGAAmG,CACpG,CAAA;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=synthesis-bundle.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"synthesis-bundle.test.d.ts","sourceRoot":"","sources":["../../src/lib/synthesis-bundle.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,61 @@
1
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'fs';
2
+ import { tmpdir } from 'os';
3
+ import { join } from 'path';
4
+ import { describe, it, beforeEach, afterEach } from 'node:test';
5
+ import assert from 'node:assert/strict';
6
+ import { resolveSynthesisEntry, SynthesisResolveError } from './synthesis-bundle.js';
7
+ let root;
8
+ function writeBuiltSynthesis(repoRoot) {
9
+ const dist = join(repoRoot, 'packages', 'synthesis', 'dist');
10
+ mkdirSync(dist, { recursive: true });
11
+ const entry = join(dist, 'index.js');
12
+ writeFileSync(entry, '// built synthesis bundle');
13
+ return entry;
14
+ }
15
+ beforeEach(() => {
16
+ root = mkdtempSync(join(tmpdir(), 'robrain-synth-'));
17
+ });
18
+ afterEach(() => {
19
+ rmSync(root, { recursive: true, force: true });
20
+ });
21
+ describe('resolveSynthesisEntry', () => {
22
+ it('prefers a built ROBRAIN_REPO checkout and reports it as repoRoot', () => {
23
+ const repo = join(root, 'clone');
24
+ const entry = writeBuiltSynthesis(repo);
25
+ const resolved = resolveSynthesisEntry({ ROBRAIN_REPO: repo }, { checkoutRoot: null });
26
+ assert.equal(resolved.entry, entry);
27
+ assert.equal(resolved.repoRoot, repo);
28
+ });
29
+ it('rejects a ROBRAIN_REPO that is not a robrain checkout', () => {
30
+ const notRepo = join(root, 'elsewhere');
31
+ mkdirSync(notRepo, { recursive: true });
32
+ assert.throws(() => resolveSynthesisEntry({ ROBRAIN_REPO: notRepo }, { checkoutRoot: null }), SynthesisResolveError);
33
+ });
34
+ it('tells the user to build when the checkout has no dist', () => {
35
+ const repo = join(root, 'clone');
36
+ mkdirSync(join(repo, 'packages', 'synthesis'), { recursive: true });
37
+ assert.throws(() => resolveSynthesisEntry({ ROBRAIN_REPO: repo }, { checkoutRoot: null }), /pnpm install && pnpm --filter @robrain\/synthesis build/);
38
+ });
39
+ it('uses an inferred checkout when ROBRAIN_REPO is unset', () => {
40
+ const repo = join(root, 'checkout');
41
+ const entry = writeBuiltSynthesis(repo);
42
+ const resolved = resolveSynthesisEntry({}, { checkoutRoot: repo });
43
+ assert.equal(resolved.entry, entry);
44
+ assert.equal(resolved.repoRoot, repo);
45
+ });
46
+ it('falls back to the vendored bundle with no checkout anywhere', () => {
47
+ const cliRoot = join(root, 'npx-cache', 'node_modules', 'robrain');
48
+ const vendoredDist = join(cliRoot, 'vendor', 'synthesis', 'dist');
49
+ mkdirSync(vendoredDist, { recursive: true });
50
+ writeFileSync(join(vendoredDist, 'index.js'), '// vendored synthesis bundle');
51
+ const resolved = resolveSynthesisEntry({}, { checkoutRoot: null, cliRoot });
52
+ assert.equal(resolved.entry, join(vendoredDist, 'index.js'));
53
+ assert.equal(resolved.repoRoot, undefined);
54
+ });
55
+ it('throws a remediation message when nothing resolves', () => {
56
+ const cliRoot = join(root, 'bare');
57
+ mkdirSync(cliRoot, { recursive: true });
58
+ assert.throws(() => resolveSynthesisEntry({}, { checkoutRoot: null, cliRoot }), /npx robrain@latest synth|ROBRAIN_REPO/);
59
+ });
60
+ });
61
+ //# sourceMappingURL=synthesis-bundle.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"synthesis-bundle.test.js","sourceRoot":"","sources":["../../src/lib/synthesis-bundle.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,IAAI,CAAA;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAA;AAC3B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAC/D,OAAO,MAAM,MAAM,oBAAoB,CAAA;AACvC,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAEpF,IAAI,IAAY,CAAA;AAEhB,SAAS,mBAAmB,CAAC,QAAgB;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,CAAC,CAAA;IAC5D,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;IACpC,aAAa,CAAC,KAAK,EAAE,2BAA2B,CAAC,CAAA;IACjD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,UAAU,CAAC,GAAG,EAAE;IACd,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAA;AACtD,CAAC,CAAC,CAAA;AAEF,SAAS,CAAC,GAAG,EAAE;IACb,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;AAChD,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAChC,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAA;QACvC,MAAM,QAAQ,GAAG,qBAAqB,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAA;QACtF,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;QACnC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IACvC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAA;QACvC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACvC,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,CAAC,qBAAqB,CAAC,EAAE,YAAY,EAAE,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,EAC9E,qBAAqB,CACtB,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAChC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACnE,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,CAAC,qBAAqB,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,EAC3E,yDAAyD,CAC1D,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;QACnC,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAA;QACvC,MAAM,QAAQ,GAAG,qBAAqB,CAAC,EAAE,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAA;QAClE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;QACnC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IACvC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,CAAC,CAAA;QAClE,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,CAAC,CAAA;QACjE,SAAS,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAC5C,aAAa,CAAC,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,EAAE,8BAA8B,CAAC,CAAA;QAC7E,MAAM,QAAQ,GAAG,qBAAqB,CAAC,EAAE,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;QAC3E,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,CAAA;QAC5D,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;IAC5C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QAClC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACvC,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,CAAC,qBAAqB,CAAC,EAAE,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAChE,uCAAuC,CACxC,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "robrain",
3
- "version": "2.4.4",
3
+ "version": "2.4.6",
4
4
  "type": "module",
5
5
  "description": "RoBrain CLI for installation, setup, and memory workflows",
6
6
  "author": "Rory Plans, Inc.",
@@ -57,7 +57,7 @@
57
57
  "build": "tsc",
58
58
  "dev": "tsc --watch",
59
59
  "typecheck": "tsc --noEmit",
60
- "test": "pnpm build && node --test dist/lib/editor.codex.test.js dist/lib/release-guard.test.js dist/lib/mcp-bundle.test.js dist/lib/control-bundle.test.js dist/lib/claude-plugin.test.js dist/lib/hermes-plugin.test.js dist/lib/codex-hooks.test.js dist/commands/outcomes.test.js dist/commands/export-interchange.test.js dist/commands/up.test.js dist/commands/mcp.test.js dist/commands/install.test.js",
60
+ "test": "pnpm build && node --test dist/lib/editor.codex.test.js dist/lib/editor.stale-block.test.js dist/lib/release-guard.test.js dist/lib/mcp-bundle.test.js dist/lib/control-bundle.test.js dist/lib/claude-plugin.test.js dist/lib/hermes-plugin.test.js dist/lib/codex-hooks.test.js dist/commands/outcomes.test.js dist/commands/export-interchange.test.js dist/commands/up.test.js dist/commands/mcp.test.js dist/commands/install.test.js dist/lib/synthesis-bundle.test.js",
61
61
  "pack:verify": "node scripts/verify-publish-tarball.mjs",
62
62
  "postinstall": "node scripts/chmod-bin.cjs"
63
63
  }
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ // Copy the built synthesis bundle into vendor/ so the published robrain
3
+ // tarball is self-contained — `npx robrain synth` runs without a repo clone.
4
+ import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'fs'
5
+ import { dirname, join } from 'path'
6
+ import { fileURLToPath } from 'url'
7
+
8
+ const cliRoot = join(dirname(fileURLToPath(import.meta.url)), '..')
9
+ const src = join(cliRoot, '..', 'synthesis')
10
+ const dest = join(cliRoot, 'vendor', 'synthesis')
11
+ const srcEntry = join(src, 'dist', 'index.js')
12
+
13
+ if (!existsSync(srcEntry)) {
14
+ console.error('vendor-synthesis: missing', srcEntry)
15
+ console.error('Run: pnpm --filter @robrain/synthesis build')
16
+ process.exit(1)
17
+ }
18
+
19
+ const version = JSON.parse(readFileSync(join(src, 'package.json'), 'utf8')).version
20
+
21
+ rmSync(dest, { recursive: true, force: true })
22
+ mkdirSync(join(dest, 'dist'), { recursive: true })
23
+ cpSync(join(src, 'dist'), join(dest, 'dist'), { recursive: true })
24
+ writeFileSync(
25
+ join(dest, 'package.json'),
26
+ JSON.stringify(
27
+ { name: '@robrain/synthesis', version, private: true, type: 'module', main: './dist/index.js' },
28
+ null,
29
+ 2,
30
+ ) + '\n',
31
+ )
32
+ console.log(`Vendored synthesis@${version} → packages/cli/vendor/synthesis`)
@@ -19,6 +19,7 @@ mkdirSync(work, { recursive: true })
19
19
 
20
20
  try {
21
21
  execFileSync('node', ['scripts/vendor-sensing-mcp.mjs'], { cwd: cliRoot, stdio: 'inherit' })
22
+ execFileSync('node', ['scripts/vendor-synthesis.mjs'], { cwd: cliRoot, stdio: 'inherit' })
22
23
  execFileSync('node', ['scripts/vendor-hermes-plugin.mjs'], { cwd: cliRoot, stdio: 'inherit' })
23
24
  execFileSync('node', ['scripts/vendor-codex-hooks.mjs'], { cwd: cliRoot, stdio: 'inherit' })
24
25
 
@@ -51,6 +52,26 @@ try {
51
52
  fail(`resolved dir has no dist/index.js: ${dir}`)
52
53
  }
53
54
 
55
+ const synthVendorEntry = join(extracted, 'vendor', 'synthesis', 'dist', 'index.js')
56
+ if (!existsSync(synthVendorEntry)) {
57
+ fail('vendor/synthesis/dist/index.js missing from tarball')
58
+ }
59
+
60
+ const synthUrl = pathToFileURL(join(extracted, 'dist', 'lib', 'synthesis-bundle.js')).href
61
+ const { resolveSynthesisEntry } = await import(synthUrl)
62
+ // Empty env + checkoutRoot:null simulates an npx install outside any checkout —
63
+ // the resolver must land on the tarball's own vendored bundle.
64
+ const synthResolved = resolveSynthesisEntry({}, { checkoutRoot: null })
65
+ if (!existsSync(synthResolved.entry)) {
66
+ fail(`resolveSynthesisEntry() entry does not exist: ${synthResolved.entry}`)
67
+ }
68
+ // realpath both sides — on macOS the tmpdir is reached via the /var →
69
+ // /private/var symlink, so raw equality false-negatives.
70
+ const { realpathSync: realpath } = await import('fs')
71
+ if (realpath(synthResolved.entry) !== realpath(synthVendorEntry)) {
72
+ fail(`resolveSynthesisEntry() did not pick the tarball's vendored bundle: ${synthResolved.entry}`)
73
+ }
74
+
54
75
  const hermesVendorEntry = join(extracted, 'vendor', 'hermes-plugin', 'robrain', '__init__.py')
55
76
  if (!existsSync(hermesVendorEntry)) {
56
77
  fail('vendor/hermes-plugin/robrain/__init__.py missing from tarball')
@@ -6432,8 +6432,8 @@ var require_llm = __commonJS({
6432
6432
  return env.LLM_PROVIDER?.trim().toLowerCase() === "openai" ? "openai" : "anthropic";
6433
6433
  }
6434
6434
  exports.DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1";
6435
- function resolveOpenAiBaseUrl2(env = process.env) {
6436
- const raw = env.OPENAI_BASE_URL?.trim();
6435
+ function resolveOpenAiBaseUrl2(env = process.env, options = {}) {
6436
+ const raw = options.preferHost ? env.OPENAI_HOST_BASE_URL?.trim() || env.OPENAI_BASE_URL?.trim() : env.OPENAI_BASE_URL?.trim();
6437
6437
  if (!raw)
6438
6438
  return exports.DEFAULT_OPENAI_BASE_URL;
6439
6439
  return (0, load_env_js_1.normalizeLoopbackUrl)(raw.replace(/\/+$/, ""));
@@ -6538,12 +6538,12 @@ var require_embeddings = __commonJS({
6538
6538
  exports.DEFAULT_EMBEDDING_TIMEOUT_MS = 15e3;
6539
6539
  var DEFAULT_MAX_ATTEMPTS = 5;
6540
6540
  var DEFAULT_BASE_DELAY_MS = 350;
6541
- function resolveEmbeddingConfig2(env = process.env) {
6541
+ function resolveEmbeddingConfig2(env = process.env, options = {}) {
6542
6542
  const dims = Number(env.OPENAI_EMBEDDING_DIMENSIONS);
6543
6543
  return {
6544
6544
  provider: env.EMBEDDING_PROVIDER ?? "openai",
6545
6545
  openaiApiKey: env.OPENAI_API_KEY,
6546
- openaiBaseUrl: (env.OPENAI_BASE_URL ?? llm_js_1.DEFAULT_OPENAI_BASE_URL).replace(/\/+$/, ""),
6546
+ openaiBaseUrl: (0, llm_js_1.resolveOpenAiBaseUrl)(env, options),
6547
6547
  openaiModel: env.OPENAI_EMBEDDING_MODEL ?? exports.DEFAULT_OPENAI_EMBEDDING_MODEL,
6548
6548
  openaiDimensions: Number.isFinite(dims) && dims > 0 ? dims : void 0,
6549
6549
  voyageApiKey: env.VOYAGE_API_KEY,
@@ -22742,7 +22742,8 @@ var init_config = __esm({
22742
22742
  // OPENAI_BASE_URL — point the OpenAI-compatible calls (LLM_PROVIDER=openai
22743
22743
  // chat AND EMBEDDING_PROVIDER=openai embeddings) at Ollama / LM Studio /
22744
22744
  // vLLM for a fully-local setup. When set, OPENAI_API_KEY becomes optional.
22745
- openaiBaseUrl: (0, import_shared.resolveOpenAiBaseUrl)(),
22745
+ // preferHost: OPENAI_HOST_BASE_URL wins when set (host vs Docker URL split).
22746
+ openaiBaseUrl: (0, import_shared.resolveOpenAiBaseUrl)(process.env, { preferHost: true }),
22746
22747
  // ── Anthropic (needed for decision classifier Stage 2 — Haiku) ─
22747
22748
  // Not validated at process start so the MCP server can boot when Cursor
22748
22749
  // does not inject env (set ANTHROPIC_API_KEY in MCP server config or shell).
@@ -22754,7 +22755,7 @@ var init_config = __esm({
22754
22755
  // 'cohere') plus its API key. Provider, model, timeout, and retry env vars
22755
22756
  // are all resolved by @robrain/shared so Sensing and Perception always
22756
22757
  // embed with the same model — see shared/src/embeddings.ts for the list.
22757
- embedding: (0, import_shared.resolveEmbeddingConfig)(),
22758
+ embedding: (0, import_shared.resolveEmbeddingConfig)(process.env, { preferHost: true }),
22758
22759
  // Also reused by the OpenAI chat path when LLM_PROVIDER=openai.
22759
22760
  openaiApiKey: process.env.OPENAI_API_KEY,
22760
22761
  // ── Perception API (required — where signals get sent) ──────
@@ -23296,7 +23297,7 @@ function resolveSessionId(raw) {
23296
23297
  function buildServer() {
23297
23298
  const server = new McpServer({
23298
23299
  name: "sensing-mcp",
23299
- version: "2.4.4"
23300
+ version: "2.4.6"
23300
23301
  });
23301
23302
  server.tool(
23302
23303
  "sensing_start_session",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robrain/sensing-mcp",
3
- "version": "2.4.4",
3
+ "version": "2.4.6",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "main": "./dist/index.js"