@kuralle-agents/core 0.13.0 → 0.14.0
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/README.md +4 -4
- package/dist/ai-sdk/uiMessageStream.d.ts +2 -2
- package/dist/ai-sdk/uiMessageStream.js +42 -29
- package/dist/capabilities/LivePromptAssembler.d.ts +1 -1
- package/dist/capabilities/LivePromptAssembler.js +1 -1
- package/dist/capabilities/index.d.ts +1 -1
- package/dist/eval/EvalRunner.js +4 -4
- package/dist/eval/simulation.js +4 -3
- package/dist/events/TurnHandle.d.ts +3 -3
- package/dist/flow/collectUntilComplete.js +4 -4
- package/dist/flow/degrade.js +8 -4
- package/dist/flow/emitInteractive.d.ts +2 -2
- package/dist/flow/emitInteractive.js +6 -3
- package/dist/flow/extraction.d.ts +2 -2
- package/dist/flow/extraction.js +10 -4
- package/dist/flow/reduceTransition.d.ts +2 -2
- package/dist/flow/reduceTransition.js +7 -3
- package/dist/flow/runFlow.js +34 -12
- package/dist/foundation/AgentStateController.d.ts +1 -1
- package/dist/foundation/ToolExecutor.d.ts +2 -2
- package/dist/foundation/index.d.ts +0 -11
- package/dist/foundation/index.js +0 -5
- package/dist/index.d.ts +9 -14
- package/dist/index.js +5 -6
- package/dist/outcomes/streamPart.d.ts +2 -2
- package/dist/outcomes/streamPart.js +2 -3
- package/dist/prompts/PromptBuilder.d.ts +3 -3
- package/dist/prompts/PromptBuilder.js +6 -6
- package/dist/prompts/index.d.ts +1 -1
- package/dist/prompts/types.d.ts +7 -2
- package/dist/runtime/InMemoryRetrievalCache.d.ts +1 -1
- package/dist/runtime/KnowledgeProvider.d.ts +3 -2
- package/dist/runtime/KnowledgeProvider.js +54 -30
- package/dist/runtime/Runtime.d.ts +3 -1
- package/dist/runtime/Runtime.js +84 -30
- package/dist/runtime/TraceRecorder.d.ts +22 -4
- package/dist/runtime/TraceRecorder.js +65 -29
- package/dist/runtime/buildAgentToolSurface.js +1 -1
- package/dist/runtime/channels/TextDriver.js +12 -9
- package/dist/runtime/channels/executeModelTool.d.ts +6 -0
- package/dist/runtime/channels/executeModelTool.js +70 -10
- package/dist/runtime/channels/extractionTurn.js +1 -1
- package/dist/runtime/channels/index.d.ts +0 -3
- package/dist/runtime/channels/index.js +0 -6
- package/dist/runtime/channels/streaming/hostControlSpeak.js +5 -1
- package/dist/runtime/channels/streaming/speakGated.js +24 -12
- package/dist/runtime/citations/index.d.ts +3 -3
- package/dist/runtime/closeRun.js +3 -2
- package/dist/runtime/controlFlowSignal.d.ts +24 -0
- package/dist/runtime/controlFlowSignal.js +29 -0
- package/dist/runtime/ctx.d.ts +3 -4
- package/dist/runtime/ctx.js +39 -5
- package/dist/runtime/durable/RunStore.js +1 -1
- package/dist/runtime/grounding/gather.d.ts +1 -1
- package/dist/runtime/grounding/inMemoryKnowledge.d.ts +1 -1
- package/dist/runtime/grounding/knowledge.d.ts +1 -1
- package/dist/runtime/hostLoop.js +26 -6
- package/dist/runtime/index.d.ts +1 -2
- package/dist/runtime/index.js +1 -1
- package/dist/runtime/outcomeMarking.d.ts +2 -2
- package/dist/runtime/outcomeMarking.js +2 -1
- package/dist/runtime/policies/agentTurn.d.ts +1 -1
- package/dist/runtime/runHookSafely.d.ts +3 -0
- package/dist/runtime/runHookSafely.js +19 -0
- package/dist/scheduler/index.d.ts +2 -2
- package/dist/scheduler/index.js +1 -1
- package/dist/services/TracingService.js +2 -3
- package/dist/skills/collectSkills.d.ts +11 -3
- package/dist/skills/collectSkills.js +51 -8
- package/dist/skills/compositeSkillStore.d.ts +26 -0
- package/dist/skills/compositeSkillStore.js +54 -0
- package/dist/skills/defineSkill.d.ts +21 -0
- package/dist/skills/defineSkill.js +26 -0
- package/dist/skills/fsSkillStore.d.ts +3 -0
- package/dist/skills/fsSkillStore.js +79 -0
- package/dist/skills/index.d.ts +4 -0
- package/dist/skills/index.js +4 -0
- package/dist/skills/parseSkillFrontmatter.d.ts +14 -0
- package/dist/skills/parseSkillFrontmatter.js +183 -0
- package/dist/skills/wireAgentSkills.d.ts +2 -1
- package/dist/skills/wireAgentSkills.js +2 -2
- package/dist/testing/mocks.d.ts +3 -3
- package/dist/testing/mocks.js +7 -3
- package/dist/tools/controlResults.d.ts +14 -0
- package/dist/tools/controlResults.js +15 -0
- package/dist/tools/effect/ToolExecutor.d.ts +6 -0
- package/dist/tools/effect/ToolExecutor.js +71 -35
- package/dist/tools/effect/defineTool.d.ts +9 -0
- package/dist/tools/effect/defineTool.js +1 -0
- package/dist/tools/effect/errors.d.ts +2 -5
- package/dist/tools/effect/errors.js +2 -5
- package/dist/tools/index.d.ts +0 -1
- package/dist/tools/index.js +0 -1
- package/dist/types/effectTool.d.ts +2 -0
- package/dist/types/flow.d.ts +1 -1
- package/dist/types/guardrails.d.ts +5 -0
- package/dist/types/hooks.d.ts +2 -2
- package/dist/types/index.d.ts +25 -16
- package/dist/types/index.js +8 -13
- package/dist/types/knowledge.d.ts +213 -0
- package/dist/types/processors.d.ts +0 -58
- package/dist/types/run-context.d.ts +3 -7
- package/dist/types/runtime.d.ts +3 -74
- package/dist/types/session.d.ts +1 -1
- package/dist/types/skills.d.ts +15 -1
- package/dist/types/stream.d.ts +133 -71
- package/dist/types/stream.js +34 -1
- package/dist/types/trace.d.ts +2 -0
- package/guides/AGENTS.md +3 -3
- package/guides/FLOWS.md +1 -1
- package/guides/GETTING_STARTED.md +1 -1
- package/guides/RUNTIME.md +20 -15
- package/guides/TOOLS.md +1 -1
- package/package.json +3 -13
- package/dist/foundation/AgentDefinition.d.ts +0 -17
- package/dist/foundation/ConversationEventLog.d.ts +0 -71
- package/dist/foundation/ConversationEventLog.js +0 -1
- package/dist/foundation/ConversationState.d.ts +0 -33
- package/dist/foundation/ConversationState.js +0 -1
- package/dist/foundation/DefaultConversationEventLog.d.ts +0 -27
- package/dist/foundation/DefaultConversationEventLog.js +0 -205
- package/dist/foundation/DefaultConversationState.d.ts +0 -36
- package/dist/foundation/DefaultConversationState.js +0 -103
- package/dist/foundation/DefaultToolExecutor.d.ts +0 -57
- package/dist/foundation/DefaultToolExecutor.js +0 -132
- package/dist/foundation/createFoundation.d.ts +0 -32
- package/dist/foundation/createFoundation.js +0 -33
- package/dist/hooks/HookRunner.d.ts +0 -37
- package/dist/hooks/HookRunner.js +0 -111
- package/dist/hooks/builtin/logging.d.ts +0 -5
- package/dist/hooks/builtin/logging.js +0 -98
- package/dist/hooks/builtin/metrics.d.ts +0 -7
- package/dist/hooks/builtin/metrics.js +0 -60
- package/dist/hooks/builtin/observability.d.ts +0 -20
- package/dist/hooks/builtin/observability.js +0 -572
- package/dist/hooks/helpers.d.ts +0 -22
- package/dist/hooks/helpers.js +0 -183
- package/dist/hooks/index.d.ts +0 -8
- package/dist/hooks/index.js +0 -6
- package/dist/realtime/RealtimeAudioClient.d.ts +0 -166
- package/dist/realtime/RealtimeAudioClient.js +0 -14
- package/dist/realtime/RealtimeSessionHandle.d.ts +0 -6
- package/dist/realtime/RealtimeSessionHandle.js +0 -1
- package/dist/realtime/index.d.ts +0 -2
- package/dist/realtime/index.js +0 -1
- package/dist/runtime/channels/VoiceDriver.d.ts +0 -31
- package/dist/runtime/channels/VoiceDriver.js +0 -321
- package/dist/runtime/channels/voiceTools.d.ts +0 -9
- package/dist/runtime/channels/voiceTools.js +0 -51
- package/dist/tools/errorHandling.d.ts +0 -35
- package/dist/tools/errorHandling.js +0 -145
- package/dist/types/voice.d.ts +0 -517
- package/dist/types/voice.js +0 -14
- package/dist/utils/isRecord.d.ts +0 -1
- package/dist/utils/isRecord.js +0 -3
- package/dist/utils/messageNormalization.d.ts +0 -2
- package/dist/utils/messageNormalization.js +0 -137
- /package/dist/{foundation/AgentDefinition.js → types/knowledge.js} +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @kuralle-agents/core
|
|
2
2
|
|
|
3
|
-
The runtime and primitives for building conversational AI agents
|
|
3
|
+
The runtime and primitives for building conversational AI agents with structured flows, routing, and durable tool execution.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -54,8 +54,8 @@ const runtime = createRuntime({ agents: [agent], defaultAgentId: 'support' });
|
|
|
54
54
|
|
|
55
55
|
const handle = runtime.run({ input: 'Hello', sessionId: 'demo' });
|
|
56
56
|
for await (const part of handle.events) { // events is a property, not a method
|
|
57
|
-
if (part.type === 'text-delta') process.stdout.write(part.delta);
|
|
58
|
-
if (part.type === 'done') console.log('\nSession:', part.sessionId);
|
|
57
|
+
if (part.type === 'text-delta') process.stdout.write(part.payload.delta);
|
|
58
|
+
if (part.type === 'done') console.log('\nSession:', part.payload.sessionId);
|
|
59
59
|
}
|
|
60
60
|
await handle; // resolves to TurnResult once the stream is consumed
|
|
61
61
|
```
|
|
@@ -230,7 +230,7 @@ return handle.toUIMessageStreamResponse({ sessionId: 'demo' });
|
|
|
230
230
|
|
|
231
231
|
Kuralle orchestration events (flow telemetry, safety blocks, interactive choices) arrive as typed `data-kuralle-*` parts. Import `KuralleUIMessage` and `KuralleDataParts` for compile-time-safe `message.parts` and `useChat({ onData })` handlers.
|
|
232
232
|
|
|
233
|
-
For non-UI consumers (curl, custom transports), use `handle.toResponseStream('sse')` to emit raw `
|
|
233
|
+
For non-UI consumers (curl, custom transports), use `handle.toResponseStream('sse')` to emit raw `StreamPart` JSON-SSE. Or use `@kuralle-agents/hono-server` — `POST /api/chat/sse` defaults to native `UIMessageStream`; append `?format=raw` for the legacy wire.
|
|
234
234
|
|
|
235
235
|
## Related
|
|
236
236
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type UIMessage } from 'ai';
|
|
2
2
|
import type { ConversationOutcome } from '../outcomes/types.js';
|
|
3
3
|
import type { ChoiceOption } from '../types/selection.js';
|
|
4
|
-
import type {
|
|
4
|
+
import type { StreamPart } from '../types/stream.js';
|
|
5
5
|
export type KuralleMetadata = {
|
|
6
6
|
sessionId?: string;
|
|
7
7
|
};
|
|
@@ -46,6 +46,6 @@ export type KuralleDataParts = {
|
|
|
46
46
|
};
|
|
47
47
|
};
|
|
48
48
|
export type KuralleUIMessage = UIMessage<KuralleMetadata, KuralleDataParts>;
|
|
49
|
-
export declare function harnessToUIMessageStream(source: AsyncIterable<
|
|
49
|
+
export declare function harnessToUIMessageStream(source: AsyncIterable<StreamPart>, opts?: {
|
|
50
50
|
sessionId?: string;
|
|
51
51
|
}): ReadableStream;
|
|
@@ -2,64 +2,64 @@ import { createUIMessageStream, generateId, } from 'ai';
|
|
|
2
2
|
function writeHarnessPart(part, writer) {
|
|
3
3
|
switch (part.type) {
|
|
4
4
|
case 'text-start':
|
|
5
|
-
writer.write({ type: 'text-start', id: part.id });
|
|
5
|
+
writer.write({ type: 'text-start', id: part.payload.id });
|
|
6
6
|
break;
|
|
7
7
|
case 'text-delta':
|
|
8
|
-
writer.write({ type: 'text-delta', id: part.id, delta: part.delta });
|
|
8
|
+
writer.write({ type: 'text-delta', id: part.payload.id, delta: part.payload.delta });
|
|
9
9
|
break;
|
|
10
10
|
case 'text-end':
|
|
11
|
-
writer.write({ type: 'text-end', id: part.id });
|
|
11
|
+
writer.write({ type: 'text-end', id: part.payload.id });
|
|
12
12
|
break;
|
|
13
13
|
case 'text-cancel':
|
|
14
|
-
writer.write({ type: 'text-end', id: part.id });
|
|
14
|
+
writer.write({ type: 'text-end', id: part.payload.id });
|
|
15
15
|
break;
|
|
16
16
|
case 'tool-call':
|
|
17
17
|
writer.write({
|
|
18
18
|
type: 'tool-input-available',
|
|
19
|
-
toolCallId: part.toolCallId ?? generateId(),
|
|
20
|
-
toolName: part.toolName,
|
|
21
|
-
input: part.args,
|
|
19
|
+
toolCallId: part.payload.toolCallId ?? generateId(),
|
|
20
|
+
toolName: part.payload.toolName,
|
|
21
|
+
input: part.payload.args,
|
|
22
22
|
});
|
|
23
23
|
break;
|
|
24
24
|
case 'tool-result':
|
|
25
25
|
writer.write({
|
|
26
26
|
type: 'tool-output-available',
|
|
27
|
-
toolCallId: part.toolCallId ?? 'unknown',
|
|
28
|
-
output: part.result,
|
|
27
|
+
toolCallId: part.payload.toolCallId ?? 'unknown',
|
|
28
|
+
output: part.payload.result,
|
|
29
29
|
});
|
|
30
30
|
break;
|
|
31
31
|
case 'node-enter':
|
|
32
32
|
writer.write({
|
|
33
33
|
type: 'data-kuralle-node',
|
|
34
|
-
data: { event: 'enter', node: part.nodeName },
|
|
34
|
+
data: { event: 'enter', node: part.payload.nodeName },
|
|
35
35
|
transient: true,
|
|
36
36
|
});
|
|
37
37
|
break;
|
|
38
38
|
case 'node-exit':
|
|
39
39
|
writer.write({
|
|
40
40
|
type: 'data-kuralle-node',
|
|
41
|
-
data: { event: 'exit', node: part.nodeName },
|
|
41
|
+
data: { event: 'exit', node: part.payload.nodeName },
|
|
42
42
|
transient: true,
|
|
43
43
|
});
|
|
44
44
|
break;
|
|
45
45
|
case 'flow-enter':
|
|
46
46
|
writer.write({
|
|
47
47
|
type: 'data-kuralle-flow',
|
|
48
|
-
data: { event: 'enter', flow: part.flow },
|
|
48
|
+
data: { event: 'enter', flow: part.payload.flow },
|
|
49
49
|
transient: true,
|
|
50
50
|
});
|
|
51
51
|
break;
|
|
52
52
|
case 'flow-end':
|
|
53
53
|
writer.write({
|
|
54
54
|
type: 'data-kuralle-flow',
|
|
55
|
-
data: { event: 'end', flow: part.flow, reason: part.reason },
|
|
55
|
+
data: { event: 'end', flow: part.payload.flow, reason: part.payload.reason },
|
|
56
56
|
transient: true,
|
|
57
57
|
});
|
|
58
58
|
break;
|
|
59
59
|
case 'flow-transition':
|
|
60
60
|
writer.write({
|
|
61
61
|
type: 'data-kuralle-flow',
|
|
62
|
-
data: { event: 'transition', from: part.from, to: part.to },
|
|
62
|
+
data: { event: 'transition', from: part.payload.from, to: part.payload.to },
|
|
63
63
|
transient: true,
|
|
64
64
|
});
|
|
65
65
|
break;
|
|
@@ -67,14 +67,18 @@ function writeHarnessPart(part, writer) {
|
|
|
67
67
|
writer.write({
|
|
68
68
|
type: 'data-kuralle-handoff',
|
|
69
69
|
id: generateId(),
|
|
70
|
-
data: { targetAgent: part.targetAgent, reason: part.reason },
|
|
70
|
+
data: { targetAgent: part.payload.targetAgent, reason: part.payload.reason },
|
|
71
71
|
});
|
|
72
72
|
break;
|
|
73
73
|
case 'interactive':
|
|
74
74
|
writer.write({
|
|
75
75
|
type: 'data-kuralle-interactive',
|
|
76
|
-
id: part.nodeId,
|
|
77
|
-
data: {
|
|
76
|
+
id: part.payload.nodeId,
|
|
77
|
+
data: {
|
|
78
|
+
nodeId: part.payload.nodeId,
|
|
79
|
+
prompt: part.payload.prompt,
|
|
80
|
+
options: part.payload.options,
|
|
81
|
+
},
|
|
78
82
|
});
|
|
79
83
|
break;
|
|
80
84
|
case 'safety-blocked':
|
|
@@ -83,9 +87,9 @@ function writeHarnessPart(part, writer) {
|
|
|
83
87
|
id: generateId(),
|
|
84
88
|
data: {
|
|
85
89
|
kind: 'safety-blocked',
|
|
86
|
-
moderator: part.moderator,
|
|
87
|
-
rationale: part.rationale,
|
|
88
|
-
userFacingMessage: part.userFacingMessage,
|
|
90
|
+
moderator: part.payload.moderator,
|
|
91
|
+
rationale: part.payload.rationale,
|
|
92
|
+
userFacingMessage: part.payload.userFacingMessage,
|
|
89
93
|
},
|
|
90
94
|
});
|
|
91
95
|
break;
|
|
@@ -95,8 +99,8 @@ function writeHarnessPart(part, writer) {
|
|
|
95
99
|
id: generateId(),
|
|
96
100
|
data: {
|
|
97
101
|
kind: 'pipeline-validation-block',
|
|
98
|
-
rationale: part.rationale,
|
|
99
|
-
userFacingMessage: part.userFacingMessage,
|
|
102
|
+
rationale: part.payload.rationale,
|
|
103
|
+
userFacingMessage: part.payload.userFacingMessage,
|
|
100
104
|
},
|
|
101
105
|
});
|
|
102
106
|
break;
|
|
@@ -104,35 +108,44 @@ function writeHarnessPart(part, writer) {
|
|
|
104
108
|
writer.write({
|
|
105
109
|
type: 'data-kuralle-outcome',
|
|
106
110
|
id: generateId(),
|
|
107
|
-
data: { outcome: part.outcome },
|
|
111
|
+
data: { outcome: part.payload.outcome },
|
|
108
112
|
});
|
|
109
113
|
break;
|
|
110
114
|
case 'interrupted':
|
|
111
115
|
writer.write({
|
|
112
116
|
type: 'data-kuralle-control',
|
|
113
|
-
data: { event: 'interrupted', reason: part.reason },
|
|
117
|
+
data: { event: 'interrupted', reason: part.payload.reason },
|
|
114
118
|
transient: true,
|
|
115
119
|
});
|
|
116
120
|
break;
|
|
117
121
|
case 'paused':
|
|
118
122
|
writer.write({
|
|
119
123
|
type: 'data-kuralle-control',
|
|
120
|
-
data: { event: 'paused', waitingFor: part.waitingFor },
|
|
124
|
+
data: { event: 'paused', waitingFor: part.payload.waitingFor },
|
|
121
125
|
transient: true,
|
|
122
126
|
});
|
|
123
127
|
break;
|
|
124
128
|
case 'custom':
|
|
125
129
|
writer.write({
|
|
126
130
|
type: 'data-kuralle-custom',
|
|
127
|
-
data: { name: part.name, data: part.data },
|
|
131
|
+
data: { name: part.payload.name, data: part.payload.data },
|
|
128
132
|
transient: true,
|
|
129
133
|
});
|
|
130
134
|
break;
|
|
131
135
|
case 'error':
|
|
132
|
-
throw new Error(part.error);
|
|
136
|
+
throw new Error(part.payload.error);
|
|
133
137
|
case 'done':
|
|
134
138
|
case 'turn-end':
|
|
135
139
|
break;
|
|
140
|
+
default: {
|
|
141
|
+
// Client-channel exhaustiveness guard. Internal-channel parts are
|
|
142
|
+
// deliberately unmapped here — they never reach a UI client. But a new
|
|
143
|
+
// `client` variant added without a case above would be silently dropped
|
|
144
|
+
// on the ADR-0005 default output path, so pin the residual to internal:
|
|
145
|
+
// adding a client variant without a case fails this assignment.
|
|
146
|
+
const _internalOnly = part;
|
|
147
|
+
void _internalOnly;
|
|
148
|
+
}
|
|
136
149
|
}
|
|
137
150
|
}
|
|
138
151
|
export function harnessToUIMessageStream(source, opts) {
|
|
@@ -146,8 +159,8 @@ export function harnessToUIMessageStream(source, opts) {
|
|
|
146
159
|
});
|
|
147
160
|
}
|
|
148
161
|
for await (const part of source) {
|
|
149
|
-
if (part.type === 'done' && part.sessionId) {
|
|
150
|
-
doneSessionId = doneSessionId ?? part.sessionId;
|
|
162
|
+
if (part.type === 'done' && part.payload.sessionId) {
|
|
163
|
+
doneSessionId = doneSessionId ?? part.payload.sessionId;
|
|
151
164
|
}
|
|
152
165
|
else {
|
|
153
166
|
writeHarnessPart(part, writer);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* CapabilityHost with Runtime context (working memory, long-term memory,
|
|
8
8
|
* policy injections) and structures the output per audio-model best practices.
|
|
9
9
|
*
|
|
10
|
-
* Adapters
|
|
10
|
+
* Adapters can extend or replace
|
|
11
11
|
* the default with backend-specific voice rules and guardrails.
|
|
12
12
|
*
|
|
13
13
|
* Prompt structure follows Google's Live API best practices and
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* CapabilityHost with Runtime context (working memory, long-term memory,
|
|
8
8
|
* policy injections) and structures the output per audio-model best practices.
|
|
9
9
|
*
|
|
10
|
-
* Adapters
|
|
10
|
+
* Adapters can extend or replace
|
|
11
11
|
* the default with backend-specific voice rules and guardrails.
|
|
12
12
|
*
|
|
13
13
|
* Prompt structure follows Google's Live API best practices and
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ZodTypeAny } from 'zod';
|
|
2
2
|
/**
|
|
3
3
|
* Backend-agnostic tool declaration. Produced by capabilities,
|
|
4
|
-
* consumed by adapters (
|
|
4
|
+
* consumed by adapters (AI SDK and others).
|
|
5
5
|
*/
|
|
6
6
|
export interface ToolDeclaration<TInput = unknown, TOutput = unknown> {
|
|
7
7
|
name: string;
|
package/dist/eval/EvalRunner.js
CHANGED
|
@@ -25,16 +25,16 @@ export class EvalRunner {
|
|
|
25
25
|
const handle = runtime.run({ input: turn.input, sessionId });
|
|
26
26
|
for await (const part of handle.events) {
|
|
27
27
|
if (part.type === 'text-delta') {
|
|
28
|
-
response += part.delta;
|
|
28
|
+
response += part.payload.delta;
|
|
29
29
|
}
|
|
30
30
|
if (part.type === 'tool-call') {
|
|
31
|
-
toolsCalled.push(part.toolName);
|
|
31
|
+
toolsCalled.push(part.payload.toolName);
|
|
32
32
|
}
|
|
33
33
|
if (part.type === 'flow-transition') {
|
|
34
|
-
transitions.push({ from: part.from, to: part.to });
|
|
34
|
+
transitions.push({ from: part.payload.from, to: part.payload.to });
|
|
35
35
|
}
|
|
36
36
|
if (part.type === 'done') {
|
|
37
|
-
sessionId = part.sessionId;
|
|
37
|
+
sessionId = part.payload.sessionId;
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
await handle;
|
package/dist/eval/simulation.js
CHANGED
|
@@ -66,10 +66,11 @@ export async function simulateConversation(options) {
|
|
|
66
66
|
let reply = '';
|
|
67
67
|
for await (const part of handle.events) {
|
|
68
68
|
if (part.type === 'text-delta')
|
|
69
|
-
reply += part.delta;
|
|
69
|
+
reply += part.payload.delta;
|
|
70
70
|
if (part.type === 'tool-call')
|
|
71
|
-
toolsCalled.push(part.toolName);
|
|
72
|
-
if (part.type === 'escalation' ||
|
|
71
|
+
toolsCalled.push(part.payload.toolName);
|
|
72
|
+
if (part.type === 'escalation' ||
|
|
73
|
+
(part.type === 'handoff' && part.payload.targetAgent === 'human')) {
|
|
73
74
|
escalated = true;
|
|
74
75
|
}
|
|
75
76
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { StreamPart, TurnHandle } from '../types/stream.js';
|
|
2
2
|
export interface EventBus {
|
|
3
|
-
emit(part:
|
|
4
|
-
events(): AsyncIterable<
|
|
3
|
+
emit(part: StreamPart): void;
|
|
4
|
+
events(): AsyncIterable<StreamPart>;
|
|
5
5
|
close(): void;
|
|
6
6
|
}
|
|
7
7
|
export declare function createEventBus(): EventBus;
|
|
@@ -121,10 +121,10 @@ export function emitCollectAsk(node, run, ctx) {
|
|
|
121
121
|
return;
|
|
122
122
|
}
|
|
123
123
|
const id = crypto.randomUUID();
|
|
124
|
-
ctx.emit({ type: 'text-start', id });
|
|
125
|
-
ctx.emit({ type: 'text-delta', id, delta: text });
|
|
126
|
-
ctx.emit({ type: 'text-end', id });
|
|
127
|
-
ctx.emit({ type: 'turn-end' });
|
|
124
|
+
ctx.emit({ channel: 'client', type: 'text-start', payload: { id } });
|
|
125
|
+
ctx.emit({ channel: 'client', type: 'text-delta', payload: { id, delta: text } });
|
|
126
|
+
ctx.emit({ channel: 'client', type: 'text-end', payload: { id } });
|
|
127
|
+
ctx.emit({ channel: 'internal', type: 'turn-end', payload: {} });
|
|
128
128
|
appendAssistantMessage(run, text);
|
|
129
129
|
}
|
|
130
130
|
function mergeExtractionFromTurn(node, run, turn, ctx) {
|
package/dist/flow/degrade.js
CHANGED
|
@@ -7,9 +7,9 @@ export function appendSafeAssistantMessage(run, ctx, text = SAFE_DEGRADED_MESSAG
|
|
|
7
7
|
const message = { role: 'assistant', content: text };
|
|
8
8
|
run.messages = [...run.messages, message];
|
|
9
9
|
const id = crypto.randomUUID();
|
|
10
|
-
ctx.emit({ type: 'text-start', id });
|
|
11
|
-
ctx.emit({ type: 'text-delta', id, delta: text });
|
|
12
|
-
ctx.emit({ type: 'text-end', id });
|
|
10
|
+
ctx.emit({ channel: 'client', type: 'text-start', payload: { id } });
|
|
11
|
+
ctx.emit({ channel: 'client', type: 'text-delta', payload: { id, delta: text } });
|
|
12
|
+
ctx.emit({ channel: 'client', type: 'text-end', payload: { id } });
|
|
13
13
|
}
|
|
14
14
|
export async function degradeFlowError(flow, registry, run, driver, ctx, dispatchNode) {
|
|
15
15
|
appendSafeAssistantMessage(run, ctx);
|
|
@@ -29,6 +29,10 @@ export async function degradeFlowError(flow, registry, run, driver, ctx, dispatc
|
|
|
29
29
|
// Fall through to graceful end if the escalate node also fails.
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
|
-
ctx.emit({
|
|
32
|
+
ctx.emit({
|
|
33
|
+
channel: 'internal',
|
|
34
|
+
type: 'flow-end',
|
|
35
|
+
payload: { flow: flow.name, reason: 'error_degraded' },
|
|
36
|
+
});
|
|
33
37
|
return { kind: 'ended', reason: 'error_degraded' };
|
|
34
38
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { FlowNode, FlowState } from '../types/flow.js';
|
|
2
|
-
import type {
|
|
3
|
-
export declare function emitInteractiveOnNodeEnter(node: FlowNode, state: FlowState, emit: (part:
|
|
2
|
+
import type { StreamPart } from '../types/stream.js';
|
|
3
|
+
export declare function emitInteractiveOnNodeEnter(node: FlowNode, state: FlowState, emit: (part: StreamPart) => void): void;
|
|
@@ -35,9 +35,12 @@ export function emitInteractiveOnNodeEnter(node, state, emit) {
|
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
37
|
emit({
|
|
38
|
+
channel: 'internal',
|
|
38
39
|
type: 'interactive',
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
payload: {
|
|
41
|
+
nodeId: node.id,
|
|
42
|
+
options: node.choices,
|
|
43
|
+
prompt: interactivePrompt(node, state),
|
|
44
|
+
},
|
|
42
45
|
});
|
|
43
46
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CollectNode, FlowState } from '../types/flow.js';
|
|
2
2
|
import type { Tool } from '../types/effectTool.js';
|
|
3
|
-
import type {
|
|
3
|
+
import type { StreamPart } from '../types/stream.js';
|
|
4
4
|
export declare function resetCollect(state: FlowState, nodeId: string): void;
|
|
5
5
|
export declare function getCollectData(state: FlowState, nodeId: string): Record<string, unknown>;
|
|
6
6
|
export declare function incrementCollectTurns(state: FlowState, nodeId: string): number;
|
|
@@ -20,4 +20,4 @@ export declare function mergeTurnExtraction(node: CollectNode, state: FlowState,
|
|
|
20
20
|
name: string;
|
|
21
21
|
result: unknown;
|
|
22
22
|
}>): MergeTurnExtractionResult;
|
|
23
|
-
export declare function emitExtractionTelemetry(node: CollectNode, state: FlowState, incoming: Record<string, unknown>, emit: (part:
|
|
23
|
+
export declare function emitExtractionTelemetry(node: CollectNode, state: FlowState, incoming: Record<string, unknown>, emit: (part: StreamPart) => void): void;
|
package/dist/flow/extraction.js
CHANGED
|
@@ -129,16 +129,22 @@ export function emitExtractionTelemetry(node, state, incoming, emit) {
|
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
emit({
|
|
132
|
+
channel: 'internal',
|
|
132
133
|
type: 'custom',
|
|
133
|
-
|
|
134
|
-
|
|
134
|
+
payload: {
|
|
135
|
+
name: 'flow.extraction.submission',
|
|
136
|
+
data: { node: node.id, fieldsAccepted, fieldsRejected },
|
|
137
|
+
},
|
|
135
138
|
});
|
|
136
139
|
const collected = getCollectData(state, node.id);
|
|
137
140
|
const missing = computeMissingFields(node, collected);
|
|
138
141
|
emit({
|
|
142
|
+
channel: 'internal',
|
|
139
143
|
type: 'custom',
|
|
140
|
-
|
|
141
|
-
|
|
144
|
+
payload: {
|
|
145
|
+
name: 'flow.extraction.update',
|
|
146
|
+
data: { nodeId: node.id, collected, missing },
|
|
147
|
+
},
|
|
142
148
|
});
|
|
143
149
|
}
|
|
144
150
|
function fieldPopulated(value) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { LanguageModel } from 'ai';
|
|
2
2
|
import type { Flow, FlowNode } from '../types/flow.js';
|
|
3
3
|
import type { RunState } from '../runtime/durable/types.js';
|
|
4
|
-
import type {
|
|
4
|
+
import type { StreamPart } from '../types/stream.js';
|
|
5
5
|
export interface ReduceTransitionInput {
|
|
6
6
|
fromNodeId: string;
|
|
7
7
|
toNode: FlowNode;
|
|
@@ -9,7 +9,7 @@ export interface ReduceTransitionInput {
|
|
|
9
9
|
flow: Flow;
|
|
10
10
|
model: LanguageModel;
|
|
11
11
|
data?: Record<string, unknown>;
|
|
12
|
-
emit: (part:
|
|
12
|
+
emit: (part: StreamPart) => void;
|
|
13
13
|
abortSignal?: AbortSignal;
|
|
14
14
|
}
|
|
15
15
|
export declare function reduceTransition(input: ReduceTransitionInput): Promise<void>;
|
|
@@ -8,9 +8,13 @@ function resolveNodeContext(toNode, flow) {
|
|
|
8
8
|
}
|
|
9
9
|
export async function reduceTransition(input) {
|
|
10
10
|
const { fromNodeId, toNode, run, flow, model, data, emit, abortSignal } = input;
|
|
11
|
-
emit({ type: 'node-exit', nodeName: fromNodeId });
|
|
12
|
-
emit({
|
|
13
|
-
|
|
11
|
+
emit({ channel: 'internal', type: 'node-exit', payload: { nodeName: fromNodeId } });
|
|
12
|
+
emit({
|
|
13
|
+
channel: 'internal',
|
|
14
|
+
type: 'flow-transition',
|
|
15
|
+
payload: { from: fromNodeId, to: toNode.id },
|
|
16
|
+
});
|
|
17
|
+
emit({ channel: 'internal', type: 'node-enter', payload: { nodeName: toNode.id } });
|
|
14
18
|
emitInteractiveOnNodeEnter(toNode, run.state, emit);
|
|
15
19
|
await applyContextStrategy({
|
|
16
20
|
strategy: resolveNodeContext(toNode, flow),
|
package/dist/flow/runFlow.js
CHANGED
|
@@ -11,8 +11,7 @@ import { evaluateReplyControl } from './controlEvaluator.js';
|
|
|
11
11
|
import { runNodeVerify, VerifyBlockedError } from './verify.js';
|
|
12
12
|
import { loadRecordedSteps } from '../runtime/durable/replay.js';
|
|
13
13
|
import { persistTurnUsageFromTurn } from '../runtime/turnTokenUsage.js';
|
|
14
|
-
import {
|
|
15
|
-
import { ToolApprovalDeniedError } from '../tools/effect/errors.js';
|
|
14
|
+
import { isApprovalDenial, isControlFlowSignal } from '../runtime/controlFlowSignal.js';
|
|
16
15
|
import { emitInteractiveOnNodeEnter } from './emitInteractive.js';
|
|
17
16
|
import { appendConversationAudit } from '../audit/record.js';
|
|
18
17
|
import { appendSafeAssistantMessage, degradeFlowError, findEscalateNode, } from './degrade.js';
|
|
@@ -265,8 +264,8 @@ export async function runFlow(flow, run, driver, ctx, agent) {
|
|
|
265
264
|
if (!run.activeNode) {
|
|
266
265
|
run.activeNode = node.id;
|
|
267
266
|
run.activeFlow = flow.name;
|
|
268
|
-
ctx.emit({ type: 'flow-enter', flow: flow.name });
|
|
269
|
-
ctx.emit({ type: 'node-enter', nodeName: node.id });
|
|
267
|
+
ctx.emit({ channel: 'internal', type: 'flow-enter', payload: { flow: flow.name } });
|
|
268
|
+
ctx.emit({ channel: 'internal', type: 'node-enter', payload: { nodeName: node.id } });
|
|
270
269
|
emitInteractiveOnNodeEnter(node, run.state, ctx.emit);
|
|
271
270
|
}
|
|
272
271
|
const edgeCounts = new Map();
|
|
@@ -277,11 +276,14 @@ export async function runFlow(flow, run, driver, ctx, agent) {
|
|
|
277
276
|
transition = await dispatchNode(node, run, driver, ctx, agent, flow);
|
|
278
277
|
}
|
|
279
278
|
catch (error) {
|
|
280
|
-
|
|
279
|
+
// Neither is a malfunction, so neither may reach degradeFlowError and be reported to
|
|
280
|
+
// the user as "something went wrong on my side". A suspend resumes later; a denial is
|
|
281
|
+
// the action node author's to handle, since they chose to call the tool.
|
|
282
|
+
if (isControlFlowSignal(error) || isApprovalDenial(error)) {
|
|
281
283
|
throw error;
|
|
282
284
|
}
|
|
283
285
|
const message = error instanceof Error ? error.message : String(error);
|
|
284
|
-
ctx.emit({ type: 'error', error: message });
|
|
286
|
+
ctx.emit({ channel: 'client', type: 'error', payload: { error: message } });
|
|
285
287
|
return degradeFlowError(flow, registry, run, driver, ctx, (n, r, d, c) => dispatchNode(n, r, d, c, agent, flow));
|
|
286
288
|
}
|
|
287
289
|
if (transition.kind === 'switchFlow') {
|
|
@@ -298,15 +300,27 @@ export async function runFlow(flow, run, driver, ctx, agent) {
|
|
|
298
300
|
run.activeFlow = park.flow;
|
|
299
301
|
run.activeNode = park.node;
|
|
300
302
|
await ctx.runStore.putRunState(run);
|
|
301
|
-
ctx.emit({
|
|
303
|
+
ctx.emit({
|
|
304
|
+
channel: 'internal',
|
|
305
|
+
type: 'flow-end',
|
|
306
|
+
payload: { flow: flow.name, reason: transition.reason },
|
|
307
|
+
});
|
|
302
308
|
return runFlow(parkedFlow, run, driver, ctx, agent);
|
|
303
309
|
}
|
|
304
310
|
}
|
|
305
|
-
ctx.emit({
|
|
311
|
+
ctx.emit({
|
|
312
|
+
channel: 'internal',
|
|
313
|
+
type: 'flow-end',
|
|
314
|
+
payload: { flow: flow.name, reason: transition.reason },
|
|
315
|
+
});
|
|
306
316
|
return { kind: 'ended', reason: transition.reason };
|
|
307
317
|
}
|
|
308
318
|
if (transition.kind === 'handoff') {
|
|
309
|
-
ctx.emit({
|
|
319
|
+
ctx.emit({
|
|
320
|
+
channel: 'internal',
|
|
321
|
+
type: 'handoff',
|
|
322
|
+
payload: { targetAgent: transition.to, reason: transition.reason },
|
|
323
|
+
});
|
|
310
324
|
return { kind: 'handoff', to: transition.to, reason: transition.reason };
|
|
311
325
|
}
|
|
312
326
|
if (transition.kind === 'escalate') {
|
|
@@ -337,14 +351,18 @@ export async function runFlow(flow, run, driver, ctx, agent) {
|
|
|
337
351
|
}
|
|
338
352
|
catch (error) {
|
|
339
353
|
if (error instanceof VerifyBlockedError) {
|
|
340
|
-
ctx.emit({ type: 'error', error: error.message });
|
|
354
|
+
ctx.emit({ channel: 'client', type: 'error', payload: { error: error.message } });
|
|
341
355
|
return { kind: 'awaitingUser' };
|
|
342
356
|
}
|
|
343
357
|
throw error;
|
|
344
358
|
}
|
|
345
359
|
const oscillation = bumpOscillation(edgeCounts, node.id, target.id);
|
|
346
360
|
if (oscillation > maxOscillations) {
|
|
347
|
-
ctx.emit({
|
|
361
|
+
ctx.emit({
|
|
362
|
+
channel: 'client',
|
|
363
|
+
type: 'error',
|
|
364
|
+
payload: { error: `Flow oscillation blocked: ${node.id} -> ${target.id}` },
|
|
365
|
+
});
|
|
348
366
|
const escalateNode = findEscalateNode(registry);
|
|
349
367
|
if (escalateNode) {
|
|
350
368
|
appendSafeAssistantMessage(run, ctx);
|
|
@@ -363,7 +381,11 @@ export async function runFlow(flow, run, driver, ctx, agent) {
|
|
|
363
381
|
continue;
|
|
364
382
|
}
|
|
365
383
|
appendSafeAssistantMessage(run, ctx);
|
|
366
|
-
ctx.emit({
|
|
384
|
+
ctx.emit({
|
|
385
|
+
channel: 'internal',
|
|
386
|
+
type: 'flow-end',
|
|
387
|
+
payload: { flow: flow.name, reason: 'error_degraded' },
|
|
388
|
+
});
|
|
367
389
|
return { kind: 'ended', reason: 'error_degraded' };
|
|
368
390
|
}
|
|
369
391
|
await reduceTransition({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Session } from '../types/index.js';
|
|
2
2
|
/**
|
|
3
3
|
* Manages active agent resolution, handoff recording, and agent state.
|
|
4
|
-
*
|
|
4
|
+
* Used by Runtime.
|
|
5
5
|
*/
|
|
6
6
|
export interface AgentStateController {
|
|
7
7
|
/** Resolve the active agent ID, falling back to the provided default. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Session, ToolCallRecord } from '../types/index.js';
|
|
2
2
|
/**
|
|
3
3
|
* Minimal tool shape required by the executor.
|
|
4
|
-
* Compatible with AI SDK `Tool
|
|
4
|
+
* Compatible with AI SDK `Tool` and plain `{ execute }` objects.
|
|
5
5
|
*/
|
|
6
6
|
export interface ExecutableTool {
|
|
7
7
|
execute: (args: unknown, options?: unknown) => Promise<unknown>;
|
|
@@ -9,7 +9,7 @@ export interface ExecutableTool {
|
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
11
|
* Encapsulates tool execution with enforcement, idempotency, and context enrichment.
|
|
12
|
-
*
|
|
12
|
+
* Used by Runtime.
|
|
13
13
|
*/
|
|
14
14
|
export interface ToolExecutor {
|
|
15
15
|
/**
|
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
export type { AgentDefinition } from './AgentDefinition.js';
|
|
2
1
|
export type { ToolExecutor, ExecutableTool } from './ToolExecutor.js';
|
|
3
|
-
export type { ConversationState } from './ConversationState.js';
|
|
4
|
-
export type { ConversationEventLog, ConversationEvent } from './ConversationEventLog.js';
|
|
5
2
|
export type { AgentStateController } from './AgentStateController.js';
|
|
6
|
-
export { DefaultToolExecutor, ToolTimeoutError } from './DefaultToolExecutor.js';
|
|
7
|
-
export type { DefaultToolExecutorConfig } from './DefaultToolExecutor.js';
|
|
8
|
-
export { DefaultConversationState } from './DefaultConversationState.js';
|
|
9
|
-
export type { DefaultConversationStateConfig } from './DefaultConversationState.js';
|
|
10
|
-
export { DefaultConversationEventLog } from './DefaultConversationEventLog.js';
|
|
11
|
-
export type { DefaultConversationEventLogConfig } from './DefaultConversationEventLog.js';
|
|
12
3
|
export { DefaultAgentStateController } from './DefaultAgentStateController.js';
|
|
13
|
-
export { createFoundation } from './createFoundation.js';
|
|
14
|
-
export type { Foundation, FoundationConfig } from './createFoundation.js';
|
package/dist/foundation/index.js
CHANGED
|
@@ -1,7 +1,2 @@
|
|
|
1
1
|
// Default implementations
|
|
2
|
-
export { DefaultToolExecutor, ToolTimeoutError } from './DefaultToolExecutor.js';
|
|
3
|
-
export { DefaultConversationState } from './DefaultConversationState.js';
|
|
4
|
-
export { DefaultConversationEventLog } from './DefaultConversationEventLog.js';
|
|
5
2
|
export { DefaultAgentStateController } from './DefaultAgentStateController.js';
|
|
6
|
-
// Factory
|
|
7
|
-
export { createFoundation } from './createFoundation.js';
|