vault-go 0.27.0 → 0.29.0
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/README.md +4 -0
- package/dist/cloud.d.ts +2 -0
- package/dist/cloud.js +3 -0
- package/dist/hooks.d.ts +2 -0
- package/dist/hooks.js +27 -5
- package/dist/knowledge-agent.d.ts +2 -2
- package/dist/project-scope.d.ts +13 -0
- package/dist/project-scope.js +22 -0
- package/dist/repo-key.d.ts +7 -0
- package/dist/repo-key.js +91 -0
- package/dist/server.js +27 -7
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -148,6 +148,10 @@ Projects and sessions: `vault_go_projects`, `vault_go_project_create`, `vault_go
|
|
|
148
148
|
|
|
149
149
|
Capture and recall: `vault_go_event`, `vault_go_remember`, `vault_go_forget`, `vault_go_search`, `vault_go_search_index`, `vault_go_retrieve`, `vault_go_observations`, `vault_go_timeline`, `vault_go_context`, `vault_go_file_context`, `vault_go_feed`, `vault_go_memory`, `vault_go_tool_uses`, `vault_go_stats`.
|
|
150
150
|
|
|
151
|
+
Projects are matched by path first and then by repository: vault-go reads the checkout's `origin` remote, normalizes it to `host/owner/repo` and records it as the project's `repoKey`. A clone on another machine or user joins the oldest project with the same `repoKey` instead of creating a new one, and projects created before this are backfilled the first time a capture matches them by path.
|
|
152
|
+
|
|
153
|
+
Read tools (`vault_go_search`, `vault_go_search_index`, `vault_go_feed`, `vault_go_retrieve` and query-anchored `vault_go_timeline`) are scoped to the project of the MCP server's working directory when no `projectId` is given; a git worktree maps to its main checkout. Pass `scope: "account"` to search every project of the account. Outside a known project they fall back to the account, and no project is created. Memories marked private stay out of search and feed results unless `includePrivate: true` is set.
|
|
154
|
+
|
|
151
155
|
`vault_go_retrieve` lets the central memory engine choose a bounded retrieval path while every explicit retrieval tool remains available. `vault_go_decision_status` reports sanitized rollout/circuit state. Jev and its credential remain in the engine; a healthy deployment does not by itself prove provider availability or decision quality. `vault_go_decide` sends a caller-authored state plus up to 8 typed questions (`noul`, `choice`, `score`) to the central Jev and returns probabilities; it runs only in `full` rollout, one call at a time, refuses secrets, e-mails, identifiers, URLs and absolute local paths before anything leaves Vault, and persists nothing. The caller still owns the decision.
|
|
152
156
|
|
|
153
157
|
Knowledge bases: `vault_go_knowledge_bases`, `vault_go_knowledge_base`, `vault_go_knowledge_build`, `vault_go_knowledge_rebuild`, `vault_go_knowledge_query`, `vault_go_knowledge_delete`, `vault_go_prime_corpus`, `vault_go_query_corpus`, `vault_go_reprime_corpus`.
|
package/dist/cloud.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export interface VaultMemoryApi {
|
|
|
18
18
|
health(): Promise<unknown>;
|
|
19
19
|
projects(): Promise<unknown>;
|
|
20
20
|
createProject(input: Record<string, unknown>): Promise<unknown>;
|
|
21
|
+
updateProject?(id: string, input: Record<string, unknown>): Promise<unknown>;
|
|
21
22
|
startSession(input: Record<string, unknown>): Promise<unknown>;
|
|
22
23
|
endSession(id: string): Promise<unknown>;
|
|
23
24
|
event(input: Record<string, unknown>): Promise<unknown>;
|
|
@@ -65,6 +66,7 @@ export declare class VaultCloudClient implements VaultMemoryApi {
|
|
|
65
66
|
rotateDevice(id: string): Promise<unknown>;
|
|
66
67
|
deviceAction(id: string, token: string, action: 'heartbeat' | 'disconnect', body?: Record<string, unknown>): Promise<unknown>;
|
|
67
68
|
projects(): Promise<unknown>;
|
|
69
|
+
updateProject(id: string, input: Record<string, unknown>): Promise<unknown>;
|
|
68
70
|
createProject(input: Record<string, unknown>): Promise<unknown>;
|
|
69
71
|
startSession(input: Record<string, unknown>): Promise<unknown>;
|
|
70
72
|
endSession(id: string): Promise<unknown>;
|
package/dist/cloud.js
CHANGED
|
@@ -80,6 +80,9 @@ export class VaultCloudClient {
|
|
|
80
80
|
async projects() {
|
|
81
81
|
return this.request('/memory/projects');
|
|
82
82
|
}
|
|
83
|
+
async updateProject(id, input) {
|
|
84
|
+
return this.request(`/memory/projects/${encodeURIComponent(id)}`, { method: 'PATCH', body: input });
|
|
85
|
+
}
|
|
83
86
|
async createProject(input) {
|
|
84
87
|
return this.request('/memory/projects', { method: 'POST', body: input });
|
|
85
88
|
}
|
package/dist/hooks.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ import { type VaultMemoryApi } from "./cloud.js";
|
|
|
3
3
|
export declare const HOOK_EVENTS: readonly ["context", "session-init", "observation", "file-context", "summarize"];
|
|
4
4
|
export type HookEvent = (typeof HOOK_EVENTS)[number];
|
|
5
5
|
type RecordValue = Record<string, unknown>;
|
|
6
|
+
/** The existing project for a working directory (worktrees map to their main checkout); never creates one. */
|
|
7
|
+
export declare function findWorkspaceProject(cloud: Pick<VaultMemoryApi, "projects">, cwd: string): Promise<RecordValue | undefined>;
|
|
6
8
|
export declare function normalizeHookInput(adapter: string, value: unknown): RecordValue;
|
|
7
9
|
export declare function hookOutput(event: HookEvent, context?: string, adapter?: string): RecordValue;
|
|
8
10
|
export declare function executeHook(adapter: string, event: HookEvent, value: unknown, cloud?: VaultMemoryApi, home?: string, options?: {
|
package/dist/hooks.js
CHANGED
|
@@ -5,6 +5,7 @@ import { basename, dirname, isAbsolute, relative, resolve } from "node:path";
|
|
|
5
5
|
import { existsSync, readFileSync, realpathSync, statSync } from "node:fs";
|
|
6
6
|
import { applyCustomModeContext } from './custom-modes.js';
|
|
7
7
|
import { VaultCloudClient } from "./cloud.js";
|
|
8
|
+
import { repoKey } from "./repo-key.js";
|
|
8
9
|
import { vaultHome } from "./config.js";
|
|
9
10
|
import { enqueueGeneration } from "./hook-queue.js";
|
|
10
11
|
import { transcriptCaptureEnabled } from './transcript-config.js';
|
|
@@ -66,6 +67,25 @@ function projectRoots(workspace) {
|
|
|
66
67
|
return fallback;
|
|
67
68
|
}
|
|
68
69
|
}
|
|
70
|
+
function matchWorkspaceProject(projects, roots, key) {
|
|
71
|
+
if (!Array.isArray(projects))
|
|
72
|
+
throw new Error("Resposta de projetos inválida");
|
|
73
|
+
const byPath = roots.map((cwd) => projects.find((item) => item &&
|
|
74
|
+
typeof item === "object" &&
|
|
75
|
+
typeof item.rootPath === "string" &&
|
|
76
|
+
Boolean(String(item.rootPath).trim()) &&
|
|
77
|
+
resolvedPath(String(item.rootPath)) === cwd)).find(Boolean);
|
|
78
|
+
if (byPath || !key)
|
|
79
|
+
return byPath;
|
|
80
|
+
// Why: a clone on another machine or user shares the repository, not the path.
|
|
81
|
+
// Projects arrive newest first; the oldest one with this key is the canonical one.
|
|
82
|
+
return projects.filter((item) => item && typeof item === "object" && item.repoKey === key).at(-1);
|
|
83
|
+
}
|
|
84
|
+
/** The existing project for a working directory (worktrees map to their main checkout); never creates one. */
|
|
85
|
+
export async function findWorkspaceProject(cloud, cwd) {
|
|
86
|
+
const workspace = root(cwd);
|
|
87
|
+
return matchWorkspaceProject(await cloud.projects(), projectRoots(workspace), repoKey(workspace));
|
|
88
|
+
}
|
|
69
89
|
function canonicalFile(file, workspace, project) {
|
|
70
90
|
const absolute = resolve(workspace, file);
|
|
71
91
|
for (const directory of [workspace, resolvedPath(workspace)]) {
|
|
@@ -173,11 +193,8 @@ export async function executeHook(adapter, event, value, cloud = new VaultCloudC
|
|
|
173
193
|
const projects = await cloud.projects();
|
|
174
194
|
if (!Array.isArray(projects))
|
|
175
195
|
throw new Error("Resposta de projetos inválida");
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
typeof item.rootPath === "string" &&
|
|
179
|
-
Boolean(String(item.rootPath).trim()) &&
|
|
180
|
-
resolvedPath(String(item.rootPath)) === cwd)).find(Boolean);
|
|
196
|
+
const key = repoKey(workspace);
|
|
197
|
+
let project = matchWorkspaceProject(projects, roots, key);
|
|
181
198
|
const cwd = project ? resolvedPath(String(project.rootPath)) : roots[0];
|
|
182
199
|
if (!project && reading)
|
|
183
200
|
return hookOutput(event, "", adapter);
|
|
@@ -185,8 +202,13 @@ export async function executeHook(adapter, event, value, cloud = new VaultCloudC
|
|
|
185
202
|
project = record(await cloud.createProject({
|
|
186
203
|
name: (basename(cwd) || "workspace").padEnd(3, "_").slice(0, 80),
|
|
187
204
|
rootPath: cwd,
|
|
205
|
+
...(key ? { repoKey: key } : {}),
|
|
188
206
|
}));
|
|
189
207
|
}
|
|
208
|
+
else if (!reading && key && !project.repoKey && typeof project.id === "string" && cloud.updateProject) {
|
|
209
|
+
// Backfill projects created before repository keys; never blocks capture.
|
|
210
|
+
await cloud.updateProject(project.id, { repoKey: key }).catch(() => undefined);
|
|
211
|
+
}
|
|
190
212
|
if (typeof project.id !== "string")
|
|
191
213
|
throw new Error("Projeto inválido");
|
|
192
214
|
const limits = {
|
|
@@ -10,7 +10,7 @@ export declare function primeKnowledgeAgent(home: string, cloud: VaultMemoryApi,
|
|
|
10
10
|
primed: boolean;
|
|
11
11
|
memoryCount: number;
|
|
12
12
|
conversationReset: boolean;
|
|
13
|
-
engine: "vault-ai-resume" | "claude-subscription" | "openai-subscription" | "openrouter"
|
|
13
|
+
engine: "gemini" | "vault-ai-resume" | "claude-subscription" | "openai-subscription" | "openrouter";
|
|
14
14
|
model: string;
|
|
15
15
|
}>;
|
|
16
16
|
export declare function queryKnowledgeAgent(home: string, cloud: VaultMemoryApi, id: string, question: string, dependencies?: Dependencies): Promise<{
|
|
@@ -31,7 +31,7 @@ export declare function queryKnowledgeAgent(home: string, cloud: VaultMemoryApi,
|
|
|
31
31
|
title: string;
|
|
32
32
|
}[];
|
|
33
33
|
generated: boolean;
|
|
34
|
-
engine: "vault-ai-resume" | "claude-subscription" | "openai-subscription" | "openrouter"
|
|
34
|
+
engine: "gemini" | "vault-ai-resume" | "claude-subscription" | "openai-subscription" | "openrouter";
|
|
35
35
|
model: string;
|
|
36
36
|
conversationTurns: number;
|
|
37
37
|
contextTruncated: boolean;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { VaultMemoryApi } from './cloud.js';
|
|
2
|
+
export type ProjectScope = 'project' | 'account';
|
|
3
|
+
type ScopedInput = Record<string, unknown> & {
|
|
4
|
+
projectId?: string | undefined;
|
|
5
|
+
scope?: ProjectScope | undefined;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Why: MCP reads used to span every project of the account, so an agent in one
|
|
9
|
+
* repository received memories from unrelated clients. Reads now default to the
|
|
10
|
+
* project of the MCP server's working directory; `scope: "account"` widens them.
|
|
11
|
+
*/
|
|
12
|
+
export declare function createProjectScope(cloud: VaultMemoryApi, cwd?: () => string): (input: ScopedInput) => Promise<Record<string, unknown>>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { findWorkspaceProject } from './hooks.js';
|
|
2
|
+
const CACHE_MS = 60_000;
|
|
3
|
+
/**
|
|
4
|
+
* Why: MCP reads used to span every project of the account, so an agent in one
|
|
5
|
+
* repository received memories from unrelated clients. Reads now default to the
|
|
6
|
+
* project of the MCP server's working directory; `scope: "account"` widens them.
|
|
7
|
+
*/
|
|
8
|
+
export function createProjectScope(cloud, cwd = () => process.cwd()) {
|
|
9
|
+
let cached;
|
|
10
|
+
return async (input) => {
|
|
11
|
+
const { scope = 'project', ...rest } = input;
|
|
12
|
+
if (rest.projectId || scope === 'account')
|
|
13
|
+
return rest;
|
|
14
|
+
const workspace = cwd();
|
|
15
|
+
if (!cached || cached.cwd !== workspace || Date.now() - cached.at > CACHE_MS) {
|
|
16
|
+
const project = await findWorkspaceProject(cloud, workspace);
|
|
17
|
+
cached = { cwd: workspace, at: Date.now(), projectId: typeof project?.id === 'string' ? project.id : undefined };
|
|
18
|
+
}
|
|
19
|
+
// Outside a known project there is nothing narrower to scope to.
|
|
20
|
+
return cached.projectId ? { ...rest, projectId: cached.projectId } : rest;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalizes a git remote to `host/owner/repo` (no scheme, credentials, port or
|
|
3
|
+
* `.git`). Local paths and unrecognized forms return undefined.
|
|
4
|
+
*/
|
|
5
|
+
export declare function normalizeRemote(remote: string): string | undefined;
|
|
6
|
+
/** Repository key for a checkout (worktrees share their main checkout's remote). */
|
|
7
|
+
export declare function repoKey(workspace: string): string | undefined;
|
package/dist/repo-key.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
|
+
// Same shape the engine accepts: lowercase host plus 1–8 path segments.
|
|
4
|
+
const REPO_KEY = /^[a-z0-9][a-z0-9.-]{0,252}(\/[a-z0-9._~-]{1,200}){1,8}$/;
|
|
5
|
+
function smallFile(path, limit) {
|
|
6
|
+
try {
|
|
7
|
+
const file = statSync(path);
|
|
8
|
+
if (!file.isFile() || file.size > limit)
|
|
9
|
+
return undefined;
|
|
10
|
+
return readFileSync(path, 'utf8');
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/** The shared git directory holding `config`; worktrees point to it through `commondir`. */
|
|
17
|
+
function commonGitDir(workspace) {
|
|
18
|
+
const dotGit = resolve(workspace, '.git');
|
|
19
|
+
try {
|
|
20
|
+
if (statSync(dotGit).isDirectory())
|
|
21
|
+
return dotGit;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
const marker = /^gitdir:\s*(.+)$/m.exec(smallFile(dotGit, 4096) ?? '');
|
|
27
|
+
if (!marker)
|
|
28
|
+
return undefined;
|
|
29
|
+
const gitdir = resolve(workspace, marker[1].trim());
|
|
30
|
+
const common = smallFile(resolve(gitdir, 'commondir'), 4096)?.trim();
|
|
31
|
+
return common ? resolve(gitdir, common) : gitdir;
|
|
32
|
+
}
|
|
33
|
+
function originUrl(config) {
|
|
34
|
+
let section = '';
|
|
35
|
+
let first;
|
|
36
|
+
for (const line of config.split(/\r?\n/)) {
|
|
37
|
+
const header = /^\s*\[([^\]]+)\]\s*$/.exec(line);
|
|
38
|
+
if (header) {
|
|
39
|
+
section = header[1].trim();
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const url = /^\s*url\s*=\s*(.+?)\s*$/.exec(line);
|
|
43
|
+
if (!url || !section.startsWith('remote '))
|
|
44
|
+
continue;
|
|
45
|
+
if (section === 'remote "origin"')
|
|
46
|
+
return url[1];
|
|
47
|
+
first ??= url[1];
|
|
48
|
+
}
|
|
49
|
+
return first;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Normalizes a git remote to `host/owner/repo` (no scheme, credentials, port or
|
|
53
|
+
* `.git`). Local paths and unrecognized forms return undefined.
|
|
54
|
+
*/
|
|
55
|
+
export function normalizeRemote(remote) {
|
|
56
|
+
const value = remote.trim();
|
|
57
|
+
let host;
|
|
58
|
+
let path;
|
|
59
|
+
const scp = /^(?:[^@/\s]+@)?([^:/\s]+):(?!\/)(.+)$/.exec(value);
|
|
60
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value)) {
|
|
61
|
+
let url;
|
|
62
|
+
try {
|
|
63
|
+
url = new URL(value);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
if (url.protocol === 'file:')
|
|
69
|
+
return undefined;
|
|
70
|
+
host = url.hostname;
|
|
71
|
+
path = url.pathname;
|
|
72
|
+
}
|
|
73
|
+
else if (scp) {
|
|
74
|
+
host = scp[1];
|
|
75
|
+
path = scp[2];
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
const key = `${host}/${path.replace(/^\/+|\/+$/g, '').replace(/\.git$/i, '')}`.toLowerCase();
|
|
81
|
+
return REPO_KEY.test(key) && !key.endsWith('.git') ? key : undefined;
|
|
82
|
+
}
|
|
83
|
+
/** Repository key for a checkout (worktrees share their main checkout's remote). */
|
|
84
|
+
export function repoKey(workspace) {
|
|
85
|
+
const gitDir = commonGitDir(workspace);
|
|
86
|
+
if (!gitDir || dirname(gitDir) === gitDir)
|
|
87
|
+
return undefined;
|
|
88
|
+
const config = smallFile(resolve(gitDir, 'config'), 64 * 1024);
|
|
89
|
+
const url = config ? originUrl(config) : undefined;
|
|
90
|
+
return url ? normalizeRemote(url) : undefined;
|
|
91
|
+
}
|
package/dist/server.js
CHANGED
|
@@ -9,6 +9,7 @@ import { registerCrystalTools } from './crystal-tools.js';
|
|
|
9
9
|
import { registerModeIntegrations } from './mode-integrations.js';
|
|
10
10
|
import { registerKnowledgeAgentTools } from './knowledge-tools.js';
|
|
11
11
|
import { redact } from './hooks.js';
|
|
12
|
+
import { createProjectScope } from './project-scope.js';
|
|
12
13
|
import { VaultCloudClient } from './cloud.js';
|
|
13
14
|
import { getStatus, vaultHome } from './config.js';
|
|
14
15
|
import { createPrivateBackup, restorePrivateBackup } from './backup.js';
|
|
@@ -172,12 +173,23 @@ export function createVaultGoServer(home = vaultHome(), cloud = new VaultCloudCl
|
|
|
172
173
|
inputSchema: { id: uuid },
|
|
173
174
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true },
|
|
174
175
|
}, async ({ id }) => run(() => cloud.forget(id)));
|
|
176
|
+
const scoped = createProjectScope(cloud);
|
|
177
|
+
const scope = z
|
|
178
|
+
.enum(['project', 'account'])
|
|
179
|
+
.default('project')
|
|
180
|
+
.describe('project (padrão): só o projeto do diretório atual quando projectId não é informado; account: todos os projetos da conta.');
|
|
181
|
+
const includePrivate = z
|
|
182
|
+
.boolean()
|
|
183
|
+
.default(false)
|
|
184
|
+
.describe('Inclui memórias marcadas como privadas (por padrão ficam de fora).');
|
|
175
185
|
server.registerTool('vault_go_search', {
|
|
176
186
|
title: 'Pesquisar no Vault',
|
|
177
187
|
description: 'Pesquisa memórias persistidas na plataforma Vault.',
|
|
178
188
|
inputSchema: {
|
|
179
189
|
query: z.string().trim().max(1_000).default(''),
|
|
180
190
|
projectId: uuid.optional(),
|
|
191
|
+
scope,
|
|
192
|
+
includePrivate,
|
|
181
193
|
kind: z.string().trim().max(100).optional(),
|
|
182
194
|
memoryType: z.string().trim().max(100).optional(),
|
|
183
195
|
platformSource: z.string().trim().max(100).optional(),
|
|
@@ -190,23 +202,24 @@ export function createVaultGoServer(home = vaultHome(), cloud = new VaultCloudCl
|
|
|
190
202
|
orderBy: z.enum(['date_asc', 'date_desc']).optional(),
|
|
191
203
|
},
|
|
192
204
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
193
|
-
}, async (input) => run(() => cloud.search(input)));
|
|
205
|
+
}, async (input) => run(async () => cloud.search(await scoped(input))));
|
|
194
206
|
server.registerTool('vault_go_retrieve', {
|
|
195
207
|
title: 'Recuperação automática do Vault',
|
|
196
208
|
description: 'Delega ao motor central a escolha tipada entre busca, contexto de arquivo, linha do tempo, base de conhecimento, grafo ou nenhum resultado. Falhas usam busca determinística.',
|
|
197
209
|
inputSchema: {
|
|
198
210
|
query: z.string().trim().min(1).max(1_000),
|
|
199
211
|
projectId: uuid.optional(),
|
|
212
|
+
scope,
|
|
200
213
|
files: z.array(z.string().trim().min(1).max(2_000)).max(50).default([]),
|
|
201
214
|
knowledgeBaseId: uuid.optional(),
|
|
202
215
|
limit: z.number().int().min(1).max(200).default(20),
|
|
203
216
|
maxChars: z.number().int().min(1_000).max(100_000).optional(),
|
|
204
217
|
},
|
|
205
218
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
206
|
-
}, async (input) => run(() => {
|
|
219
|
+
}, async (input) => run(async () => {
|
|
207
220
|
if (!cloud.retrieve)
|
|
208
221
|
throw new Error('Native retrieval is unavailable on this deployment.');
|
|
209
|
-
return cloud.retrieve(input);
|
|
222
|
+
return cloud.retrieve(await scoped(input));
|
|
210
223
|
}));
|
|
211
224
|
server.registerTool('vault_go_decision_status', {
|
|
212
225
|
title: 'Status da camada de decisão',
|
|
@@ -258,6 +271,8 @@ export function createVaultGoServer(home = vaultHome(), cloud = new VaultCloudCl
|
|
|
258
271
|
inputSchema: {
|
|
259
272
|
query: z.string().trim().max(1_000).default(''),
|
|
260
273
|
projectId: uuid.optional(),
|
|
274
|
+
scope,
|
|
275
|
+
includePrivate,
|
|
261
276
|
kind: z.string().trim().max(100).optional(),
|
|
262
277
|
memoryType: z.string().trim().max(100).optional(),
|
|
263
278
|
platformSource: z.string().trim().max(100).optional(),
|
|
@@ -270,7 +285,7 @@ export function createVaultGoServer(home = vaultHome(), cloud = new VaultCloudCl
|
|
|
270
285
|
orderBy: z.enum(['date_asc', 'date_desc']).optional(),
|
|
271
286
|
},
|
|
272
287
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
273
|
-
}, async (input) => run(() => cloud.searchIndex(input)));
|
|
288
|
+
}, async (input) => run(async () => cloud.searchIndex(await scoped(input))));
|
|
274
289
|
server.registerTool('vault_go_observations', {
|
|
275
290
|
title: 'Carregar observações por ID',
|
|
276
291
|
description: 'Terceira camada de recuperação: carrega em lote somente as observações escolhidas no índice ou na linha do tempo.',
|
|
@@ -286,15 +301,18 @@ export function createVaultGoServer(home = vaultHome(), cloud = new VaultCloudCl
|
|
|
286
301
|
anchorId: uuid.optional(),
|
|
287
302
|
query: z.string().trim().min(1).max(1_000).optional(),
|
|
288
303
|
projectId: uuid.optional(),
|
|
304
|
+
scope,
|
|
289
305
|
platformSource: z.string().trim().min(1).max(100).optional(),
|
|
290
306
|
before: z.number().int().min(0).max(100).default(5),
|
|
291
307
|
after: z.number().int().min(0).max(100).default(5),
|
|
292
308
|
},
|
|
293
309
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
294
|
-
}, async (input) => run(() => {
|
|
310
|
+
}, async (input) => run(async () => {
|
|
295
311
|
if (Boolean(input.anchorId) === Boolean(input.query))
|
|
296
312
|
throw new Error('Informe exatamente anchorId ou query.');
|
|
297
|
-
|
|
313
|
+
// An anchor already identifies its project; only query anchors are scoped.
|
|
314
|
+
const { scope: _scope, ...anchored } = input;
|
|
315
|
+
return cloud.timeline(input.anchorId ? anchored : await scoped(input));
|
|
298
316
|
}));
|
|
299
317
|
server.registerTool('vault_go_context', {
|
|
300
318
|
title: 'Montar contexto',
|
|
@@ -329,6 +347,8 @@ export function createVaultGoServer(home = vaultHome(), cloud = new VaultCloudCl
|
|
|
329
347
|
description: 'Lista memórias recentes com paginação estável por cursor.',
|
|
330
348
|
inputSchema: {
|
|
331
349
|
projectId: uuid.optional(),
|
|
350
|
+
scope,
|
|
351
|
+
includePrivate,
|
|
332
352
|
kind: z.string().trim().max(100).optional(),
|
|
333
353
|
memoryType: z.string().trim().max(100).optional(),
|
|
334
354
|
platformSource: z.string().trim().max(100).optional(),
|
|
@@ -336,7 +356,7 @@ export function createVaultGoServer(home = vaultHome(), cloud = new VaultCloudCl
|
|
|
336
356
|
limit: z.number().int().min(1).max(100).default(20),
|
|
337
357
|
},
|
|
338
358
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
339
|
-
}, async (input) => run(() => cloud.feed(input)));
|
|
359
|
+
}, async (input) => run(async () => cloud.feed(await scoped(input))));
|
|
340
360
|
server.registerTool('vault_go_knowledge_bases', {
|
|
341
361
|
title: 'Listar bases de conhecimento',
|
|
342
362
|
description: 'Lista bases filtradas e persistidas na plataforma Vault.',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vault-go",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"description": "MCP server and installer for Vault Memory: search, capture, and use account memory across AI clients.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -84,7 +84,11 @@
|
|
|
84
84
|
"dist/mcp-clients.js",
|
|
85
85
|
"dist/mcp-clients.d.ts",
|
|
86
86
|
"dist/mcp-result.js",
|
|
87
|
+
"dist/project-scope.js",
|
|
87
88
|
"dist/mcp-result.d.ts",
|
|
89
|
+
"dist/project-scope.d.ts",
|
|
90
|
+
"dist/repo-key.js",
|
|
91
|
+
"dist/repo-key.d.ts",
|
|
88
92
|
"dist/parity-tools.js",
|
|
89
93
|
"dist/parity-tools.d.ts",
|
|
90
94
|
"dist/capabilities.js",
|
|
@@ -133,7 +137,7 @@
|
|
|
133
137
|
],
|
|
134
138
|
"scripts": {
|
|
135
139
|
"clean": "bun -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
136
|
-
"build": "bun run clean && tsc -p tsconfig.json",
|
|
140
|
+
"build": "bun run clean && tsc -p tsconfig.build.json",
|
|
137
141
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
138
142
|
"test": "bun run build && bun test src",
|
|
139
143
|
"pack:check": "npm pack --dry-run",
|