mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-05-28 19:05:31 +02:00
feat: background tasks
Adds Background Tasks — recurring background agents the user can set up to either keep a digest current (daily email summary, top HN stories, weather brief) or perform a recurring action (draft a reply, post to Slack, call an API). Each task is a persistent set of instructions plus optional triggers (schedule, time-of-day window, or matching incoming Gmail / calendar event). The agent reads the verbs in the instructions on every run and picks the right mode automatically. User-facing surfaces: - New "Background tasks" entry in the sidebar, with a table listing every task, its schedule, last run, and an active toggle. - A detail page per task with a max-width reader showing the task's current output and a control sidebar for editing instructions, triggers, and reviewing run history. - "New task" can open in a free-form box where the user describes what they want and Copilot sets it up end-to-end, or in a structured form for manual setup. - "Edit with Copilot" hand-off from the detail view, pre-seeded with the task's context. Under the hood: - The event pipeline that previously powered live-notes is now a generic consumer registry. Live-notes and background tasks both subscribe; incoming events are routed to candidates from both concurrently. - Schedule helpers and the agent-message trigger block are factored out of live-notes into shared modules. Both features use the same building blocks now. - Copilot's proactive routing is reframed: anything recurring (cadence words, watch / monitor verbs, action verbs, event-conditional asks) now flows to background tasks. Live-notes load only on explicit mention. - A small reliability fix for the run-creation fallback chain: an empty-string model/provider passed by an LLM tool call now correctly falls through to the default instead of being persisted as a real value. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
13fa80c687
commit
b01af12148
45 changed files with 4025 additions and 594 deletions
|
|
@ -7,6 +7,12 @@ import { AgentScheduleConfig, AgentScheduleEntry } from './agent-schedule.js';
|
|||
import { AgentScheduleState } from './agent-schedule-state.js';
|
||||
import { ServiceEvent } from './service-events.js';
|
||||
import { LiveNoteAgentEvent, LiveNoteSchema } from './live-note.js';
|
||||
import {
|
||||
BackgroundTaskAgentEvent,
|
||||
BackgroundTaskSchema,
|
||||
BackgroundTaskSummarySchema,
|
||||
TriggersSchema,
|
||||
} from './background-task.js';
|
||||
import { UserMessageContent } from './message.js';
|
||||
import { RowboatApiConfig } from './rowboat-account.js';
|
||||
import { ZListToolkitsResponse } from './composio.js';
|
||||
|
|
@ -218,6 +224,10 @@ const ipcSchemas = {
|
|||
req: LiveNoteAgentEvent,
|
||||
res: z.null(),
|
||||
},
|
||||
'bg-task-agent:events': {
|
||||
req: BackgroundTaskAgentEvent,
|
||||
res: z.null(),
|
||||
},
|
||||
'models:list': {
|
||||
req: z.null(),
|
||||
res: z.object({
|
||||
|
|
@ -691,6 +701,95 @@ const ipcSchemas = {
|
|||
})),
|
||||
}),
|
||||
},
|
||||
// Background-task channels
|
||||
'bg-task:run': {
|
||||
req: z.object({
|
||||
slug: z.string(),
|
||||
context: z.string().optional(),
|
||||
}),
|
||||
res: z.object({
|
||||
success: z.boolean(),
|
||||
runId: z.string().nullable().optional(),
|
||||
summary: z.string().nullable().optional(),
|
||||
error: z.string().optional(),
|
||||
}),
|
||||
},
|
||||
'bg-task:get': {
|
||||
req: z.object({
|
||||
slug: z.string(),
|
||||
}),
|
||||
res: z.object({
|
||||
success: z.boolean(),
|
||||
task: BackgroundTaskSchema.nullable().optional(),
|
||||
error: z.string().optional(),
|
||||
}),
|
||||
},
|
||||
'bg-task:patch': {
|
||||
req: z.object({
|
||||
slug: z.string(),
|
||||
partial: BackgroundTaskSchema.partial(),
|
||||
}),
|
||||
res: z.object({
|
||||
success: z.boolean(),
|
||||
task: BackgroundTaskSchema.nullable().optional(),
|
||||
error: z.string().optional(),
|
||||
}),
|
||||
},
|
||||
'bg-task:create': {
|
||||
req: z.object({
|
||||
name: z.string(),
|
||||
instructions: z.string(),
|
||||
triggers: TriggersSchema.optional(),
|
||||
model: z.string().optional(),
|
||||
provider: z.string().optional(),
|
||||
}),
|
||||
res: z.object({
|
||||
success: z.boolean(),
|
||||
slug: z.string().optional(),
|
||||
error: z.string().optional(),
|
||||
}),
|
||||
},
|
||||
'bg-task:delete': {
|
||||
req: z.object({
|
||||
slug: z.string(),
|
||||
}),
|
||||
res: z.object({
|
||||
success: z.boolean(),
|
||||
error: z.string().optional(),
|
||||
}),
|
||||
},
|
||||
'bg-task:stop': {
|
||||
req: z.object({
|
||||
slug: z.string(),
|
||||
}),
|
||||
res: z.object({
|
||||
success: z.boolean(),
|
||||
error: z.string().optional(),
|
||||
}),
|
||||
},
|
||||
'bg-task:list': {
|
||||
req: z.object({
|
||||
offset: z.number().int().nonnegative().optional(),
|
||||
limit: z.number().int().positive().optional(),
|
||||
sort: z.enum(['createdAt:desc', 'createdAt:asc', 'name:asc']).optional(),
|
||||
}),
|
||||
res: z.object({
|
||||
items: z.array(BackgroundTaskSummarySchema),
|
||||
total: z.number().int().nonnegative(),
|
||||
}),
|
||||
},
|
||||
// Returns the runIds recorded in `bg-tasks/<slug>/runs.log` (newest first).
|
||||
// The renderer turns each id into a full Run via the existing `runs:fetch`
|
||||
// channel — bg-task transcripts now live at the global $WorkDir/runs/.
|
||||
'bg-task:listRunIds': {
|
||||
req: z.object({
|
||||
slug: z.string(),
|
||||
limit: z.number().int().positive().optional(),
|
||||
}),
|
||||
res: z.object({
|
||||
runIds: z.array(z.string()),
|
||||
}),
|
||||
},
|
||||
// Embedded browser (WebContentsView) channels
|
||||
'browser:setBounds': {
|
||||
req: z.object({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue