@ekairos/thread 1.22.3 → 1.22.4-beta.feature-thread-unify.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/README.md +292 -353
- package/dist/index.d.ts +5 -1
- package/dist/index.js +3 -1
- package/dist/react.d.ts +4 -3
- package/dist/reactors/ai-sdk.reactor.d.ts +38 -0
- package/dist/reactors/ai-sdk.reactor.js +65 -0
- package/dist/reactors/scripted.reactor.d.ts +23 -0
- package/dist/reactors/scripted.reactor.js +56 -0
- package/dist/reactors/types.d.ts +48 -0
- package/dist/reactors/types.js +1 -0
- package/dist/steps/do-thread-stream-step.d.ts +2 -1
- package/dist/steps/do-thread-stream-step.js +4 -2
- package/dist/steps/reaction.steps.d.ts +3 -2
- package/dist/steps/reaction.steps.js +7 -66
- package/dist/steps/store.steps.js +1 -2
- package/dist/steps/trace.steps.d.ts +2 -1
- package/dist/steps/trace.steps.js +9 -4
- package/dist/stores/instant.documents.d.ts +2 -2
- package/dist/stores/instant.documents.js +1 -1
- package/dist/stores/instant.store.js +57 -4
- package/dist/thread.builder.js +4 -1
- package/dist/thread.contract.d.ts +45 -0
- package/dist/thread.contract.js +98 -0
- package/dist/thread.d.ts +1 -1
- package/dist/thread.engine.d.ts +1 -1
- package/dist/thread.engine.js +44 -17
- package/dist/thread.events.js +17 -2
- package/dist/thread.js +1 -1
- package/dist/thread.reactor.d.ts +3 -82
- package/dist/thread.reactor.js +2 -65
- package/dist/thread.store.d.ts +12 -8
- package/dist/thread.stream.d.ts +119 -0
- package/dist/thread.stream.js +152 -0
- package/package.json +9 -3
package/dist/thread.builder.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { Thread, } from "./thread.engine.js";
|
|
2
2
|
import { registerThread } from "./thread.registry.js";
|
|
3
|
+
function isDynamicModelSelector(model) {
|
|
4
|
+
return typeof model === "function" && model.length >= 1;
|
|
5
|
+
}
|
|
3
6
|
export function thread(config) {
|
|
4
7
|
class FunctionalThread extends Thread {
|
|
5
8
|
constructor() {
|
|
@@ -28,7 +31,7 @@ export function thread(config) {
|
|
|
28
31
|
throw new Error("Thread config is missing actions()");
|
|
29
32
|
}
|
|
30
33
|
getModel(context, env) {
|
|
31
|
-
if (
|
|
34
|
+
if (isDynamicModelSelector(config.model))
|
|
32
35
|
return config.model(context, env);
|
|
33
36
|
return config.model ?? super.getModel(context, env);
|
|
34
37
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export type Transition<From extends string, To extends string> = {
|
|
2
|
+
from: From;
|
|
3
|
+
to: To;
|
|
4
|
+
};
|
|
5
|
+
export declare const THREAD_STATUSES: readonly ["open", "streaming", "closed", "failed"];
|
|
6
|
+
export type ThreadThreadStatus = (typeof THREAD_STATUSES)[number];
|
|
7
|
+
export declare const THREAD_CONTEXT_STATUSES: readonly ["open", "streaming", "closed"];
|
|
8
|
+
export type ThreadContextStatus = (typeof THREAD_CONTEXT_STATUSES)[number];
|
|
9
|
+
export declare const THREAD_EXECUTION_STATUSES: readonly ["executing", "completed", "failed"];
|
|
10
|
+
export type ThreadExecutionStatus = (typeof THREAD_EXECUTION_STATUSES)[number];
|
|
11
|
+
export declare const THREAD_STEP_STATUSES: readonly ["running", "completed", "failed"];
|
|
12
|
+
export type ThreadStepStatus = (typeof THREAD_STEP_STATUSES)[number];
|
|
13
|
+
export declare const THREAD_ITEM_STATUSES: readonly ["stored", "pending", "completed"];
|
|
14
|
+
export type ThreadItemStatus = (typeof THREAD_ITEM_STATUSES)[number];
|
|
15
|
+
export declare const THREAD_ITEM_TYPES: readonly ["input_text", "output_text", "ekairos:system"];
|
|
16
|
+
export type ThreadItemType = (typeof THREAD_ITEM_TYPES)[number];
|
|
17
|
+
export declare const THREAD_CHANNELS: readonly ["web", "whatsapp", "email"];
|
|
18
|
+
export type ThreadChannel = (typeof THREAD_CHANNELS)[number];
|
|
19
|
+
export declare const THREAD_TRACE_EVENT_KINDS: readonly ["workflow.run", "workflow.step", "thread.run", "thread.context", "thread.execution", "thread.item", "thread.review", "thread.step", "thread.part", "thread.llm"];
|
|
20
|
+
export type ThreadTraceEventKind = (typeof THREAD_TRACE_EVENT_KINDS)[number];
|
|
21
|
+
export declare const THREAD_STREAM_CHUNK_TYPES: readonly ["data-context-id", "data-context-substate", "data-thread-ping", "tool-output-available", "tool-output-error", "finish"];
|
|
22
|
+
export type ThreadStreamChunkType = (typeof THREAD_STREAM_CHUNK_TYPES)[number];
|
|
23
|
+
export declare const THREAD_CONTEXT_SUBSTATE_KEYS: readonly ["actions"];
|
|
24
|
+
export type ThreadContextSubstateKey = (typeof THREAD_CONTEXT_SUBSTATE_KEYS)[number];
|
|
25
|
+
export type ThreadTransition = Transition<"open" | "streaming" | "failed", "open" | "streaming" | "closed" | "failed">;
|
|
26
|
+
export type ContextTransition = Transition<"open" | "streaming", "streaming" | "open" | "closed">;
|
|
27
|
+
export type ExecutionTransition = Transition<"executing", "completed" | "failed">;
|
|
28
|
+
export type StepTransition = Transition<"running", "completed" | "failed">;
|
|
29
|
+
export type ItemTransition = Transition<"stored" | "pending", "pending" | "completed">;
|
|
30
|
+
export declare const THREAD_THREAD_TRANSITIONS: readonly ThreadTransition[];
|
|
31
|
+
export declare const THREAD_CONTEXT_TRANSITIONS: readonly ContextTransition[];
|
|
32
|
+
export declare const THREAD_EXECUTION_TRANSITIONS: readonly ExecutionTransition[];
|
|
33
|
+
export declare const THREAD_STEP_TRANSITIONS: readonly StepTransition[];
|
|
34
|
+
export declare const THREAD_ITEM_TRANSITIONS: readonly ItemTransition[];
|
|
35
|
+
export declare function canThreadTransition(from: string, to: string): boolean;
|
|
36
|
+
export declare function canContextTransition(from: string, to: string): boolean;
|
|
37
|
+
export declare function canExecutionTransition(from: string, to: string): boolean;
|
|
38
|
+
export declare function canStepTransition(from: string, to: string): boolean;
|
|
39
|
+
export declare function canItemTransition(from: string, to: string): boolean;
|
|
40
|
+
export declare function assertThreadTransition(from: string, to: string): void;
|
|
41
|
+
export declare function assertContextTransition(from: string, to: string): void;
|
|
42
|
+
export declare function assertExecutionTransition(from: string, to: string): void;
|
|
43
|
+
export declare function assertStepTransition(from: string, to: string): void;
|
|
44
|
+
export declare function assertItemTransition(from: string, to: string): void;
|
|
45
|
+
export declare function assertThreadPartKey(stepId: string, idx: number, key: string): void;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
export const THREAD_STATUSES = ["open", "streaming", "closed", "failed"];
|
|
2
|
+
export const THREAD_CONTEXT_STATUSES = ["open", "streaming", "closed"];
|
|
3
|
+
export const THREAD_EXECUTION_STATUSES = ["executing", "completed", "failed"];
|
|
4
|
+
export const THREAD_STEP_STATUSES = ["running", "completed", "failed"];
|
|
5
|
+
export const THREAD_ITEM_STATUSES = ["stored", "pending", "completed"];
|
|
6
|
+
export const THREAD_ITEM_TYPES = ["input_text", "output_text", "ekairos:system"];
|
|
7
|
+
export const THREAD_CHANNELS = ["web", "whatsapp", "email"];
|
|
8
|
+
export const THREAD_TRACE_EVENT_KINDS = [
|
|
9
|
+
"workflow.run",
|
|
10
|
+
"workflow.step",
|
|
11
|
+
"thread.run",
|
|
12
|
+
"thread.context",
|
|
13
|
+
"thread.execution",
|
|
14
|
+
"thread.item",
|
|
15
|
+
"thread.review",
|
|
16
|
+
"thread.step",
|
|
17
|
+
"thread.part",
|
|
18
|
+
"thread.llm",
|
|
19
|
+
];
|
|
20
|
+
export const THREAD_STREAM_CHUNK_TYPES = [
|
|
21
|
+
"data-context-id",
|
|
22
|
+
"data-context-substate",
|
|
23
|
+
"data-thread-ping",
|
|
24
|
+
"tool-output-available",
|
|
25
|
+
"tool-output-error",
|
|
26
|
+
"finish",
|
|
27
|
+
];
|
|
28
|
+
export const THREAD_CONTEXT_SUBSTATE_KEYS = ["actions"];
|
|
29
|
+
export const THREAD_THREAD_TRANSITIONS = [
|
|
30
|
+
{ from: "open", to: "streaming" },
|
|
31
|
+
{ from: "streaming", to: "open" },
|
|
32
|
+
{ from: "streaming", to: "closed" },
|
|
33
|
+
{ from: "streaming", to: "failed" },
|
|
34
|
+
{ from: "failed", to: "open" },
|
|
35
|
+
];
|
|
36
|
+
export const THREAD_CONTEXT_TRANSITIONS = [
|
|
37
|
+
{ from: "open", to: "streaming" },
|
|
38
|
+
{ from: "streaming", to: "open" },
|
|
39
|
+
{ from: "open", to: "closed" },
|
|
40
|
+
{ from: "streaming", to: "closed" },
|
|
41
|
+
];
|
|
42
|
+
export const THREAD_EXECUTION_TRANSITIONS = [
|
|
43
|
+
{ from: "executing", to: "completed" },
|
|
44
|
+
{ from: "executing", to: "failed" },
|
|
45
|
+
];
|
|
46
|
+
export const THREAD_STEP_TRANSITIONS = [
|
|
47
|
+
{ from: "running", to: "completed" },
|
|
48
|
+
{ from: "running", to: "failed" },
|
|
49
|
+
];
|
|
50
|
+
export const THREAD_ITEM_TRANSITIONS = [
|
|
51
|
+
{ from: "stored", to: "pending" },
|
|
52
|
+
{ from: "stored", to: "completed" },
|
|
53
|
+
{ from: "pending", to: "completed" },
|
|
54
|
+
];
|
|
55
|
+
function canTransition(transitions, from, to) {
|
|
56
|
+
return transitions.some((transition) => transition.from === from && transition.to === to);
|
|
57
|
+
}
|
|
58
|
+
function assertTransition(transitions, from, to, entity) {
|
|
59
|
+
if (!canTransition(transitions, from, to)) {
|
|
60
|
+
throw new Error(`Invalid ${entity} transition: ${from} -> ${to}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export function canThreadTransition(from, to) {
|
|
64
|
+
return canTransition(THREAD_THREAD_TRANSITIONS, from, to);
|
|
65
|
+
}
|
|
66
|
+
export function canContextTransition(from, to) {
|
|
67
|
+
return canTransition(THREAD_CONTEXT_TRANSITIONS, from, to);
|
|
68
|
+
}
|
|
69
|
+
export function canExecutionTransition(from, to) {
|
|
70
|
+
return canTransition(THREAD_EXECUTION_TRANSITIONS, from, to);
|
|
71
|
+
}
|
|
72
|
+
export function canStepTransition(from, to) {
|
|
73
|
+
return canTransition(THREAD_STEP_TRANSITIONS, from, to);
|
|
74
|
+
}
|
|
75
|
+
export function canItemTransition(from, to) {
|
|
76
|
+
return canTransition(THREAD_ITEM_TRANSITIONS, from, to);
|
|
77
|
+
}
|
|
78
|
+
export function assertThreadTransition(from, to) {
|
|
79
|
+
assertTransition(THREAD_THREAD_TRANSITIONS, from, to, "thread.status");
|
|
80
|
+
}
|
|
81
|
+
export function assertContextTransition(from, to) {
|
|
82
|
+
assertTransition(THREAD_CONTEXT_TRANSITIONS, from, to, "context.status");
|
|
83
|
+
}
|
|
84
|
+
export function assertExecutionTransition(from, to) {
|
|
85
|
+
assertTransition(THREAD_EXECUTION_TRANSITIONS, from, to, "execution.status");
|
|
86
|
+
}
|
|
87
|
+
export function assertStepTransition(from, to) {
|
|
88
|
+
assertTransition(THREAD_STEP_TRANSITIONS, from, to, "step.status");
|
|
89
|
+
}
|
|
90
|
+
export function assertItemTransition(from, to) {
|
|
91
|
+
assertTransition(THREAD_ITEM_TRANSITIONS, from, to, "item.status");
|
|
92
|
+
}
|
|
93
|
+
export function assertThreadPartKey(stepId, idx, key) {
|
|
94
|
+
const expected = `${stepId}:${idx}`;
|
|
95
|
+
if (key !== expected) {
|
|
96
|
+
throw new Error(`Invalid thread_parts.key: expected "${expected}" got "${key}"`);
|
|
97
|
+
}
|
|
98
|
+
}
|
package/dist/thread.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { Thread, type ThreadOptions, type ThreadStreamOptions, type ShouldContinue, type ThreadShouldContinueArgs, } from "./thread.engine.js";
|
|
2
2
|
export { thread, createThread, type ThreadConfig, type ThreadInstance, type RegistrableThreadBuilder, } from "./thread.builder.js";
|
|
3
|
-
export { createAiSdkReactor, type CreateAiSdkReactorOptions, type ThreadReactor, type ThreadReactorParams, type ThreadReactionResult, type ThreadReactionToolCall, type ThreadReactionLLM, } from "./thread.reactor.js";
|
|
3
|
+
export { createAiSdkReactor, createScriptedReactor, type CreateAiSdkReactorOptions, type CreateScriptedReactorOptions, type ScriptedReactorStep, type ThreadReactor, type ThreadReactorParams, type ThreadReactionResult, type ThreadReactionToolCall, type ThreadReactionLLM, } from "./thread.reactor.js";
|
package/dist/thread.engine.d.ts
CHANGED
|
@@ -66,7 +66,7 @@ export interface ThreadStreamOptions {
|
|
|
66
66
|
* - `function`: a function that returns a model instance. For Workflow compatibility, this should
|
|
67
67
|
* be a `"use-step"` function (so it can be serialized by reference).
|
|
68
68
|
*/
|
|
69
|
-
export type ThreadModelInit = string | (() => Promise<any>)
|
|
69
|
+
export type ThreadModelInit = string | (() => Promise<any>);
|
|
70
70
|
export type ThreadReactParams<Env extends ThreadEnvironment = ThreadEnvironment> = {
|
|
71
71
|
env: Env;
|
|
72
72
|
/**
|
package/dist/thread.engine.js
CHANGED
|
@@ -100,6 +100,15 @@ export class Thread {
|
|
|
100
100
|
});
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
|
+
// Reactor/steps always receive a stream argument.
|
|
104
|
+
// In silent mode (or when no workflow writable is available), we use an in-memory sink.
|
|
105
|
+
if (!writable) {
|
|
106
|
+
writable = new WritableStream({
|
|
107
|
+
write() {
|
|
108
|
+
// noop
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
}
|
|
103
112
|
const contextSelector = params.contextIdentifier?.id
|
|
104
113
|
? { id: String(params.contextIdentifier.id) }
|
|
105
114
|
: params.contextIdentifier?.key
|
|
@@ -208,6 +217,13 @@ export class Thread {
|
|
|
208
217
|
// The story exposes a single visible `context_event` per turn (`reactionEventId`) so the UI
|
|
209
218
|
// doesn't render duplicate assistant messages (LLM-step + aggregated reaction).
|
|
210
219
|
const stepParts = (assistantEvent?.content?.parts ?? []);
|
|
220
|
+
const assistantEventEffective = {
|
|
221
|
+
...assistantEvent,
|
|
222
|
+
content: {
|
|
223
|
+
...(assistantEvent?.content ?? {}),
|
|
224
|
+
parts: stepParts,
|
|
225
|
+
},
|
|
226
|
+
};
|
|
211
227
|
await saveThreadPartsStep({
|
|
212
228
|
env: params.env,
|
|
213
229
|
stepId: stepCreate.stepId,
|
|
@@ -219,7 +235,7 @@ export class Thread {
|
|
|
219
235
|
// Persist/append the aggregated reaction event (stable `reactionEventId` for the execution).
|
|
220
236
|
if (!reactionEvent) {
|
|
221
237
|
const reactionPayload = {
|
|
222
|
-
...
|
|
238
|
+
...assistantEventEffective,
|
|
223
239
|
status: "pending",
|
|
224
240
|
};
|
|
225
241
|
reactionEvent = await saveReactionItem(params.env, contextSelector, reactionPayload, {
|
|
@@ -229,21 +245,26 @@ export class Thread {
|
|
|
229
245
|
});
|
|
230
246
|
}
|
|
231
247
|
else {
|
|
232
|
-
|
|
248
|
+
const existingReactionParts = Array.isArray(reactionEvent.content?.parts)
|
|
249
|
+
? reactionEvent.content.parts
|
|
250
|
+
: [];
|
|
251
|
+
const nextAssistantParts = Array.isArray(assistantEventEffective.content?.parts)
|
|
252
|
+
? assistantEventEffective.content.parts
|
|
253
|
+
: [];
|
|
254
|
+
const nextReactionEvent = {
|
|
233
255
|
...reactionEvent,
|
|
234
256
|
content: {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
...(assistantEvent?.content?.parts ?? []),
|
|
238
|
-
],
|
|
257
|
+
...reactionEvent.content,
|
|
258
|
+
parts: [...existingReactionParts, ...nextAssistantParts],
|
|
239
259
|
},
|
|
240
260
|
status: "pending",
|
|
241
|
-
}
|
|
261
|
+
};
|
|
262
|
+
reactionEvent = await updateItem(params.env, reactionEvent.id, nextReactionEvent, { executionId, contextId: String(currentContext.id) });
|
|
242
263
|
}
|
|
243
|
-
story.opts.onEventCreated?.(
|
|
264
|
+
story.opts.onEventCreated?.(assistantEventEffective);
|
|
244
265
|
// Done: no tool calls requested by the model
|
|
245
266
|
if (!toolCalls.length) {
|
|
246
|
-
const endResult = await story.callOnEnd(
|
|
267
|
+
const endResult = await story.callOnEnd(assistantEventEffective);
|
|
247
268
|
if (endResult) {
|
|
248
269
|
// Mark iteration step completed (no tools)
|
|
249
270
|
await updateThreadStep({
|
|
@@ -261,7 +282,7 @@ export class Thread {
|
|
|
261
282
|
});
|
|
262
283
|
// Mark reaction event completed
|
|
263
284
|
await updateItem(params.env, reactionEventId, {
|
|
264
|
-
...reactionEvent,
|
|
285
|
+
...(reactionEvent ?? assistantEventEffective),
|
|
265
286
|
status: "completed",
|
|
266
287
|
}, { executionId, contextId: String(currentContext.id) });
|
|
267
288
|
await completeExecution(params.env, contextSelector, executionId, "completed");
|
|
@@ -359,7 +380,9 @@ export class Thread {
|
|
|
359
380
|
}
|
|
360
381
|
// Merge tool results into persisted parts (so next LLM call can see them)
|
|
361
382
|
if (reactionEvent) {
|
|
362
|
-
let parts = reactionEvent
|
|
383
|
+
let parts = Array.isArray(reactionEvent.content?.parts)
|
|
384
|
+
? [...reactionEvent.content.parts]
|
|
385
|
+
: [];
|
|
363
386
|
for (const r of executionResults) {
|
|
364
387
|
parts = applyToolExecutionResultToParts(parts, r.tc, {
|
|
365
388
|
success: Boolean(r.success),
|
|
@@ -367,11 +390,15 @@ export class Thread {
|
|
|
367
390
|
message: r.errorText,
|
|
368
391
|
});
|
|
369
392
|
}
|
|
370
|
-
|
|
393
|
+
const nextReactionEvent = {
|
|
371
394
|
...reactionEvent,
|
|
372
|
-
content: {
|
|
395
|
+
content: {
|
|
396
|
+
...reactionEvent.content,
|
|
397
|
+
parts,
|
|
398
|
+
},
|
|
373
399
|
status: "pending",
|
|
374
|
-
}
|
|
400
|
+
};
|
|
401
|
+
reactionEvent = await updateItem(params.env, reactionEventId, nextReactionEvent, { executionId, contextId: String(currentContext.id) });
|
|
375
402
|
}
|
|
376
403
|
// Callback for observability/integration
|
|
377
404
|
for (const r of executionResults) {
|
|
@@ -390,8 +417,8 @@ export class Thread {
|
|
|
390
417
|
const continueLoop = await story.shouldContinue({
|
|
391
418
|
env: params.env,
|
|
392
419
|
context: updatedContext,
|
|
393
|
-
reactionEvent: reactionEvent ??
|
|
394
|
-
assistantEvent,
|
|
420
|
+
reactionEvent: reactionEvent ?? assistantEventEffective,
|
|
421
|
+
assistantEvent: assistantEventEffective,
|
|
395
422
|
toolCalls,
|
|
396
423
|
toolExecutionResults: executionResults,
|
|
397
424
|
});
|
|
@@ -411,7 +438,7 @@ export class Thread {
|
|
|
411
438
|
});
|
|
412
439
|
if (continueLoop === false) {
|
|
413
440
|
await updateItem(params.env, reactionEventId, {
|
|
414
|
-
...reactionEvent,
|
|
441
|
+
...(reactionEvent ?? assistantEventEffective),
|
|
415
442
|
status: "completed",
|
|
416
443
|
}, { executionId, contextId: String(currentContext.id) });
|
|
417
444
|
await completeExecution(params.env, contextSelector, executionId, "completed");
|
package/dist/thread.events.js
CHANGED
|
@@ -46,10 +46,13 @@ export function convertToUIMessage(item) {
|
|
|
46
46
|
else {
|
|
47
47
|
role = "assistant";
|
|
48
48
|
}
|
|
49
|
+
const parts = Array.isArray(item.content.parts)
|
|
50
|
+
? item.content.parts
|
|
51
|
+
: [];
|
|
49
52
|
return {
|
|
50
53
|
id: item.id,
|
|
51
54
|
role: role,
|
|
52
|
-
parts
|
|
55
|
+
parts,
|
|
53
56
|
metadata: {
|
|
54
57
|
channel: item.channel,
|
|
55
58
|
type: item.type,
|
|
@@ -76,6 +79,18 @@ export async function convertItemToModelMessages(item) {
|
|
|
76
79
|
const message = convertToUIMessage(item);
|
|
77
80
|
return convertToModelMessages([message]);
|
|
78
81
|
}
|
|
82
|
+
function normalizeModelMessageContentToParts(content) {
|
|
83
|
+
if (Array.isArray(content))
|
|
84
|
+
return content;
|
|
85
|
+
if (typeof content === "string") {
|
|
86
|
+
if (!content.trim())
|
|
87
|
+
return [];
|
|
88
|
+
return [{ type: "text", text: content }];
|
|
89
|
+
}
|
|
90
|
+
if (content === null || content === undefined)
|
|
91
|
+
return [];
|
|
92
|
+
return [content];
|
|
93
|
+
}
|
|
79
94
|
export function convertModelMessageToItem(itemId, message) {
|
|
80
95
|
let type;
|
|
81
96
|
switch (message.message.role) {
|
|
@@ -98,7 +113,7 @@ export function convertModelMessageToItem(itemId, message) {
|
|
|
98
113
|
type: type,
|
|
99
114
|
channel: WEB_CHANNEL,
|
|
100
115
|
content: {
|
|
101
|
-
parts: message.message.content,
|
|
116
|
+
parts: normalizeModelMessageContentToParts(message.message.content),
|
|
102
117
|
},
|
|
103
118
|
createdAt: message.timestamp.toISOString(),
|
|
104
119
|
};
|
package/dist/thread.js
CHANGED
package/dist/thread.reactor.d.ts
CHANGED
|
@@ -1,82 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import type { ContextIdentifier, StoredContext, ThreadItem } from "./thread.store.js";
|
|
5
|
-
import type { SerializableToolForModel } from "./tools-to-model-tools.js";
|
|
6
|
-
export type ThreadReactionToolCall = {
|
|
7
|
-
toolCallId: string;
|
|
8
|
-
toolName: string;
|
|
9
|
-
args: unknown;
|
|
10
|
-
};
|
|
11
|
-
export type ThreadReactionLLM = {
|
|
12
|
-
provider?: string;
|
|
13
|
-
model?: string;
|
|
14
|
-
promptTokens?: number;
|
|
15
|
-
promptTokensCached?: number;
|
|
16
|
-
promptTokensUncached?: number;
|
|
17
|
-
completionTokens?: number;
|
|
18
|
-
totalTokens?: number;
|
|
19
|
-
latencyMs?: number;
|
|
20
|
-
rawUsage?: unknown;
|
|
21
|
-
rawProviderMetadata?: unknown;
|
|
22
|
-
};
|
|
23
|
-
export type ThreadReactionResult = {
|
|
24
|
-
assistantEvent: ThreadItem;
|
|
25
|
-
toolCalls: ThreadReactionToolCall[];
|
|
26
|
-
messagesForModel: ModelMessage[];
|
|
27
|
-
llm?: ThreadReactionLLM;
|
|
28
|
-
};
|
|
29
|
-
export type ThreadReactorParams<Context = unknown, Env extends ThreadEnvironment = ThreadEnvironment> = {
|
|
30
|
-
env: Env;
|
|
31
|
-
context: StoredContext<Context>;
|
|
32
|
-
contextIdentifier: ContextIdentifier;
|
|
33
|
-
triggerEvent: ThreadItem;
|
|
34
|
-
model: ThreadModelInit;
|
|
35
|
-
systemPrompt: string;
|
|
36
|
-
actions: Record<string, unknown>;
|
|
37
|
-
toolsForModel: Record<string, SerializableToolForModel>;
|
|
38
|
-
eventId: string;
|
|
39
|
-
executionId: string;
|
|
40
|
-
contextId: string;
|
|
41
|
-
stepId: string;
|
|
42
|
-
iteration: number;
|
|
43
|
-
maxModelSteps: number;
|
|
44
|
-
sendStart: boolean;
|
|
45
|
-
silent: boolean;
|
|
46
|
-
writable?: WritableStream<UIMessageChunk>;
|
|
47
|
-
};
|
|
48
|
-
export type ThreadReactor<Context = unknown, Env extends ThreadEnvironment = ThreadEnvironment> = (params: ThreadReactorParams<Context, Env>) => Promise<ThreadReactionResult>;
|
|
49
|
-
export type CreateAiSdkReactorOptions<Context = unknown, Env extends ThreadEnvironment = ThreadEnvironment, Config = unknown> = {
|
|
50
|
-
resolveConfig?: (params: {
|
|
51
|
-
env: Env;
|
|
52
|
-
context: StoredContext<Context>;
|
|
53
|
-
contextIdentifier: ContextIdentifier;
|
|
54
|
-
triggerEvent: ThreadItem;
|
|
55
|
-
model: ThreadModelInit;
|
|
56
|
-
eventId: string;
|
|
57
|
-
executionId: string;
|
|
58
|
-
contextId: string;
|
|
59
|
-
stepId: string;
|
|
60
|
-
iteration: number;
|
|
61
|
-
}) => Promise<Config> | Config;
|
|
62
|
-
selectModel?: (params: {
|
|
63
|
-
env: Env;
|
|
64
|
-
context: StoredContext<Context>;
|
|
65
|
-
triggerEvent: ThreadItem;
|
|
66
|
-
baseModel: ThreadModelInit;
|
|
67
|
-
config: Config;
|
|
68
|
-
}) => Promise<ThreadModelInit> | ThreadModelInit;
|
|
69
|
-
selectMaxModelSteps?: (params: {
|
|
70
|
-
env: Env;
|
|
71
|
-
context: StoredContext<Context>;
|
|
72
|
-
triggerEvent: ThreadItem;
|
|
73
|
-
baseMaxModelSteps: number;
|
|
74
|
-
config: Config;
|
|
75
|
-
}) => Promise<number> | number;
|
|
76
|
-
};
|
|
77
|
-
/**
|
|
78
|
-
* Default reactor for Thread: Vercel AI SDK (`streamText`) with tool-call extraction.
|
|
79
|
-
*
|
|
80
|
-
* This keeps current behavior and can be replaced per-thread using `.reactor(...)`.
|
|
81
|
-
*/
|
|
82
|
-
export declare function createAiSdkReactor<Context = unknown, Env extends ThreadEnvironment = ThreadEnvironment, Config = unknown>(options?: CreateAiSdkReactorOptions<Context, Env, Config>): ThreadReactor<Context, Env>;
|
|
1
|
+
export { createAiSdkReactor, type CreateAiSdkReactorOptions, } from "./reactors/ai-sdk.reactor.js";
|
|
2
|
+
export { createScriptedReactor, type CreateScriptedReactorOptions, type ScriptedReactorStep, } from "./reactors/scripted.reactor.js";
|
|
3
|
+
export type { ThreadReactor, ThreadReactorParams, ThreadReactionResult, ThreadReactionToolCall, ThreadReactionLLM, } from "./reactors/types.js";
|
package/dist/thread.reactor.js
CHANGED
|
@@ -1,65 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* Default reactor for Thread: Vercel AI SDK (`streamText`) with tool-call extraction.
|
|
4
|
-
*
|
|
5
|
-
* This keeps current behavior and can be replaced per-thread using `.reactor(...)`.
|
|
6
|
-
*/
|
|
7
|
-
export function createAiSdkReactor(options) {
|
|
8
|
-
return async (params) => {
|
|
9
|
-
let config;
|
|
10
|
-
if (options?.resolveConfig) {
|
|
11
|
-
config = await options.resolveConfig({
|
|
12
|
-
env: params.env,
|
|
13
|
-
context: params.context,
|
|
14
|
-
contextIdentifier: params.contextIdentifier,
|
|
15
|
-
triggerEvent: params.triggerEvent,
|
|
16
|
-
model: params.model,
|
|
17
|
-
eventId: params.eventId,
|
|
18
|
-
executionId: params.executionId,
|
|
19
|
-
contextId: params.contextId,
|
|
20
|
-
stepId: params.stepId,
|
|
21
|
-
iteration: params.iteration,
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
const model = options?.selectModel && config !== undefined
|
|
25
|
-
? await options.selectModel({
|
|
26
|
-
env: params.env,
|
|
27
|
-
context: params.context,
|
|
28
|
-
triggerEvent: params.triggerEvent,
|
|
29
|
-
baseModel: params.model,
|
|
30
|
-
config,
|
|
31
|
-
})
|
|
32
|
-
: params.model;
|
|
33
|
-
const maxSteps = options?.selectMaxModelSteps && config !== undefined
|
|
34
|
-
? await options.selectMaxModelSteps({
|
|
35
|
-
env: params.env,
|
|
36
|
-
context: params.context,
|
|
37
|
-
triggerEvent: params.triggerEvent,
|
|
38
|
-
baseMaxModelSteps: params.maxModelSteps,
|
|
39
|
-
config,
|
|
40
|
-
})
|
|
41
|
-
: params.maxModelSteps;
|
|
42
|
-
const result = await executeReaction({
|
|
43
|
-
env: params.env,
|
|
44
|
-
contextIdentifier: params.contextIdentifier,
|
|
45
|
-
model,
|
|
46
|
-
system: params.systemPrompt,
|
|
47
|
-
tools: params.toolsForModel,
|
|
48
|
-
eventId: params.eventId,
|
|
49
|
-
iteration: params.iteration,
|
|
50
|
-
maxSteps,
|
|
51
|
-
sendStart: params.sendStart,
|
|
52
|
-
silent: params.silent,
|
|
53
|
-
writable: params.writable,
|
|
54
|
-
executionId: params.executionId,
|
|
55
|
-
contextId: params.contextId,
|
|
56
|
-
stepId: params.stepId,
|
|
57
|
-
});
|
|
58
|
-
return {
|
|
59
|
-
assistantEvent: result.assistantEvent,
|
|
60
|
-
toolCalls: result.toolCalls,
|
|
61
|
-
messagesForModel: result.messagesForModel,
|
|
62
|
-
llm: result.llm,
|
|
63
|
-
};
|
|
64
|
-
};
|
|
65
|
-
}
|
|
1
|
+
export { createAiSdkReactor, } from "./reactors/ai-sdk.reactor.js";
|
|
2
|
+
export { createScriptedReactor, } from "./reactors/scripted.reactor.js";
|
package/dist/thread.store.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ModelMessage } from "ai";
|
|
2
|
+
import type { ThreadThreadStatus, ThreadContextStatus, ThreadExecutionStatus, ThreadStepStatus as ContractThreadStepStatus, ThreadItemStatus, ThreadItemType, ThreadChannel } from "./thread.contract.js";
|
|
2
3
|
/**
|
|
3
4
|
* ## thread.store.ts
|
|
4
5
|
*
|
|
@@ -18,8 +19,8 @@ export type ThreadIdentifier = {
|
|
|
18
19
|
id?: never;
|
|
19
20
|
};
|
|
20
21
|
export type ContextIdentifier = ThreadIdentifier;
|
|
21
|
-
export type ThreadStatus =
|
|
22
|
-
export type ContextStatus =
|
|
22
|
+
export type ThreadStatus = ThreadThreadStatus;
|
|
23
|
+
export type ContextStatus = ThreadContextStatus;
|
|
23
24
|
export type StoredThread = {
|
|
24
25
|
id: string;
|
|
25
26
|
key: string | null;
|
|
@@ -39,14 +40,17 @@ export type StoredContext<Context> = {
|
|
|
39
40
|
};
|
|
40
41
|
export type ThreadItem = {
|
|
41
42
|
id: string;
|
|
42
|
-
type:
|
|
43
|
-
channel:
|
|
43
|
+
type: ThreadItemType;
|
|
44
|
+
channel: ThreadChannel;
|
|
44
45
|
createdAt: string;
|
|
45
|
-
status?:
|
|
46
|
-
content:
|
|
46
|
+
status?: ThreadItemStatus;
|
|
47
|
+
content: {
|
|
48
|
+
parts?: unknown[];
|
|
49
|
+
[key: string]: unknown;
|
|
50
|
+
};
|
|
47
51
|
};
|
|
48
|
-
export type ExecutionStatus =
|
|
49
|
-
export type ThreadStepStatus =
|
|
52
|
+
export type ExecutionStatus = ThreadExecutionStatus;
|
|
53
|
+
export type ThreadStepStatus = ContractThreadStepStatus;
|
|
50
54
|
export type ThreadStep = {
|
|
51
55
|
id: string;
|
|
52
56
|
createdAt: Date;
|