@theokit/sdk-memory 0.4.0 → 0.5.1
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/CHANGELOG.md +40 -0
- package/dist/index.cjs +106 -235
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +27 -223
- package/dist/index.js.map +1 -1
- package/dist/internal/active-memory/active-memory.d.ts.map +1 -1
- package/dist/internal/dreaming/dreaming-diary.d.ts +6 -61
- package/dist/internal/dreaming/dreaming-diary.d.ts.map +1 -1
- package/dist/internal/index/index-db.d.ts +0 -7
- package/dist/internal/index/index-db.d.ts.map +1 -1
- package/dist/internal/index/index-manager.d.ts +9 -1
- package/dist/internal/index/index-manager.d.ts.map +1 -1
- package/dist/internal/index/lance-index.d.ts +3 -6
- package/dist/internal/index/lance-index.d.ts.map +1 -1
- package/dist/internal/index/migrate-sqlite-to-lance.d.ts +5 -0
- package/dist/internal/index/migrate-sqlite-to-lance.d.ts.map +1 -1
- package/dist/internal/store/markdown-store.d.ts +1 -1
- package/dist/internal/store/markdown-store.d.ts.map +1 -1
- package/dist/internal/store/session-loader.d.ts +3 -27
- package/dist/internal/store/session-loader.d.ts.map +1 -1
- package/dist/internal/store/session-summary-writer.d.ts +6 -53
- package/dist/internal/store/session-summary-writer.d.ts.map +1 -1
- package/dist/internal/store/transcript-store.d.ts +3 -45
- package/dist/internal/store/transcript-store.d.ts.map +1 -1
- package/dist/internal/store/wiki-loader.d.ts +3 -32
- package/dist/internal/store/wiki-loader.d.ts.map +1 -1
- package/dist/internal/tools.d.ts +3 -1
- package/dist/internal/tools.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/in-memory-provider.ts","../src/internal/store/markdown-store.ts","../src/internal/store/transcript-store.ts","../src/internal/active-memory/active-memory.ts","../src/internal/circuit-breaker.ts","../src/internal/active-memory/active-memory-cache.ts","../src/internal/embedding/azure-openai-embedding.ts","../src/internal/embedding/cohere-embedding.ts","../src/internal/embedding/deepinfra-embedding.ts","../src/internal/embedding/gemini-embedding.ts","../src/internal/embedding/jina-embedding.ts","../src/internal/embedding/mistral-embedding.ts","../src/internal/embedding/ollama-embedding.ts","../src/internal/embedding/openai-embedding.ts","../src/internal/embedding/openrouter-embedding.ts","../src/internal/embedding/voyage-embedding.ts","../src/internal/adapter-catalog.ts","../src/internal/memory-types.ts","../src/internal/adapter-http-error.ts","../src/internal/categorized-memory.ts","../src/internal/dreaming/dreaming-diary.ts","../src/internal/dreaming/dreaming-phases.ts","../src/internal/dreaming/dreaming-run.ts","../src/internal/index/index-schema.ts","../src/internal/index/index-db.ts","../src/internal/store/chunk-markdown.ts","../src/internal/store/session-summary-writer.ts","../src/internal/store/session-loader.ts","../src/internal/store/wiki-loader.ts","../src/internal/index/lance-index.ts","../src/internal/index/memory-index.ts","../src/internal/index/lance-memory-adapter.ts","../src/internal/index/index-manager-dispatch.ts","../src/internal/index/sqlite-vec-loader.ts","../src/internal/index/vec-index.ts","../src/internal/index/index-manager.ts","../src/internal/index/migrate-sqlite-to-lance.ts","../src/internal/index/migration.ts","../src/internal/store/reader.ts","../src/internal/tools.ts"],"names":["sessionsDir","readdir","join","finalized","DIMENSION_BY_MODEL","Security","resolvePath","ConfigurationError","safePathJoin","sanitizeIdentifier","mkdir","replaceFileAtomic","readFile","createHash","kept","withCwdMutex","notesDir","sanitizeRunId","truncate","relativeToRoot","existsSync","mkdirSync"],"mappings":";;;;;;;;;;;;;;;AA6CA,IAAM,UAAA,GAAa,cAAA;AAmBnB,IAAM,cAAA,0BAAwB,4BAA4B,CAAA;AAE1D,SAAS,iBAAA,GAA+C;AACtD,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,KAAA;AAAA,IACT,QAAA,EAAU,KAAA;AAAA,IACV,OAAA,EAAS,KAAA;AAAA,IACT,SAAA,EAAW,KAAA;AAAA,IACX,WAAA,EAAa,KAAA;AAAA,IACb,QAAA,EAAU;AAAA,GACZ;AACF;AAEA,SAAS,aAAa,KAAA,EAA2C;AAC/D,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,UAAA;AAAA,IACJ,cAAc,iBAAA,EAAkB;AAAA,IAChC,WAAA,GAAuB;AACrB,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IACA,MAAM,KAAA,CAAM,OAAA,EAAuC,IAAA,EAAwC;AACzF,MAAA,MAAM,IAAA,GAAO,OAAO,OAAA,KAAY,QAAA,GAAW,OAAA,GAAU,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,CAAA,CAAE,KAAK,IAAI,CAAA;AAK5F,MAAA,MAAM,QAAA,GAAW,QAAA,CAAS,MAAA,CAAO,IAAI,CAAA;AACrC,MAAA,MAAM,KAAK,CAAA,EAAG,UAAU,CAAA,CAAA,EAAI,KAAA,CAAM,QAAQ,IAAA,EAAM,CAAA,CAAA;AAChD,MAAA,KAAA,CAAM,KAAA,CAAM,IAAI,EAAA,EAAI;AAAA,QAClB,EAAA;AAAA,QACA,OAAA,EAAS,QAAA;AAAA,QACT,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA;AAAY,OACnC,CAAA;AACD,MAAA,OAAO,EAAA;AAAA,IACT,CAAA;AAAA,IACA,MAAM,MAAA,CAAO,MAAA,EAAgB,IAAA,EAAqB,CAAA,EAAmC;AAGnF,MAAA,MAAM,MAAM,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,QAAQ,CAAA;AAC3C,MAAA,MAAM,QAAQ,CAAA,KAAM,MAAA,IAAa,CAAA,IAAK,CAAA,GAAI,IAAI,GAAA,CAAI,MAAA;AAClD,MAAA,OAAO,GAAA,CAAI,KAAA,CAAM,CAAA,EAAG,KAAK,CAAA;AAAA,IAC3B,CAAA;AAAA,IACA,MAAM,OAAO,EAAA,EAA6B;AACxC,MAAA,IAAI,CAAC,OAAO,EAAE,CAAA,CAAE,WAAW,CAAA,EAAG,UAAU,GAAG,CAAA,EAAG;AAC5C,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,0BAAA,EAA6B,MAAA,CAAO,EAAE,CAAC,gCAAgC,UAAU,CAAA,CAAA;AAAA,SACnF;AAAA,MACF;AACA,MAAA,KAAA,CAAM,KAAA,CAAM,OAAO,EAAE,CAAA;AAAA,IACvB;AAAA,GACF;AACF;AAGA,IAAM,sBAAA,GAAyB,GAAA;AAE/B,SAAS,SAAS,IAAA,EAAsB;AACtC,EAAA,IAAI,IAAA,CAAK,MAAA,IAAU,sBAAA,EAAwB,OAAO,IAAA;AAClD,EAAA,OAAO,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,sBAAsB,CAAC,CAAA,MAAA,CAAA;AACjD;AAQA,SAAS,cAAc,KAAA,EAAuB;AAC5C,EAAA,OAAO,MAAM,OAAA,CAAQ,iBAAA,EAAmB,GAAG,CAAA,CAAE,KAAA,CAAM,GAAG,GAAG,CAAA;AAC3D;AAGA,SAAS,6BAA6B,IAAA,EAAwC;AAC5E,EAAA,MAAM,MAAM,IAAI,IAAA,CAAK,IAAA,CAAK,EAAE,EAAE,WAAA,EAAY;AAM1C,EAAA,MAAM,WAAW,QAAA,CAAS,MAAA,CAAO,QAAA,CAAS,IAAA,CAAK,QAAQ,CAAC,CAAA;AACxD,EAAA,MAAM,gBAAgB,QAAA,CAAS,MAAA,CAAO,QAAA,CAAS,IAAA,CAAK,aAAa,CAAC,CAAA;AAClE,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,CAAA,OAAA,EAAU,KAAK,KAAK,CAAA,CAAA;AAAA,IACpB,CAAA,SAAA,EAAY,KAAK,OAAO,CAAA,CAAA;AAAA,IACxB,OAAO,GAAG,CAAA,CAAA;AAAA,IACV,CAAA,QAAA,EAAW,KAAK,MAAM,CAAA,CAAA;AAAA,IACtB,KAAA;AAAA,IACA,EAAA;AAAA,IACA,SAAA;AAAA,IACA,EAAA;AAAA,IACA,QAAA;AAAA,IACA,EAAA;AAAA,IACA,cAAA;AAAA,IACA,EAAA;AAAA,IACA,aAAA;AAAA,IACA;AAAA,GACF,CAAE,KAAK,IAAI,CAAA;AACb;AAiBA,SAAS,8BAA8B,OAAA,EAAqC;AAE1E,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,CAAM,oBAAoB,CAAA;AAChD,EAAA,IAAI,UAAU,IAAA,IAAQ,KAAA,CAAM,CAAC,CAAA,KAAM,QAAW,OAAO,MAAA;AACrD,EAAA,OAAO,KAAA,CAAM,CAAC,CAAA,CAAE,IAAA,EAAK;AACvB;AAeA,eAAe,sBAAA,CACb,GAAA,EACA,WAAA,EACA,aAAA,EACoC;AACpC,EAAA,MAAM,UAAA,GAAa,CAAA;AACnB,EAAA,MAAMA,YAAAA,GAAc,IAAA,CAAK,GAAA,EAAK,UAAA,EAAY,UAAU,UAAU,CAAA;AAC9D,EAAA,IAAI,KAAA;AACJ,EAAA,IAAI;AACF,IAAA,KAAA,GAAQ,MAAM,QAAQA,YAAW,CAAA;AAAA,EACnC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACA,EAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,WAAA,EAAY,CAAE,IAAA,EAAK;AAC7C,EAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,EAAC;AAChC,EAAA,MAAM,OAAqB,EAAC;AAC5B,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,KAAK,CAAA,EAAG;AAC3B,IAAA,IAAI,IAAA,CAAK,UAAU,UAAA,EAAY;AAC/B,IAAA,MAAM,QAAA,GAAW,IAAA,CAAKA,YAAAA,EAAa,IAAI,CAAA;AACvC,IAAA,IAAI,OAAA;AACJ,IAAA,IAAI;AACF,MAAA,OAAA,GAAU,MAAM,QAAA,CAAS,QAAA,EAAU,OAAO,CAAA;AAAA,IAC5C,CAAA,CAAA,MAAQ;AACN,MAAA;AAAA,IACF;AAIA,IAAA,IAAI,kBAAkB,MAAA,EAAW;AAC/B,MAAA,MAAM,WAAA,GAAc,8BAA8B,OAAO,CAAA;AACzD,MAAA,IAAI,gBAAgB,aAAA,EAAe;AAAA,IACrC;AACA,IAAA,IAAI,OAAA,CAAQ,WAAA,EAAY,CAAE,QAAA,CAAS,KAAK,CAAA,EAAG;AAEzC,MAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,CAAQ,SAAS,CAAA;AACzC,MAAA,MAAM,OAAA,GACJ,OAAA,IAAW,CAAA,GAAI,OAAA,CAAQ,KAAA,CAAM,OAAA,EAAS,OAAA,GAAU,GAAG,CAAA,CAAE,OAAA,CAAQ,MAAA,EAAQ,GAAG,CAAA,GAAI,IAAA;AAC9E,MAAA,MAAM,EAAA,GAAK,CAAA,EAAG,UAAU,CAAA,SAAA,EAAY,IAAI,CAAA,CAAA;AACxC,MAAA,IAAA,CAAK,IAAA,CAAK;AAAA,QACR,EAAA;AAAA,QACA,OAAA,EAAS,OAAA;AAAA,QACT,KAAA,EAAO;AAAA;AAAA,OACR,CAAA;AAAA,IACH;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAQA,SAAS,sBAAsB,KAAA,EAAwC;AACrE,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,eAAA;AAAA,IACN,WAAA,EACE,iLAAA;AAAA,IACF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,KAAA,EAAO;AAAA,UACL,IAAA,EAAM,QAAA;AAAA,UACN,WAAA,EAAa;AAAA;AACf,OACF;AAAA,MACA,QAAA,EAAU,CAAC,OAAO,CAAA;AAAA,MAClB,oBAAA,EAAsB;AAAA,KACxB;AAAA,IACA,OAAA,EAAS,OAAO,KAAA,KAAoD;AAClE,MAAA,MAAM,QAAQ,OAAO,KAAA,CAAM,KAAA,KAAU,QAAA,GAAW,MAAM,KAAA,GAAQ,EAAA;AAC9D,MAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,QAAA,OAAO,IAAA,CAAK,SAAA,CAAU,EAAE,EAAA,EAAI,KAAA,EAAO,SAAS,EAAC,EAAG,KAAA,EAAO,aAAA,EAAe,CAAA;AAAA,MACxE;AACA,MAAA,MAAM,IAAA,GAAO,MAAM,sBAAA,CAAuB,KAAA,CAAM,KAAK,KAAK,CAAA;AAC1D,MAAA,OAAO,KAAK,SAAA,CAAU;AAAA,QACpB,EAAA,EAAI,IAAA;AAAA,QACJ,OAAO,IAAA,CAAK,MAAA;AAAA,QACZ,OAAA,EAAS,IAAA,CAAK,GAAA,CAAI,CAAC,OAAO,EAAE,EAAA,EAAI,MAAA,CAAO,CAAA,CAAE,EAAE,CAAA,EAAG,OAAA,EAAS,CAAA,CAAE,SAAQ,CAAE;AAAA,OACpE,CAAA;AAAA,IACH;AAAA,GACF;AACF;AAEA,SAAS,wBAAwB,KAAA,EAAwC;AACvE,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,iBAAA;AAAA,IACN,WAAA,EACE,gJAAA;AAAA,IACF,WAAA,EAAa;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,sCAAA;AAAuC,OACjF;AAAA,MACA,QAAA,EAAU,CAAC,SAAS,CAAA;AAAA,MACpB,oBAAA,EAAsB;AAAA,KACxB;AAAA,IACA,OAAA,EAAS,OAAO,KAAA,KAAoD;AAClE,MAAA,MAAM,UAAU,OAAO,KAAA,CAAM,OAAA,KAAY,QAAA,GAAW,MAAM,OAAA,GAAU,EAAA;AACpE,MAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,QAAA,OAAO,KAAK,SAAA,CAAU,EAAE,IAAI,KAAA,EAAO,KAAA,EAAO,iBAAiB,CAAA;AAAA,MAC7D;AAOA,MAAA,MAAM,WAAA,GAAc,QAAA,CAAS,MAAA,CAAO,OAAO,CAAA;AAC3C,MAAA,MAAM,KAAK,CAAA,EAAG,UAAU,CAAA,CAAA,EAAI,KAAA,CAAM,QAAQ,IAAA,EAAM,CAAA,CAAA;AAChD,MAAA,KAAA,CAAM,KAAA,CAAM,IAAI,EAAA,EAAI;AAAA,QAClB,EAAA;AAAA,QACA,OAAA,EAAS,WAAA;AAAA,QACT,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA;AAAY,OACnC,CAAA;AACD,MAAA,OAAO,KAAK,SAAA,CAAU,EAAE,EAAA,EAAI,IAAA,EAAM,IAAI,CAAA;AAAA,IACxC;AAAA,GACF;AACF;AAeO,SAAS,8BAAA,GAAiD;AAC/D,EAAA,OAAO;AAAA,IACL,MAAM,KAAK,IAAA,EAAgE;AACzE,MAAA,MAAM,KAAA,GAA6B;AAAA,QACjC,KAAA,sBAAW,GAAA,EAAI;AAAA,QACf,OAAA,EAAS,EAAE,IAAA,EAAM,CAAA,EAAE;AAAA,QACnB,KAAK,IAAA,CAAK;AAAA,OACZ;AACA,MAAA,MAAM,OAAA,GAAU,aAAa,KAAK,CAAA;AAClC,MAAA,OAAO;AAAA,QACL,OAAA;AAAA,QACA,CAAC,cAAc,GAAG;AAAA,OACpB;AAAA,IACF,CAAA;AAAA,IACA,UAAA,CAAW,QAA8B,MAAA,EAA6C;AACpF,MAAA,MAAM,KAAA,GAAQ,OAAO,cAAc,CAAA;AACnC,MAAA,IAAI,KAAA,KAAU,MAAA,EAAW,OAAO,EAAC;AACjC,MAAA,OAAO,CAAC,uBAAA,CAAwB,KAAK,CAAA,EAAG,qBAAA,CAAsB,KAAK,CAAC,CAAA;AAAA,IACtE,CAAA;AAAA,IACA,MAAM,aAAA,CACJ,MAAA,EACA,IAAA,EACiC;AACjC,MAAA,MAAM,KAAA,GAAQ,OAAO,cAAc,CAAA;AACnC,MAAA,IAAI,UAAU,MAAA,EAAW,OAAO,EAAE,KAAA,EAAO,EAAC,EAAE;AAE5C,MAAA,MAAM,iBAAiB,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,QAAQ,CAAA;AAQtD,MAAA,MAAM,aAAA,GAAgB,MAAM,sBAAA,CAAuB,KAAA,CAAM,KAAK,IAAA,CAAK,WAAA,EAAa,KAAK,OAAO,CAAA;AAC5F,MAAA,MAAM,QAAA,GAAW,CAAC,GAAG,cAAA,EAAgB,GAAG,aAAa,CAAA;AACrD,MAAA,IAAI,SAAS,MAAA,KAAW,CAAA,SAAU,EAAE,KAAA,EAAO,EAAC,EAAE;AAC9C,MAAA,MAAM,qBAAA,GAAwB;AAAA,QAC5B,8CAAA;AAAA,QACA,GAAG,SAAS,GAAA,CAAI,CAAC,MAAM,CAAA,EAAA,EAAK,CAAA,CAAE,OAAO,CAAA,CAAE;AAAA,OACzC,CAAE,KAAK,IAAI,CAAA;AACX,MAAA,OAAO,EAAE,KAAA,EAAO,QAAA,EAAU,qBAAA,EAAsB;AAAA,IAClD,CAAA;AAAA,IACA,KAAK,OAAA,EAAqC;AAIxC,MAAA;AAAA,IACF,CAAA;AAAA,IACA,MAAM,qBAAqB,IAAA,EAA+C;AAMxE,MAAA,IAAI,IAAA,CAAK,WAAW,UAAA,EAAY;AAChC,MAAA,MAAM,eAAe,IAAA,CAAK,IAAA,CAAK,GAAA,EAAK,UAAA,EAAY,UAAU,UAAU,CAAA;AACpE,MAAA,MAAM,QAAA,GAAW,KAAK,YAAA,EAAc,CAAA,EAAG,cAAc,IAAA,CAAK,KAAK,CAAC,CAAA,GAAA,CAAK,CAAA;AACrE,MAAA,MAAM,KAAA,CAAM,YAAA,EAAc,EAAE,SAAA,EAAW,MAAM,CAAA;AAC7C,MAAA,MAAM,IAAA,GAAO,6BAA6B,IAAI,CAAA;AAC9C,MAAA,MAAM,iBAAA,CAAkB,UAAU,IAAI,CAAA;AAAA,IACxC,CAAA;AAAA,IACA,QAAQ,MAAA,EAAoC;AAC1C,MAAA,MAAM,KAAA,GAAQ,OAAO,cAAc,CAAA;AACnC,MAAA,IAAI,UAAU,MAAA,EAAW;AACzB,MAAA,KAAA,CAAM,MAAM,KAAA,EAAM;AAAA,IACpB;AAAA,GACF;AACF;AChWA,eAAsB,UAAU,GAAA,EAAkC;AAChE,EAAA,IAAI,UAAoB,EAAC;AACzB,EAAA,IAAI;AACF,IAAA,OAAA,GAAU,MAAMC,OAAAA,CAAQ,QAAA,CAAS,GAAG,CAAC,CAAA;AAAA,EACvC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACA,EAAA,OAAO,OAAA,CACJ,MAAA,CAAO,CAAC,IAAA,KAAS,IAAA,CAAK,QAAA,CAAS,KAAK,CAAC,CAAA,CACrC,GAAA,CAAI,CAAC,IAAA,MAAU,EAAE,MAAM,IAAA,CAAK,OAAA,CAAQ,OAAA,EAAS,EAAE,CAAA,EAAG,IAAA,EAAMC,IAAAA,CAAK,QAAA,CAAS,GAAG,CAAA,EAAG,IAAI,CAAA,EAAE,CAAE,CAAA;AACzF;;;ACNA,eAAsB,6BAAA,CACpB,KACA,UAAA,EACe;AACf,EAAA,IAAI;AACF,IAAA,MAAM,MAAMA,IAAAA,CAAK,SAAA,CAAU,GAAG,CAAA,EAAG,eAAe,eAAe,CAAA;AAC/D,IAAA,MAAM,OAAOA,IAAAA,CAAK,GAAA,EAAK,CAAA,EAAG,UAAA,CAAW,KAAK,CAAA,KAAA,CAAO,CAAA;AAGjD,IAAA,MAAM,eAAA,CAAgB,MAAM,UAAU,CAAA;AAAA,EACxC,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,UAAU,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AACrE,IAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,uDAAA,EAA0D,OAAO;AAAA,CAAI,CAAA;AAAA,EAC5F;AACF;;;ACPA,IAAM,kBAAA,GAAqB,eAAA;AAC3B,IAAM,mCAAA,GAAsC,mCAAA;AA0E5C,IAAM,QAAA,GAA2D;AAAA,EAC/D,SAAA,EAAW,QAAA;AAAA,EACX,SAAA,EAAW,IAAA;AAAA,EACX,eAAA,EAAiB,GAAA;AAAA,EACjB,eAAA,EAAiB;AACnB,CAAA;AA0BA,eAAsB,gBAAgB,IAAA,EAAwD;AAC5F,EAAA,MAAM,OAAA,GAAU,KAAK,GAAA,EAAI;AAGzB,EAAA,MAAM,IAAA,GAAO,sBAAsB,IAAI,CAAA;AACvC,EAAA,IAAI;AACF,IAAA,IAAI,KAAK,OAAA,CAAQ,OAAA,KAAY,IAAA,IAAQ,IAAA,CAAK,UAAU,KAAA,CAAA,EAAW;AAC7D,MAAA,OAAO,aAAA,CAAc,MAAM,IAAA,EAAM;AAAA,QAC/B,OAAA,EAAS,KAAA,CAAA;AAAA,QACT,UAAA,EAAY,CAAA;AAAA,QACZ,MAAA,EAAQ,SAAA;AAAA,QACR,MAAM;AAAC,OACR,CAAA;AAAA,IACH;AACA,IAAA,MAAM,MAAM,EAAE,GAAG,QAAA,EAAU,GAAG,KAAK,OAAA,EAAQ;AAC3C,IAAA,MAAM,UAAA,GAAa,KAAK,QAAA,IAAY,SAAA;AACpC,IAAA,IAAI,IAAA,CAAK,OAAA,EAAS,UAAA,CAAW,UAAU,MAAM,IAAA,EAAM;AACjD,MAAA,OAAO,aAAA,CAAc,MAAM,IAAA,EAAM;AAAA,QAC/B,OAAA,EAAS,KAAA,CAAA;AAAA,QACT,UAAA,EAAY,CAAA;AAAA,QACZ,MAAA,EAAQ,SAAA;AAAA,QACR,MAAM;AAAC,OACR,CAAA;AAAA,IACH;AAGA,IAAA,MAAM,SAAA,GAA2B;AAAA,MAC/B,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,OAAO,IAAA,CAAK;AAAA,KACd;AACA,IAAA,MAAM,MAAA,GAAS,KAAK,KAAA,EAAO,GAAA,CAAI,KAAK,QAAA,EAAU,GAAA,CAAI,WAAW,SAAS,CAAA;AACtE,IAAA,IAAI,WAAW,KAAA,CAAA,EAAW,OAAO,aAAA,CAAc,IAAA,EAAM,MAAM,MAAM,CAAA;AAEjE,IAAA,MAAM,KAAA,GAAQ,WAAW,IAAA,CAAK,QAAA,EAAU,KAAK,aAAA,EAAe,GAAA,CAAI,SAAA,EAAW,GAAA,CAAI,eAAe,CAAA;AAC9F,IAAA,IAAI,KAAA,CAAM,IAAA,EAAK,CAAE,MAAA,KAAW,CAAA,EAAG;AAC7B,MAAA,MAAMC,UAAAA,GAAY,MAAM,QAAA,CAAS,IAAA,EAAM,IAAI,SAAA,EAAW;AAAA,QACpD,OAAA,EAAS,KAAA,CAAA;AAAA,QACT,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,OAAA;AAAA,QACzB,MAAA,EAAQ,WAAA;AAAA,QACR,MAAM;AAAC,OACR,CAAA;AACD,MAAA,OAAO,aAAA,CAAc,IAAA,EAAM,IAAA,EAAMA,UAAS,CAAA;AAAA,IAC5C;AACA,IAAA,MAAM,SAAS,MAAM,UAAA,CAAW,IAAA,EAAM,GAAA,EAAK,OAAO,OAAO,CAAA;AACzD,IAAA,aAAA,CAAc,IAAA,CAAK,OAAA,EAAS,UAAA,EAAY,MAAA,CAAO,MAAM,CAAA;AACrD,IAAA,MAAM,YAAY,MAAM,QAAA,CAAS,IAAA,EAAM,GAAA,CAAI,WAAW,MAAM,CAAA;AAC5D,IAAA,OAAO,aAAA,CAAc,IAAA,EAAM,IAAA,EAAM,SAAS,CAAA;AAAA,EAC5C,SAAS,KAAA,EAAO;AACd,IAAA,IAAA,CAAK,gBAAgB,KAAK,CAAA;AAC1B,IAAA,IAAA,CAAK,SAAA,CAAU,EAAE,IAAA,EAAM,CAAA,EAAG,OAAA,EAAS,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAA,EAAG,CAAA;AAC3F,IAAA,IAAA,CAAK,GAAA,EAAI;AACT,IAAA,MAAM,KAAA;AAAA,EACR;AACF;AAEA,SAAS,sBAAsB,IAAA,EAAqC;AAClE,EAAA,MAAM,YAAyC,IAAA,CAAK,SAAA;AACpD,EAAA,IAAI,cAAc,MAAA,EAAW;AAE3B,IAAA,OAAO;AAAA,MACL,cAAc,MAAM;AAAA,MAAC,CAAA;AAAA,MACrB,eAAe,MAAM;AAAA,MAAC,CAAA;AAAA,MACtB,UAAU,MAAM;AAAA,MAAC,CAAA;AAAA,MACjB,WAAW,MAAM;AAAA,MAAC,CAAA;AAAA,MAClB,iBAAiB,MAAM;AAAA,MAAC,CAAA;AAAA,MACxB,KAAK,MAAM;AAAA,MAAC,CAAA;AAAA,MACZ,WAAA,EAAa,OAAO,EAAE,OAAA,EAAS,GAAA,CAAI,MAAA,CAAO,EAAE,CAAA,EAAG,MAAA,EAAQ,GAAA,CAAI,MAAA,CAAO,EAAE,CAAA,EAAE,CAAA;AAAA,MACtE,aAAa,MAAM;AAAA,KACrB;AAAA,EACF;AACA,EAAA,OAAO,SAAA,CAAU,UAAU,kBAAA,EAAoB;AAAA,IAC7C,SAAA,EAAW,IAAA,CAAK,OAAA,CAAQ,SAAA,IAAa,QAAA;AAAA,IACrC,GAAI,KAAK,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,EAAQ,IAAA,CAAK,MAAA,EAAO,GAAI,EAAC;AAAA,IAC3D,GAAI,KAAK,SAAA,KAAc,MAAA,GAAY,EAAE,SAAA,EAAW,IAAA,CAAK,SAAA,EAAU,GAAI,EAAC;AAAA,IACpE,GAAI,KAAK,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,EAAO,IAAA,CAAK,KAAA,EAAM,GAAI;AAAC,GACzD,CAAA;AACH;AAEA,SAAS,aAAA,CACP,IAAA,EACA,IAAA,EACA,MAAA,EACoB;AACpB,EAAA,IAAA,CAAK,aAAA,CAAc;AAAA,IACjB,IAAA,EAAM,OAAO,IAAA,CAAK,MAAA;AAAA,IAClB,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,YAAY,MAAA,CAAO;AAAA,GACpB,CAAA;AACD,EAAA,IAAA,CAAK,GAAA,EAAI;AACT,EAAA,IAAA,CAAK,SAAA,EAAW,eAAA,CAAgB,mCAAA,EAAqC,MAAA,CAAO,UAAA,EAAY;AAAA,IACtF,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,GAAI,KAAK,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,EAAQ,IAAA,CAAK,MAAA,EAAO,GAAI,EAAC;AAAA,IAC3D,GAAI,KAAK,SAAA,KAAc,MAAA,GAAY,EAAE,SAAA,EAAW,IAAA,CAAK,SAAA,EAAU,GAAI,EAAC;AAAA,IACpE,GAAI,KAAK,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,EAAO,IAAA,CAAK,KAAA,EAAM,GAAI;AAAC,GACzD,CAAA;AACD,EAAA,OAAO,MAAA;AACT;AASA,eAAe,UAAA,CACb,IAAA,EACA,GAAA,EACA,KAAA,EACA,OAAA,EAC6B;AAC7B,EAAA,IAAI,IAAA,CAAK,UAAU,MAAA,EAAW;AAC5B,IAAA,OAAO,EAAE,SAAS,MAAA,EAAW,UAAA,EAAY,GAAG,MAAA,EAAQ,SAAA,EAAW,IAAA,EAAM,EAAC,EAAE;AAAA,EAC1E;AACA,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,WAAA,CAAY,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,KAAA,EAAO,EAAE,UAAA,EAAY,CAAA,EAAG,CAAA,EAAG,IAAI,SAAS,CAAA;AACzF,IAAA,IAAI,SAAS,SAAA,EAAW;AACtB,MAAA,OAAO,EAAE,OAAA,EAAS,KAAA,CAAA,EAAW,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAW,IAAA,EAAM,EAAC,EAAE;AAAA,IAC7F;AACA,IAAA,IAAI,IAAA,CAAK,WAAW,CAAA,EAAG;AACrB,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,KAAA,CAAA;AAAA,QACT,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,OAAA;AAAA,QACzB,MAAA,EAAQ,WAAA;AAAA,QACR,MAAM;AAAC,OACT;AAAA,IACF;AACA,IAAA,MAAM,OAAA,GAAU,aAAA,CAAc,IAAA,EAAM,GAAA,CAAI,eAAe,CAAA;AACvD,IAAA,OAAO,EAAE,SAAS,UAAA,EAAY,IAAA,CAAK,KAAI,GAAI,OAAA,EAAS,MAAA,EAAQ,IAAA,EAAM,IAAA,EAAK;AAAA,EACzE,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,UAAU,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AACrE,IAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,2CAAA,EAA8C,OAAO;AAAA,CAAI,CAAA;AAC9E,IAAA,OAAO,EAAE,OAAA,EAAS,MAAA,EAAW,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,OAAA,EAAS,MAAA,EAAQ,OAAA,EAAS,IAAA,EAAM,EAAC,EAAE;AAAA,EAC3F;AACF;AAEA,SAAS,aAAA,CACP,OAAA,EACA,GAAA,EACA,MAAA,EACM;AACN,EAAA,IAAI,YAAY,MAAA,EAAW;AAC3B,EAAA,IAAI,MAAA,KAAW,SAAA,EAAW,OAAA,CAAQ,aAAA,CAAc,GAAG,CAAA;AAAA,OAAA,IAC1C,WAAW,IAAA,IAAQ,MAAA,KAAW,WAAA,EAAa,OAAA,CAAQ,cAAc,GAAG,CAAA;AAC/E;AAEA,eAAe,QAAA,CACb,IAAA,EACA,SAAA,EACA,MAAA,EAC6B;AAE7B,EAAA,MAAM,SAAA,GAA2B;AAAA,IAC/B,WAAW,IAAA,CAAK,SAAA;AAAA,IAChB,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,OAAO,IAAA,CAAK;AAAA,GACd;AACA,EAAA,IAAA,CAAK,OAAO,GAAA,CAAI,IAAA,CAAK,QAAA,EAAU,SAAA,EAAW,QAAQ,SAAS,CAAA;AAC3D,EAAA,IAAI,IAAA,CAAK,kBAAA,KAAuB,IAAA,IAAQ,IAAA,CAAK,QAAQ,MAAA,EAAW;AAC9D,IAAA,MAAM,6BAAA,CAA8B,KAAK,GAAA,EAAK;AAAA,MAC5C,OAAO,IAAA,CAAK,KAAA,IAAS,CAAA,IAAA,EAAO,IAAA,CAAK,KAAK,CAAA,CAAA;AAAA,MACtC,WAAA,EAAa,IAAA,CAAK,GAAA,EAAI,GAAI,MAAA,CAAO,UAAA;AAAA,MACjC,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,SAAA;AAAA,MACA,QAAQ,MAAA,CAAO,MAAA;AAAA,MACf,YAAY,MAAA,CAAO,UAAA;AAAA,MACnB,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,IAAA,EAAM,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,QAC5B,MAAM,CAAA,CAAE,IAAA;AAAA,QACR,WAAW,CAAA,CAAE,SAAA;AAAA,QACb,SAAS,CAAA,CAAE,OAAA;AAAA,QACX,OAAO,CAAA,CAAE,KAAA;AAAA,QACT,SAAS,CAAA,CAAE;AAAA,OACb,CAAE;AAAA,KACH,CAAA;AAAA,EACH;AACA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,UAAA,CACP,QAAA,EACA,aAAA,EACA,SAAA,EACA,eAAA,EACQ;AACR,EAAA,IAAI,SAAA,KAAc,WAAW,OAAO,QAAA;AACpC,EAAA,IAAI,cAAc,MAAA,EAAQ;AACxB,IAAA,MAAM,YAAA,GAAe,aAAA,CAAc,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,KAAS,MAAM,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,IAAI,CAAA;AACrF,IAAA,OAAO,CAAC,GAAG,YAAA,EAAc,QAAQ,CAAA,CAAE,KAAK,IAAI,CAAA;AAAA,EAC9C;AAEA,EAAA,MAAM,SAAS,aAAA,CACZ,MAAA,CAAO,CAAC,CAAA,KAAM,EAAE,IAAA,KAAS,MAAM,CAAA,CAC/B,KAAA,CAAM,CAAC,eAAe,CAAA,CACtB,IAAI,CAAC,CAAA,KAAM,EAAE,IAAI,CAAA;AACpB,EAAA,OAAO,CAAC,GAAG,MAAA,EAAQ,QAAQ,CAAA,CAAE,KAAK,IAAI,CAAA;AACxC;AAEA,SAAS,aAAA,CAAc,MAAsC,QAAA,EAA0B;AACrF,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,EAAA,EAAK,CAAA,CAAE,QAAQ,CAAA,EAAA,EAAK,CAAA,CAAE,OAAO,CAAA,CAAE,CAAA;AAC7D,EAAA,IAAI,OAAA,GAAU,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA;AAC7B,EAAA,IAAI,OAAA,CAAQ,MAAA,GAAS,QAAA,EAAU,OAAA,GAAU,CAAA,EAAG,QAAQ,KAAA,CAAM,CAAA,EAAG,QAAA,GAAW,CAAC,CAAC,CAAA,MAAA,CAAA;AAC1E,EAAA,OAAO,OAAA;AACT;AAEA,eAAe,WAAA,CAAe,SAAqB,SAAA,EAA2C;AAC5F,EAAA,IAAI,KAAA;AACJ,EAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAmB,CAAC,OAAA,KAAY;AAClD,IAAA,KAAA,GAAQ,UAAA,CAAW,MAAM,OAAA,CAAQ,SAAS,GAAG,SAAS,CAAA;AAAA,EACxD,CAAC,CAAA;AACD,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,MAAM,OAAA,CAAQ,KAAK,CAAC,OAAA,EAAS,OAAO,CAAC,CAAA;AACpD,IAAA,OAAO,MAAA;AAAA,EACT,CAAA,SAAE;AACA,IAAA,IAAI,KAAA,KAAU,MAAA,EAAW,YAAA,CAAa,KAAK,CAAA;AAAA,EAC7C;AACF;;;ACvWA,IAAM,oBAAA,GAAuB,CAAA;AAC7B,IAAM,mBAAA,GAAsB,GAAA;AAmBrB,IAAM,iBAAN,MAAqB;AAAA,EAG1B,WAAA,CAA6B,IAAA,GAA8B,EAAC,EAAG;AAAlC,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAAmC;AAAA,EAAnC,IAAA;AAAA,EAFZ,MAAA,uBAAa,GAAA,EAAsB;AAAA;AAAA,EAKpD,WAAW,GAAA,EAAsB;AAC/B,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,GAAG,CAAA;AACjC,IAAA,IAAI,KAAA,KAAU,QAAW,OAAO,KAAA;AAChC,IAAA,IAAI,KAAA,CAAM,eAAA,KAAoB,CAAA,EAAG,OAAO,KAAA;AACxC,IAAA,IAAI,IAAA,CAAK,GAAA,EAAI,GAAI,KAAA,CAAM,iBAAiB,OAAO,IAAA;AAE/C,IAAA,KAAA,CAAM,eAAA,GAAkB,CAAA;AACxB,IAAA,KAAA,CAAM,mBAAA,GAAsB,CAAA;AAC5B,IAAA,OAAO,KAAA;AAAA,EACT;AAAA,EAEA,cAAc,GAAA,EAAmB;AAC/B,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,GAAG,CAAA;AACjC,IAAA,IAAI,UAAU,MAAA,EAAW;AACzB,IAAA,KAAA,CAAM,mBAAA,GAAsB,CAAA;AAC5B,IAAA,KAAA,CAAM,eAAA,GAAkB,CAAA;AAAA,EAC1B;AAAA,EAEA,cAAc,GAAA,EAAmB;AAC/B,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,GAAG,KAAK,EAAE,mBAAA,EAAqB,CAAA,EAAG,eAAA,EAAiB,CAAA,EAAE;AACnF,IAAA,KAAA,CAAM,mBAAA,IAAuB,CAAA;AAC7B,IAAA,IAAI,KAAA,CAAM,mBAAA,KAAwB,IAAA,CAAK,IAAA,CAAK,eAAe,oBAAA,CAAA,EAAuB;AAChF,MAAA,KAAA,CAAM,kBAAkB,IAAA,CAAK,GAAA,EAAI,IAAK,IAAA,CAAK,KAAK,UAAA,IAAc,mBAAA,CAAA;AAAA,IAChE;AACA,IAAA,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AAAA,EAC5B;AAAA;AAAA,EAGA,QAAQ,GAAA,EAAiC;AACvC,IAAA,OAAO,IAAA,CAAK,OAAO,GAAA,CAAI,GAAG,KAAK,EAAE,mBAAA,EAAqB,CAAA,EAAG,eAAA,EAAiB,CAAA,EAAE;AAAA,EAC9E;AAAA,EAEQ,GAAA,GAAc;AACpB,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,GAAA,IAAM,IAAK,KAAK,GAAA,EAAI;AAAA,EACvC;AACF;ACpDA,IAAM,cAAA,GAAiB,IAAA;AACvB,IAAM,gBAAA,GAAmB,GAAA;AAoBlB,IAAM,oBAAN,MAAwB;AAAA,EAG7B,WAAA,CAA6B,IAAA,GAAiC,EAAC,EAAG;AAArC,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAAsC;AAAA,EAAtC,IAAA;AAAA,EAFZ,GAAA,uBAAU,GAAA,EAAwB;AAAA,EAInD,GAAA,CACE,QAAA,EACA,SAAA,EACA,SAAA,EACgC;AAChC,IAAA,MAAM,GAAA,GAAM,QAAA,CAAS,QAAA,EAAU,SAAA,EAAW,SAAS,CAAA;AACnD,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA;AAC9B,IAAA,IAAI,KAAA,KAAU,QAAW,OAAO,MAAA;AAChC,IAAA,IAAI,IAAA,CAAK,GAAA,EAAI,IAAK,KAAA,CAAM,WAAA,EAAa;AACnC,MAAA,IAAA,CAAK,GAAA,CAAI,OAAO,GAAG,CAAA;AACnB,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,IAAA,CAAK,GAAA,CAAI,OAAO,GAAG,CAAA;AACnB,IAAA,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AACvB,IAAA,OAAO,KAAA,CAAM,MAAA;AAAA,EACf;AAAA,EAEA,GAAA,CACE,QAAA,EACA,SAAA,EACA,MAAA,EACA,SAAA,EACM;AACN,IAAA,MAAM,GAAA,GAAM,QAAA,CAAS,QAAA,EAAU,SAAA,EAAW,SAAS,CAAA;AACnD,IAAA,IAAI,KAAK,GAAA,CAAI,IAAA,KAAS,IAAA,CAAK,IAAA,CAAK,YAAY,gBAAA,CAAA,EAAmB;AAC7D,MAAA,MAAM,SAAS,IAAA,CAAK,GAAA,CAAI,IAAA,EAAK,CAAE,MAAK,CAAE,KAAA;AACtC,MAAA,IAAI,MAAA,KAAW,MAAA,EAAW,IAAA,CAAK,GAAA,CAAI,OAAO,MAAM,CAAA;AAAA,IAClD;AACA,IAAA,IAAA,CAAK,GAAA,CAAI,IAAI,GAAA,EAAK;AAAA,MAChB,aAAa,IAAA,CAAK,GAAA,EAAI,IAAK,IAAA,CAAK,KAAK,KAAA,IAAS,cAAA,CAAA;AAAA,MAC9C;AAAA,KACD,CAAA;AAAA,EACH;AAAA,EAEA,IAAA,GAAe;AACb,IAAA,OAAO,KAAK,GAAA,CAAI,IAAA;AAAA,EAClB;AAAA,EAEQ,GAAA,GAAc;AACpB,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,GAAA,IAAM,IAAK,KAAK,GAAA,EAAI;AAAA,EACvC;AACF;AAsBA,SAAS,QAAA,CAAS,QAAA,EAAkB,SAAA,EAAmB,GAAA,EAA6B;AAClF,EAAA,MAAM,KAAA,GAAQ,CAAC,SAAA,EAAW,GAAA,EAAK,SAAA,IAAa,EAAA,EAAI,GAAA,EAAK,MAAA,IAAU,EAAA,EAAI,GAAA,EAAK,KAAA,IAAS,EAAA,EAAI,QAAQ,CAAA;AAC7F,EAAA,OAAO,UAAA,CAAW,QAAQ,CAAA,CAAE,MAAA,CAAO,KAAA,CAAM,KAAK,IAAM,CAAC,CAAA,CAAE,MAAA,CAAO,KAAK,CAAA;AACrE;;;ACxGO,IAAM,oCAAA,GAAuC;AAEpD,IAAM,kBAAA,GAA6C;AAAA,EACjD,wBAAA,EAA0B,IAAA;AAAA,EAC1B,wBAAA,EAA0B,IAAA;AAAA,EAC1B,wBAAA,EAA0B;AAC5B,CAAA;AAwBO,IAAM,yCAAA,GAA4E;AAAA,EACvF,EAAA,EAAI,cAAA;AAAA,EACJ,YAAA,EAAc,oCAAA;AAAA,EACd,SAAA,EAAW,QAAA;AAAA,EACX,cAAA,EAAgB,cAAA;AAAA,EAChB,kBAAA,EAAoB,EAAA;AAAA,EACpB,MAAA,EAAQ,CAAC,OAAA,KACP,6BAAA;AAAA,IACE;AAAA,MACE,EAAA,EAAI,cAAA;AAAA,MACJ,cAAA,EAAgB,wCAAA;AAAA,MAChB,SAAA,EAAW,sBAAA;AAAA,MACX,UAAA,EAAY,uBAAA;AAAA,MACZ,YAAA,EAAc,oCAAA;AAAA,MACd,cAAA,EAAgB,+DAAA;AAAA,MAChB,gBAAA,EAAkB,kBAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAKlB,OAAA,EAAS;AAAA,QACP,WAAA,EAAa,CAAC,MAAA,MAAoB,EAAE,WAAW,MAAA,EAAO,CAAA;AAAA,QACtD,MAAM,CAAC,MAAA,EAAgB,MAAA,MAAmC,EAAE,OAAO,MAAA,EAAO;AAAA;AAC5E,KACF;AAAA,IACA;AAAA;AAEN;;;AC/DO,IAAM,8BAAA,GAAiC;AAE9C,IAAMC,mBAAAA,GAA6C;AAAA,EACjD,oBAAA,EAAsB,IAAA;AAAA,EACtB,yBAAA,EAA2B,IAAA;AAAA,EAC3B,0BAAA,EAA4B,GAAA;AAAA,EAC5B,+BAAA,EAAiC;AACnC,CAAA;AAiBO,IAAM,oCAAA,GAAuE;AAAA,EAClF,EAAA,EAAI,QAAA;AAAA,EACJ,YAAA,EAAc,8BAAA;AAAA,EACd,SAAA,EAAW,QAAA;AAAA,EACX,cAAA,EAAgB,QAAA;AAAA,EAChB,kBAAA,EAAoB,EAAA;AAAA,EACpB,MAAA,EAAQ,CAAC,OAAA,KACP,6BAAA;AAAA,IACE;AAAA,MACE,EAAA,EAAI,QAAA;AAAA,MACJ,cAAA,EAAgB,wBAAA;AAAA,MAChB,SAAA,EAAW,gBAAA;AAAA,MACX,YAAA,EAAc,8BAAA;AAAA,MACd,cAAA,EAAgB,WAAA;AAAA,MAChB,gBAAA,EAAkBA,mBAAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAKlB,OAAA,EAAS;AAAA,QACP,IAAA,EAAM,CAAC,KAAA,EAAe,MAAA,MAAmC;AAAA,UACvD,KAAA;AAAA,UACA,KAAA,EAAO,CAAC,GAAG,MAAM,CAAA;AAAA,UACjB,UAAA,EAAY,iBAAA;AAAA,UACZ,eAAA,EAAiB,CAAC,OAAO;AAAA,SAC3B,CAAA;AAAA,QACA,OAAA,EAAS,CAAC,IAAA,KACP,IAAA,CAAiD,UAAA,EAAY;AAAA;AAClE,KACF;AAAA,IACA;AAAA;AAEN;;;ACrDO,IAAM,iCAAA,GAAoC;AAEjD,IAAMA,mBAAAA,GAA6C;AAAA,EACjD,wBAAA,EAA0B,IAAA;AAAA,EAC1B,uBAAA,EAAyB,GAAA;AAAA,EACzB,wBAAA,EAA0B,GAAA;AAAA,EAC1B,aAAA,EAAe,IAAA;AAAA,EACf,sBAAA,EAAwB,IAAA;AAAA,EACxB,qBAAA,EAAuB,GAAA;AAAA,EACvB,gCAAA,EAAkC,IAAA;AAAA,EAClC,wCAAA,EAA0C,GAAA;AAAA,EAC1C,oBAAA,EAAsB,IAAA;AAAA,EACtB,mBAAA,EAAqB;AACvB,CAAA;AAeO,IAAM,uCAAA,GAA0E;AAAA,EACrF,EAAA,EAAI,WAAA;AAAA,EACJ,YAAA,EAAc,iCAAA;AAAA,EACd,SAAA,EAAW,QAAA;AAAA,EACX,cAAA,EAAgB,WAAA;AAAA,EAChB,kBAAA,EAAoB,EAAA;AAAA,EACpB,MAAA,EAAQ,CAAC,OAAA,KACP,6BAAA;AAAA,IACE;AAAA,MACE,EAAA,EAAI,WAAA;AAAA,MACJ,cAAA,EAAgB,2BAAA;AAAA,MAChB,SAAA,EAAW,mBAAA;AAAA,MACX,UAAA,EAAY,wBAAA;AAAA,MACZ,YAAA,EAAc,iCAAA;AAAA,MACd,gBAAA,EAAkBA,mBAAAA;AAAA,MAClB,cAAA,EAAgB;AAAA,KAClB;AAAA,IACA;AAAA;AAEN;;;AC/CO,IAAM,8BAAA,GAAiC;AAE9C,IAAMA,mBAAAA,GAA6C;AAAA,EACjD,oBAAA,EAAsB,GAAA;AAAA,EACtB,eAAA,EAAiB;AACnB,CAAA;AAWO,IAAM,oCAAA,GAAuE;AAAA,EAClF,EAAA,EAAI,QAAA;AAAA,EACJ,YAAA,EAAc,8BAAA;AAAA,EACd,SAAA,EAAW,QAAA;AAAA,EACX,cAAA,EAAgB,QAAA;AAAA,EAChB,kBAAA,EAAoB,EAAA;AAAA,EACpB,MAAA,EAAQ,CAAC,OAAA,KACP,6BAAA;AAAA,IACE;AAAA,MACE,EAAA,EAAI,QAAA;AAAA,MACJ,cAAA,EAAgB,2CAAA;AAAA,MAChB,SAAA,EAAW,gBAAA;AAAA,MACX,YAAA,EAAc,8BAAA;AAAA;AAAA;AAAA,MAGd,cAAA,EAAgB,2BAAA;AAAA,MAChB,gBAAA,EAAkBA;AAAA,KACpB;AAAA,IACA;AAAA;AAEN;;;ACzCO,IAAM,4BAAA,GAA+B;AAE5C,IAAMA,mBAAAA,GAA6C;AAAA,EACjD,oBAAA,EAAsB,IAAA;AAAA,EACtB,4BAAA,EAA8B,GAAA;AAAA,EAC9B,6BAAA,EAA+B;AACjC,CAAA;AAWO,IAAM,kCAAA,GAAqE;AAAA,EAChF,EAAA,EAAI,MAAA;AAAA,EACJ,YAAA,EAAc,4BAAA;AAAA,EACd,SAAA,EAAW,QAAA;AAAA,EACX,cAAA,EAAgB,MAAA;AAAA,EAChB,kBAAA,EAAoB,EAAA;AAAA,EACpB,MAAA,EAAQ,CAAC,OAAA,KACP,6BAAA;AAAA,IACE;AAAA,MACE,EAAA,EAAI,MAAA;AAAA,MACJ,cAAA,EAAgB,qBAAA;AAAA,MAChB,SAAA,EAAW,cAAA;AAAA,MACX,YAAA,EAAc,4BAAA;AAAA,MACd,gBAAA,EAAkBA;AAAA,KACpB;AAAA,IACA;AAAA;AAEN;;;AC/BO,IAAM,+BAAA,GAAkC;AAE/C,IAAMA,mBAAAA,GAA6C;AAAA,EACjD,eAAA,EAAiB;AACnB,CAAA;AAUO,IAAM,qCAAA,GAAwE;AAAA,EACnF,EAAA,EAAI,SAAA;AAAA,EACJ,YAAA,EAAc,+BAAA;AAAA,EACd,SAAA,EAAW,QAAA;AAAA,EACX,cAAA,EAAgB,SAAA;AAAA,EAChB,kBAAA,EAAoB,EAAA;AAAA,EACpB,MAAA,EAAQ,CAAC,OAAA,KACP,6BAAA;AAAA,IACE;AAAA,MACE,EAAA,EAAI,SAAA;AAAA,MACJ,cAAA,EAAgB,wBAAA;AAAA,MAChB,SAAA,EAAW,iBAAA;AAAA,MACX,UAAA,EAAY,sBAAA;AAAA,MACZ,YAAA,EAAc,+BAAA;AAAA,MACd,gBAAA,EAAkBA;AAAA,KACpB;AAAA,IACA;AAAA;AAEN;;;ACFO,IAAM,8BAAA,GAAiC;AAG9C,IAAM,yBAAA,GAA4B,cAAA;AAElC,IAAMA,mBAAAA,GAA6C;AAAA;AAAA,EAEjD,kBAAA,EAAoB,GAAA;AAAA,EACpB,yBAAA,EAA2B,GAAA;AAAA;AAAA,EAE3B,YAAA,EAAc,GAAA;AAAA,EACd,mBAAA,EAAqB,GAAA;AAAA;AAAA,EAErB,WAAA,EAAa,IAAA;AAAA,EACb,kBAAA,EAAoB,IAAA;AAAA,EACpB,QAAA,EAAU,IAAA;AAAA,EACV,eAAA,EAAiB,IAAA;AAAA;AAAA,EAEjB,mBAAA,EAAqB,IAAA;AAAA,EACrB,0BAAA,EAA4B;AAC9B,CAAA;AAkBO,IAAM,oCAAA,GAAuE;AAAA,EAClF,EAAA,EAAI,QAAA;AAAA,EACJ,YAAA,EAAc,8BAAA;AAAA,EACd,SAAA,EAAW,OAAA;AAAA,EACX,cAAA,EAAgB,QAAA;AAAA;AAAA;AAAA,EAGhB,kBAAA,EAAoB,EAAA;AAAA,EACpB,MAAA,EAAQ,CAAC,OAAA,KAAiE;AAIxE,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,IAAU,OAAA,CAAQ,IAAI,cAAA,IAAkB,yBAAA;AAC/D,IAAA,OAAO,6BAAA;AAAA,MACL;AAAA,QACE,EAAA,EAAI,QAAA;AAAA,QACJ,cAAA,EAAgB,wBAAA;AAAA,QAChB,SAAA,EAAW,gBAAA;AAAA,QACX,UAAA,EAAY,aAAA;AAAA,QACZ,YAAA,EAAc,8BAAA;AAAA,QACd,gBAAA,EAAkBA;AAAA,OACpB;AAAA,MACA,EAAE,GAAG,OAAA,EAAS,MAAA;AAAO,KACvB;AAAA,EACF;AACF;;;ACvFO,IAAM,8BAAA,GAAiC;AAE9C,IAAMA,mBAAAA,GAA6C;AAAA,EACjD,wBAAA,EAA0B,IAAA;AAAA,EAC1B,wBAAA,EAA0B,IAAA;AAAA,EAC1B,wBAAA,EAA0B;AAC5B,CAAA;AAqBO,IAAM,oCAAA,GAAuE;AAAA,EAClF,EAAA,EAAI,QAAA;AAAA,EACJ,YAAA,EAAc,8BAAA;AAAA,EACd,SAAA,EAAW,QAAA;AAAA,EACX,cAAA,EAAgB,QAAA;AAAA,EAChB,kBAAA,EAAoB,EAAA;AAAA,EACpB,MAAA,EAAQ,CAAC,OAAA,KACP,6BAAA;AAAA,IACE;AAAA,MACE,EAAA,EAAI,QAAA;AAAA,MACJ,cAAA,EAAgB,wBAAA;AAAA,MAChB,SAAA,EAAW,gBAAA;AAAA,MACX,UAAA,EAAY,qBAAA;AAAA,MACZ,YAAA,EAAc,8BAAA;AAAA,MACd,gBAAA,EAAkBA;AAAA,KACpB;AAAA,IACA;AAAA;AAEN;;;ACjDO,IAAM,kCAAA,GAAqC;AAElD,IAAMA,mBAAAA,GAA6C;AAAA,EACjD,+BAAA,EAAiC,IAAA;AAAA,EACjC,+BAAA,EAAiC,IAAA;AAAA,EACjC,+BAAA,EAAiC,IAAA;AAAA,EACjC,yBAAA,EAA2B;AAC7B,CAAA;AAcO,IAAM,wCAAA,GAA2E;AAAA,EACtF,EAAA,EAAI,YAAA;AAAA,EACJ,YAAA,EAAc,kCAAA;AAAA,EACd,SAAA,EAAW,QAAA;AAAA,EACX,cAAA,EAAgB,YAAA;AAAA,EAChB,kBAAA,EAAoB,EAAA;AAAA,EACpB,MAAA,EAAQ,CAAC,OAAA,KACP,6BAAA;AAAA,IACE;AAAA,MACE,EAAA,EAAI,YAAA;AAAA,MACJ,cAAA,EAAgB,2BAAA;AAAA,MAChB,SAAA,EAAW,oBAAA;AAAA,MACX,UAAA,EAAY,yBAAA;AAAA,MACZ,YAAA,EAAc,kCAAA;AAAA,MACd,gBAAA,EAAkBA;AAAA,KACpB;AAAA,IACA;AAAA;AAEN;;;ACzCO,IAAM,8BAAA,GAAiC;AAE9C,IAAMA,oBAAAA,GAA6C;AAAA,EACjD,eAAA,EAAiB,GAAA;AAAA,EACjB,UAAA,EAAY,IAAA;AAAA,EACZ,gBAAA,EAAkB,IAAA;AAAA,EAClB,eAAA,EAAiB,IAAA;AAAA,EACjB,uBAAA,EAAyB;AAC3B,CAAA;AAWO,IAAM,oCAAA,GAAuE;AAAA,EAClF,EAAA,EAAI,QAAA;AAAA,EACJ,YAAA,EAAc,8BAAA;AAAA,EACd,SAAA,EAAW,QAAA;AAAA,EACX,cAAA,EAAgB,QAAA;AAAA,EAChB,kBAAA,EAAoB,EAAA;AAAA,EACpB,MAAA,EAAQ,CAAC,OAAA,KACP,6BAAA;AAAA,IACE;AAAA,MACE,EAAA,EAAI,QAAA;AAAA,MACJ,cAAA,EAAgB,0BAAA;AAAA,MAChB,SAAA,EAAW,gBAAA;AAAA,MACX,UAAA,EAAY,qBAAA;AAAA,MACZ,YAAA,EAAc,8BAAA;AAAA,MACd,gBAAA,EAAkBA;AAAA,KACpB;AAAA,IACA;AAAA;AAEN;;;ACDO,IAAM,yBAAA,GAA4B;AAAA,EACvC,MAAA,EAAQ,oCAAA;AAAA,EACR,OAAA,EAAS,qCAAA;AAAA,EACT,UAAA,EAAY,wCAAA;AAAA,EACZ,MAAA,EAAQ,oCAAA;AAAA,EACR,SAAA,EAAW,uCAAA;AAAA,EACX,MAAA,EAAQ,oCAAA;AAAA;AAAA,EAER,cAAA,EAAgB,yCAAA;AAAA,EAChB,MAAA,EAAQ,oCAAA;AAAA,EACR,IAAA,EAAM,kCAAA;AAAA,EACN,MAAA,EAAQ;AACV;ACOO,SAAS,aAAA,CAAc,MAAe,IAAA,EAAuC;AAClF,EAAA,OAAOC,QAAAA,CAAS,MAAA,CAAO,IAAA,EAAM,IAAI,CAAA;AACnC;AAOO,SAAS,oBAAA,CAAqB,KAAa,MAAA,EAA8B;AAK9E,EAAA,IAAI,MAAA,CAAO,cAAc,MAAA,EAAW;AAClC,IAAA,OAAOC,OAAA,CAAY,GAAA,EAAK,MAAA,CAAO,SAAS,CAAA;AAAA,EAC1C;AACA,EAAA,MAAM,SAAA,GAAY,kBAAA,CAAmB,MAAA,CAAO,SAAA,IAAa,SAAS,CAAA;AAClE,EAAA,MAAM,KAAA,GAAQ,mBAAmB,MAAA,CAAO,KAAA,IAAS,SAAS,EAAE,MAAA,EAAQ,IAAI,CAAA;AACxE,EAAA,MAAM,MAAA,GAAS,kBAAA,CAAmB,MAAA,CAAO,MAAA,IAAU,SAAS,CAAA;AAC5D,EAAA,OAAO,YAAA,CAAa,KAAK,UAAA,EAAY,QAAA,EAAU,WAAW,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,MAAM,CAAA,KAAA,CAAO,CAAA;AACrF;;;ACpDA,IAAM,aAAA,GAAgB,IAAA;AAMf,SAAS,gBAAgB,OAAA,EAAkD;AAChF,EAAA,IAAI,OAAA,KAAY,QAAW,OAAO,MAAA;AAClC,EAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,GAAA,CAAI,aAAa,CAAA;AACrC,EAAA,IAAI,GAAA,KAAQ,MAAM,OAAO,MAAA;AACzB,EAAA,MAAM,CAAA,GAAI,OAAO,GAAG,CAAA;AACpB,EAAA,IAAI,MAAA,CAAO,SAAS,CAAC,CAAA,IAAK,KAAK,CAAA,EAAG,OAAO,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA;AACpD,EAAA,OAAO,MAAA;AACT;AAQO,SAAS,YAAY,IAAA,EAAwB;AAClD,EAAA,IAAI,IAAA,KAAS,IAAA,IAAQ,IAAA,KAAS,MAAA,EAAW,OAAO,MAAA;AAChD,EAAA,MAAM,IAAI,OAAO,IAAA,KAAS,WAAW,IAAA,GAAO,IAAA,CAAK,UAAU,IAAI,CAAA;AAC/D,EAAA,MAAM,SAAA,GAAY,CAAA,CAAE,MAAA,IAAU,aAAA,GAAgB,CAAA,GAAI,GAAG,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,aAAa,CAAC,CAAA,MAAA,CAAA;AAC9E,EAAA,OAAO,cAAc,SAAS,CAAA;AAChC;AAMO,SAAS,mBAAmB,IAAA,EAOjB;AAChB,EAAA,MAAM,UAAA,GAAa,eAAA,CAAgB,IAAA,CAAK,OAAO,CAAA;AAC/C,EAAA,MAAM,GAAA,GAAM,WAAA,CAAY,IAAA,CAAK,IAAI,CAAA;AACjC,EAAA,OAAO;AAAA,IACL,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,YAAY,IAAA,CAAK,MAAA;AAAA,IACjB,GAAI,UAAA,KAAe,MAAA,GAAY,EAAE,UAAA,KAAe,EAAC;AAAA,IACjD,GAAI,GAAA,KAAQ,MAAA,GAAY,EAAE,GAAA,KAAQ;AAAC,GACrC;AACF;AA4BO,SAAS,yBAAyB,IAAA,EAA6C;AACpF,EAAA,MAAM,EAAE,UAAA,EAAY,MAAA,EAAQ,IAAA,EAAM,OAAA,EAAS,UAAS,GAAI,IAAA;AACxD,EAAA,MAAM,IAAA,GAAO,qBAAA,CAAsB,MAAA,EAAQ,IAAI,CAAA;AAC/C,EAAA,MAAM,OAAA,GAAU,aAAA,CAAc,UAAA,EAAY,MAAA,EAAQ,IAAI,CAAA;AACtD,EAAA,MAAM,WAAW,kBAAA,CAAmB;AAAA,IAClC,QAAA,EAAU,UAAA;AAAA,IACV,QAAA;AAAA,IACA,IAAA;AAAA,IACA,MAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,IAAI,MAAA,KAAW,GAAA,IAAO,MAAA,KAAW,GAAA,EAAK;AACpC,IAAA,OAAO,IAAI,oBAAoB,OAAA,EAAS,EAAE,MAAM,CAAA,EAAG,UAAU,CAAA,YAAA,CAAA,EAAgB,QAAA,EAAU,CAAA;AAAA,EACzF;AACA,EAAA,IAAI,WAAW,GAAA,EAAK;AAClB,IAAA,OAAO,IAAI,eAAe,OAAA,EAAS,EAAE,MAAM,CAAA,EAAG,UAAU,CAAA,WAAA,CAAA,EAAe,QAAA,EAAU,CAAA;AAAA,EACnF;AACA,EAAA,IAAI,WAAW,GAAA,EAAK;AAClB,IAAA,OAAO,IAAI,kBAAA,CAAmB,OAAA,EAAS,EAAE,IAAA,EAAM,CAAA,EAAG,UAAU,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA,EAAI,QAAA,EAAU,CAAA;AAAA,EACpF;AACA,EAAA,IAAI,WAAW,GAAA,EAAK;AAClB,IAAA,OAAO,IAAI,aAAa,OAAA,EAAS,EAAE,MAAM,CAAA,EAAG,UAAU,CAAA,QAAA,CAAA,EAAY,QAAA,EAAU,CAAA;AAAA,EAC9E;AACA,EAAA,IAAI,MAAA,IAAU,GAAA,IAAO,MAAA,GAAS,GAAA,EAAK;AACjC,IAAA,OAAO,IAAI,aAAa,OAAA,EAAS,EAAE,MAAM,CAAA,EAAG,UAAU,CAAA,aAAA,CAAA,EAAiB,QAAA,EAAU,CAAA;AAAA,EACnF;AACA,EAAA,OAAO,IAAI,kBAAkB,OAAA,EAAS,EAAE,MAAM,CAAA,EAAG,UAAU,CAAA,QAAA,CAAA,EAAY,QAAA,EAAU,CAAA;AACnF;AAEA,SAAS,uBAAuB,IAAA,EAAmC;AACjE,EAAA,IAAI,IAAA,KAAS,IAAA,IAAQ,OAAO,IAAA,KAAS,UAAU,OAAO,MAAA;AACtD,EAAA,MAAM,MAAO,IAAA,CAAwD,KAAA;AACrE,EAAA,IAAI,GAAA,KAAQ,MAAA,IAAa,GAAA,KAAQ,IAAA,EAAM,OAAO,MAAA;AAC9C,EAAA,IAAI,OAAO,GAAA,CAAI,IAAA,KAAS,QAAA,SAAiB,GAAA,CAAI,IAAA;AAC7C,EAAA,IAAI,OAAO,GAAA,CAAI,IAAA,KAAS,QAAA,SAAiB,GAAA,CAAI,IAAA;AAC7C,EAAA,OAAO,MAAA;AACT;AAGA,SAAS,qBAAA,CAAsB,QAAgB,IAAA,EAA0B;AACvE,EAAA,MAAM,OAAA,GAAU,sBAAA,CAAuB,IAAI,CAAA,EAAG,aAAY,IAAK,EAAA;AAE/D,EAAA,IACE,OAAA,CAAQ,QAAA,CAAS,gBAAgB,CAAA,IACjC,QAAQ,QAAA,CAAS,gBAAgB,CAAA,IACjC,OAAA,CAAQ,SAAS,iBAAiB,CAAA,IAClC,OAAA,CAAQ,QAAA,CAAS,YAAY,CAAA,EAC7B;AACA,IAAA,OAAO,kBAAA;AAAA,EACT;AACA,EAAA,IACE,OAAA,CAAQ,QAAA,CAAS,gBAAgB,CAAA,IACjC,OAAA,CAAQ,QAAA,CAAS,gBAAgB,CAAA,IACjC,OAAA,CAAQ,QAAA,CAAS,QAAQ,CAAA,EACzB;AACA,IAAA,OAAO,kBAAA;AAAA,EACT;AACA,EAAA,IACE,OAAA,CAAQ,QAAA,CAAS,iBAAiB,CAAA,IAClC,OAAA,CAAQ,QAAA,CAAS,mBAAmB,CAAA,IACpC,OAAA,CAAQ,QAAA,CAAS,eAAe,CAAA,EAChC;AACA,IAAA,OAAO,mBAAA;AAAA,EACT;AAGA,EAAA,IACE,MAAA,KAAW,OACX,OAAA,CAAQ,QAAA,CAAS,oBAAoB,CAAA,IACrC,OAAA,CAAQ,QAAA,CAAS,gBAAgB,CAAA,EACjC;AACA,IAAA,OAAO,gBAAA;AAAA,EACT;AAEA,EAAA,IAAI,MAAA,KAAW,GAAA,IAAO,MAAA,KAAW,GAAA,EAAK,OAAO,aAAA;AAC7C,EAAA,IAAI,MAAA,KAAW,KAAK,OAAO,YAAA;AAC3B,EAAA,IAAI,MAAA,KAAW,KAAK,OAAO,SAAA;AAC3B,EAAA,IAAI,MAAA,KAAW,KAAK,OAAO,iBAAA;AAC3B,EAAA,IAAI,MAAA,IAAU,GAAA,IAAO,MAAA,GAAS,GAAA,EAAK,OAAO,cAAA;AAC1C,EAAA,OAAO,SAAA;AACT;AAEA,SAAS,aAAA,CAAc,UAAA,EAAoB,MAAA,EAAgB,IAAA,EAAyB;AAClF,EAAA,OAAO,CAAA,EAAG,UAAU,CAAA,YAAA,EAAe,IAAI,UAAU,MAAM,CAAA,CAAA,CAAA;AACzD;ACtJA,IAAM,aAAA,GAAgB,UAAA;AAUf,SAAS,wBACd,OAAA,EACmB;AACnB,EAAA,MAAM,EAAE,IAAA,EAAM,UAAA,EAAW,GAAI,OAAA;AAC7B,EAAA,kBAAA,CAAmB,UAAU,CAAA;AAC7B,EAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAI,UAAU,CAAA;AAElC,EAAA,SAAS,YAAY,QAAA,EAAwB;AAC3C,IAAA,IAAI,CAAC,OAAA,CAAQ,GAAA,CAAI,QAAQ,CAAA,EAAG;AAC1B,MAAA,MAAM,IAAIC,kBAAAA;AAAA,QACR,CAAA,0CAAA,EAA6C,KAAK,SAAA,CAAU,QAAQ,CAAC,CAAA,YAAA,EAAe,UAAA,CAAW,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,CAAA;AAAA,QACzG,EAAE,MAAM,kBAAA;AAAmB,OAC7B;AAAA,IACF;AAAA,EACF;AAEA,EAAA,SAAS,aAAa,QAAA,EAA0B;AAC9C,IAAA,OAAOC,aAAa,IAAA,EAAM,CAAA,EAAGC,kBAAAA,CAAmB,QAAQ,CAAC,CAAA,GAAA,CAAK,CAAA;AAAA,EAChE;AAEA,EAAA,eAAe,GAAA,CAAI,UAAkB,IAAA,EAA6B;AAChE,IAAA,WAAA,CAAY,QAAQ,CAAA;AAKpB,IAAA,MAAM,OAAA,GAAU,UAAA,CAAW,aAAA,CAAc,IAAI,CAAC,CAAA;AAC9C,IAAA,MAAM,IAAA,GAAOA,mBAAmB,QAAQ,CAAA;AACxC,IAAA,MAAM,aAAa,CAAA,OAAA,EAAU,IAAI,CAAA,CAAA,EAAI,IAAI,IAAI,YAAY;AACvD,MAAA,MAAM,IAAA,GAAOD,YAAAA,CAAa,IAAA,EAAM,CAAA,EAAG,IAAI,CAAA,GAAA,CAAK,CAAA;AAC5C,MAAA,MAAM,MAAO,MAAM,eAAA,CAAgB,IAAI,CAAA,IAAM,OAAO,QAAQ,CAAA;AAC5D,MAAA,MAAME,KAAAA,CAAM,IAAA,EAAM,EAAE,SAAA,EAAW,MAAM,CAAA;AACrC,MAAA,MAAMC,iBAAAA,CAAkB,IAAA,EAAM,YAAA,CAAa,GAAA,EAAK,OAAO,CAAC,CAAA;AAAA,IAC1D,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,eAAe,KAAK,QAAA,EAA+C;AACjE,IAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,MAAA,WAAA,CAAY,QAAQ,CAAA;AACpB,MAAA,OAAO,YAAA,CAAa,YAAA,CAAa,QAAQ,CAAA,EAAG,QAAQ,CAAA;AAAA,IACtD;AACA,IAAA,MAAM,MAAyB,EAAC;AAChC,IAAA,KAAA,MAAW,KAAK,UAAA,EAAY;AAC1B,MAAA,GAAA,CAAI,IAAA,CAAK,GAAI,MAAM,YAAA,CAAa,aAAa,CAAC,CAAA,EAAG,CAAC,CAAE,CAAA;AAAA,IACtD;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AAEA,EAAA,OAAO,EAAE,UAAA,EAAY,CAAC,GAAG,UAAU,CAAA,EAAG,KAAK,IAAA,EAAK;AAClD;AAEA,SAAS,mBAAmB,UAAA,EAAqC;AAC/D,EAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC3B,IAAA,MAAM,IAAIJ,mBAAmB,uDAAA,EAAyD;AAAA,MACpF,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AACA,EAAA,IAAI,IAAI,GAAA,CAAI,UAAU,CAAA,CAAE,IAAA,KAAS,WAAW,MAAA,EAAQ;AAClD,IAAA,MAAM,IAAIA,mBAAmB,oDAAA,EAAsD;AAAA,MACjF,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AACA,EAAA,MAAM,YAAY,UAAA,CAAW,GAAA,CAAI,CAAC,CAAA,KAAM,WAAA,CAAY,CAAC,CAAC,CAAA;AACtD,EAAA,IAAI,IAAI,GAAA,CAAI,SAAS,CAAA,CAAE,IAAA,KAAS,WAAW,MAAA,EAAQ;AACjD,IAAA,MAAM,IAAIA,kBAAAA;AAAA,MACR,uFAAA;AAAA,MACA,EAAE,MAAM,oBAAA;AAAqB,KAC/B;AAAA,EACF;AACF;AAEA,SAAS,YAAY,QAAA,EAA0B;AAC7C,EAAA,IAAI;AACF,IAAA,OAAOE,mBAAmB,QAAQ,CAAA;AAAA,EACpC,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,IAAIF,kBAAAA;AAAA,MACR,CAAA,kCAAA,EAAqC,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAC,CAAA,0BAAA,CAAA;AAAA,MAC7D,EAAE,IAAA,EAAM,oBAAA,EAAsB,KAAA;AAAM,KACtC;AAAA,EACF;AACF;AAEA,SAAS,OAAO,QAAA,EAA0B;AACxC,EAAA,OAAO,CAAA;AAAA,UAAA,EAAkB,QAAQ;AAAA;;AAAA,EAAY,aAAa;AAAA,CAAA;AAC5D;AAEA,eAAe,gBAAgB,IAAA,EAA+B;AAC5D,EAAA,IAAI;AACF,IAAA,OAAO,MAAMK,QAAAA,CAAS,IAAA,EAAM,MAAM,CAAA;AAAA,EACpC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAA;AAAA,EACT;AACF;AAEA,eAAe,YAAA,CAAa,MAAc,QAAA,EAA8C;AACtF,EAAA,MAAM,GAAA,GAAM,MAAM,eAAA,CAAgB,IAAI,CAAA;AACtC,EAAA,OAAO,gBAAA,CAAiB,GAAG,CAAA,CAAE,GAAA,CAAI,CAAC,IAAA,MAAU,EAAE,IAAA,EAAM,UAAA,CAAW,IAAI,CAAA,EAAG,QAAA,EAAS,CAAE,CAAA;AACnF;AAOA,SAAS,WAAW,IAAA,EAAsB;AACxC,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,KAAA,EAAO,MAAM,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,KAAK,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,KAAK,CAAA;AAC/E;AAOA,SAAS,WAAW,IAAA,EAAsB;AACxC,EAAA,OAAO,IAAA,CAAK,OAAA;AAAA,IAAQ,QAAA;AAAA,IAAU,CAAC,QAAQ,IAAA,KACrC,IAAA,KAAS,MAAM,IAAA,GAAO,IAAA,KAAS,MAAM,IAAA,GAAO;AAAA,GAC9C;AACF;AAGA,SAAS,iBAAiB,GAAA,EAAuB;AAC/C,EAAA,MAAM,GAAA,GAAM,GAAA,CAAI,OAAA,CAAQ,aAAa,CAAA;AACrC,EAAA,IAAI,GAAA,KAAQ,EAAA,EAAI,OAAO,EAAC;AACxB,EAAA,MAAM,IAAA,GAAO,GAAA,CAAI,KAAA,CAAM,GAAA,GAAM,cAAc,MAAM,CAAA;AACjD,EAAA,MAAM,WAAA,GAAc,IAAA,CAAK,MAAA,CAAO,YAAY,CAAA;AAC5C,EAAA,MAAM,QAAQ,WAAA,KAAgB,EAAA,GAAK,OAAO,IAAA,CAAK,KAAA,CAAM,GAAG,WAAW,CAAA;AACnE,EAAA,OAAO,KAAA,CACJ,KAAA,CAAM,IAAI,CAAA,CACV,GAAA,CAAI,CAAC,IAAA,KAAS,IAAA,CAAK,IAAA,EAAM,CAAA,CACzB,MAAA,CAAO,CAAC,IAAA,KAAS,IAAA,CAAK,UAAA,CAAW,IAAI,CAAC,CAAA,CACtC,GAAA,CAAI,CAAC,IAAA,KAAS,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,CAAE,IAAA,EAAM,CAAA;AACvC;AAGA,SAAS,YAAA,CAAa,KAAa,IAAA,EAAsB;AACvD,EAAA,MAAM,MAAA,GAAS,KAAK,IAAI,CAAA,CAAA;AACxB,EAAA,MAAM,GAAA,GAAM,GAAA,CAAI,OAAA,CAAQ,aAAa,CAAA;AACrC,EAAA,IAAI,QAAQ,EAAA,EAAI;AACd,IAAA,MAAM,GAAA,GAAM,GAAA,CAAI,QAAA,CAAS,IAAI,IAAI,EAAA,GAAK,IAAA;AACtC,IAAA,OAAO,CAAA,EAAG,GAAG,CAAA,EAAG,GAAG,GAAG,aAAa;;AAAA,EAAO,MAAM;AAAA,CAAA;AAAA,EAClD;AACA,EAAA,MAAM,KAAA,GAAQ,MAAM,aAAA,CAAc,MAAA;AAClC,EAAA,MAAM,cAAc,GAAA,CAAI,KAAA,CAAM,KAAK,CAAA,CAAE,OAAO,YAAY,CAAA;AACxD,EAAA,IAAI,gBAAgB,EAAA,EAAI;AACtB,IAAA,MAAM,QAAA,GAAW,GAAA,CAAI,QAAA,CAAS,IAAI,IAAI,EAAA,GAAK,IAAA;AAC3C,IAAA,OAAO,CAAA,EAAG,GAAG,CAAA,EAAG,QAAQ,GAAG,MAAM;AAAA,CAAA;AAAA,EACnC;AACA,EAAA,MAAM,WAAW,KAAA,GAAQ,WAAA;AACzB,EAAA,OAAO,CAAA,EAAG,GAAA,CAAI,KAAA,CAAM,CAAA,EAAG,QAAQ,CAAC;AAAA,EAAK,MAAM,CAAA,EAAG,GAAA,CAAI,KAAA,CAAM,QAAQ,CAAC,CAAA,CAAA;AACnE;AC3KO,SAAS,UAAU,GAAA,EAAqB;AAC7C,EAAA,OAAOV,IAAAA,CAAK,SAAA,CAAU,GAAG,CAAA,EAAG,gBAAgB,CAAA;AAC9C;AAOO,SAAS,iBAAiB,KAAA,EAA2B;AAC1D,EAAA,MAAM,QAAQ,IAAI,IAAA,CAAK,KAAA,CAAM,WAAW,EAAE,WAAA,EAAY;AACtD,EAAA,MAAM,OAAO,SAAA,CAAU,KAAK,CAAA,CAAE,KAAA,CAAM,GAAG,CAAC,CAAA;AACxC,EAAA,OAAO;AAAA,IACL,MAAM,KAAK,CAAA,CAAA;AAAA,IACX,EAAA;AAAA,IACA,iBAAiB,IAAI,CAAA,CAAA;AAAA,IACrB,CAAA,gBAAA,EAAmB,MAAM,WAAW,CAAA,CAAA;AAAA,IACpC,CAAA,eAAA,EAAkB,MAAM,UAAU,CAAA,CAAA;AAAA,IAClC,CAAA,sBAAA,EAAyB,MAAM,iBAAiB,CAAA,CAAA;AAAA,IAChD,CAAA,oBAAA,EAAuB,MAAM,eAAe,CAAA,CAAA;AAAA,IAC5C,CAAA,iBAAA,EAAoB,MAAM,YAAY,CAAA,CAAA;AAAA,IACtC;AAAA,GACF,CAAE,KAAK,IAAI,CAAA;AACb;AAeA,eAAsB,gBAAA,CAAiB,KAAa,KAAA,EAAkC;AACpF,EAAA,MAAM,IAAA,GAAO,UAAU,GAAG,CAAA;AAC1B,EAAA,IAAI,GAAA,GAAM,EAAA;AACV,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,MAAMU,QAAAA,CAAS,IAAA,EAAM,MAAM,CAAA;AAAA,EACnC,CAAA,CAAA,MAAQ;AACN,IAAA,GAAA,GAAM,mBAAA;AAAA,EACR;AACA,EAAA,MAAM,IAAA,GAAO,GAAG,GAAA,CAAI,QAAA,CAAS,IAAI,CAAA,GAAI,GAAA,GAAM,GAAG,GAAG;AAAA,CAAI,CAAA,EAAG,gBAAA,CAAiB,KAAK,CAAC,CAAA,CAAA;AAC/E,EAAA,MAAMD,iBAAAA,CAAkB,MAAM,IAAI,CAAA;AACpC;AAUO,SAAS,UAAU,KAAA,EAA2B;AACnD,EAAA,OAAOE,UAAAA,CAAW,QAAQ,CAAA,CACvB,MAAA;AAAA,IACC;AAAA,MACE,KAAA,CAAM,WAAA;AAAA,MACN,KAAA,CAAM,UAAA;AAAA,MACN,KAAA,CAAM,iBAAA;AAAA,MACN,KAAA,CAAM,eAAA;AAAA,MACN,KAAA,CAAM;AAAA,KACR,CAAE,KAAK,GAAG;AAAA,GACZ,CACC,OAAO,KAAK,CAAA;AACjB;;;AC9DA,IAAM,uBAAA,GAA0B,IAAA;AAChC,IAAM,yBAAA,GAA4B,IAAA;AAGlC,eAAsB,UAAA,CACpB,KAAA,EACA,SAAA,EACA,SAAA,GAAoB,uBAAA,EACE;AACtB,EAAA,IAAI,KAAA,CAAM,MAAA,IAAU,CAAA,EAAG,OAAO,EAAE,IAAA,EAAM,CAAC,GAAG,KAAK,CAAA,EAAG,iBAAA,EAAmB,CAAA,EAAE;AACvE,EAAA,MAAM,OAAA,GAAU,MAAM,SAAA,CAAU,KAAA,CAAM,KAAA,CAAM,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAC,CAAA;AAC9D,EAAA,MAAM,UAAoB,EAAC;AAC3B,EAAA,MAAM,WAAuB,EAAC;AAC9B,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,CAAC,CAAA,IAAK,EAAC;AAC3B,IAAA,MAAM,KAAA,GAAQ,SAAS,IAAA,CAAK,CAACC,UAAS,gBAAA,CAAiB,GAAA,EAAKA,KAAI,CAAA,IAAK,SAAS,CAAA;AAC9E,IAAA,IAAI,KAAA,EAAO;AACX,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AACd,IAAA,QAAA,CAAS,KAAK,GAAG,CAAA;AAAA,EACnB;AACA,EAAA,MAAM,OAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,KAAA,CAAM,CAAC,CAAe,CAAA;AACtD,EAAA,OAAO,EAAE,IAAA,EAAM,iBAAA,EAAmB,KAAA,CAAM,MAAA,GAAS,KAAK,MAAA,EAAO;AAC/D;AASA,IAAM,2BAAA,GAA8B,GAAA;AAGpC,eAAsB,SACpB,KAAA,EACA,SAAA,EACA,SAAA,GAAoB,yBAAA,EACpB,mBAA2B,2BAAA,EACH;AACxB,EAAA,IAAI,MAAM,MAAA,KAAW,CAAA,SAAU,EAAE,QAAA,EAAU,EAAC,EAAE;AAE9C,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,GAAS,gBAAA,GAAmB,MAAM,KAAA,CAAM,CAAA,EAAG,gBAAgB,CAAA,GAAI,KAAA;AACpF,EAAA,MAAM,OAAA,GAAU,MAAM,SAAA,CAAU,KAAA,CAAM,MAAA,CAAO,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAC,CAAA;AAC/D,EAAA,MAAM,YAAA,GAAe,gBAAA,CAAiB,OAAA,EAAS,SAAS,CAAA;AACxD,EAAA,MAAM,MAAA,GAAS,wBAAA,CAAyB,MAAA,EAAQ,YAAY,CAAA;AAC5D,EAAA,OAAO,EAAE,QAAA,EAAU,CAAC,GAAG,MAAA,CAAO,QAAQ,CAAA,CAAE,GAAA,CAAI,uBAAuB,CAAA,EAAE;AACvE;AAEA,SAAS,gBAAA,CACP,SACA,SAAA,EACU;AACV,EAAA,MAAM,eAAe,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,EAAG,MAAM,CAAC,CAAA;AAC5C,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,OAAA,CAAQ,QAAQ,CAAA,EAAA,EAAK;AACvC,IAAA,KAAA,IAAS,IAAI,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,OAAA,CAAQ,QAAQ,CAAA,EAAA,EAAK;AAC3C,MAAA,IAAI,gBAAA,CAAiB,OAAA,CAAQ,CAAC,CAAA,IAAK,EAAC,EAAG,OAAA,CAAQ,CAAC,CAAA,IAAK,EAAE,CAAA,IAAK,SAAA,EAAW;AACrE,QAAA,aAAA,CAAc,YAAA,EAAc,GAAG,CAAC,CAAA;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,YAAA;AACT;AAEA,SAAS,wBAAA,CACP,OACA,YAAA,EAC2B;AAC3B,EAAA,MAAM,MAAA,uBAAa,GAAA,EAA0B;AAC7C,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,MAAM,IAAA,GAAO,QAAA,CAAS,YAAA,EAAc,CAAC,CAAA;AACrC,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,GAAA,CAAI,IAAI,KAAK,EAAC;AAClC,IAAA,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,CAAC,CAAe,CAAA;AAChC,IAAA,MAAA,CAAO,GAAA,CAAI,MAAM,IAAI,CAAA;AAAA,EACvB;AACA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,wBAAwB,OAAA,EAA6C;AAC5E,EAAA,MAAM,MAAA,GAAS,CAAC,GAAG,OAAO,EAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,IAAA,CAAK,MAAA,GAAS,CAAA,CAAE,KAAK,MAAM,CAAA;AACxE,EAAA,OAAO,EAAE,kBAAA,EAAoB,MAAA,CAAO,CAAC,CAAA,EAAG,IAAA,IAAQ,IAAI,OAAA,EAAQ;AAC9D;AAGO,SAAS,SAAA,CAAU,UAAkC,WAAA,EAA6B;AACvF,EAAA,IAAI,QAAA,CAAS,MAAA,KAAW,CAAA,EAAG,OAAO,EAAA;AAClC,EAAA,MAAM,QAAA,GAAW,IAAI,IAAA,CAAK,WAAW,EAAE,WAAA,EAAY;AACnD,EAAA,MAAM,KAAA,GAAkB,CAAC,CAAA,UAAA,EAAa,QAAQ,IAAI,EAAE,CAAA;AACpD,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,QAAA,CAAS,QAAQ,CAAA,EAAA,EAAK;AACxC,IAAA,MAAM,CAAA,GAAI,SAAS,CAAC,CAAA;AACpB,IAAA,IAAI,MAAM,MAAA,EAAW;AACrB,IAAA,KAAA,CAAM,KAAK,CAAA,WAAA,EAAc,CAAA,GAAI,CAAC,CAAA,EAAA,EAAK,CAAA,CAAE,kBAAkB,CAAA,CAAE,CAAA;AACzD,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,IAAA,KAAA,MAAW,MAAA,IAAU,EAAE,OAAA,EAAS,KAAA,CAAM,KAAK,CAAA,EAAA,EAAK,MAAA,CAAO,IAAI,CAAA,CAAE,CAAA;AAC7D,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAAA,EACf;AACA,EAAA,OAAO,CAAA,EAAG,KAAA,CAAM,IAAA,CAAK,IAAI,CAAC;AAAA,CAAA;AAC5B;AAEA,SAAS,gBAAA,CAAiB,GAA0B,CAAA,EAAkC;AACpF,EAAA,IAAI,CAAA,CAAE,MAAA,KAAW,CAAA,IAAK,CAAA,CAAE,MAAA,KAAW,KAAK,CAAA,CAAE,MAAA,KAAW,CAAA,CAAE,MAAA,EAAQ,OAAO,CAAA;AACtE,EAAA,IAAI,GAAA,GAAM,CAAA;AACV,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,CAAE,QAAQ,CAAA,EAAA,EAAK;AACjC,IAAA,MAAM,EAAA,GAAK,CAAA,CAAE,CAAC,CAAA,IAAK,CAAA;AACnB,IAAA,MAAM,EAAA,GAAK,CAAA,CAAE,CAAC,CAAA,IAAK,CAAA;AACnB,IAAA,GAAA,IAAO,EAAA,GAAK,EAAA;AACZ,IAAA,KAAA,IAAS,EAAA,GAAK,EAAA;AACd,IAAA,KAAA,IAAS,EAAA,GAAK,EAAA;AAAA,EAChB;AACA,EAAA,MAAM,QAAQ,IAAA,CAAK,IAAA,CAAK,KAAK,CAAA,GAAI,IAAA,CAAK,KAAK,KAAK,CAAA;AAChD,EAAA,OAAO,KAAA,KAAU,CAAA,GAAI,CAAA,GAAI,GAAA,GAAM,KAAA;AACjC;AAEA,SAAS,QAAA,CAAS,SAAmB,CAAA,EAAmB;AACtD,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,OAAO,OAAA,CAAQ,IAAI,CAAA,KAAM,IAAA,EAAM;AAC7B,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,IAAI,CAAA,IAAK,IAAA;AAC9B,IAAA,IAAI,SAAS,IAAA,EAAM;AACnB,IAAA,IAAA,GAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAA,CAAQ,CAAC,CAAA,GAAI,IAAA;AACb,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,aAAA,CAAc,OAAA,EAAmB,CAAA,EAAW,CAAA,EAAiB;AACpE,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,OAAA,EAAS,CAAC,CAAA;AACjC,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,OAAA,EAAS,CAAC,CAAA;AACjC,EAAA,IAAI,KAAA,KAAU,KAAA,EAAO,OAAA,CAAQ,KAAK,CAAA,GAAI,KAAA;AACxC;AC5FO,SAAS,iBAAiB,OAAA,EAAmD;AAClF,EAAA,OAAOC,YAAAA,CAAa,SAAS,OAAA,CAAQ,GAAG,IAAI,MAAM,QAAA,CAAS,OAAO,CAAC,CAAA;AACrE;AAEA,eAAe,SAAS,OAAA,EAAmD;AACzE,EAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,GAAA,IAAO,IAAA,CAAK,GAAA;AAChC,EAAA,MAAM,cAAc,GAAA,EAAI;AACxB,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,GAAQ,MAAM,qBAAA,CAAsB,OAAA,CAAQ,GAAG,CAAA;AACrD,IAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,MAAA,OAAO,YAAY,SAAS,CAAA;AAAA,IAC9B;AACA,IAAA,MAAM,QAAQ,MAAM,UAAA,CAAW,OAAO,OAAA,CAAQ,SAAA,EAAW,QAAQ,cAAc,CAAA;AAC/E,IAAA,MAAM,GAAA,GAAM,MAAM,QAAA,CAAS,KAAA,CAAM,MAAM,OAAA,CAAQ,SAAA,EAAW,QAAQ,gBAAgB,CAAA;AAClF,IAAA,MAAM,eAAe,MAAM,sBAAA,CAAuB,QAAQ,GAAA,EAAK,GAAA,CAAI,UAAU,WAAW,CAAA;AACxF,IAAA,MAAM,MAAA,GAAyB;AAAA,MAC7B,MAAA,EAAQ,IAAA;AAAA,MACR,aAAa,KAAA,CAAM,MAAA;AAAA,MACnB,UAAA,EAAY,MAAM,IAAA,CAAK,MAAA;AAAA,MACvB,mBAAmB,KAAA,CAAM,iBAAA;AAAA,MACzB,eAAA,EAAiB,IAAI,QAAA,CAAS,MAAA;AAAA,MAC9B,YAAA;AAAA,MACA,cAAA,EAAgB,KAAA;AAAA,KAClB;AACA,IAAA,MAAM,gBAAA,CAAiB,QAAQ,GAAA,EAAK;AAAA,MAClC,WAAA;AAAA,MACA,aAAa,MAAA,CAAO,WAAA;AAAA,MACpB,YAAY,MAAA,CAAO,UAAA;AAAA,MACnB,mBAAmB,MAAA,CAAO,iBAAA;AAAA,MAC1B,iBAAiB,MAAA,CAAO,eAAA;AAAA,MACxB,cAAc,MAAA,CAAO;AAAA,KACtB,CAAA;AACD,IAAA,OAAO,MAAA;AAAA,EACT,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,UAAU,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AACrE,IAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,qCAAA,EAAwC,OAAO;AAAA,CAAI,CAAA;AACxE,IAAA,OAAO,YAAY,OAAO,CAAA;AAAA,EAC5B;AACF;AAEA,eAAe,sBAAA,CACb,GAAA,EACA,QAAA,EACA,WAAA,EACiB;AACjB,EAAA,IAAI,QAAA,CAAS,MAAA,KAAW,CAAA,EAAG,OAAO,CAAA;AAClC,EAAA,MAAMC,SAAAA,GAAWd,IAAAA,CAAK,SAAA,CAAU,GAAG,GAAG,OAAO,CAAA;AAC7C,EAAA,MAAMQ,KAAAA,CAAMM,SAAAA,EAAU,EAAE,SAAA,EAAW,MAAM,CAAA;AACzC,EAAA,MAAM,OAAA,GAAU,IAAI,IAAA,CAAK,WAAW,EAAE,WAAA,EAAY,CAAE,OAAA,CAAQ,SAAA,EAAW,GAAG,CAAA;AAC1E,EAAA,MAAM,IAAA,GAAOd,IAAAA,CAAKc,SAAAA,EAAU,CAAA,QAAA,EAAW,OAAO,CAAA,GAAA,CAAK,CAAA;AACnD,EAAA,MAAM,IAAA,GAAO,SAAA,CAAU,QAAA,EAAU,WAAW,CAAA;AAC5C,EAAA,MAAML,iBAAAA,CAAkB,MAAM,IAAI,CAAA;AAClC,EAAA,OAAO,CAAA;AACT;AAEA,SAAS,YAAY,MAAA,EAA6C;AAChE,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,WAAA,EAAa,CAAA;AAAA,IACb,UAAA,EAAY,CAAA;AAAA,IACZ,iBAAA,EAAmB,CAAA;AAAA,IACnB,eAAA,EAAiB,CAAA;AAAA,IACjB,YAAA,EAAc,CAAA;AAAA,IACd,cAAA,EAAgB;AAAA,GAClB;AACF;;;ACpIO,IAAM,iBAAA,GAA2C;AAAA,EACtD,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,CAAA;AAAA,EAQA,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,CAAA;AAAA,EASA,CAAA;AAAA;AAAA;AAAA;AAAA,IAAA,CAAA;AAAA,EAKA,CAAA;AAAA;AAAA,MAAA,CAAA;AAAA,EAGA,CAAA;AAAA;AAAA,MAAA,CAAA;AAAA,EAGA,CAAA;AAAA;AAAA;AAAA,IAAA,CAAA;AAAA,EAIA,CAAA,gEAAA;AACF;AAOO,IAAM,iBAAA,GAA2C;AAAA,EACtD,2BAAA;AAAA,EACA;AACF;;;ACGA,eAAsB,aAAa,IAAA,EAAwC;AACzE,EAAA,OAAO,mBAAA,CAA8B;AAAA,IACnC,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,KAAA,EAAO,cAAA;AAAA,IACP,gBAAgB,IAAA,CAAK,cAAA;AAAA,IACrB,MAAA,EAAQ,CAAC,EAAA,KAAO;AAEd,MAAA,KAAA,MAAW,MAAA,IAAU,iBAAA,EAAmB,EAAA,CAAG,IAAA,CAAK,MAAM,CAAA;AACtD,MAAA,KAAA,MAAW,IAAA,IAAQ,iBAAA,EAAmB,EAAA,CAAG,IAAA,CAAK,IAAI,CAAA;AAAA,IACpD;AAAA,GACD,CAAA;AACH;AAQO,SAAS,iBAAiB,GAAA,EAAqB;AACpD,EAAA,OAAOT,IAAAA,CAAK,GAAA,EAAK,UAAA,EAAY,QAAA,EAAU,UAAU,eAAe,CAAA;AAClE;ACvBA,IAAM,UAAA,GAAa,uBAAA;AA0BZ,SAAS,aAAA,CAAc,IAAA,EAAc,OAAA,GAAgC,EAAC,EAAkB;AAC7F,EAAA,MAAM,QAAA,GAAW,QAAQ,QAAA,IAAY,GAAA;AACrC,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,EAAC;AAC/B,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC7B,EAAA,MAAM,GAAA,GAAwB,EAAE,MAAA,EAAQ,EAAC,EAAG,KAAA,EAAO,EAAC,EAAG,KAAA,EAAO,CAAA,EAAG,OAAA,EAAS,MAAA,EAAU;AACpF,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,CAAC,CAAA,IAAK,EAAA;AACzB,IAAA,MAAM,aAAa,CAAA,GAAI,CAAA;AACvB,IAAA,WAAA,CAAY,GAAA,EAAK,IAAA,EAAM,UAAA,EAAY,QAAQ,CAAA;AAAA,EAC7C;AACA,EAAA,gBAAA,CAAiB,GAAA,EAAK,KAAA,CAAM,MAAA,EAAQ,QAAQ,CAAA;AAC5C,EAAA,OAAO,GAAA,CAAI,MAAA;AACb;AAEA,SAAS,WAAA,CACP,GAAA,EACA,IAAA,EACA,UAAA,EACA,QAAA,EACM;AACN,EAAA,MAAM,YAAA,GAAe,UAAA,CAAW,IAAA,CAAK,IAAI,CAAA;AACzC,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,IAAA,EAAK,CAAE,MAAA,KAAW,CAAA;AACvC,EAAA,IAAI,YAAA,KAAiB,IAAA,IAAQ,GAAA,CAAI,KAAA,CAAM,SAAS,CAAA,EAAG;AACjD,IAAA,gBAAA,CAAiB,GAAA,EAAK,UAAA,GAAa,CAAA,EAAG,QAAQ,CAAA;AAAA,EAChD;AACA,EAAA,IAAI,YAAA,KAAiB,IAAA,EAAM,GAAA,CAAI,OAAA,GAAU,aAAa,CAAC,CAAA;AACvD,EAAA,GAAA,CAAI,KAAA,CAAM,KAAK,IAAI,CAAA;AACnB,EAAA,IAAI,OAAA,IAAW,GAAA,CAAI,KAAA,CAAM,MAAA,GAAS,CAAA,EAAG;AACnC,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA;AAClC,IAAA,IAAI,MAAA,CAAO,MAAK,CAAE,MAAA,GAAS,GAAG,gBAAA,CAAiB,GAAA,EAAK,YAAY,QAAQ,CAAA;AAAA,EAC1E;AACF;AAEA,SAAS,gBAAA,CAAiB,GAAA,EAAuB,gBAAA,EAA0B,QAAA,EAAwB;AACjG,EAAA,IAAI,GAAA,CAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG;AAC5B,EAAA,MAAM,SAAA,GAAY,GAAA,CAAI,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA;AACrC,EAAA,IAAI,SAAA,CAAU,IAAA,EAAK,CAAE,MAAA,KAAW,CAAA,EAAG;AACjC,IAAA,GAAA,CAAI,QAAQ,EAAC;AACb,IAAA,GAAA,CAAI,QAAQ,gBAAA,GAAmB,CAAA;AAC/B,IAAA;AAAA,EACF;AACA,EAAA,IAAI,SAAA,CAAU,SAAS,QAAA,EAAU;AAC/B,IAAA,mBAAA,CAAoB,IAAI,MAAA,EAAQ,SAAA,EAAW,IAAI,KAAA,EAAO,GAAA,CAAI,SAAS,QAAQ,CAAA;AAAA,EAC7E,CAAA,MAAO;AACL,IAAA,GAAA,CAAI,MAAA,CAAO,KAAK,UAAA,CAAW,SAAA,EAAW,IAAI,KAAA,EAAO,gBAAA,EAAkB,GAAA,CAAI,OAAO,CAAC,CAAA;AAAA,EACjF;AACA,EAAA,GAAA,CAAI,QAAQ,EAAC;AACb,EAAA,GAAA,CAAI,QAAQ,gBAAA,GAAmB,CAAA;AACjC;AAEA,SAAS,UAAA,CACP,IAAA,EACA,SAAA,EACA,OAAA,EACA,OAAA,EACa;AACb,EAAA,OAAO;AAAA,IACL,SAAA;AAAA,IACA,OAAA;AAAA,IACA,IAAA;AAAA,IACA,IAAA,EAAMW,WAAW,QAAQ,CAAA,CAAE,OAAO,IAAI,CAAA,CAAE,OAAO,KAAK,CAAA;AAAA,IACpD,GAAI,OAAA,KAAY,MAAA,GAAY,EAAE,OAAA,KAAY;AAAC,GAC7C;AACF;AAEA,SAAS,mBAAA,CACP,MAAA,EACA,IAAA,EACA,SAAA,EACA,SACA,QAAA,EACM;AACN,EAAA,IAAI,SAAA,GAAY,IAAA;AAChB,EAAA,IAAI,UAAA,GAAa,SAAA;AACjB,EAAA,OAAO,SAAA,CAAU,SAAS,QAAA,EAAU;AAClC,IAAA,MAAM,OAAA,GAAU,qBAAA,CAAsB,SAAA,EAAW,QAAQ,CAAA;AACzD,IAAA,MAAM,KAAA,GAAQ,SAAA,CAAU,KAAA,CAAM,CAAA,EAAG,OAAO,CAAA;AACxC,IAAA,MAAM,UAAA,GAAa,KAAA,CAAM,KAAA,CAAM,IAAI,CAAA,CAAE,MAAA;AACrC,IAAA,MAAA,CAAO,IAAA,CAAK,WAAW,KAAA,EAAO,UAAA,EAAY,aAAa,UAAA,GAAa,CAAA,EAAG,OAAO,CAAC,CAAA;AAC/E,IAAA,SAAA,GAAY,UAAU,KAAA,CAAM,OAAO,CAAA,CAAE,OAAA,CAAQ,QAAQ,EAAE,CAAA;AACvD,IAAA,UAAA,IAAc,UAAA,GAAa,CAAA;AAAA,EAC7B;AACA,EAAA,IAAI,SAAA,CAAU,SAAS,CAAA,EAAG;AACxB,IAAA,MAAM,UAAA,GAAa,SAAA,CAAU,KAAA,CAAM,IAAI,CAAA,CAAE,MAAA;AACzC,IAAA,MAAA,CAAO,IAAA,CAAK,WAAW,SAAA,EAAW,UAAA,EAAY,aAAa,UAAA,GAAa,CAAA,EAAG,OAAO,CAAC,CAAA;AAAA,EACrF;AACF;AAOA,SAAS,qBAAA,CAAsB,MAAc,QAAA,EAA0B;AACrE,EAAA,IAAI,IAAA,CAAK,MAAA,IAAU,QAAA,EAAU,OAAO,IAAA,CAAK,MAAA;AAEzC,EAAA,KAAA,IAAS,CAAA,GAAI,UAAU,CAAA,GAAI,IAAA,CAAK,IAAI,CAAA,EAAG,QAAA,GAAW,GAAG,CAAA,EAAG,CAAA,EAAA,EAAK;AAC3D,IAAA,IAAI,KAAK,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,IAAK,GAAG,GAAG,OAAO,CAAA;AAAA,EACxC;AAEA,EAAA,OAAO,QAAA;AACT;AC1JA,IAAM,cAAA,GAAiB,GAAA;AAOhB,SAAS,YAAY,GAAA,EAAqB;AAC/C,EAAA,OAAOX,IAAAA,CAAK,SAAA,CAAU,GAAG,CAAA,EAAG,UAAU,CAAA;AACxC;AAWO,SAAS,kBAAA,CAAmB,KAAa,KAAA,EAAuB;AACrE,EAAA,OAAOA,IAAAA,CAAK,YAAY,GAAG,CAAA,EAAG,GAAGe,cAAAA,CAAc,KAAK,CAAC,CAAA,GAAA,CAAK,CAAA;AAC5D;AAEA,SAASA,eAAc,KAAA,EAAuB;AAG5C,EAAA,OAAO,MAAM,OAAA,CAAQ,iBAAA,EAAmB,GAAG,CAAA,CAAE,KAAA,CAAM,GAAG,GAAG,CAAA;AAC3D;AAEA,SAASC,UAAS,IAAA,EAAsB;AACtC,EAAA,IAAI,IAAA,CAAK,MAAA,IAAU,cAAA,EAAgB,OAAO,IAAA;AAC1C,EAAA,OAAO,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,cAAc,CAAC,CAAA,MAAA,CAAA;AACzC;AASA,eAAsB,oBAAoB,KAAA,EAA2C;AACnF,EAAA,IAAI,KAAA,CAAM,WAAW,UAAA,EAAY;AACjC,EAAA,MAAM,IAAA,GAAO,kBAAA,CAAmB,KAAA,CAAM,GAAA,EAAK,MAAM,KAAK,CAAA;AACtD,EAAA,MAAMR,KAAAA,CAAM,YAAY,KAAA,CAAM,GAAG,GAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AAEvD,EAAA,MAAM,QAAA,GAAW,aAAA,CAAcQ,SAAAA,CAAS,KAAA,CAAM,QAAQ,CAAC,CAAA;AACvD,EAAA,MAAM,aAAA,GAAgB,aAAA,CAAcA,SAAAA,CAAS,KAAA,CAAM,aAAa,CAAC,CAAA;AACjE,EAAA,MAAM,MAAM,IAAI,IAAA,CAAK,KAAA,CAAM,EAAE,EAAE,WAAA,EAAY;AAE3C,EAAA,MAAM,IAAA,GAAO;AAAA,IACX,KAAA;AAAA,IACA,CAAA,OAAA,EAAU,MAAM,KAAK,CAAA,CAAA;AAAA,IACrB,CAAA,SAAA,EAAY,MAAM,OAAO,CAAA,CAAA;AAAA,IACzB,OAAO,GAAG,CAAA,CAAA;AAAA,IACV,CAAA,QAAA,EAAW,MAAM,MAAM,CAAA,CAAA;AAAA,IACvB,KAAA;AAAA,IACA,EAAA;AAAA,IACA,SAAA;AAAA,IACA,EAAA;AAAA,IACA,QAAA;AAAA,IACA,EAAA;AAAA,IACA,cAAA;AAAA,IACA,EAAA;AAAA,IACA,aAAA;AAAA,IACA;AAAA,GACF,CAAE,KAAK,IAAI,CAAA;AAEX,EAAA,MAAMP,iBAAAA,CAAkB,MAAM,IAAI,CAAA;AACpC;;;AC3EA,eAAsB,qBAAqB,GAAA,EAAqC;AAC9E,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI;AACF,IAAA,OAAA,GAAU,MAAMV,OAAAA,CAAQ,WAAA,CAAY,GAAG,CAAC,CAAA;AAAA,EAC1C,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACA,EAAA,MAAM,IAAA,GAAO,UAAU,GAAG,CAAA;AAC1B,EAAA,OAAO,OAAA,CACJ,MAAA,CAAO,CAAC,KAAA,KAAU,KAAA,CAAM,QAAA,CAAS,KAAK,CAAC,CAAA,CACvC,GAAA,CAAI,CAAC,KAAA,KAAU;AACd,IAAA,MAAM,YAAA,GAAeC,IAAAA,CAAK,WAAA,CAAY,GAAG,GAAG,KAAK,CAAA;AACjD,IAAA,OAAO;AAAA,MACL,YAAA;AAAA,MACA,OAAA,EAAS,cAAA,CAAe,IAAA,EAAM,YAAY;AAAA,KAC5C;AAAA,EACF,CAAC,CAAA;AACL;AAEA,SAAS,cAAA,CAAe,MAAc,YAAA,EAA8B;AAClE,EAAA,IAAI,YAAA,CAAa,UAAA,CAAW,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,CAAA,EAAG,OAAO,YAAA,CAAa,KAAA,CAAM,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA;AAClF,EAAA,OAAO,YAAA;AACT;ACzBO,SAAS,QAAQ,GAAA,EAAqB;AAC3C,EAAA,OAAOA,IAAAA,CAAK,SAAA,CAAU,GAAG,CAAA,EAAG,MAAM,CAAA;AACpC;AAQA,eAAsB,kBAAkB,GAAA,EAAkC;AACxE,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI;AACF,IAAA,OAAA,GAAU,MAAMD,OAAAA,CAAQ,OAAA,CAAQ,GAAG,CAAC,CAAA;AAAA,EACtC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACA,EAAA,MAAM,IAAA,GAAO,UAAU,GAAG,CAAA;AAC1B,EAAA,OAAO,OAAA,CACJ,MAAA,CAAO,CAAC,KAAA,KAAU,KAAA,CAAM,QAAA,CAAS,KAAK,CAAC,CAAA,CACvC,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,IACf,YAAA,EAAcC,IAAAA,CAAK,OAAA,CAAQ,GAAG,GAAG,KAAK,CAAA;AAAA,IACtC,OAAA,EAASA,IAAAA,CAAK,MAAA,EAAQ,KAAK;AAAA,GAC7B,CAAE,CAAA,CACD,GAAA,CAAI,CAAC,IAAA,MAAU;AAAA,IACd,cAAc,IAAA,CAAK,YAAA;AAAA,IACnB,OAAA,EAASiB,eAAAA,CAAe,IAAA,EAAM,IAAA,CAAK,YAAY;AAAA,GACjD,CAAE,CAAA;AACN;AAEA,SAASA,eAAAA,CAAe,MAAc,YAAA,EAA8B;AAGlE,EAAA,IAAI,YAAA,CAAa,UAAA,CAAW,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,CAAA,EAAG,OAAO,YAAA,CAAa,KAAA,CAAM,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA;AAClF,EAAA,OAAO,YAAA;AACT;ACkEA,SAAS,YAAA,GAA4B;AACnC,EAAA,IAAI;AACF,IAAA,MAAM,CAAA,GAAI,aAAA,CAAc,MAAA,CAAA,IAAA,CAAY,GAAG,CAAA;AACvC,IAAA,OAAO,EAAE,kBAAkB,CAAA;AAAA,EAC7B,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,IAAIZ,kBAAAA;AAAA,MACR,+KAAA;AAAA,MAEA,EAAE,IAAA,EAAM,2BAAA,EAA6B,KAAA;AAAM,KAC7C;AAAA,EACF;AACF;AAQO,IAAM,UAAA,GAAN,MAAM,WAAA,CAAW;AAAA,EACd,WAAA,CACW,KAAA,EACA,SAAA,EACA,YAAA,EACjB;AAHiB,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AACA,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AACA,IAAA,IAAA,CAAA,YAAA,GAAA,YAAA;AAAA,EAChB;AAAA,EAHgB,KAAA;AAAA,EACA,SAAA;AAAA,EACA,YAAA;AAAA,EAGnB,aAAa,KAAK,IAAA,EAA6C;AAC7D,IAAA,MAAM,QAAQ,YAAA,EAAa;AAC3B,IAAA,MAAM,WAAA,GAAc,KAAK,WAAA,IAAeL,IAAAA,CAAK,KAAK,GAAA,EAAK,UAAA,EAAY,UAAU,OAAO,CAAA;AACpF,IAAA,SAAA,CAAU,WAAA,EAAa,EAAE,SAAA,EAAW,IAAA,EAAM,CAAA;AAC1C,IAAA,MAAM,IAAA,GAAO,MAAM,KAAA,CAAM,OAAA,CAAQ,WAAW,CAAA;AAC5C,IAAA,MAAM,GAAA,GAAM,KAAK,SAAA,CAAU,SAAA;AAC3B,IAAA,MAAM,SAAA,GAAY,OAAA;AAClB,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,UAAA,EAAW;AACvC,IAAA,IAAI,KAAA;AACJ,IAAA,IAAI,QAAA,CAAS,QAAA,CAAS,SAAS,CAAA,EAAG;AAChC,MAAA,KAAA,GAAQ,MAAM,IAAA,CAAK,SAAA,CAAU,SAAS,CAAA;AAKtC,MAAA,MAAM,MAAA,GAAS,MAAM,KAAA,CAAM,MAAA,EAAO;AAClC,MAAA,MAAM,QAAA,GAAW,OAAO,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,WAAW,CAAA;AACjE,MAAA,MAAM,WAAA,GAAc,QAAA,EAAU,IAAA,EAAM,QAAA,IAAY,UAAU,IAAA,EAAM,SAAA;AAChE,MAAA,IAAI,OAAO,WAAA,KAAgB,QAAA,IAAY,WAAA,KAAgB,GAAA,EAAK;AAC1D,QAAA,MAAM,IAAIK,kBAAAA;AAAA,UACR,CAAA,yDAAA,EAA4D,WAAW,CAAA,sCAAA,EAAyC,GAAG,CAAA,+FAAA,CAAA;AAAA,UACnH,EAAE,MAAM,8BAAA;AAA+B,SACzC;AAAA,MACF;AAAA,IACF,CAAA,MAAO;AAGL,MAAA,MAAM,SAAA,GAA6B;AAAA,QACjC,EAAA,EAAI,eAAA;AAAA,QACJ,IAAA,EAAM,EAAA;AAAA,QACN,MAAA,EAAQ,QAAA;AAAA,QACR,WAAW,IAAI,KAAA,CAAM,GAAG,CAAA,CAAE,KAAK,CAAC,CAAA;AAAA,QAChC,SAAA,EAAW,eAAA;AAAA,QACX,KAAA,EAAO,eAAA;AAAA,QACP,OAAA,EAAS,eAAA;AAAA,QACT,SAAA,EAAW;AAAA,OACb;AACA,MAAA,KAAA,GAAQ,MAAM,IAAA,CAAK,WAAA,CAAY,SAAA,EAAW,CAAC,SAAS,CAAC,CAAA;AACrD,MAAA,MAAM,KAAA,CAAM,OAAO,6BAA6B,CAAA;AAAA,IAClD;AACA,IAAA,OAAO,IAAI,WAAA,CAAW,KAAA,EAAO,IAAA,CAAK,WAAW,GAAG,CAAA;AAAA,EAClD;AAAA,EAEA,MAAM,SAAS,KAAA,EAAyE;AACtF,IAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACxB,IAAA,MAAM,QAAQ,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,IAAI,CAAA;AACrC,IAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK,SAAA,CAAU,MAAM,KAAK,CAAA;AACnD,IAAA,MAAM,IAAA,GAA0B,KAAA,CAAM,GAAA,CAAI,CAAC,GAAG,CAAA,MAAO;AAAA,MACnD,GAAG,CAAA;AAAA,MACH,SAAA,EAAW,UAAA,CAAW,CAAC,CAAA,IAAK,IAAI,MAAM,IAAA,CAAK,YAAY,CAAA,CAAE,IAAA,CAAK,CAAC;AAAA,KACjE,CAAE,CAAA;AACF,IAAA,MAAM,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,IAAI,CAAA;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,MAAA,CAAO,KAAA,EAAe,IAAA,EAAqD;AAC/E,IAAA,MAAM,CAAC,SAAS,CAAA,GAAI,MAAM,KAAK,SAAA,CAAU,KAAA,CAAM,CAAC,KAAK,CAAC,CAAA;AACtD,IAAA,IAAI,SAAA,KAAc,MAAA,EAAW,OAAO,EAAC;AAQrC,IAAA,MAAM,aAAuB,CAAC,CAAA,aAAA,EAAgB,eAAe,IAAA,CAAK,SAAS,CAAC,CAAA,CAAA,CAAG,CAAA;AAC/E,IAAA,IAAI,IAAA,CAAK,UAAU,MAAA,EAAW;AAC5B,MAAA,UAAA,CAAW,KAAK,CAAA,SAAA,EAAY,cAAA,CAAe,IAAA,CAAK,KAAK,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,IAC3D;AACA,IAAA,IAAI,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,SAAS,EAAE,KAAA,CAAM,UAAA,CAAW,IAAA,CAAK,OAAO,CAAC,CAAA;AACnE,IAAA,IAAI,KAAK,KAAA,KAAU,MAAA,MAAe,CAAA,CAAE,KAAA,CAAM,KAAK,KAAK,CAAA;AACpD,IAAA,MAAM,OAAA,GAAU,MAAM,CAAA,CAAE,OAAA,EAAQ;AAChC,IAAA,OAAO,QACJ,MAAA,CAAO,CAAC,CAAA,KAAM,IAAA,CAAK,YAAY,MAAA,IAAa,IAAA,CAAK,OAAA,CAAQ,QAAA,CAAS,EAAE,MAAM,CAAC,CAAA,CAC3E,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MACX,IAAI,CAAA,CAAE,EAAA;AAAA,MACN,MAAM,CAAA,CAAE,IAAA;AAAA,MACR,QAAQ,CAAA,CAAE,MAAA;AAAA,MACV,WAAW,CAAA,CAAE,SAAA;AAAA,MACb,OAAO,CAAA,CAAE,KAAA;AAAA,MACT,QAAQ,CAAA,CAAE,OAAA;AAAA;AAAA,MAEV,KAAA,EAAO,CAAA,IAAK,CAAA,IAAK,CAAA,CAAE,SAAA,IAAa,CAAA,CAAA;AAAA,KAClC,CAAE,CAAA;AAAA,EACN;AAAA,EAEA,MAAM,WAAW,SAAA,EAAoC;AAKnD,IAAA,OAAO,IAAA,CAAK,MAAM,SAAA,EAAU;AAAA,EAC9B;AAAA,EAEA,MAAM,YAAY,GAAA,EAA2C;AAC3D,IAAA,IAAI,GAAA,CAAI,WAAW,CAAA,EAAG;AAKtB,IAAA,MAAM,OAAA,GAAU,GAAA,CAAI,GAAA,CAAI,CAAC,OAAO,CAAA,CAAA,EAAI,EAAA,CAAG,OAAA,CAAQ,IAAA,EAAM,IAAI,CAAC,CAAA,CAAA,CAAG,CAAA,CAAE,KAAK,IAAI,CAAA;AACxE,IAAA,MAAM,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,CAAA,OAAA,EAAU,OAAO,CAAA,CAAA,CAAG,CAAA;AAAA,EAC9C;AAAA,EAEA,MAAM,KAAA,GAAuB;AAAA,EAE7B;AACF;AAUA,SAAS,eAAe,KAAA,EAAuB;AAS7C,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,UAAA,CAAW,CAAC,CAAA;AAC/B,IAAA,IAAI,SAAS,CAAA,IAAS,IAAA,IAAQ,KAAQ,IAAA,IAAQ,EAAA,IAAS,SAAS,GAAA,EAAM;AACpE,MAAA,MAAM,IAAIA,kBAAAA;AAAA,QACR,2DAA2D,CAAC,CAAA,IAAA,EAAO,IAAA,CAAK,QAAA,CAAS,EAAE,CAAC,CAAA,0CAAA,CAAA;AAAA,QAEpF,EAAE,MAAM,uBAAA;AAAwB,OAClC;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,MAAM,OAAA,CAAQ,KAAA,EAAO,MAAM,CAAA,CAAE,OAAA,CAAQ,MAAM,IAAI,CAAA;AACxD;AASO,SAAS,gBAAA,GAA4B;AAC1C,EAAA,IAAI;AACF,IAAA,MAAM,CAAA,GAAI,aAAA,CAAc,MAAA,CAAA,IAAA,CAAY,GAAG,CAAA;AACvC,IAAA,CAAA,CAAE,kBAAkB,CAAA;AACpB,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAOO,SAAS,iBAAiB,GAAA,EAAqB;AACpD,EAAA,OAAOL,IAAAA,CAAK,GAAA,EAAK,UAAA,EAAY,QAAA,EAAU,OAAO,CAAA;AAChD;;;ACzQO,SAAS,kBAAA,CAAmB,OAAA,GAAyB,EAAC,EAG3D;AACA,EAAA,OAAO;AAAA,IACL,YAAY,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAA,CAAQ,cAAc,EAAE,CAAA;AAAA,IAChD,QAAA,EAAU,QAAQ,QAAA,IAAY;AAAA,GAChC;AACF;;;ACiCA,IAAM,iBAAA,GAAoB,SAAA;AAG1B,IAAM,iBAAA,GAAgC,OAAO,MAAA,CAAO;AAAA,EAClD,YAAA,EAAc,CAAA;AAAA,EACd,YAAA,EAAc,CAAA;AAAA,EACd,aAAA,EAAe,CAAA;AAAA,EACf,cAAA,EAAgB;AAClB,CAAC,CAAA;AAsBM,IAAM,qBAAN,MAAgD;AAAA,EACrD,YAA6B,KAAA,EAAmB;AAAnB,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AAAA,EAAoB;AAAA,EAApB,KAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM7B,MAAM,IAAA,GAA4B;AAChC,IAAA,OAAO,iBAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAA,CAAO,KAAA,EAAe,OAAA,GAAyB,EAAC,EAA+B;AACnF,IAAA,IAAI,MAAM,IAAA,EAAK,CAAE,MAAA,KAAW,CAAA,SAAU,EAAC;AACvC,IAAA,MAAM,EAAE,UAAA,EAAY,QAAA,EAAS,GAAI,mBAAmB,OAAO,CAAA;AAE3D,IAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,KAAA,CAAM,OAAO,KAAA,EAAO;AAAA,MAC/C,SAAA,EAAW,iBAAA;AAAA,MACX,OAAO,UAAA,GAAa,CAAA;AAAA,MACpB,GAAI,QAAQ,OAAA,KAAY,MAAA,GAAY,EAAE,OAAA,EAAS,OAAA,CAAQ,OAAA,EAAQ,GAAI;AAAC,KACrE,CAAA;AACD,IAAA,OAAO,UACJ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,QAAQ,CAAA,CACjC,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA,CACnB,GAAA,CAAI,CAAC,CAAA,KAAM,iBAAA,CAAkB,CAAC,CAAC,CAAA;AAAA,EACpC;AAAA,EAEA,MAAA,GAAsB;AAIpB,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,QAAA;AAAA,MACT,YAAA,EAAc,CAAA;AAAA,MACd,aAAA,EAAe;AAAA,KACjB;AAAA,EACF;AAAA,EAEA,MAAM,KAAA,GAAuB;AAC3B,IAAA,MAAM,IAAA,CAAK,MAAM,KAAA,EAAM;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAA,GAAqB;AACnB,IAAA,OAAO,IAAA,CAAK,KAAA;AAAA,EACd;AACF;AAaA,SAAS,kBAAkB,GAAA,EAKP;AAClB,EAAA,OAAO;AAAA,IACL,MAAM,GAAA,CAAI,EAAA;AAAA,IACV,SAAA,EAAW,CAAA;AAAA,IACX,OAAA,EAAS,CAAA;AAAA,IACT,OAAO,GAAA,CAAI,KAAA;AAAA,IACX,SAAA,EAAW,CAAA;AAAA,IACX,aAAa,GAAA,CAAI,KAAA;AAAA,IACjB,OAAA,EAAS,GAAA,CAAI,IAAA,CAAK,KAAA,CAAM,GAAG,GAAG,CAAA;AAAA,IAC9B,QAAQ,GAAA,CAAI,MAAA;AAAA,IACZ,UAAU,GAAA,CAAI;AAAA,GAChB;AACF;;;AC5LO,IAAM,cAAA,GAA2C,CAAC,YAAA,EAAc,OAAO;AAOvE,SAAS,mBAAmB,OAAA,EAAmD;AACpF,EAAA,IAAI,CAAC,cAAA,CAAe,QAAA,CAAS,OAAwB,CAAA,EAAG;AACtD,IAAA,MAAM,IAAIK,kBAAAA;AAAA,MACR,2BAA2B,OAAO,CAAA,iBAAA,EAAoB,cAAA,CAAe,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,CAAA;AAAA,MAC/E,EAAE,MAAM,wBAAA;AAAyB,KACnC;AAAA,EACF;AACF;AAQA,eAAsB,eAAe,IAAA,EAA8C;AACjF,EAAA,IAAI,IAAA,CAAK,cAAc,MAAA,EAAW;AAChC,IAAA,MAAM,IAAIA,kBAAAA;AAAA,MACR,gKAAA;AAAA,MACA,EAAE,MAAM,0BAAA;AAA2B,KACrC;AAAA,EACF;AACA,EAAA,MAAM,KAAA,GAAQ,MAAM,UAAA,CAAW,IAAA,CAAK;AAAA,IAClC,KAAK,IAAA,CAAK,GAAA;AAAA,IACV,WAAW,IAAA,CAAK,SAAA;AAAA,IAChB,GAAI,KAAK,QAAA,KAAa,MAAA,GAAY,EAAE,WAAA,EAAa,IAAA,CAAK,QAAA,EAAS,GAAI;AAAC,GACrE,CAAA;AACD,EAAA,OAAO,IAAI,mBAAmB,KAAK,CAAA;AACrC;ACPA,eAAsB,uBAAuB,EAAA,EAA6B;AACxE,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAM,OAAO,YAAY,CAAA;AACrC,IAAA,MAAM,SAAU,GAAA,CAAyC,IAAA;AACzD,IAAA,IAAI,OAAO,WAAW,UAAA,EAAY;AAChC,MAAA,MAAM,IAAI,MAAM,4CAA4C,CAAA;AAAA,IAC9D;AACA,IAAA,MAAA,CAAO,EAAE,CAAA;AAAA,EACX,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,UAAU,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AACrE,IAAA,MAAM,IAAIA,kBAAAA;AAAA,MACR,wHAAwH,OAAO,CAAA,CAAA;AAAA,MAC/H,EAAE,IAAA,EAAM,wBAAA,EAA0B,KAAA;AAAM,KAC1C;AAAA,EACF;AACF;AAGO,SAAS,kBAAkB,EAAA,EAAuB;AACvD,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,EAAA,CAAG,OAAA,CAAQ,2BAA2B,EAAE,GAAA,EAAI;AACxD,IAAA,OAAO,GAAA,KAAQ,KAAA,CAAA,IAAa,GAAA,CAAI,CAAA,KAAM,KAAA,CAAA;AAAA,EACxC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;;;AC9BO,IAAM,oBAAA,GAAuB;AAE7B,IAAM,cAAA,GAAiB;AAEvB,IAAM,kBAAA,GAAqB;AAuB3B,SAAS,sBAAsB,EAAA,EAA6C;AACjF,EAAA,MAAM,GAAA,GAAM,CAAC,GAAA,KAAoC;AAC/C,IAAA,MAAM,MAAM,EAAA,CAAG,OAAA,CAAQ,sCAAsC,CAAA,CAAE,IAAI,GAAG,CAAA;AACtE,IAAA,OAAO,GAAA,KAAQ,MAAA,GAAY,MAAA,CAAO,GAAA,CAAI,KAAK,CAAA,GAAI,MAAA;AAAA,EACjD,CAAA;AACA,EAAA,MAAM,UAAA,GAAa,IAAI,oBAAoB,CAAA;AAC3C,EAAA,MAAM,KAAA,GAAQ,IAAI,cAAc,CAAA;AAChC,EAAA,MAAM,MAAA,GAAS,IAAI,kBAAkB,CAAA;AACrC,EAAA,IAAI,eAAe,MAAA,IAAa,KAAA,KAAU,MAAA,IAAa,MAAA,KAAW,QAAW,OAAO,MAAA;AACpF,EAAA,MAAM,SAAA,GAAY,OAAO,MAAM,CAAA;AAC/B,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,SAAS,CAAA,IAAK,SAAA,IAAa,GAAG,OAAO,MAAA;AAC1D,EAAA,OAAO,EAAE,UAAA,EAAY,KAAA,EAAO,SAAA,EAAU;AACxC;AAOO,SAAS,sBAAA,CAAuB,IAAc,QAAA,EAAmC;AACtF,EAAA,MAAM,OAAO,EAAA,CAAG,OAAA;AAAA,IACd;AAAA,GACF;AACA,EAAA,IAAA,CAAK,GAAA,CAAI,oBAAA,EAAsB,QAAA,CAAS,UAAU,CAAA;AAClD,EAAA,IAAA,CAAK,GAAA,CAAI,cAAA,EAAgB,QAAA,CAAS,KAAK,CAAA;AACvC,EAAA,IAAA,CAAK,GAAA,CAAI,kBAAA,EAAoB,MAAA,CAAO,QAAA,CAAS,SAAS,CAAC,CAAA;AACzD;AAOO,SAAS,eAAA,CAAgB,GAAsB,CAAA,EAA+B;AACnF,EAAA,OAAO,CAAA,CAAE,UAAA,KAAe,CAAA,CAAE,UAAA,IAAc,CAAA,CAAE,UAAU,CAAA,CAAE,KAAA,IAAS,CAAA,CAAE,SAAA,KAAc,CAAA,CAAE,SAAA;AACnF;AASO,SAAS,gBAAgB,EAAA,EAAoB;AAClD,EAAA,EAAA,CAAG,KAAK,iCAAiC,CAAA;AAC3C;AAWO,SAAS,iBAAA,CAAkB,IAAc,SAAA,EAAyB;AACvE,EAAA,EAAA,CAAG,IAAA,CAAK,CAAA;AAAA;AAAA,cAAA,EAEM,SAAS,CAAA;AAAA,GAAA,CACrB,CAAA;AACJ;AAGO,SAAS,WAAW,GAAA,EAAoC;AAC7D,EAAA,MAAM,GAAA,GAAM,IAAI,YAAA,CAAa,GAAA,CAAI,MAAM,CAAA;AACvC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,MAAA,EAAQ,CAAA,EAAA,EAAK,GAAA,CAAI,CAAC,CAAA,GAAI,GAAA,CAAI,CAAC,CAAA,IAAK,CAAA;AACxD,EAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA;AAC/B;AASO,SAAS,eAAA,CAAgB,EAAA,EAAc,OAAA,EAAiB,GAAA,EAAkC;AAI/F,EAAA,MAAM,EAAA,GAAK,OAAO,OAAO,CAAA;AACzB,EAAA,EAAA,CAAG,OAAA,CAAQ,2CAA2C,CAAA,CAAE,GAAA,CAAI,EAAE,CAAA;AAC9D,EAAA,EAAA,CAAG,QAAQ,sDAAsD,CAAA,CAAE,IAAI,EAAA,EAAI,UAAA,CAAW,GAAG,CAAC,CAAA;AAC5F;AAqBO,SAAS,YAAA,CACd,EAAA,EACA,KAAA,EACA,CAAA,EACgB;AAGhB,EAAA,MAAM,OAAO,EAAA,CACV,OAAA;AAAA,IACC,CAAA;AAAA;AAAA,wBAAA;AAAA,IAID,GAAA,CAAI,UAAA,CAAW,KAAK,CAAA,EAAG,MAAA,CAAO,CAAC,CAAC,CAAA;AACnC,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS,EAAE,QAAA,EAAU,MAAA,CAAO,GAAA,CAAI,QAAQ,GAAG,QAAA,EAAU,MAAA,CAAO,GAAA,CAAI,QAAQ,GAAE,CAAE,CAAA;AAC/F;AASA,eAAsB,mBAAmB,IAAA,EAAqC;AAC5E,EAAA,MAAM,IAAA,GAAO,KAAK,EAAA,CACf,OAAA;AAAA,IACC,CAAA;AAAA;AAAA;AAAA,wCAAA;AAAA,IAKD,GAAA,EAAI;AACP,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,CAAA;AAC9B,EAAA,MAAM,aAAa,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS,EAAE,EAAA,EAAI,MAAA,CAAO,GAAA,CAAI,EAAE,GAAG,IAAA,EAAM,MAAA,CAAO,IAAI,IAAA,IAAQ,EAAE,GAAE,CAAE,CAAA;AAC3F,EAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,UAAA,CAAW,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAC,CAAA;AACtE,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,UAAA,CAAW,QAAQ,CAAA,EAAA,EAAK;AAC1C,IAAA,MAAM,GAAA,GAAM,WAAW,CAAC,CAAA;AACxB,IAAA,MAAM,MAAA,GAAS,QAAQ,CAAC,CAAA;AACxB,IAAA,IAAI,GAAA,KAAQ,MAAA,IAAa,MAAA,KAAW,MAAA,EAAW;AAC/C,IAAA,eAAA,CAAgB,IAAA,CAAK,EAAA,EAAI,GAAA,CAAI,EAAA,EAAI,MAAM,CAAA;AAAA,EACzC;AACA,EAAA,OAAO,UAAA,CAAW,MAAA;AACpB;;;ACtGO,IAAM,YAAA,GAAN,MAAM,aAAA,CAAoC;AAAA,EAIvC,WAAA,CACW,GAAA,EACA,EAAA,EACA,SAAA,EACjB;AAHiB,IAAA,IAAA,CAAA,GAAA,GAAA,GAAA;AACA,IAAA,IAAA,CAAA,EAAA,GAAA,EAAA;AACA,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AAAA,EAChB;AAAA,EAHgB,GAAA;AAAA,EACA,EAAA;AAAA,EACA,SAAA;AAAA,EANX,UAAA;AAAA,EACA,WAAA,GAAc,KAAA;AAAA,EAiBtB,aAAa,KAAK,IAAA,EAA8C;AAC9D,IAAA,MAAM,OAAA,GAAU,KAAK,OAAA,IAAW,YAAA;AAChC,IAAA,kBAAA,CAAmB,OAAO,CAAA;AAC1B,IAAA,IAAI,OAAA,KAAY,OAAA,EAAS,OAAO,MAAM,eAAe,IAAI,CAAA;AACzD,IAAA,OAAO,MAAM,aAAA,CAAa,kBAAA,CAAmB,IAAI,CAAA;AAAA,EACnD;AAAA;AAAA,EAGA,aAAqB,mBAAmB,IAAA,EAA+C;AACrF,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,QAAA,IAAY,gBAAA,CAAiB,KAAK,GAAG,CAAA;AAC3D,IAAA,MAAM,EAAA,GAAK,MAAM,YAAA,CAAa,EAAE,UAAU,CAAA;AAC1C,IAAA,MAAM,UAAU,IAAI,aAAA,CAAa,KAAK,GAAA,EAAK,EAAA,EAAI,KAAK,SAAS,CAAA;AAC7D,IAAA,IAAI,KAAK,SAAA,KAAc,MAAA,QAAiB,OAAA,CAAQ,iBAAA,CAAkB,KAAK,SAAS,CAAA;AAChF,IAAA,OAAO,OAAA;AAAA,EACT;AAAA,EAEA,MAAc,kBAAkB,OAAA,EAA0C;AACxE,IAAA,MAAM,sBAAA,CAAuB,KAAK,EAAE,CAAA;AACpC,IAAA,MAAM,eAAA,GAAkB;AAAA,MACtB,YAAY,OAAA,CAAQ,EAAA;AAAA,MACpB,OAAO,OAAA,CAAQ,KAAA;AAAA,MACf,WAAW,OAAA,CAAQ;AAAA,KACrB;AACA,IAAA,MAAM,SAAA,GAAY,qBAAA,CAAsB,IAAA,CAAK,EAAE,CAAA;AAC/C,IAAA,IAAI,cAAc,MAAA,IAAa,CAAC,eAAA,CAAgB,SAAA,EAAW,eAAe,CAAA,EAAG;AAG3E,MAAA,eAAA,CAAgB,KAAK,EAAE,CAAA;AAAA,IACzB;AACA,IAAA,iBAAA,CAAkB,IAAA,CAAK,EAAA,EAAI,OAAA,CAAQ,SAAS,CAAA;AAC5C,IAAA,sBAAA,CAAuB,IAAA,CAAK,IAAI,eAAe,CAAA;AAC/C,IAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AAAA,EACrB;AAAA;AAAA,EAGA,MAAM,IAAA,GAKH;AACD,IAAA,MAAM,KAAA,GAAQ,MAAM,oBAAA,CAAqB,IAAA,CAAK,GAAG,CAAA;AACjD,IAAA,IAAI,YAAA,GAAe,CAAA;AACnB,IAAA,IAAI,aAAA,GAAgB,CAAA;AACpB,IAAA,MAAM,cAAA,GAAiB,KAAK,cAAA,EAAe;AAC3C,IAAA,KAAA,MAAW,SAAS,KAAA,EAAO;AACzB,MAAA,MAAM,GAAA,GAAM,MAAMK,QAAAA,CAAS,KAAA,CAAM,cAAc,MAAM,CAAA;AACrD,MAAA,MAAM,IAAA,GAAO,OAAO,GAAG,CAAA;AACvB,MAAA,MAAM,QAAA,GAAW,cAAA,CAAe,GAAA,CAAI,KAAA,CAAM,YAAY,CAAA;AACtD,MAAA,IAAI,QAAA,KAAa,MAAA,IAAa,QAAA,CAAS,IAAA,KAAS,IAAA,EAAM;AACtD,MAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,KAAA,CAAM,YAAY,CAAA;AAC3C,MAAA,MAAM,SAAS,IAAA,CAAK,UAAA;AAAA,QAClB,KAAA,CAAM,YAAA;AAAA,QACN,KAAA,CAAM,OAAA;AAAA,QACN,IAAA;AAAA,QACA,KAAA,CAAM,OAAA;AAAA,QACN,KAAA,CAAM;AAAA,OACR;AACA,MAAA,IAAA,CAAK,oBAAoB,MAAM,CAAA;AAC/B,MAAA,MAAM,MAAA,GAAS,cAAc,GAAG,CAAA;AAChC,MAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,QAAA,IAAA,CAAK,WAAA,CAAY,QAAQ,KAAA,CAAM,SAAA,EAAW,MAAM,OAAA,EAAS,KAAA,CAAM,IAAA,EAAM,KAAA,CAAM,IAAI,CAAA;AAAA,MACjF;AACA,MAAA,YAAA,IAAgB,CAAA;AAChB,MAAA,aAAA,IAAiB,MAAA,CAAO,MAAA;AAAA,IAC1B;AACA,IAAA,IAAI,cAAA,GAAiB,CAAA;AACrB,IAAA,IAAI,IAAA,CAAK,WAAA,IAAe,IAAA,CAAK,SAAA,KAAc,MAAA,EAAW;AACpD,MAAA,cAAA,GAAiB,MAAM,mBAAmB,EAAE,EAAA,EAAI,KAAK,EAAA,EAAI,OAAA,EAAS,IAAA,CAAK,SAAA,EAAW,CAAA;AAAA,IACpF;AACA,IAAA,IAAA,CAAK,UAAA,GAAa,KAAK,GAAA,EAAI;AAC3B,IAAA,OAAO,EAAE,YAAA,EAAc,KAAA,CAAM,MAAA,EAAQ,YAAA,EAAc,eAAe,cAAA,EAAe;AAAA,EACnF;AAAA,EAEA,MAAM,MAAA,CAAO,KAAA,EAAe,OAAA,GAAyB,EAAC,EAA+B;AACnF,IAAA,IAAI,MAAM,IAAA,EAAK,CAAE,MAAA,KAAW,CAAA,SAAU,EAAC;AACvC,IAAA,MAAM,EAAE,UAAA,EAAY,QAAA,EAAS,GAAI,mBAAmB,OAAO,CAAA;AAC3D,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,SAAA,CAAU,KAAA,EAAO,aAAa,CAAC,CAAA;AACrD,IAAA,MAAM,iBAAiB,MAAM,IAAA,CAAK,gBAAA,CAAiB,KAAA,EAAO,aAAa,CAAC,CAAA;AACxE,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,mBAAA,CAAoB,QAAA,EAAU,gBAAgB,OAAO,CAAA;AAC3E,IAAA,OAAO,QAAA,CACJ,OAAO,CAAC,CAAA,KAAM,EAAE,KAAA,IAAS,QAAQ,CAAA,CACjC,MAAA,CAAO,CAAC,CAAA,KAAM,QAAQ,OAAA,KAAY,MAAA,IAAa,OAAA,CAAQ,OAAA,CAAQ,QAAA,CAAS,CAAA,CAAE,MAAM,CAAC,CAAA,CACjF,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA;AAAA,EACxB;AAAA,EAEA,MAAA,GAAsB;AACpB,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,EAAA,CAAG,OAAA,CAAQ,iCAAiC,EAAE,GAAA,EAAI,IAAK,EAAE,CAAA,EAAG,CAAA,EAAE;AACjF,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,EAAA,CAAG,OAAA,CAAQ,kCAAkC,EAAE,GAAA,EAAI,IAAK,EAAE,CAAA,EAAG,CAAA,EAAE;AACnF,IAAA,MAAM,MAAA,GAAsB;AAAA,MAC1B,OAAA,EAAS,IAAA,CAAK,WAAA,GAAc,QAAA,GAAW,UAAA;AAAA,MACvC,YAAA,EAAc,MAAA,CAAO,KAAA,CAAM,CAAA,IAAK,CAAC,CAAA;AAAA,MACjC,aAAA,EAAe,MAAA,CAAO,MAAA,CAAO,CAAA,IAAK,CAAC;AAAA,KACrC;AACA,IAAA,IAAI,IAAA,CAAK,UAAA,KAAe,MAAA,EAAW,MAAA,CAAO,aAAa,IAAA,CAAK,UAAA;AAC5D,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA,EAIQ,SAAA,CAAU,OAAe,KAAA,EAA6D;AAG5F,IAAA,MAAM,SAAA,GAAY,kBAAkB,KAAK,CAAA;AACzC,IAAA,IAAI,SAAA,CAAU,MAAA,KAAW,CAAA,EAAG,OAAO,EAAC;AACpC,IAAA,MAAM,IAAA,GAAO,KAAK,EAAA,CAAG,OAAA;AAAA,MACnB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAAA;AAAA,KASF;AACA,IAAA,IAAI,OAAuC,EAAC;AAC5C,IAAA,IAAI;AACF,MAAA,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,SAAA,EAAW,KAAK,CAAA;AAAA,IAClC,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,EAAC;AAAA,IACV;AACA,IAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,KAAQ;AACvB,MAAA,MAAM,IAAA,GAAO,MAAA,CAAO,GAAA,CAAI,UAAA,IAAc,CAAC,CAAA;AACvC,MAAA,MAAM,SAAA,GAAY,IAAA,GAAO,CAAA,GAAI,CAAA,IAAK,CAAA,GAAI,KAAK,GAAA,CAAI,IAAI,CAAA,CAAA,GAAK,CAAA,IAAK,CAAA,GAAI,IAAA,CAAA;AACjE,MAAA,MAAM,SAAA,GAAY,MAAA,CAAO,GAAA,CAAI,UAAA,IAAc,CAAC,CAAA;AAC5C,MAAA,MAAM,OAAA,GAAU,MAAA,CAAO,GAAA,CAAI,QAAA,IAAY,CAAC,CAAA;AACxC,MAAA,MAAM,IAAA,GAAO,MAAA,CAAO,GAAA,CAAI,QAAQ,CAAA;AAChC,MAAA,OAAO;AAAA,QACL,IAAA;AAAA,QACA,SAAA;AAAA,QACA,OAAA;AAAA,QACA,KAAA,EAAO,SAAA;AAAA,QACP,SAAA;AAAA,QACA,SAAS,eAAA,CAAgB,MAAA,CAAO,GAAA,CAAI,IAAA,IAAQ,EAAE,CAAC,CAAA;AAAA,QAC/C,MAAA,EAAQ,MAAA,CAAO,GAAA,CAAI,MAAM,CAAA;AAAA,QACzB,UAAU,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,SAAS,IAAI,OAAO,CAAA,CAAA;AAAA;AAAA;AAAA,QAGzC,OAAA,EAAS,MAAA,CAAO,GAAA,CAAI,EAAE;AAAA,OACxB;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,MAAc,gBAAA,CACZ,KAAA,EACA,KAAA,EACiE;AACjE,IAAA,IAAI,CAAC,KAAK,WAAA,IAAe,IAAA,CAAK,cAAc,MAAA,EAAW,2BAAW,GAAA,EAAI;AACtE,IAAA,MAAM,CAAC,QAAQ,CAAA,GAAI,MAAM,KAAK,SAAA,CAAU,KAAA,CAAM,CAAC,KAAK,CAAC,CAAA;AACrD,IAAA,IAAI,QAAA,KAAa,MAAA,EAAW,uBAAO,IAAI,GAAA,EAAI;AAC3C,IAAA,MAAM,IAAA,GAAO,YAAA,CAAa,IAAA,CAAK,EAAA,EAAI,UAAU,KAAK,CAAA;AAElD,IAAA,MAAM,GAAA,uBAAU,GAAA,EAAqC;AACrD,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,MAAM,QAAQ,CAAA,IAAK,CAAA,GAAI,KAAK,GAAA,CAAI,CAAA,EAAG,IAAI,QAAQ,CAAA,CAAA;AAC/C,MAAA,GAAA,CAAI,IAAI,GAAA,CAAI,QAAA,EAAU,EAAE,WAAA,EAAa,OAAO,CAAA;AAAA,IAC9C;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AAAA,EAEQ,mBAAA,CACN,QAAA,EACA,cAAA,EACA,OAAA,EACmB;AACnB,IAAA,MAAM,OAAA,GAAU,eAAe,OAAO,CAAA;AACtC,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,SAAA,CAAU,QAAA,EAAU,cAAc,CAAA;AACtD,IAAA,MAAM,WAAW,CAAC,GAAG,MAAA,CAAO,MAAA,EAAQ,CAAA,CAAE,GAAA;AAAA,MAAI,CAAC,GAAA,KACzC,WAAA,CAAY,GAAA,EAAK,cAAA,CAAe,GAAA,CAAI,GAAA,CAAI,OAAO,CAAA,EAAG,WAAA,IAAe,CAAA,EAAG,OAAO;AAAA,KAC7E;AACA,IAAA,OAAO,QAAA,CAAS,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,KAAA,GAAQ,EAAE,KAAK,CAAA;AAAA,EAClD;AAAA,EAEQ,SAAA,CACN,UACA,cAAA,EACoD;AACpD,IAAA,MAAM,MAAA,uBAAa,GAAA,EAAmD;AACtE,IAAA,KAAA,MAAW,OAAO,QAAA,EAAU,MAAA,CAAO,GAAA,CAAI,GAAA,CAAI,SAAS,GAAG,CAAA;AACvD,IAAA,MAAM,UAAA,GAAa,CAAC,GAAG,cAAA,CAAe,MAAM,CAAA,CAAE,MAAA,CAAO,CAAC,EAAA,KAAO,CAAC,MAAA,CAAO,GAAA,CAAI,EAAE,CAAC,CAAA;AAC5E,IAAA,IAAI,UAAA,CAAW,SAAS,CAAA,EAAG;AACzB,MAAA,KAAA,MAAW,GAAA,IAAO,IAAA,CAAK,gBAAA,CAAiB,UAAU,CAAA,EAAG;AACnD,QAAA,MAAA,CAAO,GAAA,CAAI,GAAA,CAAI,OAAA,EAAS,EAAE,GAAG,KAAK,KAAA,EAAO,CAAA,EAAG,SAAA,EAAW,CAAA,EAAG,CAAA;AAAA,MAC5D;AAAA,IACF;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEQ,iBACN,GAAA,EAC8C;AAC9C,IAAA,IAAI,GAAA,CAAI,MAAA,KAAW,CAAA,EAAG,OAAO,EAAC;AAC9B,IAAA,MAAM,eAAe,GAAA,CAAI,GAAA,CAAI,MAAM,GAAG,CAAA,CAAE,KAAK,GAAG,CAAA;AAChD,IAAA,MAAM,IAAA,GAAO,KAAK,EAAA,CACf,OAAA;AAAA,MACC,CAAA;AAAA;AAAA;AAAA;AAAA,6BAAA,EAIuB,YAAY,CAAA,CAAA;AAAA,KACrC,CACC,GAAA,CAAI,GAAG,GAAG,CAAA;AACb,IAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,KAAQ;AACvB,MAAA,MAAM,SAAA,GAAY,MAAA,CAAO,GAAA,CAAI,UAAA,IAAc,CAAC,CAAA;AAC5C,MAAA,MAAM,OAAA,GAAU,MAAA,CAAO,GAAA,CAAI,QAAA,IAAY,CAAC,CAAA;AACxC,MAAA,MAAM,IAAA,GAAO,MAAA,CAAO,GAAA,CAAI,QAAQ,CAAA;AAChC,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,MAAA,CAAO,GAAA,CAAI,EAAE,CAAA;AAAA,QACtB,IAAA;AAAA,QACA,SAAA;AAAA,QACA,OAAA;AAAA,QACA,KAAA,EAAO,CAAA;AAAA,QACP,SAAA,EAAW,CAAA;AAAA,QACX,SAAS,eAAA,CAAgB,MAAA,CAAO,GAAA,CAAI,IAAA,IAAQ,EAAE,CAAC,CAAA;AAAA,QAC/C,MAAA,EAAQ,MAAA,CAAO,GAAA,CAAI,MAAM,CAAA;AAAA,QACzB,UAAU,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,SAAS,IAAI,OAAO,CAAA;AAAA,OAC3C;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA;AAAA,EAIQ,cAAA,GAA4D;AAClE,IAAA,MAAM,OAAO,IAAA,CAAK,EAAA,CAAG,OAAA,CAAQ,kCAAkC,EAAE,GAAA,EAAI;AAKrE,IAAA,OAAO,IAAI,GAAA,CAAI,IAAA,CAAK,IAAI,CAAC,GAAA,KAAQ,CAAC,GAAA,CAAI,IAAA,EAAM,EAAE,EAAA,EAAI,IAAI,EAAA,EAAI,IAAA,EAAM,IAAI,IAAA,EAAM,CAAC,CAAC,CAAA;AAAA,EAC9E;AAAA,EAEQ,WACN,OAAA,EACA,OAAA,EACA,IAAA,EACA,OAAA,EACA,SAAyC,QAAA,EACjC;AACR,IAAA,MAAM,IAAA,GAAO,KAAK,EAAA,CAAG,OAAA;AAAA,MACnB,CAAA;AAAA;AAAA,mBAAA;AAAA,KAGF;AACA,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,OAAA,EAAS,KAAK,KAAA,CAAM,OAAO,CAAA,EAAG,IAAA,EAAM,MAAM,CAAA;AACxE,IAAA,OAAO,GAAA,CAAI,EAAA;AAAA,EACb;AAAA,EAEQ,oBAAoB,MAAA,EAAsB;AAChD,IAAA,IAAA,CAAK,EAAA,CAAG,OAAA,CAAQ,sCAAsC,CAAA,CAAE,IAAI,MAAM,CAAA;AAAA,EACpE;AAAA,EAEQ,WAAA,CACN,MAAA,EACA,SAAA,EACA,OAAA,EACA,MACA,IAAA,EACM;AACN,IAAA,IAAA,CAAK,EAAA,CACF,OAAA;AAAA,MACC;AAAA,MAED,GAAA,CAAI,MAAA,EAAQ,SAAA,EAAW,OAAA,EAAS,MAAM,IAAI,CAAA;AAAA,EAC/C;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,GAAG,KAAA,EAAM;AAAA,EAChB;AACF;AAUA,SAAS,eAAe,OAAA,EAAuC;AAC7D,EAAA,MAAM,YAAA,GAAe,QAAQ,YAAA,IAAgB,GAAA;AAC7C,EAAA,MAAM,UAAA,GAAa,QAAQ,UAAA,IAAc,GAAA;AACzC,EAAA,MAAM,KAAA,GAAQ,eAAe,UAAA,IAAc,CAAA;AAC3C,EAAA,OAAO,EAAE,YAAA,EAAc,UAAA,EAAY,KAAA,EAAM;AAC3C;AAEA,SAAS,WAAA,CACP,GAAA,EACA,WAAA,EACA,OAAA,EACiB;AACjB,EAAA,MAAM,KAAA,GAAA,CACH,cAAc,OAAA,CAAQ,YAAA,GAAe,IAAI,SAAA,GAAY,OAAA,CAAQ,cAAc,OAAA,CAAQ,KAAA;AACtF,EAAA,OAAO;AAAA,IACL,MAAM,GAAA,CAAI,IAAA;AAAA,IACV,WAAW,GAAA,CAAI,SAAA;AAAA,IACf,SAAS,GAAA,CAAI,OAAA;AAAA,IACb,KAAA;AAAA,IACA,WAAW,GAAA,CAAI,SAAA;AAAA,IACf,SAAS,GAAA,CAAI,OAAA;AAAA,IACb,QAAQ,GAAA,CAAI,MAAA;AAAA,IACZ,UAAU,GAAA,CAAI,QAAA;AAAA,IACd,GAAI,WAAA,GAAc,CAAA,GAAI,EAAE,WAAA,KAAgB;AAAC,GAC3C;AACF;AAQA,eAAe,qBAAqB,GAAA,EAAwC;AAC1E,EAAA,MAAM,IAAA,GAAO,UAAU,GAAG,CAAA;AAC1B,EAAA,MAAM,UAA4B,EAAC;AAEnC,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,CAAK,YAAA,CAAa,GAAG,CAAC,CAAA;AAC5B,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,YAAA,EAAc,aAAa,GAAG,CAAA;AAAA,MAC9B,OAAA,EAAS,QAAA,CAAS,IAAA,EAAM,YAAA,CAAa,GAAG,CAAC,CAAA;AAAA,MACzC,MAAA,EAAQ;AAAA,KACT,CAAA;AAAA,EACH,CAAA,CAAA,MAAQ;AAAA,EAER;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,MAAMX,OAAAA,CAAQe,QAAAA,CAAS,GAAG,CAAC,CAAA;AAC3C,IAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,MAAA,IAAI,CAAC,KAAA,CAAM,QAAA,CAAS,KAAK,CAAA,EAAG;AAC5B,MAAA,MAAM,GAAA,GAAMd,IAAAA,CAAKc,QAAAA,CAAS,GAAG,GAAG,KAAK,CAAA;AACrC,MAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,YAAA,EAAc,GAAA,EAAK,OAAA,EAAS,QAAA,CAAS,IAAA,EAAM,GAAG,CAAA,EAAG,MAAA,EAAQ,QAAA,EAAU,CAAA;AAAA,IACpF;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAER;AAEA,EAAA,MAAM,SAAA,GAAY,MAAM,iBAAA,CAAkB,GAAG,CAAA;AAC7C,EAAA,KAAA,MAAW,QAAQ,SAAA,EAAW;AAC5B,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,cAAc,IAAA,CAAK,YAAA;AAAA,MACnB,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,MAAA,EAAQ;AAAA,KACT,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,YAAA,GAAe,MAAM,oBAAA,CAAqB,GAAG,CAAA;AACnD,EAAA,KAAA,MAAW,WAAW,YAAA,EAAc;AAClC,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,cAAc,OAAA,CAAQ,YAAA;AAAA,MACtB,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,MAAA,EAAQ;AAAA,KACT,CAAA;AAAA,EACH;AACA,EAAA,OAAO,OAAA;AACT;AAEA,SAAS,OAAO,IAAA,EAAsB;AACpC,EAAA,OAAOH,WAAW,QAAQ,CAAA,CAAE,OAAO,IAAI,CAAA,CAAE,OAAO,KAAK,CAAA;AACvD;AAEA,SAAS,gBAAgB,IAAA,EAAsB;AAC7C,EAAA,MAAM,GAAA,GAAM,GAAA;AACZ,EAAA,OAAO,IAAA,CAAK,UAAU,GAAA,GAAM,IAAA,GAAO,GAAG,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,GAAG,CAAC,CAAA,MAAA,CAAA;AAC1D;AC9aA,eAAe,mBAAmB,GAAA,EAAuC;AACvE,EAAA,MAAM,MAAA,GAAS,iBAAiB,GAAG,CAAA;AACnC,EAAA,IAAI,CAACO,UAAAA,CAAW,MAAM,CAAA,SAAU,EAAC;AACjC,EAAA,MAAM,KAAK,MAAM,YAAA,CAAa,EAAE,QAAA,EAAU,QAAQ,CAAA;AAClD,EAAA,IAAI;AAGF,IAAA,MAAM,IAAA,GAAO,EAAA,CAAG,OAAA,CAAQ,iEAAiE,CAAA;AACzF,IAAA,MAAM,IAAA,GAAO,KAAK,GAAA,EAAI;AAQtB,IAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MACtB,GAAG,CAAA;AAAA,MACH,SAAA,EAAW,SAAA;AAAA,MACX,KAAA,EAAO,OAAA;AAAA,MACP,OAAA,EAAS;AAAA,KACX,CAAE,CAAA;AAAA,EACJ,CAAA,SAAE;AACA,IAAA,EAAA,CAAG,KAAA,EAAM;AAAA,EACX;AACF;AASA,SAAS,QAAA,CAAS,GAAW,CAAA,EAAoB;AAC/C,EAAA,OAAO,EAAE,SAAA,CAAU,KAAK,CAAA,KAAM,CAAA,CAAE,UAAU,KAAK,CAAA;AACjD;AAUA,eAAsB,qBAAqB,IAAA,EAA8C;AACvF,EAAA,MAAM,MAAM,IAAA,CAAK,GAAA;AACjB,EAAA,MAAM,SAAA,GAAY,iBAAiB,GAAG,CAAA;AACtC,EAAA,MAAM,OAAA,GAAUlB,IAAAA,CAAK,GAAA,EAAK,UAAA,EAAY,UAAU,WAAW,CAAA;AAI3D,EAAA,MAAM,SAAS,IAAA,CAAK,MAAA,KAAW,CAAC,CAAA,KAAc,OAAA,CAAQ,IAAI,CAAC,CAAA,CAAA;AAC3D,EAAA,MAAM,MAAM,CAAC,CAAA,KAAc,MAAA,CAAO,aAAA,CAAc,CAAC,CAAC,CAAA;AAGlD,EAAA,IAAIkB,UAAAA,CAAW,SAAS,CAAA,EAAG;AACzB,IAAA,MAAM,IAAIb,kBAAAA;AAAA,MACR,CAAA,4BAAA,EAA+B,SAAS,CAAA,+BAAA,EAAkC,SAAS,CAAA,eAAA,CAAA;AAAA,MACnF,EAAE,MAAM,8BAAA;AAA+B,KACzC;AAAA,EACF;AACA,EAAA,IAAIa,UAAAA,CAAW,OAAO,CAAA,EAAG;AAEvB,IAAA,GAAA,CAAI,CAAA,eAAA,EAAkB,OAAO,CAAA,uBAAA,CAAyB,CAAA;AACtD,IAAA,MAAA,CAAO,SAAS,EAAE,SAAA,EAAW,IAAA,EAAM,KAAA,EAAO,MAAM,CAAA;AAAA,EAClD;AAEA,EAAA,GAAA,CAAI,CAAA,0BAAA,EAA6B,GAAG,CAAA,iCAAA,CAAmC,CAAA;AACvE,EAAA,MAAM,WAAA,GAAc,MAAM,kBAAA,CAAmB,GAAG,CAAA;AAChD,EAAA,GAAA,CAAI,CAAA,WAAA,EAAc,WAAA,CAAY,MAAM,CAAA,OAAA,CAAS,CAAA;AAC7C,EAAA,IAAI,WAAA,CAAY,WAAW,CAAA,EAAG;AAC5B,IAAA,OAAO;AAAA,MACL,WAAA,EAAa,CAAA;AAAA,MACb,UAAA,EAAY,CAAA;AAAA,MACZ,SAAA,EAAW,IAAA;AAAA,MACX,mBAAmB,EAAC;AAAA,MACpB,SAAA,EAAW,SAAA;AAAA,MACX,SAAA,EAAW;AAAA,KACb;AAAA,EACF;AAQA,EAAA,MAAM,oBAAA,GAAuB;AAAA,IAC3B,EAAA,EAAI,uBAAA;AAAA,IACJ,KAAA,EAAO,oBAAA;AAAA,IACP,SAAA,EAAW,CAAA;AAAA,IACX,KAAA,EAAO,OAAO,KAAA,KAAiC;AAE7C,MAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM;AACtB,QAAA,MAAM,MAAM,IAAI,KAAA,CAAM,CAAC,CAAA,CAAE,KAAK,CAAC,CAAA;AAC/B,QAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,CAAA,CAAE,MAAA,EAAQ,KAAK,CAAA,EAAG;AACpC,UAAA,GAAA,CAAI,CAAA,GAAI,CAAC,CAAA,IAAK,CAAA,CAAE,WAAW,CAAC,CAAA;AAAA,QAC9B;AACA,QAAA,OAAO,GAAA,CAAI,GAAA,CAAI,CAAC,CAAA,KAAM,IAAI,GAAI,CAAA;AAAA,MAChC,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,IACA,KAAA,EAAO,OAAO,EAAE,SAAA,EAAW,CAAA,EAAG,aAAa,CAAA,EAAG,SAAA,EAAW,CAAA,EAAG,OAAA,EAAS,CAAA,EAAE;AAAA,GACzE;AAEA,EAAAC,SAAAA,CAAU,OAAA,EAAS,EAAE,SAAA,EAAW,MAAM,CAAA;AACtC,EAAA,GAAA,CAAI,CAAA,uBAAA,EAA0B,OAAO,CAAA,IAAA,CAAM,CAAA;AAE3C,EAAA,MAAM,KAAA,GAAQ,MAAM,UAAA,CAAW,IAAA,CAAK;AAAA,IAClC,GAAA;AAAA,IACA,SAAA,EAAW,oBAAA;AAAA,IACX,WAAA,EAAa;AAAA,GACd,CAAA;AAED,EAAA,MAAM,SAAA,GAAY,KAAK,SAAA,IAAa,GAAA;AACpC,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,WAAA,CAAY,MAAA,EAAQ,KAAK,SAAA,EAAW;AACtD,IAAA,MAAM,KAAA,GAAQ,YAAY,KAAA,CAAM,CAAA,EAAG,IAAI,SAAS,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MAC5D,IAAI,CAAA,CAAE,EAAA;AAAA,MACN,MAAM,CAAA,CAAE,IAAA;AAAA,MACR,QAAQ,CAAA,CAAE,MAAA;AAAA,MACV,SAAA,EAAW,EAAE,SAAA,IAAa,SAAA;AAAA,MAC1B,KAAA,EAAO,EAAE,KAAA,IAAS,OAAA;AAAA,MAClB,OAAA,EAAS,EAAE,OAAA,IAAW,SAAA;AAAA,MACtB,SAAA,EAAW;AAAA,KACb,CAAE,CAAA;AACF,IAAA,MAAM,KAAA,CAAM,SAAS,KAAK,CAAA;AAC1B,IAAA,GAAA,CAAI,CAAA,WAAA,EAAc,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,SAAA,EAAW,WAAA,CAAY,MAAM,CAAC,CAAA,CAAA,EAAI,WAAA,CAAY,MAAM,CAAA,CAAE,CAAA;AAAA,EACvF;AAGA,EAAA,MAAM,UAAA,GAAa,MAAM,KAAA,CAAM,UAAA,CAAW,SAAS,CAAA;AACnD,EAAA,GAAA,CAAI,CAAA,UAAA,EAAa,UAAU,CAAA,iBAAA,EAAoB,WAAA,CAAY,MAAM,CAAA,EAAA,CAAI,CAAA;AAErE,EAAA,MAAM,UAAA,GAAa,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,YAAY,MAAM,CAAA;AAClD,EAAA,MAAM,oBAAsD,EAAC;AAC7D,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,UAAA,EAAY,KAAK,CAAA,EAAG;AACtC,IAAA,MAAM,UAAA,GAAa,YAAY,IAAA,CAAK,KAAA,CAAO,IAAI,WAAA,CAAY,MAAA,GAAU,UAAU,CAAC,CAAA;AAChF,IAAA,IAAI,eAAe,MAAA,EAAW;AAE9B,IAAA,MAAM,IAAA,GAAO,MAAM,KAAA,CAAM,MAAA,CAAO,WAAW,IAAA,EAAM;AAAA,MAC/C,SAAA,EAAW,WAAW,SAAA,IAAa,SAAA;AAAA,MACnC,KAAA,EAAO;AAAA,KACR,CAAA;AAED,IAAA,MAAM,GAAA,GAAM,KAAK,CAAC,CAAA;AAClB,IAAA,MAAM,QAAQ,GAAA,KAAQ,MAAA,IAAa,SAAS,GAAA,CAAI,IAAA,EAAM,WAAW,IAAI,CAAA;AACrE,IAAA,iBAAA,CAAkB,KAAK,EAAE,EAAA,EAAI,UAAA,CAAW,EAAA,EAAI,OAAO,CAAA;AAAA,EACrD;AAEA,EAAA,MAAM,WAAW,iBAAA,CAAkB,KAAA,CAAM,CAAC,CAAA,KAAM,EAAE,KAAK,CAAA;AACvD,EAAA,MAAM,UAAA,GAAa,eAAe,WAAA,CAAY,MAAA;AAC9C,EAAA,MAAM,YAAY,QAAA,IAAY,UAAA;AAE9B,EAAA,MAAM,MAAM,KAAA,EAAM;AAElB,EAAA,IAAI,IAAA,CAAK,WAAW,IAAA,EAAM;AACxB,IAAA,GAAA,CAAI,mDAA8C,CAAA;AAClD,IAAA,MAAA,CAAO,SAAS,EAAE,SAAA,EAAW,IAAA,EAAM,KAAA,EAAO,MAAM,CAAA;AAChD,IAAA,OAAO;AAAA,MACL,aAAa,WAAA,CAAY,MAAA;AAAA,MACzB,UAAA,EAAY,UAAA;AAAA,MACZ,SAAA;AAAA,MACA,iBAAA;AAAA,MACA,SAAA,EAAW,SAAA;AAAA,MACX,SAAA,EAAW;AAAA,KACb;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,GAAA,CAAI,6EAAwE,CAAA;AAC5E,IAAA,MAAA,CAAO,SAAS,EAAE,SAAA,EAAW,IAAA,EAAM,KAAA,EAAO,MAAM,CAAA;AAChD,IAAA,OAAO;AAAA,MACL,aAAa,WAAA,CAAY,MAAA;AAAA,MACzB,UAAA,EAAY,UAAA;AAAA,MACZ,SAAA,EAAW,KAAA;AAAA,MACX,iBAAA;AAAA,MACA,SAAA,EAAW,SAAA;AAAA,MACX,SAAA,EAAW;AAAA,KACb;AAAA,EACF;AAGA,EAAA,UAAA,CAAW,SAAS,SAAS,CAAA;AAC7B,EAAA,GAAA,CAAI,CAAA,uBAAA,EAA0B,SAAS,CAAA,CAAA,CAAG,CAAA;AAC1C,EAAA,OAAO;AAAA,IACL,aAAa,WAAA,CAAY,MAAA;AAAA,IACzB,UAAA,EAAY,UAAA;AAAA,IACZ,SAAA,EAAW,IAAA;AAAA,IACX,iBAAA;AAAA,IACA,SAAA,EAAW,SAAA;AAAA,IACX,SAAA,EAAW;AAAA,GACb;AACF;ACjPA,eAAe,WAAW,IAAA,EAAgC;AACxD,EAAA,IAAI;AACF,IAAA,MAAM,OAAO,IAAI,CAAA;AACjB,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,eAAe,gBAAgB,QAAA,EAAqD;AAClF,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAMT,QAAAA,CAAS,QAAA,EAAU,MAAM,CAAA;AAC3C,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC7B,IAAA,OAAO,MAAM,OAAA,CAAQ,MAAA,CAAO,KAAK,CAAA,GAAI,MAAA,CAAO,QAAQ,EAAC;AAAA,EACvD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAEA,eAAe,kBAAA,CACb,GAAA,EACA,QAAA,EACA,KAAA,EAC0B;AAC1B,EAAA,IAAI;AACF,IAAA,KAAA,MAAW,IAAA,IAAQ,KAAA,EAAO,MAAM,oBAAA,CAAqB,KAAK,IAAI,CAAA;AAC9D,IAAA,MAAM,MAAA,CAAO,QAAQ,CAAA,CAAE,KAAA,CAAM,MAAM,KAAA,CAAS,CAAA;AAC5C,IAAA,OAAA,CAAQ,MAAA,CAAO,KAAA;AAAA,MACb,CAAA,uBAAA,EAA0B,KAAA,CAAM,MAAM,CAAA,cAAA,EAAiB,QAAQ,CAAA;AAAA;AAAA,KACjE;AACA,IAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,SAAA,EAAW,MAAM,MAAA,EAAO;AAAA,EACnD,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,UAAU,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AACrE,IAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,sDAAA,EAAyD,OAAO;AAAA,CAAI,CAAA;AACzF,IAAA,OAAO,EAAE,QAAA,EAAU,KAAA,EAAO,SAAA,EAAW,CAAA,EAAG,QAAQ,aAAA,EAAc;AAAA,EAChE;AACF;AAEA,IAAM,YAAA,uBAAmB,GAAA,EAAY;AAkCrC,eAAsB,iBAAA,CACpB,KACA,MAAA,EAC0B;AAC1B,EAAA,MAAM,GAAA,GAAM,CAAA,EAAG,GAAG,CAAA,EAAA,EAAK,OAAO,SAAA,IAAa,SAAS,CAAA,EAAA,EAAK,MAAA,CAAO,KAAA,IAAS,OAAO,CAAA,EAAA,EAAK,MAAA,CAAO,UAAU,SAAS,CAAA,CAAA;AAC/G,EAAA,IAAI,YAAA,CAAa,GAAA,CAAI,GAAG,CAAA,EAAG,OAAO,EAAE,QAAA,EAAU,KAAA,EAAO,SAAA,EAAW,CAAA,EAAG,MAAA,EAAQ,kBAAA,EAAmB;AAC9F,EAAA,YAAA,CAAa,IAAI,GAAG,CAAA;AAEpB,EAAA,MAAM,QAAA,GAAW,oBAAA,CAAqB,GAAA,EAAK,MAAM,CAAA;AACjD,EAAA,IAAI,CAAE,MAAM,UAAA,CAAW,QAAQ,CAAA,EAAI;AACjC,IAAA,OAAO,EAAE,QAAA,EAAU,KAAA,EAAO,SAAA,EAAW,CAAA,EAAG,QAAQ,gBAAA,EAAiB;AAAA,EACnE;AACA,EAAA,IAAI,MAAM,UAAA,CAAW,YAAA,CAAa,GAAG,CAAC,CAAA,EAAG;AACvC,IAAA,OAAA,CAAQ,MAAA,CAAO,KAAA;AAAA,MACb,mFAAmF,QAAQ,CAAA;AAAA;AAAA,KAC7F;AACA,IAAA,OAAO,EAAE,QAAA,EAAU,KAAA,EAAO,SAAA,EAAW,CAAA,EAAG,QAAQ,iBAAA,EAAkB;AAAA,EACpE;AAEA,EAAA,MAAM,KAAA,GAAQ,MAAM,eAAA,CAAgB,QAAQ,CAAA;AAC5C,EAAA,IAAI,KAAA,KAAU,QAAW,OAAO,EAAE,UAAU,KAAA,EAAO,SAAA,EAAW,CAAA,EAAG,MAAA,EAAQ,gBAAA,EAAiB;AAC1F,EAAA,OAAO,kBAAA,CAAmB,GAAA,EAAK,QAAA,EAAU,KAAK,CAAA;AAChD;AAGO,SAAS,2BAAA,GAAoC;AAClD,EAAA,YAAA,CAAa,KAAA,EAAM;AACrB;ACtEO,IAAM,yBAAA,GAA4B;AAgCzC,eAAsB,sBAAsB,IAAA,EAAkD;AAC5F,EAAA,MAAM,YAAA,GAAeN,OAAAA,CAAY,IAAA,CAAK,GAAA,EAAK,KAAK,OAAO,CAAA;AACvD,EAAA,MAAM,GAAA,GAAM,MAAMM,QAAAA,CAAS,YAAA,EAAc,MAAM,CAAA;AAC/C,EAAA,MAAM,QAAA,GAAW,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA;AAG/B,EAAA,MAAM,YAAA,GACJ,QAAA,CAAS,MAAA,GAAS,CAAA,IAAK,SAAS,QAAA,CAAS,MAAA,GAAS,CAAC,CAAA,KAAM,EAAA,GAAK,QAAA,CAAS,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,GAAI,QAAA;AACxF,EAAA,MAAM,aAAa,YAAA,CAAa,MAAA;AAEhC,EAAA,MAAM,gBAAgB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,QAAQ,CAAC,CAAA;AAChD,EAAA,MAAM,iBAAiB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,SAAS,yBAAyB,CAAA;AAC1E,EAAA,MAAM,WAAW,aAAA,GAAgB,CAAA;AACjC,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,UAAA,EAAY,WAAW,cAAc,CAAA;AAC7D,EAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,KAAA,CAAM,QAAA,EAAU,MAAM,CAAA;AACjD,EAAA,MAAM,gBAAgB,KAAA,CAAM,MAAA;AAC5B,EAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,aAAa,MAAM,CAAA;AAEtD,EAAA,MAAM,YAAY,cAAA,GAAiB,CAAA;AAEnC,EAAA,OAAO;AAAA,IACL,MAAM,IAAA,CAAK,OAAA;AAAA,IACX,IAAA,EAAM,aAAA;AAAA,IACN,aAAA;AAAA,IACA,UAAA;AAAA,IACA,SAAA;AAAA,IACA,cAAA;AAAA,IACA,IAAA,EAAM,KAAA,CAAM,IAAA,CAAK,IAAI;AAAA,GACvB;AACF;ACvEA,IAAM,kBAAA,GACJ,qaAAA;AAEF,IAAM,eAAA,GACJ,2SAAA;AAEF,IAAM,oBAAA,GAAgD;AAAA,EACpD,IAAA,EAAM,QAAA;AAAA,EACN,QAAA,EAAU,CAAC,OAAO,CAAA;AAAA,EAClB,UAAA,EAAY;AAAA,IACV,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,yBAAA,EAA0B;AAAA,IAChE,YAAY,EAAE,IAAA,EAAM,WAAW,OAAA,EAAS,CAAA,EAAG,SAAS,EAAA,EAAG;AAAA,IACvD,UAAU,EAAE,IAAA,EAAM,UAAU,OAAA,EAAS,CAAA,EAAG,SAAS,CAAA,EAAE;AAAA,IACnD,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,IAAA,EAAM,CAAC,QAAA,EAAU,UAAA,EAAY,MAAA,EAAQ,KAAK,CAAA;AAAE,GACxE;AAAA,EACA,oBAAA,EAAsB;AACxB,CAAA;AAEA,IAAM,iBAAA,GAA6C;AAAA,EACjD,IAAA,EAAM,QAAA;AAAA,EACN,QAAA,EAAU,CAAC,MAAM,CAAA;AAAA,EACjB,UAAA,EAAY;AAAA,IACV,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,mCAAA,EAAoC;AAAA,IACzE,IAAA,EAAM,EAAE,IAAA,EAAM,SAAA,EAAW,SAAS,CAAA,EAAE;AAAA,IACpC,OAAO,EAAE,IAAA,EAAM,WAAW,OAAA,EAAS,CAAA,EAAG,SAAS,GAAA;AAAK,GACtD;AAAA,EACA,oBAAA,EAAsB;AACxB,CAAA;AAEA,IAAM,uBAAA,GAA0B,KAAA;AA4BzB,SAAS,uBAAuB,IAAA,EAA2C;AAChF,EAAA,MAAM,GAAA,GAAM,KAAK,aAAA,IAAiB,uBAAA;AAClC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,eAAA;AAAA,IACN,WAAA,EAAa,kBAAA;AAAA,IACb,WAAA,EAAa,oBAAA;AAAA,IACb,MAAM,QAAQ,KAAA,EAAiD;AAC7D,MAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,KAAA,CAAM,KAAA,EAAO,mBAAmB,CAAA;AACzD,MAAA,MAAM,UAAA,GAAa,UAAA,CAAW,KAAA,CAAM,UAAU,CAAA,IAAK,EAAA;AACnD,MAAA,MAAM,QAAA,GAAW,UAAA,CAAW,KAAA,CAAM,QAAQ,CAAA;AAC1C,MAAA,MAAM,MAAA,GAAS,UAAA,CAAW,KAAA,CAAM,MAAA,EAAQ,QAAW,IAAI,CAAA;AACvD,MAAA,MAAM,OAAA,GAAU,mBAAmB,MAAM,CAAA;AACzC,MAAA,MAAM,aAAA,GAAgB;AAAA,QACpB,UAAA;AAAA,QACA,GAAI,QAAA,KAAa,MAAA,GAAY,EAAE,QAAA,KAAa,EAAC;AAAA,QAC7C,GAAI,OAAA,KAAY,MAAA,GAAY,EAAE,OAAA,KAAY;AAAC,OAC7C;AACA,MAAA,MAAM,OAAO,MAAM,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,OAAO,aAAa,CAAA;AACzD,MAAA,OAAO,IAAA,CAAK,SAAA,CAAU,eAAA,CAAgB,IAAA,EAAM,GAAG,CAAC,CAAA;AAAA,IAClD;AAAA,GACF;AACF;AAmBO,SAAS,oBAAoB,IAAA,EAAwC;AAC1E,EAAA,MAAM,UAAA,GAAaN,OAAAA,CAAY,SAAA,CAAU,IAAA,CAAK,GAAG,CAAC,CAAA;AAClD,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,YAAA;AAAA,IACN,WAAA,EAAa,eAAA;AAAA,IACb,WAAA,EAAa,iBAAA;AAAA,IACb,MAAM,QAAQ,KAAA,EAAiD;AAC7D,MAAA,MAAM,OAAA,GAAU,UAAA,CAAW,KAAA,CAAM,IAAA,EAAM,kBAAkB,CAAA;AACzD,MAAA,MAAM,IAAA,GAAO,UAAA,CAAW,KAAA,CAAM,IAAI,CAAA;AAClC,MAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,KAAA,CAAM,KAAK,CAAA;AAEpC,MAAA,MAAM,QAAA,GAAWA,OAAAA,CAAY,UAAA,EAAY,OAAO,CAAA;AAChD,MAAA,IAAI,CAAC,YAAA,CAAa,UAAA,EAAY,QAAQ,CAAA,EAAG;AACvC,QAAA,MAAM,IAAIC,kBAAAA;AAAA,UACR,sDAAsD,OAAO,CAAA,CAAA;AAAA,UAC7D,EAAE,MAAM,0BAAA;AAA2B,SACrC;AAAA,MACF;AACA,MAAA,MAAM,QAAA,GAA4E;AAAA,QAChF,GAAA,EAAK,UAAA;AAAA,QACL;AAAA,OACF;AACA,MAAA,IAAI,IAAA,KAAS,MAAA,EAAW,QAAA,CAAS,IAAA,GAAO,IAAA;AACxC,MAAA,IAAI,KAAA,KAAU,MAAA,EAAW,QAAA,CAAS,KAAA,GAAQ,KAAA;AAC1C,MAAA,MAAM,MAAA,GAAS,MAAM,qBAAA,CAAsB,QAAQ,CAAA;AACnD,MAAA,OAAO,IAAA,CAAK,UAAU,MAAM,CAAA;AAAA,IAC9B;AAAA,GACF;AACF;AAIA,SAAS,UAAA,CAAW,KAAA,EAAgB,cAAA,EAAyB,cAAA,GAAiB,KAAA,EAAe;AAC3F,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA;AACtC,EAAA,IAAI,cAAA,KAAmB,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,OAAO,OAAO,EAAA;AACtE,EAAA,IAAI,mBAAmB,MAAA,EAAW;AAChC,IAAA,MAAM,IAAIA,kBAAAA,CAAmB,cAAA,EAAgB,EAAE,IAAA,EAAM,wBAAwB,CAAA;AAAA,EAC/E;AACA,EAAA,OAAO,EAAA;AACT;AAEA,SAAS,WAAW,KAAA,EAAoC;AACtD,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,OAAO,QAAA,CAAS,KAAK,GAAG,OAAO,KAAA;AAChE,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,MAAM,IAAA,EAAK,CAAE,SAAS,CAAA,EAAG;AACxD,IAAA,MAAM,CAAA,GAAI,OAAO,KAAK,CAAA;AACtB,IAAA,IAAI,MAAA,CAAO,QAAA,CAAS,CAAC,CAAA,EAAG,OAAO,CAAA;AAAA,EACjC;AACA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,mBACP,MAAA,EAC2D;AAC3D,EAAA,IAAI,MAAA,KAAW,EAAA,IAAM,MAAA,KAAW,KAAA,EAAO,OAAO,MAAA;AAC9C,EAAA,IAAI,MAAA,KAAW,QAAA,EAAU,OAAO,CAAC,QAAQ,CAAA;AACzC,EAAA,IAAI,MAAA,KAAW,MAAA,EAAQ,OAAO,CAAC,MAAM,CAAA;AACrC,EAAA,IAAI,MAAA,KAAW,UAAA,EAAY,OAAO,CAAC,UAAU,CAAA;AAC7C,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,eAAA,CACP,MACA,aAAA,EACiD;AACjD,EAAA,IAAI,IAAA,CAAK,WAAW,CAAA,EAAG,OAAO,EAAE,IAAA,EAAM,EAAC,EAAG,SAAA,EAAW,KAAA,EAAM;AAC3D,EAAA,MAAM,OAA0B,EAAC;AACjC,EAAA,IAAI,YAAA,GAAe,CAAA;AACnB,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,MAAM,aAAa,GAAA,CAAI,OAAA,CAAQ,UAAU,GAAA,CAAI,QAAA,EAAU,UAAU,CAAA,CAAA,GAAK,EAAA;AACtE,IAAA,IAAI,IAAA,CAAK,MAAA,GAAS,CAAA,IAAK,YAAA,GAAe,aAAa,aAAA,EAAe;AAChE,MAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,SAAA,EAAW,IAAA,EAAK;AAAA,IACvC;AACA,IAAA,IAAA,CAAK,KAAK,GAAG,CAAA;AACb,IAAA,YAAA,IAAgB,UAAA;AAAA,EAClB;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,SAAA,EAAW,KAAA,EAAM;AACxC;AAEA,SAAS,YAAA,CAAa,MAAc,SAAA,EAA4B;AAC9D,EAAA,MAAM,iBAAiB,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA,GAAI,IAAA,GAAO,GAAG,IAAI,CAAA,CAAA,CAAA;AAC1D,EAAA,OAAO,SAAA,KAAc,IAAA,IAAQ,SAAA,CAAU,UAAA,CAAW,cAAc,CAAA;AAClE","file":"index.js","sourcesContent":["/**\n * `createInMemoryMarkdownProvider` — first concrete `MemoryProvider`\n * impl shipped in `@theokit/sdk-memory` (SDK 2.0 Phase 1 / T1.6).\n *\n * Goal: prove the contract works end-to-end with a real (non-no-op)\n * impl WITHOUT pulling LanceDB / embedding / circuit-breaker infrastructure.\n * That richer impl lands in subsequent iters.\n *\n * Semantics:\n * - Stores recalled facts in a per-agent in-process Map.\n * - `runActivePass()` returns the facts plus a `systemPromptAdditions`\n * string that joins fact contents with newlines (so the LLM sees\n * them in the system slot).\n * - `buildTools()` surfaces a `memory_remember(content)` tool the LLM\n * can call to persist a fact mid-conversation.\n * - `recordSessionSummary()` writes a markdown summary to\n * `${cwd}/.theokit/memory/sessions/${runId}.md` (real disk write\n * via `@theokit/sdk/persistence` per ADR-008).\n * - `dispose()` clears the handle's per-agent map (releases memory).\n *\n * @public\n */\n\nimport { mkdir, readdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type {\n ActiveMemoryPassArgs,\n ActiveMemoryPassResult,\n CustomTool,\n MemoryAdapter,\n MemoryAdapterCapabilities,\n MemoryContext,\n MemoryFact,\n MemoryId,\n MemoryProvider,\n MemoryProviderHandle,\n MemoryProviderInitOptions,\n MemoryTurnMessage,\n RecordSessionSummaryArgs,\n SDKAgent,\n} from \"@theokit/sdk\";\nimport { Security } from \"@theokit/sdk\";\nimport { replaceFileAtomic } from \"@theokit/sdk/persistence\";\n\n/** Adapter id prefix — namespaces minted MemoryIds so cross-adapter delete is safe (EC-B). */\nconst ADAPTER_ID = \"in-memory-md\";\n\n/** Per-agent state holder. Stored on the handle via the opaque symbol slot. */\ninterface InMemoryHandleState {\n readonly facts: Map<string, MemoryFact>;\n readonly counter: { next: number };\n /**\n * Workspace cwd captured at `init()` time. Used by `runActivePass()`\n * to read previously-written session summaries from disk for recall\n * (iter 34 — closes the \"write but never read\" gap from iter 33).\n */\n readonly cwd: string;\n /**\n * `sessions: true` capability is set when cwd is available (always),\n * so future Stage 3 work can mark this provider as the canonical\n * sessions-recall path (vs. the no-op default).\n */\n}\n\nconst INTERNAL_STATE = Symbol(\"sdk-memory.in-memory.state\");\n\nfunction buildCapabilities(): MemoryAdapterCapabilities {\n return {\n history: false,\n sessions: false,\n tenancy: false,\n reasoning: false,\n toolSchemas: false,\n prefetch: false,\n };\n}\n\nfunction buildAdapter(state: InMemoryHandleState): MemoryAdapter {\n return {\n id: ADAPTER_ID,\n capabilities: buildCapabilities(),\n isAvailable(): boolean {\n return true;\n },\n async write(content: string | MemoryTurnMessage[], _ctx: MemoryContext): Promise<MemoryId> {\n const text = typeof content === \"string\" ? content : content.map((m) => m.content).join(\"\\n\");\n // Iter 43: redact secrets before persisting. Same posture as\n // memory_remember tool handler — secret-containing payloads\n // submitted to MemoryAdapter.write directly should never\n // surface verbatim in subsequent recall.\n const safeText = Security.redact(text);\n const id = `${ADAPTER_ID}:${state.counter.next++}` as MemoryId;\n state.facts.set(id, {\n id,\n content: safeText,\n createdAt: new Date().toISOString(),\n });\n return id;\n },\n async recall(_query: string, _ctx: MemoryContext, k?: number): Promise<MemoryFact[]> {\n // Naive recall — return everything (cap at k). Real impls in\n // subsequent iters add semantic similarity via embeddings.\n const all = Array.from(state.facts.values());\n const limit = k !== undefined && k >= 0 ? k : all.length;\n return all.slice(0, limit);\n },\n async delete(id: MemoryId): Promise<void> {\n if (!String(id).startsWith(`${ADAPTER_ID}:`)) {\n throw new Error(\n `MemoryAdapter.delete: id \"${String(id)}\" was not minted by adapter \"${ADAPTER_ID}\"`,\n );\n }\n state.facts.delete(id);\n },\n };\n}\n\n/** Truncate session-summary text fields to bound disk size. */\nconst MAX_SUMMARY_TURN_CHARS = 2000;\n\nfunction truncate(text: string): string {\n if (text.length <= MAX_SUMMARY_TURN_CHARS) return text;\n return `${text.slice(0, MAX_SUMMARY_TURN_CHARS)}…`;\n}\n\n/**\n * Sanitize a runId for use as a filename. Strip path separators +\n * traversal patterns; keep `[a-zA-Z0-9_-]`; cap at 128 chars.\n * Mirrors sdk-core's legacy `writeSessionSummary` sanitizer so the\n * file-path semantics are identical across paths.\n */\nfunction sanitizeRunId(runId: string): string {\n return runId.replace(/[^a-zA-Z0-9_-]/g, \"_\").slice(0, 128);\n}\n\n/** Render the session-summary markdown body. */\nfunction renderSessionSummaryMarkdown(args: RecordSessionSummaryArgs): string {\n const iso = new Date(args.at).toISOString();\n // Iter 42: redact secrets from User + Assistant text via the public\n // `Security.redact()` API (sdk-core's ADR D68 canonical redactor —\n // 12 built-in patterns: OpenAI, Anthropic, GitHub PAT, AWS, etc.).\n // Mirrors sdk-core's legacy writeSessionSummary behavior so the\n // disk artefact never leaks API keys typed by the user.\n const safeUser = Security.redact(truncate(args.userText));\n const safeAssistant = Security.redact(truncate(args.assistantText));\n return [\n \"---\",\n `runId: ${args.runId}`,\n `agentId: ${args.agentId}`,\n `at: ${iso}`,\n `status: ${args.status}`,\n \"---\",\n \"\",\n \"## User\",\n \"\",\n safeUser,\n \"\",\n \"## Assistant\",\n \"\",\n safeAssistant,\n \"\",\n ].join(\"\\n\");\n}\n\n/**\n * Extract `agentId:` value from a session-summary YAML frontmatter.\n * Returns undefined when the file is malformed or has no agentId.\n *\n * The frontmatter shape is:\n * ---\n * runId: ...\n * agentId: ...\n * ...\n * ---\n *\n * Parsing is intentionally simple (regex line-match) — full YAML parse\n * is overkill for the 5-field frontmatter we emit. A malformed file\n * shows up as undefined → falls out of the optional agentId filter.\n */\nfunction extractAgentIdFromFrontmatter(content: string): string | undefined {\n // Match `agentId: <value>` within the leading frontmatter block.\n const match = content.match(/^agentId:\\s*(.+)$/m);\n if (match === null || match[1] === undefined) return undefined;\n return match[1].trim();\n}\n\n/**\n * Read previously-written session summaries from disk + substring-\n * match against the user message. Best-effort: errors degrade to\n * empty recall (no throw — matches the non-throwing-on-hot-path\n * contract).\n *\n * Iter 34: this is the SUBSTRING-match version. Future iters can\n * upgrade to embedding-based semantic similarity (LanceDB ANN)\n * without changing the public surface.\n *\n * Cap: returns at most 5 hits to bound the systemPromptAdditions size.\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: session recall has branching on multiple storage modes\nasync function recallSessionSummaries(\n cwd: string,\n userMessage: string,\n agentIdFilter?: string,\n): Promise<ReadonlyArray<MemoryFact>> {\n const RECALL_CAP = 5;\n const sessionsDir = join(cwd, \".theokit\", \"memory\", \"sessions\");\n let files: string[];\n try {\n files = await readdir(sessionsDir);\n } catch {\n return [];\n }\n const query = userMessage.toLowerCase().trim();\n if (query.length === 0) return [];\n const hits: MemoryFact[] = [];\n for (const file of files) {\n if (!file.endsWith(\".md\")) continue;\n if (hits.length >= RECALL_CAP) break;\n const filePath = join(sessionsDir, file);\n let content: string;\n try {\n content = await readFile(filePath, \"utf-8\");\n } catch {\n continue;\n }\n // Iter 36: agentId scope filter. When set, skip summaries whose\n // frontmatter `agentId:` field doesn't match. Prevents cross-agent\n // data leakage in multi-agent setups.\n if (agentIdFilter !== undefined) {\n const fileAgentId = extractAgentIdFromFrontmatter(content);\n if (fileAgentId !== agentIdFilter) continue;\n }\n if (content.toLowerCase().includes(query)) {\n // Extract a short snippet — the User section (first 200 chars).\n const userIdx = content.indexOf(\"## User\");\n const snippet =\n userIdx >= 0 ? content.slice(userIdx, userIdx + 200).replace(/\\s+/g, \" \") : file;\n const id = `${ADAPTER_ID}:session:${file}` as MemoryId;\n hits.push({\n id,\n content: snippet,\n score: 0.5, // substring-match has no real score; placeholder\n });\n }\n }\n return hits;\n}\n\n/**\n * Build the LLM-facing `memory_search` tool (iter 35). The LLM calls\n * this when the user asks about something it might have learned in a\n * previous session. Queries the disk-backed sessions corpus via the\n * same `recallSessionSummaries` helper used by `runActivePass`.\n */\nfunction buildMemorySearchTool(state: InMemoryHandleState): CustomTool {\n return {\n name: \"memory_search\",\n description:\n \"Search past session summaries for content related to a query. Use when the user asks about something they mentioned in a previous conversation. Returns up to 5 short snippets.\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: {\n type: \"string\",\n description: \"What to search for (a topic, fact, or keyword).\",\n },\n },\n required: [\"query\"],\n additionalProperties: false,\n },\n handler: async (input: Record<string, unknown>): Promise<string> => {\n const query = typeof input.query === \"string\" ? input.query : \"\";\n if (query.length === 0) {\n return JSON.stringify({ ok: false, results: [], error: \"empty query\" });\n }\n const hits = await recallSessionSummaries(state.cwd, query);\n return JSON.stringify({\n ok: true,\n count: hits.length,\n results: hits.map((h) => ({ id: String(h.id), snippet: h.content })),\n });\n },\n };\n}\n\nfunction buildMemoryRememberTool(state: InMemoryHandleState): CustomTool {\n return {\n name: \"memory_remember\",\n description:\n \"Persist a short fact about the user/conversation to memory so it can be recalled in future turns. Pass a single concise sentence as `content`.\",\n inputSchema: {\n type: \"object\",\n properties: {\n content: { type: \"string\", description: \"The fact to remember (one sentence).\" },\n },\n required: [\"content\"],\n additionalProperties: false,\n },\n handler: async (input: Record<string, unknown>): Promise<string> => {\n const content = typeof input.content === \"string\" ? input.content : \"\";\n if (content.length === 0) {\n return JSON.stringify({ ok: false, error: \"empty content\" });\n }\n // Iter 43: redact secrets from the LLM-supplied content BEFORE\n // storing in the Map. The LLM may quote a key from the user\n // verbatim (e.g., \"user said their key is sk-proj-...\"); without\n // this, that secret would persist + leak into systemPromptAdditions\n // on subsequent runActivePass calls. Mirrors the iter 42\n // recordSessionSummary redaction posture.\n const safeContent = Security.redact(content);\n const id = `${ADAPTER_ID}:${state.counter.next++}` as MemoryId;\n state.facts.set(id, {\n id,\n content: safeContent,\n createdAt: new Date().toISOString(),\n });\n return JSON.stringify({ ok: true, id });\n },\n };\n}\n\n/**\n * Build a fresh `MemoryProvider` whose facts live in-process. The\n * returned provider is independent — call `createInMemoryMarkdownProvider()`\n * per agent OR share across agents (each `init()` gets its own state).\n *\n * Iter 33: `recordSessionSummary()` writes session-summary markdown\n * files to disk under `${cwd}/.theokit/memory/sessions/`.\n * Iter 34: `runActivePass()` reads back those summaries + substring-\n * matches against the user message for genuine cross-session recall.\n *\n * Future LanceDB-backed impl will replace the substring match with\n * semantic-similarity ANN over embedding vectors.\n */\nexport function createInMemoryMarkdownProvider(): MemoryProvider {\n return {\n async init(opts: MemoryProviderInitOptions): Promise<MemoryProviderHandle> {\n const state: InMemoryHandleState = {\n facts: new Map(),\n counter: { next: 0 },\n cwd: opts.cwd,\n };\n const adapter = buildAdapter(state);\n return {\n adapter,\n [INTERNAL_STATE]: state,\n };\n },\n buildTools(handle: MemoryProviderHandle, _agent: SDKAgent): ReadonlyArray<CustomTool> {\n const state = handle[INTERNAL_STATE] as InMemoryHandleState | undefined;\n if (state === undefined) return [];\n return [buildMemoryRememberTool(state), buildMemorySearchTool(state)];\n },\n async runActivePass(\n handle: MemoryProviderHandle,\n args: ActiveMemoryPassArgs,\n ): Promise<ActiveMemoryPassResult> {\n const state = handle[INTERNAL_STATE] as InMemoryHandleState | undefined;\n if (state === undefined) return { facts: [] };\n // (1) In-process facts (from memory_remember tool calls this turn).\n const inProcessFacts = Array.from(state.facts.values());\n // (2) Persisted session-summary recall — iter 34. Read previously-\n // written summaries from disk + substring-match against the user\n // message. Best-effort: read errors degrade to empty recall.\n //\n // Iter 36: scope the disk recall to args.agentId so a session\n // summary written by agent-A never bleeds into agent-B's recall.\n // This is the multi-agent privacy invariant.\n const persistedHits = await recallSessionSummaries(state.cwd, args.userMessage, args.agentId);\n const allFacts = [...inProcessFacts, ...persistedHits];\n if (allFacts.length === 0) return { facts: [] };\n const systemPromptAdditions = [\n \"Known facts about the user/session (recall):\",\n ...allFacts.map((f) => `- ${f.content}`),\n ].join(\"\\n\");\n return { facts: allFacts, systemPromptAdditions };\n },\n sync(_handle: MemoryProviderHandle): void {\n // No-op for the in-memory impl — facts are written synchronously to\n // the Map at handler-call time; nothing to re-index post-run. Future\n // LanceDB-backed impl will fire IndexManager.sync() here.\n return;\n },\n async recordSessionSummary(args: RecordSessionSummaryArgs): Promise<void> {\n // Real filesystem write via `@theokit/sdk/persistence`'s\n // `replaceFileAtomic`. ADR-008 sub-path resolution guarantees the\n // same process-level write lock as sdk-core's legacy\n // `writeSessionSummary`. Future LanceDB-backed impl additionally\n // triggers IndexManager re-sync after the write.\n if (args.status !== \"finished\") return;\n const sessionsPath = join(args.cwd, \".theokit\", \"memory\", \"sessions\");\n const filePath = join(sessionsPath, `${sanitizeRunId(args.runId)}.md`);\n await mkdir(sessionsPath, { recursive: true });\n const body = renderSessionSummaryMarkdown(args);\n await replaceFileAtomic(filePath, body);\n },\n dispose(handle: MemoryProviderHandle): void {\n const state = handle[INTERNAL_STATE] as InMemoryHandleState | undefined;\n if (state === undefined) return;\n state.facts.clear();\n },\n };\n}\n","import { readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { notesDir } from \"@theokit/sdk/internal/memory-store\";\n\n/**\n * Markdown-first memory storage — re-exported from `@theokit/sdk`, not reimplemented here.\n *\n * This file used to be a full copy (iter 56, Stage 3 source-move #13). The copy went stale: `#389`\n * moved the layout from bullets under `MEMORY.md ## Facts` to a file per memory, and the\n * Claude Code compatibility work added two more read roots — both landed in the SDK's copy and\n * neither in this one. Because `Memory.runDreamingSweep` routes through this package whenever it is\n * installed, **the copy that ran was not the copy anyone had updated**: installing\n * `@theokit/sdk-memory` made every memory the SDK had written unreadable, reported as\n * `factsBefore: 0` — a number that reads exactly like an empty store (#430).\n *\n * theokit#160 fixed the identical shape for the embedding runtime, in this same package pair, by\n * importing one implementation instead of syncing two. Same remedy here. Re-syncing the copy would\n * have fixed today's divergence and left tomorrow's free to happen.\n *\n * The re-exported signatures are supersets of what this package used to expose — the added\n * parameters are optional — so nothing that called them before has to change.\n *\n * @internal\n */\nexport {\n appendFact,\n appendFactToMarkdown,\n claudeProjectMemoryDir,\n memoryDir,\n memoryMdPath,\n memoryWriteDir,\n notesDir,\n readFacts,\n readFactsFromMarkdown,\n} from \"@theokit/sdk/internal/memory-store\";\n\n/** One note discovered under `notes/`: its file name without the `.md` suffix, and its absolute path. */\nexport interface NoteFile {\n slug: string;\n path: string;\n}\n\n/**\n * List the `.md` files directly under `notes/`. Returns `[]` when the directory does not exist, so\n * a workspace that has never written a note is not an error. Does not recurse into sub-directories.\n *\n * Stays here rather than moving to the shared store: notes are this package's concept, and only\n * this package reads them.\n */\nexport async function listNotes(cwd: string): Promise<NoteFile[]> {\n let entries: string[] = [];\n try {\n entries = await readdir(notesDir(cwd));\n } catch {\n return [];\n }\n return entries\n .filter((name) => name.endsWith(\".md\"))\n .map((name) => ({ slug: name.replace(/\\.md$/, \"\"), path: join(notesDir(cwd), name) }));\n}\n","import { join } from \"node:path\";\n\nimport { atomicWriteJson } from \"@theokit/sdk/persistence\";\n\nimport { memoryDir } from \"./markdown-store.js\";\n\n/**\n * Optional on-disk persistence for Active Memory recall transcripts (ADR D6).\n *\n * Writes one JSON file per run under\n * `.theokit/memory/transcripts/active-memory/<runId>.json` when the agent\n * passes `persistTranscripts: true`. Failures are swallowed with a stderr\n * warning so transcript IO never crashes the agent run.\n *\n * Iter 58 (Stage 3 source-move #15): hybrid copy from sdk-core's\n * `internal/memory/storage/transcript-store.ts`. sdk-core retains its\n * copy for v1.x active-memory back-compat; sdk-memory ships the\n * canonical copy that the future `active-memory.ts` move will compose\n * with as a sibling. Dependency chain (both resolved):\n * - `@theokit/sdk/persistence` for `atomicWriteJson`\n * - sibling `./markdown-store.js` for `memoryDir` (moved iter 56)\n *\n * @internal\n */\n\nexport interface ActiveMemoryTranscript {\n runId: string;\n startedAtMs: number;\n userText: string;\n queryMode: string;\n status: string;\n durationMs: number;\n summary: string | undefined;\n hits: ReadonlyArray<{\n path: string;\n startLine: number;\n endLine: number;\n score: number;\n snippet: string;\n }>;\n}\n\n/**\n * Write one recall transcript to\n * `<memory root>/transcripts/active-memory/<runId>.json`, creating the parent\n * directories and replacing the file atomically.\n *\n * Never rejects. A failure is reported on stderr and swallowed, because losing a\n * diagnostic file must not fail the agent run that produced it. That also means\n * a successful resolution is not evidence the file was written.\n *\n * The run id is used verbatim in the file name — unlike the session summary\n * writer, nothing sanitises it here, so pass an id you control.\n */\nexport async function persistActiveMemoryTranscript(\n cwd: string,\n transcript: ActiveMemoryTranscript,\n): Promise<void> {\n try {\n const dir = join(memoryDir(cwd), \"transcripts\", \"active-memory\");\n const file = join(dir, `${transcript.runId}.json`);\n // atomicWriteJson auto-creates the parent directory + writes atomically\n // (no torn writes during crash).\n await atomicWriteJson(file, transcript);\n } catch (cause) {\n const message = cause instanceof Error ? cause.message : String(cause);\n process.stderr.write(`[theokit-sdk] active-memory transcript persist failed: ${message}\\n`);\n }\n}\n","/**\n * Active Memory blocking recall (ADR D6 of memory-system-peer-project-parity).\n *\n * Runs BEFORE `agent.send()` assembles the system prompt. Issues a direct\n * call to `IndexManager.search` with the user message (and optional recent\n * turns per `queryMode`).\n *\n * Returns a `summary` string capped at `maxSummaryChars` (default 220 to\n * match peer-project's `DEFAULT_MAX_SUMMARY_CHARS`) which the system-prompt\n * pipeline prepends as a `<active-memory>` block (priority 5).\n *\n * Iter 75 (Stage 3 source-move #38, FINAL move): hybrid copy from\n * sdk-core's `internal/memory/active-memory.ts`. sdk-core retains its\n * copy as the v1.x runtime that `Memory` class delegates to;\n * sdk-memory ships the canonical copy that future Stage 4 port-based\n * composition will consume.\n *\n * **CLOSES the Stage 3 source-move stage in sdk-memory.** Every\n * memory-related concept under sdk-core's internal/memory/ is now\n * canonical in @theokit/sdk-memory (38 source files moved across\n * iter 44-75; 2 inlined adapters added: adapter-http-error iter 73\n * + adapter-catalog renamed iter 74).\n *\n * **Cross-package telemetry contract:** `OTelSpan` and `TelemetryHandle`\n * are now imported from `@theokit/sdk`, which exports them since #295.\n * This file previously inlined structural mirrors of both, with a note\n * that they MUST be replaced once sdk-core made them public — and by\n * the time anyone looked, the mirrors had drifted: they narrowed\n * `setAttributes` to reject the `undefined` values the canonical type\n * accepts, and declared `end()` without its `endTime` parameter. That\n * is how a structural mirror fails: quietly, with both sides compiling.\n *\n * The 2 constant strings (`memory.recall` span name +\n * `theokit_memory_recall_duration_ms` histogram name) are still inlined\n * below, because sdk-core's `span-names.ts` remains private. They are\n * values rather than types, so exporting them is a separate decision\n * with a real bundle cost — unlike these two, which erase at build time.\n *\n * @internal\n */\n\nimport type { OTelSpan, TelemetryHandle } from \"@theokit/sdk\";\n\nimport type { CircuitBreaker } from \"../circuit-breaker.js\";\nimport type { MemorySearchHit } from \"../index/index-manager-contract.js\";\nimport type { MemoryIndex } from \"../index/memory-index.js\";\nimport { persistActiveMemoryTranscript } from \"../store/transcript-store.js\";\nimport type { ActiveMemoryCache, TenantContext } from \"./active-memory-cache.js\";\n// T4.1 / D438 — `ActiveMemoryResult` and its helpers moved to `./active-memory-types.ts`\n// so `./active-memory-cache.ts` can reach them without cycling back here (cycle #10).\n// Re-exported below for back-compat with in-tree consumers.\nimport type {\n ActiveMemoryQueryMode,\n ActiveMemoryResult,\n ActiveMemoryStatus,\n} from \"./active-memory-types.js\";\n\nexport type { ActiveMemoryQueryMode, ActiveMemoryResult, ActiveMemoryStatus };\n\n// Iter 75 inlined constants — sdk-core's telemetry/span-names.ts is\n// not public. These two are the only ones this file uses.\nconst SPAN_MEMORY_RECALL = \"memory.recall\";\nconst HISTOGRAM_MEMORY_RECALL_DURATION_MS = \"theokit_memory_recall_duration_ms\";\n\n// #295 — the canonical types, not a copy of them.\n//\n// Iter 75 inlined structural mirrors here because sdk-core's telemetry/tracer.ts\n// was not public, with a note that they MUST be replaced once it was. They had\n// already drifted by the time anyone checked: the mirror narrowed `setAttributes`\n// to reject the `undefined` values the canonical type accepts, and declared\n// `end()` without the `endTime` parameter. Neither broke a build — a structural\n// mirror fails by being quietly wrong, not by being loudly missing.\n//\n// `@theokit/sdk` is already a peerDependency of this package, and both types are\n// erased at build time, so this costs nothing at runtime.\n\n/**\n * Tuning for one recall attempt. Recall is off unless `enabled` is exactly\n * `true`, so an options object that omits it disables recall rather than\n * enabling it with defaults.\n */\nexport interface ActiveMemoryOptions {\n /** Whether active recall is enabled. Default `false`. */\n enabled?: boolean;\n /** Query construction strategy. Default `\"recent\"`. */\n queryMode?: ActiveMemoryQueryMode;\n /** Hard timeout in ms. Default `15000`. */\n timeoutMs?: number;\n /** Max chars in the summary. Default `220`. */\n maxSummaryChars?: number;\n /** Number of recent user turns to include in `queryMode === \"recent\"`. Default `2`. */\n recentUserTurns?: number;\n}\n\n/**\n * Everything {@link runActiveMemory} needs for one attempt. Only `userText`,\n * `priorMessages`, `index` and `options` are required; the rest add breaker,\n * cache, transcript persistence and telemetry, each of which is inert when\n * omitted.\n *\n * `index` is accepted as `undefined` on purpose — an agent with memory\n * configured but no index open is a normal state, and it produces a `skipped`\n * result rather than an error.\n */\nexport interface RunActiveMemoryArgs {\n userText: string;\n priorMessages: ReadonlyArray<{ role: \"user\" | \"assistant\"; text: string }>;\n index: MemoryIndex | undefined;\n options: ActiveMemoryOptions;\n /** Per-agent circuit breaker (Phase 8). */\n breaker?: CircuitBreaker;\n /** Per-agent result cache (Phase 8). */\n cache?: ActiveMemoryCache;\n /** Workspace root for transcript persistence. */\n cwd?: string;\n /** When true, write transcript JSON under .theokit/memory/transcripts/active-memory/. */\n persistTranscripts?: boolean;\n /** Stable key the breaker + cache key by (default `default`). */\n agentKey?: string;\n /** Run id for transcript file naming. */\n runId?: string;\n /**\n * T0.1 — optional telemetry handle. When provided AND telemetry is enabled,\n * `memory.recall` span is emitted with `{ userId, namespace, scope, queryMode,\n * hits, status }` attrs and `theokit_memory_recall_duration_ms` histogram is\n * recorded with the same dimension keys.\n */\n telemetry?: TelemetryHandle;\n /** User id surfaced as a memory.recall span attr for cross-tenant tracing. */\n userId?: string;\n /** Memory namespace (e.g. `default`, `<orgId>`) for span/histogram dimensions. */\n namespace?: string;\n /** Memory scope (`session` / `user` / `global`) for span/histogram dimensions. */\n scope?: string;\n}\n\nconst DEFAULTS: Required<Omit<ActiveMemoryOptions, \"enabled\">> = {\n queryMode: \"recent\",\n timeoutMs: 15000,\n maxSummaryChars: 220,\n recentUserTurns: 2,\n};\n\n/**\n * Run one blocking recall before the system prompt is assembled, and report what\n * happened. Never throws for a recall failure: a search that times out or\n * rejects comes back as a `timeout` or `error` status with no summary, and the\n * agent run continues without memory.\n *\n * The order of the short-circuits decides what a caller sees. Recall disabled or\n * no index gives `skipped` with no search. An open circuit breaker gives\n * `skipped` too. A cache hit returns the earlier result as-is, which means it\n * also returns that result's `status` and `durationMs` — a cached `no-recall`\n * looks exactly like a fresh one. An empty query gives `no-recall`.\n *\n * Only a real search reaches the breaker: `timeout` records a timeout, `ok` and\n * `no-recall` record a success, and `error` records neither, so a provider that\n * keeps throwing will not trip the breaker.\n *\n * `timeoutMs` bounds how long this waits, not how long the search runs — the\n * underlying `index.search` is left running when the timer wins. The search asks\n * the index for at most 5 hits regardless of options.\n *\n * Cache entries are keyed by tenant as well as by query text, so two callers\n * with the same question and different `userId` / `namespace` / `scope` never\n * share an entry.\n */\nexport async function runActiveMemory(args: RunActiveMemoryArgs): Promise<ActiveMemoryResult> {\n const started = Date.now();\n // T0.1 — `memory.recall` span emitted around the entire body so skipped /\n // cached / no-recall paths still surface in telemetry with the correct status.\n const span = startMemoryRecallSpan(args);\n try {\n if (args.options.enabled !== true || args.index === undefined) {\n return endRecallSpan(span, args, {\n summary: undefined,\n durationMs: 0,\n status: \"skipped\",\n hits: [],\n });\n }\n const cfg = { ...DEFAULTS, ...args.options };\n const breakerKey = args.agentKey ?? \"default\";\n if (args.breaker?.shouldSkip(breakerKey) === true) {\n return endRecallSpan(span, args, {\n summary: undefined,\n durationMs: 0,\n status: \"skipped\",\n hits: [],\n });\n }\n // #56 (GAP-B) — key the cache read by tenant identity so two callers with\n // the same query text but different identity never share a cache entry.\n const tenantCtx: TenantContext = {\n namespace: args.namespace,\n userId: args.userId,\n scope: args.scope,\n };\n const cached = args.cache?.get(args.userText, cfg.queryMode, tenantCtx);\n if (cached !== undefined) return endRecallSpan(span, args, cached);\n\n const query = buildQuery(args.userText, args.priorMessages, cfg.queryMode, cfg.recentUserTurns);\n if (query.trim().length === 0) {\n const finalized = await finalize(args, cfg.queryMode, {\n summary: undefined,\n durationMs: Date.now() - started,\n status: \"no-recall\",\n hits: [],\n });\n return endRecallSpan(span, args, finalized);\n }\n const result = await searchOnce(args, cfg, query, started);\n notifyBreaker(args.breaker, breakerKey, result.status);\n const finalized = await finalize(args, cfg.queryMode, result);\n return endRecallSpan(span, args, finalized);\n } catch (cause) {\n span.recordException(cause);\n span.setStatus({ code: 2, message: cause instanceof Error ? cause.message : String(cause) });\n span.end();\n throw cause;\n }\n}\n\nfunction startMemoryRecallSpan(args: RunActiveMemoryArgs): OTelSpan {\n const telemetry: TelemetryHandle | undefined = args.telemetry;\n if (telemetry === undefined) {\n // No-op span identical to the runtime no-op when telemetry is disabled.\n return {\n setAttribute: () => {},\n setAttributes: () => {},\n addEvent: () => {},\n setStatus: () => {},\n recordException: () => {},\n end: () => {},\n spanContext: () => ({ traceId: \"0\".repeat(32), spanId: \"0\".repeat(16) }),\n isRecording: () => false,\n };\n }\n return telemetry.startSpan(SPAN_MEMORY_RECALL, {\n queryMode: args.options.queryMode ?? \"recent\",\n ...(args.userId !== undefined ? { userId: args.userId } : {}),\n ...(args.namespace !== undefined ? { namespace: args.namespace } : {}),\n ...(args.scope !== undefined ? { scope: args.scope } : {}),\n });\n}\n\nfunction endRecallSpan(\n span: OTelSpan,\n args: RunActiveMemoryArgs,\n result: ActiveMemoryResult,\n): ActiveMemoryResult {\n span.setAttributes({\n hits: result.hits.length,\n status: result.status,\n durationMs: result.durationMs,\n });\n span.end();\n args.telemetry?.recordHistogram(HISTOGRAM_MEMORY_RECALL_DURATION_MS, result.durationMs, {\n status: result.status,\n ...(args.userId !== undefined ? { userId: args.userId } : {}),\n ...(args.namespace !== undefined ? { namespace: args.namespace } : {}),\n ...(args.scope !== undefined ? { scope: args.scope } : {}),\n });\n return result;\n}\n\ninterface ResolvedConfig {\n queryMode: ActiveMemoryQueryMode;\n timeoutMs: number;\n maxSummaryChars: number;\n recentUserTurns: number;\n}\n\nasync function searchOnce(\n args: RunActiveMemoryArgs,\n cfg: ResolvedConfig,\n query: string,\n started: number,\n): Promise<ActiveMemoryResult> {\n if (args.index === undefined) {\n return { summary: undefined, durationMs: 0, status: \"skipped\", hits: [] };\n }\n try {\n const hits = await withTimeout(args.index.search(query, { maxResults: 5 }), cfg.timeoutMs);\n if (hits === \"timeout\") {\n return { summary: undefined, durationMs: Date.now() - started, status: \"timeout\", hits: [] };\n }\n if (hits.length === 0) {\n return {\n summary: undefined,\n durationMs: Date.now() - started,\n status: \"no-recall\",\n hits: [],\n };\n }\n const summary = formatSummary(hits, cfg.maxSummaryChars);\n return { summary, durationMs: Date.now() - started, status: \"ok\", hits };\n } catch (cause) {\n const message = cause instanceof Error ? cause.message : String(cause);\n process.stderr.write(`[theokit-sdk] active-memory recall failed: ${message}\\n`);\n return { summary: undefined, durationMs: Date.now() - started, status: \"error\", hits: [] };\n }\n}\n\nfunction notifyBreaker(\n breaker: CircuitBreaker | undefined,\n key: string,\n status: ActiveMemoryStatus,\n): void {\n if (breaker === undefined) return;\n if (status === \"timeout\") breaker.recordTimeout(key);\n else if (status === \"ok\" || status === \"no-recall\") breaker.recordSuccess(key);\n}\n\nasync function finalize(\n args: RunActiveMemoryArgs,\n queryMode: ActiveMemoryQueryMode,\n result: ActiveMemoryResult,\n): Promise<ActiveMemoryResult> {\n // #56 (GAP-B) — key the cache write by tenant identity (mirrors the get side).\n const tenantCtx: TenantContext = {\n namespace: args.namespace,\n userId: args.userId,\n scope: args.scope,\n };\n args.cache?.set(args.userText, queryMode, result, tenantCtx);\n if (args.persistTranscripts === true && args.cwd !== undefined) {\n await persistActiveMemoryTranscript(args.cwd, {\n runId: args.runId ?? `run-${Date.now()}`,\n startedAtMs: Date.now() - result.durationMs,\n userText: args.userText,\n queryMode,\n status: result.status,\n durationMs: result.durationMs,\n summary: result.summary,\n hits: result.hits.map((h) => ({\n path: h.path,\n startLine: h.startLine,\n endLine: h.endLine,\n score: h.score,\n snippet: h.snippet,\n })),\n });\n }\n return result;\n}\n\nfunction buildQuery(\n userText: string,\n priorMessages: ReadonlyArray<{ role: \"user\" | \"assistant\"; text: string }>,\n queryMode: ActiveMemoryQueryMode,\n recentUserTurns: number,\n): string {\n if (queryMode === \"message\") return userText;\n if (queryMode === \"full\") {\n const allUserTurns = priorMessages.filter((m) => m.role === \"user\").map((m) => m.text);\n return [...allUserTurns, userText].join(\"\\n\");\n }\n // recent\n const recent = priorMessages\n .filter((m) => m.role === \"user\")\n .slice(-recentUserTurns)\n .map((m) => m.text);\n return [...recent, userText].join(\"\\n\");\n}\n\nfunction formatSummary(hits: ReadonlyArray<MemorySearchHit>, maxChars: number): string {\n const lines = hits.map((h) => `- ${h.citation}: ${h.snippet}`);\n let summary = lines.join(\"\\n\");\n if (summary.length > maxChars) summary = `${summary.slice(0, maxChars - 1)}…`;\n return summary;\n}\n\nasync function withTimeout<T>(promise: Promise<T>, timeoutMs: number): Promise<T | \"timeout\"> {\n let timer: NodeJS.Timeout | undefined;\n const timeout = new Promise<\"timeout\">((resolve) => {\n timer = setTimeout(() => resolve(\"timeout\"), timeoutMs);\n });\n try {\n const winner = await Promise.race([promise, timeout]);\n return winner;\n } finally {\n if (timer !== undefined) clearTimeout(timer);\n }\n}\n","/**\n * Consecutive-timeout circuit breaker for Active Memory recall.\n *\n * Mirrors peer-project's `circuitBreakerMaxTimeouts` + `circuitBreakerCooldownMs`\n * config: after N consecutive timeouts the breaker trips and `shouldSkip`\n * returns `true` until `cooldownMs` has elapsed. A successful recall resets\n * the counter immediately.\n *\n * Per-key isolation so two agents in the same process don't share a counter.\n *\n * @internal\n */\n\nexport interface CircuitBreakerOptions {\n maxTimeouts?: number;\n cooldownMs?: number;\n /** Injectable clock for tests. */\n now?: () => number;\n}\n\ninterface KeyState {\n consecutiveTimeouts: number;\n cooldownUntilMs: number;\n}\n\nconst DEFAULT_MAX_TIMEOUTS = 3;\nconst DEFAULT_COOLDOWN_MS = 60_000;\n\n/**\n * Stops calling a recall path that keeps timing out.\n *\n * After `maxTimeouts` consecutive timeouts on a key (default 3) the breaker\n * opens and {@link CircuitBreaker.shouldSkip} reports `true` until `cooldownMs`\n * has elapsed (default 60s). The first `shouldSkip` after the cooldown closes\n * the breaker and resets the counter, so it re-opens only after another full run\n * of timeouts.\n *\n * It counts timeouts, not failures. An error recorded by neither\n * `recordTimeout` nor `recordSuccess` leaves the counter where it was, so a call\n * path that throws rather than hanging will never trip it.\n *\n * State is per key and held in this instance, which is what keeps two agents in\n * one process from sharing a counter. Construct one per agent and pass a stable\n * key.\n */\nexport class CircuitBreaker {\n private readonly states = new Map<string, KeyState>();\n\n constructor(private readonly opts: CircuitBreakerOptions = {}) {}\n\n /** @returns true when the breaker is open and the call should be skipped. */\n shouldSkip(key: string): boolean {\n const state = this.states.get(key);\n if (state === undefined) return false;\n if (state.cooldownUntilMs === 0) return false;\n if (this.now() < state.cooldownUntilMs) return true;\n // Cooldown elapsed — close the breaker.\n state.cooldownUntilMs = 0;\n state.consecutiveTimeouts = 0;\n return false;\n }\n\n recordSuccess(key: string): void {\n const state = this.states.get(key);\n if (state === undefined) return;\n state.consecutiveTimeouts = 0;\n state.cooldownUntilMs = 0;\n }\n\n recordTimeout(key: string): void {\n const state = this.states.get(key) ?? { consecutiveTimeouts: 0, cooldownUntilMs: 0 };\n state.consecutiveTimeouts += 1;\n if (state.consecutiveTimeouts >= (this.opts.maxTimeouts ?? DEFAULT_MAX_TIMEOUTS)) {\n state.cooldownUntilMs = this.now() + (this.opts.cooldownMs ?? DEFAULT_COOLDOWN_MS);\n }\n this.states.set(key, state);\n }\n\n /** @internal — tests inspect counter state. */\n inspect(key: string): Readonly<KeyState> {\n return this.states.get(key) ?? { consecutiveTimeouts: 0, cooldownUntilMs: 0 };\n }\n\n private now(): number {\n return this.opts.now?.() ?? Date.now();\n }\n}\n","import { createHash } from \"node:crypto\";\n\n// T4.1 / D438 — import from leaf to break the active-memory cluster cycle (#10).\nimport type { ActiveMemoryResult } from \"./active-memory-types.js\";\n\n/**\n * TTL-bounded cache for `runActiveMemory` results. Keyed by\n * `sha256(userText + queryMode)` so two identical sends within `cacheTtlMs`\n * (default 15s, matching peer-project's `DEFAULT_CACHE_TTL_MS`) share a single\n * search.\n *\n * Bounded size; oldest entries evicted first when capacity is exceeded.\n *\n * Iter 51 (Stage 3 source-move #8): hybrid copy from sdk-core's\n * `internal/memory/active-memory-cache.ts`. sdk-core retains its copy\n * for v1.x active-memory back-compat; sdk-memory ships the canonical\n * copy that the future `active-memory.ts` move will target as a\n * sibling. Depends only on `node:crypto` + `./active-memory-types.js`\n * (moved iter 48), so no further dependency chain is required.\n *\n * @internal\n */\n\nexport interface ActiveMemoryCacheOptions {\n ttlMs?: number;\n capacity?: number;\n now?: () => number;\n}\n\ninterface CacheEntry {\n expiresAtMs: number;\n result: ActiveMemoryResult;\n}\n\nconst DEFAULT_TTL_MS = 15_000;\nconst DEFAULT_CAPACITY = 1000;\n\n/**\n * A bounded, TTL-expiring cache of recall results, so two identical sends in\n * quick succession run one search.\n *\n * Entries expire `ttlMs` after they were written (default 15s) and are dropped\n * on the read that finds them expired. A read that hits also moves the entry to\n * the most-recent position, so eviction under pressure removes the\n * least-recently-read entry rather than the oldest write.\n *\n * The key covers the query text, the query mode, and the tenant triple\n * (`namespace`, `userId`, `scope`) joined by NUL bytes. Passing no tenant\n * context is allowed and hashes as three empty strings — safe only when the\n * process serves a single tenant.\n *\n * Not process-wide: construct one per agent. Nothing here expires in the\n * background, so an untouched entry occupies its slot until it is read or\n * evicted.\n */\nexport class ActiveMemoryCache {\n private readonly map = new Map<string, CacheEntry>();\n\n constructor(private readonly opts: ActiveMemoryCacheOptions = {}) {}\n\n get(\n userText: string,\n queryMode: string,\n tenantCtx?: TenantContext,\n ): ActiveMemoryResult | undefined {\n const key = cacheKey(userText, queryMode, tenantCtx);\n const entry = this.map.get(key);\n if (entry === undefined) return undefined;\n if (this.now() >= entry.expiresAtMs) {\n this.map.delete(key);\n return undefined;\n }\n // LRU bump\n this.map.delete(key);\n this.map.set(key, entry);\n return entry.result;\n }\n\n set(\n userText: string,\n queryMode: string,\n result: ActiveMemoryResult,\n tenantCtx?: TenantContext,\n ): void {\n const key = cacheKey(userText, queryMode, tenantCtx);\n if (this.map.size >= (this.opts.capacity ?? DEFAULT_CAPACITY)) {\n const oldest = this.map.keys().next().value;\n if (oldest !== undefined) this.map.delete(oldest);\n }\n this.map.set(key, {\n expiresAtMs: this.now() + (this.opts.ttlMs ?? DEFAULT_TTL_MS),\n result,\n });\n }\n\n size(): number {\n return this.map.size;\n }\n\n private now(): number {\n return this.opts.now?.() ?? Date.now();\n }\n}\n\n/**\n * T4.9 — Tenant isolation context for cache key derivation.\n * Pre-T4.9 the key was `sha256(queryMode + userText)` — two users\n * sharing a process with the same query got each other's results.\n * CRITICAL cross-tenant data leak (DR4 finding #9).\n *\n * Synced from sdk-core's `internal/memory/active-memory-cache.ts`\n * per ADR 0002 Stage 4 routing byte-equivalence invariant (iter 112).\n *\n * @internal\n */\nexport interface TenantContext {\n namespace?: string;\n userId?: string;\n scope?: string;\n}\n\n// T4.9 — cache key now includes namespace, userId, scope separated by\n// NUL bytes to prevent collision between `user: \"ab\"` + `scope: \"cd\"`\n// and `user: \"a\"` + `scope: \"bcd\"` (without separator these hash identically).\nfunction cacheKey(userText: string, queryMode: string, ctx?: TenantContext): string {\n const parts = [queryMode, ctx?.namespace ?? \"\", ctx?.userId ?? \"\", ctx?.scope ?? \"\", userText];\n return createHash(\"sha256\").update(parts.join(\"\\x00\")).digest(\"hex\");\n}\n","import type { MemoryEmbeddingProviderAdapter } from \"./embedding-adapter.js\";\nimport { createOpenAiCompatibleRuntime } from \"./openai-compatible.js\";\n\n// Iter 74 rollup-plugin-dts workaround: see openai-embedding.ts header.\n\n/**\n * Azure OpenAI embedding adapter.\n *\n * Azure addresses the DEPLOYMENT in the path rather than the model in the body:\n * `https://{resource}.openai.azure.com/openai/deployments/{deployment}/embeddings?api-version=...`.\n * `{model}` in `embeddingsPath` is substituted by `createOpenAiCompatibleRuntime`, so `model` here\n * names the Azure deployment.\n *\n * `AZURE_OPENAI_ENDPOINT` supplies the resource URL (without the `/openai/...` suffix);\n * `AZURE_OPENAI_API_KEY` the credential.\n *\n * theokit#128 (catalog parity): sdk-core gained this adapter in T4.10 and the peer never mirrored\n * it, so a `sdk-memory` user asking for `azure-openai` was rejected by a provider the SDK's own\n * `Theokit.inspect.embeddingAdapters()` advertised.\n *\n * @internal\n */\n\nexport const DEFAULT_AZURE_OPENAI_EMBEDDING_MODEL = \"text-embedding-3-small\";\n\nconst DIMENSION_BY_MODEL: Record<string, number> = {\n \"text-embedding-3-small\": 1536,\n \"text-embedding-3-large\": 3072,\n \"text-embedding-ada-002\": 1536,\n};\n\n/**\n * Azure OpenAI embeddings. Same models as the OpenAI adapter, addressed the\n * Azure way, and the one adapter whose configuration is not just \"set a key\".\n *\n * Two things differ from every other adapter here. `model` names your Azure\n * DEPLOYMENT, not an OpenAI model id — it is substituted into the path\n * (`/openai/deployments/{model}/embeddings`) rather than sent in the body. And\n * `AZURE_OPENAI_ENDPOINT` must be set to your resource URL, without the\n * `/openai/...` suffix; the built-in default is a placeholder that resolves\n * nowhere, so leaving it unset fails at the network rather than at\n * configuration.\n *\n * Authentication uses the `api-key` header, which is what an Azure resource key\n * expects; Entra ID bearer tokens are not supported by this adapter. Reads\n * `AZURE_OPENAI_API_KEY`. The API version is pinned to `2024-02-01`.\n *\n * The deployment name still has to appear in the dimension table\n * (`text-embedding-3-small`, `-3-large`, `ada-002`), so a deployment named\n * anything else is refused with `embedding_unknown_model` — pass `model` as the\n * matching id and point the base URL at the right deployment, or add the name to\n * the table.\n */\nexport const azureOpenAiMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapter = {\n id: \"azure-openai\",\n defaultModel: DEFAULT_AZURE_OPENAI_EMBEDDING_MODEL,\n transport: \"remote\" as const,\n authProviderId: \"azure-openai\",\n autoSelectPriority: 25,\n create: (options: Parameters<typeof createOpenAiCompatibleRuntime>[1]) =>\n createOpenAiCompatibleRuntime(\n {\n id: \"azure-openai\",\n defaultBaseUrl: \"https://your-resource.openai.azure.com\",\n apiKeyEnv: \"AZURE_OPENAI_API_KEY\",\n baseUrlEnv: \"AZURE_OPENAI_ENDPOINT\",\n defaultModel: DEFAULT_AZURE_OPENAI_EMBEDDING_MODEL,\n embeddingsPath: \"/openai/deployments/{model}/embeddings?api-version=2024-02-01\",\n dimensionByModel: DIMENSION_BY_MODEL,\n // theokit#159 — Azure is NOT OpenAI on the wire, despite the name. It authenticates an API\n // key with the `api-key` header (`Authorization: Bearer` is for Entra ID tokens, not for\n // AZURE_OPENAI_API_KEY), and the deployment already rides in the path, so `model` has no\n // place in the body. Sending the OpenAI shape meant every request was rejected.\n dialect: {\n authHeaders: (apiKey: string) => ({ \"api-key\": apiKey }),\n body: (_model: string, inputs: ReadonlyArray<string>) => ({ input: inputs }),\n },\n },\n options,\n ),\n};\n","import type { MemoryEmbeddingProviderAdapter } from \"./embedding-adapter.js\";\nimport { createOpenAiCompatibleRuntime } from \"./openai-compatible.js\";\n\n// Iter 74 rollup-plugin-dts workaround: see openai-embedding.ts header.\n\n/**\n * Cohere embedding adapter — `POST /v2/embed` at `https://api.cohere.com`. Despite living beside\n * the OpenAI-compatible adapters, this endpoint is NOT OpenAI-shaped in either direction; the\n * `dialect` below is what makes it work.\n *\n * Honors `COHERE_API_KEY`.\n *\n * theokit#128 (catalog parity): mirrors sdk-core's T4.10 adapter, which the peer never picked up.\n *\n * @internal\n */\n\nexport const DEFAULT_COHERE_EMBEDDING_MODEL = \"embed-english-v3.0\";\n\nconst DIMENSION_BY_MODEL: Record<string, number> = {\n \"embed-english-v3.0\": 1024,\n \"embed-multilingual-v3.0\": 1024,\n \"embed-english-light-v3.0\": 384,\n \"embed-multilingual-light-v3.0\": 384,\n};\n\n/**\n * Cohere embeddings. Priority 30, so it is auto-selected ahead of OpenAI when\n * both keys are present.\n *\n * Cohere does not speak the OpenAI wire, and this adapter supplies a dialect for\n * it: the request names its payload `texts`, the response returns\n * `{embeddings: {float: [...]}}`, and `input_type` is sent as\n * `search_document`. That last choice matters — Cohere's v3 models embed\n * documents and queries into different spaces, and this runtime always embeds as\n * a document, including the query side of a search. Expect somewhat weaker\n * retrieval than a Cohere-native setup that embeds queries as `search_query`.\n *\n * Reads `COHERE_API_KEY`; no base-URL environment override is declared. The\n * light models are 384 dimensions and the others 1024.\n */\nexport const cohereMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapter = {\n id: \"cohere\",\n defaultModel: DEFAULT_COHERE_EMBEDDING_MODEL,\n transport: \"remote\" as const,\n authProviderId: \"cohere\",\n autoSelectPriority: 30,\n create: (options: Parameters<typeof createOpenAiCompatibleRuntime>[1]) =>\n createOpenAiCompatibleRuntime(\n {\n id: \"cohere\",\n defaultBaseUrl: \"https://api.cohere.com\",\n apiKeyEnv: \"COHERE_API_KEY\",\n defaultModel: DEFAULT_COHERE_EMBEDDING_MODEL,\n embeddingsPath: \"/v2/embed\",\n dimensionByModel: DIMENSION_BY_MODEL,\n // theokit#159 — `/v2/embed` diverges in BOTH directions: it names the payload `texts`, requires\n // `input_type`, and answers `{embeddings:{float:[[...]]}}` rather than `{data:[{embedding}]}`.\n // `search_document` is the right default here because this runtime embeds material for\n // storage; a query-side embedder would use `search_query`.\n dialect: {\n body: (model: string, inputs: ReadonlyArray<string>) => ({\n model,\n texts: [...inputs],\n input_type: \"search_document\",\n embedding_types: [\"float\"],\n }),\n vectors: (json: unknown) =>\n (json as { embeddings?: { float?: number[][] } }).embeddings?.float,\n },\n },\n options,\n ),\n};\n","import type { MemoryEmbeddingProviderAdapter } from \"./embedding-adapter.js\";\nimport { createOpenAiCompatibleRuntime } from \"./openai-compatible.js\";\n\n// Iter 74 rollup-plugin-dts workaround: see openai-embedding.ts header.\n\n/**\n * DeepInfra embedding adapter — hosts open-source embedding models\n * (BGE, E5, Jina, etc.) at pay-per-token. OpenAI-compatible REST at\n * `POST /v1/openai/embeddings` (note the `/openai` segment; not the\n * canonical `/v1/embeddings`). The `embeddingsPath` override on\n * `OpenAiCompatibleConfig` REPLACES the default suffix (EC-2).\n *\n * Honors `DEEPINFRA_API_KEY` and `DEEPINFRA_API_BASE_URL`.\n *\n * Iter 74 (Stage 3 source-move #33): hybrid copy from sdk-core's\n * `internal/memory/adapters/deepinfra-embedding.ts`.\n *\n * @internal\n */\n\nexport const DEFAULT_DEEPINFRA_EMBEDDING_MODEL = \"BAAI/bge-large-en-v1.5\";\n\nconst DIMENSION_BY_MODEL: Record<string, number> = {\n \"BAAI/bge-large-en-v1.5\": 1024,\n \"BAAI/bge-base-en-v1.5\": 768,\n \"BAAI/bge-small-en-v1.5\": 384,\n \"BAAI/bge-m3\": 1024,\n \"intfloat/e5-large-v2\": 1024,\n \"intfloat/e5-base-v2\": 768,\n \"intfloat/multilingual-e5-large\": 1024,\n \"sentence-transformers/all-MiniLM-L6-v2\": 384,\n \"thenlper/gte-large\": 1024,\n \"thenlper/gte-base\": 768,\n};\n\n/**\n * Open-weight embedding models (BGE, E5, GTE, MiniLM) hosted by DeepInfra.\n * Reach for it when you want a specific open model — particularly a multilingual\n * one — behind a hosted API rather than running it yourself.\n *\n * Its endpoint is `/v1/openai/embeddings`, not the canonical `/v1/embeddings`;\n * the wire format is otherwise OpenAI-shaped. Reads `DEEPINFRA_API_KEY` and\n * honours `DEEPINFRA_API_BASE_URL`. Priority 13.\n *\n * Dimensions vary sharply across the ten models it knows (384 to 1024), and\n * switching between them invalidates an existing vector index — the index drops\n * every vector and re-embeds on the next sync.\n */\nexport const deepinfraMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapter = {\n id: \"deepinfra\",\n defaultModel: DEFAULT_DEEPINFRA_EMBEDDING_MODEL,\n transport: \"remote\" as const,\n authProviderId: \"deepinfra\",\n autoSelectPriority: 13,\n create: (options: Parameters<typeof createOpenAiCompatibleRuntime>[1]) =>\n createOpenAiCompatibleRuntime(\n {\n id: \"deepinfra\",\n defaultBaseUrl: \"https://api.deepinfra.com\",\n apiKeyEnv: \"DEEPINFRA_API_KEY\",\n baseUrlEnv: \"DEEPINFRA_API_BASE_URL\",\n defaultModel: DEFAULT_DEEPINFRA_EMBEDDING_MODEL,\n dimensionByModel: DIMENSION_BY_MODEL,\n embeddingsPath: \"/v1/openai/embeddings\",\n },\n options,\n ),\n};\n","import type { MemoryEmbeddingProviderAdapter } from \"./embedding-adapter.js\";\nimport { createOpenAiCompatibleRuntime } from \"./openai-compatible.js\";\n\n// Iter 74 rollup-plugin-dts workaround: see openai-embedding.ts header.\n\n/**\n * Google Gemini embedding adapter — the OpenAI-compatible surface at\n * `https://generativelanguage.googleapis.com/v1/embeddings`.\n *\n * Gemini's NATIVE embedding endpoint has a different shape\n * (`POST /v1beta/models/{model}:embedContent`); this adapter deliberately targets the\n * OpenAI-compatible one so it composes with the shared runtime.\n *\n * Honors `GEMINI_API_KEY`.\n *\n * theokit#128 (catalog parity): mirrors sdk-core's T4.10 adapter, which the peer never picked up.\n *\n * @internal\n */\n\nexport const DEFAULT_GEMINI_EMBEDDING_MODEL = \"text-embedding-004\";\n\nconst DIMENSION_BY_MODEL: Record<string, number> = {\n \"text-embedding-004\": 768,\n \"embedding-001\": 768,\n};\n\n/**\n * Google Gemini embeddings through Google's OpenAI-compatible surface at\n * `/v1beta/openai/embeddings`. Gemini's native embedding endpoint\n * (`/v1beta/models/{model}:embedContent`) has a different shape and is\n * deliberately not used, so this composes with the shared runtime like the rest.\n *\n * Both known models are 768 dimensions. Reads `GEMINI_API_KEY`; no base-URL\n * environment override is declared. Priority 30.\n */\nexport const geminiMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapter = {\n id: \"gemini\",\n defaultModel: DEFAULT_GEMINI_EMBEDDING_MODEL,\n transport: \"remote\" as const,\n authProviderId: \"gemini\",\n autoSelectPriority: 30,\n create: (options: Parameters<typeof createOpenAiCompatibleRuntime>[1]) =>\n createOpenAiCompatibleRuntime(\n {\n id: \"gemini\",\n defaultBaseUrl: \"https://generativelanguage.googleapis.com\",\n apiKeyEnv: \"GEMINI_API_KEY\",\n defaultModel: DEFAULT_GEMINI_EMBEDDING_MODEL,\n // theokit#159 — the compat surface is under `/v1beta/openai/`, not the default\n // `/v1/embeddings`; the previous path 404'd on every call.\n embeddingsPath: \"/v1beta/openai/embeddings\",\n dimensionByModel: DIMENSION_BY_MODEL,\n },\n options,\n ),\n};\n","import type { MemoryEmbeddingProviderAdapter } from \"./embedding-adapter.js\";\nimport { createOpenAiCompatibleRuntime } from \"./openai-compatible.js\";\n\n// Iter 74 rollup-plugin-dts workaround: see openai-embedding.ts header.\n\n/**\n * Jina AI embedding adapter — OpenAI-compatible at `https://api.jina.ai/v1/embeddings`.\n *\n * Honors `JINA_API_KEY`.\n *\n * theokit#128 (catalog parity): mirrors sdk-core's T4.10 adapter, which the peer never picked up.\n *\n * @internal\n */\n\nexport const DEFAULT_JINA_EMBEDDING_MODEL = \"jina-embeddings-v3\";\n\nconst DIMENSION_BY_MODEL: Record<string, number> = {\n \"jina-embeddings-v3\": 1024,\n \"jina-embeddings-v2-base-en\": 768,\n \"jina-embeddings-v2-small-en\": 512,\n};\n\n/**\n * Jina AI embeddings, over the standard OpenAI wire. Highest auto-select\n * priority in the catalog (35), so it wins over OpenAI when both keys are\n * present.\n *\n * Default `jina-embeddings-v3` at 1024 dimensions; the v2 models are 768 and\n * 512. Reads `JINA_API_KEY`. No base-URL environment override is declared —\n * point it elsewhere by passing `baseUrl` to `create`.\n */\nexport const jinaMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapter = {\n id: \"jina\",\n defaultModel: DEFAULT_JINA_EMBEDDING_MODEL,\n transport: \"remote\" as const,\n authProviderId: \"jina\",\n autoSelectPriority: 35,\n create: (options: Parameters<typeof createOpenAiCompatibleRuntime>[1]) =>\n createOpenAiCompatibleRuntime(\n {\n id: \"jina\",\n defaultBaseUrl: \"https://api.jina.ai\",\n apiKeyEnv: \"JINA_API_KEY\",\n defaultModel: DEFAULT_JINA_EMBEDDING_MODEL,\n dimensionByModel: DIMENSION_BY_MODEL,\n },\n options,\n ),\n};\n","import type { MemoryEmbeddingProviderAdapter } from \"./embedding-adapter.js\";\nimport { createOpenAiCompatibleRuntime } from \"./openai-compatible.js\";\n\n// Iter 74 rollup-plugin-dts workaround: see openai-embedding.ts header.\n\n/**\n * Mistral embedding adapter — OpenAI-compatible REST surface\n * (`POST /v1/embeddings` against `https://api.mistral.ai`). Default model\n * `mistral-embed` (1024 dims).\n *\n * Mirrors `reference/peer-project/extensions/mistral/memory-embedding-adapter.ts`.\n *\n * Iter 74 (Stage 3 source-move #32): hybrid copy from sdk-core's\n * `internal/memory/adapters/mistral-embedding.ts`.\n *\n * @internal\n */\n\nexport const DEFAULT_MISTRAL_EMBEDDING_MODEL = \"mistral-embed\";\n\nconst DIMENSION_BY_MODEL: Record<string, number> = {\n \"mistral-embed\": 1024,\n};\n\n/**\n * Mistral embeddings, over the standard OpenAI wire. One model only,\n * `mistral-embed` at 1024 dimensions; any other id is refused with\n * `embedding_unknown_model`.\n *\n * Reads `MISTRAL_API_KEY` and honours `MISTRAL_API_BASE_URL`. Priority 18, just\n * below OpenAI.\n */\nexport const mistralMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapter = {\n id: \"mistral\",\n defaultModel: DEFAULT_MISTRAL_EMBEDDING_MODEL,\n transport: \"remote\" as const,\n authProviderId: \"mistral\",\n autoSelectPriority: 18,\n create: (options: Parameters<typeof createOpenAiCompatibleRuntime>[1]) =>\n createOpenAiCompatibleRuntime(\n {\n id: \"mistral\",\n defaultBaseUrl: \"https://api.mistral.ai\",\n apiKeyEnv: \"MISTRAL_API_KEY\",\n baseUrlEnv: \"MISTRAL_API_BASE_URL\",\n defaultModel: DEFAULT_MISTRAL_EMBEDDING_MODEL,\n dimensionByModel: DIMENSION_BY_MODEL,\n },\n options,\n ),\n};\n","/**\n * Ollama embedding adapter (T3.1, ADR D183).\n *\n * Targets Ollama's OpenAI-compatible `/v1/embeddings` endpoint and reuses\n * the shared `createOpenAiCompatibleRuntime` factory. The differentiating\n * bits:\n *\n * - `authType: \"none\"` — Ollama local ignores `Authorization`. Sentinel\n * `\"ollama-local\"` is passed as apiKey to satisfy the factory contract\n * (mirrors peer-project `OLLAMA_DEFAULT_API_KEY = \"ollama-local\"`).\n * - `OLLAMA_HOST` overrides the default `http://localhost:11434`.\n * - `OLLAMA_API_KEY` (optional) overrides the sentinel for Ollama Cloud\n * or reverse-proxy auth setups.\n * - Default model: `nomic-embed-text` (768 dim, ~274MB). User can opt\n * into `all-minilm` (384 dim, ~45MB) or any other locally-installed\n * embedding model.\n *\n * EC-B MUST FIX (edge-case review 2026-05-21): empty text is rejected\n * upstream in the shared factory (`classifyEntry` short-circuits to a\n * zero vector). That behavior is acceptable here because the zero\n * vector is identical for any empty input — downstream similarity\n * calcs ignore zero-norm vectors via the existing `cosineSimilarity`\n * guard. No additional fail-fast needed.\n *\n * EC-A MUST FIX (edge-case review 2026-05-21): dimension is locked\n * by the `DIMENSION_BY_MODEL` table; an unknown model id throws\n * `ConfigurationError(code: \"embedding_unknown_model\")` per the\n * factory's EC-4 contract. Future model versions with different\n * dimensions are added to the table here without breaking changes.\n *\n * Iter 74 (Stage 3 source-move #36): hybrid copy from sdk-core's\n * `internal/memory/adapters/ollama-embedding.ts`. The only\n * `transport: \"local\"` adapter in the cluster — enables 100%-local\n * RAG with no remote API key.\n *\n * @internal\n */\n\nimport type { MemoryEmbeddingProviderAdapter } from \"./embedding-adapter.js\";\nimport { createOpenAiCompatibleRuntime } from \"./openai-compatible.js\";\n\n// Iter 74 rollup-plugin-dts workaround: see openai-embedding.ts header.\n\n/**\n * Model used when the caller names none: `nomic-embed-text`, 768 dimensions,\n * roughly 274MB to pull. `all-minilm` is the smaller alternative at 384\n * dimensions and roughly 45MB.\n */\nexport const DEFAULT_OLLAMA_EMBEDDING_MODEL = \"nomic-embed-text\";\n\n/** Sentinel forwarded as Bearer token; Ollama local ignores Authorization. */\nconst OLLAMA_LOCAL_SENTINEL_KEY = \"ollama-local\";\n\nconst DIMENSION_BY_MODEL: Record<string, number> = {\n // Nomic — local default, recommended quality/size balance.\n \"nomic-embed-text\": 768,\n \"nomic-embed-text:latest\": 768,\n // Sentence-transformers MiniLM — smaller, faster, lower quality.\n \"all-minilm\": 384,\n \"all-minilm:latest\": 384,\n // BGE family.\n \"bge-large\": 1024,\n \"bge-large:latest\": 1024,\n \"bge-m3\": 1024,\n \"bge-m3:latest\": 1024,\n // mxbai-embed-large.\n \"mxbai-embed-large\": 1024,\n \"mxbai-embed-large:latest\": 1024,\n};\n\n/**\n * Embeddings from a local Ollama instance — the only adapter in the catalog with\n * `transport: \"local\"`, and the one to choose when the corpus must not leave the\n * machine or when there is no API key to spend.\n *\n * It needs an Ollama server reachable at `OLLAMA_HOST` (default\n * `http://localhost:11434`) with the chosen embedding model already pulled;\n * nothing here starts a server or downloads a model, so a missing model surfaces\n * as an HTTP error from Ollama rather than a configuration error.\n *\n * No credential is required: a sentinel key is sent and local Ollama ignores it.\n * Set `OLLAMA_API_KEY` for Ollama Cloud or an authenticating reverse proxy.\n *\n * Auto-select priority is 10, the lowest in the catalog, so a configured remote\n * provider wins over it. Request it explicitly to prefer local.\n */\nexport const ollamaMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapter = {\n id: \"ollama\",\n defaultModel: DEFAULT_OLLAMA_EMBEDDING_MODEL,\n transport: \"local\" as const,\n authProviderId: \"ollama\",\n // Lower than remote providers — chosen only when explicitly requested\n // OR when no remote provider key is configured (local-first developer).\n autoSelectPriority: 10,\n create: (options: Parameters<typeof createOpenAiCompatibleRuntime>[1]) => {\n // Honor OLLAMA_API_KEY (Ollama Cloud / reverse-proxy auth), else use\n // sentinel that local Ollama silently ignores. This mirrors\n // `sentinelForNoAuth` in router.ts and peer-project's `resolveSyntheticAuth`.\n const apiKey = options.apiKey ?? process.env.OLLAMA_API_KEY ?? OLLAMA_LOCAL_SENTINEL_KEY;\n return createOpenAiCompatibleRuntime(\n {\n id: \"ollama\",\n defaultBaseUrl: \"http://localhost:11434\",\n apiKeyEnv: \"OLLAMA_API_KEY\",\n baseUrlEnv: \"OLLAMA_HOST\",\n defaultModel: DEFAULT_OLLAMA_EMBEDDING_MODEL,\n dimensionByModel: DIMENSION_BY_MODEL,\n },\n { ...options, apiKey },\n );\n },\n};\n","import type { MemoryEmbeddingProviderAdapter } from \"./embedding-adapter.js\";\nimport { createOpenAiCompatibleRuntime } from \"./openai-compatible.js\";\n\n// **Iter 74 rollup-plugin-dts workaround:** importing\n// `MemoryEmbeddingProviderAdapter` from sibling `./embedding-adapter.js`\n// fails dts emit because no public type reaches it transitively yet\n// (same iter 48/53/55/66/67/69/72 class). Fix: drop the explicit\n// type annotation on the exported adapter; TS infers the structural\n// shape from the literal, and the catalog (iter 37 / this same iter)\n// pin assignability against the canonical interface via its own\n// `Record<string, MemoryEmbeddingProviderAdapter>` constraint.\n\n/**\n * OpenAI embedding adapter (ADR D3) — built on the shared OpenAI-compatible\n * factory. Native fetch only.\n *\n * Iter 74 (Stage 3 source-move #31): hybrid copy from sdk-core's\n * `internal/memory/adapters/openai-embedding.ts`. Composes iter 45's\n * `MemoryEmbeddingProviderAdapter` + iter 73's\n * `createOpenAiCompatibleRuntime`.\n *\n * @internal\n */\n\nexport const DEFAULT_OPENAI_EMBEDDING_MODEL = \"text-embedding-3-small\";\n\nconst DIMENSION_BY_MODEL: Record<string, number> = {\n \"text-embedding-3-small\": 1536,\n \"text-embedding-3-large\": 3072,\n \"text-embedding-ada-002\": 1536,\n};\n\n/**\n * OpenAI embeddings — `text-embedding-3-small` (1536), `text-embedding-3-large` (3072) and\n * `text-embedding-ada-002` (1536).\n *\n * It is NOT selected for you. The provider is whatever the caller names in\n * `embedding: { provider }`; omit that and no embedding runtime is built at all. Its\n * `autoSelectPriority` of `20` is metadata no code path reads today, and it is not the highest\n * value in the catalog either — `jina` is 35, `cohere` and `gemini` are 30, `azure-openai` is 25.\n * The 3072-wide `text-embedding-3-large` is reachable through `azure-openai` and, as\n * `openai/text-embedding-3-large`, through `openrouter` as well.\n *\n * Reads `OPENAI_API_KEY`; `OPENAI_API_BASE_URL` redirects it at a compatible\n * gateway. `create` rejects with an `AuthenticationError`\n * (`embedding_missing_api_key`) when no key is found, and with a\n * `ConfigurationError` (`embedding_unknown_model`) for a model outside\n * `text-embedding-3-small`, `text-embedding-3-large` and\n * `text-embedding-ada-002` — the dimension has to be known before any vector\n * table is created, so an unlisted model is refused rather than probed.\n */\nexport const openAiMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapter = {\n id: \"openai\",\n defaultModel: DEFAULT_OPENAI_EMBEDDING_MODEL,\n transport: \"remote\" as const,\n authProviderId: \"openai\",\n autoSelectPriority: 20,\n create: (options: Parameters<typeof createOpenAiCompatibleRuntime>[1]) =>\n createOpenAiCompatibleRuntime(\n {\n id: \"openai\",\n defaultBaseUrl: \"https://api.openai.com\",\n apiKeyEnv: \"OPENAI_API_KEY\",\n baseUrlEnv: \"OPENAI_API_BASE_URL\",\n defaultModel: DEFAULT_OPENAI_EMBEDDING_MODEL,\n dimensionByModel: DIMENSION_BY_MODEL,\n },\n options,\n ),\n};\n","import type { MemoryEmbeddingProviderAdapter } from \"./embedding-adapter.js\";\nimport { createOpenAiCompatibleRuntime } from \"./openai-compatible.js\";\n\n// Iter 74 rollup-plugin-dts workaround: see openai-embedding.ts header.\n\n/**\n * OpenRouter embedding adapter — routes through OpenRouter's\n * `POST /api/v1/embeddings` endpoint (OpenAI-compatible request/response\n * shape). The provider id strings follow OpenRouter's catalog\n * (e.g. `\"openai/text-embedding-3-small\"`, `\"mistralai/mistral-embed\"`).\n *\n * Honors `OPENROUTER_API_KEY` and `OPENROUTER_API_BASE_URL`. Default base\n * URL is `https://openrouter.ai/api`.\n *\n * Iter 74 (Stage 3 source-move #35): hybrid copy from sdk-core's\n * `internal/memory/adapters/openrouter-embedding.ts`.\n *\n * @internal\n */\n\nexport const DEFAULT_OPENROUTER_EMBEDDING_MODEL = \"openai/text-embedding-3-small\";\n\nconst DIMENSION_BY_MODEL: Record<string, number> = {\n \"openai/text-embedding-3-small\": 1536,\n \"openai/text-embedding-3-large\": 3072,\n \"openai/text-embedding-ada-002\": 1536,\n \"mistralai/mistral-embed\": 1024,\n};\n\n/**\n * Embeddings routed through OpenRouter, which lets one key reach several\n * upstream providers. Use it when you want to switch provider without changing\n * credentials; use the provider's own adapter when you want its full model\n * range, since only the four ids in this adapter's dimension table are\n * accepted.\n *\n * Model ids carry the upstream prefix, for example\n * `openai/text-embedding-3-small` or `mistralai/mistral-embed`. The endpoint is\n * `/v1/embeddings` under the base `https://openrouter.ai/api`. Reads\n * `OPENROUTER_API_KEY` and honours `OPENROUTER_API_BASE_URL`. Priority 15.\n */\nexport const openRouterMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapter = {\n id: \"openrouter\",\n defaultModel: DEFAULT_OPENROUTER_EMBEDDING_MODEL,\n transport: \"remote\" as const,\n authProviderId: \"openrouter\",\n autoSelectPriority: 15,\n create: (options: Parameters<typeof createOpenAiCompatibleRuntime>[1]) =>\n createOpenAiCompatibleRuntime(\n {\n id: \"openrouter\",\n defaultBaseUrl: \"https://openrouter.ai/api\",\n apiKeyEnv: \"OPENROUTER_API_KEY\",\n baseUrlEnv: \"OPENROUTER_API_BASE_URL\",\n defaultModel: DEFAULT_OPENROUTER_EMBEDDING_MODEL,\n dimensionByModel: DIMENSION_BY_MODEL,\n },\n options,\n ),\n};\n","import type { MemoryEmbeddingProviderAdapter } from \"./embedding-adapter.js\";\nimport { createOpenAiCompatibleRuntime } from \"./openai-compatible.js\";\n\n// Iter 74 rollup-plugin-dts workaround: see openai-embedding.ts header.\n\n/**\n * Voyage AI embedding adapter — `POST /v1/embeddings` at\n * `https://api.voyageai.com` with the OpenAI-compatible `{ model, input }`\n * request shape. Free tier (200M tokens/month) covers most SDK use.\n *\n * Honors `VOYAGE_API_KEY` and `VOYAGE_API_BASE_URL`.\n *\n * Iter 74 (Stage 3 source-move #34): hybrid copy from sdk-core's\n * `internal/memory/adapters/voyage-embedding.ts`.\n *\n * @internal\n */\n\nexport const DEFAULT_VOYAGE_EMBEDDING_MODEL = \"voyage-3-lite\";\n\nconst DIMENSION_BY_MODEL: Record<string, number> = {\n \"voyage-3-lite\": 512,\n \"voyage-3\": 1024,\n \"voyage-3-large\": 1024,\n \"voyage-code-3\": 1024,\n \"voyage-multilingual-2\": 1024,\n};\n\n/**\n * Voyage AI embeddings, over the standard OpenAI wire. Default model\n * `voyage-3-lite` at 512 dimensions — the narrowest in the catalog, which makes\n * the index smaller and the search cheaper at some cost in quality; `voyage-3`\n * and `voyage-3-large` are 1024, and `voyage-code-3` is the one to pick for\n * source code.\n *\n * Reads `VOYAGE_API_KEY` and honours `VOYAGE_API_BASE_URL`. Priority 14.\n */\nexport const voyageMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapter = {\n id: \"voyage\",\n defaultModel: DEFAULT_VOYAGE_EMBEDDING_MODEL,\n transport: \"remote\" as const,\n authProviderId: \"voyage\",\n autoSelectPriority: 14,\n create: (options: Parameters<typeof createOpenAiCompatibleRuntime>[1]) =>\n createOpenAiCompatibleRuntime(\n {\n id: \"voyage\",\n defaultBaseUrl: \"https://api.voyageai.com\",\n apiKeyEnv: \"VOYAGE_API_KEY\",\n baseUrlEnv: \"VOYAGE_API_BASE_URL\",\n defaultModel: DEFAULT_VOYAGE_EMBEDDING_MODEL,\n dimensionByModel: DIMENSION_BY_MODEL,\n },\n options,\n ),\n};\n","import { azureOpenAiMemoryEmbeddingProviderAdapter } from \"./embedding/azure-openai-embedding.js\";\nimport { cohereMemoryEmbeddingProviderAdapter } from \"./embedding/cohere-embedding.js\";\nimport { deepinfraMemoryEmbeddingProviderAdapter } from \"./embedding/deepinfra-embedding.js\";\nimport { geminiMemoryEmbeddingProviderAdapter } from \"./embedding/gemini-embedding.js\";\nimport { jinaMemoryEmbeddingProviderAdapter } from \"./embedding/jina-embedding.js\";\nimport { mistralMemoryEmbeddingProviderAdapter } from \"./embedding/mistral-embedding.js\";\nimport { ollamaMemoryEmbeddingProviderAdapter } from \"./embedding/ollama-embedding.js\";\nimport { openAiMemoryEmbeddingProviderAdapter } from \"./embedding/openai-embedding.js\";\nimport { openRouterMemoryEmbeddingProviderAdapter } from \"./embedding/openrouter-embedding.js\";\nimport { voyageMemoryEmbeddingProviderAdapter } from \"./embedding/voyage-embedding.js\";\n\n// Iter 74 rollup-plugin-dts workaround: see openai-embedding.ts header.\n// Catalog value type is inferred from the literal record; canonical\n// assignability is checked at consumer call sites that destructure into\n// the canonical `MemoryEmbeddingProviderAdapter` shape.\n\n/**\n * Memory embedding adapter catalog, indexed by provider id.\n *\n * Only adapters with full, tested implementations are exposed. The\n * `openrouter` provider proxies through OpenRouter to whichever embedding\n * model the caller selects via `model` (e.g.\n * `\"openai/text-embedding-3-small\"`, `\"mistralai/mistral-embed\"`).\n *\n * Locked by ADR D11: `openai`, `mistral`, `openrouter`, `voyage`, `deepinfra`\n * ship in v1.0. ADR D183: `ollama` added — first `transport: \"local\"`\n * adapter, enables 100%-local RAG (no remote API key needed).\n * `lmstudio`, `google`, `bedrock` are deferred to v1.1.\n *\n * Iter 74 (Stage 3 source-move #37): hybrid copy from sdk-core's\n * `internal/memory/adapters/catalog.ts`. Filename renamed to\n * `adapter-catalog.ts` in sdk-memory to disambiguate from the broader\n * \"catalog\" notion at the package barrel level.\n *\n * **This catalog must serve every provider sdk-core ADVERTISES** (theokit#128). When the peer is\n * installed it REPLACES core's catalog in the routing path (`sdk/src/memory.ts`), while the public\n * `Theokit.inspect.embeddingAdapters()` keeps listing core's — so any id core has and this one\n * lacks is a provider the SDK promises and then rejects. That is what happened to `azure-openai`,\n * `cohere`, `jina` and `gemini` for the two months between core's T4.10 and the parity fix.\n * The invariant is enforced by `@theokit/sdk-peer-integration-tests` (`peer-parity.test.ts`).\n *\n * **CLOSES the embedding-adapter cluster in sdk-memory.** The provider adapters + the shared\n * OpenAI-compatible runtime + the inlined HTTP error mapper are canonical here:\n * - iter 45: embedding-adapter (types)\n * - iter 46: embedding-cache (LRU) — REMOVED by theokit#160: the shared runtime owns caching now\n * - iter 73: openai-compatible (shared factory) + adapter-http-error\n * (inlined mapper)\n * - iter 74: openai-embedding + mistral-embedding + deepinfra-embedding\n * + voyage-embedding + openrouter-embedding + ollama-embedding +\n * adapter-catalog (THIS)\n * - theokit#128: azure-openai + cohere + jina + gemini (parity with core's T4.10)\n *\n * @internal\n */\nexport const MEMORY_EMBEDDING_ADAPTERS = {\n openai: openAiMemoryEmbeddingProviderAdapter,\n mistral: mistralMemoryEmbeddingProviderAdapter,\n openrouter: openRouterMemoryEmbeddingProviderAdapter,\n voyage: voyageMemoryEmbeddingProviderAdapter,\n deepinfra: deepinfraMemoryEmbeddingProviderAdapter,\n ollama: ollamaMemoryEmbeddingProviderAdapter,\n // theokit#128 — mirrors sdk-core's T4.10 additions, which the peer had drifted behind.\n \"azure-openai\": azureOpenAiMemoryEmbeddingProviderAdapter,\n cohere: cohereMemoryEmbeddingProviderAdapter,\n jina: jinaMemoryEmbeddingProviderAdapter,\n gemini: geminiMemoryEmbeddingProviderAdapter,\n};\n","/**\n * Public memory types (used by runtime + storage + migration + future index).\n *\n * Leaf module — depends only on `node:path` + the public\n * `@theokit/sdk/path-safety` re-exports (`safePathJoin`,\n * `sanitizeIdentifier`) + `@theokit/sdk`'s `Security` for the\n * canonical `redactSecrets` 12-pattern list (ADR D68).\n *\n * Iter 52 (Stage 3 source-move #9): hybrid copy from sdk-core's\n * `internal/memory/types.ts`. sdk-core retains its copy for v1.x\n * back-compat; sdk-memory ships the canonical copy that future\n * `storage/*`, `migration`, and `tools` moves will target as siblings.\n *\n * **Sub-path-import contract:** sdk-core copy imports\n * `safePathJoin`/`sanitizeIdentifier` from `../security/path-guard.js`\n * (internal path); sdk-memory copy imports them from\n * `@theokit/sdk/path-safety` (public sub-path stable per this\n * iter — sanitizeIdentifier was promoted to the public surface to\n * unblock this move). Same runtime, same grammar.\n *\n * @internal\n */\nimport { resolve as resolvePath } from \"node:path\";\n\nimport { Security } from \"@theokit/sdk\";\nimport { safePathJoin, sanitizeIdentifier } from \"@theokit/sdk/path-safety\";\n\n/**\n * Per-agent memory configuration. `enabled` gates the configuration-aware\n * accessors (`readFacts`, `appendFact`) — with it `false` they resolve without\n * touching disk, while the lower-level markdown functions ignore it.\n *\n * `namespace`, `scope` and `userId` are only consulted for the legacy JSON path\n * (see {@link legacyMemoryJsonPath}); the markdown store keeps one `MEMORY.md`\n * per workspace and does not partition by them. They are treated as\n * user-supplied and sanitised before they reach a path. `storePath` is treated\n * as trusted and resolved as given.\n */\nexport interface MemoryConfig {\n enabled: boolean;\n namespace?: string;\n userId?: string;\n scope?: \"agent\" | \"user\" | \"team\";\n storePath?: string;\n}\n\n/**\n * One remembered statement. `text` is what gets written, embedded and searched;\n * it passes through secret redaction on the way to disk, so what is stored may\n * differ from what was passed in.\n */\nexport interface MemoryFact {\n text: string;\n /**\n * Optional taxonomy bucket (M4-3). Backward-compatible — flat-store facts\n * omit it; the categorized store (`createCategorizedMemory`) always sets it.\n */\n category?: string;\n}\n\n/**\n * Canonical credential-redaction primitive (ADR D68).\n *\n * sdk-core's copy re-exports `redactSecrets` directly from\n * `../security/index.js` (internal path). sdk-core's PUBLIC surface\n * (`@theokit/sdk`) doesn't expose a bare `redactSecrets` symbol —\n * it ships `Security.redact()` instead (T2.1, by design — the\n * namespace also carries `Security.addPattern()`). sdk-memory's\n * canonical `redactSecrets` re-export wraps `Security.redact` 1-to-1\n * so consumers continue to see the same symbol name without sdk-memory\n * having to import sdk-core's internal subpath. Same 12-pattern\n * list, same two-bucket mask shape, same disable-via-env behavior.\n */\nexport function redactSecrets(text: unknown, opts?: { codeFile?: boolean }): string {\n return Security.redact(text, opts);\n}\n\n/**\n * Resolve the legacy JSON memory path used pre-ADR-D8 (kept for migration\n * helpers + tests). Centralized here so `migration.ts` and the legacy-aware\n * `runtime/memory-store.ts` don't duplicate the path logic (jscpd cleanup).\n */\nexport function legacyMemoryJsonPath(cwd: string, config: MemoryConfig): string {\n // ADRs D79-D81: storePath is programmatic (trusted); namespace/scope/userId\n // are user-shaped and pass sanitizeIdentifier. EC-7 (edge-case review):\n // realistic userIds (UUIDs, hash IDs, \"default\") pass; \"user@example.com\"\n // and similar need to be normalized by the caller before passing.\n if (config.storePath !== undefined) {\n return resolvePath(cwd, config.storePath);\n }\n const namespace = sanitizeIdentifier(config.namespace ?? \"default\");\n const scope = sanitizeIdentifier(config.scope ?? \"agent\", { maxLen: 16 });\n const userId = sanitizeIdentifier(config.userId ?? \"default\");\n return safePathJoin(cwd, \".theokit\", \"memory\", namespace, `${scope}-${userId}.json`);\n}\n\n/**\n * A semantically meaningful slice of a markdown memory file, produced by\n * `chunkMarkdown`. Each chunk carries stable line numbers + a content hash\n * used downstream by the embedding cache.\n *\n * Mirrors peer-project's `MemoryChunk` shape\n * (`reference/peer-project/packages/memory-host-sdk/src/host/engine-storage.ts`).\n *\n * @internal\n */\nexport interface MemoryChunk {\n /** 1-indexed starting line in the source file. */\n startLine: number;\n /** 1-indexed ending line (inclusive). */\n endLine: number;\n /** Slice of markdown source text. */\n text: string;\n /** sha256 of `text`; stable across runs for identical inputs. */\n hash: string;\n /** Optional nearest heading text (without the `#` markers). */\n heading?: string;\n}\n\n/**\n * Result of `reader.readFile`. Contains the bounded slice plus truncation\n * + provenance info.\n *\n * Mirrors peer-project's `MemoryReadResult` shape.\n *\n * @internal\n */\nexport interface MemoryReadResult {\n path: string;\n /** Requested starting line (1-indexed, defaults to 1). */\n from: number;\n /** Number of lines actually returned (may be less than `lines` near EOF). */\n linesReturned: number;\n /** Total lines in the file (after the read). */\n totalLines: number;\n /** True when content remains after the returned slice, i.e. `remainingLines > 0`. */\n truncated: boolean;\n /** Lines past the returned slice that remain in the file. */\n remainingLines: number;\n /** Slice text (joined with `\\n`). */\n text: string;\n}\n\n/**\n * Lightweight reference to a markdown file in the memory corpus.\n *\n * Mirrors peer-project's `MemoryFileEntry`.\n *\n * @internal\n */\nexport interface MemoryFileEntry {\n /** Absolute path on disk. */\n path: string;\n /** Path relative to the memory root (e.g. \"MEMORY.md\", \"notes/foo.md\"). */\n relPath: string;\n /** ms-since-epoch mtime. */\n mtime: number;\n /** sha256 of the file content; recomputed on each read. */\n hash: string;\n}\n","/**\n * OpenAI-compatible HTTP error mapper (ADR D67) — sdk-memory inlined copy.\n *\n * Translates OpenAI-shaped API error responses (covers OpenAI, OpenRouter,\n * DeepSeek, Together, Mistral, Voyage, DeepInfra, etc.) into typed\n * `TheokitAgentError` subclasses with full `ErrorMetadata`.\n *\n * Body inspection: looks at `body.error.code` / `body.error.type` to detect\n * `context_too_long`, `content_filtered`, `model_unavailable` semantics.\n * Falls back to status-based mapping when body doesn't expose `.error`\n * (e.g., HTML server error page, DeepInfra's `{message: \"...\"}` shape).\n *\n * Never throws — caller is already in an error path.\n *\n * Iter 73 (Stage 3 source-move #30): inlined adaptation of sdk-core's\n * `internal/errors/mappers/openai-compatible.ts` + `shared.ts`. sdk-core's\n * mapper is internal — not part of the public errors surface — so sdk-memory\n * carries its own minimal copy here. Behavior MUST stay byte-equivalent\n * with sdk-core's so consumers consuming hits via either package surface\n * see identical error shape.\n *\n * The 4 helpers (`parseRetryAfter`, `truncateRaw`, `buildErrorMetadata`,\n * `mapOpenAICompatibleError`) are intentionally co-located in this single\n * file so all 8 embedding adapter moves (catalog + 7 providers) share one\n * import target.\n *\n * @internal\n */\n\nimport {\n AuthenticationError,\n ConfigurationError,\n type ErrorCode,\n type ErrorMetadata,\n NetworkError,\n RateLimitError,\n type TheokitAgentError,\n UnknownAgentError,\n} from \"@theokit/sdk/errors\";\n\nimport { redactSecrets } from \"./memory-types.js\";\n\nconst RAW_MAX_BYTES = 2048;\n\n/**\n * Parse `retry-after` header in numeric-seconds form. HTTP-date form\n * (RFC 7231) returns `undefined` to avoid NaN propagation downstream.\n */\nexport function parseRetryAfter(headers: Headers | undefined): number | undefined {\n if (headers === undefined) return undefined;\n const raw = headers.get(\"retry-after\");\n if (raw === null) return undefined;\n const n = Number(raw);\n if (Number.isFinite(n) && n >= 0) return Math.ceil(n);\n return undefined;\n}\n\n/**\n * Truncate raw response body to ~2KB and redact known credential\n * patterns so it can ride inside `ErrorMetadata.raw` without\n * ballooning logs OR leaking tokens. Returns `undefined` for\n * null/undefined input.\n */\nexport function truncateRaw(body: unknown): unknown {\n if (body === null || body === undefined) return undefined;\n const s = typeof body === \"string\" ? body : JSON.stringify(body);\n const truncated = s.length <= RAW_MAX_BYTES ? s : `${s.slice(0, RAW_MAX_BYTES)}…`;\n return redactSecrets(truncated);\n}\n\n/**\n * Build an `ErrorMetadata` object with all optional fields included\n * conditionally (no `undefined` keys in the output).\n */\nexport function buildErrorMetadata(args: {\n provider: string;\n endpoint: string;\n code: ErrorCode;\n status: number;\n headers: Headers | undefined;\n body: unknown;\n}): ErrorMetadata {\n const retryAfter = parseRetryAfter(args.headers);\n const raw = truncateRaw(args.body);\n return {\n provider: args.provider,\n endpoint: args.endpoint,\n code: args.code,\n statusCode: args.status,\n ...(retryAfter !== undefined ? { retryAfter } : {}),\n ...(raw !== undefined ? { raw } : {}),\n };\n}\n\ninterface MapOpenAiErrorArgs {\n providerId: string;\n status: number;\n body: unknown;\n headers: Headers | undefined;\n endpoint: string;\n}\n\n/**\n * Turn a failed OpenAI-shaped HTTP response into the typed error the SDK throws.\n * Builds the error, it does not throw it.\n *\n * The HTTP status picks the class: 401 and 403 give an `AuthenticationError`,\n * 429 a `RateLimitError`, 400 a `ConfigurationError`, 408 and 5xx a\n * `NetworkError`, and anything else an `UnknownAgentError`.\n *\n * The `code` on the metadata is finer than the class and is read from\n * `body.error.code` (or `.type`) first, so a 400 that names a context-window\n * problem carries `context_too_long` rather than `invalid_request`. A body code\n * naming an exhausted quota, and HTTP 402, both map to `quota_exceeded` — note\n * that a 402 keeps that code while still producing an `UnknownAgentError`,\n * because no status branch claims it.\n *\n * The raw body rides along on the metadata, truncated to about 2KB and passed\n * through secret redaction, so it is safe to log.\n */\nexport function mapOpenAICompatibleError(args: MapOpenAiErrorArgs): TheokitAgentError {\n const { providerId, status, body, headers, endpoint } = args;\n const code = mapOpenAiStatusToCode(status, body);\n const message = formatMessage(providerId, status, code);\n const metadata = buildErrorMetadata({\n provider: providerId,\n endpoint,\n code,\n status,\n headers,\n body,\n });\n\n if (status === 401 || status === 403) {\n return new AuthenticationError(message, { code: `${providerId}_auth_failed`, metadata });\n }\n if (status === 429) {\n return new RateLimitError(message, { code: `${providerId}_rate_limit`, metadata });\n }\n if (status === 400) {\n return new ConfigurationError(message, { code: `${providerId}_${code}`, metadata });\n }\n if (status === 408) {\n return new NetworkError(message, { code: `${providerId}_timeout`, metadata });\n }\n if (status >= 500 && status < 600) {\n return new NetworkError(message, { code: `${providerId}_server_error`, metadata });\n }\n return new UnknownAgentError(message, { code: `${providerId}_unknown`, metadata });\n}\n\nfunction extractOpenAiErrorCode(body: unknown): string | undefined {\n if (body === null || typeof body !== \"object\") return undefined;\n const err = (body as { error?: { code?: unknown; type?: unknown } }).error;\n if (err === undefined || err === null) return undefined;\n if (typeof err.code === \"string\") return err.code;\n if (typeof err.type === \"string\") return err.type;\n return undefined;\n}\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: explicit branch table is clearer than splitting\nfunction mapOpenAiStatusToCode(status: number, body: unknown): ErrorCode {\n const rawCode = extractOpenAiErrorCode(body)?.toLowerCase() ?? \"\";\n\n if (\n rawCode.includes(\"context_length\") ||\n rawCode.includes(\"context_window\") ||\n rawCode.includes(\"too_many_tokens\") ||\n rawCode.includes(\"max_tokens\")\n ) {\n return \"context_too_long\";\n }\n if (\n rawCode.includes(\"content_filter\") ||\n rawCode.includes(\"content_policy\") ||\n rawCode.includes(\"safety\")\n ) {\n return \"content_filtered\";\n }\n if (\n rawCode.includes(\"model_not_found\") ||\n rawCode.includes(\"model_unavailable\") ||\n rawCode.includes(\"invalid_model\")\n ) {\n return \"model_unavailable\";\n }\n // T3.7 — 402 / Insufficient credits / insufficient_quota body code flow\n // to canonical `quota_exceeded` (ADR-spec'd in ErrorCode union).\n if (\n status === 402 ||\n rawCode.includes(\"insufficient_quota\") ||\n rawCode.includes(\"quota_exceeded\")\n ) {\n return \"quota_exceeded\";\n }\n\n if (status === 401 || status === 403) return \"auth_failed\";\n if (status === 429) return \"rate_limit\";\n if (status === 408) return \"timeout\";\n if (status === 400) return \"invalid_request\";\n if (status >= 500 && status < 600) return \"server_error\";\n return \"unknown\";\n}\n\nfunction formatMessage(providerId: string, status: number, code: ErrorCode): string {\n return `${providerId} API error: ${code} (HTTP ${status})`;\n}\n","import { mkdir, readFile } from \"node:fs/promises\";\n\nimport { ConfigurationError } from \"@theokit/sdk/errors\";\nimport { safePathJoin, sanitizeIdentifier } from \"@theokit/sdk/path-safety\";\nimport { replaceFileAtomic, withCwdMutex } from \"@theokit/sdk/persistence\";\n\nimport { type MemoryFact, redactSecrets } from \"./memory-types.js\";\n\n/**\n * A fact stored under a typed category. Unlike the flat {@link MemoryFact}, the\n * `category` is always present in the categorized store's read shape.\n *\n * @public\n */\nexport interface CategorizedFact extends MemoryFact {\n category: string;\n}\n\n/**\n * Options for {@link createCategorizedMemory}.\n *\n * @public\n */\nexport interface CreateCategorizedMemoryOptions {\n /** Directory holding one markdown file per category (`<root>/<category>.md`). */\n root: string;\n /**\n * The closed category taxonomy. This list IS the schema: an `add`/`list`\n * with a category not in it is rejected. Must be non-empty, unique, each\n * sanitizable to a distinct filename.\n */\n categories: readonly string[];\n}\n\n/**\n * A typed, category-partitioned markdown memory store.\n *\n * @public\n */\nexport interface CategorizedMemory {\n /** The declared (frozen) category taxonomy. */\n readonly categories: readonly string[];\n /**\n * Append a fact under `category` (validated against the taxonomy). The text\n * is secret-redacted before persistence. Concurrent adds to the same category\n * are serialized (no lost update). Throws `ConfigurationError(unknown_category)`\n * for an undeclared category (before any I/O).\n */\n add(category: string, text: string): Promise<void>;\n /**\n * Read facts for one category (or every category when omitted). Never throws —\n * a missing/unreadable category file yields no facts.\n */\n list(category?: string): Promise<CategorizedFact[]>;\n}\n\nconst FACTS_HEADING = \"## Facts\";\n\n/**\n * Create a typed categorized memory store over the closed `categories`\n * taxonomy. Composes the shipped `safePathJoin`/`sanitizeIdentifier` path\n * guard, `redactSecrets`, and the atomic `replaceFileAtomic` + `withCwdMutex`\n * persistence primitives — zero new dependencies.\n *\n * @public\n */\nexport function createCategorizedMemory(\n options: CreateCategorizedMemoryOptions,\n): CategorizedMemory {\n const { root, categories } = options;\n validateCategories(categories);\n const allowed = new Set(categories);\n\n function assertKnown(category: string): void {\n if (!allowed.has(category)) {\n throw new ConfigurationError(\n `createCategorizedMemory: unknown category ${JSON.stringify(category)} (declared: ${categories.join(\", \")})`,\n { code: \"unknown_category\" },\n );\n }\n }\n\n function categoryPath(category: string): string {\n return safePathJoin(root, `${sanitizeIdentifier(category)}.md`);\n }\n\n async function add(category: string, text: string): Promise<void> {\n assertKnown(category);\n // Redact secrets, THEN encode newlines/backslashes so a multiline fact (or\n // one containing a `- ` / `## ` line) stays a single bullet and round-trips\n // faithfully — `list` decodes it back. Without this, the `## Facts` bullet\n // parse would split or truncate the fact (silent data loss).\n const encoded = encodeFact(redactSecrets(text));\n const sane = sanitizeIdentifier(category);\n await withCwdMutex(`catmem:${root}:${sane}`, async () => {\n const path = safePathJoin(root, `${sane}.md`);\n const raw = (await readFileOrEmpty(path)) || header(category);\n await mkdir(root, { recursive: true });\n await replaceFileAtomic(path, appendBullet(raw, encoded));\n });\n }\n\n async function list(category?: string): Promise<CategorizedFact[]> {\n if (category !== undefined) {\n assertKnown(category);\n return readCategory(categoryPath(category), category);\n }\n const out: CategorizedFact[] = [];\n for (const c of categories) {\n out.push(...(await readCategory(categoryPath(c), c)));\n }\n return out;\n }\n\n return { categories: [...categories], add, list };\n}\n\nfunction validateCategories(categories: readonly string[]): void {\n if (categories.length === 0) {\n throw new ConfigurationError(\"createCategorizedMemory: categories must be non-empty\", {\n code: \"invalid_categories\",\n });\n }\n if (new Set(categories).size !== categories.length) {\n throw new ConfigurationError(\"createCategorizedMemory: categories must be unique\", {\n code: \"invalid_categories\",\n });\n }\n const sanitized = categories.map((c) => trySanitize(c));\n if (new Set(sanitized).size !== categories.length) {\n throw new ConfigurationError(\n \"createCategorizedMemory: categories must map to distinct filenames after sanitization\",\n { code: \"invalid_categories\" },\n );\n }\n}\n\nfunction trySanitize(category: string): string {\n try {\n return sanitizeIdentifier(category);\n } catch (cause) {\n throw new ConfigurationError(\n `createCategorizedMemory: category ${JSON.stringify(category)} is not a valid identifier`,\n { code: \"invalid_categories\", cause },\n );\n }\n}\n\nfunction header(category: string): string {\n return `---\\ncategory: ${category}\\n---\\n\\n${FACTS_HEADING}\\n`;\n}\n\nasync function readFileOrEmpty(path: string): Promise<string> {\n try {\n return await readFile(path, \"utf8\");\n } catch {\n return \"\";\n }\n}\n\nasync function readCategory(path: string, category: string): Promise<CategorizedFact[]> {\n const raw = await readFileOrEmpty(path);\n return parseFactBullets(raw).map((text) => ({ text: decodeFact(text), category }));\n}\n\n/**\n * Encode a fact for single-bullet storage: escape `\\` first, then `\\r`/`\\n`, so\n * the text occupies exactly one `- ` line (no split, no `## ` heading injection).\n * Pure + reversible by {@link decodeFact}.\n */\nfunction encodeFact(text: string): string {\n return text.replace(/\\\\/g, \"\\\\\\\\\").replace(/\\r/g, \"\\\\r\").replace(/\\n/g, \"\\\\n\");\n}\n\n/**\n * Reverse {@link encodeFact}. A single left-to-right pass over each `\\<char>`\n * escape: `\\n`→newline, `\\r`→CR, and any other escaped char (notably `\\\\`)→the\n * literal char. Non-overlapping matching makes this exact for encoded input.\n */\nfunction decodeFact(text: string): string {\n return text.replace(/\\\\(.)/g, (_match, char: string) =>\n char === \"n\" ? \"\\n\" : char === \"r\" ? \"\\r\" : char,\n );\n}\n\n/** Parse `- text` bullets under the `## Facts` heading. Pure. */\nfunction parseFactBullets(raw: string): string[] {\n const idx = raw.indexOf(FACTS_HEADING);\n if (idx === -1) return [];\n const tail = raw.slice(idx + FACTS_HEADING.length);\n const nextHeading = tail.search(/\\n#{1,2}\\s/);\n const block = nextHeading === -1 ? tail : tail.slice(0, nextHeading);\n return block\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.startsWith(\"- \"))\n .map((line) => line.slice(2).trim());\n}\n\n/** Append a `- text` bullet under the `## Facts` heading. Pure. */\nfunction appendBullet(raw: string, text: string): string {\n const bullet = `- ${text}`;\n const idx = raw.indexOf(FACTS_HEADING);\n if (idx === -1) {\n const sep = raw.endsWith(\"\\n\") ? \"\" : \"\\n\";\n return `${raw}${sep}${FACTS_HEADING}\\n\\n${bullet}\\n`;\n }\n const after = idx + FACTS_HEADING.length;\n const nextHeading = raw.slice(after).search(/\\n#{1,2}\\s/);\n if (nextHeading === -1) {\n const trailing = raw.endsWith(\"\\n\") ? \"\" : \"\\n\";\n return `${raw}${trailing}${bullet}\\n`;\n }\n const insertAt = after + nextHeading;\n return `${raw.slice(0, insertAt)}\\n${bullet}${raw.slice(insertAt)}`;\n}\n","import { createHash } from \"node:crypto\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { replaceFileAtomic } from \"@theokit/sdk/persistence\";\n\nimport { memoryDir } from \"../store/markdown-store.js\";\n\n/**\n * Dream-diary append (ADR D7).\n *\n * Diary lives at `.theokit/memory/dream-diary.md` and grows with one entry\n * per sweep. Each entry is content-hashed so the same input produces the\n * same entry — idempotency contract.\n *\n * Writes go through `replaceFileAtomic` (EC-3 of edge-case review) so a\n * crash mid-write can never leave a half-written diary.\n *\n * Iter 59 (Stage 3 source-move #16): hybrid copy from sdk-core's\n * `internal/memory/dreaming/diary.ts`. sdk-core retains its copy for\n * v1.x dream-diary back-compat; sdk-memory ships the canonical copy\n * that the future `dreaming-run.ts` move will compose with as a\n * sibling (run.ts imports `appendDiaryEntry` after each dreaming\n * sweep). Dependency chain (both resolved):\n * - `@theokit/sdk/persistence` for `replaceFileAtomic`\n * - sibling `./markdown-store.js` for `memoryDir` (moved iter 56)\n *\n * Flat-naming convention (not `dreaming/diary.ts`): sdk-memory's\n * `internal/` directory stays flat. The `dreaming-` prefix preserves\n * the topical grouping (companion to iter 54's `dreaming-phases`).\n *\n * @internal\n */\n\nexport interface DiaryEntry {\n timestampMs: number;\n factsBefore: number;\n factsAfter: number;\n duplicatesRemoved: number;\n clustersCreated: number;\n notesWritten: number;\n}\n\n/** Path to the dream diary, `<memory root>/dream-diary.md`. Pure path computation. */\nexport function diaryPath(cwd: string): string {\n return join(memoryDir(cwd), \"dream-diary.md\");\n}\n\n/**\n * Render one entry as the markdown block {@link appendDiaryEntry} writes: an h2\n * heading carrying the ISO timestamp, then a bullet list of the counts, prefixed\n * by the first eight hex characters of {@link entryHash}.\n */\nexport function renderDiaryEntry(entry: DiaryEntry): string {\n const stamp = new Date(entry.timestampMs).toISOString();\n const hash = entryHash(entry).slice(0, 8);\n return [\n `## ${stamp}`,\n \"\",\n `- entry-hash: ${hash}`,\n `- facts before: ${entry.factsBefore}`,\n `- facts after: ${entry.factsAfter}`,\n `- duplicates removed: ${entry.duplicatesRemoved}`,\n `- clusters created: ${entry.clustersCreated}`,\n `- notes written: ${entry.notesWritten}`,\n \"\",\n ].join(\"\\n\");\n}\n\n/**\n * Append one entry to the dream diary, creating the file with a `# Dream Diary`\n * header when it does not exist yet. The whole file is rewritten through an\n * atomic replace, so a crash mid-write leaves the previous diary intact rather\n * than a truncated one.\n *\n * The parent directory is not created here. Call this against a workspace whose\n * memory directory already exists — a dreaming sweep does, because it has just\n * read `MEMORY.md` from it.\n *\n * Appending is unconditional: passing an entry that was already written adds a\n * second block. The hash identifies repeated content, it does not suppress it.\n */\nexport async function appendDiaryEntry(cwd: string, entry: DiaryEntry): Promise<void> {\n const path = diaryPath(cwd);\n let raw = \"\";\n try {\n raw = await readFile(path, \"utf8\");\n } catch {\n raw = \"# Dream Diary\\n\\n\";\n }\n const next = `${raw.endsWith(\"\\n\") ? raw : `${raw}\\n`}${renderDiaryEntry(entry)}`;\n await replaceFileAtomic(path, next);\n}\n\n/**\n * A sha256 over the five counts of an entry, as a hex string.\n *\n * The timestamp is deliberately NOT part of the hash, so two sweeps that changed\n * nothing produce the same hash at different times — that is the signal the\n * diary is meant to carry. It also means the hash does not identify an entry\n * uniquely.\n */\nexport function entryHash(entry: DiaryEntry): string {\n return createHash(\"sha256\")\n .update(\n [\n entry.factsBefore,\n entry.factsAfter,\n entry.duplicatesRemoved,\n entry.clustersCreated,\n entry.notesWritten,\n ].join(\"|\"),\n )\n .digest(\"hex\");\n}\n","import type { EmbeddingRuntime } from \"../embedding/embedding-adapter.js\";\nimport type { MemoryFact } from \"../memory-types.js\";\n\n/**\n * Dreaming/REM phase logic.\n *\n * Three phases:\n * - **light** — drop near-duplicate facts (cosine similarity > 0.95).\n * - **REM** — cluster thematically related facts (cosine ≥ 0.75).\n * - **deep** — pick a representative bullet per cluster (longest text\n * wins) and emit consolidated markdown notes.\n *\n * Iter 54 (Stage 3 source-move #11): hybrid copy from sdk-core's\n * `internal/memory/dreaming/phases.ts`. sdk-core retains its copy\n * for v1.x dreaming back-compat; sdk-memory ships the canonical copy\n * that future `dreaming/run.ts` move will compose with as a sibling.\n * Dependencies (both moved): `EmbeddingRuntime` (iter 45) +\n * `MemoryFact` (iter 52).\n *\n * Flat-naming convention (not `dreaming/phases.ts`): sdk-memory's\n * `internal/` directory stays flat to keep relative-import paths\n * uniform across iter 44-53. The `dreaming-` prefix preserves the\n * topical grouping without a sub-directory.\n *\n * @internal\n */\n\nexport interface DedupResult {\n kept: MemoryFact[];\n duplicatesRemoved: number;\n}\n\n/**\n * A group of facts the REM phase judged related. `representativeText` is the\n * text of the longest member, used as the cluster's heading in the consolidated\n * note — longest, not most central, so it is a readable label rather than a\n * centroid. `members` includes that fact as well.\n */\nexport interface Cluster {\n representativeText: string;\n members: ReadonlyArray<MemoryFact>;\n}\n\n/**\n * What {@link remPhase} produced. Every input fact appears in exactly one\n * cluster, so a fact related to nothing comes back as a cluster of one — the\n * count is not a count of *interesting* groupings.\n */\nexport interface ClusterResult {\n clusters: Cluster[];\n}\n\nconst DEFAULT_DEDUP_THRESHOLD = 0.95;\nconst DEFAULT_CLUSTER_THRESHOLD = 0.75;\n\n/** Light phase — drop facts whose embedding is too similar to one already kept. */\nexport async function lightPhase(\n facts: ReadonlyArray<MemoryFact>,\n embedding: EmbeddingRuntime,\n threshold: number = DEFAULT_DEDUP_THRESHOLD,\n): Promise<DedupResult> {\n if (facts.length <= 1) return { kept: [...facts], duplicatesRemoved: 0 };\n const vectors = await embedding.embed(facts.map((f) => f.text));\n const keptIdx: number[] = [];\n const keptVecs: number[][] = [];\n for (let i = 0; i < facts.length; i++) {\n const vec = vectors[i] ?? [];\n const isDup = keptVecs.some((kept) => cosineSimilarity(vec, kept) >= threshold);\n if (isDup) continue;\n keptIdx.push(i);\n keptVecs.push(vec);\n }\n const kept = keptIdx.map((i) => facts[i] as MemoryFact);\n return { kept, duplicatesRemoved: facts.length - kept.length };\n}\n\n// T4.6 — cap facts per sweep to prevent O(N²) blowup. 500 facts →\n// 125K comparisons (acceptable). 5000 facts → 12.5M (unacceptable).\n// Over the cap, the clustering considers the FIRST `maxFactsPerSweep`\n// facts and ignores the rest. It is deterministic (same input, same\n// subset) but positional: nothing carries the remainder into a later\n// sweep, so facts past the cap are never clustered while the ones\n// before them stay in place.\nconst DEFAULT_MAX_FACTS_PER_SWEEP = 500;\n\n/** REM phase — single-link agglomerative clustering by cosine similarity. */\nexport async function remPhase(\n facts: ReadonlyArray<MemoryFact>,\n embedding: EmbeddingRuntime,\n threshold: number = DEFAULT_CLUSTER_THRESHOLD,\n maxFactsPerSweep: number = DEFAULT_MAX_FACTS_PER_SWEEP,\n): Promise<ClusterResult> {\n if (facts.length === 0) return { clusters: [] };\n // T4.6 — cap: take the leading window when facts exceed the budget.\n const capped = facts.length > maxFactsPerSweep ? facts.slice(0, maxFactsPerSweep) : facts;\n const vectors = await embedding.embed(capped.map((f) => f.text));\n const clusterOfIdx = unionFindByPairs(vectors, threshold);\n const groups = bucketFactsByClusterRoot(capped, clusterOfIdx);\n return { clusters: [...groups.values()].map(buildClusterFromMembers) };\n}\n\nfunction unionFindByPairs(\n vectors: ReadonlyArray<ReadonlyArray<number>>,\n threshold: number,\n): number[] {\n const clusterOfIdx = vectors.map((_, i) => i);\n for (let i = 0; i < vectors.length; i++) {\n for (let j = i + 1; j < vectors.length; j++) {\n if (cosineSimilarity(vectors[i] ?? [], vectors[j] ?? []) >= threshold) {\n unifyClusters(clusterOfIdx, i, j);\n }\n }\n }\n return clusterOfIdx;\n}\n\nfunction bucketFactsByClusterRoot(\n facts: ReadonlyArray<MemoryFact>,\n clusterOfIdx: number[],\n): Map<number, MemoryFact[]> {\n const groups = new Map<number, MemoryFact[]>();\n for (let i = 0; i < facts.length; i++) {\n const root = findRoot(clusterOfIdx, i);\n const list = groups.get(root) ?? [];\n list.push(facts[i] as MemoryFact);\n groups.set(root, list);\n }\n return groups;\n}\n\nfunction buildClusterFromMembers(members: ReadonlyArray<MemoryFact>): Cluster {\n const sorted = [...members].sort((a, b) => b.text.length - a.text.length);\n return { representativeText: sorted[0]?.text ?? \"\", members };\n}\n\n/** Deep phase — render consolidated markdown for the dreamed note. */\nexport function deepPhase(clusters: ReadonlyArray<Cluster>, timestampMs: number): string {\n if (clusters.length === 0) return \"\";\n const isoStamp = new Date(timestampMs).toISOString();\n const lines: string[] = [`# Dreamed ${isoStamp}`, \"\"];\n for (let i = 0; i < clusters.length; i++) {\n const c = clusters[i];\n if (c === undefined) continue;\n lines.push(`## Cluster ${i + 1}: ${c.representativeText}`);\n lines.push(\"\");\n for (const member of c.members) lines.push(`- ${member.text}`);\n lines.push(\"\");\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction cosineSimilarity(a: ReadonlyArray<number>, b: ReadonlyArray<number>): number {\n if (a.length === 0 || b.length === 0 || a.length !== b.length) return 0;\n let dot = 0;\n let aNorm = 0;\n let bNorm = 0;\n for (let i = 0; i < a.length; i++) {\n const ai = a[i] ?? 0;\n const bi = b[i] ?? 0;\n dot += ai * bi;\n aNorm += ai * ai;\n bNorm += bi * bi;\n }\n const denom = Math.sqrt(aNorm) * Math.sqrt(bNorm);\n return denom === 0 ? 0 : dot / denom;\n}\n\nfunction findRoot(parents: number[], i: number): number {\n let root = i;\n while (parents[root] !== root) {\n const next = parents[root] ?? root;\n if (next === root) break;\n root = next;\n }\n parents[i] = root;\n return root;\n}\n\nfunction unifyClusters(parents: number[], a: number, b: number): void {\n const rootA = findRoot(parents, a);\n const rootB = findRoot(parents, b);\n if (rootA !== rootB) parents[rootB] = rootA;\n}\n","import { mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { replaceFileAtomic, withCwdMutex } from \"@theokit/sdk/persistence\";\nimport type { EmbeddingRuntime } from \"../embedding/embedding-adapter.js\";\nimport { memoryDir, readFactsFromMarkdown } from \"../store/markdown-store.js\";\nimport { appendDiaryEntry } from \"./dreaming-diary.js\";\nimport { deepPhase, lightPhase, remPhase } from \"./dreaming-phases.js\";\n\n/**\n * Dreaming sweep orchestrator (ADR D7 of memory-system-peer-project-parity).\n *\n * Phases:\n * 1. **light** — drop near-duplicate facts via cosine similarity.\n * 2. **REM** — cluster thematically related facts.\n * 3. **deep** — write a `notes/dreamed-<ts>.md` per sweep with consolidated\n * clusters; append a diary entry.\n *\n * All file writes go through `replaceFileAtomic` (EC-3). The sweep holds a\n * mutex for the whole run, so two sweeps over the same workspace serialize.\n * Note the key is `dream:<cwd>`, while `appendFactToMarkdown` locks on the\n * memory directory — different keys, so a concurrent `Remember:` append is NOT\n * excluded by this lock. It cannot corrupt a file (each write is atomic), but a\n * fact appended after the sweep read `MEMORY.md` is simply not in the sweep.\n *\n * Iter 60 (Stage 3 source-move #17): hybrid copy from sdk-core's\n * `internal/memory/dreaming/run.ts`. sdk-core retains its copy for\n * v1.x dreaming back-compat; sdk-memory ships the canonical\n * orchestrator that composes all four sibling moves from iter 45\n * (`EmbeddingRuntime`), iter 54 (`lightPhase`+`remPhase`+`deepPhase`),\n * iter 56 (`memoryDir`+`readFactsFromMarkdown`), and iter 59\n * (`appendDiaryEntry`). Persistence sub-path provides\n * `replaceFileAtomic` + `withCwdMutex`. This closes the dreaming/\n * cluster — 4 files all in sdk-memory now.\n *\n * Flat-naming convention (not `dreaming/run.ts`): sdk-memory's\n * `internal/` directory stays flat. The `dreaming-` prefix preserves\n * the topical grouping (companion to iter 54's `dreaming-phases` and\n * iter 59's `dreaming-diary`).\n *\n * @internal\n */\n\nexport interface DreamingOptions {\n cwd: string;\n embedding: EmbeddingRuntime;\n dedupThreshold?: number;\n clusterThreshold?: number;\n /** Test hook — fixed timestamp for the run. */\n now?: () => number;\n}\n\n/**\n * What one sweep did. `skipped` means `MEMORY.md` held no facts; `error` means\n * the sweep threw and the counts are all zero.\n *\n * `factsAfter` is the count that survived in-memory deduplication, not a new\n * size for `MEMORY.md` — the sweep does not rewrite it, so the duplicates it\n * counted are still on disk and will be counted again next time. `notesWritten`\n * is 0 or 1: one consolidated note per sweep, holding every cluster.\n *\n * `diaryEntryHash` is currently always `undefined`, on every path including\n * success, even though the diary entry itself is written with a hash.\n */\nexport interface DreamingResult {\n status: \"ok\" | \"skipped\" | \"error\";\n factsBefore: number;\n factsAfter: number;\n duplicatesRemoved: number;\n clustersCreated: number;\n notesWritten: number;\n diaryEntryHash: string | undefined;\n}\n\n/**\n * Run one consolidation sweep over `MEMORY.md`: drop near-duplicate facts,\n * cluster what is left, write a consolidated note under `notes/`, and append a\n * diary entry.\n *\n * Every fact is embedded on each sweep, and clustering compares every pair, so\n * cost grows with the square of the corpus. That is why the REM phase looks at\n * the first 500 facts only.\n *\n * Never rejects: a failure is written to stderr and reported as\n * `status: \"error\"`, so a sweep scheduled inside an agent run cannot break it.\n *\n * The sweep is read-only with respect to `MEMORY.md`. It produces a note beside\n * it and leaves the fact list untouched, which means running it twice produces\n * two notes over the same facts.\n */\nexport function runDreamingSweep(options: DreamingOptions): Promise<DreamingResult> {\n return withCwdMutex(`dream:${options.cwd}`, () => runInner(options));\n}\n\nasync function runInner(options: DreamingOptions): Promise<DreamingResult> {\n const now = options.now ?? Date.now;\n const timestampMs = now();\n try {\n const facts = await readFactsFromMarkdown(options.cwd);\n if (facts.length === 0) {\n return emptyResult(\"skipped\");\n }\n const dedup = await lightPhase(facts, options.embedding, options.dedupThreshold);\n const rem = await remPhase(dedup.kept, options.embedding, options.clusterThreshold);\n const notesWritten = await writeConsolidatedNotes(options.cwd, rem.clusters, timestampMs);\n const result: DreamingResult = {\n status: \"ok\",\n factsBefore: facts.length,\n factsAfter: dedup.kept.length,\n duplicatesRemoved: dedup.duplicatesRemoved,\n clustersCreated: rem.clusters.length,\n notesWritten,\n diaryEntryHash: undefined,\n };\n await appendDiaryEntry(options.cwd, {\n timestampMs,\n factsBefore: result.factsBefore,\n factsAfter: result.factsAfter,\n duplicatesRemoved: result.duplicatesRemoved,\n clustersCreated: result.clustersCreated,\n notesWritten: result.notesWritten,\n });\n return result;\n } catch (cause) {\n const message = cause instanceof Error ? cause.message : String(cause);\n process.stderr.write(`[theokit-sdk] dreaming sweep failed: ${message}\\n`);\n return emptyResult(\"error\");\n }\n}\n\nasync function writeConsolidatedNotes(\n cwd: string,\n clusters: ReadonlyArray<{ representativeText: string; members: ReadonlyArray<{ text: string }> }>,\n timestampMs: number,\n): Promise<number> {\n if (clusters.length === 0) return 0;\n const notesDir = join(memoryDir(cwd), \"notes\");\n await mkdir(notesDir, { recursive: true });\n const isoSlug = new Date(timestampMs).toISOString().replace(/[^\\dT]/g, \"-\");\n const file = join(notesDir, `dreamed-${isoSlug}.md`);\n const body = deepPhase(clusters, timestampMs);\n await replaceFileAtomic(file, body);\n return 1;\n}\n\nfunction emptyResult(status: \"skipped\" | \"error\"): DreamingResult {\n return {\n status,\n factsBefore: 0,\n factsAfter: 0,\n duplicatesRemoved: 0,\n clustersCreated: 0,\n notesWritten: 0,\n diaryEntryHash: undefined,\n };\n}\n","/**\n * SQLite schema for the memory index.\n *\n * Tables:\n * - files — one row per indexed markdown file (path, mtime, hash).\n * - chunks — one row per chunk produced by `chunkMarkdown`.\n * - chunks_fts — FTS5 virtual table mirroring chunks.text for BM25 search.\n * - meta — key/value store; persists the active embedding identity\n * (provider id, model, dimension) so we detect when the\n * index was built against a different embedding setup.\n * - embeddings — sqlite-vec virtual table holding the chunk vectors\n * (created on demand by `vec-index.ts`).\n *\n * Iter 49 (Stage 3 source-move #6): pure SQL-string leaf copied from\n * sdk-core's `internal/memory/index-schema.ts`. Hybrid dual-copy per\n * Phase 2 Stage 1 precedent — sdk-core retains its copy for v1.x\n * back-compat; sdk-memory ships the canonical copy that future\n * sqlite/lance index moves (`index-db`, `index-manager`, `vec-index`,\n * `lance-index`) will target as siblings.\n *\n * @internal\n */\n\nexport const SCHEMA_STATEMENTS: ReadonlyArray<string> = [\n `CREATE TABLE IF NOT EXISTS files (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n path TEXT UNIQUE NOT NULL,\n rel_path TEXT NOT NULL,\n mtime INTEGER NOT NULL,\n hash TEXT NOT NULL,\n source TEXT NOT NULL DEFAULT 'memory'\n )`,\n `CREATE TABLE IF NOT EXISTS chunks (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n file_id INTEGER NOT NULL REFERENCES files(id) ON DELETE CASCADE,\n start_line INTEGER NOT NULL,\n end_line INTEGER NOT NULL,\n text TEXT NOT NULL,\n hash TEXT NOT NULL,\n session_key TEXT\n )`,\n `CREATE VIRTUAL TABLE IF NOT EXISTS chunks_fts USING fts5(\n text,\n content='chunks',\n content_rowid='id'\n )`,\n `CREATE TRIGGER IF NOT EXISTS chunks_fts_insert AFTER INSERT ON chunks BEGIN\n INSERT INTO chunks_fts(rowid, text) VALUES (new.id, new.text);\n END`,\n `CREATE TRIGGER IF NOT EXISTS chunks_fts_delete AFTER DELETE ON chunks BEGIN\n INSERT INTO chunks_fts(chunks_fts, rowid, text) VALUES ('delete', old.id, old.text);\n END`,\n `CREATE TABLE IF NOT EXISTS meta (\n key TEXT PRIMARY KEY,\n value TEXT\n )`,\n `CREATE INDEX IF NOT EXISTS idx_chunks_file_id ON chunks(file_id)`,\n];\n\n/**\n * Non-WAL pragmas. WAL is applied separately via\n * `applyWalWithFallback` (T4.2, ADR D63) so NFS/SMB users get a graceful\n * DELETE fallback instead of crashing.\n */\nexport const PRAGMA_STATEMENTS: ReadonlyArray<string> = [\n \"PRAGMA synchronous=NORMAL\",\n \"PRAGMA foreign_keys=ON\",\n];\n","import { join } from \"node:path\";\n\nimport { openSqliteResilient } from \"@theokit/sdk/persistence\";\n\nimport { PRAGMA_STATEMENTS, SCHEMA_STATEMENTS } from \"./index-schema.js\";\n\n/**\n * Thin wrapper around the SQLite driver. Prefers `node:sqlite` when available\n * (Node 22.5+) and falls back to `better-sqlite3`. Both expose nearly the\n * same `prepare/exec/close` surface; we normalize via a minimal adapter.\n *\n * Corrupt-DB recovery (EC-7): when opening fails with a \"file is encrypted\n * or is not a database\" or \"malformed\" error, the file is renamed aside to\n * `<path>.corrupt-<ts>` and the schema is rebuilt from scratch.\n *\n * Iter 65 (Stage 3 source-move #22): hybrid copy from sdk-core's\n * `internal/memory/index-db.ts`. sdk-core retains its copy for v1.x\n * sqlite-vec back-compat; sdk-memory ships the canonical copy that\n * future `sqlite-vec-loader`, `vec-index`, `index-manager` moves\n * will compose with. Dependency chain (all resolved):\n * - `@theokit/sdk/errors` for `ConfigurationError` (public)\n * - `@theokit/sdk/persistence` for `applyWalWithFallback`\n * (ADR D63 — NFS/SMB/FUSE-safe WAL adoption)\n * - sibling `./index-schema.js` for SCHEMA + PRAGMA statements (moved iter 49)\n *\n * @internal\n */\n\nexport interface MemoryDb {\n exec(sql: string): void;\n prepare(sql: string): {\n run(...args: unknown[]): { changes: number; lastInsertRowid: number | bigint };\n get(...args: unknown[]): Record<string, unknown> | undefined;\n all(...args: unknown[]): Array<Record<string, unknown>>;\n };\n /** SQLite `pragma()` access (used by `applyWalWithFallback`). */\n pragma(statement: string, options?: { simple?: boolean }): unknown;\n close(): void;\n /** Load a SQLite loadable extension at the given path (used by sqlite-vec). */\n loadExtension(path: string): void;\n}\n\n/** Options for {@link openMemoryDb}. */\nexport interface OpenDbOptions {\n filePath: string;\n /**\n * When true and opening fails with a corruption error, rename the file aside\n * and create a fresh DB. Default true.\n */\n recoverCorrupt?: boolean;\n}\n\n/**\n * Open (or create) the SQLite memory index at `filePath`, applying the pragmas\n * and creating the schema before returning. Parent directories are created as\n * needed, so pointing this at a fresh workspace works.\n *\n * The driver is chosen at runtime: `node:sqlite` where the running Node exposes\n * it, and `better-sqlite3` otherwise. `better-sqlite3` is an optional peer\n * dependency of this package — on a Node build without `node:sqlite` and\n * without it installed, opening fails.\n *\n * A file that is corrupt, truncated or encrypted is renamed aside to\n * `<path>.corrupt-<timestamp>` and rebuilt empty, unless `recoverCorrupt` is\n * `false`. Recovery loses every indexed chunk; the markdown corpus is the source\n * of truth and the next `sync()` rebuilds from it.\n *\n * Loading the sqlite-vec extension is a separate step — this returns an index\n * that can do text search only.\n */\nexport async function openMemoryDb(opts: OpenDbOptions): Promise<MemoryDb> {\n return openSqliteResilient<MemoryDb>({\n filePath: opts.filePath,\n label: \"memory-index\",\n recoverCorrupt: opts.recoverCorrupt,\n onOpen: (db) => {\n // PRAGMA + SCHEMA run after WAL is applied (handled by openSqliteResilient).\n for (const pragma of PRAGMA_STATEMENTS) db.exec(pragma);\n for (const stmt of SCHEMA_STATEMENTS) db.exec(stmt);\n },\n });\n}\n\n/**\n * Where the SQLite index lives when the caller does not name a path:\n * `<cwd>/.theokit/memory/.index/memory.sqlite`. Pure path computation. The file\n * sits under the memory root but outside the markdown corpus, so it is never\n * indexed as content.\n */\nexport function defaultIndexPath(cwd: string): string {\n return join(cwd, \".theokit\", \"memory\", \".index\", \"memory.sqlite\");\n}\n","import { createHash } from \"node:crypto\";\n\n/**\n * **Iter 53 rollup-plugin-dts workaround** (mirrors iter 48\n * MemorySearchHit pattern). The canonical sdk-core copy imports\n * `MemoryChunk` from `../types.js`. In sdk-memory the same type lives\n * in sibling `./memory-types.js` (moved iter 52) but rollup-dts\n * treeshakes it out of the dist .d.ts because no PUBLIC type\n * references it transitively yet — the public `chunkMarkdown(text):\n * MemoryChunk[]` signature would be the first transitive reachable\n * consumer, BUT rollup-dts processes files in an order that asks for\n * the import resolution BEFORE chunk-markdown.ts itself becomes the\n * reachable consumer. Result: \"MemoryChunk is not exported by\n * src/internal/memory-types.ts\" build error.\n *\n * Fix: declare a byte-identical mirror of MemoryChunk inline. When a\n * future move turns MemoryChunk into a publicly-reachable type\n * through a different path (e.g. `index-db.ts` or `IndexManager`\n * methods that return arrays of it), this mirror MUST be deleted +\n * the canonical import restored to maintain single source of truth.\n *\n * @internal\n */\ninterface MemoryChunk {\n /** 1-indexed starting line in the source file. */\n startLine: number;\n /** 1-indexed ending line (inclusive). */\n endLine: number;\n /** Slice of markdown source text. */\n text: string;\n /** sha256 of `text`; stable across runs for identical inputs. */\n hash: string;\n /** Optional nearest heading text (without the `#` markers). */\n heading?: string;\n}\n\n/**\n * Split a markdown document into semantically meaningful chunks (ADR D1 of\n * memory-system-peer-project-parity).\n *\n * Algorithm:\n * 1. Walk lines tracking the current heading (latest `^#+ ` line).\n * 2. Split chunks at the next heading boundary AND on blank-line paragraph\n * boundaries.\n * 3. If a single paragraph exceeds `maxChars`, split it at the nearest\n * whitespace ≤ maxChars (word-aligned per edge-case review EC-6) —\n * never mid-word.\n *\n * Mirrors peer-project's `chunkMarkdown` from\n * `packages/memory-host-sdk/src/host/chunk-markdown.ts`.\n *\n * Iter 53 (Stage 3 source-move #10): hybrid copy from sdk-core's\n * `internal/memory/storage/chunk-markdown.ts`. sdk-core retains its\n * copy for v1.x back-compat; sdk-memory ships the canonical copy that\n * future `storage/markdown-store`, `migration`, `index-db`, and\n * `index-manager` moves will target as siblings. The `MemoryChunk`\n * type comes from sibling `./memory-types.js` (moved iter 52).\n *\n * @internal\n */\n\nexport interface ChunkMarkdownOptions {\n /** Maximum chars per chunk. Default 800. */\n maxChars?: number;\n /** Minimum chars per chunk (avoids splintering tiny lines). Default 80. */\n minChars?: number;\n}\n\nconst HEADING_RE = /^(#{1,6})\\s+(.+?)\\s*$/;\n\ninterface ChunkAccumulator {\n chunks: MemoryChunk[];\n lines: string[];\n start: number;\n heading: string | undefined;\n}\n\n/**\n * Split markdown into the chunks that get embedded and searched.\n *\n * Boundaries are structural rather than fixed-width: a chunk ends at the next\n * heading, or at a blank line. Each chunk carries the nearest preceding heading,\n * so a hit can be cited with the section it came from. A run of text longer than\n * `maxChars` is then cut at the last whitespace within 200 characters of the\n * limit, falling back to a hard cut when a single token is longer than that.\n *\n * Returns `[]` for empty input. `minChars` on the options is currently not read\n * — small paragraphs are emitted as their own chunks regardless.\n *\n * Line numbers are 1-indexed and inclusive at both ends. They are exact for\n * normal chunks; for a paragraph that had to be split by length, the numbers are\n * derived from newline counts within the slice and mark the span the slice came\n * from rather than a precise per-slice range.\n */\nexport function chunkMarkdown(text: string, options: ChunkMarkdownOptions = {}): MemoryChunk[] {\n const maxChars = options.maxChars ?? 800;\n if (text.length === 0) return [];\n const lines = text.split(\"\\n\");\n const acc: ChunkAccumulator = { chunks: [], lines: [], start: 1, heading: undefined };\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i] ?? \"\";\n const lineNumber = i + 1;\n processLine(acc, line, lineNumber, maxChars);\n }\n flushAccumulator(acc, lines.length, maxChars);\n return acc.chunks;\n}\n\nfunction processLine(\n acc: ChunkAccumulator,\n line: string,\n lineNumber: number,\n maxChars: number,\n): void {\n const headingMatch = HEADING_RE.exec(line);\n const isBlank = line.trim().length === 0;\n if (headingMatch !== null && acc.lines.length > 0) {\n flushAccumulator(acc, lineNumber - 1, maxChars);\n }\n if (headingMatch !== null) acc.heading = headingMatch[2];\n acc.lines.push(line);\n if (isBlank && acc.lines.length > 1) {\n const joined = acc.lines.join(\"\\n\");\n if (joined.trim().length > 0) flushAccumulator(acc, lineNumber, maxChars);\n }\n}\n\nfunction flushAccumulator(acc: ChunkAccumulator, endLineExclusive: number, maxChars: number): void {\n if (acc.lines.length === 0) return;\n const chunkText = acc.lines.join(\"\\n\");\n if (chunkText.trim().length === 0) {\n acc.lines = [];\n acc.start = endLineExclusive + 1;\n return;\n }\n if (chunkText.length > maxChars) {\n pushOversizedSlices(acc.chunks, chunkText, acc.start, acc.heading, maxChars);\n } else {\n acc.chunks.push(buildChunk(chunkText, acc.start, endLineExclusive, acc.heading));\n }\n acc.lines = [];\n acc.start = endLineExclusive + 1;\n}\n\nfunction buildChunk(\n text: string,\n startLine: number,\n endLine: number,\n heading: string | undefined,\n): MemoryChunk {\n return {\n startLine,\n endLine,\n text,\n hash: createHash(\"sha256\").update(text).digest(\"hex\"),\n ...(heading !== undefined ? { heading } : {}),\n };\n}\n\nfunction pushOversizedSlices(\n chunks: MemoryChunk[],\n text: string,\n startLine: number,\n heading: string | undefined,\n maxChars: number,\n): void {\n let remaining = text;\n let lineCursor = startLine;\n while (remaining.length > maxChars) {\n const splitAt = findWordBoundarySplit(remaining, maxChars);\n const slice = remaining.slice(0, splitAt);\n const sliceLines = slice.split(\"\\n\").length;\n chunks.push(buildChunk(slice, lineCursor, lineCursor + sliceLines - 1, heading));\n remaining = remaining.slice(splitAt).replace(/^\\s+/, \"\");\n lineCursor += sliceLines - 1;\n }\n if (remaining.length > 0) {\n const sliceLines = remaining.split(\"\\n\").length;\n chunks.push(buildChunk(remaining, lineCursor, lineCursor + sliceLines - 1, heading));\n }\n}\n\n/**\n * Find a split point ≤ maxChars that lands on a whitespace boundary so we\n * don't slice a word in half. Falls back to maxChars if no whitespace is\n * within range (very rare — a single token > maxChars).\n */\nfunction findWordBoundarySplit(text: string, maxChars: number): number {\n if (text.length <= maxChars) return text.length;\n // Walk backward from maxChars looking for whitespace.\n for (let i = maxChars; i > Math.max(0, maxChars - 200); i--) {\n if (/\\s/.test(text[i] ?? \"x\")) return i;\n }\n // No whitespace within 200 chars of the cap — accept a hard split.\n return maxChars;\n}\n","import { mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { replaceFileAtomic } from \"@theokit/sdk/persistence\";\nimport { redactSecrets } from \"../memory-types.js\";\nimport { memoryDir } from \"./markdown-store.js\";\n\n/**\n * Per-run session summary writer (ADR D20).\n *\n * After every finished run, write a markdown summary to\n * `.theokit/memory/sessions/<runId>.md`. IndexManager picks these up with\n * `source=\"sessions\"` so `memory_search({ corpus: \"sessions\" })` can recall\n * past conversations.\n *\n * EC-9: only `status === \"finished\"` runs trigger a write. Cancelled/errored\n * runs would otherwise pollute the recall corpus with partial transcripts.\n *\n * Iter 61 (Stage 3 source-move #18): hybrid copy from sdk-core's\n * `internal/memory/storage/session-summary-writer.ts`. sdk-core\n * retains its copy for v1.x sessions back-compat; sdk-memory ships\n * the canonical copy that the future `session-loader.ts` move will\n * compose with as a sibling (loader reads back the markdown files\n * this writer emits). Dependency chain (all resolved):\n * - `@theokit/sdk/persistence` for `replaceFileAtomic`\n * - sibling `./markdown-store.js` for `memoryDir` (moved iter 56)\n * - sibling `./memory-types.js` for `redactSecrets` (moved iter 52)\n *\n * @internal\n */\n\nexport interface SessionSummaryInput {\n cwd: string;\n runId: string;\n agentId: string;\n userText: string;\n assistantText: string;\n status: \"finished\" | \"running\" | \"error\" | \"cancelled\";\n at: number;\n}\n\nconst MAX_TURN_CHARS = 2000;\n\n/**\n * Path to `<memory root>/sessions`, where one markdown summary per finished run\n * is written. `IndexManager.sync()` indexes these with `source: \"sessions\"`.\n * Pure path computation.\n */\nexport function sessionsDir(cwd: string): string {\n return join(memoryDir(cwd), \"sessions\");\n}\n\n/**\n * Path of the summary file for a run.\n *\n * The run id is sanitised before it reaches the path: every character outside\n * `[a-zA-Z0-9_-]` becomes an underscore and the result is cut to 128\n * characters. That keeps a hostile id inside the sessions directory, and it also\n * means two different ids can collide onto one file — pass ids that are already\n * within the safe alphabet if that matters.\n */\nexport function sessionSummaryPath(cwd: string, runId: string): string {\n return join(sessionsDir(cwd), `${sanitizeRunId(runId)}.md`);\n}\n\nfunction sanitizeRunId(runId: string): string {\n // Strip path separators and obvious traversal patterns so a malicious\n // run-id cannot escape the sessions directory. Keep `[a-zA-Z0-9_-]`.\n return runId.replace(/[^a-zA-Z0-9_-]/g, \"_\").slice(0, 128);\n}\n\nfunction truncate(text: string): string {\n if (text.length <= MAX_TURN_CHARS) return text;\n return `${text.slice(0, MAX_TURN_CHARS)}…`;\n}\n\n/**\n * Write a session summary file. EC-9: a non-finished status returns early\n * without touching disk. Secrets in both user and assistant text are\n * redacted via the shared `redactSecrets` pattern.\n *\n * @internal\n */\nexport async function writeSessionSummary(input: SessionSummaryInput): Promise<void> {\n if (input.status !== \"finished\") return;\n const path = sessionSummaryPath(input.cwd, input.runId);\n await mkdir(sessionsDir(input.cwd), { recursive: true });\n\n const safeUser = redactSecrets(truncate(input.userText));\n const safeAssistant = redactSecrets(truncate(input.assistantText));\n const iso = new Date(input.at).toISOString();\n\n const body = [\n \"---\",\n `runId: ${input.runId}`,\n `agentId: ${input.agentId}`,\n `at: ${iso}`,\n `status: ${input.status}`,\n \"---\",\n \"\",\n \"## User\",\n \"\",\n safeUser,\n \"\",\n \"## Assistant\",\n \"\",\n safeAssistant,\n \"\",\n ].join(\"\\n\");\n\n await replaceFileAtomic(path, body);\n}\n","import { readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { memoryDir } from \"./markdown-store.js\";\nimport { sessionsDir } from \"./session-summary-writer.js\";\n\n/**\n * Session summary discovery (ADR D20).\n *\n * Mirrors `wiki-loader.ts:discoverWikiFiles`: scans\n * `.theokit/memory/sessions/*.md` and returns `MemoryFileEntry`-shaped\n * records. IndexManager tags each chunk with `source=\"sessions\"` so\n * `memory_search({ corpus: \"sessions\" })` filters them in.\n *\n * Iter 62 (Stage 3 source-move #19): hybrid copy from sdk-core's\n * `internal/memory/storage/session-loader.ts`. sdk-core retains its\n * copy for v1.x sessions back-compat; sdk-memory ships the canonical\n * copy. **Closes the sessions/ cluster in sdk-memory** — session\n * summary writer (iter 61) + session-loader (this iter) are both\n * canonical. Dependencies (sibling, both moved):\n * - `memoryDir` from `./markdown-store.js` (moved iter 56)\n * - `sessionsDir` from `./session-summary-writer.js` (moved iter 61)\n *\n * @internal\n */\n\nexport interface SessionFile {\n absolutePath: string;\n relPath: string;\n}\n\n/**\n * List the session summaries under `sessions/`, with each path expressed\n * relative to the memory root so the index can store a stable `sessions/<id>.md`.\n * Returns `[]` when the directory does not exist. Does not recurse.\n */\nexport async function discoverSessionFiles(cwd: string): Promise<SessionFile[]> {\n let entries: string[];\n try {\n entries = await readdir(sessionsDir(cwd));\n } catch {\n return [];\n }\n const root = memoryDir(cwd);\n return entries\n .filter((entry) => entry.endsWith(\".md\"))\n .map((entry) => {\n const absolutePath = join(sessionsDir(cwd), entry);\n return {\n absolutePath,\n relPath: relativeToRoot(root, absolutePath),\n };\n });\n}\n\nfunction relativeToRoot(root: string, absolutePath: string): string {\n if (absolutePath.startsWith(`${root}/`)) return absolutePath.slice(root.length + 1);\n return absolutePath;\n}\n","import { readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { memoryDir } from \"./markdown-store.js\";\n\n/**\n * Wiki supplement discovery (ADR Phase 10 of memory-system-peer-project-parity).\n *\n * Wiki files live under `.theokit/memory/wiki/*.md`. They are READ-ONLY —\n * the SDK never writes here. Each indexed chunk carries `source=\"wiki\"` so\n * `memory_search { corpus: \"wiki\" }` and `corpus: \"all\"` can scope hits.\n *\n * Iter 57 (Stage 3 source-move #14): hybrid copy from sdk-core's\n * `internal/memory/storage/wiki-loader.ts`. sdk-core retains its copy\n * for v1.x back-compat; sdk-memory ships the canonical copy that\n * future `index-db` + `index-manager` moves will compose with\n * (memory_search corpus filter scopes wiki hits via this loader's\n * relPath convention). `memoryDir` comes from sibling\n * `./markdown-store.js` (moved iter 56).\n *\n * @internal\n */\n\nexport interface WikiFile {\n absolutePath: string;\n relPath: string;\n}\n\n/**\n * Path to `<memory root>/wiki`, the read-only supplement directory. Nothing in\n * this package writes there — it is for material a human or another tool puts\n * in place. Pure path computation.\n */\nexport function wikiDir(cwd: string): string {\n return join(memoryDir(cwd), \"wiki\");\n}\n\n/**\n * List the `.md` files directly under `wiki/`, with each path expressed relative\n * to the memory root so the index can store a stable `wiki/<name>.md`. Returns\n * `[]` when the directory does not exist. Does not recurse, so wiki material\n * organised into sub-directories is not picked up.\n */\nexport async function discoverWikiFiles(cwd: string): Promise<WikiFile[]> {\n let entries: string[];\n try {\n entries = await readdir(wikiDir(cwd));\n } catch {\n return [];\n }\n const root = memoryDir(cwd);\n return entries\n .filter((entry) => entry.endsWith(\".md\"))\n .map((entry) => ({\n absolutePath: join(wikiDir(cwd), entry),\n relPath: join(\"wiki\", entry),\n }))\n .map((file) => ({\n absolutePath: file.absolutePath,\n relPath: relativeToRoot(root, file.absolutePath),\n }));\n}\n\nfunction relativeToRoot(root: string, absolutePath: string): string {\n // memory root is e.g. /tmp/x/.theokit/memory; wiki file is /tmp/x/.theokit/memory/wiki/foo.md\n // Strip the root + \"/\" prefix to get \"wiki/foo.md\".\n if (absolutePath.startsWith(`${root}/`)) return absolutePath.slice(root.length + 1);\n return absolutePath;\n}\n","import { existsSync, mkdirSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { join } from \"node:path\";\n\nimport { ConfigurationError } from \"@theokit/sdk/errors\";\n\nimport type { EmbeddingRuntime } from \"../embedding/embedding-adapter.js\";\n\n/**\n * LanceDB-backed memory index (ADR D43). Implements the same logical\n * interface as `IndexManager` but stores embeddings in Lance's columnar\n * vector-aware file format — scalable to 100k+ facts.\n *\n * Opt-in via `Memory.create({ index: { backend: \"lance\" } })`. SQLite\n * remains the default; this code path only activates when explicitly\n * requested AND `@lancedb/lancedb` is installed.\n *\n * EC-1 MUST FIX: filters use Lance's SQL string predicate API — bind\n * parameters are not supported; single-quote escape (`'` → `''`) is the\n * only injection-safe option. Backed by integration test (lancedb-backend-ship-v1-1).\n *\n * EC-8: embedding dimension is validated when opening an existing table.\n *\n * Iter 68 (Stage 3 source-move #25): hybrid copy from sdk-core's\n * `internal/memory/lance-index.ts`. sdk-core retains its copy for v1.x\n * Lance back-compat; sdk-memory ships the canonical copy that future\n * `lance-memory-adapter.ts` move will compose with as a sibling.\n * Dependency chain (all resolved):\n * - `@theokit/sdk/errors` for `ConfigurationError` (public)\n * - sibling `./embedding-adapter.js` for `EmbeddingRuntime` (moved iter 45)\n * - dynamic-required `@lancedb/lancedb` (optional peer — typed\n * ConfigurationError on missing module per EC of the\n * lancedb-backend-ship plan)\n *\n * @internal\n */\n\ninterface LanceModule {\n connect: (uri: string) => Promise<LanceConnection>;\n}\n\ninterface LanceConnection {\n openTable: (name: string) => Promise<LanceTable>;\n createTable: (name: string, data: ReadonlyArray<LanceFactRecord>) => Promise<LanceTable>;\n tableNames: () => Promise<string[]>;\n}\n\ninterface LanceTable {\n add: (rows: ReadonlyArray<LanceFactRecord>) => Promise<void>;\n search: (vector: ReadonlyArray<number>) => LanceQuery;\n delete: (predicate: string) => Promise<void>;\n countRows: () => Promise<number>;\n // EC-8: schema introspection for dimension check.\n schema: () => Promise<{\n fields: ReadonlyArray<{\n name: string;\n // Lance 0.30 returns Apache Arrow Field. FixedSizeList type has\n // `listSize`, not `fixedSize`. typeId=16 = FixedSizeList in Arrow.\n type: { listSize?: number; fixedSize?: number };\n }>;\n }>;\n}\n\ninterface LanceQuery {\n where: (filter: string | Record<string, unknown>) => LanceQuery;\n limit: (n: number) => LanceQuery;\n toArray: () => Promise<ReadonlyArray<LanceFactRecord & { _distance?: number }>>;\n}\n\n/**\n * One row of the Lance `facts` table, as it is stored. Field names are the\n * on-disk column names, which is why `user_id` is snake_case here while the\n * search result reports `userId`.\n *\n * `embedding` must be exactly as wide as the table was created with; the width\n * is fixed by the embedding runtime on the first open and checked on every\n * later one.\n */\nexport interface LanceFactRecord {\n id: string;\n text: string;\n source: \"memory\" | \"sessions\" | \"wiki\";\n embedding: ReadonlyArray<number>;\n namespace: string;\n scope: string;\n user_id: string;\n timestamp: number;\n}\n\n/**\n * Options for `LanceIndex.open`. The embedding runtime is required, not\n * optional: Lance here is vector-only, so there is no text-search fallback to\n * open without one.\n */\nexport interface OpenLanceOptions {\n cwd: string;\n embedding: EmbeddingRuntime;\n /** Override storage location. Default: `<cwd>/.theokit/memory/lance/`. */\n storagePath?: string;\n}\n\n/**\n * Filters for `LanceIndex.search`. `namespace` is required and `scope` is\n * optional; both are applied as a SQL predicate inside Lance. `sources` is\n * applied in this process, after the rows come back, so it narrows the result\n * without narrowing what `limit` counted.\n */\nexport interface LanceSearchOptions {\n namespace: string;\n scope?: string;\n limit?: number;\n sources?: ReadonlyArray<\"memory\" | \"sessions\" | \"wiki\">;\n}\n\n/**\n * One Lance search result. `score` is a similarity in `(0, 1]` derived from\n * Lance's distance as `1 / (1 + distance)`, so higher is better — the opposite\n * direction from the raw distance Lance returns.\n */\nexport interface LanceSearchHit {\n id: string;\n text: string;\n source: \"memory\" | \"sessions\" | \"wiki\";\n namespace: string;\n scope: string;\n userId: string;\n score: number;\n}\n\n/**\n * Lazily load `@lancedb/lancedb`. Throws typed error when absent.\n *\n * @internal\n */\nfunction requireLance(): LanceModule {\n try {\n const r = createRequire(import.meta.url);\n return r(\"@lancedb/lancedb\") as LanceModule;\n } catch (cause) {\n throw new ConfigurationError(\n \"Lance backend selected but `@lancedb/lancedb` is not installed. \" +\n 'Install with: `pnpm add @lancedb/lancedb`. SQLite remains available as the default (omit `backend: \"lance\"`).',\n { code: \"lance_backend_unavailable\", cause },\n );\n }\n}\n\n/**\n * Lance-backed memory index. Public API mirrors the SQLite one logically:\n * `addFacts`, `search`, `countFacts`, `removeFacts`, `close`.\n *\n * @internal\n */\nexport class LanceIndex {\n private constructor(\n private readonly table: LanceTable,\n private readonly embedding: EmbeddingRuntime,\n private readonly embeddingDim: number,\n ) {}\n\n static async open(opts: OpenLanceOptions): Promise<LanceIndex> {\n const lance = requireLance();\n const storagePath = opts.storagePath ?? join(opts.cwd, \".theokit\", \"memory\", \"lance\");\n mkdirSync(storagePath, { recursive: true });\n const conn = await lance.connect(storagePath);\n const dim = opts.embedding.dimension;\n const tableName = \"facts\";\n const existing = await conn.tableNames();\n let table: LanceTable;\n if (existing.includes(tableName)) {\n table = await conn.openTable(tableName);\n // EC-8: validate embedding dimension matches what's in storage.\n // Lance 0.30 uses Apache Arrow FixedSizeList type — the size lives\n // in `type.listSize` (older API used `fixedSize`; we read both for\n // forward/backward safety).\n const schema = await table.schema();\n const embField = schema.fields.find((f) => f.name === \"embedding\");\n const existingDim = embField?.type?.listSize ?? embField?.type?.fixedSize;\n if (typeof existingDim === \"number\" && existingDim !== dim) {\n throw new ConfigurationError(\n `Embedding dimension mismatch in Lance index: storage has ${existingDim}-dim vectors, current provider yields ${dim}-dim. Run \\`theokit-migrate-memory\\` after switching providers, or use a different storagePath.`,\n { code: \"embedding_dimension_mismatch\" },\n );\n }\n } else {\n // Create with one bootstrap record. Lance requires an initial row to\n // infer schema; we delete the bootstrap immediately.\n const bootstrap: LanceFactRecord = {\n id: \"__bootstrap__\",\n text: \"\",\n source: \"memory\",\n embedding: new Array(dim).fill(0),\n namespace: \"__bootstrap__\",\n scope: \"__bootstrap__\",\n user_id: \"__bootstrap__\",\n timestamp: 0,\n };\n table = await conn.createTable(tableName, [bootstrap]);\n await table.delete(\"namespace = '__bootstrap__'\");\n }\n return new LanceIndex(table, opts.embedding, dim);\n }\n\n async addFacts(facts: ReadonlyArray<Omit<LanceFactRecord, \"embedding\">>): Promise<void> {\n if (facts.length === 0) return;\n const texts = facts.map((f) => f.text);\n const embeddings = await this.embedding.embed(texts);\n const rows: LanceFactRecord[] = facts.map((f, i) => ({\n ...f,\n embedding: embeddings[i] ?? new Array(this.embeddingDim).fill(0),\n }));\n await this.table.add(rows);\n }\n\n /**\n * Search facts by semantic similarity. EC-1: filters use Lance's\n * SQL string predicate with `'` → `''` escape — bind parameters are\n * not supported by Lance 0.30.\n */\n async search(query: string, opts: LanceSearchOptions): Promise<LanceSearchHit[]> {\n const [embedding] = await this.embedding.embed([query]);\n if (embedding === undefined) return [];\n // EC-1 (lancedb-backend-ship-v1-1 integration test caught this 2026-05-31):\n // Lance 0.30.0's `.where()` accepts SQL STRING only, NOT object filter —\n // contrary to D43's original assumption. We build the SQL string with\n // single-quote escaping (`'` → `''`) to neutralize injection. This is\n // the standard SQL string-literal escape; bind parameters are not\n // supported in Lance's predicate API. Backed by integration test\n // `injection attempt in namespace does not break filter` (test 7).\n const predicates: string[] = [`namespace = '${escapeSqlValue(opts.namespace)}'`];\n if (opts.scope !== undefined) {\n predicates.push(`scope = '${escapeSqlValue(opts.scope)}'`);\n }\n let q = this.table.search(embedding).where(predicates.join(\" AND \"));\n if (opts.limit !== undefined) q = q.limit(opts.limit);\n const results = await q.toArray();\n return results\n .filter((r) => opts.sources === undefined || opts.sources.includes(r.source))\n .map((r) => ({\n id: r.id,\n text: r.text,\n source: r.source,\n namespace: r.namespace,\n scope: r.scope,\n userId: r.user_id,\n // Lower _distance = better match; normalize to 0..1 (1=best).\n score: 1 / (1 + (r._distance ?? 1)),\n }));\n }\n\n async countFacts(namespace: string): Promise<number> {\n // Total count, regardless of namespace, used by migration validation.\n // For per-namespace count, callers can do a where() + countRows() if\n // Lance supports it; v1.2 ships with global count only.\n void namespace;\n return this.table.countRows();\n }\n\n async removeFacts(ids: ReadonlyArray<string>): Promise<void> {\n if (ids.length === 0) return;\n // Build a parameterized-style delete predicate. Lance's delete still\n // takes a string predicate, so we explicitly quote-escape each id —\n // ids in our system are content-hashed (alphanumeric), so the risk\n // is low, but we belt-and-suspenders.\n const escaped = ids.map((id) => `'${id.replace(/'/g, \"''\")}'`).join(\", \");\n await this.table.delete(`id IN (${escaped})`);\n }\n\n async close(): Promise<void> {\n // Lance auto-closes on GC; no explicit shutdown needed.\n }\n}\n\n/**\n * Escape a value for safe SQL string interpolation in Lance predicates.\n * Lance does not support bind parameters — string-quote escape is the\n * only injection-safe option. Standard SQL: replace single quotes with\n * doubled single quotes.\n *\n * @internal\n */\nfunction escapeSqlValue(value: string): string {\n // T5.2 — Harden SQL value escaping for Lance `.where()` predicates.\n // Pre-T5.2 this only escaped single quotes (`'` → `''`). T5.2 adds:\n // - NUL byte rejection (NUL truncates the string in some SQL engines)\n // - C0 control char rejection (prevents invisible payload injection)\n // - Backslash escaping (`\\` → `\\\\` — some engines interpret `\\'` as\n // a single-quote escape, bypassing the `''` defense)\n // Synced from sdk-core per ADR 0002 byte-equivalence (iter 115).\n // Reject NUL + C0/DEL control chars (T5.5 pattern adapted for SQL).\n for (let i = 0; i < value.length; i++) {\n const code = value.charCodeAt(i);\n if (code === 0x00 || (code >= 0x01 && code <= 0x1f) || code === 0x7f) {\n throw new ConfigurationError(\n `SQL filter value contains control character at position ${i} (0x${code.toString(16)}). ` +\n \"This may indicate an injection attempt.\",\n { code: \"sql_injection_blocked\" },\n );\n }\n }\n // Escape both single-quote and backslash.\n return value.replace(/\\\\/g, \"\\\\\\\\\").replace(/'/g, \"''\");\n}\n\n/**\n * Test helper for {@link LanceIndex}: indicates whether the Lance module\n * is loadable in the current environment. Allows tests to gracefully skip\n * when the optional dep is absent.\n *\n * @internal\n */\nexport function isLanceAvailable(): boolean {\n try {\n const r = createRequire(import.meta.url);\n r(\"@lancedb/lancedb\");\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Test helper: re-export the storage path computation.\n *\n * @internal\n */\nexport function lanceStoragePath(cwd: string): string {\n return join(cwd, \".theokit\", \"memory\", \"lance\");\n}\n\nvoid existsSync; // imported but only used conditionally via mkdirSync\n","/**\n * Common `MemoryIndex` interface shared between the SQLite-backed\n * `IndexManager` (default) and the Lance-backed adapter (ADR D43, shipped\n * v1.4.0 via lancedb-backend-ship-v1-1 plan).\n *\n * Consumers (`local-agent-memory.ts`, `active-memory.ts`, `tools.ts`,\n * `runActiveMemory`) only ever call `sync()`, `search()`, `status()`,\n * `close()` — the union of those four methods is the portable surface.\n *\n * Why a separate file (vs declaring inline in `index-manager.ts`)? D43\n * promised \"extract an abstract `MemoryIndex` interface in\n * `internal/memory/index-interface.ts`\". Keeping the contract physically\n * separated from one of its implementations preserves OCP — future\n * backends (Qdrant, PGVector) can land without touching IndexManager.\n *\n * Iter 50 (Stage 3 source-move #7): hybrid copy from sdk-core's\n * `internal/memory/memory-index.ts`. sdk-core retains its copy for v1.x\n * back-compat; sdk-memory ships the canonical copy that future\n * `index-manager`, `lance-memory-adapter`, and `active-memory` moves\n * will target as siblings.\n *\n * **Iter 50 side-effect:** by publicly re-exporting `MemorySearchHit`\n * via the sdk-memory barrel, this file creates the FIRST reachable\n * downstream consumer for `MemorySearchHit` inside sdk-memory's\n * graph. That unblocks the rollup-plugin-dts treeshake limitation\n * the iter 48 inline-duplicate workaround was guarding against —\n * `internal/active-memory-types.ts` can now re-import the canonical\n * `MemorySearchHit` from `./index-manager-contract.js` and drop its\n * inline mirror. Deletion of that workaround lands in this same iter.\n *\n * @internal\n */\n\nimport type { IndexStatus, MemorySearchHit, SearchOptions } from \"./index-manager-contract.js\";\n\n// NOTE: the canonical sdk-core copy re-exports\n// `IndexStatus`/`MemorySearchHit`/`SearchOptions` here for stable\n// internal import paths. In sdk-memory the public barrel already does\n// `export * from \"./internal/index-manager-contract.js\"` (iter 47),\n// so re-exporting them a second time from this file confuses\n// rollup-plugin-dts and triggers a \"is not defined\" emit error\n// (rollup#4860-class pattern). Internal sdk-memory consumers should\n// import these types directly from `./index-manager-contract.js`.\n\n/**\n * What one `sync()` did. `filesScanned` counts every markdown file discovered,\n * including the unchanged ones; `filesUpdated` counts only those whose content\n * hash moved. `chunksEmbedded` is 0 on an index with no embedding runtime, and\n * also on a hybrid index where every chunk already had a vector.\n */\nexport interface SyncResult {\n filesScanned: number;\n filesUpdated: number;\n chunksWritten: number;\n chunksEmbedded: number;\n}\n\n/**\n * Common search-options parser used by both `IndexManager.search` and\n * `LanceMemoryAdapter.search`. Returns the normalized cap + minimum-score\n * floor — eliminates jscpd duplication while keeping per-backend search\n * logic distinct.\n */\nexport function parseSearchOptions(options: SearchOptions = {}): {\n maxResults: number;\n minScore: number;\n} {\n return {\n maxResults: Math.max(1, options.maxResults ?? 10),\n minScore: options.minScore ?? 0,\n };\n}\n\n/**\n * The four operations both backends implement, and the type every consumer\n * should hold. `IndexManager.open` returns this rather than a concrete class\n * precisely so `backend: \"lance\"` can be swapped in without changing the caller.\n *\n * The two backends differ in what they can honour, and the differences are\n * visible in the results rather than in the types — see `sync` and `search`\n * below, and `LanceMemoryAdapter` for the full list.\n */\nexport interface MemoryIndex {\n /**\n * Walk the memory corpus + reindex changed files. Lance backend has no\n * markdown corpus to walk — its adapter returns zero counts (no-op) and\n * relies on explicit `addFact` calls instead.\n */\n sync(): Promise<SyncResult>;\n\n /**\n * Semantic + textual search over the indexed corpus. Both backends\n * return the same `MemorySearchHit[]` shape; Lance reports `textScore` as 0\n * on every hit, because it is vector-only and has no FTS5 layer.\n */\n search(query: string, options?: SearchOptions): Promise<MemorySearchHit[]>;\n\n /** Snapshot of the index health (backend type + counts). */\n status(): IndexStatus;\n\n /** Release native handles. Idempotent. */\n close(): Promise<void> | void;\n}\n","/**\n * `LanceMemoryAdapter` — wraps `LanceIndex` to expose the common\n * `MemoryIndex` interface (sync/search/status/close) so consumers of\n * `IndexManager.open({ backend: \"lance\" })` get a drop-in replacement\n * for the SQLite-backed `IndexManager`.\n *\n * Semantic deltas vs SQLite (documented so callers know what to expect):\n *\n * - `sync()` is a NO-OP. Lance is a pure vector store — there is no\n * markdown corpus to crawl. Returns zero counts. Consumers writing\n * facts use `LanceIndex.addFacts` directly (exposed via the index\n * object returned to advanced callers).\n * - `search()` performs vector-only retrieval. `MemorySearchHit.textScore`\n * is 0 on every hit (no FTS5 layer); `vectorScore === score`.\n * - `status()` always reports `backend: \"hybrid\"` — embedding is required\n * at open, so there is no text-only Lance index. Both counts are 0: the\n * Lance row count is only available asynchronously and `status()` is\n * synchronous, so callers needing a real count call\n * `unwrap().countFacts()`. Lance does not track file provenance per row,\n * so `filesIndexed` has nothing to report either way.\n *\n * Ships with the lancedb-backend-ship-v1-1 plan (close D12, supersede via\n * D43). v1.4.0 of `@theokit/sdk`.\n *\n * Iter 69 (Stage 3 source-move #26): hybrid copy from sdk-core's\n * `internal/memory/lance-memory-adapter.ts`. sdk-core retains its\n * copy for v1.x Lance back-compat; sdk-memory ships the canonical\n * copy that the future `index-manager-dispatch.ts` move will compose\n * with as a sibling. Dependency chain (all sibling, all moved):\n * - `IndexStatus`, `MemorySearchHit`, `SearchOptions` from\n * `./index-manager-contract.js` (moved iter 47)\n * - `LanceIndex` from `./lance-index.js` (moved iter 68)\n * - `MemoryIndex`, `parseSearchOptions`, `SyncResult` from\n * `./memory-index.js` (moved iter 50)\n *\n * @internal\n */\n\nimport type { IndexStatus, MemorySearchHit, SearchOptions } from \"./index-manager-contract.js\";\nimport { type MemoryIndex, parseSearchOptions, type SyncResult } from \"./memory-index.js\";\n\n/**\n * **Iter 69 rollup-plugin-dts workaround** (mirrors iter 48/53/55/66/67 pattern).\n * Importing `LanceIndex` from sibling `./lance-index.js` fails dts\n * emit with `\"LanceIndex\" is not exported by \"src/internal/lance-index.ts\"`\n * because rollup-dts treeshakes the class when it has no public\n * type reaching it transitively — even though the barrel `export *`\n * makes it publicly callable. Same class as iter 66/67's MemoryDb.\n *\n * Fix: inline a structural mirror of the minimal LanceIndex surface\n * the adapter actually uses (search + close + identity for unwrap()\n * via `inner === actual LanceIndex`). The mirror is purely a TYPE —\n * the runtime continues to receive the real LanceIndex instance\n * unchanged. When a future move surfaces LanceIndex through a\n * different publicly-reachable path, this mirror MUST be deleted +\n * the canonical type import restored.\n *\n * @internal\n */\ninterface LanceIndex {\n addFacts(\n facts: ReadonlyArray<{\n id: string;\n text: string;\n source: \"memory\" | \"sessions\" | \"wiki\";\n namespace: string;\n scope: string;\n user_id: string;\n timestamp: number;\n }>,\n ): Promise<void>;\n search(\n query: string,\n opts: {\n namespace: string;\n scope?: string;\n limit?: number;\n sources?: ReadonlyArray<\"memory\" | \"sessions\" | \"wiki\">;\n },\n ): Promise<\n ReadonlyArray<{\n id: string;\n text: string;\n source: \"memory\" | \"sessions\" | \"wiki\";\n namespace: string;\n scope: string;\n userId: string;\n score: number;\n }>\n >;\n countFacts(namespace: string): Promise<number>;\n removeFacts(ids: ReadonlyArray<string>): Promise<void>;\n close(): Promise<void>;\n}\n\n/**\n * Default namespace used when consumers call `search()` without specifying\n * one. The SQLite `IndexManager` does not surface namespace in its public\n * `search()` signature either — both backends therefore behave consistently\n * under the \"single-workspace, single-namespace\" assumption that v1.4 ships.\n *\n * v1.5 candidate: surface `namespace` in `SearchOptions` (additive — no\n * breaking change) so multi-tenant Lance consumers can scope queries.\n */\nconst DEFAULT_NAMESPACE = \"default\";\n\n/** Empty sync result — Lance has no corpus to walk. */\nconst EMPTY_SYNC_RESULT: SyncResult = Object.freeze({\n filesScanned: 0,\n filesUpdated: 0,\n chunksWritten: 0,\n chunksEmbedded: 0,\n});\n\n/**\n * Presents a `LanceIndex` as a {@link MemoryIndex}, so a consumer written\n * against the SQLite index runs unchanged on `backend: \"lance\"`.\n *\n * Choose it when the corpus is large enough that SQLite plus sqlite-vec is the\n * bottleneck and you are willing to feed the index yourself. Stay on the SQLite\n * default when you want the markdown corpus crawled for you, or text matching on\n * exact terms: this adapter's `sync()` does nothing and its `search()` is\n * vector-only, so a query that would have matched by keyword now has to match by\n * meaning.\n *\n * Requires `@lancedb/lancedb`, an optional peer dependency. It is loaded when\n * the index is opened, not here.\n *\n * Two behaviours are worth knowing before switching. Facts only enter the index\n * through `unwrap().addFacts(...)` — nothing else writes to it. And `search()`\n * always queries the `default` namespace, because `SearchOptions` has no\n * namespace field to pass through, so a multi-tenant caller must open one index\n * per tenant rather than relying on the filter.\n */\nexport class LanceMemoryAdapter implements MemoryIndex {\n constructor(private readonly inner: LanceIndex) {}\n\n /**\n * No-op for Lance — see file header. Returns zero counts so callers'\n * existing logging (`filesScanned: X`) does not break.\n */\n async sync(): Promise<SyncResult> {\n return EMPTY_SYNC_RESULT;\n }\n\n // jscpd:ignore-start — search signature + early-out is idiomatic\n // overlap with IndexManager.search; further factoring would hurt\n // readability (the bodies diverge sharply right after).\n async search(query: string, options: SearchOptions = {}): Promise<MemorySearchHit[]> {\n if (query.trim().length === 0) return [];\n const { maxResults, minScore } = parseSearchOptions(options);\n // jscpd:ignore-end\n const lanceHits = await this.inner.search(query, {\n namespace: DEFAULT_NAMESPACE,\n limit: maxResults * 2,\n ...(options.sources !== undefined ? { sources: options.sources } : {}),\n });\n return lanceHits\n .filter((h) => h.score >= minScore)\n .slice(0, maxResults)\n .map((h) => translateLanceHit(h));\n }\n\n status(): IndexStatus {\n // chunksIndexed via a synchronous best-effort — Lance API is async so\n // we surface zero here and document that consumers needing exact counts\n // should call `inner.countFacts()` directly.\n return {\n backend: \"hybrid\",\n filesIndexed: 0,\n chunksIndexed: 0,\n };\n }\n\n async close(): Promise<void> {\n await this.inner.close();\n }\n\n /**\n * Escape hatch for advanced callers (migration tool, benchmark script)\n * that need direct access to addFacts/countFacts/removeFacts.\n */\n unwrap(): LanceIndex {\n return this.inner;\n }\n}\n\n/**\n * Translate `LanceSearchHit` to `MemorySearchHit`. Field mapping:\n *\n * - `id` → `path` (Lance has no file-system provenance; use opaque id)\n * - `text` → `snippet` (truncated to 200 chars matching IndexManager convention)\n * - `score` → `score` AND `vectorScore` (Lance is vector-only)\n * - `source` → `source`\n * - synthetic `startLine: 0, endLine: 0` (Lance has no line info)\n * - synthetic `citation: id` (no path:line citation available)\n * - `textScore` set to 0 (Lance does NOT do FTS5)\n */\nfunction translateLanceHit(hit: {\n id: string;\n text: string;\n source: \"memory\" | \"sessions\" | \"wiki\";\n score: number;\n}): MemorySearchHit {\n return {\n path: hit.id,\n startLine: 0,\n endLine: 0,\n score: hit.score,\n textScore: 0,\n vectorScore: hit.score,\n snippet: hit.text.slice(0, 200),\n source: hit.source,\n citation: hit.id,\n };\n}\n","/**\n * Dispatch helpers for `IndexManager.open`. Extracted to keep\n * `index-manager.ts` under the G8 400-LoC budget (lancedb-backend-ship-v1-1).\n *\n * Iter 70 (Stage 3 source-move #27): hybrid copy from sdk-core's\n * `internal/memory/index-manager-dispatch.ts`. sdk-core retains\n * its copy for v1.x back-compat; sdk-memory ships the canonical\n * copy that the future `index-manager.ts` move will compose with\n * as a sibling. Dependency chain (all sibling, all moved):\n * - `@theokit/sdk/errors` for `ConfigurationError` (public)\n * - `./index-manager-contract.js` for `MemoryBackend` +\n * `OpenIndexOptions` (moved iter 47)\n * - `./lance-index.js` for `LanceIndex` (moved iter 68)\n * - `./lance-memory-adapter.js` for `LanceMemoryAdapter` (moved iter 69)\n * - `./memory-index.js` for `MemoryIndex` (moved iter 50)\n *\n * @internal\n */\n\nimport { ConfigurationError } from \"@theokit/sdk/errors\";\n\nimport type { MemoryBackend, OpenIndexOptions } from \"./index-manager-contract.js\";\nimport { LanceIndex } from \"./lance-index.js\";\nimport { LanceMemoryAdapter } from \"./lance-memory-adapter.js\";\nimport type { MemoryIndex } from \"./memory-index.js\";\n\n/** Valid backend identifiers — runtime guard against TS-narrowing escapes (EC-1). */\nexport const VALID_BACKENDS: readonly MemoryBackend[] = [\"sqlite-vec\", \"lance\"];\n\n/**\n * EC-1: runtime guard for `opts.backend`. TS union is compile-time only;\n * consumers passing JS `as any` typos must hit a typed error, not silent\n * SQLite fallback.\n */\nexport function assertValidBackend(backend: string): asserts backend is MemoryBackend {\n if (!VALID_BACKENDS.includes(backend as MemoryBackend)) {\n throw new ConfigurationError(\n `Invalid memory backend \"${backend}\". Valid values: ${VALID_BACKENDS.join(\", \")}.`,\n { code: \"invalid_memory_backend\" },\n );\n }\n}\n\n/**\n * Lance-path open. Throws `lance_requires_embedding` when no embedding\n * runtime is provided (Lance is vector-only — no FTS fallback).\n * Surfaces `lance_backend_unavailable` from LanceIndex.open when peer\n * dep is absent.\n */\nexport async function openLanceIndex(opts: OpenIndexOptions): Promise<MemoryIndex> {\n if (opts.embedding === undefined) {\n throw new ConfigurationError(\n \"Lance backend requires an embedding runtime. Pass `embedding: { provider, model, apiKey }` in Memory.create options (or omit `backend` to use SQLite default).\",\n { code: \"lance_requires_embedding\" },\n );\n }\n const lance = await LanceIndex.open({\n cwd: opts.cwd,\n embedding: opts.embedding,\n ...(opts.filePath !== undefined ? { storagePath: opts.filePath } : {}),\n });\n return new LanceMemoryAdapter(lance);\n}\n","import { ConfigurationError } from \"@theokit/sdk/errors\";\n\n/**\n * **Iter 66 rollup-plugin-dts workaround** (mirrors iter 48/53/55 pattern).\n * The canonical sdk-core copy imports `MemoryDb` from `./index-db.js`\n * (sibling). In sdk-memory the same interface lives in sibling\n * `./index-db.js` (moved iter 65) but rollup-plugin-dts treeshakes\n * it out of the bundled .d.ts emit because no PUBLIC type reaches it\n * transitively yet — sqlite-vec-loader's signatures would be the\n * first consumer BUT rollup-dts resolves the import BEFORE the\n * loader's exports are bundled into the public emit. Result:\n * \"MemoryDb is not exported by src/internal/index-db.ts\" build error.\n *\n * Fix: inline a structural mirror of the minimal MemoryDb shape that\n * sqlite-vec-loader actually needs (just `prepare` for the version\n * probe; everything else delegated via the loader's untyped\n * dynamic-import call to sqlite-vec's native `load`). Mirror is\n * narrower than the canonical contract on purpose — this file's\n * runtime never touches exec/close/pragma/loadExtension directly.\n * When a future move turns MemoryDb into a publicly-reachable type\n * through a different path (e.g. vec-index.ts surfacing the interface\n * from its own typed signatures), this mirror MUST be deleted +\n * the canonical import restored.\n *\n * @internal\n */\ninterface MemoryDb {\n exec(sql: string): void;\n prepare(sql: string): {\n run(...args: unknown[]): { changes: number; lastInsertRowid: number | bigint };\n get(...args: unknown[]): Record<string, unknown> | undefined;\n all(...args: unknown[]): Array<Record<string, unknown>>;\n };\n pragma(statement: string, options?: { simple?: boolean }): unknown;\n close(): void;\n loadExtension(path: string): void;\n}\n\n/**\n * Load the `sqlite-vec` extension into an opened SQLite connection.\n *\n * Wraps the native `load(db)` call from the `sqlite-vec` npm package with a\n * typed error path (EC-8 of the edge-case review) so callers see a\n * `sqlite_vec_unavailable` ConfigurationError instead of a raw native error.\n *\n * Iter 66 (Stage 3 source-move #23): hybrid copy from sdk-core's\n * `internal/memory/sqlite-vec-loader.ts`. sdk-core retains its copy\n * for v1.x sqlite-vec back-compat; sdk-memory ships the canonical\n * copy that future `vec-index.ts` move will compose with as a\n * sibling. Dependency chain (all resolved):\n * - `@theokit/sdk/errors` for `ConfigurationError` (public)\n * - sibling `./index-db.js` for `MemoryDb` (moved iter 65)\n *\n * @internal\n */\nexport async function loadSqliteVecExtension(db: MemoryDb): Promise<void> {\n try {\n const mod = await import(\"sqlite-vec\");\n const loadFn = (mod as { load?: (db: unknown) => void }).load;\n if (typeof loadFn !== \"function\") {\n throw new Error(\"sqlite-vec module exposes no `load` export\");\n }\n loadFn(db);\n } catch (cause) {\n const message = cause instanceof Error ? cause.message : String(cause);\n throw new ConfigurationError(\n `sqlite-vec extension unavailable. Install \\`sqlite-vec\\` and ensure the native binary matches your Node + OS. Cause: ${message}`,\n { code: \"sqlite_vec_unavailable\", cause },\n );\n }\n}\n\n/** Check whether sqlite-vec is loaded by running a tiny version query. */\nexport function isSqliteVecLoaded(db: MemoryDb): boolean {\n try {\n const row = db.prepare(\"SELECT vec_version() as v\").get();\n return row !== undefined && row.v !== undefined;\n } catch {\n return false;\n }\n}\n","import type { EmbeddingRuntime } from \"../embedding/embedding-adapter.js\";\n\n/**\n * **Iter 67 rollup-plugin-dts workaround** (mirrors iter 48/53/55/66 pattern).\n * The canonical sdk-core copy imports `MemoryDb` from sibling\n * `./index-db.js`. In sdk-memory the same interface lives in sibling\n * `./index-db.js` (moved iter 65) but rollup-dts treeshakes it\n * out of the bundled .d.ts emit because no PUBLIC type reaches it\n * transitively yet. Same pattern as iter 66 with sqlite-vec-loader.\n *\n * Fix: inline a structural mirror of the minimal MemoryDb shape this\n * file actually needs (exec + prepare for SQL emits, plus pragma /\n * close / loadExtension on the canonical surface to stay shape-compatible\n * with consumers passing the real MemoryDb). When a future move\n * surfaces MemoryDb through a different publicly-reachable path,\n * this mirror MUST be deleted + the canonical import restored.\n *\n * @internal\n */\ninterface MemoryDb {\n exec(sql: string): void;\n prepare(sql: string): {\n run(...args: unknown[]): { changes: number; lastInsertRowid: number | bigint };\n get(...args: unknown[]): Record<string, unknown> | undefined;\n all(...args: unknown[]): Array<Record<string, unknown>>;\n };\n pragma(statement: string, options?: { simple?: boolean }): unknown;\n close(): void;\n loadExtension(path: string): void;\n}\n\n// Vector index helpers (ADR D2 + D4 of memory-system-peer-project-parity).\n//\n// Embeddings live in `embeddings(chunk_id, vec)` — a `vec0` virtual table\n// provided by the sqlite-vec extension. Embedding identity (providerId +\n// model + dimension) lives in the `meta` table; mismatches force a full\n// re-embed sweep (EC-1).\n//\n// Iter 67 (Stage 3 source-move #24): hybrid copy from sdk-core's\n// `internal/memory/vec-index.ts`. sdk-core retains its copy for v1.x\n// sqlite-vec back-compat; sdk-memory ships the canonical copy that\n// future `index-manager.ts` move will compose with as a sibling.\n// Dependency chain (both sibling, both moved):\n// - `EmbeddingRuntime` from `./embedding-adapter.js` (moved iter 45)\n// - `MemoryDb` from `./index-db.js` (moved iter 65)\n\n/**\n * `meta` table key holding the id of the embedding provider that produced the\n * vectors currently on disk (for example `openai`, `ollama`).\n */\nexport const META_KEY_PROVIDER_ID = \"embedding.providerId\";\n/** `meta` table key holding the embedding model id the vectors were produced with. */\nexport const META_KEY_MODEL = \"embedding.model\";\n/** `meta` table key holding the vector width the `embeddings` vec0 table was created with. */\nexport const META_KEY_DIMENSION = \"embedding.dimension\";\n\n/**\n * The three facts that decide whether the vectors already stored are still\n * usable: who produced them, with which model, at which width. A change in any\n * of the three invalidates every vector in the index, because embeddings from\n * different models are not comparable and a different width will not even fit\n * the vec0 table.\n */\nexport interface EmbeddingIdentity {\n providerId: string;\n model: string;\n dimension: number;\n}\n\n/**\n * Read the embedding identity recorded in the `meta` table.\n *\n * Returns `undefined` when the index has never been embedded, and also when the\n * record is incomplete or unusable: any of the three keys missing, or a stored\n * dimension that is not a finite number greater than zero. Callers treat that as\n * \"no identity\" and write a fresh one rather than trying to repair it.\n */\nexport function readEmbeddingIdentity(db: MemoryDb): EmbeddingIdentity | undefined {\n const get = (key: string): string | undefined => {\n const row = db.prepare(\"SELECT value FROM meta WHERE key = ?\").get(key);\n return row !== undefined ? String(row.value) : undefined;\n };\n const providerId = get(META_KEY_PROVIDER_ID);\n const model = get(META_KEY_MODEL);\n const dimRaw = get(META_KEY_DIMENSION);\n if (providerId === undefined || model === undefined || dimRaw === undefined) return undefined;\n const dimension = Number(dimRaw);\n if (!Number.isFinite(dimension) || dimension <= 0) return undefined;\n return { providerId, model, dimension };\n}\n\n/**\n * Record the embedding identity in the `meta` table, upserting each of the three\n * keys. Call this after {@link createVectorIndex}, so that a later open can tell\n * whether the vectors on disk match the runtime it has been handed.\n */\nexport function writeEmbeddingIdentity(db: MemoryDb, identity: EmbeddingIdentity): void {\n const stmt = db.prepare(\n \"INSERT INTO meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value\",\n );\n stmt.run(META_KEY_PROVIDER_ID, identity.providerId);\n stmt.run(META_KEY_MODEL, identity.model);\n stmt.run(META_KEY_DIMENSION, String(identity.dimension));\n}\n\n/**\n * Compare two embedding identities field by field. All three fields must be\n * equal; there is no tolerance on dimension, because a mismatch there is a hard\n * failure at the vec0 table rather than a quality regression.\n */\nexport function identityMatches(a: EmbeddingIdentity, b: EmbeddingIdentity): boolean {\n return a.providerId === b.providerId && a.model === b.model && a.dimension === b.dimension;\n}\n\n/**\n * Drop the `embeddings` table, discarding every stored vector. `IndexManager`\n * calls this when {@link identityMatches} reports that the persisted identity\n * differs from the embedding runtime it was opened with; the next `sync()` then\n * re-embeds the whole corpus. The `chunks` and `files` tables are untouched, so\n * the text index survives the drop.\n */\nexport function dropVectorIndex(db: MemoryDb): void {\n db.exec(\"DROP TABLE IF EXISTS embeddings\");\n}\n\n/**\n * Create the `embeddings` vec0 virtual table at the given vector width, if it\n * does not exist already. Requires the sqlite-vec extension to be loaded into\n * `db` first (see `loadSqliteVecExtension`) — without it SQLite has no `vec0`\n * module and the statement fails.\n *\n * `IF NOT EXISTS` means this will NOT widen an existing table: to change the\n * dimension, call {@link dropVectorIndex} first.\n */\nexport function createVectorIndex(db: MemoryDb, dimension: number): void {\n db.exec(`CREATE VIRTUAL TABLE IF NOT EXISTS embeddings USING vec0(\n chunk_id INTEGER PRIMARY KEY,\n vec FLOAT[${dimension}]\n )`);\n}\n\n/** Pack a Float32Array into a Buffer suitable for sqlite-vec BLOB binding. */\nexport function packVector(vec: ReadonlyArray<number>): Buffer {\n const f32 = new Float32Array(vec.length);\n for (let i = 0; i < vec.length; i++) f32[i] = vec[i] ?? 0;\n return Buffer.from(f32.buffer);\n}\n\n/**\n * Store the vector for one chunk, replacing any vector already held for it.\n *\n * Implemented as DELETE followed by INSERT because vec0 virtual tables do not\n * support `ON CONFLICT`. The chunk id is bound as a BigInt: vec0 v0.1.9 rejects\n * a JavaScript number for its primary-key column.\n */\nexport function upsertEmbedding(db: MemoryDb, chunkId: number, vec: ReadonlyArray<number>): void {\n // sqlite-vec vec0 virtual tables don't support UPSERT — emulate via\n // DELETE-then-INSERT. vec0 REJECTS JS Number for chunk_id columns; it\n // requires BigInt binding. Verified via repro against vec0 v0.1.9.\n const id = BigInt(chunkId);\n db.prepare(\"DELETE FROM embeddings WHERE chunk_id = ?\").run(id);\n db.prepare(\"INSERT INTO embeddings (chunk_id, vec) VALUES (?, ?)\").run(id, packVector(vec));\n}\n\n/**\n * One row of a vec0 KNN result: the chunk id and its raw distance from the query\n * vector. Distance is the sqlite-vec convention — lower is closer — and is NOT a\n * similarity score. `IndexManager` maps it to `1 / (1 + distance)` before\n * blending it with the text score.\n */\nexport interface VectorHitRow {\n chunk_id: number;\n distance: number;\n}\n\n/**\n * Run a k-nearest-neighbour query against the `embeddings` table and return the\n * matches ordered by ascending distance (closest first).\n *\n * `query` must have the same width the table was created with. Both the query\n * vector and `k` are bound in the form vec0 expects — the vector as a packed\n * Float32 blob, `k` as a BigInt.\n */\nexport function vectorSearch(\n db: MemoryDb,\n query: ReadonlyArray<number>,\n k: number,\n): VectorHitRow[] {\n // sqlite-vec returns distance (lower = closer). Use KNN syntax. k needs\n // a BigInt-typed binding too.\n const rows = db\n .prepare(\n `SELECT chunk_id, distance FROM embeddings\n WHERE vec MATCH ? AND k = ?\n ORDER BY distance`,\n )\n .all(packVector(query), BigInt(k));\n return rows.map((row) => ({ chunk_id: Number(row.chunk_id), distance: Number(row.distance) }));\n}\n\n/** Inputs for {@link embedMissingChunks}: the open database and the embedding runtime to call. */\nexport interface EmbedAllArgs {\n db: MemoryDb;\n runtime: EmbeddingRuntime;\n}\n\n/** Embed every chunk that doesn't yet have a vector. */\nexport async function embedMissingChunks(args: EmbedAllArgs): Promise<number> {\n const rows = args.db\n .prepare(\n `SELECT chunks.id as id, chunks.text as text\n FROM chunks\n LEFT JOIN embeddings ON embeddings.chunk_id = chunks.id\n WHERE embeddings.chunk_id IS NULL`,\n )\n .all();\n if (rows.length === 0) return 0;\n const normalized = rows.map((row) => ({ id: Number(row.id), text: String(row.text ?? \"\") }));\n const vectors = await args.runtime.embed(normalized.map((r) => r.text));\n for (let i = 0; i < normalized.length; i++) {\n const row = normalized[i];\n const vector = vectors[i];\n if (row === undefined || vector === undefined) continue;\n upsertEmbedding(args.db, row.id, vector);\n }\n return normalized.length;\n}\n","import { createHash } from \"node:crypto\";\nimport { readdir, readFile, stat } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\n\nimport { sanitizeFts5Query } from \"@theokit/sdk/persistence\";\nimport type { EmbeddingRuntime } from \"../embedding/embedding-adapter.js\";\nimport { chunkMarkdown } from \"../store/chunk-markdown.js\";\nimport { memoryDir, memoryMdPath, notesDir } from \"../store/markdown-store.js\";\nimport { discoverSessionFiles } from \"../store/session-loader.js\";\nimport { discoverWikiFiles } from \"../store/wiki-loader.js\";\nimport { defaultIndexPath, type MemoryDb, openMemoryDb } from \"./index-db.js\";\nimport { assertValidBackend, openLanceIndex } from \"./index-manager-dispatch.js\";\nimport { type MemoryIndex, parseSearchOptions } from \"./memory-index.js\";\nimport { loadSqliteVecExtension } from \"./sqlite-vec-loader.js\";\nimport {\n createVectorIndex,\n dropVectorIndex,\n embedMissingChunks,\n identityMatches,\n readEmbeddingIdentity,\n vectorSearch,\n writeEmbeddingIdentity,\n} from \"./vec-index.js\";\n\n/**\n * Memory index manager (ADR D2). FTS5-only at Phase 3; vector index lands in\n * Phase 5.\n *\n * Lifecycle:\n * const idx = await IndexManager.open({ cwd });\n * await idx.sync();\n * const hits = await idx.search(\"query\");\n * idx.close();\n *\n * Iter 72 (Stage 3 source-move #29): hybrid copy from sdk-core's\n * `internal/memory/index-manager.ts`. sdk-core retains its copy for\n * v1.x back-compat; sdk-memory ships the canonical orchestrator\n * composing every prior Stage 3 move (sqlite-vec stack iter 47/49/50/53/55-57/62/65-67,\n * lance stack iter 68-70, storage iter 56). The biggest move of the\n * stage at 446 LOC — closes the index/ cluster.\n *\n * @internal\n */\n\n// T2.1 / ADR D433 — these types live in `index-manager-contract.ts`\n// (iter 47). The canonical sdk-core copy re-exports them here for\n// back-compat. In sdk-memory the public barrel already does\n// `export * from \"./internal/index-manager-contract.js\"` so a second\n// re-export from this file confuses rollup-dts and triggers\n// \"is not exported\" emit errors. Mirrors iter 50 memory-index NOTE.\n//\n// **Iter 72 rollup-plugin-dts workaround** (mirrors iter 48/53/55/66/67/69):\n// the canonical sdk-core copy imports `MemorySearchHit` (et al.) from\n// sibling. rollup-dts treeshakes the inner type declarations because\n// no PUBLIC type reaches them transitively yet within this file's\n// bundling pass. Fix: declare structural mirrors of the index-manager-contract\n// types inline so the index-manager.ts file's emit is self-contained.\n// When a future move surfaces these through a different\n// publicly-reachable path, these mirrors MUST be deleted + the\n// canonical type imports restored.\n\ninterface MemorySearchHit {\n readonly path: string;\n readonly startLine: number;\n readonly endLine: number;\n readonly score: number;\n readonly textScore: number;\n readonly vectorScore?: number;\n readonly snippet: string;\n readonly source: \"memory\" | \"sessions\" | \"wiki\";\n readonly citation: string;\n}\n\ninterface IndexStatus {\n backend: \"fts-only\" | \"hybrid\";\n filesIndexed: number;\n chunksIndexed: number;\n lastSyncMs?: number;\n}\n\ninterface SearchOptions {\n maxResults?: number;\n minScore?: number;\n vectorWeight?: number;\n textWeight?: number;\n sources?: ReadonlyArray<\"memory\" | \"sessions\" | \"wiki\">;\n}\n\ninterface OpenIndexOptions {\n cwd: string;\n filePath?: string;\n embedding?: EmbeddingRuntime;\n backend?: \"sqlite-vec\" | \"lance\";\n}\n\n/**\n * The default memory index: SQLite for storage, FTS5 for text matching, and\n * sqlite-vec for vectors when an embedding runtime is supplied.\n *\n * Open it with the static `open`, which is also the dispatch point for\n * `backend: \"lance\"` — that overload returns a `LanceMemoryAdapter`, not an\n * `IndexManager`, so hold the result as {@link MemoryIndex} unless you need this\n * class specifically.\n *\n * Storage needs `better-sqlite3` unless the running Node exposes `node:sqlite`,\n * and vectors additionally need `sqlite-vec`. Both are optional peer\n * dependencies of this package. Without an embedding runtime the index opens\n * text-only and reports `backend: \"fts-only\"`; no vector table is created and\n * search degrades to BM25 rather than failing.\n *\n * `sync()` crawls the markdown corpus — `MEMORY.md`, `notes/`, `wiki/` and\n * `sessions/` — skipping files whose content hash has not moved, and re-chunking\n * the rest. Nothing is indexed until it runs.\n *\n * If the embedding provider, model or dimension differs from what the database\n * recorded, opening drops the whole vector table so the next `sync()` re-embeds\n * from scratch. Switching embedding models is therefore safe but not cheap.\n *\n * `search()` runs both halves and blends them per chunk, so a chunk found only\n * by vector still appears with a text score of 0 and the other way round.\n * `close()` releases the database handle; it is synchronous here, unlike the\n * Lance adapter's, so a caller holding the {@link MemoryIndex} type must await\n * it either way.\n */\nexport class IndexManager implements MemoryIndex {\n private lastSyncMs: number | undefined;\n private vectorReady = false;\n\n private constructor(\n private readonly cwd: string,\n private readonly db: MemoryDb,\n private readonly embedding: EmbeddingRuntime | undefined,\n ) {}\n\n /**\n * Open a memory index. Dispatches to SQLite (default) or Lance (opt-in\n * via `backend: \"lance\"`). See `openLanceIndex` for Lance-specific\n * preconditions + typed errors.\n */\n static async open(opts: OpenIndexOptions & { backend: \"lance\" }): Promise<MemoryIndex>;\n static async open(\n opts: Omit<OpenIndexOptions, \"backend\"> | (OpenIndexOptions & { backend?: \"sqlite-vec\" }),\n ): Promise<IndexManager>;\n static async open(opts: OpenIndexOptions): Promise<MemoryIndex> {\n const backend = opts.backend ?? \"sqlite-vec\";\n assertValidBackend(backend);\n if (backend === \"lance\") return await openLanceIndex(opts);\n return await IndexManager.openSqliteInternal(opts);\n }\n\n /** Internal SQLite-path open. Renamed from previous public `open`. */\n private static async openSqliteInternal(opts: OpenIndexOptions): Promise<IndexManager> {\n const filePath = opts.filePath ?? defaultIndexPath(opts.cwd);\n const db = await openMemoryDb({ filePath });\n const manager = new IndexManager(opts.cwd, db, opts.embedding);\n if (opts.embedding !== undefined) await manager.initVectorBackend(opts.embedding);\n return manager;\n }\n\n private async initVectorBackend(runtime: EmbeddingRuntime): Promise<void> {\n await loadSqliteVecExtension(this.db);\n const currentIdentity = {\n providerId: runtime.id,\n model: runtime.model,\n dimension: runtime.dimension,\n };\n const persisted = readEmbeddingIdentity(this.db);\n if (persisted !== undefined && !identityMatches(persisted, currentIdentity)) {\n // EC-1: dimension/model/provider changed — drop the vector index and\n // force a full re-embed on next sync.\n dropVectorIndex(this.db);\n }\n createVectorIndex(this.db, runtime.dimension);\n writeEmbeddingIdentity(this.db, currentIdentity);\n this.vectorReady = true;\n }\n\n /** Walk the memory corpus + (re)index changed files. */\n async sync(): Promise<{\n filesScanned: number;\n filesUpdated: number;\n chunksWritten: number;\n chunksEmbedded: number;\n }> {\n const files = await collectMarkdownFiles(this.cwd);\n let filesUpdated = 0;\n let chunksWritten = 0;\n const existingByPath = this.loadFilesIndex();\n for (const entry of files) {\n const raw = await readFile(entry.absolutePath, \"utf8\");\n const hash = sha256(raw);\n const existing = existingByPath.get(entry.absolutePath);\n if (existing !== undefined && existing.hash === hash) continue;\n const stats = await stat(entry.absolutePath);\n const fileId = this.upsertFile(\n entry.absolutePath,\n entry.relPath,\n hash,\n stats.mtimeMs,\n entry.source,\n );\n this.deleteChunksForFile(fileId);\n const chunks = chunkMarkdown(raw);\n for (const chunk of chunks) {\n this.insertChunk(fileId, chunk.startLine, chunk.endLine, chunk.text, chunk.hash);\n }\n filesUpdated += 1;\n chunksWritten += chunks.length;\n }\n let chunksEmbedded = 0;\n if (this.vectorReady && this.embedding !== undefined) {\n chunksEmbedded = await embedMissingChunks({ db: this.db, runtime: this.embedding });\n }\n this.lastSyncMs = Date.now();\n return { filesScanned: files.length, filesUpdated, chunksWritten, chunksEmbedded };\n }\n\n async search(query: string, options: SearchOptions = {}): Promise<MemorySearchHit[]> {\n if (query.trim().length === 0) return [];\n const { maxResults, minScore } = parseSearchOptions(options);\n const textHits = this.ftsSearch(query, maxResults * 2);\n const vectorHitsById = await this.vectorSearchById(query, maxResults * 2);\n const combined = this.combineHybridScores(textHits, vectorHitsById, options);\n return combined\n .filter((h) => h.score >= minScore)\n .filter((h) => options.sources === undefined || options.sources.includes(h.source))\n .slice(0, maxResults);\n }\n\n status(): IndexStatus {\n const files = this.db.prepare(\"SELECT COUNT(*) as n FROM files\").get() ?? { n: 0 };\n const chunks = this.db.prepare(\"SELECT COUNT(*) as n FROM chunks\").get() ?? { n: 0 };\n const status: IndexStatus = {\n backend: this.vectorReady ? \"hybrid\" : \"fts-only\",\n filesIndexed: Number(files.n ?? 0),\n chunksIndexed: Number(chunks.n ?? 0),\n };\n if (this.lastSyncMs !== undefined) status.lastSyncMs = this.lastSyncMs;\n return status;\n }\n\n // ───── search internals ──────────────────────────────────────────────\n\n private ftsSearch(query: string, limit: number): Array<MemorySearchHit & { chunkId: number }> {\n // EC-3: short-circuit when sanitizer reduces input to empty string.\n // Calling `MATCH ''` would error inside FTS5 on some SQLite versions.\n const sanitized = sanitizeFts5Query(query);\n if (sanitized.length === 0) return [];\n const stmt = this.db.prepare(\n `SELECT chunks.id as id, files.rel_path as rel_path, files.source as source,\n chunks.start_line as start_line, chunks.end_line as end_line,\n chunks.text as text, bm25(chunks_fts) as bm25_score\n FROM chunks_fts\n JOIN chunks ON chunks_fts.rowid = chunks.id\n JOIN files ON chunks.file_id = files.id\n WHERE chunks_fts MATCH ?\n ORDER BY bm25_score\n LIMIT ?`,\n );\n let rows: Array<Record<string, unknown>> = [];\n try {\n rows = stmt.all(sanitized, limit);\n } catch {\n return [];\n }\n return rows.map((row) => {\n const bm25 = Number(row.bm25_score ?? 0);\n const textScore = bm25 < 0 ? 1 / (1 + Math.abs(bm25)) : 1 / (1 + bm25);\n const startLine = Number(row.start_line ?? 0);\n const endLine = Number(row.end_line ?? 0);\n const path = String(row.rel_path);\n return {\n path,\n startLine,\n endLine,\n score: textScore,\n textScore,\n snippet: truncateSnippet(String(row.text ?? \"\")),\n source: String(row.source) as \"memory\" | \"sessions\" | \"wiki\",\n citation: `${path}:${startLine}-${endLine}`,\n // sneak the chunk id through for the hybrid join below\n // (cast away later)\n chunkId: Number(row.id),\n } as MemorySearchHit & { chunkId: number };\n });\n }\n\n private async vectorSearchById(\n query: string,\n limit: number,\n ): Promise<Map<number, { vectorScore: number; snippet?: string }>> {\n if (!this.vectorReady || this.embedding === undefined) return new Map();\n const [queryVec] = await this.embedding.embed([query]);\n if (queryVec === undefined) return new Map();\n const rows = vectorSearch(this.db, queryVec, limit);\n // sqlite-vec distance: lower = closer. Normalize to 0..1 with higher = better.\n const out = new Map<number, { vectorScore: number }>();\n for (const row of rows) {\n const score = 1 / (1 + Math.max(0, row.distance));\n out.set(row.chunk_id, { vectorScore: score });\n }\n return out;\n }\n\n private combineHybridScores(\n textHits: Array<MemorySearchHit & { chunkId: number }>,\n vectorHitsById: Map<number, { vectorScore: number }>,\n options: SearchOptions,\n ): MemorySearchHit[] {\n const weights = resolveWeights(options);\n const merged = this.mergeHits(textHits, vectorHitsById);\n const combined = [...merged.values()].map((hit) =>\n blendScores(hit, vectorHitsById.get(hit.chunkId)?.vectorScore ?? 0, weights),\n );\n return combined.sort((a, b) => b.score - a.score);\n }\n\n private mergeHits(\n textHits: Array<MemorySearchHit & { chunkId: number }>,\n vectorHitsById: Map<number, { vectorScore: number }>,\n ): Map<number, MemorySearchHit & { chunkId: number }> {\n const merged = new Map<number, MemorySearchHit & { chunkId: number }>();\n for (const hit of textHits) merged.set(hit.chunkId, hit);\n const missingIds = [...vectorHitsById.keys()].filter((id) => !merged.has(id));\n if (missingIds.length > 0) {\n for (const hit of this.fetchChunksByIds(missingIds)) {\n merged.set(hit.chunkId, { ...hit, score: 0, textScore: 0 });\n }\n }\n return merged;\n }\n\n private fetchChunksByIds(\n ids: ReadonlyArray<number>,\n ): Array<MemorySearchHit & { chunkId: number }> {\n if (ids.length === 0) return [];\n const placeholders = ids.map(() => \"?\").join(\",\");\n const rows = this.db\n .prepare(\n `SELECT chunks.id as id, files.rel_path as rel_path, files.source as source,\n chunks.start_line as start_line, chunks.end_line as end_line,\n chunks.text as text\n FROM chunks JOIN files ON chunks.file_id = files.id\n WHERE chunks.id IN (${placeholders})`,\n )\n .all(...ids);\n return rows.map((row) => {\n const startLine = Number(row.start_line ?? 0);\n const endLine = Number(row.end_line ?? 0);\n const path = String(row.rel_path);\n return {\n chunkId: Number(row.id),\n path,\n startLine,\n endLine,\n score: 0,\n textScore: 0,\n snippet: truncateSnippet(String(row.text ?? \"\")),\n source: String(row.source) as \"memory\" | \"sessions\" | \"wiki\",\n citation: `${path}:${startLine}-${endLine}`,\n };\n });\n }\n\n // ───── persistence helpers ─────────────────────────────────────────\n\n private loadFilesIndex(): Map<string, { id: number; hash: string }> {\n const rows = this.db.prepare(\"SELECT id, path, hash FROM files\").all() as Array<{\n id: number;\n path: string;\n hash: string;\n }>;\n return new Map(rows.map((row) => [row.path, { id: row.id, hash: row.hash }]));\n }\n\n private upsertFile(\n absPath: string,\n relPath: string,\n hash: string,\n mtimeMs: number,\n source: \"memory\" | \"wiki\" | \"sessions\" = \"memory\",\n ): number {\n const stmt = this.db.prepare(\n `INSERT INTO files (path, rel_path, mtime, hash, source) VALUES (?, ?, ?, ?, ?)\n ON CONFLICT(path) DO UPDATE SET hash = excluded.hash, mtime = excluded.mtime, source = excluded.source\n RETURNING id`,\n );\n const row = stmt.get(absPath, relPath, Math.floor(mtimeMs), hash, source) as { id: number };\n return row.id;\n }\n\n private deleteChunksForFile(fileId: number): void {\n this.db.prepare(\"DELETE FROM chunks WHERE file_id = ?\").run(fileId);\n }\n\n private insertChunk(\n fileId: number,\n startLine: number,\n endLine: number,\n text: string,\n hash: string,\n ): void {\n this.db\n .prepare(\n \"INSERT INTO chunks (file_id, start_line, end_line, text, hash) VALUES (?, ?, ?, ?, ?)\",\n )\n .run(fileId, startLine, endLine, text, hash);\n }\n\n close(): void {\n this.db.close();\n }\n}\n\n// ───── module-level helpers (hybrid scoring) ─────────────────────────────\n\ninterface HybridWeights {\n vectorWeight: number;\n textWeight: number;\n total: number;\n}\n\nfunction resolveWeights(options: SearchOptions): HybridWeights {\n const vectorWeight = options.vectorWeight ?? 0.6;\n const textWeight = options.textWeight ?? 0.4;\n const total = vectorWeight + textWeight || 1;\n return { vectorWeight, textWeight, total };\n}\n\nfunction blendScores(\n hit: MemorySearchHit & { chunkId: number },\n vectorScore: number,\n weights: HybridWeights,\n): MemorySearchHit {\n const score =\n (vectorScore * weights.vectorWeight + hit.textScore * weights.textWeight) / weights.total;\n return {\n path: hit.path,\n startLine: hit.startLine,\n endLine: hit.endLine,\n score,\n textScore: hit.textScore,\n snippet: hit.snippet,\n source: hit.source,\n citation: hit.citation,\n ...(vectorScore > 0 ? { vectorScore } : {}),\n };\n}\n\ninterface DiscoveredFile {\n absolutePath: string;\n relPath: string;\n source: \"memory\" | \"wiki\" | \"sessions\";\n}\n\nasync function collectMarkdownFiles(cwd: string): Promise<DiscoveredFile[]> {\n const root = memoryDir(cwd);\n const results: DiscoveredFile[] = [];\n // MEMORY.md\n try {\n await stat(memoryMdPath(cwd));\n results.push({\n absolutePath: memoryMdPath(cwd),\n relPath: relative(root, memoryMdPath(cwd)),\n source: \"memory\",\n });\n } catch {\n // skip\n }\n // notes/*.md\n try {\n const entries = await readdir(notesDir(cwd));\n for (const entry of entries) {\n if (!entry.endsWith(\".md\")) continue;\n const abs = join(notesDir(cwd), entry);\n results.push({ absolutePath: abs, relPath: relative(root, abs), source: \"memory\" });\n }\n } catch {\n // notes dir doesn't exist yet — that's fine\n }\n // wiki/*.md (Phase 10 — read-only supplements)\n const wikiFiles = await discoverWikiFiles(cwd);\n for (const wiki of wikiFiles) {\n results.push({\n absolutePath: wiki.absolutePath,\n relPath: wiki.relPath,\n source: \"wiki\",\n });\n }\n // sessions/*.md (ADR D20 — per-run summaries for corpus=\"sessions\" recall)\n const sessionFiles = await discoverSessionFiles(cwd);\n for (const session of sessionFiles) {\n results.push({\n absolutePath: session.absolutePath,\n relPath: session.relPath,\n source: \"sessions\",\n });\n }\n return results;\n}\n\nfunction sha256(text: string): string {\n return createHash(\"sha256\").update(text).digest(\"hex\");\n}\n\nfunction truncateSnippet(text: string): string {\n const max = 500;\n return text.length <= max ? text : `${text.slice(0, max)}…`;\n}\n\n// Replaced by `sanitizeFts5Query` from `@theokit/sdk/persistence`\n// (T5.2, ADR D64). The new sanitizer is the 6-step port of Hermes'\n// `_sanitize_fts5_query` and handles hyphens/dots/underscores correctly\n// without quoting every token.\n","import { existsSync, mkdirSync, renameSync, rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { ConfigurationError } from \"@theokit/sdk/errors\";\nimport { redactSecrets } from \"../memory-types.js\";\nimport { defaultIndexPath, openMemoryDb } from \"./index-db.js\";\nimport { LanceIndex, lanceStoragePath } from \"./lance-index.js\";\n\n/**\n * Migrate Memory.index from SQLite to LanceDB (ADR D44).\n *\n * EC-3 MUST FIX: validation uses NFC unicode normalization on both sides.\n *\n * Iter 71 (Stage 3 source-move #28): hybrid copy from sdk-core's\n * `internal/memory/migrate-sqlite-to-lance.ts`. sdk-core retains its\n * copy for v1.x migration back-compat; sdk-memory ships the canonical\n * copy.\n *\n * Dependency chain (all resolved):\n * - `@theokit/sdk/errors` for `ConfigurationError` (public)\n * - sibling `./memory-types.js` for `redactSecrets` (moved iter 52)\n * - sibling `./index-db.js` for `defaultIndexPath` + `openMemoryDb` (moved iter 65)\n * - sibling `./lance-index.js` for `LanceIndex` + `lanceStoragePath` (moved iter 68)\n *\n * @internal\n */\n\nexport interface MigrateOptions {\n cwd: string;\n dryRun?: boolean;\n batchSize?: number;\n /** Inject for tests; defaults to console.log. */\n logger?: (msg: string) => void;\n}\n\n/**\n * Outcome of {@link migrateSqliteToLance}.\n *\n * Read `committed` first: it is `false` for a dry run and for a failed\n * validation, and only `true` when the staging directory was promoted to\n * `lance/`. `validated` reports whether the counts matched and the sampled facts\n * compared equal; `sampleComparisons` holds up to ten of those comparisons so a\n * failure can be inspected rather than merely counted.\n *\n * The SQLite database is left in place either way — this migration copies, it\n * does not move.\n */\nexport interface MigrateResult {\n countSqlite: number;\n countLance: number;\n /** Set when validation succeeded (or dryRun); false on validation failure. */\n validated: boolean;\n /** Per-fact compare results (size = sample count, up to 10). */\n sampleComparisons: ReadonlyArray<{ id: string; match: boolean }>;\n /** Lance storage location (final, after migration). */\n lancePath: string;\n /** Was the migration committed (false for dry-run). */\n committed: boolean;\n}\n\ninterface SqliteFactRow {\n id: string;\n path: string;\n source: \"memory\" | \"sessions\" | \"wiki\";\n start_line: number;\n end_line: number;\n text: string;\n namespace?: string | null;\n scope?: string | null;\n user_id?: string | null;\n}\n\n/**\n * Read all facts from the SQLite memory index. Returns empty array if the\n * SQLite db file does not exist (workspace never used Memory).\n *\n * @internal\n */\nasync function readAllSqliteFacts(cwd: string): Promise<SqliteFactRow[]> {\n const dbPath = defaultIndexPath(cwd);\n if (!existsSync(dbPath)) return [];\n const db = await openMemoryDb({ filePath: dbPath });\n try {\n // SQLite schema: chunks table holds the facts. Schema may vary; we\n // probe column existence and fall back to safe defaults.\n const stmt = db.prepare(\"SELECT id, path, source, start_line, end_line, text FROM chunks\");\n const rows = stmt.all() as Array<{\n id: string;\n path: string;\n source: \"memory\" | \"sessions\" | \"wiki\";\n start_line: number;\n end_line: number;\n text: string;\n }>;\n return rows.map((r) => ({\n ...r,\n namespace: \"default\",\n scope: \"agent\",\n user_id: \"default\",\n }));\n } finally {\n db.close();\n }\n}\n\n/**\n * Compare two strings via NFC normalization (EC-3 MUST FIX). Required\n * because SQLite/Lance native bindings can normalize unicode differently\n * (NFC vs NFD), producing false negatives on facts with accents/emojis.\n *\n * @internal\n */\nfunction nfcEqual(a: string, b: string): boolean {\n return a.normalize(\"NFC\") === b.normalize(\"NFC\");\n}\n\n/**\n * Run the migration. Writes Lance to `<cwd>/.theokit/memory/lance-new/`\n * first, validates round-trip, then renames to `lance/` on success.\n * SQLite db is preserved (CLI prompts user to delete).\n *\n * @internal\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: migration is a single transaction (read → write → validate → commit-or-rollback); splitting harms atomicity reasoning.\nexport async function migrateSqliteToLance(opts: MigrateOptions): Promise<MigrateResult> {\n const cwd = opts.cwd;\n const finalPath = lanceStoragePath(cwd);\n const newPath = join(cwd, \".theokit\", \"memory\", \"lance-new\");\n // T1.4 (ADR D68): wrap logger so any fact text containing secrets is\n // masked before reaching the destination (console or user-supplied sink).\n // Caller-supplied loggers cannot bypass — by design (D70).\n const rawLog = opts.logger ?? ((m: string) => console.log(m));\n const log = (m: string) => rawLog(redactSecrets(m));\n\n // EC: destination exists → typed error.\n if (existsSync(finalPath)) {\n throw new ConfigurationError(\n `Destination already exists: ${finalPath}. Remove it manually (\\`rm -rf ${finalPath}\\`) and re-run.`,\n { code: \"migration_destination_exists\" },\n );\n }\n if (existsSync(newPath)) {\n // Leftover from a previous failed/interrupted migration. Safe to delete.\n log(`Removing stale ${newPath} from a previous run...`);\n rmSync(newPath, { recursive: true, force: true });\n }\n\n log(`Reading SQLite facts from ${cwd}/.theokit/memory/index.sqlite ...`);\n const sqliteFacts = await readAllSqliteFacts(cwd);\n log(`SQLite has ${sqliteFacts.length} facts.`);\n if (sqliteFacts.length === 0) {\n return {\n countSqlite: 0,\n countLance: 0,\n validated: true,\n sampleComparisons: [],\n lancePath: finalPath,\n committed: false,\n };\n }\n\n // Reuse the embedding runtime configured in the workspace? For v1.2 we\n // require the caller to pass embedding explicitly via env. The migration\n // path is documented as: \"set OPENAI_API_KEY (or similar) before running.\"\n // Here we ship a placeholder embedder that uses a deterministic\n // content-hash — sufficient for migration validation; consumers should\n // re-embed on first real query after migration if needed.\n const placeholderEmbedding = {\n id: \"migration-placeholder\",\n model: \"deterministic-hash\",\n dimension: 8,\n embed: async (texts: ReadonlyArray<string>) => {\n // Simple deterministic hash → 8-dim vector (migration validation only).\n return texts.map((t) => {\n const arr = new Array(8).fill(0);\n for (let i = 0; i < t.length; i += 1) {\n arr[i % 8] += t.charCodeAt(i);\n }\n return arr.map((x) => x / 1000);\n });\n },\n stats: () => ({ cacheHits: 0, cacheMisses: 0, httpCalls: 0, retries: 0 }),\n };\n\n mkdirSync(newPath, { recursive: true });\n log(`Writing Lance index to ${newPath} ...`);\n\n const lance = await LanceIndex.open({\n cwd,\n embedding: placeholderEmbedding,\n storagePath: newPath,\n });\n\n const batchSize = opts.batchSize ?? 100;\n for (let i = 0; i < sqliteFacts.length; i += batchSize) {\n const batch = sqliteFacts.slice(i, i + batchSize).map((f) => ({\n id: f.id,\n text: f.text,\n source: f.source,\n namespace: f.namespace ?? \"default\",\n scope: f.scope ?? \"agent\",\n user_id: f.user_id ?? \"default\",\n timestamp: 0,\n }));\n await lance.addFacts(batch);\n log(` Migrated ${Math.min(i + batchSize, sqliteFacts.length)}/${sqliteFacts.length}`);\n }\n\n // Validation: count + sample compare (10 random) with NFC normalization.\n const lanceCount = await lance.countFacts(\"default\");\n log(`Lance has ${lanceCount} facts (expected ${sqliteFacts.length}).`);\n\n const sampleSize = Math.min(10, sqliteFacts.length);\n const sampleComparisons: { id: string; match: boolean }[] = [];\n for (let i = 0; i < sampleSize; i += 1) {\n const sqliteFact = sqliteFacts[Math.floor((i * sqliteFacts.length) / sampleSize)];\n if (sqliteFact === undefined) continue;\n // Search Lance for this fact's text — best-effort round-trip.\n const hits = await lance.search(sqliteFact.text, {\n namespace: sqliteFact.namespace ?? \"default\",\n limit: 1,\n });\n // EC-3: compare with NFC normalization.\n const hit = hits[0];\n const match = hit !== undefined && nfcEqual(hit.text, sqliteFact.text);\n sampleComparisons.push({ id: sqliteFact.id, match });\n }\n\n const allMatch = sampleComparisons.every((c) => c.match);\n const countMatch = lanceCount === sqliteFacts.length;\n const validated = allMatch && countMatch;\n\n await lance.close();\n\n if (opts.dryRun === true) {\n log(\"Dry-run mode — discarding Lance staging dir.\");\n rmSync(newPath, { recursive: true, force: true });\n return {\n countSqlite: sqliteFacts.length,\n countLance: lanceCount,\n validated,\n sampleComparisons,\n lancePath: finalPath,\n committed: false,\n };\n }\n\n if (!validated) {\n log(\"Validation FAILED — leaving SQLite intact, removing Lance staging dir.\");\n rmSync(newPath, { recursive: true, force: true });\n return {\n countSqlite: sqliteFacts.length,\n countLance: lanceCount,\n validated: false,\n sampleComparisons,\n lancePath: finalPath,\n committed: false,\n };\n }\n\n // Atomic commit via rename.\n renameSync(newPath, finalPath);\n log(`Migration committed to ${finalPath}.`);\n return {\n countSqlite: sqliteFacts.length,\n countLance: lanceCount,\n validated: true,\n sampleComparisons,\n lancePath: finalPath,\n committed: true,\n };\n}\n","import { access, readFile, unlink } from \"node:fs/promises\";\nimport { legacyMemoryJsonPath, type MemoryConfig, type MemoryFact } from \"../memory-types.js\";\nimport { appendFactToMarkdown, memoryMdPath } from \"../store/markdown-store.js\";\n\n/**\n * One-shot legacy-JSON → markdown migration (ADR D8 of memory-system-peer-project-parity).\n *\n * Triggers when `.theokit/memory/<namespace>/<scope>-<userId>.json` exists AND\n * `.theokit/memory/MEMORY.md` does not. Reads the JSON facts, writes each\n * bullet to MEMORY.md, then deletes the JSON file. Idempotent.\n *\n * Iter 63 (Stage 3 source-move #20): hybrid copy from sdk-core's\n * `internal/memory/migration.ts`. sdk-core retains its copy for v1.x\n * legacy migration back-compat; sdk-memory ships the canonical copy.\n *\n * **Process-global migration flag map (`migrationRun`) is per-package.**\n * sdk-core's copy and sdk-memory's copy each maintain their own\n * `Set<string>` so the same key migrated through one package's copy\n * is NOT recorded in the other's. In v1.x active-memory-mode this\n * runs only via sdk-core; once sdk-core's runtime swaps to consume\n * sdk-memory's exports (later Stage 4), only sdk-memory's flag map\n * matters. Stage 3 source-move alone doesn't switch consumers.\n *\n * Dependency chain (sibling, all moved):\n * - `appendFactToMarkdown`, `memoryMdPath` → ./markdown-store.js (iter 56)\n * - `legacyMemoryJsonPath`, `MemoryConfig`, `MemoryFact` → ./memory-types.js (iter 52)\n *\n * @internal\n */\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function readLegacyFacts(jsonPath: string): Promise<MemoryFact[] | undefined> {\n try {\n const raw = await readFile(jsonPath, \"utf8\");\n const parsed = JSON.parse(raw) as { facts?: MemoryFact[] };\n return Array.isArray(parsed.facts) ? parsed.facts : [];\n } catch {\n return undefined;\n }\n}\n\nasync function writeMigratedFacts(\n cwd: string,\n jsonPath: string,\n facts: MemoryFact[],\n): Promise<MigrationResult> {\n try {\n for (const fact of facts) await appendFactToMarkdown(cwd, fact);\n await unlink(jsonPath).catch(() => undefined);\n process.stderr.write(\n `[theokit-sdk] migrated ${facts.length} fact(s) from ${jsonPath} to MEMORY.md\\n`,\n );\n return { migrated: true, factCount: facts.length };\n } catch (cause) {\n const message = cause instanceof Error ? cause.message : String(cause);\n process.stderr.write(`[theokit-sdk] memory migration failed (readonly fs?): ${message}\\n`);\n return { migrated: false, factCount: 0, reason: \"readonly-fs\" };\n }\n}\n\nconst migrationRun = new Set<string>();\n\n/**\n * Outcome of {@link migrateLegacyJson}. `reason` is present on every non-migrated\n * result and says which guard stopped it: `already-migrated` (this key was\n * attempted earlier in this process), `no-legacy-json` (nothing to migrate, or\n * the file could not be read or parsed), `markdown-exists` (both files present,\n * so neither was touched), `readonly-fs` (the write failed).\n */\nexport interface MigrationResult {\n migrated: boolean;\n factCount: number;\n reason?: \"already-migrated\" | \"no-legacy-json\" | \"markdown-exists\" | \"readonly-fs\";\n}\n\n/**\n * Move facts from the pre-markdown JSON store into `MEMORY.md`, once.\n *\n * It runs only when the legacy file exists and `MEMORY.md` does not. When both\n * exist it stops and leaves both alone — merging would need a conflict rule\n * nobody has picked, and losing hand-written notes is worse than skipping. On\n * success each fact is appended as a `## Facts` bullet and the JSON file is\n * deleted.\n *\n * Guarded by a per-process set keyed on cwd, namespace, scope and user id, so\n * the second call for the same key returns `already-migrated` without touching\n * disk — including after a genuine failure. That set is per module instance, so\n * a process that loads both this package's copy and the one inside\n * `@theokit/sdk` has two independent sets.\n *\n * Never throws: a JSON file that cannot be read or parsed reports\n * `no-legacy-json`, and a failed write reports `readonly-fs` after a warning on\n * stderr.\n */\nexport async function migrateLegacyJson(\n cwd: string,\n config: MemoryConfig,\n): Promise<MigrationResult> {\n const key = `${cwd}::${config.namespace ?? \"default\"}::${config.scope ?? \"agent\"}::${config.userId ?? \"default\"}`;\n if (migrationRun.has(key)) return { migrated: false, factCount: 0, reason: \"already-migrated\" };\n migrationRun.add(key);\n\n const jsonPath = legacyMemoryJsonPath(cwd, config);\n if (!(await fileExists(jsonPath))) {\n return { migrated: false, factCount: 0, reason: \"no-legacy-json\" };\n }\n if (await fileExists(memoryMdPath(cwd))) {\n process.stderr.write(\n `[theokit-sdk] memory migration skipped: both MEMORY.md and legacy JSON exist at ${jsonPath}; leaving both intact\\n`,\n );\n return { migrated: false, factCount: 0, reason: \"markdown-exists\" };\n }\n\n const facts = await readLegacyFacts(jsonPath);\n if (facts === undefined) return { migrated: false, factCount: 0, reason: \"no-legacy-json\" };\n return writeMigratedFacts(cwd, jsonPath, facts);\n}\n\n/** Test-only — reset the in-process migration flag map. */\nexport function resetMigrationStateForTests(): void {\n migrationRun.clear();\n}\n","import { readFile } from \"node:fs/promises\";\nimport { resolve as resolvePath } from \"node:path\";\n\n/**\n * **Iter 55 rollup-plugin-dts workaround** (mirrors iter 48/53 pattern).\n * The canonical sdk-core copy imports `MemoryReadResult` from\n * `../types.js`. In sdk-memory the same type lives in sibling\n * `./memory-types.js` (moved iter 52) but rollup-dts treeshakes it\n * out of the dist .d.ts because no PUBLIC type reaches it\n * transitively yet — `readMemoryFileBounded`'s return type would be\n * the consumer BUT rollup-dts processes the import resolution before\n * reader.ts itself becomes bundled into the public emit. Same class\n * of bug as iter 48 (MemorySearchHit) + iter 53 (MemoryChunk).\n *\n * Fix: declare a byte-identical mirror of MemoryReadResult inline.\n * When a future move (e.g. tools.ts wrapping readMemoryFileBounded\n * as a public LLM tool, or IndexManager surface emitting these)\n * gives MemoryReadResult a different publicly-reachable path, this\n * mirror MUST be deleted + the canonical import restored to maintain\n * single source of truth.\n *\n * @internal\n */\ninterface MemoryReadResult {\n path: string;\n /** Requested starting line (1-indexed, defaults to 1). */\n from: number;\n /** Number of lines actually returned (may be less than `lines` near EOF). */\n linesReturned: number;\n /** Total lines in the file (after the read). */\n totalLines: number;\n /** True when content remains after the returned slice, i.e. `remainingLines > 0`. */\n truncated: boolean;\n /** Lines past the returned slice that remain in the file. */\n remainingLines: number;\n /** Slice text (joined with `\\n`). */\n text: string;\n}\n\n/**\n * Bounded read with truncation info (ADR D5 — `memory_get` foundation).\n *\n * Mirrors peer-project's `buildMemoryReadResult` semantics:\n * - `from` is 1-indexed.\n * - `lines` defaults to 200 (`DEFAULT_MEMORY_READ_LINES`).\n * - Returns up to EOF when the requested slice extends past file end.\n * - Sets `truncated: true` whenever content remains past the returned slice,\n * whether or not the slice was shorter than requested. (At EOF, `false`.)\n *\n * Iter 55 (Stage 3 source-move #12): hybrid copy from sdk-core's\n * `internal/memory/storage/reader.ts`. sdk-core retains its copy for\n * v1.x `memory_get` back-compat; sdk-memory ships the canonical copy\n * that future `tools.ts` move (memory_get LLM tool wraps this) will\n * target as a sibling. `MemoryReadResult` comes from sibling\n * `./memory-types.js` (moved iter 52).\n *\n * @internal\n */\n\nexport const DEFAULT_MEMORY_READ_LINES = 200;\n\n/**\n * Inputs for {@link readMemoryFileBounded}. `relPath` is resolved against `cwd`,\n * and this function performs no containment check of its own — a `relPath`\n * containing `..` escapes. The `memory_get` tool validates containment before\n * calling in.\n *\n * `from` is 1-indexed and clamped to at least 1; `lines` defaults to 200 and is\n * clamped to at least 1.\n */\nexport interface ReadFileOptions {\n cwd: string;\n relPath: string;\n from?: number;\n lines?: number;\n}\n\n/**\n * Read a bounded slice of a text file and report what was left behind.\n *\n * A single trailing newline is not counted as a line, so `totalLines` matches\n * what an editor shows. `from` past the end of the file is not an error: it\n * returns an empty slice with `linesReturned: 0`.\n *\n * `truncated` means content remains after the returned slice — it is exactly\n * `remainingLines > 0`. It does not mean fewer lines were returned than\n * requested: a full 200-line slice of a 1000-line file is `truncated: true`,\n * and a short slice that reached the end is `truncated: false`.\n *\n * Rejects with the underlying filesystem error when the file cannot be read.\n */\nexport async function readMemoryFileBounded(opts: ReadFileOptions): Promise<MemoryReadResult> {\n const absolutePath = resolvePath(opts.cwd, opts.relPath);\n const raw = await readFile(absolutePath, \"utf8\");\n const allLines = raw.split(\"\\n\");\n // Strip a trailing empty line caused by a final \\n so totalLines reflects\n // the editor-visible line count, not the byte-level split.\n const trimmedLines =\n allLines.length > 0 && allLines[allLines.length - 1] === \"\" ? allLines.slice(0, -1) : allLines;\n const totalLines = trimmedLines.length;\n\n const requestedFrom = Math.max(1, opts.from ?? 1);\n const requestedLines = Math.max(1, opts.lines ?? DEFAULT_MEMORY_READ_LINES);\n const startIdx = requestedFrom - 1;\n const endIdx = Math.min(totalLines, startIdx + requestedLines);\n const slice = trimmedLines.slice(startIdx, endIdx);\n const linesReturned = slice.length;\n const remainingLines = Math.max(0, totalLines - endIdx);\n // truncated = \"more content exists past the returned slice\"\n const truncated = remainingLines > 0;\n\n return {\n path: opts.relPath,\n from: requestedFrom,\n linesReturned,\n totalLines,\n truncated,\n remainingLines,\n text: slice.join(\"\\n\"),\n };\n}\n","import { resolve as resolvePath } from \"node:path\";\n\nimport { ConfigurationError } from \"@theokit/sdk/errors\";\n\nimport type { MemorySearchHit } from \"./index/index-manager-contract.js\";\nimport type { MemoryIndex } from \"./index/memory-index.js\";\nimport { memoryDir } from \"./store/markdown-store.js\";\nimport { readMemoryFileBounded } from \"./store/reader.js\";\n\n/**\n * Memory tools (`memory_search` + `memory_get`) — ADR D5 of\n * memory-system-peer-project-parity. Tool schemas mirror peer-project\n * (`reference/peer-project/extensions/memory-core/src/tools.ts:228-475`).\n *\n * Each tool is exposed as a `MemoryTool` (name + description + JSON schema +\n * async execute). The agent-loop integration wires them via the existing\n * `ResolvedTool` interface in `tool-dispatch.ts`.\n *\n * Iter 64 (Stage 3 source-move #21): hybrid copy from sdk-core's\n * `internal/memory/tools.ts`. sdk-core retains its copy for v1.x\n * memory-tools back-compat; sdk-memory ships the canonical copy.\n * Dependency chain (all resolved):\n * - `@theokit/sdk/errors` for `ConfigurationError` (public)\n * - sibling `./index-manager-contract.js` for `MemorySearchHit`\n * (moved iter 47 — note: sdk-core copy imports from\n * `./index-manager.js`; sdk-memory uses the contract leaf\n * directly since the canonical type lives there)\n * - sibling `./memory-index.js` for `MemoryIndex` (moved iter 50)\n * - sibling `./markdown-store.js` for `memoryDir` (moved iter 56)\n * - sibling `./reader.js` for `readMemoryFileBounded` (moved iter 55)\n *\n * @internal\n */\n\nexport interface MemoryToolJson {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n}\n\n/**\n * A memory tool ready to hand to the agent loop: the JSON-serialisable\n * description an LLM sees, plus the `execute` that runs it. `execute` resolves\n * to a JSON string — the tool layer does no further encoding.\n */\nexport interface MemoryTool extends MemoryToolJson {\n execute(input: Record<string, unknown>): Promise<string>;\n}\n\nconst SEARCH_DESCRIPTION =\n \"Mandatory recall step: semantically search MEMORY.md + memory/notes/*.md (and optional wiki supplements) before answering questions about prior work, decisions, dates, people, preferences, or todos. `corpus=memory` (default) restricts to indexed memory files; `corpus=wiki` restricts to read-only wiki supplements; `corpus=all` returns both. Returns ranked `{ path, startLine, endLine, score, snippet, citation }` hits.\";\n\nconst GET_DESCRIPTION =\n \"Safe exact excerpt read from MEMORY.md or memory/notes/*.md. Defaults to a bounded excerpt (200 lines). Returns `{ path, from, linesReturned, totalLines, truncated, remainingLines, text }`. Paths are resolved against the memory root — attempts to read outside `.theokit/memory/` are rejected.\";\n\nconst MEMORY_SEARCH_SCHEMA: Record<string, unknown> = {\n type: \"object\",\n required: [\"query\"],\n properties: {\n query: { type: \"string\", description: \"Natural-language query.\" },\n maxResults: { type: \"integer\", minimum: 1, maximum: 50 },\n minScore: { type: \"number\", minimum: 0, maximum: 1 },\n corpus: { type: \"string\", enum: [\"memory\", \"sessions\", \"wiki\", \"all\"] },\n },\n additionalProperties: false,\n};\n\nconst MEMORY_GET_SCHEMA: Record<string, unknown> = {\n type: \"object\",\n required: [\"path\"],\n properties: {\n path: { type: \"string\", description: \"Path relative to .theokit/memory/\" },\n from: { type: \"integer\", minimum: 1 },\n lines: { type: \"integer\", minimum: 1, maximum: 2000 },\n },\n additionalProperties: false,\n};\n\nconst DEFAULT_MAX_TOTAL_CHARS = 16384;\n\n/** Options for {@link createMemorySearchTool}. */\nexport interface MemorySearchToolOptions {\n index: MemoryIndex;\n /** Cap on the JSON response size (EC-10 of edge-case review). Default 16384. */\n maxTotalChars?: number;\n}\n\n/**\n * Build the `memory_search` tool over an index that is already open. The tool\n * never opens or syncs anything: if `index.sync()` has not run, the search runs\n * against whatever the index last recorded, and a freshly created index returns\n * no hits.\n *\n * The tool accepts `query` (required), `maxResults` (default 10), `minScore`,\n * and `corpus`, where `corpus` maps to the index's source filter: `memory`,\n * `sessions`, `wiki`, or `all` (the default, which applies no filter). An\n * unrecognised `corpus` value is treated as `all` rather than rejected.\n *\n * `execute` returns `{\"hits\": [...], \"truncated\": bool}`. Hits are dropped from\n * the tail once their estimated size would exceed `maxTotalChars`, except that\n * the first hit is always kept even when it alone exceeds the cap.\n *\n * Use this for recall by meaning across the whole corpus, and\n * {@link createMemoryGetTool} when the model already knows the file and wants\n * exact lines.\n */\nexport function createMemorySearchTool(opts: MemorySearchToolOptions): MemoryTool {\n const cap = opts.maxTotalChars ?? DEFAULT_MAX_TOTAL_CHARS;\n return {\n name: \"memory_search\",\n description: SEARCH_DESCRIPTION,\n inputSchema: MEMORY_SEARCH_SCHEMA,\n async execute(input: Record<string, unknown>): Promise<string> {\n const query = readString(input.query, \"query is required\");\n const maxResults = readNumber(input.maxResults) ?? 10;\n const minScore = readNumber(input.minScore);\n const corpus = readString(input.corpus, undefined, true);\n const sources = mapCorpusToSources(corpus);\n const searchOptions = {\n maxResults,\n ...(minScore !== undefined ? { minScore } : {}),\n ...(sources !== undefined ? { sources } : {}),\n };\n const hits = await opts.index.search(query, searchOptions);\n return JSON.stringify(capByTotalChars(hits, cap));\n },\n };\n}\n\n/** Options for {@link createMemoryGetTool}. `cwd` is the workspace root, not the memory directory. */\nexport interface MemoryGetToolOptions {\n cwd: string;\n}\n\n/**\n * Build the `memory_get` tool, which reads an exact excerpt from a file under\n * `<cwd>/.theokit/memory`. Needs no index and no embedding runtime — it is\n * plain file reading, so it works in a workspace where search is not configured.\n *\n * The tool accepts `path` (required, relative to the memory root), `from`\n * (1-indexed, default 1) and `lines` (default 200). A `path` whose resolved\n * location falls outside the memory root is rejected with a\n * `ConfigurationError` carrying the code `memory_path_escapes_root`. A path that\n * stays inside but does not exist is not caught here: the underlying read\n * rejects with the filesystem error.\n */\nexport function createMemoryGetTool(opts: MemoryGetToolOptions): MemoryTool {\n const memoryRoot = resolvePath(memoryDir(opts.cwd));\n return {\n name: \"memory_get\",\n description: GET_DESCRIPTION,\n inputSchema: MEMORY_GET_SCHEMA,\n async execute(input: Record<string, unknown>): Promise<string> {\n const relPath = readString(input.path, \"path is required\");\n const from = readNumber(input.from);\n const lines = readNumber(input.lines);\n // EC-2: enforce that the resolved path stays inside the memory root.\n const resolved = resolvePath(memoryRoot, relPath);\n if (!isPathInside(memoryRoot, resolved)) {\n throw new ConfigurationError(\n `memory_get rejected path that escapes memory root: ${relPath}`,\n { code: \"memory_path_escapes_root\" },\n );\n }\n const readArgs: { cwd: string; relPath: string; from?: number; lines?: number } = {\n cwd: memoryRoot,\n relPath,\n };\n if (from !== undefined) readArgs.from = from;\n if (lines !== undefined) readArgs.lines = lines;\n const result = await readMemoryFileBounded(readArgs);\n return JSON.stringify(result);\n },\n };\n}\n\n// ───── helpers ──────────────────────────────────────────────────────────\n\nfunction readString(value: unknown, errorIfMissing?: string, allowUndefined = false): string {\n if (typeof value === \"string\") return value;\n if (allowUndefined && (value === undefined || value === null)) return \"\";\n if (errorIfMissing !== undefined) {\n throw new ConfigurationError(errorIfMissing, { code: \"memory_tool_bad_args\" });\n }\n return \"\";\n}\n\nfunction readNumber(value: unknown): number | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value === \"string\" && value.trim().length > 0) {\n const n = Number(value);\n if (Number.isFinite(n)) return n;\n }\n return undefined;\n}\n\nfunction mapCorpusToSources(\n corpus: string,\n): ReadonlyArray<\"memory\" | \"sessions\" | \"wiki\"> | undefined {\n if (corpus === \"\" || corpus === \"all\") return undefined;\n if (corpus === \"memory\") return [\"memory\"];\n if (corpus === \"wiki\") return [\"wiki\"];\n if (corpus === \"sessions\") return [\"sessions\"];\n return undefined;\n}\n\nfunction capByTotalChars(\n hits: ReadonlyArray<MemorySearchHit>,\n maxTotalChars: number,\n): { hits: MemorySearchHit[]; truncated: boolean } {\n if (hits.length === 0) return { hits: [], truncated: false };\n const kept: MemorySearchHit[] = [];\n let runningChars = 0;\n for (const hit of hits) {\n const snippetLen = hit.snippet.length + (hit.citation?.length ?? 0) + 32; // overhead estimate\n if (kept.length > 0 && runningChars + snippetLen > maxTotalChars) {\n return { hits: kept, truncated: true };\n }\n kept.push(hit);\n runningChars += snippetLen;\n }\n return { hits: kept, truncated: false };\n}\n\nfunction isPathInside(root: string, candidate: string): boolean {\n const normalizedRoot = root.endsWith(\"/\") ? root : `${root}/`;\n return candidate === root || candidate.startsWith(normalizedRoot);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/in-memory-provider.ts","../src/internal/store/markdown-store.ts","../src/internal/active-memory/active-memory.ts","../src/internal/circuit-breaker.ts","../src/internal/active-memory/active-memory-cache.ts","../src/internal/embedding/azure-openai-embedding.ts","../src/internal/embedding/cohere-embedding.ts","../src/internal/embedding/deepinfra-embedding.ts","../src/internal/embedding/gemini-embedding.ts","../src/internal/embedding/jina-embedding.ts","../src/internal/embedding/mistral-embedding.ts","../src/internal/embedding/ollama-embedding.ts","../src/internal/embedding/openai-embedding.ts","../src/internal/embedding/openrouter-embedding.ts","../src/internal/embedding/voyage-embedding.ts","../src/internal/adapter-catalog.ts","../src/internal/memory-types.ts","../src/internal/adapter-http-error.ts","../src/internal/categorized-memory.ts","../src/internal/dreaming/dreaming-phases.ts","../src/internal/dreaming/dreaming-run.ts","../src/internal/index/index-schema.ts","../src/internal/index/index-db.ts","../src/internal/store/chunk-markdown.ts","../src/internal/index/lance-index.ts","../src/internal/index/memory-index.ts","../src/internal/index/lance-memory-adapter.ts","../src/internal/index/index-manager-dispatch.ts","../src/internal/index/sqlite-vec-loader.ts","../src/internal/index/vec-index.ts","../src/internal/index/index-manager.ts","../src/internal/index/migrate-sqlite-to-lance.ts","../src/internal/index/migration.ts","../src/internal/store/reader.ts","../src/internal/tools.ts"],"names":["sessionsDir","readdir","join","finalized","resolveMemoryRoot","DIMENSION_BY_MODEL","Security","resolvePath","ConfigurationError","safePathJoin","sanitizeIdentifier","mkdir","replaceFileAtomic","readFile","kept","withCwdMutex","notesDir","createHash","existsSync","mkdirSync"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * `createInMemoryMarkdownProvider` — first concrete `MemoryProvider`\n * impl shipped in `@theokit/sdk-memory` (SDK 2.0 Phase 1 / T1.6).\n *\n * Goal: prove the contract works end-to-end with a real (non-no-op)\n * impl WITHOUT pulling LanceDB / embedding / circuit-breaker infrastructure.\n * That richer impl lands in subsequent iters.\n *\n * Semantics:\n * - Stores recalled facts in a per-agent in-process Map.\n * - `runActivePass()` returns the facts plus a `systemPromptAdditions`\n * string that joins fact contents with newlines (so the LLM sees\n * them in the system slot).\n * - `buildTools()` surfaces a `memory_remember(content)` tool the LLM\n * can call to persist a fact mid-conversation.\n * - `recordSessionSummary()` writes a markdown summary to\n * `${cwd}/.theokit/memory/sessions/${runId}.md` (real disk write\n * via `@theokit/sdk/persistence` per ADR-008).\n * - `dispose()` clears the handle's per-agent map (releases memory).\n *\n * @public\n */\n\nimport { mkdir, readdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type {\n ActiveMemoryPassArgs,\n ActiveMemoryPassResult,\n CustomTool,\n MemoryAdapter,\n MemoryAdapterCapabilities,\n MemoryContext,\n MemoryFact,\n MemoryId,\n MemoryProvider,\n MemoryProviderHandle,\n MemoryProviderInitOptions,\n MemoryTurnMessage,\n RecordSessionSummaryArgs,\n SDKAgent,\n} from \"@theokit/sdk\";\nimport { Security } from \"@theokit/sdk\";\nimport { replaceFileAtomic } from \"@theokit/sdk/persistence\";\n\n/** Adapter id prefix — namespaces minted MemoryIds so cross-adapter delete is safe (EC-B). */\nconst ADAPTER_ID = \"in-memory-md\";\n\n/** Per-agent state holder. Stored on the handle via the opaque symbol slot. */\ninterface InMemoryHandleState {\n readonly facts: Map<string, MemoryFact>;\n readonly counter: { next: number };\n /**\n * Workspace cwd captured at `init()` time. Used by `runActivePass()`\n * to read previously-written session summaries from disk for recall\n * (iter 34 — closes the \"write but never read\" gap from iter 33).\n */\n readonly cwd: string;\n /**\n * `sessions: true` capability is set when cwd is available (always),\n * so future Stage 3 work can mark this provider as the canonical\n * sessions-recall path (vs. the no-op default).\n */\n}\n\nconst INTERNAL_STATE = Symbol(\"sdk-memory.in-memory.state\");\n\nfunction buildCapabilities(): MemoryAdapterCapabilities {\n return {\n history: false,\n sessions: false,\n tenancy: false,\n reasoning: false,\n toolSchemas: false,\n prefetch: false,\n };\n}\n\nfunction buildAdapter(state: InMemoryHandleState): MemoryAdapter {\n return {\n id: ADAPTER_ID,\n capabilities: buildCapabilities(),\n isAvailable(): boolean {\n return true;\n },\n async write(content: string | MemoryTurnMessage[], _ctx: MemoryContext): Promise<MemoryId> {\n const text = typeof content === \"string\" ? content : content.map((m) => m.content).join(\"\\n\");\n // Iter 43: redact secrets before persisting. Same posture as\n // memory_remember tool handler — secret-containing payloads\n // submitted to MemoryAdapter.write directly should never\n // surface verbatim in subsequent recall.\n const safeText = Security.redact(text);\n const id = `${ADAPTER_ID}:${state.counter.next++}` as MemoryId;\n state.facts.set(id, {\n id,\n content: safeText,\n createdAt: new Date().toISOString(),\n });\n return id;\n },\n async recall(_query: string, _ctx: MemoryContext, k?: number): Promise<MemoryFact[]> {\n // Naive recall — return everything (cap at k). Real impls in\n // subsequent iters add semantic similarity via embeddings.\n const all = Array.from(state.facts.values());\n const limit = k !== undefined && k >= 0 ? k : all.length;\n return all.slice(0, limit);\n },\n async delete(id: MemoryId): Promise<void> {\n if (!String(id).startsWith(`${ADAPTER_ID}:`)) {\n throw new Error(\n `MemoryAdapter.delete: id \"${String(id)}\" was not minted by adapter \"${ADAPTER_ID}\"`,\n );\n }\n state.facts.delete(id);\n },\n };\n}\n\n/** Truncate session-summary text fields to bound disk size. */\nconst MAX_SUMMARY_TURN_CHARS = 2000;\n\nfunction truncate(text: string): string {\n if (text.length <= MAX_SUMMARY_TURN_CHARS) return text;\n return `${text.slice(0, MAX_SUMMARY_TURN_CHARS)}…`;\n}\n\n/**\n * Sanitize a runId for use as a filename. Strip path separators +\n * traversal patterns; keep `[a-zA-Z0-9_-]`; cap at 128 chars.\n * Mirrors sdk-core's legacy `writeSessionSummary` sanitizer so the\n * file-path semantics are identical across paths.\n */\nfunction sanitizeRunId(runId: string): string {\n return runId.replace(/[^a-zA-Z0-9_-]/g, \"_\").slice(0, 128);\n}\n\n/** Render the session-summary markdown body. */\nfunction renderSessionSummaryMarkdown(args: RecordSessionSummaryArgs): string {\n const iso = new Date(args.at).toISOString();\n // Iter 42: redact secrets from User + Assistant text via the public\n // `Security.redact()` API (sdk-core's ADR D68 canonical redactor —\n // 12 built-in patterns: OpenAI, Anthropic, GitHub PAT, AWS, etc.).\n // Mirrors sdk-core's legacy writeSessionSummary behavior so the\n // disk artefact never leaks API keys typed by the user.\n const safeUser = Security.redact(truncate(args.userText));\n const safeAssistant = Security.redact(truncate(args.assistantText));\n return [\n \"---\",\n `runId: ${args.runId}`,\n `agentId: ${args.agentId}`,\n `at: ${iso}`,\n `status: ${args.status}`,\n \"---\",\n \"\",\n \"## User\",\n \"\",\n safeUser,\n \"\",\n \"## Assistant\",\n \"\",\n safeAssistant,\n \"\",\n ].join(\"\\n\");\n}\n\n/**\n * Extract `agentId:` value from a session-summary YAML frontmatter.\n * Returns undefined when the file is malformed or has no agentId.\n *\n * The frontmatter shape is:\n * ---\n * runId: ...\n * agentId: ...\n * ...\n * ---\n *\n * Parsing is intentionally simple (regex line-match) — full YAML parse\n * is overkill for the 5-field frontmatter we emit. A malformed file\n * shows up as undefined → falls out of the optional agentId filter.\n */\nfunction extractAgentIdFromFrontmatter(content: string): string | undefined {\n // Match `agentId: <value>` within the leading frontmatter block.\n const match = content.match(/^agentId:\\s*(.+)$/m);\n if (match === null || match[1] === undefined) return undefined;\n return match[1].trim();\n}\n\n/**\n * Read previously-written session summaries from disk + substring-\n * match against the user message. Best-effort: errors degrade to\n * empty recall (no throw — matches the non-throwing-on-hot-path\n * contract).\n *\n * Iter 34: this is the SUBSTRING-match version. Future iters can\n * upgrade to embedding-based semantic similarity (LanceDB ANN)\n * without changing the public surface.\n *\n * Cap: returns at most 5 hits to bound the systemPromptAdditions size.\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: session recall has branching on multiple storage modes\nasync function recallSessionSummaries(\n cwd: string,\n userMessage: string,\n agentIdFilter?: string,\n): Promise<ReadonlyArray<MemoryFact>> {\n const RECALL_CAP = 5;\n const sessionsDir = join(cwd, \".theokit\", \"memory\", \"sessions\");\n let files: string[];\n try {\n files = await readdir(sessionsDir);\n } catch {\n return [];\n }\n const query = userMessage.toLowerCase().trim();\n if (query.length === 0) return [];\n const hits: MemoryFact[] = [];\n for (const file of files) {\n if (!file.endsWith(\".md\")) continue;\n if (hits.length >= RECALL_CAP) break;\n const filePath = join(sessionsDir, file);\n let content: string;\n try {\n content = await readFile(filePath, \"utf-8\");\n } catch {\n continue;\n }\n // Iter 36: agentId scope filter. When set, skip summaries whose\n // frontmatter `agentId:` field doesn't match. Prevents cross-agent\n // data leakage in multi-agent setups.\n if (agentIdFilter !== undefined) {\n const fileAgentId = extractAgentIdFromFrontmatter(content);\n if (fileAgentId !== agentIdFilter) continue;\n }\n if (content.toLowerCase().includes(query)) {\n // Extract a short snippet — the User section (first 200 chars).\n const userIdx = content.indexOf(\"## User\");\n const snippet =\n userIdx >= 0 ? content.slice(userIdx, userIdx + 200).replace(/\\s+/g, \" \") : file;\n const id = `${ADAPTER_ID}:session:${file}` as MemoryId;\n hits.push({\n id,\n content: snippet,\n score: 0.5, // substring-match has no real score; placeholder\n });\n }\n }\n return hits;\n}\n\n/**\n * Build the LLM-facing `memory_search` tool (iter 35). The LLM calls\n * this when the user asks about something it might have learned in a\n * previous session. Queries the disk-backed sessions corpus via the\n * same `recallSessionSummaries` helper used by `runActivePass`.\n */\nfunction buildMemorySearchTool(state: InMemoryHandleState): CustomTool {\n return {\n name: \"memory_search\",\n description:\n \"Search past session summaries for content related to a query. Use when the user asks about something they mentioned in a previous conversation. Returns up to 5 short snippets.\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: {\n type: \"string\",\n description: \"What to search for (a topic, fact, or keyword).\",\n },\n },\n required: [\"query\"],\n additionalProperties: false,\n },\n handler: async (input: Record<string, unknown>): Promise<string> => {\n const query = typeof input.query === \"string\" ? input.query : \"\";\n if (query.length === 0) {\n return JSON.stringify({ ok: false, results: [], error: \"empty query\" });\n }\n const hits = await recallSessionSummaries(state.cwd, query);\n return JSON.stringify({\n ok: true,\n count: hits.length,\n results: hits.map((h) => ({ id: String(h.id), snippet: h.content })),\n });\n },\n };\n}\n\nfunction buildMemoryRememberTool(state: InMemoryHandleState): CustomTool {\n return {\n name: \"memory_remember\",\n description:\n \"Persist a short fact about the user/conversation to memory so it can be recalled in future turns. Pass a single concise sentence as `content`.\",\n inputSchema: {\n type: \"object\",\n properties: {\n content: { type: \"string\", description: \"The fact to remember (one sentence).\" },\n },\n required: [\"content\"],\n additionalProperties: false,\n },\n handler: async (input: Record<string, unknown>): Promise<string> => {\n const content = typeof input.content === \"string\" ? input.content : \"\";\n if (content.length === 0) {\n return JSON.stringify({ ok: false, error: \"empty content\" });\n }\n // Iter 43: redact secrets from the LLM-supplied content BEFORE\n // storing in the Map. The LLM may quote a key from the user\n // verbatim (e.g., \"user said their key is sk-proj-...\"); without\n // this, that secret would persist + leak into systemPromptAdditions\n // on subsequent runActivePass calls. Mirrors the iter 42\n // recordSessionSummary redaction posture.\n const safeContent = Security.redact(content);\n const id = `${ADAPTER_ID}:${state.counter.next++}` as MemoryId;\n state.facts.set(id, {\n id,\n content: safeContent,\n createdAt: new Date().toISOString(),\n });\n return JSON.stringify({ ok: true, id });\n },\n };\n}\n\n/**\n * Build a fresh `MemoryProvider` whose facts live in-process. The\n * returned provider is independent — call `createInMemoryMarkdownProvider()`\n * per agent OR share across agents (each `init()` gets its own state).\n *\n * Iter 33: `recordSessionSummary()` writes session-summary markdown\n * files to disk under `${cwd}/.theokit/memory/sessions/`.\n * Iter 34: `runActivePass()` reads back those summaries + substring-\n * matches against the user message for genuine cross-session recall.\n *\n * Future LanceDB-backed impl will replace the substring match with\n * semantic-similarity ANN over embedding vectors.\n */\nexport function createInMemoryMarkdownProvider(): MemoryProvider {\n return {\n async init(opts: MemoryProviderInitOptions): Promise<MemoryProviderHandle> {\n const state: InMemoryHandleState = {\n facts: new Map(),\n counter: { next: 0 },\n cwd: opts.cwd,\n };\n const adapter = buildAdapter(state);\n return {\n adapter,\n [INTERNAL_STATE]: state,\n };\n },\n buildTools(handle: MemoryProviderHandle, _agent: SDKAgent): ReadonlyArray<CustomTool> {\n const state = handle[INTERNAL_STATE] as InMemoryHandleState | undefined;\n if (state === undefined) return [];\n return [buildMemoryRememberTool(state), buildMemorySearchTool(state)];\n },\n async runActivePass(\n handle: MemoryProviderHandle,\n args: ActiveMemoryPassArgs,\n ): Promise<ActiveMemoryPassResult> {\n const state = handle[INTERNAL_STATE] as InMemoryHandleState | undefined;\n if (state === undefined) return { facts: [] };\n // (1) In-process facts (from memory_remember tool calls this turn).\n const inProcessFacts = Array.from(state.facts.values());\n // (2) Persisted session-summary recall — iter 34. Read previously-\n // written summaries from disk + substring-match against the user\n // message. Best-effort: read errors degrade to empty recall.\n //\n // Iter 36: scope the disk recall to args.agentId so a session\n // summary written by agent-A never bleeds into agent-B's recall.\n // This is the multi-agent privacy invariant.\n const persistedHits = await recallSessionSummaries(state.cwd, args.userMessage, args.agentId);\n const allFacts = [...inProcessFacts, ...persistedHits];\n if (allFacts.length === 0) return { facts: [] };\n const systemPromptAdditions = [\n \"Known facts about the user/session (recall):\",\n ...allFacts.map((f) => `- ${f.content}`),\n ].join(\"\\n\");\n return { facts: allFacts, systemPromptAdditions };\n },\n sync(_handle: MemoryProviderHandle): void {\n // No-op for the in-memory impl — facts are written synchronously to\n // the Map at handler-call time; nothing to re-index post-run. Future\n // LanceDB-backed impl will fire IndexManager.sync() here.\n return;\n },\n async recordSessionSummary(args: RecordSessionSummaryArgs): Promise<void> {\n // Real filesystem write via `@theokit/sdk/persistence`'s\n // `replaceFileAtomic`. ADR-008 sub-path resolution guarantees the\n // same process-level write lock as sdk-core's legacy\n // `writeSessionSummary`. Future LanceDB-backed impl additionally\n // triggers IndexManager re-sync after the write.\n if (args.status !== \"finished\") return;\n const sessionsPath = join(args.cwd, \".theokit\", \"memory\", \"sessions\");\n const filePath = join(sessionsPath, `${sanitizeRunId(args.runId)}.md`);\n await mkdir(sessionsPath, { recursive: true });\n const body = renderSessionSummaryMarkdown(args);\n await replaceFileAtomic(filePath, body);\n },\n dispose(handle: MemoryProviderHandle): void {\n const state = handle[INTERNAL_STATE] as InMemoryHandleState | undefined;\n if (state === undefined) return;\n state.facts.clear();\n },\n };\n}\n","import { readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { notesDir, resolveMemoryRoot } from \"@theokit/sdk/internal/memory-store\";\n\n/**\n * Markdown-first memory storage — re-exported from `@theokit/sdk`, not reimplemented here.\n *\n * This file used to be a full copy (iter 56, Stage 3 source-move #13). The copy went stale: `#389`\n * moved the layout from bullets under `MEMORY.md ## Facts` to a file per memory, and the\n * Claude Code compatibility work added two more read roots — both landed in the SDK's copy and\n * neither in this one. Because `Memory.runDreamingSweep` routes through this package whenever it is\n * installed, **the copy that ran was not the copy anyone had updated**: installing\n * `@theokit/sdk-memory` made every memory the SDK had written unreadable, reported as\n * `factsBefore: 0` — a number that reads exactly like an empty store (#430).\n *\n * theokit#160 fixed the identical shape for the embedding runtime, in this same package pair, by\n * importing one implementation instead of syncing two. Same remedy here. Re-syncing the copy would\n * have fixed today's divergence and left tomorrow's free to happen.\n *\n * The re-exported signatures are supersets of what this package used to expose — the added\n * parameters are optional — so nothing that called them before has to change.\n *\n * @internal\n */\nexport {\n appendFact,\n appendFactToMarkdown,\n asMemoryRoot,\n claudeProjectMemoryDir,\n collectMarkdownFiles,\n type DiscoveredFile,\n defaultIndexPath,\n indexBudgetWarning,\n lanceStoragePath,\n MEMORY_INDEX_MAX_BYTES,\n MEMORY_INDEX_MAX_LINES,\n type MemoryLocationConfig,\n type MemoryRoot,\n memoryMdPath,\n memoryReadRoots,\n notesDir,\n projectMemoryDir,\n readAllSqliteFacts,\n readFacts,\n readFactsFromMarkdown,\n resolveMemoryRoot,\n type SqliteFactRow,\n} from \"@theokit/sdk/internal/memory-store\";\n\n/** One note discovered under `notes/`: its file name without the `.md` suffix, and its absolute path. */\nexport interface NoteFile {\n slug: string;\n path: string;\n}\n\n/**\n * List the `.md` files directly under `notes/`. Returns `[]` when the directory does not exist, so\n * a workspace that has never written a note is not an error. Does not recurse into sub-directories.\n *\n * Stays here rather than moving to the shared store: notes are this package's concept, and only\n * this package reads them.\n */\nexport async function listNotes(cwd: string): Promise<NoteFile[]> {\n let entries: string[] = [];\n try {\n entries = await readdir(notesDir(resolveMemoryRoot(cwd)));\n } catch {\n return [];\n }\n return entries\n .filter((name) => name.endsWith(\".md\"))\n .map((name) => ({\n slug: name.replace(/\\.md$/, \"\"),\n path: join(notesDir(resolveMemoryRoot(cwd)), name),\n }));\n}\n","/**\n * Active Memory blocking recall (ADR D6 of memory-system-peer-project-parity).\n *\n * Runs BEFORE `agent.send()` assembles the system prompt. Issues a direct\n * call to `IndexManager.search` with the user message (and optional recent\n * turns per `queryMode`).\n *\n * Returns a `summary` string capped at `maxSummaryChars` (default 220 to\n * match peer-project's `DEFAULT_MAX_SUMMARY_CHARS`) which the system-prompt\n * pipeline prepends as a `<active-memory>` block (priority 5).\n *\n * Iter 75 (Stage 3 source-move #38, FINAL move): hybrid copy from\n * sdk-core's `internal/memory/active-memory.ts`. sdk-core retains its\n * copy as the v1.x runtime that `Memory` class delegates to;\n * sdk-memory ships the canonical copy that future Stage 4 port-based\n * composition will consume.\n *\n * **CLOSES the Stage 3 source-move stage in sdk-memory.** Every\n * memory-related concept under sdk-core's internal/memory/ is now\n * canonical in @theokit/sdk-memory (38 source files moved across\n * iter 44-75; 2 inlined adapters added: adapter-http-error iter 73\n * + adapter-catalog renamed iter 74).\n *\n * **Cross-package telemetry contract:** `OTelSpan` and `TelemetryHandle`\n * are now imported from `@theokit/sdk`, which exports them since #295.\n * This file previously inlined structural mirrors of both, with a note\n * that they MUST be replaced once sdk-core made them public — and by\n * the time anyone looked, the mirrors had drifted: they narrowed\n * `setAttributes` to reject the `undefined` values the canonical type\n * accepts, and declared `end()` without its `endTime` parameter. That\n * is how a structural mirror fails: quietly, with both sides compiling.\n *\n * The 2 constant strings (`memory.recall` span name +\n * `theokit_memory_recall_duration_ms` histogram name) are still inlined\n * below, because sdk-core's `span-names.ts` remains private. They are\n * values rather than types, so exporting them is a separate decision\n * with a real bundle cost — unlike these two, which erase at build time.\n *\n * @internal\n */\n\nimport type { OTelSpan, TelemetryHandle } from \"@theokit/sdk\";\n\nimport type { CircuitBreaker } from \"../circuit-breaker.js\";\nimport type { MemorySearchHit } from \"../index/index-manager-contract.js\";\nimport type { MemoryIndex } from \"../index/memory-index.js\";\nimport { resolveMemoryRoot } from \"../store/markdown-store.js\";\nimport { persistActiveMemoryTranscript } from \"../store/transcript-store.js\";\nimport type { ActiveMemoryCache, TenantContext } from \"./active-memory-cache.js\";\n// T4.1 / D438 — `ActiveMemoryResult` and its helpers moved to `./active-memory-types.ts`\n// so `./active-memory-cache.ts` can reach them without cycling back here (cycle #10).\n// Re-exported below for back-compat with in-tree consumers.\nimport type {\n ActiveMemoryQueryMode,\n ActiveMemoryResult,\n ActiveMemoryStatus,\n} from \"./active-memory-types.js\";\n\nexport type { ActiveMemoryQueryMode, ActiveMemoryResult, ActiveMemoryStatus };\n\n// Iter 75 inlined constants — sdk-core's telemetry/span-names.ts is\n// not public. These two are the only ones this file uses.\nconst SPAN_MEMORY_RECALL = \"memory.recall\";\nconst HISTOGRAM_MEMORY_RECALL_DURATION_MS = \"theokit_memory_recall_duration_ms\";\n\n// #295 — the canonical types, not a copy of them.\n//\n// Iter 75 inlined structural mirrors here because sdk-core's telemetry/tracer.ts\n// was not public, with a note that they MUST be replaced once it was. They had\n// already drifted by the time anyone checked: the mirror narrowed `setAttributes`\n// to reject the `undefined` values the canonical type accepts, and declared\n// `end()` without the `endTime` parameter. Neither broke a build — a structural\n// mirror fails by being quietly wrong, not by being loudly missing.\n//\n// `@theokit/sdk` is already a peerDependency of this package, and both types are\n// erased at build time, so this costs nothing at runtime.\n\n/**\n * Tuning for one recall attempt. Recall is off unless `enabled` is exactly\n * `true`, so an options object that omits it disables recall rather than\n * enabling it with defaults.\n */\nexport interface ActiveMemoryOptions {\n /** Whether active recall is enabled. Default `false`. */\n enabled?: boolean;\n /** Query construction strategy. Default `\"recent\"`. */\n queryMode?: ActiveMemoryQueryMode;\n /** Hard timeout in ms. Default `15000`. */\n timeoutMs?: number;\n /** Max chars in the summary. Default `220`. */\n maxSummaryChars?: number;\n /** Number of recent user turns to include in `queryMode === \"recent\"`. Default `2`. */\n recentUserTurns?: number;\n}\n\n/**\n * Everything {@link runActiveMemory} needs for one attempt. Only `userText`,\n * `priorMessages`, `index` and `options` are required; the rest add breaker,\n * cache, transcript persistence and telemetry, each of which is inert when\n * omitted.\n *\n * `index` is accepted as `undefined` on purpose — an agent with memory\n * configured but no index open is a normal state, and it produces a `skipped`\n * result rather than an error.\n */\nexport interface RunActiveMemoryArgs {\n userText: string;\n priorMessages: ReadonlyArray<{ role: \"user\" | \"assistant\"; text: string }>;\n index: MemoryIndex | undefined;\n options: ActiveMemoryOptions;\n /** Per-agent circuit breaker (Phase 8). */\n breaker?: CircuitBreaker;\n /** Per-agent result cache (Phase 8). */\n cache?: ActiveMemoryCache;\n /** Workspace root for transcript persistence. */\n cwd?: string;\n /** When true, write transcript JSON under .theokit/memory/transcripts/active-memory/. */\n persistTranscripts?: boolean;\n /** Stable key the breaker + cache key by (default `default`). */\n agentKey?: string;\n /** Run id for transcript file naming. */\n runId?: string;\n /**\n * T0.1 — optional telemetry handle. When provided AND telemetry is enabled,\n * `memory.recall` span is emitted with `{ userId, namespace, scope, queryMode,\n * hits, status }` attrs and `theokit_memory_recall_duration_ms` histogram is\n * recorded with the same dimension keys.\n */\n telemetry?: TelemetryHandle;\n /** User id surfaced as a memory.recall span attr for cross-tenant tracing. */\n userId?: string;\n /** Memory namespace (e.g. `default`, `<orgId>`) for span/histogram dimensions. */\n namespace?: string;\n /** Memory scope (`session` / `user` / `global`) for span/histogram dimensions. */\n scope?: string;\n}\n\nconst DEFAULTS: Required<Omit<ActiveMemoryOptions, \"enabled\">> = {\n queryMode: \"recent\",\n timeoutMs: 15000,\n maxSummaryChars: 220,\n recentUserTurns: 2,\n};\n\n/**\n * Run one blocking recall before the system prompt is assembled, and report what\n * happened. Never throws for a recall failure: a search that times out or\n * rejects comes back as a `timeout` or `error` status with no summary, and the\n * agent run continues without memory.\n *\n * The order of the short-circuits decides what a caller sees. Recall disabled or\n * no index gives `skipped` with no search. An open circuit breaker gives\n * `skipped` too. A cache hit returns the earlier result as-is, which means it\n * also returns that result's `status` and `durationMs` — a cached `no-recall`\n * looks exactly like a fresh one. An empty query gives `no-recall`.\n *\n * Only a real search reaches the breaker: `timeout` records a timeout, `ok` and\n * `no-recall` record a success, and `error` records neither, so a provider that\n * keeps throwing will not trip the breaker.\n *\n * `timeoutMs` bounds how long this waits, not how long the search runs — the\n * underlying `index.search` is left running when the timer wins. The search asks\n * the index for at most 5 hits regardless of options.\n *\n * Cache entries are keyed by tenant as well as by query text, so two callers\n * with the same question and different `userId` / `namespace` / `scope` never\n * share an entry.\n */\nexport async function runActiveMemory(args: RunActiveMemoryArgs): Promise<ActiveMemoryResult> {\n const started = Date.now();\n // T0.1 — `memory.recall` span emitted around the entire body so skipped /\n // cached / no-recall paths still surface in telemetry with the correct status.\n const span = startMemoryRecallSpan(args);\n try {\n if (args.options.enabled !== true || args.index === undefined) {\n return endRecallSpan(span, args, {\n summary: undefined,\n durationMs: 0,\n status: \"skipped\",\n hits: [],\n });\n }\n const cfg = { ...DEFAULTS, ...args.options };\n const breakerKey = args.agentKey ?? \"default\";\n if (args.breaker?.shouldSkip(breakerKey) === true) {\n return endRecallSpan(span, args, {\n summary: undefined,\n durationMs: 0,\n status: \"skipped\",\n hits: [],\n });\n }\n // #56 (GAP-B) — key the cache read by tenant identity so two callers with\n // the same query text but different identity never share a cache entry.\n const tenantCtx: TenantContext = {\n namespace: args.namespace,\n userId: args.userId,\n scope: args.scope,\n };\n const cached = args.cache?.get(args.userText, cfg.queryMode, tenantCtx);\n if (cached !== undefined) return endRecallSpan(span, args, cached);\n\n const query = buildQuery(args.userText, args.priorMessages, cfg.queryMode, cfg.recentUserTurns);\n if (query.trim().length === 0) {\n const finalized = await finalize(args, cfg.queryMode, {\n summary: undefined,\n durationMs: Date.now() - started,\n status: \"no-recall\",\n hits: [],\n });\n return endRecallSpan(span, args, finalized);\n }\n const result = await searchOnce(args, cfg, query, started);\n notifyBreaker(args.breaker, breakerKey, result.status);\n const finalized = await finalize(args, cfg.queryMode, result);\n return endRecallSpan(span, args, finalized);\n } catch (cause) {\n span.recordException(cause);\n span.setStatus({ code: 2, message: cause instanceof Error ? cause.message : String(cause) });\n span.end();\n throw cause;\n }\n}\n\nfunction startMemoryRecallSpan(args: RunActiveMemoryArgs): OTelSpan {\n const telemetry: TelemetryHandle | undefined = args.telemetry;\n if (telemetry === undefined) {\n // No-op span identical to the runtime no-op when telemetry is disabled.\n return {\n setAttribute: () => {},\n setAttributes: () => {},\n addEvent: () => {},\n setStatus: () => {},\n recordException: () => {},\n end: () => {},\n spanContext: () => ({ traceId: \"0\".repeat(32), spanId: \"0\".repeat(16) }),\n isRecording: () => false,\n };\n }\n return telemetry.startSpan(SPAN_MEMORY_RECALL, {\n queryMode: args.options.queryMode ?? \"recent\",\n ...(args.userId !== undefined ? { userId: args.userId } : {}),\n ...(args.namespace !== undefined ? { namespace: args.namespace } : {}),\n ...(args.scope !== undefined ? { scope: args.scope } : {}),\n });\n}\n\nfunction endRecallSpan(\n span: OTelSpan,\n args: RunActiveMemoryArgs,\n result: ActiveMemoryResult,\n): ActiveMemoryResult {\n span.setAttributes({\n hits: result.hits.length,\n status: result.status,\n durationMs: result.durationMs,\n });\n span.end();\n args.telemetry?.recordHistogram(HISTOGRAM_MEMORY_RECALL_DURATION_MS, result.durationMs, {\n status: result.status,\n ...(args.userId !== undefined ? { userId: args.userId } : {}),\n ...(args.namespace !== undefined ? { namespace: args.namespace } : {}),\n ...(args.scope !== undefined ? { scope: args.scope } : {}),\n });\n return result;\n}\n\ninterface ResolvedConfig {\n queryMode: ActiveMemoryQueryMode;\n timeoutMs: number;\n maxSummaryChars: number;\n recentUserTurns: number;\n}\n\nasync function searchOnce(\n args: RunActiveMemoryArgs,\n cfg: ResolvedConfig,\n query: string,\n started: number,\n): Promise<ActiveMemoryResult> {\n if (args.index === undefined) {\n return { summary: undefined, durationMs: 0, status: \"skipped\", hits: [] };\n }\n try {\n const hits = await withTimeout(args.index.search(query, { maxResults: 5 }), cfg.timeoutMs);\n if (hits === \"timeout\") {\n return { summary: undefined, durationMs: Date.now() - started, status: \"timeout\", hits: [] };\n }\n if (hits.length === 0) {\n return {\n summary: undefined,\n durationMs: Date.now() - started,\n status: \"no-recall\",\n hits: [],\n };\n }\n const summary = formatSummary(hits, cfg.maxSummaryChars);\n return { summary, durationMs: Date.now() - started, status: \"ok\", hits };\n } catch (cause) {\n const message = cause instanceof Error ? cause.message : String(cause);\n process.stderr.write(`[theokit-sdk] active-memory recall failed: ${message}\\n`);\n return { summary: undefined, durationMs: Date.now() - started, status: \"error\", hits: [] };\n }\n}\n\nfunction notifyBreaker(\n breaker: CircuitBreaker | undefined,\n key: string,\n status: ActiveMemoryStatus,\n): void {\n if (breaker === undefined) return;\n if (status === \"timeout\") breaker.recordTimeout(key);\n else if (status === \"ok\" || status === \"no-recall\") breaker.recordSuccess(key);\n}\n\nasync function finalize(\n args: RunActiveMemoryArgs,\n queryMode: ActiveMemoryQueryMode,\n result: ActiveMemoryResult,\n): Promise<ActiveMemoryResult> {\n // #56 (GAP-B) — key the cache write by tenant identity (mirrors the get side).\n const tenantCtx: TenantContext = {\n namespace: args.namespace,\n userId: args.userId,\n scope: args.scope,\n };\n args.cache?.set(args.userText, queryMode, result, tenantCtx);\n if (args.persistTranscripts === true && args.cwd !== undefined) {\n await persistActiveMemoryTranscript(resolveMemoryRoot(args.cwd), {\n runId: args.runId ?? `run-${Date.now()}`,\n startedAtMs: Date.now() - result.durationMs,\n userText: args.userText,\n queryMode,\n status: result.status,\n durationMs: result.durationMs,\n summary: result.summary,\n hits: result.hits.map((h) => ({\n path: h.path,\n startLine: h.startLine,\n endLine: h.endLine,\n score: h.score,\n snippet: h.snippet,\n })),\n });\n }\n return result;\n}\n\nfunction buildQuery(\n userText: string,\n priorMessages: ReadonlyArray<{ role: \"user\" | \"assistant\"; text: string }>,\n queryMode: ActiveMemoryQueryMode,\n recentUserTurns: number,\n): string {\n if (queryMode === \"message\") return userText;\n if (queryMode === \"full\") {\n const allUserTurns = priorMessages.filter((m) => m.role === \"user\").map((m) => m.text);\n return [...allUserTurns, userText].join(\"\\n\");\n }\n // recent\n const recent = priorMessages\n .filter((m) => m.role === \"user\")\n .slice(-recentUserTurns)\n .map((m) => m.text);\n return [...recent, userText].join(\"\\n\");\n}\n\nfunction formatSummary(hits: ReadonlyArray<MemorySearchHit>, maxChars: number): string {\n const lines = hits.map((h) => `- ${h.citation}: ${h.snippet}`);\n let summary = lines.join(\"\\n\");\n if (summary.length > maxChars) summary = `${summary.slice(0, maxChars - 1)}…`;\n return summary;\n}\n\nasync function withTimeout<T>(promise: Promise<T>, timeoutMs: number): Promise<T | \"timeout\"> {\n let timer: NodeJS.Timeout | undefined;\n const timeout = new Promise<\"timeout\">((resolve) => {\n timer = setTimeout(() => resolve(\"timeout\"), timeoutMs);\n });\n try {\n const winner = await Promise.race([promise, timeout]);\n return winner;\n } finally {\n if (timer !== undefined) clearTimeout(timer);\n }\n}\n","/**\n * Consecutive-timeout circuit breaker for Active Memory recall.\n *\n * Mirrors peer-project's `circuitBreakerMaxTimeouts` + `circuitBreakerCooldownMs`\n * config: after N consecutive timeouts the breaker trips and `shouldSkip`\n * returns `true` until `cooldownMs` has elapsed. A successful recall resets\n * the counter immediately.\n *\n * Per-key isolation so two agents in the same process don't share a counter.\n *\n * @internal\n */\n\nexport interface CircuitBreakerOptions {\n maxTimeouts?: number;\n cooldownMs?: number;\n /** Injectable clock for tests. */\n now?: () => number;\n}\n\ninterface KeyState {\n consecutiveTimeouts: number;\n cooldownUntilMs: number;\n}\n\nconst DEFAULT_MAX_TIMEOUTS = 3;\nconst DEFAULT_COOLDOWN_MS = 60_000;\n\n/**\n * Stops calling a recall path that keeps timing out.\n *\n * After `maxTimeouts` consecutive timeouts on a key (default 3) the breaker\n * opens and {@link CircuitBreaker.shouldSkip} reports `true` until `cooldownMs`\n * has elapsed (default 60s). The first `shouldSkip` after the cooldown closes\n * the breaker and resets the counter, so it re-opens only after another full run\n * of timeouts.\n *\n * It counts timeouts, not failures. An error recorded by neither\n * `recordTimeout` nor `recordSuccess` leaves the counter where it was, so a call\n * path that throws rather than hanging will never trip it.\n *\n * State is per key and held in this instance, which is what keeps two agents in\n * one process from sharing a counter. Construct one per agent and pass a stable\n * key.\n */\nexport class CircuitBreaker {\n private readonly states = new Map<string, KeyState>();\n\n constructor(private readonly opts: CircuitBreakerOptions = {}) {}\n\n /** @returns true when the breaker is open and the call should be skipped. */\n shouldSkip(key: string): boolean {\n const state = this.states.get(key);\n if (state === undefined) return false;\n if (state.cooldownUntilMs === 0) return false;\n if (this.now() < state.cooldownUntilMs) return true;\n // Cooldown elapsed — close the breaker.\n state.cooldownUntilMs = 0;\n state.consecutiveTimeouts = 0;\n return false;\n }\n\n recordSuccess(key: string): void {\n const state = this.states.get(key);\n if (state === undefined) return;\n state.consecutiveTimeouts = 0;\n state.cooldownUntilMs = 0;\n }\n\n recordTimeout(key: string): void {\n const state = this.states.get(key) ?? { consecutiveTimeouts: 0, cooldownUntilMs: 0 };\n state.consecutiveTimeouts += 1;\n if (state.consecutiveTimeouts >= (this.opts.maxTimeouts ?? DEFAULT_MAX_TIMEOUTS)) {\n state.cooldownUntilMs = this.now() + (this.opts.cooldownMs ?? DEFAULT_COOLDOWN_MS);\n }\n this.states.set(key, state);\n }\n\n /** @internal — tests inspect counter state. */\n inspect(key: string): Readonly<KeyState> {\n return this.states.get(key) ?? { consecutiveTimeouts: 0, cooldownUntilMs: 0 };\n }\n\n private now(): number {\n return this.opts.now?.() ?? Date.now();\n }\n}\n","import { createHash } from \"node:crypto\";\n\n// T4.1 / D438 — import from leaf to break the active-memory cluster cycle (#10).\nimport type { ActiveMemoryResult } from \"./active-memory-types.js\";\n\n/**\n * TTL-bounded cache for `runActiveMemory` results. Keyed by\n * `sha256(userText + queryMode)` so two identical sends within `cacheTtlMs`\n * (default 15s, matching peer-project's `DEFAULT_CACHE_TTL_MS`) share a single\n * search.\n *\n * Bounded size; oldest entries evicted first when capacity is exceeded.\n *\n * Iter 51 (Stage 3 source-move #8): hybrid copy from sdk-core's\n * `internal/memory/active-memory-cache.ts`. sdk-core retains its copy\n * for v1.x active-memory back-compat; sdk-memory ships the canonical\n * copy that the future `active-memory.ts` move will target as a\n * sibling. Depends only on `node:crypto` + `./active-memory-types.js`\n * (moved iter 48), so no further dependency chain is required.\n *\n * @internal\n */\n\nexport interface ActiveMemoryCacheOptions {\n ttlMs?: number;\n capacity?: number;\n now?: () => number;\n}\n\ninterface CacheEntry {\n expiresAtMs: number;\n result: ActiveMemoryResult;\n}\n\nconst DEFAULT_TTL_MS = 15_000;\nconst DEFAULT_CAPACITY = 1000;\n\n/**\n * A bounded, TTL-expiring cache of recall results, so two identical sends in\n * quick succession run one search.\n *\n * Entries expire `ttlMs` after they were written (default 15s) and are dropped\n * on the read that finds them expired. A read that hits also moves the entry to\n * the most-recent position, so eviction under pressure removes the\n * least-recently-read entry rather than the oldest write.\n *\n * The key covers the query text, the query mode, and the tenant triple\n * (`namespace`, `userId`, `scope`) joined by NUL bytes. Passing no tenant\n * context is allowed and hashes as three empty strings — safe only when the\n * process serves a single tenant.\n *\n * Not process-wide: construct one per agent. Nothing here expires in the\n * background, so an untouched entry occupies its slot until it is read or\n * evicted.\n */\nexport class ActiveMemoryCache {\n private readonly map = new Map<string, CacheEntry>();\n\n constructor(private readonly opts: ActiveMemoryCacheOptions = {}) {}\n\n get(\n userText: string,\n queryMode: string,\n tenantCtx?: TenantContext,\n ): ActiveMemoryResult | undefined {\n const key = cacheKey(userText, queryMode, tenantCtx);\n const entry = this.map.get(key);\n if (entry === undefined) return undefined;\n if (this.now() >= entry.expiresAtMs) {\n this.map.delete(key);\n return undefined;\n }\n // LRU bump\n this.map.delete(key);\n this.map.set(key, entry);\n return entry.result;\n }\n\n set(\n userText: string,\n queryMode: string,\n result: ActiveMemoryResult,\n tenantCtx?: TenantContext,\n ): void {\n const key = cacheKey(userText, queryMode, tenantCtx);\n if (this.map.size >= (this.opts.capacity ?? DEFAULT_CAPACITY)) {\n const oldest = this.map.keys().next().value;\n if (oldest !== undefined) this.map.delete(oldest);\n }\n this.map.set(key, {\n expiresAtMs: this.now() + (this.opts.ttlMs ?? DEFAULT_TTL_MS),\n result,\n });\n }\n\n size(): number {\n return this.map.size;\n }\n\n private now(): number {\n return this.opts.now?.() ?? Date.now();\n }\n}\n\n/**\n * T4.9 — Tenant isolation context for cache key derivation.\n * Pre-T4.9 the key was `sha256(queryMode + userText)` — two users\n * sharing a process with the same query got each other's results.\n * CRITICAL cross-tenant data leak (DR4 finding #9).\n *\n * Synced from sdk-core's `internal/memory/active-memory-cache.ts`\n * per ADR 0002 Stage 4 routing byte-equivalence invariant (iter 112).\n *\n * @internal\n */\nexport interface TenantContext {\n namespace?: string;\n userId?: string;\n scope?: string;\n}\n\n// T4.9 — cache key now includes namespace, userId, scope separated by\n// NUL bytes to prevent collision between `user: \"ab\"` + `scope: \"cd\"`\n// and `user: \"a\"` + `scope: \"bcd\"` (without separator these hash identically).\nfunction cacheKey(userText: string, queryMode: string, ctx?: TenantContext): string {\n const parts = [queryMode, ctx?.namespace ?? \"\", ctx?.userId ?? \"\", ctx?.scope ?? \"\", userText];\n return createHash(\"sha256\").update(parts.join(\"\\x00\")).digest(\"hex\");\n}\n","import type { MemoryEmbeddingProviderAdapter } from \"./embedding-adapter.js\";\nimport { createOpenAiCompatibleRuntime } from \"./openai-compatible.js\";\n\n// Iter 74 rollup-plugin-dts workaround: see openai-embedding.ts header.\n\n/**\n * Azure OpenAI embedding adapter.\n *\n * Azure addresses the DEPLOYMENT in the path rather than the model in the body:\n * `https://{resource}.openai.azure.com/openai/deployments/{deployment}/embeddings?api-version=...`.\n * `{model}` in `embeddingsPath` is substituted by `createOpenAiCompatibleRuntime`, so `model` here\n * names the Azure deployment.\n *\n * `AZURE_OPENAI_ENDPOINT` supplies the resource URL (without the `/openai/...` suffix);\n * `AZURE_OPENAI_API_KEY` the credential.\n *\n * theokit#128 (catalog parity): sdk-core gained this adapter in T4.10 and the peer never mirrored\n * it, so a `sdk-memory` user asking for `azure-openai` was rejected by a provider the SDK's own\n * `Theokit.inspect.embeddingAdapters()` advertised.\n *\n * @internal\n */\n\nexport const DEFAULT_AZURE_OPENAI_EMBEDDING_MODEL = \"text-embedding-3-small\";\n\nconst DIMENSION_BY_MODEL: Record<string, number> = {\n \"text-embedding-3-small\": 1536,\n \"text-embedding-3-large\": 3072,\n \"text-embedding-ada-002\": 1536,\n};\n\n/**\n * Azure OpenAI embeddings. Same models as the OpenAI adapter, addressed the\n * Azure way, and the one adapter whose configuration is not just \"set a key\".\n *\n * Two things differ from every other adapter here. `model` names your Azure\n * DEPLOYMENT, not an OpenAI model id — it is substituted into the path\n * (`/openai/deployments/{model}/embeddings`) rather than sent in the body. And\n * `AZURE_OPENAI_ENDPOINT` must be set to your resource URL, without the\n * `/openai/...` suffix; the built-in default is a placeholder that resolves\n * nowhere, so leaving it unset fails at the network rather than at\n * configuration.\n *\n * Authentication uses the `api-key` header, which is what an Azure resource key\n * expects; Entra ID bearer tokens are not supported by this adapter. Reads\n * `AZURE_OPENAI_API_KEY`. The API version is pinned to `2024-02-01`.\n *\n * The deployment name still has to appear in the dimension table\n * (`text-embedding-3-small`, `-3-large`, `ada-002`), so a deployment named\n * anything else is refused with `embedding_unknown_model` — pass `model` as the\n * matching id and point the base URL at the right deployment, or add the name to\n * the table.\n */\nexport const azureOpenAiMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapter = {\n id: \"azure-openai\",\n defaultModel: DEFAULT_AZURE_OPENAI_EMBEDDING_MODEL,\n transport: \"remote\" as const,\n authProviderId: \"azure-openai\",\n autoSelectPriority: 25,\n create: (options: Parameters<typeof createOpenAiCompatibleRuntime>[1]) =>\n createOpenAiCompatibleRuntime(\n {\n id: \"azure-openai\",\n defaultBaseUrl: \"https://your-resource.openai.azure.com\",\n apiKeyEnv: \"AZURE_OPENAI_API_KEY\",\n baseUrlEnv: \"AZURE_OPENAI_ENDPOINT\",\n defaultModel: DEFAULT_AZURE_OPENAI_EMBEDDING_MODEL,\n embeddingsPath: \"/openai/deployments/{model}/embeddings?api-version=2024-02-01\",\n dimensionByModel: DIMENSION_BY_MODEL,\n // theokit#159 — Azure is NOT OpenAI on the wire, despite the name. It authenticates an API\n // key with the `api-key` header (`Authorization: Bearer` is for Entra ID tokens, not for\n // AZURE_OPENAI_API_KEY), and the deployment already rides in the path, so `model` has no\n // place in the body. Sending the OpenAI shape meant every request was rejected.\n dialect: {\n authHeaders: (apiKey: string) => ({ \"api-key\": apiKey }),\n body: (_model: string, inputs: ReadonlyArray<string>) => ({ input: inputs }),\n },\n },\n options,\n ),\n};\n","import type { MemoryEmbeddingProviderAdapter } from \"./embedding-adapter.js\";\nimport { createOpenAiCompatibleRuntime } from \"./openai-compatible.js\";\n\n// Iter 74 rollup-plugin-dts workaround: see openai-embedding.ts header.\n\n/**\n * Cohere embedding adapter — `POST /v2/embed` at `https://api.cohere.com`. Despite living beside\n * the OpenAI-compatible adapters, this endpoint is NOT OpenAI-shaped in either direction; the\n * `dialect` below is what makes it work.\n *\n * Honors `COHERE_API_KEY`.\n *\n * theokit#128 (catalog parity): mirrors sdk-core's T4.10 adapter, which the peer never picked up.\n *\n * @internal\n */\n\nexport const DEFAULT_COHERE_EMBEDDING_MODEL = \"embed-english-v3.0\";\n\nconst DIMENSION_BY_MODEL: Record<string, number> = {\n \"embed-english-v3.0\": 1024,\n \"embed-multilingual-v3.0\": 1024,\n \"embed-english-light-v3.0\": 384,\n \"embed-multilingual-light-v3.0\": 384,\n};\n\n/**\n * Cohere embeddings. Priority 30, so it is auto-selected ahead of OpenAI when\n * both keys are present.\n *\n * Cohere does not speak the OpenAI wire, and this adapter supplies a dialect for\n * it: the request names its payload `texts`, the response returns\n * `{embeddings: {float: [...]}}`, and `input_type` is sent as\n * `search_document`. That last choice matters — Cohere's v3 models embed\n * documents and queries into different spaces, and this runtime always embeds as\n * a document, including the query side of a search. Expect somewhat weaker\n * retrieval than a Cohere-native setup that embeds queries as `search_query`.\n *\n * Reads `COHERE_API_KEY`; no base-URL environment override is declared. The\n * light models are 384 dimensions and the others 1024.\n */\nexport const cohereMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapter = {\n id: \"cohere\",\n defaultModel: DEFAULT_COHERE_EMBEDDING_MODEL,\n transport: \"remote\" as const,\n authProviderId: \"cohere\",\n autoSelectPriority: 30,\n create: (options: Parameters<typeof createOpenAiCompatibleRuntime>[1]) =>\n createOpenAiCompatibleRuntime(\n {\n id: \"cohere\",\n defaultBaseUrl: \"https://api.cohere.com\",\n apiKeyEnv: \"COHERE_API_KEY\",\n defaultModel: DEFAULT_COHERE_EMBEDDING_MODEL,\n embeddingsPath: \"/v2/embed\",\n dimensionByModel: DIMENSION_BY_MODEL,\n // theokit#159 — `/v2/embed` diverges in BOTH directions: it names the payload `texts`, requires\n // `input_type`, and answers `{embeddings:{float:[[...]]}}` rather than `{data:[{embedding}]}`.\n // `search_document` is the right default here because this runtime embeds material for\n // storage; a query-side embedder would use `search_query`.\n dialect: {\n body: (model: string, inputs: ReadonlyArray<string>) => ({\n model,\n texts: [...inputs],\n input_type: \"search_document\",\n embedding_types: [\"float\"],\n }),\n vectors: (json: unknown) =>\n (json as { embeddings?: { float?: number[][] } }).embeddings?.float,\n },\n },\n options,\n ),\n};\n","import type { MemoryEmbeddingProviderAdapter } from \"./embedding-adapter.js\";\nimport { createOpenAiCompatibleRuntime } from \"./openai-compatible.js\";\n\n// Iter 74 rollup-plugin-dts workaround: see openai-embedding.ts header.\n\n/**\n * DeepInfra embedding adapter — hosts open-source embedding models\n * (BGE, E5, Jina, etc.) at pay-per-token. OpenAI-compatible REST at\n * `POST /v1/openai/embeddings` (note the `/openai` segment; not the\n * canonical `/v1/embeddings`). The `embeddingsPath` override on\n * `OpenAiCompatibleConfig` REPLACES the default suffix (EC-2).\n *\n * Honors `DEEPINFRA_API_KEY` and `DEEPINFRA_API_BASE_URL`.\n *\n * Iter 74 (Stage 3 source-move #33): hybrid copy from sdk-core's\n * `internal/memory/adapters/deepinfra-embedding.ts`.\n *\n * @internal\n */\n\nexport const DEFAULT_DEEPINFRA_EMBEDDING_MODEL = \"BAAI/bge-large-en-v1.5\";\n\nconst DIMENSION_BY_MODEL: Record<string, number> = {\n \"BAAI/bge-large-en-v1.5\": 1024,\n \"BAAI/bge-base-en-v1.5\": 768,\n \"BAAI/bge-small-en-v1.5\": 384,\n \"BAAI/bge-m3\": 1024,\n \"intfloat/e5-large-v2\": 1024,\n \"intfloat/e5-base-v2\": 768,\n \"intfloat/multilingual-e5-large\": 1024,\n \"sentence-transformers/all-MiniLM-L6-v2\": 384,\n \"thenlper/gte-large\": 1024,\n \"thenlper/gte-base\": 768,\n};\n\n/**\n * Open-weight embedding models (BGE, E5, GTE, MiniLM) hosted by DeepInfra.\n * Reach for it when you want a specific open model — particularly a multilingual\n * one — behind a hosted API rather than running it yourself.\n *\n * Its endpoint is `/v1/openai/embeddings`, not the canonical `/v1/embeddings`;\n * the wire format is otherwise OpenAI-shaped. Reads `DEEPINFRA_API_KEY` and\n * honours `DEEPINFRA_API_BASE_URL`. Priority 13.\n *\n * Dimensions vary sharply across the ten models it knows (384 to 1024), and\n * switching between them invalidates an existing vector index — the index drops\n * every vector and re-embeds on the next sync.\n */\nexport const deepinfraMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapter = {\n id: \"deepinfra\",\n defaultModel: DEFAULT_DEEPINFRA_EMBEDDING_MODEL,\n transport: \"remote\" as const,\n authProviderId: \"deepinfra\",\n autoSelectPriority: 13,\n create: (options: Parameters<typeof createOpenAiCompatibleRuntime>[1]) =>\n createOpenAiCompatibleRuntime(\n {\n id: \"deepinfra\",\n defaultBaseUrl: \"https://api.deepinfra.com\",\n apiKeyEnv: \"DEEPINFRA_API_KEY\",\n baseUrlEnv: \"DEEPINFRA_API_BASE_URL\",\n defaultModel: DEFAULT_DEEPINFRA_EMBEDDING_MODEL,\n dimensionByModel: DIMENSION_BY_MODEL,\n embeddingsPath: \"/v1/openai/embeddings\",\n },\n options,\n ),\n};\n","import type { MemoryEmbeddingProviderAdapter } from \"./embedding-adapter.js\";\nimport { createOpenAiCompatibleRuntime } from \"./openai-compatible.js\";\n\n// Iter 74 rollup-plugin-dts workaround: see openai-embedding.ts header.\n\n/**\n * Google Gemini embedding adapter — the OpenAI-compatible surface at\n * `https://generativelanguage.googleapis.com/v1/embeddings`.\n *\n * Gemini's NATIVE embedding endpoint has a different shape\n * (`POST /v1beta/models/{model}:embedContent`); this adapter deliberately targets the\n * OpenAI-compatible one so it composes with the shared runtime.\n *\n * Honors `GEMINI_API_KEY`.\n *\n * theokit#128 (catalog parity): mirrors sdk-core's T4.10 adapter, which the peer never picked up.\n *\n * @internal\n */\n\nexport const DEFAULT_GEMINI_EMBEDDING_MODEL = \"text-embedding-004\";\n\nconst DIMENSION_BY_MODEL: Record<string, number> = {\n \"text-embedding-004\": 768,\n \"embedding-001\": 768,\n};\n\n/**\n * Google Gemini embeddings through Google's OpenAI-compatible surface at\n * `/v1beta/openai/embeddings`. Gemini's native embedding endpoint\n * (`/v1beta/models/{model}:embedContent`) has a different shape and is\n * deliberately not used, so this composes with the shared runtime like the rest.\n *\n * Both known models are 768 dimensions. Reads `GEMINI_API_KEY`; no base-URL\n * environment override is declared. Priority 30.\n */\nexport const geminiMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapter = {\n id: \"gemini\",\n defaultModel: DEFAULT_GEMINI_EMBEDDING_MODEL,\n transport: \"remote\" as const,\n authProviderId: \"gemini\",\n autoSelectPriority: 30,\n create: (options: Parameters<typeof createOpenAiCompatibleRuntime>[1]) =>\n createOpenAiCompatibleRuntime(\n {\n id: \"gemini\",\n defaultBaseUrl: \"https://generativelanguage.googleapis.com\",\n apiKeyEnv: \"GEMINI_API_KEY\",\n defaultModel: DEFAULT_GEMINI_EMBEDDING_MODEL,\n // theokit#159 — the compat surface is under `/v1beta/openai/`, not the default\n // `/v1/embeddings`; the previous path 404'd on every call.\n embeddingsPath: \"/v1beta/openai/embeddings\",\n dimensionByModel: DIMENSION_BY_MODEL,\n },\n options,\n ),\n};\n","import type { MemoryEmbeddingProviderAdapter } from \"./embedding-adapter.js\";\nimport { createOpenAiCompatibleRuntime } from \"./openai-compatible.js\";\n\n// Iter 74 rollup-plugin-dts workaround: see openai-embedding.ts header.\n\n/**\n * Jina AI embedding adapter — OpenAI-compatible at `https://api.jina.ai/v1/embeddings`.\n *\n * Honors `JINA_API_KEY`.\n *\n * theokit#128 (catalog parity): mirrors sdk-core's T4.10 adapter, which the peer never picked up.\n *\n * @internal\n */\n\nexport const DEFAULT_JINA_EMBEDDING_MODEL = \"jina-embeddings-v3\";\n\nconst DIMENSION_BY_MODEL: Record<string, number> = {\n \"jina-embeddings-v3\": 1024,\n \"jina-embeddings-v2-base-en\": 768,\n \"jina-embeddings-v2-small-en\": 512,\n};\n\n/**\n * Jina AI embeddings, over the standard OpenAI wire. Highest auto-select\n * priority in the catalog (35), so it wins over OpenAI when both keys are\n * present.\n *\n * Default `jina-embeddings-v3` at 1024 dimensions; the v2 models are 768 and\n * 512. Reads `JINA_API_KEY`. No base-URL environment override is declared —\n * point it elsewhere by passing `baseUrl` to `create`.\n */\nexport const jinaMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapter = {\n id: \"jina\",\n defaultModel: DEFAULT_JINA_EMBEDDING_MODEL,\n transport: \"remote\" as const,\n authProviderId: \"jina\",\n autoSelectPriority: 35,\n create: (options: Parameters<typeof createOpenAiCompatibleRuntime>[1]) =>\n createOpenAiCompatibleRuntime(\n {\n id: \"jina\",\n defaultBaseUrl: \"https://api.jina.ai\",\n apiKeyEnv: \"JINA_API_KEY\",\n defaultModel: DEFAULT_JINA_EMBEDDING_MODEL,\n dimensionByModel: DIMENSION_BY_MODEL,\n },\n options,\n ),\n};\n","import type { MemoryEmbeddingProviderAdapter } from \"./embedding-adapter.js\";\nimport { createOpenAiCompatibleRuntime } from \"./openai-compatible.js\";\n\n// Iter 74 rollup-plugin-dts workaround: see openai-embedding.ts header.\n\n/**\n * Mistral embedding adapter — OpenAI-compatible REST surface\n * (`POST /v1/embeddings` against `https://api.mistral.ai`). Default model\n * `mistral-embed` (1024 dims).\n *\n * Mirrors `reference/peer-project/extensions/mistral/memory-embedding-adapter.ts`.\n *\n * Iter 74 (Stage 3 source-move #32): hybrid copy from sdk-core's\n * `internal/memory/adapters/mistral-embedding.ts`.\n *\n * @internal\n */\n\nexport const DEFAULT_MISTRAL_EMBEDDING_MODEL = \"mistral-embed\";\n\nconst DIMENSION_BY_MODEL: Record<string, number> = {\n \"mistral-embed\": 1024,\n};\n\n/**\n * Mistral embeddings, over the standard OpenAI wire. One model only,\n * `mistral-embed` at 1024 dimensions; any other id is refused with\n * `embedding_unknown_model`.\n *\n * Reads `MISTRAL_API_KEY` and honours `MISTRAL_API_BASE_URL`. Priority 18, just\n * below OpenAI.\n */\nexport const mistralMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapter = {\n id: \"mistral\",\n defaultModel: DEFAULT_MISTRAL_EMBEDDING_MODEL,\n transport: \"remote\" as const,\n authProviderId: \"mistral\",\n autoSelectPriority: 18,\n create: (options: Parameters<typeof createOpenAiCompatibleRuntime>[1]) =>\n createOpenAiCompatibleRuntime(\n {\n id: \"mistral\",\n defaultBaseUrl: \"https://api.mistral.ai\",\n apiKeyEnv: \"MISTRAL_API_KEY\",\n baseUrlEnv: \"MISTRAL_API_BASE_URL\",\n defaultModel: DEFAULT_MISTRAL_EMBEDDING_MODEL,\n dimensionByModel: DIMENSION_BY_MODEL,\n },\n options,\n ),\n};\n","/**\n * Ollama embedding adapter (T3.1, ADR D183).\n *\n * Targets Ollama's OpenAI-compatible `/v1/embeddings` endpoint and reuses\n * the shared `createOpenAiCompatibleRuntime` factory. The differentiating\n * bits:\n *\n * - `authType: \"none\"` — Ollama local ignores `Authorization`. Sentinel\n * `\"ollama-local\"` is passed as apiKey to satisfy the factory contract\n * (mirrors peer-project `OLLAMA_DEFAULT_API_KEY = \"ollama-local\"`).\n * - `OLLAMA_HOST` overrides the default `http://localhost:11434`.\n * - `OLLAMA_API_KEY` (optional) overrides the sentinel for Ollama Cloud\n * or reverse-proxy auth setups.\n * - Default model: `nomic-embed-text` (768 dim, ~274MB). User can opt\n * into `all-minilm` (384 dim, ~45MB) or any other locally-installed\n * embedding model.\n *\n * EC-B MUST FIX (edge-case review 2026-05-21): empty text is rejected\n * upstream in the shared factory (`classifyEntry` short-circuits to a\n * zero vector). That behavior is acceptable here because the zero\n * vector is identical for any empty input — downstream similarity\n * calcs ignore zero-norm vectors via the existing `cosineSimilarity`\n * guard. No additional fail-fast needed.\n *\n * EC-A MUST FIX (edge-case review 2026-05-21): dimension is locked\n * by the `DIMENSION_BY_MODEL` table; an unknown model id throws\n * `ConfigurationError(code: \"embedding_unknown_model\")` per the\n * factory's EC-4 contract. Future model versions with different\n * dimensions are added to the table here without breaking changes.\n *\n * Iter 74 (Stage 3 source-move #36): hybrid copy from sdk-core's\n * `internal/memory/adapters/ollama-embedding.ts`. The only\n * `transport: \"local\"` adapter in the cluster — enables 100%-local\n * RAG with no remote API key.\n *\n * @internal\n */\n\nimport type { MemoryEmbeddingProviderAdapter } from \"./embedding-adapter.js\";\nimport { createOpenAiCompatibleRuntime } from \"./openai-compatible.js\";\n\n// Iter 74 rollup-plugin-dts workaround: see openai-embedding.ts header.\n\n/**\n * Model used when the caller names none: `nomic-embed-text`, 768 dimensions,\n * roughly 274MB to pull. `all-minilm` is the smaller alternative at 384\n * dimensions and roughly 45MB.\n */\nexport const DEFAULT_OLLAMA_EMBEDDING_MODEL = \"nomic-embed-text\";\n\n/** Sentinel forwarded as Bearer token; Ollama local ignores Authorization. */\nconst OLLAMA_LOCAL_SENTINEL_KEY = \"ollama-local\";\n\nconst DIMENSION_BY_MODEL: Record<string, number> = {\n // Nomic — local default, recommended quality/size balance.\n \"nomic-embed-text\": 768,\n \"nomic-embed-text:latest\": 768,\n // Sentence-transformers MiniLM — smaller, faster, lower quality.\n \"all-minilm\": 384,\n \"all-minilm:latest\": 384,\n // BGE family.\n \"bge-large\": 1024,\n \"bge-large:latest\": 1024,\n \"bge-m3\": 1024,\n \"bge-m3:latest\": 1024,\n // mxbai-embed-large.\n \"mxbai-embed-large\": 1024,\n \"mxbai-embed-large:latest\": 1024,\n};\n\n/**\n * Embeddings from a local Ollama instance — the only adapter in the catalog with\n * `transport: \"local\"`, and the one to choose when the corpus must not leave the\n * machine or when there is no API key to spend.\n *\n * It needs an Ollama server reachable at `OLLAMA_HOST` (default\n * `http://localhost:11434`) with the chosen embedding model already pulled;\n * nothing here starts a server or downloads a model, so a missing model surfaces\n * as an HTTP error from Ollama rather than a configuration error.\n *\n * No credential is required: a sentinel key is sent and local Ollama ignores it.\n * Set `OLLAMA_API_KEY` for Ollama Cloud or an authenticating reverse proxy.\n *\n * Auto-select priority is 10, the lowest in the catalog, so a configured remote\n * provider wins over it. Request it explicitly to prefer local.\n */\nexport const ollamaMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapter = {\n id: \"ollama\",\n defaultModel: DEFAULT_OLLAMA_EMBEDDING_MODEL,\n transport: \"local\" as const,\n authProviderId: \"ollama\",\n // Lower than remote providers — chosen only when explicitly requested\n // OR when no remote provider key is configured (local-first developer).\n autoSelectPriority: 10,\n create: (options: Parameters<typeof createOpenAiCompatibleRuntime>[1]) => {\n // Honor OLLAMA_API_KEY (Ollama Cloud / reverse-proxy auth), else use\n // sentinel that local Ollama silently ignores. This mirrors\n // `sentinelForNoAuth` in router.ts and peer-project's `resolveSyntheticAuth`.\n const apiKey = options.apiKey ?? process.env.OLLAMA_API_KEY ?? OLLAMA_LOCAL_SENTINEL_KEY;\n return createOpenAiCompatibleRuntime(\n {\n id: \"ollama\",\n defaultBaseUrl: \"http://localhost:11434\",\n apiKeyEnv: \"OLLAMA_API_KEY\",\n baseUrlEnv: \"OLLAMA_HOST\",\n defaultModel: DEFAULT_OLLAMA_EMBEDDING_MODEL,\n dimensionByModel: DIMENSION_BY_MODEL,\n },\n { ...options, apiKey },\n );\n },\n};\n","import type { MemoryEmbeddingProviderAdapter } from \"./embedding-adapter.js\";\nimport { createOpenAiCompatibleRuntime } from \"./openai-compatible.js\";\n\n// **Iter 74 rollup-plugin-dts workaround:** importing\n// `MemoryEmbeddingProviderAdapter` from sibling `./embedding-adapter.js`\n// fails dts emit because no public type reaches it transitively yet\n// (same iter 48/53/55/66/67/69/72 class). Fix: drop the explicit\n// type annotation on the exported adapter; TS infers the structural\n// shape from the literal, and the catalog (iter 37 / this same iter)\n// pin assignability against the canonical interface via its own\n// `Record<string, MemoryEmbeddingProviderAdapter>` constraint.\n\n/**\n * OpenAI embedding adapter (ADR D3) — built on the shared OpenAI-compatible\n * factory. Native fetch only.\n *\n * Iter 74 (Stage 3 source-move #31): hybrid copy from sdk-core's\n * `internal/memory/adapters/openai-embedding.ts`. Composes iter 45's\n * `MemoryEmbeddingProviderAdapter` + iter 73's\n * `createOpenAiCompatibleRuntime`.\n *\n * @internal\n */\n\nexport const DEFAULT_OPENAI_EMBEDDING_MODEL = \"text-embedding-3-small\";\n\nconst DIMENSION_BY_MODEL: Record<string, number> = {\n \"text-embedding-3-small\": 1536,\n \"text-embedding-3-large\": 3072,\n \"text-embedding-ada-002\": 1536,\n};\n\n/**\n * OpenAI embeddings — `text-embedding-3-small` (1536), `text-embedding-3-large` (3072) and\n * `text-embedding-ada-002` (1536).\n *\n * It is NOT selected for you. The provider is whatever the caller names in\n * `embedding: { provider }`; omit that and no embedding runtime is built at all. Its\n * `autoSelectPriority` of `20` is metadata no code path reads today, and it is not the highest\n * value in the catalog either — `jina` is 35, `cohere` and `gemini` are 30, `azure-openai` is 25.\n * The 3072-wide `text-embedding-3-large` is reachable through `azure-openai` and, as\n * `openai/text-embedding-3-large`, through `openrouter` as well.\n *\n * Reads `OPENAI_API_KEY`; `OPENAI_API_BASE_URL` redirects it at a compatible\n * gateway. `create` rejects with an `AuthenticationError`\n * (`embedding_missing_api_key`) when no key is found, and with a\n * `ConfigurationError` (`embedding_unknown_model`) for a model outside\n * `text-embedding-3-small`, `text-embedding-3-large` and\n * `text-embedding-ada-002` — the dimension has to be known before any vector\n * table is created, so an unlisted model is refused rather than probed.\n */\nexport const openAiMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapter = {\n id: \"openai\",\n defaultModel: DEFAULT_OPENAI_EMBEDDING_MODEL,\n transport: \"remote\" as const,\n authProviderId: \"openai\",\n autoSelectPriority: 20,\n create: (options: Parameters<typeof createOpenAiCompatibleRuntime>[1]) =>\n createOpenAiCompatibleRuntime(\n {\n id: \"openai\",\n defaultBaseUrl: \"https://api.openai.com\",\n apiKeyEnv: \"OPENAI_API_KEY\",\n baseUrlEnv: \"OPENAI_API_BASE_URL\",\n defaultModel: DEFAULT_OPENAI_EMBEDDING_MODEL,\n dimensionByModel: DIMENSION_BY_MODEL,\n },\n options,\n ),\n};\n","import type { MemoryEmbeddingProviderAdapter } from \"./embedding-adapter.js\";\nimport { createOpenAiCompatibleRuntime } from \"./openai-compatible.js\";\n\n// Iter 74 rollup-plugin-dts workaround: see openai-embedding.ts header.\n\n/**\n * OpenRouter embedding adapter — routes through OpenRouter's\n * `POST /api/v1/embeddings` endpoint (OpenAI-compatible request/response\n * shape). The provider id strings follow OpenRouter's catalog\n * (e.g. `\"openai/text-embedding-3-small\"`, `\"mistralai/mistral-embed\"`).\n *\n * Honors `OPENROUTER_API_KEY` and `OPENROUTER_API_BASE_URL`. Default base\n * URL is `https://openrouter.ai/api`.\n *\n * Iter 74 (Stage 3 source-move #35): hybrid copy from sdk-core's\n * `internal/memory/adapters/openrouter-embedding.ts`.\n *\n * @internal\n */\n\nexport const DEFAULT_OPENROUTER_EMBEDDING_MODEL = \"openai/text-embedding-3-small\";\n\nconst DIMENSION_BY_MODEL: Record<string, number> = {\n \"openai/text-embedding-3-small\": 1536,\n \"openai/text-embedding-3-large\": 3072,\n \"openai/text-embedding-ada-002\": 1536,\n \"mistralai/mistral-embed\": 1024,\n};\n\n/**\n * Embeddings routed through OpenRouter, which lets one key reach several\n * upstream providers. Use it when you want to switch provider without changing\n * credentials; use the provider's own adapter when you want its full model\n * range, since only the four ids in this adapter's dimension table are\n * accepted.\n *\n * Model ids carry the upstream prefix, for example\n * `openai/text-embedding-3-small` or `mistralai/mistral-embed`. The endpoint is\n * `/v1/embeddings` under the base `https://openrouter.ai/api`. Reads\n * `OPENROUTER_API_KEY` and honours `OPENROUTER_API_BASE_URL`. Priority 15.\n */\nexport const openRouterMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapter = {\n id: \"openrouter\",\n defaultModel: DEFAULT_OPENROUTER_EMBEDDING_MODEL,\n transport: \"remote\" as const,\n authProviderId: \"openrouter\",\n autoSelectPriority: 15,\n create: (options: Parameters<typeof createOpenAiCompatibleRuntime>[1]) =>\n createOpenAiCompatibleRuntime(\n {\n id: \"openrouter\",\n defaultBaseUrl: \"https://openrouter.ai/api\",\n apiKeyEnv: \"OPENROUTER_API_KEY\",\n baseUrlEnv: \"OPENROUTER_API_BASE_URL\",\n defaultModel: DEFAULT_OPENROUTER_EMBEDDING_MODEL,\n dimensionByModel: DIMENSION_BY_MODEL,\n },\n options,\n ),\n};\n","import type { MemoryEmbeddingProviderAdapter } from \"./embedding-adapter.js\";\nimport { createOpenAiCompatibleRuntime } from \"./openai-compatible.js\";\n\n// Iter 74 rollup-plugin-dts workaround: see openai-embedding.ts header.\n\n/**\n * Voyage AI embedding adapter — `POST /v1/embeddings` at\n * `https://api.voyageai.com` with the OpenAI-compatible `{ model, input }`\n * request shape. Free tier (200M tokens/month) covers most SDK use.\n *\n * Honors `VOYAGE_API_KEY` and `VOYAGE_API_BASE_URL`.\n *\n * Iter 74 (Stage 3 source-move #34): hybrid copy from sdk-core's\n * `internal/memory/adapters/voyage-embedding.ts`.\n *\n * @internal\n */\n\nexport const DEFAULT_VOYAGE_EMBEDDING_MODEL = \"voyage-3-lite\";\n\nconst DIMENSION_BY_MODEL: Record<string, number> = {\n \"voyage-3-lite\": 512,\n \"voyage-3\": 1024,\n \"voyage-3-large\": 1024,\n \"voyage-code-3\": 1024,\n \"voyage-multilingual-2\": 1024,\n};\n\n/**\n * Voyage AI embeddings, over the standard OpenAI wire. Default model\n * `voyage-3-lite` at 512 dimensions — the narrowest in the catalog, which makes\n * the index smaller and the search cheaper at some cost in quality; `voyage-3`\n * and `voyage-3-large` are 1024, and `voyage-code-3` is the one to pick for\n * source code.\n *\n * Reads `VOYAGE_API_KEY` and honours `VOYAGE_API_BASE_URL`. Priority 14.\n */\nexport const voyageMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapter = {\n id: \"voyage\",\n defaultModel: DEFAULT_VOYAGE_EMBEDDING_MODEL,\n transport: \"remote\" as const,\n authProviderId: \"voyage\",\n autoSelectPriority: 14,\n create: (options: Parameters<typeof createOpenAiCompatibleRuntime>[1]) =>\n createOpenAiCompatibleRuntime(\n {\n id: \"voyage\",\n defaultBaseUrl: \"https://api.voyageai.com\",\n apiKeyEnv: \"VOYAGE_API_KEY\",\n baseUrlEnv: \"VOYAGE_API_BASE_URL\",\n defaultModel: DEFAULT_VOYAGE_EMBEDDING_MODEL,\n dimensionByModel: DIMENSION_BY_MODEL,\n },\n options,\n ),\n};\n","import { azureOpenAiMemoryEmbeddingProviderAdapter } from \"./embedding/azure-openai-embedding.js\";\nimport { cohereMemoryEmbeddingProviderAdapter } from \"./embedding/cohere-embedding.js\";\nimport { deepinfraMemoryEmbeddingProviderAdapter } from \"./embedding/deepinfra-embedding.js\";\nimport { geminiMemoryEmbeddingProviderAdapter } from \"./embedding/gemini-embedding.js\";\nimport { jinaMemoryEmbeddingProviderAdapter } from \"./embedding/jina-embedding.js\";\nimport { mistralMemoryEmbeddingProviderAdapter } from \"./embedding/mistral-embedding.js\";\nimport { ollamaMemoryEmbeddingProviderAdapter } from \"./embedding/ollama-embedding.js\";\nimport { openAiMemoryEmbeddingProviderAdapter } from \"./embedding/openai-embedding.js\";\nimport { openRouterMemoryEmbeddingProviderAdapter } from \"./embedding/openrouter-embedding.js\";\nimport { voyageMemoryEmbeddingProviderAdapter } from \"./embedding/voyage-embedding.js\";\n\n// Iter 74 rollup-plugin-dts workaround: see openai-embedding.ts header.\n// Catalog value type is inferred from the literal record; canonical\n// assignability is checked at consumer call sites that destructure into\n// the canonical `MemoryEmbeddingProviderAdapter` shape.\n\n/**\n * Memory embedding adapter catalog, indexed by provider id.\n *\n * Only adapters with full, tested implementations are exposed. The\n * `openrouter` provider proxies through OpenRouter to whichever embedding\n * model the caller selects via `model` (e.g.\n * `\"openai/text-embedding-3-small\"`, `\"mistralai/mistral-embed\"`).\n *\n * Locked by ADR D11: `openai`, `mistral`, `openrouter`, `voyage`, `deepinfra`\n * ship in v1.0. ADR D183: `ollama` added — first `transport: \"local\"`\n * adapter, enables 100%-local RAG (no remote API key needed).\n * `lmstudio`, `google`, `bedrock` are deferred to v1.1.\n *\n * Iter 74 (Stage 3 source-move #37): hybrid copy from sdk-core's\n * `internal/memory/adapters/catalog.ts`. Filename renamed to\n * `adapter-catalog.ts` in sdk-memory to disambiguate from the broader\n * \"catalog\" notion at the package barrel level.\n *\n * **This catalog must serve every provider sdk-core ADVERTISES** (theokit#128). When the peer is\n * installed it REPLACES core's catalog in the routing path (`sdk/src/memory.ts`), while the public\n * `Theokit.inspect.embeddingAdapters()` keeps listing core's — so any id core has and this one\n * lacks is a provider the SDK promises and then rejects. That is what happened to `azure-openai`,\n * `cohere`, `jina` and `gemini` for the two months between core's T4.10 and the parity fix.\n * The invariant is enforced by `@theokit/sdk-peer-integration-tests` (`peer-parity.test.ts`).\n *\n * **CLOSES the embedding-adapter cluster in sdk-memory.** The provider adapters + the shared\n * OpenAI-compatible runtime + the inlined HTTP error mapper are canonical here:\n * - iter 45: embedding-adapter (types)\n * - iter 46: embedding-cache (LRU) — REMOVED by theokit#160: the shared runtime owns caching now\n * - iter 73: openai-compatible (shared factory) + adapter-http-error\n * (inlined mapper)\n * - iter 74: openai-embedding + mistral-embedding + deepinfra-embedding\n * + voyage-embedding + openrouter-embedding + ollama-embedding +\n * adapter-catalog (THIS)\n * - theokit#128: azure-openai + cohere + jina + gemini (parity with core's T4.10)\n *\n * @internal\n */\nexport const MEMORY_EMBEDDING_ADAPTERS = {\n openai: openAiMemoryEmbeddingProviderAdapter,\n mistral: mistralMemoryEmbeddingProviderAdapter,\n openrouter: openRouterMemoryEmbeddingProviderAdapter,\n voyage: voyageMemoryEmbeddingProviderAdapter,\n deepinfra: deepinfraMemoryEmbeddingProviderAdapter,\n ollama: ollamaMemoryEmbeddingProviderAdapter,\n // theokit#128 — mirrors sdk-core's T4.10 additions, which the peer had drifted behind.\n \"azure-openai\": azureOpenAiMemoryEmbeddingProviderAdapter,\n cohere: cohereMemoryEmbeddingProviderAdapter,\n jina: jinaMemoryEmbeddingProviderAdapter,\n gemini: geminiMemoryEmbeddingProviderAdapter,\n};\n","/**\n * Public memory types (used by runtime + storage + migration + future index).\n *\n * Leaf module — depends only on `node:path` + the public\n * `@theokit/sdk/path-safety` re-exports (`safePathJoin`,\n * `sanitizeIdentifier`) + `@theokit/sdk`'s `Security` for the\n * canonical `redactSecrets` 12-pattern list (ADR D68).\n *\n * Iter 52 (Stage 3 source-move #9): hybrid copy from sdk-core's\n * `internal/memory/types.ts`. sdk-core retains its copy for v1.x\n * back-compat; sdk-memory ships the canonical copy that future\n * `storage/*`, `migration`, and `tools` moves will target as siblings.\n *\n * **Sub-path-import contract:** sdk-core copy imports\n * `safePathJoin`/`sanitizeIdentifier` from `../security/path-guard.js`\n * (internal path); sdk-memory copy imports them from\n * `@theokit/sdk/path-safety` (public sub-path stable per this\n * iter — sanitizeIdentifier was promoted to the public surface to\n * unblock this move). Same runtime, same grammar.\n *\n * @internal\n */\nimport { resolve as resolvePath } from \"node:path\";\n\nimport { Security } from \"@theokit/sdk\";\nimport { safePathJoin, sanitizeIdentifier } from \"@theokit/sdk/path-safety\";\n\n/**\n * Per-agent memory configuration. `enabled` gates the configuration-aware\n * accessors (`readFacts`, `appendFact`) — with it `false` they resolve without\n * touching disk, while the lower-level markdown functions ignore it.\n *\n * `namespace`, `scope` and `userId` are only consulted for the legacy JSON path\n * (see {@link legacyMemoryJsonPath}); the markdown store keeps one `MEMORY.md`\n * per workspace and does not partition by them. They are treated as\n * user-supplied and sanitised before they reach a path. `storePath` is treated\n * as trusted and resolved as given.\n */\nexport interface MemoryConfig {\n enabled: boolean;\n namespace?: string;\n userId?: string;\n scope?: \"agent\" | \"user\" | \"team\";\n storePath?: string;\n}\n\n/**\n * One remembered statement. `text` is what gets written, embedded and searched;\n * it passes through secret redaction on the way to disk, so what is stored may\n * differ from what was passed in.\n */\nexport interface MemoryFact {\n text: string;\n /**\n * Optional taxonomy bucket (M4-3). Backward-compatible — flat-store facts\n * omit it; the categorized store (`createCategorizedMemory`) always sets it.\n */\n category?: string;\n}\n\n/**\n * Canonical credential-redaction primitive (ADR D68).\n *\n * sdk-core's copy re-exports `redactSecrets` directly from\n * `../security/index.js` (internal path). sdk-core's PUBLIC surface\n * (`@theokit/sdk`) doesn't expose a bare `redactSecrets` symbol —\n * it ships `Security.redact()` instead (T2.1, by design — the\n * namespace also carries `Security.addPattern()`). sdk-memory's\n * canonical `redactSecrets` re-export wraps `Security.redact` 1-to-1\n * so consumers continue to see the same symbol name without sdk-memory\n * having to import sdk-core's internal subpath. Same 12-pattern\n * list, same two-bucket mask shape, same disable-via-env behavior.\n */\nexport function redactSecrets(text: unknown, opts?: { codeFile?: boolean }): string {\n return Security.redact(text, opts);\n}\n\n/**\n * Resolve the legacy JSON memory path used pre-ADR-D8 (kept for migration\n * helpers + tests). Centralized here so `migration.ts` and the legacy-aware\n * `runtime/memory-store.ts` don't duplicate the path logic (jscpd cleanup).\n */\nexport function legacyMemoryJsonPath(cwd: string, config: MemoryConfig): string {\n // ADRs D79-D81: storePath is programmatic (trusted); namespace/scope/userId\n // are user-shaped and pass sanitizeIdentifier. EC-7 (edge-case review):\n // realistic userIds (UUIDs, hash IDs, \"default\") pass; \"user@example.com\"\n // and similar need to be normalized by the caller before passing.\n if (config.storePath !== undefined) {\n return resolvePath(cwd, config.storePath);\n }\n const namespace = sanitizeIdentifier(config.namespace ?? \"default\");\n const scope = sanitizeIdentifier(config.scope ?? \"agent\", { maxLen: 16 });\n const userId = sanitizeIdentifier(config.userId ?? \"default\");\n return safePathJoin(cwd, \".theokit\", \"memory\", namespace, `${scope}-${userId}.json`);\n}\n\n/**\n * A semantically meaningful slice of a markdown memory file, produced by\n * `chunkMarkdown`. Each chunk carries stable line numbers + a content hash\n * used downstream by the embedding cache.\n *\n * Mirrors peer-project's `MemoryChunk` shape\n * (`reference/peer-project/packages/memory-host-sdk/src/host/engine-storage.ts`).\n *\n * @internal\n */\nexport interface MemoryChunk {\n /** 1-indexed starting line in the source file. */\n startLine: number;\n /** 1-indexed ending line (inclusive). */\n endLine: number;\n /** Slice of markdown source text. */\n text: string;\n /** sha256 of `text`; stable across runs for identical inputs. */\n hash: string;\n /** Optional nearest heading text (without the `#` markers). */\n heading?: string;\n}\n\n/**\n * Result of `reader.readFile`. Contains the bounded slice plus truncation\n * + provenance info.\n *\n * Mirrors peer-project's `MemoryReadResult` shape.\n *\n * @internal\n */\nexport interface MemoryReadResult {\n path: string;\n /** Requested starting line (1-indexed, defaults to 1). */\n from: number;\n /** Number of lines actually returned (may be less than `lines` near EOF). */\n linesReturned: number;\n /** Total lines in the file (after the read). */\n totalLines: number;\n /** True when content remains after the returned slice, i.e. `remainingLines > 0`. */\n truncated: boolean;\n /** Lines past the returned slice that remain in the file. */\n remainingLines: number;\n /** Slice text (joined with `\\n`). */\n text: string;\n}\n\n/**\n * Lightweight reference to a markdown file in the memory corpus.\n *\n * Mirrors peer-project's `MemoryFileEntry`.\n *\n * @internal\n */\nexport interface MemoryFileEntry {\n /** Absolute path on disk. */\n path: string;\n /** Path relative to the memory root (e.g. \"MEMORY.md\", \"notes/foo.md\"). */\n relPath: string;\n /** ms-since-epoch mtime. */\n mtime: number;\n /** sha256 of the file content; recomputed on each read. */\n hash: string;\n}\n","/**\n * OpenAI-compatible HTTP error mapper (ADR D67) — sdk-memory inlined copy.\n *\n * Translates OpenAI-shaped API error responses (covers OpenAI, OpenRouter,\n * DeepSeek, Together, Mistral, Voyage, DeepInfra, etc.) into typed\n * `TheokitAgentError` subclasses with full `ErrorMetadata`.\n *\n * Body inspection: looks at `body.error.code` / `body.error.type` to detect\n * `context_too_long`, `content_filtered`, `model_unavailable` semantics.\n * Falls back to status-based mapping when body doesn't expose `.error`\n * (e.g., HTML server error page, DeepInfra's `{message: \"...\"}` shape).\n *\n * Never throws — caller is already in an error path.\n *\n * Iter 73 (Stage 3 source-move #30): inlined adaptation of sdk-core's\n * `internal/errors/mappers/openai-compatible.ts` + `shared.ts`. sdk-core's\n * mapper is internal — not part of the public errors surface — so sdk-memory\n * carries its own minimal copy here. Behavior MUST stay byte-equivalent\n * with sdk-core's so consumers consuming hits via either package surface\n * see identical error shape.\n *\n * The 4 helpers (`parseRetryAfter`, `truncateRaw`, `buildErrorMetadata`,\n * `mapOpenAICompatibleError`) are intentionally co-located in this single\n * file so all 8 embedding adapter moves (catalog + 7 providers) share one\n * import target.\n *\n * @internal\n */\n\nimport {\n AuthenticationError,\n ConfigurationError,\n type ErrorCode,\n type ErrorMetadata,\n NetworkError,\n RateLimitError,\n type TheokitAgentError,\n UnknownAgentError,\n} from \"@theokit/sdk/errors\";\n\nimport { redactSecrets } from \"./memory-types.js\";\n\nconst RAW_MAX_BYTES = 2048;\n\n/**\n * Parse `retry-after` header in numeric-seconds form. HTTP-date form\n * (RFC 7231) returns `undefined` to avoid NaN propagation downstream.\n */\nexport function parseRetryAfter(headers: Headers | undefined): number | undefined {\n if (headers === undefined) return undefined;\n const raw = headers.get(\"retry-after\");\n if (raw === null) return undefined;\n const n = Number(raw);\n if (Number.isFinite(n) && n >= 0) return Math.ceil(n);\n return undefined;\n}\n\n/**\n * Truncate raw response body to ~2KB and redact known credential\n * patterns so it can ride inside `ErrorMetadata.raw` without\n * ballooning logs OR leaking tokens. Returns `undefined` for\n * null/undefined input.\n */\nexport function truncateRaw(body: unknown): unknown {\n if (body === null || body === undefined) return undefined;\n const s = typeof body === \"string\" ? body : JSON.stringify(body);\n const truncated = s.length <= RAW_MAX_BYTES ? s : `${s.slice(0, RAW_MAX_BYTES)}…`;\n return redactSecrets(truncated);\n}\n\n/**\n * Build an `ErrorMetadata` object with all optional fields included\n * conditionally (no `undefined` keys in the output).\n */\nexport function buildErrorMetadata(args: {\n provider: string;\n endpoint: string;\n code: ErrorCode;\n status: number;\n headers: Headers | undefined;\n body: unknown;\n}): ErrorMetadata {\n const retryAfter = parseRetryAfter(args.headers);\n const raw = truncateRaw(args.body);\n return {\n provider: args.provider,\n endpoint: args.endpoint,\n code: args.code,\n statusCode: args.status,\n ...(retryAfter !== undefined ? { retryAfter } : {}),\n ...(raw !== undefined ? { raw } : {}),\n };\n}\n\ninterface MapOpenAiErrorArgs {\n providerId: string;\n status: number;\n body: unknown;\n headers: Headers | undefined;\n endpoint: string;\n}\n\n/**\n * Turn a failed OpenAI-shaped HTTP response into the typed error the SDK throws.\n * Builds the error, it does not throw it.\n *\n * The HTTP status picks the class: 401 and 403 give an `AuthenticationError`,\n * 429 a `RateLimitError`, 400 a `ConfigurationError`, 408 and 5xx a\n * `NetworkError`, and anything else an `UnknownAgentError`.\n *\n * The `code` on the metadata is finer than the class and is read from\n * `body.error.code` (or `.type`) first, so a 400 that names a context-window\n * problem carries `context_too_long` rather than `invalid_request`. A body code\n * naming an exhausted quota, and HTTP 402, both map to `quota_exceeded` — note\n * that a 402 keeps that code while still producing an `UnknownAgentError`,\n * because no status branch claims it.\n *\n * The raw body rides along on the metadata, truncated to about 2KB and passed\n * through secret redaction, so it is safe to log.\n */\nexport function mapOpenAICompatibleError(args: MapOpenAiErrorArgs): TheokitAgentError {\n const { providerId, status, body, headers, endpoint } = args;\n const code = mapOpenAiStatusToCode(status, body);\n const message = formatMessage(providerId, status, code);\n const metadata = buildErrorMetadata({\n provider: providerId,\n endpoint,\n code,\n status,\n headers,\n body,\n });\n\n if (status === 401 || status === 403) {\n return new AuthenticationError(message, { code: `${providerId}_auth_failed`, metadata });\n }\n if (status === 429) {\n return new RateLimitError(message, { code: `${providerId}_rate_limit`, metadata });\n }\n if (status === 400) {\n return new ConfigurationError(message, { code: `${providerId}_${code}`, metadata });\n }\n if (status === 408) {\n return new NetworkError(message, { code: `${providerId}_timeout`, metadata });\n }\n if (status >= 500 && status < 600) {\n return new NetworkError(message, { code: `${providerId}_server_error`, metadata });\n }\n return new UnknownAgentError(message, { code: `${providerId}_unknown`, metadata });\n}\n\nfunction extractOpenAiErrorCode(body: unknown): string | undefined {\n if (body === null || typeof body !== \"object\") return undefined;\n const err = (body as { error?: { code?: unknown; type?: unknown } }).error;\n if (err === undefined || err === null) return undefined;\n if (typeof err.code === \"string\") return err.code;\n if (typeof err.type === \"string\") return err.type;\n return undefined;\n}\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: explicit branch table is clearer than splitting\nfunction mapOpenAiStatusToCode(status: number, body: unknown): ErrorCode {\n const rawCode = extractOpenAiErrorCode(body)?.toLowerCase() ?? \"\";\n\n if (\n rawCode.includes(\"context_length\") ||\n rawCode.includes(\"context_window\") ||\n rawCode.includes(\"too_many_tokens\") ||\n rawCode.includes(\"max_tokens\")\n ) {\n return \"context_too_long\";\n }\n if (\n rawCode.includes(\"content_filter\") ||\n rawCode.includes(\"content_policy\") ||\n rawCode.includes(\"safety\")\n ) {\n return \"content_filtered\";\n }\n if (\n rawCode.includes(\"model_not_found\") ||\n rawCode.includes(\"model_unavailable\") ||\n rawCode.includes(\"invalid_model\")\n ) {\n return \"model_unavailable\";\n }\n // T3.7 — 402 / Insufficient credits / insufficient_quota body code flow\n // to canonical `quota_exceeded` (ADR-spec'd in ErrorCode union).\n if (\n status === 402 ||\n rawCode.includes(\"insufficient_quota\") ||\n rawCode.includes(\"quota_exceeded\")\n ) {\n return \"quota_exceeded\";\n }\n\n if (status === 401 || status === 403) return \"auth_failed\";\n if (status === 429) return \"rate_limit\";\n if (status === 408) return \"timeout\";\n if (status === 400) return \"invalid_request\";\n if (status >= 500 && status < 600) return \"server_error\";\n return \"unknown\";\n}\n\nfunction formatMessage(providerId: string, status: number, code: ErrorCode): string {\n return `${providerId} API error: ${code} (HTTP ${status})`;\n}\n","import { mkdir, readFile } from \"node:fs/promises\";\n\nimport { ConfigurationError } from \"@theokit/sdk/errors\";\nimport { safePathJoin, sanitizeIdentifier } from \"@theokit/sdk/path-safety\";\nimport { replaceFileAtomic, withCwdMutex } from \"@theokit/sdk/persistence\";\n\nimport { type MemoryFact, redactSecrets } from \"./memory-types.js\";\n\n/**\n * A fact stored under a typed category. Unlike the flat {@link MemoryFact}, the\n * `category` is always present in the categorized store's read shape.\n *\n * @public\n */\nexport interface CategorizedFact extends MemoryFact {\n category: string;\n}\n\n/**\n * Options for {@link createCategorizedMemory}.\n *\n * @public\n */\nexport interface CreateCategorizedMemoryOptions {\n /** Directory holding one markdown file per category (`<root>/<category>.md`). */\n root: string;\n /**\n * The closed category taxonomy. This list IS the schema: an `add`/`list`\n * with a category not in it is rejected. Must be non-empty, unique, each\n * sanitizable to a distinct filename.\n */\n categories: readonly string[];\n}\n\n/**\n * A typed, category-partitioned markdown memory store.\n *\n * @public\n */\nexport interface CategorizedMemory {\n /** The declared (frozen) category taxonomy. */\n readonly categories: readonly string[];\n /**\n * Append a fact under `category` (validated against the taxonomy). The text\n * is secret-redacted before persistence. Concurrent adds to the same category\n * are serialized (no lost update). Throws `ConfigurationError(unknown_category)`\n * for an undeclared category (before any I/O).\n */\n add(category: string, text: string): Promise<void>;\n /**\n * Read facts for one category (or every category when omitted). Never throws —\n * a missing/unreadable category file yields no facts.\n */\n list(category?: string): Promise<CategorizedFact[]>;\n}\n\nconst FACTS_HEADING = \"## Facts\";\n\n/**\n * Create a typed categorized memory store over the closed `categories`\n * taxonomy. Composes the shipped `safePathJoin`/`sanitizeIdentifier` path\n * guard, `redactSecrets`, and the atomic `replaceFileAtomic` + `withCwdMutex`\n * persistence primitives — zero new dependencies.\n *\n * @public\n */\nexport function createCategorizedMemory(\n options: CreateCategorizedMemoryOptions,\n): CategorizedMemory {\n const { root, categories } = options;\n validateCategories(categories);\n const allowed = new Set(categories);\n\n function assertKnown(category: string): void {\n if (!allowed.has(category)) {\n throw new ConfigurationError(\n `createCategorizedMemory: unknown category ${JSON.stringify(category)} (declared: ${categories.join(\", \")})`,\n { code: \"unknown_category\" },\n );\n }\n }\n\n function categoryPath(category: string): string {\n return safePathJoin(root, `${sanitizeIdentifier(category)}.md`);\n }\n\n async function add(category: string, text: string): Promise<void> {\n assertKnown(category);\n // Redact secrets, THEN encode newlines/backslashes so a multiline fact (or\n // one containing a `- ` / `## ` line) stays a single bullet and round-trips\n // faithfully — `list` decodes it back. Without this, the `## Facts` bullet\n // parse would split or truncate the fact (silent data loss).\n const encoded = encodeFact(redactSecrets(text));\n const sane = sanitizeIdentifier(category);\n await withCwdMutex(`catmem:${root}:${sane}`, async () => {\n const path = safePathJoin(root, `${sane}.md`);\n const raw = (await readFileOrEmpty(path)) || header(category);\n await mkdir(root, { recursive: true });\n await replaceFileAtomic(path, appendBullet(raw, encoded));\n });\n }\n\n async function list(category?: string): Promise<CategorizedFact[]> {\n if (category !== undefined) {\n assertKnown(category);\n return readCategory(categoryPath(category), category);\n }\n const out: CategorizedFact[] = [];\n for (const c of categories) {\n out.push(...(await readCategory(categoryPath(c), c)));\n }\n return out;\n }\n\n return { categories: [...categories], add, list };\n}\n\nfunction validateCategories(categories: readonly string[]): void {\n if (categories.length === 0) {\n throw new ConfigurationError(\"createCategorizedMemory: categories must be non-empty\", {\n code: \"invalid_categories\",\n });\n }\n if (new Set(categories).size !== categories.length) {\n throw new ConfigurationError(\"createCategorizedMemory: categories must be unique\", {\n code: \"invalid_categories\",\n });\n }\n const sanitized = categories.map((c) => trySanitize(c));\n if (new Set(sanitized).size !== categories.length) {\n throw new ConfigurationError(\n \"createCategorizedMemory: categories must map to distinct filenames after sanitization\",\n { code: \"invalid_categories\" },\n );\n }\n}\n\nfunction trySanitize(category: string): string {\n try {\n return sanitizeIdentifier(category);\n } catch (cause) {\n throw new ConfigurationError(\n `createCategorizedMemory: category ${JSON.stringify(category)} is not a valid identifier`,\n { code: \"invalid_categories\", cause },\n );\n }\n}\n\nfunction header(category: string): string {\n return `---\\ncategory: ${category}\\n---\\n\\n${FACTS_HEADING}\\n`;\n}\n\nasync function readFileOrEmpty(path: string): Promise<string> {\n try {\n return await readFile(path, \"utf8\");\n } catch {\n return \"\";\n }\n}\n\nasync function readCategory(path: string, category: string): Promise<CategorizedFact[]> {\n const raw = await readFileOrEmpty(path);\n return parseFactBullets(raw).map((text) => ({ text: decodeFact(text), category }));\n}\n\n/**\n * Encode a fact for single-bullet storage: escape `\\` first, then `\\r`/`\\n`, so\n * the text occupies exactly one `- ` line (no split, no `## ` heading injection).\n * Pure + reversible by {@link decodeFact}.\n */\nfunction encodeFact(text: string): string {\n return text.replace(/\\\\/g, \"\\\\\\\\\").replace(/\\r/g, \"\\\\r\").replace(/\\n/g, \"\\\\n\");\n}\n\n/**\n * Reverse {@link encodeFact}. A single left-to-right pass over each `\\<char>`\n * escape: `\\n`→newline, `\\r`→CR, and any other escaped char (notably `\\\\`)→the\n * literal char. Non-overlapping matching makes this exact for encoded input.\n */\nfunction decodeFact(text: string): string {\n return text.replace(/\\\\(.)/g, (_match, char: string) =>\n char === \"n\" ? \"\\n\" : char === \"r\" ? \"\\r\" : char,\n );\n}\n\n/** Parse `- text` bullets under the `## Facts` heading. Pure. */\nfunction parseFactBullets(raw: string): string[] {\n const idx = raw.indexOf(FACTS_HEADING);\n if (idx === -1) return [];\n const tail = raw.slice(idx + FACTS_HEADING.length);\n const nextHeading = tail.search(/\\n#{1,2}\\s/);\n const block = nextHeading === -1 ? tail : tail.slice(0, nextHeading);\n return block\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.startsWith(\"- \"))\n .map((line) => line.slice(2).trim());\n}\n\n/** Append a `- text` bullet under the `## Facts` heading. Pure. */\nfunction appendBullet(raw: string, text: string): string {\n const bullet = `- ${text}`;\n const idx = raw.indexOf(FACTS_HEADING);\n if (idx === -1) {\n const sep = raw.endsWith(\"\\n\") ? \"\" : \"\\n\";\n return `${raw}${sep}${FACTS_HEADING}\\n\\n${bullet}\\n`;\n }\n const after = idx + FACTS_HEADING.length;\n const nextHeading = raw.slice(after).search(/\\n#{1,2}\\s/);\n if (nextHeading === -1) {\n const trailing = raw.endsWith(\"\\n\") ? \"\" : \"\\n\";\n return `${raw}${trailing}${bullet}\\n`;\n }\n const insertAt = after + nextHeading;\n return `${raw.slice(0, insertAt)}\\n${bullet}${raw.slice(insertAt)}`;\n}\n","import type { EmbeddingRuntime } from \"../embedding/embedding-adapter.js\";\nimport type { MemoryFact } from \"../memory-types.js\";\n\n/**\n * Dreaming/REM phase logic.\n *\n * Three phases:\n * - **light** — drop near-duplicate facts (cosine similarity > 0.95).\n * - **REM** — cluster thematically related facts (cosine ≥ 0.75).\n * - **deep** — pick a representative bullet per cluster (longest text\n * wins) and emit consolidated markdown notes.\n *\n * Iter 54 (Stage 3 source-move #11): hybrid copy from sdk-core's\n * `internal/memory/dreaming/phases.ts`. sdk-core retains its copy\n * for v1.x dreaming back-compat; sdk-memory ships the canonical copy\n * that future `dreaming/run.ts` move will compose with as a sibling.\n * Dependencies (both moved): `EmbeddingRuntime` (iter 45) +\n * `MemoryFact` (iter 52).\n *\n * Flat-naming convention (not `dreaming/phases.ts`): sdk-memory's\n * `internal/` directory stays flat to keep relative-import paths\n * uniform across iter 44-53. The `dreaming-` prefix preserves the\n * topical grouping without a sub-directory.\n *\n * @internal\n */\n\nexport interface DedupResult {\n kept: MemoryFact[];\n duplicatesRemoved: number;\n}\n\n/**\n * A group of facts the REM phase judged related. `representativeText` is the\n * text of the longest member, used as the cluster's heading in the consolidated\n * note — longest, not most central, so it is a readable label rather than a\n * centroid. `members` includes that fact as well.\n */\nexport interface Cluster {\n representativeText: string;\n members: ReadonlyArray<MemoryFact>;\n}\n\n/**\n * What {@link remPhase} produced. Every input fact appears in exactly one\n * cluster, so a fact related to nothing comes back as a cluster of one — the\n * count is not a count of *interesting* groupings.\n */\nexport interface ClusterResult {\n clusters: Cluster[];\n}\n\nconst DEFAULT_DEDUP_THRESHOLD = 0.95;\nconst DEFAULT_CLUSTER_THRESHOLD = 0.75;\n\n/** Light phase — drop facts whose embedding is too similar to one already kept. */\nexport async function lightPhase(\n facts: ReadonlyArray<MemoryFact>,\n embedding: EmbeddingRuntime,\n threshold: number = DEFAULT_DEDUP_THRESHOLD,\n): Promise<DedupResult> {\n if (facts.length <= 1) return { kept: [...facts], duplicatesRemoved: 0 };\n const vectors = await embedding.embed(facts.map((f) => f.text));\n const keptIdx: number[] = [];\n const keptVecs: number[][] = [];\n for (let i = 0; i < facts.length; i++) {\n const vec = vectors[i] ?? [];\n const isDup = keptVecs.some((kept) => cosineSimilarity(vec, kept) >= threshold);\n if (isDup) continue;\n keptIdx.push(i);\n keptVecs.push(vec);\n }\n const kept = keptIdx.map((i) => facts[i] as MemoryFact);\n return { kept, duplicatesRemoved: facts.length - kept.length };\n}\n\n// T4.6 — cap facts per sweep to prevent O(N²) blowup. 500 facts →\n// 125K comparisons (acceptable). 5000 facts → 12.5M (unacceptable).\n// Over the cap, the clustering considers the FIRST `maxFactsPerSweep`\n// facts and ignores the rest. It is deterministic (same input, same\n// subset) but positional: nothing carries the remainder into a later\n// sweep, so facts past the cap are never clustered while the ones\n// before them stay in place.\nconst DEFAULT_MAX_FACTS_PER_SWEEP = 500;\n\n/** REM phase — single-link agglomerative clustering by cosine similarity. */\nexport async function remPhase(\n facts: ReadonlyArray<MemoryFact>,\n embedding: EmbeddingRuntime,\n threshold: number = DEFAULT_CLUSTER_THRESHOLD,\n maxFactsPerSweep: number = DEFAULT_MAX_FACTS_PER_SWEEP,\n): Promise<ClusterResult> {\n if (facts.length === 0) return { clusters: [] };\n // T4.6 — cap: take the leading window when facts exceed the budget.\n const capped = facts.length > maxFactsPerSweep ? facts.slice(0, maxFactsPerSweep) : facts;\n const vectors = await embedding.embed(capped.map((f) => f.text));\n const clusterOfIdx = unionFindByPairs(vectors, threshold);\n const groups = bucketFactsByClusterRoot(capped, clusterOfIdx);\n return { clusters: [...groups.values()].map(buildClusterFromMembers) };\n}\n\nfunction unionFindByPairs(\n vectors: ReadonlyArray<ReadonlyArray<number>>,\n threshold: number,\n): number[] {\n const clusterOfIdx = vectors.map((_, i) => i);\n for (let i = 0; i < vectors.length; i++) {\n for (let j = i + 1; j < vectors.length; j++) {\n if (cosineSimilarity(vectors[i] ?? [], vectors[j] ?? []) >= threshold) {\n unifyClusters(clusterOfIdx, i, j);\n }\n }\n }\n return clusterOfIdx;\n}\n\nfunction bucketFactsByClusterRoot(\n facts: ReadonlyArray<MemoryFact>,\n clusterOfIdx: number[],\n): Map<number, MemoryFact[]> {\n const groups = new Map<number, MemoryFact[]>();\n for (let i = 0; i < facts.length; i++) {\n const root = findRoot(clusterOfIdx, i);\n const list = groups.get(root) ?? [];\n list.push(facts[i] as MemoryFact);\n groups.set(root, list);\n }\n return groups;\n}\n\nfunction buildClusterFromMembers(members: ReadonlyArray<MemoryFact>): Cluster {\n const sorted = [...members].sort((a, b) => b.text.length - a.text.length);\n return { representativeText: sorted[0]?.text ?? \"\", members };\n}\n\n/** Deep phase — render consolidated markdown for the dreamed note. */\nexport function deepPhase(clusters: ReadonlyArray<Cluster>, timestampMs: number): string {\n if (clusters.length === 0) return \"\";\n const isoStamp = new Date(timestampMs).toISOString();\n const lines: string[] = [`# Dreamed ${isoStamp}`, \"\"];\n for (let i = 0; i < clusters.length; i++) {\n const c = clusters[i];\n if (c === undefined) continue;\n lines.push(`## Cluster ${i + 1}: ${c.representativeText}`);\n lines.push(\"\");\n for (const member of c.members) lines.push(`- ${member.text}`);\n lines.push(\"\");\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction cosineSimilarity(a: ReadonlyArray<number>, b: ReadonlyArray<number>): number {\n if (a.length === 0 || b.length === 0 || a.length !== b.length) return 0;\n let dot = 0;\n let aNorm = 0;\n let bNorm = 0;\n for (let i = 0; i < a.length; i++) {\n const ai = a[i] ?? 0;\n const bi = b[i] ?? 0;\n dot += ai * bi;\n aNorm += ai * ai;\n bNorm += bi * bi;\n }\n const denom = Math.sqrt(aNorm) * Math.sqrt(bNorm);\n return denom === 0 ? 0 : dot / denom;\n}\n\nfunction findRoot(parents: number[], i: number): number {\n let root = i;\n while (parents[root] !== root) {\n const next = parents[root] ?? root;\n if (next === root) break;\n root = next;\n }\n parents[i] = root;\n return root;\n}\n\nfunction unifyClusters(parents: number[], a: number, b: number): void {\n const rootA = findRoot(parents, a);\n const rootB = findRoot(parents, b);\n if (rootA !== rootB) parents[rootB] = rootA;\n}\n","import { mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { replaceFileAtomic, withCwdMutex } from \"@theokit/sdk/persistence\";\nimport type { EmbeddingRuntime } from \"../embedding/embedding-adapter.js\";\nimport { readFactsFromMarkdown, resolveMemoryRoot } from \"../store/markdown-store.js\";\nimport { appendDiaryEntry } from \"./dreaming-diary.js\";\nimport { deepPhase, lightPhase, remPhase } from \"./dreaming-phases.js\";\n\n/**\n * Dreaming sweep orchestrator (ADR D7 of memory-system-peer-project-parity).\n *\n * Phases:\n * 1. **light** — drop near-duplicate facts via cosine similarity.\n * 2. **REM** — cluster thematically related facts.\n * 3. **deep** — write a `notes/dreamed-<ts>.md` per sweep with consolidated\n * clusters; append a diary entry.\n *\n * All file writes go through `replaceFileAtomic` (EC-3). The sweep holds a\n * mutex for the whole run, so two sweeps over the same workspace serialize.\n * Note the key is `dream:<cwd>`, while `appendFactToMarkdown` locks on the\n * memory directory — different keys, so a concurrent `Remember:` append is NOT\n * excluded by this lock. It cannot corrupt a file (each write is atomic), but a\n * fact appended after the sweep read `MEMORY.md` is simply not in the sweep.\n *\n * Iter 60 (Stage 3 source-move #17): hybrid copy from sdk-core's\n * `internal/memory/dreaming/run.ts`. sdk-core retains its copy for\n * v1.x dreaming back-compat; sdk-memory ships the canonical\n * orchestrator that composes all four sibling moves from iter 45\n * (`EmbeddingRuntime`), iter 54 (`lightPhase`+`remPhase`+`deepPhase`),\n * iter 56 (`memoryDir`+`readFactsFromMarkdown`), and iter 59\n * (`appendDiaryEntry`). Persistence sub-path provides\n * `replaceFileAtomic` + `withCwdMutex`. This closes the dreaming/\n * cluster — 4 files all in sdk-memory now.\n *\n * Flat-naming convention (not `dreaming/run.ts`): sdk-memory's\n * `internal/` directory stays flat. The `dreaming-` prefix preserves\n * the topical grouping (companion to iter 54's `dreaming-phases` and\n * iter 59's `dreaming-diary`).\n *\n * @internal\n */\n\nexport interface DreamingOptions {\n cwd: string;\n embedding: EmbeddingRuntime;\n dedupThreshold?: number;\n clusterThreshold?: number;\n /** Test hook — fixed timestamp for the run. */\n now?: () => number;\n}\n\n/**\n * What one sweep did. `skipped` means `MEMORY.md` held no facts; `error` means\n * the sweep threw and the counts are all zero.\n *\n * `factsAfter` is the count that survived in-memory deduplication, not a new\n * size for `MEMORY.md` — the sweep does not rewrite it, so the duplicates it\n * counted are still on disk and will be counted again next time. `notesWritten`\n * is 0 or 1: one consolidated note per sweep, holding every cluster.\n *\n * `diaryEntryHash` is currently always `undefined`, on every path including\n * success, even though the diary entry itself is written with a hash.\n */\nexport interface DreamingResult {\n status: \"ok\" | \"skipped\" | \"error\";\n factsBefore: number;\n factsAfter: number;\n duplicatesRemoved: number;\n clustersCreated: number;\n notesWritten: number;\n diaryEntryHash: string | undefined;\n}\n\n/**\n * Run one consolidation sweep over `MEMORY.md`: drop near-duplicate facts,\n * cluster what is left, write a consolidated note under `notes/`, and append a\n * diary entry.\n *\n * Every fact is embedded on each sweep, and clustering compares every pair, so\n * cost grows with the square of the corpus. That is why the REM phase looks at\n * the first 500 facts only.\n *\n * Never rejects: a failure is written to stderr and reported as\n * `status: \"error\"`, so a sweep scheduled inside an agent run cannot break it.\n *\n * The sweep is read-only with respect to `MEMORY.md`. It produces a note beside\n * it and leaves the fact list untouched, which means running it twice produces\n * two notes over the same facts.\n */\nexport function runDreamingSweep(options: DreamingOptions): Promise<DreamingResult> {\n return withCwdMutex(`dream:${options.cwd}`, () => runInner(options));\n}\n\nasync function runInner(options: DreamingOptions): Promise<DreamingResult> {\n const now = options.now ?? Date.now;\n const timestampMs = now();\n try {\n const facts = await readFactsFromMarkdown(options.cwd);\n if (facts.length === 0) {\n return emptyResult(\"skipped\");\n }\n const dedup = await lightPhase(facts, options.embedding, options.dedupThreshold);\n const rem = await remPhase(dedup.kept, options.embedding, options.clusterThreshold);\n const notesWritten = await writeConsolidatedNotes(options.cwd, rem.clusters, timestampMs);\n const result: DreamingResult = {\n status: \"ok\",\n factsBefore: facts.length,\n factsAfter: dedup.kept.length,\n duplicatesRemoved: dedup.duplicatesRemoved,\n clustersCreated: rem.clusters.length,\n notesWritten,\n diaryEntryHash: undefined,\n };\n await appendDiaryEntry(resolveMemoryRoot(options.cwd), {\n timestampMs,\n factsBefore: result.factsBefore,\n factsAfter: result.factsAfter,\n duplicatesRemoved: result.duplicatesRemoved,\n clustersCreated: result.clustersCreated,\n notesWritten: result.notesWritten,\n });\n return result;\n } catch (cause) {\n const message = cause instanceof Error ? cause.message : String(cause);\n process.stderr.write(`[theokit-sdk] dreaming sweep failed: ${message}\\n`);\n return emptyResult(\"error\");\n }\n}\n\nasync function writeConsolidatedNotes(\n cwd: string,\n clusters: ReadonlyArray<{ representativeText: string; members: ReadonlyArray<{ text: string }> }>,\n timestampMs: number,\n): Promise<number> {\n if (clusters.length === 0) return 0;\n const notesDir = join(resolveMemoryRoot(cwd), \"notes\");\n await mkdir(notesDir, { recursive: true });\n const isoSlug = new Date(timestampMs).toISOString().replace(/[^\\dT]/g, \"-\");\n const file = join(notesDir, `dreamed-${isoSlug}.md`);\n const body = deepPhase(clusters, timestampMs);\n await replaceFileAtomic(file, body);\n return 1;\n}\n\nfunction emptyResult(status: \"skipped\" | \"error\"): DreamingResult {\n return {\n status,\n factsBefore: 0,\n factsAfter: 0,\n duplicatesRemoved: 0,\n clustersCreated: 0,\n notesWritten: 0,\n diaryEntryHash: undefined,\n };\n}\n","/**\n * SQLite schema for the memory index.\n *\n * Tables:\n * - files — one row per indexed markdown file (path, mtime, hash).\n * - chunks — one row per chunk produced by `chunkMarkdown`.\n * - chunks_fts — FTS5 virtual table mirroring chunks.text for BM25 search.\n * - meta — key/value store; persists the active embedding identity\n * (provider id, model, dimension) so we detect when the\n * index was built against a different embedding setup.\n * - embeddings — sqlite-vec virtual table holding the chunk vectors\n * (created on demand by `vec-index.ts`).\n *\n * Iter 49 (Stage 3 source-move #6): pure SQL-string leaf copied from\n * sdk-core's `internal/memory/index-schema.ts`. Hybrid dual-copy per\n * Phase 2 Stage 1 precedent — sdk-core retains its copy for v1.x\n * back-compat; sdk-memory ships the canonical copy that future\n * sqlite/lance index moves (`index-db`, `index-manager`, `vec-index`,\n * `lance-index`) will target as siblings.\n *\n * @internal\n */\n\nexport const SCHEMA_STATEMENTS: ReadonlyArray<string> = [\n `CREATE TABLE IF NOT EXISTS files (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n path TEXT UNIQUE NOT NULL,\n rel_path TEXT NOT NULL,\n mtime INTEGER NOT NULL,\n hash TEXT NOT NULL,\n source TEXT NOT NULL DEFAULT 'memory'\n )`,\n `CREATE TABLE IF NOT EXISTS chunks (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n file_id INTEGER NOT NULL REFERENCES files(id) ON DELETE CASCADE,\n start_line INTEGER NOT NULL,\n end_line INTEGER NOT NULL,\n text TEXT NOT NULL,\n hash TEXT NOT NULL,\n session_key TEXT\n )`,\n `CREATE VIRTUAL TABLE IF NOT EXISTS chunks_fts USING fts5(\n text,\n content='chunks',\n content_rowid='id'\n )`,\n `CREATE TRIGGER IF NOT EXISTS chunks_fts_insert AFTER INSERT ON chunks BEGIN\n INSERT INTO chunks_fts(rowid, text) VALUES (new.id, new.text);\n END`,\n `CREATE TRIGGER IF NOT EXISTS chunks_fts_delete AFTER DELETE ON chunks BEGIN\n INSERT INTO chunks_fts(chunks_fts, rowid, text) VALUES ('delete', old.id, old.text);\n END`,\n `CREATE TABLE IF NOT EXISTS meta (\n key TEXT PRIMARY KEY,\n value TEXT\n )`,\n `CREATE INDEX IF NOT EXISTS idx_chunks_file_id ON chunks(file_id)`,\n];\n\n/**\n * Non-WAL pragmas. WAL is applied separately via\n * `applyWalWithFallback` (T4.2, ADR D63) so NFS/SMB users get a graceful\n * DELETE fallback instead of crashing.\n */\nexport const PRAGMA_STATEMENTS: ReadonlyArray<string> = [\n \"PRAGMA synchronous=NORMAL\",\n \"PRAGMA foreign_keys=ON\",\n];\n","import { openSqliteResilient } from \"@theokit/sdk/persistence\";\nimport { PRAGMA_STATEMENTS, SCHEMA_STATEMENTS } from \"./index-schema.js\";\n\n/**\n * Thin wrapper around the SQLite driver. Prefers `node:sqlite` when available\n * (Node 22.5+) and falls back to `better-sqlite3`. Both expose nearly the\n * same `prepare/exec/close` surface; we normalize via a minimal adapter.\n *\n * Corrupt-DB recovery (EC-7): when opening fails with a \"file is encrypted\n * or is not a database\" or \"malformed\" error, the file is renamed aside to\n * `<path>.corrupt-<ts>` and the schema is rebuilt from scratch.\n *\n * Iter 65 (Stage 3 source-move #22): hybrid copy from sdk-core's\n * `internal/memory/index-db.ts`. sdk-core retains its copy for v1.x\n * sqlite-vec back-compat; sdk-memory ships the canonical copy that\n * future `sqlite-vec-loader`, `vec-index`, `index-manager` moves\n * will compose with. Dependency chain (all resolved):\n * - `@theokit/sdk/errors` for `ConfigurationError` (public)\n * - `@theokit/sdk/persistence` for `applyWalWithFallback`\n * (ADR D63 — NFS/SMB/FUSE-safe WAL adoption)\n * - sibling `./index-schema.js` for SCHEMA + PRAGMA statements (moved iter 49)\n *\n * @internal\n */\n\nexport interface MemoryDb {\n exec(sql: string): void;\n prepare(sql: string): {\n run(...args: unknown[]): { changes: number; lastInsertRowid: number | bigint };\n get(...args: unknown[]): Record<string, unknown> | undefined;\n all(...args: unknown[]): Array<Record<string, unknown>>;\n };\n /** SQLite `pragma()` access (used by `applyWalWithFallback`). */\n pragma(statement: string, options?: { simple?: boolean }): unknown;\n close(): void;\n /** Load a SQLite loadable extension at the given path (used by sqlite-vec). */\n loadExtension(path: string): void;\n}\n\n/** Options for {@link openMemoryDb}. */\nexport interface OpenDbOptions {\n filePath: string;\n /**\n * When true and opening fails with a corruption error, rename the file aside\n * and create a fresh DB. Default true.\n */\n recoverCorrupt?: boolean;\n}\n\n/**\n * Open (or create) the SQLite memory index at `filePath`, applying the pragmas\n * and creating the schema before returning. Parent directories are created as\n * needed, so pointing this at a fresh workspace works.\n *\n * The driver is chosen at runtime: `node:sqlite` where the running Node exposes\n * it, and `better-sqlite3` otherwise. `better-sqlite3` is an optional peer\n * dependency of this package — on a Node build without `node:sqlite` and\n * without it installed, opening fails.\n *\n * A file that is corrupt, truncated or encrypted is renamed aside to\n * `<path>.corrupt-<timestamp>` and rebuilt empty, unless `recoverCorrupt` is\n * `false`. Recovery loses every indexed chunk; the markdown corpus is the source\n * of truth and the next `sync()` rebuilds from it.\n *\n * Loading the sqlite-vec extension is a separate step — this returns an index\n * that can do text search only.\n */\nexport async function openMemoryDb(opts: OpenDbOptions): Promise<MemoryDb> {\n return openSqliteResilient<MemoryDb>({\n filePath: opts.filePath,\n label: \"memory-index\",\n recoverCorrupt: opts.recoverCorrupt,\n onOpen: (db) => {\n // PRAGMA + SCHEMA run after WAL is applied (handled by openSqliteResilient).\n for (const pragma of PRAGMA_STATEMENTS) db.exec(pragma);\n for (const stmt of SCHEMA_STATEMENTS) db.exec(stmt);\n },\n });\n}\n","import { createHash } from \"node:crypto\";\n\n/**\n * **Iter 53 rollup-plugin-dts workaround** (mirrors iter 48\n * MemorySearchHit pattern). The canonical sdk-core copy imports\n * `MemoryChunk` from `../types.js`. In sdk-memory the same type lives\n * in sibling `./memory-types.js` (moved iter 52) but rollup-dts\n * treeshakes it out of the dist .d.ts because no PUBLIC type\n * references it transitively yet — the public `chunkMarkdown(text):\n * MemoryChunk[]` signature would be the first transitive reachable\n * consumer, BUT rollup-dts processes files in an order that asks for\n * the import resolution BEFORE chunk-markdown.ts itself becomes the\n * reachable consumer. Result: \"MemoryChunk is not exported by\n * src/internal/memory-types.ts\" build error.\n *\n * Fix: declare a byte-identical mirror of MemoryChunk inline. When a\n * future move turns MemoryChunk into a publicly-reachable type\n * through a different path (e.g. `index-db.ts` or `IndexManager`\n * methods that return arrays of it), this mirror MUST be deleted +\n * the canonical import restored to maintain single source of truth.\n *\n * @internal\n */\ninterface MemoryChunk {\n /** 1-indexed starting line in the source file. */\n startLine: number;\n /** 1-indexed ending line (inclusive). */\n endLine: number;\n /** Slice of markdown source text. */\n text: string;\n /** sha256 of `text`; stable across runs for identical inputs. */\n hash: string;\n /** Optional nearest heading text (without the `#` markers). */\n heading?: string;\n}\n\n/**\n * Split a markdown document into semantically meaningful chunks (ADR D1 of\n * memory-system-peer-project-parity).\n *\n * Algorithm:\n * 1. Walk lines tracking the current heading (latest `^#+ ` line).\n * 2. Split chunks at the next heading boundary AND on blank-line paragraph\n * boundaries.\n * 3. If a single paragraph exceeds `maxChars`, split it at the nearest\n * whitespace ≤ maxChars (word-aligned per edge-case review EC-6) —\n * never mid-word.\n *\n * Mirrors peer-project's `chunkMarkdown` from\n * `packages/memory-host-sdk/src/host/chunk-markdown.ts`.\n *\n * Iter 53 (Stage 3 source-move #10): hybrid copy from sdk-core's\n * `internal/memory/storage/chunk-markdown.ts`. sdk-core retains its\n * copy for v1.x back-compat; sdk-memory ships the canonical copy that\n * future `storage/markdown-store`, `migration`, `index-db`, and\n * `index-manager` moves will target as siblings. The `MemoryChunk`\n * type comes from sibling `./memory-types.js` (moved iter 52).\n *\n * @internal\n */\n\nexport interface ChunkMarkdownOptions {\n /** Maximum chars per chunk. Default 800. */\n maxChars?: number;\n /** Minimum chars per chunk (avoids splintering tiny lines). Default 80. */\n minChars?: number;\n}\n\nconst HEADING_RE = /^(#{1,6})\\s+(.+?)\\s*$/;\n\ninterface ChunkAccumulator {\n chunks: MemoryChunk[];\n lines: string[];\n start: number;\n heading: string | undefined;\n}\n\n/**\n * Split markdown into the chunks that get embedded and searched.\n *\n * Boundaries are structural rather than fixed-width: a chunk ends at the next\n * heading, or at a blank line. Each chunk carries the nearest preceding heading,\n * so a hit can be cited with the section it came from. A run of text longer than\n * `maxChars` is then cut at the last whitespace within 200 characters of the\n * limit, falling back to a hard cut when a single token is longer than that.\n *\n * Returns `[]` for empty input. `minChars` on the options is currently not read\n * — small paragraphs are emitted as their own chunks regardless.\n *\n * Line numbers are 1-indexed and inclusive at both ends. They are exact for\n * normal chunks; for a paragraph that had to be split by length, the numbers are\n * derived from newline counts within the slice and mark the span the slice came\n * from rather than a precise per-slice range.\n */\nexport function chunkMarkdown(text: string, options: ChunkMarkdownOptions = {}): MemoryChunk[] {\n const maxChars = options.maxChars ?? 800;\n if (text.length === 0) return [];\n const lines = text.split(\"\\n\");\n const acc: ChunkAccumulator = { chunks: [], lines: [], start: 1, heading: undefined };\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i] ?? \"\";\n const lineNumber = i + 1;\n processLine(acc, line, lineNumber, maxChars);\n }\n flushAccumulator(acc, lines.length, maxChars);\n return acc.chunks;\n}\n\nfunction processLine(\n acc: ChunkAccumulator,\n line: string,\n lineNumber: number,\n maxChars: number,\n): void {\n const headingMatch = HEADING_RE.exec(line);\n const isBlank = line.trim().length === 0;\n if (headingMatch !== null && acc.lines.length > 0) {\n flushAccumulator(acc, lineNumber - 1, maxChars);\n }\n if (headingMatch !== null) acc.heading = headingMatch[2];\n acc.lines.push(line);\n if (isBlank && acc.lines.length > 1) {\n const joined = acc.lines.join(\"\\n\");\n if (joined.trim().length > 0) flushAccumulator(acc, lineNumber, maxChars);\n }\n}\n\nfunction flushAccumulator(acc: ChunkAccumulator, endLineExclusive: number, maxChars: number): void {\n if (acc.lines.length === 0) return;\n const chunkText = acc.lines.join(\"\\n\");\n if (chunkText.trim().length === 0) {\n acc.lines = [];\n acc.start = endLineExclusive + 1;\n return;\n }\n if (chunkText.length > maxChars) {\n pushOversizedSlices(acc.chunks, chunkText, acc.start, acc.heading, maxChars);\n } else {\n acc.chunks.push(buildChunk(chunkText, acc.start, endLineExclusive, acc.heading));\n }\n acc.lines = [];\n acc.start = endLineExclusive + 1;\n}\n\nfunction buildChunk(\n text: string,\n startLine: number,\n endLine: number,\n heading: string | undefined,\n): MemoryChunk {\n return {\n startLine,\n endLine,\n text,\n hash: createHash(\"sha256\").update(text).digest(\"hex\"),\n ...(heading !== undefined ? { heading } : {}),\n };\n}\n\nfunction pushOversizedSlices(\n chunks: MemoryChunk[],\n text: string,\n startLine: number,\n heading: string | undefined,\n maxChars: number,\n): void {\n let remaining = text;\n let lineCursor = startLine;\n while (remaining.length > maxChars) {\n const splitAt = findWordBoundarySplit(remaining, maxChars);\n const slice = remaining.slice(0, splitAt);\n const sliceLines = slice.split(\"\\n\").length;\n chunks.push(buildChunk(slice, lineCursor, lineCursor + sliceLines - 1, heading));\n remaining = remaining.slice(splitAt).replace(/^\\s+/, \"\");\n lineCursor += sliceLines - 1;\n }\n if (remaining.length > 0) {\n const sliceLines = remaining.split(\"\\n\").length;\n chunks.push(buildChunk(remaining, lineCursor, lineCursor + sliceLines - 1, heading));\n }\n}\n\n/**\n * Find a split point ≤ maxChars that lands on a whitespace boundary so we\n * don't slice a word in half. Falls back to maxChars if no whitespace is\n * within range (very rare — a single token > maxChars).\n */\nfunction findWordBoundarySplit(text: string, maxChars: number): number {\n if (text.length <= maxChars) return text.length;\n // Walk backward from maxChars looking for whitespace.\n for (let i = maxChars; i > Math.max(0, maxChars - 200); i--) {\n if (/\\s/.test(text[i] ?? \"x\")) return i;\n }\n // No whitespace within 200 chars of the cap — accept a hard split.\n return maxChars;\n}\n","import { existsSync, mkdirSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\n\nimport { ConfigurationError } from \"@theokit/sdk/errors\";\n\nimport type { EmbeddingRuntime } from \"../embedding/embedding-adapter.js\";\nimport { lanceStoragePath, type MemoryRoot, resolveMemoryRoot } from \"../store/markdown-store.js\";\n\n/**\n * LanceDB-backed memory index (ADR D43). Implements the same logical\n * interface as `IndexManager` but stores embeddings in Lance's columnar\n * vector-aware file format — scalable to 100k+ facts.\n *\n * Opt-in via `Memory.create({ index: { backend: \"lance\" } })`. SQLite\n * remains the default; this code path only activates when explicitly\n * requested AND `@lancedb/lancedb` is installed.\n *\n * EC-1 MUST FIX: filters use Lance's SQL string predicate API — bind\n * parameters are not supported; single-quote escape (`'` → `''`) is the\n * only injection-safe option. Backed by integration test (lancedb-backend-ship-v1-1).\n *\n * EC-8: embedding dimension is validated when opening an existing table.\n *\n * Iter 68 (Stage 3 source-move #25): hybrid copy from sdk-core's\n * `internal/memory/lance-index.ts`. sdk-core retains its copy for v1.x\n * Lance back-compat; sdk-memory ships the canonical copy that future\n * `lance-memory-adapter.ts` move will compose with as a sibling.\n * Dependency chain (all resolved):\n * - `@theokit/sdk/errors` for `ConfigurationError` (public)\n * - sibling `./embedding-adapter.js` for `EmbeddingRuntime` (moved iter 45)\n * - dynamic-required `@lancedb/lancedb` (optional peer — typed\n * ConfigurationError on missing module per EC of the\n * lancedb-backend-ship plan)\n *\n * @internal\n */\n\ninterface LanceModule {\n connect: (uri: string) => Promise<LanceConnection>;\n}\n\ninterface LanceConnection {\n openTable: (name: string) => Promise<LanceTable>;\n createTable: (name: string, data: ReadonlyArray<LanceFactRecord>) => Promise<LanceTable>;\n tableNames: () => Promise<string[]>;\n}\n\ninterface LanceTable {\n add: (rows: ReadonlyArray<LanceFactRecord>) => Promise<void>;\n search: (vector: ReadonlyArray<number>) => LanceQuery;\n delete: (predicate: string) => Promise<void>;\n countRows: () => Promise<number>;\n // EC-8: schema introspection for dimension check.\n schema: () => Promise<{\n fields: ReadonlyArray<{\n name: string;\n // Lance 0.30 returns Apache Arrow Field. FixedSizeList type has\n // `listSize`, not `fixedSize`. typeId=16 = FixedSizeList in Arrow.\n type: { listSize?: number; fixedSize?: number };\n }>;\n }>;\n}\n\ninterface LanceQuery {\n where: (filter: string | Record<string, unknown>) => LanceQuery;\n limit: (n: number) => LanceQuery;\n toArray: () => Promise<ReadonlyArray<LanceFactRecord & { _distance?: number }>>;\n}\n\n/**\n * One row of the Lance `facts` table, as it is stored. Field names are the\n * on-disk column names, which is why `user_id` is snake_case here while the\n * search result reports `userId`.\n *\n * `embedding` must be exactly as wide as the table was created with; the width\n * is fixed by the embedding runtime on the first open and checked on every\n * later one.\n */\nexport interface LanceFactRecord {\n id: string;\n text: string;\n source: \"memory\" | \"sessions\" | \"wiki\";\n embedding: ReadonlyArray<number>;\n namespace: string;\n scope: string;\n user_id: string;\n timestamp: number;\n}\n\n/**\n * Options for `LanceIndex.open`. The embedding runtime is required, not\n * optional: Lance here is vector-only, so there is no text-search fallback to\n * open without one.\n */\nexport interface OpenLanceOptions {\n cwd: string;\n /** The resolved memory root. Defaults to `<cwd>/.theokit/memory` (#463). */\n memoryRoot?: MemoryRoot;\n embedding: EmbeddingRuntime;\n /** Override storage location. Default: `<cwd>/.theokit/memory/lance/`. */\n storagePath?: string;\n}\n\n/**\n * Filters for `LanceIndex.search`. `namespace` is required and `scope` is\n * optional; both are applied as a SQL predicate inside Lance. `sources` is\n * applied in this process, after the rows come back, so it narrows the result\n * without narrowing what `limit` counted.\n */\nexport interface LanceSearchOptions {\n namespace: string;\n scope?: string;\n limit?: number;\n sources?: ReadonlyArray<\"memory\" | \"sessions\" | \"wiki\">;\n}\n\n/**\n * One Lance search result. `score` is a similarity in `(0, 1]` derived from\n * Lance's distance as `1 / (1 + distance)`, so higher is better — the opposite\n * direction from the raw distance Lance returns.\n */\nexport interface LanceSearchHit {\n id: string;\n text: string;\n source: \"memory\" | \"sessions\" | \"wiki\";\n namespace: string;\n scope: string;\n userId: string;\n score: number;\n}\n\n/**\n * Lazily load `@lancedb/lancedb`. Throws typed error when absent.\n *\n * @internal\n */\nfunction requireLance(): LanceModule {\n try {\n const r = createRequire(import.meta.url);\n return r(\"@lancedb/lancedb\") as LanceModule;\n } catch (cause) {\n throw new ConfigurationError(\n \"Lance backend selected but `@lancedb/lancedb` is not installed. \" +\n 'Install with: `pnpm add @lancedb/lancedb`. SQLite remains available as the default (omit `backend: \"lance\"`).',\n { code: \"lance_backend_unavailable\", cause },\n );\n }\n}\n\n/**\n * Lance-backed memory index. Public API mirrors the SQLite one logically:\n * `addFacts`, `search`, `countFacts`, `removeFacts`, `close`.\n *\n * @internal\n */\nexport class LanceIndex {\n private constructor(\n private readonly table: LanceTable,\n private readonly embedding: EmbeddingRuntime,\n private readonly embeddingDim: number,\n ) {}\n\n static async open(opts: OpenLanceOptions): Promise<LanceIndex> {\n const lance = requireLance();\n const storagePath =\n opts.storagePath ?? lanceStoragePath(opts.memoryRoot ?? resolveMemoryRoot(opts.cwd));\n mkdirSync(storagePath, { recursive: true });\n const conn = await lance.connect(storagePath);\n const dim = opts.embedding.dimension;\n const tableName = \"facts\";\n const existing = await conn.tableNames();\n let table: LanceTable;\n if (existing.includes(tableName)) {\n table = await conn.openTable(tableName);\n // EC-8: validate embedding dimension matches what's in storage.\n // Lance 0.30 uses Apache Arrow FixedSizeList type — the size lives\n // in `type.listSize` (older API used `fixedSize`; we read both for\n // forward/backward safety).\n const schema = await table.schema();\n const embField = schema.fields.find((f) => f.name === \"embedding\");\n const existingDim = embField?.type?.listSize ?? embField?.type?.fixedSize;\n if (typeof existingDim === \"number\" && existingDim !== dim) {\n throw new ConfigurationError(\n `Embedding dimension mismatch in Lance index: storage has ${existingDim}-dim vectors, current provider yields ${dim}-dim. Run \\`theokit-migrate-memory\\` after switching providers, or use a different storagePath.`,\n { code: \"embedding_dimension_mismatch\" },\n );\n }\n } else {\n // Create with one bootstrap record. Lance requires an initial row to\n // infer schema; we delete the bootstrap immediately.\n const bootstrap: LanceFactRecord = {\n id: \"__bootstrap__\",\n text: \"\",\n source: \"memory\",\n embedding: new Array(dim).fill(0),\n namespace: \"__bootstrap__\",\n scope: \"__bootstrap__\",\n user_id: \"__bootstrap__\",\n timestamp: 0,\n };\n table = await conn.createTable(tableName, [bootstrap]);\n await table.delete(\"namespace = '__bootstrap__'\");\n }\n return new LanceIndex(table, opts.embedding, dim);\n }\n\n async addFacts(facts: ReadonlyArray<Omit<LanceFactRecord, \"embedding\">>): Promise<void> {\n if (facts.length === 0) return;\n const texts = facts.map((f) => f.text);\n const embeddings = await this.embedding.embed(texts);\n const rows: LanceFactRecord[] = facts.map((f, i) => ({\n ...f,\n embedding: embeddings[i] ?? new Array(this.embeddingDim).fill(0),\n }));\n await this.table.add(rows);\n }\n\n /**\n * Search facts by semantic similarity. EC-1: filters use Lance's\n * SQL string predicate with `'` → `''` escape — bind parameters are\n * not supported by Lance 0.30.\n */\n async search(query: string, opts: LanceSearchOptions): Promise<LanceSearchHit[]> {\n const [embedding] = await this.embedding.embed([query]);\n if (embedding === undefined) return [];\n // EC-1 (lancedb-backend-ship-v1-1 integration test caught this 2026-05-31):\n // Lance 0.30.0's `.where()` accepts SQL STRING only, NOT object filter —\n // contrary to D43's original assumption. We build the SQL string with\n // single-quote escaping (`'` → `''`) to neutralize injection. This is\n // the standard SQL string-literal escape; bind parameters are not\n // supported in Lance's predicate API. Backed by integration test\n // `injection attempt in namespace does not break filter` (test 7).\n const predicates: string[] = [`namespace = '${escapeSqlValue(opts.namespace)}'`];\n if (opts.scope !== undefined) {\n predicates.push(`scope = '${escapeSqlValue(opts.scope)}'`);\n }\n let q = this.table.search(embedding).where(predicates.join(\" AND \"));\n if (opts.limit !== undefined) q = q.limit(opts.limit);\n const results = await q.toArray();\n return results\n .filter((r) => opts.sources === undefined || opts.sources.includes(r.source))\n .map((r) => ({\n id: r.id,\n text: r.text,\n source: r.source,\n namespace: r.namespace,\n scope: r.scope,\n userId: r.user_id,\n // Lower _distance = better match; normalize to 0..1 (1=best).\n score: 1 / (1 + (r._distance ?? 1)),\n }));\n }\n\n async countFacts(namespace: string): Promise<number> {\n // Total count, regardless of namespace, used by migration validation.\n // For per-namespace count, callers can do a where() + countRows() if\n // Lance supports it; v1.2 ships with global count only.\n void namespace;\n return this.table.countRows();\n }\n\n async removeFacts(ids: ReadonlyArray<string>): Promise<void> {\n if (ids.length === 0) return;\n // Build a parameterized-style delete predicate. Lance's delete still\n // takes a string predicate, so we explicitly quote-escape each id —\n // ids in our system are content-hashed (alphanumeric), so the risk\n // is low, but we belt-and-suspenders.\n const escaped = ids.map((id) => `'${id.replace(/'/g, \"''\")}'`).join(\", \");\n await this.table.delete(`id IN (${escaped})`);\n }\n\n async close(): Promise<void> {\n // Lance auto-closes on GC; no explicit shutdown needed.\n }\n}\n\n/**\n * Escape a value for safe SQL string interpolation in Lance predicates.\n * Lance does not support bind parameters — string-quote escape is the\n * only injection-safe option. Standard SQL: replace single quotes with\n * doubled single quotes.\n *\n * @internal\n */\nfunction escapeSqlValue(value: string): string {\n // T5.2 — Harden SQL value escaping for Lance `.where()` predicates.\n // Pre-T5.2 this only escaped single quotes (`'` → `''`). T5.2 adds:\n // - NUL byte rejection (NUL truncates the string in some SQL engines)\n // - C0 control char rejection (prevents invisible payload injection)\n // - Backslash escaping (`\\` → `\\\\` — some engines interpret `\\'` as\n // a single-quote escape, bypassing the `''` defense)\n // Synced from sdk-core per ADR 0002 byte-equivalence (iter 115).\n // Reject NUL + C0/DEL control chars (T5.5 pattern adapted for SQL).\n for (let i = 0; i < value.length; i++) {\n const code = value.charCodeAt(i);\n if (code === 0x00 || (code >= 0x01 && code <= 0x1f) || code === 0x7f) {\n throw new ConfigurationError(\n `SQL filter value contains control character at position ${i} (0x${code.toString(16)}). ` +\n \"This may indicate an injection attempt.\",\n { code: \"sql_injection_blocked\" },\n );\n }\n }\n // Escape both single-quote and backslash.\n return value.replace(/\\\\/g, \"\\\\\\\\\").replace(/'/g, \"''\");\n}\n\n/**\n * Test helper for {@link LanceIndex}: indicates whether the Lance module\n * is loadable in the current environment. Allows tests to gracefully skip\n * when the optional dep is absent.\n *\n * @internal\n */\nexport function isLanceAvailable(): boolean {\n try {\n const r = createRequire(import.meta.url);\n r(\"@lancedb/lancedb\");\n return true;\n } catch {\n return false;\n }\n}\n\nvoid existsSync; // imported but only used conditionally via mkdirSync\n","/**\n * Common `MemoryIndex` interface shared between the SQLite-backed\n * `IndexManager` (default) and the Lance-backed adapter (ADR D43, shipped\n * v1.4.0 via lancedb-backend-ship-v1-1 plan).\n *\n * Consumers (`local-agent-memory.ts`, `active-memory.ts`, `tools.ts`,\n * `runActiveMemory`) only ever call `sync()`, `search()`, `status()`,\n * `close()` — the union of those four methods is the portable surface.\n *\n * Why a separate file (vs declaring inline in `index-manager.ts`)? D43\n * promised \"extract an abstract `MemoryIndex` interface in\n * `internal/memory/index-interface.ts`\". Keeping the contract physically\n * separated from one of its implementations preserves OCP — future\n * backends (Qdrant, PGVector) can land without touching IndexManager.\n *\n * Iter 50 (Stage 3 source-move #7): hybrid copy from sdk-core's\n * `internal/memory/memory-index.ts`. sdk-core retains its copy for v1.x\n * back-compat; sdk-memory ships the canonical copy that future\n * `index-manager`, `lance-memory-adapter`, and `active-memory` moves\n * will target as siblings.\n *\n * **Iter 50 side-effect:** by publicly re-exporting `MemorySearchHit`\n * via the sdk-memory barrel, this file creates the FIRST reachable\n * downstream consumer for `MemorySearchHit` inside sdk-memory's\n * graph. That unblocks the rollup-plugin-dts treeshake limitation\n * the iter 48 inline-duplicate workaround was guarding against —\n * `internal/active-memory-types.ts` can now re-import the canonical\n * `MemorySearchHit` from `./index-manager-contract.js` and drop its\n * inline mirror. Deletion of that workaround lands in this same iter.\n *\n * @internal\n */\n\nimport type { IndexStatus, MemorySearchHit, SearchOptions } from \"./index-manager-contract.js\";\n\n// NOTE: the canonical sdk-core copy re-exports\n// `IndexStatus`/`MemorySearchHit`/`SearchOptions` here for stable\n// internal import paths. In sdk-memory the public barrel already does\n// `export * from \"./internal/index-manager-contract.js\"` (iter 47),\n// so re-exporting them a second time from this file confuses\n// rollup-plugin-dts and triggers a \"is not defined\" emit error\n// (rollup#4860-class pattern). Internal sdk-memory consumers should\n// import these types directly from `./index-manager-contract.js`.\n\n/**\n * What one `sync()` did. `filesScanned` counts every markdown file discovered,\n * including the unchanged ones; `filesUpdated` counts only those whose content\n * hash moved. `chunksEmbedded` is 0 on an index with no embedding runtime, and\n * also on a hybrid index where every chunk already had a vector.\n */\nexport interface SyncResult {\n filesScanned: number;\n filesUpdated: number;\n chunksWritten: number;\n chunksEmbedded: number;\n}\n\n/**\n * Common search-options parser used by both `IndexManager.search` and\n * `LanceMemoryAdapter.search`. Returns the normalized cap + minimum-score\n * floor — eliminates jscpd duplication while keeping per-backend search\n * logic distinct.\n */\nexport function parseSearchOptions(options: SearchOptions = {}): {\n maxResults: number;\n minScore: number;\n} {\n return {\n maxResults: Math.max(1, options.maxResults ?? 10),\n minScore: options.minScore ?? 0,\n };\n}\n\n/**\n * The four operations both backends implement, and the type every consumer\n * should hold. `IndexManager.open` returns this rather than a concrete class\n * precisely so `backend: \"lance\"` can be swapped in without changing the caller.\n *\n * The two backends differ in what they can honour, and the differences are\n * visible in the results rather than in the types — see `sync` and `search`\n * below, and `LanceMemoryAdapter` for the full list.\n */\nexport interface MemoryIndex {\n /**\n * Walk the memory corpus + reindex changed files. Lance backend has no\n * markdown corpus to walk — its adapter returns zero counts (no-op) and\n * relies on explicit `addFact` calls instead.\n */\n sync(): Promise<SyncResult>;\n\n /**\n * Semantic + textual search over the indexed corpus. Both backends\n * return the same `MemorySearchHit[]` shape; Lance reports `textScore` as 0\n * on every hit, because it is vector-only and has no FTS5 layer.\n */\n search(query: string, options?: SearchOptions): Promise<MemorySearchHit[]>;\n\n /** Snapshot of the index health (backend type + counts). */\n status(): IndexStatus;\n\n /** Release native handles. Idempotent. */\n close(): Promise<void> | void;\n}\n","/**\n * `LanceMemoryAdapter` — wraps `LanceIndex` to expose the common\n * `MemoryIndex` interface (sync/search/status/close) so consumers of\n * `IndexManager.open({ backend: \"lance\" })` get a drop-in replacement\n * for the SQLite-backed `IndexManager`.\n *\n * Semantic deltas vs SQLite (documented so callers know what to expect):\n *\n * - `sync()` is a NO-OP. Lance is a pure vector store — there is no\n * markdown corpus to crawl. Returns zero counts. Consumers writing\n * facts use `LanceIndex.addFacts` directly (exposed via the index\n * object returned to advanced callers).\n * - `search()` performs vector-only retrieval. `MemorySearchHit.textScore`\n * is 0 on every hit (no FTS5 layer); `vectorScore === score`.\n * - `status()` always reports `backend: \"hybrid\"` — embedding is required\n * at open, so there is no text-only Lance index. Both counts are 0: the\n * Lance row count is only available asynchronously and `status()` is\n * synchronous, so callers needing a real count call\n * `unwrap().countFacts()`. Lance does not track file provenance per row,\n * so `filesIndexed` has nothing to report either way.\n *\n * Ships with the lancedb-backend-ship-v1-1 plan (close D12, supersede via\n * D43). v1.4.0 of `@theokit/sdk`.\n *\n * Iter 69 (Stage 3 source-move #26): hybrid copy from sdk-core's\n * `internal/memory/lance-memory-adapter.ts`. sdk-core retains its\n * copy for v1.x Lance back-compat; sdk-memory ships the canonical\n * copy that the future `index-manager-dispatch.ts` move will compose\n * with as a sibling. Dependency chain (all sibling, all moved):\n * - `IndexStatus`, `MemorySearchHit`, `SearchOptions` from\n * `./index-manager-contract.js` (moved iter 47)\n * - `LanceIndex` from `./lance-index.js` (moved iter 68)\n * - `MemoryIndex`, `parseSearchOptions`, `SyncResult` from\n * `./memory-index.js` (moved iter 50)\n *\n * @internal\n */\n\nimport type { IndexStatus, MemorySearchHit, SearchOptions } from \"./index-manager-contract.js\";\nimport { type MemoryIndex, parseSearchOptions, type SyncResult } from \"./memory-index.js\";\n\n/**\n * **Iter 69 rollup-plugin-dts workaround** (mirrors iter 48/53/55/66/67 pattern).\n * Importing `LanceIndex` from sibling `./lance-index.js` fails dts\n * emit with `\"LanceIndex\" is not exported by \"src/internal/lance-index.ts\"`\n * because rollup-dts treeshakes the class when it has no public\n * type reaching it transitively — even though the barrel `export *`\n * makes it publicly callable. Same class as iter 66/67's MemoryDb.\n *\n * Fix: inline a structural mirror of the minimal LanceIndex surface\n * the adapter actually uses (search + close + identity for unwrap()\n * via `inner === actual LanceIndex`). The mirror is purely a TYPE —\n * the runtime continues to receive the real LanceIndex instance\n * unchanged. When a future move surfaces LanceIndex through a\n * different publicly-reachable path, this mirror MUST be deleted +\n * the canonical type import restored.\n *\n * @internal\n */\ninterface LanceIndex {\n addFacts(\n facts: ReadonlyArray<{\n id: string;\n text: string;\n source: \"memory\" | \"sessions\" | \"wiki\";\n namespace: string;\n scope: string;\n user_id: string;\n timestamp: number;\n }>,\n ): Promise<void>;\n search(\n query: string,\n opts: {\n namespace: string;\n scope?: string;\n limit?: number;\n sources?: ReadonlyArray<\"memory\" | \"sessions\" | \"wiki\">;\n },\n ): Promise<\n ReadonlyArray<{\n id: string;\n text: string;\n source: \"memory\" | \"sessions\" | \"wiki\";\n namespace: string;\n scope: string;\n userId: string;\n score: number;\n }>\n >;\n countFacts(namespace: string): Promise<number>;\n removeFacts(ids: ReadonlyArray<string>): Promise<void>;\n close(): Promise<void>;\n}\n\n/**\n * Default namespace used when consumers call `search()` without specifying\n * one. The SQLite `IndexManager` does not surface namespace in its public\n * `search()` signature either — both backends therefore behave consistently\n * under the \"single-workspace, single-namespace\" assumption that v1.4 ships.\n *\n * v1.5 candidate: surface `namespace` in `SearchOptions` (additive — no\n * breaking change) so multi-tenant Lance consumers can scope queries.\n */\nconst DEFAULT_NAMESPACE = \"default\";\n\n/** Empty sync result — Lance has no corpus to walk. */\nconst EMPTY_SYNC_RESULT: SyncResult = Object.freeze({\n filesScanned: 0,\n filesUpdated: 0,\n chunksWritten: 0,\n chunksEmbedded: 0,\n});\n\n/**\n * Presents a `LanceIndex` as a {@link MemoryIndex}, so a consumer written\n * against the SQLite index runs unchanged on `backend: \"lance\"`.\n *\n * Choose it when the corpus is large enough that SQLite plus sqlite-vec is the\n * bottleneck and you are willing to feed the index yourself. Stay on the SQLite\n * default when you want the markdown corpus crawled for you, or text matching on\n * exact terms: this adapter's `sync()` does nothing and its `search()` is\n * vector-only, so a query that would have matched by keyword now has to match by\n * meaning.\n *\n * Requires `@lancedb/lancedb`, an optional peer dependency. It is loaded when\n * the index is opened, not here.\n *\n * Two behaviours are worth knowing before switching. Facts only enter the index\n * through `unwrap().addFacts(...)` — nothing else writes to it. And `search()`\n * always queries the `default` namespace, because `SearchOptions` has no\n * namespace field to pass through, so a multi-tenant caller must open one index\n * per tenant rather than relying on the filter.\n */\nexport class LanceMemoryAdapter implements MemoryIndex {\n constructor(private readonly inner: LanceIndex) {}\n\n /**\n * No-op for Lance — see file header. Returns zero counts so callers'\n * existing logging (`filesScanned: X`) does not break.\n */\n async sync(): Promise<SyncResult> {\n return EMPTY_SYNC_RESULT;\n }\n\n // jscpd:ignore-start — search signature + early-out is idiomatic\n // overlap with IndexManager.search; further factoring would hurt\n // readability (the bodies diverge sharply right after).\n async search(query: string, options: SearchOptions = {}): Promise<MemorySearchHit[]> {\n if (query.trim().length === 0) return [];\n const { maxResults, minScore } = parseSearchOptions(options);\n // jscpd:ignore-end\n const lanceHits = await this.inner.search(query, {\n namespace: DEFAULT_NAMESPACE,\n limit: maxResults * 2,\n ...(options.sources !== undefined ? { sources: options.sources } : {}),\n });\n return lanceHits\n .filter((h) => h.score >= minScore)\n .slice(0, maxResults)\n .map((h) => translateLanceHit(h));\n }\n\n status(): IndexStatus {\n // chunksIndexed via a synchronous best-effort — Lance API is async so\n // we surface zero here and document that consumers needing exact counts\n // should call `inner.countFacts()` directly.\n return {\n backend: \"hybrid\",\n filesIndexed: 0,\n chunksIndexed: 0,\n };\n }\n\n async close(): Promise<void> {\n await this.inner.close();\n }\n\n /**\n * Escape hatch for advanced callers (migration tool, benchmark script)\n * that need direct access to addFacts/countFacts/removeFacts.\n */\n unwrap(): LanceIndex {\n return this.inner;\n }\n}\n\n/**\n * Translate `LanceSearchHit` to `MemorySearchHit`. Field mapping:\n *\n * - `id` → `path` (Lance has no file-system provenance; use opaque id)\n * - `text` → `snippet` (truncated to 200 chars matching IndexManager convention)\n * - `score` → `score` AND `vectorScore` (Lance is vector-only)\n * - `source` → `source`\n * - synthetic `startLine: 0, endLine: 0` (Lance has no line info)\n * - synthetic `citation: id` (no path:line citation available)\n * - `textScore` set to 0 (Lance does NOT do FTS5)\n */\nfunction translateLanceHit(hit: {\n id: string;\n text: string;\n source: \"memory\" | \"sessions\" | \"wiki\";\n score: number;\n}): MemorySearchHit {\n return {\n path: hit.id,\n startLine: 0,\n endLine: 0,\n score: hit.score,\n textScore: 0,\n vectorScore: hit.score,\n snippet: hit.text.slice(0, 200),\n source: hit.source,\n citation: hit.id,\n };\n}\n","/**\n * Dispatch helpers for `IndexManager.open`. Extracted to keep\n * `index-manager.ts` under the G8 400-LoC budget (lancedb-backend-ship-v1-1).\n *\n * Iter 70 (Stage 3 source-move #27): hybrid copy from sdk-core's\n * `internal/memory/index-manager-dispatch.ts`. sdk-core retains\n * its copy for v1.x back-compat; sdk-memory ships the canonical\n * copy that the future `index-manager.ts` move will compose with\n * as a sibling. Dependency chain (all sibling, all moved):\n * - `@theokit/sdk/errors` for `ConfigurationError` (public)\n * - `./index-manager-contract.js` for `MemoryBackend` +\n * `OpenIndexOptions` (moved iter 47)\n * - `./lance-index.js` for `LanceIndex` (moved iter 68)\n * - `./lance-memory-adapter.js` for `LanceMemoryAdapter` (moved iter 69)\n * - `./memory-index.js` for `MemoryIndex` (moved iter 50)\n *\n * @internal\n */\n\nimport { ConfigurationError } from \"@theokit/sdk/errors\";\n\nimport type { MemoryBackend, OpenIndexOptions } from \"./index-manager-contract.js\";\nimport { LanceIndex } from \"./lance-index.js\";\nimport { LanceMemoryAdapter } from \"./lance-memory-adapter.js\";\nimport type { MemoryIndex } from \"./memory-index.js\";\n\n/** Valid backend identifiers — runtime guard against TS-narrowing escapes (EC-1). */\nexport const VALID_BACKENDS: readonly MemoryBackend[] = [\"sqlite-vec\", \"lance\"];\n\n/**\n * EC-1: runtime guard for `opts.backend`. TS union is compile-time only;\n * consumers passing JS `as any` typos must hit a typed error, not silent\n * SQLite fallback.\n */\nexport function assertValidBackend(backend: string): asserts backend is MemoryBackend {\n if (!VALID_BACKENDS.includes(backend as MemoryBackend)) {\n throw new ConfigurationError(\n `Invalid memory backend \"${backend}\". Valid values: ${VALID_BACKENDS.join(\", \")}.`,\n { code: \"invalid_memory_backend\" },\n );\n }\n}\n\n/**\n * Lance-path open. Throws `lance_requires_embedding` when no embedding\n * runtime is provided (Lance is vector-only — no FTS fallback).\n * Surfaces `lance_backend_unavailable` from LanceIndex.open when peer\n * dep is absent.\n */\nexport async function openLanceIndex(opts: OpenIndexOptions): Promise<MemoryIndex> {\n if (opts.embedding === undefined) {\n throw new ConfigurationError(\n \"Lance backend requires an embedding runtime. Pass `embedding: { provider, model, apiKey }` in Memory.create options (or omit `backend` to use SQLite default).\",\n { code: \"lance_requires_embedding\" },\n );\n }\n const lance = await LanceIndex.open({\n cwd: opts.cwd,\n embedding: opts.embedding,\n ...(opts.filePath !== undefined ? { storagePath: opts.filePath } : {}),\n });\n return new LanceMemoryAdapter(lance);\n}\n","import { ConfigurationError } from \"@theokit/sdk/errors\";\n\n/**\n * **Iter 66 rollup-plugin-dts workaround** (mirrors iter 48/53/55 pattern).\n * The canonical sdk-core copy imports `MemoryDb` from `./index-db.js`\n * (sibling). In sdk-memory the same interface lives in sibling\n * `./index-db.js` (moved iter 65) but rollup-plugin-dts treeshakes\n * it out of the bundled .d.ts emit because no PUBLIC type reaches it\n * transitively yet — sqlite-vec-loader's signatures would be the\n * first consumer BUT rollup-dts resolves the import BEFORE the\n * loader's exports are bundled into the public emit. Result:\n * \"MemoryDb is not exported by src/internal/index-db.ts\" build error.\n *\n * Fix: inline a structural mirror of the minimal MemoryDb shape that\n * sqlite-vec-loader actually needs (just `prepare` for the version\n * probe; everything else delegated via the loader's untyped\n * dynamic-import call to sqlite-vec's native `load`). Mirror is\n * narrower than the canonical contract on purpose — this file's\n * runtime never touches exec/close/pragma/loadExtension directly.\n * When a future move turns MemoryDb into a publicly-reachable type\n * through a different path (e.g. vec-index.ts surfacing the interface\n * from its own typed signatures), this mirror MUST be deleted +\n * the canonical import restored.\n *\n * @internal\n */\ninterface MemoryDb {\n exec(sql: string): void;\n prepare(sql: string): {\n run(...args: unknown[]): { changes: number; lastInsertRowid: number | bigint };\n get(...args: unknown[]): Record<string, unknown> | undefined;\n all(...args: unknown[]): Array<Record<string, unknown>>;\n };\n pragma(statement: string, options?: { simple?: boolean }): unknown;\n close(): void;\n loadExtension(path: string): void;\n}\n\n/**\n * Load the `sqlite-vec` extension into an opened SQLite connection.\n *\n * Wraps the native `load(db)` call from the `sqlite-vec` npm package with a\n * typed error path (EC-8 of the edge-case review) so callers see a\n * `sqlite_vec_unavailable` ConfigurationError instead of a raw native error.\n *\n * Iter 66 (Stage 3 source-move #23): hybrid copy from sdk-core's\n * `internal/memory/sqlite-vec-loader.ts`. sdk-core retains its copy\n * for v1.x sqlite-vec back-compat; sdk-memory ships the canonical\n * copy that future `vec-index.ts` move will compose with as a\n * sibling. Dependency chain (all resolved):\n * - `@theokit/sdk/errors` for `ConfigurationError` (public)\n * - sibling `./index-db.js` for `MemoryDb` (moved iter 65)\n *\n * @internal\n */\nexport async function loadSqliteVecExtension(db: MemoryDb): Promise<void> {\n try {\n const mod = await import(\"sqlite-vec\");\n const loadFn = (mod as { load?: (db: unknown) => void }).load;\n if (typeof loadFn !== \"function\") {\n throw new Error(\"sqlite-vec module exposes no `load` export\");\n }\n loadFn(db);\n } catch (cause) {\n const message = cause instanceof Error ? cause.message : String(cause);\n throw new ConfigurationError(\n `sqlite-vec extension unavailable. Install \\`sqlite-vec\\` and ensure the native binary matches your Node + OS. Cause: ${message}`,\n { code: \"sqlite_vec_unavailable\", cause },\n );\n }\n}\n\n/** Check whether sqlite-vec is loaded by running a tiny version query. */\nexport function isSqliteVecLoaded(db: MemoryDb): boolean {\n try {\n const row = db.prepare(\"SELECT vec_version() as v\").get();\n return row !== undefined && row.v !== undefined;\n } catch {\n return false;\n }\n}\n","import type { EmbeddingRuntime } from \"../embedding/embedding-adapter.js\";\n\n/**\n * **Iter 67 rollup-plugin-dts workaround** (mirrors iter 48/53/55/66 pattern).\n * The canonical sdk-core copy imports `MemoryDb` from sibling\n * `./index-db.js`. In sdk-memory the same interface lives in sibling\n * `./index-db.js` (moved iter 65) but rollup-dts treeshakes it\n * out of the bundled .d.ts emit because no PUBLIC type reaches it\n * transitively yet. Same pattern as iter 66 with sqlite-vec-loader.\n *\n * Fix: inline a structural mirror of the minimal MemoryDb shape this\n * file actually needs (exec + prepare for SQL emits, plus pragma /\n * close / loadExtension on the canonical surface to stay shape-compatible\n * with consumers passing the real MemoryDb). When a future move\n * surfaces MemoryDb through a different publicly-reachable path,\n * this mirror MUST be deleted + the canonical import restored.\n *\n * @internal\n */\ninterface MemoryDb {\n exec(sql: string): void;\n prepare(sql: string): {\n run(...args: unknown[]): { changes: number; lastInsertRowid: number | bigint };\n get(...args: unknown[]): Record<string, unknown> | undefined;\n all(...args: unknown[]): Array<Record<string, unknown>>;\n };\n pragma(statement: string, options?: { simple?: boolean }): unknown;\n close(): void;\n loadExtension(path: string): void;\n}\n\n// Vector index helpers (ADR D2 + D4 of memory-system-peer-project-parity).\n//\n// Embeddings live in `embeddings(chunk_id, vec)` — a `vec0` virtual table\n// provided by the sqlite-vec extension. Embedding identity (providerId +\n// model + dimension) lives in the `meta` table; mismatches force a full\n// re-embed sweep (EC-1).\n//\n// Iter 67 (Stage 3 source-move #24): hybrid copy from sdk-core's\n// `internal/memory/vec-index.ts`. sdk-core retains its copy for v1.x\n// sqlite-vec back-compat; sdk-memory ships the canonical copy that\n// future `index-manager.ts` move will compose with as a sibling.\n// Dependency chain (both sibling, both moved):\n// - `EmbeddingRuntime` from `./embedding-adapter.js` (moved iter 45)\n// - `MemoryDb` from `./index-db.js` (moved iter 65)\n\n/**\n * `meta` table key holding the id of the embedding provider that produced the\n * vectors currently on disk (for example `openai`, `ollama`).\n */\nexport const META_KEY_PROVIDER_ID = \"embedding.providerId\";\n/** `meta` table key holding the embedding model id the vectors were produced with. */\nexport const META_KEY_MODEL = \"embedding.model\";\n/** `meta` table key holding the vector width the `embeddings` vec0 table was created with. */\nexport const META_KEY_DIMENSION = \"embedding.dimension\";\n\n/**\n * The three facts that decide whether the vectors already stored are still\n * usable: who produced them, with which model, at which width. A change in any\n * of the three invalidates every vector in the index, because embeddings from\n * different models are not comparable and a different width will not even fit\n * the vec0 table.\n */\nexport interface EmbeddingIdentity {\n providerId: string;\n model: string;\n dimension: number;\n}\n\n/**\n * Read the embedding identity recorded in the `meta` table.\n *\n * Returns `undefined` when the index has never been embedded, and also when the\n * record is incomplete or unusable: any of the three keys missing, or a stored\n * dimension that is not a finite number greater than zero. Callers treat that as\n * \"no identity\" and write a fresh one rather than trying to repair it.\n */\nexport function readEmbeddingIdentity(db: MemoryDb): EmbeddingIdentity | undefined {\n const get = (key: string): string | undefined => {\n const row = db.prepare(\"SELECT value FROM meta WHERE key = ?\").get(key);\n return row !== undefined ? String(row.value) : undefined;\n };\n const providerId = get(META_KEY_PROVIDER_ID);\n const model = get(META_KEY_MODEL);\n const dimRaw = get(META_KEY_DIMENSION);\n if (providerId === undefined || model === undefined || dimRaw === undefined) return undefined;\n const dimension = Number(dimRaw);\n if (!Number.isFinite(dimension) || dimension <= 0) return undefined;\n return { providerId, model, dimension };\n}\n\n/**\n * Record the embedding identity in the `meta` table, upserting each of the three\n * keys. Call this after {@link createVectorIndex}, so that a later open can tell\n * whether the vectors on disk match the runtime it has been handed.\n */\nexport function writeEmbeddingIdentity(db: MemoryDb, identity: EmbeddingIdentity): void {\n const stmt = db.prepare(\n \"INSERT INTO meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value\",\n );\n stmt.run(META_KEY_PROVIDER_ID, identity.providerId);\n stmt.run(META_KEY_MODEL, identity.model);\n stmt.run(META_KEY_DIMENSION, String(identity.dimension));\n}\n\n/**\n * Compare two embedding identities field by field. All three fields must be\n * equal; there is no tolerance on dimension, because a mismatch there is a hard\n * failure at the vec0 table rather than a quality regression.\n */\nexport function identityMatches(a: EmbeddingIdentity, b: EmbeddingIdentity): boolean {\n return a.providerId === b.providerId && a.model === b.model && a.dimension === b.dimension;\n}\n\n/**\n * Drop the `embeddings` table, discarding every stored vector. `IndexManager`\n * calls this when {@link identityMatches} reports that the persisted identity\n * differs from the embedding runtime it was opened with; the next `sync()` then\n * re-embeds the whole corpus. The `chunks` and `files` tables are untouched, so\n * the text index survives the drop.\n */\nexport function dropVectorIndex(db: MemoryDb): void {\n db.exec(\"DROP TABLE IF EXISTS embeddings\");\n}\n\n/**\n * Create the `embeddings` vec0 virtual table at the given vector width, if it\n * does not exist already. Requires the sqlite-vec extension to be loaded into\n * `db` first (see `loadSqliteVecExtension`) — without it SQLite has no `vec0`\n * module and the statement fails.\n *\n * `IF NOT EXISTS` means this will NOT widen an existing table: to change the\n * dimension, call {@link dropVectorIndex} first.\n */\nexport function createVectorIndex(db: MemoryDb, dimension: number): void {\n db.exec(`CREATE VIRTUAL TABLE IF NOT EXISTS embeddings USING vec0(\n chunk_id INTEGER PRIMARY KEY,\n vec FLOAT[${dimension}]\n )`);\n}\n\n/** Pack a Float32Array into a Buffer suitable for sqlite-vec BLOB binding. */\nexport function packVector(vec: ReadonlyArray<number>): Buffer {\n const f32 = new Float32Array(vec.length);\n for (let i = 0; i < vec.length; i++) f32[i] = vec[i] ?? 0;\n return Buffer.from(f32.buffer);\n}\n\n/**\n * Store the vector for one chunk, replacing any vector already held for it.\n *\n * Implemented as DELETE followed by INSERT because vec0 virtual tables do not\n * support `ON CONFLICT`. The chunk id is bound as a BigInt: vec0 v0.1.9 rejects\n * a JavaScript number for its primary-key column.\n */\nexport function upsertEmbedding(db: MemoryDb, chunkId: number, vec: ReadonlyArray<number>): void {\n // sqlite-vec vec0 virtual tables don't support UPSERT — emulate via\n // DELETE-then-INSERT. vec0 REJECTS JS Number for chunk_id columns; it\n // requires BigInt binding. Verified via repro against vec0 v0.1.9.\n const id = BigInt(chunkId);\n db.prepare(\"DELETE FROM embeddings WHERE chunk_id = ?\").run(id);\n db.prepare(\"INSERT INTO embeddings (chunk_id, vec) VALUES (?, ?)\").run(id, packVector(vec));\n}\n\n/**\n * One row of a vec0 KNN result: the chunk id and its raw distance from the query\n * vector. Distance is the sqlite-vec convention — lower is closer — and is NOT a\n * similarity score. `IndexManager` maps it to `1 / (1 + distance)` before\n * blending it with the text score.\n */\nexport interface VectorHitRow {\n chunk_id: number;\n distance: number;\n}\n\n/**\n * Run a k-nearest-neighbour query against the `embeddings` table and return the\n * matches ordered by ascending distance (closest first).\n *\n * `query` must have the same width the table was created with. Both the query\n * vector and `k` are bound in the form vec0 expects — the vector as a packed\n * Float32 blob, `k` as a BigInt.\n */\nexport function vectorSearch(\n db: MemoryDb,\n query: ReadonlyArray<number>,\n k: number,\n): VectorHitRow[] {\n // sqlite-vec returns distance (lower = closer). Use KNN syntax. k needs\n // a BigInt-typed binding too.\n const rows = db\n .prepare(\n `SELECT chunk_id, distance FROM embeddings\n WHERE vec MATCH ? AND k = ?\n ORDER BY distance`,\n )\n .all(packVector(query), BigInt(k));\n return rows.map((row) => ({ chunk_id: Number(row.chunk_id), distance: Number(row.distance) }));\n}\n\n/** Inputs for {@link embedMissingChunks}: the open database and the embedding runtime to call. */\nexport interface EmbedAllArgs {\n db: MemoryDb;\n runtime: EmbeddingRuntime;\n}\n\n/** Embed every chunk that doesn't yet have a vector. */\nexport async function embedMissingChunks(args: EmbedAllArgs): Promise<number> {\n const rows = args.db\n .prepare(\n `SELECT chunks.id as id, chunks.text as text\n FROM chunks\n LEFT JOIN embeddings ON embeddings.chunk_id = chunks.id\n WHERE embeddings.chunk_id IS NULL`,\n )\n .all();\n if (rows.length === 0) return 0;\n const normalized = rows.map((row) => ({ id: Number(row.id), text: String(row.text ?? \"\") }));\n const vectors = await args.runtime.embed(normalized.map((r) => r.text));\n for (let i = 0; i < normalized.length; i++) {\n const row = normalized[i];\n const vector = vectors[i];\n if (row === undefined || vector === undefined) continue;\n upsertEmbedding(args.db, row.id, vector);\n }\n return normalized.length;\n}\n","import { createHash } from \"node:crypto\";\nimport { readFile, stat } from \"node:fs/promises\";\n\nimport { sanitizeFts5Query } from \"@theokit/sdk/persistence\";\nimport type { EmbeddingRuntime } from \"../embedding/embedding-adapter.js\";\nimport { chunkMarkdown } from \"../store/chunk-markdown.js\";\nimport {\n collectMarkdownFiles,\n defaultIndexPath,\n type MemoryRoot,\n projectMemoryDir,\n resolveMemoryRoot,\n} from \"../store/markdown-store.js\";\nimport { type MemoryDb, openMemoryDb } from \"./index-db.js\";\nimport { assertValidBackend, openLanceIndex } from \"./index-manager-dispatch.js\";\nimport { type MemoryIndex, parseSearchOptions } from \"./memory-index.js\";\nimport { loadSqliteVecExtension } from \"./sqlite-vec-loader.js\";\nimport {\n createVectorIndex,\n dropVectorIndex,\n embedMissingChunks,\n identityMatches,\n readEmbeddingIdentity,\n vectorSearch,\n writeEmbeddingIdentity,\n} from \"./vec-index.js\";\n\n/**\n * Memory index manager (ADR D2). FTS5-only at Phase 3; vector index lands in\n * Phase 5.\n *\n * Lifecycle:\n * const idx = await IndexManager.open({ cwd });\n * await idx.sync();\n * const hits = await idx.search(\"query\");\n * idx.close();\n *\n * Iter 72 (Stage 3 source-move #29): hybrid copy from sdk-core's\n * `internal/memory/index-manager.ts`. sdk-core retains its copy for\n * v1.x back-compat; sdk-memory ships the canonical orchestrator\n * composing every prior Stage 3 move (sqlite-vec stack iter 47/49/50/53/55-57/62/65-67,\n * lance stack iter 68-70, storage iter 56). The biggest move of the\n * stage at 446 LOC — closes the index/ cluster.\n *\n * @internal\n */\n\n// T2.1 / ADR D433 — these types live in `index-manager-contract.ts`\n// (iter 47). The canonical sdk-core copy re-exports them here for\n// back-compat. In sdk-memory the public barrel already does\n// `export * from \"./internal/index-manager-contract.js\"` so a second\n// re-export from this file confuses rollup-dts and triggers\n// \"is not exported\" emit errors. Mirrors iter 50 memory-index NOTE.\n//\n// **Iter 72 rollup-plugin-dts workaround** (mirrors iter 48/53/55/66/67/69):\n// the canonical sdk-core copy imports `MemorySearchHit` (et al.) from\n// sibling. rollup-dts treeshakes the inner type declarations because\n// no PUBLIC type reaches them transitively yet within this file's\n// bundling pass. Fix: declare structural mirrors of the index-manager-contract\n// types inline so the index-manager.ts file's emit is self-contained.\n// When a future move surfaces these through a different\n// publicly-reachable path, these mirrors MUST be deleted + the\n// canonical type imports restored.\n\ninterface MemorySearchHit {\n readonly path: string;\n readonly startLine: number;\n readonly endLine: number;\n readonly score: number;\n readonly textScore: number;\n readonly vectorScore?: number;\n readonly snippet: string;\n readonly source: \"memory\" | \"sessions\" | \"wiki\";\n readonly citation: string;\n}\n\ninterface IndexStatus {\n backend: \"fts-only\" | \"hybrid\";\n filesIndexed: number;\n chunksIndexed: number;\n lastSyncMs?: number;\n}\n\ninterface SearchOptions {\n maxResults?: number;\n minScore?: number;\n vectorWeight?: number;\n textWeight?: number;\n sources?: ReadonlyArray<\"memory\" | \"sessions\" | \"wiki\">;\n}\n\ninterface OpenIndexOptions {\n cwd: string;\n /**\n * The memory root to index and to place the database under. Defaults to `<cwd>/.theokit/memory`.\n *\n * Optional here and required below: this is the entry point a caller reaches with a workspace in\n * hand, while every path helper under it demands a resolved root (#463).\n */\n memoryRoot?: MemoryRoot;\n filePath?: string;\n embedding?: EmbeddingRuntime;\n backend?: \"sqlite-vec\" | \"lance\";\n}\n\n/**\n * The default memory index: SQLite for storage, FTS5 for text matching, and\n * sqlite-vec for vectors when an embedding runtime is supplied.\n *\n * Open it with the static `open`, which is also the dispatch point for\n * `backend: \"lance\"` — that overload returns a `LanceMemoryAdapter`, not an\n * `IndexManager`, so hold the result as {@link MemoryIndex} unless you need this\n * class specifically.\n *\n * Storage needs `better-sqlite3` unless the running Node exposes `node:sqlite`,\n * and vectors additionally need `sqlite-vec`. Both are optional peer\n * dependencies of this package. Without an embedding runtime the index opens\n * text-only and reports `backend: \"fts-only\"`; no vector table is created and\n * search degrades to BM25 rather than failing.\n *\n * `sync()` crawls the markdown corpus — `MEMORY.md`, `notes/`, `wiki/` and\n * `sessions/` — skipping files whose content hash has not moved, and re-chunking\n * the rest. Nothing is indexed until it runs.\n *\n * If the embedding provider, model or dimension differs from what the database\n * recorded, opening drops the whole vector table so the next `sync()` re-embeds\n * from scratch. Switching embedding models is therefore safe but not cheap.\n *\n * `search()` runs both halves and blends them per chunk, so a chunk found only\n * by vector still appears with a text score of 0 and the other way round.\n * `close()` releases the database handle; it is synchronous here, unlike the\n * Lance adapter's, so a caller holding the {@link MemoryIndex} type must await\n * it either way.\n */\nexport class IndexManager implements MemoryIndex {\n private lastSyncMs: number | undefined;\n private vectorReady = false;\n\n private constructor(\n private readonly memoryRoot: MemoryRoot,\n private readonly db: MemoryDb,\n private readonly embedding: EmbeddingRuntime | undefined,\n ) {}\n\n /**\n * Open a memory index. Dispatches to SQLite (default) or Lance (opt-in\n * via `backend: \"lance\"`). See `openLanceIndex` for Lance-specific\n * preconditions + typed errors.\n */\n static async open(opts: OpenIndexOptions & { backend: \"lance\" }): Promise<MemoryIndex>;\n static async open(\n opts: Omit<OpenIndexOptions, \"backend\"> | (OpenIndexOptions & { backend?: \"sqlite-vec\" }),\n ): Promise<IndexManager>;\n static async open(opts: OpenIndexOptions): Promise<MemoryIndex> {\n const backend = opts.backend ?? \"sqlite-vec\";\n assertValidBackend(backend);\n if (backend === \"lance\") return await openLanceIndex(opts);\n return await IndexManager.openSqliteInternal(opts);\n }\n\n /** Internal SQLite-path open. Renamed from previous public `open`. */\n private static async openSqliteInternal(opts: OpenIndexOptions): Promise<IndexManager> {\n const memoryRoot = opts.memoryRoot ?? resolveMemoryRoot(opts.cwd);\n // Corpus and database diverge on purpose — see `defaultIndexPath` for why (#463).\n const filePath = opts.filePath ?? defaultIndexPath(projectMemoryDir(opts.cwd));\n const db = await openMemoryDb({ filePath });\n const manager = new IndexManager(memoryRoot, db, opts.embedding);\n if (opts.embedding !== undefined) await manager.initVectorBackend(opts.embedding);\n return manager;\n }\n\n private async initVectorBackend(runtime: EmbeddingRuntime): Promise<void> {\n await loadSqliteVecExtension(this.db);\n const currentIdentity = {\n providerId: runtime.id,\n model: runtime.model,\n dimension: runtime.dimension,\n };\n const persisted = readEmbeddingIdentity(this.db);\n if (persisted !== undefined && !identityMatches(persisted, currentIdentity)) {\n // EC-1: dimension/model/provider changed — drop the vector index and\n // force a full re-embed on next sync.\n dropVectorIndex(this.db);\n }\n createVectorIndex(this.db, runtime.dimension);\n writeEmbeddingIdentity(this.db, currentIdentity);\n this.vectorReady = true;\n }\n\n /** Walk the memory corpus + (re)index changed files. */\n async sync(): Promise<{\n filesScanned: number;\n filesUpdated: number;\n chunksWritten: number;\n chunksEmbedded: number;\n }> {\n const files = await collectMarkdownFiles(this.memoryRoot);\n let filesUpdated = 0;\n let chunksWritten = 0;\n const existingByPath = this.loadFilesIndex();\n for (const entry of files) {\n const raw = await readFile(entry.absolutePath, \"utf8\");\n const hash = sha256(raw);\n const existing = existingByPath.get(entry.absolutePath);\n if (existing !== undefined && existing.hash === hash) continue;\n const stats = await stat(entry.absolutePath);\n const fileId = this.upsertFile(\n entry.absolutePath,\n entry.relPath,\n hash,\n stats.mtimeMs,\n entry.source,\n );\n this.deleteChunksForFile(fileId);\n const chunks = chunkMarkdown(raw);\n for (const chunk of chunks) {\n this.insertChunk(fileId, chunk.startLine, chunk.endLine, chunk.text, chunk.hash);\n }\n filesUpdated += 1;\n chunksWritten += chunks.length;\n }\n let chunksEmbedded = 0;\n if (this.vectorReady && this.embedding !== undefined) {\n chunksEmbedded = await embedMissingChunks({ db: this.db, runtime: this.embedding });\n }\n this.lastSyncMs = Date.now();\n return { filesScanned: files.length, filesUpdated, chunksWritten, chunksEmbedded };\n }\n\n async search(query: string, options: SearchOptions = {}): Promise<MemorySearchHit[]> {\n if (query.trim().length === 0) return [];\n const { maxResults, minScore } = parseSearchOptions(options);\n const textHits = this.ftsSearch(query, maxResults * 2);\n const vectorHitsById = await this.vectorSearchById(query, maxResults * 2);\n const combined = this.combineHybridScores(textHits, vectorHitsById, options);\n return combined\n .filter((h) => h.score >= minScore)\n .filter((h) => options.sources === undefined || options.sources.includes(h.source))\n .slice(0, maxResults);\n }\n\n status(): IndexStatus {\n const files = this.db.prepare(\"SELECT COUNT(*) as n FROM files\").get() ?? { n: 0 };\n const chunks = this.db.prepare(\"SELECT COUNT(*) as n FROM chunks\").get() ?? { n: 0 };\n const status: IndexStatus = {\n backend: this.vectorReady ? \"hybrid\" : \"fts-only\",\n filesIndexed: Number(files.n ?? 0),\n chunksIndexed: Number(chunks.n ?? 0),\n };\n if (this.lastSyncMs !== undefined) status.lastSyncMs = this.lastSyncMs;\n return status;\n }\n\n // ───── search internals ──────────────────────────────────────────────\n\n private ftsSearch(query: string, limit: number): Array<MemorySearchHit & { chunkId: number }> {\n // EC-3: short-circuit when sanitizer reduces input to empty string.\n // Calling `MATCH ''` would error inside FTS5 on some SQLite versions.\n const sanitized = sanitizeFts5Query(query);\n if (sanitized.length === 0) return [];\n const stmt = this.db.prepare(\n `SELECT chunks.id as id, files.rel_path as rel_path, files.source as source,\n chunks.start_line as start_line, chunks.end_line as end_line,\n chunks.text as text, bm25(chunks_fts) as bm25_score\n FROM chunks_fts\n JOIN chunks ON chunks_fts.rowid = chunks.id\n JOIN files ON chunks.file_id = files.id\n WHERE chunks_fts MATCH ?\n ORDER BY bm25_score\n LIMIT ?`,\n );\n let rows: Array<Record<string, unknown>> = [];\n try {\n rows = stmt.all(sanitized, limit);\n } catch {\n return [];\n }\n return rows.map((row) => {\n const bm25 = Number(row.bm25_score ?? 0);\n const textScore = bm25 < 0 ? 1 / (1 + Math.abs(bm25)) : 1 / (1 + bm25);\n const startLine = Number(row.start_line ?? 0);\n const endLine = Number(row.end_line ?? 0);\n const path = String(row.rel_path);\n return {\n path,\n startLine,\n endLine,\n score: textScore,\n textScore,\n snippet: truncateSnippet(String(row.text ?? \"\")),\n source: String(row.source) as \"memory\" | \"sessions\" | \"wiki\",\n citation: `${path}:${startLine}-${endLine}`,\n // sneak the chunk id through for the hybrid join below\n // (cast away later)\n chunkId: Number(row.id),\n } as MemorySearchHit & { chunkId: number };\n });\n }\n\n private async vectorSearchById(\n query: string,\n limit: number,\n ): Promise<Map<number, { vectorScore: number; snippet?: string }>> {\n if (!this.vectorReady || this.embedding === undefined) return new Map();\n const [queryVec] = await this.embedding.embed([query]);\n if (queryVec === undefined) return new Map();\n const rows = vectorSearch(this.db, queryVec, limit);\n // sqlite-vec distance: lower = closer. Normalize to 0..1 with higher = better.\n const out = new Map<number, { vectorScore: number }>();\n for (const row of rows) {\n const score = 1 / (1 + Math.max(0, row.distance));\n out.set(row.chunk_id, { vectorScore: score });\n }\n return out;\n }\n\n private combineHybridScores(\n textHits: Array<MemorySearchHit & { chunkId: number }>,\n vectorHitsById: Map<number, { vectorScore: number }>,\n options: SearchOptions,\n ): MemorySearchHit[] {\n const weights = resolveWeights(options);\n const merged = this.mergeHits(textHits, vectorHitsById);\n const combined = [...merged.values()].map((hit) =>\n blendScores(hit, vectorHitsById.get(hit.chunkId)?.vectorScore ?? 0, weights),\n );\n return combined.sort((a, b) => b.score - a.score);\n }\n\n private mergeHits(\n textHits: Array<MemorySearchHit & { chunkId: number }>,\n vectorHitsById: Map<number, { vectorScore: number }>,\n ): Map<number, MemorySearchHit & { chunkId: number }> {\n const merged = new Map<number, MemorySearchHit & { chunkId: number }>();\n for (const hit of textHits) merged.set(hit.chunkId, hit);\n const missingIds = [...vectorHitsById.keys()].filter((id) => !merged.has(id));\n if (missingIds.length > 0) {\n for (const hit of this.fetchChunksByIds(missingIds)) {\n merged.set(hit.chunkId, { ...hit, score: 0, textScore: 0 });\n }\n }\n return merged;\n }\n\n private fetchChunksByIds(\n ids: ReadonlyArray<number>,\n ): Array<MemorySearchHit & { chunkId: number }> {\n if (ids.length === 0) return [];\n const placeholders = ids.map(() => \"?\").join(\",\");\n const rows = this.db\n .prepare(\n `SELECT chunks.id as id, files.rel_path as rel_path, files.source as source,\n chunks.start_line as start_line, chunks.end_line as end_line,\n chunks.text as text\n FROM chunks JOIN files ON chunks.file_id = files.id\n WHERE chunks.id IN (${placeholders})`,\n )\n .all(...ids);\n return rows.map((row) => {\n const startLine = Number(row.start_line ?? 0);\n const endLine = Number(row.end_line ?? 0);\n const path = String(row.rel_path);\n return {\n chunkId: Number(row.id),\n path,\n startLine,\n endLine,\n score: 0,\n textScore: 0,\n snippet: truncateSnippet(String(row.text ?? \"\")),\n source: String(row.source) as \"memory\" | \"sessions\" | \"wiki\",\n citation: `${path}:${startLine}-${endLine}`,\n };\n });\n }\n\n // ───── persistence helpers ─────────────────────────────────────────\n\n private loadFilesIndex(): Map<string, { id: number; hash: string }> {\n const rows = this.db.prepare(\"SELECT id, path, hash FROM files\").all() as Array<{\n id: number;\n path: string;\n hash: string;\n }>;\n return new Map(rows.map((row) => [row.path, { id: row.id, hash: row.hash }]));\n }\n\n private upsertFile(\n absPath: string,\n relPath: string,\n hash: string,\n mtimeMs: number,\n source: \"memory\" | \"wiki\" | \"sessions\" = \"memory\",\n ): number {\n const stmt = this.db.prepare(\n `INSERT INTO files (path, rel_path, mtime, hash, source) VALUES (?, ?, ?, ?, ?)\n ON CONFLICT(path) DO UPDATE SET hash = excluded.hash, mtime = excluded.mtime, source = excluded.source\n RETURNING id`,\n );\n const row = stmt.get(absPath, relPath, Math.floor(mtimeMs), hash, source) as { id: number };\n return row.id;\n }\n\n private deleteChunksForFile(fileId: number): void {\n this.db.prepare(\"DELETE FROM chunks WHERE file_id = ?\").run(fileId);\n }\n\n private insertChunk(\n fileId: number,\n startLine: number,\n endLine: number,\n text: string,\n hash: string,\n ): void {\n this.db\n .prepare(\n \"INSERT INTO chunks (file_id, start_line, end_line, text, hash) VALUES (?, ?, ?, ?, ?)\",\n )\n .run(fileId, startLine, endLine, text, hash);\n }\n\n close(): void {\n this.db.close();\n }\n}\n\n// ───── module-level helpers (hybrid scoring) ─────────────────────────────\n\ninterface HybridWeights {\n vectorWeight: number;\n textWeight: number;\n total: number;\n}\n\nfunction resolveWeights(options: SearchOptions): HybridWeights {\n const vectorWeight = options.vectorWeight ?? 0.6;\n const textWeight = options.textWeight ?? 0.4;\n const total = vectorWeight + textWeight || 1;\n return { vectorWeight, textWeight, total };\n}\n\nfunction blendScores(\n hit: MemorySearchHit & { chunkId: number },\n vectorScore: number,\n weights: HybridWeights,\n): MemorySearchHit {\n const score =\n (vectorScore * weights.vectorWeight + hit.textScore * weights.textWeight) / weights.total;\n return {\n path: hit.path,\n startLine: hit.startLine,\n endLine: hit.endLine,\n score,\n textScore: hit.textScore,\n snippet: hit.snippet,\n source: hit.source,\n citation: hit.citation,\n ...(vectorScore > 0 ? { vectorScore } : {}),\n };\n}\n\nfunction sha256(text: string): string {\n return createHash(\"sha256\").update(text).digest(\"hex\");\n}\n\nfunction truncateSnippet(text: string): string {\n const max = 500;\n return text.length <= max ? text : `${text.slice(0, max)}…`;\n}\n\n// Replaced by `sanitizeFts5Query` from `@theokit/sdk/persistence`\n// (T5.2, ADR D64). The new sanitizer is the 6-step port of Hermes'\n// `_sanitize_fts5_query` and handles hyphens/dots/underscores correctly\n// without quoting every token.\n","import { existsSync, mkdirSync, renameSync, rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { ConfigurationError } from \"@theokit/sdk/errors\";\nimport { redactSecrets } from \"../memory-types.js\";\nimport {\n lanceStoragePath,\n readAllSqliteFacts,\n resolveMemoryRoot,\n} from \"../store/markdown-store.js\";\nimport { LanceIndex } from \"./lance-index.js\";\n\n/**\n * Migrate Memory.index from SQLite to LanceDB (ADR D44).\n *\n * EC-3 MUST FIX: validation uses NFC unicode normalization on both sides.\n *\n * Iter 71 (Stage 3 source-move #28): hybrid copy from sdk-core's\n * `internal/memory/migrate-sqlite-to-lance.ts`. sdk-core retains its\n * copy for v1.x migration back-compat; sdk-memory ships the canonical\n * copy.\n *\n * Dependency chain (all resolved):\n * - `@theokit/sdk/errors` for `ConfigurationError` (public)\n * - sibling `./memory-types.js` for `redactSecrets` (moved iter 52)\n * - sibling `./index-db.js` for `defaultIndexPath` + `openMemoryDb` (moved iter 65)\n * - sibling `./lance-index.js` for `LanceIndex` + `lanceStoragePath` (moved iter 68)\n *\n * @internal\n */\n\nexport interface MigrateOptions {\n cwd: string;\n /**\n * Absolute path (or `~/`-prefixed) of the memory root to migrate, when the agent that wrote it\n * set `memory.directory`. Defaults to `<cwd>/.theokit/memory` (#463).\n */\n directory?: string;\n dryRun?: boolean;\n batchSize?: number;\n /** Inject for tests; defaults to console.log. */\n logger?: (msg: string) => void;\n}\n\n/**\n * Outcome of {@link migrateSqliteToLance}.\n *\n * Read `committed` first: it is `false` for a dry run and for a failed\n * validation, and only `true` when the staging directory was promoted to\n * `lance/`. `validated` reports whether the counts matched and the sampled facts\n * compared equal; `sampleComparisons` holds up to ten of those comparisons so a\n * failure can be inspected rather than merely counted.\n *\n * The SQLite database is left in place either way — this migration copies, it\n * does not move.\n */\nexport interface MigrateResult {\n countSqlite: number;\n countLance: number;\n /** Set when validation succeeded (or dryRun); false on validation failure. */\n validated: boolean;\n /** Per-fact compare results (size = sample count, up to 10). */\n sampleComparisons: ReadonlyArray<{ id: string; match: boolean }>;\n /** Lance storage location (final, after migration). */\n lancePath: string;\n /** Was the migration committed (false for dry-run). */\n committed: boolean;\n}\n\n/**\n * Compare two strings via NFC normalization (EC-3 MUST FIX). Required\n * because SQLite/Lance native bindings can normalize unicode differently\n * (NFC vs NFD), producing false negatives on facts with accents/emojis.\n *\n * @internal\n */\nfunction nfcEqual(a: string, b: string): boolean {\n return a.normalize(\"NFC\") === b.normalize(\"NFC\");\n}\n\n/**\n * Run the migration. Writes Lance to `<cwd>/.theokit/memory/lance-new/`\n * first, validates round-trip, then renames to `lance/` on success.\n * SQLite db is preserved (CLI prompts user to delete).\n *\n * @internal\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: migration is a single transaction (read → write → validate → commit-or-rollback); splitting harms atomicity reasoning.\nexport async function migrateSqliteToLance(opts: MigrateOptions): Promise<MigrateResult> {\n const cwd = opts.cwd;\n // One resolution, reused by every path this migration touches (#463).\n const memoryRoot = resolveMemoryRoot(cwd, { directory: opts.directory });\n const finalPath = lanceStoragePath(memoryRoot);\n const newPath = join(memoryRoot, \"lance-new\");\n // T1.4 (ADR D68): wrap logger so any fact text containing secrets is\n // masked before reaching the destination (console or user-supplied sink).\n // Caller-supplied loggers cannot bypass — by design (D70).\n const rawLog = opts.logger ?? ((m: string) => console.log(m));\n const log = (m: string) => rawLog(redactSecrets(m));\n\n // EC: destination exists → typed error.\n if (existsSync(finalPath)) {\n throw new ConfigurationError(\n `Destination already exists: ${finalPath}. Remove it manually (\\`rm -rf ${finalPath}\\`) and re-run.`,\n { code: \"migration_destination_exists\" },\n );\n }\n if (existsSync(newPath)) {\n // Leftover from a previous failed/interrupted migration. Safe to delete.\n log(`Removing stale ${newPath} from a previous run...`);\n rmSync(newPath, { recursive: true, force: true });\n }\n\n log(`Reading SQLite facts from ${cwd}/.theokit/memory/index.sqlite ...`);\n const sqliteFacts = await readAllSqliteFacts(memoryRoot);\n log(`SQLite has ${sqliteFacts.length} facts.`);\n if (sqliteFacts.length === 0) {\n return {\n countSqlite: 0,\n countLance: 0,\n validated: true,\n sampleComparisons: [],\n lancePath: finalPath,\n committed: false,\n };\n }\n\n // Reuse the embedding runtime configured in the workspace? For v1.2 we\n // require the caller to pass embedding explicitly via env. The migration\n // path is documented as: \"set OPENAI_API_KEY (or similar) before running.\"\n // Here we ship a placeholder embedder that uses a deterministic\n // content-hash — sufficient for migration validation; consumers should\n // re-embed on first real query after migration if needed.\n const placeholderEmbedding = {\n id: \"migration-placeholder\",\n model: \"deterministic-hash\",\n dimension: 8,\n embed: async (texts: ReadonlyArray<string>) => {\n // Simple deterministic hash → 8-dim vector (migration validation only).\n return texts.map((t) => {\n const arr = new Array(8).fill(0);\n for (let i = 0; i < t.length; i += 1) {\n arr[i % 8] += t.charCodeAt(i);\n }\n return arr.map((x) => x / 1000);\n });\n },\n stats: () => ({ cacheHits: 0, cacheMisses: 0, httpCalls: 0, retries: 0 }),\n };\n\n mkdirSync(newPath, { recursive: true });\n log(`Writing Lance index to ${newPath} ...`);\n\n const lance = await LanceIndex.open({\n cwd,\n embedding: placeholderEmbedding,\n storagePath: newPath,\n });\n\n const batchSize = opts.batchSize ?? 100;\n for (let i = 0; i < sqliteFacts.length; i += batchSize) {\n const batch = sqliteFacts.slice(i, i + batchSize).map((f) => ({\n id: f.id,\n text: f.text,\n source: f.source,\n namespace: f.namespace ?? \"default\",\n scope: f.scope ?? \"agent\",\n user_id: f.user_id ?? \"default\",\n timestamp: 0,\n }));\n await lance.addFacts(batch);\n log(` Migrated ${Math.min(i + batchSize, sqliteFacts.length)}/${sqliteFacts.length}`);\n }\n\n // Validation: count + sample compare (10 random) with NFC normalization.\n const lanceCount = await lance.countFacts(\"default\");\n log(`Lance has ${lanceCount} facts (expected ${sqliteFacts.length}).`);\n\n const sampleSize = Math.min(10, sqliteFacts.length);\n const sampleComparisons: { id: string; match: boolean }[] = [];\n for (let i = 0; i < sampleSize; i += 1) {\n const sqliteFact = sqliteFacts[Math.floor((i * sqliteFacts.length) / sampleSize)];\n if (sqliteFact === undefined) continue;\n // Search Lance for this fact's text — best-effort round-trip.\n const hits = await lance.search(sqliteFact.text, {\n namespace: sqliteFact.namespace ?? \"default\",\n limit: 1,\n });\n // EC-3: compare with NFC normalization.\n const hit = hits[0];\n const match = hit !== undefined && nfcEqual(hit.text, sqliteFact.text);\n sampleComparisons.push({ id: sqliteFact.id, match });\n }\n\n const allMatch = sampleComparisons.every((c) => c.match);\n const countMatch = lanceCount === sqliteFacts.length;\n const validated = allMatch && countMatch;\n\n await lance.close();\n\n if (opts.dryRun === true) {\n log(\"Dry-run mode — discarding Lance staging dir.\");\n rmSync(newPath, { recursive: true, force: true });\n return {\n countSqlite: sqliteFacts.length,\n countLance: lanceCount,\n validated,\n sampleComparisons,\n lancePath: finalPath,\n committed: false,\n };\n }\n\n if (!validated) {\n log(\"Validation FAILED — leaving SQLite intact, removing Lance staging dir.\");\n rmSync(newPath, { recursive: true, force: true });\n return {\n countSqlite: sqliteFacts.length,\n countLance: lanceCount,\n validated: false,\n sampleComparisons,\n lancePath: finalPath,\n committed: false,\n };\n }\n\n // Atomic commit via rename.\n renameSync(newPath, finalPath);\n log(`Migration committed to ${finalPath}.`);\n return {\n countSqlite: sqliteFacts.length,\n countLance: lanceCount,\n validated: true,\n sampleComparisons,\n lancePath: finalPath,\n committed: true,\n };\n}\n","import { access, readFile, unlink } from \"node:fs/promises\";\nimport { legacyMemoryJsonPath, type MemoryConfig, type MemoryFact } from \"../memory-types.js\";\nimport { appendFactToMarkdown, memoryMdPath, resolveMemoryRoot } from \"../store/markdown-store.js\";\n\n/**\n * One-shot legacy-JSON → markdown migration (ADR D8 of memory-system-peer-project-parity).\n *\n * Triggers when `.theokit/memory/<namespace>/<scope>-<userId>.json` exists AND\n * `.theokit/memory/MEMORY.md` does not. Reads the JSON facts, writes each\n * bullet to MEMORY.md, then deletes the JSON file. Idempotent.\n *\n * Iter 63 (Stage 3 source-move #20): hybrid copy from sdk-core's\n * `internal/memory/migration.ts`. sdk-core retains its copy for v1.x\n * legacy migration back-compat; sdk-memory ships the canonical copy.\n *\n * **Process-global migration flag map (`migrationRun`) is per-package.**\n * sdk-core's copy and sdk-memory's copy each maintain their own\n * `Set<string>` so the same key migrated through one package's copy\n * is NOT recorded in the other's. In v1.x active-memory-mode this\n * runs only via sdk-core; once sdk-core's runtime swaps to consume\n * sdk-memory's exports (later Stage 4), only sdk-memory's flag map\n * matters. Stage 3 source-move alone doesn't switch consumers.\n *\n * Dependency chain (sibling, all moved):\n * - `appendFactToMarkdown`, `memoryMdPath` → ./markdown-store.js (iter 56)\n * - `legacyMemoryJsonPath`, `MemoryConfig`, `MemoryFact` → ./memory-types.js (iter 52)\n *\n * @internal\n */\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function readLegacyFacts(jsonPath: string): Promise<MemoryFact[] | undefined> {\n try {\n const raw = await readFile(jsonPath, \"utf8\");\n const parsed = JSON.parse(raw) as { facts?: MemoryFact[] };\n return Array.isArray(parsed.facts) ? parsed.facts : [];\n } catch {\n return undefined;\n }\n}\n\nasync function writeMigratedFacts(\n cwd: string,\n jsonPath: string,\n facts: MemoryFact[],\n): Promise<MigrationResult> {\n try {\n for (const fact of facts) await appendFactToMarkdown(cwd, fact);\n await unlink(jsonPath).catch(() => undefined);\n process.stderr.write(\n `[theokit-sdk] migrated ${facts.length} fact(s) from ${jsonPath} to MEMORY.md\\n`,\n );\n return { migrated: true, factCount: facts.length };\n } catch (cause) {\n const message = cause instanceof Error ? cause.message : String(cause);\n process.stderr.write(`[theokit-sdk] memory migration failed (readonly fs?): ${message}\\n`);\n return { migrated: false, factCount: 0, reason: \"readonly-fs\" };\n }\n}\n\nconst migrationRun = new Set<string>();\n\n/**\n * Outcome of {@link migrateLegacyJson}. `reason` is present on every non-migrated\n * result and says which guard stopped it: `already-migrated` (this key was\n * attempted earlier in this process), `no-legacy-json` (nothing to migrate, or\n * the file could not be read or parsed), `markdown-exists` (both files present,\n * so neither was touched), `readonly-fs` (the write failed).\n */\nexport interface MigrationResult {\n migrated: boolean;\n factCount: number;\n reason?: \"already-migrated\" | \"no-legacy-json\" | \"markdown-exists\" | \"readonly-fs\";\n}\n\n/**\n * Move facts from the pre-markdown JSON store into `MEMORY.md`, once.\n *\n * It runs only when the legacy file exists and `MEMORY.md` does not. When both\n * exist it stops and leaves both alone — merging would need a conflict rule\n * nobody has picked, and losing hand-written notes is worse than skipping. On\n * success each fact is appended as a `## Facts` bullet and the JSON file is\n * deleted.\n *\n * Guarded by a per-process set keyed on cwd, namespace, scope and user id, so\n * the second call for the same key returns `already-migrated` without touching\n * disk — including after a genuine failure. That set is per module instance, so\n * a process that loads both this package's copy and the one inside\n * `@theokit/sdk` has two independent sets.\n *\n * Never throws: a JSON file that cannot be read or parsed reports\n * `no-legacy-json`, and a failed write reports `readonly-fs` after a warning on\n * stderr.\n */\nexport async function migrateLegacyJson(\n cwd: string,\n config: MemoryConfig,\n): Promise<MigrationResult> {\n const key = `${cwd}::${config.namespace ?? \"default\"}::${config.scope ?? \"agent\"}::${config.userId ?? \"default\"}`;\n if (migrationRun.has(key)) return { migrated: false, factCount: 0, reason: \"already-migrated\" };\n migrationRun.add(key);\n\n const jsonPath = legacyMemoryJsonPath(cwd, config);\n if (!(await fileExists(jsonPath))) {\n return { migrated: false, factCount: 0, reason: \"no-legacy-json\" };\n }\n if (await fileExists(memoryMdPath(resolveMemoryRoot(cwd)))) {\n process.stderr.write(\n `[theokit-sdk] memory migration skipped: both MEMORY.md and legacy JSON exist at ${jsonPath}; leaving both intact\\n`,\n );\n return { migrated: false, factCount: 0, reason: \"markdown-exists\" };\n }\n\n const facts = await readLegacyFacts(jsonPath);\n if (facts === undefined) return { migrated: false, factCount: 0, reason: \"no-legacy-json\" };\n return writeMigratedFacts(cwd, jsonPath, facts);\n}\n\n/** Test-only — reset the in-process migration flag map. */\nexport function resetMigrationStateForTests(): void {\n migrationRun.clear();\n}\n","import { readFile } from \"node:fs/promises\";\nimport { resolve as resolvePath } from \"node:path\";\n\n/**\n * **Iter 55 rollup-plugin-dts workaround** (mirrors iter 48/53 pattern).\n * The canonical sdk-core copy imports `MemoryReadResult` from\n * `../types.js`. In sdk-memory the same type lives in sibling\n * `./memory-types.js` (moved iter 52) but rollup-dts treeshakes it\n * out of the dist .d.ts because no PUBLIC type reaches it\n * transitively yet — `readMemoryFileBounded`'s return type would be\n * the consumer BUT rollup-dts processes the import resolution before\n * reader.ts itself becomes bundled into the public emit. Same class\n * of bug as iter 48 (MemorySearchHit) + iter 53 (MemoryChunk).\n *\n * Fix: declare a byte-identical mirror of MemoryReadResult inline.\n * When a future move (e.g. tools.ts wrapping readMemoryFileBounded\n * as a public LLM tool, or IndexManager surface emitting these)\n * gives MemoryReadResult a different publicly-reachable path, this\n * mirror MUST be deleted + the canonical import restored to maintain\n * single source of truth.\n *\n * @internal\n */\ninterface MemoryReadResult {\n path: string;\n /** Requested starting line (1-indexed, defaults to 1). */\n from: number;\n /** Number of lines actually returned (may be less than `lines` near EOF). */\n linesReturned: number;\n /** Total lines in the file (after the read). */\n totalLines: number;\n /** True when content remains after the returned slice, i.e. `remainingLines > 0`. */\n truncated: boolean;\n /** Lines past the returned slice that remain in the file. */\n remainingLines: number;\n /** Slice text (joined with `\\n`). */\n text: string;\n}\n\n/**\n * Bounded read with truncation info (ADR D5 — `memory_get` foundation).\n *\n * Mirrors peer-project's `buildMemoryReadResult` semantics:\n * - `from` is 1-indexed.\n * - `lines` defaults to 200 (`DEFAULT_MEMORY_READ_LINES`).\n * - Returns up to EOF when the requested slice extends past file end.\n * - Sets `truncated: true` whenever content remains past the returned slice,\n * whether or not the slice was shorter than requested. (At EOF, `false`.)\n *\n * Iter 55 (Stage 3 source-move #12): hybrid copy from sdk-core's\n * `internal/memory/storage/reader.ts`. sdk-core retains its copy for\n * v1.x `memory_get` back-compat; sdk-memory ships the canonical copy\n * that future `tools.ts` move (memory_get LLM tool wraps this) will\n * target as a sibling. `MemoryReadResult` comes from sibling\n * `./memory-types.js` (moved iter 52).\n *\n * @internal\n */\n\nexport const DEFAULT_MEMORY_READ_LINES = 200;\n\n/**\n * Inputs for {@link readMemoryFileBounded}. `relPath` is resolved against `cwd`,\n * and this function performs no containment check of its own — a `relPath`\n * containing `..` escapes. The `memory_get` tool validates containment before\n * calling in.\n *\n * `from` is 1-indexed and clamped to at least 1; `lines` defaults to 200 and is\n * clamped to at least 1.\n */\nexport interface ReadFileOptions {\n cwd: string;\n relPath: string;\n from?: number;\n lines?: number;\n}\n\n/**\n * Read a bounded slice of a text file and report what was left behind.\n *\n * A single trailing newline is not counted as a line, so `totalLines` matches\n * what an editor shows. `from` past the end of the file is not an error: it\n * returns an empty slice with `linesReturned: 0`.\n *\n * `truncated` means content remains after the returned slice — it is exactly\n * `remainingLines > 0`. It does not mean fewer lines were returned than\n * requested: a full 200-line slice of a 1000-line file is `truncated: true`,\n * and a short slice that reached the end is `truncated: false`.\n *\n * Rejects with the underlying filesystem error when the file cannot be read.\n */\nexport async function readMemoryFileBounded(opts: ReadFileOptions): Promise<MemoryReadResult> {\n const absolutePath = resolvePath(opts.cwd, opts.relPath);\n const raw = await readFile(absolutePath, \"utf8\");\n const allLines = raw.split(\"\\n\");\n // Strip a trailing empty line caused by a final \\n so totalLines reflects\n // the editor-visible line count, not the byte-level split.\n const trimmedLines =\n allLines.length > 0 && allLines[allLines.length - 1] === \"\" ? allLines.slice(0, -1) : allLines;\n const totalLines = trimmedLines.length;\n\n const requestedFrom = Math.max(1, opts.from ?? 1);\n const requestedLines = Math.max(1, opts.lines ?? DEFAULT_MEMORY_READ_LINES);\n const startIdx = requestedFrom - 1;\n const endIdx = Math.min(totalLines, startIdx + requestedLines);\n const slice = trimmedLines.slice(startIdx, endIdx);\n const linesReturned = slice.length;\n const remainingLines = Math.max(0, totalLines - endIdx);\n // truncated = \"more content exists past the returned slice\"\n const truncated = remainingLines > 0;\n\n return {\n path: opts.relPath,\n from: requestedFrom,\n linesReturned,\n totalLines,\n truncated,\n remainingLines,\n text: slice.join(\"\\n\"),\n };\n}\n","import { resolve as resolvePath } from \"node:path\";\n\nimport { ConfigurationError } from \"@theokit/sdk/errors\";\n\nimport type { MemorySearchHit } from \"./index/index-manager-contract.js\";\nimport type { MemoryIndex } from \"./index/memory-index.js\";\nimport type { MemoryRoot } from \"./store/markdown-store.js\";\nimport { readMemoryFileBounded } from \"./store/reader.js\";\n\n/**\n * Memory tools (`memory_search` + `memory_get`) — ADR D5 of\n * memory-system-peer-project-parity. Tool schemas mirror peer-project\n * (`reference/peer-project/extensions/memory-core/src/tools.ts:228-475`).\n *\n * Each tool is exposed as a `MemoryTool` (name + description + JSON schema +\n * async execute). The agent-loop integration wires them via the existing\n * `ResolvedTool` interface in `tool-dispatch.ts`.\n *\n * Iter 64 (Stage 3 source-move #21): hybrid copy from sdk-core's\n * `internal/memory/tools.ts`. sdk-core retains its copy for v1.x\n * memory-tools back-compat; sdk-memory ships the canonical copy.\n * Dependency chain (all resolved):\n * - `@theokit/sdk/errors` for `ConfigurationError` (public)\n * - sibling `./index-manager-contract.js` for `MemorySearchHit`\n * (moved iter 47 — note: sdk-core copy imports from\n * `./index-manager.js`; sdk-memory uses the contract leaf\n * directly since the canonical type lives there)\n * - sibling `./memory-index.js` for `MemoryIndex` (moved iter 50)\n * - sibling `./markdown-store.js` for `memoryDir` (moved iter 56)\n * - sibling `./reader.js` for `readMemoryFileBounded` (moved iter 55)\n *\n * @internal\n */\n\nexport interface MemoryToolJson {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n}\n\n/**\n * A memory tool ready to hand to the agent loop: the JSON-serialisable\n * description an LLM sees, plus the `execute` that runs it. `execute` resolves\n * to a JSON string — the tool layer does no further encoding.\n */\nexport interface MemoryTool extends MemoryToolJson {\n execute(input: Record<string, unknown>): Promise<string>;\n}\n\nconst SEARCH_DESCRIPTION =\n \"Mandatory recall step: semantically search MEMORY.md + memory/notes/*.md (and optional wiki supplements) before answering questions about prior work, decisions, dates, people, preferences, or todos. `corpus=memory` (default) restricts to indexed memory files; `corpus=wiki` restricts to read-only wiki supplements; `corpus=all` returns both. Returns ranked `{ path, startLine, endLine, score, snippet, citation }` hits.\";\n\nconst GET_DESCRIPTION =\n \"Safe exact excerpt read from MEMORY.md or memory/notes/*.md. Defaults to a bounded excerpt (200 lines). Returns `{ path, from, linesReturned, totalLines, truncated, remainingLines, text }`. Paths are resolved against the memory root — attempts to read outside `.theokit/memory/` are rejected.\";\n\nconst MEMORY_SEARCH_SCHEMA: Record<string, unknown> = {\n type: \"object\",\n required: [\"query\"],\n properties: {\n query: { type: \"string\", description: \"Natural-language query.\" },\n maxResults: { type: \"integer\", minimum: 1, maximum: 50 },\n minScore: { type: \"number\", minimum: 0, maximum: 1 },\n corpus: { type: \"string\", enum: [\"memory\", \"sessions\", \"wiki\", \"all\"] },\n },\n additionalProperties: false,\n};\n\nconst MEMORY_GET_SCHEMA: Record<string, unknown> = {\n type: \"object\",\n required: [\"path\"],\n properties: {\n path: { type: \"string\", description: \"Path relative to .theokit/memory/\" },\n from: { type: \"integer\", minimum: 1 },\n lines: { type: \"integer\", minimum: 1, maximum: 2000 },\n },\n additionalProperties: false,\n};\n\nconst DEFAULT_MAX_TOTAL_CHARS = 16384;\n\n/** Options for {@link createMemorySearchTool}. */\nexport interface MemorySearchToolOptions {\n index: MemoryIndex;\n /** Cap on the JSON response size (EC-10 of edge-case review). Default 16384. */\n maxTotalChars?: number;\n}\n\n/**\n * Build the `memory_search` tool over an index that is already open. The tool\n * never opens or syncs anything: if `index.sync()` has not run, the search runs\n * against whatever the index last recorded, and a freshly created index returns\n * no hits.\n *\n * The tool accepts `query` (required), `maxResults` (default 10), `minScore`,\n * and `corpus`, where `corpus` maps to the index's source filter: `memory`,\n * `sessions`, `wiki`, or `all` (the default, which applies no filter). An\n * unrecognised `corpus` value is treated as `all` rather than rejected.\n *\n * `execute` returns `{\"hits\": [...], \"truncated\": bool}`. Hits are dropped from\n * the tail once their estimated size would exceed `maxTotalChars`, except that\n * the first hit is always kept even when it alone exceeds the cap.\n *\n * Use this for recall by meaning across the whole corpus, and\n * {@link createMemoryGetTool} when the model already knows the file and wants\n * exact lines.\n */\nexport function createMemorySearchTool(opts: MemorySearchToolOptions): MemoryTool {\n const cap = opts.maxTotalChars ?? DEFAULT_MAX_TOTAL_CHARS;\n return {\n name: \"memory_search\",\n description: SEARCH_DESCRIPTION,\n inputSchema: MEMORY_SEARCH_SCHEMA,\n async execute(input: Record<string, unknown>): Promise<string> {\n const query = readString(input.query, \"query is required\");\n const maxResults = readNumber(input.maxResults) ?? 10;\n const minScore = readNumber(input.minScore);\n const corpus = readString(input.corpus, undefined, true);\n const sources = mapCorpusToSources(corpus);\n const searchOptions = {\n maxResults,\n ...(minScore !== undefined ? { minScore } : {}),\n ...(sources !== undefined ? { sources } : {}),\n };\n const hits = await opts.index.search(query, searchOptions);\n return JSON.stringify(capByTotalChars(hits, cap));\n },\n };\n}\n\n/** Options for {@link createMemoryGetTool}. `cwd` is the workspace root, not the memory directory. */\nexport interface MemoryGetToolOptions {\n /** The RESOLVED memory root the tool may read inside — not a cwd (#463). */\n root: MemoryRoot;\n}\n\n/**\n * Build the `memory_get` tool, which reads an exact excerpt from a file under\n * `<cwd>/.theokit/memory`. Needs no index and no embedding runtime — it is\n * plain file reading, so it works in a workspace where search is not configured.\n *\n * The tool accepts `path` (required, relative to the memory root), `from`\n * (1-indexed, default 1) and `lines` (default 200). A `path` whose resolved\n * location falls outside the memory root is rejected with a\n * `ConfigurationError` carrying the code `memory_path_escapes_root`. A path that\n * stays inside but does not exist is not caught here: the underlying read\n * rejects with the filesystem error.\n */\nexport function createMemoryGetTool(opts: MemoryGetToolOptions): MemoryTool {\n const memoryRoot = resolvePath(opts.root);\n return {\n name: \"memory_get\",\n description: GET_DESCRIPTION,\n inputSchema: MEMORY_GET_SCHEMA,\n async execute(input: Record<string, unknown>): Promise<string> {\n const relPath = readString(input.path, \"path is required\");\n const from = readNumber(input.from);\n const lines = readNumber(input.lines);\n // EC-2: enforce that the resolved path stays inside the memory root.\n const resolved = resolvePath(memoryRoot, relPath);\n if (!isPathInside(memoryRoot, resolved)) {\n throw new ConfigurationError(\n `memory_get rejected path that escapes memory root: ${relPath}`,\n { code: \"memory_path_escapes_root\" },\n );\n }\n const readArgs: { cwd: string; relPath: string; from?: number; lines?: number } = {\n cwd: memoryRoot,\n relPath,\n };\n if (from !== undefined) readArgs.from = from;\n if (lines !== undefined) readArgs.lines = lines;\n const result = await readMemoryFileBounded(readArgs);\n return JSON.stringify(result);\n },\n };\n}\n\n// ───── helpers ──────────────────────────────────────────────────────────\n\nfunction readString(value: unknown, errorIfMissing?: string, allowUndefined = false): string {\n if (typeof value === \"string\") return value;\n if (allowUndefined && (value === undefined || value === null)) return \"\";\n if (errorIfMissing !== undefined) {\n throw new ConfigurationError(errorIfMissing, { code: \"memory_tool_bad_args\" });\n }\n return \"\";\n}\n\nfunction readNumber(value: unknown): number | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value === \"string\" && value.trim().length > 0) {\n const n = Number(value);\n if (Number.isFinite(n)) return n;\n }\n return undefined;\n}\n\nfunction mapCorpusToSources(\n corpus: string,\n): ReadonlyArray<\"memory\" | \"sessions\" | \"wiki\"> | undefined {\n if (corpus === \"\" || corpus === \"all\") return undefined;\n if (corpus === \"memory\") return [\"memory\"];\n if (corpus === \"wiki\") return [\"wiki\"];\n if (corpus === \"sessions\") return [\"sessions\"];\n return undefined;\n}\n\nfunction capByTotalChars(\n hits: ReadonlyArray<MemorySearchHit>,\n maxTotalChars: number,\n): { hits: MemorySearchHit[]; truncated: boolean } {\n if (hits.length === 0) return { hits: [], truncated: false };\n const kept: MemorySearchHit[] = [];\n let runningChars = 0;\n for (const hit of hits) {\n const snippetLen = hit.snippet.length + (hit.citation?.length ?? 0) + 32; // overhead estimate\n if (kept.length > 0 && runningChars + snippetLen > maxTotalChars) {\n return { hits: kept, truncated: true };\n }\n kept.push(hit);\n runningChars += snippetLen;\n }\n return { hits: kept, truncated: false };\n}\n\nfunction isPathInside(root: string, candidate: string): boolean {\n const normalizedRoot = root.endsWith(\"/\") ? root : `${root}/`;\n return candidate === root || candidate.startsWith(normalizedRoot);\n}\n"]}
|