@zapier/zapier-sdk 0.70.4 → 0.71.1

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.
Files changed (81) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +149 -31
  3. package/dist/api/approval-review-stream.d.ts +25 -0
  4. package/dist/api/approval-review-stream.d.ts.map +1 -0
  5. package/dist/api/approval-review-stream.js +104 -0
  6. package/dist/api/client.d.ts.map +1 -1
  7. package/dist/api/client.js +215 -27
  8. package/dist/api/types.d.ts +13 -3
  9. package/dist/api/types.d.ts.map +1 -1
  10. package/dist/constants.d.ts +1 -0
  11. package/dist/constants.d.ts.map +1 -1
  12. package/dist/constants.js +6 -0
  13. package/dist/experimental.cjs +602 -37
  14. package/dist/experimental.d.mts +88 -2
  15. package/dist/experimental.d.ts +90 -4
  16. package/dist/experimental.d.ts.map +1 -1
  17. package/dist/experimental.js +10 -0
  18. package/dist/experimental.mjs +602 -38
  19. package/dist/{index-BNaiNmM-.d.mts → index-B43uST61.d.mts} +181 -12
  20. package/dist/{index-BNaiNmM-.d.ts → index-B43uST61.d.ts} +181 -12
  21. package/dist/index.cjs +592 -32
  22. package/dist/index.d.mts +1 -1
  23. package/dist/index.mjs +592 -33
  24. package/dist/plugins/api/index.d.ts.map +1 -1
  25. package/dist/plugins/api/index.js +2 -1
  26. package/dist/plugins/codeSubstrate/createWorkflow/index.d.ts +1 -0
  27. package/dist/plugins/codeSubstrate/createWorkflow/index.d.ts.map +1 -1
  28. package/dist/plugins/codeSubstrate/createWorkflow/index.js +3 -2
  29. package/dist/plugins/codeSubstrate/createWorkflow/schemas.d.ts +1 -0
  30. package/dist/plugins/codeSubstrate/createWorkflow/schemas.d.ts.map +1 -1
  31. package/dist/plugins/codeSubstrate/createWorkflow/schemas.js +7 -1
  32. package/dist/plugins/codeSubstrate/deleteWorkflow/index.d.ts +1 -1
  33. package/dist/plugins/codeSubstrate/disableWorkflow/index.d.ts +1 -1
  34. package/dist/plugins/codeSubstrate/enableWorkflow/index.d.ts +1 -1
  35. package/dist/plugins/codeSubstrate/getDurableRun/schemas.d.ts +4 -4
  36. package/dist/plugins/codeSubstrate/getWorkflow/index.d.ts +2 -2
  37. package/dist/plugins/codeSubstrate/getWorkflow/schemas.d.ts +1 -1
  38. package/dist/plugins/codeSubstrate/getWorkflowRun/index.d.ts +1 -1
  39. package/dist/plugins/codeSubstrate/getWorkflowVersion/index.d.ts +1 -1
  40. package/dist/plugins/codeSubstrate/listWorkflowRuns/index.d.ts +1 -1
  41. package/dist/plugins/codeSubstrate/listWorkflowVersions/index.d.ts +1 -1
  42. package/dist/plugins/codeSubstrate/listWorkflows/index.d.ts +1 -1
  43. package/dist/plugins/codeSubstrate/listWorkflows/schemas.d.ts +2 -2
  44. package/dist/plugins/codeSubstrate/publishWorkflowVersion/index.d.ts +1 -1
  45. package/dist/plugins/codeSubstrate/runDurable/schemas.js +1 -1
  46. package/dist/plugins/codeSubstrate/shared-schemas.d.ts +2 -2
  47. package/dist/plugins/codeSubstrate/triggerWorkflow/index.d.ts +1 -1
  48. package/dist/plugins/codeSubstrate/updateWorkflow/index.d.ts +1 -1
  49. package/dist/plugins/createConnection/index.d.ts +189 -0
  50. package/dist/plugins/createConnection/index.d.ts.map +1 -0
  51. package/dist/plugins/createConnection/index.js +71 -0
  52. package/dist/plugins/createConnection/schemas.d.ts +21 -0
  53. package/dist/plugins/createConnection/schemas.d.ts.map +1 -0
  54. package/dist/plugins/createConnection/schemas.js +38 -0
  55. package/dist/plugins/getConnectionStartUrl/index.d.ts +206 -0
  56. package/dist/plugins/getConnectionStartUrl/index.d.ts.map +1 -0
  57. package/dist/plugins/getConnectionStartUrl/index.js +39 -0
  58. package/dist/plugins/getConnectionStartUrl/schemas.d.ts +15 -0
  59. package/dist/plugins/getConnectionStartUrl/schemas.d.ts.map +1 -0
  60. package/dist/plugins/getConnectionStartUrl/schemas.js +23 -0
  61. package/dist/plugins/waitForNewConnection/index.d.ts +209 -0
  62. package/dist/plugins/waitForNewConnection/index.d.ts.map +1 -0
  63. package/dist/plugins/waitForNewConnection/index.js +75 -0
  64. package/dist/plugins/waitForNewConnection/schemas.d.ts +17 -0
  65. package/dist/plugins/waitForNewConnection/schemas.d.ts.map +1 -0
  66. package/dist/plugins/waitForNewConnection/schemas.js +39 -0
  67. package/dist/sdk.d.ts +126 -0
  68. package/dist/sdk.d.ts.map +1 -1
  69. package/dist/sdk.js +8 -0
  70. package/dist/types/errors.d.ts +13 -4
  71. package/dist/types/errors.d.ts.map +1 -1
  72. package/dist/types/errors.js +2 -0
  73. package/dist/types/sdk.d.ts +1 -0
  74. package/dist/types/sdk.d.ts.map +1 -1
  75. package/dist/types/sdk.js +5 -1
  76. package/dist/utils/open-url.d.ts.map +1 -1
  77. package/dist/utils/open-url.js +7 -0
  78. package/dist/utils/should-open-browser.d.ts +24 -0
  79. package/dist/utils/should-open-browser.d.ts.map +1 -0
  80. package/dist/utils/should-open-browser.js +55 -0
  81. package/package.json +1 -1
@@ -1170,6 +1170,8 @@ var ZapierApprovalError = class extends ZapierError {
1170
1170
  this.approvalStatus = options.status;
1171
1171
  this.approvalUrl = options.approvalUrl;
1172
1172
  this.pollUrl = options.pollUrl;
1173
+ this.streamUrl = options.streamUrl;
1174
+ this.reason = options.reason;
1173
1175
  }
1174
1176
  };
1175
1177
  var ZapierRelayError = class extends ZapierError {
@@ -1312,6 +1314,11 @@ function getZapierApprovalMode() {
1312
1314
  return value;
1313
1315
  return void 0;
1314
1316
  }
1317
+ function getZapierOpenAutoModeApprovalsInBrowser() {
1318
+ const value = globalThis.process?.env?.ZAPIER_OPEN_AUTO_MODE_APPROVALS_IN_BROWSER;
1319
+ if (value === void 0) return void 0;
1320
+ return value === "true";
1321
+ }
1315
1322
  function getZapierDefaultApprovalMode() {
1316
1323
  const isInteractive = !!globalThis.process?.stdin?.isTTY && !!globalThis.process?.stdout?.isTTY;
1317
1324
  return isInteractive ? "poll" : "throw";
@@ -3186,9 +3193,101 @@ function createSseParserStream() {
3186
3193
  }
3187
3194
  });
3188
3195
  }
3196
+ var ApprovalReviewChunkSchema = zod.z.discriminatedUnion("type", [
3197
+ zod.z.object({
3198
+ type: zod.z.literal("text-delta"),
3199
+ delta: zod.z.string()
3200
+ }).passthrough(),
3201
+ zod.z.object({
3202
+ type: zod.z.literal("tool-input-available"),
3203
+ toolCallId: zod.z.string(),
3204
+ toolName: zod.z.string()
3205
+ }).passthrough(),
3206
+ zod.z.object({
3207
+ type: zod.z.literal("tool-output-available"),
3208
+ toolCallId: zod.z.string(),
3209
+ output: zod.z.unknown()
3210
+ }).passthrough()
3211
+ ]);
3212
+ var ReportDecisionOutputSchema = zod.z.object({
3213
+ success: zod.z.boolean().optional(),
3214
+ decision: zod.z.enum(["approved", "denied"]),
3215
+ reason: zod.z.string().optional()
3216
+ }).passthrough();
3217
+ async function consumeApprovalReviewStream({
3218
+ approvalId,
3219
+ streamUrl,
3220
+ signal,
3221
+ stream,
3222
+ emitEvent
3223
+ }) {
3224
+ try {
3225
+ const toolNames = /* @__PURE__ */ new Map();
3226
+ for await (const frame of stream(streamUrl, {
3227
+ method: "GET",
3228
+ headers: {
3229
+ "Accept-Encoding": "identity"
3230
+ },
3231
+ signal
3232
+ })) {
3233
+ if (!frame.parsed) continue;
3234
+ const payload = parseApprovalReviewStreamPayload(frame.data, toolNames);
3235
+ if (!payload) continue;
3236
+ if (payload.kind === "message") {
3237
+ emitEvent("approval:review_message", {
3238
+ approvalId,
3239
+ streamUrl,
3240
+ data: payload.data,
3241
+ message: payload.message
3242
+ });
3243
+ continue;
3244
+ }
3245
+ emitEvent("approval:review_decision", {
3246
+ approvalId,
3247
+ streamUrl,
3248
+ data: payload.data,
3249
+ decision: payload.decision,
3250
+ ...payload.reason ? { reason: payload.reason } : {}
3251
+ });
3252
+ }
3253
+ } catch (err) {
3254
+ if (isAbortError(err) || signal.aborted) return;
3255
+ emitEvent("approval:review_stream_error", {
3256
+ approvalId,
3257
+ streamUrl,
3258
+ message: err instanceof Error ? err.message : String(err)
3259
+ });
3260
+ }
3261
+ }
3262
+ function parseApprovalReviewStreamPayload(parsed, toolNames) {
3263
+ const chunk = ApprovalReviewChunkSchema.safeParse(parsed);
3264
+ if (!chunk.success) return void 0;
3265
+ switch (chunk.data.type) {
3266
+ case "text-delta": {
3267
+ const message = chunk.data.delta.trim();
3268
+ return message.length > 0 ? { kind: "message", data: parsed, message } : void 0;
3269
+ }
3270
+ case "tool-input-available":
3271
+ toolNames.set(chunk.data.toolCallId, chunk.data.toolName);
3272
+ return void 0;
3273
+ case "tool-output-available": {
3274
+ if (toolNames.get(chunk.data.toolCallId) !== "report_decision") {
3275
+ return void 0;
3276
+ }
3277
+ const decision = ReportDecisionOutputSchema.safeParse(chunk.data.output);
3278
+ if (!decision.success) return void 0;
3279
+ return {
3280
+ kind: "decision",
3281
+ data: parsed,
3282
+ decision: decision.data.decision,
3283
+ ...decision.data.reason ? { reason: decision.data.reason } : {}
3284
+ };
3285
+ }
3286
+ }
3287
+ }
3189
3288
 
3190
3289
  // src/sdk-version.ts
3191
- var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.70.4" : void 0) || "unknown";
3290
+ var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.71.1" : void 0) || "unknown";
3192
3291
 
3193
3292
  // src/utils/open-url.ts
3194
3293
  var nodePrefix = "node:";
@@ -3240,6 +3339,9 @@ var openUrl = async (url) => {
3240
3339
  } else if (platform === "win32") {
3241
3340
  command = "rundll32";
3242
3341
  args = ["url.dll,FileProtocolHandler", target];
3342
+ } else if (platform === "linux") {
3343
+ command = "xdg-open";
3344
+ args = [target];
3243
3345
  } else {
3244
3346
  throw new Error(`Unsupported platform: ${platform}`);
3245
3347
  }
@@ -3262,16 +3364,39 @@ async function openApproval(url) {
3262
3364
  } catch {
3263
3365
  }
3264
3366
  }
3265
- var ApprovalStatusSchema = zod.z.enum(["pending_approval", "approved", "denied"]);
3367
+ var ApprovalStatusSchema = zod.z.enum([
3368
+ "pending_approval",
3369
+ "approved",
3370
+ "denied",
3371
+ "failed"
3372
+ ]);
3373
+ var ApprovalModeSchema = zod.z.enum(["manual", "auto"]);
3266
3374
  var CreateApprovalResponseSchema = zod.z.object({
3375
+ id: zod.z.string().optional(),
3267
3376
  status: ApprovalStatusSchema,
3268
- approval_id: zod.z.string(),
3377
+ approval_id: zod.z.string().optional(),
3378
+ mode: ApprovalModeSchema,
3269
3379
  approval_url: zod.z.string().url(),
3270
- poll_url: zod.z.string().url()
3380
+ poll_url: zod.z.string().url(),
3381
+ stream_url: zod.z.string().url().optional(),
3382
+ reason: zod.z.string().optional()
3383
+ }).transform((approval, ctx) => {
3384
+ const id = approval.id ?? approval.approval_id;
3385
+ if (!id) {
3386
+ ctx.addIssue({
3387
+ code: "custom",
3388
+ message: "Approval response must include id"
3389
+ });
3390
+ return zod.z.NEVER;
3391
+ }
3392
+ return { ...approval, id };
3271
3393
  });
3272
3394
  var PollApprovalResponseSchema = zod.z.object({
3395
+ id: zod.z.string().optional(),
3273
3396
  status: ApprovalStatusSchema,
3274
- approval_id: zod.z.string()
3397
+ approval_id: zod.z.string().optional(),
3398
+ mode: ApprovalModeSchema.optional(),
3399
+ reason: zod.z.string().optional()
3275
3400
  });
3276
3401
  var APPROVAL_MAX_POLLING_INTERVAL_MS = 5e3;
3277
3402
  function parseRateLimitHeaders(response) {
@@ -3544,7 +3669,11 @@ var ZapierApiClient = class {
3544
3669
  { statusCode: 403 }
3545
3670
  );
3546
3671
  }
3547
- await this.runOneApprovalRound(init.approvalContext, mode);
3672
+ await this.runOneApprovalRound(
3673
+ init.approvalContext,
3674
+ mode,
3675
+ init.signal ?? void 0
3676
+ );
3548
3677
  }
3549
3678
  throw new ZapierApprovalError(
3550
3679
  `Exceeded maximum approval retries (${maxRetries}) for ${path}`,
@@ -3572,6 +3701,7 @@ var ZapierApiClient = class {
3572
3701
  * any frame), so transport / auth failures surface as usual.
3573
3702
  */
3574
3703
  this.fetchJsonStream = (path, init) => jsonFrames(this.fetchStream(path, init));
3704
+ this.streamTrustedJsonUrl = (url, init) => jsonFrames(this.streamTrustedSseUrl(url, init));
3575
3705
  this.get = async (path, options = {}) => {
3576
3706
  return this.fetchJson("GET", path, void 0, options);
3577
3707
  };
@@ -3911,7 +4041,7 @@ var ZapierApiClient = class {
3911
4041
  // bound `fetchStream` arrow above for parity with the other client methods.
3912
4042
  async *streamSse(path, init) {
3913
4043
  const { onOpen, headers: initHeaders, ...fetchInit } = init ?? {};
3914
- const signal = fetchInit.signal;
4044
+ const signal = fetchInit.signal ?? void 0;
3915
4045
  if (signal?.aborted) return;
3916
4046
  const wasMissingAuthToken = fetchInit.authRequired === true && await this.getAuthToken({
3917
4047
  requiredScopes: fetchInit.requiredScopes
@@ -3929,13 +4059,62 @@ var ZapierApiClient = class {
3929
4059
  if (signal?.aborted || isAbortError(err)) return;
3930
4060
  throw err;
3931
4061
  }
4062
+ yield* this.readSseResponse({
4063
+ response,
4064
+ signal,
4065
+ onOpen,
4066
+ wasMissingAuthToken,
4067
+ requiredScopes: fetchInit.requiredScopes
4068
+ });
4069
+ }
4070
+ // Approval `stream_url` is server-supplied and origin-pinned before use, like
4071
+ // `poll_url`; keep absolute-URL streaming private rather than widening the
4072
+ // public path-based `fetchStream` API.
4073
+ async *streamTrustedSseUrl(url, init) {
4074
+ const { onOpen, headers: initHeaders, ...fetchInit } = init ?? {};
4075
+ const signal = fetchInit.signal ?? void 0;
4076
+ if (signal?.aborted) return;
4077
+ const wasMissingAuthToken = fetchInit.authRequired === true && await this.getAuthToken({
4078
+ requiredScopes: fetchInit.requiredScopes
4079
+ }) == null;
4080
+ const headers = new Headers(initHeaders);
4081
+ if (!headers.has("Accept")) headers.set("Accept", "text/event-stream");
4082
+ let response;
4083
+ try {
4084
+ response = await this.withSemaphore(
4085
+ { url, method: fetchInit.method ?? "GET", signal },
4086
+ () => this.rawFetchUrl(url, {
4087
+ ...fetchInit,
4088
+ method: fetchInit.method ?? "GET",
4089
+ headers
4090
+ })
4091
+ );
4092
+ } catch (err) {
4093
+ if (signal?.aborted || isAbortError(err)) return;
4094
+ throw err;
4095
+ }
4096
+ yield* this.readSseResponse({
4097
+ response,
4098
+ signal,
4099
+ onOpen,
4100
+ wasMissingAuthToken,
4101
+ requiredScopes: fetchInit.requiredScopes
4102
+ });
4103
+ }
4104
+ async *readSseResponse({
4105
+ response,
4106
+ signal,
4107
+ onOpen,
4108
+ wasMissingAuthToken,
4109
+ requiredScopes
4110
+ }) {
3932
4111
  if (!response.ok) {
3933
4112
  const { data } = await this.parseResult(response);
3934
4113
  await this.throwForErrorResponse({
3935
4114
  response,
3936
4115
  responseData: data,
3937
4116
  wasMissingAuthToken,
3938
- requiredScopes: fetchInit.requiredScopes
4117
+ requiredScopes
3939
4118
  });
3940
4119
  }
3941
4120
  if (!response.body) return;
@@ -3961,12 +4140,12 @@ var ZapierApiClient = class {
3961
4140
  /**
3962
4141
  * Run a single approval round: create the approval, open the URL (poll mode)
3963
4142
  * or throw (throw mode), poll until resolved, and emit events. Throws on
3964
- * denied/timeout/unexpected status. Returns on approved.
4143
+ * denied/failed/timeout/unexpected status. Returns on approved.
3965
4144
  *
3966
4145
  * Caller is responsible for passing a non-"disabled" mode; this method
3967
4146
  * unconditionally creates an approval.
3968
4147
  */
3969
- async runOneApprovalRound(buildContext, mode) {
4148
+ async runOneApprovalRound(buildContext, mode, signal) {
3970
4149
  const context = buildContext();
3971
4150
  let approvalResponse;
3972
4151
  try {
@@ -3976,9 +4155,11 @@ var ZapierApiClient = class {
3976
4155
  "Content-Type": "application/json",
3977
4156
  Accept: "application/json"
3978
4157
  },
3979
- body: JSON.stringify({ context })
4158
+ body: JSON.stringify({ context }),
4159
+ signal
3980
4160
  });
3981
4161
  } catch (err) {
4162
+ if (isAbortError(err)) throw err;
3982
4163
  throw new ZapierApiError("Failed to create approval request", {
3983
4164
  statusCode: 0,
3984
4165
  cause: err
@@ -4031,6 +4212,9 @@ var ZapierApiClient = class {
4031
4212
  };
4032
4213
  if (!isLocalhostBaseUrl(this.options.baseUrl)) {
4033
4214
  assertApprovalOrigin(approval.poll_url, sdkapiOrigin, "poll_url");
4215
+ if (approval.stream_url) {
4216
+ assertApprovalOrigin(approval.stream_url, sdkapiOrigin, "stream_url");
4217
+ }
4034
4218
  assertApprovalOrigin(
4035
4219
  approval.approval_url,
4036
4220
  browserOrigin,
@@ -4038,19 +4222,79 @@ var ZapierApiClient = class {
4038
4222
  );
4039
4223
  }
4040
4224
  this.emitEvent("approval:required", {
4041
- approvalId: approval.approval_id,
4042
- approvalUrl: approval.approval_url
4225
+ approvalId: approval.id,
4226
+ approvalUrl: approval.approval_url,
4227
+ mode: approval.mode,
4228
+ ...approval.stream_url ? { streamUrl: approval.stream_url } : {}
4043
4229
  });
4044
- if (mode === "throw") {
4045
- throw new ZapierApprovalError("This request requires approval.", {
4046
- approvalId: approval.approval_id,
4047
- approvalUrl: approval.approval_url,
4048
- pollUrl: approval.poll_url,
4049
- status: "pending"
4050
- });
4230
+ const shouldOpenAutoModeApproval = this.options.openAutoModeApprovalsInBrowser ?? getZapierOpenAutoModeApprovalsInBrowser() ?? false;
4231
+ if (approval.mode === "auto") {
4232
+ if (shouldOpenAutoModeApproval) {
4233
+ await openApproval(approval.approval_url);
4234
+ }
4235
+ if (approval.status === "approved") {
4236
+ this.emitEvent("approval:approved", {
4237
+ approvalId: approval.id
4238
+ });
4239
+ return;
4240
+ }
4241
+ if (approval.status === "denied") {
4242
+ this.emitEvent("approval:denied", {
4243
+ approvalId: approval.id,
4244
+ ...approval.reason ? { reason: approval.reason } : {}
4245
+ });
4246
+ throw new ZapierApprovalError(
4247
+ approval.reason ? `Request denied: ${approval.reason}` : "Request denied by user",
4248
+ {
4249
+ approvalId: approval.id,
4250
+ status: "denied",
4251
+ reason: approval.reason
4252
+ }
4253
+ );
4254
+ }
4255
+ if (approval.status === "failed") {
4256
+ this.throwApprovalFailed({
4257
+ approvalId: approval.id,
4258
+ approvalUrl: approval.approval_url,
4259
+ pollUrl: approval.poll_url,
4260
+ streamUrl: approval.stream_url,
4261
+ reason: approval.reason
4262
+ });
4263
+ }
4264
+ } else {
4265
+ if (mode === "throw") {
4266
+ throw new ZapierApprovalError("This request requires approval.", {
4267
+ approvalId: approval.id,
4268
+ approvalUrl: approval.approval_url,
4269
+ pollUrl: approval.poll_url,
4270
+ streamUrl: approval.stream_url,
4271
+ status: "pending"
4272
+ });
4273
+ }
4274
+ await openApproval(approval.approval_url);
4051
4275
  }
4052
- await openApproval(approval.approval_url);
4053
4276
  const timeoutMs = this.options.approvalTimeoutMs ?? DEFAULT_APPROVAL_TIMEOUT_MS;
4277
+ let streamAbortController;
4278
+ let streamPromise;
4279
+ let removeStreamAbortListener;
4280
+ if (approval.mode === "auto" && approval.stream_url) {
4281
+ const streamUrl = approval.stream_url;
4282
+ streamAbortController = new AbortController();
4283
+ const abortStream = () => streamAbortController?.abort();
4284
+ if (signal?.aborted) {
4285
+ abortStream();
4286
+ } else if (signal) {
4287
+ signal.addEventListener("abort", abortStream, { once: true });
4288
+ removeStreamAbortListener = () => signal.removeEventListener("abort", abortStream);
4289
+ }
4290
+ streamPromise = consumeApprovalReviewStream({
4291
+ approvalId: approval.id,
4292
+ streamUrl,
4293
+ signal: streamAbortController.signal,
4294
+ stream: (url, streamInit) => this.streamTrustedJsonUrl(url, streamInit),
4295
+ emitEvent: (type, payload) => this.emitEvent(type, payload)
4296
+ });
4297
+ }
4054
4298
  let rawPollResult;
4055
4299
  try {
4056
4300
  rawPollResult = await pollUntilComplete({
@@ -4061,14 +4305,16 @@ var ZapierApiClient = class {
4061
4305
  // semaphore — but we deliberately do not hold a slot across the
4062
4306
  // sleep between polls or across the human-approval wait.
4063
4307
  fetchPoll: () => this.withSemaphore(
4064
- { url: approval.poll_url, method: "GET" },
4308
+ { url: approval.poll_url, method: "GET", signal },
4065
4309
  () => this.rawFetchUrl(approval.poll_url, {
4066
4310
  method: "GET",
4067
- headers: { Accept: "application/json" }
4311
+ headers: { Accept: "application/json" },
4312
+ signal
4068
4313
  })
4069
4314
  ),
4070
4315
  timeoutMs,
4071
4316
  maxPollingIntervalMs: APPROVAL_MAX_POLLING_INTERVAL_MS,
4317
+ signal,
4072
4318
  isPending: (body2) => {
4073
4319
  const parsed = PollApprovalResponseSchema.safeParse(body2);
4074
4320
  return parsed.success && parsed.data.status === "pending_approval";
@@ -4076,25 +4322,38 @@ var ZapierApiClient = class {
4076
4322
  });
4077
4323
  } catch (err) {
4078
4324
  if (!(err instanceof ZapierTimeoutError)) {
4325
+ this.emitEvent("approval:error", {
4326
+ approvalId: approval.id,
4327
+ message: err instanceof Error ? err.message : String(err)
4328
+ });
4079
4329
  throw err;
4080
4330
  }
4081
4331
  this.emitEvent("approval:timeout", {
4082
- approvalId: approval.approval_id
4332
+ approvalId: approval.id
4083
4333
  });
4084
4334
  throw new ZapierApprovalError(
4085
4335
  `Approval timed out after ${timeoutMs / 1e3} seconds`,
4086
4336
  {
4087
- approvalId: approval.approval_id,
4337
+ approvalId: approval.id,
4088
4338
  approvalUrl: approval.approval_url,
4089
4339
  pollUrl: approval.poll_url,
4340
+ streamUrl: approval.stream_url,
4090
4341
  status: "timeout",
4091
4342
  cause: err
4092
4343
  }
4093
4344
  );
4345
+ } finally {
4346
+ removeStreamAbortListener?.();
4347
+ streamAbortController?.abort();
4348
+ await streamPromise;
4094
4349
  }
4095
4350
  const pollParse = PollApprovalResponseSchema.safeParse(rawPollResult);
4096
4351
  if (!pollParse.success) {
4097
4352
  const bodyPreview = typeof rawPollResult === "string" ? rawPollResult : JSON.stringify(rawPollResult);
4353
+ this.emitEvent("approval:error", {
4354
+ approvalId: approval.id,
4355
+ message: `Failed to parse approval poll response: ${bodyPreview}`
4356
+ });
4098
4357
  throw new ZapierApiError(
4099
4358
  `Failed to parse approval poll response: ${bodyPreview}`,
4100
4359
  {
@@ -4107,22 +4366,63 @@ var ZapierApiClient = class {
4107
4366
  const pollResult = pollParse.data;
4108
4367
  if (pollResult.status === "denied") {
4109
4368
  this.emitEvent("approval:denied", {
4110
- approvalId: approval.approval_id
4369
+ approvalId: approval.id,
4370
+ ...pollResult.reason ? { reason: pollResult.reason } : {}
4111
4371
  });
4112
- throw new ZapierApprovalError("Request denied by user", {
4113
- approvalId: approval.approval_id,
4114
- status: "denied"
4372
+ throw new ZapierApprovalError(
4373
+ pollResult.reason ? `Request denied: ${pollResult.reason}` : "Request denied by user",
4374
+ {
4375
+ approvalId: approval.id,
4376
+ status: "denied",
4377
+ reason: pollResult.reason
4378
+ }
4379
+ );
4380
+ }
4381
+ if (pollResult.status === "failed") {
4382
+ this.throwApprovalFailed({
4383
+ approvalId: approval.id,
4384
+ approvalUrl: approval.approval_url,
4385
+ pollUrl: approval.poll_url,
4386
+ streamUrl: approval.stream_url,
4387
+ reason: pollResult.reason
4115
4388
  });
4116
4389
  }
4117
4390
  if (pollResult.status !== "approved") {
4391
+ this.emitEvent("approval:error", {
4392
+ approvalId: approval.id,
4393
+ message: `Unexpected approval status received: ${pollResult.status}`
4394
+ });
4118
4395
  throw new ZapierApiError(
4119
4396
  `Unexpected approval status received: ${pollResult.status}`
4120
4397
  );
4121
4398
  }
4122
4399
  this.emitEvent("approval:approved", {
4123
- approvalId: approval.approval_id
4400
+ approvalId: approval.id
4124
4401
  });
4125
4402
  }
4403
+ throwApprovalFailed({
4404
+ approvalId,
4405
+ approvalUrl,
4406
+ pollUrl,
4407
+ streamUrl,
4408
+ reason
4409
+ }) {
4410
+ this.emitEvent("approval:failed", {
4411
+ approvalId,
4412
+ ...reason ? { reason } : {}
4413
+ });
4414
+ throw new ZapierApprovalError(
4415
+ reason ? `Approval failed: ${reason}` : "Approval failed",
4416
+ {
4417
+ approvalId,
4418
+ approvalUrl,
4419
+ pollUrl,
4420
+ streamUrl,
4421
+ status: "failed",
4422
+ reason
4423
+ }
4424
+ );
4425
+ }
4126
4426
  };
4127
4427
  var createZapierApi = (options) => {
4128
4428
  const { debug = false, fetch: originalFetch = globalThis.fetch } = options;
@@ -4183,6 +4483,7 @@ var apiPlugin = definePlugin(
4183
4483
  approvalTimeoutMs,
4184
4484
  maxApprovalRetries,
4185
4485
  approvalMode,
4486
+ openAutoModeApprovalsInBrowser,
4186
4487
  callerPackage
4187
4488
  } = sdk.context.options;
4188
4489
  const api = createZapierApi({
@@ -4198,6 +4499,7 @@ var apiPlugin = definePlugin(
4198
4499
  approvalTimeoutMs,
4199
4500
  maxApprovalRetries,
4200
4501
  approvalMode,
4502
+ openAutoModeApprovalsInBrowser,
4201
4503
  callerPackage
4202
4504
  });
4203
4505
  return {
@@ -6435,6 +6737,260 @@ var findUniqueConnectionPlugin = definePlugin(
6435
6737
  }
6436
6738
  })
6437
6739
  );
6740
+ var GetConnectionStartUrlSchema = zod.z.object({
6741
+ app: AppPropertySchema
6742
+ }).describe(
6743
+ "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 \u2014 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.\n\nUse 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 \u2014 call this alone, skip `wait-for-new-connection` entirely, or (b) do something custom between minting the URL and waiting for the connection \u2014 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.\n\nPair 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):\n\n```ts\nconst { data: { url, app, startedAt } } = await zapier.getConnectionStartUrl({ app: 'slack' });\n// hand `url` off \u2014 print it, DM it, email it, render a button, whatever\nconst { data: conn } = await zapier.waitForNewConnection({ app, startedAt });\n```"
6744
+ );
6745
+ var GetConnectionStartUrlItemSchema = zod.z.object({
6746
+ url: zod.z.string().describe(
6747
+ "URL the user should open in their browser to complete the auth flow. Single-use, time-limited."
6748
+ ),
6749
+ expiresAt: zod.z.number().describe(
6750
+ "Unix timestamp (seconds) after which the URL's signature is rejected by zapier.com."
6751
+ ),
6752
+ startedAt: zod.z.number().describe(
6753
+ "Unix timestamp (seconds) when the server minted the URL. Use it as the `startedAt` for `wait-for-new-connection` so polling is anchored to server time rather than a possibly-skewed client clock."
6754
+ ),
6755
+ app: zod.z.string().describe(
6756
+ "Versionless app key the URL was minted for (e.g., 'SlackCLIAPI'). Useful for downstream filtering."
6757
+ )
6758
+ }).describe(
6759
+ "The signed start-URL plus metadata needed to poll for completion."
6760
+ );
6761
+
6762
+ // src/plugins/getConnectionStartUrl/index.ts
6763
+ var START_PATH = "/zapier/api/authentications/v1/sdk/connections/start";
6764
+ var getConnectionStartUrlPlugin = definePlugin(
6765
+ (sdk) => createPluginMethod(sdk, {
6766
+ name: "getConnectionStartUrl",
6767
+ categories: ["connection"],
6768
+ type: "create",
6769
+ itemType: "ConnectionStartUrl",
6770
+ inputSchema: GetConnectionStartUrlSchema,
6771
+ outputSchema: GetConnectionStartUrlItemSchema,
6772
+ resolvers: { app: appKeyResolver },
6773
+ handler: async ({
6774
+ sdk: inner,
6775
+ options
6776
+ }) => {
6777
+ const versionedKey = await inner.context.getVersionedImplementationId(
6778
+ options.app
6779
+ );
6780
+ const selectedApi = versionedKey ? versionedKey.split("@")[0] : options.app;
6781
+ setMethodMetadata({ selectedApi });
6782
+ const response = await inner.context.api.post(
6783
+ START_PATH,
6784
+ { selected_api: selectedApi },
6785
+ { authRequired: true }
6786
+ );
6787
+ return {
6788
+ data: GetConnectionStartUrlItemSchema.parse({
6789
+ url: response.url,
6790
+ expiresAt: response.expires_at,
6791
+ startedAt: response.started_at,
6792
+ app: selectedApi
6793
+ })
6794
+ };
6795
+ }
6796
+ })
6797
+ );
6798
+ var WaitForNewConnectionSchema = zod.z.object({
6799
+ app: AppPropertySchema,
6800
+ startedAt: zod.z.number().int().nonnegative().describe(
6801
+ "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` \u2014 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."
6802
+ ),
6803
+ timeoutMs: zod.z.number().int().positive().optional().describe(
6804
+ "How long to wait before giving up. Default 5 minutes (300_000)."
6805
+ ),
6806
+ pollIntervalMs: zod.z.number().int().positive().optional().describe(
6807
+ "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)."
6808
+ )
6809
+ }).describe(
6810
+ "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` \u2014 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):\n\n```ts\nconst { data: { url, app, startedAt } } = await zapier.getConnectionStartUrl({ app: 'slack' });\n// show `url` to the user via the channel they're reading from\nconst { data: conn } = await zapier.waitForNewConnection({ app, startedAt });\n```"
6811
+ );
6812
+ var WaitForNewConnectionItemSchema = zod.z.object({
6813
+ id: zod.z.string().describe(
6814
+ "The new connection's ID. Public UUID when available, falling back to the numeric ID."
6815
+ ),
6816
+ app: zod.z.string().describe(
6817
+ "Versionless app key the connection was created for (e.g., 'SlackCLIAPI')."
6818
+ ),
6819
+ title: zod.z.string().nullable().optional().describe(
6820
+ "Human-readable connection title set by the auth flow, when available."
6821
+ )
6822
+ }).describe("The new connection that was detected.");
6823
+
6824
+ // src/plugins/waitForNewConnection/index.ts
6825
+ var CONNECTIONS_PATH = "/api/v0/connections";
6826
+ var waitForNewConnectionPlugin = definePlugin(
6827
+ (sdk) => createPluginMethod(sdk, {
6828
+ name: "waitForNewConnection",
6829
+ categories: ["connection"],
6830
+ type: "item",
6831
+ itemType: "Connection",
6832
+ inputSchema: WaitForNewConnectionSchema,
6833
+ outputSchema: WaitForNewConnectionItemSchema,
6834
+ resolvers: { app: appKeyResolver },
6835
+ handler: async ({
6836
+ sdk: inner,
6837
+ options
6838
+ }) => {
6839
+ const versionedKey = await inner.context.getVersionedImplementationId(
6840
+ options.app
6841
+ );
6842
+ const appKey = versionedKey ? versionedKey.split("@")[0] : options.app;
6843
+ setMethodMetadata({ selectedApi: appKey });
6844
+ try {
6845
+ const top = await inner.context.api.poll(
6846
+ CONNECTIONS_PATH,
6847
+ {
6848
+ searchParams: {
6849
+ app_key: appKey,
6850
+ // Scope to the current user's own connections. The connection
6851
+ // we're waiting on is by definition owned by the caller; without
6852
+ // this the one-row head-check could match a teammate's freshly
6853
+ // created connection for the same app.
6854
+ owner: "me",
6855
+ is_expired: "false",
6856
+ ordering: "-date",
6857
+ page_size: "1"
6858
+ },
6859
+ authRequired: true,
6860
+ timeoutMs: options.timeoutMs ?? 3e5,
6861
+ initialDelay: options.pollIntervalMs ?? 3e3,
6862
+ isPending: (body) => {
6863
+ const rows = body.data ?? [];
6864
+ const head = rows[0];
6865
+ if (!head?.date) return true;
6866
+ const created = Math.floor(new Date(head.date).getTime() / 1e3);
6867
+ return !Number.isFinite(created) || created < options.startedAt;
6868
+ },
6869
+ resultExtractor: (body) => (
6870
+ // `isPending` guaranteed a fresh row at index 0 before this fires.
6871
+ body.data[0]
6872
+ )
6873
+ }
6874
+ );
6875
+ return {
6876
+ data: WaitForNewConnectionItemSchema.parse({
6877
+ id: String(top.public_id ?? top.id),
6878
+ app: appKey,
6879
+ title: top.title ?? null
6880
+ })
6881
+ };
6882
+ } catch (err) {
6883
+ if (err instanceof ZapierTimeoutError) {
6884
+ throw new ZapierTimeoutError(
6885
+ `Timed out waiting for a new "${appKey}" connection. If the user completed the auth flow, retrieve the connection via sdk.getConnection({ id }) with the ID shown on the completion page.`
6886
+ );
6887
+ }
6888
+ throw err;
6889
+ }
6890
+ }
6891
+ })
6892
+ );
6893
+
6894
+ // src/utils/should-open-browser.ts
6895
+ function shouldOpenBrowser() {
6896
+ if (isCiEnv()) return false;
6897
+ const env = globalThis.process?.env;
6898
+ if (env?.SSH_TTY || env?.SSH_CONNECTION) return false;
6899
+ if (globalThis.process?.platform === "linux" && !env?.DISPLAY && !env?.WAYLAND_DISPLAY) {
6900
+ return false;
6901
+ }
6902
+ return true;
6903
+ }
6904
+ function isCiEnv() {
6905
+ const env = globalThis.process?.env;
6906
+ return !!(env?.CI || env?.CONTINUOUS_INTEGRATION || env?.GITHUB_ACTIONS || env?.JENKINS_URL || env?.GITLAB_CI || env?.CIRCLECI || env?.TRAVIS || env?.BUILDKITE || env?.DRONE || env?.BITBUCKET_PIPELINES_UUID);
6907
+ }
6908
+ var CreateConnectionSchema = zod.z.object({
6909
+ app: AppPropertySchema,
6910
+ browser: zod.z.enum(["auto", "always", "never"]).default("auto").describe(
6911
+ "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 \u2014 a failed or skipped open degrades gracefully to copy-paste."
6912
+ ),
6913
+ timeoutMs: zod.z.number().int().positive().optional().describe(
6914
+ "How long to wait for the user to complete the connection flow before giving up. Default 5 minutes (300_000)."
6915
+ ),
6916
+ pollIntervalMs: zod.z.number().int().positive().optional().describe(
6917
+ "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)."
6918
+ )
6919
+ }).describe(
6920
+ "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 \u2014 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.\n\nThis 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 \u2014 call `get-connection-start-url` alone, no `wait-for-new-connection` needed, or (b) do something custom between minting the URL and waiting \u2014 call `get-connection-start-url`, do your work (email or DM the URL, render a QR code, etc.), then `wait-for-new-connection`."
6921
+ );
6922
+ var CreateConnectionItemSchema = zod.z.object({
6923
+ id: zod.z.string().describe(
6924
+ "The new connection's ID. Public UUID when available, falling back to the numeric ID."
6925
+ ),
6926
+ app: zod.z.string().describe(
6927
+ "Versionless app key the connection was created for (e.g., 'SlackCLIAPI')."
6928
+ ),
6929
+ title: zod.z.string().nullable().optional().describe(
6930
+ "Human-readable connection title set by the auth flow, when available."
6931
+ )
6932
+ }).describe("The newly created connection.");
6933
+
6934
+ // src/plugins/createConnection/index.ts
6935
+ var createConnectionPlugin = definePlugin(
6936
+ (sdk) => createPluginMethod(sdk, {
6937
+ name: "createConnection",
6938
+ categories: ["connection"],
6939
+ type: "create",
6940
+ itemType: "Connection",
6941
+ inputSchema: CreateConnectionSchema,
6942
+ outputSchema: CreateConnectionItemSchema,
6943
+ resolvers: { app: appKeyResolver },
6944
+ formatter: {
6945
+ format: (item) => ({
6946
+ title: `Connection created: ${item.title || item.id}`,
6947
+ id: item.id,
6948
+ details: [
6949
+ { text: `App: ${item.app}`, style: "normal" },
6950
+ { text: `ID: ${item.id}`, style: "accent" }
6951
+ ]
6952
+ })
6953
+ },
6954
+ handler: async ({
6955
+ sdk: inner,
6956
+ options
6957
+ }) => {
6958
+ const { data: start } = await inner.getConnectionStartUrl({
6959
+ app: options.app
6960
+ });
6961
+ setMethodMetadata({ selectedApi: start.app });
6962
+ console.error(
6963
+ `
6964
+ Open this URL to complete the connection:
6965
+ ${start.url}
6966
+ `
6967
+ );
6968
+ const shouldOpen = options.browser === "always" || options.browser === "auto" && shouldOpenBrowser();
6969
+ if (shouldOpen) {
6970
+ try {
6971
+ await open_url_default(start.url);
6972
+ } catch {
6973
+ }
6974
+ }
6975
+ const { data: fresh } = await inner.waitForNewConnection({
6976
+ app: start.app,
6977
+ // Server-stamped mint time: measured on the same clock as a
6978
+ // connection's `date`, so the freshness check is immune to
6979
+ // client/server clock skew.
6980
+ startedAt: start.startedAt,
6981
+ timeoutMs: options.timeoutMs,
6982
+ pollIntervalMs: options.pollIntervalMs
6983
+ });
6984
+ return {
6985
+ data: CreateConnectionItemSchema.parse({
6986
+ id: fresh.id,
6987
+ app: start.app,
6988
+ title: fresh.title ?? null
6989
+ })
6990
+ };
6991
+ }
6992
+ })
6993
+ );
6438
6994
 
6439
6995
  // src/plugins/deprecated/authentications.ts
6440
6996
  var listAuthenticationsPlugin = definePlugin(
@@ -9492,7 +10048,7 @@ function createZapierSdkWithoutRegistry(options = {}) {
9492
10048
  return createZapierSdk(options);
9493
10049
  }
9494
10050
  function createZapierSdkStack(options = {}) {
9495
- return createZapierCoreStack().use(createOptionsPlugin(options)).use(eventEmissionPlugin).use(apiPlugin).use(manifestPlugin).use(capabilitiesPlugin).use(connectionsPlugin).use(listAppsPlugin).use(getAppPlugin).use(listConnectionsPlugin).use(getConnectionPlugin).use(findFirstConnectionPlugin).use(findUniqueConnectionPlugin).use(listActionsPlugin).use(getActionPlugin).use(listActionInputFieldsPlugin).use(getActionInputFieldsSchemaPlugin).use(listActionInputFieldChoicesPlugin).use(listInputFieldsDeprecatedPlugin).use(getInputFieldsSchemaDeprecatedPlugin).use(listInputFieldChoicesDeprecatedPlugin).use(runActionPlugin).use(listAuthenticationsPlugin).use(getAuthenticationPlugin).use(findFirstAuthenticationPlugin).use(findUniqueAuthenticationPlugin).use(listClientCredentialsPlugin).use(createClientCredentialsPlugin).use(deleteClientCredentialsPlugin).use(fetchPlugin).use(requestPlugin).use(listTablesPlugin).use(getTablePlugin).use(deleteTablePlugin).use(createTablePlugin).use(listTableFieldsPlugin).use(createTableFieldsPlugin).use(deleteTableFieldsPlugin).use(listTableRecordsPlugin).use(getTableRecordPlugin).use(createTableRecordsPlugin).use(deleteTableRecordsPlugin).use(updateTableRecordsPlugin).use(appsPlugin).use(getProfilePlugin);
10051
+ return createZapierCoreStack().use(createOptionsPlugin(options)).use(eventEmissionPlugin).use(apiPlugin).use(manifestPlugin).use(capabilitiesPlugin).use(connectionsPlugin).use(listAppsPlugin).use(getAppPlugin).use(listConnectionsPlugin).use(getConnectionPlugin).use(findFirstConnectionPlugin).use(findUniqueConnectionPlugin).use(getConnectionStartUrlPlugin).use(waitForNewConnectionPlugin).use(createConnectionPlugin).use(listActionsPlugin).use(getActionPlugin).use(listActionInputFieldsPlugin).use(getActionInputFieldsSchemaPlugin).use(listActionInputFieldChoicesPlugin).use(listInputFieldsDeprecatedPlugin).use(getInputFieldsSchemaDeprecatedPlugin).use(listInputFieldChoicesDeprecatedPlugin).use(runActionPlugin).use(listAuthenticationsPlugin).use(getAuthenticationPlugin).use(findFirstAuthenticationPlugin).use(findUniqueAuthenticationPlugin).use(listClientCredentialsPlugin).use(createClientCredentialsPlugin).use(deleteClientCredentialsPlugin).use(fetchPlugin).use(requestPlugin).use(listTablesPlugin).use(getTablePlugin).use(deleteTablePlugin).use(createTablePlugin).use(listTableFieldsPlugin).use(createTableFieldsPlugin).use(deleteTableFieldsPlugin).use(listTableRecordsPlugin).use(getTableRecordPlugin).use(createTableRecordsPlugin).use(deleteTableRecordsPlugin).use(updateTableRecordsPlugin).use(appsPlugin).use(getProfilePlugin);
9496
10052
  }
9497
10053
  function createZapierSdk(options = {}) {
9498
10054
  return withDeprecatedAddPlugin(createZapierSdkStack(options).toSdk());
@@ -11379,9 +11935,13 @@ var getWorkflowPlugin = definePlugin(
11379
11935
  var CreateWorkflowOptionsSchema = zod.z.object({
11380
11936
  name: zod.z.string().min(1).describe("Workflow name"),
11381
11937
  description: zod.z.string().optional().describe("Optional description for the workflow"),
11938
+ private: zod.z.boolean().optional().describe(
11939
+ "If true, only the creating user can see or manage this workflow. Defaults to false (account-visible)."
11940
+ ),
11941
+ /** @deprecated Use `private` instead. */
11382
11942
  is_private: zod.z.boolean().optional().describe(
11383
11943
  "If true, only the creating user can see or manage this workflow. Defaults to false (account-visible)."
11384
- )
11944
+ ).meta({ deprecated: true })
11385
11945
  }).describe(
11386
11946
  "Create a durable workflow container. Starts disabled with no version; publish a version to add code."
11387
11947
  );
@@ -11416,8 +11976,9 @@ var createWorkflowPlugin = definePlugin(
11416
11976
  if (options.description !== void 0) {
11417
11977
  body.description = options.description;
11418
11978
  }
11419
- if (options.is_private !== void 0) {
11420
- body.is_private = options.is_private;
11979
+ const isPrivate = options.private ?? options.is_private;
11980
+ if (isPrivate !== void 0) {
11981
+ body.is_private = isPrivate;
11421
11982
  }
11422
11983
  const raw = await sdk2.context.api.post(
11423
11984
  "/durableworkflowzaps/api/v0/workflows",
@@ -11806,7 +12367,7 @@ var RunDurableOptionsSchema = zod.z.object({
11806
12367
  'Exact semver of @zapier/zapier-durable to use (e.g. "1.2.3"). Defaults to server-configured version if omitted.'
11807
12368
  ),
11808
12369
  connections: zod.z.record(zod.z.string(), ConnectionMapEntrySchema).optional().describe(
11809
- "Named connection aliases. Maps alias names to Zapier connection IDs."
12370
+ 'Named connection aliases. Maps each alias to an object holding its Zapier connection ID, e.g. `{ "slack": { "connection_id": "123" } }`.'
11810
12371
  ),
11811
12372
  app_versions: zod.z.record(zod.z.string(), AppVersionMapEntrySchema).optional().describe(
11812
12373
  "Pinned app versions. Maps app keys (slugs) to implementation names and versions."
@@ -12485,7 +13046,10 @@ var BaseSdkOptionsSchema = zod.z.object({
12485
13046
  "Maximum number of sequential approval rounds per request (one per gating policy) before giving up. Default: 2."
12486
13047
  ),
12487
13048
  approvalMode: zod.z.enum(["disabled", "poll", "throw"]).optional().describe(
12488
- '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).'
13049
+ '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).'
13050
+ ),
13051
+ openAutoModeApprovalsInBrowser: zod.z.boolean().optional().describe(
13052
+ "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."
12489
13053
  ),
12490
13054
  // Internal
12491
13055
  manifestPath: zod.z.string().optional().describe("Path to a .zapierrc manifest file for app version locking.").meta({ internal: true }),
@@ -12513,7 +13077,7 @@ var registryPlugin = definePlugin((_sdk) => {
12513
13077
 
12514
13078
  // src/experimental.ts
12515
13079
  function createZapierSdkStack2(options = {}) {
12516
- return createZapierCoreStack().use(createOptionsPlugin(options)).use(eventEmissionPlugin).use(apiPlugin).use(manifestPlugin).use(capabilitiesPlugin).use(connectionsPlugin).use(listAppsPlugin).use(getAppPlugin).use(listConnectionsPlugin).use(getConnectionPlugin).use(findFirstConnectionPlugin).use(findUniqueConnectionPlugin).use(listActionsPlugin).use(getActionPlugin).use(listActionInputFieldsPlugin).use(getActionInputFieldsSchemaPlugin).use(listActionInputFieldChoicesPlugin).use(listInputFieldsDeprecatedPlugin).use(getInputFieldsSchemaDeprecatedPlugin).use(listInputFieldChoicesDeprecatedPlugin).use(runActionPlugin).use(listAuthenticationsPlugin).use(getAuthenticationPlugin).use(findFirstAuthenticationPlugin).use(findUniqueAuthenticationPlugin).use(listClientCredentialsPlugin).use(createClientCredentialsPlugin).use(deleteClientCredentialsPlugin).use(fetchPlugin).use(requestPlugin).use(listTriggerInboxesPlugin).use(createTriggerInboxPlugin).use(ensureTriggerInboxPlugin).use(getTriggerInboxPlugin).use(updateTriggerInboxPlugin).use(deleteTriggerInboxPlugin).use(pauseTriggerInboxPlugin).use(resumeTriggerInboxPlugin).use(listTriggerInboxMessagesPlugin).use(leaseTriggerInboxMessagesPlugin).use(ackTriggerInboxMessagesPlugin).use(releaseTriggerInboxMessagesPlugin).use(drainTriggerInboxPlugin).use(watchTriggerInboxPlugin).use(listTriggersPlugin).use(listTriggerInputFieldsPlugin).use(listTriggerInputFieldChoicesPlugin).use(getTriggerInputFieldsSchemaPlugin).use(listTablesPlugin).use(getTablePlugin).use(deleteTablePlugin).use(createTablePlugin).use(listTableFieldsPlugin).use(createTableFieldsPlugin).use(deleteTableFieldsPlugin).use(listTableRecordsPlugin).use(getTableRecordPlugin).use(createTableRecordsPlugin).use(deleteTableRecordsPlugin).use(updateTableRecordsPlugin).use(listWorkflowsPlugin).use(getWorkflowPlugin).use(createWorkflowPlugin).use(updateWorkflowPlugin).use(enableWorkflowPlugin).use(disableWorkflowPlugin).use(deleteWorkflowPlugin).use(listDurableRunsPlugin).use(getDurableRunPlugin).use(runDurablePlugin).use(cancelDurableRunPlugin).use(publishWorkflowVersionPlugin).use(listWorkflowVersionsPlugin).use(getWorkflowVersionPlugin).use(listWorkflowRunsPlugin).use(getWorkflowRunPlugin).use(getTriggerRunPlugin).use(triggerWorkflowPlugin).use(appsPlugin).use(getProfilePlugin);
13080
+ return createZapierCoreStack().use(createOptionsPlugin(options)).use(eventEmissionPlugin).use(apiPlugin).use(manifestPlugin).use(capabilitiesPlugin).use(connectionsPlugin).use(listAppsPlugin).use(getAppPlugin).use(listConnectionsPlugin).use(getConnectionPlugin).use(findFirstConnectionPlugin).use(findUniqueConnectionPlugin).use(getConnectionStartUrlPlugin).use(waitForNewConnectionPlugin).use(createConnectionPlugin).use(listActionsPlugin).use(getActionPlugin).use(listActionInputFieldsPlugin).use(getActionInputFieldsSchemaPlugin).use(listActionInputFieldChoicesPlugin).use(listInputFieldsDeprecatedPlugin).use(getInputFieldsSchemaDeprecatedPlugin).use(listInputFieldChoicesDeprecatedPlugin).use(runActionPlugin).use(listAuthenticationsPlugin).use(getAuthenticationPlugin).use(findFirstAuthenticationPlugin).use(findUniqueAuthenticationPlugin).use(listClientCredentialsPlugin).use(createClientCredentialsPlugin).use(deleteClientCredentialsPlugin).use(fetchPlugin).use(requestPlugin).use(listTriggerInboxesPlugin).use(createTriggerInboxPlugin).use(ensureTriggerInboxPlugin).use(getTriggerInboxPlugin).use(updateTriggerInboxPlugin).use(deleteTriggerInboxPlugin).use(pauseTriggerInboxPlugin).use(resumeTriggerInboxPlugin).use(listTriggerInboxMessagesPlugin).use(leaseTriggerInboxMessagesPlugin).use(ackTriggerInboxMessagesPlugin).use(releaseTriggerInboxMessagesPlugin).use(drainTriggerInboxPlugin).use(watchTriggerInboxPlugin).use(listTriggersPlugin).use(listTriggerInputFieldsPlugin).use(listTriggerInputFieldChoicesPlugin).use(getTriggerInputFieldsSchemaPlugin).use(listTablesPlugin).use(getTablePlugin).use(deleteTablePlugin).use(createTablePlugin).use(listTableFieldsPlugin).use(createTableFieldsPlugin).use(deleteTableFieldsPlugin).use(listTableRecordsPlugin).use(getTableRecordPlugin).use(createTableRecordsPlugin).use(deleteTableRecordsPlugin).use(updateTableRecordsPlugin).use(listWorkflowsPlugin).use(getWorkflowPlugin).use(createWorkflowPlugin).use(updateWorkflowPlugin).use(enableWorkflowPlugin).use(disableWorkflowPlugin).use(deleteWorkflowPlugin).use(listDurableRunsPlugin).use(getDurableRunPlugin).use(runDurablePlugin).use(cancelDurableRunPlugin).use(publishWorkflowVersionPlugin).use(listWorkflowVersionsPlugin).use(getWorkflowVersionPlugin).use(listWorkflowRunsPlugin).use(getWorkflowRunPlugin).use(getTriggerRunPlugin).use(triggerWorkflowPlugin).use(appsPlugin).use(getProfilePlugin);
12517
13081
  }
12518
13082
  function createZapierSdk2(options = {}) {
12519
13083
  return withDeprecatedAddPlugin(createZapierSdkStack2(options).toSdk());
@@ -12670,6 +13234,7 @@ exports.getTokenFromCliLogin = getTokenFromCliLogin;
12670
13234
  exports.getTtyContext = getTtyContext;
12671
13235
  exports.getZapierApprovalMode = getZapierApprovalMode;
12672
13236
  exports.getZapierDefaultApprovalMode = getZapierDefaultApprovalMode;
13237
+ exports.getZapierOpenAutoModeApprovalsInBrowser = getZapierOpenAutoModeApprovalsInBrowser;
12673
13238
  exports.getZapierSdkService = getZapierSdkService;
12674
13239
  exports.injectCliLogin = injectCliLogin;
12675
13240
  exports.inputFieldKeyResolver = inputFieldKeyResolver;