@naisys/hub-database 3.0.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +84 -0
- package/dist/dbConfig.js +4 -0
- package/dist/generated/prisma/browser.js +17 -0
- package/dist/generated/prisma/client.js +34 -0
- package/dist/generated/prisma/commonInputTypes.js +10 -0
- package/dist/generated/prisma/enums.js +56 -0
- package/dist/generated/prisma/internal/class.js +49 -0
- package/dist/generated/prisma/internal/prismaNamespace.js +248 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +219 -0
- package/dist/generated/prisma/models/attachments.js +1 -0
- package/dist/generated/prisma/models/config_revisions.js +1 -0
- package/dist/generated/prisma/models/context_log.js +1 -0
- package/dist/generated/prisma/models/costs.js +1 -0
- package/dist/generated/prisma/models/hosts.js +1 -0
- package/dist/generated/prisma/models/mail_attachments.js +1 -0
- package/dist/generated/prisma/models/mail_messages.js +1 -0
- package/dist/generated/prisma/models/mail_recipients.js +1 -0
- package/dist/generated/prisma/models/models.js +1 -0
- package/dist/generated/prisma/models/run_session.js +1 -0
- package/dist/generated/prisma/models/schema_version.js +1 -0
- package/dist/generated/prisma/models/user_hosts.js +1 -0
- package/dist/generated/prisma/models/user_notifications.js +1 -0
- package/dist/generated/prisma/models/users.js +1 -0
- package/dist/generated/prisma/models/variables.js +1 -0
- package/dist/generated/prisma/models.js +1 -0
- package/dist/hubDatabaseService.js +38 -0
- package/dist/hubSessionService.js +112 -0
- package/dist/index.js +13 -0
- package/dist/prismaClient.js +21 -0
- package/package.json +42 -0
- package/prisma/migrations/20260223234341_init/migration.sql +237 -0
- package/prisma/migrations/20260225041145_add_host_restricted/migration.sql +20 -0
- package/prisma/migrations/20260227000000_add_host_type/migration.sql +21 -0
- package/prisma/migrations/20260302000000_make_from_user_id_not_null/migration.sql +37 -0
- package/prisma/migrations/20260302100000_add_cost_suspended_reason/migration.sql +2 -0
- package/prisma/migrations/20260305000000_make_participant_ids_not_null/migration.sql +31 -0
- package/prisma/migrations/20260306000000_add_host_last_ip/migration.sql +1 -0
- package/prisma/migrations/20260310000000_rename_participant_ids_to_participants/migration.sql +61 -0
- package/prisma/migrations/20260312000000_fix_empty_enum_strings/migration.sql +31 -0
- package/prisma/migrations/20260313000000_add_user_enabled/migration.sql +5 -0
- package/prisma/migrations/20260327000000_add_config_revisions/migration.sql +13 -0
- package/prisma/migrations/20260328000000_add_from_recipient_type/migration.sql +13 -0
- package/prisma/migrations/20260328100000_add_spend_limit_reset_at/migration.sql +1 -0
- package/prisma/migrations/20260328200000_add_budget_left/migration.sql +1 -0
- package/prisma/migrations/20260401000000_rename_workspace_to_tool/migration.sql +2 -0
- package/prisma/migrations/20260403000000_add_export_to_shell/migration.sql +2 -0
- package/prisma/migrations/20260404000000_add_attachment_public_id/migration.sql +8 -0
- package/prisma/migrations/migration_lock.toml +3 -0
- package/prisma/schema.prisma +307 -0
- package/prisma.config.ts +18 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
generator client {
|
|
2
|
+
provider = "prisma-client"
|
|
3
|
+
output = "../src/generated/prisma"
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
datasource db {
|
|
7
|
+
provider = "sqlite"
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// --- Enums (client-side only for SQLite — stored as TEXT) ---
|
|
11
|
+
// These enums are intentionally duplicated as Zod schemas in @naisys/hub-protocol
|
|
12
|
+
// and @naisys-supervisor/shared to avoid pulling heavy native deps (better-sqlite3,
|
|
13
|
+
// @prisma/client) into lightweight shared packages. The sync test in
|
|
14
|
+
// apps/supervisor/server/src/tests/hub-enum-sync.test.ts ensures they stay aligned.
|
|
15
|
+
|
|
16
|
+
enum ContextLogRole {
|
|
17
|
+
NAISYS
|
|
18
|
+
LLM
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
enum ContextLogSource {
|
|
22
|
+
startPrompt
|
|
23
|
+
endPrompt
|
|
24
|
+
console
|
|
25
|
+
llm
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
enum ContextLogType {
|
|
29
|
+
comment
|
|
30
|
+
error
|
|
31
|
+
system
|
|
32
|
+
tool
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
enum MessageKind {
|
|
36
|
+
mail
|
|
37
|
+
chat
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
enum RecipientType {
|
|
41
|
+
to
|
|
42
|
+
cc
|
|
43
|
+
bcc
|
|
44
|
+
from
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
enum AttachmentPurpose {
|
|
48
|
+
mail
|
|
49
|
+
context
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
enum HostType {
|
|
53
|
+
naisys
|
|
54
|
+
supervisor
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
enum ModelType {
|
|
58
|
+
llm
|
|
59
|
+
image
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
enum CostSource {
|
|
63
|
+
console
|
|
64
|
+
write_protection
|
|
65
|
+
compact
|
|
66
|
+
lynx
|
|
67
|
+
look
|
|
68
|
+
listen
|
|
69
|
+
genimg
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// --- Models ---
|
|
73
|
+
|
|
74
|
+
model context_log {
|
|
75
|
+
id Int @id @default(autoincrement())
|
|
76
|
+
user_id Int
|
|
77
|
+
run_id Int
|
|
78
|
+
session_id Int
|
|
79
|
+
host_id Int
|
|
80
|
+
role ContextLogRole
|
|
81
|
+
source ContextLogSource?
|
|
82
|
+
type ContextLogType?
|
|
83
|
+
message String
|
|
84
|
+
attachment_id Int?
|
|
85
|
+
created_at DateTime @default(now())
|
|
86
|
+
users users @relation("context_log_user", fields: [user_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
|
|
87
|
+
run_session run_session @relation(fields: [user_id, run_id, session_id], references: [user_id, run_id, session_id], onDelete: NoAction, onUpdate: NoAction)
|
|
88
|
+
host hosts @relation(fields: [host_id], references: [id])
|
|
89
|
+
attachment attachments? @relation(fields: [attachment_id], references: [id], onDelete: SetNull, onUpdate: NoAction)
|
|
90
|
+
|
|
91
|
+
@@index([user_id, run_id, session_id], map: "idx_context_log_user_run_session") // WHERE user_id, run_id, session_id in runsService.getContextLog
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
model costs {
|
|
95
|
+
id Int @id @default(autoincrement())
|
|
96
|
+
user_id Int
|
|
97
|
+
run_id Int
|
|
98
|
+
session_id Int
|
|
99
|
+
host_id Int
|
|
100
|
+
source CostSource
|
|
101
|
+
model String
|
|
102
|
+
cost Float? @default(0)
|
|
103
|
+
input_tokens Int? @default(0)
|
|
104
|
+
output_tokens Int? @default(0)
|
|
105
|
+
cache_write_tokens Int? @default(0)
|
|
106
|
+
cache_read_tokens Int? @default(0)
|
|
107
|
+
created_at DateTime @default(now())
|
|
108
|
+
users users @relation("costs_user", fields: [user_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
|
|
109
|
+
run_session run_session @relation(fields: [user_id, run_id, session_id], references: [user_id, run_id, session_id], onDelete: NoAction, onUpdate: NoAction)
|
|
110
|
+
host hosts @relation(fields: [host_id], references: [id])
|
|
111
|
+
|
|
112
|
+
@@index([created_at], map: "idx_costs_created_at") // ORDER BY created_at DESC, WHERE created_at >= in aggregate time range filtering
|
|
113
|
+
@@index([user_id], map: "idx_costs_user_id") // Optional WHERE user_id filter in aggregate spend limit queries
|
|
114
|
+
@@index([user_id, run_id, session_id, source, model], map: "idx_costs_user_run_session_source_model") // WHERE user_id, run_id, session_id, source, model in hubCostService findFirst
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
model mail_messages {
|
|
118
|
+
id Int @id @default(autoincrement())
|
|
119
|
+
from_user_id Int
|
|
120
|
+
host_id Int? // Sender's host
|
|
121
|
+
kind MessageKind @default(mail)
|
|
122
|
+
participants String // Sorted CSV of participant usernames, used as conversation lookup key
|
|
123
|
+
subject String
|
|
124
|
+
body String
|
|
125
|
+
created_at DateTime @default(now())
|
|
126
|
+
from_user users @relation("mail_messages_from_user", fields: [from_user_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
|
127
|
+
host hosts? @relation(fields: [host_id], references: [id])
|
|
128
|
+
recipients mail_recipients[]
|
|
129
|
+
mail_attachments mail_attachments[]
|
|
130
|
+
|
|
131
|
+
@@index([from_user_id], map: "idx_mail_messages_from_user_id") // WHERE from_user_id in sent messages filter
|
|
132
|
+
@@index([created_at(sort: Desc)], map: "idx_mail_messages_created_at_desc") // ORDER BY created_at DESC in listMessages and searchMessages
|
|
133
|
+
@@index([participants], map: "idx_mail_messages_participants") // WHERE participants in chat recent filtering
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
model attachments {
|
|
137
|
+
id Int @id @default(autoincrement())
|
|
138
|
+
public_id String @unique
|
|
139
|
+
filepath String
|
|
140
|
+
filename String
|
|
141
|
+
file_size Int
|
|
142
|
+
file_hash String
|
|
143
|
+
purpose AttachmentPurpose
|
|
144
|
+
uploaded_by Int
|
|
145
|
+
created_at DateTime @default(now())
|
|
146
|
+
uploader users @relation("uploaded_attachments", fields: [uploaded_by], references: [id], onDelete: NoAction, onUpdate: NoAction)
|
|
147
|
+
mail_attachments mail_attachments[]
|
|
148
|
+
context_logs context_log[]
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
model mail_attachments {
|
|
152
|
+
message_id Int
|
|
153
|
+
attachment_id Int
|
|
154
|
+
created_at DateTime @default(now())
|
|
155
|
+
message mail_messages @relation(fields: [message_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
|
|
156
|
+
attachment attachments @relation(fields: [attachment_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
|
|
157
|
+
|
|
158
|
+
@@id([message_id, attachment_id])
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
model mail_recipients {
|
|
162
|
+
id Int @id @default(autoincrement())
|
|
163
|
+
message_id Int
|
|
164
|
+
user_id Int
|
|
165
|
+
type RecipientType
|
|
166
|
+
read_at DateTime?
|
|
167
|
+
archived_at DateTime?
|
|
168
|
+
created_at DateTime @default(now())
|
|
169
|
+
message mail_messages @relation(fields: [message_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
|
|
170
|
+
user users @relation(fields: [user_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
|
|
171
|
+
|
|
172
|
+
@@index([message_id, user_id], map: "idx_mail_recipients_message_user") // JOIN from mail_messages includes, WHERE message_id + user_id in read/archive updateMany
|
|
173
|
+
@@index([user_id, message_id(sort: Desc)], map: "idx_mail_recipients_user_message_desc") // recipients.some({ user_id }) in mail list/search/unread filtering
|
|
174
|
+
@@index([read_at, user_id], map: "idx_mail_recipients_read_at_user_id") // WHERE read_at IS NULL with distinct/select user_id for auto-start candidate scans
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
model users {
|
|
178
|
+
id Int @id @default(autoincrement())
|
|
179
|
+
uuid String @unique
|
|
180
|
+
username String @unique
|
|
181
|
+
title String
|
|
182
|
+
api_key String @unique
|
|
183
|
+
lead_user_id Int?
|
|
184
|
+
config String @default("{}")
|
|
185
|
+
created_at DateTime @default(now())
|
|
186
|
+
updated_at DateTime @updatedAt
|
|
187
|
+
enabled Boolean @default(true)
|
|
188
|
+
archived Boolean @default(false)
|
|
189
|
+
lead_user users? @relation("lead_to_subagents", fields: [lead_user_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
|
|
190
|
+
subagents users[] @relation("lead_to_subagents")
|
|
191
|
+
mail_messages_sent mail_messages[] @relation("mail_messages_from_user")
|
|
192
|
+
mail_recipients mail_recipients[]
|
|
193
|
+
run_sessions run_session[]
|
|
194
|
+
context_logs context_log[] @relation("context_log_user")
|
|
195
|
+
costs costs[] @relation("costs_user")
|
|
196
|
+
uploaded_attachments attachments[] @relation("uploaded_attachments")
|
|
197
|
+
user_notifications user_notifications?
|
|
198
|
+
user_hosts user_hosts[]
|
|
199
|
+
config_revisions config_revisions[] @relation("config_revision_user")
|
|
200
|
+
config_changes_made config_revisions[] @relation("config_revision_changed_by")
|
|
201
|
+
// username has @unique which creates an implicit index
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
model user_notifications {
|
|
205
|
+
user_id Int @id
|
|
206
|
+
latest_host_id Int?
|
|
207
|
+
latest_log_id Int @default(0)
|
|
208
|
+
latest_mail_id Int @default(0)
|
|
209
|
+
latest_chat_id Int @default(0)
|
|
210
|
+
last_active DateTime?
|
|
211
|
+
cost_suspended_reason String?
|
|
212
|
+
spend_limit_reset_at DateTime?
|
|
213
|
+
budget_left Decimal?
|
|
214
|
+
updated_at DateTime @updatedAt
|
|
215
|
+
users users @relation(fields: [user_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
|
|
216
|
+
host hosts? @relation(fields: [latest_host_id], references: [id])
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
model user_hosts {
|
|
220
|
+
user_id Int
|
|
221
|
+
host_id Int
|
|
222
|
+
created_at DateTime @default(now())
|
|
223
|
+
users users @relation(fields: [user_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
|
|
224
|
+
host hosts @relation(fields: [host_id], references: [id])
|
|
225
|
+
|
|
226
|
+
@@id([user_id, host_id])
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
model run_session {
|
|
230
|
+
user_id Int
|
|
231
|
+
run_id Int
|
|
232
|
+
session_id Int
|
|
233
|
+
host_id Int
|
|
234
|
+
last_active DateTime
|
|
235
|
+
model_name String
|
|
236
|
+
latest_log_id Int @default(0)
|
|
237
|
+
total_lines Int @default(0)
|
|
238
|
+
total_cost Float @default(0)
|
|
239
|
+
created_at DateTime @default(now())
|
|
240
|
+
updated_at DateTime @updatedAt
|
|
241
|
+
users users @relation(fields: [user_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
|
|
242
|
+
host hosts @relation(fields: [host_id], references: [id])
|
|
243
|
+
context_logs context_log[]
|
|
244
|
+
costs costs[]
|
|
245
|
+
|
|
246
|
+
@@id([user_id, run_id, session_id])
|
|
247
|
+
@@index([run_id(sort: Desc)], map: "idx_run_session_run_id_desc") // ORDER BY run_id DESC in hubRunService to find max run_id for new runs
|
|
248
|
+
@@index([user_id, last_active(sort: Desc)], map: "idx_run_session_user_last_active_desc") // WHERE user_id ORDER BY last_active DESC in supervisor runsService pagination
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
model schema_version {
|
|
252
|
+
id Int @id @default(1)
|
|
253
|
+
version Int @unique(map: "unq_schema_version_version")
|
|
254
|
+
updated DateTime
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
model hosts {
|
|
258
|
+
id Int @id @default(autoincrement())
|
|
259
|
+
name String @unique(map: "unq_hosts_name") // NAISYS_HOSTNAME
|
|
260
|
+
restricted Boolean @default(false)
|
|
261
|
+
host_type HostType @default(naisys)
|
|
262
|
+
last_ip String?
|
|
263
|
+
last_active DateTime?
|
|
264
|
+
created_at DateTime @default(now())
|
|
265
|
+
user_notifications user_notifications[]
|
|
266
|
+
mail_messages mail_messages[]
|
|
267
|
+
run_sessions run_session[]
|
|
268
|
+
costs costs[]
|
|
269
|
+
context_logs context_log[]
|
|
270
|
+
user_hosts user_hosts[]
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
model config_revisions {
|
|
274
|
+
id Int @id @default(autoincrement())
|
|
275
|
+
user_id Int
|
|
276
|
+
config String
|
|
277
|
+
changed_by_id Int
|
|
278
|
+
created_at DateTime @default(now())
|
|
279
|
+
|
|
280
|
+
user users @relation("config_revision_user", fields: [user_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
|
281
|
+
changed_by users @relation("config_revision_changed_by", fields: [changed_by_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
|
|
282
|
+
|
|
283
|
+
@@index([user_id, created_at(sort: Desc)], map: "idx_config_revisions_user_created_desc")
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
model variables {
|
|
287
|
+
key String @id
|
|
288
|
+
value String
|
|
289
|
+
export_to_shell Boolean @default(false)
|
|
290
|
+
created_by String
|
|
291
|
+
updated_by String
|
|
292
|
+
created_at DateTime @default(now())
|
|
293
|
+
updated_at DateTime @updatedAt
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
model models {
|
|
297
|
+
id Int @id @default(autoincrement())
|
|
298
|
+
key String @unique
|
|
299
|
+
type ModelType
|
|
300
|
+
label String
|
|
301
|
+
version_name String
|
|
302
|
+
is_builtin Boolean @default(false)
|
|
303
|
+
is_custom Boolean @default(false)
|
|
304
|
+
meta String // JSON blob — type-specific properties validated by Zod
|
|
305
|
+
created_at DateTime @default(now())
|
|
306
|
+
updated_at DateTime @updatedAt
|
|
307
|
+
}
|
package/prisma.config.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import "dotenv/config";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { defineConfig } from "prisma/config";
|
|
4
|
+
|
|
5
|
+
// Use placeholder during generation, actual path provided at runtime
|
|
6
|
+
const naisysFolder = process.env.NAISYS_FOLDER || "";
|
|
7
|
+
|
|
8
|
+
export default defineConfig({
|
|
9
|
+
schema: "prisma/schema.prisma",
|
|
10
|
+
migrations: {
|
|
11
|
+
path: "prisma/migrations",
|
|
12
|
+
},
|
|
13
|
+
datasource: {
|
|
14
|
+
// Used in dev when we run migrate manually to generate migration scripts
|
|
15
|
+
// Used in prod when self-migrating an existing database
|
|
16
|
+
url: `file:` + join(naisysFolder, "database", `naisys_hub.db`),
|
|
17
|
+
},
|
|
18
|
+
});
|