@zapier/zapier-sdk-cli 0.55.6 → 0.55.8

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/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @zapier/zapier-sdk-cli
2
2
 
3
+ ## 0.55.8
4
+
5
+ ### Patch Changes
6
+
7
+ - 2521624: Rename `createWorkflow`'s `is_private` input to `private` to match `runDurable`, keeping `is_private` as a deprecated alias; the wire field stays `is_private`. Clarify the `run-durable` connections param description to show the required object shape.
8
+ - Updated dependencies [2521624]
9
+ - @zapier/zapier-sdk@0.71.1
10
+ - @zapier/zapier-sdk-mcp@0.13.34
11
+
12
+ ## 0.55.7
13
+
14
+ ### Patch Changes
15
+
16
+ - 3474ff3: Add `createConnection` and two lower-level building blocks for connecting an app from code, end to end:
17
+ - `createConnection({ app, browser?, timeoutMs?, pollIntervalMs? })` — high-level: mints a connection URL, prints it (and opens it in a browser when it's safe to do so), waits for the user to finish, and returns the new connection. `browser` is `"auto"` (default — opens locally, skips CI / SSH / headless Linux), `"always"`, or `"never"`. The URL is always printed, so a skipped or failed open falls back to copy/paste.
18
+ - `getConnectionStartUrl({ app })` — low-level: mints a short-lived, signed start URL bound to the current user/account. Returns `{ url, startedAt, expiresAt, app }`.
19
+ - `waitForNewConnection({ app, startedAt, timeoutMs?, pollIntervalMs? })` — low-level: polls until a connection for the app created at or after `startedAt` appears, then returns `{ id, app, title? }`. Throws `ZapierTimeoutError` after `timeoutMs` (default 5 minutes).
20
+
21
+ `createConnection` is the right call for most cases. Reach for the two low-level methods when you want to hand off the URL without blocking (call `getConnectionStartUrl` alone), or do something custom between minting the URL and waiting — email it, post it to Slack, render a QR code — then call `waitForNewConnection`.
22
+
23
+ - 5ca445d: Add private-beta support for streaming auto-mode approval review messages and handling terminal failed approvals through the SDK and CLI. Auto mode is only enabled service-side for approved beta users.
24
+ - Updated dependencies [3474ff3]
25
+ - Updated dependencies [5ca445d]
26
+ - @zapier/zapier-sdk@0.71.0
27
+ - @zapier/zapier-sdk-mcp@0.13.33
28
+
3
29
  ## 0.55.6
4
30
 
5
31
  ### Patch Changes
package/README.md CHANGED
@@ -46,10 +46,13 @@
46
46
  - [`trigger-workflow`](#trigger-workflow--experimental)
47
47
  - [`update-workflow`](#update-workflow--experimental)
48
48
  - [Connections](#connections)
49
+ - [`create-connection`](#create-connection)
49
50
  - [`find-first-connection`](#find-first-connection)
50
51
  - [`find-unique-connection`](#find-unique-connection)
51
52
  - [`get-connection`](#get-connection)
53
+ - [`get-connection-start-url`](#get-connection-start-url)
52
54
  - [`list-connections`](#list-connections)
55
+ - [`wait-for-new-connection`](#wait-for-new-connection)
53
56
  - [HTTP Requests](#http-requests)
54
57
  - [`curl`](#curl)
55
58
  - [Tables](#tables)
@@ -154,27 +157,28 @@ npx zapier-sdk fetch "https://gmail.googleapis.com/gmail/v1/users/me/labels" --c
154
157
 
155
158
  These options are available for all commands:
156
159
 
157
- | Option | Short | Description |
158
- | -------------------------------------- | ----- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
159
- | `--version` | `-V` | Display version number |
160
- | `--help` | `-h` | Display help for command |
161
- | `--credentials <token>` | | Authentication token. |
162
- | `--credentials-client-id <id>` | | OAuth client ID for authentication. |
163
- | `--credentials-client-secret <secret>` | | OAuth client secret for authentication. |
164
- | `--credentials-base-url <url>` | | Override authentication base URL. |
165
- | `--debug` | | Enable debug logging. |
166
- | `--base-url <url>` | | Base URL for Zapier API endpoints. |
167
- | `--tracking-base-url <url>` | | Base URL for Zapier tracking endpoints. |
168
- | `--max-network-retries <count>` | | Max retries for rate-limited requests (default: 3). |
169
- | `--max-network-retry-delay-ms <ms>` | | Max delay in ms to wait for retry (default: 60000). |
170
- | `--max-concurrent-requests <count>` | | Max concurrent in-flight HTTP requests (default: 200, max: 10000). |
171
- | `--approval-timeout-ms <ms>` | | Timeout in ms for approval polling. Default: 600000 (10 min). |
172
- | `--max-approval-retries` | | Maximum number of sequential approval rounds per request (one per gating policy) before giving up. Default: 2. |
173
- | `--approval-mode` | | Approval flow behavior. "poll" creates the approval, opens it in a browser, polls until resolved, and retries the original request. "throw" creates the approval and throws a ZapierApprovalError with the approval URL so the caller can surface it. "disabled" throws a ZapierApprovalError on approval-required responses without creating an approval. Resolution order is: explicit option, then ZAPIER_APPROVAL_MODE, then the default behavior (poll for interactive TTY, throw otherwise). |
174
- | `--can-include-shared-connections` | | Allow listing shared connections. |
175
- | `--can-include-shared-tables` | | Allow listing shared tables. |
176
- | `--can-delete-tables` | | Allow deleting tables. |
177
- | `--json` | | Output raw JSON instead of formatted results |
160
+ | Option | Short | Description |
161
+ | --------------------------------------- | ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
162
+ | `--version` | `-V` | Display version number |
163
+ | `--help` | `-h` | Display help for command |
164
+ | `--credentials <token>` | | Authentication token. |
165
+ | `--credentials-client-id <id>` | | OAuth client ID for authentication. |
166
+ | `--credentials-client-secret <secret>` | | OAuth client secret for authentication. |
167
+ | `--credentials-base-url <url>` | | Override authentication base URL. |
168
+ | `--debug` | | Enable debug logging. |
169
+ | `--base-url <url>` | | Base URL for Zapier API endpoints. |
170
+ | `--tracking-base-url <url>` | | Base URL for Zapier tracking endpoints. |
171
+ | `--max-network-retries <count>` | | Max retries for rate-limited requests (default: 3). |
172
+ | `--max-network-retry-delay-ms <ms>` | | Max delay in ms to wait for retry (default: 60000). |
173
+ | `--max-concurrent-requests <count>` | | Max concurrent in-flight HTTP requests (default: 200, max: 10000). |
174
+ | `--approval-timeout-ms <ms>` | | Timeout in ms for approval polling. Default: 600000 (10 min). |
175
+ | `--max-approval-retries` | | Maximum number of sequential approval rounds per request (one per gating policy) before giving up. Default: 2. |
176
+ | `--approval-mode` | | Approval flow behavior for manual approvals. "poll" creates the approval, opens it in a browser, polls until resolved, and retries the original request. "throw" creates the manual approval and throws a ZapierApprovalError with the approval URL so the caller can surface it. Server-created auto-mode approvals always poll until they reach a terminal status and retry the original request on approval, even when this option is "throw". "disabled" throws a ZapierApprovalError on approval-required responses without creating an approval. Resolution order is: explicit option, then ZAPIER_APPROVAL_MODE, then the default behavior (poll for interactive TTY, throw otherwise). |
177
+ | `--open-auto-mode-approvals-in-browser` | | By default, auto-mode approvals do not open in a browser. Enable this option to open the approval URL and watch the approval process. Resolution order is: explicit option, then ZAPIER_OPEN_AUTO_MODE_APPROVALS_IN_BROWSER, then false. |
178
+ | `--can-include-shared-connections` | | Allow listing shared connections. |
179
+ | `--can-include-shared-tables` | | Allow listing shared tables. |
180
+ | `--can-delete-tables` | | Allow deleting tables. |
181
+ | `--json` | | Output raw JSON instead of formatted results |
178
182
 
179
183
  ## Available Commands
180
184
 
@@ -493,12 +497,12 @@ Create a durable workflow container. Starts disabled with no version; publish a
493
497
  | --------------- | --------- | -------- | ------- | --------------- | ----------------------------------------------------------------------------------------------------- |
494
498
  | `<name>` | `string` | ✅ | — | — | Workflow name |
495
499
  | `--description` | `string` | ❌ | — | — | Optional description for the workflow |
496
- | `--is_private` | `boolean` | ❌ | — | — | If true, only the creating user can see or manage this workflow. Defaults to false (account-visible). |
500
+ | `--private` | `boolean` | ❌ | — | — | If true, only the creating user can see or manage this workflow. Defaults to false (account-visible). |
497
501
 
498
502
  **Usage:**
499
503
 
500
504
  ```bash
501
- npx zapier-sdk create-workflow <name> [--description] [--is_private]
505
+ npx zapier-sdk create-workflow <name> [--description] [--private]
502
506
  ```
503
507
 
504
508
  #### `delete-workflow` 🧪 _experimental_
@@ -738,16 +742,16 @@ Run a workflow source file as a run-once durable run on sdkdurableapi (no deploy
738
742
 
739
743
  **Options:**
740
744
 
741
- | Option | Type | Required | Default | Possible Values | Description |
742
- | -------------------------- | --------- | -------- | ------- | --------------- | --------------------------------------------------------------------------------------------------------------- |
743
- | `<source_files>` | `object` | ✅ | — | — | Source files keyed by filename → contents |
744
- | `--input` | `unknown` | ❌ | — | — | Input data passed to the run |
745
- | `--dependencies` | `object` | ❌ | — | — | Optional npm package dependencies |
746
- | `--zapier_durable_version` | `string` | ❌ | — | — | Exact semver of @zapier/zapier-durable to use (e.g. "1.2.3"). Defaults to server-configured version if omitted. |
747
- | `--connections` | `object` | ❌ | — | — | Named connection aliases. Maps alias names to Zapier connection IDs. |
748
- | `--app_versions` | `object` | ❌ | — | — | Pinned app versions. Maps app keys (slugs) to implementation names and versions. |
749
- | `--private` | `boolean` | ❌ | — | — | Only the creating user can see the run (default false) |
750
- | `--notifications` | `array` | ❌ | — | — | Webhook subscribers for run lifecycle events. Each entry specifies a URL and the events it subscribes to. |
745
+ | Option | Type | Required | Default | Possible Values | Description |
746
+ | -------------------------- | --------- | -------- | ------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
747
+ | `<source_files>` | `object` | ✅ | — | — | Source files keyed by filename → contents |
748
+ | `--input` | `unknown` | ❌ | — | — | Input data passed to the run |
749
+ | `--dependencies` | `object` | ❌ | — | — | Optional npm package dependencies |
750
+ | `--zapier_durable_version` | `string` | ❌ | — | — | Exact semver of @zapier/zapier-durable to use (e.g. "1.2.3"). Defaults to server-configured version if omitted. |
751
+ | `--connections` | `object` | ❌ | — | — | Named connection aliases. Maps each alias to an object holding its Zapier connection ID, e.g. `{ "slack": { "connection_id": "123" } }`. |
752
+ | `--app_versions` | `object` | ❌ | — | — | Pinned app versions. Maps app keys (slugs) to implementation names and versions. |
753
+ | `--private` | `boolean` | ❌ | — | — | Only the creating user can see the run (default false) |
754
+ | `--notifications` | `array` | ❌ | — | — | Webhook subscribers for run lifecycle events. Each entry specifies a URL and the events it subscribes to. |
751
755
 
752
756
  **Usage:**
753
757
 
@@ -792,6 +796,27 @@ npx zapier-sdk update-workflow <workflow> [--name] [--description]
792
796
 
793
797
  ### Connections
794
798
 
799
+ #### `create-connection`
800
+
801
+ Create a new app connection, end-to-end. Mints the start URL via `get-connection-start-url`, prints it to stderr, opportunistically opens it in a browser when it looks safe to do so (skipping CI / SSH / headless-Linux by default — pass `--browser always` to force, `--browser never` to suppress), then polls via `wait-for-new-connection` until the user completes OAuth and the new connection appears. Returns the connection.
802
+
803
+ This is the right command for most callers. Reach for the lower-level building blocks when you want either of: (a) hand off the URL and _not_ block on completion — call `get-connection-start-url` alone, no `wait-for-new-connection` needed, or (b) do something custom between minting the URL and waiting — call `get-connection-start-url`, do your work (email or DM the URL, render a QR code, etc.), then `wait-for-new-connection`.
804
+
805
+ **Options:**
806
+
807
+ | Option | Type | Required | Default | Possible Values | Description |
808
+ | -------------------- | -------- | -------- | -------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
809
+ | `<app>` | `string` | ✅ | — | — | App slug (e.g., 'github'), implementation name (e.g., 'SlackCLIAPI'), or versioned ID (e.g., 'github@1.2.3') |
810
+ | `--browser` | `string` | ❌ | `"auto"` | `auto`, `always`, `never` | When to auto-open the URL in a browser. `auto` (default) opens in local sessions and skips opening in CI / SSH / headless-Linux. `always` forces the open attempt. `never` skips it. The URL is always printed to stderr regardless — a failed or skipped open degrades gracefully to copy-paste. |
811
+ | `--timeout-ms` | `number` | ❌ | — | — | How long to wait for the user to complete the connection flow before giving up. Default 5 minutes (300_000). |
812
+ | `--poll-interval-ms` | `number` | ❌ | — | — | Delay before the first poll request, in ms. Default 3 seconds (3_000). Subsequent polling cadence is managed by the SDK's polling primitive (backoff with sane defaults). |
813
+
814
+ **Usage:**
815
+
816
+ ```bash
817
+ npx zapier-sdk create-connection <app> [--browser] [--timeout-ms] [--poll-interval-ms]
818
+ ```
819
+
795
820
  #### `find-first-connection`
796
821
 
797
822
  Find the first connection matching the criteria
@@ -852,6 +877,34 @@ Execute getConnection
852
877
  npx zapier-sdk get-connection [--connection]
853
878
  ```
854
879
 
880
+ #### `get-connection-start-url`
881
+
882
+ Mint a short-lived URL that begins an SDK-initiated connection flow. The URL is signed by zapier.com and bound to the current user/account — opening it in a different browser session will fail the binding check. Returns the URL as data so the caller decides what to do with it.
883
+
884
+ Use this directly (rather than the higher-level `create-connection`) when you want either of: (a) hand off the URL and _not_ block waiting for completion — call this alone, skip `wait-for-new-connection` entirely, or (b) do something custom between minting the URL and waiting for the connection — call this, then email or DM the URL, render it as a QR code for mobile sign-in, etc., then call `wait-for-new-connection`. For the common case where you'd just print and poll back-to-back, `create-connection` is one call.
885
+
886
+ Pair with `wait-for-new-connection` to detect completion: pass the `startedAt` returned here straight through (it's the server's mint time, so polling isn't affected by client clock skew). Example (JS):
887
+
888
+ ```ts
889
+ const {
890
+ data: { url, app, startedAt },
891
+ } = await zapier.getConnectionStartUrl({ app: "slack" });
892
+ // hand `url` off — print it, DM it, email it, render a button, whatever
893
+ const { data: conn } = await zapier.waitForNewConnection({ app, startedAt });
894
+ ```
895
+
896
+ **Options:**
897
+
898
+ | Option | Type | Required | Default | Possible Values | Description |
899
+ | ------- | -------- | -------- | ------- | --------------- | ------------------------------------------------------------------------------------------------------------ |
900
+ | `<app>` | `string` | ✅ | — | — | App slug (e.g., 'github'), implementation name (e.g., 'SlackCLIAPI'), or versioned ID (e.g., 'github@1.2.3') |
901
+
902
+ **Usage:**
903
+
904
+ ```bash
905
+ npx zapier-sdk get-connection-start-url <app>
906
+ ```
907
+
855
908
  #### `list-connections`
856
909
 
857
910
  List available connections with optional filtering
@@ -878,6 +931,33 @@ List available connections with optional filtering
878
931
  npx zapier-sdk list-connections [app] [--search] [--title] [--owner] [--connections] [--account] [--include-shared] [--expired] [--page-size] [--max-items] [--cursor]
879
932
  ```
880
933
 
934
+ #### `wait-for-new-connection`
935
+
936
+ Wait for a new connection to appear for the given app. Polls `/api/v0/connections` with server-side `ordering=-date` until the most recent matching row's `date` is at or after the started-at timestamp, then returns it. Pair with `get-connection-start-url` — that mints the URL the user opens, this waits for the resulting connection to land. Errors with a timeout after the configured timeout (default 5 min). Example (JS):
937
+
938
+ ```ts
939
+ const {
940
+ data: { url, app, startedAt },
941
+ } = await zapier.getConnectionStartUrl({ app: "slack" });
942
+ // show `url` to the user via the channel they're reading from
943
+ const { data: conn } = await zapier.waitForNewConnection({ app, startedAt });
944
+ ```
945
+
946
+ **Options:**
947
+
948
+ | Option | Type | Required | Default | Possible Values | Description |
949
+ | -------------------- | -------- | -------- | ------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
950
+ | `<app>` | `string` | ✅ | — | — | App slug (e.g., 'github'), implementation name (e.g., 'SlackCLIAPI'), or versioned ID (e.g., 'github@1.2.3') |
951
+ | `<started-at>` | `number` | ✅ | — | — | Unix timestamp (seconds). Only connections whose `date` is at or after this value count as 'new'. Prefer the `startedAt` returned by `get-connection-start-url` — it's server-stamped, so the comparison isn't thrown off by client clock skew. If you mint the timestamp yourself, capture it _before_ showing the start URL so a fast OAuth completion isn't missed. |
952
+ | `--timeout-ms` | `number` | ❌ | — | — | How long to wait before giving up. Default 5 minutes (300_000). |
953
+ | `--poll-interval-ms` | `number` | ❌ | — | — | Delay before the first poll request, in ms. Default 3 seconds (3_000). Subsequent polling cadence is managed by the SDK's polling primitive (backoff with sane defaults). |
954
+
955
+ **Usage:**
956
+
957
+ ```bash
958
+ npx zapier-sdk wait-for-new-connection <app> <started-at> [--timeout-ms] [--poll-interval-ms]
959
+ ```
960
+
881
961
  ### HTTP Requests
882
962
 
883
963
  #### `curl`
package/dist/cli.cjs CHANGED
@@ -33,6 +33,8 @@ var url = require('url');
33
33
  var experimental = require('@zapier/zapier-sdk/experimental');
34
34
  var packageJsonLib = require('package-json');
35
35
  var semver = require('semver');
36
+ var React = require('react');
37
+ var jsxRuntime = require('react/jsx-runtime');
36
38
 
37
39
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
38
40
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -75,6 +77,7 @@ var isInstalledGlobally__default = /*#__PURE__*/_interopDefault(isInstalledGloba
75
77
  var Handlebars__default = /*#__PURE__*/_interopDefault(Handlebars);
76
78
  var packageJsonLib__default = /*#__PURE__*/_interopDefault(packageJsonLib);
77
79
  var semver__default = /*#__PURE__*/_interopDefault(semver);
80
+ var React__default = /*#__PURE__*/_interopDefault(React);
78
81
 
79
82
  var __defProp = Object.defineProperty;
80
83
  var __export = (target, all) => {
@@ -1573,7 +1576,7 @@ var SHARED_COMMAND_CLI_OPTIONS = [
1573
1576
 
1574
1577
  // package.json
1575
1578
  var package_default = {
1576
- version: "0.55.6"};
1579
+ version: "0.55.8"};
1577
1580
 
1578
1581
  // src/telemetry/builders.ts
1579
1582
  function createCliBaseEvent(context = {}) {
@@ -1629,6 +1632,11 @@ function buildCliCommandExecutedEvent({
1629
1632
  subprocess_count: data.subprocess_count ?? null
1630
1633
  };
1631
1634
  }
1635
+ function getApprovalReason(error) {
1636
+ if (!(error instanceof zapierSdk.ZapierApprovalError)) return void 0;
1637
+ const { reason } = error;
1638
+ return typeof reason === "string" && reason.trim().length > 0 ? reason.trim() : void 0;
1639
+ }
1632
1640
  function formatJsonOutput(data) {
1633
1641
  if (data === void 0) {
1634
1642
  return;
@@ -1769,7 +1777,14 @@ function buildJsonErrors(error) {
1769
1777
  }
1770
1778
  const code = error instanceof zapierSdk.ZapierError ? error.code : "UNKNOWN_ERROR";
1771
1779
  const message = error instanceof Error ? error.message : String(error);
1772
- return [{ code, message }];
1780
+ const reason = getApprovalReason(error);
1781
+ return [
1782
+ {
1783
+ code,
1784
+ message,
1785
+ ...reason ? { reason } : {}
1786
+ }
1787
+ ];
1773
1788
  }
1774
1789
  async function unwrapHttpResponse(response) {
1775
1790
  const text = await response.text().catch(() => "[unable to read body]");
@@ -2410,7 +2425,10 @@ function createCommandConfig(cliCommandName, functionInfo, sdk) {
2410
2425
  const commandObj = args[args.length - 1];
2411
2426
  const options = commandObj.opts();
2412
2427
  const interactiveMode = !options.json;
2413
- const renderer = interactiveMode ? createInteractiveRenderer({ sdk, params: resolvedParams }) : createJsonRenderer();
2428
+ const renderer = interactiveMode ? createInteractiveRenderer({
2429
+ sdk,
2430
+ params: resolvedParams
2431
+ }) : createJsonRenderer();
2414
2432
  try {
2415
2433
  emitDeprecationWarning({
2416
2434
  cliCommandName,
@@ -7237,7 +7255,7 @@ var watchTriggerInboxCliPlugin = zapierSdk.definePlugin(
7237
7255
  // package.json with { type: 'json' }
7238
7256
  var package_default2 = {
7239
7257
  name: "@zapier/zapier-sdk-cli",
7240
- version: "0.55.6"};
7258
+ version: "0.55.8"};
7241
7259
 
7242
7260
  // src/sdk.ts
7243
7261
  zapierSdk.injectCliLogin(login_exports);
@@ -7481,6 +7499,232 @@ async function checkAndNotifyUpdates({
7481
7499
  const versionInfo = await checkForUpdates({ packageName, currentVersion });
7482
7500
  displayUpdateNotification(versionInfo, packageName);
7483
7501
  }
7502
+ var FALLBACK_PANEL_WIDTH = 72;
7503
+ var MIN_PANEL_WIDTH = 36;
7504
+ var MAX_PANEL_WIDTH = 88;
7505
+ var SPINNER_INTERVAL_MS = 80;
7506
+ var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
7507
+ var inkImportPromise;
7508
+ function loadInk() {
7509
+ inkImportPromise ?? (inkImportPromise = import('ink'));
7510
+ return inkImportPromise;
7511
+ }
7512
+ function createInitialState() {
7513
+ return {
7514
+ messages: [],
7515
+ active: false
7516
+ };
7517
+ }
7518
+ function getPanelWidth() {
7519
+ const terminalColumns = process.stderr.columns;
7520
+ if (!terminalColumns) return FALLBACK_PANEL_WIDTH;
7521
+ return Math.min(
7522
+ Math.max(terminalColumns - 4, MIN_PANEL_WIDTH),
7523
+ MAX_PANEL_WIDTH
7524
+ );
7525
+ }
7526
+ function getPayloadString(event, key) {
7527
+ const value = event.payload?.[key];
7528
+ if (typeof value !== "string") return void 0;
7529
+ const trimmed = value.trim();
7530
+ return trimmed.length > 0 ? trimmed : void 0;
7531
+ }
7532
+ function getApprovedVerdict(decision, reason) {
7533
+ if (decision !== "approved") return void 0;
7534
+ return {
7535
+ icon: "\u2713",
7536
+ label: "Approved",
7537
+ color: "green",
7538
+ reason
7539
+ };
7540
+ }
7541
+ function Spinner({ text }) {
7542
+ const [frameIndex, setFrameIndex] = React__default.default.useState(0);
7543
+ const InkText = text;
7544
+ React__default.default.useEffect(() => {
7545
+ const timer = setInterval(() => {
7546
+ setFrameIndex((index) => (index + 1) % SPINNER_FRAMES.length);
7547
+ }, SPINNER_INTERVAL_MS);
7548
+ return () => clearInterval(timer);
7549
+ }, []);
7550
+ return /* @__PURE__ */ jsxRuntime.jsx(InkText, { color: "yellow", children: `${SPINNER_FRAMES[frameIndex]} Checking approval...` });
7551
+ }
7552
+ function ApprovalProgressView({
7553
+ state,
7554
+ box,
7555
+ text
7556
+ }) {
7557
+ if (!state.active) return null;
7558
+ const InkBox = box;
7559
+ const InkText = text;
7560
+ const recentMessages = state.messages.slice(-5);
7561
+ const hasMessages = recentMessages.length > 0;
7562
+ return /* @__PURE__ */ jsxRuntime.jsxs(
7563
+ InkBox,
7564
+ {
7565
+ borderColor: "cyan",
7566
+ borderStyle: "round",
7567
+ flexDirection: "column",
7568
+ paddingX: 1,
7569
+ width: getPanelWidth(),
7570
+ children: [
7571
+ /* @__PURE__ */ jsxRuntime.jsx(InkText, { bold: true, color: "cyan", children: "Approval review" }),
7572
+ /* @__PURE__ */ jsxRuntime.jsxs(InkBox, { flexDirection: "column", marginTop: 1, children: [
7573
+ !state.verdict && /* @__PURE__ */ jsxRuntime.jsx(Spinner, { text }),
7574
+ recentMessages.map((message, index) => /* @__PURE__ */ jsxRuntime.jsxs(InkBox, { flexDirection: "row", children: [
7575
+ /* @__PURE__ */ jsxRuntime.jsx(InkText, { color: "cyan", children: "> " }),
7576
+ /* @__PURE__ */ jsxRuntime.jsx(
7577
+ InkText,
7578
+ {
7579
+ dimColor: Boolean(state.verdict) || index < recentMessages.length - 1,
7580
+ wrap: "wrap",
7581
+ children: message
7582
+ }
7583
+ )
7584
+ ] }, `${index}-${message}`)),
7585
+ state.streamError && /* @__PURE__ */ jsxRuntime.jsxs(
7586
+ InkBox,
7587
+ {
7588
+ flexDirection: "column",
7589
+ marginTop: hasMessages || !state.verdict ? 1 : 0,
7590
+ children: [
7591
+ /* @__PURE__ */ jsxRuntime.jsx(InkText, { bold: true, color: "red", children: "Approval stream error" }),
7592
+ /* @__PURE__ */ jsxRuntime.jsx(InkText, { wrap: "wrap", children: ` ${state.streamError}` })
7593
+ ]
7594
+ }
7595
+ ),
7596
+ state.verdict && /* @__PURE__ */ jsxRuntime.jsxs(
7597
+ InkBox,
7598
+ {
7599
+ flexDirection: "column",
7600
+ marginTop: hasMessages || state.streamError ? 1 : 0,
7601
+ children: [
7602
+ /* @__PURE__ */ jsxRuntime.jsx(InkText, { bold: true, color: state.verdict.color, children: `${state.verdict.icon} ${state.verdict.label}` }),
7603
+ state.verdict.reason && /* @__PURE__ */ jsxRuntime.jsx(InkText, { wrap: "wrap", children: ` ${state.verdict.reason}` })
7604
+ ]
7605
+ }
7606
+ )
7607
+ ] })
7608
+ ]
7609
+ }
7610
+ );
7611
+ }
7612
+ function createApprovalProgressRenderer({
7613
+ enabled,
7614
+ onEvent
7615
+ }) {
7616
+ let instance;
7617
+ let currentState = createInitialState();
7618
+ let renderQueue = Promise.resolve();
7619
+ let renderGeneration = 0;
7620
+ let renderEnabled = enabled;
7621
+ let renderErrorReported = false;
7622
+ function update(nextState, { complete = false } = {}) {
7623
+ const generation = renderGeneration;
7624
+ currentState = complete ? createInitialState() : nextState;
7625
+ renderQueue = renderQueue.then(async () => {
7626
+ if (generation !== renderGeneration) return;
7627
+ const { Box, Text, render } = await loadInk();
7628
+ if (generation !== renderGeneration) return;
7629
+ const element = /* @__PURE__ */ jsxRuntime.jsx(ApprovalProgressView, { state: nextState, box: Box, text: Text });
7630
+ if (!instance) {
7631
+ instance = render(element, {
7632
+ stdout: process.stderr,
7633
+ stderr: process.stderr
7634
+ });
7635
+ } else {
7636
+ instance.rerender(element);
7637
+ }
7638
+ if (complete) {
7639
+ instance.unmount();
7640
+ instance = void 0;
7641
+ }
7642
+ }).catch((error) => {
7643
+ if (generation !== renderGeneration) return;
7644
+ renderEnabled = false;
7645
+ currentState = createInitialState();
7646
+ if (renderErrorReported) return;
7647
+ renderErrorReported = true;
7648
+ const message = error instanceof Error ? error.message : String(error);
7649
+ process.stderr.write(`Approval progress unavailable: ${message}
7650
+ `);
7651
+ });
7652
+ }
7653
+ function dismiss() {
7654
+ renderGeneration++;
7655
+ currentState = createInitialState();
7656
+ instance?.unmount();
7657
+ instance = void 0;
7658
+ }
7659
+ return {
7660
+ onEvent(event) {
7661
+ onEvent?.(event);
7662
+ if (!renderEnabled) return;
7663
+ if (event.type === "approval:required") {
7664
+ if (event.payload?.mode !== "auto") return;
7665
+ update({
7666
+ approvalId: getPayloadString(event, "approvalId"),
7667
+ messages: [],
7668
+ active: true
7669
+ });
7670
+ return;
7671
+ }
7672
+ if (event.type === "approval:review_message") {
7673
+ if (!currentState.active) return;
7674
+ const message = getPayloadString(event, "message");
7675
+ if (!message) return;
7676
+ update({
7677
+ ...currentState,
7678
+ messages: [...currentState.messages, message]
7679
+ });
7680
+ return;
7681
+ }
7682
+ if (event.type === "approval:review_decision") {
7683
+ if (!currentState.active) return;
7684
+ const verdict = getApprovedVerdict(
7685
+ event.payload?.decision,
7686
+ getPayloadString(event, "reason")
7687
+ );
7688
+ if (!verdict) return;
7689
+ update(
7690
+ {
7691
+ ...currentState,
7692
+ verdict
7693
+ },
7694
+ { complete: true }
7695
+ );
7696
+ return;
7697
+ }
7698
+ if (event.type === "approval:review_stream_error") {
7699
+ if (!currentState.active) return;
7700
+ update({
7701
+ ...currentState,
7702
+ streamError: getPayloadString(event, "message") ?? "Approval review stream failed"
7703
+ });
7704
+ return;
7705
+ }
7706
+ if (!currentState.active) return;
7707
+ if (event.type === "approval:approved") {
7708
+ update(
7709
+ {
7710
+ ...currentState,
7711
+ verdict: getApprovedVerdict(
7712
+ "approved",
7713
+ getPayloadString(event, "reason")
7714
+ )
7715
+ },
7716
+ { complete: true }
7717
+ );
7718
+ return;
7719
+ }
7720
+ if (event.type === "approval:denied" || event.type === "approval:failed" || event.type === "approval:timeout" || event.type === "approval:error") {
7721
+ dismiss();
7722
+ }
7723
+ }
7724
+ };
7725
+ }
7726
+
7727
+ // src/cli.ts
7484
7728
  var EXIT_GRACE_PERIOD_MS = 500;
7485
7729
  var program = new commander.Command();
7486
7730
  var versionOption = getReservedCliOption("version" /* Version */);
@@ -7516,7 +7760,7 @@ for (const [key, fieldSchema] of Object.entries(
7516
7760
  }
7517
7761
  if (inner instanceof zod.z.ZodBoolean && key !== "debug") {
7518
7762
  const kebab = key.replace(/([A-Z])/g, "-$1").toLowerCase();
7519
- const description = fieldSchema._zod?.def?.description ?? "";
7763
+ const description = fieldSchema.description ?? inner.description ?? "";
7520
7764
  booleanFlags.push({ camelName: key, kebabFlag: `--${kebab}` });
7521
7765
  program.option(`--${kebab}`, description);
7522
7766
  }
@@ -7586,6 +7830,9 @@ for (const { camelName, kebabFlag } of booleanFlags) {
7586
7830
  }
7587
7831
  var useExperimental = process.argv.includes("--experimental") || process.env.ZAPIER_EXPERIMENTAL === "1" || process.env.ZAPIER_EXPERIMENTAL === "true";
7588
7832
  var createZapierCliSdk3 = useExperimental ? createZapierCliSdk2 : createZapierCliSdk;
7833
+ var approvalProgress = createApprovalProgressRenderer({
7834
+ enabled: process.stderr.isTTY === true
7835
+ });
7589
7836
  program.exitOverride();
7590
7837
  (async () => {
7591
7838
  let exitCode = 0;
@@ -7598,6 +7845,7 @@ program.exitOverride();
7598
7845
  maxNetworkRetries,
7599
7846
  maxNetworkRetryDelayMs,
7600
7847
  maxConcurrentRequests,
7848
+ onEvent: approvalProgress.onEvent,
7601
7849
  ...flagOverrides,
7602
7850
  extensions
7603
7851
  });