mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-29 22:55:24 +00:00
feat(ai): add remote coding agent sessions for SSH hosts (#1545)
* feat(ai): add host coding agent sessions with configured providers * Wait for agent initialization and shutdown before resuming sessions * Keep Pi transcripts outside its configuration migration directory * Cover Pi session directory separation * Update core permission catalog expectations for remote agents * Install remote agent runtimes from verified official sources * Wait for the identity panel credentials request in its test * Add scoped SSH forwarding setup for remote agents * Verify forwarding setup through a fresh SSH connection * Bound the SSH forwarding verification timeout * Return the forwarding verification callback result * fix(ai): support agent send and interrupt keyboard shortcuts * feat(ai): add agent queues attachments worktrees and session recovery * fix(ai): handle deleted workspace paths and duplicate status events * fix(ai): accept file references in root workspaces * fix(ai): refresh paused queues after agent errors * fix(ai): store agent sessions in plugin tables and lock down OpenCode Agent sessions lived in a single ctx.kv value holding up to 2000 events, which passed the 256 KB kv limit within minutes of a normal run. Every save after that failed, so history, nativeId, queue and archive changes were lost and every event wrote a kv audit row. Sessions, events and queued prompts now have their own tables. A running agent appends events in batches at most once a second with a lazy save; session and queue changes save immediately. Prompts, drafts and stored event text are capped in UTF-8 bytes to fit MySQL TEXT. kv:own is no longer requested. The OpenCode server now requires a per-session password, so other local accounts on the host cannot drive the agent through its loopback port. * test(upgrade): include agent session tables in the reviewed upgrade SQL
This commit is contained in:
1 parent
77bcbdb3d6
commit
bf817d8bd1
75 files changed
+7292
-6
No files matched your search
@@ -905,6 +905,54 @@ RENAME TABLE `ai_proposals` TO `p_ai_proposals`;
|
||||
-- ==== plugin ai 0002_provider_sync.sql ====
|
||||
ALTER TABLE `p_ai_providers` ADD COLUMN `sync_id` varchar(255) UNIQUE;
|
||||
|
||||
-- ==== plugin ai 0003_agent_sessions.sql ====
|
||||
-- ai 0003: agent_sessions
|
||||
-- Generated by termix-plugin migrations. Review before committing.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `p_ai_agent_sessions` (
|
||||
`id` int AUTO_INCREMENT PRIMARY KEY,
|
||||
`session_id` varchar(36) NOT NULL UNIQUE,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`provider_id` int NOT NULL,
|
||||
`agent` varchar(32) NOT NULL,
|
||||
`model` text NOT NULL,
|
||||
`cwd` text NOT NULL,
|
||||
`executable` text NOT NULL,
|
||||
`native_id` text,
|
||||
`title` text,
|
||||
`archived` boolean NOT NULL DEFAULT false,
|
||||
`queue_paused` boolean NOT NULL DEFAULT false,
|
||||
`draft` text,
|
||||
`attachments` text NOT NULL DEFAULT ('[]'),
|
||||
`updated_at` text NOT NULL,
|
||||
FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||
);
|
||||
CREATE INDEX `idx_ai_agent_sessions_user` ON `p_ai_agent_sessions` (`user_id`);
|
||||
CREATE TABLE IF NOT EXISTS `p_ai_agent_events` (
|
||||
`id` int AUTO_INCREMENT PRIMARY KEY,
|
||||
`session_id` varchar(36) NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`seq` int NOT NULL,
|
||||
`kind` varchar(16) NOT NULL,
|
||||
`text` text NOT NULL,
|
||||
`request_id` text,
|
||||
`choices` text,
|
||||
FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||
);
|
||||
CREATE UNIQUE INDEX `idx_ai_agent_events_session_seq` ON `p_ai_agent_events` (`session_id`, `seq`);
|
||||
CREATE TABLE IF NOT EXISTS `p_ai_agent_queue` (
|
||||
`id` int AUTO_INCREMENT PRIMARY KEY,
|
||||
`session_id` varchar(36) NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`prompt_id` varchar(36) NOT NULL,
|
||||
`position` int NOT NULL,
|
||||
`text` text NOT NULL,
|
||||
`attachment_ids` text NOT NULL DEFAULT ('[]'),
|
||||
FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||
);
|
||||
CREATE INDEX `idx_ai_agent_queue_session` ON `p_ai_agent_queue` (`session_id`, `position`);
|
||||
|
||||
-- ==== plugin alerts 0001_create_alerts.sql ====
|
||||
-- alerts 0001: create_alerts
|
||||
-- Generated by termix-plugin migrations. Review before committing.
|
||||
|
||||
@@ -953,6 +953,54 @@ ALTER TABLE "ai_proposals" RENAME TO "p_ai_proposals";
|
||||
-- ==== plugin ai 0002_provider_sync.sql ====
|
||||
ALTER TABLE "p_ai_providers" ADD COLUMN "sync_id" varchar(255) UNIQUE;
|
||||
|
||||
-- ==== plugin ai 0003_agent_sessions.sql ====
|
||||
-- ai 0003: agent_sessions
|
||||
-- Generated by termix-plugin migrations. Review before committing.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "p_ai_agent_sessions" (
|
||||
"id" serial PRIMARY KEY,
|
||||
"session_id" varchar(36) NOT NULL UNIQUE,
|
||||
"user_id" varchar(255) NOT NULL,
|
||||
"host_id" integer NOT NULL,
|
||||
"provider_id" integer NOT NULL,
|
||||
"agent" varchar(32) NOT NULL,
|
||||
"model" text NOT NULL,
|
||||
"cwd" text NOT NULL,
|
||||
"executable" text NOT NULL,
|
||||
"native_id" text,
|
||||
"title" text,
|
||||
"archived" boolean NOT NULL DEFAULT false,
|
||||
"queue_paused" boolean NOT NULL DEFAULT false,
|
||||
"draft" text,
|
||||
"attachments" text NOT NULL DEFAULT '[]',
|
||||
"updated_at" text NOT NULL,
|
||||
FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE CASCADE
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS "idx_ai_agent_sessions_user" ON "p_ai_agent_sessions" ("user_id");
|
||||
CREATE TABLE IF NOT EXISTS "p_ai_agent_events" (
|
||||
"id" serial PRIMARY KEY,
|
||||
"session_id" varchar(36) NOT NULL,
|
||||
"user_id" varchar(255) NOT NULL,
|
||||
"seq" integer NOT NULL,
|
||||
"kind" varchar(16) NOT NULL,
|
||||
"text" text NOT NULL,
|
||||
"request_id" text,
|
||||
"choices" text,
|
||||
FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE CASCADE
|
||||
);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "idx_ai_agent_events_session_seq" ON "p_ai_agent_events" ("session_id", "seq");
|
||||
CREATE TABLE IF NOT EXISTS "p_ai_agent_queue" (
|
||||
"id" serial PRIMARY KEY,
|
||||
"session_id" varchar(36) NOT NULL,
|
||||
"user_id" varchar(255) NOT NULL,
|
||||
"prompt_id" varchar(36) NOT NULL,
|
||||
"position" integer NOT NULL,
|
||||
"text" text NOT NULL,
|
||||
"attachment_ids" text NOT NULL DEFAULT '[]',
|
||||
FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE CASCADE
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS "idx_ai_agent_queue_session" ON "p_ai_agent_queue" ("session_id", "position");
|
||||
|
||||
-- ==== plugin alerts 0001_create_alerts.sql ====
|
||||
-- alerts 0001: create_alerts
|
||||
-- Generated by termix-plugin migrations. Review before committing.
|
||||
|
||||
@@ -378,6 +378,7 @@ describe("shipped manifests keep their permission ids", () => {
|
||||
"ai.apply_proposals",
|
||||
"ai.services.use",
|
||||
"ai.secrets.share",
|
||||
"ai.agents",
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user