loopengine 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,26 +1,55 @@
1
- import type { WorkflowStep } from './system-agents/workflow-planner.js';
2
- export interface WorkflowRecord {
3
- /** lowercase-hyphenated; also its skill's folder name. */
1
+ export interface WorkflowParameter {
2
+ description: string;
3
+ required: boolean;
4
+ }
5
+ export interface Workflow {
6
+ /** The skill's id (its folder name). */
4
7
  id: string;
5
- name: string;
6
- summary: string;
7
- trigger: {
8
- kind: 'schedule' | 'on_request';
9
- description: string;
10
- };
11
- steps: WorkflowStep[];
12
- /** The message each run starts with. */
8
+ /** A name for people, e.g. "Refund check". */
9
+ title: string;
10
+ description: string;
13
11
  startMessage: string;
14
- /** Its schedule's name, when it has one (the Schedules tab's task_name). */
15
- scheduleName?: string;
16
- /** What the person wrote, kept for reference. */
17
- description?: string;
18
- createdAt: string;
12
+ /** When it runs, in plain words: "Every Monday at 9", "When asked". */
13
+ trigger: string;
14
+ parameters: Record<string, WorkflowParameter>;
15
+ /** Its steps: the skill body, placeholders unfilled. */
16
+ steps: string;
17
+ }
18
+ /** The front matter that makes a skill a workflow. */
19
+ export interface WorkflowFields {
20
+ title?: string;
21
+ startMessage: string;
22
+ trigger?: string;
23
+ parameters?: Record<string, WorkflowParameter>;
19
24
  }
20
- export declare function workflowsPath(agentDir: string): string;
21
- /** The agent's workflows; none when it has no workflows.yml or it can't be read. */
22
- export declare function readWorkflows(agentDir: string): WorkflowRecord[];
23
- /** Adds a workflow, replacing one with the same id. */
24
- export declare function saveWorkflow(agentDir: string, workflow: WorkflowRecord): void;
25
- /** Forgets a workflow. Its skill, schedule and rules are left as they are. */
26
- export declare function removeWorkflow(agentDir: string, id: string): void;
25
+ export declare class WorkflowParamsError extends Error {
26
+ }
27
+ /** Writes a skill file: its front matter (name and description first) and
28
+ * body. */
29
+ export declare function writeSkillFile(path: string, frontmatter: Record<string, unknown>, body: string): void;
30
+ /** The agent's workflows: its skills that have a start message. */
31
+ export declare function readWorkflows(agentDir: string): Workflow[];
32
+ export declare function readWorkflow(agentDir: string, id: string): Workflow | undefined;
33
+ /** Makes a skill a workflow, or changes how its runs start. The skill must
34
+ * exist; its body and other front matter are kept. */
35
+ export declare function setWorkflowFields(agentDir: string, id: string, fields: WorkflowFields): void;
36
+ /** Stops a skill being a workflow. The skill itself stays. */
37
+ export declare function clearWorkflowFields(agentDir: string, id: string): void;
38
+ /** Checks a run's parameters against what the workflow declares: every
39
+ * required one given, no unknown ones. Values are given as text (numbers
40
+ * and true/false are accepted and turned into text). */
41
+ export declare function validateParams(workflow: Workflow, input: unknown): Record<string, string>;
42
+ /** The message a run of the workflow starts with: its start message, then
43
+ * its steps, each $parameter filled in. Values no placeholder uses are
44
+ * listed as inputs, so the agent still gets them. */
45
+ export declare function workflowRunMessage(workflow: Workflow, params?: Record<string, string>): string;
46
+ export declare function legacyWorkflowsPath(agentDir: string): string;
47
+ /** Moves the workflows in an agent's workflows.yml into their skills'
48
+ * front matter, then renames the file to workflows.migrated.yml. Returns
49
+ * each moved workflow's id with the schedule name it was linked by, so
50
+ * the caller can point those schedules at the workflow. Does nothing
51
+ * when there is no workflows.yml. */
52
+ export declare function migrateWorkflowsFile(agentDir: string): {
53
+ id: string;
54
+ scheduleName?: string;
55
+ }[];
@@ -1,39 +1,230 @@
1
- // An agent's workflows: jobs it does, each a skill (its steps), a trigger
2
- // (a schedule, or a message) and checkpoints (questions, and tools set to
3
- // "ask"). Recorded in agents/<name>/workflows.yml when one is added from
4
- // "Describe a workflow", so the agent's Overview can list them; the skill,
5
- // the schedule and the rules themselves live where they always do.
6
- import { existsSync, readFileSync, writeFileSync } from 'node:fs';
7
- import { join } from 'node:path';
1
+ // An agent's workflows: skills it can be told to run, by hand, from an app
2
+ // over the API, or on a schedule. A workflow is a skill
3
+ // (agents/<name>/skills/<id>/SKILL.md) whose front matter also says how a
4
+ // run starts:
5
+ //
6
+ // ---
7
+ // name: refund-check
8
+ // description: Check a refund request against the order and our policy
9
+ // title: Refund check
10
+ // start_message: Check the refund request for order $order_number.
11
+ // trigger: When a refund request comes in
12
+ // parameters:
13
+ // order_number: { description: The order to check, required: true }
14
+ // customer_note: { description: What the customer wrote }
15
+ // ---
16
+ // 1. Look up order $order_number…
17
+ //
18
+ // The body is its steps. A run starts with the start message and those
19
+ // steps, with each $parameter filled in, so the model has them from its
20
+ // first turn rather than picking the skill from its index. None of these
21
+ // keys reach the model otherwise: the skill index shows only a skill's
22
+ // name and description (core/skillgarden).
23
+ //
24
+ // Agents from before kept their workflows in workflows.yml;
25
+ // migrateWorkflowsFile moves those into their skills.
26
+ import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, writeFileSync } from 'node:fs';
27
+ import { dirname, join } from 'node:path';
8
28
  import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
9
- export function workflowsPath(agentDir) {
10
- return join(agentDir, 'workflows.yml');
29
+ import { parseSkillFile, substituteParameters } from './skillgarden/index.js';
30
+ export class WorkflowParamsError extends Error {
31
+ }
32
+ const PARAMETER_NAME = /^[a-z_][a-z0-9_]*$/;
33
+ const WORKFLOW_KEYS = ['title', 'start_message', 'trigger', 'parameters'];
34
+ function skillsDir(agentDir) {
35
+ return join(agentDir, 'skills');
36
+ }
37
+ function skillPath(agentDir, id) {
38
+ return join(skillsDir(agentDir), id, 'SKILL.md');
39
+ }
40
+ function readSkillFile(path, id) {
41
+ if (!existsSync(path))
42
+ return undefined;
43
+ try {
44
+ const { frontmatter, body } = parseSkillFile(readFileSync(path, 'utf8'), id);
45
+ return { frontmatter: frontmatter, body };
46
+ }
47
+ catch {
48
+ return undefined;
49
+ }
11
50
  }
12
- /** The agent's workflows; none when it has no workflows.yml or it can't be read. */
51
+ /** Writes a skill file: its front matter (name and description first) and
52
+ * body. */
53
+ export function writeSkillFile(path, frontmatter, body) {
54
+ const { name, description, ...rest } = frontmatter;
55
+ const ordered = { name, description, ...rest };
56
+ mkdirSync(dirname(path), { recursive: true });
57
+ writeFileSync(path, `---\n${stringifyYaml(ordered).trimEnd()}\n---\n\n${body.trim()}\n`);
58
+ }
59
+ function titleFromId(id) {
60
+ const words = id.replace(/-/g, ' ');
61
+ return words.charAt(0).toUpperCase() + words.slice(1);
62
+ }
63
+ function parametersFrom(value) {
64
+ if (!value || typeof value !== 'object' || Array.isArray(value))
65
+ return {};
66
+ const parameters = {};
67
+ for (const [name, spec] of Object.entries(value)) {
68
+ if (!PARAMETER_NAME.test(name))
69
+ continue;
70
+ const s = spec && typeof spec === 'object' ? spec : {};
71
+ parameters[name] = { description: typeof s.description === 'string' ? s.description : '', required: s.required === true };
72
+ }
73
+ return parameters;
74
+ }
75
+ function workflowFrom(id, frontmatter, body) {
76
+ const startMessage = typeof frontmatter.start_message === 'string' ? frontmatter.start_message.trim() : '';
77
+ if (!startMessage)
78
+ return undefined;
79
+ return {
80
+ id,
81
+ title: typeof frontmatter.title === 'string' && frontmatter.title.trim() ? frontmatter.title.trim() : titleFromId(id),
82
+ description: typeof frontmatter.description === 'string' ? frontmatter.description : '',
83
+ startMessage,
84
+ trigger: typeof frontmatter.trigger === 'string' && frontmatter.trigger.trim() ? frontmatter.trigger.trim() : 'When asked',
85
+ parameters: parametersFrom(frontmatter.parameters),
86
+ steps: body,
87
+ };
88
+ }
89
+ /** The agent's workflows: its skills that have a start message. */
13
90
  export function readWorkflows(agentDir) {
14
- const path = workflowsPath(agentDir);
91
+ const dir = skillsDir(agentDir);
92
+ if (!existsSync(dir))
93
+ return [];
94
+ return readdirSync(dir, { withFileTypes: true })
95
+ .filter((entry) => entry.isDirectory())
96
+ .map((entry) => entry.name)
97
+ .sort()
98
+ .flatMap((id) => {
99
+ const skill = readSkillFile(skillPath(agentDir, id), id);
100
+ const workflow = skill && workflowFrom(id, skill.frontmatter, skill.body);
101
+ return workflow ? [workflow] : [];
102
+ });
103
+ }
104
+ export function readWorkflow(agentDir, id) {
105
+ if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(id))
106
+ return undefined;
107
+ const skill = readSkillFile(skillPath(agentDir, id), id);
108
+ return skill && workflowFrom(id, skill.frontmatter, skill.body);
109
+ }
110
+ /** Makes a skill a workflow, or changes how its runs start. The skill must
111
+ * exist; its body and other front matter are kept. */
112
+ export function setWorkflowFields(agentDir, id, fields) {
113
+ const path = skillPath(agentDir, id);
114
+ const skill = readSkillFile(path, id);
115
+ if (!skill)
116
+ throw new Error(`No skill "${id}" to make a workflow.`);
117
+ for (const name of Object.keys(fields.parameters ?? {})) {
118
+ if (!PARAMETER_NAME.test(name))
119
+ throw new Error(`Parameter "${name}": use lowercase letters, digits and _, starting with a letter, e.g. "order_number".`);
120
+ }
121
+ const frontmatter = { ...skill.frontmatter };
122
+ for (const key of WORKFLOW_KEYS)
123
+ delete frontmatter[key];
124
+ writeSkillFile(path, {
125
+ ...frontmatter,
126
+ ...(fields.title ? { title: fields.title } : {}),
127
+ start_message: fields.startMessage,
128
+ ...(fields.trigger ? { trigger: fields.trigger } : {}),
129
+ ...(fields.parameters && Object.keys(fields.parameters).length ? { parameters: fields.parameters } : {}),
130
+ }, skill.body);
131
+ }
132
+ /** Stops a skill being a workflow. The skill itself stays. */
133
+ export function clearWorkflowFields(agentDir, id) {
134
+ const path = skillPath(agentDir, id);
135
+ const skill = readSkillFile(path, id);
136
+ if (!skill)
137
+ return;
138
+ const frontmatter = { ...skill.frontmatter };
139
+ for (const key of WORKFLOW_KEYS)
140
+ delete frontmatter[key];
141
+ writeSkillFile(path, frontmatter, skill.body);
142
+ }
143
+ /** Checks a run's parameters against what the workflow declares: every
144
+ * required one given, no unknown ones. Values are given as text (numbers
145
+ * and true/false are accepted and turned into text). */
146
+ export function validateParams(workflow, input) {
147
+ if (input !== undefined && input !== null && (typeof input !== 'object' || Array.isArray(input))) {
148
+ throw new WorkflowParamsError('params must be an object of names to values, e.g. { "order_number": "EM20-123" }');
149
+ }
150
+ const given = (input ?? {});
151
+ const params = {};
152
+ const problems = [];
153
+ for (const [name, value] of Object.entries(given)) {
154
+ if (!(name in workflow.parameters)) {
155
+ problems.push(`unknown parameter "${name}"`);
156
+ continue;
157
+ }
158
+ if (value === undefined || value === null || value === '')
159
+ continue;
160
+ if (typeof value !== 'string' && typeof value !== 'number' && typeof value !== 'boolean') {
161
+ problems.push(`"${name}" must be text`);
162
+ continue;
163
+ }
164
+ params[name] = String(value);
165
+ }
166
+ for (const [name, spec] of Object.entries(workflow.parameters)) {
167
+ if (spec.required && !params[name]?.trim())
168
+ problems.push(`"${name}" is required`);
169
+ }
170
+ if (problems.length) {
171
+ const known = Object.keys(workflow.parameters);
172
+ throw new WorkflowParamsError(`${workflow.title}: ${problems.join('; ')}${known.length ? ` (its parameters: ${known.join(', ')})` : ' (it takes no parameters)'}`);
173
+ }
174
+ return params;
175
+ }
176
+ /** The message a run of the workflow starts with: its start message, then
177
+ * its steps, each $parameter filled in. Values no placeholder uses are
178
+ * listed as inputs, so the agent still gets them. */
179
+ export function workflowRunMessage(workflow, params = {}) {
180
+ const used = new Set();
181
+ const declared = Object.keys(workflow.parameters);
182
+ // Named placeholders only: positional $1-style filling would eat dollar
183
+ // amounts like "$50" in the steps.
184
+ const fill = (text) => substituteParameters(text, params, { declared, used });
185
+ const start = fill(workflow.startMessage);
186
+ const steps = fill(workflow.steps).trim();
187
+ const unused = Object.entries(params).filter(([name]) => !used.has(name));
188
+ return [
189
+ start,
190
+ unused.length ? `Inputs:\n${unused.map(([name, value]) => `- ${name}: ${value}`).join('\n')}` : '',
191
+ steps ? `These are the steps, from your "${workflow.id}" skill:\n\n${steps}` : '',
192
+ ].filter(Boolean).join('\n\n');
193
+ }
194
+ export function legacyWorkflowsPath(agentDir) {
195
+ return join(agentDir, 'workflows.yml');
196
+ }
197
+ /** Moves the workflows in an agent's workflows.yml into their skills'
198
+ * front matter, then renames the file to workflows.migrated.yml. Returns
199
+ * each moved workflow's id with the schedule name it was linked by, so
200
+ * the caller can point those schedules at the workflow. Does nothing
201
+ * when there is no workflows.yml. */
202
+ export function migrateWorkflowsFile(agentDir) {
203
+ const path = legacyWorkflowsPath(agentDir);
15
204
  if (!existsSync(path))
16
205
  return [];
206
+ let records = [];
17
207
  try {
18
208
  const parsed = parseYaml(readFileSync(path, 'utf8'));
19
- return Array.isArray(parsed?.workflows) ? parsed.workflows.filter((w) => w && typeof w.id === 'string' && typeof w.name === 'string') : [];
209
+ records = Array.isArray(parsed?.workflows) ? parsed.workflows.filter((w) => w && typeof w.id === 'string') : [];
20
210
  }
21
211
  catch {
22
212
  return [];
23
213
  }
24
- }
25
- /** Adds a workflow, replacing one with the same id. */
26
- export function saveWorkflow(agentDir, workflow) {
27
- const workflows = readWorkflows(agentDir).filter((w) => w.id !== workflow.id);
28
- workflows.push(workflow);
29
- const header = "# This agent's workflows, added from the console's \"Describe a workflow\". Each one's\n# steps are its skill (skills/<id>/SKILL.md); its schedule and rules are in the Schedules and Permissions tabs.\n";
30
- writeFileSync(workflowsPath(agentDir), header + stringifyYaml({ workflows }));
31
- }
32
- /** Forgets a workflow. Its skill, schedule and rules are left as they are. */
33
- export function removeWorkflow(agentDir, id) {
34
- const workflows = readWorkflows(agentDir);
35
- if (!workflows.some((w) => w.id === id))
36
- return;
37
- const rest = workflows.filter((w) => w.id !== id);
38
- writeFileSync(workflowsPath(agentDir), stringifyYaml({ workflows: rest }));
214
+ const moved = [];
215
+ for (const record of records) {
216
+ const skill = readSkillFile(skillPath(agentDir, record.id), record.id);
217
+ if (!skill || !record.startMessage?.trim())
218
+ continue;
219
+ if (!workflowFrom(record.id, skill.frontmatter, skill.body)) {
220
+ setWorkflowFields(agentDir, record.id, {
221
+ ...(record.name ? { title: record.name } : {}),
222
+ startMessage: record.startMessage,
223
+ ...(record.trigger?.description ? { trigger: record.trigger.description } : {}),
224
+ });
225
+ }
226
+ moved.push({ id: record.id, ...(record.scheduleName ? { scheduleName: record.scheduleName } : {}) });
227
+ }
228
+ renameSync(path, join(agentDir, 'workflows.migrated.yml'));
229
+ return moved;
39
230
  }
package/dist/index.d.ts CHANGED
@@ -10,7 +10,7 @@ export { setUsageSink, recordUsage, type UsageEvent, type UsageSink } from '#cor
10
10
  export { readNotifierFile, writeNotifierFile, removeNotifierFile, validateNotifierFile, notifierConfigFromFile, NotifierFileError, NOTIFIER_SECRET_VARS, type NotifierFile, type MessagingApprover } from '#core/notifier-file.js';
11
11
  export { listDeliveries, recordDelivery, type NotifierDelivery } from '#core/notifier-deliveries.js';
12
12
  export { describeNotifier } from '#core/http-notifier.js';
13
- export { Scheduler, ScheduleError, FileSchedulerStore, getSchedulerStore, setSchedulerStore, createScheduledTask, listScheduledTasks, getScheduledTask, cancelScheduledTask, pauseScheduledTask, resumeScheduledTask, runScheduledTaskNow, deleteScheduledTask, nextScheduledWakeAt, moveScheduledTasksToTimeZone, importLegacyScheduledTasks, parseEvery, describeSchedule, type ScheduledTask, type ScheduledTaskRun, type ScheduledTaskStatus, type Schedule, type SchedulerStore, type FireTask, type CreateScheduledTaskInput } from '#core/scheduler.js';
13
+ export { Scheduler, ScheduleError, FileSchedulerStore, getSchedulerStore, setSchedulerStore, createScheduledTask, listScheduledTasks, getScheduledTask, cancelScheduledTask, pauseScheduledTask, resumeScheduledTask, runScheduledTaskNow, setScheduledTaskNotify, deleteScheduledTask, nextScheduledWakeAt, moveScheduledTasksToTimeZone, importLegacyScheduledTasks, parseEvery, describeSchedule, type ScheduledTask, type ScheduledTaskRun, type ScheduledTaskStatus, type Schedule, type SchedulerStore, type FireTask, type CreateScheduledTaskInput } from '#core/scheduler.js';
14
14
  export { NOTIFIER_SLACK_SIGNING_SECRET_VAR } from '#core/notifier-file.js';
15
15
  export { firstSighting, handleInboundMessage, handleMessagingAction, settleThreadChoice, isPlainApproval, type MessagingDeps, type MessagingDecision, type DecisionOutcome } from '#core/messaging/engine.js';
16
16
  export { formatArgs, formatChange, labelFor } from '#core/messaging/format-args.js';
@@ -81,9 +81,12 @@ export { templatesPageHtml } from './web/templates-page.js';
81
81
  export { TemplateError, createFromTemplate, createFromTemplateObject, describeTemplateSchedule, listTemplates, previewTemplate, templateChecklist, type CreatedTemplateAgent, type LegacyTemplateCreateDeps, type TemplateChecklistItem, type TemplateCreateDeps, type TemplatePreview, type TemplateSummary, } from './web/templates-admin.js';
82
82
  export { STARTER_TEMPLATES, starterTemplate, templateScheduleStart, type StarterTemplate, type TemplateRule, type TemplateSchedule, type TemplateSetup, type TemplateSkill, } from './core/system-agents/templates.js';
83
83
  export { workflowPageHtml } from './web/workflow-page.js';
84
- export { WorkflowError, checkWorkflowForAgent, createWorkflow, forgetWorkflow, getPlanJob, listAgentWorkflows, planWorkflow, resolveConnections, runWorkflowNow, startPlanJob, type AgentWorkflowView, type CreatedWorkflow, type PlanJob, type PlannedWorkflow, type WorkflowAgentInfo, type WorkflowCheck, type WorkflowConflict, type WorkflowCreateDeps, type WorkflowMcpDeps, type WorkflowMcpCreateDeps, resolveMcpServers, prepareMcpAbilities, } from './web/workflow-admin.js';
85
- export { WORKFLOW_PLANNER_PROMPT, planWorkflowWithModel, validateWorkflowPlan, workflowTemplate, type WorkflowPlan, type WorkflowPlannerTools, type WorkflowStep } from './core/system-agents/workflow-planner.js';
86
- export { readWorkflows, removeWorkflow, saveWorkflow, type WorkflowRecord } from './core/workflows.js';
84
+ export { WorkflowError, checkWorkflowForAgent, createWorkflow, forgetWorkflow, migrateAgentWorkflows, getPlanJob, listAgentWorkflows, planWorkflow, resolveConnections, prepareWorkflowRun, updateWorkflow, startPlanJob, type AgentWorkflowView, type CreatedWorkflow, type PlanJob, type PlannedWorkflow, type WorkflowAgentInfo, type WorkflowCheck, type WorkflowConflict, type WorkflowCreateDeps, type WorkflowMcpDeps, type WorkflowMcpCreateDeps, resolveMcpServers, prepareMcpAbilities, } from './web/workflow-admin.js';
85
+ export { WORKFLOW_PLANNER_PROMPT, planParameters, planWorkflowWithModel, validateWorkflowPlan, workflowTemplate, type WorkflowPlan, type WorkflowPlannerTools, type WorkflowStep } from './core/system-agents/workflow-planner.js';
86
+ export { createTrigger, updateTrigger, rotateTrigger, listTriggers, findTriggerByToken, publicTrigger, checkTriggerSettings, verifySenderSignature, parsePayload, valueAt, deliveryId, passesFilter, paramsFromPayload, recordDelivery as recordTriggerDelivery, FileTriggerStore, getTriggerStore, setTriggerStore, TriggerError, type WorkflowTrigger, type PublicTrigger, type TriggerSettings, type TriggerVerify, type TriggerFilter, type TriggerSender, type SignatureAlgorithm, type TriggerDelivery, type TriggerOutcome, type TriggerStore } from './core/workflow-triggers.js';
87
+ export { checkCallbackUrl, callbackSecret, signCallback, deliverCallback, runCallbackPayload, isPrivateAddress, CallbackUrlError, type CallbackDelivery, type RunCallbackEvent } from './core/run-callbacks.js';
88
+ export { WorkflowRunner, FileRunStore, getRunStore, setRunStore, listRuns, getRun, isUnderWay, RunError, type WorkflowRun, type WorkflowRunStatus, type RunStore, type ExecuteRun, type RunOutcome, type StartRunInput } from './core/workflow-runs.js';
89
+ export { readWorkflows, readWorkflow, setWorkflowFields, clearWorkflowFields, validateParams, workflowRunMessage, migrateWorkflowsFile, WorkflowParamsError, type Workflow, type WorkflowFields, type WorkflowParameter } from './core/workflows.js';
87
90
  export { globalConfigPageHtml } from './web/global-config-page.js';
88
91
  export { playgroundHtml } from './web/playground.js';
89
92
  export { readSkill, writeSkill, deleteSkill, SkillInvalidIdError, SkillNotFoundError } from './web/skills-admin.js';
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ export { setUsageSink, recordUsage } from '#core/usage.js';
12
12
  export { readNotifierFile, writeNotifierFile, removeNotifierFile, validateNotifierFile, notifierConfigFromFile, NotifierFileError, NOTIFIER_SECRET_VARS } from '#core/notifier-file.js';
13
13
  export { listDeliveries, recordDelivery } from '#core/notifier-deliveries.js';
14
14
  export { describeNotifier } from '#core/http-notifier.js';
15
- export { Scheduler, ScheduleError, FileSchedulerStore, getSchedulerStore, setSchedulerStore, createScheduledTask, listScheduledTasks, getScheduledTask, cancelScheduledTask, pauseScheduledTask, resumeScheduledTask, runScheduledTaskNow, deleteScheduledTask, nextScheduledWakeAt, moveScheduledTasksToTimeZone, importLegacyScheduledTasks, parseEvery, describeSchedule } from '#core/scheduler.js';
15
+ export { Scheduler, ScheduleError, FileSchedulerStore, getSchedulerStore, setSchedulerStore, createScheduledTask, listScheduledTasks, getScheduledTask, cancelScheduledTask, pauseScheduledTask, resumeScheduledTask, runScheduledTaskNow, setScheduledTaskNotify, deleteScheduledTask, nextScheduledWakeAt, moveScheduledTasksToTimeZone, importLegacyScheduledTasks, parseEvery, describeSchedule } from '#core/scheduler.js';
16
16
  export { NOTIFIER_SLACK_SIGNING_SECRET_VAR } from '#core/notifier-file.js';
17
17
  export { firstSighting, handleInboundMessage, handleMessagingAction, settleThreadChoice, isPlainApproval } from '#core/messaging/engine.js';
18
18
  export { formatArgs, formatChange, labelFor } from '#core/messaging/format-args.js';
@@ -74,9 +74,12 @@ export { templatesPageHtml } from './web/templates-page.js';
74
74
  export { TemplateError, createFromTemplate, createFromTemplateObject, describeTemplateSchedule, listTemplates, previewTemplate, templateChecklist, } from './web/templates-admin.js';
75
75
  export { STARTER_TEMPLATES, starterTemplate, templateScheduleStart, } from './core/system-agents/templates.js';
76
76
  export { workflowPageHtml } from './web/workflow-page.js';
77
- export { WorkflowError, checkWorkflowForAgent, createWorkflow, forgetWorkflow, getPlanJob, listAgentWorkflows, planWorkflow, resolveConnections, runWorkflowNow, startPlanJob, resolveMcpServers, prepareMcpAbilities, } from './web/workflow-admin.js';
78
- export { WORKFLOW_PLANNER_PROMPT, planWorkflowWithModel, validateWorkflowPlan, workflowTemplate } from './core/system-agents/workflow-planner.js';
79
- export { readWorkflows, removeWorkflow, saveWorkflow } from './core/workflows.js';
77
+ export { WorkflowError, checkWorkflowForAgent, createWorkflow, forgetWorkflow, migrateAgentWorkflows, getPlanJob, listAgentWorkflows, planWorkflow, resolveConnections, prepareWorkflowRun, updateWorkflow, startPlanJob, resolveMcpServers, prepareMcpAbilities, } from './web/workflow-admin.js';
78
+ export { WORKFLOW_PLANNER_PROMPT, planParameters, planWorkflowWithModel, validateWorkflowPlan, workflowTemplate } from './core/system-agents/workflow-planner.js';
79
+ export { createTrigger, updateTrigger, rotateTrigger, listTriggers, findTriggerByToken, publicTrigger, checkTriggerSettings, verifySenderSignature, parsePayload, valueAt, deliveryId, passesFilter, paramsFromPayload, recordDelivery as recordTriggerDelivery, FileTriggerStore, getTriggerStore, setTriggerStore, TriggerError } from './core/workflow-triggers.js';
80
+ export { checkCallbackUrl, callbackSecret, signCallback, deliverCallback, runCallbackPayload, isPrivateAddress, CallbackUrlError } from './core/run-callbacks.js';
81
+ export { WorkflowRunner, FileRunStore, getRunStore, setRunStore, listRuns, getRun, isUnderWay, RunError } from './core/workflow-runs.js';
82
+ export { readWorkflows, readWorkflow, setWorkflowFields, clearWorkflowFields, validateParams, workflowRunMessage, migrateWorkflowsFile, WorkflowParamsError } from './core/workflows.js';
80
83
  export { globalConfigPageHtml } from './web/global-config-page.js';
81
84
  export { playgroundHtml } from './web/playground.js';
82
85
  export { readSkill, writeSkill, deleteSkill, SkillInvalidIdError, SkillNotFoundError } from './web/skills-admin.js';