@ekairos/thread 1.22.4-beta.feature-thread-unify.0 → 1.22.4-beta.feature-core-thread-registry-sync.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.
Files changed (37) hide show
  1. package/README.md +7 -1
  2. package/dist/index.d.ts +5 -5
  3. package/dist/index.js +2 -2
  4. package/dist/react.d.ts +2 -18
  5. package/dist/react.js +2 -15
  6. package/dist/reactors/ai-sdk.chunk-map.d.ts +12 -0
  7. package/dist/reactors/ai-sdk.chunk-map.js +143 -0
  8. package/dist/reactors/ai-sdk.reactor.js +5 -1
  9. package/dist/reactors/scripted.reactor.d.ts +2 -2
  10. package/dist/reactors/scripted.reactor.js +3 -2
  11. package/dist/reactors/types.d.ts +6 -6
  12. package/dist/schema.js +10 -9
  13. package/dist/steps/do-thread-stream-step.d.ts +6 -2
  14. package/dist/steps/do-thread-stream-step.js +9 -5
  15. package/dist/steps/reaction.steps.d.ts +1 -1
  16. package/dist/steps/reaction.steps.js +48 -14
  17. package/dist/steps/store.steps.d.ts +10 -11
  18. package/dist/steps/store.steps.js +34 -77
  19. package/dist/steps/stream.steps.d.ts +3 -33
  20. package/dist/steps/stream.steps.js +7 -68
  21. package/dist/steps/trace.steps.js +1 -1
  22. package/dist/stores/instant.documents.d.ts +1 -1
  23. package/dist/stores/instant.documents.js +1 -1
  24. package/dist/stores/instant.store.d.ts +7 -3
  25. package/dist/stores/instant.store.js +32 -86
  26. package/dist/thread.contract.d.ts +16 -8
  27. package/dist/thread.contract.js +61 -19
  28. package/dist/thread.d.ts +1 -1
  29. package/dist/thread.engine.d.ts +13 -9
  30. package/dist/thread.engine.js +463 -84
  31. package/dist/thread.events.d.ts +3 -3
  32. package/dist/thread.events.js +11 -34
  33. package/dist/thread.reactor.d.ts +1 -1
  34. package/dist/thread.store.d.ts +9 -9
  35. package/dist/thread.stream.d.ts +100 -33
  36. package/dist/thread.stream.js +72 -63
  37. package/package.json +3 -2
@@ -1,8 +1,8 @@
1
1
  import { type ModelMessage, type UIMessage } from "ai";
2
2
  import type { ThreadItem } from "./thread.store.js";
3
- export declare const INPUT_TEXT_ITEM_TYPE = "input_text";
4
- export declare const OUTPUT_TEXT_ITEM_TYPE = "output_text";
5
- export declare const SYSTEM_TEXT_ITEM_TYPE = "ekairos:system";
3
+ export declare const INPUT_ITEM_TYPE = "input";
4
+ export declare const OUTPUT_ITEM_TYPE = "output";
5
+ export declare const INPUT_TEXT_ITEM_TYPE = "input";
6
6
  export declare const WEB_CHANNEL = "web";
7
7
  export declare const AGENT_CHANNEL = "whatsapp";
8
8
  export declare const EMAIL_CHANNEL = "email";
@@ -1,7 +1,7 @@
1
1
  import { convertToModelMessages } from "ai";
2
- export const INPUT_TEXT_ITEM_TYPE = "input_text";
3
- export const OUTPUT_TEXT_ITEM_TYPE = "output_text";
4
- export const SYSTEM_TEXT_ITEM_TYPE = "ekairos:system";
2
+ export const INPUT_ITEM_TYPE = "input";
3
+ export const OUTPUT_ITEM_TYPE = "output";
4
+ export const INPUT_TEXT_ITEM_TYPE = INPUT_ITEM_TYPE;
5
5
  export const WEB_CHANNEL = "web";
6
6
  export const AGENT_CHANNEL = "whatsapp";
7
7
  export const EMAIL_CHANNEL = "email";
@@ -12,7 +12,7 @@ export function createUserItemFromUIMessages(messages) {
12
12
  const lastMessage = messages[messages.length - 1];
13
13
  return {
14
14
  id: lastMessage.id,
15
- type: INPUT_TEXT_ITEM_TYPE,
15
+ type: INPUT_ITEM_TYPE,
16
16
  channel: WEB_CHANNEL,
17
17
  content: {
18
18
  parts: lastMessage.parts,
@@ -27,7 +27,7 @@ export function createAssistantItemFromUIMessages(itemId, messages) {
27
27
  const lastMessage = messages[messages.length - 1];
28
28
  return {
29
29
  id: itemId,
30
- type: OUTPUT_TEXT_ITEM_TYPE,
30
+ type: OUTPUT_ITEM_TYPE,
31
31
  channel: WEB_CHANNEL,
32
32
  content: {
33
33
  parts: lastMessage.parts,
@@ -36,28 +36,19 @@ export function createAssistantItemFromUIMessages(itemId, messages) {
36
36
  };
37
37
  }
38
38
  export function convertToUIMessage(item) {
39
- let role;
40
- if (item.type === INPUT_TEXT_ITEM_TYPE) {
41
- role = "user";
42
- }
43
- else if (item.type === SYSTEM_TEXT_ITEM_TYPE) {
44
- role = "system";
45
- }
46
- else {
47
- role = "assistant";
48
- }
39
+ const role = item.type === INPUT_ITEM_TYPE ? "user" : "assistant";
49
40
  const parts = Array.isArray(item.content.parts)
50
41
  ? item.content.parts
51
42
  : [];
52
43
  return {
53
44
  id: item.id,
54
- role: role,
45
+ role,
55
46
  parts,
56
47
  metadata: {
57
48
  channel: item.channel,
58
49
  type: item.type,
59
50
  createdAt: item.createdAt,
60
- }
51
+ },
61
52
  };
62
53
  }
63
54
  /**
@@ -92,25 +83,11 @@ function normalizeModelMessageContentToParts(content) {
92
83
  return [content];
93
84
  }
94
85
  export function convertModelMessageToItem(itemId, message) {
95
- let type;
96
- switch (message.message.role) {
97
- case "user":
98
- type = INPUT_TEXT_ITEM_TYPE;
99
- break;
100
- case "assistant":
101
- type = OUTPUT_TEXT_ITEM_TYPE;
102
- break;
103
- case "system":
104
- type = SYSTEM_TEXT_ITEM_TYPE;
105
- break;
106
- default:
107
- // Fallback for roles not mapped to our item types (e.g. tool).
108
- type = OUTPUT_TEXT_ITEM_TYPE;
109
- break;
110
- }
86
+ const role = message.message.role;
87
+ const type = role === "user" ? INPUT_ITEM_TYPE : OUTPUT_ITEM_TYPE;
111
88
  return {
112
89
  id: itemId,
113
- type: type,
90
+ type,
114
91
  channel: WEB_CHANNEL,
115
92
  content: {
116
93
  parts: normalizeModelMessageContentToParts(message.message.content),
@@ -1,3 +1,3 @@
1
1
  export { createAiSdkReactor, type CreateAiSdkReactorOptions, } from "./reactors/ai-sdk.reactor.js";
2
2
  export { createScriptedReactor, type CreateScriptedReactorOptions, type ScriptedReactorStep, } from "./reactors/scripted.reactor.js";
3
- export type { ThreadReactor, ThreadReactorParams, ThreadReactionResult, ThreadReactionToolCall, ThreadReactionLLM, } from "./reactors/types.js";
3
+ export type { ThreadReactor, ThreadReactorParams, ThreadReactionResult, ThreadActionRequest, ThreadReactionLLM, } from "./reactors/types.js";
@@ -1,5 +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
+ import type { ThreadThreadStatus, ThreadContextStatus, ThreadExecutionStatus, ThreadStepStatus as ContractThreadStepStatus, ThreadStepKind, ThreadItemStatus, ThreadItemType, ThreadChannel } from "./thread.contract.js";
3
3
  /**
4
4
  * ## thread.store.ts
5
5
  *
@@ -57,12 +57,13 @@ export type ThreadStep = {
57
57
  updatedAt?: Date;
58
58
  status: ThreadStepStatus;
59
59
  iteration: number;
60
- executionId: string;
61
- triggerEventId?: string;
62
- reactionEventId?: string;
63
- eventId: string;
64
- toolCalls?: any;
65
- toolExecutionResults?: any;
60
+ kind?: ThreadStepKind;
61
+ actionName?: string;
62
+ actionInput?: unknown;
63
+ actionOutput?: unknown;
64
+ actionError?: string;
65
+ actionRequests?: any;
66
+ actionResults?: any;
66
67
  continueLoop?: boolean;
67
68
  errorText?: string;
68
69
  };
@@ -92,12 +93,11 @@ export interface ThreadStore {
92
93
  iteration: number;
93
94
  }): Promise<{
94
95
  id: string;
95
- eventId: string;
96
96
  }>;
97
97
  /**
98
98
  * Updates a persisted thread step with completion metadata (tools, errors, continue signal, etc).
99
99
  */
100
- updateStep(stepId: string, patch: Partial<Pick<ThreadStep, "status" | "toolCalls" | "toolExecutionResults" | "continueLoop" | "errorText" | "updatedAt">>): Promise<void>;
100
+ updateStep(stepId: string, patch: Partial<Pick<ThreadStep, "status" | "kind" | "actionName" | "actionInput" | "actionOutput" | "actionError" | "actionRequests" | "actionResults" | "continueLoop" | "errorText" | "updatedAt">>): Promise<void>;
101
101
  /**
102
102
  * Persists normalized parts for a given step (parts-first).
103
103
  * The item keeps `content.parts` for back-compat, but the source-of-truth can be `thread_parts`.
@@ -1,4 +1,4 @@
1
- import { type ThreadContextStatus, type ThreadExecutionStatus, type ThreadItemStatus, type ThreadStepStatus, type ThreadStreamChunkType, type ThreadThreadStatus } from "./thread.contract.js";
1
+ import type { ThreadContextStatus, ThreadItemStatus, ThreadItemType, ThreadStepKind, ThreadStepStatus, ThreadStreamChunkType, ThreadThreadStatus } from "./thread.contract.js";
2
2
  type IsoDateString = string;
3
3
  type ThreadStreamEventBase = {
4
4
  type: string;
@@ -16,12 +16,22 @@ export type ContextResolvedEvent = ThreadStreamEventBase & {
16
16
  threadId: string;
17
17
  status: ThreadContextStatus;
18
18
  };
19
- export type ContextStatusChangedEvent = ThreadStreamEventBase & {
20
- type: "context.status.changed";
19
+ export type ContextOpenedEvent = ThreadStreamEventBase & {
20
+ type: "context.opened";
21
+ contextId: string;
22
+ threadId: string;
23
+ status: "open";
24
+ };
25
+ export type ContextClosedEvent = ThreadStreamEventBase & {
26
+ type: "context.closed";
27
+ contextId: string;
28
+ threadId: string;
29
+ status: "closed";
30
+ };
31
+ export type ContextContentUpdatedEvent = ThreadStreamEventBase & {
32
+ type: "context.content_updated";
21
33
  contextId: string;
22
34
  threadId: string;
23
- from: ThreadContextStatus;
24
- to: ThreadContextStatus;
25
35
  };
26
36
  export type ThreadCreatedEvent = ThreadStreamEventBase & {
27
37
  type: "thread.created";
@@ -33,33 +43,36 @@ export type ThreadResolvedEvent = ThreadStreamEventBase & {
33
43
  threadId: string;
34
44
  status: ThreadThreadStatus;
35
45
  };
36
- export type ThreadStatusChangedEvent = ThreadStreamEventBase & {
37
- type: "thread.status.changed";
46
+ export type ThreadStreamingStartedEvent = ThreadStreamEventBase & {
47
+ type: "thread.streaming_started";
48
+ threadId: string;
49
+ status: "streaming";
50
+ };
51
+ export type ThreadIdleEvent = ThreadStreamEventBase & {
52
+ type: "thread.idle";
38
53
  threadId: string;
39
- from: ThreadThreadStatus;
40
- to: ThreadThreadStatus;
54
+ status: "idle";
41
55
  };
42
56
  export type ExecutionCreatedEvent = ThreadStreamEventBase & {
43
57
  type: "execution.created";
44
58
  executionId: string;
45
59
  contextId: string;
46
60
  threadId: string;
47
- status: ThreadExecutionStatus;
61
+ status: "executing";
48
62
  };
49
- export type ExecutionStatusChangedEvent = ThreadStreamEventBase & {
50
- type: "execution.status.changed";
63
+ export type ExecutionCompletedEvent = ThreadStreamEventBase & {
64
+ type: "execution.completed";
51
65
  executionId: string;
52
66
  contextId: string;
53
67
  threadId: string;
54
- from: ThreadExecutionStatus;
55
- to: ThreadExecutionStatus;
68
+ status: "completed";
56
69
  };
57
- export type ThreadFinishedEvent = ThreadStreamEventBase & {
58
- type: "thread.finished";
59
- threadId: string;
60
- contextId: string;
70
+ export type ExecutionFailedEvent = ThreadStreamEventBase & {
71
+ type: "execution.failed";
61
72
  executionId: string;
62
- result: "completed" | "failed";
73
+ contextId: string;
74
+ threadId: string;
75
+ status: "failed";
63
76
  };
64
77
  export type ItemCreatedEvent = ThreadStreamEventBase & {
65
78
  type: "item.created";
@@ -68,41 +81,82 @@ export type ItemCreatedEvent = ThreadStreamEventBase & {
68
81
  threadId: string;
69
82
  executionId?: string;
70
83
  status: ThreadItemStatus;
84
+ itemType?: ThreadItemType;
71
85
  };
72
- export type ItemStatusChangedEvent = ThreadStreamEventBase & {
73
- type: "item.status.changed";
86
+ export type ItemUpdatedEvent = ThreadStreamEventBase & {
87
+ type: "item.updated";
74
88
  itemId: string;
89
+ contextId: string;
90
+ threadId: string;
75
91
  executionId?: string;
76
- from: ThreadItemStatus;
77
- to: ThreadItemStatus;
92
+ status?: ThreadItemStatus;
93
+ };
94
+ export type ItemPendingEvent = ThreadStreamEventBase & {
95
+ type: "item.pending";
96
+ itemId: string;
97
+ contextId: string;
98
+ threadId: string;
99
+ executionId?: string;
100
+ status: "pending";
101
+ };
102
+ export type ItemCompletedEvent = ThreadStreamEventBase & {
103
+ type: "item.completed";
104
+ itemId: string;
105
+ contextId: string;
106
+ threadId: string;
107
+ executionId?: string;
108
+ status: "completed";
78
109
  };
79
110
  export type StepCreatedEvent = ThreadStreamEventBase & {
80
111
  type: "step.created";
81
112
  stepId: string;
82
113
  executionId: string;
83
114
  iteration: number;
84
- status: ThreadStepStatus;
115
+ status: "running";
85
116
  };
86
- export type StepStatusChangedEvent = ThreadStreamEventBase & {
87
- type: "step.status.changed";
117
+ export type StepUpdatedEvent = ThreadStreamEventBase & {
118
+ type: "step.updated";
88
119
  stepId: string;
89
120
  executionId: string;
90
- from: ThreadStepStatus;
91
- to: ThreadStepStatus;
121
+ iteration?: number;
122
+ status?: ThreadStepStatus;
123
+ kind?: ThreadStepKind;
124
+ actionName?: string;
125
+ };
126
+ export type StepCompletedEvent = ThreadStreamEventBase & {
127
+ type: "step.completed";
128
+ stepId: string;
129
+ executionId: string;
130
+ iteration?: number;
131
+ status: "completed";
132
+ };
133
+ export type StepFailedEvent = ThreadStreamEventBase & {
134
+ type: "step.failed";
135
+ stepId: string;
136
+ executionId: string;
137
+ iteration?: number;
138
+ status: "failed";
139
+ errorText?: string;
92
140
  };
93
141
  export type PartCreatedEvent = ThreadStreamEventBase & {
94
142
  type: "part.created";
95
143
  partKey: string;
96
144
  stepId: string;
97
145
  idx: number;
98
- part?: unknown;
146
+ partType?: string;
147
+ partPreview?: string;
148
+ partState?: string;
149
+ partToolCallId?: string;
99
150
  };
100
151
  export type PartUpdatedEvent = ThreadStreamEventBase & {
101
152
  type: "part.updated";
102
153
  partKey: string;
103
154
  stepId: string;
104
155
  idx: number;
105
- part?: unknown;
156
+ partType?: string;
157
+ partPreview?: string;
158
+ partState?: string;
159
+ partToolCallId?: string;
106
160
  };
107
161
  export type ChunkEmittedEvent = ThreadStreamEventBase & {
108
162
  type: "chunk.emitted";
@@ -110,10 +164,23 @@ export type ChunkEmittedEvent = ThreadStreamEventBase & {
110
164
  contextId: string;
111
165
  executionId?: string;
112
166
  stepId?: string;
167
+ itemId?: string;
168
+ partKey?: string;
169
+ actionRef?: string;
170
+ provider?: string;
171
+ providerChunkType?: string;
172
+ sequence: number;
113
173
  data?: unknown;
114
- };
115
- export type ThreadStreamEvent = ContextCreatedEvent | ContextResolvedEvent | ContextStatusChangedEvent | ThreadCreatedEvent | ThreadResolvedEvent | ThreadStatusChangedEvent | ExecutionCreatedEvent | ExecutionStatusChangedEvent | ThreadFinishedEvent | ItemCreatedEvent | ItemStatusChangedEvent | StepCreatedEvent | StepStatusChangedEvent | PartCreatedEvent | PartUpdatedEvent | ChunkEmittedEvent;
174
+ raw?: unknown;
175
+ };
176
+ export type ContextEvent = ContextCreatedEvent | ContextResolvedEvent | ContextOpenedEvent | ContextClosedEvent | ContextContentUpdatedEvent;
177
+ export type ThreadEvent = ThreadCreatedEvent | ThreadResolvedEvent | ThreadStreamingStartedEvent | ThreadIdleEvent;
178
+ export type ExecutionEvent = ExecutionCreatedEvent | ExecutionCompletedEvent | ExecutionFailedEvent;
179
+ export type ItemEvent = ItemCreatedEvent | ItemUpdatedEvent | ItemPendingEvent | ItemCompletedEvent;
180
+ export type StepEvent = StepCreatedEvent | StepUpdatedEvent | StepCompletedEvent | StepFailedEvent;
181
+ export type PartEvent = PartCreatedEvent | PartUpdatedEvent;
182
+ export type ThreadStreamEvent = ContextEvent | ThreadEvent | ExecutionEvent | ItemEvent | StepEvent | PartEvent | ChunkEmittedEvent;
116
183
  export declare function parseThreadStreamEvent(value: unknown): ThreadStreamEvent;
117
- export declare function assertThreadStreamTransitions(event: ThreadStreamEvent): void;
184
+ export declare function assertThreadStreamTransitions(_event: ThreadStreamEvent): void;
118
185
  export declare function validateThreadStreamTimeline(events: readonly ThreadStreamEvent[]): void;
119
186
  export {};
@@ -1,4 +1,4 @@
1
- import { assertContextTransition, assertExecutionTransition, assertItemTransition, assertStepTransition, assertThreadTransition, } from "./thread.contract.js";
1
+ import { isThreadStreamChunkType } from "./thread.contract.js";
2
2
  function assertObject(value, label) {
3
3
  if (!value || typeof value !== "object") {
4
4
  throw new Error(`Invalid ${label}: expected object.`);
@@ -14,6 +14,16 @@ function assertNumber(value, label) {
14
14
  throw new Error(`Invalid ${label}: expected number.`);
15
15
  }
16
16
  }
17
+ function assertOptionalString(value, label) {
18
+ if (value !== undefined) {
19
+ assertString(value, label);
20
+ }
21
+ }
22
+ function assertOptionalNumber(value, label) {
23
+ if (value !== undefined) {
24
+ assertNumber(value, label);
25
+ }
26
+ }
17
27
  export function parseThreadStreamEvent(value) {
18
28
  assertObject(value, "thread stream event");
19
29
  assertString(value.type, "thread stream event.type");
@@ -27,64 +37,59 @@ export function parseThreadStreamEvent(value) {
27
37
  assertString(value.status, `${type}.status`);
28
38
  return value;
29
39
  }
30
- case "context.status.changed": {
40
+ case "context.opened":
41
+ case "context.closed": {
31
42
  assertString(value.contextId, `${type}.contextId`);
32
43
  assertString(value.threadId, `${type}.threadId`);
33
- assertString(value.from, `${type}.from`);
34
- assertString(value.to, `${type}.to`);
44
+ assertString(value.status, `${type}.status`);
35
45
  return value;
36
46
  }
37
- case "thread.created":
38
- case "thread.resolved": {
47
+ case "context.content_updated": {
48
+ assertString(value.contextId, `${type}.contextId`);
39
49
  assertString(value.threadId, `${type}.threadId`);
40
- assertString(value.status, `${type}.status`);
41
50
  return value;
42
51
  }
43
- case "thread.status.changed": {
52
+ case "thread.created":
53
+ case "thread.resolved":
54
+ case "thread.streaming_started":
55
+ case "thread.idle": {
44
56
  assertString(value.threadId, `${type}.threadId`);
45
- assertString(value.from, `${type}.from`);
46
- assertString(value.to, `${type}.to`);
57
+ assertString(value.status, `${type}.status`);
47
58
  return value;
48
59
  }
49
- case "execution.created": {
60
+ case "execution.created":
61
+ case "execution.completed":
62
+ case "execution.failed": {
50
63
  assertString(value.executionId, `${type}.executionId`);
51
64
  assertString(value.contextId, `${type}.contextId`);
52
65
  assertString(value.threadId, `${type}.threadId`);
53
66
  assertString(value.status, `${type}.status`);
54
67
  return value;
55
68
  }
56
- case "execution.status.changed": {
57
- assertString(value.executionId, `${type}.executionId`);
69
+ case "item.created": {
70
+ assertString(value.itemId, `${type}.itemId`);
58
71
  assertString(value.contextId, `${type}.contextId`);
59
72
  assertString(value.threadId, `${type}.threadId`);
60
- assertString(value.from, `${type}.from`);
61
- assertString(value.to, `${type}.to`);
73
+ assertString(value.status, `${type}.status`);
74
+ assertOptionalString(value.executionId, `${type}.executionId`);
75
+ assertOptionalString(value.itemType, `${type}.itemType`);
62
76
  return value;
63
77
  }
64
- case "thread.finished": {
65
- assertString(value.threadId, `${type}.threadId`);
78
+ case "item.updated": {
79
+ assertString(value.itemId, `${type}.itemId`);
66
80
  assertString(value.contextId, `${type}.contextId`);
67
- assertString(value.executionId, `${type}.executionId`);
68
- assertString(value.result, `${type}.result`);
81
+ assertString(value.threadId, `${type}.threadId`);
82
+ assertOptionalString(value.executionId, `${type}.executionId`);
83
+ assertOptionalString(value.status, `${type}.status`);
69
84
  return value;
70
85
  }
71
- case "item.created": {
86
+ case "item.pending":
87
+ case "item.completed": {
72
88
  assertString(value.itemId, `${type}.itemId`);
73
89
  assertString(value.contextId, `${type}.contextId`);
74
90
  assertString(value.threadId, `${type}.threadId`);
91
+ assertOptionalString(value.executionId, `${type}.executionId`);
75
92
  assertString(value.status, `${type}.status`);
76
- if (value.executionId !== undefined) {
77
- assertString(value.executionId, `${type}.executionId`);
78
- }
79
- return value;
80
- }
81
- case "item.status.changed": {
82
- assertString(value.itemId, `${type}.itemId`);
83
- assertString(value.from, `${type}.from`);
84
- assertString(value.to, `${type}.to`);
85
- if (value.executionId !== undefined) {
86
- assertString(value.executionId, `${type}.executionId`);
87
- }
88
93
  return value;
89
94
  }
90
95
  case "step.created": {
@@ -94,11 +99,25 @@ export function parseThreadStreamEvent(value) {
94
99
  assertString(value.status, `${type}.status`);
95
100
  return value;
96
101
  }
97
- case "step.status.changed": {
102
+ case "step.updated": {
103
+ assertString(value.stepId, `${type}.stepId`);
104
+ assertString(value.executionId, `${type}.executionId`);
105
+ if (value.iteration !== undefined)
106
+ assertNumber(value.iteration, `${type}.iteration`);
107
+ assertOptionalString(value.status, `${type}.status`);
108
+ assertOptionalString(value.kind, `${type}.kind`);
109
+ assertOptionalString(value.actionName, `${type}.actionName`);
110
+ return value;
111
+ }
112
+ case "step.completed":
113
+ case "step.failed": {
98
114
  assertString(value.stepId, `${type}.stepId`);
99
115
  assertString(value.executionId, `${type}.executionId`);
100
- assertString(value.from, `${type}.from`);
101
- assertString(value.to, `${type}.to`);
116
+ if (value.iteration !== undefined)
117
+ assertNumber(value.iteration, `${type}.iteration`);
118
+ assertString(value.status, `${type}.status`);
119
+ if (type === "step.failed")
120
+ assertOptionalString(value.errorText, `${type}.errorText`);
102
121
  return value;
103
122
  }
104
123
  case "part.created":
@@ -106,44 +125,34 @@ export function parseThreadStreamEvent(value) {
106
125
  assertString(value.partKey, `${type}.partKey`);
107
126
  assertString(value.stepId, `${type}.stepId`);
108
127
  assertNumber(value.idx, `${type}.idx`);
128
+ assertOptionalString(value.partType, `${type}.partType`);
129
+ assertOptionalString(value.partPreview, `${type}.partPreview`);
130
+ assertOptionalString(value.partState, `${type}.partState`);
131
+ assertOptionalString(value.partToolCallId, `${type}.partToolCallId`);
109
132
  return value;
110
133
  }
111
134
  case "chunk.emitted": {
112
135
  assertString(value.chunkType, `${type}.chunkType`);
113
- assertString(value.contextId, `${type}.contextId`);
114
- if (value.executionId !== undefined) {
115
- assertString(value.executionId, `${type}.executionId`);
116
- }
117
- if (value.stepId !== undefined) {
118
- assertString(value.stepId, `${type}.stepId`);
136
+ if (!isThreadStreamChunkType(value.chunkType)) {
137
+ throw new Error(`Invalid ${type}.chunkType: ${String(value.chunkType)}`);
119
138
  }
139
+ assertString(value.contextId, `${type}.contextId`);
140
+ assertOptionalString(value.executionId, `${type}.executionId`);
141
+ assertOptionalString(value.stepId, `${type}.stepId`);
142
+ assertOptionalString(value.itemId, `${type}.itemId`);
143
+ assertOptionalString(value.partKey, `${type}.partKey`);
144
+ assertOptionalString(value.actionRef, `${type}.actionRef`);
145
+ assertOptionalString(value.provider, `${type}.provider`);
146
+ assertOptionalString(value.providerChunkType, `${type}.providerChunkType`);
147
+ assertOptionalNumber(value.sequence, `${type}.sequence`);
120
148
  return value;
121
149
  }
122
- default: {
150
+ default:
123
151
  throw new Error(`Unsupported thread stream event type: ${type}`);
124
- }
125
152
  }
126
153
  }
127
- export function assertThreadStreamTransitions(event) {
128
- switch (event.type) {
129
- case "context.status.changed":
130
- assertContextTransition(event.from, event.to);
131
- return;
132
- case "thread.status.changed":
133
- assertThreadTransition(event.from, event.to);
134
- return;
135
- case "execution.status.changed":
136
- assertExecutionTransition(event.from, event.to);
137
- return;
138
- case "item.status.changed":
139
- assertItemTransition(event.from, event.to);
140
- return;
141
- case "step.status.changed":
142
- assertStepTransition(event.from, event.to);
143
- return;
144
- default:
145
- return;
146
- }
154
+ export function assertThreadStreamTransitions(_event) {
155
+ return;
147
156
  }
148
157
  export function validateThreadStreamTimeline(events) {
149
158
  for (const event of events) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ekairos/thread",
3
- "version": "1.22.4-beta.feature-thread-unify.0",
3
+ "version": "1.22.4-beta.feature-core-thread-registry-sync.0",
4
4
  "description": "Pulzar Thread - Workflow-based AI Threads",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -109,11 +109,12 @@
109
109
  "typecheck": "tsc --noEmit",
110
110
  "test": "vitest run -c vitest.config.mts",
111
111
  "test:ai-sdk-reactor": "vitest run -c vitest.config.mts src/tests/thread.ai-sdk-reactor.instant.test.ts",
112
+ "test:ai-sdk-reactor:real": "vitest run -c vitest.config.mts src/tests/thread.ai-sdk-reactor.real.instant.test.ts",
112
113
  "test:scripted-reactor": "vitest run -c vitest.config.mts src/tests/thread.scripted-reactor.instant.test.ts"
113
114
  },
114
115
  "dependencies": {
115
116
  "@ai-sdk/openai": "^2.0.52",
116
- "@ekairos/domain": "^1.22.4-beta.feature-thread-unify.0",
117
+ "@ekairos/domain": "^1.22.4-beta.feature-core-thread-registry-sync.0",
117
118
  "@instantdb/admin": "0.22.126",
118
119
  "@instantdb/core": "0.22.126",
119
120
  "@vercel/mcp-adapter": "^1.0.0",