mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-04-25 00:16:29 +02:00
copilot can trigger runs
This commit is contained in:
parent
e9a073e2e4
commit
88e27c04b7
3 changed files with 92 additions and 3 deletions
|
|
@ -17,7 +17,7 @@ import tracksSkill from "./tracks/skill.js";
|
|||
const CURRENT_DIR = path.dirname(fileURLToPath(import.meta.url));
|
||||
const CATALOG_PREFIX = "src/application/assistant/skills";
|
||||
|
||||
console.log(tracksSkill);
|
||||
// console.log(tracksSkill);
|
||||
|
||||
type SkillDefinition = {
|
||||
id: string; // Also used as folder name
|
||||
|
|
|
|||
|
|
@ -206,8 +206,63 @@ schedule:
|
|||
## After Insertion
|
||||
|
||||
- Confirm in one line: "Added ` + "`" + `chicago-time` + "`" + ` track, refreshing hourly."
|
||||
- Mention the user can click **Play** on the block to run it immediately.
|
||||
- **Do not** write anything into the ` + "`" + `<!--track-target:...-->` + "`" + ` region — the runner populates it.
|
||||
- **Then offer to run it once now** (see "Running a Track" below) — especially valuable for newly created blocks where the target region is otherwise empty until the next scheduled or event-triggered run.
|
||||
- **Do not** write anything into the ` + "`" + `<!--track-target:...-->` + "`" + ` region yourself — use the ` + "`" + `run-track-block` + "`" + ` tool to delegate to the track agent.
|
||||
|
||||
## Running a Track (the ` + "`" + `run-track-block` + "`" + ` tool)
|
||||
|
||||
The ` + "`" + `run-track-block` + "`" + ` tool manually triggers a track run right now. Equivalent to the user clicking the Play button — but you can pass extra ` + "`" + `context` + "`" + ` to bias what the track agent does on this single run (without modifying the block's ` + "`" + `instruction` + "`" + `).
|
||||
|
||||
### When to proactively offer to run
|
||||
|
||||
These are upsells — ask first, don't run silently.
|
||||
|
||||
- **Just created a new track block.** Before declaring done, offer:
|
||||
> "Want me to run it once now to seed the initial content?"
|
||||
|
||||
This is **especially valuable for event-triggered tracks** (with ` + "`" + `eventMatchCriteria` + "`" + `) — otherwise the target region stays empty until the next matching event arrives.
|
||||
|
||||
For tracks that pull from existing local data (synced emails, calendar, meeting notes), suggest a **backfill** with explicit context (see below).
|
||||
|
||||
- **Just edited an existing track.** Offer:
|
||||
> "Want me to run it now to see the updated output?"
|
||||
|
||||
- **Explicit user request.** "run the X track", "test it", "refresh that block" → call the tool directly.
|
||||
|
||||
### Using the ` + "`" + `context` + "`" + ` parameter (the powerful case)
|
||||
|
||||
The ` + "`" + `context` + "`" + ` parameter is extra guidance for the track agent on this run only. It's the difference between a stock refresh and a smart backfill.
|
||||
|
||||
**Examples:**
|
||||
|
||||
- New track: "Track emails about Q3 planning" → after creating it, run with:
|
||||
> context: "Initial backfill — scan ` + "`" + `gmail_sync/` + "`" + ` for emails from the last 90 days that match this track's topic (Q3 planning, OKRs, roadmap), and synthesize the initial summary."
|
||||
|
||||
- New track: "Summarize this week's customer calls" → run with:
|
||||
> context: "Backfill from this week's meeting notes in ` + "`" + `granola_sync/` + "`" + ` and ` + "`" + `fireflies_sync/` + "`" + `."
|
||||
|
||||
- Manual refresh after the user mentions a recent change:
|
||||
> context: "Focus on changes from the last 7 days only."
|
||||
|
||||
- Plain refresh (user says "run it now"): **omit ` + "`" + `context` + "`" + ` entirely**. Don't invent context — it can mislead the agent.
|
||||
|
||||
### What to do with the result
|
||||
|
||||
The tool returns ` + "`" + `{ success, runId, action, summary, contentAfter, error }` + "`" + `:
|
||||
|
||||
- **` + "`" + `action: 'replace'` + "`" + `** → the track was updated. Confirm with one line, optionally citing the first line of ` + "`" + `contentAfter` + "`" + `:
|
||||
> "Done — track now shows: 72°F, partly cloudy in Chicago."
|
||||
|
||||
- **` + "`" + `action: 'no_update'` + "`" + `** → the agent decided nothing needed to change. Tell the user briefly; ` + "`" + `summary` + "`" + ` may explain why.
|
||||
|
||||
- **` + "`" + `error` + "`" + ` set** → surface it concisely. If the error is ` + "`" + `'Already running'` + "`" + ` (concurrency guard), let the user know the track is mid-run and to retry shortly.
|
||||
|
||||
### Don'ts
|
||||
|
||||
- **Don't auto-run** after every edit — ask first.
|
||||
- **Don't pass ` + "`" + `context` + "`" + `** for a plain refresh — only when there's specific extra guidance to give.
|
||||
- **Don't use ` + "`" + `run-track-block` + "`" + ` to manually write content** — that's ` + "`" + `update-track-content` + "`" + `'s job (and even that should be rare; the track agent handles content via this tool).
|
||||
- **Don't ` + "`" + `run-track-block` + "`" + ` repeatedly** in a single turn — one run per user-facing action.
|
||||
|
||||
## Proactive Suggestions
|
||||
|
||||
|
|
|
|||
|
|
@ -1450,4 +1450,38 @@ export const BuiltinTools: z.infer<typeof BuiltinToolsSchema> = {
|
|||
}
|
||||
},
|
||||
},
|
||||
|
||||
'run-track-block': {
|
||||
description: "Manually trigger a track block to run now. Equivalent to the user clicking the Play button on the block, but you can pass extra `context` to bias what the track agent does this run — most useful for backfills (e.g. seeding a new email-tracking block from existing synced emails) or focused refreshes. Returns the action taken, summary, and the new content.",
|
||||
inputSchema: z.object({
|
||||
filePath: z.string().describe("Workspace-relative path to the note file (e.g., 'knowledge/Notes/my-note.md')"),
|
||||
trackId: z.string().describe("The track block's trackId (must exist in the file)"),
|
||||
context: z.string().optional().describe(
|
||||
"Optional extra context for the track agent to consider for THIS run only — does not modify the block's instruction. " +
|
||||
"Use it to drive backfills (e.g. 'Backfill from existing synced emails in gmail_sync/ from the last 90 days about this topic') " +
|
||||
"or focused refreshes (e.g. 'Focus on changes from the last 7 days'). " +
|
||||
"Omit for a plain refresh."
|
||||
),
|
||||
}),
|
||||
execute: async ({ filePath, trackId, context }: { filePath: string; trackId: string; context?: string }) => {
|
||||
const knowledgeRelativePath = filePath.replace(/^knowledge\//, '');
|
||||
try {
|
||||
// Lazy import to break a module-init cycle:
|
||||
// builtin-tools → track/runner → runs/runs → agents/runtime → builtin-tools
|
||||
const { triggerTrackUpdate } = await import("../../knowledge/track/runner.js");
|
||||
const result = await triggerTrackUpdate(trackId, knowledgeRelativePath, context, 'manual');
|
||||
return {
|
||||
success: !result.error,
|
||||
runId: result.runId,
|
||||
action: result.action,
|
||||
summary: result.summary,
|
||||
contentAfter: result.contentAfter,
|
||||
error: result.error,
|
||||
};
|
||||
} catch (err) {
|
||||
const msg = err instanceof Error ? err.message : String(err);
|
||||
return { success: false, error: msg };
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue