@sekuire/sdk 0.1.10 → 0.1.11
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/README.md +69 -5
- package/dist/beacon.d.ts +40 -5
- package/dist/config/loader.d.ts +38 -1
- package/dist/index.d.ts +297 -20
- package/dist/index.esm.js +1527 -277
- package/dist/index.js +1127 -133
- package/dist/memory/base.d.ts +7 -0
- package/dist/memory/cloudflare-d1.d.ts +24 -0
- package/dist/memory/cloudflare-kv.d.ts +25 -0
- package/dist/memory/convex.d.ts +21 -0
- package/dist/memory/dynamodb.d.ts +28 -0
- package/dist/memory/in-memory.d.ts +1 -0
- package/dist/memory/index.d.ts +28 -1
- package/dist/memory/postgres.d.ts +5 -1
- package/dist/memory/redis.d.ts +5 -1
- package/dist/memory/registry.d.ts +12 -0
- package/dist/memory/sqlite.d.ts +22 -0
- package/dist/memory/turso.d.ts +23 -0
- package/dist/memory/upstash.d.ts +22 -0
- package/dist/sdk.d.ts +14 -9
- package/package.json +33 -2
package/dist/index.esm.js
CHANGED
|
@@ -78,6 +78,10 @@ function detectDeploymentUrl() {
|
|
|
78
78
|
*
|
|
79
79
|
* Automatically registers the agent with Sekuire and sends periodic heartbeats
|
|
80
80
|
* to show online status in the Dashboard.
|
|
81
|
+
*
|
|
82
|
+
* Supports two authentication modes:
|
|
83
|
+
* 1. Install Token (recommended): Use an install token from the dashboard
|
|
84
|
+
* 2. API Key: Use an API key for SDK-initiated bootstrap (requires workspace)
|
|
81
85
|
*/
|
|
82
86
|
// ============================================================================
|
|
83
87
|
// Beacon Class
|
|
@@ -86,16 +90,21 @@ class Beacon {
|
|
|
86
90
|
constructor(config) {
|
|
87
91
|
this.intervalId = null;
|
|
88
92
|
this.installationId = null;
|
|
93
|
+
this.runtimeToken = null;
|
|
94
|
+
this.refreshToken = null;
|
|
89
95
|
this.lastHeartbeat = null;
|
|
90
96
|
this.failedHeartbeats = 0;
|
|
91
97
|
const resolvedApiKey = config.apiKey || this.getApiKey() || '';
|
|
98
|
+
const resolvedInstallToken = config.installToken || this.getInstallToken();
|
|
92
99
|
this.config = {
|
|
93
100
|
...config,
|
|
94
|
-
|
|
101
|
+
heartbeatIntervalSeconds: config.heartbeatIntervalSeconds ?? 60,
|
|
95
102
|
apiKey: resolvedApiKey,
|
|
103
|
+
installToken: resolvedInstallToken,
|
|
104
|
+
capabilities: config.capabilities ?? [],
|
|
96
105
|
};
|
|
97
|
-
if (!this.config.apiKey) {
|
|
98
|
-
console.warn('[Beacon] No API key provided. Set
|
|
106
|
+
if (!this.config.installToken && !this.config.apiKey) {
|
|
107
|
+
console.warn('[Beacon] No install token or API key provided. Set SEKUIRE_INSTALL_TOKEN or SEKUIRE_API_KEY.');
|
|
99
108
|
}
|
|
100
109
|
}
|
|
101
110
|
/**
|
|
@@ -111,22 +120,27 @@ class Beacon {
|
|
|
111
120
|
if (deploymentUrl) {
|
|
112
121
|
console.log(`[Beacon] Deployment URL: ${deploymentUrl}`);
|
|
113
122
|
}
|
|
114
|
-
// Bootstrap registration
|
|
123
|
+
// Bootstrap registration (exchanges install token for runtime credentials)
|
|
115
124
|
try {
|
|
116
125
|
await this.bootstrap(deploymentUrl);
|
|
126
|
+
console.log(`[Beacon] Bootstrap successful, installation ID: ${this.installationId}`);
|
|
117
127
|
}
|
|
118
128
|
catch (error) {
|
|
119
129
|
console.error('[Beacon] Bootstrap failed:', error);
|
|
120
|
-
|
|
130
|
+
this.notifyStatusChange();
|
|
131
|
+
// Cannot continue without bootstrap - runtime token required for heartbeats
|
|
132
|
+
throw error;
|
|
121
133
|
}
|
|
122
134
|
// Start heartbeat loop
|
|
135
|
+
const intervalMs = this.config.heartbeatIntervalSeconds * 1000;
|
|
123
136
|
this.intervalId = setInterval(() => {
|
|
124
137
|
this.heartbeat().catch((err) => {
|
|
125
138
|
console.error('[Beacon] Heartbeat failed:', err);
|
|
126
139
|
});
|
|
127
|
-
},
|
|
140
|
+
}, intervalMs);
|
|
128
141
|
// Send first heartbeat immediately
|
|
129
142
|
await this.heartbeat().catch(() => { });
|
|
143
|
+
this.notifyStatusChange();
|
|
130
144
|
}
|
|
131
145
|
/**
|
|
132
146
|
* Stop the beacon
|
|
@@ -145,6 +159,7 @@ class Beacon {
|
|
|
145
159
|
return {
|
|
146
160
|
isRunning: this.intervalId !== null,
|
|
147
161
|
installationId: this.installationId || undefined,
|
|
162
|
+
runtimeToken: this.runtimeToken ? '***' + this.runtimeToken.slice(-4) : undefined,
|
|
148
163
|
deploymentUrl: this.config.deploymentUrl || detectDeploymentUrl(),
|
|
149
164
|
lastHeartbeat: this.lastHeartbeat || undefined,
|
|
150
165
|
failedHeartbeats: this.failedHeartbeats,
|
|
@@ -152,72 +167,116 @@ class Beacon {
|
|
|
152
167
|
}
|
|
153
168
|
/**
|
|
154
169
|
* Bootstrap registration with Sekuire
|
|
170
|
+
*
|
|
171
|
+
* Exchanges an install token for runtime credentials (installation_id + runtime_token).
|
|
172
|
+
* The install token is obtained from the dashboard or CLI.
|
|
155
173
|
*/
|
|
156
174
|
async bootstrap(deploymentUrl) {
|
|
157
|
-
if (!this.config.
|
|
158
|
-
throw new Error('
|
|
175
|
+
if (!this.config.installToken) {
|
|
176
|
+
throw new Error('Install token required for beacon registration. ' +
|
|
177
|
+
'Generate one from the dashboard or use: sekuire install token --workspace <id>');
|
|
159
178
|
}
|
|
160
179
|
const response = await fetch(`${this.config.apiBaseUrl}/api/v1/installations/bootstrap`, {
|
|
161
180
|
method: 'POST',
|
|
162
181
|
headers: {
|
|
163
182
|
'Content-Type': 'application/json',
|
|
164
|
-
'X-API-Key': this.config.apiKey,
|
|
165
183
|
},
|
|
166
184
|
body: JSON.stringify({
|
|
167
|
-
|
|
185
|
+
install_token: this.config.installToken,
|
|
168
186
|
upstream_url: deploymentUrl,
|
|
187
|
+
capabilities: this.config.capabilities ?? [],
|
|
188
|
+
heartbeat_interval_seconds: this.config.heartbeatIntervalSeconds,
|
|
169
189
|
}),
|
|
170
190
|
});
|
|
171
191
|
if (!response.ok) {
|
|
172
|
-
|
|
192
|
+
const body = await response.text();
|
|
193
|
+
throw new Error(`Bootstrap failed: ${response.status} ${response.statusText} - ${body}`);
|
|
173
194
|
}
|
|
174
195
|
const data = await response.json();
|
|
175
196
|
this.installationId = data.installation_id;
|
|
176
|
-
|
|
197
|
+
this.runtimeToken = data.runtime_token;
|
|
198
|
+
this.refreshToken = data.refresh_token;
|
|
177
199
|
}
|
|
178
200
|
/**
|
|
179
|
-
* Send heartbeat to Sekuire
|
|
201
|
+
* Send heartbeat (lease renewal) to Sekuire
|
|
202
|
+
*
|
|
203
|
+
* Uses the installation-based lease endpoint with runtime token authentication.
|
|
180
204
|
*/
|
|
181
205
|
async heartbeat() {
|
|
182
|
-
if (!this.
|
|
206
|
+
if (!this.installationId || !this.runtimeToken) {
|
|
207
|
+
console.warn('[Beacon] Cannot send heartbeat - not bootstrapped');
|
|
183
208
|
return;
|
|
184
209
|
}
|
|
185
210
|
const deploymentUrl = this.config.deploymentUrl || detectDeploymentUrl();
|
|
186
211
|
const prevFailed = this.failedHeartbeats;
|
|
187
212
|
try {
|
|
188
|
-
const
|
|
189
|
-
? await this.config.onHeartbeat(deploymentUrl)
|
|
190
|
-
: {
|
|
191
|
-
agent_id: this.config.agentId,
|
|
192
|
-
status: 'running',
|
|
193
|
-
public_url: deploymentUrl,
|
|
194
|
-
load: 0.0,
|
|
195
|
-
};
|
|
196
|
-
const response = await fetch(`${this.config.apiBaseUrl}/api/v1/agents/heartbeat`, {
|
|
213
|
+
const response = await fetch(`${this.config.apiBaseUrl}/api/v1/installations/${this.installationId}/lease`, {
|
|
197
214
|
method: 'POST',
|
|
198
215
|
headers: {
|
|
199
216
|
'Content-Type': 'application/json',
|
|
200
|
-
'
|
|
217
|
+
'Authorization': `Bearer ${this.runtimeToken}`,
|
|
201
218
|
},
|
|
202
|
-
body: JSON.stringify(
|
|
219
|
+
body: JSON.stringify({
|
|
220
|
+
status: 'running',
|
|
221
|
+
heartbeat_interval_seconds: this.config.heartbeatIntervalSeconds,
|
|
222
|
+
upstream_url: deploymentUrl,
|
|
223
|
+
}),
|
|
203
224
|
});
|
|
225
|
+
if (response.status === 401) {
|
|
226
|
+
// Token expired - try to refresh
|
|
227
|
+
console.warn('[Beacon] Runtime token expired, attempting refresh...');
|
|
228
|
+
await this.refreshRuntimeToken();
|
|
229
|
+
// Retry heartbeat after refresh
|
|
230
|
+
return this.heartbeat();
|
|
231
|
+
}
|
|
204
232
|
if (!response.ok) {
|
|
205
|
-
|
|
233
|
+
const body = await response.text();
|
|
234
|
+
throw new Error(`Heartbeat failed: ${response.status} - ${body}`);
|
|
206
235
|
}
|
|
207
236
|
this.lastHeartbeat = new Date();
|
|
208
237
|
this.failedHeartbeats = 0;
|
|
209
|
-
if (prevFailed > 0
|
|
210
|
-
this.
|
|
238
|
+
if (prevFailed > 0) {
|
|
239
|
+
this.notifyStatusChange();
|
|
211
240
|
}
|
|
212
241
|
}
|
|
213
242
|
catch (error) {
|
|
214
243
|
this.failedHeartbeats++;
|
|
215
|
-
|
|
216
|
-
this.config.onStatusChange(this.getStatus());
|
|
217
|
-
}
|
|
244
|
+
this.notifyStatusChange();
|
|
218
245
|
throw error;
|
|
219
246
|
}
|
|
220
247
|
}
|
|
248
|
+
/**
|
|
249
|
+
* Refresh the runtime token using the refresh token
|
|
250
|
+
*/
|
|
251
|
+
async refreshRuntimeToken() {
|
|
252
|
+
if (!this.installationId || !this.refreshToken) {
|
|
253
|
+
throw new Error('Cannot refresh token - missing installation ID or refresh token');
|
|
254
|
+
}
|
|
255
|
+
const response = await fetch(`${this.config.apiBaseUrl}/api/v1/installations/${this.installationId}/refresh`, {
|
|
256
|
+
method: 'POST',
|
|
257
|
+
headers: {
|
|
258
|
+
'Content-Type': 'application/json',
|
|
259
|
+
},
|
|
260
|
+
body: JSON.stringify({
|
|
261
|
+
refresh_token: this.refreshToken,
|
|
262
|
+
}),
|
|
263
|
+
});
|
|
264
|
+
if (!response.ok) {
|
|
265
|
+
const body = await response.text();
|
|
266
|
+
throw new Error(`Token refresh failed: ${response.status} - ${body}`);
|
|
267
|
+
}
|
|
268
|
+
const data = await response.json();
|
|
269
|
+
this.runtimeToken = data.runtime_token;
|
|
270
|
+
console.log('[Beacon] Runtime token refreshed successfully');
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Notify status change callback
|
|
274
|
+
*/
|
|
275
|
+
notifyStatusChange() {
|
|
276
|
+
if (this.config.onStatusChange) {
|
|
277
|
+
this.config.onStatusChange(this.getStatus());
|
|
278
|
+
}
|
|
279
|
+
}
|
|
221
280
|
/**
|
|
222
281
|
* Get API key from environment
|
|
223
282
|
*/
|
|
@@ -227,6 +286,15 @@ class Beacon {
|
|
|
227
286
|
}
|
|
228
287
|
return undefined;
|
|
229
288
|
}
|
|
289
|
+
/**
|
|
290
|
+
* Get install token from environment
|
|
291
|
+
*/
|
|
292
|
+
getInstallToken() {
|
|
293
|
+
if (typeof process !== 'undefined' && process.env) {
|
|
294
|
+
return process.env.SEKUIRE_INSTALL_TOKEN;
|
|
295
|
+
}
|
|
296
|
+
return undefined;
|
|
297
|
+
}
|
|
230
298
|
}
|
|
231
299
|
// ============================================================================
|
|
232
300
|
// Convenience Export
|
|
@@ -730,17 +798,20 @@ class SekuireSDK {
|
|
|
730
798
|
throw new Error("agentId is required");
|
|
731
799
|
}
|
|
732
800
|
const apiKey = config.apiKey || process.env.SEKUIRE_API_KEY;
|
|
801
|
+
const installToken = config.installToken || process.env.SEKUIRE_INSTALL_TOKEN;
|
|
733
802
|
this.config = {
|
|
734
803
|
privateKey: config.privateKey,
|
|
735
804
|
apiKey,
|
|
805
|
+
installToken,
|
|
736
806
|
agentId: config.agentId,
|
|
737
807
|
agentName: config.agentName ?? "Unknown",
|
|
738
808
|
apiUrl: (config.apiUrl ?? DEFAULT_API_URL).replace(/\/$/, ""),
|
|
739
809
|
workspaceId: config.workspaceId ?? "",
|
|
740
810
|
environment: config.environment ?? "production",
|
|
741
811
|
autoHeartbeat: config.autoHeartbeat !== false,
|
|
742
|
-
|
|
812
|
+
heartbeatIntervalSeconds: config.heartbeatIntervalSeconds ?? 60,
|
|
743
813
|
loggingEnabled: config.loggingEnabled !== false,
|
|
814
|
+
capabilities: config.capabilities ?? [],
|
|
744
815
|
};
|
|
745
816
|
this.identity = new AgentIdentity(this.config.agentName, this.config.agentId, this.config.privateKey);
|
|
746
817
|
const loggerConfig = {
|
|
@@ -759,22 +830,12 @@ class SekuireSDK {
|
|
|
759
830
|
});
|
|
760
831
|
this.beacon = new Beacon({
|
|
761
832
|
apiBaseUrl: this.config.apiUrl,
|
|
833
|
+
installToken: this.config.installToken,
|
|
762
834
|
apiKey: this.config.apiKey,
|
|
763
835
|
agentId: this.config.agentId,
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
const timestamp = Math.floor(Date.now() / 1000);
|
|
768
|
-
const message = `${this.config.agentId}|${deploymentUrl ?? ""}|${timestamp}`;
|
|
769
|
-
const signature = await this.identity.sign(message);
|
|
770
|
-
return {
|
|
771
|
-
sekuire_id: this.config.agentId,
|
|
772
|
-
url: deploymentUrl ?? null,
|
|
773
|
-
timestamp,
|
|
774
|
-
signature,
|
|
775
|
-
};
|
|
776
|
-
}
|
|
777
|
-
: undefined,
|
|
836
|
+
workspaceId: this.config.workspaceId || undefined,
|
|
837
|
+
heartbeatIntervalSeconds: this.config.heartbeatIntervalSeconds,
|
|
838
|
+
capabilities: this.config.capabilities,
|
|
778
839
|
});
|
|
779
840
|
}
|
|
780
841
|
/**
|
|
@@ -782,10 +843,11 @@ class SekuireSDK {
|
|
|
782
843
|
*
|
|
783
844
|
* Required env vars:
|
|
784
845
|
* SEKUIRE_AGENT_ID - The agent's sekuire_id
|
|
846
|
+
* SEKUIRE_INSTALL_TOKEN - Install token from dashboard (required for heartbeat)
|
|
785
847
|
*
|
|
786
848
|
* Optional env vars:
|
|
787
849
|
* SEKUIRE_API_KEY - API key for authentication (X-API-Key header)
|
|
788
|
-
* SEKUIRE_PRIVATE_KEY - Private key for signing
|
|
850
|
+
* SEKUIRE_PRIVATE_KEY - Private key for signing
|
|
789
851
|
* SEKUIRE_AGENT_NAME - Human-readable agent name
|
|
790
852
|
* SEKUIRE_API_URL - API base URL (default: https://api.sekuire.ai)
|
|
791
853
|
* SEKUIRE_WORKSPACE_ID - Workspace ID for policy enforcement
|
|
@@ -799,6 +861,7 @@ class SekuireSDK {
|
|
|
799
861
|
return new SekuireSDK({
|
|
800
862
|
privateKey: process.env.SEKUIRE_PRIVATE_KEY,
|
|
801
863
|
apiKey: process.env.SEKUIRE_API_KEY,
|
|
864
|
+
installToken: process.env.SEKUIRE_INSTALL_TOKEN,
|
|
802
865
|
agentId,
|
|
803
866
|
agentName: process.env.SEKUIRE_AGENT_NAME,
|
|
804
867
|
apiUrl: process.env.SEKUIRE_API_URL ?? DEFAULT_API_URL,
|
|
@@ -811,46 +874,32 @@ class SekuireSDK {
|
|
|
811
874
|
/**
|
|
812
875
|
* Start the SDK.
|
|
813
876
|
*
|
|
814
|
-
* -
|
|
877
|
+
* - Bootstraps with Sekuire using the install token
|
|
815
878
|
* - Starts auto-heartbeat loop if enabled
|
|
879
|
+
*
|
|
880
|
+
* Requires SEKUIRE_INSTALL_TOKEN to be set (from dashboard or CLI).
|
|
816
881
|
*/
|
|
817
882
|
async start() {
|
|
818
883
|
if (this.isRunning) {
|
|
819
884
|
return;
|
|
820
885
|
}
|
|
821
886
|
this.isRunning = true;
|
|
822
|
-
if (this.config.autoHeartbeat &&
|
|
887
|
+
if (this.config.autoHeartbeat && this.config.installToken) {
|
|
823
888
|
await this.beacon.start();
|
|
824
889
|
}
|
|
890
|
+
else if (this.config.autoHeartbeat && !this.config.installToken) {
|
|
891
|
+
console.warn("[SekuireSDK] Auto-heartbeat enabled but no install token provided. " +
|
|
892
|
+
"Set SEKUIRE_INSTALL_TOKEN or generate one from the dashboard.");
|
|
893
|
+
}
|
|
825
894
|
}
|
|
826
895
|
/**
|
|
827
|
-
*
|
|
828
|
-
*
|
|
829
|
-
* The heartbeat proves the agent is running and has access to the private key.
|
|
896
|
+
* Check if the beacon is connected and sending heartbeats.
|
|
830
897
|
*
|
|
831
|
-
* @
|
|
832
|
-
* @returns True if heartbeat was acknowledged, False otherwise
|
|
898
|
+
* @returns True if the beacon has successfully bootstrapped
|
|
833
899
|
*/
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
}
|
|
838
|
-
const timestamp = Math.floor(Date.now() / 1000);
|
|
839
|
-
const message = `${this.config.agentId}|${url ?? ""}|${timestamp}`;
|
|
840
|
-
const signature = await this.identity.sign(message);
|
|
841
|
-
const payload = {
|
|
842
|
-
sekuire_id: this.config.agentId,
|
|
843
|
-
url: url ?? null,
|
|
844
|
-
timestamp,
|
|
845
|
-
signature,
|
|
846
|
-
};
|
|
847
|
-
try {
|
|
848
|
-
const response = await this.client.post("/api/v1/agents/heartbeat", payload);
|
|
849
|
-
return response.status === 200;
|
|
850
|
-
}
|
|
851
|
-
catch {
|
|
852
|
-
return false;
|
|
853
|
-
}
|
|
900
|
+
isConnected() {
|
|
901
|
+
const status = this.beacon.getStatus();
|
|
902
|
+
return status.isRunning && !!status.installationId;
|
|
854
903
|
}
|
|
855
904
|
/**
|
|
856
905
|
* Log an event to Sekuire.
|
|
@@ -3070,12 +3119,25 @@ const llm = {
|
|
|
3070
3119
|
};
|
|
3071
3120
|
|
|
3072
3121
|
class BaseMemoryStorage {
|
|
3122
|
+
constructor() {
|
|
3123
|
+
this._connected = false;
|
|
3124
|
+
}
|
|
3125
|
+
async connect() {
|
|
3126
|
+
this._connected = true;
|
|
3127
|
+
}
|
|
3128
|
+
async disconnect() {
|
|
3129
|
+
this._connected = false;
|
|
3130
|
+
}
|
|
3131
|
+
isConnected() {
|
|
3132
|
+
return this._connected;
|
|
3133
|
+
}
|
|
3073
3134
|
}
|
|
3074
3135
|
|
|
3075
3136
|
class InMemoryStorage extends BaseMemoryStorage {
|
|
3076
3137
|
constructor() {
|
|
3077
|
-
super(
|
|
3138
|
+
super();
|
|
3078
3139
|
this.storage = new Map();
|
|
3140
|
+
this._connected = true;
|
|
3079
3141
|
}
|
|
3080
3142
|
async add(sessionId, message) {
|
|
3081
3143
|
if (!this.storage.has(sessionId)) {
|
|
@@ -3104,32 +3166,49 @@ class InMemoryStorage extends BaseMemoryStorage {
|
|
|
3104
3166
|
class PostgresStorage extends BaseMemoryStorage {
|
|
3105
3167
|
constructor(config) {
|
|
3106
3168
|
super();
|
|
3107
|
-
this.
|
|
3169
|
+
this.connectionPromise = null;
|
|
3108
3170
|
this.tableName = config.tableName || 'sekuire_memory';
|
|
3109
|
-
this.
|
|
3171
|
+
this.config = config;
|
|
3172
|
+
if (!config.lazyConnect) {
|
|
3173
|
+
this.connectionPromise = this.connect();
|
|
3174
|
+
}
|
|
3175
|
+
}
|
|
3176
|
+
async connect() {
|
|
3177
|
+
if (this._connected)
|
|
3178
|
+
return;
|
|
3179
|
+
if (this.connectionPromise)
|
|
3180
|
+
return this.connectionPromise;
|
|
3181
|
+
this.connectionPromise = this.initPool();
|
|
3182
|
+
return this.connectionPromise;
|
|
3110
3183
|
}
|
|
3111
|
-
async initPool(
|
|
3184
|
+
async initPool() {
|
|
3112
3185
|
try {
|
|
3113
3186
|
const { Pool } = await import('pg');
|
|
3114
|
-
if (config.connectionString) {
|
|
3115
|
-
this.pool = new Pool({ connectionString: config.connectionString });
|
|
3187
|
+
if (this.config.connectionString) {
|
|
3188
|
+
this.pool = new Pool({ connectionString: this.config.connectionString });
|
|
3116
3189
|
}
|
|
3117
3190
|
else {
|
|
3118
3191
|
this.pool = new Pool({
|
|
3119
|
-
host: config.host || 'localhost',
|
|
3120
|
-
port: config.port || 5432,
|
|
3121
|
-
database: config.database,
|
|
3122
|
-
user: config.user,
|
|
3123
|
-
password: config.password,
|
|
3192
|
+
host: this.config.host || 'localhost',
|
|
3193
|
+
port: this.config.port || 5432,
|
|
3194
|
+
database: this.config.database,
|
|
3195
|
+
user: this.config.user,
|
|
3196
|
+
password: this.config.password,
|
|
3124
3197
|
});
|
|
3125
3198
|
}
|
|
3126
3199
|
await this.createTableIfNotExists();
|
|
3127
|
-
this.
|
|
3200
|
+
this._connected = true;
|
|
3128
3201
|
}
|
|
3129
3202
|
catch (error) {
|
|
3203
|
+
this.connectionPromise = null;
|
|
3130
3204
|
throw new Error(`Failed to initialize Postgres: ${error}`);
|
|
3131
3205
|
}
|
|
3132
3206
|
}
|
|
3207
|
+
async ensureConnected() {
|
|
3208
|
+
if (!this._connected) {
|
|
3209
|
+
await this.connect();
|
|
3210
|
+
}
|
|
3211
|
+
}
|
|
3133
3212
|
async createTableIfNotExists() {
|
|
3134
3213
|
const query = `
|
|
3135
3214
|
CREATE TABLE IF NOT EXISTS ${this.tableName} (
|
|
@@ -3146,8 +3225,7 @@ class PostgresStorage extends BaseMemoryStorage {
|
|
|
3146
3225
|
await this.pool.query(query);
|
|
3147
3226
|
}
|
|
3148
3227
|
async add(sessionId, message) {
|
|
3149
|
-
|
|
3150
|
-
throw new Error('Postgres not initialized');
|
|
3228
|
+
await this.ensureConnected();
|
|
3151
3229
|
const query = `
|
|
3152
3230
|
INSERT INTO ${this.tableName} (session_id, role, content, timestamp, metadata)
|
|
3153
3231
|
VALUES ($1, $2, $3, $4, $5)
|
|
@@ -3161,8 +3239,7 @@ class PostgresStorage extends BaseMemoryStorage {
|
|
|
3161
3239
|
]);
|
|
3162
3240
|
}
|
|
3163
3241
|
async get(sessionId, limit) {
|
|
3164
|
-
|
|
3165
|
-
throw new Error('Postgres not initialized');
|
|
3242
|
+
await this.ensureConnected();
|
|
3166
3243
|
let query = `
|
|
3167
3244
|
SELECT role, content, timestamp, metadata
|
|
3168
3245
|
FROM ${this.tableName}
|
|
@@ -3181,8 +3258,7 @@ class PostgresStorage extends BaseMemoryStorage {
|
|
|
3181
3258
|
}));
|
|
3182
3259
|
}
|
|
3183
3260
|
async clear(sessionId) {
|
|
3184
|
-
|
|
3185
|
-
throw new Error('Postgres not initialized');
|
|
3261
|
+
await this.ensureConnected();
|
|
3186
3262
|
const query = `DELETE FROM ${this.tableName} WHERE session_id = $1`;
|
|
3187
3263
|
await this.pool.query(query, [sessionId]);
|
|
3188
3264
|
}
|
|
@@ -3190,16 +3266,16 @@ class PostgresStorage extends BaseMemoryStorage {
|
|
|
3190
3266
|
await this.clear(sessionId);
|
|
3191
3267
|
}
|
|
3192
3268
|
async exists(sessionId) {
|
|
3193
|
-
|
|
3194
|
-
throw new Error('Postgres not initialized');
|
|
3269
|
+
await this.ensureConnected();
|
|
3195
3270
|
const query = `SELECT COUNT(*) FROM ${this.tableName} WHERE session_id = $1`;
|
|
3196
3271
|
const result = await this.pool.query(query, [sessionId]);
|
|
3197
3272
|
return parseInt(result.rows[0].count) > 0;
|
|
3198
3273
|
}
|
|
3199
3274
|
async disconnect() {
|
|
3200
|
-
if (this.
|
|
3275
|
+
if (this._connected && this.pool) {
|
|
3201
3276
|
await this.pool.end();
|
|
3202
|
-
this.
|
|
3277
|
+
this._connected = false;
|
|
3278
|
+
this.connectionPromise = null;
|
|
3203
3279
|
}
|
|
3204
3280
|
}
|
|
3205
3281
|
}
|
|
@@ -3208,56 +3284,70 @@ class RedisStorage extends BaseMemoryStorage {
|
|
|
3208
3284
|
constructor(config) {
|
|
3209
3285
|
super();
|
|
3210
3286
|
this.client = null;
|
|
3211
|
-
this.
|
|
3287
|
+
this.connectionPromise = null;
|
|
3212
3288
|
this.keyPrefix = config.keyPrefix || 'sekuire:memory:';
|
|
3213
|
-
this.
|
|
3289
|
+
this.config = config;
|
|
3290
|
+
if (!config.lazyConnect) {
|
|
3291
|
+
this.connectionPromise = this.connect();
|
|
3292
|
+
}
|
|
3293
|
+
}
|
|
3294
|
+
async connect() {
|
|
3295
|
+
if (this._connected)
|
|
3296
|
+
return;
|
|
3297
|
+
if (this.connectionPromise)
|
|
3298
|
+
return this.connectionPromise;
|
|
3299
|
+
this.connectionPromise = this.initClient();
|
|
3300
|
+
return this.connectionPromise;
|
|
3214
3301
|
}
|
|
3215
|
-
async initClient(
|
|
3302
|
+
async initClient() {
|
|
3216
3303
|
try {
|
|
3217
3304
|
const { createClient } = await import('redis');
|
|
3218
|
-
if (config.url) {
|
|
3219
|
-
this.client = createClient({ url: config.url });
|
|
3305
|
+
if (this.config.url) {
|
|
3306
|
+
this.client = createClient({ url: this.config.url });
|
|
3220
3307
|
}
|
|
3221
3308
|
else {
|
|
3222
3309
|
this.client = createClient({
|
|
3223
3310
|
socket: {
|
|
3224
|
-
host: config.host || 'localhost',
|
|
3225
|
-
port: config.port || 6379,
|
|
3311
|
+
host: this.config.host || 'localhost',
|
|
3312
|
+
port: this.config.port || 6379,
|
|
3226
3313
|
},
|
|
3227
|
-
password: config.password,
|
|
3228
|
-
database: config.db || 0,
|
|
3314
|
+
password: this.config.password,
|
|
3315
|
+
database: this.config.db || 0,
|
|
3229
3316
|
});
|
|
3230
3317
|
}
|
|
3231
3318
|
this.client.on('error', (err) => {
|
|
3232
3319
|
console.error('Redis client error:', err);
|
|
3233
3320
|
});
|
|
3234
3321
|
await this.client.connect();
|
|
3235
|
-
this.
|
|
3322
|
+
this._connected = true;
|
|
3236
3323
|
}
|
|
3237
3324
|
catch (error) {
|
|
3325
|
+
this.connectionPromise = null;
|
|
3238
3326
|
throw new Error(`Failed to initialize Redis: ${error}`);
|
|
3239
3327
|
}
|
|
3240
3328
|
}
|
|
3329
|
+
async ensureConnected() {
|
|
3330
|
+
if (!this._connected) {
|
|
3331
|
+
await this.connect();
|
|
3332
|
+
}
|
|
3333
|
+
}
|
|
3241
3334
|
getKey(sessionId) {
|
|
3242
3335
|
return `${this.keyPrefix}${sessionId}`;
|
|
3243
3336
|
}
|
|
3244
3337
|
async add(sessionId, message) {
|
|
3245
|
-
|
|
3246
|
-
throw new Error('Redis not connected');
|
|
3338
|
+
await this.ensureConnected();
|
|
3247
3339
|
const key = this.getKey(sessionId);
|
|
3248
3340
|
await this.client.rPush(key, JSON.stringify(message));
|
|
3249
3341
|
}
|
|
3250
3342
|
async get(sessionId, limit) {
|
|
3251
|
-
|
|
3252
|
-
throw new Error('Redis not connected');
|
|
3343
|
+
await this.ensureConnected();
|
|
3253
3344
|
const key = this.getKey(sessionId);
|
|
3254
3345
|
const start = limit ? -limit : 0;
|
|
3255
3346
|
const messages = await this.client.lRange(key, start, -1);
|
|
3256
3347
|
return messages.map((msg) => JSON.parse(msg));
|
|
3257
3348
|
}
|
|
3258
3349
|
async clear(sessionId) {
|
|
3259
|
-
|
|
3260
|
-
throw new Error('Redis not connected');
|
|
3350
|
+
await this.ensureConnected();
|
|
3261
3351
|
const key = this.getKey(sessionId);
|
|
3262
3352
|
await this.client.del(key);
|
|
3263
3353
|
}
|
|
@@ -3265,190 +3355,1080 @@ class RedisStorage extends BaseMemoryStorage {
|
|
|
3265
3355
|
await this.clear(sessionId);
|
|
3266
3356
|
}
|
|
3267
3357
|
async exists(sessionId) {
|
|
3268
|
-
|
|
3269
|
-
throw new Error('Redis not connected');
|
|
3358
|
+
await this.ensureConnected();
|
|
3270
3359
|
const key = this.getKey(sessionId);
|
|
3271
3360
|
return (await this.client.exists(key)) === 1;
|
|
3272
3361
|
}
|
|
3273
3362
|
async disconnect() {
|
|
3274
|
-
if (this.
|
|
3363
|
+
if (this._connected && this.client) {
|
|
3275
3364
|
await this.client.quit();
|
|
3276
|
-
this.
|
|
3365
|
+
this._connected = false;
|
|
3366
|
+
this.connectionPromise = null;
|
|
3277
3367
|
}
|
|
3278
3368
|
}
|
|
3279
3369
|
}
|
|
3280
3370
|
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
throw new Error('Redis config required for redis memory type');
|
|
3290
|
-
}
|
|
3291
|
-
return new RedisStorage(config.redis);
|
|
3292
|
-
case 'postgres':
|
|
3293
|
-
if (!config.postgres) {
|
|
3294
|
-
throw new Error('Postgres config required for postgres memory type');
|
|
3295
|
-
}
|
|
3296
|
-
return new PostgresStorage(config.postgres);
|
|
3297
|
-
default:
|
|
3298
|
-
throw new Error(`Unknown memory type: ${config.type}`);
|
|
3299
|
-
}
|
|
3300
|
-
}
|
|
3301
|
-
|
|
3302
|
-
const DEFAULT_OVERRIDE_ENV = "SEKUIRE_POLICY_DEV_OVERRIDE";
|
|
3303
|
-
class PolicyEnforcer {
|
|
3304
|
-
constructor(policy, override, onViolation) {
|
|
3305
|
-
this.policy = policy;
|
|
3306
|
-
this.onViolation = onViolation;
|
|
3307
|
-
const envOverride = process.env[DEFAULT_OVERRIDE_ENV] === "true";
|
|
3308
|
-
this.override = override ?? envOverride;
|
|
3309
|
-
if (this.override) {
|
|
3310
|
-
console.warn("[policy] override enabled; policy enforcement is running in warn-only mode");
|
|
3311
|
-
}
|
|
3371
|
+
class SQLiteStorage extends BaseMemoryStorage {
|
|
3372
|
+
constructor(config) {
|
|
3373
|
+
super();
|
|
3374
|
+
this.db = null;
|
|
3375
|
+
this.connectionPromise = null;
|
|
3376
|
+
this.config = config;
|
|
3377
|
+
this.tableName = config.tableName || 'sekuire_memory';
|
|
3378
|
+
this.connectionPromise = this.connect();
|
|
3312
3379
|
}
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
if (!perms) {
|
|
3316
|
-
this.warnOnly("network.missing", "Network permissions not configured");
|
|
3380
|
+
async connect() {
|
|
3381
|
+
if (this._connected)
|
|
3317
3382
|
return;
|
|
3383
|
+
if (this.connectionPromise && !this._connected)
|
|
3384
|
+
return this.connectionPromise;
|
|
3385
|
+
try {
|
|
3386
|
+
const Database = (await import('better-sqlite3')).default;
|
|
3387
|
+
this.db = new Database(this.config.filename, {
|
|
3388
|
+
readonly: this.config.readonly || false,
|
|
3389
|
+
});
|
|
3390
|
+
this.db.pragma('journal_mode = WAL');
|
|
3391
|
+
this.ensureTableExists();
|
|
3392
|
+
this._connected = true;
|
|
3318
3393
|
}
|
|
3319
|
-
|
|
3320
|
-
this.
|
|
3321
|
-
|
|
3322
|
-
this.throw("network.tls_required", "TLS is required for network requests");
|
|
3323
|
-
}
|
|
3324
|
-
if (perms.blocked_domains && this.matches(domain, perms.blocked_domains)) {
|
|
3325
|
-
this.throw("network.blocked", `Domain ${domain} is blocked by policy`);
|
|
3326
|
-
}
|
|
3327
|
-
if (perms.allowed_domains && !this.matches(domain, perms.allowed_domains)) {
|
|
3328
|
-
this.throw("network.not_allowed", `Domain ${domain} is not in the allowlist`);
|
|
3394
|
+
catch (error) {
|
|
3395
|
+
this.connectionPromise = null;
|
|
3396
|
+
throw new Error(`Failed to initialize SQLite: ${error}`);
|
|
3329
3397
|
}
|
|
3330
3398
|
}
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
if (ext && !perms.allowed_extensions.includes(ext)) {
|
|
3348
|
-
this.throw("fs.ext", `Extension ${ext} is not allowed`);
|
|
3349
|
-
}
|
|
3350
|
-
}
|
|
3399
|
+
ensureTableExists() {
|
|
3400
|
+
this.db.exec(`
|
|
3401
|
+
CREATE TABLE IF NOT EXISTS ${this.tableName} (
|
|
3402
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
3403
|
+
session_id TEXT NOT NULL,
|
|
3404
|
+
role TEXT NOT NULL,
|
|
3405
|
+
content TEXT NOT NULL,
|
|
3406
|
+
timestamp INTEGER NOT NULL,
|
|
3407
|
+
metadata TEXT,
|
|
3408
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
3409
|
+
)
|
|
3410
|
+
`);
|
|
3411
|
+
this.db.exec(`
|
|
3412
|
+
CREATE INDEX IF NOT EXISTS idx_${this.tableName}_session_id
|
|
3413
|
+
ON ${this.tableName}(session_id)
|
|
3414
|
+
`);
|
|
3351
3415
|
}
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
if (tools?.blocked_tools?.includes(toolName)) {
|
|
3356
|
-
this.throw("tool.blocked", `Tool ${toolName} is blocked`);
|
|
3357
|
-
}
|
|
3358
|
-
// If no allowlist, allow all tools
|
|
3359
|
-
if (!tools?.allowed_tools || tools.allowed_tools.length === 0) {
|
|
3360
|
-
return;
|
|
3361
|
-
}
|
|
3362
|
-
// Check allowlist with pattern matching
|
|
3363
|
-
const isAllowed = tools.allowed_tools.some((t) => {
|
|
3364
|
-
const pattern = t.name;
|
|
3365
|
-
// Exact match
|
|
3366
|
-
if (pattern === toolName) {
|
|
3367
|
-
return true;
|
|
3368
|
-
}
|
|
3369
|
-
// Category patterns: "files:*" => matches "file_read", "file_write", etc
|
|
3370
|
-
// Check this BEFORE wildcard matching since it contains both : and *
|
|
3371
|
-
if (pattern.includes(":")) {
|
|
3372
|
-
const [category, ops] = pattern.split(":", 2);
|
|
3373
|
-
const categoryPrefix = this.getCategoryPrefix(category);
|
|
3374
|
-
if (ops === "*") {
|
|
3375
|
-
// Match all tools in category
|
|
3376
|
-
const matches = toolName.startsWith(categoryPrefix + "_");
|
|
3377
|
-
return matches;
|
|
3378
|
-
}
|
|
3379
|
-
if (ops.startsWith("[") && ops.endsWith("]")) {
|
|
3380
|
-
// Match specific operations: "files:[read,write]"
|
|
3381
|
-
const operations = ops.slice(1, -1).split(",").map(s => s.trim());
|
|
3382
|
-
const matches = operations.some(op => toolName === `${categoryPrefix}_${op}`);
|
|
3383
|
-
console.log(`[DEBUG] ${matches ? '✓' : '✗'} Category ops: ${operations.join(",")}`);
|
|
3384
|
-
return matches;
|
|
3385
|
-
}
|
|
3386
|
-
}
|
|
3387
|
-
// Pattern matching: "file_*", etc (simple wildcards without :)
|
|
3388
|
-
if (pattern.includes("*")) {
|
|
3389
|
-
const regex = new RegExp("^" + pattern.replace(/\*/g, ".*") + "$");
|
|
3390
|
-
const matches = regex.test(toolName);
|
|
3391
|
-
return matches;
|
|
3392
|
-
}
|
|
3393
|
-
return false;
|
|
3394
|
-
});
|
|
3395
|
-
if (!isAllowed) {
|
|
3396
|
-
this.throw("tool.not_allowed", `Tool ${toolName} is not in the allowlist`);
|
|
3416
|
+
async ensureConnected() {
|
|
3417
|
+
if (!this._connected) {
|
|
3418
|
+
await this.connect();
|
|
3397
3419
|
}
|
|
3398
3420
|
}
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
};
|
|
3407
|
-
return prefixMap[category] || category;
|
|
3421
|
+
async add(sessionId, message) {
|
|
3422
|
+
await this.ensureConnected();
|
|
3423
|
+
const stmt = this.db.prepare(`
|
|
3424
|
+
INSERT INTO ${this.tableName} (session_id, role, content, timestamp, metadata)
|
|
3425
|
+
VALUES (?, ?, ?, ?, ?)
|
|
3426
|
+
`);
|
|
3427
|
+
stmt.run(sessionId, message.role, message.content, message.timestamp, message.metadata ? JSON.stringify(message.metadata) : null);
|
|
3408
3428
|
}
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3429
|
+
async get(sessionId, limit) {
|
|
3430
|
+
await this.ensureConnected();
|
|
3431
|
+
let sql = `
|
|
3432
|
+
SELECT role, content, timestamp, metadata
|
|
3433
|
+
FROM ${this.tableName}
|
|
3434
|
+
WHERE session_id = ?
|
|
3435
|
+
ORDER BY timestamp ASC
|
|
3436
|
+
`;
|
|
3437
|
+
if (limit) {
|
|
3438
|
+
sql += ` LIMIT ${limit}`;
|
|
3416
3439
|
}
|
|
3440
|
+
const stmt = this.db.prepare(sql);
|
|
3441
|
+
const rows = stmt.all(sessionId);
|
|
3442
|
+
return rows.map((row) => ({
|
|
3443
|
+
role: row.role,
|
|
3444
|
+
content: row.content,
|
|
3445
|
+
timestamp: row.timestamp,
|
|
3446
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
|
|
3447
|
+
}));
|
|
3417
3448
|
}
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3449
|
+
async clear(sessionId) {
|
|
3450
|
+
await this.ensureConnected();
|
|
3451
|
+
const stmt = this.db.prepare(`DELETE FROM ${this.tableName} WHERE session_id = ?`);
|
|
3452
|
+
stmt.run(sessionId);
|
|
3453
|
+
}
|
|
3454
|
+
async delete(sessionId) {
|
|
3455
|
+
await this.clear(sessionId);
|
|
3456
|
+
}
|
|
3457
|
+
async exists(sessionId) {
|
|
3458
|
+
await this.ensureConnected();
|
|
3459
|
+
const stmt = this.db.prepare(`SELECT COUNT(*) as count FROM ${this.tableName} WHERE session_id = ?`);
|
|
3460
|
+
const result = stmt.get(sessionId);
|
|
3461
|
+
return result.count > 0;
|
|
3462
|
+
}
|
|
3463
|
+
async disconnect() {
|
|
3464
|
+
if (this._connected && this.db) {
|
|
3465
|
+
this.db.close();
|
|
3466
|
+
this._connected = false;
|
|
3467
|
+
this.connectionPromise = null;
|
|
3429
3468
|
}
|
|
3430
3469
|
}
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3470
|
+
}
|
|
3471
|
+
|
|
3472
|
+
class UpstashStorage extends BaseMemoryStorage {
|
|
3473
|
+
constructor(config) {
|
|
3474
|
+
super();
|
|
3475
|
+
this.client = null;
|
|
3476
|
+
this.connectionPromise = null;
|
|
3477
|
+
this.keyPrefix = config.keyPrefix || 'sekuire:memory:';
|
|
3478
|
+
this.config = config;
|
|
3479
|
+
this.connectionPromise = this.connect();
|
|
3438
3480
|
}
|
|
3439
|
-
|
|
3440
|
-
if (this.
|
|
3441
|
-
this.warnOnly(rule, reason);
|
|
3481
|
+
async connect() {
|
|
3482
|
+
if (this._connected)
|
|
3442
3483
|
return;
|
|
3484
|
+
if (this.connectionPromise && !this._connected)
|
|
3485
|
+
return this.connectionPromise;
|
|
3486
|
+
try {
|
|
3487
|
+
const { Redis } = await import('@upstash/redis');
|
|
3488
|
+
this.client = new Redis({
|
|
3489
|
+
url: this.config.url,
|
|
3490
|
+
token: this.config.token,
|
|
3491
|
+
});
|
|
3492
|
+
this._connected = true;
|
|
3493
|
+
}
|
|
3494
|
+
catch (error) {
|
|
3495
|
+
this.connectionPromise = null;
|
|
3496
|
+
throw new Error(`Failed to initialize Upstash Redis: ${error}`);
|
|
3443
3497
|
}
|
|
3444
|
-
if (this.onViolation)
|
|
3445
|
-
this.onViolation(rule, reason);
|
|
3446
|
-
throw new PolicyViolationError(reason, rule);
|
|
3447
3498
|
}
|
|
3448
|
-
|
|
3449
|
-
if (this.
|
|
3450
|
-
this.
|
|
3451
|
-
|
|
3499
|
+
async ensureConnected() {
|
|
3500
|
+
if (!this._connected) {
|
|
3501
|
+
await this.connect();
|
|
3502
|
+
}
|
|
3503
|
+
}
|
|
3504
|
+
getKey(sessionId) {
|
|
3505
|
+
return `${this.keyPrefix}${sessionId}`;
|
|
3506
|
+
}
|
|
3507
|
+
async add(sessionId, message) {
|
|
3508
|
+
await this.ensureConnected();
|
|
3509
|
+
const key = this.getKey(sessionId);
|
|
3510
|
+
await this.client.rpush(key, JSON.stringify(message));
|
|
3511
|
+
}
|
|
3512
|
+
async get(sessionId, limit) {
|
|
3513
|
+
await this.ensureConnected();
|
|
3514
|
+
const key = this.getKey(sessionId);
|
|
3515
|
+
const start = limit ? -limit : 0;
|
|
3516
|
+
const messages = await this.client.lrange(key, start, -1);
|
|
3517
|
+
return messages.map((msg) => JSON.parse(msg));
|
|
3518
|
+
}
|
|
3519
|
+
async clear(sessionId) {
|
|
3520
|
+
await this.ensureConnected();
|
|
3521
|
+
const key = this.getKey(sessionId);
|
|
3522
|
+
await this.client.del(key);
|
|
3523
|
+
}
|
|
3524
|
+
async delete(sessionId) {
|
|
3525
|
+
await this.clear(sessionId);
|
|
3526
|
+
}
|
|
3527
|
+
async exists(sessionId) {
|
|
3528
|
+
await this.ensureConnected();
|
|
3529
|
+
const key = this.getKey(sessionId);
|
|
3530
|
+
return (await this.client.exists(key)) === 1;
|
|
3531
|
+
}
|
|
3532
|
+
async disconnect() {
|
|
3533
|
+
this._connected = false;
|
|
3534
|
+
this.client = null;
|
|
3535
|
+
this.connectionPromise = null;
|
|
3536
|
+
}
|
|
3537
|
+
}
|
|
3538
|
+
|
|
3539
|
+
class CloudflareKVStorage extends BaseMemoryStorage {
|
|
3540
|
+
constructor(config) {
|
|
3541
|
+
super();
|
|
3542
|
+
this.binding = null;
|
|
3543
|
+
this.config = config;
|
|
3544
|
+
this.keyPrefix = config.keyPrefix || 'sekuire:memory:';
|
|
3545
|
+
if (config.binding) {
|
|
3546
|
+
this.binding = config.binding;
|
|
3547
|
+
this.useRestApi = false;
|
|
3548
|
+
this._connected = true;
|
|
3549
|
+
}
|
|
3550
|
+
else if (config.accountId && config.namespaceId && config.apiToken) {
|
|
3551
|
+
this.useRestApi = true;
|
|
3552
|
+
this._connected = true;
|
|
3553
|
+
}
|
|
3554
|
+
else {
|
|
3555
|
+
throw new Error('CloudflareKVConfig requires either a binding (in Workers) or accountId, namespaceId, and apiToken (for REST API)');
|
|
3556
|
+
}
|
|
3557
|
+
}
|
|
3558
|
+
getKey(sessionId) {
|
|
3559
|
+
return `${this.keyPrefix}${sessionId}`;
|
|
3560
|
+
}
|
|
3561
|
+
async kvGet(key) {
|
|
3562
|
+
if (!this.useRestApi) {
|
|
3563
|
+
return this.binding.get(key);
|
|
3564
|
+
}
|
|
3565
|
+
const { accountId, namespaceId, apiToken } = this.config;
|
|
3566
|
+
const url = `https://api.cloudflare.com/client/v4/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${encodeURIComponent(key)}`;
|
|
3567
|
+
const response = await fetch(url, {
|
|
3568
|
+
headers: { Authorization: `Bearer ${apiToken}` },
|
|
3569
|
+
});
|
|
3570
|
+
if (response.status === 404)
|
|
3571
|
+
return null;
|
|
3572
|
+
if (!response.ok)
|
|
3573
|
+
throw new Error(`KV GET failed: ${response.statusText}`);
|
|
3574
|
+
return response.text();
|
|
3575
|
+
}
|
|
3576
|
+
async kvPut(key, value) {
|
|
3577
|
+
if (!this.useRestApi) {
|
|
3578
|
+
await this.binding.put(key, value);
|
|
3579
|
+
return;
|
|
3580
|
+
}
|
|
3581
|
+
const { accountId, namespaceId, apiToken } = this.config;
|
|
3582
|
+
const url = `https://api.cloudflare.com/client/v4/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${encodeURIComponent(key)}`;
|
|
3583
|
+
const response = await fetch(url, {
|
|
3584
|
+
method: 'PUT',
|
|
3585
|
+
headers: {
|
|
3586
|
+
Authorization: `Bearer ${apiToken}`,
|
|
3587
|
+
'Content-Type': 'text/plain',
|
|
3588
|
+
},
|
|
3589
|
+
body: value,
|
|
3590
|
+
});
|
|
3591
|
+
if (!response.ok)
|
|
3592
|
+
throw new Error(`KV PUT failed: ${response.statusText}`);
|
|
3593
|
+
}
|
|
3594
|
+
async kvDelete(key) {
|
|
3595
|
+
if (!this.useRestApi) {
|
|
3596
|
+
await this.binding.delete(key);
|
|
3597
|
+
return;
|
|
3598
|
+
}
|
|
3599
|
+
const { accountId, namespaceId, apiToken } = this.config;
|
|
3600
|
+
const url = `https://api.cloudflare.com/client/v4/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${encodeURIComponent(key)}`;
|
|
3601
|
+
const response = await fetch(url, {
|
|
3602
|
+
method: 'DELETE',
|
|
3603
|
+
headers: { Authorization: `Bearer ${apiToken}` },
|
|
3604
|
+
});
|
|
3605
|
+
if (!response.ok && response.status !== 404) {
|
|
3606
|
+
throw new Error(`KV DELETE failed: ${response.statusText}`);
|
|
3607
|
+
}
|
|
3608
|
+
}
|
|
3609
|
+
async add(sessionId, message) {
|
|
3610
|
+
const key = this.getKey(sessionId);
|
|
3611
|
+
const existing = await this.kvGet(key);
|
|
3612
|
+
const messages = existing ? JSON.parse(existing) : [];
|
|
3613
|
+
messages.push(message);
|
|
3614
|
+
await this.kvPut(key, JSON.stringify(messages));
|
|
3615
|
+
}
|
|
3616
|
+
async get(sessionId, limit) {
|
|
3617
|
+
const key = this.getKey(sessionId);
|
|
3618
|
+
const data = await this.kvGet(key);
|
|
3619
|
+
if (!data)
|
|
3620
|
+
return [];
|
|
3621
|
+
const messages = JSON.parse(data);
|
|
3622
|
+
if (limit) {
|
|
3623
|
+
return messages.slice(-limit);
|
|
3624
|
+
}
|
|
3625
|
+
return messages;
|
|
3626
|
+
}
|
|
3627
|
+
async clear(sessionId) {
|
|
3628
|
+
const key = this.getKey(sessionId);
|
|
3629
|
+
await this.kvDelete(key);
|
|
3630
|
+
}
|
|
3631
|
+
async delete(sessionId) {
|
|
3632
|
+
await this.clear(sessionId);
|
|
3633
|
+
}
|
|
3634
|
+
async exists(sessionId) {
|
|
3635
|
+
const key = this.getKey(sessionId);
|
|
3636
|
+
const data = await this.kvGet(key);
|
|
3637
|
+
return data !== null;
|
|
3638
|
+
}
|
|
3639
|
+
async disconnect() {
|
|
3640
|
+
this._connected = false;
|
|
3641
|
+
}
|
|
3642
|
+
}
|
|
3643
|
+
|
|
3644
|
+
class CloudflareD1Storage extends BaseMemoryStorage {
|
|
3645
|
+
constructor(config) {
|
|
3646
|
+
super();
|
|
3647
|
+
this.binding = null;
|
|
3648
|
+
this.tableInitialized = false;
|
|
3649
|
+
this.config = config;
|
|
3650
|
+
this.tableName = config.tableName || 'sekuire_memory';
|
|
3651
|
+
if (config.binding) {
|
|
3652
|
+
this.binding = config.binding;
|
|
3653
|
+
this.useRestApi = false;
|
|
3654
|
+
this._connected = true;
|
|
3655
|
+
}
|
|
3656
|
+
else if (config.accountId && config.databaseId && config.apiToken) {
|
|
3657
|
+
this.useRestApi = true;
|
|
3658
|
+
this._connected = true;
|
|
3659
|
+
}
|
|
3660
|
+
else {
|
|
3661
|
+
throw new Error('CloudflareD1Config requires either a binding (in Workers) or accountId, databaseId, and apiToken (for REST API)');
|
|
3662
|
+
}
|
|
3663
|
+
}
|
|
3664
|
+
async executeQuery(sql, params = []) {
|
|
3665
|
+
if (!this.useRestApi) {
|
|
3666
|
+
const stmt = this.binding.prepare(sql);
|
|
3667
|
+
if (params.length > 0) {
|
|
3668
|
+
return stmt.bind(...params).all();
|
|
3669
|
+
}
|
|
3670
|
+
return stmt.all();
|
|
3671
|
+
}
|
|
3672
|
+
const { accountId, databaseId, apiToken } = this.config;
|
|
3673
|
+
const url = `https://api.cloudflare.com/client/v4/accounts/${accountId}/d1/database/${databaseId}/query`;
|
|
3674
|
+
const response = await fetch(url, {
|
|
3675
|
+
method: 'POST',
|
|
3676
|
+
headers: {
|
|
3677
|
+
Authorization: `Bearer ${apiToken}`,
|
|
3678
|
+
'Content-Type': 'application/json',
|
|
3679
|
+
},
|
|
3680
|
+
body: JSON.stringify({ sql, params }),
|
|
3681
|
+
});
|
|
3682
|
+
if (!response.ok) {
|
|
3683
|
+
const errorText = await response.text();
|
|
3684
|
+
throw new Error(`D1 query failed: ${response.statusText} - ${errorText}`);
|
|
3685
|
+
}
|
|
3686
|
+
const result = await response.json();
|
|
3687
|
+
if (!result.success) {
|
|
3688
|
+
throw new Error(`D1 query failed: ${JSON.stringify(result.errors)}`);
|
|
3689
|
+
}
|
|
3690
|
+
return result.result?.[0] || { results: [] };
|
|
3691
|
+
}
|
|
3692
|
+
async ensureTableExists() {
|
|
3693
|
+
if (this.tableInitialized)
|
|
3694
|
+
return;
|
|
3695
|
+
const createTableSQL = `
|
|
3696
|
+
CREATE TABLE IF NOT EXISTS ${this.tableName} (
|
|
3697
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
3698
|
+
session_id TEXT NOT NULL,
|
|
3699
|
+
role TEXT NOT NULL,
|
|
3700
|
+
content TEXT NOT NULL,
|
|
3701
|
+
timestamp INTEGER NOT NULL,
|
|
3702
|
+
metadata TEXT,
|
|
3703
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
3704
|
+
)
|
|
3705
|
+
`;
|
|
3706
|
+
const createIndexSQL = `
|
|
3707
|
+
CREATE INDEX IF NOT EXISTS idx_${this.tableName}_session_id ON ${this.tableName}(session_id)
|
|
3708
|
+
`;
|
|
3709
|
+
await this.executeQuery(createTableSQL);
|
|
3710
|
+
await this.executeQuery(createIndexSQL);
|
|
3711
|
+
this.tableInitialized = true;
|
|
3712
|
+
}
|
|
3713
|
+
async add(sessionId, message) {
|
|
3714
|
+
await this.ensureTableExists();
|
|
3715
|
+
const sql = `
|
|
3716
|
+
INSERT INTO ${this.tableName} (session_id, role, content, timestamp, metadata)
|
|
3717
|
+
VALUES (?, ?, ?, ?, ?)
|
|
3718
|
+
`;
|
|
3719
|
+
await this.executeQuery(sql, [
|
|
3720
|
+
sessionId,
|
|
3721
|
+
message.role,
|
|
3722
|
+
message.content,
|
|
3723
|
+
message.timestamp,
|
|
3724
|
+
message.metadata ? JSON.stringify(message.metadata) : null,
|
|
3725
|
+
]);
|
|
3726
|
+
}
|
|
3727
|
+
async get(sessionId, limit) {
|
|
3728
|
+
await this.ensureTableExists();
|
|
3729
|
+
let sql = `
|
|
3730
|
+
SELECT role, content, timestamp, metadata
|
|
3731
|
+
FROM ${this.tableName}
|
|
3732
|
+
WHERE session_id = ?
|
|
3733
|
+
ORDER BY timestamp ASC
|
|
3734
|
+
`;
|
|
3735
|
+
if (limit) {
|
|
3736
|
+
sql += ` LIMIT ${limit}`;
|
|
3737
|
+
}
|
|
3738
|
+
const result = await this.executeQuery(sql, [sessionId]);
|
|
3739
|
+
return (result.results || []).map((row) => ({
|
|
3740
|
+
role: row.role,
|
|
3741
|
+
content: row.content,
|
|
3742
|
+
timestamp: row.timestamp,
|
|
3743
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
|
|
3744
|
+
}));
|
|
3745
|
+
}
|
|
3746
|
+
async clear(sessionId) {
|
|
3747
|
+
await this.ensureTableExists();
|
|
3748
|
+
const sql = `DELETE FROM ${this.tableName} WHERE session_id = ?`;
|
|
3749
|
+
await this.executeQuery(sql, [sessionId]);
|
|
3750
|
+
}
|
|
3751
|
+
async delete(sessionId) {
|
|
3752
|
+
await this.clear(sessionId);
|
|
3753
|
+
}
|
|
3754
|
+
async exists(sessionId) {
|
|
3755
|
+
await this.ensureTableExists();
|
|
3756
|
+
const sql = `SELECT COUNT(*) as count FROM ${this.tableName} WHERE session_id = ?`;
|
|
3757
|
+
const result = await this.executeQuery(sql, [sessionId]);
|
|
3758
|
+
return (result.results?.[0]?.count || 0) > 0;
|
|
3759
|
+
}
|
|
3760
|
+
async disconnect() {
|
|
3761
|
+
this._connected = false;
|
|
3762
|
+
}
|
|
3763
|
+
}
|
|
3764
|
+
|
|
3765
|
+
class DynamoDBStorage extends BaseMemoryStorage {
|
|
3766
|
+
constructor(config) {
|
|
3767
|
+
super();
|
|
3768
|
+
this.client = null;
|
|
3769
|
+
this.docClient = null;
|
|
3770
|
+
this.connectionPromise = null;
|
|
3771
|
+
this.tableReady = false;
|
|
3772
|
+
this.config = config;
|
|
3773
|
+
this.connectionPromise = this.connect();
|
|
3774
|
+
}
|
|
3775
|
+
async connect() {
|
|
3776
|
+
if (this._connected)
|
|
3777
|
+
return;
|
|
3778
|
+
if (this.connectionPromise && !this._connected)
|
|
3779
|
+
return this.connectionPromise;
|
|
3780
|
+
try {
|
|
3781
|
+
const { DynamoDBClient, CreateTableCommand, DescribeTableCommand } = await import('@aws-sdk/client-dynamodb');
|
|
3782
|
+
const { DynamoDBDocumentClient, PutCommand, QueryCommand, DeleteCommand } = await import('@aws-sdk/lib-dynamodb');
|
|
3783
|
+
const clientConfig = {
|
|
3784
|
+
region: this.config.region || process.env.AWS_REGION || 'us-east-1',
|
|
3785
|
+
};
|
|
3786
|
+
if (this.config.endpoint) {
|
|
3787
|
+
clientConfig.endpoint = this.config.endpoint;
|
|
3788
|
+
}
|
|
3789
|
+
if (this.config.credentials) {
|
|
3790
|
+
clientConfig.credentials = this.config.credentials;
|
|
3791
|
+
}
|
|
3792
|
+
this.client = new DynamoDBClient(clientConfig);
|
|
3793
|
+
this.docClient = DynamoDBDocumentClient.from(this.client);
|
|
3794
|
+
if (this.config.createTable) {
|
|
3795
|
+
await this.ensureTableExists();
|
|
3796
|
+
}
|
|
3797
|
+
this._connected = true;
|
|
3798
|
+
}
|
|
3799
|
+
catch (error) {
|
|
3800
|
+
this.connectionPromise = null;
|
|
3801
|
+
throw new Error(`Failed to initialize DynamoDB: ${error}`);
|
|
3802
|
+
}
|
|
3803
|
+
}
|
|
3804
|
+
async ensureTableExists() {
|
|
3805
|
+
if (this.tableReady)
|
|
3806
|
+
return;
|
|
3807
|
+
try {
|
|
3808
|
+
const { DescribeTableCommand } = await import('@aws-sdk/client-dynamodb');
|
|
3809
|
+
await this.client.send(new DescribeTableCommand({ TableName: this.config.tableName }));
|
|
3810
|
+
this.tableReady = true;
|
|
3811
|
+
return;
|
|
3812
|
+
}
|
|
3813
|
+
catch (error) {
|
|
3814
|
+
if (error.name !== 'ResourceNotFoundException') {
|
|
3815
|
+
throw error;
|
|
3816
|
+
}
|
|
3817
|
+
}
|
|
3818
|
+
const { CreateTableCommand } = await import('@aws-sdk/client-dynamodb');
|
|
3819
|
+
await this.client.send(new CreateTableCommand({
|
|
3820
|
+
TableName: this.config.tableName,
|
|
3821
|
+
KeySchema: [
|
|
3822
|
+
{ AttributeName: 'sessionId', KeyType: 'HASH' },
|
|
3823
|
+
{ AttributeName: 'timestamp', KeyType: 'RANGE' },
|
|
3824
|
+
],
|
|
3825
|
+
AttributeDefinitions: [
|
|
3826
|
+
{ AttributeName: 'sessionId', AttributeType: 'S' },
|
|
3827
|
+
{ AttributeName: 'timestamp', AttributeType: 'N' },
|
|
3828
|
+
],
|
|
3829
|
+
BillingMode: 'PAY_PER_REQUEST',
|
|
3830
|
+
}));
|
|
3831
|
+
const { waitUntilTableExists } = await import('@aws-sdk/client-dynamodb');
|
|
3832
|
+
await waitUntilTableExists({ client: this.client, maxWaitTime: 120 }, { TableName: this.config.tableName });
|
|
3833
|
+
this.tableReady = true;
|
|
3834
|
+
}
|
|
3835
|
+
async ensureConnected() {
|
|
3836
|
+
if (!this._connected) {
|
|
3837
|
+
await this.connect();
|
|
3838
|
+
}
|
|
3839
|
+
}
|
|
3840
|
+
async add(sessionId, message) {
|
|
3841
|
+
await this.ensureConnected();
|
|
3842
|
+
const { PutCommand } = await import('@aws-sdk/lib-dynamodb');
|
|
3843
|
+
await this.docClient.send(new PutCommand({
|
|
3844
|
+
TableName: this.config.tableName,
|
|
3845
|
+
Item: {
|
|
3846
|
+
sessionId,
|
|
3847
|
+
timestamp: message.timestamp,
|
|
3848
|
+
role: message.role,
|
|
3849
|
+
content: message.content,
|
|
3850
|
+
metadata: message.metadata || {},
|
|
3851
|
+
},
|
|
3852
|
+
}));
|
|
3853
|
+
}
|
|
3854
|
+
async get(sessionId, limit) {
|
|
3855
|
+
await this.ensureConnected();
|
|
3856
|
+
const { QueryCommand } = await import('@aws-sdk/lib-dynamodb');
|
|
3857
|
+
const params = {
|
|
3858
|
+
TableName: this.config.tableName,
|
|
3859
|
+
KeyConditionExpression: 'sessionId = :sid',
|
|
3860
|
+
ExpressionAttributeValues: {
|
|
3861
|
+
':sid': sessionId,
|
|
3862
|
+
},
|
|
3863
|
+
ScanIndexForward: true,
|
|
3864
|
+
};
|
|
3865
|
+
if (limit) {
|
|
3866
|
+
params.Limit = limit;
|
|
3867
|
+
params.ScanIndexForward = false;
|
|
3868
|
+
}
|
|
3869
|
+
const result = await this.docClient.send(new QueryCommand(params));
|
|
3870
|
+
const items = result.Items || [];
|
|
3871
|
+
const messages = items.map((item) => ({
|
|
3872
|
+
role: item.role,
|
|
3873
|
+
content: item.content,
|
|
3874
|
+
timestamp: item.timestamp,
|
|
3875
|
+
metadata: item.metadata && Object.keys(item.metadata).length > 0 ? item.metadata : undefined,
|
|
3876
|
+
}));
|
|
3877
|
+
if (limit) {
|
|
3878
|
+
messages.reverse();
|
|
3879
|
+
}
|
|
3880
|
+
return messages;
|
|
3881
|
+
}
|
|
3882
|
+
async clear(sessionId) {
|
|
3883
|
+
await this.ensureConnected();
|
|
3884
|
+
const messages = await this.get(sessionId);
|
|
3885
|
+
const { DeleteCommand } = await import('@aws-sdk/lib-dynamodb');
|
|
3886
|
+
for (const message of messages) {
|
|
3887
|
+
await this.docClient.send(new DeleteCommand({
|
|
3888
|
+
TableName: this.config.tableName,
|
|
3889
|
+
Key: {
|
|
3890
|
+
sessionId,
|
|
3891
|
+
timestamp: message.timestamp,
|
|
3892
|
+
},
|
|
3893
|
+
}));
|
|
3894
|
+
}
|
|
3895
|
+
}
|
|
3896
|
+
async delete(sessionId) {
|
|
3897
|
+
await this.clear(sessionId);
|
|
3898
|
+
}
|
|
3899
|
+
async exists(sessionId) {
|
|
3900
|
+
await this.ensureConnected();
|
|
3901
|
+
const { QueryCommand } = await import('@aws-sdk/lib-dynamodb');
|
|
3902
|
+
const result = await this.docClient.send(new QueryCommand({
|
|
3903
|
+
TableName: this.config.tableName,
|
|
3904
|
+
KeyConditionExpression: 'sessionId = :sid',
|
|
3905
|
+
ExpressionAttributeValues: {
|
|
3906
|
+
':sid': sessionId,
|
|
3907
|
+
},
|
|
3908
|
+
Limit: 1,
|
|
3909
|
+
Select: 'COUNT',
|
|
3910
|
+
}));
|
|
3911
|
+
return (result.Count || 0) > 0;
|
|
3912
|
+
}
|
|
3913
|
+
async disconnect() {
|
|
3914
|
+
if (this._connected && this.client) {
|
|
3915
|
+
this.client.destroy();
|
|
3916
|
+
this._connected = false;
|
|
3917
|
+
this.connectionPromise = null;
|
|
3918
|
+
}
|
|
3919
|
+
}
|
|
3920
|
+
}
|
|
3921
|
+
|
|
3922
|
+
class TursoStorage extends BaseMemoryStorage {
|
|
3923
|
+
constructor(config) {
|
|
3924
|
+
super();
|
|
3925
|
+
this.client = null;
|
|
3926
|
+
this.connectionPromise = null;
|
|
3927
|
+
this.tableInitialized = false;
|
|
3928
|
+
this.config = config;
|
|
3929
|
+
this.tableName = config.tableName || 'sekuire_memory';
|
|
3930
|
+
this.connectionPromise = this.connect();
|
|
3931
|
+
}
|
|
3932
|
+
async connect() {
|
|
3933
|
+
if (this._connected)
|
|
3934
|
+
return;
|
|
3935
|
+
if (this.connectionPromise && !this._connected)
|
|
3936
|
+
return this.connectionPromise;
|
|
3937
|
+
try {
|
|
3938
|
+
const { createClient } = await import('@libsql/client');
|
|
3939
|
+
this.client = createClient({
|
|
3940
|
+
url: this.config.url,
|
|
3941
|
+
authToken: this.config.authToken,
|
|
3942
|
+
});
|
|
3943
|
+
await this.ensureTableExists();
|
|
3944
|
+
this._connected = true;
|
|
3945
|
+
}
|
|
3946
|
+
catch (error) {
|
|
3947
|
+
this.connectionPromise = null;
|
|
3948
|
+
throw new Error(`Failed to initialize Turso: ${error}`);
|
|
3949
|
+
}
|
|
3950
|
+
}
|
|
3951
|
+
async ensureTableExists() {
|
|
3952
|
+
if (this.tableInitialized)
|
|
3953
|
+
return;
|
|
3954
|
+
await this.client.execute(`
|
|
3955
|
+
CREATE TABLE IF NOT EXISTS ${this.tableName} (
|
|
3956
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
3957
|
+
session_id TEXT NOT NULL,
|
|
3958
|
+
role TEXT NOT NULL,
|
|
3959
|
+
content TEXT NOT NULL,
|
|
3960
|
+
timestamp INTEGER NOT NULL,
|
|
3961
|
+
metadata TEXT,
|
|
3962
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
3963
|
+
)
|
|
3964
|
+
`);
|
|
3965
|
+
await this.client.execute(`
|
|
3966
|
+
CREATE INDEX IF NOT EXISTS idx_${this.tableName}_session_id ON ${this.tableName}(session_id)
|
|
3967
|
+
`);
|
|
3968
|
+
this.tableInitialized = true;
|
|
3969
|
+
}
|
|
3970
|
+
async ensureConnected() {
|
|
3971
|
+
if (!this._connected) {
|
|
3972
|
+
await this.connect();
|
|
3973
|
+
}
|
|
3974
|
+
}
|
|
3975
|
+
async add(sessionId, message) {
|
|
3976
|
+
await this.ensureConnected();
|
|
3977
|
+
await this.client.execute({
|
|
3978
|
+
sql: `
|
|
3979
|
+
INSERT INTO ${this.tableName} (session_id, role, content, timestamp, metadata)
|
|
3980
|
+
VALUES (?, ?, ?, ?, ?)
|
|
3981
|
+
`,
|
|
3982
|
+
args: [
|
|
3983
|
+
sessionId,
|
|
3984
|
+
message.role,
|
|
3985
|
+
message.content,
|
|
3986
|
+
message.timestamp,
|
|
3987
|
+
message.metadata ? JSON.stringify(message.metadata) : null,
|
|
3988
|
+
],
|
|
3989
|
+
});
|
|
3990
|
+
}
|
|
3991
|
+
async get(sessionId, limit) {
|
|
3992
|
+
await this.ensureConnected();
|
|
3993
|
+
let sql = `
|
|
3994
|
+
SELECT role, content, timestamp, metadata
|
|
3995
|
+
FROM ${this.tableName}
|
|
3996
|
+
WHERE session_id = ?
|
|
3997
|
+
ORDER BY timestamp ASC
|
|
3998
|
+
`;
|
|
3999
|
+
if (limit) {
|
|
4000
|
+
sql += ` LIMIT ${limit}`;
|
|
4001
|
+
}
|
|
4002
|
+
const result = await this.client.execute({
|
|
4003
|
+
sql,
|
|
4004
|
+
args: [sessionId],
|
|
4005
|
+
});
|
|
4006
|
+
return result.rows.map((row) => ({
|
|
4007
|
+
role: row.role,
|
|
4008
|
+
content: row.content,
|
|
4009
|
+
timestamp: Number(row.timestamp),
|
|
4010
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
|
|
4011
|
+
}));
|
|
4012
|
+
}
|
|
4013
|
+
async clear(sessionId) {
|
|
4014
|
+
await this.ensureConnected();
|
|
4015
|
+
await this.client.execute({
|
|
4016
|
+
sql: `DELETE FROM ${this.tableName} WHERE session_id = ?`,
|
|
4017
|
+
args: [sessionId],
|
|
4018
|
+
});
|
|
4019
|
+
}
|
|
4020
|
+
async delete(sessionId) {
|
|
4021
|
+
await this.clear(sessionId);
|
|
4022
|
+
}
|
|
4023
|
+
async exists(sessionId) {
|
|
4024
|
+
await this.ensureConnected();
|
|
4025
|
+
const result = await this.client.execute({
|
|
4026
|
+
sql: `SELECT COUNT(*) as count FROM ${this.tableName} WHERE session_id = ?`,
|
|
4027
|
+
args: [sessionId],
|
|
4028
|
+
});
|
|
4029
|
+
return Number(result.rows[0]?.count || 0) > 0;
|
|
4030
|
+
}
|
|
4031
|
+
async disconnect() {
|
|
4032
|
+
if (this._connected && this.client) {
|
|
4033
|
+
this.client.close();
|
|
4034
|
+
this._connected = false;
|
|
4035
|
+
this.connectionPromise = null;
|
|
4036
|
+
}
|
|
4037
|
+
}
|
|
4038
|
+
}
|
|
4039
|
+
|
|
4040
|
+
class ConvexStorage extends BaseMemoryStorage {
|
|
4041
|
+
constructor(config) {
|
|
4042
|
+
super();
|
|
4043
|
+
this.client = null;
|
|
4044
|
+
this.connectionPromise = null;
|
|
4045
|
+
this.config = config;
|
|
4046
|
+
this.connectionPromise = this.connect();
|
|
4047
|
+
}
|
|
4048
|
+
async connect() {
|
|
4049
|
+
if (this._connected)
|
|
4050
|
+
return;
|
|
4051
|
+
if (this.connectionPromise && !this._connected)
|
|
4052
|
+
return this.connectionPromise;
|
|
4053
|
+
try {
|
|
4054
|
+
const { ConvexHttpClient } = await import('convex/browser');
|
|
4055
|
+
this.client = new ConvexHttpClient(this.config.url);
|
|
4056
|
+
this._connected = true;
|
|
4057
|
+
}
|
|
4058
|
+
catch (error) {
|
|
4059
|
+
this.connectionPromise = null;
|
|
4060
|
+
throw new Error(`Failed to initialize Convex: ${error}`);
|
|
4061
|
+
}
|
|
4062
|
+
}
|
|
4063
|
+
async ensureConnected() {
|
|
4064
|
+
if (!this._connected) {
|
|
4065
|
+
await this.connect();
|
|
4066
|
+
}
|
|
4067
|
+
}
|
|
4068
|
+
async add(sessionId, message) {
|
|
4069
|
+
await this.ensureConnected();
|
|
4070
|
+
await this.client.mutation('sekuireMemory:add', {
|
|
4071
|
+
sessionId,
|
|
4072
|
+
role: message.role,
|
|
4073
|
+
content: message.content,
|
|
4074
|
+
timestamp: message.timestamp,
|
|
4075
|
+
metadata: message.metadata || {},
|
|
4076
|
+
});
|
|
4077
|
+
}
|
|
4078
|
+
async get(sessionId, limit) {
|
|
4079
|
+
await this.ensureConnected();
|
|
4080
|
+
const messages = await this.client.query('sekuireMemory:get', {
|
|
4081
|
+
sessionId,
|
|
4082
|
+
limit,
|
|
4083
|
+
});
|
|
4084
|
+
return messages.map((msg) => ({
|
|
4085
|
+
role: msg.role,
|
|
4086
|
+
content: msg.content,
|
|
4087
|
+
timestamp: msg.timestamp,
|
|
4088
|
+
metadata: msg.metadata && Object.keys(msg.metadata).length > 0 ? msg.metadata : undefined,
|
|
4089
|
+
}));
|
|
4090
|
+
}
|
|
4091
|
+
async clear(sessionId) {
|
|
4092
|
+
await this.ensureConnected();
|
|
4093
|
+
await this.client.mutation('sekuireMemory:clear', { sessionId });
|
|
4094
|
+
}
|
|
4095
|
+
async delete(sessionId) {
|
|
4096
|
+
await this.clear(sessionId);
|
|
4097
|
+
}
|
|
4098
|
+
async exists(sessionId) {
|
|
4099
|
+
await this.ensureConnected();
|
|
4100
|
+
return this.client.query('sekuireMemory:exists', { sessionId });
|
|
4101
|
+
}
|
|
4102
|
+
async disconnect() {
|
|
4103
|
+
this._connected = false;
|
|
4104
|
+
this.client = null;
|
|
4105
|
+
this.connectionPromise = null;
|
|
4106
|
+
}
|
|
4107
|
+
}
|
|
4108
|
+
const CONVEX_SCHEMA_TEMPLATE = `
|
|
4109
|
+
// convex/schema.ts
|
|
4110
|
+
import { defineSchema, defineTable } from "convex/server";
|
|
4111
|
+
import { v } from "convex/values";
|
|
4112
|
+
|
|
4113
|
+
export default defineSchema({
|
|
4114
|
+
sekuireMemory: defineTable({
|
|
4115
|
+
sessionId: v.string(),
|
|
4116
|
+
role: v.union(v.literal("user"), v.literal("assistant"), v.literal("system")),
|
|
4117
|
+
content: v.string(),
|
|
4118
|
+
timestamp: v.number(),
|
|
4119
|
+
metadata: v.optional(v.any()),
|
|
4120
|
+
}).index("by_session", ["sessionId", "timestamp"]),
|
|
4121
|
+
});
|
|
4122
|
+
`;
|
|
4123
|
+
const CONVEX_FUNCTIONS_TEMPLATE = `
|
|
4124
|
+
// convex/sekuireMemory.ts
|
|
4125
|
+
import { mutation, query } from "./_generated/server";
|
|
4126
|
+
import { v } from "convex/values";
|
|
4127
|
+
|
|
4128
|
+
export const add = mutation({
|
|
4129
|
+
args: {
|
|
4130
|
+
sessionId: v.string(),
|
|
4131
|
+
role: v.union(v.literal("user"), v.literal("assistant"), v.literal("system")),
|
|
4132
|
+
content: v.string(),
|
|
4133
|
+
timestamp: v.number(),
|
|
4134
|
+
metadata: v.optional(v.any()),
|
|
4135
|
+
},
|
|
4136
|
+
handler: async (ctx, args) => {
|
|
4137
|
+
await ctx.db.insert("sekuireMemory", args);
|
|
4138
|
+
},
|
|
4139
|
+
});
|
|
4140
|
+
|
|
4141
|
+
export const get = query({
|
|
4142
|
+
args: {
|
|
4143
|
+
sessionId: v.string(),
|
|
4144
|
+
limit: v.optional(v.number()),
|
|
4145
|
+
},
|
|
4146
|
+
handler: async (ctx, args) => {
|
|
4147
|
+
let query = ctx.db
|
|
4148
|
+
.query("sekuireMemory")
|
|
4149
|
+
.withIndex("by_session", (q) => q.eq("sessionId", args.sessionId))
|
|
4150
|
+
.order("asc");
|
|
4151
|
+
|
|
4152
|
+
const messages = await query.collect();
|
|
4153
|
+
|
|
4154
|
+
if (args.limit) {
|
|
4155
|
+
return messages.slice(-args.limit);
|
|
4156
|
+
}
|
|
4157
|
+
return messages;
|
|
4158
|
+
},
|
|
4159
|
+
});
|
|
4160
|
+
|
|
4161
|
+
export const clear = mutation({
|
|
4162
|
+
args: {
|
|
4163
|
+
sessionId: v.string(),
|
|
4164
|
+
},
|
|
4165
|
+
handler: async (ctx, args) => {
|
|
4166
|
+
const messages = await ctx.db
|
|
4167
|
+
.query("sekuireMemory")
|
|
4168
|
+
.withIndex("by_session", (q) => q.eq("sessionId", args.sessionId))
|
|
4169
|
+
.collect();
|
|
4170
|
+
|
|
4171
|
+
for (const message of messages) {
|
|
4172
|
+
await ctx.db.delete(message._id);
|
|
4173
|
+
}
|
|
4174
|
+
},
|
|
4175
|
+
});
|
|
4176
|
+
|
|
4177
|
+
export const exists = query({
|
|
4178
|
+
args: {
|
|
4179
|
+
sessionId: v.string(),
|
|
4180
|
+
},
|
|
4181
|
+
handler: async (ctx, args) => {
|
|
4182
|
+
const message = await ctx.db
|
|
4183
|
+
.query("sekuireMemory")
|
|
4184
|
+
.withIndex("by_session", (q) => q.eq("sessionId", args.sessionId))
|
|
4185
|
+
.first();
|
|
4186
|
+
return message !== null;
|
|
4187
|
+
},
|
|
4188
|
+
});
|
|
4189
|
+
`;
|
|
4190
|
+
|
|
4191
|
+
const storageRegistry = new Map();
|
|
4192
|
+
function registerStorage(type, factory, description) {
|
|
4193
|
+
if (storageRegistry.has(type)) {
|
|
4194
|
+
console.warn(`Storage type '${type}' is already registered. Overwriting.`);
|
|
4195
|
+
}
|
|
4196
|
+
storageRegistry.set(type, { factory, description });
|
|
4197
|
+
}
|
|
4198
|
+
function getStorageFactory(type) {
|
|
4199
|
+
const registration = storageRegistry.get(type);
|
|
4200
|
+
return registration?.factory;
|
|
4201
|
+
}
|
|
4202
|
+
function hasStorage(type) {
|
|
4203
|
+
return storageRegistry.has(type);
|
|
4204
|
+
}
|
|
4205
|
+
function listStorageTypes() {
|
|
4206
|
+
return Array.from(storageRegistry.keys());
|
|
4207
|
+
}
|
|
4208
|
+
function getStorageInfo() {
|
|
4209
|
+
return Array.from(storageRegistry.entries()).map(([type, reg]) => ({
|
|
4210
|
+
type,
|
|
4211
|
+
description: reg.description,
|
|
4212
|
+
}));
|
|
4213
|
+
}
|
|
4214
|
+
|
|
4215
|
+
registerStorage('in-memory', () => new InMemoryStorage(), 'Simple in-memory storage using Map');
|
|
4216
|
+
registerStorage('buffer', () => new InMemoryStorage(), 'Alias for in-memory storage');
|
|
4217
|
+
registerStorage('redis', (config) => {
|
|
4218
|
+
if (!config.redis) {
|
|
4219
|
+
throw new Error('Redis config required for redis memory type');
|
|
4220
|
+
}
|
|
4221
|
+
return new RedisStorage(config.redis);
|
|
4222
|
+
}, 'Self-hosted Redis for persistence and scaling');
|
|
4223
|
+
registerStorage('postgres', (config) => {
|
|
4224
|
+
if (!config.postgres) {
|
|
4225
|
+
throw new Error('Postgres config required for postgres memory type');
|
|
4226
|
+
}
|
|
4227
|
+
return new PostgresStorage(config.postgres);
|
|
4228
|
+
}, 'PostgreSQL with full SQL capabilities');
|
|
4229
|
+
registerStorage('sqlite', (config) => {
|
|
4230
|
+
if (!config.sqlite) {
|
|
4231
|
+
throw new Error('SQLite config required for sqlite memory type');
|
|
4232
|
+
}
|
|
4233
|
+
return new SQLiteStorage(config.sqlite);
|
|
4234
|
+
}, 'Local SQLite database for development and single-node deployments');
|
|
4235
|
+
registerStorage('upstash', (config) => {
|
|
4236
|
+
if (!config.upstash) {
|
|
4237
|
+
throw new Error('Upstash config required for upstash memory type');
|
|
4238
|
+
}
|
|
4239
|
+
return new UpstashStorage(config.upstash);
|
|
4240
|
+
}, 'Upstash Redis - serverless Redis with HTTP API');
|
|
4241
|
+
registerStorage('cloudflare-kv', (config) => {
|
|
4242
|
+
if (!config.cloudflareKV) {
|
|
4243
|
+
throw new Error('CloudflareKV config required for cloudflare-kv memory type');
|
|
4244
|
+
}
|
|
4245
|
+
return new CloudflareKVStorage(config.cloudflareKV);
|
|
4246
|
+
}, 'Cloudflare KV - edge key-value storage');
|
|
4247
|
+
registerStorage('cloudflare-d1', (config) => {
|
|
4248
|
+
if (!config.cloudflareD1) {
|
|
4249
|
+
throw new Error('CloudflareD1 config required for cloudflare-d1 memory type');
|
|
4250
|
+
}
|
|
4251
|
+
return new CloudflareD1Storage(config.cloudflareD1);
|
|
4252
|
+
}, 'Cloudflare D1 - edge SQLite database');
|
|
4253
|
+
registerStorage('dynamodb', (config) => {
|
|
4254
|
+
if (!config.dynamodb) {
|
|
4255
|
+
throw new Error('DynamoDB config required for dynamodb memory type');
|
|
4256
|
+
}
|
|
4257
|
+
return new DynamoDBStorage(config.dynamodb);
|
|
4258
|
+
}, 'AWS DynamoDB - serverless NoSQL database');
|
|
4259
|
+
registerStorage('turso', (config) => {
|
|
4260
|
+
if (!config.turso) {
|
|
4261
|
+
throw new Error('Turso config required for turso memory type');
|
|
4262
|
+
}
|
|
4263
|
+
return new TursoStorage(config.turso);
|
|
4264
|
+
}, 'Turso - edge SQLite with libSQL');
|
|
4265
|
+
registerStorage('convex', (config) => {
|
|
4266
|
+
if (!config.convex) {
|
|
4267
|
+
throw new Error('Convex config required for convex memory type');
|
|
4268
|
+
}
|
|
4269
|
+
return new ConvexStorage(config.convex);
|
|
4270
|
+
}, 'Convex - real-time backend platform');
|
|
4271
|
+
function createMemoryStorage(config) {
|
|
4272
|
+
if (config.instance) {
|
|
4273
|
+
return config.instance;
|
|
4274
|
+
}
|
|
4275
|
+
const factory = getStorageFactory(config.type);
|
|
4276
|
+
if (factory) {
|
|
4277
|
+
return factory(config);
|
|
4278
|
+
}
|
|
4279
|
+
throw new Error(`Unknown memory type: ${config.type}. Available types: ${listStorageTypes().join(', ')}`);
|
|
4280
|
+
}
|
|
4281
|
+
|
|
4282
|
+
const DEFAULT_OVERRIDE_ENV = "SEKUIRE_POLICY_DEV_OVERRIDE";
|
|
4283
|
+
class PolicyEnforcer {
|
|
4284
|
+
constructor(policy, override, onViolation) {
|
|
4285
|
+
this.policy = policy;
|
|
4286
|
+
this.onViolation = onViolation;
|
|
4287
|
+
const envOverride = process.env[DEFAULT_OVERRIDE_ENV] === "true";
|
|
4288
|
+
this.override = override ?? envOverride;
|
|
4289
|
+
if (this.override) {
|
|
4290
|
+
console.warn("[policy] override enabled; policy enforcement is running in warn-only mode");
|
|
4291
|
+
}
|
|
4292
|
+
}
|
|
4293
|
+
enforceNetwork(domain, protocol) {
|
|
4294
|
+
const perms = this.policy.content?.permissions?.network;
|
|
4295
|
+
if (!perms) {
|
|
4296
|
+
this.warnOnly("network.missing", "Network permissions not configured");
|
|
4297
|
+
return;
|
|
4298
|
+
}
|
|
4299
|
+
if (!perms.enabled)
|
|
4300
|
+
this.throw("network.disabled", "Network access is disabled");
|
|
4301
|
+
if (perms.require_tls && protocol !== "https") {
|
|
4302
|
+
this.throw("network.tls_required", "TLS is required for network requests");
|
|
4303
|
+
}
|
|
4304
|
+
if (perms.blocked_domains && this.matches(domain, perms.blocked_domains)) {
|
|
4305
|
+
this.throw("network.blocked", `Domain ${domain} is blocked by policy`);
|
|
4306
|
+
}
|
|
4307
|
+
if (perms.allowed_domains && !this.matches(domain, perms.allowed_domains)) {
|
|
4308
|
+
this.throw("network.not_allowed", `Domain ${domain} is not in the allowlist`);
|
|
4309
|
+
}
|
|
4310
|
+
}
|
|
4311
|
+
enforceFilesystem(path, operation) {
|
|
4312
|
+
const perms = this.policy.content?.permissions?.filesystem;
|
|
4313
|
+
if (!perms) {
|
|
4314
|
+
this.warnOnly("fs.missing", "Filesystem permissions not configured");
|
|
4315
|
+
return;
|
|
4316
|
+
}
|
|
4317
|
+
if (!perms.enabled)
|
|
4318
|
+
this.throw("fs.disabled", "Filesystem access is disabled");
|
|
4319
|
+
if (perms.blocked_paths && this.pathMatch(path, perms.blocked_paths)) {
|
|
4320
|
+
this.throw("fs.blocked", `Path ${path} is blocked`);
|
|
4321
|
+
}
|
|
4322
|
+
if (perms.allowed_paths && !this.pathMatch(path, perms.allowed_paths)) {
|
|
4323
|
+
this.throw("fs.not_allowed", `Path ${path} is not in the allowlist`);
|
|
4324
|
+
}
|
|
4325
|
+
if (perms.allowed_extensions) {
|
|
4326
|
+
const ext = path.includes(".") ? `.${path.split(".").pop()}` : "";
|
|
4327
|
+
if (ext && !perms.allowed_extensions.includes(ext)) {
|
|
4328
|
+
this.throw("fs.ext", `Extension ${ext} is not allowed`);
|
|
4329
|
+
}
|
|
4330
|
+
}
|
|
4331
|
+
}
|
|
4332
|
+
enforceTool(toolName) {
|
|
4333
|
+
const tools = this.policy.content?.tools;
|
|
4334
|
+
// Check blocked tools
|
|
4335
|
+
if (tools?.blocked_tools?.includes(toolName)) {
|
|
4336
|
+
this.throw("tool.blocked", `Tool ${toolName} is blocked`);
|
|
4337
|
+
}
|
|
4338
|
+
// If no allowlist, allow all tools
|
|
4339
|
+
if (!tools?.allowed_tools || tools.allowed_tools.length === 0) {
|
|
4340
|
+
return;
|
|
4341
|
+
}
|
|
4342
|
+
// Check allowlist with pattern matching
|
|
4343
|
+
const isAllowed = tools.allowed_tools.some((t) => {
|
|
4344
|
+
const pattern = t.name;
|
|
4345
|
+
// Exact match
|
|
4346
|
+
if (pattern === toolName) {
|
|
4347
|
+
return true;
|
|
4348
|
+
}
|
|
4349
|
+
// Category patterns: "files:*" => matches "file_read", "file_write", etc
|
|
4350
|
+
// Check this BEFORE wildcard matching since it contains both : and *
|
|
4351
|
+
if (pattern.includes(":")) {
|
|
4352
|
+
const [category, ops] = pattern.split(":", 2);
|
|
4353
|
+
const categoryPrefix = this.getCategoryPrefix(category);
|
|
4354
|
+
if (ops === "*") {
|
|
4355
|
+
// Match all tools in category
|
|
4356
|
+
const matches = toolName.startsWith(categoryPrefix + "_");
|
|
4357
|
+
return matches;
|
|
4358
|
+
}
|
|
4359
|
+
if (ops.startsWith("[") && ops.endsWith("]")) {
|
|
4360
|
+
// Match specific operations: "files:[read,write]"
|
|
4361
|
+
const operations = ops.slice(1, -1).split(",").map(s => s.trim());
|
|
4362
|
+
const matches = operations.some(op => toolName === `${categoryPrefix}_${op}`);
|
|
4363
|
+
console.log(`[DEBUG] ${matches ? '✓' : '✗'} Category ops: ${operations.join(",")}`);
|
|
4364
|
+
return matches;
|
|
4365
|
+
}
|
|
4366
|
+
}
|
|
4367
|
+
// Pattern matching: "file_*", etc (simple wildcards without :)
|
|
4368
|
+
if (pattern.includes("*")) {
|
|
4369
|
+
const regex = new RegExp("^" + pattern.replace(/\*/g, ".*") + "$");
|
|
4370
|
+
const matches = regex.test(toolName);
|
|
4371
|
+
return matches;
|
|
4372
|
+
}
|
|
4373
|
+
return false;
|
|
4374
|
+
});
|
|
4375
|
+
if (!isAllowed) {
|
|
4376
|
+
this.throw("tool.not_allowed", `Tool ${toolName} is not in the allowlist`);
|
|
4377
|
+
}
|
|
4378
|
+
}
|
|
4379
|
+
getCategoryPrefix(category) {
|
|
4380
|
+
const prefixMap = {
|
|
4381
|
+
files: "file",
|
|
4382
|
+
directories: "dir",
|
|
4383
|
+
network: "http",
|
|
4384
|
+
data: "json",
|
|
4385
|
+
system: "env",
|
|
4386
|
+
};
|
|
4387
|
+
return prefixMap[category] || category;
|
|
4388
|
+
}
|
|
4389
|
+
enforceModel(model) {
|
|
4390
|
+
const models = this.policy.content?.agent?.models;
|
|
4391
|
+
if (models?.allowed_models && !models.allowed_models.includes(model)) {
|
|
4392
|
+
this.throw("model.not_allowed", `Model ${model} is not allowed`);
|
|
4393
|
+
}
|
|
4394
|
+
if (models?.blocked_models && models.blocked_models.includes(model)) {
|
|
4395
|
+
this.throw("model.blocked", `Model ${model} is blocked`);
|
|
4396
|
+
}
|
|
4397
|
+
}
|
|
4398
|
+
enforceApi(service) {
|
|
4399
|
+
const perms = this.policy.content?.permissions?.api;
|
|
4400
|
+
if (!perms) {
|
|
4401
|
+
this.warnOnly("api.missing", "API permissions not configured");
|
|
4402
|
+
return;
|
|
4403
|
+
}
|
|
4404
|
+
if (!perms.enabled)
|
|
4405
|
+
this.throw("api.disabled", "API access is disabled");
|
|
4406
|
+
if (perms.allowed_services &&
|
|
4407
|
+
!perms.allowed_services.some((s) => s.service_name === service)) {
|
|
4408
|
+
this.throw("api.not_allowed", `API service ${service} is not in the allowlist`);
|
|
4409
|
+
}
|
|
4410
|
+
}
|
|
4411
|
+
enforceRateLimit(type, count = 1) {
|
|
4412
|
+
const limits = this.policy.content?.rate_limits?.per_agent;
|
|
4413
|
+
if (!limits)
|
|
4414
|
+
return;
|
|
4415
|
+
// Simple local enforcement (note: this does not sync across instances)
|
|
4416
|
+
// TODO: Implement proper token bucket or sliding window
|
|
4417
|
+
if (type === "request" && limits.requests_per_minute) ;
|
|
4418
|
+
}
|
|
4419
|
+
throw(rule, reason) {
|
|
4420
|
+
if (this.override) {
|
|
4421
|
+
this.warnOnly(rule, reason);
|
|
4422
|
+
return;
|
|
4423
|
+
}
|
|
4424
|
+
if (this.onViolation)
|
|
4425
|
+
this.onViolation(rule, reason);
|
|
4426
|
+
throw new PolicyViolationError(reason, rule);
|
|
4427
|
+
}
|
|
4428
|
+
warnOnly(rule, reason) {
|
|
4429
|
+
if (this.onViolation)
|
|
4430
|
+
this.onViolation(rule, reason);
|
|
4431
|
+
console.warn(`[policy][${rule}] ${reason}`);
|
|
3452
4432
|
}
|
|
3453
4433
|
matches(domain, patterns) {
|
|
3454
4434
|
return patterns.some((pattern) => {
|
|
@@ -3907,7 +4887,7 @@ var __spreadArray$5 = (undefined && undefined.__spreadArray) || function (to, fr
|
|
|
3907
4887
|
}
|
|
3908
4888
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
3909
4889
|
};
|
|
3910
|
-
var API_NAME$
|
|
4890
|
+
var API_NAME$4 = 'diag';
|
|
3911
4891
|
/**
|
|
3912
4892
|
* Singleton object which represents the entry point to the OpenTelemetry internal
|
|
3913
4893
|
* diagnostic API
|
|
@@ -3962,7 +4942,7 @@ var DiagAPI = /** @class */ (function () {
|
|
|
3962
4942
|
};
|
|
3963
4943
|
self.setLogger = setLogger;
|
|
3964
4944
|
self.disable = function () {
|
|
3965
|
-
unregisterGlobal(API_NAME$
|
|
4945
|
+
unregisterGlobal(API_NAME$4, self);
|
|
3966
4946
|
};
|
|
3967
4947
|
self.createComponentLogger = function (options) {
|
|
3968
4948
|
return new DiagComponentLogger(options);
|
|
@@ -4196,6 +5176,171 @@ var BaseContext = /** @class */ (function () {
|
|
|
4196
5176
|
/** The root context is used as the default parent context when there is no active context */
|
|
4197
5177
|
var ROOT_CONTEXT = new BaseContext();
|
|
4198
5178
|
|
|
5179
|
+
/*
|
|
5180
|
+
* Copyright The OpenTelemetry Authors
|
|
5181
|
+
*
|
|
5182
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5183
|
+
* you may not use this file except in compliance with the License.
|
|
5184
|
+
* You may obtain a copy of the License at
|
|
5185
|
+
*
|
|
5186
|
+
* https://www.apache.org/licenses/LICENSE-2.0
|
|
5187
|
+
*
|
|
5188
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
5189
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
5190
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
5191
|
+
* See the License for the specific language governing permissions and
|
|
5192
|
+
* limitations under the License.
|
|
5193
|
+
*/
|
|
5194
|
+
var __extends$3 = (undefined && undefined.__extends) || (function () {
|
|
5195
|
+
var extendStatics = function (d, b) {
|
|
5196
|
+
extendStatics = Object.setPrototypeOf ||
|
|
5197
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
5198
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
5199
|
+
return extendStatics(d, b);
|
|
5200
|
+
};
|
|
5201
|
+
return function (d, b) {
|
|
5202
|
+
if (typeof b !== "function" && b !== null)
|
|
5203
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
5204
|
+
extendStatics(d, b);
|
|
5205
|
+
function __() { this.constructor = d; }
|
|
5206
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
5207
|
+
};
|
|
5208
|
+
})();
|
|
5209
|
+
/**
|
|
5210
|
+
* NoopMeter is a noop implementation of the {@link Meter} interface. It reuses
|
|
5211
|
+
* constant NoopMetrics for all of its methods.
|
|
5212
|
+
*/
|
|
5213
|
+
var NoopMeter = /** @class */ (function () {
|
|
5214
|
+
function NoopMeter() {
|
|
5215
|
+
}
|
|
5216
|
+
/**
|
|
5217
|
+
* @see {@link Meter.createGauge}
|
|
5218
|
+
*/
|
|
5219
|
+
NoopMeter.prototype.createGauge = function (_name, _options) {
|
|
5220
|
+
return NOOP_GAUGE_METRIC;
|
|
5221
|
+
};
|
|
5222
|
+
/**
|
|
5223
|
+
* @see {@link Meter.createHistogram}
|
|
5224
|
+
*/
|
|
5225
|
+
NoopMeter.prototype.createHistogram = function (_name, _options) {
|
|
5226
|
+
return NOOP_HISTOGRAM_METRIC;
|
|
5227
|
+
};
|
|
5228
|
+
/**
|
|
5229
|
+
* @see {@link Meter.createCounter}
|
|
5230
|
+
*/
|
|
5231
|
+
NoopMeter.prototype.createCounter = function (_name, _options) {
|
|
5232
|
+
return NOOP_COUNTER_METRIC;
|
|
5233
|
+
};
|
|
5234
|
+
/**
|
|
5235
|
+
* @see {@link Meter.createUpDownCounter}
|
|
5236
|
+
*/
|
|
5237
|
+
NoopMeter.prototype.createUpDownCounter = function (_name, _options) {
|
|
5238
|
+
return NOOP_UP_DOWN_COUNTER_METRIC;
|
|
5239
|
+
};
|
|
5240
|
+
/**
|
|
5241
|
+
* @see {@link Meter.createObservableGauge}
|
|
5242
|
+
*/
|
|
5243
|
+
NoopMeter.prototype.createObservableGauge = function (_name, _options) {
|
|
5244
|
+
return NOOP_OBSERVABLE_GAUGE_METRIC;
|
|
5245
|
+
};
|
|
5246
|
+
/**
|
|
5247
|
+
* @see {@link Meter.createObservableCounter}
|
|
5248
|
+
*/
|
|
5249
|
+
NoopMeter.prototype.createObservableCounter = function (_name, _options) {
|
|
5250
|
+
return NOOP_OBSERVABLE_COUNTER_METRIC;
|
|
5251
|
+
};
|
|
5252
|
+
/**
|
|
5253
|
+
* @see {@link Meter.createObservableUpDownCounter}
|
|
5254
|
+
*/
|
|
5255
|
+
NoopMeter.prototype.createObservableUpDownCounter = function (_name, _options) {
|
|
5256
|
+
return NOOP_OBSERVABLE_UP_DOWN_COUNTER_METRIC;
|
|
5257
|
+
};
|
|
5258
|
+
/**
|
|
5259
|
+
* @see {@link Meter.addBatchObservableCallback}
|
|
5260
|
+
*/
|
|
5261
|
+
NoopMeter.prototype.addBatchObservableCallback = function (_callback, _observables) { };
|
|
5262
|
+
/**
|
|
5263
|
+
* @see {@link Meter.removeBatchObservableCallback}
|
|
5264
|
+
*/
|
|
5265
|
+
NoopMeter.prototype.removeBatchObservableCallback = function (_callback) { };
|
|
5266
|
+
return NoopMeter;
|
|
5267
|
+
}());
|
|
5268
|
+
var NoopMetric = /** @class */ (function () {
|
|
5269
|
+
function NoopMetric() {
|
|
5270
|
+
}
|
|
5271
|
+
return NoopMetric;
|
|
5272
|
+
}());
|
|
5273
|
+
var NoopCounterMetric = /** @class */ (function (_super) {
|
|
5274
|
+
__extends$3(NoopCounterMetric, _super);
|
|
5275
|
+
function NoopCounterMetric() {
|
|
5276
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
5277
|
+
}
|
|
5278
|
+
NoopCounterMetric.prototype.add = function (_value, _attributes) { };
|
|
5279
|
+
return NoopCounterMetric;
|
|
5280
|
+
}(NoopMetric));
|
|
5281
|
+
var NoopUpDownCounterMetric = /** @class */ (function (_super) {
|
|
5282
|
+
__extends$3(NoopUpDownCounterMetric, _super);
|
|
5283
|
+
function NoopUpDownCounterMetric() {
|
|
5284
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
5285
|
+
}
|
|
5286
|
+
NoopUpDownCounterMetric.prototype.add = function (_value, _attributes) { };
|
|
5287
|
+
return NoopUpDownCounterMetric;
|
|
5288
|
+
}(NoopMetric));
|
|
5289
|
+
var NoopGaugeMetric = /** @class */ (function (_super) {
|
|
5290
|
+
__extends$3(NoopGaugeMetric, _super);
|
|
5291
|
+
function NoopGaugeMetric() {
|
|
5292
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
5293
|
+
}
|
|
5294
|
+
NoopGaugeMetric.prototype.record = function (_value, _attributes) { };
|
|
5295
|
+
return NoopGaugeMetric;
|
|
5296
|
+
}(NoopMetric));
|
|
5297
|
+
var NoopHistogramMetric = /** @class */ (function (_super) {
|
|
5298
|
+
__extends$3(NoopHistogramMetric, _super);
|
|
5299
|
+
function NoopHistogramMetric() {
|
|
5300
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
5301
|
+
}
|
|
5302
|
+
NoopHistogramMetric.prototype.record = function (_value, _attributes) { };
|
|
5303
|
+
return NoopHistogramMetric;
|
|
5304
|
+
}(NoopMetric));
|
|
5305
|
+
var NoopObservableMetric = /** @class */ (function () {
|
|
5306
|
+
function NoopObservableMetric() {
|
|
5307
|
+
}
|
|
5308
|
+
NoopObservableMetric.prototype.addCallback = function (_callback) { };
|
|
5309
|
+
NoopObservableMetric.prototype.removeCallback = function (_callback) { };
|
|
5310
|
+
return NoopObservableMetric;
|
|
5311
|
+
}());
|
|
5312
|
+
var NoopObservableCounterMetric = /** @class */ (function (_super) {
|
|
5313
|
+
__extends$3(NoopObservableCounterMetric, _super);
|
|
5314
|
+
function NoopObservableCounterMetric() {
|
|
5315
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
5316
|
+
}
|
|
5317
|
+
return NoopObservableCounterMetric;
|
|
5318
|
+
}(NoopObservableMetric));
|
|
5319
|
+
var NoopObservableGaugeMetric = /** @class */ (function (_super) {
|
|
5320
|
+
__extends$3(NoopObservableGaugeMetric, _super);
|
|
5321
|
+
function NoopObservableGaugeMetric() {
|
|
5322
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
5323
|
+
}
|
|
5324
|
+
return NoopObservableGaugeMetric;
|
|
5325
|
+
}(NoopObservableMetric));
|
|
5326
|
+
var NoopObservableUpDownCounterMetric = /** @class */ (function (_super) {
|
|
5327
|
+
__extends$3(NoopObservableUpDownCounterMetric, _super);
|
|
5328
|
+
function NoopObservableUpDownCounterMetric() {
|
|
5329
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
5330
|
+
}
|
|
5331
|
+
return NoopObservableUpDownCounterMetric;
|
|
5332
|
+
}(NoopObservableMetric));
|
|
5333
|
+
var NOOP_METER = new NoopMeter();
|
|
5334
|
+
// Synchronous instruments
|
|
5335
|
+
var NOOP_COUNTER_METRIC = new NoopCounterMetric();
|
|
5336
|
+
var NOOP_GAUGE_METRIC = new NoopGaugeMetric();
|
|
5337
|
+
var NOOP_HISTOGRAM_METRIC = new NoopHistogramMetric();
|
|
5338
|
+
var NOOP_UP_DOWN_COUNTER_METRIC = new NoopUpDownCounterMetric();
|
|
5339
|
+
// Asynchronous instruments
|
|
5340
|
+
var NOOP_OBSERVABLE_COUNTER_METRIC = new NoopObservableCounterMetric();
|
|
5341
|
+
var NOOP_OBSERVABLE_GAUGE_METRIC = new NoopObservableGaugeMetric();
|
|
5342
|
+
var NOOP_OBSERVABLE_UP_DOWN_COUNTER_METRIC = new NoopObservableUpDownCounterMetric();
|
|
5343
|
+
|
|
4199
5344
|
/*
|
|
4200
5345
|
* Copyright The OpenTelemetry Authors
|
|
4201
5346
|
*
|
|
@@ -4339,7 +5484,7 @@ var __spreadArray$3 = (undefined && undefined.__spreadArray) || function (to, fr
|
|
|
4339
5484
|
}
|
|
4340
5485
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
4341
5486
|
};
|
|
4342
|
-
var API_NAME$
|
|
5487
|
+
var API_NAME$3 = 'context';
|
|
4343
5488
|
var NOOP_CONTEXT_MANAGER = new NoopContextManager();
|
|
4344
5489
|
/**
|
|
4345
5490
|
* Singleton object which represents the entry point to the OpenTelemetry Context API
|
|
@@ -4361,7 +5506,7 @@ var ContextAPI = /** @class */ (function () {
|
|
|
4361
5506
|
* @returns true if the context manager was successfully registered, else false
|
|
4362
5507
|
*/
|
|
4363
5508
|
ContextAPI.prototype.setGlobalContextManager = function (contextManager) {
|
|
4364
|
-
return registerGlobal(API_NAME$
|
|
5509
|
+
return registerGlobal(API_NAME$3, contextManager, DiagAPI.instance());
|
|
4365
5510
|
};
|
|
4366
5511
|
/**
|
|
4367
5512
|
* Get the currently active context
|
|
@@ -4395,12 +5540,12 @@ var ContextAPI = /** @class */ (function () {
|
|
|
4395
5540
|
return this._getContextManager().bind(context, target);
|
|
4396
5541
|
};
|
|
4397
5542
|
ContextAPI.prototype._getContextManager = function () {
|
|
4398
|
-
return getGlobal(API_NAME$
|
|
5543
|
+
return getGlobal(API_NAME$3) || NOOP_CONTEXT_MANAGER;
|
|
4399
5544
|
};
|
|
4400
5545
|
/** Disable and remove the global context manager */
|
|
4401
5546
|
ContextAPI.prototype.disable = function () {
|
|
4402
5547
|
this._getContextManager().disable();
|
|
4403
|
-
unregisterGlobal(API_NAME$
|
|
5548
|
+
unregisterGlobal(API_NAME$3, DiagAPI.instance());
|
|
4404
5549
|
};
|
|
4405
5550
|
return ContextAPI;
|
|
4406
5551
|
}());
|
|
@@ -4977,6 +6122,111 @@ var context = ContextAPI.getInstance();
|
|
|
4977
6122
|
*/
|
|
4978
6123
|
var diag = DiagAPI.instance();
|
|
4979
6124
|
|
|
6125
|
+
/*
|
|
6126
|
+
* Copyright The OpenTelemetry Authors
|
|
6127
|
+
*
|
|
6128
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6129
|
+
* you may not use this file except in compliance with the License.
|
|
6130
|
+
* You may obtain a copy of the License at
|
|
6131
|
+
*
|
|
6132
|
+
* https://www.apache.org/licenses/LICENSE-2.0
|
|
6133
|
+
*
|
|
6134
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
6135
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
6136
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
6137
|
+
* See the License for the specific language governing permissions and
|
|
6138
|
+
* limitations under the License.
|
|
6139
|
+
*/
|
|
6140
|
+
/**
|
|
6141
|
+
* An implementation of the {@link MeterProvider} which returns an impotent Meter
|
|
6142
|
+
* for all calls to `getMeter`
|
|
6143
|
+
*/
|
|
6144
|
+
var NoopMeterProvider = /** @class */ (function () {
|
|
6145
|
+
function NoopMeterProvider() {
|
|
6146
|
+
}
|
|
6147
|
+
NoopMeterProvider.prototype.getMeter = function (_name, _version, _options) {
|
|
6148
|
+
return NOOP_METER;
|
|
6149
|
+
};
|
|
6150
|
+
return NoopMeterProvider;
|
|
6151
|
+
}());
|
|
6152
|
+
var NOOP_METER_PROVIDER = new NoopMeterProvider();
|
|
6153
|
+
|
|
6154
|
+
/*
|
|
6155
|
+
* Copyright The OpenTelemetry Authors
|
|
6156
|
+
*
|
|
6157
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6158
|
+
* you may not use this file except in compliance with the License.
|
|
6159
|
+
* You may obtain a copy of the License at
|
|
6160
|
+
*
|
|
6161
|
+
* https://www.apache.org/licenses/LICENSE-2.0
|
|
6162
|
+
*
|
|
6163
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
6164
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
6165
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
6166
|
+
* See the License for the specific language governing permissions and
|
|
6167
|
+
* limitations under the License.
|
|
6168
|
+
*/
|
|
6169
|
+
var API_NAME$2 = 'metrics';
|
|
6170
|
+
/**
|
|
6171
|
+
* Singleton object which represents the entry point to the OpenTelemetry Metrics API
|
|
6172
|
+
*/
|
|
6173
|
+
var MetricsAPI = /** @class */ (function () {
|
|
6174
|
+
/** Empty private constructor prevents end users from constructing a new instance of the API */
|
|
6175
|
+
function MetricsAPI() {
|
|
6176
|
+
}
|
|
6177
|
+
/** Get the singleton instance of the Metrics API */
|
|
6178
|
+
MetricsAPI.getInstance = function () {
|
|
6179
|
+
if (!this._instance) {
|
|
6180
|
+
this._instance = new MetricsAPI();
|
|
6181
|
+
}
|
|
6182
|
+
return this._instance;
|
|
6183
|
+
};
|
|
6184
|
+
/**
|
|
6185
|
+
* Set the current global meter provider.
|
|
6186
|
+
* Returns true if the meter provider was successfully registered, else false.
|
|
6187
|
+
*/
|
|
6188
|
+
MetricsAPI.prototype.setGlobalMeterProvider = function (provider) {
|
|
6189
|
+
return registerGlobal(API_NAME$2, provider, DiagAPI.instance());
|
|
6190
|
+
};
|
|
6191
|
+
/**
|
|
6192
|
+
* Returns the global meter provider.
|
|
6193
|
+
*/
|
|
6194
|
+
MetricsAPI.prototype.getMeterProvider = function () {
|
|
6195
|
+
return getGlobal(API_NAME$2) || NOOP_METER_PROVIDER;
|
|
6196
|
+
};
|
|
6197
|
+
/**
|
|
6198
|
+
* Returns a meter from the global meter provider.
|
|
6199
|
+
*/
|
|
6200
|
+
MetricsAPI.prototype.getMeter = function (name, version, options) {
|
|
6201
|
+
return this.getMeterProvider().getMeter(name, version, options);
|
|
6202
|
+
};
|
|
6203
|
+
/** Remove the global meter provider */
|
|
6204
|
+
MetricsAPI.prototype.disable = function () {
|
|
6205
|
+
unregisterGlobal(API_NAME$2, DiagAPI.instance());
|
|
6206
|
+
};
|
|
6207
|
+
return MetricsAPI;
|
|
6208
|
+
}());
|
|
6209
|
+
|
|
6210
|
+
/*
|
|
6211
|
+
* Copyright The OpenTelemetry Authors
|
|
6212
|
+
*
|
|
6213
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6214
|
+
* you may not use this file except in compliance with the License.
|
|
6215
|
+
* You may obtain a copy of the License at
|
|
6216
|
+
*
|
|
6217
|
+
* https://www.apache.org/licenses/LICENSE-2.0
|
|
6218
|
+
*
|
|
6219
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
6220
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
6221
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
6222
|
+
* See the License for the specific language governing permissions and
|
|
6223
|
+
* limitations under the License.
|
|
6224
|
+
*/
|
|
6225
|
+
// Split module-level variable definition into separate files to allow
|
|
6226
|
+
// tree-shaking on each api instance.
|
|
6227
|
+
/** Entrypoint for metrics API */
|
|
6228
|
+
MetricsAPI.getInstance();
|
|
6229
|
+
|
|
4980
6230
|
/*
|
|
4981
6231
|
* Copyright The OpenTelemetry Authors
|
|
4982
6232
|
*
|
|
@@ -15941,4 +17191,4 @@ function createDelegator(config) {
|
|
|
15941
17191
|
return new A2ATaskDelegator(config);
|
|
15942
17192
|
}
|
|
15943
17193
|
|
|
15944
|
-
export { A2AClient, A2AError, A2AServer, A2ATaskDelegator, SekuireAgent as Agent, AgentIdentity, AnthropicProvider, Beacon, ComplianceError, ComplianceMonitor, ContentPolicyError, CryptoError, DEFAULT_API_URL, FileAccessError, GoogleProvider, InMemoryStorage, NetworkComplianceError, NetworkError, OllamaProvider, OpenAIProvider, PolicyClient, PolicyEnforcer, PolicyViolationError, PostgresStorage, ProtocolError, RedisStorage, SekuireAgent$1 as SekuireAgent, SekuireAgentBuilder, SekuireClient, SekuireCrypto, SekuireError, SekuireLogger, SekuireRegistryClient, SekuireSDK, SekuireServer, SekuireSpanExporter, TaskWorker, ToolPatternParser, ToolRegistry, ToolUsageError, builtInTools, calculateSekuireId, createAgent, createBeacon, createDefaultToolRegistry, createDelegationTool, createDelegator, createDiscoveryTool, createLLMProvider, createMemoryStorage, createRegistryClient, createSekuireClient, createSekuireExpressMiddleware, createSekuireFastifyPlugin, createWorker, detectDeploymentUrl, generateKeyPair, getAgent, getAgentConfig, getAgents, getTools$1 as getLegacyTools, getSystemPrompt, getTools, getTracer, initTelemetry, llm, loadConfig, loadSystemPrompt, loadTools, shutdownTelemetry, tool, tools };
|
|
17194
|
+
export { A2AClient, A2AError, A2AServer, A2ATaskDelegator, SekuireAgent as Agent, AgentIdentity, AnthropicProvider, BaseMemoryStorage, Beacon, CONVEX_FUNCTIONS_TEMPLATE, CONVEX_SCHEMA_TEMPLATE, CloudflareD1Storage, CloudflareKVStorage, ComplianceError, ComplianceMonitor, ContentPolicyError, ConvexStorage, CryptoError, DEFAULT_API_URL, DynamoDBStorage, FileAccessError, GoogleProvider, InMemoryStorage, NetworkComplianceError, NetworkError, OllamaProvider, OpenAIProvider, PolicyClient, PolicyEnforcer, PolicyViolationError, PostgresStorage, ProtocolError, RedisStorage, SQLiteStorage, SekuireAgent$1 as SekuireAgent, SekuireAgentBuilder, SekuireClient, SekuireCrypto, SekuireError, SekuireLogger, SekuireRegistryClient, SekuireSDK, SekuireServer, SekuireSpanExporter, TaskWorker, ToolPatternParser, ToolRegistry, ToolUsageError, TursoStorage, UpstashStorage, builtInTools, calculateSekuireId, createAgent, createBeacon, createDefaultToolRegistry, createDelegationTool, createDelegator, createDiscoveryTool, createLLMProvider, createMemoryStorage, createRegistryClient, createSekuireClient, createSekuireExpressMiddleware, createSekuireFastifyPlugin, createWorker, detectDeploymentUrl, generateKeyPair, getAgent, getAgentConfig, getAgents, getTools$1 as getLegacyTools, getStorageInfo, getSystemPrompt, getTools, getTracer, hasStorage, initTelemetry, listStorageTypes, llm, loadConfig, loadSystemPrompt, loadTools, registerStorage, shutdownTelemetry, tool, tools };
|