@vpxa/aikit 0.1.209 → 0.1.210

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.
Files changed (53) hide show
  1. package/package.json +1 -1
  2. package/packages/cli/dist/index.js +13 -13
  3. package/packages/core/dist/index.d.ts +2 -0
  4. package/packages/server/dist/auth-Bz5dmZgR.js +1 -0
  5. package/packages/server/dist/bin.js +12 -6
  6. package/packages/server/dist/config-C4mVyqAF.js +2 -0
  7. package/packages/server/dist/config-jGZ91cRx.js +1 -0
  8. package/packages/server/dist/curated-manager-D1u5qOwK.js +7 -0
  9. package/packages/server/dist/evolution-9hXRopDC.js +3 -0
  10. package/packages/server/dist/evolution-DJhTM6nu.js +2 -0
  11. package/packages/server/dist/index.d.ts +28 -1
  12. package/packages/server/dist/index.js +1 -1
  13. package/packages/server/dist/lessons-B05P_TOl.js +3 -0
  14. package/packages/server/dist/lessons-D7sdHa2e.js +2 -0
  15. package/packages/server/dist/promotion-Bd_YB7E1.js +3 -0
  16. package/packages/server/dist/promotion-OY53YCsT.js +2 -0
  17. package/packages/server/dist/proxy.js +1 -1
  18. package/packages/server/dist/replay-interceptor-CGLyom5f.js +7 -0
  19. package/packages/server/dist/retention-B4ITAs7F.js +1 -0
  20. package/packages/server/dist/retention-C3tsarCT.js +2 -0
  21. package/packages/server/dist/rolldown-runtime-DT7IzrpZ.js +1 -0
  22. package/packages/server/dist/{server-BaMsrcyc.js → server-BA1mIjBc.js} +163 -139
  23. package/packages/server/dist/{server-BhQwVWsr.js → server-CtFr8YsZ.js} +162 -140
  24. package/packages/server/dist/supersession-9edUDEQ8.js +1 -0
  25. package/packages/server/dist/{version-check-BgHzxxCW.js → version-check-D_uN0n0Y.js} +1 -1
  26. package/packages/store/dist/index.js +30 -30
  27. package/packages/tools/dist/index.d.ts +9 -1
  28. package/packages/tools/dist/index.js +78 -79
  29. package/packages/tools/package.json +5 -5
  30. package/scaffold/dist/adapters/claude-code.mjs +10 -10
  31. package/scaffold/dist/adapters/copilot.mjs +17 -17
  32. package/scaffold/dist/adapters/hooks.mjs +1 -0
  33. package/scaffold/dist/definitions/bodies.mjs +20 -114
  34. package/scaffold/dist/definitions/exec-hooks.mjs +1 -0
  35. package/scaffold/dist/definitions/flows.mjs +81 -345
  36. package/scaffold/dist/definitions/protocols.mjs +21 -4
  37. package/scaffold/dist/definitions/skills/aikit.mjs +35 -55
  38. package/scaffold/dist/definitions/skills/lesson-learned.mjs +46 -0
  39. package/scaffold/general/hooks/scripts/_runtime.mjs +161 -0
  40. package/scaffold/general/hooks/scripts/post-edit-check.mjs +36 -0
  41. package/scaffold/general/hooks/scripts/pre-compact-save.mjs +13 -0
  42. package/scaffold/general/hooks/scripts/privacy-guard.mjs +39 -0
  43. package/scaffold/general/hooks/scripts/scout-guard.mjs +45 -0
  44. package/scaffold/general/hooks/scripts/session-init.mjs +85 -0
  45. package/scaffold/general/hooks/scripts/session-learn.mjs +53 -0
  46. package/scaffold/general/hooks/scripts/session-observer.mjs +77 -0
  47. package/scaffold/general/hooks/scripts/subagent-context.mjs +59 -0
  48. package/packages/server/dist/auth-BfqgawfR.js +0 -1
  49. package/packages/server/dist/config-DAnAxrUW.js +0 -1
  50. package/packages/server/dist/config-PfoXsIC3.js +0 -2
  51. package/packages/server/dist/curated-manager-BnP6VqvL.js +0 -7
  52. package/packages/server/dist/supersession-BIV-v6JG.js +0 -3
  53. package/packages/server/dist/supersession-DJQGXMWm.js +0 -2
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * session-observer — PostToolUse hook for autonomous learning.
4
+ *
5
+ * Captures tool usage observations to a JSONL buffer for later pattern analysis.
6
+ * Fire-and-forget writes (<5ms). Nudges agent when batch threshold reached.
7
+ *
8
+ * @tier efficiency
9
+ * @event PostToolUse
10
+ * @scope user
11
+ */
12
+ import fs from 'node:fs';
13
+ import os from 'node:os';
14
+ import path from 'node:path';
15
+ import process from 'node:process';
16
+ import { createHook } from './_runtime.mjs';
17
+
18
+ const bufferPath = path.join(os.tmpdir(), `aikit-obs-${process.ppid}.jsonl`);
19
+ const BATCH_THRESHOLD = 20;
20
+ const EXCLUDE = new Set([
21
+ 'knowledge',
22
+ 'replay',
23
+ 'stash',
24
+ 'checkpoint',
25
+ 'session_digest',
26
+ 'reindex',
27
+ 'status',
28
+ 'flow',
29
+ 'evidence_map',
30
+ 'present',
31
+ ]);
32
+
33
+ const countLines = (filePath) => {
34
+ try {
35
+ return fs.readFileSync(filePath, 'utf8').split('\n').filter(Boolean).length;
36
+ } catch {
37
+ return 0;
38
+ }
39
+ };
40
+
41
+ const summarize = (input, maxLen = 200) => {
42
+ if (!input) return '';
43
+ const value = typeof input === 'string' ? input : JSON.stringify(input);
44
+ return value.length > maxLen ? `${value.slice(0, maxLen)}...` : value;
45
+ };
46
+
47
+ /** Captures tool-use observations and nudges lesson extraction at batch thresholds. */
48
+ export const sessionObserver = async (context) => {
49
+ if (context.event !== 'PostToolUse') return { decision: 'allow' };
50
+ const toolBase = context.toolName.replace(/^mcp_aikit_/, '');
51
+ if (EXCLUDE.has(toolBase)) return { decision: 'allow' };
52
+
53
+ const entry = JSON.stringify({
54
+ ts: Date.now(),
55
+ tool: context.toolName,
56
+ input: summarize(context.toolInput),
57
+ files: context.filePaths.slice(0, 5),
58
+ });
59
+
60
+ try {
61
+ fs.appendFileSync(bufferPath, `${entry}\n`);
62
+ } catch {}
63
+
64
+ const count = countLines(bufferPath);
65
+ if (count > 0 && count >= BATCH_THRESHOLD && count % BATCH_THRESHOLD === 0) {
66
+ return {
67
+ additionalContext: [
68
+ `[Observer] ${count} tool calls captured this session.`,
69
+ 'Consider: knowledge({ action: "lesson", subAction: "auto-observe" })',
70
+ ].join(' '),
71
+ };
72
+ }
73
+
74
+ return { decision: 'allow' };
75
+ };
76
+
77
+ createHook(sessionObserver);
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { createHook } from './_runtime.mjs';
5
+
6
+ const readJson = (cwd, name) => {
7
+ try {
8
+ return JSON.parse(fs.readFileSync(path.join(cwd, name), 'utf8'));
9
+ } catch {
10
+ return null;
11
+ }
12
+ };
13
+ const truncate = (value, limit) =>
14
+ String(value ?? '')
15
+ .replace(/\s+/g, ' ')
16
+ .trim()
17
+ .slice(0, limit);
18
+ const detectStack = (manifest, pkg) => {
19
+ const explicit = manifest?.stack ?? manifest?.techStack ?? manifest?.project?.stack;
20
+ if (explicit) return Array.isArray(explicit) ? explicit.join(', ') : String(explicit);
21
+ const deps = { ...pkg?.dependencies, ...pkg?.devDependencies };
22
+ const found = [];
23
+ if (pkg) found.push('Node.js');
24
+ if (deps.react) found.push('React');
25
+ if (deps.vue) found.push('Vue');
26
+ if (deps.next) found.push('Next.js');
27
+ if (deps.express) found.push('Express');
28
+ if (deps.fastify) found.push('Fastify');
29
+ if (deps['@nestjs/core']) found.push('NestJS');
30
+ return found.join(', ');
31
+ };
32
+
33
+ /** Injects compact project metadata into every subagent start. */
34
+ export const subagentContext = async (context) => {
35
+ if (context.event !== 'SubagentStart') return { decision: 'allow' };
36
+ const manifest = readJson(context.cwd, '.aikit-scaffold.json');
37
+ const pkg = readJson(context.cwd, 'package.json');
38
+ if (!manifest && !pkg) return { decision: 'allow' };
39
+ const conventions =
40
+ manifest?.conventions ?? manifest?.keyConventions ?? manifest?.project?.conventions;
41
+ const conventionText = Array.isArray(conventions)
42
+ ? conventions.slice(0, 3).join('; ')
43
+ : conventions;
44
+ const name = truncate(pkg?.name ?? manifest?.name ?? path.basename(context.cwd), 60);
45
+ const description = truncate(
46
+ pkg?.description ?? manifest?.description ?? manifest?.project?.description,
47
+ 120,
48
+ );
49
+ const stack = truncate(detectStack(manifest, pkg) || 'unknown', 80);
50
+ const contextText = [
51
+ `Project: ${name}${description ? ` — ${description}` : ''}`,
52
+ `Stack: ${stack}`,
53
+ `Conventions: ${truncate(conventionText || 'Reuse existing scaffold patterns.', 120)}`,
54
+ 'Use aikit search/file_summary/compact — NOT raw read_file for understanding code.',
55
+ ].join('\n');
56
+ return { additionalContext: contextText };
57
+ };
58
+
59
+ createHook(subagentContext);
@@ -1 +0,0 @@
1
- import"node:module";import{randomBytes as e,timingSafeEqual as t}from"node:crypto";import*as n from"node:fs";import{join as r}from"node:path";import{homedir as i}from"node:os";var a=Object.defineProperty,o=((e,t)=>{let n={};for(var r in e)a(n,r,{get:e[r],enumerable:!0});return t||a(n,Symbol.toStringTag,{value:`Module`}),n})({authMiddleware:()=>d,getOrCreateToken:()=>u,readToken:()=>f});const s=r(i(),`.aikit`);function c(e){let t=e?.tokenDir??s;return{tokenDir:t,tokenFile:r(t,`token`)}}function l(e,n){let r=Buffer.from(e),i=Buffer.from(n);return r.length===i.length?t(r,i):!1}function u(t){let{tokenDir:r,tokenFile:i}=c(t);if(n.existsSync(i)){let e=n.readFileSync(i,`utf-8`).trim();if(e.length>0)return e}n.existsSync(r)||n.mkdirSync(r,{recursive:!0,mode:448});let a=e(32).toString(`hex`);return n.writeFileSync(i,a,{mode:384}),a}function d(e){return(t,n,r)=>{if(t.path===`/health`||t.path===`/healthz`){r();return}let i=t.headers.authorization;if(!i?.startsWith(`Bearer `)){n.status(401).json({error:`Unauthorized: Bearer token required`});return}if(!l(i.slice(7).trim(),e)){n.status(401).json({error:`Unauthorized: Invalid token`});return}r()}}function f(e){try{let{tokenFile:t}=c(e);return n.readFileSync(t,`utf-8`).trim()}catch{return}}export{f as n,o as t};
@@ -1 +0,0 @@
1
- import{_ as e,a as t,l as n,t as r}from"./supersession-DJQGXMWm.js";import{existsSync as i,readFileSync as a}from"node:fs";import{dirname as o,resolve as s}from"node:path";import{fileURLToPath as c}from"node:url";import{AIKIT_PATHS as l,EMBEDDING_DEFAULTS as u,createLogger as d,getPartitionDir as f,isUserInstalled as p,registerWorkspace as m,serializeError as h}from"../../core/dist/index.js";const g=o(c(import.meta.url)),_=d(`server`),v=[`auto`,`manual`,`smart`],y={model:u.model,dimensions:u.dimensions,childProcess:!0,idleTimeoutMs:6e4};function b(e){return typeof e==`string`&&v.includes(e)}function x(e,t,n){let r=s(e),i=s(t);if(!r.startsWith(i))throw Error(`Config ${n} path escapes workspace root: ${e} is not under ${t}`);return r}function S(e){let t=process.env.AIKIT_INDEX_MODE;if(b(t))return t;if(e.indexMode)return e.indexMode;let n=process.env.AIKIT_AUTO_INDEX;return n===void 0?e.autoIndex===void 0?`smart`:e.autoIndex?`auto`:`manual`:n===`true`?`auto`:`manual`}function C(){let c=process.env.AIKIT_CONFIG_PATH??(i(s(process.cwd(),`aikit.config.json`))?s(process.cwd(),`aikit.config.json`):s(g,`..`,`..`,`..`,`aikit.config.json`));try{if(!i(c))return _.info(`No config file found, using defaults`,{configPath:c}),w();let u=a(c,`utf-8`),d=JSON.parse(u);if(d.embedding={...y,...d.embedding},d.memory={retention:{...t,...d.memory?.retention},lessons:{...n,...d.memory?.lessons},consolidation:{...e,...d.memory?.consolidation},supersession:{...r,...d.memory?.supersession}},!d.sources||!Array.isArray(d.sources)||d.sources.length===0)throw Error(`Config must have at least one source`);if(!d.store?.path)throw Error(`Config must specify store.path`);if(d.autoIndex!==void 0&&typeof d.autoIndex!=`boolean`)throw Error(`Config autoIndex must be a boolean`);if(d.indexMode!==void 0&&!b(d.indexMode))throw Error(`Config indexMode must be one of: ${v.join(`, `)}`);let f=o(c);return d.sources=d.sources.map(e=>({...e,path:x(s(f,e.path),f,`source`)})),d.store.path=x(s(f,d.store.path),f,`store`),d.curated=d.curated??{path:l.aiCurated},d.curated.path=x(s(f,d.curated.path),f,`curated`),T(d,f),d.indexMode=S(d),d}catch(e){return _.error(`Failed to load config`,{configPath:c,...h(e)}),_.warn(`Falling back to default configuration`,{configPath:c}),w()}}function w(){let i=process.env.AIKIT_WORKSPACE_ROOT??process.cwd(),a={sources:[{path:i,excludePatterns:[`node_modules/**`,`dist/**`,`.git/**`,`coverage/**`,`*.lock`,`pnpm-lock.yaml`]}],serverName:`aikit`,indexing:{chunkSize:1500,chunkOverlap:200,minChunkSize:100},embedding:{...y},store:{backend:`sqlite-vec`,path:s(i,l.data)},curated:{path:s(i,l.aiCurated)},memory:{retention:{...t},lessons:{...n},consolidation:{...e},supersession:{...r}},onboardDir:s(i,l.aiContext),stateDir:s(i,l.state)};return T(a,i),a.indexMode=S(a),a}function T(e,t){if(!p())return;let n=m(t);e.store.path=s(f(n.partition)),e.onboardDir=s(f(n.partition),`onboard`),e.stateDir=s(f(n.partition),`state`),e.curated={path:s(f(n.partition),`curated`)}}function E(e,t){if(!i(t))throw Error(`Workspace root does not exist: ${t}`);_.info(`Reconfiguring for workspace root`,{workspaceRoot:t});try{process.chdir(t),_.info(`Changed process cwd to workspace root`,{cwd:process.cwd()})}catch(e){_.warn(`Failed to chdir to workspace root`,{workspaceRoot:t,...h(e)})}e.sources=[{path:t,excludePatterns:e.sources[0]?.excludePatterns??[`node_modules/**`,`dist/**`,`.git/**`,`coverage/**`,`*.lock`,`pnpm-lock.yaml`]}],e.store.path=s(t,l.data),e.curated={path:s(t,l.aiCurated)},e.onboardDir=s(t,l.aiContext),e.stateDir=s(t,l.state),T(e,t)}export{C as loadConfig,E as reconfigureForWorkspace,S as resolveIndexMode};
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- import{_ as e,a as t,l as n,t as r}from"./supersession-BIV-v6JG.js";import{existsSync as i,readFileSync as a}from"node:fs";import{dirname as o,resolve as s}from"node:path";import{fileURLToPath as c}from"node:url";import{AIKIT_PATHS as l,EMBEDDING_DEFAULTS as u,createLogger as d,getPartitionDir as f,isUserInstalled as p,registerWorkspace as m,serializeError as h}from"../../core/dist/index.js";const g=o(c(import.meta.url)),_=d(`server`),v=[`auto`,`manual`,`smart`],y={model:u.model,dimensions:u.dimensions,childProcess:!0,idleTimeoutMs:6e4};function b(e){return typeof e==`string`&&v.includes(e)}function x(e,t,n){let r=s(e),i=s(t);if(!r.startsWith(i))throw Error(`Config ${n} path escapes workspace root: ${e} is not under ${t}`);return r}function S(e){let t=process.env.AIKIT_INDEX_MODE;if(b(t))return t;if(e.indexMode)return e.indexMode;let n=process.env.AIKIT_AUTO_INDEX;return n===void 0?e.autoIndex===void 0?`smart`:e.autoIndex?`auto`:`manual`:n===`true`?`auto`:`manual`}function C(){let c=process.env.AIKIT_CONFIG_PATH??(i(s(process.cwd(),`aikit.config.json`))?s(process.cwd(),`aikit.config.json`):s(g,`..`,`..`,`..`,`aikit.config.json`));try{if(!i(c))return _.info(`No config file found, using defaults`,{configPath:c}),w();let u=a(c,`utf-8`),d=JSON.parse(u);if(d.embedding={...y,...d.embedding},d.memory={retention:{...t,...d.memory?.retention},lessons:{...n,...d.memory?.lessons},consolidation:{...e,...d.memory?.consolidation},supersession:{...r,...d.memory?.supersession}},!d.sources||!Array.isArray(d.sources)||d.sources.length===0)throw Error(`Config must have at least one source`);if(!d.store?.path)throw Error(`Config must specify store.path`);if(d.autoIndex!==void 0&&typeof d.autoIndex!=`boolean`)throw Error(`Config autoIndex must be a boolean`);if(d.indexMode!==void 0&&!b(d.indexMode))throw Error(`Config indexMode must be one of: ${v.join(`, `)}`);let f=o(c);return d.sources=d.sources.map(e=>({...e,path:x(s(f,e.path),f,`source`)})),d.store.path=x(s(f,d.store.path),f,`store`),d.curated=d.curated??{path:l.aiCurated},d.curated.path=x(s(f,d.curated.path),f,`curated`),T(d,f),d.indexMode=S(d),d}catch(e){return _.error(`Failed to load config`,{configPath:c,...h(e)}),_.warn(`Falling back to default configuration`,{configPath:c}),w()}}function w(){let i=process.env.AIKIT_WORKSPACE_ROOT??process.cwd(),a={sources:[{path:i,excludePatterns:[`node_modules/**`,`dist/**`,`.git/**`,`coverage/**`,`*.lock`,`pnpm-lock.yaml`]}],serverName:`aikit`,indexing:{chunkSize:1500,chunkOverlap:200,minChunkSize:100},embedding:{...y},store:{backend:`sqlite-vec`,path:s(i,l.data)},curated:{path:s(i,l.aiCurated)},memory:{retention:{...t},lessons:{...n},consolidation:{...e},supersession:{...r}},onboardDir:s(i,l.aiContext),stateDir:s(i,l.state)};return T(a,i),a.indexMode=S(a),a}function T(e,t){if(!p())return;let n=m(t);e.store.path=s(f(n.partition)),e.onboardDir=s(f(n.partition),`onboard`),e.stateDir=s(f(n.partition),`state`),e.curated={path:s(f(n.partition),`curated`)}}function E(e,t){if(!i(t))throw Error(`Workspace root does not exist: ${t}`);_.info(`Reconfiguring for workspace root`,{workspaceRoot:t});try{process.chdir(t),_.info(`Changed process cwd to workspace root`,{cwd:process.cwd()})}catch(e){_.warn(`Failed to chdir to workspace root`,{workspaceRoot:t,...h(e)})}e.sources=[{path:t,excludePatterns:e.sources[0]?.excludePatterns??[`node_modules/**`,`dist/**`,`.git/**`,`coverage/**`,`*.lock`,`pnpm-lock.yaml`]}],e.store.path=s(t,l.data),e.curated={path:s(t,l.aiCurated)},e.onboardDir=s(t,l.aiContext),e.stateDir=s(t,l.state),T(e,t)}export{C as loadConfig,E as reconfigureForWorkspace,S as resolveIndexMode};
@@ -1,7 +0,0 @@
1
- import{createHash as e}from"node:crypto";import{dirname as t,isAbsolute as n,join as r}from"node:path";import{createLogger as i,serializeError as a}from"../../core/dist/index.js";import{GIT_REF_SLUG_PATTERN as o,gitAvailable as s,gitCommitToRef as c,gitExec as l,slugForRef as u}from"../../tools/dist/index.js";import{mkdir as d,readFile as f,readdir as p,stat as m,unlink as h,writeFile as g}from"node:fs/promises";var _=class{baseDir;constructor(e){this.baseDir=e}async initialize(){await d(this.baseDir,{recursive:!0})}async read(e){let t=r(this.baseDir,e);try{return await f(t,`utf-8`)}catch(e){if(e.code===`ENOENT`)return null;throw e}}async write(e,n,i){let a=r(this.baseDir,e);await d(t(a),{recursive:!0}),await g(a,n,{encoding:`utf-8`,flag:i?.exclusive?`wx`:`w`})}async delete(e){let t=r(this.baseDir,e);try{return await h(t),!0}catch(e){if(e.code===`ENOENT`)return!1;throw e}}async list(e){let t=[],n=e?[e]:await this.listDirectories();for(let e of n){let n=r(this.baseDir,e),i;try{i=await p(n)}catch{continue}for(let n of i){if(!n.endsWith(`.md`))continue;let i=`${e}/${n}`,a=r(this.baseDir,i);try{let e=await m(a);t.push({path:i,size:e.size})}catch{}}}return t}async exists(e){let t=r(this.baseDir,e);try{return await m(t),!0}catch{return!1}}async listDirectories(){try{return(await p(this.baseDir,{withFileTypes:!0})).filter(e=>e.isDirectory()&&/^[a-z][a-z0-9-]*$/.test(e.name)).map(e=>e.name)}catch{return[]}}async close(){}};const v=50*1024,y=`refs/aikit/knowledge`,b=i(`server`);var x=class{curatedDir;store;embedder;adapter;constructor(e,t,n,r=new _(e)){this.curatedDir=e,this.store=t,this.embedder=n,this.adapter=r}async remember(e,t,n,r=[]){this.validateCategoryName(n),this.validateContentSize(t);let i=this.slugify(e),a=await this.uniqueRelativePath(n,i),o=new Date().toISOString(),s={title:e,category:n,tags:r,created:o,updated:o,version:1,origin:`curated`,changelog:[{version:1,date:o,reason:`Initial creation`}]},c=this.serializeFile(t,s);try{await this.adapter.write(a,c,{exclusive:!0})}catch(e){throw e.code===`EEXIST`?Error(`Concurrent write collision for "${a}" — retry the operation`):e}try{await this.indexCuratedFile(a,t,s)}catch(e){throw await this.adapter.delete(a).catch(()=>{}),Error(`Remember failed: wrote file but indexing failed — rolled back. ${e.message}`)}return this.gitCommitKnowledge(a,c,`remember: ${e}\n\nCategory: ${n}\nTags: ${r.join(`, `)}`),{path:a}}async update(e,t,n){e=this.guardPath(e),this.validateContentSize(t);let r=await this.adapter.read(e);if(r==null)throw Error(`Curated entry not found: ${e}`);let{frontmatter:i}=this.parseFile(r),a=(i.version??1)+1,o=new Date().toISOString();i.version=a,i.updated=o,i.changelog=[...i.changelog??[],{version:a,date:o,reason:n}];let s=this.serializeFile(t,i);return await this.adapter.write(e,s),await this.indexCuratedFile(e,t,i),this.gitCommitKnowledge(e,s,`update(v${a}): ${i.title}\n\nReason: ${n}\nVersion: ${a}`),{path:e,version:a}}async forget(e,t){if(e=this.guardPath(e),!await this.adapter.delete(e))throw Error(`Curated entry not found: ${e}`);let n=`.ai/curated/${e}`;return await this.store.deleteBySourcePath(n).catch(e=>{b.warn(`File deleted but vector cleanup failed`,{sourcePath:n,...a(e)})}),this.gitDeleteKnowledgeRef(e),{path:e}}async history(e,t=20){if(e=this.guardPath(e),!s(this.curatedDir))return[];let n=this.knowledgeRefForPath(e);if(!n)return[];let r=l([`log`,`--format=%H|%aI|%s`,n,`-n`,String(t)],this.curatedDir);return r?r.split(`
2
- `).filter(Boolean).map(e=>{let[t,n,...r]=e.split(`|`);return{sha:t,date:n,message:r.join(`|`)}}):[]}async diff(e,t,n){if(e=this.guardPath(e),!s(this.curatedDir))return``;if(!n){let r=await this.history(e,2);if(r.length===0)return``;n=r[0].sha,r.length>1&&!t&&(t=r[1].sha)}return t&&n?l([`diff`,`${t}:entry.md`,`${n}:entry.md`],this.curatedDir)??``:n?l([`show`,`${n}:entry.md`],this.curatedDir)??``:``}async recover(e){if(e=this.guardPath(e),await this.adapter.exists(e))throw Error(`Entry already exists on filesystem: ${e}. Use update() instead.`);if(!s(this.curatedDir))return null;let t=this.knowledgeRefForPath(e);if(!t)return null;let n=l([`show`,`${t}:entry.md`],this.curatedDir);if(!n)return null;await this.adapter.write(e,n);let{frontmatter:r,content:i}=this.parseFile(n);return await this.indexCuratedFile(e,i,r),{path:e,version:r.version??1}}async listOrphaned(){if(!s(this.curatedDir))return[];let e=l([`for-each-ref`,`--format=%(refname)|%(subject)`,`${y}/`],this.curatedDir);if(!e)return[];let t=[];for(let n of e.split(`
3
- `).filter(Boolean)){let[e,...r]=n.split(`|`),i=r.join(`|`),a=`${e.replace(`${y}/`,``)}.md`;await this.adapter.exists(a)||t.push({ref:e,path:a,lastMessage:i})}return t}async read(e){e=this.guardPath(e);let t=await this.adapter.read(e);if(t==null)throw Error(`Curated entry not found: ${e}`);let{frontmatter:n,content:r}=this.parseFile(t),i=e.split(`/`)[0];return{path:e,title:n.title??e,category:i,tags:n.tags??[],version:n.version??1,created:n.created??``,updated:n.updated??``,contentPreview:r.slice(0,200),content:r}}async list(e){let t=[],n=e?.category?[e.category]:await this.discoverCategories();for(let r of n){let n=await this.adapter.list(r);for(let i of n){let n=await this.adapter.read(i.path);if(n==null)continue;let{frontmatter:a,content:o}=this.parseFile(n);e?.tag&&!(a.tags??[]).includes(e.tag)||t.push({path:i.path,title:a.title??i.path,category:r,tags:a.tags??[],version:a.version??1,created:a.created??``,updated:a.updated??``,contentPreview:o.slice(0,200)})}}return t}async reindexAll(){let e=await this.discoverCategories(),t=[],n=[];for(let r of e){let e=await this.adapter.list(r);for(let r of e){let e=r.path;try{let r=await this.adapter.read(e);if(r==null){t.push(`${e}: read failed`);continue}let{frontmatter:i,content:a}=this.parseFile(r);n.push({relativePath:e,content:a,frontmatter:i})}catch(n){b.error(`Failed to read curated file`,{relativePath:e,...a(n)}),t.push(`${e}: read failed`)}}}if(n.length===0)return{indexed:0,errors:t};let r=await this.embedder.embedBatch(n.map(e=>e.content)),i=new Date().toISOString(),o=n.map(e=>{let t=`.ai/curated/${e.relativePath}`;return{id:this.hashId(t,0),content:e.content,sourcePath:t,contentType:`curated-knowledge`,headingPath:e.frontmatter.title,chunkIndex:0,totalChunks:1,startLine:1,endLine:e.content.split(`
4
- `).length,fileHash:this.hash(e.content),indexedAt:i,origin:`curated`,tags:e.frontmatter.tags,category:e.frontmatter.category,version:e.frontmatter.version}});return await this.store.upsert(o,r),{indexed:n.length,errors:t}}gitCommitKnowledge(e,t,n){try{if(!s(this.curatedDir))return;let r=this.knowledgeRefForPath(e);if(!r)return;c(r,`entry.md`,t,n,this.curatedDir)}catch{}}gitDeleteKnowledgeRef(e){try{if(!s(this.curatedDir))return;let t=this.knowledgeRefForPath(e);if(!t)return;l([`update-ref`,`-d`,t],this.curatedDir)}catch{}}knowledgeRefForPath(e){let t=e.replace(/\.md$/,``).split(`/`).map(e=>u(e)).join(`/`);return t.split(`/`).every(e=>o.test(e))?`${y}/${t}`:null}async indexCuratedFile(e,t,n){let r=await this.embedder.embed(t),i=`.ai/curated/${e}`,a=new Date().toISOString(),o={id:this.hashId(i,0),content:t,sourcePath:i,contentType:`curated-knowledge`,headingPath:n.title,chunkIndex:0,totalChunks:1,startLine:1,endLine:t.split(`
5
- `).length,fileHash:this.hash(t),indexedAt:a,origin:`curated`,tags:n.tags,category:n.category,version:n.version};await this.store.upsert([o],[r])}async discoverCategories(){return this.adapter.listDirectories()}guardPath(e){let t=e.replace(/^\.ai\/curated\//,``);if(t.endsWith(`.md`)||(t+=`.md`),t.includes(`..`)||n(t))throw Error(`Invalid path: ${t}. Must be relative within .ai/curated/ directory.`);let r=t.split(`/`)[0];return this.validateCategoryName(r),t}validateCategoryName(e){if(!/^[a-z][a-z0-9-]*$/.test(e))throw Error(`Invalid category name: "${e}". Must be lowercase kebab-case (e.g., "decisions", "api-contracts").`)}validateContentSize(e){if(Buffer.byteLength(e,`utf-8`)>v)throw Error(`Content exceeds maximum size of ${v/1024}KB`)}slugify(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-|-$/g,``).slice(0,80)}async uniqueRelativePath(e,t){let n=`${e}/${t}.md`;if(!await this.adapter.exists(n))return n;for(let n=2;n<=100;n++){let r=`${e}/${t}-${n}.md`;if(!await this.adapter.exists(r))return r}throw Error(`Too many entries with slug "${t}" in category "${e}"`)}hash(t){return e(`sha256`).update(t).digest(`hex`).slice(0,16)}hashId(e,t){return this.hash(`${e}::${t}`)}serializeFile(e,t){return`${[`---`,`title: "${t.title.replace(/"/g,`\\"`)}"`,`category: ${t.category}`,`tags: [${t.tags.map(e=>`"${e}"`).join(`, `)}]`,`created: ${t.created}`,`updated: ${t.updated}`,`version: ${t.version}`,`origin: ${t.origin}`,`changelog:`,...t.changelog.map(e=>` - version: ${e.version}\n date: ${e.date}\n reason: "${e.reason.replace(/"/g,`\\"`)}"`),`---`].join(`
6
- `)}\n\n${e}\n`}parseFile(e){let t=e.match(/^---\n([\s\S]*?)\n---\n\n?([\s\S]*)$/);if(!t)return{frontmatter:{title:`Untitled`,category:`notes`,tags:[],created:``,updated:``,version:1,origin:`curated`,changelog:[]},content:e};let n=t[1],r=t[2].trim(),i={},a=[],o=n.split(`
7
- `),s=!1,c={};for(let e of o){if(/^changelog:\s*$/.test(e)){s=!0;continue}if(s){let t=e.match(/^\s+-\s+version:\s*(\d+)$/);if(t){c.version!=null&&a.push(c),c={version:parseInt(t[1],10)};continue}let n=e.match(/^\s+date:\s*(.+)$/);if(n){c.date=n[1].trim();continue}let r=e.match(/^\s+reason:\s*"?(.*?)"?\s*$/);if(r){c.reason=r[1];continue}/^\w/.test(e)&&(s=!1,c.version!=null&&a.push(c),c={});continue}let t=e.match(/^(\w+):\s*(.*)$/);if(t){let e=t[1],n=t[2];typeof n==`string`&&n.startsWith(`[`)&&n.endsWith(`]`)?n=n.slice(1,-1).split(`,`).map(e=>e.trim().replace(/^"|"$/g,``)).filter(e=>e.length>0):typeof n==`string`&&/^\d+$/.test(n)?n=parseInt(n,10):typeof n==`string`&&n.startsWith(`"`)&&n.endsWith(`"`)&&(n=n.slice(1,-1)),i[e]=n}}return c.version!=null&&a.push(c),{frontmatter:{title:i.title??`Untitled`,category:i.category??`notes`,tags:i.tags??[],created:i.created??``,updated:i.updated??``,version:i.version??1,origin:`curated`,changelog:a},content:r}}};export{_ as n,x as t};
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env node
2
- const e={workingToEpisodicAccesses:2,episodicToSemanticReferences:3,semanticToProceduralVerifications:5},t={working:1,episodic:2,semantic:4,procedural:12};function n(t,n=e){switch(t.tier){case`working`:if(t.accessCount>=n.workingToEpisodicAccesses)return`episodic`;break;case`episodic`:if(t.accessCount>=n.workingToEpisodicAccesses+n.episodicToSemanticReferences)return`semantic`;break;case`semantic`:if(t.accessCount>=n.workingToEpisodicAccesses+n.episodicToSemanticReferences+n.semanticToProceduralVerifications)return`procedural`;break;case`procedural`:break;default:break}}function r(e,t,n){e.memoryMetaUpdateTier(t,n)}const i={confirmIncrement:10,contradictDecrement:20,autoArchiveDays:30,archiveThreshold:20},a=`lesson:auto-archive`;function o(e){return{confirmIncrement:Math.max(0,Math.trunc(e?.confirmIncrement??i.confirmIncrement)),contradictDecrement:Math.max(0,Math.trunc(e?.contradictDecrement??i.contradictDecrement)),autoArchiveDays:Math.max(1,Math.trunc(e?.autoArchiveDays??i.autoArchiveDays)),archiveThreshold:Math.min(100,Math.max(0,Math.trunc(e?.archiveThreshold??i.archiveThreshold)))}}function s(e){return[`## Lesson: ${e.title}`,``,`**Confidence:** ${e.confidence}/100`,``,`### Context`,e.context,``,`### Insight`,e.insight,``,`### Evidence`,e.evidence].join(`
3
- `)}function c(e){let t=e.match(/^## Lesson:\s+(.+)$/m),n=e.match(/\*\*Confidence:\*\*\s+(\d+)\/100/),r=e.match(/### Context\r?\n([\s\S]*?)(?=\r?\n### |$)/),i=e.match(/### Insight\r?\n([\s\S]*?)(?=\r?\n### |$)/),a=e.match(/### Evidence\r?\n([\s\S]*?)(?=\r?\n### |$)/);return{title:t?.[1]?.trim(),confidence:n?Number(n[1]):void 0,context:r?.[1]?.trim(),insight:i?.[1]?.trim(),evidence:a?.[1]?.trim()}}function l(e,t){let n=Math.min(100,Math.max(0,Math.trunc(t)));return/\*\*Confidence:\*\*/.test(e)?e.replace(/\*\*Confidence:\*\*\s+\d+\/100/,`**Confidence:** ${n}/100`):e.match(/^(## Lesson:[^\r\n]*)(\r?\n)/)?e.replace(/^(## Lesson:[^\r\n]*)(\r?\n)/,`$1$2$2**Confidence:** ${n}/100$2$2`):`**Confidence:** ${n}/100\n\n${e}`}function u(e,t,n=i){let r=o(n);return t===`confirm`?Math.min(100,e+r.confirmIncrement):Math.max(0,e-r.contradictDecrement)}function d(e,t=i){let n=o(t);if(e.confidence>=n.archiveThreshold)return!1;let r=e.lastAccessedAt?new Date(e.lastAccessedAt):new Date(e.createdAt);return(Date.now()-r.getTime())/(1e3*60*60*24)>=n.autoArchiveDays}const f={stabilityHours:168,accessMultiplier:1.5,flagThreshold:.1,maxStabilityHours:8760};function p(e){return{...f,...e}}function m(e,t){if(!e)return t;let n=Date.parse(e);return Number.isNaN(n)?t:n}function h(e){return e&&e in t?e:`working`}function g(e,n,r,i=f,a){let o=typeof i==`string`?h(i):`working`,s=p(typeof i==`string`?a:i),c=m(e,m(r,Date.now())),l=Math.max(0,Date.now()-c)/(1e3*60*60),u=Math.min(s.stabilityHours*t[o]*s.accessMultiplier**Math.max(0,n),s.maxStabilityHours);return Math.exp(-l/u)}function _(e,t,n){let r=e.memoryMetaGet(t);if(!r)return;let i=g(r.lastAccessedAt,r.accessCount,r.createdAt,r.tier,n);return r.retentionScore!==i&&e.memoryMetaUpdateScore(t,i),e.memoryMetaGet(t)??{...r,retentionScore:i}}function v(e,t,n){e.memoryMetaGet(t)||e.memoryMetaCreate(t),e.memoryMetaTouch(t);let r=e.memoryMetaGet(t);if(!r)return 1;let i=g(r.lastAccessedAt,r.accessCount,r.createdAt,r.tier,n);return e.memoryMetaUpdateScore(t,i),i}function y(e,t){let n=p(t);return e.memoryMetaList().map(t=>_(e,t.entryId,n)??t).filter(e=>e.retentionScore<n.flagThreshold).sort((e,t)=>e.retentionScore-t.retentionScore)}const b={threshold:.7,maxCompare:50,autoThreshold:.95};function x(e){let t=Math.min(1,Math.max(0,e?.threshold??b.threshold)),n=Math.min(1,Math.max(t,e?.autoThreshold??b.autoThreshold));return{threshold:t,maxCompare:Math.max(1,Math.trunc(e?.maxCompare??b.maxCompare)),autoThreshold:n}}function S(e){let t=e.toLowerCase().match(/[a-z0-9]{2,}/g)??[];return new Set(t)}function C(e,t){let n=S(e),r=S(t);if(n.size===0&&r.size===0)return 1;if(n.size===0||r.size===0)return 0;let i=new Set([...n].filter(e=>r.has(e))),a=new Set([...n,...r]);return i.size/a.size}function w(e,t,n=b){let r=x(n);return t.slice(0,r.maxCompare).map(t=>({entryId:t.id,title:t.title,similarity:C(e,t.content),path:t.path})).filter(e=>e.similarity>=r.threshold).sort((e,t)=>t.similarity-e.similarity)}function T(e,t,n){e.memoryMetaCreate(t),e.memoryMetaSetSuperseded(t,n)}export{e as _,f as a,v as c,u as d,s as f,d as g,l as h,x as i,i as l,o as m,w as n,y as o,c as p,T as r,_ as s,b as t,a as u,n as v,r as y};
@@ -1,2 +0,0 @@
1
- const e={workingToEpisodicAccesses:2,episodicToSemanticReferences:3,semanticToProceduralVerifications:5},t={working:1,episodic:2,semantic:4,procedural:12};function n(t,n=e){switch(t.tier){case`working`:if(t.accessCount>=n.workingToEpisodicAccesses)return`episodic`;break;case`episodic`:if(t.accessCount>=n.workingToEpisodicAccesses+n.episodicToSemanticReferences)return`semantic`;break;case`semantic`:if(t.accessCount>=n.workingToEpisodicAccesses+n.episodicToSemanticReferences+n.semanticToProceduralVerifications)return`procedural`;break;case`procedural`:break;default:break}}function r(e,t,n){e.memoryMetaUpdateTier(t,n)}const i={confirmIncrement:10,contradictDecrement:20,autoArchiveDays:30,archiveThreshold:20},a=`lesson:auto-archive`;function o(e){return{confirmIncrement:Math.max(0,Math.trunc(e?.confirmIncrement??i.confirmIncrement)),contradictDecrement:Math.max(0,Math.trunc(e?.contradictDecrement??i.contradictDecrement)),autoArchiveDays:Math.max(1,Math.trunc(e?.autoArchiveDays??i.autoArchiveDays)),archiveThreshold:Math.min(100,Math.max(0,Math.trunc(e?.archiveThreshold??i.archiveThreshold)))}}function s(e){return[`## Lesson: ${e.title}`,``,`**Confidence:** ${e.confidence}/100`,``,`### Context`,e.context,``,`### Insight`,e.insight,``,`### Evidence`,e.evidence].join(`
2
- `)}function c(e){let t=e.match(/^## Lesson:\s+(.+)$/m),n=e.match(/\*\*Confidence:\*\*\s+(\d+)\/100/),r=e.match(/### Context\r?\n([\s\S]*?)(?=\r?\n### |$)/),i=e.match(/### Insight\r?\n([\s\S]*?)(?=\r?\n### |$)/),a=e.match(/### Evidence\r?\n([\s\S]*?)(?=\r?\n### |$)/);return{title:t?.[1]?.trim(),confidence:n?Number(n[1]):void 0,context:r?.[1]?.trim(),insight:i?.[1]?.trim(),evidence:a?.[1]?.trim()}}function l(e,t){let n=Math.min(100,Math.max(0,Math.trunc(t)));return/\*\*Confidence:\*\*/.test(e)?e.replace(/\*\*Confidence:\*\*\s+\d+\/100/,`**Confidence:** ${n}/100`):e.match(/^(## Lesson:[^\r\n]*)(\r?\n)/)?e.replace(/^(## Lesson:[^\r\n]*)(\r?\n)/,`$1$2$2**Confidence:** ${n}/100$2$2`):`**Confidence:** ${n}/100\n\n${e}`}function u(e,t,n=i){let r=o(n);return t===`confirm`?Math.min(100,e+r.confirmIncrement):Math.max(0,e-r.contradictDecrement)}function d(e,t=i){let n=o(t);if(e.confidence>=n.archiveThreshold)return!1;let r=e.lastAccessedAt?new Date(e.lastAccessedAt):new Date(e.createdAt);return(Date.now()-r.getTime())/(1e3*60*60*24)>=n.autoArchiveDays}const f={stabilityHours:168,accessMultiplier:1.5,flagThreshold:.1,maxStabilityHours:8760};function p(e){return{...f,...e}}function m(e,t){if(!e)return t;let n=Date.parse(e);return Number.isNaN(n)?t:n}function h(e){return e&&e in t?e:`working`}function g(e,n,r,i=f,a){let o=typeof i==`string`?h(i):`working`,s=p(typeof i==`string`?a:i),c=m(e,m(r,Date.now())),l=Math.max(0,Date.now()-c)/(1e3*60*60),u=Math.min(s.stabilityHours*t[o]*s.accessMultiplier**Math.max(0,n),s.maxStabilityHours);return Math.exp(-l/u)}function _(e,t,n){let r=e.memoryMetaGet(t);if(!r)return;let i=g(r.lastAccessedAt,r.accessCount,r.createdAt,r.tier,n);return r.retentionScore!==i&&e.memoryMetaUpdateScore(t,i),e.memoryMetaGet(t)??{...r,retentionScore:i}}function v(e,t,n){e.memoryMetaGet(t)||e.memoryMetaCreate(t),e.memoryMetaTouch(t);let r=e.memoryMetaGet(t);if(!r)return 1;let i=g(r.lastAccessedAt,r.accessCount,r.createdAt,r.tier,n);return e.memoryMetaUpdateScore(t,i),i}function y(e,t){let n=p(t);return e.memoryMetaList().map(t=>_(e,t.entryId,n)??t).filter(e=>e.retentionScore<n.flagThreshold).sort((e,t)=>e.retentionScore-t.retentionScore)}const b={threshold:.7,maxCompare:50,autoThreshold:.95};function x(e){let t=Math.min(1,Math.max(0,e?.threshold??b.threshold)),n=Math.min(1,Math.max(t,e?.autoThreshold??b.autoThreshold));return{threshold:t,maxCompare:Math.max(1,Math.trunc(e?.maxCompare??b.maxCompare)),autoThreshold:n}}function S(e){let t=e.toLowerCase().match(/[a-z0-9]{2,}/g)??[];return new Set(t)}function C(e,t){let n=S(e),r=S(t);if(n.size===0&&r.size===0)return 1;if(n.size===0||r.size===0)return 0;let i=new Set([...n].filter(e=>r.has(e))),a=new Set([...n,...r]);return i.size/a.size}function w(e,t,n=b){let r=x(n);return t.slice(0,r.maxCompare).map(t=>({entryId:t.id,title:t.title,similarity:C(e,t.content),path:t.path})).filter(e=>e.similarity>=r.threshold).sort((e,t)=>t.similarity-e.similarity)}function T(e,t,n){e.memoryMetaCreate(t),e.memoryMetaSetSuperseded(t,n)}export{e as _,f as a,v as c,u as d,s as f,d as g,l as h,x as i,i as l,o as m,w as n,y as o,c as p,T as r,_ as s,b as t,a as u,n as v,r as y};