dialai 1.5.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/.claude/specs/poll-gate.md +269 -0
  2. package/dist/dialai/asl/choice-extractor.d.ts +60 -0
  3. package/dist/dialai/asl/choice-extractor.d.ts.map +1 -0
  4. package/dist/dialai/asl/choice-extractor.js +131 -0
  5. package/dist/dialai/asl/choice-extractor.js.map +1 -0
  6. package/dist/dialai/asl/index.d.ts +6 -0
  7. package/dist/dialai/asl/index.d.ts.map +1 -0
  8. package/dist/dialai/asl/index.js +9 -0
  9. package/dist/dialai/asl/index.js.map +1 -0
  10. package/dist/dialai/asl/interpreter.d.ts +6 -0
  11. package/dist/dialai/asl/interpreter.d.ts.map +1 -0
  12. package/dist/dialai/asl/interpreter.js +260 -0
  13. package/dist/dialai/asl/interpreter.js.map +1 -0
  14. package/dist/dialai/asl/jsonpath.d.ts +34 -0
  15. package/dist/dialai/asl/jsonpath.d.ts.map +1 -0
  16. package/dist/dialai/asl/jsonpath.js +229 -0
  17. package/dist/dialai/asl/jsonpath.js.map +1 -0
  18. package/dist/dialai/asl/types.d.ts +45 -0
  19. package/dist/dialai/asl/types.d.ts.map +1 -0
  20. package/dist/dialai/asl/types.js +2 -0
  21. package/dist/dialai/asl/types.js.map +1 -0
  22. package/dist/dialai/asl/validator.d.ts +17 -0
  23. package/dist/dialai/asl/validator.d.ts.map +1 -0
  24. package/dist/dialai/asl/validator.js +75 -0
  25. package/dist/dialai/asl/validator.js.map +1 -0
  26. package/dist/dialai/cli.js +0 -0
  27. package/dist/dialai/docs-loader.d.ts +6 -0
  28. package/dist/dialai/docs-loader.d.ts.map +1 -0
  29. package/dist/dialai/docs-loader.js +63 -0
  30. package/dist/dialai/docs-loader.js.map +1 -0
  31. package/dist/dialai/gate.d.ts +44 -0
  32. package/dist/dialai/gate.d.ts.map +1 -0
  33. package/dist/dialai/gate.js +169 -0
  34. package/dist/dialai/gate.js.map +1 -0
  35. package/dist/dialai/llm.d.ts.map +1 -1
  36. package/dist/dialai/llm.js +11 -2
  37. package/dist/dialai/llm.js.map +1 -1
  38. package/dist/dialai/mcp.js +0 -0
  39. package/dist/dialai/migrations/002-users-credits.d.ts +5 -0
  40. package/dist/dialai/migrations/002-users-credits.d.ts.map +1 -0
  41. package/dist/dialai/migrations/002-users-credits.js +30 -0
  42. package/dist/dialai/migrations/002-users-credits.js.map +1 -0
  43. package/dist/dialai/migrations/004-rename-round-to-evaluation.d.ts +8 -0
  44. package/dist/dialai/migrations/004-rename-round-to-evaluation.d.ts.map +1 -0
  45. package/dist/dialai/migrations/004-rename-round-to-evaluation.js +63 -0
  46. package/dist/dialai/migrations/004-rename-round-to-evaluation.js.map +1 -0
  47. package/package.json +1 -1
@@ -0,0 +1,269 @@
1
+ # Poll Gate Spec
2
+
3
+ A poll is a gate that fans a question out to N diverse LLM models, collects their answers, and uses an arbiter to summarize consensus. The gate is the reusable infrastructure — which models, what judge, what threshold. Each question is just another invocation of that gate.
4
+
5
+ ```typescript
6
+ // Create the gate once — this is the HOW
7
+ await createGate({
8
+ gateId: "10-model-poll",
9
+ prompt: "Answer the following question accurately and concisely.",
10
+ transitions: { resolved: "Consensus answer found" },
11
+ specialists: [
12
+ { specialistId: "claude-sonnet", role: "proposer", modelId: "anthropic/claude-sonnet-4-20250514" },
13
+ { specialistId: "gpt-4o", role: "proposer", modelId: "openai/gpt-4o" },
14
+ { specialistId: "gemini-flash", role: "proposer", modelId: "google/gemini-2.0-flash-001" },
15
+ { specialistId: "llama-70b", role: "proposer", modelId: "meta-llama/llama-3.1-70b-instruct" },
16
+ { specialistId: "mistral-large", role: "proposer", modelId: "mistralai/mistral-large-2411" },
17
+ { specialistId: "deepseek-v3", role: "proposer", modelId: "deepseek/deepseek-chat-v3-0324" },
18
+ { specialistId: "qwen-72b", role: "proposer", modelId: "qwen/qwen-2.5-72b-instruct" },
19
+ { specialistId: "cohere-r-plus", role: "proposer", modelId: "cohere/command-r-plus-08-2024" },
20
+ { specialistId: "claude-haiku", role: "proposer", modelId: "anthropic/claude-haiku-4-5-20251001" },
21
+ { specialistId: "gpt-4o-mini", role: "proposer", modelId: "openai/gpt-4o-mini" },
22
+ { specialistId: "judge", role: "arbiter" }
23
+ ],
24
+ consensusThreshold: 0.5,
25
+ });
26
+
27
+ // Ask questions — each is an invocation of the same gate
28
+ const r1 = await invokeGate("10-model-poll", { promptSuffix: "Who won the 2025 World Series?" });
29
+ const r2 = await invokeGate("10-model-poll", { promptSuffix: "What is the capital of Australia?" });
30
+ // r1.reasoning → "7/10 said Dodgers because X, 3/10 said Yankees because Y"
31
+ ```
32
+
33
+ ## How It Maps to DIAL 1.5
34
+
35
+ Built entirely from existing primitives. No engine, strategy, or store changes.
36
+
37
+ | Poll concept | DIAL 1.5 primitive |
38
+ |---|---|
39
+ | Gate definition | `MachineDefinition` (synthetic 2-state machine) |
40
+ | Gate identity (`gateId`) | `machineName` — scopes alignment + exemplars |
41
+ | Invoking a gate | `createSession` + `submitProposal` × N + `submitArbitration` |
42
+ | A question | `promptSuffix` appended to gate prompt |
43
+ | An evaluation | A session with one round |
44
+ | Each model's answer | `submitProposal({ sessionId, specialistId })` |
45
+ | The judge | `submitArbitration({ sessionId })` via custom `strategyFn` |
46
+ | Human correction | `submitArbitration({ sessionId, specialistId: human, transitionName })` |
47
+ | Learning | Alignment + exemplars accumulate under `gateId` across all questions |
48
+
49
+ The synthetic machine has two states:
50
+
51
+ ```
52
+ evaluate ──resolved──▶ done
53
+ ```
54
+
55
+ Every proposer picks `resolved` (there's only one transition). Their answer goes in `reasoning`. The arbiter reads all proposals' reasoning and determines consensus.
56
+
57
+ ## What Gets Built
58
+
59
+ ### New file: `src/dialai/gate.ts`
60
+
61
+ Two functions. Everything else is reused.
62
+
63
+ #### `createGate(definition: GateDefinition): GateDefinition`
64
+
65
+ Stores the gate definition in an in-memory registry (Map). Returns the definition. Phase 2 moves this to the store.
66
+
67
+ #### `invokeGate(gateId, context, runtimeSpecialists?): GateResult`
68
+
69
+ 1. Look up gate definition from registry.
70
+ 2. Build synthetic `MachineDefinition`:
71
+ - `machineName` = `gateId` (so alignment/exemplars scope to gate)
72
+ - `initialState` = `"evaluate"`, `goalState` = `"done"`
73
+ - `evaluate` state: prompt = `gate.prompt + context.promptSuffix`, transitions all target `"done"`, specialists from gate definition, threshold from gate
74
+ - `done` state: empty (terminal)
75
+ 3. `createSession(machine, context.metaJson)` — session persisted in store.
76
+ 4. Register specialists:
77
+ - From `runtimeSpecialists` if provided (for function refs that can't serialize).
78
+ - From `gate.specialists` (strategyFnName-based auto-registration, same as `runSession` does).
79
+ - Defaults (`firstAvailable` proposer + `firstProposal` arbiter) if none.
80
+ 5. `Promise.all` → all proposers invoked concurrently via `submitProposal`.
81
+ 6. `submitArbitration({ sessionId })` — arbiter evaluates all proposals.
82
+ 7. Return `GateResult`.
83
+
84
+ ### New types in `types.ts`
85
+
86
+ ```typescript
87
+ interface GateDefinition {
88
+ gateId: string;
89
+ prompt?: string;
90
+ transitions: Record<string, string | TransitionDefinition>;
91
+ specialists?: SpecialistDefinition[];
92
+ consensusThreshold?: number;
93
+ }
94
+
95
+ interface GateContext {
96
+ metaJson?: Record<string, unknown>;
97
+ history?: TransitionRecord[];
98
+ promptSuffix?: string;
99
+ }
100
+
101
+ interface GateResult {
102
+ evaluationId: string;
103
+ gateId: string;
104
+ transitionName: string | null;
105
+ reasoning: string;
106
+ needsHuman: boolean;
107
+ proposals: Proposal[];
108
+ metaJson?: Record<string, unknown>;
109
+ costUSD?: number;
110
+ latencyMsec?: number;
111
+ }
112
+ ```
113
+
114
+ All field types are existing DIAL types. Three types total.
115
+
116
+ ### Registry helpers
117
+
118
+ ```typescript
119
+ createGate(definition: GateDefinition): GateDefinition
120
+ getGate(gateId: string): GateDefinition
121
+ listGates(): GateDefinition[]
122
+ deleteGate(gateId: string): void
123
+ clearGateRegistry(): void
124
+ ```
125
+
126
+ In-memory Map for Phase 1. Phase 2 adds store persistence.
127
+
128
+ ### Exports in `index.ts`
129
+
130
+ ```typescript
131
+ export type { GateDefinition, GateContext, GateResult } from "./types.js";
132
+ export { createGate, getGate, listGates, deleteGate, clearGateRegistry, invokeGate } from "./gate.js";
133
+ ```
134
+
135
+ ## The LLM-as-Judge Arbiter
136
+
137
+ The judge is a custom `strategyFn` on the arbiter — no framework changes needed. The consumer provides it via `runtimeSpecialists`:
138
+
139
+ ```typescript
140
+ const result = await invokeGate("10-model-poll", {
141
+ promptSuffix: "Who won the 2025 World Series?"
142
+ }, {
143
+ arbiter: {
144
+ specialistId: "judge",
145
+ machineName: "10-model-poll",
146
+ strategyFn: async (ctx: ArbiterContext): Promise<ArbiterStrategyResult> => {
147
+ const responses = ctx.proposals.map((p, i) =>
148
+ `Model ${i + 1} (${p.specialistId}): ${p.reasoning}`
149
+ ).join("\n\n");
150
+
151
+ const { content } = await callLlm(
152
+ "anthropic/claude-sonnet-4-20250514",
153
+ "You are a consensus judge. Read all model responses to a question. " +
154
+ "Determine if there is meaningful agreement. " +
155
+ "Respond with JSON: { \"consensusReached\": true/false, " +
156
+ "\"winningProposalId\": \"<proposalId of best response>\", " +
157
+ "\"reasoning\": \"<narrative: how many agreed, what they said, why>\" }",
158
+ `Question: ${ctx.prompt}\n\n${ctx.proposals.length} models responded:\n\n${responses}`
159
+ );
160
+
161
+ const parsed = JSON.parse(content);
162
+ return {
163
+ consensusReached: parsed.consensusReached,
164
+ winningProposalId: parsed.winningProposalId,
165
+ reasoning: parsed.reasoning,
166
+ };
167
+ },
168
+ },
169
+ });
170
+ ```
171
+
172
+ The judge reads all N proposals, clusters the answers semantically ("LA Dodgers" = "The Dodgers" = "Los Angeles Dodgers"), produces a narrative summary ("7/10 said Dodgers because they won in 5 games, 2 said Yankees, 1 said Mets"), and picks the best-articulated winning response.
173
+
174
+ This is a regular custom arbiter. The DIAL framework doesn't need to know it's backed by an LLM.
175
+
176
+ ## How a Question Flows Through
177
+
178
+ ```
179
+ 1. Consumer calls: invokeGate("10-model-poll", { promptSuffix: "Who won the 2025 WS?" })
180
+
181
+ 2. invokeGate builds synthetic machine:
182
+ machineName: "10-model-poll"
183
+ states:
184
+ evaluate:
185
+ prompt: "Answer the following question accurately and concisely.\n\nWho won the 2025 WS?"
186
+ transitions: { resolved: { target: "done", description: "Consensus answer found" } }
187
+ done: {}
188
+
189
+ 3. createSession("10-model-poll", {}) → session with sessionId + roundId
190
+
191
+ 4. Register 10 proposers + 1 arbiter under machineName "10-model-poll"
192
+
193
+ 5. Promise.all → 10 concurrent submitProposal calls
194
+ Each proposer:
195
+ - Gets ProposerContext with prompt, transitions: { resolved → done }, exemplars
196
+ - LLM mode: contextFn builds context → callLlm → parses response
197
+ - Returns { transitionName: "resolved", toState: "done", reasoning: "The LA Dodgers won..." }
198
+ - Stored as Proposal in the round
199
+
200
+ 6. submitArbitration({ sessionId })
201
+ - Loads all 10 proposals
202
+ - Calls judge arbiter strategyFn
203
+ - Judge LLM reads all 10 answers, determines consensus
204
+ - Returns { consensusReached: true, winningProposalId: "...", reasoning: "7/10 said Dodgers..." }
205
+ - If consensus: executes transition, session moves to "done"
206
+ - If no consensus: returns needsHuman
207
+
208
+ 7. GateResult returned:
209
+ { evaluationId, gateId: "10-model-poll", transitionName: "resolved",
210
+ reasoning: "7/10 said Dodgers...", needsHuman: false,
211
+ proposals: [all 10] }
212
+ ```
213
+
214
+ ## Human Override
215
+
216
+ When the judge says `needsHuman` (or a human disagrees with the consensus), the consumer can call `submitArbitration` directly on the session (the `evaluationId` in `GateResult` maps to the underlying `sessionId`):
217
+
218
+ ```typescript
219
+ const result = await invokeGate("10-model-poll", { promptSuffix: "Who won the 2025 WS?" });
220
+
221
+ if (result.needsHuman) {
222
+ // Register a human specialist (once)
223
+ await registerProposer({
224
+ specialistId: "human-reviewer",
225
+ machineName: "10-model-poll",
226
+ isHuman: true,
227
+ strategyFnName: "firstAvailable",
228
+ });
229
+
230
+ // Human forces the answer using the evaluationId as sessionId
231
+ await submitArbitration({
232
+ sessionId: result.evaluationId,
233
+ specialistId: "human-reviewer",
234
+ transitionName: "resolved",
235
+ reasoning: "The correct answer is the LA Dodgers. They won in 5 games against the Yankees.",
236
+ });
237
+ }
238
+ ```
239
+
240
+ This triggers the standard DIAL learning cycle:
241
+ - Alignment updated for all 10 proposers (did they agree with the human?)
242
+ - Exemplar captured (question context + all proposals + human's answer)
243
+ - Future invocations include this exemplar as a few-shot example
244
+
245
+ Over time, the gate collapses: models that consistently agree with humans earn high alignment, the arbiter's job gets easier, and eventually a champion model handles questions autonomously.
246
+
247
+ ## What Doesn't Change
248
+
249
+ Nothing. The gate is built entirely from existing DIAL 1.5 primitives:
250
+
251
+ - `createSession` / `submitProposal` / `submitArbitration` — unchanged
252
+ - `registerProposer` / `registerArbiter` — unchanged
253
+ - Alignment tracking — unchanged (scoped by `machineName` = `gateId`)
254
+ - Exemplar system — unchanged (scoped by `machineName` = `gateId`)
255
+ - Store interface — unchanged
256
+ - Engine / tick loop — not used (gates use `Promise.all` for parallel fan-out)
257
+ - LLM integration — unchanged (proposers use `contextFn + modelId`, judge uses `callLlm` inside a `strategyFn`)
258
+ - Strategies — unchanged (consumer provides custom `strategyFn` for the judge)
259
+
260
+ ## Files Touched
261
+
262
+ | File | Change |
263
+ |---|---|
264
+ | `src/dialai/types.ts` | Add 3 types: `GateDefinition`, `GateContext`, `GateResult` |
265
+ | `src/dialai/gate.ts` | **New file** — `createGate`, `invokeGate`, registry helpers |
266
+ | `src/dialai/index.ts` | Export new types + gate functions |
267
+ | `tests/unit/gate.test.ts` | Gate tests |
268
+
269
+ Zero changes to `api.ts`, `engine.ts`, `llm.ts`, `strategies.ts`, `store.ts`, `alignment.ts`, `exemplars.ts`.
@@ -0,0 +1,60 @@
1
+ import type { TransitionOption } from "./types.js";
2
+ interface ChoiceRule {
3
+ Variable?: string;
4
+ StringEquals?: string;
5
+ StringEqualsPath?: string;
6
+ StringLessThan?: string;
7
+ StringLessThanPath?: string;
8
+ StringGreaterThan?: string;
9
+ StringGreaterThanPath?: string;
10
+ StringLessThanEquals?: string;
11
+ StringLessThanEqualsPath?: string;
12
+ StringGreaterThanEquals?: string;
13
+ StringGreaterThanEqualsPath?: string;
14
+ StringMatches?: string;
15
+ NumericEquals?: number;
16
+ NumericEqualsPath?: string;
17
+ NumericLessThan?: number;
18
+ NumericLessThanPath?: string;
19
+ NumericGreaterThan?: number;
20
+ NumericGreaterThanPath?: string;
21
+ NumericLessThanEquals?: number;
22
+ NumericLessThanEqualsPath?: string;
23
+ NumericGreaterThanEquals?: number;
24
+ NumericGreaterThanEqualsPath?: string;
25
+ BooleanEquals?: boolean;
26
+ BooleanEqualsPath?: string;
27
+ TimestampEquals?: string;
28
+ TimestampEqualsPath?: string;
29
+ TimestampLessThan?: string;
30
+ TimestampLessThanPath?: string;
31
+ TimestampGreaterThan?: string;
32
+ TimestampGreaterThanPath?: string;
33
+ TimestampLessThanEquals?: string;
34
+ TimestampLessThanEqualsPath?: string;
35
+ TimestampGreaterThanEquals?: string;
36
+ TimestampGreaterThanEqualsPath?: string;
37
+ IsNull?: boolean;
38
+ IsPresent?: boolean;
39
+ IsNumeric?: boolean;
40
+ IsString?: boolean;
41
+ IsBoolean?: boolean;
42
+ IsTimestamp?: boolean;
43
+ And?: ChoiceRule[];
44
+ Or?: ChoiceRule[];
45
+ Not?: ChoiceRule;
46
+ Next?: string;
47
+ }
48
+ interface ChoiceState {
49
+ Type: "Choice";
50
+ Comment?: string;
51
+ Choices: ChoiceRule[];
52
+ Default?: string;
53
+ }
54
+ /**
55
+ * Extract transition options from a Choice state.
56
+ * For $.transition StringEquals rules, uses the value as the transition name.
57
+ */
58
+ export declare function extractTransitions(choiceState: ChoiceState): TransitionOption[];
59
+ export {};
60
+ //# sourceMappingURL=choice-extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"choice-extractor.d.ts","sourceRoot":"","sources":["../../../src/dialai/asl/choice-extractor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEpE,UAAU,UAAU;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,4BAA4B,CAAC,EAAE,MAAM,CAAC;IACtC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,GAAG,CAAC,EAAE,UAAU,EAAE,CAAC;IACnB,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC;IAClB,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,WAAW,GAAG,gBAAgB,EAAE,CA0B/E"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Extract transition options from a Choice state.
3
+ * For $.transition StringEquals rules, uses the value as the transition name.
4
+ */
5
+ export function extractTransitions(choiceState) {
6
+ const transitions = [];
7
+ for (const rule of choiceState.Choices) {
8
+ const condition = extractCondition(rule);
9
+ const name = deriveTransitionName(rule, condition);
10
+ if (rule.Next) {
11
+ transitions.push({
12
+ name,
13
+ targetState: rule.Next,
14
+ condition,
15
+ });
16
+ }
17
+ }
18
+ // Add Default as a fallback option
19
+ if (choiceState.Default) {
20
+ transitions.push({
21
+ name: "default",
22
+ targetState: choiceState.Default,
23
+ condition: { operator: "default" },
24
+ });
25
+ }
26
+ return transitions;
27
+ }
28
+ /**
29
+ * Derive a human-readable transition name from the rule.
30
+ * For $.transition StringEquals, use the value.
31
+ * Otherwise, generate a descriptive name.
32
+ */
33
+ function deriveTransitionName(rule, condition) {
34
+ // Special case: $.transition StringEquals "value" -> use "value" as name
35
+ if (rule.Variable === "$.transition" &&
36
+ rule.StringEquals !== undefined) {
37
+ return rule.StringEquals;
38
+ }
39
+ // For compound rules, try to find a $.transition StringEquals in children
40
+ if (condition.children) {
41
+ for (const child of condition.children) {
42
+ if (child.variable === "$.transition" &&
43
+ child.operator === "StringEquals" &&
44
+ typeof child.value === "string") {
45
+ return child.value;
46
+ }
47
+ }
48
+ }
49
+ // Generate name from condition
50
+ if (condition.variable && condition.value !== undefined) {
51
+ return `${condition.operator}_${String(condition.value)}`;
52
+ }
53
+ return `to_${rule.Next}`;
54
+ }
55
+ /**
56
+ * Extract a ChoiceCondition from a rule.
57
+ */
58
+ function extractCondition(rule) {
59
+ // Compound rules
60
+ if (rule.And) {
61
+ return {
62
+ operator: "And",
63
+ children: rule.And.map(extractCondition),
64
+ };
65
+ }
66
+ if (rule.Or) {
67
+ return {
68
+ operator: "Or",
69
+ children: rule.Or.map(extractCondition),
70
+ };
71
+ }
72
+ if (rule.Not) {
73
+ return {
74
+ operator: "Not",
75
+ children: [extractCondition(rule.Not)],
76
+ };
77
+ }
78
+ // Simple comparison operators
79
+ const operators = [
80
+ "StringEquals",
81
+ "StringEqualsPath",
82
+ "StringLessThan",
83
+ "StringLessThanPath",
84
+ "StringGreaterThan",
85
+ "StringGreaterThanPath",
86
+ "StringLessThanEquals",
87
+ "StringLessThanEqualsPath",
88
+ "StringGreaterThanEquals",
89
+ "StringGreaterThanEqualsPath",
90
+ "StringMatches",
91
+ "NumericEquals",
92
+ "NumericEqualsPath",
93
+ "NumericLessThan",
94
+ "NumericLessThanPath",
95
+ "NumericGreaterThan",
96
+ "NumericGreaterThanPath",
97
+ "NumericLessThanEquals",
98
+ "NumericLessThanEqualsPath",
99
+ "NumericGreaterThanEquals",
100
+ "NumericGreaterThanEqualsPath",
101
+ "BooleanEquals",
102
+ "BooleanEqualsPath",
103
+ "TimestampEquals",
104
+ "TimestampEqualsPath",
105
+ "TimestampLessThan",
106
+ "TimestampLessThanPath",
107
+ "TimestampGreaterThan",
108
+ "TimestampGreaterThanPath",
109
+ "TimestampLessThanEquals",
110
+ "TimestampLessThanEqualsPath",
111
+ "TimestampGreaterThanEquals",
112
+ "TimestampGreaterThanEqualsPath",
113
+ "IsNull",
114
+ "IsPresent",
115
+ "IsNumeric",
116
+ "IsString",
117
+ "IsBoolean",
118
+ "IsTimestamp",
119
+ ];
120
+ for (const op of operators) {
121
+ if (rule[op] !== undefined) {
122
+ return {
123
+ variable: rule.Variable,
124
+ operator: op,
125
+ value: rule[op],
126
+ };
127
+ }
128
+ }
129
+ return { operator: "unknown" };
130
+ }
131
+ //# sourceMappingURL=choice-extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"choice-extractor.js","sourceRoot":"","sources":["../../../src/dialai/asl/choice-extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export type { DIALStateMachine, StateResult, TransitionOption, ChoiceCondition, TaskHandler, InterpreterConfig, ExecutionContext, } from "./types.js";
2
+ export { validateDIALStateMachine, parseDIALStateMachine, type ValidationResult, } from "./validator.js";
3
+ export { extractTransitions } from "./choice-extractor.js";
4
+ export { executeState } from "./interpreter.js";
5
+ export { getJsonPathValue, setJsonPathValue, applyInputPath, applyOutputPath, applyResultPath, applyParameters, applyResultSelector, } from "./jsonpath.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/dialai/asl/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAG3D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGhD,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,eAAe,EACf,eAAe,EACf,mBAAmB,GACpB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,9 @@
1
+ // Validator
2
+ export { validateDIALStateMachine, parseDIALStateMachine, } from "./validator.js";
3
+ // Choice extractor
4
+ export { extractTransitions } from "./choice-extractor.js";
5
+ // Interpreter
6
+ export { executeState } from "./interpreter.js";
7
+ // JSONPath utilities
8
+ export { getJsonPathValue, setJsonPathValue, applyInputPath, applyOutputPath, applyResultPath, applyParameters, applyResultSelector, } from "./jsonpath.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/dialai/asl/index.ts"],"names":[],"mappings":"AAWA,YAAY;AACZ,OAAO,EACL,wBAAwB,EACxB,qBAAqB,GAEtB,MAAM,gBAAgB,CAAC;AAExB,mBAAmB;AACnB,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D,cAAc;AACd,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD,qBAAqB;AACrB,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,eAAe,EACf,eAAe,EACf,mBAAmB,GACpB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { DIALStateMachine, StateResult, InterpreterConfig, ExecutionContext } from "./types.js";
2
+ /**
3
+ * Execute a single state in the state machine.
4
+ */
5
+ export declare function executeState(machine: DIALStateMachine, stateName: string, context: ExecutionContext, config?: InterpreterConfig): Promise<StateResult>;
6
+ //# sourceMappingURL=interpreter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interpreter.d.ts","sourceRoot":"","sources":["../../../src/dialai/asl/interpreter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAsCpB;;GAEG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,gBAAgB,EACzB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,gBAAgB,EACzB,MAAM,GAAE,iBAAsB,GAC7B,OAAO,CAAC,WAAW,CAAC,CA0BtB"}