@jiggai/recipes 0.4.62 → 0.4.64

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.
@@ -2,7 +2,7 @@
2
2
  "id": "recipes",
3
3
  "name": "Recipes",
4
4
  "description": "Markdown recipes that scaffold agents and teams (workspace-local).",
5
- "version": "0.4.62",
5
+ "version": "0.4.64",
6
6
  "configSchema": {
7
7
  "type": "object",
8
8
  "additionalProperties": false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jiggai/recipes",
3
- "version": "0.4.62",
3
+ "version": "0.4.64",
4
4
  "description": "ClawRecipes plugin for OpenClaw (markdown recipes -> scaffold agents/teams)",
5
5
  "main": "index.ts",
6
6
  "type": "commonjs",
@@ -1112,6 +1112,10 @@ export async function runWorkflowWorkerTick(api: OpenClawPluginApi, opts: {
1112
1112
  const artifactsDir = path.join(runDir, 'artifacts');
1113
1113
  await ensureDir(artifactsDir);
1114
1114
  const artifactPath = path.join(artifactsDir, `${String(nodeIdx).padStart(3, '0')}-${node.id}.tool.json`);
1115
+ // Captures the "human-readable output" each tool produced so the post-
1116
+ // branch code can surface it as `.text` in the node-output file for
1117
+ // downstream `{{nodeId.field}}` templating. Each branch sets this.
1118
+ let toolOutputText = '';
1115
1119
  try {
1116
1120
  // Runner-native tools (preferred): do NOT depend on gateway tool exposure.
1117
1121
  if (toolName === 'fs.append') {
@@ -1135,6 +1139,7 @@ export async function runWorkflowWorkerTick(api: OpenClawPluginApi, opts: {
1135
1139
 
1136
1140
  const result = { appendedTo: path.relative(teamDir, abs), bytes: Buffer.byteLength(content, 'utf8') };
1137
1141
  await fs.writeFile(artifactPath, JSON.stringify({ ok: true, tool: toolName, args: toolArgs, result }, null, 2) + '\n', 'utf8');
1142
+ toolOutputText = JSON.stringify(result);
1138
1143
 
1139
1144
  } else if (toolName === 'fs.write') {
1140
1145
  const relPathRaw = String(toolArgs.path ?? '').trim();
@@ -1155,6 +1160,7 @@ export async function runWorkflowWorkerTick(api: OpenClawPluginApi, opts: {
1155
1160
 
1156
1161
  const result = { writtenTo: path.relative(teamDir, abs), bytes: Buffer.byteLength(content, 'utf8') };
1157
1162
  await fs.writeFile(artifactPath, JSON.stringify({ ok: true, tool: toolName, args: toolArgs, result }, null, 2) + '\n', 'utf8');
1163
+ toolOutputText = JSON.stringify(result);
1158
1164
 
1159
1165
  } else {
1160
1166
  const vars = await buildTemplateVars(teamDir, runsDir, runId, workflowFile, workflow);
@@ -1211,6 +1217,18 @@ export async function runWorkflowWorkerTick(api: OpenClawPluginApi, opts: {
1211
1217
  }
1212
1218
 
1213
1219
  await fs.writeFile(artifactPath, JSON.stringify({ ok: true, tool: toolName, args: processedToolArgs, result: toolRes }, null, 2) + '\n', 'utf8');
1220
+
1221
+ // Surface tool output as `.text` so downstream `{{nodeId.field}}`
1222
+ // templating resolves. For `exec`, use stdout (commonly JSON emitted
1223
+ // by a script, which buildTemplateVars parses into per-field vars).
1224
+ // For other tools, use the raw string or stringified object.
1225
+ if (toolName === 'exec' && toolRes && typeof toolRes === 'object' && 'stdout' in (toolRes as Record<string, unknown>)) {
1226
+ toolOutputText = String((toolRes as { stdout?: unknown }).stdout ?? '').trim();
1227
+ } else if (typeof toolRes === 'string') {
1228
+ toolOutputText = toolRes;
1229
+ } else {
1230
+ toolOutputText = JSON.stringify(toolRes, null, 2);
1231
+ }
1214
1232
  }
1215
1233
 
1216
1234
  const defaultNodeOutputRel = path.join('node-outputs', `${String(nodeIdx).padStart(3, '0')}-${node.id}.json`);
@@ -1224,6 +1242,7 @@ export async function runWorkflowWorkerTick(api: OpenClawPluginApi, opts: {
1224
1242
  kind: node.kind,
1225
1243
  completedAt: new Date().toISOString(),
1226
1244
  tool: toolName,
1245
+ text: toolOutputText,
1227
1246
  artifactPath: path.relative(teamDir, artifactPath),
1228
1247
  }, null, 2) + '\n', 'utf8');
1229
1248
 
@@ -47,7 +47,15 @@ function parseToolsInvokeError(json: ToolsInvokeResponse, status: number): strin
47
47
 
48
48
  async function doSingleToolsInvoke<T>(url: string, token: string, req: ToolsInvokeRequest): Promise<T> {
49
49
  const ac = new AbortController();
50
- const t = setTimeout(() => ac.abort(), TOOLS_INVOKE_TIMEOUT_MS);
50
+ // Honor per-call timeoutMs (e.g. LLM nodes often pass 300000-900000 ms).
51
+ // Add a 30s HTTP/gateway overhead buffer so the LLM has the full node-
52
+ // configured window to produce its response before the fetch aborts.
53
+ // Fall back to the module default when no timeout was passed.
54
+ const argsTimeout = typeof (req.args as Record<string, unknown> | undefined)?.['timeoutMs'] === 'number'
55
+ ? (req.args as { timeoutMs: number }).timeoutMs
56
+ : 0;
57
+ const fetchTimeoutMs = argsTimeout > 0 ? argsTimeout + 30_000 : TOOLS_INVOKE_TIMEOUT_MS;
58
+ const t = setTimeout(() => ac.abort(), fetchTimeoutMs);
51
59
  const res = await fetch(url, {
52
60
  method: "POST",
53
61
  signal: ac.signal,