openclaw/apps/web/lib/agent-runner.ts

383 lines
10 KiB
TypeScript
Raw Normal View History

import { spawn } from "node:child_process";
import { createInterface } from "node:readline";
import { join } from "node:path";
export type AgentEvent = {
event: string;
runId?: string;
stream?: string;
data?: Record<string, unknown>;
seq?: number;
ts?: number;
sessionKey?: string;
status?: string;
result?: {
payloads?: Array<{ text?: string; mediaUrl?: string | null }>;
meta?: Record<string, unknown>;
};
};
/** Extracted text + details from a tool result event. */
export type ToolResult = {
text?: string;
details?: Record<string, unknown>;
};
export type AgentCallback = {
onTextDelta: (delta: string) => void;
onThinkingDelta: (delta: string) => void;
onToolStart: (
toolCallId: string,
toolName: string,
args?: Record<string, unknown>,
) => void;
onToolEnd: (
toolCallId: string,
toolName: string,
isError: boolean,
result?: ToolResult,
) => void;
onLifecycleEnd: () => void;
onError: (error: Error) => void;
onClose: (code: number | null) => void;
Dench workspace: Tiptap markdown editor, subagent sessions, and error surfacing ── Tiptap Markdown Editor ── - Add full Tiptap-based WYSIWYG markdown editor (markdown-editor.tsx, 709 LOC) with bubble menu, auto-save (debounced), image drag-and-drop/paste upload, table editing, task list checkboxes, and frontmatter preservation on save. - Add slash command system (slash-command.tsx, 607 LOC) with "/" trigger for block insertion (headings, lists, tables, code blocks, images, reports) and "@" trigger for file/document mention with fuzzy search across the workspace tree. - Add ReportBlockNode (report-block-node.tsx) — custom Tiptap node that renders embedded report-json blocks as interactive ReportCard widgets inline in the editor, with expand/collapse and edit-JSON support. - Add workspace asset serving API (api/workspace/assets/[...path]/route.ts) to serve images from the workspace with proper MIME types. - Add workspace file upload orkspace/upload/route.ts) for multipart image uploads (10 MB limit, image types only), saving to assets/ directory. - Add ~500 lines of Tiptap editor CSS to globals.css (editor layout, task lists, images, tables, slash command dropdown, bubble menu toolbar, code blocks, etc.). - Add 14 @tiptap/* dependencies to apps/web/package.json (react, starter-kit, markdown, image, link, table, task-list, suggestion, placeholder, etc.). ── Document View: Edit/Read Mode Toggle ── - document-view.tsx: Add edit/read mode toggle; defaults to edit mode when a filePath is available. Lazy-loads MarkdownEditor to keep initial bundle light. - workspace/page.tsx: Pass activePath, tree, onSave, onNavigate, and onRefreshTree through to DocumentView for full editor integration with workspace navigation and tree refresh after saves. ── Subagent Session Isolation ── - agent-runner.ts: Add RunAgentOptions with optional sessionId; when set, spawns the agent with --session-key agent:main:subagent:<id> ant so file-scoped sidebar chats run in isolated sessions independent of the main agent. - route.ts (chat API): Accept sessionId from request body and forward it to runAgent. Resolve workspace file path prefixes (resolveAgentWorkspacePrefix) so tree-relative paths become agent-cwd-relative. - chat-panel.tsx: Create per-instance DefaultChatTransport that injects sessionId via body function and a ref (avoids stale closures). On file change, auto-load the most recent session and its messages. Refresh session tab list after streaming ends. Stop ongoing stream when switching sessions. - register.agent.ts: Add --session-key <key> and --lane <lane> CLI flags. - agent-via-gateway.ts: Wire sessionKey into session resolution and validation for both interactive and --stream-json code paths. - workspace.ts: Add resolveAgentWorkspacePrefix() to map workspace-root-relative paths to repo-root-relative paths for the agent process. ── Error Surfacing ── - agent-runner.ts: Add onAgentError callback extraction helpers (parseAgentErrorMessage, parseErrorBody, parseErrorFromStderr) to surface API-level errors (402 payment, rate limits, etc.) to the UI. Captures stderr for fallback error detection on non-zero exit. - route.ts: Wire onAgentError into the SSE stream as [error]-prefixed text parts. Improve onError and onClose handlers with clearer error messages and exit code reporting. - chat-message.tsx: Detect [error]-prefixed text segments and render them as styled error banners with alert icon instead of plain text. - chat-panel.tsx: Restyle the transport-level error bar with themed colors and an alert icon consistent with in-message error styling.
2026-02-11 20:54:30 -08:00
/** Called when the agent encounters an API or runtime error (402, rate limit, etc.) */
onAgentError?: (message: string) => void;
};
/**
* Extract text content from the agent's tool result object.
* The result has `content: Array<{ type: "text", text: string } | ...>` and
* optional `details` (exit codes, file paths, etc.).
*/
function extractToolResult(
raw: unknown,
): ToolResult | undefined {
Dench workspace: Tiptap markdown editor, subagent sessions, and error surfacing ── Tiptap Markdown Editor ── - Add full Tiptap-based WYSIWYG markdown editor (markdown-editor.tsx, 709 LOC) with bubble menu, auto-save (debounced), image drag-and-drop/paste upload, table editing, task list checkboxes, and frontmatter preservation on save. - Add slash command system (slash-command.tsx, 607 LOC) with "/" trigger for block insertion (headings, lists, tables, code blocks, images, reports) and "@" trigger for file/document mention with fuzzy search across the workspace tree. - Add ReportBlockNode (report-block-node.tsx) — custom Tiptap node that renders embedded report-json blocks as interactive ReportCard widgets inline in the editor, with expand/collapse and edit-JSON support. - Add workspace asset serving API (api/workspace/assets/[...path]/route.ts) to serve images from the workspace with proper MIME types. - Add workspace file upload orkspace/upload/route.ts) for multipart image uploads (10 MB limit, image types only), saving to assets/ directory. - Add ~500 lines of Tiptap editor CSS to globals.css (editor layout, task lists, images, tables, slash command dropdown, bubble menu toolbar, code blocks, etc.). - Add 14 @tiptap/* dependencies to apps/web/package.json (react, starter-kit, markdown, image, link, table, task-list, suggestion, placeholder, etc.). ── Document View: Edit/Read Mode Toggle ── - document-view.tsx: Add edit/read mode toggle; defaults to edit mode when a filePath is available. Lazy-loads MarkdownEditor to keep initial bundle light. - workspace/page.tsx: Pass activePath, tree, onSave, onNavigate, and onRefreshTree through to DocumentView for full editor integration with workspace navigation and tree refresh after saves. ── Subagent Session Isolation ── - agent-runner.ts: Add RunAgentOptions with optional sessionId; when set, spawns the agent with --session-key agent:main:subagent:<id> ant so file-scoped sidebar chats run in isolated sessions independent of the main agent. - route.ts (chat API): Accept sessionId from request body and forward it to runAgent. Resolve workspace file path prefixes (resolveAgentWorkspacePrefix) so tree-relative paths become agent-cwd-relative. - chat-panel.tsx: Create per-instance DefaultChatTransport that injects sessionId via body function and a ref (avoids stale closures). On file change, auto-load the most recent session and its messages. Refresh session tab list after streaming ends. Stop ongoing stream when switching sessions. - register.agent.ts: Add --session-key <key> and --lane <lane> CLI flags. - agent-via-gateway.ts: Wire sessionKey into session resolution and validation for both interactive and --stream-json code paths. - workspace.ts: Add resolveAgentWorkspacePrefix() to map workspace-root-relative paths to repo-root-relative paths for the agent process. ── Error Surfacing ── - agent-runner.ts: Add onAgentError callback extraction helpers (parseAgentErrorMessage, parseErrorBody, parseErrorFromStderr) to surface API-level errors (402 payment, rate limits, etc.) to the UI. Captures stderr for fallback error detection on non-zero exit. - route.ts: Wire onAgentError into the SSE stream as [error]-prefixed text parts. Improve onError and onClose handlers with clearer error messages and exit code reporting. - chat-message.tsx: Detect [error]-prefixed text segments and render them as styled error banners with alert icon instead of plain text. - chat-panel.tsx: Restyle the transport-level error bar with themed colors and an alert icon consistent with in-message error styling.
2026-02-11 20:54:30 -08:00
if (!raw || typeof raw !== "object") {return undefined;}
const r = raw as Record<string, unknown>;
// Extract text from content blocks
const content = Array.isArray(r.content) ? r.content : [];
const textParts: string[] = [];
for (const block of content) {
if (
block &&
typeof block === "object" &&
(block as Record<string, unknown>).type === "text" &&
typeof (block as Record<string, unknown>).text === "string"
) {
textParts.push((block as Record<string, unknown>).text as string);
}
}
const text = textParts.length > 0 ? textParts.join("\n") : undefined;
const details =
r.details && typeof r.details === "object"
? (r.details as Record<string, unknown>)
: undefined;
return { text, details };
}
Dench workspace: Tiptap markdown editor, subagent sessions, and error surfacing ── Tiptap Markdown Editor ── - Add full Tiptap-based WYSIWYG markdown editor (markdown-editor.tsx, 709 LOC) with bubble menu, auto-save (debounced), image drag-and-drop/paste upload, table editing, task list checkboxes, and frontmatter preservation on save. - Add slash command system (slash-command.tsx, 607 LOC) with "/" trigger for block insertion (headings, lists, tables, code blocks, images, reports) and "@" trigger for file/document mention with fuzzy search across the workspace tree. - Add ReportBlockNode (report-block-node.tsx) — custom Tiptap node that renders embedded report-json blocks as interactive ReportCard widgets inline in the editor, with expand/collapse and edit-JSON support. - Add workspace asset serving API (api/workspace/assets/[...path]/route.ts) to serve images from the workspace with proper MIME types. - Add workspace file upload orkspace/upload/route.ts) for multipart image uploads (10 MB limit, image types only), saving to assets/ directory. - Add ~500 lines of Tiptap editor CSS to globals.css (editor layout, task lists, images, tables, slash command dropdown, bubble menu toolbar, code blocks, etc.). - Add 14 @tiptap/* dependencies to apps/web/package.json (react, starter-kit, markdown, image, link, table, task-list, suggestion, placeholder, etc.). ── Document View: Edit/Read Mode Toggle ── - document-view.tsx: Add edit/read mode toggle; defaults to edit mode when a filePath is available. Lazy-loads MarkdownEditor to keep initial bundle light. - workspace/page.tsx: Pass activePath, tree, onSave, onNavigate, and onRefreshTree through to DocumentView for full editor integration with workspace navigation and tree refresh after saves. ── Subagent Session Isolation ── - agent-runner.ts: Add RunAgentOptions with optional sessionId; when set, spawns the agent with --session-key agent:main:subagent:<id> ant so file-scoped sidebar chats run in isolated sessions independent of the main agent. - route.ts (chat API): Accept sessionId from request body and forward it to runAgent. Resolve workspace file path prefixes (resolveAgentWorkspacePrefix) so tree-relative paths become agent-cwd-relative. - chat-panel.tsx: Create per-instance DefaultChatTransport that injects sessionId via body function and a ref (avoids stale closures). On file change, auto-load the most recent session and its messages. Refresh session tab list after streaming ends. Stop ongoing stream when switching sessions. - register.agent.ts: Add --session-key <key> and --lane <lane> CLI flags. - agent-via-gateway.ts: Wire sessionKey into session resolution and validation for both interactive and --stream-json code paths. - workspace.ts: Add resolveAgentWorkspacePrefix() to map workspace-root-relative paths to repo-root-relative paths for the agent process. ── Error Surfacing ── - agent-runner.ts: Add onAgentError callback extraction helpers (parseAgentErrorMessage, parseErrorBody, parseErrorFromStderr) to surface API-level errors (402 payment, rate limits, etc.) to the UI. Captures stderr for fallback error detection on non-zero exit. - route.ts: Wire onAgentError into the SSE stream as [error]-prefixed text parts. Improve onError and onClose handlers with clearer error messages and exit code reporting. - chat-message.tsx: Detect [error]-prefixed text segments and render them as styled error banners with alert icon instead of plain text. - chat-panel.tsx: Restyle the transport-level error bar with themed colors and an alert icon consistent with in-message error styling.
2026-02-11 20:54:30 -08:00
export type RunAgentOptions = {
/** When set, the agent runs in an isolated session (e.g. file-scoped subagent). */
sessionId?: string;
};
/**
* Spawn the openclaw agent and stream its output.
* Pass an AbortSignal to kill the child process when the caller cancels.
Dench workspace: Tiptap markdown editor, subagent sessions, and error surfacing ── Tiptap Markdown Editor ── - Add full Tiptap-based WYSIWYG markdown editor (markdown-editor.tsx, 709 LOC) with bubble menu, auto-save (debounced), image drag-and-drop/paste upload, table editing, task list checkboxes, and frontmatter preservation on save. - Add slash command system (slash-command.tsx, 607 LOC) with "/" trigger for block insertion (headings, lists, tables, code blocks, images, reports) and "@" trigger for file/document mention with fuzzy search across the workspace tree. - Add ReportBlockNode (report-block-node.tsx) — custom Tiptap node that renders embedded report-json blocks as interactive ReportCard widgets inline in the editor, with expand/collapse and edit-JSON support. - Add workspace asset serving API (api/workspace/assets/[...path]/route.ts) to serve images from the workspace with proper MIME types. - Add workspace file upload orkspace/upload/route.ts) for multipart image uploads (10 MB limit, image types only), saving to assets/ directory. - Add ~500 lines of Tiptap editor CSS to globals.css (editor layout, task lists, images, tables, slash command dropdown, bubble menu toolbar, code blocks, etc.). - Add 14 @tiptap/* dependencies to apps/web/package.json (react, starter-kit, markdown, image, link, table, task-list, suggestion, placeholder, etc.). ── Document View: Edit/Read Mode Toggle ── - document-view.tsx: Add edit/read mode toggle; defaults to edit mode when a filePath is available. Lazy-loads MarkdownEditor to keep initial bundle light. - workspace/page.tsx: Pass activePath, tree, onSave, onNavigate, and onRefreshTree through to DocumentView for full editor integration with workspace navigation and tree refresh after saves. ── Subagent Session Isolation ── - agent-runner.ts: Add RunAgentOptions with optional sessionId; when set, spawns the agent with --session-key agent:main:subagent:<id> ant so file-scoped sidebar chats run in isolated sessions independent of the main agent. - route.ts (chat API): Accept sessionId from request body and forward it to runAgent. Resolve workspace file path prefixes (resolveAgentWorkspacePrefix) so tree-relative paths become agent-cwd-relative. - chat-panel.tsx: Create per-instance DefaultChatTransport that injects sessionId via body function and a ref (avoids stale closures). On file change, auto-load the most recent session and its messages. Refresh session tab list after streaming ends. Stop ongoing stream when switching sessions. - register.agent.ts: Add --session-key <key> and --lane <lane> CLI flags. - agent-via-gateway.ts: Wire sessionKey into session resolution and validation for both interactive and --stream-json code paths. - workspace.ts: Add resolveAgentWorkspacePrefix() to map workspace-root-relative paths to repo-root-relative paths for the agent process. ── Error Surfacing ── - agent-runner.ts: Add onAgentError callback extraction helpers (parseAgentErrorMessage, parseErrorBody, parseErrorFromStderr) to surface API-level errors (402 payment, rate limits, etc.) to the UI. Captures stderr for fallback error detection on non-zero exit. - route.ts: Wire onAgentError into the SSE stream as [error]-prefixed text parts. Improve onError and onClose handlers with clearer error messages and exit code reporting. - chat-message.tsx: Detect [error]-prefixed text segments and render them as styled error banners with alert icon instead of plain text. - chat-panel.tsx: Restyle the transport-level error bar with themed colors and an alert icon consistent with in-message error styling.
2026-02-11 20:54:30 -08:00
*
* When `options.sessionId` is set the child process gets `--session-id <id>`,
* which creates an isolated agent session that won't interfere with the main
* agent or other sidebar chats.
*/
export async function runAgent(
message: string,
signal: AbortSignal | undefined,
callback: AgentCallback,
Dench workspace: Tiptap markdown editor, subagent sessions, and error surfacing ── Tiptap Markdown Editor ── - Add full Tiptap-based WYSIWYG markdown editor (markdown-editor.tsx, 709 LOC) with bubble menu, auto-save (debounced), image drag-and-drop/paste upload, table editing, task list checkboxes, and frontmatter preservation on save. - Add slash command system (slash-command.tsx, 607 LOC) with "/" trigger for block insertion (headings, lists, tables, code blocks, images, reports) and "@" trigger for file/document mention with fuzzy search across the workspace tree. - Add ReportBlockNode (report-block-node.tsx) — custom Tiptap node that renders embedded report-json blocks as interactive ReportCard widgets inline in the editor, with expand/collapse and edit-JSON support. - Add workspace asset serving API (api/workspace/assets/[...path]/route.ts) to serve images from the workspace with proper MIME types. - Add workspace file upload orkspace/upload/route.ts) for multipart image uploads (10 MB limit, image types only), saving to assets/ directory. - Add ~500 lines of Tiptap editor CSS to globals.css (editor layout, task lists, images, tables, slash command dropdown, bubble menu toolbar, code blocks, etc.). - Add 14 @tiptap/* dependencies to apps/web/package.json (react, starter-kit, markdown, image, link, table, task-list, suggestion, placeholder, etc.). ── Document View: Edit/Read Mode Toggle ── - document-view.tsx: Add edit/read mode toggle; defaults to edit mode when a filePath is available. Lazy-loads MarkdownEditor to keep initial bundle light. - workspace/page.tsx: Pass activePath, tree, onSave, onNavigate, and onRefreshTree through to DocumentView for full editor integration with workspace navigation and tree refresh after saves. ── Subagent Session Isolation ── - agent-runner.ts: Add RunAgentOptions with optional sessionId; when set, spawns the agent with --session-key agent:main:subagent:<id> ant so file-scoped sidebar chats run in isolated sessions independent of the main agent. - route.ts (chat API): Accept sessionId from request body and forward it to runAgent. Resolve workspace file path prefixes (resolveAgentWorkspacePrefix) so tree-relative paths become agent-cwd-relative. - chat-panel.tsx: Create per-instance DefaultChatTransport that injects sessionId via body function and a ref (avoids stale closures). On file change, auto-load the most recent session and its messages. Refresh session tab list after streaming ends. Stop ongoing stream when switching sessions. - register.agent.ts: Add --session-key <key> and --lane <lane> CLI flags. - agent-via-gateway.ts: Wire sessionKey into session resolution and validation for both interactive and --stream-json code paths. - workspace.ts: Add resolveAgentWorkspacePrefix() to map workspace-root-relative paths to repo-root-relative paths for the agent process. ── Error Surfacing ── - agent-runner.ts: Add onAgentError callback extraction helpers (parseAgentErrorMessage, parseErrorBody, parseErrorFromStderr) to surface API-level errors (402 payment, rate limits, etc.) to the UI. Captures stderr for fallback error detection on non-zero exit. - route.ts: Wire onAgentError into the SSE stream as [error]-prefixed text parts. Improve onError and onClose handlers with clearer error messages and exit code reporting. - chat-message.tsx: Detect [error]-prefixed text segments and render them as styled error banners with alert icon instead of plain text. - chat-panel.tsx: Restyle the transport-level error bar with themed colors and an alert icon consistent with in-message error styling.
2026-02-11 20:54:30 -08:00
options?: RunAgentOptions,
): Promise<void> {
// Get repo root - construct path dynamically at runtime
const cwd = process.cwd();
const root = cwd.endsWith(join("apps", "web"))
? join(cwd, "..", "..")
: cwd;
// Construct script path at runtime to avoid static analysis
const pathParts = ["scripts", "run-node.mjs"];
const scriptPath = join(root, ...pathParts);
return new Promise<void>((resolve) => {
Dench workspace: Tiptap markdown editor, subagent sessions, and error surfacing ── Tiptap Markdown Editor ── - Add full Tiptap-based WYSIWYG markdown editor (markdown-editor.tsx, 709 LOC) with bubble menu, auto-save (debounced), image drag-and-drop/paste upload, table editing, task list checkboxes, and frontmatter preservation on save. - Add slash command system (slash-command.tsx, 607 LOC) with "/" trigger for block insertion (headings, lists, tables, code blocks, images, reports) and "@" trigger for file/document mention with fuzzy search across the workspace tree. - Add ReportBlockNode (report-block-node.tsx) — custom Tiptap node that renders embedded report-json blocks as interactive ReportCard widgets inline in the editor, with expand/collapse and edit-JSON support. - Add workspace asset serving API (api/workspace/assets/[...path]/route.ts) to serve images from the workspace with proper MIME types. - Add workspace file upload orkspace/upload/route.ts) for multipart image uploads (10 MB limit, image types only), saving to assets/ directory. - Add ~500 lines of Tiptap editor CSS to globals.css (editor layout, task lists, images, tables, slash command dropdown, bubble menu toolbar, code blocks, etc.). - Add 14 @tiptap/* dependencies to apps/web/package.json (react, starter-kit, markdown, image, link, table, task-list, suggestion, placeholder, etc.). ── Document View: Edit/Read Mode Toggle ── - document-view.tsx: Add edit/read mode toggle; defaults to edit mode when a filePath is available. Lazy-loads MarkdownEditor to keep initial bundle light. - workspace/page.tsx: Pass activePath, tree, onSave, onNavigate, and onRefreshTree through to DocumentView for full editor integration with workspace navigation and tree refresh after saves. ── Subagent Session Isolation ── - agent-runner.ts: Add RunAgentOptions with optional sessionId; when set, spawns the agent with --session-key agent:main:subagent:<id> ant so file-scoped sidebar chats run in isolated sessions independent of the main agent. - route.ts (chat API): Accept sessionId from request body and forward it to runAgent. Resolve workspace file path prefixes (resolveAgentWorkspacePrefix) so tree-relative paths become agent-cwd-relative. - chat-panel.tsx: Create per-instance DefaultChatTransport that injects sessionId via body function and a ref (avoids stale closures). On file change, auto-load the most recent session and its messages. Refresh session tab list after streaming ends. Stop ongoing stream when switching sessions. - register.agent.ts: Add --session-key <key> and --lane <lane> CLI flags. - agent-via-gateway.ts: Wire sessionKey into session resolution and validation for both interactive and --stream-json code paths. - workspace.ts: Add resolveAgentWorkspacePrefix() to map workspace-root-relative paths to repo-root-relative paths for the agent process. ── Error Surfacing ── - agent-runner.ts: Add onAgentError callback extraction helpers (parseAgentErrorMessage, parseErrorBody, parseErrorFromStderr) to surface API-level errors (402 payment, rate limits, etc.) to the UI. Captures stderr for fallback error detection on non-zero exit. - route.ts: Wire onAgentError into the SSE stream as [error]-prefixed text parts. Improve onError and onClose handlers with clearer error messages and exit code reporting. - chat-message.tsx: Detect [error]-prefixed text segments and render them as styled error banners with alert icon instead of plain text. - chat-panel.tsx: Restyle the transport-level error bar with themed colors and an alert icon consistent with in-message error styling.
2026-02-11 20:54:30 -08:00
const args = [
scriptPath,
"agent",
"--agent",
"main",
"--message",
message,
"--stream-json",
// Run embedded (--local) so we get ALL events (tool, thinking,
// lifecycle) unfiltered. The gateway path drops tool events
// unless verbose is explicitly "on".
"--local",
];
// Isolated session for file-scoped subagent chats.
// Uses a proper subagent session key (agent:main:subagent:<id>) so the
// agent runs in the Subagent concurrency lane with its own session
// context, completely independent of the main agent session.
if (options?.sessionId) {
const sessionKey = `agent:main:subagent:${options.sessionId}`;
args.push("--session-key", sessionKey, "--lane", "subagent");
}
const child = spawn(
"node",
Dench workspace: Tiptap markdown editor, subagent sessions, and error surfacing ── Tiptap Markdown Editor ── - Add full Tiptap-based WYSIWYG markdown editor (markdown-editor.tsx, 709 LOC) with bubble menu, auto-save (debounced), image drag-and-drop/paste upload, table editing, task list checkboxes, and frontmatter preservation on save. - Add slash command system (slash-command.tsx, 607 LOC) with "/" trigger for block insertion (headings, lists, tables, code blocks, images, reports) and "@" trigger for file/document mention with fuzzy search across the workspace tree. - Add ReportBlockNode (report-block-node.tsx) — custom Tiptap node that renders embedded report-json blocks as interactive ReportCard widgets inline in the editor, with expand/collapse and edit-JSON support. - Add workspace asset serving API (api/workspace/assets/[...path]/route.ts) to serve images from the workspace with proper MIME types. - Add workspace file upload orkspace/upload/route.ts) for multipart image uploads (10 MB limit, image types only), saving to assets/ directory. - Add ~500 lines of Tiptap editor CSS to globals.css (editor layout, task lists, images, tables, slash command dropdown, bubble menu toolbar, code blocks, etc.). - Add 14 @tiptap/* dependencies to apps/web/package.json (react, starter-kit, markdown, image, link, table, task-list, suggestion, placeholder, etc.). ── Document View: Edit/Read Mode Toggle ── - document-view.tsx: Add edit/read mode toggle; defaults to edit mode when a filePath is available. Lazy-loads MarkdownEditor to keep initial bundle light. - workspace/page.tsx: Pass activePath, tree, onSave, onNavigate, and onRefreshTree through to DocumentView for full editor integration with workspace navigation and tree refresh after saves. ── Subagent Session Isolation ── - agent-runner.ts: Add RunAgentOptions with optional sessionId; when set, spawns the agent with --session-key agent:main:subagent:<id> ant so file-scoped sidebar chats run in isolated sessions independent of the main agent. - route.ts (chat API): Accept sessionId from request body and forward it to runAgent. Resolve workspace file path prefixes (resolveAgentWorkspacePrefix) so tree-relative paths become agent-cwd-relative. - chat-panel.tsx: Create per-instance DefaultChatTransport that injects sessionId via body function and a ref (avoids stale closures). On file change, auto-load the most recent session and its messages. Refresh session tab list after streaming ends. Stop ongoing stream when switching sessions. - register.agent.ts: Add --session-key <key> and --lane <lane> CLI flags. - agent-via-gateway.ts: Wire sessionKey into session resolution and validation for both interactive and --stream-json code paths. - workspace.ts: Add resolveAgentWorkspacePrefix() to map workspace-root-relative paths to repo-root-relative paths for the agent process. ── Error Surfacing ── - agent-runner.ts: Add onAgentError callback extraction helpers (parseAgentErrorMessage, parseErrorBody, parseErrorFromStderr) to surface API-level errors (402 payment, rate limits, etc.) to the UI. Captures stderr for fallback error detection on non-zero exit. - route.ts: Wire onAgentError into the SSE stream as [error]-prefixed text parts. Improve onError and onClose handlers with clearer error messages and exit code reporting. - chat-message.tsx: Detect [error]-prefixed text segments and render them as styled error banners with alert icon instead of plain text. - chat-panel.tsx: Restyle the transport-level error bar with themed colors and an alert icon consistent with in-message error styling.
2026-02-11 20:54:30 -08:00
args,
{
cwd: root,
env: { ...process.env },
stdio: ["ignore", "pipe", "pipe"],
},
);
// Kill the child process if the caller aborts (e.g. user hit stop).
if (signal) {
const onAbort = () => child.kill("SIGTERM");
if (signal.aborted) {
child.kill("SIGTERM");
} else {
signal.addEventListener("abort", onAbort, { once: true });
child.on("close", () =>
signal.removeEventListener("abort", onAbort),
);
}
}
Dench workspace: Tiptap markdown editor, subagent sessions, and error surfacing ── Tiptap Markdown Editor ── - Add full Tiptap-based WYSIWYG markdown editor (markdown-editor.tsx, 709 LOC) with bubble menu, auto-save (debounced), image drag-and-drop/paste upload, table editing, task list checkboxes, and frontmatter preservation on save. - Add slash command system (slash-command.tsx, 607 LOC) with "/" trigger for block insertion (headings, lists, tables, code blocks, images, reports) and "@" trigger for file/document mention with fuzzy search across the workspace tree. - Add ReportBlockNode (report-block-node.tsx) — custom Tiptap node that renders embedded report-json blocks as interactive ReportCard widgets inline in the editor, with expand/collapse and edit-JSON support. - Add workspace asset serving API (api/workspace/assets/[...path]/route.ts) to serve images from the workspace with proper MIME types. - Add workspace file upload orkspace/upload/route.ts) for multipart image uploads (10 MB limit, image types only), saving to assets/ directory. - Add ~500 lines of Tiptap editor CSS to globals.css (editor layout, task lists, images, tables, slash command dropdown, bubble menu toolbar, code blocks, etc.). - Add 14 @tiptap/* dependencies to apps/web/package.json (react, starter-kit, markdown, image, link, table, task-list, suggestion, placeholder, etc.). ── Document View: Edit/Read Mode Toggle ── - document-view.tsx: Add edit/read mode toggle; defaults to edit mode when a filePath is available. Lazy-loads MarkdownEditor to keep initial bundle light. - workspace/page.tsx: Pass activePath, tree, onSave, onNavigate, and onRefreshTree through to DocumentView for full editor integration with workspace navigation and tree refresh after saves. ── Subagent Session Isolation ── - agent-runner.ts: Add RunAgentOptions with optional sessionId; when set, spawns the agent with --session-key agent:main:subagent:<id> ant so file-scoped sidebar chats run in isolated sessions independent of the main agent. - route.ts (chat API): Accept sessionId from request body and forward it to runAgent. Resolve workspace file path prefixes (resolveAgentWorkspacePrefix) so tree-relative paths become agent-cwd-relative. - chat-panel.tsx: Create per-instance DefaultChatTransport that injects sessionId via body function and a ref (avoids stale closures). On file change, auto-load the most recent session and its messages. Refresh session tab list after streaming ends. Stop ongoing stream when switching sessions. - register.agent.ts: Add --session-key <key> and --lane <lane> CLI flags. - agent-via-gateway.ts: Wire sessionKey into session resolution and validation for both interactive and --stream-json code paths. - workspace.ts: Add resolveAgentWorkspacePrefix() to map workspace-root-relative paths to repo-root-relative paths for the agent process. ── Error Surfacing ── - agent-runner.ts: Add onAgentError callback extraction helpers (parseAgentErrorMessage, parseErrorBody, parseErrorFromStderr) to surface API-level errors (402 payment, rate limits, etc.) to the UI. Captures stderr for fallback error detection on non-zero exit. - route.ts: Wire onAgentError into the SSE stream as [error]-prefixed text parts. Improve onError and onClose handlers with clearer error messages and exit code reporting. - chat-message.tsx: Detect [error]-prefixed text segments and render them as styled error banners with alert icon instead of plain text. - chat-panel.tsx: Restyle the transport-level error bar with themed colors and an alert icon consistent with in-message error styling.
2026-02-11 20:54:30 -08:00
// Collect stderr so we can surface errors to the UI
const stderrChunks: string[] = [];
let agentErrorReported = false;
const rl = createInterface({ input: child.stdout });
rl.on("line", (line: string) => {
Dench workspace: Tiptap markdown editor, subagent sessions, and error surfacing ── Tiptap Markdown Editor ── - Add full Tiptap-based WYSIWYG markdown editor (markdown-editor.tsx, 709 LOC) with bubble menu, auto-save (debounced), image drag-and-drop/paste upload, table editing, task list checkboxes, and frontmatter preservation on save. - Add slash command system (slash-command.tsx, 607 LOC) with "/" trigger for block insertion (headings, lists, tables, code blocks, images, reports) and "@" trigger for file/document mention with fuzzy search across the workspace tree. - Add ReportBlockNode (report-block-node.tsx) — custom Tiptap node that renders embedded report-json blocks as interactive ReportCard widgets inline in the editor, with expand/collapse and edit-JSON support. - Add workspace asset serving API (api/workspace/assets/[...path]/route.ts) to serve images from the workspace with proper MIME types. - Add workspace file upload orkspace/upload/route.ts) for multipart image uploads (10 MB limit, image types only), saving to assets/ directory. - Add ~500 lines of Tiptap editor CSS to globals.css (editor layout, task lists, images, tables, slash command dropdown, bubble menu toolbar, code blocks, etc.). - Add 14 @tiptap/* dependencies to apps/web/package.json (react, starter-kit, markdown, image, link, table, task-list, suggestion, placeholder, etc.). ── Document View: Edit/Read Mode Toggle ── - document-view.tsx: Add edit/read mode toggle; defaults to edit mode when a filePath is available. Lazy-loads MarkdownEditor to keep initial bundle light. - workspace/page.tsx: Pass activePath, tree, onSave, onNavigate, and onRefreshTree through to DocumentView for full editor integration with workspace navigation and tree refresh after saves. ── Subagent Session Isolation ── - agent-runner.ts: Add RunAgentOptions with optional sessionId; when set, spawns the agent with --session-key agent:main:subagent:<id> ant so file-scoped sidebar chats run in isolated sessions independent of the main agent. - route.ts (chat API): Accept sessionId from request body and forward it to runAgent. Resolve workspace file path prefixes (resolveAgentWorkspacePrefix) so tree-relative paths become agent-cwd-relative. - chat-panel.tsx: Create per-instance DefaultChatTransport that injects sessionId via body function and a ref (avoids stale closures). On file change, auto-load the most recent session and its messages. Refresh session tab list after streaming ends. Stop ongoing stream when switching sessions. - register.agent.ts: Add --session-key <key> and --lane <lane> CLI flags. - agent-via-gateway.ts: Wire sessionKey into session resolution and validation for both interactive and --stream-json code paths. - workspace.ts: Add resolveAgentWorkspacePrefix() to map workspace-root-relative paths to repo-root-relative paths for the agent process. ── Error Surfacing ── - agent-runner.ts: Add onAgentError callback extraction helpers (parseAgentErrorMessage, parseErrorBody, parseErrorFromStderr) to surface API-level errors (402 payment, rate limits, etc.) to the UI. Captures stderr for fallback error detection on non-zero exit. - route.ts: Wire onAgentError into the SSE stream as [error]-prefixed text parts. Improve onError and onClose handlers with clearer error messages and exit code reporting. - chat-message.tsx: Detect [error]-prefixed text segments and render them as styled error banners with alert icon instead of plain text. - chat-panel.tsx: Restyle the transport-level error bar with themed colors and an alert icon consistent with in-message error styling.
2026-02-11 20:54:30 -08:00
if (!line.trim()) {return;}
let event: AgentEvent;
try {
event = JSON.parse(line) as AgentEvent;
} catch {
console.log("[agent-runner] Non-JSON line:", line);
return; // skip non-JSON lines
}
// Handle assistant text deltas
if (event.event === "agent" && event.stream === "assistant") {
const delta =
typeof event.data?.delta === "string"
? event.data.delta
: undefined;
if (delta) {
callback.onTextDelta(delta);
}
}
// Handle thinking/reasoning deltas
if (event.event === "agent" && event.stream === "thinking") {
const delta =
typeof event.data?.delta === "string"
? event.data.delta
: undefined;
if (delta) {
callback.onThinkingDelta(delta);
}
}
// Handle tool execution events
if (event.event === "agent" && event.stream === "tool") {
const phase =
typeof event.data?.phase === "string"
? event.data.phase
: undefined;
const toolCallId =
typeof event.data?.toolCallId === "string"
? event.data.toolCallId
: "";
const toolName =
typeof event.data?.name === "string"
? event.data.name
: "";
if (phase === "start") {
const args =
event.data?.args &&
typeof event.data.args === "object"
? (event.data.args as Record<string, unknown>)
: undefined;
callback.onToolStart(toolCallId, toolName, args);
} else if (phase === "result") {
const isError = event.data?.isError === true;
const result = extractToolResult(event.data?.result);
callback.onToolEnd(toolCallId, toolName, isError, result);
}
}
// Handle lifecycle end
if (
event.event === "agent" &&
event.stream === "lifecycle" &&
event.data?.phase === "end"
) {
callback.onLifecycleEnd();
}
Dench workspace: Tiptap markdown editor, subagent sessions, and error surfacing ── Tiptap Markdown Editor ── - Add full Tiptap-based WYSIWYG markdown editor (markdown-editor.tsx, 709 LOC) with bubble menu, auto-save (debounced), image drag-and-drop/paste upload, table editing, task list checkboxes, and frontmatter preservation on save. - Add slash command system (slash-command.tsx, 607 LOC) with "/" trigger for block insertion (headings, lists, tables, code blocks, images, reports) and "@" trigger for file/document mention with fuzzy search across the workspace tree. - Add ReportBlockNode (report-block-node.tsx) — custom Tiptap node that renders embedded report-json blocks as interactive ReportCard widgets inline in the editor, with expand/collapse and edit-JSON support. - Add workspace asset serving API (api/workspace/assets/[...path]/route.ts) to serve images from the workspace with proper MIME types. - Add workspace file upload orkspace/upload/route.ts) for multipart image uploads (10 MB limit, image types only), saving to assets/ directory. - Add ~500 lines of Tiptap editor CSS to globals.css (editor layout, task lists, images, tables, slash command dropdown, bubble menu toolbar, code blocks, etc.). - Add 14 @tiptap/* dependencies to apps/web/package.json (react, starter-kit, markdown, image, link, table, task-list, suggestion, placeholder, etc.). ── Document View: Edit/Read Mode Toggle ── - document-view.tsx: Add edit/read mode toggle; defaults to edit mode when a filePath is available. Lazy-loads MarkdownEditor to keep initial bundle light. - workspace/page.tsx: Pass activePath, tree, onSave, onNavigate, and onRefreshTree through to DocumentView for full editor integration with workspace navigation and tree refresh after saves. ── Subagent Session Isolation ── - agent-runner.ts: Add RunAgentOptions with optional sessionId; when set, spawns the agent with --session-key agent:main:subagent:<id> ant so file-scoped sidebar chats run in isolated sessions independent of the main agent. - route.ts (chat API): Accept sessionId from request body and forward it to runAgent. Resolve workspace file path prefixes (resolveAgentWorkspacePrefix) so tree-relative paths become agent-cwd-relative. - chat-panel.tsx: Create per-instance DefaultChatTransport that injects sessionId via body function and a ref (avoids stale closures). On file change, auto-load the most recent session and its messages. Refresh session tab list after streaming ends. Stop ongoing stream when switching sessions. - register.agent.ts: Add --session-key <key> and --lane <lane> CLI flags. - agent-via-gateway.ts: Wire sessionKey into session resolution and validation for both interactive and --stream-json code paths. - workspace.ts: Add resolveAgentWorkspacePrefix() to map workspace-root-relative paths to repo-root-relative paths for the agent process. ── Error Surfacing ── - agent-runner.ts: Add onAgentError callback extraction helpers (parseAgentErrorMessage, parseErrorBody, parseErrorFromStderr) to surface API-level errors (402 payment, rate limits, etc.) to the UI. Captures stderr for fallback error detection on non-zero exit. - route.ts: Wire onAgentError into the SSE stream as [error]-prefixed text parts. Improve onError and onClose handlers with clearer error messages and exit code reporting. - chat-message.tsx: Detect [error]-prefixed text segments and render them as styled error banners with alert icon instead of plain text. - chat-panel.tsx: Restyle the transport-level error bar with themed colors and an alert icon consistent with in-message error styling.
2026-02-11 20:54:30 -08:00
// ── Surface agent-level errors (API 402, rate limits, etc.) ──
// Lifecycle error phase
if (
event.event === "agent" &&
event.stream === "lifecycle" &&
event.data?.phase === "error"
) {
const msg = parseAgentErrorMessage(event.data);
if (msg && !agentErrorReported) {
agentErrorReported = true;
callback.onAgentError?.(msg);
}
}
// Top-level error events
if (event.event === "error") {
const msg = parseAgentErrorMessage(event.data ?? event);
if (msg && !agentErrorReported) {
agentErrorReported = true;
callback.onAgentError?.(msg);
}
}
// Messages with stopReason "error" (some agents inline errors this way)
if (
event.event === "agent" &&
event.stream === "assistant" &&
typeof event.data?.stopReason === "string" &&
event.data.stopReason === "error" &&
typeof event.data?.errorMessage === "string"
) {
if (!agentErrorReported) {
agentErrorReported = true;
callback.onAgentError?.(
parseErrorBody(event.data.errorMessage as string),
);
}
}
});
child.on("close", (code) => {
Dench workspace: Tiptap markdown editor, subagent sessions, and error surfacing ── Tiptap Markdown Editor ── - Add full Tiptap-based WYSIWYG markdown editor (markdown-editor.tsx, 709 LOC) with bubble menu, auto-save (debounced), image drag-and-drop/paste upload, table editing, task list checkboxes, and frontmatter preservation on save. - Add slash command system (slash-command.tsx, 607 LOC) with "/" trigger for block insertion (headings, lists, tables, code blocks, images, reports) and "@" trigger for file/document mention with fuzzy search across the workspace tree. - Add ReportBlockNode (report-block-node.tsx) — custom Tiptap node that renders embedded report-json blocks as interactive ReportCard widgets inline in the editor, with expand/collapse and edit-JSON support. - Add workspace asset serving API (api/workspace/assets/[...path]/route.ts) to serve images from the workspace with proper MIME types. - Add workspace file upload orkspace/upload/route.ts) for multipart image uploads (10 MB limit, image types only), saving to assets/ directory. - Add ~500 lines of Tiptap editor CSS to globals.css (editor layout, task lists, images, tables, slash command dropdown, bubble menu toolbar, code blocks, etc.). - Add 14 @tiptap/* dependencies to apps/web/package.json (react, starter-kit, markdown, image, link, table, task-list, suggestion, placeholder, etc.). ── Document View: Edit/Read Mode Toggle ── - document-view.tsx: Add edit/read mode toggle; defaults to edit mode when a filePath is available. Lazy-loads MarkdownEditor to keep initial bundle light. - workspace/page.tsx: Pass activePath, tree, onSave, onNavigate, and onRefreshTree through to DocumentView for full editor integration with workspace navigation and tree refresh after saves. ── Subagent Session Isolation ── - agent-runner.ts: Add RunAgentOptions with optional sessionId; when set, spawns the agent with --session-key agent:main:subagent:<id> ant so file-scoped sidebar chats run in isolated sessions independent of the main agent. - route.ts (chat API): Accept sessionId from request body and forward it to runAgent. Resolve workspace file path prefixes (resolveAgentWorkspacePrefix) so tree-relative paths become agent-cwd-relative. - chat-panel.tsx: Create per-instance DefaultChatTransport that injects sessionId via body function and a ref (avoids stale closures). On file change, auto-load the most recent session and its messages. Refresh session tab list after streaming ends. Stop ongoing stream when switching sessions. - register.agent.ts: Add --session-key <key> and --lane <lane> CLI flags. - agent-via-gateway.ts: Wire sessionKey into session resolution and validation for both interactive and --stream-json code paths. - workspace.ts: Add resolveAgentWorkspacePrefix() to map workspace-root-relative paths to repo-root-relative paths for the agent process. ── Error Surfacing ── - agent-runner.ts: Add onAgentError callback extraction helpers (parseAgentErrorMessage, parseErrorBody, parseErrorFromStderr) to surface API-level errors (402 payment, rate limits, etc.) to the UI. Captures stderr for fallback error detection on non-zero exit. - route.ts: Wire onAgentError into the SSE stream as [error]-prefixed text parts. Improve onError and onClose handlers with clearer error messages and exit code reporting. - chat-message.tsx: Detect [error]-prefixed text segments and render them as styled error banners with alert icon instead of plain text. - chat-panel.tsx: Restyle the transport-level error bar with themed colors and an alert icon consistent with in-message error styling.
2026-02-11 20:54:30 -08:00
// If no error was reported yet, check stderr for useful info
if (!agentErrorReported && stderrChunks.length > 0) {
const stderr = stderrChunks.join("").trim();
const msg = parseErrorFromStderr(stderr);
if (msg) {
agentErrorReported = true;
callback.onAgentError?.(msg);
}
}
callback.onClose(code);
resolve();
});
child.on("error", (err) => {
callback.onError(err);
resolve();
});
Dench workspace: Tiptap markdown editor, subagent sessions, and error surfacing ── Tiptap Markdown Editor ── - Add full Tiptap-based WYSIWYG markdown editor (markdown-editor.tsx, 709 LOC) with bubble menu, auto-save (debounced), image drag-and-drop/paste upload, table editing, task list checkboxes, and frontmatter preservation on save. - Add slash command system (slash-command.tsx, 607 LOC) with "/" trigger for block insertion (headings, lists, tables, code blocks, images, reports) and "@" trigger for file/document mention with fuzzy search across the workspace tree. - Add ReportBlockNode (report-block-node.tsx) — custom Tiptap node that renders embedded report-json blocks as interactive ReportCard widgets inline in the editor, with expand/collapse and edit-JSON support. - Add workspace asset serving API (api/workspace/assets/[...path]/route.ts) to serve images from the workspace with proper MIME types. - Add workspace file upload orkspace/upload/route.ts) for multipart image uploads (10 MB limit, image types only), saving to assets/ directory. - Add ~500 lines of Tiptap editor CSS to globals.css (editor layout, task lists, images, tables, slash command dropdown, bubble menu toolbar, code blocks, etc.). - Add 14 @tiptap/* dependencies to apps/web/package.json (react, starter-kit, markdown, image, link, table, task-list, suggestion, placeholder, etc.). ── Document View: Edit/Read Mode Toggle ── - document-view.tsx: Add edit/read mode toggle; defaults to edit mode when a filePath is available. Lazy-loads MarkdownEditor to keep initial bundle light. - workspace/page.tsx: Pass activePath, tree, onSave, onNavigate, and onRefreshTree through to DocumentView for full editor integration with workspace navigation and tree refresh after saves. ── Subagent Session Isolation ── - agent-runner.ts: Add RunAgentOptions with optional sessionId; when set, spawns the agent with --session-key agent:main:subagent:<id> ant so file-scoped sidebar chats run in isolated sessions independent of the main agent. - route.ts (chat API): Accept sessionId from request body and forward it to runAgent. Resolve workspace file path prefixes (resolveAgentWorkspacePrefix) so tree-relative paths become agent-cwd-relative. - chat-panel.tsx: Create per-instance DefaultChatTransport that injects sessionId via body function and a ref (avoids stale closures). On file change, auto-load the most recent session and its messages. Refresh session tab list after streaming ends. Stop ongoing stream when switching sessions. - register.agent.ts: Add --session-key <key> and --lane <lane> CLI flags. - agent-via-gateway.ts: Wire sessionKey into session resolution and validation for both interactive and --stream-json code paths. - workspace.ts: Add resolveAgentWorkspacePrefix() to map workspace-root-relative paths to repo-root-relative paths for the agent process. ── Error Surfacing ── - agent-runner.ts: Add onAgentError callback extraction helpers (parseAgentErrorMessage, parseErrorBody, parseErrorFromStderr) to surface API-level errors (402 payment, rate limits, etc.) to the UI. Captures stderr for fallback error detection on non-zero exit. - route.ts: Wire onAgentError into the SSE stream as [error]-prefixed text parts. Improve onError and onClose handlers with clearer error messages and exit code reporting. - chat-message.tsx: Detect [error]-prefixed text segments and render them as styled error banners with alert icon instead of plain text. - chat-panel.tsx: Restyle the transport-level error bar with themed colors and an alert icon consistent with in-message error styling.
2026-02-11 20:54:30 -08:00
// Capture stderr for debugging + error surfacing
child.stderr?.on("data", (chunk: Buffer) => {
Dench workspace: Tiptap markdown editor, subagent sessions, and error surfacing ── Tiptap Markdown Editor ── - Add full Tiptap-based WYSIWYG markdown editor (markdown-editor.tsx, 709 LOC) with bubble menu, auto-save (debounced), image drag-and-drop/paste upload, table editing, task list checkboxes, and frontmatter preservation on save. - Add slash command system (slash-command.tsx, 607 LOC) with "/" trigger for block insertion (headings, lists, tables, code blocks, images, reports) and "@" trigger for file/document mention with fuzzy search across the workspace tree. - Add ReportBlockNode (report-block-node.tsx) — custom Tiptap node that renders embedded report-json blocks as interactive ReportCard widgets inline in the editor, with expand/collapse and edit-JSON support. - Add workspace asset serving API (api/workspace/assets/[...path]/route.ts) to serve images from the workspace with proper MIME types. - Add workspace file upload orkspace/upload/route.ts) for multipart image uploads (10 MB limit, image types only), saving to assets/ directory. - Add ~500 lines of Tiptap editor CSS to globals.css (editor layout, task lists, images, tables, slash command dropdown, bubble menu toolbar, code blocks, etc.). - Add 14 @tiptap/* dependencies to apps/web/package.json (react, starter-kit, markdown, image, link, table, task-list, suggestion, placeholder, etc.). ── Document View: Edit/Read Mode Toggle ── - document-view.tsx: Add edit/read mode toggle; defaults to edit mode when a filePath is available. Lazy-loads MarkdownEditor to keep initial bundle light. - workspace/page.tsx: Pass activePath, tree, onSave, onNavigate, and onRefreshTree through to DocumentView for full editor integration with workspace navigation and tree refresh after saves. ── Subagent Session Isolation ── - agent-runner.ts: Add RunAgentOptions with optional sessionId; when set, spawns the agent with --session-key agent:main:subagent:<id> ant so file-scoped sidebar chats run in isolated sessions independent of the main agent. - route.ts (chat API): Accept sessionId from request body and forward it to runAgent. Resolve workspace file path prefixes (resolveAgentWorkspacePrefix) so tree-relative paths become agent-cwd-relative. - chat-panel.tsx: Create per-instance DefaultChatTransport that injects sessionId via body function and a ref (avoids stale closures). On file change, auto-load the most recent session and its messages. Refresh session tab list after streaming ends. Stop ongoing stream when switching sessions. - register.agent.ts: Add --session-key <key> and --lane <lane> CLI flags. - agent-via-gateway.ts: Wire sessionKey into session resolution and validation for both interactive and --stream-json code paths. - workspace.ts: Add resolveAgentWorkspacePrefix() to map workspace-root-relative paths to repo-root-relative paths for the agent process. ── Error Surfacing ── - agent-runner.ts: Add onAgentError callback extraction helpers (parseAgentErrorMessage, parseErrorBody, parseErrorFromStderr) to surface API-level errors (402 payment, rate limits, etc.) to the UI. Captures stderr for fallback error detection on non-zero exit. - route.ts: Wire onAgentError into the SSE stream as [error]-prefixed text parts. Improve onError and onClose handlers with clearer error messages and exit code reporting. - chat-message.tsx: Detect [error]-prefixed text segments and render them as styled error banners with alert icon instead of plain text. - chat-panel.tsx: Restyle the transport-level error bar with themed colors and an alert icon consistent with in-message error styling.
2026-02-11 20:54:30 -08:00
const text = chunk.toString();
stderrChunks.push(text);
Ironclaw rebrand: rename user-facing strings, package identity, and CLI references Rebrand from OpenClaw to Ironclaw across 16 files: Web app (apps/web): - layout.tsx: update metadata title to "Ironclaw" and description to "AI CRM with an agent that connects to your apps and does the work for you" - page.tsx: change landing page heading from "OpenClaw Dench" to "Ironclaw" - agent-runner.ts: rename stderr log prefix to [ironclaw stderr] - package.json: rename package from "openclaw-web" to "ironclaw-web" Package identity (root): - package.json: rename package from "openclaw-ai-sdk" to "ironclaw", update description to reflect CRM/workspace focus, change bin entry from "openclaw-ai-sdk" to "ironclaw" - openclaw.mjs: update error message to reference "ironclaw" - src/version.ts: change CORE_PACKAGE_NAME to "ironclaw" CLI and TUI: - command-format.ts: extend CLI prefix regex to accept both "ironclaw" and "openclaw" for backward compatibility - register.agent.ts: update example identity name to "Ironclaw" with 🔩 emoji (replacing 🦞) - tui.ts: rename TUI header from "openclaw tui" to "ironclaw tui" Onboarding and configuration wizards: - configure.wizard.ts: rename engine selection prompts and wizard intro headers to "Ironclaw" - onboarding.ts: rename onboarding intro and security warning text - onboarding.finalize.ts: rename all dashboard/control-UI messages and Brave Search setup instructions to reference "Ironclaw" Security audit: - audit.ts: rename state-dir permission warning details to "Ironclaw" - audit-extra.ts: rename plugin remediation text to "Ironclaw" Telegram: - bot-message-context.ts: rename access-denied message to "Ironclaw"
2026-02-11 23:38:34 -08:00
console.error("[ironclaw stderr]", text);
});
});
}
Dench workspace: Tiptap markdown editor, subagent sessions, and error surfacing ── Tiptap Markdown Editor ── - Add full Tiptap-based WYSIWYG markdown editor (markdown-editor.tsx, 709 LOC) with bubble menu, auto-save (debounced), image drag-and-drop/paste upload, table editing, task list checkboxes, and frontmatter preservation on save. - Add slash command system (slash-command.tsx, 607 LOC) with "/" trigger for block insertion (headings, lists, tables, code blocks, images, reports) and "@" trigger for file/document mention with fuzzy search across the workspace tree. - Add ReportBlockNode (report-block-node.tsx) — custom Tiptap node that renders embedded report-json blocks as interactive ReportCard widgets inline in the editor, with expand/collapse and edit-JSON support. - Add workspace asset serving API (api/workspace/assets/[...path]/route.ts) to serve images from the workspace with proper MIME types. - Add workspace file upload orkspace/upload/route.ts) for multipart image uploads (10 MB limit, image types only), saving to assets/ directory. - Add ~500 lines of Tiptap editor CSS to globals.css (editor layout, task lists, images, tables, slash command dropdown, bubble menu toolbar, code blocks, etc.). - Add 14 @tiptap/* dependencies to apps/web/package.json (react, starter-kit, markdown, image, link, table, task-list, suggestion, placeholder, etc.). ── Document View: Edit/Read Mode Toggle ── - document-view.tsx: Add edit/read mode toggle; defaults to edit mode when a filePath is available. Lazy-loads MarkdownEditor to keep initial bundle light. - workspace/page.tsx: Pass activePath, tree, onSave, onNavigate, and onRefreshTree through to DocumentView for full editor integration with workspace navigation and tree refresh after saves. ── Subagent Session Isolation ── - agent-runner.ts: Add RunAgentOptions with optional sessionId; when set, spawns the agent with --session-key agent:main:subagent:<id> ant so file-scoped sidebar chats run in isolated sessions independent of the main agent. - route.ts (chat API): Accept sessionId from request body and forward it to runAgent. Resolve workspace file path prefixes (resolveAgentWorkspacePrefix) so tree-relative paths become agent-cwd-relative. - chat-panel.tsx: Create per-instance DefaultChatTransport that injects sessionId via body function and a ref (avoids stale closures). On file change, auto-load the most recent session and its messages. Refresh session tab list after streaming ends. Stop ongoing stream when switching sessions. - register.agent.ts: Add --session-key <key> and --lane <lane> CLI flags. - agent-via-gateway.ts: Wire sessionKey into session resolution and validation for both interactive and --stream-json code paths. - workspace.ts: Add resolveAgentWorkspacePrefix() to map workspace-root-relative paths to repo-root-relative paths for the agent process. ── Error Surfacing ── - agent-runner.ts: Add onAgentError callback extraction helpers (parseAgentErrorMessage, parseErrorBody, parseErrorFromStderr) to surface API-level errors (402 payment, rate limits, etc.) to the UI. Captures stderr for fallback error detection on non-zero exit. - route.ts: Wire onAgentError into the SSE stream as [error]-prefixed text parts. Improve onError and onClose handlers with clearer error messages and exit code reporting. - chat-message.tsx: Detect [error]-prefixed text segments and render them as styled error banners with alert icon instead of plain text. - chat-panel.tsx: Restyle the transport-level error bar with themed colors and an alert icon consistent with in-message error styling.
2026-02-11 20:54:30 -08:00
// ── Error message extraction helpers ──
/**
* Extract a user-friendly error message from an agent event's data object.
* Handles various shapes: `{ error: "..." }`, `{ message: "..." }`,
* `{ errorMessage: "402 {...}" }`, etc.
*/
function parseAgentErrorMessage(
data: Record<string, unknown> | undefined,
): string | undefined {
if (!data) {return undefined;}
// Direct error string
if (typeof data.error === "string") {return parseErrorBody(data.error);}
// Message field
if (typeof data.message === "string") {return parseErrorBody(data.message);}
// errorMessage field (may contain "402 {json}")
if (typeof data.errorMessage === "string")
{return parseErrorBody(data.errorMessage);}
return undefined;
}
/**
* Parse a raw error string that may contain an HTTP status + JSON body,
* e.g. `402 {"error":{"message":"Insufficient funds..."}}`.
* Returns a clean, user-readable message.
*/
function parseErrorBody(raw: string): string {
// Try to extract JSON body from "STATUS {json}" pattern
const jsonIdx = raw.indexOf("{");
if (jsonIdx >= 0) {
try {
const parsed = JSON.parse(raw.slice(jsonIdx));
const msg =
parsed?.error?.message ?? parsed?.message ?? parsed?.error;
if (typeof msg === "string") {return msg;}
} catch {
// not valid JSON, fall through
}
}
return raw;
}
/**
* Extract a meaningful error message from raw stderr output.
* Strips ANSI codes and looks for common error patterns.
*/
function parseErrorFromStderr(stderr: string): string | undefined {
if (!stderr) {return undefined;}
// Strip ANSI escape codes
const clean = stderr.replace(
/\x1B\[[0-9;]*[A-Za-z]/g,
"",
);
// Look for JSON error bodies (e.g. from API responses)
const jsonMatch = clean.match(/\{"error":\{[^}]*"message":"([^"]+)"[^}]*\}/);
if (jsonMatch?.[1]) {return jsonMatch[1];}
// Look for lines containing "error" (case-insensitive)
const lines = clean.split("\n").filter(Boolean);
for (const line of lines) {
const trimmed = line.trim();
if (/\b(error|failed|fatal)\b/i.test(trimmed)) {
// Strip common prefixes like "[openclaw]", timestamps, etc.
const stripped = trimmed
.replace(/^\[.*?\]\s*/, "")
.replace(/^Error:\s*/i, "");
if (stripped.length > 5) {return stripped;}
}
}
// Last resort: return last non-empty line if it's short enough
const last = lines[lines.length - 1]?.trim();
if (last && last.length <= 300) {return last;}
return undefined;
}