@rubytech/create-realagent 1.0.839 → 1.0.840
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/package.json +1 -1
- package/payload/platform/plugins/docs/references/internals.md +1 -1
- package/payload/platform/plugins/docs/references/platform.md +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/uuid.js +7 -7
- package/payload/platform/plugins/memory/mcp/dist/lib/uuid.js.map +1 -1
- package/payload/platform/plugins/whatsapp/PLUGIN.md +1 -1
- package/payload/server/chunk-CJWFM3WX.js +2098 -0
- package/payload/server/chunk-D5U4XQ66.js +656 -0
- package/payload/server/chunk-DJXPAH7T.js +1480 -0
- package/payload/server/chunk-T2MQIKBT.js +10001 -0
- package/payload/server/client-pool-M25CGILI.js +32 -0
- package/payload/server/cloudflare-task-tracker-GQFKLY62.js +20 -0
- package/payload/server/maxy-edge.js +3 -4
- package/payload/server/public/assets/{Checkbox-Bq6ORjz2.js → Checkbox-aCc0UGp3.js} +1 -1
- package/payload/server/public/assets/{admin-CstEkw-G.js → admin-D678VwpH.js} +2 -2
- package/payload/server/public/assets/data-DsItQm8c.js +1 -0
- package/payload/server/public/assets/graph-C-HOmfmU.js +1 -0
- package/payload/server/public/assets/{jsx-runtime-DidQeNoZ.css → jsx-runtime-BKoartnM.css} +1 -1
- package/payload/server/public/assets/{page-CFWoVkgV.js → page-D7LchjvY.js} +1 -1
- package/payload/server/public/assets/{page-Bpi_jPw6.js → page-DTmTvkNo.js} +1 -1
- package/payload/server/public/assets/{public-BWMwq5Jj.js → public-C7mCgRX0.js} +1 -1
- package/payload/server/public/assets/{useAdminFetch-B93ig7ef.js → useAdminFetch-BgDL3JGd.js} +1 -1
- package/payload/server/public/assets/{useVoiceRecorder-Cb0nAtOo.js → useVoiceRecorder-Bx903Mk1.js} +1 -1
- package/payload/server/public/data.html +5 -5
- package/payload/server/public/graph.html +6 -6
- package/payload/server/public/index.html +8 -8
- package/payload/server/public/public.html +5 -5
- package/payload/server/server.js +21 -31
- package/payload/platform/neo4j/migrations/001-backfill-scope.cypher +0 -30
- package/payload/platform/neo4j/migrations/002-project-public-agents.ts +0 -191
- package/payload/platform/neo4j/migrations/003-person-name-eradicate.cypher +0 -24
- package/payload/platform/neo4j/migrations/004-project-admin-agent.ts +0 -348
- package/payload/platform/neo4j/migrations/004-prune-alien-accounts.ts +0 -133
- package/payload/platform/neo4j/migrations/005-removed-review-feature.ts +0 -102
- package/payload/platform/neo4j/migrations/006-prune-bogus-whatsapp-persons.ts +0 -132
- package/payload/platform/neo4j/migrations/007-conversation-archive-source.ts +0 -116
- package/payload/platform/neo4j/migrations/008-adminuser-accountid-backfill.ts +0 -85
- package/payload/platform/neo4j/migrations/009-conversation-archive-title.ts +0 -197
- package/payload/server/public/assets/data-DwZZ7qbH.js +0 -1
- package/payload/server/public/assets/graph-DceEv42K.js +0 -1
- /package/payload/server/public/assets/{jsx-runtime-DH5S-MwB.js → jsx-runtime-WW3O7tSz.js} +0 -0
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Real Agent</title>
|
|
7
7
|
<link rel="icon" href="/favicon.ico">
|
|
8
|
-
<script type="module" crossorigin src="/assets/public-
|
|
8
|
+
<script type="module" crossorigin src="/assets/public-C7mCgRX0.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/chunk-DD-I1_y5.js">
|
|
10
|
-
<link rel="modulepreload" crossorigin href="/assets/jsx-runtime-
|
|
10
|
+
<link rel="modulepreload" crossorigin href="/assets/jsx-runtime-WW3O7tSz.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/preload-helper-qlgyTAkD.js">
|
|
12
|
-
<link rel="modulepreload" crossorigin href="/assets/Checkbox-
|
|
13
|
-
<link rel="modulepreload" crossorigin href="/assets/useVoiceRecorder-
|
|
14
|
-
<link rel="stylesheet" crossorigin href="/assets/jsx-runtime-
|
|
12
|
+
<link rel="modulepreload" crossorigin href="/assets/Checkbox-aCc0UGp3.js">
|
|
13
|
+
<link rel="modulepreload" crossorigin href="/assets/useVoiceRecorder-Bx903Mk1.js">
|
|
14
|
+
<link rel="stylesheet" crossorigin href="/assets/jsx-runtime-BKoartnM.css">
|
|
15
15
|
<link rel="stylesheet" href="/brand-defaults.css">
|
|
16
16
|
</head>
|
|
17
17
|
<body>
|
package/payload/server/server.js
CHANGED
|
@@ -45,14 +45,23 @@ import {
|
|
|
45
45
|
vncLog,
|
|
46
46
|
waitForExit,
|
|
47
47
|
writeChromiumWrapper
|
|
48
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-T2MQIKBT.js";
|
|
49
49
|
import {
|
|
50
|
+
ACCOUNTS_DIR,
|
|
51
|
+
COMMERCIAL_MODE,
|
|
52
|
+
LOG_DIR,
|
|
53
|
+
MAXY_DIR,
|
|
54
|
+
PLATFORM_ROOT,
|
|
55
|
+
TELEGRAM_ADMIN_WEBHOOK_SECRET_FILE,
|
|
56
|
+
TELEGRAM_WEBHOOK_SECRET_FILE,
|
|
57
|
+
USERS_FILE,
|
|
50
58
|
agentLogStream,
|
|
51
59
|
clearSessionHistory,
|
|
52
60
|
completeGrantSetup,
|
|
53
61
|
getAccountIdForSession,
|
|
54
62
|
getAgentNameForSession,
|
|
55
63
|
getConversationIdForSession,
|
|
64
|
+
getDefaultAccountId,
|
|
56
65
|
getGrantForSession,
|
|
57
66
|
getGroupSlugForSession,
|
|
58
67
|
getRoleForSession,
|
|
@@ -60,6 +69,7 @@ import {
|
|
|
60
69
|
getUserIdForSession,
|
|
61
70
|
getUserNameForSession,
|
|
62
71
|
getVisitorIdForSession,
|
|
72
|
+
hasStubAccountDir,
|
|
63
73
|
interruptClient,
|
|
64
74
|
listAdminSessionsInProgress,
|
|
65
75
|
preConversationLogStream,
|
|
@@ -67,30 +77,18 @@ import {
|
|
|
67
77
|
registerGrantSession,
|
|
68
78
|
registerResumedSession,
|
|
69
79
|
registerSession,
|
|
80
|
+
resolveAccount,
|
|
81
|
+
resolveAgentConfig,
|
|
82
|
+
resolveDefaultAgentSlug,
|
|
83
|
+
resolveUserAccounts,
|
|
70
84
|
setAgentSessionId,
|
|
71
85
|
setConversationIdForSession,
|
|
72
86
|
setGroupContextForSession,
|
|
73
87
|
sigtermFlushStreamLogs,
|
|
74
88
|
unregisterSession,
|
|
89
|
+
validateAgentSlug,
|
|
75
90
|
validateSession
|
|
76
|
-
} from "./chunk-
|
|
77
|
-
import {
|
|
78
|
-
ACCOUNTS_DIR,
|
|
79
|
-
COMMERCIAL_MODE,
|
|
80
|
-
LOG_DIR,
|
|
81
|
-
MAXY_DIR,
|
|
82
|
-
PLATFORM_ROOT,
|
|
83
|
-
TELEGRAM_ADMIN_WEBHOOK_SECRET_FILE,
|
|
84
|
-
TELEGRAM_WEBHOOK_SECRET_FILE,
|
|
85
|
-
USERS_FILE,
|
|
86
|
-
getDefaultAccountId,
|
|
87
|
-
hasStubAccountDir,
|
|
88
|
-
resolveAccount,
|
|
89
|
-
resolveAgentConfig,
|
|
90
|
-
resolveDefaultAgentSlug,
|
|
91
|
-
resolveUserAccounts,
|
|
92
|
-
validateAgentSlug
|
|
93
|
-
} from "./chunk-OJZPS4BL.js";
|
|
91
|
+
} from "./chunk-DJXPAH7T.js";
|
|
94
92
|
import {
|
|
95
93
|
CLOUDFLARE_TASK_DIAGNOSTICS,
|
|
96
94
|
appendCloudflareSteps,
|
|
@@ -98,7 +96,7 @@ import {
|
|
|
98
96
|
openCloudflareTask,
|
|
99
97
|
readTunnelState,
|
|
100
98
|
resolveUnitGoneVerdict
|
|
101
|
-
} from "./chunk-
|
|
99
|
+
} from "./chunk-D5U4XQ66.js";
|
|
102
100
|
import {
|
|
103
101
|
GREETING_DIRECTIVE,
|
|
104
102
|
HAIKU_MODEL,
|
|
@@ -125,11 +123,10 @@ import {
|
|
|
125
123
|
projectAgent,
|
|
126
124
|
renameConversation,
|
|
127
125
|
runAdminUserSelfHeal,
|
|
128
|
-
runBootMigrations,
|
|
129
126
|
verifyAndGetConversationUpdatedAt,
|
|
130
127
|
verifyConversationOwnership,
|
|
131
128
|
writeAdminUserAndPerson
|
|
132
|
-
} from "./chunk-
|
|
129
|
+
} from "./chunk-CJWFM3WX.js";
|
|
133
130
|
import {
|
|
134
131
|
__commonJS,
|
|
135
132
|
__toESM
|
|
@@ -7496,7 +7493,7 @@ var app11 = new Hono();
|
|
|
7496
7493
|
app11.post("/cancel", requireAdminSession, async (c) => {
|
|
7497
7494
|
const session_key = c.var.sessionKey;
|
|
7498
7495
|
try {
|
|
7499
|
-
const { interruptClient: interruptClient2 } = await import("./client-pool-
|
|
7496
|
+
const { interruptClient: interruptClient2 } = await import("./client-pool-M25CGILI.js");
|
|
7500
7497
|
await interruptClient2(session_key);
|
|
7501
7498
|
return c.json({ ok: true });
|
|
7502
7499
|
} catch (err) {
|
|
@@ -13050,13 +13047,6 @@ try {
|
|
|
13050
13047
|
console.error(`[session] backfill startup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
13051
13048
|
}
|
|
13052
13049
|
})();
|
|
13053
|
-
(async () => {
|
|
13054
|
-
try {
|
|
13055
|
-
await runBootMigrations();
|
|
13056
|
-
} catch (err) {
|
|
13057
|
-
console.error(`[migration] runBootMigrations rejected: ${err instanceof Error ? err.message : String(err)}`);
|
|
13058
|
-
}
|
|
13059
|
-
})();
|
|
13060
13050
|
(async () => {
|
|
13061
13051
|
try {
|
|
13062
13052
|
if (!existsSync23(USERS_FILE)) return;
|
|
@@ -13093,7 +13083,7 @@ autoDeliverPremiumPlugins(bootEntitlement?.purchasedPlugins ?? void 0);
|
|
|
13093
13083
|
(async () => {
|
|
13094
13084
|
if (!bootAccount) return;
|
|
13095
13085
|
try {
|
|
13096
|
-
const { recoverRunningCloudflareTasks } = await import("./cloudflare-task-tracker-
|
|
13086
|
+
const { recoverRunningCloudflareTasks } = await import("./cloudflare-task-tracker-GQFKLY62.js");
|
|
13097
13087
|
const result = await recoverRunningCloudflareTasks(
|
|
13098
13088
|
bootAccount.accountId,
|
|
13099
13089
|
configDirForWhatsApp,
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
// ============================================================
|
|
2
|
-
// Migration 001: Backfill scope property on all existing nodes
|
|
3
|
-
//
|
|
4
|
-
// Sets scope on every node that participates in memory-search.
|
|
5
|
-
// Product knowledge → 'public', internal data → 'admin'.
|
|
6
|
-
// Safe to re-run: only touches nodes where scope IS NULL.
|
|
7
|
-
//
|
|
8
|
-
// Run via: cypher-shell -u neo4j -p <password> -f 001-backfill-scope.cypher
|
|
9
|
-
// ============================================================
|
|
10
|
-
|
|
11
|
-
// --- Product knowledge (public agent can see) ---
|
|
12
|
-
|
|
13
|
-
MATCH (n:Question) WHERE n.scope IS NULL SET n.scope = 'public';
|
|
14
|
-
MATCH (n:DefinedTerm) WHERE n.scope IS NULL SET n.scope = 'public';
|
|
15
|
-
MATCH (n:Service) WHERE n.scope IS NULL SET n.scope = 'public';
|
|
16
|
-
MATCH (n:Review) WHERE n.scope IS NULL SET n.scope = 'public';
|
|
17
|
-
MATCH (n:PriceSpecification) WHERE n.scope IS NULL SET n.scope = 'public';
|
|
18
|
-
MATCH (n:LocalBusiness) WHERE n.scope IS NULL SET n.scope = 'public';
|
|
19
|
-
MATCH (n:KnowledgeDocument) WHERE n.scope IS NULL SET n.scope = 'public';
|
|
20
|
-
MATCH (n:Section) WHERE n.scope IS NULL SET n.scope = 'public';
|
|
21
|
-
MATCH (n:Chunk) WHERE n.scope IS NULL SET n.scope = 'public';
|
|
22
|
-
MATCH (n:DigitalDocument) WHERE n.scope IS NULL SET n.scope = 'public';
|
|
23
|
-
|
|
24
|
-
// --- Internal data (admin agent only) ---
|
|
25
|
-
|
|
26
|
-
MATCH (n:CreativeWork) WHERE n.scope IS NULL SET n.scope = 'admin';
|
|
27
|
-
MATCH (n:Task) WHERE n.scope IS NULL SET n.scope = 'admin';
|
|
28
|
-
MATCH (n:Person) WHERE n.scope IS NULL SET n.scope = 'admin';
|
|
29
|
-
MATCH (n:Event) WHERE n.scope IS NULL SET n.scope = 'admin';
|
|
30
|
-
MATCH (n:OnboardingState) WHERE n.scope IS NULL SET n.scope = 'admin';
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Migration 002 — Project file-based public agents into the graph (Task 837).
|
|
3
|
-
*
|
|
4
|
-
* Two passes:
|
|
5
|
-
*
|
|
6
|
-
* 1. Walk every account directory under data/accounts/<accountId>/agents/
|
|
7
|
-
* and call projectAgent(accountId, accountDir, slug) for each non-admin
|
|
8
|
-
* agent that has a config.json. The projector is idempotent: re-running
|
|
9
|
-
* this migration produces no duplicate nodes or edges.
|
|
10
|
-
*
|
|
11
|
-
* 2. For every existing public Conversation that carries an agentSlug
|
|
12
|
-
* property, MATCH the corresponding :Agent and MERGE the
|
|
13
|
-
* (:Conversation)-[:HANDLED_BY]->(:Agent) edge. Conversations whose
|
|
14
|
-
* slug doesn't resolve to an Agent (orphan slugs from deleted agents,
|
|
15
|
-
* or DM-channel public flows that haven't been extended to register a
|
|
16
|
-
* slug) are left edge-less; they will gain the edge automatically once
|
|
17
|
-
* the slug is registered or a new agent at that slug is projected.
|
|
18
|
-
*
|
|
19
|
-
* Run via the platform/ui standalone runtime so it picks up the same
|
|
20
|
-
* NEO4J_URI / accounts-directory resolution as the server:
|
|
21
|
-
*
|
|
22
|
-
* cd platform/ui && \
|
|
23
|
-
* NEO4J_URI=bolt://… NEO4J_PASSWORD=… \
|
|
24
|
-
* npx tsx ../neo4j/migrations/002-project-public-agents.ts
|
|
25
|
-
*
|
|
26
|
-
* Output: structured `[agent-graph-backfill]` lines per account + a final
|
|
27
|
-
* totals line. A non-zero exit code on any per-account failure surfaces to
|
|
28
|
-
* the operator; subsequent accounts are still attempted (the migration is
|
|
29
|
-
* isolating by account, not all-or-nothing).
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
import { existsSync, readdirSync } from "node:fs";
|
|
33
|
-
import { resolve } from "node:path";
|
|
34
|
-
import {
|
|
35
|
-
projectAgent,
|
|
36
|
-
getSession,
|
|
37
|
-
} from "../../ui/app/lib/neo4j-store";
|
|
38
|
-
import { ACCOUNTS_DIR } from "../../ui/app/lib/claude-agent/account";
|
|
39
|
-
|
|
40
|
-
interface PerAccountStats {
|
|
41
|
-
accountId: string;
|
|
42
|
-
agents: number;
|
|
43
|
-
agentFailures: number;
|
|
44
|
-
convEdges: number;
|
|
45
|
-
convOrphans: number;
|
|
46
|
-
convCandidates: number;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async function projectAccountAgents(
|
|
50
|
-
accountId: string,
|
|
51
|
-
accountDir: string,
|
|
52
|
-
): Promise<{ agents: number; agentFailures: number }> {
|
|
53
|
-
const agentsDir = resolve(accountDir, "agents");
|
|
54
|
-
if (!existsSync(agentsDir)) return { agents: 0, agentFailures: 0 };
|
|
55
|
-
|
|
56
|
-
let agents = 0;
|
|
57
|
-
let agentFailures = 0;
|
|
58
|
-
for (const entry of readdirSync(agentsDir, { withFileTypes: true })) {
|
|
59
|
-
if (!entry.isDirectory()) continue;
|
|
60
|
-
if (entry.name === "admin") continue;
|
|
61
|
-
|
|
62
|
-
const configPath = resolve(agentsDir, entry.name, "config.json");
|
|
63
|
-
if (!existsSync(configPath)) continue;
|
|
64
|
-
|
|
65
|
-
try {
|
|
66
|
-
await projectAgent(accountId, accountDir, entry.name);
|
|
67
|
-
agents++;
|
|
68
|
-
} catch (err) {
|
|
69
|
-
agentFailures++;
|
|
70
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
71
|
-
console.error(
|
|
72
|
-
`[agent-graph-backfill] account=${accountId.slice(0, 8)} agent=${entry.name} project FAILED error="${msg}"`,
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return { agents, agentFailures };
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
interface HandledByBackfillStats {
|
|
80
|
-
candidates: number;
|
|
81
|
-
edges: number;
|
|
82
|
-
orphans: number;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Two-pass: count candidate Conversations (those carrying agentSlug),
|
|
87
|
-
* then OPTIONAL MATCH to surface orphans separately from successful merges.
|
|
88
|
-
* A hard MATCH-then-MATCH chain would silently filter orphan-slug rows out,
|
|
89
|
-
* making `edges=0` indistinguishable from "no public conversations exist"
|
|
90
|
-
* vs "every slug is orphaned" — different incidents, different fixes.
|
|
91
|
-
*/
|
|
92
|
-
async function backfillHandledByEdges(accountId: string): Promise<HandledByBackfillStats> {
|
|
93
|
-
const session = getSession();
|
|
94
|
-
try {
|
|
95
|
-
const result = await session.run(
|
|
96
|
-
`MATCH (c:Conversation {accountId: $accountId, agentType: 'public'})
|
|
97
|
-
WHERE c.agentSlug IS NOT NULL
|
|
98
|
-
OPTIONAL MATCH (a:Agent {accountId: $accountId, slug: c.agentSlug})
|
|
99
|
-
FOREACH (_ IN CASE WHEN a IS NULL THEN [] ELSE [1] END | MERGE (c)-[:HANDLED_BY]->(a))
|
|
100
|
-
RETURN
|
|
101
|
-
count(c) AS candidates,
|
|
102
|
-
sum(CASE WHEN a IS NULL THEN 0 ELSE 1 END) AS edges,
|
|
103
|
-
sum(CASE WHEN a IS NULL THEN 1 ELSE 0 END) AS orphans`,
|
|
104
|
-
{ accountId },
|
|
105
|
-
);
|
|
106
|
-
const toNum = (v: unknown): number => {
|
|
107
|
-
if (typeof v === "number") return v;
|
|
108
|
-
if (v && typeof (v as { toNumber: () => number }).toNumber === "function") {
|
|
109
|
-
return (v as { toNumber: () => number }).toNumber();
|
|
110
|
-
}
|
|
111
|
-
return 0;
|
|
112
|
-
};
|
|
113
|
-
return {
|
|
114
|
-
candidates: toNum(result.records[0]?.get("candidates")),
|
|
115
|
-
edges: toNum(result.records[0]?.get("edges")),
|
|
116
|
-
orphans: toNum(result.records[0]?.get("orphans")),
|
|
117
|
-
};
|
|
118
|
-
} finally {
|
|
119
|
-
await session.close();
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
async function main(): Promise<void> {
|
|
124
|
-
const start = Date.now();
|
|
125
|
-
|
|
126
|
-
if (!existsSync(ACCOUNTS_DIR)) {
|
|
127
|
-
console.error(`[agent-graph-backfill] ACCOUNTS_DIR missing at ${ACCOUNTS_DIR} — nothing to do`);
|
|
128
|
-
process.exit(0);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const accountEntries = readdirSync(ACCOUNTS_DIR, { withFileTypes: true })
|
|
132
|
-
.filter((e) => e.isDirectory());
|
|
133
|
-
|
|
134
|
-
console.error(`[agent-graph-backfill] start accounts=${accountEntries.length}`);
|
|
135
|
-
|
|
136
|
-
let totalAgents = 0;
|
|
137
|
-
let totalAgentFailures = 0;
|
|
138
|
-
let totalConvEdges = 0;
|
|
139
|
-
let totalConvOrphans = 0;
|
|
140
|
-
let totalConvCandidates = 0;
|
|
141
|
-
const perAccount: PerAccountStats[] = [];
|
|
142
|
-
|
|
143
|
-
for (const entry of accountEntries) {
|
|
144
|
-
const accountDir = resolve(ACCOUNTS_DIR, entry.name);
|
|
145
|
-
const accountId = entry.name;
|
|
146
|
-
const accountStart = Date.now();
|
|
147
|
-
|
|
148
|
-
const { agents, agentFailures } = await projectAccountAgents(accountId, accountDir);
|
|
149
|
-
totalAgents += agents;
|
|
150
|
-
totalAgentFailures += agentFailures;
|
|
151
|
-
|
|
152
|
-
let convStats: HandledByBackfillStats = { candidates: 0, edges: 0, orphans: 0 };
|
|
153
|
-
try {
|
|
154
|
-
convStats = await backfillHandledByEdges(accountId);
|
|
155
|
-
totalConvEdges += convStats.edges;
|
|
156
|
-
totalConvOrphans += convStats.orphans;
|
|
157
|
-
totalConvCandidates += convStats.candidates;
|
|
158
|
-
} catch (err) {
|
|
159
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
160
|
-
console.error(
|
|
161
|
-
`[agent-graph-backfill] account=${accountId.slice(0, 8)} handled-by-backfill FAILED error="${msg}"`,
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
perAccount.push({
|
|
166
|
-
accountId,
|
|
167
|
-
agents,
|
|
168
|
-
agentFailures,
|
|
169
|
-
convEdges: convStats.edges,
|
|
170
|
-
convOrphans: convStats.orphans,
|
|
171
|
-
convCandidates: convStats.candidates,
|
|
172
|
-
});
|
|
173
|
-
const ms = Date.now() - accountStart;
|
|
174
|
-
console.error(
|
|
175
|
-
`[agent-graph-backfill] account=${accountId.slice(0, 8)} agents=${agents} failures=${agentFailures} conv-candidates=${convStats.candidates} conv-edges=${convStats.edges} conv-orphans=${convStats.orphans} ms=${ms}`,
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const ms = Date.now() - start;
|
|
180
|
-
console.error(
|
|
181
|
-
`[agent-graph-backfill] done totals: agents=${totalAgents} agent-failures=${totalAgentFailures} conv-candidates=${totalConvCandidates} conv-edges=${totalConvEdges} conv-orphans=${totalConvOrphans} ms=${ms}`,
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
process.exit(totalAgentFailures > 0 ? 1 : 0);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
main().catch((err) => {
|
|
188
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
189
|
-
console.error(`[agent-graph-backfill] fatal error="${msg}"`);
|
|
190
|
-
process.exit(2);
|
|
191
|
-
});
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
// ============================================================
|
|
2
|
-
// Migration 003 — Person.name eradication (Task 849)
|
|
3
|
-
//
|
|
4
|
-
// Removes the denormalised `name` property from every Person node.
|
|
5
|
-
// `Person.name` is forbidden by schema-base.md "Forbidden Properties":
|
|
6
|
-
// the canonical fields are `givenName` + `familyName`, composed at
|
|
7
|
-
// read time by display-helpers.ts. Persisted `name` was a divergence
|
|
8
|
-
// trap — LLM extraction emitted `name = givenName` ("Dan") alongside
|
|
9
|
-
// the structured pair, so the canvas rendered "Dan" instead of
|
|
10
|
-
// "Dan Brett".
|
|
11
|
-
//
|
|
12
|
-
// Idempotent: subsequent runs find no Persons with `name` set and
|
|
13
|
-
// return removed=0.
|
|
14
|
-
//
|
|
15
|
-
// Applied at boot by platform/ui/app/lib/neo4j-migrations.ts. Safe to
|
|
16
|
-
// run manually:
|
|
17
|
-
// cypher-shell -u neo4j -p <password> -a $NEO4J_URI \
|
|
18
|
-
// -f platform/neo4j/migrations/003-person-name-eradicate.cypher
|
|
19
|
-
// ============================================================
|
|
20
|
-
|
|
21
|
-
MATCH (p:Person)
|
|
22
|
-
WHERE p.name IS NOT NULL
|
|
23
|
-
REMOVE p.name
|
|
24
|
-
RETURN count(p) AS removed
|