@kuralle-agents/core 0.3.17 → 0.3.18
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/dist/audit/index.d.ts +1 -0
- package/dist/audit/index.js +1 -0
- package/dist/audit/record.d.ts +15 -0
- package/dist/audit/record.js +23 -0
- package/dist/capabilities/ValidationCapability.d.ts +8 -0
- package/dist/flow/runFlow.js +16 -0
- package/dist/runtime/channels/TextDriver.js +7 -5
- package/dist/runtime/channels/VoiceDriver.js +7 -4
- package/dist/runtime/grounding/gather.d.ts +2 -0
- package/dist/runtime/grounding/gather.js +22 -4
- package/dist/runtime/grounding/knowledge.js +7 -1
- package/dist/runtime/policies/agentTurn.d.ts +5 -1
- package/dist/runtime/policies/agentTurn.js +93 -7
- package/dist/runtime/policies/resolvePolicies.js +2 -2
- package/dist/types/agentConfig.d.ts +6 -0
- package/dist/types/flow.d.ts +5 -0
- package/dist/types/run-context.d.ts +8 -2
- package/package.json +2 -2
package/dist/audit/index.d.ts
CHANGED
package/dist/audit/index.js
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ConversationAuditEntry, AuditEntryBase } from './types.js';
|
|
2
|
+
import type { Session } from '../types/session.js';
|
|
3
|
+
export interface AuditRecordContext {
|
|
4
|
+
sessionId: string;
|
|
5
|
+
conversationId?: string;
|
|
6
|
+
userId?: string;
|
|
7
|
+
agentId?: string;
|
|
8
|
+
turnIndex?: number;
|
|
9
|
+
}
|
|
10
|
+
export type NewAuditEntry = {
|
|
11
|
+
[K in ConversationAuditEntry['type']]: Omit<Extract<ConversationAuditEntry, {
|
|
12
|
+
type: K;
|
|
13
|
+
}>, keyof AuditEntryBase>;
|
|
14
|
+
}[ConversationAuditEntry['type']];
|
|
15
|
+
export declare function appendConversationAudit(session: Session, ctx: AuditRecordContext, entry: NewAuditEntry): void;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function appendConversationAudit(session, ctx, entry) {
|
|
2
|
+
const at = new Date().toISOString();
|
|
3
|
+
const full = {
|
|
4
|
+
at,
|
|
5
|
+
sessionId: ctx.sessionId,
|
|
6
|
+
conversationId: ctx.conversationId,
|
|
7
|
+
userId: ctx.userId,
|
|
8
|
+
agentId: ctx.agentId,
|
|
9
|
+
turnIndex: ctx.turnIndex,
|
|
10
|
+
...entry,
|
|
11
|
+
};
|
|
12
|
+
if (!session.metadata) {
|
|
13
|
+
session.metadata = {
|
|
14
|
+
createdAt: session.createdAt,
|
|
15
|
+
lastActiveAt: session.updatedAt,
|
|
16
|
+
totalTokens: 0,
|
|
17
|
+
totalSteps: 0,
|
|
18
|
+
handoffHistory: [],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
session.metadata.audit ??= [];
|
|
22
|
+
session.metadata.audit.push(full);
|
|
23
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { EscalationReason } from '../escalation/types.js';
|
|
1
2
|
import type { Session, SourceRef, ToolCallRecord } from '../types/index.js';
|
|
2
3
|
export interface ValidationCapability {
|
|
3
4
|
readonly name: string;
|
|
@@ -21,6 +22,13 @@ export type ValidateDecision = {
|
|
|
21
22
|
confidence: number;
|
|
22
23
|
rewrittenOutput: string;
|
|
23
24
|
rationale: string;
|
|
25
|
+
} | {
|
|
26
|
+
decision: 'escalate';
|
|
27
|
+
confidence: number;
|
|
28
|
+
rationale: string;
|
|
29
|
+
escalateTo?: string;
|
|
30
|
+
escalationReason?: EscalationReason;
|
|
31
|
+
userFacingMessage?: string;
|
|
24
32
|
} | {
|
|
25
33
|
decision: 'block';
|
|
26
34
|
confidence: number;
|
package/dist/flow/runFlow.js
CHANGED
|
@@ -12,6 +12,7 @@ import { loadRecordedSteps } from '../runtime/durable/replay.js';
|
|
|
12
12
|
import { SuspendError } from '../runtime/durable/RunStore.js';
|
|
13
13
|
import { ToolApprovalDeniedError } from '../tools/effect/errors.js';
|
|
14
14
|
import { emitInteractiveOnNodeEnter } from './emitInteractive.js';
|
|
15
|
+
import { appendConversationAudit } from '../audit/record.js';
|
|
15
16
|
import { appendSafeAssistantMessage, degradeFlowError, findEscalateNode, } from './degrade.js';
|
|
16
17
|
export class FlowOscillationError extends Error {
|
|
17
18
|
constructor(from, to) {
|
|
@@ -169,6 +170,21 @@ async function dispatchNode(node, run, driver, ctx, agent, flow) {
|
|
|
169
170
|
if (turn.control?.type === 'recover') {
|
|
170
171
|
return { kind: 'end', reason: turn.control.reason ?? 'error_degraded' };
|
|
171
172
|
}
|
|
173
|
+
if (node.confidenceGate &&
|
|
174
|
+
turn.confidence != null &&
|
|
175
|
+
turn.confidence < node.confidenceGate.min) {
|
|
176
|
+
appendConversationAudit(ctx.session, {
|
|
177
|
+
sessionId: ctx.session.id,
|
|
178
|
+
conversationId: ctx.session.conversationId,
|
|
179
|
+
userId: ctx.session.userId,
|
|
180
|
+
agentId: ctx.runState.activeAgentId,
|
|
181
|
+
}, {
|
|
182
|
+
type: 'escalation',
|
|
183
|
+
reason: 'low-confidence',
|
|
184
|
+
confidence: turn.confidence,
|
|
185
|
+
});
|
|
186
|
+
return normalizeTransition(node.confidenceGate.onLow);
|
|
187
|
+
}
|
|
172
188
|
if (node.next) {
|
|
173
189
|
return normalizeTransition(await node.next(turn, run.state));
|
|
174
190
|
}
|
|
@@ -98,11 +98,13 @@ export class TextDriver {
|
|
|
98
98
|
messages.push(toolResultMessage({ toolName: call.toolName, input: call.input, toolCallId: call.toolCallId }, toolResult));
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
|
-
const postTurn = await applyPostTurnPolicies(ctx, draftText, toolCallsMade);
|
|
102
|
-
|
|
103
|
-
out.
|
|
104
|
-
|
|
105
|
-
|
|
101
|
+
const postTurn = await applyPostTurnPolicies(ctx, draftText, toolCallsMade, gather.citations ?? []);
|
|
102
|
+
out.confidence = postTurn.confidence;
|
|
103
|
+
out.control = postTurn.control;
|
|
104
|
+
const emitText = postTurn.control ? (postTurn.blockedMessage ?? postTurn.text) : postTurn.text;
|
|
105
|
+
out.text = emitText;
|
|
106
|
+
if (emitText) {
|
|
107
|
+
ctx.emit({ type: 'text-delta', text: emitText });
|
|
106
108
|
}
|
|
107
109
|
ctx.emit({ type: 'turn-end' });
|
|
108
110
|
return out;
|
|
@@ -56,10 +56,13 @@ export class VoiceDriver {
|
|
|
56
56
|
break;
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
|
-
const postTurn = await applyPostTurnPolicies(ctx, draftText, toolCallsMade);
|
|
60
|
-
out.
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
const postTurn = await applyPostTurnPolicies(ctx, draftText, toolCallsMade, gather.citations ?? []);
|
|
60
|
+
out.confidence = postTurn.confidence;
|
|
61
|
+
out.control = postTurn.control;
|
|
62
|
+
const emitText = postTurn.control ? (postTurn.blockedMessage ?? postTurn.text) : postTurn.text;
|
|
63
|
+
out.text = emitText;
|
|
64
|
+
if (emitText) {
|
|
65
|
+
ctx.emit({ type: 'text-delta', text: emitText });
|
|
63
66
|
}
|
|
64
67
|
ctx.emit({ type: 'turn-end' });
|
|
65
68
|
return out;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import type { SourceRef } from '../../types/voice.js';
|
|
1
2
|
import type { GatherScope, RunContext } from '../../types/run-context.js';
|
|
2
3
|
export type { GatherScope } from '../../types/run-context.js';
|
|
3
4
|
export interface GatherResult {
|
|
4
5
|
retrievalBlock?: string;
|
|
5
6
|
memoryBlock?: string;
|
|
7
|
+
citations?: SourceRef[];
|
|
6
8
|
}
|
|
7
9
|
export declare function runGatherPhase(ctx: RunContext, scope?: GatherScope): Promise<GatherResult>;
|
|
@@ -1,9 +1,27 @@
|
|
|
1
|
+
function normalizeRetrieveResult(raw) {
|
|
2
|
+
if (raw == null) {
|
|
3
|
+
return {};
|
|
4
|
+
}
|
|
5
|
+
if (typeof raw === 'string') {
|
|
6
|
+
return { retrievalBlock: raw };
|
|
7
|
+
}
|
|
8
|
+
return { retrievalBlock: raw.block, citations: raw.citations };
|
|
9
|
+
}
|
|
1
10
|
export async function runGatherPhase(ctx, scope) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
11
|
+
let retrievalBlock;
|
|
12
|
+
let citations;
|
|
13
|
+
if (ctx.autoRetrieve && scope?.knowledge?.autoRetrieve !== false) {
|
|
14
|
+
const raw = await ctx.autoRetrieve.retrieve(ctx, scope);
|
|
15
|
+
const normalized = normalizeRetrieveResult(raw);
|
|
16
|
+
retrievalBlock = normalized.retrievalBlock;
|
|
17
|
+
citations = normalized.citations;
|
|
18
|
+
ctx.lastRetrievalCitations = citations;
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
ctx.lastRetrievalCitations = undefined;
|
|
22
|
+
}
|
|
5
23
|
const memoryBlock = ctx.memoryService?.preload && scope?.memory?.preload !== false
|
|
6
24
|
? await ctx.memoryService.preload(ctx, scope)
|
|
7
25
|
: undefined;
|
|
8
|
-
return { retrievalBlock, memoryBlock };
|
|
26
|
+
return { retrievalBlock, memoryBlock, citations };
|
|
9
27
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeCitations } from '../citations/index.js';
|
|
1
2
|
import { KnowledgeProvider } from '../KnowledgeProvider.js';
|
|
2
3
|
function latestUserMessage(ctx) {
|
|
3
4
|
for (let index = ctx.runState.messages.length - 1; index >= 0; index -= 1) {
|
|
@@ -51,7 +52,12 @@ export function buildAutoRetrieveProvider(provider, agent) {
|
|
|
51
52
|
...retrievalResults.map((result) => ({ text: result.text })),
|
|
52
53
|
];
|
|
53
54
|
const maxChars = provider.resolveConfig(merged).maxOutputTokens * 4;
|
|
54
|
-
|
|
55
|
+
const block = formatRetrievalBlock(combined, maxChars);
|
|
56
|
+
const citations = normalizeCitations(retrievalResults);
|
|
57
|
+
if (!block && citations.length === 0) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
return { block, citations: citations.length > 0 ? citations : undefined };
|
|
55
61
|
},
|
|
56
62
|
};
|
|
57
63
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import type { TurnControl } from '../../types/channel.js';
|
|
1
2
|
import type { ToolCallRecord } from '../../types/session.js';
|
|
3
|
+
import type { SourceRef } from '../../types/voice.js';
|
|
2
4
|
import type { RunContext } from '../../types/run-context.js';
|
|
3
5
|
export interface PreTurnResult {
|
|
4
6
|
proceed: boolean;
|
|
@@ -9,6 +11,8 @@ export interface PostTurnResult {
|
|
|
9
11
|
proceed: boolean;
|
|
10
12
|
text: string;
|
|
11
13
|
blockedMessage?: string;
|
|
14
|
+
control?: TurnControl;
|
|
15
|
+
confidence?: number;
|
|
12
16
|
}
|
|
13
17
|
export declare function applyPreTurnPolicies(ctx: RunContext): Promise<PreTurnResult>;
|
|
14
|
-
export declare function applyPostTurnPolicies(ctx: RunContext, assistantOutput: string, toolCallsMade?: ToolCallRecord[]): Promise<PostTurnResult>;
|
|
18
|
+
export declare function applyPostTurnPolicies(ctx: RunContext, assistantOutput: string, toolCallsMade?: ToolCallRecord[], knowledgeCitations?: SourceRef[]): Promise<PostTurnResult>;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { appendConversationAudit } from '../../audit/record.js';
|
|
2
|
+
import { SAFE_DEGRADED_MESSAGE } from '../../flow/degrade.js';
|
|
1
3
|
import { runInputProcessors, runOutputProcessors } from '../../processors/ProcessorRunner.js';
|
|
2
4
|
function latestUserMessage(messages) {
|
|
3
5
|
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
@@ -8,6 +10,67 @@ function latestUserMessage(messages) {
|
|
|
8
10
|
}
|
|
9
11
|
return '';
|
|
10
12
|
}
|
|
13
|
+
function auditContext(ctx) {
|
|
14
|
+
return {
|
|
15
|
+
sessionId: ctx.session.id,
|
|
16
|
+
conversationId: ctx.session.conversationId,
|
|
17
|
+
userId: ctx.session.userId,
|
|
18
|
+
agentId: ctx.runState.activeAgentId,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function recordKnowledgeCitations(ctx, citations) {
|
|
22
|
+
for (const citation of citations) {
|
|
23
|
+
appendConversationAudit(ctx.session, auditContext(ctx), {
|
|
24
|
+
type: 'knowledge-citation',
|
|
25
|
+
sourceId: citation.id,
|
|
26
|
+
title: citation.title,
|
|
27
|
+
score: citation.score,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function recordValidationDecision(ctx, policyName, decision) {
|
|
32
|
+
if (decision.decision === 'block') {
|
|
33
|
+
appendConversationAudit(ctx.session, auditContext(ctx), {
|
|
34
|
+
type: 'safety-block',
|
|
35
|
+
moderator: policyName,
|
|
36
|
+
rationale: decision.rationale,
|
|
37
|
+
userFacingMessage: decision.userFacingMessage ?? decision.rationale,
|
|
38
|
+
});
|
|
39
|
+
appendConversationAudit(ctx.session, auditContext(ctx), {
|
|
40
|
+
type: 'validation',
|
|
41
|
+
aggregate: 'block',
|
|
42
|
+
confidence: decision.confidence,
|
|
43
|
+
rationale: decision.rationale,
|
|
44
|
+
moderator: policyName,
|
|
45
|
+
});
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (decision.decision === 'escalate') {
|
|
49
|
+
appendConversationAudit(ctx.session, auditContext(ctx), {
|
|
50
|
+
type: 'escalation',
|
|
51
|
+
reason: decision.escalationReason ?? 'low-confidence',
|
|
52
|
+
confidence: decision.confidence,
|
|
53
|
+
});
|
|
54
|
+
appendConversationAudit(ctx.session, auditContext(ctx), {
|
|
55
|
+
type: 'validation',
|
|
56
|
+
aggregate: 'block',
|
|
57
|
+
confidence: decision.confidence,
|
|
58
|
+
rationale: decision.rationale,
|
|
59
|
+
moderator: policyName,
|
|
60
|
+
});
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
appendConversationAudit(ctx.session, auditContext(ctx), {
|
|
64
|
+
type: 'validation',
|
|
65
|
+
aggregate: decision.decision === 'rewrite' ? 'rewrite' : 'continue',
|
|
66
|
+
confidence: decision.confidence,
|
|
67
|
+
rationale: decision.rationale ?? '',
|
|
68
|
+
moderator: policyName,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function safeBlockedText(decision) {
|
|
72
|
+
return decision.userFacingMessage?.trim() || decision.rationale?.trim() || SAFE_DEGRADED_MESSAGE;
|
|
73
|
+
}
|
|
11
74
|
async function runRefinementPolicies(ctx, userMessage) {
|
|
12
75
|
const policies = ctx.refinementPolicies ?? [];
|
|
13
76
|
if (policies.length === 0) {
|
|
@@ -36,34 +99,56 @@ async function runRefinementPolicies(ctx, userMessage) {
|
|
|
36
99
|
}
|
|
37
100
|
return { proceed: true, userMessage: current };
|
|
38
101
|
}
|
|
39
|
-
async function runValidationPolicies(ctx, userMessage, assistantOutput, toolCallsMade) {
|
|
102
|
+
async function runValidationPolicies(ctx, userMessage, assistantOutput, toolCallsMade, knowledgeCitations) {
|
|
40
103
|
const policies = ctx.validationPolicies ?? [];
|
|
41
104
|
if (policies.length === 0) {
|
|
42
105
|
return { proceed: true, text: assistantOutput };
|
|
43
106
|
}
|
|
107
|
+
if (knowledgeCitations.length > 0) {
|
|
108
|
+
recordKnowledgeCitations(ctx, knowledgeCitations);
|
|
109
|
+
}
|
|
44
110
|
const sorted = [...policies].sort((a, b) => a.name.localeCompare(b.name));
|
|
45
111
|
let current = assistantOutput;
|
|
112
|
+
let lastConfidence;
|
|
46
113
|
for (const policy of sorted) {
|
|
47
114
|
const decision = await policy.validate({
|
|
48
115
|
session: ctx.session,
|
|
49
116
|
userMessage,
|
|
50
117
|
assistantOutput: current,
|
|
51
118
|
toolCallsMade,
|
|
52
|
-
knowledgeCitations
|
|
119
|
+
knowledgeCitations,
|
|
53
120
|
abortSignal: ctx.abortSignal,
|
|
54
121
|
});
|
|
122
|
+
recordValidationDecision(ctx, policy.name, decision);
|
|
123
|
+
lastConfidence = decision.confidence;
|
|
55
124
|
if (decision.decision === 'block') {
|
|
125
|
+
const safe = safeBlockedText(decision);
|
|
56
126
|
return {
|
|
57
127
|
proceed: false,
|
|
58
|
-
text:
|
|
59
|
-
blockedMessage:
|
|
128
|
+
text: safe,
|
|
129
|
+
blockedMessage: safe,
|
|
130
|
+
control: { type: 'recover', reason: decision.rationale },
|
|
131
|
+
confidence: decision.confidence,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
if (decision.decision === 'escalate') {
|
|
135
|
+
const safe = safeBlockedText(decision);
|
|
136
|
+
return {
|
|
137
|
+
proceed: false,
|
|
138
|
+
text: safe,
|
|
139
|
+
blockedMessage: safe,
|
|
140
|
+
control: { type: 'escalate', reason: decision.rationale },
|
|
141
|
+
confidence: decision.confidence,
|
|
60
142
|
};
|
|
61
143
|
}
|
|
62
144
|
if (decision.decision === 'rewrite') {
|
|
63
145
|
current = decision.rewrittenOutput;
|
|
64
146
|
}
|
|
65
147
|
}
|
|
66
|
-
|
|
148
|
+
if (ctx.session.metadata) {
|
|
149
|
+
ctx.session.metadata.lastValidationConfidence = lastConfidence;
|
|
150
|
+
}
|
|
151
|
+
return { proceed: true, text: current, confidence: lastConfidence };
|
|
67
152
|
}
|
|
68
153
|
export async function applyPreTurnPolicies(ctx) {
|
|
69
154
|
const userMessage = latestUserMessage(ctx.runState.messages);
|
|
@@ -92,7 +177,7 @@ export async function applyPreTurnPolicies(ctx) {
|
|
|
92
177
|
}
|
|
93
178
|
return runRefinementPolicies(ctx, latestUserMessage(ctx.runState.messages));
|
|
94
179
|
}
|
|
95
|
-
export async function applyPostTurnPolicies(ctx, assistantOutput, toolCallsMade = []) {
|
|
180
|
+
export async function applyPostTurnPolicies(ctx, assistantOutput, toolCallsMade = [], knowledgeCitations = []) {
|
|
96
181
|
const userMessage = latestUserMessage(ctx.runState.messages);
|
|
97
182
|
const processors = ctx.outputProcessors ?? [];
|
|
98
183
|
let current = assistantOutput;
|
|
@@ -117,7 +202,8 @@ export async function applyPostTurnPolicies(ctx, assistantOutput, toolCallsMade
|
|
|
117
202
|
}
|
|
118
203
|
current = outcome.text;
|
|
119
204
|
}
|
|
120
|
-
|
|
205
|
+
const citations = knowledgeCitations.length > 0 ? knowledgeCitations : (ctx.lastRetrievalCitations ?? []);
|
|
206
|
+
return runValidationPolicies(ctx, userMessage, current, toolCallsMade, citations);
|
|
121
207
|
}
|
|
122
208
|
function patchLatestUserMessage(messages, next) {
|
|
123
209
|
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
@@ -5,8 +5,8 @@ export function resolveAgentPolicies(agent) {
|
|
|
5
5
|
return {
|
|
6
6
|
inputProcessors: guardrails?.input ?? [],
|
|
7
7
|
outputProcessors: guardrails?.output ?? [],
|
|
8
|
-
refinementPolicies: [],
|
|
9
|
-
validationPolicies: [],
|
|
8
|
+
refinementPolicies: agent.refine ?? [],
|
|
9
|
+
validationPolicies: agent.validate ?? [],
|
|
10
10
|
limits: agent.limits,
|
|
11
11
|
enforcer: enforcementRules.length > 0 ? createToolEnforcer(enforcementRules) : undefined,
|
|
12
12
|
};
|
|
@@ -4,6 +4,8 @@ import type { Flow } from './flow.js';
|
|
|
4
4
|
import type { Route, RoutingPolicy } from './route.js';
|
|
5
5
|
import type { Guardrails, Limits } from './guardrails.js';
|
|
6
6
|
import type { AgentKnowledge, AgentMemory } from './grounding.js';
|
|
7
|
+
import type { RefinementCapability } from '../capabilities/RefinementCapability.js';
|
|
8
|
+
import type { ValidationCapability } from '../capabilities/ValidationCapability.js';
|
|
7
9
|
import type { AnyTool } from './effectTool.js';
|
|
8
10
|
export type Instructions = string | AgentPrompt | ((ctx: {
|
|
9
11
|
state: Record<string, unknown>;
|
|
@@ -35,6 +37,10 @@ export interface AgentConfig {
|
|
|
35
37
|
memory?: AgentMemory;
|
|
36
38
|
guardrails?: Guardrails;
|
|
37
39
|
limits?: Limits;
|
|
40
|
+
/** Post-turn validation policies (grounding/confidence gate). Default: none. */
|
|
41
|
+
validate?: ValidationCapability[];
|
|
42
|
+
/** Pre-turn refinement policies. Default: none. */
|
|
43
|
+
refine?: RefinementCapability[];
|
|
38
44
|
experimental?: {
|
|
39
45
|
/** Flow reply nodes: silo flow-transition control tools + deterministic evaluator (ADR 0003 H1). Default OFF. */
|
|
40
46
|
outOfBandControl?: boolean;
|
package/dist/types/flow.d.ts
CHANGED
|
@@ -56,6 +56,11 @@ export interface ReplyNode {
|
|
|
56
56
|
model?: LanguageModel;
|
|
57
57
|
context?: ContextStrategy;
|
|
58
58
|
grounding?: NodeGrounding;
|
|
59
|
+
/** When set, routes to `onLow` when post-turn validation confidence is below `min`. */
|
|
60
|
+
confidenceGate?: {
|
|
61
|
+
min: number;
|
|
62
|
+
onLow: Transition;
|
|
63
|
+
};
|
|
59
64
|
next?: (turn: TurnResult, state: FlowState) => Transition | Promise<Transition>;
|
|
60
65
|
}
|
|
61
66
|
export interface CollectNode {
|
|
@@ -9,7 +9,7 @@ import type { ValidationCapability } from '../capabilities/ValidationCapability.
|
|
|
9
9
|
import type { Limits } from './guardrails.js';
|
|
10
10
|
import type { AnyTool } from './effectTool.js';
|
|
11
11
|
import type { Instructions } from './agentConfig.js';
|
|
12
|
-
import type { AgentKnowledgeOverrides } from './voice.js';
|
|
12
|
+
import type { AgentKnowledgeOverrides, SourceRef } from './voice.js';
|
|
13
13
|
export interface GatherScope {
|
|
14
14
|
query?: string;
|
|
15
15
|
knowledge?: AgentKnowledgeOverrides & {
|
|
@@ -33,8 +33,12 @@ export interface EffectToolExecutor {
|
|
|
33
33
|
/** Resolve a registered tool definition by name (used to read flags like `needsApproval`). */
|
|
34
34
|
getTool?(name: string): AnyTool | undefined;
|
|
35
35
|
}
|
|
36
|
+
export interface AutoRetrieveResult {
|
|
37
|
+
block?: string;
|
|
38
|
+
citations?: SourceRef[];
|
|
39
|
+
}
|
|
36
40
|
export interface AutoRetrieveProvider {
|
|
37
|
-
retrieve(ctx: RunContext, scope?: GatherScope): Promise<string | undefined>;
|
|
41
|
+
retrieve(ctx: RunContext, scope?: GatherScope): Promise<AutoRetrieveResult | string | undefined>;
|
|
38
42
|
}
|
|
39
43
|
export interface MemoryService {
|
|
40
44
|
preload?(ctx: RunContext, scope?: GatherScope): Promise<string | undefined>;
|
|
@@ -73,6 +77,8 @@ export interface RunContext {
|
|
|
73
77
|
* context. Reset to false on every `createRunContext` (i.e. every turn).
|
|
74
78
|
*/
|
|
75
79
|
turnInputConsumed?: boolean;
|
|
80
|
+
/** Citations from the latest gather-phase retrieval on this turn. */
|
|
81
|
+
lastRetrievalCitations?: SourceRef[];
|
|
76
82
|
/** Agent base layer (ADR 0001), set when entering a flow. `baseInstructions`
|
|
77
83
|
* is composed as a prefix into every node turn's system prompt (persona /
|
|
78
84
|
* safety / grounding floor); `globalTools` are safe tools made model-visible
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"url": "git+https://github.com/kuralle/kuralle-agents.git",
|
|
7
7
|
"directory": "packages/kuralle-core"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.3.
|
|
9
|
+
"version": "0.3.18",
|
|
10
10
|
"description": "A framework for structured conversational AI agents",
|
|
11
11
|
"publishConfig": {
|
|
12
12
|
"access": "public"
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
"dotenv": "^16.4.0",
|
|
98
98
|
"typescript": "^5.3.0",
|
|
99
99
|
"zod": "^3.23.0",
|
|
100
|
-
"@kuralle-agents/realtime-audio": "0.3.
|
|
100
|
+
"@kuralle-agents/realtime-audio": "0.3.18"
|
|
101
101
|
},
|
|
102
102
|
"dependencies": {
|
|
103
103
|
"chrono-node": "^2.6.0",
|