@agentuity/runtime 2.0.11 → 3.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +37 -65
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +59 -61
- package/dist/index.js.map +1 -1
- package/package.json +9 -38
- package/src/index.ts +58 -259
- package/AGENTS.md +0 -116
- package/dist/_config.d.ts +0 -100
- package/dist/_config.d.ts.map +0 -1
- package/dist/_config.js +0 -147
- package/dist/_config.js.map +0 -1
- package/dist/_context.d.ts +0 -80
- package/dist/_context.d.ts.map +0 -1
- package/dist/_context.js +0 -160
- package/dist/_context.js.map +0 -1
- package/dist/_events.d.ts +0 -64
- package/dist/_events.d.ts.map +0 -1
- package/dist/_events.js +0 -92
- package/dist/_events.js.map +0 -1
- package/dist/_globals.d.ts +0 -58
- package/dist/_globals.d.ts.map +0 -1
- package/dist/_globals.js +0 -71
- package/dist/_globals.js.map +0 -1
- package/dist/_idle.d.ts +0 -7
- package/dist/_idle.d.ts.map +0 -1
- package/dist/_idle.js +0 -10
- package/dist/_idle.js.map +0 -1
- package/dist/_metadata.d.ts +0 -117
- package/dist/_metadata.d.ts.map +0 -1
- package/dist/_metadata.js +0 -268
- package/dist/_metadata.js.map +0 -1
- package/dist/_process-protection.d.ts +0 -27
- package/dist/_process-protection.d.ts.map +0 -1
- package/dist/_process-protection.js +0 -56
- package/dist/_process-protection.js.map +0 -1
- package/dist/_server.d.ts +0 -50
- package/dist/_server.d.ts.map +0 -1
- package/dist/_server.js +0 -89
- package/dist/_server.js.map +0 -1
- package/dist/_services.d.ts +0 -25
- package/dist/_services.d.ts.map +0 -1
- package/dist/_services.js +0 -286
- package/dist/_services.js.map +0 -1
- package/dist/_standalone.d.ts +0 -212
- package/dist/_standalone.d.ts.map +0 -1
- package/dist/_standalone.js +0 -556
- package/dist/_standalone.js.map +0 -1
- package/dist/_tokens.d.ts +0 -12
- package/dist/_tokens.d.ts.map +0 -1
- package/dist/_tokens.js +0 -97
- package/dist/_tokens.js.map +0 -1
- package/dist/_util.d.ts +0 -16
- package/dist/_util.d.ts.map +0 -1
- package/dist/_util.js +0 -54
- package/dist/_util.js.map +0 -1
- package/dist/_validation.d.ts +0 -89
- package/dist/_validation.d.ts.map +0 -1
- package/dist/_validation.js +0 -29
- package/dist/_validation.js.map +0 -1
- package/dist/_waituntil.d.ts +0 -32
- package/dist/_waituntil.d.ts.map +0 -1
- package/dist/_waituntil.js +0 -156
- package/dist/_waituntil.js.map +0 -1
- package/dist/agent.d.ts +0 -1262
- package/dist/agent.d.ts.map +0 -1
- package/dist/agent.js +0 -981
- package/dist/agent.js.map +0 -1
- package/dist/app.d.ts +0 -514
- package/dist/app.d.ts.map +0 -1
- package/dist/app.js +0 -228
- package/dist/app.js.map +0 -1
- package/dist/bootstrap.d.ts +0 -44
- package/dist/bootstrap.d.ts.map +0 -1
- package/dist/bootstrap.js +0 -259
- package/dist/bootstrap.js.map +0 -1
- package/dist/bun-s3-patch.d.ts +0 -37
- package/dist/bun-s3-patch.d.ts.map +0 -1
- package/dist/bun-s3-patch.js +0 -142
- package/dist/bun-s3-patch.js.map +0 -1
- package/dist/cors.d.ts +0 -42
- package/dist/cors.d.ts.map +0 -1
- package/dist/cors.js +0 -117
- package/dist/cors.js.map +0 -1
- package/dist/dev-patches/aisdk.d.ts +0 -17
- package/dist/dev-patches/aisdk.d.ts.map +0 -1
- package/dist/dev-patches/aisdk.js +0 -160
- package/dist/dev-patches/aisdk.js.map +0 -1
- package/dist/dev-patches/gateway.d.ts +0 -16
- package/dist/dev-patches/gateway.d.ts.map +0 -1
- package/dist/dev-patches/gateway.js +0 -54
- package/dist/dev-patches/gateway.js.map +0 -1
- package/dist/dev-patches/index.d.ts +0 -21
- package/dist/dev-patches/index.d.ts.map +0 -1
- package/dist/dev-patches/index.js +0 -33
- package/dist/dev-patches/index.js.map +0 -1
- package/dist/dev-patches/otel-llm.d.ts +0 -12
- package/dist/dev-patches/otel-llm.d.ts.map +0 -1
- package/dist/dev-patches/otel-llm.js +0 -352
- package/dist/dev-patches/otel-llm.js.map +0 -1
- package/dist/devmode.d.ts +0 -3
- package/dist/devmode.d.ts.map +0 -1
- package/dist/devmode.js +0 -167
- package/dist/devmode.js.map +0 -1
- package/dist/eval.d.ts +0 -91
- package/dist/eval.d.ts.map +0 -1
- package/dist/eval.js +0 -16
- package/dist/eval.js.map +0 -1
- package/dist/handlers/_route-meta.d.ts +0 -22
- package/dist/handlers/_route-meta.d.ts.map +0 -1
- package/dist/handlers/_route-meta.js +0 -25
- package/dist/handlers/_route-meta.js.map +0 -1
- package/dist/handlers/cron.d.ts +0 -73
- package/dist/handlers/cron.d.ts.map +0 -1
- package/dist/handlers/cron.js +0 -43
- package/dist/handlers/cron.js.map +0 -1
- package/dist/handlers/index.d.ts +0 -6
- package/dist/handlers/index.d.ts.map +0 -1
- package/dist/handlers/index.js +0 -6
- package/dist/handlers/index.js.map +0 -1
- package/dist/handlers/sse.d.ts +0 -163
- package/dist/handlers/sse.d.ts.map +0 -1
- package/dist/handlers/sse.js +0 -175
- package/dist/handlers/sse.js.map +0 -1
- package/dist/handlers/stream.d.ts +0 -52
- package/dist/handlers/stream.d.ts.map +0 -1
- package/dist/handlers/stream.js +0 -108
- package/dist/handlers/stream.js.map +0 -1
- package/dist/handlers/webrtc.d.ts +0 -49
- package/dist/handlers/webrtc.d.ts.map +0 -1
- package/dist/handlers/webrtc.js +0 -109
- package/dist/handlers/webrtc.js.map +0 -1
- package/dist/handlers/websocket.d.ts +0 -88
- package/dist/handlers/websocket.d.ts.map +0 -1
- package/dist/handlers/websocket.js +0 -161
- package/dist/handlers/websocket.js.map +0 -1
- package/dist/logger/console.d.ts +0 -70
- package/dist/logger/console.d.ts.map +0 -1
- package/dist/logger/console.js +0 -278
- package/dist/logger/console.js.map +0 -1
- package/dist/logger/index.d.ts +0 -3
- package/dist/logger/index.d.ts.map +0 -1
- package/dist/logger/index.js +0 -3
- package/dist/logger/index.js.map +0 -1
- package/dist/logger/internal.d.ts +0 -79
- package/dist/logger/internal.d.ts.map +0 -1
- package/dist/logger/internal.js +0 -133
- package/dist/logger/internal.js.map +0 -1
- package/dist/logger/logger.d.ts +0 -41
- package/dist/logger/logger.d.ts.map +0 -1
- package/dist/logger/logger.js +0 -2
- package/dist/logger/logger.js.map +0 -1
- package/dist/logger/user.d.ts +0 -8
- package/dist/logger/user.d.ts.map +0 -1
- package/dist/logger/user.js +0 -7
- package/dist/logger/user.js.map +0 -1
- package/dist/logger/util.d.ts +0 -11
- package/dist/logger/util.d.ts.map +0 -1
- package/dist/logger/util.js +0 -77
- package/dist/logger/util.js.map +0 -1
- package/dist/middleware.d.ts +0 -105
- package/dist/middleware.d.ts.map +0 -1
- package/dist/middleware.js +0 -763
- package/dist/middleware.js.map +0 -1
- package/dist/otel/config.d.ts +0 -19
- package/dist/otel/config.d.ts.map +0 -1
- package/dist/otel/config.js +0 -26
- package/dist/otel/config.js.map +0 -1
- package/dist/otel/console.d.ts +0 -33
- package/dist/otel/console.d.ts.map +0 -1
- package/dist/otel/console.js +0 -86
- package/dist/otel/console.js.map +0 -1
- package/dist/otel/exporters/index.d.ts +0 -4
- package/dist/otel/exporters/index.d.ts.map +0 -1
- package/dist/otel/exporters/index.js +0 -4
- package/dist/otel/exporters/index.js.map +0 -1
- package/dist/otel/exporters/jsonl-log-exporter.d.ts +0 -36
- package/dist/otel/exporters/jsonl-log-exporter.d.ts.map +0 -1
- package/dist/otel/exporters/jsonl-log-exporter.js +0 -103
- package/dist/otel/exporters/jsonl-log-exporter.js.map +0 -1
- package/dist/otel/exporters/jsonl-metric-exporter.d.ts +0 -40
- package/dist/otel/exporters/jsonl-metric-exporter.d.ts.map +0 -1
- package/dist/otel/exporters/jsonl-metric-exporter.js +0 -104
- package/dist/otel/exporters/jsonl-metric-exporter.js.map +0 -1
- package/dist/otel/exporters/jsonl-trace-exporter.d.ts +0 -36
- package/dist/otel/exporters/jsonl-trace-exporter.d.ts.map +0 -1
- package/dist/otel/exporters/jsonl-trace-exporter.js +0 -111
- package/dist/otel/exporters/jsonl-trace-exporter.js.map +0 -1
- package/dist/otel/fetch.d.ts +0 -12
- package/dist/otel/fetch.d.ts.map +0 -1
- package/dist/otel/fetch.js +0 -82
- package/dist/otel/fetch.js.map +0 -1
- package/dist/otel/http.d.ts +0 -16
- package/dist/otel/http.d.ts.map +0 -1
- package/dist/otel/http.js +0 -44
- package/dist/otel/http.js.map +0 -1
- package/dist/otel/logger.d.ts +0 -37
- package/dist/otel/logger.d.ts.map +0 -1
- package/dist/otel/logger.js +0 -265
- package/dist/otel/logger.js.map +0 -1
- package/dist/otel/otel.d.ts +0 -68
- package/dist/otel/otel.d.ts.map +0 -1
- package/dist/otel/otel.js +0 -245
- package/dist/otel/otel.js.map +0 -1
- package/dist/otel/tracestate.d.ts +0 -44
- package/dist/otel/tracestate.d.ts.map +0 -1
- package/dist/otel/tracestate.js +0 -84
- package/dist/otel/tracestate.js.map +0 -1
- package/dist/router.d.ts +0 -66
- package/dist/router.d.ts.map +0 -1
- package/dist/router.js +0 -44
- package/dist/router.js.map +0 -1
- package/dist/services/evalrun/composite.d.ts +0 -21
- package/dist/services/evalrun/composite.d.ts.map +0 -1
- package/dist/services/evalrun/composite.js +0 -26
- package/dist/services/evalrun/composite.js.map +0 -1
- package/dist/services/evalrun/http.d.ts +0 -24
- package/dist/services/evalrun/http.d.ts.map +0 -1
- package/dist/services/evalrun/http.js +0 -115
- package/dist/services/evalrun/http.js.map +0 -1
- package/dist/services/evalrun/index.d.ts +0 -5
- package/dist/services/evalrun/index.d.ts.map +0 -1
- package/dist/services/evalrun/index.js +0 -5
- package/dist/services/evalrun/index.js.map +0 -1
- package/dist/services/evalrun/json.d.ts +0 -21
- package/dist/services/evalrun/json.d.ts.map +0 -1
- package/dist/services/evalrun/json.js +0 -38
- package/dist/services/evalrun/json.js.map +0 -1
- package/dist/services/evalrun/local.d.ts +0 -19
- package/dist/services/evalrun/local.d.ts.map +0 -1
- package/dist/services/evalrun/local.js +0 -22
- package/dist/services/evalrun/local.js.map +0 -1
- package/dist/services/local/_db.d.ts +0 -4
- package/dist/services/local/_db.d.ts.map +0 -1
- package/dist/services/local/_db.js +0 -281
- package/dist/services/local/_db.js.map +0 -1
- package/dist/services/local/_router.d.ts +0 -3
- package/dist/services/local/_router.d.ts.map +0 -1
- package/dist/services/local/_router.js +0 -28
- package/dist/services/local/_router.js.map +0 -1
- package/dist/services/local/_util.d.ts +0 -18
- package/dist/services/local/_util.d.ts.map +0 -1
- package/dist/services/local/_util.js +0 -44
- package/dist/services/local/_util.js.map +0 -1
- package/dist/services/local/email.d.ts +0 -24
- package/dist/services/local/email.d.ts.map +0 -1
- package/dist/services/local/email.js +0 -58
- package/dist/services/local/email.js.map +0 -1
- package/dist/services/local/index.d.ts +0 -10
- package/dist/services/local/index.d.ts.map +0 -1
- package/dist/services/local/index.js +0 -10
- package/dist/services/local/index.js.map +0 -1
- package/dist/services/local/keyvalue.d.ts +0 -17
- package/dist/services/local/keyvalue.d.ts.map +0 -1
- package/dist/services/local/keyvalue.js +0 -133
- package/dist/services/local/keyvalue.js.map +0 -1
- package/dist/services/local/queue.d.ts +0 -10
- package/dist/services/local/queue.d.ts.map +0 -1
- package/dist/services/local/queue.js +0 -96
- package/dist/services/local/queue.js.map +0 -1
- package/dist/services/local/stream.d.ts +0 -12
- package/dist/services/local/stream.d.ts.map +0 -1
- package/dist/services/local/stream.js +0 -266
- package/dist/services/local/stream.js.map +0 -1
- package/dist/services/local/task.d.ts +0 -55
- package/dist/services/local/task.d.ts.map +0 -1
- package/dist/services/local/task.js +0 -1248
- package/dist/services/local/task.js.map +0 -1
- package/dist/services/local/vector.d.ts +0 -17
- package/dist/services/local/vector.d.ts.map +0 -1
- package/dist/services/local/vector.js +0 -303
- package/dist/services/local/vector.js.map +0 -1
- package/dist/services/sandbox/http.d.ts +0 -23
- package/dist/services/sandbox/http.d.ts.map +0 -1
- package/dist/services/sandbox/http.js +0 -327
- package/dist/services/sandbox/http.js.map +0 -1
- package/dist/services/sandbox/index.d.ts +0 -2
- package/dist/services/sandbox/index.d.ts.map +0 -1
- package/dist/services/sandbox/index.js +0 -2
- package/dist/services/sandbox/index.js.map +0 -1
- package/dist/services/session/composite.d.ts +0 -21
- package/dist/services/session/composite.d.ts.map +0 -1
- package/dist/services/session/composite.js +0 -26
- package/dist/services/session/composite.js.map +0 -1
- package/dist/services/session/http.d.ts +0 -34
- package/dist/services/session/http.d.ts.map +0 -1
- package/dist/services/session/http.js +0 -124
- package/dist/services/session/http.js.map +0 -1
- package/dist/services/session/index.d.ts +0 -5
- package/dist/services/session/index.d.ts.map +0 -1
- package/dist/services/session/index.js +0 -5
- package/dist/services/session/index.js.map +0 -1
- package/dist/services/session/json.d.ts +0 -22
- package/dist/services/session/json.d.ts.map +0 -1
- package/dist/services/session/json.js +0 -35
- package/dist/services/session/json.js.map +0 -1
- package/dist/services/session/local.d.ts +0 -19
- package/dist/services/session/local.d.ts.map +0 -1
- package/dist/services/session/local.js +0 -23
- package/dist/services/session/local.js.map +0 -1
- package/dist/services/thread/local.d.ts +0 -20
- package/dist/services/thread/local.d.ts.map +0 -1
- package/dist/services/thread/local.js +0 -158
- package/dist/services/thread/local.js.map +0 -1
- package/dist/session.d.ts +0 -734
- package/dist/session.d.ts.map +0 -1
- package/dist/session.js +0 -1140
- package/dist/session.js.map +0 -1
- package/dist/signature.d.ts +0 -22
- package/dist/signature.d.ts.map +0 -1
- package/dist/signature.js +0 -63
- package/dist/signature.js.map +0 -1
- package/dist/validator.d.ts +0 -142
- package/dist/validator.d.ts.map +0 -1
- package/dist/validator.js +0 -149
- package/dist/validator.js.map +0 -1
- package/dist/version-check.d.ts +0 -20
- package/dist/version-check.d.ts.map +0 -1
- package/dist/version-check.js +0 -157
- package/dist/version-check.js.map +0 -1
- package/dist/web.d.ts +0 -8
- package/dist/web.d.ts.map +0 -1
- package/dist/web.js +0 -67
- package/dist/web.js.map +0 -1
- package/dist/webrtc-signaling.d.ts +0 -80
- package/dist/webrtc-signaling.d.ts.map +0 -1
- package/dist/webrtc-signaling.js +0 -237
- package/dist/webrtc-signaling.js.map +0 -1
- package/dist/workbench.d.ts +0 -17
- package/dist/workbench.d.ts.map +0 -1
- package/dist/workbench.js +0 -605
- package/dist/workbench.js.map +0 -1
- package/src/_config.ts +0 -163
- package/src/_context.ts +0 -240
- package/src/_events.ts +0 -142
- package/src/_globals.ts +0 -92
- package/src/_idle.ts +0 -10
- package/src/_metadata.ts +0 -407
- package/src/_process-protection.ts +0 -71
- package/src/_server.ts +0 -109
- package/src/_services.ts +0 -379
- package/src/_standalone.ts +0 -710
- package/src/_tokens.ts +0 -114
- package/src/_util.ts +0 -62
- package/src/_validation.ts +0 -119
- package/src/_waituntil.ts +0 -188
- package/src/agent.ts +0 -2739
- package/src/app.ts +0 -769
- package/src/bootstrap.ts +0 -321
- package/src/bun-s3-patch.ts +0 -224
- package/src/cors.ts +0 -137
- package/src/dev-patches/aisdk.ts +0 -169
- package/src/dev-patches/gateway.ts +0 -68
- package/src/dev-patches/index.ts +0 -37
- package/src/dev-patches/otel-llm.ts +0 -405
- package/src/devmode.ts +0 -171
- package/src/eval.ts +0 -109
- package/src/globals.d.ts +0 -28
- package/src/handlers/_route-meta.ts +0 -33
- package/src/handlers/cron.ts +0 -141
- package/src/handlers/index.ts +0 -18
- package/src/handlers/sse.ts +0 -358
- package/src/handlers/stream.ts +0 -121
- package/src/handlers/webrtc.ts +0 -125
- package/src/handlers/websocket.ts +0 -203
- package/src/logger/console.ts +0 -323
- package/src/logger/index.ts +0 -2
- package/src/logger/internal.ts +0 -165
- package/src/logger/logger.ts +0 -44
- package/src/logger/user.ts +0 -15
- package/src/logger/util.ts +0 -80
- package/src/middleware.ts +0 -1095
- package/src/otel/config.ts +0 -47
- package/src/otel/console.ts +0 -91
- package/src/otel/exporters/README.md +0 -217
- package/src/otel/exporters/index.ts +0 -3
- package/src/otel/exporters/jsonl-log-exporter.ts +0 -113
- package/src/otel/exporters/jsonl-metric-exporter.ts +0 -120
- package/src/otel/exporters/jsonl-trace-exporter.ts +0 -121
- package/src/otel/fetch.ts +0 -105
- package/src/otel/http.ts +0 -53
- package/src/otel/logger.ts +0 -293
- package/src/otel/otel.ts +0 -354
- package/src/otel/tracestate.ts +0 -108
- package/src/router.ts +0 -75
- package/src/services/evalrun/composite.ts +0 -34
- package/src/services/evalrun/http.ts +0 -167
- package/src/services/evalrun/index.ts +0 -4
- package/src/services/evalrun/json.ts +0 -46
- package/src/services/evalrun/local.ts +0 -28
- package/src/services/local/README.md +0 -1576
- package/src/services/local/_db.ts +0 -353
- package/src/services/local/_router.ts +0 -40
- package/src/services/local/_util.ts +0 -55
- package/src/services/local/email.ts +0 -91
- package/src/services/local/index.ts +0 -9
- package/src/services/local/keyvalue.ts +0 -174
- package/src/services/local/queue.ts +0 -145
- package/src/services/local/stream.ts +0 -358
- package/src/services/local/task.ts +0 -1711
- package/src/services/local/vector.ts +0 -438
- package/src/services/sandbox/http.ts +0 -522
- package/src/services/sandbox/index.ts +0 -1
- package/src/services/session/composite.ts +0 -33
- package/src/services/session/http.ts +0 -167
- package/src/services/session/index.ts +0 -4
- package/src/services/session/json.ts +0 -42
- package/src/services/session/local.ts +0 -33
- package/src/services/thread/local.ts +0 -199
- package/src/session.ts +0 -1960
- package/src/signature.ts +0 -82
- package/src/validator.ts +0 -283
- package/src/version-check.ts +0 -184
- package/src/web.ts +0 -76
- package/src/webrtc-signaling.ts +0 -288
- package/src/workbench.ts +0 -725
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import type { Database } from 'bun:sqlite';
|
|
2
|
-
import type {
|
|
3
|
-
KeyValueStorage,
|
|
4
|
-
DataResult,
|
|
5
|
-
DataResultNotFound,
|
|
6
|
-
KeyValueStorageSetParams,
|
|
7
|
-
KeyValueStats,
|
|
8
|
-
KeyValueItemWithMetadata,
|
|
9
|
-
CreateNamespaceParams,
|
|
10
|
-
GetAllStatsParams,
|
|
11
|
-
KeyValueStatsPaginated,
|
|
12
|
-
} from '@agentuity/core';
|
|
13
|
-
import { now } from './_util';
|
|
14
|
-
|
|
15
|
-
export class LocalKeyValueStorage implements KeyValueStorage {
|
|
16
|
-
#db: Database;
|
|
17
|
-
#projectPath: string;
|
|
18
|
-
|
|
19
|
-
constructor(db: Database, projectPath: string) {
|
|
20
|
-
this.#db = db;
|
|
21
|
-
this.#projectPath = projectPath;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async get<T>(name: string, key: string): Promise<DataResult<T>> {
|
|
25
|
-
const query = this.#db.query(`
|
|
26
|
-
SELECT value, content_type, expires_at
|
|
27
|
-
FROM kv_storage
|
|
28
|
-
WHERE project_path = ? AND name = ? AND key = ?
|
|
29
|
-
`);
|
|
30
|
-
|
|
31
|
-
const row = query.get(this.#projectPath, name, key) as {
|
|
32
|
-
value: Buffer;
|
|
33
|
-
content_type: string;
|
|
34
|
-
expires_at: number | null;
|
|
35
|
-
} | null;
|
|
36
|
-
|
|
37
|
-
if (!row) {
|
|
38
|
-
return { exists: false } as DataResultNotFound;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Check expiration
|
|
42
|
-
if (row.expires_at && row.expires_at < now()) {
|
|
43
|
-
// Delete expired row
|
|
44
|
-
await this.delete(name, key);
|
|
45
|
-
return { exists: false } as DataResultNotFound;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Deserialize based on content type
|
|
49
|
-
let data: T;
|
|
50
|
-
if (row.content_type === 'application/json') {
|
|
51
|
-
try {
|
|
52
|
-
const text = row.value.toString('utf-8');
|
|
53
|
-
data = JSON.parse(text);
|
|
54
|
-
} catch {
|
|
55
|
-
// If JSON parse fails, return the raw buffer as Uint8Array
|
|
56
|
-
data = new Uint8Array(row.value) as T;
|
|
57
|
-
}
|
|
58
|
-
} else if (row.content_type.startsWith('text/')) {
|
|
59
|
-
data = row.value.toString('utf-8') as T;
|
|
60
|
-
} else {
|
|
61
|
-
data = new Uint8Array(row.value) as T;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return {
|
|
65
|
-
data,
|
|
66
|
-
contentType: row.content_type,
|
|
67
|
-
exists: true,
|
|
68
|
-
// Include expiresAt if set (convert from Unix timestamp to ISO string)
|
|
69
|
-
...(row.expires_at && { expiresAt: new Date(row.expires_at).toISOString() }),
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
async set<T = unknown>(
|
|
74
|
-
name: string,
|
|
75
|
-
key: string,
|
|
76
|
-
value: T,
|
|
77
|
-
params?: KeyValueStorageSetParams
|
|
78
|
-
): Promise<void> {
|
|
79
|
-
// Serialize value
|
|
80
|
-
let buffer: Buffer;
|
|
81
|
-
let contentType = params?.contentType || 'application/octet-stream';
|
|
82
|
-
|
|
83
|
-
if (typeof value === 'string') {
|
|
84
|
-
buffer = Buffer.from(value, 'utf-8');
|
|
85
|
-
if (!params?.contentType) {
|
|
86
|
-
contentType = 'text/plain';
|
|
87
|
-
}
|
|
88
|
-
} else if (value instanceof Uint8Array) {
|
|
89
|
-
buffer = Buffer.from(value);
|
|
90
|
-
} else if (value instanceof ArrayBuffer) {
|
|
91
|
-
buffer = Buffer.from(new Uint8Array(value));
|
|
92
|
-
} else if (
|
|
93
|
-
typeof value === 'number' ||
|
|
94
|
-
typeof value === 'boolean' ||
|
|
95
|
-
typeof value === 'object'
|
|
96
|
-
) {
|
|
97
|
-
// Use JSON for numbers, booleans, and objects to preserve type on round-trip
|
|
98
|
-
buffer = Buffer.from(JSON.stringify(value), 'utf-8');
|
|
99
|
-
contentType = 'application/json';
|
|
100
|
-
} else {
|
|
101
|
-
// Fallback for other types
|
|
102
|
-
buffer = Buffer.from(String(value), 'utf-8');
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Calculate expiration
|
|
106
|
-
// TTL handling: null or 0 = no expiration, positive = TTL in seconds
|
|
107
|
-
// undefined = use default (7 days for consistency with cloud namespace default)
|
|
108
|
-
let expiresAt: number | null = null;
|
|
109
|
-
if (params?.ttl === undefined) {
|
|
110
|
-
// Default to 7 days (matching cloud namespace default behavior)
|
|
111
|
-
expiresAt = now() + 7 * 24 * 60 * 60 * 1000;
|
|
112
|
-
} else if (params.ttl !== null && params.ttl > 0) {
|
|
113
|
-
expiresAt = now() + params.ttl * 1000;
|
|
114
|
-
}
|
|
115
|
-
// else: ttl is null or 0, so expiresAt stays null (no expiration)
|
|
116
|
-
const timestamp = now();
|
|
117
|
-
|
|
118
|
-
// UPSERT
|
|
119
|
-
const stmt = this.#db.prepare(`
|
|
120
|
-
INSERT INTO kv_storage (project_path, name, key, value, content_type, expires_at, created_at, updated_at)
|
|
121
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
122
|
-
ON CONFLICT(project_path, name, key)
|
|
123
|
-
DO UPDATE SET
|
|
124
|
-
value = excluded.value,
|
|
125
|
-
content_type = excluded.content_type,
|
|
126
|
-
expires_at = excluded.expires_at,
|
|
127
|
-
updated_at = excluded.updated_at
|
|
128
|
-
`);
|
|
129
|
-
|
|
130
|
-
stmt.run(this.#projectPath, name, key, buffer, contentType, expiresAt, timestamp, timestamp);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
async delete(name: string, key: string): Promise<void> {
|
|
134
|
-
const stmt = this.#db.prepare(`
|
|
135
|
-
DELETE FROM kv_storage
|
|
136
|
-
WHERE project_path = ? AND name = ? AND key = ?
|
|
137
|
-
`);
|
|
138
|
-
|
|
139
|
-
stmt.run(this.#projectPath, name, key);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
async getStats(_name: string): Promise<KeyValueStats> {
|
|
143
|
-
throw new Error('getStats not implemented for local storage');
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
async getAllStats(
|
|
147
|
-
_params?: GetAllStatsParams
|
|
148
|
-
): Promise<Record<string, KeyValueStats> | KeyValueStatsPaginated> {
|
|
149
|
-
throw new Error('getAllStats not implemented for local storage');
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
async getNamespaces(): Promise<string[]> {
|
|
153
|
-
throw new Error('getNamespaces not implemented for local storage');
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
async search<T = unknown>(
|
|
157
|
-
_name: string,
|
|
158
|
-
_keyword: string
|
|
159
|
-
): Promise<Record<string, KeyValueItemWithMetadata<T>>> {
|
|
160
|
-
throw new Error('search not implemented for local storage');
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
async getKeys(_name: string): Promise<string[]> {
|
|
164
|
-
throw new Error('getKeys not implemented for local storage');
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
async deleteNamespace(_name: string): Promise<void> {
|
|
168
|
-
throw new Error('deleteNamespace not implemented for local storage');
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
async createNamespace(_name: string, _params?: CreateNamespaceParams): Promise<void> {
|
|
172
|
-
throw new Error('createNamespace not implemented for local storage');
|
|
173
|
-
}
|
|
174
|
-
}
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import type { Database } from 'bun:sqlite';
|
|
2
|
-
import type {
|
|
3
|
-
QueueService,
|
|
4
|
-
QueuePublishParams,
|
|
5
|
-
QueuePublishResult,
|
|
6
|
-
QueueCreateParams,
|
|
7
|
-
QueueCreateResult,
|
|
8
|
-
} from '@agentuity/core';
|
|
9
|
-
|
|
10
|
-
export class LocalQueueStorage implements QueueService {
|
|
11
|
-
#db: Database;
|
|
12
|
-
#projectPath: string;
|
|
13
|
-
|
|
14
|
-
constructor(db: Database, projectPath: string) {
|
|
15
|
-
this.#db = db;
|
|
16
|
-
this.#projectPath = projectPath;
|
|
17
|
-
this.#initializeTable();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
#initializeTable(): void {
|
|
21
|
-
this.#db.run(`
|
|
22
|
-
CREATE TABLE IF NOT EXISTS queue_messages (
|
|
23
|
-
id TEXT PRIMARY KEY,
|
|
24
|
-
project_path TEXT NOT NULL,
|
|
25
|
-
queue_name TEXT NOT NULL,
|
|
26
|
-
offset INTEGER NOT NULL,
|
|
27
|
-
payload TEXT NOT NULL,
|
|
28
|
-
metadata TEXT,
|
|
29
|
-
partition_key TEXT,
|
|
30
|
-
idempotency_key TEXT,
|
|
31
|
-
ttl_seconds INTEGER,
|
|
32
|
-
expires_at TEXT,
|
|
33
|
-
state TEXT NOT NULL DEFAULT 'pending',
|
|
34
|
-
created_at TEXT NOT NULL,
|
|
35
|
-
published_at TEXT NOT NULL
|
|
36
|
-
)
|
|
37
|
-
`);
|
|
38
|
-
|
|
39
|
-
this.#db.run(`
|
|
40
|
-
CREATE INDEX IF NOT EXISTS idx_queue_name
|
|
41
|
-
ON queue_messages(project_path, queue_name)
|
|
42
|
-
`);
|
|
43
|
-
|
|
44
|
-
this.#db.run(`
|
|
45
|
-
CREATE UNIQUE INDEX IF NOT EXISTS idx_queue_idempotency_unique
|
|
46
|
-
ON queue_messages(project_path, queue_name, idempotency_key)
|
|
47
|
-
WHERE idempotency_key IS NOT NULL
|
|
48
|
-
`);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
async publish(
|
|
52
|
-
queueName: string,
|
|
53
|
-
payload: string | object,
|
|
54
|
-
params?: QueuePublishParams
|
|
55
|
-
): Promise<QueuePublishResult> {
|
|
56
|
-
const id = crypto.randomUUID();
|
|
57
|
-
const timestamp = new Date().toISOString();
|
|
58
|
-
const payloadStr = typeof payload === 'string' ? payload : JSON.stringify(payload);
|
|
59
|
-
const metadataStr = params?.metadata ? JSON.stringify(params.metadata) : null;
|
|
60
|
-
const ttlSeconds = params?.ttl ?? null;
|
|
61
|
-
const expiresAt = ttlSeconds ? new Date(Date.now() + ttlSeconds * 1000).toISOString() : null;
|
|
62
|
-
|
|
63
|
-
const publishInTransaction = this.#db.transaction(() => {
|
|
64
|
-
if (params?.idempotencyKey) {
|
|
65
|
-
const existing = this.#db
|
|
66
|
-
.query(
|
|
67
|
-
`
|
|
68
|
-
SELECT id, offset, published_at
|
|
69
|
-
FROM queue_messages
|
|
70
|
-
WHERE project_path = ? AND queue_name = ? AND idempotency_key = ?
|
|
71
|
-
`
|
|
72
|
-
)
|
|
73
|
-
.get(this.#projectPath, queueName, params.idempotencyKey) as {
|
|
74
|
-
id: string;
|
|
75
|
-
offset: number;
|
|
76
|
-
published_at: string;
|
|
77
|
-
} | null;
|
|
78
|
-
|
|
79
|
-
if (existing) {
|
|
80
|
-
return {
|
|
81
|
-
id: existing.id,
|
|
82
|
-
offset: existing.offset,
|
|
83
|
-
publishedAt: existing.published_at,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const offsetResult = this.#db
|
|
89
|
-
.query(
|
|
90
|
-
`
|
|
91
|
-
SELECT COALESCE(MAX(offset), -1) + 1 as next_offset
|
|
92
|
-
FROM queue_messages
|
|
93
|
-
WHERE project_path = ? AND queue_name = ?
|
|
94
|
-
`
|
|
95
|
-
)
|
|
96
|
-
.get(this.#projectPath, queueName) as { next_offset: number };
|
|
97
|
-
|
|
98
|
-
const offset = offsetResult.next_offset;
|
|
99
|
-
|
|
100
|
-
this.#db
|
|
101
|
-
.prepare(
|
|
102
|
-
`
|
|
103
|
-
INSERT INTO queue_messages (
|
|
104
|
-
id, project_path, queue_name, offset, payload, metadata,
|
|
105
|
-
partition_key, idempotency_key, ttl_seconds, expires_at, state, created_at, published_at
|
|
106
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'pending', ?, ?)
|
|
107
|
-
`
|
|
108
|
-
)
|
|
109
|
-
.run(
|
|
110
|
-
id,
|
|
111
|
-
this.#projectPath,
|
|
112
|
-
queueName,
|
|
113
|
-
offset,
|
|
114
|
-
payloadStr,
|
|
115
|
-
metadataStr,
|
|
116
|
-
params?.partitionKey ?? null,
|
|
117
|
-
params?.idempotencyKey ?? null,
|
|
118
|
-
ttlSeconds,
|
|
119
|
-
expiresAt,
|
|
120
|
-
timestamp,
|
|
121
|
-
timestamp
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
return {
|
|
125
|
-
id,
|
|
126
|
-
offset,
|
|
127
|
-
publishedAt: timestamp,
|
|
128
|
-
};
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
return publishInTransaction.immediate();
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
async createQueue(queueName: string, params?: QueueCreateParams): Promise<QueueCreateResult> {
|
|
135
|
-
console.debug(`[local] createQueue: ${queueName}`);
|
|
136
|
-
return {
|
|
137
|
-
name: queueName,
|
|
138
|
-
queueType: params?.queueType ?? 'worker',
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
async deleteQueue(_queueName: string): Promise<void> {
|
|
143
|
-
// No-op in local mode — queues don't need provisioning locally
|
|
144
|
-
}
|
|
145
|
-
}
|
|
@@ -1,358 +0,0 @@
|
|
|
1
|
-
import type { Database } from 'bun:sqlite';
|
|
2
|
-
import type {
|
|
3
|
-
StreamStorage,
|
|
4
|
-
Stream,
|
|
5
|
-
CreateStreamProps,
|
|
6
|
-
ListStreamsParams,
|
|
7
|
-
ListStreamsResponse,
|
|
8
|
-
StreamInfo,
|
|
9
|
-
} from '@agentuity/core';
|
|
10
|
-
import { now } from './_util';
|
|
11
|
-
import { join } from 'node:path';
|
|
12
|
-
import { homedir } from 'node:os';
|
|
13
|
-
import { randomUUID } from 'node:crypto';
|
|
14
|
-
import { mkdirSync, existsSync, unlinkSync } from 'node:fs';
|
|
15
|
-
import { openSync, writeSync, closeSync, readFileSync } from 'node:fs';
|
|
16
|
-
|
|
17
|
-
export class LocalStreamStorage implements StreamStorage {
|
|
18
|
-
#db: Database;
|
|
19
|
-
#projectPath: string;
|
|
20
|
-
#serverUrl: string;
|
|
21
|
-
#tempDir: string;
|
|
22
|
-
|
|
23
|
-
constructor(db: Database, projectPath: string, serverUrl: string) {
|
|
24
|
-
this.#db = db;
|
|
25
|
-
this.#projectPath = projectPath;
|
|
26
|
-
this.#serverUrl = serverUrl;
|
|
27
|
-
|
|
28
|
-
// Create temp directory for stream buffering
|
|
29
|
-
this.#tempDir = join(homedir(), '.config', 'agentuity', 'streams');
|
|
30
|
-
if (!existsSync(this.#tempDir)) {
|
|
31
|
-
mkdirSync(this.#tempDir, { recursive: true });
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async create(namespace: string, props?: CreateStreamProps): Promise<Stream> {
|
|
36
|
-
if (!namespace || namespace.length < 1 || namespace.length > 254) {
|
|
37
|
-
throw new Error('Stream namespace must be between 1 and 254 characters');
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const id = randomUUID();
|
|
41
|
-
const timestamp = now();
|
|
42
|
-
const metadata = props?.metadata ? JSON.stringify(props.metadata) : null;
|
|
43
|
-
|
|
44
|
-
// Insert stream record with NULL data
|
|
45
|
-
const stmt = this.#db.prepare(`
|
|
46
|
-
INSERT INTO stream_storage (
|
|
47
|
-
project_path, id, name, metadata, content_type, created_at
|
|
48
|
-
)
|
|
49
|
-
VALUES (?, ?, ?, ?, ?, ?)
|
|
50
|
-
`);
|
|
51
|
-
|
|
52
|
-
stmt.run(
|
|
53
|
-
this.#projectPath,
|
|
54
|
-
id,
|
|
55
|
-
namespace,
|
|
56
|
-
metadata,
|
|
57
|
-
props?.contentType || 'application/octet-stream',
|
|
58
|
-
timestamp
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
const url = `${this.#serverUrl}/_agentuity/local/stream/${id}`;
|
|
62
|
-
|
|
63
|
-
return new LocalStream(
|
|
64
|
-
id,
|
|
65
|
-
url,
|
|
66
|
-
this.#db,
|
|
67
|
-
this.#projectPath,
|
|
68
|
-
this.#tempDir,
|
|
69
|
-
props?.compress ?? false
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
async list(params?: ListStreamsParams): Promise<ListStreamsResponse> {
|
|
74
|
-
if (params?.limit && (params.limit <= 0 || params.limit > 1000)) {
|
|
75
|
-
throw new Error('limit must be between 1 and 1000');
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
let query = `
|
|
79
|
-
SELECT id, name, metadata, size_bytes
|
|
80
|
-
FROM stream_storage
|
|
81
|
-
WHERE project_path = ?
|
|
82
|
-
`;
|
|
83
|
-
const queryParams: (string | number)[] = [this.#projectPath];
|
|
84
|
-
|
|
85
|
-
// Add filters (map namespace to name for the database)
|
|
86
|
-
if (params?.namespace) {
|
|
87
|
-
query += ` AND name = ?`;
|
|
88
|
-
queryParams.push(params.namespace);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (params?.metadata) {
|
|
92
|
-
// Simple JSON matching - check if metadata contains all key-value pairs
|
|
93
|
-
for (const [key, value] of Object.entries(params.metadata)) {
|
|
94
|
-
query += ` AND metadata LIKE ?`;
|
|
95
|
-
queryParams.push(`%"${key}":"${value}"%`);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Get total count
|
|
100
|
-
const countQuery = this.#db.query(
|
|
101
|
-
query.replace('SELECT id, name, metadata, size_bytes', 'SELECT COUNT(*) as count')
|
|
102
|
-
);
|
|
103
|
-
const { count } = countQuery.get(...queryParams) as { count: number };
|
|
104
|
-
|
|
105
|
-
// Add pagination
|
|
106
|
-
query += ` ORDER BY created_at DESC`;
|
|
107
|
-
if (params?.limit) {
|
|
108
|
-
query += ` LIMIT ${params.limit}`;
|
|
109
|
-
}
|
|
110
|
-
if (params?.offset) {
|
|
111
|
-
query += ` OFFSET ${params.offset}`;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const stmt = this.#db.query(query);
|
|
115
|
-
const rows = stmt.all(...queryParams) as Array<{
|
|
116
|
-
id: string;
|
|
117
|
-
name: string;
|
|
118
|
-
metadata: string | null;
|
|
119
|
-
size_bytes: number;
|
|
120
|
-
}>;
|
|
121
|
-
|
|
122
|
-
// Map name to namespace for the SDK interface
|
|
123
|
-
const streams: StreamInfo[] = rows.map((row) => ({
|
|
124
|
-
id: row.id,
|
|
125
|
-
namespace: row.name,
|
|
126
|
-
metadata: row.metadata ? JSON.parse(row.metadata) : {},
|
|
127
|
-
url: `${this.#serverUrl}/_agentuity/local/stream/${row.id}`,
|
|
128
|
-
sizeBytes: row.size_bytes,
|
|
129
|
-
expiresAt: null,
|
|
130
|
-
}));
|
|
131
|
-
|
|
132
|
-
return {
|
|
133
|
-
success: true,
|
|
134
|
-
streams,
|
|
135
|
-
total: count,
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
async get(id: string): Promise<StreamInfo> {
|
|
140
|
-
if (!id?.trim()) {
|
|
141
|
-
throw new Error('Stream id is required');
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const stmt = this.#db.query<
|
|
145
|
-
{ id: string; name: string; metadata: string | null; size_bytes: number },
|
|
146
|
-
[string, string]
|
|
147
|
-
>(`
|
|
148
|
-
SELECT id, name, metadata, size_bytes
|
|
149
|
-
FROM stream_storage
|
|
150
|
-
WHERE project_path = ? AND id = ?
|
|
151
|
-
`);
|
|
152
|
-
|
|
153
|
-
const row = stmt.get(this.#projectPath, id);
|
|
154
|
-
|
|
155
|
-
if (!row) {
|
|
156
|
-
throw new Error(`Stream not found: ${id}`);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const metadata = row.metadata ? JSON.parse(row.metadata) : {};
|
|
160
|
-
const url = `${this.#serverUrl}/_agentuity/local/stream/${id}`;
|
|
161
|
-
|
|
162
|
-
// Map name to namespace for the SDK interface
|
|
163
|
-
return {
|
|
164
|
-
id: row.id,
|
|
165
|
-
namespace: row.name,
|
|
166
|
-
metadata,
|
|
167
|
-
url,
|
|
168
|
-
sizeBytes: row.size_bytes,
|
|
169
|
-
expiresAt: null,
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
async download(id: string): Promise<ReadableStream<Uint8Array>> {
|
|
174
|
-
if (!id?.trim()) {
|
|
175
|
-
throw new Error('Stream id is required');
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const stmt = this.#db.query<{ data: Buffer | null }, [string, string]>(`
|
|
179
|
-
SELECT data FROM stream_storage
|
|
180
|
-
WHERE project_path = ? AND id = ?
|
|
181
|
-
`);
|
|
182
|
-
|
|
183
|
-
const row = stmt.get(this.#projectPath, id);
|
|
184
|
-
|
|
185
|
-
if (!row || !row.data) {
|
|
186
|
-
throw new Error(`Stream not found or empty: ${id}`);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Convert Buffer to ReadableStream
|
|
190
|
-
const buffer = row.data;
|
|
191
|
-
return new ReadableStream({
|
|
192
|
-
start(controller) {
|
|
193
|
-
controller.enqueue(new Uint8Array(buffer));
|
|
194
|
-
controller.close();
|
|
195
|
-
},
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
async delete(id: string): Promise<void> {
|
|
200
|
-
if (!id?.trim()) {
|
|
201
|
-
throw new Error('Stream id is required');
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const stmt = this.#db.prepare(`
|
|
205
|
-
DELETE FROM stream_storage
|
|
206
|
-
WHERE project_path = ? AND id = ?
|
|
207
|
-
`);
|
|
208
|
-
|
|
209
|
-
stmt.run(this.#projectPath, id);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
class LocalStream extends WritableStream implements Stream {
|
|
214
|
-
public readonly id: string;
|
|
215
|
-
public readonly url: string;
|
|
216
|
-
|
|
217
|
-
#db: Database;
|
|
218
|
-
#projectPath: string;
|
|
219
|
-
#compressed: boolean;
|
|
220
|
-
#tempFilePath: string;
|
|
221
|
-
#fileHandle: number | null = null;
|
|
222
|
-
#bytesWritten = 0;
|
|
223
|
-
#closed = false;
|
|
224
|
-
|
|
225
|
-
constructor(
|
|
226
|
-
id: string,
|
|
227
|
-
url: string,
|
|
228
|
-
db: Database,
|
|
229
|
-
projectPath: string,
|
|
230
|
-
tempDir: string,
|
|
231
|
-
compressed: boolean
|
|
232
|
-
) {
|
|
233
|
-
super({
|
|
234
|
-
write: async (chunk: Uint8Array) => {
|
|
235
|
-
await this.#writeToFile(chunk);
|
|
236
|
-
},
|
|
237
|
-
close: async () => {
|
|
238
|
-
await this.#persist();
|
|
239
|
-
},
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
this.id = id;
|
|
243
|
-
this.url = url;
|
|
244
|
-
this.#db = db;
|
|
245
|
-
this.#projectPath = projectPath;
|
|
246
|
-
this.#compressed = compressed;
|
|
247
|
-
this.#tempFilePath = join(tempDir, `${id}.tmp`);
|
|
248
|
-
|
|
249
|
-
// Open file for writing
|
|
250
|
-
this.#fileHandle = openSync(this.#tempFilePath, 'w');
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
get bytesWritten(): number {
|
|
254
|
-
return this.#bytesWritten;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
get compressed(): boolean {
|
|
258
|
-
return this.#compressed;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
async write(chunk: string | Uint8Array | ArrayBuffer | Buffer | object): Promise<void> {
|
|
262
|
-
if (this.#closed) {
|
|
263
|
-
throw new Error('Stream is closed');
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
let binary: Uint8Array;
|
|
267
|
-
if (chunk instanceof Uint8Array) {
|
|
268
|
-
binary = chunk;
|
|
269
|
-
} else if (typeof chunk === 'string') {
|
|
270
|
-
binary = new TextEncoder().encode(chunk);
|
|
271
|
-
} else if (chunk instanceof ArrayBuffer) {
|
|
272
|
-
binary = new Uint8Array(chunk);
|
|
273
|
-
} else if (typeof chunk === 'object') {
|
|
274
|
-
binary = new TextEncoder().encode(JSON.stringify(chunk));
|
|
275
|
-
} else {
|
|
276
|
-
binary = new TextEncoder().encode(String(chunk));
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
await this.#writeToFile(binary);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
override async close(): Promise<void> {
|
|
283
|
-
if (this.#closed) {
|
|
284
|
-
return;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
this.#closed = true;
|
|
288
|
-
|
|
289
|
-
// Close file handle if open
|
|
290
|
-
if (this.#fileHandle !== null) {
|
|
291
|
-
closeSync(this.#fileHandle);
|
|
292
|
-
this.#fileHandle = null;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
await this.#persist();
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
getReader(): ReadableStream<Uint8Array> {
|
|
299
|
-
const db = this.#db;
|
|
300
|
-
const projectPath = this.#projectPath;
|
|
301
|
-
const id = this.id;
|
|
302
|
-
|
|
303
|
-
return new ReadableStream({
|
|
304
|
-
start(controller) {
|
|
305
|
-
const query = db.query(`
|
|
306
|
-
SELECT data FROM stream_storage
|
|
307
|
-
WHERE project_path = ? AND id = ?
|
|
308
|
-
`);
|
|
309
|
-
|
|
310
|
-
const row = query.get(projectPath, id) as { data: Buffer | null } | null;
|
|
311
|
-
|
|
312
|
-
if (!row || !row.data) {
|
|
313
|
-
controller.error(new Error('Stream not found or not finalized'));
|
|
314
|
-
return;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
controller.enqueue(new Uint8Array(row.data));
|
|
318
|
-
controller.close();
|
|
319
|
-
},
|
|
320
|
-
});
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
async #writeToFile(chunk: Uint8Array): Promise<void> {
|
|
324
|
-
if (this.#fileHandle === null) {
|
|
325
|
-
throw new Error('File handle is closed');
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
const written = writeSync(this.#fileHandle, chunk);
|
|
329
|
-
this.#bytesWritten += written;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
async #persist(): Promise<void> {
|
|
333
|
-
// Read buffered file
|
|
334
|
-
let data: Buffer = readFileSync(this.#tempFilePath);
|
|
335
|
-
|
|
336
|
-
// Optional: Apply compression if enabled
|
|
337
|
-
if (this.#compressed) {
|
|
338
|
-
const { gzipSync } = await import('node:zlib');
|
|
339
|
-
data = gzipSync(data) as Buffer;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
// Update DB with finalized data
|
|
343
|
-
const stmt = this.#db.prepare(`
|
|
344
|
-
UPDATE stream_storage
|
|
345
|
-
SET data = ?, size_bytes = ?
|
|
346
|
-
WHERE project_path = ? AND id = ?
|
|
347
|
-
`);
|
|
348
|
-
|
|
349
|
-
stmt.run(data, this.#bytesWritten, this.#projectPath, this.id);
|
|
350
|
-
|
|
351
|
-
// Clean up temp file
|
|
352
|
-
try {
|
|
353
|
-
unlinkSync(this.#tempFilePath);
|
|
354
|
-
} catch {
|
|
355
|
-
// Ignore cleanup errors
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
}
|