Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions apps/web/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ When to add or change one:

- Every route is under `/api/v1/` (plus `/auth/*`, `/healthz`). It must pass the auth cookie and Origin checks in
`server.ts`; the server listens on `127.0.0.1` only. Never log the launch token or the cookie secret.
- `/api/v1/session-imports` adapts the coding-agent offline migration service.
Scan the Host machine, exclude archives by default, and require previewed
fingerprints plus explicit destination directories before importing. Close
the importer before the session index. Imported tools never create native
child-agent links, revertable file changes or running-state indicators.
- Adding or changing a route or payload: update `openapi.yaml` in the same change, update `client/src/state/types.ts`,
and add a unit test.
- Anything a reloaded page must show again belongs in the session snapshot (e.g. `pendingApprovals`), not only in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { useLocale, useT } from "../../i18n";
import { collectTurnChanges } from "../../lib/turn-changes";
import { setUi, useAppStore } from "../../state/store";
import type { SteeringMessage, TimelineItem } from "../../state/types";
import { Icon } from "../../ui";
import { openSettings } from "../settings/actions";
import { MessageActions, MessageItem } from "./MessageItem";
import { ProcessGroup } from "./ProcessGroup";
import {
Expand All @@ -23,13 +25,28 @@ import { collectTurnFooters } from "./turn-footers";
/** Shown while the timeline is empty (legacy index.html 835-842, `renderTimeline`). */
function EmptyConversation() {
const t = useT();
const draft = useAppStore((state) => state.current === null);
return (
<div className="empty-state">
<div className="empty-wordmark">
<span>STEP</span>
<strong>CODE</strong>
</div>
<p>{t("emptyConversation")}</p>
{draft ? (
<button
type="button"
id="emptySessionImport"
className="empty-session-import"
onClick={() => openSettings("migration")}
>
<Icon name="folder" size="sm" />
<span>
{t("emptySessionImport")}
<small>{t("emptySessionImportSources")}</small>
</span>
</button>
) : null}
</div>
);
}
Expand Down
2 changes: 1 addition & 1 deletion apps/web/client/src/features/conversation/ToolCall.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export const ToolRow = memo(function ToolRow({
const call = callPath(item.args, cwd);
const shown = call.shown;
// Only a file opens in the preview; a search or list path is usually a folder.
const openable = FILE_KINDS.has(toolKind(item)) ? call.openable : null;
const openable = !item.imported && FILE_KINDS.has(toolKind(item)) ? call.openable : null;
const copyValue = toolKind(item) === "bash" ? (item.args?.command ?? "") : output;
const card = toolKind(item) === "edit" || toolKind(item) === "write";
if (!readOnly && item.toolName === "subagent" && item.subagentTasks?.length && item.state !== "failed") {
Expand Down
22 changes: 22 additions & 0 deletions apps/web/client/src/features/conversation/stream.css
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,28 @@
letter-spacing: 0.01em;
}

.empty-session-import {
display: flex;
align-items: flex-start;
gap: 8px;
margin-top: 20px;
padding: 8px 12px;
border-radius: var(--radius-control);
color: var(--ink-2);
font-size: 13px;
text-align: left;
transition: background-color var(--fast), color var(--fast);
}
.empty-session-import .icon { margin-top: 2px; }
.empty-session-import small {
display: block;
margin-top: 4px;
color: var(--ink-3);
font-size: 12px;
}
.empty-session-import:hover { background: var(--hover); color: var(--ink); }
.empty-session-import:focus-visible { outline: 2px solid var(--focus-border); outline-offset: 2px; }

.message {
display: flex;
flex-direction: column;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export function toolKind(item: Pick<ToolTimelineItem, "toolName">): ToolKind {

/** State comes from the host, never from output text or the whole turn's activity. */
export function toolLabel(item: Pick<ToolTimelineItem, "toolName" | "state">, t: TranslateFn): string {
if (item.state === "unknown") return item.toolName || t("toolStatus.unknown");
const kind = toolKind(item);
const action = item.toolName === "find" ? "find" : kind;
return t(`toolAction.${action}.${item.state}`, { name: item.toolName || t("approvalTool") });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function turnArtifacts(
const keyOf = (path: string) => (windows ? path.toLowerCase() : path);
for (let index = Math.max(0, start); index <= footer.lastIndex; index++) {
const item = items[index];
if (item.kind !== "tool" || item.state !== "completed") continue;
if (item.kind !== "tool" || item.state !== "completed" || item.imported) continue;
if (!["edit", "write", "edit_file", "write_file", "apply_patch"].includes(item.toolName)) continue;
const raw = item.change?.path ?? item.args?.path;
const path = raw ? workspaceFilePath(cwd, raw) : undefined;
Expand Down
Loading
Loading