@rubytech/create-maxy-code 0.1.132 → 0.1.140
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/__tests__/installer-specialist-registration.test.js +5 -40
- package/dist/index.js +24 -28
- package/dist/specialist-registration.js +0 -15
- package/package.json +1 -1
- package/payload/platform/config/brand.json +1 -1
- package/payload/platform/lib/graph-search/dist/boosts.d.ts +39 -0
- package/payload/platform/lib/graph-search/dist/boosts.d.ts.map +1 -0
- package/payload/platform/lib/graph-search/dist/boosts.js +57 -0
- package/payload/platform/lib/graph-search/dist/boosts.js.map +1 -0
- package/payload/platform/lib/graph-search/dist/dedup.d.ts +29 -0
- package/payload/platform/lib/graph-search/dist/dedup.d.ts.map +1 -0
- package/payload/platform/lib/graph-search/dist/dedup.js +97 -0
- package/payload/platform/lib/graph-search/dist/dedup.js.map +1 -0
- package/payload/platform/lib/graph-search/dist/index.d.ts +70 -8
- package/payload/platform/lib/graph-search/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-search/dist/index.js +323 -62
- package/payload/platform/lib/graph-search/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-search/dist/query-expansion.d.ts +37 -0
- package/payload/platform/lib/graph-search/dist/query-expansion.d.ts.map +1 -0
- package/payload/platform/lib/graph-search/dist/query-expansion.js +101 -0
- package/payload/platform/lib/graph-search/dist/query-expansion.js.map +1 -0
- package/payload/platform/lib/graph-search/dist/route.d.ts +29 -0
- package/payload/platform/lib/graph-search/dist/route.d.ts.map +1 -0
- package/payload/platform/lib/graph-search/dist/route.js +53 -0
- package/payload/platform/lib/graph-search/dist/route.js.map +1 -0
- package/payload/platform/lib/graph-search/dist/rrf-fusion.d.ts +31 -0
- package/payload/platform/lib/graph-search/dist/rrf-fusion.d.ts.map +1 -0
- package/payload/platform/lib/graph-search/dist/rrf-fusion.js +57 -0
- package/payload/platform/lib/graph-search/dist/rrf-fusion.js.map +1 -0
- package/payload/platform/lib/graph-search/src/__tests__/boosts.test.ts +59 -0
- package/payload/platform/lib/graph-search/src/__tests__/dedup.test.ts +83 -0
- package/payload/platform/lib/graph-search/src/__tests__/query-expansion.test.ts +96 -0
- package/payload/platform/lib/graph-search/src/__tests__/route.test.ts +62 -0
- package/payload/platform/lib/graph-search/src/__tests__/rrf-fusion.test.ts +39 -0
- package/payload/platform/lib/graph-search/src/boosts.ts +61 -0
- package/payload/platform/lib/graph-search/src/dedup.ts +108 -0
- package/payload/platform/lib/graph-search/src/index.ts +407 -65
- package/payload/platform/lib/graph-search/src/query-expansion.ts +129 -0
- package/payload/platform/lib/graph-search/src/route.ts +70 -0
- package/payload/platform/lib/graph-search/src/rrf-fusion.ts +62 -0
- package/payload/platform/lib/obsidian-parser/dist/index.d.ts +98 -0
- package/payload/platform/lib/obsidian-parser/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/obsidian-parser/dist/index.js +480 -0
- package/payload/platform/lib/obsidian-parser/dist/index.js.map +1 -0
- package/payload/platform/lib/obsidian-parser/src/index.ts +572 -0
- package/payload/platform/lib/obsidian-parser/tsconfig.json +8 -0
- package/payload/platform/neo4j/schema.cypher +86 -1
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/.claude-plugin/marketplace.json +10 -0
- package/payload/platform/plugins/admin/hooks/session-end-retrospective.sh +4 -2
- package/payload/platform/plugins/admin/mcp/dist/index.js +6 -4
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/docs/references/internals.md +36 -10
- package/payload/platform/plugins/docs/references/neo4j.md +63 -0
- package/payload/platform/plugins/docs/references/plugins-guide.md +2 -0
- package/payload/platform/plugins/docs/references/session-retrospective.md +11 -4
- package/payload/platform/plugins/graph-viewer/mcp/dist/tools/graph-render.js +2 -2
- package/payload/platform/plugins/graph-viewer/mcp/dist/tools/graph-render.js.map +1 -1
- package/payload/platform/plugins/memory/PLUGIN.md +3 -0
- package/payload/platform/plugins/memory/mcp/dist/index.js +203 -7
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-property.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-property.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-property.test.js +25 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-property.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/timeline-extractor.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/timeline-extractor.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/timeline-extractor.test.js +70 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/timeline-extractor.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.js +50 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.d.ts +33 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.js +99 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.d.ts +21 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.js +24 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/timeline-extractor.d.ts +13 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/timeline-extractor.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/timeline-extractor.js +151 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/timeline-extractor.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts +55 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.js +290 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.d.ts +19 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js +102 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.js +18 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.js +5 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-emit.test.js +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-emit.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts +64 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js +258 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js +14 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts +29 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js +22 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.d.ts +31 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js +182 -50
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +76 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/obsidian-vault-import.d.ts +127 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/obsidian-vault-import.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/obsidian-vault-import.js +477 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/obsidian-vault-import.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/session-retrospective-skip-rate.d.ts +30 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/session-retrospective-skip-rate.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/session-retrospective-skip-rate.js +129 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/session-retrospective-skip-rate.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/scripts/backfill-typed-edges.ts +72 -0
- package/payload/platform/plugins/memory/mcp/scripts/generate-edge-docs.ts +75 -0
- package/payload/platform/plugins/memory/mcp/vitest.config.ts +5 -0
- package/payload/platform/plugins/memory/references/schema-base.md +44 -0
- package/payload/platform/plugins/notion-import/.claude-plugin/plugin.json +8 -0
- package/payload/platform/plugins/notion-import/PLUGIN.md +27 -0
- package/payload/platform/plugins/notion-import/skills/notion-import/SKILL.md +110 -0
- package/payload/platform/plugins/notion-import/skills/notion-import/references/attachments.md +55 -0
- package/payload/platform/plugins/notion-import/skills/notion-import/references/databases.md +81 -0
- package/payload/platform/plugins/notion-import/skills/notion-import/references/page-tree.md +61 -0
- package/payload/platform/plugins/notion-import/skills/notion-import/references/workspace-export.md +41 -0
- package/payload/platform/plugins/obsidian-import/.claude-plugin/plugin.json +8 -0
- package/payload/platform/plugins/obsidian-import/PLUGIN.md +39 -0
- package/payload/platform/plugins/obsidian-import/skills/obsidian-import/SKILL.md +92 -0
- package/payload/platform/plugins/obsidian-import/skills/obsidian-import/references/attachments.md +80 -0
- package/payload/platform/plugins/obsidian-import/skills/obsidian-import/references/daily-notes.md +31 -0
- package/payload/platform/plugins/obsidian-import/skills/obsidian-import/references/vault-structure.md +46 -0
- package/payload/platform/plugins/obsidian-import/skills/obsidian-import/references/wikilinks.md +70 -0
- package/payload/platform/scripts/seed-neo4j.sh +49 -0
- package/payload/platform/templates/agents/admin/IDENTITY.md +4 -3
- package/payload/platform/templates/specialists/agents/database-operator.md +21 -1
- package/payload/server/{adminuser-self-heal-QAWOZ3JV.js → adminuser-self-heal-YC47O34W.js} +2 -1
- package/payload/server/{chunk-JSBRDJBE.js → chunk-HYQNUVGO.js} +9 -1
- package/payload/server/{chunk-HCYM5FLU.js → chunk-T3DJD5QR.js} +3 -1
- package/payload/server/maxy-edge.js +3 -2
- package/payload/server/public/assets/{admin-FcRHAL-3.js → admin-BM9aXUUh.js} +1 -1
- package/payload/server/public/assets/{data-Ds37mflX.js → data-Ds2ECtfP.js} +1 -1
- package/payload/server/public/assets/{graph-CmWRhaiS.js → graph-BzxObKMM.js} +1 -1
- package/payload/server/public/assets/{graph-labels-Ch2r00Gt.js → graph-labels-Dwgep_nr.js} +1 -1
- package/payload/server/public/assets/{page-BcHhJXUt.js → page-BlkBsjP2.js} +1 -1
- package/payload/server/public/assets/page-h_SA5SVQ.js +51 -0
- package/payload/server/public/data.html +3 -3
- package/payload/server/public/graph.html +3 -3
- package/payload/server/public/index.html +4 -4
- package/payload/server/server.js +803 -76
- package/payload/server/public/assets/page-BOtNny_4.js +0 -51
|
@@ -7,7 +7,7 @@ import assert from "node:assert/strict";
|
|
|
7
7
|
import { mkdtempSync, mkdirSync, writeFileSync, readlinkSync, lstatSync, rmSync, symlinkSync, readdirSync } from "node:fs";
|
|
8
8
|
import { tmpdir } from "node:os";
|
|
9
9
|
import { join, resolve } from "node:path";
|
|
10
|
-
import { registerSpecialistAgentsAt,
|
|
10
|
+
import { registerSpecialistAgentsAt, SpecialistSymlinkCollision } from "../specialist-registration.js";
|
|
11
11
|
function makeTemplates(dir, names) {
|
|
12
12
|
mkdirSync(dir, { recursive: true });
|
|
13
13
|
for (const n of names)
|
|
@@ -90,45 +90,10 @@ test("skips with reason=no-templates-dir when templates dir is absent", () => {
|
|
|
90
90
|
rmSync(agentsDir, { recursive: true, force: true });
|
|
91
91
|
}
|
|
92
92
|
});
|
|
93
|
-
// Task
|
|
94
|
-
//
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
// quartet) threw `specialist-agent-file-missing` at spawn time.
|
|
98
|
-
test("premium bundle: symlinks each agent in the bundle's agents/ into agentsDir", () => {
|
|
99
|
-
const installDir = mkdtempSync(join(tmpdir(), "t349-install-"));
|
|
100
|
-
const agentsDir = mkdtempSync(join(tmpdir(), "t349-agents-"));
|
|
101
|
-
try {
|
|
102
|
-
const bundleAgentsDir = join(installDir, "premium-plugins", "real-agent", "agents");
|
|
103
|
-
makeTemplates(bundleAgentsDir, ["listing-curator", "negotiator", "valuer", "compliance"]);
|
|
104
|
-
const result = registerPremiumBundleAgents(installDir, ["real-agent"], agentsDir);
|
|
105
|
-
assert.deepEqual(result.bundles, ["real-agent"]);
|
|
106
|
-
for (const n of ["listing-curator", "negotiator", "valuer", "compliance"]) {
|
|
107
|
-
const linkPath = join(agentsDir, `${n}.md`);
|
|
108
|
-
const stat = lstatSync(linkPath);
|
|
109
|
-
assert.ok(stat.isSymbolicLink(), `${n}.md must be a symlink`);
|
|
110
|
-
const target = resolve(agentsDir, readlinkSync(linkPath));
|
|
111
|
-
assert.equal(target, resolve(bundleAgentsDir, `${n}.md`));
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
finally {
|
|
115
|
-
rmSync(installDir, { recursive: true, force: true });
|
|
116
|
-
rmSync(agentsDir, { recursive: true, force: true });
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
test("premium bundle: empty bundle list is a no-op — no error, no writes", () => {
|
|
120
|
-
const installDir = mkdtempSync(join(tmpdir(), "t349-install-"));
|
|
121
|
-
const agentsDir = mkdtempSync(join(tmpdir(), "t349-agents-"));
|
|
122
|
-
try {
|
|
123
|
-
const result = registerPremiumBundleAgents(installDir, [], agentsDir);
|
|
124
|
-
assert.deepEqual(result.bundles, []);
|
|
125
|
-
assert.deepEqual(readdirSync(agentsDir), []);
|
|
126
|
-
}
|
|
127
|
-
finally {
|
|
128
|
-
rmSync(installDir, { recursive: true, force: true });
|
|
129
|
-
rmSync(agentsDir, { recursive: true, force: true });
|
|
130
|
-
}
|
|
131
|
-
});
|
|
93
|
+
// Task 394 — premium-bundle agents previously registered via this same
|
|
94
|
+
// symlink path; they now register through the native Claude Code plugin
|
|
95
|
+
// manifest at bundle time. The two `premium bundle:` tests that asserted
|
|
96
|
+
// the symlink-channel behaviour were deleted with `registerPremiumBundleAgents`.
|
|
132
97
|
test("collides loudly on a regular file at the destination (no silent overwrite)", () => {
|
|
133
98
|
const templatesDir = mkdtempSync(join(tmpdir(), "t165-tpl-"));
|
|
134
99
|
const agentsDir = mkdtempSync(join(tmpdir(), "t165-agents-"));
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { execFileSync, spawn, spawnSync } from "node:child_process";
|
|
3
3
|
import { existsSync, mkdirSync, writeFileSync, cpSync, readFileSync, rmSync, readdirSync, appendFileSync, openSync, closeSync, chmodSync, statSync, realpathSync } from "node:fs";
|
|
4
|
-
import { registerSpecialistAgentsAt,
|
|
4
|
+
import { registerSpecialistAgentsAt, SpecialistSymlinkCollision } from "./specialist-registration.js";
|
|
5
5
|
import { resolve, join, dirname } from "node:path";
|
|
6
6
|
import { randomBytes } from "node:crypto";
|
|
7
7
|
import { resolveInstallPortFromFs, buildMaxyUnitFile, buildClaudeSessionManagerUnitFile, buildClaudePtysSliceUnitFile } from "./port-resolution.js";
|
|
@@ -2463,15 +2463,16 @@ function writeEntitlementFromFlag(payload) {
|
|
|
2463
2463
|
console.log(line);
|
|
2464
2464
|
logFile(line);
|
|
2465
2465
|
}
|
|
2466
|
+
// Task 394 — premium-bundle agents register through the native Claude Code
|
|
2467
|
+
// subagent registry via `.claude-plugin/plugin.json` manifests emitted by
|
|
2468
|
+
// scripts/generate-plugin-manifests.mjs at bundle time, not through a
|
|
2469
|
+
// parallel symlink channel. This function still wires the bundled platform
|
|
2470
|
+
// specialists (database-operator, project-manager, …) under
|
|
2471
|
+
// platform/templates/specialists/agents/, which are not part of a
|
|
2472
|
+
// registered plugin and rely on $CLAUDE_CONFIG_DIR/agents/ resolution.
|
|
2466
2473
|
function registerSpecialistAgents() {
|
|
2467
2474
|
try {
|
|
2468
2475
|
registerSpecialistAgentsAt(join(INSTALL_DIR, "platform/templates/specialists/agents"), join(CLAUDE_CONFIG_DIR, "agents"), (line) => { console.log(line); logFile(line); });
|
|
2469
|
-
// Task 349 — symlink each premium-bundle's agents/ into the same
|
|
2470
|
-
// $CLAUDE_CONFIG_DIR/agents/ so `--agent <name>` resolves for premium
|
|
2471
|
-
// specialists (e.g. realagent's listing-curator, negotiator, valuer,
|
|
2472
|
-
// compliance). The pty-spawner reads exactly one agents dir; the bundle
|
|
2473
|
-
// payload alone is insufficient without the symlink step here.
|
|
2474
|
-
registerPremiumBundleAgents(INSTALL_DIR, resolvePremiumBundles(), join(CLAUDE_CONFIG_DIR, "agents"), (line) => { console.log(line); logFile(line); });
|
|
2475
2476
|
}
|
|
2476
2477
|
catch (err) {
|
|
2477
2478
|
if (err instanceof SpecialistSymlinkCollision) {
|
|
@@ -2482,23 +2483,6 @@ function registerSpecialistAgents() {
|
|
|
2482
2483
|
throw err;
|
|
2483
2484
|
}
|
|
2484
2485
|
}
|
|
2485
|
-
// Resolve the brand's premium-bundle list for installer-side iteration.
|
|
2486
|
-
// `true` widens to every directory under <INSTALL_DIR>/premium-plugins/;
|
|
2487
|
-
// an explicit array is used verbatim; absent/false → no premium bundles.
|
|
2488
|
-
function resolvePremiumBundles() {
|
|
2489
|
-
const ships = BRAND.shipsPremiumBundles;
|
|
2490
|
-
if (Array.isArray(ships))
|
|
2491
|
-
return ships;
|
|
2492
|
-
if (ships === true) {
|
|
2493
|
-
const root = join(INSTALL_DIR, "premium-plugins");
|
|
2494
|
-
if (!existsSync(root))
|
|
2495
|
-
return [];
|
|
2496
|
-
return readdirSync(root, { withFileTypes: true })
|
|
2497
|
-
.filter((d) => d.isDirectory())
|
|
2498
|
-
.map((d) => d.name);
|
|
2499
|
-
}
|
|
2500
|
-
return [];
|
|
2501
|
-
}
|
|
2502
2486
|
// ---------------------------------------------------------------------------
|
|
2503
2487
|
// Account discovery (shared by installService + the post-install summary)
|
|
2504
2488
|
//
|
|
@@ -2567,9 +2551,12 @@ function installServiceDarwin() {
|
|
|
2567
2551
|
// Mirror the Linux brand systemd unit's `Environment=` lines into .env.
|
|
2568
2552
|
// Linux stamps every var explicitly on the unit; darwin has no systemd
|
|
2569
2553
|
// EnvironmentFile primitive, so the wrapper sources .env before exec'ing
|
|
2570
|
-
// node. Any var the boot path
|
|
2571
|
-
//
|
|
2572
|
-
//
|
|
2554
|
+
// node. Any var the boot path or per-request handlers require (PORT,
|
|
2555
|
+
// MAXY_UI_INTERNAL_PORT, CLAUDE_SESSION_MANAGER_PORT, ACCOUNT_ID,
|
|
2556
|
+
// MAXY_PLATFORM_ROOT, NEO4J_URI, CLAUDE_CONFIG_DIR, NODE_ENV) must be
|
|
2557
|
+
// written here or the server hard-fails — boot-throw for module-init
|
|
2558
|
+
// consumers, per-request 500s for handlers like /api/admin/claude-sessions*
|
|
2559
|
+
// that requirePortEnv lazily on the manager port.
|
|
2573
2560
|
// VNC/X11 vars (DISPLAY, RFB_PORT, WEBSOCKIFY_PORT, CDP_PORT) are Pi-only
|
|
2574
2561
|
// and excluded — darwin runs no kiosk display stack.
|
|
2575
2562
|
//
|
|
@@ -2604,11 +2591,20 @@ function installServiceDarwin() {
|
|
|
2604
2591
|
["NEO4J_URI", `bolt://localhost:${NEO4J_PORT}`],
|
|
2605
2592
|
["PORT", String(PORT)],
|
|
2606
2593
|
["MAXY_UI_INTERNAL_PORT", String(PORT)],
|
|
2594
|
+
["CLAUDE_SESSION_MANAGER_PORT", String(BRAND.claudeSessionManagerPort)],
|
|
2607
2595
|
["ACCOUNT_ID", installAccountId],
|
|
2608
2596
|
["MAXY_PLATFORM_ROOT", `${INSTALL_DIR}/platform`],
|
|
2609
2597
|
["CLAUDE_CONFIG_DIR", `${persistDir}/.claude`],
|
|
2610
2598
|
["HOSTNAME", "0.0.0.0"],
|
|
2611
2599
|
["KEEP_ALIVE_TIMEOUT", "61000"],
|
|
2600
|
+
// launchd hands the server a bare PATH (/usr/bin:/bin:/usr/sbin:/sbin)
|
|
2601
|
+
// that excludes the two Homebrew prefixes the `claude` binary lives in
|
|
2602
|
+
// under Apple Silicon and Intel. The wrapper sources this file with
|
|
2603
|
+
// `set -a; . "$envPath"; set +a`, so `$PATH` expands at source-time
|
|
2604
|
+
// against the bare launchd PATH and Homebrew prefixes get prepended for
|
|
2605
|
+
// every spawned descendant (claude-session-manager, MCP plugin spawns,
|
|
2606
|
+
// route-level spawn('claude', ...)). Task 386.
|
|
2607
|
+
["PATH", "/opt/homebrew/bin:/usr/local/bin:$PATH"],
|
|
2612
2608
|
]) {
|
|
2613
2609
|
const re = new RegExp(`^${key}=.*$`, "m");
|
|
2614
2610
|
if (re.test(envContent)) {
|
|
@@ -2619,7 +2615,7 @@ function installServiceDarwin() {
|
|
|
2619
2615
|
}
|
|
2620
2616
|
}
|
|
2621
2617
|
writeFileSync(envPath, envContent);
|
|
2622
|
-
logFile(` .env: DISPLAY_MODE=${DISPLAY_MODE}, EMBED_MODEL=${EMBED_MODEL}, EMBED_DIMENSIONS=${EMBED_DIMS}, NEO4J_URI=bolt://localhost:${NEO4J_PORT}, PORT=${PORT}, MAXY_UI_INTERNAL_PORT=${PORT} (darwin-collapsed), HOSTNAME=0.0.0.0, ACCOUNT_ID=${installAccountId.slice(0, 8)}…, CLAUDE_CONFIG_DIR=${persistDir}/.claude`);
|
|
2618
|
+
logFile(` .env: DISPLAY_MODE=${DISPLAY_MODE}, EMBED_MODEL=${EMBED_MODEL}, EMBED_DIMENSIONS=${EMBED_DIMS}, NEO4J_URI=bolt://localhost:${NEO4J_PORT}, PORT=${PORT}, MAXY_UI_INTERNAL_PORT=${PORT} (darwin-collapsed), CLAUDE_SESSION_MANAGER_PORT=${BRAND.claudeSessionManagerPort}, HOSTNAME=0.0.0.0, ACCOUNT_ID=${installAccountId.slice(0, 8)}…, CLAUDE_CONFIG_DIR=${persistDir}/.claude`);
|
|
2623
2619
|
}
|
|
2624
2620
|
catch (err) {
|
|
2625
2621
|
console.error(` WARNING: failed to write .env to ${envPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -47,21 +47,6 @@ export function registerSpecialistAgentsAt(templatesDir, agentsDir, log = () =>
|
|
|
47
47
|
}
|
|
48
48
|
return { registered, skipped: null };
|
|
49
49
|
}
|
|
50
|
-
// Task 349 — premium-bundle specialist symlinking. The installer wires each
|
|
51
|
-
// brand-shipped premium bundle's `agents/` directory into the same
|
|
52
|
-
// $CLAUDE_CONFIG_DIR/agents/ so `--agent <name>` resolves for premium
|
|
53
|
-
// specialists (e.g. realagent's listing-curator). `bundles` is the resolved
|
|
54
|
-
// list of bundle directory names; an empty list is a no-op (no error, no
|
|
55
|
-
// writes). Missing per-bundle `agents/` dirs are tolerated via
|
|
56
|
-
// registerSpecialistAgentsAt's existing no-templates-dir skip.
|
|
57
|
-
export function registerPremiumBundleAgents(installDir, bundles, agentsDir, log = () => { }) {
|
|
58
|
-
const registered = [];
|
|
59
|
-
for (const bundle of bundles) {
|
|
60
|
-
registerSpecialistAgentsAt(join(installDir, "premium-plugins", bundle, "agents"), agentsDir, log);
|
|
61
|
-
registered.push(bundle);
|
|
62
|
-
}
|
|
63
|
-
return { bundles: registered };
|
|
64
|
-
}
|
|
65
50
|
export function replaceSpecialistSymlink(linkPath, targetAbs) {
|
|
66
51
|
let lstat = null;
|
|
67
52
|
try {
|
package/package.json
CHANGED
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"plugins": {
|
|
51
51
|
"core": ["admin", "memory", "docs", "cloudflare", "anthropic", "workflows", "work", "scheduling", "email", "contacts", "projects"],
|
|
52
52
|
"defaultEnabled": ["business-assistant", "sales"],
|
|
53
|
-
"available": ["telegram", "deep-research", "whatsapp", "replicate", "linkedin-import"],
|
|
53
|
+
"available": ["telegram", "deep-research", "whatsapp", "replicate", "linkedin-import", "notion-import", "obsidian-import"],
|
|
54
54
|
"excluded": []
|
|
55
55
|
},
|
|
56
56
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Score boosts (Task 308).
|
|
3
|
+
*
|
|
4
|
+
* Two post-fetch score adjustments that re-rank hybrid hits using
|
|
5
|
+
* properties that the typed-edge hook (Task 305) and compiled-truth
|
|
6
|
+
* migration (Task 306) populate. Both are no-ops on the current corpus
|
|
7
|
+
* until those tasks land — the boost reads a missing property as zero
|
|
8
|
+
* and adds nothing.
|
|
9
|
+
*
|
|
10
|
+
* Boosts are pure functions over the scored hit array. They never query
|
|
11
|
+
* Neo4j; the data they read is already on each hit's `properties` map.
|
|
12
|
+
*/
|
|
13
|
+
export interface ScoredHit {
|
|
14
|
+
nodeId: string;
|
|
15
|
+
properties: Record<string, unknown>;
|
|
16
|
+
score: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Add a flat fractional bump to any hit whose node carries a non-null
|
|
20
|
+
* `compiledTruth` property. Authoritative summaries beat noisy timeline
|
|
21
|
+
* fragments — this puts compiled rows ahead when the score is close.
|
|
22
|
+
*
|
|
23
|
+
* Default weight 0.15 (+15%); the brief reserves room to tune.
|
|
24
|
+
*/
|
|
25
|
+
export declare function applyCompiledTruthBoost<T extends ScoredHit>(hits: T[], weight?: number): T[];
|
|
26
|
+
/**
|
|
27
|
+
* Log-weighted boost scaled by inbound MENTIONS edge count.
|
|
28
|
+
*
|
|
29
|
+
* Formula: `bump = clamp(0.05 + 0.05 * log10(count), 0.05, 0.25)` when
|
|
30
|
+
* count > 0; zero otherwise. So 1 backlink → +5%, 10 → +10%, 100 → +15%,
|
|
31
|
+
* 1000 → +20%, 10000+ → capped at +25%. Backlink-rich nodes (the
|
|
32
|
+
* graph's natural authorities) surface higher.
|
|
33
|
+
*
|
|
34
|
+
* Reads from `hit.properties.backlinkCount` — a property Task 305's
|
|
35
|
+
* post-write hook maintains. Until 305 lands the count is absent and
|
|
36
|
+
* the boost is identity.
|
|
37
|
+
*/
|
|
38
|
+
export declare function applyBacklinkBoost<T extends ScoredHit>(hits: T[]): T[];
|
|
39
|
+
//# sourceMappingURL=boosts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boosts.d.ts","sourceRoot":"","sources":["../src/boosts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,SAAS,EACzD,IAAI,EAAE,CAAC,EAAE,EACT,MAAM,SAAO,GACZ,CAAC,EAAE,CASL;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAQtE"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Score boosts (Task 308).
|
|
4
|
+
*
|
|
5
|
+
* Two post-fetch score adjustments that re-rank hybrid hits using
|
|
6
|
+
* properties that the typed-edge hook (Task 305) and compiled-truth
|
|
7
|
+
* migration (Task 306) populate. Both are no-ops on the current corpus
|
|
8
|
+
* until those tasks land — the boost reads a missing property as zero
|
|
9
|
+
* and adds nothing.
|
|
10
|
+
*
|
|
11
|
+
* Boosts are pure functions over the scored hit array. They never query
|
|
12
|
+
* Neo4j; the data they read is already on each hit's `properties` map.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.applyCompiledTruthBoost = applyCompiledTruthBoost;
|
|
16
|
+
exports.applyBacklinkBoost = applyBacklinkBoost;
|
|
17
|
+
/**
|
|
18
|
+
* Add a flat fractional bump to any hit whose node carries a non-null
|
|
19
|
+
* `compiledTruth` property. Authoritative summaries beat noisy timeline
|
|
20
|
+
* fragments — this puts compiled rows ahead when the score is close.
|
|
21
|
+
*
|
|
22
|
+
* Default weight 0.15 (+15%); the brief reserves room to tune.
|
|
23
|
+
*/
|
|
24
|
+
function applyCompiledTruthBoost(hits, weight = 0.15) {
|
|
25
|
+
if (weight < 0 || weight > 1) {
|
|
26
|
+
throw new Error(`applyCompiledTruthBoost: weight must be in [0,1], got ${weight}`);
|
|
27
|
+
}
|
|
28
|
+
return hits.map((hit) => {
|
|
29
|
+
const compiled = hit.properties["compiledTruth"];
|
|
30
|
+
if (compiled === null || compiled === undefined || compiled === "")
|
|
31
|
+
return hit;
|
|
32
|
+
return { ...hit, score: hit.score * (1 + weight) };
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Log-weighted boost scaled by inbound MENTIONS edge count.
|
|
37
|
+
*
|
|
38
|
+
* Formula: `bump = clamp(0.05 + 0.05 * log10(count), 0.05, 0.25)` when
|
|
39
|
+
* count > 0; zero otherwise. So 1 backlink → +5%, 10 → +10%, 100 → +15%,
|
|
40
|
+
* 1000 → +20%, 10000+ → capped at +25%. Backlink-rich nodes (the
|
|
41
|
+
* graph's natural authorities) surface higher.
|
|
42
|
+
*
|
|
43
|
+
* Reads from `hit.properties.backlinkCount` — a property Task 305's
|
|
44
|
+
* post-write hook maintains. Until 305 lands the count is absent and
|
|
45
|
+
* the boost is identity.
|
|
46
|
+
*/
|
|
47
|
+
function applyBacklinkBoost(hits) {
|
|
48
|
+
return hits.map((hit) => {
|
|
49
|
+
const raw = hit.properties["backlinkCount"];
|
|
50
|
+
const count = typeof raw === "number" ? raw : Number(raw);
|
|
51
|
+
if (!Number.isFinite(count) || count <= 0)
|
|
52
|
+
return hit;
|
|
53
|
+
const bump = Math.max(0.05, Math.min(0.25, 0.05 + 0.05 * Math.log10(count)));
|
|
54
|
+
return { ...hit, score: hit.score * (1 + bump) };
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=boosts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boosts.js","sourceRoot":"","sources":["../src/boosts.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;AAeH,0DAYC;AAcD,gDAQC;AAzCD;;;;;;GAMG;AACH,SAAgB,uBAAuB,CACrC,IAAS,EACT,MAAM,GAAG,IAAI;IAEb,IAAI,MAAM,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,yDAAyD,MAAM,EAAE,CAAC,CAAC;IACrF,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACtB,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;QACjD,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,EAAE;YAAE,OAAO,GAAG,CAAC;QAC/E,OAAO,EAAE,GAAG,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC;IACrD,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,kBAAkB,CAAsB,IAAS;IAC/D,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACtB,MAAM,GAAG,GAAG,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;YAAE,OAAO,GAAG,CAAC;QACtD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC7E,OAAO,EAAE,GAAG,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 4-layer dedup (Task 308).
|
|
3
|
+
*
|
|
4
|
+
* Strict superset of the previous nodeId-only dedup. Catches duplicate
|
|
5
|
+
* representations the typed-edge hook (Task 305) and document-ingest
|
|
6
|
+
* pipeline will inevitably create: slug variants, canonical-name
|
|
7
|
+
* variants, and content-hash duplicates.
|
|
8
|
+
*
|
|
9
|
+
* Order: hits are sorted by descending score FIRST, then walked. The
|
|
10
|
+
* highest-score representative wins on every layer; later entries with
|
|
11
|
+
* the same key on any active layer are dropped. Missing values on a
|
|
12
|
+
* layer (no `slug`, no `canonicalName`, no derivable hash) are not
|
|
13
|
+
* collisions — they simply skip that layer for that row.
|
|
14
|
+
*/
|
|
15
|
+
export type DedupLayer = "nodeId" | "slug" | "canonicalName" | "contentHash";
|
|
16
|
+
export declare const DEFAULT_LAYERS: DedupLayer[];
|
|
17
|
+
interface DedupHit {
|
|
18
|
+
nodeId: string;
|
|
19
|
+
properties: Record<string, unknown>;
|
|
20
|
+
score: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Dedup `hits` across the requested layers. Returns a new array with the
|
|
24
|
+
* highest-scoring representative per collision class, in original
|
|
25
|
+
* descending-score order.
|
|
26
|
+
*/
|
|
27
|
+
export declare function dedup<T extends DedupHit>(hits: T[], layers?: DedupLayer[]): T[];
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=dedup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dedup.d.ts","sourceRoot":"","sources":["../src/dedup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,eAAe,GAAG,aAAa,CAAC;AAE7E,eAAO,MAAM,cAAc,EAAE,UAAU,EAKtC,CAAC;AAEF,UAAU,QAAQ;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC;CACf;AA6BD;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,QAAQ,EACtC,IAAI,EAAE,CAAC,EAAE,EACT,MAAM,GAAE,UAAU,EAAmB,GACpC,CAAC,EAAE,CAwCL"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* 4-layer dedup (Task 308).
|
|
4
|
+
*
|
|
5
|
+
* Strict superset of the previous nodeId-only dedup. Catches duplicate
|
|
6
|
+
* representations the typed-edge hook (Task 305) and document-ingest
|
|
7
|
+
* pipeline will inevitably create: slug variants, canonical-name
|
|
8
|
+
* variants, and content-hash duplicates.
|
|
9
|
+
*
|
|
10
|
+
* Order: hits are sorted by descending score FIRST, then walked. The
|
|
11
|
+
* highest-score representative wins on every layer; later entries with
|
|
12
|
+
* the same key on any active layer are dropped. Missing values on a
|
|
13
|
+
* layer (no `slug`, no `canonicalName`, no derivable hash) are not
|
|
14
|
+
* collisions — they simply skip that layer for that row.
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.DEFAULT_LAYERS = void 0;
|
|
18
|
+
exports.dedup = dedup;
|
|
19
|
+
const node_crypto_1 = require("node:crypto");
|
|
20
|
+
exports.DEFAULT_LAYERS = [
|
|
21
|
+
"nodeId",
|
|
22
|
+
"slug",
|
|
23
|
+
"canonicalName",
|
|
24
|
+
"contentHash",
|
|
25
|
+
];
|
|
26
|
+
function readSlug(props) {
|
|
27
|
+
const slug = props["slug"];
|
|
28
|
+
return typeof slug === "string" && slug.length > 0 ? slug : null;
|
|
29
|
+
}
|
|
30
|
+
function readCanonicalName(props) {
|
|
31
|
+
const canonical = props["canonicalName"];
|
|
32
|
+
if (typeof canonical === "string" && canonical.length > 0) {
|
|
33
|
+
return canonical.toLowerCase();
|
|
34
|
+
}
|
|
35
|
+
const name = props["name"];
|
|
36
|
+
if (typeof name === "string" && name.length > 0) {
|
|
37
|
+
return name.toLowerCase();
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
function readContentHash(props) {
|
|
42
|
+
const compiled = props["compiledTruth"];
|
|
43
|
+
const content = props["content"];
|
|
44
|
+
const source = (typeof compiled === "string" && compiled.length > 0)
|
|
45
|
+
? compiled
|
|
46
|
+
: (typeof content === "string" && content.length > 0 ? content : null);
|
|
47
|
+
if (source === null)
|
|
48
|
+
return null;
|
|
49
|
+
return (0, node_crypto_1.createHash)("sha256").update(source).digest("hex").slice(0, 16);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Dedup `hits` across the requested layers. Returns a new array with the
|
|
53
|
+
* highest-scoring representative per collision class, in original
|
|
54
|
+
* descending-score order.
|
|
55
|
+
*/
|
|
56
|
+
function dedup(hits, layers = exports.DEFAULT_LAYERS) {
|
|
57
|
+
const sorted = [...hits].sort((a, b) => b.score - a.score);
|
|
58
|
+
const seen = new Map();
|
|
59
|
+
for (const layer of layers)
|
|
60
|
+
seen.set(layer, new Set());
|
|
61
|
+
const out = [];
|
|
62
|
+
for (const hit of sorted) {
|
|
63
|
+
let collision = false;
|
|
64
|
+
const keys = [];
|
|
65
|
+
for (const layer of layers) {
|
|
66
|
+
let key;
|
|
67
|
+
switch (layer) {
|
|
68
|
+
case "nodeId":
|
|
69
|
+
key = hit.nodeId;
|
|
70
|
+
break;
|
|
71
|
+
case "slug":
|
|
72
|
+
key = readSlug(hit.properties);
|
|
73
|
+
break;
|
|
74
|
+
case "canonicalName":
|
|
75
|
+
key = readCanonicalName(hit.properties);
|
|
76
|
+
break;
|
|
77
|
+
case "contentHash":
|
|
78
|
+
key = readContentHash(hit.properties);
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
if (key === null)
|
|
82
|
+
continue;
|
|
83
|
+
if (seen.get(layer).has(key)) {
|
|
84
|
+
collision = true;
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
keys.push([layer, key]);
|
|
88
|
+
}
|
|
89
|
+
if (collision)
|
|
90
|
+
continue;
|
|
91
|
+
for (const [layer, key] of keys)
|
|
92
|
+
seen.get(layer).add(key);
|
|
93
|
+
out.push(hit);
|
|
94
|
+
}
|
|
95
|
+
return out;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=dedup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dedup.js","sourceRoot":"","sources":["../src/dedup.ts"],"names":[],"mappings":"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"}
|
|
@@ -39,6 +39,10 @@
|
|
|
39
39
|
* line with the prefix and fields it wants.
|
|
40
40
|
*/
|
|
41
41
|
import { type Session } from "neo4j-driver";
|
|
42
|
+
import { DEFAULT_LAYERS, type DedupLayer } from "./dedup.js";
|
|
43
|
+
import { type RetrievalClass } from "./route.js";
|
|
44
|
+
export type { DedupLayer, RetrievalClass };
|
|
45
|
+
export { DEFAULT_LAYERS };
|
|
42
46
|
/**
|
|
43
47
|
* Name of the universal fulltext index. Mirrors the `CREATE FULLTEXT
|
|
44
48
|
* INDEX` declaration in `platform/neo4j/schema.cypher`. The doctrine test
|
|
@@ -99,7 +103,17 @@ export interface ScoredNode {
|
|
|
99
103
|
*/
|
|
100
104
|
bm25Hit: boolean;
|
|
101
105
|
}
|
|
102
|
-
|
|
106
|
+
/**
|
|
107
|
+
* `"hybrid"` = weighted-sum fusion path (the baseline; the
|
|
108
|
+
* brief calls this `weighted-sum`).
|
|
109
|
+
* `"rrf"` = RRF fusion path (Task 308, flagged via `MAXY_GS_RRF`).
|
|
110
|
+
* `"bm25"` = degraded path after embed failure with `degradeOnEmbedFailure`.
|
|
111
|
+
*
|
|
112
|
+
* UI callers (e.g. `platform/ui/app/graph/page.tsx`) pattern-match on
|
|
113
|
+
* `"bm25"` to render the Ollama-down banner; non-`"bm25"` values collapse
|
|
114
|
+
* to the normal banner, so adding `"rrf"` is wire-compatible.
|
|
115
|
+
*/
|
|
116
|
+
export type SearchMode = "hybrid" | "rrf" | "bm25";
|
|
103
117
|
export interface Bm25OnlyParams {
|
|
104
118
|
query: string;
|
|
105
119
|
accountId?: string;
|
|
@@ -144,6 +158,30 @@ export interface HybridParams extends Bm25OnlyParams {
|
|
|
144
158
|
* default; the lib itself takes no opinion on the value.
|
|
145
159
|
*/
|
|
146
160
|
vectorThreshold?: number;
|
|
161
|
+
/**
|
|
162
|
+
* Routing hint from the inbound-gateway classifier (Task 304). When
|
|
163
|
+
* the `MAXY_GS_ROUTE` flag is on, the lib picks a label filter and
|
|
164
|
+
* fusion-weight plan per class. Omitted ⇒ `"general"` (unflagged
|
|
165
|
+
* callers see no change).
|
|
166
|
+
*/
|
|
167
|
+
retrievalClass?: RetrievalClass;
|
|
168
|
+
/** Per-call override: enable Reciprocal Rank Fusion. */
|
|
169
|
+
enableRrf?: boolean;
|
|
170
|
+
/** Per-call override: enable Haiku multi-query expansion. */
|
|
171
|
+
enableExpansion?: boolean;
|
|
172
|
+
/** Per-call override: enable compiledTruth + backlink boosts. */
|
|
173
|
+
enableBoosts?: boolean;
|
|
174
|
+
/** Per-call override: enable 4-layer dedup (default layers below). */
|
|
175
|
+
enableDedup?: boolean;
|
|
176
|
+
/** Per-call override: enable retrieval-class routing. */
|
|
177
|
+
enableRoute?: boolean;
|
|
178
|
+
/**
|
|
179
|
+
* Layers passed to the 4-layer dedup when `enableDedup` is true.
|
|
180
|
+
* Defaults to `["nodeId","slug","canonicalName","contentHash"]`.
|
|
181
|
+
*/
|
|
182
|
+
dedupLayers?: DedupLayer[];
|
|
183
|
+
/** RRF smoothing constant. Default 60 (gbrain default). */
|
|
184
|
+
rrfK?: number;
|
|
147
185
|
}
|
|
148
186
|
export interface HybridResponse {
|
|
149
187
|
mode: SearchMode;
|
|
@@ -178,6 +216,21 @@ export interface HybridResponse {
|
|
|
178
216
|
suppressed: number;
|
|
179
217
|
bm25Bypass: number;
|
|
180
218
|
threshold: number | null;
|
|
219
|
+
/**
|
|
220
|
+
* Per-stage counts surfaced for the caller's `[graph-search:hybrid]`
|
|
221
|
+
* log line (Task 308). Always present; values reflect whichever
|
|
222
|
+
* enhancements ran on this call. `expansions` is 1 when expansion
|
|
223
|
+
* was off, `boosted - fused` is 0 when boosts were no-ops, etc.
|
|
224
|
+
*/
|
|
225
|
+
stageCounts: {
|
|
226
|
+
expansions: number;
|
|
227
|
+
vector: number;
|
|
228
|
+
bm25: number;
|
|
229
|
+
fused: number;
|
|
230
|
+
boosted: number;
|
|
231
|
+
deduped: number;
|
|
232
|
+
final: number;
|
|
233
|
+
};
|
|
181
234
|
}
|
|
182
235
|
export type EmbedFn = (text: string) => Promise<number[]>;
|
|
183
236
|
/**
|
|
@@ -207,20 +260,29 @@ export declare function bm25Only(session: Session, params: Bm25OnlyParams): Prom
|
|
|
207
260
|
* Hybrid vector + BM25 search with graph expansion.
|
|
208
261
|
*
|
|
209
262
|
* Sequence:
|
|
210
|
-
* 1.
|
|
263
|
+
* 1. Resolve flags + route plan. Route may short-circuit (`retrievalClass=none`).
|
|
264
|
+
* 2. Multi-query expansion (Task 308 flag): Haiku produces 3-5 paraphrases.
|
|
265
|
+
* Each paraphrase is embedded and run through vector+BM25 in parallel.
|
|
266
|
+
* 3. embed(query) — may throw if Ollama is unreachable. When
|
|
211
267
|
* `degradeOnEmbedFailure=true`, caller receives bm25Only() result
|
|
212
268
|
* with `mode: "bm25"`; otherwise the throw propagates.
|
|
213
|
-
*
|
|
269
|
+
* 4. Vector search per label (one query per vector index discovered at
|
|
214
270
|
* boot). Nodes-by-label filter short-circuits when the requested
|
|
215
271
|
* labels have no index.
|
|
216
|
-
*
|
|
272
|
+
* 5. BM25 search on the universal `entity_search` index —
|
|
217
273
|
* same filter semantics as vector half (scope/agent/keyword/trashed).
|
|
218
|
-
*
|
|
274
|
+
* 6. Keyword subscriptions (when set): BM25 per keyword + property
|
|
219
275
|
* lookup against `node.keywords` array. Both bypass the agentSlug
|
|
220
276
|
* filter — subscriptions are scope-inclusive by design (matches
|
|
221
|
-
* memory-search.ts comment L319).
|
|
222
|
-
*
|
|
223
|
-
*
|
|
277
|
+
* memory-search.ts comment L319). Runs once, not per expansion.
|
|
278
|
+
* 7. Fusion: weighted-sum (`vw * vector + bw * bm25_norm`) by default,
|
|
279
|
+
* RRF when `MAXY_GS_RRF` is on. Route plan supplies fusion weights.
|
|
280
|
+
* 8. Boosts (Task 308 flag): compiledTruth bump + backlink log-bump.
|
|
281
|
+
* 9. Dedup (Task 308 flag): 4-layer dedup over the union, default layers
|
|
282
|
+
* `[nodeId, slug, canonicalName, contentHash]`.
|
|
283
|
+
* 10. Threshold + sort + slice. Counts (rawMerged / suppressed / bm25Bypass)
|
|
284
|
+
* reflect the pre-threshold and post-threshold populations.
|
|
285
|
+
* 11. Graph expand (1 hop by default, 0 to skip) — notTrashed filter +
|
|
224
286
|
* scope + agent clauses mirrored.
|
|
225
287
|
*/
|
|
226
288
|
export declare function hybrid(session: Session, embed: EmbedFn, params: HybridParams): Promise<HybridResponse>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,EAAO,KAAK,OAAO,EAAE,MAAM,cAAc,CAAC;AAKjD;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AAEnD,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAa,SAAQ,SAAS;IAC7C;;;;;;;;;OASG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,KAAK,CAAC;QACb;;;;WAIG;QACH,MAAM,EAAE,MAAM,CAAC;QACf,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACrC,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;;;OAYG;IACH,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|