@minion-stack/db 0.4.0 → 0.7.0

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 (120) hide show
  1. package/dist/pg/schema/agent-groups.d.ts +169 -0
  2. package/dist/pg/schema/agent-groups.d.ts.map +1 -0
  3. package/dist/pg/schema/agent-groups.js +21 -0
  4. package/dist/pg/schema/agent-groups.js.map +1 -0
  5. package/dist/pg/schema/agent-memories.d.ts +281 -0
  6. package/dist/pg/schema/agent-memories.d.ts.map +1 -0
  7. package/dist/pg/schema/agent-memories.js +59 -0
  8. package/dist/pg/schema/agent-memories.js.map +1 -0
  9. package/dist/pg/schema/builder.d.ts +1432 -0
  10. package/dist/pg/schema/builder.d.ts.map +1 -0
  11. package/dist/pg/schema/builder.js +160 -0
  12. package/dist/pg/schema/builder.js.map +1 -0
  13. package/dist/pg/schema/channels.d.ts +441 -0
  14. package/dist/pg/schema/channels.d.ts.map +1 -0
  15. package/dist/pg/schema/channels.js +62 -0
  16. package/dist/pg/schema/channels.js.map +1 -0
  17. package/dist/pg/schema/chat-messages.d.ts +184 -0
  18. package/dist/pg/schema/chat-messages.d.ts.map +1 -0
  19. package/dist/pg/schema/chat-messages.js +26 -0
  20. package/dist/pg/schema/chat-messages.js.map +1 -0
  21. package/dist/pg/schema/device-identities.d.ts +111 -0
  22. package/dist/pg/schema/device-identities.d.ts.map +1 -0
  23. package/dist/pg/schema/device-identities.js +11 -0
  24. package/dist/pg/schema/device-identities.js.map +1 -0
  25. package/dist/pg/schema/files.d.ts +162 -0
  26. package/dist/pg/schema/files.d.ts.map +1 -0
  27. package/dist/pg/schema/files.js +15 -0
  28. package/dist/pg/schema/files.js.map +1 -0
  29. package/dist/pg/schema/index.d.ts +20 -0
  30. package/dist/pg/schema/index.d.ts.map +1 -1
  31. package/dist/pg/schema/index.js +22 -0
  32. package/dist/pg/schema/index.js.map +1 -1
  33. package/dist/pg/schema/marketplace.d.ts +459 -0
  34. package/dist/pg/schema/marketplace.d.ts.map +1 -0
  35. package/dist/pg/schema/marketplace.js +42 -0
  36. package/dist/pg/schema/marketplace.js.map +1 -0
  37. package/dist/pg/schema/messages.d.ts +391 -0
  38. package/dist/pg/schema/messages.d.ts.map +1 -0
  39. package/dist/pg/schema/messages.js +44 -0
  40. package/dist/pg/schema/messages.js.map +1 -0
  41. package/dist/pg/schema/missions.d.ts +361 -0
  42. package/dist/pg/schema/missions.d.ts.map +1 -0
  43. package/dist/pg/schema/missions.js +48 -0
  44. package/dist/pg/schema/missions.js.map +1 -0
  45. package/dist/pg/schema/personal-agents.d.ts +285 -0
  46. package/dist/pg/schema/personal-agents.d.ts.map +1 -0
  47. package/dist/pg/schema/personal-agents.js +40 -0
  48. package/dist/pg/schema/personal-agents.js.map +1 -0
  49. package/dist/pg/schema/profiles.d.ts +17 -0
  50. package/dist/pg/schema/profiles.d.ts.map +1 -1
  51. package/dist/pg/schema/profiles.js +2 -0
  52. package/dist/pg/schema/profiles.js.map +1 -1
  53. package/dist/pg/schema/server-ops.d.ts +836 -0
  54. package/dist/pg/schema/server-ops.d.ts.map +1 -0
  55. package/dist/pg/schema/server-ops.js +88 -0
  56. package/dist/pg/schema/server-ops.js.map +1 -0
  57. package/dist/pg/schema/sessions.d.ts +395 -0
  58. package/dist/pg/schema/sessions.d.ts.map +1 -0
  59. package/dist/pg/schema/sessions.js +50 -0
  60. package/dist/pg/schema/sessions.js.map +1 -0
  61. package/dist/pg/schema/settings.d.ts +111 -0
  62. package/dist/pg/schema/settings.d.ts.map +1 -0
  63. package/dist/pg/schema/settings.js +17 -0
  64. package/dist/pg/schema/settings.js.map +1 -0
  65. package/dist/pg/schema/skills.d.ts +395 -0
  66. package/dist/pg/schema/skills.d.ts.map +1 -0
  67. package/dist/pg/schema/skills.js +45 -0
  68. package/dist/pg/schema/skills.js.map +1 -0
  69. package/dist/pg/schema/user-agents.d.ts +80 -0
  70. package/dist/pg/schema/user-agents.d.ts.map +1 -0
  71. package/dist/pg/schema/user-agents.js +21 -0
  72. package/dist/pg/schema/user-agents.js.map +1 -0
  73. package/dist/pg/schema/user-identities.d.ts +1 -1
  74. package/dist/pg/schema/user-preferences.d.ts +97 -0
  75. package/dist/pg/schema/user-preferences.d.ts.map +1 -0
  76. package/dist/pg/schema/user-preferences.js +19 -0
  77. package/dist/pg/schema/user-preferences.js.map +1 -0
  78. package/dist/pg/schema/workshop-saves.d.ts +145 -0
  79. package/dist/pg/schema/workshop-saves.d.ts.map +1 -0
  80. package/dist/pg/schema/workshop-saves.js +13 -0
  81. package/dist/pg/schema/workshop-saves.js.map +1 -0
  82. package/dist/pg/schema/workspace-membership.d.ts +83 -0
  83. package/dist/pg/schema/workspace-membership.d.ts.map +1 -0
  84. package/dist/pg/schema/workspace-membership.js +19 -0
  85. package/dist/pg/schema/workspace-membership.js.map +1 -0
  86. package/dist/schema/index.d.ts +2 -0
  87. package/dist/schema/index.d.ts.map +1 -1
  88. package/dist/schema/index.js +1 -0
  89. package/dist/schema/index.js.map +1 -1
  90. package/dist/schema/join-requests.d.ts +188 -0
  91. package/dist/schema/join-requests.d.ts.map +1 -0
  92. package/dist/schema/join-requests.js +35 -0
  93. package/dist/schema/join-requests.js.map +1 -0
  94. package/dist/schema/personal-agents.d.ts +1 -1
  95. package/dist/schema/reliability-events.d.ts +1 -1
  96. package/dist/schema/skill-execution-stats.d.ts +1 -1
  97. package/package.json +1 -1
  98. package/src/pg/schema/agent-groups.ts +30 -0
  99. package/src/pg/schema/agent-memories.ts +73 -0
  100. package/src/pg/schema/builder.ts +205 -0
  101. package/src/pg/schema/channels.ts +77 -0
  102. package/src/pg/schema/chat-messages.ts +30 -0
  103. package/src/pg/schema/device-identities.ts +11 -0
  104. package/src/pg/schema/files.ts +19 -0
  105. package/src/pg/schema/index.ts +38 -0
  106. package/src/pg/schema/marketplace.ts +47 -0
  107. package/src/pg/schema/messages.ts +48 -0
  108. package/src/pg/schema/missions.ts +58 -0
  109. package/src/pg/schema/personal-agents.ts +44 -0
  110. package/src/pg/schema/profiles.ts +2 -0
  111. package/src/pg/schema/server-ops.ts +126 -0
  112. package/src/pg/schema/sessions.ts +60 -0
  113. package/src/pg/schema/settings.ts +21 -0
  114. package/src/pg/schema/skills.ts +65 -0
  115. package/src/pg/schema/user-agents.ts +25 -0
  116. package/src/pg/schema/user-preferences.ts +23 -0
  117. package/src/pg/schema/workshop-saves.ts +13 -0
  118. package/src/pg/schema/workspace-membership.ts +26 -0
  119. package/src/schema/index.ts +2 -0
  120. package/src/schema/join-requests.ts +42 -0
@@ -0,0 +1,35 @@
1
+ import { sqliteTable, text, integer, index } from 'drizzle-orm/sqlite-core';
2
+ import { user } from './auth/index.js';
3
+ import { organization } from './auth/index.js';
4
+ /**
5
+ * join_requests — users requesting to join an organization.
6
+ *
7
+ * When a user not-yet-in-an-org wants access, they submit a join request.
8
+ * Org admins review (approve/deny). On approval the user is added as a member.
9
+ *
10
+ * Used by:
11
+ * - /join page (submission)
12
+ * - /api/join-requests/* (listing, counting, review)
13
+ * - notifications panel
14
+ */
15
+ export const joinRequests = sqliteTable('join_requests', {
16
+ id: text('id').primaryKey(),
17
+ userId: text('user_id')
18
+ .notNull()
19
+ .references(() => user.id, { onDelete: 'cascade' }),
20
+ orgId: text('org_id')
21
+ .notNull()
22
+ .references(() => organization.id, { onDelete: 'cascade' }),
23
+ email: text('email').notNull(),
24
+ message: text('message'),
25
+ status: text('status', { enum: ['pending', 'approved', 'denied'] })
26
+ .notNull()
27
+ .default('pending'),
28
+ reviewedBy: text('reviewed_by'),
29
+ reviewedAt: integer('reviewed_at'),
30
+ createdAt: integer('created_at').notNull(),
31
+ }, (t) => [
32
+ index('idx_join_requests_user').on(t.userId),
33
+ index('idx_join_requests_org_status').on(t.orgId, t.status),
34
+ ]);
35
+ //# sourceMappingURL=join-requests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"join-requests.js","sourceRoot":"","sources":["../../src/schema/join-requests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,WAAW,CACrC,eAAe,EACf;IACE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE;IAC3B,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;SACpB,OAAO,EAAE;SACT,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IACrD,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;SAClB,OAAO,EAAE;SACT,UAAU,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IAC7D,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE;IAC9B,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC;IACxB,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,CAAC;SAChE,OAAO,EAAE;SACT,OAAO,CAAC,SAAS,CAAC;IACrB,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC;IAC/B,UAAU,EAAE,OAAO,CAAC,aAAa,CAAC;IAClC,SAAS,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;CAC3C,EACD,CAAC,CAAC,EAAE,EAAE,CAAC;IACL,KAAK,CAAC,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IAC5C,KAAK,CAAC,8BAA8B,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;CAC5D,CACF,CAAC"}
@@ -195,7 +195,7 @@ export declare const personalAgents: import("drizzle-orm/sqlite-core").SQLiteTab
195
195
  tableName: "personal_agents";
196
196
  dataType: "string";
197
197
  columnType: "SQLiteText";
198
- data: "pending" | "provisioning" | "active" | "error";
198
+ data: "active" | "error" | "pending" | "provisioning";
199
199
  driverParam: string;
200
200
  notNull: true;
201
201
  hasDefault: true;
@@ -81,7 +81,7 @@ export declare const reliabilityEvents: import("drizzle-orm/sqlite-core").SQLite
81
81
  tableName: "reliability_events";
82
82
  dataType: "string";
83
83
  columnType: "SQLiteText";
84
- data: "general" | "cron" | "browser" | "timezone" | "auth" | "skill" | "agent" | "gateway";
84
+ data: "general" | "gateway" | "cron" | "browser" | "timezone" | "auth" | "skill" | "agent";
85
85
  driverParam: string;
86
86
  notNull: true;
87
87
  hasDefault: false;
@@ -119,7 +119,7 @@ export declare const skillExecutionStats: import("drizzle-orm/sqlite-core").SQLi
119
119
  tableName: "skill_execution_stats";
120
120
  dataType: "string";
121
121
  columnType: "SQLiteText";
122
- data: "ok" | "error" | "auth_error" | "timeout";
122
+ data: "ok" | "auth_error" | "timeout" | "error";
123
123
  driverParam: string;
124
124
  notNull: true;
125
125
  hasDefault: false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minion-stack/db",
3
- "version": "0.4.0",
3
+ "version": "0.7.0",
4
4
  "description": "Drizzle ORM schema for the Minion shared database (LibSQL/Turso).",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -0,0 +1,30 @@
1
+ import { pgTable, uuid, text, integer, timestamp, index, primaryKey } from 'drizzle-orm/pg-core';
2
+ import { profiles } from './profiles.js';
3
+
4
+ /** User-defined agent groupings. Mirrors Turso `agent_groups`. user_id → profile_id, tenant_id → organizations.id. */
5
+ export const agentGroups = pgTable(
6
+ 'agent_groups',
7
+ {
8
+ id: text('id').primaryKey(),
9
+ profileId: uuid('profile_id')
10
+ .notNull()
11
+ .references(() => profiles.id, { onDelete: 'cascade' }),
12
+ tenantId: uuid('tenant_id').notNull(),
13
+ name: text('name').notNull(),
14
+ sortOrder: integer('sort_order').default(0),
15
+ createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
16
+ },
17
+ (t) => [index('idx_agent_groups_profile').on(t.profileId, t.tenantId)],
18
+ );
19
+
20
+ export const agentGroupMembers = pgTable(
21
+ 'agent_group_members',
22
+ {
23
+ groupId: text('group_id')
24
+ .notNull()
25
+ .references(() => agentGroups.id, { onDelete: 'cascade' }),
26
+ agentId: text('agent_id').notNull(),
27
+ sortOrder: integer('sort_order').default(0),
28
+ },
29
+ (t) => [primaryKey({ columns: [t.groupId, t.agentId] })],
30
+ );
@@ -0,0 +1,73 @@
1
+ import { sql } from 'drizzle-orm';
2
+ import {
3
+ pgTable,
4
+ uuid,
5
+ text,
6
+ real,
7
+ timestamp,
8
+ jsonb,
9
+ vector,
10
+ index,
11
+ uniqueIndex,
12
+ } from 'drizzle-orm/pg-core';
13
+
14
+ /**
15
+ * Org-scoped agent memory corpus with pgvector embeddings. This is the
16
+ * system-of-record home for agent memories (migrated off the gateway-local
17
+ * LanceDB store): semantic memory, session-memory summaries, and captured
18
+ * facts/preferences/decisions/entities. Both the hub (visualization) and the
19
+ * flow runner (RAG retrieval) read from here.
20
+ *
21
+ * Embedding dimension matches OpenAI `text-embedding-3-small` (1536). If the
22
+ * embedding model changes, add a new column / table rather than mixing
23
+ * dimensions in one column.
24
+ *
25
+ * RLS (org isolation) is added in the hand-written companion migration
26
+ * `<ts>_agent_memories_rls.sql` (role app_ledger + app.current_org_id GUC),
27
+ * mirroring `messages`. Drizzle does not manage roles/policies, the `vector`
28
+ * extension, or the HNSW index — those live in the companion SQL.
29
+ */
30
+ export const agentMemories = pgTable(
31
+ 'agent_memories',
32
+ {
33
+ id: uuid('id').primaryKey().defaultRandom(),
34
+ // RLS pivot. Better Auth org id (text), matches messages.org_id convention.
35
+ orgId: text('org_id').notNull(),
36
+ // Producing gateway/server id (hub servers.id; text — not a PG uuid).
37
+ gatewayId: text('gateway_id'),
38
+ // Memory is agent-scoped; agentId is the gateway agent id (text).
39
+ agentId: text('agent_id').notNull(),
40
+ // Optional owner for personal memories (profiles.id); null = agent-global.
41
+ profileId: uuid('profile_id'),
42
+ // The memory content (what gets embedded + shown).
43
+ content: text('content').notNull(),
44
+ // OpenAI text-embedding-3-small dimension. Nullable so a row can be inserted
45
+ // before its embedding is computed (async backfill).
46
+ embedding: vector('embedding', { dimensions: 1536 }),
47
+ category: text('category', {
48
+ enum: ['preference', 'fact', 'decision', 'entity', 'other'],
49
+ })
50
+ .notNull()
51
+ .default('other'),
52
+ // 0..1 salience used for ranking + decay.
53
+ importance: real('importance').notNull().default(0.5),
54
+ // Which subsystem produced this row: lancedb | session | manual | kg | ledger.
55
+ source: text('source').notNull().default('manual'),
56
+ // Original id in the source system (e.g. LanceDB MemoryEntry.id) — enables
57
+ // idempotent migration + dedupe.
58
+ sourceId: text('source_id'),
59
+ occurredAt: timestamp('occurred_at', { withTimezone: true }),
60
+ createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
61
+ updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
62
+ metadata: jsonb('metadata').notNull().default({}),
63
+ },
64
+ (t) => ({
65
+ // Idempotent migration / cross-source dedupe.
66
+ sourceUnique: uniqueIndex('agent_memories_source_uniq')
67
+ .on(t.orgId, t.source, t.sourceId)
68
+ .where(sql`source_id is not null`),
69
+ orgAgentIdx: index('agent_memories_org_agent_idx').on(t.orgId, t.agentId),
70
+ orgCategoryIdx: index('agent_memories_org_category_idx').on(t.orgId, t.category),
71
+ orgTimeIdx: index('agent_memories_org_time_idx').on(t.orgId, t.createdAt),
72
+ }),
73
+ );
@@ -0,0 +1,205 @@
1
+ import { pgTable, uuid, text, integer, real, timestamp, index } from 'drizzle-orm/pg-core';
2
+ import { gateway } from './gateway.js';
3
+
4
+ /**
5
+ * Visual builder (Workshop) tables. Mirrors Turso `built_*` / `agent_built_skills`.
6
+ * FK remap on migration:
7
+ * server_id → gateway_id (gateway.id, matched via gateway.legacy_server_id)
8
+ * tenant_id → organizations.id (plain uuid, soft ref — enforced via RLS)
9
+ * created_by → kept as text (loose audit field, may be a legacy user id)
10
+ * created_at / updated_at / published_at (integer epoch) → timestamptz
11
+ */
12
+
13
+ // ── Built Skills ──────────────────────────────────────────────────────
14
+ export const builtSkills = pgTable(
15
+ 'built_skills',
16
+ {
17
+ id: text('id').primaryKey(),
18
+ name: text('name').notNull(),
19
+ description: text('description').default(''),
20
+ emoji: text('emoji').default('📖'),
21
+ status: text('status', { enum: ['draft', 'published'] })
22
+ .notNull()
23
+ .default('draft'),
24
+ maxCycles: integer('max_cycles').notNull().default(3),
25
+ gatewayId: uuid('gateway_id').references(() => gateway.id, { onDelete: 'cascade' }),
26
+ tenantId: uuid('tenant_id'),
27
+ createdBy: text('created_by'),
28
+ publishedAt: timestamp('published_at', { withTimezone: true }),
29
+ createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
30
+ updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
31
+ },
32
+ (t) => [
33
+ index('idx_built_skills_gateway').on(t.gatewayId),
34
+ index('idx_built_skills_tenant').on(t.tenantId),
35
+ ],
36
+ );
37
+
38
+ // ── Skill Tool Pool (junction: skill → gateway tool IDs) ─────────────
39
+ export const builtSkillTools = pgTable(
40
+ 'built_skill_tools',
41
+ {
42
+ id: text('id').primaryKey(),
43
+ skillId: text('skill_id')
44
+ .notNull()
45
+ .references(() => builtSkills.id, { onDelete: 'cascade' }),
46
+ toolId: text('tool_id').notNull(),
47
+ },
48
+ (t) => [index('idx_built_skill_tools_skill').on(t.skillId)],
49
+ );
50
+
51
+ // ── Chapters (subprocess nodes in the DAG) ───────────────────────────
52
+ export const builtChapters = pgTable(
53
+ 'built_chapters',
54
+ {
55
+ id: text('id').primaryKey(),
56
+ skillId: text('skill_id')
57
+ .notNull()
58
+ .references(() => builtSkills.id, { onDelete: 'cascade' }),
59
+ type: text('type', { enum: ['chapter', 'condition'] })
60
+ .notNull()
61
+ .default('chapter'),
62
+ name: text('name').notNull(),
63
+ description: text('description').default(''),
64
+ guide: text('guide').default(''),
65
+ context: text('context').default(''),
66
+ outputDef: text('output_def').default(''),
67
+ conditionText: text('condition_text').default(''),
68
+ positionX: real('position_x').notNull().default(0),
69
+ positionY: real('position_y').notNull().default(0),
70
+ createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
71
+ updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
72
+ },
73
+ (t) => [index('idx_built_chapters_skill').on(t.skillId)],
74
+ );
75
+
76
+ // ── Chapter Edges (DAG connections between chapters) ─────────────────
77
+ export const builtChapterEdges = pgTable(
78
+ 'built_chapter_edges',
79
+ {
80
+ id: text('id').primaryKey(),
81
+ skillId: text('skill_id')
82
+ .notNull()
83
+ .references(() => builtSkills.id, { onDelete: 'cascade' }),
84
+ sourceChapterId: text('source_chapter_id')
85
+ .notNull()
86
+ .references(() => builtChapters.id, { onDelete: 'cascade' }),
87
+ targetChapterId: text('target_chapter_id')
88
+ .notNull()
89
+ .references(() => builtChapters.id, { onDelete: 'cascade' }),
90
+ label: text('label'),
91
+ },
92
+ (t) => [index('idx_built_chapter_edges_skill').on(t.skillId)],
93
+ );
94
+
95
+ // ── Chapter Tools (junction: chapter → subset of skill's tool pool) ──
96
+ export const builtChapterTools = pgTable(
97
+ 'built_chapter_tools',
98
+ {
99
+ id: text('id').primaryKey(),
100
+ chapterId: text('chapter_id')
101
+ .notNull()
102
+ .references(() => builtChapters.id, { onDelete: 'cascade' }),
103
+ toolId: text('tool_id').notNull(),
104
+ },
105
+ (t) => [index('idx_built_chapter_tools_chapter').on(t.chapterId)],
106
+ );
107
+
108
+ // ── Built Agents ─────────────────────────────────────────────────────
109
+ export const builtAgents = pgTable(
110
+ 'built_agents',
111
+ {
112
+ id: text('id').primaryKey(),
113
+ name: text('name').notNull(),
114
+ emoji: text('emoji').default('🤖'),
115
+ description: text('description').default(''),
116
+ model: text('model'),
117
+ systemPrompt: text('system_prompt').default(''),
118
+ temperature: real('temperature').default(0.7),
119
+ maxTokens: integer('max_tokens').default(4096),
120
+ retryPolicy: text('retry_policy').default('{}'),
121
+ fallbackAgentId: text('fallback_agent_id'),
122
+ status: text('status', { enum: ['draft', 'published'] })
123
+ .notNull()
124
+ .default('draft'),
125
+ gatewayId: uuid('gateway_id').references(() => gateway.id, { onDelete: 'cascade' }),
126
+ tenantId: uuid('tenant_id'),
127
+ createdBy: text('created_by'),
128
+ publishedAt: timestamp('published_at', { withTimezone: true }),
129
+ createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
130
+ updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
131
+ },
132
+ (t) => [
133
+ index('idx_built_agents_gateway').on(t.gatewayId),
134
+ index('idx_built_agents_tenant').on(t.tenantId),
135
+ ],
136
+ );
137
+
138
+ // ── Agent Skill Slots (junction: agent → skill with order) ───────────
139
+ export const builtAgentSkills = pgTable(
140
+ 'built_agent_skills',
141
+ {
142
+ id: text('id').primaryKey(),
143
+ agentId: text('agent_id')
144
+ .notNull()
145
+ .references(() => builtAgents.id, { onDelete: 'cascade' }),
146
+ skillId: text('skill_id')
147
+ .notNull()
148
+ .references(() => builtSkills.id, { onDelete: 'cascade' }),
149
+ position: integer('position').notNull().default(0),
150
+ configOverrides: text('config_overrides').default('{}'),
151
+ },
152
+ (t) => [index('idx_built_agent_skills_agent').on(t.agentId)],
153
+ );
154
+
155
+ // ── Agent Built Skills (junction: gateway agent → built skill) ────────
156
+ export const agentBuiltSkills = pgTable(
157
+ 'agent_built_skills',
158
+ {
159
+ id: text('id').primaryKey(),
160
+ gatewayAgentId: text('gateway_agent_id').notNull(),
161
+ gatewayId: uuid('gateway_id')
162
+ .notNull()
163
+ .references(() => gateway.id, { onDelete: 'cascade' }),
164
+ tenantId: uuid('tenant_id').notNull(),
165
+ skillId: text('skill_id')
166
+ .notNull()
167
+ .references(() => builtSkills.id, { onDelete: 'cascade' }),
168
+ position: integer('position').notNull().default(0),
169
+ createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
170
+ },
171
+ (t) => [
172
+ index('idx_agent_built_skills_gateway_agent').on(t.gatewayAgentId),
173
+ index('idx_agent_built_skills_tenant').on(t.tenantId),
174
+ ],
175
+ );
176
+
177
+ // ── Built Tools (admin-only playground) ──────────────────────────────
178
+ export const builtTools = pgTable(
179
+ 'built_tools',
180
+ {
181
+ id: text('id').primaryKey(),
182
+ name: text('name').notNull(),
183
+ description: text('description').default(''),
184
+ scriptCode: text('script_code').default(''),
185
+ scriptLang: text('script_lang', { enum: ['javascript', 'python', 'bash'] })
186
+ .notNull()
187
+ .default('javascript'),
188
+ envVars: text('env_vars').default('{}'),
189
+ validationRules: text('validation_rules').default('{}'),
190
+ executionConfig: text('execution_config').default('{}'),
191
+ status: text('status', { enum: ['draft', 'published'] })
192
+ .notNull()
193
+ .default('draft'),
194
+ gatewayId: uuid('gateway_id').references(() => gateway.id, { onDelete: 'cascade' }),
195
+ tenantId: uuid('tenant_id'),
196
+ createdBy: text('created_by'),
197
+ publishedAt: timestamp('published_at', { withTimezone: true }),
198
+ createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
199
+ updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
200
+ },
201
+ (t) => [
202
+ index('idx_built_tools_gateway').on(t.gatewayId),
203
+ index('idx_built_tools_tenant').on(t.tenantId),
204
+ ],
205
+ );
@@ -0,0 +1,77 @@
1
+ import { pgTable, uuid, text, timestamp, index, uniqueIndex } from 'drizzle-orm/pg-core';
2
+ import { gateway } from './gateway.js';
3
+ import { profiles } from './profiles.js';
4
+
5
+ /**
6
+ * Channel connections + assignments + identity mappings.
7
+ * Mirrors Turso `channels` / `channel_assignments` / `channel_identities`.
8
+ * FK remap: server_id → gateway_id (gateway.id via legacy_server_id),
9
+ * tenant_id → organizations.id (plain uuid soft-ref, RLS-enforced),
10
+ * user_id → profiles.id (matched via profiles.legacy_user_id).
11
+ */
12
+
13
+ export const channels = pgTable(
14
+ 'channels',
15
+ {
16
+ id: text('id').primaryKey(),
17
+ tenantId: uuid('tenant_id').notNull(),
18
+ gatewayId: uuid('gateway_id')
19
+ .notNull()
20
+ .references(() => gateway.id, { onDelete: 'cascade' }),
21
+ type: text('type', { enum: ['discord', 'whatsapp', 'telegram'] }).notNull(),
22
+ label: text('label').notNull(),
23
+ credentials: text('credentials').notNull().default(''),
24
+ credentialsIv: text('credentials_iv').notNull().default(''),
25
+ credentialsMeta: text('credentials_meta').notNull().default('{}'),
26
+ status: text('status', { enum: ['active', 'inactive', 'pairing'] })
27
+ .notNull()
28
+ .default('inactive'),
29
+ createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
30
+ updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
31
+ },
32
+ (t) => [
33
+ index('idx_channels_tenant_gateway').on(t.tenantId, t.gatewayId),
34
+ uniqueIndex('channels_uniq_type_label').on(t.tenantId, t.gatewayId, t.type, t.label),
35
+ ],
36
+ );
37
+
38
+ export const channelAssignments = pgTable(
39
+ 'channel_assignments',
40
+ {
41
+ id: text('id').primaryKey(),
42
+ tenantId: uuid('tenant_id').notNull(),
43
+ channelId: text('channel_id')
44
+ .notNull()
45
+ .references(() => channels.id, { onDelete: 'cascade' }),
46
+ targetType: text('target_type', { enum: ['user', 'session'] }).notNull(),
47
+ targetId: text('target_id').notNull(),
48
+ createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
49
+ },
50
+ (t) => [
51
+ index('idx_channel_assign_channel').on(t.channelId),
52
+ uniqueIndex('channel_assign_uniq').on(t.channelId, t.targetType, t.targetId),
53
+ ],
54
+ );
55
+
56
+ /**
57
+ * Maps channel sender IDs (e.g. telegram:12345) to hub users.
58
+ * Used by the gateway to resolve user identity from channel messages.
59
+ */
60
+ export const channelIdentities = pgTable(
61
+ 'channel_identities',
62
+ {
63
+ id: text('id').primaryKey(),
64
+ userId: uuid('user_id')
65
+ .notNull()
66
+ .references(() => profiles.id, { onDelete: 'cascade' }),
67
+ channel: text('channel').notNull(),
68
+ channelUserId: text('channel_user_id').notNull(),
69
+ displayName: text('display_name'),
70
+ verifiedAt: timestamp('verified_at', { withTimezone: true }),
71
+ createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
72
+ },
73
+ (t) => [
74
+ uniqueIndex('idx_channel_identity_unique').on(t.channel, t.channelUserId),
75
+ index('idx_channel_identity_user').on(t.userId),
76
+ ],
77
+ );
@@ -0,0 +1,30 @@
1
+ import { pgTable, uuid, text, bigserial, timestamp, index } from 'drizzle-orm/pg-core';
2
+ import { gateway } from './gateway.js';
3
+
4
+ /**
5
+ * Persisted chat transcript. Mirrors Turso `chat_messages`.
6
+ * FK remap: server_id → gateway_id, tenant_id → organizations.id (soft-ref).
7
+ * id: SQLite autoincrement integer → Postgres bigserial.
8
+ * timestamp / created_at: integer epoch (ms) → timestamptz.
9
+ */
10
+ export const chatMessages = pgTable(
11
+ 'chat_messages',
12
+ {
13
+ id: bigserial('id', { mode: 'number' }).primaryKey(),
14
+ tenantId: uuid('tenant_id').notNull(),
15
+ gatewayId: uuid('gateway_id')
16
+ .notNull()
17
+ .references(() => gateway.id, { onDelete: 'cascade' }),
18
+ agentId: text('agent_id').notNull(),
19
+ sessionKey: text('session_key').notNull(),
20
+ role: text('role', { enum: ['user', 'assistant'] }).notNull(),
21
+ content: text('content').notNull(),
22
+ runId: text('run_id'),
23
+ timestamp: timestamp('timestamp', { withTimezone: true }).notNull(),
24
+ createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
25
+ },
26
+ (t) => [
27
+ index('idx_chat_tenant').on(t.tenantId),
28
+ index('idx_chat_by_agent').on(t.agentId, t.sessionKey, t.timestamp),
29
+ ],
30
+ );
@@ -0,0 +1,11 @@
1
+ import { pgTable, uuid, text, timestamp } from 'drizzle-orm/pg-core';
2
+
3
+ /** Per-tenant device keypair. Mirrors Turso `device_identities`. tenant_id → organizations.id. */
4
+ export const deviceIdentities = pgTable('device_identities', {
5
+ id: text('id').primaryKey(),
6
+ tenantId: uuid('tenant_id').notNull().unique(),
7
+ deviceId: text('device_id').notNull(),
8
+ publicKeyPem: text('public_key_pem').notNull(),
9
+ privateKeyPem: text('private_key_pem').notNull(),
10
+ createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
11
+ });
@@ -0,0 +1,19 @@
1
+ import { pgTable, uuid, text, bigint, timestamp, index } from 'drizzle-orm/pg-core';
2
+ import { profiles } from './profiles.js';
3
+
4
+ /** B2-backed file records. Mirrors Turso `files`. tenant_id → organizations.id, uploaded_by → profiles.id. */
5
+ export const files = pgTable(
6
+ 'files',
7
+ {
8
+ id: text('id').primaryKey(),
9
+ tenantId: uuid('tenant_id').notNull(),
10
+ uploadedBy: uuid('uploaded_by').references(() => profiles.id, { onDelete: 'set null' }),
11
+ b2FileKey: text('b2_file_key').notNull(),
12
+ fileName: text('file_name').notNull(),
13
+ contentType: text('content_type').notNull(),
14
+ sizeBytes: bigint('size_bytes', { mode: 'number' }).notNull(),
15
+ category: text('category').notNull().default('general'),
16
+ createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
17
+ },
18
+ (t) => [index('idx_files_tenant').on(t.tenantId)],
19
+ );
@@ -12,3 +12,41 @@ export type {
12
12
  } from '../identity-mapper.js';
13
13
  export { sealSecret, openSecret } from '../crypto.js';
14
14
  export { gateway, userGateway } from './gateway.js';
15
+ export { messages } from './messages.js';
16
+ // App tables migrated off Turso (telemetry/app split) — see
17
+ // docs/superpowers/specs/2026-06-05-turso-supabase-split-migration.md
18
+ export { userPreferences } from './user-preferences.js';
19
+ export { personalAgents } from './personal-agents.js';
20
+ export { settings } from './settings.js';
21
+ export { workshopSaves } from './workshop-saves.js';
22
+ export { deviceIdentities } from './device-identities.js';
23
+ export { files } from './files.js';
24
+ export { agentGroups, agentGroupMembers } from './agent-groups.js';
25
+ export { marketplaceAgents, marketplaceInstalls } from './marketplace.js';
26
+ export {
27
+ builtSkills,
28
+ builtSkillTools,
29
+ builtChapters,
30
+ builtChapterEdges,
31
+ builtChapterTools,
32
+ builtAgents,
33
+ builtAgentSkills,
34
+ agentBuiltSkills,
35
+ builtTools,
36
+ } from './builder.js';
37
+ export { channels, channelAssignments, channelIdentities } from './channels.js';
38
+ export { sessions, sessionTasks } from './sessions.js';
39
+ export { missions, tasks } from './missions.js';
40
+ export { chatMessages } from './chat-messages.js';
41
+ export { userAgents } from './user-agents.js';
42
+ export { skills, skillExecutionStats } from './skills.js';
43
+ export {
44
+ serverBackups,
45
+ serverProvisionConfigs,
46
+ backupConfigs,
47
+ configSnapshots,
48
+ } from './server-ops.js';
49
+ export { workspaceMembership } from './workspace-membership.js';
50
+ export type { WorkspaceMembership, NewWorkspaceMembership } from './workspace-membership.js';
51
+ // Org-scoped agent memory corpus (pgvector) — RAG retrieval + hub visualization.
52
+ export { agentMemories } from './agent-memories.js';
@@ -0,0 +1,47 @@
1
+ import { pgTable, uuid, text, integer, timestamp, index } from 'drizzle-orm/pg-core';
2
+ import { gateway } from './gateway.js';
3
+
4
+ /** Marketplace agent catalog. Mirrors Turso `marketplace_agents`. */
5
+ export const marketplaceAgents = pgTable('marketplace_agents', {
6
+ id: text('id').primaryKey(),
7
+ name: text('name').notNull(),
8
+ role: text('role').notNull(),
9
+ category: text('category').notNull(),
10
+ tags: text('tags').notNull(),
11
+ description: text('description').notNull(),
12
+ catchphrase: text('catchphrase'),
13
+ version: text('version').notNull(),
14
+ model: text('model'),
15
+ avatarSeed: text('avatar_seed').notNull(),
16
+ githubPath: text('github_path').notNull(),
17
+ soulMd: text('soul_md'),
18
+ identityMd: text('identity_md'),
19
+ userMd: text('user_md'),
20
+ contextMd: text('context_md'),
21
+ skillsMd: text('skills_md'),
22
+ installCount: integer('install_count').default(0),
23
+ syncedAt: timestamp('synced_at', { withTimezone: true }).notNull().defaultNow(),
24
+ filesLoadedAt: timestamp('files_loaded_at', { withTimezone: true }),
25
+ createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
26
+ updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
27
+ });
28
+
29
+ /** Per-tenant marketplace installs. tenant_id → organizations.id, server_id → gateway.id. */
30
+ export const marketplaceInstalls = pgTable(
31
+ 'marketplace_installs',
32
+ {
33
+ id: text('id').primaryKey(),
34
+ tenantId: uuid('tenant_id').notNull(),
35
+ agentId: text('agent_id')
36
+ .notNull()
37
+ .references(() => marketplaceAgents.id, { onDelete: 'cascade' }),
38
+ gatewayId: uuid('gateway_id')
39
+ .notNull()
40
+ .references(() => gateway.id, { onDelete: 'cascade' }),
41
+ installedAt: timestamp('installed_at', { withTimezone: true }).notNull().defaultNow(),
42
+ },
43
+ (t) => [
44
+ index('idx_marketplace_installs_tenant').on(t.tenantId),
45
+ index('idx_marketplace_installs_agent').on(t.agentId),
46
+ ],
47
+ );