Share one crew across the install, keep user memory per user
Bots, workspaces and computers now belong to the install. Users reach workers only through bot_users (assigned by a super admin or admin) and workspace_users; the coordinator and main computer are one per install, and only the super admin sees the coordinator. Conversations are per user (bot_sessions.user_id), jobs run for the session's user, and live updates go only to who should see them. A bot's core memory is now general knowledge shared by every user it works for; what it learns about a user lives in bot_user_memories. One-off scripts move existing installs over: move-bot-memory-to-owners (run first), then share-crew. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
+158
-26
@@ -208,15 +208,8 @@ const schema: BUN_SQLITE_DatabaseSchemaType = {
|
||||
fields: [
|
||||
{
|
||||
fieldName: "user_id",
|
||||
fieldDescription: `Bot owner`,
|
||||
fieldDescription: `Who created the bot. Not a foreign key, and not access: bots belong to the install, reached through \`bot_users\` and \`workspace_users\``,
|
||||
dataType: "INTEGER",
|
||||
foreignKey: {
|
||||
cascadeDelete: true,
|
||||
destinationTableName: "users",
|
||||
destinationTableColumnName: "id",
|
||||
destinationTableColumnType: "INTEGER",
|
||||
foreignKeyName: "bot_user_fk",
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: "name",
|
||||
@@ -259,7 +252,7 @@ const schema: BUN_SQLITE_DatabaseSchemaType = {
|
||||
},
|
||||
{
|
||||
fieldName: "memory",
|
||||
fieldDescription: `What the bot must always remember, in markdown. The bot keeps it up to date`,
|
||||
fieldDescription: `What the bot must always remember, in markdown, the same for every user it works with: never about one user (that's \`bot_user_memories\`). The bot keeps it up to date`,
|
||||
dataType: "TEXT",
|
||||
},
|
||||
{
|
||||
@@ -282,8 +275,20 @@ const schema: BUN_SQLITE_DatabaseSchemaType = {
|
||||
},
|
||||
{
|
||||
tableName: "bot_sessions",
|
||||
tableDescription: `A stretch of one conversation: a bot in its own chat (no workspace) or in one workspace. Only the active session's messages go to the model; closed ones can be searched and reopened`,
|
||||
tableDescription: `A stretch of one user's conversation with a bot: in its own chat (no workspace) or in one workspace. Every user has their own. Only the active session's messages go to the model; closed ones can be searched and reopened`,
|
||||
fields: [
|
||||
{
|
||||
fieldName: "user_id",
|
||||
fieldDescription: `The user the conversation is with: only they see it, and the bot's runs in it work for them`,
|
||||
dataType: "INTEGER",
|
||||
foreignKey: {
|
||||
cascadeDelete: true,
|
||||
destinationTableName: "users",
|
||||
destinationTableColumnName: "id",
|
||||
destinationTableColumnType: "INTEGER",
|
||||
foreignKeyName: "bot_session_user_fk",
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: "bot_id",
|
||||
fieldDescription: `The bot`,
|
||||
@@ -351,6 +356,10 @@ const schema: BUN_SQLITE_DatabaseSchemaType = {
|
||||
indexName: "idx_bot_sessions_workspace_id",
|
||||
indexTableFields: ["workspace_id"],
|
||||
},
|
||||
{
|
||||
indexName: "idx_bot_sessions_user_id",
|
||||
indexTableFields: ["user_id", "bot_id", "workspace_id", "status"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -825,15 +834,8 @@ const schema: BUN_SQLITE_DatabaseSchemaType = {
|
||||
fields: [
|
||||
{
|
||||
fieldName: "user_id",
|
||||
fieldDescription: `Workspace owner`,
|
||||
fieldDescription: `Who created the workspace. Not a foreign key, and not access: workspaces belong to the install, reached through \`workspace_users\``,
|
||||
dataType: "INTEGER",
|
||||
foreignKey: {
|
||||
cascadeDelete: true,
|
||||
destinationTableName: "users",
|
||||
destinationTableColumnName: "id",
|
||||
destinationTableColumnType: "INTEGER",
|
||||
foreignKeyName: "workspace_user_fk",
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: "name",
|
||||
@@ -925,6 +927,143 @@ const schema: BUN_SQLITE_DatabaseSchemaType = {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
tableName: "workspace_users",
|
||||
tableDescription: `Users added to a workspace (by a super admin or admin): they chat with every worker in it there`,
|
||||
fields: [
|
||||
{
|
||||
fieldName: "workspace_id",
|
||||
dataType: "INTEGER",
|
||||
foreignKey: {
|
||||
cascadeDelete: true,
|
||||
destinationTableName: "workspaces",
|
||||
destinationTableColumnName: "id",
|
||||
destinationTableColumnType: "INTEGER",
|
||||
foreignKeyName: "workspace_users_workspace_fk",
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: "user_id",
|
||||
dataType: "INTEGER",
|
||||
foreignKey: {
|
||||
cascadeDelete: true,
|
||||
destinationTableName: "users",
|
||||
destinationTableColumnName: "id",
|
||||
destinationTableColumnType: "INTEGER",
|
||||
foreignKeyName: "workspace_users_user_fk",
|
||||
},
|
||||
},
|
||||
],
|
||||
uniqueConstraints: [
|
||||
{
|
||||
alias: "one_user_per_workspace",
|
||||
constraintName: "A user joins a workspace once",
|
||||
constraintTableFields: [
|
||||
{ value: "workspace_id" },
|
||||
{ value: "user_id" },
|
||||
],
|
||||
},
|
||||
],
|
||||
indexes: [
|
||||
{
|
||||
indexName: "idx_workspace_users_user_id",
|
||||
indexTableFields: ["user_id"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
tableName: "bot_users",
|
||||
tableDescription: `Worker bots assigned to a user (by a super admin or admin): the user chats with the bot in its own chat. Nobody but the super admin reaches the coordinator`,
|
||||
fields: [
|
||||
{
|
||||
fieldName: "bot_id",
|
||||
dataType: "INTEGER",
|
||||
foreignKey: {
|
||||
cascadeDelete: true,
|
||||
destinationTableName: "bots",
|
||||
destinationTableColumnName: "id",
|
||||
destinationTableColumnType: "INTEGER",
|
||||
foreignKeyName: "bot_users_bot_fk",
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: "user_id",
|
||||
dataType: "INTEGER",
|
||||
foreignKey: {
|
||||
cascadeDelete: true,
|
||||
destinationTableName: "users",
|
||||
destinationTableColumnName: "id",
|
||||
destinationTableColumnType: "INTEGER",
|
||||
foreignKeyName: "bot_users_user_fk",
|
||||
},
|
||||
},
|
||||
],
|
||||
uniqueConstraints: [
|
||||
{
|
||||
alias: "one_user_per_bot",
|
||||
constraintName: "A bot is assigned to a user once",
|
||||
constraintTableFields: [
|
||||
{ value: "bot_id" },
|
||||
{ value: "user_id" },
|
||||
],
|
||||
},
|
||||
],
|
||||
indexes: [
|
||||
{
|
||||
indexName: "idx_bot_users_user_id",
|
||||
indexTableFields: ["user_id"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
tableName: "bot_user_memories",
|
||||
tableDescription: `What a bot remembers about one user (markdown). Only that user's runs see it, the way a workspace's memory stays in the workspace`,
|
||||
fields: [
|
||||
{
|
||||
fieldName: "bot_id",
|
||||
dataType: "INTEGER",
|
||||
foreignKey: {
|
||||
cascadeDelete: true,
|
||||
destinationTableName: "bots",
|
||||
destinationTableColumnName: "id",
|
||||
destinationTableColumnType: "INTEGER",
|
||||
foreignKeyName: "bot_user_memory_bot_fk",
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: "user_id",
|
||||
dataType: "INTEGER",
|
||||
foreignKey: {
|
||||
cascadeDelete: true,
|
||||
destinationTableName: "users",
|
||||
destinationTableColumnName: "id",
|
||||
destinationTableColumnType: "INTEGER",
|
||||
foreignKeyName: "bot_user_memory_user_fk",
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: "memory",
|
||||
fieldDescription: `What the bot must remember about this user (markdown), after its core memory. The bot keeps it up to date`,
|
||||
dataType: "TEXT",
|
||||
},
|
||||
],
|
||||
uniqueConstraints: [
|
||||
{
|
||||
alias: "one_memory_per_bot_user",
|
||||
constraintName: "A bot has one memory per user",
|
||||
constraintTableFields: [
|
||||
{ value: "bot_id" },
|
||||
{ value: "user_id" },
|
||||
],
|
||||
},
|
||||
],
|
||||
indexes: [
|
||||
{
|
||||
indexName: "idx_bot_user_memories_user_id",
|
||||
indexTableFields: ["user_id"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
tableName: "bot_message_media",
|
||||
tableDescription: `Files attached to a chat message (\`media\` rows, private to the message's owner)`,
|
||||
@@ -1039,15 +1178,8 @@ const schema: BUN_SQLITE_DatabaseSchemaType = {
|
||||
fields: [
|
||||
{
|
||||
fieldName: "user_id",
|
||||
fieldDescription: `Computer owner`,
|
||||
fieldDescription: `Who created the computer. Not a foreign key, and not access: computers belong to the install, reached through the bots that use them`,
|
||||
dataType: "INTEGER",
|
||||
foreignKey: {
|
||||
cascadeDelete: true,
|
||||
destinationTableName: "users",
|
||||
destinationTableColumnName: "id",
|
||||
destinationTableColumnType: "INTEGER",
|
||||
foreignKeyName: "computer_user_fk",
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: "container_id",
|
||||
|
||||
+67
-5
@@ -15,6 +15,9 @@ export const BunSQLiteTables = [
|
||||
"cron_jobs",
|
||||
"workspaces",
|
||||
"workspace_bots",
|
||||
"workspace_users",
|
||||
"bot_users",
|
||||
"bot_user_memories",
|
||||
"bot_message_media",
|
||||
"containers",
|
||||
"computers",
|
||||
@@ -160,7 +163,7 @@ export type BUN_SQLITE_COBBLE_BOTS = {
|
||||
*/
|
||||
updated_at?: number | "";
|
||||
/**
|
||||
* Bot owner
|
||||
* Who created the bot. Not a foreign key, and not access: bots belong to the install, reached through `bot_users` and `workspace_users`
|
||||
*/
|
||||
user_id?: number | "";
|
||||
name?: string;
|
||||
@@ -189,7 +192,7 @@ export type BUN_SQLITE_COBBLE_BOTS = {
|
||||
*/
|
||||
system_prompt?: string;
|
||||
/**
|
||||
* What the bot must always remember, in markdown. The bot keeps it up to date
|
||||
* What the bot must always remember, in markdown, the same for every user it works with: never about one user (that's `bot_user_memories`). The bot keeps it up to date
|
||||
*/
|
||||
memory?: string;
|
||||
/**
|
||||
@@ -215,6 +218,10 @@ export type BUN_SQLITE_COBBLE_BOT_SESSIONS = {
|
||||
* The time when the record was updated. (Unix Timestamp)
|
||||
*/
|
||||
updated_at?: number | "";
|
||||
/**
|
||||
* The user the conversation is with: only they see it, and the bot's runs in it work for them
|
||||
*/
|
||||
user_id?: number | "";
|
||||
/**
|
||||
* The bot
|
||||
*/
|
||||
@@ -543,7 +550,7 @@ export type BUN_SQLITE_COBBLE_WORKSPACES = {
|
||||
*/
|
||||
updated_at?: number | "";
|
||||
/**
|
||||
* Workspace owner
|
||||
* Who created the workspace. Not a foreign key, and not access: workspaces belong to the install, reached through `workspace_users`
|
||||
*/
|
||||
user_id?: number | "";
|
||||
name?: string;
|
||||
@@ -588,6 +595,61 @@ export type BUN_SQLITE_COBBLE_WORKSPACE_BOTS = {
|
||||
memory?: string;
|
||||
}
|
||||
|
||||
export type BUN_SQLITE_COBBLE_WORKSPACE_USERS = {
|
||||
/**
|
||||
* The unique identifier of the record.
|
||||
*/
|
||||
id?: number | "";
|
||||
/**
|
||||
* The time when the record was created. (Unix Timestamp)
|
||||
*/
|
||||
created_at?: number | "";
|
||||
/**
|
||||
* The time when the record was updated. (Unix Timestamp)
|
||||
*/
|
||||
updated_at?: number | "";
|
||||
workspace_id?: number | "";
|
||||
user_id?: number | "";
|
||||
}
|
||||
|
||||
export type BUN_SQLITE_COBBLE_BOT_USERS = {
|
||||
/**
|
||||
* The unique identifier of the record.
|
||||
*/
|
||||
id?: number | "";
|
||||
/**
|
||||
* The time when the record was created. (Unix Timestamp)
|
||||
*/
|
||||
created_at?: number | "";
|
||||
/**
|
||||
* The time when the record was updated. (Unix Timestamp)
|
||||
*/
|
||||
updated_at?: number | "";
|
||||
bot_id?: number | "";
|
||||
user_id?: number | "";
|
||||
}
|
||||
|
||||
export type BUN_SQLITE_COBBLE_BOT_USER_MEMORIES = {
|
||||
/**
|
||||
* The unique identifier of the record.
|
||||
*/
|
||||
id?: number | "";
|
||||
/**
|
||||
* The time when the record was created. (Unix Timestamp)
|
||||
*/
|
||||
created_at?: number | "";
|
||||
/**
|
||||
* The time when the record was updated. (Unix Timestamp)
|
||||
*/
|
||||
updated_at?: number | "";
|
||||
bot_id?: number | "";
|
||||
user_id?: number | "";
|
||||
/**
|
||||
* What the bot must remember about this user (markdown), after its core memory. The bot keeps it up to date
|
||||
*/
|
||||
memory?: string;
|
||||
}
|
||||
|
||||
export type BUN_SQLITE_COBBLE_BOT_MESSAGE_MEDIA = {
|
||||
/**
|
||||
* The unique identifier of the record.
|
||||
@@ -675,7 +737,7 @@ export type BUN_SQLITE_COBBLE_COMPUTERS = {
|
||||
*/
|
||||
updated_at?: number | "";
|
||||
/**
|
||||
* Computer owner
|
||||
* Who created the computer. Not a foreign key, and not access: computers belong to the install, reached through the bots that use them
|
||||
*/
|
||||
user_id?: number | "";
|
||||
/**
|
||||
@@ -1040,4 +1102,4 @@ export type BUN_SQLITE_COBBLE_ENVS = {
|
||||
expose_to_computers?: 0 | 1 | "";
|
||||
}
|
||||
|
||||
export type BUN_SQLITE_COBBLE_ALL_TYPEDEFS = BUN_SQLITE_COBBLE_USERS & BUN_SQLITE_COBBLE_USER_TYPES & BUN_SQLITE_COBBLE_SSO_LOGIN_CODES & BUN_SQLITE_COBBLE_USER_PASSWORDS & BUN_SQLITE_COBBLE_MEDIA & BUN_SQLITE_COBBLE_MEDIA_PARADIGMS & BUN_SQLITE_COBBLE_BOTS & BUN_SQLITE_COBBLE_BOT_SESSIONS & BUN_SQLITE_COBBLE_BOT_MESSAGES & BUN_SQLITE_COBBLE_BOT_TASKS & BUN_SQLITE_COBBLE_BOT_TASK_STEPS & BUN_SQLITE_COBBLE_BOTS_QUEUE & BUN_SQLITE_COBBLE_BOTS_QUEUE_UPDATES & BUN_SQLITE_COBBLE_CRON_JOBS & BUN_SQLITE_COBBLE_WORKSPACES & BUN_SQLITE_COBBLE_WORKSPACE_BOTS & BUN_SQLITE_COBBLE_BOT_MESSAGE_MEDIA & BUN_SQLITE_COBBLE_CONTAINERS & BUN_SQLITE_COBBLE_COMPUTERS & BUN_SQLITE_COBBLE_BOT_COMPUTERS & BUN_SQLITE_COBBLE_WORKSPACE_COMPUTERS & BUN_SQLITE_COBBLE_HARNESS_PROVIDERS & BUN_SQLITE_COBBLE_HARNESS_MODELS & BUN_SQLITE_COBBLE_HARNESS_SETTINGS & BUN_SQLITE_COBBLE_BOT_HARNESS_SETTINGS & BUN_SQLITE_COBBLE_WORKSPACE_HARNESS_SETTINGS & BUN_SQLITE_COBBLE_LOGS & BUN_SQLITE_COBBLE_ENVS
|
||||
export type BUN_SQLITE_COBBLE_ALL_TYPEDEFS = BUN_SQLITE_COBBLE_USERS & BUN_SQLITE_COBBLE_USER_TYPES & BUN_SQLITE_COBBLE_SSO_LOGIN_CODES & BUN_SQLITE_COBBLE_USER_PASSWORDS & BUN_SQLITE_COBBLE_MEDIA & BUN_SQLITE_COBBLE_MEDIA_PARADIGMS & BUN_SQLITE_COBBLE_BOTS & BUN_SQLITE_COBBLE_BOT_SESSIONS & BUN_SQLITE_COBBLE_BOT_MESSAGES & BUN_SQLITE_COBBLE_BOT_TASKS & BUN_SQLITE_COBBLE_BOT_TASK_STEPS & BUN_SQLITE_COBBLE_BOTS_QUEUE & BUN_SQLITE_COBBLE_BOTS_QUEUE_UPDATES & BUN_SQLITE_COBBLE_CRON_JOBS & BUN_SQLITE_COBBLE_WORKSPACES & BUN_SQLITE_COBBLE_WORKSPACE_BOTS & BUN_SQLITE_COBBLE_WORKSPACE_USERS & BUN_SQLITE_COBBLE_BOT_USERS & BUN_SQLITE_COBBLE_BOT_USER_MEMORIES & BUN_SQLITE_COBBLE_BOT_MESSAGE_MEDIA & BUN_SQLITE_COBBLE_CONTAINERS & BUN_SQLITE_COBBLE_COMPUTERS & BUN_SQLITE_COBBLE_BOT_COMPUTERS & BUN_SQLITE_COBBLE_WORKSPACE_COMPUTERS & BUN_SQLITE_COBBLE_HARNESS_PROVIDERS & BUN_SQLITE_COBBLE_HARNESS_MODELS & BUN_SQLITE_COBBLE_HARNESS_SETTINGS & BUN_SQLITE_COBBLE_BOT_HARNESS_SETTINGS & BUN_SQLITE_COBBLE_WORKSPACE_HARNESS_SETTINGS & BUN_SQLITE_COBBLE_LOGS & BUN_SQLITE_COBBLE_ENVS
|
||||
Reference in New Issue
Block a user