@rubytech/create-realagent-code 0.1.253 → 0.1.255
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/.docs/search-surface-contract.md +58 -0
- package/payload/platform/lib/embed-client/dist/index.d.ts +4 -0
- package/payload/platform/lib/embed-client/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/embed-client/dist/index.js +53 -0
- package/payload/platform/lib/embed-client/dist/index.js.map +1 -0
- package/payload/platform/lib/embed-client/src/index.ts +53 -0
- package/payload/platform/lib/embed-client/tsconfig.json +8 -0
- package/payload/platform/lib/graph-search/dist/index.d.ts +27 -6
- package/payload/platform/lib/graph-search/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-search/dist/index.js +19 -1
- package/payload/platform/lib/graph-search/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-search/src/index.ts +28 -6
- package/payload/platform/lib/graph-write/dist/index.d.ts +25 -0
- package/payload/platform/lib/graph-write/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-write/dist/index.js +78 -2
- package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-write/src/index.ts +96 -1
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +3 -3
- package/payload/platform/plugins/admin/hooks/__tests__/{session-end-retrospective.test.sh → insight.test.sh} +152 -153
- package/payload/platform/plugins/admin/hooks/insight.sh +219 -0
- package/payload/platform/plugins/admin/hooks/lib/admin-graph-pass-common.sh +5 -5
- package/payload/platform/plugins/admin/mcp/dist/index.js +33 -19
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +23 -23
- package/payload/platform/plugins/docs/references/graph.md +2 -0
- package/payload/platform/plugins/docs/references/internals.md +12 -1
- package/payload/platform/plugins/docs/references/neo4j.md +2 -2
- package/payload/platform/plugins/docs/references/platform.md +1 -1
- package/payload/platform/plugins/docs/references/session-retrospective.md +5 -18
- package/payload/platform/plugins/email/PLUGIN.md +2 -2
- package/payload/platform/plugins/email/mcp/dist/index.js +8 -0
- package/payload/platform/plugins/email/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/attachment-resolve.d.ts +19 -0
- package/payload/platform/plugins/email/mcp/dist/lib/attachment-resolve.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/attachment-resolve.js +64 -0
- package/payload/platform/plugins/email/mcp/dist/lib/attachment-resolve.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/smtp.d.ts +4 -0
- package/payload/platform/plugins/email/mcp/dist/lib/smtp.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/smtp.js +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/smtp.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-reply.d.ts +1 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-reply.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-reply.js +6 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-reply.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-send.d.ts +1 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-send.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-send.js +7 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-send.js.map +1 -1
- package/payload/platform/plugins/email/references/email-reference.md +4 -0
- package/payload/platform/plugins/memory/PLUGIN.md +1 -2
- package/payload/platform/plugins/memory/mcp/dist/index.js +5 -43
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/document-sectioniser.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/document-sectioniser.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/document-sectioniser.test.js +41 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/document-sectioniser.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-embed-net.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-embed-net.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-embed-net.test.js +90 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-embed-net.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/vector-indexed-labels-drift.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/vector-indexed-labels-drift.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/vector-indexed-labels-drift.test.js +27 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/vector-indexed-labels-drift.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/document-sectioniser.d.ts +10 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/document-sectioniser.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/document-sectioniser.js +47 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/document-sectioniser.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.d.ts +1 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.js +5 -28
- package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/build-text-representation-bound.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/build-text-representation-bound.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/build-text-representation-bound.test.js +20 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/build-text-representation-bound.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-preference-embed.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-preference-embed.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-preference-embed.test.js +67 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-preference-embed.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embeddings-cap.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embeddings-cap.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embeddings-cap.test.js +34 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embeddings-cap.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-section-writer.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-section-writer.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-section-writer.test.js +61 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-section-writer.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js +23 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex.test.js +87 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.js +3 -0
- 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-search-threshold.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-threshold.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-threshold.test.js +34 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-threshold.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js +19 -4
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts +33 -6
- 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 +280 -10
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.js +76 -37
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.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 +11 -2
- 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 +3 -3
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js +2 -2
- 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 +10 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js +6 -3
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/vitest.config.ts +5 -0
- package/payload/platform/plugins/memory/references/schema-base.md +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.js +15 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.js.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.js +4 -0
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.js.map +1 -1
- package/payload/platform/scripts/identity-forbidden-token-check.mjs +0 -1
- package/payload/platform/scripts/setup-account.sh +2 -8
- package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.d.ts +23 -0
- package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.js +29 -0
- package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +0 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +14 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +8 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.d.ts +13 -1
- package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.js +26 -2
- package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts +12 -3
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js +3 -2
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
- package/payload/platform/templates/agents/admin/IDENTITY.md +2 -2
- package/payload/platform/templates/specialists/agents/database-operator.md +2 -6
- package/payload/server/{chunk-M6A6EZD4.js → chunk-76HRO7NX.js} +16 -2
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/server.js +534 -35
- package/payload/platform/plugins/admin/hooks/session-end-retrospective.sh +0 -214
package/payload/server/server.js
CHANGED
|
@@ -93,7 +93,7 @@ import {
|
|
|
93
93
|
vncLog,
|
|
94
94
|
walkPremiumBundles,
|
|
95
95
|
writeAdminUserAndPerson
|
|
96
|
-
} from "./chunk-
|
|
96
|
+
} from "./chunk-76HRO7NX.js";
|
|
97
97
|
import {
|
|
98
98
|
__commonJS,
|
|
99
99
|
__require,
|
|
@@ -5211,6 +5211,374 @@ var require_dist3 = __commonJS({
|
|
|
5211
5211
|
}
|
|
5212
5212
|
});
|
|
5213
5213
|
|
|
5214
|
+
// ../lib/graph-write/dist/audit.js
|
|
5215
|
+
var require_audit = __commonJS({
|
|
5216
|
+
"../lib/graph-write/dist/audit.js"(exports) {
|
|
5217
|
+
"use strict";
|
|
5218
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5219
|
+
exports.auditCypherWrite = auditCypherWrite;
|
|
5220
|
+
exports.formatAuditLine = formatAuditLine;
|
|
5221
|
+
var EDGE_PATTERN = /\[[^\]]*?:([A-Z_][A-Za-z0-9_]*(?:\|[A-Z_][A-Za-z0-9_]*)*)[^\]]*?\]/g;
|
|
5222
|
+
var CREATE_OR_MERGE_NODE = /\b(?:CREATE|MERGE)\s*\(\s*[A-Za-z_][A-Za-z0-9_]*\s*:\s*[A-Z]/g;
|
|
5223
|
+
var PROVENANCE_TOKEN = /\bcreatedBy(?:Agent|Tool|Session|Source)\b/g;
|
|
5224
|
+
function stripStringLiterals(cypher) {
|
|
5225
|
+
return cypher.replace(/'[^']*'|"[^"]*"/g, '""');
|
|
5226
|
+
}
|
|
5227
|
+
function extractEdgeTypes(cleaned) {
|
|
5228
|
+
const out = /* @__PURE__ */ new Set();
|
|
5229
|
+
for (const m of cleaned.matchAll(EDGE_PATTERN)) {
|
|
5230
|
+
for (const t of m[1].split("|")) {
|
|
5231
|
+
const clean = t.trim();
|
|
5232
|
+
if (clean)
|
|
5233
|
+
out.add(clean);
|
|
5234
|
+
}
|
|
5235
|
+
}
|
|
5236
|
+
return out;
|
|
5237
|
+
}
|
|
5238
|
+
function countCreateOrMergeNodes(cleaned) {
|
|
5239
|
+
const matches = cleaned.match(CREATE_OR_MERGE_NODE);
|
|
5240
|
+
return matches ? matches.length : 0;
|
|
5241
|
+
}
|
|
5242
|
+
function countProvenanceStamps(cleaned) {
|
|
5243
|
+
const matches = cleaned.match(PROVENANCE_TOKEN);
|
|
5244
|
+
return matches ? matches.length : 0;
|
|
5245
|
+
}
|
|
5246
|
+
function auditCypherWrite(input) {
|
|
5247
|
+
const warnings = [];
|
|
5248
|
+
const cleaned = stripStringLiterals(input.cypher);
|
|
5249
|
+
const referencedTypes = extractEdgeTypes(cleaned);
|
|
5250
|
+
for (const t of referencedTypes) {
|
|
5251
|
+
if (!input.schema.relationshipTypes.has(t)) {
|
|
5252
|
+
warnings.push({ kind: "unknown-type-warning", type: t });
|
|
5253
|
+
}
|
|
5254
|
+
}
|
|
5255
|
+
if (input.nodesCreated > 0) {
|
|
5256
|
+
const createOrMergeNodes = countCreateOrMergeNodes(cleaned);
|
|
5257
|
+
if (createOrMergeNodes > 0) {
|
|
5258
|
+
const stamps = countProvenanceStamps(cleaned);
|
|
5259
|
+
if (stamps < createOrMergeNodes) {
|
|
5260
|
+
warnings.push({
|
|
5261
|
+
kind: "missing-provenance-warning",
|
|
5262
|
+
created: createOrMergeNodes,
|
|
5263
|
+
stamped: stamps
|
|
5264
|
+
});
|
|
5265
|
+
}
|
|
5266
|
+
}
|
|
5267
|
+
}
|
|
5268
|
+
if (input.orphanIds.length > 0) {
|
|
5269
|
+
warnings.push({ kind: "orphan-warning", orphanIds: input.orphanIds });
|
|
5270
|
+
}
|
|
5271
|
+
return warnings;
|
|
5272
|
+
}
|
|
5273
|
+
function formatAuditLine(line) {
|
|
5274
|
+
const prefixField = `query="${line.cypherPrefix.replace(/"/g, "'")}"`;
|
|
5275
|
+
switch (line.kind) {
|
|
5276
|
+
case "accepted":
|
|
5277
|
+
return `[graph-cypher-write] accepted ${prefixField} nodesCreated=${line.nodesCreated} relsCreated=${line.relsCreated} agentName=${line.agentName} sessionId=${line.sessionId}`;
|
|
5278
|
+
case "orphan-warning":
|
|
5279
|
+
return `[graph-cypher-write] orphan-warning ${prefixField} orphanIds=${line.orphanIds.join(",")}`;
|
|
5280
|
+
case "unknown-type-warning":
|
|
5281
|
+
return `[graph-cypher-write] unknown-type-warning ${prefixField} type=${line.type}`;
|
|
5282
|
+
case "missing-provenance-warning":
|
|
5283
|
+
return `[graph-cypher-write] missing-provenance-warning ${prefixField} created=${line.created} stamped=${line.stamped}`;
|
|
5284
|
+
}
|
|
5285
|
+
}
|
|
5286
|
+
}
|
|
5287
|
+
});
|
|
5288
|
+
|
|
5289
|
+
// ../lib/graph-write/dist/conversation-provenance.js
|
|
5290
|
+
var require_conversation_provenance = __commonJS({
|
|
5291
|
+
"../lib/graph-write/dist/conversation-provenance.js"(exports) {
|
|
5292
|
+
"use strict";
|
|
5293
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5294
|
+
exports.injectConversationProvenance = injectConversationProvenance;
|
|
5295
|
+
var index_js_1 = require_dist4();
|
|
5296
|
+
async function injectConversationProvenance(params) {
|
|
5297
|
+
const { session, relationships, accountId, writeLabels, conversationNodeId, logNamespace, tool } = params;
|
|
5298
|
+
const original = [...relationships];
|
|
5299
|
+
if (!writeLabels.some((l) => index_js_1.ACTION_PROVENANCE_LABELS.has(l)))
|
|
5300
|
+
return original;
|
|
5301
|
+
if (!conversationNodeId)
|
|
5302
|
+
return original;
|
|
5303
|
+
if (hasInboundProducedEdge(original))
|
|
5304
|
+
return original;
|
|
5305
|
+
let lookup;
|
|
5306
|
+
try {
|
|
5307
|
+
lookup = await session.run(`MATCH (c:Conversation {sessionId: $cid, accountId: $accountId})
|
|
5308
|
+
RETURN elementId(c) AS elementId, labels(c) AS labels LIMIT 1`, { cid: conversationNodeId, accountId });
|
|
5309
|
+
} catch (err) {
|
|
5310
|
+
process.stderr.write(`[${logNamespace}] [provenance-missing] tool=${tool} reason=driver-error message=${err instanceof Error ? err.message : String(err)} conversationNodeId=${conversationNodeId}
|
|
5311
|
+
`);
|
|
5312
|
+
return original;
|
|
5313
|
+
}
|
|
5314
|
+
if (lookup.records.length === 0) {
|
|
5315
|
+
process.stderr.write(`[${logNamespace}] [provenance-missing] tool=${tool} reason=node-not-found conversationNodeId=${conversationNodeId}
|
|
5316
|
+
`);
|
|
5317
|
+
return original;
|
|
5318
|
+
}
|
|
5319
|
+
const elementId = lookup.records[0].get("elementId");
|
|
5320
|
+
const labels = lookup.records[0].get("labels");
|
|
5321
|
+
const sourceLabel = labels.find((l) => index_js_1.PROVENANCE_SOURCE_LABELS.has(l));
|
|
5322
|
+
if (!sourceLabel) {
|
|
5323
|
+
process.stderr.write(`[${logNamespace}] [provenance-missing] tool=${tool} reason=wrong-source-label labels=${labels.join(",")} conversationNodeId=${conversationNodeId}
|
|
5324
|
+
`);
|
|
5325
|
+
return original;
|
|
5326
|
+
}
|
|
5327
|
+
process.stderr.write(`[${logNamespace}] [provenance-inject] tool=${tool} from=${sourceLabel}:${conversationNodeId}
|
|
5328
|
+
`);
|
|
5329
|
+
return [
|
|
5330
|
+
{
|
|
5331
|
+
type: "PRODUCED",
|
|
5332
|
+
direction: "incoming",
|
|
5333
|
+
targetNodeId: elementId
|
|
5334
|
+
},
|
|
5335
|
+
...original
|
|
5336
|
+
];
|
|
5337
|
+
}
|
|
5338
|
+
function hasInboundProducedEdge(relationships) {
|
|
5339
|
+
return relationships.some((r) => r.type === "PRODUCED" && r.direction === "incoming");
|
|
5340
|
+
}
|
|
5341
|
+
}
|
|
5342
|
+
});
|
|
5343
|
+
|
|
5344
|
+
// ../lib/graph-write/dist/index.js
|
|
5345
|
+
var require_dist4 = __commonJS({
|
|
5346
|
+
"../lib/graph-write/dist/index.js"(exports) {
|
|
5347
|
+
"use strict";
|
|
5348
|
+
var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
5349
|
+
if (k2 === void 0) k2 = k;
|
|
5350
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5351
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
5352
|
+
desc = { enumerable: true, get: function() {
|
|
5353
|
+
return m[k];
|
|
5354
|
+
} };
|
|
5355
|
+
}
|
|
5356
|
+
Object.defineProperty(o, k2, desc);
|
|
5357
|
+
}) : (function(o, m, k, k2) {
|
|
5358
|
+
if (k2 === void 0) k2 = k;
|
|
5359
|
+
o[k2] = m[k];
|
|
5360
|
+
}));
|
|
5361
|
+
var __exportStar = exports && exports.__exportStar || function(m, exports2) {
|
|
5362
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p)) __createBinding(exports2, m, p);
|
|
5363
|
+
};
|
|
5364
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5365
|
+
exports.DOCUMENT_ARCHIVE_LABELS = exports.VECTOR_INDEXED_LABELS = exports.PROVENANCE_SOURCE_LABELS = exports.ACTION_PROVENANCE_LABELS = void 0;
|
|
5366
|
+
exports.stampCreatedBy = stampCreatedBy;
|
|
5367
|
+
exports.writeNodeWithEdges = writeNodeWithEdges;
|
|
5368
|
+
__exportStar(require_audit(), exports);
|
|
5369
|
+
__exportStar(require_conversation_provenance(), exports);
|
|
5370
|
+
exports.ACTION_PROVENANCE_LABELS = /* @__PURE__ */ new Set([
|
|
5371
|
+
"Person",
|
|
5372
|
+
"UserProfile",
|
|
5373
|
+
"AdminUser",
|
|
5374
|
+
"Organization",
|
|
5375
|
+
"LocalBusiness",
|
|
5376
|
+
"CloudflareTunnel",
|
|
5377
|
+
"CloudflareHostname"
|
|
5378
|
+
]);
|
|
5379
|
+
exports.PROVENANCE_SOURCE_LABELS = /* @__PURE__ */ new Set([
|
|
5380
|
+
"Task",
|
|
5381
|
+
"Conversation",
|
|
5382
|
+
"Message"
|
|
5383
|
+
]);
|
|
5384
|
+
function requiresActionProvenance(labels) {
|
|
5385
|
+
for (const label of labels) {
|
|
5386
|
+
if (exports.ACTION_PROVENANCE_LABELS.has(label))
|
|
5387
|
+
return true;
|
|
5388
|
+
}
|
|
5389
|
+
return false;
|
|
5390
|
+
}
|
|
5391
|
+
exports.VECTOR_INDEXED_LABELS = /* @__PURE__ */ new Set([
|
|
5392
|
+
"Question",
|
|
5393
|
+
"DefinedTerm",
|
|
5394
|
+
"Review",
|
|
5395
|
+
"Service",
|
|
5396
|
+
"Person",
|
|
5397
|
+
"LocalBusiness",
|
|
5398
|
+
"Organization",
|
|
5399
|
+
"PriceSpecification",
|
|
5400
|
+
"Task",
|
|
5401
|
+
"CreativeWork",
|
|
5402
|
+
"DigitalDocument",
|
|
5403
|
+
"KnowledgeDocument",
|
|
5404
|
+
"ConversationArchive",
|
|
5405
|
+
"Section",
|
|
5406
|
+
"Chunk",
|
|
5407
|
+
"Project",
|
|
5408
|
+
"Position",
|
|
5409
|
+
"Conversation",
|
|
5410
|
+
"Message",
|
|
5411
|
+
"Event",
|
|
5412
|
+
"Workflow",
|
|
5413
|
+
"Preference",
|
|
5414
|
+
"Listing",
|
|
5415
|
+
"Idea",
|
|
5416
|
+
"TimelineEvent",
|
|
5417
|
+
"Report",
|
|
5418
|
+
"FileArtifact"
|
|
5419
|
+
]);
|
|
5420
|
+
exports.DOCUMENT_ARCHIVE_LABELS = /* @__PURE__ */ new Set([
|
|
5421
|
+
"KnowledgeDocument",
|
|
5422
|
+
"DigitalDocument",
|
|
5423
|
+
"ConversationArchive"
|
|
5424
|
+
]);
|
|
5425
|
+
function labelsAreIndexed(labels) {
|
|
5426
|
+
for (const l of labels)
|
|
5427
|
+
if (exports.VECTOR_INDEXED_LABELS.has(l))
|
|
5428
|
+
return true;
|
|
5429
|
+
return false;
|
|
5430
|
+
}
|
|
5431
|
+
function boundedEmbedText(labels, props) {
|
|
5432
|
+
const PER_VALUE = 2e3;
|
|
5433
|
+
const TOTAL = 8e3;
|
|
5434
|
+
const docPreferred = labels.some((l) => exports.DOCUMENT_ARCHIVE_LABELS.has(l));
|
|
5435
|
+
const parts = [`[${labels.join(", ")}]`];
|
|
5436
|
+
for (const [k, v] of Object.entries(props)) {
|
|
5437
|
+
if (v === null || v === void 0 || k === "embedding")
|
|
5438
|
+
continue;
|
|
5439
|
+
if (docPreferred && (k === "body" || k === "text"))
|
|
5440
|
+
continue;
|
|
5441
|
+
const s = String(v);
|
|
5442
|
+
parts.push(`${k}: ${s.length > PER_VALUE ? s.slice(0, PER_VALUE) : s}`);
|
|
5443
|
+
}
|
|
5444
|
+
const joined = parts.join(" | ");
|
|
5445
|
+
return joined.length > TOTAL ? joined.slice(0, TOTAL) : joined;
|
|
5446
|
+
}
|
|
5447
|
+
function findProvenanceCandidates(relationships) {
|
|
5448
|
+
return relationships.filter((r) => r.type === "PRODUCED" && r.direction === "incoming");
|
|
5449
|
+
}
|
|
5450
|
+
function stampCreatedBy(props, createdBy) {
|
|
5451
|
+
return {
|
|
5452
|
+
...props,
|
|
5453
|
+
createdByAgent: createdBy.agent ?? "unknown",
|
|
5454
|
+
createdBySession: createdBy.session ?? "unknown",
|
|
5455
|
+
createdByTool: createdBy.tool ?? null,
|
|
5456
|
+
createdBySource: createdBy.source ?? null
|
|
5457
|
+
};
|
|
5458
|
+
}
|
|
5459
|
+
async function writeNodeWithEdges(params) {
|
|
5460
|
+
const { session, labels, props, relationships, createdBy } = params;
|
|
5461
|
+
const agentLabel = createdBy.agent ?? createdBy.source ?? "unknown";
|
|
5462
|
+
const labelCsv = labels.join(",");
|
|
5463
|
+
const isSystemBootstrap = (createdBy.agent ?? "") === "system";
|
|
5464
|
+
if (!isSystemBootstrap) {
|
|
5465
|
+
const accountId = props.accountId;
|
|
5466
|
+
const expectedAccountId = params.expectedAccountId ?? process.env.ACCOUNT_ID;
|
|
5467
|
+
if (typeof accountId !== "string" || !expectedAccountId || accountId !== expectedAccountId) {
|
|
5468
|
+
const slice = typeof accountId === "string" ? accountId.slice(0, 8) : "missing";
|
|
5469
|
+
process.stderr.write(`[graph-write] reject reason=invalid-account-id accountId=${slice} writer=${agentLabel}
|
|
5470
|
+
`);
|
|
5471
|
+
throw new Error(`Write doctrine violated: invalid-account-id (${slice}) \u2014 accountId must equal ACCOUNT_ID set by the spawning process. See .docs/neo4j.md "Account isolation invariant".`);
|
|
5472
|
+
}
|
|
5473
|
+
}
|
|
5474
|
+
const reviewDigestActionTool = typeof props.actionTool === "string" && props.actionTool === "review-digest-compose";
|
|
5475
|
+
if (labels.includes("ReviewAlert") || reviewDigestActionTool) {
|
|
5476
|
+
const actionToolField = reviewDigestActionTool ? "review-digest-compose" : "n/a";
|
|
5477
|
+
process.stderr.write(`[graph-write] reject reason=removed-feature labels=${labelCsv} actionTool=${actionToolField} agent=${agentLabel}
|
|
5478
|
+
`);
|
|
5479
|
+
throw new Error("Write doctrine violated: review-detector feature removed \u2014 `:ReviewAlert` and `:Event {actionTool:'review-digest-compose'}` writes are not allowed.");
|
|
5480
|
+
}
|
|
5481
|
+
if (!relationships || relationships.length < 1) {
|
|
5482
|
+
process.stderr.write(`[graph-write] reject reason=zero-relationships labels=${labelCsv} agent=${agentLabel}
|
|
5483
|
+
`);
|
|
5484
|
+
throw new Error("Write doctrine violated: a node must be created with at least one relationship. See .docs/neo4j.md (Write doctrine).");
|
|
5485
|
+
}
|
|
5486
|
+
const indexed = labelsAreIndexed(labels);
|
|
5487
|
+
let embedded = Array.isArray(props.embedding) && props.embedding.length > 0;
|
|
5488
|
+
const workingProps = { ...props };
|
|
5489
|
+
if (indexed && !embedded && typeof params.embed === "function") {
|
|
5490
|
+
try {
|
|
5491
|
+
const vec = await params.embed(boundedEmbedText(labels, props));
|
|
5492
|
+
if (Array.isArray(vec) && vec.length > 0) {
|
|
5493
|
+
workingProps.embedding = vec;
|
|
5494
|
+
embedded = true;
|
|
5495
|
+
}
|
|
5496
|
+
} catch (err) {
|
|
5497
|
+
process.stderr.write(`[graph-write] warn reason=embed-failed labels=${labelCsv} agent=${agentLabel} detail=${err instanceof Error ? err.message : String(err)}
|
|
5498
|
+
`);
|
|
5499
|
+
}
|
|
5500
|
+
}
|
|
5501
|
+
const labelStr = labels.map((l) => `\`${l.replace(/`/g, "")}\``).join(":");
|
|
5502
|
+
const nodeProps = stampCreatedBy(workingProps, createdBy);
|
|
5503
|
+
return await session.executeWrite(async (tx) => {
|
|
5504
|
+
const targetIds = relationships.map((r) => r.targetNodeId);
|
|
5505
|
+
const check = await tx.run(`UNWIND $ids AS id MATCH (t) WHERE elementId(t) = id RETURN elementId(t) AS id, labels(t) AS labels`, { ids: targetIds });
|
|
5506
|
+
const labelsByTarget = /* @__PURE__ */ new Map();
|
|
5507
|
+
for (const rec of check.records) {
|
|
5508
|
+
labelsByTarget.set(rec.get("id"), rec.get("labels"));
|
|
5509
|
+
}
|
|
5510
|
+
const found = labelsByTarget.size;
|
|
5511
|
+
const uniqueRequested = new Set(targetIds).size;
|
|
5512
|
+
if (found !== uniqueRequested) {
|
|
5513
|
+
process.stderr.write(`[graph-write] reject reason=unresolved-target labels=${labelCsv} agent=${agentLabel} requested=${uniqueRequested} found=${found}
|
|
5514
|
+
`);
|
|
5515
|
+
throw new Error(`Write doctrine violated: ${uniqueRequested - found} of ${uniqueRequested} relationship target(s) did not resolve (elementId mismatch). No node created.`);
|
|
5516
|
+
}
|
|
5517
|
+
let provenanceSourceId = null;
|
|
5518
|
+
let provenanceSourceLabel = null;
|
|
5519
|
+
if (requiresActionProvenance(labels) && (createdBy.agent ?? "") !== "system") {
|
|
5520
|
+
const candidates = findProvenanceCandidates(relationships);
|
|
5521
|
+
const matched = candidates.map((r) => {
|
|
5522
|
+
const lbls = labelsByTarget.get(r.targetNodeId);
|
|
5523
|
+
if (!Array.isArray(lbls))
|
|
5524
|
+
return null;
|
|
5525
|
+
const sourceLabel = lbls.find((l) => exports.PROVENANCE_SOURCE_LABELS.has(l));
|
|
5526
|
+
return sourceLabel ? { rel: r, sourceLabel } : null;
|
|
5527
|
+
}).filter((m) => m !== null);
|
|
5528
|
+
if (matched.length === 0) {
|
|
5529
|
+
process.stderr.write(`[graph-write] warn reason=missing-provenance labels=${labelCsv} agent=${agentLabel}
|
|
5530
|
+
`);
|
|
5531
|
+
} else {
|
|
5532
|
+
provenanceSourceId = matched[0].rel.targetNodeId;
|
|
5533
|
+
provenanceSourceLabel = matched[0].sourceLabel;
|
|
5534
|
+
}
|
|
5535
|
+
}
|
|
5536
|
+
let nodeRes;
|
|
5537
|
+
try {
|
|
5538
|
+
nodeRes = await tx.run(`CREATE (n:${labelStr} $props) RETURN elementId(n) AS nodeId, labels(n) AS nodeLabels`, { props: nodeProps });
|
|
5539
|
+
} catch (err) {
|
|
5540
|
+
const code = err?.code ?? "";
|
|
5541
|
+
if (code === "Neo.ClientError.Schema.ConstraintValidationFailed" && labels.includes("UserProfile")) {
|
|
5542
|
+
const accountIdProp = nodeProps.accountId;
|
|
5543
|
+
const userIdProp = nodeProps.userId;
|
|
5544
|
+
const acctSlice2 = typeof accountIdProp === "string" ? accountIdProp.slice(0, 8) : "unknown";
|
|
5545
|
+
const userSlice = typeof userIdProp === "string" ? userIdProp.slice(0, 8) : "unknown";
|
|
5546
|
+
process.stderr.write(`[graph-write] reject reason=user-profile-uniqueness-violation accountId=${acctSlice2} userId=${userSlice} writer=${agentLabel}
|
|
5547
|
+
`);
|
|
5548
|
+
}
|
|
5549
|
+
throw err;
|
|
5550
|
+
}
|
|
5551
|
+
const nodeId = nodeRes.records[0].get("nodeId");
|
|
5552
|
+
const nodeLabels = nodeRes.records[0].get("nodeLabels");
|
|
5553
|
+
let edgesCreated = 0;
|
|
5554
|
+
for (const rel of relationships) {
|
|
5555
|
+
const type = rel.type.replace(/`/g, "");
|
|
5556
|
+
const q = rel.direction === "outgoing" ? `MATCH (a), (b) WHERE elementId(a) = $from AND elementId(b) = $to CREATE (a)-[:\`${type}\`]->(b)` : `MATCH (a), (b) WHERE elementId(a) = $from AND elementId(b) = $to CREATE (b)-[:\`${type}\`]->(a)`;
|
|
5557
|
+
const r = await tx.run(q, { from: nodeId, to: rel.targetNodeId });
|
|
5558
|
+
const created = r.summary.counters.updates().relationshipsCreated;
|
|
5559
|
+
if (created === 0) {
|
|
5560
|
+
process.stderr.write(`[graph-write] reject reason=unresolved-target-on-create labels=${labelCsv} agent=${agentLabel} relType=${rel.type} targetId=${rel.targetNodeId}
|
|
5561
|
+
`);
|
|
5562
|
+
throw new Error(`Write doctrine violated: relationship CREATE to target ${rel.targetNodeId} produced 0 edges (target likely deleted concurrently after pre-check). Transaction rolled back.`);
|
|
5563
|
+
}
|
|
5564
|
+
edgesCreated += created;
|
|
5565
|
+
}
|
|
5566
|
+
if (edgesCreated !== relationships.length) {
|
|
5567
|
+
process.stderr.write(`[graph-write] reject reason=edge-count-mismatch labels=${labelCsv} agent=${agentLabel} requested=${relationships.length} created=${edgesCreated}
|
|
5568
|
+
`);
|
|
5569
|
+
throw new Error(`Write doctrine violated: expected ${relationships.length} edges, created ${edgesCreated}. Transaction rolled back.`);
|
|
5570
|
+
}
|
|
5571
|
+
process.stderr.write(`[graph-write] accepted labels=${labelCsv} edges=${edgesCreated} createdByAgent=${createdBy.agent ?? "unknown"} createdByTool=${createdBy.tool ?? createdBy.source ?? "unknown"} producedBy=${provenanceSourceLabel ?? "none"}:${provenanceSourceId ?? "none"}
|
|
5572
|
+
`);
|
|
5573
|
+
const acctSlice = typeof props.accountId === "string" ? props.accountId.slice(0, 8) : "none";
|
|
5574
|
+
process.stderr.write(`[graph-write] op=node-written label=${labelCsv} accountId=${acctSlice} embedded=${embedded} indexed=${indexed}
|
|
5575
|
+
`);
|
|
5576
|
+
return { nodeId, labels: nodeLabels, edgesCreated };
|
|
5577
|
+
});
|
|
5578
|
+
}
|
|
5579
|
+
}
|
|
5580
|
+
});
|
|
5581
|
+
|
|
5214
5582
|
// node_modules/hono/dist/utils/mime.js
|
|
5215
5583
|
var getMimeType = (filename, mimes = baseMimes) => {
|
|
5216
5584
|
const regexp = /\.([a-zA-Z0-9]+?)$/;
|
|
@@ -8857,8 +9225,9 @@ async function managerDelete(sessionId) {
|
|
|
8857
9225
|
await fetch(`${managerBase()}/${sessionId}`, { method: "DELETE" }).catch(() => {
|
|
8858
9226
|
});
|
|
8859
9227
|
}
|
|
8860
|
-
function managerLogFollowUrl(sessionId) {
|
|
8861
|
-
|
|
9228
|
+
function managerLogFollowUrl(sessionId, opts) {
|
|
9229
|
+
const base = `${managerBase()}/${sessionId}/log?follow=1`;
|
|
9230
|
+
return opts?.boundary ? `${base}&boundary=1` : base;
|
|
8862
9231
|
}
|
|
8863
9232
|
|
|
8864
9233
|
// app/lib/channel-pty-bridge/admin-session-id.ts
|
|
@@ -9044,9 +9413,10 @@ function startFollower(opts) {
|
|
|
9044
9413
|
let res;
|
|
9045
9414
|
let attempt = 0;
|
|
9046
9415
|
for (; ; ) {
|
|
9047
|
-
res = await fetch(
|
|
9048
|
-
|
|
9049
|
-
|
|
9416
|
+
res = await fetch(
|
|
9417
|
+
managerLogFollowUrl(entry.sessionId, { boundary: opts.suppressResumeReplay === true }),
|
|
9418
|
+
{ signal: abort.signal }
|
|
9419
|
+
);
|
|
9050
9420
|
console.error(`${tag} follower-connect sessionId=${sid} status=${res.status}`);
|
|
9051
9421
|
if (res.status === 202) {
|
|
9052
9422
|
attempt += 1;
|
|
@@ -9075,6 +9445,9 @@ function startFollower(opts) {
|
|
|
9075
9445
|
let buffered = "";
|
|
9076
9446
|
const fileDelivery = opts.fileDelivery ?? null;
|
|
9077
9447
|
let firedFileTools = [];
|
|
9448
|
+
let suppressing = opts.suppressResumeReplay === true;
|
|
9449
|
+
let discardedTurns = 0;
|
|
9450
|
+
let discardedFileTools = 0;
|
|
9078
9451
|
while (!abort.signal.aborted) {
|
|
9079
9452
|
const { value, done } = await reader.read();
|
|
9080
9453
|
if (done) break;
|
|
@@ -9094,6 +9467,15 @@ function startFollower(opts) {
|
|
|
9094
9467
|
);
|
|
9095
9468
|
continue;
|
|
9096
9469
|
}
|
|
9470
|
+
if (event.type === "__channel_resume_boundary__") {
|
|
9471
|
+
if (suppressing) {
|
|
9472
|
+
suppressing = false;
|
|
9473
|
+
console.error(
|
|
9474
|
+
`${tag} follower-resume-boundary sessionId=${sid} discarded-head-turns=${discardedTurns} discarded-head-filetools=${discardedFileTools}`
|
|
9475
|
+
);
|
|
9476
|
+
}
|
|
9477
|
+
continue;
|
|
9478
|
+
}
|
|
9097
9479
|
if (event.type === "user") {
|
|
9098
9480
|
entry.pendingTurnText = "";
|
|
9099
9481
|
firedFileTools = [];
|
|
@@ -9107,6 +9489,10 @@ function startFollower(opts) {
|
|
|
9107
9489
|
if (block?.type === "text" && typeof block.text === "string") {
|
|
9108
9490
|
entry.pendingTurnText += block.text;
|
|
9109
9491
|
} else if (fileDelivery && block?.type === "tool_use" && typeof block.name === "string" && fileDelivery.isFileDeliveryTool(block.name)) {
|
|
9492
|
+
if (suppressing) {
|
|
9493
|
+
discardedFileTools += 1;
|
|
9494
|
+
continue;
|
|
9495
|
+
}
|
|
9110
9496
|
firedFileTools.push(block.name);
|
|
9111
9497
|
try {
|
|
9112
9498
|
await fileDelivery.onFileToolUse({ toolName: block.name, input: block.input });
|
|
@@ -9119,6 +9505,12 @@ function startFollower(opts) {
|
|
|
9119
9505
|
}
|
|
9120
9506
|
}
|
|
9121
9507
|
if (msg.stop_reason === "end_turn") {
|
|
9508
|
+
if (suppressing) {
|
|
9509
|
+
entry.pendingTurnText = "";
|
|
9510
|
+
firedFileTools = [];
|
|
9511
|
+
discardedTurns += 1;
|
|
9512
|
+
continue;
|
|
9513
|
+
}
|
|
9122
9514
|
const flush = entry.pendingTurnText;
|
|
9123
9515
|
entry.pendingTurnText = "";
|
|
9124
9516
|
if (flush.trim()) {
|
|
@@ -9166,13 +9558,27 @@ import { realpathSync as realpathSync2 } from "fs";
|
|
|
9166
9558
|
import { readFile, stat as stat2 } from "fs/promises";
|
|
9167
9559
|
import { resolve as resolve4, basename } from "path";
|
|
9168
9560
|
var TAG15 = "[whatsapp:outbound]";
|
|
9561
|
+
var WHATSAPP_DOCUMENT_MAX_BYTES = 100 * 1024 * 1024;
|
|
9169
9562
|
var lastDocumentOutboundAt = /* @__PURE__ */ new Map();
|
|
9563
|
+
var lastRouteDocumentOutboundAt = /* @__PURE__ */ new Map();
|
|
9170
9564
|
function normalizeJid(to) {
|
|
9171
9565
|
return to.includes("@") ? to : toWhatsappJid(to);
|
|
9172
9566
|
}
|
|
9567
|
+
function routeKey(to, filePath) {
|
|
9568
|
+
return `${normalizeJid(to)}\0${filePath}`;
|
|
9569
|
+
}
|
|
9173
9570
|
function documentOutboundAt(to) {
|
|
9174
9571
|
return lastDocumentOutboundAt.get(normalizeJid(to));
|
|
9175
9572
|
}
|
|
9573
|
+
function recordDocumentOutbound(to) {
|
|
9574
|
+
lastDocumentOutboundAt.set(normalizeJid(to), Date.now());
|
|
9575
|
+
}
|
|
9576
|
+
function recordRouteDocumentOutbound(to, filePath) {
|
|
9577
|
+
lastRouteDocumentOutboundAt.set(routeKey(to, filePath), Date.now());
|
|
9578
|
+
}
|
|
9579
|
+
function routeDocumentOutboundAt(to, filePath) {
|
|
9580
|
+
return lastRouteDocumentOutboundAt.get(routeKey(to, filePath));
|
|
9581
|
+
}
|
|
9176
9582
|
async function sendWhatsAppDocument(input) {
|
|
9177
9583
|
const { to, filePath, caption, accountId, maxyAccountId, platformRoot: platformRoot2 } = input;
|
|
9178
9584
|
if (!to || !filePath) {
|
|
@@ -9201,11 +9607,11 @@ async function sendWhatsAppDocument(input) {
|
|
|
9201
9607
|
return { ok: false, status: 500, error: String(err) };
|
|
9202
9608
|
}
|
|
9203
9609
|
const fileStat = await stat2(resolvedPath);
|
|
9204
|
-
if (fileStat.size >
|
|
9610
|
+
if (fileStat.size > WHATSAPP_DOCUMENT_MAX_BYTES) {
|
|
9205
9611
|
return {
|
|
9206
9612
|
ok: false,
|
|
9207
9613
|
status: 400,
|
|
9208
|
-
error: `File exceeds
|
|
9614
|
+
error: `File exceeds 100 MB limit (${(fileStat.size / 1024 / 1024).toFixed(1)} MB)`
|
|
9209
9615
|
};
|
|
9210
9616
|
}
|
|
9211
9617
|
const filename = basename(resolvedPath);
|
|
@@ -9227,7 +9633,7 @@ async function sendWhatsAppDocument(input) {
|
|
|
9227
9633
|
`${TAG15} sent document to=${jid} file=${filename} bytes=${fileStat.size} ok=${result.success}` + (result.messageId ? ` id=${result.messageId}` : "")
|
|
9228
9634
|
);
|
|
9229
9635
|
if (result.success) {
|
|
9230
|
-
|
|
9636
|
+
recordDocumentOutbound(to);
|
|
9231
9637
|
return { ok: true, messageId: result.messageId };
|
|
9232
9638
|
}
|
|
9233
9639
|
return { ok: false, status: 500, error: result.error ?? "send failed" };
|
|
@@ -9242,12 +9648,23 @@ function platformRoot() {
|
|
|
9242
9648
|
}
|
|
9243
9649
|
function makeWhatsAppFileDelivery(entry) {
|
|
9244
9650
|
let turnStartedAt = null;
|
|
9651
|
+
let failedFiles = [];
|
|
9652
|
+
let sendUserFileAttempts = 0;
|
|
9653
|
+
let routeCalls = [];
|
|
9245
9654
|
return {
|
|
9246
9655
|
isFileDeliveryTool(toolName) {
|
|
9247
9656
|
return toolName === SEND_USER_FILE || toolName === WHATSAPP_SEND_DOCUMENT;
|
|
9248
9657
|
},
|
|
9249
9658
|
async onFileToolUse(use) {
|
|
9250
9659
|
if (turnStartedAt === null) turnStartedAt = Date.now();
|
|
9660
|
+
if (use.toolName === WHATSAPP_SEND_DOCUMENT) {
|
|
9661
|
+
const input2 = use.input ?? {};
|
|
9662
|
+
routeCalls.push({
|
|
9663
|
+
to: typeof input2.to === "string" ? input2.to : void 0,
|
|
9664
|
+
filePath: typeof input2.filePath === "string" ? input2.filePath : void 0
|
|
9665
|
+
});
|
|
9666
|
+
return;
|
|
9667
|
+
}
|
|
9251
9668
|
if (use.toolName !== SEND_USER_FILE) return;
|
|
9252
9669
|
const input = use.input ?? {};
|
|
9253
9670
|
const files = Array.isArray(input.files) ? input.files.filter((f) => typeof f === "string") : [];
|
|
@@ -9263,6 +9680,7 @@ function makeWhatsAppFileDelivery(entry) {
|
|
|
9263
9680
|
return;
|
|
9264
9681
|
}
|
|
9265
9682
|
for (let i = 0; i < files.length; i++) {
|
|
9683
|
+
sendUserFileAttempts++;
|
|
9266
9684
|
const result = await sendWhatsAppDocument({
|
|
9267
9685
|
to: entry.senderId,
|
|
9268
9686
|
filePath: files[i],
|
|
@@ -9272,6 +9690,7 @@ function makeWhatsAppFileDelivery(entry) {
|
|
|
9272
9690
|
platformRoot: platformRoot()
|
|
9273
9691
|
});
|
|
9274
9692
|
if (!result.ok) {
|
|
9693
|
+
failedFiles.push(files[i]);
|
|
9275
9694
|
console.error(
|
|
9276
9695
|
`${TAG16} file-delivery reject reason=send-failed sender=${entry.senderId} status=${result.status} message=${result.error}`
|
|
9277
9696
|
);
|
|
@@ -9280,13 +9699,34 @@ function makeWhatsAppFileDelivery(entry) {
|
|
|
9280
9699
|
},
|
|
9281
9700
|
onTurnEnd(firedTools) {
|
|
9282
9701
|
const startedAt = turnStartedAt ?? 0;
|
|
9702
|
+
const failed = failedFiles;
|
|
9703
|
+
const attempts = sendUserFileAttempts;
|
|
9704
|
+
const routes = routeCalls;
|
|
9283
9705
|
turnStartedAt = null;
|
|
9284
|
-
|
|
9285
|
-
|
|
9706
|
+
failedFiles = [];
|
|
9707
|
+
sendUserFileAttempts = 0;
|
|
9708
|
+
routeCalls = [];
|
|
9286
9709
|
const sid = entry.sessionId.slice(0, 8);
|
|
9287
|
-
for (const
|
|
9710
|
+
for (const file of failed) {
|
|
9711
|
+
console.error(
|
|
9712
|
+
`${TAG16} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${SEND_USER_FILE} file=${file}`
|
|
9713
|
+
);
|
|
9714
|
+
}
|
|
9715
|
+
const okAt = documentOutboundAt(entry.senderId);
|
|
9716
|
+
const documentWentOut = okAt !== void 0 && okAt >= startedAt;
|
|
9717
|
+
for (const call of routes) {
|
|
9718
|
+
const routeAt = call.to !== void 0 && call.filePath !== void 0 ? routeDocumentOutboundAt(call.to, call.filePath) : void 0;
|
|
9719
|
+
const delivered = routeAt !== void 0 && routeAt >= startedAt;
|
|
9720
|
+
if (!delivered) {
|
|
9721
|
+
const fileField = call.filePath !== void 0 ? ` file=${call.filePath}` : "";
|
|
9722
|
+
console.error(
|
|
9723
|
+
`${TAG16} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${WHATSAPP_SEND_DOCUMENT}${fileField}`
|
|
9724
|
+
);
|
|
9725
|
+
}
|
|
9726
|
+
}
|
|
9727
|
+
if (firedTools.includes(SEND_USER_FILE) && attempts === 0 && !documentWentOut) {
|
|
9288
9728
|
console.error(
|
|
9289
|
-
`${TAG16} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${
|
|
9729
|
+
`${TAG16} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${SEND_USER_FILE}`
|
|
9290
9730
|
);
|
|
9291
9731
|
}
|
|
9292
9732
|
}
|
|
@@ -9322,6 +9762,12 @@ async function ensureEntry(input) {
|
|
|
9322
9762
|
entry: existing,
|
|
9323
9763
|
tag,
|
|
9324
9764
|
fileDelivery: fileDeliveryFor(existing),
|
|
9765
|
+
// Task 631 — every channel attach resumes an existing session after a
|
|
9766
|
+
// restart (the in-memory index is process memory and empty post-restart).
|
|
9767
|
+
// Suppress replay of the pre-attach JSONL so the first inbound is answered
|
|
9768
|
+
// by a fresh turn, not a historical end_turn, and historical SendUserFile
|
|
9769
|
+
// is not re-sent.
|
|
9770
|
+
suppressResumeReplay: true,
|
|
9325
9771
|
onClose: () => {
|
|
9326
9772
|
existing.followerRunning = false;
|
|
9327
9773
|
}
|
|
@@ -9383,6 +9829,11 @@ async function ensureEntry(input) {
|
|
|
9383
9829
|
entry,
|
|
9384
9830
|
tag,
|
|
9385
9831
|
fileDelivery: fileDeliveryFor(entry),
|
|
9832
|
+
// Task 631 — see the existing-entry branch above. A fresh spawn has an
|
|
9833
|
+
// empty JSONL, so the manager emits the boundary sentinel right after an
|
|
9834
|
+
// empty head and the follower arms immediately; suppression is a no-op for
|
|
9835
|
+
// the cold-spawn first turn and correct for any resume.
|
|
9836
|
+
suppressResumeReplay: true,
|
|
9386
9837
|
onClose: () => {
|
|
9387
9838
|
entry.followerRunning = false;
|
|
9388
9839
|
}
|
|
@@ -10759,6 +11210,7 @@ app3.post("/send-document", async (c) => {
|
|
|
10759
11210
|
platformRoot: PLATFORM_ROOT4
|
|
10760
11211
|
});
|
|
10761
11212
|
if (!result.ok) return c.json({ error: result.error }, result.status);
|
|
11213
|
+
recordRouteDocumentOutbound(to, filePath);
|
|
10762
11214
|
return c.json({ success: true, messageId: result.messageId });
|
|
10763
11215
|
} catch (err) {
|
|
10764
11216
|
console.error(`${TAG19} send-document error: ${String(err)}`);
|
|
@@ -14664,6 +15116,7 @@ function buildScopeAndSliceClause(allowedScopes, sliceToken, alias = "node") {
|
|
|
14664
15116
|
params: { allowedScopes }
|
|
14665
15117
|
};
|
|
14666
15118
|
}
|
|
15119
|
+
var DEFAULT_VECTOR_THRESHOLD = 0.82;
|
|
14667
15120
|
function escapeLucene(query) {
|
|
14668
15121
|
return query.replace(/[+\-&|!(){}[\]^"~*?:\\/]/g, "\\$&");
|
|
14669
15122
|
}
|
|
@@ -15218,7 +15671,6 @@ function plainProperties(properties) {
|
|
|
15218
15671
|
// server/routes/admin/graph-search.ts
|
|
15219
15672
|
var DEFAULT_LIMIT = 20;
|
|
15220
15673
|
var MAX_LIMIT = 2e3;
|
|
15221
|
-
var DEFAULT_VECTOR_THRESHOLD = 0.82;
|
|
15222
15674
|
var MESSAGE_FAMILY_LABELS = ["Message", "UserMessage", "AssistantMessage", "WhatsAppMessage"];
|
|
15223
15675
|
var CONVERSATION_PARENT_LABELS = /* @__PURE__ */ new Set(["AdminConversation", "PublicConversation"]);
|
|
15224
15676
|
var app16 = new Hono();
|
|
@@ -15236,8 +15688,10 @@ app16.get("/", requireAdminSession, async (c) => {
|
|
|
15236
15688
|
if (!q) return c.json({ error: "q (search query) required" }, 400);
|
|
15237
15689
|
const labels = rawLabels ? rawLabels.split(",").map((s) => s.trim()).filter((s) => s.length > 0) : [];
|
|
15238
15690
|
const wildcard = labels.includes("*");
|
|
15239
|
-
|
|
15240
|
-
|
|
15691
|
+
const noChips = labels.length === 0;
|
|
15692
|
+
const allLabels = wildcard || noChips;
|
|
15693
|
+
if (noChips && !wildcard) {
|
|
15694
|
+
console.error(`[graph-search] op=labels-default applied=all query="${q}"`);
|
|
15241
15695
|
}
|
|
15242
15696
|
const parsedLimit = rawLimit ? parseInt(rawLimit, 10) : DEFAULT_LIMIT;
|
|
15243
15697
|
const limit = Number.isFinite(parsedLimit) && parsedLimit > 0 ? Math.min(parsedLimit, MAX_LIMIT) : DEFAULT_LIMIT;
|
|
@@ -15248,8 +15702,8 @@ app16.get("/", requireAdminSession, async (c) => {
|
|
|
15248
15702
|
vectorThreshold = parsed;
|
|
15249
15703
|
}
|
|
15250
15704
|
}
|
|
15251
|
-
const wantsBodyFulltext = !
|
|
15252
|
-
const forwardedLabels =
|
|
15705
|
+
const wantsBodyFulltext = !allLabels && labels.some((l) => CONVERSATION_PARENT_LABELS.has(l));
|
|
15706
|
+
const forwardedLabels = allLabels ? void 0 : wantsBodyFulltext ? Array.from(/* @__PURE__ */ new Set([...labels, ...MESSAGE_FAMILY_LABELS])) : labels;
|
|
15253
15707
|
if (labels.includes("FileArtifact")) {
|
|
15254
15708
|
await reconcileFileIndexDebounced(accountId);
|
|
15255
15709
|
}
|
|
@@ -15324,7 +15778,7 @@ app16.get("/", requireAdminSession, async (c) => {
|
|
|
15324
15778
|
`[graph-search] body-fulltext query="${q}" hits=${bodyFulltextCount} ms=${total}`
|
|
15325
15779
|
);
|
|
15326
15780
|
}
|
|
15327
|
-
const labelsToken = wildcard ? "*" : labels.join(",");
|
|
15781
|
+
const labelsToken = wildcard ? "*" : noChips ? "all" : labels.join(",");
|
|
15328
15782
|
const expandedFlag = !wildcard && wantsBodyFulltext ? 1 : 0;
|
|
15329
15783
|
console.error(
|
|
15330
15784
|
`[graph-search] query="${q}" labels=${labelsToken} expanded=${expandedFlag} limit=${limit} mode=${res.mode} raw-results=${res.results.length} resolved-results=${resolvedResults.length} expand-ms=${res.expandMs} total-ms=${total}`
|
|
@@ -19194,7 +19648,15 @@ app42.post("/", async (c) => {
|
|
|
19194
19648
|
var session_default2 = app42;
|
|
19195
19649
|
|
|
19196
19650
|
// app/lib/graph-health.ts
|
|
19651
|
+
var import_dist5 = __toESM(require_dist4(), 1);
|
|
19197
19652
|
var HOUR_MS = 60 * 60 * 1e3;
|
|
19653
|
+
function renderLabelTop(rows) {
|
|
19654
|
+
return rows.map((b) => {
|
|
19655
|
+
const labels = b.labels.join("+") || "(none)";
|
|
19656
|
+
const c = typeof b.count === "number" ? b.count : b.count.toNumber?.() ?? 0;
|
|
19657
|
+
return `${labels}:${c}`;
|
|
19658
|
+
}).join(",");
|
|
19659
|
+
}
|
|
19198
19660
|
var timer = null;
|
|
19199
19661
|
async function runGraphHealthTick() {
|
|
19200
19662
|
const session = getSession();
|
|
@@ -19231,6 +19693,34 @@ async function runGraphHealthTick() {
|
|
|
19231
19693
|
console.error(
|
|
19232
19694
|
`[graph-health] userprofile-multi accounts=${upAccounts} top=${upTop.length > 0 ? upTop.join(",") : "none"}`
|
|
19233
19695
|
);
|
|
19696
|
+
const indexed = [...import_dist5.VECTOR_INDEXED_LABELS];
|
|
19697
|
+
const embCount = await session.run(
|
|
19698
|
+
`MATCH (n) WHERE n.embedding IS NULL AND any(l IN labels(n) WHERE l IN $indexed)
|
|
19699
|
+
RETURN count(n) AS total`,
|
|
19700
|
+
{ indexed }
|
|
19701
|
+
);
|
|
19702
|
+
const embTotal = embCount.records[0]?.get("total")?.toNumber?.() ?? 0;
|
|
19703
|
+
const embTopRes = await session.run(
|
|
19704
|
+
`MATCH (n) WHERE n.embedding IS NULL AND any(l IN labels(n) WHERE l IN $indexed)
|
|
19705
|
+
WITH labels(n) AS lbls, count(*) AS c
|
|
19706
|
+
ORDER BY c DESC LIMIT 5
|
|
19707
|
+
RETURN collect({labels: lbls, count: c}) AS top`,
|
|
19708
|
+
{ indexed }
|
|
19709
|
+
);
|
|
19710
|
+
const embTop = embTopRes.records[0]?.get("top") ?? [];
|
|
19711
|
+
console.error(`[embed-audit] null-embedding labels=${renderLabelTop(embTop) || "none"} count=${embTotal}`);
|
|
19712
|
+
const acctCount = await session.run(
|
|
19713
|
+
`MATCH (n) WHERE n.accountId IS NULL RETURN count(n) AS total`
|
|
19714
|
+
);
|
|
19715
|
+
const acctTotal = acctCount.records[0]?.get("total")?.toNumber?.() ?? 0;
|
|
19716
|
+
const acctTopRes = await session.run(
|
|
19717
|
+
`MATCH (n) WHERE n.accountId IS NULL
|
|
19718
|
+
WITH labels(n) AS lbls, count(*) AS c
|
|
19719
|
+
ORDER BY c DESC LIMIT 5
|
|
19720
|
+
RETURN collect({labels: lbls, count: c}) AS top`
|
|
19721
|
+
);
|
|
19722
|
+
const acctTop = acctTopRes.records[0]?.get("top") ?? [];
|
|
19723
|
+
console.error(`[account-audit] null-account labels=${renderLabelTop(acctTop) || "none"} count=${acctTotal}`);
|
|
19234
19724
|
} catch (err) {
|
|
19235
19725
|
console.error(
|
|
19236
19726
|
`[graph-health] query failed: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -19382,15 +19872,29 @@ var TAG30 = "[whatsapp-adaptor]";
|
|
|
19382
19872
|
function whatsappTurnTimeoutMs() {
|
|
19383
19873
|
return Number(process.env.WHATSAPP_PTY_TURN_TIMEOUT_MS ?? String(5 * 6e4));
|
|
19384
19874
|
}
|
|
19875
|
+
function composeTurn(input) {
|
|
19876
|
+
const caption = input.text.trim();
|
|
19877
|
+
const hasFileMedia = !!input.mediaPath && input.mediaType !== "audio";
|
|
19878
|
+
if (!hasFileMedia) return caption;
|
|
19879
|
+
const type = input.mediaType ?? "file";
|
|
19880
|
+
const note = input.role === "admin" ? `[Inbound WhatsApp ${type}: ${input.mediaPath}${input.mediaMimetype ? ` (${input.mediaMimetype})` : ""}. Read this file to see what the sender shared.]` : `[The sender shared a ${type}. You cannot open shared files in this session \u2014 ask them to describe or paste the relevant content.]`;
|
|
19881
|
+
return caption ? `${caption}
|
|
19882
|
+
|
|
19883
|
+
${note}` : note;
|
|
19884
|
+
}
|
|
19385
19885
|
async function dispatchToClaude(input) {
|
|
19386
|
-
|
|
19886
|
+
const hasFileMedia = !!input.mediaPath && input.mediaType !== "audio";
|
|
19887
|
+
const mediaField = hasFileMedia ? `media=${input.mediaType} mediaPath=${input.mediaPath}` : input.mediaType === "audio" ? "media=audio mediaPath=transcribed" : "media=none";
|
|
19888
|
+
console.error(`${TAG30} inbound-media ${mediaField} role=${input.role} senderId=${input.senderId}`);
|
|
19889
|
+
const text = composeTurn(input);
|
|
19890
|
+
if (!text.trim()) return;
|
|
19387
19891
|
const result = await dispatchOnce({
|
|
19388
19892
|
accountId: input.accountId,
|
|
19389
19893
|
senderId: input.senderId,
|
|
19390
19894
|
role: input.role,
|
|
19391
19895
|
channel: "whatsapp",
|
|
19392
19896
|
agentSlug: input.agentSlug,
|
|
19393
|
-
text
|
|
19897
|
+
text,
|
|
19394
19898
|
timeoutMs: whatsappTurnTimeoutMs()
|
|
19395
19899
|
});
|
|
19396
19900
|
if ("error" in result) {
|
|
@@ -20183,10 +20687,7 @@ var brandedHtmlCache = /* @__PURE__ */ new Map();
|
|
|
20183
20687
|
function loadBrandingCache(agentSlug) {
|
|
20184
20688
|
const configDir2 = join17(homedir2(), BRAND.configDir);
|
|
20185
20689
|
try {
|
|
20186
|
-
const
|
|
20187
|
-
if (!existsSync23(accountJsonPath)) return null;
|
|
20188
|
-
const account = JSON.parse(readFileSync22(accountJsonPath, "utf-8"));
|
|
20189
|
-
const accountId = account.accountId;
|
|
20690
|
+
const accountId = getDefaultAccountId();
|
|
20190
20691
|
if (!accountId) return null;
|
|
20191
20692
|
const cachePath = join17(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
20192
20693
|
if (!existsSync23(cachePath)) return null;
|
|
@@ -20196,15 +20697,9 @@ function loadBrandingCache(agentSlug) {
|
|
|
20196
20697
|
}
|
|
20197
20698
|
}
|
|
20198
20699
|
function resolveDefaultSlug() {
|
|
20199
|
-
|
|
20200
|
-
|
|
20201
|
-
|
|
20202
|
-
if (!existsSync23(accountJsonPath)) return null;
|
|
20203
|
-
const account = JSON.parse(readFileSync22(accountJsonPath, "utf-8"));
|
|
20204
|
-
return account.defaultAgent || null;
|
|
20205
|
-
} catch {
|
|
20206
|
-
return null;
|
|
20207
|
-
}
|
|
20700
|
+
const account = resolveAccount();
|
|
20701
|
+
if (!account) return null;
|
|
20702
|
+
return resolveDefaultAgentSlug(account.accountDir);
|
|
20208
20703
|
}
|
|
20209
20704
|
function brandedPublicHtml(agentSlug) {
|
|
20210
20705
|
const baseHtml = cachedHtml("public.html");
|
|
@@ -20250,6 +20745,7 @@ app43.get("/", (c) => {
|
|
|
20250
20745
|
503
|
|
20251
20746
|
);
|
|
20252
20747
|
}
|
|
20748
|
+
console.error(`[public-root] op=serve-default slug=${defaultSlug}`);
|
|
20253
20749
|
return c.html(brandedPublicHtml(defaultSlug));
|
|
20254
20750
|
}
|
|
20255
20751
|
return c.html(cachedHtml("index.html"));
|
|
@@ -20530,7 +21026,7 @@ init({
|
|
|
20530
21026
|
platformRoot: resolve26(process.env.MAXY_PLATFORM_ROOT ?? join17(__dirname, "..")),
|
|
20531
21027
|
accountConfig: bootAccountConfig,
|
|
20532
21028
|
onMessage: async (msg) => {
|
|
20533
|
-
if (msg.text && !msg.isOwnerMirror) {
|
|
21029
|
+
if ((msg.text || msg.mediaPath) && !msg.isOwnerMirror) {
|
|
20534
21030
|
try {
|
|
20535
21031
|
void msg.composing().catch(() => {
|
|
20536
21032
|
});
|
|
@@ -20552,6 +21048,9 @@ init({
|
|
|
20552
21048
|
role: msg.agentType,
|
|
20553
21049
|
agentSlug: agentSlugForBridge,
|
|
20554
21050
|
text: msg.text,
|
|
21051
|
+
mediaPath: msg.mediaPath,
|
|
21052
|
+
mediaType: msg.mediaType,
|
|
21053
|
+
mediaMimetype: msg.mediaMimetype,
|
|
20555
21054
|
reply: msg.reply
|
|
20556
21055
|
});
|
|
20557
21056
|
} catch (err) {
|