@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.
Files changed (161) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/.docs/search-surface-contract.md +58 -0
  3. package/payload/platform/lib/embed-client/dist/index.d.ts +4 -0
  4. package/payload/platform/lib/embed-client/dist/index.d.ts.map +1 -0
  5. package/payload/platform/lib/embed-client/dist/index.js +53 -0
  6. package/payload/platform/lib/embed-client/dist/index.js.map +1 -0
  7. package/payload/platform/lib/embed-client/src/index.ts +53 -0
  8. package/payload/platform/lib/embed-client/tsconfig.json +8 -0
  9. package/payload/platform/lib/graph-search/dist/index.d.ts +27 -6
  10. package/payload/platform/lib/graph-search/dist/index.d.ts.map +1 -1
  11. package/payload/platform/lib/graph-search/dist/index.js +19 -1
  12. package/payload/platform/lib/graph-search/dist/index.js.map +1 -1
  13. package/payload/platform/lib/graph-search/src/index.ts +28 -6
  14. package/payload/platform/lib/graph-write/dist/index.d.ts +25 -0
  15. package/payload/platform/lib/graph-write/dist/index.d.ts.map +1 -1
  16. package/payload/platform/lib/graph-write/dist/index.js +78 -2
  17. package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
  18. package/payload/platform/lib/graph-write/src/index.ts +96 -1
  19. package/payload/platform/package.json +2 -2
  20. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
  21. package/payload/platform/plugins/admin/PLUGIN.md +3 -3
  22. package/payload/platform/plugins/admin/hooks/__tests__/{session-end-retrospective.test.sh → insight.test.sh} +152 -153
  23. package/payload/platform/plugins/admin/hooks/insight.sh +219 -0
  24. package/payload/platform/plugins/admin/hooks/lib/admin-graph-pass-common.sh +5 -5
  25. package/payload/platform/plugins/admin/mcp/dist/index.js +33 -19
  26. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  27. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +23 -23
  28. package/payload/platform/plugins/docs/references/graph.md +2 -0
  29. package/payload/platform/plugins/docs/references/internals.md +12 -1
  30. package/payload/platform/plugins/docs/references/neo4j.md +2 -2
  31. package/payload/platform/plugins/docs/references/platform.md +1 -1
  32. package/payload/platform/plugins/docs/references/session-retrospective.md +5 -18
  33. package/payload/platform/plugins/email/PLUGIN.md +2 -2
  34. package/payload/platform/plugins/email/mcp/dist/index.js +8 -0
  35. package/payload/platform/plugins/email/mcp/dist/index.js.map +1 -1
  36. package/payload/platform/plugins/email/mcp/dist/lib/attachment-resolve.d.ts +19 -0
  37. package/payload/platform/plugins/email/mcp/dist/lib/attachment-resolve.d.ts.map +1 -0
  38. package/payload/platform/plugins/email/mcp/dist/lib/attachment-resolve.js +64 -0
  39. package/payload/platform/plugins/email/mcp/dist/lib/attachment-resolve.js.map +1 -0
  40. package/payload/platform/plugins/email/mcp/dist/lib/smtp.d.ts +4 -0
  41. package/payload/platform/plugins/email/mcp/dist/lib/smtp.d.ts.map +1 -1
  42. package/payload/platform/plugins/email/mcp/dist/lib/smtp.js +1 -0
  43. package/payload/platform/plugins/email/mcp/dist/lib/smtp.js.map +1 -1
  44. package/payload/platform/plugins/email/mcp/dist/tools/email-reply.d.ts +1 -0
  45. package/payload/platform/plugins/email/mcp/dist/tools/email-reply.d.ts.map +1 -1
  46. package/payload/platform/plugins/email/mcp/dist/tools/email-reply.js +6 -1
  47. package/payload/platform/plugins/email/mcp/dist/tools/email-reply.js.map +1 -1
  48. package/payload/platform/plugins/email/mcp/dist/tools/email-send.d.ts +1 -0
  49. package/payload/platform/plugins/email/mcp/dist/tools/email-send.d.ts.map +1 -1
  50. package/payload/platform/plugins/email/mcp/dist/tools/email-send.js +7 -1
  51. package/payload/platform/plugins/email/mcp/dist/tools/email-send.js.map +1 -1
  52. package/payload/platform/plugins/email/references/email-reference.md +4 -0
  53. package/payload/platform/plugins/memory/PLUGIN.md +1 -2
  54. package/payload/platform/plugins/memory/mcp/dist/index.js +5 -43
  55. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  56. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/document-sectioniser.test.d.ts +2 -0
  57. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/document-sectioniser.test.d.ts.map +1 -0
  58. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/document-sectioniser.test.js +41 -0
  59. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/document-sectioniser.test.js.map +1 -0
  60. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-embed-net.test.d.ts +2 -0
  61. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-embed-net.test.d.ts.map +1 -0
  62. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-embed-net.test.js +90 -0
  63. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-embed-net.test.js.map +1 -0
  64. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/vector-indexed-labels-drift.test.d.ts +2 -0
  65. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/vector-indexed-labels-drift.test.d.ts.map +1 -0
  66. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/vector-indexed-labels-drift.test.js +27 -0
  67. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/vector-indexed-labels-drift.test.js.map +1 -0
  68. package/payload/platform/plugins/memory/mcp/dist/lib/document-sectioniser.d.ts +10 -0
  69. package/payload/platform/plugins/memory/mcp/dist/lib/document-sectioniser.d.ts.map +1 -0
  70. package/payload/platform/plugins/memory/mcp/dist/lib/document-sectioniser.js +47 -0
  71. package/payload/platform/plugins/memory/mcp/dist/lib/document-sectioniser.js.map +1 -0
  72. package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.d.ts +1 -2
  73. package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.d.ts.map +1 -1
  74. package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.js +5 -28
  75. package/payload/platform/plugins/memory/mcp/dist/lib/embeddings.js.map +1 -1
  76. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/build-text-representation-bound.test.d.ts +2 -0
  77. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/build-text-representation-bound.test.d.ts.map +1 -0
  78. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/build-text-representation-bound.test.js +20 -0
  79. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/build-text-representation-bound.test.js.map +1 -0
  80. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-preference-embed.test.d.ts +2 -0
  81. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-preference-embed.test.d.ts.map +1 -0
  82. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-preference-embed.test.js +67 -0
  83. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-preference-embed.test.js.map +1 -0
  84. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embeddings-cap.test.d.ts +2 -0
  85. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embeddings-cap.test.d.ts.map +1 -0
  86. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embeddings-cap.test.js +34 -0
  87. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/embeddings-cap.test.js.map +1 -0
  88. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-section-writer.test.d.ts +2 -0
  89. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-section-writer.test.d.ts.map +1 -0
  90. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-section-writer.test.js +61 -0
  91. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-section-writer.test.js.map +1 -0
  92. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js +23 -1
  93. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js.map +1 -1
  94. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex.test.d.ts +2 -0
  95. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex.test.d.ts.map +1 -0
  96. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex.test.js +87 -0
  97. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex.test.js.map +1 -0
  98. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.js +3 -0
  99. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.js.map +1 -1
  100. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-threshold.test.d.ts +2 -0
  101. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-threshold.test.d.ts.map +1 -0
  102. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-threshold.test.js +34 -0
  103. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-threshold.test.js.map +1 -0
  104. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.d.ts.map +1 -1
  105. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js +19 -4
  106. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js.map +1 -1
  107. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts +33 -6
  108. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts.map +1 -1
  109. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js +280 -10
  110. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
  111. package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.d.ts.map +1 -1
  112. package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.js +76 -37
  113. package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.js.map +1 -1
  114. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.d.ts.map +1 -1
  115. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js +11 -2
  116. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js.map +1 -1
  117. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts +3 -3
  118. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js +2 -2
  119. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -1
  120. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +10 -2
  121. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
  122. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js +6 -3
  123. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -1
  124. package/payload/platform/plugins/memory/mcp/vitest.config.ts +5 -0
  125. package/payload/platform/plugins/memory/references/schema-base.md +1 -1
  126. package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.d.ts.map +1 -1
  127. package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.js +15 -0
  128. package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.js.map +1 -1
  129. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.js +4 -0
  130. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.js.map +1 -1
  131. package/payload/platform/scripts/identity-forbidden-token-check.mjs +0 -1
  132. package/payload/platform/scripts/setup-account.sh +2 -8
  133. package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.d.ts +23 -0
  134. package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.d.ts.map +1 -0
  135. package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.js +29 -0
  136. package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.js.map +1 -0
  137. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  138. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +0 -1
  139. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  140. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  141. package/payload/platform/services/claude-session-manager/dist/http-server.js +14 -0
  142. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  143. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  144. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +8 -1
  145. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  146. package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.d.ts +13 -1
  147. package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.d.ts.map +1 -1
  148. package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.js +26 -2
  149. package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.js.map +1 -1
  150. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +1 -1
  151. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  152. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts +12 -3
  153. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
  154. package/payload/platform/services/claude-session-manager/dist/system-prompt.js +3 -2
  155. package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
  156. package/payload/platform/templates/agents/admin/IDENTITY.md +2 -2
  157. package/payload/platform/templates/specialists/agents/database-operator.md +2 -6
  158. package/payload/server/{chunk-M6A6EZD4.js → chunk-76HRO7NX.js} +16 -2
  159. package/payload/server/maxy-edge.js +1 -1
  160. package/payload/server/server.js +534 -35
  161. package/payload/platform/plugins/admin/hooks/session-end-retrospective.sh +0 -214
@@ -93,7 +93,7 @@ import {
93
93
  vncLog,
94
94
  walkPremiumBundles,
95
95
  writeAdminUserAndPerson
96
- } from "./chunk-M6A6EZD4.js";
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
- return `${managerBase()}/${sessionId}/log?follow=1`;
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(managerLogFollowUrl(entry.sessionId), {
9048
- signal: abort.signal
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 > MAX_FILE_SIZE_BYTES) {
9610
+ if (fileStat.size > WHATSAPP_DOCUMENT_MAX_BYTES) {
9205
9611
  return {
9206
9612
  ok: false,
9207
9613
  status: 400,
9208
- error: `File exceeds 50 MB limit (${(fileStat.size / 1024 / 1024).toFixed(1)} MB)`
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
- lastDocumentOutboundAt.set(jid, Date.now());
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
- const okAt = documentOutboundAt(entry.senderId);
9285
- if (okAt !== void 0 && okAt >= startedAt) return;
9706
+ failedFiles = [];
9707
+ sendUserFileAttempts = 0;
9708
+ routeCalls = [];
9286
9709
  const sid = entry.sessionId.slice(0, 8);
9287
- for (const tool of firedTools) {
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=${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
- if (labels.length === 0) {
15240
- return c.json({ error: "Select at least one filter chip before searching." }, 400);
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 = !wildcard && labels.some((l) => CONVERSATION_PARENT_LABELS.has(l));
15252
- const forwardedLabels = wildcard ? void 0 : wantsBodyFulltext ? Array.from(/* @__PURE__ */ new Set([...labels, ...MESSAGE_FAMILY_LABELS])) : labels;
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
- if (!input.text.trim()) return;
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: input.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 accountJsonPath = join17(configDir2, "account.json");
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
- try {
20200
- const configDir2 = join17(homedir2(), BRAND.configDir);
20201
- const accountJsonPath = join17(configDir2, "account.json");
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) {