vault-go 0.24.0 → 0.25.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.
@@ -0,0 +1,18 @@
1
+ import type { VaultMemoryApi } from './cloud.js';
2
+ import type { ContextResult } from './context-engines.js';
3
+ type MirrorJob = {
4
+ id: string;
5
+ projectId: string;
6
+ kind: string;
7
+ generate?: boolean;
8
+ };
9
+ export declare function shouldMirrorCrystalMemory(job: MirrorJob): boolean;
10
+ export declare function crystalProjectFolder(project: unknown): string | null;
11
+ export declare function resolveCrystalProjectFolder(cloud: Pick<VaultMemoryApi, 'projects'>, projectId: string): Promise<string | null>;
12
+ export declare function mirrorCrystalMemory(input: {
13
+ home: string;
14
+ cloud: Pick<VaultMemoryApi, 'projects'>;
15
+ job: MirrorJob;
16
+ result: Pick<ContextResult, 'title' | 'content' | 'concepts'>;
17
+ }): Promise<void>;
18
+ export {};
@@ -0,0 +1,47 @@
1
+ import { basename } from 'node:path';
2
+ export function shouldMirrorCrystalMemory(job) {
3
+ if (job.kind === 'summary')
4
+ return true;
5
+ if (job.generate === false)
6
+ return true;
7
+ return false;
8
+ }
9
+ export function crystalProjectFolder(project) {
10
+ if (!project || typeof project !== 'object')
11
+ return null;
12
+ const rec = project;
13
+ if (typeof rec.name === 'string' && rec.name.trim())
14
+ return rec.name.trim();
15
+ if (typeof rec.rootPath === 'string' && rec.rootPath.trim()) {
16
+ const base = basename(rec.rootPath.replace(/\\/g, '/'));
17
+ return base || null;
18
+ }
19
+ return null;
20
+ }
21
+ export async function resolveCrystalProjectFolder(cloud, projectId) {
22
+ const projects = await cloud.projects().catch(() => null);
23
+ if (!Array.isArray(projects))
24
+ return null;
25
+ const found = projects.find((item) => item && typeof item === 'object' && item.id === projectId);
26
+ return crystalProjectFolder(found);
27
+ }
28
+ export async function mirrorCrystalMemory(input) {
29
+ if (!shouldMirrorCrystalMemory(input.job))
30
+ return;
31
+ const project = await resolveCrystalProjectFolder(input.cloud, input.job.projectId);
32
+ if (!project)
33
+ return;
34
+ try {
35
+ const { callCrystalTool } = await import('./crystal-tools.js');
36
+ await callCrystalTool(input.home, 'crystal_memory_write', {
37
+ project,
38
+ title: input.result.title,
39
+ content: input.result.content,
40
+ tags: input.result.concepts,
41
+ sourceId: `vault-go:event:${input.job.id}`,
42
+ });
43
+ }
44
+ catch {
45
+ // Crystal MCP is optional; account memory already persisted.
46
+ }
47
+ }
@@ -103,4 +103,19 @@ export function registerCrystalTools(server, home) {
103
103
  add('delete', 'Exclui uma nota do Crystal.', { path: notePath }, false, true);
104
104
  add('sync', 'Sincroniza o Crystal com o Vault Cloud.', {}, false);
105
105
  add('status', 'Mostra o estado do Crystal e da sincronização.', {});
106
+ add('memory_list', 'Lista notas duráveis em {projeto}/Memory no Crystal.', { project: z.string().trim().min(1).max(200).optional() });
107
+ add('memory_write', 'Grava uma nota durável em {projeto}/Memory no Crystal.', {
108
+ project: z.string().trim().min(1).max(200),
109
+ content: z.string().max(10 * 1024 * 1024),
110
+ title: z.string().max(1000).optional(),
111
+ tags: z.array(z.string().max(200)).max(100).optional(),
112
+ sourceId: z.string().max(500).optional(),
113
+ }, false);
114
+ add('memory_append', 'Acrescenta texto a uma nota em {projeto}/Memory no Crystal.', {
115
+ project: z.string().trim().min(1).max(200),
116
+ content: z.string().max(10 * 1024 * 1024),
117
+ title: z.string().max(1000).optional(),
118
+ tags: z.array(z.string().max(200)).max(100).optional(),
119
+ sourceId: z.string().max(500).optional(),
120
+ }, false);
106
121
  }
@@ -6,6 +6,7 @@ import { loadConfig, loadTokens, vaultHome } from './config.js';
6
6
  import { generateContext, selectedContextEngine } from './context-engines.js';
7
7
  import { notifyTelegramObservation } from './telegram.js';
8
8
  import { pushAwareness } from './grok-awareness.js';
9
+ import { mirrorCrystalMemory } from './crystal-memory-mirror.js';
9
10
  const queuePath = (home) => join(home, 'generation-queue.json');
10
11
  function ownerKey(home) {
11
12
  const config = loadConfig(home);
@@ -161,6 +162,7 @@ export async function processGenerationQueue(home = vaultHome(), cloud = new Vau
161
162
  const awareness = await pushAwareness(home, { ...(job.agentId ? { agentId: job.agentId } : {}), observations: [{ type: memoryType, title: result.title || job.title || 'Memória', facts: result.facts, concepts: result.concepts }] });
162
163
  if (awareness.error)
163
164
  throw new Error('Awareness delivery failed; retry with cached generation.');
165
+ await mirrorCrystalMemory({ home, cloud, job, result });
164
166
  await mutate(home, jobs => jobs.filter(item => item.id !== job.id));
165
167
  if (job.kind === 'observation' && owner === ownerKey(home)) {
166
168
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vault-go",
3
- "version": "0.24.0",
3
+ "version": "0.25.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": {
@@ -42,6 +42,8 @@
42
42
  "dist/config.d.ts",
43
43
  "dist/context-engines.js",
44
44
  "dist/context-engines.d.ts",
45
+ "dist/crystal-memory-mirror.js",
46
+ "dist/crystal-memory-mirror.d.ts",
45
47
  "dist/crystal-tools.js",
46
48
  "dist/crystal-tools.d.ts",
47
49
  "dist/hook-install.js",