openclaw-workflowskill 0.2.1 → 0.3.1

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.
package/README.md CHANGED
@@ -13,38 +13,12 @@ Author, validate, run, and review WorkflowSkill workflows — without leaving th
13
13
  2. The agent writes, validates, and test-runs the workflow in chat
14
14
  3. Schedule it with cron — runs autonomously, no agent session needed
15
15
 
16
- ## What it looks like
17
-
18
- > **You:** I want to check Hacker News for AI stories every morning and email me a summary.
19
- >
20
- > **Agent:** I'll author a WorkflowSkill for that. *(invokes `/workflowskill-author`, writes a SKILL.md, runs `workflowskill_validate`)*
21
- >
22
- > Validated — 3 steps: `fetch`, `filter`, `email`. Running a test now... *(invokes `workflowskill_run`)*
23
- >
24
- > Run complete: 4 AI stories found, summary drafted. Ready to schedule — want me to set up a daily cron at 8 AM?
25
-
26
- ## Workflow Lifecycle
27
-
28
- ```
29
- describe workflow in natural language
30
-
31
- /workflowskill-author (agent writes YAML)
32
-
33
- workflowskill_validate (catch errors early)
34
-
35
- workflowskill_run (test run, review RunLog)
36
-
37
- workflowskill_runs (diagnose failures, iterate)
38
-
39
- cron (schedule for automated execution)
40
- ```
41
-
42
16
  ## Repositories
43
17
 
44
- | Repo | Description |
45
- |------|-------------|
46
- | [workflowskill](https://github.com/matthew-h-cromer/workflowskill) | Specification and reference runtime |
47
- | **openclaw-workflowskill** (this repo) | OpenClaw plugin — author, validate, run, and review workflows from the agent |
18
+ | Repo | Description |
19
+ | ------------------------------------------------------------------ | ---------------------------------------------------------------------------- |
20
+ | [workflowskill](https://github.com/matthew-h-cromer/workflowskill) | Specification and reference runtime |
21
+ | **openclaw-workflowskill** (this repo) | OpenClaw plugin — author, validate, run, and review workflows from the agent |
48
22
 
49
23
  ## Quick Start
50
24
 
@@ -56,17 +30,13 @@ Requires [OpenClaw](https://openclaw.ai).
56
30
  openclaw plugins install openclaw-workflowskill
57
31
  ```
58
32
 
59
- ### 2. Configure Anthropic credentials
60
-
61
- The plugin reads your Anthropic API key from OpenClaw's credential store — no `.env` file needed. Make sure an Anthropic auth profile is configured in OpenClaw (`~/.openclaw/agents/main/agent/auth-profiles.json`).
62
-
63
- ### 3. Restart the gateway
33
+ ### 2. Restart the gateway
64
34
 
65
35
  ```bash
66
36
  openclaw gateway restart
67
37
  ```
68
38
 
69
- ### 4. Verify
39
+ ### 3. Verify
70
40
 
71
41
  ```bash
72
42
  openclaw plugins list
@@ -76,16 +46,46 @@ openclaw skills list
76
46
  # → workflowskill-author (user-invocable)
77
47
  ```
78
48
 
49
+ > **Note:** `workflowskill_llm` uses your Anthropic credentials from the main agent — no separate API key configuration needed.
50
+
51
+ ### 4. Create a workflow
52
+
53
+ Just tell the agent what you want to automate:
54
+
55
+ > **You:** I want to check Hacker News for AI stories every morning and email me a summary.
56
+ >
57
+ > **Agent:** I'll author a WorkflowSkill for that. _(invokes `/workflowskill-author`, writes a SKILL.md, runs `workflowskill_validate`)_
58
+ >
59
+ > Validated — 3 steps: `fetch`, `filter`, `email`. Running a test now... _(invokes `workflowskill_run`)_
60
+ >
61
+ > Run complete: 4 AI stories found, summary drafted. Ready to schedule — want me to set up a daily cron at 8 AM?
62
+
63
+ ### 5. Schedule it
64
+
65
+ Ask the agent to set up a cron job, or add one manually at `~/.openclaw/cron/jobs.json`:
66
+
67
+ ```json
68
+ {
69
+ "payload": {
70
+ "kind": "agentTurn",
71
+ "message": "Run the daily-triage workflow using workflowskill_run\n\nSend results to Slack in the #general channel",
72
+ "model": "haiku"
73
+ }
74
+ }
75
+ ```
76
+
77
+ Your agent will use `"model": "haiku"` for cron jobs, ensuring execution is cheap and lightweight.
78
+
79
79
  ## Tools
80
80
 
81
81
  Registers four tools with the OpenClaw agent:
82
82
 
83
- | Tool | Description |
84
- |------|-------------|
85
- | `workflowskill_validate` | Parse and validate a SKILL.md or raw YAML workflow |
86
- | `workflowskill_run` | Execute a workflow and return a compact run summary |
87
- | `workflowskill_runs` | List and inspect past run logs |
88
- | `workflowskill_llm` | Call Anthropic directly for inline LLM reasoning in workflows |
83
+ | Tool | Description |
84
+ | ------------------------ | ------------------------------------------------------------- |
85
+ | `workflowskill_validate` | Parse and validate a SKILL.md or raw YAML workflow |
86
+ | `workflowskill_run` | Execute a workflow and return a compact run summary |
87
+ | `workflowskill_runs` | List and inspect past run logs |
88
+ | `workflowskill_llm` | Call Anthropic directly for inline LLM reasoning in workflows |
89
89
 
90
90
  Also ships the `/workflowskill-author` skill — just say "I want to automate X" and the agent handles the rest: researching, writing, validating, and test-running the workflow in chat.
91
91
 
@@ -100,22 +100,6 @@ Also ships the `/workflowskill-author` skill — just say "I want to automate X"
100
100
  daily-triage-2024-01-15T09-00-00.000Z.json
101
101
  ```
102
102
 
103
- ## Cron Scheduling
104
-
105
- Schedule a workflow to run autonomously via OpenClaw's cron, at `~/.openclaw/cron/jobs.json`:
106
-
107
- ```json
108
- {
109
- "payload": {
110
- "kind": "agentTurn",
111
- "message": "Run the daily-triage workflow using workflowskill_run\n\nSend results to Slack in the #general channel",
112
- "model": "haiku"
113
- }
114
- }
115
- ```
116
-
117
- Always set `"model": "haiku"` — cron runs are lightweight orchestration and don't need a powerful model. Put delivery instructions (e.g. Slack channel) in the cron message, not in the workflow, so workflows stay reusable.
118
-
119
103
  Review past runs via `workflowskill_runs`.
120
104
 
121
105
  ## Architecture
@@ -134,9 +118,9 @@ The plugin's own four tools (`workflowskill_validate`, `workflowskill_run`, `wor
134
118
 
135
119
  Parse and validate a SKILL.md or raw YAML workflow.
136
120
 
137
- | Param | Type | Required | Description |
138
- |-------|------|----------|-------------|
139
- | `content` | string | yes | SKILL.md text or raw workflow YAML |
121
+ | Param | Type | Required | Description |
122
+ | --------- | ------ | -------- | ---------------------------------- |
123
+ | `content` | string | yes | SKILL.md text or raw workflow YAML |
140
124
 
141
125
  Returns `{ valid, errors[], name, stepCount, stepTypes[] }`.
142
126
 
@@ -144,23 +128,23 @@ Returns `{ valid, errors[], name, stepCount, stepTypes[] }`.
144
128
 
145
129
  Execute a workflow and return a compact run summary. The full RunLog is persisted to `workflow-runs/` and retrievable via `workflowskill_runs` with `run_id`.
146
130
 
147
- | Param | Type | Required | Description |
148
- |-------|------|----------|-------------|
149
- | `workflow_name` | string | no* | Name of a skill resolved from skills directories |
150
- | `content` | string | no* | Inline SKILL.md content (bypasses skill files) |
151
- | `inputs` | object | no | Override workflow input defaults |
131
+ | Param | Type | Required | Description |
132
+ | --------------- | ------ | -------- | ------------------------------------------------ |
133
+ | `workflow_name` | string | no\* | Name of a skill resolved from skills directories |
134
+ | `content` | string | no\* | Inline SKILL.md content (bypasses skill files) |
135
+ | `inputs` | object | no | Override workflow input defaults |
152
136
 
153
- *One of `workflow_name` or `content` is required.
137
+ \*One of `workflow_name` or `content` is required.
154
138
 
155
139
  ### `workflowskill_runs`
156
140
 
157
141
  List and inspect past run logs.
158
142
 
159
- | Param | Type | Required | Description |
160
- |-------|------|----------|-------------|
161
- | `workflow_name` | string | no | Filter by workflow name |
162
- | `run_id` | string | no | Get full RunLog detail for one run |
163
- | `status` | string | no | Filter by `"success"` or `"failed"` |
143
+ | Param | Type | Required | Description |
144
+ | --------------- | ------ | -------- | ----------------------------------- |
145
+ | `workflow_name` | string | no | Filter by workflow name |
146
+ | `run_id` | string | no | Get full RunLog detail for one run |
147
+ | `status` | string | no | Filter by `"success"` or `"failed"` |
164
148
 
165
149
  No params → 20 most recent runs (summary view).
166
150
 
@@ -168,16 +152,16 @@ No params → 20 most recent runs (summary view).
168
152
 
169
153
  Call Anthropic directly and return the text response. Uses the API key from OpenClaw's credential store. Useful in workflow `tool` steps when you need inline LLM reasoning.
170
154
 
171
- | Param | Type | Required | Description |
172
- |-------|------|----------|-------------|
173
- | `prompt` | string | yes | The prompt to send to the LLM |
174
- | `model` | string | no | Model alias (`haiku`, `sonnet`, `opus`) or full model ID — omit to use the default |
155
+ | Param | Type | Required | Description |
156
+ | -------- | ------ | -------- | ---------------------------------------------------------------------------------- |
157
+ | `prompt` | string | yes | The prompt to send to the LLM |
158
+ | `model` | string | no | Model alias (`haiku`, `sonnet`, `opus`) or full model ID — omit to use the default |
175
159
 
176
160
  Returns `{ text: string }`.
177
161
 
178
162
  ## Development
179
163
 
180
- The plugin imports from `workflowskill` (peer dependency), installed from npm. No build step is required for type checking:
164
+ The plugin imports from `workflowskill`, installed from npm. No build step is required for type checking:
181
165
 
182
166
  ```bash
183
167
  npm install
package/index.ts CHANGED
@@ -4,12 +4,13 @@
4
4
  // Default-exports an object with id + register(api) per the OpenClaw plugin API.
5
5
 
6
6
  import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
7
+ import { homedir } from 'node:os';
7
8
  import { join } from 'node:path';
8
9
  import { AUTHORING_SKILL } from 'workflowskill';
9
10
  import { validateHandler } from './tools/validate.js';
10
11
  import { runHandler } from './tools/run.js';
11
12
  import { runsHandler } from './tools/runs.js';
12
- import { createAdapters, type GatewayConfig } from './lib/adapters.js';
13
+ import { createToolAdapter, type GatewayConfig } from './lib/adapters.js';
13
14
 
14
15
  // ─── OpenClaw plugin API types ─────────────────────────────────────────────
15
16
 
@@ -80,6 +81,70 @@ function toContent(result: unknown): { content: TextContent[] } {
80
81
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
81
82
  }
82
83
 
84
+ // ─── LLM helpers ───────────────────────────────────────────────────────────
85
+
86
+ const MODEL_ALIASES: Record<string, string> = {
87
+ haiku: 'claude-haiku-4-5-20251001',
88
+ sonnet: 'claude-sonnet-4-6',
89
+ opus: 'claude-opus-4-6',
90
+ };
91
+ const DEFAULT_MODEL = 'claude-haiku-4-5-20251001';
92
+
93
+ function readAnthropicApiKey(): string {
94
+ const profilesPath = join(homedir(), '.openclaw', 'agents', 'main', 'agent', 'auth-profiles.json');
95
+ let parsed: {
96
+ profiles?: Record<string, { provider?: string; key?: string }>;
97
+ lastGood?: Record<string, string>;
98
+ };
99
+ try {
100
+ parsed = JSON.parse(readFileSync(profilesPath, 'utf-8')) as typeof parsed;
101
+ } catch (err) {
102
+ throw new Error(
103
+ `WorkflowSkill: could not read OpenClaw auth profiles from ${profilesPath}: ${err instanceof Error ? err.message : String(err)}`,
104
+ );
105
+ }
106
+ const profiles = parsed.profiles ?? {};
107
+ const lastGoodName = parsed.lastGood?.['anthropic'];
108
+ const profile = lastGoodName
109
+ ? profiles[lastGoodName]
110
+ : Object.values(profiles).find((p) => p.provider === 'anthropic');
111
+ if (!profile?.key) {
112
+ throw new Error(
113
+ `WorkflowSkill: no anthropic profile found in ${profilesPath}. Add a profile with provider "anthropic" and a key.`,
114
+ );
115
+ }
116
+ return profile.key;
117
+ }
118
+
119
+ const ANTHROPIC_TIMEOUT_MS = 60_000;
120
+
121
+ async function callAnthropic(apiKey: string, model: string, prompt: string): Promise<string> {
122
+ const resolvedModel = MODEL_ALIASES[model] ?? model;
123
+ const response = await fetch('https://api.anthropic.com/v1/messages', {
124
+ method: 'POST',
125
+ headers: {
126
+ 'Content-Type': 'application/json',
127
+ 'x-api-key': apiKey,
128
+ 'anthropic-version': '2023-06-01',
129
+ },
130
+ body: JSON.stringify({
131
+ model: resolvedModel,
132
+ max_tokens: 8192,
133
+ messages: [{ role: 'user', content: prompt }],
134
+ }),
135
+ signal: AbortSignal.timeout(ANTHROPIC_TIMEOUT_MS),
136
+ });
137
+ if (!response.ok) {
138
+ const body = await response.text().catch(() => '');
139
+ throw new Error(`Anthropic API error ${response.status}: ${body}`);
140
+ }
141
+ const data = (await response.json()) as {
142
+ content: Array<{ type: string; text: string }>;
143
+ };
144
+ const text = data.content.find((b) => b.type === 'text')?.text ?? '';
145
+ return text;
146
+ }
147
+
83
148
  // ─── Plugin entry point ────────────────────────────────────────────────────
84
149
 
85
150
  export default {
@@ -104,7 +169,7 @@ export default {
104
169
  writeFileSync(join(skillDir, 'SKILL.md'), AUTHORING_SKILL + '\n' + openclawContext, 'utf-8');
105
170
 
106
171
  const gatewayConfig = buildGatewayConfig(api.config);
107
- const adapters = createAdapters(gatewayConfig);
172
+ const toolAdapter = createToolAdapter(gatewayConfig);
108
173
  const { registerTool } = api;
109
174
 
110
175
  // ── workflowskill_validate ────────────────────────────────────────────
@@ -125,7 +190,7 @@ export default {
125
190
  required: ['content'],
126
191
  },
127
192
  execute: async (_id, params) => {
128
- return toContent(await validateHandler(params as { content: string }, adapters.toolAdapter));
193
+ return toContent(validateHandler(params as { content: string }, toolAdapter));
129
194
  },
130
195
  });
131
196
 
@@ -159,7 +224,7 @@ export default {
159
224
  await runHandler(
160
225
  params as { workflow_name?: string; content?: string; inputs?: Record<string, unknown> },
161
226
  workspace,
162
- adapters,
227
+ toolAdapter,
163
228
  ),
164
229
  );
165
230
  },
@@ -203,14 +268,14 @@ export default {
203
268
  },
204
269
  });
205
270
 
206
- // ── workflowskill_llm ─────────────────────────────────────────────────────
271
+ // ── workflowskill_llm ─────────────────────────────────────────────────
207
272
  registerTool({
208
273
  name: 'workflowskill_llm',
209
274
  description:
210
- 'Call Anthropic directly and return the text response. ' +
211
- 'Uses the API key from OpenClaw\'s credential store (~/.openclaw/agents/main/agent/auth-profiles.json). ' +
275
+ 'Call the Anthropic LLM and return { text }. ' +
276
+ 'Uses the API key from OpenClaw\'s credential store. ' +
212
277
  'Use in workflow tool steps when you need LLM reasoning inline. ' +
213
- 'model is optional (haiku / sonnet / opus or full model ID); omit for the default.',
278
+ 'model is optional (haiku / sonnet / opus or full model ID); omit for haiku.',
214
279
  parameters: {
215
280
  type: 'object',
216
281
  properties: {
@@ -220,16 +285,18 @@ export default {
220
285
  },
221
286
  model: {
222
287
  type: 'string',
223
- description: 'Model alias or ID. Optional — omit to use the Anthropic default.',
288
+ description: 'Model alias (haiku/sonnet/opus) or full model ID. Optional.',
224
289
  },
225
290
  },
226
291
  required: ['prompt'],
227
292
  },
228
293
  execute: async (_id, params) => {
229
- const { prompt, model } = params as { prompt: string; model?: string };
230
- const result = await adapters.llmAdapter.call(model, prompt);
231
- return toContent({ text: result.text });
294
+ const { prompt, model = DEFAULT_MODEL } = params as { prompt: string; model?: string };
295
+ const apiKey = readAnthropicApiKey();
296
+ const text = await callAnthropic(apiKey, model, prompt);
297
+ return toContent({ text });
232
298
  },
233
299
  });
300
+
234
301
  },
235
302
  };
package/lib/adapters.ts CHANGED
@@ -1,27 +1,8 @@
1
- // adapters.ts — host-delegating adapters for the OpenClaw plugin.
1
+ // adapters.ts — host-delegating tool adapter for the OpenClaw plugin.
2
2
  //
3
3
  // Tool steps delegate to the Gateway HTTP API via HostToolAdapter (POST /tools/invoke).
4
- // LLM steps use AnthropicLLMAdapter with the API key read directly from
5
- // OpenClaw's credential store at ~/.openclaw/agents/main/agent/auth-profiles.json.
6
4
 
7
- import { readFileSync } from 'node:fs';
8
- import { homedir } from 'node:os';
9
- import { join } from 'node:path';
10
- import type { LLMAdapter, ToolAdapter, ToolDescriptor, ToolResult } from 'workflowskill';
11
- import { AnthropicLLMAdapter, BuiltinToolAdapter } from 'workflowskill';
12
-
13
- // Tools served locally by BuiltinToolAdapter (web.scrape, etc.)
14
- // These bypass the gateway and run in-process.
15
- const BUILTIN_TOOL_NAMES = new Set(['web.scrape']);
16
-
17
- // Lazy singleton — BuiltinToolAdapter.create() is async so we initialize on first use.
18
- let _builtinToolsPromise: Promise<BuiltinToolAdapter> | null = null;
19
- function getBuiltinTools(): Promise<BuiltinToolAdapter> {
20
- if (!_builtinToolsPromise) {
21
- _builtinToolsPromise = BuiltinToolAdapter.create();
22
- }
23
- return _builtinToolsPromise as Promise<BuiltinToolAdapter>;
24
- }
5
+ import type { ToolAdapter, ToolDescriptor, ToolResult } from 'workflowskill';
25
6
 
26
7
  export interface GatewayConfig {
27
8
  baseUrl: string;
@@ -29,11 +10,6 @@ export interface GatewayConfig {
29
10
  timeoutMs?: number;
30
11
  }
31
12
 
32
- export interface AdapterSet {
33
- toolAdapter: ToolAdapter;
34
- llmAdapter: LLMAdapter;
35
- }
36
-
37
13
  // Tools this plugin registers — must not be forwarded to the gateway to prevent infinite recursion.
38
14
  const SELF_REFERENCING_TOOLS = new Set([
39
15
  'workflowskill_validate',
@@ -116,84 +92,11 @@ export class HostToolAdapter implements ToolAdapter {
116
92
  }
117
93
 
118
94
  /**
119
- * Read the Anthropic API key from OpenClaw's credential store.
120
- * Throws a clear error if the file is missing or has no anthropic profile.
121
- */
122
- function readAnthropicApiKey(): string {
123
- const profilesPath = join(homedir(), '.openclaw', 'agents', 'main', 'agent', 'auth-profiles.json');
124
- let parsed: {
125
- profiles?: Record<string, { provider?: string; key?: string }>;
126
- lastGood?: Record<string, string>;
127
- };
128
- try {
129
- parsed = JSON.parse(readFileSync(profilesPath, 'utf-8')) as typeof parsed;
130
- } catch (err) {
131
- throw new Error(
132
- `WorkflowSkill: could not read OpenClaw auth profiles from ${profilesPath}: ${err instanceof Error ? err.message : String(err)}`,
133
- );
134
- }
135
- const profiles = parsed.profiles ?? {};
136
- // Prefer the profile OpenClaw last used successfully for anthropic.
137
- const lastGoodName = parsed.lastGood?.['anthropic'];
138
- const profile = lastGoodName
139
- ? profiles[lastGoodName]
140
- : Object.values(profiles).find((p) => p.provider === 'anthropic');
141
- if (!profile?.key) {
142
- throw new Error(
143
- `WorkflowSkill: no anthropic profile found in ${profilesPath}. Add a profile with provider "anthropic" and a key.`,
144
- );
145
- }
146
- return profile.key;
147
- }
148
-
149
- /**
150
- * Create host adapters backed by the Gateway HTTP API.
95
+ * Create a ToolAdapter backed by the Gateway HTTP API.
151
96
  *
152
97
  * HostToolAdapter forwards tool steps to the gateway's POST /tools/invoke endpoint.
153
- * Self-referencing tools (the plugin's own four tools) are blocked to prevent recursion.
154
- * LLM steps use AnthropicLLMAdapter with the key read from OpenClaw's credential store.
98
+ * Self-referencing tools (the plugin's own tools) are blocked to prevent recursion.
155
99
  */
156
- export function createAdapters(gatewayConfig: GatewayConfig): AdapterSet {
157
- const hostTools = new HostToolAdapter(gatewayConfig);
158
- const llmAdapter = new AnthropicLLMAdapter(readAnthropicApiKey());
159
-
160
- const LLM_COMPLETE = 'workflowskill_llm';
161
- const LLM_COMPLETE_DESCRIPTOR: ToolDescriptor = {
162
- name: LLM_COMPLETE,
163
- description: 'Call the host LLM with a prompt; returns { text }.',
164
- };
165
-
166
- const toolAdapter: ToolAdapter = {
167
- has(toolName: string): boolean {
168
- if (toolName === LLM_COMPLETE) return true;
169
- if (BUILTIN_TOOL_NAMES.has(toolName)) return true;
170
- return hostTools.has(toolName);
171
- },
172
- async invoke(toolName: string, args: Record<string, unknown>): Promise<ToolResult> {
173
- if (toolName === LLM_COMPLETE) {
174
- const result = await llmAdapter.call(
175
- args.model as string | undefined,
176
- args.prompt as string,
177
- );
178
- return { output: { text: result.text } };
179
- }
180
- if (BUILTIN_TOOL_NAMES.has(toolName)) {
181
- const builtinTools = await getBuiltinTools();
182
- return builtinTools.invoke(toolName, args);
183
- }
184
- return hostTools.invoke(toolName, args);
185
- },
186
- list(): ToolDescriptor[] {
187
- const hostToolList = hostTools.list();
188
- return [
189
- LLM_COMPLETE_DESCRIPTOR,
190
- ...hostToolList.filter((t) => t.name !== LLM_COMPLETE),
191
- ];
192
- },
193
- };
194
-
195
- return {
196
- toolAdapter,
197
- llmAdapter,
198
- };
100
+ export function createToolAdapter(gatewayConfig: GatewayConfig): ToolAdapter {
101
+ return new HostToolAdapter(gatewayConfig);
199
102
  }
package/lib/storage.ts CHANGED
@@ -53,7 +53,7 @@ export interface RunSummaryEntry {
53
53
  duration_ms: number;
54
54
  steps_executed: number;
55
55
  steps_skipped: number;
56
- total_tokens: number;
56
+ total_duration_ms: number;
57
57
  error_message?: string;
58
58
  }
59
59
 
@@ -87,7 +87,7 @@ export function listRuns(
87
87
  duration_ms: log.duration_ms,
88
88
  steps_executed: log.summary.steps_executed,
89
89
  steps_skipped: log.summary.steps_skipped,
90
- total_tokens: log.summary.total_tokens,
90
+ total_duration_ms: log.summary.total_duration_ms,
91
91
  error_message: log.error?.message,
92
92
  });
93
93
  } catch {
@@ -2,7 +2,7 @@
2
2
  "id": "workflowskill",
3
3
  "name": "WorkflowSkill",
4
4
  "description": "Author, validate, run, and review WorkflowSkill YAML workflows",
5
- "version": "0.1.0",
5
+ "version": "0.3.1",
6
6
  "skills": ["skills/workflowskill-author"],
7
7
  "configSchema": {
8
8
  "type": "object",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-workflowskill",
3
- "version": "0.2.1",
3
+ "version": "0.3.1",
4
4
  "description": "WorkflowSkill plugin for OpenClaw — author, validate, run, and review YAML workflows",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -35,7 +35,7 @@
35
35
  ]
36
36
  },
37
37
  "dependencies": {
38
- "workflowskill": "^0.2.0"
38
+ "workflowskill": "^0.3.1"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/node": "^25.3.0",
package/tools/run.ts CHANGED
@@ -5,8 +5,7 @@
5
5
  // Returns a compact summary to avoid blowing up the calling agent's context.
6
6
 
7
7
  import { runWorkflowSkill } from 'workflowskill';
8
- import type { RunLog, RunSummary } from 'workflowskill';
9
- import type { AdapterSet } from '../lib/adapters.js';
8
+ import type { RunLog, RunSummary, ToolAdapter } from 'workflowskill';
10
9
  import { resolveSkillContent, saveRunLog } from '../lib/storage.js';
11
10
 
12
11
  export interface RunParams {
@@ -64,7 +63,7 @@ function summarizeRunLog(log: RunLog): RunSummarySuccess | RunSummaryFailed {
64
63
  export async function runHandler(
65
64
  params: RunParams,
66
65
  workspace: string,
67
- adapters: AdapterSet,
66
+ toolAdapter: ToolAdapter,
68
67
  ): Promise<RunSummarySuccess | RunSummaryFailed> {
69
68
  const { workflow_name, content: inlineContent, inputs = {} } = params;
70
69
 
@@ -73,13 +72,10 @@ export async function runHandler(
73
72
  content = resolveSkillContent(workspace, workflow_name);
74
73
  }
75
74
 
76
- const { toolAdapter, llmAdapter } = adapters;
77
-
78
75
  const log: RunLog = await runWorkflowSkill({
79
76
  content,
80
77
  inputs,
81
78
  toolAdapter,
82
- llmAdapter,
83
79
  workflowName: workflow_name ?? 'inline',
84
80
  });
85
81
 
package/tools/validate.ts CHANGED
@@ -15,6 +15,6 @@ export interface ValidateResult {
15
15
  stepTypes?: string[];
16
16
  }
17
17
 
18
- export async function validateHandler(params: ValidateParams, toolAdapter: ToolAdapter): Promise<ValidateResult> {
18
+ export function validateHandler(params: ValidateParams, toolAdapter: ToolAdapter): ValidateResult {
19
19
  return validateWorkflowSkill({ content: params.content, toolAdapter });
20
20
  }