@kuralle-agents/core 0.7.1 → 0.7.2
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/index.d.ts
CHANGED
|
@@ -55,6 +55,8 @@ export { resolveAgentWorkspace, type ResolvedAgentWorkspace, } from './runtime/r
|
|
|
55
55
|
export { DEFAULT_CONTEXT_BUDGET, VOICE_CONTEXT_BUDGET, computeMessageHistoryBudget, truncateToTokenBudget, formatMemoryWithBudget, estimateTokenCount, ContextBudget, } from './runtime/ContextBudget.js';
|
|
56
56
|
export type { ContextBudgetConfig } from './runtime/ContextBudget.js';
|
|
57
57
|
export { TokenAccumulator } from './runtime/TokenAccumulator.js';
|
|
58
|
+
export { applyPromptCache, applyAnthropicCacheControl, buildOpenAIResponsesProviderOptions, isAnthropicLanguageModel, isOpenAIResponsesModel, } from './runtime/promptCache.js';
|
|
59
|
+
export type { AnthropicCacheTtl, OpenAIResponsesCompactOptions } from './runtime/promptCache.js';
|
|
58
60
|
export { handoffFilters, removeToolHistory, keepRecentMessages, removeKeys, composeFilters, } from './runtime/handoffFilters.js';
|
|
59
61
|
export type { HandoffInputFilter, HandoffInputData, HandoffInputResult, } from './runtime/handoffFilters.js';
|
|
60
62
|
export { DefaultToolExecutor, DefaultConversationState, DefaultConversationEventLog, DefaultAgentStateController, createFoundation, } from './foundation/index.js';
|
package/dist/index.js
CHANGED
|
@@ -34,6 +34,7 @@ export { wireWorkingMemory, loadWorkingMemoryBlocks, formatWorkingMemorySection,
|
|
|
34
34
|
export { resolveAgentWorkspace, } from './runtime/resolveAgentWorkspace.js';
|
|
35
35
|
export { DEFAULT_CONTEXT_BUDGET, VOICE_CONTEXT_BUDGET, computeMessageHistoryBudget, truncateToTokenBudget, formatMemoryWithBudget, estimateTokenCount, ContextBudget, } from './runtime/ContextBudget.js';
|
|
36
36
|
export { TokenAccumulator } from './runtime/TokenAccumulator.js';
|
|
37
|
+
export { applyPromptCache, applyAnthropicCacheControl, buildOpenAIResponsesProviderOptions, isAnthropicLanguageModel, isOpenAIResponsesModel, } from './runtime/promptCache.js';
|
|
37
38
|
export { handoffFilters, removeToolHistory, keepRecentMessages, removeKeys, composeFilters, } from './runtime/handoffFilters.js';
|
|
38
39
|
export { DefaultToolExecutor, DefaultConversationState, DefaultConversationEventLog, DefaultAgentStateController, createFoundation, } from './foundation/index.js';
|
|
39
40
|
export { CapabilityHost, ExtractionCapability, GuardrailCapability, AutoRetrieveCapability, PassThroughRefinement, PassThroughValidation, toGeminiDeclarations, toAISDKTools, } from './capabilities/index.js';
|
|
@@ -9,6 +9,7 @@ import { resolveMaxSteps } from '../policies/limits.js';
|
|
|
9
9
|
import { speakWithHostControl } from './streaming/hostControlSpeak.js';
|
|
10
10
|
import { resolveStreamMode } from './streaming/mode.js';
|
|
11
11
|
import { appendGatherBlocks, resolveNodeGatherScope, runGatherPhase } from '../grounding/index.js';
|
|
12
|
+
import { applyPromptCache } from '../promptCache.js';
|
|
12
13
|
import { isFlowTransitionControlTool } from '../../flow/flowControlTools.js';
|
|
13
14
|
import { resolveStructuredDecide } from '../../flow/choiceMatch.js';
|
|
14
15
|
export class TextDriver {
|
|
@@ -50,12 +51,14 @@ export class TextDriver {
|
|
|
50
51
|
const source = {
|
|
51
52
|
async *[Symbol.asyncIterator]() {
|
|
52
53
|
for (let step = 0; step < maxSteps; step += 1) {
|
|
54
|
+
const cached = applyPromptCache(model, ctx.session.id, messages);
|
|
53
55
|
const result = streamText({
|
|
54
56
|
model,
|
|
55
57
|
system,
|
|
56
|
-
messages,
|
|
58
|
+
messages: cached.messages,
|
|
57
59
|
tools: aiTools,
|
|
58
60
|
abortSignal: ctx.abortSignal,
|
|
61
|
+
...(cached.providerOptions ? { providerOptions: cached.providerOptions } : {}),
|
|
59
62
|
});
|
|
60
63
|
for await (const part of result.fullStream) {
|
|
61
64
|
if (part.type === 'text-delta') {
|
|
@@ -2,6 +2,7 @@ import { streamText } from 'ai';
|
|
|
2
2
|
import { executeModelToolCall, toolResultMessage } from './executeModelTool.js';
|
|
3
3
|
import { buildToolSet } from '../../tools/effect/index.js';
|
|
4
4
|
import { buildNodePrompt, composeSystem } from '../../flow/nodeBuilders.js';
|
|
5
|
+
import { applyPromptCache } from '../promptCache.js';
|
|
5
6
|
/**
|
|
6
7
|
* Shared, NON-SPEAKING field extraction for `collect` nodes, used by every
|
|
7
8
|
* ChannelDriver so text and voice behave identically. It runs the model with the
|
|
@@ -20,13 +21,15 @@ export async function runSilentExtraction(node, ctx, model, maxSteps) {
|
|
|
20
21
|
const aiTools = resolveExtractionTools(node);
|
|
21
22
|
const out = { text: '', toolResults: [] };
|
|
22
23
|
for (let step = 0; step < maxSteps; step += 1) {
|
|
24
|
+
const cached = applyPromptCache(model, ctx.session.id, messages);
|
|
23
25
|
const result = streamText({
|
|
24
26
|
model,
|
|
25
27
|
system,
|
|
26
|
-
messages,
|
|
28
|
+
messages: cached.messages,
|
|
27
29
|
tools: aiTools,
|
|
28
30
|
temperature: 0,
|
|
29
31
|
abortSignal: ctx.abortSignal,
|
|
32
|
+
...(cached.providerOptions ? { providerOptions: cached.providerOptions } : {}),
|
|
30
33
|
});
|
|
31
34
|
for await (const part of result.fullStream) {
|
|
32
35
|
// Intentionally NOT handling 'text-delta' — extraction never speaks.
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
* but extends caching across short user idle periods + cross-session
|
|
24
24
|
* within an hour.
|
|
25
25
|
*/
|
|
26
|
-
import type { ModelMessage } from 'ai';
|
|
26
|
+
import type { JSONValue, ModelMessage } from 'ai';
|
|
27
27
|
export type AnthropicCacheTtl = '5m' | '1h';
|
|
28
28
|
/**
|
|
29
29
|
* Returns a SHALLOW-COPIED message list with cache_control markers
|
|
@@ -90,3 +90,19 @@ export interface OpenAIResponsesCompactOptions {
|
|
|
90
90
|
* branch but ignored otherwise.
|
|
91
91
|
*/
|
|
92
92
|
export declare function buildOpenAIResponsesProviderOptions(opts: OpenAIResponsesCompactOptions, sessionId: string): Record<string, unknown> | null;
|
|
93
|
+
/**
|
|
94
|
+
* Single wiring point for provider prompt caching, called by the driver
|
|
95
|
+
* `streamText` sites. Gated by the conservative detectors so non-matching
|
|
96
|
+
* providers are untouched:
|
|
97
|
+
* - Anthropic → applies `cache_control` breakpoints (caches the system+tools
|
|
98
|
+
* prefix + recent history; ~75% input-cost + TTFT off multi-turn turns).
|
|
99
|
+
* - OpenAI Responses → sets `promptCacheKey` (= sessionId, pins same-session
|
|
100
|
+
* turns to one cache slot) + `truncation: 'auto'` overflow safety net.
|
|
101
|
+
* Returns the (possibly transformed) messages + an optional `providerOptions`
|
|
102
|
+
* bag ready to spread into `streamText`. Default-on: both are no-ops on
|
|
103
|
+
* providers that ignore the fields.
|
|
104
|
+
*/
|
|
105
|
+
export declare function applyPromptCache(model: unknown, sessionId: string, messages: ModelMessage[]): {
|
|
106
|
+
messages: ModelMessage[];
|
|
107
|
+
providerOptions?: Record<string, Record<string, JSONValue>>;
|
|
108
|
+
};
|
|
@@ -110,6 +110,30 @@ export function buildOpenAIResponsesProviderOptions(opts, sessionId) {
|
|
|
110
110
|
}
|
|
111
111
|
return Object.keys(out).length > 0 ? out : null;
|
|
112
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* Single wiring point for provider prompt caching, called by the driver
|
|
115
|
+
* `streamText` sites. Gated by the conservative detectors so non-matching
|
|
116
|
+
* providers are untouched:
|
|
117
|
+
* - Anthropic → applies `cache_control` breakpoints (caches the system+tools
|
|
118
|
+
* prefix + recent history; ~75% input-cost + TTFT off multi-turn turns).
|
|
119
|
+
* - OpenAI Responses → sets `promptCacheKey` (= sessionId, pins same-session
|
|
120
|
+
* turns to one cache slot) + `truncation: 'auto'` overflow safety net.
|
|
121
|
+
* Returns the (possibly transformed) messages + an optional `providerOptions`
|
|
122
|
+
* bag ready to spread into `streamText`. Default-on: both are no-ops on
|
|
123
|
+
* providers that ignore the fields.
|
|
124
|
+
*/
|
|
125
|
+
export function applyPromptCache(model, sessionId, messages) {
|
|
126
|
+
const outMessages = isAnthropicLanguageModel(model)
|
|
127
|
+
? applyAnthropicCacheControl(messages)
|
|
128
|
+
: messages;
|
|
129
|
+
if (isOpenAIResponsesModel(model)) {
|
|
130
|
+
const openai = buildOpenAIResponsesProviderOptions({ useSessionAsPromptCacheKey: true, truncationFallback: 'auto' }, sessionId);
|
|
131
|
+
if (openai) {
|
|
132
|
+
return { messages: outMessages, providerOptions: { openai: openai } };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return { messages: outMessages };
|
|
136
|
+
}
|
|
113
137
|
function withProviderOptions(msg, cacheControl) {
|
|
114
138
|
const existing = msg.providerOptions ?? {};
|
|
115
139
|
const existingAnthropic = existing.anthropic ?? {};
|
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.2",
|
|
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.2"
|
|
107
107
|
},
|
|
108
108
|
"dependencies": {
|
|
109
109
|
"chrono-node": "^2.6.0"
|