vault-go 0.16.1 → 0.17.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 -1
- package/dist/cli.js +2 -2
- package/dist/hook-install.d.ts +2 -1
- package/dist/hook-install.js +35 -0
- package/dist/hooks.d.ts +2 -1
- package/dist/hooks.js +44 -17
- package/dist/installer.d.ts +1 -1
- package/dist/installer.js +70 -2
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -76,6 +76,9 @@ Clientes suportados:
|
|
|
76
76
|
|
|
77
77
|
- Codex e ChatGPT Desktop local;
|
|
78
78
|
- Claude Code e Claude Desktop;
|
|
79
|
+
- Grok (config.toml nativo e hooks em `~/.grok/hooks`);
|
|
80
|
+
- Agy / Antigravity CLI e IDE;
|
|
81
|
+
- Gemini CLI;
|
|
79
82
|
- Cursor e Windsurf;
|
|
80
83
|
- VS Code com GitHub Copilot;
|
|
81
84
|
- GitHub Copilot CLI;
|
|
@@ -170,7 +173,7 @@ limitados.
|
|
|
170
173
|
|
|
171
174
|
O seletor de motor segue o mesmo modelo do claude-mem: Claude (CLI da assinatura), OpenRouter (chave), Gemini (chave) ou o Vault AI Resume da conta. Grave chaves com `vault-go engine key openrouter|gemini` ou no painel local; as ferramentas MCP não aceitam segredos.
|
|
172
175
|
|
|
173
|
-
Na instalação, o Vault Go registra hooks no Claude Code e no
|
|
176
|
+
Na instalação, o Vault Go registra hooks no Claude Code, no Codex, no Grok e no Agy. Eles injetam contexto no início da sessão, capturam prompts e ferramentas, e o serviço local (`http://localhost:38850`) gera memórias com o motor escolhido — o mesmo ciclo do claude-mem, persistindo no Vault.
|
|
174
177
|
|
|
175
178
|
O recurso `vault-go://status` fornece o resumo sanitizado em JSON.
|
|
176
179
|
|
package/dist/cli.js
CHANGED
|
@@ -324,8 +324,8 @@ Uso:
|
|
|
324
324
|
Escolhe o motor e o modelo de contexto. No Claude: haiku, sonnet ou opus.
|
|
325
325
|
|
|
326
326
|
vault-go hook <adaptador> <evento>
|
|
327
|
-
Usado pelos hooks do Claude
|
|
328
|
-
e enfileira geração com o motor escolhido.
|
|
327
|
+
Usado pelos hooks do Claude, Codex, Grok e Agy: injeta contexto,
|
|
328
|
+
captura atividade e enfileira geração com o motor escolhido.
|
|
329
329
|
|
|
330
330
|
--lang pt|en|es
|
|
331
331
|
Idioma do assistente (padrão: idioma do sistema).
|
package/dist/hook-install.d.ts
CHANGED
|
@@ -9,5 +9,6 @@ export declare const HOOK_EVENTS: {
|
|
|
9
9
|
export declare function quoteShell(value: string): string;
|
|
10
10
|
export declare function hookEntryPath(configHome?: string): string;
|
|
11
11
|
export declare function hookCommand(adapter: string, event: string, configHome?: string): string;
|
|
12
|
-
export
|
|
12
|
+
export type HookClient = "claude" | "codex" | "grok" | "agy";
|
|
13
|
+
export declare function installClientHooks(client: HookClient, userHome?: string, configHome?: string): void;
|
|
13
14
|
export declare function repairClientHooks(userHome?: string, configHome?: string): void;
|
package/dist/hook-install.js
CHANGED
|
@@ -73,7 +73,34 @@ function hookManifest(adapter, configHome = vaultHome()) {
|
|
|
73
73
|
])),
|
|
74
74
|
};
|
|
75
75
|
}
|
|
76
|
+
function agyHandler(event, configHome = vaultHome()) {
|
|
77
|
+
return {
|
|
78
|
+
type: "command",
|
|
79
|
+
command: hookCommand("agy", event, configHome),
|
|
80
|
+
timeout: event === "context" ? 60 : 20,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function agyHookManifest(configHome = vaultHome()) {
|
|
84
|
+
return {
|
|
85
|
+
PreInvocation: [agyHandler("context", configHome)],
|
|
86
|
+
PreToolUse: [{ matcher: "*", hooks: [agyHandler("file-context", configHome)] }],
|
|
87
|
+
PostToolUse: [
|
|
88
|
+
{ matcher: "*", hooks: [agyHandler("observation", configHome)] },
|
|
89
|
+
],
|
|
90
|
+
Stop: [agyHandler("summarize", configHome)],
|
|
91
|
+
};
|
|
92
|
+
}
|
|
76
93
|
export function installClientHooks(client, userHome = homedir(), configHome = vaultHome()) {
|
|
94
|
+
if (client === "grok") {
|
|
95
|
+
atomicWriteJson(join(userHome, ".grok", "hooks", "vault-go.json"), hookManifest("grok", configHome));
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (client === "agy") {
|
|
99
|
+
const path = join(userHome, ".gemini", "config", "hooks.json");
|
|
100
|
+
const config = readJsonObject(path);
|
|
101
|
+
atomicWriteJson(path, { ...config, "vault-go": agyHookManifest(configHome) });
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
77
104
|
const path = join(userHome, client === "claude" ? ".claude/settings.json" : ".codex/hooks.json");
|
|
78
105
|
const config = readJsonObject(path);
|
|
79
106
|
const hooks = {
|
|
@@ -110,4 +137,12 @@ export function installClientHooks(client, userHome = homedir(), configHome = va
|
|
|
110
137
|
export function repairClientHooks(userHome = homedir(), configHome = vaultHome()) {
|
|
111
138
|
installClientHooks("claude", userHome, configHome);
|
|
112
139
|
installClientHooks("codex", userHome, configHome);
|
|
140
|
+
if (existsSync(join(userHome, ".grok"))) {
|
|
141
|
+
installClientHooks("grok", userHome, configHome);
|
|
142
|
+
}
|
|
143
|
+
if (existsSync(join(userHome, ".gemini", "config")) ||
|
|
144
|
+
existsSync(join(userHome, ".gemini", "antigravity")) ||
|
|
145
|
+
existsSync(join(userHome, ".gemini", "antigravity-cli"))) {
|
|
146
|
+
installClientHooks("agy", userHome, configHome);
|
|
147
|
+
}
|
|
113
148
|
}
|
package/dist/hooks.d.ts
CHANGED
|
@@ -2,7 +2,8 @@ import { type VaultMemoryApi } from "./cloud.js";
|
|
|
2
2
|
export declare const HOOK_EVENTS: readonly ["context", "session-init", "observation", "file-context", "summarize"];
|
|
3
3
|
export type HookEvent = (typeof HOOK_EVENTS)[number];
|
|
4
4
|
type RecordValue = Record<string, unknown>;
|
|
5
|
-
export declare function
|
|
5
|
+
export declare function normalizeHookInput(adapter: string, value: unknown): RecordValue;
|
|
6
|
+
export declare function hookOutput(event: HookEvent, context?: string, adapter?: string): RecordValue;
|
|
6
7
|
export declare function executeHook(adapter: string, event: HookEvent, value: unknown, cloud?: VaultMemoryApi, home?: string): Promise<RecordValue>;
|
|
7
8
|
export declare function readHookInput(stream?: NodeJS.ReadableStream): Promise<unknown>;
|
|
8
9
|
export declare function runHook(adapter: string, event: string): Promise<void>;
|
package/dist/hooks.js
CHANGED
|
@@ -45,7 +45,34 @@ function redact(value) {
|
|
|
45
45
|
}
|
|
46
46
|
return value;
|
|
47
47
|
}
|
|
48
|
-
export function
|
|
48
|
+
export function normalizeHookInput(adapter, value) {
|
|
49
|
+
const input = record(value);
|
|
50
|
+
const toolCall = record(input.toolCall);
|
|
51
|
+
const workspaces = Array.isArray(input.workspacePaths)
|
|
52
|
+
? input.workspacePaths
|
|
53
|
+
: [];
|
|
54
|
+
const workspace = workspaces.find((item) => typeof item === "string" && Boolean(item.trim()));
|
|
55
|
+
return {
|
|
56
|
+
...input,
|
|
57
|
+
session_id: string(input.session_id, input.sessionId, input.conversation_id, input.conversationId, input.thread_id),
|
|
58
|
+
cwd: string(input.cwd, input.workspace, input.workspaceRoot, workspace),
|
|
59
|
+
tool_name: string(input.tool_name, input.toolName, toolCall.name),
|
|
60
|
+
tool_input: record(input.tool_input ?? input.toolInput ?? toolCall.args),
|
|
61
|
+
last_assistant_message: string(input.last_assistant_message, input.lastAssistantMessage, input.response, input.summary),
|
|
62
|
+
prompt: string(input.prompt, input.user_prompt, input.userPrompt),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export function hookOutput(event, context = "", adapter = "claude") {
|
|
66
|
+
if (adapter === "agy") {
|
|
67
|
+
if (event === "context" || event === "session-init") {
|
|
68
|
+
return context
|
|
69
|
+
? { injectSteps: [{ ephemeralMessage: context }] }
|
|
70
|
+
: {};
|
|
71
|
+
}
|
|
72
|
+
if (event === "file-context")
|
|
73
|
+
return { decision: "allow" };
|
|
74
|
+
return {};
|
|
75
|
+
}
|
|
49
76
|
const result = { continue: true, suppressOutput: true };
|
|
50
77
|
const name = event === "context"
|
|
51
78
|
? "SessionStart"
|
|
@@ -79,29 +106,29 @@ async function preferences(cloud) {
|
|
|
79
106
|
};
|
|
80
107
|
}
|
|
81
108
|
export async function executeHook(adapter, event, value, cloud = new VaultCloudClient(), home = vaultHome()) {
|
|
82
|
-
const input =
|
|
83
|
-
const toolName = string(input.tool_name
|
|
109
|
+
const input = normalizeHookInput(adapter, value);
|
|
110
|
+
const toolName = string(input.tool_name);
|
|
84
111
|
if (input.private === true ||
|
|
85
112
|
input.is_private === true ||
|
|
86
113
|
/vault[_-]go|vault[_-]mem/.test(toolName)) {
|
|
87
|
-
return hookOutput(event);
|
|
114
|
+
return hookOutput(event, "", adapter);
|
|
88
115
|
}
|
|
89
116
|
const prefs = await preferences(cloud);
|
|
90
117
|
const reading = event === "context" || event === "file-context";
|
|
91
118
|
if (!reading && prefs.automaticCapture !== true)
|
|
92
|
-
return hookOutput(event);
|
|
93
|
-
const tool = record(input.tool_input
|
|
94
|
-
const file = string(tool.file_path, tool.path, tool.notebook_path);
|
|
119
|
+
return hookOutput(event, "", adapter);
|
|
120
|
+
const tool = record(input.tool_input);
|
|
121
|
+
const file = string(tool.file_path, tool.path, tool.notebook_path, tool.AbsolutePath, tool.Path, tool.filePath);
|
|
95
122
|
const modifies = /write|edit|patch|create|delete|move|rename/i.test(toolName);
|
|
96
123
|
if (!reading && prefs.captureMode === "focused" && event !== "summarize")
|
|
97
|
-
return hookOutput(event);
|
|
124
|
+
return hookOutput(event, "", adapter);
|
|
98
125
|
if (event === "observation" && prefs.captureMode === "balanced" && !modifies)
|
|
99
|
-
return hookOutput(event);
|
|
126
|
+
return hookOutput(event, "", adapter);
|
|
100
127
|
if (event === "file-context" && !file)
|
|
101
|
-
return hookOutput(event);
|
|
102
|
-
const sessionId = string(input.session_id
|
|
128
|
+
return hookOutput(event, "", adapter);
|
|
129
|
+
const sessionId = string(input.session_id);
|
|
103
130
|
if (!reading && !sessionId)
|
|
104
|
-
return hookOutput(event);
|
|
131
|
+
return hookOutput(event, "", adapter);
|
|
105
132
|
const cwd = root(string(input.cwd, input.workspace) || process.cwd());
|
|
106
133
|
const projects = await cloud.projects();
|
|
107
134
|
if (!Array.isArray(projects))
|
|
@@ -110,7 +137,7 @@ export async function executeHook(adapter, event, value, cloud = new VaultCloudC
|
|
|
110
137
|
typeof item === "object" &&
|
|
111
138
|
resolve(String(item.rootPath || "")) === cwd);
|
|
112
139
|
if (!project && reading)
|
|
113
|
-
return hookOutput(event);
|
|
140
|
+
return hookOutput(event, "", adapter);
|
|
114
141
|
if (!project) {
|
|
115
142
|
project = record(await cloud.createProject({
|
|
116
143
|
name: (basename(cwd) || "workspace").padEnd(3, "_").slice(0, 80),
|
|
@@ -131,7 +158,7 @@ export async function executeHook(adapter, event, value, cloud = new VaultCloudC
|
|
|
131
158
|
paths: [...new Set([file, resolve(cwd, file)])],
|
|
132
159
|
})
|
|
133
160
|
: await cloud.context(limits));
|
|
134
|
-
return hookOutput(event, string(result.context).slice(0, 24_000));
|
|
161
|
+
return hookOutput(event, string(result.context).slice(0, 24_000), adapter);
|
|
135
162
|
}
|
|
136
163
|
const session = record(await cloud.startSession({
|
|
137
164
|
projectId: project.id,
|
|
@@ -140,8 +167,8 @@ export async function executeHook(adapter, event, value, cloud = new VaultCloudC
|
|
|
140
167
|
}));
|
|
141
168
|
if (typeof session.id !== "string")
|
|
142
169
|
throw new Error("Sessão inválida");
|
|
143
|
-
const prompt = string(input.prompt
|
|
144
|
-
const response = string(input.last_assistant_message
|
|
170
|
+
const prompt = string(input.prompt);
|
|
171
|
+
const response = string(input.last_assistant_message);
|
|
145
172
|
const rawContent = event === "session-init"
|
|
146
173
|
? prompt
|
|
147
174
|
: event === "summarize"
|
|
@@ -195,7 +222,7 @@ export async function executeHook(adapter, event, value, cloud = new VaultCloudC
|
|
|
195
222
|
}
|
|
196
223
|
if (event === "summarize")
|
|
197
224
|
await cloud.endSession(session.id);
|
|
198
|
-
return hookOutput(event);
|
|
225
|
+
return hookOutput(event, "", adapter);
|
|
199
226
|
}
|
|
200
227
|
export async function readHookInput(stream = process.stdin) {
|
|
201
228
|
const chunks = [];
|
package/dist/installer.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const MCP_SERVER_NAME = "vault-go";
|
|
2
2
|
export declare const MCP_SERVER_COMMAND: readonly ["bunx", "--bun", "vault-go@latest", "serve"];
|
|
3
|
-
export declare const MCP_CLIENTS: readonly ["codex", "claude", "claude-desktop", "cursor", "vscode", "copilot", "windsurf", "roo", "opencode"];
|
|
3
|
+
export declare const MCP_CLIENTS: readonly ["codex", "claude", "claude-desktop", "cursor", "vscode", "copilot", "windsurf", "roo", "opencode", "grok", "agy", "gemini"];
|
|
4
4
|
export type McpClient = (typeof MCP_CLIENTS)[number];
|
|
5
5
|
export interface DetectedClient {
|
|
6
6
|
client: McpClient;
|
package/dist/installer.js
CHANGED
|
@@ -17,7 +17,14 @@ export const MCP_CLIENTS = [
|
|
|
17
17
|
'windsurf',
|
|
18
18
|
'roo',
|
|
19
19
|
'opencode',
|
|
20
|
+
'grok',
|
|
21
|
+
'agy',
|
|
22
|
+
'gemini',
|
|
20
23
|
];
|
|
24
|
+
const CLIENT_ALIASES = {
|
|
25
|
+
antigravity: 'agy',
|
|
26
|
+
'gemini-cli': 'gemini',
|
|
27
|
+
};
|
|
21
28
|
const runCommand = (command, args) => spawnSync(command, [...args], { stdio: 'ignore' });
|
|
22
29
|
function readJsonObject(path) {
|
|
23
30
|
if (!existsSync(path))
|
|
@@ -35,12 +42,37 @@ function readJsonObject(path) {
|
|
|
35
42
|
return parsed;
|
|
36
43
|
}
|
|
37
44
|
function atomicWriteJson(path, value) {
|
|
45
|
+
atomicWriteText(path, `${JSON.stringify(value, null, 2)}\n`);
|
|
46
|
+
}
|
|
47
|
+
function atomicWriteText(path, text) {
|
|
38
48
|
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
|
|
39
49
|
const temporary = join(dirname(path), `.${process.pid}.${Date.now()}.tmp`);
|
|
40
|
-
writeFileSync(temporary,
|
|
50
|
+
writeFileSync(temporary, text.endsWith('\n') ? text : `${text}\n`, { mode: 0o600 });
|
|
41
51
|
renameSync(temporary, path);
|
|
42
52
|
chmodSync(path, 0o600);
|
|
43
53
|
}
|
|
54
|
+
function formatTomlValue(value) {
|
|
55
|
+
if (typeof value === 'boolean')
|
|
56
|
+
return value ? 'true' : 'false';
|
|
57
|
+
if (typeof value === 'string')
|
|
58
|
+
return JSON.stringify(value);
|
|
59
|
+
return `[${value.map((item) => JSON.stringify(item)).join(', ')}]`;
|
|
60
|
+
}
|
|
61
|
+
function upsertTomlTable(path, table, assignments) {
|
|
62
|
+
const previous = existsSync(path) ? readFileSync(path, 'utf8') : '';
|
|
63
|
+
const body = Object.entries(assignments)
|
|
64
|
+
.map(([key, value]) => `${key} = ${formatTomlValue(value)}`)
|
|
65
|
+
.join('\n');
|
|
66
|
+
const block = `[${table}]\n${body}\n`;
|
|
67
|
+
const escaped = table.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
68
|
+
const pattern = new RegExp(`(^|\\r?\\n)\\[${escaped}\\](?:\\r?\\n(?!\\[).*)*`);
|
|
69
|
+
const next = pattern.test(previous)
|
|
70
|
+
? previous.replace(pattern, (match) => `${/^\r?\n/.exec(match)?.[0] ?? ''}${block}`)
|
|
71
|
+
: previous.trimEnd()
|
|
72
|
+
? `${previous.trimEnd()}\n\n${block}`
|
|
73
|
+
: block;
|
|
74
|
+
atomicWriteText(path, next);
|
|
75
|
+
}
|
|
44
76
|
function standardServer() {
|
|
45
77
|
return {
|
|
46
78
|
command: MCP_SERVER_COMMAND[0],
|
|
@@ -125,6 +157,36 @@ export function installMcpClient(client, options = {}) {
|
|
|
125
157
|
}
|
|
126
158
|
return { client, status: 'installed', destination: 'VS Code user profile' };
|
|
127
159
|
}
|
|
160
|
+
if (client === 'grok') {
|
|
161
|
+
const destination = join(home, '.grok', 'config.toml');
|
|
162
|
+
upsertTomlTable(destination, 'mcp_servers.vault-go', {
|
|
163
|
+
command: MCP_SERVER_COMMAND[0],
|
|
164
|
+
args: MCP_SERVER_COMMAND.slice(1),
|
|
165
|
+
enabled: true,
|
|
166
|
+
});
|
|
167
|
+
try {
|
|
168
|
+
stageLocalRuntime(vaultHome());
|
|
169
|
+
}
|
|
170
|
+
catch { /* incomplete installs still write hooks */ }
|
|
171
|
+
installClientHooks('grok', home);
|
|
172
|
+
return { client, status: 'installed', destination };
|
|
173
|
+
}
|
|
174
|
+
if (client === 'agy') {
|
|
175
|
+
const cliPath = join(home, '.gemini', 'config', 'mcp_config.json');
|
|
176
|
+
mergeServer(cliPath);
|
|
177
|
+
mergeServer(join(home, '.gemini', 'antigravity', 'mcp_config.json'));
|
|
178
|
+
try {
|
|
179
|
+
stageLocalRuntime(vaultHome());
|
|
180
|
+
}
|
|
181
|
+
catch { /* incomplete installs still write hooks */ }
|
|
182
|
+
installClientHooks('agy', home);
|
|
183
|
+
return { client, status: 'installed', destination: cliPath };
|
|
184
|
+
}
|
|
185
|
+
if (client === 'gemini') {
|
|
186
|
+
const path = join(home, '.gemini', 'settings.json');
|
|
187
|
+
mergeServer(path);
|
|
188
|
+
return { client, status: 'installed', destination: path };
|
|
189
|
+
}
|
|
128
190
|
let path;
|
|
129
191
|
if (client === 'claude-desktop')
|
|
130
192
|
path = claudeDesktopPath(home);
|
|
@@ -169,6 +231,9 @@ export function detectMcpClients(home = homedir()) {
|
|
|
169
231
|
['windsurf', ['windsurf'], [join(home, '.codeium', 'windsurf')]],
|
|
170
232
|
['roo', [], []],
|
|
171
233
|
['opencode', ['opencode'], [join(home, '.config', 'opencode')]],
|
|
234
|
+
['grok', ['grok'], [join(home, '.grok')]],
|
|
235
|
+
['agy', ['agy'], [join(home, '.gemini', 'antigravity-cli'), join(home, '.gemini', 'config'), join(home, '.gemini', 'antigravity')]],
|
|
236
|
+
['gemini', ['gemini'], [join(home, '.gemini', 'settings.json')]],
|
|
172
237
|
];
|
|
173
238
|
return definitions.map(([client, commands, paths]) => {
|
|
174
239
|
const command = commands.find((candidate) => Bun.which(candidate));
|
|
@@ -195,7 +260,10 @@ export function parseClientSelection(value) {
|
|
|
195
260
|
const normalized = value.trim().toLowerCase();
|
|
196
261
|
if (normalized === 'all' || normalized === 'todos')
|
|
197
262
|
return [...MCP_CLIENTS];
|
|
198
|
-
const selected = [...new Set(normalized.split(',').map((item) =>
|
|
263
|
+
const selected = [...new Set(normalized.split(',').map((item) => {
|
|
264
|
+
const trimmed = item.trim();
|
|
265
|
+
return CLIENT_ALIASES[trimmed] ?? trimmed;
|
|
266
|
+
}).filter(Boolean))];
|
|
199
267
|
const invalid = selected.filter((item) => !MCP_CLIENTS.includes(item));
|
|
200
268
|
if (invalid.length > 0)
|
|
201
269
|
throw new Error(`Clientes MCP desconhecidos: ${invalid.join(', ')}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vault-go",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "Servidor MCP universal com autenticação e instalação multi-cliente para a plataforma Vault.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -103,7 +103,10 @@
|
|
|
103
103
|
"codex",
|
|
104
104
|
"claude",
|
|
105
105
|
"copilot",
|
|
106
|
-
"cursor"
|
|
106
|
+
"cursor",
|
|
107
|
+
"grok",
|
|
108
|
+
"opencode",
|
|
109
|
+
"antigravity"
|
|
107
110
|
],
|
|
108
111
|
"author": "Gutierrez Henrique",
|
|
109
112
|
"license": "MIT",
|