universal-agent-memory 0.6.1 β 0.6.3
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/dist/benchmarks/agents/naive-agent.d.ts +60 -0
- package/dist/benchmarks/agents/naive-agent.d.ts.map +1 -0
- package/dist/benchmarks/agents/naive-agent.js +144 -0
- package/dist/benchmarks/agents/naive-agent.js.map +1 -0
- package/dist/benchmarks/agents/uam-agent.d.ts +167 -0
- package/dist/benchmarks/agents/uam-agent.d.ts.map +1 -0
- package/dist/benchmarks/agents/uam-agent.js +386 -0
- package/dist/benchmarks/agents/uam-agent.js.map +1 -0
- package/dist/benchmarks/benchmark.d.ts +328 -0
- package/dist/benchmarks/benchmark.d.ts.map +1 -0
- package/dist/benchmarks/benchmark.js +104 -0
- package/dist/benchmarks/benchmark.js.map +1 -0
- package/dist/benchmarks/execution-verifier.d.ts +41 -0
- package/dist/benchmarks/execution-verifier.d.ts.map +1 -0
- package/dist/benchmarks/execution-verifier.js +301 -0
- package/dist/benchmarks/execution-verifier.js.map +1 -0
- package/dist/benchmarks/hierarchical-prompting.d.ts +37 -0
- package/dist/benchmarks/hierarchical-prompting.d.ts.map +1 -0
- package/dist/benchmarks/hierarchical-prompting.js +260 -0
- package/dist/benchmarks/hierarchical-prompting.js.map +1 -0
- package/dist/benchmarks/improved-benchmark.d.ts +88 -0
- package/dist/benchmarks/improved-benchmark.d.ts.map +1 -0
- package/dist/benchmarks/improved-benchmark.js +533 -0
- package/dist/benchmarks/improved-benchmark.js.map +1 -0
- package/dist/benchmarks/index.d.ts +10 -0
- package/dist/benchmarks/index.d.ts.map +1 -0
- package/dist/benchmarks/index.js +10 -0
- package/dist/benchmarks/index.js.map +1 -0
- package/dist/benchmarks/multi-turn-agent.d.ts +44 -0
- package/dist/benchmarks/multi-turn-agent.d.ts.map +1 -0
- package/dist/benchmarks/multi-turn-agent.js +235 -0
- package/dist/benchmarks/multi-turn-agent.js.map +1 -0
- package/dist/benchmarks/runner.d.ts +2 -0
- package/dist/benchmarks/runner.d.ts.map +1 -0
- package/dist/benchmarks/runner.js +2 -0
- package/dist/benchmarks/runner.js.map +1 -0
- package/dist/benchmarks/tasks.d.ts +19 -0
- package/dist/benchmarks/tasks.d.ts.map +1 -0
- package/dist/benchmarks/tasks.js +371 -0
- package/dist/benchmarks/tasks.js.map +1 -0
- package/dist/bin/cli.js +0 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/memory/backends/qdrant-cloud.d.ts +1 -1
- package/dist/memory/backends/qdrant-cloud.d.ts.map +1 -1
- package/dist/memory/backends/qdrant-cloud.js +6 -4
- package/dist/memory/backends/qdrant-cloud.js.map +1 -1
- package/dist/memory/dynamic-retrieval.d.ts +26 -0
- package/dist/memory/dynamic-retrieval.d.ts.map +1 -0
- package/dist/memory/dynamic-retrieval.js +378 -0
- package/dist/memory/dynamic-retrieval.js.map +1 -0
- package/dist/memory/embeddings.d.ts +82 -0
- package/dist/memory/embeddings.d.ts.map +1 -0
- package/dist/memory/embeddings.js +297 -0
- package/dist/memory/embeddings.js.map +1 -0
- package/dist/memory/task-classifier.d.ts +33 -0
- package/dist/memory/task-classifier.d.ts.map +1 -0
- package/dist/memory/task-classifier.js +277 -0
- package/dist/memory/task-classifier.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts +62 -0
- package/dist/utils/rate-limiter.d.ts.map +1 -0
- package/dist/utils/rate-limiter.js +150 -0
- package/dist/utils/rate-limiter.js.map +1 -0
- package/dist/utils/validate-json.d.ts +52 -0
- package/dist/utils/validate-json.d.ts.map +1 -0
- package/dist/utils/validate-json.js +99 -0
- package/dist/utils/validate-json.js.map +1 -0
- package/package.json +2 -1
- package/templates/CLAUDE.template.md +51 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration options for the RateLimiter.
|
|
3
|
+
*/
|
|
4
|
+
export interface RateLimiterConfig {
|
|
5
|
+
maxRequests: number;
|
|
6
|
+
windowMs: number;
|
|
7
|
+
}
|
|
8
|
+
export declare class RateLimiter {
|
|
9
|
+
private static readonly configSchema;
|
|
10
|
+
private static readonly clientIdSchema;
|
|
11
|
+
private readonly maxRequests;
|
|
12
|
+
private readonly windowMs;
|
|
13
|
+
private readonly requests;
|
|
14
|
+
/**
|
|
15
|
+
* Creates a new RateLimiter instance.
|
|
16
|
+
*
|
|
17
|
+
* @param config - Configuration for request limits and window size
|
|
18
|
+
* @returns A configured RateLimiter instance
|
|
19
|
+
* @throws AppError when config is invalid
|
|
20
|
+
*/
|
|
21
|
+
constructor(config: RateLimiterConfig);
|
|
22
|
+
/**
|
|
23
|
+
* Checks if a request from the given client is allowed and records it if so.
|
|
24
|
+
*
|
|
25
|
+
* @param clientId - Identifier for the calling client
|
|
26
|
+
* @returns True if the request is allowed; otherwise false
|
|
27
|
+
* @throws AppError when clientId is invalid
|
|
28
|
+
*/
|
|
29
|
+
isAllowed(clientId: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Returns the remaining number of requests for a client in the current window.
|
|
32
|
+
*
|
|
33
|
+
* @param clientId - Identifier for the calling client
|
|
34
|
+
* @returns Remaining number of requests in the window
|
|
35
|
+
* @throws AppError when clientId is invalid
|
|
36
|
+
*/
|
|
37
|
+
getRemainingRequests(clientId: string): number;
|
|
38
|
+
/**
|
|
39
|
+
* Resets rate limiting for a single client or all clients.
|
|
40
|
+
*
|
|
41
|
+
* @param clientId - Optional client identifier to reset; omit to reset all
|
|
42
|
+
* @returns Nothing
|
|
43
|
+
*/
|
|
44
|
+
reset(clientId?: string): void;
|
|
45
|
+
/**
|
|
46
|
+
* Removes expired timestamps and deletes empty client entries.
|
|
47
|
+
*
|
|
48
|
+
* @param now - Current timestamp used as reference
|
|
49
|
+
* @param clientId - Optional client identifier to scope cleanup
|
|
50
|
+
* @returns Nothing
|
|
51
|
+
*/
|
|
52
|
+
private cleanupExpiredEntries;
|
|
53
|
+
/**
|
|
54
|
+
* Ensures the client identifier is valid.
|
|
55
|
+
*
|
|
56
|
+
* @param clientId - Identifier to validate
|
|
57
|
+
* @returns Nothing
|
|
58
|
+
* @throws AppError when clientId is invalid
|
|
59
|
+
*/
|
|
60
|
+
private ensureValidClientId;
|
|
61
|
+
}
|
|
62
|
+
//# 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;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AASD,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAejC;IAEH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAKE;IAExC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoC;IAE7D;;;;;;OAMG;gBACS,MAAM,EAAE,iBAAiB;IAcrC;;;;;;OAMG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAgBpC;;;;;;OAMG;IACH,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAc9C;;;;;OAKG;IACH,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAU9B;;;;;;OAMG;IACH,OAAO,CAAC,qBAAqB;IAoC7B;;;;;;OAMG;IACH,OAAO,CAAC,mBAAmB;CAU5B"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A sliding-window rate limiter that tracks requests per client.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { AppError } from './validate-json.js';
|
|
6
|
+
export class RateLimiter {
|
|
7
|
+
static configSchema = z.object({
|
|
8
|
+
maxRequests: z
|
|
9
|
+
.number({
|
|
10
|
+
required_error: 'maxRequests is required',
|
|
11
|
+
invalid_type_error: 'maxRequests must be a number',
|
|
12
|
+
})
|
|
13
|
+
.int('maxRequests must be an integer')
|
|
14
|
+
.positive('maxRequests must be greater than 0'),
|
|
15
|
+
windowMs: z
|
|
16
|
+
.number({
|
|
17
|
+
required_error: 'windowMs is required',
|
|
18
|
+
invalid_type_error: 'windowMs must be a number',
|
|
19
|
+
})
|
|
20
|
+
.int('windowMs must be an integer')
|
|
21
|
+
.positive('windowMs must be greater than 0'),
|
|
22
|
+
});
|
|
23
|
+
static clientIdSchema = z
|
|
24
|
+
.string({
|
|
25
|
+
required_error: 'clientId is required',
|
|
26
|
+
invalid_type_error: 'clientId must be a string',
|
|
27
|
+
})
|
|
28
|
+
.min(1, 'clientId must not be empty');
|
|
29
|
+
maxRequests;
|
|
30
|
+
windowMs;
|
|
31
|
+
requests = new Map();
|
|
32
|
+
/**
|
|
33
|
+
* Creates a new RateLimiter instance.
|
|
34
|
+
*
|
|
35
|
+
* @param config - Configuration for request limits and window size
|
|
36
|
+
* @returns A configured RateLimiter instance
|
|
37
|
+
* @throws AppError when config is invalid
|
|
38
|
+
*/
|
|
39
|
+
constructor(config) {
|
|
40
|
+
const validation = RateLimiter.configSchema.safeParse(config);
|
|
41
|
+
if (!validation.success) {
|
|
42
|
+
throw new AppError('Invalid rate limiter configuration', 'INVALID_CONFIG', {
|
|
43
|
+
errors: validation.error.errors,
|
|
44
|
+
received: config,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
this.maxRequests = validation.data.maxRequests;
|
|
48
|
+
this.windowMs = validation.data.windowMs;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Checks if a request from the given client is allowed and records it if so.
|
|
52
|
+
*
|
|
53
|
+
* @param clientId - Identifier for the calling client
|
|
54
|
+
* @returns True if the request is allowed; otherwise false
|
|
55
|
+
* @throws AppError when clientId is invalid
|
|
56
|
+
*/
|
|
57
|
+
isAllowed(clientId) {
|
|
58
|
+
this.ensureValidClientId(clientId);
|
|
59
|
+
const now = Date.now();
|
|
60
|
+
this.cleanupExpiredEntries(now, clientId);
|
|
61
|
+
const timestamps = this.requests.get(clientId) ?? [];
|
|
62
|
+
if (timestamps.length < this.maxRequests) {
|
|
63
|
+
timestamps.push(now);
|
|
64
|
+
this.requests.set(clientId, timestamps);
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Returns the remaining number of requests for a client in the current window.
|
|
71
|
+
*
|
|
72
|
+
* @param clientId - Identifier for the calling client
|
|
73
|
+
* @returns Remaining number of requests in the window
|
|
74
|
+
* @throws AppError when clientId is invalid
|
|
75
|
+
*/
|
|
76
|
+
getRemainingRequests(clientId) {
|
|
77
|
+
this.ensureValidClientId(clientId);
|
|
78
|
+
const now = Date.now();
|
|
79
|
+
this.cleanupExpiredEntries(now, clientId);
|
|
80
|
+
const timestamps = this.requests.get(clientId);
|
|
81
|
+
if (!timestamps) {
|
|
82
|
+
return this.maxRequests;
|
|
83
|
+
}
|
|
84
|
+
return Math.max(0, this.maxRequests - timestamps.length);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Resets rate limiting for a single client or all clients.
|
|
88
|
+
*
|
|
89
|
+
* @param clientId - Optional client identifier to reset; omit to reset all
|
|
90
|
+
* @returns Nothing
|
|
91
|
+
*/
|
|
92
|
+
reset(clientId) {
|
|
93
|
+
if (clientId) {
|
|
94
|
+
this.ensureValidClientId(clientId);
|
|
95
|
+
this.requests.delete(clientId);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
this.requests.clear();
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Removes expired timestamps and deletes empty client entries.
|
|
102
|
+
*
|
|
103
|
+
* @param now - Current timestamp used as reference
|
|
104
|
+
* @param clientId - Optional client identifier to scope cleanup
|
|
105
|
+
* @returns Nothing
|
|
106
|
+
*/
|
|
107
|
+
cleanupExpiredEntries(now, clientId) {
|
|
108
|
+
const cutoff = now - this.windowMs;
|
|
109
|
+
if (clientId) {
|
|
110
|
+
const timestamps = this.requests.get(clientId);
|
|
111
|
+
if (!timestamps) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const validTimestamps = timestamps.filter((timestamp) => timestamp > cutoff);
|
|
115
|
+
if (validTimestamps.length === 0) {
|
|
116
|
+
this.requests.delete(clientId);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
this.requests.set(clientId, validTimestamps);
|
|
120
|
+
}
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
for (const [id, timestamps] of this.requests.entries()) {
|
|
124
|
+
const validTimestamps = timestamps.filter((timestamp) => timestamp > cutoff);
|
|
125
|
+
if (validTimestamps.length === 0) {
|
|
126
|
+
this.requests.delete(id);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
this.requests.set(id, validTimestamps);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Ensures the client identifier is valid.
|
|
135
|
+
*
|
|
136
|
+
* @param clientId - Identifier to validate
|
|
137
|
+
* @returns Nothing
|
|
138
|
+
* @throws AppError when clientId is invalid
|
|
139
|
+
*/
|
|
140
|
+
ensureValidClientId(clientId) {
|
|
141
|
+
const validation = RateLimiter.clientIdSchema.safeParse(clientId);
|
|
142
|
+
if (!validation.success) {
|
|
143
|
+
throw new AppError('Invalid client identifier', 'INVALID_CLIENT_ID', {
|
|
144
|
+
errors: validation.error.errors,
|
|
145
|
+
received: clientId,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=rate-limiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/utils/rate-limiter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error class for application-level errors with detailed context.
|
|
3
|
+
* Extends the built-in Error class to provide additional metadata.
|
|
4
|
+
*/
|
|
5
|
+
export declare class AppError extends Error {
|
|
6
|
+
/** Error code for programmatic handling */
|
|
7
|
+
readonly code: string;
|
|
8
|
+
/** Additional context about the error */
|
|
9
|
+
readonly context?: Record<string, unknown>;
|
|
10
|
+
/**
|
|
11
|
+
* Creates a new AppError instance.
|
|
12
|
+
*
|
|
13
|
+
* @param message - Human-readable error message
|
|
14
|
+
* @param code - Error code for programmatic handling
|
|
15
|
+
* @param context - Optional additional context
|
|
16
|
+
*/
|
|
17
|
+
constructor(message: string, code: string, context?: Record<string, unknown>);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Validates that a string is valid JSON and parses it.
|
|
21
|
+
*
|
|
22
|
+
* Uses zod for runtime validation to ensure the input is a valid string
|
|
23
|
+
* before attempting to parse. The parsed result is then validated
|
|
24
|
+
* against a permissive schema that accepts any valid JSON value.
|
|
25
|
+
*
|
|
26
|
+
* @param input - The string to validate and parse as JSON
|
|
27
|
+
* @returns The parsed JSON value (object, array, string, number, boolean, or null)
|
|
28
|
+
* @throws AppError with code 'INVALID_INPUT' if input is not a string
|
|
29
|
+
* @throws AppError with code 'JSON_PARSE_ERROR' if the string is not valid JSON
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* // Parse a valid JSON object
|
|
34
|
+
* const obj = validateAndParseJSON('{"name": "test", "value": 42}');
|
|
35
|
+
* // Returns: { name: "test", value: 42 }
|
|
36
|
+
*
|
|
37
|
+
* // Parse a valid JSON array
|
|
38
|
+
* const arr = validateAndParseJSON('[1, 2, 3]');
|
|
39
|
+
* // Returns: [1, 2, 3]
|
|
40
|
+
*
|
|
41
|
+
* // Invalid JSON throws AppError
|
|
42
|
+
* try {
|
|
43
|
+
* validateAndParseJSON('{invalid}');
|
|
44
|
+
* } catch (error) {
|
|
45
|
+
* if (error instanceof AppError) {
|
|
46
|
+
* console.log(error.code); // 'JSON_PARSE_ERROR'
|
|
47
|
+
* }
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare function validateAndParseJSON(input: string): Promise<unknown>;
|
|
52
|
+
//# sourceMappingURL=validate-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-json.d.ts","sourceRoot":"","sources":["../../src/utils/validate-json.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,2CAA2C;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE3C;;;;;;OAMG;gBAED,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAYpC;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAiD1E"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Custom error class for application-level errors with detailed context.
|
|
4
|
+
* Extends the built-in Error class to provide additional metadata.
|
|
5
|
+
*/
|
|
6
|
+
export class AppError extends Error {
|
|
7
|
+
/** Error code for programmatic handling */
|
|
8
|
+
code;
|
|
9
|
+
/** Additional context about the error */
|
|
10
|
+
context;
|
|
11
|
+
/**
|
|
12
|
+
* Creates a new AppError instance.
|
|
13
|
+
*
|
|
14
|
+
* @param message - Human-readable error message
|
|
15
|
+
* @param code - Error code for programmatic handling
|
|
16
|
+
* @param context - Optional additional context
|
|
17
|
+
*/
|
|
18
|
+
constructor(message, code, context) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.name = 'AppError';
|
|
21
|
+
this.code = code;
|
|
22
|
+
this.context = context;
|
|
23
|
+
// Maintains proper stack trace for where error was thrown (V8 engines)
|
|
24
|
+
if (Error.captureStackTrace) {
|
|
25
|
+
Error.captureStackTrace(this, AppError);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Zod schema for validating that a value is valid JSON.
|
|
31
|
+
* Accepts any valid JSON value (object, array, string, number, boolean, null).
|
|
32
|
+
*/
|
|
33
|
+
const jsonSchema = z.unknown();
|
|
34
|
+
/**
|
|
35
|
+
* Validates that a string is valid JSON and parses it.
|
|
36
|
+
*
|
|
37
|
+
* Uses zod for runtime validation to ensure the input is a valid string
|
|
38
|
+
* before attempting to parse. The parsed result is then validated
|
|
39
|
+
* against a permissive schema that accepts any valid JSON value.
|
|
40
|
+
*
|
|
41
|
+
* @param input - The string to validate and parse as JSON
|
|
42
|
+
* @returns The parsed JSON value (object, array, string, number, boolean, or null)
|
|
43
|
+
* @throws AppError with code 'INVALID_INPUT' if input is not a string
|
|
44
|
+
* @throws AppError with code 'JSON_PARSE_ERROR' if the string is not valid JSON
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* // Parse a valid JSON object
|
|
49
|
+
* const obj = validateAndParseJSON('{"name": "test", "value": 42}');
|
|
50
|
+
* // Returns: { name: "test", value: 42 }
|
|
51
|
+
*
|
|
52
|
+
* // Parse a valid JSON array
|
|
53
|
+
* const arr = validateAndParseJSON('[1, 2, 3]');
|
|
54
|
+
* // Returns: [1, 2, 3]
|
|
55
|
+
*
|
|
56
|
+
* // Invalid JSON throws AppError
|
|
57
|
+
* try {
|
|
58
|
+
* validateAndParseJSON('{invalid}');
|
|
59
|
+
* } catch (error) {
|
|
60
|
+
* if (error instanceof AppError) {
|
|
61
|
+
* console.log(error.code); // 'JSON_PARSE_ERROR'
|
|
62
|
+
* }
|
|
63
|
+
* }
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export async function validateAndParseJSON(input) {
|
|
67
|
+
// Validate input is a string using zod
|
|
68
|
+
const stringSchema = z.string({
|
|
69
|
+
required_error: 'Input is required',
|
|
70
|
+
invalid_type_error: 'Input must be a string',
|
|
71
|
+
});
|
|
72
|
+
const validationResult = stringSchema.safeParse(input);
|
|
73
|
+
if (!validationResult.success) {
|
|
74
|
+
throw new AppError('Input must be a valid string', 'INVALID_INPUT', {
|
|
75
|
+
errors: validationResult.error.errors,
|
|
76
|
+
receivedType: typeof input,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
// Attempt to parse the JSON string
|
|
80
|
+
let parsed;
|
|
81
|
+
try {
|
|
82
|
+
parsed = JSON.parse(validationResult.data);
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
throw new AppError(`Failed to parse JSON: ${error instanceof Error ? error.message : 'Unknown error'}`, 'JSON_PARSE_ERROR', {
|
|
86
|
+
input: input.length > 100 ? `${input.substring(0, 100)}...` : input,
|
|
87
|
+
originalError: error instanceof Error ? error.message : String(error),
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
// Validate the parsed result with zod (accepts any valid JSON value)
|
|
91
|
+
const parseResult = jsonSchema.safeParse(parsed);
|
|
92
|
+
if (!parseResult.success) {
|
|
93
|
+
throw new AppError('Parsed value failed schema validation', 'SCHEMA_VALIDATION_ERROR', {
|
|
94
|
+
errors: parseResult.error.errors,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return parseResult.data;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=validate-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-json.js","sourceRoot":"","sources":["../../src/utils/validate-json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,MAAM,OAAO,QAAS,SAAQ,KAAK;IACjC,2CAA2C;IAClC,IAAI,CAAS;IACtB,yCAAyC;IAChC,OAAO,CAA2B;IAE3C;;;;;;OAMG;IACH,YACE,OAAe,EACf,IAAY,EACZ,OAAiC;QAEjC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QAEvB,uEAAuE;QACvE,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;YAC5B,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;AAE/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,KAAa;IACtD,uCAAuC;IACvC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;QAC5B,cAAc,EAAE,mBAAmB;QACnC,kBAAkB,EAAE,wBAAwB;KAC7C,CAAC,CAAC;IAEH,MAAM,gBAAgB,GAAG,YAAY,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAEvD,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC;QAC9B,MAAM,IAAI,QAAQ,CAChB,8BAA8B,EAC9B,eAAe,EACf;YACE,MAAM,EAAE,gBAAgB,CAAC,KAAK,CAAC,MAAM;YACrC,YAAY,EAAE,OAAO,KAAK;SAC3B,CACF,CAAC;IACJ,CAAC;IAED,mCAAmC;IACnC,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,QAAQ,CAChB,yBAAyB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,EACnF,kBAAkB,EAClB;YACE,KAAK,EAAE,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK;YACnE,aAAa,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SACtE,CACF,CAAC;IACJ,CAAC;IAED,qEAAqE;IACrE,MAAM,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAEjD,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QACzB,MAAM,IAAI,QAAQ,CAChB,uCAAuC,EACvC,yBAAyB,EACzB;YACE,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM;SACjC,CACF,CAAC;IACJ,CAAC;IAED,OAAO,WAAW,CAAC,IAAI,CAAC;AAC1B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "universal-agent-memory",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.3",
|
|
4
4
|
"description": "Universal AI agent memory system - CLAUDE.md templates, memory, worktrees for Claude Code, Factory.AI, VSCode, OpenCode",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
"eslint": "^8.56.0",
|
|
79
79
|
"fake-indexeddb": "^6.0.0",
|
|
80
80
|
"prettier": "^3.2.4",
|
|
81
|
+
"tsx": "^4.21.0",
|
|
81
82
|
"typescript": "^5.3.3",
|
|
82
83
|
"vitest": "^1.2.0"
|
|
83
84
|
},
|
|
@@ -188,6 +188,56 @@ multi_tool_use.parallel([
|
|
|
188
188
|
|
|
189
189
|
---
|
|
190
190
|
|
|
191
|
+
## π§© MULTI-AGENT EXECUTION (DEPENDENCY-AWARE)
|
|
192
|
+
|
|
193
|
+
**Goal**: Finish faster by parallelizing independent work while preserving correctness and avoiding conflicts.
|
|
194
|
+
|
|
195
|
+
**Aggressive parallelization mandate**: Default to multi-agent execution whenever tasks can be safely decomposed; only stay single-threaded when dependencies or overlap risk make parallel work unsafe.
|
|
196
|
+
|
|
197
|
+
**Process**:
|
|
198
|
+
1. **Decompose** the request into discrete work items with clear inputs/outputs.
|
|
199
|
+
2. **Map dependencies** (A blocks B). Only run B after A is complete.
|
|
200
|
+
3. **Parallelize** dependency-free items with separate agents and explicit file boundaries.
|
|
201
|
+
4. **Gate edits** with `uam agent overlaps --resource "<files>"` before touching any file.
|
|
202
|
+
5. **Merge in dependency order** (upstream first). Rebase or re-run dependent steps if needed.
|
|
203
|
+
|
|
204
|
+
**When to expand the agent pool**:
|
|
205
|
+
- Multiple files/modules with low coupling
|
|
206
|
+
- Parallel research or analysis tasks
|
|
207
|
+
- Independent test or verification tasks
|
|
208
|
+
|
|
209
|
+
**Example**:
|
|
210
|
+
```bash
|
|
211
|
+
# Parallel research tasks (dependency-free)
|
|
212
|
+
Task(subagent_type: "security-auditor", prompt: "Threat model: auth flow in src/auth/*")
|
|
213
|
+
Task(subagent_type: "performance-optimizer", prompt: "Find hotspots in src/cache/*")
|
|
214
|
+
|
|
215
|
+
# Dependent work (sequential)
|
|
216
|
+
# 1) Agent A updates schema β 2) Agent B updates queries β 3) Agent C updates tests
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**Conflict avoidance**:
|
|
220
|
+
- One agent per file at a time
|
|
221
|
+
- Declare file ownership in prompts
|
|
222
|
+
- If overlap risk is high, wait or split by section
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## π οΈ SKILLFORGE MODE (OPTIONAL)
|
|
227
|
+
|
|
228
|
+
**Use when**: The request is to create, improve, or compose skills (not regular feature work).
|
|
229
|
+
|
|
230
|
+
**Phases**:
|
|
231
|
+
0. **Triage** β USE_EXISTING / IMPROVE_EXISTING / CREATE_NEW / COMPOSE
|
|
232
|
+
1. **Deep Analysis** (multiβlens, edge cases, constraints)
|
|
233
|
+
2. **Specification** (structured skill spec)
|
|
234
|
+
3. **Generation** (implement skill)
|
|
235
|
+
4. **MultiβAgent Synthesis** (quality + security + evolution approval)
|
|
236
|
+
|
|
237
|
+
**Fallback**: If SkillForge scripts/requirements are unavailable, use the existing skill routing matrix and create skills manually in `{{SKILLS_PATH}}`.
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
191
241
|
## π§Ύ TOKEN EFFICIENCY RULES
|
|
192
242
|
|
|
193
243
|
- Prefer concise, high-signal responses; avoid repeating instructions or large logs.
|
|
@@ -216,7 +266,7 @@ multi_tool_use.parallel([
|
|
|
216
266
|
β β
|
|
217
267
|
β 4. WORKTREE β {{WORKTREE_CREATE_CMD}} <slug> β
|
|
218
268
|
β β cd {{WORKTREE_DIR}}/NNN-<slug>/ β
|
|
219
|
-
β β NEVER commit to {{DEFAULT_BRANCH}}
|
|
269
|
+
β β NEVER commit directly to {{DEFAULT_BRANCH}} β
|
|
220
270
|
β β
|
|
221
271
|
β 5. WORK β Implement β Test β {{WORKTREE_PR_CMD}} β
|
|
222
272
|
β β
|