@jigyasudham/veto 3.2.1 → 3.4.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 +62 -7
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +4 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/agents/llm-runner.d.ts.map +1 -1
- package/dist/agents/llm-runner.js +17 -4
- package/dist/agents/llm-runner.js.map +1 -1
- package/dist/cli/context-guidance.d.ts +16 -0
- package/dist/cli/context-guidance.d.ts.map +1 -0
- package/dist/cli/context-guidance.js +20 -0
- package/dist/cli/context-guidance.js.map +1 -0
- package/dist/cli/leftover-guides.d.ts +38 -0
- package/dist/cli/leftover-guides.d.ts.map +1 -0
- package/dist/cli/leftover-guides.js +135 -0
- package/dist/cli/leftover-guides.js.map +1 -0
- package/dist/cli/statusline-hosts.d.ts +36 -0
- package/dist/cli/statusline-hosts.d.ts.map +1 -0
- package/dist/cli/statusline-hosts.js +212 -0
- package/dist/cli/statusline-hosts.js.map +1 -0
- package/dist/cli/statusline.d.ts +6 -0
- package/dist/cli/statusline.d.ts.map +1 -1
- package/dist/cli/statusline.js +51 -10
- package/dist/cli/statusline.js.map +1 -1
- package/dist/cli.js +105 -48
- package/dist/cli.js.map +1 -1
- package/dist/council/llm-council.d.ts.map +1 -1
- package/dist/council/llm-council.js +13 -8
- package/dist/council/llm-council.js.map +1 -1
- package/dist/lessons/adapters/claude.d.ts +10 -0
- package/dist/lessons/adapters/claude.d.ts.map +1 -0
- package/dist/lessons/adapters/claude.js +18 -0
- package/dist/lessons/adapters/claude.js.map +1 -0
- package/dist/lessons/adapters/codex.d.ts +7 -0
- package/dist/lessons/adapters/codex.d.ts.map +1 -0
- package/dist/lessons/adapters/codex.js +9 -0
- package/dist/lessons/adapters/codex.js.map +1 -0
- package/dist/lessons/adapters/gemini.d.ts +4 -0
- package/dist/lessons/adapters/gemini.d.ts.map +1 -0
- package/dist/lessons/adapters/gemini.js +44 -0
- package/dist/lessons/adapters/gemini.js.map +1 -0
- package/dist/lessons/adapters/index.d.ts +6 -0
- package/dist/lessons/adapters/index.d.ts.map +1 -0
- package/dist/lessons/adapters/index.js +14 -0
- package/dist/lessons/adapters/index.js.map +1 -0
- package/dist/lessons/adapters/markdown.d.ts +16 -0
- package/dist/lessons/adapters/markdown.d.ts.map +1 -0
- package/dist/lessons/adapters/markdown.js +130 -0
- package/dist/lessons/adapters/markdown.js.map +1 -0
- package/dist/lessons/adapters/types.d.ts +27 -0
- package/dist/lessons/adapters/types.d.ts.map +1 -0
- package/dist/lessons/adapters/types.js +2 -0
- package/dist/lessons/adapters/types.js.map +1 -0
- package/dist/lessons/classify.d.ts +30 -0
- package/dist/lessons/classify.d.ts.map +1 -0
- package/dist/lessons/classify.js +101 -0
- package/dist/lessons/classify.js.map +1 -0
- package/dist/lessons/discover.d.ts +19 -0
- package/dist/lessons/discover.d.ts.map +1 -0
- package/dist/lessons/discover.js +65 -0
- package/dist/lessons/discover.js.map +1 -0
- package/dist/lessons/harvest.d.ts +48 -0
- package/dist/lessons/harvest.d.ts.map +1 -0
- package/dist/lessons/harvest.js +96 -0
- package/dist/lessons/harvest.js.map +1 -0
- package/dist/lessons/identity.d.ts +23 -0
- package/dist/lessons/identity.d.ts.map +1 -0
- package/dist/lessons/identity.js +81 -0
- package/dist/lessons/identity.js.map +1 -0
- package/dist/lessons/mask.d.ts +6 -0
- package/dist/lessons/mask.d.ts.map +1 -0
- package/dist/lessons/mask.js +22 -0
- package/dist/lessons/mask.js.map +1 -0
- package/dist/lessons/select.d.ts +23 -0
- package/dist/lessons/select.d.ts.map +1 -0
- package/dist/lessons/select.js +134 -0
- package/dist/lessons/select.js.map +1 -0
- package/dist/lessons/source-project.d.ts +9 -0
- package/dist/lessons/source-project.d.ts.map +1 -0
- package/dist/lessons/source-project.js +149 -0
- package/dist/lessons/source-project.js.map +1 -0
- package/dist/lessons/store.d.ts +56 -0
- package/dist/lessons/store.d.ts.map +1 -0
- package/dist/lessons/store.js +85 -0
- package/dist/lessons/store.js.map +1 -0
- package/dist/memory/config.d.ts +14 -0
- package/dist/memory/config.d.ts.map +1 -1
- package/dist/memory/config.js +43 -0
- package/dist/memory/config.js.map +1 -1
- package/dist/memory/decisions.d.ts +34 -1
- package/dist/memory/decisions.d.ts.map +1 -1
- package/dist/memory/decisions.js +158 -13
- package/dist/memory/decisions.js.map +1 -1
- package/dist/memory/local.d.ts.map +1 -1
- package/dist/memory/local.js +38 -4
- package/dist/memory/local.js.map +1 -1
- package/dist/memory/schema.d.ts +2 -1
- package/dist/memory/schema.d.ts.map +1 -1
- package/dist/memory/schema.js +69 -0
- package/dist/memory/schema.js.map +1 -1
- package/dist/server/handlers/council.d.ts.map +1 -1
- package/dist/server/handlers/council.js +16 -2
- package/dist/server/handlers/council.js.map +1 -1
- package/dist/server/handlers/generators.d.ts.map +1 -1
- package/dist/server/handlers/generators.js +8 -0
- package/dist/server/handlers/generators.js.map +1 -1
- package/dist/server/handlers/memory.d.ts.map +1 -1
- package/dist/server/handlers/memory.js +44 -7
- package/dist/server/handlers/memory.js.map +1 -1
- package/dist/server/handlers/session.d.ts.map +1 -1
- package/dist/server/handlers/session.js +52 -22
- package/dist/server/handlers/session.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +12 -3
- package/dist/server.js.map +1 -1
- package/dist/tools/definitions.d.ts +7 -3
- package/dist/tools/definitions.d.ts.map +1 -1
- package/dist/tools/definitions.js +4 -3
- package/dist/tools/definitions.js.map +1 -1
- package/dist/transcripts/cache.d.ts +1 -0
- package/dist/transcripts/cache.d.ts.map +1 -1
- package/dist/transcripts/cache.js +0 -0
- package/dist/transcripts/cache.js.map +1 -1
- package/dist/transcripts/claude-paths.d.ts +5 -0
- package/dist/transcripts/claude-paths.d.ts.map +1 -0
- package/dist/transcripts/claude-paths.js +21 -0
- package/dist/transcripts/claude-paths.js.map +1 -0
- package/dist/transcripts/context.d.ts +41 -0
- package/dist/transcripts/context.d.ts.map +1 -0
- package/dist/transcripts/context.js +144 -0
- package/dist/transcripts/context.js.map +1 -0
- package/dist/transcripts/discover.d.ts +12 -2
- package/dist/transcripts/discover.d.ts.map +1 -1
- package/dist/transcripts/discover.js +55 -7
- package/dist/transcripts/discover.js.map +1 -1
- package/dist/transcripts/manage.d.ts +8 -0
- package/dist/transcripts/manage.d.ts.map +1 -1
- package/dist/transcripts/manage.js +28 -13
- package/dist/transcripts/manage.js.map +1 -1
- package/dist/transcripts/mapping.d.ts.map +1 -1
- package/dist/transcripts/mapping.js +4 -2
- package/dist/transcripts/mapping.js.map +1 -1
- package/dist/transcripts/on-save.d.ts +9 -0
- package/dist/transcripts/on-save.d.ts.map +1 -1
- package/dist/transcripts/on-save.js +36 -9
- package/dist/transcripts/on-save.js.map +1 -1
- package/dist/transcripts/project-key.d.ts +4 -0
- package/dist/transcripts/project-key.d.ts.map +1 -0
- package/dist/transcripts/project-key.js +30 -0
- package/dist/transcripts/project-key.js.map +1 -0
- package/dist/transcripts/recall.d.ts +4 -0
- package/dist/transcripts/recall.d.ts.map +1 -1
- package/dist/transcripts/recall.js +6 -5
- package/dist/transcripts/recall.js.map +1 -1
- package/dist/transcripts/stopwords.d.ts +2 -0
- package/dist/transcripts/stopwords.d.ts.map +1 -0
- package/dist/transcripts/stopwords.js +8 -0
- package/dist/transcripts/stopwords.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { parseMarkdownMemory } from './markdown.js';
|
|
3
|
+
// Gemini CLI's save_memory tool appends `- <fact>` lines under this heading in
|
|
4
|
+
// ~/.gemini/GEMINI.md; the rest of the file is the user's own instructions.
|
|
5
|
+
export const GEMINI_MEMORY_HEADING = 'Gemini Added Memories';
|
|
6
|
+
/**
|
|
7
|
+
* One saved fact per section. Anchors hash the fact rather than count bullets,
|
|
8
|
+
* so inserting a memory does not re-key every memory after it.
|
|
9
|
+
*/
|
|
10
|
+
function splitSavedMemories(section) {
|
|
11
|
+
const facts = [];
|
|
12
|
+
const rest = [];
|
|
13
|
+
for (const line of section.text.split('\n').slice(1)) {
|
|
14
|
+
const bullet = /^\s*[-*]\s+(.+)$/.exec(line);
|
|
15
|
+
if (bullet)
|
|
16
|
+
facts.push(bullet[1].trim());
|
|
17
|
+
else if (/^\s+\S/.test(line) && facts.length)
|
|
18
|
+
facts[facts.length - 1] += ` ${line.trim()}`;
|
|
19
|
+
else if (line.trim())
|
|
20
|
+
rest.push(line);
|
|
21
|
+
}
|
|
22
|
+
const seen = new Set();
|
|
23
|
+
const out = [];
|
|
24
|
+
for (const fact of facts) {
|
|
25
|
+
const anchor = `${section.anchor}-${createHash('sha256').update(fact).digest('hex').slice(0, 8)}`;
|
|
26
|
+
if (seen.has(anchor))
|
|
27
|
+
continue;
|
|
28
|
+
seen.add(anchor);
|
|
29
|
+
out.push({ anchor, title: section.title, text: fact });
|
|
30
|
+
}
|
|
31
|
+
if (rest.length)
|
|
32
|
+
out.push({ ...section, text: `${section.title}\n${rest.join('\n')}` });
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
export function parseGeminiMemory(raw, fileName = '') {
|
|
36
|
+
const parsed = parseMarkdownMemory(raw, fileName || 'GEMINI.md');
|
|
37
|
+
if (!parsed.ok || 'skip' in parsed)
|
|
38
|
+
return parsed;
|
|
39
|
+
return {
|
|
40
|
+
...parsed,
|
|
41
|
+
sections: parsed.sections.flatMap(section => section.title === GEMINI_MEMORY_HEADING ? splitSavedMemories(section) : [section]),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=gemini.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../../src/lessons/adapters/gemini.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAGpD,+EAA+E;AAC/E,4EAA4E;AAC5E,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAuB,CAAC;AAE7D;;;GAGG;AACH,SAAS,kBAAkB,CAAC,OAAsB;IAChD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;aACpC,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,MAAM;YAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;aACtF,IAAI,IAAI,CAAC,IAAI,EAAE;YAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAoB,EAAE,CAAC;IAChC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAClG,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,SAAS;QAC/B,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACjB,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,IAAI,CAAC,MAAM;QAAE,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IACxF,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAW,EAAE,QAAQ,GAAG,EAAE;IAC1D,MAAM,MAAM,GAAG,mBAAmB,CAAC,GAAG,EAAE,QAAQ,IAAI,WAAW,CAAC,CAAC;IACjE,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,MAAM,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAClD,OAAO;QACL,GAAG,MAAM;QACT,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAC1C,OAAO,CAAC,KAAK,KAAK,qBAAqB,CAAC,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;KACrF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { LessonSource, MemoryParseResult } from './types.js';
|
|
2
|
+
export type { LessonSource, MemoryFrontmatter, MemoryParseResult, MemorySection } from './types.js';
|
|
3
|
+
export { LESSON_SOURCES } from './types.js';
|
|
4
|
+
/** Parse one native-memory document using its host-specific adapter. */
|
|
5
|
+
export declare function parseNativeMemory(source: LessonSource, raw: string, fileName?: string): MemoryParseResult;
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lessons/adapters/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAElE,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACpG,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAQ5C,wEAAwE;AACxE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,SAAK,GAAG,iBAAiB,CAErG"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { parseClaudeMemory } from './claude.js';
|
|
2
|
+
import { parseCodexMemory } from './codex.js';
|
|
3
|
+
import { parseGeminiMemory } from './gemini.js';
|
|
4
|
+
export { LESSON_SOURCES } from './types.js';
|
|
5
|
+
const PARSERS = {
|
|
6
|
+
claude: parseClaudeMemory,
|
|
7
|
+
codex: parseCodexMemory,
|
|
8
|
+
gemini: parseGeminiMemory,
|
|
9
|
+
};
|
|
10
|
+
/** Parse one native-memory document using its host-specific adapter. */
|
|
11
|
+
export function parseNativeMemory(source, raw, fileName = '') {
|
|
12
|
+
return PARSERS[source](raw, fileName);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lessons/adapters/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIhD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,OAAO,GAA+E;IAC1F,MAAM,EAAE,iBAAiB;IACzB,KAAK,EAAE,gBAAgB;IACvB,MAAM,EAAE,iBAAiB;CAC1B,CAAC;AAEF,wEAAwE;AACxE,MAAM,UAAU,iBAAiB,CAAC,MAAoB,EAAE,GAAW,EAAE,QAAQ,GAAG,EAAE;IAChF,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { MemoryParseResult, MemorySection } from './types.js';
|
|
2
|
+
export declare function normalizeMarkdown(raw: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* Split a Markdown body into section-level notes. Text before the first heading
|
|
5
|
+
* is a note of its own (most Claude entries have no heading at all). Headings
|
|
6
|
+
* inside fenced code are not structure, and a heading with no body is only a
|
|
7
|
+
* document title. Anchors are unique within the document.
|
|
8
|
+
*/
|
|
9
|
+
export declare function splitSections(body: string, fallbackTitle: string): MemorySection[];
|
|
10
|
+
/**
|
|
11
|
+
* Native memory documents are Markdown, optionally with YAML frontmatter.
|
|
12
|
+
* Only shapes that cannot be Markdown count as drift and fail closed; a
|
|
13
|
+
* headingless entry is the normal Claude shape, not drift.
|
|
14
|
+
*/
|
|
15
|
+
export declare function parseMarkdownMemory(raw: string, fallbackTitle?: string): MemoryParseResult;
|
|
16
|
+
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../../src/lessons/adapters/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAqB,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAMtF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAErD;AAiDD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,aAAa,EAAE,CAyBlF;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,SAAK,GAAG,iBAAiB,CAwBtF"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
const FRONTMATTER_RE = /^---\n([\s\S]*?)\n---[ \t]*(?:\n|$)/;
|
|
2
|
+
const HEADING_RE = /^(#{1,6})\s+(.+?)(?:\s+#+)?\s*$/;
|
|
3
|
+
const FENCE_RE = /^\s*(```|~~~)/;
|
|
4
|
+
export function normalizeMarkdown(raw) {
|
|
5
|
+
return raw.replace(/^\uFEFF/, '').replace(/\r\n?/g, '\n');
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The guide `veto init` used to write over ~/.gemini/GEMINI.md and
|
|
9
|
+
* ~/.codex/AGENTS.override.md. It is Veto's own text, not a host's memory.
|
|
10
|
+
* Every version of it has exactly one heading, so it is always exactly one
|
|
11
|
+
* section, and a host that later appended its own memories below it keeps them.
|
|
12
|
+
*/
|
|
13
|
+
function isVetoGuideSection(section) {
|
|
14
|
+
return section.title === 'Veto MCP Server' && /\bVeto is active\b/.test(section.text);
|
|
15
|
+
}
|
|
16
|
+
function unquote(value) {
|
|
17
|
+
const v = value.trim();
|
|
18
|
+
if (v.length >= 2 && v.startsWith('"') && v.endsWith('"'))
|
|
19
|
+
return v.slice(1, -1).replace(/\\(["\\])/g, '$1');
|
|
20
|
+
if (v.length >= 2 && v.startsWith("'") && v.endsWith("'"))
|
|
21
|
+
return v.slice(1, -1).replace(/''/g, "'");
|
|
22
|
+
return v;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Just enough YAML for memory frontmatter: top-level `name`/`description`, and
|
|
26
|
+
* `type` either top-level (older entries) or nested under `metadata:` (current
|
|
27
|
+
* Claude entries). Block scalars are ignored rather than guessed at.
|
|
28
|
+
*/
|
|
29
|
+
function readFrontmatter(yaml) {
|
|
30
|
+
const out = {};
|
|
31
|
+
let parent = null;
|
|
32
|
+
for (const line of yaml.split('\n')) {
|
|
33
|
+
const m = /^(\s*)([A-Za-z_][\w-]*):[ \t]*(.*)$/.exec(line);
|
|
34
|
+
if (!m)
|
|
35
|
+
continue;
|
|
36
|
+
const [, indent, key, rawValue] = m;
|
|
37
|
+
const value = rawValue.trim();
|
|
38
|
+
if (indent.length === 0) {
|
|
39
|
+
parent = value === '' ? key : null;
|
|
40
|
+
if (value === '' || value === '|' || value === '>')
|
|
41
|
+
continue;
|
|
42
|
+
if (key === 'name')
|
|
43
|
+
out.name = unquote(value);
|
|
44
|
+
else if (key === 'description')
|
|
45
|
+
out.description = unquote(value);
|
|
46
|
+
else if (key === 'type')
|
|
47
|
+
out.type = unquote(value).toLowerCase();
|
|
48
|
+
}
|
|
49
|
+
else if (parent === 'metadata' && key === 'type' && value) {
|
|
50
|
+
out.type = unquote(value).toLowerCase();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
function slug(title) {
|
|
56
|
+
return title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Split a Markdown body into section-level notes. Text before the first heading
|
|
60
|
+
* is a note of its own (most Claude entries have no heading at all). Headings
|
|
61
|
+
* inside fenced code are not structure, and a heading with no body is only a
|
|
62
|
+
* document title. Anchors are unique within the document.
|
|
63
|
+
*/
|
|
64
|
+
export function splitSections(body, fallbackTitle) {
|
|
65
|
+
const lines = body.split('\n');
|
|
66
|
+
const headings = [];
|
|
67
|
+
let inFence = false;
|
|
68
|
+
lines.forEach((line, index) => {
|
|
69
|
+
if (FENCE_RE.test(line)) {
|
|
70
|
+
inFence = !inFence;
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (inFence)
|
|
74
|
+
return;
|
|
75
|
+
const m = HEADING_RE.exec(line);
|
|
76
|
+
if (m)
|
|
77
|
+
headings.push({ index, title: m[2].trim() });
|
|
78
|
+
});
|
|
79
|
+
const raw = [];
|
|
80
|
+
const preamble = lines.slice(0, headings[0]?.index ?? lines.length).join('\n').trim();
|
|
81
|
+
if (preamble)
|
|
82
|
+
raw.push({ base: 'body', title: fallbackTitle, body: preamble });
|
|
83
|
+
headings.forEach((heading, i) => {
|
|
84
|
+
const text = lines.slice(heading.index + 1, headings[i + 1]?.index ?? lines.length).join('\n').trim();
|
|
85
|
+
if (text)
|
|
86
|
+
raw.push({ base: slug(heading.title) || `section-${i + 1}`, title: heading.title, body: text });
|
|
87
|
+
});
|
|
88
|
+
const seen = new Map();
|
|
89
|
+
return raw.map(({ base, title, body: text }) => {
|
|
90
|
+
const n = (seen.get(base) ?? 0) + 1;
|
|
91
|
+
seen.set(base, n);
|
|
92
|
+
return { anchor: n === 1 ? base : `${base}-${n}`, title, text: title ? `${title}\n${text}` : text };
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Native memory documents are Markdown, optionally with YAML frontmatter.
|
|
97
|
+
* Only shapes that cannot be Markdown count as drift and fail closed; a
|
|
98
|
+
* headingless entry is the normal Claude shape, not drift.
|
|
99
|
+
*/
|
|
100
|
+
export function parseMarkdownMemory(raw, fallbackTitle = '') {
|
|
101
|
+
const text = normalizeMarkdown(raw);
|
|
102
|
+
if (text.includes('\u0000'))
|
|
103
|
+
return { ok: false, reason: 'binary content where Markdown was expected' };
|
|
104
|
+
const trimmed = text.trim();
|
|
105
|
+
if (!trimmed)
|
|
106
|
+
return { ok: true, skip: 'empty' };
|
|
107
|
+
if (/^[[{]/.test(trimmed)) {
|
|
108
|
+
try {
|
|
109
|
+
JSON.parse(trimmed);
|
|
110
|
+
return { ok: false, reason: 'JSON document where Markdown was expected' };
|
|
111
|
+
}
|
|
112
|
+
catch { /* Markdown that happens to start with a bracket */ }
|
|
113
|
+
}
|
|
114
|
+
let frontmatter = {};
|
|
115
|
+
let body = text;
|
|
116
|
+
if (text.startsWith('---\n')) {
|
|
117
|
+
const fm = FRONTMATTER_RE.exec(text);
|
|
118
|
+
if (!fm)
|
|
119
|
+
return { ok: false, reason: 'frontmatter is not terminated' };
|
|
120
|
+
frontmatter = readFrontmatter(fm[1]);
|
|
121
|
+
body = text.slice(fm[0].length);
|
|
122
|
+
}
|
|
123
|
+
const title = frontmatter.description || frontmatter.name || fallbackTitle;
|
|
124
|
+
const all = splitSections(body, title);
|
|
125
|
+
const sections = all.filter(section => !isVetoGuideSection(section));
|
|
126
|
+
if (sections.length)
|
|
127
|
+
return { ok: true, frontmatter, sections };
|
|
128
|
+
return { ok: true, skip: all.length ? 'veto-authored' : 'empty' };
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../../src/lessons/adapters/markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export declare const LESSON_SOURCES: readonly ["claude", "codex", "gemini"];
|
|
2
|
+
export type LessonSource = (typeof LESSON_SOURCES)[number];
|
|
3
|
+
export type MemorySection = {
|
|
4
|
+
anchor: string;
|
|
5
|
+
/** Heading, or the entry's frontmatter description/name for body text. */
|
|
6
|
+
title: string;
|
|
7
|
+
/** Title and body as one note; this is what gets masked and stored. */
|
|
8
|
+
text: string;
|
|
9
|
+
};
|
|
10
|
+
export type MemoryFrontmatter = {
|
|
11
|
+
name?: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
/** Claude memory type: user | feedback | project | reference. */
|
|
14
|
+
type?: string;
|
|
15
|
+
};
|
|
16
|
+
export type MemoryParseResult = {
|
|
17
|
+
ok: true;
|
|
18
|
+
frontmatter: MemoryFrontmatter;
|
|
19
|
+
sections: MemorySection[];
|
|
20
|
+
} | {
|
|
21
|
+
ok: true;
|
|
22
|
+
skip: 'empty' | 'index' | 'veto-authored';
|
|
23
|
+
} | {
|
|
24
|
+
ok: false;
|
|
25
|
+
reason: string;
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lessons/adapters/types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,wCAAyC,CAAC;AACrE,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,iBAAiB,GACzB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,WAAW,EAAE,iBAAiB,CAAC;IAAC,QAAQ,EAAE,aAAa,EAAE,CAAA;CAAE,GAGvE;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,eAAe,CAAA;CAAE,GAEvD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/lessons/adapters/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAU,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { LessonSource, MemoryFrontmatter, MemorySection } from './adapters/index.js';
|
|
2
|
+
export type LessonScope = 'project' | 'user' | 'machine';
|
|
3
|
+
export type LessonClassification = {
|
|
4
|
+
scope: LessonScope;
|
|
5
|
+
kind: string;
|
|
6
|
+
/** Non-null keeps the note inside its own project, whatever its scope. */
|
|
7
|
+
quarantineReason: string | null;
|
|
8
|
+
};
|
|
9
|
+
export declare function isSensitiveNote(fileName: string, frontmatter: MemoryFrontmatter, sectionTitle: string): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Scope rules. User and machine scope can come ONLY from the sources below,
|
|
12
|
+
* and even then a note that names its own project is about that project:
|
|
13
|
+
* - a host's GLOBAL file (~/.codex/AGENTS.md, ~/.gemini/GEMINI.md) is the
|
|
14
|
+
* user's own standing instructions → user;
|
|
15
|
+
* - a Claude entry typed `user` or `feedback` → user;
|
|
16
|
+
* - a section whose heading names the environment → machine;
|
|
17
|
+
* - everything else, including anything untyped → project.
|
|
18
|
+
*/
|
|
19
|
+
export declare function classifyLesson(input: {
|
|
20
|
+
source: LessonSource;
|
|
21
|
+
fileName: string;
|
|
22
|
+
global: boolean;
|
|
23
|
+
frontmatter: MemoryFrontmatter;
|
|
24
|
+
section: MemorySection;
|
|
25
|
+
maskedText: string;
|
|
26
|
+
secrets: number;
|
|
27
|
+
/** The note's own project's names (folder, repository); empty for global files. */
|
|
28
|
+
projectNames?: string[];
|
|
29
|
+
}): LessonClassification;
|
|
30
|
+
//# sourceMappingURL=classify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/lessons/classify.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE1F,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;AAEzD,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,WAAW,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC,CAAC;AA6DF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAE/G;AASD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE;IACpC,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,iBAAiB,CAAC;IAC/B,OAAO,EAAE,aAAa,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,mFAAmF;IACnF,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB,GAAG,oBAAoB,CAUvB"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// Deterministic classification of a harvested section (council 320c40dc).
|
|
2
|
+
//
|
|
3
|
+
// Scope decides WHERE a note may go; quarantine decides whether it may leave
|
|
4
|
+
// its own project at all. Both are rules, not judgement: "ambiguous" always
|
|
5
|
+
// resolves to the narrower answer, because a wrong narrow call costs a missed
|
|
6
|
+
// note while a wrong wide call spreads text into other projects and vendors.
|
|
7
|
+
// Notes ABOUT secrets, identity, sanitization or credentials never cross scope.
|
|
8
|
+
// Matched on what names the note (file name, entry name and description,
|
|
9
|
+
// section heading), not on every passing mention in its body.
|
|
10
|
+
const SENSITIVE_NAME_RE = /(secret|credential|passw(or)?d|api[-_ ]?key|private[-_ ]?key|ssh[-_ ]?key|access[-_ ]?token|auth[-_ ]?token|api[-_ ]?token|identit(y|ies)|saniti[sz]|\bpii\b|personal|profile|employer)/i;
|
|
11
|
+
// A section whose heading names the shell, console or network environment is a
|
|
12
|
+
// machine lesson (cp1252, Git Bash quoting, dead IPv6). Heading only: a body
|
|
13
|
+
// that merely mentions PowerShell is still a project note.
|
|
14
|
+
const ENVIRONMENT_TITLE_RE = /\b(git[ -]bash|powershell|pwsh|cmd\.exe|wsl|cp\d{3,4}|code ?page|encoding|utf-?8|crlf|line endings?|ipv[46]|dns|proxy|locale|terminal|console|shell)\b/i;
|
|
15
|
+
const URL_RE = /\b(?:https?|ftp|file|ssh|git|wss?):\/\/|\bwww\.[a-z0-9-]+\.[a-z]{2,}/i;
|
|
16
|
+
const EXECUTABLES = [
|
|
17
|
+
'npm', 'npx', 'pnpm', 'yarn', 'bun', 'node', 'deno', 'python3?', 'py', 'pip3?', 'uv', 'uvx', 'git', 'gh',
|
|
18
|
+
'curl', 'wget', 'ssh', 'scp', 'rsync', 'nc', 'ncat', 'telnet', 'ftp', 'docker', 'kubectl', 'helm',
|
|
19
|
+
'terraform', 'aws', 'gcloud', 'az', 'powershell(?:\\.exe)?', 'pwsh', 'cmd(?:\\.exe)?', 'bash', 'sh', 'zsh',
|
|
20
|
+
'sudo', 'chmod', 'chown', 'rm', 'del', 'rmdir', 'mv', 'cp', 'iwr', 'irm', 'iex', 'invoke-webrequest',
|
|
21
|
+
'invoke-restmethod', 'invoke-expression', 'start-process', 'remove-item', 'set-executionpolicy', 'reg',
|
|
22
|
+
'schtasks', 'certutil', 'bitsadmin', 'mshta', 'rundll32', 'regsvr32', 'msiexec', 'winget', 'choco', 'scoop',
|
|
23
|
+
'brew', 'apt(?:-get)?', 'yum', 'dnf', 'cargo', 'make', 'mcp-publisher', 'smithery', 'veto',
|
|
24
|
+
].join('|');
|
|
25
|
+
const EXEC = `(?:${EXECUTABLES})(?:\\.(?:cmd|exe|bat|ps1))?`;
|
|
26
|
+
// Prose lines are NOT scanned for a leading executable ("Make sure…", "Node
|
|
27
|
+
// 22.13 is the floor"); commands are recognised where commands are written:
|
|
28
|
+
// behind a prompt, inside a code span, inside a fence, or after "run".
|
|
29
|
+
const PROMPT_LINE_RE = /(?:^|\n)[ \t]*(?:\$|PS>|PS [^>\n]*>)[ \t]*\S/;
|
|
30
|
+
const COMMAND_SPAN_RE = new RegExp('`[ \\t]*(?:\\$[ \\t]*)?' + EXEC + '(?:[ \\t][^`]*)?`', 'i');
|
|
31
|
+
const FENCED_LINE_RE = new RegExp(`^[ \\t]*(?:\\$[ \\t]*)?${EXEC}(?:[ \\t]|$)`, 'i');
|
|
32
|
+
const SHELL_FENCE_RE = /(?:^|\n)[ \t]*(?:```|~~~)[ \t]*(?:bash|sh|zsh|shell|console|terminal|powershell|pwsh|ps1?|cmd|bat|batch)\b/i;
|
|
33
|
+
const PIPE_TO_SHELL_RE = /\|\s*(?:sh|bash|zsh|iex|invoke-expression|powershell|pwsh)\b/i;
|
|
34
|
+
const RUN_DIRECTIVE_RE = new RegExp(`\\b(?:run|execute|exec|type|paste|invoke)\\s+[\`'"]?${EXEC}\\b`, 'i');
|
|
35
|
+
const DIRECTIVE_RES = [
|
|
36
|
+
/\b(?:ignore|disregard|override|forget)\b[^.\n]{0,30}\b(?:previous|prior|above|system|all|earlier)\b[^.\n]{0,20}\b(?:instructions?|rules?|prompts?|guidelines?)\b/i,
|
|
37
|
+
/\b(?:always|must|should)\s+(?:run|execute)\s+(?:this|these|it|them|the following)\b/i,
|
|
38
|
+
/\b(?:always|must|should)\s+(?:download|fetch|install|open|visit|send|upload)\b/i,
|
|
39
|
+
/\b(?:download|fetch)\b[^.\n]{0,60}\b(?:from|url|link|script)\b/i,
|
|
40
|
+
/\b(?:send|post|upload|exfiltrate|forward)\b[^.\n]{0,60}\bto\b[^.\n]{0,40}(?:\[email redacted\]|server|endpoint|webhook|url|address)/i,
|
|
41
|
+
];
|
|
42
|
+
function fencedCommand(text) {
|
|
43
|
+
let inFence = false;
|
|
44
|
+
for (const line of text.split('\n')) {
|
|
45
|
+
if (/^\s*(```|~~~)/.test(line)) {
|
|
46
|
+
inFence = !inFence;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (inFence && FENCED_LINE_RE.test(line))
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
function quarantineReason(text, secrets, sensitive) {
|
|
55
|
+
if (sensitive)
|
|
56
|
+
return 'sensitive';
|
|
57
|
+
if (secrets > 0 || /REDACTED\[sha256:/.test(text))
|
|
58
|
+
return 'credential';
|
|
59
|
+
if (URL_RE.test(text))
|
|
60
|
+
return 'url';
|
|
61
|
+
if (SHELL_FENCE_RE.test(text) || PROMPT_LINE_RE.test(text) || COMMAND_SPAN_RE.test(text) || fencedCommand(text)
|
|
62
|
+
|| PIPE_TO_SHELL_RE.test(text) || RUN_DIRECTIVE_RE.test(text))
|
|
63
|
+
return 'command';
|
|
64
|
+
if (DIRECTIVE_RES.some(re => re.test(text)))
|
|
65
|
+
return 'directive';
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
export function isSensitiveNote(fileName, frontmatter, sectionTitle) {
|
|
69
|
+
return [fileName, frontmatter.name, frontmatter.description, sectionTitle].some(label => SENSITIVE_NAME_RE.test(label ?? ''));
|
|
70
|
+
}
|
|
71
|
+
function namesProject(text, names) {
|
|
72
|
+
return names.some(name => {
|
|
73
|
+
const pattern = name.trim().split(/[\s_-]+/).map(part => part.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('[\\s_-]+');
|
|
74
|
+
return pattern && new RegExp(`(?<![\\p{L}\\p{N}])${pattern}(?![\\p{L}\\p{N}])`, 'iu').test(text);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Scope rules. User and machine scope can come ONLY from the sources below,
|
|
79
|
+
* and even then a note that names its own project is about that project:
|
|
80
|
+
* - a host's GLOBAL file (~/.codex/AGENTS.md, ~/.gemini/GEMINI.md) is the
|
|
81
|
+
* user's own standing instructions → user;
|
|
82
|
+
* - a Claude entry typed `user` or `feedback` → user;
|
|
83
|
+
* - a section whose heading names the environment → machine;
|
|
84
|
+
* - everything else, including anything untyped → project.
|
|
85
|
+
*/
|
|
86
|
+
export function classifyLesson(input) {
|
|
87
|
+
const type = input.frontmatter.type;
|
|
88
|
+
const kind = type ?? (input.global ? 'instructions' : 'note');
|
|
89
|
+
let scope = 'project';
|
|
90
|
+
if (input.global)
|
|
91
|
+
scope = 'user';
|
|
92
|
+
else if (namesProject(input.maskedText, input.projectNames ?? []))
|
|
93
|
+
scope = 'project';
|
|
94
|
+
else if (type === 'user' || type === 'feedback')
|
|
95
|
+
scope = 'user';
|
|
96
|
+
else if (ENVIRONMENT_TITLE_RE.test(input.section.title))
|
|
97
|
+
scope = 'machine';
|
|
98
|
+
const sensitive = isSensitiveNote(input.fileName, input.frontmatter, input.section.title);
|
|
99
|
+
return { scope, kind, quarantineReason: quarantineReason(input.maskedText, input.secrets, sensitive) };
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=classify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.js","sourceRoot":"","sources":["../../src/lessons/classify.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,EAAE;AACF,6EAA6E;AAC7E,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAa7E,gFAAgF;AAChF,yEAAyE;AACzE,8DAA8D;AAC9D,MAAM,iBAAiB,GAAG,0LAA0L,CAAC;AAErN,+EAA+E;AAC/E,6EAA6E;AAC7E,2DAA2D;AAC3D,MAAM,oBAAoB,GAAG,yJAAyJ,CAAC;AAEvL,MAAM,MAAM,GAAG,uEAAuE,CAAC;AAEvF,MAAM,WAAW,GAAG;IAClB,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI;IACxG,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM;IACjG,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,uBAAuB,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK;IAC1G,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,mBAAmB;IACpG,mBAAmB,EAAE,mBAAmB,EAAE,eAAe,EAAE,aAAa,EAAE,qBAAqB,EAAE,KAAK;IACtG,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO;IAC3G,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM;CAC3F,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACZ,MAAM,IAAI,GAAG,MAAM,WAAW,8BAA8B,CAAC;AAC7D,4EAA4E;AAC5E,4EAA4E;AAC5E,uEAAuE;AACvE,MAAM,cAAc,GAAG,8CAA8C,CAAC;AACtE,MAAM,eAAe,GAAG,IAAI,MAAM,CAAC,yBAAyB,GAAG,IAAI,GAAG,mBAAmB,EAAE,GAAG,CAAC,CAAC;AAChG,MAAM,cAAc,GAAG,IAAI,MAAM,CAAC,0BAA0B,IAAI,cAAc,EAAE,GAAG,CAAC,CAAC;AACrF,MAAM,cAAc,GAAG,6GAA6G,CAAC;AACrI,MAAM,gBAAgB,GAAG,+DAA+D,CAAC;AACzF,MAAM,gBAAgB,GAAG,IAAI,MAAM,CAAC,uDAAuD,IAAI,KAAK,EAAE,GAAG,CAAC,CAAC;AAE3G,MAAM,aAAa,GAAa;IAC9B,mKAAmK;IACnK,sFAAsF;IACtF,iFAAiF;IACjF,iEAAiE;IACjE,sIAAsI;CACvI,CAAC;AAEF,SAAS,aAAa,CAAC,IAAY;IACjC,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAAC,OAAO,GAAG,CAAC,OAAO,CAAC;YAAC,SAAS;QAAC,CAAC;QACjE,IAAI,OAAO,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IACxD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY,EAAE,OAAe,EAAE,SAAkB;IACzE,IAAI,SAAS;QAAE,OAAO,WAAW,CAAC;IAClC,IAAI,OAAO,GAAG,CAAC,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,YAAY,CAAC;IACvE,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC;WAC1G,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAClF,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,WAAW,CAAC;IAChE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAgB,EAAE,WAA8B,EAAE,YAAoB;IACpG,OAAO,CAAC,QAAQ,EAAE,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;AAChI,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,KAAe;IACjD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACvH,OAAO,OAAO,IAAI,IAAI,MAAM,CAAC,sBAAsB,OAAO,oBAAoB,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnG,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,KAU9B;IACC,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC;IACpC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC9D,IAAI,KAAK,GAAgB,SAAS,CAAC;IACnC,IAAI,KAAK,CAAC,MAAM;QAAE,KAAK,GAAG,MAAM,CAAC;SAC5B,IAAI,YAAY,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC;QAAE,KAAK,GAAG,SAAS,CAAC;SAChF,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,UAAU;QAAE,KAAK,GAAG,MAAM,CAAC;SAC3D,IAAI,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,KAAK,GAAG,SAAS,CAAC;IAC3E,MAAM,SAAS,GAAG,eAAe,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1F,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,gBAAgB,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC;AACzG,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { LessonSource } from './adapters/index.js';
|
|
2
|
+
export type NativeMemorySource = {
|
|
3
|
+
source: LessonSource;
|
|
4
|
+
sourcePath: string;
|
|
5
|
+
fileName: string;
|
|
6
|
+
mtimeMs: number;
|
|
7
|
+
/** A host-wide file every session of that host loads, not tied to a project. */
|
|
8
|
+
global: boolean;
|
|
9
|
+
/** Claude only: the ~/.claude/projects/<slug> folder the entry lives in. */
|
|
10
|
+
claudeFolder?: string;
|
|
11
|
+
claudeSlug?: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Known native-memory locations only; discovery reads directory listings and
|
|
15
|
+
* file metadata and performs no writes. CODEX_HOME relocates ~/.codex, as it
|
|
16
|
+
* does for Codex itself.
|
|
17
|
+
*/
|
|
18
|
+
export declare function discoverNativeMemorySources(home?: string): NativeMemorySource[];
|
|
19
|
+
//# sourceMappingURL=discover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../../src/lessons/discover.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,MAAM,EAAE,OAAO,CAAC;IAChB,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AA8BF;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,SAAY,GAAG,kBAAkB,EAAE,CAUlF"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { existsSync, readdirSync, statSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { basename, join } from 'node:path';
|
|
4
|
+
function candidate(source, sourcePath, extra = {}) {
|
|
5
|
+
try {
|
|
6
|
+
const stat = statSync(sourcePath);
|
|
7
|
+
return stat.isFile() ? { source, sourcePath, fileName: basename(sourcePath), mtimeMs: stat.mtimeMs, global: false, ...extra } : null;
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function claudeMemoryFiles(claudeHome) {
|
|
14
|
+
const projects = join(claudeHome, 'projects');
|
|
15
|
+
if (!existsSync(projects))
|
|
16
|
+
return [];
|
|
17
|
+
const out = [];
|
|
18
|
+
let folders;
|
|
19
|
+
try {
|
|
20
|
+
folders = readdirSync(projects, { withFileTypes: true });
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return out;
|
|
24
|
+
}
|
|
25
|
+
for (const folder of folders) {
|
|
26
|
+
if (!folder.isDirectory())
|
|
27
|
+
continue;
|
|
28
|
+
const claudeFolder = join(projects, folder.name);
|
|
29
|
+
const memory = join(claudeFolder, 'memory');
|
|
30
|
+
let files;
|
|
31
|
+
try {
|
|
32
|
+
files = readdirSync(memory, { withFileTypes: true });
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
for (const file of files) {
|
|
38
|
+
if (!file.isFile() || !file.name.toLowerCase().endsWith('.md'))
|
|
39
|
+
continue;
|
|
40
|
+
const found = candidate('claude', join(memory, file.name), { claudeFolder, claudeSlug: folder.name });
|
|
41
|
+
if (found)
|
|
42
|
+
out.push(found);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Known native-memory locations only; discovery reads directory listings and
|
|
49
|
+
* file metadata and performs no writes. CODEX_HOME relocates ~/.codex, as it
|
|
50
|
+
* does for Codex itself.
|
|
51
|
+
*/
|
|
52
|
+
export function discoverNativeMemorySources(home = homedir()) {
|
|
53
|
+
const codexHome = home === homedir() && process.env.CODEX_HOME ? process.env.CODEX_HOME : join(home, '.codex');
|
|
54
|
+
const out = claudeMemoryFiles(join(home, '.claude'));
|
|
55
|
+
for (const path of [join(codexHome, 'AGENTS.md'), join(codexHome, 'AGENTS.override.md')]) {
|
|
56
|
+
const found = candidate('codex', path, { global: true });
|
|
57
|
+
if (found)
|
|
58
|
+
out.push(found);
|
|
59
|
+
}
|
|
60
|
+
const gemini = candidate('gemini', join(home, '.gemini', 'GEMINI.md'), { global: true });
|
|
61
|
+
if (gemini)
|
|
62
|
+
out.push(gemini);
|
|
63
|
+
return out.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=discover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/lessons/discover.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAe3C,SAAS,SAAS,CAAC,MAAoB,EAAE,UAAkB,EAAE,QAAqC,EAAE;IAClG,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACvI,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;AAC1B,CAAC;AAED,SAAS,iBAAiB,CAAC,UAAkB;IAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAC9C,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,CAAC;IACrC,MAAM,GAAG,GAAyB,EAAE,CAAC;IACrC,IAAI,OAAO,CAAC;IACZ,IAAI,CAAC;QAAC,OAAO,GAAG,WAAW,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,GAAG,CAAC;IAAC,CAAC;IACvF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE;YAAE,SAAS;QACpC,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QAC5C,IAAI,KAAK,CAAC;QACV,IAAI,CAAC;YAAC,KAAK,GAAG,WAAW,CAAC,MAAM,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,SAAS;QAAC,CAAC;QACjF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,SAAS;YACzE,MAAM,KAAK,GAAG,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YACtG,IAAI,KAAK;gBAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,2BAA2B,CAAC,IAAI,GAAG,OAAO,EAAE;IAC1D,MAAM,SAAS,GAAG,IAAI,KAAK,OAAO,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC/G,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;IACrD,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC;QACzF,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,IAAI,KAAK;YAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IACD,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACzF,IAAI,MAAM;QAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC7B,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type LessonSource } from './adapters/index.js';
|
|
2
|
+
export type HarvestOutcome = {
|
|
3
|
+
status: 'harvested';
|
|
4
|
+
inserted: number;
|
|
5
|
+
updated: number;
|
|
6
|
+
removed: number;
|
|
7
|
+
} | {
|
|
8
|
+
status: 'skipped';
|
|
9
|
+
reason: 'empty' | 'index' | 'veto-authored';
|
|
10
|
+
removed: number;
|
|
11
|
+
} | {
|
|
12
|
+
status: 'disabled' | 'unavailable';
|
|
13
|
+
reason: string;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Read and harvest a single host-native memory file. The source is only ever
|
|
17
|
+
* opened for reading. An unrecognised shape disables that host's harvester
|
|
18
|
+
* (the format-drift canary) and leaves its existing rows untouched; selection
|
|
19
|
+
* stops serving them while the host is disabled.
|
|
20
|
+
*/
|
|
21
|
+
export declare function harvestNativeMemory(input: {
|
|
22
|
+
source: LessonSource;
|
|
23
|
+
sourcePath: string;
|
|
24
|
+
projectIdentity: string;
|
|
25
|
+
projectLabel?: string | null;
|
|
26
|
+
/** The project's own names; a note naming its project stays project scope. */
|
|
27
|
+
projectNames?: string[];
|
|
28
|
+
global?: boolean;
|
|
29
|
+
}): HarvestOutcome;
|
|
30
|
+
export type LessonSyncReport = {
|
|
31
|
+
consent: boolean;
|
|
32
|
+
sources: number;
|
|
33
|
+
harvested: number;
|
|
34
|
+
skipped: number;
|
|
35
|
+
disabled: number;
|
|
36
|
+
unavailable: number;
|
|
37
|
+
inserted: number;
|
|
38
|
+
updated: number;
|
|
39
|
+
removed: number;
|
|
40
|
+
unresolvedProjects: number;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* One full pass: discover every known native-memory file, harvest it under its
|
|
44
|
+
* project's identity, and delete rows whose file has gone. Nothing is read
|
|
45
|
+
* until the user has accepted consent v2.
|
|
46
|
+
*/
|
|
47
|
+
export declare function syncLessonSources(home?: string): LessonSyncReport;
|
|
48
|
+
//# sourceMappingURL=harvest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harvest.d.ts","sourceRoot":"","sources":["../../src/lessons/harvest.ts"],"names":[],"mappings":"AAGA,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAQ3E,MAAM,MAAM,cAAc,GACtB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC3E;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,OAAO,GAAG,OAAO,GAAG,eAAe,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACnF;IAAE,MAAM,EAAE,UAAU,GAAG,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,GAAG,cAAc,CA6BjB;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAgBF;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAsBjE"}
|