@agentick/kernel 0.0.1
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/LICENSE +21 -0
- package/README.md +401 -0
- package/dist/.tsbuildinfo.build +1 -0
- package/dist/channel-helpers.d.ts +32 -0
- package/dist/channel-helpers.d.ts.map +1 -0
- package/dist/channel-helpers.js +62 -0
- package/dist/channel-helpers.js.map +1 -0
- package/dist/channel.d.ts +164 -0
- package/dist/channel.d.ts.map +1 -0
- package/dist/channel.js +199 -0
- package/dist/channel.js.map +1 -0
- package/dist/context.d.ts +412 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +289 -0
- package/dist/context.js.map +1 -0
- package/dist/event-buffer.d.ts +208 -0
- package/dist/event-buffer.d.ts.map +1 -0
- package/dist/event-buffer.js +335 -0
- package/dist/event-buffer.js.map +1 -0
- package/dist/execution-helpers.d.ts +179 -0
- package/dist/execution-helpers.d.ts.map +1 -0
- package/dist/execution-helpers.js +212 -0
- package/dist/execution-helpers.js.map +1 -0
- package/dist/execution-tracker.d.ts +61 -0
- package/dist/execution-tracker.d.ts.map +1 -0
- package/dist/execution-tracker.js +319 -0
- package/dist/execution-tracker.js.map +1 -0
- package/dist/guard.d.ts +65 -0
- package/dist/guard.d.ts.map +1 -0
- package/dist/guard.js +15 -0
- package/dist/guard.js.map +1 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +341 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +346 -0
- package/dist/logger.js.map +1 -0
- package/dist/metrics-helpers.d.ts +40 -0
- package/dist/metrics-helpers.d.ts.map +1 -0
- package/dist/metrics-helpers.js +72 -0
- package/dist/metrics-helpers.js.map +1 -0
- package/dist/otel-provider.d.ts +54 -0
- package/dist/otel-provider.d.ts.map +1 -0
- package/dist/otel-provider.js +107 -0
- package/dist/otel-provider.js.map +1 -0
- package/dist/procedure-graph.d.ts +136 -0
- package/dist/procedure-graph.d.ts.map +1 -0
- package/dist/procedure-graph.js +272 -0
- package/dist/procedure-graph.js.map +1 -0
- package/dist/procedure.d.ts +757 -0
- package/dist/procedure.d.ts.map +1 -0
- package/dist/procedure.js +895 -0
- package/dist/procedure.js.map +1 -0
- package/dist/schema.d.ts +153 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +385 -0
- package/dist/schema.js.map +1 -0
- package/dist/stream.d.ts +106 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/stream.js +186 -0
- package/dist/stream.js.map +1 -0
- package/dist/telemetry.d.ts +182 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +124 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/testing.d.ts +55 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +96 -0
- package/dist/testing.js.map +1 -0
- package/package.json +48 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Agentick Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
# @agentick/kernel
|
|
2
|
+
|
|
3
|
+
Low-level execution primitives for Agentick. Provides procedures, async context management, schema validation, logging, telemetry, and event streaming.
|
|
4
|
+
|
|
5
|
+
> **Note:** Most applications should use `@agentick/core` instead. This package is the foundation that core builds upon.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add @agentick/kernel
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Core Primitives
|
|
14
|
+
|
|
15
|
+
### Procedures
|
|
16
|
+
|
|
17
|
+
Procedures wrap async functions with middleware, validation, and execution control:
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { createProcedure } from "@agentick/kernel";
|
|
21
|
+
import { z } from "zod";
|
|
22
|
+
|
|
23
|
+
const fetchUser = createProcedure(
|
|
24
|
+
{
|
|
25
|
+
name: "fetchUser",
|
|
26
|
+
schema: z.object({ id: z.string() }),
|
|
27
|
+
},
|
|
28
|
+
async ({ id }) => {
|
|
29
|
+
return await db.users.find(id);
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
// Execute
|
|
34
|
+
const user = await fetchUser({ id: "123" });
|
|
35
|
+
|
|
36
|
+
// With middleware
|
|
37
|
+
const withLogging = fetchUser.use(async (args, ctx, next) => {
|
|
38
|
+
console.log("Fetching user:", args.id);
|
|
39
|
+
const result = await next(args);
|
|
40
|
+
console.log("Found:", result);
|
|
41
|
+
return result;
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
#### ExecutionHandle
|
|
46
|
+
|
|
47
|
+
Procedures are callable directly. You can also use `.exec()`:
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// Direct call (preferred)
|
|
51
|
+
const handle = await fetchUser({ id: "123" });
|
|
52
|
+
|
|
53
|
+
// Or explicit .exec()
|
|
54
|
+
const handle = await fetchUser.exec({ id: "123" });
|
|
55
|
+
|
|
56
|
+
// Check status
|
|
57
|
+
console.log(handle.status); // "pending" | "running" | "completed" | "error"
|
|
58
|
+
|
|
59
|
+
// Abort if needed
|
|
60
|
+
handle.abort();
|
|
61
|
+
|
|
62
|
+
// Wait for result
|
|
63
|
+
const user = await handle.result;
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
#### Composition
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { pipe, compose } from "@agentick/kernel";
|
|
70
|
+
|
|
71
|
+
// Chain procedures left-to-right
|
|
72
|
+
const pipeline = pipe(validate, transform, save);
|
|
73
|
+
|
|
74
|
+
// Or right-to-left (functional style)
|
|
75
|
+
const composed = compose(save, transform, validate);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Context (AsyncLocalStorage)
|
|
79
|
+
|
|
80
|
+
Request-scoped state that flows through async operations automatically:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import { Context } from "@agentick/kernel";
|
|
84
|
+
|
|
85
|
+
// Create and run within context
|
|
86
|
+
Context.run({ user: { id: "123" }, metadata: { traceId: "abc" } }, async () => {
|
|
87
|
+
const ctx = Context.get();
|
|
88
|
+
console.log(ctx.user?.id); // "123"
|
|
89
|
+
|
|
90
|
+
// Context propagates through async calls
|
|
91
|
+
await someAsyncOperation(); // Still has access to context
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Fork for parallel execution (safe isolation)
|
|
95
|
+
await Context.fork({ metadata: { branch: "A" } }, async () => {
|
|
96
|
+
// Child context with overrides
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
#### Global Event Subscribers
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
// Subscribe to all context events (useful for DevTools/telemetry)
|
|
104
|
+
const unsubscribe = Context.subscribeGlobal((event) => {
|
|
105
|
+
console.log(event.type, event.payload);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Emit events from anywhere
|
|
109
|
+
Context.emit("custom:event", { data: "value" });
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Schema Validation
|
|
113
|
+
|
|
114
|
+
Unified handling for Zod 3, Zod 4, and Standard Schema:
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
import { detectSchemaType, toJSONSchema, validateSchema, parseSchema } from "@agentick/kernel";
|
|
118
|
+
|
|
119
|
+
// Detect schema type
|
|
120
|
+
const type = detectSchemaType(schema); // "zod3" | "zod4" | "standard-schema" | "json-schema"
|
|
121
|
+
|
|
122
|
+
// Convert to JSON Schema
|
|
123
|
+
const jsonSchema = toJSONSchema(myZodSchema);
|
|
124
|
+
|
|
125
|
+
// Validate (returns result object)
|
|
126
|
+
const result = validateSchema(schema, data);
|
|
127
|
+
if (result.success) {
|
|
128
|
+
console.log(result.data);
|
|
129
|
+
} else {
|
|
130
|
+
console.log(result.issues);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Parse (throws on failure)
|
|
134
|
+
const data = parseSchema(schema, input);
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Logging
|
|
138
|
+
|
|
139
|
+
Structured logging with automatic context injection:
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
import { Logger } from "@agentick/kernel";
|
|
143
|
+
|
|
144
|
+
// Configure globally
|
|
145
|
+
Logger.configure({
|
|
146
|
+
level: "info",
|
|
147
|
+
transport: "pretty", // or "json"
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// Get context-aware logger
|
|
151
|
+
const log = Logger.get();
|
|
152
|
+
log.info("Processing request", { userId: "123" });
|
|
153
|
+
|
|
154
|
+
// Scoped logger
|
|
155
|
+
const dbLog = Logger.for("database");
|
|
156
|
+
dbLog.debug("Query executed", { query, duration });
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Telemetry
|
|
160
|
+
|
|
161
|
+
Spans and metrics for observability:
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
import { Telemetry } from "@agentick/kernel";
|
|
165
|
+
|
|
166
|
+
// Start a trace
|
|
167
|
+
const trace = Telemetry.startTrace("handle-request");
|
|
168
|
+
|
|
169
|
+
// Create spans
|
|
170
|
+
const span = Telemetry.startSpan("fetch-user");
|
|
171
|
+
span.setAttribute("userId", "123");
|
|
172
|
+
try {
|
|
173
|
+
// ... work
|
|
174
|
+
} catch (error) {
|
|
175
|
+
span.recordError(error);
|
|
176
|
+
} finally {
|
|
177
|
+
span.end();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Metrics
|
|
181
|
+
const requestCounter = Telemetry.getCounter("requests_total");
|
|
182
|
+
requestCounter.add(1, { method: "POST" });
|
|
183
|
+
|
|
184
|
+
const latencyHistogram = Telemetry.getHistogram("request_duration_ms");
|
|
185
|
+
latencyHistogram.record(42, { endpoint: "/api/users" });
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Channels
|
|
189
|
+
|
|
190
|
+
Bidirectional communication for real-time updates:
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
import { Channel } from "@agentick/kernel";
|
|
194
|
+
|
|
195
|
+
const channel = new Channel();
|
|
196
|
+
|
|
197
|
+
// Subscribe
|
|
198
|
+
channel.on("message", (payload) => {
|
|
199
|
+
console.log("Received:", payload);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// Publish
|
|
203
|
+
channel.emit("message", { text: "Hello" });
|
|
204
|
+
|
|
205
|
+
// Request/response pattern
|
|
206
|
+
const response = await channel.request("getUser", { id: "123" }, 5000);
|
|
207
|
+
|
|
208
|
+
// Broadcast to all
|
|
209
|
+
channel.broadcast("notification", { message: "System update" });
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### EventBuffer
|
|
213
|
+
|
|
214
|
+
Type-safe event streaming with replay:
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
import { EventBuffer } from "@agentick/kernel";
|
|
218
|
+
|
|
219
|
+
type MyEvent =
|
|
220
|
+
| { type: "start"; id: string }
|
|
221
|
+
| { type: "progress"; percent: number }
|
|
222
|
+
| { type: "complete"; result: unknown };
|
|
223
|
+
|
|
224
|
+
const buffer = new EventBuffer<MyEvent>();
|
|
225
|
+
|
|
226
|
+
// Subscribe with type narrowing
|
|
227
|
+
buffer.on("progress", (event) => {
|
|
228
|
+
console.log(`${event.percent}% complete`);
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// Late subscribers can replay
|
|
232
|
+
buffer.onReplay("start", (event) => {
|
|
233
|
+
console.log("Started:", event.id);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// Async iteration
|
|
237
|
+
for await (const event of buffer) {
|
|
238
|
+
console.log(event.type);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Push events
|
|
242
|
+
buffer.push({ type: "start", id: "123" });
|
|
243
|
+
buffer.push({ type: "progress", percent: 50 });
|
|
244
|
+
buffer.push({ type: "complete", result: { success: true } });
|
|
245
|
+
|
|
246
|
+
// Close when done
|
|
247
|
+
buffer.close();
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Guards
|
|
251
|
+
|
|
252
|
+
Gate procedure execution with access control checks:
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
import { createGuard, GuardError } from "@agentick/kernel";
|
|
256
|
+
|
|
257
|
+
// Simple predicate — deny throws GuardError
|
|
258
|
+
const adminOnly = createGuard(
|
|
259
|
+
(envelope) => envelope.context.user?.roles?.includes("admin") ?? false,
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
// With config — custom reason and guard type
|
|
263
|
+
const roleGuard = createGuard(
|
|
264
|
+
{
|
|
265
|
+
name: "role-guard",
|
|
266
|
+
guardType: "role",
|
|
267
|
+
reason: (envelope) => `User ${envelope.context.user?.id} lacks required role`,
|
|
268
|
+
},
|
|
269
|
+
(envelope) => envelope.context.user?.roles?.includes("admin") ?? false,
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
// Throw GuardError directly for full control
|
|
273
|
+
const customGuard = createGuard({ name: "acl-guard" }, (envelope) => {
|
|
274
|
+
if (!hasPermission(envelope.context.user)) {
|
|
275
|
+
throw GuardError.role(["admin", "moderator"]);
|
|
276
|
+
}
|
|
277
|
+
return true;
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
// Apply to any procedure via .use()
|
|
281
|
+
const secured = fetchUser.use(adminOnly);
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
Guards are middleware — they compose with `.use()` like any other middleware but are purpose-built for allow/deny decisions.
|
|
285
|
+
|
|
286
|
+
#### GuardError
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
import { GuardError, isGuardError } from "@agentick/kernel";
|
|
290
|
+
|
|
291
|
+
// Factories
|
|
292
|
+
GuardError.role(["admin"]); // "Requires one of roles [admin]"
|
|
293
|
+
GuardError.denied("Custom reason"); // Custom denial
|
|
294
|
+
|
|
295
|
+
// Type guard
|
|
296
|
+
if (isGuardError(error)) {
|
|
297
|
+
error.code; // "GUARD_DENIED"
|
|
298
|
+
error.guardType; // "role", "custom", etc.
|
|
299
|
+
error.details; // { roles: [...], guard: "name", ... }
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## Key Patterns
|
|
304
|
+
|
|
305
|
+
### Middleware Pipelines
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
import { createPipeline } from "@agentick/kernel";
|
|
309
|
+
|
|
310
|
+
const authPipeline = createPipeline([
|
|
311
|
+
async (args, ctx, next) => {
|
|
312
|
+
if (!ctx.user) throw new Error("Unauthorized");
|
|
313
|
+
return next(args);
|
|
314
|
+
},
|
|
315
|
+
async (args, ctx, next) => {
|
|
316
|
+
ctx.metadata.startTime = Date.now();
|
|
317
|
+
return next(args);
|
|
318
|
+
},
|
|
319
|
+
]);
|
|
320
|
+
|
|
321
|
+
// Apply to any procedure
|
|
322
|
+
const securedFetch = fetchUser.use(authPipeline);
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Immutable Composition
|
|
326
|
+
|
|
327
|
+
All procedure methods return new instances:
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
const base = createProcedure({ name: "base" }, handler);
|
|
331
|
+
const withTimeout = base.withTimeout(5000);
|
|
332
|
+
const withContext = withTimeout.withContext({ tenant: "acme" });
|
|
333
|
+
|
|
334
|
+
// Original unchanged
|
|
335
|
+
console.log(base === withTimeout); // false
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
## API Reference
|
|
339
|
+
|
|
340
|
+
### Procedures
|
|
341
|
+
|
|
342
|
+
| Export | Description |
|
|
343
|
+
| ----------------------------------- | ----------------------- |
|
|
344
|
+
| `createProcedure(options, handler)` | Create a procedure |
|
|
345
|
+
| `createHook(options, handler)` | Create a hook procedure |
|
|
346
|
+
| `pipe(...procedures)` | Chain left-to-right |
|
|
347
|
+
| `compose(...procedures)` | Chain right-to-left |
|
|
348
|
+
| `createPipeline(middleware)` | Bundle middleware |
|
|
349
|
+
|
|
350
|
+
### Guards
|
|
351
|
+
|
|
352
|
+
| Export | Description |
|
|
353
|
+
| --------------------------- | --------------------------- |
|
|
354
|
+
| `createGuard(fn)` | Create guard from predicate |
|
|
355
|
+
| `createGuard(config, fn)` | Create guard with config |
|
|
356
|
+
| `GuardError` | Access denied error class |
|
|
357
|
+
| `GuardError.role(roles)` | Role-based denial factory |
|
|
358
|
+
| `GuardError.denied(reason)` | Custom denial factory |
|
|
359
|
+
| `isGuardError(error)` | Type guard for GuardError |
|
|
360
|
+
|
|
361
|
+
### Context
|
|
362
|
+
|
|
363
|
+
| Export | Description |
|
|
364
|
+
| ------------------------------------ | --------------------------- |
|
|
365
|
+
| `Context.create(overrides?)` | Create root context |
|
|
366
|
+
| `Context.run(context, fn)` | Run within context |
|
|
367
|
+
| `Context.fork(overrides, fn)` | Fork for parallel execution |
|
|
368
|
+
| `Context.get()` / `Context.tryGet()` | Access current context |
|
|
369
|
+
| `Context.emit(type, payload)` | Emit event |
|
|
370
|
+
| `Context.subscribeGlobal(handler)` | Subscribe to all events |
|
|
371
|
+
|
|
372
|
+
### Schema
|
|
373
|
+
|
|
374
|
+
| Export | Description |
|
|
375
|
+
| ------------------------------- | --------------------------- |
|
|
376
|
+
| `detectSchemaType(schema)` | Identify schema type |
|
|
377
|
+
| `toJSONSchema(schema)` | Convert to JSON Schema |
|
|
378
|
+
| `validateSchema(schema, value)` | Validate with result object |
|
|
379
|
+
| `parseSchema(schema, value)` | Parse or throw |
|
|
380
|
+
|
|
381
|
+
### Logging & Telemetry
|
|
382
|
+
|
|
383
|
+
| Export | Description |
|
|
384
|
+
| ------------------------------ | ------------------------ |
|
|
385
|
+
| `Logger.configure(options)` | Configure logging |
|
|
386
|
+
| `Logger.get()` | Get context-aware logger |
|
|
387
|
+
| `Logger.for(name)` | Get scoped logger |
|
|
388
|
+
| `Telemetry.startSpan(name)` | Create span |
|
|
389
|
+
| `Telemetry.getCounter(name)` | Create counter metric |
|
|
390
|
+
| `Telemetry.getHistogram(name)` | Create histogram metric |
|
|
391
|
+
|
|
392
|
+
### Streaming
|
|
393
|
+
|
|
394
|
+
| Export | Description |
|
|
395
|
+
| ---------------- | ----------------------------- |
|
|
396
|
+
| `Channel` | Pub/sub with request/response |
|
|
397
|
+
| `EventBuffer<T>` | Type-safe event streaming |
|
|
398
|
+
|
|
399
|
+
## License
|
|
400
|
+
|
|
401
|
+
MIT
|