@hazeljs/agent 0.2.0-beta.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/IMPLEMENTATION_SUMMARY.md +400 -0
- package/PERSISTENCE.md +201 -0
- package/PRISMA_INTEGRATION.md +499 -0
- package/PRODUCTION_READINESS.md +264 -0
- package/QUICKSTART.md +135 -0
- package/README.md +427 -0
- package/STATE_VS_MEMORY.md +243 -0
- package/dist/agent.module.d.ts +42 -0
- package/dist/agent.module.d.ts.map +1 -0
- package/dist/agent.module.js +90 -0
- package/dist/agent.module.js.map +1 -0
- package/dist/context/agent.context.d.ts +27 -0
- package/dist/context/agent.context.d.ts.map +1 -0
- package/dist/context/agent.context.js +98 -0
- package/dist/context/agent.context.js.map +1 -0
- package/dist/decorators/agent.decorator.d.ts +21 -0
- package/dist/decorators/agent.decorator.d.ts.map +1 -0
- package/dist/decorators/agent.decorator.js +38 -0
- package/dist/decorators/agent.decorator.js.map +1 -0
- package/dist/decorators/tool.decorator.d.ts +23 -0
- package/dist/decorators/tool.decorator.d.ts.map +1 -0
- package/dist/decorators/tool.decorator.js +61 -0
- package/dist/decorators/tool.decorator.js.map +1 -0
- package/dist/events/event.emitter.d.ts +45 -0
- package/dist/events/event.emitter.d.ts.map +1 -0
- package/dist/events/event.emitter.js +96 -0
- package/dist/events/event.emitter.js.map +1 -0
- package/dist/executor/agent.executor.d.ts +57 -0
- package/dist/executor/agent.executor.d.ts.map +1 -0
- package/dist/executor/agent.executor.js +303 -0
- package/dist/executor/agent.executor.js.map +1 -0
- package/dist/executor/tool.executor.d.ts +53 -0
- package/dist/executor/tool.executor.d.ts.map +1 -0
- package/dist/executor/tool.executor.js +234 -0
- package/dist/executor/tool.executor.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/dist/registry/agent.registry.d.ts +49 -0
- package/dist/registry/agent.registry.d.ts.map +1 -0
- package/dist/registry/agent.registry.js +90 -0
- package/dist/registry/agent.registry.js.map +1 -0
- package/dist/registry/tool.registry.d.ts +54 -0
- package/dist/registry/tool.registry.d.ts.map +1 -0
- package/dist/registry/tool.registry.js +153 -0
- package/dist/registry/tool.registry.js.map +1 -0
- package/dist/runtime/agent.runtime.d.ts +155 -0
- package/dist/runtime/agent.runtime.d.ts.map +1 -0
- package/dist/runtime/agent.runtime.extensions.d.ts +49 -0
- package/dist/runtime/agent.runtime.extensions.d.ts.map +1 -0
- package/dist/runtime/agent.runtime.extensions.js +93 -0
- package/dist/runtime/agent.runtime.extensions.js.map +1 -0
- package/dist/runtime/agent.runtime.js +347 -0
- package/dist/runtime/agent.runtime.js.map +1 -0
- package/dist/state/agent-state.interface.d.ts +63 -0
- package/dist/state/agent-state.interface.d.ts.map +1 -0
- package/dist/state/agent-state.interface.js +7 -0
- package/dist/state/agent-state.interface.js.map +1 -0
- package/dist/state/agent.state.d.ts +67 -0
- package/dist/state/agent.state.d.ts.map +1 -0
- package/dist/state/agent.state.js +172 -0
- package/dist/state/agent.state.js.map +1 -0
- package/dist/state/database-state.manager.d.ts +63 -0
- package/dist/state/database-state.manager.d.ts.map +1 -0
- package/dist/state/database-state.manager.js +282 -0
- package/dist/state/database-state.manager.js.map +1 -0
- package/dist/state/redis-state.manager.d.ts +81 -0
- package/dist/state/redis-state.manager.d.ts.map +1 -0
- package/dist/state/redis-state.manager.js +253 -0
- package/dist/state/redis-state.manager.js.map +1 -0
- package/dist/types/agent.types.d.ts +151 -0
- package/dist/types/agent.types.d.ts.map +1 -0
- package/dist/types/agent.types.js +32 -0
- package/dist/types/agent.types.js.map +1 -0
- package/dist/types/event.types.d.ts +123 -0
- package/dist/types/event.types.d.ts.map +1 -0
- package/dist/types/event.types.js +30 -0
- package/dist/types/event.types.js.map +1 -0
- package/dist/types/llm.types.d.ts +66 -0
- package/dist/types/llm.types.d.ts.map +1 -0
- package/dist/types/llm.types.js +7 -0
- package/dist/types/llm.types.js.map +1 -0
- package/dist/types/rag.types.d.ts +40 -0
- package/dist/types/rag.types.d.ts.map +1 -0
- package/dist/types/rag.types.js +7 -0
- package/dist/types/rag.types.js.map +1 -0
- package/dist/types/tool.types.d.ts +118 -0
- package/dist/types/tool.types.d.ts.map +1 -0
- package/dist/types/tool.types.js +19 -0
- package/dist/types/tool.types.js.map +1 -0
- package/dist/utils/circuit-breaker.d.ts +69 -0
- package/dist/utils/circuit-breaker.d.ts.map +1 -0
- package/dist/utils/circuit-breaker.js +156 -0
- package/dist/utils/circuit-breaker.js.map +1 -0
- package/dist/utils/health-check.d.ts +71 -0
- package/dist/utils/health-check.d.ts.map +1 -0
- package/dist/utils/health-check.js +156 -0
- package/dist/utils/health-check.js.map +1 -0
- package/dist/utils/logger.d.ts +53 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +133 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/metrics.d.ts +90 -0
- package/dist/utils/metrics.d.ts.map +1 -0
- package/dist/utils/metrics.js +186 -0
- package/dist/utils/metrics.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts +44 -0
- package/dist/utils/rate-limiter.d.ts.map +1 -0
- package/dist/utils/rate-limiter.js +82 -0
- package/dist/utils/rate-limiter.js.map +1 -0
- package/dist/utils/retry.d.ts +42 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +103 -0
- package/dist/utils/retry.js.map +1 -0
- package/package.json +58 -0
- package/prisma-schema.example.prisma +76 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiter
|
|
3
|
+
* Token bucket algorithm for rate limiting agent executions
|
|
4
|
+
*/
|
|
5
|
+
export interface RateLimiterConfig {
|
|
6
|
+
tokensPerMinute: number;
|
|
7
|
+
burstSize?: number;
|
|
8
|
+
}
|
|
9
|
+
export declare class RateLimiter {
|
|
10
|
+
private tokens;
|
|
11
|
+
private lastRefill;
|
|
12
|
+
private readonly tokensPerMinute;
|
|
13
|
+
private readonly burstSize;
|
|
14
|
+
private readonly refillRate;
|
|
15
|
+
constructor(config: RateLimiterConfig);
|
|
16
|
+
/**
|
|
17
|
+
* Try to consume a token
|
|
18
|
+
* @returns true if token was consumed, false if rate limit exceeded
|
|
19
|
+
*/
|
|
20
|
+
tryConsume(): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Wait until a token is available
|
|
23
|
+
* @param timeoutMs Maximum time to wait in milliseconds
|
|
24
|
+
* @returns true if token was acquired, false if timeout
|
|
25
|
+
*/
|
|
26
|
+
waitForToken(timeoutMs?: number): Promise<boolean>;
|
|
27
|
+
/**
|
|
28
|
+
* Get current token count
|
|
29
|
+
*/
|
|
30
|
+
getAvailableTokens(): number;
|
|
31
|
+
/**
|
|
32
|
+
* Reset the rate limiter
|
|
33
|
+
*/
|
|
34
|
+
reset(): void;
|
|
35
|
+
/**
|
|
36
|
+
* Refill tokens based on elapsed time
|
|
37
|
+
*/
|
|
38
|
+
private refill;
|
|
39
|
+
/**
|
|
40
|
+
* Sleep utility
|
|
41
|
+
*/
|
|
42
|
+
private sleep;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=rate-limiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../src/utils/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,MAAM,EAAE,iBAAiB;IAQrC;;;OAGG;IACH,UAAU,IAAI,OAAO;IAWrB;;;;OAIG;IACG,YAAY,CAAC,SAAS,GAAE,MAAc,GAAG,OAAO,CAAC,OAAO,CAAC;IAsB/D;;OAEG;IACH,kBAAkB,IAAI,MAAM;IAK5B;;OAEG;IACH,KAAK,IAAI,IAAI;IAKb;;OAEG;IACH,OAAO,CAAC,MAAM;IASd;;OAEG;IACH,OAAO,CAAC,KAAK;CAGd"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Rate Limiter
|
|
4
|
+
* Token bucket algorithm for rate limiting agent executions
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.RateLimiter = void 0;
|
|
8
|
+
class RateLimiter {
|
|
9
|
+
constructor(config) {
|
|
10
|
+
this.tokensPerMinute = config.tokensPerMinute;
|
|
11
|
+
this.burstSize = config.burstSize || config.tokensPerMinute;
|
|
12
|
+
this.tokens = this.burstSize;
|
|
13
|
+
this.lastRefill = Date.now();
|
|
14
|
+
this.refillRate = this.tokensPerMinute / 60000; // tokens per millisecond
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Try to consume a token
|
|
18
|
+
* @returns true if token was consumed, false if rate limit exceeded
|
|
19
|
+
*/
|
|
20
|
+
tryConsume() {
|
|
21
|
+
this.refill();
|
|
22
|
+
if (this.tokens >= 1) {
|
|
23
|
+
this.tokens -= 1;
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Wait until a token is available
|
|
30
|
+
* @param timeoutMs Maximum time to wait in milliseconds
|
|
31
|
+
* @returns true if token was acquired, false if timeout
|
|
32
|
+
*/
|
|
33
|
+
async waitForToken(timeoutMs = 30000) {
|
|
34
|
+
const startTime = Date.now();
|
|
35
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
36
|
+
if (this.tryConsume()) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
// Calculate wait time until next token
|
|
40
|
+
const tokensNeeded = 1 - this.tokens;
|
|
41
|
+
const waitMs = Math.ceil(tokensNeeded / this.refillRate);
|
|
42
|
+
const remainingTimeout = timeoutMs - (Date.now() - startTime);
|
|
43
|
+
const actualWaitMs = Math.min(waitMs, remainingTimeout, 1000);
|
|
44
|
+
if (actualWaitMs > 0) {
|
|
45
|
+
await this.sleep(actualWaitMs);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get current token count
|
|
52
|
+
*/
|
|
53
|
+
getAvailableTokens() {
|
|
54
|
+
this.refill();
|
|
55
|
+
return Math.floor(this.tokens);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Reset the rate limiter
|
|
59
|
+
*/
|
|
60
|
+
reset() {
|
|
61
|
+
this.tokens = this.burstSize;
|
|
62
|
+
this.lastRefill = Date.now();
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Refill tokens based on elapsed time
|
|
66
|
+
*/
|
|
67
|
+
refill() {
|
|
68
|
+
const now = Date.now();
|
|
69
|
+
const elapsed = now - this.lastRefill;
|
|
70
|
+
const tokensToAdd = elapsed * this.refillRate;
|
|
71
|
+
this.tokens = Math.min(this.burstSize, this.tokens + tokensToAdd);
|
|
72
|
+
this.lastRefill = now;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Sleep utility
|
|
76
|
+
*/
|
|
77
|
+
sleep(ms) {
|
|
78
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
exports.RateLimiter = RateLimiter;
|
|
82
|
+
//# sourceMappingURL=rate-limiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/utils/rate-limiter.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAOH,MAAa,WAAW;IAOtB,YAAY,MAAyB;QACnC,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;QAC9C,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,eAAe,CAAC;QAC5D,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC,CAAC,yBAAyB;IAC3E,CAAC;IAED;;;OAGG;IACH,UAAU;QACR,IAAI,CAAC,MAAM,EAAE,CAAC;QAEd,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YACrB,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;YACjB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,YAAY,CAAC,YAAoB,KAAK;QAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,SAAS,EAAE,CAAC;YAC1C,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;gBACtB,OAAO,IAAI,CAAC;YACd,CAAC;YAED,uCAAuC;YACvC,MAAM,YAAY,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;YACrC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;YACzD,MAAM,gBAAgB,GAAG,SAAS,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;YAC9D,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,CAAC,CAAC;YAE9D,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;gBACrB,MAAM,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,kBAAkB;QAChB,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC/B,CAAC;IAED;;OAEG;IACK,MAAM;QACZ,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC;QACtC,MAAM,WAAW,GAAG,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC;QAE9C,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC,CAAC;QAClE,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC;IACxB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,EAAU;QACtB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IAC3D,CAAC;CACF;AA3FD,kCA2FC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry Logic with Exponential Backoff
|
|
3
|
+
* Handles transient failures with configurable retry strategies
|
|
4
|
+
*/
|
|
5
|
+
export interface RetryConfig {
|
|
6
|
+
maxRetries: number;
|
|
7
|
+
initialDelayMs: number;
|
|
8
|
+
maxDelayMs: number;
|
|
9
|
+
backoffMultiplier: number;
|
|
10
|
+
retryableErrors?: string[];
|
|
11
|
+
onRetry?: (attempt: number, error: Error) => void;
|
|
12
|
+
}
|
|
13
|
+
export declare class RetryError extends Error {
|
|
14
|
+
readonly attempts: number;
|
|
15
|
+
readonly lastError: Error;
|
|
16
|
+
constructor(message: string, attempts: number, lastError: Error);
|
|
17
|
+
}
|
|
18
|
+
export declare class RetryHandler {
|
|
19
|
+
private config;
|
|
20
|
+
constructor(config?: Partial<RetryConfig>);
|
|
21
|
+
/**
|
|
22
|
+
* Execute a function with retry logic
|
|
23
|
+
*/
|
|
24
|
+
execute<T>(fn: () => Promise<T>): Promise<T>;
|
|
25
|
+
/**
|
|
26
|
+
* Check if an error is retryable
|
|
27
|
+
*/
|
|
28
|
+
private isRetryable;
|
|
29
|
+
/**
|
|
30
|
+
* Calculate delay with exponential backoff and jitter
|
|
31
|
+
*/
|
|
32
|
+
private calculateDelay;
|
|
33
|
+
/**
|
|
34
|
+
* Sleep utility
|
|
35
|
+
*/
|
|
36
|
+
private sleep;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Decorator for automatic retry
|
|
40
|
+
*/
|
|
41
|
+
export declare function Retry(config?: Partial<RetryConfig>): MethodDecorator;
|
|
42
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACnD;AAED,qBAAa,UAAW,SAAQ,KAAK;aAGjB,QAAQ,EAAE,MAAM;aAChB,SAAS,EAAE,KAAK;gBAFhC,OAAO,EAAE,MAAM,EACC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,KAAK;CAKnC;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAwB;gBAE1B,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM;IAmB7C;;OAEG;IACG,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAqClD;;OAEG;IACH,OAAO,CAAC,WAAW;IAWnB;;OAEG;IACH,OAAO,CAAC,cAAc;IAYtB;;OAEG;IACH,OAAO,CAAC,KAAK;CAGd;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,eAAe,CAYpE"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Retry Logic with Exponential Backoff
|
|
4
|
+
* Handles transient failures with configurable retry strategies
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.RetryHandler = exports.RetryError = void 0;
|
|
8
|
+
exports.Retry = Retry;
|
|
9
|
+
class RetryError extends Error {
|
|
10
|
+
constructor(message, attempts, lastError) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.attempts = attempts;
|
|
13
|
+
this.lastError = lastError;
|
|
14
|
+
this.name = 'RetryError';
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.RetryError = RetryError;
|
|
18
|
+
class RetryHandler {
|
|
19
|
+
constructor(config = {}) {
|
|
20
|
+
this.config = {
|
|
21
|
+
maxRetries: config.maxRetries ?? 3,
|
|
22
|
+
initialDelayMs: config.initialDelayMs ?? 1000,
|
|
23
|
+
maxDelayMs: config.maxDelayMs ?? 30000,
|
|
24
|
+
backoffMultiplier: config.backoffMultiplier ?? 2,
|
|
25
|
+
retryableErrors: config.retryableErrors ?? [
|
|
26
|
+
'ECONNRESET',
|
|
27
|
+
'ETIMEDOUT',
|
|
28
|
+
'ENOTFOUND',
|
|
29
|
+
'ECONNREFUSED',
|
|
30
|
+
'RATE_LIMIT',
|
|
31
|
+
'SERVICE_UNAVAILABLE',
|
|
32
|
+
'TIMEOUT',
|
|
33
|
+
],
|
|
34
|
+
onRetry: config.onRetry ?? (() => { }),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Execute a function with retry logic
|
|
39
|
+
*/
|
|
40
|
+
async execute(fn) {
|
|
41
|
+
let lastError;
|
|
42
|
+
let attempt = 0;
|
|
43
|
+
while (attempt <= this.config.maxRetries) {
|
|
44
|
+
try {
|
|
45
|
+
return await fn();
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
lastError = error;
|
|
49
|
+
attempt++;
|
|
50
|
+
if (attempt > this.config.maxRetries) {
|
|
51
|
+
throw new RetryError(`Failed after ${attempt} attempts: ${lastError.message}`, attempt, lastError);
|
|
52
|
+
}
|
|
53
|
+
if (!this.isRetryable(lastError)) {
|
|
54
|
+
throw lastError;
|
|
55
|
+
}
|
|
56
|
+
const delay = this.calculateDelay(attempt);
|
|
57
|
+
this.config.onRetry(attempt, lastError);
|
|
58
|
+
await this.sleep(delay);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
throw new RetryError(`Failed after ${attempt} attempts: ${lastError.message}`, attempt, lastError);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Check if an error is retryable
|
|
65
|
+
*/
|
|
66
|
+
isRetryable(error) {
|
|
67
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
68
|
+
const errorCode = error.code || error.name;
|
|
69
|
+
const errorMessage = error.message.toUpperCase();
|
|
70
|
+
return this.config.retryableErrors.some((retryableError) => errorCode === retryableError || errorMessage.includes(retryableError.toUpperCase()));
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Calculate delay with exponential backoff and jitter
|
|
74
|
+
*/
|
|
75
|
+
calculateDelay(attempt) {
|
|
76
|
+
const exponentialDelay = this.config.initialDelayMs * Math.pow(this.config.backoffMultiplier, attempt - 1);
|
|
77
|
+
const delayWithCap = Math.min(exponentialDelay, this.config.maxDelayMs);
|
|
78
|
+
// Add jitter (±25%)
|
|
79
|
+
const jitter = delayWithCap * 0.25 * (Math.random() * 2 - 1);
|
|
80
|
+
return Math.max(0, delayWithCap + jitter);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Sleep utility
|
|
84
|
+
*/
|
|
85
|
+
sleep(ms) {
|
|
86
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
exports.RetryHandler = RetryHandler;
|
|
90
|
+
/**
|
|
91
|
+
* Decorator for automatic retry
|
|
92
|
+
*/
|
|
93
|
+
function Retry(config) {
|
|
94
|
+
const retryHandler = new RetryHandler(config);
|
|
95
|
+
return function (target, propertyKey, descriptor) {
|
|
96
|
+
const originalMethod = descriptor.value;
|
|
97
|
+
descriptor.value = async function (...args) {
|
|
98
|
+
return retryHandler.execute(() => originalMethod.apply(this, args));
|
|
99
|
+
};
|
|
100
|
+
return descriptor;
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hazeljs/agent",
|
|
3
|
+
"version": "0.2.0-beta.1",
|
|
4
|
+
"description": "AI-native Agent Runtime for HazelJS - stateful, long-running agents with tools, memory, and human-in-the-loop",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc --build",
|
|
9
|
+
"test": "jest --coverage --passWithNoTests",
|
|
10
|
+
"test:watch": "jest --watch",
|
|
11
|
+
"lint": "eslint src --ext .ts",
|
|
12
|
+
"lint:fix": "eslint src --ext .ts --fix"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"hazeljs",
|
|
16
|
+
"agent",
|
|
17
|
+
"ai-agent",
|
|
18
|
+
"llm",
|
|
19
|
+
"agentic",
|
|
20
|
+
"agent-runtime",
|
|
21
|
+
"tools",
|
|
22
|
+
"memory",
|
|
23
|
+
"human-in-the-loop"
|
|
24
|
+
],
|
|
25
|
+
"author": "HazelJS Team",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/hazeljs/hazeljs",
|
|
30
|
+
"directory": "packages/agent"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@hazeljs/core": "file:../core",
|
|
34
|
+
"@hazeljs/rag": "file:../rag",
|
|
35
|
+
"reflect-metadata": "^0.2.1"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/jest": "^29.5.11",
|
|
39
|
+
"@types/node": "^20.10.0",
|
|
40
|
+
"jest": "^29.7.0",
|
|
41
|
+
"ts-jest": "^29.1.1",
|
|
42
|
+
"typescript": "^5.3.3"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"@hazeljs/core": ">=0.2.0",
|
|
46
|
+
"@hazeljs/rag": ">=0.1.0"
|
|
47
|
+
},
|
|
48
|
+
"peerDependenciesMeta": {
|
|
49
|
+
"redis": {
|
|
50
|
+
"optional": true,
|
|
51
|
+
"description": "Required for RedisStateManager"
|
|
52
|
+
},
|
|
53
|
+
"@prisma/client": {
|
|
54
|
+
"optional": true,
|
|
55
|
+
"description": "Required for DatabaseStateManager"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Example Prisma schema for Agent State Persistence
|
|
2
|
+
//
|
|
3
|
+
// INSTRUCTIONS:
|
|
4
|
+
// 1. Copy the models below into your existing prisma/schema.prisma file
|
|
5
|
+
// 2. Run: npx prisma migrate dev --name add_agent_state_models
|
|
6
|
+
// 3. Run: npx prisma generate
|
|
7
|
+
// 4. See PRISMA_INTEGRATION.md for detailed instructions
|
|
8
|
+
//
|
|
9
|
+
// NOTE: This is an example file. You need to add these models to your actual schema.prisma
|
|
10
|
+
|
|
11
|
+
model AgentContext {
|
|
12
|
+
id String @id @default(uuid())
|
|
13
|
+
executionId String @unique
|
|
14
|
+
agentId String
|
|
15
|
+
sessionId String
|
|
16
|
+
userId String?
|
|
17
|
+
input String
|
|
18
|
+
state String // AgentState enum as string
|
|
19
|
+
steps Json // AgentStep[]
|
|
20
|
+
conversationHistory Json // ConversationMessage[]
|
|
21
|
+
workingMemory Json // Record<string, unknown>
|
|
22
|
+
facts Json // string[]
|
|
23
|
+
entities Json // Entity[]
|
|
24
|
+
ragContext Json? // string[]
|
|
25
|
+
metadata Json // Record<string, unknown>
|
|
26
|
+
createdAt DateTime @default(now())
|
|
27
|
+
updatedAt DateTime @updatedAt
|
|
28
|
+
deletedAt DateTime? // For soft deletes
|
|
29
|
+
agentSteps AgentStep[]? // Optional: relation to steps table
|
|
30
|
+
|
|
31
|
+
@@index([sessionId])
|
|
32
|
+
@@index([userId])
|
|
33
|
+
@@index([agentId])
|
|
34
|
+
@@index([state])
|
|
35
|
+
@@index([createdAt])
|
|
36
|
+
@@index([deletedAt])
|
|
37
|
+
@@map("agent_contexts")
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Optional: Separate table for execution steps (for better querying)
|
|
41
|
+
model AgentStep {
|
|
42
|
+
id String @id @default(uuid())
|
|
43
|
+
executionId String
|
|
44
|
+
stepNumber Int
|
|
45
|
+
state String
|
|
46
|
+
action Json?
|
|
47
|
+
result Json?
|
|
48
|
+
error String?
|
|
49
|
+
timestamp DateTime @default(now())
|
|
50
|
+
duration Int?
|
|
51
|
+
|
|
52
|
+
context AgentContext @relation(fields: [executionId], references: [executionId], onDelete: Cascade)
|
|
53
|
+
|
|
54
|
+
// Note: If you don't want a separate steps table, remove this model
|
|
55
|
+
// and store steps as JSON in AgentContext.steps field
|
|
56
|
+
|
|
57
|
+
@@index([executionId])
|
|
58
|
+
@@index([timestamp])
|
|
59
|
+
@@map("agent_steps")
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Optional: Session tracking
|
|
63
|
+
model AgentSession {
|
|
64
|
+
id String @id @default(uuid())
|
|
65
|
+
sessionId String @unique
|
|
66
|
+
userId String?
|
|
67
|
+
agentId String
|
|
68
|
+
createdAt DateTime @default(now())
|
|
69
|
+
updatedAt DateTime @updatedAt
|
|
70
|
+
completedAt DateTime?
|
|
71
|
+
|
|
72
|
+
@@index([userId])
|
|
73
|
+
@@index([agentId])
|
|
74
|
+
@@index([createdAt])
|
|
75
|
+
@@map("agent_sessions")
|
|
76
|
+
}
|