Files
AgentCompany/AgentCompany-New/src/main/database/schema.ts
T
ZacharyZhang-NY 74266566b7 Rebuild AgentCompany-New renderer to match design spec
- Port design tokens, sidebar, topbar, and icons to inline SVG set
- Rewrite each page (Home/Team/Work/Chat/Files/Approvals/Social/Settings)
  to drive real snapshot data and match the bento, kanban, three-pane chat,
  file tree + pinned cards, approval queue, social schedule + calendar,
  and settings sub-nav layouts
- Split Chat and Settings into per-concern subcomponents so every file
  stays under 500 lines
- Add schema v4 for pinned files and scheduled posts plus IPC + service
  wiring; cover new behavior in unit tests
- Update onboarding labels and Hire form to remove ambiguity for the
  expanded e2e suite (all settings tabs + 8 routes at 1280 and 980)
2026-05-21 19:42:38 -04:00

489 lines
17 KiB
TypeScript

import type { DatabaseSync } from "node:sqlite";
const SCHEMA_VERSION = 4;
export function installSchema(db: DatabaseSync): void {
db.exec(`
create table if not exists schema_migrations (
version integer primary key,
name text not null,
applied_at text not null
);
`);
const row = db.prepare("select coalesce(max(version), 0) as version from schema_migrations").get() as { version: number };
let currentVersion = row.version;
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'));
`);
}
}