@kuralle-agents/core 0.7.2 → 0.8.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/dist/flow/collectUntilComplete.js +5 -2
- package/dist/flow/runFlow.js +6 -3
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -0
- package/dist/runtime/Runtime.d.ts +10 -2
- package/dist/runtime/Runtime.js +1 -0
- package/dist/runtime/channels/inputBuffer.d.ts +4 -3
- package/dist/runtime/ctx.js +9 -0
- package/dist/runtime/hostLoop.js +6 -0
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.js +4 -0
- package/dist/runtime/openRun.d.ts +4 -2
- package/dist/runtime/openRun.js +9 -2
- package/dist/runtime/userInput.d.ts +24 -0
- package/dist/runtime/userInput.js +67 -0
- package/dist/testing/mocks.d.ts +2 -1
- package/dist/types/channel.d.ts +2 -1
- package/dist/types/run-context.d.ts +4 -0
- package/package.json +2 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { runCollectDigression } from './collectDigression.js';
|
|
2
2
|
import { hasPendingUserInput } from '../runtime/channels/inputBuffer.js';
|
|
3
|
+
import { userInputToText } from '../runtime/userInput.js';
|
|
3
4
|
import { resolveCollectExtractionNode } from './nodeBuilders.js';
|
|
4
5
|
import { computeMissingFields, createExtractionSubmitTool, getCollectData, incrementCollectTurns, emitExtractionTelemetry, mergeTurnExtraction, projectCollectData, schemaSatisfied, } from './extraction.js';
|
|
5
6
|
import { normalizeTransition } from './normalizeTransition.js';
|
|
@@ -127,8 +128,10 @@ function mergeExtractionFromTurn(node, run, turn, ctx) {
|
|
|
127
128
|
function peekLatestUserMessage(run) {
|
|
128
129
|
for (let i = run.messages.length - 1; i >= 0; i -= 1) {
|
|
129
130
|
const message = run.messages[i];
|
|
130
|
-
if (message?.role === 'user'
|
|
131
|
-
|
|
131
|
+
if (message?.role === 'user') {
|
|
132
|
+
const text = userInputToText(message.content);
|
|
133
|
+
if (text)
|
|
134
|
+
return text;
|
|
132
135
|
}
|
|
133
136
|
}
|
|
134
137
|
return undefined;
|
package/dist/flow/runFlow.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getFlowPark } from './collectDigression.js';
|
|
2
2
|
import { parseConfirmation } from './confirmParse.js';
|
|
3
3
|
import { hasPendingUserInput } from '../runtime/channels/inputBuffer.js';
|
|
4
|
+
import { userInputToText } from '../runtime/userInput.js';
|
|
4
5
|
import { collectUntilComplete } from './collectUntilComplete.js';
|
|
5
6
|
import { isActionNode, isCollectNode, isDecideNode, isReplyNode, } from './nodeKinds.js';
|
|
6
7
|
import { normalizeTransition, resolveNodeRef } from './normalizeTransition.js';
|
|
@@ -53,8 +54,10 @@ function appendUserMessage(run, input) {
|
|
|
53
54
|
function latestUserText(run) {
|
|
54
55
|
for (let i = run.messages.length - 1; i >= 0; i -= 1) {
|
|
55
56
|
const message = run.messages[i];
|
|
56
|
-
if (message?.role === 'user'
|
|
57
|
-
|
|
57
|
+
if (message?.role === 'user') {
|
|
58
|
+
const text = userInputToText(message.content);
|
|
59
|
+
if (text)
|
|
60
|
+
return text;
|
|
58
61
|
}
|
|
59
62
|
}
|
|
60
63
|
return '';
|
|
@@ -67,7 +70,7 @@ async function dispatchConfirmGate(node, run, driver, ctx) {
|
|
|
67
70
|
let input = '';
|
|
68
71
|
if (hasPendingUserInput(ctx.session)) {
|
|
69
72
|
const signal = await driver.awaitUser(ctx);
|
|
70
|
-
input = signal.input;
|
|
73
|
+
input = userInputToText(signal.input);
|
|
71
74
|
appendUserMessage(run, signal.input);
|
|
72
75
|
}
|
|
73
76
|
else {
|
package/dist/index.d.ts
CHANGED
|
@@ -90,10 +90,12 @@ export type { HarnessStreamPart } from './types/stream.js';
|
|
|
90
90
|
export { harnessToUIMessageStream } from './ai-sdk/uiMessageStream.js';
|
|
91
91
|
export type { KuralleMetadata, KuralleDataParts, KuralleUIMessage, } from './ai-sdk/uiMessageStream.js';
|
|
92
92
|
export type { ChoiceOption, ResolvedSelection } from './types/selection.js';
|
|
93
|
-
export type { RunState, StepRecord } from './runtime/durable/types.js';
|
|
93
|
+
export type { RunState, StepRecord, SignalDelivery, SessionDurableRuns, PersistedRun, } from './runtime/durable/types.js';
|
|
94
|
+
export { DURABLE_RUNS_KEY } from './runtime/durable/types.js';
|
|
94
95
|
export type { RunStore } from './runtime/durable/RunStore.js';
|
|
95
96
|
export type { ChannelDriver, TextDriver } from './runtime/channels/index.js';
|
|
96
97
|
export type { TurnResult } from './types/channel.js';
|
|
97
98
|
export type { RunContext } from './types/run-context.js';
|
|
98
99
|
export { createRuntime, Runtime, type HarnessConfig, type RunOptions, } from './runtime/Runtime.js';
|
|
99
100
|
export type { RuntimeLike } from './runtime/RuntimeLike.js';
|
|
101
|
+
export { userInputToText, hasMediaParts, transcribeAudioParts, type UserInputContent, } from './runtime/userInput.js';
|
package/dist/index.js
CHANGED
|
@@ -47,4 +47,6 @@ export { SkillsCapability, wireAgentSkills, collectRegisteredNames, validateSkil
|
|
|
47
47
|
export { buildToolSet, toolToAiSdk, wrapAiSdkTool, ToolApprovalDeniedError, ToolTimeoutError, } from './tools/effect/index.js';
|
|
48
48
|
export { parseConfirmation } from './flow/confirmParse.js';
|
|
49
49
|
export { harnessToUIMessageStream } from './ai-sdk/uiMessageStream.js';
|
|
50
|
+
export { DURABLE_RUNS_KEY } from './runtime/durable/types.js';
|
|
50
51
|
export { createRuntime, Runtime, } from './runtime/Runtime.js';
|
|
52
|
+
export { userInputToText, hasMediaParts, transcribeAudioParts, } from './runtime/userInput.js';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { LanguageModel, ModelMessage } from 'ai';
|
|
1
|
+
import type { LanguageModel, ModelMessage, TranscriptionModel } from 'ai';
|
|
2
|
+
import type { UserInputContent } from './userInput.js';
|
|
2
3
|
import type { Session } from '../types/session.js';
|
|
3
4
|
import type { SessionStore } from '../session/SessionStore.js';
|
|
4
5
|
import type { AuditListOptions, ConversationAuditEntry } from '../audit/types.js';
|
|
@@ -31,10 +32,17 @@ export interface HarnessConfig {
|
|
|
31
32
|
memoryService?: V1MemoryService;
|
|
32
33
|
/** Default store for `agent.memory.workingMemory` when `workingMemory.store` is omitted. */
|
|
33
34
|
defaultWorkingMemoryStore?: PersistentMemoryStore;
|
|
35
|
+
/**
|
|
36
|
+
* Optional AI SDK transcription model. When set, inbound audio file parts (voice
|
|
37
|
+
* notes) are transcribed to text before the model turn — so voice input works on
|
|
38
|
+
* text-only models. When omitted, audio parts pass through to audio-capable models.
|
|
39
|
+
*/
|
|
40
|
+
transcriptionModel?: TranscriptionModel;
|
|
34
41
|
}
|
|
35
42
|
export interface RunOptions {
|
|
36
43
|
sessionId?: string;
|
|
37
|
-
|
|
44
|
+
/** The user turn: plain text, or AI SDK multimodal content (text + file/image/audio parts). */
|
|
45
|
+
input?: UserInputContent;
|
|
38
46
|
selection?: ResolvedSelection;
|
|
39
47
|
userId?: string;
|
|
40
48
|
agentId?: string;
|
package/dist/runtime/Runtime.js
CHANGED
|
@@ -60,6 +60,7 @@ export class Runtime {
|
|
|
60
60
|
seedMessages: opts.seedMessages,
|
|
61
61
|
historyDelta: opts.historyDelta,
|
|
62
62
|
signalDelivery: opts.signalDelivery,
|
|
63
|
+
transcriptionModel: this.config.transcriptionModel,
|
|
63
64
|
defaultAgentId: this.config.defaultAgentId,
|
|
64
65
|
sessionStore: this.sessionStore,
|
|
65
66
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Session } from '../../types/session.js';
|
|
2
|
-
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function
|
|
2
|
+
import type { UserInputContent } from '../userInput.js';
|
|
3
|
+
export declare function setPendingUserInput(session: Session, input: UserInputContent): void;
|
|
4
|
+
export declare function consumePendingUserInput(session: Session): UserInputContent;
|
|
5
|
+
export declare function peekPendingUserInput(session: Session): UserInputContent | undefined;
|
|
5
6
|
export declare function hasPendingUserInput(session: Session): boolean;
|
package/dist/runtime/ctx.js
CHANGED
|
@@ -112,6 +112,15 @@ function makeCtx(deps) {
|
|
|
112
112
|
bargeIn: deps.bargeIn,
|
|
113
113
|
abortSignal: deps.abortSignal,
|
|
114
114
|
turnInputConsumed: false,
|
|
115
|
+
// Rebase durable effect callsites to 0. Called at flow entry so a flow's
|
|
116
|
+
// effects (and any suspend/resume callsite) are anchored to the flow itself —
|
|
117
|
+
// identical whether the flow was entered fresh after an answering turn (which
|
|
118
|
+
// may have consumed callsites via enter_flow / tool calls) or re-entered on
|
|
119
|
+
// resume (where that answering turn does not re-run). Without this, a suspend's
|
|
120
|
+
// recorded callsite would not match on resume and the run would re-suspend.
|
|
121
|
+
resetCallsites: () => {
|
|
122
|
+
effectOrdinal = 0;
|
|
123
|
+
},
|
|
115
124
|
tool: async (name, args, options) => {
|
|
116
125
|
// needsApproval gate: a tool flagged `needsApproval` must be approved by a human
|
|
117
126
|
// before it runs. Approval is a durable pause (the `__approval` signal); on resume
|
package/dist/runtime/hostLoop.js
CHANGED
|
@@ -59,6 +59,12 @@ async function runAnsweringAgent(agent, run, driver, ctx, classify) {
|
|
|
59
59
|
async function runActiveFlow(flow, run, driver, ctx, agent) {
|
|
60
60
|
incrementTurnCount(run);
|
|
61
61
|
assertWithinTurnLimit(run, ctx.limits);
|
|
62
|
+
// Anchor durable effect callsites to the flow. On a fresh entry the answering
|
|
63
|
+
// turn may have consumed callsites (enter_flow / tool calls); on resume that
|
|
64
|
+
// turn does not re-run. Rebasing here makes the flow's callsites (and any
|
|
65
|
+
// suspend/resume key) identical across both paths, so a resumed run does not
|
|
66
|
+
// re-suspend on a callsite mismatch.
|
|
67
|
+
ctx.resetCallsites();
|
|
62
68
|
const result = await runFlow(flow, run, driver, ctx, agent);
|
|
63
69
|
if (result.kind === 'handoff') {
|
|
64
70
|
return { kind: 'handoff', to: result.to, reason: result.reason };
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -4,4 +4,5 @@ export { SessionWorkingMemory } from './WorkingMemory.js';
|
|
|
4
4
|
export { TextDriver, VoiceDriver } from './channels/index.js';
|
|
5
5
|
export type { VoiceDriverConfig } from './channels/index.js';
|
|
6
6
|
export { setPendingUserInput, consumePendingUserInput, peekPendingUserInput, hasPendingUserInput, } from './channels/index.js';
|
|
7
|
+
export { userInputToText, hasMediaParts, transcribeAudioParts, type UserInputContent, } from './userInput.js';
|
|
7
8
|
export { isAbortSignal, type InterruptionEvent, type AbortOptions, type CancellationReason, } from '../types/index.js';
|
package/dist/runtime/index.js
CHANGED
|
@@ -5,4 +5,8 @@ export { TextDriver, VoiceDriver } from './channels/index.js';
|
|
|
5
5
|
// implement awaitUser the same FIFO-aware way the built-in drivers do (the
|
|
6
6
|
// buffer is an ordered queue since 0.3.13/H3, not a single slot).
|
|
7
7
|
export { setPendingUserInput, consumePendingUserInput, peekPendingUserInput, hasPendingUserInput, } from './channels/index.js';
|
|
8
|
+
// Multimodal user input — `UserInputContent` is the runtime's accepted user-turn
|
|
9
|
+
// shape (text or AI SDK file/image/audio parts). Helpers project to text and
|
|
10
|
+
// transcribe audio so ingress adapters (web/messaging) can build it uniformly.
|
|
11
|
+
export { userInputToText, hasMediaParts, transcribeAudioParts, } from './userInput.js';
|
|
8
12
|
export { isAbortSignal, } from '../types/index.js';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { ModelMessage } from 'ai';
|
|
1
|
+
import type { ModelMessage, TranscriptionModel } from 'ai';
|
|
2
|
+
import { type UserInputContent } from './userInput.js';
|
|
2
3
|
import type { Session } from '../types/session.js';
|
|
3
4
|
import type { SessionStore } from '../session/SessionStore.js';
|
|
4
5
|
import type { AgentConfig } from '../types/agentConfig.js';
|
|
@@ -9,12 +10,13 @@ import type { ResolvedSelection } from '../types/selection.js';
|
|
|
9
10
|
export interface OpenRunOptions {
|
|
10
11
|
sessionId: string;
|
|
11
12
|
userId?: string;
|
|
12
|
-
input?:
|
|
13
|
+
input?: UserInputContent;
|
|
13
14
|
selection?: ResolvedSelection;
|
|
14
15
|
agentId?: string;
|
|
15
16
|
seedMessages?: ModelMessage[];
|
|
16
17
|
historyDelta?: ModelMessage[];
|
|
17
18
|
signalDelivery?: SignalDelivery;
|
|
19
|
+
transcriptionModel?: TranscriptionModel;
|
|
18
20
|
defaultAgentId: string;
|
|
19
21
|
sessionStore: SessionStore;
|
|
20
22
|
}
|
package/dist/runtime/openRun.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { transcribeAudioParts } from './userInput.js';
|
|
2
3
|
import { setPendingUserInput } from './channels/inputBuffer.js';
|
|
3
4
|
import { SessionRunStore } from './durable/SessionRunStore.js';
|
|
4
5
|
import { recordSignalDelivery } from './durable/replay.js';
|
|
@@ -45,8 +46,14 @@ export async function openRun(agentsById, options) {
|
|
|
45
46
|
runState.updatedAt = Date.now();
|
|
46
47
|
await runStore.putRunState(runState);
|
|
47
48
|
}
|
|
48
|
-
const
|
|
49
|
-
|
|
49
|
+
const rawInput = options.selection?.id ?? options.input;
|
|
50
|
+
const effectiveInput = rawInput === undefined
|
|
51
|
+
? undefined
|
|
52
|
+
: await transcribeAudioParts(rawInput, options.transcriptionModel);
|
|
53
|
+
const hasInput = typeof effectiveInput === 'string'
|
|
54
|
+
? effectiveInput.length > 0
|
|
55
|
+
: Array.isArray(effectiveInput) && effectiveInput.length > 0;
|
|
56
|
+
if (hasInput && effectiveInput !== undefined) {
|
|
50
57
|
runState.updatedAt = Date.now();
|
|
51
58
|
if (runState.activeFlow) {
|
|
52
59
|
await runStore.putRunState(runState);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type UserContent, type TranscriptionModel } from 'ai';
|
|
2
|
+
/**
|
|
3
|
+
* User-turn content the runtime accepts: plain text, or AI SDK multimodal parts
|
|
4
|
+
* (text + file/image/audio). This is exactly the `content` of a user `ModelMessage`,
|
|
5
|
+
* so it threads into the model with no translation.
|
|
6
|
+
*
|
|
7
|
+
* Durability invariant: any `FilePart.data` flowing through the runtime must be
|
|
8
|
+
* JSON-serializable (a base64 string, data URL, or https URL) — never a raw
|
|
9
|
+
* `Buffer`/`Uint8Array`. `RunState.messages`, `session.messages`, and the pending
|
|
10
|
+
* input buffer are all persisted through the `SessionStore` (JSON/Redis/Postgres).
|
|
11
|
+
*/
|
|
12
|
+
export type UserInputContent = UserContent;
|
|
13
|
+
/** Text projection of user input — for confirm-gate parsing, choice matching, and
|
|
14
|
+
* extraction hints. Non-text parts are dropped. A plain string returns as-is. */
|
|
15
|
+
export declare function userInputToText(input: UserInputContent): string;
|
|
16
|
+
/** Whether the input carries any non-text (file/image/audio) parts. */
|
|
17
|
+
export declare function hasMediaParts(input: UserInputContent): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Replace audio file parts with their transcript (a text part) using an AI SDK
|
|
20
|
+
* transcription model. With no model configured, audio parts pass through
|
|
21
|
+
* unchanged — audio-capable models (e.g. Gemini) accept them directly. Non-audio
|
|
22
|
+
* parts (images, documents) are always left untouched.
|
|
23
|
+
*/
|
|
24
|
+
export declare function transcribeAudioParts(input: UserInputContent, transcriptionModel: TranscriptionModel | undefined): Promise<UserInputContent>;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { experimental_transcribe as transcribe, } from 'ai';
|
|
2
|
+
function isFilePart(part) {
|
|
3
|
+
return part.type === 'file';
|
|
4
|
+
}
|
|
5
|
+
function isAudioPart(part) {
|
|
6
|
+
return typeof part.mediaType === 'string' && part.mediaType.startsWith('audio/');
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Normalize a FilePart's `data` into something AI SDK `transcribe` accepts as
|
|
10
|
+
* `audio`. A bare string is treated by `transcribe` as base64, so http(s) URLs
|
|
11
|
+
* must become a `URL` (fetched via the built-in download) and `data:` URLs must
|
|
12
|
+
* be reduced to their base64 payload. Bytes and `URL`s pass through unchanged.
|
|
13
|
+
*/
|
|
14
|
+
function audioSource(data) {
|
|
15
|
+
if (typeof data !== 'string')
|
|
16
|
+
return data;
|
|
17
|
+
if (data.startsWith('data:')) {
|
|
18
|
+
const comma = data.indexOf(',');
|
|
19
|
+
return comma === -1 ? data : data.slice(comma + 1);
|
|
20
|
+
}
|
|
21
|
+
if (data.startsWith('http://') || data.startsWith('https://')) {
|
|
22
|
+
return new URL(data);
|
|
23
|
+
}
|
|
24
|
+
return data;
|
|
25
|
+
}
|
|
26
|
+
/** Text projection of user input — for confirm-gate parsing, choice matching, and
|
|
27
|
+
* extraction hints. Non-text parts are dropped. A plain string returns as-is. */
|
|
28
|
+
export function userInputToText(input) {
|
|
29
|
+
if (typeof input === 'string')
|
|
30
|
+
return input;
|
|
31
|
+
return input
|
|
32
|
+
.filter((p) => p.type === 'text')
|
|
33
|
+
.map((p) => p.text)
|
|
34
|
+
.join(' ')
|
|
35
|
+
.trim();
|
|
36
|
+
}
|
|
37
|
+
/** Whether the input carries any non-text (file/image/audio) parts. */
|
|
38
|
+
export function hasMediaParts(input) {
|
|
39
|
+
return typeof input !== 'string' && input.some((p) => p.type !== 'text');
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Replace audio file parts with their transcript (a text part) using an AI SDK
|
|
43
|
+
* transcription model. With no model configured, audio parts pass through
|
|
44
|
+
* unchanged — audio-capable models (e.g. Gemini) accept them directly. Non-audio
|
|
45
|
+
* parts (images, documents) are always left untouched.
|
|
46
|
+
*/
|
|
47
|
+
export async function transcribeAudioParts(input, transcriptionModel) {
|
|
48
|
+
if (!transcriptionModel || typeof input === 'string')
|
|
49
|
+
return input;
|
|
50
|
+
if (!input.some((p) => isFilePart(p) && isAudioPart(p)))
|
|
51
|
+
return input;
|
|
52
|
+
const out = [];
|
|
53
|
+
for (const part of input) {
|
|
54
|
+
if (isFilePart(part) && isAudioPart(part)) {
|
|
55
|
+
const { text } = await transcribe({
|
|
56
|
+
model: transcriptionModel,
|
|
57
|
+
audio: audioSource(part.data),
|
|
58
|
+
});
|
|
59
|
+
if (text.trim())
|
|
60
|
+
out.push({ type: 'text', text });
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
out.push(part);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
package/dist/testing/mocks.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { HarnessStreamPart, TurnHandle } from '../types/stream.js';
|
|
2
2
|
import type { TurnResult } from '../types/channel.js';
|
|
3
3
|
import type { Session } from '../types/session.js';
|
|
4
|
+
import type { UserInputContent } from '../runtime/userInput.js';
|
|
4
5
|
import type { RuntimeLike } from '../runtime/RuntimeLike.js';
|
|
5
6
|
export interface MockRuntimeRunCall {
|
|
6
7
|
sessionId?: string;
|
|
7
|
-
input?:
|
|
8
|
+
input?: UserInputContent;
|
|
8
9
|
agentId?: string;
|
|
9
10
|
seedMessages?: unknown[];
|
|
10
11
|
}
|
package/dist/types/channel.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ToolSet } from 'ai';
|
|
2
|
+
import type { UserInputContent } from '../runtime/userInput.js';
|
|
2
3
|
import type { RunContext } from './run-context.js';
|
|
3
4
|
import type { FlowNode } from './flow.js';
|
|
4
5
|
import type { AnyTool } from './effectTool.js';
|
|
@@ -44,7 +45,7 @@ export interface TurnResult {
|
|
|
44
45
|
}
|
|
45
46
|
export type UserSignal = {
|
|
46
47
|
type: 'message';
|
|
47
|
-
input:
|
|
48
|
+
input: UserInputContent;
|
|
48
49
|
};
|
|
49
50
|
interface ToolResultRecord {
|
|
50
51
|
name: string;
|
|
@@ -112,6 +112,10 @@ export interface RunContext {
|
|
|
112
112
|
}): Promise<unknown>;
|
|
113
113
|
now(): Promise<number>;
|
|
114
114
|
uuid(): Promise<string>;
|
|
115
|
+
/** Rebase durable effect callsites to 0. The runtime calls this at flow entry so
|
|
116
|
+
* a flow's durable callsites are anchored to the flow — identical on fresh entry
|
|
117
|
+
* (after an answering turn) and on resume (where that turn does not re-run). */
|
|
118
|
+
resetCallsites(): void;
|
|
115
119
|
}
|
|
116
120
|
export type ActionContext = Pick<RunContext, 'tool' | 'approve' | 'signal' | 'now' | 'uuid' | 'emit' | 'fs'>;
|
|
117
121
|
export type ToolContext = Pick<RunContext, 'session' | 'runState' | 'tool' | 'now' | 'uuid' | 'emit' | 'fs'>;
|
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.
|
|
9
|
+
"version": "0.8.0",
|
|
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.
|
|
106
|
+
"@kuralle-agents/realtime-audio": "0.8.0"
|
|
107
107
|
},
|
|
108
108
|
"dependencies": {
|
|
109
109
|
"chrono-node": "^2.6.0"
|