@codeworksh/aikit 0.3.0 → 0.4.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 (41) hide show
  1. package/README.md +73 -81
  2. package/{agent → dist/pack/agent}/codemode/drivers/drivers.d.mts +1 -1
  3. package/dist/pack/codemode-BEDXG7WN.d.mts +8736 -0
  4. package/{index.d.mts → dist/pack/index.d.mts} +3 -3
  5. package/dist/pack/index.mjs +8226 -0
  6. package/dist/pack/index.mjs.map +1 -0
  7. package/package.json +32 -22
  8. package/src/agent/agent.ts +790 -0
  9. package/src/agent/codemode/codemode.ts +561 -0
  10. package/src/agent/codemode/drivers/drivers.ts +1 -0
  11. package/src/agent/codemode/drivers/quickjs-wasi-driver.ts +149 -0
  12. package/src/agent/codemode/index.ts +1 -0
  13. package/src/agent/loop.ts +903 -0
  14. package/src/agent.ts +11 -0
  15. package/src/event/event.ts +277 -0
  16. package/src/index.ts +6 -0
  17. package/src/llm.ts +31 -0
  18. package/src/message/message.ts +311 -0
  19. package/src/model/catalog.ts +94 -0
  20. package/src/model/model.ts +250 -0
  21. package/src/model/transform.ts +59 -0
  22. package/src/provider/provider.ts +60 -0
  23. package/src/provider/providers/anthropic/index.ts +792 -0
  24. package/src/provider/providers/github/github.ts +34 -0
  25. package/src/provider/providers/openai/completions.ts +953 -0
  26. package/src/provider/providers/utils.ts +7 -0
  27. package/src/provider/register.ts +6 -0
  28. package/src/provider/stream.ts +278 -0
  29. package/src/stream.ts +72 -0
  30. package/src/utils/eventstream.ts +95 -0
  31. package/src/utils/helpers.ts +24 -0
  32. package/src/utils/jsonparse.ts +32 -0
  33. package/src/utils/overflow.ts +121 -0
  34. package/src/utils/sanitize.ts +25 -0
  35. package/src/utils/validation.ts +87 -0
  36. package/LICENSE +0 -21
  37. package/codemode-z3ZIw-5q.d.mts +0 -8234
  38. package/index.mjs +0 -2694
  39. package/index.mjs.map +0 -1
  40. /package/{agent → dist/pack/agent}/codemode/drivers/drivers.mjs +0 -0
  41. /package/{agent → dist/pack/agent}/codemode/drivers/drivers.mjs.map +0 -0
package/src/agent.ts ADDED
@@ -0,0 +1,11 @@
1
+ import { Loop } from "./agent/loop";
2
+
3
+ type AgentFacade = {
4
+ loop: typeof Loop.run;
5
+ loopContinue: typeof Loop.runContinue;
6
+ };
7
+
8
+ export const agent = {
9
+ loop: Loop.run,
10
+ loopContinue: Loop.runContinue,
11
+ } as AgentFacade;
@@ -0,0 +1,277 @@
1
+ import Type, { type Static } from "typebox";
2
+ import { Agent } from "../agent/agent";
3
+ import { Message } from "../message/message";
4
+
5
+ // TODO @sanchitrk:
6
+ // for delta events we can have metadata KV that a provider can use for internal state
7
+ // similar to index what anthropic does
8
+ export namespace Event {
9
+ export const LLMMessageEventType = {
10
+ start: "start",
11
+
12
+ textStart: "text.start",
13
+ textDelta: "text.delta",
14
+ textEnd: "text.end",
15
+
16
+ thinkingStart: "thinking.start",
17
+ thinkingDelta: "thinking.delta",
18
+ thinkingEnd: "thinking.end",
19
+
20
+ toolcallStart: "toolcall.start",
21
+ toolcallDelta: "toolcall.delta",
22
+ toolcallEnd: "toolcall.end",
23
+
24
+ done: "done",
25
+ error: "error",
26
+ } as const;
27
+ export type LLMMessageEventType = (typeof LLMMessageEventType)[keyof typeof LLMMessageEventType];
28
+
29
+ /**
30
+ * Event protocol for AssistantMessageEventStream.
31
+ *
32
+ * Streams should emit `start` before partial updates, then terminate with either:
33
+ * - `done` carrying the final successful AssistantMessage, or
34
+ * - `error` carrying the final AssistantMessage with stopReason "error" or "aborted"
35
+ * and errorMessage.
36
+ */
37
+ export const LLMMessageEventSchema = Type.Union([
38
+ Type.Object({
39
+ type: Type.Literal(LLMMessageEventType.start),
40
+ partial: Message.AssistantMessageSchema,
41
+ }),
42
+ Type.Object({
43
+ type: Type.Literal(LLMMessageEventType.textStart),
44
+ partIndex: Type.Number(),
45
+ partial: Message.AssistantMessageSchema,
46
+ }),
47
+ Type.Object({
48
+ type: Type.Literal(LLMMessageEventType.textDelta),
49
+ partIndex: Type.Number(),
50
+ delta: Type.String(),
51
+ partial: Message.AssistantMessageSchema,
52
+ }),
53
+ Type.Object({
54
+ type: Type.Literal(LLMMessageEventType.textEnd),
55
+ partIndex: Type.Number(),
56
+ content: Type.String(),
57
+ partial: Message.AssistantMessageSchema,
58
+ }),
59
+ Type.Object({
60
+ type: Type.Literal(LLMMessageEventType.thinkingStart),
61
+ partIndex: Type.Number(),
62
+ partial: Message.AssistantMessageSchema,
63
+ }),
64
+ Type.Object({
65
+ type: Type.Literal(LLMMessageEventType.thinkingDelta),
66
+ partIndex: Type.Number(),
67
+ delta: Type.String(),
68
+ partial: Message.AssistantMessageSchema,
69
+ }),
70
+ Type.Object({
71
+ type: Type.Literal(LLMMessageEventType.thinkingEnd),
72
+ partIndex: Type.Number(),
73
+ content: Type.String(),
74
+ partial: Message.AssistantMessageSchema,
75
+ }),
76
+ Type.Object({
77
+ type: Type.Literal(LLMMessageEventType.toolcallStart),
78
+ partIndex: Type.Number(),
79
+ partial: Message.AssistantMessageSchema,
80
+ }),
81
+ Type.Object({
82
+ type: Type.Literal(LLMMessageEventType.toolcallDelta),
83
+ partIndex: Type.Number(),
84
+ delta: Type.String(),
85
+ partial: Message.AssistantMessageSchema,
86
+ }),
87
+ Type.Object({
88
+ type: Type.Literal(LLMMessageEventType.toolcallEnd),
89
+ partIndex: Type.Number(),
90
+ toolCall: Message.ToolCallSchema,
91
+ partial: Message.AssistantMessageSchema,
92
+ }),
93
+ Type.Object({
94
+ type: Type.Literal(LLMMessageEventType.done),
95
+ reason: Type.Union([Type.Literal("stop"), Type.Literal("length"), Type.Literal("toolUse")]),
96
+ message: Message.AssistantMessageSchema,
97
+ }),
98
+ Type.Object({
99
+ type: Type.Literal(LLMMessageEventType.error),
100
+ reason: Type.Union([Type.Literal("aborted"), Type.Literal("error")]),
101
+ error: Message.AssistantMessageSchema,
102
+ }),
103
+ ]);
104
+ export type LLMMessageEvent = Static<typeof LLMMessageEventSchema>;
105
+
106
+ export const AgentEventType = {
107
+ // Agent lifecycle
108
+ agentStart: "agent.start",
109
+ agentEnd: "agent.end",
110
+ // Turn lifecycle - a turn is one assistant response + any tool calls/results
111
+ turnStart: "turn.start",
112
+ turnEnd: "turn.end",
113
+ // Message lifecycle - emitted for user, assistant message and corresponding parts
114
+ messageStart: "message.start",
115
+
116
+ messagePartStart: "message.part.start",
117
+ messagePartUpdate: "message.part.update",
118
+ messagePartEnd: "message.part.end",
119
+
120
+ messageUpdate: "message.update",
121
+ messageEnd: "message.end",
122
+ // Tool execution lifecycle
123
+ toolExecutionStart: "tool.execution.start",
124
+ toolExecutionUpdate: "tool.execution.update",
125
+ toolExecutionEnd: "tool.execution.end",
126
+ } as const;
127
+ export type AgentEventType = (typeof AgentEventType)[keyof typeof AgentEventType];
128
+
129
+ //
130
+ // message parts
131
+ const UserMessagePart = Type.Union([Message.TextContentSchema, Message.ImageContentSchema]);
132
+ const AssistantMessagePart = Type.Union([
133
+ Message.TextContentSchema,
134
+ Message.ImageContentSchema,
135
+ Message.ThinkingContentSchema,
136
+ Message.ToolCallSchema,
137
+ ]);
138
+
139
+ //
140
+ // user message part
141
+ // part start
142
+ const UserMessagePartStart = Type.Object({
143
+ type: Type.Literal(AgentEventType.messagePartStart),
144
+ message: Message.UserMessageSchema,
145
+ partIndex: Type.Number(),
146
+ part: UserMessagePart,
147
+ });
148
+ // part end
149
+ const UserMessagePartEnd = Type.Object({
150
+ type: Type.Literal(AgentEventType.messagePartEnd),
151
+ message: Message.UserMessageSchema,
152
+ partIndex: Type.Number(),
153
+ part: UserMessagePart,
154
+ });
155
+
156
+ //
157
+ // assistant message part
158
+ // part start
159
+ const AssistantMessagePartStart = Type.Object({
160
+ type: Type.Literal(AgentEventType.messagePartStart),
161
+ message: Message.AssistantMessageSchema,
162
+ partIndex: Type.Number(),
163
+ part: AssistantMessagePart,
164
+ });
165
+ // part update llm
166
+ const AssistantMessagePartLLMUpdate = Type.Object({
167
+ type: Type.Literal(AgentEventType.messagePartUpdate),
168
+ message: Message.AssistantMessageSchema,
169
+ partIndex: Type.Number(),
170
+ part: AssistantMessagePart,
171
+ source: Type.Literal("llm"),
172
+ });
173
+ // part update tool
174
+ const AssistantMessagePartToolUpdate = Type.Object({
175
+ type: Type.Literal(AgentEventType.messagePartUpdate),
176
+ message: Message.AssistantMessageSchema,
177
+ partIndex: Type.Number(),
178
+ part: AssistantMessagePart,
179
+ source: Type.Literal("tool"),
180
+ });
181
+ // part end
182
+ const AssistantMessagePartEnd = Type.Object({
183
+ type: Type.Literal(AgentEventType.messagePartEnd),
184
+ message: Message.AssistantMessageSchema,
185
+ partIndex: Type.Number(),
186
+ part: AssistantMessagePart,
187
+ });
188
+
189
+ //
190
+ // tool exection
191
+ const ToolExecutionStartSchema = Type.Evaluate(
192
+ Type.Intersect([
193
+ Agent.ToolCallInFlightSchema,
194
+ Type.Object({
195
+ type: Type.Literal(AgentEventType.toolExecutionStart),
196
+ }),
197
+ ]),
198
+ );
199
+ export type ToolExecutionStart = Static<typeof ToolExecutionStartSchema>;
200
+
201
+ const ToolExecutionUpdateSchema = Type.Evaluate(
202
+ Type.Intersect([
203
+ Agent.ToolCallInFlightSchema,
204
+ Type.Object({
205
+ type: Type.Literal(AgentEventType.toolExecutionUpdate),
206
+ }),
207
+ Message.ToolRunningSchema,
208
+ ]),
209
+ );
210
+ export type ToolExecutionUpdate = Static<typeof ToolExecutionUpdateSchema>;
211
+
212
+ const ToolExecutionEndSchema = Type.Evaluate(
213
+ Type.Intersect([
214
+ Agent.ToolCallInFlightSchema,
215
+ Type.Object({
216
+ type: Type.Literal(AgentEventType.toolExecutionEnd),
217
+ }),
218
+ Type.Union([Message.ToolCompletedSchema, Message.ToolErrorSchema]),
219
+ ]),
220
+ );
221
+ export type ToolExecutionEnd = Static<typeof ToolExecutionEndSchema>;
222
+
223
+ /**
224
+ * Events emitted by the Agent lifecycle
225
+ * These events provide fine-grained lifecycle information for messages, turns, and tool execution.
226
+ */
227
+ export const AgentEventSchema = Type.Union([
228
+ //
229
+ // Agent lifecycle
230
+ Type.Object({
231
+ type: Type.Literal(AgentEventType.agentStart),
232
+ }),
233
+ Type.Object({
234
+ type: Type.Literal(AgentEventType.agentEnd),
235
+ messages: Type.Array(Message.MessageSchema),
236
+ }),
237
+ //
238
+ // Turn lifecycle - a turn is one assistant response + any tool calls/results
239
+ Type.Object({
240
+ type: Type.Literal(AgentEventType.turnStart),
241
+ }),
242
+ Type.Object({
243
+ type: Type.Literal(AgentEventType.turnEnd),
244
+ message: Message.AssistantMessageSchema,
245
+ }),
246
+ //
247
+ // Message lifecycle - emitted for user, assistant and corresponding parts
248
+ Type.Object({
249
+ type: Type.Literal(AgentEventType.messageStart),
250
+ message: Message.MessageSchema,
251
+ }),
252
+ // user message parts lifecycle
253
+ Type.Union([UserMessagePartStart, UserMessagePartEnd]),
254
+ //
255
+ // assistant message parts lifecycle
256
+ Type.Union([
257
+ AssistantMessagePartStart,
258
+ AssistantMessagePartLLMUpdate,
259
+ AssistantMessagePartToolUpdate,
260
+ AssistantMessagePartEnd,
261
+ ]),
262
+ Type.Object({
263
+ type: Type.Literal(AgentEventType.messageUpdate),
264
+ message: Message.MessageSchema,
265
+ }),
266
+ Type.Object({
267
+ type: Type.Literal(AgentEventType.messageEnd),
268
+ message: Message.MessageSchema,
269
+ }),
270
+ //
271
+ // Tool execution lifecycle
272
+ ToolExecutionStartSchema,
273
+ ToolExecutionUpdateSchema,
274
+ ToolExecutionEndSchema,
275
+ ]);
276
+ export type AgentEvent = Static<typeof AgentEventSchema>;
277
+ }
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export { agent } from "./agent.ts";
2
+ export { Agent } from "./agent/agent";
3
+ export { CodeMode } from "./agent/codemode";
4
+ export { llm } from "./llm";
5
+ export { Message } from "./message/message";
6
+ export { stream } from "./stream";
package/src/llm.ts ADDED
@@ -0,0 +1,31 @@
1
+ import { Model } from "./model/model";
2
+ import type { Provider } from "./provider/provider";
3
+
4
+ type LLM = {
5
+ <TProvider extends Provider.KnownProvider, TModel extends Model.Info["id"]>(
6
+ provider: TProvider,
7
+ model: TModel,
8
+ overrides?: Partial<Model.Info>,
9
+ ): Promise<Model.Info | undefined>;
10
+ model: typeof Model.getModel;
11
+ models: typeof Model.getModels;
12
+ providers: typeof Model.getProviders;
13
+ registry: typeof Model.registry;
14
+ supportsXhigh: typeof Model.supportsXhigh;
15
+ modelsAreEqual: typeof Model.modelsAreEqual;
16
+ };
17
+
18
+ const llmImpl = async <TProvider extends Provider.KnownProvider, TModel extends Model.Info["id"]>(
19
+ provider: TProvider,
20
+ model: TModel,
21
+ overrides?: Partial<Model.Info>,
22
+ ): Promise<Model.Info | undefined> => Model.getModel(provider, model, overrides);
23
+
24
+ export const llm = Object.assign(llmImpl, {
25
+ model: Model.getModel,
26
+ models: Model.getModels,
27
+ providers: Model.getProviders,
28
+ registry: Model.registry,
29
+ supportsXhigh: Model.supportsXhigh,
30
+ modelsAreEqual: Model.modelsAreEqual,
31
+ }) as LLM;
@@ -0,0 +1,311 @@
1
+ import Type, { type Static, type TSchema } from "typebox";
2
+ import { uuidv7 } from "uuidv7";
3
+ import { Model } from "../model/model";
4
+ import { Provider } from "../provider/provider";
5
+
6
+ export namespace Message {
7
+ export const TextContentSchema = Type.Object({
8
+ type: Type.Literal("text"),
9
+ text: Type.String(),
10
+ textSignature: Type.Optional(Type.String()), // e.g., for OpenAI responses, the message ID
11
+ });
12
+ export type TextContent = Static<typeof TextContentSchema>;
13
+
14
+ export const ImageContentSchema = Type.Object({
15
+ type: Type.Literal("image"),
16
+ data: Type.String(), // base64 encoded image data
17
+ mimeType: Type.String(), // e.g., "image/jpeg", "image/png"
18
+ });
19
+ export type ImageContent = Static<typeof ImageContentSchema>;
20
+
21
+ export const ThinkingContentSchema = Type.Object({
22
+ type: Type.Literal("thinking"),
23
+ thinking: Type.String(),
24
+ thinkingSignature: Type.Optional(Type.String()), // e.g., for OpenAI responses, the reasoning item ID
25
+ /** When true, the thinking content was redacted by safety filters. The opaque
26
+ * encrypted payload is stored in `thinkingSignature` so it can be passed back
27
+ * to the API for multi-turn continuity. */
28
+ redacted: Type.Optional(Type.Boolean()),
29
+ });
30
+ export type ThinkingContent = Static<typeof ThinkingContentSchema>;
31
+
32
+ export const ToolCallBaseSchema = Type.Object({
33
+ type: Type.Literal("toolCall"),
34
+ callID: Type.String(),
35
+ name: Type.String(),
36
+ arguments: Type.Record(Type.String(), Type.Any()),
37
+ thoughtSignature: Type.Optional(Type.String()), // Google-specific: opaque signature for reusing thought context
38
+ time: Type.Object({
39
+ start: Type.Number(), // Unix timestamp in milliseconds
40
+ end: Type.Number(), // Unix timestamp in milliseconds, last known lifecycle update
41
+ }),
42
+ });
43
+
44
+ export const ToolSuccessResult = Type.Object({
45
+ content: Type.Array(Type.Union([TextContentSchema, ImageContentSchema])),
46
+ details: Type.Optional(Type.Any()),
47
+ isError: Type.Literal(false),
48
+ });
49
+ export const ToolErrorResult = Type.Object({
50
+ content: Type.Array(Type.Union([TextContentSchema, ImageContentSchema])),
51
+ details: Type.Optional(Type.Any()),
52
+ isError: Type.Literal(true),
53
+ });
54
+ export const ToolRunningPartial = Type.Object({
55
+ content: Type.Optional(Type.Array(Type.Union([TextContentSchema, ImageContentSchema]))),
56
+ details: Type.Optional(Type.Any()),
57
+ });
58
+
59
+ export const ToolStatusEnum = {
60
+ pending: "pending",
61
+ running: "running",
62
+ completed: "completed",
63
+ error: "error",
64
+ skipped: "skipped",
65
+ aborted: "aborted",
66
+ } as const;
67
+
68
+ export const ToolRunningSchema = Type.Object({
69
+ status: Type.Literal(ToolStatusEnum.running),
70
+ partial: Type.Optional(ToolRunningPartial),
71
+ });
72
+ export const ToolCompletedSchema = Type.Object({
73
+ status: Type.Literal(ToolStatusEnum.completed),
74
+ result: ToolSuccessResult,
75
+ });
76
+ export const ToolErrorSchema = Type.Object({
77
+ status: Type.Literal(ToolStatusEnum.error),
78
+ result: ToolErrorResult,
79
+ });
80
+ export const ToolSkippedSchema = Type.Object({
81
+ status: Type.Literal(ToolStatusEnum.skipped),
82
+ result: ToolErrorResult,
83
+ });
84
+ export const ToolAbortedSchema = Type.Object({
85
+ status: Type.Literal(ToolStatusEnum.aborted),
86
+ result: ToolErrorResult,
87
+ });
88
+
89
+ const ToolCallPendingPart = Type.Intersect([
90
+ ToolCallBaseSchema,
91
+ Type.Object({
92
+ status: Type.Literal(ToolStatusEnum.pending),
93
+ }),
94
+ ]);
95
+ const ToolCallRunningPart = Type.Evaluate(Type.Intersect([ToolCallBaseSchema, ToolRunningSchema]));
96
+ const ToolCallCompletedPart = Type.Evaluate(Type.Intersect([ToolCallBaseSchema, ToolCompletedSchema]));
97
+ const ToolCallErrorPart = Type.Evaluate(Type.Intersect([ToolCallBaseSchema, ToolErrorSchema]));
98
+ const ToolCallSkippedPart = Type.Evaluate(Type.Intersect([ToolCallBaseSchema, ToolSkippedSchema]));
99
+ const ToolCallAbortedPart = Type.Evaluate(Type.Intersect([ToolCallBaseSchema, ToolAbortedSchema]));
100
+
101
+ export const ToolCallSchema = Type.Union([
102
+ ToolCallPendingPart,
103
+ ToolCallRunningPart,
104
+ ToolCallCompletedPart,
105
+ ToolCallErrorPart,
106
+ ToolCallSkippedPart,
107
+ ToolCallAbortedPart,
108
+ ]);
109
+
110
+ export type ToolCall = Static<typeof ToolCallSchema>;
111
+ export type ToolCallPendingPart = Static<typeof ToolCallPendingPart>;
112
+ export type ToolCallRunningPart = Static<typeof ToolCallRunningPart>;
113
+ export type ToolCallCompletedPart = Static<typeof ToolCallCompletedPart>;
114
+ export type ToolCallErrorPart = Static<typeof ToolCallErrorPart>;
115
+
116
+ export const UsageSchema = Type.Object({
117
+ input: Type.Number(),
118
+ output: Type.Number(),
119
+ cacheRead: Type.Number(),
120
+ cacheWrite: Type.Number(),
121
+ totalTokens: Type.Number(),
122
+ cost: Type.Object({
123
+ input: Type.Number(),
124
+ output: Type.Number(),
125
+ cacheRead: Type.Number(),
126
+ cacheWrite: Type.Number(),
127
+ total: Type.Number(),
128
+ }),
129
+ });
130
+ export type Usage = Static<typeof UsageSchema>;
131
+
132
+ export const StopReasonSchema = Type.Union([
133
+ Type.Literal("stop"),
134
+ Type.Literal("length"),
135
+ Type.Literal("toolUse"),
136
+ Type.Literal("error"),
137
+ Type.Literal("aborted"),
138
+ ]);
139
+ export type StopReason = Static<typeof StopReasonSchema>;
140
+
141
+ export const UserMessageSchema = Type.Object({
142
+ messageId: Type.String(),
143
+ role: Type.Literal("user"),
144
+ time: Type.Object({
145
+ created: Type.Number(),
146
+ }),
147
+ parts: Type.Array(Type.Union([TextContentSchema, ImageContentSchema])),
148
+ });
149
+ export type UserMessage = Static<typeof UserMessageSchema>;
150
+
151
+ export const AssistantMessageSchema = Type.Object({
152
+ role: Type.Literal("assistant"),
153
+ protocol: Model.KnownProtocolSchema,
154
+ provider: Provider.Info,
155
+ model: Type.String(),
156
+ usage: UsageSchema,
157
+ stopReason: StopReasonSchema,
158
+ errorMessage: Type.Optional(Type.String()),
159
+ time: Type.Object({
160
+ created: Type.Number(),
161
+ completed: Type.Number(),
162
+ }),
163
+ parts: Type.Array(Type.Union([TextContentSchema, ImageContentSchema, ThinkingContentSchema, ToolCallSchema])),
164
+ responseId: Type.Optional(Type.String()), // Provider-specific response/message identifier when the upstream API exposes one
165
+ messageId: Type.String(),
166
+ });
167
+ export type AssistantMessage = Static<typeof AssistantMessageSchema>;
168
+
169
+ export const MessageSchema = Type.Union([UserMessageSchema, AssistantMessageSchema]);
170
+ export type Message = Static<typeof MessageSchema>;
171
+
172
+ type UserMessageInit = Omit<UserMessage, "messageId"> & {
173
+ messageId?: string;
174
+ };
175
+
176
+ type AssistantMessageInit = Omit<AssistantMessage, "messageId"> & {
177
+ messageId?: string;
178
+ };
179
+
180
+ export function createMessageId(): string {
181
+ return uuidv7();
182
+ }
183
+
184
+ export function createUserMessage(message: UserMessageInit): UserMessage {
185
+ const { messageId = createMessageId(), ...rest } = message;
186
+ return {
187
+ messageId,
188
+ ...rest,
189
+ };
190
+ }
191
+
192
+ export function createAssistantMessage(message: AssistantMessageInit): AssistantMessage {
193
+ const { messageId = createMessageId(), ...rest } = message;
194
+ return {
195
+ messageId,
196
+ ...rest,
197
+ };
198
+ }
199
+
200
+ /**
201
+ * Generic tool definition with typed parameter schema.
202
+ * Usage:
203
+ *
204
+ * const search = Message.defineTool({
205
+ * name: "search",
206
+ * description: "Search documents",
207
+ * parameters: Type.Object({
208
+ * query: Type.String(),
209
+ * limit: Type.Optional(Type.Number()),
210
+ * }),
211
+ * });
212
+ *
213
+ * type SearchParams = Static<typeof search.parameters>;
214
+ */
215
+ export const ToolSchema = Type.Object({
216
+ name: Type.String(),
217
+ description: Type.String(),
218
+ parameters: Type.Unsafe<TSchema>({}),
219
+ });
220
+ export interface Tool<TParameters extends TSchema = TSchema> {
221
+ name: string;
222
+ description: string;
223
+ parameters: TParameters;
224
+ }
225
+ export type ToolArguments<T extends Tool> = Static<T["parameters"]>;
226
+
227
+ export function defineTool<TParameters extends TSchema>(tool: Tool<TParameters>): Tool<TParameters> {
228
+ return tool;
229
+ }
230
+
231
+ export const ContextSchema = Type.Object({
232
+ systemPrompt: Type.Optional(Type.String()),
233
+ messages: Type.Array(MessageSchema),
234
+ tools: Type.Optional(Type.Array(ToolSchema)),
235
+ });
236
+ export type Context = Static<typeof ContextSchema>;
237
+
238
+ export function transformMessages<TProtocol extends Model.KnownProtocol>(
239
+ messages: Message[],
240
+ model: Model.TModel<TProtocol>,
241
+ normalizeToolCallId?: (id: string, model: Model.TModel<TProtocol>, source: AssistantMessage) => string,
242
+ ): Message[] {
243
+ const toolCallIDMap = new Map<string, string>();
244
+
245
+ const transformed: Message[] = [];
246
+ for (const msg of messages) {
247
+ if (msg.role === "user") {
248
+ transformed.push(msg);
249
+ continue;
250
+ }
251
+
252
+ const assistantMsg = msg as AssistantMessage;
253
+ const isSameModel =
254
+ assistantMsg.provider.id === model.provider.id &&
255
+ assistantMsg.protocol === model.protocol &&
256
+ assistantMsg.model === model.id;
257
+
258
+ const parts = assistantMsg.parts.flatMap((block) => {
259
+ if (block.type === "thinking") {
260
+ if (isSameModel && block.thinkingSignature) return block;
261
+ if (!block.thinking || block.thinking.trim() === "") return [];
262
+ if (isSameModel) return block;
263
+ return {
264
+ type: "text" as const,
265
+ text: block.thinking,
266
+ };
267
+ }
268
+
269
+ if (block.type === "text") {
270
+ if (isSameModel) return block;
271
+ return {
272
+ type: "text" as const,
273
+ text: block.text,
274
+ };
275
+ }
276
+
277
+ if (block.type === "toolCall") {
278
+ const toolCall = block as ToolCall;
279
+ let normalizedToolCall: ToolCall = toolCall;
280
+
281
+ if (!isSameModel && toolCall.thoughtSignature) {
282
+ normalizedToolCall = { ...toolCall };
283
+ delete (normalizedToolCall as { thoughtSignature?: string }).thoughtSignature;
284
+ }
285
+
286
+ const normalizedID = toolCallIDMap.get(block.callID);
287
+ if (normalizedID && normalizedID !== block.callID) {
288
+ normalizedToolCall = { ...normalizedToolCall, callID: normalizedID };
289
+ } else if (!isSameModel && normalizeToolCallId) {
290
+ const nextID = normalizeToolCallId(toolCall.callID, model, assistantMsg);
291
+ if (nextID !== toolCall.callID) {
292
+ toolCallIDMap.set(toolCall.callID, nextID);
293
+ normalizedToolCall = { ...normalizedToolCall, callID: nextID };
294
+ }
295
+ }
296
+
297
+ return normalizedToolCall;
298
+ }
299
+
300
+ return block;
301
+ });
302
+
303
+ transformed.push({
304
+ ...assistantMsg,
305
+ parts,
306
+ });
307
+ }
308
+
309
+ return transformed;
310
+ }
311
+ }