@withone/cli 1.35.0 → 1.37.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.
package/README.md
CHANGED
|
@@ -255,6 +255,7 @@ one actions execute stripe <actionId> <connectionKey> \
|
|
|
255
255
|
| `--dry-run` | Show the request without executing it |
|
|
256
256
|
| `--mock` | Return example response without making an API call |
|
|
257
257
|
| `--skip-validation` | Skip input validation against the action schema |
|
|
258
|
+
| `--output <path>` | Save response to a file (for binary downloads) |
|
|
258
259
|
|
|
259
260
|
The CLI validates required parameters (path variables, query params, body fields) against the action schema before executing. Missing params return a clear error with the flag name and description. Pass `--skip-validation` to bypass.
|
|
260
261
|
|
|
@@ -11,6 +11,10 @@ import { exec, spawn } from "child_process";
|
|
|
11
11
|
import { promisify } from "util";
|
|
12
12
|
|
|
13
13
|
// src/lib/api.ts
|
|
14
|
+
import { createWriteStream } from "fs";
|
|
15
|
+
import { resolve } from "path";
|
|
16
|
+
import { pipeline } from "stream/promises";
|
|
17
|
+
import { Readable } from "stream";
|
|
14
18
|
var ApiError = class extends Error {
|
|
15
19
|
constructor(status, message, retryAfterSeconds) {
|
|
16
20
|
super(message);
|
|
@@ -328,12 +332,45 @@ var OneApi = class {
|
|
|
328
332
|
const text = await response.text();
|
|
329
333
|
throw new ApiError(response.status, text || `HTTP ${response.status}`);
|
|
330
334
|
}
|
|
335
|
+
const responseContentType = response.headers.get("content-type") || "";
|
|
336
|
+
const isExplicitJson = responseContentType.includes("application/json") || responseContentType.includes("text/");
|
|
337
|
+
if (isExplicitJson || !responseContentType) {
|
|
338
|
+
const responseText2 = await response.text();
|
|
339
|
+
const responseData = responseText2 ? JSON.parse(responseText2) : {};
|
|
340
|
+
return { requestConfig: sanitizedConfig, responseData };
|
|
341
|
+
}
|
|
342
|
+
if (args.output) {
|
|
343
|
+
const outputPath = resolve(args.output);
|
|
344
|
+
const body = response.body;
|
|
345
|
+
if (!body) {
|
|
346
|
+
throw new ApiError(0, "Response body is null \u2014 cannot save to file");
|
|
347
|
+
}
|
|
348
|
+
const nodeReadable = Readable.fromWeb(body);
|
|
349
|
+
await pipeline(nodeReadable, createWriteStream(outputPath));
|
|
350
|
+
const contentLength = response.headers.get("content-length");
|
|
351
|
+
const size = contentLength ? parseInt(contentLength, 10) : void 0;
|
|
352
|
+
return {
|
|
353
|
+
requestConfig: sanitizedConfig,
|
|
354
|
+
responseData: { saved: true, path: outputPath, size, contentType: responseContentType }
|
|
355
|
+
};
|
|
356
|
+
}
|
|
331
357
|
const responseText = await response.text();
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
requestConfig: sanitizedConfig,
|
|
335
|
-
|
|
336
|
-
|
|
358
|
+
try {
|
|
359
|
+
const responseData = responseText ? JSON.parse(responseText) : {};
|
|
360
|
+
return { requestConfig: sanitizedConfig, responseData };
|
|
361
|
+
} catch {
|
|
362
|
+
const contentLength = response.headers.get("content-length");
|
|
363
|
+
const size = contentLength ? parseInt(contentLength, 10) : responseText.length;
|
|
364
|
+
return {
|
|
365
|
+
requestConfig: sanitizedConfig,
|
|
366
|
+
responseData: {
|
|
367
|
+
binary: true,
|
|
368
|
+
size,
|
|
369
|
+
contentType: responseContentType,
|
|
370
|
+
message: "Binary response received. Use --output <path> to save to a file."
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
}
|
|
337
374
|
}
|
|
338
375
|
// Webhook Relay methods
|
|
339
376
|
async createRelayEndpoint(body) {
|
|
@@ -394,7 +431,7 @@ var TimeoutError = class extends Error {
|
|
|
394
431
|
}
|
|
395
432
|
};
|
|
396
433
|
function sleep(ms) {
|
|
397
|
-
return new Promise((
|
|
434
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
398
435
|
}
|
|
399
436
|
function replacePathVariables(path3, variables) {
|
|
400
437
|
if (!path3) return path3;
|
|
@@ -532,7 +569,7 @@ function setByDotPath(obj, dotPath, value) {
|
|
|
532
569
|
// src/lib/flow-engine.ts
|
|
533
570
|
var execAsync = promisify(exec);
|
|
534
571
|
function sleep2(ms) {
|
|
535
|
-
return new Promise((
|
|
572
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
536
573
|
}
|
|
537
574
|
var StepTimeoutError = class extends Error {
|
|
538
575
|
errorCode = "TIMEOUT";
|
|
@@ -843,7 +880,7 @@ async function executeCodeModule(stepId, modulePath, context, options) {
|
|
|
843
880
|
const { env: _omitEnv, ...safeContext } = context;
|
|
844
881
|
void _omitEnv;
|
|
845
882
|
const stdinPayload = JSON.stringify(safeContext);
|
|
846
|
-
return await new Promise((
|
|
883
|
+
return await new Promise((resolve2, reject) => {
|
|
847
884
|
const child = spawn(process.execPath, [absPath], {
|
|
848
885
|
cwd: rootDir,
|
|
849
886
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -862,11 +899,11 @@ async function executeCodeModule(stepId, modulePath, context, options) {
|
|
|
862
899
|
}
|
|
863
900
|
const trimmed = stdout.trim();
|
|
864
901
|
if (trimmed === "") {
|
|
865
|
-
|
|
902
|
+
resolve2(void 0);
|
|
866
903
|
return;
|
|
867
904
|
}
|
|
868
905
|
try {
|
|
869
|
-
|
|
906
|
+
resolve2(JSON.parse(stripCodeFences(trimmed)));
|
|
870
907
|
} catch (err) {
|
|
871
908
|
reject(new Error(`Code module "${modulePath}" did not print valid JSON to stdout: ${err.message}`));
|
|
872
909
|
}
|
|
@@ -1042,7 +1079,7 @@ async function executeSubflowStep(step, context, api, permissions, allowedAction
|
|
|
1042
1079
|
if (flowStack.includes(resolvedKey)) {
|
|
1043
1080
|
throw new Error(`Circular flow detected: ${[...flowStack, resolvedKey].join(" \u2192 ")}`);
|
|
1044
1081
|
}
|
|
1045
|
-
const { loadFlowWithMeta: loadFlowWithMeta2 } = await import("./flow-runner-
|
|
1082
|
+
const { loadFlowWithMeta: loadFlowWithMeta2 } = await import("./flow-runner-OVOGDXNR.js");
|
|
1046
1083
|
const { flow: subFlow, rootDir: subRootDir } = loadFlowWithMeta2(resolvedKey);
|
|
1047
1084
|
const subContext = await executeFlow(
|
|
1048
1085
|
subFlow,
|
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
resolveFlowPath,
|
|
20
20
|
saveFlow,
|
|
21
21
|
validateActionInput
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-MNJJE4PJ.js";
|
|
23
23
|
|
|
24
24
|
// src/index.ts
|
|
25
25
|
import { createRequire as createRequire2 } from "module";
|
|
@@ -2771,7 +2771,8 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
|
|
|
2771
2771
|
headers,
|
|
2772
2772
|
isFormData: options.formData,
|
|
2773
2773
|
isFormUrlEncoded: options.formUrlEncoded,
|
|
2774
|
-
dryRun: options.dryRun
|
|
2774
|
+
dryRun: options.dryRun,
|
|
2775
|
+
output: options.output
|
|
2775
2776
|
},
|
|
2776
2777
|
actionDetails
|
|
2777
2778
|
);
|
|
@@ -4333,6 +4334,7 @@ async function relayCreateCommand(options) {
|
|
|
4333
4334
|
if (options.description) body.description = options.description;
|
|
4334
4335
|
if (options.eventFilters) body.eventFilters = parseJsonArg2(options.eventFilters, "--event-filters");
|
|
4335
4336
|
if (options.tags) body.tags = parseJsonArg2(options.tags, "--tags");
|
|
4337
|
+
if (options.metadata) body.metadata = parseJsonArg2(options.metadata, "--metadata");
|
|
4336
4338
|
if (options.createWebhook) body.createWebhook = true;
|
|
4337
4339
|
const result = await api.createRelayEndpoint(body);
|
|
4338
4340
|
if (isAgentMode()) {
|
|
@@ -4347,6 +4349,10 @@ async function relayCreateCommand(options) {
|
|
|
4347
4349
|
if (result.description) console.log(` ${pc8.dim("Description:")} ${result.description}`);
|
|
4348
4350
|
if (result.eventFilters?.length) console.log(` ${pc8.dim("Events:")} ${result.eventFilters.join(", ")}`);
|
|
4349
4351
|
if (result.webhookPayload?.id) console.log(` ${pc8.dim("Webhook ID:")} ${result.webhookPayload.id}`);
|
|
4352
|
+
if (result.warning) {
|
|
4353
|
+
console.log();
|
|
4354
|
+
console.log(` ${pc8.yellow("\u26A0 Warning:")} ${result.warning}`);
|
|
4355
|
+
}
|
|
4350
4356
|
console.log();
|
|
4351
4357
|
} catch (error2) {
|
|
4352
4358
|
spinner6.stop("Failed to create relay endpoint");
|
|
@@ -8006,6 +8012,7 @@ one --agent actions execute <platform> <actionId> <key> -d '{}' # Execute it
|
|
|
8006
8012
|
- \`--dry-run\` \u2014 Preview request without executing
|
|
8007
8013
|
- \`--mock\` \u2014 Return example response without making an API call (useful for building UI against a response shape)
|
|
8008
8014
|
- \`--skip-validation\` \u2014 Skip input validation against the action schema
|
|
8015
|
+
- \`--output <path>\` \u2014 Save response to a file (for binary downloads like PDFs, images, documents)
|
|
8009
8016
|
|
|
8010
8017
|
The CLI validates required parameters against the action schema before executing. If you're missing a required path variable, query param, or body field, you'll get a clear error listing what's missing and which flag to use. Pass \`--skip-validation\` to bypass.
|
|
8011
8018
|
|
|
@@ -8129,6 +8136,7 @@ one --agent actions execute <platform> <actionId> <connectionKey> [options]
|
|
|
8129
8136
|
- \`--dry-run\` \u2014 Preview without executing
|
|
8130
8137
|
- \`--mock\` \u2014 Return example response without making an API call
|
|
8131
8138
|
- \`--skip-validation\` \u2014 Skip input validation against the action schema
|
|
8139
|
+
- \`--output <path>\` \u2014 Save response to a file (for binary downloads like PDFs, images, documents)
|
|
8132
8140
|
|
|
8133
8141
|
**Do NOT** pass path or query parameters in \`-d\`. Use the correct flags.
|
|
8134
8142
|
|
|
@@ -8198,8 +8206,32 @@ one --agent relay deliveries --endpoint-id <id> # Check delivery status
|
|
|
8198
8206
|
2. **Get event types** \u2014 \`one --agent relay event-types <platform>\`
|
|
8199
8207
|
3. **Get source knowledge** \u2014 understand the incoming webhook payload shape (\`{{payload.*}}\` paths)
|
|
8200
8208
|
4. **Get destination knowledge** \u2014 understand the outgoing API body shape
|
|
8201
|
-
5. **Create endpoint** \u2014 with \`--create-webhook
|
|
8202
|
-
6. **Activate** \u2014 with passthrough action mapping source fields to destination fields
|
|
8209
|
+
5. **Create endpoint** \u2014 with \`--create-webhook\`, \`--event-filters\`, and \`--metadata\` if the source platform requires it
|
|
8210
|
+
6. **Activate** \u2014 with passthrough action mapping source fields to destination fields. **Do NOT pass \`--webhook-secret\`** when the endpoint was created with \`--create-webhook\` \u2014 the correct secret is auto-stored, and supplying a wrong one silently drops every delivery (events arrive, 0 deliveries).
|
|
8211
|
+
|
|
8212
|
+
## Platform-Specific Metadata (\`--metadata\`)
|
|
8213
|
+
|
|
8214
|
+
Some source platforms need extra identifiers to register a webhook. Pass these via \`--metadata '<json>'\` on \`relay create\`. Without them, \`--create-webhook\` silently fails:
|
|
8215
|
+
|
|
8216
|
+
| Platform | Required metadata keys |
|
|
8217
|
+
|---|---|
|
|
8218
|
+
| \`github\` | \`GITHUB_OWNER\`, \`GITHUB_REPOSITORY\` |
|
|
8219
|
+
| \`typeform\` | \`TYPEFORM_FORM_ID\` |
|
|
8220
|
+
| \`stripe\` | (none) |
|
|
8221
|
+
| \`airtable\` | (none) |
|
|
8222
|
+
| \`attio\` | (none) |
|
|
8223
|
+
| \`google-calendar\` | (none) |
|
|
8224
|
+
|
|
8225
|
+
Example (GitHub):
|
|
8226
|
+
|
|
8227
|
+
\`\`\`bash
|
|
8228
|
+
one --agent relay create \\
|
|
8229
|
+
--connection-key "live::github::default::<key>" \\
|
|
8230
|
+
--event-filters '["issues","pull_request"]' \\
|
|
8231
|
+
--metadata '{"GITHUB_OWNER":"my-org","GITHUB_REPOSITORY":"my-repo"}' \\
|
|
8232
|
+
--description "GitHub relay" \\
|
|
8233
|
+
--create-webhook
|
|
8234
|
+
\`\`\`
|
|
8203
8235
|
|
|
8204
8236
|
## Template Context
|
|
8205
8237
|
|
|
@@ -8250,6 +8282,8 @@ Any connected platform can be a destination via passthrough actions.
|
|
|
8250
8282
|
2. \`relay events --platform <p>\` \u2014 check events are arriving
|
|
8251
8283
|
3. \`relay deliveries --event-id <id>\` \u2014 check delivery status and errors
|
|
8252
8284
|
4. \`relay event <id>\` \u2014 inspect full payload to verify template paths
|
|
8285
|
+
|
|
8286
|
+
**If events arrive but 0 deliveries succeed**: you likely passed a wrong \`--webhook-secret\` on \`relay activate\`. When you created the endpoint with \`--create-webhook\`, the secret was registered with the source platform and stored automatically \u2014 do not pass it again on activate. Signature verification will fail silently and every event will be dropped.
|
|
8253
8287
|
`;
|
|
8254
8288
|
var GUIDE_CACHE = `# One Cache \u2014 Reference
|
|
8255
8289
|
|
|
@@ -9369,7 +9403,7 @@ actions.command("search <platform> <query>").description('Search for actions on
|
|
|
9369
9403
|
actions.command("knowledge <platform> <actionId>").alias("k").description("Get full docs for an action \u2014 MUST call before execute to know required params").option("--no-cache", "Skip cache, fetch fresh from API").option("--cache-status", "Print cache metadata without fetching").action(async (platform, actionId, options) => {
|
|
9370
9404
|
await actionsKnowledgeCommand(platform, actionId, options);
|
|
9371
9405
|
});
|
|
9372
|
-
actions.command("execute [platform] [actionId] [connectionKey]").alias("x").allowUnknownOption(true).allowExcessArguments(true).description("Execute an action (or multiple with --parallel, separated by --)").option("-d, --data <json>", "Request body as JSON").option("--path-vars <json>", "Path variables as JSON").option("--query-params <json>", "Query parameters as JSON").option("--headers <json>", "Additional headers as JSON").option("--form-data", "Send as multipart/form-data").option("--form-url-encoded", "Send as application/x-www-form-urlencoded").option("--dry-run", "Show request that would be sent without executing").option("--mock", "Return example response without making an API call").option("--skip-validation", "Skip input validation against the action schema").option("--parallel", "Execute multiple actions concurrently (separate actions with --)").option("--max-concurrency <n>", "Max concurrent actions when using --parallel (default: 5)", "5").action(async (platform, actionId, connectionKey, options) => {
|
|
9406
|
+
actions.command("execute [platform] [actionId] [connectionKey]").alias("x").allowUnknownOption(true).allowExcessArguments(true).description("Execute an action (or multiple with --parallel, separated by --)").option("-d, --data <json>", "Request body as JSON").option("--path-vars <json>", "Path variables as JSON").option("--query-params <json>", "Query parameters as JSON").option("--headers <json>", "Additional headers as JSON").option("--form-data", "Send as multipart/form-data").option("--form-url-encoded", "Send as application/x-www-form-urlencoded").option("--dry-run", "Show request that would be sent without executing").option("--mock", "Return example response without making an API call").option("--skip-validation", "Skip input validation against the action schema").option("--output <path>", "Save binary response to a file (for non-JSON responses like file downloads)").option("--parallel", "Execute multiple actions concurrently (separate actions with --)").option("--max-concurrency <n>", "Max concurrent actions when using --parallel (default: 5)", "5").action(async (platform, actionId, connectionKey, options) => {
|
|
9373
9407
|
if (options.parallel) {
|
|
9374
9408
|
await actionsExecuteParallelCommand();
|
|
9375
9409
|
return;
|
|
@@ -9386,7 +9420,8 @@ actions.command("execute [platform] [actionId] [connectionKey]").alias("x").allo
|
|
|
9386
9420
|
formUrlEncoded: options.formUrlEncoded,
|
|
9387
9421
|
dryRun: options.dryRun,
|
|
9388
9422
|
mock: options.mock,
|
|
9389
|
-
skipValidation: options.skipValidation
|
|
9423
|
+
skipValidation: options.skipValidation,
|
|
9424
|
+
output: options.output
|
|
9390
9425
|
});
|
|
9391
9426
|
});
|
|
9392
9427
|
var flow = program.command("flow").alias("f").description("Create, execute, and manage multi-step workflows");
|
|
@@ -9412,7 +9447,7 @@ flow.command("scaffold [template]").description("Generate a workflow scaffold (t
|
|
|
9412
9447
|
await flowScaffoldCommand(template);
|
|
9413
9448
|
});
|
|
9414
9449
|
var relay = program.command("relay").alias("r").description("Receive webhooks from platforms and relay them via passthrough actions");
|
|
9415
|
-
relay.command("create").description("Create a new relay endpoint for a connection").requiredOption("--connection-key <key>", "Connection key for the source platform").option("--description <desc>", "Description of the relay endpoint").option("--event-filters <json>", `JSON array of event types to filter (e.g. '["customer.created"]')`).option("--tags <json>", "JSON array of tags").option("--create-webhook", "Automatically register the webhook with the source platform").action(async (options) => {
|
|
9450
|
+
relay.command("create").description("Create a new relay endpoint for a connection").requiredOption("--connection-key <key>", "Connection key for the source platform").option("--description <desc>", "Description of the relay endpoint").option("--event-filters <json>", `JSON array of event types to filter (e.g. '["customer.created"]')`).option("--tags <json>", "JSON array of tags").option("--metadata <json>", `JSON object of platform-specific metadata required to register the webhook (e.g. GitHub: '{"GITHUB_OWNER":"org","GITHUB_REPOSITORY":"repo"}', Typeform: '{"TYPEFORM_FORM_ID":"abc"}')`).option("--create-webhook", "Automatically register the webhook with the source platform").action(async (options) => {
|
|
9416
9451
|
await relayCreateCommand(options);
|
|
9417
9452
|
});
|
|
9418
9453
|
relay.command("list").alias("ls").description("List all relay endpoints").option("--limit <n>", "Max results per page").option("--page <n>", "Page number").action(async (options) => {
|
package/package.json
CHANGED
package/skills/one/SKILL.md
CHANGED
|
@@ -87,6 +87,7 @@ Options:
|
|
|
87
87
|
- `--dry-run` — Preview the request without executing
|
|
88
88
|
- `--mock` — Return example response without making an API call (useful for building UI)
|
|
89
89
|
- `--skip-validation` — Skip input validation against the action schema
|
|
90
|
+
- `--output <path>` — Save response to a file (for binary downloads like PDFs, images, documents)
|
|
90
91
|
|
|
91
92
|
The CLI validates required parameters before executing. Missing params return a structured error with the flag name, parameter name, and description. Pass `--skip-validation` to bypass.
|
|
92
93
|
|
|
@@ -52,6 +52,25 @@ one --agent relay create \
|
|
|
52
52
|
|
|
53
53
|
Always use `--create-webhook` — it registers the webhook URL with the source platform automatically.
|
|
54
54
|
|
|
55
|
+
**Some source platforms require extra identifiers via `--metadata`:**
|
|
56
|
+
|
|
57
|
+
| Platform | Required metadata keys |
|
|
58
|
+
|---|---|
|
|
59
|
+
| `github` | `GITHUB_OWNER`, `GITHUB_REPOSITORY` |
|
|
60
|
+
| `typeform` | `TYPEFORM_FORM_ID` |
|
|
61
|
+
| `stripe`, `airtable`, `attio`, `google-calendar` | (none) |
|
|
62
|
+
|
|
63
|
+
Without metadata, `--create-webhook` silently fails for these platforms. Example for GitHub:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
one --agent relay create \
|
|
67
|
+
--connection-key "live::github::default::<key>" \
|
|
68
|
+
--event-filters '["issues","pull_request"]' \
|
|
69
|
+
--metadata '{"GITHUB_OWNER":"my-org","GITHUB_REPOSITORY":"my-repo"}' \
|
|
70
|
+
--description "GitHub relay" \
|
|
71
|
+
--create-webhook
|
|
72
|
+
```
|
|
73
|
+
|
|
55
74
|
### Step 6: Activate with a passthrough action
|
|
56
75
|
|
|
57
76
|
```bash
|
|
@@ -66,6 +85,8 @@ one --agent relay activate <relay-id> --actions '[{
|
|
|
66
85
|
}]'
|
|
67
86
|
```
|
|
68
87
|
|
|
88
|
+
**Do NOT pass `--webhook-secret` on activate** when you created the endpoint with `--create-webhook`. The correct secret is registered with the source platform and stored automatically. Supplying a wrong one does not error — events arrive but every delivery is dropped during signature verification (0 deliveries). If you don't have a reason to override the secret, omit the flag.
|
|
89
|
+
|
|
69
90
|
## Template Context
|
|
70
91
|
|
|
71
92
|
| Variable | Description |
|
|
@@ -177,3 +198,5 @@ one --agent relay deliveries --event-id <id>
|
|
|
177
198
|
- Event filters on both the endpoint and individual actions must match
|
|
178
199
|
- Multiple actions can be attached to a single relay endpoint
|
|
179
200
|
- Missing template variables resolve to empty strings — verify `{{payload.*}}` paths against the actual payload
|
|
201
|
+
- GitHub and Typeform relays require `--metadata` on create; without it `--create-webhook` silently fails
|
|
202
|
+
- Never pass `--webhook-secret` on activate when the endpoint was created with `--create-webhook` — the auto-stored secret is correct, and a wrong one causes signature verification to drop every event silently
|