@mondaydotcomorg/atp-providers 0.17.16 → 0.18.4-rc.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/dist/audit/jsonl.d.ts +29 -0
- package/dist/audit/jsonl.d.ts.map +1 -0
- package/dist/audit/jsonl.js +163 -0
- package/dist/audit/jsonl.js.map +1 -0
- package/dist/audit/opentelemetry.d.ts +23 -0
- package/dist/audit/opentelemetry.d.ts.map +1 -0
- package/dist/audit/opentelemetry.js +240 -0
- package/dist/audit/opentelemetry.js.map +1 -0
- package/dist/audit/otel-metrics.d.ts +111 -0
- package/dist/audit/otel-metrics.d.ts.map +1 -0
- package/dist/audit/otel-metrics.js +115 -0
- package/dist/audit/otel-metrics.js.map +1 -0
- package/dist/auth/env.d.ts +21 -0
- package/dist/auth/env.d.ts.map +1 -0
- package/dist/auth/env.js +48 -0
- package/dist/auth/env.js.map +1 -0
- package/dist/cache/file.d.ts +47 -0
- package/dist/cache/file.d.ts.map +1 -0
- package/dist/cache/file.js +262 -0
- package/dist/cache/file.js.map +1 -0
- package/dist/cache/memory.d.ts +30 -0
- package/dist/cache/memory.d.ts.map +1 -0
- package/dist/cache/memory.js +81 -0
- package/dist/cache/memory.js.map +1 -0
- package/dist/cache/redis.d.ts +28 -0
- package/dist/cache/redis.d.ts.map +1 -0
- package/dist/cache/redis.js +124 -0
- package/dist/cache/redis.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/oauth/index.d.ts +2 -0
- package/dist/oauth/index.d.ts.map +1 -0
- package/dist/oauth/index.js +2 -0
- package/dist/oauth/index.js.map +1 -0
- package/dist/oauth/scope-checkers.d.ts +61 -0
- package/dist/oauth/scope-checkers.d.ts.map +1 -0
- package/dist/oauth/scope-checkers.js +166 -0
- package/dist/oauth/scope-checkers.js.map +1 -0
- package/package.json +8 -2
- package/project.json +1 -3
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenTelemetry Metrics Definitions
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Counter metric names
|
|
6
|
+
*/
|
|
7
|
+
export var OTelCounter;
|
|
8
|
+
(function (OTelCounter) {
|
|
9
|
+
OTelCounter["EXECUTIONS_TOTAL"] = "atp.executions.total";
|
|
10
|
+
OTelCounter["TOOLS_CALLS"] = "atp.tools.calls";
|
|
11
|
+
OTelCounter["LLM_CALLS"] = "atp.llm.calls";
|
|
12
|
+
OTelCounter["APPROVALS_TOTAL"] = "atp.approvals.total";
|
|
13
|
+
OTelCounter["SECURITY_EVENTS"] = "atp.security.events";
|
|
14
|
+
})(OTelCounter || (OTelCounter = {}));
|
|
15
|
+
/**
|
|
16
|
+
* Histogram metric names
|
|
17
|
+
*/
|
|
18
|
+
export var OTelHistogram;
|
|
19
|
+
(function (OTelHistogram) {
|
|
20
|
+
OTelHistogram["EXECUTION_DURATION"] = "atp.execution.duration";
|
|
21
|
+
OTelHistogram["TOOL_DURATION"] = "atp.tool.duration";
|
|
22
|
+
})(OTelHistogram || (OTelHistogram = {}));
|
|
23
|
+
/**
|
|
24
|
+
* Span/trace names
|
|
25
|
+
*/
|
|
26
|
+
export var OTelSpan;
|
|
27
|
+
(function (OTelSpan) {
|
|
28
|
+
OTelSpan["EXECUTION_START"] = "atp.execution.start";
|
|
29
|
+
OTelSpan["EXECUTION_COMPLETE"] = "atp.execution.complete";
|
|
30
|
+
OTelSpan["EXECUTION_PAUSE"] = "atp.execution.pause";
|
|
31
|
+
OTelSpan["EXECUTION_RESUME"] = "atp.execution.resume";
|
|
32
|
+
OTelSpan["EXECUTION_ERROR"] = "atp.execution.error";
|
|
33
|
+
OTelSpan["TOOL_CALL"] = "atp.tool_call";
|
|
34
|
+
OTelSpan["LLM_CALL"] = "atp.llm_call";
|
|
35
|
+
OTelSpan["APPROVAL_REQUEST"] = "atp.approval.request";
|
|
36
|
+
OTelSpan["APPROVAL_RESPONSE"] = "atp.approval.response";
|
|
37
|
+
OTelSpan["CLIENT_INIT"] = "atp.client_init";
|
|
38
|
+
OTelSpan["ERROR"] = "atp.error";
|
|
39
|
+
})(OTelSpan || (OTelSpan = {}));
|
|
40
|
+
/**
|
|
41
|
+
* Attribute names (for consistent span/metric attributes)
|
|
42
|
+
*/
|
|
43
|
+
export var OTelAttribute;
|
|
44
|
+
(function (OTelAttribute) {
|
|
45
|
+
OTelAttribute["EVENT_ID"] = "atp.event.id";
|
|
46
|
+
OTelAttribute["EVENT_TYPE"] = "atp.event.type";
|
|
47
|
+
OTelAttribute["EVENT_ACTION"] = "atp.event.action";
|
|
48
|
+
OTelAttribute["TIMESTAMP"] = "atp.timestamp";
|
|
49
|
+
OTelAttribute["CLIENT_ID"] = "atp.client.id";
|
|
50
|
+
OTelAttribute["USER_ID"] = "atp.user.id";
|
|
51
|
+
OTelAttribute["IP_ADDRESS"] = "atp.ip_address";
|
|
52
|
+
OTelAttribute["USER_AGENT"] = "atp.user_agent";
|
|
53
|
+
OTelAttribute["STATUS"] = "atp.status";
|
|
54
|
+
OTelAttribute["RESOURCE"] = "atp.resource";
|
|
55
|
+
OTelAttribute["RESOURCE_ID"] = "atp.resource.id";
|
|
56
|
+
OTelAttribute["TOOL_NAME"] = "atp.tool.name";
|
|
57
|
+
OTelAttribute["TOOL_INPUT_SIZE"] = "tool.input_size";
|
|
58
|
+
OTelAttribute["TOOL_OUTPUT_SIZE"] = "tool.output_size";
|
|
59
|
+
OTelAttribute["API_GROUP"] = "atp.api.group";
|
|
60
|
+
OTelAttribute["DURATION_MS"] = "atp.duration_ms";
|
|
61
|
+
OTelAttribute["MEMORY_BYTES"] = "atp.memory_bytes";
|
|
62
|
+
OTelAttribute["LLM_CALLS"] = "atp.llm_calls";
|
|
63
|
+
OTelAttribute["HTTP_CALLS"] = "atp.http_calls";
|
|
64
|
+
OTelAttribute["RISK_SCORE"] = "atp.security.risk_score";
|
|
65
|
+
OTelAttribute["SECURITY_EVENTS"] = "atp.security.events";
|
|
66
|
+
OTelAttribute["SECURITY_EVENTS_COUNT"] = "atp.security.events_count";
|
|
67
|
+
OTelAttribute["ERROR_MESSAGE"] = "atp.error.message";
|
|
68
|
+
OTelAttribute["ERROR_CODE"] = "atp.error.code";
|
|
69
|
+
OTelAttribute["ERROR_STACK"] = "atp.error.stack";
|
|
70
|
+
})(OTelAttribute || (OTelAttribute = {}));
|
|
71
|
+
/**
|
|
72
|
+
* Metric configurations
|
|
73
|
+
*/
|
|
74
|
+
export const METRIC_CONFIGS = {
|
|
75
|
+
[OTelCounter.EXECUTIONS_TOTAL]: {
|
|
76
|
+
description: 'Total number of executions',
|
|
77
|
+
unit: '1',
|
|
78
|
+
},
|
|
79
|
+
[OTelCounter.TOOLS_CALLS]: {
|
|
80
|
+
description: 'Tool call count',
|
|
81
|
+
unit: '1',
|
|
82
|
+
},
|
|
83
|
+
[OTelCounter.LLM_CALLS]: {
|
|
84
|
+
description: 'LLM call count',
|
|
85
|
+
unit: '1',
|
|
86
|
+
},
|
|
87
|
+
[OTelCounter.APPROVALS_TOTAL]: {
|
|
88
|
+
description: 'Approval request count',
|
|
89
|
+
unit: '1',
|
|
90
|
+
},
|
|
91
|
+
[OTelCounter.SECURITY_EVENTS]: {
|
|
92
|
+
description: 'Security events count',
|
|
93
|
+
unit: '1',
|
|
94
|
+
},
|
|
95
|
+
[OTelHistogram.EXECUTION_DURATION]: {
|
|
96
|
+
description: 'Execution duration in milliseconds',
|
|
97
|
+
unit: 'ms',
|
|
98
|
+
},
|
|
99
|
+
[OTelHistogram.TOOL_DURATION]: {
|
|
100
|
+
description: 'Tool execution duration',
|
|
101
|
+
unit: 'ms',
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* OpenTelemetry tracer and meter names
|
|
106
|
+
*/
|
|
107
|
+
export const OTEL_SERVICE_NAME = 'agent-tool-protocol';
|
|
108
|
+
export const OTEL_TRACER_NAME = 'agent-tool-protocol';
|
|
109
|
+
export const OTEL_METER_NAME = 'agent-tool-protocol';
|
|
110
|
+
/**
|
|
111
|
+
* Attribute prefixes for custom metadata
|
|
112
|
+
*/
|
|
113
|
+
export const ATTRIBUTE_PREFIX_TOOL = 'atp.tool';
|
|
114
|
+
export const ATTRIBUTE_PREFIX_METADATA = 'atp.metadata';
|
|
115
|
+
//# sourceMappingURL=otel-metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otel-metrics.js","sourceRoot":"","sources":["../../src/audit/otel-metrics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { AuthProvider } from '@mondaydotcomorg/atp-protocol';
|
|
2
|
+
/**
|
|
3
|
+
* Environment variable based auth provider
|
|
4
|
+
* Simple provider that reads credentials from process.env
|
|
5
|
+
* Good for development and simple deployments
|
|
6
|
+
*/
|
|
7
|
+
export declare class EnvAuthProvider implements AuthProvider {
|
|
8
|
+
name: string;
|
|
9
|
+
private prefix;
|
|
10
|
+
private credentials;
|
|
11
|
+
constructor(options?: {
|
|
12
|
+
prefix?: string;
|
|
13
|
+
credentials?: Record<string, string>;
|
|
14
|
+
});
|
|
15
|
+
getCredential(key: string): Promise<string | null>;
|
|
16
|
+
setCredential(key: string, value: string, _ttl?: number): Promise<void>;
|
|
17
|
+
deleteCredential(key: string): Promise<void>;
|
|
18
|
+
listCredentials(): Promise<string[]>;
|
|
19
|
+
disconnect(): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/auth/env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAElE;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,YAAY;IACnD,IAAI,SAAS;IACb,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAsB;gBAGxC,OAAO,GAAE;QACR,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAChC;IAYD,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IASlD,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvE,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5C,eAAe,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAgBpC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAGjC"}
|
package/dist/auth/env.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment variable based auth provider
|
|
3
|
+
* Simple provider that reads credentials from process.env
|
|
4
|
+
* Good for development and simple deployments
|
|
5
|
+
*/
|
|
6
|
+
export class EnvAuthProvider {
|
|
7
|
+
name = 'env';
|
|
8
|
+
prefix;
|
|
9
|
+
credentials;
|
|
10
|
+
constructor(options = {}) {
|
|
11
|
+
this.prefix = options.prefix || 'ATP_';
|
|
12
|
+
this.credentials = new Map();
|
|
13
|
+
if (options.credentials) {
|
|
14
|
+
for (const [key, value] of Object.entries(options.credentials)) {
|
|
15
|
+
this.credentials.set(key, value);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async getCredential(key) {
|
|
20
|
+
if (this.credentials.has(key)) {
|
|
21
|
+
return this.credentials.get(key) || null;
|
|
22
|
+
}
|
|
23
|
+
const envValue = process.env[key] || process.env[`${this.prefix}${key}`];
|
|
24
|
+
return envValue || null;
|
|
25
|
+
}
|
|
26
|
+
async setCredential(key, value, _ttl) {
|
|
27
|
+
this.credentials.set(key, value);
|
|
28
|
+
}
|
|
29
|
+
async deleteCredential(key) {
|
|
30
|
+
this.credentials.delete(key);
|
|
31
|
+
}
|
|
32
|
+
async listCredentials() {
|
|
33
|
+
const keys = new Set();
|
|
34
|
+
for (const key of this.credentials.keys()) {
|
|
35
|
+
keys.add(key);
|
|
36
|
+
}
|
|
37
|
+
for (const key of Object.keys(process.env)) {
|
|
38
|
+
if (key.startsWith(this.prefix)) {
|
|
39
|
+
keys.add(key.substring(this.prefix.length));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return Array.from(keys);
|
|
43
|
+
}
|
|
44
|
+
async disconnect() {
|
|
45
|
+
this.credentials.clear();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/auth/env.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,OAAO,eAAe;IAC3B,IAAI,GAAG,KAAK,CAAC;IACL,MAAM,CAAS;IACf,WAAW,CAAsB;IAEzC,YACC,UAGI,EAAE;QAEN,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC;QACvC,IAAI,CAAC,WAAW,GAAG,IAAI,GAAG,EAAE,CAAC;QAE7B,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YACzB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;gBAChE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAClC,CAAC;QACF,CAAC;IACF,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,GAAW;QAC9B,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/B,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;QAC1C,CAAC;QAED,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,CAAC;QACzE,OAAO,QAAQ,IAAI,IAAI,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,GAAW,EAAE,KAAa,EAAE,IAAa;QAC5D,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,GAAW;QACjC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,eAAe;QACpB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAE/B,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC;YAC3C,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACf,CAAC;QAED,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5C,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;gBACjC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;YAC7C,CAAC;QACF,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,UAAU;QACf,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC;CACD"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { CacheProvider } from '@mondaydotcomorg/atp-protocol';
|
|
2
|
+
export interface FileCacheOptions {
|
|
3
|
+
cacheDir?: string;
|
|
4
|
+
maxKeys?: number;
|
|
5
|
+
defaultTTL?: number;
|
|
6
|
+
cleanupInterval?: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* File-based cache provider for persistent local caching
|
|
10
|
+
* Good for single-server deployments that need persistence across restarts
|
|
11
|
+
* Supports cross-pod scenarios when using a shared filesystem (NFS, EFS, etc.)
|
|
12
|
+
*/
|
|
13
|
+
export declare class FileCache implements CacheProvider {
|
|
14
|
+
name: string;
|
|
15
|
+
private cacheDir;
|
|
16
|
+
private maxKeys;
|
|
17
|
+
private defaultTTL;
|
|
18
|
+
private cleanupInterval;
|
|
19
|
+
private cleanupTimer?;
|
|
20
|
+
private initPromise?;
|
|
21
|
+
constructor(options?: FileCacheOptions);
|
|
22
|
+
private initialize;
|
|
23
|
+
private ensureInitialized;
|
|
24
|
+
private getFilePath;
|
|
25
|
+
private startCleanup;
|
|
26
|
+
private cleanExpired;
|
|
27
|
+
private enforceMaxKeys;
|
|
28
|
+
get<T>(key: string): Promise<T | null>;
|
|
29
|
+
set(key: string, value: unknown, ttl?: number): Promise<void>;
|
|
30
|
+
delete(key: string): Promise<void>;
|
|
31
|
+
has(key: string): Promise<boolean>;
|
|
32
|
+
clear(pattern?: string): Promise<void>;
|
|
33
|
+
mget(keys: string[]): Promise<Array<unknown | null>>;
|
|
34
|
+
mset(entries: Array<[string, unknown, number?]>): Promise<void>;
|
|
35
|
+
disconnect(): Promise<void>;
|
|
36
|
+
/** Get cache statistics */
|
|
37
|
+
getStats(): Promise<{
|
|
38
|
+
keys: number;
|
|
39
|
+
maxKeys: number;
|
|
40
|
+
utilization: number;
|
|
41
|
+
sizeBytes: number;
|
|
42
|
+
cacheDir: string;
|
|
43
|
+
}>;
|
|
44
|
+
/** Manually trigger cleanup of expired entries */
|
|
45
|
+
cleanup(): Promise<void>;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/cache/file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAUnE,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,qBAAa,SAAU,YAAW,aAAa;IAC9C,IAAI,SAAU;IACd,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,YAAY,CAAC,CAAiB;IACtC,OAAO,CAAC,WAAW,CAAC,CAAgB;gBAExB,OAAO,GAAE,gBAAqB;YAU5B,UAAU;YAaV,iBAAiB;IAM/B,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,YAAY;YAeN,YAAY;YAqCZ,cAAc;IAmCtB,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IA0BtC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB7D,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBlC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKlC,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA+CtC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAIpD,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/D,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQjC,2BAA2B;IACrB,QAAQ;;;;;;;IAqCd,kDAAkD;IAC5C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAG9B"}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
/**
|
|
5
|
+
* File-based cache provider for persistent local caching
|
|
6
|
+
* Good for single-server deployments that need persistence across restarts
|
|
7
|
+
* Supports cross-pod scenarios when using a shared filesystem (NFS, EFS, etc.)
|
|
8
|
+
*/
|
|
9
|
+
export class FileCache {
|
|
10
|
+
name = 'file';
|
|
11
|
+
cacheDir;
|
|
12
|
+
maxKeys;
|
|
13
|
+
defaultTTL;
|
|
14
|
+
cleanupInterval;
|
|
15
|
+
cleanupTimer;
|
|
16
|
+
initPromise;
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
this.cacheDir = options.cacheDir || path.join(os.tmpdir(), 'atp-cache');
|
|
19
|
+
this.maxKeys = options.maxKeys || 1000;
|
|
20
|
+
this.defaultTTL = options.defaultTTL || 3600;
|
|
21
|
+
this.cleanupInterval = options.cleanupInterval || 300; // 5 minutes
|
|
22
|
+
// Initialize asynchronously
|
|
23
|
+
this.initPromise = this.initialize();
|
|
24
|
+
}
|
|
25
|
+
async initialize() {
|
|
26
|
+
try {
|
|
27
|
+
await fs.mkdir(this.cacheDir, { recursive: true });
|
|
28
|
+
// Start periodic cleanup
|
|
29
|
+
this.startCleanup();
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
console.error('[FileCache] Failed to initialize cache directory:', error instanceof Error ? error.message : error);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async ensureInitialized() {
|
|
36
|
+
if (this.initPromise) {
|
|
37
|
+
await this.initPromise;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
getFilePath(key) {
|
|
41
|
+
// Sanitize key to be filesystem-safe
|
|
42
|
+
const sanitizedKey = key.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
43
|
+
return path.join(this.cacheDir, `${sanitizedKey}.json`);
|
|
44
|
+
}
|
|
45
|
+
startCleanup() {
|
|
46
|
+
if (this.cleanupInterval > 0) {
|
|
47
|
+
this.cleanupTimer = setInterval(() => {
|
|
48
|
+
this.cleanExpired().catch((error) => {
|
|
49
|
+
console.error('[FileCache] Cleanup error:', error);
|
|
50
|
+
});
|
|
51
|
+
}, this.cleanupInterval * 1000);
|
|
52
|
+
// Don't prevent process exit
|
|
53
|
+
if (this.cleanupTimer.unref) {
|
|
54
|
+
this.cleanupTimer.unref();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async cleanExpired() {
|
|
59
|
+
try {
|
|
60
|
+
await this.ensureInitialized();
|
|
61
|
+
const files = await fs.readdir(this.cacheDir);
|
|
62
|
+
const now = Date.now();
|
|
63
|
+
for (const file of files) {
|
|
64
|
+
if (!file.endsWith('.json'))
|
|
65
|
+
continue;
|
|
66
|
+
const filePath = path.join(this.cacheDir, file);
|
|
67
|
+
try {
|
|
68
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
69
|
+
const entry = JSON.parse(content);
|
|
70
|
+
if (entry.expiresAt !== -1 && now > entry.expiresAt) {
|
|
71
|
+
await fs.unlink(filePath);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// If we can't read or parse a file, delete it
|
|
76
|
+
try {
|
|
77
|
+
await fs.unlink(filePath);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// Ignore deletion errors
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Enforce max keys limit
|
|
85
|
+
await this.enforceMaxKeys();
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
console.error('[FileCache] Failed to clean expired entries:', error instanceof Error ? error.message : error);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async enforceMaxKeys() {
|
|
92
|
+
try {
|
|
93
|
+
const files = await fs.readdir(this.cacheDir);
|
|
94
|
+
const jsonFiles = files.filter((f) => f.endsWith('.json'));
|
|
95
|
+
if (jsonFiles.length > this.maxKeys) {
|
|
96
|
+
// Sort by modification time and remove oldest
|
|
97
|
+
const fileStats = await Promise.all(jsonFiles.map(async (file) => {
|
|
98
|
+
const filePath = path.join(this.cacheDir, file);
|
|
99
|
+
const stats = await fs.stat(filePath);
|
|
100
|
+
return { file, mtime: stats.mtime.getTime() };
|
|
101
|
+
}));
|
|
102
|
+
fileStats.sort((a, b) => a.mtime - b.mtime);
|
|
103
|
+
const toDelete = fileStats.slice(0, jsonFiles.length - this.maxKeys);
|
|
104
|
+
await Promise.all(toDelete.map((item) => {
|
|
105
|
+
const filePath = path.join(this.cacheDir, item.file);
|
|
106
|
+
return fs.unlink(filePath).catch(() => {
|
|
107
|
+
// Ignore errors
|
|
108
|
+
});
|
|
109
|
+
}));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
console.error('[FileCache] Failed to enforce max keys:', error instanceof Error ? error.message : error);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async get(key) {
|
|
117
|
+
try {
|
|
118
|
+
await this.ensureInitialized();
|
|
119
|
+
const filePath = this.getFilePath(key);
|
|
120
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
121
|
+
const entry = JSON.parse(content);
|
|
122
|
+
if (entry.expiresAt !== -1 && Date.now() > entry.expiresAt) {
|
|
123
|
+
await this.delete(key);
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
return entry.value;
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
if (error.code === 'ENOENT') {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
console.error('[FileCache] Failed to get key:', key, error instanceof Error ? error.message : error);
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
async set(key, value, ttl) {
|
|
137
|
+
try {
|
|
138
|
+
await this.ensureInitialized();
|
|
139
|
+
await this.enforceMaxKeys();
|
|
140
|
+
const expiresAt = ttl
|
|
141
|
+
? Date.now() + ttl * 1000
|
|
142
|
+
: this.defaultTTL > 0
|
|
143
|
+
? Date.now() + this.defaultTTL * 1000
|
|
144
|
+
: -1;
|
|
145
|
+
const entry = { value, expiresAt };
|
|
146
|
+
const filePath = this.getFilePath(key);
|
|
147
|
+
await fs.writeFile(filePath, JSON.stringify(entry), 'utf-8');
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
console.error('[FileCache] Failed to set key:', key, error instanceof Error ? error.message : error);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
async delete(key) {
|
|
154
|
+
try {
|
|
155
|
+
await this.ensureInitialized();
|
|
156
|
+
const filePath = this.getFilePath(key);
|
|
157
|
+
await fs.unlink(filePath);
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
if (error.code !== 'ENOENT') {
|
|
161
|
+
console.error('[FileCache] Failed to delete key:', key, error instanceof Error ? error.message : error);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
async has(key) {
|
|
166
|
+
const value = await this.get(key);
|
|
167
|
+
return value !== null;
|
|
168
|
+
}
|
|
169
|
+
async clear(pattern) {
|
|
170
|
+
try {
|
|
171
|
+
await this.ensureInitialized();
|
|
172
|
+
const files = await fs.readdir(this.cacheDir);
|
|
173
|
+
if (!pattern) {
|
|
174
|
+
// Clear all cache files
|
|
175
|
+
await Promise.all(files
|
|
176
|
+
.filter((f) => f.endsWith('.json'))
|
|
177
|
+
.map((file) => {
|
|
178
|
+
const filePath = path.join(this.cacheDir, file);
|
|
179
|
+
return fs.unlink(filePath).catch(() => {
|
|
180
|
+
// Ignore errors
|
|
181
|
+
});
|
|
182
|
+
}));
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
// Convert glob pattern to regex
|
|
186
|
+
const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$');
|
|
187
|
+
// Read all files and check if they match the pattern
|
|
188
|
+
for (const file of files) {
|
|
189
|
+
if (!file.endsWith('.json'))
|
|
190
|
+
continue;
|
|
191
|
+
// Extract original key from filename (reverse sanitization is approximate)
|
|
192
|
+
const keyBase = file.replace('.json', '');
|
|
193
|
+
// We need to read the file to get the original key
|
|
194
|
+
// For now, use a simple pattern match on the sanitized filename
|
|
195
|
+
if (regex.test(keyBase)) {
|
|
196
|
+
const filePath = path.join(this.cacheDir, file);
|
|
197
|
+
await fs.unlink(filePath).catch(() => {
|
|
198
|
+
// Ignore errors
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
console.error('[FileCache] Failed to clear cache:', error instanceof Error ? error.message : error);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
async mget(keys) {
|
|
208
|
+
return Promise.all(keys.map((key) => this.get(key)));
|
|
209
|
+
}
|
|
210
|
+
async mset(entries) {
|
|
211
|
+
await Promise.all(entries.map(([key, value, ttl]) => this.set(key, value, ttl)));
|
|
212
|
+
}
|
|
213
|
+
async disconnect() {
|
|
214
|
+
if (this.cleanupTimer) {
|
|
215
|
+
clearInterval(this.cleanupTimer);
|
|
216
|
+
this.cleanupTimer = undefined;
|
|
217
|
+
}
|
|
218
|
+
// Don't delete cache files on disconnect - they should persist
|
|
219
|
+
}
|
|
220
|
+
/** Get cache statistics */
|
|
221
|
+
async getStats() {
|
|
222
|
+
try {
|
|
223
|
+
await this.ensureInitialized();
|
|
224
|
+
const files = await fs.readdir(this.cacheDir);
|
|
225
|
+
const jsonFiles = files.filter((f) => f.endsWith('.json'));
|
|
226
|
+
// Calculate total size
|
|
227
|
+
let totalSize = 0;
|
|
228
|
+
for (const file of jsonFiles) {
|
|
229
|
+
const filePath = path.join(this.cacheDir, file);
|
|
230
|
+
try {
|
|
231
|
+
const stats = await fs.stat(filePath);
|
|
232
|
+
totalSize += stats.size;
|
|
233
|
+
}
|
|
234
|
+
catch {
|
|
235
|
+
// Ignore errors
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
keys: jsonFiles.length,
|
|
240
|
+
maxKeys: this.maxKeys,
|
|
241
|
+
utilization: (jsonFiles.length / this.maxKeys) * 100,
|
|
242
|
+
sizeBytes: totalSize,
|
|
243
|
+
cacheDir: this.cacheDir,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
console.error('[FileCache] Failed to get stats:', error);
|
|
248
|
+
return {
|
|
249
|
+
keys: 0,
|
|
250
|
+
maxKeys: this.maxKeys,
|
|
251
|
+
utilization: 0,
|
|
252
|
+
sizeBytes: 0,
|
|
253
|
+
cacheDir: this.cacheDir,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/** Manually trigger cleanup of expired entries */
|
|
258
|
+
async cleanup() {
|
|
259
|
+
await this.cleanExpired();
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.js","sourceRoot":"","sources":["../../src/cache/file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { CacheProvider } from '@mondaydotcomorg/atp-protocol';
|
|
2
|
+
/**
|
|
3
|
+
* In-memory cache provider with LRU eviction
|
|
4
|
+
* Good for development and single-server deployments
|
|
5
|
+
*/
|
|
6
|
+
export declare class MemoryCache implements CacheProvider {
|
|
7
|
+
name: string;
|
|
8
|
+
private cache;
|
|
9
|
+
private maxKeys;
|
|
10
|
+
private defaultTTL;
|
|
11
|
+
constructor(options?: {
|
|
12
|
+
maxKeys?: number;
|
|
13
|
+
defaultTTL?: number;
|
|
14
|
+
});
|
|
15
|
+
get<T>(key: string): Promise<T | null>;
|
|
16
|
+
set(key: string, value: unknown, ttl?: number): Promise<void>;
|
|
17
|
+
delete(key: string): Promise<void>;
|
|
18
|
+
has(key: string): Promise<boolean>;
|
|
19
|
+
clear(pattern?: string): Promise<void>;
|
|
20
|
+
mget(keys: string[]): Promise<Array<unknown | null>>;
|
|
21
|
+
mset(entries: Array<[string, unknown, number?]>): Promise<void>;
|
|
22
|
+
disconnect(): Promise<void>;
|
|
23
|
+
/** Get cache statistics */
|
|
24
|
+
getStats(): {
|
|
25
|
+
keys: number;
|
|
26
|
+
maxKeys: number;
|
|
27
|
+
utilization: number;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/cache/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAOnE;;;GAGG;AACH,qBAAa,WAAY,YAAW,aAAa;IAChD,IAAI,SAAY;IAChB,OAAO,CAAC,KAAK,CAA0B;IACvC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAS;gBAEf,OAAO,GAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAO;IAM7D,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAkBtC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB7D,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKlC,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAetC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAIpD,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAM/D,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC,2BAA2B;IAC3B,QAAQ;;;;;CAOR"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory cache provider with LRU eviction
|
|
3
|
+
* Good for development and single-server deployments
|
|
4
|
+
*/
|
|
5
|
+
export class MemoryCache {
|
|
6
|
+
name = 'memory';
|
|
7
|
+
cache;
|
|
8
|
+
maxKeys;
|
|
9
|
+
defaultTTL;
|
|
10
|
+
constructor(options = {}) {
|
|
11
|
+
this.cache = new Map();
|
|
12
|
+
this.maxKeys = options.maxKeys || 1000;
|
|
13
|
+
this.defaultTTL = options.defaultTTL || 3600;
|
|
14
|
+
}
|
|
15
|
+
async get(key) {
|
|
16
|
+
const entry = this.cache.get(key);
|
|
17
|
+
if (!entry) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
if (entry.expiresAt !== -1 && Date.now() > entry.expiresAt) {
|
|
21
|
+
this.cache.delete(key);
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
this.cache.delete(key);
|
|
25
|
+
this.cache.set(key, entry);
|
|
26
|
+
return entry.value;
|
|
27
|
+
}
|
|
28
|
+
async set(key, value, ttl) {
|
|
29
|
+
if (this.cache.size >= this.maxKeys && !this.cache.has(key)) {
|
|
30
|
+
const firstKey = this.cache.keys().next().value;
|
|
31
|
+
if (firstKey) {
|
|
32
|
+
this.cache.delete(firstKey);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const expiresAt = ttl
|
|
36
|
+
? Date.now() + ttl * 1000
|
|
37
|
+
: this.defaultTTL > 0
|
|
38
|
+
? Date.now() + this.defaultTTL * 1000
|
|
39
|
+
: -1;
|
|
40
|
+
this.cache.set(key, { value, expiresAt });
|
|
41
|
+
}
|
|
42
|
+
async delete(key) {
|
|
43
|
+
this.cache.delete(key);
|
|
44
|
+
}
|
|
45
|
+
async has(key) {
|
|
46
|
+
const value = await this.get(key);
|
|
47
|
+
return value !== null;
|
|
48
|
+
}
|
|
49
|
+
async clear(pattern) {
|
|
50
|
+
if (!pattern) {
|
|
51
|
+
this.cache.clear();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$');
|
|
55
|
+
for (const key of this.cache.keys()) {
|
|
56
|
+
if (regex.test(key)) {
|
|
57
|
+
this.cache.delete(key);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async mget(keys) {
|
|
62
|
+
return Promise.all(keys.map((key) => this.get(key)));
|
|
63
|
+
}
|
|
64
|
+
async mset(entries) {
|
|
65
|
+
for (const [key, value, ttl] of entries) {
|
|
66
|
+
await this.set(key, value, ttl);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async disconnect() {
|
|
70
|
+
this.cache.clear();
|
|
71
|
+
}
|
|
72
|
+
/** Get cache statistics */
|
|
73
|
+
getStats() {
|
|
74
|
+
return {
|
|
75
|
+
keys: this.cache.size,
|
|
76
|
+
maxKeys: this.maxKeys,
|
|
77
|
+
utilization: (this.cache.size / this.maxKeys) * 100,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/cache/memory.ts"],"names":[],"mappings":"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"}
|