@jiggai/recipes 0.4.25 → 0.4.26
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/index.ts
CHANGED
|
@@ -654,10 +654,12 @@ const recipesPlugin = {
|
|
|
654
654
|
.description("Claim and execute a single queued workflow run (intended for cron-driven runner)")
|
|
655
655
|
.requiredOption("--team-id <teamId>", "Team id (workspace-<teamId>)")
|
|
656
656
|
.option("--lease-seconds <n>", "Lease duration in seconds", (v: string) => Number(v))
|
|
657
|
-
.
|
|
657
|
+
.option("--run-id <runId>", "Only claim this specific run id")
|
|
658
|
+
.action(async (options: { teamId?: string; leaseSeconds?: number; runId?: string }) => {
|
|
658
659
|
const res = await handleWorkflowsRunnerOnce(api, {
|
|
659
660
|
teamId: String(options.teamId ?? ""),
|
|
660
661
|
leaseSeconds: typeof options.leaseSeconds === "number" ? options.leaseSeconds : undefined,
|
|
662
|
+
runId: options.runId,
|
|
661
663
|
});
|
|
662
664
|
console.log(JSON.stringify(res, null, 2));
|
|
663
665
|
});
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -17,9 +17,10 @@ export async function handleWorkflowsRun(api: OpenClawPluginApi, opts: {
|
|
|
17
17
|
export async function handleWorkflowsRunnerOnce(api: OpenClawPluginApi, opts: {
|
|
18
18
|
teamId: string;
|
|
19
19
|
leaseSeconds?: number;
|
|
20
|
+
runId?: string;
|
|
20
21
|
}) {
|
|
21
22
|
if (!opts.teamId) throw new Error('--team-id is required');
|
|
22
|
-
return runWorkflowRunnerOnce(api, { teamId: opts.teamId, leaseSeconds: opts.leaseSeconds });
|
|
23
|
+
return runWorkflowRunnerOnce(api, { teamId: opts.teamId, leaseSeconds: opts.leaseSeconds, runId: opts.runId });
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
|
|
@@ -124,6 +124,7 @@ export async function enqueueWorkflowRun(api: OpenClawPluginApi, opts: {
|
|
|
124
124
|
export async function runWorkflowRunnerOnce(api: OpenClawPluginApi, opts: {
|
|
125
125
|
teamId: string;
|
|
126
126
|
leaseSeconds?: number;
|
|
127
|
+
runId?: string;
|
|
127
128
|
}) {
|
|
128
129
|
const teamId = String(opts.teamId);
|
|
129
130
|
const teamDir = resolveTeamDir(api, teamId);
|
|
@@ -169,6 +170,14 @@ export async function runWorkflowRunnerOnce(api: OpenClawPluginApi, opts: {
|
|
|
169
170
|
}
|
|
170
171
|
}
|
|
171
172
|
|
|
173
|
+
// If a specific runId was requested, only consider that run.
|
|
174
|
+
const targetRunId = opts.runId?.trim();
|
|
175
|
+
if (targetRunId) {
|
|
176
|
+
const match = candidates.filter((c) => path.basename(path.dirname(c.file)) === targetRunId);
|
|
177
|
+
candidates.length = 0;
|
|
178
|
+
candidates.push(...match);
|
|
179
|
+
}
|
|
180
|
+
|
|
172
181
|
if (!candidates.length) {
|
|
173
182
|
return { ok: true as const, teamId, claimed: 0, message: 'No queued runs available.' };
|
|
174
183
|
}
|
|
@@ -415,6 +415,44 @@ export async function runWorkflowWorkerTick(api: OpenClawPluginApi, opts: {
|
|
|
415
415
|
await fs.writeFile(artifactPath, JSON.stringify({ ok: true, tool: toolName, args: toolArgs, result }, null, 2) + '\n', 'utf8');
|
|
416
416
|
|
|
417
417
|
|
|
418
|
+
} else if (toolName === 'fs.write') {
|
|
419
|
+
const relPathRaw = String(toolArgs.path ?? '').trim();
|
|
420
|
+
const contentRaw = String(toolArgs.content ?? '');
|
|
421
|
+
if (!relPathRaw) throw new Error('fs.write requires args.path');
|
|
422
|
+
|
|
423
|
+
const vars = {
|
|
424
|
+
date: new Date().toISOString(),
|
|
425
|
+
'run.id': runId,
|
|
426
|
+
'run.timestamp': runId,
|
|
427
|
+
'workflow.id': String(workflow.id ?? ''),
|
|
428
|
+
'workflow.name': String(workflow.name ?? workflow.id ?? workflowFile),
|
|
429
|
+
};
|
|
430
|
+
// Also inject node outputs so templates like {{brand_review.output}} resolve
|
|
431
|
+
const { run: runSnap } = await loadRunFile(teamDir, runsDir, task.runId);
|
|
432
|
+
for (const nr of (runSnap.nodeResults ?? [])) {
|
|
433
|
+
const nid = String((nr as Record<string, unknown>).nodeId ?? '');
|
|
434
|
+
const nrOutPath = String((nr as Record<string, unknown>).nodeOutputPath ?? '');
|
|
435
|
+
if (nid && nrOutPath) {
|
|
436
|
+
try {
|
|
437
|
+
const outAbs = path.resolve(teamDir, nrOutPath);
|
|
438
|
+
vars[`${nid}.output`] = await fs.readFile(outAbs, 'utf8');
|
|
439
|
+
} catch { /* node output may not exist */ }
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
const relPath = templateReplace(relPathRaw, vars);
|
|
443
|
+
const content = templateReplace(contentRaw, vars);
|
|
444
|
+
|
|
445
|
+
const abs = path.resolve(teamDir, relPath);
|
|
446
|
+
if (!abs.startsWith(teamDir + path.sep) && abs !== teamDir) {
|
|
447
|
+
throw new Error('fs.write path must be within the team workspace');
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
await ensureDir(path.dirname(abs));
|
|
451
|
+
await fs.writeFile(abs, content, 'utf8');
|
|
452
|
+
|
|
453
|
+
const result = { writtenTo: path.relative(teamDir, abs), bytes: Buffer.byteLength(content, 'utf8') };
|
|
454
|
+
await fs.writeFile(artifactPath, JSON.stringify({ ok: true, tool: toolName, args: toolArgs, result }, null, 2) + '\n', 'utf8');
|
|
455
|
+
|
|
418
456
|
} else if (toolName === 'marketing.post_all') {
|
|
419
457
|
// Disabled by default: do not ship plugins that spawn local processes for posting.
|
|
420
458
|
// Use an approval-gated workflow node that calls a dedicated posting tool/plugin instead.
|