0a1dcfeb7f
- Stop (a tab's or pane's X, Close tab) now archives the session it held (DELETE /api/run/:id?archive=1); the new Sleep (moon left of the X, and in the tab, pane and session right-click menus) stops the pane but keeps the session listed to resume later. Shared endRuns in client/src/lib/stopSession.ts. - Git identity (#82): an account keeps an ED25519 AND an RSA key (AWS CodeCommit takes only RSA), every ssh git offers both, and a member's ~/.gitconfig gets core.sshCommand so a git typed in a terminal uses them. - Update dialog: Auto fix starts a Claude Code session on the install folder with the failed update's error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
58 lines
2.0 KiB
TypeScript
58 lines
2.0 KiB
TypeScript
/**
|
|
* @file stopSession — the one way the UI ends live panes: **Stop** kills the
|
|
* pane and ARCHIVES the session it held (`DELETE /api/run/:id?archive=1`), so
|
|
* a session the user closed leaves its workspace's lists; **Sleep** kills the
|
|
* pane and KEEPS the session listed, to be resumed later by sending it a
|
|
* message. Both ask first when any pane holds an AI agent (it may be
|
|
* mid-turn); a plain shell holds no session, so it neither asks nor sleeps.
|
|
* Used by the tab bar (`ConsoleTabs`), the split panes (`Workspace`) and a
|
|
* session's right-click menu (`SessionMenu`).
|
|
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
|
*/
|
|
|
|
import type { TFunction } from "i18next";
|
|
import { api, type RunHandle } from "./api";
|
|
import { confirmDialog } from "./confirm";
|
|
import { toast } from "./toast";
|
|
|
|
/** Whether a pane can sleep: an AI pane (a shell has no session to keep). */
|
|
export const canSleep = (run: RunHandle | null | undefined): boolean =>
|
|
!!run && run.tool !== "shell";
|
|
|
|
/**
|
|
* Stop (archive) or sleep (keep) `runs` after a confirm, and return the ids
|
|
* that were ended. `name` titles a one-pane confirm; `t` is the `lanes`
|
|
* namespace.
|
|
*/
|
|
export async function endRuns(
|
|
runs: RunHandle[],
|
|
{ sleep = false, name, t }: { sleep?: boolean; name: string; t: TFunction }
|
|
): Promise<string[]> {
|
|
const list = sleep ? runs.filter(canSleep) : runs;
|
|
if (!list.length) return [];
|
|
const kind = sleep ? "sleep" : "stop";
|
|
if (
|
|
list.some((r) => r.tool !== "shell") &&
|
|
!(await confirmDialog({
|
|
title:
|
|
list.length > 1
|
|
? t(`tabs.${kind}GroupTitle`, { count: list.length })
|
|
: t(`tabs.${kind}Title`, { name }),
|
|
message: t(`tabs.${kind}Body`),
|
|
confirmLabel: t(`tabs.${kind}Confirm`),
|
|
destructive: !sleep,
|
|
}))
|
|
)
|
|
return [];
|
|
const ended: string[] = [];
|
|
for (const r of list) {
|
|
try {
|
|
await api.run.kill(r.id, { archive: !sleep });
|
|
ended.push(r.id);
|
|
} catch (err) {
|
|
toast.error(err);
|
|
}
|
|
}
|
|
return ended;
|
|
}
|