@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
package/payload/server/server.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
1
2
|
import {
|
|
2
3
|
ACCOUNTS_DIR,
|
|
3
4
|
BIN_DIR,
|
|
@@ -83,11 +84,12 @@ import {
|
|
|
83
84
|
vncLog,
|
|
84
85
|
walkPremiumBundles,
|
|
85
86
|
writeAdminUserAndPerson
|
|
86
|
-
} from "./chunk-
|
|
87
|
+
} from "./chunk-T3DJD5QR.js";
|
|
87
88
|
import {
|
|
88
89
|
__commonJS,
|
|
90
|
+
__require,
|
|
89
91
|
__toESM
|
|
90
|
-
} from "./chunk-
|
|
92
|
+
} from "./chunk-HYQNUVGO.js";
|
|
91
93
|
|
|
92
94
|
// ../lib/graph-trash/dist/index.js
|
|
93
95
|
var require_dist = __commonJS({
|
|
@@ -365,8 +367,314 @@ var require_dist = __commonJS({
|
|
|
365
367
|
}
|
|
366
368
|
});
|
|
367
369
|
|
|
368
|
-
// ../lib/
|
|
370
|
+
// ../lib/oauth-llm/dist/index.js
|
|
369
371
|
var require_dist2 = __commonJS({
|
|
372
|
+
"../lib/oauth-llm/dist/index.js"(exports) {
|
|
373
|
+
"use strict";
|
|
374
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
375
|
+
exports.OAUTH_BETA_HEADER = void 0;
|
|
376
|
+
exports.callOauthLlm = callOauthLlm3;
|
|
377
|
+
var node_fs_1 = __require("fs");
|
|
378
|
+
var node_path_1 = __require("path");
|
|
379
|
+
var node_os_1 = __require("os");
|
|
380
|
+
var CREDENTIALS_FILE2 = process.env.CLAUDE_CONFIG_DIR ? (0, node_path_1.resolve)(process.env.CLAUDE_CONFIG_DIR, ".credentials.json") : (0, node_path_1.resolve)((0, node_os_1.homedir)(), ".claude", ".credentials.json");
|
|
381
|
+
var TOKEN_ENDPOINT3 = "https://platform.claude.com/v1/oauth/token";
|
|
382
|
+
var ANTHROPIC_MESSAGES_ENDPOINT2 = "https://api.anthropic.com/v1/messages";
|
|
383
|
+
var ANTHROPIC_VERSION2 = "2023-06-01";
|
|
384
|
+
var CLIENT_ID3 = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
|
|
385
|
+
var OAUTH_BETA_HEADER2 = "oauth-2025-04-20";
|
|
386
|
+
exports.OAUTH_BETA_HEADER = OAUTH_BETA_HEADER2;
|
|
387
|
+
var EXPIRING_THRESHOLD_MS3 = 5 * 60 * 1e3;
|
|
388
|
+
var INPUT_TOO_LARGE_MARKERS2 = [
|
|
389
|
+
"prompt is too long",
|
|
390
|
+
"context_length_exceeded",
|
|
391
|
+
"too many tokens"
|
|
392
|
+
];
|
|
393
|
+
function isInputTooLargeBody2(body) {
|
|
394
|
+
const lower = body.toLowerCase();
|
|
395
|
+
return INPUT_TOO_LARGE_MARKERS2.some((m) => lower.includes(m));
|
|
396
|
+
}
|
|
397
|
+
function readCredentials3() {
|
|
398
|
+
let raw;
|
|
399
|
+
try {
|
|
400
|
+
raw = (0, node_fs_1.readFileSync)(CREDENTIALS_FILE2, "utf-8");
|
|
401
|
+
} catch {
|
|
402
|
+
return null;
|
|
403
|
+
}
|
|
404
|
+
let data;
|
|
405
|
+
try {
|
|
406
|
+
data = JSON.parse(raw);
|
|
407
|
+
} catch {
|
|
408
|
+
return null;
|
|
409
|
+
}
|
|
410
|
+
const oauth = data.claudeAiOauth;
|
|
411
|
+
if (!oauth || typeof oauth !== "object")
|
|
412
|
+
return null;
|
|
413
|
+
const accessToken = oauth.accessToken;
|
|
414
|
+
const refreshToken = oauth.refreshToken;
|
|
415
|
+
const expiresAt = oauth.expiresAt;
|
|
416
|
+
if (typeof accessToken !== "string" || !accessToken)
|
|
417
|
+
return null;
|
|
418
|
+
if (typeof expiresAt !== "number" || !Number.isFinite(expiresAt) || expiresAt <= 0) {
|
|
419
|
+
return null;
|
|
420
|
+
}
|
|
421
|
+
return {
|
|
422
|
+
accessToken,
|
|
423
|
+
refreshToken: typeof refreshToken === "string" && refreshToken ? refreshToken : null,
|
|
424
|
+
expiresAt
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
function writeCredentials2(tokens) {
|
|
428
|
+
const newExpiresAt = typeof tokens.expiresIn === "number" && tokens.expiresIn > 0 ? Date.now() + tokens.expiresIn * 1e3 : Date.now() + 3600 * 1e3;
|
|
429
|
+
let fileData = {};
|
|
430
|
+
try {
|
|
431
|
+
fileData = JSON.parse((0, node_fs_1.readFileSync)(CREDENTIALS_FILE2, "utf-8"));
|
|
432
|
+
} catch {
|
|
433
|
+
}
|
|
434
|
+
const existing = fileData.claudeAiOauth;
|
|
435
|
+
fileData.claudeAiOauth = {
|
|
436
|
+
...existing,
|
|
437
|
+
accessToken: tokens.accessToken,
|
|
438
|
+
...tokens.refreshToken != null ? { refreshToken: tokens.refreshToken } : {},
|
|
439
|
+
expiresAt: newExpiresAt
|
|
440
|
+
};
|
|
441
|
+
(0, node_fs_1.writeFileSync)(CREDENTIALS_FILE2, JSON.stringify(fileData, null, 2), "utf-8");
|
|
442
|
+
return newExpiresAt;
|
|
443
|
+
}
|
|
444
|
+
var refreshLock3 = null;
|
|
445
|
+
async function refreshAccessToken3(current) {
|
|
446
|
+
if (refreshLock3)
|
|
447
|
+
return refreshLock3;
|
|
448
|
+
refreshLock3 = (async () => {
|
|
449
|
+
const fresh = readCredentials3();
|
|
450
|
+
if (fresh && fresh.expiresAt - Date.now() > EXPIRING_THRESHOLD_MS3) {
|
|
451
|
+
return fresh;
|
|
452
|
+
}
|
|
453
|
+
if (!current.refreshToken) {
|
|
454
|
+
return null;
|
|
455
|
+
}
|
|
456
|
+
let res;
|
|
457
|
+
try {
|
|
458
|
+
res = await fetch(TOKEN_ENDPOINT3, {
|
|
459
|
+
method: "POST",
|
|
460
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
461
|
+
body: new URLSearchParams({
|
|
462
|
+
grant_type: "refresh_token",
|
|
463
|
+
refresh_token: current.refreshToken,
|
|
464
|
+
client_id: CLIENT_ID3
|
|
465
|
+
})
|
|
466
|
+
});
|
|
467
|
+
} catch (err) {
|
|
468
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
469
|
+
console.error(`[oauth-llm] refresh network error: ${msg}`);
|
|
470
|
+
return null;
|
|
471
|
+
}
|
|
472
|
+
if (!res.ok) {
|
|
473
|
+
const body = await res.text().catch(() => "");
|
|
474
|
+
console.error(`[oauth-llm] refresh failed status=${res.status} body=${body.slice(0, 200)}`);
|
|
475
|
+
return null;
|
|
476
|
+
}
|
|
477
|
+
let tokenData;
|
|
478
|
+
try {
|
|
479
|
+
tokenData = await res.json();
|
|
480
|
+
} catch {
|
|
481
|
+
console.error("[oauth-llm] refresh returned malformed JSON");
|
|
482
|
+
return null;
|
|
483
|
+
}
|
|
484
|
+
const newAccessToken = tokenData.access_token;
|
|
485
|
+
const newRefreshToken = tokenData.refresh_token;
|
|
486
|
+
const expiresIn = tokenData.expires_in;
|
|
487
|
+
if (typeof newAccessToken !== "string" || !newAccessToken) {
|
|
488
|
+
console.error("[oauth-llm] refresh response missing access_token");
|
|
489
|
+
return null;
|
|
490
|
+
}
|
|
491
|
+
const newExpiresAt = writeCredentials2({
|
|
492
|
+
accessToken: newAccessToken,
|
|
493
|
+
refreshToken: typeof newRefreshToken === "string" && newRefreshToken ? newRefreshToken : current.refreshToken,
|
|
494
|
+
expiresIn: typeof expiresIn === "number" && expiresIn > 0 ? expiresIn : void 0
|
|
495
|
+
});
|
|
496
|
+
console.error(`[oauth-llm] refresh ok expiresAt=${new Date(newExpiresAt).toISOString()}`);
|
|
497
|
+
return {
|
|
498
|
+
accessToken: newAccessToken,
|
|
499
|
+
refreshToken: typeof newRefreshToken === "string" && newRefreshToken ? newRefreshToken : current.refreshToken,
|
|
500
|
+
expiresAt: newExpiresAt
|
|
501
|
+
};
|
|
502
|
+
})();
|
|
503
|
+
try {
|
|
504
|
+
return await refreshLock3;
|
|
505
|
+
} finally {
|
|
506
|
+
refreshLock3 = null;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
async function ensureValidToken2() {
|
|
510
|
+
const creds = readCredentials3();
|
|
511
|
+
if (!creds)
|
|
512
|
+
return null;
|
|
513
|
+
const remaining = creds.expiresAt - Date.now();
|
|
514
|
+
if (remaining > EXPIRING_THRESHOLD_MS3)
|
|
515
|
+
return creds;
|
|
516
|
+
if (remaining > 0 && !creds.refreshToken)
|
|
517
|
+
return creds;
|
|
518
|
+
if (remaining <= 0 && !creds.refreshToken)
|
|
519
|
+
return null;
|
|
520
|
+
return refreshAccessToken3(creds);
|
|
521
|
+
}
|
|
522
|
+
var betaHeaderLogged2 = false;
|
|
523
|
+
function logBetaHeaderOnce2() {
|
|
524
|
+
if (betaHeaderLogged2)
|
|
525
|
+
return;
|
|
526
|
+
betaHeaderLogged2 = true;
|
|
527
|
+
console.error(`[oauth-llm] beta-header=${OAUTH_BETA_HEADER2}`);
|
|
528
|
+
}
|
|
529
|
+
async function callOauthLlm3(params) {
|
|
530
|
+
const { model, system, userMessage, maxTokens = 4096, timeoutMs = 6e4, tools, toolChoiceName } = params;
|
|
531
|
+
if (tools && tools.length > 0 && !toolChoiceName) {
|
|
532
|
+
return {
|
|
533
|
+
kind: "fallback",
|
|
534
|
+
cause: "unexpected",
|
|
535
|
+
reason: "callOauthLlm: `tools` provided without `toolChoiceName`. Forced tool selection is required."
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
logBetaHeaderOnce2();
|
|
539
|
+
const creds = await ensureValidToken2();
|
|
540
|
+
if (!creds) {
|
|
541
|
+
return {
|
|
542
|
+
kind: "fallback",
|
|
543
|
+
cause: "missing-creds",
|
|
544
|
+
reason: "Claude Code OAuth credentials missing or expired with no refresh token available \u2014 operator must re-authenticate."
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
const controller = new AbortController();
|
|
548
|
+
const timer2 = setTimeout(() => controller.abort(), timeoutMs);
|
|
549
|
+
let res;
|
|
550
|
+
try {
|
|
551
|
+
res = await fetch(ANTHROPIC_MESSAGES_ENDPOINT2, {
|
|
552
|
+
method: "POST",
|
|
553
|
+
headers: {
|
|
554
|
+
"Content-Type": "application/json",
|
|
555
|
+
"anthropic-version": ANTHROPIC_VERSION2,
|
|
556
|
+
"anthropic-beta": OAUTH_BETA_HEADER2,
|
|
557
|
+
Authorization: `Bearer ${creds.accessToken}`
|
|
558
|
+
},
|
|
559
|
+
body: JSON.stringify({
|
|
560
|
+
model,
|
|
561
|
+
max_tokens: maxTokens,
|
|
562
|
+
system,
|
|
563
|
+
messages: [{ role: "user", content: userMessage }],
|
|
564
|
+
...tools && tools.length > 0 ? { tools } : {},
|
|
565
|
+
...toolChoiceName ? { tool_choice: { type: "tool", name: toolChoiceName } } : {}
|
|
566
|
+
}),
|
|
567
|
+
signal: controller.signal
|
|
568
|
+
});
|
|
569
|
+
} catch (err) {
|
|
570
|
+
clearTimeout(timer2);
|
|
571
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
572
|
+
if (controller.signal.aborted) {
|
|
573
|
+
return {
|
|
574
|
+
kind: "fallback",
|
|
575
|
+
cause: "timeout",
|
|
576
|
+
reason: `Model call timed out after ${timeoutMs}ms.`
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
return {
|
|
580
|
+
kind: "fallback",
|
|
581
|
+
cause: "network-error",
|
|
582
|
+
reason: `Network error reaching Anthropic: ${msg}`
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
clearTimeout(timer2);
|
|
586
|
+
if (!res.ok) {
|
|
587
|
+
const body = await res.text().catch(() => "");
|
|
588
|
+
if (res.status === 401 || res.status === 403) {
|
|
589
|
+
return {
|
|
590
|
+
kind: "fallback",
|
|
591
|
+
cause: "auth-error",
|
|
592
|
+
reason: `OAuth bearer rejected (status=${res.status}) \u2014 token may be revoked or beta header rejected. body=${body.slice(0, 200)}`
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
if (res.status === 429) {
|
|
596
|
+
return {
|
|
597
|
+
kind: "fallback",
|
|
598
|
+
cause: "rate-limit",
|
|
599
|
+
reason: `Anthropic rate limit hit (status=429): ${body.slice(0, 200)}`
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
if (res.status >= 500) {
|
|
603
|
+
return {
|
|
604
|
+
kind: "fallback",
|
|
605
|
+
cause: "server-error",
|
|
606
|
+
reason: `Anthropic server error (status=${res.status}): ${body.slice(0, 200)}`
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
if (res.status === 400 && isInputTooLargeBody2(body)) {
|
|
610
|
+
return {
|
|
611
|
+
kind: "fallback",
|
|
612
|
+
cause: "input-too-large",
|
|
613
|
+
reason: `Input exceeds Haiku context window (status=400 body=${body.slice(0, 200)}). Split the source into smaller segments.`
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
return {
|
|
617
|
+
kind: "fallback",
|
|
618
|
+
cause: "unexpected",
|
|
619
|
+
reason: `Anthropic returned status=${res.status}: ${body.slice(0, 200)}`
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
let payload;
|
|
623
|
+
try {
|
|
624
|
+
payload = await res.json();
|
|
625
|
+
} catch {
|
|
626
|
+
return {
|
|
627
|
+
kind: "fallback",
|
|
628
|
+
cause: "malformed-response",
|
|
629
|
+
reason: "Anthropic returned malformed JSON."
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
if (payload.error) {
|
|
633
|
+
return {
|
|
634
|
+
kind: "fallback",
|
|
635
|
+
cause: "unexpected",
|
|
636
|
+
reason: `Anthropic API error: ${payload.error.type ?? "unknown"} ${payload.error.message ?? ""}`
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
const stopReason = typeof payload.stop_reason === "string" ? payload.stop_reason : void 0;
|
|
640
|
+
const outputTokens = typeof payload.usage?.output_tokens === "number" ? payload.usage.output_tokens : void 0;
|
|
641
|
+
if (toolChoiceName) {
|
|
642
|
+
const toolBlock = payload.content?.find((block) => block.type === "tool_use");
|
|
643
|
+
if (!toolBlock || !toolBlock.input || typeof toolBlock.input !== "object") {
|
|
644
|
+
return {
|
|
645
|
+
kind: "fallback",
|
|
646
|
+
cause: "empty-response",
|
|
647
|
+
reason: "Model returned no tool_use block despite forced tool selection."
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
return {
|
|
651
|
+
kind: "ok-tool",
|
|
652
|
+
toolName: toolBlock.name ?? toolChoiceName,
|
|
653
|
+
input: toolBlock.input,
|
|
654
|
+
stopReason,
|
|
655
|
+
outputTokens
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
const textBlock = payload.content?.find((block) => {
|
|
659
|
+
if (block.type !== "text")
|
|
660
|
+
return false;
|
|
661
|
+
const candidate = block.text;
|
|
662
|
+
return typeof candidate === "string" && candidate.trim().length > 0;
|
|
663
|
+
});
|
|
664
|
+
if (!textBlock) {
|
|
665
|
+
return {
|
|
666
|
+
kind: "fallback",
|
|
667
|
+
cause: "empty-response",
|
|
668
|
+
reason: "Model returned no text content."
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
return { kind: "ok", text: textBlock.text, stopReason, outputTokens };
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
});
|
|
675
|
+
|
|
676
|
+
// ../lib/graph-style/dist/index.js
|
|
677
|
+
var require_dist3 = __commonJS({
|
|
370
678
|
"../lib/graph-style/dist/index.js"(exports) {
|
|
371
679
|
"use strict";
|
|
372
680
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -1874,17 +2182,17 @@ var INBOUND_TTL_MS = 20 * 6e4;
|
|
|
1874
2182
|
var INBOUND_MAX = 5e3;
|
|
1875
2183
|
var agentSentCache = /* @__PURE__ */ new Map();
|
|
1876
2184
|
var inboundCache = /* @__PURE__ */ new Map();
|
|
1877
|
-
function pruneCache(
|
|
2185
|
+
function pruneCache(cache3, ttl, max) {
|
|
1878
2186
|
const now = Date.now();
|
|
1879
|
-
for (const [key, entry] of
|
|
1880
|
-
if (now - entry.ts > ttl)
|
|
2187
|
+
for (const [key, entry] of cache3) {
|
|
2188
|
+
if (now - entry.ts > ttl) cache3.delete(key);
|
|
1881
2189
|
}
|
|
1882
|
-
if (
|
|
1883
|
-
const excess =
|
|
2190
|
+
if (cache3.size > max) {
|
|
2191
|
+
const excess = cache3.size - max;
|
|
1884
2192
|
let count = 0;
|
|
1885
|
-
for (const key of
|
|
2193
|
+
for (const key of cache3.keys()) {
|
|
1886
2194
|
if (count >= excess) break;
|
|
1887
|
-
|
|
2195
|
+
cache3.delete(key);
|
|
1888
2196
|
count++;
|
|
1889
2197
|
}
|
|
1890
2198
|
}
|
|
@@ -6502,16 +6810,11 @@ function readUsersFile() {
|
|
|
6502
6810
|
if (!raw) return [];
|
|
6503
6811
|
return JSON.parse(raw);
|
|
6504
6812
|
}
|
|
6505
|
-
function claudeSpawnPath() {
|
|
6506
|
-
const base = process.env.PATH ?? "/usr/bin:/bin:/usr/sbin:/sbin";
|
|
6507
|
-
return `${base}:/opt/homebrew/bin:/usr/local/bin`;
|
|
6508
|
-
}
|
|
6509
6813
|
function checkAuthStatus() {
|
|
6510
6814
|
try {
|
|
6511
6815
|
execFileSync2("claude", ["auth", "status"], {
|
|
6512
6816
|
encoding: "utf-8",
|
|
6513
|
-
timeout: 5e3
|
|
6514
|
-
env: { ...process.env, PATH: claudeSpawnPath() }
|
|
6817
|
+
timeout: 5e3
|
|
6515
6818
|
});
|
|
6516
6819
|
return true;
|
|
6517
6820
|
} catch {
|
|
@@ -6573,7 +6876,6 @@ app4.post("/claude-auth", async (c) => {
|
|
|
6573
6876
|
if (process.platform === "darwin") {
|
|
6574
6877
|
vncLog("claude-auth", { action: "start", transport: "native", platform: "darwin" });
|
|
6575
6878
|
const claudeProc2 = spawn("claude", ["auth", "login"], {
|
|
6576
|
-
env: { ...process.env, PATH: claudeSpawnPath() },
|
|
6577
6879
|
stdio: ["ignore", "pipe", "pipe"]
|
|
6578
6880
|
});
|
|
6579
6881
|
claudeProc2.unref();
|
|
@@ -9716,10 +10018,251 @@ app18.delete("/", requireAdminSession, async (c) => {
|
|
|
9716
10018
|
var files_default = app18;
|
|
9717
10019
|
|
|
9718
10020
|
// ../lib/graph-search/src/index.ts
|
|
9719
|
-
var
|
|
10021
|
+
var import_dist2 = __toESM(require_dist());
|
|
9720
10022
|
import { int } from "neo4j-driver";
|
|
10023
|
+
|
|
10024
|
+
// ../lib/graph-search/src/rrf-fusion.ts
|
|
10025
|
+
function fuseRrf(rankedLists, k = 60) {
|
|
10026
|
+
const scores = /* @__PURE__ */ new Map();
|
|
10027
|
+
const representatives = /* @__PURE__ */ new Map();
|
|
10028
|
+
const firstSeen = /* @__PURE__ */ new Map();
|
|
10029
|
+
let order = 0;
|
|
10030
|
+
for (const list of rankedLists) {
|
|
10031
|
+
for (let rank = 0; rank < list.length; rank++) {
|
|
10032
|
+
const candidate = list[rank];
|
|
10033
|
+
const contribution = 1 / (k + rank);
|
|
10034
|
+
const prior = scores.get(candidate.nodeId) ?? 0;
|
|
10035
|
+
scores.set(candidate.nodeId, prior + contribution);
|
|
10036
|
+
if (!representatives.has(candidate.nodeId)) {
|
|
10037
|
+
representatives.set(candidate.nodeId, candidate);
|
|
10038
|
+
firstSeen.set(candidate.nodeId, order++);
|
|
10039
|
+
}
|
|
10040
|
+
}
|
|
10041
|
+
}
|
|
10042
|
+
const out = [];
|
|
10043
|
+
for (const [nodeId, rrfScore] of scores) {
|
|
10044
|
+
const rep = representatives.get(nodeId);
|
|
10045
|
+
out.push({ ...rep, rrfScore });
|
|
10046
|
+
}
|
|
10047
|
+
out.sort((a, b) => {
|
|
10048
|
+
if (b.rrfScore !== a.rrfScore) return b.rrfScore - a.rrfScore;
|
|
10049
|
+
return firstSeen.get(a.nodeId) - firstSeen.get(b.nodeId);
|
|
10050
|
+
});
|
|
10051
|
+
return out;
|
|
10052
|
+
}
|
|
10053
|
+
|
|
10054
|
+
// ../lib/graph-search/src/query-expansion.ts
|
|
10055
|
+
var import_dist = __toESM(require_dist2());
|
|
10056
|
+
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
10057
|
+
var HAIKU_MODEL2 = "claude-haiku-4-5";
|
|
10058
|
+
var MAX_PARAPHRASES = 5;
|
|
10059
|
+
var cache2 = /* @__PURE__ */ new Map();
|
|
10060
|
+
async function expandQuery(params) {
|
|
10061
|
+
const { query, retrievalClass = "general", accountId = "", useCache = true } = params;
|
|
10062
|
+
const normalised = query.trim().toLowerCase();
|
|
10063
|
+
const cacheKey = `${accountId}::${retrievalClass}::${normalised}`;
|
|
10064
|
+
if (useCache) {
|
|
10065
|
+
const hit = cache2.get(cacheKey);
|
|
10066
|
+
if (hit && hit.expiresAt > Date.now()) {
|
|
10067
|
+
return [query, ...hit.expansions];
|
|
10068
|
+
}
|
|
10069
|
+
}
|
|
10070
|
+
const systemPrompt = [
|
|
10071
|
+
"You generate paraphrases of a user query for hybrid graph search.",
|
|
10072
|
+
"Return 3-5 alternative phrasings that preserve the user's intent but vary the surface form (synonyms, word order, entity-vs-attribute framing).",
|
|
10073
|
+
"Do not change the entity names. Do not invent constraints the user did not state.",
|
|
10074
|
+
"Output ONLY a JSON object via the provided tool; never free text."
|
|
10075
|
+
].join("\n");
|
|
10076
|
+
const classHint = retrievalClass === "general" ? "" : `The retrieval class is '${retrievalClass}' \u2014 tailor paraphrases accordingly.`;
|
|
10077
|
+
const userMessage = [
|
|
10078
|
+
`Original query: ${query}`,
|
|
10079
|
+
classHint
|
|
10080
|
+
].filter((s) => s.length > 0).join("\n");
|
|
10081
|
+
const result = await (0, import_dist.callOauthLlm)({
|
|
10082
|
+
model: HAIKU_MODEL2,
|
|
10083
|
+
system: systemPrompt,
|
|
10084
|
+
userMessage,
|
|
10085
|
+
maxTokens: 512,
|
|
10086
|
+
timeoutMs: 15e3,
|
|
10087
|
+
tools: [
|
|
10088
|
+
{
|
|
10089
|
+
name: "emit_paraphrases",
|
|
10090
|
+
description: "Emit 3-5 paraphrases of the user query.",
|
|
10091
|
+
input_schema: {
|
|
10092
|
+
type: "object",
|
|
10093
|
+
properties: {
|
|
10094
|
+
paraphrases: {
|
|
10095
|
+
type: "array",
|
|
10096
|
+
items: { type: "string" },
|
|
10097
|
+
minItems: 3,
|
|
10098
|
+
maxItems: MAX_PARAPHRASES
|
|
10099
|
+
}
|
|
10100
|
+
},
|
|
10101
|
+
required: ["paraphrases"]
|
|
10102
|
+
}
|
|
10103
|
+
}
|
|
10104
|
+
],
|
|
10105
|
+
toolChoiceName: "emit_paraphrases"
|
|
10106
|
+
});
|
|
10107
|
+
if (result.kind !== "ok-tool") {
|
|
10108
|
+
process.stderr.write(
|
|
10109
|
+
`[graph-search:expansion-failed] cause=${result.kind === "fallback" ? result.cause : "unexpected"} query=${query.slice(0, 60).replace(/\s+/g, " ")}
|
|
10110
|
+
`
|
|
10111
|
+
);
|
|
10112
|
+
return [query];
|
|
10113
|
+
}
|
|
10114
|
+
const raw = result.input.paraphrases;
|
|
10115
|
+
if (!Array.isArray(raw)) return [query];
|
|
10116
|
+
const expansions = raw.filter((p) => typeof p === "string" && p.trim().length > 0).map((p) => p.trim()).slice(0, MAX_PARAPHRASES);
|
|
10117
|
+
if (useCache) {
|
|
10118
|
+
cache2.set(cacheKey, { expansions, expiresAt: Date.now() + CACHE_TTL_MS });
|
|
10119
|
+
}
|
|
10120
|
+
return [query, ...expansions];
|
|
10121
|
+
}
|
|
10122
|
+
|
|
10123
|
+
// ../lib/graph-search/src/boosts.ts
|
|
10124
|
+
function applyCompiledTruthBoost(hits, weight = 0.15) {
|
|
10125
|
+
if (weight < 0 || weight > 1) {
|
|
10126
|
+
throw new Error(`applyCompiledTruthBoost: weight must be in [0,1], got ${weight}`);
|
|
10127
|
+
}
|
|
10128
|
+
return hits.map((hit) => {
|
|
10129
|
+
const compiled = hit.properties["compiledTruth"];
|
|
10130
|
+
if (compiled === null || compiled === void 0 || compiled === "") return hit;
|
|
10131
|
+
return { ...hit, score: hit.score * (1 + weight) };
|
|
10132
|
+
});
|
|
10133
|
+
}
|
|
10134
|
+
function applyBacklinkBoost(hits) {
|
|
10135
|
+
return hits.map((hit) => {
|
|
10136
|
+
const raw = hit.properties["backlinkCount"];
|
|
10137
|
+
const count = typeof raw === "number" ? raw : Number(raw);
|
|
10138
|
+
if (!Number.isFinite(count) || count <= 0) return hit;
|
|
10139
|
+
const bump = Math.max(0.05, Math.min(0.25, 0.05 + 0.05 * Math.log10(count)));
|
|
10140
|
+
return { ...hit, score: hit.score * (1 + bump) };
|
|
10141
|
+
});
|
|
10142
|
+
}
|
|
10143
|
+
|
|
10144
|
+
// ../lib/graph-search/src/dedup.ts
|
|
10145
|
+
import { createHash as createHash3 } from "crypto";
|
|
10146
|
+
var DEFAULT_LAYERS = [
|
|
10147
|
+
"nodeId",
|
|
10148
|
+
"slug",
|
|
10149
|
+
"canonicalName",
|
|
10150
|
+
"contentHash"
|
|
10151
|
+
];
|
|
10152
|
+
function readSlug(props) {
|
|
10153
|
+
const slug = props["slug"];
|
|
10154
|
+
return typeof slug === "string" && slug.length > 0 ? slug : null;
|
|
10155
|
+
}
|
|
10156
|
+
function readCanonicalName(props) {
|
|
10157
|
+
const canonical = props["canonicalName"];
|
|
10158
|
+
if (typeof canonical === "string" && canonical.length > 0) {
|
|
10159
|
+
return canonical.toLowerCase();
|
|
10160
|
+
}
|
|
10161
|
+
const name = props["name"];
|
|
10162
|
+
if (typeof name === "string" && name.length > 0) {
|
|
10163
|
+
return name.toLowerCase();
|
|
10164
|
+
}
|
|
10165
|
+
return null;
|
|
10166
|
+
}
|
|
10167
|
+
function readContentHash(props) {
|
|
10168
|
+
const compiled = props["compiledTruth"];
|
|
10169
|
+
const content = props["content"];
|
|
10170
|
+
const source = typeof compiled === "string" && compiled.length > 0 ? compiled : typeof content === "string" && content.length > 0 ? content : null;
|
|
10171
|
+
if (source === null) return null;
|
|
10172
|
+
return createHash3("sha256").update(source).digest("hex").slice(0, 16);
|
|
10173
|
+
}
|
|
10174
|
+
function dedup(hits, layers = DEFAULT_LAYERS) {
|
|
10175
|
+
const sorted = [...hits].sort((a, b) => b.score - a.score);
|
|
10176
|
+
const seen = /* @__PURE__ */ new Map();
|
|
10177
|
+
for (const layer of layers) seen.set(layer, /* @__PURE__ */ new Set());
|
|
10178
|
+
const out = [];
|
|
10179
|
+
for (const hit of sorted) {
|
|
10180
|
+
let collision = false;
|
|
10181
|
+
const keys = [];
|
|
10182
|
+
for (const layer of layers) {
|
|
10183
|
+
let key;
|
|
10184
|
+
switch (layer) {
|
|
10185
|
+
case "nodeId":
|
|
10186
|
+
key = hit.nodeId;
|
|
10187
|
+
break;
|
|
10188
|
+
case "slug":
|
|
10189
|
+
key = readSlug(hit.properties);
|
|
10190
|
+
break;
|
|
10191
|
+
case "canonicalName":
|
|
10192
|
+
key = readCanonicalName(hit.properties);
|
|
10193
|
+
break;
|
|
10194
|
+
case "contentHash":
|
|
10195
|
+
key = readContentHash(hit.properties);
|
|
10196
|
+
break;
|
|
10197
|
+
}
|
|
10198
|
+
if (key === null) continue;
|
|
10199
|
+
if (seen.get(layer).has(key)) {
|
|
10200
|
+
collision = true;
|
|
10201
|
+
break;
|
|
10202
|
+
}
|
|
10203
|
+
keys.push([layer, key]);
|
|
10204
|
+
}
|
|
10205
|
+
if (collision) continue;
|
|
10206
|
+
for (const [layer, key] of keys) seen.get(layer).add(key);
|
|
10207
|
+
out.push(hit);
|
|
10208
|
+
}
|
|
10209
|
+
return out;
|
|
10210
|
+
}
|
|
10211
|
+
|
|
10212
|
+
// ../lib/graph-search/src/route.ts
|
|
10213
|
+
function pickIndexMix(retrievalClass) {
|
|
10214
|
+
switch (retrievalClass) {
|
|
10215
|
+
case "entity":
|
|
10216
|
+
return {
|
|
10217
|
+
skip: false,
|
|
10218
|
+
labelFilter: ["Person", "Company", "Concept"],
|
|
10219
|
+
vectorWeight: 0.85,
|
|
10220
|
+
bm25Weight: 0.15
|
|
10221
|
+
};
|
|
10222
|
+
case "temporal":
|
|
10223
|
+
return {
|
|
10224
|
+
skip: false,
|
|
10225
|
+
labelFilter: ["Event"],
|
|
10226
|
+
vectorWeight: 0.2,
|
|
10227
|
+
bm25Weight: 0.8
|
|
10228
|
+
};
|
|
10229
|
+
case "event":
|
|
10230
|
+
return {
|
|
10231
|
+
skip: false,
|
|
10232
|
+
labelFilter: ["Event"],
|
|
10233
|
+
vectorWeight: 0,
|
|
10234
|
+
bm25Weight: 1
|
|
10235
|
+
};
|
|
10236
|
+
case "none":
|
|
10237
|
+
return { skip: true, vectorWeight: 0, bm25Weight: 0 };
|
|
10238
|
+
case "general":
|
|
10239
|
+
default:
|
|
10240
|
+
if (retrievalClass && retrievalClass !== "general") {
|
|
10241
|
+
process.stderr.write(
|
|
10242
|
+
`[graph-search:unknown-class] rc=${retrievalClass} fallback=general
|
|
10243
|
+
`
|
|
10244
|
+
);
|
|
10245
|
+
}
|
|
10246
|
+
return { skip: false, vectorWeight: 0.7, bm25Weight: 0.3 };
|
|
10247
|
+
}
|
|
10248
|
+
}
|
|
10249
|
+
|
|
10250
|
+
// ../lib/graph-search/src/index.ts
|
|
9721
10251
|
var VECTOR_WEIGHT = 0.7;
|
|
9722
10252
|
var BM25_WEIGHT = 0.3;
|
|
10253
|
+
function envFlag(name) {
|
|
10254
|
+
const v = process.env[name];
|
|
10255
|
+
return v === "1" || v === "true" || v === "yes";
|
|
10256
|
+
}
|
|
10257
|
+
function readFlags() {
|
|
10258
|
+
return {
|
|
10259
|
+
rrf: envFlag("MAXY_GS_RRF"),
|
|
10260
|
+
expansion: envFlag("MAXY_GS_EXPANSION"),
|
|
10261
|
+
boosts: envFlag("MAXY_GS_BOOSTS"),
|
|
10262
|
+
dedup: envFlag("MAXY_GS_DEDUP"),
|
|
10263
|
+
route: envFlag("MAXY_GS_ROUTE")
|
|
10264
|
+
};
|
|
10265
|
+
}
|
|
9723
10266
|
var FULLTEXT_INDEX_NAME = "entity_search";
|
|
9724
10267
|
function escapeLucene(query) {
|
|
9725
10268
|
return query.replace(/[+\-&|!(){}[\]^"~*?:\\/]/g, "\\$&");
|
|
@@ -9771,7 +10314,7 @@ async function bm25Only(session, params) {
|
|
|
9771
10314
|
${scopeClause}
|
|
9772
10315
|
${agentClause}
|
|
9773
10316
|
${labelClause}
|
|
9774
|
-
AND ${(0,
|
|
10317
|
+
AND ${(0, import_dist2.notTrashed)("node")}
|
|
9775
10318
|
${kwClause}
|
|
9776
10319
|
RETURN node, score, labels(node) AS nodeLabels, elementId(node) AS nodeId
|
|
9777
10320
|
ORDER BY score DESC
|
|
@@ -9818,17 +10361,49 @@ async function hybrid(session, embed2, params) {
|
|
|
9818
10361
|
agentSlug,
|
|
9819
10362
|
keywordSubscriptions,
|
|
9820
10363
|
expandHops = 1,
|
|
9821
|
-
degradeOnEmbedFailure = false
|
|
10364
|
+
degradeOnEmbedFailure = false,
|
|
10365
|
+
retrievalClass,
|
|
10366
|
+
dedupLayers = DEFAULT_LAYERS,
|
|
10367
|
+
rrfK = 60
|
|
9822
10368
|
} = params;
|
|
10369
|
+
const envFlags = readFlags();
|
|
10370
|
+
const useRoute = params.enableRoute ?? envFlags.route;
|
|
10371
|
+
const useRrf = params.enableRrf ?? envFlags.rrf;
|
|
10372
|
+
const useExpansion = params.enableExpansion ?? envFlags.expansion;
|
|
10373
|
+
const useBoosts = params.enableBoosts ?? envFlags.boosts;
|
|
10374
|
+
const useDedup = params.enableDedup ?? envFlags.dedup;
|
|
10375
|
+
const plan = useRoute ? pickIndexMix(retrievalClass) : { skip: false, vectorWeight: VECTOR_WEIGHT, bm25Weight: BM25_WEIGHT, labelFilter: void 0 };
|
|
10376
|
+
const emptyStageCounts = {
|
|
10377
|
+
expansions: 1,
|
|
10378
|
+
vector: 0,
|
|
10379
|
+
bm25: 0,
|
|
10380
|
+
fused: 0,
|
|
10381
|
+
boosted: 0,
|
|
10382
|
+
deduped: 0,
|
|
10383
|
+
final: 0
|
|
10384
|
+
};
|
|
10385
|
+
if (plan.skip) {
|
|
10386
|
+
return {
|
|
10387
|
+
mode: useRrf ? "rrf" : "hybrid",
|
|
10388
|
+
results: [],
|
|
10389
|
+
expandMs: 0,
|
|
10390
|
+
rawMerged: 0,
|
|
10391
|
+
suppressed: 0,
|
|
10392
|
+
bm25Bypass: 0,
|
|
10393
|
+
threshold: params.vectorThreshold ?? null,
|
|
10394
|
+
stageCounts: emptyStageCounts
|
|
10395
|
+
};
|
|
10396
|
+
}
|
|
10397
|
+
const effectiveLabels = labels && labels.length > 0 ? labels : plan.labelFilter;
|
|
9823
10398
|
let queryEmbedding;
|
|
9824
10399
|
try {
|
|
9825
10400
|
queryEmbedding = await embed2(query);
|
|
9826
10401
|
} catch (err) {
|
|
9827
10402
|
if (!degradeOnEmbedFailure) throw err;
|
|
9828
10403
|
const msg = err instanceof Error ? err.message : String(err);
|
|
9829
|
-
const
|
|
9830
|
-
const normalised = normaliseBm25Scores(
|
|
9831
|
-
const results2 =
|
|
10404
|
+
const bm25Hits = await bm25Only(session, { ...params, labels: effectiveLabels });
|
|
10405
|
+
const normalised = normaliseBm25Scores(bm25Hits.map((h) => h.score));
|
|
10406
|
+
const results2 = bm25Hits.map((h, i) => ({
|
|
9832
10407
|
...h,
|
|
9833
10408
|
vectorScore: 0,
|
|
9834
10409
|
bm25Score: normalised[i] ?? 0,
|
|
@@ -9842,26 +10417,32 @@ async function hybrid(session, embed2, params) {
|
|
|
9842
10417
|
rawMerged: results2.length,
|
|
9843
10418
|
suppressed: 0,
|
|
9844
10419
|
bm25Bypass: 0,
|
|
9845
|
-
threshold: null
|
|
10420
|
+
threshold: null,
|
|
10421
|
+
stageCounts: {
|
|
10422
|
+
expansions: 1,
|
|
10423
|
+
vector: 0,
|
|
10424
|
+
bm25: results2.length,
|
|
10425
|
+
fused: results2.length,
|
|
10426
|
+
boosted: results2.length,
|
|
10427
|
+
deduped: results2.length,
|
|
10428
|
+
final: results2.length
|
|
10429
|
+
}
|
|
9846
10430
|
};
|
|
9847
10431
|
}
|
|
9848
10432
|
const labelToIndex = await discoverIndexes(session);
|
|
9849
|
-
const keywordFilter = buildKeywordFilter(keywords, keywordMatch);
|
|
9850
|
-
const keywordClause = keywordFilter?.clause ?? "";
|
|
9851
|
-
const keywordParams = keywordFilter?.params ?? {};
|
|
9852
|
-
const scoreMap = /* @__PURE__ */ new Map();
|
|
9853
10433
|
let indexesToQuery;
|
|
9854
|
-
if (
|
|
9855
|
-
indexesToQuery =
|
|
10434
|
+
if (effectiveLabels && effectiveLabels.length > 0) {
|
|
10435
|
+
indexesToQuery = effectiveLabels.map((l) => labelToIndex.get(l)).filter((idx) => idx !== void 0);
|
|
9856
10436
|
if (indexesToQuery.length === 0) {
|
|
9857
10437
|
return {
|
|
9858
|
-
mode: "hybrid",
|
|
10438
|
+
mode: useRrf ? "rrf" : "hybrid",
|
|
9859
10439
|
results: [],
|
|
9860
10440
|
expandMs: 0,
|
|
9861
10441
|
rawMerged: 0,
|
|
9862
10442
|
suppressed: 0,
|
|
9863
10443
|
bm25Bypass: 0,
|
|
9864
|
-
threshold: params.vectorThreshold ?? null
|
|
10444
|
+
threshold: params.vectorThreshold ?? null,
|
|
10445
|
+
stageCounts: emptyStageCounts
|
|
9865
10446
|
};
|
|
9866
10447
|
}
|
|
9867
10448
|
} else {
|
|
@@ -9871,56 +10452,162 @@ async function hybrid(session, embed2, params) {
|
|
|
9871
10452
|
const scopeParams = allowedScopes ? { allowedScopes } : {};
|
|
9872
10453
|
const agentClause = agentSlug ? "AND node.agents IS NOT NULL AND $agentSlug IN node.agents" : "";
|
|
9873
10454
|
const agentParams = agentSlug ? { agentSlug } : {};
|
|
9874
|
-
|
|
9875
|
-
|
|
9876
|
-
|
|
9877
|
-
|
|
10455
|
+
const keywordFilter = buildKeywordFilter(keywords, keywordMatch);
|
|
10456
|
+
const keywordClause = keywordFilter?.clause ?? "";
|
|
10457
|
+
const keywordParams = keywordFilter?.params ?? {};
|
|
10458
|
+
const expansions = useExpansion ? await expandQuery({ query, retrievalClass, accountId }) : [query];
|
|
10459
|
+
const passes = await Promise.all(
|
|
10460
|
+
expansions.map(async (qText, idx) => {
|
|
10461
|
+
let pEmbed;
|
|
10462
|
+
if (idx === 0) {
|
|
10463
|
+
pEmbed = queryEmbedding;
|
|
10464
|
+
} else {
|
|
10465
|
+
try {
|
|
10466
|
+
pEmbed = await embed2(qText);
|
|
10467
|
+
} catch {
|
|
10468
|
+
pEmbed = null;
|
|
10469
|
+
}
|
|
10470
|
+
}
|
|
10471
|
+
const vectorRanked = [];
|
|
10472
|
+
const vectorSeen = /* @__PURE__ */ new Map();
|
|
10473
|
+
if (pEmbed) {
|
|
10474
|
+
for (const indexName of indexesToQuery) {
|
|
10475
|
+
const vectorResult = await session.run(
|
|
10476
|
+
`CALL db.index.vector.queryNodes($indexName, $limit, $embedding)
|
|
10477
|
+
YIELD node, score
|
|
10478
|
+
WHERE node.accountId = $accountId
|
|
10479
|
+
${scopeClause}
|
|
10480
|
+
${agentClause}
|
|
10481
|
+
AND ${(0, import_dist2.notTrashed)("node")}
|
|
10482
|
+
${keywordClause}
|
|
10483
|
+
RETURN node, score, labels(node) AS nodeLabels, elementId(node) AS nodeId
|
|
10484
|
+
ORDER BY score DESC
|
|
10485
|
+
LIMIT $limit`,
|
|
10486
|
+
{
|
|
10487
|
+
indexName,
|
|
10488
|
+
embedding: pEmbed,
|
|
10489
|
+
limit: int(limit),
|
|
10490
|
+
accountId,
|
|
10491
|
+
...scopeParams,
|
|
10492
|
+
...agentParams,
|
|
10493
|
+
...keywordParams
|
|
10494
|
+
}
|
|
10495
|
+
);
|
|
10496
|
+
for (const record of vectorResult.records) {
|
|
10497
|
+
const nodeId = record.get("nodeId");
|
|
10498
|
+
const scoreRaw = record.get("score");
|
|
10499
|
+
const score = typeof scoreRaw === "number" ? scoreRaw : Number(scoreRaw);
|
|
10500
|
+
const existingIdx = vectorSeen.get(nodeId);
|
|
10501
|
+
if (existingIdx !== void 0) {
|
|
10502
|
+
const existing = vectorRanked[existingIdx];
|
|
10503
|
+
if (score > existing.vectorScore) existing.vectorScore = score;
|
|
10504
|
+
continue;
|
|
10505
|
+
}
|
|
10506
|
+
const node = record.get("node");
|
|
10507
|
+
vectorSeen.set(nodeId, vectorRanked.length);
|
|
10508
|
+
vectorRanked.push({
|
|
10509
|
+
nodeId,
|
|
10510
|
+
labels: record.get("nodeLabels"),
|
|
10511
|
+
properties: plainProperties(node.properties),
|
|
10512
|
+
vectorScore: score,
|
|
10513
|
+
bm25Score: 0,
|
|
10514
|
+
bm25Hit: false
|
|
10515
|
+
});
|
|
10516
|
+
}
|
|
10517
|
+
}
|
|
10518
|
+
vectorRanked.sort((a, b) => b.vectorScore - a.vectorScore);
|
|
10519
|
+
}
|
|
10520
|
+
const bm25Hits = await bm25Only(session, {
|
|
10521
|
+
...params,
|
|
10522
|
+
query: qText,
|
|
10523
|
+
labels: effectiveLabels
|
|
10524
|
+
});
|
|
10525
|
+
const bm25Norm = normaliseBm25Scores(bm25Hits.map((h) => h.score));
|
|
10526
|
+
const bm25Ranked = bm25Hits.map((h, i) => ({
|
|
10527
|
+
nodeId: h.nodeId,
|
|
10528
|
+
labels: h.labels,
|
|
10529
|
+
properties: h.properties,
|
|
10530
|
+
vectorScore: 0,
|
|
10531
|
+
bm25Score: bm25Norm[i] ?? 0,
|
|
10532
|
+
bm25Hit: true
|
|
10533
|
+
}));
|
|
10534
|
+
return { queryText: qText, embedding: pEmbed, vectorRanked, bm25Ranked };
|
|
10535
|
+
})
|
|
10536
|
+
);
|
|
10537
|
+
const scoreMap = /* @__PURE__ */ new Map();
|
|
10538
|
+
let totalVector = 0;
|
|
10539
|
+
let totalBm25 = 0;
|
|
10540
|
+
for (const pass of passes) {
|
|
10541
|
+
totalVector += pass.vectorRanked.length;
|
|
10542
|
+
totalBm25 += pass.bm25Ranked.length;
|
|
10543
|
+
for (const v of pass.vectorRanked) {
|
|
10544
|
+
const existing = scoreMap.get(v.nodeId);
|
|
10545
|
+
if (existing) {
|
|
10546
|
+
existing.vectorScore = Math.max(existing.vectorScore, v.vectorScore);
|
|
10547
|
+
} else {
|
|
10548
|
+
scoreMap.set(v.nodeId, { ...v });
|
|
10549
|
+
}
|
|
10550
|
+
}
|
|
10551
|
+
for (const b of pass.bm25Ranked) {
|
|
10552
|
+
mergeBm25Hit(scoreMap, {
|
|
10553
|
+
nodeId: b.nodeId,
|
|
10554
|
+
labels: b.labels,
|
|
10555
|
+
properties: b.properties,
|
|
10556
|
+
score: b.bm25Score
|
|
10557
|
+
}, b.bm25Score);
|
|
10558
|
+
}
|
|
10559
|
+
}
|
|
10560
|
+
if (keywordSubscriptions && keywordSubscriptions.length > 0) {
|
|
10561
|
+
for (const kw of keywordSubscriptions) {
|
|
10562
|
+
const kwHits = await bm25Only(session, {
|
|
10563
|
+
query: kw,
|
|
10564
|
+
accountId,
|
|
10565
|
+
limit,
|
|
10566
|
+
allowedScopes
|
|
10567
|
+
});
|
|
10568
|
+
if (kwHits.length === 0) continue;
|
|
10569
|
+
const rawScores = kwHits.map((h) => h.score);
|
|
10570
|
+
const normalised = normaliseBm25Scores(rawScores);
|
|
10571
|
+
for (let i = 0; i < kwHits.length; i++) {
|
|
10572
|
+
mergeBm25Hit(scoreMap, kwHits[i], normalised[i]);
|
|
10573
|
+
}
|
|
10574
|
+
}
|
|
10575
|
+
const propScopeClause = allowedScopes ? "AND (node.scope IS NULL OR node.scope IN $allowedScopes)" : "";
|
|
10576
|
+
const propResult = await session.run(
|
|
10577
|
+
`MATCH (node)
|
|
9878
10578
|
WHERE node.accountId = $accountId
|
|
9879
|
-
${
|
|
9880
|
-
|
|
9881
|
-
AND $
|
|
9882
|
-
${
|
|
9883
|
-
RETURN node,
|
|
9884
|
-
ORDER BY score DESC
|
|
10579
|
+
AND ${(0, import_dist2.notTrashed)("node")}
|
|
10580
|
+
AND node.keywords IS NOT NULL
|
|
10581
|
+
AND ANY(kw IN $kwSubs WHERE ANY(nk IN node.keywords WHERE toLower(nk) = kw))
|
|
10582
|
+
${propScopeClause}
|
|
10583
|
+
RETURN node, labels(node) AS nodeLabels, elementId(node) AS nodeId
|
|
9885
10584
|
LIMIT $limit`,
|
|
9886
10585
|
{
|
|
9887
|
-
indexName,
|
|
9888
|
-
embedding: queryEmbedding,
|
|
9889
|
-
limit: int(limit),
|
|
9890
10586
|
accountId,
|
|
9891
|
-
|
|
9892
|
-
|
|
9893
|
-
...
|
|
10587
|
+
kwSubs: keywordSubscriptions,
|
|
10588
|
+
limit: int(limit),
|
|
10589
|
+
...allowedScopes ? { allowedScopes } : {}
|
|
9894
10590
|
}
|
|
9895
10591
|
);
|
|
9896
|
-
for (const record of
|
|
10592
|
+
for (const record of propResult.records) {
|
|
9897
10593
|
const nodeId = record.get("nodeId");
|
|
9898
|
-
const scoreRaw = record.get("score");
|
|
9899
|
-
const score = typeof scoreRaw === "number" ? scoreRaw : Number(scoreRaw);
|
|
9900
10594
|
const existing = scoreMap.get(nodeId);
|
|
9901
10595
|
if (existing) {
|
|
9902
|
-
existing.
|
|
10596
|
+
existing.bm25Score = Math.max(existing.bm25Score, 1);
|
|
10597
|
+
existing.bm25Hit = true;
|
|
9903
10598
|
} else {
|
|
9904
10599
|
const node = record.get("node");
|
|
9905
10600
|
scoreMap.set(nodeId, {
|
|
9906
10601
|
nodeId,
|
|
9907
10602
|
labels: record.get("nodeLabels"),
|
|
9908
10603
|
properties: plainProperties(node.properties),
|
|
9909
|
-
vectorScore:
|
|
9910
|
-
bm25Score:
|
|
9911
|
-
bm25Hit:
|
|
10604
|
+
vectorScore: 0,
|
|
10605
|
+
bm25Score: 1,
|
|
10606
|
+
bm25Hit: true
|
|
9912
10607
|
});
|
|
9913
10608
|
}
|
|
9914
10609
|
}
|
|
9915
10610
|
}
|
|
9916
|
-
const bm25Hits = await bm25Only(session, params);
|
|
9917
|
-
if (bm25Hits.length > 0) {
|
|
9918
|
-
const rawScores = bm25Hits.map((h) => h.score);
|
|
9919
|
-
const normalised = normaliseBm25Scores(rawScores);
|
|
9920
|
-
for (let i = 0; i < bm25Hits.length; i++) {
|
|
9921
|
-
mergeBm25Hit(scoreMap, bm25Hits[i], normalised[i]);
|
|
9922
|
-
}
|
|
9923
|
-
}
|
|
9924
10611
|
if (keywordSubscriptions && keywordSubscriptions.length > 0) {
|
|
9925
10612
|
for (const kw of keywordSubscriptions) {
|
|
9926
10613
|
const kwHits = await bm25Only(session, {
|
|
@@ -9940,7 +10627,7 @@ async function hybrid(session, embed2, params) {
|
|
|
9940
10627
|
const propResult = await session.run(
|
|
9941
10628
|
`MATCH (node)
|
|
9942
10629
|
WHERE node.accountId = $accountId
|
|
9943
|
-
AND ${(0,
|
|
10630
|
+
AND ${(0, import_dist2.notTrashed)("node")}
|
|
9944
10631
|
AND node.keywords IS NOT NULL
|
|
9945
10632
|
AND ANY(kw IN $kwSubs WHERE ANY(nk IN node.keywords WHERE toLower(nk) = kw))
|
|
9946
10633
|
${propScopeClause}
|
|
@@ -9972,10 +10659,41 @@ async function hybrid(session, embed2, params) {
|
|
|
9972
10659
|
}
|
|
9973
10660
|
}
|
|
9974
10661
|
}
|
|
9975
|
-
|
|
9976
|
-
|
|
9977
|
-
|
|
9978
|
-
|
|
10662
|
+
let allMerged;
|
|
10663
|
+
if (useRrf) {
|
|
10664
|
+
const rankedLists = [];
|
|
10665
|
+
for (const pass of passes) {
|
|
10666
|
+
if (pass.vectorRanked.length > 0) rankedLists.push(pass.vectorRanked);
|
|
10667
|
+
if (pass.bm25Ranked.length > 0) rankedLists.push(pass.bm25Ranked);
|
|
10668
|
+
}
|
|
10669
|
+
const fused = fuseRrf(rankedLists, rrfK);
|
|
10670
|
+
allMerged = fused.map((f) => {
|
|
10671
|
+
const rep = scoreMap.get(f.nodeId) ?? f;
|
|
10672
|
+
return { ...rep, combinedScore: f.rrfScore };
|
|
10673
|
+
});
|
|
10674
|
+
} else {
|
|
10675
|
+
allMerged = [...scoreMap.values()].map((node) => ({
|
|
10676
|
+
...node,
|
|
10677
|
+
combinedScore: plan.vectorWeight * node.vectorScore + plan.bm25Weight * node.bm25Score
|
|
10678
|
+
}));
|
|
10679
|
+
}
|
|
10680
|
+
const fusedCount = allMerged.length;
|
|
10681
|
+
if (useBoosts) {
|
|
10682
|
+
allMerged = applyCompiledTruthBoost(
|
|
10683
|
+
applyBacklinkBoost(allMerged.map((m) => ({
|
|
10684
|
+
...m,
|
|
10685
|
+
score: m.combinedScore
|
|
10686
|
+
})))
|
|
10687
|
+
).map((m) => ({ ...m, combinedScore: m.score }));
|
|
10688
|
+
}
|
|
10689
|
+
const boostedCount = allMerged.length;
|
|
10690
|
+
if (useDedup) {
|
|
10691
|
+
allMerged = dedup(
|
|
10692
|
+
allMerged.map((m) => ({ ...m, score: m.combinedScore })),
|
|
10693
|
+
dedupLayers
|
|
10694
|
+
).map((m) => ({ ...m, combinedScore: m.score }));
|
|
10695
|
+
}
|
|
10696
|
+
const dedupedCount = allMerged.length;
|
|
9979
10697
|
const rawMerged = allMerged.length;
|
|
9980
10698
|
const threshold = params.vectorThreshold;
|
|
9981
10699
|
let kept = allMerged;
|
|
@@ -10016,7 +10734,7 @@ async function hybrid(session, embed2, params) {
|
|
|
10016
10734
|
`UNWIND $nodeIds AS nid
|
|
10017
10735
|
MATCH (n)-[r]-(related)
|
|
10018
10736
|
WHERE elementId(n) = nid
|
|
10019
|
-
AND ${(0,
|
|
10737
|
+
AND ${(0, import_dist2.notTrashed)("related")}
|
|
10020
10738
|
${expandScopeClause}
|
|
10021
10739
|
${expandAgentClause}
|
|
10022
10740
|
WITH nid, n, r, related
|
|
@@ -10049,13 +10767,22 @@ async function hybrid(session, embed2, params) {
|
|
|
10049
10767
|
}
|
|
10050
10768
|
}
|
|
10051
10769
|
return {
|
|
10052
|
-
mode: "hybrid",
|
|
10770
|
+
mode: useRrf ? "rrf" : "hybrid",
|
|
10053
10771
|
results,
|
|
10054
10772
|
expandMs,
|
|
10055
10773
|
rawMerged,
|
|
10056
10774
|
suppressed,
|
|
10057
10775
|
bm25Bypass,
|
|
10058
|
-
threshold: threshold ?? null
|
|
10776
|
+
threshold: threshold ?? null,
|
|
10777
|
+
stageCounts: {
|
|
10778
|
+
expansions: expansions.length,
|
|
10779
|
+
vector: totalVector,
|
|
10780
|
+
bm25: totalBm25,
|
|
10781
|
+
fused: fusedCount,
|
|
10782
|
+
boosted: boostedCount,
|
|
10783
|
+
deduped: dedupedCount,
|
|
10784
|
+
final: results.length
|
|
10785
|
+
}
|
|
10059
10786
|
};
|
|
10060
10787
|
}
|
|
10061
10788
|
function mergeBm25Hit(map, hit, normalisedScore) {
|
|
@@ -10231,8 +10958,8 @@ var graph_search_default = app19;
|
|
|
10231
10958
|
import neo4j from "neo4j-driver";
|
|
10232
10959
|
|
|
10233
10960
|
// app/lib/graph-labels.ts
|
|
10234
|
-
var
|
|
10235
|
-
var
|
|
10961
|
+
var import_dist3 = __toESM(require_dist3(), 1);
|
|
10962
|
+
var import_dist4 = __toESM(require_dist3(), 1);
|
|
10236
10963
|
var HIDDEN_BY_DEFAULT_LABELS = Object.freeze(
|
|
10237
10964
|
/* @__PURE__ */ new Set(["Chunk", "GraphPreference"])
|
|
10238
10965
|
);
|
|
@@ -10288,7 +11015,7 @@ var EXCLUDED_EDGE_TYPES = Object.freeze(
|
|
|
10288
11015
|
])
|
|
10289
11016
|
);
|
|
10290
11017
|
function isKnownLabel(label) {
|
|
10291
|
-
return Object.prototype.hasOwnProperty.call(
|
|
11018
|
+
return Object.prototype.hasOwnProperty.call(import_dist4.GRAPH_LABEL_COLOURS, label);
|
|
10292
11019
|
}
|
|
10293
11020
|
function isHiddenByDefault(label) {
|
|
10294
11021
|
return HIDDEN_BY_DEFAULT_LABELS.has(label);
|
|
@@ -13096,7 +13823,7 @@ function broadcastAdminShutdown(reason) {
|
|
|
13096
13823
|
}
|
|
13097
13824
|
|
|
13098
13825
|
// ../lib/entitlement/src/index.ts
|
|
13099
|
-
import { createPublicKey, createHash as
|
|
13826
|
+
import { createPublicKey, createHash as createHash4, verify as cryptoVerify } from "crypto";
|
|
13100
13827
|
import { existsSync as existsSync23, readFileSync as readFileSync20, statSync as statSync8 } from "fs";
|
|
13101
13828
|
import { resolve as resolve20 } from "path";
|
|
13102
13829
|
|
|
@@ -13167,7 +13894,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
|
|
|
13167
13894
|
reason: "pubkey-missing"
|
|
13168
13895
|
});
|
|
13169
13896
|
}
|
|
13170
|
-
const pubkeyHash =
|
|
13897
|
+
const pubkeyHash = createHash4("sha256").update(pubkeyPem).digest("hex");
|
|
13171
13898
|
if (pubkeyHash !== PUBKEY_SHA256) {
|
|
13172
13899
|
return logResolved(anonymousFallback("pubkey-tamper"), {
|
|
13173
13900
|
reason: "pubkey-tamper"
|