diff --git a/AgentCompany-New/src/main/database/migrations/001-initial.ts b/AgentCompany-New/src/main/database/migrations/001-initial.ts new file mode 100644 index 00000000..7b317626 --- /dev/null +++ b/AgentCompany-New/src/main/database/migrations/001-initial.ts @@ -0,0 +1,235 @@ +export const initialEnterpriseSchema = ` + create table if not exists organizations ( + id text primary key, + name text not null, + mission text not null, + goal text not null, + created_at text not null + ); + + create table if not exists employees ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + display_name text not null, + role text not null, + created_at text not null + ); + + create table if not exists agents ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + name text not null, + role text not null, + department text not null, + model_provider_id text, + model_id text, + budget_cents integer not null, + manager_agent_id text references agents(id) on delete set null, + lifecycle text not null, + created_at text not null + ); + + create table if not exists tasks ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + title text not null, + description text not null, + status text not null, + assignee_agent_id text references agents(id) on delete set null, + risk text not null, + created_at text not null, + updated_at text not null + ); + + create table if not exists approvals ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + kind text not null, + title text not null, + details text not null, + risk text not null, + requested_by_type text not null, + requested_by_id text, + state text not null, + decided_by_employee_id text references employees(id) on delete set null, + created_at text not null, + decided_at text + ); + + create table if not exists chat_spaces ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + space_type text not null, + name text not null, + topic text not null, + visibility text not null, + created_at text not null + ); + + create table if not exists chat_memberships ( + space_id text not null references chat_spaces(id) on delete cascade, + principal_type text not null, + principal_id text not null, + role text not null, + mute_state text not null, + primary key (space_id, principal_type, principal_id) + ); + + create table if not exists chat_messages ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + space_id text not null references chat_spaces(id) on delete cascade, + thread_id text, + sender_type text not null, + sender_id text, + body_md text not null, + created_at text not null, + edited_at text, + deleted_at text + ); + + create table if not exists file_objects ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + name text not null, + kind text not null, + size_bytes integer not null, + sha256 text not null, + storage_path text not null, + owner_type text not null, + owner_id text, + created_at text not null + ); + + create table if not exists providers ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + provider_key text not null, + label text not null, + auth_type text not null, + model text, + credential_id text, + enabled integer not null, + created_at text not null, + unique(org_id, provider_key) + ); + + create table if not exists credentials ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + provider_key text not null, + kind text not null, + ciphertext blob not null, + display_hint text not null, + created_at text not null + ); + + create table if not exists skill_definitions ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + slug text not null, + name text not null, + owner_type text not null, + status text not null, + created_at text not null, + unique(org_id, slug) + ); + + create table if not exists skill_revisions ( + id text primary key, + skill_id text not null references skill_definitions(id) on delete cascade, + version_semver text not null, + manifest_json text not null, + source_type text not null, + source_ref text not null, + published_at text not null, + immutable_checksum text not null, + unique(skill_id, version_semver) + ); + + create table if not exists skill_artifacts ( + id text primary key, + revision_id text not null references skill_revisions(id) on delete cascade, + artifact_type text not null, + object_key text not null, + sha256 text not null, + size_bytes integer not null + ); + + create table if not exists skill_tests ( + id text primary key, + revision_id text not null references skill_revisions(id) on delete cascade, + test_type text not null, + expected_output_ref text not null, + last_result text, + last_run_at text + ); + + create table if not exists skill_bindings ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + agent_id text not null references agents(id) on delete cascade, + skill_id text not null references skill_definitions(id) on delete cascade, + pinned_revision_id text not null references skill_revisions(id) on delete cascade, + binding_mode text not null, + priority integer not null, + enabled integer not null, + unique(agent_id, skill_id) + ); + + create table if not exists social_accounts ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + platform text not null, + handle text not null, + display_name text not null, + authorized_employee_id text references employees(id) on delete set null, + created_at text not null + ); + + create table if not exists social_account_grants ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + social_account_id text not null references social_accounts(id) on delete cascade, + employee_id text not null references employees(id) on delete cascade, + role text not null, + scope_json text not null, + created_at text not null + ); + + create table if not exists browser_actions ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + social_account_id text not null references social_accounts(id) on delete cascade, + action_type text not null, + policy_decision text not null, + evidence_file_id text references file_objects(id) on delete set null, + created_at text not null + ); + + create table if not exists migration_reports ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + source_ref text not null, + report_json text not null, + created_at text not null + ); + + create table if not exists audit_events ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + entity_type text not null, + entity_id text not null, + actor_type text not null, + actor_id text, + action text not null, + payload_json text not null, + created_at text not null + ); + + create index if not exists idx_tasks_org_status on tasks(org_id, status); + create index if not exists idx_messages_space_created on chat_messages(space_id, created_at); + create index if not exists idx_audit_org_created on audit_events(org_id, created_at); + insert into schema_migrations(version, name, applied_at) + values (1, 'initial_enterprise_schema', datetime('now')); +`; diff --git a/AgentCompany-New/src/main/database/migrations/002-collaboration.ts b/AgentCompany-New/src/main/database/migrations/002-collaboration.ts new file mode 100644 index 00000000..408789be --- /dev/null +++ b/AgentCompany-New/src/main/database/migrations/002-collaboration.ts @@ -0,0 +1,117 @@ +export const collaborationProviderPolicySchema = ` + create table if not exists skill_dependencies ( + revision_id text not null references skill_revisions(id) on delete cascade, + depends_on_revision_id text not null references skill_revisions(id) on delete cascade, + dependency_kind text not null, + optional integer not null, + primary key (revision_id, depends_on_revision_id) + ); + + create table if not exists skill_runtime_snapshots ( + id text primary key, + agent_id text not null references agents(id) on delete cascade, + run_id text not null, + compiled_prompt text not null, + tools_manifest text not null, + source_revision_ids text not null, + created_at text not null + ); + + create table if not exists skill_catalog_tags ( + skill_id text not null references skill_definitions(id) on delete cascade, + tag text not null, + tag_type text not null, + primary key (skill_id, tag, tag_type) + ); + + create table if not exists chat_threads ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + space_id text not null references chat_spaces(id) on delete cascade, + root_message_id text references chat_messages(id) on delete set null, + title text not null, + state text not null, + created_at text not null, + updated_at text not null + ); + + create table if not exists chat_mentions ( + message_id text not null references chat_messages(id) on delete cascade, + target_type text not null, + target_id text not null, + offset_start integer not null, + offset_end integer not null + ); + + create table if not exists chat_attachments ( + message_id text not null references chat_messages(id) on delete cascade, + file_id text not null references file_objects(id) on delete cascade, + transfer_type text not null, + checksum text not null, + preview_key text + ); + + create table if not exists chat_presence ( + principal_type text not null, + principal_id text not null, + status text not null, + status_text text not null, + last_seen_at text not null, + primary key (principal_type, principal_id) + ); + + create table if not exists chat_slash_invocations ( + id text primary key, + message_id text not null references chat_messages(id) on delete cascade, + command text not null, + args_json text not null, + result_ref text, + created_at text not null + ); + + create table if not exists provider_requests ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + provider_id text not null references providers(id) on delete cascade, + provider_key text not null, + model text not null, + prompt_sha256 text not null, + response_text text, + raw_response_json text, + state text not null, + error_message text, + created_at text not null, + completed_at text + ); + + create table if not exists policy_rules ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + subject_type text not null, + subject_id text, + action text not null, + effect text not null, + risk_ceiling text not null, + created_at text not null + ); + + create index if not exists idx_provider_requests_org_created on provider_requests(org_id, created_at); + create index if not exists idx_chat_threads_space_updated on chat_threads(space_id, updated_at); + insert into policy_rules(id, org_id, subject_type, subject_id, action, effect, risk_ceiling, created_at) + select + 'pol_' || lower(hex(randomblob(16))), + id, + 'organization', + id, + 'task_create', + 'require_approval', + 'medium', + datetime('now') + from organizations + where not exists ( + select 1 from policy_rules + where policy_rules.org_id = organizations.id and policy_rules.action = 'task_create' + ); + insert into schema_migrations(version, name, applied_at) + values (2, 'collaboration_provider_policy_schema', datetime('now')); +`; diff --git a/AgentCompany-New/src/main/database/migrations/003-onboarding.ts b/AgentCompany-New/src/main/database/migrations/003-onboarding.ts new file mode 100644 index 00000000..5b52c831 --- /dev/null +++ b/AgentCompany-New/src/main/database/migrations/003-onboarding.ts @@ -0,0 +1,76 @@ +export const onboardingExecutionSchema = ` + alter table organizations add column description text not null default ''; + alter table organizations add column execution_mode text not null default 'ai_ceo'; + alter table organizations add column auto_approve_hires integer not null default 1; + alter table organizations add column review_deliverables integer not null default 0; + + alter table agents add column title text not null default ''; + alter table agents add column role_level text not null default 'staff'; + alter table agents add column model_strategy text not null default 'pooled'; + alter table agents add column workspace_id text; + alter table agents add column heartbeat_enabled integer not null default 0; + alter table agents add column heartbeat_interval_sec integer not null default 0; + + alter table tasks add column project_id text; + alter table tasks add column goal_id text; + alter table tasks add column workspace_id text; + alter table tasks add column priority text not null default 'normal'; + alter table tasks add column requires_filesystem integer not null default 0; + + create table if not exists workspaces ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + name text not null, + local_path text not null, + repo_url text not null, + repo_ref text not null, + project_id text, + is_primary integer not null, + created_at text not null, + updated_at text not null + ); + + create table if not exists goals ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + title text not null, + description text not null, + status text not null, + owner_agent_id text references agents(id) on delete set null, + created_at text not null, + updated_at text not null + ); + + create table if not exists projects ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + goal_id text references goals(id) on delete set null, + name text not null, + description text not null, + lead_agent_id text references agents(id) on delete set null, + status text not null, + created_at text not null, + updated_at text not null + ); + + create table if not exists task_runs ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + task_id text not null references tasks(id) on delete cascade, + agent_id text references agents(id) on delete set null, + provider_id text references providers(id) on delete set null, + trigger text not null, + state text not null, + created_at text not null, + started_at text, + completed_at text, + error_message text + ); + + create index if not exists idx_workspaces_org_primary on workspaces(org_id, is_primary); + create index if not exists idx_goals_org_status on goals(org_id, status); + create index if not exists idx_projects_org_status on projects(org_id, status); + create index if not exists idx_task_runs_task_created on task_runs(task_id, created_at); + insert into schema_migrations(version, name, applied_at) + values (3, 'onboarding_execution_schema', datetime('now')); +`; diff --git a/AgentCompany-New/src/main/database/migrations/004-files-posts.ts b/AgentCompany-New/src/main/database/migrations/004-files-posts.ts new file mode 100644 index 00000000..dc7cd07c --- /dev/null +++ b/AgentCompany-New/src/main/database/migrations/004-files-posts.ts @@ -0,0 +1,25 @@ +export const filesPinnedAndScheduledPosts = ` + alter table file_objects add column pinned integer not null default 0; + alter table file_objects add column space_id text; + alter table file_objects add column updated_at text; + + create table if not exists scheduled_posts ( + id text primary key, + org_id text not null references organizations(id) on delete cascade, + social_account_id text not null references social_accounts(id) on delete cascade, + body_md text not null, + scheduled_for text not null, + state text not null, + approval_id text references approvals(id) on delete set null, + created_by_employee_id text references employees(id) on delete set null, + created_at text not null, + updated_at text not null + ); + + create index if not exists idx_files_org_pinned on file_objects(org_id, pinned); + create index if not exists idx_scheduled_posts_org_state on scheduled_posts(org_id, state); + create index if not exists idx_scheduled_posts_account_date on scheduled_posts(social_account_id, scheduled_for); + + insert into schema_migrations(version, name, applied_at) + values (4, 'files_pinned_and_scheduled_posts', datetime('now')); +`; diff --git a/AgentCompany-New/src/main/database/migrations/005-chat-read-state.ts b/AgentCompany-New/src/main/database/migrations/005-chat-read-state.ts new file mode 100644 index 00000000..ff041461 --- /dev/null +++ b/AgentCompany-New/src/main/database/migrations/005-chat-read-state.ts @@ -0,0 +1,15 @@ +export const chatReadState = ` + create table if not exists chat_read_state ( + org_id text not null references organizations(id) on delete cascade, + employee_id text not null references employees(id) on delete cascade, + space_id text not null references chat_spaces(id) on delete cascade, + last_read_message_id text references chat_messages(id) on delete set null, + last_read_at text not null, + primary key (employee_id, space_id) + ); + + create index if not exists idx_chat_read_state_org on chat_read_state(org_id, employee_id); + + insert into schema_migrations(version, name, applied_at) + values (5, 'chat_read_state', datetime('now')); +`; diff --git a/AgentCompany-New/src/main/database/schema.ts b/AgentCompany-New/src/main/database/schema.ts index 6083cd32..e081b591 100644 --- a/AgentCompany-New/src/main/database/schema.ts +++ b/AgentCompany-New/src/main/database/schema.ts @@ -1,6 +1,19 @@ import type { DatabaseSync } from "node:sqlite"; +import { initialEnterpriseSchema } from "./migrations/001-initial"; +import { collaborationProviderPolicySchema } from "./migrations/002-collaboration"; +import { onboardingExecutionSchema } from "./migrations/003-onboarding"; +import { filesPinnedAndScheduledPosts } from "./migrations/004-files-posts"; +import { chatReadState } from "./migrations/005-chat-read-state"; -const SCHEMA_VERSION = 5; +const MIGRATIONS: Array<{ version: number; sql: string }> = [ + { version: 1, sql: initialEnterpriseSchema }, + { version: 2, sql: collaborationProviderPolicySchema }, + { version: 3, sql: onboardingExecutionSchema }, + { version: 4, sql: filesPinnedAndScheduledPosts }, + { version: 5, sql: chatReadState }, +]; + +const SCHEMA_VERSION = MIGRATIONS[MIGRATIONS.length - 1].version; export function installSchema(db: DatabaseSync): void { db.exec(` @@ -16,492 +29,10 @@ export function installSchema(db: DatabaseSync): void { if (currentVersion > SCHEMA_VERSION) { throw new Error(`Database schema ${currentVersion} is newer than supported schema ${SCHEMA_VERSION}.`); } - if (currentVersion === SCHEMA_VERSION) return; - if (currentVersion < 1) { - db.exec(` - create table if not exists organizations ( - id text primary key, - name text not null, - mission text not null, - goal text not null, - created_at text not null - ); - - create table if not exists employees ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - display_name text not null, - role text not null, - created_at text not null - ); - - create table if not exists agents ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - name text not null, - role text not null, - department text not null, - model_provider_id text, - model_id text, - budget_cents integer not null, - manager_agent_id text references agents(id) on delete set null, - lifecycle text not null, - created_at text not null - ); - - create table if not exists tasks ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - title text not null, - description text not null, - status text not null, - assignee_agent_id text references agents(id) on delete set null, - risk text not null, - created_at text not null, - updated_at text not null - ); - - create table if not exists approvals ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - kind text not null, - title text not null, - details text not null, - risk text not null, - requested_by_type text not null, - requested_by_id text, - state text not null, - decided_by_employee_id text references employees(id) on delete set null, - created_at text not null, - decided_at text - ); - - create table if not exists chat_spaces ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - space_type text not null, - name text not null, - topic text not null, - visibility text not null, - created_at text not null - ); - - create table if not exists chat_memberships ( - space_id text not null references chat_spaces(id) on delete cascade, - principal_type text not null, - principal_id text not null, - role text not null, - mute_state text not null, - primary key (space_id, principal_type, principal_id) - ); - - create table if not exists chat_messages ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - space_id text not null references chat_spaces(id) on delete cascade, - thread_id text, - sender_type text not null, - sender_id text, - body_md text not null, - created_at text not null, - edited_at text, - deleted_at text - ); - - create table if not exists file_objects ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - name text not null, - kind text not null, - size_bytes integer not null, - sha256 text not null, - storage_path text not null, - owner_type text not null, - owner_id text, - created_at text not null - ); - - create table if not exists providers ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - provider_key text not null, - label text not null, - auth_type text not null, - model text, - credential_id text, - enabled integer not null, - created_at text not null, - unique(org_id, provider_key) - ); - - create table if not exists credentials ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - provider_key text not null, - kind text not null, - ciphertext blob not null, - display_hint text not null, - created_at text not null - ); - - create table if not exists skill_definitions ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - slug text not null, - name text not null, - owner_type text not null, - status text not null, - created_at text not null, - unique(org_id, slug) - ); - - create table if not exists skill_revisions ( - id text primary key, - skill_id text not null references skill_definitions(id) on delete cascade, - version_semver text not null, - manifest_json text not null, - source_type text not null, - source_ref text not null, - published_at text not null, - immutable_checksum text not null, - unique(skill_id, version_semver) - ); - - create table if not exists skill_artifacts ( - id text primary key, - revision_id text not null references skill_revisions(id) on delete cascade, - artifact_type text not null, - object_key text not null, - sha256 text not null, - size_bytes integer not null - ); - - create table if not exists skill_tests ( - id text primary key, - revision_id text not null references skill_revisions(id) on delete cascade, - test_type text not null, - expected_output_ref text not null, - last_result text, - last_run_at text - ); - - create table if not exists skill_bindings ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - agent_id text not null references agents(id) on delete cascade, - skill_id text not null references skill_definitions(id) on delete cascade, - pinned_revision_id text not null references skill_revisions(id) on delete cascade, - binding_mode text not null, - priority integer not null, - enabled integer not null, - unique(agent_id, skill_id) - ); - - create table if not exists social_accounts ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - platform text not null, - handle text not null, - display_name text not null, - authorized_employee_id text references employees(id) on delete set null, - created_at text not null - ); - - create table if not exists social_account_grants ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - social_account_id text not null references social_accounts(id) on delete cascade, - employee_id text not null references employees(id) on delete cascade, - role text not null, - scope_json text not null, - created_at text not null - ); - - create table if not exists browser_actions ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - social_account_id text not null references social_accounts(id) on delete cascade, - action_type text not null, - policy_decision text not null, - evidence_file_id text references file_objects(id) on delete set null, - created_at text not null - ); - - create table if not exists migration_reports ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - source_ref text not null, - report_json text not null, - created_at text not null - ); - - create table if not exists audit_events ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - entity_type text not null, - entity_id text not null, - actor_type text not null, - actor_id text, - action text not null, - payload_json text not null, - created_at text not null - ); - - create index if not exists idx_tasks_org_status on tasks(org_id, status); - create index if not exists idx_messages_space_created on chat_messages(space_id, created_at); - create index if not exists idx_audit_org_created on audit_events(org_id, created_at); - insert into schema_migrations(version, name, applied_at) - values (1, 'initial_enterprise_schema', datetime('now')); - `); - currentVersion = 1; - } - - if (currentVersion < 2) { - db.exec(` - create table if not exists skill_dependencies ( - revision_id text not null references skill_revisions(id) on delete cascade, - depends_on_revision_id text not null references skill_revisions(id) on delete cascade, - dependency_kind text not null, - optional integer not null, - primary key (revision_id, depends_on_revision_id) - ); - - create table if not exists skill_runtime_snapshots ( - id text primary key, - agent_id text not null references agents(id) on delete cascade, - run_id text not null, - compiled_prompt text not null, - tools_manifest text not null, - source_revision_ids text not null, - created_at text not null - ); - - create table if not exists skill_catalog_tags ( - skill_id text not null references skill_definitions(id) on delete cascade, - tag text not null, - tag_type text not null, - primary key (skill_id, tag, tag_type) - ); - - create table if not exists chat_threads ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - space_id text not null references chat_spaces(id) on delete cascade, - root_message_id text references chat_messages(id) on delete set null, - title text not null, - state text not null, - created_at text not null, - updated_at text not null - ); - - create table if not exists chat_mentions ( - message_id text not null references chat_messages(id) on delete cascade, - target_type text not null, - target_id text not null, - offset_start integer not null, - offset_end integer not null - ); - - create table if not exists chat_attachments ( - message_id text not null references chat_messages(id) on delete cascade, - file_id text not null references file_objects(id) on delete cascade, - transfer_type text not null, - checksum text not null, - preview_key text - ); - - create table if not exists chat_presence ( - principal_type text not null, - principal_id text not null, - status text not null, - status_text text not null, - last_seen_at text not null, - primary key (principal_type, principal_id) - ); - - create table if not exists chat_slash_invocations ( - id text primary key, - message_id text not null references chat_messages(id) on delete cascade, - command text not null, - args_json text not null, - result_ref text, - created_at text not null - ); - - create table if not exists provider_requests ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - provider_id text not null references providers(id) on delete cascade, - provider_key text not null, - model text not null, - prompt_sha256 text not null, - response_text text, - raw_response_json text, - state text not null, - error_message text, - created_at text not null, - completed_at text - ); - - create table if not exists policy_rules ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - subject_type text not null, - subject_id text, - action text not null, - effect text not null, - risk_ceiling text not null, - created_at text not null - ); - - create index if not exists idx_provider_requests_org_created on provider_requests(org_id, created_at); - create index if not exists idx_chat_threads_space_updated on chat_threads(space_id, updated_at); - insert into policy_rules(id, org_id, subject_type, subject_id, action, effect, risk_ceiling, created_at) - select - 'pol_' || lower(hex(randomblob(16))), - id, - 'organization', - id, - 'task_create', - 'require_approval', - 'medium', - datetime('now') - from organizations - where not exists ( - select 1 from policy_rules - where policy_rules.org_id = organizations.id and policy_rules.action = 'task_create' - ); - insert into schema_migrations(version, name, applied_at) - values (2, 'collaboration_provider_policy_schema', datetime('now')); - `); - currentVersion = 2; - } - - if (currentVersion < 3) { - db.exec(` - alter table organizations add column description text not null default ''; - alter table organizations add column execution_mode text not null default 'ai_ceo'; - alter table organizations add column auto_approve_hires integer not null default 1; - alter table organizations add column review_deliverables integer not null default 0; - - alter table agents add column title text not null default ''; - alter table agents add column role_level text not null default 'staff'; - alter table agents add column model_strategy text not null default 'pooled'; - alter table agents add column workspace_id text; - alter table agents add column heartbeat_enabled integer not null default 0; - alter table agents add column heartbeat_interval_sec integer not null default 0; - - alter table tasks add column project_id text; - alter table tasks add column goal_id text; - alter table tasks add column workspace_id text; - alter table tasks add column priority text not null default 'normal'; - alter table tasks add column requires_filesystem integer not null default 0; - - create table if not exists workspaces ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - name text not null, - local_path text not null, - repo_url text not null, - repo_ref text not null, - project_id text, - is_primary integer not null, - created_at text not null, - updated_at text not null - ); - - create table if not exists goals ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - title text not null, - description text not null, - status text not null, - owner_agent_id text references agents(id) on delete set null, - created_at text not null, - updated_at text not null - ); - - create table if not exists projects ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - goal_id text references goals(id) on delete set null, - name text not null, - description text not null, - lead_agent_id text references agents(id) on delete set null, - status text not null, - created_at text not null, - updated_at text not null - ); - - create table if not exists task_runs ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - task_id text not null references tasks(id) on delete cascade, - agent_id text references agents(id) on delete set null, - provider_id text references providers(id) on delete set null, - trigger text not null, - state text not null, - created_at text not null, - started_at text, - completed_at text, - error_message text - ); - - create index if not exists idx_workspaces_org_primary on workspaces(org_id, is_primary); - create index if not exists idx_goals_org_status on goals(org_id, status); - create index if not exists idx_projects_org_status on projects(org_id, status); - create index if not exists idx_task_runs_task_created on task_runs(task_id, created_at); - insert into schema_migrations(version, name, applied_at) - values (3, 'onboarding_execution_schema', datetime('now')); - `); - currentVersion = 3; - } - - if (currentVersion < 4) { - db.exec(` - alter table file_objects add column pinned integer not null default 0; - alter table file_objects add column space_id text; - alter table file_objects add column updated_at text; - - create table if not exists scheduled_posts ( - id text primary key, - org_id text not null references organizations(id) on delete cascade, - social_account_id text not null references social_accounts(id) on delete cascade, - body_md text not null, - scheduled_for text not null, - state text not null, - approval_id text references approvals(id) on delete set null, - created_by_employee_id text references employees(id) on delete set null, - created_at text not null, - updated_at text not null - ); - - create index if not exists idx_files_org_pinned on file_objects(org_id, pinned); - create index if not exists idx_scheduled_posts_org_state on scheduled_posts(org_id, state); - create index if not exists idx_scheduled_posts_account_date on scheduled_posts(social_account_id, scheduled_for); - - insert into schema_migrations(version, name, applied_at) - values (4, 'files_pinned_and_scheduled_posts', datetime('now')); - `); - currentVersion = 4; - } - - if (currentVersion < 5) { - db.exec(` - create table if not exists chat_read_state ( - org_id text not null references organizations(id) on delete cascade, - employee_id text not null references employees(id) on delete cascade, - space_id text not null references chat_spaces(id) on delete cascade, - last_read_message_id text references chat_messages(id) on delete set null, - last_read_at text not null, - primary key (employee_id, space_id) - ); - - create index if not exists idx_chat_read_state_org on chat_read_state(org_id, employee_id); - - insert into schema_migrations(version, name, applied_at) - values (5, 'chat_read_state', datetime('now')); - `); + for (const migration of MIGRATIONS) { + if (currentVersion >= migration.version) continue; + db.exec(migration.sql); + currentVersion = migration.version; } }