feat: phase 3-5 — workflow engine, background subagents, multi-modal, cache shape, inline diff
Phase 3: Dynamic Workflow Engine - VM sandbox (node:vm) with agent/parallel/pipeline API, Claude Code compatible - Workflow file discovery (.boocode/workflows/*.js + ~/.boocode/workflows/*.js) - Workflow manager with session/chat creation and inference dispatch - Built-in catalog: deep-research, review-code, find-issues - Resumability cache: SHA-256 hash of agent spec, in-memory Map Phase 4: Background Subagents - background-task.ts service: spawn/poll/cancel lifecycle - spawn_subagent, subagent_status, subagent_result tools in ALL_TOOLS Phase 5: Multi-modal + Cache Shape - Multi-modal stub with type defs and hook point in payload.ts - CacheShapeBadge component in trace viewer (colored bar + %)
This commit is contained in:
@@ -76,6 +76,8 @@ export const MessageStartedFrame = z.object({
|
||||
message_id: Uuid,
|
||||
chat_id: Uuid.optional(),
|
||||
role: MessageRoleValue,
|
||||
// v2.8-compare: groups messages belonging to the same compare operation.
|
||||
compare_group_id: z.string().uuid().optional(),
|
||||
});
|
||||
|
||||
export const DeltaFrame = z.object({
|
||||
@@ -83,6 +85,7 @@ export const DeltaFrame = z.object({
|
||||
message_id: Uuid,
|
||||
chat_id: Uuid.optional(),
|
||||
content: z.string(),
|
||||
compare_group_id: z.string().uuid().optional(),
|
||||
});
|
||||
|
||||
export const ReasoningDeltaFrame = z.object({
|
||||
@@ -107,6 +110,10 @@ export const ToolResultFrame = z.object({
|
||||
output: z.unknown(),
|
||||
truncated: z.boolean(),
|
||||
error: z.string().optional(),
|
||||
// v2.8: unified diff for write tools (edit_file, create_file, etc.).
|
||||
// Published alongside successful tool results so the frontend can render
|
||||
// a compact diff snippet inline. Absent for read-only tools or failures.
|
||||
diff: z.string().optional(),
|
||||
});
|
||||
|
||||
export const MessageCompleteFrame = z.object({
|
||||
@@ -132,6 +139,7 @@ export const MessageCompleteFrame = z.object({
|
||||
// web reducer can render a muted "Stopped" / failed state without a new frame
|
||||
// type. Optional → fail-closed publishFrame must keep, not strip, it.
|
||||
status: z.enum(['complete', 'cancelled', 'failed']).optional(),
|
||||
compare_group_id: z.string().uuid().optional(),
|
||||
});
|
||||
|
||||
export const UsageFrame = z.object({
|
||||
@@ -168,6 +176,7 @@ export const ErrorFrame = z.object({
|
||||
chat_id: Uuid.optional(),
|
||||
error: z.string(),
|
||||
reason: ErrorReasonValue.optional(),
|
||||
compare_group_id: z.string().uuid().optional(),
|
||||
});
|
||||
|
||||
// ---- per-user channel frames (sidebar refresh) -----------------------------
|
||||
@@ -472,6 +481,7 @@ const TextChannelPayload = z.object({
|
||||
message_id: Uuid,
|
||||
chat_id: Uuid.optional(),
|
||||
content: z.string(),
|
||||
compare_group_id: z.string().uuid().optional(),
|
||||
});
|
||||
|
||||
const ToolCallChannelPayload = z.object({
|
||||
@@ -487,6 +497,7 @@ const ToolResultChannelPayload = z.object({
|
||||
output: z.unknown(),
|
||||
truncated: z.boolean(),
|
||||
error: z.string().optional(),
|
||||
diff: z.string().optional(),
|
||||
});
|
||||
|
||||
const StatusChannelPayload = z.object({
|
||||
@@ -534,6 +545,7 @@ export const ChannelDeltaFrame = z.object({
|
||||
tool_call_id: ToolCallId.optional(),
|
||||
output: z.unknown().optional(),
|
||||
truncated: z.boolean().optional(),
|
||||
diff: z.string().optional(),
|
||||
});
|
||||
|
||||
// ---- discriminated union ---------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user