@absolutejs/ai 0.0.10 → 0.0.12
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/dist/ai/client/index.js +3 -1
- package/dist/ai/client/index.js.map +2 -2
- package/dist/ai/index.js +3 -1
- package/dist/ai/index.js.map +2 -2
- package/dist/ai/providers/anthropic.js +3 -1
- package/dist/ai/providers/anthropic.js.map +2 -2
- package/dist/ai/providers/gemini.js +3 -1
- package/dist/ai/providers/gemini.js.map +2 -2
- package/dist/ai/providers/ollama.js +3 -1
- package/dist/ai/providers/ollama.js.map +2 -2
- package/dist/ai/providers/openai.js +3 -1
- package/dist/ai/providers/openai.js.map +2 -2
- package/dist/ai/providers/openaiCompatible.js +3 -1
- package/dist/ai/providers/openaiCompatible.js.map +2 -2
- package/dist/ai/providers/openaiResponses.js +3 -1
- package/dist/ai/providers/openaiResponses.js.map +2 -2
- package/dist/ai/tools/index.js +309 -0
- package/dist/ai/tools/index.js.map +11 -0
- package/dist/src/ai/tools/codeExecution.d.ts +85 -0
- package/dist/src/ai/tools/codeMode.d.ts +115 -0
- package/dist/src/ai/tools/index.d.ts +13 -0
- package/package.json +17 -8
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `codeModeTool` — Code Mode for AI agents.
|
|
3
|
+
*
|
|
4
|
+
* Instead of exposing N tools to the model and having it call them one
|
|
5
|
+
* at a time (N round-trips per turn, N tool-call tokens, the model has
|
|
6
|
+
* to track intermediate state in context), Code Mode exposes ONE tool:
|
|
7
|
+
* `run_code`. The model sees the typed TypeScript signatures of all
|
|
8
|
+
* underlying tools and emits a single function that chains them.
|
|
9
|
+
*
|
|
10
|
+
* Pattern was popularized by Cloudflare's Dynamic Workers (April 2026
|
|
11
|
+
* blog post: "100× faster than containers"). Anthropic's programmatic
|
|
12
|
+
* tool calling is the same idea — execution pauses on a sub-tool call,
|
|
13
|
+
* the API yields a tool_use, you return a result, execution resumes.
|
|
14
|
+
* Both vendors report ~80% token reduction on multi-tool turns.
|
|
15
|
+
*
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { codeModeTool } from '@absolutejs/ai/tools';
|
|
18
|
+
*
|
|
19
|
+
* const tools = {
|
|
20
|
+
* run_code: codeModeTool({
|
|
21
|
+
* timeout: 5000,
|
|
22
|
+
* tools: {
|
|
23
|
+
* search_products: {
|
|
24
|
+
* description: 'Full-text search the product catalogue.',
|
|
25
|
+
* tsSignature: '(query: string) => Promise<Product[]>',
|
|
26
|
+
* handler: async (q) => db.products.search(q as string),
|
|
27
|
+
* },
|
|
28
|
+
* get_product: {
|
|
29
|
+
* description: 'Fetch one product by id.',
|
|
30
|
+
* tsSignature: '(id: string) => Promise<Product | null>',
|
|
31
|
+
* handler: async (id) => db.products.findById(id as string),
|
|
32
|
+
* },
|
|
33
|
+
* },
|
|
34
|
+
* types: `
|
|
35
|
+
* type Product = { id: string; name: string; price: number };
|
|
36
|
+
* `,
|
|
37
|
+
* }),
|
|
38
|
+
* };
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* The model emits a single function:
|
|
42
|
+
*
|
|
43
|
+
* ```js
|
|
44
|
+
* const items = await search_products('hat');
|
|
45
|
+
* const cheapest = items.sort((a, b) => a.price - b.price)[0];
|
|
46
|
+
* const detail = await get_product(cheapest.id);
|
|
47
|
+
* return { name: detail.name, price: detail.price };
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* One sandbox eval. Two host-fn calls. One returned value. The model's
|
|
51
|
+
* context only ever sees the final return — intermediate tool results
|
|
52
|
+
* don't enter the conversation window, so multi-step workflows are
|
|
53
|
+
* dramatically cheaper.
|
|
54
|
+
*
|
|
55
|
+
* Each underlying tool's `handler` runs on the HOST side (not in the
|
|
56
|
+
* sandbox). Async host fns work on both FFI (via the 0.4 pump) and
|
|
57
|
+
* Worker backends since isolated-jsc 0.4+. Errors thrown by host
|
|
58
|
+
* handlers propagate into the sandbox as JS Errors the model can
|
|
59
|
+
* catch and recover from.
|
|
60
|
+
*/
|
|
61
|
+
import type { AIToolDefinition } from "../../../types/ai";
|
|
62
|
+
/**
|
|
63
|
+
* One callable surfaced to the sandbox. The `tsSignature` shows up in
|
|
64
|
+
* the model-visible description; `handler` runs on the host when the
|
|
65
|
+
* sandbox calls it.
|
|
66
|
+
*/
|
|
67
|
+
export type CodeModeHostTool = {
|
|
68
|
+
/** One-line human description of what this tool does. */
|
|
69
|
+
description: string;
|
|
70
|
+
/** TypeScript signature shown to the model. Example:
|
|
71
|
+
* `'(query: string, options?: { limit?: number }) => Promise<Item[]>'`.
|
|
72
|
+
* The model writes JS against this signature; we don't enforce it at
|
|
73
|
+
* runtime — type-check is the model's responsibility. */
|
|
74
|
+
tsSignature: string;
|
|
75
|
+
/** Host implementation. Receives positional args as the model passed
|
|
76
|
+
* them. Return value is structure-cloned back into the sandbox. */
|
|
77
|
+
handler: (...args: unknown[]) => unknown;
|
|
78
|
+
};
|
|
79
|
+
/** Options for {@link codeModeTool}. */
|
|
80
|
+
export type CodeModeToolOptions = {
|
|
81
|
+
/** Map of host-tool name → {@link CodeModeHostTool}. */
|
|
82
|
+
tools: Record<string, CodeModeHostTool>;
|
|
83
|
+
/**
|
|
84
|
+
* Optional shared TypeScript declarations stitched into the prompt
|
|
85
|
+
* (type aliases, interfaces, etc.) so signatures can reference them.
|
|
86
|
+
* Use raw TS source; no parsing happens host-side.
|
|
87
|
+
*/
|
|
88
|
+
types?: string;
|
|
89
|
+
/**
|
|
90
|
+
* Per-isolate heap memory cap (MB). Default 64. As with the regular
|
|
91
|
+
* code-execution tool, FFI's cold heap is much smaller than Worker's,
|
|
92
|
+
* but per-call retention scales similarly.
|
|
93
|
+
*/
|
|
94
|
+
memoryLimit?: number;
|
|
95
|
+
/** Wall-clock timeout per `run_code` call (ms). Default 5000. */
|
|
96
|
+
timeout?: number;
|
|
97
|
+
/**
|
|
98
|
+
* isolated-jsc backend. Defaults to `'auto'`. Since isolated-jsc 0.4
|
|
99
|
+
* both backends support async host fns, so the choice is purely
|
|
100
|
+
* about cold spawn (FFI wins ~6×) vs Web APIs availability (Worker
|
|
101
|
+
* has `URL` / `TextEncoder` / `WebSocket`; FFI does not).
|
|
102
|
+
*/
|
|
103
|
+
backend?: "auto" | "ffi" | "worker";
|
|
104
|
+
/**
|
|
105
|
+
* Override the auto-generated description. By default we emit the
|
|
106
|
+
* model-facing prompt: a short instruction header + the host fn
|
|
107
|
+
* signatures + any shared `types`.
|
|
108
|
+
*/
|
|
109
|
+
description?: string;
|
|
110
|
+
/** Pool size cap. Default 8. */
|
|
111
|
+
poolSize?: number;
|
|
112
|
+
/** Recycle the isolate after N successful runs. Default 50. */
|
|
113
|
+
recycleAfter?: number;
|
|
114
|
+
};
|
|
115
|
+
export declare const codeModeTool: (options: CodeModeToolOptions) => AIToolDefinition;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@absolutejs/ai/tools` — first-party `AIToolDefinition`s ready to drop
|
|
3
|
+
* into the `tools: {...}` map you hand to `streamAI` / `generateAI`.
|
|
4
|
+
*
|
|
5
|
+
* - {@link codeExecutionTool} — execute model-generated JavaScript in a
|
|
6
|
+
* sandboxed `@absolutejs/isolated-jsc` isolate. Optional peer; install
|
|
7
|
+
* `@absolutejs/isolated-jsc` to use it.
|
|
8
|
+
* - {@link codeModeTool} — "Code Mode" wrapper for N host tools: model
|
|
9
|
+
* sees typed TS signatures, emits one function chaining several
|
|
10
|
+
* tool calls, ~80% token reduction vs N separate tool calls.
|
|
11
|
+
*/
|
|
12
|
+
export { codeExecutionTool, type CodeExecutionToolOptions, } from "./codeExecution";
|
|
13
|
+
export { type CodeModeHostTool, codeModeTool, type CodeModeToolOptions, } from "./codeMode";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@absolutejs/ai",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"description": "AI runtime, providers, streaming, and framework adapters extracted from AbsoluteJS",
|
|
5
5
|
"license": "BSL-1.1",
|
|
6
6
|
"type": "module",
|
|
@@ -62,6 +62,10 @@
|
|
|
62
62
|
"./providers": {
|
|
63
63
|
"import": "./dist/ai/providers/openaiCompatible.js",
|
|
64
64
|
"types": "./dist/src/ai/providers/openaiCompatible.d.ts"
|
|
65
|
+
},
|
|
66
|
+
"./tools": {
|
|
67
|
+
"import": "./dist/ai/tools/index.js",
|
|
68
|
+
"types": "./dist/src/ai/tools/index.d.ts"
|
|
65
69
|
}
|
|
66
70
|
},
|
|
67
71
|
"dependencies": {
|
|
@@ -69,6 +73,7 @@
|
|
|
69
73
|
"@absolutejs/sync": "0.7.0"
|
|
70
74
|
},
|
|
71
75
|
"peerDependencies": {
|
|
76
|
+
"@absolutejs/isolated-jsc": ">= 0.4.0",
|
|
72
77
|
"@angular/core": "^21.0.0",
|
|
73
78
|
"elysia": "^1.4.18",
|
|
74
79
|
"react": "^19.2.0",
|
|
@@ -76,6 +81,9 @@
|
|
|
76
81
|
"vue": "^3.5.27"
|
|
77
82
|
},
|
|
78
83
|
"peerDependenciesMeta": {
|
|
84
|
+
"@absolutejs/isolated-jsc": {
|
|
85
|
+
"optional": true
|
|
86
|
+
},
|
|
79
87
|
"@angular/core": {
|
|
80
88
|
"optional": true
|
|
81
89
|
},
|
|
@@ -91,21 +99,22 @@
|
|
|
91
99
|
},
|
|
92
100
|
"devDependencies": {
|
|
93
101
|
"@absolutejs/absolute": "^0.19.0-beta.1051",
|
|
102
|
+
"@absolutejs/isolated-jsc": "0.6.0",
|
|
94
103
|
"@angular/core": "^21.0.0",
|
|
104
|
+
"@eslint/js": "^10.0.1",
|
|
95
105
|
"@types/bun": "1.3.9",
|
|
96
106
|
"@types/react": "19.2.0",
|
|
97
107
|
"elysia": "1.4.18",
|
|
98
|
-
"react": "19.2.1",
|
|
99
|
-
"svelte": "5.55.0",
|
|
100
|
-
"typescript": "^5.9.3",
|
|
101
|
-
"vue": "3.5.27",
|
|
102
|
-
"@eslint/js": "^10.0.1",
|
|
103
108
|
"eslint": "^10.0.3",
|
|
109
|
+
"eslint-plugin-absolute": "^0.2.6",
|
|
110
|
+
"eslint-plugin-promise": "^7.2.1",
|
|
104
111
|
"globals": "^17.4.0",
|
|
105
112
|
"prettier": "^3.5.3",
|
|
113
|
+
"react": "19.2.1",
|
|
114
|
+
"svelte": "5.55.0",
|
|
115
|
+
"typescript": "^5.9.3",
|
|
106
116
|
"typescript-eslint": "^8.56.1",
|
|
107
|
-
"
|
|
108
|
-
"eslint-plugin-promise": "^7.2.1"
|
|
117
|
+
"vue": "3.5.27"
|
|
109
118
|
},
|
|
110
119
|
"scripts": {
|
|
111
120
|
"build": "bun run scripts/build.ts",
|