@rubytech/create-realagent 1.0.773 → 1.0.789
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/dist/index.js +30 -39
- package/package.json +1 -1
- package/payload/platform/config/brand.json +1 -0
- package/payload/platform/lib/entitlement/PUBKEY-HASH.txt +1 -0
- package/payload/platform/lib/entitlement/dist/canonicalize.d.ts +26 -0
- package/payload/platform/lib/entitlement/dist/canonicalize.d.ts.map +1 -0
- package/payload/platform/lib/entitlement/dist/canonicalize.js +54 -0
- package/payload/platform/lib/entitlement/dist/canonicalize.js.map +1 -0
- package/payload/platform/lib/entitlement/dist/index.d.ts +76 -0
- package/payload/platform/lib/entitlement/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/entitlement/dist/index.js +293 -0
- package/payload/platform/lib/entitlement/dist/index.js.map +1 -0
- package/payload/platform/lib/entitlement/rubytech-pubkey.pem +3 -0
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/admin/hooks/pre-tool-use.sh +32 -0
- package/payload/platform/plugins/admin/mcp/dist/index.js +97 -6
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/skills/plugin-management/SKILL.md +10 -5
- package/payload/platform/plugins/docs/references/troubleshooting.md +1 -1
- package/payload/platform/scripts/generate-entitlement-fixture.mjs +152 -0
- package/payload/platform/scripts/wifi-provision-server/server.js +157 -59
- package/payload/platform/scripts/wifi-provision.sh +88 -8
- package/payload/server/chunk-FEEKJZOY.js +9841 -0
- package/payload/server/chunk-MIP54X7Q.js +3244 -0
- package/payload/server/chunk-TM3EQSID.js +9800 -0
- package/payload/server/client-pool-4MZN42GG.js +28 -0
- package/payload/server/maxy-edge.js +81 -25
- package/payload/server/public/assets/{Checkbox-DEE8t2QO.js → Checkbox-DZgcVkLU.js} +1 -1
- package/payload/server/public/assets/{admin-C4CTVtBu.js → admin-pSseUJFx.js} +30 -30
- package/payload/server/public/assets/data-Dbl98u-8.js +1 -0
- package/payload/server/public/assets/graph-B6QNcEdZ.js +1 -0
- package/payload/server/public/assets/{jsx-runtime-DSbkOE76.css → jsx-runtime-CSZKQ_0M.css} +1 -1
- package/payload/server/public/assets/{page-YUT5e7hL.js → page-DUiVzuAl.js} +2 -2
- package/payload/server/public/assets/{page-ZATk95ZG.js → page-DzXDy3ON.js} +1 -1
- package/payload/server/public/assets/{public-BLi3J8KU.js → public--QCAsuXZ.js} +1 -1
- package/payload/server/public/assets/{share-2-DS7Pnkkq.js → share-2-DHxwin_o.js} +1 -1
- package/payload/server/public/assets/{useVoiceRecorder-pEHqS1ib.js → useVoiceRecorder-DNApywpF.js} +1 -1
- package/payload/server/public/data.html +5 -5
- package/payload/server/public/graph.html +6 -6
- package/payload/server/public/index.html +8 -8
- package/payload/server/public/public.html +5 -5
- package/payload/server/server.js +31 -16
- package/payload/platform/scripts/embed-backfill.sh +0 -382
- package/payload/server/public/assets/data-ryPag-T-.js +0 -1
- package/payload/server/public/assets/graph-BPnH-UZB.js +0 -1
- /package/payload/server/public/assets/{jsx-runtime-DeNudFNA.js → jsx-runtime-Fjep7VIt.js} +0 -0
package/dist/index.js
CHANGED
|
@@ -430,6 +430,18 @@ function installSystemDeps() {
|
|
|
430
430
|
console.log(` Avahi host-name: ${HOSTNAME_FLAG} (updated avahi-daemon.conf)`);
|
|
431
431
|
}
|
|
432
432
|
catch { /* avahi-daemon.conf may not exist — non-critical */ }
|
|
433
|
+
// Restart avahi-daemon so the new hostname takes effect immediately
|
|
434
|
+
// and any stale "maxytest-2" auto-renamed records from a previous
|
|
435
|
+
// boot's hostname-conflict cycle are withdrawn. Without this,
|
|
436
|
+
// avahi-resolve -n <hostname>.local times out from the device itself
|
|
437
|
+
// because the daemon is still advertising the previous identity.
|
|
438
|
+
try {
|
|
439
|
+
console.log(" [privileged] systemctl restart avahi-daemon");
|
|
440
|
+
shell("systemctl", ["restart", "avahi-daemon"], { sudo: true });
|
|
441
|
+
}
|
|
442
|
+
catch (err) {
|
|
443
|
+
console.error(` WARNING: avahi-daemon restart failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
444
|
+
}
|
|
433
445
|
}
|
|
434
446
|
catch (err) {
|
|
435
447
|
console.error(` WARNING: Failed to set hostname to '${HOSTNAME_FLAG}': ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -1346,6 +1358,19 @@ function buildPlatform() {
|
|
|
1346
1358
|
// server/package.json but NOT shipped as pre-built node_modules — npm pack silently
|
|
1347
1359
|
// strips files from nested node_modules (e.g. rxjs/package.json), breaking require().
|
|
1348
1360
|
// Install fresh on device to guarantee a complete dependency tree.
|
|
1361
|
+
//
|
|
1362
|
+
// On upgrade, wipe `node_modules` first so npm extracts a clean tree. Without
|
|
1363
|
+
// this, an interrupted previous install (network blip, operator cancellation,
|
|
1364
|
+
// power loss) can leave nested package.json files half-truncated — the most
|
|
1365
|
+
// common manifestation is `Error: Invalid package config .../rxjs/package.json`
|
|
1366
|
+
// at server startup, which loops the brand service indefinitely. The wipe
|
|
1367
|
+
// adds ~30 s to upgrades but eliminates a class of unrecoverable customer
|
|
1368
|
+
// states; reliability wins over speed for a one-shot install path.
|
|
1369
|
+
const serverNodeModules = join(INSTALL_DIR, "server", "node_modules");
|
|
1370
|
+
if (existsSync(serverNodeModules)) {
|
|
1371
|
+
console.log(" Wiping previous server/node_modules for a clean reinstall...");
|
|
1372
|
+
rmSync(serverNodeModules, { recursive: true, force: true });
|
|
1373
|
+
}
|
|
1349
1374
|
console.log(` Installing server dependencies (${join(INSTALL_DIR, "server")})...`);
|
|
1350
1375
|
shellRetry("npm", ["install", "--omit=dev", ...NPM_NET_FLAGS], { cwd: join(INSTALL_DIR, "server") }, 3, 15);
|
|
1351
1376
|
}
|
|
@@ -1541,11 +1566,11 @@ function setupVncViewer() {
|
|
|
1541
1566
|
}
|
|
1542
1567
|
function setupAccount() {
|
|
1543
1568
|
log("10", TOTAL, "Setting up...");
|
|
1544
|
-
//
|
|
1545
|
-
//
|
|
1546
|
-
//
|
|
1547
|
-
//
|
|
1548
|
-
//
|
|
1569
|
+
// Task 787 — seed-neo4j.sh hard-exits without NEO4J_URI. The installer
|
|
1570
|
+
// owns the brand-correct URI and password, so we derive them once.
|
|
1571
|
+
// Missing password file is a hard error: ensureNeo4jPassword() ran
|
|
1572
|
+
// upstream and would have thrown already if it couldn't reach the
|
|
1573
|
+
// brand's Neo4j.
|
|
1549
1574
|
const passwordFile = join(INSTALL_DIR, "platform/config/.neo4j-password");
|
|
1550
1575
|
if (!existsSync(passwordFile)) {
|
|
1551
1576
|
throw new Error(`Neo4j password file missing at ${passwordFile} — required by setup step.`);
|
|
@@ -1559,40 +1584,6 @@ function setupAccount() {
|
|
|
1559
1584
|
logFile(` [neo4j] passing NEO4J_URI=${neo4jUri} to seed`);
|
|
1560
1585
|
shell("bash", [seedScript], { cwd: INSTALL_DIR, env: neo4jEnv });
|
|
1561
1586
|
}
|
|
1562
|
-
// Task 748 — universal embedding coverage backfill. Run after seed so the
|
|
1563
|
-
// entity_search index is in place and any pre-Task-748 nodes (e.g. the
|
|
1564
|
-
// 5096 LinkedIn-imported Persons on existing Pis that bulk-import skipped
|
|
1565
|
-
// embedding for) get a vector populated. Idempotent — instant no-op when
|
|
1566
|
-
// nothing is pending, so re-running on every install is harmless.
|
|
1567
|
-
//
|
|
1568
|
-
// Failure-mode policy: WARN, do not abort. The fulltext index is already
|
|
1569
|
-
// applied above, so BM25 search works end-to-end without embeddings; the
|
|
1570
|
-
// only gap is vector ranking quality on legacy nodes. Aborting the
|
|
1571
|
-
// installer on an Ollama hiccup would block every install for a
|
|
1572
|
-
// strictly-degradable feature. The script's own loud-failure output
|
|
1573
|
-
// tells the operator how to re-run.
|
|
1574
|
-
const backfillScript = join(INSTALL_DIR, "platform/scripts/embed-backfill.sh");
|
|
1575
|
-
if (existsSync(backfillScript)) {
|
|
1576
|
-
const start = Date.now();
|
|
1577
|
-
logFile(`> bash ${backfillScript} (warn-not-abort)`);
|
|
1578
|
-
const result = spawnSync("bash", [backfillScript], {
|
|
1579
|
-
stdio: "inherit",
|
|
1580
|
-
timeout: 30 * 60_000,
|
|
1581
|
-
cwd: INSTALL_DIR,
|
|
1582
|
-
env: neo4jEnv,
|
|
1583
|
-
});
|
|
1584
|
-
const dur = ((Date.now() - start) / 1000).toFixed(1);
|
|
1585
|
-
if (result.status !== 0 || result.signal) {
|
|
1586
|
-
const reason = result.signal ? `signal=${result.signal}` : `exit=${result.status}`;
|
|
1587
|
-
logFile(` WARN: embed-backfill non-zero (${reason}) after ${dur}s`);
|
|
1588
|
-
console.warn(`\n WARNING: embed-backfill did not complete (${reason}) — BM25 search works,\n` +
|
|
1589
|
-
` but vector ranking on legacy nodes will be sparse until you re-run:\n` +
|
|
1590
|
-
` bash ${backfillScript}\n`);
|
|
1591
|
-
}
|
|
1592
|
-
else {
|
|
1593
|
-
logFile(` OK embed-backfill in ${dur}s`);
|
|
1594
|
-
}
|
|
1595
|
-
}
|
|
1596
1587
|
}
|
|
1597
1588
|
// ---------------------------------------------------------------------------
|
|
1598
1589
|
// Tunnel script shortcuts
|
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d99db79
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic canonical JSON serializer for Ed25519 signing/verification.
|
|
3
|
+
*
|
|
4
|
+
* Why purpose-built and not RFC 8785 (JCS) or a vendored canonicalize lib:
|
|
5
|
+
* the entitlement payload schema is tightly controlled — flat object, primitives
|
|
6
|
+
* plus one string array (purchasedPlugins). A 30-line implementation covers it
|
|
7
|
+
* exactly and stays zero-dep, which matters because the create-maxy bundle
|
|
8
|
+
* has a hardcoded externalDeps surface that any new runtime dep must thread.
|
|
9
|
+
*
|
|
10
|
+
* Rules:
|
|
11
|
+
* - object keys sorted lexicographically (Array.prototype.sort default)
|
|
12
|
+
* - no whitespace
|
|
13
|
+
* - strings JSON.stringify-escaped (handles unicode, quotes, backslashes)
|
|
14
|
+
* - numbers in finite IEEE 754; reject NaN / Infinity / -0
|
|
15
|
+
* - booleans + null verbatim
|
|
16
|
+
* - arrays preserve element order (signing party owns array semantics)
|
|
17
|
+
* - throws on unsupported value types (functions, undefined, symbols, bigint)
|
|
18
|
+
*
|
|
19
|
+
* Both sides (Rubytech signer + customer verifier) call canonicalize() before
|
|
20
|
+
* signing/verifying. Canonical bytes are UTF-8 of the returned string.
|
|
21
|
+
*/
|
|
22
|
+
export type CanonicalValue = string | number | boolean | null | CanonicalValue[] | {
|
|
23
|
+
[k: string]: CanonicalValue;
|
|
24
|
+
};
|
|
25
|
+
export declare function canonicalize(value: CanonicalValue): string;
|
|
26
|
+
//# sourceMappingURL=canonicalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonicalize.d.ts","sourceRoot":"","sources":["../src/canonicalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,MAAM,cAAc,GACtB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,cAAc,EAAE,GAChB;IAAE,CAAC,CAAC,EAAE,MAAM,GAAG,cAAc,CAAA;CAAE,CAAC;AAEpC,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAyB1D"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Deterministic canonical JSON serializer for Ed25519 signing/verification.
|
|
4
|
+
*
|
|
5
|
+
* Why purpose-built and not RFC 8785 (JCS) or a vendored canonicalize lib:
|
|
6
|
+
* the entitlement payload schema is tightly controlled — flat object, primitives
|
|
7
|
+
* plus one string array (purchasedPlugins). A 30-line implementation covers it
|
|
8
|
+
* exactly and stays zero-dep, which matters because the create-maxy bundle
|
|
9
|
+
* has a hardcoded externalDeps surface that any new runtime dep must thread.
|
|
10
|
+
*
|
|
11
|
+
* Rules:
|
|
12
|
+
* - object keys sorted lexicographically (Array.prototype.sort default)
|
|
13
|
+
* - no whitespace
|
|
14
|
+
* - strings JSON.stringify-escaped (handles unicode, quotes, backslashes)
|
|
15
|
+
* - numbers in finite IEEE 754; reject NaN / Infinity / -0
|
|
16
|
+
* - booleans + null verbatim
|
|
17
|
+
* - arrays preserve element order (signing party owns array semantics)
|
|
18
|
+
* - throws on unsupported value types (functions, undefined, symbols, bigint)
|
|
19
|
+
*
|
|
20
|
+
* Both sides (Rubytech signer + customer verifier) call canonicalize() before
|
|
21
|
+
* signing/verifying. Canonical bytes are UTF-8 of the returned string.
|
|
22
|
+
*/
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.canonicalize = canonicalize;
|
|
25
|
+
function canonicalize(value) {
|
|
26
|
+
if (value === null)
|
|
27
|
+
return "null";
|
|
28
|
+
if (typeof value === "boolean")
|
|
29
|
+
return value ? "true" : "false";
|
|
30
|
+
if (typeof value === "string")
|
|
31
|
+
return JSON.stringify(value);
|
|
32
|
+
if (typeof value === "number") {
|
|
33
|
+
if (!Number.isFinite(value)) {
|
|
34
|
+
throw new Error(`canonicalize: non-finite number rejected (${value})`);
|
|
35
|
+
}
|
|
36
|
+
if (Object.is(value, -0)) {
|
|
37
|
+
throw new Error("canonicalize: negative zero rejected");
|
|
38
|
+
}
|
|
39
|
+
return JSON.stringify(value);
|
|
40
|
+
}
|
|
41
|
+
if (Array.isArray(value)) {
|
|
42
|
+
return "[" + value.map(canonicalize).join(",") + "]";
|
|
43
|
+
}
|
|
44
|
+
if (typeof value === "object") {
|
|
45
|
+
const keys = Object.keys(value).sort();
|
|
46
|
+
const parts = [];
|
|
47
|
+
for (const k of keys) {
|
|
48
|
+
parts.push(JSON.stringify(k) + ":" + canonicalize(value[k]));
|
|
49
|
+
}
|
|
50
|
+
return "{" + parts.join(",") + "}";
|
|
51
|
+
}
|
|
52
|
+
throw new Error(`canonicalize: unsupported value type ${typeof value}`);
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=canonicalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonicalize.js","sourceRoot":"","sources":["../src/canonicalize.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;AAUH,oCAyBC;AAzBD,SAAgB,YAAY,CAAC,KAAqB;IAChD,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IAClC,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IAChE,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC5D,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,6CAA6C,KAAK,GAAG,CAAC,CAAC;QACzE,CAAC;QACD,IAAI,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC1D,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IACvD,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;QACvC,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IACrC,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,wCAAwC,OAAO,KAAK,EAAE,CAAC,CAAC;AAC1E,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entitlement verifier — single source of truth for effective tier and
|
|
3
|
+
* purchasedPlugins on a Maxy/Real-Agent install. Pre-launch security gate
|
|
4
|
+
* for paid tiers (Task 831).
|
|
5
|
+
*
|
|
6
|
+
* Doctrine: account.json is agent-writable; entitlement is not. Effective
|
|
7
|
+
* tier and purchasedPlugins derive from a Rubytech-signed Ed25519 payload,
|
|
8
|
+
* not from raw account.json values. Editing account.json directly has no
|
|
9
|
+
* runtime effect; the verifier compares disk against signed and uses signed.
|
|
10
|
+
*
|
|
11
|
+
* ┌────────────────────────────┐
|
|
12
|
+
* │ session start │
|
|
13
|
+
* └─────────────┬──────────────┘
|
|
14
|
+
* ▼
|
|
15
|
+
* ┌────────────────────────────┐
|
|
16
|
+
* │ read brand.json │
|
|
17
|
+
* │ commercialMode? (default │
|
|
18
|
+
* │ false on personal-mode) │
|
|
19
|
+
* └────────┬───────────────┬───┘
|
|
20
|
+
* │false │true
|
|
21
|
+
* ▼ ▼
|
|
22
|
+
* source=implicit-trust read entitlement.json
|
|
23
|
+
* (raw account.json) │
|
|
24
|
+
* ├─missing──▶ anonymous-fallback (lock)
|
|
25
|
+
* ├─malformed─▶ anonymous-fallback
|
|
26
|
+
* ├─pubkey-tampered─▶ anonymous-fallback
|
|
27
|
+
* ├─bad sig──▶ anonymous-fallback
|
|
28
|
+
* ├─binding mismatch─▶ anonymous-fallback
|
|
29
|
+
* ├─clock skew──▶ anonymous-fallback
|
|
30
|
+
* ├─expired+grace─▶ signed-grace
|
|
31
|
+
* ├─expired post-grace─▶ anonymous-fallback (lock)
|
|
32
|
+
* └─valid─▶ signed
|
|
33
|
+
*
|
|
34
|
+
* Threat model: this code closes the agent-self-elevation bypass and the
|
|
35
|
+
* casual operator vim-edit bypass. A determined operator with shell access
|
|
36
|
+
* who replaces the vendored pubkey AND regenerates the SHA-256 hash baked
|
|
37
|
+
* into PUBKEY_SHA256 below can still defeat the verifier — that is the
|
|
38
|
+
* accepted out-of-scope per task 831 ("raise bypass cost to break the
|
|
39
|
+
* signature, not to edit JSON"). Hardware binding is the only counter and
|
|
40
|
+
* is explicitly out of scope.
|
|
41
|
+
*/
|
|
42
|
+
export declare const PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d99db79";
|
|
43
|
+
export type EntitlementSource = "signed" | "signed-grace" | "implicit-trust" | "anonymous-fallback";
|
|
44
|
+
export interface ResolvedEntitlement {
|
|
45
|
+
tier: string;
|
|
46
|
+
purchasedPlugins: string[];
|
|
47
|
+
source: EntitlementSource;
|
|
48
|
+
issued: string | null;
|
|
49
|
+
expires: string | null;
|
|
50
|
+
}
|
|
51
|
+
export interface AccountConfigSubset {
|
|
52
|
+
accountId: string;
|
|
53
|
+
customerEmail?: string;
|
|
54
|
+
tier?: string;
|
|
55
|
+
purchasedPlugins?: string[];
|
|
56
|
+
}
|
|
57
|
+
export interface BrandConfigSubset {
|
|
58
|
+
/** Absolute path to ~/<configDir> where entitlement.json is delivered. */
|
|
59
|
+
configDir: string;
|
|
60
|
+
/** Absolute path to platform/ root; pubkey lives at <platformRoot>/lib/entitlement/rubytech-pubkey.pem. */
|
|
61
|
+
platformRoot: string;
|
|
62
|
+
/** True only when this brand has flipped to commercial entitlement enforcement. */
|
|
63
|
+
commercialMode?: boolean;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Resolve effective entitlement for the current install. Sync — Ed25519
|
|
67
|
+
* verify is a CPU-bound primitive on the order of 0.3ms; no async surface.
|
|
68
|
+
*
|
|
69
|
+
* @param brand Brand config (read from platform/config/brand.json by caller)
|
|
70
|
+
* @param account Account config (read from data/accounts/<id>/account.json)
|
|
71
|
+
* @returns Effective entitlement plus the source tag for observability.
|
|
72
|
+
*/
|
|
73
|
+
export declare function resolveEntitlement(brand: BrandConfigSubset, account: AccountConfigSubset): ResolvedEntitlement;
|
|
74
|
+
/** Test-only: clear the memoization cache. Not used in production. */
|
|
75
|
+
export declare function _clearMemo(): void;
|
|
76
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAoBH,eAAO,MAAM,aAAa,qEAAqE,CAAC;AAMhG,MAAM,MAAM,iBAAiB,GACzB,QAAQ,GACR,cAAc,GACd,gBAAgB,GAChB,oBAAoB,CAAC;AAEzB,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;IAClB,2GAA2G;IAC3G,YAAY,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AA0BD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,iBAAiB,EACxB,OAAO,EAAE,mBAAmB,GAC3B,mBAAmB,CAuBrB;AAED,sEAAsE;AACtE,wBAAgB,UAAU,IAAI,IAAI,CAEjC"}
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Entitlement verifier — single source of truth for effective tier and
|
|
4
|
+
* purchasedPlugins on a Maxy/Real-Agent install. Pre-launch security gate
|
|
5
|
+
* for paid tiers (Task 831).
|
|
6
|
+
*
|
|
7
|
+
* Doctrine: account.json is agent-writable; entitlement is not. Effective
|
|
8
|
+
* tier and purchasedPlugins derive from a Rubytech-signed Ed25519 payload,
|
|
9
|
+
* not from raw account.json values. Editing account.json directly has no
|
|
10
|
+
* runtime effect; the verifier compares disk against signed and uses signed.
|
|
11
|
+
*
|
|
12
|
+
* ┌────────────────────────────┐
|
|
13
|
+
* │ session start │
|
|
14
|
+
* └─────────────┬──────────────┘
|
|
15
|
+
* ▼
|
|
16
|
+
* ┌────────────────────────────┐
|
|
17
|
+
* │ read brand.json │
|
|
18
|
+
* │ commercialMode? (default │
|
|
19
|
+
* │ false on personal-mode) │
|
|
20
|
+
* └────────┬───────────────┬───┘
|
|
21
|
+
* │false │true
|
|
22
|
+
* ▼ ▼
|
|
23
|
+
* source=implicit-trust read entitlement.json
|
|
24
|
+
* (raw account.json) │
|
|
25
|
+
* ├─missing──▶ anonymous-fallback (lock)
|
|
26
|
+
* ├─malformed─▶ anonymous-fallback
|
|
27
|
+
* ├─pubkey-tampered─▶ anonymous-fallback
|
|
28
|
+
* ├─bad sig──▶ anonymous-fallback
|
|
29
|
+
* ├─binding mismatch─▶ anonymous-fallback
|
|
30
|
+
* ├─clock skew──▶ anonymous-fallback
|
|
31
|
+
* ├─expired+grace─▶ signed-grace
|
|
32
|
+
* ├─expired post-grace─▶ anonymous-fallback (lock)
|
|
33
|
+
* └─valid─▶ signed
|
|
34
|
+
*
|
|
35
|
+
* Threat model: this code closes the agent-self-elevation bypass and the
|
|
36
|
+
* casual operator vim-edit bypass. A determined operator with shell access
|
|
37
|
+
* who replaces the vendored pubkey AND regenerates the SHA-256 hash baked
|
|
38
|
+
* into PUBKEY_SHA256 below can still defeat the verifier — that is the
|
|
39
|
+
* accepted out-of-scope per task 831 ("raise bypass cost to break the
|
|
40
|
+
* signature, not to edit JSON"). Hardware binding is the only counter and
|
|
41
|
+
* is explicitly out of scope.
|
|
42
|
+
*/
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.PUBKEY_SHA256 = void 0;
|
|
45
|
+
exports.resolveEntitlement = resolveEntitlement;
|
|
46
|
+
exports._clearMemo = _clearMemo;
|
|
47
|
+
const node_crypto_1 = require("node:crypto");
|
|
48
|
+
const node_fs_1 = require("node:fs");
|
|
49
|
+
const node_path_1 = require("node:path");
|
|
50
|
+
const canonicalize_js_1 = require("./canonicalize.js");
|
|
51
|
+
// __dirname is undefined in pure ESM bundles (platform/ui's tsup output is
|
|
52
|
+
// format: ['esm'] with no shims:true). The MCP plugin path imports the CJS
|
|
53
|
+
// build (dist/) where __dirname works, but the UI server imports the TS
|
|
54
|
+
// source directly and tsup-bundles it as ESM. To work in both worlds, the
|
|
55
|
+
// caller passes the platform root explicitly via BrandConfigSubset.platformRoot.
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// Vendored pubkey — shipped at platform/lib/entitlement/rubytech-pubkey.pem.
|
|
58
|
+
// PUBKEY_SHA256 is the expected hex SHA-256 of the file's bytes; if the
|
|
59
|
+
// on-disk file's hash diverges the verifier emits pubkey-tamper and falls
|
|
60
|
+
// back to anonymous. Update both when Rubytech rotates the keypair.
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
exports.PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d99db79";
|
|
63
|
+
const GRACE_DAYS = 7;
|
|
64
|
+
const GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1000;
|
|
65
|
+
function pubkeyPath(brand) {
|
|
66
|
+
return (0, node_path_1.resolve)(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
|
|
67
|
+
}
|
|
68
|
+
// Memoize per-process, scoped to (mtime, accountId, customerEmail). Scoping
|
|
69
|
+
// by accountId is mandatory: the binding check at verifyAndResolve runs once
|
|
70
|
+
// per call, and a memo keyed on mtime alone would return account A's verified
|
|
71
|
+
// result to account B's request — bypassing the per-call binding check
|
|
72
|
+
// (account isolation doctrine, feedback_account_isolation_absolute).
|
|
73
|
+
let memo = null;
|
|
74
|
+
function memoKey(mtimeMs, account) {
|
|
75
|
+
// Coarse 60-second time bucket ensures the memo invalidates around the
|
|
76
|
+
// expires/grace boundary even when entitlement.json mtime never changes
|
|
77
|
+
// (long-running UI server, no file refresh until Task 832 ships).
|
|
78
|
+
const bucket = Math.floor(Date.now() / 60000);
|
|
79
|
+
return `${mtimeMs}:${bucket}:${account.accountId}:${account.customerEmail ?? ""}`;
|
|
80
|
+
}
|
|
81
|
+
const VALID_TIERS = new Set(["solo", "family", "pro"]);
|
|
82
|
+
/**
|
|
83
|
+
* Resolve effective entitlement for the current install. Sync — Ed25519
|
|
84
|
+
* verify is a CPU-bound primitive on the order of 0.3ms; no async surface.
|
|
85
|
+
*
|
|
86
|
+
* @param brand Brand config (read from platform/config/brand.json by caller)
|
|
87
|
+
* @param account Account config (read from data/accounts/<id>/account.json)
|
|
88
|
+
* @returns Effective entitlement plus the source tag for observability.
|
|
89
|
+
*/
|
|
90
|
+
function resolveEntitlement(brand, account) {
|
|
91
|
+
// Personal mode (commercialMode !== true): always implicit-trust. A stray
|
|
92
|
+
// entitlement.json (backup-restore, dev artefact) must NOT lock out a
|
|
93
|
+
// personal-mode user — verification only runs when the brand is commercial.
|
|
94
|
+
if (brand.commercialMode !== true) {
|
|
95
|
+
return logResolved(implicitTrust(account), null);
|
|
96
|
+
}
|
|
97
|
+
const entitlementPath = (0, node_path_1.resolve)(brand.configDir, "entitlement.json");
|
|
98
|
+
if (!(0, node_fs_1.existsSync)(entitlementPath)) {
|
|
99
|
+
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
100
|
+
}
|
|
101
|
+
// (mtime, time-bucket, accountId, customerEmail)-keyed memoization
|
|
102
|
+
const stat = (0, node_fs_1.statSync)(entitlementPath);
|
|
103
|
+
const key = memoKey(stat.mtimeMs, account);
|
|
104
|
+
if (memo && memo.key === key) {
|
|
105
|
+
return memo.result;
|
|
106
|
+
}
|
|
107
|
+
const result = verifyAndResolve(brand, entitlementPath, account);
|
|
108
|
+
memo = { key, result };
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
/** Test-only: clear the memoization cache. Not used in production. */
|
|
112
|
+
function _clearMemo() {
|
|
113
|
+
memo = null;
|
|
114
|
+
}
|
|
115
|
+
// ---------------------------------------------------------------------------
|
|
116
|
+
// Internals
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
function verifyAndResolve(brand, entitlementPath, account) {
|
|
119
|
+
// Step 1: pubkey integrity. If the vendored pubkey has been swapped on
|
|
120
|
+
// disk, refuse to use it — emit verify-failed and degrade.
|
|
121
|
+
let pubkeyPem;
|
|
122
|
+
try {
|
|
123
|
+
pubkeyPem = (0, node_fs_1.readFileSync)(pubkeyPath(brand), "utf-8");
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
return logResolved(anonymousFallback("pubkey-missing"), {
|
|
127
|
+
reason: "pubkey-missing",
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
const pubkeyHash = (0, node_crypto_1.createHash)("sha256").update(pubkeyPem).digest("hex");
|
|
131
|
+
if (pubkeyHash !== exports.PUBKEY_SHA256) {
|
|
132
|
+
return logResolved(anonymousFallback("pubkey-tamper"), {
|
|
133
|
+
reason: "pubkey-tamper",
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
// Step 2: parse the entitlement envelope.
|
|
137
|
+
let envelope;
|
|
138
|
+
try {
|
|
139
|
+
envelope = JSON.parse((0, node_fs_1.readFileSync)(entitlementPath, "utf-8"));
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
|
|
143
|
+
}
|
|
144
|
+
if (typeof envelope !== "object" ||
|
|
145
|
+
envelope === null ||
|
|
146
|
+
typeof envelope.signature !== "string" ||
|
|
147
|
+
typeof envelope.payload !== "object" ||
|
|
148
|
+
envelope.payload === null) {
|
|
149
|
+
return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
|
|
150
|
+
}
|
|
151
|
+
const payload = envelope.payload;
|
|
152
|
+
const signatureB64 = envelope.signature;
|
|
153
|
+
// Step 3: signature verification over canonical bytes.
|
|
154
|
+
let pubkey;
|
|
155
|
+
try {
|
|
156
|
+
pubkey = (0, node_crypto_1.createPublicKey)(pubkeyPem);
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
return logResolved(anonymousFallback("pubkey-malformed"), {
|
|
160
|
+
reason: "pubkey-malformed",
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
let canonical;
|
|
164
|
+
try {
|
|
165
|
+
canonical = (0, canonicalize_js_1.canonicalize)(payload);
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
return logResolved(anonymousFallback("payload-shape"), {
|
|
169
|
+
reason: "payload-shape",
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
let sigBuf;
|
|
173
|
+
try {
|
|
174
|
+
sigBuf = Buffer.from(signatureB64, "base64");
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return logResolved(anonymousFallback("signature-encoding"), {
|
|
178
|
+
reason: "signature-encoding",
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
const ok = (0, node_crypto_1.verify)(null, Buffer.from(canonical, "utf-8"), pubkey, sigBuf);
|
|
182
|
+
if (!ok) {
|
|
183
|
+
return logResolved(anonymousFallback("signature"), { reason: "signature" });
|
|
184
|
+
}
|
|
185
|
+
// Step 4: bindings — accountId and customerEmail must match local truth.
|
|
186
|
+
if (typeof payload.accountId !== "string" || payload.accountId !== account.accountId) {
|
|
187
|
+
return logResolved(anonymousFallback("binding-account"), {
|
|
188
|
+
reason: "binding-account",
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
// customerEmail binding: enforce when EITHER side has a value. Skipping when
|
|
192
|
+
// only the local side is empty would let an attacker forge an account.json
|
|
193
|
+
// without customerEmail to silently bypass the email binding while keeping
|
|
194
|
+
// the matching accountId. Symmetric: signed has it OR local has it → must match.
|
|
195
|
+
const signedEmail = typeof payload.customerEmail === "string" ? payload.customerEmail : undefined;
|
|
196
|
+
if (signedEmail !== undefined || account.customerEmail !== undefined) {
|
|
197
|
+
if (signedEmail !== account.customerEmail) {
|
|
198
|
+
return logResolved(anonymousFallback("binding-email"), {
|
|
199
|
+
reason: "binding-email",
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// Step 5: temporal checks.
|
|
204
|
+
const issuedRaw = payload.issued;
|
|
205
|
+
const expiresRaw = payload.expires;
|
|
206
|
+
if (typeof issuedRaw !== "string" || typeof expiresRaw !== "string") {
|
|
207
|
+
return logResolved(anonymousFallback("temporal-shape"), {
|
|
208
|
+
reason: "temporal-shape",
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
const issued = Date.parse(issuedRaw);
|
|
212
|
+
const expires = Date.parse(expiresRaw);
|
|
213
|
+
const now = Date.now();
|
|
214
|
+
if (Number.isNaN(issued) || Number.isNaN(expires)) {
|
|
215
|
+
return logResolved(anonymousFallback("temporal-shape"), {
|
|
216
|
+
reason: "temporal-shape",
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
if (issued > now) {
|
|
220
|
+
return logResolved(anonymousFallback("clock-skew"), {
|
|
221
|
+
reason: "clock-skew",
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
// Reject empty/unknown tier. An empty string passing through here would
|
|
225
|
+
// hit `MAX_ADMINS_BY_TIER[""] ?? MAX_ADMINS_DEFAULT` at admin-add and
|
|
226
|
+
// silently grant pro-tier admin slots — a signing-side bug becoming a
|
|
227
|
+
// privilege grant. Strict allowlist closes the gap.
|
|
228
|
+
const tier = typeof payload.tier === "string" ? payload.tier : "";
|
|
229
|
+
if (!VALID_TIERS.has(tier)) {
|
|
230
|
+
return logResolved(anonymousFallback("tier-shape"), { reason: "tier-shape" });
|
|
231
|
+
}
|
|
232
|
+
const purchased = Array.isArray(payload.purchasedPlugins)
|
|
233
|
+
? payload.purchasedPlugins.filter((s) => typeof s === "string")
|
|
234
|
+
: [];
|
|
235
|
+
// Step 6: expiry gate.
|
|
236
|
+
if (now <= expires) {
|
|
237
|
+
return logResolved({
|
|
238
|
+
tier,
|
|
239
|
+
purchasedPlugins: purchased,
|
|
240
|
+
source: "signed",
|
|
241
|
+
issued: issuedRaw,
|
|
242
|
+
expires: expiresRaw,
|
|
243
|
+
}, maybeTamperLine(account, tier));
|
|
244
|
+
}
|
|
245
|
+
if (now <= expires + GRACE_MS) {
|
|
246
|
+
return logResolved({
|
|
247
|
+
tier,
|
|
248
|
+
purchasedPlugins: purchased,
|
|
249
|
+
source: "signed-grace",
|
|
250
|
+
issued: issuedRaw,
|
|
251
|
+
expires: expiresRaw,
|
|
252
|
+
}, maybeTamperLine(account, tier));
|
|
253
|
+
}
|
|
254
|
+
return logResolved(anonymousFallback("expired"), { reason: "expired" });
|
|
255
|
+
}
|
|
256
|
+
function implicitTrust(account) {
|
|
257
|
+
const tier = typeof account.tier === "string" ? account.tier : "";
|
|
258
|
+
const purchased = Array.isArray(account.purchasedPlugins) ? account.purchasedPlugins : [];
|
|
259
|
+
return {
|
|
260
|
+
tier,
|
|
261
|
+
purchasedPlugins: purchased,
|
|
262
|
+
source: "implicit-trust",
|
|
263
|
+
issued: null,
|
|
264
|
+
expires: null,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
function anonymousFallback(_reason) {
|
|
268
|
+
return {
|
|
269
|
+
tier: "solo",
|
|
270
|
+
purchasedPlugins: [],
|
|
271
|
+
source: "anonymous-fallback",
|
|
272
|
+
issued: null,
|
|
273
|
+
expires: null,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
function maybeTamperLine(account, signedTier) {
|
|
277
|
+
if (typeof account.tier === "string" && account.tier !== signedTier) {
|
|
278
|
+
return { reason: "tampered", diskTier: account.tier, signedTier };
|
|
279
|
+
}
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
function logResolved(result, detail) {
|
|
283
|
+
console.error(`[entitlement] resolved: tier=${result.tier} plugins=${result.purchasedPlugins.length} source=${result.source} issued=${result.issued ?? "-"} expires=${result.expires ?? "-"}`);
|
|
284
|
+
if (detail && "diskTier" in detail) {
|
|
285
|
+
console.error(`[entitlement] tampered: tier-on-disk=${detail.diskTier} signed=${detail.signedTier} action=using-signed`);
|
|
286
|
+
}
|
|
287
|
+
else if (detail && result.source === "anonymous-fallback") {
|
|
288
|
+
const action = detail.reason === "expired" || detail.reason === "missing" ? "lock" : "degrade";
|
|
289
|
+
console.error(`[entitlement] verify-failed: reason=${detail.reason} action=${action}`);
|
|
290
|
+
}
|
|
291
|
+
return result;
|
|
292
|
+
}
|
|
293
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;;;AAwFH,gDA0BC;AAGD,gCAEC;AArHD,6CAAkF;AAClF,qCAA6D;AAC7D,yCAAoC;AACpC,uDAAsE;AAEtE,2EAA2E;AAC3E,2EAA2E;AAC3E,wEAAwE;AACxE,0EAA0E;AAC1E,iFAAiF;AAEjF,8EAA8E;AAC9E,6EAA6E;AAC7E,wEAAwE;AACxE,0EAA0E;AAC1E,oEAAoE;AACpE,8EAA8E;AAEjE,QAAA,aAAa,GAAG,kEAAkE,CAAC;AAoChG,MAAM,UAAU,GAAG,CAAC,CAAC;AACrB,MAAM,QAAQ,GAAG,UAAU,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAElD,SAAS,UAAU,CAAC,KAAwB;IAC1C,OAAO,IAAA,mBAAO,EAAC,KAAK,CAAC,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,qBAAqB,CAAC,CAAC;AAClF,CAAC;AAED,4EAA4E;AAC5E,6EAA6E;AAC7E,8EAA8E;AAC9E,uEAAuE;AACvE,qEAAqE;AACrE,IAAI,IAAI,GAAwD,IAAI,CAAC;AAErE,SAAS,OAAO,CAAC,OAAe,EAAE,OAA4B;IAC5D,uEAAuE;IACvE,wEAAwE;IACxE,kEAAkE;IAClE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC;IAC9C,OAAO,GAAG,OAAO,IAAI,MAAM,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,aAAa,IAAI,EAAE,EAAE,CAAC;AACpF,CAAC;AAED,MAAM,WAAW,GAAwB,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;AAE5E;;;;;;;GAOG;AACH,SAAgB,kBAAkB,CAChC,KAAwB,EACxB,OAA4B;IAE5B,0EAA0E;IAC1E,sEAAsE;IACtE,4EAA4E;IAC5E,IAAI,KAAK,CAAC,cAAc,KAAK,IAAI,EAAE,CAAC;QAClC,OAAO,WAAW,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,eAAe,GAAG,IAAA,mBAAO,EAAC,KAAK,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;IACrE,IAAI,CAAC,IAAA,oBAAU,EAAC,eAAe,CAAC,EAAE,CAAC;QACjC,OAAO,WAAW,CAAC,iBAAiB,CAAC,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,mEAAmE;IACnE,MAAM,IAAI,GAAG,IAAA,kBAAQ,EAAC,eAAe,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC3C,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,EAAE,eAAe,EAAE,OAAO,CAAC,CAAC;IACjE,IAAI,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,sEAAsE;AACtE,SAAgB,UAAU;IACxB,IAAI,GAAG,IAAI,CAAC;AACd,CAAC;AAED,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,SAAS,gBAAgB,CACvB,KAAwB,EACxB,eAAuB,EACvB,OAA4B;IAE5B,uEAAuE;IACvE,2DAA2D;IAC3D,IAAI,SAAiB,CAAC;IACtB,IAAI,CAAC;QACH,SAAS,GAAG,IAAA,sBAAY,EAAC,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC;IACvD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,WAAW,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,EAAE;YACtD,MAAM,EAAE,gBAAgB;SACzB,CAAC,CAAC;IACL,CAAC;IACD,MAAM,UAAU,GAAG,IAAA,wBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACxE,IAAI,UAAU,KAAK,qBAAa,EAAE,CAAC;QACjC,OAAO,WAAW,CAAC,iBAAiB,CAAC,eAAe,CAAC,EAAE;YACrD,MAAM,EAAE,eAAe;SACxB,CAAC,CAAC;IACL,CAAC;IAED,0CAA0C;IAC1C,IAAI,QAAoD,CAAC;IACzD,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,sBAAY,EAAC,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,WAAW,CAAC,iBAAiB,CAAC,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED,IACE,OAAO,QAAQ,KAAK,QAAQ;QAC5B,QAAQ,KAAK,IAAI;QACjB,OAAO,QAAQ,CAAC,SAAS,KAAK,QAAQ;QACtC,OAAO,QAAQ,CAAC,OAAO,KAAK,QAAQ;QACpC,QAAQ,CAAC,OAAO,KAAK,IAAI,EACzB,CAAC;QACD,OAAO,WAAW,CAAC,iBAAiB,CAAC,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAkC,CAAC;IAC5D,MAAM,YAAY,GAAG,QAAQ,CAAC,SAAS,CAAC;IAExC,uDAAuD;IACvD,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,GAAG,IAAA,6BAAe,EAAC,SAAS,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,WAAW,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,EAAE;YACxD,MAAM,EAAE,kBAAkB;SAC3B,CAAC,CAAC;IACL,CAAC;IAED,IAAI,SAAiB,CAAC;IACtB,IAAI,CAAC;QACH,SAAS,GAAG,IAAA,8BAAY,EAAC,OAAyB,CAAC,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,WAAW,CAAC,iBAAiB,CAAC,eAAe,CAAC,EAAE;YACrD,MAAM,EAAE,eAAe;SACxB,CAAC,CAAC;IACL,CAAC;IAED,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,WAAW,CAAC,iBAAiB,CAAC,oBAAoB,CAAC,EAAE;YAC1D,MAAM,EAAE,oBAAoB;SAC7B,CAAC,CAAC;IACL,CAAC;IAED,MAAM,EAAE,GAAG,IAAA,oBAAY,EAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/E,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,OAAO,WAAW,CAAC,iBAAiB,CAAC,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED,yEAAyE;IACzE,IAAI,OAAO,OAAO,CAAC,SAAS,KAAK,QAAQ,IAAI,OAAO,CAAC,SAAS,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC;QACrF,OAAO,WAAW,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,EAAE;YACvD,MAAM,EAAE,iBAAiB;SAC1B,CAAC,CAAC;IACL,CAAC;IACD,6EAA6E;IAC7E,2EAA2E;IAC3E,2EAA2E;IAC3E,iFAAiF;IACjF,MAAM,WAAW,GAAG,OAAO,OAAO,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;IAClG,IAAI,WAAW,KAAK,SAAS,IAAI,OAAO,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;QACrE,IAAI,WAAW,KAAK,OAAO,CAAC,aAAa,EAAE,CAAC;YAC1C,OAAO,WAAW,CAAC,iBAAiB,CAAC,eAAe,CAAC,EAAE;gBACrD,MAAM,EAAE,eAAe;aACxB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,2BAA2B;IAC3B,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;IACjC,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;IACnC,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QACpE,OAAO,WAAW,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,EAAE;YACtD,MAAM,EAAE,gBAAgB;SACzB,CAAC,CAAC;IACL,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAClD,OAAO,WAAW,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,EAAE;YACtD,MAAM,EAAE,gBAAgB;SACzB,CAAC,CAAC;IACL,CAAC;IACD,IAAI,MAAM,GAAG,GAAG,EAAE,CAAC;QACjB,OAAO,WAAW,CAAC,iBAAiB,CAAC,YAAY,CAAC,EAAE;YAClD,MAAM,EAAE,YAAY;SACrB,CAAC,CAAC;IACL,CAAC;IAED,wEAAwE;IACxE,sEAAsE;IACtE,sEAAsE;IACtE,oDAAoD;IACpD,MAAM,IAAI,GAAG,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAClE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,OAAO,WAAW,CAAC,iBAAiB,CAAC,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;IAChF,CAAC;IACD,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC;QACvD,CAAC,CAAE,OAAO,CAAC,gBAA8B,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;QAC3F,CAAC,CAAC,EAAE,CAAC;IAEP,uBAAuB;IACvB,IAAI,GAAG,IAAI,OAAO,EAAE,CAAC;QACnB,OAAO,WAAW,CAChB;YACE,IAAI;YACJ,gBAAgB,EAAE,SAAS;YAC3B,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,SAAS;YACjB,OAAO,EAAE,UAAU;SACpB,EACD,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,CAC/B,CAAC;IACJ,CAAC;IACD,IAAI,GAAG,IAAI,OAAO,GAAG,QAAQ,EAAE,CAAC;QAC9B,OAAO,WAAW,CAChB;YACE,IAAI;YACJ,gBAAgB,EAAE,SAAS;YAC3B,MAAM,EAAE,cAAc;YACtB,MAAM,EAAE,SAAS;YACjB,OAAO,EAAE,UAAU;SACpB,EACD,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,CAC/B,CAAC;IACJ,CAAC;IACD,OAAO,WAAW,CAAC,iBAAiB,CAAC,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,aAAa,CAAC,OAA4B;IACjD,MAAM,IAAI,GAAG,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAClE,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1F,OAAO;QACL,IAAI;QACJ,gBAAgB,EAAE,SAAS;QAC3B,MAAM,EAAE,gBAAgB;QACxB,MAAM,EAAE,IAAI;QACZ,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAe;IACxC,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,gBAAgB,EAAE,EAAE;QACpB,MAAM,EAAE,oBAAoB;QAC5B,MAAM,EAAE,IAAI;QACZ,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CACtB,OAA4B,EAC5B,UAAkB;IAElB,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QACpE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC;IACpE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,WAAW,CAClB,MAA2B,EAC3B,MAGQ;IAER,OAAO,CAAC,KAAK,CACX,gCAAgC,MAAM,CAAC,IAAI,YAAY,MAAM,CAAC,gBAAgB,CAAC,MAAM,WAAW,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,MAAM,IAAI,GAAG,YAAY,MAAM,CAAC,OAAO,IAAI,GAAG,EAAE,CAChL,CAAC;IACF,IAAI,MAAM,IAAI,UAAU,IAAI,MAAM,EAAE,CAAC;QACnC,OAAO,CAAC,KAAK,CACX,wCAAwC,MAAM,CAAC,QAAQ,WAAW,MAAM,CAAC,UAAU,sBAAsB,CAC1G,CAAC;IACJ,CAAC;SAAM,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,oBAAoB,EAAE,CAAC;QAC5D,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;QAC/F,OAAO,CAAC,KAAK,CACX,uCAAuC,MAAM,CAAC,MAAM,WAAW,MAAM,EAAE,CACxE,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
"plugins/*/mcp"
|
|
7
7
|
],
|
|
8
8
|
"scripts": {
|
|
9
|
-
"build": "tsc -p lib/models/tsconfig.json && tsc -p lib/anthropic-key/tsconfig.json && tsc -p lib/oauth-llm/tsconfig.json && tsc -p lib/mcp-stderr-tee/tsconfig.json && tsc -p lib/mcp-spawn-tee/tsconfig.json && tsc -p lib/graph-write/tsconfig.json && tsc -p lib/graph-mcp/tsconfig.json && tsc -p lib/graph-trash/tsconfig.json && tsc -p lib/graph-search/tsconfig.json && tsc -p lib/screening-patterns/tsconfig.json && tsc -p lib/device-url/tsconfig.json && tsc -p lib/brand-templating/tsconfig.json && tsc -p plugins/whatsapp-import/lib/tsconfig.json && NODE_OPTIONS='--max-old-space-size=8192' tsc -b plugins/*/mcp/tsconfig.json",
|
|
10
|
-
"build:lib": "tsc -p lib/models/tsconfig.json && tsc -p lib/anthropic-key/tsconfig.json && tsc -p lib/oauth-llm/tsconfig.json && tsc -p lib/mcp-stderr-tee/tsconfig.json && tsc -p lib/mcp-spawn-tee/tsconfig.json && tsc -p lib/graph-write/tsconfig.json && tsc -p lib/graph-mcp/tsconfig.json && tsc -p lib/graph-trash/tsconfig.json && tsc -p lib/graph-search/tsconfig.json && tsc -p lib/screening-patterns/tsconfig.json && tsc -p lib/device-url/tsconfig.json && tsc -p lib/brand-templating/tsconfig.json && tsc -p plugins/whatsapp-import/lib/tsconfig.json",
|
|
9
|
+
"build": "tsc -p lib/models/tsconfig.json && tsc -p lib/anthropic-key/tsconfig.json && tsc -p lib/oauth-llm/tsconfig.json && tsc -p lib/mcp-stderr-tee/tsconfig.json && tsc -p lib/mcp-spawn-tee/tsconfig.json && tsc -p lib/graph-write/tsconfig.json && tsc -p lib/graph-mcp/tsconfig.json && tsc -p lib/graph-trash/tsconfig.json && tsc -p lib/graph-search/tsconfig.json && tsc -p lib/screening-patterns/tsconfig.json && tsc -p lib/device-url/tsconfig.json && tsc -p lib/brand-templating/tsconfig.json && tsc -p lib/entitlement/tsconfig.json && tsc -p plugins/whatsapp-import/lib/tsconfig.json && NODE_OPTIONS='--max-old-space-size=8192' tsc -b plugins/*/mcp/tsconfig.json",
|
|
10
|
+
"build:lib": "tsc -p lib/models/tsconfig.json && tsc -p lib/anthropic-key/tsconfig.json && tsc -p lib/oauth-llm/tsconfig.json && tsc -p lib/mcp-stderr-tee/tsconfig.json && tsc -p lib/mcp-spawn-tee/tsconfig.json && tsc -p lib/graph-write/tsconfig.json && tsc -p lib/graph-mcp/tsconfig.json && tsc -p lib/graph-trash/tsconfig.json && tsc -p lib/graph-search/tsconfig.json && tsc -p lib/screening-patterns/tsconfig.json && tsc -p lib/device-url/tsconfig.json && tsc -p lib/brand-templating/tsconfig.json && tsc -p lib/entitlement/tsconfig.json && tsc -p plugins/whatsapp-import/lib/tsconfig.json",
|
|
11
11
|
"build:memory": "tsc -p plugins/memory/mcp/tsconfig.json",
|
|
12
12
|
"build:contacts": "tsc -p plugins/contacts/mcp/tsconfig.json",
|
|
13
13
|
"build:telegram": "tsc -p plugins/telegram/mcp/tsconfig.json",
|