@rubytech/create-realagent 1.0.829 → 1.0.830
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/config/brand.json +1 -1
- package/payload/platform/lib/oauth-llm/dist/index.d.ts +1 -1
- package/payload/platform/lib/oauth-llm/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/oauth-llm/dist/index.js +21 -0
- package/payload/platform/lib/oauth-llm/dist/index.js.map +1 -1
- package/payload/platform/lib/oauth-llm/src/index.ts +24 -0
- package/payload/platform/neo4j/migrations/007-conversation-archive-source.ts +116 -0
- package/payload/platform/neo4j/schema.cypher +12 -3
- package/payload/platform/plugins/admin/hooks/__tests__/archive-ingest-surface-gate.test.sh +54 -39
- package/payload/platform/plugins/admin/hooks/archive-ingest-surface-gate.sh +64 -26
- package/payload/platform/plugins/contacts/mcp/dist/index.js +5 -5
- package/payload/platform/plugins/contacts/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.d.ts +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.d.ts.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js +29 -23
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js.map +1 -1
- package/payload/platform/plugins/docs/references/plugins-guide.md +1 -1
- package/payload/platform/plugins/memory/PLUGIN.md +2 -1
- package/payload/platform/plugins/memory/bin/conversation-archive-ingest.mjs +541 -0
- package/payload/platform/plugins/memory/bin/conversation-archive-ingest.sh +106 -0
- package/payload/platform/plugins/memory/mcp/dist/index.js +30 -16
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/llm-classifier.test.js +4 -3
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/llm-classifier.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.js +11 -6
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.d.ts +5 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.js +30 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.d.ts +48 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.js +23 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/whatsapp-text.d.ts +3 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/whatsapp-text.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/whatsapp-text.js +237 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/whatsapp-text.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/delta-cursor.d.ts +11 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/delta-cursor.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/delta-cursor.js +21 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/delta-cursor.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.d.ts +16 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.js +39 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sender-bind.d.ts +17 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sender-bind.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sender-bind.js +90 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sender-bind.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sessionize.d.ts +9 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sessionize.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sessionize.js +32 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sessionize.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/to-turn-text.d.ts +3 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/to-turn-text.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/to-turn-text.js +27 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/to-turn-text.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/document-chunker.d.ts +45 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/document-chunker.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/document-chunker.js +125 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/document-chunker.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.d.ts +24 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.js +266 -16
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-ranker.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-ranker.js +9 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-ranker.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-source-agnosticism.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-source-agnosticism.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-source-agnosticism.test.js +75 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-source-agnosticism.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-whatsapp-text.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-whatsapp-text.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-whatsapp-text.test.js +67 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-whatsapp-text.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.js +34 -3
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts +17 -0
- 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 +34 -13
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts +18 -7
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +24 -8
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
- package/payload/platform/plugins/memory/references/schema-base.md +2 -2
- package/payload/platform/plugins/memory/skills/conversation-archive/SKILL.md +133 -0
- package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +5 -2
- package/payload/platform/plugins/whatsapp/PLUGIN.md +1 -1
- package/payload/platform/scripts/seed-neo4j.sh +15 -15
- package/payload/platform/templates/specialists/agents/database-operator.md +8 -9
- package/payload/server/chunk-7BO5HDJC.js +10093 -0
- package/payload/server/chunk-EL4DZ56X.js +1116 -0
- package/payload/server/chunk-QOJ2D26Z.js +654 -0
- package/payload/server/chunk-RC46ZYGT.js +2305 -0
- package/payload/server/client-pool-7NTEFNVQ.js +32 -0
- package/payload/server/cloudflare-task-tracker-WE77WXSI.js +19 -0
- package/payload/server/maxy-edge.js +3 -3
- package/payload/server/neo4j-migrations-4XPNJNM6.js +490 -0
- package/payload/server/server.js +6 -6
package/package.json
CHANGED
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"plugins": {
|
|
45
45
|
"core": ["admin", "memory", "docs", "cloudflare", "anthropic", "workflows", "tasks", "business-assistant", "contacts", "scheduling", "email"],
|
|
46
46
|
"defaultEnabled": ["sales"],
|
|
47
|
-
"available": ["deep-research", "waitlist", "projects", "whatsapp", "replicate", "linkedin-import"
|
|
47
|
+
"available": ["deep-research", "waitlist", "projects", "whatsapp", "replicate", "linkedin-import"],
|
|
48
48
|
"excluded": ["telegram"]
|
|
49
49
|
}
|
|
50
50
|
}
|
|
@@ -83,7 +83,7 @@ export interface CallOauthLlmFallback {
|
|
|
83
83
|
/** Human-readable single-line reason (for operator-visible blocker). */
|
|
84
84
|
reason: string;
|
|
85
85
|
/** Stable classifier — callers can pattern-match for retry/abort policy. */
|
|
86
|
-
cause: "missing-creds" | "dead-token" | "refresh-failed" | "auth-error" | "rate-limit" | "server-error" | "network-error" | "timeout" | "empty-response" | "malformed-response" | "unexpected";
|
|
86
|
+
cause: "missing-creds" | "dead-token" | "refresh-failed" | "auth-error" | "rate-limit" | "server-error" | "network-error" | "timeout" | "empty-response" | "malformed-response" | "input-too-large" | "unexpected";
|
|
87
87
|
}
|
|
88
88
|
/**
|
|
89
89
|
* Call an Anthropic model via OAuth bearer auth.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAgBH,QAAA,MAAM,iBAAiB,qBAAqB,CAAC;AAe7C,sFAAsF;AACtF,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,kBAAkB;IACjC,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;OAUG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC;IACvB,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,6EAA6E;AAC7E,MAAM,MAAM,sBAAsB,GAC9B;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC5B,oBAAoB,CAAC;AAEzB,4EAA4E;AAC5E,MAAM,MAAM,sBAAsB,GAC9B;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GACrE,oBAAoB,CAAC;AAEzB,sFAAsF;AACtF,MAAM,MAAM,kBAAkB,GAAG,sBAAsB,GAAG,sBAAsB,CAAC;AAEjF,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,UAAU,CAAC;IACjB,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,KAAK,EACD,eAAe,GACf,YAAY,GACZ,gBAAgB,GAChB,YAAY,GACZ,YAAY,GACZ,cAAc,GACd,eAAe,GACf,SAAS,GACT,gBAAgB,GAChB,oBAAoB,GACpB,YAAY,CAAC;CAClB;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAgBH,QAAA,MAAM,iBAAiB,qBAAqB,CAAC;AAe7C,sFAAsF;AACtF,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,kBAAkB;IACjC,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;OAUG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC;IACvB,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,6EAA6E;AAC7E,MAAM,MAAM,sBAAsB,GAC9B;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC5B,oBAAoB,CAAC;AAEzB,4EAA4E;AAC5E,MAAM,MAAM,sBAAsB,GAC9B;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GACrE,oBAAoB,CAAC;AAEzB,sFAAsF;AACtF,MAAM,MAAM,kBAAkB,GAAG,sBAAsB,GAAG,sBAAsB,CAAC;AAEjF,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,UAAU,CAAC;IACjB,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,KAAK,EACD,eAAe,GACf,YAAY,GACZ,gBAAgB,GAChB,YAAY,GACZ,YAAY,GACZ,cAAc,GACd,eAAe,GACf,SAAS,GACT,gBAAgB,GAChB,oBAAoB,GACpB,iBAAiB,GACjB,YAAY,CAAC;CAClB;AAuOD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,IAAI,CAAC,kBAAkB,EAAE,OAAO,GAAG,gBAAgB,CAAC,GAC3D,OAAO,CAAC,sBAAsB,CAAC,CAAC;AACnC,wBAAgB,YAAY,CAC1B,MAAM,EAAE,kBAAkB,GAAG;IAAE,KAAK,EAAE,YAAY,EAAE,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GAC7E,OAAO,CAAC,sBAAsB,CAAC,CAAC;AACnC,wBAAgB,YAAY,CAC1B,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,kBAAkB,CAAC,CAAC;AA+K/B,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -47,6 +47,20 @@ const OAUTH_BETA_HEADER = "oauth-2025-04-20";
|
|
|
47
47
|
exports.OAUTH_BETA_HEADER = OAUTH_BETA_HEADER;
|
|
48
48
|
/** Refresh proactively when the token expires within this window. */
|
|
49
49
|
const EXPIRING_THRESHOLD_MS = 5 * 60 * 1000;
|
|
50
|
+
// Anthropic's 400 response carries a JSON body whose `error.message` names the
|
|
51
|
+
// failure. The three phrases below are the load-bearing markers for an oversize
|
|
52
|
+
// input across the SDK's vocabulary; matching any one promotes the generic
|
|
53
|
+
// status=400 into a typed cause callers can act on (chunk, defer, surface
|
|
54
|
+
// remediation). Generic 400s still fall through to cause:"unexpected".
|
|
55
|
+
const INPUT_TOO_LARGE_MARKERS = [
|
|
56
|
+
"prompt is too long",
|
|
57
|
+
"context_length_exceeded",
|
|
58
|
+
"too many tokens",
|
|
59
|
+
];
|
|
60
|
+
function isInputTooLargeBody(body) {
|
|
61
|
+
const lower = body.toLowerCase();
|
|
62
|
+
return INPUT_TOO_LARGE_MARKERS.some((m) => lower.includes(m));
|
|
63
|
+
}
|
|
50
64
|
// ---------------------------------------------------------------------------
|
|
51
65
|
// Credential reading + refresh — minimal duplicate of platform/ui claude-auth.
|
|
52
66
|
// We duplicate (not import) so this lib stays self-contained and importable
|
|
@@ -294,6 +308,13 @@ async function callOauthLlm(params) {
|
|
|
294
308
|
reason: `Anthropic server error (status=${res.status}): ${body.slice(0, 200)}`,
|
|
295
309
|
};
|
|
296
310
|
}
|
|
311
|
+
if (res.status === 400 && isInputTooLargeBody(body)) {
|
|
312
|
+
return {
|
|
313
|
+
kind: "fallback",
|
|
314
|
+
cause: "input-too-large",
|
|
315
|
+
reason: `Input exceeds Haiku context window (status=400 body=${body.slice(0, 200)}). Split the source into smaller segments.`,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
297
318
|
return {
|
|
298
319
|
kind: "fallback",
|
|
299
320
|
cause: "unexpected",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -125,9 +125,26 @@ export interface CallOauthLlmFallback {
|
|
|
125
125
|
| "timeout"
|
|
126
126
|
| "empty-response"
|
|
127
127
|
| "malformed-response"
|
|
128
|
+
| "input-too-large"
|
|
128
129
|
| "unexpected";
|
|
129
130
|
}
|
|
130
131
|
|
|
132
|
+
// Anthropic's 400 response carries a JSON body whose `error.message` names the
|
|
133
|
+
// failure. The three phrases below are the load-bearing markers for an oversize
|
|
134
|
+
// input across the SDK's vocabulary; matching any one promotes the generic
|
|
135
|
+
// status=400 into a typed cause callers can act on (chunk, defer, surface
|
|
136
|
+
// remediation). Generic 400s still fall through to cause:"unexpected".
|
|
137
|
+
const INPUT_TOO_LARGE_MARKERS = [
|
|
138
|
+
"prompt is too long",
|
|
139
|
+
"context_length_exceeded",
|
|
140
|
+
"too many tokens",
|
|
141
|
+
] as const;
|
|
142
|
+
|
|
143
|
+
function isInputTooLargeBody(body: string): boolean {
|
|
144
|
+
const lower = body.toLowerCase();
|
|
145
|
+
return INPUT_TOO_LARGE_MARKERS.some((m) => lower.includes(m));
|
|
146
|
+
}
|
|
147
|
+
|
|
131
148
|
// ---------------------------------------------------------------------------
|
|
132
149
|
// Credential reading + refresh — minimal duplicate of platform/ui claude-auth.
|
|
133
150
|
// We duplicate (not import) so this lib stays self-contained and importable
|
|
@@ -465,6 +482,13 @@ export async function callOauthLlm(
|
|
|
465
482
|
reason: `Anthropic server error (status=${res.status}): ${body.slice(0, 200)}`,
|
|
466
483
|
};
|
|
467
484
|
}
|
|
485
|
+
if (res.status === 400 && isInputTooLargeBody(body)) {
|
|
486
|
+
return {
|
|
487
|
+
kind: "fallback",
|
|
488
|
+
cause: "input-too-large",
|
|
489
|
+
reason: `Input exceeds Haiku context window (status=400 body=${body.slice(0, 200)}). Split the source into smaller segments.`,
|
|
490
|
+
};
|
|
491
|
+
}
|
|
468
492
|
return {
|
|
469
493
|
kind: "fallback",
|
|
470
494
|
cause: "unexpected",
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration 007 — Backfill `source` and rename provenance on existing
|
|
3
|
+
* :ConversationArchive parents and :Section:Conversation chunks (Task 894).
|
|
4
|
+
*
|
|
5
|
+
* Pre-Task-894 the conversation-archive write path stamped every node with
|
|
6
|
+
* `createdByAgent = 'whatsapp-import'` and `source = 'whatsapp'`. Task 894
|
|
7
|
+
* generalises the path: `createdByAgent` becomes `'conversation-archive'`
|
|
8
|
+
* (one orchestrator, one skill, regardless of source); `source` is a property
|
|
9
|
+
* carrying the source format ('whatsapp', 'telegram', 'slack', …).
|
|
10
|
+
*
|
|
11
|
+
* Without this migration the diagnostic surface fragments — queries that
|
|
12
|
+
* filter by createdByAgent return only post-894 data; the new
|
|
13
|
+
* (accountId, source) index is empty for legacy archives. This migration
|
|
14
|
+
* rewrites both sides idempotently:
|
|
15
|
+
*
|
|
16
|
+
* 1. :ConversationArchive without `source` → SET source='whatsapp'
|
|
17
|
+
* (every pre-894 archive came from the whatsapp-import bin script).
|
|
18
|
+
* 2. :ConversationArchive.createdByAgent='whatsapp-import' →
|
|
19
|
+
* SET createdByAgent='conversation-archive'.
|
|
20
|
+
* 3. :Section:Conversation without `source` → SET source='whatsapp'.
|
|
21
|
+
* 4. :Section:Conversation.createdByAgent='whatsapp-import' →
|
|
22
|
+
* SET createdByAgent='conversation-archive'.
|
|
23
|
+
* 5. :HAS_SECTION / :NEXT / :PARTICIPANT_IN edges with
|
|
24
|
+
* createdByAgent='whatsapp-import' → SET createdByAgent='conversation-archive'.
|
|
25
|
+
*
|
|
26
|
+
* Re-runs are no-ops (each WHERE clause excludes the post-rename state).
|
|
27
|
+
*
|
|
28
|
+
* Observability:
|
|
29
|
+
* `[migration:conversation-archive-source]
|
|
30
|
+
* archives-source-set=N archives-agent-renamed=N
|
|
31
|
+
* chunks-source-set=N chunks-agent-renamed=N edges-agent-renamed=N`
|
|
32
|
+
*
|
|
33
|
+
* REMOVE WHEN: every install we ship has been booted once on a version
|
|
34
|
+
* ≥ Task 894 AND no live archive carries the legacy provenance string.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
type Neo4jDriverLike = {
|
|
38
|
+
session(): {
|
|
39
|
+
run(
|
|
40
|
+
cypher: string,
|
|
41
|
+
params?: Record<string, unknown>,
|
|
42
|
+
): Promise<{ records: Array<{ get(key: string): unknown }> }>;
|
|
43
|
+
close(): Promise<void>;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export async function backfillConversationArchiveSource(
|
|
48
|
+
driver: Neo4jDriverLike,
|
|
49
|
+
): Promise<void> {
|
|
50
|
+
const session = driver.session();
|
|
51
|
+
try {
|
|
52
|
+
const archivesSourceSet = await runCount(
|
|
53
|
+
session,
|
|
54
|
+
`MATCH (a:ConversationArchive)
|
|
55
|
+
WHERE a.source IS NULL
|
|
56
|
+
SET a.source = 'whatsapp'
|
|
57
|
+
RETURN count(a) AS n`,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const archivesAgentRenamed = await runCount(
|
|
61
|
+
session,
|
|
62
|
+
`MATCH (a:ConversationArchive)
|
|
63
|
+
WHERE a.createdByAgent = 'whatsapp-import'
|
|
64
|
+
SET a.createdByAgent = 'conversation-archive'
|
|
65
|
+
RETURN count(a) AS n`,
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const chunksSourceSet = await runCount(
|
|
69
|
+
session,
|
|
70
|
+
`MATCH (c:Section:Conversation)
|
|
71
|
+
WHERE c.source IS NULL
|
|
72
|
+
SET c.source = 'whatsapp'
|
|
73
|
+
RETURN count(c) AS n`,
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
const chunksAgentRenamed = await runCount(
|
|
77
|
+
session,
|
|
78
|
+
`MATCH (c:Section:Conversation)
|
|
79
|
+
WHERE c.createdByAgent = 'whatsapp-import'
|
|
80
|
+
SET c.createdByAgent = 'conversation-archive'
|
|
81
|
+
RETURN count(c) AS n`,
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const edgesAgentRenamed = await runCount(
|
|
85
|
+
session,
|
|
86
|
+
`MATCH (a:ConversationArchive)-[r]-()
|
|
87
|
+
WHERE r.createdByAgent = 'whatsapp-import'
|
|
88
|
+
SET r.createdByAgent = 'conversation-archive'
|
|
89
|
+
RETURN count(r) AS n`,
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
console.error(
|
|
93
|
+
`[migration:conversation-archive-source] ` +
|
|
94
|
+
`archives-source-set=${archivesSourceSet} ` +
|
|
95
|
+
`archives-agent-renamed=${archivesAgentRenamed} ` +
|
|
96
|
+
`chunks-source-set=${chunksSourceSet} ` +
|
|
97
|
+
`chunks-agent-renamed=${chunksAgentRenamed} ` +
|
|
98
|
+
`edges-agent-renamed=${edgesAgentRenamed}`,
|
|
99
|
+
);
|
|
100
|
+
} finally {
|
|
101
|
+
await session.close();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function runCount(
|
|
106
|
+
session: { run(c: string, p?: Record<string, unknown>): Promise<{ records: Array<{ get(k: string): unknown }> }> },
|
|
107
|
+
cypher: string,
|
|
108
|
+
): Promise<number> {
|
|
109
|
+
const res = await session.run(cypher);
|
|
110
|
+
const v = res.records[0]?.get("n");
|
|
111
|
+
if (typeof v === "number") return v;
|
|
112
|
+
if (v && typeof (v as { toNumber?: () => number }).toNumber === "function") {
|
|
113
|
+
return (v as { toNumber: () => number }).toNumber();
|
|
114
|
+
}
|
|
115
|
+
return 0;
|
|
116
|
+
}
|
|
@@ -259,7 +259,10 @@ OPTIONS {
|
|
|
259
259
|
};
|
|
260
260
|
|
|
261
261
|
// ----------------------------------------------------------
|
|
262
|
-
// ConversationArchive — chunked
|
|
262
|
+
// ConversationArchive — chunked conversation archive (Task 894 generalises
|
|
263
|
+
// Task 891). Source-agnostic: WhatsApp `_chat.txt`, Telegram, Signal,
|
|
264
|
+
// LinkedIn DMs, Zoom transcript, meeting minutes, iMessage, Slack — every
|
|
265
|
+
// source flows through the same shape with `source` as the discriminator.
|
|
263
266
|
//
|
|
264
267
|
// :ConversationArchive parent + :Section:Conversation chunks (HAS_SECTION + NEXT chain).
|
|
265
268
|
// MERGE-keyed on conversationIdentity = sha256(accountId + ":" + sortedParticipantElementIds).
|
|
@@ -269,8 +272,11 @@ OPTIONS {
|
|
|
269
272
|
//
|
|
270
273
|
// :PARTICIPANT_IN edges from :Person/:AdminUser to :ConversationArchive are
|
|
271
274
|
// MERGEd on every ingest (idempotent); the operator confirms each participant
|
|
272
|
-
// up front via the
|
|
273
|
-
//
|
|
275
|
+
// up front via the conversation-archive skill flow.
|
|
276
|
+
//
|
|
277
|
+
// `source` is a closed enum ('whatsapp' | 'telegram' | 'signal' |
|
|
278
|
+
// 'linkedin-messages' | 'zoom-transcript' | 'meeting-minutes' | 'imessage' |
|
|
279
|
+
// 'slack' | 'other') — see `conversation-normalisers/types.ts`.
|
|
274
280
|
// ----------------------------------------------------------
|
|
275
281
|
|
|
276
282
|
CREATE CONSTRAINT conversation_archive_identity_unique IF NOT EXISTS
|
|
@@ -282,6 +288,9 @@ FOR (a:ConversationArchive) ON (a.accountId);
|
|
|
282
288
|
CREATE INDEX conversation_archive_session IF NOT EXISTS
|
|
283
289
|
FOR (a:ConversationArchive) ON (a.createdBySession);
|
|
284
290
|
|
|
291
|
+
CREATE INDEX conversation_archive_account_source IF NOT EXISTS
|
|
292
|
+
FOR (a:ConversationArchive) ON (a.accountId, a.source);
|
|
293
|
+
|
|
285
294
|
CREATE VECTOR INDEX conversation_archive_embedding IF NOT EXISTS
|
|
286
295
|
FOR (a:ConversationArchive) ON (a.embedding)
|
|
287
296
|
OPTIONS {
|
|
@@ -1,30 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Regression test for archive-ingest-surface-gate.sh (Task 855
|
|
2
|
+
# Regression test for archive-ingest-surface-gate.sh (Task 855).
|
|
3
3
|
#
|
|
4
|
-
# Covers
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
# - memory-archive-write archiveType='whatsapp-export' block (the enum value
|
|
22
|
-
# was dropped from memory-archive-write).
|
|
23
|
-
#
|
|
24
|
-
# A generic LinkedIn-shaped fixture stands in for the parse-error lifecycle —
|
|
25
|
-
# the gate's PostToolUse pattern matches `mcp__*__*-export-parse` /
|
|
26
|
-
# `mcp__*__*-import-parse`, so any plausible parser tool name exercises the
|
|
27
|
-
# flag-set / flag-clear path.
|
|
4
|
+
# Covers:
|
|
5
|
+
# Preserved-from-Task-846:
|
|
6
|
+
# 1. Edit on /platform/plugins/<x>/lib/* → BLOCKED
|
|
7
|
+
# 2. Edit on benign path → ALLOWED
|
|
8
|
+
# 3. Bash with `npx vitest`/`bun test`/`npm test` → BLOCKED
|
|
9
|
+
# 4. PostToolUse on whatsapp-export-parse with isError:true sets flag
|
|
10
|
+
# 5. Subsequent PreToolUse on ANY tool → BLOCKED
|
|
11
|
+
# 6. UserPromptSubmit clears flag → normal allow resumes
|
|
12
|
+
# 7. PostToolUse with isError:false → flag absent
|
|
13
|
+
# 8. Stale flag (>600s) auto-clears
|
|
14
|
+
# New (Task 855):
|
|
15
|
+
# A. PreToolUse mcp__memory__whatsapp-export-parse → BLOCKED
|
|
16
|
+
# B. PreToolUse mcp__memory__whatsapp-export-insight-write → BLOCKED
|
|
17
|
+
# C. PreToolUse mcp__memory__memory-archive-write w/ archiveType=whatsapp-export → BLOCKED
|
|
18
|
+
# D. PreToolUse mcp__memory__memory-archive-write w/ archiveType=linkedin-connections → ALLOWED
|
|
19
|
+
# E. PreToolUse Bash invoking conversation-archive-ingest.sh → ALLOWED
|
|
20
|
+
# F. Default-allow emits a [archive-ingest-gate] decision=allow log line
|
|
28
21
|
|
|
29
22
|
set -u
|
|
30
23
|
|
|
@@ -58,20 +51,18 @@ run_case() {
|
|
|
58
51
|
fi
|
|
59
52
|
}
|
|
60
53
|
|
|
61
|
-
#
|
|
54
|
+
# Preserved cases ---------------------------------------------------------
|
|
62
55
|
|
|
63
|
-
run_case "Edit on platform/plugins/
|
|
64
|
-
'{"hook_event_name":"PreToolUse","tool_name":"Edit","tool_input":{"file_path":"/Users/x/repo/platform/plugins/
|
|
56
|
+
run_case "Edit on platform/plugins/memory/mcp/src/lib/conversation-normalisers/whatsapp-text.ts → BLOCKED" \
|
|
57
|
+
'{"hook_event_name":"PreToolUse","tool_name":"Edit","tool_input":{"file_path":"/Users/x/repo/platform/plugins/memory/mcp/src/lib/conversation-normalisers/whatsapp-text.ts","old_string":"a","new_string":"b"}}' \
|
|
65
58
|
2
|
|
66
59
|
|
|
67
60
|
run_case "Edit on README.md → ALLOWED" \
|
|
68
61
|
'{"hook_event_name":"PreToolUse","tool_name":"Edit","tool_input":{"file_path":"/Users/x/repo/README.md","old_string":"a","new_string":"b"}}' \
|
|
69
62
|
0
|
|
70
63
|
|
|
71
|
-
# Test-runner block (Bash) ------------------------------------------------
|
|
72
|
-
|
|
73
64
|
run_case "Bash 'npx vitest run' → BLOCKED" \
|
|
74
|
-
'{"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"npx vitest run
|
|
65
|
+
'{"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"npx vitest run parse-export.test.ts"}}' \
|
|
75
66
|
2
|
|
76
67
|
|
|
77
68
|
run_case "Bash 'ls -la' → ALLOWED" \
|
|
@@ -86,18 +77,45 @@ run_case "Bash 'npm test' → BLOCKED" \
|
|
|
86
77
|
'{"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"npm test"}}' \
|
|
87
78
|
2
|
|
88
79
|
|
|
89
|
-
#
|
|
80
|
+
# New (Task 855) cases ----------------------------------------------------
|
|
81
|
+
|
|
82
|
+
run_case "PreToolUse mcp__memory__whatsapp-export-parse → BLOCKED" \
|
|
83
|
+
'{"hook_event_name":"PreToolUse","tool_name":"mcp__memory__whatsapp-export-parse","tool_input":{"filePath":"/tmp/_chat.txt","accountId":"acct1","timezone":"Europe/London"}}' \
|
|
84
|
+
2
|
|
85
|
+
|
|
86
|
+
run_case "PreToolUse mcp__memory__whatsapp-export-insight-write → BLOCKED" \
|
|
87
|
+
'{"hook_event_name":"PreToolUse","tool_name":"mcp__memory__whatsapp-export-insight-write","tool_input":{"kind":"MENTIONS","name":"Joel"}}' \
|
|
88
|
+
2
|
|
89
|
+
|
|
90
|
+
run_case "PreToolUse memory-archive-write w/ archiveType=whatsapp-export → BLOCKED" \
|
|
91
|
+
'{"hook_event_name":"PreToolUse","tool_name":"mcp__memory__memory-archive-write","tool_input":{"archiveType":"whatsapp-export","ownerNodeId":"x","accountId":"a","rows":[]}}' \
|
|
92
|
+
2
|
|
90
93
|
|
|
91
94
|
run_case "PreToolUse memory-archive-write w/ archiveType=linkedin-connections → ALLOWED" \
|
|
92
95
|
'{"hook_event_name":"PreToolUse","tool_name":"mcp__memory__memory-archive-write","tool_input":{"archiveType":"linkedin-connections","ownerNodeId":"x","accountId":"a","rows":[]}}' \
|
|
93
96
|
0
|
|
94
97
|
|
|
98
|
+
# Bypass attempts (Task 855 code-review C1): nested archiveType in rows[0]
|
|
99
|
+
# or conversation must NOT defeat the block. The gate must read the
|
|
100
|
+
# top-level tool_input.archiveType, not the first textual occurrence.
|
|
101
|
+
run_case "BYPASS: nested rows[0].archiveType=linkedin + top-level archiveType=whatsapp-export → BLOCKED" \
|
|
102
|
+
'{"hook_event_name":"PreToolUse","tool_name":"mcp__memory__memory-archive-write","tool_input":{"rows":[{"archiveType":"linkedin-connections"}],"archiveType":"whatsapp-export","ownerNodeId":"x","accountId":"a"}}' \
|
|
103
|
+
2
|
|
104
|
+
|
|
105
|
+
run_case "BYPASS: conversation.archiveType=linkedin + top-level archiveType=whatsapp-export → BLOCKED" \
|
|
106
|
+
'{"hook_event_name":"PreToolUse","tool_name":"mcp__memory__memory-archive-write","tool_input":{"conversation":{"archiveType":"linkedin-connections","conversationId":"x"},"archiveType":"whatsapp-export","ownerNodeId":"x","accountId":"a","rows":[]}}' \
|
|
107
|
+
2
|
|
108
|
+
|
|
95
109
|
# Plugin-source-edit path block must read tool_input.file_path top-level,
|
|
96
110
|
# not a nested file_path in old_string/new_string.
|
|
97
111
|
run_case "BYPASS: nested file_path in old_string + top-level file_path in lib/* → BLOCKED" \
|
|
98
|
-
'{"hook_event_name":"PreToolUse","tool_name":"Edit","tool_input":{"file_path":"/repo/platform/plugins/
|
|
112
|
+
'{"hook_event_name":"PreToolUse","tool_name":"Edit","tool_input":{"file_path":"/repo/platform/plugins/memory/mcp/src/lib/conversation-normalisers/whatsapp-text.ts","old_string":"file_path:/safe/path","new_string":"x"}}' \
|
|
99
113
|
2
|
|
100
114
|
|
|
115
|
+
run_case "PreToolUse Bash invoking conversation-archive-ingest.sh → ALLOWED" \
|
|
116
|
+
'{"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"bash platform/plugins/memory/bin/conversation-archive-ingest.sh /tmp/chat.zip --source whatsapp --owner-element-id 4:abc:1 --participant-person-ids 4:abc:2 --scope admin"}}' \
|
|
117
|
+
0
|
|
118
|
+
|
|
101
119
|
# Default-allow log-line check
|
|
102
120
|
LOG=$(printf '%s' '{"hook_event_name":"PreToolUse","tool_name":"Read","tool_input":{"file_path":"/tmp/foo"}}' | bash "$HOOK" 2>&1 1>/dev/null)
|
|
103
121
|
if printf '%s' "$LOG" | grep -q '\[archive-ingest-gate\] decision=allow tool=Read reason=default'; then
|
|
@@ -118,13 +136,10 @@ else
|
|
|
118
136
|
FAIL=$((FAIL + 1))
|
|
119
137
|
fi
|
|
120
138
|
|
|
121
|
-
# Parse-error flag lifecycle (preserved)
|
|
122
|
-
# `mcp__*__*-export-parse` / `mcp__*__*-import-parse` — exercise via the
|
|
123
|
-
# linkedin-import-parse name (synthetic — the linkedin importer currently
|
|
124
|
-
# uses memory-archive-write, but the gate matches by tool name shape).
|
|
139
|
+
# Parse-error flag lifecycle (preserved)
|
|
125
140
|
rm -f "$FLAG_FILE"
|
|
126
141
|
run_case "PostToolUse parse-error sets flag (exit 0)" \
|
|
127
|
-
'{"hook_event_name":"PostToolUse","tool_name":"
|
|
142
|
+
'{"hook_event_name":"PostToolUse","tool_name":"mcp__memory__whatsapp-export-parse","tool_input":{"filePath":"_chat.txt"},"tool_response":{"isError":true,"content":[{"type":"text","text":"parse-error file=_chat.txt line=1 reason=not-a-_chat.txt"}]}}' \
|
|
128
143
|
0
|
|
129
144
|
[[ -f "$FLAG_FILE" ]] && { echo "PASS: parse-error flag created"; PASS=$((PASS+1)); } \
|
|
130
145
|
|| { echo "FAIL: parse-error flag NOT created" >&2; FAIL=$((FAIL+1)); }
|
|
@@ -153,7 +168,7 @@ run_case "Stale flag auto-clears, PreToolUse Read → ALLOWED" \
|
|
|
153
168
|
# PostToolUse parse-success leaves flag absent
|
|
154
169
|
rm -f "$FLAG_FILE"
|
|
155
170
|
run_case "PostToolUse parse-success (isError:false) does NOT set flag" \
|
|
156
|
-
'{"hook_event_name":"PostToolUse","tool_name":"
|
|
171
|
+
'{"hook_event_name":"PostToolUse","tool_name":"mcp__memory__whatsapp-export-parse","tool_input":{"filePath":"_chat.txt"},"tool_response":{"isError":false,"content":[{"type":"text","text":"{\"parsedLines\":[]}"}]}}' \
|
|
157
172
|
0
|
|
158
173
|
[[ ! -f "$FLAG_FILE" ]] && { echo "PASS: parse-success leaves flag absent"; PASS=$((PASS+1)); } \
|
|
159
174
|
|| { echo "FAIL: parse-success incorrectly created flag" >&2; FAIL=$((FAIL+1)); }
|
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Archive-ingest surface gate (Task 855, updated by Task 891
|
|
2
|
+
# Archive-ingest surface gate (Task 855, updated by Task 891).
|
|
3
3
|
#
|
|
4
|
-
#
|
|
5
|
-
# Task 855
|
|
6
|
-
# archive ingestion
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
# future flat-dataset archive types that ship per-source parsers.
|
|
4
|
+
# Five enforcements, one script — phase decided by `hook_event_name` on stdin.
|
|
5
|
+
# Task 855 narrows the database-operator subagent's effective surface during
|
|
6
|
+
# WhatsApp archive ingestion to exactly one Bash entry
|
|
7
|
+
# (`memory/bin/conversation-archive-ingest.sh`) plus read-only neighbours, by
|
|
8
|
+
# blocking the legacy MCP deviation tools mechanically. Task 891 retired the
|
|
9
|
+
# `whatsapp-export-insight-pass` tool entirely (Phase 2 enrichment moved to a
|
|
10
|
+
# separate follow-up task that will operate on :Section:Conversation chunks);
|
|
11
|
+
# the tool name is added to the BLOCK list so any agent that still references
|
|
12
|
+
# it from a stale skill or runbook gets a loud denial instead of MCP-not-found.
|
|
14
13
|
#
|
|
15
|
-
# 1.
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
14
|
+
# 1. PreToolUse on the four legacy WhatsApp MCP tools — BLOCK unconditionally.
|
|
15
|
+
# The single deterministic Bash entry is the only supported path for
|
|
16
|
+
# `archiveType=whatsapp-export`. Tool source for #1-#3 remains until cleanup;
|
|
17
|
+
# `whatsapp-export-insight-pass` source was deleted by Task 891 and the
|
|
18
|
+
# block here catches stale references.
|
|
19
|
+
# mcp__memory__whatsapp-export-parse
|
|
20
|
+
# mcp__memory__whatsapp-export-insight-write
|
|
21
|
+
# mcp__memory__whatsapp-export-insight-pass (Task 891 — deleted, retired)
|
|
22
|
+
# mcp__memory__memory-archive-write (only when `archiveType` is
|
|
23
|
+
# `whatsapp-export`; LinkedIn
|
|
24
|
+
# and other archiveTypes pass
|
|
25
|
+
# through unchanged.)
|
|
22
26
|
#
|
|
23
27
|
# 2. PreToolUse Edit/Write/NotebookEdit: deny writes under
|
|
24
28
|
# `*platform/plugins/*/lib/*` (parser/CSV-shape source for any *-import or
|
|
@@ -28,10 +32,18 @@
|
|
|
28
32
|
# 3. PreToolUse Bash: deny commands invoking JavaScript test runners
|
|
29
33
|
# (vitest|bun test|npm test|npx jest|node .*vitest). Preserved from Task 846.
|
|
30
34
|
#
|
|
31
|
-
# 4.
|
|
35
|
+
# 4. Parse-error gate: PostToolUse on any `mcp__*__*-export-parse` /
|
|
36
|
+
# `mcp__*__*-import-parse` tool whose `tool_response.isError == true`
|
|
37
|
+
# writes a flag file. Subsequent PreToolUse on ANY tool blocks until
|
|
38
|
+
# UserPromptSubmit clears the flag. A 600s TTL is the cross-session safety
|
|
39
|
+
# net. Preserved from Task 846 because LinkedIn and future per-source archive
|
|
40
|
+
# parsers still use the legacy MCP path until they migrate to their own
|
|
41
|
+
# deterministic Bash entries.
|
|
42
|
+
#
|
|
43
|
+
# 5. Logging: every PreToolUse decision emits one line in the format
|
|
32
44
|
# [archive-ingest-gate] decision=<allow|block> tool=<name> reason=<r> ...
|
|
33
45
|
# so the operator can grep the full decision trail for one ingest from
|
|
34
|
-
# server.log.
|
|
46
|
+
# server.log alongside the [whatsapp-ingest] script lines.
|
|
35
47
|
#
|
|
36
48
|
# Exit codes follow Claude Code hook protocol: 0 = allow, 2 = block (stderr
|
|
37
49
|
# message shown to the agent). Fail-closed on terminal stdin to match
|
|
@@ -128,12 +140,25 @@ if [ -f "$FLAG_FILE" ]; then
|
|
|
128
140
|
fi
|
|
129
141
|
fi
|
|
130
142
|
|
|
143
|
+
# --- Block 2: legacy WhatsApp MCP tools — defensive denial ----------------
|
|
144
|
+
# These tool sources were deleted by Task 894; the block stays as a stale-
|
|
145
|
+
# reference catch (skill markdown checked into older installs may still name
|
|
146
|
+
# them). The harness will return tool-not-found anyway, but a named block
|
|
147
|
+
# message guides the operator to the new entry.
|
|
148
|
+
case "$TOOL_NAME" in
|
|
149
|
+
mcp__memory__whatsapp-export-parse|mcp__memory__whatsapp-export-insight-write|mcp__memory__whatsapp-export-insight-pass|mcp__memory__whatsapp-export-preview)
|
|
150
|
+
emit_decision "block" "denied-mcp-legacy" \
|
|
151
|
+
"Blocked: ${TOOL_NAME} is a retired path. Task 894 generalised conversation-archive ingest — invoke 'bash platform/plugins/memory/bin/conversation-archive-ingest.sh <archive> --source whatsapp --owner-element-id <id> --participant-person-ids <csv> --scope <admin|public>' once. Normalise, sessionize, classify (mode=chat), and memory-ingest (parentLabel=ConversationArchive, source=<enum>) all run in-process."
|
|
152
|
+
;;
|
|
153
|
+
esac
|
|
154
|
+
|
|
131
155
|
# Helper: extract a top-level field from `tool_input` via python3 — never via
|
|
132
156
|
# grep+sed against the raw JSON, which would pick the first textual occurrence
|
|
133
|
-
# including nested-object matches (`rows[0].archiveType`,
|
|
134
|
-
#
|
|
135
|
-
# JSON-aware hook parsing
|
|
136
|
-
#
|
|
157
|
+
# including nested-object matches (`rows[0].archiveType`,
|
|
158
|
+
# `conversation.archiveType`, etc.) and let a malicious payload bypass the
|
|
159
|
+
# block. python3 is the project standard for JSON-aware hook parsing
|
|
160
|
+
# (mirrors lane-gate.sh:31-46). On parse failure return empty string —
|
|
161
|
+
# downstream block conditions skip cleanly.
|
|
137
162
|
extract_tool_input_field() {
|
|
138
163
|
local field="$1"
|
|
139
164
|
printf '%s' "$INPUT" | python3 -c "
|
|
@@ -146,7 +171,20 @@ except Exception:
|
|
|
146
171
|
" 2>/dev/null || echo ""
|
|
147
172
|
}
|
|
148
173
|
|
|
149
|
-
# --- Block
|
|
174
|
+
# --- Block 3: memory-archive-write conditional on conversation-shaped types
|
|
175
|
+
# LinkedIn-connections and future flat-dataset archiveTypes flow unchanged.
|
|
176
|
+
# `whatsapp-export` was the only conversation-shaped archiveType; Task 894
|
|
177
|
+
# deleted that handler entirely, so the type itself is now invalid input —
|
|
178
|
+
# the block stays defensive against operator-edited skills that still name it.
|
|
179
|
+
if [ "$TOOL_NAME" = "mcp__memory__memory-archive-write" ]; then
|
|
180
|
+
ARCHIVE_TYPE=$(extract_tool_input_field archiveType)
|
|
181
|
+
if [ "$ARCHIVE_TYPE" = "whatsapp-export" ]; then
|
|
182
|
+
emit_decision "block" "denied-mcp-legacy archiveType=whatsapp-export" \
|
|
183
|
+
"Blocked: memory-archive-write with archiveType='whatsapp-export' is a retired path. Task 894 routes conversation transcripts through 'bash platform/plugins/memory/bin/conversation-archive-ingest.sh <archive> --source whatsapp --owner-element-id <id> --participant-person-ids <csv> --scope <admin|public>'. Flat-dataset archiveTypes (linkedin-connections, …) flow through memory-archive-write unchanged."
|
|
184
|
+
fi
|
|
185
|
+
fi
|
|
186
|
+
|
|
187
|
+
# --- Block 4: plugin-source path block (Edit/Write/NotebookEdit) -----------
|
|
150
188
|
case "$TOOL_NAME" in
|
|
151
189
|
Edit|Write|NotebookEdit)
|
|
152
190
|
FILE_PATH=$(extract_tool_input_field file_path)
|
|
@@ -159,7 +197,7 @@ case "$TOOL_NAME" in
|
|
|
159
197
|
;;
|
|
160
198
|
esac
|
|
161
199
|
|
|
162
|
-
# --- Block
|
|
200
|
+
# --- Block 5: shell test-runner block (Bash) -------------------------------
|
|
163
201
|
COMMAND=""
|
|
164
202
|
if [ "$TOOL_NAME" = "Bash" ]; then
|
|
165
203
|
COMMAND=$(extract_tool_input_field command)
|
|
@@ -23,11 +23,11 @@ if (!accountId) {
|
|
|
23
23
|
}
|
|
24
24
|
const agentSlug = process.env.AGENT_SLUG;
|
|
25
25
|
const sessionId = process.env.SESSION_ID;
|
|
26
|
-
server.tool("contact-create", "Create a new contact (schema:Person) in the graph.
|
|
27
|
-
givenName: z.string().describe("First name"),
|
|
26
|
+
server.tool("contact-create", "Create a new contact (schema:Person) in the graph. Any single identifying property — name, email, or telephone — suffices; the agent judges what to capture and dedup/conflicts are managed downstream. When email or telephone is supplied, contact-create deduplicates against existing live persons and returns the match instead of writing a duplicate. Write doctrine (Task 673): the new contact must link to at least one existing node (typically a Conversation or Organization). Pass elementIds found via memory-search.", {
|
|
27
|
+
givenName: z.string().optional().describe("First name (optional — supply whichever identifying fields you have)"),
|
|
28
28
|
familyName: z.string().optional().describe("Last name"),
|
|
29
|
-
email: z.string().email().optional().describe("Email address
|
|
30
|
-
telephone: z.string().min(1).max(30).optional().describe("Phone number
|
|
29
|
+
email: z.string().email().optional().describe("Email address — when present, used as the dedup key"),
|
|
30
|
+
telephone: z.string().min(1).max(30).optional().describe("Phone number — when present, used as the dedup key"),
|
|
31
31
|
jobTitle: z.string().optional().describe("Job title"),
|
|
32
32
|
source: z
|
|
33
33
|
.string()
|
|
@@ -69,7 +69,7 @@ server.tool("contact-create", "Create a new contact (schema:Person) in the graph
|
|
|
69
69
|
content: [
|
|
70
70
|
{
|
|
71
71
|
type: "text",
|
|
72
|
-
text: `Contact created: ${
|
|
72
|
+
text: `Contact created: ${result.identifier} (ID: ${result.nodeId}, status: ${params.status ?? "waitlist"})`,
|
|
73
73
|
},
|
|
74
74
|
],
|
|
75
75
|
};
|