@zapier/zapier-sdk-cli 0.65.4 → 0.65.7

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,28 @@
1
1
  # @zapier/zapier-sdk-cli
2
2
 
3
+ ## 0.65.7
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [197a125]
8
+ - @zapier/zapier-sdk@0.84.1
9
+ - @zapier/zapier-sdk-mcp@0.18.7
10
+
11
+ ## 0.65.6
12
+
13
+ ### Patch Changes
14
+
15
+ - 4328489: Removed the `react` and `ink` runtime dependencies from the CLI, along with the `@types/react` dev dependency. The approval progress panel is now rendered directly using the terminal libraries already bundled with the CLI, so its appearance and behavior are unchanged while the installed dependency tree is significantly smaller.
16
+
17
+ ## 0.65.5
18
+
19
+ ### Patch Changes
20
+
21
+ - e1896a3: Code Substrate methods now use the `/code-substrate-runner` and `/code-substrate-workflows` API path prefixes across the SDK, the CLI, and the MCP server, and `sdk.context.api` and the CLI `curl` command accept paths built on them. The previous `/sdkdurableapi` and `/durableworkflowzaps` prefixes remain supported.
22
+ - Updated dependencies [e1896a3]
23
+ - @zapier/zapier-sdk@0.84.0
24
+ - @zapier/zapier-sdk-mcp@0.18.6
25
+
3
26
  ## 0.65.4
4
27
 
5
28
  ### Patch Changes
package/README.md CHANGED
@@ -741,7 +741,7 @@ npx zapier-sdk publish-workflow-version <workflow> <source-files> [--dependencie
741
741
 
742
742
  #### `run-durable` 🧪 _experimental_
743
743
 
744
- Run a workflow source file as a run-once durable run on sdkdurableapi (no deployed workflow required). Returns the run ID immediately; poll via getDurableRun for terminal status.
744
+ Run a workflow source file as a run-once durable run on code-substrate-runner (no deployed workflow required). Returns the run ID immediately; poll via getDurableRun for terminal status.
745
745
 
746
746
  **Options:**
747
747
 
package/dist/cli.cjs CHANGED
@@ -9,7 +9,7 @@ var search = require('@inquirer/search');
9
9
  var chalk = require('chalk');
10
10
  var ora = require('ora');
11
11
  var util = require('util');
12
- var wrapAnsi = require('wrap-ansi');
12
+ var wrapAnsi3 = require('wrap-ansi');
13
13
  var jwt = require('jsonwebtoken');
14
14
  var crossKeychain = require('cross-keychain');
15
15
  var Conf = require('conf');
@@ -33,8 +33,7 @@ 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
+ var readline = require('readline');
38
37
 
39
38
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
40
39
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -62,7 +61,7 @@ var search__default = /*#__PURE__*/_interopDefault(search);
62
61
  var chalk__default = /*#__PURE__*/_interopDefault(chalk);
63
62
  var ora__default = /*#__PURE__*/_interopDefault(ora);
64
63
  var util__default = /*#__PURE__*/_interopDefault(util);
65
- var wrapAnsi__default = /*#__PURE__*/_interopDefault(wrapAnsi);
64
+ var wrapAnsi3__default = /*#__PURE__*/_interopDefault(wrapAnsi3);
66
65
  var jwt__namespace = /*#__PURE__*/_interopNamespace(jwt);
67
66
  var Conf__default = /*#__PURE__*/_interopDefault(Conf);
68
67
  var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
@@ -77,7 +76,7 @@ var isInstalledGlobally__default = /*#__PURE__*/_interopDefault(isInstalledGloba
77
76
  var Handlebars__default = /*#__PURE__*/_interopDefault(Handlebars);
78
77
  var packageJsonLib__default = /*#__PURE__*/_interopDefault(packageJsonLib);
79
78
  var semver__default = /*#__PURE__*/_interopDefault(semver);
80
- var React__default = /*#__PURE__*/_interopDefault(React);
79
+ var readline__namespace = /*#__PURE__*/_interopNamespace(readline);
81
80
 
82
81
  var __defProp = Object.defineProperty;
83
82
  var __export = (target, all) => {
@@ -638,25 +637,25 @@ var SchemaParameterResolver = class {
638
637
  name: chalk__default.default.dim("(Try a different search)"),
639
638
  value: TRY_AGAIN_SENTINEL
640
639
  };
641
- const out = [];
640
+ const out2 = [];
642
641
  if (orderedMatches.length === 0) {
643
- out.push(useAsIsChoice);
644
- out.push(tryAgainChoice);
645
- out.push(...skipChoice);
642
+ out2.push(useAsIsChoice);
643
+ out2.push(tryAgainChoice);
644
+ out2.push(...skipChoice);
646
645
  } else {
647
- out.push(...orderedMatches);
648
- out.push(...skipChoice);
649
- out.push(useAsIsChoice);
650
- out.push(tryAgainChoice);
646
+ out2.push(...orderedMatches);
647
+ out2.push(...skipChoice);
648
+ out2.push(useAsIsChoice);
649
+ out2.push(tryAgainChoice);
651
650
  }
652
651
  for (const message2 of capabilityHintMessages) {
653
- out.push({
652
+ out2.push({
654
653
  name: chalk__default.default.dim(message2),
655
654
  value: SKIP_SENTINEL,
656
655
  disabled: true
657
656
  });
658
657
  }
659
- return out;
658
+ return out2;
660
659
  }
661
660
  });
662
661
  if (selected === SKIP_SENTINEL) return void 0;
@@ -838,7 +837,7 @@ var SchemaParameterResolver = class {
838
837
  const matches = trimmed ? dataChoices.filter(
839
838
  (c) => c.name.toLowerCase().includes(lower)
840
839
  ) : dataChoices;
841
- const out = [];
840
+ const out2 = [];
842
841
  const skipChoice = isOptional ? [
843
842
  {
844
843
  name: chalk__default.default.dim("(Skip)"),
@@ -856,24 +855,24 @@ var SchemaParameterResolver = class {
856
855
  value: LOAD_MORE_SENTINEL
857
856
  } : null;
858
857
  if (matchesFirst && orderedMatches.length > 0) {
859
- out.push(...orderedMatches);
860
- out.push(...skipChoice);
861
- out.push(customValueChoice);
862
- if (loadMoreChoice) out.push(loadMoreChoice);
858
+ out2.push(...orderedMatches);
859
+ out2.push(...skipChoice);
860
+ out2.push(customValueChoice);
861
+ if (loadMoreChoice) out2.push(loadMoreChoice);
863
862
  } else if (matchesFirst) {
864
- out.push(customValueChoice);
865
- if (loadMoreChoice) out.push(loadMoreChoice);
866
- out.push(...skipChoice);
863
+ out2.push(customValueChoice);
864
+ if (loadMoreChoice) out2.push(loadMoreChoice);
865
+ out2.push(...skipChoice);
867
866
  } else {
868
- out.push(...skipChoice);
869
- out.push(customValueChoice);
870
- out.push(...orderedMatches);
871
- if (loadMoreChoice) out.push(loadMoreChoice);
867
+ out2.push(...skipChoice);
868
+ out2.push(customValueChoice);
869
+ out2.push(...orderedMatches);
870
+ if (loadMoreChoice) out2.push(loadMoreChoice);
872
871
  }
873
872
  if (capabilityHints.length > 0 && (!trimmed || matches.length > 0)) {
874
- out.push(...capabilityHints);
873
+ out2.push(...capabilityHints);
875
874
  }
876
- return out;
875
+ return out2;
877
876
  }
878
877
  });
879
878
  } else {
@@ -1315,7 +1314,7 @@ Optional fields${pathContext}:`));
1315
1314
  const trimmed = (term ?? "").trim();
1316
1315
  const lower = trimmed.toLowerCase();
1317
1316
  const matches = trimmed ? dataChoices.filter((c) => c.name.toLowerCase().includes(lower)) : dataChoices;
1318
- const out = [];
1317
+ const out2 = [];
1319
1318
  const skipChoice = !fieldMeta.isRequired ? [{ name: chalk__default.default.dim("(Skip)"), value: SKIP_SENTINEL }] : [];
1320
1319
  const customValueChoice = {
1321
1320
  name: chalk__default.default.dim("(Enter custom value)"),
@@ -1326,21 +1325,21 @@ Optional fields${pathContext}:`));
1326
1325
  value: LOAD_MORE_SENTINEL
1327
1326
  } : null;
1328
1327
  if (trimmed && matches.length > 0) {
1329
- out.push(...matches);
1330
- out.push(...skipChoice);
1331
- out.push(customValueChoice);
1332
- if (loadMoreChoice) out.push(loadMoreChoice);
1328
+ out2.push(...matches);
1329
+ out2.push(...skipChoice);
1330
+ out2.push(customValueChoice);
1331
+ if (loadMoreChoice) out2.push(loadMoreChoice);
1333
1332
  } else if (trimmed) {
1334
- out.push(customValueChoice);
1335
- if (loadMoreChoice) out.push(loadMoreChoice);
1336
- out.push(...skipChoice);
1333
+ out2.push(customValueChoice);
1334
+ if (loadMoreChoice) out2.push(loadMoreChoice);
1335
+ out2.push(...skipChoice);
1337
1336
  } else {
1338
- out.push(...skipChoice);
1339
- out.push(customValueChoice);
1340
- out.push(...matches);
1341
- if (loadMoreChoice) out.push(loadMoreChoice);
1337
+ out2.push(...skipChoice);
1338
+ out2.push(customValueChoice);
1339
+ out2.push(...matches);
1340
+ if (loadMoreChoice) out2.push(loadMoreChoice);
1342
1341
  }
1343
- return out;
1342
+ return out2;
1344
1343
  }
1345
1344
  });
1346
1345
  if (selectedValue === SKIP_SENTINEL) {
@@ -1760,7 +1759,7 @@ var SHARED_COMMAND_CLI_OPTIONS = [
1760
1759
 
1761
1760
  // package.json
1762
1761
  var package_default = {
1763
- version: "0.65.4"};
1762
+ version: "0.65.7"};
1764
1763
 
1765
1764
  // src/telemetry/builders.ts
1766
1765
  function createCliBaseEvent(context = {}) {
@@ -1903,7 +1902,7 @@ var DETAIL_INDENT = " ";
1903
1902
  var DETAIL_MAX_LINES = 5;
1904
1903
  function formatDetailText(text, indent = DETAIL_INDENT) {
1905
1904
  const columns = Math.max((process.stdout.columns || 80) - indent.length, 40);
1906
- const wrapped = wrapAnsi__default.default(text, columns, { hard: true, trim: false });
1905
+ const wrapped = wrapAnsi3__default.default(text, columns, { hard: true, trim: false });
1907
1906
  const lines = wrapped.split("\n");
1908
1907
  if (lines.length <= DETAIL_MAX_LINES) {
1909
1908
  return lines.join("\n" + indent);
@@ -6658,27 +6657,27 @@ function formatWriteOut(params) {
6658
6657
  "%{url_effective}": params.urlEffective,
6659
6658
  "%{content_type}": params.contentType ?? ""
6660
6659
  };
6661
- let out = template;
6660
+ let out2 = template;
6662
6661
  for (const [token, value] of Object.entries(replacements)) {
6663
- out = out.split(token).join(value);
6662
+ out2 = out2.split(token).join(value);
6664
6663
  }
6665
- return decodeWriteOutEscapes(out);
6664
+ return decodeWriteOutEscapes(out2);
6666
6665
  }
6667
6666
  function appendQueryParams(url, dataParts) {
6668
- const out = new URL(url.toString());
6667
+ const out2 = new URL(url.toString());
6669
6668
  for (const part of dataParts) {
6670
6669
  const segments = part.split("&");
6671
6670
  for (const seg of segments) {
6672
6671
  if (!seg) continue;
6673
6672
  const idx = seg.indexOf("=");
6674
6673
  if (idx === -1) {
6675
- out.searchParams.append(seg, "");
6674
+ out2.searchParams.append(seg, "");
6676
6675
  } else {
6677
- out.searchParams.append(seg.slice(0, idx), seg.slice(idx + 1));
6676
+ out2.searchParams.append(seg.slice(0, idx), seg.slice(idx + 1));
6678
6677
  }
6679
6678
  }
6680
6679
  }
6681
- return out;
6680
+ return out2;
6682
6681
  }
6683
6682
  async function readAllStdin() {
6684
6683
  const chunks = [];
@@ -8008,7 +8007,7 @@ function renderDeprecationNotices() {
8008
8007
  function buildBoxLines(message) {
8009
8008
  const innerWidth = BOX_WIDTH - 4;
8010
8009
  const pad = (line) => `\u2502 ${line.padEnd(innerWidth)} \u2502`;
8011
- const wrapped = wrapAnsi__default.default(message, innerWidth, { hard: true }).split("\n");
8010
+ const wrapped = wrapAnsi3__default.default(message, innerWidth, { hard: true }).split("\n");
8012
8011
  return [
8013
8012
  `\u256D${"\u2500".repeat(BOX_WIDTH - 2)}\u256E`,
8014
8013
  pad(BOX_TITLE),
@@ -8021,7 +8020,7 @@ function buildBoxLines(message) {
8021
8020
  // package.json with { type: 'json' }
8022
8021
  var package_default2 = {
8023
8022
  name: "@zapier/zapier-sdk-cli",
8024
- version: "0.65.4"};
8023
+ version: "0.65.7"};
8025
8024
 
8026
8025
  // src/sdk.ts
8027
8026
  var warnedDeprecatedMethods = /* @__PURE__ */ new Set();
@@ -8359,16 +8358,63 @@ async function checkAndNotifyUpdates({
8359
8358
  const versionInfo = await checkForUpdates({ packageName, currentVersion });
8360
8359
  displayUpdateNotification(versionInfo, packageName);
8361
8360
  }
8361
+ var EMOJI_PRESENTATION_PATTERN = /\p{Emoji_Presentation}/u;
8362
+ var WIDE_CODE_POINT_RANGES = [
8363
+ [4352, 4447],
8364
+ // Hangul Jamo
8365
+ [11904, 12350],
8366
+ // CJK Radicals ... CJK Symbols and Punctuation
8367
+ [12353, 13311],
8368
+ // Hiragana ... CJK Compatibility
8369
+ [13312, 19903],
8370
+ // CJK Unified Ideographs Extension A
8371
+ [19968, 40959],
8372
+ // CJK Unified Ideographs
8373
+ [40960, 42191],
8374
+ // Yi Syllables, Yi Radicals
8375
+ [44032, 55203],
8376
+ // Hangul Syllables
8377
+ [63744, 64255],
8378
+ // CJK Compatibility Ideographs
8379
+ [65040, 65049],
8380
+ // Vertical Forms
8381
+ [65072, 65131],
8382
+ // CJK Compatibility Forms, Small Form Variants
8383
+ [65281, 65376],
8384
+ // Fullwidth Forms
8385
+ [65504, 65510],
8386
+ // Fullwidth Signs
8387
+ [110592, 110593],
8388
+ // Kana Supplement
8389
+ [131072, 262141]
8390
+ // CJK Unified Ideographs Extension B and beyond
8391
+ ];
8392
+ function isWideCodePoint(codePoint) {
8393
+ return WIDE_CODE_POINT_RANGES.some(
8394
+ ([start, end]) => codePoint >= start && codePoint <= end
8395
+ );
8396
+ }
8397
+ function displayWidth(text) {
8398
+ let width = 0;
8399
+ for (const character of util.stripVTControlCharacters(text)) {
8400
+ const codePoint = character.codePointAt(0);
8401
+ if (codePoint === void 0) continue;
8402
+ width += isWideCodePoint(codePoint) || EMOJI_PRESENTATION_PATTERN.test(character) ? 2 : 1;
8403
+ }
8404
+ return width;
8405
+ }
8406
+
8407
+ // src/utils/approval-progress.ts
8362
8408
  var FALLBACK_PANEL_WIDTH = 72;
8363
8409
  var MIN_PANEL_WIDTH = 36;
8364
8410
  var MAX_PANEL_WIDTH = 88;
8365
8411
  var SPINNER_INTERVAL_MS = 80;
8366
8412
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
8367
- var inkImportPromise;
8368
- function loadInk() {
8369
- inkImportPromise ?? (inkImportPromise = import('ink'));
8370
- return inkImportPromise;
8371
- }
8413
+ var ESC = String.fromCharCode(27);
8414
+ var HIDE_CURSOR = `${ESC}[?25l`;
8415
+ var SHOW_CURSOR = `${ESC}[?25h`;
8416
+ var CURSOR_RESTORE_SIGNALS = ["SIGINT", "SIGTERM"];
8417
+ var out = process.stderr;
8372
8418
  function createInitialState() {
8373
8419
  return {
8374
8420
  messages: [],
@@ -8376,7 +8422,7 @@ function createInitialState() {
8376
8422
  };
8377
8423
  }
8378
8424
  function getPanelWidth() {
8379
- const terminalColumns = process.stderr.columns;
8425
+ const terminalColumns = out.columns;
8380
8426
  if (!terminalColumns) return FALLBACK_PANEL_WIDTH;
8381
8427
  return Math.min(
8382
8428
  Math.max(terminalColumns - 4, MIN_PANEL_WIDTH),
@@ -8398,128 +8444,186 @@ function getApprovedVerdict(decision, reason) {
8398
8444
  reason
8399
8445
  };
8400
8446
  }
8401
- function Spinner({ text }) {
8402
- const [frameIndex, setFrameIndex] = React__default.default.useState(0);
8403
- const InkText = text;
8404
- React__default.default.useEffect(() => {
8405
- const timer = setInterval(() => {
8406
- setFrameIndex((index) => (index + 1) % SPINNER_FRAMES.length);
8407
- }, SPINNER_INTERVAL_MS);
8408
- return () => clearInterval(timer);
8409
- }, []);
8410
- return /* @__PURE__ */ jsxRuntime.jsx(InkText, { color: "yellow", children: `${SPINNER_FRAMES[frameIndex]} Checking approval...` });
8411
- }
8412
- function ApprovalProgressView({
8413
- state,
8414
- box,
8415
- text
8416
- }) {
8417
- if (!state.active) return null;
8418
- const InkBox = box;
8419
- const InkText = text;
8447
+ function buildFrameLines(state, frameIndex) {
8448
+ const width = getPanelWidth();
8449
+ const innerWidth = width - 4;
8450
+ const bodyWidth = width - 2;
8451
+ const bodyTextWidth = innerWidth - 2;
8452
+ const content = [];
8453
+ content.push(chalk__default.default.bold.cyan("Approval review"));
8454
+ content.push("");
8455
+ if (!state.verdict) {
8456
+ content.push(
8457
+ chalk__default.default.yellow(`${SPINNER_FRAMES[frameIndex]} Checking approval...`)
8458
+ );
8459
+ }
8420
8460
  const recentMessages = state.messages.slice(-5);
8421
8461
  const hasMessages = recentMessages.length > 0;
8422
- return /* @__PURE__ */ jsxRuntime.jsxs(
8423
- InkBox,
8424
- {
8425
- borderColor: "cyan",
8426
- borderStyle: "round",
8427
- flexDirection: "column",
8428
- paddingX: 1,
8429
- width: getPanelWidth(),
8430
- children: [
8431
- /* @__PURE__ */ jsxRuntime.jsx(InkText, { bold: true, color: "cyan", children: "Approval review" }),
8432
- /* @__PURE__ */ jsxRuntime.jsxs(InkBox, { flexDirection: "column", marginTop: 1, children: [
8433
- !state.verdict && /* @__PURE__ */ jsxRuntime.jsx(Spinner, { text }),
8434
- recentMessages.map((message, index) => /* @__PURE__ */ jsxRuntime.jsxs(InkBox, { flexDirection: "row", children: [
8435
- /* @__PURE__ */ jsxRuntime.jsx(InkText, { color: "cyan", children: "> " }),
8436
- /* @__PURE__ */ jsxRuntime.jsx(
8437
- InkText,
8438
- {
8439
- dimColor: Boolean(state.verdict) || index < recentMessages.length - 1,
8440
- wrap: "wrap",
8441
- children: message
8442
- }
8443
- )
8444
- ] }, `${index}-${message}`)),
8445
- state.streamError && /* @__PURE__ */ jsxRuntime.jsxs(
8446
- InkBox,
8447
- {
8448
- flexDirection: "column",
8449
- marginTop: hasMessages || !state.verdict ? 1 : 0,
8450
- children: [
8451
- /* @__PURE__ */ jsxRuntime.jsx(InkText, { bold: true, color: "red", children: "Approval stream error" }),
8452
- /* @__PURE__ */ jsxRuntime.jsx(InkText, { wrap: "wrap", children: ` ${state.streamError}` })
8453
- ]
8454
- }
8455
- ),
8456
- state.verdict && /* @__PURE__ */ jsxRuntime.jsxs(
8457
- InkBox,
8458
- {
8459
- flexDirection: "column",
8460
- marginTop: hasMessages || state.streamError ? 1 : 0,
8461
- children: [
8462
- /* @__PURE__ */ jsxRuntime.jsx(InkText, { bold: true, color: state.verdict.color, children: `${state.verdict.icon} ${state.verdict.label}` }),
8463
- state.verdict.reason && /* @__PURE__ */ jsxRuntime.jsx(InkText, { wrap: "wrap", children: ` ${state.verdict.reason}` })
8464
- ]
8465
- }
8466
- )
8467
- ] })
8468
- ]
8462
+ recentMessages.forEach((message, index) => {
8463
+ const dimmed = Boolean(state.verdict) || index < recentMessages.length - 1;
8464
+ const segments = wrapAnsi3__default.default(message, bodyTextWidth, { hard: true }).split(
8465
+ "\n"
8466
+ );
8467
+ segments.forEach((segment, segmentIndex) => {
8468
+ const prefix = segmentIndex === 0 ? chalk__default.default.cyan("> ") : " ";
8469
+ content.push(`${prefix}${dimmed ? chalk__default.default.dim(segment) : segment}`);
8470
+ });
8471
+ });
8472
+ if (state.streamError) {
8473
+ if (hasMessages || !state.verdict) content.push("");
8474
+ content.push(chalk__default.default.bold.red("Approval stream error"));
8475
+ for (const segment of wrapAnsi3__default.default(state.streamError, bodyTextWidth, {
8476
+ hard: true
8477
+ }).split("\n")) {
8478
+ content.push(` ${segment}`);
8479
+ }
8480
+ }
8481
+ if (state.verdict) {
8482
+ if (hasMessages || state.streamError) content.push("");
8483
+ content.push(
8484
+ chalk__default.default.bold.green(`${state.verdict.icon} ${state.verdict.label}`)
8485
+ );
8486
+ if (state.verdict.reason) {
8487
+ for (const segment of wrapAnsi3__default.default(state.verdict.reason, bodyTextWidth, {
8488
+ hard: true
8489
+ }).split("\n")) {
8490
+ content.push(` ${segment}`);
8491
+ }
8469
8492
  }
8470
- );
8493
+ }
8494
+ const pad = (line) => {
8495
+ const padding = " ".repeat(Math.max(0, innerWidth - displayWidth(line)));
8496
+ return `${chalk__default.default.cyan("\u2502")} ${line}${padding} ${chalk__default.default.cyan("\u2502")}`;
8497
+ };
8498
+ return [
8499
+ chalk__default.default.cyan(`\u256D${"\u2500".repeat(bodyWidth)}\u256E`),
8500
+ ...content.map(pad),
8501
+ chalk__default.default.cyan(`\u2570${"\u2500".repeat(bodyWidth)}\u256F`)
8502
+ ];
8471
8503
  }
8472
8504
  function createApprovalProgressRenderer({
8473
8505
  enabled,
8474
8506
  onEvent
8475
8507
  }) {
8476
- let instance;
8477
8508
  let currentState = createInitialState();
8478
- let renderQueue = Promise.resolve();
8479
- let renderGeneration = 0;
8480
8509
  let renderEnabled = enabled;
8510
+ let disposed = false;
8481
8511
  let renderErrorReported = false;
8512
+ let lastFrameLineCount = 0;
8513
+ let spinnerFrameIndex = 0;
8514
+ let spinnerTimer;
8515
+ let cursorHidden = false;
8516
+ let signalHandlers = [];
8517
+ function restoreCursor() {
8518
+ if (cursorHidden) {
8519
+ try {
8520
+ out.write(SHOW_CURSOR);
8521
+ } catch {
8522
+ }
8523
+ cursorHidden = false;
8524
+ }
8525
+ for (const { signal, handler } of signalHandlers) {
8526
+ process.removeListener(signal, handler);
8527
+ }
8528
+ signalHandlers = [];
8529
+ }
8530
+ function ensureCursorHidden() {
8531
+ if (cursorHidden) return;
8532
+ out.write(HIDE_CURSOR);
8533
+ cursorHidden = true;
8534
+ for (const signal of CURSOR_RESTORE_SIGNALS) {
8535
+ const handler = () => {
8536
+ restoreCursor();
8537
+ if (process.listenerCount(signal) === 0) {
8538
+ process.kill(process.pid, signal);
8539
+ }
8540
+ };
8541
+ signalHandlers.push({ signal, handler });
8542
+ process.once(signal, handler);
8543
+ }
8544
+ }
8545
+ function eraseFrame() {
8546
+ if (lastFrameLineCount === 0) return;
8547
+ readline__namespace.moveCursor(out, 0, -lastFrameLineCount);
8548
+ readline__namespace.cursorTo(out, 0);
8549
+ readline__namespace.clearScreenDown(out);
8550
+ lastFrameLineCount = 0;
8551
+ }
8552
+ function paint(lines) {
8553
+ eraseFrame();
8554
+ out.write(`${lines.join("\n")}
8555
+ `);
8556
+ lastFrameLineCount = lines.length;
8557
+ }
8558
+ function renderFrame(state) {
8559
+ paint(buildFrameLines(state, spinnerFrameIndex));
8560
+ }
8561
+ function stopSpinnerTimer() {
8562
+ if (spinnerTimer) {
8563
+ clearInterval(spinnerTimer);
8564
+ spinnerTimer = void 0;
8565
+ }
8566
+ }
8567
+ function disableAfterError(error) {
8568
+ renderEnabled = false;
8569
+ stopSpinnerTimer();
8570
+ restoreCursor();
8571
+ lastFrameLineCount = 0;
8572
+ currentState = createInitialState();
8573
+ if (renderErrorReported) return;
8574
+ renderErrorReported = true;
8575
+ const message = error instanceof Error ? error.message : String(error);
8576
+ try {
8577
+ out.write(`Approval progress unavailable: ${message}
8578
+ `);
8579
+ } catch {
8580
+ }
8581
+ }
8582
+ function ensureSpinnerTimer() {
8583
+ if (spinnerTimer) return;
8584
+ spinnerTimer = setInterval(() => {
8585
+ if (!renderEnabled || !currentState.active || currentState.verdict) {
8586
+ return;
8587
+ }
8588
+ spinnerFrameIndex = (spinnerFrameIndex + 1) % SPINNER_FRAMES.length;
8589
+ try {
8590
+ renderFrame(currentState);
8591
+ } catch (error) {
8592
+ disableAfterError(error);
8593
+ }
8594
+ }, SPINNER_INTERVAL_MS);
8595
+ spinnerTimer.unref?.();
8596
+ }
8482
8597
  function update(nextState, { complete = false } = {}) {
8483
- const generation = renderGeneration;
8484
- currentState = complete ? createInitialState() : nextState;
8485
- renderQueue = renderQueue.then(async () => {
8486
- if (generation !== renderGeneration) return;
8487
- const { Box, Text, render } = await loadInk();
8488
- if (generation !== renderGeneration) return;
8489
- const element = /* @__PURE__ */ jsxRuntime.jsx(ApprovalProgressView, { state: nextState, box: Box, text: Text });
8490
- if (!instance) {
8491
- instance = render(element, {
8492
- stdout: process.stderr,
8493
- stderr: process.stderr
8494
- });
8598
+ try {
8599
+ ensureCursorHidden();
8600
+ renderFrame(nextState);
8601
+ if (complete) {
8602
+ stopSpinnerTimer();
8603
+ restoreCursor();
8604
+ lastFrameLineCount = 0;
8605
+ currentState = createInitialState();
8495
8606
  } else {
8496
- instance.rerender(element);
8607
+ currentState = nextState;
8608
+ ensureSpinnerTimer();
8497
8609
  }
8498
- if (complete) {
8499
- instance.unmount();
8500
- instance = void 0;
8501
- }
8502
- }).catch((error) => {
8503
- if (generation !== renderGeneration) return;
8504
- renderEnabled = false;
8505
- currentState = createInitialState();
8506
- if (renderErrorReported) return;
8507
- renderErrorReported = true;
8508
- const message = error instanceof Error ? error.message : String(error);
8509
- process.stderr.write(`Approval progress unavailable: ${message}
8510
- `);
8511
- });
8610
+ } catch (error) {
8611
+ disableAfterError(error);
8612
+ }
8512
8613
  }
8513
8614
  function dismiss() {
8514
- renderGeneration++;
8615
+ stopSpinnerTimer();
8616
+ try {
8617
+ eraseFrame();
8618
+ } catch {
8619
+ }
8620
+ restoreCursor();
8515
8621
  currentState = createInitialState();
8516
- instance?.unmount();
8517
- instance = void 0;
8518
8622
  }
8519
8623
  return {
8520
8624
  onEvent(event) {
8521
8625
  onEvent?.(event);
8522
- if (!renderEnabled) return;
8626
+ if (disposed || !renderEnabled) return;
8523
8627
  if (event.type === "approval:required") {
8524
8628
  if (event.payload?.mode !== "auto") return;
8525
8629
  update({
@@ -8580,6 +8684,11 @@ function createApprovalProgressRenderer({
8580
8684
  if (event.type === "approval:denied" || event.type === "approval:failed" || event.type === "approval:timeout" || event.type === "approval:error") {
8581
8685
  dismiss();
8582
8686
  }
8687
+ },
8688
+ dispose() {
8689
+ disposed = true;
8690
+ stopSpinnerTimer();
8691
+ restoreCursor();
8583
8692
  }
8584
8693
  };
8585
8694
  }
@@ -8725,6 +8834,8 @@ program.exitOverride();
8725
8834
  console.error("Unexpected error:", error);
8726
8835
  exitCode = 1;
8727
8836
  }
8837
+ } finally {
8838
+ approvalProgress.dispose();
8728
8839
  }
8729
8840
  await versionCheckPromise;
8730
8841
  await zapierSdk.disposeSdk(sdk, { exitCode }).catch(() => {