@uptimizr/agent-core 0.1.0

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 (49) hide show
  1. package/AGENTS.md +40 -0
  2. package/LICENSE +201 -0
  3. package/README.md +125 -0
  4. package/dist/client.d.ts +33 -0
  5. package/dist/client.d.ts.map +1 -0
  6. package/dist/client.js +38 -0
  7. package/dist/client.js.map +1 -0
  8. package/dist/index.d.ts +5 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +4 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/loop.d.ts +47 -0
  13. package/dist/loop.d.ts.map +1 -0
  14. package/dist/loop.js +84 -0
  15. package/dist/loop.js.map +1 -0
  16. package/dist/provider.d.ts +73 -0
  17. package/dist/provider.d.ts.map +1 -0
  18. package/dist/provider.js +12 -0
  19. package/dist/provider.js.map +1 -0
  20. package/dist/providers/anthropic.d.ts +56 -0
  21. package/dist/providers/anthropic.d.ts.map +1 -0
  22. package/dist/providers/anthropic.js +75 -0
  23. package/dist/providers/anthropic.js.map +1 -0
  24. package/dist/providers/config.d.ts +74 -0
  25. package/dist/providers/config.d.ts.map +1 -0
  26. package/dist/providers/config.js +93 -0
  27. package/dist/providers/config.js.map +1 -0
  28. package/dist/providers/hosted.d.ts +50 -0
  29. package/dist/providers/hosted.d.ts.map +1 -0
  30. package/dist/providers/hosted.js +102 -0
  31. package/dist/providers/hosted.js.map +1 -0
  32. package/dist/providers/index.d.ts +16 -0
  33. package/dist/providers/index.d.ts.map +1 -0
  34. package/dist/providers/index.js +16 -0
  35. package/dist/providers/index.js.map +1 -0
  36. package/dist/providers/openai.d.ts +53 -0
  37. package/dist/providers/openai.d.ts.map +1 -0
  38. package/dist/providers/openai.js +79 -0
  39. package/dist/providers/openai.js.map +1 -0
  40. package/dist/providers/webllm.d.ts +128 -0
  41. package/dist/providers/webllm.d.ts.map +1 -0
  42. package/dist/providers/webllm.js +158 -0
  43. package/dist/providers/webllm.js.map +1 -0
  44. package/dist/tools.d.ts +28 -0
  45. package/dist/tools.d.ts.map +1 -0
  46. package/dist/tools.js +327 -0
  47. package/dist/tools.js.map +1 -0
  48. package/llms.txt +20 -0
  49. package/package.json +86 -0
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Pure translation between the agent-core conversation shape and the OpenAI
3
+ * Chat Completions wire format. Shared by the bring-your-own hosted adapter
4
+ * (OpenAI-compatible mode) and the WebLLM adapter — the MLC runtime exposes an
5
+ * OpenAI-compatible `chat.completions.create`. No I/O, no dependencies: just
6
+ * shape mapping, so both adapters agree on tool-calling semantics.
7
+ */
8
+ import type { AgentMessage, AgentToolSchema, ProviderResponse } from "../provider.js";
9
+ /** OpenAI chat message (request side). */
10
+ export interface OpenAiMessage {
11
+ role: "system" | "user" | "assistant" | "tool";
12
+ content: string;
13
+ tool_calls?: OpenAiToolCall[];
14
+ tool_call_id?: string;
15
+ name?: string;
16
+ }
17
+ /** OpenAI tool-call (both request echo and response). */
18
+ export interface OpenAiToolCall {
19
+ id: string;
20
+ type: "function";
21
+ function: {
22
+ name: string;
23
+ arguments: string;
24
+ };
25
+ }
26
+ /** OpenAI tool advertisement (function schema). */
27
+ export interface OpenAiTool {
28
+ type: "function";
29
+ function: {
30
+ name: string;
31
+ description: string;
32
+ parameters: Record<string, unknown>;
33
+ };
34
+ }
35
+ /** The subset of an OpenAI chat-completion response this module reads. */
36
+ export interface OpenAiCompletion {
37
+ choices?: Array<{
38
+ message?: {
39
+ content?: string | null;
40
+ tool_calls?: OpenAiToolCall[] | null;
41
+ };
42
+ }>;
43
+ }
44
+ /** Map the agent conversation to OpenAI request messages. */
45
+ export declare function toOpenAiMessages(messages: readonly AgentMessage[]): OpenAiMessage[];
46
+ /** Map the read-only tool schemas to OpenAI `tools`. */
47
+ export declare function toOpenAiTools(tools: readonly AgentToolSchema[]): OpenAiTool[];
48
+ /**
49
+ * Normalise an OpenAI completion into a {@link ProviderResponse}. Tool calls
50
+ * take precedence; otherwise the message content is the final answer.
51
+ */
52
+ export declare function parseOpenAiCompletion(completion: OpenAiCompletion): ProviderResponse;
53
+ //# sourceMappingURL=openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,YAAY,EAEZ,eAAe,EACf,gBAAgB,EACjB,MAAM,gBAAgB,CAAC;AAExB,0CAA0C;AAC1C,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,yDAAyD;AACzD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/C;AAED,mDAAmD;AACnD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;CACtF;AAED,0EAA0E;AAC1E,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,KAAK,CAAC;QACd,OAAO,CAAC,EAAE;YACR,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;YACxB,UAAU,CAAC,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC;SACtC,CAAC;KACH,CAAC,CAAC;CACJ;AAED,6DAA6D;AAC7D,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG,aAAa,EAAE,CAsBnF;AAUD,wDAAwD;AACxD,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,eAAe,EAAE,GAAG,UAAU,EAAE,CAK7E;AAaD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,gBAAgB,GAAG,gBAAgB,CAkBpF"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Pure translation between the agent-core conversation shape and the OpenAI
3
+ * Chat Completions wire format. Shared by the bring-your-own hosted adapter
4
+ * (OpenAI-compatible mode) and the WebLLM adapter — the MLC runtime exposes an
5
+ * OpenAI-compatible `chat.completions.create`. No I/O, no dependencies: just
6
+ * shape mapping, so both adapters agree on tool-calling semantics.
7
+ */
8
+ /** Map the agent conversation to OpenAI request messages. */
9
+ export function toOpenAiMessages(messages) {
10
+ return messages.map((message) => {
11
+ switch (message.role) {
12
+ case "assistant":
13
+ return {
14
+ role: "assistant",
15
+ content: message.content,
16
+ ...(message.toolCalls && message.toolCalls.length > 0
17
+ ? { tool_calls: message.toolCalls.map(toOpenAiToolCall) }
18
+ : {}),
19
+ };
20
+ case "tool":
21
+ return {
22
+ role: "tool",
23
+ content: message.content,
24
+ tool_call_id: message.toolCallId,
25
+ name: message.name,
26
+ };
27
+ default:
28
+ return { role: message.role, content: message.content };
29
+ }
30
+ });
31
+ }
32
+ function toOpenAiToolCall(call) {
33
+ return {
34
+ id: call.id,
35
+ type: "function",
36
+ function: { name: call.name, arguments: JSON.stringify(call.arguments ?? {}) },
37
+ };
38
+ }
39
+ /** Map the read-only tool schemas to OpenAI `tools`. */
40
+ export function toOpenAiTools(tools) {
41
+ return tools.map((tool) => ({
42
+ type: "function",
43
+ function: { name: tool.name, description: tool.description, parameters: tool.parameters },
44
+ }));
45
+ }
46
+ /** Parse tool-call arguments that arrive as a JSON string (OpenAI encoding). */
47
+ function parseArguments(raw) {
48
+ if (!raw)
49
+ return {};
50
+ try {
51
+ const parsed = JSON.parse(raw);
52
+ return parsed && typeof parsed === "object" ? parsed : {};
53
+ }
54
+ catch {
55
+ return {};
56
+ }
57
+ }
58
+ /**
59
+ * Normalise an OpenAI completion into a {@link ProviderResponse}. Tool calls
60
+ * take precedence; otherwise the message content is the final answer.
61
+ */
62
+ export function parseOpenAiCompletion(completion) {
63
+ const message = completion.choices?.[0]?.message;
64
+ const toolCalls = message?.tool_calls ?? [];
65
+ const content = message?.content ?? "";
66
+ if (toolCalls.length > 0) {
67
+ return {
68
+ kind: "tool_calls",
69
+ toolCalls: toolCalls.map((call) => ({
70
+ id: call.id,
71
+ name: call.function.name,
72
+ arguments: parseArguments(call.function.arguments),
73
+ })),
74
+ ...(content ? { content } : {}),
75
+ };
76
+ }
77
+ return { kind: "final", content };
78
+ }
79
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Local, in-browser LLM adapter backed by WebLLM / WebGPU (ADR 0050 §4/§6).
3
+ *
4
+ * Zero data egress: the model runs entirely on the user's GPU and nothing —
5
+ * neither prompt nor results — leaves the browser. The heavy `@mlc-ai/web-llm`
6
+ * runtime is an **optional** dependency loaded via a lazy `import()` only when
7
+ * the user actually runs the assistant, so `@uptimizr/agent-core` stays small
8
+ * and browser-safe for everyone else. Model weights are downloaded on first use
9
+ * (behind explicit consent) and cached by the runtime in the browser's Cache
10
+ * Storage — never part of any precache.
11
+ */
12
+ import type { LlmProvider } from "../provider.js";
13
+ import { type OpenAiCompletion, type OpenAiMessage, type OpenAiTool } from "./openai.js";
14
+ /** A curated model the user may install (ADR 0050 §4). */
15
+ export interface CuratedModel {
16
+ /** MLC model id passed to the runtime. */
17
+ id: string;
18
+ /** Human-friendly name for the picker. */
19
+ label: string;
20
+ /** Approximate download size, for the consent disclosure. */
21
+ downloadSize: string;
22
+ /** Approximate GPU memory (VRAM) required. */
23
+ vram: string;
24
+ /** One-line description of the trade-off. */
25
+ description: string;
26
+ }
27
+ /**
28
+ * The complete set of model ids WebLLM supports for `ChatCompletionRequest.tools`
29
+ * (function calling). WebLLM hard-codes tool-calling to the Hermes-2-Pro /
30
+ * Hermes-3 family — its tool-call system prompt and output parser are
31
+ * Hermes-specific — so passing any other model with `tools` throws at runtime.
32
+ * The assistant relies on tool-calling, so every {@link CuratedModel} MUST be in
33
+ * this allowlist. Keep this list in sync with WebLLM's own supported set (these
34
+ * are the exact ids WebLLM names in its runtime error). Plain string membership
35
+ * only — never build a regex from a model id.
36
+ */
37
+ export declare const SUPPORTED_TOOL_CALLING_MODELS: readonly string[];
38
+ /**
39
+ * A small, curated set of **tool-calling-capable** models (ADR 0050 §4). WebLLM
40
+ * only supports function calling on the 7–8B Hermes family (see
41
+ * {@link SUPPORTED_TOOL_CALLING_MODELS}), so there is no small (<3 GB) option —
42
+ * local mode has an inherent ~4 GB download / ~5 GB-VRAM floor. Ordered
43
+ * smallest-first so the default is the least-friction working model. Sizes are
44
+ * approximate (sourced from WebLLM's `prebuiltAppConfig`) and shown to the user
45
+ * before any download.
46
+ */
47
+ export declare const CURATED_MODELS: readonly CuratedModel[];
48
+ /** Progress report emitted while weights download / the engine initialises. */
49
+ export interface InitProgress {
50
+ /** Fraction complete in [0, 1]. */
51
+ progress: number;
52
+ /** Human-readable status text from the runtime. */
53
+ text: string;
54
+ }
55
+ /** The minimal slice of the `@mlc-ai/web-llm` runtime this adapter uses. */
56
+ export interface WebLlmEngine {
57
+ chat: {
58
+ completions: {
59
+ create(request: {
60
+ messages: OpenAiMessage[];
61
+ tools?: OpenAiTool[];
62
+ tool_choice?: "auto";
63
+ stream?: false;
64
+ }): Promise<OpenAiCompletion>;
65
+ };
66
+ };
67
+ unload?(): Promise<void>;
68
+ }
69
+ /** The subset of the `@mlc-ai/web-llm` module surface this adapter loads. */
70
+ export interface WebLlmRuntime {
71
+ CreateMLCEngine(model: string, engineConfig?: {
72
+ initProgressCallback?: (report: {
73
+ progress: number;
74
+ text: string;
75
+ }) => void;
76
+ }): Promise<WebLlmEngine>;
77
+ }
78
+ /** Options for {@link createWebLlmProvider}. */
79
+ export interface WebLlmProviderOptions {
80
+ /** Curated model id to load. Defaults to the first curated model. */
81
+ model?: string;
82
+ /**
83
+ * Consent gate invoked once, before weights download begins. Return `false`
84
+ * (or reject) to abort — the adapter throws {@link WebLlmConsentError} and no
85
+ * data is downloaded. Use this to show the "~N GB, runs 100% locally" prompt.
86
+ */
87
+ confirmDownload?: (model: CuratedModel) => boolean | Promise<boolean>;
88
+ /** Called with download/initialise progress. */
89
+ onInitProgress?: (progress: InitProgress) => void;
90
+ /**
91
+ * Injectable runtime loader (for tests / custom hosting). Defaults to a lazy
92
+ * `import("@mlc-ai/web-llm")`.
93
+ */
94
+ loadRuntime?: () => Promise<WebLlmRuntime>;
95
+ /** Injectable WebGPU check (for tests); defaults to real feature detection. */
96
+ hasWebGpu?: () => boolean;
97
+ }
98
+ /** A WebLLM provider, plus a hook to release GPU resources. */
99
+ export interface WebLlmProvider extends LlmProvider {
100
+ /** Release the loaded engine and its GPU memory. Safe to call repeatedly. */
101
+ unload(): Promise<void>;
102
+ }
103
+ /** Thrown when the local backend is used on a browser without WebGPU. */
104
+ export declare class WebGpuUnavailableError extends Error {
105
+ constructor();
106
+ }
107
+ /** Thrown when the user declines the model-download consent prompt. */
108
+ export declare class WebLlmConsentError extends Error {
109
+ constructor();
110
+ }
111
+ /**
112
+ * Thrown when the requested model is not one WebLLM supports for tool-calling
113
+ * (see {@link SUPPORTED_TOOL_CALLING_MODELS}). Raised as a preflight check —
114
+ * *before* any weights download or engine init — so the user never downloads
115
+ * gigabytes only to hit WebLLM's runtime `tools` error. The message mirrors
116
+ * WebLLM's own so consumers can surface a consistent explanation.
117
+ */
118
+ export declare class UnsupportedToolCallingModelError extends Error {
119
+ constructor(modelId: string);
120
+ }
121
+ /**
122
+ * Create a local WebLLM provider. The runtime and model weights load lazily on
123
+ * the first {@link LlmProvider.complete} call — construction is cheap and has no
124
+ * side effects, so it is safe to build eagerly and feature-detect via
125
+ * {@link isWebGpuAvailable} before offering the local option.
126
+ */
127
+ export declare function createWebLlmProvider(options?: WebLlmProviderOptions): WebLlmProvider;
128
+ //# sourceMappingURL=webllm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webllm.d.ts","sourceRoot":"","sources":["../../src/providers/webllm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAqC,MAAM,gBAAgB,CAAC;AAErF,OAAO,EAIL,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,UAAU,EAChB,MAAM,aAAa,CAAC;AAErB,0DAA0D;AAC1D,MAAM,WAAW,YAAY;IAC3B,0CAA0C;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,YAAY,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,6BAA6B,EAAE,SAAS,MAAM,EAM1D,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,YAAY,EAsBjD,CAAC;AAEF,+EAA+E;AAC/E,MAAM,WAAW,YAAY;IAC3B,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,4EAA4E;AAC5E,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE;QACJ,WAAW,EAAE;YACX,MAAM,CAAC,OAAO,EAAE;gBACd,QAAQ,EAAE,aAAa,EAAE,CAAC;gBAC1B,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;gBACrB,WAAW,CAAC,EAAE,MAAM,CAAC;gBACrB,MAAM,CAAC,EAAE,KAAK,CAAC;aAChB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;SAC/B,CAAC;KACH,CAAC;IACF,MAAM,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,6EAA6E;AAC7E,MAAM,WAAW,aAAa;IAC5B,eAAe,CACb,KAAK,EAAE,MAAM,EACb,YAAY,CAAC,EAAE;QAAE,oBAAoB,CAAC,EAAE,CAAC,MAAM,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,KAAK,IAAI,CAAA;KAAE,GAC7F,OAAO,CAAC,YAAY,CAAC,CAAC;CAC1B;AAED,gDAAgD;AAChD,MAAM,WAAW,qBAAqB;IACpC,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtE,gDAAgD;IAChD,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;IAClD;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC;IAC3C,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;CAC3B;AAED,+DAA+D;AAC/D,MAAM,WAAW,cAAe,SAAQ,WAAW;IACjD,6EAA6E;IAC7E,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAED,yEAAyE;AACzE,qBAAa,sBAAuB,SAAQ,KAAK;;CAKhD;AAED,uEAAuE;AACvE,qBAAa,kBAAmB,SAAQ,KAAK;;CAK5C;AAED;;;;;;GAMG;AACH,qBAAa,gCAAiC,SAAQ,KAAK;gBAC7C,OAAO,EAAE,MAAM;CAO5B;AAUD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,qBAA0B,GAAG,cAAc,CAuDxF"}
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Local, in-browser LLM adapter backed by WebLLM / WebGPU (ADR 0050 §4/§6).
3
+ *
4
+ * Zero data egress: the model runs entirely on the user's GPU and nothing —
5
+ * neither prompt nor results — leaves the browser. The heavy `@mlc-ai/web-llm`
6
+ * runtime is an **optional** dependency loaded via a lazy `import()` only when
7
+ * the user actually runs the assistant, so `@uptimizr/agent-core` stays small
8
+ * and browser-safe for everyone else. Model weights are downloaded on first use
9
+ * (behind explicit consent) and cached by the runtime in the browser's Cache
10
+ * Storage — never part of any precache.
11
+ */
12
+ import { isWebGpuAvailable } from "./config.js";
13
+ import { parseOpenAiCompletion, toOpenAiMessages, toOpenAiTools, } from "./openai.js";
14
+ /**
15
+ * The complete set of model ids WebLLM supports for `ChatCompletionRequest.tools`
16
+ * (function calling). WebLLM hard-codes tool-calling to the Hermes-2-Pro /
17
+ * Hermes-3 family — its tool-call system prompt and output parser are
18
+ * Hermes-specific — so passing any other model with `tools` throws at runtime.
19
+ * The assistant relies on tool-calling, so every {@link CuratedModel} MUST be in
20
+ * this allowlist. Keep this list in sync with WebLLM's own supported set (these
21
+ * are the exact ids WebLLM names in its runtime error). Plain string membership
22
+ * only — never build a regex from a model id.
23
+ */
24
+ export const SUPPORTED_TOOL_CALLING_MODELS = [
25
+ "Hermes-2-Pro-Llama-3-8B-q4f16_1-MLC",
26
+ "Hermes-2-Pro-Llama-3-8B-q4f32_1-MLC",
27
+ "Hermes-2-Pro-Mistral-7B-q4f16_1-MLC",
28
+ "Hermes-3-Llama-3.1-8B-q4f32_1-MLC",
29
+ "Hermes-3-Llama-3.1-8B-q4f16_1-MLC",
30
+ ];
31
+ /**
32
+ * A small, curated set of **tool-calling-capable** models (ADR 0050 §4). WebLLM
33
+ * only supports function calling on the 7–8B Hermes family (see
34
+ * {@link SUPPORTED_TOOL_CALLING_MODELS}), so there is no small (<3 GB) option —
35
+ * local mode has an inherent ~4 GB download / ~5 GB-VRAM floor. Ordered
36
+ * smallest-first so the default is the least-friction working model. Sizes are
37
+ * approximate (sourced from WebLLM's `prebuiltAppConfig`) and shown to the user
38
+ * before any download.
39
+ */
40
+ export const CURATED_MODELS = [
41
+ {
42
+ id: "Hermes-2-Pro-Mistral-7B-q4f16_1-MLC",
43
+ label: "Hermes 2 Pro (Mistral 7B)",
44
+ downloadSize: "~3.9 GB",
45
+ vram: "~4.0 GB",
46
+ description: "Smallest tool-calling model; the least-friction default.",
47
+ },
48
+ {
49
+ id: "Hermes-2-Pro-Llama-3-8B-q4f16_1-MLC",
50
+ label: "Hermes 2 Pro (Llama 3 8B)",
51
+ downloadSize: "~4.6 GB",
52
+ vram: "~5.0 GB",
53
+ description: "Stronger Llama-3 base; needs a capable GPU.",
54
+ },
55
+ {
56
+ id: "Hermes-3-Llama-3.1-8B-q4f16_1-MLC",
57
+ label: "Hermes 3 (Llama 3.1 8B)",
58
+ downloadSize: "~4.5 GB",
59
+ vram: "~4.9 GB",
60
+ description: "Highest quality; needs a capable GPU (~5 GB VRAM).",
61
+ },
62
+ ];
63
+ /** Thrown when the local backend is used on a browser without WebGPU. */
64
+ export class WebGpuUnavailableError extends Error {
65
+ constructor() {
66
+ super("WebGPU is not available in this browser; the local model cannot run.");
67
+ this.name = "WebGpuUnavailableError";
68
+ }
69
+ }
70
+ /** Thrown when the user declines the model-download consent prompt. */
71
+ export class WebLlmConsentError extends Error {
72
+ constructor() {
73
+ super("Model download was not confirmed by the user.");
74
+ this.name = "WebLlmConsentError";
75
+ }
76
+ }
77
+ /**
78
+ * Thrown when the requested model is not one WebLLM supports for tool-calling
79
+ * (see {@link SUPPORTED_TOOL_CALLING_MODELS}). Raised as a preflight check —
80
+ * *before* any weights download or engine init — so the user never downloads
81
+ * gigabytes only to hit WebLLM's runtime `tools` error. The message mirrors
82
+ * WebLLM's own so consumers can surface a consistent explanation.
83
+ */
84
+ export class UnsupportedToolCallingModelError extends Error {
85
+ constructor(modelId) {
86
+ super(`${modelId} is not supported for tool-calling. The assistant requires function calling; ` +
87
+ `WebLLM supports it only on these models: ${SUPPORTED_TOOL_CALLING_MODELS.join(", ")}.`);
88
+ this.name = "UnsupportedToolCallingModelError";
89
+ }
90
+ }
91
+ function resolveModel(id) {
92
+ const model = id ? CURATED_MODELS.find((m) => m.id === id) : CURATED_MODELS[0];
93
+ return model ?? { id: id ?? "", label: id ?? "", downloadSize: "?", vram: "?", description: "" };
94
+ }
95
+ const defaultLoadRuntime = () => import("@mlc-ai/web-llm");
96
+ /**
97
+ * Create a local WebLLM provider. The runtime and model weights load lazily on
98
+ * the first {@link LlmProvider.complete} call — construction is cheap and has no
99
+ * side effects, so it is safe to build eagerly and feature-detect via
100
+ * {@link isWebGpuAvailable} before offering the local option.
101
+ */
102
+ export function createWebLlmProvider(options = {}) {
103
+ const model = resolveModel(options.model);
104
+ // Preflight (defense-in-depth): fail fast if the model can't do tool-calling,
105
+ // so we never download weights only to hit WebLLM's runtime `tools` error.
106
+ if (!SUPPORTED_TOOL_CALLING_MODELS.includes(model.id)) {
107
+ throw new UnsupportedToolCallingModelError(model.id);
108
+ }
109
+ const loadRuntime = options.loadRuntime ?? defaultLoadRuntime;
110
+ const hasWebGpu = options.hasWebGpu ?? (() => isWebGpuAvailable());
111
+ let enginePromise;
112
+ function ensureEngine() {
113
+ if (!enginePromise) {
114
+ enginePromise = initEngine().catch((err) => {
115
+ // Reset so a later attempt (e.g. after granting consent) can retry.
116
+ enginePromise = undefined;
117
+ throw err;
118
+ });
119
+ }
120
+ return enginePromise;
121
+ }
122
+ async function initEngine() {
123
+ if (!hasWebGpu())
124
+ throw new WebGpuUnavailableError();
125
+ if (options.confirmDownload) {
126
+ const ok = await options.confirmDownload(model);
127
+ if (!ok)
128
+ throw new WebLlmConsentError();
129
+ }
130
+ const runtime = await loadRuntime();
131
+ return runtime.CreateMLCEngine(model.id, {
132
+ initProgressCallback: options.onInitProgress
133
+ ? (report) => options.onInitProgress?.({ progress: report.progress, text: report.text })
134
+ : undefined,
135
+ });
136
+ }
137
+ return {
138
+ async complete(request) {
139
+ const engine = await ensureEngine();
140
+ const completion = await engine.chat.completions.create({
141
+ messages: toOpenAiMessages(request.messages),
142
+ tools: toOpenAiTools(request.tools),
143
+ tool_choice: "auto",
144
+ stream: false,
145
+ });
146
+ return parseOpenAiCompletion(completion);
147
+ },
148
+ async unload() {
149
+ const promise = enginePromise;
150
+ enginePromise = undefined;
151
+ if (!promise)
152
+ return;
153
+ const engine = await promise.catch(() => undefined);
154
+ await engine?.unload?.();
155
+ },
156
+ };
157
+ }
158
+ //# sourceMappingURL=webllm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webllm.js","sourceRoot":"","sources":["../../src/providers/webllm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { z } from "zod";
2
+ import type { QueryParams } from "./client.js";
3
+ /** A resolved read request: the collector path and its query parameters. */
4
+ export interface ReadToolRequest {
5
+ path: string;
6
+ params: QueryParams;
7
+ }
8
+ /**
9
+ * A read-only tool definition. `inputSchema` is a Zod raw shape the MCP runtime
10
+ * uses to validate arguments; `buildRequest` maps validated arguments to a
11
+ * `GET` against the collector. Definitions are pure and unit-testable without a
12
+ * live collector.
13
+ */
14
+ export interface ReadTool {
15
+ name: string;
16
+ title: string;
17
+ description: string;
18
+ inputSchema: z.ZodRawShape;
19
+ buildRequest: (args: Record<string, unknown>) => ReadToolRequest;
20
+ }
21
+ /**
22
+ * The catalog of read-only tools. Each wraps one documented collector query
23
+ * endpoint (docs/integration.md §Query). There are intentionally **no**
24
+ * ingestion, mutation, or raw per-session event tools — the surface is
25
+ * aggregate, read-only, and privacy-preserving (ADR 0003 / ADR 0017).
26
+ */
27
+ export declare const readTools: readonly ReadTool[];
28
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;CACrB;AAED;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,CAAC,CAAC,WAAW,CAAC;IAC3B,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,eAAe,CAAC;CAClE;AAqDD;;;;;GAKG;AACH,eAAO,MAAM,SAAS,EAAE,SAAS,QAAQ,EAwRxC,CAAC"}