mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-15 20:15:30 +00:00
The backend import package is now docsgpt, the name it will carry on PyPI; application was far too generic to install into anyone's site-packages. git mv plus a mechanical rewrite of every import, dotted string and path reference: 734 Python files, the compose files, Dockerfile, workflows, docs, setup scripts, devcontainer, k8s manifests, vscode config, pytest and coverage config, .gitignore. Behaviour is unchanged. Kept for one release: - A top-level application package whose meta-path finder resolves application.x.y to the already-imported docsgpt.x.y object, so old imports and entry points (celery -A application.app.celery, uvicorn application.asgi:asgi_app) keep working with a FutureWarning. - Celery registers every application.* task name as an alias of its docsgpt.* task on start-up, so messages queued by the previous release still run. The redbeat key prefix moves to redbeat:docsgpt:v2: so schedule entries the previous release wrote are left unread instead of firing twice. The backend image builds from the repository root (docker build -f docsgpt/Dockerfile .) so it can ship the alias package; a root .dockerignore allow-lists docsgpt/ and application/ and keeps caches, local data, .env files, the sample index files and the Dockerfile out. Compose and the image workflows point at the new context.
118 lines
4.2 KiB
Python
118 lines
4.2 KiB
Python
"""0012 remote devices — devices, device_audit_log, device_auto_approve_patterns.
|
|
|
|
Adds tables for the Remote Device feature: paired remote hosts that DocsGPT
|
|
agents can drive via shell tool calls.
|
|
|
|
Revision ID: 0012_remote_devices
|
|
Revises: 0011_schedules_nullable_agent
|
|
"""
|
|
|
|
from typing import Sequence, Union
|
|
|
|
from alembic import op
|
|
|
|
|
|
revision: str = "0012_remote_devices"
|
|
down_revision: Union[str, None] = "0011_schedules_nullable_agent"
|
|
branch_labels: Union[str, Sequence[str], None] = None
|
|
depends_on: Union[str, Sequence[str], None] = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.execute(
|
|
"""
|
|
CREATE TABLE devices (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL,
|
|
name TEXT NOT NULL,
|
|
hostname TEXT,
|
|
os TEXT,
|
|
arch TEXT,
|
|
cli_version TEXT,
|
|
machine_pubkey_fingerprint TEXT NOT NULL,
|
|
token_hash TEXT NOT NULL,
|
|
approval_mode TEXT NOT NULL DEFAULT 'ask',
|
|
description TEXT,
|
|
status TEXT NOT NULL DEFAULT 'active',
|
|
paired_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
last_seen_at TIMESTAMPTZ,
|
|
revoked_at TIMESTAMPTZ,
|
|
revoke_reason TEXT,
|
|
CONSTRAINT devices_approval_mode_chk
|
|
CHECK (approval_mode IN ('ask', 'writes-only', 'never')),
|
|
CONSTRAINT devices_status_chk
|
|
CHECK (status IN ('active', 'revoked')),
|
|
CONSTRAINT devices_user_name_uidx UNIQUE (user_id, name)
|
|
);
|
|
"""
|
|
)
|
|
op.execute(
|
|
"CREATE INDEX devices_user_active_idx ON devices(user_id) "
|
|
"WHERE status = 'active';"
|
|
)
|
|
|
|
op.execute(
|
|
"""
|
|
CREATE TABLE device_audit_log (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
device_id TEXT NOT NULL REFERENCES devices(id) ON DELETE CASCADE,
|
|
user_id TEXT NOT NULL,
|
|
agent_id TEXT,
|
|
conversation_id TEXT,
|
|
invocation_id TEXT NOT NULL,
|
|
action TEXT NOT NULL,
|
|
command TEXT NOT NULL,
|
|
working_dir TEXT,
|
|
approval_mode TEXT NOT NULL,
|
|
decision TEXT NOT NULL,
|
|
decision_reason TEXT,
|
|
issued_at TIMESTAMPTZ NOT NULL,
|
|
started_at TIMESTAMPTZ,
|
|
finished_at TIMESTAMPTZ,
|
|
exit_code INTEGER,
|
|
duration_ms INTEGER,
|
|
stdout_sha256 CHAR(64),
|
|
stderr_sha256 CHAR(64),
|
|
stdout_bytes INTEGER,
|
|
stderr_bytes INTEGER,
|
|
error TEXT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
"""
|
|
)
|
|
op.execute(
|
|
"CREATE INDEX device_audit_device_idx "
|
|
"ON device_audit_log(device_id, created_at DESC);"
|
|
)
|
|
op.execute(
|
|
"CREATE INDEX device_audit_user_idx "
|
|
"ON device_audit_log(user_id, created_at DESC);"
|
|
)
|
|
|
|
# Per-device, per-user sticky "don't ask again" patterns. Normalized
|
|
# form: command head + first sub-token, wildcard rest (see
|
|
# docsgpt/devices/normalizer.py).
|
|
op.execute(
|
|
"""
|
|
CREATE TABLE device_auto_approve_patterns (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
device_id TEXT NOT NULL REFERENCES devices(id) ON DELETE CASCADE,
|
|
user_id TEXT NOT NULL,
|
|
pattern TEXT NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
CONSTRAINT device_auto_approve_uidx
|
|
UNIQUE (device_id, user_id, pattern)
|
|
);
|
|
"""
|
|
)
|
|
op.execute(
|
|
"CREATE INDEX device_auto_approve_lookup_idx "
|
|
"ON device_auto_approve_patterns(device_id, user_id);"
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.execute("DROP TABLE IF EXISTS device_auto_approve_patterns CASCADE;")
|
|
op.execute("DROP TABLE IF EXISTS device_audit_log CASCADE;")
|
|
op.execute("DROP TABLE IF EXISTS devices CASCADE;")
|