gnosys 4.0.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/LICENSE +21 -0
- package/README.md +1387 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +3753 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2267 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/archive.d.ts +95 -0
- package/dist/lib/archive.d.ts.map +1 -0
- package/dist/lib/archive.js +311 -0
- package/dist/lib/archive.js.map +1 -0
- package/dist/lib/ask.d.ts +77 -0
- package/dist/lib/ask.d.ts.map +1 -0
- package/dist/lib/ask.js +316 -0
- package/dist/lib/ask.js.map +1 -0
- package/dist/lib/audit.d.ts +47 -0
- package/dist/lib/audit.d.ts.map +1 -0
- package/dist/lib/audit.js +136 -0
- package/dist/lib/audit.js.map +1 -0
- package/dist/lib/bootstrap.d.ts +56 -0
- package/dist/lib/bootstrap.d.ts.map +1 -0
- package/dist/lib/bootstrap.js +163 -0
- package/dist/lib/bootstrap.js.map +1 -0
- package/dist/lib/config.d.ts +239 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +371 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/dashboard.d.ts +81 -0
- package/dist/lib/dashboard.d.ts.map +1 -0
- package/dist/lib/dashboard.js +314 -0
- package/dist/lib/dashboard.js.map +1 -0
- package/dist/lib/db.d.ts +182 -0
- package/dist/lib/db.d.ts.map +1 -0
- package/dist/lib/db.js +620 -0
- package/dist/lib/db.js.map +1 -0
- package/dist/lib/dbSearch.d.ts +65 -0
- package/dist/lib/dbSearch.d.ts.map +1 -0
- package/dist/lib/dbSearch.js +239 -0
- package/dist/lib/dbSearch.js.map +1 -0
- package/dist/lib/dbWrite.d.ts +56 -0
- package/dist/lib/dbWrite.d.ts.map +1 -0
- package/dist/lib/dbWrite.js +171 -0
- package/dist/lib/dbWrite.js.map +1 -0
- package/dist/lib/dream.d.ts +170 -0
- package/dist/lib/dream.d.ts.map +1 -0
- package/dist/lib/dream.js +706 -0
- package/dist/lib/dream.js.map +1 -0
- package/dist/lib/embeddings.d.ts +84 -0
- package/dist/lib/embeddings.d.ts.map +1 -0
- package/dist/lib/embeddings.js +226 -0
- package/dist/lib/embeddings.js.map +1 -0
- package/dist/lib/export.d.ts +92 -0
- package/dist/lib/export.d.ts.map +1 -0
- package/dist/lib/export.js +362 -0
- package/dist/lib/export.js.map +1 -0
- package/dist/lib/federated.d.ts +113 -0
- package/dist/lib/federated.d.ts.map +1 -0
- package/dist/lib/federated.js +346 -0
- package/dist/lib/federated.js.map +1 -0
- package/dist/lib/graph.d.ts +50 -0
- package/dist/lib/graph.d.ts.map +1 -0
- package/dist/lib/graph.js +118 -0
- package/dist/lib/graph.js.map +1 -0
- package/dist/lib/history.d.ts +39 -0
- package/dist/lib/history.d.ts.map +1 -0
- package/dist/lib/history.js +112 -0
- package/dist/lib/history.js.map +1 -0
- package/dist/lib/hybridSearch.d.ts +80 -0
- package/dist/lib/hybridSearch.d.ts.map +1 -0
- package/dist/lib/hybridSearch.js +296 -0
- package/dist/lib/hybridSearch.js.map +1 -0
- package/dist/lib/import.d.ts +52 -0
- package/dist/lib/import.d.ts.map +1 -0
- package/dist/lib/import.js +365 -0
- package/dist/lib/import.js.map +1 -0
- package/dist/lib/ingest.d.ts +51 -0
- package/dist/lib/ingest.d.ts.map +1 -0
- package/dist/lib/ingest.js +144 -0
- package/dist/lib/ingest.js.map +1 -0
- package/dist/lib/lensing.d.ts +35 -0
- package/dist/lib/lensing.d.ts.map +1 -0
- package/dist/lib/lensing.js +85 -0
- package/dist/lib/lensing.js.map +1 -0
- package/dist/lib/llm.d.ts +84 -0
- package/dist/lib/llm.d.ts.map +1 -0
- package/dist/lib/llm.js +386 -0
- package/dist/lib/llm.js.map +1 -0
- package/dist/lib/lock.d.ts +28 -0
- package/dist/lib/lock.d.ts.map +1 -0
- package/dist/lib/lock.js +145 -0
- package/dist/lib/lock.js.map +1 -0
- package/dist/lib/maintenance.d.ts +124 -0
- package/dist/lib/maintenance.d.ts.map +1 -0
- package/dist/lib/maintenance.js +587 -0
- package/dist/lib/maintenance.js.map +1 -0
- package/dist/lib/migrate.d.ts +19 -0
- package/dist/lib/migrate.d.ts.map +1 -0
- package/dist/lib/migrate.js +260 -0
- package/dist/lib/migrate.js.map +1 -0
- package/dist/lib/preferences.d.ts +49 -0
- package/dist/lib/preferences.d.ts.map +1 -0
- package/dist/lib/preferences.js +149 -0
- package/dist/lib/preferences.js.map +1 -0
- package/dist/lib/projectIdentity.d.ts +66 -0
- package/dist/lib/projectIdentity.d.ts.map +1 -0
- package/dist/lib/projectIdentity.js +148 -0
- package/dist/lib/projectIdentity.js.map +1 -0
- package/dist/lib/recall.d.ts +82 -0
- package/dist/lib/recall.d.ts.map +1 -0
- package/dist/lib/recall.js +289 -0
- package/dist/lib/recall.js.map +1 -0
- package/dist/lib/resolver.d.ts +116 -0
- package/dist/lib/resolver.d.ts.map +1 -0
- package/dist/lib/resolver.js +372 -0
- package/dist/lib/resolver.js.map +1 -0
- package/dist/lib/retry.d.ts +24 -0
- package/dist/lib/retry.d.ts.map +1 -0
- package/dist/lib/retry.js +60 -0
- package/dist/lib/retry.js.map +1 -0
- package/dist/lib/rulesGen.d.ts +51 -0
- package/dist/lib/rulesGen.d.ts.map +1 -0
- package/dist/lib/rulesGen.js +167 -0
- package/dist/lib/rulesGen.js.map +1 -0
- package/dist/lib/search.d.ts +51 -0
- package/dist/lib/search.d.ts.map +1 -0
- package/dist/lib/search.js +190 -0
- package/dist/lib/search.js.map +1 -0
- package/dist/lib/staticSearch.d.ts +70 -0
- package/dist/lib/staticSearch.d.ts.map +1 -0
- package/dist/lib/staticSearch.js +162 -0
- package/dist/lib/staticSearch.js.map +1 -0
- package/dist/lib/store.d.ts +79 -0
- package/dist/lib/store.d.ts.map +1 -0
- package/dist/lib/store.js +227 -0
- package/dist/lib/store.js.map +1 -0
- package/dist/lib/structuredIngest.d.ts +37 -0
- package/dist/lib/structuredIngest.d.ts.map +1 -0
- package/dist/lib/structuredIngest.js +208 -0
- package/dist/lib/structuredIngest.js.map +1 -0
- package/dist/lib/tags.d.ts +26 -0
- package/dist/lib/tags.d.ts.map +1 -0
- package/dist/lib/tags.js +109 -0
- package/dist/lib/tags.js.map +1 -0
- package/dist/lib/timeline.d.ts +34 -0
- package/dist/lib/timeline.d.ts.map +1 -0
- package/dist/lib/timeline.js +116 -0
- package/dist/lib/timeline.js.map +1 -0
- package/dist/lib/trace.d.ts +42 -0
- package/dist/lib/trace.d.ts.map +1 -0
- package/dist/lib/trace.js +338 -0
- package/dist/lib/trace.js.map +1 -0
- package/dist/lib/webIndex.d.ts +28 -0
- package/dist/lib/webIndex.d.ts.map +1 -0
- package/dist/lib/webIndex.js +208 -0
- package/dist/lib/webIndex.js.map +1 -0
- package/dist/lib/webIngest.d.ts +51 -0
- package/dist/lib/webIngest.d.ts.map +1 -0
- package/dist/lib/webIngest.js +533 -0
- package/dist/lib/webIngest.js.map +1 -0
- package/dist/lib/wikilinks.d.ts +63 -0
- package/dist/lib/wikilinks.d.ts.map +1 -0
- package/dist/lib/wikilinks.js +146 -0
- package/dist/lib/wikilinks.js.map +1 -0
- package/dist/sandbox/client.d.ts +82 -0
- package/dist/sandbox/client.d.ts.map +1 -0
- package/dist/sandbox/client.js +128 -0
- package/dist/sandbox/client.js.map +1 -0
- package/dist/sandbox/helper-template.d.ts +14 -0
- package/dist/sandbox/helper-template.d.ts.map +1 -0
- package/dist/sandbox/helper-template.js +285 -0
- package/dist/sandbox/helper-template.js.map +1 -0
- package/dist/sandbox/index.d.ts +10 -0
- package/dist/sandbox/index.d.ts.map +1 -0
- package/dist/sandbox/index.js +10 -0
- package/dist/sandbox/index.js.map +1 -0
- package/dist/sandbox/manager.d.ts +40 -0
- package/dist/sandbox/manager.d.ts.map +1 -0
- package/dist/sandbox/manager.js +220 -0
- package/dist/sandbox/manager.js.map +1 -0
- package/dist/sandbox/server.d.ts +44 -0
- package/dist/sandbox/server.d.ts.map +1 -0
- package/dist/sandbox/server.js +661 -0
- package/dist/sandbox/server.js.map +1 -0
- package/package.json +103 -0
- package/prompts/synthesize.md +21 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gnosys Project Identity — v3.0 Centralized Brain.
|
|
3
|
+
*
|
|
4
|
+
* Each project has a .gnosys/gnosys.json that stores its identity:
|
|
5
|
+
* projectId, projectName, workingDirectory, user, agentRulesTarget, obsidianVault
|
|
6
|
+
*
|
|
7
|
+
* The central DB (~/.gnosys/gnosys.db) mirrors this in the `projects` table.
|
|
8
|
+
* gnosys init creates both the local identity file AND the central DB record.
|
|
9
|
+
*/
|
|
10
|
+
import fs from "fs/promises";
|
|
11
|
+
import fsSync from "fs";
|
|
12
|
+
import path from "path";
|
|
13
|
+
import crypto from "crypto";
|
|
14
|
+
import os from "os";
|
|
15
|
+
const IDENTITY_SCHEMA_VERSION = 1;
|
|
16
|
+
/**
|
|
17
|
+
* Detect which agent IDE is being used.
|
|
18
|
+
* Returns the appropriate rules file target path.
|
|
19
|
+
*/
|
|
20
|
+
export function detectAgentRulesTarget(projectDir) {
|
|
21
|
+
// Check for Cursor
|
|
22
|
+
if (fsSync.existsSync(path.join(projectDir, ".cursor"))) {
|
|
23
|
+
return ".cursor/rules/gnosys.mdc";
|
|
24
|
+
}
|
|
25
|
+
// Check for Claude Code
|
|
26
|
+
if (fsSync.existsSync(path.join(projectDir, "CLAUDE.md"))) {
|
|
27
|
+
return "CLAUDE.md";
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Read project identity from .gnosys/gnosys.json.
|
|
33
|
+
* Returns null if file doesn't exist or is invalid.
|
|
34
|
+
*/
|
|
35
|
+
export async function readProjectIdentity(projectDir) {
|
|
36
|
+
const identityPath = path.join(projectDir, ".gnosys", "gnosys.json");
|
|
37
|
+
try {
|
|
38
|
+
const raw = await fs.readFile(identityPath, "utf-8");
|
|
39
|
+
const parsed = JSON.parse(raw);
|
|
40
|
+
// Validate required fields
|
|
41
|
+
if (!parsed.projectId || !parsed.projectName || !parsed.workingDirectory) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
return parsed;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Write project identity to .gnosys/gnosys.json.
|
|
52
|
+
*/
|
|
53
|
+
export async function writeProjectIdentity(projectDir, identity) {
|
|
54
|
+
const identityPath = path.join(projectDir, ".gnosys", "gnosys.json");
|
|
55
|
+
await fs.writeFile(identityPath, JSON.stringify(identity, null, 2) + "\n", "utf-8");
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Create a new project identity.
|
|
59
|
+
* Generates UUID, detects IDE, writes local file, registers in central DB.
|
|
60
|
+
*/
|
|
61
|
+
export async function createProjectIdentity(projectDir, opts) {
|
|
62
|
+
const resolvedDir = path.resolve(projectDir);
|
|
63
|
+
const projectName = opts?.projectName || path.basename(resolvedDir);
|
|
64
|
+
const user = os.userInfo().username || "unknown";
|
|
65
|
+
const now = new Date().toISOString();
|
|
66
|
+
// Check if identity already exists and reuse the projectId
|
|
67
|
+
const existing = await readProjectIdentity(resolvedDir);
|
|
68
|
+
const identity = {
|
|
69
|
+
projectId: existing?.projectId || crypto.randomUUID(),
|
|
70
|
+
projectName,
|
|
71
|
+
workingDirectory: resolvedDir,
|
|
72
|
+
user,
|
|
73
|
+
agentRulesTarget: detectAgentRulesTarget(resolvedDir),
|
|
74
|
+
obsidianVault: ".gnosys/vault",
|
|
75
|
+
createdAt: existing?.createdAt || now,
|
|
76
|
+
schemaVersion: IDENTITY_SCHEMA_VERSION,
|
|
77
|
+
};
|
|
78
|
+
// Write local identity file
|
|
79
|
+
await writeProjectIdentity(resolvedDir, identity);
|
|
80
|
+
// Register in central DB if available
|
|
81
|
+
if (opts?.centralDb?.isAvailable()) {
|
|
82
|
+
const dbProject = {
|
|
83
|
+
id: identity.projectId,
|
|
84
|
+
name: identity.projectName,
|
|
85
|
+
working_directory: identity.workingDirectory,
|
|
86
|
+
user: identity.user,
|
|
87
|
+
agent_rules_target: identity.agentRulesTarget,
|
|
88
|
+
obsidian_vault: identity.obsidianVault
|
|
89
|
+
? path.join(identity.workingDirectory, identity.obsidianVault)
|
|
90
|
+
: null,
|
|
91
|
+
created: identity.createdAt,
|
|
92
|
+
modified: now,
|
|
93
|
+
};
|
|
94
|
+
opts.centralDb.insertProject(dbProject);
|
|
95
|
+
}
|
|
96
|
+
return identity;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Check if the working directory has changed since last init.
|
|
100
|
+
* Returns the identity if a mismatch is detected (needs re-init).
|
|
101
|
+
*/
|
|
102
|
+
export async function checkDirectoryMismatch(projectDir) {
|
|
103
|
+
const resolvedDir = path.resolve(projectDir);
|
|
104
|
+
const identity = await readProjectIdentity(resolvedDir);
|
|
105
|
+
if (!identity) {
|
|
106
|
+
return { mismatch: false, identity: null, currentDir: resolvedDir };
|
|
107
|
+
}
|
|
108
|
+
const mismatch = identity.workingDirectory !== resolvedDir;
|
|
109
|
+
return { mismatch, identity, currentDir: resolvedDir };
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Update the working directory in both local identity and central DB.
|
|
113
|
+
* Called when a directory move is detected.
|
|
114
|
+
*/
|
|
115
|
+
export async function updateWorkingDirectory(projectDir, centralDb) {
|
|
116
|
+
const resolvedDir = path.resolve(projectDir);
|
|
117
|
+
const identity = await readProjectIdentity(resolvedDir);
|
|
118
|
+
if (!identity)
|
|
119
|
+
return null;
|
|
120
|
+
// Update local file
|
|
121
|
+
identity.workingDirectory = resolvedDir;
|
|
122
|
+
await writeProjectIdentity(resolvedDir, identity);
|
|
123
|
+
// Update central DB
|
|
124
|
+
if (centralDb?.isAvailable()) {
|
|
125
|
+
centralDb.updateProject(identity.projectId, {
|
|
126
|
+
working_directory: resolvedDir,
|
|
127
|
+
modified: new Date().toISOString(),
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
return identity;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Find the project identity by walking up from a directory.
|
|
134
|
+
* Returns the identity and project root directory if found.
|
|
135
|
+
*/
|
|
136
|
+
export async function findProjectIdentity(startDir) {
|
|
137
|
+
let dir = path.resolve(startDir);
|
|
138
|
+
const root = path.parse(dir).root;
|
|
139
|
+
while (dir !== root) {
|
|
140
|
+
const identity = await readProjectIdentity(dir);
|
|
141
|
+
if (identity) {
|
|
142
|
+
return { identity, projectRoot: dir };
|
|
143
|
+
}
|
|
144
|
+
dir = path.dirname(dir);
|
|
145
|
+
}
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=projectIdentity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projectIdentity.js","sourceRoot":"","sources":["../../src/lib/projectIdentity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gnosys Recall — Automatic memory injection via MCP Resource.
|
|
3
|
+
*
|
|
4
|
+
* The host (Cursor, Claude Desktop, Claude Code, Cowork) reads the
|
|
5
|
+
* gnosys://recall resource on every turn. This module runs the fast
|
|
6
|
+
* FTS5 lookup and returns a citation-heavy <gnosys-recall> block that
|
|
7
|
+
* gets injected into the model context automatically — no tool call needed.
|
|
8
|
+
*
|
|
9
|
+
* Pipeline: FTS5 keyword search → relevance scoring → aggressive/filtered
|
|
10
|
+
* selection → archive fallback → format as [[wikilink]] block.
|
|
11
|
+
*
|
|
12
|
+
* Config (gnosys.json):
|
|
13
|
+
* "recall": { "aggressive": true, "maxMemories": 8, "minRelevance": 0.4 }
|
|
14
|
+
*
|
|
15
|
+
* When aggressive=true (default): inject top memories even if relevance is
|
|
16
|
+
* medium. This boosts recall in long sessions where context drifts.
|
|
17
|
+
*
|
|
18
|
+
* v2.0: When GnosysDB is available, recall runs entirely from SQLite —
|
|
19
|
+
* no filesystem reads, no separate search.db. Pure DB lookup. Sub-10ms.
|
|
20
|
+
*
|
|
21
|
+
* No LLM calls. No embeddings. Pure index lookup. Sub-50ms.
|
|
22
|
+
*/
|
|
23
|
+
import { GnosysSearch } from "./search.js";
|
|
24
|
+
import { GnosysResolver } from "./resolver.js";
|
|
25
|
+
import { GnosysDB } from "./db.js";
|
|
26
|
+
import { RecallConfig } from "./config.js";
|
|
27
|
+
export interface RecallResult {
|
|
28
|
+
memories: RecallMemory[];
|
|
29
|
+
totalActive: number;
|
|
30
|
+
totalArchived: number;
|
|
31
|
+
recallTimeMs: number;
|
|
32
|
+
aggressive: boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface RecallMemory {
|
|
35
|
+
id: string;
|
|
36
|
+
title: string;
|
|
37
|
+
category: string;
|
|
38
|
+
relevance: string;
|
|
39
|
+
confidence: number;
|
|
40
|
+
path: string;
|
|
41
|
+
fromArchive: boolean;
|
|
42
|
+
snippet: string;
|
|
43
|
+
/** Normalized relevance score (0-1, higher = more relevant) */
|
|
44
|
+
relevanceScore: number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Fast recall — keyword search only, no LLM, no embeddings.
|
|
48
|
+
* Designed to run on every host turn via MCP Resource (sub-50ms target).
|
|
49
|
+
*
|
|
50
|
+
* v2.0: When gnosysDb is provided, recall runs entirely from SQLite.
|
|
51
|
+
* No filesystem reads. Sub-10ms.
|
|
52
|
+
*
|
|
53
|
+
* When aggressive=true (default):
|
|
54
|
+
* - Always returns up to maxMemories regardless of relevance score
|
|
55
|
+
* - Uses minRelevance as a soft floor, not a hard cutoff
|
|
56
|
+
* - Injects even medium-relevance memories to boost context in long sessions
|
|
57
|
+
*
|
|
58
|
+
* When aggressive=false:
|
|
59
|
+
* - Only returns memories above minRelevance threshold
|
|
60
|
+
* - May return zero memories if nothing matches well
|
|
61
|
+
*/
|
|
62
|
+
export declare function recall(query: string, options: {
|
|
63
|
+
limit?: number;
|
|
64
|
+
search: GnosysSearch;
|
|
65
|
+
resolver: GnosysResolver;
|
|
66
|
+
storePath: string;
|
|
67
|
+
traceId?: string;
|
|
68
|
+
recallConfig?: RecallConfig;
|
|
69
|
+
/** v2.0: When provided, recall uses SQLite directly — no filesystem reads */
|
|
70
|
+
gnosysDb?: GnosysDB;
|
|
71
|
+
}): Promise<RecallResult>;
|
|
72
|
+
/**
|
|
73
|
+
* Format recall results as a host-friendly <gnosys-recall> block.
|
|
74
|
+
* This is what gets injected into the model context on every turn
|
|
75
|
+
* via the MCP Resource. Citation-heavy with [[wikilinks]].
|
|
76
|
+
*/
|
|
77
|
+
export declare function formatRecall(result: RecallResult): string;
|
|
78
|
+
/**
|
|
79
|
+
* Format recall results as a concise CLI-friendly output.
|
|
80
|
+
*/
|
|
81
|
+
export declare function formatRecallCLI(result: RecallResult): string;
|
|
82
|
+
//# sourceMappingURL=recall.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recall.d.ts","sourceRoot":"","sources":["../../src/lib/recall.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,cAAc,EAAE,MAAM,CAAC;CACxB;AA2BD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,MAAM,CAC1B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE;IACP,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,GACA,OAAO,CAAC,YAAY,CAAC,CAuFvB;AAiID;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAoBzD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAwB5D"}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gnosys Recall — Automatic memory injection via MCP Resource.
|
|
3
|
+
*
|
|
4
|
+
* The host (Cursor, Claude Desktop, Claude Code, Cowork) reads the
|
|
5
|
+
* gnosys://recall resource on every turn. This module runs the fast
|
|
6
|
+
* FTS5 lookup and returns a citation-heavy <gnosys-recall> block that
|
|
7
|
+
* gets injected into the model context automatically — no tool call needed.
|
|
8
|
+
*
|
|
9
|
+
* Pipeline: FTS5 keyword search → relevance scoring → aggressive/filtered
|
|
10
|
+
* selection → archive fallback → format as [[wikilink]] block.
|
|
11
|
+
*
|
|
12
|
+
* Config (gnosys.json):
|
|
13
|
+
* "recall": { "aggressive": true, "maxMemories": 8, "minRelevance": 0.4 }
|
|
14
|
+
*
|
|
15
|
+
* When aggressive=true (default): inject top memories even if relevance is
|
|
16
|
+
* medium. This boosts recall in long sessions where context drifts.
|
|
17
|
+
*
|
|
18
|
+
* v2.0: When GnosysDB is available, recall runs entirely from SQLite —
|
|
19
|
+
* no filesystem reads, no separate search.db. Pure DB lookup. Sub-10ms.
|
|
20
|
+
*
|
|
21
|
+
* No LLM calls. No embeddings. Pure index lookup. Sub-50ms.
|
|
22
|
+
*/
|
|
23
|
+
import { GnosysArchive } from "./archive.js";
|
|
24
|
+
import { auditLog } from "./audit.js";
|
|
25
|
+
/** Default recall config */
|
|
26
|
+
const DEFAULT_RECALL_CONFIG = {
|
|
27
|
+
aggressive: true,
|
|
28
|
+
maxMemories: 8,
|
|
29
|
+
minRelevance: 0.4,
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Normalize FTS5 rank to a 0-1 relevance score.
|
|
33
|
+
* FTS5 rank is negative (closer to 0 = more relevant).
|
|
34
|
+
* We map it to 0-1 where 1 = most relevant.
|
|
35
|
+
*/
|
|
36
|
+
function normalizeRank(rank, allRanks) {
|
|
37
|
+
if (allRanks.length === 0)
|
|
38
|
+
return 0.5;
|
|
39
|
+
if (allRanks.length === 1)
|
|
40
|
+
return 0.9;
|
|
41
|
+
const minRank = Math.min(...allRanks); // Most relevant (most negative)
|
|
42
|
+
const maxRank = Math.max(...allRanks); // Least relevant
|
|
43
|
+
if (maxRank === minRank)
|
|
44
|
+
return 0.9;
|
|
45
|
+
// Linear normalization: most negative → 1.0, least negative → 0.3
|
|
46
|
+
return 0.3 + 0.7 * ((maxRank - rank) / (maxRank - minRank));
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Fast recall — keyword search only, no LLM, no embeddings.
|
|
50
|
+
* Designed to run on every host turn via MCP Resource (sub-50ms target).
|
|
51
|
+
*
|
|
52
|
+
* v2.0: When gnosysDb is provided, recall runs entirely from SQLite.
|
|
53
|
+
* No filesystem reads. Sub-10ms.
|
|
54
|
+
*
|
|
55
|
+
* When aggressive=true (default):
|
|
56
|
+
* - Always returns up to maxMemories regardless of relevance score
|
|
57
|
+
* - Uses minRelevance as a soft floor, not a hard cutoff
|
|
58
|
+
* - Injects even medium-relevance memories to boost context in long sessions
|
|
59
|
+
*
|
|
60
|
+
* When aggressive=false:
|
|
61
|
+
* - Only returns memories above minRelevance threshold
|
|
62
|
+
* - May return zero memories if nothing matches well
|
|
63
|
+
*/
|
|
64
|
+
export async function recall(query, options) {
|
|
65
|
+
const start = performance.now();
|
|
66
|
+
const cfg = options.recallConfig || DEFAULT_RECALL_CONFIG;
|
|
67
|
+
const limit = options.limit || cfg.maxMemories;
|
|
68
|
+
// ─── v2.0 DB-backed fast path ──────────────────────────────────────
|
|
69
|
+
if (options.gnosysDb?.isAvailable() && options.gnosysDb?.isMigrated()) {
|
|
70
|
+
return recallFromDb(query, options.gnosysDb, limit, cfg, options.traceId);
|
|
71
|
+
}
|
|
72
|
+
// ─── v1.x legacy path (filesystem + search.db) ────────────────────
|
|
73
|
+
const memories = [];
|
|
74
|
+
// Step 1: Fast keyword search on active memories (FTS5 — sub-10ms)
|
|
75
|
+
const fetchLimit = Math.max(limit * 2, 15);
|
|
76
|
+
const activeResults = options.search.discover(query, fetchLimit);
|
|
77
|
+
const allRanks = activeResults.map((r) => r.rank);
|
|
78
|
+
for (const r of activeResults) {
|
|
79
|
+
const memory = await options.resolver.readMemory(r.relative_path);
|
|
80
|
+
if (memory) {
|
|
81
|
+
const relevanceScore = normalizeRank(r.rank, allRanks);
|
|
82
|
+
memories.push({
|
|
83
|
+
id: memory.frontmatter.id,
|
|
84
|
+
title: memory.frontmatter.title,
|
|
85
|
+
category: memory.frontmatter.category,
|
|
86
|
+
relevance: memory.frontmatter.relevance || "",
|
|
87
|
+
confidence: memory.frontmatter.confidence,
|
|
88
|
+
path: r.relative_path,
|
|
89
|
+
fromArchive: false,
|
|
90
|
+
snippet: memory.content.substring(0, 300),
|
|
91
|
+
relevanceScore,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Step 2: Archive fallback if active results are thin
|
|
96
|
+
let totalArchived = 0;
|
|
97
|
+
if (memories.length < limit) {
|
|
98
|
+
try {
|
|
99
|
+
const archive = new GnosysArchive(options.storePath);
|
|
100
|
+
if (archive.isAvailable()) {
|
|
101
|
+
const stats = archive.getStats();
|
|
102
|
+
totalArchived = stats.totalArchived;
|
|
103
|
+
const archiveResults = archive.searchArchive(query, limit - memories.length);
|
|
104
|
+
const existingTitles = new Set(memories.map((m) => m.title.toLowerCase()));
|
|
105
|
+
for (const ar of archiveResults) {
|
|
106
|
+
if (!existingTitles.has(ar.title.toLowerCase())) {
|
|
107
|
+
memories.push({
|
|
108
|
+
id: ar.id,
|
|
109
|
+
title: ar.title,
|
|
110
|
+
category: ar.category,
|
|
111
|
+
relevance: ar.tags,
|
|
112
|
+
confidence: 0,
|
|
113
|
+
path: `archive:${ar.category}/${ar.id}`,
|
|
114
|
+
fromArchive: true,
|
|
115
|
+
snippet: ar.snippet,
|
|
116
|
+
relevanceScore: 0.5,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
archive.close();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// Archive not available — degrade gracefully
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Step 3: Apply filtering
|
|
128
|
+
const result = applyRecallFiltering(memories, activeResults.length, totalArchived, limit, cfg, start);
|
|
129
|
+
auditLog({
|
|
130
|
+
operation: "recall",
|
|
131
|
+
query,
|
|
132
|
+
resultCount: result.memories.length,
|
|
133
|
+
durationMs: result.recallTimeMs,
|
|
134
|
+
traceId: options.traceId,
|
|
135
|
+
details: {
|
|
136
|
+
aggressive: cfg.aggressive,
|
|
137
|
+
totalCandidates: memories.length,
|
|
138
|
+
filtered: result.memories.length,
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
return result;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* v2.0 DB-backed recall — runs entirely from gnosys.db.
|
|
145
|
+
* No filesystem reads. No separate search.db. Sub-10ms target.
|
|
146
|
+
*/
|
|
147
|
+
function recallFromDb(query, db, limit, cfg, traceId) {
|
|
148
|
+
const start = performance.now();
|
|
149
|
+
const memories = [];
|
|
150
|
+
// Step 1: FTS5 discover on gnosys.db
|
|
151
|
+
const fetchLimit = Math.max(limit * 2, 15);
|
|
152
|
+
const dbResults = db.discoverFts(query, fetchLimit);
|
|
153
|
+
const allRanks = dbResults.map((r) => r.rank);
|
|
154
|
+
for (const r of dbResults) {
|
|
155
|
+
const mem = db.getMemory(r.id);
|
|
156
|
+
if (mem && mem.tier === "active" && mem.status === "active") {
|
|
157
|
+
const relevanceScore = normalizeRank(r.rank, allRanks);
|
|
158
|
+
memories.push({
|
|
159
|
+
id: mem.id,
|
|
160
|
+
title: mem.title,
|
|
161
|
+
category: mem.category,
|
|
162
|
+
relevance: mem.relevance || "",
|
|
163
|
+
confidence: mem.confidence,
|
|
164
|
+
path: mem.id,
|
|
165
|
+
fromArchive: false,
|
|
166
|
+
snippet: mem.content.substring(0, 300),
|
|
167
|
+
relevanceScore,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// Step 2: Archive tier fallback if active results are thin
|
|
172
|
+
const counts = db.getMemoryCount();
|
|
173
|
+
if (memories.length < limit) {
|
|
174
|
+
for (const r of dbResults) {
|
|
175
|
+
if (memories.length >= limit)
|
|
176
|
+
break;
|
|
177
|
+
const mem = db.getMemory(r.id);
|
|
178
|
+
if (mem && mem.tier === "archive") {
|
|
179
|
+
const existingIds = new Set(memories.map((m) => m.id));
|
|
180
|
+
if (!existingIds.has(mem.id)) {
|
|
181
|
+
const relevanceScore = normalizeRank(r.rank, allRanks);
|
|
182
|
+
memories.push({
|
|
183
|
+
id: mem.id,
|
|
184
|
+
title: mem.title,
|
|
185
|
+
category: mem.category,
|
|
186
|
+
relevance: mem.relevance || "",
|
|
187
|
+
confidence: mem.confidence,
|
|
188
|
+
path: mem.id,
|
|
189
|
+
fromArchive: true,
|
|
190
|
+
snippet: mem.content.substring(0, 300),
|
|
191
|
+
relevanceScore,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// Step 3: Apply same filtering logic
|
|
198
|
+
const result = applyRecallFiltering(memories, dbResults.filter((r) => {
|
|
199
|
+
const m = db.getMemory(r.id);
|
|
200
|
+
return m && m.tier === "active";
|
|
201
|
+
}).length, counts.archived, limit, cfg, start);
|
|
202
|
+
// Audit via db instead of JSONL
|
|
203
|
+
db.logAudit({
|
|
204
|
+
timestamp: new Date().toISOString(),
|
|
205
|
+
operation: "recall",
|
|
206
|
+
memory_id: null,
|
|
207
|
+
details: JSON.stringify({
|
|
208
|
+
query,
|
|
209
|
+
aggressive: cfg.aggressive,
|
|
210
|
+
totalCandidates: memories.length,
|
|
211
|
+
filtered: result.memories.length,
|
|
212
|
+
}),
|
|
213
|
+
duration_ms: Math.round(result.recallTimeMs),
|
|
214
|
+
trace_id: traceId || null,
|
|
215
|
+
});
|
|
216
|
+
return result;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Shared filtering logic for both v1.x and v2.0 paths.
|
|
220
|
+
*/
|
|
221
|
+
function applyRecallFiltering(memories, totalActive, totalArchived, limit, cfg, startTime) {
|
|
222
|
+
const sorted = [...memories].sort((a, b) => b.relevanceScore - a.relevanceScore);
|
|
223
|
+
let filtered;
|
|
224
|
+
if (cfg.aggressive) {
|
|
225
|
+
const guaranteed = sorted.slice(0, 3);
|
|
226
|
+
const rest = sorted.slice(3).filter((m) => m.relevanceScore >= cfg.minRelevance);
|
|
227
|
+
filtered = [...guaranteed, ...rest].slice(0, limit);
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
filtered = sorted.filter((m) => m.relevanceScore >= cfg.minRelevance).slice(0, limit);
|
|
231
|
+
}
|
|
232
|
+
const elapsed = performance.now() - startTime;
|
|
233
|
+
return {
|
|
234
|
+
memories: filtered,
|
|
235
|
+
totalActive,
|
|
236
|
+
totalArchived,
|
|
237
|
+
recallTimeMs: Math.round(elapsed * 100) / 100,
|
|
238
|
+
aggressive: cfg.aggressive,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Format recall results as a host-friendly <gnosys-recall> block.
|
|
243
|
+
* This is what gets injected into the model context on every turn
|
|
244
|
+
* via the MCP Resource. Citation-heavy with [[wikilinks]].
|
|
245
|
+
*/
|
|
246
|
+
export function formatRecall(result) {
|
|
247
|
+
if (result.memories.length === 0) {
|
|
248
|
+
return `<gnosys: no-strong-recall-needed>`;
|
|
249
|
+
}
|
|
250
|
+
const lines = [`<gnosys-recall>`];
|
|
251
|
+
for (let i = 0; i < result.memories.length; i++) {
|
|
252
|
+
const m = result.memories[i];
|
|
253
|
+
const archive = m.fromArchive ? " [ARCHIVED]" : "";
|
|
254
|
+
const filename = m.path.split("/").pop() || m.path;
|
|
255
|
+
lines.push(`[Memory ${i + 1}] [[${filename}]] (relevance: ${m.relevanceScore.toFixed(2)})${archive}`);
|
|
256
|
+
if (m.snippet) {
|
|
257
|
+
lines.push(m.snippet.substring(0, 250).replace(/\n/g, " ").trim());
|
|
258
|
+
}
|
|
259
|
+
lines.push("");
|
|
260
|
+
}
|
|
261
|
+
lines.push(`</gnosys-recall>`);
|
|
262
|
+
return lines.join("\n");
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Format recall results as a concise CLI-friendly output.
|
|
266
|
+
*/
|
|
267
|
+
export function formatRecallCLI(result) {
|
|
268
|
+
const mode = result.aggressive ? "aggressive" : "filtered";
|
|
269
|
+
if (result.memories.length === 0) {
|
|
270
|
+
return `[Gnosys Recall] No relevant memories found. (${mode}, ${result.recallTimeMs}ms)`;
|
|
271
|
+
}
|
|
272
|
+
const lines = [
|
|
273
|
+
`[Gnosys Recall] ${result.memories.length} memories (${mode}, ${result.recallTimeMs}ms)`,
|
|
274
|
+
"",
|
|
275
|
+
];
|
|
276
|
+
for (const m of result.memories) {
|
|
277
|
+
const archive = m.fromArchive ? " [ARCHIVED]" : "";
|
|
278
|
+
const score = m.relevanceScore.toFixed(2);
|
|
279
|
+
lines.push(`• ${m.title}${archive} (relevance: ${score})`);
|
|
280
|
+
lines.push(` Category: ${m.category} | Confidence: ${m.confidence}`);
|
|
281
|
+
lines.push(` Path: [[${m.path}]]`);
|
|
282
|
+
if (m.snippet) {
|
|
283
|
+
lines.push(` ${m.snippet.substring(0, 150).replace(/\n/g, " ").trim()}`);
|
|
284
|
+
}
|
|
285
|
+
lines.push("");
|
|
286
|
+
}
|
|
287
|
+
return lines.join("\n");
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=recall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recall.js","sourceRoot":"","sources":["../../src/lib/recall.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAwBtC,4BAA4B;AAC5B,MAAM,qBAAqB,GAAiB;IAC1C,UAAU,EAAE,IAAI;IAChB,WAAW,EAAE,CAAC;IACd,YAAY,EAAE,GAAG;CAClB,CAAC;AAEF;;;;GAIG;AACH,SAAS,aAAa,CAAC,IAAY,EAAE,QAAkB;IACrD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IACtC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAEtC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,gCAAgC;IACvE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,iBAAiB;IAExD,IAAI,OAAO,KAAK,OAAO;QAAE,OAAO,GAAG,CAAC;IAEpC,kEAAkE;IAClE,OAAO,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,KAAa,EACb,OASC;IAED,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IAChC,MAAM,GAAG,GAAG,OAAO,CAAC,YAAY,IAAI,qBAAqB,CAAC;IAC1D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,GAAG,CAAC,WAAW,CAAC;IAE/C,sEAAsE;IACtE,IAAI,OAAO,CAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,OAAO,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,CAAC;QACtE,OAAO,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5E,CAAC;IAED,qEAAqE;IACrE,MAAM,QAAQ,GAAmB,EAAE,CAAC;IAEpC,mEAAmE;IACnE,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;IAC3C,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IACjE,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAElD,KAAK,MAAM,CAAC,IAAI,aAAa,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;QAClE,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,cAAc,GAAG,aAAa,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACvD,QAAQ,CAAC,IAAI,CAAC;gBACZ,EAAE,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE;gBACzB,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,KAAK;gBAC/B,QAAQ,EAAE,MAAM,CAAC,WAAW,CAAC,QAAQ;gBACrC,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,SAAS,IAAI,EAAE;gBAC7C,UAAU,EAAE,MAAM,CAAC,WAAW,CAAC,UAAU;gBACzC,IAAI,EAAE,CAAC,CAAC,aAAa;gBACrB,WAAW,EAAE,KAAK;gBAClB,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC;gBACzC,cAAc;aACf,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,sDAAsD;IACtD,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,IAAI,QAAQ,CAAC,MAAM,GAAG,KAAK,EAAE,CAAC;QAC5B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,aAAa,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YACrD,IAAI,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;gBAC1B,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACjC,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;gBAEpC,MAAM,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAC7E,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;gBAE3E,KAAK,MAAM,EAAE,IAAI,cAAc,EAAE,CAAC;oBAChC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;wBAChD,QAAQ,CAAC,IAAI,CAAC;4BACZ,EAAE,EAAE,EAAE,CAAC,EAAE;4BACT,KAAK,EAAE,EAAE,CAAC,KAAK;4BACf,QAAQ,EAAE,EAAE,CAAC,QAAQ;4BACrB,SAAS,EAAE,EAAE,CAAC,IAAI;4BAClB,UAAU,EAAE,CAAC;4BACb,IAAI,EAAE,WAAW,EAAE,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,EAAE;4BACvC,WAAW,EAAE,IAAI;4BACjB,OAAO,EAAE,EAAE,CAAC,OAAO;4BACnB,cAAc,EAAE,GAAG;yBACpB,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;gBACD,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,6CAA6C;QAC/C,CAAC;IACH,CAAC;IAED,0BAA0B;IAC1B,MAAM,MAAM,GAAG,oBAAoB,CAAC,QAAQ,EAAE,aAAa,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IAEtG,QAAQ,CAAC;QACP,SAAS,EAAE,QAAQ;QACnB,KAAK;QACL,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM;QACnC,UAAU,EAAE,MAAM,CAAC,YAAY;QAC/B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,OAAO,EAAE;YACP,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,eAAe,EAAE,QAAQ,CAAC,MAAM;YAChC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM;SACjC;KACF,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY,CACnB,KAAa,EACb,EAAY,EACZ,KAAa,EACb,GAAiB,EACjB,OAAgB;IAEhB,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IAChC,MAAM,QAAQ,GAAmB,EAAE,CAAC;IAEpC,qCAAqC;IACrC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAE9C,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/B,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC5D,MAAM,cAAc,GAAG,aAAa,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACvD,QAAQ,CAAC,IAAI,CAAC;gBACZ,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,SAAS,EAAE,GAAG,CAAC,SAAS,IAAI,EAAE;gBAC9B,UAAU,EAAE,GAAG,CAAC,UAAU;gBAC1B,IAAI,EAAE,GAAG,CAAC,EAAE;gBACZ,WAAW,EAAE,KAAK;gBAClB,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC;gBACtC,cAAc;aACf,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,2DAA2D;IAC3D,MAAM,MAAM,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC;IACnC,IAAI,QAAQ,CAAC,MAAM,GAAG,KAAK,EAAE,CAAC;QAC5B,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;YAC1B,IAAI,QAAQ,CAAC,MAAM,IAAI,KAAK;gBAAE,MAAM;YACpC,MAAM,GAAG,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC/B,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAClC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;gBACvD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;oBAC7B,MAAM,cAAc,GAAG,aAAa,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;oBACvD,QAAQ,CAAC,IAAI,CAAC;wBACZ,EAAE,EAAE,GAAG,CAAC,EAAE;wBACV,KAAK,EAAE,GAAG,CAAC,KAAK;wBAChB,QAAQ,EAAE,GAAG,CAAC,QAAQ;wBACtB,SAAS,EAAE,GAAG,CAAC,SAAS,IAAI,EAAE;wBAC9B,UAAU,EAAE,GAAG,CAAC,UAAU;wBAC1B,IAAI,EAAE,GAAG,CAAC,EAAE;wBACZ,WAAW,EAAE,IAAI;wBACjB,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC;wBACtC,cAAc;qBACf,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,qCAAqC;IACrC,MAAM,MAAM,GAAG,oBAAoB,CACjC,QAAQ,EACR,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QACrB,MAAM,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC7B,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC;IAClC,CAAC,CAAC,CAAC,MAAM,EACT,MAAM,CAAC,QAAQ,EACf,KAAK,EACL,GAAG,EACH,KAAK,CACN,CAAC;IAEF,gCAAgC;IAChC,EAAE,CAAC,QAAQ,CAAC;QACV,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,SAAS,EAAE,QAAQ;QACnB,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC;YACtB,KAAK;YACL,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,eAAe,EAAE,QAAQ,CAAC,MAAM;YAChC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM;SACjC,CAAC;QACF,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC;QAC5C,QAAQ,EAAE,OAAO,IAAI,IAAI;KAC1B,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAC3B,QAAwB,EACxB,WAAmB,EACnB,aAAqB,EACrB,KAAa,EACb,GAAiB,EACjB,SAAiB;IAEjB,MAAM,MAAM,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,GAAG,CAAC,CAAC,cAAc,CAAC,CAAC;IACjF,IAAI,QAAwB,CAAC;IAE7B,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;QACnB,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACtC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;QACjF,QAAQ,GAAG,CAAC,GAAG,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACtD,CAAC;SAAM,CAAC;QACN,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACxF,CAAC;IAED,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IAE9C,OAAO;QACL,QAAQ,EAAE,QAAQ;QAClB,WAAW;QACX,aAAa;QACb,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC,GAAG,GAAG;QAC7C,UAAU,EAAE,GAAG,CAAC,UAAU;KAC3B,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,MAAoB;IAC/C,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,mCAAmC,CAAC;IAC7C,CAAC;IAED,MAAM,KAAK,GAAa,CAAC,iBAAiB,CAAC,CAAC;IAE5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChD,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC7B,MAAM,OAAO,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,MAAM,QAAQ,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC;QACnD,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,QAAQ,kBAAkB,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC;QACtG,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;YACd,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACrE,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC/B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,MAAoB;IAClD,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC;IAC3D,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,gDAAgD,IAAI,KAAK,MAAM,CAAC,YAAY,KAAK,CAAC;IAC3F,CAAC;IAED,MAAM,KAAK,GAAa;QACtB,mBAAmB,MAAM,CAAC,QAAQ,CAAC,MAAM,cAAc,IAAI,KAAK,MAAM,CAAC,YAAY,KAAK;QACxF,EAAE;KACH,CAAC;IAEF,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,MAAM,KAAK,GAAG,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC1C,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,OAAO,gBAAgB,KAAK,GAAG,CAAC,CAAC;QAC3D,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,QAAQ,kBAAkB,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;QACtE,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;YACd,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC5E,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gnosys Store Resolver — Discovers and manages layered stores.
|
|
3
|
+
*
|
|
4
|
+
* Four layers, resolved in specificity order:
|
|
5
|
+
* Project (auto-discovered from cwd, writable, default write target)
|
|
6
|
+
* Optional (GNOSYS_STORES, read-only)
|
|
7
|
+
* Personal (GNOSYS_PERSONAL, writable, fallback write target)
|
|
8
|
+
* Global (GNOSYS_GLOBAL, writable only when explicitly targeted)
|
|
9
|
+
*/
|
|
10
|
+
import { GnosysStore, Memory } from "./store.js";
|
|
11
|
+
export type StoreLayer = "project" | "personal" | "global" | "optional";
|
|
12
|
+
export interface ResolvedStore {
|
|
13
|
+
layer: StoreLayer;
|
|
14
|
+
label: string;
|
|
15
|
+
store: GnosysStore;
|
|
16
|
+
writable: boolean;
|
|
17
|
+
path: string;
|
|
18
|
+
}
|
|
19
|
+
export interface LayeredMemory extends Memory {
|
|
20
|
+
sourceLayer: StoreLayer;
|
|
21
|
+
sourceLabel: string;
|
|
22
|
+
}
|
|
23
|
+
export declare class GnosysResolver {
|
|
24
|
+
private stores;
|
|
25
|
+
/** MCP workspace roots (file:// URIs → local paths). Updated via roots/list. */
|
|
26
|
+
private static mcpRoots;
|
|
27
|
+
/**
|
|
28
|
+
* Update the MCP roots list. Call this from the MCP server on init
|
|
29
|
+
* and on "notifications/roots/list_changed".
|
|
30
|
+
*/
|
|
31
|
+
static setMcpRoots(roots: Array<{
|
|
32
|
+
uri: string;
|
|
33
|
+
name?: string;
|
|
34
|
+
}>): void;
|
|
35
|
+
/**
|
|
36
|
+
* Get the current MCP roots as local paths.
|
|
37
|
+
*/
|
|
38
|
+
static getMcpRoots(): string[];
|
|
39
|
+
/**
|
|
40
|
+
* Create a resolver scoped to a specific project root.
|
|
41
|
+
* Used for per-tool projectRoot parameter — each call gets its own
|
|
42
|
+
* resolver instance, so there's no shared mutable state.
|
|
43
|
+
*/
|
|
44
|
+
static resolveForProject(projectRoot: string): Promise<GnosysResolver>;
|
|
45
|
+
/**
|
|
46
|
+
* Discover and initialize all store layers.
|
|
47
|
+
*/
|
|
48
|
+
resolve(): Promise<ResolvedStore[]>;
|
|
49
|
+
/**
|
|
50
|
+
* Get all stores in precedence order.
|
|
51
|
+
*/
|
|
52
|
+
getStores(): ResolvedStore[];
|
|
53
|
+
/**
|
|
54
|
+
* Get all memories across all stores, tagged with their source.
|
|
55
|
+
*/
|
|
56
|
+
getAllMemories(): Promise<LayeredMemory[]>;
|
|
57
|
+
/**
|
|
58
|
+
* Read a memory, searching stores in precedence order.
|
|
59
|
+
* Path format: "layer:category/filename.md" or just "category/filename.md" (searches all).
|
|
60
|
+
*/
|
|
61
|
+
readMemory(memPath: string): Promise<LayeredMemory | null>;
|
|
62
|
+
/**
|
|
63
|
+
* Get the writable store for a given target layer.
|
|
64
|
+
*
|
|
65
|
+
* When no target is specified, auto-selects: project → personal.
|
|
66
|
+
* Global is writable but NEVER auto-selected — it must be explicitly
|
|
67
|
+
* requested (store: "global"). This prevents accidental writes to
|
|
68
|
+
* shared org knowledge.
|
|
69
|
+
* Optional stores are always read-only.
|
|
70
|
+
*/
|
|
71
|
+
getWriteTarget(target?: StoreLayer): ResolvedStore | null;
|
|
72
|
+
/**
|
|
73
|
+
* Get a summary of all active stores for logging.
|
|
74
|
+
*/
|
|
75
|
+
getSummary(): string;
|
|
76
|
+
/**
|
|
77
|
+
* Register a project directory in the persistent project registry.
|
|
78
|
+
* Called by gnosys_init after creating a new store.
|
|
79
|
+
*/
|
|
80
|
+
registerProject(projectDir: string): Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* Directly add a project store to the active stores list.
|
|
83
|
+
* Used after gnosys_init creates a store, to avoid re-resolving from cwd.
|
|
84
|
+
*/
|
|
85
|
+
addProjectStore(storePath: string): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* Find a project store. Priority order:
|
|
88
|
+
* 1. Registered projects (~/.config/gnosys/projects.json)
|
|
89
|
+
* 2. MCP workspace roots (from roots/list)
|
|
90
|
+
* 3. Walk up from cwd (legacy fallback)
|
|
91
|
+
*/
|
|
92
|
+
private findProjectStore;
|
|
93
|
+
/**
|
|
94
|
+
* Read registered project directories from persistent config.
|
|
95
|
+
*/
|
|
96
|
+
private getRegisteredProjects;
|
|
97
|
+
/**
|
|
98
|
+
* Path to the persistent project registry file.
|
|
99
|
+
*/
|
|
100
|
+
private getRegistryPath;
|
|
101
|
+
/**
|
|
102
|
+
* Detect all available stores from all sources (registered, MCP roots, cwd, env vars).
|
|
103
|
+
* Returns a flat list for debugging. Does NOT modify the active stores.
|
|
104
|
+
*/
|
|
105
|
+
detectAllStores(): Promise<Array<{
|
|
106
|
+
source: string;
|
|
107
|
+
path: string;
|
|
108
|
+
hasGnosys: boolean;
|
|
109
|
+
isActive: boolean;
|
|
110
|
+
}>>;
|
|
111
|
+
/**
|
|
112
|
+
* Check if a path looks like a valid Gnosys store.
|
|
113
|
+
*/
|
|
114
|
+
private isValidStore;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/lib/resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,UAAU,CAAC;AAExE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,UAAU,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAc,SAAQ,MAAM;IAC3C,WAAW,EAAE,UAAU,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAuB;IAErC,gFAAgF;IAChF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAgB;IAEvC;;;OAGG;IACH,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI;IAgBtE;;OAEG;IACH,MAAM,CAAC,WAAW,IAAI,MAAM,EAAE;IAI9B;;;;OAIG;WACU,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAwB5E;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;IA6EzC;;OAEG;IACH,SAAS,IAAI,aAAa,EAAE;IAI5B;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;IAiBhD;;;OAGG;IACG,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAyBhE;;;;;;;;OAQG;IACH,cAAc,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,aAAa,GAAG,IAAI;IAgBzD;;OAEG;IACH,UAAU,IAAI,MAAM;IAapB;;;OAGG;IACG,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBxD;;;OAGG;IACG,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAevD;;;;;OAKG;YACW,gBAAgB;IAkC9B;;OAEG;YACW,qBAAqB;IASnC;;OAEG;IACH,OAAO,CAAC,eAAe;IAKvB;;;OAGG;IACG,eAAe,IAAI,OAAO,CAAC,KAAK,CAAC;QACrC,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,OAAO,CAAC;QACnB,QAAQ,EAAE,OAAO,CAAC;KACnB,CAAC,CAAC;IAyCH;;OAEG;YACW,YAAY;CAQ3B"}
|