Repository navigation
v1.4.0
DIAL 1.4.0
Migration Guide
ProposerContext.transitions changed from Record<string, string> to Record<string, TransitionDefinition>. If you have a custom strategyFn that reads transition targets, update every access:
// Before (1.3.x)
const toState = ctx.transitions[name];
// After (1.4.0)
const toState = ctx.transitions[name].target;Machine definitions are not affected — the shorthand form { close: "closed" } still works everywhere. normalizeMachine converts it to { close: { target: "closed" } } internally.
New
-
TransitionDefinitiontype — transitions can now carrydescriptionandparametersalongsidetarget. Import it:import type { TransitionDefinition } from "dialai". When a transition hasdescriptionorparameters, DIAL automatically builds OpenAI-compatible tool definitions and uses native function calling.const machine = { machineName: "booking", initialState: "idle", goalState: "booked", states: { idle: { prompt: "Book a ride for the user", transitions: { book_ride: { target: "booked", description: "Book a ride to the destination", parameters: { type: "object", properties: { destination: { type: "string" }, rideType: { type: "string", enum: ["standard", "premium"] }, }, required: ["destination"], }, }, }, }, booked: {}, }, };
-
callLlmWithTools(modelId, systemMessage, userMessage, tools, auditContext?)— new function that sends OpenAI-compatible tool definitions to an LLM endpoint. Returns aToolCallResultwithname,arguments, andreasoning. ThrowsNoToolCallErrorif the model responds with text instead of a tool call.callLlmis completely unchanged. -
buildToolsFromTransitions(transitions)— convertsRecord<string, TransitionDefinition>into an array of OpenAI tool definitions. Returnsnullif no transitions havedescriptionorparameters(i.e., all are plain shorthand). -
NoToolCallError— thrown bycallLlmWithToolswhen the model returns text instead of a tool call. Hascontent(the text response) andusagefields. -
parseModelId(raw)— parsesmodelId[tools=no]syntax. Returns{ modelId, useTools }. Use[tools=no]suffix to skip the tool-calling attempt for models that don't support tools:await registerProposer({ specialistId: "legacy-model", machineName: "booking", modelId: "some-model[tools=no]", strategyFnName: "firstAvailable", });
-
executeProposerLlmtool-calling path — when transitions havedescription/parametersand the model is not opted out via[tools=no],executeProposerLlmnow triescallLlmWithToolsfirst. If the model returns a tool call, the function name maps totransitionNameand parsed arguments land inProposerStrategyResult.metaJson. OnNoToolCallError, it attempts to parse the text as DIAL JSON; if that fails, it falls back to the existingcallLlmtext path. HTTP errors re-throw without fallback.
Changes
-
ProposerContext.transitionsis nowRecord<string, TransitionDefinition>(wasRecord<string, string>). Every customstrategyFnthat readsctx.transitions[name]must add.target. Search your codebase forctx.transitionsin anystrategyFncallback. -
ProposerStrategyResult.metaJson— tool call arguments are automatically placed here. If you already returnmetaJsonfrom a custom strategy, no change needed. If you passmetaJsoninsubmitProposalopts AND the strategy also returnsmetaJson, the opts value takes precedence. -
submitProposalnow mergesmetaJsonfrom the strategy result into the proposal when the caller does not providemetaJsonin opts.