@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.
@@ -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 (typeof config.model === "function")
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";
@@ -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>) | any;
69
+ export type ThreadModelInit = string | (() => Promise<any>);
70
70
  export type ThreadReactParams<Env extends ThreadEnvironment = ThreadEnvironment> = {
71
71
  env: Env;
72
72
  /**
@@ -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
- ...assistantEvent,
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
- reactionEvent = await updateItem(params.env, reactionEvent.id, {
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
- parts: [
236
- ...(reactionEvent?.content?.parts ?? []),
237
- ...(assistantEvent?.content?.parts ?? []),
238
- ],
257
+ ...reactionEvent.content,
258
+ parts: [...existingReactionParts, ...nextAssistantParts],
239
259
  },
240
260
  status: "pending",
241
- }, { executionId, contextId: String(currentContext.id) });
261
+ };
262
+ reactionEvent = await updateItem(params.env, reactionEvent.id, nextReactionEvent, { executionId, contextId: String(currentContext.id) });
242
263
  }
243
- story.opts.onEventCreated?.(assistantEvent);
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(assistantEvent);
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?.content?.parts ?? [];
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
- reactionEvent = await updateItem(params.env, reactionEventId, {
393
+ const nextReactionEvent = {
371
394
  ...reactionEvent,
372
- content: { parts },
395
+ content: {
396
+ ...reactionEvent.content,
397
+ parts,
398
+ },
373
399
  status: "pending",
374
- }, { executionId, contextId: String(currentContext.id) });
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 ?? assistantEvent,
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");
@@ -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: item.content.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
@@ -4,4 +4,4 @@ Thread, } from "./thread.engine.js";
4
4
  export {
5
5
  // builder
6
6
  thread, createThread, } from "./thread.builder.js";
7
- export { createAiSdkReactor, } from "./thread.reactor.js";
7
+ export { createAiSdkReactor, createScriptedReactor, } from "./thread.reactor.js";
@@ -1,82 +1,3 @@
1
- import type { ModelMessage, UIMessageChunk } from "ai";
2
- import type { ThreadEnvironment } from "./thread.config.js";
3
- import type { ThreadModelInit } from "./thread.engine.js";
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";
@@ -1,65 +1,2 @@
1
- import { executeReaction } from "./steps/reaction.steps.js";
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";
@@ -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 = "open" | "streaming" | "closed" | "failed";
22
- export type ContextStatus = "open" | "streaming" | "closed";
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: string;
43
- channel: string;
43
+ type: ThreadItemType;
44
+ channel: ThreadChannel;
44
45
  createdAt: string;
45
- status?: string;
46
- content: any;
46
+ status?: ThreadItemStatus;
47
+ content: {
48
+ parts?: unknown[];
49
+ [key: string]: unknown;
50
+ };
47
51
  };
48
- export type ExecutionStatus = "executing" | "completed" | "failed";
49
- export type ThreadStepStatus = "running" | "completed" | "failed";
52
+ export type ExecutionStatus = ThreadExecutionStatus;
53
+ export type ThreadStepStatus = ContractThreadStepStatus;
50
54
  export type ThreadStep = {
51
55
  id: string;
52
56
  createdAt: Date;