expo-ai-kit 0.6.0 → 0.8.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.
package/build/models.js CHANGED
@@ -19,6 +19,7 @@ export const MODEL_REGISTRY = [
19
19
  contextWindow: 8_000,
20
20
  minRamBytes: 2_000_000_000, // 2GB — LiteRT-LM memory-maps weights, actual RSS ~1.5GB
21
21
  supportedPlatforms: ['ios', 'android'],
22
+ license: 'Gemma',
22
23
  },
23
24
  {
24
25
  id: 'gemma-e4b',
@@ -31,6 +32,65 @@ export const MODEL_REGISTRY = [
31
32
  contextWindow: 16_000,
32
33
  minRamBytes: 3_000_000_000, // 3GB — LiteRT-LM memory-maps weights
33
34
  supportedPlatforms: ['ios', 'android'],
35
+ license: 'Gemma',
36
+ },
37
+ // --- Qwen3 (Apache-2.0) — official litert-community builds. A size ladder
38
+ // from a sub-GB model that runs anywhere up to a 4B that rivals Gemma E4B. ---
39
+ {
40
+ id: 'qwen3-0.6b',
41
+ name: 'Qwen3 0.6B',
42
+ parameterCount: '0.6B',
43
+ quantization: 'mixed-int4',
44
+ downloadUrl: 'https://huggingface.co/litert-community/Qwen3-0.6B/resolve/main/qwen3_0_6b_mixed_int4.litertlm',
45
+ sha256: 'b1baab462f6be49d70eada79d715c2c52cd9ece0cad00bddf6a2c097d23498e9',
46
+ sizeBytes: 497_664_000, // 475MB (exact, HF LFS)
47
+ // The int4 build ships a 2048-token KV. TODO: benchmark on device.
48
+ contextWindow: 2_048,
49
+ minRamBytes: 1_000_000_000, // 1GB — tiny; runs on virtually any modern device
50
+ supportedPlatforms: ['ios', 'android'],
51
+ license: 'Apache-2.0',
52
+ },
53
+ {
54
+ id: 'qwen3-1.7b',
55
+ name: 'Qwen3 1.7B',
56
+ parameterCount: '1.7B',
57
+ quantization: 'dynamic-int8',
58
+ downloadUrl: 'https://huggingface.co/litert-community/Qwen3-1.7B/resolve/main/Qwen3_1.7B.litertlm',
59
+ sha256: '66064a4e9269cb693e124c4e3040bcb8a446b10bca42663896329495add3861c',
60
+ sizeBytes: 2_056_729_520, // 2.06GB (exact, HF LFS)
61
+ // Conservative default (not marked in the filename). TODO: benchmark on device.
62
+ contextWindow: 4_096,
63
+ minRamBytes: 2_000_000_000, // 2GB
64
+ supportedPlatforms: ['ios', 'android'],
65
+ license: 'Apache-2.0',
66
+ },
67
+ {
68
+ id: 'qwen3-4b',
69
+ name: 'Qwen3 4B',
70
+ parameterCount: '4B',
71
+ quantization: 'mixed-int4',
72
+ downloadUrl: 'https://huggingface.co/litert-community/Qwen3-4B/resolve/main/qwen3_4b_mixed_int4.litertlm',
73
+ sha256: 'f0794bc77efeaaf4f7af815f04c483b19b8f2ae4a102cef1b7b760a25848a18e',
74
+ sizeBytes: 2_659_057_664, // 2.66GB (exact, HF LFS)
75
+ // Conservative default (not marked in the filename). TODO: benchmark on device.
76
+ contextWindow: 4_096,
77
+ minRamBytes: 3_000_000_000, // 3GB — 4B params need more headroom than the similarly-sized E2B
78
+ supportedPlatforms: ['ios', 'android'],
79
+ license: 'Apache-2.0',
80
+ },
81
+ // --- Phi-4 Mini (MIT) — strong reasoning; q8 build, the heaviest downloadable. ---
82
+ {
83
+ id: 'phi-4-mini',
84
+ name: 'Phi-4 Mini',
85
+ parameterCount: '3.8B',
86
+ quantization: 'int8',
87
+ downloadUrl: 'https://huggingface.co/litert-community/Phi-4-mini-instruct/resolve/main/Phi-4-mini-instruct_multi-prefill-seq_q8_ekv4096.litertlm',
88
+ sha256: '7764d4deb53800578307be33039476b38a6c370fff71bedb3c0552563e23ab02',
89
+ sizeBytes: 3_910_090_752, // 3.91GB (exact, HF LFS)
90
+ contextWindow: 4_096, // ekv4096 build
91
+ minRamBytes: 4_000_000_000, // 4GB — q8 weights, heaviest downloadable
92
+ supportedPlatforms: ['ios', 'android'],
93
+ license: 'MIT',
34
94
  },
35
95
  ];
36
96
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA+BH,MAAM,CAAC,MAAM,cAAc,GAAyB;IAClD;QACE,EAAE,EAAE,WAAW;QACf,IAAI,EAAE,aAAa;QACnB,cAAc,EAAE,MAAM;QACtB,YAAY,EAAE,iBAAiB;QAC/B,WAAW,EACT,uGAAuG;QACzG,MAAM,EAAE,kEAAkE;QAC1E,SAAS,EAAE,aAAa,EAAE,yBAAyB;QACnD,0CAA0C;QAC1C,0CAA0C;QAC1C,aAAa,EAAE,KAAK;QACpB,WAAW,EAAE,aAAa,EAAE,yDAAyD;QACrF,kBAAkB,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC;KACvC;IACD;QACE,EAAE,EAAE,WAAW;QACf,IAAI,EAAE,aAAa;QACnB,cAAc,EAAE,MAAM;QACtB,YAAY,EAAE,eAAe;QAC7B,WAAW,EACT,uGAAuG;QACzG,MAAM,EAAE,kEAAkE;QAC1E,SAAS,EAAE,aAAa,EAAE,yBAAyB;QACnD,aAAa,EAAE,MAAM;QACrB,WAAW,EAAE,aAAa,EAAE,sCAAsC;QAClE,kBAAkB,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC;KACvC;CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;AACtD,CAAC","sourcesContent":["/**\n * Model Registry\n *\n * Defines all downloadable models known to expo-ai-kit.\n * getDownloadableModels() reads from this registry and enriches\n * each entry with on-device status from the native layer.\n */\n\nexport type ModelRegistryEntry = {\n /** Unique model identifier used in setModel/downloadModel */\n id: string;\n /** Human-readable model name */\n name: string;\n /** Parameter count label */\n parameterCount: string;\n /** Quantization variant */\n quantization: string;\n /** URL to download the LiteRT-LM model file */\n downloadUrl: string;\n /** SHA256 hash for integrity verification after download */\n sha256: string;\n /** Download file size in bytes */\n sizeBytes: number;\n /**\n * Practical context window (max tokens) for this model on constrained devices.\n *\n * These are conservative defaults, NOT the base model's theoretical max.\n * These values should be benchmarked and adjusted during testing with\n * real devices.\n */\n contextWindow: number;\n /** Minimum device RAM in bytes required to run this model */\n minRamBytes: number;\n /** Platforms this model can run on */\n supportedPlatforms: ('ios' | 'android')[];\n};\n\nexport const MODEL_REGISTRY: ModelRegistryEntry[] = [\n {\n id: 'gemma-e2b',\n name: 'Gemma 4 E2B',\n parameterCount: '2.3B',\n quantization: 'mixed-2/4/8-bit',\n downloadUrl:\n 'https://huggingface.co/litert-community/gemma-4-E2B-it-litert-lm/resolve/main/gemma-4-E2B-it.litertlm',\n sha256: '181938105e0eefd105961417e8da75903eacda102c4fce9ce90f50b97139a63c',\n sizeBytes: 2_588_147_712, // 2.59GB (exact, HF LFS)\n // Conservative limit for 4GB RAM devices.\n // TODO: Benchmark during Phase 2 testing.\n contextWindow: 8_000,\n minRamBytes: 2_000_000_000, // 2GB — LiteRT-LM memory-maps weights, actual RSS ~1.5GB\n supportedPlatforms: ['ios', 'android'],\n },\n {\n id: 'gemma-e4b',\n name: 'Gemma 4 E4B',\n parameterCount: '4.5B',\n quantization: 'mixed-4/8-bit',\n downloadUrl:\n 'https://huggingface.co/litert-community/gemma-4-E4B-it-litert-lm/resolve/main/gemma-4-E4B-it.litertlm',\n sha256: '0b2a8980ce155fd97673d8e820b4d29d9c7d99b8fa6806f425d969b145bd52e0',\n sizeBytes: 3_659_530_240, // 3.66GB (exact, HF LFS)\n contextWindow: 16_000,\n minRamBytes: 3_000_000_000, // 3GB — LiteRT-LM memory-maps weights\n supportedPlatforms: ['ios', 'android'],\n },\n];\n\n/**\n * Look up a model registry entry by ID.\n * Returns undefined if not found.\n */\nexport function getRegistryEntry(modelId: string): ModelRegistryEntry | undefined {\n return MODEL_REGISTRY.find((m) => m.id === modelId);\n}\n"]}
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Model Registry\n *\n * Defines all downloadable models known to expo-ai-kit.\n * getDownloadableModels() reads from this registry and enriches\n * each entry with on-device status from the native layer.\n */\n\nexport type ModelRegistryEntry = {\n /** Unique model identifier used in setModel/downloadModel */\n id: string;\n /** Human-readable model name */\n name: string;\n /** Parameter count label */\n parameterCount: string;\n /** Quantization variant */\n quantization: string;\n /** URL to download the LiteRT-LM model file */\n downloadUrl: string;\n /** SHA256 hash for integrity verification after download */\n sha256: string;\n /** Download file size in bytes */\n sizeBytes: number;\n /**\n * Practical context window (max tokens) for this model on constrained devices.\n *\n * These are conservative defaults, NOT the base model's theoretical max.\n * These values should be benchmarked and adjusted during testing with\n * real devices.\n */\n contextWindow: number;\n /** Minimum device RAM in bytes required to run this model */\n minRamBytes: number;\n /** Platforms this model can run on */\n supportedPlatforms: ('ios' | 'android')[];\n /**\n * License the model weights are distributed under — an SPDX identifier\n * (e.g. 'Apache-2.0', 'MIT') or a family name for non-OSI terms (e.g. 'Gemma',\n * 'Llama-3.2'). Surfaced on {@link DownloadableModel} so app developers can\n * check their obligations before shipping a model to users.\n */\n license: string;\n};\n\nexport const MODEL_REGISTRY: ModelRegistryEntry[] = [\n {\n id: 'gemma-e2b',\n name: 'Gemma 4 E2B',\n parameterCount: '2.3B',\n quantization: 'mixed-2/4/8-bit',\n downloadUrl:\n 'https://huggingface.co/litert-community/gemma-4-E2B-it-litert-lm/resolve/main/gemma-4-E2B-it.litertlm',\n sha256: '181938105e0eefd105961417e8da75903eacda102c4fce9ce90f50b97139a63c',\n sizeBytes: 2_588_147_712, // 2.59GB (exact, HF LFS)\n // Conservative limit for 4GB RAM devices.\n // TODO: Benchmark during Phase 2 testing.\n contextWindow: 8_000,\n minRamBytes: 2_000_000_000, // 2GB — LiteRT-LM memory-maps weights, actual RSS ~1.5GB\n supportedPlatforms: ['ios', 'android'],\n license: 'Gemma',\n },\n {\n id: 'gemma-e4b',\n name: 'Gemma 4 E4B',\n parameterCount: '4.5B',\n quantization: 'mixed-4/8-bit',\n downloadUrl:\n 'https://huggingface.co/litert-community/gemma-4-E4B-it-litert-lm/resolve/main/gemma-4-E4B-it.litertlm',\n sha256: '0b2a8980ce155fd97673d8e820b4d29d9c7d99b8fa6806f425d969b145bd52e0',\n sizeBytes: 3_659_530_240, // 3.66GB (exact, HF LFS)\n contextWindow: 16_000,\n minRamBytes: 3_000_000_000, // 3GB — LiteRT-LM memory-maps weights\n supportedPlatforms: ['ios', 'android'],\n license: 'Gemma',\n },\n // --- Qwen3 (Apache-2.0) — official litert-community builds. A size ladder\n // from a sub-GB model that runs anywhere up to a 4B that rivals Gemma E4B. ---\n {\n id: 'qwen3-0.6b',\n name: 'Qwen3 0.6B',\n parameterCount: '0.6B',\n quantization: 'mixed-int4',\n downloadUrl:\n 'https://huggingface.co/litert-community/Qwen3-0.6B/resolve/main/qwen3_0_6b_mixed_int4.litertlm',\n sha256: 'b1baab462f6be49d70eada79d715c2c52cd9ece0cad00bddf6a2c097d23498e9',\n sizeBytes: 497_664_000, // 475MB (exact, HF LFS)\n // The int4 build ships a 2048-token KV. TODO: benchmark on device.\n contextWindow: 2_048,\n minRamBytes: 1_000_000_000, // 1GB — tiny; runs on virtually any modern device\n supportedPlatforms: ['ios', 'android'],\n license: 'Apache-2.0',\n },\n {\n id: 'qwen3-1.7b',\n name: 'Qwen3 1.7B',\n parameterCount: '1.7B',\n quantization: 'dynamic-int8',\n downloadUrl:\n 'https://huggingface.co/litert-community/Qwen3-1.7B/resolve/main/Qwen3_1.7B.litertlm',\n sha256: '66064a4e9269cb693e124c4e3040bcb8a446b10bca42663896329495add3861c',\n sizeBytes: 2_056_729_520, // 2.06GB (exact, HF LFS)\n // Conservative default (not marked in the filename). TODO: benchmark on device.\n contextWindow: 4_096,\n minRamBytes: 2_000_000_000, // 2GB\n supportedPlatforms: ['ios', 'android'],\n license: 'Apache-2.0',\n },\n {\n id: 'qwen3-4b',\n name: 'Qwen3 4B',\n parameterCount: '4B',\n quantization: 'mixed-int4',\n downloadUrl:\n 'https://huggingface.co/litert-community/Qwen3-4B/resolve/main/qwen3_4b_mixed_int4.litertlm',\n sha256: 'f0794bc77efeaaf4f7af815f04c483b19b8f2ae4a102cef1b7b760a25848a18e',\n sizeBytes: 2_659_057_664, // 2.66GB (exact, HF LFS)\n // Conservative default (not marked in the filename). TODO: benchmark on device.\n contextWindow: 4_096,\n minRamBytes: 3_000_000_000, // 3GB — 4B params need more headroom than the similarly-sized E2B\n supportedPlatforms: ['ios', 'android'],\n license: 'Apache-2.0',\n },\n // --- Phi-4 Mini (MIT) — strong reasoning; q8 build, the heaviest downloadable. ---\n {\n id: 'phi-4-mini',\n name: 'Phi-4 Mini',\n parameterCount: '3.8B',\n quantization: 'int8',\n downloadUrl:\n 'https://huggingface.co/litert-community/Phi-4-mini-instruct/resolve/main/Phi-4-mini-instruct_multi-prefill-seq_q8_ekv4096.litertlm',\n sha256: '7764d4deb53800578307be33039476b38a6c370fff71bedb3c0552563e23ab02',\n sizeBytes: 3_910_090_752, // 3.91GB (exact, HF LFS)\n contextWindow: 4_096, // ekv4096 build\n minRamBytes: 4_000_000_000, // 4GB — q8 weights, heaviest downloadable\n supportedPlatforms: ['ios', 'android'],\n license: 'MIT',\n },\n];\n\n/**\n * Look up a model registry entry by ID.\n * Returns undefined if not found.\n */\nexport function getRegistryEntry(modelId: string): ModelRegistryEntry | undefined {\n return MODEL_REGISTRY.find((m) => m.id === modelId);\n}\n"]}
@@ -0,0 +1,41 @@
1
+ import type { JSONSchema, ToolSet } from './types';
2
+ /** Build the instruction appended to the system prompt to enable tool calling. */
3
+ export declare function buildToolInstruction(tools: ToolSet): string;
4
+ /**
5
+ * What {@link parseToolCall} found in a model response.
6
+ *
7
+ * - `tool`: a well-formed call to a known tool (args still need schema validation).
8
+ * - `unknown-tool`: looked like a tool call but the name isn't in the tool set.
9
+ * - `text`: no tool call — treat the response as the final answer.
10
+ */
11
+ export type ParsedToolCall = {
12
+ kind: 'tool';
13
+ toolName: string;
14
+ args: unknown;
15
+ } | {
16
+ kind: 'unknown-tool';
17
+ toolName: string;
18
+ } | {
19
+ kind: 'text';
20
+ };
21
+ /**
22
+ * Detect a tool call in model output.
23
+ *
24
+ * A response is a tool call when it contains a JSON object (possibly wrapped in
25
+ * prose or a ```json fence) with a string `tool` field. We tolerate `arguments`
26
+ * or `args` for the payload. If `tool` names something not in `toolNames` it's
27
+ * reported as `unknown-tool` so the loop can re-prompt instead of leaking the
28
+ * raw JSON as an answer. Anything else is plain `text`.
29
+ */
30
+ export declare function parseToolCall(text: string, toolNames: string[]): ParsedToolCall;
31
+ /** Follow-up prompt when the model named a tool that doesn't exist. */
32
+ export declare function buildUnknownToolRepair(toolName: string, toolNames: string[]): string;
33
+ /** Follow-up prompt when a tool's proposed arguments failed schema validation. */
34
+ export declare function buildToolArgsRepair(toolName: string, errors: string[]): string;
35
+ /**
36
+ * Render a tool result as the user-turn text fed back to the model.
37
+ * Non-string results are JSON-encoded; strings pass through as-is.
38
+ */
39
+ export declare function formatToolResult(toolName: string, result: unknown): string;
40
+ export type { JSONSchema };
41
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAgBnD,kFAAkF;AAClF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAwB3D;AAED;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErB;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,cAAc,CAgB/E;AAED,uEAAuE;AACvE,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAMpF;AAED,kFAAkF;AAClF,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAQ9E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,CAI1E;AAeD,YAAY,EAAE,UAAU,EAAE,CAAC"}
package/build/tools.js ADDED
@@ -0,0 +1,86 @@
1
+ import { extractJson } from './structured';
2
+ // ---------------------------------------------------------------------------
3
+ // Pure helpers for generateText() tool calling.
4
+ //
5
+ // Like structured.ts, this module imports no native module so its logic can be
6
+ // unit-tested in plain Node. generateText() (in index.ts) drives the inference
7
+ // + tool-execution loop on top of these.
8
+ //
9
+ // On-device backends have no native tool-call channel, so we define a tiny text
10
+ // protocol: the model emits a JSON object `{"tool": "<name>", "arguments": {…}}`
11
+ // to request a call, or plain text to answer. We parse that back out tolerantly
12
+ // (reusing extractJson), validate the name + args, and run the tool in JS.
13
+ // ---------------------------------------------------------------------------
14
+ /** Build the instruction appended to the system prompt to enable tool calling. */
15
+ export function buildToolInstruction(tools) {
16
+ const names = Object.keys(tools);
17
+ const lines = [
18
+ 'You have access to the following tools. Use one only when it helps answer the request:',
19
+ '',
20
+ ];
21
+ for (const name of names) {
22
+ const tool = tools[name];
23
+ lines.push(`- ${name}: ${tool.description}`);
24
+ lines.push(` arguments JSON Schema: ${JSON.stringify(tool.parameters)}`);
25
+ }
26
+ lines.push('', 'To call a tool, respond with ONLY a JSON object of this exact form and nothing else:', '{"tool": "<tool name>", "arguments": { ... }}', '', 'Rules:', '- Call at most one tool per response.', `- "tool" must be exactly one of: ${names.join(', ')}.`, '- "arguments" must conform to that tool\'s arguments JSON Schema.', '- If you do not need a tool, answer the user directly in plain text with no JSON.', '- After you receive a tool result, use it to answer; do not repeat the same call.');
27
+ return lines.join('\n');
28
+ }
29
+ /**
30
+ * Detect a tool call in model output.
31
+ *
32
+ * A response is a tool call when it contains a JSON object (possibly wrapped in
33
+ * prose or a ```json fence) with a string `tool` field. We tolerate `arguments`
34
+ * or `args` for the payload. If `tool` names something not in `toolNames` it's
35
+ * reported as `unknown-tool` so the loop can re-prompt instead of leaking the
36
+ * raw JSON as an answer. Anything else is plain `text`.
37
+ */
38
+ export function parseToolCall(text, toolNames) {
39
+ const parsed = extractJson(text);
40
+ if (!parsed.ok)
41
+ return { kind: 'text' };
42
+ const value = parsed.value;
43
+ if (!isPlainObject(value) || typeof value.tool !== 'string') {
44
+ return { kind: 'text' };
45
+ }
46
+ const toolName = value.tool;
47
+ if (!toolNames.includes(toolName)) {
48
+ return { kind: 'unknown-tool', toolName };
49
+ }
50
+ const rawArgs = 'arguments' in value ? value.arguments : value.args;
51
+ return { kind: 'tool', toolName, args: rawArgs ?? {} };
52
+ }
53
+ /** Follow-up prompt when the model named a tool that doesn't exist. */
54
+ export function buildUnknownToolRepair(toolName, toolNames) {
55
+ return (`The tool "${toolName}" does not exist. ` +
56
+ `Available tools are: ${toolNames.join(', ')}. ` +
57
+ 'Either call one of these tools using the required JSON form, or answer in plain text.');
58
+ }
59
+ /** Follow-up prompt when a tool's proposed arguments failed schema validation. */
60
+ export function buildToolArgsRepair(toolName, errors) {
61
+ const detail = errors.slice(0, 8).join('; ');
62
+ return (`The arguments for "${toolName}" did not match its schema: ${detail}. ` +
63
+ 'Respond again with ONLY the corrected {"tool": "' +
64
+ toolName +
65
+ '", "arguments": { ... }} JSON — no prose, no markdown code fences.');
66
+ }
67
+ /**
68
+ * Render a tool result as the user-turn text fed back to the model.
69
+ * Non-string results are JSON-encoded; strings pass through as-is.
70
+ */
71
+ export function formatToolResult(toolName, result) {
72
+ const body = typeof result === 'string' ? result : safeStringify(result);
73
+ return `Result of calling the tool "${toolName}":\n${body}`;
74
+ }
75
+ function safeStringify(value) {
76
+ try {
77
+ return JSON.stringify(value) ?? String(value);
78
+ }
79
+ catch {
80
+ return String(value);
81
+ }
82
+ }
83
+ function isPlainObject(value) {
84
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
85
+ }
86
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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","sourcesContent":["import type { JSONSchema, ToolSet } from './types';\nimport { extractJson } from './structured';\n\n// ---------------------------------------------------------------------------\n// Pure helpers for generateText() tool calling.\n//\n// Like structured.ts, this module imports no native module so its logic can be\n// unit-tested in plain Node. generateText() (in index.ts) drives the inference\n// + tool-execution loop on top of these.\n//\n// On-device backends have no native tool-call channel, so we define a tiny text\n// protocol: the model emits a JSON object `{\"tool\": \"<name>\", \"arguments\": {…}}`\n// to request a call, or plain text to answer. We parse that back out tolerantly\n// (reusing extractJson), validate the name + args, and run the tool in JS.\n// ---------------------------------------------------------------------------\n\n/** Build the instruction appended to the system prompt to enable tool calling. */\nexport function buildToolInstruction(tools: ToolSet): string {\n const names = Object.keys(tools);\n const lines: string[] = [\n 'You have access to the following tools. Use one only when it helps answer the request:',\n '',\n ];\n for (const name of names) {\n const tool = tools[name];\n lines.push(`- ${name}: ${tool.description}`);\n lines.push(` arguments JSON Schema: ${JSON.stringify(tool.parameters)}`);\n }\n lines.push(\n '',\n 'To call a tool, respond with ONLY a JSON object of this exact form and nothing else:',\n '{\"tool\": \"<tool name>\", \"arguments\": { ... }}',\n '',\n 'Rules:',\n '- Call at most one tool per response.',\n `- \"tool\" must be exactly one of: ${names.join(', ')}.`,\n '- \"arguments\" must conform to that tool\\'s arguments JSON Schema.',\n '- If you do not need a tool, answer the user directly in plain text with no JSON.',\n '- After you receive a tool result, use it to answer; do not repeat the same call.'\n );\n return lines.join('\\n');\n}\n\n/**\n * What {@link parseToolCall} found in a model response.\n *\n * - `tool`: a well-formed call to a known tool (args still need schema validation).\n * - `unknown-tool`: looked like a tool call but the name isn't in the tool set.\n * - `text`: no tool call — treat the response as the final answer.\n */\nexport type ParsedToolCall =\n | { kind: 'tool'; toolName: string; args: unknown }\n | { kind: 'unknown-tool'; toolName: string }\n | { kind: 'text' };\n\n/**\n * Detect a tool call in model output.\n *\n * A response is a tool call when it contains a JSON object (possibly wrapped in\n * prose or a ```json fence) with a string `tool` field. We tolerate `arguments`\n * or `args` for the payload. If `tool` names something not in `toolNames` it's\n * reported as `unknown-tool` so the loop can re-prompt instead of leaking the\n * raw JSON as an answer. Anything else is plain `text`.\n */\nexport function parseToolCall(text: string, toolNames: string[]): ParsedToolCall {\n const parsed = extractJson(text);\n if (!parsed.ok) return { kind: 'text' };\n\n const value = parsed.value;\n if (!isPlainObject(value) || typeof value.tool !== 'string') {\n return { kind: 'text' };\n }\n\n const toolName = value.tool;\n if (!toolNames.includes(toolName)) {\n return { kind: 'unknown-tool', toolName };\n }\n\n const rawArgs = 'arguments' in value ? value.arguments : value.args;\n return { kind: 'tool', toolName, args: rawArgs ?? {} };\n}\n\n/** Follow-up prompt when the model named a tool that doesn't exist. */\nexport function buildUnknownToolRepair(toolName: string, toolNames: string[]): string {\n return (\n `The tool \"${toolName}\" does not exist. ` +\n `Available tools are: ${toolNames.join(', ')}. ` +\n 'Either call one of these tools using the required JSON form, or answer in plain text.'\n );\n}\n\n/** Follow-up prompt when a tool's proposed arguments failed schema validation. */\nexport function buildToolArgsRepair(toolName: string, errors: string[]): string {\n const detail = errors.slice(0, 8).join('; ');\n return (\n `The arguments for \"${toolName}\" did not match its schema: ${detail}. ` +\n 'Respond again with ONLY the corrected {\"tool\": \"' +\n toolName +\n '\", \"arguments\": { ... }} JSON — no prose, no markdown code fences.'\n );\n}\n\n/**\n * Render a tool result as the user-turn text fed back to the model.\n * Non-string results are JSON-encoded; strings pass through as-is.\n */\nexport function formatToolResult(toolName: string, result: unknown): string {\n const body =\n typeof result === 'string' ? result : safeStringify(result);\n return `Result of calling the tool \"${toolName}\":\\n${body}`;\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return String(value);\n }\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n// Re-export for callers that want the schema type alongside tool helpers.\nexport type { JSONSchema };\n"]}
package/build/types.d.ts CHANGED
@@ -191,6 +191,117 @@ export type GenerateObjectResult<T = unknown> = {
191
191
  /** The raw model output that produced `object` (useful for debugging). */
192
192
  text: string;
193
193
  };
194
+ /**
195
+ * A tool (function) the model may call to fetch data or take an action.
196
+ *
197
+ * The model never runs anything itself — it *proposes* a call (a name + JSON
198
+ * arguments), {@link generateText} validates the arguments against `parameters`,
199
+ * and only then invokes your `execute`. The result is fed back into the
200
+ * conversation so the model can use it to produce its final answer.
201
+ *
202
+ * @typeParam TArgs - Shape of the validated arguments passed to `execute`.
203
+ * @typeParam TResult - What `execute` returns (serialized back to the model).
204
+ */
205
+ export type Tool<TArgs = any, TResult = any> = {
206
+ /**
207
+ * What the tool does and when to use it. This is how the model decides
208
+ * whether a request matches this tool — make it specific and action-oriented.
209
+ */
210
+ description: string;
211
+ /**
212
+ * JSON Schema for the tool's arguments. The model is told to conform to it,
213
+ * and the args it proposes are validated against it (same pragmatic subset as
214
+ * {@link generateObject}) before `execute` runs. Keep it small and shallow.
215
+ */
216
+ parameters: JSONSchema;
217
+ /**
218
+ * Runs the tool with the validated arguments and returns a result.
219
+ *
220
+ * **Optional on purpose.** If you omit it, {@link generateText} does not run
221
+ * anything — it stops with `finishReason: 'tool-calls'` and hands you the
222
+ * proposed call so you can confirm, gate, or execute it yourself.
223
+ */
224
+ execute?: (args: TArgs) => TResult | Promise<TResult>;
225
+ };
226
+ /** A map of tool name → {@link Tool}, passed to {@link generateText}. */
227
+ export type ToolSet = Record<string, Tool>;
228
+ /** A tool invocation the model proposed (name + validated arguments). */
229
+ export type ToolCall = {
230
+ /** The tool's key in the {@link ToolSet}. */
231
+ toolName: string;
232
+ /** Arguments the model supplied, validated against the tool's `parameters`. */
233
+ args: unknown;
234
+ };
235
+ /** The outcome of running a {@link ToolCall} via its `execute`. */
236
+ export type ToolResult = {
237
+ /** The tool's key in the {@link ToolSet}. */
238
+ toolName: string;
239
+ /** The arguments that were passed to `execute`. */
240
+ args: unknown;
241
+ /** Whatever `execute` returned (or `{ error }` if it threw). */
242
+ result: unknown;
243
+ };
244
+ /** One model round-trip in the {@link generateText} loop. */
245
+ export type StepResult = {
246
+ /** Assistant text produced this step (empty when the step only called a tool). */
247
+ text: string;
248
+ /** Tool calls proposed this step (at most one in the current protocol). */
249
+ toolCalls: ToolCall[];
250
+ /** Results of the tool calls executed this step. */
251
+ toolResults: ToolResult[];
252
+ };
253
+ /**
254
+ * Why {@link generateText} stopped.
255
+ *
256
+ * - `'stop'`: the model produced a final text answer.
257
+ * - `'tool-calls'`: stopped because a proposed tool has no `execute` — the call
258
+ * is returned for you to handle (human-in-the-loop).
259
+ * - `'max-steps'`: hit the `maxSteps` cap while still calling tools. Raise the cap.
260
+ */
261
+ export type GenerateTextFinishReason = 'stop' | 'tool-calls' | 'max-steps';
262
+ /**
263
+ * Options for {@link generateText}.
264
+ */
265
+ export type GenerateTextOptions = {
266
+ /** Tools the model may call. Omit (or pass `{}`) for a plain text generation. */
267
+ tools?: ToolSet;
268
+ /**
269
+ * Maximum number of model round-trips (each call + tool execution is one step).
270
+ * Bounds the tool-calling chain so it can't run away. Defaults to 5.
271
+ */
272
+ maxSteps?: number;
273
+ /**
274
+ * System prompt used when the messages array has no system message. The tool
275
+ * instructions are appended to it (or to the array's system message if present).
276
+ */
277
+ systemPrompt?: string;
278
+ /**
279
+ * Abort the request. Behaves like {@link LLMSendOptions.signal} — the returned
280
+ * promise rejects with an INFERENCE_CANCELLED {@link ModelError}.
281
+ */
282
+ signal?: AbortSignal;
283
+ /**
284
+ * How many times to re-prompt within a step when the model emits a malformed
285
+ * tool call, an unknown tool name, or arguments that fail schema validation.
286
+ * Defaults to 2. If it still can't comply, `generateText` throws INFERENCE_FAILED.
287
+ */
288
+ maxRepairAttempts?: number;
289
+ };
290
+ /**
291
+ * Result of {@link generateText}.
292
+ */
293
+ export type GenerateTextResult = {
294
+ /** The final assistant text (empty if it stopped on a tool call without `execute`). */
295
+ text: string;
296
+ /** Every step taken, in order — useful for tracing or debugging. */
297
+ steps: StepResult[];
298
+ /** All tool calls across every step, flattened. */
299
+ toolCalls: ToolCall[];
300
+ /** All tool results across every step, flattened. */
301
+ toolResults: ToolResult[];
302
+ /** Why generation stopped. See {@link GenerateTextFinishReason}. */
303
+ finishReason: GenerateTextFinishReason;
304
+ };
194
305
  /**
195
306
  * A built-in model provided by the OS (e.g. Apple Foundation Models, ML Kit).
196
307
  * These are always available on supported devices -- no download needed.
@@ -218,6 +329,8 @@ export type DownloadableModel = {
218
329
  name: string;
219
330
  /** Parameter count label (e.g. '2.3B') */
220
331
  parameterCount: string;
332
+ /** License the weights are distributed under (e.g. 'Apache-2.0', 'MIT', 'Gemma'). */
333
+ license: string;
221
334
  /** Download file size in bytes */
222
335
  sizeBytes: number;
223
336
  /** Maximum context window in tokens */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA6SA;;GAEG;AACH,MAAM,OAAO,UAAW,SAAQ,KAAK;IACnC,IAAI,CAAiB;IACrB,OAAO,CAAS;IAEhB,YAAY,IAAoB,EAAE,OAAe,EAAE,OAAgB;QACjE,KAAK,CAAC,OAAO,IAAI,GAAG,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF","sourcesContent":["/**\n * Hardware backend for on-device model inference.\n *\n * - 'auto': Try GPU first, fall back to CPU (default)\n * - 'gpu': Force GPU — faster (~40-50 tok/s) but needs more memory\n * - 'cpu': Force CPU — slower (~2-5 tok/s) but works on low-RAM devices\n */\nexport type InferenceBackend = 'auto' | 'gpu' | 'cpu';\n\n/**\n * Sampling / generation parameters applied to a model session.\n *\n * Support is per-backend (on-device runtimes expose different knobs), so these\n * are best-effort — unsupported fields are ignored rather than erroring:\n *\n * | field | Gemma (LiteRT-LM) | Apple Foundation Models | ML Kit |\n * |-------------|:-----------------:|:-----------------------:|:------:|\n * | temperature | ✓ | ✓ | — |\n * | topK | ✓ | — | — |\n * | topP | ✓ | — | — |\n * | seed | ✓ (iOS only) | — | — |\n * | maxTokens | — | ✓ (max output) | — |\n *\n * Notes:\n * - Gemma/LiteRT-LM has no per-generation output-token cap (its `maxNumTokens`\n * is the total KV-cache size, set at load), so `maxTokens` is not honored\n * there. Its sampler (topK/topP/temperature[/seed]) is fixed at conversation\n * creation, which is why generation config lives on setModel() rather than\n * per-call. `seed` is currently wired on iOS only.\n * - The ML Kit built-in (Android default) does not yet apply generation config;\n * it uses its own defaults.\n */\nexport type GenerationConfig = {\n /** Sampling temperature. Lower = more deterministic. Typically 0.0–2.0. */\n temperature?: number;\n /** Nucleus sampling: number of top logits to consider. Must be > 0. */\n topK?: number;\n /** Nucleus sampling: cumulative probability threshold in [0, 1]. */\n topP?: number;\n /** RNG seed for reproducible sampling (Gemma only). */\n seed?: number;\n /** Maximum number of output tokens to generate (Apple FM / ML Kit only). */\n maxTokens?: number;\n};\n\n/**\n * Options for setModel.\n */\nexport type SetModelOptions = {\n /** Hardware backend to use for inference. Defaults to 'auto'. */\n backend?: InferenceBackend;\n /**\n * Default sampling parameters for this model session. Applied when the model\n * is activated and used for all subsequent sendMessage/streamMessage calls\n * until the next setModel(). See {@link GenerationConfig} for per-backend support.\n */\n generation?: GenerationConfig;\n};\n\n/**\n * Role in a conversation message.\n */\nexport type LLMRole = 'system' | 'user' | 'assistant';\n\n/**\n * A single message in a conversation.\n */\nexport type LLMMessage = {\n role: LLMRole;\n content: string;\n};\n\n/**\n * Options for sendMessage.\n */\nexport type LLMSendOptions = {\n /**\n * Default system prompt to use if no system message is provided in the messages array.\n * If a system message exists in the array, this is ignored.\n */\n systemPrompt?: string;\n /**\n * Abort the request. When the signal fires, the returned promise rejects with\n * an INFERENCE_CANCELLED {@link ModelError}.\n *\n * Note: on-device, non-streaming generation cannot always be interrupted\n * mid-decode — abort always unblocks the caller, but the model may keep\n * computing in the background until it finishes, during which a new\n * sendMessage/streamMessage will throw INFERENCE_BUSY. To truly interrupt a\n * long generation, prefer streamMessage().stop().\n */\n signal?: AbortSignal;\n};\n\n/**\n * Response from sendMessage.\n */\nexport type LLMResponse = {\n /** The generated response text */\n text: string;\n};\n\n/**\n * Options for streamMessage.\n */\nexport type LLMStreamOptions = {\n /**\n * Default system prompt to use if no system message is provided in the messages array.\n * If a system message exists in the array, this is ignored.\n */\n systemPrompt?: string;\n};\n\n/**\n * Handle returned by streamMessage.\n */\nexport type LLMStreamHandle = {\n /** Resolves with the final text when streaming completes or is stopped. */\n promise: Promise<LLMResponse>;\n /** Stop streaming. Resolves `promise` with the text accumulated so far. */\n stop: () => void;\n};\n\n/**\n * Event payload for streaming tokens.\n */\nexport type LLMStreamEvent = {\n /** Unique identifier for this streaming session */\n sessionId: string;\n /** The token/chunk of text received */\n token: string;\n /** Accumulated text so far */\n accumulatedText: string;\n /** Whether this is the final chunk */\n isDone: boolean;\n};\n\n/**\n * Callback function for streaming events.\n */\nexport type LLMStreamCallback = (event: LLMStreamEvent) => void;\n\n\n// ============================================================================\n// Structured Output (generateObject)\n// ============================================================================\n\n/**\n * The set of JSON Schema primitive `type` values understood by\n * {@link generateObject}'s local validator.\n */\nexport type JSONSchemaType =\n | 'object'\n | 'array'\n | 'string'\n | 'number'\n | 'integer'\n | 'boolean'\n | 'null';\n\n/**\n * A JSON Schema describing the shape you want {@link generateObject} to return.\n *\n * A pragmatic subset is enforced locally — `type`, `properties`, `required`,\n * `items`, and `enum` — which covers most extraction shapes. Any other JSON\n * Schema keywords you include (e.g. `description`, `minLength`) are still sent\n * to the model to guide it, but are not validated on-device. Keep schemas small:\n * on-device models follow flat, shallow shapes far more reliably than deeply\n * nested ones.\n */\nexport type JSONSchema = {\n /** Expected JSON type (or a union of types). */\n type?: JSONSchemaType | JSONSchemaType[];\n /** Human-readable hint passed through to the model. */\n description?: string;\n /** For `object` schemas: the schema of each named property. */\n properties?: Record<string, JSONSchema>;\n /** For `object` schemas: property names that must be present. */\n required?: string[];\n /** For `array` schemas: the schema each element must satisfy. */\n items?: JSONSchema;\n /** Restrict the value to this set of literals. */\n enum?: ReadonlyArray<string | number | boolean | null>;\n /** Other JSON Schema keywords are accepted and forwarded to the model. */\n [key: string]: unknown;\n};\n\n/**\n * Options for {@link generateObject}.\n */\nexport type GenerateObjectOptions = {\n /**\n * System prompt used when the messages array has no system message. Defaults\n * to a structured-output-oriented instruction. If a system message is present\n * in the array, this is ignored (the schema instruction is appended to it).\n */\n systemPrompt?: string;\n /**\n * Abort the request. Behaves like {@link LLMSendOptions.signal} — the returned\n * promise rejects with an INFERENCE_CANCELLED {@link ModelError}.\n */\n signal?: AbortSignal;\n /**\n * How many times to re-prompt the model when its output is not valid JSON or\n * does not match the schema. Each repair feeds the error back to the model.\n * Defaults to 2 (i.e. up to 3 generations total).\n */\n maxRepairAttempts?: number;\n};\n\n/**\n * Result of {@link generateObject}.\n */\nexport type GenerateObjectResult<T = unknown> = {\n /** The parsed value, validated against the schema. */\n object: T;\n /** The raw model output that produced `object` (useful for debugging). */\n text: string;\n};\n\n\n// ============================================================================\n// Model Types\n// ============================================================================\n\n/**\n * A built-in model provided by the OS (e.g. Apple Foundation Models, ML Kit).\n * These are always available on supported devices -- no download needed.\n */\nexport type BuiltInModel = {\n /** Unique model identifier (e.g. 'apple-fm', 'mlkit') */\n id: string;\n /** Human-readable model name */\n name: string;\n /** Whether this model is available on the current device/OS */\n available: boolean;\n /** Platform this model is associated with */\n platform: 'ios' | 'android';\n /** Maximum context window in tokens */\n contextWindow: number;\n};\n\n/**\n * A downloadable model that the user manages (download, load, delete).\n * These require explicit download before use.\n */\nexport type DownloadableModel = {\n /** Unique model identifier (e.g. 'gemma-e2b', 'gemma-e4b') */\n id: string;\n /** Human-readable model name */\n name: string;\n /** Parameter count label (e.g. '2.3B') */\n parameterCount: string;\n /** Download file size in bytes */\n sizeBytes: number;\n /** Maximum context window in tokens */\n contextWindow: number;\n /** Minimum device RAM in bytes required to run */\n minRamBytes: number;\n /** Whether this device meets the model's minimum RAM requirement */\n meetsRequirements: boolean;\n /** Current lifecycle status */\n status: DownloadableModelStatus;\n};\n\n/**\n * Lifecycle status of a downloadable model.\n *\n * - 'not-downloaded': Model file is not on disk\n * - 'downloading': Model file is being downloaded\n * - 'downloaded': Model file is on disk but not loaded into memory. Call\n * setModel() to load it. This survives app restarts, so use it to decide\n * whether a (re-)download is needed.\n * - 'loading': File is on disk, model is being loaded into memory for inference\n * - 'ready': Model is loaded in memory and ready for inference\n */\nexport type DownloadableModelStatus =\n | 'not-downloaded'\n | 'downloading'\n | 'downloaded'\n | 'loading'\n | 'ready';\n\n/**\n * Error codes for model-related operations.\n */\nexport type ModelErrorCode =\n | 'MODEL_NOT_FOUND'\n | 'MODEL_NOT_DOWNLOADED'\n | 'DOWNLOAD_FAILED'\n | 'DOWNLOAD_CORRUPT'\n | 'DOWNLOAD_STORAGE_FULL'\n | 'DOWNLOAD_CANCELLED'\n | 'INFERENCE_OOM'\n | 'INFERENCE_FAILED'\n | 'INFERENCE_BUSY'\n | 'INFERENCE_CANCELLED'\n | 'MODEL_LOAD_FAILED'\n | 'DEVICE_NOT_SUPPORTED'\n | 'UNKNOWN';\n\n/**\n * Structured error for model operations.\n */\nexport class ModelError extends Error {\n code: ModelErrorCode;\n modelId: string;\n\n constructor(code: ModelErrorCode, modelId: string, message?: string) {\n super(message ?? `${code}: ${modelId}`);\n this.name = 'ModelError';\n this.code = code;\n this.modelId = modelId;\n }\n}\n\n/**\n * Event payload for model download progress.\n */\nexport type ModelDownloadProgressEvent = {\n /** Model being downloaded */\n modelId: string;\n /** Download progress from 0 to 1 */\n progress: number;\n};\n\n/**\n * Event payload for model state changes.\n */\nexport type ModelStateChangeEvent = {\n /** Model whose state changed */\n modelId: string;\n /** New status */\n status: DownloadableModelStatus;\n};\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA2aA;;GAEG;AACH,MAAM,OAAO,UAAW,SAAQ,KAAK;IACnC,IAAI,CAAiB;IACrB,OAAO,CAAS;IAEhB,YAAY,IAAoB,EAAE,OAAe,EAAE,OAAgB;QACjE,KAAK,CAAC,OAAO,IAAI,GAAG,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF","sourcesContent":["/**\n * Hardware backend for on-device model inference.\n *\n * - 'auto': Try GPU first, fall back to CPU (default)\n * - 'gpu': Force GPU — faster (~40-50 tok/s) but needs more memory\n * - 'cpu': Force CPU — slower (~2-5 tok/s) but works on low-RAM devices\n */\nexport type InferenceBackend = 'auto' | 'gpu' | 'cpu';\n\n/**\n * Sampling / generation parameters applied to a model session.\n *\n * Support is per-backend (on-device runtimes expose different knobs), so these\n * are best-effort — unsupported fields are ignored rather than erroring:\n *\n * | field | Gemma (LiteRT-LM) | Apple Foundation Models | ML Kit |\n * |-------------|:-----------------:|:-----------------------:|:------:|\n * | temperature | ✓ | ✓ | — |\n * | topK | ✓ | — | — |\n * | topP | ✓ | — | — |\n * | seed | ✓ (iOS only) | — | — |\n * | maxTokens | — | ✓ (max output) | — |\n *\n * Notes:\n * - Gemma/LiteRT-LM has no per-generation output-token cap (its `maxNumTokens`\n * is the total KV-cache size, set at load), so `maxTokens` is not honored\n * there. Its sampler (topK/topP/temperature[/seed]) is fixed at conversation\n * creation, which is why generation config lives on setModel() rather than\n * per-call. `seed` is currently wired on iOS only.\n * - The ML Kit built-in (Android default) does not yet apply generation config;\n * it uses its own defaults.\n */\nexport type GenerationConfig = {\n /** Sampling temperature. Lower = more deterministic. Typically 0.0–2.0. */\n temperature?: number;\n /** Nucleus sampling: number of top logits to consider. Must be > 0. */\n topK?: number;\n /** Nucleus sampling: cumulative probability threshold in [0, 1]. */\n topP?: number;\n /** RNG seed for reproducible sampling (Gemma only). */\n seed?: number;\n /** Maximum number of output tokens to generate (Apple FM / ML Kit only). */\n maxTokens?: number;\n};\n\n/**\n * Options for setModel.\n */\nexport type SetModelOptions = {\n /** Hardware backend to use for inference. Defaults to 'auto'. */\n backend?: InferenceBackend;\n /**\n * Default sampling parameters for this model session. Applied when the model\n * is activated and used for all subsequent sendMessage/streamMessage calls\n * until the next setModel(). See {@link GenerationConfig} for per-backend support.\n */\n generation?: GenerationConfig;\n};\n\n/**\n * Role in a conversation message.\n */\nexport type LLMRole = 'system' | 'user' | 'assistant';\n\n/**\n * A single message in a conversation.\n */\nexport type LLMMessage = {\n role: LLMRole;\n content: string;\n};\n\n/**\n * Options for sendMessage.\n */\nexport type LLMSendOptions = {\n /**\n * Default system prompt to use if no system message is provided in the messages array.\n * If a system message exists in the array, this is ignored.\n */\n systemPrompt?: string;\n /**\n * Abort the request. When the signal fires, the returned promise rejects with\n * an INFERENCE_CANCELLED {@link ModelError}.\n *\n * Note: on-device, non-streaming generation cannot always be interrupted\n * mid-decode — abort always unblocks the caller, but the model may keep\n * computing in the background until it finishes, during which a new\n * sendMessage/streamMessage will throw INFERENCE_BUSY. To truly interrupt a\n * long generation, prefer streamMessage().stop().\n */\n signal?: AbortSignal;\n};\n\n/**\n * Response from sendMessage.\n */\nexport type LLMResponse = {\n /** The generated response text */\n text: string;\n};\n\n/**\n * Options for streamMessage.\n */\nexport type LLMStreamOptions = {\n /**\n * Default system prompt to use if no system message is provided in the messages array.\n * If a system message exists in the array, this is ignored.\n */\n systemPrompt?: string;\n};\n\n/**\n * Handle returned by streamMessage.\n */\nexport type LLMStreamHandle = {\n /** Resolves with the final text when streaming completes or is stopped. */\n promise: Promise<LLMResponse>;\n /** Stop streaming. Resolves `promise` with the text accumulated so far. */\n stop: () => void;\n};\n\n/**\n * Event payload for streaming tokens.\n */\nexport type LLMStreamEvent = {\n /** Unique identifier for this streaming session */\n sessionId: string;\n /** The token/chunk of text received */\n token: string;\n /** Accumulated text so far */\n accumulatedText: string;\n /** Whether this is the final chunk */\n isDone: boolean;\n};\n\n/**\n * Callback function for streaming events.\n */\nexport type LLMStreamCallback = (event: LLMStreamEvent) => void;\n\n\n// ============================================================================\n// Structured Output (generateObject)\n// ============================================================================\n\n/**\n * The set of JSON Schema primitive `type` values understood by\n * {@link generateObject}'s local validator.\n */\nexport type JSONSchemaType =\n | 'object'\n | 'array'\n | 'string'\n | 'number'\n | 'integer'\n | 'boolean'\n | 'null';\n\n/**\n * A JSON Schema describing the shape you want {@link generateObject} to return.\n *\n * A pragmatic subset is enforced locally — `type`, `properties`, `required`,\n * `items`, and `enum` — which covers most extraction shapes. Any other JSON\n * Schema keywords you include (e.g. `description`, `minLength`) are still sent\n * to the model to guide it, but are not validated on-device. Keep schemas small:\n * on-device models follow flat, shallow shapes far more reliably than deeply\n * nested ones.\n */\nexport type JSONSchema = {\n /** Expected JSON type (or a union of types). */\n type?: JSONSchemaType | JSONSchemaType[];\n /** Human-readable hint passed through to the model. */\n description?: string;\n /** For `object` schemas: the schema of each named property. */\n properties?: Record<string, JSONSchema>;\n /** For `object` schemas: property names that must be present. */\n required?: string[];\n /** For `array` schemas: the schema each element must satisfy. */\n items?: JSONSchema;\n /** Restrict the value to this set of literals. */\n enum?: ReadonlyArray<string | number | boolean | null>;\n /** Other JSON Schema keywords are accepted and forwarded to the model. */\n [key: string]: unknown;\n};\n\n/**\n * Options for {@link generateObject}.\n */\nexport type GenerateObjectOptions = {\n /**\n * System prompt used when the messages array has no system message. Defaults\n * to a structured-output-oriented instruction. If a system message is present\n * in the array, this is ignored (the schema instruction is appended to it).\n */\n systemPrompt?: string;\n /**\n * Abort the request. Behaves like {@link LLMSendOptions.signal} — the returned\n * promise rejects with an INFERENCE_CANCELLED {@link ModelError}.\n */\n signal?: AbortSignal;\n /**\n * How many times to re-prompt the model when its output is not valid JSON or\n * does not match the schema. Each repair feeds the error back to the model.\n * Defaults to 2 (i.e. up to 3 generations total).\n */\n maxRepairAttempts?: number;\n};\n\n/**\n * Result of {@link generateObject}.\n */\nexport type GenerateObjectResult<T = unknown> = {\n /** The parsed value, validated against the schema. */\n object: T;\n /** The raw model output that produced `object` (useful for debugging). */\n text: string;\n};\n\n\n// ============================================================================\n// Tool / Function Calling (generateText)\n// ============================================================================\n\n/**\n * A tool (function) the model may call to fetch data or take an action.\n *\n * The model never runs anything itself — it *proposes* a call (a name + JSON\n * arguments), {@link generateText} validates the arguments against `parameters`,\n * and only then invokes your `execute`. The result is fed back into the\n * conversation so the model can use it to produce its final answer.\n *\n * @typeParam TArgs - Shape of the validated arguments passed to `execute`.\n * @typeParam TResult - What `execute` returns (serialized back to the model).\n */\nexport type Tool<TArgs = any, TResult = any> = {\n /**\n * What the tool does and when to use it. This is how the model decides\n * whether a request matches this tool — make it specific and action-oriented.\n */\n description: string;\n /**\n * JSON Schema for the tool's arguments. The model is told to conform to it,\n * and the args it proposes are validated against it (same pragmatic subset as\n * {@link generateObject}) before `execute` runs. Keep it small and shallow.\n */\n parameters: JSONSchema;\n /**\n * Runs the tool with the validated arguments and returns a result.\n *\n * **Optional on purpose.** If you omit it, {@link generateText} does not run\n * anything — it stops with `finishReason: 'tool-calls'` and hands you the\n * proposed call so you can confirm, gate, or execute it yourself.\n */\n execute?: (args: TArgs) => TResult | Promise<TResult>;\n};\n\n/** A map of tool name → {@link Tool}, passed to {@link generateText}. */\nexport type ToolSet = Record<string, Tool>;\n\n/** A tool invocation the model proposed (name + validated arguments). */\nexport type ToolCall = {\n /** The tool's key in the {@link ToolSet}. */\n toolName: string;\n /** Arguments the model supplied, validated against the tool's `parameters`. */\n args: unknown;\n};\n\n/** The outcome of running a {@link ToolCall} via its `execute`. */\nexport type ToolResult = {\n /** The tool's key in the {@link ToolSet}. */\n toolName: string;\n /** The arguments that were passed to `execute`. */\n args: unknown;\n /** Whatever `execute` returned (or `{ error }` if it threw). */\n result: unknown;\n};\n\n/** One model round-trip in the {@link generateText} loop. */\nexport type StepResult = {\n /** Assistant text produced this step (empty when the step only called a tool). */\n text: string;\n /** Tool calls proposed this step (at most one in the current protocol). */\n toolCalls: ToolCall[];\n /** Results of the tool calls executed this step. */\n toolResults: ToolResult[];\n};\n\n/**\n * Why {@link generateText} stopped.\n *\n * - `'stop'`: the model produced a final text answer.\n * - `'tool-calls'`: stopped because a proposed tool has no `execute` — the call\n * is returned for you to handle (human-in-the-loop).\n * - `'max-steps'`: hit the `maxSteps` cap while still calling tools. Raise the cap.\n */\nexport type GenerateTextFinishReason = 'stop' | 'tool-calls' | 'max-steps';\n\n/**\n * Options for {@link generateText}.\n */\nexport type GenerateTextOptions = {\n /** Tools the model may call. Omit (or pass `{}`) for a plain text generation. */\n tools?: ToolSet;\n /**\n * Maximum number of model round-trips (each call + tool execution is one step).\n * Bounds the tool-calling chain so it can't run away. Defaults to 5.\n */\n maxSteps?: number;\n /**\n * System prompt used when the messages array has no system message. The tool\n * instructions are appended to it (or to the array's system message if present).\n */\n systemPrompt?: string;\n /**\n * Abort the request. Behaves like {@link LLMSendOptions.signal} — the returned\n * promise rejects with an INFERENCE_CANCELLED {@link ModelError}.\n */\n signal?: AbortSignal;\n /**\n * How many times to re-prompt within a step when the model emits a malformed\n * tool call, an unknown tool name, or arguments that fail schema validation.\n * Defaults to 2. If it still can't comply, `generateText` throws INFERENCE_FAILED.\n */\n maxRepairAttempts?: number;\n};\n\n/**\n * Result of {@link generateText}.\n */\nexport type GenerateTextResult = {\n /** The final assistant text (empty if it stopped on a tool call without `execute`). */\n text: string;\n /** Every step taken, in order — useful for tracing or debugging. */\n steps: StepResult[];\n /** All tool calls across every step, flattened. */\n toolCalls: ToolCall[];\n /** All tool results across every step, flattened. */\n toolResults: ToolResult[];\n /** Why generation stopped. See {@link GenerateTextFinishReason}. */\n finishReason: GenerateTextFinishReason;\n};\n\n\n// ============================================================================\n// Model Types\n// ============================================================================\n\n/**\n * A built-in model provided by the OS (e.g. Apple Foundation Models, ML Kit).\n * These are always available on supported devices -- no download needed.\n */\nexport type BuiltInModel = {\n /** Unique model identifier (e.g. 'apple-fm', 'mlkit') */\n id: string;\n /** Human-readable model name */\n name: string;\n /** Whether this model is available on the current device/OS */\n available: boolean;\n /** Platform this model is associated with */\n platform: 'ios' | 'android';\n /** Maximum context window in tokens */\n contextWindow: number;\n};\n\n/**\n * A downloadable model that the user manages (download, load, delete).\n * These require explicit download before use.\n */\nexport type DownloadableModel = {\n /** Unique model identifier (e.g. 'gemma-e2b', 'gemma-e4b') */\n id: string;\n /** Human-readable model name */\n name: string;\n /** Parameter count label (e.g. '2.3B') */\n parameterCount: string;\n /** License the weights are distributed under (e.g. 'Apache-2.0', 'MIT', 'Gemma'). */\n license: string;\n /** Download file size in bytes */\n sizeBytes: number;\n /** Maximum context window in tokens */\n contextWindow: number;\n /** Minimum device RAM in bytes required to run */\n minRamBytes: number;\n /** Whether this device meets the model's minimum RAM requirement */\n meetsRequirements: boolean;\n /** Current lifecycle status */\n status: DownloadableModelStatus;\n};\n\n/**\n * Lifecycle status of a downloadable model.\n *\n * - 'not-downloaded': Model file is not on disk\n * - 'downloading': Model file is being downloaded\n * - 'downloaded': Model file is on disk but not loaded into memory. Call\n * setModel() to load it. This survives app restarts, so use it to decide\n * whether a (re-)download is needed.\n * - 'loading': File is on disk, model is being loaded into memory for inference\n * - 'ready': Model is loaded in memory and ready for inference\n */\nexport type DownloadableModelStatus =\n | 'not-downloaded'\n | 'downloading'\n | 'downloaded'\n | 'loading'\n | 'ready';\n\n/**\n * Error codes for model-related operations.\n */\nexport type ModelErrorCode =\n | 'MODEL_NOT_FOUND'\n | 'MODEL_NOT_DOWNLOADED'\n | 'DOWNLOAD_FAILED'\n | 'DOWNLOAD_CORRUPT'\n | 'DOWNLOAD_STORAGE_FULL'\n | 'DOWNLOAD_CANCELLED'\n | 'INFERENCE_OOM'\n | 'INFERENCE_FAILED'\n | 'INFERENCE_BUSY'\n | 'INFERENCE_CANCELLED'\n | 'MODEL_LOAD_FAILED'\n | 'DEVICE_NOT_SUPPORTED'\n | 'UNKNOWN';\n\n/**\n * Structured error for model operations.\n */\nexport class ModelError extends Error {\n code: ModelErrorCode;\n modelId: string;\n\n constructor(code: ModelErrorCode, modelId: string, message?: string) {\n super(message ?? `${code}: ${modelId}`);\n this.name = 'ModelError';\n this.code = code;\n this.modelId = modelId;\n }\n}\n\n/**\n * Event payload for model download progress.\n */\nexport type ModelDownloadProgressEvent = {\n /** Model being downloaded */\n modelId: string;\n /** Download progress from 0 to 1 */\n progress: number;\n};\n\n/**\n * Event payload for model state changes.\n */\nexport type ModelStateChangeEvent = {\n /** Model whose state changed */\n modelId: string;\n /** New status */\n status: DownloadableModelStatus;\n};\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "expo-ai-kit",
3
- "version": "0.6.0",
4
- "description": "On-device AI for Expo — run Gemma 4, Apple Foundation Models & ML Kit locally: streaming, structured output, zero API keys",
3
+ "version": "0.8.0",
4
+ "description": "On-device AI for Expo — run Gemma 4, Apple Foundation Models & ML Kit locally: streaming, structured output, tool calling, zero API keys",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
7
7
  "files": [
@@ -38,6 +38,9 @@
38
38
  "expo",
39
39
  "gemma",
40
40
  "gemma-4",
41
+ "qwen",
42
+ "qwen3",
43
+ "phi-4",
41
44
  "on-device-ai",
42
45
  "llm",
43
46
  "litert",
@@ -45,6 +48,8 @@
45
48
  "ml-kit",
46
49
  "local-inference",
47
50
  "structured-output",
51
+ "tool-calling",
52
+ "function-calling",
48
53
  "json-schema",
49
54
  "expo-ai-kit",
50
55
  "ExpoAiKit"