@jiggai/recipes 0.4.69 → 0.4.71
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
|
@@ -2,34 +2,49 @@ import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
|
2
2
|
import { upsertAgentInConfig, type AgentConfigSnippet } from "./agent-config";
|
|
3
3
|
import { stableStringify } from "./stable-stringify";
|
|
4
4
|
|
|
5
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* Runtime API shape for config access. Mirrors the modern surface
|
|
7
|
+
* (`current` + `replaceConfigFile`) so we don't trigger the
|
|
8
|
+
* `runtime-config-load-write` deprecation warning that the legacy
|
|
9
|
+
* `loadConfig` / `writeConfigFile` helpers emit.
|
|
10
|
+
*/
|
|
6
11
|
interface OpenClawRuntimeConfig {
|
|
7
|
-
|
|
8
|
-
|
|
12
|
+
current?: () => unknown;
|
|
13
|
+
replaceConfigFile?: (params: {
|
|
14
|
+
nextConfig: unknown;
|
|
15
|
+
afterWrite: { mode: "auto" } | { mode: "restart"; reason: string } | { mode: "none"; reason: string };
|
|
16
|
+
}) => Promise<unknown>;
|
|
9
17
|
}
|
|
10
18
|
|
|
11
19
|
/**
|
|
12
20
|
* Load OpenClaw config via runtime API.
|
|
21
|
+
* Returns a deep clone of the runtime snapshot so callers may mutate it
|
|
22
|
+
* before persisting via {@link writeOpenClawConfig}; the runtime's own
|
|
23
|
+
* snapshot from `current()` is `DeepReadonly` and must not be mutated.
|
|
13
24
|
* @param api - OpenClaw plugin API
|
|
14
|
-
* @returns Config object (mutable)
|
|
15
|
-
* @throws If
|
|
25
|
+
* @returns Config object (mutable copy)
|
|
26
|
+
* @throws If the runtime config API is unavailable
|
|
16
27
|
*/
|
|
17
28
|
export async function loadOpenClawConfig(api: OpenClawPluginApi): Promise<Record<string, unknown>> {
|
|
18
29
|
const runtime = api.runtime as { config?: OpenClawRuntimeConfig };
|
|
19
|
-
const
|
|
20
|
-
if (!
|
|
21
|
-
|
|
22
|
-
return cfgObj as Record<string, unknown>;
|
|
30
|
+
const snapshot = runtime.config?.current?.();
|
|
31
|
+
if (!snapshot) throw new Error("Failed to load config via api.runtime.config.current()");
|
|
32
|
+
return JSON.parse(JSON.stringify(snapshot)) as Record<string, unknown>;
|
|
23
33
|
}
|
|
24
34
|
|
|
25
35
|
/**
|
|
26
|
-
*
|
|
36
|
+
* Persist a full OpenClaw config replacement via the runtime API.
|
|
37
|
+
* Uses `afterWrite: { mode: "auto" }` to let the gateway choose between
|
|
38
|
+
* hot-reload and restart, matching the legacy `writeConfigFile` default.
|
|
27
39
|
* @param api - OpenClaw plugin API
|
|
28
40
|
* @param cfgObj - Config object to write
|
|
29
41
|
*/
|
|
30
42
|
export async function writeOpenClawConfig(api: OpenClawPluginApi, cfgObj: Record<string, unknown>): Promise<void> {
|
|
31
43
|
const runtime = api.runtime as { config?: OpenClawRuntimeConfig };
|
|
32
|
-
await runtime.config?.
|
|
44
|
+
await runtime.config?.replaceConfigFile?.({
|
|
45
|
+
nextConfig: cfgObj,
|
|
46
|
+
afterWrite: { mode: "auto" },
|
|
47
|
+
});
|
|
33
48
|
}
|
|
34
49
|
|
|
35
50
|
export type BindingMatch = {
|
|
@@ -305,16 +305,59 @@ 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. Wrap in try/catch + Telegram bot-API
|
|
309
|
+
// fallback because OpenClaw 2026.4.26's gateway has been observed to
|
|
310
|
+
// return "Tool not available: message" from /tools/invoke even though
|
|
311
|
+
// the channel itself is healthy. The approval.json file is durable
|
|
312
|
+
// either way, so we never fail the run on delivery error — operators
|
|
313
|
+
// can still approve via the kitchen UI or `openclaw recipes workflows
|
|
314
|
+
// approve` CLI when this falls through.
|
|
315
|
+
let approvalDelivered = false;
|
|
316
|
+
try {
|
|
317
|
+
await toolsInvoke<ToolTextResult>(api, {
|
|
318
|
+
tool: 'message',
|
|
319
|
+
args: {
|
|
320
|
+
action: 'send',
|
|
321
|
+
channel,
|
|
322
|
+
target,
|
|
323
|
+
...(accountId ? { accountId } : {}),
|
|
324
|
+
message: msg,
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
approvalDelivered = true;
|
|
328
|
+
} catch (err) {
|
|
329
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
330
|
+
console.warn(`[workflow] tools.invoke('message') failed for run ${runId} on node ${node.id}: ${errMsg}`);
|
|
331
|
+
if (channel === 'telegram') {
|
|
332
|
+
try {
|
|
333
|
+
const cfg = await loadOpenClawConfig(api);
|
|
334
|
+
const tgToken = (cfg as { channels?: { telegram?: { botToken?: string } } })
|
|
335
|
+
.channels?.telegram?.botToken;
|
|
336
|
+
if (tgToken) {
|
|
337
|
+
const tgRes = await fetch(`https://api.telegram.org/bot${tgToken}/sendMessage`, {
|
|
338
|
+
method: 'POST',
|
|
339
|
+
headers: { 'content-type': 'application/json' },
|
|
340
|
+
body: JSON.stringify({ chat_id: target, text: msg }),
|
|
341
|
+
});
|
|
342
|
+
if (tgRes.ok) {
|
|
343
|
+
approvalDelivered = true;
|
|
344
|
+
console.log(`[workflow] approval delivered via direct telegram bot API for run ${runId}`);
|
|
345
|
+
} else {
|
|
346
|
+
const tgBody = await tgRes.text().catch(() => '');
|
|
347
|
+
console.error(`[workflow] telegram fallback failed (${tgRes.status}) for run ${runId}: ${tgBody}`);
|
|
348
|
+
}
|
|
349
|
+
} else {
|
|
350
|
+
console.error(`[workflow] telegram fallback skipped for run ${runId}: missing channels.telegram.botToken in openclaw config`);
|
|
351
|
+
}
|
|
352
|
+
} catch (fbErr) {
|
|
353
|
+
const fbMsg = fbErr instanceof Error ? fbErr.message : String(fbErr);
|
|
354
|
+
console.error(`[workflow] telegram fallback threw for run ${runId}: ${fbMsg}`);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
if (!approvalDelivered) {
|
|
358
|
+
console.warn(`[workflow] approval message not delivered for run ${runId}; approve via kitchen UI or CLI`);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
318
361
|
|
|
319
362
|
const waitingTs = new Date().toISOString();
|
|
320
363
|
await appendRunLog(runLogPath, (cur) => ({
|