@rubytech/create-realagent 1.0.664 → 1.0.665
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +5 -1
- package/package.json +1 -1
- package/payload/platform/plugins/docs/references/memory-guide.md +1 -1
- package/payload/platform/plugins/docs/references/platform.md +1 -1
- package/payload/platform/plugins/docs/references/troubleshooting.md +24 -6
- package/payload/platform/scripts/vnc.sh +174 -2
- package/payload/server/public/assets/{admin-Bo3NKS_u.js → admin-Brug36E-.js} +5 -5
- package/payload/server/public/assets/{data-DQcIUUZW.js → data-woLf2Tmp.js} +1 -1
- package/payload/server/public/assets/{file-BhFSdU7V.js → file-rN5uuyaV.js} +1 -1
- package/payload/server/public/assets/{graph-DSUSNmfO.js → graph-BYaOEZUg.js} +17 -17
- package/payload/server/public/assets/{house-CA7LcTyb.js → house-DnFgpCt2.js} +1 -1
- package/payload/server/public/assets/jsx-runtime-CSCPZpLN.css +1 -0
- package/payload/server/public/assets/{public-C7sPrAvE.js → public-BRrqpeVH.js} +1 -1
- package/payload/server/public/assets/{share-2-CVCJTVW7.js → share-2-DLjRUEiG.js} +1 -1
- package/payload/server/public/assets/{useVoiceRecorder-DwMKR9su.js → useVoiceRecorder-D_efR3Nx.js} +1 -1
- package/payload/server/public/assets/{x-Dnw-ie9I.js → x-L6KPMfIN.js} +1 -1
- package/payload/server/public/brand/claude.png +0 -0
- package/payload/server/public/data.html +6 -6
- package/payload/server/public/graph.html +6 -6
- package/payload/server/public/index.html +7 -7
- package/payload/server/public/public.html +4 -4
- package/payload/server/server.js +252 -114
- package/payload/platform/plugins/admin/mcp/dist/lib/onboarding.test.d.ts +0 -2
- package/payload/platform/plugins/admin/mcp/dist/lib/onboarding.test.d.ts.map +0 -1
- package/payload/platform/plugins/admin/mcp/dist/lib/onboarding.test.js +0 -224
- package/payload/platform/plugins/admin/mcp/dist/lib/onboarding.test.js.map +0 -1
- package/payload/platform/plugins/documents/mcp/dist/index.d.ts +0 -2
- package/payload/platform/plugins/documents/mcp/dist/index.d.ts.map +0 -1
- package/payload/platform/plugins/documents/mcp/dist/index.js +0 -98
- package/payload/platform/plugins/documents/mcp/dist/index.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/semantic-chunker.test.d.ts +0 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/semantic-chunker.test.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/semantic-chunker.test.js +0 -233
- package/payload/platform/plugins/memory/mcp/dist/lib/semantic-chunker.test.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/scripts/graph-prune.d.ts +0 -18
- package/payload/platform/plugins/memory/mcp/dist/scripts/graph-prune.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/scripts/graph-prune.js +0 -80
- package/payload/platform/plugins/memory/mcp/dist/scripts/graph-prune.js.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-run.d.ts +0 -7
- package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-run.d.ts.map +0 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-run.js +0 -10
- package/payload/platform/plugins/memory/mcp/dist/tools/graph-prune-run.js.map +0 -1
- package/payload/platform/plugins/waitlist/mcp/dist/lib/anthropic.d.ts +0 -23
- package/payload/platform/plugins/waitlist/mcp/dist/lib/anthropic.d.ts.map +0 -1
- package/payload/platform/plugins/waitlist/mcp/dist/lib/anthropic.js +0 -115
- package/payload/platform/plugins/waitlist/mcp/dist/lib/anthropic.js.map +0 -1
- package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-extract.d.ts +0 -12
- package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-extract.d.ts.map +0 -1
- package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-extract.js +0 -197
- package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-extract.js.map +0 -1
- package/payload/server/public/assets/jsx-runtime-CH3XaSdT.css +0 -1
- /package/payload/server/public/assets/{jsx-runtime-BZgdWJ0Y.js → jsx-runtime-XWiDQoTG.js} +0 -0
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cron script: graph-prune
|
|
3
|
-
*
|
|
4
|
-
* Daily Neo4j hygiene runner. Triggered by crontab at the configured local
|
|
5
|
-
* hour (default 03:00). Reads ${configDir}/graph-prune.config.json for the
|
|
6
|
-
* disable switch; reads ${configDir}/graph-prune-denylist.json for the
|
|
7
|
-
* operator-curated bad-string list. All actual rule logic lives in
|
|
8
|
-
* lib/graph-prune.ts so the on-demand graph-prune-run MCP tool exercises the
|
|
9
|
-
* same code path.
|
|
10
|
-
*
|
|
11
|
-
* Exit codes are advisory only — cron does not surface them. The script logs
|
|
12
|
-
* its outcome via [graph:prune:*] lines on stderr; logs-read ${configDir}/logs/graph-prune.log
|
|
13
|
-
* is the canonical reader.
|
|
14
|
-
*
|
|
15
|
-
* PLATFORM_ROOT=... ACCOUNT_ID=... node dist/scripts/graph-prune.js
|
|
16
|
-
*/
|
|
17
|
-
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
18
|
-
import { resolve } from "node:path";
|
|
19
|
-
import { closeDriver, getDriver } from "../lib/neo4j.js";
|
|
20
|
-
import { loadConfig, loadDenylist, resolveConfigDir, runPrune, } from "../lib/graph-prune.js";
|
|
21
|
-
const CONFIG_DIR = resolveConfigDir();
|
|
22
|
-
const LOCK_FILE = resolve(CONFIG_DIR, "graph-prune.lock");
|
|
23
|
-
function acquireLock() {
|
|
24
|
-
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
25
|
-
if (existsSync(LOCK_FILE)) {
|
|
26
|
-
const pid = readFileSync(LOCK_FILE, "utf-8").trim();
|
|
27
|
-
try {
|
|
28
|
-
process.kill(Number(pid), 0);
|
|
29
|
-
return false; // a previous run is still alive
|
|
30
|
-
}
|
|
31
|
-
catch {
|
|
32
|
-
unlinkSync(LOCK_FILE); // stale lock from a crashed run
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
writeFileSync(LOCK_FILE, String(process.pid));
|
|
36
|
-
return true;
|
|
37
|
-
}
|
|
38
|
-
function releaseLock() {
|
|
39
|
-
try {
|
|
40
|
-
if (existsSync(LOCK_FILE)) {
|
|
41
|
-
const pid = readFileSync(LOCK_FILE, "utf-8").trim();
|
|
42
|
-
if (pid === String(process.pid))
|
|
43
|
-
unlinkSync(LOCK_FILE);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
/* best-effort */
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
async function main() {
|
|
51
|
-
const accountId = process.env.ACCOUNT_ID;
|
|
52
|
-
if (!accountId) {
|
|
53
|
-
process.stderr.write("[graph:prune:error] ACCOUNT_ID environment variable is required\n");
|
|
54
|
-
process.exit(1);
|
|
55
|
-
}
|
|
56
|
-
if (!acquireLock()) {
|
|
57
|
-
process.stderr.write("[graph:prune:skip] another run holds the lock — exiting\n");
|
|
58
|
-
process.exit(0);
|
|
59
|
-
}
|
|
60
|
-
try {
|
|
61
|
-
const config = loadConfig(CONFIG_DIR);
|
|
62
|
-
if (!config.enabled) {
|
|
63
|
-
process.stderr.write(`[graph:prune:disabled] account=${accountId} — graph-prune.config.json has enabled=false\n`);
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
const denylist = loadDenylist(CONFIG_DIR);
|
|
67
|
-
const driver = getDriver();
|
|
68
|
-
await runPrune(driver, accountId, config, denylist, { dryRun: false });
|
|
69
|
-
}
|
|
70
|
-
catch (err) {
|
|
71
|
-
process.stderr.write(`[graph:prune:error] ${err instanceof Error ? err.stack ?? err.message : String(err)}\n`);
|
|
72
|
-
process.exit(1);
|
|
73
|
-
}
|
|
74
|
-
finally {
|
|
75
|
-
releaseLock();
|
|
76
|
-
await closeDriver();
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
main();
|
|
80
|
-
//# sourceMappingURL=graph-prune.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"graph-prune.js","sourceRoot":"","sources":["../../src/scripts/graph-prune.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { type PruneSummary } from "../lib/graph-prune.js";
|
|
2
|
-
export interface GraphPruneRunParams {
|
|
3
|
-
accountId: string;
|
|
4
|
-
dryRun?: boolean;
|
|
5
|
-
}
|
|
6
|
-
export declare function graphPruneRun(params: GraphPruneRunParams): Promise<PruneSummary>;
|
|
7
|
-
//# sourceMappingURL=graph-prune-run.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"graph-prune-run.d.ts","sourceRoot":"","sources":["../../src/tools/graph-prune-run.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,YAAY,CAAC,CAMvB"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { getDriver } from "../lib/neo4j.js";
|
|
2
|
-
import { loadConfig, loadDenylist, resolveConfigDir, runPrune, } from "../lib/graph-prune.js";
|
|
3
|
-
export async function graphPruneRun(params) {
|
|
4
|
-
const configDir = resolveConfigDir();
|
|
5
|
-
const config = loadConfig(configDir);
|
|
6
|
-
const denylist = loadDenylist(configDir);
|
|
7
|
-
const driver = getDriver();
|
|
8
|
-
return runPrune(driver, params.accountId, config, denylist, { dryRun: params.dryRun ?? false });
|
|
9
|
-
}
|
|
10
|
-
//# sourceMappingURL=graph-prune-run.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"graph-prune-run.js","sourceRoot":"","sources":["../../src/tools/graph-prune-run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EACL,UAAU,EACV,YAAY,EACZ,gBAAgB,EAChB,QAAQ,GAET,MAAM,uBAAuB,CAAC;AAO/B,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAA2B;IAE3B,MAAM,SAAS,GAAG,gBAAgB,EAAE,CAAC;IACrC,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,OAAO,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC,CAAC;AAClG,CAAC"}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
export declare function resolveApiKey(): Promise<string>;
|
|
2
|
-
export interface DiscoveryNotes {
|
|
3
|
-
businessType: string | null;
|
|
4
|
-
role: string | null;
|
|
5
|
-
needs: string | null;
|
|
6
|
-
challenges: string | null;
|
|
7
|
-
interests: string | null;
|
|
8
|
-
engagementQuality: string | null;
|
|
9
|
-
otherSignals: string | null;
|
|
10
|
-
}
|
|
11
|
-
export interface ExtractionResult {
|
|
12
|
-
email: string;
|
|
13
|
-
givenName: string | null;
|
|
14
|
-
familyName: string | null;
|
|
15
|
-
discoveryNotes: DiscoveryNotes | null;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Send a conversation transcript to Haiku and extract structured lead data.
|
|
19
|
-
* Returns null if no email is found in the conversation.
|
|
20
|
-
* Throws on API or parse errors (caller handles via try/catch).
|
|
21
|
-
*/
|
|
22
|
-
export declare function extractFromConversation(messages: string[], apiKey: string): Promise<ExtractionResult | null>;
|
|
23
|
-
//# sourceMappingURL=anthropic.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/lib/anthropic.ts"],"names":[],"mappings":"AAcA,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,CAiBrD;AAMD,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,cAAc,EAAE,cAAc,GAAG,IAAI,CAAC;CACvC;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAAE,EAClB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAgHlC"}
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { readFile } from "node:fs/promises";
|
|
2
|
-
import { resolve } from "node:path";
|
|
3
|
-
import { homedir } from "node:os";
|
|
4
|
-
const HAIKU_MODEL = "claude-haiku-4-5-20251001";
|
|
5
|
-
const API_URL = "https://api.anthropic.com/v1/messages";
|
|
6
|
-
const API_VERSION = "2023-06-01";
|
|
7
|
-
const REQUEST_TIMEOUT_MS = 15_000;
|
|
8
|
-
// ---------------------------------------------------------------------------
|
|
9
|
-
// API key resolution — reads ~/.maxy/.anthropic-api-key
|
|
10
|
-
// Same pattern as admin MCP (api-key-verify).
|
|
11
|
-
// ---------------------------------------------------------------------------
|
|
12
|
-
export async function resolveApiKey() {
|
|
13
|
-
const keyPath = resolve(homedir(), ".maxy", ".anthropic-api-key");
|
|
14
|
-
let raw;
|
|
15
|
-
try {
|
|
16
|
-
raw = await readFile(keyPath, "utf-8");
|
|
17
|
-
}
|
|
18
|
-
catch {
|
|
19
|
-
throw new Error(`No Anthropic API key file at ${keyPath}. Run the get-api-key skill to set one up.`);
|
|
20
|
-
}
|
|
21
|
-
const key = raw.trim();
|
|
22
|
-
if (!key) {
|
|
23
|
-
throw new Error(`Anthropic API key file at ${keyPath} is empty. Store a valid key with api-key-store.`);
|
|
24
|
-
}
|
|
25
|
-
return key;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Send a conversation transcript to Haiku and extract structured lead data.
|
|
29
|
-
* Returns null if no email is found in the conversation.
|
|
30
|
-
* Throws on API or parse errors (caller handles via try/catch).
|
|
31
|
-
*/
|
|
32
|
-
export async function extractFromConversation(messages, apiKey) {
|
|
33
|
-
const transcript = messages.join("\n");
|
|
34
|
-
const res = await fetch(API_URL, {
|
|
35
|
-
method: "POST",
|
|
36
|
-
headers: {
|
|
37
|
-
"Content-Type": "application/json",
|
|
38
|
-
"x-api-key": apiKey,
|
|
39
|
-
"anthropic-version": API_VERSION,
|
|
40
|
-
},
|
|
41
|
-
body: JSON.stringify({
|
|
42
|
-
model: HAIKU_MODEL,
|
|
43
|
-
max_tokens: 1024,
|
|
44
|
-
system: "You extract contact details and customer discovery intelligence from a visitor's chat messages. " +
|
|
45
|
-
"Return ONLY a JSON object with these fields:\n" +
|
|
46
|
-
'- "email": the visitor\'s email address, or null if none given\n' +
|
|
47
|
-
'- "givenName": the visitor\'s first/given name, or null if unclear\n' +
|
|
48
|
-
'- "familyName": the visitor\'s last/family name, or null if unclear\n' +
|
|
49
|
-
'- "businessType": what kind of business they run or work in (e.g. "estate agency", "accounting firm"), or null\n' +
|
|
50
|
-
'- "role": their role or position (e.g. "owner", "marketing manager"), or null\n' +
|
|
51
|
-
'- "needs": what they need or are looking for, in their own words where possible, or null\n' +
|
|
52
|
-
'- "challenges": pain points or challenges they mentioned, or null\n' +
|
|
53
|
-
'- "interests": specific features, capabilities, or topics they asked about or expressed interest in, or null\n' +
|
|
54
|
-
'- "engagementQuality": one of "high" (asked detailed questions, shared specifics about their situation), "medium" (some back-and-forth, showed genuine interest), or "low" (brief, noncommittal), or null\n' +
|
|
55
|
-
'- "otherSignals": any other noteworthy signal — e.g. timeline urgency, competitor mentions, referral source, or null\n' +
|
|
56
|
-
"Only include fields where the visitor actually revealed information. " +
|
|
57
|
-
"Return valid JSON only. No markdown, no explanation.",
|
|
58
|
-
messages: [
|
|
59
|
-
{
|
|
60
|
-
role: "user",
|
|
61
|
-
content: `Extract the visitor's contact details and discovery intelligence from these chat messages:\n\n${transcript}`,
|
|
62
|
-
},
|
|
63
|
-
],
|
|
64
|
-
}),
|
|
65
|
-
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
66
|
-
});
|
|
67
|
-
if (!res.ok) {
|
|
68
|
-
const body = await res.text().catch(() => "");
|
|
69
|
-
throw new Error(`Anthropic API returned ${res.status}: ${body.slice(0, 200)}`);
|
|
70
|
-
}
|
|
71
|
-
const apiResponse = (await res.json());
|
|
72
|
-
const text = apiResponse.content
|
|
73
|
-
?.filter((b) => b.type === "text")
|
|
74
|
-
.map((b) => b.text ?? "")
|
|
75
|
-
.join("");
|
|
76
|
-
if (!text) {
|
|
77
|
-
throw new Error("Haiku returned empty content");
|
|
78
|
-
}
|
|
79
|
-
// Strip markdown code fences if Haiku wraps the JSON despite instructions
|
|
80
|
-
const cleaned = text
|
|
81
|
-
.replace(/^```json?\s*/i, "")
|
|
82
|
-
.replace(/\s*```\s*$/i, "")
|
|
83
|
-
.trim();
|
|
84
|
-
const parsed = JSON.parse(cleaned);
|
|
85
|
-
if (!parsed.email || typeof parsed.email !== "string")
|
|
86
|
-
return null;
|
|
87
|
-
const email = parsed.email.trim().toLowerCase();
|
|
88
|
-
if (!email.includes("@"))
|
|
89
|
-
return null;
|
|
90
|
-
// Validate the email actually appears in the source messages.
|
|
91
|
-
// Guards against hallucination — if Haiku invents an email not in the
|
|
92
|
-
// conversation, we skip rather than create a spurious Person node.
|
|
93
|
-
const joined = messages.join(" ").toLowerCase();
|
|
94
|
-
if (!joined.includes(email))
|
|
95
|
-
return null;
|
|
96
|
-
const givenName = typeof parsed.givenName === "string"
|
|
97
|
-
? parsed.givenName.trim() || null
|
|
98
|
-
: null;
|
|
99
|
-
const familyName = typeof parsed.familyName === "string"
|
|
100
|
-
? parsed.familyName.trim() || null
|
|
101
|
-
: null;
|
|
102
|
-
const str = (v) => typeof v === "string" && v.trim() ? v.trim() : null;
|
|
103
|
-
const notes = {
|
|
104
|
-
businessType: str(parsed.businessType),
|
|
105
|
-
role: str(parsed.role),
|
|
106
|
-
needs: str(parsed.needs),
|
|
107
|
-
challenges: str(parsed.challenges),
|
|
108
|
-
interests: str(parsed.interests),
|
|
109
|
-
engagementQuality: str(parsed.engagementQuality),
|
|
110
|
-
otherSignals: str(parsed.otherSignals),
|
|
111
|
-
};
|
|
112
|
-
const hasAnyNote = Object.values(notes).some((v) => v !== null);
|
|
113
|
-
return { email, givenName, familyName, discoveryNotes: hasAnyNote ? notes : null };
|
|
114
|
-
}
|
|
115
|
-
//# sourceMappingURL=anthropic.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/lib/anthropic.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export interface WaitlistExtractResult {
|
|
2
|
-
conversations: number;
|
|
3
|
-
messages: number;
|
|
4
|
-
created: number;
|
|
5
|
-
updated: number;
|
|
6
|
-
existing: number;
|
|
7
|
-
flaggedForReview: number;
|
|
8
|
-
withDiscoveryNotes: number;
|
|
9
|
-
errors: number;
|
|
10
|
-
}
|
|
11
|
-
export declare function waitlistExtract(accountId: string): Promise<WaitlistExtractResult>;
|
|
12
|
-
//# sourceMappingURL=waitlist-extract.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"waitlist-extract.d.ts","sourceRoot":"","sources":["../../src/tools/waitlist-extract.ts"],"names":[],"mappings":"AAqMA,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,qBAAqB,CAAC,CA2EhC"}
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import { getSession } from "../lib/neo4j.js";
|
|
2
|
-
import { computeEmbedding, buildPersonEmbeddingText } from "../lib/embedding.js";
|
|
3
|
-
import { resolveApiKey, extractFromConversation, } from "../lib/anthropic.js";
|
|
4
|
-
/**
|
|
5
|
-
* Merge two DiscoveryNotes objects: new non-null values overwrite,
|
|
6
|
-
* null values in the new extraction preserve existing values.
|
|
7
|
-
*/
|
|
8
|
-
function mergeDiscoveryNotes(existing, incoming) {
|
|
9
|
-
return {
|
|
10
|
-
businessType: incoming.businessType ?? existing.businessType,
|
|
11
|
-
role: incoming.role ?? existing.role,
|
|
12
|
-
needs: incoming.needs ?? existing.needs,
|
|
13
|
-
challenges: incoming.challenges ?? existing.challenges,
|
|
14
|
-
interests: incoming.interests ?? existing.interests,
|
|
15
|
-
engagementQuality: incoming.engagementQuality ?? existing.engagementQuality,
|
|
16
|
-
otherSignals: incoming.otherSignals ?? existing.otherSignals,
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
async function createOrUpdatePerson(extraction, accountId, conversationId) {
|
|
20
|
-
const { email, givenName: rawGiven, familyName, discoveryNotes } = extraction;
|
|
21
|
-
const hasName = !!rawGiven;
|
|
22
|
-
const status = hasName ? "waitlist" : "review";
|
|
23
|
-
const givenName = rawGiven ?? "Unknown";
|
|
24
|
-
const session = getSession();
|
|
25
|
-
try {
|
|
26
|
-
const createdOn = new Date().toISOString();
|
|
27
|
-
const notesJson = discoveryNotes ? JSON.stringify(discoveryNotes) : null;
|
|
28
|
-
const setProps = [
|
|
29
|
-
"p.givenName = $givenName",
|
|
30
|
-
...(familyName ? ["p.familyName = $familyName"] : []),
|
|
31
|
-
"p.source = 'waitlist'",
|
|
32
|
-
"p.status = $status",
|
|
33
|
-
"p.createdOn = $createdOn",
|
|
34
|
-
"p.sessionId = $conversationId",
|
|
35
|
-
...(notesJson ? ["p.discoveryNotes = $notesJson"] : []),
|
|
36
|
-
].join(",\n ");
|
|
37
|
-
// ON MATCH SET: update name and status only when:
|
|
38
|
-
// - the existing node has no real name (givenName is "Unknown" or missing)
|
|
39
|
-
// - the new extraction provides a real name
|
|
40
|
-
// This preserves admin-reviewed names while backfilling from Haiku.
|
|
41
|
-
const matchProps = hasName
|
|
42
|
-
? [
|
|
43
|
-
"p.givenName = CASE WHEN p.givenName = 'Unknown' OR p.givenName IS NULL THEN $givenName ELSE p.givenName END",
|
|
44
|
-
...(familyName
|
|
45
|
-
? [
|
|
46
|
-
"p.familyName = CASE WHEN p.givenName = 'Unknown' OR p.givenName IS NULL THEN $familyName ELSE COALESCE(p.familyName, $familyName) END",
|
|
47
|
-
]
|
|
48
|
-
: []),
|
|
49
|
-
"p.status = CASE WHEN p.givenName = 'Unknown' OR p.givenName IS NULL THEN $status ELSE p.status END",
|
|
50
|
-
].join(",\n ")
|
|
51
|
-
: "";
|
|
52
|
-
const onMatchClause = matchProps
|
|
53
|
-
? `ON MATCH SET ${matchProps}`
|
|
54
|
-
: "";
|
|
55
|
-
const result = await session.run(`MERGE (p:Person {email: $email, accountId: $accountId})
|
|
56
|
-
ON CREATE SET ${setProps}
|
|
57
|
-
${onMatchClause}
|
|
58
|
-
RETURN p.createdOn = $createdOn AS created,
|
|
59
|
-
p.givenName AS currentName,
|
|
60
|
-
p.discoveryNotes AS existingNotes`, {
|
|
61
|
-
email,
|
|
62
|
-
accountId,
|
|
63
|
-
givenName,
|
|
64
|
-
...(familyName ? { familyName } : {}),
|
|
65
|
-
status,
|
|
66
|
-
createdOn,
|
|
67
|
-
conversationId,
|
|
68
|
-
...(notesJson ? { notesJson } : {}),
|
|
69
|
-
});
|
|
70
|
-
const record = result.records[0];
|
|
71
|
-
if (!record)
|
|
72
|
-
throw new Error(`MERGE returned no record for ${email}`);
|
|
73
|
-
const created = record.get("created");
|
|
74
|
-
const currentName = record.get("currentName");
|
|
75
|
-
const existingNotesRaw = record.get("existingNotes");
|
|
76
|
-
const updated = !created && currentName === givenName && givenName !== "Unknown";
|
|
77
|
-
// On MATCH: merge discoveryNotes (new non-null fields enrich existing)
|
|
78
|
-
let finalNotes = discoveryNotes;
|
|
79
|
-
if (!created && discoveryNotes) {
|
|
80
|
-
let existingNotes = null;
|
|
81
|
-
if (existingNotesRaw) {
|
|
82
|
-
try {
|
|
83
|
-
existingNotes = JSON.parse(existingNotesRaw);
|
|
84
|
-
}
|
|
85
|
-
catch {
|
|
86
|
-
// Malformed existing notes — overwrite with fresh extraction
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
finalNotes = existingNotes
|
|
90
|
-
? mergeDiscoveryNotes(existingNotes, discoveryNotes)
|
|
91
|
-
: discoveryNotes;
|
|
92
|
-
const mergedJson = JSON.stringify(finalNotes);
|
|
93
|
-
await session.run(`MATCH (p:Person {email: $email, accountId: $accountId})
|
|
94
|
-
SET p.discoveryNotes = $mergedJson`, { email, accountId, mergedJson });
|
|
95
|
-
}
|
|
96
|
-
// Recompute embedding with discovery context
|
|
97
|
-
if (created || updated || discoveryNotes) {
|
|
98
|
-
try {
|
|
99
|
-
const finalNotesJson = finalNotes ? JSON.stringify(finalNotes) : null;
|
|
100
|
-
const textForEmbedding = buildPersonEmbeddingText(givenName, familyName ?? null, email, status, finalNotesJson);
|
|
101
|
-
const embedding = await computeEmbedding(textForEmbedding);
|
|
102
|
-
if (embedding.length > 0) {
|
|
103
|
-
await session.run(`MATCH (p:Person {email: $email, accountId: $accountId})
|
|
104
|
-
SET p.embedding = $embedding`, { email, accountId, embedding });
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
catch {
|
|
108
|
-
// Non-fatal — Person stored without embedding
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return { email, givenName, created, updated, status };
|
|
112
|
-
}
|
|
113
|
-
finally {
|
|
114
|
-
await session.close();
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
async function queryPublicConversations(accountId) {
|
|
118
|
-
const session = getSession();
|
|
119
|
-
try {
|
|
120
|
-
const result = await session.run(`MATCH (c:Conversation {agentType: 'public', accountId: $accountId})
|
|
121
|
-
<-[:PART_OF]-(m:Message {role: 'user'})
|
|
122
|
-
WITH c, m ORDER BY m.createdAt ASC
|
|
123
|
-
RETURN c.conversationId AS conversationId,
|
|
124
|
-
collect(m.content) AS messages,
|
|
125
|
-
c.createdAt AS createdAt
|
|
126
|
-
ORDER BY createdAt ASC`, { accountId });
|
|
127
|
-
return result.records.map((r) => ({
|
|
128
|
-
conversationId: r.get("conversationId"),
|
|
129
|
-
messages: r.get("messages"),
|
|
130
|
-
}));
|
|
131
|
-
}
|
|
132
|
-
finally {
|
|
133
|
-
await session.close();
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
export async function waitlistExtract(accountId) {
|
|
137
|
-
const apiKey = await resolveApiKey();
|
|
138
|
-
const conversations = await queryPublicConversations(accountId);
|
|
139
|
-
const totalMessages = conversations.reduce((sum, c) => sum + c.messages.length, 0);
|
|
140
|
-
if (conversations.length === 0) {
|
|
141
|
-
return {
|
|
142
|
-
conversations: 0,
|
|
143
|
-
messages: 0,
|
|
144
|
-
created: 0,
|
|
145
|
-
updated: 0,
|
|
146
|
-
existing: 0,
|
|
147
|
-
flaggedForReview: 0,
|
|
148
|
-
withDiscoveryNotes: 0,
|
|
149
|
-
errors: 0,
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
let created = 0;
|
|
153
|
-
let updated = 0;
|
|
154
|
-
let existing = 0;
|
|
155
|
-
let flaggedForReview = 0;
|
|
156
|
-
let withDiscoveryNotes = 0;
|
|
157
|
-
let errors = 0;
|
|
158
|
-
for (const conv of conversations) {
|
|
159
|
-
try {
|
|
160
|
-
const extraction = await extractFromConversation(conv.messages, apiKey);
|
|
161
|
-
if (!extraction)
|
|
162
|
-
continue;
|
|
163
|
-
if (extraction.discoveryNotes)
|
|
164
|
-
withDiscoveryNotes++;
|
|
165
|
-
const result = await createOrUpdatePerson(extraction, accountId, conv.conversationId);
|
|
166
|
-
if (result.created) {
|
|
167
|
-
if (result.status === "review") {
|
|
168
|
-
flaggedForReview++;
|
|
169
|
-
}
|
|
170
|
-
else {
|
|
171
|
-
created++;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
else if (result.updated) {
|
|
175
|
-
updated++;
|
|
176
|
-
}
|
|
177
|
-
else {
|
|
178
|
-
existing++;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
catch (err) {
|
|
182
|
-
console.error(`[waitlist-extract] conv=${conv.conversationId} error=${err instanceof Error ? err.message : String(err)}`);
|
|
183
|
-
errors++;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
return {
|
|
187
|
-
conversations: conversations.length,
|
|
188
|
-
messages: totalMessages,
|
|
189
|
-
created,
|
|
190
|
-
updated,
|
|
191
|
-
existing,
|
|
192
|
-
flaggedForReview,
|
|
193
|
-
withDiscoveryNotes,
|
|
194
|
-
errors,
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
//# sourceMappingURL=waitlist-extract.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"waitlist-extract.js","sourceRoot":"","sources":["../../src/tools/waitlist-extract.ts"],"names":[],"mappings":"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"}
|