tjs-lang 0.8.1 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/CLAUDE.md +9 -3
  2. package/demo/examples.test.ts +6 -2
  3. package/demo/src/playground-shared.ts +48 -16
  4. package/demo/src/playground-test-results.test.ts +112 -0
  5. package/demo/src/tjs-playground.ts +11 -5
  6. package/dist/examples/modules/dist/main.d.ts +34 -0
  7. package/dist/examples/modules/dist/math.d.ts +120 -0
  8. package/dist/index.js +115 -112
  9. package/dist/index.js.map +4 -4
  10. package/dist/src/lang/core.d.ts +1 -1
  11. package/dist/src/lang/dialect.d.ts +35 -0
  12. package/dist/src/lang/emitters/ast.d.ts +1 -1
  13. package/dist/src/lang/emitters/js-tests.d.ts +7 -0
  14. package/dist/src/lang/emitters/js.d.ts +12 -0
  15. package/dist/src/lang/index.d.ts +2 -1
  16. package/dist/src/lang/parser-types.d.ts +17 -0
  17. package/dist/src/lang/parser.d.ts +18 -0
  18. package/dist/src/lang/transpiler.d.ts +1 -0
  19. package/dist/src/lang/types.d.ts +18 -0
  20. package/dist/src/vm/runtime.d.ts +18 -0
  21. package/dist/src/vm/vm.d.ts +15 -1
  22. package/dist/tjs-batteries.js +2 -2
  23. package/dist/tjs-batteries.js.map +2 -2
  24. package/dist/tjs-eval.js +43 -43
  25. package/dist/tjs-eval.js.map +3 -3
  26. package/dist/tjs-from-ts.js +1 -1
  27. package/dist/tjs-from-ts.js.map +2 -2
  28. package/dist/tjs-lang.js +76 -73
  29. package/dist/tjs-lang.js.map +4 -4
  30. package/dist/tjs-vm.js +49 -49
  31. package/dist/tjs-vm.js.map +3 -3
  32. package/llms.txt +1 -0
  33. package/package.json +20 -1
  34. package/src/batteries/audit.ts +3 -2
  35. package/src/cli/commands/check.ts +3 -2
  36. package/src/cli/commands/emit.ts +4 -2
  37. package/src/cli/commands/run.ts +6 -2
  38. package/src/cli/commands/types.ts +2 -2
  39. package/src/lang/codegen.test.ts +4 -1
  40. package/src/lang/core.ts +6 -4
  41. package/src/lang/dialect.test.ts +63 -0
  42. package/src/lang/dialect.ts +50 -0
  43. package/src/lang/emitters/ast.ts +145 -2
  44. package/src/lang/emitters/js-tests.ts +46 -37
  45. package/src/lang/emitters/js.ts +19 -2
  46. package/src/lang/features.test.ts +6 -5
  47. package/src/lang/index.ts +18 -5
  48. package/src/lang/parser-types.ts +17 -0
  49. package/src/lang/parser.test.ts +12 -6
  50. package/src/lang/parser.ts +113 -3
  51. package/src/lang/subset-invariant.test.ts +90 -0
  52. package/src/lang/transpiler.ts +8 -0
  53. package/src/lang/types.ts +18 -0
  54. package/src/lang/wasm.test.ts +8 -2
  55. package/src/linalg/linalg.test.ts +8 -2
  56. package/src/use-cases/batteries.test.ts +4 -0
  57. package/src/use-cases/local-helpers.test.ts +219 -0
  58. package/src/use-cases/timeout-overrides.test.ts +169 -0
  59. package/src/vm/atoms/batteries.ts +17 -3
  60. package/src/vm/runtime.ts +89 -4
  61. package/src/vm/vm.ts +47 -9
@@ -8,7 +8,7 @@ import type { SeqNode } from '../builder';
8
8
  import type { TranspileOptions, TranspileResult, FunctionSignature } from './types';
9
9
  import { type TJSTranspileResult, type TJSTranspileOptions } from './emitters/js';
10
10
  export * from './types';
11
- export { parse, preprocess, extractTDoc, validateSingleFunction, } from './parser';
11
+ export { parse, preprocess, extractTDoc, validateSingleFunction, extractFunctions, } from './parser';
12
12
  export { transformFunction } from './emitters/ast';
13
13
  /**
14
14
  * Transpile JavaScript source code to Agent99 AST
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Dialect resolution for file-based tooling.
3
+ *
4
+ * The subset invariant (see PRINCIPLES.md) says plain JavaScript must transpile
5
+ * through TJS without changing meaning, while native `.tjs` gets the full
6
+ * footgun-removal feature set. The unit of opt-in is the *dialect* — and for a
7
+ * file, the dialect is its extension. This is the one canonical mapping that
8
+ * CLIs, bundler plugins, module loaders, and doc systems should all share so
9
+ * `.js` is never silently "improved" into different semantics.
10
+ */
11
+ /** Source dialect understood by `tjs(src, { dialect })`. */
12
+ export type Dialect = 'js' | 'tjs';
13
+ /** How a file should be transpiled, based on its extension. */
14
+ export type SourceKind = 'js' | 'ts' | 'tjs';
15
+ /**
16
+ * Classify a file by extension into the source kind that determines its
17
+ * transpile path:
18
+ * - `'tjs'` → native TJS: `tjs(src)` (all modes ON — the better language)
19
+ * - `'js'` → plain JS: `tjs(src, { dialect: 'js' })` (semantics preserved)
20
+ * - `'ts'` → TypeScript: route through `fromTS` (TS → TJS → JS)
21
+ *
22
+ * Unknown extensions default to `'tjs'` (the native language). `.d.ts` is
23
+ * treated as TypeScript.
24
+ */
25
+ export declare function sourceKindForFilename(filename: string): SourceKind;
26
+ /**
27
+ * Map a filename to the `dialect` option for `tjs()`. `.js`/`.mjs`/`.cjs` ⇒
28
+ * `'js'` (plain JavaScript, semantics preserved); everything else ⇒ `'tjs'`
29
+ * (native TJS).
30
+ *
31
+ * NOTE: TypeScript files are NOT a `tjs()` dialect — transpile them with
32
+ * `fromTS` first. Use {@link sourceKindForFilename} when you need to tell
33
+ * `.ts` apart from `.js`/`.tjs`.
34
+ */
35
+ export declare function dialectForFilename(filename: string): Dialect;
@@ -9,7 +9,7 @@ import type { TransformContext, TranspileOptions, FunctionSignature, TranspileWa
9
9
  /**
10
10
  * Transform a function declaration into Agent99 AST
11
11
  */
12
- export declare function transformFunction(func: FunctionDeclaration, source: string, returnTypeAnnotation: string | undefined, options?: TranspileOptions, requiredParamsFromPreprocess?: Set<string>): {
12
+ export declare function transformFunction(func: FunctionDeclaration, source: string, returnTypeAnnotation: string | undefined, options?: TranspileOptions, requiredParamsFromPreprocess?: Set<string>, helpers?: Map<string, FunctionDeclaration>): {
13
13
  ast: BaseNode;
14
14
  signature: FunctionSignature;
15
15
  warnings: TranspileWarning[];
@@ -13,6 +13,13 @@ export interface TestResult {
13
13
  error?: string;
14
14
  /** Whether this was an implicit signature test */
15
15
  isSignatureTest?: boolean;
16
+ /**
17
+ * The test could not be *run* (e.g. it references a name TJS can't resolve at
18
+ * build time — like an AJS atom — or the harness couldn't execute the module).
19
+ * Inconclusive ≠ failed: it never blocks transpilation. Surfaced as a warning
20
+ * (e.g. in the playground). See PRINCIPLES.md ("more, never illegal").
21
+ */
22
+ inconclusive?: boolean;
16
23
  /** Source line number (1-indexed) where the test or error occurred */
17
24
  line?: number;
18
25
  /** Source column number (1-indexed) */
@@ -54,6 +54,18 @@ export interface TJSTranspileOptions {
54
54
  sourceMap?: boolean;
55
55
  /** Mode: 'dev' | 'strict' | 'production' */
56
56
  mode?: 'dev' | 'strict' | 'production';
57
+ /**
58
+ * Source dialect — what kind of source this string is:
59
+ * - `'tjs'` (default for a bare string): native TJS, footgun-removal modes ON
60
+ * (structural `==`, `TjsStandard`, etc.).
61
+ * - `'js'`: plain JavaScript — modes OFF, `safety: 'none'`; the source's own
62
+ * semantics are preserved (no `==`→`Eq`, no truthiness rewrite, no input
63
+ * validation). Use this when feeding tjs() a vanilla `.js` string so it
64
+ * transpiles without changing meaning. See PRINCIPLES.md (TJS ⊇ JS).
65
+ *
66
+ * For TypeScript, use the `fromTS` entry point (TS → TJS → JS).
67
+ */
68
+ dialect?: 'js' | 'tjs';
57
69
  /**
58
70
  * Test execution mode:
59
71
  * - true (default): run tests at transpile time, throw on failure
@@ -23,7 +23,8 @@
23
23
  import type { SeqNode } from '../builder';
24
24
  import type { TranspileOptions, TranspileResult, FunctionSignature } from './types';
25
25
  export * from './types';
26
- export { parse, preprocess, extractTDoc } from './parser';
26
+ export { parse, preprocess, extractTDoc, validateSingleFunction, extractFunctions, } from './parser';
27
+ export { dialectForFilename, sourceKindForFilename, type Dialect, type SourceKind, } from './dialect';
27
28
  export { transformFunction } from './emitters/ast';
28
29
  export { transpileToJS, stripModuleSyntax, stripTjsPreamble, type TJSTranspileOptions, type TJSTranspileResult, type TJSTypeInfo, } from './emitters/js';
29
30
  export { generateDTS, typeDescriptorToTS, type GenerateDTSOptions, } from './emitters/dts';
@@ -14,6 +14,17 @@ export interface ParseOptions {
14
14
  * When true, skips == to Is() transformation since the VM handles == correctly.
15
15
  */
16
16
  vmTarget?: boolean;
17
+ /**
18
+ * Source dialect — tells the transpiler what kind of source this string is:
19
+ * - `'tjs'`: native TJS, all footgun-removal modes ON (structural `==`,
20
+ * `TjsStandard`, etc.). This is the default for a bare string.
21
+ * - `'js'`: plain JavaScript — modes OFF and `safety: 'none'`, so the source's
22
+ * own semantics are preserved (no `==`→`Eq`, no truthiness rewrite, etc.).
23
+ *
24
+ * Authoritative when set; otherwise the dialect is inferred (the fromTS
25
+ * annotation and `vmTarget` ⇒ JS-compatible). See PRINCIPLES.md (TJS ⊇ JS).
26
+ */
27
+ dialect?: 'js' | 'tjs';
17
28
  /**
18
29
  * Optional ModuleLoader for cross-file `wasm function` composition (Phase 3).
19
30
  * When provided, imports are resolved at transpile time and matching wasm
@@ -105,6 +116,12 @@ export interface PreprocessOptions {
105
116
  * Default: false (transform == to Is() for TJS code running in regular JS)
106
117
  */
107
118
  vmTarget?: boolean;
119
+ /**
120
+ * Source dialect: `'js'` ⇒ modes OFF / `safety: 'none'` (preserve plain-JS
121
+ * semantics); `'tjs'` ⇒ native modes ON. Authoritative when set; otherwise
122
+ * inferred from the fromTS annotation / `vmTarget`. See ParseOptions.dialect.
123
+ */
124
+ dialect?: 'js' | 'tjs';
108
125
  /**
109
126
  * Optional ModuleLoader for cross-file `wasm function` composition (Phase 3).
110
127
  * See ParseOptions.moduleLoader for details.
@@ -53,6 +53,24 @@ export declare function parse(source: string, options?: ParseOptions): {
53
53
  * Validate that the source contains exactly one function declaration
54
54
  */
55
55
  export declare function validateSingleFunction(ast: Program, filename?: string): FunctionDeclaration;
56
+ /**
57
+ * Extract top-level function declarations from the parsed program.
58
+ *
59
+ * Returns `{ entry, helpers }` where:
60
+ * - `entry` is the last function declaration (the agent's entry point)
61
+ * - `helpers` are all preceding function declarations, looked up by name
62
+ *
63
+ * This matches the natural "helpers first, agent last" pattern, including
64
+ * the TOOL_LIBRARY use case where helper async wrappers are prepended
65
+ * before the user-supplied agent function.
66
+ *
67
+ * Same top-level construct restrictions as `validateSingleFunction`:
68
+ * imports, exports, and classes are rejected.
69
+ */
70
+ export declare function extractFunctions(ast: Program, filename?: string): {
71
+ entry: FunctionDeclaration;
72
+ helpers: Map<string, FunctionDeclaration>;
73
+ };
56
74
  /**
57
75
  * Extract TDoc comment from before a function
58
76
  *
@@ -11,6 +11,7 @@
11
11
  */
12
12
  export { transpile, ajs, tjs, createAgent, getToolDefinitions } from './core';
13
13
  export { parse, preprocess, extractTDoc } from './parser';
14
+ export { dialectForFilename, sourceKindForFilename, type Dialect, type SourceKind, } from './dialect';
14
15
  export { transformFunction } from './emitters/ast';
15
16
  export { transpileToJS } from './emitters/js';
16
17
  export type { TJSTranspileOptions, TJSTranspileResult, TJSTypeInfo, } from './emitters/js';
@@ -143,6 +143,24 @@ export interface TransformContext {
143
143
  filename: string;
144
144
  /** Options */
145
145
  options: TranspileOptions;
146
+ /**
147
+ * Helper functions (top-level functions declared before the entry function).
148
+ * Calls to these names emit `callLocal` instead of treating them as atom calls.
149
+ */
150
+ helpers?: Map<string, any>;
151
+ /**
152
+ * Cache of transformed helper bodies. Lazily populated as helpers are
153
+ * referenced from the entry function (or from other helpers).
154
+ */
155
+ helperSteps?: Map<string, {
156
+ steps: any[];
157
+ paramNames: string[];
158
+ }>;
159
+ /**
160
+ * Names of helpers currently being transformed. Used to detect direct or
161
+ * transitive recursion.
162
+ */
163
+ helperTransforming?: Set<string>;
146
164
  }
147
165
  /** Create a child context for nested scopes */
148
166
  export declare function createChildContext(parent: TransformContext): TransformContext;
@@ -60,6 +60,8 @@ export interface TraceEvent {
60
60
  }
61
61
  /** Cost override: static number or dynamic function */
62
62
  export type CostOverride = number | ((input: any, ctx: RuntimeContext) => number);
63
+ /** Timeout override: static number (ms) or dynamic function. 0 disables. */
64
+ export type TimeoutOverride = number | ((input: any, ctx: RuntimeContext) => number);
63
65
  export interface RuntimeContext {
64
66
  fuel: {
65
67
  current: number;
@@ -76,8 +78,15 @@ export interface RuntimeContext {
76
78
  warnings?: string[];
77
79
  signal?: AbortSignal;
78
80
  costOverrides?: Record<string, CostOverride>;
81
+ timeoutOverrides?: Record<string, TimeoutOverride>;
79
82
  context?: Record<string, any>;
80
83
  runCodeDepth?: number;
84
+ localCall?: boolean;
85
+ helpers?: Record<string, {
86
+ steps: any[];
87
+ paramNames: string[];
88
+ }>;
89
+ callDepth?: number;
81
90
  }
82
91
  export type AtomExec = (step: any, ctx: RuntimeContext) => Promise<void>;
83
92
  export interface AtomDef {
@@ -218,6 +227,14 @@ export declare const varsImport: Atom<Record<string, any>, void>;
218
227
  export declare const varsLet: Atom<Record<string, any>, void>;
219
228
  export declare const varsExport: Atom<Record<string, any>, Record<string, any>>;
220
229
  export declare const scope: Atom<Record<string, any>, void>;
230
+ /**
231
+ * Maximum helper-call nesting depth. Fuel + timeout bound the total *work* a
232
+ * recursive helper can do, but deeply-nested `await seq.exec` would overflow
233
+ * the host JS stack (an uncatchable RangeError) before fuel runs out. This cap
234
+ * converts runaway recursion into a clean monadic error instead.
235
+ */
236
+ export declare const MAX_CALL_DEPTH = 256;
237
+ export declare const callLocal: Atom<Record<string, any>, any>;
221
238
  export declare const map: Atom<Record<string, any>, any[]>;
222
239
  export declare const filter: Atom<Record<string, any>, any[]>;
223
240
  export declare const reduce: Atom<Record<string, any>, any>;
@@ -281,6 +298,7 @@ export declare const coreAtoms: {
281
298
  varsLet: Atom<Record<string, any>, void>;
282
299
  varsExport: Atom<Record<string, any>, Record<string, any>>;
283
300
  scope: Atom<Record<string, any>, void>;
301
+ callLocal: Atom<Record<string, any>, any>;
284
302
  map: Atom<Record<string, any>, any[]>;
285
303
  filter: Atom<Record<string, any>, any[]>;
286
304
  reduce: Atom<Record<string, any>, any>;
@@ -1,8 +1,21 @@
1
- import { type Atom, type Capabilities, type RunResult, type CostOverride, coreAtoms } from './runtime';
1
+ import { type Atom, type Capabilities, type RunResult, type CostOverride, type TimeoutOverride, coreAtoms } from './runtime';
2
2
  import { type BaseNode, type BuilderType } from '../builder';
3
3
  export declare class AgentVM<M extends Record<string, Atom<any, any>>> {
4
4
  readonly atoms: typeof coreAtoms & M;
5
+ private _defaultRunTimeout?;
5
6
  constructor(customAtoms?: M);
7
+ /**
8
+ * Default run-level wall-clock timeout when `run()` is given no explicit
9
+ * `timeoutMs`. Derived as `max(per-atom timeoutMs) × 2` over the registered
10
+ * atoms (with headroom for an agent that chains a couple of slow calls), so
11
+ * the run-level backstop can never be shorter than the slowest single atom's
12
+ * own budget — otherwise that per-atom budget would be dead config (e.g.
13
+ * `llmVision`/`llmPredictBattery` are 120s; a fixed 60s run default would kill
14
+ * them mid-call). Atoms with `timeoutMs: 0` (no timeout, e.g. `seq`) are
15
+ * excluded; the result is floored at {@link MIN_DEFAULT_RUN_TIMEOUT_MS}.
16
+ * Self-adjusting: registering a slower custom atom raises the default.
17
+ */
18
+ get defaultRunTimeout(): number;
6
19
  get builder(): BuilderType<typeof coreAtoms & M>;
7
20
  get Agent(): BuilderType<typeof coreAtoms & M>;
8
21
  /** @deprecated Use `Agent` instead */
@@ -23,6 +36,7 @@ export declare class AgentVM<M extends Record<string, Atom<any, any>>> {
23
36
  timeoutMs?: number;
24
37
  signal?: AbortSignal;
25
38
  costOverrides?: Record<string, CostOverride>;
39
+ timeoutOverrides?: Record<string, TimeoutOverride>;
26
40
  context?: Record<string, any>;
27
41
  }): Promise<RunResult>;
28
42
  }
@@ -1,3 +1,3 @@
1
- var S=new Map,p=new Map;function k(e,t){if(e.length!==t.length)throw new Error("Vectors must have the same length for cosine similarity.");let n=0,o=0,s=0;for(let r=0;r<e.length;r++)n+=e[r]*t[r],o+=e[r]*e[r],s+=t[r]*t[r];return o=Math.sqrt(o),s=Math.sqrt(s),o===0||s===0?0:n/(o*s)}function w(){return{async get(e){return S.get(e)},async set(e,t){S.set(e,t)},async createCollection(e,t,n){p.has(e)&&console.warn(`Collection '${e}' already exists. Overwriting.`),p.set(e,[])},async vectorAdd(e,t){let n=p.get(e);if(!n)throw new Error(`Collection '${e}' not found. Create it first.`);if(!t.embedding||!Array.isArray(t.embedding))throw new Error("Document must have an 'embedding' property that is an array of numbers.");n.push(t)},async vectorSearch(e,t,n=5){let o=p.get(e);if(!o)throw new Error(`Collection '${e}' not found. Create it first.`);let s=o.map(r=>({doc:r,score:k(t,r.embedding)}));return s.sort((r,i)=>i.score-r.score),s.slice(0,n).map(r=>r.doc)}}}function O(e){if(typeof e=="string")return{role:"user",content:e};let t=[{type:"text",text:e.text}];for(let n of e.images||[])t.push({type:"image_url",image_url:{url:n}});return{role:"user",content:t}}var P="http://localhost:1234/v1";function E(e,t=P){return{async predict(n,o,s,r){try{let i=r?e.getStructuredLLM():e.getLLM(),l=[{role:"system",content:n},O(o)],a=await fetch(`${t}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:i.id,messages:l,temperature:.7,...s&&s.length>0?{tools:s}:{},response_format:r})});if(!a.ok)throw new Error(`LLM Error: ${a.status} ${a.statusText}`);return(await a.json()).choices[0]?.message??{content:""}}catch(i){throw i.cause?.code==="ECONNREFUSED"?new Error("No LLM provider configured. Please start LM Studio or provide an API key.",{cause:i}):i}},async embed(n){try{let o=e.getEmbedding(),s=await fetch(`${t}/embeddings`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:o.id,input:n})});if(!s.ok)throw new Error(`Embedding Error: ${s.status}`);return(await s.json()).data[0]?.embedding??[]}catch(o){throw o.cause?.code==="ECONNREFUSED"?new Error("No LLM provider configured. Please start LM Studio or provide an API key.",{cause:o}):o}}}}var h=".models.cache.json";var c=typeof window<"u"&&typeof window.localStorage<"u";async function _(e){try{if(c){let t=window.localStorage.getItem(h);if(!t)return null;let n=JSON.parse(t);return n.baseUrl!==e||Date.now()-n.timestamp>864e5?null:n.models}else{let t=await import("node:fs/promises"),o=(await import("node:path")).join(process.cwd(),h);try{let s=await t.readFile(o,"utf-8"),r=JSON.parse(s);return r.baseUrl!==e||Date.now()-r.timestamp>864e5?null:r.models}catch{return null}}}catch(t){return console.warn("\u26A0\uFE0F Error reading model cache:",t),null}}async function N(e,t){let n={timestamp:Date.now(),baseUrl:e,models:t};try{if(c)window.localStorage.setItem(h,JSON.stringify(n));else{let o=await import("node:fs/promises"),r=(await import("node:path")).join(process.cwd(),h);await o.writeFile(r,JSON.stringify(n,null,2))}}catch(o){console.error("\u274C Error writing model cache:",o)}}var u=async(e,t)=>{let n=new AbortController,o=setTimeout(()=>n.abort(),6e4);try{let s=await fetch(e,{...t,signal:n.signal});return clearTimeout(o),s}catch(s){throw clearTimeout(o),s}};async function v(e,t){try{let n={type:"json_schema",json_schema:{name:"test",strict:!1,schema:{type:"object",properties:{status:{type:"string"}}}}},o=await u(`${e}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:t,messages:[{role:"system",content:"You respond in JSON."},{role:"user",content:'Return JSON: {"status": "ok"}'}],response_format:n,max_tokens:20})});if(!o.ok)return o.status===400?x(e,t):{ok:!1,msg:`HTTP ${o.status}`};let s=await o.json();return JSON.parse(s.choices[0].message.content),{ok:!0,msg:"OK (Schema)"}}catch(n){return{ok:!1,msg:n.message||"Error"}}}async function x(e,t){try{return(await u(`${e}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:t,messages:[{role:"user",content:'JSON: {"a":1}'}],response_format:{type:"json_object"},max_tokens:10})})).ok?{ok:!0,msg:"OK (Legacy Mode)"}:{ok:!1,msg:"Not Supported"}}catch{return{ok:!1,msg:"Legacy Fail"}}}async function D(e,t){try{return(await u(`${e}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:t,messages:[{role:"user",content:"hi"}],max_tokens:1})})).ok}catch{return!1}}async function j(e,t){try{let n=await u(`${e}/embeddings`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:t,input:"test"})});return n.ok?(await n.json()).data[0]?.embedding?.length??null:null}catch{return null}}var J="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==";async function $(e,t){try{return(await u(`${e}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:t,messages:[{role:"user",content:[{type:"text",text:"What color is this?"},{type:"image_url",image_url:{url:J}}]}],max_tokens:10})})).ok}catch{return!1}}async function A(e){let t=await _(e),n;try{let i=await fetch(`${e}/models`);if(!i.ok)throw new Error("Could not connect");n=(await i.json()).data.map(a=>a.id).sort()}catch{return t?(console.log("\u26A0\uFE0F LM Studio unavailable, using cached model audit."),t):(console.error("\u274C Failed to connect to LM Studio."),[])}if(t){let i=t.map(l=>l.id).sort();if(JSON.stringify(n)===JSON.stringify(i))return console.log("\u2705 Using cached model audit."),t;console.log("\u{1F50D} Model list changed. Re-running audit...")}console.log("\u{1F50D} Scanning models (this may take a moment)...");let o=[],s=n.map(i=>({id:i})),r;c||(r=await import("node:readline"));for(let i of s){!c&&r&&(r.cursorTo(process.stdout,0),process.stdout.write(`\u{1F449} Testing: ${i.id}...`),r.clearLine(process.stdout,1));let l="Unknown",a=!1,g=!1,d,b,T=await D(e,i.id),f=await j(e,i.id);if(f&&(b=f),T){l="LLM";let L=await v(e,i.id);a=L.ok,g=await $(e,i.id),d=a?L.msg:`Fail: ${L.msg}`,g&&(d+=" +Vision")}else f?(l="Embedding",d=`OK (Dim: ${f})`):d="LLM Fail";o.push({id:i.id,type:l,structuredOutput:a,vision:g,dimension:b,status:d})}return!c&&r&&(r.cursorTo(process.stdout,0),r.clearLine(process.stdout,0)),console.log(`
2
- `),console.table(o),await N(e,o),console.log("\u{1F4DD} Audit results saved to cache."),o}var U="http://localhost:1234/v1",y=class{constructor(t=U){this.baseUrl=t}baseUrl;models=[];defaultLLM=null;defaultEmbedding=null;defaultStructuredLLM=null;async audit(){this.models=await A(this.baseUrl),this.selectDefaults()}selectDefaults(){this.defaultEmbedding=this.models.find(t=>t.type==="Embedding")||null,this.defaultLLM=this.models.find(t=>t.type==="LLM")||null,this.defaultStructuredLLM=this.models.find(t=>t.type==="LLM"&&t.structuredOutput)||null,this.defaultEmbedding||console.warn("\u26A0\uFE0F No embedding model found."),this.defaultLLM||console.warn("\u26A0\uFE0F No LLM found."),this.defaultStructuredLLM||console.warn("\u26A0\uFE0F No LLM with structured output support found.")}getModels(){return this.models}_setDefaultModel(t,n,o,s){let r=this.models.find(i=>i.id===t&&o(i));if(!r)throw new Error(`Model '${t}' not found or is not ${s}.`);this[n]=r}setDefaultLLM(t){this._setDefaultModel(t,"defaultLLM",n=>n.type==="LLM","an LLM")}setDefaultEmbedding(t){this._setDefaultModel(t,"defaultEmbedding",n=>n.dimension!==void 0,"an embedding model")}setDefaultStructuredLLM(t){this._setDefaultModel(t,"defaultStructuredLLM",n=>n.type==="LLM"&&n.structuredOutput,"a structured-output LLM")}getLLM(){if(!this.defaultLLM)throw new Error("No LLM available.");return this.defaultLLM}getEmbedding(){if(!this.defaultEmbedding)throw new Error("No embedding model available.");return this.defaultEmbedding}getStructuredLLM(){if(!this.defaultStructuredLLM)throw new Error("No structured-output LLM available.");return this.defaultStructuredLLM}};var F=typeof window<"u",R=F&&window.location.protocol==="https:",m=null,M=null,C=!1;async function I(){if(C)return{localModels:m,llm:M};if(C=!0,R)return console.log("\u{1F4E1} HTTPS detected - local LLM endpoints disabled. Use HTTP for local LLM support."),{localModels:null,llm:null};try{m=new y,await m.audit(),M=E(m)}catch(e){console.warn("\u26A0\uFE0F Could not connect to local LLM:",e)}return{localModels:m,llm:M}}async function B(){let{localModels:e,llm:t}=await I();return{vector:t?{embed:t.embed}:void 0,store:w(),llmBattery:t,models:e}}async function W(){return B()}var X={store:w(),llmBattery:null,vector:void 0,models:null};export{y as LocalModels,X as batteries,B as getBatteries,E as getLLMCapability,W as getStandardCapabilities,w as getStoreCapabilityDefault};
1
+ var S=new Map,p=new Map;function O(e,t){if(e.length!==t.length)throw new Error("Vectors must have the same length for cosine similarity.");let o=0,n=0,s=0;for(let r=0;r<e.length;r++)o+=e[r]*t[r],n+=e[r]*e[r],s+=t[r]*t[r];return n=Math.sqrt(n),s=Math.sqrt(s),n===0||s===0?0:o/(n*s)}function M(){return{async get(e){return S.get(e)},async set(e,t){S.set(e,t)},async createCollection(e,t,o){p.has(e)&&console.warn(`Collection '${e}' already exists. Overwriting.`),p.set(e,[])},async vectorAdd(e,t){let o=p.get(e);if(!o)throw new Error(`Collection '${e}' not found. Create it first.`);if(!t.embedding||!Array.isArray(t.embedding))throw new Error("Document must have an 'embedding' property that is an array of numbers.");o.push(t)},async vectorSearch(e,t,o=5){let n=p.get(e);if(!n)throw new Error(`Collection '${e}' not found. Create it first.`);let s=n.map(r=>({doc:r,score:O(t,r.embedding)}));return s.sort((r,i)=>i.score-r.score),s.slice(0,o).map(r=>r.doc)}}}function k(e){if(typeof e=="string")return{role:"user",content:e};let t=[{type:"text",text:e.text}];for(let o of e.images||[])t.push({type:"image_url",image_url:{url:o}});return{role:"user",content:t}}var N="http://localhost:1234/v1";function A(e,t=N){return{async predict(o,n,s,r){try{let i=r?e.getStructuredLLM():e.getLLM(),l=[{role:"system",content:o},k(n)],a=await fetch(`${t}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:i.id,messages:l,temperature:.7,...s&&s.length>0?{tools:s}:{},response_format:r})});if(!a.ok)throw new Error(`LLM Error: ${a.status} ${a.statusText}`);return(await a.json()).choices[0]?.message??{content:""}}catch(i){throw i.cause?.code==="ECONNREFUSED"?new Error("No LLM provider configured. Please start LM Studio or provide an API key.",{cause:i}):i}},async embed(o){try{let n=e.getEmbedding(),s=await fetch(`${t}/embeddings`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:n.id,input:o})});if(!s.ok)throw new Error(`Embedding Error: ${s.status}`);return(await s.json()).data[0]?.embedding??[]}catch(n){throw n.cause?.code==="ECONNREFUSED"?new Error("No LLM provider configured. Please start LM Studio or provide an API key.",{cause:n}):n}}}}var h=".models.cache.json";var c=typeof window<"u"&&typeof window.localStorage<"u";async function _(e){try{if(c){let t=window.localStorage.getItem(h);if(!t)return null;let o=JSON.parse(t);return o.baseUrl!==e||Date.now()-o.timestamp>864e5?null:o.models}else{let t=await import("node:fs/promises"),n=(await import("node:path")).join(process.cwd(),h);try{let s=await t.readFile(n,"utf-8"),r=JSON.parse(s);return r.baseUrl!==e||Date.now()-r.timestamp>864e5?null:r.models}catch{return null}}}catch(t){return console.warn("\u26A0\uFE0F Error reading model cache:",t),null}}async function P(e,t){let o={timestamp:Date.now(),baseUrl:e,models:t};try{if(c)window.localStorage.setItem(h,JSON.stringify(o));else{let n=await import("node:fs/promises"),r=(await import("node:path")).join(process.cwd(),h);await n.writeFile(r,JSON.stringify(o,null,2))}}catch(n){console.error("\u274C Error writing model cache:",n)}}var u=async(e,t)=>{let o=new AbortController,n=setTimeout(()=>o.abort(),6e4);try{let s=await fetch(e,{...t,signal:o.signal});return clearTimeout(n),s}catch(s){throw clearTimeout(n),s}};async function v(e,t){try{let o={type:"json_schema",json_schema:{name:"test",strict:!1,schema:{type:"object",properties:{status:{type:"string"}}}}},n=await u(`${e}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:t,messages:[{role:"system",content:"You respond in JSON."},{role:"user",content:'Return JSON: {"status": "ok"}'}],response_format:o,max_tokens:20})});if(!n.ok)return n.status===400?x(e,t):{ok:!1,msg:`HTTP ${n.status}`};let s=await n.json();return JSON.parse(s.choices[0].message.content),{ok:!0,msg:"OK (Schema)"}}catch(o){return{ok:!1,msg:o.message||"Error"}}}async function x(e,t){try{return(await u(`${e}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:t,messages:[{role:"user",content:'JSON: {"a":1}'}],response_format:{type:"json_object"},max_tokens:10})})).ok?{ok:!0,msg:"OK (Legacy Mode)"}:{ok:!1,msg:"Not Supported"}}catch{return{ok:!1,msg:"Legacy Fail"}}}async function D(e,t){try{return(await u(`${e}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:t,messages:[{role:"user",content:"hi"}],max_tokens:1})})).ok}catch{return!1}}async function j(e,t){try{let o=await u(`${e}/embeddings`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:t,input:"test"})});return o.ok?(await o.json()).data[0]?.embedding?.length??null:null}catch{return null}}var J="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAMUlEQVR4nGO4o6FBU8QwasFoEI2motF8MFpUjJamo/XBaJU52qoYbReNNh01hkg+AACGobA9N+tfoAAAAABJRU5ErkJggg==";async function U(e,t){try{return(await u(`${e}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:t,messages:[{role:"user",content:[{type:"text",text:"What color is this?"},{type:"image_url",image_url:{url:J}}]}],max_tokens:10})})).ok}catch{return!1}}async function E(e){let t=await _(e),o;try{let i=await fetch(`${e}/models`);if(!i.ok)throw new Error("Could not connect");o=(await i.json()).data.map(a=>a.id).sort()}catch{return t?(console.log("\u26A0\uFE0F LM Studio unavailable, using cached model audit."),t):(console.error("\u274C Failed to connect to LM Studio."),[])}if(t){let i=t.map(l=>l.id).sort();if(JSON.stringify(o)===JSON.stringify(i))return console.log("\u2705 Using cached model audit."),t;console.log("\u{1F50D} Model list changed. Re-running audit...")}console.log("\u{1F50D} Scanning models (this may take a moment)...");let n=[],s=o.map(i=>({id:i})),r;c||(r=await import("node:readline"));for(let i of s){!c&&r&&(r.cursorTo(process.stdout,0),process.stdout.write(`\u{1F449} Testing: ${i.id}...`),r.clearLine(process.stdout,1));let l="Unknown",a=!1,g=!1,d,b,T=await D(e,i.id),f=await j(e,i.id);if(f&&(b=f),T){l="LLM";let L=await v(e,i.id);a=L.ok,g=await U(e,i.id),d=a?L.msg:`Fail: ${L.msg}`,g&&(d+=" +Vision")}else f?(l="Embedding",d=`OK (Dim: ${f})`):d="LLM Fail";n.push({id:i.id,type:l,structuredOutput:a,vision:g,dimension:b,status:d})}return!c&&r&&(r.cursorTo(process.stdout,0),r.clearLine(process.stdout,0)),console.log(`
2
+ `),console.table(n),await P(e,n),console.log("\u{1F4DD} Audit results saved to cache."),n}var $="http://localhost:1234/v1",y=class{constructor(t=$){this.baseUrl=t}baseUrl;models=[];defaultLLM=null;defaultEmbedding=null;defaultStructuredLLM=null;async audit(){this.models=await E(this.baseUrl),this.selectDefaults()}selectDefaults(){this.defaultEmbedding=this.models.find(t=>t.type==="Embedding")||null,this.defaultLLM=this.models.find(t=>t.type==="LLM")||null,this.defaultStructuredLLM=this.models.find(t=>t.type==="LLM"&&t.structuredOutput)||null,this.defaultEmbedding||console.warn("\u26A0\uFE0F No embedding model found."),this.defaultLLM||console.warn("\u26A0\uFE0F No LLM found."),this.defaultStructuredLLM||console.warn("\u26A0\uFE0F No LLM with structured output support found.")}getModels(){return this.models}_setDefaultModel(t,o,n,s){let r=this.models.find(i=>i.id===t&&n(i));if(!r)throw new Error(`Model '${t}' not found or is not ${s}.`);this[o]=r}setDefaultLLM(t){this._setDefaultModel(t,"defaultLLM",o=>o.type==="LLM","an LLM")}setDefaultEmbedding(t){this._setDefaultModel(t,"defaultEmbedding",o=>o.dimension!==void 0,"an embedding model")}setDefaultStructuredLLM(t){this._setDefaultModel(t,"defaultStructuredLLM",o=>o.type==="LLM"&&o.structuredOutput,"a structured-output LLM")}getLLM(){if(!this.defaultLLM)throw new Error("No LLM available.");return this.defaultLLM}getEmbedding(){if(!this.defaultEmbedding)throw new Error("No embedding model available.");return this.defaultEmbedding}getStructuredLLM(){if(!this.defaultStructuredLLM)throw new Error("No structured-output LLM available.");return this.defaultStructuredLLM}};var F=typeof window<"u",R=F&&window.location.protocol==="https:",m=null,w=null,C=!1;async function I(){if(C)return{localModels:m,llm:w};if(C=!0,R)return console.log("\u{1F4E1} HTTPS detected - local LLM endpoints disabled. Use HTTP for local LLM support."),{localModels:null,llm:null};try{m=new y,await m.audit(),w=A(m)}catch(e){console.warn("\u26A0\uFE0F Could not connect to local LLM:",e)}return{localModels:m,llm:w}}async function B(){let{localModels:e,llm:t}=await I();return{vector:t?{embed:t.embed}:void 0,store:M(),llmBattery:t,models:e}}async function W(){return B()}var X={store:M(),llmBattery:null,vector:void 0,models:null};export{y as LocalModels,X as batteries,B as getBatteries,A as getLLMCapability,W as getStandardCapabilities,M as getStoreCapabilityDefault};
3
3
  //# sourceMappingURL=tjs-batteries.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/batteries/store.ts", "../src/batteries/llm.ts", "../src/batteries/audit.ts", "../src/batteries/models.ts", "../src/batteries/index.ts"],
4
- "sourcesContent": ["/**\n * Store Capability Battery\n * Provides Key-Value storage and lightweight in-memory Vector Search.\n */\n\nexport interface StoreCapability {\n get(key: string): Promise<any>\n set(key: string, val: any): Promise<void>\n createCollection(\n name: string,\n schema?: any,\n dimension?: number\n ): Promise<void>\n vectorAdd(collection: string, doc: any): Promise<void>\n vectorSearch(collection: string, vector: number[], k?: number): Promise<any[]>\n}\n\n// In-memory KV store fallback\nconst kvStore = new Map<string, any>()\n// In-memory Vector store fallback\nconst collections = new Map<string, any[]>()\n\nexport function cosineSimilarity(vecA: number[], vecB: number[]): number {\n if (vecA.length !== vecB.length) {\n throw new Error('Vectors must have the same length for cosine similarity.')\n }\n let dotProduct = 0\n let magA = 0\n let magB = 0\n for (let i = 0; i < vecA.length; i++) {\n dotProduct += vecA[i] * vecB[i]\n magA += vecA[i] * vecA[i]\n magB += vecB[i] * vecB[i]\n }\n magA = Math.sqrt(magA)\n magB = Math.sqrt(magB)\n if (magA === 0 || magB === 0) {\n return 0\n }\n return dotProduct / (magA * magB)\n}\n\nexport function getStoreCapability(): StoreCapability {\n return {\n async get(key: string) {\n return kvStore.get(key)\n },\n\n async set(key: string, val: any) {\n kvStore.set(key, val)\n },\n\n async createCollection(name: string, _schema?: any, _dimension?: number) {\n if (collections.has(name)) {\n console.warn(`Collection '${name}' already exists. Overwriting.`)\n }\n collections.set(name, [])\n },\n\n async vectorAdd(collection: string, doc: any) {\n const db = collections.get(collection)\n if (!db)\n throw new Error(\n `Collection '${collection}' not found. Create it first.`\n )\n if (!doc.embedding || !Array.isArray(doc.embedding)) {\n throw new Error(\n \"Document must have an 'embedding' property that is an array of numbers.\"\n )\n }\n db.push(doc)\n },\n\n async vectorSearch(collection: string, vector: number[], k = 5) {\n const db = collections.get(collection)\n if (!db)\n throw new Error(\n `Collection '${collection}' not found. Create it first.`\n )\n\n const scoredDocs = db.map((doc) => ({\n doc,\n score: cosineSimilarity(vector, doc.embedding),\n }))\n\n scoredDocs.sort((a, b) => b.score - a.score)\n\n return scoredDocs.slice(0, k).map((item) => item.doc)\n },\n }\n}\n", "import { LocalModels } from './models'\n\n/**\n * LLM Capability Battery\n * Bridges to local LM Studio instance via HTTP.\n */\n\n/**\n * User content can be a simple string or multimodal with images.\n * Images should be URLs or data URIs (data:image/...;base64,...)\n */\nexport type UserContent = string | { text: string; images?: string[] }\n\nexport interface LLMCapability {\n predict(\n system: string,\n user: UserContent,\n tools?: any[],\n responseFormat?: any\n ): Promise<any>\n embed(text: string): Promise<number[]>\n}\n\n/**\n * Build user message content - supports text-only or multimodal (text + images)\n */\nfunction buildUserMessage(user: UserContent): { role: string; content: any } {\n if (typeof user === 'string') {\n return { role: 'user', content: user }\n }\n\n // Multimodal: array of content blocks (OpenAI vision format)\n const content: any[] = [{ type: 'text', text: user.text }]\n\n for (const img of user.images || []) {\n content.push({\n type: 'image_url',\n image_url: {\n url: img, // Can be URL or data:image/...;base64,...\n },\n })\n }\n\n return { role: 'user', content }\n}\n\nconst DEFAULT_BASE_URL = 'http://localhost:1234/v1'\n\nexport function getLLMCapability(\n models: LocalModels,\n baseUrl = DEFAULT_BASE_URL\n): LLMCapability {\n return {\n async predict(\n system: string,\n user: UserContent,\n tools?: any[],\n responseFormat?: any\n ): Promise<any> {\n try {\n const model = responseFormat\n ? models.getStructuredLLM()\n : models.getLLM()\n const messages = [\n { role: 'system', content: system },\n buildUserMessage(user),\n ]\n\n const response = await fetch(`${baseUrl}/chat/completions`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: model.id,\n messages,\n temperature: 0.7,\n // Only include tools when non-empty: an empty tools array makes\n // LM Studio apply a tool-call grammar that can't be combined with\n // a structured-output response_format (\"lazy grammar\" 400).\n ...(tools && tools.length > 0 ? { tools } : {}),\n response_format: responseFormat,\n }),\n })\n\n if (!response.ok) {\n throw new Error(\n `LLM Error: ${response.status} ${response.statusText}`\n )\n }\n\n const data = await response.json()\n return data.choices[0]?.message ?? { content: '' }\n } catch (e: any) {\n if (e.cause?.code === 'ECONNREFUSED') {\n throw new Error(\n 'No LLM provider configured. Please start LM Studio or provide an API key.',\n { cause: e }\n )\n }\n throw e\n }\n },\n\n async embed(text: string): Promise<number[]> {\n try {\n const model = models.getEmbedding()\n const response = await fetch(`${baseUrl}/embeddings`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: model.id,\n input: text,\n }),\n })\n\n if (!response.ok) {\n throw new Error(`Embedding Error: ${response.status}`)\n }\n\n const data = await response.json()\n return data.data[0]?.embedding ?? []\n } catch (e: any) {\n if (e.cause?.code === 'ECONNREFUSED') {\n throw new Error(\n 'No LLM provider configured. Please start LM Studio or provide an API key.',\n { cause: e }\n )\n }\n throw e\n }\n },\n }\n}\n", "const TIMEOUT_MS = 60000\nconst CACHE_FILE = '.models.cache.json'\nconst CACHE_TTL_MS = 24 * 60 * 60 * 1000 // 24 hours\n\nexport interface ModelAudit {\n id: string\n type: 'LLM' | 'Embedding' | 'Unknown'\n structuredOutput: boolean\n vision: boolean\n dimension?: number\n status: string\n}\n\ninterface CacheData {\n timestamp: number\n baseUrl: string\n models: ModelAudit[]\n}\n\nconst isBrowser =\n typeof window !== 'undefined' && typeof window.localStorage !== 'undefined'\n\nasync function readCache(baseUrl: string): Promise<ModelAudit[] | null> {\n try {\n if (isBrowser) {\n const cached = window.localStorage.getItem(CACHE_FILE)\n if (!cached) return null\n const data: CacheData = JSON.parse(cached)\n // Check TTL and baseUrl match\n if (data.baseUrl !== baseUrl) return null\n if (Date.now() - data.timestamp > CACHE_TTL_MS) return null\n return data.models\n } else {\n // Node.js: read from file\n const fs = await import('node:fs/promises')\n const path = await import('node:path')\n const cacheFile = path.join(process.cwd(), CACHE_FILE)\n try {\n const content = await fs.readFile(cacheFile, 'utf-8')\n const data: CacheData = JSON.parse(content)\n // Check TTL and baseUrl match\n if (data.baseUrl !== baseUrl) return null\n if (Date.now() - data.timestamp > CACHE_TTL_MS) return null\n return data.models\n } catch {\n return null // File doesn't exist or can't be read\n }\n }\n } catch (e) {\n console.warn('\u26A0\uFE0F Error reading model cache:', e)\n return null\n }\n}\n\nasync function writeCache(\n baseUrl: string,\n models: ModelAudit[]\n): Promise<void> {\n const data: CacheData = {\n timestamp: Date.now(),\n baseUrl,\n models,\n }\n try {\n if (isBrowser) {\n window.localStorage.setItem(CACHE_FILE, JSON.stringify(data))\n } else {\n // Node.js: write to file\n const fs = await import('node:fs/promises')\n const path = await import('node:path')\n const cacheFile = path.join(process.cwd(), CACHE_FILE)\n await fs.writeFile(cacheFile, JSON.stringify(data, null, 2))\n }\n } catch (e) {\n console.error('\u274C Error writing model cache:', e)\n }\n}\n\n// ... (fetchWithTimeout, checkStructured, etc. remain the same)\nconst fetchWithTimeout = async (url: string, options: RequestInit) => {\n const controller = new AbortController()\n const id = setTimeout(() => controller.abort(), TIMEOUT_MS)\n try {\n const res = await fetch(url, { ...options, signal: controller.signal })\n clearTimeout(id)\n return res\n } catch (error) {\n clearTimeout(id)\n throw error\n }\n}\n\nasync function checkStructured(\n baseUrl: string,\n modelId: string\n): Promise<{ ok: boolean; msg?: string }> {\n try {\n const schemaPayload = {\n type: 'json_schema',\n json_schema: {\n name: 'test',\n strict: false,\n schema: {\n type: 'object',\n properties: { status: { type: 'string' } },\n },\n },\n }\n const res = await fetchWithTimeout(`${baseUrl}/chat/completions`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: modelId,\n messages: [\n { role: 'system', content: 'You respond in JSON.' },\n { role: 'user', content: 'Return JSON: {\"status\": \"ok\"}' },\n ],\n response_format: schemaPayload,\n max_tokens: 20,\n }),\n })\n if (!res.ok) {\n if (res.status === 400) {\n return checkStructuredLegacy(baseUrl, modelId)\n }\n return { ok: false, msg: `HTTP ${res.status}` }\n }\n const data = await res.json()\n JSON.parse(data.choices[0].message.content)\n return { ok: true, msg: 'OK (Schema)' }\n } catch (e: any) {\n return { ok: false, msg: e.message || 'Error' }\n }\n}\n\nasync function checkStructuredLegacy(\n baseUrl: string,\n modelId: string\n): Promise<{ ok: boolean; msg?: string }> {\n try {\n const res = await fetchWithTimeout(`${baseUrl}/chat/completions`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: modelId,\n messages: [{ role: 'user', content: 'JSON: {\"a\":1}' }],\n response_format: { type: 'json_object' },\n max_tokens: 10,\n }),\n })\n if (res.ok) return { ok: true, msg: 'OK (Legacy Mode)' }\n return { ok: false, msg: 'Not Supported' }\n } catch {\n return { ok: false, msg: 'Legacy Fail' }\n }\n}\n\nasync function checkLLM(baseUrl: string, modelId: string): Promise<boolean> {\n try {\n const res = await fetchWithTimeout(`${baseUrl}/chat/completions`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: modelId,\n messages: [{ role: 'user', content: 'hi' }],\n max_tokens: 1,\n }),\n })\n return res.ok\n } catch {\n return false\n }\n}\n\nasync function checkEmbedding(\n baseUrl: string,\n modelId: string\n): Promise<number | null> {\n try {\n const res = await fetchWithTimeout(`${baseUrl}/embeddings`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ model: modelId, input: 'test' }),\n })\n if (!res.ok) return null\n const data = await res.json()\n return data.data[0]?.embedding?.length ?? null\n } catch {\n return null\n }\n}\n\n// Tiny 1x1 red PNG as base64 for vision testing\nconst TINY_TEST_IMAGE =\n 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg=='\n\nasync function checkVision(baseUrl: string, modelId: string): Promise<boolean> {\n try {\n const res = await fetchWithTimeout(`${baseUrl}/chat/completions`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: modelId,\n messages: [\n {\n role: 'user',\n content: [\n { type: 'text', text: 'What color is this?' },\n { type: 'image_url', image_url: { url: TINY_TEST_IMAGE } },\n ],\n },\n ],\n max_tokens: 10,\n }),\n })\n // If the model accepts the multimodal format without error, it supports vision\n return res.ok\n } catch {\n return false\n }\n}\n\nexport async function auditModels(baseUrl: string): Promise<ModelAudit[]> {\n // 1. Try to load from cache first (file-based with 24h TTL)\n const cachedData = await readCache(baseUrl)\n\n // 2. Get current model list from server\n let serverModelIds: string[]\n try {\n const res = await fetch(`${baseUrl}/models`)\n if (!res.ok) throw new Error('Could not connect')\n const data = (await res.json()) as { data: { id: string }[] }\n serverModelIds = data.data.map((m) => m.id).sort()\n } catch {\n // If we have cache and server is unavailable, use cache\n if (cachedData) {\n console.log('\u26A0\uFE0F LM Studio unavailable, using cached model audit.')\n return cachedData\n }\n console.error('\u274C Failed to connect to LM Studio.')\n return []\n }\n\n // 3. Check if cache is still valid (same models)\n if (cachedData) {\n const cachedModelIds = cachedData.map((m) => m.id).sort()\n if (JSON.stringify(serverModelIds) === JSON.stringify(cachedModelIds)) {\n console.log('\u2705 Using cached model audit.')\n return cachedData\n }\n console.log('\uD83D\uDD0D Model list changed. Re-running audit...')\n }\n\n // 4. Run full audit\n console.log('\uD83D\uDD0D Scanning models (this may take a moment)...')\n const results: ModelAudit[] = []\n const modelList = serverModelIds.map((id) => ({ id }))\n\n let readline: typeof import('node:readline') | undefined\n if (!isBrowser) {\n readline = await import('node:readline')\n }\n\n for (const model of modelList) {\n if (!isBrowser && readline) {\n readline.cursorTo(process.stdout, 0)\n process.stdout.write(`\uD83D\uDC49 Testing: ${model.id}...`)\n readline.clearLine(process.stdout, 1)\n }\n let type: ModelAudit['type'] = 'Unknown'\n let structured = false\n let vision = false\n let statusMsg: string\n let dimension: number | undefined = undefined\n\n const isLLM = await checkLLM(baseUrl, model.id)\n const dim = await checkEmbedding(baseUrl, model.id)\n\n if (dim) {\n dimension = dim\n }\n\n if (isLLM) {\n type = 'LLM'\n const structRes = await checkStructured(baseUrl, model.id)\n structured = structRes.ok\n vision = await checkVision(baseUrl, model.id)\n statusMsg = structured ? structRes.msg! : `Fail: ${structRes.msg}`\n if (vision) statusMsg += ' +Vision'\n } else if (dim) {\n type = 'Embedding'\n statusMsg = `OK (Dim: ${dim})`\n } else {\n statusMsg = 'LLM Fail'\n }\n\n results.push({\n id: model.id,\n type,\n structuredOutput: structured,\n vision,\n dimension,\n status: statusMsg,\n })\n }\n if (!isBrowser && readline) {\n readline.cursorTo(process.stdout, 0)\n readline.clearLine(process.stdout, 0)\n }\n\n console.log('\\n')\n console.table(results)\n\n // 5. Save to cache\n await writeCache(baseUrl, results)\n console.log(`\uD83D\uDCDD Audit results saved to cache.`)\n\n return results\n}\n", "import { auditModels, type ModelAudit } from './audit'\n\nconst DEFAULT_BASE_URL = 'http://localhost:1234/v1'\n\nexport class LocalModels {\n private models: ModelAudit[] = []\n private defaultLLM: ModelAudit | null = null\n private defaultEmbedding: ModelAudit | null = null\n private defaultStructuredLLM: ModelAudit | null = null\n\n constructor(private baseUrl = DEFAULT_BASE_URL) {}\n\n async audit() {\n this.models = await auditModels(this.baseUrl)\n this.selectDefaults()\n }\n\n private selectDefaults() {\n this.defaultEmbedding =\n this.models.find((m) => m.type === 'Embedding') || null\n this.defaultLLM = this.models.find((m) => m.type === 'LLM') || null\n this.defaultStructuredLLM =\n this.models.find((m) => m.type === 'LLM' && m.structuredOutput) || null\n\n if (!this.defaultEmbedding) {\n console.warn('\u26A0\uFE0F No embedding model found.')\n }\n if (!this.defaultLLM) {\n console.warn('\u26A0\uFE0F No LLM found.')\n }\n if (!this.defaultStructuredLLM) {\n console.warn('\u26A0\uFE0F No LLM with structured output support found.')\n }\n }\n\n getModels() {\n return this.models\n }\n\n private _setDefaultModel(\n modelId: string,\n property: 'defaultLLM' | 'defaultEmbedding' | 'defaultStructuredLLM',\n predicate: (model: ModelAudit) => boolean,\n errorType: string\n ) {\n const model = this.models.find((m) => m.id === modelId && predicate(m))\n if (!model) {\n throw new Error(`Model '${modelId}' not found or is not ${errorType}.`)\n }\n this[property] = model\n }\n\n setDefaultLLM(modelId: string) {\n this._setDefaultModel(\n modelId,\n 'defaultLLM',\n (m) => m.type === 'LLM',\n 'an LLM'\n )\n }\n\n setDefaultEmbedding(modelId: string) {\n this._setDefaultModel(\n modelId,\n 'defaultEmbedding',\n (m) => m.dimension !== undefined,\n 'an embedding model'\n )\n }\n\n setDefaultStructuredLLM(modelId: string) {\n this._setDefaultModel(\n modelId,\n 'defaultStructuredLLM',\n (m) => m.type === 'LLM' && m.structuredOutput,\n 'a structured-output LLM'\n )\n }\n\n getLLM() {\n if (!this.defaultLLM) {\n throw new Error('No LLM available.')\n }\n return this.defaultLLM\n }\n\n getEmbedding() {\n if (!this.defaultEmbedding) {\n throw new Error('No embedding model available.')\n }\n return this.defaultEmbedding\n }\n\n getStructuredLLM() {\n if (!this.defaultStructuredLLM) {\n throw new Error('No structured-output LLM available.')\n }\n return this.defaultStructuredLLM\n }\n}\n", "import { getStoreCapability as getStoreCapabilityDefault } from './store'\nimport { getLLMCapability } from './llm'\nimport { LocalModels } from './models'\n\n// Check if we're in a browser on HTTPS (can't connect to local HTTP endpoints)\nconst isBrowser = typeof window !== 'undefined'\nconst isHttps = isBrowser && window.location.protocol === 'https:'\n\n// Lazy initialization - don't audit on import\nlet localModels: LocalModels | null = null\nlet llm: ReturnType<typeof getLLMCapability> | null = null\nlet initializationAttempted = false\n\nasync function ensureInitialized() {\n if (initializationAttempted) {\n return { localModels, llm }\n }\n initializationAttempted = true\n\n // Skip local LLM initialization on HTTPS (mixed content would block it anyway)\n if (isHttps) {\n console.log(\n '\uD83D\uDCE1 HTTPS detected - local LLM endpoints disabled. Use HTTP for local LLM support.'\n )\n return { localModels: null, llm: null }\n }\n\n try {\n localModels = new LocalModels()\n await localModels.audit()\n llm = getLLMCapability(localModels)\n } catch (e) {\n console.warn('\u26A0\uFE0F Could not connect to local LLM:', e)\n }\n return { localModels, llm }\n}\n\nexport async function getBatteries() {\n const { localModels, llm } = await ensureInitialized()\n return {\n vector: llm ? { embed: llm.embed } : undefined,\n store: getStoreCapabilityDefault(),\n llmBattery: llm,\n models: localModels,\n }\n}\n\nexport async function getStandardCapabilities() {\n return getBatteries()\n}\n\n// For non-async access (after initialization)\nexport { LocalModels, getLLMCapability, getStoreCapabilityDefault }\n\n// Synchronous batteries object for tests and simple use cases\nexport const batteries = {\n store: getStoreCapabilityDefault(),\n llmBattery: null as ReturnType<typeof getLLMCapability> | null,\n vector: undefined as\n | { embed: (text: string) => Promise<number[]> }\n | undefined,\n models: null as LocalModels | null,\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Store Capability Battery\n * Provides Key-Value storage and lightweight in-memory Vector Search.\n */\n\nexport interface StoreCapability {\n get(key: string): Promise<any>\n set(key: string, val: any): Promise<void>\n createCollection(\n name: string,\n schema?: any,\n dimension?: number\n ): Promise<void>\n vectorAdd(collection: string, doc: any): Promise<void>\n vectorSearch(collection: string, vector: number[], k?: number): Promise<any[]>\n}\n\n// In-memory KV store fallback\nconst kvStore = new Map<string, any>()\n// In-memory Vector store fallback\nconst collections = new Map<string, any[]>()\n\nexport function cosineSimilarity(vecA: number[], vecB: number[]): number {\n if (vecA.length !== vecB.length) {\n throw new Error('Vectors must have the same length for cosine similarity.')\n }\n let dotProduct = 0\n let magA = 0\n let magB = 0\n for (let i = 0; i < vecA.length; i++) {\n dotProduct += vecA[i] * vecB[i]\n magA += vecA[i] * vecA[i]\n magB += vecB[i] * vecB[i]\n }\n magA = Math.sqrt(magA)\n magB = Math.sqrt(magB)\n if (magA === 0 || magB === 0) {\n return 0\n }\n return dotProduct / (magA * magB)\n}\n\nexport function getStoreCapability(): StoreCapability {\n return {\n async get(key: string) {\n return kvStore.get(key)\n },\n\n async set(key: string, val: any) {\n kvStore.set(key, val)\n },\n\n async createCollection(name: string, _schema?: any, _dimension?: number) {\n if (collections.has(name)) {\n console.warn(`Collection '${name}' already exists. Overwriting.`)\n }\n collections.set(name, [])\n },\n\n async vectorAdd(collection: string, doc: any) {\n const db = collections.get(collection)\n if (!db)\n throw new Error(\n `Collection '${collection}' not found. Create it first.`\n )\n if (!doc.embedding || !Array.isArray(doc.embedding)) {\n throw new Error(\n \"Document must have an 'embedding' property that is an array of numbers.\"\n )\n }\n db.push(doc)\n },\n\n async vectorSearch(collection: string, vector: number[], k = 5) {\n const db = collections.get(collection)\n if (!db)\n throw new Error(\n `Collection '${collection}' not found. Create it first.`\n )\n\n const scoredDocs = db.map((doc) => ({\n doc,\n score: cosineSimilarity(vector, doc.embedding),\n }))\n\n scoredDocs.sort((a, b) => b.score - a.score)\n\n return scoredDocs.slice(0, k).map((item) => item.doc)\n },\n }\n}\n", "import { LocalModels } from './models'\n\n/**\n * LLM Capability Battery\n * Bridges to local LM Studio instance via HTTP.\n */\n\n/**\n * User content can be a simple string or multimodal with images.\n * Images should be URLs or data URIs (data:image/...;base64,...)\n */\nexport type UserContent = string | { text: string; images?: string[] }\n\nexport interface LLMCapability {\n predict(\n system: string,\n user: UserContent,\n tools?: any[],\n responseFormat?: any\n ): Promise<any>\n embed(text: string): Promise<number[]>\n}\n\n/**\n * Build user message content - supports text-only or multimodal (text + images)\n */\nfunction buildUserMessage(user: UserContent): { role: string; content: any } {\n if (typeof user === 'string') {\n return { role: 'user', content: user }\n }\n\n // Multimodal: array of content blocks (OpenAI vision format)\n const content: any[] = [{ type: 'text', text: user.text }]\n\n for (const img of user.images || []) {\n content.push({\n type: 'image_url',\n image_url: {\n url: img, // Can be URL or data:image/...;base64,...\n },\n })\n }\n\n return { role: 'user', content }\n}\n\nconst DEFAULT_BASE_URL = 'http://localhost:1234/v1'\n\nexport function getLLMCapability(\n models: LocalModels,\n baseUrl = DEFAULT_BASE_URL\n): LLMCapability {\n return {\n async predict(\n system: string,\n user: UserContent,\n tools?: any[],\n responseFormat?: any\n ): Promise<any> {\n try {\n const model = responseFormat\n ? models.getStructuredLLM()\n : models.getLLM()\n const messages = [\n { role: 'system', content: system },\n buildUserMessage(user),\n ]\n\n const response = await fetch(`${baseUrl}/chat/completions`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: model.id,\n messages,\n temperature: 0.7,\n // Only include tools when non-empty: an empty tools array makes\n // LM Studio apply a tool-call grammar that can't be combined with\n // a structured-output response_format (\"lazy grammar\" 400).\n ...(tools && tools.length > 0 ? { tools } : {}),\n response_format: responseFormat,\n }),\n })\n\n if (!response.ok) {\n throw new Error(\n `LLM Error: ${response.status} ${response.statusText}`\n )\n }\n\n const data = await response.json()\n return data.choices[0]?.message ?? { content: '' }\n } catch (e: any) {\n if (e.cause?.code === 'ECONNREFUSED') {\n throw new Error(\n 'No LLM provider configured. Please start LM Studio or provide an API key.',\n { cause: e }\n )\n }\n throw e\n }\n },\n\n async embed(text: string): Promise<number[]> {\n try {\n const model = models.getEmbedding()\n const response = await fetch(`${baseUrl}/embeddings`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: model.id,\n input: text,\n }),\n })\n\n if (!response.ok) {\n throw new Error(`Embedding Error: ${response.status}`)\n }\n\n const data = await response.json()\n return data.data[0]?.embedding ?? []\n } catch (e: any) {\n if (e.cause?.code === 'ECONNREFUSED') {\n throw new Error(\n 'No LLM provider configured. Please start LM Studio or provide an API key.',\n { cause: e }\n )\n }\n throw e\n }\n },\n }\n}\n", "const TIMEOUT_MS = 60000\nconst CACHE_FILE = '.models.cache.json'\nconst CACHE_TTL_MS = 24 * 60 * 60 * 1000 // 24 hours\n\nexport interface ModelAudit {\n id: string\n type: 'LLM' | 'Embedding' | 'Unknown'\n structuredOutput: boolean\n vision: boolean\n dimension?: number\n status: string\n}\n\ninterface CacheData {\n timestamp: number\n baseUrl: string\n models: ModelAudit[]\n}\n\nconst isBrowser =\n typeof window !== 'undefined' && typeof window.localStorage !== 'undefined'\n\nasync function readCache(baseUrl: string): Promise<ModelAudit[] | null> {\n try {\n if (isBrowser) {\n const cached = window.localStorage.getItem(CACHE_FILE)\n if (!cached) return null\n const data: CacheData = JSON.parse(cached)\n // Check TTL and baseUrl match\n if (data.baseUrl !== baseUrl) return null\n if (Date.now() - data.timestamp > CACHE_TTL_MS) return null\n return data.models\n } else {\n // Node.js: read from file\n const fs = await import('node:fs/promises')\n const path = await import('node:path')\n const cacheFile = path.join(process.cwd(), CACHE_FILE)\n try {\n const content = await fs.readFile(cacheFile, 'utf-8')\n const data: CacheData = JSON.parse(content)\n // Check TTL and baseUrl match\n if (data.baseUrl !== baseUrl) return null\n if (Date.now() - data.timestamp > CACHE_TTL_MS) return null\n return data.models\n } catch {\n return null // File doesn't exist or can't be read\n }\n }\n } catch (e) {\n console.warn('\u26A0\uFE0F Error reading model cache:', e)\n return null\n }\n}\n\nasync function writeCache(\n baseUrl: string,\n models: ModelAudit[]\n): Promise<void> {\n const data: CacheData = {\n timestamp: Date.now(),\n baseUrl,\n models,\n }\n try {\n if (isBrowser) {\n window.localStorage.setItem(CACHE_FILE, JSON.stringify(data))\n } else {\n // Node.js: write to file\n const fs = await import('node:fs/promises')\n const path = await import('node:path')\n const cacheFile = path.join(process.cwd(), CACHE_FILE)\n await fs.writeFile(cacheFile, JSON.stringify(data, null, 2))\n }\n } catch (e) {\n console.error('\u274C Error writing model cache:', e)\n }\n}\n\n// ... (fetchWithTimeout, checkStructured, etc. remain the same)\nconst fetchWithTimeout = async (url: string, options: RequestInit) => {\n const controller = new AbortController()\n const id = setTimeout(() => controller.abort(), TIMEOUT_MS)\n try {\n const res = await fetch(url, { ...options, signal: controller.signal })\n clearTimeout(id)\n return res\n } catch (error) {\n clearTimeout(id)\n throw error\n }\n}\n\nasync function checkStructured(\n baseUrl: string,\n modelId: string\n): Promise<{ ok: boolean; msg?: string }> {\n try {\n const schemaPayload = {\n type: 'json_schema',\n json_schema: {\n name: 'test',\n strict: false,\n schema: {\n type: 'object',\n properties: { status: { type: 'string' } },\n },\n },\n }\n const res = await fetchWithTimeout(`${baseUrl}/chat/completions`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: modelId,\n messages: [\n { role: 'system', content: 'You respond in JSON.' },\n { role: 'user', content: 'Return JSON: {\"status\": \"ok\"}' },\n ],\n response_format: schemaPayload,\n max_tokens: 20,\n }),\n })\n if (!res.ok) {\n if (res.status === 400) {\n return checkStructuredLegacy(baseUrl, modelId)\n }\n return { ok: false, msg: `HTTP ${res.status}` }\n }\n const data = await res.json()\n JSON.parse(data.choices[0].message.content)\n return { ok: true, msg: 'OK (Schema)' }\n } catch (e: any) {\n return { ok: false, msg: e.message || 'Error' }\n }\n}\n\nasync function checkStructuredLegacy(\n baseUrl: string,\n modelId: string\n): Promise<{ ok: boolean; msg?: string }> {\n try {\n const res = await fetchWithTimeout(`${baseUrl}/chat/completions`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: modelId,\n messages: [{ role: 'user', content: 'JSON: {\"a\":1}' }],\n response_format: { type: 'json_object' },\n max_tokens: 10,\n }),\n })\n if (res.ok) return { ok: true, msg: 'OK (Legacy Mode)' }\n return { ok: false, msg: 'Not Supported' }\n } catch {\n return { ok: false, msg: 'Legacy Fail' }\n }\n}\n\nasync function checkLLM(baseUrl: string, modelId: string): Promise<boolean> {\n try {\n const res = await fetchWithTimeout(`${baseUrl}/chat/completions`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: modelId,\n messages: [{ role: 'user', content: 'hi' }],\n max_tokens: 1,\n }),\n })\n return res.ok\n } catch {\n return false\n }\n}\n\nasync function checkEmbedding(\n baseUrl: string,\n modelId: string\n): Promise<number | null> {\n try {\n const res = await fetchWithTimeout(`${baseUrl}/embeddings`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ model: modelId, input: 'test' }),\n })\n if (!res.ok) return null\n const data = await res.json()\n return data.data[0]?.embedding?.length ?? null\n } catch {\n return null\n }\n}\n\n// 32x32 solid-red PNG (base64). NOT 1x1 \u2014 degenerate sizes are rejected by\n// real vision preprocessors (e.g. gemma: \"Cannot handle this data type (1,1,1)\").\nconst TINY_TEST_IMAGE =\n 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAMUlEQVR4nGO4o6FBU8QwasFoEI2motF8MFpUjJamo/XBaJU52qoYbReNNh01hkg+AACGobA9N+tfoAAAAABJRU5ErkJggg=='\n\nasync function checkVision(baseUrl: string, modelId: string): Promise<boolean> {\n try {\n const res = await fetchWithTimeout(`${baseUrl}/chat/completions`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: modelId,\n messages: [\n {\n role: 'user',\n content: [\n { type: 'text', text: 'What color is this?' },\n { type: 'image_url', image_url: { url: TINY_TEST_IMAGE } },\n ],\n },\n ],\n max_tokens: 10,\n }),\n })\n // If the model accepts the multimodal format without error, it supports vision\n return res.ok\n } catch {\n return false\n }\n}\n\nexport async function auditModels(baseUrl: string): Promise<ModelAudit[]> {\n // 1. Try to load from cache first (file-based with 24h TTL)\n const cachedData = await readCache(baseUrl)\n\n // 2. Get current model list from server\n let serverModelIds: string[]\n try {\n const res = await fetch(`${baseUrl}/models`)\n if (!res.ok) throw new Error('Could not connect')\n const data = (await res.json()) as { data: { id: string }[] }\n serverModelIds = data.data.map((m) => m.id).sort()\n } catch {\n // If we have cache and server is unavailable, use cache\n if (cachedData) {\n console.log('\u26A0\uFE0F LM Studio unavailable, using cached model audit.')\n return cachedData\n }\n console.error('\u274C Failed to connect to LM Studio.')\n return []\n }\n\n // 3. Check if cache is still valid (same models)\n if (cachedData) {\n const cachedModelIds = cachedData.map((m) => m.id).sort()\n if (JSON.stringify(serverModelIds) === JSON.stringify(cachedModelIds)) {\n console.log('\u2705 Using cached model audit.')\n return cachedData\n }\n console.log('\uD83D\uDD0D Model list changed. Re-running audit...')\n }\n\n // 4. Run full audit\n console.log('\uD83D\uDD0D Scanning models (this may take a moment)...')\n const results: ModelAudit[] = []\n const modelList = serverModelIds.map((id) => ({ id }))\n\n let readline: typeof import('node:readline') | undefined\n if (!isBrowser) {\n readline = await import('node:readline')\n }\n\n for (const model of modelList) {\n if (!isBrowser && readline) {\n readline.cursorTo(process.stdout, 0)\n process.stdout.write(`\uD83D\uDC49 Testing: ${model.id}...`)\n readline.clearLine(process.stdout, 1)\n }\n let type: ModelAudit['type'] = 'Unknown'\n let structured = false\n let vision = false\n let statusMsg: string\n let dimension: number | undefined = undefined\n\n const isLLM = await checkLLM(baseUrl, model.id)\n const dim = await checkEmbedding(baseUrl, model.id)\n\n if (dim) {\n dimension = dim\n }\n\n if (isLLM) {\n type = 'LLM'\n const structRes = await checkStructured(baseUrl, model.id)\n structured = structRes.ok\n vision = await checkVision(baseUrl, model.id)\n statusMsg = structured ? structRes.msg! : `Fail: ${structRes.msg}`\n if (vision) statusMsg += ' +Vision'\n } else if (dim) {\n type = 'Embedding'\n statusMsg = `OK (Dim: ${dim})`\n } else {\n statusMsg = 'LLM Fail'\n }\n\n results.push({\n id: model.id,\n type,\n structuredOutput: structured,\n vision,\n dimension,\n status: statusMsg,\n })\n }\n if (!isBrowser && readline) {\n readline.cursorTo(process.stdout, 0)\n readline.clearLine(process.stdout, 0)\n }\n\n console.log('\\n')\n console.table(results)\n\n // 5. Save to cache\n await writeCache(baseUrl, results)\n console.log(`\uD83D\uDCDD Audit results saved to cache.`)\n\n return results\n}\n", "import { auditModels, type ModelAudit } from './audit'\n\nconst DEFAULT_BASE_URL = 'http://localhost:1234/v1'\n\nexport class LocalModels {\n private models: ModelAudit[] = []\n private defaultLLM: ModelAudit | null = null\n private defaultEmbedding: ModelAudit | null = null\n private defaultStructuredLLM: ModelAudit | null = null\n\n constructor(private baseUrl = DEFAULT_BASE_URL) {}\n\n async audit() {\n this.models = await auditModels(this.baseUrl)\n this.selectDefaults()\n }\n\n private selectDefaults() {\n this.defaultEmbedding =\n this.models.find((m) => m.type === 'Embedding') || null\n this.defaultLLM = this.models.find((m) => m.type === 'LLM') || null\n this.defaultStructuredLLM =\n this.models.find((m) => m.type === 'LLM' && m.structuredOutput) || null\n\n if (!this.defaultEmbedding) {\n console.warn('\u26A0\uFE0F No embedding model found.')\n }\n if (!this.defaultLLM) {\n console.warn('\u26A0\uFE0F No LLM found.')\n }\n if (!this.defaultStructuredLLM) {\n console.warn('\u26A0\uFE0F No LLM with structured output support found.')\n }\n }\n\n getModels() {\n return this.models\n }\n\n private _setDefaultModel(\n modelId: string,\n property: 'defaultLLM' | 'defaultEmbedding' | 'defaultStructuredLLM',\n predicate: (model: ModelAudit) => boolean,\n errorType: string\n ) {\n const model = this.models.find((m) => m.id === modelId && predicate(m))\n if (!model) {\n throw new Error(`Model '${modelId}' not found or is not ${errorType}.`)\n }\n this[property] = model\n }\n\n setDefaultLLM(modelId: string) {\n this._setDefaultModel(\n modelId,\n 'defaultLLM',\n (m) => m.type === 'LLM',\n 'an LLM'\n )\n }\n\n setDefaultEmbedding(modelId: string) {\n this._setDefaultModel(\n modelId,\n 'defaultEmbedding',\n (m) => m.dimension !== undefined,\n 'an embedding model'\n )\n }\n\n setDefaultStructuredLLM(modelId: string) {\n this._setDefaultModel(\n modelId,\n 'defaultStructuredLLM',\n (m) => m.type === 'LLM' && m.structuredOutput,\n 'a structured-output LLM'\n )\n }\n\n getLLM() {\n if (!this.defaultLLM) {\n throw new Error('No LLM available.')\n }\n return this.defaultLLM\n }\n\n getEmbedding() {\n if (!this.defaultEmbedding) {\n throw new Error('No embedding model available.')\n }\n return this.defaultEmbedding\n }\n\n getStructuredLLM() {\n if (!this.defaultStructuredLLM) {\n throw new Error('No structured-output LLM available.')\n }\n return this.defaultStructuredLLM\n }\n}\n", "import { getStoreCapability as getStoreCapabilityDefault } from './store'\nimport { getLLMCapability } from './llm'\nimport { LocalModels } from './models'\n\n// Check if we're in a browser on HTTPS (can't connect to local HTTP endpoints)\nconst isBrowser = typeof window !== 'undefined'\nconst isHttps = isBrowser && window.location.protocol === 'https:'\n\n// Lazy initialization - don't audit on import\nlet localModels: LocalModels | null = null\nlet llm: ReturnType<typeof getLLMCapability> | null = null\nlet initializationAttempted = false\n\nasync function ensureInitialized() {\n if (initializationAttempted) {\n return { localModels, llm }\n }\n initializationAttempted = true\n\n // Skip local LLM initialization on HTTPS (mixed content would block it anyway)\n if (isHttps) {\n console.log(\n '\uD83D\uDCE1 HTTPS detected - local LLM endpoints disabled. Use HTTP for local LLM support.'\n )\n return { localModels: null, llm: null }\n }\n\n try {\n localModels = new LocalModels()\n await localModels.audit()\n llm = getLLMCapability(localModels)\n } catch (e) {\n console.warn('\u26A0\uFE0F Could not connect to local LLM:', e)\n }\n return { localModels, llm }\n}\n\nexport async function getBatteries() {\n const { localModels, llm } = await ensureInitialized()\n return {\n vector: llm ? { embed: llm.embed } : undefined,\n store: getStoreCapabilityDefault(),\n llmBattery: llm,\n models: localModels,\n }\n}\n\nexport async function getStandardCapabilities() {\n return getBatteries()\n}\n\n// For non-async access (after initialization)\nexport { LocalModels, getLLMCapability, getStoreCapabilityDefault }\n\n// Synchronous batteries object for tests and simple use cases\nexport const batteries = {\n store: getStoreCapabilityDefault(),\n llmBattery: null as ReturnType<typeof getLLMCapability> | null,\n vector: undefined as\n | { embed: (text: string) => Promise<number[]> }\n | undefined,\n models: null as LocalModels | null,\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["kvStore", "collections", "cosineSimilarity", "vecA", "vecB", "dotProduct", "magA", "magB", "i", "getStoreCapability", "key", "val", "name", "_schema", "_dimension", "collection", "doc", "db", "vector", "k", "scoredDocs", "a", "b", "item", "buildUserMessage", "user", "content", "img", "DEFAULT_BASE_URL", "getLLMCapability", "models", "baseUrl", "system", "tools", "responseFormat", "model", "messages", "response", "e", "text", "CACHE_FILE", "isBrowser", "readCache", "baseUrl", "cached", "CACHE_FILE", "data", "fs", "cacheFile", "content", "e", "writeCache", "models", "fetchWithTimeout", "url", "options", "controller", "id", "res", "error", "checkStructured", "modelId", "schemaPayload", "checkStructuredLegacy", "checkLLM", "checkEmbedding", "TINY_TEST_IMAGE", "checkVision", "auditModels", "cachedData", "serverModelIds", "m", "cachedModelIds", "results", "modelList", "readline", "model", "type", "structured", "vision", "statusMsg", "dimension", "isLLM", "dim", "structRes", "DEFAULT_BASE_URL", "LocalModels", "baseUrl", "auditModels", "m", "modelId", "property", "predicate", "errorType", "model", "isBrowser", "isHttps", "localModels", "llm", "initializationAttempted", "ensureInitialized", "LocalModels", "getLLMCapability", "getBatteries", "getStoreCapability", "getStandardCapabilities", "batteries", "getStoreCapability"]
7
7
  }