@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.
- package/README.md +89 -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 +2 -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/collectDigression.d.ts +5 -2
- package/dist/flow/collectDigression.js +48 -10
- package/dist/flow/collectUntilComplete.js +13 -5
- 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 +3 -2
- package/dist/flow/extraction.js +14 -4
- package/dist/flow/reduceTransition.d.ts +2 -2
- package/dist/flow/reduceTransition.js +7 -3
- package/dist/flow/runFlow.js +97 -17
- 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 +15 -15
- package/dist/index.js +9 -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 +13 -6
- package/dist/prompts/index.d.ts +1 -1
- package/dist/prompts/types.d.ts +9 -2
- package/dist/runtime/InMemoryRetrievalCache.d.ts +25 -0
- package/dist/runtime/InMemoryRetrievalCache.js +59 -0
- package/dist/runtime/KnowledgeProvider.d.ts +3 -2
- package/dist/runtime/KnowledgeProvider.js +60 -31
- package/dist/runtime/Runtime.d.ts +47 -1
- package/dist/runtime/Runtime.js +273 -36
- package/dist/runtime/TokenAccumulator.d.ts +7 -0
- package/dist/runtime/TokenAccumulator.js +7 -0
- package/dist/runtime/TraceRecorder.d.ts +51 -0
- package/dist/runtime/TraceRecorder.js +326 -0
- package/dist/runtime/buildAgentToolSurface.js +1 -1
- package/dist/runtime/channels/TextDriver.js +57 -31
- package/dist/runtime/channels/executeModelTool.d.ts +14 -1
- package/dist/runtime/channels/executeModelTool.js +132 -3
- 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/inputBuffer.d.ts +1 -0
- package/dist/runtime/channels/inputBuffer.js +9 -0
- 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 +14 -10
- package/dist/runtime/compaction.d.ts +2 -0
- package/dist/runtime/compaction.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 +147 -60
- package/dist/runtime/durable/RunStore.d.ts +16 -0
- package/dist/runtime/durable/RunStore.js +7 -1
- package/dist/runtime/durable/SessionRunStore.d.ts +7 -2
- package/dist/runtime/durable/SessionRunStore.js +136 -34
- package/dist/runtime/durable/idempotency.d.ts +1 -0
- package/dist/runtime/durable/idempotency.js +3 -0
- package/dist/runtime/durable/replay.js +7 -2
- package/dist/runtime/durable/types.d.ts +11 -0
- package/dist/runtime/goals.d.ts +18 -0
- package/dist/runtime/goals.js +158 -0
- 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/grounding/knowledge.js +1 -1
- package/dist/runtime/handoffContinuation.d.ts +20 -0
- package/dist/runtime/handoffContinuation.js +30 -0
- package/dist/runtime/handoffOscillation.d.ts +6 -0
- package/dist/runtime/handoffOscillation.js +17 -0
- package/dist/runtime/hostLoop.js +37 -6
- package/dist/runtime/index.d.ts +4 -3
- package/dist/runtime/index.js +2 -1
- package/dist/runtime/openRun.d.ts +2 -0
- package/dist/runtime/openRun.js +46 -17
- 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/policies/limits.d.ts +1 -0
- package/dist/runtime/policies/limits.js +3 -0
- package/dist/runtime/runHookSafely.d.ts +3 -0
- package/dist/runtime/runHookSafely.js +19 -0
- package/dist/runtime/select.d.ts +5 -1
- package/dist/runtime/select.js +30 -1
- package/dist/runtime/turnTokenUsage.d.ts +28 -0
- package/dist/runtime/turnTokenUsage.js +70 -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/session/SessionStore.d.ts +6 -0
- package/dist/session/SessionStore.js +12 -1
- package/dist/session/stores/MemoryStore.d.ts +1 -1
- package/dist/session/stores/MemoryStore.js +16 -2
- package/dist/session/testing.d.ts +6 -1
- package/dist/session/testing.js +34 -0
- package/dist/session/utils.d.ts +3 -0
- package/dist/session/utils.js +23 -0
- 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 +75 -36
- package/dist/tools/effect/defineTool.d.ts +11 -0
- package/dist/tools/effect/defineTool.js +3 -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/tracing/MemoryTraceStore.d.ts +16 -0
- package/dist/tracing/MemoryTraceStore.js +56 -0
- package/dist/tracing/OtelTraceSink.d.ts +127 -0
- package/dist/tracing/OtelTraceSink.js +101 -0
- package/dist/tracing/TraceStore.d.ts +19 -0
- package/dist/tracing/TraceStore.js +32 -0
- package/dist/tracing/index.d.ts +3 -0
- package/dist/tracing/index.js +3 -0
- package/dist/tracing/testing.d.ts +3 -0
- package/dist/tracing/testing.js +45 -0
- package/dist/types/agentConfig.d.ts +2 -1
- package/dist/types/channel.d.ts +14 -1
- package/dist/types/effectTool.d.ts +6 -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 -15
- package/dist/types/index.js +8 -12
- package/dist/types/knowledge.d.ts +213 -0
- package/dist/types/processors.d.ts +0 -58
- package/dist/types/run-context.d.ts +16 -7
- package/dist/types/runtime.d.ts +3 -74
- package/dist/types/session.d.ts +11 -1
- package/dist/types/skills.d.ts +15 -1
- package/dist/types/stream.d.ts +138 -68
- package/dist/types/stream.js +34 -1
- package/dist/types/trace.d.ts +52 -0
- package/guides/AGENTS.md +3 -3
- package/guides/EXAMPLE_VERIFICATION.md +4 -4
- 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 +13 -14
- package/dist/foundation/AgentDefinition.d.ts +0 -17
- package/dist/foundation/ConversationEventLog.d.ts +0 -71
- 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/dist/{foundation/ConversationEventLog.js → types/trace.js} +0 -0
package/dist/types/runtime.d.ts
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
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:
|
|
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;
|
package/dist/types/session.d.ts
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import type { ModelMessage } from 'ai';
|
|
2
|
-
import type { RetrievalCacheAdapter } from './
|
|
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;
|
package/dist/types/skills.d.ts
CHANGED
|
@@ -16,4 +16,18 @@ export interface SkillStoreLike {
|
|
|
16
16
|
getAllSkills?(): SkillLike[] | Promise<SkillLike[]>;
|
|
17
17
|
loadAllSkills?(): Promise<SkillLike[]>;
|
|
18
18
|
}
|
|
19
|
-
|
|
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>;
|
package/dist/types/stream.d.ts
CHANGED
|
@@ -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
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
10
|
+
}
|
|
11
|
+
export interface TextDeltaPayload {
|
|
14
12
|
id: string;
|
|
15
13
|
delta: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
14
|
+
}
|
|
15
|
+
export interface TextEndPayload {
|
|
18
16
|
id: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
17
|
+
}
|
|
18
|
+
export interface TextCancelPayload {
|
|
21
19
|
id: string;
|
|
22
20
|
reason: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
21
|
+
}
|
|
22
|
+
export interface ToolCallPayload {
|
|
25
23
|
toolName: string;
|
|
26
24
|
args: unknown;
|
|
27
25
|
toolCallId?: string;
|
|
28
|
-
}
|
|
29
|
-
|
|
26
|
+
}
|
|
27
|
+
export interface ToolResultPayload {
|
|
30
28
|
toolName: string;
|
|
31
29
|
result: unknown;
|
|
32
30
|
toolCallId?: string;
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
36
|
+
}
|
|
37
|
+
export interface FlowEndPayload {
|
|
38
38
|
flow: string;
|
|
39
39
|
reason: string;
|
|
40
|
-
}
|
|
41
|
-
|
|
40
|
+
}
|
|
41
|
+
export interface NodeEnterPayload {
|
|
42
42
|
nodeName: string;
|
|
43
|
-
}
|
|
44
|
-
|
|
43
|
+
}
|
|
44
|
+
export interface NodeExitPayload {
|
|
45
45
|
nodeName: string;
|
|
46
|
-
}
|
|
47
|
-
|
|
46
|
+
}
|
|
47
|
+
export interface FlowTransitionPayload {
|
|
48
48
|
from: string;
|
|
49
49
|
to: string;
|
|
50
|
-
}
|
|
51
|
-
|
|
50
|
+
}
|
|
51
|
+
export interface HandoffPayload {
|
|
52
52
|
targetAgent: string;
|
|
53
53
|
reason?: string;
|
|
54
|
-
}
|
|
55
|
-
|
|
54
|
+
}
|
|
55
|
+
export interface InterruptedPayload {
|
|
56
56
|
reason: string;
|
|
57
57
|
lastStep: number;
|
|
58
|
-
}
|
|
59
|
-
|
|
58
|
+
}
|
|
59
|
+
export interface PausedPayload {
|
|
60
60
|
waitingFor: string;
|
|
61
|
-
}
|
|
62
|
-
|
|
61
|
+
}
|
|
62
|
+
export interface ConversationOutcomePayload {
|
|
63
63
|
outcome: ConversationOutcome;
|
|
64
|
-
}
|
|
65
|
-
|
|
64
|
+
}
|
|
65
|
+
export interface InteractivePayload {
|
|
66
66
|
nodeId: string;
|
|
67
67
|
options: ChoiceOption[];
|
|
68
68
|
prompt: string;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
69
|
+
}
|
|
70
|
+
export interface TurnEndPayload {
|
|
71
|
+
}
|
|
72
|
+
export interface PipelineValidationBlockPayload {
|
|
73
73
|
rationale: string;
|
|
74
74
|
userFacingMessage?: string;
|
|
75
|
-
}
|
|
76
|
-
|
|
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
|
-
|
|
83
|
-
type: 'wake';
|
|
81
|
+
}
|
|
82
|
+
export interface WakePayload {
|
|
84
83
|
reason: string;
|
|
85
|
-
}
|
|
86
|
-
|
|
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
|
-
|
|
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
|
-
|
|
95
|
+
}
|
|
96
|
+
export interface CompactionSkippedPayload {
|
|
102
97
|
reason: string;
|
|
103
|
-
}
|
|
104
|
-
|
|
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
|
-
|
|
102
|
+
}
|
|
103
|
+
export interface ErrorPayload {
|
|
111
104
|
error: string;
|
|
112
|
-
}
|
|
113
|
-
|
|
105
|
+
}
|
|
106
|
+
export interface CustomPayload {
|
|
114
107
|
name: string;
|
|
115
108
|
data: unknown;
|
|
116
|
-
}
|
|
117
|
-
|
|
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<
|
|
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 {};
|
package/dist/types/stream.js
CHANGED
|
@@ -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
|
-
- `
|
|
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/
|
|
12
|
-
2. `packages/
|
|
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/
|
|
34
|
-
2. `packages/
|
|
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 `
|
|
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 `
|
|
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 `
|
|
29
|
+
### Direct `StreamPart` consumption
|
|
30
30
|
|
|
31
|
-
For CLI scripts,
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
##
|
|
143
|
+
## Tracing
|
|
145
144
|
|
|
146
|
-
Use
|
|
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
|
-
|
|
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
|
```
|