Merge branch 'storage-terminal-ui-dev' into dev

# Conflicts:
#	nix/package.nix
#	packages/app/src/app/_layout.tsx
#	packages/app/src/components/sidebar-workspace-list.tsx
#	packages/app/src/hooks/use-command-center.ts
#	packages/app/src/screens/agent/draft-agent-screen.tsx
#	packages/app/src/screens/workspace/workspace-desktop-tabs-row.tsx
#	packages/app/src/screens/workspace/workspace-screen.tsx
#	packages/server/src/server/session.ts
#	packages/server/src/server/session.workspaces.test.ts
#	packages/server/src/terminal/terminal.test.ts
#	packages/server/src/terminal/terminal.ts
This commit is contained in:
Mohamed Boudra
2026-04-01 21:51:29 +07:00
217 changed files with 21076 additions and 4944 deletions

View File

@@ -25,6 +25,7 @@ export interface AgentListItem {
shortId: string;
name: string;
provider: string;
terminal: boolean;
thinking: string;
status: string;
cwd: string;
@@ -66,6 +67,7 @@ export const agentLsSchema: OutputSchema<AgentListItem> = {
{ header: "AGENT ID", field: "shortId", width: 12 },
{ header: "NAME", field: "name", width: 20 },
{ header: "PROVIDER", field: "provider", width: 15 },
{ header: "TERM", field: "terminal", width: 6 },
{ header: "THINKING", field: "thinking", width: 12 },
{
header: "STATUS",
@@ -91,6 +93,7 @@ function toListItem(agent: AgentSnapshotPayload): AgentListItem {
shortId: agent.id.slice(0, 7),
name: agent.title ?? "-",
provider: model ? `${agent.provider}/${model}` : agent.provider,
terminal: agent.terminal === true,
thinking: agent.effectiveThinkingOptionId ?? "auto",
status: agent.status,
cwd: shortenPath(agent.cwd),

View File

@@ -193,7 +193,6 @@ export async function resolveStructuredResponseMessage(options: {
try {
const timeline = await options.client.fetchAgentTimeline(options.agentId, {
direction: "tail",
projection: "projected",
limit: 200,
});
for (let index = timeline.entries.length - 1; index >= 0; index -= 1) {

View File

@@ -17,6 +17,11 @@ export interface AgentSendResult {
message: string;
}
function isTerminalAgentSendError(error: unknown): boolean {
const message = error instanceof Error ? error.message : String(error);
return /terminal agents do not support structured send operations/i.test(message);
}
/** Schema for agent send output */
export const agentSendSchema: OutputSchema<AgentSendResult> = {
idField: "agentId",
@@ -260,6 +265,15 @@ export async function runSendCommand(
} catch (err) {
await client.close().catch(() => {});
if (isTerminalAgentSendError(err)) {
const error: CommandError = {
code: "TERMINAL_AGENT_UNSUPPORTED",
message: "Cannot send messages to terminal agents",
details: "Open the terminal agent from the Sessions UI and interact through its terminal.",
};
throw error;
}
// Re-throw CommandError as-is
if (err && typeof err === "object" && "code" in err) {
throw err;

View File

@@ -3,7 +3,6 @@ import type { SingleResult } from "../../output/index.js";
import {
attachAgentNamesToMessages,
connectChatClient,
resolveChatAuthorAgentId,
toChatCommandError,
type ChatCommandOptions,
} from "./shared.js";
@@ -24,7 +23,6 @@ export async function runPostCommand(
const payload = await client.postChatMessage({
room,
body,
authorAgentId: resolveChatAuthorAgentId(),
replyToMessageId: options.replyTo,
});
const [message] = await attachAgentNamesToMessages(client, [toChatMessageRow(payload.message!)]);

View File

@@ -23,11 +23,29 @@ const PROVIDERS: ProviderListItem[] = [
defaultMode: "auto",
modes: "read-only, auto, full-access",
},
{
provider: "gemini",
status: "available",
defaultMode: "-",
modes: "-",
},
{
provider: "amp",
status: "available",
defaultMode: "-",
modes: "-",
},
{
provider: "aider",
status: "available",
defaultMode: "-",
modes: "-",
},
{
provider: "opencode",
status: "available",
defaultMode: "default",
modes: "plan, default, bypass",
defaultMode: "build",
modes: "build, plan",
},
];

View File

@@ -11,7 +11,6 @@ export async function fetchProjectedTimelineItems(
const timeline = await input.client.fetchAgentTimeline(input.agentId, {
direction: "tail",
limit: 0,
projection: "projected",
});
return timeline.entries.map((entry) => entry.item);
}