Claude Code engine, image viewer, colour tags, checks per turn and more
- Claude Code as an engine: chats on a "claude-code/<alias>" model run through the claude CLI (stream-json); tool approvals go through our permission system. Sign in from the web UI (URL + pasted code), CLI version and update from Settings; the Docker image contains the CLI. - Small models (8k context) for side tasks: input is cut to the model's context window; one-line chat status, "What does this do?" on approvals, "Plan as automation" (job draft from a chat). - Mobile: top bar no longer widens the page, image viewer (zoom, swipe, mark up, use in message), jump to previous own message, message menu, time under every message. - Approvals: push actions (allow/reject), "always allow in this project" (never for dangerous commands) with revoke. - Per turn: changed files with diffs and rollback; project check command with a green/red badge and "let the agent fix it". - Colour tags for chats in the colours of the active theme. - Project defaults for new chats, project page (timeline), offline queue. Tested in a throwaway container with a mock model (8k small model): 26 API checks passed (permissions, diffs, checks, defaults, job draft, side-task budget, Claude Code status/login URL, unsigned-in chat). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
084452abf6
commit
62fe5bf467
42 files changed
+3734
-55
No files matched your search
@@ -0,0 +1,43 @@
|
||||
import { useState } from "react";
|
||||
import { post } from "../api";
|
||||
import { toast } from "../dialogs";
|
||||
import { useT } from "../i18n";
|
||||
import { useStore } from "../store";
|
||||
import { Spinner } from "./Activity";
|
||||
import { Icon } from "./Icon";
|
||||
|
||||
/** Green/red badge of the project's check (tests, build …) for one turn; output and "let the agent fix it" on click. */
|
||||
export function TurnCheck({ sessionId, messageId, canSend }: { sessionId: string; messageId: string; canSend: boolean }) {
|
||||
const t = useT();
|
||||
const check = useStore((s) => s.checks[sessionId]?.[messageId]);
|
||||
const [open, setOpen] = useState(false);
|
||||
if (!check) return null;
|
||||
const seconds = check.duration_ms >= 1000 ? ` · ${(check.duration_ms / 1000).toFixed(check.duration_ms >= 10_000 ? 0 : 1)} s` : "";
|
||||
const label =
|
||||
check.status === "running" ? t("check.running") : check.status === "passed" ? t("check.passed") : check.status === "timeout" ? t("check.timeout") : t("check.failed");
|
||||
const fix = async () => {
|
||||
try {
|
||||
await post(`/sessions/${sessionId}/prompt`, { text: `${t("check.fixPrompt")}\n\n\`\`\`\n${check.output}\n\`\`\`` });
|
||||
} catch (e: any) {
|
||||
toast(e.message);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div className="turn-check">
|
||||
<button className={`chip check-${check.status}`} onClick={() => setOpen(!open)} aria-expanded={open} disabled={check.status === "running"}>
|
||||
{check.status === "running" ? <Spinner small /> : <Icon name={check.status === "passed" ? "check" : "x-mark"} className="tiny" />} {label}
|
||||
{seconds}
|
||||
</button>
|
||||
{open && check.status !== "running" && (
|
||||
<div className="turn-check-body">
|
||||
<pre className="mono">{check.output || t("check.noOutput")}</pre>
|
||||
{check.status !== "passed" && canSend && (
|
||||
<button className="small primary" onClick={fix}>
|
||||
<Icon name="sparkle" /> {t("check.fix")}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user