@stackory/gateway-persistence 0.0.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/README.md +49 -0
- package/dist/esm/database/index.d.ts +3 -0
- package/dist/esm/database/index.d.ts.map +1 -0
- package/dist/esm/database/index.js +3 -0
- package/dist/esm/database/index.js.map +1 -0
- package/dist/esm/database.d.ts +23 -0
- package/dist/esm/database.d.ts.map +1 -0
- package/dist/esm/database.js +53 -0
- package/dist/esm/database.js.map +1 -0
- package/dist/esm/gateway-database.d.ts +6 -0
- package/dist/esm/gateway-database.d.ts.map +1 -0
- package/dist/esm/gateway-database.js +19 -0
- package/dist/esm/gateway-database.js.map +1 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/migrations/generated.d.ts +3 -0
- package/dist/esm/migrations/generated.d.ts.map +1 -0
- package/dist/esm/migrations/generated.js +7 -0
- package/dist/esm/migrations/generated.js.map +1 -0
- package/dist/esm/migrations/index.d.ts +3 -0
- package/dist/esm/migrations/index.d.ts.map +1 -0
- package/dist/esm/migrations/index.js +2 -0
- package/dist/esm/migrations/index.js.map +1 -0
- package/dist/esm/migrations/types.d.ts +5 -0
- package/dist/esm/migrations/types.d.ts.map +1 -0
- package/dist/esm/migrations/types.js +2 -0
- package/dist/esm/migrations/types.js.map +1 -0
- package/dist/esm/schema.d.ts +579 -0
- package/dist/esm/schema.d.ts.map +1 -0
- package/dist/esm/schema.js +91 -0
- package/dist/esm/schema.js.map +1 -0
- package/dist/esm/stores/dedup-store.d.ts +14 -0
- package/dist/esm/stores/dedup-store.d.ts.map +1 -0
- package/dist/esm/stores/dedup-store.js +62 -0
- package/dist/esm/stores/dedup-store.js.map +1 -0
- package/dist/esm/stores/in-memory-session-store.d.ts +12 -0
- package/dist/esm/stores/in-memory-session-store.d.ts.map +1 -0
- package/dist/esm/stores/in-memory-session-store.js +64 -0
- package/dist/esm/stores/in-memory-session-store.js.map +1 -0
- package/dist/esm/stores/index.d.ts +7 -0
- package/dist/esm/stores/index.d.ts.map +1 -0
- package/dist/esm/stores/index.js +8 -0
- package/dist/esm/stores/index.js.map +1 -0
- package/dist/esm/stores/sqlite-binding-store.d.ts +14 -0
- package/dist/esm/stores/sqlite-binding-store.d.ts.map +1 -0
- package/dist/esm/stores/sqlite-binding-store.js +58 -0
- package/dist/esm/stores/sqlite-binding-store.js.map +1 -0
- package/dist/esm/stores/sqlite-pair-request-store.d.ts +11 -0
- package/dist/esm/stores/sqlite-pair-request-store.d.ts.map +1 -0
- package/dist/esm/stores/sqlite-pair-request-store.js +64 -0
- package/dist/esm/stores/sqlite-pair-request-store.js.map +1 -0
- package/dist/esm/stores/sqlite-policy-store.d.ts +12 -0
- package/dist/esm/stores/sqlite-policy-store.d.ts.map +1 -0
- package/dist/esm/stores/sqlite-policy-store.js +95 -0
- package/dist/esm/stores/sqlite-policy-store.js.map +1 -0
- package/dist/esm/stores/sqlite-session-store.d.ts +13 -0
- package/dist/esm/stores/sqlite-session-store.d.ts.map +1 -0
- package/dist/esm/stores/sqlite-session-store.js +107 -0
- package/dist/esm/stores/sqlite-session-store.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dedup-store.d.ts","sourceRoot":"","sources":["../../../src/stores/dedup-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAG1D;;GAEG;AACH,qBAAa,gBAAiB,YAAW,WAAW;IAIlD,OAAO,CAAC,QAAQ,CAAC,EAAE;IAHpB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAGlB,EAAE,EAAE,uBAAuB,EAC5C,UAAU,SAAS;IAKpB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IA8B1E,OAAO,CAAC,aAAa;CAiCrB;AAED,wBAAgB,gBAAgB,CAC/B,EAAE,EAAE,uBAAuB,EAC3B,UAAU,CAAC,EAAE,MAAM,GACjB,WAAW,CAEb"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { and, count, eq } from 'drizzle-orm';
|
|
2
|
+
import { inboundDedup } from '../schema';
|
|
3
|
+
/**
|
|
4
|
+
* SQLite 实现的 IDedupStore。
|
|
5
|
+
*/
|
|
6
|
+
export class SqliteDedupStore {
|
|
7
|
+
db;
|
|
8
|
+
maxEntries;
|
|
9
|
+
constructor(db, maxEntries = 10_000) {
|
|
10
|
+
this.db = db;
|
|
11
|
+
this.maxEntries = maxEntries;
|
|
12
|
+
}
|
|
13
|
+
checkAndMark(adapterId, messageId, nowMs) {
|
|
14
|
+
const existing = this.db.drizzle
|
|
15
|
+
.select({ seenAtMs: inboundDedup.seenAtMs })
|
|
16
|
+
.from(inboundDedup)
|
|
17
|
+
.where(and(eq(inboundDedup.adapterId, adapterId), eq(inboundDedup.messageId, messageId)))
|
|
18
|
+
.get();
|
|
19
|
+
if (existing !== undefined) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
this.db.drizzle
|
|
23
|
+
.insert(inboundDedup)
|
|
24
|
+
.values({
|
|
25
|
+
adapterId,
|
|
26
|
+
messageId,
|
|
27
|
+
seenAtMs: nowMs,
|
|
28
|
+
})
|
|
29
|
+
.run();
|
|
30
|
+
this.evictIfNeeded();
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
evictIfNeeded() {
|
|
34
|
+
const result = this.db.drizzle
|
|
35
|
+
.select({ total: count() })
|
|
36
|
+
.from(inboundDedup)
|
|
37
|
+
.get();
|
|
38
|
+
const total = result?.total ?? 0;
|
|
39
|
+
if (total <= this.maxEntries) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const toDelete = this.db.drizzle
|
|
43
|
+
.select({
|
|
44
|
+
messageId: inboundDedup.messageId,
|
|
45
|
+
adapterId: inboundDedup.adapterId,
|
|
46
|
+
})
|
|
47
|
+
.from(inboundDedup)
|
|
48
|
+
.orderBy(inboundDedup.seenAtMs)
|
|
49
|
+
.limit(total - this.maxEntries)
|
|
50
|
+
.all();
|
|
51
|
+
for (const row of toDelete) {
|
|
52
|
+
this.db.drizzle
|
|
53
|
+
.delete(inboundDedup)
|
|
54
|
+
.where(and(eq(inboundDedup.adapterId, row.adapterId), eq(inboundDedup.messageId, row.messageId)))
|
|
55
|
+
.run();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export function createDedupStore(db, maxEntries) {
|
|
60
|
+
return new SqliteDedupStore(db, maxEntries);
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=dedup-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dedup-store.js","sourceRoot":"","sources":["../../../src/stores/dedup-store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC;;GAEG;AACH,MAAM,OAAO,gBAAgB;IAIV;IAHD,UAAU,CAAS;IAEpC,YACkB,EAA2B,EAC5C,UAAU,GAAG,MAAM;QADF,OAAE,GAAF,EAAE,CAAyB;QAG5C,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC9B,CAAC;IAED,YAAY,CAAC,SAAiB,EAAE,SAAiB,EAAE,KAAa;QAC/D,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO;aAC9B,MAAM,CAAC,EAAE,QAAQ,EAAE,YAAY,CAAC,QAAQ,EAAE,CAAC;aAC3C,IAAI,CAAC,YAAY,CAAC;aAClB,KAAK,CACL,GAAG,CACF,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,SAAS,CAAC,EACrC,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,SAAS,CAAC,CACrC,CACD;aACA,GAAG,EAAE,CAAC;QAER,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC5B,OAAO,KAAK,CAAC;QACd,CAAC;QAED,IAAI,CAAC,EAAE,CAAC,OAAO;aACb,MAAM,CAAC,YAAY,CAAC;aACpB,MAAM,CAAC;YACP,SAAS;YACT,SAAS;YACT,QAAQ,EAAE,KAAK;SACf,CAAC;aACD,GAAG,EAAE,CAAC;QAER,IAAI,CAAC,aAAa,EAAE,CAAC;QAErB,OAAO,IAAI,CAAC;IACb,CAAC;IAEO,aAAa;QACpB,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO;aAC5B,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC;aAC1B,IAAI,CAAC,YAAY,CAAC;aAClB,GAAG,EAAE,CAAC;QAER,MAAM,KAAK,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC,CAAC;QACjC,IAAI,KAAK,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAC9B,OAAO;QACR,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO;aAC9B,MAAM,CAAC;YACP,SAAS,EAAE,YAAY,CAAC,SAAS;YACjC,SAAS,EAAE,YAAY,CAAC,SAAS;SACjC,CAAC;aACD,IAAI,CAAC,YAAY,CAAC;aAClB,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC;aAC9B,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC;aAC9B,GAAG,EAAE,CAAC;QAER,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC5B,IAAI,CAAC,EAAE,CAAC,OAAO;iBACb,MAAM,CAAC,YAAY,CAAC;iBACpB,KAAK,CACL,GAAG,CACF,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,EACzC,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,CACzC,CACD;iBACA,GAAG,EAAE,CAAC;QACT,CAAC;IACF,CAAC;CACD;AAED,MAAM,UAAU,gBAAgB,CAC/B,EAA2B,EAC3B,UAAmB;IAEnB,OAAO,IAAI,gBAAgB,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ISessionKey, ISessionRecord, ISessionStore, ITokenUsage } from '@stackory/gateway-core';
|
|
2
|
+
export declare class InMemorySessionStore implements ISessionStore {
|
|
3
|
+
private records;
|
|
4
|
+
private keyStr;
|
|
5
|
+
findActive(key: ISessionKey): ISessionRecord | null;
|
|
6
|
+
upsert(record: ISessionRecord): void;
|
|
7
|
+
markSuspended(sessionId: string, reason: 'user_stop' | 'fatal_error'): void;
|
|
8
|
+
endSession(sessionId: string): void;
|
|
9
|
+
findIdleBefore(cutoffMs: number): readonly ISessionRecord[];
|
|
10
|
+
addTokenUsage(sessionId: string, usage: ITokenUsage): void;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=in-memory-session-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in-memory-session-store.d.ts","sourceRoot":"","sources":["../../../src/stores/in-memory-session-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,WAAW,EACX,cAAc,EAEd,aAAa,EACb,WAAW,EACX,MAAM,wBAAwB,CAAC;AAahC,qBAAa,oBAAqB,YAAW,aAAa;IACzD,OAAO,CAAC,OAAO,CAAoC;IAEnD,OAAO,CAAC,MAAM;IAId,UAAU,CAAC,GAAG,EAAE,WAAW,GAAG,cAAc,GAAG,IAAI;IAMnD,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAIpC,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,aAAa,GAAG,IAAI;IAS3E,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAInC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,cAAc,EAAE;IAM3D,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI;CAS1D"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export class InMemorySessionStore {
|
|
2
|
+
records = new Map();
|
|
3
|
+
keyStr(k) {
|
|
4
|
+
return `${k.adapterId}:${k.chatId}:${k.threadId ?? ''}:${k.userId ?? ''}`;
|
|
5
|
+
}
|
|
6
|
+
findActive(key) {
|
|
7
|
+
const r = this.records.get(this.keyStr(key));
|
|
8
|
+
if (r?.state.kind !== 'active')
|
|
9
|
+
return null;
|
|
10
|
+
return toRecord(r);
|
|
11
|
+
}
|
|
12
|
+
upsert(record) {
|
|
13
|
+
this.records.set(this.keyStr(record.key), toMutable(record));
|
|
14
|
+
}
|
|
15
|
+
markSuspended(sessionId, reason) {
|
|
16
|
+
for (const r of this.records.values()) {
|
|
17
|
+
if (r.sessionId === sessionId) {
|
|
18
|
+
r.state = { kind: 'suspended', reason };
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
endSession(sessionId) {
|
|
24
|
+
this.markSuspended(sessionId, 'user_stop');
|
|
25
|
+
}
|
|
26
|
+
findIdleBefore(cutoffMs) {
|
|
27
|
+
return Array.from(this.records.values())
|
|
28
|
+
.filter((r) => r.state.kind === 'active' && r.lastTurnAtMs < cutoffMs)
|
|
29
|
+
.map(toRecord);
|
|
30
|
+
}
|
|
31
|
+
addTokenUsage(sessionId, usage) {
|
|
32
|
+
for (const r of this.records.values()) {
|
|
33
|
+
if (r.sessionId === sessionId) {
|
|
34
|
+
r.tokenInput += usage.input;
|
|
35
|
+
r.tokenOutput += usage.output;
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function toRecord(r) {
|
|
42
|
+
return {
|
|
43
|
+
key: r.key,
|
|
44
|
+
sessionId: r.sessionId,
|
|
45
|
+
state: r.state,
|
|
46
|
+
origin: r.origin,
|
|
47
|
+
createdAtMs: r.createdAtMs,
|
|
48
|
+
lastTurnAtMs: r.lastTurnAtMs,
|
|
49
|
+
tokenTotals: { input: r.tokenInput, output: r.tokenOutput },
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function toMutable(r) {
|
|
53
|
+
return {
|
|
54
|
+
key: r.key,
|
|
55
|
+
sessionId: r.sessionId,
|
|
56
|
+
state: r.state,
|
|
57
|
+
origin: r.origin,
|
|
58
|
+
createdAtMs: r.createdAtMs,
|
|
59
|
+
lastTurnAtMs: r.lastTurnAtMs,
|
|
60
|
+
tokenInput: r.tokenTotals.input,
|
|
61
|
+
tokenOutput: r.tokenTotals.output,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=in-memory-session-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in-memory-session-store.js","sourceRoot":"","sources":["../../../src/stores/in-memory-session-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { createDedupStore } from '../stores/dedup-store';
|
|
2
|
+
export { InMemorySessionStore } from '../stores/in-memory-session-store';
|
|
3
|
+
export { SqliteAdapterBindingStore } from '../stores/sqlite-binding-store';
|
|
4
|
+
export { SqlitePairRequestStore } from '../stores/sqlite-pair-request-store';
|
|
5
|
+
export { SqliteAccessPolicyStore } from '../stores/sqlite-policy-store';
|
|
6
|
+
export { SqliteSessionStore } from '../stores/sqlite-session-store';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/stores/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Level 2 — 独立 store 类,按需组合
|
|
2
|
+
export { createDedupStore } from '../stores/dedup-store';
|
|
3
|
+
export { InMemorySessionStore } from '../stores/in-memory-session-store';
|
|
4
|
+
export { SqliteAdapterBindingStore } from '../stores/sqlite-binding-store';
|
|
5
|
+
export { SqlitePairRequestStore } from '../stores/sqlite-pair-request-store';
|
|
6
|
+
export { SqliteAccessPolicyStore } from '../stores/sqlite-policy-store';
|
|
7
|
+
export { SqliteSessionStore } from '../stores/sqlite-session-store';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/stores/index.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAE5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { IAdapterBinding, IAdapterBindingRegistry, IBindingSerializer } from '@stackory/gateway-core';
|
|
2
|
+
import type { IInternalDatabaseHandle } from '../database';
|
|
3
|
+
export declare class SqliteAdapterBindingStore implements IAdapterBindingRegistry {
|
|
4
|
+
private readonly db;
|
|
5
|
+
private readonly serializers;
|
|
6
|
+
constructor(db: IInternalDatabaseHandle, serializers: ReadonlyMap<string, IBindingSerializer>);
|
|
7
|
+
add(binding: IAdapterBinding): void;
|
|
8
|
+
list(): readonly IAdapterBinding[];
|
|
9
|
+
get(adapterId: string): IAdapterBinding | undefined;
|
|
10
|
+
remove(id: string): void;
|
|
11
|
+
private rowToBinding;
|
|
12
|
+
private getSerializer;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=sqlite-binding-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-binding-store.d.ts","sourceRoot":"","sources":["../../../src/stores/sqlite-binding-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,eAAe,EACf,uBAAuB,EACvB,kBAAkB,EAClB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAG1D,qBAAa,yBAA0B,YAAW,uBAAuB;IAEvE,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,WAAW;gBADX,EAAE,EAAE,uBAAuB,EAC3B,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,kBAAkB,CAAC;IAGtE,GAAG,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI;IAcnC,IAAI,IAAI,SAAS,eAAe,EAAE;IAQlC,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAUnD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAOxB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,aAAa;CASrB"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { eq } from 'drizzle-orm';
|
|
2
|
+
import { adapterBindings } from '../schema';
|
|
3
|
+
export class SqliteAdapterBindingStore {
|
|
4
|
+
db;
|
|
5
|
+
serializers;
|
|
6
|
+
constructor(db, serializers) {
|
|
7
|
+
this.db = db;
|
|
8
|
+
this.serializers = serializers;
|
|
9
|
+
}
|
|
10
|
+
add(binding) {
|
|
11
|
+
const serializer = this.getSerializer(binding.platform);
|
|
12
|
+
const { config, secrets } = serializer.serialize(binding);
|
|
13
|
+
this.db.drizzle
|
|
14
|
+
.insert(adapterBindings)
|
|
15
|
+
.values({
|
|
16
|
+
adapterId: binding.id,
|
|
17
|
+
platform: binding.platform,
|
|
18
|
+
configJson: JSON.stringify(config),
|
|
19
|
+
secretsJson: JSON.stringify(secrets),
|
|
20
|
+
})
|
|
21
|
+
.run();
|
|
22
|
+
}
|
|
23
|
+
list() {
|
|
24
|
+
return this.db.drizzle
|
|
25
|
+
.select()
|
|
26
|
+
.from(adapterBindings)
|
|
27
|
+
.all()
|
|
28
|
+
.map((row) => this.rowToBinding(row));
|
|
29
|
+
}
|
|
30
|
+
get(adapterId) {
|
|
31
|
+
const row = this.db.drizzle
|
|
32
|
+
.select()
|
|
33
|
+
.from(adapterBindings)
|
|
34
|
+
.where(eq(adapterBindings.adapterId, adapterId))
|
|
35
|
+
.get();
|
|
36
|
+
if (!row)
|
|
37
|
+
return undefined;
|
|
38
|
+
return this.rowToBinding(row);
|
|
39
|
+
}
|
|
40
|
+
remove(id) {
|
|
41
|
+
this.db.drizzle
|
|
42
|
+
.delete(adapterBindings)
|
|
43
|
+
.where(eq(adapterBindings.adapterId, id))
|
|
44
|
+
.run();
|
|
45
|
+
}
|
|
46
|
+
rowToBinding(row) {
|
|
47
|
+
const serializer = this.getSerializer(row.platform);
|
|
48
|
+
return serializer.deserialize(row.adapterId, row.platform, JSON.parse(row.configJson), JSON.parse(row.secretsJson));
|
|
49
|
+
}
|
|
50
|
+
getSerializer(platform) {
|
|
51
|
+
const s = this.serializers.get(platform);
|
|
52
|
+
if (!s) {
|
|
53
|
+
throw new Error(`SqliteAdapterBindingStore: no serializer registered for platform "${platform}"`);
|
|
54
|
+
}
|
|
55
|
+
return s;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=sqlite-binding-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-binding-store.js","sourceRoot":"","sources":["../../../src/stores/sqlite-binding-store.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAEjC,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,OAAO,yBAAyB;IAEnB;IACA;IAFlB,YACkB,EAA2B,EAC3B,WAAoD;QADpD,OAAE,GAAF,EAAE,CAAyB;QAC3B,gBAAW,GAAX,WAAW,CAAyC;IACnE,CAAC;IAEJ,GAAG,CAAC,OAAwB;QAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACxD,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAC1D,IAAI,CAAC,EAAE,CAAC,OAAO;aACb,MAAM,CAAC,eAAe,CAAC;aACvB,MAAM,CAAC;YACP,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;YAClC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;SACpC,CAAC;aACD,GAAG,EAAE,CAAC;IACT,CAAC;IAED,IAAI;QACH,OAAO,IAAI,CAAC,EAAE,CAAC,OAAO;aACpB,MAAM,EAAE;aACR,IAAI,CAAC,eAAe,CAAC;aACrB,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;IACxC,CAAC;IAED,GAAG,CAAC,SAAiB;QACpB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO;aACzB,MAAM,EAAE;aACR,IAAI,CAAC,eAAe,CAAC;aACrB,KAAK,CAAC,EAAE,CAAC,eAAe,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;aAC/C,GAAG,EAAE,CAAC;QACR,IAAI,CAAC,GAAG;YAAE,OAAO,SAAS,CAAC;QAC3B,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,MAAM,CAAC,EAAU;QAChB,IAAI,CAAC,EAAE,CAAC,OAAO;aACb,MAAM,CAAC,eAAe,CAAC;aACvB,KAAK,CAAC,EAAE,CAAC,eAAe,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;aACxC,GAAG,EAAE,CAAC;IACT,CAAC;IAEO,YAAY,CACnB,GAAwC;QAExC,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACpD,OAAO,UAAU,CAAC,WAAW,CAC5B,GAAG,CAAC,SAAS,EACb,GAAG,CAAC,QAAQ,EACZ,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAA4B,EACrD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAA2B,CACrD,CAAC;IACH,CAAC;IAEO,aAAa,CAAC,QAAgB;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACzC,IAAI,CAAC,CAAC,EAAE,CAAC;YACR,MAAM,IAAI,KAAK,CACd,qEAAqE,QAAQ,GAAG,CAChF,CAAC;QACH,CAAC;QACD,OAAO,CAAC,CAAC;IACV,CAAC;CACD"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { IPairRequestManager } from '@stackory/gateway-core';
|
|
2
|
+
import type { IInternalDatabaseHandle } from '../database';
|
|
3
|
+
export declare class SqlitePairRequestStore implements IPairRequestManager {
|
|
4
|
+
private readonly db;
|
|
5
|
+
constructor(db: IInternalDatabaseHandle);
|
|
6
|
+
create(adapterId: string, userId: string, chatId: string): string;
|
|
7
|
+
find(code: string): ReturnType<IPairRequestManager['find']>;
|
|
8
|
+
delete(code: string): void;
|
|
9
|
+
purgeExpired(nowMs: number): number;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=sqlite-pair-request-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-pair-request-store.d.ts","sourceRoot":"","sources":["../../../src/stores/sqlite-pair-request-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAElE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAK1D,qBAAa,sBAAuB,YAAW,mBAAmB;IACrD,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,uBAAuB;IAExD,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IAiCjE,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAoB3D,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAO1B,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAOnC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { and, eq, lt } from 'drizzle-orm';
|
|
3
|
+
import { pairRequests } from '../schema';
|
|
4
|
+
const PAIR_CODE_TTL_MS = 10 * 60 * 1000;
|
|
5
|
+
export class SqlitePairRequestStore {
|
|
6
|
+
db;
|
|
7
|
+
constructor(db) {
|
|
8
|
+
this.db = db;
|
|
9
|
+
}
|
|
10
|
+
create(adapterId, userId, chatId) {
|
|
11
|
+
this.purgeExpired(Date.now());
|
|
12
|
+
const existing = this.db.drizzle
|
|
13
|
+
.select()
|
|
14
|
+
.from(pairRequests)
|
|
15
|
+
.where(and(eq(pairRequests.adapterId, adapterId), eq(pairRequests.userId, userId)))
|
|
16
|
+
.get();
|
|
17
|
+
if (existing) {
|
|
18
|
+
return existing.code;
|
|
19
|
+
}
|
|
20
|
+
const code = randomBytes(3).toString('hex').toUpperCase();
|
|
21
|
+
this.db.drizzle
|
|
22
|
+
.insert(pairRequests)
|
|
23
|
+
.values({
|
|
24
|
+
code,
|
|
25
|
+
adapterId,
|
|
26
|
+
userId,
|
|
27
|
+
chatId,
|
|
28
|
+
expiresAtMs: Date.now() + PAIR_CODE_TTL_MS,
|
|
29
|
+
})
|
|
30
|
+
.run();
|
|
31
|
+
return code;
|
|
32
|
+
}
|
|
33
|
+
find(code) {
|
|
34
|
+
const row = this.db.drizzle
|
|
35
|
+
.select()
|
|
36
|
+
.from(pairRequests)
|
|
37
|
+
.where(eq(pairRequests.code, code.toUpperCase()))
|
|
38
|
+
.get();
|
|
39
|
+
if (!row)
|
|
40
|
+
return null;
|
|
41
|
+
if (row.expiresAtMs < Date.now()) {
|
|
42
|
+
this.db.drizzle
|
|
43
|
+
.delete(pairRequests)
|
|
44
|
+
.where(eq(pairRequests.code, row.code))
|
|
45
|
+
.run();
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
return row;
|
|
49
|
+
}
|
|
50
|
+
delete(code) {
|
|
51
|
+
this.db.drizzle
|
|
52
|
+
.delete(pairRequests)
|
|
53
|
+
.where(eq(pairRequests.code, code.toUpperCase()))
|
|
54
|
+
.run();
|
|
55
|
+
}
|
|
56
|
+
purgeExpired(nowMs) {
|
|
57
|
+
const result = this.db.drizzle
|
|
58
|
+
.delete(pairRequests)
|
|
59
|
+
.where(lt(pairRequests.expiresAtMs, nowMs))
|
|
60
|
+
.run();
|
|
61
|
+
return Number(result.changes ?? 0);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=sqlite-pair-request-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-pair-request-store.js","sourceRoot":"","sources":["../../../src/stores/sqlite-pair-request-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,MAAM,gBAAgB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAExC,MAAM,OAAO,sBAAsB;IACL;IAA7B,YAA6B,EAA2B;QAA3B,OAAE,GAAF,EAAE,CAAyB;IAAG,CAAC;IAE5D,MAAM,CAAC,SAAiB,EAAE,MAAc,EAAE,MAAc;QACvD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QAE9B,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO;aAC9B,MAAM,EAAE;aACR,IAAI,CAAC,YAAY,CAAC;aAClB,KAAK,CACL,GAAG,CACF,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,SAAS,CAAC,EACrC,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAC/B,CACD;aACA,GAAG,EAAE,CAAC;QAER,IAAI,QAAQ,EAAE,CAAC;YACd,OAAO,QAAQ,CAAC,IAAI,CAAC;QACtB,CAAC;QAED,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;QAC1D,IAAI,CAAC,EAAE,CAAC,OAAO;aACb,MAAM,CAAC,YAAY,CAAC;aACpB,MAAM,CAAC;YACP,IAAI;YACJ,SAAS;YACT,MAAM;YACN,MAAM;YACN,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,gBAAgB;SAC1C,CAAC;aACD,GAAG,EAAE,CAAC;QAER,OAAO,IAAI,CAAC;IACb,CAAC;IAED,IAAI,CAAC,IAAY;QAChB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO;aACzB,MAAM,EAAE;aACR,IAAI,CAAC,YAAY,CAAC;aAClB,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;aAChD,GAAG,EAAE,CAAC;QAER,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QAEtB,IAAI,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAClC,IAAI,CAAC,EAAE,CAAC,OAAO;iBACb,MAAM,CAAC,YAAY,CAAC;iBACpB,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;iBACtC,GAAG,EAAE,CAAC;YACR,OAAO,IAAI,CAAC;QACb,CAAC;QAED,OAAO,GAAG,CAAC;IACZ,CAAC;IAED,MAAM,CAAC,IAAY;QAClB,IAAI,CAAC,EAAE,CAAC,OAAO;aACb,MAAM,CAAC,YAAY,CAAC;aACpB,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;aAChD,GAAG,EAAE,CAAC;IACT,CAAC;IAED,YAAY,CAAC,KAAa;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO;aAC5B,MAAM,CAAC,YAAY,CAAC;aACpB,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;aAC1C,GAAG,EAAE,CAAC;QACR,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;IACpC,CAAC;CACD"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IAccessPolicyStore, IChatPolicy, IChatPolicyEntry, IResolvedPolicy } from '@stackory/gateway-core';
|
|
2
|
+
import type { IInternalDatabaseHandle } from '../database';
|
|
3
|
+
export declare class SqliteAccessPolicyStore implements IAccessPolicyStore {
|
|
4
|
+
private readonly db;
|
|
5
|
+
constructor(db: IInternalDatabaseHandle);
|
|
6
|
+
findChatPolicy(adapterId: string, chatId: string): IChatPolicy | undefined;
|
|
7
|
+
upsertChatPolicy(adapterId: string, chatId: string, policy: IChatPolicy, by: string): void;
|
|
8
|
+
deleteChatPolicy(adapterId: string, chatId: string): void;
|
|
9
|
+
listChatPolicies(adapterId: string): readonly IChatPolicyEntry[];
|
|
10
|
+
resolveForChat(adapterId: string, chatId: string, _chatType: 'p2p' | 'group'): IResolvedPolicy;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=sqlite-policy-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-policy-store.d.ts","sourceRoot":"","sources":["../../../src/stores/sqlite-policy-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,kBAAkB,EAClB,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAW1D,qBAAa,uBAAwB,YAAW,kBAAkB;IACrD,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,uBAAuB;IAExD,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAY1E,gBAAgB,CACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,EACnB,EAAE,EAAE,MAAM,GACR,IAAI;IA2BP,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IASzD,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,gBAAgB,EAAE;IAShE,cAAc,CACb,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,KAAK,GAAG,OAAO,GACxB,eAAe;CAalB"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { and, eq } from 'drizzle-orm';
|
|
2
|
+
import { chatPolicy } from '../schema';
|
|
3
|
+
const DENY_ALL = {
|
|
4
|
+
source: 'default',
|
|
5
|
+
policy: 'allowlist',
|
|
6
|
+
requireMention: false,
|
|
7
|
+
effectiveAllowlist: [],
|
|
8
|
+
effectiveBlacklist: [],
|
|
9
|
+
};
|
|
10
|
+
export class SqliteAccessPolicyStore {
|
|
11
|
+
db;
|
|
12
|
+
constructor(db) {
|
|
13
|
+
this.db = db;
|
|
14
|
+
}
|
|
15
|
+
findChatPolicy(adapterId, chatId) {
|
|
16
|
+
const row = this.db.drizzle
|
|
17
|
+
.select()
|
|
18
|
+
.from(chatPolicy)
|
|
19
|
+
.where(and(eq(chatPolicy.adapterId, adapterId), eq(chatPolicy.chatId, chatId)))
|
|
20
|
+
.get();
|
|
21
|
+
if (!row)
|
|
22
|
+
return undefined;
|
|
23
|
+
return rowToPolicy(row);
|
|
24
|
+
}
|
|
25
|
+
upsertChatPolicy(adapterId, chatId, policy, by) {
|
|
26
|
+
this.db.drizzle
|
|
27
|
+
.insert(chatPolicy)
|
|
28
|
+
.values({
|
|
29
|
+
adapterId,
|
|
30
|
+
chatId,
|
|
31
|
+
policy: policy.policy,
|
|
32
|
+
requireMention: policy.requireMention ? 1 : 0,
|
|
33
|
+
allowlistJson: JSON.stringify(policy.allowlist),
|
|
34
|
+
blacklistJson: JSON.stringify(policy.blacklist),
|
|
35
|
+
updatedBy: by,
|
|
36
|
+
updatedAtMs: Date.now(),
|
|
37
|
+
})
|
|
38
|
+
.onConflictDoUpdate({
|
|
39
|
+
target: [chatPolicy.adapterId, chatPolicy.chatId],
|
|
40
|
+
set: {
|
|
41
|
+
policy: policy.policy,
|
|
42
|
+
requireMention: policy.requireMention ? 1 : 0,
|
|
43
|
+
allowlistJson: JSON.stringify(policy.allowlist),
|
|
44
|
+
blacklistJson: JSON.stringify(policy.blacklist),
|
|
45
|
+
updatedBy: by,
|
|
46
|
+
updatedAtMs: Date.now(),
|
|
47
|
+
},
|
|
48
|
+
})
|
|
49
|
+
.run();
|
|
50
|
+
}
|
|
51
|
+
deleteChatPolicy(adapterId, chatId) {
|
|
52
|
+
this.db.drizzle
|
|
53
|
+
.delete(chatPolicy)
|
|
54
|
+
.where(and(eq(chatPolicy.adapterId, adapterId), eq(chatPolicy.chatId, chatId)))
|
|
55
|
+
.run();
|
|
56
|
+
}
|
|
57
|
+
listChatPolicies(adapterId) {
|
|
58
|
+
return this.db.drizzle
|
|
59
|
+
.select()
|
|
60
|
+
.from(chatPolicy)
|
|
61
|
+
.where(eq(chatPolicy.adapterId, adapterId))
|
|
62
|
+
.all()
|
|
63
|
+
.map(rowToEntry);
|
|
64
|
+
}
|
|
65
|
+
resolveForChat(adapterId, chatId, _chatType) {
|
|
66
|
+
const policy = this.findChatPolicy(adapterId, chatId);
|
|
67
|
+
if (!policy) {
|
|
68
|
+
return DENY_ALL;
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
source: 'chat',
|
|
72
|
+
policy: policy.policy,
|
|
73
|
+
requireMention: policy.requireMention,
|
|
74
|
+
effectiveAllowlist: policy.allowlist,
|
|
75
|
+
effectiveBlacklist: policy.blacklist,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function rowToPolicy(row) {
|
|
80
|
+
return {
|
|
81
|
+
policy: row.policy,
|
|
82
|
+
requireMention: row.requireMention === 1,
|
|
83
|
+
allowlist: JSON.parse(row.allowlistJson),
|
|
84
|
+
blacklist: JSON.parse(row.blacklistJson),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function rowToEntry(row) {
|
|
88
|
+
return {
|
|
89
|
+
...rowToPolicy(row),
|
|
90
|
+
chatId: row.chatId,
|
|
91
|
+
updatedBy: row.updatedBy,
|
|
92
|
+
updatedAtMs: row.updatedAtMs,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=sqlite-policy-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-policy-store.js","sourceRoot":"","sources":["../../../src/stores/sqlite-policy-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ISessionKey, ISessionRecord, ISessionStore, ITokenUsage } from '@stackory/gateway-core';
|
|
2
|
+
import type { IInternalDatabaseHandle } from '../database';
|
|
3
|
+
export declare class SqliteSessionStore implements ISessionStore {
|
|
4
|
+
private readonly db;
|
|
5
|
+
constructor(db: IInternalDatabaseHandle);
|
|
6
|
+
findActive(key: ISessionKey): ISessionRecord | null;
|
|
7
|
+
upsert(record: ISessionRecord): void;
|
|
8
|
+
markSuspended(sessionId: string, reason: 'user_stop' | 'fatal_error'): void;
|
|
9
|
+
endSession(sessionId: string): void;
|
|
10
|
+
findIdleBefore(cutoffMs: number): readonly ISessionRecord[];
|
|
11
|
+
addTokenUsage(sessionId: string, usage: ITokenUsage): void;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=sqlite-session-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-session-store.d.ts","sourceRoot":"","sources":["../../../src/stores/sqlite-session-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,WAAW,EACX,cAAc,EAGd,aAAa,EACb,WAAW,EACX,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAG1D,qBAAa,kBAAmB,YAAW,aAAa;IAC3C,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,uBAAuB;IAExD,UAAU,CAAC,GAAG,EAAE,WAAW,GAAG,cAAc,GAAG,IAAI;IAenD,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAqCpC,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,aAAa,GAAG,IAAI;IAW3E,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAInC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,cAAc,EAAE;IAc3D,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI;CAU1D"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { and, eq, sql } from 'drizzle-orm';
|
|
2
|
+
import { sessions } from '../schema';
|
|
3
|
+
export class SqliteSessionStore {
|
|
4
|
+
db;
|
|
5
|
+
constructor(db) {
|
|
6
|
+
this.db = db;
|
|
7
|
+
}
|
|
8
|
+
findActive(key) {
|
|
9
|
+
const row = this.db.drizzle
|
|
10
|
+
.select()
|
|
11
|
+
.from(sessions)
|
|
12
|
+
.where(and(eq(sessions.adapterId, key.adapterId), eq(sessions.chatId, key.chatId)))
|
|
13
|
+
.get();
|
|
14
|
+
if (row?.stateKind !== 'active')
|
|
15
|
+
return null;
|
|
16
|
+
return rowToRecord(row);
|
|
17
|
+
}
|
|
18
|
+
upsert(record) {
|
|
19
|
+
this.db.drizzle
|
|
20
|
+
.insert(sessions)
|
|
21
|
+
.values({
|
|
22
|
+
adapterId: record.key.adapterId,
|
|
23
|
+
chatId: record.key.chatId,
|
|
24
|
+
threadId: record.key.threadId ?? '',
|
|
25
|
+
userId: record.key.userId ?? '',
|
|
26
|
+
sessionId: record.sessionId,
|
|
27
|
+
stateKind: record.state.kind,
|
|
28
|
+
stateData: JSON.stringify(record.state),
|
|
29
|
+
originJson: JSON.stringify(record.origin),
|
|
30
|
+
createdAtMs: record.createdAtMs,
|
|
31
|
+
lastTurnAtMs: record.lastTurnAtMs,
|
|
32
|
+
tokenInput: record.tokenTotals.input,
|
|
33
|
+
tokenOutput: record.tokenTotals.output,
|
|
34
|
+
})
|
|
35
|
+
.onConflictDoUpdate({
|
|
36
|
+
target: [
|
|
37
|
+
sessions.adapterId,
|
|
38
|
+
sessions.chatId,
|
|
39
|
+
sessions.threadId,
|
|
40
|
+
sessions.userId,
|
|
41
|
+
],
|
|
42
|
+
set: {
|
|
43
|
+
sessionId: record.sessionId,
|
|
44
|
+
stateKind: record.state.kind,
|
|
45
|
+
stateData: JSON.stringify(record.state),
|
|
46
|
+
originJson: JSON.stringify(record.origin),
|
|
47
|
+
lastTurnAtMs: record.lastTurnAtMs,
|
|
48
|
+
tokenInput: record.tokenTotals.input,
|
|
49
|
+
tokenOutput: record.tokenTotals.output,
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
.run();
|
|
53
|
+
}
|
|
54
|
+
markSuspended(sessionId, reason) {
|
|
55
|
+
this.db.drizzle
|
|
56
|
+
.update(sessions)
|
|
57
|
+
.set({
|
|
58
|
+
stateKind: 'suspended',
|
|
59
|
+
stateData: JSON.stringify({ kind: 'suspended', reason }),
|
|
60
|
+
})
|
|
61
|
+
.where(eq(sessions.sessionId, sessionId))
|
|
62
|
+
.run();
|
|
63
|
+
}
|
|
64
|
+
endSession(sessionId) {
|
|
65
|
+
this.markSuspended(sessionId, 'user_stop');
|
|
66
|
+
}
|
|
67
|
+
findIdleBefore(cutoffMs) {
|
|
68
|
+
return this.db.drizzle
|
|
69
|
+
.select()
|
|
70
|
+
.from(sessions)
|
|
71
|
+
.where(and(eq(sessions.stateKind, 'active'), sql `last_turn_at_ms < ${cutoffMs}`))
|
|
72
|
+
.all()
|
|
73
|
+
.map(rowToRecord);
|
|
74
|
+
}
|
|
75
|
+
addTokenUsage(sessionId, usage) {
|
|
76
|
+
this.db.drizzle
|
|
77
|
+
.update(sessions)
|
|
78
|
+
.set({
|
|
79
|
+
tokenInput: sql `token_input + ${usage.input}`,
|
|
80
|
+
tokenOutput: sql `token_output + ${usage.output}`,
|
|
81
|
+
})
|
|
82
|
+
.where(eq(sessions.sessionId, sessionId))
|
|
83
|
+
.run();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function rowToRecord(row) {
|
|
87
|
+
const state = JSON.parse(row.stateData);
|
|
88
|
+
const adapterId = row.adapterId;
|
|
89
|
+
return {
|
|
90
|
+
key: {
|
|
91
|
+
adapterId,
|
|
92
|
+
chatId: row.chatId,
|
|
93
|
+
threadId: row.threadId || undefined,
|
|
94
|
+
userId: row.userId || undefined,
|
|
95
|
+
},
|
|
96
|
+
sessionId: row.sessionId,
|
|
97
|
+
state,
|
|
98
|
+
origin: JSON.parse(row.originJson),
|
|
99
|
+
createdAtMs: row.createdAtMs,
|
|
100
|
+
lastTurnAtMs: row.lastTurnAtMs,
|
|
101
|
+
tokenTotals: {
|
|
102
|
+
input: row.tokenInput,
|
|
103
|
+
output: row.tokenOutput,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=sqlite-session-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-session-store.js","sourceRoot":"","sources":["../../../src/stores/sqlite-session-store.ts"],"names":[],"mappings":"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"}
|