kernl 0.12.4 → 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.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +12 -0
- package/README.md +29 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +2 -0
- package/dist/kernl/kernl.d.ts +6 -0
- package/dist/kernl/kernl.d.ts.map +1 -1
- package/dist/kernl/kernl.js +19 -0
- package/dist/kernl/types.d.ts +6 -0
- package/dist/kernl/types.d.ts.map +1 -1
- package/dist/lib/env.d.ts +2 -2
- package/dist/mcp/http.d.ts.map +1 -1
- package/dist/mcp/http.js +1 -5
- package/dist/mcp/sse.d.ts.map +1 -1
- package/dist/mcp/sse.js +1 -5
- package/dist/mcp/stdio.d.ts.map +1 -1
- package/dist/mcp/stdio.js +1 -5
- package/dist/task.d.ts.map +1 -1
- package/dist/task.js +0 -1
- package/dist/thread/thread.d.ts +5 -4
- package/dist/thread/thread.d.ts.map +1 -1
- package/dist/thread/thread.js +91 -22
- package/dist/thread/types.d.ts +5 -0
- package/dist/thread/types.d.ts.map +1 -1
- package/dist/tracing/__tests__/composite.test.d.ts +2 -0
- package/dist/tracing/__tests__/composite.test.d.ts.map +1 -0
- package/dist/tracing/__tests__/composite.test.js +146 -0
- package/dist/tracing/__tests__/dispatch.test.d.ts +2 -0
- package/dist/tracing/__tests__/dispatch.test.d.ts.map +1 -0
- package/dist/tracing/__tests__/dispatch.test.js +160 -0
- package/dist/tracing/__tests__/helpers.d.ts +69 -0
- package/dist/tracing/__tests__/helpers.d.ts.map +1 -0
- package/dist/tracing/__tests__/helpers.js +109 -0
- package/dist/tracing/__tests__/integration.test.d.ts +2 -0
- package/dist/tracing/__tests__/integration.test.d.ts.map +1 -0
- package/dist/tracing/__tests__/integration.test.js +675 -0
- package/dist/tracing/__tests__/span.test.d.ts +2 -0
- package/dist/tracing/__tests__/span.test.d.ts.map +1 -0
- package/dist/tracing/__tests__/span.test.js +188 -0
- package/dist/tracing/dispatch.d.ts +43 -0
- package/dist/tracing/dispatch.d.ts.map +1 -0
- package/dist/tracing/dispatch.js +70 -0
- package/dist/tracing/index.d.ts +8 -0
- package/dist/tracing/index.d.ts.map +1 -0
- package/dist/tracing/index.js +6 -0
- package/dist/tracing/span.d.ts +69 -0
- package/dist/tracing/span.d.ts.map +1 -0
- package/dist/tracing/span.js +64 -0
- package/dist/tracing/subscriber.d.ts +53 -0
- package/dist/tracing/subscriber.d.ts.map +1 -0
- package/dist/tracing/subscriber.js +1 -0
- package/dist/tracing/subscribers/composite.d.ts +26 -0
- package/dist/tracing/subscribers/composite.d.ts.map +1 -0
- package/dist/tracing/subscribers/composite.js +96 -0
- package/dist/tracing/subscribers/console.d.ts +22 -0
- package/dist/tracing/subscribers/console.d.ts.map +1 -0
- package/dist/tracing/subscribers/console.js +82 -0
- package/dist/tracing/types.d.ts +77 -0
- package/dist/tracing/types.d.ts.map +1 -0
- package/dist/tracing/types.js +1 -0
- package/package.json +5 -1
- package/src/agent.ts +2 -0
- package/src/index.ts +1 -0
- package/src/kernl/kernl.ts +21 -0
- package/src/kernl/types.ts +7 -0
- package/src/mcp/http.ts +1 -9
- package/src/mcp/sse.ts +1 -10
- package/src/mcp/stdio.ts +1 -10
- package/src/task.ts +0 -1
- package/src/thread/thread.ts +111 -24
- package/src/thread/types.ts +5 -0
- package/src/tracing/__tests__/composite.test.ts +218 -0
- package/src/tracing/__tests__/dispatch.test.ts +222 -0
- package/src/tracing/__tests__/helpers.ts +138 -0
- package/src/tracing/__tests__/integration.test.ts +808 -0
- package/src/tracing/__tests__/span.test.ts +250 -0
- package/src/tracing/dispatch.ts +114 -0
- package/src/tracing/index.ts +39 -0
- package/src/tracing/span.ts +115 -0
- package/src/tracing/subscriber.ts +62 -0
- package/src/tracing/subscribers/composite.ts +102 -0
- package/src/tracing/subscribers/console.ts +101 -0
- package/src/tracing/types.ts +115 -0
- package/dist/trace/processor.d.ts +0 -1
- package/dist/trace/processor.d.ts.map +0 -1
- package/dist/trace/processor.js +0 -1
- package/dist/trace/traces.d.ts +0 -1
- package/dist/trace/traces.d.ts.map +0 -1
- package/dist/trace/traces.js +0 -73
- package/dist/trace/utils.d.ts +0 -22
- package/dist/trace/utils.d.ts.map +0 -1
- package/dist/trace/utils.js +0 -30
- package/src/trace/processor.ts +0 -0
- package/src/trace/traces.ts +0 -86
- 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
|
+
"version": "0.12.6",
|
|
4
4
|
"description": "A modern AI agent framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"kernl",
|
|
@@ -29,6 +29,10 @@
|
|
|
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": {
|
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
package/src/kernl/kernl.ts
CHANGED
|
@@ -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
|
}
|
package/src/kernl/types.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
package/src/thread/thread.ts
CHANGED
|
@@ -7,6 +7,14 @@ import { Context } from "@/context";
|
|
|
7
7
|
import type { Task } from "@/task";
|
|
8
8
|
import type { ResolvedAgentResponse } from "@/guardrail";
|
|
9
9
|
import type { ThreadStore } from "@/storage";
|
|
10
|
+
import {
|
|
11
|
+
span,
|
|
12
|
+
event,
|
|
13
|
+
run,
|
|
14
|
+
type Span,
|
|
15
|
+
type ModelCallSpan,
|
|
16
|
+
type ToolCallSpan,
|
|
17
|
+
} from "@/tracing";
|
|
10
18
|
|
|
11
19
|
import { logger } from "@/lib/logger";
|
|
12
20
|
|
|
@@ -22,6 +30,7 @@ import {
|
|
|
22
30
|
LanguageModelStreamEvent,
|
|
23
31
|
type LanguageModelUsage,
|
|
24
32
|
type LanguageModelFinishReason,
|
|
33
|
+
type LanguageModelResponseItem,
|
|
25
34
|
} from "@kernl-sdk/protocol";
|
|
26
35
|
import { randomID, filter } from "@kernl-sdk/shared/lib";
|
|
27
36
|
|
|
@@ -111,8 +120,9 @@ export class Thread<
|
|
|
111
120
|
private history: ThreadEvent[] /* history representing the event log for the thread */;
|
|
112
121
|
private tickres?: ResolvedAgentResponse<TOutput>; /* final result from terminal tick */
|
|
113
122
|
|
|
114
|
-
private
|
|
123
|
+
private _abort?: AbortSignal;
|
|
115
124
|
private storage?: ThreadStore;
|
|
125
|
+
private _span?: Span; /* tracing span for current execution */
|
|
116
126
|
|
|
117
127
|
constructor(options: ThreadOptions<TContext, TOutput>) {
|
|
118
128
|
this.tid = options.tid ?? `tid_${randomID()}`;
|
|
@@ -134,6 +144,7 @@ export class Thread<
|
|
|
134
144
|
this.cpbuf = [];
|
|
135
145
|
this.persisted = options.persisted ?? false;
|
|
136
146
|
this.history = options.history ?? [];
|
|
147
|
+
this._abort = options.abort;
|
|
137
148
|
|
|
138
149
|
// seek to latest seq (not persisted)
|
|
139
150
|
if (this.history.length > 0) {
|
|
@@ -168,24 +179,42 @@ export class Thread<
|
|
|
168
179
|
* - Exactly one thread.stop (with result on success, error on failure)
|
|
169
180
|
*/
|
|
170
181
|
async *stream(): AsyncIterable<ThreadStreamEvent> {
|
|
171
|
-
if (this.state === RUNNING
|
|
182
|
+
if (this.state === RUNNING) {
|
|
172
183
|
throw new Error("thread already running");
|
|
173
184
|
}
|
|
174
185
|
|
|
175
186
|
this.state = RUNNING;
|
|
176
|
-
this.abort = new AbortController();
|
|
177
187
|
this.tickres = undefined; // reset for this run
|
|
178
188
|
|
|
179
189
|
await this.checkpoint(); /* c1: persist RUNNING state + initial input */
|
|
180
190
|
|
|
181
|
-
this
|
|
191
|
+
// create thread span (root span for this execution)
|
|
192
|
+
this._span = span(
|
|
193
|
+
{
|
|
194
|
+
kind: "thread",
|
|
195
|
+
threadId: this.tid,
|
|
196
|
+
agentId: this.agent.id,
|
|
197
|
+
namespace: this.namespace,
|
|
198
|
+
context: this.context.context,
|
|
199
|
+
},
|
|
200
|
+
null,
|
|
201
|
+
);
|
|
202
|
+
this._span.enter();
|
|
182
203
|
|
|
204
|
+
this.emit("thread.start");
|
|
183
205
|
yield { kind: "stream.start" }; // always yield start immediately
|
|
184
206
|
|
|
185
207
|
try {
|
|
186
208
|
yield* this._execute();
|
|
209
|
+
this._span.record({ state: "stopped", result: this.tickres });
|
|
187
210
|
this.emit("thread.stop", { state: STOPPED, result: this.tickres });
|
|
188
211
|
} catch (err) {
|
|
212
|
+
this._span.error(err instanceof Error ? err : new Error(String(err)));
|
|
213
|
+
event({
|
|
214
|
+
kind: "thread.error",
|
|
215
|
+
message: err instanceof Error ? err.message : String(err),
|
|
216
|
+
stack: err instanceof Error ? err.stack : undefined,
|
|
217
|
+
});
|
|
189
218
|
this.emit("thread.stop", {
|
|
190
219
|
state: STOPPED,
|
|
191
220
|
error: err instanceof Error ? err.message : String(err),
|
|
@@ -193,7 +222,9 @@ export class Thread<
|
|
|
193
222
|
throw err;
|
|
194
223
|
} finally {
|
|
195
224
|
this.state = STOPPED;
|
|
196
|
-
this.
|
|
225
|
+
this._span.close();
|
|
226
|
+
// (TODO): questionable whether this should be undefined. perhaps a single thread should exit + resume..
|
|
227
|
+
this._span = undefined;
|
|
197
228
|
await this.checkpoint(); /* c4: final checkpoint - persist STOPPED state */
|
|
198
229
|
}
|
|
199
230
|
}
|
|
@@ -208,7 +239,7 @@ export class Thread<
|
|
|
208
239
|
for (;;) {
|
|
209
240
|
let err: Error | undefined = undefined;
|
|
210
241
|
|
|
211
|
-
if (this.
|
|
242
|
+
if (this._abort?.aborted) {
|
|
212
243
|
return;
|
|
213
244
|
}
|
|
214
245
|
|
|
@@ -286,37 +317,70 @@ export class Thread<
|
|
|
286
317
|
|
|
287
318
|
const req = await this.prepareModelRequest(this.history);
|
|
288
319
|
|
|
320
|
+
const s = span<ModelCallSpan>(
|
|
321
|
+
{
|
|
322
|
+
kind: "model.call",
|
|
323
|
+
provider: this.model.provider,
|
|
324
|
+
modelId: this.model.modelId,
|
|
325
|
+
request: {
|
|
326
|
+
input: req.input,
|
|
327
|
+
settings: req.settings,
|
|
328
|
+
responseType: req.responseType,
|
|
329
|
+
tools: req.tools,
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
this._span!.id,
|
|
333
|
+
);
|
|
334
|
+
s.enter();
|
|
335
|
+
|
|
289
336
|
this.emit("model.call.start", { settings: req.settings ?? {} });
|
|
290
337
|
|
|
338
|
+
// tracing / observability
|
|
339
|
+
const content: LanguageModelResponseItem[] = [];
|
|
291
340
|
let usage: LanguageModelUsage | undefined;
|
|
292
|
-
let finishReason: LanguageModelFinishReason = {
|
|
341
|
+
let finishReason: LanguageModelFinishReason = {
|
|
342
|
+
unified: "other",
|
|
343
|
+
raw: undefined,
|
|
344
|
+
};
|
|
293
345
|
|
|
294
346
|
try {
|
|
295
347
|
if (this.model.stream) {
|
|
296
|
-
for await (const
|
|
297
|
-
if (
|
|
298
|
-
usage =
|
|
299
|
-
finishReason =
|
|
348
|
+
for await (const e of this.model.stream(req)) {
|
|
349
|
+
if (e.kind === "finish") {
|
|
350
|
+
usage = e.usage;
|
|
351
|
+
finishReason = e.finishReason;
|
|
300
352
|
}
|
|
301
|
-
|
|
353
|
+
if (notDelta(e)) content.push(e as LanguageModelResponseItem);
|
|
354
|
+
yield e;
|
|
302
355
|
}
|
|
303
356
|
} else {
|
|
304
357
|
// fallback: blocking generate, yield events as batch
|
|
305
358
|
const res = await this.model.generate(req);
|
|
306
359
|
usage = res.usage;
|
|
307
360
|
finishReason = res.finishReason;
|
|
308
|
-
for (const
|
|
309
|
-
|
|
361
|
+
for (const e of res.content) {
|
|
362
|
+
content.push(e);
|
|
363
|
+
yield e;
|
|
310
364
|
}
|
|
311
365
|
}
|
|
312
366
|
|
|
367
|
+
s.record({
|
|
368
|
+
response: {
|
|
369
|
+
content,
|
|
370
|
+
finishReason,
|
|
371
|
+
usage,
|
|
372
|
+
},
|
|
373
|
+
});
|
|
313
374
|
this.emit("model.call.end", { finishReason, usage });
|
|
314
375
|
} catch (error) {
|
|
376
|
+
s.error(error instanceof Error ? error : new Error(String(error)));
|
|
315
377
|
this.emit("model.call.end", { finishReason: "error" });
|
|
316
378
|
yield {
|
|
317
379
|
kind: "error",
|
|
318
380
|
error: error instanceof Error ? error : new Error(String(error)),
|
|
319
381
|
};
|
|
382
|
+
} finally {
|
|
383
|
+
s.close();
|
|
320
384
|
}
|
|
321
385
|
}
|
|
322
386
|
|
|
@@ -390,12 +454,12 @@ export class Thread<
|
|
|
390
454
|
}
|
|
391
455
|
|
|
392
456
|
/**
|
|
393
|
-
*
|
|
457
|
+
* Abort the running thread.
|
|
394
458
|
*
|
|
395
|
-
*
|
|
459
|
+
* @throws {Error} Not implemented - use AbortSignal via options instead
|
|
396
460
|
*/
|
|
397
|
-
|
|
398
|
-
|
|
461
|
+
abort() {
|
|
462
|
+
throw new Error("Not implemented: use AbortSignal via ThreadExecuteOptions");
|
|
399
463
|
}
|
|
400
464
|
|
|
401
465
|
/**
|
|
@@ -478,6 +542,18 @@ export class Thread<
|
|
|
478
542
|
calls.map(async (call: ToolCall) => {
|
|
479
543
|
const parsedArgs = JSON.parse(call.arguments || "{}");
|
|
480
544
|
|
|
545
|
+
// create tool.call span
|
|
546
|
+
const s = span<ToolCallSpan>(
|
|
547
|
+
{
|
|
548
|
+
kind: "tool.call",
|
|
549
|
+
toolId: call.toolId,
|
|
550
|
+
callId: call.callId,
|
|
551
|
+
args: parsedArgs,
|
|
552
|
+
},
|
|
553
|
+
this._span!.id,
|
|
554
|
+
);
|
|
555
|
+
s.enter();
|
|
556
|
+
|
|
481
557
|
this.emit("tool.call.start", {
|
|
482
558
|
toolId: call.toolId,
|
|
483
559
|
callId: call.callId,
|
|
@@ -501,16 +577,20 @@ export class Thread<
|
|
|
501
577
|
const ctx = new Context(this.namespace, this.context.context);
|
|
502
578
|
ctx.agent = this.agent;
|
|
503
579
|
ctx.approve(call.callId); // mark this call as approved
|
|
580
|
+
|
|
504
581
|
const res = await tool.invoke(ctx, call.arguments, call.callId);
|
|
505
582
|
|
|
583
|
+
s.record({
|
|
584
|
+
state: res.state,
|
|
585
|
+
result: res.result,
|
|
586
|
+
error: res.error,
|
|
587
|
+
});
|
|
588
|
+
|
|
506
589
|
this.emit("tool.call.end", {
|
|
507
590
|
toolId: call.toolId,
|
|
508
591
|
callId: call.callId,
|
|
509
592
|
state: res.state,
|
|
510
|
-
result:
|
|
511
|
-
typeof res.result === "string"
|
|
512
|
-
? res.result
|
|
513
|
-
: JSON.stringify(res.result),
|
|
593
|
+
result: res.result,
|
|
514
594
|
error: res.error,
|
|
515
595
|
});
|
|
516
596
|
|
|
@@ -523,11 +603,15 @@ export class Thread<
|
|
|
523
603
|
error: res.error,
|
|
524
604
|
};
|
|
525
605
|
} catch (error) {
|
|
606
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
607
|
+
s.error(error instanceof Error ? error : new Error(errMsg));
|
|
608
|
+
s.record({ state: "failed", error: errMsg });
|
|
609
|
+
|
|
526
610
|
this.emit("tool.call.end", {
|
|
527
611
|
toolId: call.toolId,
|
|
528
612
|
callId: call.callId,
|
|
529
613
|
state: FAILED,
|
|
530
|
-
error:
|
|
614
|
+
error: errMsg,
|
|
531
615
|
});
|
|
532
616
|
|
|
533
617
|
return {
|
|
@@ -536,8 +620,10 @@ export class Thread<
|
|
|
536
620
|
toolId: call.toolId,
|
|
537
621
|
state: FAILED,
|
|
538
622
|
result: undefined as any,
|
|
539
|
-
error:
|
|
623
|
+
error: errMsg,
|
|
540
624
|
};
|
|
625
|
+
} finally {
|
|
626
|
+
s.close();
|
|
541
627
|
}
|
|
542
628
|
}),
|
|
543
629
|
);
|
|
@@ -598,6 +684,7 @@ export class Thread<
|
|
|
598
684
|
settings,
|
|
599
685
|
tools,
|
|
600
686
|
responseType,
|
|
687
|
+
abort: this._abort,
|
|
601
688
|
};
|
|
602
689
|
}
|
|
603
690
|
}
|
package/src/thread/types.ts
CHANGED
|
@@ -219,6 +219,11 @@ export interface ThreadOptions<
|
|
|
219
219
|
* hydrating from a store. Callers creating new threads should omit it.
|
|
220
220
|
*/
|
|
221
221
|
persisted?: boolean;
|
|
222
|
+
/**
|
|
223
|
+
* Abort signal for cancelling thread execution.
|
|
224
|
+
* When aborted, the thread will stop at the next safe point.
|
|
225
|
+
*/
|
|
226
|
+
abort?: AbortSignal;
|
|
222
227
|
}
|
|
223
228
|
|
|
224
229
|
/**
|