@getmagical/cli 0.1.12 → 0.1.13

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);
@@ -6887,2026 +6887,2072 @@ function getErrorMessage(error) {
6887
6887
  // src/program.ts
6888
6888
  import path6 from "path";
6889
6889
 
6890
- // ../mcp-registry/src/operation-specs.ts
6890
+ // ../common/dist/src/stdlib/json.util.js
6891
+ var import_ts_essentials = __toESM(require_dist(), 1);
6892
+
6893
+ // ../common/dist/src/stdlib/result.util.js
6891
6894
  import { z } from "zod";
6892
6895
 
6893
- // ../mcp-registry/src/operation-spec.ts
6894
- function stripLeadingGraphqlComments(document) {
6895
- return document.replace(/^(?:\s*#.*\n)+/u, "").trimStart();
6896
+ // ../common/dist/src/stdlib/error-user-facing.js
6897
+ var USER_FACING_STATUS_MESSAGES = /* @__PURE__ */ new Map([
6898
+ [400, "Bad Request"],
6899
+ [401, "Unauthorized"],
6900
+ [403, "Forbidden"],
6901
+ [404, "Not Found"],
6902
+ [500, "Internal Server Error"],
6903
+ [503, "Service Unavailable"]
6904
+ ]);
6905
+ var USER_FACING_DEFAULT_ACTIONS = /* @__PURE__ */ new Map([
6906
+ [400, "Review the request payload and retry."],
6907
+ [401, "Authenticate and retry the request."],
6908
+ [403, "Verify your permissions and retry the request."],
6909
+ [404, "Verify the requested resource exists and retry."],
6910
+ [
6911
+ 500,
6912
+ "Retry the request. If this keeps happening, contact support and share the correlation ID."
6913
+ ],
6914
+ [
6915
+ 503,
6916
+ "Retry the request after a brief delay. If this keeps happening, contact support and share the correlation ID."
6917
+ ]
6918
+ ]);
6919
+ var USER_FACING_FALLBACK_CODES = /* @__PURE__ */ new Map([
6920
+ [400, "BAD_REQUEST"],
6921
+ [401, "UNAUTHORIZED"],
6922
+ [403, "FORBIDDEN"],
6923
+ [404, "NOT_FOUND"],
6924
+ [500, "INTERNAL_SERVER_ERROR"],
6925
+ [503, "SERVICE_UNAVAILABLE"]
6926
+ ]);
6927
+ function isCustomerUsageError(appError) {
6928
+ return appError.categories.includes("customer_usage");
6896
6929
  }
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
- );
6930
+ function getStatusCodeFromAppErrorCode(code) {
6931
+ if (typeof code !== "number" || !Number.isInteger(code)) {
6932
+ return void 0;
6912
6933
  }
6913
- if (actualKind !== kind || actualOperationName !== operationName) {
6914
- throw new Error(
6915
- `Operation "${operationName}" does not match its GraphQL document (${actualKind} ${actualOperationName}).`
6916
- );
6934
+ if (code >= 400 && code <= 599) {
6935
+ return code;
6917
6936
  }
6937
+ return void 0;
6918
6938
  }
6919
- function createOperationSpec(spec) {
6920
- assertDocumentMatchesOperation(spec);
6921
- return spec;
6939
+ function getStatusFamilyFallbackCode(statusCode) {
6940
+ if (statusCode >= 400 && statusCode <= 499) {
6941
+ return 400;
6942
+ }
6943
+ return 500;
6922
6944
  }
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
- };
6945
+ function getStatusMessage(statusCode) {
6946
+ const directMessage = USER_FACING_STATUS_MESSAGES.get(statusCode);
6947
+ if (directMessage !== void 0) {
6948
+ return directMessage;
6949
+ }
6950
+ return getStatusFamilyFallbackCode(statusCode) === 400 ? "Bad Request" : "Internal Server Error";
6938
6951
  }
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
- };
6952
+ function getDefaultSuggestedAction(statusCode) {
6953
+ const directAction = USER_FACING_DEFAULT_ACTIONS.get(statusCode);
6954
+ if (directAction !== void 0) {
6955
+ return directAction;
6956
+ }
6957
+ 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
6958
  }
6953
- function booleanOption({
6954
- description,
6955
- flagName,
6956
- inputKey
6957
- }) {
6958
- return {
6959
- description,
6960
- flagName,
6961
- inputKey,
6962
- valueType: "boolean"
6963
- };
6959
+ function getFallbackErrorCode(statusCode) {
6960
+ const directCode = USER_FACING_FALLBACK_CODES.get(statusCode);
6961
+ if (directCode !== void 0) {
6962
+ return directCode;
6963
+ }
6964
+ return getStatusFamilyFallbackCode(statusCode) === 400 ? "BAD_REQUEST" : "INTERNAL_SERVER_ERROR";
6964
6965
  }
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
- };
6966
+ function shouldExposeMessage({ appError, statusCode }) {
6967
+ if (statusCode >= 500) {
6968
+ return false;
6969
+ }
6970
+ return isCustomerUsageError(appError);
6979
6971
  }
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
- };
6972
+ function resolveApiMessage({ appError, statusCode }) {
6973
+ if (!shouldExposeMessage({ appError, statusCode })) {
6974
+ return getStatusMessage(statusCode);
6975
+ }
6976
+ const trimmedMessage = appError.message.trim();
6977
+ if (trimmedMessage.length > 0) {
6978
+ return trimmedMessage;
6979
+ }
6980
+ return getStatusMessage(statusCode);
6994
6981
  }
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
6982
+ function resolveApiErrorCode({ appError, statusCode }) {
6983
+ if (!shouldExposeMessage({ appError, statusCode })) {
6984
+ return getFallbackErrorCode(statusCode);
7196
6985
  }
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
6986
+ return normalizeUserFacingErrorCode({
6987
+ type: appError.type,
6988
+ fallbackCode: getFallbackErrorCode(statusCode)
6989
+ });
6990
+ }
6991
+ function resolveSuggestedAction({ appError, statusCode }) {
6992
+ const trimmedSuggestedAction = appError.suggestedAction?.trim();
6993
+ if (shouldExposeMessage({ appError, statusCode }) && trimmedSuggestedAction) {
6994
+ return trimmedSuggestedAction;
7231
6995
  }
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
- }
6996
+ return getDefaultSuggestedAction(statusCode);
6997
+ }
6998
+ function getZodIssuesFromCause(cause, maxDepth = 10) {
6999
+ if (maxDepth < 0 || typeof cause !== "object" || cause === null) {
7000
+ return void 0;
7288
7001
  }
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
7002
+ if ("issues" in cause && Array.isArray(cause.issues)) {
7003
+ return cause.issues;
7325
7004
  }
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
- }
7005
+ if ("cause" in cause) {
7006
+ return getZodIssuesFromCause(cause.cause, maxDepth - 1);
7367
7007
  }
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
7008
+ return void 0;
7009
+ }
7010
+ function toUserFacingDetailsValue(value, depth) {
7011
+ if (depth < 0) {
7012
+ return void 0;
7408
7013
  }
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
7014
+ if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
7015
+ return value;
7445
7016
  }
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
7017
+ if (Array.isArray(value)) {
7018
+ const serializedValues = value.map((item) => toUserFacingDetailsValue(item, depth - 1)).filter((item) => item !== void 0);
7019
+ return serializedValues;
7020
+ }
7021
+ if (value && typeof value === "object") {
7022
+ const serializedObject = {};
7023
+ for (const [key, itemValue] of Object.entries(value)) {
7024
+ const serializedItemValue = toUserFacingDetailsValue(itemValue, depth - 1);
7025
+ if (serializedItemValue !== void 0) {
7026
+ serializedObject[key] = serializedItemValue;
7027
+ }
7028
+ }
7029
+ if (Object.keys(serializedObject).length === 0) {
7030
+ return void 0;
7517
7031
  }
7032
+ return serializedObject;
7518
7033
  }
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
7034
+ return void 0;
7035
+ }
7036
+ function resolveApiDetails({ appError, statusCode }) {
7037
+ if (!shouldExposeMessage({ appError, statusCode })) {
7038
+ return void 0;
7592
7039
  }
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
7040
+ const zodIssues = getZodIssuesFromCause(appError.cause);
7041
+ if (zodIssues && zodIssues.length > 0) {
7042
+ return {
7043
+ validationErrors: zodIssues.map((issue) => ({
7044
+ path: Array.isArray(issue.path) ? issue.path.map(String).join(".") : "",
7045
+ message: typeof issue.message === "string" ? issue.message : "Invalid value",
7046
+ ...typeof issue.code === "string" ? { code: issue.code } : {}
7047
+ }))
7048
+ };
7644
7049
  }
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
7050
+ const rawDetails = toUserFacingDetailsValue(appError.details, 4);
7051
+ if (rawDetails && typeof rawDetails === "object" && !Array.isArray(rawDetails) && Object.keys(rawDetails).length > 0) {
7052
+ return rawDetails;
7681
7053
  }
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
7054
+ return void 0;
7055
+ }
7056
+ function getGraphQLErrorCodeFromAppErrorCode(code) {
7057
+ if (code === 400) {
7058
+ return "BAD_USER_INPUT";
7711
7059
  }
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
- }
7060
+ if (code === 401) {
7061
+ return "UNAUTHORIZED";
7756
7062
  }
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
7063
+ if (code === 403) {
7064
+ return "FORBIDDEN";
7792
7065
  }
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
7066
+ if (code === 404) {
7067
+ return "NOT_FOUND";
7829
7068
  }
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
7069
+ if (code === 500) {
7070
+ return "INTERNAL_SERVER_ERROR";
7927
7071
  }
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
7072
+ return void 0;
7073
+ }
7074
+ function resolveGraphQLErrorCode(appError) {
7075
+ const codeFromAppErrorCode = getGraphQLErrorCodeFromAppErrorCode(appError.statusCode);
7076
+ if (codeFromAppErrorCode !== void 0) {
7077
+ return codeFromAppErrorCode;
8028
7078
  }
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
7079
+ const normalizedErrorType = appError.type.toLowerCase();
7080
+ if (normalizedErrorType.includes("unauthorized")) {
7081
+ return "UNAUTHORIZED";
8091
7082
  }
8092
- }`
8093
- })
8094
- ];
8095
-
8096
- // src/program.ts
8097
- import { Command as Command2, InvalidArgumentError as InvalidArgumentError2, Option as Option2 } from "commander";
8098
-
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;
7083
+ if (normalizedErrorType.includes("forbidden")) {
7084
+ return "FORBIDDEN";
8135
7085
  }
8136
- if (parsedResponse.data.message) {
8137
- return parsedResponse.data.message;
7086
+ if (normalizedErrorType.includes("not-found")) {
7087
+ return "NOT_FOUND";
8138
7088
  }
8139
- if (!parsedResponse.data.errors || parsedResponse.data.errors.length === 0) {
8140
- return null;
7089
+ if (isCustomerUsageError(appError)) {
7090
+ return "BAD_USER_INPUT";
8141
7091
  }
8142
- return parsedResponse.data.errors.map((error) => error.message).join("\n");
8143
- }
8144
- function trimTrailingSlash(value) {
8145
- return value.replace(/\/+$/u, "");
7092
+ return "INTERNAL_SERVER_ERROR";
8146
7093
  }
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
- );
7094
+ function getStatusCodeFromGraphQLErrorCode(code) {
7095
+ switch (code) {
7096
+ case "BAD_USER_INPUT": {
7097
+ return 400;
8190
7098
  }
8191
- return responseBody;
8192
- }
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.");
8235
- }
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.");
8254
- }
8255
- return parsedResponse.data;
7099
+ case "UNAUTHORIZED": {
7100
+ return 401;
7101
+ }
7102
+ case "FORBIDDEN": {
7103
+ return 403;
7104
+ }
7105
+ case "NOT_FOUND": {
7106
+ return 404;
8256
7107
  }
8257
- };
7108
+ case "INTERNAL_SERVER_ERROR": {
7109
+ return 500;
7110
+ }
7111
+ }
8258
7112
  }
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;
7113
+ function getGraphQLErrorMessage({ code, apiMessage }) {
7114
+ switch (code) {
7115
+ case "BAD_USER_INPUT":
7116
+ case "NOT_FOUND":
7117
+ case "INTERNAL_SERVER_ERROR": {
7118
+ return apiMessage;
7119
+ }
7120
+ case "UNAUTHORIZED": {
7121
+ return "Unauthorized";
7122
+ }
7123
+ case "FORBIDDEN": {
7124
+ return "Forbidden";
7125
+ }
8279
7126
  }
8280
- if (process.platform === "darwin") {
8281
- return path.join(os.homedir(), "Library", "Application Support");
7127
+ }
7128
+ function getGraphQLAppErrorCode({ code, apiCode }) {
7129
+ if (code === "INTERNAL_SERVER_ERROR" || code === "UNAUTHORIZED" || code === "FORBIDDEN") {
7130
+ return code;
8282
7131
  }
8283
- if (process.platform === "win32") {
8284
- const appDataDirectory = process.env["APPDATA"];
8285
- return appDataDirectory ?? path.join(os.homedir(), "AppData", "Roaming");
7132
+ return apiCode;
7133
+ }
7134
+ function normalizeErrorCodeSegment(value) {
7135
+ return value.trim().toUpperCase().replaceAll(/[^\dA-Z]+/gu, "_").replaceAll(/^_+/gu, "").replaceAll(/_+$/gu, "");
7136
+ }
7137
+ function getStatusCodeForAppErrorFromAppError(appError) {
7138
+ const statusCodeFromCode = getStatusCodeFromAppErrorCode(appError.statusCode);
7139
+ if (statusCodeFromCode !== void 0) {
7140
+ return statusCodeFromCode;
8286
7141
  }
8287
- return process.env["XDG_CONFIG_HOME"] ?? path.join(os.homedir(), ".config");
7142
+ if (isCustomerUsageError(appError)) {
7143
+ return 400;
7144
+ }
7145
+ return 500;
8288
7146
  }
8289
- function resolveRefreshTokenStoreKind() {
8290
- return process.env["MAGICAL_CLI_REFRESH_TOKEN_STORE"] === "file" ? "file" : "keytar";
7147
+ function normalizeUserFacingErrorCode({ type, fallbackCode, prefix }) {
7148
+ if (!type) {
7149
+ return fallbackCode;
7150
+ }
7151
+ const normalized = normalizeErrorCodeSegment(type);
7152
+ if (normalized.length === 0) {
7153
+ return fallbackCode;
7154
+ }
7155
+ const normalizedPrefix = prefix ? normalizeErrorCodeSegment(prefix) : void 0;
7156
+ if (!normalizedPrefix) {
7157
+ return normalized;
7158
+ }
7159
+ if (normalized.startsWith(`${normalizedPrefix}_`)) {
7160
+ return normalized;
7161
+ }
7162
+ return `${normalizedPrefix}_${normalized}`;
8291
7163
  }
8292
- function getRuntimeConfig() {
8293
- const configDirectory = path.join(
8294
- resolvePlatformConfigDirectory(),
8295
- CLI_CONFIG_DIRECTORY_NAME
8296
- );
7164
+ function toUserFacingApiErrorFromAppError({ appError, correlationId, statusCode }) {
7165
+ const resolvedStatusCode = statusCode ?? getStatusCodeForAppErrorFromAppError(appError);
7166
+ const message = resolveApiMessage({
7167
+ appError,
7168
+ statusCode: resolvedStatusCode
7169
+ });
7170
+ const suggestedAction = resolveSuggestedAction({
7171
+ appError,
7172
+ statusCode: resolvedStatusCode
7173
+ });
7174
+ const details = resolveApiDetails({
7175
+ appError,
7176
+ statusCode: resolvedStatusCode
7177
+ });
8297
7178
  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
7179
+ code: resolveApiErrorCode({
7180
+ appError,
7181
+ statusCode: resolvedStatusCode
7182
+ }),
7183
+ message,
7184
+ correlationId,
7185
+ suggestedAction,
7186
+ ...details ? { details } : {}
8311
7187
  };
8312
7188
  }
8313
- function requireWorkosClientId(config) {
8314
- return config.workosClientId;
7189
+ function toUserFacingGraphQLErrorFromAppError({ appError, correlationId }) {
7190
+ const code = resolveGraphQLErrorCode(appError);
7191
+ const statusCode = getStatusCodeFromGraphQLErrorCode(code);
7192
+ const apiError = toUserFacingApiErrorFromAppError({
7193
+ appError,
7194
+ correlationId,
7195
+ statusCode
7196
+ });
7197
+ return {
7198
+ code,
7199
+ errorCode: getGraphQLAppErrorCode({ code, apiCode: apiError.code }),
7200
+ message: getGraphQLErrorMessage({ code, apiMessage: apiError.message }),
7201
+ correlationId
7202
+ };
8315
7203
  }
8316
7204
 
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
- // ../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");
7205
+ // ../common/dist/src/stdlib/error.js
7206
+ var INTERNAL_STACK_PATHS = [
7207
+ "/src/stdlib/result.util.ts",
7208
+ "/src/stdlib/error.ts"
7209
+ ];
7210
+ function stripInternalFrames(stack, internalFrames) {
7211
+ const lines = stack.split("\n");
7212
+ return lines.filter((line) => !internalFrames.some((internalFrame) => line.includes(internalFrame)));
8360
7213
  }
8361
- function getStatusCodeFromAppErrorCode(code) {
8362
- if (typeof code !== "number" || !Number.isInteger(code)) {
8363
- return void 0;
7214
+ var ORDERED_APP_ERROR_CATEGORIES = [
7215
+ "internal_platform",
7216
+ "customer_usage",
7217
+ "third_party"
7218
+ ];
7219
+ function isAppErrorCategory(category) {
7220
+ return typeof category === "string" && // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
7221
+ ORDERED_APP_ERROR_CATEGORIES.includes(category);
7222
+ }
7223
+ function isNonEmptyAppErrorCategoryArray(categories) {
7224
+ return Array.isArray(categories) && categories.length > 0 && categories.every(isAppErrorCategory);
7225
+ }
7226
+ var APP_ERROR_SEVERITIES = ["warn", "error", "fatal"];
7227
+ function isAppErrorCode(code) {
7228
+ return typeof code === "number" && Number.isInteger(code) && code >= 400 && code <= 599;
7229
+ }
7230
+ function isAppErrorSeverity(severity) {
7231
+ return typeof severity === "string" && // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
7232
+ APP_ERROR_SEVERITIES.includes(severity);
7233
+ }
7234
+ var AppError = class _AppError extends Error {
7235
+ type;
7236
+ categories;
7237
+ severity;
7238
+ statusCode;
7239
+ suggestedAction;
7240
+ nonRetryable;
7241
+ details;
7242
+ constructor({ type, categories, severity, statusCode, code, message, suggestedAction, cause, nonRetryable, stack, internalFrames, ...details }) {
7243
+ super(_AppError.resolveMessage(message, cause, type), { cause });
7244
+ this.type = type;
7245
+ this.name = type;
7246
+ this.details = details;
7247
+ this.categories = categories ?? _AppError.extractCategoriesFromCause(cause);
7248
+ this.severity = severity ?? _AppError.extractSeverityFromCause(cause);
7249
+ this.statusCode = statusCode ?? code ?? _AppError.extractStatusCodeFromCause(cause);
7250
+ this.suggestedAction = suggestedAction ?? _AppError.extractSuggestedActionFromCause(cause);
7251
+ this.nonRetryable = nonRetryable ?? false;
7252
+ _AppError.applyStack(this, stack, internalFrames);
8364
7253
  }
8365
- if (code >= 400 && code <= 599) {
8366
- return code;
7254
+ static resolveMessage(message, cause, type) {
7255
+ if (message) {
7256
+ return message;
7257
+ }
7258
+ if (cause instanceof Error) {
7259
+ return cause.message;
7260
+ }
7261
+ return type;
7262
+ }
7263
+ static getInheritedCauseField(cause, extractor, seen = /* @__PURE__ */ new Set()) {
7264
+ if (!cause || typeof cause !== "object" || seen.has(cause)) {
7265
+ return void 0;
7266
+ }
7267
+ const causeRecord = cause;
7268
+ const extractedValue = extractor(causeRecord);
7269
+ if (extractedValue !== void 0) {
7270
+ return extractedValue;
7271
+ }
7272
+ return _AppError.getInheritedCauseField(causeRecord["cause"], extractor, new Set(seen).add(cause));
7273
+ }
7274
+ static extractCategoriesFromCause(cause) {
7275
+ return _AppError.getInheritedCauseField(cause, (causeRecord) => {
7276
+ const { categories } = causeRecord;
7277
+ if (isNonEmptyAppErrorCategoryArray(categories)) {
7278
+ return categories;
7279
+ }
7280
+ return void 0;
7281
+ }) ?? ["internal_platform"];
8367
7282
  }
8368
- return void 0;
8369
- }
8370
- function getStatusFamilyFallbackCode(statusCode) {
8371
- if (statusCode >= 400 && statusCode <= 499) {
8372
- return 400;
7283
+ static extractSeverityFromCause(cause) {
7284
+ return _AppError.getInheritedCauseField(cause, (causeRecord) => {
7285
+ const { severity } = causeRecord;
7286
+ return isAppErrorSeverity(severity) ? severity : void 0;
7287
+ }) ?? "error";
8373
7288
  }
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;
7289
+ static extractStatusCodeFromCause(cause) {
7290
+ return _AppError.getInheritedCauseField(cause, (causeRecord) => {
7291
+ const { statusCode } = causeRecord;
7292
+ if (isAppErrorCode(statusCode)) {
7293
+ return statusCode;
7294
+ }
7295
+ const { code: legacyCode } = causeRecord;
7296
+ return isAppErrorCode(legacyCode) ? legacyCode : void 0;
7297
+ });
8380
7298
  }
8381
- return getStatusFamilyFallbackCode(statusCode) === 400 ? "Bad Request" : "Internal Server Error";
8382
- }
8383
- function getDefaultSuggestedAction(statusCode) {
8384
- const directAction = USER_FACING_DEFAULT_ACTIONS.get(statusCode);
8385
- if (directAction !== void 0) {
8386
- return directAction;
7299
+ /** @deprecated Use statusCode instead. */
7300
+ get code() {
7301
+ return this.statusCode;
8387
7302
  }
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
- }
8390
- function getFallbackErrorCode(statusCode) {
8391
- const directCode = USER_FACING_FALLBACK_CODES.get(statusCode);
8392
- if (directCode !== void 0) {
8393
- return directCode;
7303
+ static extractSuggestedActionFromCause(cause) {
7304
+ return _AppError.getInheritedCauseField(cause, (causeRecord) => {
7305
+ const { suggestedAction } = causeRecord;
7306
+ if (typeof suggestedAction !== "string") {
7307
+ return void 0;
7308
+ }
7309
+ const trimmedSuggestedAction = suggestedAction.trim();
7310
+ return trimmedSuggestedAction.length > 0 ? trimmedSuggestedAction : void 0;
7311
+ });
8394
7312
  }
8395
- return getStatusFamilyFallbackCode(statusCode) === 400 ? "BAD_REQUEST" : "INTERNAL_SERVER_ERROR";
8396
- }
8397
- function shouldExposeMessage({ appError, statusCode }) {
8398
- if (statusCode >= 500) {
8399
- return false;
7313
+ static applyStack(error, stack, internalFrames) {
7314
+ if (stack) {
7315
+ error.stack = stack;
7316
+ }
7317
+ error.stack &&= stripInternalFrames(error.stack, [
7318
+ ...INTERNAL_STACK_PATHS,
7319
+ ...internalFrames ?? []
7320
+ ]).join("\n");
8400
7321
  }
8401
- return isCustomerUsageError(appError);
8402
- }
8403
- function resolveApiMessage({ appError, statusCode }) {
8404
- if (!shouldExposeMessage({ appError, statusCode })) {
8405
- return getStatusMessage(statusCode);
7322
+ toApiError({ correlationId }) {
7323
+ return toUserFacingApiError({
7324
+ error: this,
7325
+ correlationId,
7326
+ statusCode: getStatusCodeForAppError(this)
7327
+ });
8406
7328
  }
8407
- const trimmedMessage = appError.message.trim();
8408
- if (trimmedMessage.length > 0) {
8409
- return trimmedMessage;
7329
+ toGqlError({ correlationId }) {
7330
+ return toUserFacingGraphQLError({
7331
+ error: this,
7332
+ correlationId
7333
+ });
8410
7334
  }
8411
- return getStatusMessage(statusCode);
7335
+ };
7336
+ function toAppError(error) {
7337
+ return error instanceof AppError ? error : new AppError(error);
8412
7338
  }
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
- });
7339
+ function getStatusCodeForAppError(error) {
7340
+ const appError = toAppError(error);
7341
+ return getStatusCodeForAppErrorFromAppError(appError);
8421
7342
  }
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);
7343
+ function toUserFacingApiError({ error, correlationId, statusCode }) {
7344
+ const appError = toAppError(error);
7345
+ return toUserFacingApiErrorFromAppError({
7346
+ appError,
7347
+ correlationId,
7348
+ statusCode
7349
+ });
8428
7350
  }
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;
7351
+ function toUserFacingGraphQLError({ error, correlationId }) {
7352
+ const appError = toAppError(error);
7353
+ return toUserFacingGraphQLErrorFromAppError({
7354
+ appError,
7355
+ correlationId
7356
+ });
8440
7357
  }
8441
- function toUserFacingDetailsValue(value, depth) {
8442
- if (depth < 0) {
8443
- return void 0;
7358
+
7359
+ // ../common/dist/src/stdlib/result.util.js
7360
+ var Result;
7361
+ (function(Result2) {
7362
+ function partition(responses) {
7363
+ const oks = responses.filter((resp) => resp._tag === "Ok").map((resp) => resp.value);
7364
+ const errs = responses.filter((resp) => resp._tag === "Err").map((resp) => resp.error);
7365
+ return [oks, errs];
8444
7366
  }
8445
- if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
8446
- return value;
7367
+ Result2.partition = partition;
7368
+ async function promiseAllAndPartition(promises) {
7369
+ const results = await Promise.all(promises);
7370
+ return partition(results);
8447
7371
  }
8448
- if (Array.isArray(value)) {
8449
- const serializedValues = value.map((item) => toUserFacingDetailsValue(item, depth - 1)).filter((item) => item !== void 0);
8450
- return serializedValues;
7372
+ Result2.promiseAllAndPartition = promiseAllAndPartition;
7373
+ function unwrapOrThrow(result) {
7374
+ if (isErr(result)) {
7375
+ throw result.error;
7376
+ }
7377
+ return result.value;
8451
7378
  }
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;
7379
+ Result2.unwrapOrThrow = unwrapOrThrow;
7380
+ async function all(promises) {
7381
+ const results = await fromThrowable(async () => Promise.all(promises.map(async (promise) => {
7382
+ const result = await promise;
7383
+ if (isErr(result)) {
7384
+ throw result.error;
8458
7385
  }
7386
+ return result;
7387
+ })), "unknown-error");
7388
+ if (isErr(results)) {
7389
+ return ErrFromThrowable(results.error.cause);
8459
7390
  }
8460
- if (Object.keys(serializedObject).length === 0) {
8461
- return void 0;
7391
+ return Ok(results.value.map((r) => r.value));
7392
+ }
7393
+ Result2.all = all;
7394
+ function andThenSync(fnFirst, ...fns) {
7395
+ let result = fnFirst();
7396
+ const values = [];
7397
+ for (const fn of fns) {
7398
+ if (isErr(result)) {
7399
+ return result;
7400
+ }
7401
+ values.unshift(result.value);
7402
+ result = fn(...values);
8462
7403
  }
8463
- return serializedObject;
7404
+ return result;
8464
7405
  }
8465
- return void 0;
8466
- }
8467
- function resolveApiDetails({ appError, statusCode }) {
8468
- if (!shouldExposeMessage({ appError, statusCode })) {
8469
- return void 0;
7406
+ Result2.andThenSync = andThenSync;
7407
+ async function andThen(fnFirst, ...fns) {
7408
+ let result = await fnFirst();
7409
+ const values = [];
7410
+ for (const fn of fns) {
7411
+ if (isErr(result)) {
7412
+ return result;
7413
+ }
7414
+ values.unshift(result.value);
7415
+ result = await fn(...values);
7416
+ }
7417
+ return result;
8470
7418
  }
8471
- const zodIssues = getZodIssuesFromCause(appError.cause);
8472
- if (zodIssues && zodIssues.length > 0) {
7419
+ Result2.andThen = andThen;
7420
+ })(Result || (Result = {}));
7421
+ function Ok(value) {
7422
+ if (arguments.length === 0) {
8473
7423
  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
- }))
7424
+ _tag: "Ok",
7425
+ value: void 0
8479
7426
  };
8480
7427
  }
8481
- const rawDetails = toUserFacingDetailsValue(appError.details, 4);
8482
- if (rawDetails && typeof rawDetails === "object" && !Array.isArray(rawDetails) && Object.keys(rawDetails).length > 0) {
8483
- return rawDetails;
7428
+ return {
7429
+ _tag: "Ok",
7430
+ value
7431
+ };
7432
+ }
7433
+ function Err(error) {
7434
+ return {
7435
+ _tag: "Err",
7436
+ error: new AppError(error)
7437
+ };
7438
+ }
7439
+ function ErrFromThrowable(error) {
7440
+ return {
7441
+ _tag: "Err",
7442
+ error
7443
+ };
7444
+ }
7445
+ function isErr(result) {
7446
+ return result._tag === "Err";
7447
+ }
7448
+ function fromThrowable(fn, errorType, errorInfo) {
7449
+ try {
7450
+ const result = fn();
7451
+ if (result && typeof result.then === "function") {
7452
+ return result.then((value) => Ok(value)).catch((err) => Err({
7453
+ ...errorInfo,
7454
+ type: errorType,
7455
+ cause: err
7456
+ }));
7457
+ }
7458
+ return Ok(result);
7459
+ } catch (err) {
7460
+ return Err({
7461
+ ...errorInfo,
7462
+ type: errorType,
7463
+ cause: err
7464
+ });
8484
7465
  }
8485
- return void 0;
8486
7466
  }
8487
- function getGraphQLErrorCodeFromAppErrorCode(code) {
8488
- if (code === 400) {
8489
- return "BAD_USER_INPUT";
8490
- }
8491
- if (code === 401) {
8492
- return "UNAUTHORIZED";
8493
- }
8494
- if (code === 403) {
8495
- return "FORBIDDEN";
8496
- }
8497
- if (code === 404) {
8498
- return "NOT_FOUND";
8499
- }
8500
- if (code === 500) {
8501
- return "INTERNAL_SERVER_ERROR";
7467
+
7468
+ // ../common/dist/src/stdlib/json.util.js
7469
+ function safeJsonParse(json) {
7470
+ try {
7471
+ return Ok(JSON.parse(json));
7472
+ } catch (error) {
7473
+ console.warn("Failed to parse JSON", { error, json });
7474
+ return Err({ type: "invalid-json", cause: error, json });
8502
7475
  }
8503
- return void 0;
8504
7476
  }
8505
- function resolveGraphQLErrorCode(appError) {
8506
- const codeFromAppErrorCode = getGraphQLErrorCodeFromAppErrorCode(appError.statusCode);
8507
- if (codeFromAppErrorCode !== void 0) {
8508
- return codeFromAppErrorCode;
8509
- }
8510
- const normalizedErrorType = appError.type.toLowerCase();
8511
- if (normalizedErrorType.includes("unauthorized")) {
8512
- return "UNAUTHORIZED";
8513
- }
8514
- if (normalizedErrorType.includes("forbidden")) {
8515
- return "FORBIDDEN";
8516
- }
8517
- if (normalizedErrorType.includes("not-found")) {
8518
- return "NOT_FOUND";
7477
+
7478
+ // ../mcp-registry/src/operation-specs.ts
7479
+ import { z as z2 } from "zod";
7480
+
7481
+ // ../mcp-registry/src/operation-spec.ts
7482
+ function stripLeadingGraphqlComments(document) {
7483
+ return document.replace(/^(?:\s*#.*\n)+/u, "").trimStart();
7484
+ }
7485
+ function assertDocumentMatchesOperation({
7486
+ document,
7487
+ kind,
7488
+ operationName
7489
+ }) {
7490
+ const normalizedDocument = stripLeadingGraphqlComments(document);
7491
+ const match = /^(?<actualKind>query|mutation)\s+(?<actualOperationName>[_A-Za-z][_0-9A-Za-z]*)/u.exec(
7492
+ normalizedDocument
7493
+ );
7494
+ const actualKind = match?.groups?.["actualKind"];
7495
+ const actualOperationName = match?.groups?.["actualOperationName"];
7496
+ if (!actualKind || !actualOperationName) {
7497
+ throw new Error(
7498
+ `Operation "${operationName}" is missing a top-level GraphQL ${kind} definition.`
7499
+ );
8519
7500
  }
8520
- if (isCustomerUsageError(appError)) {
8521
- return "BAD_USER_INPUT";
7501
+ if (actualKind !== kind || actualOperationName !== operationName) {
7502
+ throw new Error(
7503
+ `Operation "${operationName}" does not match its GraphQL document (${actualKind} ${actualOperationName}).`
7504
+ );
8522
7505
  }
8523
- return "INTERNAL_SERVER_ERROR";
8524
7506
  }
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;
7507
+ function createOperationSpec(spec) {
7508
+ assertDocumentMatchesOperation(spec);
7509
+ return spec;
7510
+ }
7511
+
7512
+ // ../mcp-registry/src/operation-specs.ts
7513
+ function stringOption({
7514
+ description,
7515
+ flagName,
7516
+ inputKey,
7517
+ required = false
7518
+ }) {
7519
+ return {
7520
+ description,
7521
+ flagName,
7522
+ inputKey,
7523
+ required,
7524
+ valueType: "string"
7525
+ };
7526
+ }
7527
+ function numberOption({
7528
+ description,
7529
+ flagName,
7530
+ inputKey,
7531
+ required = false
7532
+ }) {
7533
+ return {
7534
+ description,
7535
+ flagName,
7536
+ inputKey,
7537
+ required,
7538
+ valueType: "number"
7539
+ };
7540
+ }
7541
+ function booleanOption({
7542
+ description,
7543
+ flagName,
7544
+ inputKey
7545
+ }) {
7546
+ return {
7547
+ description,
7548
+ flagName,
7549
+ inputKey,
7550
+ valueType: "boolean"
7551
+ };
7552
+ }
7553
+ function stringArrayOption({
7554
+ description,
7555
+ flagName,
7556
+ inputKey,
7557
+ required = false
7558
+ }) {
7559
+ return {
7560
+ description,
7561
+ flagName,
7562
+ inputKey,
7563
+ required,
7564
+ valueHint: "comma-separated",
7565
+ valueType: "string-array"
7566
+ };
7567
+ }
7568
+ function jsonOption({
7569
+ description,
7570
+ flagName,
7571
+ inputKey,
7572
+ required = false
7573
+ }) {
7574
+ return {
7575
+ description,
7576
+ flagName,
7577
+ inputKey,
7578
+ required,
7579
+ valueHint: "JSON",
7580
+ valueType: "json"
7581
+ };
7582
+ }
7583
+ var jsonObjectSchema = z2.record(z2.string(), z2.unknown());
7584
+ var agentBrowserProviderOptionsSelection = ` browserbase {
7585
+ advancedStealth
7586
+ contextId
7587
+ extensionId
7588
+ instanceSize
7589
+ blockAds
7590
+ solveCaptchas
7591
+ viewport {
7592
+ width
7593
+ height
7594
+ }
7595
+ }
7596
+ agentCore {
7597
+ viewport {
7598
+ width
7599
+ height
7600
+ }
7601
+ enableWebBotAuth
7602
+ }
7603
+ local {
7604
+ viewport {
7605
+ width
7606
+ height
7607
+ }
7608
+ }
7609
+ hyperbrowser {
7610
+ viewport {
7611
+ width
7612
+ height
7613
+ }
7614
+ }
7615
+ steel {
7616
+ extensionIds
7617
+ region
7618
+ solveCaptcha
7619
+ viewport {
7620
+ width
7621
+ height
7622
+ }
7623
+ }`;
7624
+ var agentEnvironmentOptionsSelection = ` environmentOptions {
7625
+ __typename
7626
+ ... on AgentConfig_environmentOptions_Browser {
7627
+ environment
7628
+ maxMediaToIncludeInMemory
7629
+ saveAuthCookiesAfterRun
7630
+ startingUrl
7631
+ browserProvider
7632
+ browserProviderOptions {
7633
+ ${agentBrowserProviderOptionsSelection}
7634
+ }
7635
+ }
7636
+ ... on AgentConfig_environmentOptions_Browsercoordinates {
7637
+ environment
7638
+ maxMediaToIncludeInMemory
7639
+ saveAuthCookiesAfterRun
7640
+ startingUrl
7641
+ browserProvider
7642
+ browserProviderOptions {
7643
+ ${agentBrowserProviderOptionsSelection}
7644
+ }
7645
+ }
7646
+ ... on AgentConfig_environmentOptions_Desktop {
7647
+ environment
7648
+ browserProvider
7649
+ browserProviderOptions {
7650
+ ${agentBrowserProviderOptionsSelection}
7651
+ }
7652
+ maxMediaToIncludeInMemory
7653
+ startingUrl
7654
+ useCopyPasteForTyping
7655
+ }
7656
+ ... on AgentConfig_environmentOptions_Desktopapp {
7657
+ environment
7658
+ maxMediaToIncludeInMemory
7659
+ }
7660
+ ... on AgentConfig_environmentOptions_Minimal {
7661
+ environment
7662
+ }
7663
+ }`;
7664
+ var agentLimitationsSelection = ` limitations {
7665
+ maxDurationSeconds
7666
+ maxToolCalls
7667
+ allowedUrlRegexes
7668
+ }`;
7669
+ var operationSpecs = [
7670
+ createOperationSpec({
7671
+ operationName: "GetAgents",
7672
+ kind: "query",
7673
+ inputSchema: z2.object({
7674
+ ids: z2.array(z2.string().min(1)).min(1)
7675
+ }),
7676
+ cli: {
7677
+ name: "get-agents",
7678
+ path: ["agents", "get"],
7679
+ description: "Fetch one or more agents with config and schema fields.",
7680
+ resultKey: "agents",
7681
+ options: [
7682
+ stringArrayOption({
7683
+ inputKey: "ids",
7684
+ flagName: "ids",
7685
+ description: "Agent IDs.",
7686
+ required: true
7687
+ })
7688
+ ]
7689
+ },
7690
+ mcp: { fileName: "agents.graphql" },
7691
+ document: `# Query to fetch multiple agents with all fields
7692
+ # Includes nested environment and limitation config fields
7693
+ query GetAgents($ids: [ID!]!) {
7694
+ agents(ids: $ids) {
7695
+ id
7696
+ name
7697
+ description
7698
+ instructions
7699
+ organizationId
7700
+ createdAt
7701
+ updatedAt
7702
+ sourceAgentId
7703
+ inputSchema
7704
+ outputSchema
7705
+ config {
7706
+ type
7707
+ language
7708
+ model
7709
+ tools
7710
+ maxSessionMessages
7711
+ ${agentEnvironmentOptionsSelection}
7712
+ ${agentLimitationsSelection}
7713
+ commonParametersSchema
7714
+ taskQueue
7715
+ waitUponQueueing
7716
+ queueableAgentIds
7717
+ additionalSystemPrompt
7718
+ ignoreUnstableSessionState
8535
7719
  }
8536
- case "NOT_FOUND": {
8537
- return 404;
7720
+ childAgentIds
8538
7721
  }
8539
- case "INTERNAL_SERVER_ERROR": {
8540
- return 500;
7722
+ }`
7723
+ }),
7724
+ createOperationSpec({
7725
+ operationName: "GetAgentVersion",
7726
+ kind: "query",
7727
+ inputSchema: z2.object({
7728
+ agentId: z2.string().min(1),
7729
+ versionId: z2.string().min(1)
7730
+ }),
7731
+ cli: {
7732
+ name: "get-agent-version",
7733
+ path: ["agents", "versions", "get"],
7734
+ description: "Fetch one saved version for an agent.",
7735
+ resultKey: "agentVersion",
7736
+ options: [
7737
+ stringOption({
7738
+ inputKey: "agentId",
7739
+ flagName: "agent-id",
7740
+ description: "Agent ID.",
7741
+ required: true
7742
+ }),
7743
+ stringOption({
7744
+ inputKey: "versionId",
7745
+ flagName: "version-id",
7746
+ description: "Agent version ID.",
7747
+ required: true
7748
+ })
7749
+ ]
7750
+ },
7751
+ mcp: { fileName: "agentVersion.graphql" },
7752
+ document: `# Query to fetch a specific saved version for an agent
7753
+ query GetAgentVersion($agentId: ID!, $versionId: ID!) {
7754
+ agentVersion(agentId: $agentId, versionId: $versionId) {
7755
+ id
7756
+ agentId
7757
+ sequence
7758
+ name
7759
+ description
7760
+ instructions
7761
+ instructionsMode
7762
+ instructionsDoc
7763
+ updaterUserId
7764
+ createdAt
7765
+ updatedAt
7766
+ inputSchema
7767
+ outputSchema
7768
+ config {
7769
+ type
7770
+ language
7771
+ model
7772
+ tools
7773
+ maxSessionMessages
7774
+ ${agentEnvironmentOptionsSelection}
7775
+ ${agentLimitationsSelection}
7776
+ commonParametersSchema
7777
+ taskQueue
7778
+ waitUponQueueing
7779
+ queueableAgentIds
7780
+ additionalSystemPrompt
7781
+ ignoreUnstableSessionState
8541
7782
  }
7783
+ isCurrent
8542
7784
  }
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";
7785
+ }`
7786
+ }),
7787
+ createOperationSpec({
7788
+ operationName: "GetAgentVersions",
7789
+ kind: "query",
7790
+ inputSchema: z2.object({
7791
+ agentId: z2.string().min(1)
7792
+ }),
7793
+ cli: {
7794
+ name: "get-agent-versions",
7795
+ path: ["agents", "versions", "list"],
7796
+ description: "Fetch version history for an agent.",
7797
+ resultKey: "agentVersions",
7798
+ options: [
7799
+ stringOption({
7800
+ inputKey: "agentId",
7801
+ flagName: "agent-id",
7802
+ description: "Agent ID.",
7803
+ required: true
7804
+ })
7805
+ ]
7806
+ },
7807
+ mcp: { fileName: "agentVersions.graphql" },
7808
+ document: `# Query to fetch version history metadata for an agent
7809
+ query GetAgentVersions($agentId: ID!) {
7810
+ agentVersions(agentId: $agentId) {
7811
+ id
7812
+ sequence
7813
+ name
7814
+ description
7815
+ updaterUserId
7816
+ createdAt
7817
+ updatedAt
7818
+ isCurrent
7819
+ }
7820
+ }`
7821
+ }),
7822
+ createOperationSpec({
7823
+ operationName: "DiffAgentVersion",
7824
+ kind: "query",
7825
+ inputSchema: z2.object({
7826
+ agentId: z2.string().min(1),
7827
+ versionId: z2.string().min(1),
7828
+ compareVersionId: z2.string().min(1).optional()
7829
+ }),
7830
+ cli: {
7831
+ name: "diff-agent-version",
7832
+ path: ["agents", "versions", "diff"],
7833
+ description: "Diff one agent version against another version or the current latest version.",
7834
+ resultKey: "agentVersionDiff",
7835
+ options: [
7836
+ stringOption({
7837
+ inputKey: "agentId",
7838
+ flagName: "agent-id",
7839
+ description: "Agent ID.",
7840
+ required: true
7841
+ }),
7842
+ stringOption({
7843
+ inputKey: "versionId",
7844
+ flagName: "version-id",
7845
+ description: "Source agent version ID.",
7846
+ required: true
7847
+ }),
7848
+ stringOption({
7849
+ inputKey: "compareVersionId",
7850
+ flagName: "compare-version-id",
7851
+ description: "Optional target version ID. Defaults to the current latest version."
7852
+ })
7853
+ ]
7854
+ },
7855
+ mcp: { fileName: "agentVersionDiff.graphql" },
7856
+ document: `# Query to diff one agent version against another or the current latest version
7857
+ query DiffAgentVersion(
7858
+ $agentId: ID!
7859
+ $versionId: ID!
7860
+ $compareVersionId: ID
7861
+ ) {
7862
+ agentVersionDiff(
7863
+ agentId: $agentId
7864
+ versionId: $versionId
7865
+ compareVersionId: $compareVersionId
7866
+ ) {
7867
+ agentId
7868
+ fromVersionId
7869
+ toVersionId
7870
+ hasChanges
7871
+ changes {
7872
+ field
7873
+ oldValue
7874
+ newValue
8553
7875
  }
8554
- case "FORBIDDEN": {
8555
- return "Forbidden";
7876
+ }
7877
+ }`
7878
+ }),
7879
+ createOperationSpec({
7880
+ operationName: "GetAgentRun",
7881
+ kind: "query",
7882
+ inputSchema: z2.object({
7883
+ id: z2.string().min(1)
7884
+ }),
7885
+ cli: {
7886
+ name: "get-agent-run",
7887
+ path: ["agent-runs", "get"],
7888
+ description: "Fetch a single agent run.",
7889
+ resultKey: "agentRun",
7890
+ options: [
7891
+ stringOption({
7892
+ inputKey: "id",
7893
+ flagName: "id",
7894
+ description: "Agent run ID.",
7895
+ required: true
7896
+ })
7897
+ ]
7898
+ },
7899
+ mcp: { fileName: "agentRun.graphql" },
7900
+ document: `# Query a single agent run
7901
+ query GetAgentRun($id: ID!) {
7902
+ agentRun(id: $id) {
7903
+ id
7904
+ agentVersionId
7905
+ agentName
7906
+ status
7907
+ statusDetail
7908
+ isChildAgent
7909
+ input
7910
+ startedAt
7911
+ finishedAt
7912
+ parentAgentRunId
7913
+ }
7914
+ }`
7915
+ }),
7916
+ createOperationSpec({
7917
+ operationName: "GetAutomationAgents",
7918
+ kind: "query",
7919
+ inputSchema: z2.object({
7920
+ ids: z2.array(z2.string().min(1)).min(1)
7921
+ }),
7922
+ cli: {
7923
+ name: "get-automation-agents",
7924
+ path: ["automations", "agents"],
7925
+ description: "Fetch the agents attached to one or more automations.",
7926
+ resultKey: "automationAgents",
7927
+ options: [
7928
+ stringArrayOption({
7929
+ inputKey: "ids",
7930
+ flagName: "ids",
7931
+ description: "Automation IDs.",
7932
+ required: true
7933
+ })
7934
+ ]
7935
+ },
7936
+ mcp: { fileName: "automationAgents.graphql" },
7937
+ document: `# Query automation agent relationships with flat agent fields only
7938
+ # Excludes nested agent config and schemas for MCP tool simplicity
7939
+ query GetAutomationAgents($ids: [ID!]!) {
7940
+ automationAgents(ids: $ids) {
7941
+ automationId
7942
+ agentId
7943
+ isTrigger
7944
+ agent {
7945
+ id
7946
+ name
7947
+ description
7948
+ instructions
7949
+ organizationId
7950
+ createdAt
7951
+ updatedAt
7952
+ sourceAgentId
7953
+ childAgentIds
8556
7954
  }
8557
7955
  }
8558
- }
8559
- function getGraphQLAppErrorCode({ code, apiCode }) {
8560
- if (code === "INTERNAL_SERVER_ERROR" || code === "UNAUTHORIZED" || code === "FORBIDDEN") {
8561
- return code;
8562
- }
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;
8572
- }
8573
- if (isCustomerUsageError(appError)) {
8574
- return 400;
8575
- }
8576
- return 500;
8577
- }
8578
- function normalizeUserFacingErrorCode({ type, fallbackCode, prefix }) {
8579
- if (!type) {
8580
- return fallbackCode;
8581
- }
8582
- const normalized = normalizeErrorCodeSegment(type);
8583
- if (normalized.length === 0) {
8584
- return fallbackCode;
7956
+ }`
7957
+ }),
7958
+ createOperationSpec({
7959
+ operationName: "GetAutomationRun",
7960
+ kind: "query",
7961
+ inputSchema: z2.object({
7962
+ id: z2.string().min(1)
7963
+ }),
7964
+ cli: {
7965
+ name: "get-automation-run",
7966
+ path: ["automation-runs", "get"],
7967
+ description: "Fetch a single automation run.",
7968
+ resultKey: "automationRun",
7969
+ options: [
7970
+ stringOption({
7971
+ inputKey: "id",
7972
+ flagName: "id",
7973
+ description: "Automation run ID.",
7974
+ required: true
7975
+ })
7976
+ ]
7977
+ },
7978
+ mcp: { fileName: "automationRun.graphql" },
7979
+ document: `# Query a full automation run details payload
7980
+ query GetAutomationRun($id: ID!) {
7981
+ automationRun(id: $id) {
7982
+ id
7983
+ automationId
7984
+ parentAutomationRunId
7985
+ status
7986
+ statusDetail
7987
+ summary
7988
+ invocationType
7989
+ input
7990
+ additionalPrompt
7991
+ debugUrl
7992
+ createdAt
7993
+ startedAt
7994
+ pausedAt
7995
+ finishedAt
8585
7996
  }
8586
- const normalizedPrefix = prefix ? normalizeErrorCodeSegment(prefix) : void 0;
8587
- if (!normalizedPrefix) {
8588
- return normalized;
7997
+ }`
7998
+ }),
7999
+ createOperationSpec({
8000
+ operationName: "GetAutomationRunAgentRuns",
8001
+ kind: "query",
8002
+ inputSchema: z2.object({
8003
+ automationRunId: z2.string().min(1)
8004
+ }),
8005
+ cli: {
8006
+ name: "get-automation-run-agent-runs",
8007
+ path: ["automation-runs", "agent-runs"],
8008
+ description: "Fetch ordered agent runs for an automation run.",
8009
+ resultKey: "automationRunAgentRuns",
8010
+ options: [
8011
+ stringOption({
8012
+ inputKey: "automationRunId",
8013
+ flagName: "automation-run-id",
8014
+ description: "Automation run ID.",
8015
+ required: true
8016
+ })
8017
+ ]
8018
+ },
8019
+ mcp: { fileName: "automationRunAgentRuns.graphql" },
8020
+ document: `# Query ordered agent runs for an automation run
8021
+ query GetAutomationRunAgentRuns($automationRunId: ID!) {
8022
+ automationRunAgentRuns(automationRunId: $automationRunId) {
8023
+ id
8024
+ agentVersionId
8025
+ agentName
8026
+ status
8027
+ statusDetail
8028
+ isChildAgent
8029
+ input
8030
+ startedAt
8031
+ finishedAt
8032
+ parentAgentRunId
8589
8033
  }
8590
- if (normalized.startsWith(`${normalizedPrefix}_`)) {
8591
- return normalized;
8034
+ }`
8035
+ }),
8036
+ createOperationSpec({
8037
+ operationName: "GetAutomationRunIterations",
8038
+ kind: "query",
8039
+ inputSchema: z2.object({
8040
+ automationRunId: z2.string().min(1),
8041
+ agentRunId: z2.string().min(1).optional(),
8042
+ limit: z2.number().int().positive().optional(),
8043
+ reverse: z2.boolean().optional()
8044
+ }),
8045
+ cli: {
8046
+ name: "get-automation-run-iterations",
8047
+ path: ["automation-runs", "iterations"],
8048
+ description: "Fetch ordered iterations for an automation run.",
8049
+ resultKey: "automationRunIterations",
8050
+ options: [
8051
+ stringOption({
8052
+ inputKey: "automationRunId",
8053
+ flagName: "automation-run-id",
8054
+ description: "Automation run ID.",
8055
+ required: true
8056
+ }),
8057
+ stringOption({
8058
+ inputKey: "agentRunId",
8059
+ flagName: "agent-run-id",
8060
+ description: "Optional agent run ID to filter by."
8061
+ }),
8062
+ numberOption({
8063
+ inputKey: "limit",
8064
+ flagName: "limit",
8065
+ description: "Maximum number of iterations to return."
8066
+ }),
8067
+ booleanOption({
8068
+ inputKey: "reverse",
8069
+ flagName: "reverse",
8070
+ description: "Return newest iterations first."
8071
+ })
8072
+ ]
8073
+ },
8074
+ mcp: { fileName: "automationRunIterations.graphql" },
8075
+ document: `# Query iterations for an automation run with optional filtering by agent run
8076
+ query GetAutomationRunIterations(
8077
+ $automationRunId: ID!
8078
+ $agentRunId: ID
8079
+ $limit: Int
8080
+ $reverse: Boolean
8081
+ ) {
8082
+ automationRunIterations(
8083
+ automationRunId: $automationRunId
8084
+ agentRunId: $agentRunId
8085
+ limit: $limit
8086
+ reverse: $reverse
8087
+ ) {
8088
+ id
8089
+ sequence
8090
+ agentRunId
8091
+ metadata
8092
+ startedAt
8093
+ finishedAt
8094
+ totalDurationMs
8095
+ llmResponseDurationMs
8096
+ withMarksScreenshotUrl
8097
+ withMarksMimeType
8098
+ memories {
8099
+ id
8100
+ type
8101
+ value
8102
+ sequence
8103
+ screenshotUrl
8104
+ screenshotMimeType
8105
+ }
8592
8106
  }
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
8107
+ }`
8108
+ }),
8109
+ createOperationSpec({
8110
+ operationName: "GetAutomationRuns",
8111
+ kind: "query",
8112
+ inputSchema: z2.object({
8113
+ automationId: z2.string().min(1),
8114
+ status: z2.array(z2.string().min(1)).optional(),
8115
+ invocationType: z2.array(z2.string().min(1)).optional(),
8116
+ limit: z2.number().int().positive().optional(),
8117
+ page: z2.number().int().positive().optional()
8118
+ }),
8119
+ cli: {
8120
+ name: "get-automation-runs",
8121
+ path: ["automation-runs", "list"],
8122
+ description: "Fetch automation run history.",
8123
+ resultKey: "automationRuns",
8124
+ options: [
8125
+ stringOption({
8126
+ inputKey: "automationId",
8127
+ flagName: "automation-id",
8128
+ description: "Automation ID.",
8129
+ required: true
8130
+ }),
8131
+ stringArrayOption({
8132
+ inputKey: "status",
8133
+ flagName: "status",
8134
+ description: "Optional run statuses."
8135
+ }),
8136
+ stringArrayOption({
8137
+ inputKey: "invocationType",
8138
+ flagName: "invocation-type",
8139
+ description: "Optional invocation types."
8140
+ }),
8141
+ numberOption({
8142
+ inputKey: "limit",
8143
+ flagName: "limit",
8144
+ description: "Maximum number of runs to return."
8145
+ }),
8146
+ numberOption({
8147
+ inputKey: "page",
8148
+ flagName: "page",
8149
+ description: "Page number."
8150
+ })
8151
+ ]
8152
+ },
8153
+ mcp: { fileName: "automationRuns.graphql" },
8154
+ document: `# Query automation run history for a specific automation with optional filters
8155
+ query GetAutomationRuns(
8156
+ $automationId: ID!
8157
+ $status: [RunStatus!]
8158
+ $invocationType: [InvocationType!]
8159
+ $limit: Int
8160
+ $page: Int
8161
+ ) {
8162
+ automationRuns(
8163
+ automationId: $automationId
8164
+ status: $status
8165
+ invocationType: $invocationType
8166
+ limit: $limit
8167
+ page: $page
8168
+ ) {
8169
+ id
8170
+ automationId
8171
+ parentAutomationRunId
8172
+ status
8173
+ statusDetail
8174
+ invocationType
8175
+ summary
8176
+ createdAt
8177
+ startedAt
8178
+ pausedAt
8179
+ finishedAt
8180
+ }
8181
+ }`
8182
+ }),
8183
+ createOperationSpec({
8184
+ operationName: "ListAutomations",
8185
+ kind: "query",
8186
+ inputSchema: z2.object({
8187
+ limit: z2.number().positive().optional(),
8188
+ order: jsonObjectSchema.optional(),
8189
+ where: jsonObjectSchema.optional()
8613
8190
  }),
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)));
8644
- }
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);
8653
- }
8654
- function isNonEmptyAppErrorCategoryArray(categories) {
8655
- return Array.isArray(categories) && categories.length > 0 && categories.every(isAppErrorCategory);
8656
- }
8657
- var APP_ERROR_SEVERITIES = ["warn", "error", "fatal"];
8658
- function isAppErrorCode(code) {
8659
- return typeof code === "number" && Number.isInteger(code) && code >= 400 && code <= 599;
8660
- }
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);
8664
- }
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);
8191
+ cli: {
8192
+ name: "list-automations",
8193
+ path: ["automations", "list"],
8194
+ description: "List automations with optional filters.",
8195
+ resultKey: "automations",
8196
+ options: [
8197
+ numberOption({
8198
+ inputKey: "limit",
8199
+ flagName: "limit",
8200
+ description: "Maximum number of automations to return."
8201
+ }),
8202
+ jsonOption({
8203
+ inputKey: "order",
8204
+ flagName: "order-json",
8205
+ description: "GraphQL order object."
8206
+ }),
8207
+ jsonOption({
8208
+ inputKey: "where",
8209
+ flagName: "where-json",
8210
+ description: "GraphQL filter object."
8211
+ })
8212
+ ]
8213
+ },
8214
+ mcp: { fileName: "listAutomations.graphql" },
8215
+ document: `# Query to list automations with flat fields only (no nested objects)
8216
+ # Excludes config and agents for MCP tool simplicity
8217
+ query ListAutomations(
8218
+ $limit: Float
8219
+ $order: AutomationsOrder
8220
+ $where: AutomationsWhereInput
8221
+ ) {
8222
+ automations(limit: $limit, order: $order, where: $where) {
8223
+ id
8224
+ name
8225
+ organizationId
8226
+ createdAt
8227
+ updatedAt
8228
+ environment
8229
+ lastSavedAt
8230
+ publishedVersionId
8231
+ draftVersionId
8684
8232
  }
8685
- static resolveMessage(message, cause, type) {
8686
- if (message) {
8687
- return message;
8688
- }
8689
- if (cause instanceof Error) {
8690
- return cause.message;
8691
- }
8692
- return type;
8233
+ }`
8234
+ }),
8235
+ createOperationSpec({
8236
+ operationName: "GetAutomations",
8237
+ kind: "query",
8238
+ inputSchema: z2.object({
8239
+ ids: z2.array(z2.string().min(1)).min(1)
8240
+ }),
8241
+ cli: {
8242
+ name: "get-automations",
8243
+ path: ["automations", "get"],
8244
+ description: "Fetch one or more automations by IDs.",
8245
+ resultKey: "automations",
8246
+ options: [
8247
+ stringArrayOption({
8248
+ inputKey: "ids",
8249
+ flagName: "ids",
8250
+ description: "Automation IDs.",
8251
+ required: true
8252
+ })
8253
+ ]
8254
+ },
8255
+ mcp: { fileName: "automations.graphql" },
8256
+ document: `# Query to fetch automations with flat fields only (no nested objects)
8257
+ # Excludes config and agents for MCP tool simplicity
8258
+ query GetAutomations($ids: [ID!]!) {
8259
+ automations(ids: $ids) {
8260
+ id
8261
+ name
8262
+ organizationId
8263
+ createdAt
8264
+ updatedAt
8265
+ environment
8266
+ lastSavedAt
8267
+ publishedVersionId
8268
+ draftVersionId
8693
8269
  }
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;
8702
- }
8703
- return _AppError.getInheritedCauseField(causeRecord["cause"], extractor, new Set(seen).add(cause));
8270
+ }`
8271
+ }),
8272
+ createOperationSpec({
8273
+ operationName: "GetAvailableCommands",
8274
+ kind: "query",
8275
+ inputSchema: z2.object({
8276
+ env: z2.string().min(1)
8277
+ }),
8278
+ cli: {
8279
+ name: "get-available-commands",
8280
+ path: ["catalog", "commands"],
8281
+ description: "Fetch available command definitions by environment.",
8282
+ resultKey: "availableCommands",
8283
+ options: [
8284
+ stringOption({
8285
+ inputKey: "env",
8286
+ flagName: "env",
8287
+ description: "Environment name.",
8288
+ required: true
8289
+ })
8290
+ ]
8291
+ },
8292
+ mcp: { fileName: "availableCommands.graphql" },
8293
+ document: `# Query to fetch available command definitions by environment
8294
+ query GetAvailableCommands($env: AvailableCommandsEnv!) {
8295
+ availableCommands(env: $env) {
8296
+ id
8297
+ description
8298
+ inputSchema
8704
8299
  }
8705
- static extractCategoriesFromCause(cause) {
8706
- return _AppError.getInheritedCauseField(cause, (causeRecord) => {
8707
- const { categories } = causeRecord;
8708
- if (isNonEmptyAppErrorCategoryArray(categories)) {
8709
- return categories;
8300
+ }`
8301
+ }),
8302
+ createOperationSpec({
8303
+ operationName: "GetAvailableModels",
8304
+ kind: "query",
8305
+ inputSchema: z2.object({
8306
+ agentId: z2.string().min(1)
8307
+ }),
8308
+ cli: {
8309
+ name: "get-available-models",
8310
+ path: ["catalog", "models"],
8311
+ description: "Fetch available model definitions for an agent.",
8312
+ resultKey: "availableModels",
8313
+ options: [
8314
+ stringOption({
8315
+ inputKey: "agentId",
8316
+ flagName: "agent-id",
8317
+ description: "Agent ID.",
8318
+ required: true
8319
+ })
8320
+ ]
8321
+ },
8322
+ mcp: { fileName: "availableModels.graphql" },
8323
+ document: `# Query to fetch available model definitions and pools for a specific agent
8324
+ query GetAvailableModels($agentId: String!) {
8325
+ availableModels(agentId: $agentId) {
8326
+ availableModelPools {
8327
+ name
8328
+ poolId
8329
+ models {
8330
+ id
8331
+ name
8332
+ description
8333
+ status
8334
+ provider
8710
8335
  }
8711
- return void 0;
8712
- }) ?? ["internal_platform"];
8336
+ }
8337
+ allAvailableModels {
8338
+ id
8339
+ name
8340
+ description
8341
+ status
8342
+ provider
8343
+ }
8713
8344
  }
8714
- static extractSeverityFromCause(cause) {
8715
- return _AppError.getInheritedCauseField(cause, (causeRecord) => {
8716
- const { severity } = causeRecord;
8717
- return isAppErrorSeverity(severity) ? severity : void 0;
8718
- }) ?? "error";
8345
+ }`
8346
+ }),
8347
+ createOperationSpec({
8348
+ operationName: "GetAvailableTools",
8349
+ kind: "query",
8350
+ inputSchema: z2.object({
8351
+ env: z2.string().min(1),
8352
+ automationId: z2.string().min(1).optional()
8353
+ }),
8354
+ cli: {
8355
+ name: "get-available-tools",
8356
+ path: ["catalog", "tools"],
8357
+ description: "Fetch available tool definitions by environment.",
8358
+ resultKey: "availableTools",
8359
+ options: [
8360
+ stringOption({
8361
+ inputKey: "env",
8362
+ flagName: "env",
8363
+ description: "Environment name.",
8364
+ required: true
8365
+ }),
8366
+ stringOption({
8367
+ inputKey: "automationId",
8368
+ flagName: "automation-id",
8369
+ description: "Optional automation ID."
8370
+ })
8371
+ ]
8372
+ },
8373
+ mcp: { fileName: "availableTools.graphql" },
8374
+ document: `# Query to fetch available tool definitions by environment
8375
+ query GetAvailableTools($env: AvailableCommandsEnv!, $automationId: String) {
8376
+ availableTools(env: $env, automationId: $automationId) {
8377
+ id
8378
+ description
8379
+ inputSchema
8719
8380
  }
8720
- static extractStatusCodeFromCause(cause) {
8721
- return _AppError.getInheritedCauseField(cause, (causeRecord) => {
8722
- const { statusCode } = causeRecord;
8723
- if (isAppErrorCode(statusCode)) {
8724
- return statusCode;
8725
- }
8726
- const { code: legacyCode } = causeRecord;
8727
- return isAppErrorCode(legacyCode) ? legacyCode : void 0;
8728
- });
8381
+ }`
8382
+ }),
8383
+ createOperationSpec({
8384
+ operationName: "CreateAutomation",
8385
+ kind: "mutation",
8386
+ inputSchema: z2.object({
8387
+ input: jsonObjectSchema
8388
+ }),
8389
+ cli: {
8390
+ name: "create-automation",
8391
+ path: ["automations", "create"],
8392
+ description: "Create a draft automation.",
8393
+ resultKey: "createAutomation",
8394
+ options: [
8395
+ jsonOption({
8396
+ inputKey: "input",
8397
+ flagName: "input-json",
8398
+ description: "CreateAutomationInput payload.",
8399
+ required: true
8400
+ })
8401
+ ]
8402
+ },
8403
+ mcp: { fileName: "createAutomation.graphql" },
8404
+ document: `# Mutation to create a draft automation with optional initial values
8405
+ # Returns flat fields only for MCP tool simplicity
8406
+ mutation CreateAutomation($input: CreateAutomationInput!) {
8407
+ createAutomation(input: $input) {
8408
+ id
8409
+ name
8410
+ organizationId
8411
+ createdAt
8412
+ updatedAt
8413
+ environment
8414
+ lastSavedAt
8415
+ publishedVersionId
8416
+ draftVersionId
8729
8417
  }
8730
- /** @deprecated Use statusCode instead. */
8731
- get code() {
8732
- return this.statusCode;
8418
+ }`
8419
+ }),
8420
+ createOperationSpec({
8421
+ operationName: "GetGraphqlSchema",
8422
+ kind: "query",
8423
+ inputSchema: z2.object({}),
8424
+ cli: {
8425
+ name: "get-graphql-schema",
8426
+ path: ["graphql", "schema"],
8427
+ description: "Fetch GraphQL schema metadata.",
8428
+ resultKey: "graphqlSchema",
8429
+ options: []
8430
+ },
8431
+ mcp: { fileName: "graphqlSchema.graphql" },
8432
+ document: `# Query to fetch full GraphQL schema metadata.
8433
+ # Uses the first-class graphqlSchema query field to avoid __schema validation
8434
+ # issues in MCP tool-load paths while still returning introspection JSON.
8435
+ # Response can be large: call sparingly (typically once per task/session) and
8436
+ # reuse cached results.
8437
+ query GetGraphqlSchema {
8438
+ graphqlSchema
8439
+ }`
8440
+ }),
8441
+ createOperationSpec({
8442
+ operationName: "PauseAutomationRun",
8443
+ kind: "mutation",
8444
+ inputSchema: z2.object({
8445
+ automationRunId: z2.string().min(1)
8446
+ }),
8447
+ cli: {
8448
+ name: "pause-automation-run",
8449
+ path: ["automation-runs", "pause"],
8450
+ description: "Pause an automation run.",
8451
+ resultKey: "pauseAutomationRun",
8452
+ options: [
8453
+ stringOption({
8454
+ inputKey: "automationRunId",
8455
+ flagName: "automation-run-id",
8456
+ description: "Automation run ID.",
8457
+ required: true
8458
+ })
8459
+ ]
8460
+ },
8461
+ mcp: { fileName: "pauseAutomationRun.graphql" },
8462
+ document: `# Mutation to pause an automation run
8463
+ mutation PauseAutomationRun($automationRunId: ID!) {
8464
+ pauseAutomationRun(automationRunId: $automationRunId)
8465
+ }`
8466
+ }),
8467
+ createOperationSpec({
8468
+ operationName: "RerunAutomation",
8469
+ kind: "mutation",
8470
+ inputSchema: z2.object({
8471
+ automationRunId: z2.string().min(1),
8472
+ additionalPrompt: z2.string().min(1).optional(),
8473
+ idempotencyKey: z2.string().min(1)
8474
+ }),
8475
+ cli: {
8476
+ name: "rerun-automation",
8477
+ path: ["automation-runs", "rerun"],
8478
+ description: "Rerun an existing automation run.",
8479
+ resultKey: "rerunAutomation",
8480
+ options: [
8481
+ stringOption({
8482
+ inputKey: "automationRunId",
8483
+ flagName: "automation-run-id",
8484
+ description: "Automation run ID.",
8485
+ required: true
8486
+ }),
8487
+ stringOption({
8488
+ inputKey: "additionalPrompt",
8489
+ flagName: "additional-prompt",
8490
+ description: "Optional prompt appended to the rerun."
8491
+ }),
8492
+ stringOption({
8493
+ inputKey: "idempotencyKey",
8494
+ flagName: "idempotency-key",
8495
+ description: "Idempotency key for the rerun request.",
8496
+ required: true
8497
+ })
8498
+ ]
8499
+ },
8500
+ mcp: { fileName: "rerunAutomation.graphql" },
8501
+ document: `# Mutation to rerun an existing automation run
8502
+ mutation RerunAutomation(
8503
+ $automationRunId: ID!
8504
+ $additionalPrompt: String
8505
+ $idempotencyKey: String!
8506
+ ) {
8507
+ rerunAutomation(
8508
+ automationRunId: $automationRunId
8509
+ additionalPrompt: $additionalPrompt
8510
+ idempotencyKey: $idempotencyKey
8511
+ ) {
8512
+ automationRunId
8513
+ workflowId
8514
+ workflowRunId
8515
+ }
8516
+ }`
8517
+ }),
8518
+ createOperationSpec({
8519
+ operationName: "ResumeAutomationRun",
8520
+ kind: "mutation",
8521
+ inputSchema: z2.object({
8522
+ automationRunId: z2.string().min(1),
8523
+ message: z2.string().min(1).optional()
8524
+ }),
8525
+ cli: {
8526
+ name: "resume-automation-run",
8527
+ path: ["automation-runs", "resume"],
8528
+ description: "Resume a paused automation run.",
8529
+ resultKey: "resumeAutomationRun",
8530
+ options: [
8531
+ stringOption({
8532
+ inputKey: "automationRunId",
8533
+ flagName: "automation-run-id",
8534
+ description: "Automation run ID.",
8535
+ required: true
8536
+ }),
8537
+ stringOption({
8538
+ inputKey: "message",
8539
+ flagName: "message",
8540
+ description: "Optional resume message."
8541
+ })
8542
+ ]
8543
+ },
8544
+ mcp: { fileName: "resumeAutomationRun.graphql" },
8545
+ document: `# Mutation to resume an automation run
8546
+ mutation ResumeAutomationRun($automationRunId: ID!, $message: String) {
8547
+ resumeAutomationRun(automationRunId: $automationRunId, message: $message)
8548
+ }`
8549
+ }),
8550
+ createOperationSpec({
8551
+ operationName: "RunDraftAutomation",
8552
+ kind: "mutation",
8553
+ inputSchema: z2.object({
8554
+ draftAutomationId: z2.string().min(1),
8555
+ agentId: z2.string().min(1),
8556
+ idempotencyKey: z2.string().min(1),
8557
+ input: z2.unknown().optional(),
8558
+ additionalPrompt: z2.string().min(1).optional()
8559
+ }),
8560
+ cli: {
8561
+ name: "run-draft-automation",
8562
+ path: ["automations", "run-draft"],
8563
+ description: "Run a draft automation with an explicit trigger agent.",
8564
+ resultKey: "runDraftAutomation",
8565
+ options: [
8566
+ stringOption({
8567
+ inputKey: "draftAutomationId",
8568
+ flagName: "draft-automation-id",
8569
+ description: "Draft automation ID.",
8570
+ required: true
8571
+ }),
8572
+ stringOption({
8573
+ inputKey: "agentId",
8574
+ flagName: "agent-id",
8575
+ description: "Trigger agent ID.",
8576
+ required: true
8577
+ }),
8578
+ stringOption({
8579
+ inputKey: "idempotencyKey",
8580
+ flagName: "idempotency-key",
8581
+ description: "Idempotency key for the run request.",
8582
+ required: true
8583
+ }),
8584
+ jsonOption({
8585
+ inputKey: "input",
8586
+ flagName: "input-json",
8587
+ description: "Optional JSON input payload."
8588
+ }),
8589
+ stringOption({
8590
+ inputKey: "additionalPrompt",
8591
+ flagName: "additional-prompt",
8592
+ description: "Optional prompt appended to the run."
8593
+ })
8594
+ ]
8595
+ },
8596
+ mcp: { fileName: "runDraftAutomation.graphql" },
8597
+ document: `# Mutation to run a draft automation with an explicit agent.
8598
+ # \`draftAutomationId\` is the draft automation entity ID (\`Automation.id\`), not \`draftVersionId\`.
8599
+ mutation RunDraftAutomation(
8600
+ $draftAutomationId: ID!
8601
+ $agentId: ID!
8602
+ $idempotencyKey: String!
8603
+ $input: JSON
8604
+ $additionalPrompt: String
8605
+ ) {
8606
+ runDraftAutomation(
8607
+ draftAutomationId: $draftAutomationId
8608
+ agentId: $agentId
8609
+ idempotencyKey: $idempotencyKey
8610
+ input: $input
8611
+ additionalPrompt: $additionalPrompt
8612
+ ) {
8613
+ automationRunId
8614
+ workflowId
8615
+ workflowRunId
8733
8616
  }
8734
- static extractSuggestedActionFromCause(cause) {
8735
- return _AppError.getInheritedCauseField(cause, (causeRecord) => {
8736
- const { suggestedAction } = causeRecord;
8737
- if (typeof suggestedAction !== "string") {
8738
- return void 0;
8739
- }
8740
- const trimmedSuggestedAction = suggestedAction.trim();
8741
- return trimmedSuggestedAction.length > 0 ? trimmedSuggestedAction : void 0;
8742
- });
8617
+ }`
8618
+ }),
8619
+ createOperationSpec({
8620
+ operationName: "StopAutomationRun",
8621
+ kind: "mutation",
8622
+ inputSchema: z2.object({
8623
+ automationRunId: z2.string().min(1)
8624
+ }),
8625
+ cli: {
8626
+ name: "stop-automation-run",
8627
+ path: ["automation-runs", "stop"],
8628
+ description: "Stop an automation run.",
8629
+ resultKey: "stopAutomationRun",
8630
+ options: [
8631
+ stringOption({
8632
+ inputKey: "automationRunId",
8633
+ flagName: "automation-run-id",
8634
+ description: "Automation run ID.",
8635
+ required: true
8636
+ })
8637
+ ]
8638
+ },
8639
+ mcp: { fileName: "stopAutomationRun.graphql" },
8640
+ document: `# Mutation to stop an automation run
8641
+ mutation StopAutomationRun($automationRunId: ID!) {
8642
+ stopAutomationRun(automationRunId: $automationRunId)
8643
+ }`
8644
+ }),
8645
+ createOperationSpec({
8646
+ operationName: "UpdateAutomationById",
8647
+ kind: "mutation",
8648
+ inputSchema: z2.object({
8649
+ id: z2.string().min(1),
8650
+ input: jsonObjectSchema
8651
+ }),
8652
+ cli: {
8653
+ name: "update-automation-by-id",
8654
+ path: ["automations", "update"],
8655
+ description: "Update an automation.",
8656
+ resultKey: "updateAutomation",
8657
+ options: [
8658
+ stringOption({
8659
+ inputKey: "id",
8660
+ flagName: "id",
8661
+ description: "Automation ID.",
8662
+ required: true
8663
+ }),
8664
+ jsonOption({
8665
+ inputKey: "input",
8666
+ flagName: "input-json",
8667
+ description: "UpdateAutomationInput payload.",
8668
+ required: true
8669
+ })
8670
+ ]
8671
+ },
8672
+ mcp: { fileName: "updateAutomation.graphql" },
8673
+ document: `# Mutation to update an automation
8674
+ # Returns only id and lastSavedAt for MCP tool simplicity
8675
+ mutation UpdateAutomationById($id: ID!, $input: UpdateAutomationInput!) {
8676
+ updateAutomation(id: $id, input: $input) {
8677
+ id
8678
+ lastSavedAt
8743
8679
  }
8744
- static applyStack(error, stack, internalFrames) {
8745
- if (stack) {
8746
- error.stack = stack;
8747
- }
8748
- error.stack &&= stripInternalFrames(error.stack, [
8749
- ...INTERNAL_STACK_PATHS,
8750
- ...internalFrames ?? []
8751
- ]).join("\n");
8680
+ }`
8681
+ })
8682
+ ];
8683
+
8684
+ // src/program.ts
8685
+ import { Command as Command2, InvalidArgumentError as InvalidArgumentError2, Option as Option2 } from "commander";
8686
+
8687
+ // src/api.ts
8688
+ import { z as z3 } from "zod";
8689
+ var workosOrganizationsResponseSchema = z3.object({
8690
+ organizations: z3.array(
8691
+ z3.object({
8692
+ id: z3.string().min(1),
8693
+ name: z3.string().min(1),
8694
+ primaryDomain: z3.string().nullable().optional()
8695
+ })
8696
+ ),
8697
+ success: z3.boolean()
8698
+ });
8699
+ var workosUserSchema = z3.object({
8700
+ email: z3.string().nullable(),
8701
+ id: z3.string().min(1)
8702
+ });
8703
+ var nangoIntegrationWireSchema = z3.object({
8704
+ // eslint-disable-next-line @typescript-eslint/naming-convention -- mirrors Nango REST payload
8705
+ unique_key: z3.string().min(1)
8706
+ }).passthrough().transform((data) => ({
8707
+ ...data,
8708
+ uniqueKey: data.unique_key
8709
+ }));
8710
+ var nangoIntegrationsResponseSchema = z3.array(nangoIntegrationWireSchema);
8711
+ var organizationAuthenticationSchema = z3.object({
8712
+ id: z3.string().min(1),
8713
+ type: z3.string().min(1),
8714
+ connectionId: z3.string().nullable().optional(),
8715
+ providerConfigKey: z3.string().nullable().optional(),
8716
+ description: z3.string().nullable().optional(),
8717
+ hostname: z3.string().nullable().optional()
8718
+ }).passthrough();
8719
+ var organizationAuthenticationsResponseSchema = z3.object({
8720
+ authentications: z3.array(organizationAuthenticationSchema),
8721
+ success: z3.boolean()
8722
+ });
8723
+ var graphQlResponseSchema = z3.object({
8724
+ data: z3.record(z3.string(), z3.unknown()).optional(),
8725
+ errors: z3.array(
8726
+ z3.object({
8727
+ message: z3.string().min(1)
8728
+ })
8729
+ ).optional()
8730
+ });
8731
+ var apiErrorResponseSchema = z3.object({
8732
+ errors: z3.array(
8733
+ z3.object({
8734
+ message: z3.string().min(1)
8735
+ })
8736
+ ).optional(),
8737
+ message: z3.string().min(1).optional()
8738
+ });
8739
+ function getApiErrorDetail(responseBody) {
8740
+ const parsedResponse = apiErrorResponseSchema.safeParse(responseBody);
8741
+ if (!parsedResponse.success) {
8742
+ return null;
8752
8743
  }
8753
- toApiError({ correlationId }) {
8754
- return toUserFacingApiError({
8755
- error: this,
8756
- correlationId,
8757
- statusCode: getStatusCodeForAppError(this)
8758
- });
8744
+ if (parsedResponse.data.message) {
8745
+ return parsedResponse.data.message;
8759
8746
  }
8760
- toGqlError({ correlationId }) {
8761
- return toUserFacingGraphQLError({
8762
- error: this,
8763
- correlationId
8764
- });
8747
+ if (!parsedResponse.data.errors || parsedResponse.data.errors.length === 0) {
8748
+ return null;
8765
8749
  }
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
- });
8750
+ return parsedResponse.data.errors.map((error) => error.message).join("\n");
8781
8751
  }
8782
- function toUserFacingGraphQLError({ error, correlationId }) {
8783
- const appError = toAppError(error);
8784
- return toUserFacingGraphQLErrorFromAppError({
8785
- appError,
8786
- correlationId
8787
- });
8752
+ function trimTrailingSlash(value) {
8753
+ return value.replace(/\/+$/u, "");
8788
8754
  }
8789
-
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;
8755
+ function createMagicalApiClient({
8756
+ apiBaseUrl,
8757
+ fetchFn = fetch
8758
+ }) {
8759
+ const resolveApiBaseUrl = typeof apiBaseUrl === "string" ? () => apiBaseUrl : apiBaseUrl;
8760
+ async function fetchJson({
8761
+ accessToken,
8762
+ path: path7,
8763
+ init
8764
+ }) {
8765
+ const url = `${trimTrailingSlash(await resolveApiBaseUrl())}${path7}`;
8766
+ const headers = new Headers(init?.headers);
8767
+ headers.set("authorization", `Bearer ${accessToken}`);
8768
+ const response = await fetchFn(url, {
8769
+ ...init,
8770
+ headers
8771
+ }).catch((error) => {
8772
+ throw new CliError(
8773
+ `Failed to reach Magical API at ${url}. Check your configured base URL and make sure service-main is running.`,
8774
+ { cause: error }
8775
+ );
8776
+ });
8777
+ const responseBody = await response.json().catch((error) => {
8778
+ if (!response.ok) {
8779
+ throw new CliError(
8780
+ `Magical API request to ${url} failed with status ${response.status}.`,
8781
+ {
8782
+ cause: error
8783
+ }
8784
+ );
8785
+ }
8786
+ throw new CliError(
8787
+ `Magical API returned a non-JSON response for ${url}.`,
8788
+ {
8789
+ cause: error
8790
+ }
8791
+ );
8792
+ });
8793
+ if (!response.ok) {
8794
+ const errorDetail = getApiErrorDetail(responseBody);
8795
+ throw new CliError(
8796
+ `Magical API request to ${url} failed with status ${response.status}${errorDetail ? `: ${errorDetail}` : "."}`
8797
+ );
8807
8798
  }
8808
- return result.value;
8799
+ return responseBody;
8809
8800
  }
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;
8801
+ return {
8802
+ async executeGraphQl({
8803
+ accessToken,
8804
+ query,
8805
+ resultKey,
8806
+ variables
8807
+ }) {
8808
+ const headers = new Headers();
8809
+ headers.set("content-type", "application/json");
8810
+ const parsedResponse = graphQlResponseSchema.safeParse(
8811
+ await fetchJson({
8812
+ accessToken,
8813
+ path: "/graphql",
8814
+ init: {
8815
+ method: "POST",
8816
+ headers,
8817
+ body: JSON.stringify({
8818
+ query,
8819
+ variables
8820
+ })
8821
+ }
8822
+ })
8823
+ );
8824
+ if (!parsedResponse.success) {
8825
+ throw new CliError("GraphQL response payload was invalid.");
8826
+ }
8827
+ if (parsedResponse.data.errors && parsedResponse.data.errors.length > 0) {
8828
+ throw new CliError(
8829
+ parsedResponse.data.errors.map((error) => error.message).join("\n")
8830
+ );
8831
+ }
8832
+ return parsedResponse.data.data?.[resultKey] ?? null;
8833
+ },
8834
+ async fetchOrganizations({ accessToken }) {
8835
+ const parsedResponse = workosOrganizationsResponseSchema.safeParse(
8836
+ await fetchJson({
8837
+ accessToken,
8838
+ path: "/workos/organizations"
8839
+ })
8840
+ );
8841
+ if (!parsedResponse.success) {
8842
+ throw new CliError("Organization list payload was invalid.");
8816
8843
  }
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;
8844
+ return parsedResponse.data.organizations.map((organization) => ({
8845
+ id: organization.id,
8846
+ name: organization.name,
8847
+ primaryDomain: organization.primaryDomain ?? null
8848
+ }));
8849
+ },
8850
+ async fetchUser({
8851
+ accessToken,
8852
+ userId
8853
+ }) {
8854
+ const parsedResponse = workosUserSchema.safeParse(
8855
+ await fetchJson({
8856
+ accessToken,
8857
+ path: `/workos/user/${userId}`
8858
+ })
8859
+ );
8860
+ if (!parsedResponse.success) {
8861
+ throw new CliError("User payload was invalid.");
8831
8862
  }
8832
- values.unshift(result.value);
8833
- result = fn(...values);
8834
- }
8835
- return result;
8836
- }
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;
8863
+ return parsedResponse.data;
8864
+ },
8865
+ async listNangoIntegrations({
8866
+ accessToken
8867
+ }) {
8868
+ const parsedResponse = nangoIntegrationsResponseSchema.safeParse(
8869
+ await fetchJson({
8870
+ accessToken,
8871
+ path: "/nango/integrations"
8872
+ })
8873
+ );
8874
+ if (!parsedResponse.success) {
8875
+ throw new CliError("Nango integrations payload was invalid.");
8844
8876
  }
8845
- values.unshift(result.value);
8846
- result = await fn(...values);
8877
+ return parsedResponse.data;
8878
+ },
8879
+ async listNangoAuthentications({
8880
+ accessToken
8881
+ }) {
8882
+ const parsedResponse = organizationAuthenticationsResponseSchema.safeParse(
8883
+ await fetchJson({
8884
+ accessToken,
8885
+ path: "/authentications/organization?type=nangoConnection"
8886
+ })
8887
+ );
8888
+ if (!parsedResponse.success) {
8889
+ throw new CliError("Organization authentications payload was invalid.");
8890
+ }
8891
+ return parsedResponse.data.authentications;
8847
8892
  }
8848
- return result;
8893
+ };
8894
+ }
8895
+
8896
+ // src/config.ts
8897
+ import os from "os";
8898
+ import path from "path";
8899
+ var DEFAULT_MAGICAL_API_URL = "https://api-agt.getmagical.io";
8900
+ var DEFAULT_WORKOS_API_URL = "https://api.workos.com";
8901
+ var DEFAULT_WORKOS_CLIENT_ID = "client_01JJZ6XJ1RF248P20WF63M4VAM";
8902
+ var DEFAULT_STAGING_WORKOS_CLIENT_ID = "client_01JJZ6X26BGFBT8AC303XPQ9EQ";
8903
+ var DEFAULT_KEYCHAIN_SERVICE_NAME = "@getmagical/mcp-cli";
8904
+ var DEFAULT_CLI_DIST_TAG = "latest";
8905
+ var DEFAULT_CLI_NPM_REGISTRY_URL = "https://registry.npmjs.org/";
8906
+ var CLI_CONFIG_DIRECTORY_NAME = "magical-mcp-cli";
8907
+ var CLI_ACCESS_TOKEN_FILE_NAME = "access-token.txt";
8908
+ var CLI_STATE_FILE_NAME = "state.json";
8909
+ var CLI_SETTINGS_FILE_NAME = "settings.json";
8910
+ var CLI_REFRESH_TOKEN_FILE_NAME = "refresh-tokens.json";
8911
+ function resolvePlatformConfigDirectory() {
8912
+ const customConfigDirectory = process.env["MAGICAL_CLI_CONFIG_DIR"];
8913
+ if (customConfigDirectory) {
8914
+ return customConfigDirectory;
8849
8915
  }
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
- };
8916
+ if (process.platform === "darwin") {
8917
+ return path.join(os.homedir(), "Library", "Application Support");
8858
8918
  }
8859
- return {
8860
- _tag: "Ok",
8861
- value
8862
- };
8919
+ if (process.platform === "win32") {
8920
+ const appDataDirectory = process.env["APPDATA"];
8921
+ return appDataDirectory ?? path.join(os.homedir(), "AppData", "Roaming");
8922
+ }
8923
+ return process.env["XDG_CONFIG_HOME"] ?? path.join(os.homedir(), ".config");
8863
8924
  }
8864
- function Err(error) {
8865
- return {
8866
- _tag: "Err",
8867
- error: new AppError(error)
8868
- };
8925
+ function resolveRefreshTokenStoreKind() {
8926
+ return process.env["MAGICAL_CLI_REFRESH_TOKEN_STORE"] === "file" ? "file" : "keytar";
8869
8927
  }
8870
- function ErrFromThrowable(error) {
8928
+ function getRuntimeConfig() {
8929
+ const configDirectory = path.join(
8930
+ resolvePlatformConfigDirectory(),
8931
+ CLI_CONFIG_DIRECTORY_NAME
8932
+ );
8871
8933
  return {
8872
- _tag: "Err",
8873
- error
8934
+ accessTokenFilePath: path.join(configDirectory, CLI_ACCESS_TOKEN_FILE_NAME),
8935
+ cliDistTag: process.env["MAGICAL_CLI_DIST_TAG"] ?? DEFAULT_CLI_DIST_TAG,
8936
+ magicalApiUrl: DEFAULT_MAGICAL_API_URL,
8937
+ npmRegistryUrl: process.env["MAGICAL_CLI_NPM_REGISTRY_URL"] ?? DEFAULT_CLI_NPM_REGISTRY_URL,
8938
+ refreshTokenFilePath: path.join(
8939
+ configDirectory,
8940
+ CLI_REFRESH_TOKEN_FILE_NAME
8941
+ ),
8942
+ refreshTokenStoreKind: resolveRefreshTokenStoreKind(),
8943
+ stateFilePath: path.join(configDirectory, CLI_STATE_FILE_NAME),
8944
+ workosApiUrl: DEFAULT_WORKOS_API_URL,
8945
+ workosClientId: DEFAULT_WORKOS_CLIENT_ID,
8946
+ keychainServiceName: DEFAULT_KEYCHAIN_SERVICE_NAME
8874
8947
  };
8875
8948
  }
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
- }
8949
+ function requireWorkosClientId(config) {
8950
+ return config.workosClientId;
8907
8951
  }
8908
8952
 
8909
8953
  // src/settings.ts
8954
+ import { mkdir, readFile, rm, writeFile } from "fs/promises";
8955
+ import path2 from "path";
8910
8956
  import { z as z4 } from "zod";
8911
8957
  var cliSettingsSchema = z4.object({
8912
8958
  env: z4.object({
@@ -10034,13 +10080,13 @@ function parseCommandOptionValue(rawValue, optionSpec) {
10034
10080
  return rawValue.split(",").map((value) => value.trim()).filter((value) => value.length > 0);
10035
10081
  }
10036
10082
  case "json": {
10037
- try {
10038
- return JSON.parse(rawValue);
10039
- } catch {
10083
+ const parsedJson = safeJsonParse(rawValue);
10084
+ if (isErr(parsedJson)) {
10040
10085
  throw new InvalidArgumentError2(
10041
10086
  `Expected valid JSON for --${optionSpec.flagName}.`
10042
10087
  );
10043
10088
  }
10089
+ return parsedJson.value;
10044
10090
  }
10045
10091
  case "boolean": {
10046
10092
  return rawValue;
@@ -10110,6 +10156,13 @@ function requireLoggedInState(state) {
10110
10156
  function writeJsonOutput3(io, value) {
10111
10157
  io.info(JSON.stringify(value, null, 2));
10112
10158
  }
10159
+ function requireApiClientMethod(apiClient, key) {
10160
+ const method = apiClient[key];
10161
+ if (!method) {
10162
+ throw new CliError(`CLI API client method "${key}" is not wired.`);
10163
+ }
10164
+ return method;
10165
+ }
10113
10166
  function collectOperationVariables(operationSpec, options) {
10114
10167
  const variables = Object.fromEntries(
10115
10168
  operationSpec.cli.options.flatMap((optionSpec) => {
@@ -10245,6 +10298,100 @@ async function handleOperationCommand(dependencies, operationSpec, commandOption
10245
10298
  }
10246
10299
  dependencies.io.info(formatHumanReadableOutput(result));
10247
10300
  }
10301
+ async function withSelectedOrganizationAndAccessToken({
10302
+ dependencies,
10303
+ options
10304
+ }) {
10305
+ const state = requireLoggedInState(await dependencies.stateStore.load());
10306
+ const organization = resolveSelectedOrganization({
10307
+ state,
10308
+ ...options.org ? { organizationSelector: options.org } : {}
10309
+ });
10310
+ const { accessToken } = await withOrgScopedAccessToken({
10311
+ dependencies,
10312
+ organizationId: organization.id,
10313
+ state
10314
+ });
10315
+ return { accessToken, organization, state };
10316
+ }
10317
+ function writeCommandOutput({
10318
+ dependencies,
10319
+ json,
10320
+ result
10321
+ }) {
10322
+ if (json) {
10323
+ writeJsonOutput3(dependencies.io, result);
10324
+ return;
10325
+ }
10326
+ dependencies.io.info(formatHumanReadableOutput(result));
10327
+ }
10328
+ async function handleNangoIntegrationsListCommand(dependencies, options) {
10329
+ const { accessToken, organization, state } = await withSelectedOrganizationAndAccessToken({ dependencies, options });
10330
+ const listNangoIntegrations = requireApiClientMethod(
10331
+ dependencies.apiClient,
10332
+ "listNangoIntegrations"
10333
+ );
10334
+ const integrations = await listNangoIntegrations({ accessToken });
10335
+ await saveLastUsedOrganization({
10336
+ dependencies,
10337
+ organizationId: organization.id,
10338
+ state
10339
+ });
10340
+ writeCommandOutput({
10341
+ dependencies,
10342
+ json: options.json,
10343
+ result: integrations
10344
+ });
10345
+ }
10346
+ function normalizeListedNangoAuthentication(authentication) {
10347
+ return {
10348
+ id: authentication.id,
10349
+ type: authentication.type,
10350
+ ...authentication.connectionId === void 0 ? {} : { connectionId: authentication.connectionId },
10351
+ ...authentication.providerConfigKey === void 0 ? {} : { providerConfigKey: authentication.providerConfigKey },
10352
+ ...authentication.description === void 0 ? {} : { description: authentication.description },
10353
+ ...authentication.hostname === void 0 ? {} : { hostname: authentication.hostname }
10354
+ };
10355
+ }
10356
+ async function handleNangoAuthsListCommand(dependencies, options) {
10357
+ const { accessToken, organization, state } = await withSelectedOrganizationAndAccessToken({ dependencies, options });
10358
+ const listNangoAuthentications = requireApiClientMethod(
10359
+ dependencies.apiClient,
10360
+ "listNangoAuthentications"
10361
+ );
10362
+ const organizationAuthentications = await listNangoAuthentications({
10363
+ accessToken
10364
+ });
10365
+ const authentications = organizationAuthentications.filter((authentication) => {
10366
+ if (options.integration && authentication.providerConfigKey !== options.integration) {
10367
+ return false;
10368
+ }
10369
+ if (options.connectionId && authentication.connectionId !== options.connectionId) {
10370
+ return false;
10371
+ }
10372
+ return true;
10373
+ }).map(normalizeListedNangoAuthentication);
10374
+ await saveLastUsedOrganization({
10375
+ dependencies,
10376
+ organizationId: organization.id,
10377
+ state
10378
+ });
10379
+ writeCommandOutput({
10380
+ dependencies,
10381
+ json: options.json,
10382
+ result: authentications
10383
+ });
10384
+ }
10385
+ async function saveLastUsedOrganization({
10386
+ dependencies,
10387
+ organizationId,
10388
+ state
10389
+ }) {
10390
+ await dependencies.stateStore.save({
10391
+ ...state,
10392
+ lastUsedOrgId: organizationId
10393
+ });
10394
+ }
10248
10395
  function addRegistryOperationCommand({
10249
10396
  program: program2,
10250
10397
  commandGroups,
@@ -10438,6 +10585,66 @@ ${formatExamples("Examples", [
10438
10585
  );
10439
10586
  });
10440
10587
  program2.addCommand(orgCommand);
10588
+ const nangoCommand = configureCommandPresentation(
10589
+ new Command2("nango").description(
10590
+ "Inspect Nango integrations and org-scoped authentications."
10591
+ )
10592
+ ).helpGroup("Workspace:").addHelpText(
10593
+ "after",
10594
+ `
10595
+ ${formatExamples("Examples", [
10596
+ "mgcl nango integrations list --json",
10597
+ "mgcl nango auths list --integration github --json"
10598
+ ])}`
10599
+ );
10600
+ const nangoIntegrationsCommand = configureCommandPresentation(
10601
+ new Command2("integrations").description("Work with Nango integrations.")
10602
+ );
10603
+ nangoIntegrationsCommand.command("list").description("List Nango integrations available in the current workspace.").addOption(
10604
+ new Option2(
10605
+ "--org <org>",
10606
+ "Organization ID or exact organization name to use."
10607
+ ).helpGroup("Shared options:")
10608
+ ).action(async function() {
10609
+ await handleNangoIntegrationsListCommand(
10610
+ dependencies,
10611
+ this.optsWithGlobals()
10612
+ );
10613
+ });
10614
+ nangoCommand.addCommand(nangoIntegrationsCommand);
10615
+ const nangoAuthsCommand = configureCommandPresentation(
10616
+ new Command2("auths").alias("authentications").description("Work with org-scoped Nango authentications.")
10617
+ );
10618
+ nangoAuthsCommand.command("list").description(
10619
+ "List org-scoped Nango authentications and their connection IDs."
10620
+ ).addOption(
10621
+ new Option2(
10622
+ "--org <org>",
10623
+ "Organization ID or exact organization name to use."
10624
+ ).helpGroup("Shared options:")
10625
+ ).addOption(
10626
+ new Option2(
10627
+ "--integration <integration>",
10628
+ "Optional integration key to filter Nango authentications."
10629
+ )
10630
+ ).addOption(
10631
+ new Option2(
10632
+ "--connection-id <connectionId>",
10633
+ "Optional connection ID to filter Nango authentications."
10634
+ )
10635
+ ).addHelpText(
10636
+ "after",
10637
+ `
10638
+ ${formatExamples("Examples", [
10639
+ "mgcl nango auths list --json",
10640
+ "mgcl nango auths list --integration github --json",
10641
+ "mgcl nango auths list --integration github --connection-id <id> --json"
10642
+ ])}`
10643
+ ).action(async function() {
10644
+ await handleNangoAuthsListCommand(dependencies, this.optsWithGlobals());
10645
+ });
10646
+ nangoCommand.addCommand(nangoAuthsCommand);
10647
+ program2.addCommand(nangoCommand);
10441
10648
  const updateCommand = configureCommandPresentation(
10442
10649
  new Command2("update").description(
10443
10650
  "Update mgcl to the latest published npm release."