@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.
Files changed (62) hide show
  1. package/README.md +49 -0
  2. package/dist/esm/database/index.d.ts +3 -0
  3. package/dist/esm/database/index.d.ts.map +1 -0
  4. package/dist/esm/database/index.js +3 -0
  5. package/dist/esm/database/index.js.map +1 -0
  6. package/dist/esm/database.d.ts +23 -0
  7. package/dist/esm/database.d.ts.map +1 -0
  8. package/dist/esm/database.js +53 -0
  9. package/dist/esm/database.js.map +1 -0
  10. package/dist/esm/gateway-database.d.ts +6 -0
  11. package/dist/esm/gateway-database.d.ts.map +1 -0
  12. package/dist/esm/gateway-database.js +19 -0
  13. package/dist/esm/gateway-database.js.map +1 -0
  14. package/dist/esm/index.d.ts +2 -0
  15. package/dist/esm/index.d.ts.map +1 -0
  16. package/dist/esm/index.js +3 -0
  17. package/dist/esm/index.js.map +1 -0
  18. package/dist/esm/migrations/generated.d.ts +3 -0
  19. package/dist/esm/migrations/generated.d.ts.map +1 -0
  20. package/dist/esm/migrations/generated.js +7 -0
  21. package/dist/esm/migrations/generated.js.map +1 -0
  22. package/dist/esm/migrations/index.d.ts +3 -0
  23. package/dist/esm/migrations/index.d.ts.map +1 -0
  24. package/dist/esm/migrations/index.js +2 -0
  25. package/dist/esm/migrations/index.js.map +1 -0
  26. package/dist/esm/migrations/types.d.ts +5 -0
  27. package/dist/esm/migrations/types.d.ts.map +1 -0
  28. package/dist/esm/migrations/types.js +2 -0
  29. package/dist/esm/migrations/types.js.map +1 -0
  30. package/dist/esm/schema.d.ts +579 -0
  31. package/dist/esm/schema.d.ts.map +1 -0
  32. package/dist/esm/schema.js +91 -0
  33. package/dist/esm/schema.js.map +1 -0
  34. package/dist/esm/stores/dedup-store.d.ts +14 -0
  35. package/dist/esm/stores/dedup-store.d.ts.map +1 -0
  36. package/dist/esm/stores/dedup-store.js +62 -0
  37. package/dist/esm/stores/dedup-store.js.map +1 -0
  38. package/dist/esm/stores/in-memory-session-store.d.ts +12 -0
  39. package/dist/esm/stores/in-memory-session-store.d.ts.map +1 -0
  40. package/dist/esm/stores/in-memory-session-store.js +64 -0
  41. package/dist/esm/stores/in-memory-session-store.js.map +1 -0
  42. package/dist/esm/stores/index.d.ts +7 -0
  43. package/dist/esm/stores/index.d.ts.map +1 -0
  44. package/dist/esm/stores/index.js +8 -0
  45. package/dist/esm/stores/index.js.map +1 -0
  46. package/dist/esm/stores/sqlite-binding-store.d.ts +14 -0
  47. package/dist/esm/stores/sqlite-binding-store.d.ts.map +1 -0
  48. package/dist/esm/stores/sqlite-binding-store.js +58 -0
  49. package/dist/esm/stores/sqlite-binding-store.js.map +1 -0
  50. package/dist/esm/stores/sqlite-pair-request-store.d.ts +11 -0
  51. package/dist/esm/stores/sqlite-pair-request-store.d.ts.map +1 -0
  52. package/dist/esm/stores/sqlite-pair-request-store.js +64 -0
  53. package/dist/esm/stores/sqlite-pair-request-store.js.map +1 -0
  54. package/dist/esm/stores/sqlite-policy-store.d.ts +12 -0
  55. package/dist/esm/stores/sqlite-policy-store.d.ts.map +1 -0
  56. package/dist/esm/stores/sqlite-policy-store.js +95 -0
  57. package/dist/esm/stores/sqlite-policy-store.js.map +1 -0
  58. package/dist/esm/stores/sqlite-session-store.d.ts +13 -0
  59. package/dist/esm/stores/sqlite-session-store.d.ts.map +1 -0
  60. package/dist/esm/stores/sqlite-session-store.js +107 -0
  61. package/dist/esm/stores/sqlite-session-store.js.map +1 -0
  62. 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":"AAMA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAEtC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,MAAM,QAAQ,GAAoB;IACjC,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,WAAW;IACnB,cAAc,EAAE,KAAK;IACrB,kBAAkB,EAAE,EAAE;IACtB,kBAAkB,EAAE,EAAE;CACtB,CAAC;AAEF,MAAM,OAAO,uBAAuB;IACN;IAA7B,YAA6B,EAA2B;QAA3B,OAAE,GAAF,EAAE,CAAyB;IAAG,CAAC;IAE5D,cAAc,CAAC,SAAiB,EAAE,MAAc;QAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO;aACzB,MAAM,EAAE;aACR,IAAI,CAAC,UAAU,CAAC;aAChB,KAAK,CACL,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CACvE;aACA,GAAG,EAAE,CAAC;QACR,IAAI,CAAC,GAAG;YAAE,OAAO,SAAS,CAAC;QAC3B,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAED,gBAAgB,CACf,SAAiB,EACjB,MAAc,EACd,MAAmB,EACnB,EAAU;QAEV,IAAI,CAAC,EAAE,CAAC,OAAO;aACb,MAAM,CAAC,UAAU,CAAC;aAClB,MAAM,CAAC;YACP,SAAS;YACT,MAAM;YACN,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,cAAc,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC7C,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC;YAC/C,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC;YAC/C,SAAS,EAAE,EAAE;YACb,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;SACvB,CAAC;aACD,kBAAkB,CAAC;YACnB,MAAM,EAAE,CAAC,UAAU,CAAC,SAAS,EAAE,UAAU,CAAC,MAAM,CAAC;YACjD,GAAG,EAAE;gBACJ,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,cAAc,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC7C,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC;gBAC/C,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC;gBAC/C,SAAS,EAAE,EAAE;gBACb,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;aACvB;SACD,CAAC;aACD,GAAG,EAAE,CAAC;IACT,CAAC;IAED,gBAAgB,CAAC,SAAiB,EAAE,MAAc;QACjD,IAAI,CAAC,EAAE,CAAC,OAAO;aACb,MAAM,CAAC,UAAU,CAAC;aAClB,KAAK,CACL,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CACvE;aACA,GAAG,EAAE,CAAC;IACT,CAAC;IAED,gBAAgB,CAAC,SAAiB;QACjC,OAAO,IAAI,CAAC,EAAE,CAAC,OAAO;aACpB,MAAM,EAAE;aACR,IAAI,CAAC,UAAU,CAAC;aAChB,KAAK,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;aAC1C,GAAG,EAAE;aACL,GAAG,CAAC,UAAU,CAAC,CAAC;IACnB,CAAC;IAED,cAAc,CACb,SAAiB,EACjB,MAAc,EACd,SAA0B;QAE1B,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACtD,IAAI,CAAC,MAAM,EAAE,CAAC;YACb,OAAO,QAAQ,CAAC;QACjB,CAAC;QACD,OAAO;YACN,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,cAAc,EAAE,MAAM,CAAC,cAAc;YACrC,kBAAkB,EAAE,MAAM,CAAC,SAAS;YACpC,kBAAkB,EAAE,MAAM,CAAC,SAAS;SACpC,CAAC;IACH,CAAC;CACD;AAED,SAAS,WAAW,CAAC,GAAmC;IACvD,OAAO;QACN,MAAM,EAAE,GAAG,CAAC,MAA4C;QACxD,cAAc,EAAE,GAAG,CAAC,cAAc,KAAK,CAAC;QACxC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,CAAa;QACpD,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,CAAa;KACpD,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,GAAmC;IACtD,OAAO;QACN,GAAG,WAAW,CAAC,GAAG,CAAC;QACnB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,WAAW,EAAE,GAAG,CAAC,WAAW;KAC5B,CAAC;AACH,CAAC"}
@@ -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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"}