@vpxa/aikit 0.1.299 → 0.1.301

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vpxa/aikit",
3
- "version": "0.1.299",
3
+ "version": "0.1.301",
4
4
  "type": "module",
5
5
  "description": "Local-first AI developer toolkit — knowledge base, code analysis, context management, and developer tools for LLM agents",
6
6
  "license": "MIT",
@@ -155,11 +155,21 @@ declare const CHUNK_SIZES: {
155
155
  };
156
156
  /** Default embedding profile */
157
157
  declare const EMBEDDING_DEFAULTS: {
158
- readonly model: "mixedbread-ai/mxbai-embed-large-v1"; /** Native output dimensions before truncation */
159
- readonly nativeDim: 1024; /** Effective output dimensions (matryoshka truncation from native 1024) */
160
- readonly dimensions: 512; /** Query prefix applied by the profile. Defaults to empty string for backward compatibility. */
158
+ readonly model: "mixedbread-ai/mxbai-embed-xsmall-v1"; /** Native output dimensions before truncation */
159
+ readonly nativeDim: 384; /** Effective output dimensions (matryoshka truncation from native 384) */
160
+ readonly dimensions: 384; /** Query prefix applied by the profile. Defaults to empty string for backward compatibility. */
161
161
  readonly queryPrefix: "";
162
162
  };
163
+ /** Per-model capability registry for auto-resolution.
164
+ * Maps model ID to known settings. OnnxEmbedder constructor uses this
165
+ * to auto-fill dimensions, nativeDim, queryPrefix, and pooling when
166
+ * only the model ID is specified in config. */
167
+ declare const MODEL_REGISTRY: Record<string, {
168
+ nativeDim: number;
169
+ dimensions: number;
170
+ queryPrefix: string;
171
+ pooling: 'mean' | 'cls';
172
+ }>;
163
173
  /** Default store config */
164
174
  declare const STORE_DEFAULTS: {
165
175
  readonly backend: "sqlite-vec";
@@ -318,7 +328,8 @@ interface AikitConfig {
318
328
  model: string; /** Native output dimensions before truncation. Default 1024. */
319
329
  nativeDim?: number;
320
330
  dimensions: number; /** Query prefix for asymmetric retrieval. Default empty string. */
321
- queryPrefix?: string; /** Default 1. */
331
+ queryPrefix?: string; /** Pooling strategy: 'mean' averages all token embeddings, 'cls' uses the [CLS] token embedding. Default is model-specific. */
332
+ pooling?: 'mean' | 'cls'; /** Default 1. */
322
333
  interOpNumThreads?: number; /** Default 4. */
323
334
  intraOpNumThreads?: number; /** Default true. */
324
335
  childProcess?: boolean; /** Default 60000. */
@@ -666,4 +677,4 @@ interface RetryOptions {
666
677
  */
667
678
  declare function withRetry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
668
679
  //#endregion
669
- export { AIKIT_GLOBAL_PATHS, AIKIT_PATHS, AIKIT_RUNTIME_PATHS, AikitConfig, AikitError, CATEGORY_PATTERN, CHUNK_SIZES, CONTENT_TYPES, ChunkMetadata, CircuitBreaker, CircuitBreakerOptions, CircuitOpenError, CircuitState, ConfigError, ContentType, DEFAULT_CATEGORIES, EMBEDDING_DEFAULTS, EmbeddingError, FILE_LIMITS, GlobalRegistry, HealthBus, HealthEvent, HealthStatus, INDEX_MODES, IndexError, IndexMode, IndexStats, KNOWLEDGE_ORIGINS, KnowledgeOrigin, KnowledgeRecord, LogLevel, LogListener, PermanentError, RawChunk, RegistryEntry, RetryOptions, SEARCH_DEFAULTS, SOURCE_TYPES, STORE_DEFAULTS, SearchResult, SourceType, StoreError, SubsystemHealth, SupersessionConfig, TOKEN_BUDGETS, TokenBudget, TransientError, addLogListener, computePartitionKey, contentTypeToSourceType, createLogger, detectContentType, getGlobalDataDir, getLogLevel, getPartitionDir, getWorkspacePartitionDir, isPermanent, isTransient, isUserInstalled, listWorkspaces, loadRegistry, lookupWorkspace, migrateLegacyWorkspaceLayout, registerWorkspace, resetLogDir, resolveLogDir, resolveStateDir, saveRegistry, serializeError, setDetailedErrorLoggingEnabled, setFileSinkEnabled, setLogLevel, sourceTypeContentTypes, withRetry };
680
+ export { AIKIT_GLOBAL_PATHS, AIKIT_PATHS, AIKIT_RUNTIME_PATHS, AikitConfig, AikitError, CATEGORY_PATTERN, CHUNK_SIZES, CONTENT_TYPES, ChunkMetadata, CircuitBreaker, CircuitBreakerOptions, CircuitOpenError, CircuitState, ConfigError, ContentType, DEFAULT_CATEGORIES, EMBEDDING_DEFAULTS, EmbeddingError, FILE_LIMITS, GlobalRegistry, HealthBus, HealthEvent, HealthStatus, INDEX_MODES, IndexError, IndexMode, IndexStats, KNOWLEDGE_ORIGINS, KnowledgeOrigin, KnowledgeRecord, LogLevel, LogListener, MODEL_REGISTRY, PermanentError, RawChunk, RegistryEntry, RetryOptions, SEARCH_DEFAULTS, SOURCE_TYPES, STORE_DEFAULTS, SearchResult, SourceType, StoreError, SubsystemHealth, SupersessionConfig, TOKEN_BUDGETS, TokenBudget, TransientError, addLogListener, computePartitionKey, contentTypeToSourceType, createLogger, detectContentType, getGlobalDataDir, getLogLevel, getPartitionDir, getWorkspacePartitionDir, isPermanent, isTransient, isUserInstalled, listWorkspaces, loadRegistry, lookupWorkspace, migrateLegacyWorkspaceLayout, registerWorkspace, resetLogDir, resolveLogDir, resolveStateDir, saveRegistry, serializeError, setDetailedErrorLoggingEnabled, setFileSinkEnabled, setLogLevel, sourceTypeContentTypes, withRetry };
@@ -1 +1 @@
1
- import{EventEmitter as e}from"node:events";import{basename as t,extname as n,join as r,resolve as i}from"node:path";import{createHash as a}from"node:crypto";import{appendFileSync as o,closeSync as s,constants as c,copyFileSync as l,existsSync as u,lstatSync as ee,mkdirSync as d,openSync as te,readFileSync as ne,readdirSync as f,renameSync as p,rmSync as m,statSync as h,unlinkSync as g,writeFileSync as _}from"node:fs";import{homedir as v}from"node:os";var re=class t extends e{static registry=new Map;state=`closed`;failures=0;halfOpenAttempts=0;openUntil=0;threshold;cooldownMs;halfOpenMaxAttempts;jitterMs;name;onStateChange;static getAll(){return t.registry}static get(e){return t.registry.get(e)}static clearRegistry(){t.registry.clear()}constructor(e={}){super(),this.threshold=Math.max(1,e.threshold??3),this.cooldownMs=Math.max(0,e.cooldownMs??6e4),this.halfOpenMaxAttempts=Math.max(1,e.halfOpenMaxAttempts??1),this.jitterMs=Math.max(0,e.jitterMs??0),this.name=e.name,this.onStateChange=e.onStateChange,this.name&&t.registry.set(this.name,this)}async execute(e){this.assertNotOpen();try{let t=await e();return this.recordSuccess(),t}catch(e){throw this.recordFailure(),e}}getState(){return this.refreshState(),this.state}getName(){return this.name}isOpen(){return this.getState()===`open`}reset(){this.failures=0,this.halfOpenAttempts=0,this.openUntil=0,this.transitionTo(`closed`,`manual reset`)}dispose(){this.name&&t.registry.get(this.name)===this&&t.registry.delete(this.name),this.removeAllListeners()}forceOpen(e){this.failures=this.threshold,this.halfOpenAttempts=0,this.transitionTo(`open`,e??`manual override`)}recordSuccess(){this.refreshState(),this.failures=0,this.halfOpenAttempts=0,this.state===`half-open`&&this.transitionTo(`closed`,`probe succeeded`)}recordFailure(){if(this.refreshState(),this.failures+=1,this.halfOpenAttempts=0,this.state===`half-open`){this.transitionTo(`open`,`probe failed`);return}this.state===`closed`&&this.failures>=this.threshold&&this.transitionTo(`open`,`failure threshold reached`)}remainingCooldownMs(){return this.refreshState(),this.state===`open`?Math.max(0,this.openUntil-Date.now()):0}assertNotOpen(){if(this.refreshState(),this.state===`open`)throw new y(this.remainingCooldownMs());if(this.state===`half-open`){if(this.halfOpenAttempts>=this.halfOpenMaxAttempts)throw this.transitionTo(`open`,`half-open probe limit reached`),new y(this.remainingCooldownMs());this.halfOpenAttempts+=1}}refreshState(){this.state===`open`&&Date.now()>=this.openUntil&&(this.halfOpenAttempts=0,this.transitionTo(`half-open`,`cooldown expired`))}transitionTo(e,t){let n=this.state;if(n===e){e===`open`&&(this.openUntil=this.computeOpenUntil());return}this.state=e,e===`open`?(this.openUntil=this.computeOpenUntil(),this.halfOpenAttempts=0):(this.openUntil=0,e===`closed`&&(this.halfOpenAttempts=0)),this.onStateChange?.(n,e),this.emit(e,{from:n,reason:t})}computeOpenUntil(){return Date.now()+this.cooldownMs+Math.floor(Math.random()*this.jitterMs)}},y=class extends Error{remainingMs;constructor(e){super(`Circuit breaker is open — ${Math.ceil(e/1e3)}s remaining`),this.remainingMs=e,this.name=`CircuitOpenError`}};const b={root:`.aikit`,ai:`.ai`,aiContext:`.ai/context`,aiCurated:`.ai/curated`,restorePoints:`.ai/restore-points`,data:`.aikit/data`,state:`.aikit/state`,logs:`.aikit/logs`,brainstorm:`.brainstorm`,handoffs:`.handoffs`},x={data:`data`,curated:`curated`,onboard:`onboard`,state:`state`,restorePoints:`restore-points`,brainstorm:`brainstorm`,handoffs:`handoffs`},S={root:`.aikit`,registry:`registry.json`,workspaces:`workspaces`,logs:`logs`,state:`state`,legacyDataRoot:`.aikit-data`,legacyStateRoot:`.aikit-state`},ie={markdown:{max:1500,min:100},code:{max:2e3,min:50},config:{max:3e3,min:50},default:{max:1500,min:100,overlap:200}},ae={model:`mixedbread-ai/mxbai-embed-large-v1`,nativeDim:1024,dimensions:512,queryPrefix:``},C={backend:`sqlite-vec`,path:b.data,tableName:`knowledge`},oe={maxFileSizeBytes:1e6,maxCuratedFileSizeBytes:5e4},se={maxResults:10,minScore:.25},ce=/^[a-z][a-z0-9-]*$/,le=[`decisions`,`patterns`,`troubleshooting`,`conventions`,`architecture`],w={".ts":`code-typescript`,".tsx":`code-typescript`,".mts":`code-typescript`,".cts":`code-typescript`,".js":`code-javascript`,".jsx":`code-javascript`,".mjs":`code-javascript`,".cjs":`code-javascript`,".py":`code-python`,".json":`config-json`,".yaml":`config-yaml`,".yml":`config-yaml`,".toml":`config-toml`,".env":`config-env`,".md":`markdown`,".mdx":`markdown`},ue=[/\.test\.[jt]sx?$/,/\.spec\.[jt]sx?$/,/(^|\/)__tests__\//,/(^|\/)test\//,/(^|\/)tests\//,/(^|\/)spec\//,/(^|\/)fixtures\//],de=[/\.stack\.[jt]s$/,/(^|\/)stacks\//,/(^|\/)constructs\//,/cdk\.json$/];function fe(e){let r=n(e).toLowerCase(),i=t(e).toLowerCase();return e.includes(`${b.aiContext}/`)?`produced-knowledge`:e.includes(`${b.aiCurated}/`)?`curated-knowledge`:ue.some(t=>t.test(e))?`test-code`:de.some(t=>t.test(e))?`cdk-stack`:r in w?w[r]:i.startsWith(`.env`)?`config-env`:[`.go`,`.rs`,`.java`,`.rb`,`.php`,`.sh`,`.ps1`,`.sql`,`.graphql`,`.proto`,`.css`,`.scss`,`.less`,`.html`,`.htm`,`.vue`,`.svelte`,`.astro`,`.hbs`,`.ejs`,`.svg`].includes(r)?`code-other`:`unknown`}const T={"code-typescript":`source`,"code-javascript":`source`,"code-python":`source`,"code-other":`source`,"cdk-stack":`source`,"test-code":`test`,markdown:`documentation`,documentation:`documentation`,"curated-knowledge":`documentation`,"produced-knowledge":`documentation`,"config-json":`config`,"config-yaml":`config`,"config-toml":`config`,"config-env":`config`,unknown:`source`};function pe(e){return T[e]??`source`}function me(e){return Object.entries(T).filter(([,t])=>t===e).map(([e])=>e)}var E=class extends Error{code;constructor(e,t,n){super(e,n===void 0?void 0:{cause:n}),this.code=t,this.name=`AikitError`}},he=class extends E{constructor(e,t){super(e,`EMBEDDING_ERROR`,t),this.name=`EmbeddingError`}},ge=class extends E{constructor(e,t){super(e,`STORE_ERROR`,t),this.name=`StoreError`}},_e=class extends E{constructor(e,t){super(e,`INDEX_ERROR`,t),this.name=`IndexError`}},ve=class extends E{constructor(e,t){super(e,`CONFIG_ERROR`,t),this.name=`ConfigError`}},D=class extends E{retryAfterMs;constructor(e,t,n){super(e,`TRANSIENT_ERROR`,n),this.retryAfterMs=t,this.name=`TransientError`}},O=class extends E{constructor(e,t){super(e,`PERMANENT_ERROR`,t),this.name=`PermanentError`}};function ye(e){return e instanceof D}function be(e){return e instanceof O}let k=!1;function A(e){try{return!ee(e).isSymbolicLink()}catch{return!1}}function j(e,t){if(h(e).isDirectory()){d(t,{recursive:!0});for(let n of f(e))N(i(e,n),i(t,n));m(e,{recursive:!0,force:!0});return}d(i(t,`..`),{recursive:!0}),l(e,t),g(e)}function M(e,t){try{p(e,t)}catch(n){let r=n.code;if(r===`ENOENT`&&!u(e)&&u(t))return;if(r!==`EXDEV`)throw n;j(e,t)}}function N(e,t){if(!u(e)||e===t||!A(e))return;let n=h(e);if(!u(t)){d(i(t,`..`),{recursive:!0}),M(e,t);return}if(n.isDirectory()){d(t,{recursive:!0});for(let n of f(e))N(i(e,n),i(t,n));try{m(e,{recursive:!0,force:!0})}catch{}}}function P(e){if(u(e))try{f(e).length===0&&m(e,{recursive:!0,force:!0})}catch{}}function xe(e){let t=i(e,x.data);d(t,{recursive:!0});for(let n of f(e))n!==x.data&&(n===`lance`||/\.db(?:-(?:wal|shm|journal))?$/i.test(n))&&N(i(e,n),i(t,n))}function F(e){return H(R(e))}function Se(e){if(k)return;k=!0,d(e,{recursive:!0});let t=v(),n=i(t,S.legacyDataRoot),r=i(t,S.legacyStateRoot),a=i(e,S.workspaces),o=i(e,S.logs),s=i(e,S.state);if(u(n)&&n!==e){d(a,{recursive:!0});for(let t of f(n))N(i(n,t),t===S.registry||t===`global.env`||t===`flows`||t===`global-knowledge`?i(e,t):i(a,t));P(n)}if(u(r)&&r!==e){for(let e of f(r))N(i(r,e),e===`logs`?o:i(s,e));P(r)}}function I(e){let t=i(e),n=F(t),r=i(n,x.data),a=i(L(),S.logs),o=[{from:i(t,S.legacyDataRoot),to:r},{from:i(t,S.legacyStateRoot),to:i(n,x.state)},{from:i(t,b.data),to:r},{from:i(t,b.state),to:i(n,x.state)},{from:i(t,b.aiCurated),to:i(n,x.curated)},{from:i(t,b.aiContext),to:i(n,x.onboard)},{from:i(t,b.restorePoints),to:i(n,x.restorePoints)},{from:i(t,b.brainstorm),to:i(n,x.brainstorm)},{from:i(t,b.handoffs),to:i(n,x.handoffs)},{from:i(t,b.logs),to:a}];d(n,{recursive:!0}),d(a,{recursive:!0}),xe(n);for(let e of o)N(e.from,e.to);P(i(t,b.root)),P(i(t,b.ai)),P(i(t,b.brainstorm)),P(i(t,b.handoffs))}function Ce(e){return I(e),i(H(V(e).partition),x.state)}function L(){let e=process.env.AIKIT_GLOBAL_DATA_DIR,t=e??i(v(),S.root);return!e&&!process.env.VITEST&&process.env.NODE_ENV!==`test`&&Se(t),t}function R(e){let n=i(e);return`${t(n).toLowerCase().replace(/[^a-z0-9-]/g,`-`)||`workspace`}-${a(`sha256`).update(n).digest(`hex`).slice(0,8)}`}function z(){let e=i(L(),S.registry);if(!u(e))return{version:1,workspaces:{}};let t=ne(e,`utf-8`);try{return JSON.parse(t)}catch{return{version:1,workspaces:{}}}}function we(e,t=5e3){let n=`${e}.lock`,r=Date.now()+t,i=10;for(;Date.now()<r;)try{let e=te(n,c.O_CREAT|c.O_EXCL|c.O_WRONLY);return _(e,`${process.pid}\n`),s(e),n}catch(e){if(e.code!==`EEXIST`)throw e;try{let{mtimeMs:e}=h(n);if(Date.now()-e>3e4){g(n);continue}}catch{}let t=new SharedArrayBuffer(4);Atomics.wait(new Int32Array(t),0,0,i),i=Math.min(i*2,200)}throw Error(`Failed to acquire registry lock after ${t}ms`)}function Te(e){try{g(e)}catch{}}function B(e){let t=L();d(t,{recursive:!0});let n=i(t,S.registry),r=we(n);try{let t=`${n}.tmp`;_(t,JSON.stringify(e,null,2),`utf-8`),p(t,n)}finally{Te(r)}}function V(e){let t=z(),n=R(e),r=new Date().toISOString();return t.workspaces[n]?t.workspaces[n].lastAccessedAt=r:t.workspaces[n]={partition:n,workspacePath:i(e),registeredAt:r,lastAccessedAt:r},d(H(n),{recursive:!0}),B(t),t.workspaces[n]}function Ee(e){let t=z(),n=R(e);return t.workspaces[n]}function De(){let e=z();return Object.values(e.workspaces)}function H(e){return i(L(),S.workspaces,e)}function Oe(){return u(i(L(),S.registry))}function U(){return i(L(),S.logs)}var ke=class t extends e{static _instance=null;subsystems=new Map;constructor(){super()}static instance(){return t._instance||=new t,t._instance}static reset(){t._instance?.removeAllListeners(),t._instance=null}register(e){this.subsystems.has(e)||this.subsystems.set(e,{name:e,status:`healthy`,since:Date.now()})}reportDegraded(e,t){this.transition(e,`degraded`,t)}reportUnavailable(e,t){this.transition(e,`unavailable`,t)}reportRecovered(e){this.transition(e,`healthy`)}isDegraded(e){let t=this.subsystems.get(e);return t?.status===`degraded`||t?.status===`unavailable`}isHealthy(e){return this.subsystems.get(e)?.status===`healthy`}getAll(){return Array.from(this.subsystems.values(),e=>({...e}))}getSubsystem(e){let t=this.subsystems.get(e);return t?{...t}:void 0}transition(e,t,n){let r=this.subsystems.get(e);if(!r||r.status===t)return;let i={subsystem:e,status:t,previousStatus:r.status,reason:n,timestamp:Date.now()};r.status=t,r.since=i.timestamp,r.reason=n,this.emit(t,i),this.emit(`change`,i)}};const W={debug:0,info:1,warn:2,error:3},G=[];let K=process.env.AIKIT_LOG_LEVEL??`info`,q=!1,J=process.env.AIKIT_LOG_FILE_SINK===`true`||process.env.AIKIT_LOG_FILE_SINK!==`false`&&!process.env.VITEST&&process.env.NODE_ENV!==`test`;function Ae(){return J?process.env.VITEST||process.env.NODE_ENV===`test`?process.env.AIKIT_LOG_FILE_SINK===`true`:!0:!1}let Y;function X(){return Y||=U(),Y}function je(e){let t=e.toISOString().slice(0,10);return r(X(),`${t}.jsonl`)}let Z=0;function Me(){let e=Date.now();if(!(e-Z<36e5)){Z=e;try{let t=X(),n=new Date(e-30*864e5).toISOString().slice(0,10);for(let e of f(t))if(e.endsWith(`.jsonl`)&&e.slice(0,10)<n)try{g(r(t,e))}catch{}}catch{}}}function Ne(e,t){try{d(X(),{recursive:!0}),o(je(t),`${e}\n`),Me()}catch{}}function Pe(e){K=e}function Fe(){return K}function Q(e){J=e}function Ie(){Y=void 0}function Le(e){q=e}function Re(e){if(e instanceof Error){let t={error:e.message};return q?(e.stack&&(t.stack=e.stack),e.cause!==void 0&&(t.cause=e.cause instanceof Error?e.cause.message:String(e.cause)),t):t}return{error:String(e)}}function ze(e){return G.push(e),()=>{let t=G.indexOf(e);t>=0&&G.splice(t,1)}}function Be(e){function t(t,n,r){if(W[t]<W[K])return;let i=new Date,a={ts:i.toISOString(),level:t,component:e,msg:n,...r},o=JSON.stringify(a);(t===`warn`||t===`error`)&&console.error(o);for(let i of G)try{i({level:t,component:e,message:n,data:r})}catch{}Ae()&&(t===`warn`||t===`error`)&&Ne(o,i)}return{debug:(e,n)=>t(`debug`,e,n),info:(e,n)=>t(`info`,e,n),warn:(e,n)=>t(`warn`,e,n),error:(e,n)=>t(`error`,e,n)}}const $={maxAttempts:3,baseDelayMs:500,maxDelayMs:3e4,jitterFraction:.25};async function Ve(e,t={}){let{maxAttempts:n=$.maxAttempts,baseDelayMs:r=$.baseDelayMs,maxDelayMs:i=$.maxDelayMs,jitterFraction:a=$.jitterFraction}=t,o=t.shouldRetry??(e=>e instanceof D),s;for(let c=1;c<=n;c++)try{return await e()}catch(e){if(s=e,c>=n||!o(e,c))throw e;let l;if(e instanceof D&&e.retryAfterMs!=null&&e.retryAfterMs>0)l=Math.min(e.retryAfterMs,i);else{let e=r*2**(c-1),t=Math.min(e,i),n=t*a*(Math.random()*2-1);l=Math.round(t+n)}t.onRetry?.(e,c,l),await He(l)}throw s}function He(e){return new Promise(t=>setTimeout(t,e))}const Ue=[`indexed`,`curated`,`produced`],We=[`source`,`documentation`,`test`,`config`,`generated`],Ge=[`auto`,`manual`,`smart`],Ke=[`efficient`,`normal`,`full`],qe=[`documentation`,`code-typescript`,`code-javascript`,`code-python`,`code-other`,`config-json`,`config-yaml`,`config-toml`,`config-env`,`test-code`,`cdk-stack`,`markdown`,`curated-knowledge`,`produced-knowledge`,`unknown`];export{S as AIKIT_GLOBAL_PATHS,b as AIKIT_PATHS,x as AIKIT_RUNTIME_PATHS,E as AikitError,ce as CATEGORY_PATTERN,ie as CHUNK_SIZES,qe as CONTENT_TYPES,re as CircuitBreaker,y as CircuitOpenError,ve as ConfigError,le as DEFAULT_CATEGORIES,ae as EMBEDDING_DEFAULTS,he as EmbeddingError,oe as FILE_LIMITS,ke as HealthBus,Ge as INDEX_MODES,_e as IndexError,Ue as KNOWLEDGE_ORIGINS,O as PermanentError,se as SEARCH_DEFAULTS,We as SOURCE_TYPES,C as STORE_DEFAULTS,ge as StoreError,Ke as TOKEN_BUDGETS,D as TransientError,ze as addLogListener,R as computePartitionKey,pe as contentTypeToSourceType,Be as createLogger,fe as detectContentType,L as getGlobalDataDir,Fe as getLogLevel,H as getPartitionDir,F as getWorkspacePartitionDir,be as isPermanent,ye as isTransient,Oe as isUserInstalled,De as listWorkspaces,z as loadRegistry,Ee as lookupWorkspace,I as migrateLegacyWorkspaceLayout,V as registerWorkspace,Ie as resetLogDir,U as resolveLogDir,Ce as resolveStateDir,B as saveRegistry,Re as serializeError,Le as setDetailedErrorLoggingEnabled,Q as setFileSinkEnabled,Pe as setLogLevel,me as sourceTypeContentTypes,Ve as withRetry};
1
+ import{EventEmitter as e}from"node:events";import{basename as t,extname as n,join as r,resolve as i}from"node:path";import{createHash as a}from"node:crypto";import{appendFileSync as o,closeSync as s,constants as c,copyFileSync as l,existsSync as u,lstatSync as ee,mkdirSync as d,openSync as te,readFileSync as ne,readdirSync as f,renameSync as p,rmSync as m,statSync as h,unlinkSync as g,writeFileSync as _}from"node:fs";import{homedir as v}from"node:os";var re=class t extends e{static registry=new Map;state=`closed`;failures=0;halfOpenAttempts=0;openUntil=0;threshold;cooldownMs;halfOpenMaxAttempts;jitterMs;name;onStateChange;static getAll(){return t.registry}static get(e){return t.registry.get(e)}static clearRegistry(){t.registry.clear()}constructor(e={}){super(),this.threshold=Math.max(1,e.threshold??3),this.cooldownMs=Math.max(0,e.cooldownMs??6e4),this.halfOpenMaxAttempts=Math.max(1,e.halfOpenMaxAttempts??1),this.jitterMs=Math.max(0,e.jitterMs??0),this.name=e.name,this.onStateChange=e.onStateChange,this.name&&t.registry.set(this.name,this)}async execute(e){this.assertNotOpen();try{let t=await e();return this.recordSuccess(),t}catch(e){throw this.recordFailure(),e}}getState(){return this.refreshState(),this.state}getName(){return this.name}isOpen(){return this.getState()===`open`}reset(){this.failures=0,this.halfOpenAttempts=0,this.openUntil=0,this.transitionTo(`closed`,`manual reset`)}dispose(){this.name&&t.registry.get(this.name)===this&&t.registry.delete(this.name),this.removeAllListeners()}forceOpen(e){this.failures=this.threshold,this.halfOpenAttempts=0,this.transitionTo(`open`,e??`manual override`)}recordSuccess(){this.refreshState(),this.failures=0,this.halfOpenAttempts=0,this.state===`half-open`&&this.transitionTo(`closed`,`probe succeeded`)}recordFailure(){if(this.refreshState(),this.failures+=1,this.halfOpenAttempts=0,this.state===`half-open`){this.transitionTo(`open`,`probe failed`);return}this.state===`closed`&&this.failures>=this.threshold&&this.transitionTo(`open`,`failure threshold reached`)}remainingCooldownMs(){return this.refreshState(),this.state===`open`?Math.max(0,this.openUntil-Date.now()):0}assertNotOpen(){if(this.refreshState(),this.state===`open`)throw new y(this.remainingCooldownMs());if(this.state===`half-open`){if(this.halfOpenAttempts>=this.halfOpenMaxAttempts)throw this.transitionTo(`open`,`half-open probe limit reached`),new y(this.remainingCooldownMs());this.halfOpenAttempts+=1}}refreshState(){this.state===`open`&&Date.now()>=this.openUntil&&(this.halfOpenAttempts=0,this.transitionTo(`half-open`,`cooldown expired`))}transitionTo(e,t){let n=this.state;if(n===e){e===`open`&&(this.openUntil=this.computeOpenUntil());return}this.state=e,e===`open`?(this.openUntil=this.computeOpenUntil(),this.halfOpenAttempts=0):(this.openUntil=0,e===`closed`&&(this.halfOpenAttempts=0)),this.onStateChange?.(n,e),this.emit(e,{from:n,reason:t})}computeOpenUntil(){return Date.now()+this.cooldownMs+Math.floor(Math.random()*this.jitterMs)}},y=class extends Error{remainingMs;constructor(e){super(`Circuit breaker is open — ${Math.ceil(e/1e3)}s remaining`),this.remainingMs=e,this.name=`CircuitOpenError`}};const b={root:`.aikit`,ai:`.ai`,aiContext:`.ai/context`,aiCurated:`.ai/curated`,restorePoints:`.ai/restore-points`,data:`.aikit/data`,state:`.aikit/state`,logs:`.aikit/logs`,brainstorm:`.brainstorm`,handoffs:`.handoffs`},x={data:`data`,curated:`curated`,onboard:`onboard`,state:`state`,restorePoints:`restore-points`,brainstorm:`brainstorm`,handoffs:`handoffs`},S={root:`.aikit`,registry:`registry.json`,workspaces:`workspaces`,logs:`logs`,state:`state`,legacyDataRoot:`.aikit-data`,legacyStateRoot:`.aikit-state`},ie={markdown:{max:1500,min:100},code:{max:2e3,min:50},config:{max:3e3,min:50},default:{max:1500,min:100,overlap:200}},ae={model:`mixedbread-ai/mxbai-embed-xsmall-v1`,nativeDim:384,dimensions:384,queryPrefix:``},oe={"mixedbread-ai/mxbai-embed-xsmall-v1":{nativeDim:384,dimensions:384,queryPrefix:``,pooling:`mean`},"mixedbread-ai/mxbai-embed-large-v1":{nativeDim:1024,dimensions:512,queryPrefix:`Represent this sentence for searching relevant passages: `,pooling:`cls`}},se={backend:`sqlite-vec`,path:b.data,tableName:`knowledge`},ce={maxFileSizeBytes:1e6,maxCuratedFileSizeBytes:5e4},le={maxResults:10,minScore:.25},ue=/^[a-z][a-z0-9-]*$/,de=[`decisions`,`patterns`,`troubleshooting`,`conventions`,`architecture`],C={".ts":`code-typescript`,".tsx":`code-typescript`,".mts":`code-typescript`,".cts":`code-typescript`,".js":`code-javascript`,".jsx":`code-javascript`,".mjs":`code-javascript`,".cjs":`code-javascript`,".py":`code-python`,".json":`config-json`,".yaml":`config-yaml`,".yml":`config-yaml`,".toml":`config-toml`,".env":`config-env`,".md":`markdown`,".mdx":`markdown`},w=[/\.test\.[jt]sx?$/,/\.spec\.[jt]sx?$/,/(^|\/)__tests__\//,/(^|\/)test\//,/(^|\/)tests\//,/(^|\/)spec\//,/(^|\/)fixtures\//],fe=[/\.stack\.[jt]s$/,/(^|\/)stacks\//,/(^|\/)constructs\//,/cdk\.json$/];function pe(e){let r=n(e).toLowerCase(),i=t(e).toLowerCase();return e.includes(`${b.aiContext}/`)?`produced-knowledge`:e.includes(`${b.aiCurated}/`)?`curated-knowledge`:w.some(t=>t.test(e))?`test-code`:fe.some(t=>t.test(e))?`cdk-stack`:r in C?C[r]:i.startsWith(`.env`)?`config-env`:[`.go`,`.rs`,`.java`,`.rb`,`.php`,`.sh`,`.ps1`,`.sql`,`.graphql`,`.proto`,`.css`,`.scss`,`.less`,`.html`,`.htm`,`.vue`,`.svelte`,`.astro`,`.hbs`,`.ejs`,`.svg`].includes(r)?`code-other`:`unknown`}const T={"code-typescript":`source`,"code-javascript":`source`,"code-python":`source`,"code-other":`source`,"cdk-stack":`source`,"test-code":`test`,markdown:`documentation`,documentation:`documentation`,"curated-knowledge":`documentation`,"produced-knowledge":`documentation`,"config-json":`config`,"config-yaml":`config`,"config-toml":`config`,"config-env":`config`,unknown:`source`};function me(e){return T[e]??`source`}function he(e){return Object.entries(T).filter(([,t])=>t===e).map(([e])=>e)}var E=class extends Error{code;constructor(e,t,n){super(e,n===void 0?void 0:{cause:n}),this.code=t,this.name=`AikitError`}},ge=class extends E{constructor(e,t){super(e,`EMBEDDING_ERROR`,t),this.name=`EmbeddingError`}},_e=class extends E{constructor(e,t){super(e,`STORE_ERROR`,t),this.name=`StoreError`}},ve=class extends E{constructor(e,t){super(e,`INDEX_ERROR`,t),this.name=`IndexError`}},ye=class extends E{constructor(e,t){super(e,`CONFIG_ERROR`,t),this.name=`ConfigError`}},D=class extends E{retryAfterMs;constructor(e,t,n){super(e,`TRANSIENT_ERROR`,n),this.retryAfterMs=t,this.name=`TransientError`}},O=class extends E{constructor(e,t){super(e,`PERMANENT_ERROR`,t),this.name=`PermanentError`}};function be(e){return e instanceof D}function xe(e){return e instanceof O}let k=!1;function A(e){try{return!ee(e).isSymbolicLink()}catch{return!1}}function j(e,t){if(h(e).isDirectory()){d(t,{recursive:!0});for(let n of f(e))N(i(e,n),i(t,n));m(e,{recursive:!0,force:!0});return}d(i(t,`..`),{recursive:!0}),l(e,t),g(e)}function M(e,t){try{p(e,t)}catch(n){let r=n.code;if(r===`ENOENT`&&!u(e)&&u(t))return;if(r!==`EXDEV`)throw n;j(e,t)}}function N(e,t){if(!u(e)||e===t||!A(e))return;let n=h(e);if(!u(t)){d(i(t,`..`),{recursive:!0}),M(e,t);return}if(n.isDirectory()){d(t,{recursive:!0});for(let n of f(e))N(i(e,n),i(t,n));try{m(e,{recursive:!0,force:!0})}catch{}}}function P(e){if(u(e))try{f(e).length===0&&m(e,{recursive:!0,force:!0})}catch{}}function Se(e){let t=i(e,x.data);d(t,{recursive:!0});for(let n of f(e))n!==x.data&&(n===`lance`||/\.db(?:-(?:wal|shm|journal))?$/i.test(n))&&N(i(e,n),i(t,n))}function F(e){return U(R(e))}function Ce(e){if(k)return;k=!0,d(e,{recursive:!0});let t=v(),n=i(t,S.legacyDataRoot),r=i(t,S.legacyStateRoot),a=i(e,S.workspaces),o=i(e,S.logs),s=i(e,S.state);if(u(n)&&n!==e){d(a,{recursive:!0});for(let t of f(n))N(i(n,t),t===S.registry||t===`global.env`||t===`flows`||t===`global-knowledge`?i(e,t):i(a,t));P(n)}if(u(r)&&r!==e){for(let e of f(r))N(i(r,e),e===`logs`?o:i(s,e));P(r)}}function I(e){let t=i(e),n=F(t),r=i(n,x.data),a=i(L(),S.logs),o=[{from:i(t,S.legacyDataRoot),to:r},{from:i(t,S.legacyStateRoot),to:i(n,x.state)},{from:i(t,b.data),to:r},{from:i(t,b.state),to:i(n,x.state)},{from:i(t,b.aiCurated),to:i(n,x.curated)},{from:i(t,b.aiContext),to:i(n,x.onboard)},{from:i(t,b.restorePoints),to:i(n,x.restorePoints)},{from:i(t,b.brainstorm),to:i(n,x.brainstorm)},{from:i(t,b.handoffs),to:i(n,x.handoffs)},{from:i(t,b.logs),to:a}];d(n,{recursive:!0}),d(a,{recursive:!0}),Se(n);for(let e of o)N(e.from,e.to);P(i(t,b.root)),P(i(t,b.ai)),P(i(t,b.brainstorm)),P(i(t,b.handoffs))}function we(e){return I(e),i(U(V(e).partition),x.state)}function L(){let e=process.env.AIKIT_GLOBAL_DATA_DIR,t=e??i(v(),S.root);return!e&&!process.env.VITEST&&process.env.NODE_ENV!==`test`&&Ce(t),t}function R(e){let n=i(e);return`${t(n).toLowerCase().replace(/[^a-z0-9-]/g,`-`)||`workspace`}-${a(`sha256`).update(n).digest(`hex`).slice(0,8)}`}function z(){let e=i(L(),S.registry);if(!u(e))return{version:1,workspaces:{}};let t=ne(e,`utf-8`);try{return JSON.parse(t)}catch{return{version:1,workspaces:{}}}}function Te(e,t=5e3){let n=`${e}.lock`,r=Date.now()+t,i=10;for(;Date.now()<r;)try{let e=te(n,c.O_CREAT|c.O_EXCL|c.O_WRONLY);return _(e,`${process.pid}\n`),s(e),n}catch(e){if(e.code!==`EEXIST`)throw e;try{let{mtimeMs:e}=h(n);if(Date.now()-e>3e4){g(n);continue}}catch{}let t=new SharedArrayBuffer(4);Atomics.wait(new Int32Array(t),0,0,i),i=Math.min(i*2,200)}throw Error(`Failed to acquire registry lock after ${t}ms`)}function Ee(e){try{g(e)}catch{}}function B(e){let t=L();d(t,{recursive:!0});let n=i(t,S.registry),r=Te(n);try{let t=`${n}.tmp`;_(t,JSON.stringify(e,null,2),`utf-8`),p(t,n)}finally{Ee(r)}}function V(e){let t=z(),n=R(e),r=new Date().toISOString();return t.workspaces[n]?t.workspaces[n].lastAccessedAt=r:t.workspaces[n]={partition:n,workspacePath:i(e),registeredAt:r,lastAccessedAt:r},d(U(n),{recursive:!0}),B(t),t.workspaces[n]}function De(e){let t=z(),n=R(e);return t.workspaces[n]}function H(){let e=z();return Object.values(e.workspaces)}function U(e){return i(L(),S.workspaces,e)}function Oe(){return u(i(L(),S.registry))}function W(){return i(L(),S.logs)}var ke=class t extends e{static _instance=null;subsystems=new Map;constructor(){super()}static instance(){return t._instance||=new t,t._instance}static reset(){t._instance?.removeAllListeners(),t._instance=null}register(e){this.subsystems.has(e)||this.subsystems.set(e,{name:e,status:`healthy`,since:Date.now()})}reportDegraded(e,t){this.transition(e,`degraded`,t)}reportUnavailable(e,t){this.transition(e,`unavailable`,t)}reportRecovered(e){this.transition(e,`healthy`)}isDegraded(e){let t=this.subsystems.get(e);return t?.status===`degraded`||t?.status===`unavailable`}isHealthy(e){return this.subsystems.get(e)?.status===`healthy`}getAll(){return Array.from(this.subsystems.values(),e=>({...e}))}getSubsystem(e){let t=this.subsystems.get(e);return t?{...t}:void 0}transition(e,t,n){let r=this.subsystems.get(e);if(!r||r.status===t)return;let i={subsystem:e,status:t,previousStatus:r.status,reason:n,timestamp:Date.now()};r.status=t,r.since=i.timestamp,r.reason=n,this.emit(t,i),this.emit(`change`,i)}};const G={debug:0,info:1,warn:2,error:3},K=[];let q=process.env.AIKIT_LOG_LEVEL??`info`,J=!1,Y=process.env.AIKIT_LOG_FILE_SINK===`true`||process.env.AIKIT_LOG_FILE_SINK!==`false`&&!process.env.VITEST&&process.env.NODE_ENV!==`test`;function Ae(){return Y?process.env.VITEST||process.env.NODE_ENV===`test`?process.env.AIKIT_LOG_FILE_SINK===`true`:!0:!1}let X;function Z(){return X||=W(),X}function je(e){let t=e.toISOString().slice(0,10);return r(Z(),`${t}.jsonl`)}let Q=0;function Me(){let e=Date.now();if(!(e-Q<36e5)){Q=e;try{let t=Z(),n=new Date(e-30*864e5).toISOString().slice(0,10);for(let e of f(t))if(e.endsWith(`.jsonl`)&&e.slice(0,10)<n)try{g(r(t,e))}catch{}}catch{}}}function Ne(e,t){try{d(Z(),{recursive:!0}),o(je(t),`${e}\n`),Me()}catch{}}function Pe(e){q=e}function Fe(){return q}function Ie(e){Y=e}function Le(){X=void 0}function Re(e){J=e}function ze(e){if(e instanceof Error){let t={error:e.message};return J?(e.stack&&(t.stack=e.stack),e.cause!==void 0&&(t.cause=e.cause instanceof Error?e.cause.message:String(e.cause)),t):t}return{error:String(e)}}function Be(e){return K.push(e),()=>{let t=K.indexOf(e);t>=0&&K.splice(t,1)}}function Ve(e){function t(t,n,r){if(G[t]<G[q])return;let i=new Date,a={ts:i.toISOString(),level:t,component:e,msg:n,...r},o=JSON.stringify(a);(t===`warn`||t===`error`)&&console.error(o);for(let i of K)try{i({level:t,component:e,message:n,data:r})}catch{}Ae()&&(t===`warn`||t===`error`)&&Ne(o,i)}return{debug:(e,n)=>t(`debug`,e,n),info:(e,n)=>t(`info`,e,n),warn:(e,n)=>t(`warn`,e,n),error:(e,n)=>t(`error`,e,n)}}const $={maxAttempts:3,baseDelayMs:500,maxDelayMs:3e4,jitterFraction:.25};async function He(e,t={}){let{maxAttempts:n=$.maxAttempts,baseDelayMs:r=$.baseDelayMs,maxDelayMs:i=$.maxDelayMs,jitterFraction:a=$.jitterFraction}=t,o=t.shouldRetry??(e=>e instanceof D),s;for(let c=1;c<=n;c++)try{return await e()}catch(e){if(s=e,c>=n||!o(e,c))throw e;let l;if(e instanceof D&&e.retryAfterMs!=null&&e.retryAfterMs>0)l=Math.min(e.retryAfterMs,i);else{let e=r*2**(c-1),t=Math.min(e,i),n=t*a*(Math.random()*2-1);l=Math.round(t+n)}t.onRetry?.(e,c,l),await Ue(l)}throw s}function Ue(e){return new Promise(t=>setTimeout(t,e))}const We=[`indexed`,`curated`,`produced`],Ge=[`source`,`documentation`,`test`,`config`,`generated`],Ke=[`auto`,`manual`,`smart`],qe=[`efficient`,`normal`,`full`],Je=[`documentation`,`code-typescript`,`code-javascript`,`code-python`,`code-other`,`config-json`,`config-yaml`,`config-toml`,`config-env`,`test-code`,`cdk-stack`,`markdown`,`curated-knowledge`,`produced-knowledge`,`unknown`];export{S as AIKIT_GLOBAL_PATHS,b as AIKIT_PATHS,x as AIKIT_RUNTIME_PATHS,E as AikitError,ue as CATEGORY_PATTERN,ie as CHUNK_SIZES,Je as CONTENT_TYPES,re as CircuitBreaker,y as CircuitOpenError,ye as ConfigError,de as DEFAULT_CATEGORIES,ae as EMBEDDING_DEFAULTS,ge as EmbeddingError,ce as FILE_LIMITS,ke as HealthBus,Ke as INDEX_MODES,ve as IndexError,We as KNOWLEDGE_ORIGINS,oe as MODEL_REGISTRY,O as PermanentError,le as SEARCH_DEFAULTS,Ge as SOURCE_TYPES,se as STORE_DEFAULTS,_e as StoreError,qe as TOKEN_BUDGETS,D as TransientError,Be as addLogListener,R as computePartitionKey,me as contentTypeToSourceType,Ve as createLogger,pe as detectContentType,L as getGlobalDataDir,Fe as getLogLevel,U as getPartitionDir,F as getWorkspacePartitionDir,xe as isPermanent,be as isTransient,Oe as isUserInstalled,H as listWorkspaces,z as loadRegistry,De as lookupWorkspace,I as migrateLegacyWorkspaceLayout,V as registerWorkspace,Le as resetLogDir,W as resolveLogDir,we as resolveStateDir,B as saveRegistry,ze as serializeError,Re as setDetailedErrorLoggingEnabled,Ie as setFileSinkEnabled,Pe as setLogLevel,he as sourceTypeContentTypes,He as withRetry};
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{rm as e}from"node:fs/promises";import{homedir as t}from"node:os";import{join as n}from"node:path";import{EMBEDDING_DEFAULTS as r}from"../../core/dist/index.js";let i=null;function a(e){if(!(e instanceof Error))return!1;let t=e.code;return t===`ERR_MODULE_NOT_FOUND`||t===`MODULE_NOT_FOUND`?!0:/cannot find (module|package)|module not found/i.test(e.message)}async function o(){if(!i){try{i=await import(`@huggingface/transformers`)}catch(e){if(a(e)){let{createRequire:t}=await import(`node:module`),n=t(import.meta.url);try{i=n("@huggingface/transformers")}catch(t){let n=e instanceof Error?e.message:String(e),r=t instanceof Error?t.message:String(t);throw Error(`Unable to load @huggingface/transformers via ESM or CJS. ESM: ${n}; CJS: ${r}`)}}else throw e}i.env.cacheDir=n(t(),`.cache`,`huggingface`,`transformers-js`)}return i}var s=class{pipe=null;shutdownPromise=null;dimensions;modelId;nativeDim;queryPrefix;threadConfig;constructor(e={}){if(this.modelId=e.model??r.model,this.nativeDim=e.nativeDim??r.nativeDim,this.dimensions=e.dimensions??r.dimensions,this.dimensions>this.nativeDim)throw Error(`Configured dimensions (${this.dimensions}) exceeds model native output (${this.nativeDim}). Matryoshka truncation cannot upscale — dimensions must be <= nativeDim.`);this.queryPrefix=e.queryPrefix??this.detectQueryPrefix(this.modelId),this.threadConfig={interOp:e.interOpNumThreads??1,intraOp:e.intraOpNumThreads??4}}detectQueryPrefix(e){let t=e.toLowerCase();return t.includes(`bge`)||t.includes(`mxbai-embed`)?`Represent this sentence for searching relevant passages: `:t.includes(`/e5-`)||t.includes(`multilingual-e5`)?`query: `:``}getPipelineOptions(e){let t=e.backends.onnx;t.wasm||={};let n=t.wasm;return n.numThreads=this.threadConfig.intraOp,{dtype:`q8`,session_options:{interOpNumThreads:this.threadConfig.interOp,intraOpNumThreads:this.threadConfig.intraOp}}}computeNorm(e){let t=0;for(let n=0;n<e.length;n++)t+=e[n]*e[n];return Math.sqrt(t)}truncateAndRenorm(e){if(this.dimensions>=this.nativeDim){let t=this.computeNorm(e);if(!Number.isFinite(t))throw Error(`Embedding produced non-finite norm — output contained NaN or Infinity`);if(t===0)throw Error(`Embedding produced zero-norm vector from ONNX output`);return e}let t=e.subarray(0,this.dimensions),n=this.computeNorm(t);if(!Number.isFinite(n))throw Error(`Embedding produced non-finite norm — output contained NaN or Infinity`);if(n===0)throw Error(`Embedding produced zero-norm vector after truncation — input may be degenerate`);let r=new Float32Array(this.dimensions);for(let e=0;e<this.dimensions;e++)r[e]=t[e]/n;return r}async initialize(){if(this.pipe)return;this.shutdownPromise=null;let{pipeline:r,env:i}=await o();try{this.pipe=await r(`feature-extraction`,this.modelId,this.getPipelineOptions(i))}catch(a){let o=a.message?.toLowerCase()??``;if(this.isCorruptionError(o)){let a=n(i.cacheDir??n(t(),`.cache`,`huggingface`,`transformers-js`),this.modelId);console.error(`[aikit:auto-heal] Detected corrupted model cache for "${this.modelId}". Clearing cache at ${a} and retrying download...`);try{await e(a,{recursive:!0,force:!0})}catch{}try{this.pipe=await r(`feature-extraction`,this.modelId,this.getPipelineOptions(i)),console.error(`[aikit:auto-heal] Model "${this.modelId}" re-downloaded successfully.`);return}catch(e){throw Error(`Failed to initialize embedding model "${this.modelId}" after auto-heal: ${e.message}`)}}throw Error(`Failed to initialize embedding model "${this.modelId}": ${a.message}`)}}isCorruptionError(e){return[`protobuf`,`invalid model`,`invalid onnx`,`unexpected end`,`unexpected token`,`failed to load`,`checksum`,`corrupt`,`could not load`,`onnx`,`malformed`].some(t=>e.includes(t))}async shutdown(){return this.shutdownPromise||=this._doShutdown(),this.shutdownPromise}async _doShutdown(){let e=this.pipe;if(e)try{let t=e;typeof t.dispose==`function`?await t.dispose():typeof t.model?.dispose==`function`&&await t.model.dispose()}catch{}finally{this.pipe=null}}async embed(e){this.pipe||await this.initialize();let t=await this.pipe?.(e,{pooling:`mean`,normalize:!0});if(!t?.data)throw Error(`Embedding pipeline returned no output`);try{let e=new Float32Array(t.data);return this.truncateAndRenorm(e)}finally{t.dispose?.()}}async embedQuery(e){return this.embed(this.queryPrefix+e)}async embedBatch(e,t=64){if(e.length===0)return[];this.pipe||await this.initialize();let n=[];for(let r=0;r<e.length;r+=t){let i=e.slice(r,r+t),a=await this.pipe?.(i,{pooling:`mean`,normalize:!0});if(!a?.data)throw Error(`Embedding pipeline returned no output`);try{if(i.length===1){let e=new Float32Array(a.data);n.push(this.truncateAndRenorm(e))}else for(let e=0;e<i.length;e++){let t=e*this.nativeDim,r=a.data.slice(t,t+this.nativeDim);n.push(this.truncateAndRenorm(new Float32Array(r)))}}finally{a.dispose?.()}}return n}};let c=null,l=null,u=!1;const d=Number(process.env.AIKIT_EMBED_IDLE_MS),f=Number.isFinite(d)&&d>=0?d:0,p=Number(process.env.AIKIT_EMBED_MAX_RSS_MB),m=Number.isFinite(p)&&p>0?p:1536;function h(){let e=process.memoryUsage;return(typeof e.rss==`function`?e.rss():e().rss)/(1024*1024)>m}function g(e){process.send?.(e)}async function _(e){await new Promise(t=>{if(!process.send){t();return}let n=!1,r=()=>{n||(n=!0,t())};try{process.send.length<2?(process.send(e),r()):(process.send(e,()=>r()),setTimeout(r,25).unref?.())}catch{r()}})}function v(){l&&=(clearTimeout(l),null)}async function y(){if(!c)return;let e=c;c=null,await e.shutdown?.()}async function b(e,t){u&&process.exit(e),u=!0,v(),t?.notifyIdle&&await _({type:`idle-exit`});try{await y()}finally{process.exit(e)}}function x(){v(),f!==0&&(l=setTimeout(()=>{b(0,{notifyIdle:!0})},f))}function S(e){return Array.from(e)}function C(e){return e instanceof Error?e.message:String(e)}function w(){if(!c)throw Error(`Embedder not initialized`);return c}async function T(e,t){await _({type:`error`,id:e,message:C(t)})}async function E(e){v();try{switch(e.type){case`init`:await y(),c=new s(e.config),await c.initialize(),await c.embed(`warmup`),g({type:`ready`,dimensions:c.dimensions,modelId:c.modelId});break;case`embed`:{let t=await w().embed(e.text);g({type:`result`,id:e.id,data:S(t)});break}case`embedBatch`:{let t=await w().embedBatch(e.texts,e.batchSize);g({type:`batchResult`,id:e.id,data:t.map(e=>S(e))});break}case`embedQuery`:{let t=await w().embedQuery(e.text);g({type:`result`,id:e.id,data:S(t)});break}case`shutdown`:await b(0);return}}catch(t){if(await T(e.type===`shutdown`?`shutdown`:e.type===`init`?`init`:e.id,t),e.type===`init`){await b(1);return}}if(h()){await b(0,{notifyIdle:!0});return}x()}async function D(e,t){await T(e,t),await b(1)}process.on(`message`,e=>{E(e)}),process.on(`SIGTERM`,()=>{b(0)}),process.on(`uncaughtException`,e=>{D(`fatal`,e)}),process.on(`unhandledRejection`,e=>{D(`fatal`,e)});export{};
2
+ import{rm as e}from"node:fs/promises";import{homedir as t}from"node:os";import{join as n}from"node:path";import{EMBEDDING_DEFAULTS as r,MODEL_REGISTRY as i}from"../../core/dist/index.js";let a=null;function o(e){if(!(e instanceof Error))return!1;let t=e.code;return t===`ERR_MODULE_NOT_FOUND`||t===`MODULE_NOT_FOUND`?!0:/cannot find (module|package)|module not found/i.test(e.message)}async function s(){if(!a){try{a=await import(`@huggingface/transformers`)}catch(e){if(o(e)){let{createRequire:t}=await import(`node:module`),n=t(import.meta.url);try{a=n("@huggingface/transformers")}catch(t){let n=e instanceof Error?e.message:String(e),r=t instanceof Error?t.message:String(t);throw Error(`Unable to load @huggingface/transformers via ESM or CJS. ESM: ${n}; CJS: ${r}`)}}else throw e}a.env.cacheDir=n(t(),`.cache`,`huggingface`,`transformers-js`)}return a}var c=class{pipe=null;shutdownPromise=null;dimensions;modelId;nativeDim;queryPrefix;pooling;threadConfig;constructor(e={}){this.modelId=e.model??r.model;let t=i[this.modelId];if(this.nativeDim=e.nativeDim??t?.nativeDim??r.nativeDim,this.dimensions=e.dimensions??t?.dimensions??r.dimensions,this.dimensions>this.nativeDim)throw Error(`Configured dimensions (${this.dimensions}) exceeds model native output (${this.nativeDim}). Matryoshka truncation cannot upscale — dimensions must be <= nativeDim.`);this.queryPrefix=e.queryPrefix??t?.queryPrefix??this.detectQueryPrefix(this.modelId),this.pooling=e.pooling??t?.pooling??`mean`,this.threadConfig={interOp:e.interOpNumThreads??1,intraOp:e.intraOpNumThreads??4}}detectQueryPrefix(e){let t=e.toLowerCase();return t.includes(`bge`)||t.includes(`mxbai-embed`)&&!t.includes(`xsmall`)?`Represent this sentence for searching relevant passages: `:t.includes(`/e5-`)||t.includes(`multilingual-e5`)?`query: `:``}getPipelineOptions(e){let t=e.backends.onnx;t.wasm||={};let n=t.wasm;return n.numThreads=this.threadConfig.intraOp,{dtype:`q8`,session_options:{interOpNumThreads:this.threadConfig.interOp,intraOpNumThreads:this.threadConfig.intraOp}}}computeNorm(e){let t=0;for(let n=0;n<e.length;n++)t+=e[n]*e[n];return Math.sqrt(t)}truncateAndRenorm(e){if(this.dimensions>=this.nativeDim){let t=this.computeNorm(e);if(!Number.isFinite(t))throw Error(`Embedding produced non-finite norm — output contained NaN or Infinity`);if(t===0)throw Error(`Embedding produced zero-norm vector from ONNX output`);return e}let t=e.subarray(0,this.dimensions),n=this.computeNorm(t);if(!Number.isFinite(n))throw Error(`Embedding produced non-finite norm — output contained NaN or Infinity`);if(n===0)throw Error(`Embedding produced zero-norm vector after truncation — input may be degenerate`);let r=new Float32Array(this.dimensions);for(let e=0;e<this.dimensions;e++)r[e]=t[e]/n;return r}async initialize(){if(this.pipe)return;this.shutdownPromise=null;let{pipeline:r,env:i}=await s();try{this.pipe=await r(`feature-extraction`,this.modelId,this.getPipelineOptions(i))}catch(a){let o=a.message?.toLowerCase()??``;if(this.isCorruptionError(o)){let a=n(i.cacheDir??n(t(),`.cache`,`huggingface`,`transformers-js`),this.modelId);console.error(`[aikit:auto-heal] Detected corrupted model cache for "${this.modelId}". Clearing cache at ${a} and retrying download...`);try{await e(a,{recursive:!0,force:!0})}catch{}try{this.pipe=await r(`feature-extraction`,this.modelId,this.getPipelineOptions(i)),console.error(`[aikit:auto-heal] Model "${this.modelId}" re-downloaded successfully.`);return}catch(e){throw Error(`Failed to initialize embedding model "${this.modelId}" after auto-heal: ${e.message}`)}}throw Error(`Failed to initialize embedding model "${this.modelId}": ${a.message}`)}}isCorruptionError(e){return[`protobuf`,`invalid model`,`invalid onnx`,`unexpected end`,`unexpected token`,`failed to load`,`checksum`,`corrupt`,`could not load`,`onnx`,`malformed`].some(t=>e.includes(t))}async shutdown(){return this.shutdownPromise||=this._doShutdown(),this.shutdownPromise}async _doShutdown(){let e=this.pipe;if(e)try{let t=e;typeof t.dispose==`function`?await t.dispose():typeof t.model?.dispose==`function`&&await t.model.dispose()}catch{}finally{this.pipe=null}}async embed(e){this.pipe||await this.initialize();let t=await this.pipe?.(e,{pooling:this.pooling,normalize:!0});if(!t?.data)throw Error(`Embedding pipeline returned no output`);try{let e=new Float32Array(t.data);return this.truncateAndRenorm(e)}finally{t.dispose?.()}}async embedQuery(e){return this.embed(this.queryPrefix+e)}async embedBatch(e,t=64){if(e.length===0)return[];this.pipe||await this.initialize();let n=[];for(let r=0;r<e.length;r+=t){let i=e.slice(r,r+t),a=await this.pipe?.(i,{pooling:this.pooling,normalize:!0});if(!a?.data)throw Error(`Embedding pipeline returned no output`);try{if(i.length===1){let e=new Float32Array(a.data);n.push(this.truncateAndRenorm(e))}else for(let e=0;e<i.length;e++){let t=e*this.nativeDim,r=a.data.slice(t,t+this.nativeDim);n.push(this.truncateAndRenorm(new Float32Array(r)))}}finally{a.dispose?.()}}return n}};let l=null,u=null,d=!1;const f=Number(process.env.AIKIT_EMBED_IDLE_MS),p=Number.isFinite(f)&&f>=0?f:0,m=Number(process.env.AIKIT_EMBED_MAX_RSS_MB),h=Number.isFinite(m)&&m>0?m:1536;function g(){let e=process.memoryUsage;return(typeof e.rss==`function`?e.rss():e().rss)/(1024*1024)>h}function _(e){process.send?.(e)}async function v(e){await new Promise(t=>{if(!process.send){t();return}let n=!1,r=()=>{n||(n=!0,t())};try{process.send.length<2?(process.send(e),r()):(process.send(e,()=>r()),setTimeout(r,25).unref?.())}catch{r()}})}function y(){u&&=(clearTimeout(u),null)}async function b(){if(!l)return;let e=l;l=null,await e.shutdown?.()}async function x(e,t){d&&process.exit(e),d=!0,y(),t?.notifyIdle&&await v({type:`idle-exit`});try{await b()}finally{process.exit(e)}}function S(){y(),p!==0&&(u=setTimeout(()=>{x(0,{notifyIdle:!0})},p))}function C(e){return Array.from(e)}function w(e){return e instanceof Error?e.message:String(e)}function T(){if(!l)throw Error(`Embedder not initialized`);return l}async function E(e,t){await v({type:`error`,id:e,message:w(t)})}async function D(e){y();try{switch(e.type){case`init`:await b(),l=new c(e.config),await l.initialize(),await l.embed(`warmup`),_({type:`ready`,dimensions:l.dimensions,modelId:l.modelId});break;case`embed`:{let t=await T().embed(e.text);_({type:`result`,id:e.id,data:C(t)});break}case`embedBatch`:{let t=await T().embedBatch(e.texts,e.batchSize);_({type:`batchResult`,id:e.id,data:t.map(e=>C(e))});break}case`embedQuery`:{let t=await T().embedQuery(e.text);_({type:`result`,id:e.id,data:C(t)});break}case`shutdown`:await x(0);return}}catch(t){if(await E(e.type===`shutdown`?`shutdown`:e.type===`init`?`init`:e.id,t),e.type===`init`){await x(1);return}}if(g()){await x(0,{notifyIdle:!0});return}S()}async function O(e,t){await E(e,t),await x(1)}process.on(`message`,e=>{D(e)}),process.on(`SIGTERM`,()=>{x(0)}),process.on(`uncaughtException`,e=>{O(`fatal`,e)}),process.on(`unhandledRejection`,e=>{O(`fatal`,e)});export{};
@@ -32,6 +32,7 @@ interface EmbedderProxyOptions {
32
32
  dimensions?: number;
33
33
  nativeDim?: number;
34
34
  queryPrefix?: string;
35
+ pooling?: 'mean' | 'cls';
35
36
  interOpNumThreads?: number;
36
37
  intraOpNumThreads?: number;
37
38
  initTimeoutMs?: number;
@@ -109,12 +110,14 @@ declare class OnnxEmbedder implements IEmbedder {
109
110
  readonly modelId: string;
110
111
  private readonly nativeDim;
111
112
  private readonly queryPrefix;
113
+ private readonly pooling;
112
114
  private readonly threadConfig;
113
115
  constructor(options?: {
114
116
  model?: string;
115
117
  dimensions?: number;
116
118
  nativeDim?: number;
117
119
  queryPrefix?: string;
120
+ pooling?: 'mean' | 'cls';
118
121
  interOpNumThreads?: number;
119
122
  intraOpNumThreads?: number;
120
123
  });
@@ -1 +1 @@
1
- import{fork as e}from"node:child_process";import{randomUUID as t}from"node:crypto";import{existsSync as n}from"node:fs";import{dirname as r,join as i}from"node:path";import{fileURLToPath as a}from"node:url";import{CircuitBreaker as o,CircuitOpenError as s,EMBEDDING_DEFAULTS as c,HealthBus as l}from"../../core/dist/index.js";import{rm as u}from"node:fs/promises";import{homedir as d}from"node:os";var f=class{options;logger;healthBus=l.instance();cb;initTimeoutMs;requestTimeoutMs;maxRetries;retryBaseDelayMs;workerAvailable=!0;workerPath=i(r(a(import.meta.url)),`embedder-worker.js`);pendingRequests=new Map;childState=new WeakMap;childErrors=new WeakMap;child=null;readyChild=null;pendingInit=null;pendingShutdown=null;initializePromise=null;shutdownPromise=null;cooldownRespawnTimer=null;currentDimensions;currentModelId;coldStart=!0;constructor(e={}){this.options=e,this.logger=e.logger,this.healthBus.register(`embedder`),this.cb=new o({threshold:3,cooldownMs:6e4,name:`embedder`}),this.cb.on(`open`,()=>{this.healthBus.reportDegraded(`embedder`,`Circuit breaker open — consecutive timeouts`),this.startCooldownRespawn()}),this.cb.on(`closed`,()=>{this.healthBus.reportRecovered(`embedder`)}),this.initTimeoutMs=Math.max(0,e.initTimeoutMs??6e4),this.requestTimeoutMs=Math.max(0,e.requestTimeoutMs??(process.platform===`win32`?6e4:3e4)),this.maxRetries=Math.max(0,e.maxRetries??3),this.retryBaseDelayMs=Math.max(0,e.retryBaseDelayMs??500),this.currentDimensions=e.dimensions??c.dimensions,this.currentModelId=e.model??c.model}get dimensions(){return this.currentDimensions}get modelId(){return this.currentModelId}get isCircuitOpen(){return this.cb.isOpen()}async initialize(){if(!(this.readyChild&&this.child===this.readyChild)&&this.workerAvailable){if(!n(this.workerPath)){this.workerAvailable=!1,console.warn(`[aikit] Embedder worker not found at ${this.workerPath}. Embedding disabled - search will use keyword matching only. This usually means the npx cache is corrupted; restart to fix.`);return}if(this.initializePromise)return this.initializePromise;if(this.shutdownPromise){try{await this.shutdownPromise}catch{}if(this.readyChild&&this.child===this.readyChild)return}return this.initializePromise=this.startWorker().finally(()=>{this.initializePromise=null}),this.initializePromise}}async embed(e){if(!this.workerAvailable||(this.assertCircuitClosed(),await this.initialize(),!this.workerAvailable))throw Error(`Embedding worker is not available — embeddings cannot be computed. Check server logs for initialization errors.`);return this.sendVectorRequestWithRetry({type:`embed`,text:e})}async embedQuery(e){if(!this.workerAvailable||(this.assertCircuitClosed(),await this.initialize(),!this.workerAvailable))throw Error(`Embedding worker is not available — embeddings cannot be computed. Check server logs for initialization errors.`);return this.sendVectorRequestWithRetry({type:`embedQuery`,text:e})}async embedBatch(e,t){if(e.length===0)return[];if(!this.workerAvailable||(this.assertCircuitClosed(),await this.initialize(),!this.workerAvailable))throw Error(`Embedding worker is not available — embeddings cannot be computed. Check server logs for initialization errors.`);return this.withWorkerExitRetry(`embedBatch`,()=>this.sendBatchRequest(e,t))}async sendBatchRequest(e,n){await this.initialize();let r=this.requireReadyChild(),i=t(),a=new Promise((e,t)=>{this.pendingRequests.set(i,{child:r,resolve:t=>e(t),reject:t})});try{r.send({type:`embedBatch`,id:i,texts:e,batchSize:n})}catch(e){throw this.pendingRequests.delete(i),this.toError(e,`Failed to send embedBatch request to worker`)}let o=this.requestTimeoutMs>0?Math.max(this.requestTimeoutMs*3,9e4):0;if(o>0){let t,n=new Promise((n,r)=>{t=setTimeout(()=>{this.pendingRequests.delete(i),this.markWorkerUnresponsive(),r(Error(`Embedder embedBatch request timed out after ${o/1e3}s (${e.length} texts). The worker has been killed and will attempt to respawn automatically.`))},o)});try{return await Promise.race([a,n])}finally{t!==void 0&&clearTimeout(t)}}return a}async shutdown(){if(this.clearCooldownRespawnTimer(),this.shutdownPromise)return this.shutdownPromise;let e=this.child;if(!e)return;let t=this.requireChildState(e);t.shutdownRequested=!0,this.readyChild===e&&(this.readyChild=null),this.shutdownPromise=new Promise((t,n)=>{this.pendingShutdown={child:e,resolve:t,reject:n}}).finally(()=>{this.shutdownPromise=null});try{e.send({type:`shutdown`})}catch(t){let n=this.toError(t,`Failed to send shutdown request to worker`);throw this.clearChildReference(e),this.rejectPendingForChild(e,n),this.rejectLifecycleIfOwned(`shutdown`,e,n),n}return this.shutdownPromise}async startWorker(){this.child&&this.readyChild!==this.child&&(this.child=null),this.clearCooldownRespawnTimer(),this.coldStart=!0;let e=this.spawnChild();this.child=e,this.readyChild=null;let t=new Promise((t,n)=>{this.pendingInit={child:e,resolve:t,reject:n}});try{e.send({type:`init`,config:this.buildInitConfig()})}catch(t){let n=this.toError(t,`Failed to send init request to worker`);throw this.pendingInit=null,this.clearChildReference(e),n}if(this.initTimeoutMs>0){let n,r=new Promise((e,t)=>{n=setTimeout(()=>{t(Error(`Embedder worker initialization timed out after ${this.initTimeoutMs/1e3}s. The ONNX model may be downloading or the child process is stuck. Check network connectivity and disk space, or restart the server.`))},this.initTimeoutMs)});try{await Promise.race([t,r]);return}catch(t){this.pendingInit=null;try{e.kill()}catch{}throw this.clearChildReference(e),t}finally{n!==void 0&&clearTimeout(n)}}await t}spawnChild(){let t=e(this.workerPath,[],{env:this.buildChildEnv()});return this.childState.set(t,{idleExitNotified:!1,shutdownRequested:!1,terminated:!1}),t.on(`message`,e=>{this.handleChildMessage(t,e)}),t.once(`error`,e=>{this.handleChildFailure(t,this.toError(e,`Embedder worker failed`))}),t.once(`exit`,(e,n)=>{this.handleChildExit(t,e,n)}),t}handleChildMessage(e,t){switch(t.type){case`ready`:{this.currentDimensions=t.dimensions,this.currentModelId=t.modelId,this.healthBus.reportRecovered(`embedder`),this.child===e&&(this.readyChild=e,this.cb.getState()!==`closed`&&this.cb.reset());let n=this.pendingInit;n?.child===e&&(this.pendingInit=null,n.resolve());return}case`result`:{let n=this.pendingRequests.get(t.id);if(!n||n.child!==e)return;this.pendingRequests.delete(t.id),this.coldStart=!1,this.cb.recordSuccess(),n.resolve(new Float32Array(t.data));return}case`batchResult`:{let n=this.pendingRequests.get(t.id);if(!n||n.child!==e)return;if(this.pendingRequests.delete(t.id),!t.data||!Array.isArray(t.data)||t.data.length===0)n.reject(Error(`Worker returned empty or invalid batch result`));else{let e=t.data.map(e=>new Float32Array(e)),r=e.findIndex(e=>e.length===0);r>=0?n.reject(Error(`Worker returned zero-length vector at index ${r}`)):(this.coldStart=!1,this.cb.recordSuccess(),n.resolve(e))}return}case`error`:{let n=Error(t.message);if(this.childErrors.set(e,n),t.id===`init`){this.clearChildReference(e),this.rejectLifecycleIfOwned(`init`,e,n);return}if(t.id===`shutdown`){this.rejectLifecycleIfOwned(`shutdown`,e,n);return}let r=this.pendingRequests.get(t.id);if(!r||r.child!==e)return;this.pendingRequests.delete(t.id),r.reject(n);return}case`idle-exit`:{let t=this.requireChildState(e);t.idleExitNotified=!0,this.clearChildReference(e);return}}}handleChildExit(e,t,n){let r=this.requireChildState(e);if(r.terminated)return;r.terminated=!0,this.clearChildReference(e);let i=t===0&&n===null,a=r.shutdownRequested||r.idleExitNotified||i,o=this.childErrors.get(e)??Error(a?`Embedder worker exited before completing request`:`Embedder worker exited unexpectedly (code ${t??`null`}${n?`, signal ${n}`:``})`);this.rejectLifecycleIfOwned(`init`,e,o),a?this.resolveLifecycleIfOwned(`shutdown`,e):this.rejectLifecycleIfOwned(`shutdown`,e,o),this.rejectPendingForChild(e,o),a||this.cb.recordFailure()}handleChildFailure(e,t){let n=this.requireChildState(e);n.terminated||(n.terminated=!0,this.clearChildReference(e),this.rejectLifecycleIfOwned(`init`,e,t),this.rejectLifecycleIfOwned(`shutdown`,e,t),this.rejectPendingForChild(e,t))}async sendVectorRequestWithRetry(e){return this.withWorkerExitRetry(e.type,()=>this.sendVectorRequest(e))}async sendVectorRequest(e){await this.initialize();let n=this.requireReadyChild(),r=t(),i=this.requestTimeoutMs>0?this.coldStart?this.requestTimeoutMs*2:this.requestTimeoutMs:0,a=new Promise((e,t)=>{this.pendingRequests.set(r,{child:n,resolve:t=>e(t),reject:t})});try{n.send({...e,id:r})}catch(t){throw this.pendingRequests.delete(r),this.toError(t,`Failed to send ${e.type} request to worker`)}if(i>0){let t,n=new Promise((n,a)=>{t=setTimeout(()=>{this.pendingRequests.delete(r),this.markWorkerUnresponsive(),a(Error(`Embedder ${e.type} request timed out after ${i/1e3}s. The worker has been killed and will attempt to respawn automatically.`))},i)});try{return await Promise.race([a,n])}finally{t!==void 0&&clearTimeout(t)}}return a}async withWorkerExitRetry(e,t){let n=null,r=this.maxRetries;for(let i=0;i<=r;i++)try{return await t()}catch(t){let a=this.toError(t,`Failed to process ${e} request`);if(!this.isWorkerExitError(a))throw a;if(n??=a,i===0&&/exited/i.test(a.message)&&!/timed out/i.test(a.message)&&(r=Math.min(r,1)),i===r)throw n;let o=i+1,s=this.retryBaseDelayMs*2**i;if(this.healthBus.reportDegraded(`embedder`,`Worker crashed during ${e} — retrying (${o}/${r})`),this.logger?.warn?.(`Embedder retry ${o}/${r} after ${s}ms`,{requestType:e,delayMs:s,error:a.message}),this.child=null,this.readyChild=null,await this.wait(s),this.cb.isOpen())throw n??a}throw n??Error(`Failed to process ${e} request`)}isWorkerExitError(e){return/embedder worker exited|EPIPE|ECONNRESET|ERR_IPC_CHANNEL_CLOSED|channel closed|write after end/i.test(e.message)}wait(e){return new Promise(t=>{setTimeout(t,e)})}requireReadyChild(){if(!this.child||this.readyChild!==this.child)throw Error(`Embedder worker is not initialized`);return this.child}buildInitConfig(){return{model:this.options.model,dimensions:this.options.dimensions,nativeDim:this.options.nativeDim,queryPrefix:this.options.queryPrefix,interOpNumThreads:this.options.interOpNumThreads,intraOpNumThreads:this.options.intraOpNumThreads}}buildChildEnv(){return this.options.idleTimeoutMs===void 0?process.env:{...process.env,AIKIT_EMBED_IDLE_MS:String(this.options.idleTimeoutMs)}}requireChildState(e){let t=this.childState.get(e);if(!t)throw Error(`Embedder worker state not found`);return t}clearChildReference(e){this.child===e&&(this.child=null),this.readyChild===e&&(this.readyChild=null)}clearCooldownRespawnTimer(){this.cooldownRespawnTimer&&=(clearTimeout(this.cooldownRespawnTimer),null)}startCooldownRespawn(){this.clearCooldownRespawnTimer(),this.cooldownRespawnTimer=setTimeout(()=>{this.cooldownRespawnTimer=null,!this.child&&!this.shutdownPromise&&this.workerAvailable&&this.initialize().catch(()=>{})},6e4),this.logger?.warn?.(`Embedder circuit breaker OPEN — too many consecutive failures`,{cooldownMs:6e4})}markWorkerUnresponsive(){let e=this.child;if(e){try{e.kill()}catch{}this.clearChildReference(e),this.cb.recordFailure(),this.cb.isOpen()||setImmediate(()=>{!this.child&&this.workerAvailable&&!this.shutdownPromise&&this.initialize().catch(()=>{})})}}assertCircuitClosed(){if(this.cb.isOpen())throw new s(this.cb.remainingCooldownMs())}rejectPendingForChild(e,t){for(let[n,r]of this.pendingRequests)r.child===e&&(this.pendingRequests.delete(n),r.reject(t))}resolveLifecycleIfOwned(e,t){let n=this.pendingShutdown;!n||n.child!==t||(this.pendingShutdown=null,n.resolve())}rejectLifecycleIfOwned(e,t,n){let r=e===`init`?this.pendingInit:this.pendingShutdown;!r||r.child!==t||(e===`init`?this.pendingInit=null:this.pendingShutdown=null,r.reject(n))}toError(e,t){return e instanceof Error?e:Error(`${t}: ${String(e)}`)}};let p=null;function m(e){if(!(e instanceof Error))return!1;let t=e.code;return t===`ERR_MODULE_NOT_FOUND`||t===`MODULE_NOT_FOUND`?!0:/cannot find (module|package)|module not found/i.test(e.message)}async function h(){if(!p){try{p=await import(`@huggingface/transformers`)}catch(e){if(m(e)){let{createRequire:t}=await import(`node:module`),n=t(import.meta.url);try{p=n("@huggingface/transformers")}catch(t){let n=e instanceof Error?e.message:String(e),r=t instanceof Error?t.message:String(t);throw Error(`Unable to load @huggingface/transformers via ESM or CJS. ESM: ${n}; CJS: ${r}`)}}else throw e}p.env.cacheDir=i(d(),`.cache`,`huggingface`,`transformers-js`)}return p}var g=class{pipe=null;shutdownPromise=null;dimensions;modelId;nativeDim;queryPrefix;threadConfig;constructor(e={}){if(this.modelId=e.model??c.model,this.nativeDim=e.nativeDim??c.nativeDim,this.dimensions=e.dimensions??c.dimensions,this.dimensions>this.nativeDim)throw Error(`Configured dimensions (${this.dimensions}) exceeds model native output (${this.nativeDim}). Matryoshka truncation cannot upscale — dimensions must be <= nativeDim.`);this.queryPrefix=e.queryPrefix??this.detectQueryPrefix(this.modelId),this.threadConfig={interOp:e.interOpNumThreads??1,intraOp:e.intraOpNumThreads??4}}detectQueryPrefix(e){let t=e.toLowerCase();return t.includes(`bge`)||t.includes(`mxbai-embed`)?`Represent this sentence for searching relevant passages: `:t.includes(`/e5-`)||t.includes(`multilingual-e5`)?`query: `:``}getPipelineOptions(e){let t=e.backends.onnx;t.wasm||={};let n=t.wasm;return n.numThreads=this.threadConfig.intraOp,{dtype:`q8`,session_options:{interOpNumThreads:this.threadConfig.interOp,intraOpNumThreads:this.threadConfig.intraOp}}}computeNorm(e){let t=0;for(let n=0;n<e.length;n++)t+=e[n]*e[n];return Math.sqrt(t)}truncateAndRenorm(e){if(this.dimensions>=this.nativeDim){let t=this.computeNorm(e);if(!Number.isFinite(t))throw Error(`Embedding produced non-finite norm — output contained NaN or Infinity`);if(t===0)throw Error(`Embedding produced zero-norm vector from ONNX output`);return e}let t=e.subarray(0,this.dimensions),n=this.computeNorm(t);if(!Number.isFinite(n))throw Error(`Embedding produced non-finite norm — output contained NaN or Infinity`);if(n===0)throw Error(`Embedding produced zero-norm vector after truncation — input may be degenerate`);let r=new Float32Array(this.dimensions);for(let e=0;e<this.dimensions;e++)r[e]=t[e]/n;return r}async initialize(){if(this.pipe)return;this.shutdownPromise=null;let{pipeline:e,env:t}=await h();try{this.pipe=await e(`feature-extraction`,this.modelId,this.getPipelineOptions(t))}catch(n){let r=n.message?.toLowerCase()??``;if(this.isCorruptionError(r)){let n=i(t.cacheDir??i(d(),`.cache`,`huggingface`,`transformers-js`),this.modelId);console.error(`[aikit:auto-heal] Detected corrupted model cache for "${this.modelId}". Clearing cache at ${n} and retrying download...`);try{await u(n,{recursive:!0,force:!0})}catch{}try{this.pipe=await e(`feature-extraction`,this.modelId,this.getPipelineOptions(t)),console.error(`[aikit:auto-heal] Model "${this.modelId}" re-downloaded successfully.`);return}catch(e){throw Error(`Failed to initialize embedding model "${this.modelId}" after auto-heal: ${e.message}`)}}throw Error(`Failed to initialize embedding model "${this.modelId}": ${n.message}`)}}isCorruptionError(e){return[`protobuf`,`invalid model`,`invalid onnx`,`unexpected end`,`unexpected token`,`failed to load`,`checksum`,`corrupt`,`could not load`,`onnx`,`malformed`].some(t=>e.includes(t))}async shutdown(){return this.shutdownPromise||=this._doShutdown(),this.shutdownPromise}async _doShutdown(){let e=this.pipe;if(e)try{let t=e;typeof t.dispose==`function`?await t.dispose():typeof t.model?.dispose==`function`&&await t.model.dispose()}catch{}finally{this.pipe=null}}async embed(e){this.pipe||await this.initialize();let t=await this.pipe?.(e,{pooling:`mean`,normalize:!0});if(!t?.data)throw Error(`Embedding pipeline returned no output`);try{let e=new Float32Array(t.data);return this.truncateAndRenorm(e)}finally{t.dispose?.()}}async embedQuery(e){return this.embed(this.queryPrefix+e)}async embedBatch(e,t=64){if(e.length===0)return[];this.pipe||await this.initialize();let n=[];for(let r=0;r<e.length;r+=t){let i=e.slice(r,r+t),a=await this.pipe?.(i,{pooling:`mean`,normalize:!0});if(!a?.data)throw Error(`Embedding pipeline returned no output`);try{if(i.length===1){let e=new Float32Array(a.data);n.push(this.truncateAndRenorm(e))}else for(let e=0;e<i.length;e++){let t=e*this.nativeDim,r=a.data.slice(t,t+this.nativeDim);n.push(this.truncateAndRenorm(new Float32Array(r)))}}finally{a.dispose?.()}}return n}};export{f as EmbedderProxy,g as OnnxEmbedder};
1
+ import{fork as e}from"node:child_process";import{randomUUID as t}from"node:crypto";import{existsSync as n}from"node:fs";import{dirname as r,join as i}from"node:path";import{fileURLToPath as a}from"node:url";import{CircuitBreaker as o,CircuitOpenError as s,EMBEDDING_DEFAULTS as c,HealthBus as l,MODEL_REGISTRY as u}from"../../core/dist/index.js";import{rm as d}from"node:fs/promises";import{homedir as f}from"node:os";var p=class{options;logger;healthBus=l.instance();cb;initTimeoutMs;requestTimeoutMs;maxRetries;retryBaseDelayMs;workerAvailable=!0;workerPath=i(r(a(import.meta.url)),`embedder-worker.js`);pendingRequests=new Map;childState=new WeakMap;childErrors=new WeakMap;child=null;readyChild=null;pendingInit=null;pendingShutdown=null;initializePromise=null;shutdownPromise=null;cooldownRespawnTimer=null;currentDimensions;currentModelId;coldStart=!0;constructor(e={}){this.options=e,this.logger=e.logger,this.healthBus.register(`embedder`),this.cb=new o({threshold:3,cooldownMs:6e4,name:`embedder`}),this.cb.on(`open`,()=>{this.healthBus.reportDegraded(`embedder`,`Circuit breaker open — consecutive timeouts`),this.startCooldownRespawn()}),this.cb.on(`closed`,()=>{this.healthBus.reportRecovered(`embedder`)}),this.initTimeoutMs=Math.max(0,e.initTimeoutMs??6e4),this.requestTimeoutMs=Math.max(0,e.requestTimeoutMs??(process.platform===`win32`?6e4:3e4)),this.maxRetries=Math.max(0,e.maxRetries??3),this.retryBaseDelayMs=Math.max(0,e.retryBaseDelayMs??500),this.currentDimensions=e.dimensions??c.dimensions,this.currentModelId=e.model??c.model}get dimensions(){return this.currentDimensions}get modelId(){return this.currentModelId}get isCircuitOpen(){return this.cb.isOpen()}async initialize(){if(!(this.readyChild&&this.child===this.readyChild)&&this.workerAvailable){if(!n(this.workerPath)){this.workerAvailable=!1,console.warn(`[aikit] Embedder worker not found at ${this.workerPath}. Embedding disabled - search will use keyword matching only. This usually means the npx cache is corrupted; restart to fix.`);return}if(this.initializePromise)return this.initializePromise;if(this.shutdownPromise){try{await this.shutdownPromise}catch{}if(this.readyChild&&this.child===this.readyChild)return}return this.initializePromise=this.startWorker().finally(()=>{this.initializePromise=null}),this.initializePromise}}async embed(e){if(!this.workerAvailable||(this.assertCircuitClosed(),await this.initialize(),!this.workerAvailable))throw Error(`Embedding worker is not available — embeddings cannot be computed. Check server logs for initialization errors.`);return this.sendVectorRequestWithRetry({type:`embed`,text:e})}async embedQuery(e){if(!this.workerAvailable||(this.assertCircuitClosed(),await this.initialize(),!this.workerAvailable))throw Error(`Embedding worker is not available — embeddings cannot be computed. Check server logs for initialization errors.`);return this.sendVectorRequestWithRetry({type:`embedQuery`,text:e})}async embedBatch(e,t){if(e.length===0)return[];if(!this.workerAvailable||(this.assertCircuitClosed(),await this.initialize(),!this.workerAvailable))throw Error(`Embedding worker is not available — embeddings cannot be computed. Check server logs for initialization errors.`);return this.withWorkerExitRetry(`embedBatch`,()=>this.sendBatchRequest(e,t))}async sendBatchRequest(e,n){await this.initialize();let r=this.requireReadyChild(),i=t(),a=new Promise((e,t)=>{this.pendingRequests.set(i,{child:r,resolve:t=>e(t),reject:t})});try{r.send({type:`embedBatch`,id:i,texts:e,batchSize:n})}catch(e){throw this.pendingRequests.delete(i),this.toError(e,`Failed to send embedBatch request to worker`)}let o=this.requestTimeoutMs>0?Math.max(this.requestTimeoutMs*3,9e4):0;if(o>0){let t,n=new Promise((n,r)=>{t=setTimeout(()=>{this.pendingRequests.delete(i),this.markWorkerUnresponsive(),r(Error(`Embedder embedBatch request timed out after ${o/1e3}s (${e.length} texts). The worker has been killed and will attempt to respawn automatically.`))},o)});try{return await Promise.race([a,n])}finally{t!==void 0&&clearTimeout(t)}}return a}async shutdown(){if(this.clearCooldownRespawnTimer(),this.shutdownPromise)return this.shutdownPromise;let e=this.child;if(!e)return;let t=this.requireChildState(e);t.shutdownRequested=!0,this.readyChild===e&&(this.readyChild=null),this.shutdownPromise=new Promise((t,n)=>{this.pendingShutdown={child:e,resolve:t,reject:n}}).finally(()=>{this.shutdownPromise=null});try{e.send({type:`shutdown`})}catch(t){let n=this.toError(t,`Failed to send shutdown request to worker`);throw this.clearChildReference(e),this.rejectPendingForChild(e,n),this.rejectLifecycleIfOwned(`shutdown`,e,n),n}return this.shutdownPromise}async startWorker(){this.child&&this.readyChild!==this.child&&(this.child=null),this.clearCooldownRespawnTimer(),this.coldStart=!0;let e=this.spawnChild();this.child=e,this.readyChild=null;let t=new Promise((t,n)=>{this.pendingInit={child:e,resolve:t,reject:n}});try{e.send({type:`init`,config:this.buildInitConfig()})}catch(t){let n=this.toError(t,`Failed to send init request to worker`);throw this.pendingInit=null,this.clearChildReference(e),n}if(this.initTimeoutMs>0){let n,r=new Promise((e,t)=>{n=setTimeout(()=>{t(Error(`Embedder worker initialization timed out after ${this.initTimeoutMs/1e3}s. The ONNX model may be downloading or the child process is stuck. Check network connectivity and disk space, or restart the server.`))},this.initTimeoutMs)});try{await Promise.race([t,r]);return}catch(t){this.pendingInit=null;try{e.kill()}catch{}throw this.clearChildReference(e),t}finally{n!==void 0&&clearTimeout(n)}}await t}spawnChild(){let t=e(this.workerPath,[],{env:this.buildChildEnv()});return this.childState.set(t,{idleExitNotified:!1,shutdownRequested:!1,terminated:!1}),t.on(`message`,e=>{this.handleChildMessage(t,e)}),t.once(`error`,e=>{this.handleChildFailure(t,this.toError(e,`Embedder worker failed`))}),t.once(`exit`,(e,n)=>{this.handleChildExit(t,e,n)}),t}handleChildMessage(e,t){switch(t.type){case`ready`:{this.currentDimensions=t.dimensions,this.currentModelId=t.modelId,this.healthBus.reportRecovered(`embedder`),this.child===e&&(this.readyChild=e,this.cb.getState()!==`closed`&&this.cb.reset());let n=this.pendingInit;n?.child===e&&(this.pendingInit=null,n.resolve());return}case`result`:{let n=this.pendingRequests.get(t.id);if(!n||n.child!==e)return;this.pendingRequests.delete(t.id),this.coldStart=!1,this.cb.recordSuccess(),n.resolve(new Float32Array(t.data));return}case`batchResult`:{let n=this.pendingRequests.get(t.id);if(!n||n.child!==e)return;if(this.pendingRequests.delete(t.id),!t.data||!Array.isArray(t.data)||t.data.length===0)n.reject(Error(`Worker returned empty or invalid batch result`));else{let e=t.data.map(e=>new Float32Array(e)),r=e.findIndex(e=>e.length===0);r>=0?n.reject(Error(`Worker returned zero-length vector at index ${r}`)):(this.coldStart=!1,this.cb.recordSuccess(),n.resolve(e))}return}case`error`:{let n=Error(t.message);if(this.childErrors.set(e,n),t.id===`init`){this.clearChildReference(e),this.rejectLifecycleIfOwned(`init`,e,n);return}if(t.id===`shutdown`){this.rejectLifecycleIfOwned(`shutdown`,e,n);return}let r=this.pendingRequests.get(t.id);if(!r||r.child!==e)return;this.pendingRequests.delete(t.id),r.reject(n);return}case`idle-exit`:{let t=this.requireChildState(e);t.idleExitNotified=!0,this.clearChildReference(e);return}}}handleChildExit(e,t,n){let r=this.requireChildState(e);if(r.terminated)return;r.terminated=!0,this.clearChildReference(e);let i=t===0&&n===null,a=r.shutdownRequested||r.idleExitNotified||i,o=this.childErrors.get(e)??Error(a?`Embedder worker exited before completing request`:`Embedder worker exited unexpectedly (code ${t??`null`}${n?`, signal ${n}`:``})`);this.rejectLifecycleIfOwned(`init`,e,o),a?this.resolveLifecycleIfOwned(`shutdown`,e):this.rejectLifecycleIfOwned(`shutdown`,e,o),this.rejectPendingForChild(e,o),a||this.cb.recordFailure()}handleChildFailure(e,t){let n=this.requireChildState(e);n.terminated||(n.terminated=!0,this.clearChildReference(e),this.rejectLifecycleIfOwned(`init`,e,t),this.rejectLifecycleIfOwned(`shutdown`,e,t),this.rejectPendingForChild(e,t))}async sendVectorRequestWithRetry(e){return this.withWorkerExitRetry(e.type,()=>this.sendVectorRequest(e))}async sendVectorRequest(e){await this.initialize();let n=this.requireReadyChild(),r=t(),i=this.requestTimeoutMs>0?this.coldStart?this.requestTimeoutMs*2:this.requestTimeoutMs:0,a=new Promise((e,t)=>{this.pendingRequests.set(r,{child:n,resolve:t=>e(t),reject:t})});try{n.send({...e,id:r})}catch(t){throw this.pendingRequests.delete(r),this.toError(t,`Failed to send ${e.type} request to worker`)}if(i>0){let t,n=new Promise((n,a)=>{t=setTimeout(()=>{this.pendingRequests.delete(r),this.markWorkerUnresponsive(),a(Error(`Embedder ${e.type} request timed out after ${i/1e3}s. The worker has been killed and will attempt to respawn automatically.`))},i)});try{return await Promise.race([a,n])}finally{t!==void 0&&clearTimeout(t)}}return a}async withWorkerExitRetry(e,t){let n=null,r=this.maxRetries;for(let i=0;i<=r;i++)try{return await t()}catch(t){let a=this.toError(t,`Failed to process ${e} request`);if(!this.isWorkerExitError(a))throw a;if(n??=a,i===0&&/exited/i.test(a.message)&&!/timed out/i.test(a.message)&&(r=Math.min(r,1)),i===r)throw n;let o=i+1,s=this.retryBaseDelayMs*2**i;if(this.healthBus.reportDegraded(`embedder`,`Worker crashed during ${e} — retrying (${o}/${r})`),this.logger?.warn?.(`Embedder retry ${o}/${r} after ${s}ms`,{requestType:e,delayMs:s,error:a.message}),this.child=null,this.readyChild=null,await this.wait(s),this.cb.isOpen())throw n??a}throw n??Error(`Failed to process ${e} request`)}isWorkerExitError(e){return/embedder worker exited|EPIPE|ECONNRESET|ERR_IPC_CHANNEL_CLOSED|channel closed|write after end/i.test(e.message)}wait(e){return new Promise(t=>{setTimeout(t,e)})}requireReadyChild(){if(!this.child||this.readyChild!==this.child)throw Error(`Embedder worker is not initialized`);return this.child}buildInitConfig(){return{model:this.options.model,dimensions:this.options.dimensions,nativeDim:this.options.nativeDim,queryPrefix:this.options.queryPrefix,pooling:this.options.pooling,interOpNumThreads:this.options.interOpNumThreads,intraOpNumThreads:this.options.intraOpNumThreads}}buildChildEnv(){return this.options.idleTimeoutMs===void 0?process.env:{...process.env,AIKIT_EMBED_IDLE_MS:String(this.options.idleTimeoutMs)}}requireChildState(e){let t=this.childState.get(e);if(!t)throw Error(`Embedder worker state not found`);return t}clearChildReference(e){this.child===e&&(this.child=null),this.readyChild===e&&(this.readyChild=null)}clearCooldownRespawnTimer(){this.cooldownRespawnTimer&&=(clearTimeout(this.cooldownRespawnTimer),null)}startCooldownRespawn(){this.clearCooldownRespawnTimer(),this.cooldownRespawnTimer=setTimeout(()=>{this.cooldownRespawnTimer=null,!this.child&&!this.shutdownPromise&&this.workerAvailable&&this.initialize().catch(()=>{})},6e4),this.logger?.warn?.(`Embedder circuit breaker OPEN — too many consecutive failures`,{cooldownMs:6e4})}markWorkerUnresponsive(){let e=this.child;if(e){try{e.kill()}catch{}this.clearChildReference(e),this.cb.recordFailure(),this.cb.isOpen()||setImmediate(()=>{!this.child&&this.workerAvailable&&!this.shutdownPromise&&this.initialize().catch(()=>{})})}}assertCircuitClosed(){if(this.cb.isOpen())throw new s(this.cb.remainingCooldownMs())}rejectPendingForChild(e,t){for(let[n,r]of this.pendingRequests)r.child===e&&(this.pendingRequests.delete(n),r.reject(t))}resolveLifecycleIfOwned(e,t){let n=this.pendingShutdown;!n||n.child!==t||(this.pendingShutdown=null,n.resolve())}rejectLifecycleIfOwned(e,t,n){let r=e===`init`?this.pendingInit:this.pendingShutdown;!r||r.child!==t||(e===`init`?this.pendingInit=null:this.pendingShutdown=null,r.reject(n))}toError(e,t){return e instanceof Error?e:Error(`${t}: ${String(e)}`)}};let m=null;function h(e){if(!(e instanceof Error))return!1;let t=e.code;return t===`ERR_MODULE_NOT_FOUND`||t===`MODULE_NOT_FOUND`?!0:/cannot find (module|package)|module not found/i.test(e.message)}async function g(){if(!m){try{m=await import(`@huggingface/transformers`)}catch(e){if(h(e)){let{createRequire:t}=await import(`node:module`),n=t(import.meta.url);try{m=n("@huggingface/transformers")}catch(t){let n=e instanceof Error?e.message:String(e),r=t instanceof Error?t.message:String(t);throw Error(`Unable to load @huggingface/transformers via ESM or CJS. ESM: ${n}; CJS: ${r}`)}}else throw e}m.env.cacheDir=i(f(),`.cache`,`huggingface`,`transformers-js`)}return m}var _=class{pipe=null;shutdownPromise=null;dimensions;modelId;nativeDim;queryPrefix;pooling;threadConfig;constructor(e={}){this.modelId=e.model??c.model;let t=u[this.modelId];if(this.nativeDim=e.nativeDim??t?.nativeDim??c.nativeDim,this.dimensions=e.dimensions??t?.dimensions??c.dimensions,this.dimensions>this.nativeDim)throw Error(`Configured dimensions (${this.dimensions}) exceeds model native output (${this.nativeDim}). Matryoshka truncation cannot upscale — dimensions must be <= nativeDim.`);this.queryPrefix=e.queryPrefix??t?.queryPrefix??this.detectQueryPrefix(this.modelId),this.pooling=e.pooling??t?.pooling??`mean`,this.threadConfig={interOp:e.interOpNumThreads??1,intraOp:e.intraOpNumThreads??4}}detectQueryPrefix(e){let t=e.toLowerCase();return t.includes(`bge`)||t.includes(`mxbai-embed`)&&!t.includes(`xsmall`)?`Represent this sentence for searching relevant passages: `:t.includes(`/e5-`)||t.includes(`multilingual-e5`)?`query: `:``}getPipelineOptions(e){let t=e.backends.onnx;t.wasm||={};let n=t.wasm;return n.numThreads=this.threadConfig.intraOp,{dtype:`q8`,session_options:{interOpNumThreads:this.threadConfig.interOp,intraOpNumThreads:this.threadConfig.intraOp}}}computeNorm(e){let t=0;for(let n=0;n<e.length;n++)t+=e[n]*e[n];return Math.sqrt(t)}truncateAndRenorm(e){if(this.dimensions>=this.nativeDim){let t=this.computeNorm(e);if(!Number.isFinite(t))throw Error(`Embedding produced non-finite norm — output contained NaN or Infinity`);if(t===0)throw Error(`Embedding produced zero-norm vector from ONNX output`);return e}let t=e.subarray(0,this.dimensions),n=this.computeNorm(t);if(!Number.isFinite(n))throw Error(`Embedding produced non-finite norm — output contained NaN or Infinity`);if(n===0)throw Error(`Embedding produced zero-norm vector after truncation — input may be degenerate`);let r=new Float32Array(this.dimensions);for(let e=0;e<this.dimensions;e++)r[e]=t[e]/n;return r}async initialize(){if(this.pipe)return;this.shutdownPromise=null;let{pipeline:e,env:t}=await g();try{this.pipe=await e(`feature-extraction`,this.modelId,this.getPipelineOptions(t))}catch(n){let r=n.message?.toLowerCase()??``;if(this.isCorruptionError(r)){let n=i(t.cacheDir??i(f(),`.cache`,`huggingface`,`transformers-js`),this.modelId);console.error(`[aikit:auto-heal] Detected corrupted model cache for "${this.modelId}". Clearing cache at ${n} and retrying download...`);try{await d(n,{recursive:!0,force:!0})}catch{}try{this.pipe=await e(`feature-extraction`,this.modelId,this.getPipelineOptions(t)),console.error(`[aikit:auto-heal] Model "${this.modelId}" re-downloaded successfully.`);return}catch(e){throw Error(`Failed to initialize embedding model "${this.modelId}" after auto-heal: ${e.message}`)}}throw Error(`Failed to initialize embedding model "${this.modelId}": ${n.message}`)}}isCorruptionError(e){return[`protobuf`,`invalid model`,`invalid onnx`,`unexpected end`,`unexpected token`,`failed to load`,`checksum`,`corrupt`,`could not load`,`onnx`,`malformed`].some(t=>e.includes(t))}async shutdown(){return this.shutdownPromise||=this._doShutdown(),this.shutdownPromise}async _doShutdown(){let e=this.pipe;if(e)try{let t=e;typeof t.dispose==`function`?await t.dispose():typeof t.model?.dispose==`function`&&await t.model.dispose()}catch{}finally{this.pipe=null}}async embed(e){this.pipe||await this.initialize();let t=await this.pipe?.(e,{pooling:this.pooling,normalize:!0});if(!t?.data)throw Error(`Embedding pipeline returned no output`);try{let e=new Float32Array(t.data);return this.truncateAndRenorm(e)}finally{t.dispose?.()}}async embedQuery(e){return this.embed(this.queryPrefix+e)}async embedBatch(e,t=64){if(e.length===0)return[];this.pipe||await this.initialize();let n=[];for(let r=0;r<e.length;r+=t){let i=e.slice(r,r+t),a=await this.pipe?.(i,{pooling:this.pooling,normalize:!0});if(!a?.data)throw Error(`Embedding pipeline returned no output`);try{if(i.length===1){let e=new Float32Array(a.data);n.push(this.truncateAndRenorm(e))}else for(let e=0;e<i.length;e++){let t=e*this.nativeDim,r=a.data.slice(t,t+this.nativeDim);n.push(this.truncateAndRenorm(new Float32Array(r)))}}finally{a.dispose?.()}}return n}};export{p as EmbedderProxy,_ as OnnxEmbedder};