@jiggai/recipes 0.4.70 → 0.4.72
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/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -305,16 +305,28 @@ export async function executeWorkflowNodes(opts: {
|
|
|
305
305
|
`- openclaw recipes workflows resume --team-id ${teamId} --run-id ${runId}`,
|
|
306
306
|
].join('\n');
|
|
307
307
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
308
|
+
// Deliver the approval prompt via the OpenClaw `message` tool. The tool
|
|
309
|
+
// requires the calling agent to have `group:messaging` (or `message`)
|
|
310
|
+
// in its tools.allow policy — see openclaw/openclaw#74780. If delivery
|
|
311
|
+
// fails (misconfigured policy, channel adapter down, etc.) we log and
|
|
312
|
+
// continue; approval.json is durable, so operators can still approve
|
|
313
|
+
// via the kitchen UI or `openclaw recipes workflows approve` CLI.
|
|
314
|
+
try {
|
|
315
|
+
await toolsInvoke<ToolTextResult>(api, {
|
|
316
|
+
tool: 'message',
|
|
317
|
+
args: {
|
|
318
|
+
action: 'send',
|
|
319
|
+
channel,
|
|
320
|
+
target,
|
|
321
|
+
...(accountId ? { accountId } : {}),
|
|
322
|
+
message: msg,
|
|
323
|
+
},
|
|
324
|
+
});
|
|
325
|
+
} catch (err) {
|
|
326
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
327
|
+
console.warn(`[workflow] tools.invoke('message') failed for run ${runId} on node ${node.id}: ${errMsg}`);
|
|
328
|
+
console.warn(`[workflow] approval message not delivered for run ${runId}; approve via kitchen UI or CLI`);
|
|
329
|
+
}
|
|
318
330
|
|
|
319
331
|
const waitingTs = new Date().toISOString();
|
|
320
332
|
await appendRunLog(runLogPath, (cur) => ({
|
|
@@ -12,7 +12,7 @@ import type { WorkflowLane, WorkflowNode, RunLog } from './workflow-types';
|
|
|
12
12
|
import { dequeueNextTask, enqueueTask, hasPendingTaskFor, releaseTaskClaim, compactQueue } from './workflow-queue';
|
|
13
13
|
import { currentLockOwner, isLockHolderDead } from './lock-liveness';
|
|
14
14
|
import { loadPriorLlmInput, loadProposedPostTextFromPriorNode } from './workflow-node-output-readers';
|
|
15
|
-
import { readTextFile } from './workflow-runner-io';
|
|
15
|
+
import { readTextFile, readJsonFile } from './workflow-runner-io';
|
|
16
16
|
import { resolveApprovalBindingTarget } from './workflow-node-executor';
|
|
17
17
|
import { buildKitchenWorkflowReviewUrl } from './kitchen-review-url';
|
|
18
18
|
import {
|
|
@@ -45,7 +45,7 @@ async function buildMemoryContext(teamDir: string): Promise<string> {
|
|
|
45
45
|
// Read pinned items first (highest priority)
|
|
46
46
|
const pinnedPath = path.join(memoryDir, 'pinned.jsonl');
|
|
47
47
|
if (await fileExists(pinnedPath)) {
|
|
48
|
-
const pinnedContent = await
|
|
48
|
+
const pinnedContent = await readTextFile(pinnedPath);
|
|
49
49
|
const pinnedItems = pinnedContent.trim().split('\n').filter(Boolean);
|
|
50
50
|
|
|
51
51
|
if (pinnedItems.length > 0) {
|
|
@@ -75,7 +75,7 @@ async function buildMemoryContext(teamDir: string): Promise<string> {
|
|
|
75
75
|
if (currentTokens > maxTokens * 0.8) break; // Leave room for recent items
|
|
76
76
|
|
|
77
77
|
const filePath = path.join(memoryDir, filename);
|
|
78
|
-
const content = await
|
|
78
|
+
const content = await readTextFile(filePath);
|
|
79
79
|
const items = content.trim().split('\n').filter(Boolean);
|
|
80
80
|
|
|
81
81
|
if (items.length > 0) {
|
|
@@ -151,7 +151,7 @@ async function buildTemplateVars(
|
|
|
151
151
|
if (nid && nrOutPath) {
|
|
152
152
|
try {
|
|
153
153
|
const outAbs = path.resolve(teamDir, nrOutPath);
|
|
154
|
-
const outputContent = await
|
|
154
|
+
const outputContent = await readTextFile(outAbs);
|
|
155
155
|
vars[`${nid}.output`] = outputContent;
|
|
156
156
|
|
|
157
157
|
try {
|
|
@@ -314,7 +314,7 @@ async function checkWaitingHandoffs(api: OpenClawPluginApi, teamId: string, team
|
|
|
314
314
|
const runPath = path.join(runDir, 'run.json');
|
|
315
315
|
let run: RunLog;
|
|
316
316
|
try {
|
|
317
|
-
const raw = await
|
|
317
|
+
const raw = await readTextFile(runPath);
|
|
318
318
|
run = JSON.parse(raw) as RunLog;
|
|
319
319
|
} catch { continue; }
|
|
320
320
|
|
|
@@ -335,7 +335,7 @@ async function checkWaitingHandoffs(api: OpenClawPluginApi, teamId: string, team
|
|
|
335
335
|
nodeOutputRel: string;
|
|
336
336
|
};
|
|
337
337
|
try {
|
|
338
|
-
marker =
|
|
338
|
+
marker = await readJsonFile<typeof marker>(waitPath);
|
|
339
339
|
} catch { continue; }
|
|
340
340
|
|
|
341
341
|
// Check timeout
|
|
@@ -416,7 +416,7 @@ async function checkWaitingHandoffs(api: OpenClawPluginApi, teamId: string, team
|
|
|
416
416
|
const workflowsDir = path.join(teamDir, 'shared-context', 'workflows');
|
|
417
417
|
let workflow;
|
|
418
418
|
try {
|
|
419
|
-
const wfRaw = await
|
|
419
|
+
const wfRaw = await readTextFile(path.join(workflowsDir, run.workflow.file));
|
|
420
420
|
workflow = normalizeWorkflow(JSON.parse(wfRaw));
|
|
421
421
|
} catch { workflow = null; }
|
|
422
422
|
|
|
@@ -1505,7 +1505,7 @@ export async function runWorkflowWorkerTick(api: OpenClawPluginApi, opts: {
|
|
|
1505
1505
|
if (!wf.endsWith('.json')) continue;
|
|
1506
1506
|
try {
|
|
1507
1507
|
const wfPath = path.join(targetWorkflowsDir, wf);
|
|
1508
|
-
const wfRaw = await
|
|
1508
|
+
const wfRaw = await readTextFile(wfPath);
|
|
1509
1509
|
const wfParsed = JSON.parse(wfRaw);
|
|
1510
1510
|
if (String(wfParsed.id ?? '') === targetWorkflowId || String(wfParsed.name ?? '') === targetWorkflowId) {
|
|
1511
1511
|
targetWorkflowFile = wf;
|