@kuralle-agents/core 0.3.0 → 0.3.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.
@@ -61,6 +61,15 @@ async function dispatchNode(node, run, driver, ctx) {
61
61
  if (!driver.runStructured) {
62
62
  throw new Error('ChannelDriver.runStructured is required for decide nodes');
63
63
  }
64
+ // On resume, the new turn's input is buffered as pending and is not yet in
65
+ // the message history the decision reads. Consume it first (mirrors the
66
+ // collect path) so the decision sees the user's actual reply instead of
67
+ // stale context — without this, a multi-turn flow stalls at the first
68
+ // interactive decide because the reply never reaches `decide()`.
69
+ if (hasPendingUserInput(ctx.session)) {
70
+ const signal = await driver.awaitUser(ctx);
71
+ appendUserMessage(run, signal.input);
72
+ }
64
73
  const structured = await driver.runStructured(node, ctx);
65
74
  return normalizeTransition(await node.decide(structured, run.state));
66
75
  }
@@ -127,8 +127,17 @@ export class TextDriver {
127
127
  return out;
128
128
  }
129
129
  async runStructured(node, ctx) {
130
- const system = resolveInstructions(node.instructions, ctx.runState.state);
130
+ const base = resolveInstructions(node.instructions, ctx.runState.state);
131
131
  const schema = node.schema;
132
+ // When the node offers choices (e.g. via withChoices), constrain the model
133
+ // to return exactly one option id. Otherwise an unconstrained string schema
134
+ // lets the model reply with free-form prose that `decide()` can't match,
135
+ // stalling the flow at every interactive node.
136
+ const system = node.choices?.length
137
+ ? `${base}\n\nYou MUST pick exactly ONE option by its id. Valid ids: ${node.choices
138
+ .map((c) => c.id)
139
+ .join(', ')}. Respond with only the chosen id, nothing else.`
140
+ : base;
132
141
  const { object } = await generateObject({
133
142
  model: ctx.model,
134
143
  schema,
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "url": "git+https://github.com/kuralle/kuralle-agents.git",
7
7
  "directory": "packages/kuralle-core"
8
8
  },
9
- "version": "0.3.0",
9
+ "version": "0.3.1",
10
10
  "description": "A framework for structured conversational AI agents",
11
11
  "publishConfig": {
12
12
  "access": "public"
@@ -97,7 +97,7 @@
97
97
  "dotenv": "^16.4.0",
98
98
  "typescript": "^5.3.0",
99
99
  "zod": "^3.23.0",
100
- "@kuralle-agents/realtime-audio": "0.3.0"
100
+ "@kuralle-agents/realtime-audio": "0.3.1"
101
101
  },
102
102
  "dependencies": {
103
103
  "chrono-node": "^2.6.0",