@getmagical/cli 0.1.12 → 0.1.15

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/dist/index.js CHANGED
@@ -6590,7 +6590,7 @@ import { Help } from "commander";
6590
6590
  var EMPTY_VALUE = "-";
6591
6591
  var TABLE_GAP = " ";
6592
6592
  function applyStyle(value, style, enabled = true) {
6593
- if (!enabled) {
6593
+ if (!enabled || typeof styleText !== "function") {
6594
6594
  return value;
6595
6595
  }
6596
6596
  return styleText(style, value);
@@ -6885,2028 +6885,2147 @@ function getErrorMessage(error) {
6885
6885
  }
6886
6886
 
6887
6887
  // src/program.ts
6888
+ import { readFile as readFile4 } from "fs/promises";
6888
6889
  import path6 from "path";
6889
6890
 
6890
- // ../mcp-registry/src/operation-specs.ts
6891
+ // ../common/dist/src/stdlib/json.util.js
6892
+ var import_ts_essentials = __toESM(require_dist(), 1);
6893
+
6894
+ // ../common/dist/src/stdlib/result.util.js
6891
6895
  import { z } from "zod";
6892
6896
 
6893
- // ../mcp-registry/src/operation-spec.ts
6894
- function stripLeadingGraphqlComments(document) {
6895
- return document.replace(/^(?:\s*#.*\n)+/u, "").trimStart();
6897
+ // ../common/dist/src/stdlib/error-user-facing.js
6898
+ var USER_FACING_STATUS_MESSAGES = /* @__PURE__ */ new Map([
6899
+ [400, "Bad Request"],
6900
+ [401, "Unauthorized"],
6901
+ [403, "Forbidden"],
6902
+ [404, "Not Found"],
6903
+ [500, "Internal Server Error"],
6904
+ [503, "Service Unavailable"]
6905
+ ]);
6906
+ var USER_FACING_DEFAULT_ACTIONS = /* @__PURE__ */ new Map([
6907
+ [400, "Review the request payload and retry."],
6908
+ [401, "Authenticate and retry the request."],
6909
+ [403, "Verify your permissions and retry the request."],
6910
+ [404, "Verify the requested resource exists and retry."],
6911
+ [
6912
+ 500,
6913
+ "Retry the request. If this keeps happening, contact support and share the correlation ID."
6914
+ ],
6915
+ [
6916
+ 503,
6917
+ "Retry the request after a brief delay. If this keeps happening, contact support and share the correlation ID."
6918
+ ]
6919
+ ]);
6920
+ var USER_FACING_FALLBACK_CODES = /* @__PURE__ */ new Map([
6921
+ [400, "BAD_REQUEST"],
6922
+ [401, "UNAUTHORIZED"],
6923
+ [403, "FORBIDDEN"],
6924
+ [404, "NOT_FOUND"],
6925
+ [500, "INTERNAL_SERVER_ERROR"],
6926
+ [503, "SERVICE_UNAVAILABLE"]
6927
+ ]);
6928
+ function isCustomerUsageError(appError) {
6929
+ return appError.categories.includes("customer_usage");
6896
6930
  }
6897
- function assertDocumentMatchesOperation({
6898
- document,
6899
- kind,
6900
- operationName
6901
- }) {
6902
- const normalizedDocument = stripLeadingGraphqlComments(document);
6903
- const match = /^(?<actualKind>query|mutation)\s+(?<actualOperationName>[_A-Za-z][_0-9A-Za-z]*)/u.exec(
6904
- normalizedDocument
6905
- );
6906
- const actualKind = match?.groups?.["actualKind"];
6907
- const actualOperationName = match?.groups?.["actualOperationName"];
6908
- if (!actualKind || !actualOperationName) {
6909
- throw new Error(
6910
- `Operation "${operationName}" is missing a top-level GraphQL ${kind} definition.`
6911
- );
6931
+ function getStatusCodeFromAppErrorCode(code) {
6932
+ if (typeof code !== "number" || !Number.isInteger(code)) {
6933
+ return void 0;
6912
6934
  }
6913
- if (actualKind !== kind || actualOperationName !== operationName) {
6914
- throw new Error(
6915
- `Operation "${operationName}" does not match its GraphQL document (${actualKind} ${actualOperationName}).`
6916
- );
6935
+ if (code >= 400 && code <= 599) {
6936
+ return code;
6917
6937
  }
6938
+ return void 0;
6918
6939
  }
6919
- function createOperationSpec(spec) {
6920
- assertDocumentMatchesOperation(spec);
6921
- return spec;
6940
+ function getStatusFamilyFallbackCode(statusCode) {
6941
+ if (statusCode >= 400 && statusCode <= 499) {
6942
+ return 400;
6943
+ }
6944
+ return 500;
6922
6945
  }
6923
-
6924
- // ../mcp-registry/src/operation-specs.ts
6925
- function stringOption({
6926
- description,
6927
- flagName,
6928
- inputKey,
6929
- required = false
6930
- }) {
6931
- return {
6932
- description,
6933
- flagName,
6934
- inputKey,
6935
- required,
6936
- valueType: "string"
6937
- };
6946
+ function getStatusMessage(statusCode) {
6947
+ const directMessage = USER_FACING_STATUS_MESSAGES.get(statusCode);
6948
+ if (directMessage !== void 0) {
6949
+ return directMessage;
6950
+ }
6951
+ return getStatusFamilyFallbackCode(statusCode) === 400 ? "Bad Request" : "Internal Server Error";
6938
6952
  }
6939
- function numberOption({
6940
- description,
6941
- flagName,
6942
- inputKey,
6943
- required = false
6944
- }) {
6945
- return {
6946
- description,
6947
- flagName,
6948
- inputKey,
6949
- required,
6950
- valueType: "number"
6951
- };
6953
+ function getDefaultSuggestedAction(statusCode) {
6954
+ const directAction = USER_FACING_DEFAULT_ACTIONS.get(statusCode);
6955
+ if (directAction !== void 0) {
6956
+ return directAction;
6957
+ }
6958
+ return getStatusFamilyFallbackCode(statusCode) === 400 ? "Review the request payload and retry." : "Retry the request. If this keeps happening, contact support and share the correlation ID.";
6952
6959
  }
6953
- function booleanOption({
6954
- description,
6955
- flagName,
6956
- inputKey
6957
- }) {
6958
- return {
6959
- description,
6960
- flagName,
6961
- inputKey,
6962
- valueType: "boolean"
6963
- };
6960
+ function getFallbackErrorCode(statusCode) {
6961
+ const directCode = USER_FACING_FALLBACK_CODES.get(statusCode);
6962
+ if (directCode !== void 0) {
6963
+ return directCode;
6964
+ }
6965
+ return getStatusFamilyFallbackCode(statusCode) === 400 ? "BAD_REQUEST" : "INTERNAL_SERVER_ERROR";
6964
6966
  }
6965
- function stringArrayOption({
6966
- description,
6967
- flagName,
6968
- inputKey,
6969
- required = false
6970
- }) {
6971
- return {
6972
- description,
6973
- flagName,
6974
- inputKey,
6975
- required,
6976
- valueHint: "comma-separated",
6977
- valueType: "string-array"
6978
- };
6967
+ function shouldExposeMessage({ appError, statusCode }) {
6968
+ if (statusCode >= 500) {
6969
+ return false;
6970
+ }
6971
+ return isCustomerUsageError(appError);
6979
6972
  }
6980
- function jsonOption({
6981
- description,
6982
- flagName,
6983
- inputKey,
6984
- required = false
6985
- }) {
6986
- return {
6987
- description,
6988
- flagName,
6989
- inputKey,
6990
- required,
6991
- valueHint: "JSON",
6992
- valueType: "json"
6993
- };
6973
+ function resolveApiMessage({ appError, statusCode }) {
6974
+ if (!shouldExposeMessage({ appError, statusCode })) {
6975
+ return getStatusMessage(statusCode);
6976
+ }
6977
+ const trimmedMessage = appError.message.trim();
6978
+ if (trimmedMessage.length > 0) {
6979
+ return trimmedMessage;
6980
+ }
6981
+ return getStatusMessage(statusCode);
6994
6982
  }
6995
- var jsonObjectSchema = z.record(z.string(), z.unknown());
6996
- var agentBrowserProviderOptionsSelection = ` browserbase {
6997
- advancedStealth
6998
- contextId
6999
- extensionId
7000
- instanceSize
7001
- blockAds
7002
- solveCaptchas
7003
- viewport {
7004
- width
7005
- height
7006
- }
7007
- }
7008
- agentCore {
7009
- viewport {
7010
- width
7011
- height
7012
- }
7013
- enableWebBotAuth
7014
- }
7015
- local {
7016
- viewport {
7017
- width
7018
- height
7019
- }
7020
- }
7021
- hyperbrowser {
7022
- viewport {
7023
- width
7024
- height
7025
- }
7026
- }
7027
- steel {
7028
- extensionIds
7029
- region
7030
- solveCaptcha
7031
- viewport {
7032
- width
7033
- height
7034
- }
7035
- }`;
7036
- var agentEnvironmentOptionsSelection = ` environmentOptions {
7037
- __typename
7038
- ... on AgentConfig_environmentOptions_Browser {
7039
- environment
7040
- maxMediaToIncludeInMemory
7041
- saveAuthCookiesAfterRun
7042
- startingUrl
7043
- browserProvider
7044
- browserProviderOptions {
7045
- ${agentBrowserProviderOptionsSelection}
7046
- }
7047
- }
7048
- ... on AgentConfig_environmentOptions_Browsercoordinates {
7049
- environment
7050
- maxMediaToIncludeInMemory
7051
- saveAuthCookiesAfterRun
7052
- startingUrl
7053
- browserProvider
7054
- browserProviderOptions {
7055
- ${agentBrowserProviderOptionsSelection}
7056
- }
7057
- }
7058
- ... on AgentConfig_environmentOptions_Desktop {
7059
- environment
7060
- browserProvider
7061
- browserProviderOptions {
7062
- ${agentBrowserProviderOptionsSelection}
7063
- }
7064
- maxMediaToIncludeInMemory
7065
- startingUrl
7066
- useCopyPasteForTyping
7067
- }
7068
- ... on AgentConfig_environmentOptions_Desktopapp {
7069
- environment
7070
- maxMediaToIncludeInMemory
7071
- }
7072
- ... on AgentConfig_environmentOptions_Minimal {
7073
- environment
7074
- }
7075
- }`;
7076
- var agentLimitationsSelection = ` limitations {
7077
- maxDurationSeconds
7078
- maxToolCalls
7079
- allowedUrlRegexes
7080
- }`;
7081
- var operationSpecs = [
7082
- createOperationSpec({
7083
- operationName: "GetAgents",
7084
- kind: "query",
7085
- inputSchema: z.object({
7086
- ids: z.array(z.string().min(1)).min(1)
7087
- }),
7088
- cli: {
7089
- name: "get-agents",
7090
- path: ["agents", "get"],
7091
- description: "Fetch one or more agents with config and schema fields.",
7092
- resultKey: "agents",
7093
- options: [
7094
- stringArrayOption({
7095
- inputKey: "ids",
7096
- flagName: "ids",
7097
- description: "Agent IDs.",
7098
- required: true
7099
- })
7100
- ]
7101
- },
7102
- mcp: { fileName: "agents.graphql" },
7103
- document: `# Query to fetch multiple agents with all fields
7104
- # Includes nested environment and limitation config fields
7105
- query GetAgents($ids: [ID!]!) {
7106
- agents(ids: $ids) {
7107
- id
7108
- name
7109
- description
7110
- instructions
7111
- organizationId
7112
- createdAt
7113
- updatedAt
7114
- sourceAgentId
7115
- inputSchema
7116
- outputSchema
7117
- config {
7118
- type
7119
- language
7120
- model
7121
- tools
7122
- maxSessionMessages
7123
- ${agentEnvironmentOptionsSelection}
7124
- ${agentLimitationsSelection}
7125
- commonParametersSchema
7126
- taskQueue
7127
- waitUponQueueing
7128
- queueableAgentIds
7129
- additionalSystemPrompt
7130
- ignoreUnstableSessionState
7131
- }
7132
- childAgentIds
7133
- }
7134
- }`
7135
- }),
7136
- createOperationSpec({
7137
- operationName: "GetAgentVersion",
7138
- kind: "query",
7139
- inputSchema: z.object({
7140
- agentId: z.string().min(1),
7141
- versionId: z.string().min(1)
7142
- }),
7143
- cli: {
7144
- name: "get-agent-version",
7145
- path: ["agents", "versions", "get"],
7146
- description: "Fetch one saved version for an agent.",
7147
- resultKey: "agentVersion",
7148
- options: [
7149
- stringOption({
7150
- inputKey: "agentId",
7151
- flagName: "agent-id",
7152
- description: "Agent ID.",
7153
- required: true
7154
- }),
7155
- stringOption({
7156
- inputKey: "versionId",
7157
- flagName: "version-id",
7158
- description: "Agent version ID.",
7159
- required: true
7160
- })
7161
- ]
7162
- },
7163
- mcp: { fileName: "agentVersion.graphql" },
7164
- document: `# Query to fetch a specific saved version for an agent
7165
- query GetAgentVersion($agentId: ID!, $versionId: ID!) {
7166
- agentVersion(agentId: $agentId, versionId: $versionId) {
7167
- id
7168
- agentId
7169
- sequence
7170
- name
7171
- description
7172
- instructions
7173
- instructionsMode
7174
- instructionsDoc
7175
- updaterUserId
7176
- createdAt
7177
- updatedAt
7178
- inputSchema
7179
- outputSchema
7180
- config {
7181
- type
7182
- language
7183
- model
7184
- tools
7185
- maxSessionMessages
7186
- ${agentEnvironmentOptionsSelection}
7187
- ${agentLimitationsSelection}
7188
- commonParametersSchema
7189
- taskQueue
7190
- waitUponQueueing
7191
- queueableAgentIds
7192
- additionalSystemPrompt
7193
- ignoreUnstableSessionState
7194
- }
7195
- isCurrent
6983
+ function resolveApiErrorCode({ appError, statusCode }) {
6984
+ if (!shouldExposeMessage({ appError, statusCode })) {
6985
+ return getFallbackErrorCode(statusCode);
7196
6986
  }
7197
- }`
7198
- }),
7199
- createOperationSpec({
7200
- operationName: "GetAgentVersions",
7201
- kind: "query",
7202
- inputSchema: z.object({
7203
- agentId: z.string().min(1)
7204
- }),
7205
- cli: {
7206
- name: "get-agent-versions",
7207
- path: ["agents", "versions", "list"],
7208
- description: "Fetch version history for an agent.",
7209
- resultKey: "agentVersions",
7210
- options: [
7211
- stringOption({
7212
- inputKey: "agentId",
7213
- flagName: "agent-id",
7214
- description: "Agent ID.",
7215
- required: true
7216
- })
7217
- ]
7218
- },
7219
- mcp: { fileName: "agentVersions.graphql" },
7220
- document: `# Query to fetch version history metadata for an agent
7221
- query GetAgentVersions($agentId: ID!) {
7222
- agentVersions(agentId: $agentId) {
7223
- id
7224
- sequence
7225
- name
7226
- description
7227
- updaterUserId
7228
- createdAt
7229
- updatedAt
7230
- isCurrent
6987
+ return normalizeUserFacingErrorCode({
6988
+ type: appError.type,
6989
+ fallbackCode: getFallbackErrorCode(statusCode)
6990
+ });
6991
+ }
6992
+ function resolveSuggestedAction({ appError, statusCode }) {
6993
+ const trimmedSuggestedAction = appError.suggestedAction?.trim();
6994
+ if (shouldExposeMessage({ appError, statusCode }) && trimmedSuggestedAction) {
6995
+ return trimmedSuggestedAction;
7231
6996
  }
7232
- }`
7233
- }),
7234
- createOperationSpec({
7235
- operationName: "DiffAgentVersion",
7236
- kind: "query",
7237
- inputSchema: z.object({
7238
- agentId: z.string().min(1),
7239
- versionId: z.string().min(1),
7240
- compareVersionId: z.string().min(1).optional()
7241
- }),
7242
- cli: {
7243
- name: "diff-agent-version",
7244
- path: ["agents", "versions", "diff"],
7245
- description: "Diff one agent version against another version or the current latest version.",
7246
- resultKey: "agentVersionDiff",
7247
- options: [
7248
- stringOption({
7249
- inputKey: "agentId",
7250
- flagName: "agent-id",
7251
- description: "Agent ID.",
7252
- required: true
7253
- }),
7254
- stringOption({
7255
- inputKey: "versionId",
7256
- flagName: "version-id",
7257
- description: "Source agent version ID.",
7258
- required: true
7259
- }),
7260
- stringOption({
7261
- inputKey: "compareVersionId",
7262
- flagName: "compare-version-id",
7263
- description: "Optional target version ID. Defaults to the current latest version."
7264
- })
7265
- ]
7266
- },
7267
- mcp: { fileName: "agentVersionDiff.graphql" },
7268
- document: `# Query to diff one agent version against another or the current latest version
7269
- query DiffAgentVersion(
7270
- $agentId: ID!
7271
- $versionId: ID!
7272
- $compareVersionId: ID
7273
- ) {
7274
- agentVersionDiff(
7275
- agentId: $agentId
7276
- versionId: $versionId
7277
- compareVersionId: $compareVersionId
7278
- ) {
7279
- agentId
7280
- fromVersionId
7281
- toVersionId
7282
- hasChanges
7283
- changes {
7284
- field
7285
- oldValue
7286
- newValue
7287
- }
6997
+ return getDefaultSuggestedAction(statusCode);
6998
+ }
6999
+ function getZodIssuesFromCause(cause, maxDepth = 10) {
7000
+ if (maxDepth < 0 || typeof cause !== "object" || cause === null) {
7001
+ return void 0;
7288
7002
  }
7289
- }`
7290
- }),
7291
- createOperationSpec({
7292
- operationName: "GetAgentRun",
7293
- kind: "query",
7294
- inputSchema: z.object({
7295
- id: z.string().min(1)
7296
- }),
7297
- cli: {
7298
- name: "get-agent-run",
7299
- path: ["agent-runs", "get"],
7300
- description: "Fetch a single agent run.",
7301
- resultKey: "agentRun",
7302
- options: [
7303
- stringOption({
7304
- inputKey: "id",
7305
- flagName: "id",
7306
- description: "Agent run ID.",
7307
- required: true
7308
- })
7309
- ]
7310
- },
7311
- mcp: { fileName: "agentRun.graphql" },
7312
- document: `# Query a single agent run
7313
- query GetAgentRun($id: ID!) {
7314
- agentRun(id: $id) {
7315
- id
7316
- agentVersionId
7317
- agentName
7318
- status
7319
- statusDetail
7320
- isChildAgent
7321
- input
7322
- startedAt
7323
- finishedAt
7324
- parentAgentRunId
7003
+ if ("issues" in cause && Array.isArray(cause.issues)) {
7004
+ return cause.issues;
7325
7005
  }
7326
- }`
7327
- }),
7328
- createOperationSpec({
7329
- operationName: "GetAutomationAgents",
7330
- kind: "query",
7331
- inputSchema: z.object({
7332
- ids: z.array(z.string().min(1)).min(1)
7333
- }),
7334
- cli: {
7335
- name: "get-automation-agents",
7336
- path: ["automations", "agents"],
7337
- description: "Fetch the agents attached to one or more automations.",
7338
- resultKey: "automationAgents",
7339
- options: [
7340
- stringArrayOption({
7341
- inputKey: "ids",
7342
- flagName: "ids",
7343
- description: "Automation IDs.",
7344
- required: true
7345
- })
7346
- ]
7347
- },
7348
- mcp: { fileName: "automationAgents.graphql" },
7349
- document: `# Query automation agent relationships with flat agent fields only
7350
- # Excludes nested agent config and schemas for MCP tool simplicity
7351
- query GetAutomationAgents($ids: [ID!]!) {
7352
- automationAgents(ids: $ids) {
7353
- automationId
7354
- agentId
7355
- isTrigger
7356
- agent {
7357
- id
7358
- name
7359
- description
7360
- instructions
7361
- organizationId
7362
- createdAt
7363
- updatedAt
7364
- sourceAgentId
7365
- childAgentIds
7366
- }
7006
+ if ("cause" in cause) {
7007
+ return getZodIssuesFromCause(cause.cause, maxDepth - 1);
7367
7008
  }
7368
- }`
7369
- }),
7370
- createOperationSpec({
7371
- operationName: "GetAutomationRun",
7372
- kind: "query",
7373
- inputSchema: z.object({
7374
- id: z.string().min(1)
7375
- }),
7376
- cli: {
7377
- name: "get-automation-run",
7378
- path: ["automation-runs", "get"],
7379
- description: "Fetch a single automation run.",
7380
- resultKey: "automationRun",
7381
- options: [
7382
- stringOption({
7383
- inputKey: "id",
7384
- flagName: "id",
7385
- description: "Automation run ID.",
7386
- required: true
7387
- })
7388
- ]
7389
- },
7390
- mcp: { fileName: "automationRun.graphql" },
7391
- document: `# Query a full automation run details payload
7392
- query GetAutomationRun($id: ID!) {
7393
- automationRun(id: $id) {
7394
- id
7395
- automationId
7396
- parentAutomationRunId
7397
- status
7398
- statusDetail
7399
- summary
7400
- invocationType
7401
- input
7402
- additionalPrompt
7403
- debugUrl
7404
- createdAt
7405
- startedAt
7406
- pausedAt
7407
- finishedAt
7009
+ return void 0;
7010
+ }
7011
+ function toUserFacingDetailsValue(value, depth) {
7012
+ if (depth < 0) {
7013
+ return void 0;
7408
7014
  }
7409
- }`
7410
- }),
7411
- createOperationSpec({
7412
- operationName: "GetAutomationRunAgentRuns",
7413
- kind: "query",
7414
- inputSchema: z.object({
7415
- automationRunId: z.string().min(1)
7416
- }),
7417
- cli: {
7418
- name: "get-automation-run-agent-runs",
7419
- path: ["automation-runs", "agent-runs"],
7420
- description: "Fetch ordered agent runs for an automation run.",
7421
- resultKey: "automationRunAgentRuns",
7422
- options: [
7423
- stringOption({
7424
- inputKey: "automationRunId",
7425
- flagName: "automation-run-id",
7426
- description: "Automation run ID.",
7427
- required: true
7428
- })
7429
- ]
7430
- },
7431
- mcp: { fileName: "automationRunAgentRuns.graphql" },
7432
- document: `# Query ordered agent runs for an automation run
7433
- query GetAutomationRunAgentRuns($automationRunId: ID!) {
7434
- automationRunAgentRuns(automationRunId: $automationRunId) {
7435
- id
7436
- agentVersionId
7437
- agentName
7438
- status
7439
- statusDetail
7440
- isChildAgent
7441
- input
7442
- startedAt
7443
- finishedAt
7444
- parentAgentRunId
7015
+ if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
7016
+ return value;
7445
7017
  }
7446
- }`
7447
- }),
7448
- createOperationSpec({
7449
- operationName: "GetAutomationRunIterations",
7450
- kind: "query",
7451
- inputSchema: z.object({
7452
- automationRunId: z.string().min(1),
7453
- agentRunId: z.string().min(1).optional(),
7454
- limit: z.number().int().positive().optional(),
7455
- reverse: z.boolean().optional()
7456
- }),
7457
- cli: {
7458
- name: "get-automation-run-iterations",
7459
- path: ["automation-runs", "iterations"],
7460
- description: "Fetch ordered iterations for an automation run.",
7461
- resultKey: "automationRunIterations",
7462
- options: [
7463
- stringOption({
7464
- inputKey: "automationRunId",
7465
- flagName: "automation-run-id",
7466
- description: "Automation run ID.",
7467
- required: true
7468
- }),
7469
- stringOption({
7470
- inputKey: "agentRunId",
7471
- flagName: "agent-run-id",
7472
- description: "Optional agent run ID to filter by."
7473
- }),
7474
- numberOption({
7475
- inputKey: "limit",
7476
- flagName: "limit",
7477
- description: "Maximum number of iterations to return."
7478
- }),
7479
- booleanOption({
7480
- inputKey: "reverse",
7481
- flagName: "reverse",
7482
- description: "Return newest iterations first."
7483
- })
7484
- ]
7485
- },
7486
- mcp: { fileName: "automationRunIterations.graphql" },
7487
- document: `# Query iterations for an automation run with optional filtering by agent run
7488
- query GetAutomationRunIterations(
7489
- $automationRunId: ID!
7490
- $agentRunId: ID
7491
- $limit: Int
7492
- $reverse: Boolean
7493
- ) {
7494
- automationRunIterations(
7495
- automationRunId: $automationRunId
7496
- agentRunId: $agentRunId
7497
- limit: $limit
7498
- reverse: $reverse
7499
- ) {
7500
- id
7501
- sequence
7502
- agentRunId
7503
- metadata
7504
- startedAt
7505
- finishedAt
7506
- totalDurationMs
7507
- llmResponseDurationMs
7508
- withMarksScreenshotUrl
7509
- withMarksMimeType
7510
- memories {
7511
- id
7512
- type
7513
- value
7514
- sequence
7515
- screenshotUrl
7516
- screenshotMimeType
7018
+ if (Array.isArray(value)) {
7019
+ const serializedValues = value.map((item) => toUserFacingDetailsValue(item, depth - 1)).filter((item) => item !== void 0);
7020
+ return serializedValues;
7021
+ }
7022
+ if (value && typeof value === "object") {
7023
+ const serializedObject = {};
7024
+ for (const [key, itemValue] of Object.entries(value)) {
7025
+ const serializedItemValue = toUserFacingDetailsValue(itemValue, depth - 1);
7026
+ if (serializedItemValue !== void 0) {
7027
+ serializedObject[key] = serializedItemValue;
7028
+ }
7029
+ }
7030
+ if (Object.keys(serializedObject).length === 0) {
7031
+ return void 0;
7517
7032
  }
7033
+ return serializedObject;
7518
7034
  }
7519
- }`
7520
- }),
7521
- createOperationSpec({
7522
- operationName: "GetAutomationRuns",
7523
- kind: "query",
7524
- inputSchema: z.object({
7525
- automationId: z.string().min(1),
7526
- status: z.array(z.string().min(1)).optional(),
7527
- invocationType: z.array(z.string().min(1)).optional(),
7528
- limit: z.number().int().positive().optional(),
7529
- page: z.number().int().positive().optional()
7530
- }),
7531
- cli: {
7532
- name: "get-automation-runs",
7533
- path: ["automation-runs", "list"],
7534
- description: "Fetch automation run history.",
7535
- resultKey: "automationRuns",
7536
- options: [
7537
- stringOption({
7538
- inputKey: "automationId",
7539
- flagName: "automation-id",
7540
- description: "Automation ID.",
7541
- required: true
7542
- }),
7543
- stringArrayOption({
7544
- inputKey: "status",
7545
- flagName: "status",
7546
- description: "Optional run statuses."
7547
- }),
7548
- stringArrayOption({
7549
- inputKey: "invocationType",
7550
- flagName: "invocation-type",
7551
- description: "Optional invocation types."
7552
- }),
7553
- numberOption({
7554
- inputKey: "limit",
7555
- flagName: "limit",
7556
- description: "Maximum number of runs to return."
7557
- }),
7558
- numberOption({
7559
- inputKey: "page",
7560
- flagName: "page",
7561
- description: "Page number."
7562
- })
7563
- ]
7564
- },
7565
- mcp: { fileName: "automationRuns.graphql" },
7566
- document: `# Query automation run history for a specific automation with optional filters
7567
- query GetAutomationRuns(
7568
- $automationId: ID!
7569
- $status: [RunStatus!]
7570
- $invocationType: [InvocationType!]
7571
- $limit: Int
7572
- $page: Int
7573
- ) {
7574
- automationRuns(
7575
- automationId: $automationId
7576
- status: $status
7577
- invocationType: $invocationType
7578
- limit: $limit
7579
- page: $page
7580
- ) {
7581
- id
7582
- automationId
7583
- parentAutomationRunId
7584
- status
7585
- statusDetail
7586
- invocationType
7587
- summary
7588
- createdAt
7589
- startedAt
7590
- pausedAt
7591
- finishedAt
7035
+ return void 0;
7036
+ }
7037
+ function resolveApiDetails({ appError, statusCode }) {
7038
+ if (!shouldExposeMessage({ appError, statusCode })) {
7039
+ return void 0;
7592
7040
  }
7593
- }`
7594
- }),
7595
- createOperationSpec({
7596
- operationName: "ListAutomations",
7597
- kind: "query",
7598
- inputSchema: z.object({
7599
- limit: z.number().positive().optional(),
7600
- order: jsonObjectSchema.optional(),
7601
- where: jsonObjectSchema.optional()
7602
- }),
7603
- cli: {
7604
- name: "list-automations",
7605
- path: ["automations", "list"],
7606
- description: "List automations with optional filters.",
7607
- resultKey: "automations",
7608
- options: [
7609
- numberOption({
7610
- inputKey: "limit",
7611
- flagName: "limit",
7612
- description: "Maximum number of automations to return."
7613
- }),
7614
- jsonOption({
7615
- inputKey: "order",
7616
- flagName: "order-json",
7617
- description: "GraphQL order object."
7618
- }),
7619
- jsonOption({
7620
- inputKey: "where",
7621
- flagName: "where-json",
7622
- description: "GraphQL filter object."
7623
- })
7624
- ]
7625
- },
7626
- mcp: { fileName: "listAutomations.graphql" },
7627
- document: `# Query to list automations with flat fields only (no nested objects)
7628
- # Excludes config and agents for MCP tool simplicity
7629
- query ListAutomations(
7630
- $limit: Float
7631
- $order: AutomationsOrder
7632
- $where: AutomationsWhereInput
7633
- ) {
7634
- automations(limit: $limit, order: $order, where: $where) {
7635
- id
7636
- name
7637
- organizationId
7638
- createdAt
7639
- updatedAt
7640
- environment
7641
- lastSavedAt
7642
- publishedVersionId
7643
- draftVersionId
7041
+ const zodIssues = getZodIssuesFromCause(appError.cause);
7042
+ if (zodIssues && zodIssues.length > 0) {
7043
+ return {
7044
+ validationErrors: zodIssues.map((issue) => ({
7045
+ path: Array.isArray(issue.path) ? issue.path.map(String).join(".") : "",
7046
+ message: typeof issue.message === "string" ? issue.message : "Invalid value",
7047
+ ...typeof issue.code === "string" ? { code: issue.code } : {}
7048
+ }))
7049
+ };
7644
7050
  }
7645
- }`
7646
- }),
7647
- createOperationSpec({
7648
- operationName: "GetAutomations",
7649
- kind: "query",
7650
- inputSchema: z.object({
7651
- ids: z.array(z.string().min(1)).min(1)
7652
- }),
7653
- cli: {
7654
- name: "get-automations",
7655
- path: ["automations", "get"],
7656
- description: "Fetch one or more automations by IDs.",
7657
- resultKey: "automations",
7658
- options: [
7659
- stringArrayOption({
7660
- inputKey: "ids",
7661
- flagName: "ids",
7662
- description: "Automation IDs.",
7663
- required: true
7664
- })
7665
- ]
7666
- },
7667
- mcp: { fileName: "automations.graphql" },
7668
- document: `# Query to fetch automations with flat fields only (no nested objects)
7669
- # Excludes config and agents for MCP tool simplicity
7670
- query GetAutomations($ids: [ID!]!) {
7671
- automations(ids: $ids) {
7672
- id
7673
- name
7674
- organizationId
7675
- createdAt
7676
- updatedAt
7677
- environment
7678
- lastSavedAt
7679
- publishedVersionId
7680
- draftVersionId
7051
+ const rawDetails = toUserFacingDetailsValue(appError.details, 4);
7052
+ if (rawDetails && typeof rawDetails === "object" && !Array.isArray(rawDetails) && Object.keys(rawDetails).length > 0) {
7053
+ return rawDetails;
7681
7054
  }
7682
- }`
7683
- }),
7684
- createOperationSpec({
7685
- operationName: "GetAvailableCommands",
7686
- kind: "query",
7687
- inputSchema: z.object({
7688
- env: z.string().min(1)
7689
- }),
7690
- cli: {
7691
- name: "get-available-commands",
7692
- path: ["catalog", "commands"],
7693
- description: "Fetch available command definitions by environment.",
7694
- resultKey: "availableCommands",
7695
- options: [
7696
- stringOption({
7697
- inputKey: "env",
7698
- flagName: "env",
7699
- description: "Environment name.",
7700
- required: true
7701
- })
7702
- ]
7703
- },
7704
- mcp: { fileName: "availableCommands.graphql" },
7705
- document: `# Query to fetch available command definitions by environment
7706
- query GetAvailableCommands($env: AvailableCommandsEnv!) {
7707
- availableCommands(env: $env) {
7708
- id
7709
- description
7710
- inputSchema
7055
+ return void 0;
7056
+ }
7057
+ function getGraphQLErrorCodeFromAppErrorCode(code) {
7058
+ if (code === 400) {
7059
+ return "BAD_USER_INPUT";
7711
7060
  }
7712
- }`
7713
- }),
7714
- createOperationSpec({
7715
- operationName: "GetAvailableModels",
7716
- kind: "query",
7717
- inputSchema: z.object({
7718
- agentId: z.string().min(1)
7719
- }),
7720
- cli: {
7721
- name: "get-available-models",
7722
- path: ["catalog", "models"],
7723
- description: "Fetch available model definitions for an agent.",
7724
- resultKey: "availableModels",
7725
- options: [
7726
- stringOption({
7727
- inputKey: "agentId",
7728
- flagName: "agent-id",
7729
- description: "Agent ID.",
7730
- required: true
7731
- })
7732
- ]
7733
- },
7734
- mcp: { fileName: "availableModels.graphql" },
7735
- document: `# Query to fetch available model definitions and pools for a specific agent
7736
- query GetAvailableModels($agentId: String!) {
7737
- availableModels(agentId: $agentId) {
7738
- availableModelPools {
7739
- name
7740
- poolId
7741
- models {
7742
- id
7743
- name
7744
- description
7745
- status
7746
- provider
7747
- }
7748
- }
7749
- allAvailableModels {
7750
- id
7751
- name
7752
- description
7753
- status
7754
- provider
7755
- }
7061
+ if (code === 401) {
7062
+ return "UNAUTHORIZED";
7756
7063
  }
7757
- }`
7758
- }),
7759
- createOperationSpec({
7760
- operationName: "GetAvailableTools",
7761
- kind: "query",
7762
- inputSchema: z.object({
7763
- env: z.string().min(1),
7764
- automationId: z.string().min(1).optional()
7765
- }),
7766
- cli: {
7767
- name: "get-available-tools",
7768
- path: ["catalog", "tools"],
7769
- description: "Fetch available tool definitions by environment.",
7770
- resultKey: "availableTools",
7771
- options: [
7772
- stringOption({
7773
- inputKey: "env",
7774
- flagName: "env",
7775
- description: "Environment name.",
7776
- required: true
7777
- }),
7778
- stringOption({
7779
- inputKey: "automationId",
7780
- flagName: "automation-id",
7781
- description: "Optional automation ID."
7782
- })
7783
- ]
7784
- },
7785
- mcp: { fileName: "availableTools.graphql" },
7786
- document: `# Query to fetch available tool definitions by environment
7787
- query GetAvailableTools($env: AvailableCommandsEnv!, $automationId: String) {
7788
- availableTools(env: $env, automationId: $automationId) {
7789
- id
7790
- description
7791
- inputSchema
7064
+ if (code === 403) {
7065
+ return "FORBIDDEN";
7792
7066
  }
7793
- }`
7794
- }),
7795
- createOperationSpec({
7796
- operationName: "CreateAutomation",
7797
- kind: "mutation",
7798
- inputSchema: z.object({
7799
- input: jsonObjectSchema
7800
- }),
7801
- cli: {
7802
- name: "create-automation",
7803
- path: ["automations", "create"],
7804
- description: "Create a draft automation.",
7805
- resultKey: "createAutomation",
7806
- options: [
7807
- jsonOption({
7808
- inputKey: "input",
7809
- flagName: "input-json",
7810
- description: "CreateAutomationInput payload.",
7811
- required: true
7812
- })
7813
- ]
7814
- },
7815
- mcp: { fileName: "createAutomation.graphql" },
7816
- document: `# Mutation to create a draft automation with optional initial values
7817
- # Returns flat fields only for MCP tool simplicity
7818
- mutation CreateAutomation($input: CreateAutomationInput!) {
7819
- createAutomation(input: $input) {
7820
- id
7821
- name
7822
- organizationId
7823
- createdAt
7824
- updatedAt
7825
- environment
7826
- lastSavedAt
7827
- publishedVersionId
7828
- draftVersionId
7067
+ if (code === 404) {
7068
+ return "NOT_FOUND";
7829
7069
  }
7830
- }`
7831
- }),
7832
- createOperationSpec({
7833
- operationName: "GetGraphqlSchema",
7834
- kind: "query",
7835
- inputSchema: z.object({}),
7836
- cli: {
7837
- name: "get-graphql-schema",
7838
- path: ["graphql", "schema"],
7839
- description: "Fetch GraphQL schema metadata.",
7840
- resultKey: "graphqlSchema",
7841
- options: []
7842
- },
7843
- mcp: { fileName: "graphqlSchema.graphql" },
7844
- document: `# Query to fetch full GraphQL schema metadata.
7845
- # Uses the first-class graphqlSchema query field to avoid __schema validation
7846
- # issues in MCP tool-load paths while still returning introspection JSON.
7847
- # Response can be large: call sparingly (typically once per task/session) and
7848
- # reuse cached results.
7849
- query GetGraphqlSchema {
7850
- graphqlSchema
7851
- }`
7852
- }),
7853
- createOperationSpec({
7854
- operationName: "PauseAutomationRun",
7855
- kind: "mutation",
7856
- inputSchema: z.object({
7857
- automationRunId: z.string().min(1)
7858
- }),
7859
- cli: {
7860
- name: "pause-automation-run",
7861
- path: ["automation-runs", "pause"],
7862
- description: "Pause an automation run.",
7863
- resultKey: "pauseAutomationRun",
7864
- options: [
7865
- stringOption({
7866
- inputKey: "automationRunId",
7867
- flagName: "automation-run-id",
7868
- description: "Automation run ID.",
7869
- required: true
7870
- })
7871
- ]
7872
- },
7873
- mcp: { fileName: "pauseAutomationRun.graphql" },
7874
- document: `# Mutation to pause an automation run
7875
- mutation PauseAutomationRun($automationRunId: ID!) {
7876
- pauseAutomationRun(automationRunId: $automationRunId)
7877
- }`
7878
- }),
7879
- createOperationSpec({
7880
- operationName: "RerunAutomation",
7881
- kind: "mutation",
7882
- inputSchema: z.object({
7883
- automationRunId: z.string().min(1),
7884
- additionalPrompt: z.string().min(1).optional(),
7885
- idempotencyKey: z.string().min(1)
7886
- }),
7887
- cli: {
7888
- name: "rerun-automation",
7889
- path: ["automation-runs", "rerun"],
7890
- description: "Rerun an existing automation run.",
7891
- resultKey: "rerunAutomation",
7892
- options: [
7893
- stringOption({
7894
- inputKey: "automationRunId",
7895
- flagName: "automation-run-id",
7896
- description: "Automation run ID.",
7897
- required: true
7898
- }),
7899
- stringOption({
7900
- inputKey: "additionalPrompt",
7901
- flagName: "additional-prompt",
7902
- description: "Optional prompt appended to the rerun."
7903
- }),
7904
- stringOption({
7905
- inputKey: "idempotencyKey",
7906
- flagName: "idempotency-key",
7907
- description: "Idempotency key for the rerun request.",
7908
- required: true
7909
- })
7910
- ]
7911
- },
7912
- mcp: { fileName: "rerunAutomation.graphql" },
7913
- document: `# Mutation to rerun an existing automation run
7914
- mutation RerunAutomation(
7915
- $automationRunId: ID!
7916
- $additionalPrompt: String
7917
- $idempotencyKey: String!
7918
- ) {
7919
- rerunAutomation(
7920
- automationRunId: $automationRunId
7921
- additionalPrompt: $additionalPrompt
7922
- idempotencyKey: $idempotencyKey
7923
- ) {
7924
- automationRunId
7925
- workflowId
7926
- workflowRunId
7070
+ if (code === 500) {
7071
+ return "INTERNAL_SERVER_ERROR";
7927
7072
  }
7928
- }`
7929
- }),
7930
- createOperationSpec({
7931
- operationName: "ResumeAutomationRun",
7932
- kind: "mutation",
7933
- inputSchema: z.object({
7934
- automationRunId: z.string().min(1),
7935
- message: z.string().min(1).optional()
7936
- }),
7937
- cli: {
7938
- name: "resume-automation-run",
7939
- path: ["automation-runs", "resume"],
7940
- description: "Resume a paused automation run.",
7941
- resultKey: "resumeAutomationRun",
7942
- options: [
7943
- stringOption({
7944
- inputKey: "automationRunId",
7945
- flagName: "automation-run-id",
7946
- description: "Automation run ID.",
7947
- required: true
7948
- }),
7949
- stringOption({
7950
- inputKey: "message",
7951
- flagName: "message",
7952
- description: "Optional resume message."
7953
- })
7954
- ]
7955
- },
7956
- mcp: { fileName: "resumeAutomationRun.graphql" },
7957
- document: `# Mutation to resume an automation run
7958
- mutation ResumeAutomationRun($automationRunId: ID!, $message: String) {
7959
- resumeAutomationRun(automationRunId: $automationRunId, message: $message)
7960
- }`
7961
- }),
7962
- createOperationSpec({
7963
- operationName: "RunDraftAutomation",
7964
- kind: "mutation",
7965
- inputSchema: z.object({
7966
- draftAutomationId: z.string().min(1),
7967
- agentId: z.string().min(1),
7968
- idempotencyKey: z.string().min(1),
7969
- input: z.unknown().optional(),
7970
- additionalPrompt: z.string().min(1).optional()
7971
- }),
7972
- cli: {
7973
- name: "run-draft-automation",
7974
- path: ["automations", "run-draft"],
7975
- description: "Run a draft automation with an explicit trigger agent.",
7976
- resultKey: "runDraftAutomation",
7977
- options: [
7978
- stringOption({
7979
- inputKey: "draftAutomationId",
7980
- flagName: "draft-automation-id",
7981
- description: "Draft automation ID.",
7982
- required: true
7983
- }),
7984
- stringOption({
7985
- inputKey: "agentId",
7986
- flagName: "agent-id",
7987
- description: "Trigger agent ID.",
7988
- required: true
7989
- }),
7990
- stringOption({
7991
- inputKey: "idempotencyKey",
7992
- flagName: "idempotency-key",
7993
- description: "Idempotency key for the run request.",
7994
- required: true
7995
- }),
7996
- jsonOption({
7997
- inputKey: "input",
7998
- flagName: "input-json",
7999
- description: "Optional JSON input payload."
8000
- }),
8001
- stringOption({
8002
- inputKey: "additionalPrompt",
8003
- flagName: "additional-prompt",
8004
- description: "Optional prompt appended to the run."
8005
- })
8006
- ]
8007
- },
8008
- mcp: { fileName: "runDraftAutomation.graphql" },
8009
- document: `# Mutation to run a draft automation with an explicit agent.
8010
- # \`draftAutomationId\` is the draft automation entity ID (\`Automation.id\`), not \`draftVersionId\`.
8011
- mutation RunDraftAutomation(
8012
- $draftAutomationId: ID!
8013
- $agentId: ID!
8014
- $idempotencyKey: String!
8015
- $input: JSON
8016
- $additionalPrompt: String
8017
- ) {
8018
- runDraftAutomation(
8019
- draftAutomationId: $draftAutomationId
8020
- agentId: $agentId
8021
- idempotencyKey: $idempotencyKey
8022
- input: $input
8023
- additionalPrompt: $additionalPrompt
8024
- ) {
8025
- automationRunId
8026
- workflowId
8027
- workflowRunId
7073
+ return void 0;
7074
+ }
7075
+ function resolveGraphQLErrorCode(appError) {
7076
+ const codeFromAppErrorCode = getGraphQLErrorCodeFromAppErrorCode(appError.statusCode);
7077
+ if (codeFromAppErrorCode !== void 0) {
7078
+ return codeFromAppErrorCode;
8028
7079
  }
8029
- }`
8030
- }),
8031
- createOperationSpec({
8032
- operationName: "StopAutomationRun",
8033
- kind: "mutation",
8034
- inputSchema: z.object({
8035
- automationRunId: z.string().min(1)
8036
- }),
8037
- cli: {
8038
- name: "stop-automation-run",
8039
- path: ["automation-runs", "stop"],
8040
- description: "Stop an automation run.",
8041
- resultKey: "stopAutomationRun",
8042
- options: [
8043
- stringOption({
8044
- inputKey: "automationRunId",
8045
- flagName: "automation-run-id",
8046
- description: "Automation run ID.",
8047
- required: true
8048
- })
8049
- ]
8050
- },
8051
- mcp: { fileName: "stopAutomationRun.graphql" },
8052
- document: `# Mutation to stop an automation run
8053
- mutation StopAutomationRun($automationRunId: ID!) {
8054
- stopAutomationRun(automationRunId: $automationRunId)
8055
- }`
8056
- }),
8057
- createOperationSpec({
8058
- operationName: "UpdateAutomationById",
8059
- kind: "mutation",
8060
- inputSchema: z.object({
8061
- id: z.string().min(1),
8062
- input: jsonObjectSchema
8063
- }),
8064
- cli: {
8065
- name: "update-automation-by-id",
8066
- path: ["automations", "update"],
8067
- description: "Update an automation.",
8068
- resultKey: "updateAutomation",
8069
- options: [
8070
- stringOption({
8071
- inputKey: "id",
8072
- flagName: "id",
8073
- description: "Automation ID.",
8074
- required: true
8075
- }),
8076
- jsonOption({
8077
- inputKey: "input",
8078
- flagName: "input-json",
8079
- description: "UpdateAutomationInput payload.",
8080
- required: true
8081
- })
8082
- ]
8083
- },
8084
- mcp: { fileName: "updateAutomation.graphql" },
8085
- document: `# Mutation to update an automation
8086
- # Returns only id and lastSavedAt for MCP tool simplicity
8087
- mutation UpdateAutomationById($id: ID!, $input: UpdateAutomationInput!) {
8088
- updateAutomation(id: $id, input: $input) {
8089
- id
8090
- lastSavedAt
7080
+ const normalizedErrorType = appError.type.toLowerCase();
7081
+ if (normalizedErrorType.includes("unauthorized")) {
7082
+ return "UNAUTHORIZED";
8091
7083
  }
8092
- }`
8093
- })
8094
- ];
8095
-
8096
- // src/program.ts
8097
- import { Command as Command2, InvalidArgumentError as InvalidArgumentError2, Option as Option2 } from "commander";
7084
+ if (normalizedErrorType.includes("forbidden")) {
7085
+ return "FORBIDDEN";
7086
+ }
7087
+ if (normalizedErrorType.includes("not-found")) {
7088
+ return "NOT_FOUND";
7089
+ }
7090
+ if (isCustomerUsageError(appError)) {
7091
+ return "BAD_USER_INPUT";
7092
+ }
7093
+ return "INTERNAL_SERVER_ERROR";
7094
+ }
7095
+ function getStatusCodeFromGraphQLErrorCode(code) {
7096
+ switch (code) {
7097
+ case "BAD_USER_INPUT": {
7098
+ return 400;
7099
+ }
7100
+ case "UNAUTHORIZED": {
7101
+ return 401;
7102
+ }
7103
+ case "FORBIDDEN": {
7104
+ return 403;
7105
+ }
7106
+ case "NOT_FOUND": {
7107
+ return 404;
7108
+ }
7109
+ case "INTERNAL_SERVER_ERROR": {
7110
+ return 500;
7111
+ }
7112
+ }
7113
+ }
7114
+ function getGraphQLErrorMessage({ code, apiMessage }) {
7115
+ switch (code) {
7116
+ case "BAD_USER_INPUT":
7117
+ case "NOT_FOUND":
7118
+ case "INTERNAL_SERVER_ERROR": {
7119
+ return apiMessage;
7120
+ }
7121
+ case "UNAUTHORIZED": {
7122
+ return "Unauthorized";
7123
+ }
7124
+ case "FORBIDDEN": {
7125
+ return "Forbidden";
7126
+ }
7127
+ }
7128
+ }
7129
+ function getGraphQLAppErrorCode({ code, apiCode }) {
7130
+ if (code === "INTERNAL_SERVER_ERROR" || code === "UNAUTHORIZED" || code === "FORBIDDEN") {
7131
+ return code;
7132
+ }
7133
+ return apiCode;
7134
+ }
7135
+ function normalizeErrorCodeSegment(value) {
7136
+ return value.trim().toUpperCase().replaceAll(/[^\dA-Z]+/gu, "_").replaceAll(/^_+/gu, "").replaceAll(/_+$/gu, "");
7137
+ }
7138
+ function getStatusCodeForAppErrorFromAppError(appError) {
7139
+ const statusCodeFromCode = getStatusCodeFromAppErrorCode(appError.statusCode);
7140
+ if (statusCodeFromCode !== void 0) {
7141
+ return statusCodeFromCode;
7142
+ }
7143
+ if (isCustomerUsageError(appError)) {
7144
+ return 400;
7145
+ }
7146
+ return 500;
7147
+ }
7148
+ function normalizeUserFacingErrorCode({ type, fallbackCode, prefix }) {
7149
+ if (!type) {
7150
+ return fallbackCode;
7151
+ }
7152
+ const normalized = normalizeErrorCodeSegment(type);
7153
+ if (normalized.length === 0) {
7154
+ return fallbackCode;
7155
+ }
7156
+ const normalizedPrefix = prefix ? normalizeErrorCodeSegment(prefix) : void 0;
7157
+ if (!normalizedPrefix) {
7158
+ return normalized;
7159
+ }
7160
+ if (normalized.startsWith(`${normalizedPrefix}_`)) {
7161
+ return normalized;
7162
+ }
7163
+ return `${normalizedPrefix}_${normalized}`;
7164
+ }
7165
+ function toUserFacingApiErrorFromAppError({ appError, correlationId, statusCode }) {
7166
+ const resolvedStatusCode = statusCode ?? getStatusCodeForAppErrorFromAppError(appError);
7167
+ const message = resolveApiMessage({
7168
+ appError,
7169
+ statusCode: resolvedStatusCode
7170
+ });
7171
+ const suggestedAction = resolveSuggestedAction({
7172
+ appError,
7173
+ statusCode: resolvedStatusCode
7174
+ });
7175
+ const details = resolveApiDetails({
7176
+ appError,
7177
+ statusCode: resolvedStatusCode
7178
+ });
7179
+ return {
7180
+ code: resolveApiErrorCode({
7181
+ appError,
7182
+ statusCode: resolvedStatusCode
7183
+ }),
7184
+ message,
7185
+ correlationId,
7186
+ suggestedAction,
7187
+ ...details ? { details } : {}
7188
+ };
7189
+ }
7190
+ function toUserFacingGraphQLErrorFromAppError({ appError, correlationId }) {
7191
+ const code = resolveGraphQLErrorCode(appError);
7192
+ const statusCode = getStatusCodeFromGraphQLErrorCode(code);
7193
+ const apiError = toUserFacingApiErrorFromAppError({
7194
+ appError,
7195
+ correlationId,
7196
+ statusCode
7197
+ });
7198
+ return {
7199
+ code,
7200
+ errorCode: getGraphQLAppErrorCode({ code, apiCode: apiError.code }),
7201
+ message: getGraphQLErrorMessage({ code, apiMessage: apiError.message }),
7202
+ correlationId
7203
+ };
7204
+ }
8098
7205
 
8099
- // src/api.ts
8100
- import { z as z2 } from "zod";
8101
- var workosOrganizationsResponseSchema = z2.object({
8102
- organizations: z2.array(
8103
- z2.object({
8104
- id: z2.string().min(1),
8105
- name: z2.string().min(1),
8106
- primaryDomain: z2.string().nullable().optional()
8107
- })
8108
- ),
8109
- success: z2.boolean()
8110
- });
8111
- var workosUserSchema = z2.object({
8112
- email: z2.string().nullable(),
8113
- id: z2.string().min(1)
8114
- });
8115
- var graphQlResponseSchema = z2.object({
8116
- data: z2.record(z2.string(), z2.unknown()).optional(),
8117
- errors: z2.array(
8118
- z2.object({
8119
- message: z2.string().min(1)
8120
- })
8121
- ).optional()
8122
- });
8123
- var apiErrorResponseSchema = z2.object({
8124
- errors: z2.array(
8125
- z2.object({
8126
- message: z2.string().min(1)
8127
- })
8128
- ).optional(),
8129
- message: z2.string().min(1).optional()
8130
- });
8131
- function getApiErrorDetail(responseBody) {
8132
- const parsedResponse = apiErrorResponseSchema.safeParse(responseBody);
8133
- if (!parsedResponse.success) {
8134
- return null;
8135
- }
8136
- if (parsedResponse.data.message) {
8137
- return parsedResponse.data.message;
8138
- }
8139
- if (!parsedResponse.data.errors || parsedResponse.data.errors.length === 0) {
8140
- return null;
8141
- }
8142
- return parsedResponse.data.errors.map((error) => error.message).join("\n");
7206
+ // ../common/dist/src/stdlib/error.js
7207
+ var INTERNAL_STACK_PATHS = [
7208
+ "/src/stdlib/result.util.ts",
7209
+ "/src/stdlib/error.ts"
7210
+ ];
7211
+ function stripInternalFrames(stack, internalFrames) {
7212
+ const lines = stack.split("\n");
7213
+ return lines.filter((line) => !internalFrames.some((internalFrame) => line.includes(internalFrame)));
8143
7214
  }
8144
- function trimTrailingSlash(value) {
8145
- return value.replace(/\/+$/u, "");
7215
+ var ORDERED_APP_ERROR_CATEGORIES = [
7216
+ "internal_platform",
7217
+ "customer_usage",
7218
+ "third_party"
7219
+ ];
7220
+ function isAppErrorCategory(category) {
7221
+ return typeof category === "string" && // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
7222
+ ORDERED_APP_ERROR_CATEGORIES.includes(category);
8146
7223
  }
8147
- function createMagicalApiClient({
8148
- apiBaseUrl,
8149
- fetchFn = fetch
8150
- }) {
8151
- const resolveApiBaseUrl = typeof apiBaseUrl === "string" ? () => apiBaseUrl : apiBaseUrl;
8152
- async function fetchJson({
8153
- accessToken,
8154
- path: path7,
8155
- init
8156
- }) {
8157
- const url = `${trimTrailingSlash(await resolveApiBaseUrl())}${path7}`;
8158
- const headers = new Headers(init?.headers);
8159
- headers.set("authorization", `Bearer ${accessToken}`);
8160
- const response = await fetchFn(url, {
8161
- ...init,
8162
- headers
8163
- }).catch((error) => {
8164
- throw new CliError(
8165
- `Failed to reach Magical API at ${url}. Check your configured base URL and make sure service-main is running.`,
8166
- { cause: error }
8167
- );
8168
- });
8169
- const responseBody = await response.json().catch((error) => {
8170
- if (!response.ok) {
8171
- throw new CliError(
8172
- `Magical API request to ${url} failed with status ${response.status}.`,
8173
- {
8174
- cause: error
8175
- }
8176
- );
8177
- }
8178
- throw new CliError(
8179
- `Magical API returned a non-JSON response for ${url}.`,
8180
- {
8181
- cause: error
8182
- }
8183
- );
8184
- });
8185
- if (!response.ok) {
8186
- const errorDetail = getApiErrorDetail(responseBody);
8187
- throw new CliError(
8188
- `Magical API request to ${url} failed with status ${response.status}${errorDetail ? `: ${errorDetail}` : "."}`
8189
- );
7224
+ function isNonEmptyAppErrorCategoryArray(categories) {
7225
+ return Array.isArray(categories) && categories.length > 0 && categories.every(isAppErrorCategory);
7226
+ }
7227
+ var APP_ERROR_SEVERITIES = ["warn", "error", "fatal"];
7228
+ function isAppErrorCode(code) {
7229
+ return typeof code === "number" && Number.isInteger(code) && code >= 400 && code <= 599;
7230
+ }
7231
+ function isAppErrorSeverity(severity) {
7232
+ return typeof severity === "string" && // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
7233
+ APP_ERROR_SEVERITIES.includes(severity);
7234
+ }
7235
+ var AppError = class _AppError extends Error {
7236
+ type;
7237
+ categories;
7238
+ severity;
7239
+ statusCode;
7240
+ suggestedAction;
7241
+ nonRetryable;
7242
+ details;
7243
+ constructor({ type, categories, severity, statusCode, code, message, suggestedAction, cause, nonRetryable, stack, internalFrames, ...details }) {
7244
+ super(_AppError.resolveMessage(message, cause, type), { cause });
7245
+ this.type = type;
7246
+ this.name = type;
7247
+ this.details = details;
7248
+ this.categories = categories ?? _AppError.extractCategoriesFromCause(cause);
7249
+ this.severity = severity ?? _AppError.extractSeverityFromCause(cause);
7250
+ this.statusCode = statusCode ?? code ?? _AppError.extractStatusCodeFromCause(cause);
7251
+ this.suggestedAction = suggestedAction ?? _AppError.extractSuggestedActionFromCause(cause);
7252
+ this.nonRetryable = nonRetryable ?? false;
7253
+ _AppError.applyStack(this, stack, internalFrames);
7254
+ }
7255
+ static resolveMessage(message, cause, type) {
7256
+ if (message) {
7257
+ return message;
8190
7258
  }
8191
- return responseBody;
7259
+ if (cause instanceof Error) {
7260
+ return cause.message;
7261
+ }
7262
+ return type;
8192
7263
  }
8193
- return {
8194
- async executeGraphQl({
8195
- accessToken,
8196
- query,
8197
- resultKey,
8198
- variables
8199
- }) {
8200
- const headers = new Headers();
8201
- headers.set("content-type", "application/json");
8202
- const parsedResponse = graphQlResponseSchema.safeParse(
8203
- await fetchJson({
8204
- accessToken,
8205
- path: "/graphql",
8206
- init: {
8207
- method: "POST",
8208
- headers,
8209
- body: JSON.stringify({
8210
- query,
8211
- variables
8212
- })
8213
- }
8214
- })
8215
- );
8216
- if (!parsedResponse.success) {
8217
- throw new CliError("GraphQL response payload was invalid.");
8218
- }
8219
- if (parsedResponse.data.errors && parsedResponse.data.errors.length > 0) {
8220
- throw new CliError(
8221
- parsedResponse.data.errors.map((error) => error.message).join("\n")
8222
- );
8223
- }
8224
- return parsedResponse.data.data?.[resultKey] ?? null;
8225
- },
8226
- async fetchOrganizations({ accessToken }) {
8227
- const parsedResponse = workosOrganizationsResponseSchema.safeParse(
8228
- await fetchJson({
8229
- accessToken,
8230
- path: "/workos/organizations"
8231
- })
8232
- );
8233
- if (!parsedResponse.success) {
8234
- throw new CliError("Organization list payload was invalid.");
7264
+ static getInheritedCauseField(cause, extractor, seen = /* @__PURE__ */ new Set()) {
7265
+ if (!cause || typeof cause !== "object" || seen.has(cause)) {
7266
+ return void 0;
7267
+ }
7268
+ const causeRecord = cause;
7269
+ const extractedValue = extractor(causeRecord);
7270
+ if (extractedValue !== void 0) {
7271
+ return extractedValue;
7272
+ }
7273
+ return _AppError.getInheritedCauseField(causeRecord["cause"], extractor, new Set(seen).add(cause));
7274
+ }
7275
+ static extractCategoriesFromCause(cause) {
7276
+ return _AppError.getInheritedCauseField(cause, (causeRecord) => {
7277
+ const { categories } = causeRecord;
7278
+ if (isNonEmptyAppErrorCategoryArray(categories)) {
7279
+ return categories;
8235
7280
  }
8236
- return parsedResponse.data.organizations.map((organization) => ({
8237
- id: organization.id,
8238
- name: organization.name,
8239
- primaryDomain: organization.primaryDomain ?? null
8240
- }));
8241
- },
8242
- async fetchUser({
8243
- accessToken,
8244
- userId
8245
- }) {
8246
- const parsedResponse = workosUserSchema.safeParse(
8247
- await fetchJson({
8248
- accessToken,
8249
- path: `/workos/user/${userId}`
8250
- })
8251
- );
8252
- if (!parsedResponse.success) {
8253
- throw new CliError("User payload was invalid.");
7281
+ return void 0;
7282
+ }) ?? ["internal_platform"];
7283
+ }
7284
+ static extractSeverityFromCause(cause) {
7285
+ return _AppError.getInheritedCauseField(cause, (causeRecord) => {
7286
+ const { severity } = causeRecord;
7287
+ return isAppErrorSeverity(severity) ? severity : void 0;
7288
+ }) ?? "error";
7289
+ }
7290
+ static extractStatusCodeFromCause(cause) {
7291
+ return _AppError.getInheritedCauseField(cause, (causeRecord) => {
7292
+ const { statusCode } = causeRecord;
7293
+ if (isAppErrorCode(statusCode)) {
7294
+ return statusCode;
8254
7295
  }
8255
- return parsedResponse.data;
8256
- }
8257
- };
8258
- }
8259
-
8260
- // src/config.ts
8261
- import os from "os";
8262
- import path from "path";
8263
- var DEFAULT_MAGICAL_API_URL = "https://api-agt.getmagical.io";
8264
- var DEFAULT_WORKOS_API_URL = "https://api.workos.com";
8265
- var DEFAULT_WORKOS_CLIENT_ID = "client_01JJZ6XJ1RF248P20WF63M4VAM";
8266
- var DEFAULT_STAGING_WORKOS_CLIENT_ID = "client_01JJZ6X26BGFBT8AC303XPQ9EQ";
8267
- var DEFAULT_KEYCHAIN_SERVICE_NAME = "@getmagical/mcp-cli";
8268
- var DEFAULT_CLI_DIST_TAG = "latest";
8269
- var DEFAULT_CLI_NPM_REGISTRY_URL = "https://registry.npmjs.org/";
8270
- var CLI_CONFIG_DIRECTORY_NAME = "magical-mcp-cli";
8271
- var CLI_ACCESS_TOKEN_FILE_NAME = "access-token.txt";
8272
- var CLI_STATE_FILE_NAME = "state.json";
8273
- var CLI_SETTINGS_FILE_NAME = "settings.json";
8274
- var CLI_REFRESH_TOKEN_FILE_NAME = "refresh-tokens.json";
8275
- function resolvePlatformConfigDirectory() {
8276
- const customConfigDirectory = process.env["MAGICAL_CLI_CONFIG_DIR"];
8277
- if (customConfigDirectory) {
8278
- return customConfigDirectory;
7296
+ const { code: legacyCode } = causeRecord;
7297
+ return isAppErrorCode(legacyCode) ? legacyCode : void 0;
7298
+ });
7299
+ }
7300
+ /** @deprecated Use statusCode instead. */
7301
+ get code() {
7302
+ return this.statusCode;
8279
7303
  }
8280
- if (process.platform === "darwin") {
8281
- return path.join(os.homedir(), "Library", "Application Support");
7304
+ static extractSuggestedActionFromCause(cause) {
7305
+ return _AppError.getInheritedCauseField(cause, (causeRecord) => {
7306
+ const { suggestedAction } = causeRecord;
7307
+ if (typeof suggestedAction !== "string") {
7308
+ return void 0;
7309
+ }
7310
+ const trimmedSuggestedAction = suggestedAction.trim();
7311
+ return trimmedSuggestedAction.length > 0 ? trimmedSuggestedAction : void 0;
7312
+ });
8282
7313
  }
8283
- if (process.platform === "win32") {
8284
- const appDataDirectory = process.env["APPDATA"];
8285
- return appDataDirectory ?? path.join(os.homedir(), "AppData", "Roaming");
7314
+ static applyStack(error, stack, internalFrames) {
7315
+ if (stack) {
7316
+ error.stack = stack;
7317
+ }
7318
+ error.stack &&= stripInternalFrames(error.stack, [
7319
+ ...INTERNAL_STACK_PATHS,
7320
+ ...internalFrames ?? []
7321
+ ]).join("\n");
8286
7322
  }
8287
- return process.env["XDG_CONFIG_HOME"] ?? path.join(os.homedir(), ".config");
7323
+ toApiError({ correlationId }) {
7324
+ return toUserFacingApiError({
7325
+ error: this,
7326
+ correlationId,
7327
+ statusCode: getStatusCodeForAppError(this)
7328
+ });
7329
+ }
7330
+ toGqlError({ correlationId }) {
7331
+ return toUserFacingGraphQLError({
7332
+ error: this,
7333
+ correlationId
7334
+ });
7335
+ }
7336
+ };
7337
+ function toAppError(error) {
7338
+ return error instanceof AppError ? error : new AppError(error);
8288
7339
  }
8289
- function resolveRefreshTokenStoreKind() {
8290
- return process.env["MAGICAL_CLI_REFRESH_TOKEN_STORE"] === "file" ? "file" : "keytar";
7340
+ function getStatusCodeForAppError(error) {
7341
+ const appError = toAppError(error);
7342
+ return getStatusCodeForAppErrorFromAppError(appError);
8291
7343
  }
8292
- function getRuntimeConfig() {
8293
- const configDirectory = path.join(
8294
- resolvePlatformConfigDirectory(),
8295
- CLI_CONFIG_DIRECTORY_NAME
8296
- );
8297
- return {
8298
- accessTokenFilePath: path.join(configDirectory, CLI_ACCESS_TOKEN_FILE_NAME),
8299
- cliDistTag: process.env["MAGICAL_CLI_DIST_TAG"] ?? DEFAULT_CLI_DIST_TAG,
8300
- magicalApiUrl: DEFAULT_MAGICAL_API_URL,
8301
- npmRegistryUrl: process.env["MAGICAL_CLI_NPM_REGISTRY_URL"] ?? DEFAULT_CLI_NPM_REGISTRY_URL,
8302
- refreshTokenFilePath: path.join(
8303
- configDirectory,
8304
- CLI_REFRESH_TOKEN_FILE_NAME
8305
- ),
8306
- refreshTokenStoreKind: resolveRefreshTokenStoreKind(),
8307
- stateFilePath: path.join(configDirectory, CLI_STATE_FILE_NAME),
8308
- workosApiUrl: DEFAULT_WORKOS_API_URL,
8309
- workosClientId: DEFAULT_WORKOS_CLIENT_ID,
8310
- keychainServiceName: DEFAULT_KEYCHAIN_SERVICE_NAME
8311
- };
7344
+ function toUserFacingApiError({ error, correlationId, statusCode }) {
7345
+ const appError = toAppError(error);
7346
+ return toUserFacingApiErrorFromAppError({
7347
+ appError,
7348
+ correlationId,
7349
+ statusCode
7350
+ });
8312
7351
  }
8313
- function requireWorkosClientId(config) {
8314
- return config.workosClientId;
7352
+ function toUserFacingGraphQLError({ error, correlationId }) {
7353
+ const appError = toAppError(error);
7354
+ return toUserFacingGraphQLErrorFromAppError({
7355
+ appError,
7356
+ correlationId
7357
+ });
8315
7358
  }
8316
7359
 
8317
- // src/settings.ts
8318
- import { mkdir, readFile, rm, writeFile } from "fs/promises";
8319
- import path2 from "path";
8320
-
8321
- // ../common/dist/src/stdlib/json.util.js
8322
- var import_ts_essentials = __toESM(require_dist(), 1);
8323
-
8324
7360
  // ../common/dist/src/stdlib/result.util.js
8325
- import { z as z3 } from "zod";
8326
-
8327
- // ../common/dist/src/stdlib/error-user-facing.js
8328
- var USER_FACING_STATUS_MESSAGES = /* @__PURE__ */ new Map([
8329
- [400, "Bad Request"],
8330
- [401, "Unauthorized"],
8331
- [403, "Forbidden"],
8332
- [404, "Not Found"],
8333
- [500, "Internal Server Error"],
8334
- [503, "Service Unavailable"]
8335
- ]);
8336
- var USER_FACING_DEFAULT_ACTIONS = /* @__PURE__ */ new Map([
8337
- [400, "Review the request payload and retry."],
8338
- [401, "Authenticate and retry the request."],
8339
- [403, "Verify your permissions and retry the request."],
8340
- [404, "Verify the requested resource exists and retry."],
8341
- [
8342
- 500,
8343
- "Retry the request. If this keeps happening, contact support and share the correlation ID."
8344
- ],
8345
- [
8346
- 503,
8347
- "Retry the request after a brief delay. If this keeps happening, contact support and share the correlation ID."
8348
- ]
8349
- ]);
8350
- var USER_FACING_FALLBACK_CODES = /* @__PURE__ */ new Map([
8351
- [400, "BAD_REQUEST"],
8352
- [401, "UNAUTHORIZED"],
8353
- [403, "FORBIDDEN"],
8354
- [404, "NOT_FOUND"],
8355
- [500, "INTERNAL_SERVER_ERROR"],
8356
- [503, "SERVICE_UNAVAILABLE"]
8357
- ]);
8358
- function isCustomerUsageError(appError) {
8359
- return appError.categories.includes("customer_usage");
8360
- }
8361
- function getStatusCodeFromAppErrorCode(code) {
8362
- if (typeof code !== "number" || !Number.isInteger(code)) {
8363
- return void 0;
7361
+ var Result;
7362
+ (function(Result2) {
7363
+ function partition(responses) {
7364
+ const oks = responses.filter((resp) => resp._tag === "Ok").map((resp) => resp.value);
7365
+ const errs = responses.filter((resp) => resp._tag === "Err").map((resp) => resp.error);
7366
+ return [oks, errs];
8364
7367
  }
8365
- if (code >= 400 && code <= 599) {
8366
- return code;
7368
+ Result2.partition = partition;
7369
+ async function promiseAllAndPartition(promises) {
7370
+ const results = await Promise.all(promises);
7371
+ return partition(results);
8367
7372
  }
8368
- return void 0;
8369
- }
8370
- function getStatusFamilyFallbackCode(statusCode) {
8371
- if (statusCode >= 400 && statusCode <= 499) {
8372
- return 400;
7373
+ Result2.promiseAllAndPartition = promiseAllAndPartition;
7374
+ function unwrapOrThrow(result) {
7375
+ if (isErr(result)) {
7376
+ throw result.error;
7377
+ }
7378
+ return result.value;
8373
7379
  }
8374
- return 500;
8375
- }
8376
- function getStatusMessage(statusCode) {
8377
- const directMessage = USER_FACING_STATUS_MESSAGES.get(statusCode);
8378
- if (directMessage !== void 0) {
8379
- return directMessage;
7380
+ Result2.unwrapOrThrow = unwrapOrThrow;
7381
+ async function all(promises) {
7382
+ const results = await fromThrowable(async () => Promise.all(promises.map(async (promise) => {
7383
+ const result = await promise;
7384
+ if (isErr(result)) {
7385
+ throw result.error;
7386
+ }
7387
+ return result;
7388
+ })), "unknown-error");
7389
+ if (isErr(results)) {
7390
+ return ErrFromThrowable(results.error.cause);
7391
+ }
7392
+ return Ok(results.value.map((r) => r.value));
8380
7393
  }
8381
- return getStatusFamilyFallbackCode(statusCode) === 400 ? "Bad Request" : "Internal Server Error";
7394
+ Result2.all = all;
7395
+ function andThenSync(fnFirst, ...fns) {
7396
+ let result = fnFirst();
7397
+ const values = [];
7398
+ for (const fn of fns) {
7399
+ if (isErr(result)) {
7400
+ return result;
7401
+ }
7402
+ values.unshift(result.value);
7403
+ result = fn(...values);
7404
+ }
7405
+ return result;
7406
+ }
7407
+ Result2.andThenSync = andThenSync;
7408
+ async function andThen(fnFirst, ...fns) {
7409
+ let result = await fnFirst();
7410
+ const values = [];
7411
+ for (const fn of fns) {
7412
+ if (isErr(result)) {
7413
+ return result;
7414
+ }
7415
+ values.unshift(result.value);
7416
+ result = await fn(...values);
7417
+ }
7418
+ return result;
7419
+ }
7420
+ Result2.andThen = andThen;
7421
+ })(Result || (Result = {}));
7422
+ function Ok(value) {
7423
+ if (arguments.length === 0) {
7424
+ return {
7425
+ _tag: "Ok",
7426
+ value: void 0
7427
+ };
7428
+ }
7429
+ return {
7430
+ _tag: "Ok",
7431
+ value
7432
+ };
8382
7433
  }
8383
- function getDefaultSuggestedAction(statusCode) {
8384
- const directAction = USER_FACING_DEFAULT_ACTIONS.get(statusCode);
8385
- if (directAction !== void 0) {
8386
- return directAction;
7434
+ function Err(error) {
7435
+ return {
7436
+ _tag: "Err",
7437
+ error: new AppError(error)
7438
+ };
7439
+ }
7440
+ function ErrFromThrowable(error) {
7441
+ return {
7442
+ _tag: "Err",
7443
+ error
7444
+ };
7445
+ }
7446
+ function isErr(result) {
7447
+ return result._tag === "Err";
7448
+ }
7449
+ function fromThrowable(fn, errorType, errorInfo) {
7450
+ try {
7451
+ const result = fn();
7452
+ if (result && typeof result.then === "function") {
7453
+ return result.then((value) => Ok(value)).catch((err) => Err({
7454
+ ...errorInfo,
7455
+ type: errorType,
7456
+ cause: err
7457
+ }));
7458
+ }
7459
+ return Ok(result);
7460
+ } catch (err) {
7461
+ return Err({
7462
+ ...errorInfo,
7463
+ type: errorType,
7464
+ cause: err
7465
+ });
8387
7466
  }
8388
- return getStatusFamilyFallbackCode(statusCode) === 400 ? "Review the request payload and retry." : "Retry the request. If this keeps happening, contact support and share the correlation ID.";
8389
7467
  }
8390
- function getFallbackErrorCode(statusCode) {
8391
- const directCode = USER_FACING_FALLBACK_CODES.get(statusCode);
8392
- if (directCode !== void 0) {
8393
- return directCode;
7468
+
7469
+ // ../common/dist/src/stdlib/json.util.js
7470
+ function safeJsonParse(json) {
7471
+ try {
7472
+ return Ok(JSON.parse(json));
7473
+ } catch (error) {
7474
+ console.warn("Failed to parse JSON", { error, json });
7475
+ return Err({ type: "invalid-json", cause: error, json });
8394
7476
  }
8395
- return getStatusFamilyFallbackCode(statusCode) === 400 ? "BAD_REQUEST" : "INTERNAL_SERVER_ERROR";
8396
7477
  }
8397
- function shouldExposeMessage({ appError, statusCode }) {
8398
- if (statusCode >= 500) {
8399
- return false;
8400
- }
8401
- return isCustomerUsageError(appError);
7478
+
7479
+ // ../mcp-registry/src/operation-specs.ts
7480
+ import { z as z2 } from "zod";
7481
+
7482
+ // ../mcp-registry/src/operation-spec.ts
7483
+ function stripLeadingGraphqlComments(document) {
7484
+ return document.replace(/^(?:\s*#.*\n)+/u, "").trimStart();
8402
7485
  }
8403
- function resolveApiMessage({ appError, statusCode }) {
8404
- if (!shouldExposeMessage({ appError, statusCode })) {
8405
- return getStatusMessage(statusCode);
7486
+ function assertDocumentMatchesOperation({
7487
+ document,
7488
+ kind,
7489
+ operationName
7490
+ }) {
7491
+ const normalizedDocument = stripLeadingGraphqlComments(document);
7492
+ const match = /^(?<actualKind>query|mutation)\s+(?<actualOperationName>[_A-Za-z][_0-9A-Za-z]*)/u.exec(
7493
+ normalizedDocument
7494
+ );
7495
+ const actualKind = match?.groups?.["actualKind"];
7496
+ const actualOperationName = match?.groups?.["actualOperationName"];
7497
+ if (!actualKind || !actualOperationName) {
7498
+ throw new Error(
7499
+ `Operation "${operationName}" is missing a top-level GraphQL ${kind} definition.`
7500
+ );
8406
7501
  }
8407
- const trimmedMessage = appError.message.trim();
8408
- if (trimmedMessage.length > 0) {
8409
- return trimmedMessage;
7502
+ if (actualKind !== kind || actualOperationName !== operationName) {
7503
+ throw new Error(
7504
+ `Operation "${operationName}" does not match its GraphQL document (${actualKind} ${actualOperationName}).`
7505
+ );
8410
7506
  }
8411
- return getStatusMessage(statusCode);
8412
7507
  }
8413
- function resolveApiErrorCode({ appError, statusCode }) {
8414
- if (!shouldExposeMessage({ appError, statusCode })) {
8415
- return getFallbackErrorCode(statusCode);
8416
- }
8417
- return normalizeUserFacingErrorCode({
8418
- type: appError.type,
8419
- fallbackCode: getFallbackErrorCode(statusCode)
8420
- });
7508
+ function createOperationSpec(spec) {
7509
+ assertDocumentMatchesOperation(spec);
7510
+ return spec;
8421
7511
  }
8422
- function resolveSuggestedAction({ appError, statusCode }) {
8423
- const trimmedSuggestedAction = appError.suggestedAction?.trim();
8424
- if (shouldExposeMessage({ appError, statusCode }) && trimmedSuggestedAction) {
8425
- return trimmedSuggestedAction;
8426
- }
8427
- return getDefaultSuggestedAction(statusCode);
7512
+
7513
+ // ../mcp-registry/src/operation-specs.ts
7514
+ function stringOption({
7515
+ description,
7516
+ flagName,
7517
+ inputKey,
7518
+ required = false
7519
+ }) {
7520
+ return {
7521
+ description,
7522
+ flagName,
7523
+ inputKey,
7524
+ required,
7525
+ valueType: "string"
7526
+ };
8428
7527
  }
8429
- function getZodIssuesFromCause(cause, maxDepth = 10) {
8430
- if (maxDepth < 0 || typeof cause !== "object" || cause === null) {
8431
- return void 0;
8432
- }
8433
- if ("issues" in cause && Array.isArray(cause.issues)) {
8434
- return cause.issues;
8435
- }
8436
- if ("cause" in cause) {
8437
- return getZodIssuesFromCause(cause.cause, maxDepth - 1);
8438
- }
8439
- return void 0;
7528
+ function numberOption({
7529
+ description,
7530
+ flagName,
7531
+ inputKey,
7532
+ required = false
7533
+ }) {
7534
+ return {
7535
+ description,
7536
+ flagName,
7537
+ inputKey,
7538
+ required,
7539
+ valueType: "number"
7540
+ };
8440
7541
  }
8441
- function toUserFacingDetailsValue(value, depth) {
8442
- if (depth < 0) {
8443
- return void 0;
8444
- }
8445
- if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
8446
- return value;
8447
- }
8448
- if (Array.isArray(value)) {
8449
- const serializedValues = value.map((item) => toUserFacingDetailsValue(item, depth - 1)).filter((item) => item !== void 0);
8450
- return serializedValues;
8451
- }
8452
- if (value && typeof value === "object") {
8453
- const serializedObject = {};
8454
- for (const [key, itemValue] of Object.entries(value)) {
8455
- const serializedItemValue = toUserFacingDetailsValue(itemValue, depth - 1);
8456
- if (serializedItemValue !== void 0) {
8457
- serializedObject[key] = serializedItemValue;
8458
- }
7542
+ function booleanOption({
7543
+ description,
7544
+ flagName,
7545
+ inputKey
7546
+ }) {
7547
+ return {
7548
+ description,
7549
+ flagName,
7550
+ inputKey,
7551
+ valueType: "boolean"
7552
+ };
7553
+ }
7554
+ function stringArrayOption({
7555
+ description,
7556
+ flagName,
7557
+ inputKey,
7558
+ required = false
7559
+ }) {
7560
+ return {
7561
+ description,
7562
+ flagName,
7563
+ inputKey,
7564
+ required,
7565
+ valueHint: "comma-separated",
7566
+ valueType: "string-array"
7567
+ };
7568
+ }
7569
+ function jsonOption({
7570
+ description,
7571
+ flagName,
7572
+ inputKey,
7573
+ required = false
7574
+ }) {
7575
+ return {
7576
+ description,
7577
+ flagName,
7578
+ inputKey,
7579
+ required,
7580
+ valueHint: "JSON",
7581
+ valueType: "json"
7582
+ };
7583
+ }
7584
+ var jsonObjectSchema = z2.record(z2.string(), z2.unknown());
7585
+ var agentBrowserProviderOptionsSelection = ` browserbase {
7586
+ advancedStealth
7587
+ contextId
7588
+ extensionId
7589
+ instanceSize
7590
+ blockAds
7591
+ solveCaptchas
7592
+ viewport {
7593
+ width
7594
+ height
7595
+ }
7596
+ }
7597
+ agentCore {
7598
+ viewport {
7599
+ width
7600
+ height
7601
+ }
7602
+ enableWebBotAuth
7603
+ }
7604
+ local {
7605
+ viewport {
7606
+ width
7607
+ height
7608
+ }
7609
+ }
7610
+ hyperbrowser {
7611
+ viewport {
7612
+ width
7613
+ height
7614
+ }
7615
+ }
7616
+ steel {
7617
+ extensionIds
7618
+ region
7619
+ solveCaptcha
7620
+ viewport {
7621
+ width
7622
+ height
7623
+ }
7624
+ }`;
7625
+ var agentEnvironmentOptionsSelection = ` environmentOptions {
7626
+ __typename
7627
+ ... on AgentConfig_environmentOptions_Browser {
7628
+ environment
7629
+ maxMediaToIncludeInMemory
7630
+ saveAuthCookiesAfterRun
7631
+ startingUrl
7632
+ browserProvider
7633
+ browserProviderOptions {
7634
+ ${agentBrowserProviderOptionsSelection}
7635
+ }
7636
+ }
7637
+ ... on AgentConfig_environmentOptions_Browsercoordinates {
7638
+ environment
7639
+ maxMediaToIncludeInMemory
7640
+ saveAuthCookiesAfterRun
7641
+ startingUrl
7642
+ browserProvider
7643
+ browserProviderOptions {
7644
+ ${agentBrowserProviderOptionsSelection}
7645
+ }
7646
+ }
7647
+ ... on AgentConfig_environmentOptions_Desktop {
7648
+ environment
7649
+ browserProvider
7650
+ browserProviderOptions {
7651
+ ${agentBrowserProviderOptionsSelection}
7652
+ }
7653
+ maxMediaToIncludeInMemory
7654
+ startingUrl
7655
+ useCopyPasteForTyping
7656
+ }
7657
+ ... on AgentConfig_environmentOptions_Desktopapp {
7658
+ environment
7659
+ maxMediaToIncludeInMemory
7660
+ }
7661
+ ... on AgentConfig_environmentOptions_Minimal {
7662
+ environment
7663
+ }
7664
+ }`;
7665
+ var agentLimitationsSelection = ` limitations {
7666
+ maxDurationSeconds
7667
+ maxToolCalls
7668
+ allowedUrlRegexes
7669
+ }`;
7670
+ var operationSpecs = [
7671
+ createOperationSpec({
7672
+ operationName: "GetAgents",
7673
+ kind: "query",
7674
+ inputSchema: z2.object({
7675
+ ids: z2.array(z2.string().min(1)).min(1)
7676
+ }),
7677
+ cli: {
7678
+ name: "get-agents",
7679
+ path: ["agents", "get"],
7680
+ description: "Fetch one or more agents with config and schema fields.",
7681
+ resultKey: "agents",
7682
+ options: [
7683
+ stringArrayOption({
7684
+ inputKey: "ids",
7685
+ flagName: "ids",
7686
+ description: "Agent IDs.",
7687
+ required: true
7688
+ })
7689
+ ]
7690
+ },
7691
+ mcp: { fileName: "agents.graphql" },
7692
+ document: `# Query to fetch multiple agents with all fields
7693
+ # Includes nested environment and limitation config fields
7694
+ query GetAgents($ids: [ID!]!) {
7695
+ agents(ids: $ids) {
7696
+ id
7697
+ name
7698
+ description
7699
+ instructions
7700
+ organizationId
7701
+ createdAt
7702
+ updatedAt
7703
+ sourceAgentId
7704
+ inputSchema
7705
+ outputSchema
7706
+ config {
7707
+ type
7708
+ language
7709
+ model
7710
+ tools
7711
+ maxSessionMessages
7712
+ ${agentEnvironmentOptionsSelection}
7713
+ ${agentLimitationsSelection}
7714
+ commonParametersSchema
7715
+ taskQueue
7716
+ waitUponQueueing
7717
+ queueableAgentIds
7718
+ systemPrompt
7719
+ additionalSystemPrompt
7720
+ ignoreUnstableSessionState
8459
7721
  }
8460
- if (Object.keys(serializedObject).length === 0) {
8461
- return void 0;
7722
+ childAgentIds
8462
7723
  }
8463
- return serializedObject;
8464
- }
8465
- return void 0;
8466
- }
8467
- function resolveApiDetails({ appError, statusCode }) {
8468
- if (!shouldExposeMessage({ appError, statusCode })) {
8469
- return void 0;
8470
- }
8471
- const zodIssues = getZodIssuesFromCause(appError.cause);
8472
- if (zodIssues && zodIssues.length > 0) {
8473
- return {
8474
- validationErrors: zodIssues.map((issue) => ({
8475
- path: Array.isArray(issue.path) ? issue.path.map(String).join(".") : "",
8476
- message: typeof issue.message === "string" ? issue.message : "Invalid value",
8477
- ...typeof issue.code === "string" ? { code: issue.code } : {}
8478
- }))
8479
- };
8480
- }
8481
- const rawDetails = toUserFacingDetailsValue(appError.details, 4);
8482
- if (rawDetails && typeof rawDetails === "object" && !Array.isArray(rawDetails) && Object.keys(rawDetails).length > 0) {
8483
- return rawDetails;
7724
+ }`
7725
+ }),
7726
+ createOperationSpec({
7727
+ operationName: "GetAgentVersion",
7728
+ kind: "query",
7729
+ inputSchema: z2.object({
7730
+ agentId: z2.string().min(1),
7731
+ versionId: z2.string().min(1)
7732
+ }),
7733
+ cli: {
7734
+ name: "get-agent-version",
7735
+ path: ["agents", "versions", "get"],
7736
+ description: "Fetch one saved version for an agent.",
7737
+ resultKey: "agentVersion",
7738
+ options: [
7739
+ stringOption({
7740
+ inputKey: "agentId",
7741
+ flagName: "agent-id",
7742
+ description: "Agent ID.",
7743
+ required: true
7744
+ }),
7745
+ stringOption({
7746
+ inputKey: "versionId",
7747
+ flagName: "version-id",
7748
+ description: "Agent version ID.",
7749
+ required: true
7750
+ })
7751
+ ]
7752
+ },
7753
+ mcp: { fileName: "agentVersion.graphql" },
7754
+ document: `# Query to fetch a specific saved version for an agent
7755
+ query GetAgentVersion($agentId: ID!, $versionId: ID!) {
7756
+ agentVersion(agentId: $agentId, versionId: $versionId) {
7757
+ id
7758
+ agentId
7759
+ sequence
7760
+ name
7761
+ description
7762
+ instructions
7763
+ instructionsMode
7764
+ instructionsDoc
7765
+ updaterUserId
7766
+ createdAt
7767
+ updatedAt
7768
+ inputSchema
7769
+ outputSchema
7770
+ config {
7771
+ type
7772
+ language
7773
+ model
7774
+ tools
7775
+ maxSessionMessages
7776
+ ${agentEnvironmentOptionsSelection}
7777
+ ${agentLimitationsSelection}
7778
+ commonParametersSchema
7779
+ taskQueue
7780
+ waitUponQueueing
7781
+ queueableAgentIds
7782
+ systemPrompt
7783
+ additionalSystemPrompt
7784
+ ignoreUnstableSessionState
7785
+ }
7786
+ isCurrent
8484
7787
  }
8485
- return void 0;
8486
- }
8487
- function getGraphQLErrorCodeFromAppErrorCode(code) {
8488
- if (code === 400) {
8489
- return "BAD_USER_INPUT";
7788
+ }`
7789
+ }),
7790
+ createOperationSpec({
7791
+ operationName: "GetAgentVersions",
7792
+ kind: "query",
7793
+ inputSchema: z2.object({
7794
+ agentId: z2.string().min(1)
7795
+ }),
7796
+ cli: {
7797
+ name: "get-agent-versions",
7798
+ path: ["agents", "versions", "list"],
7799
+ description: "Fetch version history for an agent.",
7800
+ resultKey: "agentVersions",
7801
+ options: [
7802
+ stringOption({
7803
+ inputKey: "agentId",
7804
+ flagName: "agent-id",
7805
+ description: "Agent ID.",
7806
+ required: true
7807
+ })
7808
+ ]
7809
+ },
7810
+ mcp: { fileName: "agentVersions.graphql" },
7811
+ document: `# Query to fetch version history metadata for an agent
7812
+ query GetAgentVersions($agentId: ID!) {
7813
+ agentVersions(agentId: $agentId) {
7814
+ id
7815
+ sequence
7816
+ name
7817
+ description
7818
+ updaterUserId
7819
+ createdAt
7820
+ updatedAt
7821
+ isCurrent
8490
7822
  }
8491
- if (code === 401) {
8492
- return "UNAUTHORIZED";
7823
+ }`
7824
+ }),
7825
+ createOperationSpec({
7826
+ operationName: "DiffAgentVersion",
7827
+ kind: "query",
7828
+ inputSchema: z2.object({
7829
+ agentId: z2.string().min(1),
7830
+ versionId: z2.string().min(1),
7831
+ compareVersionId: z2.string().min(1).optional()
7832
+ }),
7833
+ cli: {
7834
+ name: "diff-agent-version",
7835
+ path: ["agents", "versions", "diff"],
7836
+ description: "Diff one agent version against another version or the current latest version.",
7837
+ resultKey: "agentVersionDiff",
7838
+ options: [
7839
+ stringOption({
7840
+ inputKey: "agentId",
7841
+ flagName: "agent-id",
7842
+ description: "Agent ID.",
7843
+ required: true
7844
+ }),
7845
+ stringOption({
7846
+ inputKey: "versionId",
7847
+ flagName: "version-id",
7848
+ description: "Source agent version ID.",
7849
+ required: true
7850
+ }),
7851
+ stringOption({
7852
+ inputKey: "compareVersionId",
7853
+ flagName: "compare-version-id",
7854
+ description: "Optional target version ID. Defaults to the current latest version."
7855
+ })
7856
+ ]
7857
+ },
7858
+ mcp: { fileName: "agentVersionDiff.graphql" },
7859
+ document: `# Query to diff one agent version against another or the current latest version
7860
+ query DiffAgentVersion(
7861
+ $agentId: ID!
7862
+ $versionId: ID!
7863
+ $compareVersionId: ID
7864
+ ) {
7865
+ agentVersionDiff(
7866
+ agentId: $agentId
7867
+ versionId: $versionId
7868
+ compareVersionId: $compareVersionId
7869
+ ) {
7870
+ agentId
7871
+ fromVersionId
7872
+ toVersionId
7873
+ hasChanges
7874
+ changes {
7875
+ field
7876
+ oldValue
7877
+ newValue
7878
+ }
8493
7879
  }
8494
- if (code === 403) {
8495
- return "FORBIDDEN";
7880
+ }`
7881
+ }),
7882
+ createOperationSpec({
7883
+ operationName: "GetAgentRun",
7884
+ kind: "query",
7885
+ inputSchema: z2.object({
7886
+ id: z2.string().min(1)
7887
+ }),
7888
+ cli: {
7889
+ name: "get-agent-run",
7890
+ path: ["agent-runs", "get"],
7891
+ description: "Fetch a single agent run.",
7892
+ resultKey: "agentRun",
7893
+ options: [
7894
+ stringOption({
7895
+ inputKey: "id",
7896
+ flagName: "id",
7897
+ description: "Agent run ID.",
7898
+ required: true
7899
+ })
7900
+ ]
7901
+ },
7902
+ mcp: { fileName: "agentRun.graphql" },
7903
+ document: `# Query a single agent run
7904
+ query GetAgentRun($id: ID!) {
7905
+ agentRun(id: $id) {
7906
+ id
7907
+ agentVersionId
7908
+ agentName
7909
+ status
7910
+ statusDetail
7911
+ isChildAgent
7912
+ input
7913
+ startedAt
7914
+ finishedAt
7915
+ parentAgentRunId
8496
7916
  }
8497
- if (code === 404) {
8498
- return "NOT_FOUND";
7917
+ }`
7918
+ }),
7919
+ createOperationSpec({
7920
+ operationName: "GetAutomationAgents",
7921
+ kind: "query",
7922
+ inputSchema: z2.object({
7923
+ ids: z2.array(z2.string().min(1)).min(1)
7924
+ }),
7925
+ cli: {
7926
+ name: "get-automation-agents",
7927
+ path: ["automations", "agents"],
7928
+ description: "Fetch the agents attached to one or more automations.",
7929
+ resultKey: "automationAgents",
7930
+ options: [
7931
+ stringArrayOption({
7932
+ inputKey: "ids",
7933
+ flagName: "ids",
7934
+ description: "Automation IDs.",
7935
+ required: true
7936
+ })
7937
+ ]
7938
+ },
7939
+ mcp: { fileName: "automationAgents.graphql" },
7940
+ document: `# Query automation agent relationships with flat agent fields only
7941
+ # Excludes nested agent config and schemas for MCP tool simplicity
7942
+ query GetAutomationAgents($ids: [ID!]!) {
7943
+ automationAgents(ids: $ids) {
7944
+ automationId
7945
+ agentId
7946
+ isTrigger
7947
+ agent {
7948
+ id
7949
+ name
7950
+ description
7951
+ instructions
7952
+ organizationId
7953
+ createdAt
7954
+ updatedAt
7955
+ sourceAgentId
7956
+ childAgentIds
7957
+ }
8499
7958
  }
8500
- if (code === 500) {
8501
- return "INTERNAL_SERVER_ERROR";
7959
+ }`
7960
+ }),
7961
+ createOperationSpec({
7962
+ operationName: "GetAutomationRun",
7963
+ kind: "query",
7964
+ inputSchema: z2.object({
7965
+ id: z2.string().min(1)
7966
+ }),
7967
+ cli: {
7968
+ name: "get-automation-run",
7969
+ path: ["automation-runs", "get"],
7970
+ description: "Fetch a single automation run.",
7971
+ resultKey: "automationRun",
7972
+ options: [
7973
+ stringOption({
7974
+ inputKey: "id",
7975
+ flagName: "id",
7976
+ description: "Automation run ID.",
7977
+ required: true
7978
+ })
7979
+ ]
7980
+ },
7981
+ mcp: { fileName: "automationRun.graphql" },
7982
+ document: `# Query a full automation run details payload
7983
+ query GetAutomationRun($id: ID!) {
7984
+ automationRun(id: $id) {
7985
+ id
7986
+ automationId
7987
+ parentAutomationRunId
7988
+ status
7989
+ statusDetail
7990
+ summary
7991
+ invocationType
7992
+ input
7993
+ additionalPrompt
7994
+ debugUrl
7995
+ createdAt
7996
+ startedAt
7997
+ pausedAt
7998
+ finishedAt
8502
7999
  }
8503
- return void 0;
8504
- }
8505
- function resolveGraphQLErrorCode(appError) {
8506
- const codeFromAppErrorCode = getGraphQLErrorCodeFromAppErrorCode(appError.statusCode);
8507
- if (codeFromAppErrorCode !== void 0) {
8508
- return codeFromAppErrorCode;
8000
+ }`
8001
+ }),
8002
+ createOperationSpec({
8003
+ operationName: "GetAutomationRunAgentRuns",
8004
+ kind: "query",
8005
+ inputSchema: z2.object({
8006
+ automationRunId: z2.string().min(1)
8007
+ }),
8008
+ cli: {
8009
+ name: "get-automation-run-agent-runs",
8010
+ path: ["automation-runs", "agent-runs"],
8011
+ description: "Fetch ordered agent runs for an automation run.",
8012
+ resultKey: "automationRunAgentRuns",
8013
+ options: [
8014
+ stringOption({
8015
+ inputKey: "automationRunId",
8016
+ flagName: "automation-run-id",
8017
+ description: "Automation run ID.",
8018
+ required: true
8019
+ })
8020
+ ]
8021
+ },
8022
+ mcp: { fileName: "automationRunAgentRuns.graphql" },
8023
+ document: `# Query ordered agent runs for an automation run
8024
+ query GetAutomationRunAgentRuns($automationRunId: ID!) {
8025
+ automationRunAgentRuns(automationRunId: $automationRunId) {
8026
+ id
8027
+ agentVersionId
8028
+ agentName
8029
+ status
8030
+ statusDetail
8031
+ isChildAgent
8032
+ input
8033
+ startedAt
8034
+ finishedAt
8035
+ parentAgentRunId
8509
8036
  }
8510
- const normalizedErrorType = appError.type.toLowerCase();
8511
- if (normalizedErrorType.includes("unauthorized")) {
8512
- return "UNAUTHORIZED";
8037
+ }`
8038
+ }),
8039
+ createOperationSpec({
8040
+ operationName: "GetAutomationRunIterations",
8041
+ kind: "query",
8042
+ inputSchema: z2.object({
8043
+ automationRunId: z2.string().min(1),
8044
+ agentRunId: z2.string().min(1).optional(),
8045
+ limit: z2.number().int().positive().optional(),
8046
+ reverse: z2.boolean().optional()
8047
+ }),
8048
+ cli: {
8049
+ name: "get-automation-run-iterations",
8050
+ path: ["automation-runs", "iterations"],
8051
+ description: "Fetch ordered iterations for an automation run.",
8052
+ resultKey: "automationRunIterations",
8053
+ options: [
8054
+ stringOption({
8055
+ inputKey: "automationRunId",
8056
+ flagName: "automation-run-id",
8057
+ description: "Automation run ID.",
8058
+ required: true
8059
+ }),
8060
+ stringOption({
8061
+ inputKey: "agentRunId",
8062
+ flagName: "agent-run-id",
8063
+ description: "Optional agent run ID to filter by."
8064
+ }),
8065
+ numberOption({
8066
+ inputKey: "limit",
8067
+ flagName: "limit",
8068
+ description: "Maximum number of iterations to return."
8069
+ }),
8070
+ booleanOption({
8071
+ inputKey: "reverse",
8072
+ flagName: "reverse",
8073
+ description: "Return newest iterations first."
8074
+ })
8075
+ ]
8076
+ },
8077
+ mcp: { fileName: "automationRunIterations.graphql" },
8078
+ document: `# Query iterations for an automation run with optional filtering by agent run
8079
+ query GetAutomationRunIterations(
8080
+ $automationRunId: ID!
8081
+ $agentRunId: ID
8082
+ $limit: Int
8083
+ $reverse: Boolean
8084
+ ) {
8085
+ automationRunIterations(
8086
+ automationRunId: $automationRunId
8087
+ agentRunId: $agentRunId
8088
+ limit: $limit
8089
+ reverse: $reverse
8090
+ ) {
8091
+ id
8092
+ sequence
8093
+ agentRunId
8094
+ metadata
8095
+ startedAt
8096
+ finishedAt
8097
+ totalDurationMs
8098
+ llmResponseDurationMs
8099
+ withMarksScreenshotUrl
8100
+ withMarksMimeType
8101
+ memories {
8102
+ id
8103
+ type
8104
+ value
8105
+ sequence
8106
+ screenshotUrl
8107
+ screenshotMimeType
8108
+ }
8513
8109
  }
8514
- if (normalizedErrorType.includes("forbidden")) {
8515
- return "FORBIDDEN";
8110
+ }`
8111
+ }),
8112
+ createOperationSpec({
8113
+ operationName: "GetAutomationRuns",
8114
+ kind: "query",
8115
+ inputSchema: z2.object({
8116
+ automationId: z2.string().min(1),
8117
+ status: z2.array(z2.string().min(1)).optional(),
8118
+ invocationType: z2.array(z2.string().min(1)).optional(),
8119
+ limit: z2.number().int().positive().optional(),
8120
+ page: z2.number().int().positive().optional()
8121
+ }),
8122
+ cli: {
8123
+ name: "get-automation-runs",
8124
+ path: ["automation-runs", "list"],
8125
+ description: "Fetch automation run history.",
8126
+ resultKey: "automationRuns",
8127
+ options: [
8128
+ stringOption({
8129
+ inputKey: "automationId",
8130
+ flagName: "automation-id",
8131
+ description: "Automation ID.",
8132
+ required: true
8133
+ }),
8134
+ stringArrayOption({
8135
+ inputKey: "status",
8136
+ flagName: "status",
8137
+ description: "Optional run statuses."
8138
+ }),
8139
+ stringArrayOption({
8140
+ inputKey: "invocationType",
8141
+ flagName: "invocation-type",
8142
+ description: "Optional invocation types."
8143
+ }),
8144
+ numberOption({
8145
+ inputKey: "limit",
8146
+ flagName: "limit",
8147
+ description: "Maximum number of runs to return."
8148
+ }),
8149
+ numberOption({
8150
+ inputKey: "page",
8151
+ flagName: "page",
8152
+ description: "Page number."
8153
+ })
8154
+ ]
8155
+ },
8156
+ mcp: { fileName: "automationRuns.graphql" },
8157
+ document: `# Query automation run history for a specific automation with optional filters
8158
+ query GetAutomationRuns(
8159
+ $automationId: ID!
8160
+ $status: [RunStatus!]
8161
+ $invocationType: [InvocationType!]
8162
+ $limit: Int
8163
+ $page: Int
8164
+ ) {
8165
+ automationRuns(
8166
+ automationId: $automationId
8167
+ status: $status
8168
+ invocationType: $invocationType
8169
+ limit: $limit
8170
+ page: $page
8171
+ ) {
8172
+ id
8173
+ automationId
8174
+ parentAutomationRunId
8175
+ status
8176
+ statusDetail
8177
+ invocationType
8178
+ summary
8179
+ createdAt
8180
+ startedAt
8181
+ pausedAt
8182
+ finishedAt
8516
8183
  }
8517
- if (normalizedErrorType.includes("not-found")) {
8518
- return "NOT_FOUND";
8184
+ }`
8185
+ }),
8186
+ createOperationSpec({
8187
+ operationName: "ListAutomations",
8188
+ kind: "query",
8189
+ inputSchema: z2.object({
8190
+ limit: z2.number().positive().optional(),
8191
+ order: jsonObjectSchema.optional(),
8192
+ where: jsonObjectSchema.optional()
8193
+ }),
8194
+ cli: {
8195
+ name: "list-automations",
8196
+ path: ["automations", "list"],
8197
+ description: "List automations with optional filters.",
8198
+ resultKey: "automations",
8199
+ options: [
8200
+ numberOption({
8201
+ inputKey: "limit",
8202
+ flagName: "limit",
8203
+ description: "Maximum number of automations to return."
8204
+ }),
8205
+ jsonOption({
8206
+ inputKey: "order",
8207
+ flagName: "order-json",
8208
+ description: "GraphQL order object."
8209
+ }),
8210
+ jsonOption({
8211
+ inputKey: "where",
8212
+ flagName: "where-json",
8213
+ description: "GraphQL filter object."
8214
+ })
8215
+ ]
8216
+ },
8217
+ mcp: { fileName: "listAutomations.graphql" },
8218
+ document: `# Query to list automations with flat fields only (no nested objects)
8219
+ # Excludes config and agents for MCP tool simplicity
8220
+ query ListAutomations(
8221
+ $limit: Float
8222
+ $order: AutomationsOrder
8223
+ $where: AutomationsWhereInput
8224
+ ) {
8225
+ automations(limit: $limit, order: $order, where: $where) {
8226
+ id
8227
+ name
8228
+ organizationId
8229
+ createdAt
8230
+ updatedAt
8231
+ environment
8232
+ lastSavedAt
8233
+ publishedVersionId
8234
+ draftVersionId
8519
8235
  }
8520
- if (isCustomerUsageError(appError)) {
8521
- return "BAD_USER_INPUT";
8236
+ }`
8237
+ }),
8238
+ createOperationSpec({
8239
+ operationName: "GetAutomations",
8240
+ kind: "query",
8241
+ inputSchema: z2.object({
8242
+ ids: z2.array(z2.string().min(1)).min(1)
8243
+ }),
8244
+ cli: {
8245
+ name: "get-automations",
8246
+ path: ["automations", "get"],
8247
+ description: "Fetch one or more automations by IDs.",
8248
+ resultKey: "automations",
8249
+ options: [
8250
+ stringArrayOption({
8251
+ inputKey: "ids",
8252
+ flagName: "ids",
8253
+ description: "Automation IDs.",
8254
+ required: true
8255
+ })
8256
+ ]
8257
+ },
8258
+ mcp: { fileName: "automations.graphql" },
8259
+ document: `# Query to fetch automations with flat fields only (no nested objects)
8260
+ # Excludes config and agents for MCP tool simplicity
8261
+ query GetAutomations($ids: [ID!]!) {
8262
+ automations(ids: $ids) {
8263
+ id
8264
+ name
8265
+ organizationId
8266
+ createdAt
8267
+ updatedAt
8268
+ environment
8269
+ lastSavedAt
8270
+ publishedVersionId
8271
+ draftVersionId
8522
8272
  }
8523
- return "INTERNAL_SERVER_ERROR";
8524
- }
8525
- function getStatusCodeFromGraphQLErrorCode(code) {
8526
- switch (code) {
8527
- case "BAD_USER_INPUT": {
8528
- return 400;
8529
- }
8530
- case "UNAUTHORIZED": {
8531
- return 401;
8532
- }
8533
- case "FORBIDDEN": {
8534
- return 403;
8535
- }
8536
- case "NOT_FOUND": {
8537
- return 404;
8538
- }
8539
- case "INTERNAL_SERVER_ERROR": {
8540
- return 500;
8541
- }
8273
+ }`
8274
+ }),
8275
+ createOperationSpec({
8276
+ operationName: "GetAvailableCommands",
8277
+ kind: "query",
8278
+ inputSchema: z2.object({
8279
+ env: z2.string().min(1)
8280
+ }),
8281
+ cli: {
8282
+ name: "get-available-commands",
8283
+ path: ["catalog", "commands"],
8284
+ description: "Fetch available command definitions by environment.",
8285
+ resultKey: "availableCommands",
8286
+ options: [
8287
+ stringOption({
8288
+ inputKey: "env",
8289
+ flagName: "env",
8290
+ description: "Environment name.",
8291
+ required: true
8292
+ })
8293
+ ]
8294
+ },
8295
+ mcp: { fileName: "availableCommands.graphql" },
8296
+ document: `# Query to fetch available command definitions by environment
8297
+ query GetAvailableCommands($env: AvailableCommandsEnv!) {
8298
+ availableCommands(env: $env) {
8299
+ id
8300
+ description
8301
+ inputSchema
8542
8302
  }
8543
- }
8544
- function getGraphQLErrorMessage({ code, apiMessage }) {
8545
- switch (code) {
8546
- case "BAD_USER_INPUT":
8547
- case "NOT_FOUND":
8548
- case "INTERNAL_SERVER_ERROR": {
8549
- return apiMessage;
8550
- }
8551
- case "UNAUTHORIZED": {
8552
- return "Unauthorized";
8303
+ }`
8304
+ }),
8305
+ createOperationSpec({
8306
+ operationName: "GetAvailableModels",
8307
+ kind: "query",
8308
+ inputSchema: z2.object({
8309
+ agentId: z2.string().min(1)
8310
+ }),
8311
+ cli: {
8312
+ name: "get-available-models",
8313
+ path: ["catalog", "models"],
8314
+ description: "Fetch available model definitions for an agent.",
8315
+ resultKey: "availableModels",
8316
+ options: [
8317
+ stringOption({
8318
+ inputKey: "agentId",
8319
+ flagName: "agent-id",
8320
+ description: "Agent ID.",
8321
+ required: true
8322
+ })
8323
+ ]
8324
+ },
8325
+ mcp: { fileName: "availableModels.graphql" },
8326
+ document: `# Query to fetch available model definitions and pools for a specific agent
8327
+ query GetAvailableModels($agentId: String!) {
8328
+ availableModels(agentId: $agentId) {
8329
+ availableModelPools {
8330
+ name
8331
+ poolId
8332
+ models {
8333
+ id
8334
+ name
8335
+ description
8336
+ status
8337
+ provider
8338
+ }
8553
8339
  }
8554
- case "FORBIDDEN": {
8555
- return "Forbidden";
8340
+ allAvailableModels {
8341
+ id
8342
+ name
8343
+ description
8344
+ status
8345
+ provider
8556
8346
  }
8557
8347
  }
8558
- }
8559
- function getGraphQLAppErrorCode({ code, apiCode }) {
8560
- if (code === "INTERNAL_SERVER_ERROR" || code === "UNAUTHORIZED" || code === "FORBIDDEN") {
8561
- return code;
8348
+ }`
8349
+ }),
8350
+ createOperationSpec({
8351
+ operationName: "GetAvailableTools",
8352
+ kind: "query",
8353
+ inputSchema: z2.object({
8354
+ env: z2.string().min(1),
8355
+ automationId: z2.string().min(1).optional()
8356
+ }),
8357
+ cli: {
8358
+ name: "get-available-tools",
8359
+ path: ["catalog", "tools"],
8360
+ description: "Fetch available tool definitions by environment.",
8361
+ resultKey: "availableTools",
8362
+ options: [
8363
+ stringOption({
8364
+ inputKey: "env",
8365
+ flagName: "env",
8366
+ description: "Environment name.",
8367
+ required: true
8368
+ }),
8369
+ stringOption({
8370
+ inputKey: "automationId",
8371
+ flagName: "automation-id",
8372
+ description: "Optional automation ID."
8373
+ })
8374
+ ]
8375
+ },
8376
+ mcp: { fileName: "availableTools.graphql" },
8377
+ document: `# Query to fetch available tool definitions by environment
8378
+ query GetAvailableTools($env: AvailableCommandsEnv!, $automationId: String) {
8379
+ availableTools(env: $env, automationId: $automationId) {
8380
+ id
8381
+ description
8382
+ inputSchema
8562
8383
  }
8563
- return apiCode;
8564
- }
8565
- function normalizeErrorCodeSegment(value) {
8566
- return value.trim().toUpperCase().replaceAll(/[^\dA-Z]+/gu, "_").replaceAll(/^_+/gu, "").replaceAll(/_+$/gu, "");
8567
- }
8568
- function getStatusCodeForAppErrorFromAppError(appError) {
8569
- const statusCodeFromCode = getStatusCodeFromAppErrorCode(appError.statusCode);
8570
- if (statusCodeFromCode !== void 0) {
8571
- return statusCodeFromCode;
8384
+ }`
8385
+ }),
8386
+ createOperationSpec({
8387
+ operationName: "CreateAutomation",
8388
+ kind: "mutation",
8389
+ inputSchema: z2.object({
8390
+ input: jsonObjectSchema
8391
+ }),
8392
+ cli: {
8393
+ name: "create-automation",
8394
+ path: ["automations", "create"],
8395
+ description: "Create a draft automation.",
8396
+ resultKey: "createAutomation",
8397
+ options: [
8398
+ jsonOption({
8399
+ inputKey: "input",
8400
+ flagName: "input-json",
8401
+ description: "CreateAutomationInput payload.",
8402
+ required: true
8403
+ })
8404
+ ]
8405
+ },
8406
+ mcp: { fileName: "createAutomation.graphql" },
8407
+ document: `# Mutation to create a draft automation with optional initial values
8408
+ # Returns flat fields only for MCP tool simplicity
8409
+ mutation CreateAutomation($input: CreateAutomationInput!) {
8410
+ createAutomation(input: $input) {
8411
+ id
8412
+ name
8413
+ organizationId
8414
+ createdAt
8415
+ updatedAt
8416
+ environment
8417
+ lastSavedAt
8418
+ publishedVersionId
8419
+ draftVersionId
8572
8420
  }
8573
- if (isCustomerUsageError(appError)) {
8574
- return 400;
8421
+ }`
8422
+ }),
8423
+ createOperationSpec({
8424
+ operationName: "GetGraphqlSchema",
8425
+ kind: "query",
8426
+ inputSchema: z2.object({}),
8427
+ cli: {
8428
+ name: "get-graphql-schema",
8429
+ path: ["graphql", "schema"],
8430
+ description: "Fetch GraphQL schema metadata.",
8431
+ resultKey: "graphqlSchema",
8432
+ options: []
8433
+ },
8434
+ mcp: { fileName: "graphqlSchema.graphql" },
8435
+ document: `# Query to fetch full GraphQL schema metadata.
8436
+ # Uses the first-class graphqlSchema query field to avoid __schema validation
8437
+ # issues in MCP tool-load paths while still returning introspection JSON.
8438
+ # Response can be large: call sparingly (typically once per task/session) and
8439
+ # reuse cached results.
8440
+ query GetGraphqlSchema {
8441
+ graphqlSchema
8442
+ }`
8443
+ }),
8444
+ createOperationSpec({
8445
+ operationName: "PauseAutomationRun",
8446
+ kind: "mutation",
8447
+ inputSchema: z2.object({
8448
+ automationRunId: z2.string().min(1)
8449
+ }),
8450
+ cli: {
8451
+ name: "pause-automation-run",
8452
+ path: ["automation-runs", "pause"],
8453
+ description: "Pause an automation run.",
8454
+ resultKey: "pauseAutomationRun",
8455
+ options: [
8456
+ stringOption({
8457
+ inputKey: "automationRunId",
8458
+ flagName: "automation-run-id",
8459
+ description: "Automation run ID.",
8460
+ required: true
8461
+ })
8462
+ ]
8463
+ },
8464
+ mcp: { fileName: "pauseAutomationRun.graphql" },
8465
+ document: `# Mutation to pause an automation run
8466
+ mutation PauseAutomationRun($automationRunId: ID!) {
8467
+ pauseAutomationRun(automationRunId: $automationRunId)
8468
+ }`
8469
+ }),
8470
+ createOperationSpec({
8471
+ operationName: "RerunAutomation",
8472
+ kind: "mutation",
8473
+ inputSchema: z2.object({
8474
+ automationRunId: z2.string().min(1),
8475
+ additionalPrompt: z2.string().min(1).optional(),
8476
+ idempotencyKey: z2.string().min(1)
8477
+ }),
8478
+ cli: {
8479
+ name: "rerun-automation",
8480
+ path: ["automation-runs", "rerun"],
8481
+ description: "Rerun an existing automation run.",
8482
+ resultKey: "rerunAutomation",
8483
+ options: [
8484
+ stringOption({
8485
+ inputKey: "automationRunId",
8486
+ flagName: "automation-run-id",
8487
+ description: "Automation run ID.",
8488
+ required: true
8489
+ }),
8490
+ stringOption({
8491
+ inputKey: "additionalPrompt",
8492
+ flagName: "additional-prompt",
8493
+ description: "Optional prompt appended to the rerun."
8494
+ }),
8495
+ stringOption({
8496
+ inputKey: "idempotencyKey",
8497
+ flagName: "idempotency-key",
8498
+ description: "Idempotency key for the rerun request.",
8499
+ required: true
8500
+ })
8501
+ ]
8502
+ },
8503
+ mcp: { fileName: "rerunAutomation.graphql" },
8504
+ document: `# Mutation to rerun an existing automation run
8505
+ mutation RerunAutomation(
8506
+ $automationRunId: ID!
8507
+ $additionalPrompt: String
8508
+ $idempotencyKey: String!
8509
+ ) {
8510
+ rerunAutomation(
8511
+ automationRunId: $automationRunId
8512
+ additionalPrompt: $additionalPrompt
8513
+ idempotencyKey: $idempotencyKey
8514
+ ) {
8515
+ automationRunId
8516
+ workflowId
8517
+ workflowRunId
8575
8518
  }
8576
- return 500;
8577
- }
8578
- function normalizeUserFacingErrorCode({ type, fallbackCode, prefix }) {
8579
- if (!type) {
8580
- return fallbackCode;
8519
+ }`
8520
+ }),
8521
+ createOperationSpec({
8522
+ operationName: "ResumeAutomationRun",
8523
+ kind: "mutation",
8524
+ inputSchema: z2.object({
8525
+ automationRunId: z2.string().min(1),
8526
+ message: z2.string().min(1).optional()
8527
+ }),
8528
+ cli: {
8529
+ name: "resume-automation-run",
8530
+ path: ["automation-runs", "resume"],
8531
+ description: "Resume a paused automation run.",
8532
+ resultKey: "resumeAutomationRun",
8533
+ options: [
8534
+ stringOption({
8535
+ inputKey: "automationRunId",
8536
+ flagName: "automation-run-id",
8537
+ description: "Automation run ID.",
8538
+ required: true
8539
+ }),
8540
+ stringOption({
8541
+ inputKey: "message",
8542
+ flagName: "message",
8543
+ description: "Optional resume message."
8544
+ })
8545
+ ]
8546
+ },
8547
+ mcp: { fileName: "resumeAutomationRun.graphql" },
8548
+ document: `# Mutation to resume an automation run
8549
+ mutation ResumeAutomationRun($automationRunId: ID!, $message: String) {
8550
+ resumeAutomationRun(automationRunId: $automationRunId, message: $message)
8551
+ }`
8552
+ }),
8553
+ createOperationSpec({
8554
+ operationName: "RunDraftAutomation",
8555
+ kind: "mutation",
8556
+ inputSchema: z2.object({
8557
+ draftAutomationId: z2.string().min(1),
8558
+ agentId: z2.string().min(1),
8559
+ idempotencyKey: z2.string().min(1),
8560
+ input: z2.unknown().optional(),
8561
+ additionalPrompt: z2.string().min(1).optional()
8562
+ }),
8563
+ cli: {
8564
+ name: "run-draft-automation",
8565
+ path: ["automations", "run-draft"],
8566
+ description: "Run a draft automation with an explicit trigger agent.",
8567
+ resultKey: "runDraftAutomation",
8568
+ options: [
8569
+ stringOption({
8570
+ inputKey: "draftAutomationId",
8571
+ flagName: "draft-automation-id",
8572
+ description: "Draft automation ID.",
8573
+ required: true
8574
+ }),
8575
+ stringOption({
8576
+ inputKey: "agentId",
8577
+ flagName: "agent-id",
8578
+ description: "Trigger agent ID.",
8579
+ required: true
8580
+ }),
8581
+ stringOption({
8582
+ inputKey: "idempotencyKey",
8583
+ flagName: "idempotency-key",
8584
+ description: "Idempotency key for the run request.",
8585
+ required: true
8586
+ }),
8587
+ jsonOption({
8588
+ inputKey: "input",
8589
+ flagName: "input-json",
8590
+ description: "Optional JSON input payload."
8591
+ }),
8592
+ stringOption({
8593
+ inputKey: "additionalPrompt",
8594
+ flagName: "additional-prompt",
8595
+ description: "Optional prompt appended to the run."
8596
+ })
8597
+ ]
8598
+ },
8599
+ mcp: { fileName: "runDraftAutomation.graphql" },
8600
+ document: `# Mutation to run a draft automation with an explicit agent.
8601
+ # \`draftAutomationId\` is the draft automation entity ID (\`Automation.id\`), not \`draftVersionId\`.
8602
+ mutation RunDraftAutomation(
8603
+ $draftAutomationId: ID!
8604
+ $agentId: ID!
8605
+ $idempotencyKey: String!
8606
+ $input: JSON
8607
+ $additionalPrompt: String
8608
+ ) {
8609
+ runDraftAutomation(
8610
+ draftAutomationId: $draftAutomationId
8611
+ agentId: $agentId
8612
+ idempotencyKey: $idempotencyKey
8613
+ input: $input
8614
+ additionalPrompt: $additionalPrompt
8615
+ ) {
8616
+ automationRunId
8617
+ workflowId
8618
+ workflowRunId
8581
8619
  }
8582
- const normalized = normalizeErrorCodeSegment(type);
8583
- if (normalized.length === 0) {
8584
- return fallbackCode;
8620
+ }`
8621
+ }),
8622
+ createOperationSpec({
8623
+ operationName: "StopAutomationRun",
8624
+ kind: "mutation",
8625
+ inputSchema: z2.object({
8626
+ automationRunId: z2.string().min(1)
8627
+ }),
8628
+ cli: {
8629
+ name: "stop-automation-run",
8630
+ path: ["automation-runs", "stop"],
8631
+ description: "Stop an automation run.",
8632
+ resultKey: "stopAutomationRun",
8633
+ options: [
8634
+ stringOption({
8635
+ inputKey: "automationRunId",
8636
+ flagName: "automation-run-id",
8637
+ description: "Automation run ID.",
8638
+ required: true
8639
+ })
8640
+ ]
8641
+ },
8642
+ mcp: { fileName: "stopAutomationRun.graphql" },
8643
+ document: `# Mutation to stop an automation run
8644
+ mutation StopAutomationRun($automationRunId: ID!) {
8645
+ stopAutomationRun(automationRunId: $automationRunId)
8646
+ }`
8647
+ }),
8648
+ createOperationSpec({
8649
+ operationName: "UpdateAutomationById",
8650
+ kind: "mutation",
8651
+ inputSchema: z2.object({
8652
+ id: z2.string().min(1),
8653
+ input: jsonObjectSchema
8654
+ }),
8655
+ cli: {
8656
+ name: "update-automation-by-id",
8657
+ path: ["automations", "update"],
8658
+ description: "Update an automation.",
8659
+ resultKey: "updateAutomation",
8660
+ options: [
8661
+ stringOption({
8662
+ inputKey: "id",
8663
+ flagName: "id",
8664
+ description: "Automation ID.",
8665
+ required: true
8666
+ }),
8667
+ jsonOption({
8668
+ inputKey: "input",
8669
+ flagName: "input-json",
8670
+ description: "UpdateAutomationInput payload.",
8671
+ required: true
8672
+ })
8673
+ ]
8674
+ },
8675
+ mcp: { fileName: "updateAutomation.graphql" },
8676
+ document: `# Mutation to update an automation
8677
+ # Returns only id and lastSavedAt for MCP tool simplicity
8678
+ mutation UpdateAutomationById($id: ID!, $input: UpdateAutomationInput!) {
8679
+ updateAutomation(id: $id, input: $input) {
8680
+ id
8681
+ lastSavedAt
8682
+ }
8683
+ }`
8684
+ })
8685
+ ];
8686
+
8687
+ // src/program.ts
8688
+ import { Command as Command2, InvalidArgumentError as InvalidArgumentError2, Option as Option2 } from "commander";
8689
+
8690
+ // src/api.ts
8691
+ import { z as z3 } from "zod";
8692
+ var OTTO_AUTHORIZATION_HEADER_NAME = "X-Otto-Authorization";
8693
+ var OTTO_AUTHORIZATION_ISSUER = "magical:otto";
8694
+ var workosOrganizationsResponseSchema = z3.object({
8695
+ organizations: z3.array(
8696
+ z3.object({
8697
+ id: z3.string().min(1),
8698
+ name: z3.string().min(1),
8699
+ primaryDomain: z3.string().nullable().optional()
8700
+ })
8701
+ ),
8702
+ success: z3.boolean()
8703
+ });
8704
+ var workosUserSchema = z3.object({
8705
+ email: z3.string().nullable(),
8706
+ id: z3.string().min(1)
8707
+ });
8708
+ var nangoIntegrationWireSchema = z3.object({
8709
+ // eslint-disable-next-line @typescript-eslint/naming-convention -- mirrors Nango REST payload
8710
+ unique_key: z3.string().min(1)
8711
+ }).passthrough().transform((data) => ({
8712
+ ...data,
8713
+ uniqueKey: data.unique_key
8714
+ }));
8715
+ var nangoIntegrationsResponseSchema = z3.array(nangoIntegrationWireSchema);
8716
+ var organizationAuthenticationSchema = z3.object({
8717
+ id: z3.string().min(1),
8718
+ type: z3.string().min(1),
8719
+ connectionId: z3.string().nullable().optional(),
8720
+ providerConfigKey: z3.string().nullable().optional(),
8721
+ description: z3.string().nullable().optional(),
8722
+ hostname: z3.string().nullable().optional()
8723
+ }).passthrough();
8724
+ var organizationAuthenticationsResponseSchema = z3.object({
8725
+ authentications: z3.array(organizationAuthenticationSchema),
8726
+ success: z3.boolean()
8727
+ });
8728
+ var graphQlResponseSchema = z3.object({
8729
+ data: z3.record(z3.string(), z3.unknown()).optional(),
8730
+ errors: z3.array(
8731
+ z3.object({
8732
+ message: z3.string().min(1)
8733
+ })
8734
+ ).optional()
8735
+ });
8736
+ var apiErrorResponseSchema = z3.object({
8737
+ errors: z3.array(
8738
+ z3.object({
8739
+ message: z3.string().min(1)
8740
+ })
8741
+ ).optional(),
8742
+ message: z3.string().min(1).optional()
8743
+ });
8744
+ function getApiErrorDetail(responseBody) {
8745
+ const parsedResponse = apiErrorResponseSchema.safeParse(responseBody);
8746
+ if (!parsedResponse.success) {
8747
+ return null;
8585
8748
  }
8586
- const normalizedPrefix = prefix ? normalizeErrorCodeSegment(prefix) : void 0;
8587
- if (!normalizedPrefix) {
8588
- return normalized;
8749
+ if (parsedResponse.data.message) {
8750
+ return parsedResponse.data.message;
8589
8751
  }
8590
- if (normalized.startsWith(`${normalizedPrefix}_`)) {
8591
- return normalized;
8752
+ if (!parsedResponse.data.errors || parsedResponse.data.errors.length === 0) {
8753
+ return null;
8592
8754
  }
8593
- return `${normalizedPrefix}_${normalized}`;
8594
- }
8595
- function toUserFacingApiErrorFromAppError({ appError, correlationId, statusCode }) {
8596
- const resolvedStatusCode = statusCode ?? getStatusCodeForAppErrorFromAppError(appError);
8597
- const message = resolveApiMessage({
8598
- appError,
8599
- statusCode: resolvedStatusCode
8600
- });
8601
- const suggestedAction = resolveSuggestedAction({
8602
- appError,
8603
- statusCode: resolvedStatusCode
8604
- });
8605
- const details = resolveApiDetails({
8606
- appError,
8607
- statusCode: resolvedStatusCode
8608
- });
8609
- return {
8610
- code: resolveApiErrorCode({
8611
- appError,
8612
- statusCode: resolvedStatusCode
8613
- }),
8614
- message,
8615
- correlationId,
8616
- suggestedAction,
8617
- ...details ? { details } : {}
8618
- };
8619
- }
8620
- function toUserFacingGraphQLErrorFromAppError({ appError, correlationId }) {
8621
- const code = resolveGraphQLErrorCode(appError);
8622
- const statusCode = getStatusCodeFromGraphQLErrorCode(code);
8623
- const apiError = toUserFacingApiErrorFromAppError({
8624
- appError,
8625
- correlationId,
8626
- statusCode
8627
- });
8628
- return {
8629
- code,
8630
- errorCode: getGraphQLAppErrorCode({ code, apiCode: apiError.code }),
8631
- message: getGraphQLErrorMessage({ code, apiMessage: apiError.message }),
8632
- correlationId
8633
- };
8634
- }
8635
-
8636
- // ../common/dist/src/stdlib/error.js
8637
- var INTERNAL_STACK_PATHS = [
8638
- "/src/stdlib/result.util.ts",
8639
- "/src/stdlib/error.ts"
8640
- ];
8641
- function stripInternalFrames(stack, internalFrames) {
8642
- const lines = stack.split("\n");
8643
- return lines.filter((line) => !internalFrames.some((internalFrame) => line.includes(internalFrame)));
8755
+ return parsedResponse.data.errors.map((error) => error.message).join("\n");
8644
8756
  }
8645
- var ORDERED_APP_ERROR_CATEGORIES = [
8646
- "internal_platform",
8647
- "customer_usage",
8648
- "third_party"
8649
- ];
8650
- function isAppErrorCategory(category) {
8651
- return typeof category === "string" && // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
8652
- ORDERED_APP_ERROR_CATEGORIES.includes(category);
8757
+ function trimTrailingSlash(value) {
8758
+ return value.replace(/\/+$/u, "");
8653
8759
  }
8654
- function isNonEmptyAppErrorCategoryArray(categories) {
8655
- return Array.isArray(categories) && categories.length > 0 && categories.every(isAppErrorCategory);
8760
+ function isRecord2(value) {
8761
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8656
8762
  }
8657
- var APP_ERROR_SEVERITIES = ["warn", "error", "fatal"];
8658
- function isAppErrorCode(code) {
8659
- return typeof code === "number" && Number.isInteger(code) && code >= 400 && code <= 599;
8763
+ function decodeJwtPayload(token) {
8764
+ const [, payloadSegment] = token.split(".");
8765
+ if (!payloadSegment) {
8766
+ return null;
8767
+ }
8768
+ const payloadResult = safeJsonParse(
8769
+ Buffer.from(payloadSegment, "base64url").toString("utf8")
8770
+ );
8771
+ if (isErr(payloadResult)) {
8772
+ return null;
8773
+ }
8774
+ return isRecord2(payloadResult.value) ? payloadResult.value : null;
8660
8775
  }
8661
- function isAppErrorSeverity(severity) {
8662
- return typeof severity === "string" && // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
8663
- APP_ERROR_SEVERITIES.includes(severity);
8776
+ function isOttoAuthorizationToken(token) {
8777
+ return decodeJwtPayload(token)?.["iss"] === OTTO_AUTHORIZATION_ISSUER;
8664
8778
  }
8665
- var AppError = class _AppError extends Error {
8666
- type;
8667
- categories;
8668
- severity;
8669
- statusCode;
8670
- suggestedAction;
8671
- nonRetryable;
8672
- details;
8673
- constructor({ type, categories, severity, statusCode, code, message, suggestedAction, cause, nonRetryable, stack, internalFrames, ...details }) {
8674
- super(_AppError.resolveMessage(message, cause, type), { cause });
8675
- this.type = type;
8676
- this.name = type;
8677
- this.details = details;
8678
- this.categories = categories ?? _AppError.extractCategoriesFromCause(cause);
8679
- this.severity = severity ?? _AppError.extractSeverityFromCause(cause);
8680
- this.statusCode = statusCode ?? code ?? _AppError.extractStatusCodeFromCause(cause);
8681
- this.suggestedAction = suggestedAction ?? _AppError.extractSuggestedActionFromCause(cause);
8682
- this.nonRetryable = nonRetryable ?? false;
8683
- _AppError.applyStack(this, stack, internalFrames);
8684
- }
8685
- static resolveMessage(message, cause, type) {
8686
- if (message) {
8687
- return message;
8688
- }
8689
- if (cause instanceof Error) {
8690
- return cause.message;
8779
+ function applyAuthenticationHeaders({
8780
+ accessToken,
8781
+ allowOttoAuthorization,
8782
+ headers,
8783
+ impersonatedOrganizationId,
8784
+ organizationId
8785
+ }) {
8786
+ if (!isOttoAuthorizationToken(accessToken)) {
8787
+ headers.set("authorization", `Bearer ${accessToken}`);
8788
+ if (impersonatedOrganizationId) {
8789
+ headers.set("x-organization-id", impersonatedOrganizationId);
8691
8790
  }
8692
- return type;
8791
+ return;
8693
8792
  }
8694
- static getInheritedCauseField(cause, extractor, seen = /* @__PURE__ */ new Set()) {
8695
- if (!cause || typeof cause !== "object" || seen.has(cause)) {
8696
- return void 0;
8697
- }
8698
- const causeRecord = cause;
8699
- const extractedValue = extractor(causeRecord);
8700
- if (extractedValue !== void 0) {
8701
- return extractedValue;
8793
+ if (!allowOttoAuthorization) {
8794
+ throw new CliError(
8795
+ "Otto authorization is only supported for GraphQL requests."
8796
+ );
8797
+ }
8798
+ if (!organizationId) {
8799
+ throw new CliError("Otto authorization requires an organization ID.");
8800
+ }
8801
+ headers.set(OTTO_AUTHORIZATION_HEADER_NAME, `Bearer ${accessToken}`);
8802
+ headers.set("x-organization-id", organizationId);
8803
+ }
8804
+ function createMagicalApiClient({
8805
+ apiBaseUrl,
8806
+ fetchFn = fetch
8807
+ }) {
8808
+ const resolveApiBaseUrl = typeof apiBaseUrl === "string" ? () => apiBaseUrl : apiBaseUrl;
8809
+ async function fetchJson({
8810
+ accessToken,
8811
+ impersonatedOrganizationId,
8812
+ allowOttoAuthorization,
8813
+ path: path7,
8814
+ init,
8815
+ organizationId
8816
+ }) {
8817
+ const url = `${trimTrailingSlash(await resolveApiBaseUrl())}${path7}`;
8818
+ const headers = new Headers(init?.headers);
8819
+ applyAuthenticationHeaders({
8820
+ accessToken,
8821
+ ...allowOttoAuthorization ? { allowOttoAuthorization } : {},
8822
+ headers,
8823
+ ...impersonatedOrganizationId ? { impersonatedOrganizationId } : {},
8824
+ ...organizationId ? { organizationId } : {}
8825
+ });
8826
+ const response = await fetchFn(url, {
8827
+ ...init,
8828
+ headers
8829
+ }).catch((error) => {
8830
+ throw new CliError(
8831
+ `Failed to reach Magical API at ${url}. Check your configured base URL and make sure service-main is running.`,
8832
+ { cause: error }
8833
+ );
8834
+ });
8835
+ const responseBody = await response.json().catch((error) => {
8836
+ if (!response.ok) {
8837
+ throw new CliError(
8838
+ `Magical API request to ${url} failed with status ${response.status}.`,
8839
+ {
8840
+ cause: error
8841
+ }
8842
+ );
8843
+ }
8844
+ throw new CliError(
8845
+ `Magical API returned a non-JSON response for ${url}.`,
8846
+ {
8847
+ cause: error
8848
+ }
8849
+ );
8850
+ });
8851
+ if (!response.ok) {
8852
+ const errorDetail = getApiErrorDetail(responseBody);
8853
+ throw new CliError(
8854
+ `Magical API request to ${url} failed with status ${response.status}${errorDetail ? `: ${errorDetail}` : "."}`
8855
+ );
8702
8856
  }
8703
- return _AppError.getInheritedCauseField(causeRecord["cause"], extractor, new Set(seen).add(cause));
8857
+ return responseBody;
8704
8858
  }
8705
- static extractCategoriesFromCause(cause) {
8706
- return _AppError.getInheritedCauseField(cause, (causeRecord) => {
8707
- const { categories } = causeRecord;
8708
- if (isNonEmptyAppErrorCategoryArray(categories)) {
8709
- return categories;
8859
+ return {
8860
+ async executeGraphQl({
8861
+ accessToken,
8862
+ impersonatedOrganizationId,
8863
+ organizationId,
8864
+ query,
8865
+ resultKey,
8866
+ variables
8867
+ }) {
8868
+ const headers = new Headers();
8869
+ headers.set("content-type", "application/json");
8870
+ const parsedResponse = graphQlResponseSchema.safeParse(
8871
+ await fetchJson({
8872
+ accessToken,
8873
+ ...impersonatedOrganizationId ? { impersonatedOrganizationId } : {},
8874
+ allowOttoAuthorization: true,
8875
+ ...organizationId ? { organizationId } : {},
8876
+ path: "/graphql",
8877
+ init: {
8878
+ method: "POST",
8879
+ headers,
8880
+ body: JSON.stringify({
8881
+ query,
8882
+ variables
8883
+ })
8884
+ }
8885
+ })
8886
+ );
8887
+ if (!parsedResponse.success) {
8888
+ throw new CliError("GraphQL response payload was invalid.");
8889
+ }
8890
+ if (parsedResponse.data.errors && parsedResponse.data.errors.length > 0) {
8891
+ throw new CliError(
8892
+ parsedResponse.data.errors.map((error) => error.message).join("\n")
8893
+ );
8894
+ }
8895
+ return parsedResponse.data.data?.[resultKey] ?? null;
8896
+ },
8897
+ async fetchOrganizations({ accessToken }) {
8898
+ const parsedResponse = workosOrganizationsResponseSchema.safeParse(
8899
+ await fetchJson({
8900
+ accessToken,
8901
+ path: "/workos/organizations"
8902
+ })
8903
+ );
8904
+ if (!parsedResponse.success) {
8905
+ throw new CliError("Organization list payload was invalid.");
8906
+ }
8907
+ return parsedResponse.data.organizations.map((organization) => ({
8908
+ id: organization.id,
8909
+ name: organization.name,
8910
+ primaryDomain: organization.primaryDomain ?? null
8911
+ }));
8912
+ },
8913
+ async fetchUser({
8914
+ accessToken,
8915
+ organizationId,
8916
+ userId
8917
+ }) {
8918
+ const parsedResponse = workosUserSchema.safeParse(
8919
+ await fetchJson({
8920
+ accessToken,
8921
+ ...organizationId ? { organizationId } : {},
8922
+ path: `/workos/user/${userId}`
8923
+ })
8924
+ );
8925
+ if (!parsedResponse.success) {
8926
+ throw new CliError("User payload was invalid.");
8710
8927
  }
8711
- return void 0;
8712
- }) ?? ["internal_platform"];
8713
- }
8714
- static extractSeverityFromCause(cause) {
8715
- return _AppError.getInheritedCauseField(cause, (causeRecord) => {
8716
- const { severity } = causeRecord;
8717
- return isAppErrorSeverity(severity) ? severity : void 0;
8718
- }) ?? "error";
8719
- }
8720
- static extractStatusCodeFromCause(cause) {
8721
- return _AppError.getInheritedCauseField(cause, (causeRecord) => {
8722
- const { statusCode } = causeRecord;
8723
- if (isAppErrorCode(statusCode)) {
8724
- return statusCode;
8928
+ return parsedResponse.data;
8929
+ },
8930
+ async listNangoIntegrations({
8931
+ accessToken,
8932
+ impersonatedOrganizationId,
8933
+ organizationId
8934
+ }) {
8935
+ const parsedResponse = nangoIntegrationsResponseSchema.safeParse(
8936
+ await fetchJson({
8937
+ accessToken,
8938
+ ...impersonatedOrganizationId ? { impersonatedOrganizationId } : {},
8939
+ ...organizationId ? { organizationId } : {},
8940
+ path: "/nango/integrations"
8941
+ })
8942
+ );
8943
+ if (!parsedResponse.success) {
8944
+ throw new CliError("Nango integrations payload was invalid.");
8725
8945
  }
8726
- const { code: legacyCode } = causeRecord;
8727
- return isAppErrorCode(legacyCode) ? legacyCode : void 0;
8728
- });
8729
- }
8730
- /** @deprecated Use statusCode instead. */
8731
- get code() {
8732
- return this.statusCode;
8733
- }
8734
- static extractSuggestedActionFromCause(cause) {
8735
- return _AppError.getInheritedCauseField(cause, (causeRecord) => {
8736
- const { suggestedAction } = causeRecord;
8737
- if (typeof suggestedAction !== "string") {
8738
- return void 0;
8946
+ return parsedResponse.data;
8947
+ },
8948
+ async listNangoAuthentications({
8949
+ accessToken,
8950
+ impersonatedOrganizationId,
8951
+ organizationId
8952
+ }) {
8953
+ const parsedResponse = organizationAuthenticationsResponseSchema.safeParse(
8954
+ await fetchJson({
8955
+ accessToken,
8956
+ ...impersonatedOrganizationId ? { impersonatedOrganizationId } : {},
8957
+ ...organizationId ? { organizationId } : {},
8958
+ path: "/authentications/organization?type=nangoConnection"
8959
+ })
8960
+ );
8961
+ if (!parsedResponse.success) {
8962
+ throw new CliError("Organization authentications payload was invalid.");
8739
8963
  }
8740
- const trimmedSuggestedAction = suggestedAction.trim();
8741
- return trimmedSuggestedAction.length > 0 ? trimmedSuggestedAction : void 0;
8742
- });
8743
- }
8744
- static applyStack(error, stack, internalFrames) {
8745
- if (stack) {
8746
- error.stack = stack;
8964
+ return parsedResponse.data.authentications;
8747
8965
  }
8748
- error.stack &&= stripInternalFrames(error.stack, [
8749
- ...INTERNAL_STACK_PATHS,
8750
- ...internalFrames ?? []
8751
- ]).join("\n");
8752
- }
8753
- toApiError({ correlationId }) {
8754
- return toUserFacingApiError({
8755
- error: this,
8756
- correlationId,
8757
- statusCode: getStatusCodeForAppError(this)
8758
- });
8759
- }
8760
- toGqlError({ correlationId }) {
8761
- return toUserFacingGraphQLError({
8762
- error: this,
8763
- correlationId
8764
- });
8765
- }
8766
- };
8767
- function toAppError(error) {
8768
- return error instanceof AppError ? error : new AppError(error);
8769
- }
8770
- function getStatusCodeForAppError(error) {
8771
- const appError = toAppError(error);
8772
- return getStatusCodeForAppErrorFromAppError(appError);
8773
- }
8774
- function toUserFacingApiError({ error, correlationId, statusCode }) {
8775
- const appError = toAppError(error);
8776
- return toUserFacingApiErrorFromAppError({
8777
- appError,
8778
- correlationId,
8779
- statusCode
8780
- });
8781
- }
8782
- function toUserFacingGraphQLError({ error, correlationId }) {
8783
- const appError = toAppError(error);
8784
- return toUserFacingGraphQLErrorFromAppError({
8785
- appError,
8786
- correlationId
8787
- });
8966
+ };
8788
8967
  }
8789
8968
 
8790
- // ../common/dist/src/stdlib/result.util.js
8791
- var Result;
8792
- (function(Result2) {
8793
- function partition(responses) {
8794
- const oks = responses.filter((resp) => resp._tag === "Ok").map((resp) => resp.value);
8795
- const errs = responses.filter((resp) => resp._tag === "Err").map((resp) => resp.error);
8796
- return [oks, errs];
8797
- }
8798
- Result2.partition = partition;
8799
- async function promiseAllAndPartition(promises) {
8800
- const results = await Promise.all(promises);
8801
- return partition(results);
8802
- }
8803
- Result2.promiseAllAndPartition = promiseAllAndPartition;
8804
- function unwrapOrThrow(result) {
8805
- if (isErr(result)) {
8806
- throw result.error;
8807
- }
8808
- return result.value;
8809
- }
8810
- Result2.unwrapOrThrow = unwrapOrThrow;
8811
- async function all(promises) {
8812
- const results = await fromThrowable(async () => Promise.all(promises.map(async (promise) => {
8813
- const result = await promise;
8814
- if (isErr(result)) {
8815
- throw result.error;
8816
- }
8817
- return result;
8818
- })), "unknown-error");
8819
- if (isErr(results)) {
8820
- return ErrFromThrowable(results.error.cause);
8821
- }
8822
- return Ok(results.value.map((r) => r.value));
8823
- }
8824
- Result2.all = all;
8825
- function andThenSync(fnFirst, ...fns) {
8826
- let result = fnFirst();
8827
- const values = [];
8828
- for (const fn of fns) {
8829
- if (isErr(result)) {
8830
- return result;
8831
- }
8832
- values.unshift(result.value);
8833
- result = fn(...values);
8834
- }
8835
- return result;
8969
+ // src/config.ts
8970
+ import os from "os";
8971
+ import path from "path";
8972
+ var DEFAULT_MAGICAL_API_URL = "https://api-agt.getmagical.io";
8973
+ var DEFAULT_WORKOS_API_URL = "https://api.workos.com";
8974
+ var DEFAULT_WORKOS_CLIENT_ID = "client_01JJZ6XJ1RF248P20WF63M4VAM";
8975
+ var DEFAULT_STAGING_WORKOS_CLIENT_ID = "client_01JJZ6X26BGFBT8AC303XPQ9EQ";
8976
+ var DEFAULT_KEYCHAIN_SERVICE_NAME = "@getmagical/mcp-cli";
8977
+ var DEFAULT_CLI_DIST_TAG = "latest";
8978
+ var DEFAULT_CLI_NPM_REGISTRY_URL = "https://registry.npmjs.org/";
8979
+ var CLI_CONFIG_DIRECTORY_NAME = "magical-mcp-cli";
8980
+ var CLI_ACCESS_TOKEN_FILE_NAME = "access-token.txt";
8981
+ var CLI_STATE_FILE_NAME = "state.json";
8982
+ var CLI_SETTINGS_FILE_NAME = "settings.json";
8983
+ var CLI_REFRESH_TOKEN_FILE_NAME = "refresh-tokens.json";
8984
+ function resolvePlatformConfigDirectory() {
8985
+ const customConfigDirectory = process.env["MAGICAL_CLI_CONFIG_DIR"];
8986
+ if (customConfigDirectory) {
8987
+ return customConfigDirectory;
8836
8988
  }
8837
- Result2.andThenSync = andThenSync;
8838
- async function andThen(fnFirst, ...fns) {
8839
- let result = await fnFirst();
8840
- const values = [];
8841
- for (const fn of fns) {
8842
- if (isErr(result)) {
8843
- return result;
8844
- }
8845
- values.unshift(result.value);
8846
- result = await fn(...values);
8847
- }
8848
- return result;
8989
+ if (process.platform === "darwin") {
8990
+ return path.join(os.homedir(), "Library", "Application Support");
8849
8991
  }
8850
- Result2.andThen = andThen;
8851
- })(Result || (Result = {}));
8852
- function Ok(value) {
8853
- if (arguments.length === 0) {
8854
- return {
8855
- _tag: "Ok",
8856
- value: void 0
8857
- };
8992
+ if (process.platform === "win32") {
8993
+ const appDataDirectory = process.env["APPDATA"];
8994
+ return appDataDirectory ?? path.join(os.homedir(), "AppData", "Roaming");
8858
8995
  }
8859
- return {
8860
- _tag: "Ok",
8861
- value
8862
- };
8996
+ return process.env["XDG_CONFIG_HOME"] ?? path.join(os.homedir(), ".config");
8863
8997
  }
8864
- function Err(error) {
8865
- return {
8866
- _tag: "Err",
8867
- error: new AppError(error)
8868
- };
8998
+ function resolveRefreshTokenStoreKind() {
8999
+ return process.env["MAGICAL_CLI_REFRESH_TOKEN_STORE"] === "file" ? "file" : "keytar";
8869
9000
  }
8870
- function ErrFromThrowable(error) {
9001
+ function getRuntimeConfig() {
9002
+ const configDirectory = path.join(
9003
+ resolvePlatformConfigDirectory(),
9004
+ CLI_CONFIG_DIRECTORY_NAME
9005
+ );
8871
9006
  return {
8872
- _tag: "Err",
8873
- error
9007
+ accessTokenFilePath: path.join(configDirectory, CLI_ACCESS_TOKEN_FILE_NAME),
9008
+ cliDistTag: process.env["MAGICAL_CLI_DIST_TAG"] ?? DEFAULT_CLI_DIST_TAG,
9009
+ magicalApiUrl: DEFAULT_MAGICAL_API_URL,
9010
+ npmRegistryUrl: process.env["MAGICAL_CLI_NPM_REGISTRY_URL"] ?? DEFAULT_CLI_NPM_REGISTRY_URL,
9011
+ refreshTokenFilePath: path.join(
9012
+ configDirectory,
9013
+ CLI_REFRESH_TOKEN_FILE_NAME
9014
+ ),
9015
+ refreshTokenStoreKind: resolveRefreshTokenStoreKind(),
9016
+ stateFilePath: path.join(configDirectory, CLI_STATE_FILE_NAME),
9017
+ workosApiUrl: DEFAULT_WORKOS_API_URL,
9018
+ workosClientId: DEFAULT_WORKOS_CLIENT_ID,
9019
+ keychainServiceName: DEFAULT_KEYCHAIN_SERVICE_NAME
8874
9020
  };
8875
9021
  }
8876
- function isErr(result) {
8877
- return result._tag === "Err";
8878
- }
8879
- function fromThrowable(fn, errorType, errorInfo) {
8880
- try {
8881
- const result = fn();
8882
- if (result && typeof result.then === "function") {
8883
- return result.then((value) => Ok(value)).catch((err) => Err({
8884
- ...errorInfo,
8885
- type: errorType,
8886
- cause: err
8887
- }));
8888
- }
8889
- return Ok(result);
8890
- } catch (err) {
8891
- return Err({
8892
- ...errorInfo,
8893
- type: errorType,
8894
- cause: err
8895
- });
8896
- }
8897
- }
8898
-
8899
- // ../common/dist/src/stdlib/json.util.js
8900
- function safeJsonParse(json) {
8901
- try {
8902
- return Ok(JSON.parse(json));
8903
- } catch (error) {
8904
- console.warn("Failed to parse JSON", { error, json });
8905
- return Err({ type: "invalid-json", cause: error, json });
8906
- }
9022
+ function requireWorkosClientId(config) {
9023
+ return config.workosClientId;
8907
9024
  }
8908
9025
 
8909
9026
  // src/settings.ts
9027
+ import { mkdir, readFile, rm, writeFile } from "fs/promises";
9028
+ import path2 from "path";
8910
9029
  import { z as z4 } from "zod";
8911
9030
  var cliSettingsSchema = z4.object({
8912
9031
  env: z4.object({
@@ -9153,6 +9272,22 @@ function resolveOpenCommand(url) {
9153
9272
 
9154
9273
  // src/program-session.ts
9155
9274
  import { readFile as readFile2, rm as rm2 } from "fs/promises";
9275
+
9276
+ // ../common/dist/src/stdlib/url.utils.js
9277
+ var import_handlebars = __toESM(require_lib(), 1);
9278
+ function safeUrlConstructor(url, baseUrl) {
9279
+ try {
9280
+ return Ok(baseUrl ? new URL(url, baseUrl) : new URL(url));
9281
+ } catch {
9282
+ return Err({
9283
+ type: "invalid-url",
9284
+ message: `Invalid URL`,
9285
+ url
9286
+ });
9287
+ }
9288
+ }
9289
+
9290
+ // src/program-session.ts
9156
9291
  async function withOrgScopedAccessToken({
9157
9292
  dependencies,
9158
9293
  organizationId,
@@ -9217,10 +9352,20 @@ async function loadDirectAccessToken({
9217
9352
  if (!accessTokenFileContents) {
9218
9353
  return null;
9219
9354
  }
9220
- const claims = dependencies.authClient.decodeAccessTokenClaims(
9221
- accessTokenFileContents
9355
+ const claimsResult = fromThrowable(
9356
+ () => dependencies.authClient.decodeAccessTokenClaims(accessTokenFileContents),
9357
+ "decode-otto-session-access-token-failed"
9222
9358
  );
9359
+ if (isErr(claimsResult)) {
9360
+ return null;
9361
+ }
9362
+ const claims = claimsResult.value;
9223
9363
  if (isExpiredAccessTokenClaims(claims)) {
9364
+ if (claims.iss === "magical:otto") {
9365
+ throw new CliError(
9366
+ "The Otto session authorization token expired. Start a new Otto session from Magical."
9367
+ );
9368
+ }
9224
9369
  return null;
9225
9370
  }
9226
9371
  if (claims.org_id && claims.org_id !== organizationId) {
@@ -9242,29 +9387,10 @@ import { spawn as spawn2 } from "child_process";
9242
9387
  import fs from "fs";
9243
9388
  import path3 from "path";
9244
9389
  import { fileURLToPath } from "url";
9245
-
9246
- // ../common/dist/src/stdlib/url.utils.js
9247
- var import_handlebars = __toESM(require_lib(), 1);
9248
- function safeUrlConstructor(url, baseUrl) {
9249
- try {
9250
- return Ok(baseUrl ? new URL(url, baseUrl) : new URL(url));
9251
- } catch {
9252
- return Err({
9253
- type: "invalid-url",
9254
- message: `Invalid URL`,
9255
- url
9256
- });
9257
- }
9258
- }
9259
-
9260
- // src/self-update.ts
9261
9390
  var CLI_PACKAGE_NAME = "@getmagical/cli";
9262
9391
  var DEFAULT_CLI_DIST_TAG2 = "latest";
9263
9392
  var DEFAULT_NPM_REGISTRY_URL = "https://registry.npmjs.org/";
9264
9393
  var MANAGED_NODE_SUBPATH = "runtime/node";
9265
- function isRecord2(value) {
9266
- return typeof value === "object" && value !== null && !Array.isArray(value);
9267
- }
9268
9394
  function resolveInstalledPackageRoot({
9269
9395
  entryFilePath,
9270
9396
  packageName
@@ -9305,154 +9431,6 @@ function resolveInstallPrefixFromPackageRoot(packageRootPath) {
9305
9431
  currentPath = parentPath;
9306
9432
  }
9307
9433
  }
9308
- function readInstalledPackageVersion({
9309
- packageName,
9310
- packageRootPath
9311
- }) {
9312
- const packageManifestPath2 = path3.join(packageRootPath, "package.json");
9313
- if (!fs.existsSync(packageManifestPath2)) {
9314
- throw new CliError(
9315
- `Installed package metadata was not found at ${packageManifestPath2}. Reinstall mgcl and try again.`
9316
- );
9317
- }
9318
- const packageManifestResult2 = safeJsonParse(
9319
- fs.readFileSync(packageManifestPath2, "utf8")
9320
- );
9321
- if (isErr(packageManifestResult2)) {
9322
- throw new CliError(`Failed to parse ${packageManifestPath2}.`, {
9323
- cause: packageManifestResult2.error.cause
9324
- });
9325
- }
9326
- const packageManifest = packageManifestResult2.value;
9327
- if (packageManifest.name !== packageName) {
9328
- throw new CliError(
9329
- `Expected installed package ${packageName} at ${packageManifestPath2}. Reinstall mgcl and try again.`
9330
- );
9331
- }
9332
- if (typeof packageManifest.version !== "string" || !packageManifest.version) {
9333
- throw new CliError(
9334
- `Installed package version is missing from ${packageManifestPath2}. Reinstall mgcl and try again.`
9335
- );
9336
- }
9337
- return packageManifest.version;
9338
- }
9339
- function parseVersionSegment(segment, version) {
9340
- if (!/^\d+$/u.test(segment)) {
9341
- throw new CliError(`Invalid CLI version "${version}".`);
9342
- }
9343
- return Number(segment);
9344
- }
9345
- function parseSemanticVersion(version) {
9346
- const normalizedVersion = version.trim().replace(/^v/u, "");
9347
- const [versionWithoutBuildMetadata = ""] = normalizedVersion.split("+");
9348
- if (!versionWithoutBuildMetadata) {
9349
- throw new CliError(`Invalid CLI version "${version}".`);
9350
- }
9351
- const [releasePart, prereleasePart] = versionWithoutBuildMetadata.split("-");
9352
- if (!releasePart) {
9353
- throw new CliError(`Invalid CLI version "${version}".`);
9354
- }
9355
- return {
9356
- prerelease: prereleasePart ? prereleasePart.split(".") : null,
9357
- release: releasePart.split(".").map((segment) => parseVersionSegment(segment, version))
9358
- };
9359
- }
9360
- function comparePrereleaseIdentifiers(left, right) {
9361
- const leftIsNumeric = /^\d+$/u.test(left);
9362
- const rightIsNumeric = /^\d+$/u.test(right);
9363
- if (leftIsNumeric && rightIsNumeric) {
9364
- return Number(left) - Number(right);
9365
- }
9366
- if (leftIsNumeric) {
9367
- return -1;
9368
- }
9369
- if (rightIsNumeric) {
9370
- return 1;
9371
- }
9372
- return left.localeCompare(right);
9373
- }
9374
- function compareSemanticVersions(leftVersion, rightVersion) {
9375
- const left = parseSemanticVersion(leftVersion);
9376
- const right = parseSemanticVersion(rightVersion);
9377
- const releaseLength = Math.max(left.release.length, right.release.length);
9378
- for (let index = 0; index < releaseLength; index += 1) {
9379
- const difference = (left.release[index] ?? 0) - (right.release[index] ?? 0);
9380
- if (difference !== 0) {
9381
- return difference;
9382
- }
9383
- }
9384
- if (!left.prerelease && !right.prerelease) {
9385
- return 0;
9386
- }
9387
- if (!left.prerelease) {
9388
- return 1;
9389
- }
9390
- if (!right.prerelease) {
9391
- return -1;
9392
- }
9393
- const prereleaseLength = Math.max(
9394
- left.prerelease.length,
9395
- right.prerelease.length
9396
- );
9397
- for (let index = 0; index < prereleaseLength; index += 1) {
9398
- const leftIdentifier = left.prerelease[index];
9399
- const rightIdentifier = right.prerelease[index];
9400
- if (leftIdentifier === void 0) {
9401
- return -1;
9402
- }
9403
- if (rightIdentifier === void 0) {
9404
- return 1;
9405
- }
9406
- const difference = comparePrereleaseIdentifiers(
9407
- leftIdentifier,
9408
- rightIdentifier
9409
- );
9410
- if (difference !== 0) {
9411
- return difference;
9412
- }
9413
- }
9414
- return 0;
9415
- }
9416
- async function fetchPublishedPackageVersion({
9417
- distTag,
9418
- fetchFn = fetch,
9419
- packageName,
9420
- registryUrl
9421
- }) {
9422
- const distTagUrlResult = safeUrlConstructor(
9423
- `${registryUrl.replace(/\/?$/u, "/")}-/package/${encodeURIComponent(packageName)}/dist-tags`
9424
- );
9425
- if (isErr(distTagUrlResult)) {
9426
- throw new CliError(`Invalid npm registry URL "${registryUrl}".`);
9427
- }
9428
- const response = await fetchFn(distTagUrlResult.value, {
9429
- headers: {
9430
- accept: "application/json"
9431
- }
9432
- });
9433
- if (!response.ok) {
9434
- throw new CliError(
9435
- `Could not check the latest published mgcl version (status ${response.status}).`
9436
- );
9437
- }
9438
- const distTagsResult = safeJsonParse(await response.text());
9439
- if (isErr(distTagsResult)) {
9440
- throw new CliError("Could not parse the npm dist-tags response for mgcl.", {
9441
- cause: distTagsResult.error.cause
9442
- });
9443
- }
9444
- if (!isRecord2(distTagsResult.value)) {
9445
- throw new CliError("Could not parse the npm dist-tags response for mgcl.");
9446
- }
9447
- const distTags = distTagsResult.value;
9448
- const publishedVersion = distTags[distTag];
9449
- if (typeof publishedVersion !== "string" || publishedVersion.length === 0) {
9450
- throw new CliError(
9451
- `Could not find npm dist-tag "${distTag}" for ${packageName}.`
9452
- );
9453
- }
9454
- return publishedVersion;
9455
- }
9456
9434
  function resolveNpmCommandFromPath() {
9457
9435
  return {
9458
9436
  argsPrefix: [],
@@ -9566,45 +9544,6 @@ async function selfUpdateInstalledCli({
9566
9544
  registryUrl
9567
9545
  });
9568
9546
  }
9569
- async function getInstalledCliUpdateRequirement({
9570
- distTag = DEFAULT_CLI_DIST_TAG2,
9571
- entryFilePath = fileURLToPath(import.meta.url),
9572
- fetchFn = fetch,
9573
- packageName = CLI_PACKAGE_NAME,
9574
- registryUrl = DEFAULT_NPM_REGISTRY_URL
9575
- } = {}) {
9576
- const packageRootPath = resolveInstalledPackageRoot({
9577
- entryFilePath,
9578
- packageName
9579
- });
9580
- if (!packageRootPath) {
9581
- return null;
9582
- }
9583
- const installedVersion = readInstalledPackageVersion({
9584
- packageName,
9585
- packageRootPath
9586
- });
9587
- const publishedVersionResult = await fromThrowable(
9588
- async () => fetchPublishedPackageVersion({
9589
- distTag,
9590
- fetchFn,
9591
- packageName,
9592
- registryUrl
9593
- }),
9594
- "cli-update-check-failed"
9595
- );
9596
- if (isErr(publishedVersionResult)) {
9597
- return null;
9598
- }
9599
- const publishedVersion = publishedVersionResult.value;
9600
- if (compareSemanticVersions(installedVersion, publishedVersion) >= 0) {
9601
- return null;
9602
- }
9603
- return {
9604
- installedVersion,
9605
- latestVersion: publishedVersion
9606
- };
9607
- }
9608
9547
 
9609
9548
  // src/settings-command.ts
9610
9549
  import { Command, InvalidArgumentError, Option } from "commander";
@@ -9865,6 +9804,7 @@ var tokenErrorSchema = z6.object({
9865
9804
  });
9866
9805
  var accessTokenClaimsSchema = z6.object({
9867
9806
  exp: z6.number().int().positive().optional(),
9807
+ iss: z6.string().min(1).optional(),
9868
9808
  org_id: z6.string().min(1).optional(),
9869
9809
  sid: z6.string().min(1).optional(),
9870
9810
  sub: z6.string().min(1)
@@ -10034,13 +9974,13 @@ function parseCommandOptionValue(rawValue, optionSpec) {
10034
9974
  return rawValue.split(",").map((value) => value.trim()).filter((value) => value.length > 0);
10035
9975
  }
10036
9976
  case "json": {
10037
- try {
10038
- return JSON.parse(rawValue);
10039
- } catch {
9977
+ const parsedJson = safeJsonParse(rawValue);
9978
+ if (isErr(parsedJson)) {
10040
9979
  throw new InvalidArgumentError2(
10041
9980
  `Expected valid JSON for --${optionSpec.flagName}.`
10042
9981
  );
10043
9982
  }
9983
+ return parsedJson.value;
10044
9984
  }
10045
9985
  case "boolean": {
10046
9986
  return rawValue;
@@ -10110,6 +10050,13 @@ function requireLoggedInState(state) {
10110
10050
  function writeJsonOutput3(io, value) {
10111
10051
  io.info(JSON.stringify(value, null, 2));
10112
10052
  }
10053
+ function requireApiClientMethod(apiClient, key) {
10054
+ const method = apiClient[key];
10055
+ if (!method) {
10056
+ throw new CliError(`CLI API client method "${key}" is not wired.`);
10057
+ }
10058
+ return method;
10059
+ }
10113
10060
  function collectOperationVariables(operationSpec, options) {
10114
10061
  const variables = Object.fromEntries(
10115
10062
  operationSpec.cli.options.flatMap((optionSpec) => {
@@ -10198,39 +10145,16 @@ async function handleSelfUpdate(dependencies, options) {
10198
10145
  `Updated mgcl via npm (${updateResult.packageSpecifier}) in ${updateResult.installPrefix}.`
10199
10146
  );
10200
10147
  }
10201
- function isRootUpdateCommand(program2, actionCommand) {
10202
- return actionCommand.parent === program2 && actionCommand.name() === "update";
10203
- }
10204
- async function enforceLatestCliVersionIfNeeded({
10205
- dependencies,
10206
- program: program2,
10207
- actionCommand
10208
- }) {
10209
- if (actionCommand === program2 || isRootUpdateCommand(program2, actionCommand)) {
10210
- return;
10211
- }
10212
- const updateRequirement = await dependencies.ensureLatestCliVersion?.();
10213
- if (!updateRequirement) {
10214
- return;
10215
- }
10216
- throw new CliError(
10217
- `mgcl ${updateRequirement.installedVersion} is outdated. Upgrade to ${updateRequirement.latestVersion} with "mgcl update", then rerun your command.`
10218
- );
10219
- }
10220
10148
  async function handleOperationCommand(dependencies, operationSpec, commandOptions) {
10221
- const state = requireLoggedInState(await dependencies.stateStore.load());
10222
- const organization = resolveSelectedOrganization({
10223
- state,
10224
- ...commandOptions.org ? { organizationSelector: commandOptions.org } : {}
10225
- });
10226
- const variables = collectOperationVariables(operationSpec, commandOptions);
10227
- const { accessToken } = await withOrgScopedAccessToken({
10149
+ const { accessToken, impersonatedOrganizationId, organization, state } = await withSelectedOrganizationAndAccessToken({
10228
10150
  dependencies,
10229
- organizationId: organization.id,
10230
- state
10151
+ options: commandOptions
10231
10152
  });
10153
+ const variables = collectOperationVariables(operationSpec, commandOptions);
10232
10154
  const result = await dependencies.apiClient.executeGraphQl({
10233
10155
  accessToken,
10156
+ ...impersonatedOrganizationId ? { impersonatedOrganizationId } : {},
10157
+ organizationId: organization.id,
10234
10158
  query: operationSpec.document,
10235
10159
  resultKey: operationSpec.cli.resultKey,
10236
10160
  variables
@@ -10245,6 +10169,136 @@ async function handleOperationCommand(dependencies, operationSpec, commandOption
10245
10169
  }
10246
10170
  dependencies.io.info(formatHumanReadableOutput(result));
10247
10171
  }
10172
+ async function withSelectedOrganizationAndAccessToken({
10173
+ dependencies,
10174
+ options
10175
+ }) {
10176
+ const state = requireLoggedInState(await dependencies.stateStore.load());
10177
+ const organization = resolveSelectedOrganization({
10178
+ state,
10179
+ ...options.org ? { organizationSelector: options.org } : {}
10180
+ });
10181
+ const authenticatedOrganizationId = await resolveDirectAccessTokenOrganizationId({ dependencies });
10182
+ const shouldImpersonateOrganization = authenticatedOrganizationId !== null && organization.id !== authenticatedOrganizationId;
10183
+ const { accessToken } = await withOrgScopedAccessToken({
10184
+ dependencies,
10185
+ organizationId: shouldImpersonateOrganization && authenticatedOrganizationId ? authenticatedOrganizationId : organization.id,
10186
+ state
10187
+ });
10188
+ return {
10189
+ accessToken,
10190
+ ...shouldImpersonateOrganization ? { impersonatedOrganizationId: organization.id } : {},
10191
+ organization,
10192
+ state
10193
+ };
10194
+ }
10195
+ function writeCommandOutput({
10196
+ dependencies,
10197
+ json,
10198
+ result
10199
+ }) {
10200
+ if (json) {
10201
+ writeJsonOutput3(dependencies.io, result);
10202
+ return;
10203
+ }
10204
+ dependencies.io.info(formatHumanReadableOutput(result));
10205
+ }
10206
+ async function handleNangoIntegrationsListCommand(dependencies, options) {
10207
+ const { accessToken, impersonatedOrganizationId, organization, state } = await withSelectedOrganizationAndAccessToken({ dependencies, options });
10208
+ const listNangoIntegrations = requireApiClientMethod(
10209
+ dependencies.apiClient,
10210
+ "listNangoIntegrations"
10211
+ );
10212
+ const integrations = await listNangoIntegrations({
10213
+ accessToken,
10214
+ ...impersonatedOrganizationId ? { impersonatedOrganizationId } : {},
10215
+ organizationId: organization.id
10216
+ });
10217
+ await saveLastUsedOrganization({
10218
+ dependencies,
10219
+ organizationId: organization.id,
10220
+ state
10221
+ });
10222
+ writeCommandOutput({
10223
+ dependencies,
10224
+ json: options.json,
10225
+ result: integrations
10226
+ });
10227
+ }
10228
+ function normalizeListedNangoAuthentication(authentication) {
10229
+ return {
10230
+ id: authentication.id,
10231
+ type: authentication.type,
10232
+ ...authentication.connectionId === void 0 ? {} : { connectionId: authentication.connectionId },
10233
+ ...authentication.providerConfigKey === void 0 ? {} : { providerConfigKey: authentication.providerConfigKey },
10234
+ ...authentication.description === void 0 ? {} : { description: authentication.description },
10235
+ ...authentication.hostname === void 0 ? {} : { hostname: authentication.hostname }
10236
+ };
10237
+ }
10238
+ async function handleNangoAuthsListCommand(dependencies, options) {
10239
+ const { accessToken, impersonatedOrganizationId, organization, state } = await withSelectedOrganizationAndAccessToken({ dependencies, options });
10240
+ const listNangoAuthentications = requireApiClientMethod(
10241
+ dependencies.apiClient,
10242
+ "listNangoAuthentications"
10243
+ );
10244
+ const organizationAuthentications = await listNangoAuthentications({
10245
+ accessToken,
10246
+ ...impersonatedOrganizationId ? { impersonatedOrganizationId } : {},
10247
+ organizationId: organization.id
10248
+ });
10249
+ const authentications = organizationAuthentications.filter((authentication) => {
10250
+ if (options.integration && authentication.providerConfigKey !== options.integration) {
10251
+ return false;
10252
+ }
10253
+ if (options.connectionId && authentication.connectionId !== options.connectionId) {
10254
+ return false;
10255
+ }
10256
+ return true;
10257
+ }).map(normalizeListedNangoAuthentication);
10258
+ await saveLastUsedOrganization({
10259
+ dependencies,
10260
+ organizationId: organization.id,
10261
+ state
10262
+ });
10263
+ writeCommandOutput({
10264
+ dependencies,
10265
+ json: options.json,
10266
+ result: authentications
10267
+ });
10268
+ }
10269
+ async function resolveDirectAccessTokenOrganizationId({
10270
+ dependencies
10271
+ }) {
10272
+ const { accessTokenFilePath } = dependencies.runtimeConfig;
10273
+ if (!accessTokenFilePath) {
10274
+ return null;
10275
+ }
10276
+ const accessToken = await readFile4(accessTokenFilePath, "utf8").then((value) => value.trim()).catch((error) => {
10277
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
10278
+ return null;
10279
+ }
10280
+ throw error;
10281
+ });
10282
+ if (!accessToken) {
10283
+ return null;
10284
+ }
10285
+ try {
10286
+ const claims = dependencies.authClient.decodeAccessTokenClaims(accessToken);
10287
+ return claims.org_id ?? null;
10288
+ } catch {
10289
+ return null;
10290
+ }
10291
+ }
10292
+ async function saveLastUsedOrganization({
10293
+ dependencies,
10294
+ organizationId,
10295
+ state
10296
+ }) {
10297
+ await dependencies.stateStore.save({
10298
+ ...state,
10299
+ lastUsedOrgId: organizationId
10300
+ });
10301
+ }
10248
10302
  function addRegistryOperationCommand({
10249
10303
  program: program2,
10250
10304
  commandGroups,
@@ -10360,7 +10414,6 @@ function createDefaultDependencies() {
10360
10414
  accessTokenFilePath
10361
10415
  },
10362
10416
  refreshTokenStore: runtimeConfig.refreshTokenStoreKind === "file" ? createFileRefreshTokenStore(refreshTokenFilePath) : createKeytarRefreshTokenStore(runtimeConfig.keychainServiceName),
10363
- ensureLatestCliVersion: async () => getInstalledCliUpdateRequirement(selfUpdateOptions),
10364
10417
  settingsStore,
10365
10418
  selfUpdateCli: async () => selfUpdateInstalledCli(selfUpdateOptions),
10366
10419
  stateStore: createFileStateStore(runtimeConfig.stateFilePath)
@@ -10395,13 +10448,6 @@ ${formatOutputModesNote()}`
10395
10448
  }
10396
10449
  this.outputHelp();
10397
10450
  });
10398
- program2.hook("preAction", async (_command, actionCommand) => {
10399
- await enforceLatestCliVersionIfNeeded({
10400
- actionCommand,
10401
- dependencies,
10402
- program: program2
10403
- });
10404
- });
10405
10451
  const authCommand = configureCommandPresentation(
10406
10452
  new Command2("auth").description("Manage CLI authentication.")
10407
10453
  ).helpGroup("Workspace:").addHelpText(
@@ -10438,6 +10484,66 @@ ${formatExamples("Examples", [
10438
10484
  );
10439
10485
  });
10440
10486
  program2.addCommand(orgCommand);
10487
+ const nangoCommand = configureCommandPresentation(
10488
+ new Command2("nango").description(
10489
+ "Inspect Nango integrations and org-scoped authentications."
10490
+ )
10491
+ ).helpGroup("Workspace:").addHelpText(
10492
+ "after",
10493
+ `
10494
+ ${formatExamples("Examples", [
10495
+ "mgcl nango integrations list --json",
10496
+ "mgcl nango auths list --integration github --json"
10497
+ ])}`
10498
+ );
10499
+ const nangoIntegrationsCommand = configureCommandPresentation(
10500
+ new Command2("integrations").description("Work with Nango integrations.")
10501
+ );
10502
+ nangoIntegrationsCommand.command("list").description("List Nango integrations available in the current workspace.").addOption(
10503
+ new Option2(
10504
+ "--org <org>",
10505
+ "Organization ID or exact organization name to use."
10506
+ ).helpGroup("Shared options:")
10507
+ ).action(async function() {
10508
+ await handleNangoIntegrationsListCommand(
10509
+ dependencies,
10510
+ this.optsWithGlobals()
10511
+ );
10512
+ });
10513
+ nangoCommand.addCommand(nangoIntegrationsCommand);
10514
+ const nangoAuthsCommand = configureCommandPresentation(
10515
+ new Command2("auths").alias("authentications").description("Work with org-scoped Nango authentications.")
10516
+ );
10517
+ nangoAuthsCommand.command("list").description(
10518
+ "List org-scoped Nango authentications and their connection IDs."
10519
+ ).addOption(
10520
+ new Option2(
10521
+ "--org <org>",
10522
+ "Organization ID or exact organization name to use."
10523
+ ).helpGroup("Shared options:")
10524
+ ).addOption(
10525
+ new Option2(
10526
+ "--integration <integration>",
10527
+ "Optional integration key to filter Nango authentications."
10528
+ )
10529
+ ).addOption(
10530
+ new Option2(
10531
+ "--connection-id <connectionId>",
10532
+ "Optional connection ID to filter Nango authentications."
10533
+ )
10534
+ ).addHelpText(
10535
+ "after",
10536
+ `
10537
+ ${formatExamples("Examples", [
10538
+ "mgcl nango auths list --json",
10539
+ "mgcl nango auths list --integration github --json",
10540
+ "mgcl nango auths list --integration github --connection-id <id> --json"
10541
+ ])}`
10542
+ ).action(async function() {
10543
+ await handleNangoAuthsListCommand(dependencies, this.optsWithGlobals());
10544
+ });
10545
+ nangoCommand.addCommand(nangoAuthsCommand);
10546
+ program2.addCommand(nangoCommand);
10441
10547
  const updateCommand = configureCommandPresentation(
10442
10548
  new Command2("update").description(
10443
10549
  "Update mgcl to the latest published npm release."