@kuralle-agents/core 0.12.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.
Files changed (210) hide show
  1. package/README.md +89 -4
  2. package/dist/ai-sdk/uiMessageStream.d.ts +2 -2
  3. package/dist/ai-sdk/uiMessageStream.js +42 -29
  4. package/dist/capabilities/LivePromptAssembler.d.ts +1 -1
  5. package/dist/capabilities/LivePromptAssembler.js +2 -1
  6. package/dist/capabilities/index.d.ts +1 -1
  7. package/dist/eval/EvalRunner.js +4 -4
  8. package/dist/eval/simulation.js +4 -3
  9. package/dist/events/TurnHandle.d.ts +3 -3
  10. package/dist/flow/collectDigression.d.ts +5 -2
  11. package/dist/flow/collectDigression.js +48 -10
  12. package/dist/flow/collectUntilComplete.js +13 -5
  13. package/dist/flow/degrade.js +8 -4
  14. package/dist/flow/emitInteractive.d.ts +2 -2
  15. package/dist/flow/emitInteractive.js +6 -3
  16. package/dist/flow/extraction.d.ts +3 -2
  17. package/dist/flow/extraction.js +14 -4
  18. package/dist/flow/reduceTransition.d.ts +2 -2
  19. package/dist/flow/reduceTransition.js +7 -3
  20. package/dist/flow/runFlow.js +97 -17
  21. package/dist/foundation/AgentStateController.d.ts +1 -1
  22. package/dist/foundation/ToolExecutor.d.ts +2 -2
  23. package/dist/foundation/index.d.ts +0 -11
  24. package/dist/foundation/index.js +0 -5
  25. package/dist/index.d.ts +15 -15
  26. package/dist/index.js +9 -6
  27. package/dist/outcomes/streamPart.d.ts +2 -2
  28. package/dist/outcomes/streamPart.js +2 -3
  29. package/dist/prompts/PromptBuilder.d.ts +3 -3
  30. package/dist/prompts/PromptBuilder.js +13 -6
  31. package/dist/prompts/index.d.ts +1 -1
  32. package/dist/prompts/types.d.ts +9 -2
  33. package/dist/runtime/InMemoryRetrievalCache.d.ts +25 -0
  34. package/dist/runtime/InMemoryRetrievalCache.js +59 -0
  35. package/dist/runtime/KnowledgeProvider.d.ts +3 -2
  36. package/dist/runtime/KnowledgeProvider.js +60 -31
  37. package/dist/runtime/Runtime.d.ts +47 -1
  38. package/dist/runtime/Runtime.js +273 -36
  39. package/dist/runtime/TokenAccumulator.d.ts +7 -0
  40. package/dist/runtime/TokenAccumulator.js +7 -0
  41. package/dist/runtime/TraceRecorder.d.ts +51 -0
  42. package/dist/runtime/TraceRecorder.js +326 -0
  43. package/dist/runtime/buildAgentToolSurface.js +1 -1
  44. package/dist/runtime/channels/TextDriver.js +57 -31
  45. package/dist/runtime/channels/executeModelTool.d.ts +14 -1
  46. package/dist/runtime/channels/executeModelTool.js +132 -3
  47. package/dist/runtime/channels/extractionTurn.js +1 -1
  48. package/dist/runtime/channels/index.d.ts +0 -3
  49. package/dist/runtime/channels/index.js +0 -6
  50. package/dist/runtime/channels/inputBuffer.d.ts +1 -0
  51. package/dist/runtime/channels/inputBuffer.js +9 -0
  52. package/dist/runtime/channels/streaming/hostControlSpeak.js +5 -1
  53. package/dist/runtime/channels/streaming/speakGated.js +24 -12
  54. package/dist/runtime/citations/index.d.ts +3 -3
  55. package/dist/runtime/closeRun.js +14 -10
  56. package/dist/runtime/compaction.d.ts +2 -0
  57. package/dist/runtime/compaction.js +3 -2
  58. package/dist/runtime/controlFlowSignal.d.ts +24 -0
  59. package/dist/runtime/controlFlowSignal.js +29 -0
  60. package/dist/runtime/ctx.d.ts +3 -4
  61. package/dist/runtime/ctx.js +147 -60
  62. package/dist/runtime/durable/RunStore.d.ts +16 -0
  63. package/dist/runtime/durable/RunStore.js +7 -1
  64. package/dist/runtime/durable/SessionRunStore.d.ts +7 -2
  65. package/dist/runtime/durable/SessionRunStore.js +136 -34
  66. package/dist/runtime/durable/idempotency.d.ts +1 -0
  67. package/dist/runtime/durable/idempotency.js +3 -0
  68. package/dist/runtime/durable/replay.js +7 -2
  69. package/dist/runtime/durable/types.d.ts +11 -0
  70. package/dist/runtime/goals.d.ts +18 -0
  71. package/dist/runtime/goals.js +158 -0
  72. package/dist/runtime/grounding/gather.d.ts +1 -1
  73. package/dist/runtime/grounding/inMemoryKnowledge.d.ts +1 -1
  74. package/dist/runtime/grounding/knowledge.d.ts +1 -1
  75. package/dist/runtime/grounding/knowledge.js +1 -1
  76. package/dist/runtime/handoffContinuation.d.ts +20 -0
  77. package/dist/runtime/handoffContinuation.js +30 -0
  78. package/dist/runtime/handoffOscillation.d.ts +6 -0
  79. package/dist/runtime/handoffOscillation.js +17 -0
  80. package/dist/runtime/hostLoop.js +37 -6
  81. package/dist/runtime/index.d.ts +4 -3
  82. package/dist/runtime/index.js +2 -1
  83. package/dist/runtime/openRun.d.ts +2 -0
  84. package/dist/runtime/openRun.js +46 -17
  85. package/dist/runtime/outcomeMarking.d.ts +2 -2
  86. package/dist/runtime/outcomeMarking.js +2 -1
  87. package/dist/runtime/policies/agentTurn.d.ts +1 -1
  88. package/dist/runtime/policies/limits.d.ts +1 -0
  89. package/dist/runtime/policies/limits.js +3 -0
  90. package/dist/runtime/runHookSafely.d.ts +3 -0
  91. package/dist/runtime/runHookSafely.js +19 -0
  92. package/dist/runtime/select.d.ts +5 -1
  93. package/dist/runtime/select.js +30 -1
  94. package/dist/runtime/turnTokenUsage.d.ts +28 -0
  95. package/dist/runtime/turnTokenUsage.js +70 -0
  96. package/dist/scheduler/index.d.ts +2 -2
  97. package/dist/scheduler/index.js +1 -1
  98. package/dist/services/TracingService.js +2 -3
  99. package/dist/session/SessionStore.d.ts +6 -0
  100. package/dist/session/SessionStore.js +12 -1
  101. package/dist/session/stores/MemoryStore.d.ts +1 -1
  102. package/dist/session/stores/MemoryStore.js +16 -2
  103. package/dist/session/testing.d.ts +6 -1
  104. package/dist/session/testing.js +34 -0
  105. package/dist/session/utils.d.ts +3 -0
  106. package/dist/session/utils.js +23 -0
  107. package/dist/skills/collectSkills.d.ts +11 -3
  108. package/dist/skills/collectSkills.js +51 -8
  109. package/dist/skills/compositeSkillStore.d.ts +26 -0
  110. package/dist/skills/compositeSkillStore.js +54 -0
  111. package/dist/skills/defineSkill.d.ts +21 -0
  112. package/dist/skills/defineSkill.js +26 -0
  113. package/dist/skills/fsSkillStore.d.ts +3 -0
  114. package/dist/skills/fsSkillStore.js +79 -0
  115. package/dist/skills/index.d.ts +4 -0
  116. package/dist/skills/index.js +4 -0
  117. package/dist/skills/parseSkillFrontmatter.d.ts +14 -0
  118. package/dist/skills/parseSkillFrontmatter.js +183 -0
  119. package/dist/skills/wireAgentSkills.d.ts +2 -1
  120. package/dist/skills/wireAgentSkills.js +2 -2
  121. package/dist/testing/mocks.d.ts +3 -3
  122. package/dist/testing/mocks.js +7 -3
  123. package/dist/tools/controlResults.d.ts +14 -0
  124. package/dist/tools/controlResults.js +15 -0
  125. package/dist/tools/effect/ToolExecutor.d.ts +6 -0
  126. package/dist/tools/effect/ToolExecutor.js +75 -36
  127. package/dist/tools/effect/defineTool.d.ts +11 -0
  128. package/dist/tools/effect/defineTool.js +3 -0
  129. package/dist/tools/effect/errors.d.ts +2 -5
  130. package/dist/tools/effect/errors.js +2 -5
  131. package/dist/tools/index.d.ts +0 -1
  132. package/dist/tools/index.js +0 -1
  133. package/dist/tracing/MemoryTraceStore.d.ts +16 -0
  134. package/dist/tracing/MemoryTraceStore.js +56 -0
  135. package/dist/tracing/OtelTraceSink.d.ts +127 -0
  136. package/dist/tracing/OtelTraceSink.js +101 -0
  137. package/dist/tracing/TraceStore.d.ts +19 -0
  138. package/dist/tracing/TraceStore.js +32 -0
  139. package/dist/tracing/index.d.ts +3 -0
  140. package/dist/tracing/index.js +3 -0
  141. package/dist/tracing/testing.d.ts +3 -0
  142. package/dist/tracing/testing.js +45 -0
  143. package/dist/types/agentConfig.d.ts +2 -1
  144. package/dist/types/channel.d.ts +14 -1
  145. package/dist/types/effectTool.d.ts +6 -0
  146. package/dist/types/flow.d.ts +1 -1
  147. package/dist/types/guardrails.d.ts +5 -0
  148. package/dist/types/hooks.d.ts +2 -2
  149. package/dist/types/index.d.ts +25 -15
  150. package/dist/types/index.js +8 -12
  151. package/dist/types/knowledge.d.ts +213 -0
  152. package/dist/types/processors.d.ts +0 -58
  153. package/dist/types/run-context.d.ts +16 -7
  154. package/dist/types/runtime.d.ts +3 -74
  155. package/dist/types/session.d.ts +11 -1
  156. package/dist/types/skills.d.ts +15 -1
  157. package/dist/types/stream.d.ts +138 -68
  158. package/dist/types/stream.js +34 -1
  159. package/dist/types/trace.d.ts +52 -0
  160. package/guides/AGENTS.md +3 -3
  161. package/guides/EXAMPLE_VERIFICATION.md +4 -4
  162. package/guides/FLOWS.md +1 -1
  163. package/guides/GETTING_STARTED.md +1 -1
  164. package/guides/RUNTIME.md +20 -15
  165. package/guides/TOOLS.md +1 -1
  166. package/package.json +13 -14
  167. package/dist/foundation/AgentDefinition.d.ts +0 -17
  168. package/dist/foundation/ConversationEventLog.d.ts +0 -71
  169. package/dist/foundation/ConversationState.d.ts +0 -33
  170. package/dist/foundation/ConversationState.js +0 -1
  171. package/dist/foundation/DefaultConversationEventLog.d.ts +0 -27
  172. package/dist/foundation/DefaultConversationEventLog.js +0 -205
  173. package/dist/foundation/DefaultConversationState.d.ts +0 -36
  174. package/dist/foundation/DefaultConversationState.js +0 -103
  175. package/dist/foundation/DefaultToolExecutor.d.ts +0 -57
  176. package/dist/foundation/DefaultToolExecutor.js +0 -132
  177. package/dist/foundation/createFoundation.d.ts +0 -32
  178. package/dist/foundation/createFoundation.js +0 -33
  179. package/dist/hooks/HookRunner.d.ts +0 -37
  180. package/dist/hooks/HookRunner.js +0 -111
  181. package/dist/hooks/builtin/logging.d.ts +0 -5
  182. package/dist/hooks/builtin/logging.js +0 -98
  183. package/dist/hooks/builtin/metrics.d.ts +0 -7
  184. package/dist/hooks/builtin/metrics.js +0 -60
  185. package/dist/hooks/builtin/observability.d.ts +0 -20
  186. package/dist/hooks/builtin/observability.js +0 -572
  187. package/dist/hooks/helpers.d.ts +0 -22
  188. package/dist/hooks/helpers.js +0 -183
  189. package/dist/hooks/index.d.ts +0 -8
  190. package/dist/hooks/index.js +0 -6
  191. package/dist/realtime/RealtimeAudioClient.d.ts +0 -166
  192. package/dist/realtime/RealtimeAudioClient.js +0 -14
  193. package/dist/realtime/RealtimeSessionHandle.d.ts +0 -6
  194. package/dist/realtime/RealtimeSessionHandle.js +0 -1
  195. package/dist/realtime/index.d.ts +0 -2
  196. package/dist/realtime/index.js +0 -1
  197. package/dist/runtime/channels/VoiceDriver.d.ts +0 -31
  198. package/dist/runtime/channels/VoiceDriver.js +0 -321
  199. package/dist/runtime/channels/voiceTools.d.ts +0 -9
  200. package/dist/runtime/channels/voiceTools.js +0 -51
  201. package/dist/tools/errorHandling.d.ts +0 -35
  202. package/dist/tools/errorHandling.js +0 -145
  203. package/dist/types/voice.d.ts +0 -517
  204. package/dist/types/voice.js +0 -14
  205. package/dist/utils/isRecord.d.ts +0 -1
  206. package/dist/utils/isRecord.js +0 -3
  207. package/dist/utils/messageNormalization.d.ts +0 -2
  208. package/dist/utils/messageNormalization.js +0 -137
  209. /package/dist/{foundation/AgentDefinition.js → types/knowledge.js} +0 -0
  210. /package/dist/{foundation/ConversationEventLog.js → types/trace.js} +0 -0
@@ -1,10 +1,6 @@
1
- import type { ModelMessage } from 'ai';
2
- import type { SessionEndMetadata, TurnUsage } from './telemetry.js';
3
- import type { AgentStreamPart } from './processors.js';
4
- import type { AgentContext, RunContext, Session, ToolCallRecord } from './session.js';
5
- import type { HarnessStreamPart } from './voice.js';
1
+ import type { AgentContext, RunContext } from './session.js';
2
+ import type { StreamPart } from './stream.js';
6
3
  import type { RefineDecision, ValidateDecision } from '../capabilities/index.js';
7
- import type { ConversationOutcome, ConversationOutcomeRecord } from '../outcomes/types.js';
8
4
  import type { ChannelId } from './session.js';
9
5
  export interface RefinementStageResult {
10
6
  proceed: boolean;
@@ -24,7 +20,7 @@ export interface Hook {
24
20
  name: string;
25
21
  onTurnStart?: (ctx: AgentContext, input: string) => Promise<void>;
26
22
  onTurnEnd?: (ctx: AgentContext) => Promise<void>;
27
- onStreamPart?: (ctx: AgentContext, part: AgentStreamPart) => Promise<void>;
23
+ onStreamPart?: (ctx: AgentContext, part: StreamPart) => Promise<void>;
28
24
  onAgentSwitch?: (ctx: AgentContext, from: string, to: string) => Promise<void>;
29
25
  onError?: (ctx: AgentContext, error: Error) => Promise<void>;
30
26
  }
@@ -36,73 +32,6 @@ export interface StopCondition {
36
32
  name: string;
37
33
  check: (context: RunContext) => StopConditionResult;
38
34
  }
39
- export interface StepResult {
40
- text?: string;
41
- toolCalls: ToolCallRecord[];
42
- finishReason: string;
43
- tokensUsed: number;
44
- handoffTo?: string;
45
- }
46
- export interface TurnSummary {
47
- sessionId: string;
48
- userId?: string;
49
- agentId: string;
50
- messageCount: number;
51
- toolCallCount: number;
52
- totalTokens: number;
53
- }
54
- export interface TurnEndHookResult {
55
- outcome?: ConversationOutcome;
56
- reason?: string;
57
- }
58
- export interface HarnessHooks {
59
- onStart?: (context: RunContext) => Promise<void>;
60
- onEnd?: (context: RunContext, result: {
61
- success: boolean;
62
- error?: Error;
63
- }) => Promise<void>;
64
- onStepStart?: (context: RunContext, step: number) => Promise<void>;
65
- onStepEnd?: (context: RunContext, step: number, result: StepResult) => Promise<void>;
66
- onToolCall?: (context: RunContext, call: ToolCallRecord) => Promise<void>;
67
- onToolResult?: (context: RunContext, call: ToolCallRecord) => Promise<void>;
68
- onToolError?: (context: RunContext, call: ToolCallRecord, error: Error) => Promise<void>;
69
- onTurnEnd?: (context: RunContext, summary: TurnSummary) => Promise<TurnEndHookResult | void>;
70
- onAgentStart?: (context: RunContext, agentId: string) => Promise<void>;
71
- onAgentEnd?: (context: RunContext, agentId: string) => Promise<void>;
72
- onHandoff?: (context: RunContext, from: string, to: string, reason: string) => Promise<void>;
73
- onError?: (context: RunContext, error: Error) => Promise<void>;
74
- onMessage?: (context: RunContext, message: ModelMessage) => Promise<void>;
75
- onStreamPart?: (context: RunContext, part: HarnessStreamPart) => Promise<void>;
76
- onPersistenceError?: (session: Session, error: Error) => Promise<void>;
77
- onMemoryIngest?: (context: RunContext, session: Session) => Promise<boolean | void>;
78
- onMemoryIngested?: (context: RunContext, session: Session) => Promise<void>;
79
- onBeforeModelCall?: (context: RunContext, data: BeforeModelCallData) => Promise<BeforeModelCallResult | void>;
80
- onSessionEnd?: (session: Session, metadata: SessionEndMetadata) => Promise<void>;
81
- onConversationEnd?: (session: Session, outcome: ConversationOutcomeRecord) => Promise<{
82
- csatInvited: boolean;
83
- csatChannel?: 'email' | 'in-app' | 'sms';
84
- } | void>;
85
- onTokensUpdate?: (context: RunContext, turn: TurnUsage) => Promise<void> | void;
86
- }
87
- export interface BeforeModelCallData {
88
- systemPrompt: string;
89
- messages: ModelMessage[];
90
- estimatedTokens: number;
91
- agentId: string;
92
- tokenBreakdown: {
93
- basePrompt: number;
94
- autoRetrieve: number;
95
- workingMemory: number;
96
- extraction: number;
97
- longTermMemory: number;
98
- policyInjections: number;
99
- messageHistory: number;
100
- };
101
- }
102
- export interface BeforeModelCallResult {
103
- systemPrompt?: string;
104
- messages?: ModelMessage[];
105
- }
106
35
  export interface StreamOptions {
107
36
  input: string;
108
37
  sessionId?: string;
@@ -1,11 +1,19 @@
1
1
  import type { ModelMessage } from 'ai';
2
- import type { RetrievalCacheAdapter } from './voice.js';
2
+ import type { RetrievalCacheAdapter } from './knowledge.js';
3
3
  import type { RefinementStageResult } from './runtime.js';
4
4
  import type { EscalationReason, EscalationOutcome } from '../escalation/types.js';
5
5
  import type { ConversationOutcomeRecord, CsatRecord } from '../outcomes/types.js';
6
6
  import type { PersonaExperimentMetadata } from '../persona/types.js';
7
7
  import type { ConversationAuditEntry } from '../audit/types.js';
8
8
  export type ChannelId = 'web' | 'email' | 'sms' | 'voice' | 'api' | 'slack' | 'discord' | (string & {});
9
+ /** Structured goal/thread entry on session.workingMemory.__goals (G5). */
10
+ export type GoalStatus = 'open' | 'resolved';
11
+ export interface TrackedGoal {
12
+ topic: string;
13
+ status: GoalStatus;
14
+ lastTurn: number;
15
+ note?: string;
16
+ }
9
17
  export interface WorkingMemory {
10
18
  get<T>(key: string): T | undefined;
11
19
  set<T>(key: string, value: T): void;
@@ -42,6 +50,8 @@ export interface Session {
42
50
  pendingRefinement?: RefinementStageResult;
43
51
  /** @internal Pending key-facts extraction promises. Awaited before session save. */
44
52
  __pendingExtractions?: Promise<void>[];
53
+ /** Optimistic-concurrency version; must match the stored row on save (C2 CAS). */
54
+ version?: number;
45
55
  }
46
56
  export interface SessionMetadata {
47
57
  createdAt: Date;
@@ -16,4 +16,18 @@ export interface SkillStoreLike {
16
16
  getAllSkills?(): SkillLike[] | Promise<SkillLike[]>;
17
17
  loadAllSkills?(): Promise<SkillLike[]>;
18
18
  }
19
- export type SkillSource = SkillLike | SkillLike[] | SkillStoreLike;
19
+ /**
20
+ * One way to supply skills. A `string` is a filesystem root scanned for
21
+ * `<dir>/SKILL.md`, resolved against the agent's `workspace` filesystem.
22
+ */
23
+ export type SkillEntry = SkillLike | SkillStoreLike | string;
24
+ /**
25
+ * Skills for an agent: one entry, or an ordered array mixing inline skills, stores, and
26
+ * workspace paths. **Later entries win** on a name collision, so layering reads in the
27
+ * order you write it:
28
+ *
29
+ * ```ts
30
+ * skills: ['/skills/org', '/skills/team', defineSkill({ name: 'override', … })]
31
+ * ```
32
+ */
33
+ export type SkillSource = SkillEntry | ReadonlyArray<SkillEntry>;
@@ -1,127 +1,197 @@
1
1
  import type { ConversationOutcome } from '../outcomes/types.js';
2
2
  import type { ChoiceOption } from './selection.js';
3
3
  import type { EscalationReason } from '../escalation/types.js';
4
- /**
5
- * Authoritative runtime stream union (`runFlow` / `Runtime` emit).
6
- * `types/voice.ts` defines a separate voice/realtime union that intentionally
7
- * does not include `{ type: 'interactive' }`.
8
- */
9
- export type HarnessStreamPart = {
10
- type: 'text-start';
4
+ export type StreamChannel = 'client' | 'internal';
5
+ export interface StreamPartBase<Channel extends StreamChannel = StreamChannel> {
6
+ channel: Channel;
7
+ }
8
+ export interface TextStartPayload {
11
9
  id: string;
12
- } | {
13
- type: 'text-delta';
10
+ }
11
+ export interface TextDeltaPayload {
14
12
  id: string;
15
13
  delta: string;
16
- } | {
17
- type: 'text-end';
14
+ }
15
+ export interface TextEndPayload {
18
16
  id: string;
19
- } | {
20
- type: 'text-cancel';
17
+ }
18
+ export interface TextCancelPayload {
21
19
  id: string;
22
20
  reason: string;
23
- } | {
24
- type: 'tool-call';
21
+ }
22
+ export interface ToolCallPayload {
25
23
  toolName: string;
26
24
  args: unknown;
27
25
  toolCallId?: string;
28
- } | {
29
- type: 'tool-result';
26
+ }
27
+ export interface ToolResultPayload {
30
28
  toolName: string;
31
29
  result: unknown;
32
30
  toolCallId?: string;
33
- } | {
34
- type: 'flow-enter';
31
+ /** A chunk from a still-running async-iterable tool. The final result follows without it. */
32
+ preliminary?: boolean;
33
+ }
34
+ export interface FlowEnterPayload {
35
35
  flow: string;
36
- } | {
37
- type: 'flow-end';
36
+ }
37
+ export interface FlowEndPayload {
38
38
  flow: string;
39
39
  reason: string;
40
- } | {
41
- type: 'node-enter';
40
+ }
41
+ export interface NodeEnterPayload {
42
42
  nodeName: string;
43
- } | {
44
- type: 'node-exit';
43
+ }
44
+ export interface NodeExitPayload {
45
45
  nodeName: string;
46
- } | {
47
- type: 'flow-transition';
46
+ }
47
+ export interface FlowTransitionPayload {
48
48
  from: string;
49
49
  to: string;
50
- } | {
51
- type: 'handoff';
50
+ }
51
+ export interface HandoffPayload {
52
52
  targetAgent: string;
53
53
  reason?: string;
54
- } | {
55
- type: 'interrupted';
54
+ }
55
+ export interface InterruptedPayload {
56
56
  reason: string;
57
57
  lastStep: number;
58
- } | {
59
- type: 'paused';
58
+ }
59
+ export interface PausedPayload {
60
60
  waitingFor: string;
61
- } | {
62
- type: 'conversation-outcome';
61
+ }
62
+ export interface ConversationOutcomePayload {
63
63
  outcome: ConversationOutcome;
64
- } | {
65
- type: 'interactive';
64
+ }
65
+ export interface InteractivePayload {
66
66
  nodeId: string;
67
67
  options: ChoiceOption[];
68
68
  prompt: string;
69
- } | {
70
- type: 'turn-end';
71
- } | {
72
- type: 'pipeline-validation-block';
69
+ }
70
+ export interface TurnEndPayload {
71
+ }
72
+ export interface PipelineValidationBlockPayload {
73
73
  rationale: string;
74
74
  userFacingMessage?: string;
75
- } | {
76
- type: 'safety-blocked';
75
+ }
76
+ export interface SafetyBlockedPayload {
77
77
  moderator: string;
78
78
  rationale: string;
79
79
  userFacingMessage: string;
80
80
  handlerOutcome?: 'queued' | 'connected' | 'failed';
81
- } | {
82
- /** An agent-initiated (scheduled wake) turn — there is no new user message. */
83
- type: 'wake';
81
+ }
82
+ export interface WakePayload {
84
83
  reason: string;
85
- } | {
86
- type: 'escalation';
84
+ }
85
+ export interface EscalationPayload {
87
86
  reason: string;
88
87
  category?: EscalationReason;
89
- /** Result of the configured escalation handler. */
90
88
  outcome: 'queued' | 'connected' | 'failed';
91
- /** The LLM handoff brief included in the request, when generated. */
92
89
  summary?: string;
93
- } | {
94
- type: 'context-compacted';
95
- /** Estimated history tokens before/after compaction. */
90
+ }
91
+ export interface ContextCompactedPayload {
96
92
  beforeTokens: number;
97
93
  afterTokens: number;
98
- /** Number of older messages folded into the summary. */
99
94
  summarizedCount: number;
100
- } | {
101
- type: 'compaction-skipped';
95
+ }
96
+ export interface CompactionSkippedPayload {
102
97
  reason: string;
103
- } | {
104
- type: 'context-overflow-recovered';
105
- /** Partial assistant/tool messages stripped from the failed turn. */
98
+ }
99
+ export interface ContextOverflowRecoveredPayload {
106
100
  strippedCount: number;
107
- /** Whether the forced post-recovery compaction actually compacted. */
108
101
  compacted: boolean;
109
- } | {
110
- type: 'error';
102
+ }
103
+ export interface ErrorPayload {
111
104
  error: string;
112
- } | {
113
- type: 'custom';
105
+ }
106
+ export interface CustomPayload {
114
107
  name: string;
115
108
  data: unknown;
116
- } | {
117
- type: 'done';
109
+ }
110
+ export interface DonePayload {
118
111
  sessionId: string;
119
- };
112
+ usage?: {
113
+ inputTokens?: number;
114
+ outputTokens?: number;
115
+ contextTokens?: number;
116
+ };
117
+ }
118
+ export interface KnowledgeCacheHitPayload {
119
+ query: string;
120
+ resultCount: number;
121
+ latencyMs: number;
122
+ }
123
+ export interface KnowledgeCacheMissPayload {
124
+ query: string;
125
+ latencyMs: number;
126
+ }
127
+ export interface KnowledgeSearchPayload {
128
+ query: string;
129
+ resultCount: number;
130
+ latencyMs: number;
131
+ layer: 'cache' | 'hybrid';
132
+ }
133
+ export interface KnowledgeQualityCheckPayload {
134
+ query: string;
135
+ quality: 'high' | 'medium' | 'low';
136
+ topScore: number;
137
+ avgScore: number;
138
+ coverageEstimate: number;
139
+ }
140
+ export interface KnowledgeReformulationPayload {
141
+ originalQuery: string;
142
+ reformulatedQuery: string;
143
+ trigger: 'inline' | 'background';
144
+ latencyMs: number;
145
+ }
146
+ interface StreamPayloadMap {
147
+ 'text-start': TextStartPayload;
148
+ 'text-delta': TextDeltaPayload;
149
+ 'text-end': TextEndPayload;
150
+ 'text-cancel': TextCancelPayload;
151
+ 'tool-call': ToolCallPayload;
152
+ 'tool-result': ToolResultPayload;
153
+ 'flow-enter': FlowEnterPayload;
154
+ 'flow-end': FlowEndPayload;
155
+ 'node-enter': NodeEnterPayload;
156
+ 'node-exit': NodeExitPayload;
157
+ 'flow-transition': FlowTransitionPayload;
158
+ handoff: HandoffPayload;
159
+ interrupted: InterruptedPayload;
160
+ paused: PausedPayload;
161
+ 'conversation-outcome': ConversationOutcomePayload;
162
+ interactive: InteractivePayload;
163
+ 'turn-end': TurnEndPayload;
164
+ 'pipeline-validation-block': PipelineValidationBlockPayload;
165
+ 'safety-blocked': SafetyBlockedPayload;
166
+ wake: WakePayload;
167
+ escalation: EscalationPayload;
168
+ 'context-compacted': ContextCompactedPayload;
169
+ 'compaction-skipped': CompactionSkippedPayload;
170
+ 'context-overflow-recovered': ContextOverflowRecoveredPayload;
171
+ error: ErrorPayload;
172
+ custom: CustomPayload;
173
+ done: DonePayload;
174
+ 'knowledge-cache-hit': KnowledgeCacheHitPayload;
175
+ 'knowledge-cache-miss': KnowledgeCacheMissPayload;
176
+ 'knowledge-search': KnowledgeSearchPayload;
177
+ 'knowledge-quality-check': KnowledgeQualityCheckPayload;
178
+ 'knowledge-reformulation': KnowledgeReformulationPayload;
179
+ }
180
+ type ClientStreamPartType = 'text-start' | 'text-delta' | 'text-end' | 'text-cancel' | 'conversation-outcome' | 'error' | 'done';
181
+ type ChannelFor<Type extends keyof StreamPayloadMap> = Type extends ClientStreamPartType ? 'client' : 'internal';
182
+ export type StreamPart = {
183
+ [Type in keyof StreamPayloadMap]: StreamPartBase<ChannelFor<Type>> & {
184
+ type: Type;
185
+ payload: StreamPayloadMap[Type];
186
+ };
187
+ }[keyof StreamPayloadMap];
188
+ export declare const PART_CHANNEL: Record<StreamPart['type'], StreamChannel>;
120
189
  export interface TurnHandle extends Promise<import('./channel.js').TurnResult> {
121
- readonly events: AsyncIterable<HarnessStreamPart>;
190
+ readonly events: AsyncIterable<StreamPart>;
122
191
  toResponseStream(format?: 'sse' | 'ndjson'): ReadableStream;
123
192
  toUIMessageStreamResponse(opts?: {
124
193
  sessionId?: string;
125
194
  }): Response;
126
195
  cancel(reason?: string): void;
127
196
  }
197
+ export {};
@@ -1 +1,34 @@
1
- export {};
1
+ export const PART_CHANNEL = {
2
+ 'text-start': 'client',
3
+ 'text-delta': 'client',
4
+ 'text-end': 'client',
5
+ 'text-cancel': 'client',
6
+ 'tool-call': 'internal',
7
+ 'tool-result': 'internal',
8
+ 'flow-enter': 'internal',
9
+ 'flow-end': 'internal',
10
+ 'node-enter': 'internal',
11
+ 'node-exit': 'internal',
12
+ 'flow-transition': 'internal',
13
+ handoff: 'internal',
14
+ interrupted: 'internal',
15
+ paused: 'internal',
16
+ 'conversation-outcome': 'client',
17
+ interactive: 'internal',
18
+ 'turn-end': 'internal',
19
+ 'pipeline-validation-block': 'internal',
20
+ 'safety-blocked': 'internal',
21
+ wake: 'internal',
22
+ escalation: 'internal',
23
+ 'context-compacted': 'internal',
24
+ 'compaction-skipped': 'internal',
25
+ 'context-overflow-recovered': 'internal',
26
+ error: 'client',
27
+ custom: 'internal',
28
+ done: 'client',
29
+ 'knowledge-cache-hit': 'internal',
30
+ 'knowledge-cache-miss': 'internal',
31
+ 'knowledge-search': 'internal',
32
+ 'knowledge-quality-check': 'internal',
33
+ 'knowledge-reformulation': 'internal',
34
+ };
@@ -0,0 +1,52 @@
1
+ export type SpanKind = 'turn' | 'flow' | 'node' | 'tool' | 'handoff' | 'llm';
2
+ export interface AgentSpan {
3
+ traceId: string;
4
+ spanId: string;
5
+ parentSpanId?: string;
6
+ name: string;
7
+ kind: SpanKind;
8
+ startTime: number;
9
+ endTime?: number;
10
+ status: 'ok' | 'error';
11
+ events?: Array<{
12
+ name: string;
13
+ time: number;
14
+ attributes?: Record<string, unknown>;
15
+ }>;
16
+ attributes: {
17
+ sessionId: string;
18
+ /** Agent active when the span opened; a turn span keeps its initiating agent across handoffs. */
19
+ agentId?: string;
20
+ activeFlow?: string;
21
+ nodeId?: string;
22
+ toolName?: string;
23
+ handoffFrom?: string;
24
+ handoffTo?: string;
25
+ input?: unknown;
26
+ output?: unknown;
27
+ error?: string;
28
+ /** Input tokens consumed by this turn (delta — for cost attribution). */
29
+ tokensIn?: number;
30
+ /** Output tokens generated by this turn (delta — for cost attribution). */
31
+ tokensOut?: number;
32
+ /** Context-window occupancy at this turn (last prompt tokens — a snapshot, not a delta). */
33
+ contextTokens?: number;
34
+ };
35
+ }
36
+ export interface AgentTrace {
37
+ traceId: string;
38
+ sessionId: string;
39
+ spans: AgentSpan[];
40
+ answer: string;
41
+ usedTool: boolean;
42
+ toolCalls: Array<{
43
+ name: string;
44
+ args: unknown;
45
+ }>;
46
+ toolResults: Array<{
47
+ name: string;
48
+ result: unknown;
49
+ }>;
50
+ startedAt: number;
51
+ endedAt?: number;
52
+ }
package/guides/AGENTS.md CHANGED
@@ -43,7 +43,7 @@ const runtime = createRuntime({
43
43
 
44
44
  const handle = runtime.run({ input: 'Hello', sessionId: 'demo' });
45
45
  for await (const part of handle.events) {
46
- if (part.type === 'text-delta') process.stdout.write(part.delta);
46
+ if (part.type === 'text-delta') process.stdout.write(part.payload.delta);
47
47
  }
48
48
  await handle;
49
49
  ```
@@ -221,7 +221,7 @@ const handle = runtime.run({
221
221
  sessionId: 'demo',
222
222
  });
223
223
  for await (const part of handle.events) {
224
- if (part.type === 'text-delta') process.stdout.write(part.delta);
224
+ if (part.type === 'text-delta') process.stdout.write(part.payload.delta);
225
225
  }
226
226
  await handle;
227
227
  ```
@@ -260,7 +260,7 @@ See [standalone-agent.ts](../examples/agents/standalone-agent.ts) (Example 4) fo
260
260
  - `AgentConfig` — Agent configuration returned by `defineAgent`
261
261
  - `Route`, `RoutingPolicy` — Routing declarations on an agent
262
262
  - `Flow`, `FlowNode` — Flow graph types from `defineFlow` and node builders
263
- - `HarnessStreamPart` — Stream event union (`text-delta`, `handoff`, `flow-transition`, etc.)
263
+ - `StreamPart` — Stream event union (`text-delta`, `handoff`, `flow-transition`, etc.)
264
264
  - `TurnHandle` — Return value of `runtime.run`; async iterable via `.events`
265
265
  - `ToolExecutionOptions`, `ToolExecutionContext` — Tool execution context
266
266
  - `getRuntimeFromContext()` — Read runtime from tool context when available
@@ -8,8 +8,8 @@ This verification was run after runtime policy-profile changes to check for regr
8
8
 
9
9
  Covered suites:
10
10
 
11
- 1. `packages/kuralle-core/examples/agents` (Line parity set)
12
- 2. `packages/kuralle-core/examples/flows` (Pipecat parity set)
11
+ 1. `packages/core/examples/agents` (Line parity set)
12
+ 2. `packages/core/examples/flows` (Pipecat parity set)
13
13
  3. Extended package examples (`kuralle-tools`, `kuralle-redis-store`)
14
14
 
15
15
  ## Results
@@ -30,8 +30,8 @@ Interpretation:
30
30
 
31
31
  Non-pass items:
32
32
 
33
- 1. `packages/kuralle-redis-store/examples/local-redis/test.ts` -> `SKIPPED`
34
- 2. `packages/kuralle-redis-store/examples/local-redis/multi-turn.ts` -> `SKIPPED`
33
+ 1. `packages/redis-store/examples/local-redis/test.ts` -> `SKIPPED`
34
+ 2. `packages/redis-store/examples/local-redis/multi-turn.ts` -> `SKIPPED`
35
35
  - Cause: local Redis was not started.
36
36
 
37
37
  ## Verdict
package/guides/FLOWS.md CHANGED
@@ -57,7 +57,7 @@ const agent = defineAgent({
57
57
  const runtime = createRuntime({ agents: [agent], defaultAgentId: 'booking' });
58
58
  const handle = runtime.run({ input: 'Hi', sessionId: 'demo' });
59
59
  for await (const part of handle.events) {
60
- if (part.type === 'text-delta') process.stdout.write(part.delta);
60
+ if (part.type === 'text-delta') process.stdout.write(part.payload.delta);
61
61
  }
62
62
  await handle;
63
63
  ```
@@ -52,7 +52,7 @@ const runtime = createRuntime({
52
52
 
53
53
  const handle = runtime.run({ input: 'Hello there', sessionId: 'demo' });
54
54
  for await (const part of handle.events) {
55
- if (part.type === 'text-delta') process.stdout.write(part.delta);
55
+ if (part.type === 'text-delta') process.stdout.write(part.payload.delta);
56
56
  }
57
57
  await handle;
58
58
  ```
package/guides/RUNTIME.md CHANGED
@@ -11,7 +11,7 @@
11
11
 
12
12
  ## Stream Events
13
13
 
14
- `runtime.run()` returns a `TurnHandle` with an `.events` async iterable of `HarnessStreamPart` items.
14
+ `runtime.run()` returns a `TurnHandle` with an `.events` async iterable of `StreamPart` items.
15
15
 
16
16
  ### Web UI (AI SDK native, 0.5.0+)
17
17
 
@@ -24,29 +24,29 @@ return handle.toUIMessageStreamResponse({ sessionId });
24
24
 
25
25
  Kuralle orchestration events map to typed `data-kuralle-*` parts (see `docs/adr/0005-ai-sdk-native-uimessage-default.md`). Import `KuralleUIMessage` for compile-time-safe `message.parts`.
26
26
 
27
- With `@kuralle-agents/hono-server`, `POST /api/chat/sse` defaults to this native wire. Append `?format=raw` for legacy `HarnessStreamPart` JSON-SSE.
27
+ With `@kuralle-agents/hono-server`, `POST /api/chat/sse` defaults to this native wire. Append `?format=raw` for legacy `StreamPart` JSON-SSE.
28
28
 
29
- ### Direct `HarnessStreamPart` consumption
29
+ ### Direct `StreamPart` consumption
30
30
 
31
- For CLI scripts, cascaded voice, messaging, or custom transports, iterate `handle.events` directly. Typical usage renders `text-delta` chunks via `part.delta`.
31
+ For CLI scripts, messaging, or custom transports, iterate `handle.events` directly. Every part has `{ channel, type, payload }`; render `text-delta` chunks via `part.payload.delta`.
32
32
 
33
33
  Common types:
34
- - `text-delta`
35
- - `tool-call`, `tool-result`, `tool-error`
34
+ - `text-start`, `text-delta`, `text-end`, `text-cancel`
35
+ - `tool-call`, `tool-result`
36
36
  - `handoff`
37
- - `node-enter`, `flow-transition`, `flow-end`
37
+ - `flow-enter`, `node-enter`, `node-exit`, `flow-transition`, `flow-end`
38
38
  - `custom` (flow/runtime emitted app events)
39
- - `agent-start`, `agent-end`
40
39
  - `turn-end`, `done`, `error`
40
+ - `knowledge-cache-hit`, `knowledge-cache-miss`, `knowledge-search`, `knowledge-quality-check`, `knowledge-reformulation`
41
41
 
42
- Internal events can expose operational details. Treat them as privileged data.
42
+ Use `PART_CHANNEL` or the envelope's `channel` field to distinguish client events from privileged internal events.
43
43
 
44
44
  ## Stream Callback (Persistence Defaults)
45
45
 
46
46
  Use `streamCallback` when sending runtime events to file/webhook/DB/queue sinks.
47
47
 
48
48
  Default behavior is message-oriented:
49
- - emits: `input`, `done`, `error`, `tripwire`, `tool-call`, `tool-result`, `tool-error`, `flow-transition`, `handoff`
49
+ - emits terminal events plus configured tool and transition events
50
50
  - does not emit `text-delta` tokens unless enabled
51
51
  - attaches final assistant text as `fullText` on terminal events
52
52
  - if no sink is configured, adapter is a no-op
@@ -95,7 +95,6 @@ To prevent internal runtime state from leaking into the model's context window:
95
95
 
96
96
  Runtime checkpoints session state automatically on critical events:
97
97
  - `tool-result`
98
- - `tool-error`
99
98
  - `flow-transition`
100
99
  - handoff state updates (after `activeAgentId` mutation)
101
100
 
@@ -135,21 +134,27 @@ const runtime = createRuntime({
135
134
  ],
136
135
  hooks: {
137
136
  onStreamPart: async (ctx, part) => {
138
- if (part.type === 'error') console.error(part.error);
137
+ if (part.type === 'error') console.error(part.payload.error);
139
138
  },
140
139
  },
141
140
  });
142
141
  ```
143
142
 
144
- ## Hooks
143
+ ## Tracing
145
144
 
146
- Use hooks for logging, metrics, and audit trails without polluting prompts.
145
+ Use a trace sink for logging, metrics, and audit trails without polluting prompts.
147
146
 
148
147
  ```ts
148
+ const loggingSink: TraceSink = {
149
+ write(span) {
150
+ console.log(JSON.stringify(span));
151
+ },
152
+ };
153
+
149
154
  const runtime = createRuntime({
150
155
  agents,
151
156
  defaultAgentId: 'router',
152
- hooks: loggingHooks(),
157
+ tracing: { sinks: [loggingSink] },
153
158
  });
154
159
  ```
155
160
 
package/guides/TOOLS.md CHANGED
@@ -152,7 +152,7 @@ const handle = runtime.run({
152
152
  sessionId: 'demo',
153
153
  });
154
154
  for await (const part of handle.events) {
155
- if (part.type === 'text-delta') process.stdout.write(part.delta);
155
+ if (part.type === 'text-delta') process.stdout.write(part.payload.delta);
156
156
  }
157
157
  await handle;
158
158
  ```