@rubytech/create-realagent 1.0.678 → 1.0.681

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 (60) hide show
  1. package/dist/index.js +232 -39
  2. package/package.json +1 -1
  3. package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate.test.d.ts +2 -0
  4. package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate.test.d.ts.map +1 -0
  5. package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate.test.js +112 -0
  6. package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate.test.js.map +1 -0
  7. package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cache.test.d.ts +2 -0
  8. package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cache.test.d.ts.map +1 -0
  9. package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cache.test.js +163 -0
  10. package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cache.test.js.map +1 -0
  11. package/payload/platform/lib/graph-mcp/dist/cypher-validate.d.ts +38 -0
  12. package/payload/platform/lib/graph-mcp/dist/cypher-validate.d.ts.map +1 -0
  13. package/payload/platform/lib/graph-mcp/dist/cypher-validate.js +130 -0
  14. package/payload/platform/lib/graph-mcp/dist/cypher-validate.js.map +1 -0
  15. package/payload/platform/lib/graph-mcp/dist/index.js +201 -45
  16. package/payload/platform/lib/graph-mcp/dist/index.js.map +1 -1
  17. package/payload/platform/lib/graph-mcp/dist/schema-cache.d.ts +78 -0
  18. package/payload/platform/lib/graph-mcp/dist/schema-cache.d.ts.map +1 -0
  19. package/payload/platform/lib/graph-mcp/dist/schema-cache.js +194 -0
  20. package/payload/platform/lib/graph-mcp/dist/schema-cache.js.map +1 -0
  21. package/payload/platform/lib/graph-mcp/src/__tests__/cypher-validate.test.ts +141 -0
  22. package/payload/platform/lib/graph-mcp/src/__tests__/schema-cache.test.ts +169 -0
  23. package/payload/platform/lib/graph-mcp/src/cypher-validate.ts +157 -0
  24. package/payload/platform/lib/graph-mcp/src/index.ts +247 -47
  25. package/payload/platform/lib/graph-mcp/src/schema-cache.ts +212 -0
  26. package/payload/platform/lib/graph-trash/dist/index.d.ts +8 -0
  27. package/payload/platform/lib/graph-trash/dist/index.d.ts.map +1 -1
  28. package/payload/platform/lib/graph-trash/dist/index.js +109 -14
  29. package/payload/platform/lib/graph-trash/dist/index.js.map +1 -1
  30. package/payload/platform/lib/graph-trash/src/index.ts +136 -21
  31. package/payload/platform/plugins/docs/references/deployment.md +4 -2
  32. package/payload/platform/plugins/docs/references/memory-guide.md +5 -1
  33. package/payload/platform/plugins/docs/references/platform.md +1 -1
  34. package/payload/platform/plugins/docs/references/troubleshooting.md +20 -0
  35. package/payload/platform/plugins/memory/PLUGIN.md +1 -0
  36. package/payload/platform/plugins/memory/mcp/dist/index.js +54 -6
  37. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  38. package/payload/platform/plugins/memory/mcp/dist/lib/filter-token.d.ts +36 -0
  39. package/payload/platform/plugins/memory/mcp/dist/lib/filter-token.d.ts.map +1 -0
  40. package/payload/platform/plugins/memory/mcp/dist/lib/filter-token.js +86 -0
  41. package/payload/platform/plugins/memory/mcp/dist/lib/filter-token.js.map +1 -0
  42. package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.d.ts +23 -0
  43. package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.d.ts.map +1 -1
  44. package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js +47 -1
  45. package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js.map +1 -1
  46. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.d.ts +58 -0
  47. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.d.ts.map +1 -0
  48. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.js +125 -0
  49. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.js.map +1 -0
  50. package/payload/platform/scripts/vnc.sh +12 -409
  51. package/payload/platform/templates/agents/admin/IDENTITY.md +16 -0
  52. package/payload/platform/templates/dotfiles/.tmux.conf +1 -0
  53. package/payload/platform/templates/systemd/maxy-ttyd.service +25 -0
  54. package/payload/server/chunk-3RBKKDHC.js +783 -0
  55. package/payload/server/maxy-edge.js +377 -8
  56. package/payload/server/public/assets/admin-CIkyOur7.js +362 -0
  57. package/payload/server/public/assets/admin-kHJ-D0s7.css +1 -0
  58. package/payload/server/public/index.html +2 -1
  59. package/payload/server/server.js +391 -412
  60. package/payload/server/public/assets/admin-BBL1no_g.js +0 -352
@@ -1,9 +1,51 @@
1
1
  import { getSession } from "../lib/neo4j.js";
2
2
  import { trashNode } from "../../../../../lib/graph-trash/dist/index.js";
3
+ import { verifyFilterToken, filterTokenFingerprint } from "../lib/filter-token.js";
4
+ import { reverifyCandidate } from "./memory-find-candidates.js";
5
+ export class FilterTokenError extends Error {
6
+ reason;
7
+ constructor(message, reason) {
8
+ super(message);
9
+ this.reason = reason;
10
+ this.name = "FilterTokenError";
11
+ }
12
+ }
3
13
  export async function memoryDelete(params) {
4
- const { accountId, elementId, reason } = params;
14
+ const t0 = Date.now();
15
+ const { accountId, elementId, reason, filterToken } = params;
5
16
  const session = getSession();
6
17
  try {
18
+ // Filter-token re-verification (Task 655). Must run before trashNode so a
19
+ // rejection never mutates the graph. Observable outcome: the
20
+ // `[memory-delete]` log line carries `reverified=true|false` and
21
+ // `outcome=trashed|rejected` — never silent.
22
+ let reverified = false;
23
+ if (filterToken) {
24
+ const verify = verifyFilterToken(filterToken);
25
+ if (!verify.ok) {
26
+ const ms = Date.now() - t0;
27
+ process.stderr.write(`[memory-delete] elementId=${elementId} filterToken=${filterTokenFingerprint(filterToken)} reverified=false outcome=rejected reason=${verify.reason} ms=${ms}\n`);
28
+ throw new FilterTokenError(`memory-delete: filter token rejected (${verify.reason})`, verify.reason);
29
+ }
30
+ if (verify.payload.accountId !== accountId) {
31
+ const ms = Date.now() - t0;
32
+ process.stderr.write(`[memory-delete] elementId=${elementId} filterToken=${filterTokenFingerprint(filterToken)} reverified=false outcome=rejected reason=account-mismatch ms=${ms}\n`);
33
+ throw new FilterTokenError(`memory-delete: filter token account mismatch`, "mismatch");
34
+ }
35
+ const stillMatches = await reverifyCandidate({
36
+ session,
37
+ accountId,
38
+ filter: verify.payload.filter,
39
+ agentType: verify.payload.agentType,
40
+ elementId,
41
+ });
42
+ if (!stillMatches) {
43
+ const ms = Date.now() - t0;
44
+ process.stderr.write(`[memory-delete] elementId=${elementId} filterToken=${filterTokenFingerprint(filterToken)} reverified=false outcome=rejected reason=predicate-no-longer-matches ms=${ms}\n`);
45
+ throw new FilterTokenError(`memory-delete: target ${elementId} no longer matches filter '${verify.payload.filter}'`, "mismatch");
46
+ }
47
+ reverified = true;
48
+ }
7
49
  const root = await trashNode({
8
50
  session,
9
51
  accountId,
@@ -45,6 +87,10 @@ export async function memoryDelete(params) {
45
87
  chunks++;
46
88
  }
47
89
  }
90
+ const ms = Date.now() - t0;
91
+ const outcome = root.alreadyTrashed ? "already-trashed" : "trashed";
92
+ const tokenFp = filterToken ? filterTokenFingerprint(filterToken) : "none";
93
+ process.stderr.write(`[memory-delete] elementId=${elementId} filterToken=${tokenFp} reverified=${reverified} outcome=${outcome} ms=${ms}\n`);
48
94
  return {
49
95
  elementId,
50
96
  labels: root.labels,
@@ -1 +1 @@
1
- {"version":3,"file":"memory-delete.js","sourceRoot":"","sources":["../../src/tools/memory-delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAoB,MAAM,8CAA8C,CAAC;AAkC3F,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAA0B;IAE1B,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAChD,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,MAAM,IAAI,GAAgB,MAAM,SAAS,CAAC;YACxC,OAAO;YACP,SAAS;YACT,SAAS;YACT,EAAE,EAAE,eAAe;YACnB,MAAM;SACP,CAAC,CAAC;QAEH,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,MAAM,GAAG,CAAC,CAAC;QAEf,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC9C,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,GAAG,CACnC;;;;;+EAKuE,EACvE,EAAE,GAAG,EAAE,SAAS,EAAE,CACnB,CAAC;YACF,MAAM,UAAU,GAAI,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,YAAY,CAAc,IAAI,EAAE,CAAC;YACjF,MAAM,QAAQ,GAAI,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,UAAU,CAAc,IAAI,EAAE,CAAC;YAE7E,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;gBAC7B,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC;oBACxB,OAAO;oBACP,SAAS;oBACT,SAAS,EAAE,GAAG;oBACd,EAAE,EAAE,8BAA8B,SAAS,EAAE;oBAC7C,MAAM,EAAE,MAAM,IAAI,kCAAkC,SAAS,EAAE;iBAChE,CAAC,CAAC;gBACH,IAAI,CAAC,CAAC,OAAO;oBAAE,QAAQ,EAAE,CAAC;YAC5B,CAAC;YACD,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;gBAC3B,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC;oBACxB,OAAO;oBACP,SAAS;oBACT,SAAS,EAAE,GAAG;oBACd,EAAE,EAAE,8BAA8B,SAAS,EAAE;oBAC7C,MAAM,EAAE,MAAM,IAAI,kCAAkC,SAAS,EAAE;iBAChE,CAAC,CAAC;gBACH,IAAI,CAAC,CAAC,OAAO;oBAAE,MAAM,EAAE,CAAC;YAC1B,CAAC;QACH,CAAC;QAED,OAAO;YACL,SAAS;YACT,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE;SAC9B,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"memory-delete.js","sourceRoot":"","sources":["../../src/tools/memory-delete.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import { type CandidatesFilter } from "../lib/filter-token.js";
2
+ /**
3
+ * memory-find-candidates — deterministic bulk-delete selector.
4
+ *
5
+ * Closes the 2026-04-22 failure class where the admin agent authored a
6
+ * selection cypher against a schema it had not loaded (`[:HAS_MESSAGE]`
7
+ * instead of `[:PART_OF]`), producing a vacuously-true filter that trashed
8
+ * 175 Conversation nodes (69 with real user content). The fix removes the
9
+ * LLM from the selection predicate: the agent chooses a filter name from a
10
+ * fixed set, and the server runs the canonical cypher.
11
+ *
12
+ * Two filters ship in v1 (Task 655):
13
+ * - `empty` — zero `(m:Message)-[:PART_OF]->(c:Conversation)` Messages
14
+ * - `single-assistant` — exactly one `:PART_OF` Message, with `role='assistant'`
15
+ *
16
+ * A third filter `no-real-user-input` is deferred to Task 656 (content-match
17
+ * predicate has a distinct false-positive risk profile).
18
+ *
19
+ * The returned `filterToken` is a signed opaque bundle that `memory-delete`
20
+ * re-verifies at trash time. There is no path by which the agent can feed a
21
+ * hand-rolled list to `memory-delete` with a token — the token only exists
22
+ * when `memory-find-candidates` minted it, and the server re-runs the same
23
+ * predicate on each elementId before trashing.
24
+ */
25
+ export interface MemoryFindCandidatesParams {
26
+ accountId: string;
27
+ filter: CandidatesFilter;
28
+ agentType?: "admin" | "public";
29
+ limit?: number;
30
+ dryRun?: boolean;
31
+ }
32
+ export interface MemoryFindCandidatesItem {
33
+ elementId: string;
34
+ conversationId: string | null;
35
+ assistantMsgCount: number;
36
+ realUserMsgCount: number;
37
+ firstUserMsgPreview: string | null;
38
+ trashedAt: string | null;
39
+ }
40
+ export interface MemoryFindCandidatesResult {
41
+ filter: CandidatesFilter;
42
+ agentType?: "admin" | "public";
43
+ matched: number;
44
+ sampled: number;
45
+ items: MemoryFindCandidatesItem[];
46
+ filterToken: string;
47
+ dryRun: boolean;
48
+ }
49
+ /** Server-side re-check for `memory-delete` token verification. */
50
+ export declare function reverifyCandidate(params: {
51
+ session: import("neo4j-driver").Session;
52
+ accountId: string;
53
+ filter: CandidatesFilter;
54
+ agentType?: "admin" | "public";
55
+ elementId: string;
56
+ }): Promise<boolean>;
57
+ export declare function memoryFindCandidates(params: MemoryFindCandidatesParams): Promise<MemoryFindCandidatesResult>;
58
+ //# sourceMappingURL=memory-find-candidates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-find-candidates.d.ts","sourceRoot":"","sources":["../../src/tools/memory-find-candidates.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAEhF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,wBAAwB,EAAE,CAAC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;CACjB;AAwDD,mEAAmE;AACnE,wBAAsB,iBAAiB,CAAC,MAAM,EAAE;IAC9C,OAAO,EAAE,OAAO,cAAc,EAAE,OAAO,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,OAAO,CAAC,CA+BnB;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,0BAA0B,GACjC,OAAO,CAAC,0BAA0B,CAAC,CA6CrC"}
@@ -0,0 +1,125 @@
1
+ import { getSession } from "../lib/neo4j.js";
2
+ import { mintFilterToken } from "../lib/filter-token.js";
3
+ const DEFAULT_LIMIT = 200;
4
+ const MAX_LIMIT = 1000;
5
+ const PROJECT_AND_ORDER = `
6
+ WITH c,
7
+ size([x IN msgs WHERE x.role = 'assistant']) AS assistantMsgCount,
8
+ size([x IN msgs WHERE x.role = 'user' OR x.role IS NULL]) AS realUserMsgCount,
9
+ head([x IN msgs WHERE x.role = 'user' | x.content]) AS firstUserMsg
10
+ RETURN elementId(c) AS elementId,
11
+ c.conversationId AS conversationId,
12
+ assistantMsgCount AS assistantMsgCount,
13
+ realUserMsgCount AS realUserMsgCount,
14
+ CASE WHEN firstUserMsg IS NULL THEN NULL
15
+ WHEN size(firstUserMsg) > 120 THEN left(firstUserMsg, 120) + '…'
16
+ ELSE firstUserMsg
17
+ END AS firstUserMsgPreview,
18
+ toString(c.trashedAt) AS trashedAt
19
+ ORDER BY c.createdAt ASC
20
+ LIMIT toInteger($limit)
21
+ `;
22
+ /**
23
+ * Canonical selection cypher per filter. Agent-authored cypher never reaches
24
+ * the DB; these literals are the only delete-selection path from the admin
25
+ * agent's tool surface.
26
+ */
27
+ function buildSelectionCypher(filter) {
28
+ if (filter === "empty") {
29
+ return `
30
+ MATCH (c:Conversation)
31
+ WHERE c.accountId = $accountId
32
+ AND NOT c:Trashed
33
+ AND c.deletedAt IS NULL
34
+ AND ($agentTypeFilter IS NULL OR c.agentType = $agentTypeFilter)
35
+ AND NOT EXISTS { MATCH (:Message)-[:PART_OF]->(c) }
36
+ WITH c, [] AS msgs
37
+ ${PROJECT_AND_ORDER}
38
+ `;
39
+ }
40
+ // single-assistant
41
+ return `
42
+ MATCH (c:Conversation)
43
+ WHERE c.accountId = $accountId
44
+ AND NOT c:Trashed
45
+ AND c.deletedAt IS NULL
46
+ AND ($agentTypeFilter IS NULL OR c.agentType = $agentTypeFilter)
47
+ WITH c, [(m:Message)-[:PART_OF]->(c) | m] AS msgs
48
+ WHERE size(msgs) = 1
49
+ AND size([x IN msgs WHERE x.role = 'assistant']) = 1
50
+ ${PROJECT_AND_ORDER}
51
+ `;
52
+ }
53
+ /** Server-side re-check for `memory-delete` token verification. */
54
+ export async function reverifyCandidate(params) {
55
+ const { session, accountId, filter, agentType, elementId } = params;
56
+ const cypher = filter === "empty"
57
+ ? `
58
+ MATCH (c:Conversation)
59
+ WHERE elementId(c) = $elementId
60
+ AND c.accountId = $accountId
61
+ AND NOT c:Trashed
62
+ AND c.deletedAt IS NULL
63
+ AND ($agentTypeFilter IS NULL OR c.agentType = $agentTypeFilter)
64
+ AND NOT EXISTS { MATCH (:Message)-[:PART_OF]->(c) }
65
+ RETURN elementId(c) AS eid
66
+ `
67
+ : `
68
+ MATCH (c:Conversation)
69
+ WHERE elementId(c) = $elementId
70
+ AND c.accountId = $accountId
71
+ AND NOT c:Trashed
72
+ AND c.deletedAt IS NULL
73
+ AND ($agentTypeFilter IS NULL OR c.agentType = $agentTypeFilter)
74
+ WITH c, [(m:Message)-[:PART_OF]->(c) | m] AS msgs
75
+ WHERE size(msgs) = 1 AND size([x IN msgs WHERE x.role = 'assistant']) = 1
76
+ RETURN elementId(c) AS eid
77
+ `;
78
+ const result = await session.run(cypher, {
79
+ elementId,
80
+ accountId,
81
+ agentTypeFilter: agentType ?? null,
82
+ });
83
+ return result.records.length === 1;
84
+ }
85
+ export async function memoryFindCandidates(params) {
86
+ const t0 = Date.now();
87
+ const { accountId, filter, agentType, dryRun = false } = params;
88
+ const limit = Math.min(params.limit ?? DEFAULT_LIMIT, MAX_LIMIT);
89
+ const session = getSession();
90
+ try {
91
+ const cypher = buildSelectionCypher(filter);
92
+ const result = await session.run(cypher, {
93
+ accountId,
94
+ agentTypeFilter: agentType ?? null,
95
+ limit,
96
+ });
97
+ const items = result.records.map((r) => ({
98
+ elementId: r.get("elementId"),
99
+ conversationId: r.get("conversationId") ?? null,
100
+ assistantMsgCount: Number(r.get("assistantMsgCount") ?? 0),
101
+ realUserMsgCount: Number(r.get("realUserMsgCount") ?? 0),
102
+ firstUserMsgPreview: r.get("firstUserMsgPreview") ?? null,
103
+ trashedAt: r.get("trashedAt") ?? null,
104
+ }));
105
+ // Under dryRun the caller wants to see what would match without receiving
106
+ // an actionable token — so the agent cannot "accidentally" feed a dryRun
107
+ // result to memory-delete. Returning an empty string rather than omitting
108
+ // the field keeps the result shape stable for the MCP surface.
109
+ const filterToken = dryRun ? "" : mintFilterToken({ filter, agentType, accountId });
110
+ process.stderr.write(`[memory-find-candidates] filter=${filter} agentType=${agentType ?? "any"} matched=${items.length} sampled=${items.length} dryRun=${dryRun} ms=${Date.now() - t0}\n`);
111
+ return {
112
+ filter,
113
+ agentType,
114
+ matched: items.length,
115
+ sampled: items.length,
116
+ items,
117
+ filterToken,
118
+ dryRun,
119
+ };
120
+ }
121
+ finally {
122
+ await session.close();
123
+ }
124
+ }
125
+ //# sourceMappingURL=memory-find-candidates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-find-candidates.js","sourceRoot":"","sources":["../../src/tools/memory-find-candidates.ts"],"names":[],"mappings":"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"}