@alveus-ai/core 0.1.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.
- package/.turbo/turbo-build.log +0 -0
- package/.turbo/turbo-test.log +28 -0
- package/dist/agent.d.ts +4 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +30 -0
- package/dist/agent.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime.d.ts +121 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +51 -0
- package/dist/runtime.js.map +1 -0
- package/dist/types.d.ts +47 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/package.json +27 -0
- package/src/agent.ts +59 -0
- package/src/index.ts +49 -0
- package/src/runtime.ts +576 -0
- package/src/types.ts +146 -0
- package/test/capability-injection.test.ts +99 -0
- package/tsconfig.json +9 -0
|
File without changes
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
Serialized handler source: async(event2,ctx)=>{const result2=await ctx.db.save(event2.data);return{saved:result2}}
|
|
3
|
+
Mock DB: Saving hello from POC
|
|
4
|
+
✅ POC Success! Result: { saved: [32m'saved:hello from POC'[39m }
|
|
5
|
+
✅ Arrow function test passed: { count: [33m6[39m }
|
|
6
|
+
Mock fetch: https://api.example.com/v2?retries=3
|
|
7
|
+
✅ Configuration passing test passed: response from https://api.example.com/v2?retries=3
|
|
8
|
+
✅ Complex context test passed: { saveId: [32m'save-id-456'[39m, response: [32m'AI generated response'[39m }
|
|
9
|
+
Logs: [
|
|
10
|
+
[32m'INFO: Processing request for user user-789'[39m,
|
|
11
|
+
[32m"db.query: SELECT * FROM users WHERE id = 'user-789'"[39m,
|
|
12
|
+
[32m'openai.complete: Summarize this document'[39m,
|
|
13
|
+
[32m'db.save: {"userId":"user-789","response":"AI generated response"}'[39m
|
|
14
|
+
]
|
|
15
|
+
▶ Capability Injection POC
|
|
16
|
+
[32m✔ should inject capabilities into a deserialized function [90m(1.540707ms)[39m[39m
|
|
17
|
+
[32m✔ should work with arrow functions [90m(0.255949ms)[39m[39m
|
|
18
|
+
[32m✔ should pass configuration via event/state, not outer scope [90m(0.253008ms)[39m[39m
|
|
19
|
+
[32m✔ should handle complex context with multiple capabilities [90m(0.437631ms)[39m[39m
|
|
20
|
+
[32m✔ Capability Injection POC [90m(3.096825ms)[39m[39m
|
|
21
|
+
[34mℹ tests 4[39m
|
|
22
|
+
[34mℹ suites 1[39m
|
|
23
|
+
[34mℹ pass 4[39m
|
|
24
|
+
[34mℹ fail 0[39m
|
|
25
|
+
[34mℹ cancelled 0[39m
|
|
26
|
+
[34mℹ skipped 0[39m
|
|
27
|
+
[34mℹ todo 0[39m
|
|
28
|
+
[34mℹ duration_ms 1464.19065[39m
|
package/dist/agent.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Agent, AgentHandler, AgentOptions } from './types.js';
|
|
2
|
+
export declare function agent$<TState = any, TEvent = any, TContext = any, TResult = any>(handler: AgentHandler<TState, TEvent, TContext, TResult>, options?: AgentOptions): Agent<TState, TEvent, TContext, TResult>;
|
|
3
|
+
export declare function serializeHandler(handler: (...args: unknown[]) => unknown): string;
|
|
4
|
+
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,YAAY,EAAmB,MAAM,YAAY,CAAC;AAgBrF,wBAAgB,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EAAE,QAAQ,GAAG,GAAG,EAAE,OAAO,GAAG,GAAG,EAC9E,OAAO,EAAE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,EACxD,OAAO,CAAC,EAAE,YAAY,GACrB,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAwB1C;AAYD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,GAAG,MAAM,CAEjF"}
|
package/dist/agent.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
export function agent$(handler, options) {
|
|
3
|
+
const handlerSource = handler.toString();
|
|
4
|
+
const hash = computeHash(handlerSource);
|
|
5
|
+
const definition = {
|
|
6
|
+
hash,
|
|
7
|
+
inputs: {
|
|
8
|
+
state: 'any',
|
|
9
|
+
event: 'any',
|
|
10
|
+
context: 'any',
|
|
11
|
+
},
|
|
12
|
+
metadata: {
|
|
13
|
+
name: options?.name,
|
|
14
|
+
version: options?.version,
|
|
15
|
+
description: options?.description,
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
return {
|
|
19
|
+
definition,
|
|
20
|
+
handler,
|
|
21
|
+
options,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function computeHash(source) {
|
|
25
|
+
return crypto.createHash('sha256').update(source).digest('hex');
|
|
26
|
+
}
|
|
27
|
+
export function serializeHandler(handler) {
|
|
28
|
+
return handler.toString();
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AAiBjC,MAAM,UAAU,MAAM,CACpB,OAAwD,EACxD,OAAsB;IAGtB,MAAM,aAAa,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IACzC,MAAM,IAAI,GAAG,WAAW,CAAC,aAAa,CAAC,CAAC;IAExC,MAAM,UAAU,GAA8C;QAC5D,IAAI;QACJ,MAAM,EAAE;YACN,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,KAAK;YACZ,OAAO,EAAE,KAAK;SACf;QACD,QAAQ,EAAE;YACR,IAAI,EAAE,OAAO,EAAE,IAAI;YACnB,OAAO,EAAE,OAAO,EAAE,OAAO;YACzB,WAAW,EAAE,OAAO,EAAE,WAAW;SAClC;KACF,CAAC;IAEF,OAAO;QACL,UAAU;QACV,OAAO;QACP,OAAO;KACR,CAAC;AACJ,CAAC;AAKD,SAAS,WAAW,CAAC,MAAc;IACjC,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAClE,CAAC;AAKD,MAAM,UAAU,gBAAgB,CAAC,OAAwC;IACvE,OAAO,OAAO,CAAC,QAAQ,EAAE,CAAC;AAC5B,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { agent$, serializeHandler } from './agent.js';
|
|
2
|
+
export type { Agent, AgentDefinition, AgentHandler, AgentOptions, ExecutionContext, VirtualAgent, } from './types.js';
|
|
3
|
+
export { isVirtualAgent } from './types.js';
|
|
4
|
+
export { isDurableContext, withDurableContext } from './runtime.js';
|
|
5
|
+
export type { DurableExecutionContext, ExecutionRequest, ExecutionResult, ExecutionStatus, Registry, Runtime, RuntimeConfig, SimpleRuntimeConfig, DurableRuntimeConfig, ChatMessage, ChatOptions, LLMCapability, StorageCapability, BlobStore, AlveusEvent, EventCapability, LoggerCapability, } from './runtime.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGtD,YAAY,EACV,KAAK,EACL,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG5C,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEpE,YAAY,EAEV,uBAAuB,EACvB,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,QAAQ,EACR,OAAO,EACP,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EAEpB,WAAW,EACX,WAAW,EACX,aAAa,EAEb,iBAAiB,EACjB,SAAS,EAET,WAAW,EACX,eAAe,EAEf,gBAAgB,GACjB,MAAM,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAatD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG5C,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { ExecutionContext } from './types.js';
|
|
2
|
+
export interface AlveusEvent {
|
|
3
|
+
id: string;
|
|
4
|
+
topic: string;
|
|
5
|
+
data: any;
|
|
6
|
+
source?: string;
|
|
7
|
+
timestamp: number;
|
|
8
|
+
targetWorkflowId?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface EventCapability {
|
|
11
|
+
emit(topic: string, data: any): Promise<void>;
|
|
12
|
+
waitFor(topic: string, timeoutMs?: number): Promise<AlveusEvent>;
|
|
13
|
+
}
|
|
14
|
+
export interface SecretsCapability {
|
|
15
|
+
get(key: string): string | undefined;
|
|
16
|
+
has(key: string): boolean;
|
|
17
|
+
keys(): string[];
|
|
18
|
+
}
|
|
19
|
+
export interface LoggerCapability {
|
|
20
|
+
info(message: string, attrs?: Record<string, any>): void;
|
|
21
|
+
warn(message: string, attrs?: Record<string, any>): void;
|
|
22
|
+
error(message: string, attrs?: Record<string, any>): void;
|
|
23
|
+
debug(message: string, attrs?: Record<string, any>): void;
|
|
24
|
+
}
|
|
25
|
+
export interface ChatMessage {
|
|
26
|
+
role: 'system' | 'user' | 'assistant';
|
|
27
|
+
content: string;
|
|
28
|
+
}
|
|
29
|
+
export interface ChatOptions {
|
|
30
|
+
provider?: 'openai' | 'anthropic' | 'ollama' | 'mock';
|
|
31
|
+
model?: string;
|
|
32
|
+
temperature?: number;
|
|
33
|
+
jsonMode?: boolean;
|
|
34
|
+
maxTokens?: number;
|
|
35
|
+
streamId?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface LLMCapability {
|
|
38
|
+
chat(messages: ChatMessage[], options?: ChatOptions): Promise<string>;
|
|
39
|
+
}
|
|
40
|
+
export interface StorageCapability {
|
|
41
|
+
put(data: string | Buffer): Promise<string>;
|
|
42
|
+
get(key: string): Promise<string | null>;
|
|
43
|
+
}
|
|
44
|
+
export interface BlobStore {
|
|
45
|
+
put(data: string | Buffer): Promise<string>;
|
|
46
|
+
get(key: string): Promise<string | null>;
|
|
47
|
+
exists(key: string): Promise<boolean>;
|
|
48
|
+
delete?(key: string): Promise<void>;
|
|
49
|
+
list?(): Promise<string[]>;
|
|
50
|
+
}
|
|
51
|
+
export interface DurableExecutionContext extends ExecutionContext {
|
|
52
|
+
sleep(duration: number | string): Promise<void>;
|
|
53
|
+
sleepUntil(timestamp: string | Date): Promise<void>;
|
|
54
|
+
getExecutionId(): string;
|
|
55
|
+
getAttempt(): number;
|
|
56
|
+
log: {
|
|
57
|
+
info(message: string, ...args: any[]): void;
|
|
58
|
+
warn(message: string, ...args: any[]): void;
|
|
59
|
+
error(message: string, ...args: any[]): void;
|
|
60
|
+
debug(message: string, ...args: any[]): void;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export interface ExecutionRequest<TState = any, TEvent = any> {
|
|
64
|
+
hash: string;
|
|
65
|
+
state: TState;
|
|
66
|
+
event: TEvent;
|
|
67
|
+
executionId?: string;
|
|
68
|
+
parentExecutionId?: string;
|
|
69
|
+
}
|
|
70
|
+
export interface ExecutionResult<TResult = any> {
|
|
71
|
+
success: boolean;
|
|
72
|
+
result?: TResult;
|
|
73
|
+
error?: string;
|
|
74
|
+
metadata: {
|
|
75
|
+
hash: string;
|
|
76
|
+
executionId: string;
|
|
77
|
+
duration: number;
|
|
78
|
+
timestamp: string;
|
|
79
|
+
attempts?: number;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
export interface Registry {
|
|
83
|
+
store(hash: string, content: string): Promise<void>;
|
|
84
|
+
retrieve(hash: string): Promise<string | null>;
|
|
85
|
+
list(): Promise<string[]>;
|
|
86
|
+
exists(hash: string): Promise<boolean>;
|
|
87
|
+
}
|
|
88
|
+
export interface Runtime {
|
|
89
|
+
readonly name: string;
|
|
90
|
+
start(): Promise<void>;
|
|
91
|
+
stop(): Promise<void>;
|
|
92
|
+
execute<TState = any, TEvent = any, TResult = any>(request: ExecutionRequest<TState, TEvent>): Promise<ExecutionResult<TResult>>;
|
|
93
|
+
getExecutionStatus(executionId: string): Promise<ExecutionStatus>;
|
|
94
|
+
cancelExecution(executionId: string): Promise<void>;
|
|
95
|
+
}
|
|
96
|
+
export interface ExecutionStatus {
|
|
97
|
+
executionId: string;
|
|
98
|
+
hash: string;
|
|
99
|
+
status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';
|
|
100
|
+
startedAt?: string;
|
|
101
|
+
completedAt?: string;
|
|
102
|
+
error?: string;
|
|
103
|
+
result?: any;
|
|
104
|
+
}
|
|
105
|
+
export interface RuntimeConfig {
|
|
106
|
+
registry: Registry;
|
|
107
|
+
capabilities?: Record<string, any>;
|
|
108
|
+
}
|
|
109
|
+
export interface DurableRuntimeConfig extends RuntimeConfig {
|
|
110
|
+
address: string;
|
|
111
|
+
namespace: string;
|
|
112
|
+
taskQueue: string;
|
|
113
|
+
identity?: string;
|
|
114
|
+
}
|
|
115
|
+
export interface SimpleRuntimeConfig extends RuntimeConfig {
|
|
116
|
+
port?: number;
|
|
117
|
+
host?: string;
|
|
118
|
+
}
|
|
119
|
+
export declare function isDurableContext(ctx: ExecutionContext): ctx is DurableExecutionContext;
|
|
120
|
+
export declare function withDurableContext<TState, TEvent, TResult>(handler: (state: TState, event: TEvent, ctx: DurableExecutionContext) => Promise<TResult>): (state: TState, event: TEvent, ctx: ExecutionContext) => Promise<TResult>;
|
|
121
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export function isDurableContext(ctx) {
|
|
2
|
+
return 'sleep' in ctx && typeof ctx.sleep === 'function';
|
|
3
|
+
}
|
|
4
|
+
export function withDurableContext(handler) {
|
|
5
|
+
return async (state, event, ctx) => {
|
|
6
|
+
const durableCtx = isDurableContext(ctx)
|
|
7
|
+
? ctx
|
|
8
|
+
: {
|
|
9
|
+
...ctx,
|
|
10
|
+
sleep: async (duration) => {
|
|
11
|
+
const ms = typeof duration === 'number' ? duration : parseDuration(duration);
|
|
12
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
13
|
+
},
|
|
14
|
+
sleepUntil: async (timestamp) => {
|
|
15
|
+
const target = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;
|
|
16
|
+
const now = Date.now();
|
|
17
|
+
const delay = target.getTime() - now;
|
|
18
|
+
if (delay > 0) {
|
|
19
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
getExecutionId: () => `simple-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
23
|
+
getAttempt: () => 1,
|
|
24
|
+
log: {
|
|
25
|
+
info: (msg, ...args) => console.log(`[INFO] ${msg}`, ...args),
|
|
26
|
+
warn: (msg, ...args) => console.warn(`[WARN] ${msg}`, ...args),
|
|
27
|
+
error: (msg, ...args) => console.error(`[ERROR] ${msg}`, ...args),
|
|
28
|
+
debug: (msg, ...args) => console.debug(`[DEBUG] ${msg}`, ...args),
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
return handler(state, event, durableCtx);
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function parseDuration(duration) {
|
|
35
|
+
const match = duration.match(/^P(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+)?)S)?)?$/);
|
|
36
|
+
if (!match) {
|
|
37
|
+
throw new Error(`Invalid duration format: ${duration}`);
|
|
38
|
+
}
|
|
39
|
+
const [, days, hours, minutes, seconds] = match;
|
|
40
|
+
let ms = 0;
|
|
41
|
+
if (days)
|
|
42
|
+
ms += parseInt(days, 10) * 24 * 60 * 60 * 1000;
|
|
43
|
+
if (hours)
|
|
44
|
+
ms += parseInt(hours, 10) * 60 * 60 * 1000;
|
|
45
|
+
if (minutes)
|
|
46
|
+
ms += parseInt(minutes, 10) * 60 * 1000;
|
|
47
|
+
if (seconds)
|
|
48
|
+
ms += parseFloat(seconds) * 1000;
|
|
49
|
+
return ms;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAkfA,MAAM,UAAU,gBAAgB,CAAC,GAAqB;IACpD,OAAO,OAAO,IAAI,GAAG,IAAI,OAAQ,GAAW,CAAC,KAAK,KAAK,UAAU,CAAC;AACpE,CAAC;AAqBD,MAAM,UAAU,kBAAkB,CAChC,OAAyF;IAEzF,OAAO,KAAK,EAAE,KAAa,EAAE,KAAa,EAAE,GAAqB,EAAE,EAAE;QAEnE,MAAM,UAAU,GAA4B,gBAAgB,CAAC,GAAG,CAAC;YAC/D,CAAC,CAAC,GAAG;YACL,CAAC,CAAC;gBACE,GAAG,GAAG;gBACN,KAAK,EAAE,KAAK,EAAE,QAAyB,EAAE,EAAE;oBACzC,MAAM,EAAE,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;oBAC7E,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;gBAC3D,CAAC;gBACD,UAAU,EAAE,KAAK,EAAE,SAAwB,EAAE,EAAE;oBAC7C,MAAM,MAAM,GAAG,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;oBAC/E,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;oBACvB,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC;oBACrC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;wBACd,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;oBAC7D,CAAC;gBACH,CAAC;gBACD,cAAc,EAAE,GAAG,EAAE,CAAC,UAAU,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;gBACnF,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;gBACnB,GAAG,EAAE;oBACH,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC;oBAC7D,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC;oBAC9D,KAAK,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC;oBACjE,KAAK,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC;iBAClE;aACF,CAAC;QAEN,OAAO,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;IAC3C,CAAC,CAAC;AACJ,CAAC;AAMD,SAAS,aAAa,CAAC,QAAgB;IACrC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,iEAAiE,CAAC,CAAC;IAChG,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,4BAA4B,QAAQ,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC;IAChD,IAAI,EAAE,GAAG,CAAC,CAAC;IAEX,IAAI,IAAI;QAAE,EAAE,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACzD,IAAI,KAAK;QAAE,EAAE,IAAI,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACtD,IAAI,OAAO;QAAE,EAAE,IAAI,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;IACrD,IAAI,OAAO;QAAE,EAAE,IAAI,UAAU,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IAE9C,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface AgentDefinition<TState = any, TEvent = any, TContext = any> {
|
|
2
|
+
hash: string;
|
|
3
|
+
inputs: {
|
|
4
|
+
state: string;
|
|
5
|
+
event: string;
|
|
6
|
+
context: string;
|
|
7
|
+
};
|
|
8
|
+
metadata?: {
|
|
9
|
+
name?: string;
|
|
10
|
+
version?: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
};
|
|
13
|
+
__types?: {
|
|
14
|
+
state: TState;
|
|
15
|
+
event: TEvent;
|
|
16
|
+
context: TContext;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export type AgentHandler<TState = any, TEvent = any, TContext = any, TResult = any> = (state: TState, event: TEvent, context: TContext) => Promise<TResult> | TResult;
|
|
20
|
+
export interface AgentOptions {
|
|
21
|
+
name?: string;
|
|
22
|
+
description?: string;
|
|
23
|
+
version?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface Agent<TState = any, TEvent = any, TContext = any, TResult = any> {
|
|
26
|
+
definition: AgentDefinition<TState, TEvent, TContext>;
|
|
27
|
+
handler: AgentHandler<TState, TEvent, TContext, TResult>;
|
|
28
|
+
options?: AgentOptions;
|
|
29
|
+
}
|
|
30
|
+
export interface VirtualAgent<TInput = any> {
|
|
31
|
+
definition: Agent;
|
|
32
|
+
defaultInput: Partial<TInput>;
|
|
33
|
+
}
|
|
34
|
+
export declare function isVirtualAgent(agent: any): agent is VirtualAgent;
|
|
35
|
+
export interface ExecutionContext {
|
|
36
|
+
workflowId: string;
|
|
37
|
+
call<TInput = any, TOutput = any>(agent: Agent<any, TInput, any, TOutput> | string, input: TInput): Promise<TOutput>;
|
|
38
|
+
sleep(duration: number): Promise<void>;
|
|
39
|
+
getState<T = any>(key: string): Promise<T | null>;
|
|
40
|
+
setState(key: string, value: any): Promise<void>;
|
|
41
|
+
llm: import('./runtime.js').LLMCapability;
|
|
42
|
+
storage: import('./runtime.js').StorageCapability;
|
|
43
|
+
events: import('./runtime.js').EventCapability;
|
|
44
|
+
logger: import('./runtime.js').LoggerCapability;
|
|
45
|
+
secrets: import('./runtime.js').SecretsCapability;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,eAAe,CAAC,MAAM,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EAAE,QAAQ,GAAG,GAAG;IAEzE,IAAI,EAAE,MAAM,CAAC;IAGb,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IAGF,QAAQ,CAAC,EAAE;QACT,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IAGF,OAAO,CAAC,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,QAAQ,CAAC;KACnB,CAAC;CACH;AAKD,MAAM,MAAM,YAAY,CAAC,MAAM,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EAAE,QAAQ,GAAG,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,CACpF,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,QAAQ,KACd,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;AAKhC,MAAM,WAAW,YAAY;IAE3B,IAAI,CAAC,EAAE,MAAM,CAAC;IAGd,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAKD,MAAM,WAAW,KAAK,CAAC,MAAM,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EAAE,QAAQ,GAAG,GAAG,EAAE,OAAO,GAAG,GAAG;IAE9E,UAAU,EAAE,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IAGtD,OAAO,EAAE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAGzD,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAaD,MAAM,WAAW,YAAY,CAAC,MAAM,GAAG,GAAG;IAExC,UAAU,EAAE,KAAK,CAAC;IAGlB,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;CAC/B;AAKD,wBAAgB,cAAc,CAAC,KAAK,EAAE,GAAG,GAAG,KAAK,IAAI,YAAY,CAShE;AAQD,MAAM,WAAW,gBAAgB;IAE/B,UAAU,EAAE,MAAM,CAAC;IAGnB,IAAI,CAAC,MAAM,GAAG,GAAG,EAAE,OAAO,GAAG,GAAG,EAC9B,KAAK,EAAE,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,MAAM,EAChD,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC,CAAC;IAMpB,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAGvC,QAAQ,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAGlD,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAGjD,GAAG,EAAE,OAAO,cAAc,EAAE,aAAa,CAAC;IAG1C,OAAO,EAAE,OAAO,cAAc,EAAE,iBAAiB,CAAC;IAGlD,MAAM,EAAE,OAAO,cAAc,EAAE,eAAe,CAAC;IAG/C,MAAM,EAAE,OAAO,cAAc,EAAE,gBAAgB,CAAC;IAGhD,OAAO,EAAE,OAAO,cAAc,EAAE,iBAAiB,CAAC;CACnD"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function isVirtualAgent(agent) {
|
|
2
|
+
return (agent !== null &&
|
|
3
|
+
typeof agent === 'object' &&
|
|
4
|
+
'definition' in agent &&
|
|
5
|
+
'defaultInput' in agent &&
|
|
6
|
+
typeof agent.definition === 'object' &&
|
|
7
|
+
'definition' in agent.definition);
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA4FA,MAAM,UAAU,cAAc,CAAC,KAAU;IACvC,OAAO,CACL,KAAK,KAAK,IAAI;QACd,OAAO,KAAK,KAAK,QAAQ;QACzB,YAAY,IAAI,KAAK;QACrB,cAAc,IAAI,KAAK;QACvB,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ;QACpC,YAAY,IAAI,KAAK,CAAC,UAAU,CACjC,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@alveus-ai/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"main": "dist/index.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc",
|
|
18
|
+
"dev": "tsc --watch",
|
|
19
|
+
"test": "node --import tsx --test test/**/*.test.ts",
|
|
20
|
+
"type-check": "tsc --noEmit"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^22.10.1",
|
|
24
|
+
"tsx": "^4.19.2",
|
|
25
|
+
"typescript": "^5.7.2"
|
|
26
|
+
}
|
|
27
|
+
}
|
package/src/agent.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
import type { Agent, AgentHandler, AgentOptions, AgentDefinition } from './types.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Define an Alveus agent.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* const myAgent = agent$(
|
|
10
|
+
* async (state, event, ctx) => {
|
|
11
|
+
* const reply = await ctx.llm.chat([{ role: 'user', content: event.message }]);
|
|
12
|
+
* return { reply };
|
|
13
|
+
* },
|
|
14
|
+
* { name: 'my-agent' }
|
|
15
|
+
* );
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export function agent$<TState = any, TEvent = any, TContext = any, TResult = any>(
|
|
19
|
+
handler: AgentHandler<TState, TEvent, TContext, TResult>,
|
|
20
|
+
options?: AgentOptions,
|
|
21
|
+
): Agent<TState, TEvent, TContext, TResult> {
|
|
22
|
+
// In development mode, we compute the hash of the handler source
|
|
23
|
+
const handlerSource = handler.toString();
|
|
24
|
+
const hash = computeHash(handlerSource);
|
|
25
|
+
|
|
26
|
+
const definition: AgentDefinition<TState, TEvent, TContext> = {
|
|
27
|
+
hash,
|
|
28
|
+
inputs: {
|
|
29
|
+
state: 'any',
|
|
30
|
+
event: 'any',
|
|
31
|
+
context: 'any',
|
|
32
|
+
},
|
|
33
|
+
metadata: {
|
|
34
|
+
name: options?.name,
|
|
35
|
+
version: options?.version,
|
|
36
|
+
description: options?.description,
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
definition,
|
|
42
|
+
handler,
|
|
43
|
+
options,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Compute SHA-256 hash of a string
|
|
49
|
+
*/
|
|
50
|
+
function computeHash(source: string): string {
|
|
51
|
+
return crypto.createHash('sha256').update(source).digest('hex');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Serialize an agent handler to its source string representation.
|
|
56
|
+
*/
|
|
57
|
+
export function serializeHandler(handler: (...args: unknown[]) => unknown): string {
|
|
58
|
+
return handler.toString();
|
|
59
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @alveus-ai/core - The runtime SDK for Alveus agents
|
|
3
|
+
*
|
|
4
|
+
* This package provides the core primitives for defining and executing agents.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Agent definition and serialization
|
|
8
|
+
export { agent$, serializeHandler } from './agent.js';
|
|
9
|
+
|
|
10
|
+
// Core types
|
|
11
|
+
export type {
|
|
12
|
+
Agent,
|
|
13
|
+
AgentDefinition,
|
|
14
|
+
AgentHandler,
|
|
15
|
+
AgentOptions,
|
|
16
|
+
ExecutionContext,
|
|
17
|
+
VirtualAgent,
|
|
18
|
+
} from './types.js';
|
|
19
|
+
|
|
20
|
+
// Virtual Agent support
|
|
21
|
+
export { isVirtualAgent } from './types.js';
|
|
22
|
+
|
|
23
|
+
// Runtime abstraction layer
|
|
24
|
+
export { isDurableContext, withDurableContext } from './runtime.js';
|
|
25
|
+
|
|
26
|
+
export type {
|
|
27
|
+
// Runtime interfaces
|
|
28
|
+
DurableExecutionContext,
|
|
29
|
+
ExecutionRequest,
|
|
30
|
+
ExecutionResult,
|
|
31
|
+
ExecutionStatus,
|
|
32
|
+
Registry,
|
|
33
|
+
Runtime,
|
|
34
|
+
RuntimeConfig,
|
|
35
|
+
SimpleRuntimeConfig,
|
|
36
|
+
DurableRuntimeConfig,
|
|
37
|
+
// LLM capability
|
|
38
|
+
ChatMessage,
|
|
39
|
+
ChatOptions,
|
|
40
|
+
LLMCapability,
|
|
41
|
+
// Storage capability
|
|
42
|
+
StorageCapability,
|
|
43
|
+
BlobStore,
|
|
44
|
+
// Event capability
|
|
45
|
+
AlveusEvent,
|
|
46
|
+
EventCapability,
|
|
47
|
+
// Logger capability
|
|
48
|
+
LoggerCapability,
|
|
49
|
+
} from './runtime.js';
|
package/src/runtime.ts
ADDED
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime Abstraction Layer
|
|
3
|
+
*
|
|
4
|
+
* This module defines the interfaces that allow Alveus to run on different
|
|
5
|
+
* execution backends.
|
|
6
|
+
*
|
|
7
|
+
* Key concepts:
|
|
8
|
+
* - ExecutionContext: What agents see (call, sleep, emit, etc.)
|
|
9
|
+
* - Runtime: The execution environment that provides the context
|
|
10
|
+
* - LLMCapability: Model-agnostic AI generation
|
|
11
|
+
* - StorageCapability: Large payload handling via content-addressed references
|
|
12
|
+
* - EventCapability: Reactive event system for external triggers
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { ExecutionContext } from './types.js';
|
|
16
|
+
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// Event Capability
|
|
19
|
+
// ============================================================================
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* AlveusEvent - A durable event in the system
|
|
23
|
+
*/
|
|
24
|
+
export interface AlveusEvent {
|
|
25
|
+
/** Unique event ID */
|
|
26
|
+
id: string;
|
|
27
|
+
|
|
28
|
+
/** Topic/channel for routing (e.g., "market.btc.price", "user.approval") */
|
|
29
|
+
topic: string;
|
|
30
|
+
|
|
31
|
+
/** Event payload - any JSON-serializable data */
|
|
32
|
+
data: any;
|
|
33
|
+
|
|
34
|
+
/** Source identifier (e.g., workflow ID, external system) */
|
|
35
|
+
source?: string;
|
|
36
|
+
|
|
37
|
+
/** Unix timestamp in milliseconds */
|
|
38
|
+
timestamp: number;
|
|
39
|
+
|
|
40
|
+
/** Optional target workflow ID for direct routing */
|
|
41
|
+
targetWorkflowId?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* EventCapability - Reactive event system for agents
|
|
46
|
+
*
|
|
47
|
+
* Enables agents to:
|
|
48
|
+
* 1. Publish events to the global event bus
|
|
49
|
+
* 2. Pause execution and wait for specific events (durable wait)
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* // Publish an event
|
|
54
|
+
* await ctx.events.emit('order.completed', { orderId: '123', total: 99.99 });
|
|
55
|
+
*
|
|
56
|
+
* // Wait for an external event (durable - survives restarts)
|
|
57
|
+
* const approval = await ctx.events.waitFor('human.approval', 60000);
|
|
58
|
+
* if (approval.data.approved) {
|
|
59
|
+
* // Continue with approved action
|
|
60
|
+
* }
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export interface EventCapability {
|
|
64
|
+
/**
|
|
65
|
+
* Publish an event to the global event bus
|
|
66
|
+
*
|
|
67
|
+
* @param topic - Event topic for routing (e.g., "user.signup", "order.paid")
|
|
68
|
+
* @param data - Event payload (must be JSON-serializable)
|
|
69
|
+
*/
|
|
70
|
+
emit(topic: string, data: any): Promise<void>;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Pause execution and wait for a specific event topic
|
|
74
|
+
*
|
|
75
|
+
* This is a DURABLE wait - the workflow will resume even after:
|
|
76
|
+
* - Worker restarts
|
|
77
|
+
* - System failures
|
|
78
|
+
* - Long delays (hours, days)
|
|
79
|
+
*
|
|
80
|
+
* @param topic - Event topic to wait for
|
|
81
|
+
* @param timeoutMs - Optional timeout in milliseconds
|
|
82
|
+
* @returns The event that matched the topic
|
|
83
|
+
* @throws TimeoutError if timeout is reached without receiving event
|
|
84
|
+
*/
|
|
85
|
+
waitFor(topic: string, timeoutMs?: number): Promise<AlveusEvent>;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ============================================================================
|
|
89
|
+
// Secrets Capability
|
|
90
|
+
// ============================================================================
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* SecretsCapability - Secure runtime secrets for agents
|
|
94
|
+
*
|
|
95
|
+
* Provides access to secrets that are securely injected into the
|
|
96
|
+
* agent's execution context at runtime.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```ts
|
|
100
|
+
* // Get a secret
|
|
101
|
+
* const apiKey = ctx.secrets.get('OPENAI_API_KEY');
|
|
102
|
+
* if (!apiKey) throw new Error('OPENAI_API_KEY secret not configured');
|
|
103
|
+
*
|
|
104
|
+
* // Check if a secret exists
|
|
105
|
+
* if (ctx.secrets.has('DATABASE_URL')) {
|
|
106
|
+
* // Connect to database
|
|
107
|
+
* }
|
|
108
|
+
*
|
|
109
|
+
* // List available secrets (for debugging - shows keys only)
|
|
110
|
+
* console.log('Available secrets:', ctx.secrets.keys());
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export interface SecretsCapability {
|
|
114
|
+
/**
|
|
115
|
+
* Get a secret value by key
|
|
116
|
+
*
|
|
117
|
+
* @param key - Secret key (e.g., "OPENAI_API_KEY")
|
|
118
|
+
* @returns The secret value or undefined if not set
|
|
119
|
+
*/
|
|
120
|
+
get(key: string): string | undefined;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Check if a secret exists
|
|
124
|
+
*
|
|
125
|
+
* @param key - Secret key to check
|
|
126
|
+
*/
|
|
127
|
+
has(key: string): boolean;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Get all available secret keys (not values - for debugging)
|
|
131
|
+
*
|
|
132
|
+
* @returns Array of secret key names
|
|
133
|
+
*/
|
|
134
|
+
keys(): string[];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// ============================================================================
|
|
138
|
+
// Logger Capability
|
|
139
|
+
// ============================================================================
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* LoggerCapability - Deterministic logging for agents
|
|
143
|
+
*
|
|
144
|
+
* Provides a consistent logging interface that is safe for use in all
|
|
145
|
+
* execution environments, including replay-safe durable runtimes.
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* ctx.logger.info('Processing order', { orderId: '123' });
|
|
150
|
+
* ctx.logger.warn('Retrying operation', { attempt: 2 });
|
|
151
|
+
* ctx.logger.error('Failed to process', { error: err.message });
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
export interface LoggerCapability {
|
|
155
|
+
/** Log informational message */
|
|
156
|
+
info(message: string, attrs?: Record<string, any>): void;
|
|
157
|
+
|
|
158
|
+
/** Log warning message */
|
|
159
|
+
warn(message: string, attrs?: Record<string, any>): void;
|
|
160
|
+
|
|
161
|
+
/** Log error message */
|
|
162
|
+
error(message: string, attrs?: Record<string, any>): void;
|
|
163
|
+
|
|
164
|
+
/** Log debug message */
|
|
165
|
+
debug(message: string, attrs?: Record<string, any>): void;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// ============================================================================
|
|
169
|
+
// LLM Capability
|
|
170
|
+
// ============================================================================
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Chat message format - provider-agnostic
|
|
174
|
+
*/
|
|
175
|
+
export interface ChatMessage {
|
|
176
|
+
role: 'system' | 'user' | 'assistant';
|
|
177
|
+
content: string;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Options for LLM generation
|
|
182
|
+
*/
|
|
183
|
+
export interface ChatOptions {
|
|
184
|
+
/** Provider to use. Default: process.env.DEFAULT_LLM_PROVIDER or 'openai' */
|
|
185
|
+
provider?: 'openai' | 'anthropic' | 'ollama' | 'mock';
|
|
186
|
+
|
|
187
|
+
/** Model identifier (e.g., 'gpt-4o', 'claude-3-opus', 'llama2') */
|
|
188
|
+
model?: string;
|
|
189
|
+
|
|
190
|
+
/** Temperature for generation. Default: 0.7 */
|
|
191
|
+
temperature?: number;
|
|
192
|
+
|
|
193
|
+
/** Enforce JSON output format */
|
|
194
|
+
jsonMode?: boolean;
|
|
195
|
+
|
|
196
|
+
/** Maximum tokens to generate */
|
|
197
|
+
maxTokens?: number;
|
|
198
|
+
|
|
199
|
+
/** Stream ID for real-time token delivery. */
|
|
200
|
+
streamId?: string;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* LLM Capability - Model-agnostic AI generation
|
|
205
|
+
*
|
|
206
|
+
* Allows agents to use any LLM provider without coupling to specific SDKs.
|
|
207
|
+
* The implementation handles provider routing, retries, and rate limits.
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```ts
|
|
211
|
+
* const response = await ctx.llm.chat([
|
|
212
|
+
* { role: 'system', content: 'You are a helpful assistant.' },
|
|
213
|
+
* { role: 'user', content: 'What is 2+2?' }
|
|
214
|
+
* ], { provider: 'openai', model: 'gpt-4o' });
|
|
215
|
+
* ```
|
|
216
|
+
*/
|
|
217
|
+
export interface LLMCapability {
|
|
218
|
+
/**
|
|
219
|
+
* Generate a chat completion
|
|
220
|
+
*
|
|
221
|
+
* @param messages - Array of chat messages
|
|
222
|
+
* @param options - Provider and model options
|
|
223
|
+
* @returns The assistant's response content
|
|
224
|
+
*/
|
|
225
|
+
chat(messages: ChatMessage[], options?: ChatOptions): Promise<string>;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// ============================================================================
|
|
229
|
+
// Storage Capability
|
|
230
|
+
// ============================================================================
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Storage Capability - Large payload handling via content-addressed references
|
|
234
|
+
*
|
|
235
|
+
* Solves payload size limits by offloading large data to external storage.
|
|
236
|
+
* Agents can pass massive context using small reference keys.
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* ```ts
|
|
240
|
+
* // Store large context
|
|
241
|
+
* const key = await ctx.storage.put(JSON.stringify(largeHistory));
|
|
242
|
+
*
|
|
243
|
+
* // Pass key to child agent (small payload)
|
|
244
|
+
* await ctx.call(childAgent, { historyRef: key });
|
|
245
|
+
*
|
|
246
|
+
* // Child retrieves the data
|
|
247
|
+
* const history = JSON.parse(await ctx.storage.get(key));
|
|
248
|
+
* ```
|
|
249
|
+
*/
|
|
250
|
+
export interface StorageCapability {
|
|
251
|
+
/**
|
|
252
|
+
* Store data and get a reference key
|
|
253
|
+
*
|
|
254
|
+
* @param data - String or Buffer to store
|
|
255
|
+
* @returns Content-addressed key (e.g., "blob:sha256hash")
|
|
256
|
+
*/
|
|
257
|
+
put(data: string | Buffer): Promise<string>;
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Retrieve data by key
|
|
261
|
+
*
|
|
262
|
+
* @param key - The reference key from put()
|
|
263
|
+
* @returns The stored data, or null if not found
|
|
264
|
+
*/
|
|
265
|
+
get(key: string): Promise<string | null>;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* BlobStore Interface - Provider-agnostic blob storage abstraction
|
|
270
|
+
*/
|
|
271
|
+
export interface BlobStore {
|
|
272
|
+
/**
|
|
273
|
+
* Store data and return content-addressed key
|
|
274
|
+
*/
|
|
275
|
+
put(data: string | Buffer): Promise<string>;
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Retrieve data by key
|
|
279
|
+
*/
|
|
280
|
+
get(key: string): Promise<string | null>;
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Check if a blob exists
|
|
284
|
+
*/
|
|
285
|
+
exists(key: string): Promise<boolean>;
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Delete a blob (optional - for cleanup)
|
|
289
|
+
*/
|
|
290
|
+
delete?(key: string): Promise<void>;
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* List all blob keys (optional - for admin/debug)
|
|
294
|
+
*/
|
|
295
|
+
list?(): Promise<string[]>;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Extended ExecutionContext with durable execution primitives
|
|
300
|
+
*
|
|
301
|
+
* This extends the base ExecutionContext with methods needed for
|
|
302
|
+
* durable execution (sleep, scheduleAt, etc.)
|
|
303
|
+
*/
|
|
304
|
+
export interface DurableExecutionContext extends ExecutionContext {
|
|
305
|
+
/**
|
|
306
|
+
* Sleep for a duration (durable — survives process restarts)
|
|
307
|
+
*
|
|
308
|
+
* @param duration - Duration in milliseconds, or ISO 8601 duration string
|
|
309
|
+
* @example
|
|
310
|
+
* await ctx.sleep(5000); // Sleep for 5 seconds
|
|
311
|
+
* await ctx.sleep('PT1H'); // Sleep for 1 hour (ISO 8601)
|
|
312
|
+
* await ctx.sleep('P1D'); // Sleep for 1 day
|
|
313
|
+
*/
|
|
314
|
+
sleep(duration: number | string): Promise<void>;
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Schedule execution to resume at a specific time
|
|
318
|
+
*
|
|
319
|
+
* @param timestamp - ISO 8601 timestamp or Date object
|
|
320
|
+
* @example
|
|
321
|
+
* await ctx.sleepUntil('2024-12-25T00:00:00Z');
|
|
322
|
+
* await ctx.sleepUntil(new Date('2024-12-25'));
|
|
323
|
+
*/
|
|
324
|
+
sleepUntil(timestamp: string | Date): Promise<void>;
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Get the current workflow/execution ID
|
|
328
|
+
* Useful for correlation and debugging
|
|
329
|
+
*/
|
|
330
|
+
getExecutionId(): string;
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Get the current attempt number (for retries)
|
|
334
|
+
*/
|
|
335
|
+
getAttempt(): number;
|
|
336
|
+
|
|
337
|
+
/** Deterministic logger (safe for durable execution replay) */
|
|
338
|
+
log: {
|
|
339
|
+
info(message: string, ...args: any[]): void;
|
|
340
|
+
warn(message: string, ...args: any[]): void;
|
|
341
|
+
error(message: string, ...args: any[]): void;
|
|
342
|
+
debug(message: string, ...args: any[]): void;
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Execution Request - Input to execute an agent
|
|
348
|
+
*/
|
|
349
|
+
export interface ExecutionRequest<TState = any, TEvent = any> {
|
|
350
|
+
/** The content hash of the agent to execute */
|
|
351
|
+
hash: string;
|
|
352
|
+
|
|
353
|
+
/** The state to pass to the agent */
|
|
354
|
+
state: TState;
|
|
355
|
+
|
|
356
|
+
/** The event/input to pass to the agent */
|
|
357
|
+
event: TEvent;
|
|
358
|
+
|
|
359
|
+
/** Optional execution ID (generated if not provided) */
|
|
360
|
+
executionId?: string;
|
|
361
|
+
|
|
362
|
+
/** Optional parent execution ID (for tracing) */
|
|
363
|
+
parentExecutionId?: string;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Execution Result - Output from agent execution
|
|
368
|
+
*/
|
|
369
|
+
export interface ExecutionResult<TResult = any> {
|
|
370
|
+
/** Whether execution succeeded */
|
|
371
|
+
success: boolean;
|
|
372
|
+
|
|
373
|
+
/** The result if successful */
|
|
374
|
+
result?: TResult;
|
|
375
|
+
|
|
376
|
+
/** Error message if failed */
|
|
377
|
+
error?: string;
|
|
378
|
+
|
|
379
|
+
/** Execution metadata */
|
|
380
|
+
metadata: {
|
|
381
|
+
hash: string;
|
|
382
|
+
executionId: string;
|
|
383
|
+
duration: number;
|
|
384
|
+
timestamp: string;
|
|
385
|
+
attempts?: number;
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Registry Interface - Abstraction for blob storage
|
|
391
|
+
*/
|
|
392
|
+
export interface Registry {
|
|
393
|
+
/** Store a blob and return its hash */
|
|
394
|
+
store(hash: string, content: string): Promise<void>;
|
|
395
|
+
|
|
396
|
+
/** Retrieve a blob by hash */
|
|
397
|
+
retrieve(hash: string): Promise<string | null>;
|
|
398
|
+
|
|
399
|
+
/** List all stored hashes */
|
|
400
|
+
list(): Promise<string[]>;
|
|
401
|
+
|
|
402
|
+
/** Check if a hash exists */
|
|
403
|
+
exists(hash: string): Promise<boolean>;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Runtime Interface - The execution environment abstraction
|
|
408
|
+
*/
|
|
409
|
+
export interface Runtime {
|
|
410
|
+
/** Runtime name for debugging */
|
|
411
|
+
readonly name: string;
|
|
412
|
+
|
|
413
|
+
/** Start the runtime (connect to services, etc.) */
|
|
414
|
+
start(): Promise<void>;
|
|
415
|
+
|
|
416
|
+
/** Stop the runtime gracefully */
|
|
417
|
+
stop(): Promise<void>;
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Execute an agent by hash
|
|
421
|
+
*
|
|
422
|
+
* @param request - The execution request
|
|
423
|
+
* @returns The execution result
|
|
424
|
+
*/
|
|
425
|
+
execute<TState = any, TEvent = any, TResult = any>(
|
|
426
|
+
request: ExecutionRequest<TState, TEvent>,
|
|
427
|
+
): Promise<ExecutionResult<TResult>>;
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Get the status of an execution
|
|
431
|
+
*
|
|
432
|
+
* @param executionId - The execution ID to check
|
|
433
|
+
*/
|
|
434
|
+
getExecutionStatus(executionId: string): Promise<ExecutionStatus>;
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Cancel a running execution
|
|
438
|
+
*
|
|
439
|
+
* @param executionId - The execution ID to cancel
|
|
440
|
+
*/
|
|
441
|
+
cancelExecution(executionId: string): Promise<void>;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Execution Status - Current state of an execution
|
|
446
|
+
*/
|
|
447
|
+
export interface ExecutionStatus {
|
|
448
|
+
executionId: string;
|
|
449
|
+
hash: string;
|
|
450
|
+
status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';
|
|
451
|
+
startedAt?: string;
|
|
452
|
+
completedAt?: string;
|
|
453
|
+
error?: string;
|
|
454
|
+
result?: any;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Runtime Configuration
|
|
459
|
+
*/
|
|
460
|
+
export interface RuntimeConfig {
|
|
461
|
+
/** Registry for blob storage */
|
|
462
|
+
registry: Registry;
|
|
463
|
+
|
|
464
|
+
/** Custom capability providers */
|
|
465
|
+
capabilities?: Record<string, any>;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Durable runtime configuration
|
|
470
|
+
*/
|
|
471
|
+
export interface DurableRuntimeConfig extends RuntimeConfig {
|
|
472
|
+
/** Server address */
|
|
473
|
+
address: string;
|
|
474
|
+
|
|
475
|
+
/** Namespace */
|
|
476
|
+
namespace: string;
|
|
477
|
+
|
|
478
|
+
/** Task queue name */
|
|
479
|
+
taskQueue: string;
|
|
480
|
+
|
|
481
|
+
/** Worker identity */
|
|
482
|
+
identity?: string;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* Simple runtime configuration
|
|
487
|
+
*/
|
|
488
|
+
export interface SimpleRuntimeConfig extends RuntimeConfig {
|
|
489
|
+
/** Port to listen on */
|
|
490
|
+
port?: number;
|
|
491
|
+
|
|
492
|
+
/** Host to bind to */
|
|
493
|
+
host?: string;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Type guard for checking if context supports durable execution
|
|
498
|
+
*/
|
|
499
|
+
export function isDurableContext(ctx: ExecutionContext): ctx is DurableExecutionContext {
|
|
500
|
+
return 'sleep' in ctx && typeof (ctx as any).sleep === 'function';
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Helper to create a runtime-agnostic agent handler
|
|
505
|
+
*
|
|
506
|
+
* This wrapper ensures agents can run on any runtime by:
|
|
507
|
+
* 1. Providing safe defaults for non-durable contexts
|
|
508
|
+
* 2. Adding type safety for durable operations
|
|
509
|
+
*
|
|
510
|
+
* @example
|
|
511
|
+
* ```ts
|
|
512
|
+
* const myAgent = agent$(
|
|
513
|
+
* withDurableContext(async (state, event, ctx) => {
|
|
514
|
+
* // ctx is now typed as DurableExecutionContext
|
|
515
|
+
* await ctx.sleep(5000);
|
|
516
|
+
* const result = await ctx.call(otherAgent, { data: 'hello' });
|
|
517
|
+
* return { processed: true };
|
|
518
|
+
* })
|
|
519
|
+
* );
|
|
520
|
+
* ```
|
|
521
|
+
*/
|
|
522
|
+
export function withDurableContext<TState, TEvent, TResult>(
|
|
523
|
+
handler: (state: TState, event: TEvent, ctx: DurableExecutionContext) => Promise<TResult>,
|
|
524
|
+
): (state: TState, event: TEvent, ctx: ExecutionContext) => Promise<TResult> {
|
|
525
|
+
return async (state: TState, event: TEvent, ctx: ExecutionContext) => {
|
|
526
|
+
// If not a durable context, provide fallback implementations
|
|
527
|
+
const durableCtx: DurableExecutionContext = isDurableContext(ctx)
|
|
528
|
+
? ctx
|
|
529
|
+
: {
|
|
530
|
+
...ctx,
|
|
531
|
+
sleep: async (duration: number | string) => {
|
|
532
|
+
const ms = typeof duration === 'number' ? duration : parseDuration(duration);
|
|
533
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
534
|
+
},
|
|
535
|
+
sleepUntil: async (timestamp: string | Date) => {
|
|
536
|
+
const target = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;
|
|
537
|
+
const now = Date.now();
|
|
538
|
+
const delay = target.getTime() - now;
|
|
539
|
+
if (delay > 0) {
|
|
540
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
541
|
+
}
|
|
542
|
+
},
|
|
543
|
+
getExecutionId: () => `simple-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
544
|
+
getAttempt: () => 1,
|
|
545
|
+
log: {
|
|
546
|
+
info: (msg, ...args) => console.log(`[INFO] ${msg}`, ...args),
|
|
547
|
+
warn: (msg, ...args) => console.warn(`[WARN] ${msg}`, ...args),
|
|
548
|
+
error: (msg, ...args) => console.error(`[ERROR] ${msg}`, ...args),
|
|
549
|
+
debug: (msg, ...args) => console.debug(`[DEBUG] ${msg}`, ...args),
|
|
550
|
+
},
|
|
551
|
+
};
|
|
552
|
+
|
|
553
|
+
return handler(state, event, durableCtx);
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* Parse ISO 8601 duration string to milliseconds
|
|
559
|
+
* Supports: PT#H, PT#M, PT#S, P#D formats
|
|
560
|
+
*/
|
|
561
|
+
function parseDuration(duration: string): number {
|
|
562
|
+
const match = duration.match(/^P(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+)?)S)?)?$/);
|
|
563
|
+
if (!match) {
|
|
564
|
+
throw new Error(`Invalid duration format: ${duration}`);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
const [, days, hours, minutes, seconds] = match;
|
|
568
|
+
let ms = 0;
|
|
569
|
+
|
|
570
|
+
if (days) ms += parseInt(days, 10) * 24 * 60 * 60 * 1000;
|
|
571
|
+
if (hours) ms += parseInt(hours, 10) * 60 * 60 * 1000;
|
|
572
|
+
if (minutes) ms += parseInt(minutes, 10) * 60 * 1000;
|
|
573
|
+
if (seconds) ms += parseFloat(seconds) * 1000;
|
|
574
|
+
|
|
575
|
+
return ms;
|
|
576
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core type definitions for Alveus agents
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Agent Definition - The immutable representation of an agent
|
|
7
|
+
*/
|
|
8
|
+
export interface AgentDefinition<TState = any, TEvent = any, TContext = any> {
|
|
9
|
+
/** Content-addressed hash of the agent code */
|
|
10
|
+
hash: string;
|
|
11
|
+
|
|
12
|
+
/** Input schema definition */
|
|
13
|
+
inputs: {
|
|
14
|
+
state: string;
|
|
15
|
+
event: string;
|
|
16
|
+
context: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/** Metadata about the agent */
|
|
20
|
+
metadata?: {
|
|
21
|
+
name?: string;
|
|
22
|
+
version?: string;
|
|
23
|
+
description?: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/** Phantom properties for type safety (not present at runtime) */
|
|
27
|
+
__types?: {
|
|
28
|
+
state: TState;
|
|
29
|
+
event: TEvent;
|
|
30
|
+
context: TContext;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Agent Handler Function - The actual executable code
|
|
36
|
+
*/
|
|
37
|
+
export type AgentHandler<TState = any, TEvent = any, TContext = any, TResult = any> = (
|
|
38
|
+
state: TState,
|
|
39
|
+
event: TEvent,
|
|
40
|
+
context: TContext,
|
|
41
|
+
) => Promise<TResult> | TResult;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Agent Configuration Options
|
|
45
|
+
*/
|
|
46
|
+
export interface AgentOptions {
|
|
47
|
+
/** Optional name for debugging/logging */
|
|
48
|
+
name?: string;
|
|
49
|
+
|
|
50
|
+
/** Optional description */
|
|
51
|
+
description?: string;
|
|
52
|
+
|
|
53
|
+
/** Optional version identifier */
|
|
54
|
+
version?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Agent - The result of calling agent$()
|
|
59
|
+
*/
|
|
60
|
+
export interface Agent<TState = any, TEvent = any, TContext = any, TResult = any> {
|
|
61
|
+
/** The agent definition (with hash) */
|
|
62
|
+
definition: AgentDefinition<TState, TEvent, TContext>;
|
|
63
|
+
|
|
64
|
+
/** The handler function (only available at compile time) */
|
|
65
|
+
handler: AgentHandler<TState, TEvent, TContext, TResult>;
|
|
66
|
+
|
|
67
|
+
/** Optional configuration */
|
|
68
|
+
options?: AgentOptions;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Virtual Agent - A configuration wrapper around a compiled agent.
|
|
73
|
+
*
|
|
74
|
+
* Allows creating pre-configured variants of an agent without
|
|
75
|
+
* generating new code.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```ts
|
|
79
|
+
* const myAgent = createReActAgent({ systemPrompt: '...', tools: {...} });
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export interface VirtualAgent<TInput = any> {
|
|
83
|
+
/** The underlying agent definition */
|
|
84
|
+
definition: Agent;
|
|
85
|
+
|
|
86
|
+
/** Pre-filled input that gets merged with runtime input */
|
|
87
|
+
defaultInput: Partial<TInput>;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Type guard to check if something is a VirtualAgent
|
|
92
|
+
*/
|
|
93
|
+
export function isVirtualAgent(agent: any): agent is VirtualAgent {
|
|
94
|
+
return (
|
|
95
|
+
agent !== null &&
|
|
96
|
+
typeof agent === 'object' &&
|
|
97
|
+
'definition' in agent &&
|
|
98
|
+
'defaultInput' in agent &&
|
|
99
|
+
typeof agent.definition === 'object' &&
|
|
100
|
+
'definition' in agent.definition // Has nested Agent structure
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Execution Context - Injected capabilities and utilities
|
|
106
|
+
*
|
|
107
|
+
* This is the base context available to all agents. For durable execution
|
|
108
|
+
* features (sleep, sleepUntil, etc.), see DurableExecutionContext in runtime.ts.
|
|
109
|
+
*/
|
|
110
|
+
export interface ExecutionContext {
|
|
111
|
+
/** Unique identifier for this execution */
|
|
112
|
+
workflowId: string;
|
|
113
|
+
|
|
114
|
+
/** Call another agent (RPC-style) */
|
|
115
|
+
call<TInput = any, TOutput = any>(
|
|
116
|
+
agent: Agent<any, TInput, any, TOutput> | string,
|
|
117
|
+
input: TInput,
|
|
118
|
+
): Promise<TOutput>;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Sleep for a duration
|
|
122
|
+
* @param duration - Duration in milliseconds
|
|
123
|
+
*/
|
|
124
|
+
sleep(duration: number): Promise<void>;
|
|
125
|
+
|
|
126
|
+
/** Get a value from state storage */
|
|
127
|
+
getState<T = any>(key: string): Promise<T | null>;
|
|
128
|
+
|
|
129
|
+
/** Set a value in state storage */
|
|
130
|
+
setState(key: string, value: any): Promise<void>;
|
|
131
|
+
|
|
132
|
+
/** LLM capability - model-agnostic AI generation */
|
|
133
|
+
llm: import('./runtime.js').LLMCapability;
|
|
134
|
+
|
|
135
|
+
/** Storage capability - large payload handling */
|
|
136
|
+
storage: import('./runtime.js').StorageCapability;
|
|
137
|
+
|
|
138
|
+
/** Event capability - publish events and wait for external triggers */
|
|
139
|
+
events: import('./runtime.js').EventCapability;
|
|
140
|
+
|
|
141
|
+
/** Logger capability - deterministic, replay-safe logging */
|
|
142
|
+
logger: import('./runtime.js').LoggerCapability;
|
|
143
|
+
|
|
144
|
+
/** Secrets capability - secure runtime secrets */
|
|
145
|
+
secrets: import('./runtime.js').SecretsCapability;
|
|
146
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capability Injection Test
|
|
3
|
+
*
|
|
4
|
+
* Validates the "Data-Only Closures" + "Capabilities" pattern:
|
|
5
|
+
* agent handlers receive all external dependencies via the context
|
|
6
|
+
* parameter, never via captured outer scope.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { describe, test } from 'node:test';
|
|
10
|
+
import assert from 'node:assert';
|
|
11
|
+
|
|
12
|
+
describe('Capability Injection', () => {
|
|
13
|
+
test('should inject capabilities into a handler via context', async () => {
|
|
14
|
+
const handler = async (
|
|
15
|
+
event: { data: string },
|
|
16
|
+
ctx: { db: { save: (data: string) => Promise<string> } },
|
|
17
|
+
) => {
|
|
18
|
+
const result = await ctx.db.save(event.data);
|
|
19
|
+
return { saved: result };
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const mockContext = {
|
|
23
|
+
db: {
|
|
24
|
+
save: async (data: string) => `saved:${data}`,
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const result = await handler({ data: 'hello' }, mockContext);
|
|
29
|
+
assert.deepStrictEqual(result, { saved: 'saved:hello' });
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test('should pass configuration via event/state, not outer scope', async () => {
|
|
33
|
+
const handler = async (
|
|
34
|
+
event: { url: string; config: { apiVersion: string; maxRetries: number } },
|
|
35
|
+
ctx: { fetch: (url: string) => Promise<string> },
|
|
36
|
+
) => {
|
|
37
|
+
const fullUrl = `${event.url}/${event.config.apiVersion}?retries=${event.config.maxRetries}`;
|
|
38
|
+
return ctx.fetch(fullUrl);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const mockContext = {
|
|
42
|
+
fetch: async (url: string) => `response from ${url}`,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const result = await handler(
|
|
46
|
+
{ url: 'https://api.example.com', config: { apiVersion: 'v2', maxRetries: 3 } },
|
|
47
|
+
mockContext,
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
assert.ok(result.includes('v2'));
|
|
51
|
+
assert.ok(result.includes('retries=3'));
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('should handle complex context with multiple capabilities', async () => {
|
|
55
|
+
interface Context {
|
|
56
|
+
db: {
|
|
57
|
+
query: (sql: string) => Promise<any[]>;
|
|
58
|
+
save: (data: any) => Promise<string>;
|
|
59
|
+
};
|
|
60
|
+
llm: {
|
|
61
|
+
complete: (prompt: string) => Promise<string>;
|
|
62
|
+
};
|
|
63
|
+
logger: {
|
|
64
|
+
info: (msg: string) => void;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const handler = async (event: { userId: string; prompt: string }, ctx: Context) => {
|
|
69
|
+
ctx.logger.info(`Processing request for user ${event.userId}`);
|
|
70
|
+
await ctx.db.query(`SELECT * FROM users WHERE id = '${event.userId}'`);
|
|
71
|
+
const aiResponse = await ctx.llm.complete(event.prompt);
|
|
72
|
+
const saveId = await ctx.db.save({ userId: event.userId, response: aiResponse });
|
|
73
|
+
return { saveId, response: aiResponse };
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const logs: string[] = [];
|
|
77
|
+
const mockContext: Context = {
|
|
78
|
+
db: {
|
|
79
|
+
query: async () => [{ id: '123', name: 'Test User' }],
|
|
80
|
+
save: async () => 'save-id-456',
|
|
81
|
+
},
|
|
82
|
+
llm: {
|
|
83
|
+
complete: async () => 'AI generated response',
|
|
84
|
+
},
|
|
85
|
+
logger: {
|
|
86
|
+
info: (msg) => logs.push(msg),
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const result = await handler(
|
|
91
|
+
{ userId: 'user-789', prompt: 'Summarize this document' },
|
|
92
|
+
mockContext,
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
assert.strictEqual(result.saveId, 'save-id-456');
|
|
96
|
+
assert.strictEqual(result.response, 'AI generated response');
|
|
97
|
+
assert.ok(logs.length > 0);
|
|
98
|
+
});
|
|
99
|
+
});
|