@elizaos/plugin-sql 2.0.0-alpha.2 → 2.0.0-alpha.20

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 (108) hide show
  1. package/dist/base.d.ts +1102 -0
  2. package/dist/browser/index.browser.js +3887 -1999
  3. package/dist/browser/index.browser.js.map +32 -20
  4. package/dist/browser/index.d.ts +2 -2
  5. package/dist/cjs/index.d.ts +2 -0
  6. package/dist/cjs/index.node.cjs +8184 -0
  7. package/dist/cjs/index.node.cjs.map +67 -0
  8. package/dist/index.d.ts +4 -2
  9. package/dist/index.js +2 -0
  10. package/dist/index.node.d.ts +17 -0
  11. package/dist/migration-service.d.ts +17 -0
  12. package/dist/migrations.d.ts +15 -0
  13. package/dist/node/index.d.ts +2 -2
  14. package/dist/node/index.node.js +4411 -8649
  15. package/dist/node/index.node.js.map +34 -117
  16. package/dist/pg/adapter.d.ts +41 -0
  17. package/dist/pg/manager.d.ts +14 -0
  18. package/dist/pglite/adapter.d.ts +23 -0
  19. package/dist/pglite/errors.d.ts +20 -0
  20. package/dist/pglite/manager.d.ts +25 -0
  21. package/dist/rls.d.ts +13 -0
  22. package/dist/runtime-migrator/crypto-utils.d.ts +25 -0
  23. package/dist/runtime-migrator/drizzle-adapters/database-introspector.d.ts +58 -0
  24. package/dist/runtime-migrator/drizzle-adapters/diff-calculator.d.ts +77 -0
  25. package/dist/runtime-migrator/drizzle-adapters/snapshot-generator.d.ts +21 -0
  26. package/dist/runtime-migrator/drizzle-adapters/sql-generator.d.ts +38 -0
  27. package/dist/runtime-migrator/extension-manager.d.ts +6 -0
  28. package/dist/runtime-migrator/index.d.ts +8 -0
  29. package/dist/runtime-migrator/runtime-migrator.d.ts +95 -0
  30. package/dist/runtime-migrator/schema-transformer.d.ts +18 -0
  31. package/dist/runtime-migrator/storage/journal-storage.d.ts +10 -0
  32. package/dist/runtime-migrator/storage/migration-tracker.d.ts +13 -0
  33. package/dist/runtime-migrator/storage/snapshot-storage.d.ts +9 -0
  34. package/dist/runtime-migrator/types.d.ts +157 -0
  35. package/dist/schema/agent.d.ts +344 -0
  36. package/dist/schema/approvalRequests.d.ts +277 -0
  37. package/dist/schema/authAuditEvent.d.ts +153 -0
  38. package/dist/schema/authBootstrapJti.d.ts +49 -0
  39. package/dist/schema/authIdentity.d.ts +121 -0
  40. package/dist/schema/authOwnerBinding.d.ts +168 -0
  41. package/dist/schema/authOwnerLoginToken.d.ts +122 -0
  42. package/dist/schema/authSession.d.ts +225 -0
  43. package/dist/schema/cache.d.ts +97 -0
  44. package/dist/schema/channel.d.ts +177 -0
  45. package/dist/schema/channelParticipant.d.ts +41 -0
  46. package/dist/schema/component.d.ts +163 -0
  47. package/dist/schema/embedding.d.ts +204 -0
  48. package/dist/schema/entity.d.ts +125 -0
  49. package/dist/schema/entityIdentity.d.ts +577 -0
  50. package/dist/schema/index.d.ts +34 -0
  51. package/dist/schema/log.d.ts +114 -0
  52. package/dist/schema/longTermMemories.d.ts +254 -0
  53. package/dist/schema/memory.d.ts +185 -0
  54. package/dist/schema/memoryAccessLogs.d.ts +109 -0
  55. package/dist/schema/message.d.ts +194 -0
  56. package/dist/schema/messageServer.d.ts +126 -0
  57. package/dist/schema/messageServerAgent.d.ts +41 -0
  58. package/dist/schema/pairingAllowlist.d.ts +113 -0
  59. package/dist/schema/pairingRequest.d.ts +147 -0
  60. package/dist/schema/participant.d.ts +114 -0
  61. package/dist/schema/relationship.d.ts +156 -0
  62. package/dist/schema/room.d.ts +195 -0
  63. package/dist/schema/server.d.ts +64 -0
  64. package/dist/schema/sessionSummaries.d.ts +273 -0
  65. package/dist/schema/tasks.d.ts +225 -0
  66. package/dist/schema/types.d.ts +68 -0
  67. package/dist/schema/world.d.ts +114 -0
  68. package/dist/services/advanced-memory-storage.d.ts +36 -0
  69. package/dist/types.d.ts +13 -0
  70. package/dist/utils/string-to-uuid.d.ts +2 -0
  71. package/dist/utils.d.ts +4 -0
  72. package/dist/utils.node.d.ts +4 -0
  73. package/drizzle/index.ts +17 -0
  74. package/package.json +50 -17
  75. package/schema/agent.ts +50 -0
  76. package/schema/approvalRequests.ts +57 -0
  77. package/schema/authAuditEvent.ts +29 -0
  78. package/schema/authBootstrapJti.ts +18 -0
  79. package/schema/authIdentity.ts +35 -0
  80. package/schema/authOwnerBinding.ts +43 -0
  81. package/schema/authOwnerLoginToken.ts +50 -0
  82. package/schema/authSession.ts +44 -0
  83. package/schema/cache.ts +22 -0
  84. package/schema/channel.ts +19 -0
  85. package/schema/channelParticipant.ts +13 -0
  86. package/schema/component.ts +37 -0
  87. package/schema/embedding.ts +73 -0
  88. package/schema/entity.ts +28 -0
  89. package/schema/entityIdentity.ts +142 -0
  90. package/schema/index.ts +41 -0
  91. package/schema/log.ts +38 -0
  92. package/schema/longTermMemories.ts +27 -0
  93. package/schema/memory.ts +103 -0
  94. package/schema/memoryAccessLogs.ts +19 -0
  95. package/schema/message.ts +24 -0
  96. package/schema/messageServer.ts +12 -0
  97. package/schema/messageServerAgent.ts +16 -0
  98. package/schema/pairingAllowlist.ts +36 -0
  99. package/schema/pairingRequest.ts +46 -0
  100. package/schema/participant.ts +43 -0
  101. package/schema/relationship.ts +50 -0
  102. package/schema/room.ts +37 -0
  103. package/schema/server.ts +14 -0
  104. package/schema/sessionSummaries.ts +27 -0
  105. package/schema/tasks.ts +24 -0
  106. package/schema/types.ts +42 -0
  107. package/schema/world.ts +20 -0
  108. package/types.ts +19 -0
@@ -0,0 +1,36 @@
1
+ import { type IAgentRuntime, type MemoryStorageProvider, Service, type UUID } from "@elizaos/core";
2
+ type LongTermMemoryRecord = Awaited<ReturnType<MemoryStorageProvider["storeLongTermMemory"]>>;
3
+ type LongTermMemoryInput = Parameters<MemoryStorageProvider["storeLongTermMemory"]>[0];
4
+ type LongTermMemoryCategory = LongTermMemoryRecord["category"];
5
+ type SessionSummaryRecord = Awaited<ReturnType<MemoryStorageProvider["storeSessionSummary"]>>;
6
+ type SessionSummaryInput = Parameters<MemoryStorageProvider["storeSessionSummary"]>[0];
7
+ export declare class AdvancedMemoryStorageService extends Service implements MemoryStorageProvider {
8
+ static serviceType: "memoryStorage";
9
+ capabilityDescription: string;
10
+ static start(runtime: IAgentRuntime): Promise<Service>;
11
+ initialize(runtime: IAgentRuntime): Promise<void>;
12
+ stop(): Promise<void>;
13
+ private getMemoryWorldId;
14
+ private getLongTermRoomId;
15
+ private ensureMemoryWorld;
16
+ private ensureLongTermRoom;
17
+ private getEntityResolutionService;
18
+ private getIdentityGroup;
19
+ private getAnchorEntityId;
20
+ private parseLongTermMemory;
21
+ private parseSessionSummary;
22
+ private sortLongTermMemories;
23
+ private sortSessionSummaries;
24
+ storeLongTermMemory(memory: LongTermMemoryInput): Promise<LongTermMemoryRecord>;
25
+ getLongTermMemories(agentId: UUID, entityId: UUID, opts?: {
26
+ category?: LongTermMemoryCategory;
27
+ limit?: number;
28
+ }): Promise<LongTermMemoryRecord[]>;
29
+ updateLongTermMemory(id: UUID, agentId: UUID, entityId: UUID, updates: Partial<Omit<LongTermMemoryRecord, "id" | "agentId" | "entityId" | "createdAt">>): Promise<void>;
30
+ deleteLongTermMemory(id: UUID, agentId: UUID, entityId: UUID): Promise<void>;
31
+ storeSessionSummary(summary: SessionSummaryInput): Promise<SessionSummaryRecord>;
32
+ getCurrentSessionSummary(agentId: UUID, roomId: UUID): Promise<SessionSummaryRecord | null>;
33
+ updateSessionSummary(id: UUID, agentId: UUID, roomId: UUID, updates: Partial<Omit<SessionSummaryRecord, "id" | "agentId" | "roomId" | "createdAt" | "updatedAt">>): Promise<void>;
34
+ getSessionSummaries(agentId: UUID, roomId: UUID, limit?: number): Promise<SessionSummaryRecord[]>;
35
+ }
36
+ export {};
@@ -0,0 +1,13 @@
1
+ import type { IDatabaseAdapter } from "@elizaos/core";
2
+ import type { NodePgDatabase } from "drizzle-orm/node-postgres";
3
+ import type { PgliteDatabase } from "drizzle-orm/pglite";
4
+ export type DrizzleDatabase = NodePgDatabase | PgliteDatabase;
5
+ export interface IDatabaseClientManager<T> {
6
+ initialize(): Promise<void>;
7
+ getConnection(): T;
8
+ close(): Promise<void>;
9
+ }
10
+ export declare function getDb(adapter: IDatabaseAdapter): DrizzleDatabase;
11
+ export declare function getRow<T>(result: {
12
+ rows: unknown[];
13
+ }, index?: number): T | undefined;
@@ -0,0 +1,2 @@
1
+ import type { UUID } from "@elizaos/core";
2
+ export declare function stringToUuid(target: string | number): UUID;
@@ -0,0 +1,4 @@
1
+ export declare function expandTildePath(filepath: string): string;
2
+ export declare function resolveEnvFile(startDir?: string): string;
3
+ export declare function resolvePgliteDir(dir?: string, fallbackDir?: string): string;
4
+ export declare function sanitizeJsonObject(value: unknown, seen?: WeakSet<object>): unknown;
@@ -0,0 +1,4 @@
1
+ export declare function expandTildePath(filepath: string): string;
2
+ export declare function resolveEnvFile(startDir?: string): string;
3
+ export declare function resolvePgliteDir(dir?: string, fallbackDir?: string): string;
4
+ export declare function sanitizeJsonObject(value: unknown, seen?: WeakSet<object>): unknown;
@@ -0,0 +1,17 @@
1
+ export {
2
+ and,
3
+ asc,
4
+ count,
5
+ desc,
6
+ eq,
7
+ gt,
8
+ gte,
9
+ inArray,
10
+ isNull,
11
+ lt,
12
+ lte,
13
+ ne,
14
+ or,
15
+ type SQL,
16
+ sql,
17
+ } from "drizzle-orm";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elizaos/plugin-sql",
3
- "version": "2.0.0-alpha.2",
3
+ "version": "2.0.0-alpha.20",
4
4
  "type": "module",
5
5
  "main": "dist/node/index.node.js",
6
6
  "module": "dist/node/index.node.js",
@@ -32,45 +32,67 @@
32
32
  "default": "./dist/node/index.node.js"
33
33
  },
34
34
  "default": "./dist/node/index.node.js"
35
+ },
36
+ "./schema": {
37
+ "types": "./schema/index.ts",
38
+ "import": "./schema/index.ts",
39
+ "default": "./schema/index.ts"
40
+ },
41
+ "./drizzle": {
42
+ "types": "./drizzle/index.ts",
43
+ "import": "./drizzle/index.ts",
44
+ "default": "./drizzle/index.ts"
45
+ },
46
+ "./types": {
47
+ "types": "./types.ts",
48
+ "import": "./types.ts",
49
+ "default": "./types.ts"
35
50
  }
36
51
  },
37
52
  "sideEffects": false,
38
53
  "files": [
39
54
  "dist",
40
55
  "drizzle",
41
- "types"
56
+ "schema",
57
+ "types.ts"
42
58
  ],
43
59
  "dependencies": {
44
- "@electric-sql/pglite": "^0.3.3",
45
- "@elizaos/core": "2.0.0-alpha.2",
60
+ "@electric-sql/pglite": "^0.4.0",
61
+ "@elizaos/core": "^2.0.0-alpha.537",
62
+ "@neondatabase/serverless": "^1.1.0",
46
63
  "dotenv": "^17.2.3",
47
64
  "drizzle-kit": "^0.31.8",
48
- "drizzle-orm": "^0.45.1",
65
+ "drizzle-orm": "0.45.2",
49
66
  "pg": "^8.16.3",
50
- "uuid": "^13.0.0"
67
+ "uuid": "^14.0.0",
68
+ "ws": "^8.18.3"
51
69
  },
52
70
  "devDependencies": {
53
- "@biomejs/biome": "^2.3.11",
71
+ "@types/bun": "^1.3.5",
72
+ "@biomejs/biome": "^2.4.14",
54
73
  "@types/node": "^25.0.3",
55
74
  "@types/pg": "^8.15.6",
56
- "typescript": "^5.9.3"
75
+ "@types/ws": "^8.18.1",
76
+ "typescript": "^6.0.0",
77
+ "vitest": "^4.0.0"
57
78
  },
58
79
  "scripts": {
59
80
  "dev": "bun run build.ts --watch",
60
81
  "migrate:generate": "drizzle-kit generate",
61
82
  "migrate": "drizzle-kit migrate",
62
- "typecheck": "tsc --noEmit -p tsconfig.json || true",
83
+ "typecheck": "tsc --noEmit -p tsconfig.json",
63
84
  "clean": "rm -rf dist .turbo node_modules .turbo-tsconfig.json *.tsbuildinfo",
64
- "format": "bunx @biomejs/biome format --write .",
65
- "format:check": "bunx @biomejs/biome format .",
66
- "lint": "bunx @biomejs/biome check --write --unsafe .",
67
- "lint:check": "bunx @biomejs/biome check .",
68
- "test": "vitest run __tests__/unit/",
69
- "test:unit": "vitest run __tests__/unit/",
70
- "test:integration": "echo 'Integration tests require scripts/run-integration-tests.sh - skipping'",
85
+ "format": "bunx @biomejs/biome format --write --config-path ./biome.json .",
86
+ "format:check": "bunx @biomejs/biome format --config-path ./biome.json .",
87
+ "lint": "bunx @biomejs/biome check --write --config-path ./biome.json .",
88
+ "lint:check": "bunx @biomejs/biome check --config-path ./biome.json .",
89
+ "test": "bun run test:real",
90
+ "test:unit": "echo 'unit-only sql tests removed; use bun run test:real'",
91
+ "test:integration": "vitest run __tests__/integration/",
71
92
  "test:integration:postgres": "bash scripts/run-integration-tests.sh --postgres",
72
93
  "test:migration": "vitest run __tests__/migration/",
73
94
  "test:migration:postgres": "vitest run __tests__/migration/",
95
+ "test:real": "bun run test:integration && bun run test:migration",
74
96
  "test:e2e:upgrade": "bash __tests__/migration/e2e/run-upgrade-test.sh",
75
97
  "test:watch": "vitest",
76
98
  "test:coverage": "vitest run --coverage",
@@ -78,5 +100,16 @@
78
100
  "build": "bun run build.ts",
79
101
  "build:ts": "bun run build.ts"
80
102
  },
81
- "gitHead": "bc6cac8d36845d7cbde51a64307c6a57c16378ad"
103
+ "gitHead": "255e37c0e4a76da0b776219db5ebb9dadf20e89f",
104
+ "eliza": {
105
+ "platforms": [
106
+ "browser",
107
+ "node"
108
+ ],
109
+ "runtime": "both",
110
+ "platformDetails": {
111
+ "browser": "Browser-compatible build available via exports.browser",
112
+ "node": "Node.js build available via exports.node"
113
+ }
114
+ }
82
115
  }
@@ -0,0 +1,50 @@
1
+ import type { MessageExample } from "@elizaos/core";
2
+ import { sql } from "drizzle-orm";
3
+ import { boolean, jsonb, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
4
+
5
+ /**
6
+ * Represents a table for storing agent data.
7
+ *
8
+ * @type {Table}
9
+ */
10
+ export const agentTable = pgTable("agents", {
11
+ id: uuid("id").primaryKey().defaultRandom(),
12
+ enabled: boolean("enabled").default(true).notNull(),
13
+ server_id: uuid("server_id"),
14
+ createdAt: timestamp("created_at", { withTimezone: true }).default(sql`now()`).notNull(),
15
+
16
+ updatedAt: timestamp("updated_at", { withTimezone: true }).default(sql`now()`).notNull(),
17
+
18
+ // Character
19
+ name: text("name").notNull(),
20
+ username: text("username"),
21
+ system: text("system").default(""),
22
+ bio: jsonb("bio").$type<string | string[]>().default(sql`'[]'::jsonb`),
23
+ messageExamples: jsonb("message_examples")
24
+ .$type<MessageExample[][]>()
25
+ .default(sql`'[]'::jsonb`)
26
+ .notNull(),
27
+ postExamples: jsonb("post_examples").$type<string[]>().default(sql`'[]'::jsonb`).notNull(),
28
+ topics: jsonb("topics").$type<string[]>().default(sql`'[]'::jsonb`).notNull(),
29
+ adjectives: jsonb("adjectives").$type<string[]>().default(sql`'[]'::jsonb`).notNull(),
30
+ knowledge: jsonb("knowledge")
31
+ .$type<(string | { path: string; shared?: boolean })[]>()
32
+ .default(sql`'[]'::jsonb`)
33
+ .notNull(),
34
+ plugins: jsonb("plugins").$type<string[]>().default(sql`'[]'::jsonb`).notNull(),
35
+ settings: jsonb("settings")
36
+ .$type<{
37
+ secrets?: { [key: string]: string | boolean | number };
38
+ [key: string]: string | boolean | number | Record<string, unknown> | undefined;
39
+ }>()
40
+ .default(sql`'{}'::jsonb`)
41
+ .notNull(),
42
+ style: jsonb("style")
43
+ .$type<{
44
+ all?: string[];
45
+ chat?: string[];
46
+ post?: string[];
47
+ }>()
48
+ .default(sql`'{}'::jsonb`)
49
+ .notNull(),
50
+ });
@@ -0,0 +1,57 @@
1
+ import { sql } from "drizzle-orm";
2
+ import { index, jsonb, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
3
+ import { agentTable } from "./agent";
4
+
5
+ /**
6
+ * Persistent backing store for the LifeOps human-in-the-loop approval queue.
7
+ *
8
+ * Owned by `apps/app-lifeops` (see `src/lifeops/approval-queue.types.ts`),
9
+ * but lives in plugin-sql so the runtime migrator picks it up automatically
10
+ * for both PostgreSQL and PGlite deployments.
11
+ *
12
+ * Migration safety: this table is additive. It is created on first boot via
13
+ * the runtime migrator when absent, and existing databases are unaffected.
14
+ *
15
+ * State, action, channel, resolved_by, resolution_reason, and resolved_at are
16
+ * intentionally text/timestamp without a CHECK constraint — the application
17
+ * layer is the single source of truth for the state machine and the closed
18
+ * action/channel enums (Commandment 7).
19
+ */
20
+ export const approvalRequestTable = pgTable(
21
+ "approval_requests",
22
+ {
23
+ id: uuid("id").primaryKey().defaultRandom(),
24
+ /** Lifecycle state. See `ApprovalRequestState` in app-lifeops. */
25
+ state: text("state").notNull(),
26
+ /** Agent or service that enqueued the request. */
27
+ requestedBy: text("requested_by").notNull(),
28
+ /** Owner whose approval is required. */
29
+ subjectUserId: text("subject_user_id").notNull(),
30
+ /** Closed enum from `ApprovalAction`. */
31
+ action: text("action").notNull(),
32
+ /** Discriminated union from `ApprovalPayload`. */
33
+ payload: jsonb("payload").notNull(),
34
+ /** Closed enum from `ApprovalChannel`. */
35
+ channel: text("channel").notNull(),
36
+ /** Required justification for the request. */
37
+ reason: text("reason").notNull(),
38
+ expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
39
+ /** Null until the request leaves `pending`. */
40
+ resolvedAt: timestamp("resolved_at", { withTimezone: true }),
41
+ /** Null until resolved; resolver identity. */
42
+ resolvedBy: text("resolved_by"),
43
+ /** Null until resolved; human-readable resolution note. */
44
+ resolutionReason: text("resolution_reason"),
45
+ /** Owning agent (cascade-deletes when the agent is removed). */
46
+ agentId: uuid("agent_id")
47
+ .notNull()
48
+ .references(() => agentTable.id, { onDelete: "cascade" }),
49
+ createdAt: timestamp("created_at", { withTimezone: true }).default(sql`now()`).notNull(),
50
+ updatedAt: timestamp("updated_at", { withTimezone: true }).default(sql`now()`).notNull(),
51
+ },
52
+ (table) => [
53
+ index("approval_requests_subject_state_idx").on(table.subjectUserId, table.state),
54
+ index("approval_requests_agent_state_idx").on(table.agentId, table.state),
55
+ index("approval_requests_state_expires_idx").on(table.state, table.expiresAt),
56
+ ]
57
+ );
@@ -0,0 +1,29 @@
1
+ import { bigint, index, jsonb, pgTable, text } from "drizzle-orm/pg-core";
2
+
3
+ /**
4
+ * Append-only audit row for every sensitive auth action.
5
+ *
6
+ * Rows are also mirrored to JSONL on disk so a wiped DB does not lose history.
7
+ * Token-shaped values in `metadata` MUST be redacted before insert by the
8
+ * caller.
9
+ */
10
+ export const authAuditEventTable = pgTable(
11
+ "auth_audit_events",
12
+ {
13
+ id: text("id").primaryKey(),
14
+ ts: bigint("ts", { mode: "number" }).notNull(),
15
+ actorIdentityId: text("actor_identity_id"),
16
+ ip: text("ip"),
17
+ userAgent: text("user_agent"),
18
+ action: text("action").notNull(),
19
+ outcome: text("outcome").notNull(),
20
+ metadata: jsonb("metadata").$type<Record<string, string | number | boolean>>().notNull(),
21
+ },
22
+ (table) => [
23
+ index("auth_audit_events_action_idx").on(table.action),
24
+ index("auth_audit_events_ts_idx").on(table.ts),
25
+ index("auth_audit_events_actor_idx").on(table.actorIdentityId),
26
+ ]
27
+ );
28
+
29
+ export type AuthAuditOutcome = "success" | "failure";
@@ -0,0 +1,18 @@
1
+ import { bigint, index, pgTable, text } from "drizzle-orm/pg-core";
2
+
3
+ /**
4
+ * Replay-defence set for bootstrap-token `jti` claims. A row exists for every
5
+ * bootstrap token successfully verified on this instance; subsequent
6
+ * presentations of the same `jti` must be rejected.
7
+ *
8
+ * Rows are kept until natural `exp` of the original token plus a buffer; the
9
+ * cleanup job lives in the auth-store.
10
+ */
11
+ export const authBootstrapJtiSeenTable = pgTable(
12
+ "auth_bootstrap_jti_seen",
13
+ {
14
+ jti: text("jti").primaryKey(),
15
+ seenAt: bigint("seen_at", { mode: "number" }).notNull(),
16
+ },
17
+ (table) => [index("auth_bootstrap_jti_seen_at_idx").on(table.seenAt)]
18
+ );
@@ -0,0 +1,35 @@
1
+ import { sql } from "drizzle-orm";
2
+ import { bigint, index, pgTable, text } from "drizzle-orm/pg-core";
3
+
4
+ /**
5
+ * Auth identity row. One per real user / machine actor on this Eliza instance.
6
+ *
7
+ * `kind` distinguishes interactive ("owner") identities from non-interactive
8
+ * ("machine") identities used by long-lived bearer tokens. Exactly one of
9
+ * `passwordHash` or `cloudUserId` is expected to be populated for an owner
10
+ * (with possible owner-bindings extending login methods); machines have
11
+ * neither and are authenticated by the bearer token bound to their session.
12
+ */
13
+ export const authIdentityTable = pgTable(
14
+ "auth_identities",
15
+ {
16
+ /** uuid v7 string. Stored as text so we don't have to pull a v7 generator into pg defaults. */
17
+ id: text("id").primaryKey(),
18
+ kind: text("kind").notNull(),
19
+ displayName: text("display_name").notNull(),
20
+ createdAt: bigint("created_at", { mode: "number" }).notNull(),
21
+ /** argon2id encoded password hash. Optional: cloud-only identities may not have one. */
22
+ passwordHash: text("password_hash"),
23
+ /** Linked Eliza Cloud user id when SSO is enabled. */
24
+ cloudUserId: text("cloud_user_id"),
25
+ },
26
+ (table) => [
27
+ index("auth_identities_kind_idx").on(table.kind),
28
+ index("auth_identities_cloud_user_idx").on(table.cloudUserId),
29
+ ]
30
+ );
31
+
32
+ export type AuthIdentityKind = "owner" | "machine";
33
+
34
+ /** Default SQL `now() * 1000` to populate `created_at` when callers don't supply one. */
35
+ export const authIdentityCreatedAtDefault = sql`(extract(epoch from now()) * 1000)::bigint`;
@@ -0,0 +1,43 @@
1
+ import { bigint, foreignKey, index, pgTable, text, uniqueIndex } from "drizzle-orm/pg-core";
2
+ import { authIdentityTable } from "./authIdentity";
3
+
4
+ /**
5
+ * Connector-owner binding. Lets an external connector account (Discord,
6
+ * Telegram, WeChat, Matrix) prove ownership of a local Eliza identity.
7
+ *
8
+ * Uniqueness is enforced on `(connector, external_id, instance_id)` so the same
9
+ * Discord account can own multiple Eliza instances (one binding per
10
+ * (connector, external) pair *per instance*) without cross-talk.
11
+ */
12
+ export const authOwnerBindingTable = pgTable(
13
+ "auth_owner_bindings",
14
+ {
15
+ id: text("id").primaryKey(),
16
+ identityId: text("identity_id")
17
+ .notNull()
18
+ .references(() => authIdentityTable.id, { onDelete: "cascade" }),
19
+ connector: text("connector").notNull(),
20
+ externalId: text("external_id").notNull(),
21
+ displayHandle: text("display_handle").notNull(),
22
+ /** Stable per-instance id; populated from ELIZA_INSTANCE_ID or generated once at boot. */
23
+ instanceId: text("instance_id").notNull(),
24
+ verifiedAt: bigint("verified_at", { mode: "number" }).notNull(),
25
+ /** Hashed pairing code (sha256 hex) — never store the plaintext. */
26
+ pendingCodeHash: text("pending_code_hash"),
27
+ pendingExpiresAt: bigint("pending_expires_at", { mode: "number" }),
28
+ },
29
+ (table) => [
30
+ index("auth_owner_bindings_identity_idx").on(table.identityId),
31
+ index("auth_owner_bindings_connector_idx").on(table.connector),
32
+ uniqueIndex("auth_owner_bindings_connector_external_instance_uniq").on(
33
+ table.connector,
34
+ table.externalId,
35
+ table.instanceId
36
+ ),
37
+ foreignKey({
38
+ name: "fk_auth_owner_bindings_identity",
39
+ columns: [table.identityId],
40
+ foreignColumns: [authIdentityTable.id],
41
+ }).onDelete("cascade"),
42
+ ]
43
+ );
@@ -0,0 +1,50 @@
1
+ import { bigint, foreignKey, index, pgTable, text } from "drizzle-orm/pg-core";
2
+ import { authIdentityTable } from "./authIdentity";
3
+ import { authOwnerBindingTable } from "./authOwnerBinding";
4
+
5
+ /**
6
+ * Single-use DM-link login tokens for the connector-owner convenience flow.
7
+ *
8
+ * The user types `/eliza-pair` in their connector and asks Eliza to DM
9
+ * a login link. The DM contains a short-lived URL whose `?token=...` is
10
+ * the SHA-256 hash of a random UUID v7. The plaintext is sent only via the
11
+ * DM channel; the database stores only the hash so a DB read does not
12
+ * surrender unconsumed tokens.
13
+ *
14
+ * Tokens are consumed exactly once: the consume endpoint sets
15
+ * `consumed_at` and the row is preserved for audit. Rows older than
16
+ * `expires_at + 24h` are eligible for cleanup.
17
+ */
18
+ export const authOwnerLoginTokenTable = pgTable(
19
+ "auth_owner_login_tokens",
20
+ {
21
+ /** SHA-256 hex of the plaintext token. Plaintext is never stored. */
22
+ tokenHash: text("token_hash").primaryKey(),
23
+ identityId: text("identity_id")
24
+ .notNull()
25
+ .references(() => authIdentityTable.id, { onDelete: "cascade" }),
26
+ /** Binding that issued this token. */
27
+ bindingId: text("binding_id")
28
+ .notNull()
29
+ .references(() => authOwnerBindingTable.id, { onDelete: "cascade" }),
30
+ issuedAt: bigint("issued_at", { mode: "number" }).notNull(),
31
+ expiresAt: bigint("expires_at", { mode: "number" }).notNull(),
32
+ /** Set on first successful consume. Null while the token is live. */
33
+ consumedAt: bigint("consumed_at", { mode: "number" }),
34
+ },
35
+ (table) => [
36
+ index("auth_owner_login_tokens_identity_idx").on(table.identityId),
37
+ index("auth_owner_login_tokens_binding_idx").on(table.bindingId),
38
+ index("auth_owner_login_tokens_expires_idx").on(table.expiresAt),
39
+ foreignKey({
40
+ name: "fk_auth_owner_login_tokens_identity",
41
+ columns: [table.identityId],
42
+ foreignColumns: [authIdentityTable.id],
43
+ }).onDelete("cascade"),
44
+ foreignKey({
45
+ name: "fk_auth_owner_login_tokens_binding",
46
+ columns: [table.bindingId],
47
+ foreignColumns: [authOwnerBindingTable.id],
48
+ }).onDelete("cascade"),
49
+ ]
50
+ );
@@ -0,0 +1,44 @@
1
+ import { bigint, boolean, foreignKey, index, jsonb, pgTable, text } from "drizzle-orm/pg-core";
2
+ import { authIdentityTable } from "./authIdentity";
3
+
4
+ /**
5
+ * Active authenticated session.
6
+ *
7
+ * `id` is the opaque cookie value (256-bit hex) — server-side lookup, never JWT.
8
+ * `kind` is "browser" (sliding TTL, CSRF-bound) or "machine" (absolute TTL,
9
+ * scope-bearing bearer token).
10
+ *
11
+ * Browser sessions store a `csrfSecret` used to derive double-submit tokens.
12
+ * Machine sessions list explicit scopes; browser sessions get an empty list
13
+ * which the auth layer treats as "all scopes".
14
+ */
15
+ export const authSessionTable = pgTable(
16
+ "auth_sessions",
17
+ {
18
+ id: text("id").primaryKey(),
19
+ identityId: text("identity_id")
20
+ .notNull()
21
+ .references(() => authIdentityTable.id, { onDelete: "cascade" }),
22
+ kind: text("kind").notNull(),
23
+ createdAt: bigint("created_at", { mode: "number" }).notNull(),
24
+ lastSeenAt: bigint("last_seen_at", { mode: "number" }).notNull(),
25
+ expiresAt: bigint("expires_at", { mode: "number" }).notNull(),
26
+ rememberDevice: boolean("remember_device").notNull().default(false),
27
+ csrfSecret: text("csrf_secret").notNull(),
28
+ ip: text("ip"),
29
+ userAgent: text("user_agent"),
30
+ scopes: jsonb("scopes").$type<string[]>().notNull(),
31
+ revokedAt: bigint("revoked_at", { mode: "number" }),
32
+ },
33
+ (table) => [
34
+ index("auth_sessions_identity_idx").on(table.identityId),
35
+ index("auth_sessions_expires_idx").on(table.expiresAt),
36
+ foreignKey({
37
+ name: "fk_auth_sessions_identity",
38
+ columns: [table.identityId],
39
+ foreignColumns: [authIdentityTable.id],
40
+ }).onDelete("cascade"),
41
+ ]
42
+ );
43
+
44
+ export type AuthSessionKind = "browser" | "machine";
@@ -0,0 +1,22 @@
1
+ import { sql } from "drizzle-orm";
2
+ import { jsonb, pgTable, primaryKey, text, timestamp, uuid } from "drizzle-orm/pg-core";
3
+ import { agentTable } from "./agent";
4
+
5
+ /**
6
+ * Represents a PostgreSQL table for caching data.
7
+ *
8
+ * @type {pgTable}
9
+ */
10
+ export const cacheTable = pgTable(
11
+ "cache",
12
+ {
13
+ key: text("key").notNull(),
14
+ agentId: uuid("agent_id")
15
+ .notNull()
16
+ .references(() => agentTable.id, { onDelete: "cascade" }),
17
+ value: jsonb("value").notNull(),
18
+ createdAt: timestamp("created_at", { withTimezone: true }).default(sql`now()`).notNull(),
19
+ expiresAt: timestamp("expires_at", { withTimezone: true }),
20
+ },
21
+ (table) => [primaryKey({ columns: [table.key, table.agentId] })]
22
+ );
@@ -0,0 +1,19 @@
1
+ import { sql } from "drizzle-orm";
2
+ import { jsonb, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
3
+ import { messageServerTable } from "./messageServer";
4
+
5
+ export const channelTable = pgTable("channels", {
6
+ id: text("id").primaryKey(), // UUID stored as text
7
+ messageServerId: uuid("message_server_id")
8
+ .notNull()
9
+ .references(() => messageServerTable.id, { onDelete: "cascade" }),
10
+ name: text("name").notNull(),
11
+ type: text("type").notNull(), // Store ChannelType enum values as text
12
+ sourceType: text("source_type"),
13
+ sourceId: text("source_id"),
14
+ topic: text("topic"),
15
+ metadata: jsonb("metadata"),
16
+ // server_id is added dynamically by RLS setup
17
+ createdAt: timestamp("created_at", { mode: "date" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
18
+ updatedAt: timestamp("updated_at", { mode: "date" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
19
+ });
@@ -0,0 +1,13 @@
1
+ import { pgTable, primaryKey, text } from "drizzle-orm/pg-core";
2
+ import { channelTable } from "./channel";
3
+
4
+ export const channelParticipantsTable = pgTable(
5
+ "channel_participants",
6
+ {
7
+ channelId: text("channel_id")
8
+ .notNull()
9
+ .references(() => channelTable.id, { onDelete: "cascade" }),
10
+ entityId: text("entity_id").notNull(), // Entity UUID (can be an agentId or a dedicated central user ID)
11
+ },
12
+ (table) => [primaryKey({ columns: [table.channelId, table.entityId] })]
13
+ );
@@ -0,0 +1,37 @@
1
+ import { sql } from "drizzle-orm";
2
+ import { jsonb, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
3
+ import { agentTable } from "./agent";
4
+ import { entityTable } from "./entity";
5
+ import { roomTable } from "./room";
6
+ import { worldTable } from "./world";
7
+
8
+ /**
9
+ * Represents a component table in the database.
10
+ */
11
+ export const componentTable = pgTable("components", {
12
+ id: uuid("id").primaryKey().default(sql`gen_random_uuid()`).notNull(),
13
+
14
+ // Foreign keys
15
+ entityId: uuid("entity_id")
16
+ .references(() => entityTable.id, { onDelete: "cascade" })
17
+ .notNull(),
18
+ agentId: uuid("agent_id")
19
+ .references(() => agentTable.id, { onDelete: "cascade" })
20
+ .notNull(),
21
+ roomId: uuid("room_id")
22
+ .references(() => roomTable.id, { onDelete: "cascade" })
23
+ .notNull(),
24
+ worldId: uuid("world_id").references(() => worldTable.id, {
25
+ onDelete: "cascade",
26
+ }),
27
+ sourceEntityId: uuid("source_entity_id").references(() => entityTable.id, {
28
+ onDelete: "cascade",
29
+ }),
30
+
31
+ // Data
32
+ type: text("type").notNull(),
33
+ data: jsonb("data").default(sql`'{}'::jsonb`),
34
+
35
+ // Timestamps
36
+ createdAt: timestamp("created_at").default(sql`now()`).notNull(),
37
+ });