@adminiumjs/llm 0.1.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/LICENSE +661 -0
  2. package/dist/apply/diff.d.ts +79 -0
  3. package/dist/apply/diff.d.ts.map +1 -0
  4. package/dist/apply/diff.js +459 -0
  5. package/dist/apply/diff.js.map +1 -0
  6. package/dist/apply/index.d.ts +6 -0
  7. package/dist/apply/index.d.ts.map +1 -0
  8. package/dist/apply/index.js +6 -0
  9. package/dist/apply/index.js.map +1 -0
  10. package/dist/apply/normalize.d.ts +55 -0
  11. package/dist/apply/normalize.d.ts.map +1 -0
  12. package/dist/apply/normalize.js +232 -0
  13. package/dist/apply/normalize.js.map +1 -0
  14. package/dist/apply/plan.d.ts +206 -0
  15. package/dist/apply/plan.d.ts.map +1 -0
  16. package/dist/apply/plan.js +422 -0
  17. package/dist/apply/plan.js.map +1 -0
  18. package/dist/apply/suggestion-id.d.ts +103 -0
  19. package/dist/apply/suggestion-id.d.ts.map +1 -0
  20. package/dist/apply/suggestion-id.js +121 -0
  21. package/dist/apply/suggestion-id.js.map +1 -0
  22. package/dist/crypto.d.ts +48 -0
  23. package/dist/crypto.d.ts.map +1 -0
  24. package/dist/crypto.js +35 -0
  25. package/dist/crypto.js.map +1 -0
  26. package/dist/index.d.ts +17 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +22 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/prompt/builder.d.ts +27 -0
  31. package/dist/prompt/builder.d.ts.map +1 -0
  32. package/dist/prompt/builder.js +263 -0
  33. package/dist/prompt/builder.js.map +1 -0
  34. package/dist/prompt/chunker.d.ts +89 -0
  35. package/dist/prompt/chunker.d.ts.map +1 -0
  36. package/dist/prompt/chunker.js +383 -0
  37. package/dist/prompt/chunker.js.map +1 -0
  38. package/dist/prompt/index.d.ts +14 -0
  39. package/dist/prompt/index.d.ts.map +1 -0
  40. package/dist/prompt/index.js +14 -0
  41. package/dist/prompt/index.js.map +1 -0
  42. package/dist/prompt/serializer.d.ts +138 -0
  43. package/dist/prompt/serializer.d.ts.map +1 -0
  44. package/dist/prompt/serializer.js +178 -0
  45. package/dist/prompt/serializer.js.map +1 -0
  46. package/dist/prompt/templates/v1.d.ts +41 -0
  47. package/dist/prompt/templates/v1.d.ts.map +1 -0
  48. package/dist/prompt/templates/v1.js +312 -0
  49. package/dist/prompt/templates/v1.js.map +1 -0
  50. package/dist/prompt/token-estimate.d.ts +16 -0
  51. package/dist/prompt/token-estimate.d.ts.map +1 -0
  52. package/dist/prompt/token-estimate.js +20 -0
  53. package/dist/prompt/token-estimate.js.map +1 -0
  54. package/dist/prompt/types.d.ts +134 -0
  55. package/dist/prompt/types.d.ts.map +1 -0
  56. package/dist/prompt/types.js +44 -0
  57. package/dist/prompt/types.js.map +1 -0
  58. package/dist/providers/anthropic.d.ts +3 -0
  59. package/dist/providers/anthropic.d.ts.map +1 -0
  60. package/dist/providers/anthropic.js +65 -0
  61. package/dist/providers/anthropic.js.map +1 -0
  62. package/dist/providers/factory.d.ts +3 -0
  63. package/dist/providers/factory.d.ts.map +1 -0
  64. package/dist/providers/factory.js +37 -0
  65. package/dist/providers/factory.js.map +1 -0
  66. package/dist/providers/http.d.ts +56 -0
  67. package/dist/providers/http.d.ts.map +1 -0
  68. package/dist/providers/http.js +148 -0
  69. package/dist/providers/http.js.map +1 -0
  70. package/dist/providers/index.d.ts +15 -0
  71. package/dist/providers/index.d.ts.map +1 -0
  72. package/dist/providers/index.js +15 -0
  73. package/dist/providers/index.js.map +1 -0
  74. package/dist/providers/model-catalog.d.ts +21 -0
  75. package/dist/providers/model-catalog.d.ts.map +1 -0
  76. package/dist/providers/model-catalog.js +121 -0
  77. package/dist/providers/model-catalog.js.map +1 -0
  78. package/dist/providers/ollama.d.ts +3 -0
  79. package/dist/providers/ollama.d.ts.map +1 -0
  80. package/dist/providers/ollama.js +55 -0
  81. package/dist/providers/ollama.js.map +1 -0
  82. package/dist/providers/openai-compatible.d.ts +3 -0
  83. package/dist/providers/openai-compatible.d.ts.map +1 -0
  84. package/dist/providers/openai-compatible.js +50 -0
  85. package/dist/providers/openai-compatible.js.map +1 -0
  86. package/dist/providers/openai.d.ts +18 -0
  87. package/dist/providers/openai.d.ts.map +1 -0
  88. package/dist/providers/openai.js +68 -0
  89. package/dist/providers/openai.js.map +1 -0
  90. package/dist/providers/types.d.ts +112 -0
  91. package/dist/providers/types.d.ts.map +1 -0
  92. package/dist/providers/types.js +55 -0
  93. package/dist/providers/types.js.map +1 -0
  94. package/dist/response/errors.d.ts +60 -0
  95. package/dist/response/errors.d.ts.map +1 -0
  96. package/dist/response/errors.js +101 -0
  97. package/dist/response/errors.js.map +1 -0
  98. package/dist/response/extract.d.ts +38 -0
  99. package/dist/response/extract.d.ts.map +1 -0
  100. package/dist/response/extract.js +77 -0
  101. package/dist/response/extract.js.map +1 -0
  102. package/dist/response/index.d.ts +8 -0
  103. package/dist/response/index.d.ts.map +1 -0
  104. package/dist/response/index.js +8 -0
  105. package/dist/response/index.js.map +1 -0
  106. package/dist/response/merge.d.ts +53 -0
  107. package/dist/response/merge.d.ts.map +1 -0
  108. package/dist/response/merge.js +348 -0
  109. package/dist/response/merge.js.map +1 -0
  110. package/dist/response/referential.d.ts +113 -0
  111. package/dist/response/referential.d.ts.map +1 -0
  112. package/dist/response/referential.js +556 -0
  113. package/dist/response/referential.js.map +1 -0
  114. package/dist/response/schema.d.ts +506 -0
  115. package/dist/response/schema.d.ts.map +1 -0
  116. package/dist/response/schema.js +191 -0
  117. package/dist/response/schema.js.map +1 -0
  118. package/dist/response/validate.d.ts +29 -0
  119. package/dist/response/validate.d.ts.map +1 -0
  120. package/dist/response/validate.js +167 -0
  121. package/dist/response/validate.js.map +1 -0
  122. package/dist/types.d.ts +95 -0
  123. package/dist/types.d.ts.map +1 -0
  124. package/dist/types.js +49 -0
  125. package/dist/types.js.map +1 -0
  126. package/package.json +30 -0
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The `chars / 3.6` heuristic token estimator (06-llm-assist.md §2, §4.5).
3
+ *
4
+ * Deliberately provider-agnostic and conservative: it slightly over-counts for
5
+ * typical English + JSON so a prompt that "fits" the budget fits every supported
6
+ * provider's real tokenizer with headroom. Pure and deterministic — no model
7
+ * download, no network, no `Date.now`/`Math.random`.
8
+ */
9
+ /** Characters-per-token divisor (§4.5: `tokens ≈ ceil(chars / 3.6)`). */
10
+ export const CHARS_PER_TOKEN = 3.6;
11
+ /**
12
+ * Estimate the input-token count of `text` as `ceil(text.length / 3.6)`.
13
+ * Empty input is 0 tokens.
14
+ */
15
+ export function estimateTokens(text) {
16
+ if (text.length === 0)
17
+ return 0;
18
+ return Math.ceil(text.length / CHARS_PER_TOKEN);
19
+ }
20
+ //# sourceMappingURL=token-estimate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-estimate.js","sourceRoot":"","sources":["../../src/prompt/token-estimate.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,yEAAyE;AACzE,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC;AAEnC;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAChC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,eAAe,CAAC,CAAC;AAClD,CAAC"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Prompt-builder contract types (06-llm-assist.md §4.1, §4.4, §2).
3
+ *
4
+ * These are additive to T01's `response/schema.ts` + top-level `types.ts`: they
5
+ * name the builder's INPUT (`PromptInput`), the requested-section vocabulary
6
+ * (§4.4), the injected allow-lists, and the builder's OUTPUT (`PromptArtifact`).
7
+ * `PromptInput.schemaIr` is the engine IR (`DatabaseModel`) and `stats` is the
8
+ * engine's `StatsResult[]` (the shape every adapter's `collectTableStats`
9
+ * returns) — the doc's aspirational `SchemaIr` / `TableStats[]` names map onto
10
+ * these landed types.
11
+ *
12
+ * Browser-safe: type-only engine imports (erased at build), no runtime edge.
13
+ */
14
+ import type { DatabaseModel, StatsResult } from '@adminium/engine';
15
+ import type { LocaleCode } from '../response/schema.js';
16
+ /**
17
+ * The ten decision groups the prompt asks for, mapped 1:1 to response keys
18
+ * (§4.4). The wizard lets the user deselect groups (all on by default); a
19
+ * deselected section's numbered decision block is removed from the rendered
20
+ * user text and its key becomes optional-and-ignored downstream.
21
+ */
22
+ export declare const REQUESTED_SECTIONS: readonly ["labels", "groups", "enums", "relations", "keys", "templates", "widgets", "pii", "icons", "microcopy"];
23
+ export type RequestedSection = (typeof REQUESTED_SECTIONS)[number];
24
+ /** All ten sections, in canonical order — the default when the user deselects nothing. */
25
+ export declare const ALL_SECTIONS: readonly RequestedSection[];
26
+ /**
27
+ * Section → the 1-based number of its decision block in {@link PROMPT_V1_USER}
28
+ * (§5.2). The builder keeps the original numbering (never renumbers) so the
29
+ * cross-references inside the template — "for decision 6", "Skip decisions 2 and
30
+ * 7" — stay valid even when blocks are dropped; deselected blocks simply leave a
31
+ * gap in the sequence.
32
+ */
33
+ export declare const SECTION_DECISION_NUMBER: Readonly<Record<RequestedSection, number>>;
34
+ /**
35
+ * The closed vocabularies bounding what the model may suggest, injected as
36
+ * `{{ALLOWED_PAGE_TEMPLATE_IDS_JSON}}` / `{{ALLOWED_WIDGET_IDS_JSON}}`. In
37
+ * production these are `LLM_ALLOWED_TEMPLATES` / `LLM_ALLOWED_WIDGETS` from
38
+ * `@adminium/widgets` (derived from the live registries so prompt and runtime
39
+ * cannot drift — 06 §5). They are INJECTED rather than imported here to keep
40
+ * `@adminium/llm` browser-safe and dependency-minimal: the allow-lists live in
41
+ * the widgets *main* barrel, which pulls the React render layer, whereas this
42
+ * package must import only pure-Zod/pure-TS types (mirrors the engine rule that
43
+ * only the `@adminium/widgets/page-config` leaf may be imported). The server /
44
+ * dashboard callers, which already depend on `@adminium/widgets`, pass them in.
45
+ */
46
+ export interface AllowedVocabularies {
47
+ /** `LLM_ALLOWED_TEMPLATES` — recommendable page-template ids. */
48
+ templates: readonly string[];
49
+ /** `LLM_ALLOWED_WIDGETS` — the curated dashboard-widget subset. */
50
+ widgets: readonly string[];
51
+ }
52
+ /**
53
+ * Sampling opt-in. `null` (default) ⇒ SAMPLE-FREE: no cell value from any table
54
+ * appears anywhere in the prompt (§1 invariant 5, acceptance criterion 8). When
55
+ * set, the sampling block adds up to `maxValuesPerColumn` most-common values +
56
+ * ordered min/max — but NEVER for PII-suspected or secret columns.
57
+ */
58
+ export type Sampling = null | {
59
+ maxValuesPerColumn: number;
60
+ };
61
+ /**
62
+ * One (possibly chunked) prompt's worth of input. `schemaIr` is the
63
+ * post-inclusion IR (only included tables; PII-masked columns still listed as
64
+ * structure, flagged so the model can confirm/deny — §4.1).
65
+ */
66
+ export interface PromptInput {
67
+ /** `adminium_schema_snapshots.id` this prompt was built from (recorded, not injected). */
68
+ snapshotId: string;
69
+ /** The classified schema IR (05-introspection-engine.md). */
70
+ schemaIr: DatabaseModel;
71
+ /** Aggregate statistics, one per table (engine `collectTableStats` output). */
72
+ stats: readonly StatsResult[];
73
+ /** Subset of the 8 canonical locales; MUST include `en_US` (§4.1). */
74
+ locales: readonly LocaleCode[];
75
+ /** Which decision groups to request (§4.4). Empty ⇒ treated as all sections. */
76
+ sections: readonly RequestedSection[];
77
+ /** `null` = sample-free (default). */
78
+ sampling: Sampling;
79
+ /** ULID; echoed (optionally) by the response. */
80
+ runId: string;
81
+ /** Present only for a chunked run (§4.5); the chunker (T04) fills it. */
82
+ chunk?: PromptChunkInfo;
83
+ }
84
+ /** Chunk placement for a map-phase prompt (§4.5). `index` is 1-based for display. */
85
+ export interface PromptChunkInfo {
86
+ index: number;
87
+ total: number;
88
+ /** Qualified ids of out-of-chunk FK targets rendered as `"stub": true` context. */
89
+ stubTables: readonly string[];
90
+ }
91
+ /** Provider-agnostic input-token budget per prompt (§4.5). */
92
+ export declare const DEFAULT_TOKEN_BUDGET = 60000;
93
+ export interface BuildPromptOptions {
94
+ /** The closed vocabularies bounding suggestions (see {@link AllowedVocabularies}). */
95
+ allowed: AllowedVocabularies;
96
+ /** Input-token budget for the assembled user section (§4.5). Default {@link DEFAULT_TOKEN_BUDGET}. */
97
+ tokenBudget?: number;
98
+ }
99
+ /**
100
+ * One map-phase prompt. For an unchunked run the artifact carries exactly one
101
+ * chunk (`index: 1, total: 1`). The chunker (T04) produces the multi-chunk case;
102
+ * this shape is what it packs.
103
+ */
104
+ export interface PromptChunk {
105
+ /** 1-based position; `1` and `total: 1` for an unchunked run. */
106
+ index: number;
107
+ total: number;
108
+ /** The system section sent for this chunk (identical across chunks). */
109
+ system: string;
110
+ /** The rendered user section for this chunk. */
111
+ user: string;
112
+ /** BYO flattening: `=== SYSTEM ===\n…\n\n=== USER ===\n…` (byte-identical between markers). */
113
+ byo: string;
114
+ /** `ceil(chars / 3.6)` over the flattened document (§4.5). */
115
+ tokenEstimate: number;
116
+ }
117
+ /**
118
+ * `buildPrompt(input, opts)` output. `system`/`user` are the direct-path
119
+ * messages; `byo` is their flattened copyable document; `chunks` holds the
120
+ * map-phase prompts (one entry when unchunked). `tokenEstimate` is over `byo`
121
+ * (what BYO shows under the copy button).
122
+ */
123
+ export interface PromptArtifact {
124
+ system: string;
125
+ user: string;
126
+ byo: string;
127
+ chunks: PromptChunk[];
128
+ tokenEstimate: number;
129
+ /** Whether the assembled user section exceeds `opts.tokenBudget` (chunking hint for T04). */
130
+ overBudget: boolean;
131
+ /** The active sections after normalizing `input.sections` (empty ⇒ all). */
132
+ sections: readonly RequestedSection[];
133
+ }
134
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/prompt/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAIxD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,kHAWrB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnE,0FAA0F;AAC1F,eAAO,MAAM,YAAY,EAAE,SAAS,gBAAgB,EAAuB,CAAC;AAE5E;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAW9E,CAAC;AAIF;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,mBAAmB;IAClC,iEAAiE;IACjE,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,mEAAmE;IACnE,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B;AAID;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG;IAAE,kBAAkB,EAAE,MAAM,CAAA;CAAE,CAAC;AAI7D;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,0FAA0F;IAC1F,UAAU,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,QAAQ,EAAE,aAAa,CAAC;IACxB,+EAA+E;IAC/E,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IAC9B,sEAAsE;IACtE,OAAO,EAAE,SAAS,UAAU,EAAE,CAAC;IAC/B,gFAAgF;IAChF,QAAQ,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACtC,sCAAsC;IACtC,QAAQ,EAAE,QAAQ,CAAC;IACnB,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,KAAK,CAAC,EAAE,eAAe,CAAC;CACzB;AAED,qFAAqF;AACrF,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,mFAAmF;IACnF,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CAC/B;AAID,8DAA8D;AAC9D,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAE3C,MAAM,WAAW,kBAAkB;IACjC,sFAAsF;IACtF,OAAO,EAAE,mBAAmB,CAAC;IAC7B,sGAAsG;IACtG,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAID;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,+FAA+F;IAC/F,GAAG,EAAE,MAAM,CAAC;IACZ,8DAA8D;IAC9D,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,6FAA6F;IAC7F,UAAU,EAAE,OAAO,CAAC;IACpB,4EAA4E;IAC5E,QAAQ,EAAE,SAAS,gBAAgB,EAAE,CAAC;CACvC"}
@@ -0,0 +1,44 @@
1
+ // ─── Requested sections (§4.4) ───────────────────────────────────────────────
2
+ /**
3
+ * The ten decision groups the prompt asks for, mapped 1:1 to response keys
4
+ * (§4.4). The wizard lets the user deselect groups (all on by default); a
5
+ * deselected section's numbered decision block is removed from the rendered
6
+ * user text and its key becomes optional-and-ignored downstream.
7
+ */
8
+ export const REQUESTED_SECTIONS = [
9
+ 'labels',
10
+ 'groups',
11
+ 'enums',
12
+ 'relations',
13
+ 'keys',
14
+ 'templates',
15
+ 'widgets',
16
+ 'pii',
17
+ 'icons',
18
+ 'microcopy',
19
+ ];
20
+ /** All ten sections, in canonical order — the default when the user deselects nothing. */
21
+ export const ALL_SECTIONS = REQUESTED_SECTIONS;
22
+ /**
23
+ * Section → the 1-based number of its decision block in {@link PROMPT_V1_USER}
24
+ * (§5.2). The builder keeps the original numbering (never renumbers) so the
25
+ * cross-references inside the template — "for decision 6", "Skip decisions 2 and
26
+ * 7" — stay valid even when blocks are dropped; deselected blocks simply leave a
27
+ * gap in the sequence.
28
+ */
29
+ export const SECTION_DECISION_NUMBER = {
30
+ labels: 1,
31
+ groups: 2,
32
+ enums: 3,
33
+ relations: 4,
34
+ keys: 5,
35
+ templates: 6,
36
+ widgets: 7,
37
+ pii: 8,
38
+ icons: 9,
39
+ microcopy: 10,
40
+ };
41
+ // ─── Builder options ─────────────────────────────────────────────────────────
42
+ /** Provider-agnostic input-token budget per prompt (§4.5). */
43
+ export const DEFAULT_TOKEN_BUDGET = 60_000;
44
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/prompt/types.ts"],"names":[],"mappings":"AAiBA,gFAAgF;AAEhF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,WAAW;IACX,MAAM;IACN,WAAW;IACX,SAAS;IACT,KAAK;IACL,OAAO;IACP,WAAW;CACH,CAAC;AAIX,0FAA0F;AAC1F,MAAM,CAAC,MAAM,YAAY,GAAgC,kBAAkB,CAAC;AAE5E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAA+C;IACjF,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,CAAC;IACT,KAAK,EAAE,CAAC;IACR,SAAS,EAAE,CAAC;IACZ,IAAI,EAAE,CAAC;IACP,SAAS,EAAE,CAAC;IACZ,OAAO,EAAE,CAAC;IACV,GAAG,EAAE,CAAC;IACN,KAAK,EAAE,CAAC;IACR,SAAS,EAAE,EAAE;CACd,CAAC;AAmEF,gFAAgF;AAEhF,8DAA8D;AAC9D,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type ProviderClient, type ProviderConfig } from './types.js';
2
+ export declare function createAnthropicClient(config: ProviderConfig): ProviderClient;
3
+ //# sourceMappingURL=anthropic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"AAOA,OAAO,EAML,KAAK,cAAc,EACnB,KAAK,cAAc,EACpB,MAAM,YAAY,CAAC;AAUpB,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,cAAc,GAAG,cAAc,CA4D5E"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Anthropic Messages API client (06-llm-assist.md §3.1). Auth: `x-api-key` +
3
+ * `anthropic-version`; POST `/v1/messages` in the Messages wire format. Fetch
4
+ * only, no SDK. Enrichment temperature is fixed at 0 (asserted).
5
+ */
6
+ import { pingComplete, requestJson, toCompleteResult } from './http.js';
7
+ import { listAnthropicModels } from './model-catalog.js';
8
+ import { assertEnrichmentTemperature, ProviderError, requireApiKey, requireModel, stripTrailingSlash, } from './types.js';
9
+ const ANTHROPIC_VERSION = '2023-06-01';
10
+ const DEFAULT_BASE_URL = 'https://api.anthropic.com';
11
+ export function createAnthropicClient(config) {
12
+ const apiKey = requireApiKey(config, 'anthropic');
13
+ const baseUrl = config.baseUrl ? stripTrailingSlash(config.baseUrl) : DEFAULT_BASE_URL;
14
+ const timeoutMs = config.timeoutMs;
15
+ const headers = () => ({
16
+ 'content-type': 'application/json',
17
+ 'x-api-key': apiKey,
18
+ 'anthropic-version': ANTHROPIC_VERSION,
19
+ });
20
+ const client = {
21
+ id: 'anthropic',
22
+ async listModels() {
23
+ return listAnthropicModels({
24
+ apiKey,
25
+ baseUrl,
26
+ ...(timeoutMs !== undefined ? { timeoutMs } : {}),
27
+ });
28
+ },
29
+ async complete(req) {
30
+ assertEnrichmentTemperature(req.temperature, 'anthropic');
31
+ const json = await requestJson({
32
+ provider: 'anthropic',
33
+ method: 'POST',
34
+ url: `${baseUrl}/v1/messages`,
35
+ headers: headers(),
36
+ apiKey,
37
+ ...(timeoutMs !== undefined ? { timeoutMs } : {}),
38
+ body: {
39
+ model: req.model,
40
+ max_tokens: req.maxTokens,
41
+ temperature: req.temperature,
42
+ system: req.system,
43
+ messages: req.messages.map((m) => ({ role: m.role, content: m.content })),
44
+ },
45
+ });
46
+ const text = (json.content ?? [])
47
+ .filter((block) => block.type === 'text' && typeof block.text === 'string')
48
+ .map((block) => block.text ?? '')
49
+ .join('');
50
+ if (text.length === 0) {
51
+ throw new ProviderError({
52
+ provider: 'anthropic',
53
+ code: 'bad_response',
54
+ message: 'anthropic: response contained no text content',
55
+ });
56
+ }
57
+ return toCompleteResult(text, json.usage?.input_tokens, json.usage?.output_tokens);
58
+ },
59
+ async test() {
60
+ return pingComplete(client, requireModel(config, 'anthropic'));
61
+ },
62
+ };
63
+ return client;
64
+ }
65
+ //# sourceMappingURL=anthropic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type ProviderClient, type ProviderConfig } from './types.js';
2
+ export declare function createProviderClient(config: ProviderConfig): ProviderClient;
3
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/providers/factory.ts"],"names":[],"mappings":"AASA,OAAO,EAAiB,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAErF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,cAAc,CAyB3E"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Dispatches a `ProviderConfig` to the matching client constructor (§3.1).
3
+ * `adminium-managed` is intentionally unsupported here — that Cloud-relay client
4
+ * ships in M12, not this wave — and requesting it is a `config` error.
5
+ */
6
+ import { createAnthropicClient } from './anthropic.js';
7
+ import { createOllamaClient } from './ollama.js';
8
+ import { createOpenAiCompatibleClient } from './openai-compatible.js';
9
+ import { createOpenAiClient } from './openai.js';
10
+ import { ProviderError } from './types.js';
11
+ export function createProviderClient(config) {
12
+ switch (config.provider) {
13
+ case 'anthropic':
14
+ return createAnthropicClient(config);
15
+ case 'openai':
16
+ return createOpenAiClient(config);
17
+ case 'openai-compatible':
18
+ return createOpenAiCompatibleClient(config);
19
+ case 'ollama':
20
+ return createOllamaClient(config);
21
+ case 'adminium-managed':
22
+ throw new ProviderError({
23
+ provider: 'adminium-managed',
24
+ code: 'config',
25
+ message: 'the adminium-managed provider is not available in this build (M12)',
26
+ });
27
+ default: {
28
+ const exhaustive = config.provider;
29
+ throw new ProviderError({
30
+ provider: 'anthropic',
31
+ code: 'config',
32
+ message: `unknown provider: ${String(exhaustive)}`,
33
+ });
34
+ }
35
+ }
36
+ }
37
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/providers/factory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,aAAa,EAA4C,MAAM,YAAY,CAAC;AAErF,MAAM,UAAU,oBAAoB,CAAC,MAAsB;IACzD,QAAQ,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxB,KAAK,WAAW;YACd,OAAO,qBAAqB,CAAC,MAAM,CAAC,CAAC;QACvC,KAAK,QAAQ;YACX,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACpC,KAAK,mBAAmB;YACtB,OAAO,4BAA4B,CAAC,MAAM,CAAC,CAAC;QAC9C,KAAK,QAAQ;YACX,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACpC,KAAK,kBAAkB;YACrB,MAAM,IAAI,aAAa,CAAC;gBACtB,QAAQ,EAAE,kBAAkB;gBAC5B,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,oEAAoE;aAC9E,CAAC,CAAC;QACL,OAAO,CAAC,CAAC,CAAC;YACR,MAAM,UAAU,GAAU,MAAM,CAAC,QAAQ,CAAC;YAC1C,MAAM,IAAI,aAAa,CAAC;gBACtB,QAAQ,EAAE,WAAW;gBACrB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,qBAAqB,MAAM,CAAC,UAAU,CAAC,EAAE;aACnD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Shared fetch plumbing for the provider clients (06-llm-assist.md §3): one
3
+ * JSON request helper with a timeout, deterministic error mapping to
4
+ * `ProviderError`, and — the security-critical part (acceptance §10) — a secret
5
+ * scrubber that guarantees the API key never survives into a thrown/logged
6
+ * surface. Global `fetch` only; no SDKs, browser-safe.
7
+ */
8
+ import { type CompleteResult, type ProviderClient, type ProviderId } from './types.js';
9
+ /**
10
+ * Removes every occurrence of `secret` from `text`. Applied to any
11
+ * provider-supplied error body before it is placed in a `ProviderError.message`,
12
+ * so an echoed Authorization header or key fragment can never leak. A no-op when
13
+ * there is no secret to protect.
14
+ */
15
+ export declare function scrubSecret(text: string, secret: string | undefined): string;
16
+ /**
17
+ * Return an error safe to attach as a `ProviderError.cause` (acceptance §10): the
18
+ * key must not survive into ANY logged/inspected surface, and consumers walk the
19
+ * `[cause]` chain (`console.error`, `util.inspect`, pino/winston serializers).
20
+ * The original error's `message` — and its `stack`, which embeds the message —
21
+ * can echo an outgoing Authorization header, so when the secret appears anywhere
22
+ * in it we replace it with a fresh scrubbed `Error` (no key in message or stack).
23
+ * When there is no secret, or it does not appear, the original error is returned
24
+ * unchanged so genuine network diagnostics (DNS, ECONNREFUSED) are preserved.
25
+ */
26
+ export declare function scrubCause(err: unknown, secret: string | undefined): unknown;
27
+ export interface RequestJsonOptions {
28
+ provider: ProviderId;
29
+ url: string;
30
+ method?: 'GET' | 'POST';
31
+ headers?: Record<string, string>;
32
+ body?: unknown;
33
+ /** The secret to scrub from any error text (never sent anywhere else). */
34
+ apiKey?: string;
35
+ /** Abort after this many ms; defaults to `DEFAULT_TIMEOUT_MS`. */
36
+ timeoutMs?: number;
37
+ }
38
+ /**
39
+ * Performs a JSON request and parses the response, or throws a `ProviderError`.
40
+ * Non-2xx → status-mapped error (body scrubbed + snippeted); fetch rejection →
41
+ * `network`; our own abort → `timeout`; unparseable 2xx body → `bad_response`.
42
+ */
43
+ export declare function requestJson<T>(opts: RequestJsonOptions): Promise<T>;
44
+ /**
45
+ * Shared `ProviderClient.test()` implementation: a 1-token, temperature-0 ping
46
+ * through the client's own `complete()`, timing the round-trip. `performance.now`
47
+ * is intentionally not a determinism hazard — latency never feeds a prompt or diff.
48
+ */
49
+ export declare function pingComplete(client: ProviderClient, model: string): Promise<{
50
+ ok: true;
51
+ model: string;
52
+ latencyMs: number;
53
+ }>;
54
+ /** Builds a `CompleteResult`, attaching `usage` only when both token counts are known. */
55
+ export declare function toCompleteResult(text: string, inputTokens: number | undefined, outputTokens: number | undefined): CompleteResult;
56
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/providers/http.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,cAAc,EAEnB,KAAK,UAAU,EAChB,MAAM,YAAY,CAAC;AAEpB;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAG5E;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAQ5E;AAUD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,UAAU,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,CAAC,CAAC,CAyDzE;AAUD;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAUzD;AAED,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,YAAY,EAAE,MAAM,GAAG,SAAS,GAC/B,cAAc,CAMhB"}
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Shared fetch plumbing for the provider clients (06-llm-assist.md §3): one
3
+ * JSON request helper with a timeout, deterministic error mapping to
4
+ * `ProviderError`, and — the security-critical part (acceptance §10) — a secret
5
+ * scrubber that guarantees the API key never survives into a thrown/logged
6
+ * surface. Global `fetch` only; no SDKs, browser-safe.
7
+ */
8
+ import { DEFAULT_TIMEOUT_MS, ProviderError, } from './types.js';
9
+ /**
10
+ * Removes every occurrence of `secret` from `text`. Applied to any
11
+ * provider-supplied error body before it is placed in a `ProviderError.message`,
12
+ * so an echoed Authorization header or key fragment can never leak. A no-op when
13
+ * there is no secret to protect.
14
+ */
15
+ export function scrubSecret(text, secret) {
16
+ if (secret === undefined || secret.length === 0)
17
+ return text;
18
+ return text.split(secret).join('[REDACTED]');
19
+ }
20
+ /**
21
+ * Return an error safe to attach as a `ProviderError.cause` (acceptance §10): the
22
+ * key must not survive into ANY logged/inspected surface, and consumers walk the
23
+ * `[cause]` chain (`console.error`, `util.inspect`, pino/winston serializers).
24
+ * The original error's `message` — and its `stack`, which embeds the message —
25
+ * can echo an outgoing Authorization header, so when the secret appears anywhere
26
+ * in it we replace it with a fresh scrubbed `Error` (no key in message or stack).
27
+ * When there is no secret, or it does not appear, the original error is returned
28
+ * unchanged so genuine network diagnostics (DNS, ECONNREFUSED) are preserved.
29
+ */
30
+ export function scrubCause(err, secret) {
31
+ if (secret === undefined || secret.length === 0)
32
+ return err;
33
+ const message = err instanceof Error ? err.message : String(err);
34
+ const stack = err instanceof Error ? (err.stack ?? '') : '';
35
+ if (!message.includes(secret) && !stack.includes(secret))
36
+ return err;
37
+ const scrubbed = new Error(scrubSecret(message, secret));
38
+ if (err instanceof Error)
39
+ scrubbed.name = err.name;
40
+ return scrubbed;
41
+ }
42
+ function codeForStatus(status) {
43
+ if (status === 401 || status === 403)
44
+ return 'auth';
45
+ if (status === 404)
46
+ return 'not_found';
47
+ if (status === 429)
48
+ return 'rate_limit';
49
+ if (status >= 500)
50
+ return 'server';
51
+ return 'http';
52
+ }
53
+ /**
54
+ * Performs a JSON request and parses the response, or throws a `ProviderError`.
55
+ * Non-2xx → status-mapped error (body scrubbed + snippeted); fetch rejection →
56
+ * `network`; our own abort → `timeout`; unparseable 2xx body → `bad_response`.
57
+ */
58
+ export async function requestJson(opts) {
59
+ const { provider, url, method = 'GET', headers, body, apiKey } = opts;
60
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
61
+ const controller = new AbortController();
62
+ const timer = setTimeout(() => {
63
+ controller.abort();
64
+ }, timeoutMs);
65
+ const init = { method, signal: controller.signal };
66
+ if (headers !== undefined)
67
+ init.headers = headers;
68
+ if (body !== undefined)
69
+ init.body = JSON.stringify(body);
70
+ let res;
71
+ try {
72
+ res = await fetch(url, init);
73
+ }
74
+ catch (err) {
75
+ if (controller.signal.aborted) {
76
+ throw new ProviderError({
77
+ provider,
78
+ code: 'timeout',
79
+ message: `${provider}: request timed out after ${String(timeoutMs)}ms`,
80
+ });
81
+ }
82
+ const detail = err instanceof Error ? err.message : String(err);
83
+ throw new ProviderError({
84
+ provider,
85
+ code: 'network',
86
+ message: `${provider}: network request failed (${scrubSecret(detail, apiKey)})`,
87
+ cause: scrubCause(err, apiKey),
88
+ });
89
+ }
90
+ finally {
91
+ clearTimeout(timer);
92
+ }
93
+ if (!res.ok) {
94
+ const raw = await safeText(res);
95
+ const snippet = scrubSecret(raw, apiKey).slice(0, 500);
96
+ throw new ProviderError({
97
+ provider,
98
+ code: codeForStatus(res.status),
99
+ status: res.status,
100
+ message: `${provider}: HTTP ${String(res.status)}${snippet ? ` — ${snippet}` : ''}`,
101
+ });
102
+ }
103
+ try {
104
+ return (await res.json());
105
+ }
106
+ catch (err) {
107
+ throw new ProviderError({
108
+ provider,
109
+ code: 'bad_response',
110
+ status: res.status,
111
+ message: `${provider}: response body was not valid JSON`,
112
+ cause: scrubCause(err, apiKey),
113
+ });
114
+ }
115
+ }
116
+ async function safeText(res) {
117
+ try {
118
+ return await res.text();
119
+ }
120
+ catch {
121
+ return '';
122
+ }
123
+ }
124
+ /**
125
+ * Shared `ProviderClient.test()` implementation: a 1-token, temperature-0 ping
126
+ * through the client's own `complete()`, timing the round-trip. `performance.now`
127
+ * is intentionally not a determinism hazard — latency never feeds a prompt or diff.
128
+ */
129
+ export async function pingComplete(client, model) {
130
+ const start = performance.now();
131
+ await client.complete({
132
+ system: '',
133
+ messages: [{ role: 'user', content: 'ping' }],
134
+ model,
135
+ maxTokens: 1,
136
+ temperature: 0,
137
+ });
138
+ return { ok: true, model, latencyMs: Math.round(performance.now() - start) };
139
+ }
140
+ /** Builds a `CompleteResult`, attaching `usage` only when both token counts are known. */
141
+ export function toCompleteResult(text, inputTokens, outputTokens) {
142
+ const result = { text };
143
+ if (typeof inputTokens === 'number' && typeof outputTokens === 'number') {
144
+ result.usage = { inputTokens, outputTokens };
145
+ }
146
+ return result;
147
+ }
148
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/providers/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * `@adminium/llm` provider clients barrel (06-llm-assist.md §3). The direct-API
3
+ * wire layer: fetch-based clients for Anthropic / OpenAI / OpenAI-compatible /
4
+ * Ollama, their model catalogs, and the shared `ProviderClient` contract +
5
+ * typed `ProviderError`. Browser-safe (global `fetch` only, no SDKs).
6
+ */
7
+ export * from './types.js';
8
+ export * from './http.js';
9
+ export * from './model-catalog.js';
10
+ export * from './anthropic.js';
11
+ export * from './openai.js';
12
+ export * from './openai-compatible.js';
13
+ export * from './ollama.js';
14
+ export * from './factory.js';
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,wBAAwB,CAAC;AACvC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * `@adminium/llm` provider clients barrel (06-llm-assist.md §3). The direct-API
3
+ * wire layer: fetch-based clients for Anthropic / OpenAI / OpenAI-compatible /
4
+ * Ollama, their model catalogs, and the shared `ProviderClient` contract +
5
+ * typed `ProviderError`. Browser-safe (global `fetch` only, no SDKs).
6
+ */
7
+ export * from './types.js';
8
+ export * from './http.js';
9
+ export * from './model-catalog.js';
10
+ export * from './anthropic.js';
11
+ export * from './openai.js';
12
+ export * from './openai-compatible.js';
13
+ export * from './ollama.js';
14
+ export * from './factory.js';
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,wBAAwB,CAAC;AACvC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { type ModelInfo } from './types.js';
2
+ export declare const ANTHROPIC_STATIC_MODELS: readonly ModelInfo[];
3
+ export declare const OPENAI_STATIC_MODELS: readonly ModelInfo[];
4
+ export interface CatalogFetchOptions {
5
+ apiKey?: string;
6
+ baseUrl: string;
7
+ timeoutMs?: number;
8
+ }
9
+ /** `GET {baseUrl}/v1/models`; on any failure returns the static Anthropic list. */
10
+ export declare function listAnthropicModels(opts: CatalogFetchOptions): Promise<ModelInfo[]>;
11
+ /** `GET {baseUrl}/models` filtered to chat models; on any failure returns the static OpenAI list. */
12
+ export declare function listOpenAiModels(opts: CatalogFetchOptions): Promise<ModelInfo[]>;
13
+ /**
14
+ * `GET {baseUrl}/models` for an OpenAI-compatible endpoint. A 404 (endpoint not
15
+ * implemented) is tolerated → `[]`, signalling the UI to offer a free-text model
16
+ * field. Other failures (auth, network, 5xx) propagate as `ProviderError`.
17
+ */
18
+ export declare function listOpenAiCompatibleModels(opts: CatalogFetchOptions): Promise<ModelInfo[]>;
19
+ /** `GET {baseUrl}/api/tags`; no static fallback — propagates `ProviderError` on failure. */
20
+ export declare function listOllamaModels(opts: CatalogFetchOptions): Promise<ModelInfo[]>;
21
+ //# sourceMappingURL=model-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-catalog.d.ts","sourceRoot":"","sources":["../../src/providers/model-catalog.ts"],"names":[],"mappings":"AAYA,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAI3D,eAAO,MAAM,uBAAuB,EAAE,SAAS,SAAS,EAMvD,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,SAAS,SAAS,EAKpD,CAAC;AAIF,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAQD,mFAAmF;AACnF,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAiBzF;AAoBD,qGAAqG;AACrG,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAiBtF;AAED;;;;GAIG;AACH,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAmBhG;AAMD,4FAA4F;AAC5F,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAStF"}