mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-29 06:35:24 +00:00
* 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
49 lines
1.8 KiB
TypeScript
49 lines
1.8 KiB
TypeScript
import { expect, it } from "vitest";
|
|
import {
|
|
updateQueue,
|
|
updateSession,
|
|
promptInput,
|
|
} from "../../../src/backend/agents/session-state.js";
|
|
import type { AgentSession } from "../../../src/backend/agents/types.js";
|
|
const session = () =>
|
|
({ queue: [], attachments: [{ id: "image" }] }) as unknown as AgentSession;
|
|
it("queues, edits and removes messages without replacing their IDs", () => {
|
|
const s = session();
|
|
updateQueue(s, { operation: "add", text: "first" });
|
|
updateQueue(s, { operation: "add", text: "second" });
|
|
const id = s.queue![0].id;
|
|
updateQueue(s, {
|
|
operation: "update",
|
|
id,
|
|
text: "edited",
|
|
attachmentIds: ["image"],
|
|
});
|
|
expect(s.queue![0]).toEqual({ id, text: "edited", attachmentIds: ["image"] });
|
|
updateQueue(s, { operation: "pause" });
|
|
expect(s.queuePaused).toBe(true);
|
|
updateQueue(s, { operation: "continue" });
|
|
expect(s.queuePaused).toBe(false);
|
|
updateQueue(s, { operation: "remove", id });
|
|
expect(s.queue!.map((p) => p.text)).toEqual(["second"]);
|
|
expect(() =>
|
|
updateQueue(s, { operation: "update", id, text: "late edit" }),
|
|
).toThrow();
|
|
});
|
|
it("rejects foreign attachments and caps queues", () => {
|
|
const s = session();
|
|
expect(() =>
|
|
promptInput(s, { text: "x", attachmentIds: ["other-session"] }),
|
|
).toThrow();
|
|
for (let i = 0; i < 20; i++) updateQueue(s, { operation: "add", text: "x" });
|
|
expect(() =>
|
|
updateQueue(s, { operation: "add", text: "overflow" }),
|
|
).toThrow();
|
|
});
|
|
it("validates metadata before applying changes", () => {
|
|
const s = session();
|
|
updateSession(s, { title: "name", draft: "draft", archived: true });
|
|
expect(s).toMatchObject({ title: "name", draft: "draft", archived: true });
|
|
expect(() => updateSession(s, { title: "replacement", draft: 42 })).toThrow();
|
|
expect(s.title).toBe("name");
|
|
});
|