@withone/cli 1.51.0 → 1.52.0
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.
|
@@ -1039,6 +1039,7 @@ var FLOW_SCHEMA = {
|
|
|
1039
1039
|
command: { type: "string", required: true, description: "Shell command to execute (supports selectors)" },
|
|
1040
1040
|
timeout: { type: "number", required: false, description: "Timeout in ms (default: 30000)" },
|
|
1041
1041
|
parseJson: { type: "boolean", required: false, description: "Parse stdout as JSON (default: false). When true, $.steps.<id>.output is the parsed object/array; when false, it is the trimmed stdout string." },
|
|
1042
|
+
parseEnvelope: { type: "boolean", required: false, description: "Unwrap a `claude --print --output-format json` envelope: extract .result, strip code fences + preamble, parse the inner JSON as $.steps.<id>.output. Use this (instead of parseJson) for claude --print steps. Fails the step if the unwrapped payload isn't valid JSON." },
|
|
1042
1043
|
cwd: { type: "string", required: false, description: "Working directory (supports selectors)" },
|
|
1043
1044
|
env: { type: "object", required: false, description: "Additional environment variables" }
|
|
1044
1045
|
},
|
|
@@ -1049,7 +1050,7 @@ var FLOW_SCHEMA = {
|
|
|
1049
1050
|
bash: {
|
|
1050
1051
|
command: "cat /tmp/data.json | claude --print 'Analyze this data' --output-format json",
|
|
1051
1052
|
timeout: 18e4,
|
|
1052
|
-
|
|
1053
|
+
parseEnvelope: true
|
|
1053
1054
|
}
|
|
1054
1055
|
}
|
|
1055
1056
|
}
|
|
@@ -1986,6 +1987,40 @@ function stripCodeFences(text) {
|
|
|
1986
1987
|
const match = trimmed.match(/^```(?:\w*)\s*\n([\s\S]*?)\n\s*```\s*$/);
|
|
1987
1988
|
return match ? match[1].trim() : trimmed;
|
|
1988
1989
|
}
|
|
1990
|
+
function stripToJson(text) {
|
|
1991
|
+
const s = stripCodeFences(text);
|
|
1992
|
+
const candidates = [s.indexOf("{"), s.indexOf("[")].filter((i) => i >= 0);
|
|
1993
|
+
if (candidates.length === 0) return s;
|
|
1994
|
+
const start = Math.min(...candidates);
|
|
1995
|
+
const end = Math.max(s.lastIndexOf("}"), s.lastIndexOf("]"));
|
|
1996
|
+
return end > start ? s.slice(start, end + 1) : s;
|
|
1997
|
+
}
|
|
1998
|
+
function unwrapClaudeEnvelope(stdout, stepId) {
|
|
1999
|
+
const trimmed = stdout.trim();
|
|
2000
|
+
let envelope;
|
|
2001
|
+
try {
|
|
2002
|
+
envelope = JSON.parse(trimmed);
|
|
2003
|
+
} catch {
|
|
2004
|
+
envelope = trimmed;
|
|
2005
|
+
}
|
|
2006
|
+
let resultText;
|
|
2007
|
+
if (envelope && typeof envelope === "object" && !Array.isArray(envelope) && envelope.type === "result" && typeof envelope.result === "string") {
|
|
2008
|
+
resultText = envelope.result;
|
|
2009
|
+
} else if (typeof envelope === "string") {
|
|
2010
|
+
resultText = envelope;
|
|
2011
|
+
} else {
|
|
2012
|
+
return envelope;
|
|
2013
|
+
}
|
|
2014
|
+
const payload = stripToJson(resultText);
|
|
2015
|
+
try {
|
|
2016
|
+
return JSON.parse(payload);
|
|
2017
|
+
} catch (err) {
|
|
2018
|
+
const snippet = payload.length > 200 ? `${payload.slice(0, 200)}\u2026` : payload;
|
|
2019
|
+
throw new Error(
|
|
2020
|
+
`Bash step "${stepId}" parseEnvelope: claude output was not valid JSON after unwrapping (${err instanceof Error ? err.message : String(err)}). Got: ${snippet}`
|
|
2021
|
+
);
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
1989
2024
|
async function executeActionStep(step, context, api, permissions, allowedActionIds, options) {
|
|
1990
2025
|
const action = step.action;
|
|
1991
2026
|
const platform = resolveValue(action.platform, context);
|
|
@@ -2319,7 +2354,7 @@ async function executeSubflowStep(step, context, api, permissions, allowedAction
|
|
|
2319
2354
|
if (flowStack.includes(resolvedKey)) {
|
|
2320
2355
|
throw new Error(`Circular flow detected: ${[...flowStack, resolvedKey].join(" \u2192 ")}`);
|
|
2321
2356
|
}
|
|
2322
|
-
const { loadFlowWithMeta: loadFlowWithMeta2 } = await import("./flow-runner-
|
|
2357
|
+
const { loadFlowWithMeta: loadFlowWithMeta2 } = await import("./flow-runner-WZIYXW47.js");
|
|
2323
2358
|
const { flow: subFlow, rootDir: subRootDir } = loadFlowWithMeta2(resolvedKey);
|
|
2324
2359
|
const subContext = await executeFlow(
|
|
2325
2360
|
subFlow,
|
|
@@ -2464,7 +2499,7 @@ async function executeBashStep(step, context, options) {
|
|
|
2464
2499
|
env,
|
|
2465
2500
|
maxBuffer: 10 * 1024 * 1024
|
|
2466
2501
|
});
|
|
2467
|
-
const output = config.parseJson ? JSON.parse(stripCodeFences(stdout)) : stdout.trim();
|
|
2502
|
+
const output = config.parseEnvelope ? unwrapClaudeEnvelope(stdout, step.id) : config.parseJson ? JSON.parse(stripCodeFences(stdout)) : stdout.trim();
|
|
2468
2503
|
return {
|
|
2469
2504
|
status: "success",
|
|
2470
2505
|
output,
|
package/dist/index.js
CHANGED
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
validateActionInput,
|
|
33
33
|
walkSteps,
|
|
34
34
|
writeCache
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-K56Z5BTM.js";
|
|
36
36
|
import {
|
|
37
37
|
memSqlCommand
|
|
38
38
|
} from "./chunk-UV4YYDF3.js";
|
|
@@ -9990,7 +9990,7 @@ one --agent flow list # List all workflows
|
|
|
9990
9990
|
- Code steps can reference an external \`.mjs\` module under the flow's \`lib/\` folder (stdin JSON in, stdout JSON out) \u2014 keeps JS out of JSON strings and makes flows shareable
|
|
9991
9991
|
- 12 step types: action, transform, code, condition, loop, parallel, file-read, file-write, while, flow, paginate, bash
|
|
9992
9992
|
- Data wiring via selectors: \`$.input.param\`, \`$.steps.stepId.response\`, \`$.loop.item\`
|
|
9993
|
-
- AI analysis via bash steps: \`claude --print\` with \`
|
|
9993
|
+
- AI analysis via bash steps: \`claude --print --output-format json\` with \`parseEnvelope: true\` (unwraps the CLI envelope + fences + preamble into clean parsed JSON; use instead of \`parseJson\` for claude steps)
|
|
9994
9994
|
- Use \`--allow-bash\` to enable bash steps, \`--mock\` for dry-run with realistic mock responses (uses example data from action schemas)
|
|
9995
9995
|
- Use \`--skip-validation\` to bypass input validation on action steps
|
|
9996
9996
|
- Use \`--output-file <path>\` to stream the full result to a file instead of stdout \u2014 for large results that would otherwise be truncated or hit the JSON string-size limit; stdout (and \`--agent\` output) then carries an \`outputFile\` pointer instead of inline \`steps\`
|
package/package.json
CHANGED
|
@@ -478,10 +478,12 @@ e.g. if sub-flow `enrich-customer` has a step `load` that returns `{ TEAM: "acme
|
|
|
478
478
|
{
|
|
479
479
|
"id": "analyze",
|
|
480
480
|
"type": "bash",
|
|
481
|
-
"bash": { "command": "cat /tmp/data.json | claude --print 'Analyze this' --output-format json", "timeout": 180000, "
|
|
481
|
+
"bash": { "command": "cat /tmp/data.json | claude --print 'Analyze this' --output-format json", "timeout": 180000, "parseEnvelope": true }
|
|
482
482
|
}
|
|
483
483
|
```
|
|
484
484
|
|
|
485
|
+
**Parsing output.** `parseJson: true` parses stdout as JSON (and strips outer code fences). For **`claude --print --output-format json`** steps use **`parseEnvelope: true`** instead — `claude` wraps the model's answer in a CLI envelope `{ "type": "result", "result": "```json\n{...}\n```" }`, and `parseEnvelope` unwraps `.result`, strips the inner code fences, drops any preamble/trailer text, and parses the inner JSON as `$.steps.<id>.output`. If the unwrapped payload isn't valid JSON the step fails (no silently-broken data). No more hand-rolled `unwrap()` helpers in code steps.
|
|
486
|
+
|
|
485
487
|
**Safe interpolation.** Plain `{{$.input.x}}` does string substitution and is **unsafe** for bash — values containing quotes, `$`, backticks, `&`, etc. will break the command (or worse). Use the `q` helper to POSIX-shell-quote the value:
|
|
486
488
|
|
|
487
489
|
```json
|
|
@@ -665,8 +667,8 @@ Each substep inside `parallel.steps` must have the full step schema: `id`, `name
|
|
|
665
667
|
|
|
666
668
|
When raw data needs analysis, use this pattern:
|
|
667
669
|
1. `file-write` — save data to temp file (API responses are too large to inline)
|
|
668
|
-
2. `bash` — call `claude --print` to analyze (set timeout to 180000+, use `--output-format json`)
|
|
669
|
-
3. `code` —
|
|
670
|
+
2. `bash` — call `claude --print` to analyze (set timeout to 180000+, use `--output-format json` and `"parseEnvelope": true` so `$.steps.<id>.output` is the clean parsed JSON)
|
|
671
|
+
3. `code` — structure the AI output for downstream steps (no manual envelope unwrap needed — `parseEnvelope` already did it)
|
|
670
672
|
|
|
671
673
|
## CLI Commands
|
|
672
674
|
|