@rubytech/create-maxy-code 0.1.411 → 0.1.412
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/lib/account-scope/dist/index.d.ts +27 -0
- package/payload/platform/lib/account-scope/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/account-scope/dist/index.js +33 -0
- package/payload/platform/lib/account-scope/dist/index.js.map +1 -0
- package/payload/platform/lib/account-scope/src/index.ts +43 -0
- package/payload/platform/lib/account-scope/tsconfig.json +5 -0
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -0
- package/payload/platform/plugins/admin/hooks/lib/maxy-mcp-plugins.txt +1 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +35 -1
- package/payload/platform/plugins/business-assistant/skills/e-sign/SKILL.md +2 -0
- package/payload/platform/plugins/docs/references/cross-account-authority.md +23 -0
- package/payload/platform/plugins/docs/references/memory-guide.md +6 -0
- package/payload/platform/plugins/filesystem/.claude-plugin/plugin.json +21 -0
- package/payload/platform/plugins/filesystem/PLUGIN.md +63 -0
- package/payload/platform/plugins/filesystem/lib/mcp-spawn-tee/index.js +193 -0
- package/payload/platform/plugins/filesystem/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/plugins/filesystem/mcp/dist/index.d.ts +2 -0
- package/payload/platform/plugins/filesystem/mcp/dist/index.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/index.js +91 -0
- package/payload/platform/plugins/filesystem/mcp/dist/index.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/scope.test.d.ts +2 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/scope.test.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/scope.test.js +89 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/scope.test.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/result.d.ts +12 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/result.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/result.js +6 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/result.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.d.ts +45 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.js +86 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/walk.d.ts +11 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/walk.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/walk.js +64 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/walk.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/handlers.test.d.ts +2 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/handlers.test.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/handlers.test.js +94 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/handlers.test.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.d.ts +8 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.js +40 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.d.ts +6 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.js +13 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.d.ts +7 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.js +71 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.d.ts +6 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.js +26 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.d.ts +6 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.js +28 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.d.ts +7 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.js +25 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/package.json +21 -0
- package/payload/platform/plugins/filesystem/mcp/vitest.config.ts +8 -0
- package/payload/platform/plugins/memory/PLUGIN.md +6 -0
- package/payload/platform/plugins/memory/mcp/dist/index-testable.d.ts +34 -0
- package/payload/platform/plugins/memory/mcp/dist/index-testable.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/index-testable.js +60 -0
- package/payload/platform/plugins/memory/mcp/dist/index-testable.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/index.js +275 -133
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/cross-account.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/cross-account.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/cross-account.test.js +65 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/cross-account.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/resolve-tool-account.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/resolve-tool-account.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/resolve-tool-account.test.js +54 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/resolve-tool-account.test.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +7 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/claude-host-creds.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/claude-host-creds.js +6 -1
- package/payload/platform/services/claude-session-manager/dist/claude-host-creds.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/claude-keychain-write.d.ts +7 -1
- package/payload/platform/services/claude-session-manager/dist/claude-keychain-write.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/claude-keychain-write.js +7 -2
- package/payload/platform/services/claude-session-manager/dist/claude-keychain-write.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/config.d.ts +37 -0
- package/payload/platform/services/claude-session-manager/dist/config.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/config.js +34 -1
- package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/cross-account-census.d.ts +34 -0
- package/payload/platform/services/claude-session-manager/dist/cross-account-census.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/cross-account-census.js +98 -0
- package/payload/platform/services/claude-session-manager/dist/cross-account-census.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +10 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +17 -0
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +25 -0
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts +7 -0
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.js +8 -0
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.js.map +1 -1
- package/payload/server/{chunk-ZYS5V5QG.js → chunk-3Z5WE53X.js} +4 -0
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/public/assets/{AdminLoginScreens-BRQgI2lW.js → AdminLoginScreens-CYPTMmTk.js} +1 -1
- package/payload/server/public/assets/{AdminShell-By9n5icG.js → AdminShell-CZH_EZIy.js} +1 -1
- package/payload/server/public/assets/{Checkbox-DjEWgYu1.js → Checkbox-B0pbYJDQ.js} +1 -1
- package/payload/server/public/assets/{Transcript-BejWvOaO.js → Transcript-CYaAPBFX.js} +1 -1
- package/payload/server/public/assets/{admin-BFEMryQm.js → admin-BKDMSRto.js} +1 -1
- package/payload/server/public/assets/{browser-CMJMEUz6.js → browser-CxeMDDZA.js} +1 -1
- package/payload/server/public/assets/{calendar-C6ZGlHEP.js → calendar-DiIiTY9-.js} +1 -1
- package/payload/server/public/assets/chat-C56Oqvt1.js +1 -0
- package/payload/server/public/assets/chevron-left-Da-iZGi_.js +1 -0
- package/payload/server/public/assets/data-ZUdT44Ba.js +1 -0
- package/payload/server/public/assets/{graph-DIrXtPLv.js → graph-DC3dwnMZ.js} +1 -1
- package/payload/server/public/assets/{graph-labels-BtPf1Jom.js → graph-labels-Csnovm_c.js} +1 -1
- package/payload/server/public/assets/{maximize-2-DeJ4K8kL.js → maximize-2-WRUJsg5n.js} +1 -1
- package/payload/server/public/assets/{operator-B8QhqzLI.js → operator-BpzeHTAw.js} +1 -1
- package/payload/server/public/assets/{page-iFOy0dFx.js → page-8jJOxx6y.js} +1 -1
- package/payload/server/public/assets/{page-Df6KYkf4.js → page-IQDLdebG.js} +1 -1
- package/payload/server/public/assets/{public-BrUIRQZd.js → public-Dqg7jwjq.js} +1 -1
- package/payload/server/public/assets/{rotate-ccw-CYfntpwu.js → rotate-ccw-BayMWwfc.js} +1 -1
- package/payload/server/public/assets/{useSubAccountSwitcher-Cvnc_fwQ.css → useSubAccountSwitcher-CRZfyJXR.css} +1 -1
- package/payload/server/public/browser.html +4 -4
- package/payload/server/public/calendar.html +5 -5
- package/payload/server/public/chat.html +9 -9
- package/payload/server/public/data.html +8 -8
- package/payload/server/public/graph.html +9 -9
- package/payload/server/public/index.html +11 -11
- package/payload/server/public/operator.html +11 -11
- package/payload/server/public/public.html +9 -9
- package/payload/server/server.js +36 -11
- package/payload/server/public/assets/chat-B7s62Nnp.js +0 -1
- package/payload/server/public/assets/chevron-left-Dfjcaiyr.js +0 -1
- package/payload/server/public/assets/data-741ZbBwR.js +0 -1
- /package/payload/server/public/assets/{useSubAccountSwitcher-BK_KfOLC.js → useSubAccountSwitcher-C9aLg8yI.js} +0 -0
|
@@ -59,6 +59,10 @@ import { getSession, closeDriver } from "./lib/neo4j.js";
|
|
|
59
59
|
import { embed } from "./lib/embeddings.js";
|
|
60
60
|
import { notTrashed } from "../../../../lib/graph-trash/dist/index.js";
|
|
61
61
|
import { lifelineTool } from "../../../../lib/mcp-lifeline/dist/index.js";
|
|
62
|
+
import { resolve } from "node:path";
|
|
63
|
+
import { enumerateValidAccountIds } from "../../../../lib/account-enumeration/dist/index.js";
|
|
64
|
+
import { readHouseAdminScope } from "../../../../lib/account-scope/dist/index.js";
|
|
65
|
+
import { makeResolveToolAccount } from "./index-testable.js";
|
|
62
66
|
const server = new McpServer({
|
|
63
67
|
name: "maxy-memory",
|
|
64
68
|
version: "0.1.0",
|
|
@@ -74,18 +78,32 @@ const accountId = process.env.ACCOUNT_ID ?? null;
|
|
|
74
78
|
// accountId`; `agentSlug` empty on a specialist spawn (provenance lost);
|
|
75
79
|
// `agentScope` non-empty on the admin operator spawn (search wrongly scoped).
|
|
76
80
|
process.stderr.write(`[memory] boot accountId=${accountId ?? "null"} sessionId=${process.env.SESSION_ID || "-"} agentSlug=${process.env.AGENT_SLUG || "-"} agentScope=${process.env.AGENT_SLUG_SCOPE || "-"}\n`);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
81
|
+
// The no-account refusal (formerly `refuseNoAccount`) is now handled inside
|
|
82
|
+
// `resolveToolAccount` / `makeResolveToolAccount` (index-testable.ts), which
|
|
83
|
+
// preserves the same message when the boot ACCOUNT_ID is null. Task 1455.
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
// Cross-account authority (Task 1455). A house-scoped admin session may set an
|
|
86
|
+
// optional `targetAccountId` on any account-scoped tool to read/write a
|
|
87
|
+
// sub-account's subgraph; omitting it is byte-identical to own-account.
|
|
88
|
+
//
|
|
89
|
+
// `houseScope` rides the spawn env (Task 1440, `HOUSE_ADMIN_SCOPE`). `accountsDir`
|
|
90
|
+
// mirrors neo4j.ts's platform-root resolution (PLATFORM_ROOT env, else relative
|
|
91
|
+
// to the compiled file): from dist/index.js, `../../../..` is `platform/`, and
|
|
92
|
+
// accounts live at `<platform>/../data/accounts`. `enumerateValidAccountIds`
|
|
93
|
+
// returns [] (never throws) on a missing dir, so a misresolved path fails CLOSED
|
|
94
|
+
// — every target rejects invalid-target. The boot line makes that visible rather
|
|
95
|
+
// than silent: a zero `validAccounts` on a provisioned install is the alarm.
|
|
96
|
+
const houseScope = readHouseAdminScope();
|
|
97
|
+
const accountsDir = resolve(process.env.PLATFORM_ROOT ?? resolve(import.meta.dirname, "../../../.."), "..", "data/accounts");
|
|
98
|
+
process.stderr.write(`[xacct] boot houseScope=${houseScope ? "yes" : "no"} accountsDir=${accountsDir} validAccounts=${enumerateValidAccountIds(accountsDir).length}\n`);
|
|
99
|
+
const resolveToolAccount = makeResolveToolAccount({
|
|
100
|
+
accountId,
|
|
101
|
+
houseScope,
|
|
102
|
+
isValid: (id) => enumerateValidAccountIds(accountsDir).includes(id),
|
|
103
|
+
});
|
|
104
|
+
// Single source for the operator-facing targetAccountId description — the LLM
|
|
105
|
+
// reads this verbatim, so it must not drift across the 35 targetable tools.
|
|
106
|
+
const XACCT_DESC = "House-scoped admin only: operate on the named sub-account subgraph instead of your own. Only a house-scoped session may set this; a non-house session that sets it is rejected.";
|
|
89
107
|
// Load the markdown schema sidecar once at startup. Every memory-write call
|
|
90
108
|
// reads its required-property and synonym maps. If loading fails we throw —
|
|
91
109
|
// a memory server running with a broken schema is worse than one that fails
|
|
@@ -242,9 +260,12 @@ eagerTool(server, "memory-search", "Search the knowledge graph using semantic ve
|
|
|
242
260
|
.enum(["entity", "temporal", "event", "general", "none"])
|
|
243
261
|
.optional()
|
|
244
262
|
.describe("Hint that selects the per-class index mix (route-hint contract). Pass 'entity' for who/what-is-this lookups (vector-heavy, Person|Company|Concept filter), 'temporal' for when-did-this-happen (BM25-heavy over :Event with Timeline), 'event' for pure event listings, 'none' to skip graph lookup entirely (greetings/instructions). Omit or pass 'general' for the balanced default. Routing only takes effect when MAXY_GS_ROUTE is enabled; otherwise the value is recorded in the log line but does not change index selection."),
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
263
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
264
|
+
}, async ({ query, labels, limit, expandHops, keywords, keywordMatch, agentSlug: toolAgentSlug, fields, retrievalClass, targetAccountId }) => {
|
|
265
|
+
const scoped = resolveToolAccount("memory-search", targetAccountId);
|
|
266
|
+
if ("reject" in scoped)
|
|
267
|
+
return scoped.reject;
|
|
268
|
+
const accountId = scoped.accountId;
|
|
248
269
|
// AGENT_SLUG_SCOPE takes precedence over the tool param (security: public
|
|
249
270
|
// agent server-level enforcement). Empty for the admin operator, so admin
|
|
250
271
|
// falls through to the optional tool param (default: unscoped).
|
|
@@ -358,9 +379,12 @@ eagerTool(server, "memory-lookup-by-name", "Deterministic by-name entity lookup.
|
|
|
358
379
|
.number()
|
|
359
380
|
.optional()
|
|
360
381
|
.describe("Maximum number of matching nodes to return (default 25)."),
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
382
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
383
|
+
}, async ({ name, labels, limit, targetAccountId }) => {
|
|
384
|
+
const scoped = resolveToolAccount("memory-lookup-by-name", targetAccountId);
|
|
385
|
+
if ("reject" in scoped)
|
|
386
|
+
return scoped.reject;
|
|
387
|
+
const accountId = scoped.accountId;
|
|
364
388
|
const effectiveAgentSlug = envAgentScopeSlug;
|
|
365
389
|
try {
|
|
366
390
|
const hits = await memoryLookupByName({
|
|
@@ -425,9 +449,12 @@ lifelineTool(server, "conversation-archive-list-chunks", "Page through the :Sect
|
|
|
425
449
|
.max(20)
|
|
426
450
|
.optional()
|
|
427
451
|
.describe("Chunks per page (1..20). Default 5."),
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
452
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
453
|
+
}, async ({ archiveElementId, chunkOffset, chunkLimit, targetAccountId }) => {
|
|
454
|
+
const scoped = resolveToolAccount("conversation-archive-list-chunks", targetAccountId);
|
|
455
|
+
if ("reject" in scoped)
|
|
456
|
+
return scoped.reject;
|
|
457
|
+
const accountId = scoped.accountId;
|
|
431
458
|
try {
|
|
432
459
|
const result = await conversationArchiveListChunks({
|
|
433
460
|
accountId,
|
|
@@ -504,9 +531,12 @@ lifelineTool(server, "conversation-archive-derive-insights", "Convert one chunk'
|
|
|
504
531
|
.describe("Claims the dispatched specialist emitted in-turn from the chunk body. Zero is valid — pass [] to record an empty-chunk pass."),
|
|
505
532
|
inlineRewrite: z.boolean().optional().describe("When true, count mention-claim subjects in this chunk and return those reaching inlineRewriteThreshold in inlineRewriteSignals. The calling skill accumulates signals across chunks; when an entity's cumulative count hits threshold, resolve it via memory-search and dispatch the compiled-truth-rewriter specialist."),
|
|
506
533
|
inlineRewriteThreshold: z.number().int().min(1).optional().describe("Minimum mention-claim count for a subject to appear in inlineRewriteSignals. Default: 2."),
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
534
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
535
|
+
}, async ({ archiveElementId, chunkElementId, claims, inlineRewrite, inlineRewriteThreshold, targetAccountId }) => {
|
|
536
|
+
const scoped = resolveToolAccount("conversation-archive-derive-insights", targetAccountId);
|
|
537
|
+
if ("reject" in scoped)
|
|
538
|
+
return scoped.reject;
|
|
539
|
+
const accountId = scoped.accountId;
|
|
510
540
|
try {
|
|
511
541
|
const result = await conversationArchiveDeriveInsights({
|
|
512
542
|
accountId,
|
|
@@ -583,9 +613,12 @@ lifelineTool(server, "conversation-archive-enrich-rejection", "Record or undo a
|
|
|
583
613
|
mode: z
|
|
584
614
|
.enum(["record", "undo"])
|
|
585
615
|
.describe("record = append rejection; undo = remove rejection (called after `wire`)."),
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
616
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
617
|
+
}, async ({ archiveElementId, chunkElementId, kind, contentHash, mode, targetAccountId }) => {
|
|
618
|
+
const scoped = resolveToolAccount("conversation-archive-enrich-rejection", targetAccountId);
|
|
619
|
+
if ("reject" in scoped)
|
|
620
|
+
return scoped.reject;
|
|
621
|
+
const accountId = scoped.accountId;
|
|
589
622
|
try {
|
|
590
623
|
const result = await conversationArchiveEnrichRejection({
|
|
591
624
|
accountId,
|
|
@@ -629,9 +662,12 @@ eagerTool(server, "memory-report-read-latest", "Return the most recent :Report n
|
|
|
629
662
|
.max(20)
|
|
630
663
|
.optional()
|
|
631
664
|
.describe("Maximum number of reports to return, newest first. Default 1."),
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
665
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
666
|
+
}, async ({ keyword, limit, targetAccountId }) => {
|
|
667
|
+
const scoped = resolveToolAccount("memory-report-read-latest", targetAccountId);
|
|
668
|
+
if ("reject" in scoped)
|
|
669
|
+
return scoped.reject;
|
|
670
|
+
const accountId = scoped.accountId;
|
|
635
671
|
try {
|
|
636
672
|
const result = await memoryReportReadLatest({ accountId, keyword, limit });
|
|
637
673
|
if (result.results.length === 0) {
|
|
@@ -686,9 +722,12 @@ eagerTool(server, "memory-report-list", "List :Report nodes, newest first, with
|
|
|
686
722
|
.min(0)
|
|
687
723
|
.optional()
|
|
688
724
|
.describe("Zero-based offset for pagination. Default 0."),
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
725
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
726
|
+
}, async ({ keyword, sourceWorkflow, limit, offset, targetAccountId }) => {
|
|
727
|
+
const scoped = resolveToolAccount("memory-report-list", targetAccountId);
|
|
728
|
+
if ("reject" in scoped)
|
|
729
|
+
return scoped.reject;
|
|
730
|
+
const accountId = scoped.accountId;
|
|
692
731
|
try {
|
|
693
732
|
const result = await memoryReportList({
|
|
694
733
|
accountId,
|
|
@@ -736,9 +775,12 @@ eagerTool(server, "memory-compiled-truth-history", "Return the audit history of
|
|
|
736
775
|
nodeId: z
|
|
737
776
|
.string()
|
|
738
777
|
.describe("elementId of the :Person | :Organization | :Concept whose revision history is being read."),
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
778
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
779
|
+
}, async ({ nodeId, targetAccountId }) => {
|
|
780
|
+
const scoped = resolveToolAccount("memory-compiled-truth-history", targetAccountId);
|
|
781
|
+
if ("reject" in scoped)
|
|
782
|
+
return scoped.reject;
|
|
783
|
+
const accountId = scoped.accountId;
|
|
742
784
|
try {
|
|
743
785
|
const result = await memoryCompiledTruthHistory({ accountId, nodeId });
|
|
744
786
|
if (result.revisions.length === 0) {
|
|
@@ -793,9 +835,12 @@ if (!readOnly) {
|
|
|
793
835
|
.string()
|
|
794
836
|
.optional()
|
|
795
837
|
.describe("Active Task elementId for autonomous-workflow writes. When set, an inbound :PRODUCED edge from this Task is composed into relationships before the write. Task must share the same accountId; mismatch is rejected. Omit for direct conversation asks — the platform composes the edge from the active conversation instead."),
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
838
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
839
|
+
}, async ({ labels, properties, scope, relationships, producedByTaskId, targetAccountId }) => {
|
|
840
|
+
const scoped = resolveToolAccount("memory-write", targetAccountId);
|
|
841
|
+
if ("reject" in scoped)
|
|
842
|
+
return scoped.reject;
|
|
843
|
+
const accountId = scoped.accountId;
|
|
799
844
|
try {
|
|
800
845
|
const result = await memoryWrite({
|
|
801
846
|
labels,
|
|
@@ -853,9 +898,12 @@ if (!readOnly) {
|
|
|
853
898
|
.string()
|
|
854
899
|
.optional()
|
|
855
900
|
.describe("ISO 8601 timestamp the report describes. Defaults to now(). Override only when persisting a backdated report."),
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
901
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
902
|
+
}, async ({ title, body, keywords, sourceWorkflow, occurredAt, targetAccountId }) => {
|
|
903
|
+
const scoped = resolveToolAccount("memory-report-write", targetAccountId);
|
|
904
|
+
if ("reject" in scoped)
|
|
905
|
+
return scoped.reject;
|
|
906
|
+
const accountId = scoped.accountId;
|
|
859
907
|
try {
|
|
860
908
|
const result = await memoryReportWrite({
|
|
861
909
|
accountId,
|
|
@@ -896,9 +944,12 @@ if (!readOnly) {
|
|
|
896
944
|
properties: z
|
|
897
945
|
.record(z.string(), z.unknown())
|
|
898
946
|
.describe("Properties to set or overwrite. Same restrictions as memory-update — embedding/accountId/createdAt are silently stripped; compiled-truth fields are refused unless the caller is the compiled-truth-rewriter specialist."),
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
947
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
948
|
+
}, async ({ label, name, properties, targetAccountId }) => {
|
|
949
|
+
const scoped = resolveToolAccount("memory-update-by-name", targetAccountId);
|
|
950
|
+
if ("reject" in scoped)
|
|
951
|
+
return scoped.reject;
|
|
952
|
+
const accountId = scoped.accountId;
|
|
902
953
|
try {
|
|
903
954
|
const result = await memoryUpdateByName({
|
|
904
955
|
label,
|
|
@@ -937,9 +988,12 @@ if (!readOnly) {
|
|
|
937
988
|
properties: z
|
|
938
989
|
.record(z.string(), z.unknown())
|
|
939
990
|
.describe("Properties to set or overwrite. Restricted keys (embedding, accountId, createdAt) are ignored. Compiled-truth fields are system-managed; only the compiled-truth-rewriter specialist may write them."),
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
991
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
992
|
+
}, async ({ nodeId, properties, targetAccountId }) => {
|
|
993
|
+
const scoped = resolveToolAccount("memory-update", targetAccountId);
|
|
994
|
+
if ("reject" in scoped)
|
|
995
|
+
return scoped.reject;
|
|
996
|
+
const accountId = scoped.accountId;
|
|
943
997
|
try {
|
|
944
998
|
const result = await memoryUpdate({
|
|
945
999
|
nodeId,
|
|
@@ -978,9 +1032,12 @@ if (!readOnly) {
|
|
|
978
1032
|
toId: z.string().describe("elementId of the target node (from memory-search results)."),
|
|
979
1033
|
relationshipType: z.string().describe("Relationship type label — e.g. RELATES_TO, MENTIONS, WORKED_WITH. Uppercase-coerced. Underscore-prefixed types (_SOFT_DELETE, etc.) are reserved and rejected."),
|
|
980
1034
|
properties: z.record(z.string(), z.unknown()).optional().describe("Properties to set on the relationship on CREATE. Ignored on DELETE and on idempotent CREATE (MERGE-matched)."),
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
1035
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
1036
|
+
}, async ({ action, fromId, toId, relationshipType, properties, targetAccountId }) => {
|
|
1037
|
+
const scoped = resolveToolAccount("memory-edge", targetAccountId);
|
|
1038
|
+
if ("reject" in scoped)
|
|
1039
|
+
return scoped.reject;
|
|
1040
|
+
const accountId = scoped.accountId;
|
|
984
1041
|
try {
|
|
985
1042
|
const result = await memoryEdge({
|
|
986
1043
|
action,
|
|
@@ -1014,9 +1071,13 @@ if (!readOnly) {
|
|
|
1014
1071
|
};
|
|
1015
1072
|
}
|
|
1016
1073
|
});
|
|
1017
|
-
eagerTool(server, "session-compact-status", "Check whether a session compaction summary exists in the graph. Returns the most recent summary title, date, and briefing text. Use this at session start to determine whether a prior session was compacted and its context should be restored.", {
|
|
1018
|
-
|
|
1019
|
-
|
|
1074
|
+
eagerTool(server, "session-compact-status", "Check whether a session compaction summary exists in the graph. Returns the most recent summary title, date, and briefing text. Use this at session start to determine whether a prior session was compacted and its context should be restored.", {
|
|
1075
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
1076
|
+
}, async ({ targetAccountId }) => {
|
|
1077
|
+
const scoped = resolveToolAccount("session-compact-status", targetAccountId);
|
|
1078
|
+
if ("reject" in scoped)
|
|
1079
|
+
return scoped.reject;
|
|
1080
|
+
const accountId = scoped.accountId;
|
|
1020
1081
|
const session = getSession();
|
|
1021
1082
|
try {
|
|
1022
1083
|
const result = await session.run(`MATCH (n:CreativeWork {accountId: $accountId})
|
|
@@ -1043,8 +1104,10 @@ if (!readOnly) {
|
|
|
1043
1104
|
eagerTool(server, "session-compact", "Write a session summary to the knowledge graph. Call this when compacting context — provide the full briefing and the tool handles labelling, structure, and embedding.", {
|
|
1044
1105
|
content: z.string().describe("The session briefing — what was discussed, decisions made, work in progress, open questions, and anything learned about the user or their business"),
|
|
1045
1106
|
}, async ({ content }) => {
|
|
1046
|
-
|
|
1047
|
-
|
|
1107
|
+
const scoped = resolveToolAccount("session-compact", undefined);
|
|
1108
|
+
if ("reject" in scoped)
|
|
1109
|
+
return scoped.reject;
|
|
1110
|
+
const accountId = scoped.accountId;
|
|
1048
1111
|
try {
|
|
1049
1112
|
// Write doctrine: session summaries link back to the
|
|
1050
1113
|
// Conversation they summarise, so an operator searching a session's
|
|
@@ -1103,9 +1166,13 @@ if (!readOnly) {
|
|
|
1103
1166
|
};
|
|
1104
1167
|
}
|
|
1105
1168
|
});
|
|
1106
|
-
eagerTool(server, "memory-reindex", "Rebuild vector embeddings for all nodes missing embeddings. Run after seeding or bulk updates.", {
|
|
1107
|
-
|
|
1108
|
-
|
|
1169
|
+
eagerTool(server, "memory-reindex", "Rebuild vector embeddings for all nodes missing embeddings. Run after seeding or bulk updates.", {
|
|
1170
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
1171
|
+
}, async ({ targetAccountId }) => {
|
|
1172
|
+
const scoped = resolveToolAccount("memory-reindex", targetAccountId);
|
|
1173
|
+
if ("reject" in scoped)
|
|
1174
|
+
return scoped.reject;
|
|
1175
|
+
const accountId = scoped.accountId;
|
|
1109
1176
|
try {
|
|
1110
1177
|
const result = await memoryReindex(accountId);
|
|
1111
1178
|
return {
|
|
@@ -1140,8 +1207,10 @@ if (!readOnly) {
|
|
|
1140
1207
|
mimeType: z.string().describe("MIME type of the file"),
|
|
1141
1208
|
attachmentId: z.string().describe("UUID of the file attachment — used as cache key for memory-ingest"),
|
|
1142
1209
|
}, async ({ storagePath, filename, mimeType, attachmentId }) => {
|
|
1143
|
-
|
|
1144
|
-
|
|
1210
|
+
const scoped = resolveToolAccount("memory-ingest-extract", undefined);
|
|
1211
|
+
if ("reject" in scoped)
|
|
1212
|
+
return scoped.reject;
|
|
1213
|
+
const accountId = scoped.accountId;
|
|
1145
1214
|
try {
|
|
1146
1215
|
const result = await memoryIngestExtract({ storagePath, filename, mimeType, attachmentId });
|
|
1147
1216
|
return {
|
|
@@ -1231,9 +1300,12 @@ if (!readOnly) {
|
|
|
1231
1300
|
inlineRewrite: z.boolean().optional().describe("When true, after writing all sections and edges, run the inline compiled-truth reconciliation gate. Counts MENTIONS/REFERENCES edges from this document (KnowledgeDocument + its sections) to existing entities that carry compiledTruth. Entities with >= inlineRewriteThreshold such edges (default 2) and compiledTruthUpdatedAt older than 7 days are returned in inlineRewriteCandidates. Dispatch the compiled-truth-rewriter specialist for each before the skill returns. Disabled by default."),
|
|
1232
1301
|
forceRewrite: z.boolean().optional().describe("When inlineRewrite is true, bypass the 7-day per-entity cooldown on compiledTruthUpdatedAt. All threshold-qualifying entities are returned as inlineRewriteCandidates regardless of when their truth was last rewritten."),
|
|
1233
1302
|
inlineRewriteThreshold: z.number().int().min(1).optional().describe("Minimum MENTIONS/REFERENCES edge count from this source to an entity for it to qualify as an inline-rewrite candidate. Default: 2."),
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1303
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
1304
|
+
}, async ({ attachmentId, conversationIdentity, source, archiveSha256, archiveSourceFile, participantElementIds, lastIngestedMessageHash, lastIngestedMessageAt, archiveTitle, cleanupPriorChunks, sessionIndex, documentSummary, anchorNodeId, anchorLabel, sections, documentEdges, orphanCandidates, scope, sourceUrl, sourceType, documentKeywords, userKeywords, sessionId: sessionIdOverride, inlineRewrite, forceRewrite, inlineRewriteThreshold, targetAccountId }) => {
|
|
1305
|
+
const scoped = resolveToolAccount("memory-ingest", targetAccountId);
|
|
1306
|
+
if ("reject" in scoped)
|
|
1307
|
+
return scoped.reject;
|
|
1308
|
+
const accountId = scoped.accountId;
|
|
1237
1309
|
try {
|
|
1238
1310
|
const result = await memoryIngest({
|
|
1239
1311
|
accountId,
|
|
@@ -1296,9 +1368,12 @@ if (!readOnly) {
|
|
|
1296
1368
|
});
|
|
1297
1369
|
eagerTool(server, "kd-classify", "Operator-solicited reclassify for any :KnowledgeDocument that carries a `body` property (today: email-thread KDs; future: any thread-shaped source). Reads the KD by attachmentId, decides via a body-growth gate (proceed iff body grew ≥25% since the last classify, or first-ever classify), stages the body to a temp file under $ACCOUNT_DIR/tmp/, and returns a dispatch envelope the admin agent hands to the `librarian` specialist. Librarian runs the document-ingest skill against the temp file; memory-ingest MERGEs by attachmentId, replacing any prior :Section children, and stamps lastClassifiedAt + lastClassifiedBodyLength on the KD so the next gate call has a baseline. Bodyless attachment KDs (PDFs etc.) are not supported here — they have no growth signal.", {
|
|
1298
1370
|
attachmentId: z.string().describe("attachmentId of the :KnowledgeDocument to classify. For email threads, this is sha256(`email:<accountId>:<rootMessageId>`)."),
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1371
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
1372
|
+
}, async ({ attachmentId, targetAccountId }) => {
|
|
1373
|
+
const scoped = resolveToolAccount("kd-classify", targetAccountId);
|
|
1374
|
+
if ("reject" in scoped)
|
|
1375
|
+
return scoped.reject;
|
|
1376
|
+
const accountId = scoped.accountId;
|
|
1302
1377
|
try {
|
|
1303
1378
|
const text = await kdClassify({ accountId, attachmentId });
|
|
1304
1379
|
return { content: [{ type: "text", text }] };
|
|
@@ -1336,9 +1411,12 @@ if (!readOnly) {
|
|
|
1336
1411
|
.string()
|
|
1337
1412
|
.optional()
|
|
1338
1413
|
.describe("Skill-run UUID for provenance stamping. Falls back to SESSION_ID env var when absent."),
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1414
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
1415
|
+
}, async ({ archiveType, ownerNodeId, rows, sessionId: sessionIdOverride, targetAccountId }) => {
|
|
1416
|
+
const scoped = resolveToolAccount("memory-archive-write", targetAccountId);
|
|
1417
|
+
if ("reject" in scoped)
|
|
1418
|
+
return scoped.reject;
|
|
1419
|
+
const accountId = scoped.accountId;
|
|
1342
1420
|
try {
|
|
1343
1421
|
const result = await memoryArchiveWrite({
|
|
1344
1422
|
archiveType,
|
|
@@ -1418,9 +1496,12 @@ if (!readOnly) {
|
|
|
1418
1496
|
.string()
|
|
1419
1497
|
.optional()
|
|
1420
1498
|
.describe("Skill-run UUID for provenance stamping. Falls back to SESSION_ID env var when absent."),
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1499
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
1500
|
+
}, async ({ ownerNodeId, extractedDir, mode, importId, filters, resolutions, selectiveIngestThreshold, sessionId: sessionIdOverride, targetAccountId, }) => {
|
|
1501
|
+
const scoped = resolveToolAccount("obsidian-vault-import", targetAccountId);
|
|
1502
|
+
if ("reject" in scoped)
|
|
1503
|
+
return scoped.reject;
|
|
1504
|
+
const accountId = scoped.accountId;
|
|
1424
1505
|
try {
|
|
1425
1506
|
const result = await obsidianVaultImport({
|
|
1426
1507
|
accountId,
|
|
@@ -1469,9 +1550,12 @@ if (!readOnly) {
|
|
|
1469
1550
|
"When present, used verbatim as `KnowledgeDocument.name` (capped at 200 chars). " +
|
|
1470
1551
|
"When absent, the server falls back to the markdown H1, then a URL-derived slug, then the URL."),
|
|
1471
1552
|
scope: z.string().optional().describe("Intended visibility scope (for logging). The actual scope is set when the agent subsequently calls memory-ingest."),
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1553
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
1554
|
+
}, async ({ url, content, title, scope, targetAccountId }) => {
|
|
1555
|
+
const scoped = resolveToolAccount("memory-ingest-web", targetAccountId);
|
|
1556
|
+
if ("reject" in scoped)
|
|
1557
|
+
return scoped.reject;
|
|
1558
|
+
const accountId = scoped.accountId;
|
|
1475
1559
|
try {
|
|
1476
1560
|
const result = await memoryIngestWeb({
|
|
1477
1561
|
accountId,
|
|
@@ -1518,9 +1602,12 @@ if (!readOnly) {
|
|
|
1518
1602
|
agentType: z.enum(["admin", "public"]).optional().describe("Scope to conversations matching c.agentType. Omit to scope across both."),
|
|
1519
1603
|
limit: z.number().int().positive().optional().describe("Max candidates to return (default 200, hard cap 1000)."),
|
|
1520
1604
|
dryRun: z.boolean().optional().describe("Preview matches without minting an actionable filterToken. Candidates are listed in the response, but no delete can be performed against them — caller must re-run without dryRun to receive a token."),
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1605
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
1606
|
+
}, async ({ filter, agentType, limit, dryRun, targetAccountId }) => {
|
|
1607
|
+
const scoped = resolveToolAccount("memory-find-candidates", targetAccountId);
|
|
1608
|
+
if ("reject" in scoped)
|
|
1609
|
+
return scoped.reject;
|
|
1610
|
+
const accountId = scoped.accountId;
|
|
1524
1611
|
try {
|
|
1525
1612
|
const result = await memoryFindCandidates({ accountId, filter, agentType, limit, dryRun });
|
|
1526
1613
|
if (result.items.length === 0) {
|
|
@@ -1561,9 +1648,12 @@ if (!readOnly) {
|
|
|
1561
1648
|
"ranked discovery on general labels. Use this before any branch that claims a " +
|
|
1562
1649
|
"singleton root is missing.", {
|
|
1563
1650
|
label: z.enum(MEMORY_NODE_EXISTS_LABELS).describe("Installer-seeded singleton label. One of: LocalBusiness, AdminUser, UserProfile, Person."),
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1651
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
1652
|
+
}, async ({ label, targetAccountId }) => {
|
|
1653
|
+
const scoped = resolveToolAccount("memory-node-exists", targetAccountId);
|
|
1654
|
+
if ("reject" in scoped)
|
|
1655
|
+
return scoped.reject;
|
|
1656
|
+
const accountId = scoped.accountId;
|
|
1567
1657
|
try {
|
|
1568
1658
|
const result = await memoryNodeExists({ accountId, label });
|
|
1569
1659
|
const payload = JSON.stringify(result);
|
|
@@ -1588,9 +1678,12 @@ if (!readOnly) {
|
|
|
1588
1678
|
filterToken: z.string().optional().describe("Opaque token from memory-find-candidates. Required for bulk-selector flows; the server re-runs the " +
|
|
1589
1679
|
"canonical predicate on this elementId before trashing. Omit for single-node deletes where the caller " +
|
|
1590
1680
|
"chose the target directly (e.g. from a memory-search result)."),
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1681
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
1682
|
+
}, async ({ elementId, reason, filterToken, targetAccountId }) => {
|
|
1683
|
+
const scoped = resolveToolAccount("memory-delete", targetAccountId);
|
|
1684
|
+
if ("reject" in scoped)
|
|
1685
|
+
return scoped.reject;
|
|
1686
|
+
const accountId = scoped.accountId;
|
|
1594
1687
|
try {
|
|
1595
1688
|
const result = await memoryDelete({ accountId, elementId, reason, filterToken });
|
|
1596
1689
|
const head = result.alreadyTrashed
|
|
@@ -1617,9 +1710,12 @@ if (!readOnly) {
|
|
|
1617
1710
|
"node needs back (e.g. a fresh LocalBusiness was created while the old one was in trash) — " +
|
|
1618
1711
|
"the error names the conflicting elementId so the caller can decide how to resolve.", {
|
|
1619
1712
|
elementId: z.string().describe("Neo4j elementId of the trashed node to restore."),
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1713
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
1714
|
+
}, async ({ elementId, targetAccountId }) => {
|
|
1715
|
+
const scoped = resolveToolAccount("memory-restore", targetAccountId);
|
|
1716
|
+
if ("reject" in scoped)
|
|
1717
|
+
return scoped.reject;
|
|
1718
|
+
const accountId = scoped.accountId;
|
|
1623
1719
|
try {
|
|
1624
1720
|
const result = await memoryRestore({ accountId, elementId });
|
|
1625
1721
|
const cascade = result.cascade.sections + result.cascade.chunks > 0
|
|
@@ -1647,9 +1743,12 @@ if (!readOnly) {
|
|
|
1647
1743
|
graceDays: z.number().int().min(0).optional().describe("Minimum age in days a trashed node must reach before it's eligible. Default 30."),
|
|
1648
1744
|
dryRun: z.boolean().optional().describe("When true, lists candidates without deleting. Default false."),
|
|
1649
1745
|
labels: z.array(z.string()).optional().describe("Optional whitelist of node labels — only nodes carrying any of these labels are eligible."),
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1746
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
1747
|
+
}, async ({ graceDays, dryRun, labels, targetAccountId }) => {
|
|
1748
|
+
const scoped = resolveToolAccount("memory-empty-trash", targetAccountId);
|
|
1749
|
+
if ("reject" in scoped)
|
|
1750
|
+
return scoped.reject;
|
|
1751
|
+
const accountId = scoped.accountId;
|
|
1653
1752
|
try {
|
|
1654
1753
|
const result = await memoryEmptyTrash({ accountId, graceDays, dryRun, labels });
|
|
1655
1754
|
const lines = [];
|
|
@@ -1673,9 +1772,13 @@ if (!readOnly) {
|
|
|
1673
1772
|
});
|
|
1674
1773
|
lifelineTool(server, "memory-list-attachments", "List stored file attachments for this account with their ingestion status. " +
|
|
1675
1774
|
"Returns original filenames, sizes, upload dates, and whether each file has been ingested " +
|
|
1676
|
-
"into the knowledge graph. Does not include web-ingested documents (those have no file on disk).", {
|
|
1677
|
-
|
|
1678
|
-
|
|
1775
|
+
"into the knowledge graph. Does not include web-ingested documents (those have no file on disk).", {
|
|
1776
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
1777
|
+
}, async ({ targetAccountId }) => {
|
|
1778
|
+
const scoped = resolveToolAccount("memory-list-attachments", targetAccountId);
|
|
1779
|
+
if ("reject" in scoped)
|
|
1780
|
+
return scoped.reject;
|
|
1781
|
+
const accountId = scoped.accountId;
|
|
1679
1782
|
try {
|
|
1680
1783
|
const result = await memoryListAttachments(accountId);
|
|
1681
1784
|
if (result.entries.length === 0) {
|
|
@@ -1713,9 +1816,12 @@ if (!readOnly) {
|
|
|
1713
1816
|
"extracted text for PDFs (via pdftotext), and metadata + HTTP URL for images. " +
|
|
1714
1817
|
"Use this to show the user what's in a file or to prepare content for editing.", {
|
|
1715
1818
|
attachmentId: z.string().describe("UUID of the attachment to read"),
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1819
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
1820
|
+
}, async ({ attachmentId, targetAccountId }) => {
|
|
1821
|
+
const scoped = resolveToolAccount("memory-read-attachment", targetAccountId);
|
|
1822
|
+
if ("reject" in scoped)
|
|
1823
|
+
return scoped.reject;
|
|
1824
|
+
const accountId = scoped.accountId;
|
|
1719
1825
|
try {
|
|
1720
1826
|
const result = await memoryReadAttachment(accountId, attachmentId);
|
|
1721
1827
|
let text = `**${result.filename}** (${result.mimeType}, ${result.sizeBytes} bytes)\nStored: ${result.storedAt}\n`;
|
|
@@ -1740,9 +1846,12 @@ if (!readOnly) {
|
|
|
1740
1846
|
"Only text/plain and text/markdown files are editable — PDFs and images are rejected.", {
|
|
1741
1847
|
attachmentId: z.string().describe("UUID of the attachment to edit"),
|
|
1742
1848
|
content: z.string().describe("The full replacement text content"),
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1849
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
1850
|
+
}, async ({ attachmentId, content, targetAccountId }) => {
|
|
1851
|
+
const scoped = resolveToolAccount("memory-edit-attachment", targetAccountId);
|
|
1852
|
+
if ("reject" in scoped)
|
|
1853
|
+
return scoped.reject;
|
|
1854
|
+
const accountId = scoped.accountId;
|
|
1746
1855
|
try {
|
|
1747
1856
|
const result = await memoryEditAttachment({ accountId, attachmentId, content });
|
|
1748
1857
|
let text = `Edited: ${result.filename} (${result.oldSizeBytes} → ${result.newSizeBytes} bytes)`;
|
|
@@ -1768,9 +1877,12 @@ if (!readOnly) {
|
|
|
1768
1877
|
"is not renamed — it uses UUID-based naming. Only the human-readable metadata changes.", {
|
|
1769
1878
|
attachmentId: z.string().describe("UUID of the attachment to rename"),
|
|
1770
1879
|
newFilename: z.string().describe("The new filename (e.g. 'quarterly-report-q1.pdf')"),
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1880
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
1881
|
+
}, async ({ attachmentId, newFilename, targetAccountId }) => {
|
|
1882
|
+
const scoped = resolveToolAccount("memory-rename-attachment", targetAccountId);
|
|
1883
|
+
if ("reject" in scoped)
|
|
1884
|
+
return scoped.reject;
|
|
1885
|
+
const accountId = scoped.accountId;
|
|
1774
1886
|
try {
|
|
1775
1887
|
const result = await memoryRenameAttachment({ accountId, attachmentId, newFilename });
|
|
1776
1888
|
if (result.oldFilename === result.newFilename) {
|
|
@@ -1874,9 +1986,12 @@ if (!readOnly) {
|
|
|
1874
1986
|
.number()
|
|
1875
1987
|
.optional()
|
|
1876
1988
|
.describe("Maximum results (default 50 for conversations, 200 for messages)"),
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1989
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
1990
|
+
}, async ({ sessionId, agentType, agentSlug, since, includeMessages, limit, targetAccountId }) => {
|
|
1991
|
+
const scoped = resolveToolAccount("conversation-list", targetAccountId);
|
|
1992
|
+
if ("reject" in scoped)
|
|
1993
|
+
return scoped.reject;
|
|
1994
|
+
const accountId = scoped.accountId;
|
|
1880
1995
|
const startTime = Date.now();
|
|
1881
1996
|
const dbSession = getSession();
|
|
1882
1997
|
try {
|
|
@@ -2056,8 +2171,10 @@ if (!readOnly) {
|
|
|
2056
2171
|
mergeSourceIds: z.array(z.string()).optional()
|
|
2057
2172
|
.describe("For mode 'merge': preferenceIds of sources to combine into this preference"),
|
|
2058
2173
|
}, async ({ category, key, value, source, mode, sessionId, profileFields, personFields, mergeSourceIds }) => {
|
|
2059
|
-
|
|
2060
|
-
|
|
2174
|
+
const scoped = resolveToolAccount("profile-update", undefined);
|
|
2175
|
+
if ("reject" in scoped)
|
|
2176
|
+
return scoped.reject;
|
|
2177
|
+
const accountId = scoped.accountId;
|
|
2061
2178
|
try {
|
|
2062
2179
|
if (!userId) {
|
|
2063
2180
|
return { content: [{ type: "text", text: "profile-update requires an authenticated admin session with userId" }], isError: true };
|
|
@@ -2097,8 +2214,10 @@ if (!readOnly) {
|
|
|
2097
2214
|
.describe("Preference category"),
|
|
2098
2215
|
key: z.string().describe("Preference key to delete"),
|
|
2099
2216
|
}, async ({ category, key }) => {
|
|
2100
|
-
|
|
2101
|
-
|
|
2217
|
+
const scoped = resolveToolAccount("profile-delete", undefined);
|
|
2218
|
+
if ("reject" in scoped)
|
|
2219
|
+
return scoped.reject;
|
|
2220
|
+
const accountId = scoped.accountId;
|
|
2102
2221
|
try {
|
|
2103
2222
|
if (!userId) {
|
|
2104
2223
|
return { content: [{ type: "text", text: "profile-delete requires an authenticated admin session with userId" }], isError: true };
|
|
@@ -2131,8 +2250,10 @@ if (!readOnly) {
|
|
|
2131
2250
|
detail: z.boolean().optional().describe("When true, returns per-preference confidence, source, evidence trail, and memory statistics. " +
|
|
2132
2251
|
"Default false returns a compact summary for system prompt injection."),
|
|
2133
2252
|
}, async ({ detail }) => {
|
|
2134
|
-
|
|
2135
|
-
|
|
2253
|
+
const scoped = resolveToolAccount("profile-read", undefined);
|
|
2254
|
+
if ("reject" in scoped)
|
|
2255
|
+
return scoped.reject;
|
|
2256
|
+
const accountId = scoped.accountId;
|
|
2136
2257
|
try {
|
|
2137
2258
|
if (!userId) {
|
|
2138
2259
|
return { content: [{ type: "text", text: "profile-read requires an authenticated admin session with userId" }], isError: true };
|
|
@@ -2166,10 +2287,13 @@ if (!readOnly) {
|
|
|
2166
2287
|
"Use this when the operator asks 'what has the brain captured today?', 'show me recent mentions of X', or 'what ideas did I leave on the table this week?'.", {
|
|
2167
2288
|
windowHours: z.number().int().optional().describe("Hours back from now. Default 24. Capped at 720 (30 days)."),
|
|
2168
2289
|
limit: z.number().int().optional().describe("Max rows returned. Default 50, max 200."),
|
|
2169
|
-
|
|
2290
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
2291
|
+
}, async ({ windowHours, limit, targetAccountId }) => {
|
|
2170
2292
|
try {
|
|
2171
|
-
|
|
2172
|
-
|
|
2293
|
+
const scoped = resolveToolAccount("memory-brain-capture-recent", targetAccountId);
|
|
2294
|
+
if ("reject" in scoped)
|
|
2295
|
+
return scoped.reject;
|
|
2296
|
+
const accountId = scoped.accountId;
|
|
2173
2297
|
const result = await memoryBrainCaptureRecent({ accountId, windowHours, limit });
|
|
2174
2298
|
return {
|
|
2175
2299
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
@@ -2203,8 +2327,10 @@ if (!readOnly) {
|
|
|
2203
2327
|
"per-device and survives upgrades.", {
|
|
2204
2328
|
values: z.array(z.string().min(1)).min(1).describe("Substring values to add. Match is exact substring (case-sensitive) against string-typed properties only."),
|
|
2205
2329
|
}, async ({ values }) => {
|
|
2206
|
-
|
|
2207
|
-
|
|
2330
|
+
const scoped = resolveToolAccount("graph-prune-denylist-add", undefined);
|
|
2331
|
+
if ("reject" in scoped)
|
|
2332
|
+
return scoped.reject;
|
|
2333
|
+
const accountId = scoped.accountId;
|
|
2208
2334
|
try {
|
|
2209
2335
|
const result = await graphPruneDenylistAdd(values);
|
|
2210
2336
|
const lines = [
|
|
@@ -2229,8 +2355,10 @@ if (!readOnly) {
|
|
|
2229
2355
|
"restored — audit entries on each affected node remain for forensic review.", {
|
|
2230
2356
|
values: z.array(z.string().min(1)).min(1).describe("Substring values to remove (must match exactly as previously added)."),
|
|
2231
2357
|
}, async ({ values }) => {
|
|
2232
|
-
|
|
2233
|
-
|
|
2358
|
+
const scoped = resolveToolAccount("graph-prune-denylist-remove", undefined);
|
|
2359
|
+
if ("reject" in scoped)
|
|
2360
|
+
return scoped.reject;
|
|
2361
|
+
const accountId = scoped.accountId;
|
|
2234
2362
|
try {
|
|
2235
2363
|
const result = await graphPruneDenylistRemove(values);
|
|
2236
2364
|
const lines = [
|
|
@@ -2257,9 +2385,12 @@ if (!readOnly) {
|
|
|
2257
2385
|
"that should not propagate (e.g. wrong-account hostnames, fabricated identifiers).", {
|
|
2258
2386
|
sessionId: z.string().min(1).describe("The Conversation node's sessionId to scope the expunge to."),
|
|
2259
2387
|
pattern: z.string().min(1).describe("The substring to scrub from string properties on linked :Memory nodes."),
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2388
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
2389
|
+
}, async ({ sessionId, pattern, targetAccountId }) => {
|
|
2390
|
+
const scoped = resolveToolAccount("conversation-memory-expunge", targetAccountId);
|
|
2391
|
+
if ("reject" in scoped)
|
|
2392
|
+
return scoped.reject;
|
|
2393
|
+
const accountId = scoped.accountId;
|
|
2263
2394
|
try {
|
|
2264
2395
|
const result = await conversationMemoryExpunge({ accountId, sessionId, pattern });
|
|
2265
2396
|
const lines = [
|
|
@@ -2286,8 +2417,10 @@ if (!readOnly) {
|
|
|
2286
2417
|
// graph-prune-denylist-list and conversation-search are read-only — available regardless of readOnly mode.
|
|
2287
2418
|
lifelineTool(server, "graph-prune-denylist-list", "List the current operator-curated deny-list values used by the daily graph-prune cron. " +
|
|
2288
2419
|
"Returns the substring values, the timestamp of the last edit, and the total count.", {}, () => {
|
|
2289
|
-
|
|
2290
|
-
|
|
2420
|
+
const scoped = resolveToolAccount("graph-prune-denylist-list", undefined);
|
|
2421
|
+
if ("reject" in scoped)
|
|
2422
|
+
return scoped.reject;
|
|
2423
|
+
const accountId = scoped.accountId;
|
|
2291
2424
|
try {
|
|
2292
2425
|
const result = graphPruneDenylistList();
|
|
2293
2426
|
if (result.count === 0) {
|
|
@@ -2311,9 +2444,12 @@ eagerTool(server, "conversation-search", "Search conversation history using sema
|
|
|
2311
2444
|
.number()
|
|
2312
2445
|
.optional()
|
|
2313
2446
|
.describe("Maximum number of results (default 10)"),
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2447
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
2448
|
+
}, async ({ query, limit: maxResults, targetAccountId }) => {
|
|
2449
|
+
const scoped = resolveToolAccount("conversation-search", targetAccountId);
|
|
2450
|
+
if ("reject" in scoped)
|
|
2451
|
+
return scoped.reject;
|
|
2452
|
+
const accountId = scoped.accountId;
|
|
2317
2453
|
try {
|
|
2318
2454
|
const queryEmbedding = await embed(query);
|
|
2319
2455
|
const resultLimit = maxResults ?? 10;
|
|
@@ -2438,9 +2574,12 @@ lifelineTool(server, "memory-dream-run", "Operator-initiated dream-cycle: graph-
|
|
|
2438
2574
|
operatorId: z.string().optional().describe("Identifier of the operator who triggered the run; appears in the report and log line."),
|
|
2439
2575
|
phases: z.array(z.number().int().min(1).max(7)).optional().describe("Subset of phases to run. Default [1,2,3,4,5,6,7]. Order is fixed."),
|
|
2440
2576
|
maxEventsPerRun: z.number().int().positive().optional().describe("Phase 4 cap on :TimelineEvent rows scanned per run. Default 200."),
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2577
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
2578
|
+
}, async ({ operatorId, phases, maxEventsPerRun, targetAccountId }) => {
|
|
2579
|
+
const scoped = resolveToolAccount("memory-dream-run", targetAccountId);
|
|
2580
|
+
if ("reject" in scoped)
|
|
2581
|
+
return scoped.reject;
|
|
2582
|
+
const accountId = scoped.accountId;
|
|
2444
2583
|
try {
|
|
2445
2584
|
const result = await memoryDreamRun({ accountId, operatorId, phases, maxEventsPerRun });
|
|
2446
2585
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
@@ -2455,9 +2594,12 @@ lifelineTool(server, "memory-dream-run", "Operator-initiated dream-cycle: graph-
|
|
|
2455
2594
|
lifelineTool(server, "memory-review-queue", "Read-only summary of the dream-cycle's review queues (:OrphanCandidate, :CitationProposal). " +
|
|
2456
2595
|
"Returns per-queue counts and a small sample so the operator can see whether to triage.", {
|
|
2457
2596
|
sampleSize: z.number().int().positive().optional().describe("Sample rows per queue. Default 5, max 25."),
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2597
|
+
targetAccountId: z.string().optional().describe(XACCT_DESC),
|
|
2598
|
+
}, async ({ sampleSize, targetAccountId }) => {
|
|
2599
|
+
const scoped = resolveToolAccount("memory-review-queue", targetAccountId);
|
|
2600
|
+
if ("reject" in scoped)
|
|
2601
|
+
return scoped.reject;
|
|
2602
|
+
const accountId = scoped.accountId;
|
|
2461
2603
|
try {
|
|
2462
2604
|
const result = await memoryReviewQueue({ accountId, sampleSize });
|
|
2463
2605
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|