forked from QuintinShaw/pi-dynamic-workflows
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathworkflow.ts
More file actions
93 lines (90 loc) · 4.4 KB
/
Copy pathworkflow.ts
File metadata and controls
93 lines (90 loc) · 4.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
import {
createEffortState,
createWorkflowStorage,
createWorkflowTool,
installResultDelivery,
installTaskPanel,
installWorkflowEditor,
loadWorkflowSettings,
registerAllSavedWorkflows,
registerBuiltinWorkflows,
registerEffortCommand,
registerWorkflowCommands,
registerWorkflowModelsCommand,
saveWorkflowSettingsForCwd,
WorkflowManager,
} from "../src/index.js";
import { createWorkflowControlTool } from "../src/workflow-control-tool.js";
export default function extension(pi: ExtensionAPI) {
// Single manager/storage shared by the workflow tool and the /workflows command,
// so background runs started by the tool are reachable from the command.
const cwd = process.cwd();
const storage = createWorkflowStorage(cwd);
const settings = loadWorkflowSettings({ cwd });
const manager = new WorkflowManager({
cwd,
loadSavedWorkflow: (name) => storage.load(name)?.script,
defaultAgentTimeoutMs: settings.defaultAgentTimeoutMs ?? null,
concurrency: settings.defaultConcurrency,
defaultAgentRetries: settings.defaultAgentRetries,
persistAgentSessions: settings.persistAgentSessions,
});
const workflowTool = createWorkflowTool({ cwd, manager, storage });
const workflowControlTool = createWorkflowControlTool({ manager });
pi.registerTool(workflowTool);
pi.registerTool(workflowControlTool);
// Standing /effort opt-in (off|high|ultra): auto-arms a workflow for substantive
// messages, like CC's ultracode. Shared with the editor's input hook below and
// with the explicit /workflows run <prompt> manual trigger.
const effort = createEffortState();
registerWorkflowCommands(pi, manager, { storage, cwd, effort });
registerWorkflowModelsCommand(pi);
registerBuiltinWorkflows(pi, { cwd });
registerAllSavedWorkflows(pi, cwd, storage, manager);
registerEffortCommand(pi, effort);
// "Workflows mode": type `workflow(s)` to arm a forced workflow (animated),
// Backspace right after the word disarms it. Registers the `input` hook now;
// the editor itself is installed once the UI is available (session_start).
let editorInstalled = false;
pi.on("session_start", (_event: unknown, ctx: ExtensionContext) => {
// Tell the manager the session's main model so "explore" agents auto-tier
// down to a lighter same-family sibling (e.g. Claude → Haiku).
manager.setMainModel(ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined);
// Share the host session's model registry so tier/phase routing resolves
// extension-registered providers (e.g. ollama-cloud) consistently. Set it
// before activating the tool: the tool's promptGuidelines read the
// manager's registry lazily, so tool-registry refreshes from here on
// advertise the shared registry's models.
manager.setModelRegistry(ctx.modelRegistry);
const active = pi.getActiveTools();
const workflowTools = [workflowTool.name, workflowControlTool.name];
const missing = workflowTools.filter((name) => !active.includes(name));
if (missing.length) pi.setActiveTools([...active, ...missing]);
// Scope the /workflows history to this session: runs persist on disk across
// sessions, but the navigator/task panel show only the current session's runs.
// Switching back to a previous session re-shows that session's runs.
try {
manager.setSessionId(ctx.sessionManager?.getSessionId());
} catch {
// sessionManager may be unavailable in some contexts — fall back to global history.
}
// Deliver a background run's result into the conversation when it finishes.
// The live settings loader lets `deliveredResultMaxChars` take effect without
// a restart.
installResultDelivery(pi, manager, { loadSettings: () => loadWorkflowSettings({ cwd }) });
// Live "workflows running" panel below the input (focus + enter to open).
// Pass a live settings loader so /workflows-progress (compact|detailed) takes
// effect without a restart.
installTaskPanel(pi, manager, ctx.ui, { storage, cwd, loadSettings: () => loadWorkflowSettings({ cwd }) });
if (!editorInstalled) {
installWorkflowEditor(pi, ctx.ui, effort, {
settingsStore: {
load: () => loadWorkflowSettings({ cwd }),
save: (nextSettings) => saveWorkflowSettingsForCwd(nextSettings, cwd),
},
});
editorInstalled = true;
}
});
}