@kuralle-agents/core 0.2.1 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/LICENSE +202 -0
  2. package/dist/debug.d.ts +3 -0
  3. package/dist/debug.js +7 -0
  4. package/dist/flow/emitInteractive.d.ts +3 -0
  5. package/dist/flow/emitInteractive.js +43 -0
  6. package/dist/flow/extraction.d.ts +0 -6
  7. package/dist/flow/extraction.js +6 -6
  8. package/dist/flow/nodeBuilders.d.ts +0 -2
  9. package/dist/flow/nodeBuilders.js +1 -1
  10. package/dist/flow/normalizeTransition.d.ts +0 -1
  11. package/dist/flow/normalizeTransition.js +1 -1
  12. package/dist/flow/reduceTransition.js +2 -0
  13. package/dist/flow/runFlow.d.ts +1 -3
  14. package/dist/flow/runFlow.js +13 -2
  15. package/dist/flows/extraction.d.ts +0 -7
  16. package/dist/flows/extraction.js +0 -16
  17. package/dist/flows/template.d.ts +2 -3
  18. package/dist/flows/template.js +0 -3
  19. package/dist/flows/transitions.d.ts +4 -32
  20. package/dist/flows/transitions.js +0 -20
  21. package/dist/guards/ToolEnforcer.js +3 -2
  22. package/dist/index.d.ts +3 -2
  23. package/dist/index.js +1 -1
  24. package/dist/runtime/Runtime.d.ts +4 -0
  25. package/dist/runtime/Runtime.js +9 -0
  26. package/dist/runtime/channels/TextDriver.js +24 -11
  27. package/dist/runtime/channels/VoiceDriver.js +14 -10
  28. package/dist/runtime/channels/index.d.ts +1 -1
  29. package/dist/runtime/channels/index.js +1 -1
  30. package/dist/runtime/channels/voiceTools.d.ts +0 -1
  31. package/dist/runtime/channels/voiceTools.js +0 -10
  32. package/dist/runtime/citations/index.d.ts +1 -12
  33. package/dist/runtime/citations/index.js +0 -36
  34. package/dist/runtime/contextOverflow.d.ts +0 -11
  35. package/dist/runtime/contextOverflow.js +0 -23
  36. package/dist/runtime/ctx.d.ts +2 -2
  37. package/dist/runtime/ctx.js +20 -1
  38. package/dist/runtime/durable/idempotency.d.ts +0 -1
  39. package/dist/runtime/durable/idempotency.js +1 -1
  40. package/dist/runtime/durable/replay.d.ts +0 -1
  41. package/dist/runtime/durable/replay.js +1 -1
  42. package/dist/runtime/durable/types.d.ts +2 -1
  43. package/dist/runtime/openRun.d.ts +2 -0
  44. package/dist/runtime/openRun.js +9 -3
  45. package/dist/runtime/policies/agentTurn.d.ts +0 -5
  46. package/dist/runtime/policies/agentTurn.js +0 -6
  47. package/dist/runtime/policies/limits.d.ts +0 -1
  48. package/dist/runtime/policies/limits.js +1 -1
  49. package/dist/runtime/policies/resolvePolicies.d.ts +0 -3
  50. package/dist/runtime/policies/resolvePolicies.js +0 -13
  51. package/dist/runtime/promptCache.d.ts +0 -4
  52. package/dist/tools/Tool.d.ts +0 -6
  53. package/dist/tools/Tool.js +0 -8
  54. package/dist/tools/effect/ToolExecutor.d.ts +2 -0
  55. package/dist/tools/effect/ToolExecutor.js +6 -1
  56. package/dist/tools/effect/errors.d.ts +10 -0
  57. package/dist/tools/effect/errors.js +15 -0
  58. package/dist/tools/effect/index.d.ts +1 -0
  59. package/dist/tools/effect/index.js +1 -0
  60. package/dist/tools/errorHandling.d.ts +0 -1
  61. package/dist/types/channel.d.ts +2 -1
  62. package/dist/types/flow.d.ts +3 -0
  63. package/dist/types/index.d.ts +1 -0
  64. package/dist/types/index.js +1 -0
  65. package/dist/types/run-context.d.ts +7 -0
  66. package/dist/types/selection.d.ts +18 -0
  67. package/dist/types/selection.js +1 -0
  68. package/dist/types/stream.d.ts +11 -0
  69. package/package.json +14 -10
  70. package/dist/events/index.d.ts +0 -2
  71. package/dist/events/index.js +0 -1
  72. package/dist/flow/index.d.ts +0 -10
  73. package/dist/flow/index.js +0 -10
  74. package/dist/runtime/SessionEventManager.d.ts +0 -16
  75. package/dist/runtime/SessionEventManager.js +0 -148
  76. package/dist/runtime/durable/index.d.ts +0 -5
  77. package/dist/runtime/durable/index.js +0 -5
  78. package/dist/runtime/policies/index.d.ts +0 -3
  79. package/dist/runtime/policies/index.js +0 -3
  80. package/dist/runtime/tokenSessionUtils.d.ts +0 -5
  81. package/dist/runtime/tokenSessionUtils.js +0 -24
  82. package/dist/tools/transferToTriage.d.ts +0 -15
  83. package/dist/tools/transferToTriage.js +0 -48
  84. package/dist/utils/aiStream.d.ts +0 -6
  85. package/dist/utils/aiStream.js +0 -48
  86. package/dist/utils/streamChunk.d.ts +0 -4
  87. package/dist/utils/streamChunk.js +0 -49
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Thrown by `ctx.tool(...)` when a tool declared `needsApproval: true` is denied
3
+ * by a human (the `__approval` signal resolves with `approved: false`). Catch it
4
+ * inside the calling flow `action` node to route gracefully (e.g. escalate or end).
5
+ */
6
+ export class ToolApprovalDeniedError extends Error {
7
+ toolName;
8
+ by;
9
+ constructor(toolName, by) {
10
+ super(`Tool "${toolName}" was denied approval${by ? ` by ${by}` : ''}`);
11
+ this.name = 'ToolApprovalDeniedError';
12
+ this.toolName = toolName;
13
+ this.by = by;
14
+ }
15
+ }
@@ -4,3 +4,4 @@ export type { CoreToolExecutorConfig, CoreExecuteArgs } from './ToolExecutor.js'
4
4
  export { PairingTracker, cancelledPlaceholder, inProgressPlaceholder, } from './pairing.js';
5
5
  export type { ToolCallPair, ToolPairStatus, ToolRequestRecord, ToolResponseRecord, CancelledToolResult, InProgressToolResult, } from './pairing.js';
6
6
  export { validateAndSanitize, validateOutput, ToolValidationError } from './schema.js';
7
+ export { ToolApprovalDeniedError } from './errors.js';
@@ -2,3 +2,4 @@ export { defineTool, toolToAiSdk, buildToolSet } from './defineTool.js';
2
2
  export { CoreToolExecutor } from './ToolExecutor.js';
3
3
  export { PairingTracker, cancelledPlaceholder, inProgressPlaceholder, } from './pairing.js';
4
4
  export { validateAndSanitize, validateOutput, ToolValidationError } from './schema.js';
5
+ export { ToolApprovalDeniedError } from './errors.js';
@@ -20,7 +20,6 @@ export declare function executeWithRetry<T>(fn: () => Promise<T>, config?: {
20
20
  maxDelayMs?: number;
21
21
  onRetry?: (error: Error, attempt: number) => void;
22
22
  }): Promise<T>;
23
- export type CircuitState = 'CLOSED' | 'OPEN' | 'HALF_OPEN';
24
23
  export declare function createCircuitBreaker<T, Args extends unknown[]>(fn: (...args: Args) => Promise<T>, config?: {
25
24
  failureThreshold?: number;
26
25
  resetTimeoutMs?: number;
@@ -27,7 +27,7 @@ export type UserSignal = {
27
27
  type: 'message';
28
28
  input: string;
29
29
  };
30
- export interface ToolResultRecord {
30
+ interface ToolResultRecord {
31
31
  name: string;
32
32
  args: unknown;
33
33
  result: unknown;
@@ -41,3 +41,4 @@ export type TurnControl = {
41
41
  type: 'end';
42
42
  reason: string;
43
43
  };
44
+ export {};
@@ -5,6 +5,7 @@ import type { ContextStrategy } from './context.js';
5
5
  import type { TurnResult } from './channel.js';
6
6
  import type { ActionContext } from './run-context.js';
7
7
  import type { NodeVerify } from '../flow/verify.js';
8
+ import type { ChoiceOption } from './selection.js';
8
9
  export type FlowState = Record<string, unknown>;
9
10
  export interface Flow {
10
11
  name: string;
@@ -42,6 +43,7 @@ export interface CollectNode {
42
43
  schema: StandardSchemaV1;
43
44
  required?: string[];
44
45
  instructions?: (missing: string[], state: FlowState) => Instructions;
46
+ choices?: ChoiceOption[];
45
47
  maxTurns?: number;
46
48
  onComplete: (data: unknown, state: FlowState) => Transition | Promise<Transition>;
47
49
  }
@@ -57,6 +59,7 @@ export interface DecideNode {
57
59
  id: string;
58
60
  instructions: Instructions;
59
61
  schema: StandardSchemaV1;
62
+ choices?: ChoiceOption[];
60
63
  decide: (data: unknown, state: FlowState) => Transition | Promise<Transition>;
61
64
  }
62
65
  export declare function reply(node: Omit<ReplyNode, 'kind'>): ReplyNode;
@@ -1,3 +1,4 @@
1
+ export * from './selection.js';
1
2
  export * from './telemetry.js';
2
3
  export * from './processors.js';
3
4
  export * from './agentConfig.js';
@@ -1,3 +1,4 @@
1
+ export * from './selection.js';
1
2
  export * from './telemetry.js';
2
3
  export * from './processors.js';
3
4
  export * from './agentConfig.js';
@@ -7,6 +7,7 @@ import type { HarnessStreamPart } from './stream.js';
7
7
  import type { RefinementCapability } from '../capabilities/RefinementCapability.js';
8
8
  import type { ValidationCapability } from '../capabilities/ValidationCapability.js';
9
9
  import type { Limits } from './guardrails.js';
10
+ import type { AnyTool } from './effectTool.js';
10
11
  export interface EffectToolExecutor {
11
12
  execute(args: {
12
13
  name: string;
@@ -14,7 +15,11 @@ export interface EffectToolExecutor {
14
15
  session: Session;
15
16
  toolCallId?: string;
16
17
  abortSignal?: AbortSignal;
18
+ toolCtx?: ToolContext;
19
+ def?: AnyTool;
17
20
  }): Promise<unknown>;
21
+ /** Resolve a registered tool definition by name (used to read flags like `needsApproval`). */
22
+ getTool?(name: string): AnyTool | undefined;
18
23
  }
19
24
  export interface AutoRetrieveProvider {
20
25
  retrieve(ctx: RunContext): Promise<string | undefined>;
@@ -46,6 +51,8 @@ export interface RunContext {
46
51
  telemetry?: TelemetrySettings;
47
52
  tool(name: string, args: unknown, options?: {
48
53
  toolCallId?: string;
54
+ def?: AnyTool;
55
+ toolCtx?: ToolContext;
49
56
  }): Promise<unknown>;
50
57
  approve(req: {
51
58
  title: string;
@@ -0,0 +1,18 @@
1
+ /** Author-facing choice option (RFC §4.5). Stable shape. */
2
+ export interface ChoiceOption {
3
+ id: string;
4
+ label: string;
5
+ description?: string;
6
+ url?: string;
7
+ flow?: {
8
+ flowId: string;
9
+ cta: string;
10
+ };
11
+ }
12
+ /** A structured inbound selection propagated into a run (RFC §4.8 / REQ-20). */
13
+ export interface ResolvedSelection {
14
+ /** Stable id (button/list id, template button payload) — exposed as the routing `input`. */
15
+ id?: string;
16
+ /** Flow-form submission data (e.g. WhatsApp Flow nfm_reply) merged into flow state at turn start. */
17
+ formData?: Record<string, unknown>;
18
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,10 @@
1
1
  import type { ConversationOutcome } from '../outcomes/types.js';
2
+ import type { ChoiceOption } from './selection.js';
3
+ /**
4
+ * Authoritative runtime stream union (`runFlow` / `Runtime` emit).
5
+ * `types/voice.ts` defines a separate voice/realtime union that intentionally
6
+ * does not include `{ type: 'interactive' }`.
7
+ */
2
8
  export type HarnessStreamPart = {
3
9
  type: 'text-delta';
4
10
  text: string;
@@ -43,6 +49,11 @@ export type HarnessStreamPart = {
43
49
  } | {
44
50
  type: 'conversation-outcome';
45
51
  outcome: ConversationOutcome;
52
+ } | {
53
+ type: 'interactive';
54
+ nodeId: string;
55
+ options: ChoiceOption[];
56
+ prompt: string;
46
57
  } | {
47
58
  type: 'turn-end';
48
59
  } | {
package/package.json CHANGED
@@ -1,6 +1,12 @@
1
1
  {
2
2
  "name": "@kuralle-agents/core",
3
- "version": "0.2.1",
3
+ "license": "Apache-2.0",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/kuralle/kuralle-agents.git",
7
+ "directory": "packages/kuralle-core"
8
+ },
9
+ "version": "0.3.1",
4
10
  "description": "A framework for structured conversational AI agents",
5
11
  "publishConfig": {
6
12
  "access": "public"
@@ -84,22 +90,24 @@
84
90
  "zod": "^3.0.0"
85
91
  },
86
92
  "devDependencies": {
87
- "@kuralle-agents/realtime-audio": "workspace:*",
88
93
  "@ai-sdk/openai": "^3.0.0",
89
94
  "@types/node": "^20.11.0",
90
95
  "ai": "^6.0.0",
91
96
  "bun-types": "^1.3.0",
92
97
  "dotenv": "^16.4.0",
93
- "tsx": "^4.7.0",
94
98
  "typescript": "^5.3.0",
95
- "zod": "^3.23.0"
99
+ "zod": "^3.23.0",
100
+ "@kuralle-agents/realtime-audio": "0.3.1"
101
+ },
102
+ "dependencies": {
103
+ "chrono-node": "^2.6.0",
104
+ "zod-to-json-schema": "^3.24.0"
96
105
  },
97
106
  "scripts": {
98
107
  "prebuild": "rm -rf dist",
99
108
  "build": "tsc -p tsconfig.json",
100
109
  "typecheck:examples": "tsc --noEmit -p tsconfig.examples.json",
101
110
  "clean": "rm -rf dist",
102
- "prepublishOnly": "npm run clean && npm run build",
103
111
  "test": "bun test test",
104
112
  "smoke:textdriver": "bun test ./test/core-channel/textdriver.smoke.ts",
105
113
  "smoke:flow": "bun test ./test/core-flow/flow.smoke.ts",
@@ -107,9 +115,5 @@
107
115
  "smoke:approval": "bun test ./test/core-policy/approval.smoke.ts",
108
116
  "smoke:knowledge": "bun test ./test/core-grounding/knowledge.smoke.ts",
109
117
  "smoke:realtime": "bun test ./test/core-voice/realtime.smoke.ts"
110
- },
111
- "dependencies": {
112
- "chrono-node": "^2.6.0",
113
- "zod-to-json-schema": "^3.24.0"
114
118
  }
115
- }
119
+ }
@@ -1,2 +0,0 @@
1
- export { createEventBus, createTurnHandle } from './TurnHandle.js';
2
- export type { EventBus, TurnHandleOptions } from './TurnHandle.js';
@@ -1 +0,0 @@
1
- export { createEventBus, createTurnHandle } from './TurnHandle.js';
@@ -1,10 +0,0 @@
1
- export { classifyControl } from './classifyControl.js';
2
- export { buildNodePrompt, buildNodeTools, resolveReplyNode, resolveCollectExtractionNode, resolveInstructions, } from './nodeBuilders.js';
3
- export { isReplyNode, isCollectNode, isActionNode, isDecideNode } from './nodeKinds.js';
4
- export { normalizeTransition, resolveNodeRef, isFlowNode, type NormalizedTransition, } from './normalizeTransition.js';
5
- export { reduceTransition, type ReduceTransitionInput } from './reduceTransition.js';
6
- export { applyContextStrategy, resolveContextStrategy } from './contextStrategy.js';
7
- export { runNodeVerify, VerifyBlockedError, type NodeVerify, type VerifyInput } from './verify.js';
8
- export { collectUntilComplete } from './collectUntilComplete.js';
9
- export { collectDataKey, collectTurnsKey, computeMissingFields, createExtractionSubmitTool, getCollectData, mergeExtractionData, mergeTurnExtraction, projectCollectData, schemaSatisfied, submitToolName, } from './extraction.js';
10
- export { runFlow, buildNodeRegistry, resolveStartNode, FlowOscillationError, type FlowResult, } from './runFlow.js';
@@ -1,10 +0,0 @@
1
- export { classifyControl } from './classifyControl.js';
2
- export { buildNodePrompt, buildNodeTools, resolveReplyNode, resolveCollectExtractionNode, resolveInstructions, } from './nodeBuilders.js';
3
- export { isReplyNode, isCollectNode, isActionNode, isDecideNode } from './nodeKinds.js';
4
- export { normalizeTransition, resolveNodeRef, isFlowNode, } from './normalizeTransition.js';
5
- export { reduceTransition } from './reduceTransition.js';
6
- export { applyContextStrategy, resolveContextStrategy } from './contextStrategy.js';
7
- export { runNodeVerify, VerifyBlockedError } from './verify.js';
8
- export { collectUntilComplete } from './collectUntilComplete.js';
9
- export { collectDataKey, collectTurnsKey, computeMissingFields, createExtractionSubmitTool, getCollectData, mergeExtractionData, mergeTurnExtraction, projectCollectData, schemaSatisfied, submitToolName, } from './extraction.js';
10
- export { runFlow, buildNodeRegistry, resolveStartNode, FlowOscillationError, } from './runFlow.js';
@@ -1,16 +0,0 @@
1
- import { HarnessStreamPart, RunContext, Session } from '../types/index.js';
2
- export declare class SessionEventManager {
3
- private helpers;
4
- private assistantTextKey;
5
- private readonly runtimeEventLogKey;
6
- private readonly runtimeEventLogMaxEntries;
7
- constructor(helpers: {
8
- touchSession: (session: Session) => void;
9
- getSessionTurn: (session: Session) => number;
10
- });
11
- private appendRuntimeEvent;
12
- private toEventLogValue;
13
- private flushAssistantFinalEvent;
14
- recordRuntimeEvent(context: RunContext, part: HarnessStreamPart): void;
15
- cleanupSession(session: Session): void;
16
- }
@@ -1,148 +0,0 @@
1
- import crypto from 'node:crypto';
2
- import { isRecord } from '../utils/isRecord.js';
3
- export class SessionEventManager {
4
- helpers;
5
- assistantTextKey = '__ariaAssistantText';
6
- runtimeEventLogKey = 'runtimeEventLog';
7
- runtimeEventLogMaxEntries = 2000;
8
- constructor(helpers) {
9
- this.helpers = helpers;
10
- }
11
- appendRuntimeEvent(context, entry) {
12
- const key = this.runtimeEventLogKey;
13
- const current = context.session.workingMemory[key];
14
- const events = Array.isArray(current) ? [...current] : [];
15
- events.push(entry);
16
- const overflow = events.length - this.runtimeEventLogMaxEntries;
17
- if (overflow > 0) {
18
- events.splice(0, overflow);
19
- }
20
- context.session.workingMemory[key] = events;
21
- this.helpers.touchSession(context.session);
22
- }
23
- toEventLogValue(value, depth = 0) {
24
- if (value === null || value === undefined) {
25
- return value;
26
- }
27
- if (depth >= 5) {
28
- return '[truncated]';
29
- }
30
- if (value instanceof Date) {
31
- return value.toISOString();
32
- }
33
- if (value instanceof Error) {
34
- return { name: value.name, message: value.message };
35
- }
36
- if (Array.isArray(value)) {
37
- return value.slice(0, 50).map(item => this.toEventLogValue(item, depth + 1));
38
- }
39
- if (typeof value === 'function') {
40
- return '[function]';
41
- }
42
- if (isRecord(value)) {
43
- const out = {};
44
- for (const [k, v] of Object.entries(value).slice(0, 50)) {
45
- out[k] = this.toEventLogValue(v, depth + 1);
46
- }
47
- return out;
48
- }
49
- return value;
50
- }
51
- flushAssistantFinalEvent(context, trigger) {
52
- const textRaw = context.session.workingMemory[this.assistantTextKey];
53
- const text = (typeof textRaw === 'string' ? textRaw : '').trim();
54
- if (text.length > 0) {
55
- this.appendRuntimeEvent(context, {
56
- id: crypto.randomUUID(),
57
- sessionId: context.session.id,
58
- agentId: context.agentId,
59
- turn: this.helpers.getSessionTurn(context.session),
60
- type: 'assistant_final',
61
- trigger,
62
- text,
63
- timestamp: new Date().toISOString(),
64
- });
65
- }
66
- delete context.session.workingMemory[this.assistantTextKey];
67
- }
68
- recordRuntimeEvent(context, part) {
69
- const base = {
70
- id: crypto.randomUUID(),
71
- sessionId: context.session.id,
72
- agentId: context.agentId,
73
- turn: this.helpers.getSessionTurn(context.session),
74
- timestamp: new Date().toISOString(),
75
- };
76
- switch (part.type) {
77
- case 'text-delta': {
78
- const prevRaw = context.session.workingMemory[this.assistantTextKey];
79
- const prev = typeof prevRaw === 'string' ? prevRaw : '';
80
- context.session.workingMemory[this.assistantTextKey] = prev + part.text;
81
- return;
82
- }
83
- case 'input':
84
- this.appendRuntimeEvent(context, { ...base, type: 'user', text: part.text, userId: part.userId });
85
- return;
86
- case 'tool-call':
87
- this.appendRuntimeEvent(context, {
88
- ...base,
89
- type: 'tool_call',
90
- toolCallId: part.toolCallId,
91
- toolName: part.toolName,
92
- args: this.toEventLogValue(part.args),
93
- });
94
- return;
95
- case 'tool-result':
96
- this.appendRuntimeEvent(context, {
97
- ...base,
98
- type: 'tool_result',
99
- toolCallId: part.toolCallId,
100
- toolName: part.toolName,
101
- result: this.toEventLogValue(part.result),
102
- });
103
- return;
104
- case 'tool-error':
105
- this.appendRuntimeEvent(context, {
106
- ...base,
107
- type: 'tool_error',
108
- toolCallId: part.toolCallId,
109
- toolName: part.toolName,
110
- error: part.error,
111
- });
112
- return;
113
- case 'flow-transition':
114
- this.appendRuntimeEvent(context, {
115
- ...base,
116
- type: 'transition',
117
- kind: 'flow',
118
- from: part.from,
119
- to: part.to,
120
- });
121
- return;
122
- case 'handoff':
123
- this.appendRuntimeEvent(context, {
124
- ...base,
125
- type: 'transition',
126
- kind: 'handoff',
127
- from: part.from,
128
- to: part.to,
129
- reason: part.reason,
130
- });
131
- return;
132
- case 'turn-end':
133
- this.flushAssistantFinalEvent(context, 'turn-end');
134
- return;
135
- case 'done':
136
- this.flushAssistantFinalEvent(context, 'done');
137
- return;
138
- case 'error':
139
- this.flushAssistantFinalEvent(context, 'error');
140
- return;
141
- default:
142
- return;
143
- }
144
- }
145
- cleanupSession(session) {
146
- delete session.workingMemory[this.assistantTextKey];
147
- }
148
- }
@@ -1,5 +0,0 @@
1
- export * from './types.js';
2
- export * from './RunStore.js';
3
- export * from './SessionRunStore.js';
4
- export * from './idempotency.js';
5
- export * from './replay.js';
@@ -1,5 +0,0 @@
1
- export * from './types.js';
2
- export * from './RunStore.js';
3
- export * from './SessionRunStore.js';
4
- export * from './idempotency.js';
5
- export * from './replay.js';
@@ -1,3 +0,0 @@
1
- export { applyPreTurnPolicies, applyPostTurnPolicies, buildRefinementPolicies, buildValidationPolicies, } from './agentTurn.js';
2
- export { assertWithinTurnLimit, incrementTurnCount, LimitsExceededError, readTurnCount, resolveMaxSteps, } from './limits.js';
3
- export { resolveAgentPolicies, withEnforcementRules, withValidationPolicies, type ResolvedAgentPolicies, } from './resolvePolicies.js';
@@ -1,3 +0,0 @@
1
- export { applyPreTurnPolicies, applyPostTurnPolicies, buildRefinementPolicies, buildValidationPolicies, } from './agentTurn.js';
2
- export { assertWithinTurnLimit, incrementTurnCount, LimitsExceededError, readTurnCount, resolveMaxSteps, } from './limits.js';
3
- export { resolveAgentPolicies, withEnforcementRules, withValidationPolicies, } from './resolvePolicies.js';
@@ -1,5 +0,0 @@
1
- import type { Session } from '../types/index.js';
2
- import { ContextBudget, type ContextBudgetConfig } from './ContextBudget.js';
3
- import { TokenAccumulator } from './TokenAccumulator.js';
4
- export declare function getOrCreateTokenAccumulator(session: Session, modelContextWindow?: number): TokenAccumulator;
5
- export declare function getOrCreateContextBudgetValidator(session: Session, partial?: Partial<ContextBudgetConfig>): ContextBudget;
@@ -1,24 +0,0 @@
1
- import { ContextBudget, DEFAULT_CONTEXT_BUDGET } from './ContextBudget.js';
2
- import { TokenAccumulator } from './TokenAccumulator.js';
3
- const ACC_KEY = '__ariaTokenAccumulator';
4
- const BUDGET_KEY = '__ariaContextBudgetValidator';
5
- export function getOrCreateTokenAccumulator(session, modelContextWindow) {
6
- const existing = session.workingMemory[ACC_KEY];
7
- if (existing instanceof TokenAccumulator) {
8
- return existing;
9
- }
10
- const w = modelContextWindow ?? DEFAULT_CONTEXT_BUDGET.modelContextWindow;
11
- const acc = new TokenAccumulator(w);
12
- session.workingMemory[ACC_KEY] = acc;
13
- return acc;
14
- }
15
- export function getOrCreateContextBudgetValidator(session, partial) {
16
- const existing = session.workingMemory[BUDGET_KEY];
17
- if (existing instanceof ContextBudget) {
18
- return existing;
19
- }
20
- const cfg = { ...DEFAULT_CONTEXT_BUDGET, ...partial };
21
- const inst = new ContextBudget(cfg);
22
- session.workingMemory[BUDGET_KEY] = inst;
23
- return inst;
24
- }
@@ -1,15 +0,0 @@
1
- import type { ToolSet } from 'ai';
2
- import type { ToolDeclaration } from '../capabilities/index.js';
3
- export declare function createTransferToTriageAISDKTool(triageAgentId: string, specialistScope?: string): ToolSet[string];
4
- type TransferToTriageArgs = {
5
- reason: string;
6
- };
7
- type TransferToTriageResult = {
8
- __handoff: true;
9
- targetAgentId: string;
10
- targetAgent: string;
11
- reason: string;
12
- };
13
- export declare function createTransferToTriageDeclaration(triageAgentId: string, specialistScope?: string): ToolDeclaration<TransferToTriageArgs, TransferToTriageResult>;
14
- export declare function shouldInjectTransferToTriage(triageAgentId: string | undefined, retriagePolicy: 'never' | 'on-handoff-tool' | undefined, specialistAgentId: string, triageAgentExists: boolean, isTriageSpecialist: boolean): boolean;
15
- export {};
@@ -1,48 +0,0 @@
1
- import { tool } from 'ai';
2
- import { z } from 'zod';
3
- const BASE_DESCRIPTION = "Call this tool when the user's request is outside your area of expertise or when they explicitly ask to be transferred.";
4
- function buildTransferDescription(specialistScope) {
5
- if (!specialistScope?.trim()) {
6
- return BASE_DESCRIPTION;
7
- }
8
- const scope = specialistScope.trim();
9
- return `Call this tool ONLY when the user's request does NOT match any of these topics: ${scope}. If the request IS about one of these topics, handle it yourself. If the user explicitly asks to be transferred, you may still call this tool.`;
10
- }
11
- export function createTransferToTriageAISDKTool(triageAgentId, specialistScope) {
12
- return tool({
13
- description: buildTransferDescription(specialistScope),
14
- inputSchema: z.object({
15
- reason: z.string().describe('Why you are escalating to the routing agent'),
16
- }),
17
- execute: async ({ reason }) => ({
18
- __handoff: true,
19
- targetAgentId: triageAgentId,
20
- targetAgent: triageAgentId,
21
- reason,
22
- }),
23
- });
24
- }
25
- export function createTransferToTriageDeclaration(triageAgentId, specialistScope) {
26
- return {
27
- name: 'transfer_to_triage',
28
- description: buildTransferDescription(specialistScope),
29
- parameters: z.object({
30
- reason: z.string().describe('Why you are escalating to the routing agent'),
31
- }),
32
- execute: async (args) => ({
33
- __handoff: true,
34
- targetAgentId: triageAgentId,
35
- targetAgent: triageAgentId,
36
- reason: args.reason,
37
- }),
38
- };
39
- }
40
- export function shouldInjectTransferToTriage(triageAgentId, retriagePolicy, specialistAgentId, triageAgentExists, isTriageSpecialist) {
41
- if (retriagePolicy !== 'on-handoff-tool' || !triageAgentId) {
42
- return false;
43
- }
44
- if (!triageAgentExists || specialistAgentId === triageAgentId || isTriageSpecialist) {
45
- return false;
46
- }
47
- return true;
48
- }
@@ -1,6 +0,0 @@
1
- import type { AgentStreamPart } from '../types/index.js';
2
- /**
3
- * Processes a stream from the AI SDK and yields canonical AgentStreamParts.
4
- * Shared stream-iteration helper for model calls.
5
- */
6
- export declare function processAIStream(stream: AsyncIterable<unknown>): AsyncGenerator<AgentStreamPart>;
@@ -1,48 +0,0 @@
1
- import { getChunkArgs, getChunkResult, getChunkToolCallId, getChunkErrorMessage } from './streamChunk.js';
2
- import { isHandoffResult } from '../tools/handoff.js';
3
- function asAIStreamChunk(value) {
4
- if (typeof value !== 'object' || value === null)
5
- return null;
6
- return value;
7
- }
8
- /**
9
- * Processes a stream from the AI SDK and yields canonical AgentStreamParts.
10
- * Shared stream-iteration helper for model calls.
11
- */
12
- export async function* processAIStream(stream) {
13
- for await (const raw of stream) {
14
- const chunk = asAIStreamChunk(raw);
15
- if (!chunk)
16
- continue;
17
- if (chunk.type === 'text-delta' && typeof chunk.text === 'string') {
18
- yield { type: 'text-delta', text: chunk.text };
19
- }
20
- if (chunk.type === 'tool-call' && chunk.toolName) {
21
- const args = getChunkArgs(chunk);
22
- const toolCallId = getChunkToolCallId(chunk);
23
- yield { type: 'tool-call', toolName: chunk.toolName, args, toolCallId };
24
- }
25
- if (chunk.type === 'tool-result' && chunk.toolName) {
26
- const toolResult = getChunkResult(chunk);
27
- const toolCallId = getChunkToolCallId(chunk);
28
- yield { type: 'tool-result', toolName: chunk.toolName, result: toolResult, toolCallId };
29
- if (isHandoffResult(toolResult)) {
30
- const targetAgent = toolResult.targetAgent ?? toolResult.targetAgentId;
31
- yield {
32
- type: 'handoff',
33
- targetAgent,
34
- reason: toolResult.reason,
35
- };
36
- }
37
- }
38
- if (chunk.type === 'tool-error' && chunk.toolName) {
39
- const toolCallId = getChunkToolCallId(chunk);
40
- const error = getChunkErrorMessage(chunk);
41
- yield { type: 'tool-error', toolName: chunk.toolName, error, toolCallId };
42
- }
43
- if (chunk.type === 'error') {
44
- const error = getChunkErrorMessage(chunk);
45
- yield { type: 'error', error };
46
- }
47
- }
48
- }
@@ -1,4 +0,0 @@
1
- export declare function getChunkArgs(chunk: unknown): unknown;
2
- export declare function getChunkResult(chunk: unknown): unknown;
3
- export declare function getChunkToolCallId(chunk: unknown): string | undefined;
4
- export declare function getChunkErrorMessage(chunk: unknown): string;
@@ -1,49 +0,0 @@
1
- export function getChunkArgs(chunk) {
2
- if (!chunk || typeof chunk !== 'object') {
3
- return undefined;
4
- }
5
- const record = chunk;
6
- if ('args' in record) {
7
- return record.args;
8
- }
9
- if ('input' in record) {
10
- return record.input;
11
- }
12
- return undefined;
13
- }
14
- export function getChunkResult(chunk) {
15
- if (!chunk || typeof chunk !== 'object') {
16
- return undefined;
17
- }
18
- const record = chunk;
19
- if ('result' in record) {
20
- return record.result;
21
- }
22
- if ('output' in record) {
23
- return record.output;
24
- }
25
- return undefined;
26
- }
27
- export function getChunkToolCallId(chunk) {
28
- if (!chunk || typeof chunk !== 'object') {
29
- return undefined;
30
- }
31
- const value = chunk.toolCallId;
32
- return typeof value === 'string' ? value : undefined;
33
- }
34
- export function getChunkErrorMessage(chunk) {
35
- if (!chunk || typeof chunk !== 'object') {
36
- return 'Tool execution error';
37
- }
38
- const value = chunk.error;
39
- if (typeof value === 'string') {
40
- return value;
41
- }
42
- if (value && typeof value === 'object' && 'message' in value) {
43
- const msg = value.message;
44
- if (typeof msg === 'string') {
45
- return msg;
46
- }
47
- }
48
- return 'Tool execution error';
49
- }