kernl 0.12.3 → 0.12.6

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 (100) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +18 -0
  3. package/README.md +29 -0
  4. package/dist/agent.d.ts.map +1 -1
  5. package/dist/agent.js +2 -0
  6. package/dist/kernl/kernl.d.ts +6 -0
  7. package/dist/kernl/kernl.d.ts.map +1 -1
  8. package/dist/kernl/kernl.js +19 -0
  9. package/dist/kernl/types.d.ts +6 -0
  10. package/dist/kernl/types.d.ts.map +1 -1
  11. package/dist/lib/env.d.ts +2 -2
  12. package/dist/mcp/http.d.ts.map +1 -1
  13. package/dist/mcp/http.js +1 -5
  14. package/dist/mcp/sse.d.ts.map +1 -1
  15. package/dist/mcp/sse.js +1 -5
  16. package/dist/mcp/stdio.d.ts.map +1 -1
  17. package/dist/mcp/stdio.js +1 -5
  18. package/dist/task.d.ts.map +1 -1
  19. package/dist/task.js +0 -1
  20. package/dist/thread/__tests__/thread.test.js +241 -0
  21. package/dist/thread/thread.d.ts +5 -4
  22. package/dist/thread/thread.d.ts.map +1 -1
  23. package/dist/thread/thread.js +91 -22
  24. package/dist/thread/types.d.ts +5 -0
  25. package/dist/thread/types.d.ts.map +1 -1
  26. package/dist/tool/tool.d.ts +2 -2
  27. package/dist/tool/tool.d.ts.map +1 -1
  28. package/dist/tracing/__tests__/composite.test.d.ts +2 -0
  29. package/dist/tracing/__tests__/composite.test.d.ts.map +1 -0
  30. package/dist/tracing/__tests__/composite.test.js +146 -0
  31. package/dist/tracing/__tests__/dispatch.test.d.ts +2 -0
  32. package/dist/tracing/__tests__/dispatch.test.d.ts.map +1 -0
  33. package/dist/tracing/__tests__/dispatch.test.js +160 -0
  34. package/dist/tracing/__tests__/helpers.d.ts +69 -0
  35. package/dist/tracing/__tests__/helpers.d.ts.map +1 -0
  36. package/dist/tracing/__tests__/helpers.js +109 -0
  37. package/dist/tracing/__tests__/integration.test.d.ts +2 -0
  38. package/dist/tracing/__tests__/integration.test.d.ts.map +1 -0
  39. package/dist/tracing/__tests__/integration.test.js +675 -0
  40. package/dist/tracing/__tests__/span.test.d.ts +2 -0
  41. package/dist/tracing/__tests__/span.test.d.ts.map +1 -0
  42. package/dist/tracing/__tests__/span.test.js +188 -0
  43. package/dist/tracing/dispatch.d.ts +43 -0
  44. package/dist/tracing/dispatch.d.ts.map +1 -0
  45. package/dist/tracing/dispatch.js +70 -0
  46. package/dist/tracing/index.d.ts +8 -0
  47. package/dist/tracing/index.d.ts.map +1 -0
  48. package/dist/tracing/index.js +6 -0
  49. package/dist/tracing/span.d.ts +69 -0
  50. package/dist/tracing/span.d.ts.map +1 -0
  51. package/dist/tracing/span.js +64 -0
  52. package/dist/tracing/subscriber.d.ts +53 -0
  53. package/dist/tracing/subscriber.d.ts.map +1 -0
  54. package/dist/tracing/subscriber.js +1 -0
  55. package/dist/tracing/subscribers/composite.d.ts +26 -0
  56. package/dist/tracing/subscribers/composite.d.ts.map +1 -0
  57. package/dist/tracing/subscribers/composite.js +96 -0
  58. package/dist/tracing/subscribers/console.d.ts +22 -0
  59. package/dist/tracing/subscribers/console.d.ts.map +1 -0
  60. package/dist/tracing/subscribers/console.js +82 -0
  61. package/dist/tracing/types.d.ts +77 -0
  62. package/dist/tracing/types.d.ts.map +1 -0
  63. package/dist/tracing/types.js +1 -0
  64. package/package.json +6 -2
  65. package/src/agent.ts +2 -0
  66. package/src/index.ts +1 -0
  67. package/src/kernl/kernl.ts +21 -0
  68. package/src/kernl/types.ts +7 -0
  69. package/src/mcp/http.ts +1 -9
  70. package/src/mcp/sse.ts +1 -10
  71. package/src/mcp/stdio.ts +1 -10
  72. package/src/task.ts +0 -1
  73. package/src/thread/__tests__/thread.test.ts +280 -0
  74. package/src/thread/thread.ts +111 -24
  75. package/src/thread/types.ts +5 -0
  76. package/src/tool/tool.ts +1 -1
  77. package/src/tracing/__tests__/composite.test.ts +218 -0
  78. package/src/tracing/__tests__/dispatch.test.ts +222 -0
  79. package/src/tracing/__tests__/helpers.ts +138 -0
  80. package/src/tracing/__tests__/integration.test.ts +808 -0
  81. package/src/tracing/__tests__/span.test.ts +250 -0
  82. package/src/tracing/dispatch.ts +114 -0
  83. package/src/tracing/index.ts +39 -0
  84. package/src/tracing/span.ts +115 -0
  85. package/src/tracing/subscriber.ts +62 -0
  86. package/src/tracing/subscribers/composite.ts +102 -0
  87. package/src/tracing/subscribers/console.ts +101 -0
  88. package/src/tracing/types.ts +115 -0
  89. package/dist/trace/processor.d.ts +0 -1
  90. package/dist/trace/processor.d.ts.map +0 -1
  91. package/dist/trace/processor.js +0 -1
  92. package/dist/trace/traces.d.ts +0 -1
  93. package/dist/trace/traces.d.ts.map +0 -1
  94. package/dist/trace/traces.js +0 -73
  95. package/dist/trace/utils.d.ts +0 -22
  96. package/dist/trace/utils.d.ts.map +0 -1
  97. package/dist/trace/utils.js +0 -30
  98. package/src/trace/processor.ts +0 -0
  99. package/src/trace/traces.ts +0 -86
  100. package/src/trace/utils.ts +0 -38
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../../src/tracing/subscribers/console.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAShD;;;GAGG;AACH,qBAAa,iBAAkB,YAAW,UAAU;IAClD,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,MAAM,CAAK;IAEnB,OAAO,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO;IAIjC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM;IAYnD,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAQ3B,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAO1B,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI;IAQtD,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;IAOzC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAS3B,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAI7C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhD,OAAO,CAAC,GAAG;CAeZ"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * A simple console subscriber for development and debugging.
3
+ * Logs span lifecycle events and events to the console.
4
+ */
5
+ export class ConsoleSubscriber {
6
+ spans = new Map();
7
+ nextId = 0;
8
+ enabled(_data) {
9
+ return true;
10
+ }
11
+ span(data, parent) {
12
+ const id = `span_${this.nextId++}`;
13
+ this.spans.set(id, {
14
+ data,
15
+ parent,
16
+ startTime: Date.now(),
17
+ entered: false,
18
+ });
19
+ console.log(`[span:new] ${id} ${data.kind}`, this.fmt(data));
20
+ return id;
21
+ }
22
+ enter(spanId) {
23
+ const record = this.spans.get(spanId);
24
+ if (record) {
25
+ record.entered = true;
26
+ console.log(`[span:enter] ${spanId} ${record.data.kind}`);
27
+ }
28
+ }
29
+ exit(spanId) {
30
+ const record = this.spans.get(spanId);
31
+ if (record) {
32
+ console.log(`[span:exit] ${spanId} ${record.data.kind}`);
33
+ }
34
+ }
35
+ record(spanId, delta) {
36
+ const record = this.spans.get(spanId);
37
+ if (record) {
38
+ Object.assign(record.data, delta);
39
+ console.log(`[span:record] ${spanId}`, this.fmt(delta));
40
+ }
41
+ }
42
+ error(spanId, error) {
43
+ const record = this.spans.get(spanId);
44
+ if (record) {
45
+ console.log(`[span:error] ${spanId} ${record.data.kind}`, error.message);
46
+ }
47
+ }
48
+ close(spanId) {
49
+ const record = this.spans.get(spanId);
50
+ if (record) {
51
+ const duration = Date.now() - record.startTime;
52
+ console.log(`[span:close] ${spanId} ${record.data.kind} (${duration}ms)`);
53
+ this.spans.delete(spanId);
54
+ }
55
+ }
56
+ event(data, parent) {
57
+ console.log(`[event] ${data.kind}`, { ...data, parent });
58
+ }
59
+ async flush() {
60
+ // Console subscriber doesn't buffer
61
+ }
62
+ async shutdown(_timeout) {
63
+ this.spans.clear();
64
+ }
65
+ fmt(data) {
66
+ const { kind, ...rest } = data;
67
+ // Truncate large fields for readability
68
+ const formatted = {};
69
+ for (const [key, value] of Object.entries(rest)) {
70
+ if (typeof value === "string" && value.length > 100) {
71
+ formatted[key] = value.slice(0, 100) + "...";
72
+ }
73
+ else if (Array.isArray(value) && value.length > 3) {
74
+ formatted[key] = `[${value.length} items]`;
75
+ }
76
+ else {
77
+ formatted[key] = value;
78
+ }
79
+ }
80
+ return formatted;
81
+ }
82
+ }
@@ -0,0 +1,77 @@
1
+ import type { LanguageModelItem, LanguageModelTool, LanguageModelUsage, LanguageModelFinishReason, LanguageModelResponseItem, LanguageModelRequestSettings, LanguageModelResponseType, SharedWarning, ToolCallState } from "@kernl-sdk/protocol";
2
+ import { ThreadState } from "../internal.js";
3
+ export type SpanId = string;
4
+ export interface ThreadSpan {
5
+ kind: "thread";
6
+ threadId: string;
7
+ agentId: string;
8
+ namespace: string;
9
+ context?: unknown;
10
+ state?: ThreadState;
11
+ result?: unknown;
12
+ error?: string;
13
+ }
14
+ export interface ModelCallSpan {
15
+ kind: "model.call";
16
+ provider: string;
17
+ modelId: string;
18
+ request?: {
19
+ input: LanguageModelItem[];
20
+ settings?: LanguageModelRequestSettings;
21
+ responseType?: LanguageModelResponseType;
22
+ tools?: LanguageModelTool[];
23
+ };
24
+ response?: {
25
+ content: LanguageModelResponseItem[];
26
+ finishReason: LanguageModelFinishReason;
27
+ usage?: LanguageModelUsage;
28
+ warnings?: SharedWarning[];
29
+ };
30
+ }
31
+ export interface ToolCallSpan {
32
+ kind: "tool.call";
33
+ toolId: string;
34
+ callId: string;
35
+ args?: Record<string, unknown>;
36
+ state?: ToolCallState;
37
+ result?: string;
38
+ error?: string | null;
39
+ }
40
+ export type SpanData = ThreadSpan | ModelCallSpan | ToolCallSpan;
41
+ export type SpanKind = SpanData["kind"];
42
+ export interface ThreadErrorEvent {
43
+ kind: "thread.error";
44
+ message: string;
45
+ stack?: string;
46
+ }
47
+ export interface ThreadAbortedEvent {
48
+ kind: "thread.aborted";
49
+ reason?: string;
50
+ }
51
+ export interface ThreadGuardrailTriggeredEvent {
52
+ kind: "thread.guardrail_triggered";
53
+ name: string;
54
+ type: "input" | "output";
55
+ passed: boolean;
56
+ reason?: string;
57
+ }
58
+ export interface ToolApprovalRequestedEvent {
59
+ kind: "tool.approval_requested";
60
+ toolId: string;
61
+ callId: string;
62
+ }
63
+ export interface ToolApprovalGrantedEvent {
64
+ kind: "tool.approval_granted";
65
+ toolId: string;
66
+ callId: string;
67
+ approver?: string;
68
+ }
69
+ export interface ToolApprovalDeniedEvent {
70
+ kind: "tool.approval_denied";
71
+ toolId: string;
72
+ callId: string;
73
+ reason?: string;
74
+ }
75
+ export type EventData = ThreadErrorEvent | ThreadAbortedEvent | ThreadGuardrailTriggeredEvent | ToolApprovalRequestedEvent | ToolApprovalGrantedEvent | ToolApprovalDeniedEvent;
76
+ export type EventKind = EventData["kind"];
77
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tracing/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kernl",
3
- "version": "0.12.3",
3
+ "version": "0.12.6",
4
4
  "description": "A modern AI agent framework",
5
5
  "keywords": [
6
6
  "kernl",
@@ -29,10 +29,14 @@
29
29
  "./internal": {
30
30
  "types": "./dist/internal.d.ts",
31
31
  "import": "./dist/internal.js"
32
+ },
33
+ "./tracing": {
34
+ "types": "./dist/tracing/index.d.ts",
35
+ "import": "./dist/tracing/index.js"
32
36
  }
33
37
  },
34
38
  "dependencies": {
35
- "@modelcontextprotocol/sdk": "^1.20.2",
39
+ "@modelcontextprotocol/sdk": "^1.25.2",
36
40
  "yaml": "^2.8.2",
37
41
  "@kernl-sdk/protocol": "0.5.1",
38
42
  "@kernl-sdk/retrieval": "0.1.10",
package/src/agent.ts CHANGED
@@ -115,6 +115,7 @@ export class Agent<
115
115
  tid: options?.threadId,
116
116
  namespace: options?.namespace,
117
117
  storage: this.kernl.storage?.threads,
118
+ abort: options?.abort,
118
119
  });
119
120
  return this.kernl.spawn(thread);
120
121
  }
@@ -186,6 +187,7 @@ export class Agent<
186
187
  tid: options?.threadId,
187
188
  namespace: options?.namespace,
188
189
  storage: this.kernl.storage?.threads,
190
+ abort: options?.abort,
189
191
  });
190
192
  yield* this.kernl.spawnStream(thread);
191
193
  return;
package/src/index.ts CHANGED
@@ -102,3 +102,4 @@ export type {
102
102
  MemoryByte,
103
103
  MemoryByteCodec,
104
104
  } from "./memory";
105
+
@@ -12,6 +12,7 @@ import {
12
12
  MemoryIndexHandle,
13
13
  buildMemoryIndexSchema,
14
14
  } from "@/memory";
15
+ import { setSubscriber, clearSubscriber, type Subscriber } from "@/tracing";
15
16
 
16
17
  import { logger } from "@/lib/logger";
17
18
  import { RThreads } from "@/api/resources/threads";
@@ -33,6 +34,7 @@ export class Kernl extends KernlHooks {
33
34
  private readonly _models: ModelRegistry;
34
35
  private readonly _memopts: MemoryOptions | undefined;
35
36
  private readonly _storopts: StorageOptions | undefined;
37
+ private readonly _subscriber: Subscriber | null = null;
36
38
 
37
39
  readonly storage: KernlStorage;
38
40
  athreads: Map<string, Thread<any, any>> = new Map(); /* active threads */
@@ -60,6 +62,12 @@ export class Kernl extends KernlHooks {
60
62
  this.threads = new RThreads(this.storage.threads);
61
63
  this.agents = new RAgents(this._agents);
62
64
  this.memories = this.initmem();
65
+
66
+ // wire tracing
67
+ if (options.tracer) {
68
+ this._subscriber = options.tracer;
69
+ setSubscriber(this._subscriber);
70
+ }
63
71
  }
64
72
 
65
73
  /**
@@ -196,4 +204,17 @@ export class Kernl extends KernlHooks {
196
204
  encoder,
197
205
  });
198
206
  }
207
+
208
+ /**
209
+ * Gracefully shutdown the Kernl instance.
210
+ * Flushes and shuts down tracing subscribers, closes storage connections.
211
+ */
212
+ async shutdown(timeout?: number): Promise<void> {
213
+ if (this._subscriber) {
214
+ await this._subscriber.flush();
215
+ await this._subscriber.shutdown(timeout);
216
+ clearSubscriber();
217
+ }
218
+ // TODO: close storage connections when storage supports it
219
+ }
199
220
  }
@@ -3,6 +3,7 @@ import { SearchIndex } from "@kernl-sdk/retrieval";
3
3
 
4
4
  import { BaseAgent } from "@/agent/base";
5
5
  import { KernlStorage } from "@/storage";
6
+ import type { Subscriber } from "@/tracing";
6
7
 
7
8
  /**
8
9
  * Storage configuration for Kernl.
@@ -82,6 +83,12 @@ export interface KernlOptions {
82
83
  * Memory system configuration.
83
84
  */
84
85
  memory?: MemoryOptions;
86
+
87
+ /**
88
+ * Tracer for observability. Receives span and event data.
89
+ * Use CompositeTracer to fan out to multiple backends.
90
+ */
91
+ tracer?: Subscriber;
85
92
  }
86
93
 
87
94
  /**
package/src/mcp/http.ts CHANGED
@@ -77,7 +77,6 @@ export class MCPServerStreamableHttp extends BaseMCPServer {
77
77
  throw e;
78
78
  }
79
79
 
80
- this.logger.debug(`Connected to MCP server: ${this.id}`);
81
80
  }
82
81
 
83
82
  /**
@@ -107,7 +106,6 @@ export class MCPServerStreamableHttp extends BaseMCPServer {
107
106
  }
108
107
 
109
108
  const response = await this.session.listTools();
110
- this.logger.debug(`Listed tools: ${JSON.stringify(response)}`);
111
109
  return ListToolsResultSchema.parse(response).tools;
112
110
  }
113
111
 
@@ -136,12 +134,6 @@ export class MCPServerStreamableHttp extends BaseMCPServer {
136
134
  );
137
135
 
138
136
  const parsed = CallToolResultSchema.parse(response);
139
- const result = parsed.content;
140
-
141
- this.logger.debug(
142
- `Called tool ${toolName} (args: ${JSON.stringify(args)}, result: ${JSON.stringify(result)})`,
143
- );
144
-
145
- return result as CallToolResultContent;
137
+ return parsed.content as CallToolResultContent;
146
138
  }
147
139
  }
package/src/mcp/sse.ts CHANGED
@@ -66,8 +66,6 @@ export class MCPServerSSE extends BaseMCPServer {
66
66
  await this.close();
67
67
  throw e;
68
68
  }
69
-
70
- this.logger.debug(`Connected to MCP server: ${this.id}`);
71
69
  }
72
70
 
73
71
  /**
@@ -83,7 +81,6 @@ export class MCPServerSSE extends BaseMCPServer {
83
81
  }
84
82
 
85
83
  const response = await this.session.listTools();
86
- this.logger.debug(`Listed tools: ${JSON.stringify(response)}`);
87
84
  return ListToolsResultSchema.parse(response).tools;
88
85
  }
89
86
 
@@ -112,13 +109,7 @@ export class MCPServerSSE extends BaseMCPServer {
112
109
  );
113
110
 
114
111
  const parsed = CallToolResultSchema.parse(response);
115
- const result = parsed.content;
116
-
117
- this.logger.debug(
118
- `Called tool ${toolName} (args: ${JSON.stringify(args)}, result: ${JSON.stringify(result)})`,
119
- );
120
-
121
- return result as CallToolResultContent;
112
+ return parsed.content as CallToolResultContent;
122
113
  }
123
114
 
124
115
  /**
package/src/mcp/stdio.ts CHANGED
@@ -62,8 +62,6 @@ export class MCPServerStdio extends BaseMCPServer {
62
62
  this.serverInitializeResult = {
63
63
  serverInfo: { name: this.id, version: "1.0.0" },
64
64
  } as InitializeResult;
65
-
66
- this.logger.debug(`Connected to MCP server: ${this.id}`);
67
65
  } catch (e) {
68
66
  this.logger.error("Error initializing MCP server:", e);
69
67
  await this.close();
@@ -82,7 +80,6 @@ export class MCPServerStdio extends BaseMCPServer {
82
80
  }
83
81
 
84
82
  const response = await this.session.listTools();
85
- this.logger.debug(`Listed tools: ${JSON.stringify(response)}`);
86
83
  return ListToolsResultSchema.parse(response).tools;
87
84
  }
88
85
 
@@ -111,13 +108,7 @@ export class MCPServerStdio extends BaseMCPServer {
111
108
  );
112
109
 
113
110
  const parsed = CallToolResultSchema.parse(response);
114
- const result = parsed.content;
115
-
116
- this.logger.debug(
117
- `Called tool ${toolName} (args: ${JSON.stringify(args)}, result: ${JSON.stringify(result)})`,
118
- );
119
-
120
- return result as CallToolResultContent;
111
+ return parsed.content as CallToolResultContent;
121
112
  }
122
113
 
123
114
  /**
package/src/task.ts CHANGED
@@ -8,7 +8,6 @@ import type { Thread } from "@/thread";
8
8
  */
9
9
  export class Task<TContext = UnknownContext, TResult = unknown> {
10
10
  id: string /* unique identifier for this task (pid) */;
11
- // tgid: string | null; /* task groupid */
12
11
  // prio: TaskPriority;
13
12
  instructions:
14
13
  | string
@@ -1060,6 +1060,286 @@ describe("Thread", () => {
1060
1060
  });
1061
1061
  });
1062
1062
 
1063
+ describe("Event Sequencing", () => {
1064
+ it("should assign incrementing seq values to all persisted events", async () => {
1065
+ let callCount = 0;
1066
+
1067
+ const model = createMockModel(async (req: LanguageModelRequest) => {
1068
+ callCount++;
1069
+
1070
+ if (callCount === 1) {
1071
+ return {
1072
+ content: [
1073
+ {
1074
+ kind: "message" as const,
1075
+ id: "msg_1",
1076
+ role: "assistant" as const,
1077
+ content: [],
1078
+ },
1079
+ {
1080
+ kind: "tool.call" as const,
1081
+ toolId: "echo",
1082
+ state: IN_PROGRESS,
1083
+ callId: "call_1",
1084
+ arguments: JSON.stringify({ text: "test" }),
1085
+ },
1086
+ ],
1087
+ finishReason: "stop",
1088
+ usage: { inputTokens: 2, outputTokens: 2, totalTokens: 4 },
1089
+ warnings: [],
1090
+ };
1091
+ }
1092
+
1093
+ return {
1094
+ content: [
1095
+ {
1096
+ kind: "message" as const,
1097
+ id: "msg_2",
1098
+ role: "assistant" as const,
1099
+ content: [{ kind: "text" as const, text: "Done!" }],
1100
+ },
1101
+ ],
1102
+ finishReason: "stop",
1103
+ usage: { inputTokens: 4, outputTokens: 2, totalTokens: 6 },
1104
+ warnings: [],
1105
+ };
1106
+ });
1107
+
1108
+ const echoTool = tool({
1109
+ id: "echo",
1110
+ description: "Echoes input",
1111
+ parameters: z.object({ text: z.string() }),
1112
+ execute: async (ctx, { text }) => `Echo: ${text}`,
1113
+ });
1114
+
1115
+ const agent = new Agent({
1116
+ id: "test",
1117
+ name: "Test",
1118
+ instructions: "Test agent",
1119
+ model,
1120
+ toolkits: [
1121
+ new FunctionToolkit({ id: "test-tools", tools: [echoTool] }),
1122
+ ],
1123
+ });
1124
+
1125
+ const thread = new Thread({ agent, input: userMessage("test") });
1126
+ await thread.execute();
1127
+
1128
+ const history = (thread as any).history as ThreadEvent[];
1129
+
1130
+ // Verify all events have seq values
1131
+ for (const event of history) {
1132
+ expect(event).toHaveProperty("seq");
1133
+ expect(typeof event.seq).toBe("number");
1134
+ }
1135
+
1136
+ // Verify seq values increment: 0, 1, 2, 3, 4
1137
+ const seqValues = history.map((e) => e.seq);
1138
+ expect(seqValues).toEqual([0, 1, 2, 3, 4]);
1139
+ });
1140
+
1141
+ it("should assign consistent tid to all events in a thread", async () => {
1142
+ const model = createMockModel(async (req: LanguageModelRequest) => {
1143
+ return {
1144
+ content: [
1145
+ {
1146
+ kind: "message" as const,
1147
+ id: "msg_1",
1148
+ role: "assistant" as const,
1149
+ content: [{ kind: "text" as const, text: "Hello" }],
1150
+ },
1151
+ ],
1152
+ finishReason: "stop",
1153
+ usage: { inputTokens: 2, outputTokens: 2, totalTokens: 4 },
1154
+ warnings: [],
1155
+ };
1156
+ });
1157
+
1158
+ const agent = new Agent({
1159
+ id: "test",
1160
+ name: "Test",
1161
+ instructions: "Test agent",
1162
+ model,
1163
+ });
1164
+
1165
+ const thread = new Thread({ agent, input: userMessage("test") });
1166
+ await thread.execute();
1167
+
1168
+ const history = (thread as any).history as ThreadEvent[];
1169
+ const threadId = thread.tid;
1170
+
1171
+ // All events should have the same tid as the thread
1172
+ for (const event of history) {
1173
+ expect(event).toHaveProperty("tid");
1174
+ expect(event.tid).toBe(threadId);
1175
+ }
1176
+ });
1177
+
1178
+ it("should assign timestamps to all events", async () => {
1179
+ const model = createMockModel(async (req: LanguageModelRequest) => {
1180
+ return {
1181
+ content: [
1182
+ {
1183
+ kind: "message" as const,
1184
+ id: "msg_1",
1185
+ role: "assistant" as const,
1186
+ content: [{ kind: "text" as const, text: "Hello" }],
1187
+ },
1188
+ ],
1189
+ finishReason: "stop",
1190
+ usage: { inputTokens: 2, outputTokens: 2, totalTokens: 4 },
1191
+ warnings: [],
1192
+ };
1193
+ });
1194
+
1195
+ const agent = new Agent({
1196
+ id: "test",
1197
+ name: "Test",
1198
+ instructions: "Test agent",
1199
+ model,
1200
+ });
1201
+
1202
+ const thread = new Thread({ agent, input: userMessage("test") });
1203
+ await thread.execute();
1204
+
1205
+ const history = (thread as any).history as ThreadEvent[];
1206
+
1207
+ for (const event of history) {
1208
+ expect(event).toHaveProperty("timestamp");
1209
+ expect(event.timestamp).toBeInstanceOf(Date);
1210
+ }
1211
+ });
1212
+
1213
+ it("should generate event ids in expected format", async () => {
1214
+ let callCount = 0;
1215
+
1216
+ const model = createMockModel(async (req: LanguageModelRequest) => {
1217
+ callCount++;
1218
+
1219
+ if (callCount === 1) {
1220
+ return {
1221
+ content: [
1222
+ {
1223
+ kind: "message" as const,
1224
+ id: "msg_1",
1225
+ role: "assistant" as const,
1226
+ content: [],
1227
+ },
1228
+ {
1229
+ kind: "tool.call" as const,
1230
+ toolId: "simple",
1231
+ state: IN_PROGRESS,
1232
+ callId: "call_1",
1233
+ arguments: "{}",
1234
+ },
1235
+ ],
1236
+ finishReason: "stop",
1237
+ usage: { inputTokens: 2, outputTokens: 2, totalTokens: 4 },
1238
+ warnings: [],
1239
+ };
1240
+ }
1241
+
1242
+ return {
1243
+ content: [
1244
+ {
1245
+ kind: "message" as const,
1246
+ id: "msg_2",
1247
+ role: "assistant" as const,
1248
+ content: [{ kind: "text" as const, text: "Done" }],
1249
+ },
1250
+ ],
1251
+ finishReason: "stop",
1252
+ usage: { inputTokens: 2, outputTokens: 2, totalTokens: 4 },
1253
+ warnings: [],
1254
+ };
1255
+ });
1256
+
1257
+ const simpleTool = tool({
1258
+ id: "simple",
1259
+ description: "Simple tool",
1260
+ parameters: undefined,
1261
+ execute: async () => "result",
1262
+ });
1263
+
1264
+ const agent = new Agent({
1265
+ id: "test",
1266
+ name: "Test",
1267
+ instructions: "Test agent",
1268
+ model,
1269
+ toolkits: [
1270
+ new FunctionToolkit({ id: "test-tools", tools: [simpleTool] }),
1271
+ ],
1272
+ });
1273
+
1274
+ const thread = new Thread({ agent, input: userMessage("test") });
1275
+ await thread.execute();
1276
+
1277
+ const history = (thread as any).history as ThreadEvent[];
1278
+
1279
+ // Messages should have id format "message:{original_id}"
1280
+ const messages = history.filter((e) => e.kind === "message");
1281
+ for (const msg of messages) {
1282
+ expect(msg.id).toMatch(/^message:/);
1283
+ }
1284
+
1285
+ // Tool calls use callId (not id), so tevent falls back to randomID()
1286
+ const toolCalls = history.filter((e) => e.kind === "tool.call");
1287
+ for (const tc of toolCalls) {
1288
+ expect(tc.id).toBeDefined();
1289
+ expect(typeof tc.id).toBe("string");
1290
+ }
1291
+
1292
+ // Tool results also use callId, so tevent falls back to randomID()
1293
+ const toolResults = history.filter((e) => e.kind === "tool.result");
1294
+ for (const tr of toolResults) {
1295
+ expect(tr.id).toBeDefined();
1296
+ expect(typeof tr.id).toBe("string");
1297
+ }
1298
+ });
1299
+
1300
+ it("should yield sequenced events during streaming", async () => {
1301
+ const model = createMockModel(async (req: LanguageModelRequest) => {
1302
+ return {
1303
+ content: [
1304
+ {
1305
+ kind: "message" as const,
1306
+ id: "msg_1",
1307
+ role: "assistant" as const,
1308
+ content: [{ kind: "text" as const, text: "Hello" }],
1309
+ },
1310
+ ],
1311
+ finishReason: "stop",
1312
+ usage: { inputTokens: 2, outputTokens: 2, totalTokens: 4 },
1313
+ warnings: [],
1314
+ };
1315
+ });
1316
+
1317
+ const agent = new Agent({
1318
+ id: "test",
1319
+ name: "Test",
1320
+ instructions: "Test agent",
1321
+ model,
1322
+ });
1323
+
1324
+ const thread = new Thread({ agent, input: userMessage("test") });
1325
+
1326
+ const events: any[] = [];
1327
+ for await (const event of thread.stream()) {
1328
+ events.push(event);
1329
+ }
1330
+
1331
+ // Find the complete message event (not deltas)
1332
+ const messageEvent = events.find(
1333
+ (e) => e.kind === "message" && e.role === "assistant",
1334
+ );
1335
+
1336
+ expect(messageEvent).toBeDefined();
1337
+ expect(messageEvent).toHaveProperty("seq");
1338
+ expect(messageEvent).toHaveProperty("tid");
1339
+ expect(messageEvent).toHaveProperty("timestamp");
1340
+ });
1341
+ });
1342
+
1063
1343
  describe("Final Output Parsing", () => {
1064
1344
  it("should return text output when output is 'text'", async () => {
1065
1345
  const model = createMockModel(async (req: LanguageModelRequest) => {