@kuralle-agents/core 0.7.0 → 0.7.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.
- package/dist/runtime/Runtime.js +26 -56
- package/dist/runtime/buildAgentToolSurface.d.ts +20 -0
- package/dist/runtime/buildAgentToolSurface.js +56 -0
- package/dist/runtime/channels/TextDriver.js +5 -1
- package/dist/runtime/channels/VoiceDriver.js +5 -1
- package/dist/runtime/grounding/index.d.ts +1 -1
- package/dist/runtime/grounding/index.js +1 -1
- package/dist/runtime/grounding/knowledge.d.ts +2 -0
- package/dist/runtime/grounding/knowledge.js +37 -0
- package/dist/types/grounding.d.ts +9 -0
- package/package.json +2 -2
package/dist/runtime/Runtime.js
CHANGED
|
@@ -5,8 +5,7 @@ import { TextDriver } from './channels/TextDriver.js';
|
|
|
5
5
|
import { createRunContext } from './ctx.js';
|
|
6
6
|
import { createEventBus, createTurnHandle } from '../events/TurnHandle.js';
|
|
7
7
|
import { CoreToolExecutor } from '../tools/effect/index.js';
|
|
8
|
-
import {
|
|
9
|
-
import { wireAgentSkills } from '../skills/wireAgentSkills.js';
|
|
8
|
+
import { buildAgentToolSurface } from './buildAgentToolSurface.js';
|
|
10
9
|
import { hostLoop } from './hostLoop.js';
|
|
11
10
|
import { isDegradableRuntimeError } from '../flow/degradableErrors.js';
|
|
12
11
|
import { SAFE_DEGRADED_MESSAGE } from '../flow/degrade.js';
|
|
@@ -17,8 +16,7 @@ import { SessionRunStore } from './durable/SessionRunStore.js';
|
|
|
17
16
|
import { loadRecordedSteps } from './durable/replay.js';
|
|
18
17
|
import { markSessionOutcome } from './outcomeMarking.js';
|
|
19
18
|
import { resolveAgentPolicies } from './policies/resolvePolicies.js';
|
|
20
|
-
import { buildAutoRetrieveProvider, buildKnowledgeProvider, buildMemoryService, runMemoryIngest,
|
|
21
|
-
import { resolveAgentWorkspace } from './resolveAgentWorkspace.js';
|
|
19
|
+
import { buildAutoRetrieveProvider, buildKnowledgeProvider, buildMemoryService, runMemoryIngest, } from './grounding/index.js';
|
|
22
20
|
import { SessionMutex } from './SessionMutex.js';
|
|
23
21
|
export class Runtime {
|
|
24
22
|
config;
|
|
@@ -66,38 +64,16 @@ export class Runtime {
|
|
|
66
64
|
sessionStore: this.sessionStore,
|
|
67
65
|
});
|
|
68
66
|
const policies = resolveAgentPolicies(opened.agent);
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
};
|
|
77
|
-
const resolvedWorkspace = resolveAgentWorkspace(opened.agent.workspace);
|
|
78
|
-
if (resolvedWorkspace) {
|
|
79
|
-
agentTools.workspace = createFsTool({
|
|
80
|
-
fs: resolvedWorkspace.fs,
|
|
81
|
-
readOnly: resolvedWorkspace.readOnly,
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
const wiredWorkingMemory = await wireWorkingMemory(opened.agent, opened.session, this.config.defaultWorkingMemoryStore);
|
|
85
|
-
if (wiredWorkingMemory) {
|
|
86
|
-
agentTools.memory_block = wiredWorkingMemory.memoryBlockTool;
|
|
87
|
-
}
|
|
88
|
-
let skillPrompt;
|
|
89
|
-
let skillTools = {};
|
|
90
|
-
if (opened.agent.skills) {
|
|
91
|
-
const wired = await wireAgentSkills(opened.agent);
|
|
92
|
-
if (wired) {
|
|
93
|
-
skillTools = wired.tools;
|
|
94
|
-
Object.assign(agentTools, wired.tools);
|
|
95
|
-
skillPrompt = wired.promptSections.map((s) => s.content).join('\n\n');
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
const workspaceTool = agentTools.workspace;
|
|
67
|
+
const knowledgeProvider = this.config.knowledge
|
|
68
|
+
? buildKnowledgeProvider(this.config.knowledge)
|
|
69
|
+
: undefined;
|
|
70
|
+
const openingSurface = await buildAgentToolSurface(opened.agent, opened.session, {
|
|
71
|
+
configTools: this.config.tools,
|
|
72
|
+
knowledgeProvider,
|
|
73
|
+
defaultWorkingMemoryStore: this.config.defaultWorkingMemoryStore,
|
|
74
|
+
});
|
|
99
75
|
const toolExecutor = new CoreToolExecutor({
|
|
100
|
-
tools:
|
|
76
|
+
tools: openingSurface.executorTools,
|
|
101
77
|
enforcer: policies.enforcer,
|
|
102
78
|
agentId: opened.agent.id,
|
|
103
79
|
onInterim: (message) => {
|
|
@@ -113,9 +89,6 @@ export class Runtime {
|
|
|
113
89
|
if (!model) {
|
|
114
90
|
throw new Error('Runtime requires agent.model or config.defaultModel');
|
|
115
91
|
}
|
|
116
|
-
const knowledgeProvider = this.config.knowledge
|
|
117
|
-
? buildKnowledgeProvider(this.config.knowledge)
|
|
118
|
-
: undefined;
|
|
119
92
|
runCtx = await createRunContext({
|
|
120
93
|
session: opened.session,
|
|
121
94
|
runState: freshRunState,
|
|
@@ -137,23 +110,15 @@ export class Runtime {
|
|
|
137
110
|
memoryService: this.config.memoryService
|
|
138
111
|
? buildMemoryService(this.config.memoryService, opened.agent)
|
|
139
112
|
: undefined,
|
|
140
|
-
fs: resolvedWorkspace?.fs,
|
|
113
|
+
fs: openingSurface.resolvedWorkspace?.fs,
|
|
141
114
|
});
|
|
142
115
|
// Agent base layer (ADR 0001): composed into every node turn by the drivers.
|
|
143
116
|
runCtx.baseInstructions = opened.agent.instructions;
|
|
144
|
-
runCtx.globalTools =
|
|
145
|
-
...(opened.agent.globalTools ?? {}),
|
|
146
|
-
...(workspaceTool && resolvedWorkspace?.readOnly !== false
|
|
147
|
-
? { workspace: workspaceTool }
|
|
148
|
-
: {}),
|
|
149
|
-
...skillTools,
|
|
150
|
-
};
|
|
117
|
+
runCtx.globalTools = openingSurface.globalTools;
|
|
151
118
|
runCtx.outOfBandControl = opened.agent.experimental?.outOfBandControl ?? false;
|
|
152
|
-
runCtx.skillPrompt = skillPrompt;
|
|
153
|
-
runCtx.workingMemoryPrompt =
|
|
154
|
-
runCtx.workingMemoryTools =
|
|
155
|
-
? { memory_block: wiredWorkingMemory.memoryBlockTool }
|
|
156
|
-
: undefined;
|
|
119
|
+
runCtx.skillPrompt = openingSurface.skillPrompt;
|
|
120
|
+
runCtx.workingMemoryPrompt = openingSurface.workingMemoryPrompt;
|
|
121
|
+
runCtx.workingMemoryTools = openingSurface.workingMemoryTools;
|
|
157
122
|
await this.hooks?.onStart?.(runCtx);
|
|
158
123
|
const driver = opts.driver ?? new TextDriver();
|
|
159
124
|
let activeAgent = opened.agent;
|
|
@@ -193,17 +158,22 @@ export class Runtime {
|
|
|
193
158
|
});
|
|
194
159
|
runCtx.runState.activeAgentId = loopResult.to;
|
|
195
160
|
activeAgent = target;
|
|
161
|
+
const targetSurface = await buildAgentToolSurface(target, opened.session, {
|
|
162
|
+
configTools: this.config.tools,
|
|
163
|
+
knowledgeProvider,
|
|
164
|
+
defaultWorkingMemoryStore: this.config.defaultWorkingMemoryStore,
|
|
165
|
+
});
|
|
196
166
|
runCtx.autoRetrieve = knowledgeProvider
|
|
197
167
|
? buildAutoRetrieveProvider(knowledgeProvider, target)
|
|
198
168
|
: undefined;
|
|
169
|
+
runCtx.globalTools = targetSurface.globalTools;
|
|
170
|
+
runCtx.skillPrompt = targetSurface.skillPrompt;
|
|
171
|
+
runCtx.workingMemoryPrompt = targetSurface.workingMemoryPrompt;
|
|
172
|
+
runCtx.workingMemoryTools = targetSurface.workingMemoryTools;
|
|
173
|
+
runCtx.fs = targetSurface.resolvedWorkspace?.fs;
|
|
199
174
|
runCtx.memoryService = this.config.memoryService
|
|
200
175
|
? buildMemoryService(this.config.memoryService, target)
|
|
201
176
|
: undefined;
|
|
202
|
-
const targetWorkingMemory = await wireWorkingMemory(target, opened.session, this.config.defaultWorkingMemoryStore);
|
|
203
|
-
runCtx.workingMemoryPrompt = targetWorkingMemory?.promptSection;
|
|
204
|
-
runCtx.workingMemoryTools = targetWorkingMemory
|
|
205
|
-
? { memory_block: targetWorkingMemory.memoryBlockTool }
|
|
206
|
-
: undefined;
|
|
207
177
|
await runCtx.runStore.putRunState(runCtx.runState);
|
|
208
178
|
continue;
|
|
209
179
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AgentConfig } from '../types/agentConfig.js';
|
|
2
|
+
import type { Session } from '../types/session.js';
|
|
3
|
+
import type { AnyTool } from '../types/effectTool.js';
|
|
4
|
+
import type { PersistentMemoryStore } from '../memory/blocks/types.js';
|
|
5
|
+
import type { KnowledgeProvider } from './KnowledgeProvider.js';
|
|
6
|
+
import { type ResolvedAgentWorkspace } from './resolveAgentWorkspace.js';
|
|
7
|
+
export interface AgentToolSurface {
|
|
8
|
+
executorTools: Record<string, AnyTool>;
|
|
9
|
+
globalTools: Record<string, AnyTool>;
|
|
10
|
+
workingMemoryTools?: Record<string, AnyTool>;
|
|
11
|
+
workingMemoryPrompt?: string;
|
|
12
|
+
skillPrompt?: string;
|
|
13
|
+
resolvedWorkspace?: ResolvedAgentWorkspace;
|
|
14
|
+
}
|
|
15
|
+
export interface BuildAgentToolSurfaceDeps {
|
|
16
|
+
configTools?: Record<string, AnyTool>;
|
|
17
|
+
knowledgeProvider?: KnowledgeProvider;
|
|
18
|
+
defaultWorkingMemoryStore?: PersistentMemoryStore;
|
|
19
|
+
}
|
|
20
|
+
export declare function buildAgentToolSurface(agent: AgentConfig, session: Session, deps: BuildAgentToolSurfaceDeps): Promise<AgentToolSurface>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createFsTool } from '../tools/fs/createFsTool.js';
|
|
2
|
+
import { wireAgentSkills } from '../skills/wireAgentSkills.js';
|
|
3
|
+
import { buildKnowledgeTool, wireWorkingMemory } from './grounding/index.js';
|
|
4
|
+
import { resolveAgentWorkspace, } from './resolveAgentWorkspace.js';
|
|
5
|
+
export async function buildAgentToolSurface(agent, session, deps) {
|
|
6
|
+
const executorTools = {
|
|
7
|
+
...(deps.configTools ?? {}),
|
|
8
|
+
...(agent.tools ?? {}),
|
|
9
|
+
...(agent.globalTools ?? {}),
|
|
10
|
+
};
|
|
11
|
+
const resolvedWorkspace = resolveAgentWorkspace(agent.workspace);
|
|
12
|
+
let workspaceTool;
|
|
13
|
+
if (resolvedWorkspace) {
|
|
14
|
+
workspaceTool = createFsTool({
|
|
15
|
+
fs: resolvedWorkspace.fs,
|
|
16
|
+
readOnly: resolvedWorkspace.readOnly,
|
|
17
|
+
});
|
|
18
|
+
executorTools.workspace = workspaceTool;
|
|
19
|
+
}
|
|
20
|
+
const wiredWorkingMemory = await wireWorkingMemory(agent, session, deps.defaultWorkingMemoryStore);
|
|
21
|
+
if (wiredWorkingMemory) {
|
|
22
|
+
executorTools.memory_block = wiredWorkingMemory.memoryBlockTool;
|
|
23
|
+
}
|
|
24
|
+
let skillPrompt;
|
|
25
|
+
let skillTools = {};
|
|
26
|
+
if (agent.skills) {
|
|
27
|
+
const wired = await wireAgentSkills(agent);
|
|
28
|
+
if (wired) {
|
|
29
|
+
skillTools = wired.tools;
|
|
30
|
+
Object.assign(executorTools, wired.tools);
|
|
31
|
+
skillPrompt = wired.promptSections.map((s) => s.content).join('\n\n');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const knowledgeTool = deps.knowledgeProvider
|
|
35
|
+
? buildKnowledgeTool(deps.knowledgeProvider, agent)
|
|
36
|
+
: undefined;
|
|
37
|
+
if (knowledgeTool) {
|
|
38
|
+
executorTools.knowledge_search = knowledgeTool;
|
|
39
|
+
}
|
|
40
|
+
const globalTools = {
|
|
41
|
+
...(agent.globalTools ?? {}),
|
|
42
|
+
...(workspaceTool && resolvedWorkspace?.readOnly !== false ? { workspace: workspaceTool } : {}),
|
|
43
|
+
...skillTools,
|
|
44
|
+
...(knowledgeTool ? { knowledge_search: knowledgeTool } : {}),
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
executorTools,
|
|
48
|
+
globalTools,
|
|
49
|
+
workingMemoryPrompt: wiredWorkingMemory?.promptSection,
|
|
50
|
+
workingMemoryTools: wiredWorkingMemory
|
|
51
|
+
? { memory_block: wiredWorkingMemory.memoryBlockTool }
|
|
52
|
+
: undefined,
|
|
53
|
+
skillPrompt,
|
|
54
|
+
resolvedWorkspace,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -82,7 +82,11 @@ export class TextDriver {
|
|
|
82
82
|
args: call.input,
|
|
83
83
|
toolCallId: call.toolCallId,
|
|
84
84
|
});
|
|
85
|
-
const { result: toolResult, control, failed } = await executeModelToolCall(ctx, { toolName: call.toolName, input: call.input, toolCallId: call.toolCallId },
|
|
85
|
+
const { result: toolResult, control, failed } = await executeModelToolCall(ctx, { toolName: call.toolName, input: call.input, toolCallId: call.toolCallId }, {
|
|
86
|
+
...ctx.globalTools,
|
|
87
|
+
...(ctx.workingMemoryTools ?? {}),
|
|
88
|
+
...node.localTools,
|
|
89
|
+
});
|
|
86
90
|
out.toolResults.push({
|
|
87
91
|
name: call.toolName,
|
|
88
92
|
args: call.input,
|
|
@@ -202,7 +202,11 @@ export class VoiceDriver {
|
|
|
202
202
|
const onToolCall = (id, name, args) => {
|
|
203
203
|
void (async () => {
|
|
204
204
|
ctx.emit({ type: 'tool-call', toolName: name, args, toolCallId: id });
|
|
205
|
-
const { result: toolResult, control, failed } = await executeModelToolCall(ctx, { toolName: name, input: args, toolCallId: id },
|
|
205
|
+
const { result: toolResult, control, failed } = await executeModelToolCall(ctx, { toolName: name, input: args, toolCallId: id }, {
|
|
206
|
+
...ctx.globalTools,
|
|
207
|
+
...(ctx.workingMemoryTools ?? {}),
|
|
208
|
+
...localTools,
|
|
209
|
+
});
|
|
206
210
|
out.toolResults.push({ name, args, result: toolResult, toolCallId: id });
|
|
207
211
|
toolCallsMade.push({
|
|
208
212
|
toolCallId: id,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { appendGatherBlocks, buildAutoRetrieveProvider, buildKnowledgeProvider, } from './knowledge.js';
|
|
1
|
+
export { appendGatherBlocks, buildAutoRetrieveProvider, buildKnowledgeProvider, buildKnowledgeTool, } from './knowledge.js';
|
|
2
2
|
export { buildMemoryService, resetMissingUserIdWarningsForTests, runMemoryIngest, warnMissingUserId, } from './memory.js';
|
|
3
3
|
export { wireWorkingMemory, loadWorkingMemoryBlocks, formatWorkingMemorySection, resolveWorkingMemoryStore, resolveWorkingMemoryOwner, type LoadedWorkingMemoryBlock, type WiredWorkingMemory, } from './workingMemory.js';
|
|
4
4
|
export { runGatherPhase, type GatherResult, type GatherScope } from './gather.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { appendGatherBlocks, buildAutoRetrieveProvider, buildKnowledgeProvider, } from './knowledge.js';
|
|
1
|
+
export { appendGatherBlocks, buildAutoRetrieveProvider, buildKnowledgeProvider, buildKnowledgeTool, } from './knowledge.js';
|
|
2
2
|
export { buildMemoryService, resetMissingUserIdWarningsForTests, runMemoryIngest, warnMissingUserId, } from './memory.js';
|
|
3
3
|
export { wireWorkingMemory, loadWorkingMemoryBlocks, formatWorkingMemorySection, resolveWorkingMemoryStore, resolveWorkingMemoryOwner, } from './workingMemory.js';
|
|
4
4
|
export { runGatherPhase } from './gather.js';
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { AgentConfig } from '../../types/agentConfig.js';
|
|
2
2
|
import type { AutoRetrieveProvider } from '../../types/run-context.js';
|
|
3
|
+
import type { AnyTool } from '../../types/effectTool.js';
|
|
3
4
|
import type { KnowledgeProviderConfig } from '../../types/voice.js';
|
|
4
5
|
import { KnowledgeProvider } from '../KnowledgeProvider.js';
|
|
5
6
|
export declare function buildKnowledgeProvider(config: KnowledgeProviderConfig): KnowledgeProvider;
|
|
6
7
|
export declare function buildAutoRetrieveProvider(provider: KnowledgeProvider, agent: AgentConfig): AutoRetrieveProvider | undefined;
|
|
8
|
+
export declare function buildKnowledgeTool(provider: KnowledgeProvider, agent: AgentConfig): AnyTool | undefined;
|
|
7
9
|
export declare function appendGatherBlocks(system: string, blocks: Array<string | undefined>): string;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { defineTool } from '../../tools/effect/defineTool.js';
|
|
1
3
|
import { normalizeCitations } from '../citations/index.js';
|
|
2
4
|
import { KnowledgeProvider } from '../KnowledgeProvider.js';
|
|
3
5
|
function latestUserMessage(ctx) {
|
|
@@ -61,6 +63,41 @@ export function buildAutoRetrieveProvider(provider, agent) {
|
|
|
61
63
|
},
|
|
62
64
|
};
|
|
63
65
|
}
|
|
66
|
+
export function buildKnowledgeTool(provider, agent) {
|
|
67
|
+
if (!agent.knowledge || agent.knowledge.autoRetrieve !== false) {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
if (!provider.hasRetriever && !provider.hasCompiled) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
const overrides = agent.knowledge;
|
|
74
|
+
return defineTool({
|
|
75
|
+
name: 'knowledge_search',
|
|
76
|
+
description: 'Search the knowledge base for facts needed to answer the user. Call this whenever you need grounded information before answering. Returns relevant document snippets.',
|
|
77
|
+
input: z.object({
|
|
78
|
+
query: z
|
|
79
|
+
.string()
|
|
80
|
+
.trim()
|
|
81
|
+
.min(1, 'Query must not be empty.')
|
|
82
|
+
.describe("What to look up, in the user's language."),
|
|
83
|
+
}),
|
|
84
|
+
execute: async ({ query }, ctx) => {
|
|
85
|
+
const { results, events } = await provider.retrieve(query, undefined, overrides, false);
|
|
86
|
+
if (ctx?.emit) {
|
|
87
|
+
for (const event of events) {
|
|
88
|
+
ctx.emit(event);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const compiled = provider.getCompiledKnowledge(overrides);
|
|
92
|
+
return {
|
|
93
|
+
documents: [
|
|
94
|
+
...(compiled ? [compiled] : []),
|
|
95
|
+
...results.map((result) => result.text),
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
}
|
|
64
101
|
export function appendGatherBlocks(system, blocks) {
|
|
65
102
|
const extras = blocks.filter((block) => Boolean(block?.trim()));
|
|
66
103
|
if (extras.length === 0) {
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import type { MemoryBlockScope, PersistentMemoryConfig } from '../memory/blocks/types.js';
|
|
2
2
|
export interface AgentKnowledge {
|
|
3
|
+
/** Whether the runtime retrieves automatically. Default: `true`.
|
|
4
|
+
* - `true` (guaranteed): pre-inject retrieved knowledge before every
|
|
5
|
+
* answering turn — always grounded; a fused routing turn pays the
|
|
6
|
+
* retrieval cost (the price of a kept grounding promise).
|
|
7
|
+
* - `false` (on-demand): the runtime does not auto-inject; instead the model
|
|
8
|
+
* is given a `knowledge_search` tool and retrieves only when it answers, so
|
|
9
|
+
* routing/dispatch turns pay zero retrieval tax (grounding becomes
|
|
10
|
+
* model-discretion). `autoRetrieve` and the tool are mutually exclusive —
|
|
11
|
+
* the boolean picks the invoker (runtime vs model), not a separate mode. */
|
|
3
12
|
autoRetrieve?: boolean;
|
|
4
13
|
sources?: string[];
|
|
5
14
|
}
|
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.7.
|
|
9
|
+
"version": "0.7.1",
|
|
10
10
|
"description": "A framework for structured conversational AI agents",
|
|
11
11
|
"publishConfig": {
|
|
12
12
|
"access": "public"
|
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
"typescript": "^5.3.0",
|
|
104
104
|
"vitest": "^3.2.4",
|
|
105
105
|
"zod": "^4.0.0",
|
|
106
|
-
"@kuralle-agents/realtime-audio": "0.7.
|
|
106
|
+
"@kuralle-agents/realtime-audio": "0.7.1"
|
|
107
107
|
},
|
|
108
108
|
"dependencies": {
|
|
109
109
|
"chrono-node": "^2.6.0"
|