@ax-llm/ax 21.0.0 → 21.0.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ax-llm/ax",
3
- "version": "21.0.0",
3
+ "version": "21.0.3",
4
4
  "type": "module",
5
5
  "description": "The best library to work with LLMs",
6
6
  "repository": {
@@ -14,8 +14,7 @@
14
14
  "keywords": [],
15
15
  "types": "./index.d.ts",
16
16
  "dependencies": {
17
- "@opentelemetry/api": "^1.9.0",
18
- "dayjs": "^1.11.13"
17
+ "@opentelemetry/api": "^1.9.0"
19
18
  },
20
19
  "peerDependencies": {
21
20
  "zod": "^3.24.0 || ^4.0.0"
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: ax-agent-optimize
3
3
  description: This skill helps an LLM generate correct AxAgent tuning and evaluation code using @ax-llm/ax. Use when the user asks about agent.optimize(...), judgeOptions, eval datasets, optimization targets, saved optimizedProgram artifacts, or recursive optimization guidance.
4
- version: "21.0.0"
4
+ version: "21.0.3"
5
5
  ---
6
6
 
7
7
  # AxAgent Optimize Codegen Rules (@ax-llm/ax)
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: ax-agent
3
3
  description: This skill helps an LLM generate correct AxAgent code using @ax-llm/ax. Use when the user asks about agent(), child agents, namespaced functions, discovery mode, shared fields, llmQuery(...), RLM code execution, recursionOptions, or agent runtime behavior. For tuning and eval with agent.optimize(...), use ax-agent-optimize.
4
- version: "21.0.0"
4
+ version: "21.0.3"
5
5
  ---
6
6
 
7
7
  # AxAgent Codegen Rules (@ax-llm/ax)
@@ -462,7 +462,7 @@ const dbTool = fn('queryUsers')
462
462
 
463
463
  const myAgent = agent('query:string -> answer:string', {
464
464
  contextFields: [],
465
- functions: { local: [dbTool] },
465
+ functions: [dbTool],
466
466
  bubbleErrors: [DatabaseError, AuthError],
467
467
  });
468
468
 
@@ -535,11 +535,8 @@ const analyst = agent('context:string, query:string -> answer:string', {
535
535
  namespace: 'team',
536
536
  },
537
537
  contextFields: ['context'],
538
- agents: { local: [writer] },
539
- functions: {
540
- discovery: true,
541
- local: tools,
542
- },
538
+ functions: [writer, ...tools],
539
+ functionDiscovery: true,
543
540
  });
544
541
  ```
545
542
 
@@ -720,7 +717,7 @@ const tools = [
720
717
  const harness = agent('query:string -> answer:string', {
721
718
  contextFields: ['query'],
722
719
  runtime,
723
- functions: { local: tools },
720
+ functions: tools,
724
721
  contextPolicy: { preset: 'checkpointed', budget: 'balanced' },
725
722
  });
726
723
 
@@ -893,8 +890,7 @@ Use `onFunctionCall` when the caller wants to observe every function call the ac
893
890
  const supportAgent = agent('query:string -> answer:string', {
894
891
  contextFields: ['query'],
895
892
  runtime,
896
- agents: [helperAgent],
897
- functions: [{ name: 'lookupOrder', namespace: 'tools', /* ... */ }],
893
+ functions: [helperAgent, { name: 'lookupOrder', namespace: 'tools', /* ... */ }],
898
894
  onFunctionCall: ({ name, qualifiedName, args, kind }) => {
899
895
  console.log(`[${kind}] ${qualifiedName}`, args);
900
896
  },
@@ -1211,9 +1207,9 @@ await final("Summarize severity findings", { snippets });
1211
1207
 
1212
1208
  Reason: this mixes observation and follow-up work in one turn.
1213
1209
 
1214
- ## Shared Fields
1210
+ ## Threading Parent Fields Into Child Agents
1215
1211
 
1216
- If a child agent requires a parent field such as `audience`, prefer shared fields:
1212
+ If a child agent requires a parent field such as `audience`, declare it on the child's signature and pass it explicitly when calling the child from the actor:
1217
1213
 
1218
1214
  ```typescript
1219
1215
  const writingCoach = agent(
@@ -1222,6 +1218,7 @@ const writingCoach = agent(
1222
1218
  agentIdentity: {
1223
1219
  name: 'Writing Coach',
1224
1220
  description: 'Polishes summaries for a target audience',
1221
+ namespace: 'team',
1225
1222
  },
1226
1223
  contextFields: [],
1227
1224
  }
@@ -1230,50 +1227,55 @@ const writingCoach = agent(
1230
1227
  const analyst = agent(
1231
1228
  'context:string, audience:string, query:string -> answer:string',
1232
1229
  {
1233
- agents: { local: [writingCoach] },
1234
- fields: { shared: ['audience'] },
1230
+ functions: [writingCoach],
1235
1231
  contextFields: ['context'],
1236
1232
  }
1237
1233
  );
1238
1234
  ```
1239
1235
 
1240
- Generated runtime call:
1236
+ Generated runtime call (note: namespace comes from the child's `agentIdentity.namespace`; falls back to `utils` if unset):
1241
1237
 
1242
1238
  ```javascript
1243
- const polished = await agents.writingCoach({ draft: summary });
1239
+ const polished = await team.writingCoach({
1240
+ draft: summary,
1241
+ audience: inputs.audience,
1242
+ });
1244
1243
  ```
1245
1244
 
1246
1245
  Rules:
1247
1246
 
1248
- - Use `fields.shared` for direct children.
1249
- - Use `fields.globallyShared` for all descendants.
1250
- - Do not manually thread a parent field on every child call when shared fields fit the use case.
1247
+ - Pass parent fields explicitly via the call site — `inputs.<field>`.
1248
+ - If many children need the same field on every call, use `inputUpdateCallback` to inject the value before each executor turn.
1249
+ - Do not assume any auto-propagation: child agents receive only the args the actor passes.
1251
1250
 
1252
- ## Shared Agents And Shared Functions
1251
+ ## Grouped Function Modules
1253
1252
 
1254
- Use grouped config:
1253
+ For discovery mode, you can group functions into modules using the `AxAgentFunctionGroup` shape — handy when you want a clean `kb.find(...)`, `metrics.score(...)` namespace tree without setting `namespace` on every individual `fn(...)`:
1255
1254
 
1256
1255
  ```typescript
1257
1256
  const parent = agent('query:string -> answer:string', {
1258
- agents: {
1259
- local: [worker],
1260
- shared: [logger],
1261
- globallyShared: [auditor],
1262
- },
1263
- functions: {
1264
- local: [searchTool],
1265
- shared: [scoreTool],
1266
- globallyShared: [traceTool],
1267
- },
1257
+ functions: [
1258
+ {
1259
+ namespace: 'kb',
1260
+ description: 'Knowledge base lookups',
1261
+ functions: [findSnippetsFn, searchPagesFn],
1262
+ },
1263
+ {
1264
+ namespace: 'metrics',
1265
+ description: 'Scoring and coverage helpers',
1266
+ functions: [scoreCoverageFn],
1267
+ },
1268
+ ],
1269
+ functionDiscovery: true,
1268
1270
  contextFields: [],
1269
1271
  });
1270
1272
  ```
1271
1273
 
1272
1274
  Rules:
1273
1275
 
1274
- - `agents.shared` and `functions.shared` propagate one level down.
1275
- - `agents.globallyShared` and `functions.globallyShared` propagate to all descendants.
1276
- - Use `excluded` when a child should not receive a propagated field, agent, or function.
1276
+ - A group is `{ namespace, description, functions: [...] }`. The group's `namespace` and `description` show up in `discoverModules(...)` markdown.
1277
+ - Mix groups and ungrouped entries freely in `functions: [...]` — child agents and `fn(...)` tools sit alongside group entries.
1278
+ - There is no `local` / `shared` / `globallyShared` propagation. Each agent owns its own `functions: [...]`; pass shared tools to children explicitly.
1277
1279
 
1278
1280
  ## Tuning Hand-off
1279
1281
 
package/skills/ax-ai.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: ax-ai
3
3
  description: This skill helps an LLM generate correct AI provider setup and configuration code using @ax-llm/ax. Use when the user asks about ai(), providers, models, presets, embeddings, extended thinking, context caching, or mentions OpenAI/Anthropic/Google/Azure/Groq/DeepSeek/Mistral/Cohere/Together/Ollama/HuggingFace/Reka/OpenRouter with @ax-llm/ax.
4
- version: "21.0.0"
4
+ version: "21.0.3"
5
5
  ---
6
6
 
7
7
  # AI Provider Codegen Rules (@ax-llm/ax)
@@ -26,7 +26,7 @@ const openrouter = ai({ name: 'openrouter', apiKey: 'your-key' });
26
26
  const ollama = ai({ name: 'ollama', url: 'http://localhost:11434' });
27
27
  const hf = ai({ name: 'huggingface', apiKey: 'hf_...' });
28
28
  const reka = ai({ name: 'reka', apiKey: 'your-key' });
29
- const grok = ai({ name: 'x-grok', apiKey: 'your-key' });
29
+ const grok = ai({ name: 'grok', apiKey: 'your-key' });
30
30
  ```
31
31
 
32
32
  ## Model Presets
@@ -47,6 +47,25 @@ const gemini = ai({
47
47
  await gemini.chat({ model: 'tiny', chatPrompt: [{ role: 'user', content: 'Hi' }] });
48
48
  ```
49
49
 
50
+ ## Model Catalog
51
+
52
+ ```typescript
53
+ import { axGetSupportedAIModels } from '@ax-llm/ax';
54
+
55
+ const providers = axGetSupportedAIModels();
56
+ const openai = providers.find((provider) => provider.name === 'openai');
57
+ console.log(openai?.models[0]?.promptTokenCostPer1M);
58
+
59
+ const textProviders = axGetSupportedAIModels({ type: 'text' });
60
+ const embeddingProviders = axGetSupportedAIModels({ type: 'embeddings' });
61
+ ```
62
+
63
+ Use `axGetSupportedAIModels()` to build provider/model selectors before creating an `ai(...)` instance. It returns bundled static metadata: provider names, display names, default models, raw `AxModelInfo` pricing/details, model type (`'text'`, `'embeddings'`, `'code'`, or `'audio'`), and normalized capability flags for thinking, thoughts, structured outputs, audio, temperature, and top-p support. Provider groups and models are sorted cheapest to most expensive based on bundled input + output token pricing; unpriced models sort last.
64
+
65
+ Filter with `{ type: 'all' | 'text' | 'embeddings' | 'code' | 'audio' }` or an array of those values. The `'text'` filter includes code-capable models; use `'code'` to show only code-first models.
66
+
67
+ Dynamic providers such as Azure OpenAI deployments, OpenRouter, Ollama, and Hugging Face are marked with `isDynamic: true` and may have an empty or static-limited model list.
68
+
50
69
  ## Chat
51
70
 
52
71
  ```typescript
@@ -210,7 +229,7 @@ const client = new AxMCPClient(transport);
210
229
  ## Critical Rules
211
230
 
212
231
  - Use `ai()` factory for all providers.
213
- - Provider names: `'openai'`, `'anthropic'`, `'google-gemini'`, `'azure-openai'`, `'mistral'`, `'groq'`, `'cohere'`, `'together'`, `'deepseek'`, `'ollama'`, `'huggingface'`, `'openrouter'`, `'reka'`, `'x-grok'`
232
+ - Provider names: `'openai'`, `'anthropic'`, `'google-gemini'`, `'azure-openai'`, `'mistral'`, `'groq'`, `'cohere'`, `'together'`, `'deepseek'`, `'ollama'`, `'huggingface'`, `'openrouter'`, `'reka'`, `'grok'`
214
233
  - Thinking constraints on Anthropic: `temperature` and `topK` are ignored; `topP` only sent if >= 0.95.
215
234
  - Bedrock uses `new AxAIBedrock()`, not `ai()`.
216
235
  - Vercel AI SDK uses `AxAIProvider` wrapper.
@@ -0,0 +1,251 @@
1
+ ---
2
+ name: ax-audio
3
+ description: This skill helps an LLM generate correct conversational audio I/O code with @ax-llm/ax. Use when the user asks about .chat() audio input, audio output, OpenAI gpt-audio or realtime models, Gemini Live native audio, Grok Voice Agent models, voices, formats, transcripts, or how audio fits with signatures and structured outputs.
4
+ version: "21.0.3"
5
+ ---
6
+
7
+ # Audio I/O Codegen Rules (@ax-llm/ax)
8
+
9
+ Use this skill for bounded-turn conversational audio through `.chat()`. Prefer short, modern, copyable examples. Do not model generated audio as a DSPy signature output field.
10
+
11
+ ## Core Rule
12
+
13
+ Audio output is returned on `AxChatResponseResult.audio`, not in signature fields.
14
+
15
+ Signatures should keep text fields text-shaped:
16
+
17
+ ```typescript
18
+ const result = await llm.chat({
19
+ chatPrompt: [{ role: 'user', content: 'Say hello out loud.' }],
20
+ modelConfig: {
21
+ audio: { output: { enabled: true } },
22
+ },
23
+ });
24
+
25
+ console.log(result.results[0]?.content);
26
+ console.log(result.results[0]?.audio?.data);
27
+ console.log(result.results[0]?.audio?.transcript);
28
+ ```
29
+
30
+ Do not write signatures like `question:string -> audio:audio`. Use `.chat()` for conversational audio and use `audio.data` for the generated bytes.
31
+
32
+ ## Config Shape
33
+
34
+ ```typescript
35
+ type AxChatAudioConfig = {
36
+ input?: {
37
+ format?: 'wav' | 'mp3' | 'flac' | 'opus' | 'aac' | 'pcm16' | 'pcm' | 'ogg';
38
+ mimeType?: string;
39
+ sampleRate?: number;
40
+ channels?: number;
41
+ };
42
+ output?: {
43
+ enabled?: boolean;
44
+ voice?: string | { id: string };
45
+ format?: 'wav' | 'mp3' | 'flac' | 'opus' | 'aac' | 'pcm16' | 'pcm' | 'ogg';
46
+ sampleRate?: number;
47
+ channels?: number;
48
+ includeTranscript?: boolean;
49
+ };
50
+ live?: {
51
+ turnTimeoutMs?: number;
52
+ enableAffectiveDialog?: boolean;
53
+ proactiveAudio?: boolean;
54
+ };
55
+ };
56
+ ```
57
+
58
+ ## OpenAI Defaults
59
+
60
+ Use `axAIOpenAIAudioDefaultConfig()` for OpenAI request-based audio chat:
61
+
62
+ - model: `gpt-audio-mini`
63
+ - output enabled
64
+ - voice: `alloy`
65
+ - output format: `wav`
66
+ - transcript enabled
67
+ - streaming disabled by default
68
+ - audio input formats: `wav`, `mp3`
69
+ - audio output formats: `wav`, `mp3`, `flac`, `opus`, `aac`, `pcm16`
70
+
71
+ ```typescript
72
+ import { ai, axAIOpenAIAudioDefaultConfig } from '@ax-llm/ax';
73
+
74
+ const openai = ai({
75
+ name: 'openai',
76
+ apiKey: process.env.OPENAI_APIKEY!,
77
+ config: axAIOpenAIAudioDefaultConfig(),
78
+ });
79
+
80
+ const res = await openai.chat({
81
+ chatPrompt: [
82
+ {
83
+ role: 'user',
84
+ content: [
85
+ { type: 'text', text: 'What is in this recording?' },
86
+ { type: 'audio', data: base64Wav, format: 'wav' },
87
+ ],
88
+ },
89
+ ],
90
+ });
91
+
92
+ console.log(res.results[0]?.content);
93
+ console.log(res.results[0]?.audio?.data);
94
+ ```
95
+
96
+ Use `axAIOpenAIRealtimeDefaultConfig()` for OpenAI realtime speech-to-speech:
97
+
98
+ - model: `gpt-realtime-2`
99
+ - output enabled
100
+ - voice: `marin`
101
+ - output format: `pcm16`
102
+ - input default: `audio/pcm`, mono, 24000 Hz
103
+ - turn timeout: `30000`
104
+ - streaming disabled by default
105
+
106
+ Use `axAIOpenAIRealtimeTranscriptionDefaultConfig()` for realtime transcript deltas:
107
+
108
+ - model: `gpt-realtime-whisper`
109
+ - input default: `audio/pcm`, mono, 24000 Hz
110
+ - output audio disabled; transcript text is returned on `content`
111
+
112
+ Realtime models use a one-turn WebSocket call under `.chat()`. In Node, pass a WebSocket constructor through request options:
113
+
114
+ ```typescript
115
+ import WebSocket from 'ws';
116
+ import { ai, axAIOpenAIRealtimeDefaultConfig } from '@ax-llm/ax';
117
+
118
+ const openai = ai({
119
+ name: 'openai',
120
+ apiKey: process.env.OPENAI_APIKEY!,
121
+ config: axAIOpenAIRealtimeDefaultConfig(),
122
+ });
123
+
124
+ const stream = await openai.chat(
125
+ {
126
+ chatPrompt: [{ role: 'user', content: 'Say hello out loud.' }],
127
+ },
128
+ { stream: true, webSocket: WebSocket }
129
+ );
130
+ ```
131
+
132
+ For follow-up turns, keep the assistant audio reference in history:
133
+
134
+ ```typescript
135
+ await openai.chat({
136
+ chatPrompt: [
137
+ { role: 'assistant', audio: { id: previousAudioId } },
138
+ { role: 'user', content: 'Repeat that more slowly.' },
139
+ ],
140
+ });
141
+ ```
142
+
143
+ ## Gemini Live Defaults
144
+
145
+ Use `axAIGoogleGeminiLiveAudioDefaultConfig()` for Gemini native audio:
146
+
147
+ - model: `gemini-2.5-flash-native-audio-preview-12-2025`
148
+ - output enabled
149
+ - voice: `Kore`
150
+ - output format: `pcm16`
151
+ - output sample rate: `24000`
152
+ - input default: `audio/pcm;rate=16000`, mono
153
+ - transcript enabled
154
+ - turn timeout: `30000`
155
+ - streaming disabled by default
156
+
157
+ ```typescript
158
+ import { ai, axAIGoogleGeminiLiveAudioDefaultConfig } from '@ax-llm/ax';
159
+
160
+ const gemini = ai({
161
+ name: 'google-gemini',
162
+ apiKey: process.env.GOOGLE_APIKEY!,
163
+ config: axAIGoogleGeminiLiveAudioDefaultConfig(),
164
+ });
165
+
166
+ const res = await gemini.chat({
167
+ chatPrompt: [
168
+ {
169
+ role: 'user',
170
+ content: [
171
+ { type: 'text', text: 'Answer this spoken question.' },
172
+ {
173
+ type: 'audio',
174
+ data: base64Pcm16,
175
+ format: 'pcm16',
176
+ sampleRate: 16000,
177
+ channels: 1,
178
+ },
179
+ ],
180
+ },
181
+ ],
182
+ });
183
+
184
+ console.log(res.results[0]?.content);
185
+ console.log(res.results[0]?.audio?.data);
186
+ ```
187
+
188
+ Gemini Live uses a one-turn WebSocket call under `.chat()`. It expects PCM input for native audio turns; use `format: 'pcm16'` or `mimeType: 'audio/pcm;rate=16000'`.
189
+
190
+ ## Grok Voice Defaults
191
+
192
+ Use `axAIGrokVoiceDefaultConfig()` for xAI Grok Voice Agent:
193
+
194
+ - model: `grok-voice-think-fast-1.0`
195
+ - output enabled
196
+ - voice: `eve`
197
+ - output format: `pcm16`
198
+ - output sample rate: `24000`
199
+ - input default: `audio/pcm`, mono, 24000 Hz
200
+ - transcript enabled
201
+ - turn timeout: `30000`
202
+ - streaming disabled by default
203
+
204
+ ```typescript
205
+ import WebSocket from 'ws';
206
+ import { ai, axAIGrokVoiceDefaultConfig } from '@ax-llm/ax';
207
+
208
+ const grok = ai({
209
+ name: 'grok',
210
+ apiKey: process.env.GROK_API_KEY!,
211
+ config: axAIGrokVoiceDefaultConfig(),
212
+ });
213
+
214
+ const res = await grok.chat(
215
+ {
216
+ chatPrompt: [{ role: 'user', content: 'Say hello out loud.' }],
217
+ },
218
+ { webSocket: WebSocket }
219
+ );
220
+
221
+ console.log(res.results[0]?.content);
222
+ console.log(res.results[0]?.audio?.data);
223
+ ```
224
+
225
+ Grok Voice uses a one-turn WebSocket call under `.chat()`. It expects PCM input for spoken input turns; use `format: 'pcm16'` or `mimeType: 'audio/pcm'`.
226
+
227
+ ## Streaming Audio
228
+
229
+ OpenAI audio chat, OpenAI Realtime, Gemini Live, and Grok Voice all default to non-streaming, but each can stream deltas when you pass `{ stream: true }`.
230
+
231
+ ```typescript
232
+ const stream = await llm.chat(
233
+ {
234
+ chatPrompt: [{ role: 'user', content: 'Say hello.' }],
235
+ },
236
+ { stream: true }
237
+ );
238
+
239
+ for await (const chunk of stream) {
240
+ const audio = chunk.results[0]?.audio;
241
+ if (audio?.isDelta) {
242
+ playAudioChunk(audio.data);
243
+ }
244
+ }
245
+ ```
246
+
247
+ ## Structured Outputs
248
+
249
+ Do not combine audio output with structured response formats. Audio chat may return a text transcript in `content`, but generated audio bytes live at `result.results[0].audio`.
250
+
251
+ For structured extraction from speech, use a text-only or transcription step first, then pass the transcript into `ax(...)` or `flow(...)`.
package/skills/ax-flow.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: ax-flow
3
3
  description: This skill helps an LLM generate correct AxFlow workflow code using @ax-llm/ax. Use when the user asks about flow(), AxFlow, workflow orchestration, parallel execution, DAG workflows, conditional routing, map/reduce patterns, or multi-node AI pipelines.
4
- version: "21.0.0"
4
+ version: "21.0.3"
5
5
  ---
6
6
 
7
7
  # AxFlow Codegen Rules (@ax-llm/ax)
package/skills/ax-gen.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: ax-gen
3
3
  description: This skill helps an LLM generate correct AxGen code using @ax-llm/ax. Use when the user asks about ax(), AxGen, generators, forward(), streamingForward(), assertions, field processors, step hooks, self-tuning, or structured outputs.
4
- version: "21.0.0"
4
+ version: "21.0.3"
5
5
  ---
6
6
 
7
7
  # AxGen Codegen Rules (@ax-llm/ax)
@@ -393,7 +393,7 @@ gen.getChatLog(): readonly AxChatLogEntry[]
393
393
 
394
394
  ### getUsage()
395
395
 
396
- Returns token usage aggregated by `(ai, model)` across all steps. Reset with `resetUsage()`.
396
+ Returns token usage aggregated by `(ai, model)` across all steps. When a provider reports prompt-cache usage, `promptTokens` is the uncached input portion and `cacheReadTokens` / `cacheCreationTokens` carry the cache counters. Reset with `resetUsage()`.
397
397
 
398
398
  ```typescript
399
399
  const usage = gen.getUsage(); // AxProgramUsage[]
package/skills/ax-gepa.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: ax-gepa
3
3
  description: This skill helps an LLM generate correct AxGEPA optimization code using @ax-llm/ax. Use when the user asks about AxGEPA, GEPA, Pareto optimization, multi-objective prompt tuning, reflective prompt evolution, validationExamples, maxMetricCalls, or optimizing a generator, flow, or agent tree.
4
- version: "21.0.0"
4
+ version: "21.0.3"
5
5
  ---
6
6
 
7
7
  # AxGEPA Codegen Rules (@ax-llm/ax)
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: ax-learn
3
3
  description: This skill helps an LLM generate correct AxLearn code using @ax-llm/ax. Use when the user asks about self-improving agents, trace-backed learning, feedback-aware updates, or AxLearn modes.
4
- version: "21.0.0"
4
+ version: "21.0.3"
5
5
  ---
6
6
 
7
7
  # AxLearn Codegen Rules (@ax-llm/ax)
package/skills/ax-llm.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- name: ax
2
+ name: ax-llm
3
3
  description: This skill helps with using the @ax-llm/ax TypeScript library for building LLM applications. Use when the user asks about ax(), ai(), f(), s(), agent(), flow(), AxGen, AxAgent, AxFlow, signatures, streaming, or mentions @ax-llm/ax.
4
- version: "21.0.0"
4
+ version: "21.0.3"
5
5
  ---
6
6
 
7
7
  # Ax Library (@ax-llm/ax) Quick Reference
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: ax-signature
3
3
  description: This skill helps an LLM generate correct DSPy signature code using @ax-llm/ax. Use when the user asks about signatures, s(), f(), field types, string syntax, fluent builder API, validation constraints, or type-safe inputs/outputs.
4
- version: "21.0.0"
4
+ version: "21.0.3"
5
5
  ---
6
6
 
7
7
  # Ax Signature Reference
@@ -22,6 +22,8 @@ version: "21.0.0"
22
22
  | JSON | `:json` | `any` | `metadata:json` |
23
23
  | Date | `:date` | `Date` | `birthDate:date` |
24
24
  | DateTime | `:datetime` | `Date` | `timestamp:datetime` |
25
+ | DateRange | `:dateRange` | `{ start: Date; end: Date }` | `travelDates:dateRange` |
26
+ | DateTimeRange | `:datetimeRange` | `{ start: Date; end: Date }` | `meetingWindow:datetimeRange` |
25
27
  | Image | `:image` | `{mimeType, data}` | `photo:image` (input only) |
26
28
  | Audio | `:audio` | `{format?, data}` | `recording:audio` (input only) |
27
29
  | File | `:file` | `{mimeType, data}` | `document:file` (input only) |
@@ -29,6 +31,8 @@ version: "21.0.0"
29
31
  | Code | `:code` | `string` | `pythonScript:code` |
30
32
  | Class | `:class "a, b, c"` | `"a" \| "b" \| "c"` | `mood:class "happy, sad"` |
31
33
 
34
+ Date, datetime, and range fields are AI-friendly but strict. They accept ISO-style values, trim minor whitespace/casing issues, and parse ranges as `{ "start": "...", "end": "..." }`, `[start, end]`, `start/end`, or natural delimiters like `start to end`; invalid values and reversed ranges should fail validation rather than being silently autocorrected.
35
+
32
36
  ## Arrays, Optional, and Internal Fields
33
37
 
34
38
  ```typescript
@@ -177,7 +181,7 @@ const sig = s('base:string -> result:string')
177
181
  Type creators:
178
182
  - `f.string(desc)`, `f.number(desc)`, `f.boolean(desc)`, `f.json(desc)`
179
183
  - `f.image(desc)`, `f.audio(desc)`, `f.file(desc)`, `f.url(desc)`
180
- - `f.email(desc)`, `f.date(desc)`, `f.datetime(desc)`
184
+ - `f.email(desc)`, `f.date(desc)`, `f.datetime(desc)`, `f.dateRange(desc)`, `f.datetimeRange(desc)`
181
185
  - `f.class(['a','b','c'], desc)`, `f.code(desc)`
182
186
  - `f.object({ field: f.string() }, desc)`
183
187
 
@@ -283,7 +287,7 @@ Bad: `text`, `data`, `input`, `output`, `a`, `x`, `val` (too generic), `1field`
283
287
  - `.internal()` / `{ internal: true }` is output-only (for chain-of-thought reasoning).
284
288
  - `.cache()` / `{ cache: true }` is input-only (for prompt caching).
285
289
  - Validation errors trigger auto-retry with correction feedback.
286
- - `f.email()`, `f.url()`, `f.date()`, `f.datetime()` are shorthand for `f.string().email()` etc.
290
+ - `f.email()`, `f.url()`, `f.date()`, `f.datetime()` are shorthand for `f.string().email()` etc.; `f.dateRange()` and `f.datetimeRange()` return `{ start: Date; end: Date }`.
287
291
  - `z.enum()` maps to ax's `class` type — only valid on **output** fields.
288
292
  - For multimodal inputs (images, audio, files) use `f.image()` / `f.audio()` / `f.file()` — zod has no equivalent.
289
293