@getmagical/cli 0.3.2 → 0.6.0

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
@@ -6954,6 +6954,130 @@ function renderKeyValueBlock(entries) {
6954
6954
  function renderSection(title, bodyLines) {
6955
6955
  return [formatHeading(title), "", ...bodyLines].join("\n");
6956
6956
  }
6957
+ function getRecordArray(value) {
6958
+ return Array.isArray(value) && value.every(isRecord) ? value : null;
6959
+ }
6960
+ function getRecordScalar(record, key) {
6961
+ const value = record[key];
6962
+ return isPrimitiveLike(value) ? formatScalar(value) : EMPTY_VALUE;
6963
+ }
6964
+ function getMergeChangeExplanation(change) {
6965
+ const explanation = change["statusDescription"] ?? change["conflictDescription"];
6966
+ return typeof explanation === "string" ? formatScalar(explanation) : EMPTY_VALUE;
6967
+ }
6968
+ function formatMergeChanges(changes, includeStatus) {
6969
+ return formatTable({
6970
+ columns: includeStatus ? ["Change", "Status", "Discardable", "Explanation", "Change ID"] : ["Change", "Explanation", "Change ID"],
6971
+ rows: changes.map((change) => {
6972
+ const cells = [getRecordScalar(change, "label")];
6973
+ if (includeStatus) {
6974
+ cells.push(
6975
+ getRecordScalar(change, "status"),
6976
+ change["discardable"] === true ? "yes" : "no"
6977
+ );
6978
+ }
6979
+ cells.push(
6980
+ getMergeChangeExplanation(change),
6981
+ getRecordScalar(change, "id")
6982
+ );
6983
+ return cells;
6984
+ })
6985
+ });
6986
+ }
6987
+ function renderMergePreviewSection(title, preview, changes) {
6988
+ return renderSection(title, [
6989
+ renderKeyValueBlock([
6990
+ ["Base version", getRecordScalar(preview, "baseVersionId")],
6991
+ ["Source version", getRecordScalar(preview, "sourceVersionId")],
6992
+ ["Target version", getRecordScalar(preview, "targetVersionId")]
6993
+ ]),
6994
+ "",
6995
+ changes.length > 0 ? formatMergeChanges(changes, true) : "No changes to merge."
6996
+ ]);
6997
+ }
6998
+ function renderDiscardHint(preview, changes) {
6999
+ const hasDiscardable = changes.some(
7000
+ (change) => change["discardable"] === true
7001
+ );
7002
+ if (!hasDiscardable) {
7003
+ return null;
7004
+ }
7005
+ return renderSection("Resolve conflicts", [
7006
+ "Discards revert a change on the branch so main keeps its value; conflicts must be discarded or edited to match main before merging.",
7007
+ formatCommandSnippet(
7008
+ `mgcl --branch-id <branch-id> automations branches discard-changes --automation-id <automation-id> --change-ids <change-id,...> --source-version-id ${getRecordScalar(preview, "sourceVersionId")} --target-version-id ${getRecordScalar(preview, "targetVersionId")}`
7009
+ )
7010
+ ]);
7011
+ }
7012
+ function formatAutomationBranchMergePreviewOutput(value) {
7013
+ const changes = isRecord(value) ? getRecordArray(value["changes"]) : null;
7014
+ if (!isRecord(value) || !changes) {
7015
+ return formatHumanReadableOutput(value);
7016
+ }
7017
+ const hint = renderDiscardHint(value, changes);
7018
+ return [
7019
+ renderMergePreviewSection("Merge Preview", value, changes),
7020
+ ...hint ? [hint] : []
7021
+ ].join("\n\n");
7022
+ }
7023
+ function formatAutomationBranchDiscardOutput(value) {
7024
+ const preview = isRecord(value) ? value["preview"] : null;
7025
+ const changes = isRecord(preview) ? getRecordArray(preview["changes"]) : null;
7026
+ if (!isRecord(value) || !isRecord(preview) || !changes) {
7027
+ return formatHumanReadableOutput(value);
7028
+ }
7029
+ const discardedChangeIds = Array.isArray(value["discardedChangeIds"]) ? value["discardedChangeIds"].map(formatScalar).join(", ") : EMPTY_VALUE;
7030
+ return [
7031
+ renderSection("Branch Discard", [
7032
+ renderKeyValueBlock([
7033
+ ["Branch ID", getRecordScalar(value, "branchId")],
7034
+ ["Previous head", getRecordScalar(value, "previousHeadVersionId")],
7035
+ ["New head", getRecordScalar(value, "headVersionId")],
7036
+ ["Discarded changes", discardedChangeIds]
7037
+ ])
7038
+ ]),
7039
+ renderMergePreviewSection("Refreshed Merge Preview", preview, changes)
7040
+ ].join("\n\n");
7041
+ }
7042
+ function formatAutomationBranchMergeOutput(value) {
7043
+ if (!isRecord(value) || value["status"] !== "conflict") {
7044
+ return formatHumanReadableOutput(value);
7045
+ }
7046
+ const { preview } = value;
7047
+ const conflicts = getRecordArray(value["conflicts"]);
7048
+ if (!isRecord(preview) || !conflicts || conflicts.length === 0) {
7049
+ return formatHumanReadableOutput(value);
7050
+ }
7051
+ const changes = getRecordArray(preview["changes"]);
7052
+ if (!changes) {
7053
+ return formatHumanReadableOutput(value);
7054
+ }
7055
+ const hint = renderDiscardHint(preview, changes);
7056
+ return [
7057
+ renderSection("Branch Merge", [
7058
+ renderKeyValueBlock([
7059
+ ["Status", getRecordScalar(value, "status")],
7060
+ ["Automation ID", getRecordScalar(value, "automationId")],
7061
+ ["Branch ID", getRecordScalar(value, "branchId")],
7062
+ [
7063
+ "Source branch deleted",
7064
+ getRecordScalar(value, "sourceBranchDeleted")
7065
+ ]
7066
+ ])
7067
+ ]),
7068
+ renderSection("Merge Conflicts", [formatMergeChanges(conflicts, false)]),
7069
+ renderMergePreviewSection("Merge Preview", preview, changes),
7070
+ ...hint ? [hint] : []
7071
+ ].join("\n\n");
7072
+ }
7073
+ var BRANCH_MERGE_FORMATTERS = /* @__PURE__ */ new Map([
7074
+ ["DiscardAutomationBranchChanges", formatAutomationBranchDiscardOutput],
7075
+ ["MergeAutomationBranch", formatAutomationBranchMergeOutput],
7076
+ ["PreviewAutomationBranchMerge", formatAutomationBranchMergePreviewOutput]
7077
+ ]);
7078
+ function getBranchMergeFormatter(operationName) {
7079
+ return BRANCH_MERGE_FORMATTERS.get(operationName);
7080
+ }
6957
7081
  var MagicalHelp = class extends Help {
6958
7082
  outputHasColors = process.stdout.isTTY;
6959
7083
  constructor() {
@@ -7073,12 +7197,14 @@ function formatOutputModesNote() {
7073
7197
 
7074
7198
  // src/errors.ts
7075
7199
  var CliError = class extends Error {
7200
+ apiErrorCode;
7076
7201
  retryAfterMs;
7077
7202
  retryable;
7078
7203
  statusCode;
7079
7204
  constructor(message, options) {
7080
7205
  super(message, options);
7081
7206
  this.name = "CliError";
7207
+ this.apiErrorCode = options?.apiErrorCode;
7082
7208
  this.retryAfterMs = options?.retryAfterMs;
7083
7209
  this.retryable = options?.retryable;
7084
7210
  this.statusCode = options?.statusCode;
@@ -7095,7 +7221,7 @@ function getErrorMessage(error) {
7095
7221
  import { randomUUID as randomUUID4 } from "node:crypto";
7096
7222
  import { readFile as readFile6 } from "node:fs/promises";
7097
7223
  import path8 from "node:path";
7098
- import { setTimeout as sleep } from "node:timers/promises";
7224
+ import { setTimeout as sleep2 } from "node:timers/promises";
7099
7225
 
7100
7226
  // ../common/dist/src/stdlib/json.util.js
7101
7227
  var import_ts_essentials = __toESM(require_dist(), 1);
@@ -7767,6 +7893,8 @@ function safeJsonParseWithoutLogging(json) {
7767
7893
  // ../common/dist/src/constants/automation.js
7768
7894
  var AUTOMATION_BRANCH_NAME_MAX_LENGTH = 100;
7769
7895
  var AUTOMATION_BRANCH_NAME_MAX_LENGTH_MESSAGE = `Branch name must be ${AUTOMATION_BRANCH_NAME_MAX_LENGTH} characters or fewer.`;
7896
+ var AUTOMATION_BRANCH_DISCARD_MAX_CHANGE_IDS = 50;
7897
+ var AUTOMATION_BRANCH_CHANGE_ID_MAX_LENGTH = 256;
7770
7898
 
7771
7899
  // ../common/dist/src/constants/tool-declarations.js
7772
7900
  import { z as z15 } from "zod";
@@ -12365,6 +12493,27 @@ var clickComparisonSchema = z9.union([
12365
12493
  [COMMON_PARAMETERS_KEY]: DEFAULT_COMMON_PARAMETERS
12366
12494
  })
12367
12495
  ]);
12496
+ var holdClickMarkerInputSchema = z9.object({
12497
+ marker: markerSchema("The marker of the element to press and hold.")
12498
+ });
12499
+ var holdClickCoordinateInputSchema = z9.object({
12500
+ coordinates: coordinateSchema({
12501
+ xDescription: "The x coordinate of the element to press and hold.",
12502
+ yDescription: "The y coordinate of the element to press and hold."
12503
+ })
12504
+ });
12505
+ var holdClickComparisonSchema = z9.union([
12506
+ holdClickMarkerInputSchema.extend({
12507
+ [COMMON_PARAMETERS_KEY]: DEFAULT_COMMON_PARAMETERS
12508
+ }),
12509
+ holdClickCoordinateInputSchema.extend({
12510
+ [COMMON_PARAMETERS_KEY]: DEFAULT_COMMON_PARAMETERS
12511
+ })
12512
+ ]);
12513
+ var releaseClickInputSchema = z9.object({});
12514
+ var releaseClickComparisonSchema = releaseClickInputSchema.extend({
12515
+ [COMMON_PARAMETERS_KEY]: DEFAULT_COMMON_PARAMETERS
12516
+ });
12368
12517
  var moveMarkerInputSchema = z9.object({
12369
12518
  marker: markerSchema("The marker to move the mouse to")
12370
12519
  });
@@ -12735,7 +12884,8 @@ var PressEvent;
12735
12884
  Response2.create = create;
12736
12885
  })(Response = PressEvent2.Response || (PressEvent2.Response = {}));
12737
12886
  })(PressEvent || (PressEvent = {}));
12738
- var Keys = [
12887
+ var ModifierKeys = ["Alt", "Control", "Meta", "Shift"];
12888
+ var PhysicalKeys = [
12739
12889
  // Modifiers
12740
12890
  "Alt",
12741
12891
  "CapsLock",
@@ -12837,16 +12987,16 @@ var Keys = [
12837
12987
  "y",
12838
12988
  "Z",
12839
12989
  "z",
12840
- "0",
12841
- "1",
12842
- "2",
12843
- "3",
12844
- "4",
12845
- "5",
12846
- "6",
12847
- "7",
12848
- "8",
12849
- "9",
12990
+ "Digit0",
12991
+ "Digit1",
12992
+ "Digit2",
12993
+ "Digit3",
12994
+ "Digit4",
12995
+ "Digit5",
12996
+ "Digit6",
12997
+ "Digit7",
12998
+ "Digit8",
12999
+ "Digit9",
12850
13000
  // Punctuation
12851
13001
  "Minus",
12852
13002
  "Equal",
@@ -12863,8 +13013,106 @@ var Keys = [
12863
13013
  "Insert",
12864
13014
  "PrintScreen"
12865
13015
  ];
13016
+ var KeyAliases = [
13017
+ "0",
13018
+ "1",
13019
+ "2",
13020
+ "3",
13021
+ "4",
13022
+ "5",
13023
+ "6",
13024
+ "7",
13025
+ "8",
13026
+ "9",
13027
+ "`",
13028
+ "~",
13029
+ "-",
13030
+ "_",
13031
+ "=",
13032
+ "+",
13033
+ "[",
13034
+ "{",
13035
+ "]",
13036
+ "}",
13037
+ "\\",
13038
+ "|",
13039
+ ";",
13040
+ ":",
13041
+ "'",
13042
+ '"',
13043
+ ",",
13044
+ "<",
13045
+ ".",
13046
+ ">",
13047
+ "/",
13048
+ "?",
13049
+ "!",
13050
+ "@",
13051
+ "#",
13052
+ "$",
13053
+ "%",
13054
+ "^",
13055
+ "&",
13056
+ "*",
13057
+ "(",
13058
+ ")"
13059
+ ];
13060
+ var Keys = [...PhysicalKeys, ...KeyAliases];
13061
+ var KeyAliasMappings = [
13062
+ ["0", ["Digit0"]],
13063
+ ["1", ["Digit1"]],
13064
+ ["2", ["Digit2"]],
13065
+ ["3", ["Digit3"]],
13066
+ ["4", ["Digit4"]],
13067
+ ["5", ["Digit5"]],
13068
+ ["6", ["Digit6"]],
13069
+ ["7", ["Digit7"]],
13070
+ ["8", ["Digit8"]],
13071
+ ["9", ["Digit9"]],
13072
+ ["`", ["Backquote"]],
13073
+ ["~", ["Shift", "Backquote"]],
13074
+ ["-", ["Minus"]],
13075
+ ["_", ["Shift", "Minus"]],
13076
+ ["=", ["Equal"]],
13077
+ ["+", ["Shift", "Equal"]],
13078
+ ["[", ["BracketLeft"]],
13079
+ ["{", ["Shift", "BracketLeft"]],
13080
+ ["]", ["BracketRight"]],
13081
+ ["}", ["Shift", "BracketRight"]],
13082
+ ["\\", ["Backslash"]],
13083
+ ["|", ["Shift", "Backslash"]],
13084
+ [";", ["Semicolon"]],
13085
+ [":", ["Shift", "Semicolon"]],
13086
+ ["'", ["Quote"]],
13087
+ ['"', ["Shift", "Quote"]],
13088
+ [",", ["Comma"]],
13089
+ ["<", ["Shift", "Comma"]],
13090
+ [".", ["Period"]],
13091
+ [">", ["Shift", "Period"]],
13092
+ ["/", ["Slash"]],
13093
+ ["?", ["Shift", "Slash"]],
13094
+ ["!", ["Shift", "Digit1"]],
13095
+ ["@", ["Shift", "Digit2"]],
13096
+ ["#", ["Shift", "Digit3"]],
13097
+ ["$", ["Shift", "Digit4"]],
13098
+ ["%", ["Shift", "Digit5"]],
13099
+ ["^", ["Shift", "Digit6"]],
13100
+ ["&", ["Shift", "Digit7"]],
13101
+ ["*", ["Shift", "Digit8"]],
13102
+ ["(", ["Shift", "Digit9"]],
13103
+ [")", ["Shift", "Digit0"]]
13104
+ ];
13105
+ var KeyMappings = [
13106
+ ...PhysicalKeys.map((key) => [
13107
+ key,
13108
+ [key]
13109
+ ]),
13110
+ ...KeyAliasMappings
13111
+ ];
13112
+ var KeyMapping = new Map(KeyMappings);
13113
+ var ModifierKeySet = new Set(ModifierKeys);
12866
13114
  var pressDataSchema = z12.object({
12867
- keys: z12.array(z12.enum(Keys))
13115
+ keys: z12.array(z12.enum(Keys)).describe("Keys in one simultaneous keyboard chord. Use type for a sequence of characters. US keyboard characters and physical key codes such as Digit4 are supported.")
12868
13116
  });
12869
13117
 
12870
13118
  // ../common/dist/src/models/websocket/actions/report-stop.js
@@ -13190,6 +13438,16 @@ var baseToolDeclarations = {
13190
13438
  description: 'ONLY USE FOR CLICKING WITHOUT ENTERING TEXT. This tool clicks on an element but DOES NOT allow entering text. Use for buttons, links, checkboxes, dropdown toggles, tabs, and other clickable elements. NEVER use this when you need to enter text into a field - for text entry, use "clickFill" instead, this tool automatically moves the cursor to the element, no need to use the move tool first.',
13191
13439
  parameters: clickComparisonSchema
13192
13440
  },
13441
+ holdClick: {
13442
+ id: "holdClick",
13443
+ description: "Press and hold the left mouse button on an element that reveals content only while pressed. The hold remains active during non-browser work and is released automatically before the next browser interaction.",
13444
+ parameters: holdClickComparisonSchema
13445
+ },
13446
+ releaseClick: {
13447
+ id: "releaseClick",
13448
+ description: "Release the left mouse button after holdClick. This is safe to call again when the mouse is already released.",
13449
+ parameters: releaseClickComparisonSchema
13450
+ },
13193
13451
  multiClick: {
13194
13452
  id: "multiClick",
13195
13453
  description: "This object is deprecated, only adding here to satisfy the DB type check",
@@ -13798,12 +14056,109 @@ var apiAgentEmbeddedFilesSchema = z16.array(apiAgentEmbeddedFileSchema).superRef
13798
14056
  // ../common/dist/src/zod-schemas/api-agent-request-file-encoding.schema.js
13799
14057
  import { z as z17 } from "zod";
13800
14058
  var API_REQUEST_FILE_PATH_PATTERN = /^[A-Za-z_$][\w$-]*(?:\.[A-Za-z_$][\w$-]*)*$/u;
14059
+ var API_REQUEST_BASE64_FILE_HELPER_PATTERN = /^\s*\{\{\s*base64File\s+(?<sourceInput>[^{}\s]+)\s*\}\}\s*$/u;
14060
+ var API_REQUEST_BASE64_FILE_HELPER_USAGE_PATTERN = /\{\{\s*base64File\b/u;
14061
+ var API_REQUEST_BASE64_FILE_HELPER_EXAMPLE = "{{base64File fileInput}}";
13801
14062
  function parseApiRequestFilePath(path9) {
13802
14063
  if (!API_REQUEST_FILE_PATH_PATTERN.test(path9)) {
13803
14064
  return void 0;
13804
14065
  }
13805
14066
  return path9.split(".");
13806
14067
  }
14068
+ function inspectApiRequestBase64FileHelperValue({ path: path9, value }) {
14069
+ const match = API_REQUEST_BASE64_FILE_HELPER_PATTERN.exec(value);
14070
+ if (match === null) {
14071
+ return API_REQUEST_BASE64_FILE_HELPER_USAGE_PATTERN.test(value) ? {
14072
+ helpers: [],
14073
+ issues: [
14074
+ {
14075
+ message: `Use ${API_REQUEST_BASE64_FILE_HELPER_EXAMPLE} as the entire JSON field value.`,
14076
+ path: path9
14077
+ }
14078
+ ]
14079
+ } : { helpers: [], issues: [] };
14080
+ }
14081
+ const { sourceInput } = match.groups ?? {};
14082
+ if (sourceInput === void 0 || parseApiRequestFilePath(sourceInput) === void 0) {
14083
+ return {
14084
+ helpers: [],
14085
+ issues: [
14086
+ {
14087
+ message: "Base64 file helper input must use an object property path.",
14088
+ path: path9
14089
+ }
14090
+ ]
14091
+ };
14092
+ }
14093
+ return {
14094
+ helpers: [{ destinationPath: path9, sourceInput }],
14095
+ issues: []
14096
+ };
14097
+ }
14098
+ function inspectApiRequestBase64FileHelpers(body, path9 = []) {
14099
+ if (typeof body === "string") {
14100
+ return inspectApiRequestBase64FileHelperValue({ path: path9, value: body });
14101
+ }
14102
+ if (Array.isArray(body)) {
14103
+ return body.reduce((inspection, value, index) => {
14104
+ const nestedInspection = inspectApiRequestBase64FileHelpers(value, [
14105
+ ...path9,
14106
+ index
14107
+ ]);
14108
+ return {
14109
+ helpers: [...inspection.helpers, ...nestedInspection.helpers],
14110
+ issues: [...inspection.issues, ...nestedInspection.issues]
14111
+ };
14112
+ }, { helpers: [], issues: [] });
14113
+ }
14114
+ if (body === null || typeof body !== "object") {
14115
+ return { helpers: [], issues: [] };
14116
+ }
14117
+ return Object.entries(body).reduce((inspection, [key, value]) => {
14118
+ const nestedInspection = inspectApiRequestBase64FileHelpers(value, [
14119
+ ...path9,
14120
+ key
14121
+ ]);
14122
+ return {
14123
+ helpers: [...inspection.helpers, ...nestedInspection.helpers],
14124
+ issues: [...inspection.issues, ...nestedInspection.issues]
14125
+ };
14126
+ }, { helpers: [], issues: [] });
14127
+ }
14128
+ function validateApiRequestBase64FileHelpers({ body, bodyType, context, supportsRequestBody }) {
14129
+ const inspection = inspectApiRequestBase64FileHelpers(body);
14130
+ for (const issue of inspection.issues) {
14131
+ context.addIssue({
14132
+ code: z17.ZodIssueCode.custom,
14133
+ message: issue.message,
14134
+ path: ["body", ...issue.path]
14135
+ });
14136
+ }
14137
+ if (inspection.helpers.length === 0) {
14138
+ return;
14139
+ }
14140
+ if (!supportsRequestBody) {
14141
+ context.addIssue({
14142
+ code: z17.ZodIssueCode.custom,
14143
+ message: "Base64 file helpers are not supported for this method",
14144
+ path: ["body"]
14145
+ });
14146
+ }
14147
+ if ((bodyType ?? "json") !== "json") {
14148
+ context.addIssue({
14149
+ code: z17.ZodIssueCode.custom,
14150
+ message: "Base64 file helpers are only supported for JSON bodies",
14151
+ path: ["body"]
14152
+ });
14153
+ }
14154
+ if (body === null || typeof body !== "object" || Array.isArray(body)) {
14155
+ context.addIssue({
14156
+ code: z17.ZodIssueCode.custom,
14157
+ message: "Base64 file helpers require a JSON object body",
14158
+ path: ["body"]
14159
+ });
14160
+ }
14161
+ }
13807
14162
  var apiAgentRequestFileEncodingSchema = z17.object({
13808
14163
  sourceInput: z17.string().trim().min(1, "File input is required.").refine((path9) => parseApiRequestFilePath(path9) !== void 0, {
13809
14164
  message: "File input must use an object property path."
@@ -13978,6 +14333,13 @@ var apiToolSchema = z20.object({
13978
14333
  }).refine((data) => !data.requestFileEncodings?.length || data.body !== null && typeof data.body === "object" && !Array.isArray(data.body), {
13979
14334
  message: "Request file encoding requires a JSON object body",
13980
14335
  path: ["body"]
14336
+ }).superRefine((data, context) => {
14337
+ validateApiRequestBase64FileHelpers({
14338
+ body: data.body,
14339
+ bodyType: data.bodyType,
14340
+ context,
14341
+ supportsRequestBody: methodsWithBody.has(data.type)
14342
+ });
13981
14343
  }).refine((data) => isValidApiMultipartFormDataBody({
13982
14344
  bodyType: data.bodyType,
13983
14345
  body: data.body
@@ -14385,6 +14747,13 @@ var apiAgentConfigSchema = baseAgentConfigFieldsSchema.safeExtend({
14385
14747
  }).refine((data) => !data.requestFileEncodings?.length || data.body !== null && typeof data.body === "object" && !Array.isArray(data.body), {
14386
14748
  message: "Request file encoding requires a JSON object body",
14387
14749
  path: ["body"]
14750
+ }).superRefine((data, context) => {
14751
+ validateApiRequestBase64FileHelpers({
14752
+ body: data.body,
14753
+ bodyType: data.bodyType,
14754
+ context,
14755
+ supportsRequestBody: METHODS_WITH_BODY.has(data.method)
14756
+ });
14388
14757
  }).refine((data) => isValidApiMultipartFormDataBody({
14389
14758
  bodyType: data.bodyType,
14390
14759
  body: data.body
@@ -15161,6 +15530,7 @@ ${agentLimitationsSelection}
15161
15530
  operationName: "GetAgentVersion",
15162
15531
  kind: "query",
15163
15532
  inputSchema: z27.object({
15533
+ draftAutomationId: z27.string().min(1),
15164
15534
  agentId: z27.string().min(1),
15165
15535
  versionId: z27.string().min(1)
15166
15536
  }),
@@ -15170,6 +15540,12 @@ ${agentLimitationsSelection}
15170
15540
  description: "Fetch one saved version for an agent.",
15171
15541
  resultKey: "agentVersion",
15172
15542
  options: [
15543
+ stringOption({
15544
+ inputKey: "draftAutomationId",
15545
+ flagName: "automation-id",
15546
+ description: "Automation ID whose main draft lineage scopes the agent's history.",
15547
+ required: true
15548
+ }),
15173
15549
  stringOption({
15174
15550
  inputKey: "agentId",
15175
15551
  flagName: "agent-id",
@@ -15186,8 +15562,12 @@ ${agentLimitationsSelection}
15186
15562
  },
15187
15563
  mcp: { fileName: "agentVersion.graphql" },
15188
15564
  document: `# Query to fetch a specific saved version for an agent
15189
- query GetAgentVersion($agentId: ID!, $versionId: ID!) {
15190
- agentVersion(agentId: $agentId, versionId: $versionId) {
15565
+ query GetAgentVersion($draftAutomationId: ID!, $agentId: ID!, $versionId: ID!) {
15566
+ agentVersion(
15567
+ draftAutomationId: $draftAutomationId
15568
+ agentId: $agentId
15569
+ versionId: $versionId
15570
+ ) {
15191
15571
  id
15192
15572
  agentId
15193
15573
  sequence
@@ -15227,6 +15607,7 @@ ${agentLimitationsSelection}
15227
15607
  operationName: "GetAgentVersions",
15228
15608
  kind: "query",
15229
15609
  inputSchema: z27.object({
15610
+ draftAutomationId: z27.string().min(1),
15230
15611
  agentId: z27.string().min(1)
15231
15612
  }),
15232
15613
  cli: {
@@ -15235,6 +15616,12 @@ ${agentLimitationsSelection}
15235
15616
  description: "Fetch version history for an agent.",
15236
15617
  resultKey: "agentVersions",
15237
15618
  options: [
15619
+ stringOption({
15620
+ inputKey: "draftAutomationId",
15621
+ flagName: "automation-id",
15622
+ description: "Automation ID whose main draft lineage scopes the agent's history.",
15623
+ required: true
15624
+ }),
15238
15625
  stringOption({
15239
15626
  inputKey: "agentId",
15240
15627
  flagName: "agent-id",
@@ -15245,8 +15632,8 @@ ${agentLimitationsSelection}
15245
15632
  },
15246
15633
  mcp: { fileName: "agentVersions.graphql" },
15247
15634
  document: `# Query to fetch version history metadata for an agent
15248
- query GetAgentVersions($agentId: ID!) {
15249
- agentVersions(agentId: $agentId) {
15635
+ query GetAgentVersions($draftAutomationId: ID!, $agentId: ID!) {
15636
+ agentVersions(draftAutomationId: $draftAutomationId, agentId: $agentId) {
15250
15637
  id
15251
15638
  sequence
15252
15639
  name
@@ -15262,6 +15649,7 @@ query GetAgentVersions($agentId: ID!) {
15262
15649
  operationName: "DiffAgentVersion",
15263
15650
  kind: "query",
15264
15651
  inputSchema: z27.object({
15652
+ draftAutomationId: z27.string().min(1),
15265
15653
  agentId: z27.string().min(1),
15266
15654
  versionId: z27.string().min(1),
15267
15655
  compareVersionId: z27.string().min(1).optional()
@@ -15269,9 +15657,15 @@ query GetAgentVersions($agentId: ID!) {
15269
15657
  cli: {
15270
15658
  name: "diff-agent-version",
15271
15659
  path: ["agents", "versions", "diff"],
15272
- description: "Diff one agent version against another version or the current latest version.",
15660
+ description: "Diff one agent version against another version or the automation's current draft version.",
15273
15661
  resultKey: "agentVersionDiff",
15274
15662
  options: [
15663
+ stringOption({
15664
+ inputKey: "draftAutomationId",
15665
+ flagName: "automation-id",
15666
+ description: "Automation ID whose main draft lineage scopes the agent's history.",
15667
+ required: true
15668
+ }),
15275
15669
  stringOption({
15276
15670
  inputKey: "agentId",
15277
15671
  flagName: "agent-id",
@@ -15287,18 +15681,20 @@ query GetAgentVersions($agentId: ID!) {
15287
15681
  stringOption({
15288
15682
  inputKey: "compareVersionId",
15289
15683
  flagName: "compare-version-id",
15290
- description: "Optional target version ID. Defaults to the current latest version."
15684
+ description: "Optional target version ID. Defaults to the automation's current draft version."
15291
15685
  })
15292
15686
  ]
15293
15687
  },
15294
15688
  mcp: { fileName: "agentVersionDiff.graphql" },
15295
- document: `# Query to diff one agent version against another or the current latest version
15689
+ document: `# Query to diff one agent version against another or the automation's current draft version
15296
15690
  query DiffAgentVersion(
15691
+ $draftAutomationId: ID!
15297
15692
  $agentId: ID!
15298
15693
  $versionId: ID!
15299
15694
  $compareVersionId: ID
15300
15695
  ) {
15301
15696
  agentVersionDiff(
15697
+ draftAutomationId: $draftAutomationId
15302
15698
  agentId: $agentId
15303
15699
  versionId: $versionId
15304
15700
  compareVersionId: $compareVersionId
@@ -15340,6 +15736,7 @@ query DiffAgentVersion(
15340
15736
  query GetAgentRun($id: ID!) {
15341
15737
  agentRun(id: $id) {
15342
15738
  id
15739
+ agentId
15343
15740
  agentVersionId
15344
15741
  agentName
15345
15742
  status
@@ -15566,12 +15963,15 @@ query GetAutomationRun($id: ID!) {
15566
15963
  automationRun(id: $id) {
15567
15964
  id
15568
15965
  automationId
15966
+ automationVersionId
15569
15967
  parentAutomationRunId
15570
15968
  status
15571
15969
  statusDetail
15572
15970
  summary
15573
15971
  invocationType
15574
15972
  input
15973
+ initialStore
15974
+ currentStore
15575
15975
  additionalPrompt
15576
15976
  debugUrl
15577
15977
  createdAt
@@ -15606,6 +16006,7 @@ query GetAutomationRun($id: ID!) {
15606
16006
  query GetAutomationRunAgentRuns($automationRunId: ID!) {
15607
16007
  automationRunAgentRuns(automationRunId: $automationRunId) {
15608
16008
  id
16009
+ agentId
15609
16010
  agentVersionId
15610
16011
  agentName
15611
16012
  status
@@ -15625,6 +16026,7 @@ query GetAutomationRunAgentRuns($automationRunId: ID!) {
15625
16026
  automationRunId: z27.string().min(1),
15626
16027
  agentRunId: z27.string().min(1).optional(),
15627
16028
  limit: z27.number().int().positive().optional(),
16029
+ page: z27.number().int().nonnegative().optional(),
15628
16030
  reverse: z27.boolean().optional()
15629
16031
  }),
15630
16032
  cli: {
@@ -15649,6 +16051,11 @@ query GetAutomationRunAgentRuns($automationRunId: ID!) {
15649
16051
  flagName: "limit",
15650
16052
  description: "Maximum number of iterations to return."
15651
16053
  }),
16054
+ numberOption({
16055
+ inputKey: "page",
16056
+ flagName: "page",
16057
+ description: "Zero-based page number."
16058
+ }),
15652
16059
  booleanOption({
15653
16060
  inputKey: "reverse",
15654
16061
  flagName: "reverse",
@@ -15662,18 +16069,21 @@ query GetAutomationRunIterations(
15662
16069
  $automationRunId: ID!
15663
16070
  $agentRunId: ID
15664
16071
  $limit: Int
16072
+ $page: Int
15665
16073
  $reverse: Boolean
15666
16074
  ) {
15667
16075
  automationRunIterations(
15668
16076
  automationRunId: $automationRunId
15669
16077
  agentRunId: $agentRunId
15670
16078
  limit: $limit
16079
+ page: $page
15671
16080
  reverse: $reverse
15672
16081
  ) {
15673
16082
  id
15674
16083
  sequence
15675
16084
  agentRunId
15676
16085
  metadata
16086
+ store
15677
16087
  startedAt
15678
16088
  finishedAt
15679
16089
  totalDurationMs
@@ -15689,6 +16099,42 @@ query GetAutomationRunIterations(
15689
16099
  screenshotMimeType
15690
16100
  }
15691
16101
  }
16102
+ }`
16103
+ }),
16104
+ createOperationSpec({
16105
+ operationName: "GetIterationScreenshot",
16106
+ kind: "query",
16107
+ inputSchema: z27.object({
16108
+ iterationId: z27.string().min(1),
16109
+ hasMarks: z27.boolean().default(false)
16110
+ }),
16111
+ cli: {
16112
+ name: "get-iteration-screenshot",
16113
+ path: ["automation-runs", "iteration-screenshot"],
16114
+ description: "Fetch a fresh screenshot URL for an iteration.",
16115
+ resultKey: "iterationScreenshot",
16116
+ options: [
16117
+ stringOption({
16118
+ inputKey: "iterationId",
16119
+ flagName: "iteration-id",
16120
+ description: "Automation run iteration ID.",
16121
+ required: true
16122
+ }),
16123
+ booleanOption({
16124
+ inputKey: "hasMarks",
16125
+ flagName: "with-marks",
16126
+ description: "Fetch the marked screenshot instead of the base screenshot."
16127
+ })
16128
+ ]
16129
+ },
16130
+ mcp: { fileName: "iterationScreenshot.graphql" },
16131
+ document: `# Fetch a fresh screenshot URL for an automation run iteration
16132
+ query GetIterationScreenshot($iterationId: ID!, $hasMarks: Boolean = false) {
16133
+ iterationScreenshot(iterationId: $iterationId, hasMarks: $hasMarks) {
16134
+ status
16135
+ url
16136
+ mimeType
16137
+ }
15692
16138
  }`
15693
16139
  }),
15694
16140
  createOperationSpec({
@@ -15777,6 +16223,7 @@ query GetAutomationRuns(
15777
16223
  ) {
15778
16224
  id
15779
16225
  automationId
16226
+ automationVersionId
15780
16227
  parentAutomationRunId
15781
16228
  status
15782
16229
  statusDetail
@@ -15825,6 +16272,7 @@ query GetAutomationRunsPage(
15825
16272
  items {
15826
16273
  id
15827
16274
  automationId
16275
+ automationVersionId
15828
16276
  parentAutomationRunId
15829
16277
  status
15830
16278
  statusDetail
@@ -16123,7 +16571,7 @@ query GetAutomationBranch($automationId: ID!, $branchId: ID!) {
16123
16571
  branchContext: "required",
16124
16572
  name: "merge-automation-branch",
16125
16573
  path: ["automations", "branches", "merge"],
16126
- description: "Preview and merge a branch into main when every change is conflict-free. Exits nonzero when conflicts block the merge.",
16574
+ description: "Preview and merge a branch into main when every change is conflict-free. Exits nonzero when conflicts block the merge; use `automations branches discard-changes` to resolve them.",
16127
16575
  resultKey: "mergeAutomationBranch",
16128
16576
  options: [
16129
16577
  stringOption({
@@ -16148,16 +16596,36 @@ mutation MergeAutomationBranch($automationId: ID!, $branchId: ID!) {
16148
16596
  targetVersionId
16149
16597
  changes {
16150
16598
  id
16599
+ kind
16151
16600
  group
16152
- label
16153
16601
  status
16602
+ label
16603
+ discardable
16604
+ agentId
16605
+ agentName
16606
+ field
16607
+ configKey
16608
+ fromAgentId
16609
+ toAgentId
16610
+ conflictDescription
16611
+ statusDescription
16154
16612
  }
16155
16613
  }
16156
16614
  conflicts {
16157
16615
  id
16616
+ kind
16158
16617
  group
16159
- label
16160
16618
  status
16619
+ label
16620
+ discardable
16621
+ agentId
16622
+ agentName
16623
+ field
16624
+ configKey
16625
+ fromAgentId
16626
+ toAgentId
16627
+ conflictDescription
16628
+ statusDescription
16161
16629
  }
16162
16630
  applyResult {
16163
16631
  draftVersionId
@@ -16166,6 +16634,150 @@ mutation MergeAutomationBranch($automationId: ID!, $branchId: ID!) {
16166
16634
  wasRebased
16167
16635
  }
16168
16636
  }
16637
+ }`
16638
+ }),
16639
+ createOperationSpec({
16640
+ operationName: "PreviewAutomationBranchMerge",
16641
+ kind: "query",
16642
+ inputSchema: z27.object({
16643
+ automationId: z27.uuid("--automation-id must be a UUID."),
16644
+ branchId: z27.uuid("--branch-id must be a UUID.")
16645
+ }),
16646
+ cli: {
16647
+ branchContext: "required",
16648
+ name: "preview-automation-branch-merge",
16649
+ path: ["automations", "branches", "merge-preview"],
16650
+ description: "Explain how a branch would merge into main: one change per agent field with its status and, for conflicts, why it conflicts. Writes nothing.",
16651
+ resultKey: "automationBranchMergePreview",
16652
+ options: [
16653
+ stringOption({
16654
+ inputKey: "automationId",
16655
+ flagName: "automation-id",
16656
+ description: "Automation ID.",
16657
+ required: true
16658
+ })
16659
+ ]
16660
+ },
16661
+ mcp: { fileName: "automationBranchMergePreview.graphql" },
16662
+ document: `# Explain how a branch would merge into main without writing anything.
16663
+ query PreviewAutomationBranchMerge($automationId: ID!, $branchId: ID!) {
16664
+ automationBranchMergePreview(automationId: $automationId, branchId: $branchId) {
16665
+ baseVersionId
16666
+ sourceVersionId
16667
+ targetVersionId
16668
+ changes {
16669
+ id
16670
+ kind
16671
+ group
16672
+ status
16673
+ label
16674
+ discardable
16675
+ agentId
16676
+ agentName
16677
+ field
16678
+ configKey
16679
+ fromAgentId
16680
+ toAgentId
16681
+ conflictDescription
16682
+ statusDescription
16683
+ }
16684
+ }
16685
+ }`
16686
+ }),
16687
+ createOperationSpec({
16688
+ operationName: "DiscardAutomationBranchChanges",
16689
+ kind: "mutation",
16690
+ inputSchema: z27.object({
16691
+ automationId: z27.uuid("--automation-id must be a UUID."),
16692
+ branchId: z27.uuid("--branch-id must be a UUID."),
16693
+ changeIds: z27.array(
16694
+ z27.string().min(1).max(
16695
+ AUTOMATION_BRANCH_CHANGE_ID_MAX_LENGTH,
16696
+ `--change-ids entries must be at most ${AUTOMATION_BRANCH_CHANGE_ID_MAX_LENGTH} characters.`
16697
+ )
16698
+ ).min(1, "--change-ids must name at least one preview change id.").max(
16699
+ AUTOMATION_BRANCH_DISCARD_MAX_CHANGE_IDS,
16700
+ `--change-ids can name at most ${AUTOMATION_BRANCH_DISCARD_MAX_CHANGE_IDS} preview change ids per run.`
16701
+ ),
16702
+ sourceVersionId: z27.uuid("--source-version-id must be a UUID."),
16703
+ targetVersionId: z27.uuid("--target-version-id must be a UUID.")
16704
+ }),
16705
+ cli: {
16706
+ branchContext: "required",
16707
+ name: "discard-automation-branch-changes",
16708
+ path: ["automations", "branches", "discard-changes"],
16709
+ description: "Revert preview changes on the branch so main keeps its values. Pass the change ids plus the source and target version ids from the preview you are acting on.",
16710
+ resultKey: "discardAutomationBranchChanges",
16711
+ options: [
16712
+ stringOption({
16713
+ inputKey: "automationId",
16714
+ flagName: "automation-id",
16715
+ description: "Automation ID.",
16716
+ required: true
16717
+ }),
16718
+ stringArrayOption({
16719
+ inputKey: "changeIds",
16720
+ flagName: "change-ids",
16721
+ description: "Preview change ids to revert on the branch, for example agent:update:<agent-id>:instructions.",
16722
+ required: true
16723
+ }),
16724
+ stringOption({
16725
+ inputKey: "sourceVersionId",
16726
+ flagName: "source-version-id",
16727
+ description: "sourceVersionId from the preview being acted on.",
16728
+ required: true
16729
+ }),
16730
+ stringOption({
16731
+ inputKey: "targetVersionId",
16732
+ flagName: "target-version-id",
16733
+ description: "targetVersionId from the preview being acted on.",
16734
+ required: true
16735
+ })
16736
+ ]
16737
+ },
16738
+ mcp: { fileName: "discardAutomationBranchChanges.graphql" },
16739
+ document: `# Revert preview changes on a branch and return the refreshed merge preview.
16740
+ mutation DiscardAutomationBranchChanges(
16741
+ $automationId: ID!
16742
+ $branchId: ID!
16743
+ $changeIds: [String!]!
16744
+ $sourceVersionId: ID!
16745
+ $targetVersionId: ID!
16746
+ ) {
16747
+ discardAutomationBranchChanges(
16748
+ automationId: $automationId
16749
+ branchId: $branchId
16750
+ changeIds: $changeIds
16751
+ sourceVersionId: $sourceVersionId
16752
+ targetVersionId: $targetVersionId
16753
+ ) {
16754
+ automationId
16755
+ branchId
16756
+ previousHeadVersionId
16757
+ headVersionId
16758
+ discardedChangeIds
16759
+ preview {
16760
+ baseVersionId
16761
+ sourceVersionId
16762
+ targetVersionId
16763
+ changes {
16764
+ id
16765
+ kind
16766
+ group
16767
+ status
16768
+ label
16769
+ discardable
16770
+ agentId
16771
+ agentName
16772
+ field
16773
+ configKey
16774
+ fromAgentId
16775
+ toAgentId
16776
+ conflictDescription
16777
+ statusDescription
16778
+ }
16779
+ }
16780
+ }
16169
16781
  }`
16170
16782
  }),
16171
16783
  createOperationSpec({
@@ -16276,7 +16888,8 @@ query GetAvailableCommands($env: AvailableCommandsEnv!) {
16276
16888
  operationName: "GetAvailableModels",
16277
16889
  kind: "query",
16278
16890
  inputSchema: z27.object({
16279
- agentId: z27.string().min(1)
16891
+ agentId: z27.string().min(1),
16892
+ automationId: z27.string().min(1)
16280
16893
  }),
16281
16894
  cli: {
16282
16895
  name: "get-available-models",
@@ -16289,13 +16902,20 @@ query GetAvailableCommands($env: AvailableCommandsEnv!) {
16289
16902
  flagName: "agent-id",
16290
16903
  description: "Agent ID.",
16291
16904
  required: true
16905
+ }),
16906
+ stringOption({
16907
+ inputKey: "automationId",
16908
+ flagName: "automation-id",
16909
+ description: "Automation whose head pins the agent (required with agent-id).",
16910
+ required: true
16292
16911
  })
16293
16912
  ]
16294
16913
  },
16295
16914
  mcp: { fileName: "availableModels.graphql" },
16296
16915
  document: `# Query to fetch available model definitions and pools for a specific agent
16297
- query GetAvailableModels($agentId: String!) {
16298
- availableModels(agentId: $agentId) {
16916
+ # from that automation's head (agent model config resolves branch-safely).
16917
+ query GetAvailableModels($agentId: String!, $automationId: String!) {
16918
+ availableModels(agentId: $agentId, automationId: $automationId) {
16299
16919
  availableModelPools {
16300
16920
  name
16301
16921
  poolId
@@ -18348,7 +18968,7 @@ ${evalRunExportSelection}
18348
18968
  ];
18349
18969
 
18350
18970
  // src/program.ts
18351
- import { Command as Command3, InvalidArgumentError as InvalidArgumentError2, Option as Option3 } from "commander";
18971
+ import { Command as Command4, InvalidArgumentError as InvalidArgumentError2, Option as Option4 } from "commander";
18352
18972
 
18353
18973
  // src/api.ts
18354
18974
  import { randomUUID } from "node:crypto";
@@ -18682,8 +19302,110 @@ var pathwayRegressionRunResultResponseSchema = z28.object({
18682
19302
  workflowId: z28.string().min(1)
18683
19303
  })
18684
19304
  });
18685
- var graphQlResponseSchema = z28.object({
18686
- data: z28.record(z28.string(), z28.unknown()).nullable().optional(),
19305
+ var regressionTestPathwayStatusSchema = z28.enum([
19306
+ "new_pathway",
19307
+ "missing_after_change",
19308
+ "historical_path_missing_after_change",
19309
+ "no_matching_runs",
19310
+ "queued",
19311
+ "running",
19312
+ "passed",
19313
+ "failed",
19314
+ "inconclusive",
19315
+ "errored"
19316
+ ]);
19317
+ var regressionTestStatusSchema = z28.enum([
19318
+ "queued",
19319
+ "running",
19320
+ "passed",
19321
+ "failed",
19322
+ "inconclusive",
19323
+ "errored"
19324
+ ]);
19325
+ var regressionTestKickoffPathwaySchema = z28.object({
19326
+ baselineContractPathId: z28.string().min(1).nullable(),
19327
+ baselineLabel: z28.string().nullable(),
19328
+ candidateContractPathId: z28.string().min(1).nullable(),
19329
+ candidateLabel: z28.string().nullable(),
19330
+ id: z28.string().min(1),
19331
+ pathwayKey: z28.string().min(1),
19332
+ status: regressionTestPathwayStatusSchema
19333
+ });
19334
+ var regressionTestKickoffResponseSchema = z28.object({
19335
+ pathways: z28.array(regressionTestKickoffPathwaySchema),
19336
+ regressionTestId: z28.string().min(1),
19337
+ status: regressionTestStatusSchema
19338
+ });
19339
+ var regressionTestIterationCountsSchema = z28.object({
19340
+ errored: z28.number(),
19341
+ failed: z28.number(),
19342
+ passed: z28.number(),
19343
+ total: z28.number()
19344
+ });
19345
+ var regressionTestBaselineRunSummarySchema = z28.object({
19346
+ id: z28.string().min(1),
19347
+ iterationCounts: regressionTestIterationCountsSchema
19348
+ });
19349
+ var regressionTestPathwaySummarySchema = z28.object({
19350
+ baselineLabel: z28.string().nullable(),
19351
+ baselineRuns: z28.array(regressionTestBaselineRunSummarySchema),
19352
+ candidateLabel: z28.string().nullable(),
19353
+ id: z28.string().min(1),
19354
+ pathwayKey: z28.string().min(1),
19355
+ status: regressionTestPathwayStatusSchema
19356
+ });
19357
+ var regressionTestResultResponseSchema = z28.object({
19358
+ pathways: z28.array(regressionTestPathwaySummarySchema),
19359
+ regressionTest: z28.object({
19360
+ finishedAt: z28.string().nullable(),
19361
+ id: z28.string().min(1),
19362
+ startedAt: z28.string().nullable(),
19363
+ status: regressionTestStatusSchema
19364
+ })
19365
+ });
19366
+ var regressionTestBaselineStepSchema = z28.object({
19367
+ expectedToolCall: z28.unknown().nullable(),
19368
+ id: z28.string().min(1),
19369
+ iterationIndex: z28.number()
19370
+ });
19371
+ var regressionTestFailedToolCallSchema = z28.object({
19372
+ count: z28.number(),
19373
+ observedToolCall: z28.unknown()
19374
+ });
19375
+ var regressionTestFailedIterationSchema = z28.object({
19376
+ baselineIterationId: z28.string().min(1),
19377
+ failedToolCalls: z28.array(regressionTestFailedToolCallSchema)
19378
+ });
19379
+ var regressionTestReplayCountsSchema = z28.object({
19380
+ errored: z28.number(),
19381
+ failed: z28.number(),
19382
+ passed: z28.number()
19383
+ });
19384
+ var regressionTestBaselineRunSchema = z28.object({
19385
+ baselineAgentRunId: z28.string().min(1),
19386
+ baselineIterations: z28.array(regressionTestBaselineStepSchema),
19387
+ failedIterations: z28.array(regressionTestFailedIterationSchema),
19388
+ replayCounts: regressionTestReplayCountsSchema
19389
+ });
19390
+ var regressionTestPathwayDetailSchema = z28.object({
19391
+ baselineLabel: z28.string().nullable(),
19392
+ baselineRuns: z28.array(regressionTestBaselineRunSchema),
19393
+ candidateLabel: z28.string().nullable(),
19394
+ id: z28.string().min(1),
19395
+ pathwayKey: z28.string().min(1),
19396
+ status: regressionTestPathwayStatusSchema
19397
+ });
19398
+ var regressionTestPathwayResultResponseSchema = z28.object({
19399
+ pathway: regressionTestPathwayDetailSchema,
19400
+ regressionTest: z28.object({
19401
+ finishedAt: z28.string().nullable(),
19402
+ id: z28.string().min(1),
19403
+ startedAt: z28.string().nullable(),
19404
+ status: regressionTestStatusSchema
19405
+ })
19406
+ });
19407
+ var graphQlResponseSchema = z28.object({
19408
+ data: z28.record(z28.string(), z28.unknown()).nullable().optional(),
18687
19409
  errors: z28.array(
18688
19410
  z28.object({
18689
19411
  extensions: z28.object({
@@ -18723,6 +19445,7 @@ function getGraphQlErrorStatus(error) {
18723
19445
  return error.extensions?.appErrorType?.includes("not-found") ? 404 : void 0;
18724
19446
  }
18725
19447
  var apiErrorResponseSchema = z28.object({
19448
+ code: z28.string().min(1).optional(),
18726
19449
  errors: z28.array(
18727
19450
  z28.object({
18728
19451
  message: z28.string().min(1)
@@ -18743,6 +19466,13 @@ function getApiErrorDetail(responseBody) {
18743
19466
  }
18744
19467
  return parsedResponse.data.errors.map((error) => error.message).join("\n");
18745
19468
  }
19469
+ function getApiErrorCode(responseBody) {
19470
+ const parsedResponse = apiErrorResponseSchema.safeParse(responseBody);
19471
+ if (!parsedResponse.success) {
19472
+ return null;
19473
+ }
19474
+ return parsedResponse.data.code ?? null;
19475
+ }
18746
19476
  function getRetryAfterMs(response) {
18747
19477
  const retryAfter = response.headers.get("retry-after");
18748
19478
  if (!retryAfter) {
@@ -18872,12 +19602,12 @@ function applyAuthenticationHeaders({
18872
19602
  headers.set(OTTO_AUTHORIZATION_HEADER_NAME, `Bearer ${accessToken}`);
18873
19603
  headers.set("x-organization-id", organizationId);
18874
19604
  }
18875
- function createMagicalApiClient({
19605
+ function createFetchJson({
18876
19606
  apiBaseUrl,
18877
- fetchFn = fetch
19607
+ fetchFn
18878
19608
  }) {
18879
19609
  const resolveApiBaseUrl = typeof apiBaseUrl === "string" ? () => apiBaseUrl : apiBaseUrl;
18880
- async function fetchJson({
19610
+ return async function fetchJson({
18881
19611
  accessToken,
18882
19612
  impersonatedOrganizationId,
18883
19613
  allowOttoAuthorization,
@@ -18929,13 +19659,23 @@ function createMagicalApiClient({
18929
19659
  });
18930
19660
  if (!response.ok) {
18931
19661
  const errorDetail = getApiErrorDetail(responseBody);
19662
+ const apiErrorCode = getApiErrorCode(responseBody);
18932
19663
  throw new CliError(
18933
19664
  `Magical API request to ${url} failed with status ${response.status}${errorDetail ? `: ${errorDetail}` : "."}`,
18934
- errorOptions
19665
+ {
19666
+ ...errorOptions,
19667
+ ...apiErrorCode === null ? {} : { apiErrorCode }
19668
+ }
18935
19669
  );
18936
19670
  }
18937
19671
  return responseBody;
18938
- }
19672
+ };
19673
+ }
19674
+ function createMagicalApiClient({
19675
+ apiBaseUrl,
19676
+ fetchFn = fetch
19677
+ }) {
19678
+ const fetchJson = createFetchJson({ apiBaseUrl, fetchFn });
18939
19679
  return {
18940
19680
  async downloadFile({ outputPath, overwrite = false, url }) {
18941
19681
  if (!overwrite) {
@@ -19228,6 +19968,77 @@ function createMagicalApiClient({
19228
19968
  );
19229
19969
  }
19230
19970
  return parsedResponse.data;
19971
+ },
19972
+ async startAgentVersionRegressionTest({
19973
+ accessToken,
19974
+ agentVersionId,
19975
+ automationVersionId,
19976
+ impersonatedOrganizationId,
19977
+ organizationId
19978
+ }) {
19979
+ const parsedResponse = regressionTestKickoffResponseSchema.safeParse(
19980
+ await fetchJson({
19981
+ accessToken,
19982
+ allowOttoAuthorization: true,
19983
+ ...impersonatedOrganizationId ? { impersonatedOrganizationId } : {},
19984
+ ...organizationId ? { organizationId } : {},
19985
+ path: `/pathway-regression/tests/automation-versions/${encodeURIComponent(
19986
+ automationVersionId
19987
+ )}/agent-versions/${encodeURIComponent(agentVersionId)}/run`,
19988
+ init: {
19989
+ method: "POST"
19990
+ }
19991
+ })
19992
+ );
19993
+ if (!parsedResponse.success) {
19994
+ throw new CliError("Regression test kickoff payload was invalid.");
19995
+ }
19996
+ return parsedResponse.data;
19997
+ },
19998
+ async getAgentVersionRegressionTestResult({
19999
+ accessToken,
20000
+ impersonatedOrganizationId,
20001
+ organizationId,
20002
+ regressionTestId
20003
+ }) {
20004
+ const parsedResponse = regressionTestResultResponseSchema.safeParse(
20005
+ await fetchJson({
20006
+ accessToken,
20007
+ allowOttoAuthorization: true,
20008
+ ...impersonatedOrganizationId ? { impersonatedOrganizationId } : {},
20009
+ ...organizationId ? { organizationId } : {},
20010
+ path: `/pathway-regression/tests/${encodeURIComponent(
20011
+ regressionTestId
20012
+ )}`
20013
+ })
20014
+ );
20015
+ if (!parsedResponse.success) {
20016
+ throw new CliError("Regression test result payload was invalid.");
20017
+ }
20018
+ return parsedResponse.data;
20019
+ },
20020
+ async getAgentVersionRegressionTestPathway({
20021
+ accessToken,
20022
+ impersonatedOrganizationId,
20023
+ organizationId,
20024
+ regressionTestId,
20025
+ testPathwayId
20026
+ }) {
20027
+ const parsedResponse = regressionTestPathwayResultResponseSchema.safeParse(
20028
+ await fetchJson({
20029
+ accessToken,
20030
+ allowOttoAuthorization: true,
20031
+ ...impersonatedOrganizationId ? { impersonatedOrganizationId } : {},
20032
+ ...organizationId ? { organizationId } : {},
20033
+ path: `/pathway-regression/tests/${encodeURIComponent(
20034
+ regressionTestId
20035
+ )}/pathways/${encodeURIComponent(testPathwayId)}`
20036
+ })
20037
+ );
20038
+ if (!parsedResponse.success) {
20039
+ throw new CliError("Regression test pathway payload was invalid.");
20040
+ }
20041
+ return parsedResponse.data;
19231
20042
  }
19232
20043
  };
19233
20044
  }
@@ -19454,6 +20265,18 @@ async function handleAuthLogin(dependencies, options) {
19454
20265
  );
19455
20266
  }
19456
20267
 
20268
+ // src/branch-merge.ts
20269
+ function isRecord5(value) {
20270
+ return typeof value === "object" && value !== null && !Array.isArray(value);
20271
+ }
20272
+ function assertBranchMergeApplied(operationSpec, result) {
20273
+ if (operationSpec.operationName === "MergeAutomationBranch" && (!isRecord5(result) || result["status"] !== "merged")) {
20274
+ throw new CliError(
20275
+ isRecord5(result) && result["status"] === "conflict" ? "Merge not applied. Discard the conflicting changes with `mgcl automations branches discard-changes` (main keeps its values) or edit the branch to match main, then rerun this merge command." : "Merge not applied. Review the merge output, resolve any conflicts, then merge again."
20276
+ );
20277
+ }
20278
+ }
20279
+
19457
20280
  // src/capture-commands.ts
19458
20281
  import { Command, Option } from "commander";
19459
20282
 
@@ -19746,7 +20569,7 @@ async function pollCaptureRecording({
19746
20569
  onStatus,
19747
20570
  recordingId,
19748
20571
  signal,
19749
- sleep: sleep2 = async (delayMs) => {
20572
+ sleep: sleep3 = async (delayMs) => {
19750
20573
  await defaultSleep(delayMs, signal);
19751
20574
  }
19752
20575
  }) {
@@ -19772,7 +20595,7 @@ async function pollCaptureRecording({
19772
20595
  throw error;
19773
20596
  }
19774
20597
  onRetry?.(error, retryDelay);
19775
- await sleep2(retryDelay);
20598
+ await sleep3(retryDelay);
19776
20599
  return await pollNext(state);
19777
20600
  }
19778
20601
  const status = statusResult.value;
@@ -19787,7 +20610,7 @@ async function pollCaptureRecording({
19787
20610
  if (TERMINAL_STATUSES.has(status.status)) {
19788
20611
  return status;
19789
20612
  }
19790
- await sleep2(DEFAULT_POLL_INTERVAL_MS);
20613
+ await sleep3(DEFAULT_POLL_INTERVAL_MS);
19791
20614
  return await pollNext({
19792
20615
  effectiveDeadlineMs,
19793
20616
  hasObservedRecording: true
@@ -20053,10 +20876,10 @@ async function finishExport({
20053
20876
  async function pollExport({
20054
20877
  executeOperation,
20055
20878
  exportId,
20056
- sleep: sleep2
20879
+ sleep: sleep3
20057
20880
  }) {
20058
20881
  for (; ; ) {
20059
- await sleep2(EXPORT_POLL_INTERVAL_MS);
20882
+ await sleep3(EXPORT_POLL_INTERVAL_MS);
20060
20883
  const result = parseApiResult(
20061
20884
  // eslint-disable-next-line no-await-in-loop -- do not overlap signed-export status requests
20062
20885
  await executeOperation("GetEvalRunExport", { exportId }),
@@ -20476,6 +21299,267 @@ function isExpiredAccessTokenClaims(claims) {
20476
21299
  return claims.exp * 1e3 <= Date.now();
20477
21300
  }
20478
21301
 
21302
+ // src/regression-commands.ts
21303
+ import { setTimeout as sleep } from "node:timers/promises";
21304
+ import { Command as Command2, Option as Option2 } from "commander";
21305
+ var REGRESSION_TEST_TERMINAL_STATUSES = /* @__PURE__ */ new Set([
21306
+ "passed",
21307
+ "failed",
21308
+ "inconclusive",
21309
+ "errored"
21310
+ ]);
21311
+ var REGRESSION_TEST_POLL_INTERVAL_MS = 5e3;
21312
+ var REGRESSION_TEST_KICKOFF_RETRY_DELAY_MS = 5e3;
21313
+ var REGRESSION_TEST_RETRYABLE_KICKOFF_ERROR_CODE = "PATHWAY_CONTRACT_NOT_READY";
21314
+ function isRetryableRegressionTestKickoffError(error) {
21315
+ return error instanceof CliError && error.statusCode === 409 && error.apiErrorCode === REGRESSION_TEST_RETRYABLE_KICKOFF_ERROR_CODE;
21316
+ }
21317
+ function summarizeRegressionTestResult(result) {
21318
+ return {
21319
+ regressionTestId: result.regressionTest.id,
21320
+ status: result.regressionTest.status,
21321
+ startedAt: result.regressionTest.startedAt,
21322
+ finishedAt: result.regressionTest.finishedAt,
21323
+ pathways: result.pathways.map((pathway) => ({
21324
+ id: pathway.id,
21325
+ pathwayKey: pathway.pathwayKey,
21326
+ baselineLabel: pathway.baselineLabel,
21327
+ candidateLabel: pathway.candidateLabel,
21328
+ status: pathway.status,
21329
+ baselineRuns: pathway.baselineRuns.map((run) => ({
21330
+ id: run.id,
21331
+ iterationCounts: run.iterationCounts
21332
+ }))
21333
+ }))
21334
+ };
21335
+ }
21336
+ function summarizeRegressionTestPathway(result) {
21337
+ return {
21338
+ regressionTestId: result.regressionTest.id,
21339
+ status: result.regressionTest.status,
21340
+ pathway: {
21341
+ id: result.pathway.id,
21342
+ pathwayKey: result.pathway.pathwayKey,
21343
+ baselineLabel: result.pathway.baselineLabel,
21344
+ candidateLabel: result.pathway.candidateLabel,
21345
+ status: result.pathway.status,
21346
+ baselineRuns: result.pathway.baselineRuns.map((run) => ({
21347
+ baselineAgentRunId: run.baselineAgentRunId,
21348
+ replayCounts: run.replayCounts,
21349
+ baselineIterationCount: run.baselineIterations.length,
21350
+ failedIterations: run.failedIterations.map((fi) => ({
21351
+ baselineIterationId: fi.baselineIterationId,
21352
+ failedToolCalls: fi.failedToolCalls.map((ftc) => ({
21353
+ observedToolCall: ftc.observedToolCall,
21354
+ count: ftc.count
21355
+ }))
21356
+ }))
21357
+ }))
21358
+ }
21359
+ };
21360
+ }
21361
+ async function startRegressionTestWithRetry({
21362
+ dependencies,
21363
+ input,
21364
+ startRegressionTest
21365
+ }) {
21366
+ for (; ; ) {
21367
+ const result = await fromThrowable(
21368
+ startRegressionTest.bind(void 0, input),
21369
+ "regression-test-kickoff-failed"
21370
+ );
21371
+ if (!isErr(result)) {
21372
+ return result.value;
21373
+ }
21374
+ if (!isRetryableRegressionTestKickoffError(result.error.cause)) {
21375
+ throw result.error.cause;
21376
+ }
21377
+ dependencies.io.info("Contract generation in progress, retrying...");
21378
+ await sleep(REGRESSION_TEST_KICKOFF_RETRY_DELAY_MS);
21379
+ }
21380
+ }
21381
+ async function pollRegressionTestResult({
21382
+ dependencies,
21383
+ getRegressionTestResult,
21384
+ input,
21385
+ regressionTestId
21386
+ }) {
21387
+ for (; ; ) {
21388
+ await sleep(REGRESSION_TEST_POLL_INTERVAL_MS);
21389
+ const result = await getRegressionTestResult({
21390
+ ...input,
21391
+ regressionTestId
21392
+ });
21393
+ if (REGRESSION_TEST_TERMINAL_STATUSES.has(result.regressionTest.status)) {
21394
+ return result;
21395
+ }
21396
+ dependencies.io.info(
21397
+ `Regression test ${regressionTestId}: ${result.regressionTest.status}...`
21398
+ );
21399
+ }
21400
+ }
21401
+ async function handleRegressionRunCommand({
21402
+ dependencies,
21403
+ helpers,
21404
+ options
21405
+ }) {
21406
+ const { accessToken, impersonatedOrganizationId, organization, state } = await helpers.withSelectedOrganizationAndAccessToken({
21407
+ dependencies,
21408
+ options
21409
+ });
21410
+ const startAgentVersionRegressionTest = helpers.requireApiClientMethod(
21411
+ dependencies.apiClient,
21412
+ "startAgentVersionRegressionTest"
21413
+ );
21414
+ const getAgentVersionRegressionTestResult = helpers.requireApiClientMethod(
21415
+ dependencies.apiClient,
21416
+ "getAgentVersionRegressionTestResult"
21417
+ );
21418
+ const authParams = {
21419
+ accessToken,
21420
+ ...impersonatedOrganizationId ? { impersonatedOrganizationId } : {},
21421
+ organizationId: organization.id
21422
+ };
21423
+ const kickoffResult = await startRegressionTestWithRetry({
21424
+ dependencies,
21425
+ input: {
21426
+ ...authParams,
21427
+ agentVersionId: options.agentVersion,
21428
+ automationVersionId: options.automationVersion
21429
+ },
21430
+ startRegressionTest: startAgentVersionRegressionTest
21431
+ });
21432
+ const { regressionTestId } = kickoffResult;
21433
+ dependencies.io.info(`Regression test started: ${regressionTestId}`);
21434
+ const result = await pollRegressionTestResult({
21435
+ dependencies,
21436
+ getRegressionTestResult: getAgentVersionRegressionTestResult,
21437
+ input: authParams,
21438
+ regressionTestId
21439
+ });
21440
+ await helpers.saveLastUsedOrganization({
21441
+ dependencies,
21442
+ organizationId: organization.id,
21443
+ state
21444
+ });
21445
+ helpers.writeCommandOutput({
21446
+ dependencies,
21447
+ json: options.json,
21448
+ result: options.json ? result : summarizeRegressionTestResult(result)
21449
+ });
21450
+ }
21451
+ async function handleRegressionShowCommand({
21452
+ dependencies,
21453
+ helpers,
21454
+ options
21455
+ }) {
21456
+ const { accessToken, impersonatedOrganizationId, organization, state } = await helpers.withSelectedOrganizationAndAccessToken({
21457
+ dependencies,
21458
+ options
21459
+ });
21460
+ const authParams = {
21461
+ accessToken,
21462
+ ...impersonatedOrganizationId ? { impersonatedOrganizationId } : {},
21463
+ organizationId: organization.id
21464
+ };
21465
+ await helpers.saveLastUsedOrganization({
21466
+ dependencies,
21467
+ organizationId: organization.id,
21468
+ state
21469
+ });
21470
+ if (options.pathway) {
21471
+ const getAgentVersionRegressionTestPathway = helpers.requireApiClientMethod(
21472
+ dependencies.apiClient,
21473
+ "getAgentVersionRegressionTestPathway"
21474
+ );
21475
+ const result2 = await getAgentVersionRegressionTestPathway({
21476
+ ...authParams,
21477
+ regressionTestId: options.testId,
21478
+ testPathwayId: options.pathway
21479
+ });
21480
+ helpers.writeCommandOutput({
21481
+ dependencies,
21482
+ json: options.json,
21483
+ result: options.json ? result2 : summarizeRegressionTestPathway(result2)
21484
+ });
21485
+ return;
21486
+ }
21487
+ const getAgentVersionRegressionTestResult = helpers.requireApiClientMethod(
21488
+ dependencies.apiClient,
21489
+ "getAgentVersionRegressionTestResult"
21490
+ );
21491
+ const result = await getAgentVersionRegressionTestResult({
21492
+ ...authParams,
21493
+ regressionTestId: options.testId
21494
+ });
21495
+ helpers.writeCommandOutput({
21496
+ dependencies,
21497
+ json: options.json,
21498
+ result: options.json ? result : summarizeRegressionTestResult(result)
21499
+ });
21500
+ }
21501
+ function addRegressionCommands({
21502
+ dependencies,
21503
+ helpers,
21504
+ program: program2
21505
+ }) {
21506
+ const regressionCommand = configureCommandPresentation(
21507
+ new Command2("regression").description(
21508
+ "Run and inspect agent version regression tests."
21509
+ )
21510
+ ).helpGroup("Workspace:").addHelpText(
21511
+ "after",
21512
+ `
21513
+ ${formatExamples("Examples", [
21514
+ "mgcl regression run --automation-version <id> --agent-version <id>",
21515
+ "mgcl regression show <testId>",
21516
+ "mgcl regression show <testId> --pathway <pathwayId>"
21517
+ ])}`
21518
+ );
21519
+ regressionCommand.command("run").description(
21520
+ "Start a regression test, poll until complete, and return the summary."
21521
+ ).addOption(
21522
+ new Option2(
21523
+ "--org <org>",
21524
+ "Organization ID or exact organization name to use."
21525
+ ).helpGroup("Shared options:")
21526
+ ).addOption(
21527
+ new Option2(
21528
+ "--automation-version <id>",
21529
+ "Automation version to test against."
21530
+ ).helpGroup("Regression options:").makeOptionMandatory(true)
21531
+ ).addOption(
21532
+ new Option2("--agent-version <id>", "Agent version to test.").helpGroup("Regression options:").makeOptionMandatory(true)
21533
+ ).action(async function() {
21534
+ await handleRegressionRunCommand({
21535
+ dependencies,
21536
+ helpers,
21537
+ options: this.optsWithGlobals()
21538
+ });
21539
+ });
21540
+ regressionCommand.command("show <testId>").description("Show regression test results.").addOption(
21541
+ new Option2(
21542
+ "--org <org>",
21543
+ "Organization ID or exact organization name to use."
21544
+ ).helpGroup("Shared options:")
21545
+ ).addOption(
21546
+ new Option2(
21547
+ "--pathway <pathwayId>",
21548
+ "Show detail for a specific pathway."
21549
+ ).helpGroup("Regression options:")
21550
+ ).action(async function(testId) {
21551
+ await handleRegressionShowCommand({
21552
+ dependencies,
21553
+ helpers,
21554
+ options: {
21555
+ ...this.optsWithGlobals(),
21556
+ testId
21557
+ }
21558
+ });
21559
+ });
21560
+ program2.addCommand(regressionCommand);
21561
+ }
21562
+
20479
21563
  // src/self-update.ts
20480
21564
  import { spawn as spawn2 } from "node:child_process";
20481
21565
  import fs2 from "node:fs";
@@ -20640,7 +21724,7 @@ async function selfUpdateInstalledCli({
20640
21724
  }
20641
21725
 
20642
21726
  // src/settings-command.ts
20643
- import { Command as Command2, InvalidArgumentError, Option as Option2 } from "commander";
21727
+ import { Command as Command3, InvalidArgumentError, Option as Option3 } from "commander";
20644
21728
  function writeJsonOutput2(io, value) {
20645
21729
  io.info(JSON.stringify(value, null, 2));
20646
21730
  }
@@ -20718,7 +21802,7 @@ async function handleSettingsEnvBaseUrl(dependencies, rawBaseUrl, options) {
20718
21802
  }
20719
21803
  function createSettingsCommand(dependencies) {
20720
21804
  const settingsCommand = configureCommandPresentation(
20721
- new Command2("settings").description("Manage persisted CLI settings.")
21805
+ new Command3("settings").description("Manage persisted CLI settings.")
20722
21806
  ).helpGroup("Workspace:").addHelpText(
20723
21807
  "after",
20724
21808
  `
@@ -20728,7 +21812,7 @@ ${formatExamples("Examples", [
20728
21812
  ])}`
20729
21813
  );
20730
21814
  const settingsEnvCommand = settingsCommand.command("env").description("Manage persisted environment overrides.");
20731
- settingsEnvCommand.command("base-url [url]").description("Set or clear the persisted Magical API base URL override.").addOption(new Option2("--reset", "Clear the persisted base URL override.")).action(async function(baseUrl) {
21815
+ settingsEnvCommand.command("base-url [url]").description("Set or clear the persisted Magical API base URL override.").addOption(new Option3("--reset", "Clear the persisted base URL override.")).action(async function(baseUrl) {
20732
21816
  await handleSettingsEnvBaseUrl(
20733
21817
  dependencies,
20734
21818
  baseUrl,
@@ -21556,7 +22640,7 @@ var accessTokenClaimsSchema = z34.object({
21556
22640
  });
21557
22641
  function createWorkosAuthClient({
21558
22642
  fetchFn = fetch,
21559
- sleep: sleep2 = async (milliseconds) => {
22643
+ sleep: sleep3 = async (milliseconds) => {
21560
22644
  await new Promise((resolve) => {
21561
22645
  setTimeout(resolve, milliseconds);
21562
22646
  });
@@ -21650,12 +22734,12 @@ function createWorkosAuthClient({
21650
22734
  );
21651
22735
  }
21652
22736
  if (parsedError.data.error === "authorization_pending") {
21653
- await sleep2(nextIntervalMilliseconds);
22737
+ await sleep3(nextIntervalMilliseconds);
21654
22738
  return poll(nextIntervalMilliseconds);
21655
22739
  }
21656
22740
  if (parsedError.data.error === "slow_down") {
21657
22741
  const slowedIntervalMilliseconds = nextIntervalMilliseconds + 5e3;
21658
- await sleep2(slowedIntervalMilliseconds);
22742
+ await sleep3(slowedIntervalMilliseconds);
21659
22743
  return poll(slowedIntervalMilliseconds);
21660
22744
  }
21661
22745
  throw new CliError(
@@ -21739,7 +22823,7 @@ function parseCommandOptionValue(rawValue, optionSpec) {
21739
22823
  function createCliCommanderOption(optionSpec, helpGroup) {
21740
22824
  const optionFlags = optionSpec.valueType === "boolean" ? `--${optionSpec.flagName}` : `--${optionSpec.flagName} <value>`;
21741
22825
  const optionDescription = optionSpec.valueHint ? `${optionSpec.description} (${optionSpec.valueHint})` : optionSpec.description;
21742
- const nextOption = new Option3(optionFlags, optionDescription).helpGroup(
22826
+ const nextOption = new Option4(optionFlags, optionDescription).helpGroup(
21743
22827
  helpGroup
21744
22828
  );
21745
22829
  if (optionSpec.valueType === "boolean") {
@@ -21759,7 +22843,7 @@ function parsePositiveIntegerOption(rawValue) {
21759
22843
  }
21760
22844
  return parsedValue;
21761
22845
  }
21762
- function isRecord5(value) {
22846
+ function isRecord6(value) {
21763
22847
  return typeof value === "object" && value !== null && !Array.isArray(value);
21764
22848
  }
21765
22849
  function resolveOrganizationBySelector({
@@ -21836,7 +22920,7 @@ function parseOperationVariables(operationSpec, variables) {
21836
22920
  parsedVariables.error.issues[0]?.message ?? "Invalid command input."
21837
22921
  );
21838
22922
  }
21839
- if (!isRecord5(parsedVariables.data)) {
22923
+ if (!isRecord6(parsedVariables.data)) {
21840
22924
  throw new CliError("Invalid command input.");
21841
22925
  }
21842
22926
  return parsedVariables.data;
@@ -21934,13 +23018,17 @@ async function handleOperationCommand(dependencies, operationSpec, commandOption
21934
23018
  ...state,
21935
23019
  lastUsedOrgId: organization.id
21936
23020
  });
23021
+ const humanReadableFormatter = getBranchMergeFormatter(
23022
+ operationSpec.operationName
23023
+ );
21937
23024
  writeCommandOutput({
21938
23025
  dependencies,
23026
+ ...humanReadableFormatter ? { humanReadableFormatter } : {},
21939
23027
  json: commandOptions.json,
21940
23028
  result
21941
23029
  });
21942
23030
  assertBranchMergeApplied(operationSpec, result);
21943
- if (operationSpec.operationName === "ViewAutomationReview" && commandOptions["open"] && isRecord5(result) && typeof result["reportUrl"] === "string") {
23031
+ if (operationSpec.operationName === "ViewAutomationReview" && commandOptions["open"] && isRecord6(result) && typeof result["reportUrl"] === "string") {
21944
23032
  await dependencies.openExternalUrl(result["reportUrl"]).catch((error) => {
21945
23033
  dependencies.io.error(
21946
23034
  `Warning: Failed to open the automation review in the default browser: ${getErrorMessage(error)}`
@@ -21948,13 +23036,6 @@ async function handleOperationCommand(dependencies, operationSpec, commandOption
21948
23036
  });
21949
23037
  }
21950
23038
  }
21951
- function assertBranchMergeApplied(operationSpec, result) {
21952
- if (operationSpec.operationName === "MergeAutomationBranch" && (!isRecord5(result) || result["status"] !== "merged")) {
21953
- throw new CliError(
21954
- "Merge not applied. Review the merge output, resolve any conflicts, then merge again."
21955
- );
21956
- }
21957
- }
21958
23039
  function getOperation(operationName) {
21959
23040
  const operationSpec = operationSpecs.find(
21960
23041
  (candidate) => candidate.operationName === operationName
@@ -22127,12 +23208,12 @@ function addSkillsWorkingCopyCommands({
22127
23208
  skillsCommand
22128
23209
  }) {
22129
23210
  skillsCommand.command("pull <skill>").description("Download a root-level skill into ./skills/<skill-name>.").addOption(
22130
- new Option3(
23211
+ new Option4(
22131
23212
  "--org <org>",
22132
23213
  "Organization ID or exact organization name to use."
22133
23214
  ).helpGroup("Shared options:")
22134
23215
  ).addOption(
22135
- new Option3(
23216
+ new Option4(
22136
23217
  "--force",
22137
23218
  "Replace existing files or local edits with the remote bundle."
22138
23219
  )
@@ -22151,7 +23232,7 @@ ${formatExamples("Examples", [
22151
23232
  );
22152
23233
  });
22153
23234
  skillsCommand.command("diff <skill>").description("Preview local skill changes against the pulled bundle.").addOption(
22154
- new Option3(
23235
+ new Option4(
22155
23236
  "--org <org>",
22156
23237
  "Organization ID or exact organization name to use."
22157
23238
  ).helpGroup("Shared options:")
@@ -22170,12 +23251,12 @@ ${formatExamples("Examples", [
22170
23251
  );
22171
23252
  });
22172
23253
  skillsCommand.command("push <skill>").description("Atomically push local changes for one root-level skill.").addOption(
22173
- new Option3(
23254
+ new Option4(
22174
23255
  "--org <org>",
22175
23256
  "Organization ID or exact organization name to use."
22176
23257
  ).helpGroup("Shared options:")
22177
23258
  ).addOption(
22178
- new Option3("--message <message>", "Commit message for the skill update.")
23259
+ new Option4("--message <message>", "Commit message for the skill update.")
22179
23260
  ).addHelpText(
22180
23261
  "after",
22181
23262
  `
@@ -22216,6 +23297,7 @@ async function withSelectedOrganizationAndAccessToken({
22216
23297
  }
22217
23298
  function writeCommandOutput({
22218
23299
  dependencies,
23300
+ humanReadableFormatter = formatHumanReadableOutput,
22219
23301
  json,
22220
23302
  result
22221
23303
  }) {
@@ -22223,7 +23305,7 @@ function writeCommandOutput({
22223
23305
  writeJsonOutput3(dependencies.io, result);
22224
23306
  return;
22225
23307
  }
22226
- dependencies.io.info(formatHumanReadableOutput(result));
23308
+ dependencies.io.info(humanReadableFormatter(result));
22227
23309
  }
22228
23310
  async function handleNangoIntegrationsListCommand(dependencies, options) {
22229
23311
  const { accessToken, impersonatedOrganizationId, organization, state } = await withSelectedOrganizationAndAccessToken({ dependencies, options });
@@ -22607,7 +23689,7 @@ async function retryCaptureRequest({
22607
23689
  throw error;
22608
23690
  }
22609
23691
  onRetry(error, retryDelay);
22610
- await sleep(retryDelay, void 0, { signal }).catch(
23692
+ await sleep2(retryDelay, void 0, { signal }).catch(
22611
23693
  (sleepError) => {
22612
23694
  throw new CliError("Capture wait interrupted.", { cause: sleepError });
22613
23695
  }
@@ -22857,7 +23939,7 @@ function configureOperationalCommand(command, dependencies, operationSpec) {
22857
23939
  command.description(operationSpec.cli.description);
22858
23940
  if (operationSpec.scope !== "global") {
22859
23941
  command.addOption(
22860
- new Option3(
23942
+ new Option4(
22861
23943
  "--org <org>",
22862
23944
  "Organization ID or exact organization name to use."
22863
23945
  ).helpGroup("Shared options:")
@@ -22938,14 +24020,14 @@ function createDefaultDependencies() {
22938
24020
  }
22939
24021
  function buildProgram(dependencies) {
22940
24022
  const program2 = configureCommandPresentation(
22941
- new Command3().name("mgcl").description("Run Magical operations from the command line.")
22942
- ).addOption(new Option3("--json", "Render JSON output.")).addOption(
22943
- new Option3(
24023
+ new Command4().name("mgcl").description("Run Magical operations from the command line.")
24024
+ ).addOption(new Option4("--json", "Render JSON output.")).addOption(
24025
+ new Option4(
22944
24026
  "--branch-id <id>",
22945
24027
  'Target a supported automation command at one branch; omit it to target main. "Branch-aware commands" below lists the commands that accept it.'
22946
24028
  )
22947
24029
  ).version(CLI_VERSION, "--version", `Display mgcl version (${CLI_VERSION}).`).addOption(
22948
- new Option3(
24030
+ new Option4(
22949
24031
  "--update",
22950
24032
  "Update mgcl to the latest published npm release."
22951
24033
  )
@@ -22971,7 +24053,7 @@ function buildProgram(dependencies) {
22971
24053
  this.outputHelp();
22972
24054
  });
22973
24055
  const authCommand = configureCommandPresentation(
22974
- new Command3("auth").description("Manage CLI authentication.")
24056
+ new Command4("auth").description("Manage CLI authentication.")
22975
24057
  ).helpGroup("Workspace:").addHelpText(
22976
24058
  "after",
22977
24059
  `
@@ -22986,7 +24068,7 @@ ${formatExamples("Examples", ["mgcl auth login", "mgcl auth logout"])}`
22986
24068
  program2.addCommand(authCommand);
22987
24069
  program2.addCommand(createSettingsCommand(dependencies));
22988
24070
  const orgCommand = configureCommandPresentation(
22989
- new Command3("org").description("Manage organization selection.")
24071
+ new Command4("org").description("Manage organization selection.")
22990
24072
  ).helpGroup("Workspace:").addHelpText(
22991
24073
  "after",
22992
24074
  `
@@ -23007,7 +24089,7 @@ ${formatExamples("Examples", [
23007
24089
  });
23008
24090
  program2.addCommand(orgCommand);
23009
24091
  const pathwayRegressionCommand = configureCommandPresentation(
23010
- new Command3("pathway-regression").description(
24092
+ new Command4("pathway-regression").description(
23011
24093
  "Preview, start, and inspect pathway regression runs."
23012
24094
  )
23013
24095
  ).helpGroup("Workspace:").addHelpText(
@@ -23021,20 +24103,20 @@ ${formatExamples("Examples", [
23021
24103
  ])}`
23022
24104
  );
23023
24105
  const addPathwayRegressionAgentVersionOptions = (command) => command.addOption(
23024
- new Option3(
24106
+ new Option4(
23025
24107
  "--org <org>",
23026
24108
  "Organization ID or exact organization name to use."
23027
24109
  ).helpGroup("Shared options:")
23028
24110
  ).addOption(
23029
- new Option3(
24111
+ new Option4(
23030
24112
  "--automation-version-id <id>",
23031
24113
  "Automation version to test against."
23032
24114
  ).helpGroup("Pathway regression options:").makeOptionMandatory(true)
23033
24115
  ).addOption(
23034
- new Option3("--agent-version-id <id>", "Agent version to test.").helpGroup("Pathway regression options:").makeOptionMandatory(true)
24116
+ new Option4("--agent-version-id <id>", "Agent version to test.").helpGroup("Pathway regression options:").makeOptionMandatory(true)
23035
24117
  );
23036
24118
  const addPathwayRegressionPreviewOptions = (command) => addPathwayRegressionAgentVersionOptions(command).addOption(
23037
- new Option3(
24119
+ new Option4(
23038
24120
  "--runs-per-path <count>",
23039
24121
  "Number of historical runs to use per pathway. Defaults to the service value."
23040
24122
  ).helpGroup("Pathway regression options:").argParser(parsePositiveIntegerOption)
@@ -23056,12 +24138,12 @@ ${formatExamples("Examples", [
23056
24138
  );
23057
24139
  });
23058
24140
  pathwayRegressionCommand.command("results").description("Read a pathway regression run result.").addOption(
23059
- new Option3(
24141
+ new Option4(
23060
24142
  "--org <org>",
23061
24143
  "Organization ID or exact organization name to use."
23062
24144
  ).helpGroup("Shared options:")
23063
24145
  ).addOption(
23064
- new Option3(
24146
+ new Option4(
23065
24147
  "--regression-run-id <id>",
23066
24148
  "Pathway regression run ID to inspect."
23067
24149
  ).helpGroup("Pathway regression options:").makeOptionMandatory(true)
@@ -23072,12 +24154,12 @@ ${formatExamples("Examples", [
23072
24154
  );
23073
24155
  });
23074
24156
  pathwayRegressionCommand.command("check-results").description("Read detailed check attempts for one replay iteration.").addOption(
23075
- new Option3(
24157
+ new Option4(
23076
24158
  "--org <org>",
23077
24159
  "Organization ID or exact organization name to use."
23078
24160
  ).helpGroup("Shared options:")
23079
24161
  ).addOption(
23080
- new Option3(
24162
+ new Option4(
23081
24163
  "--regression-replay-iteration-id <id>",
23082
24164
  "Pathway regression replay iteration ID to inspect."
23083
24165
  ).helpGroup("Pathway regression options:").makeOptionMandatory(true)
@@ -23088,19 +24170,29 @@ ${formatExamples("Examples", [
23088
24170
  );
23089
24171
  });
23090
24172
  program2.addCommand(pathwayRegressionCommand);
24173
+ addRegressionCommands({
24174
+ dependencies,
24175
+ helpers: {
24176
+ requireApiClientMethod,
24177
+ saveLastUsedOrganization,
24178
+ withSelectedOrganizationAndAccessToken,
24179
+ writeCommandOutput
24180
+ },
24181
+ program: program2
24182
+ });
23091
24183
  const pathwaysCommand = configureCommandPresentation(
23092
- new Command3("pathways").description("Inspect pathways.")
24184
+ new Command4("pathways").description("Inspect pathways.")
23093
24185
  ).helpGroup("Workspace:");
23094
24186
  const pathwaySignaturesCommand = configureCommandPresentation(
23095
- new Command3("signatures").description("Inspect agent-run signatures.")
24187
+ new Command4("signatures").description("Inspect agent-run signatures.")
23096
24188
  );
23097
24189
  pathwaySignaturesCommand.command("get").description("Read an agent-run pathway signature.").addOption(
23098
- new Option3(
24190
+ new Option4(
23099
24191
  "--org <org>",
23100
24192
  "Organization ID or exact organization name to use."
23101
24193
  ).helpGroup("Shared options:")
23102
24194
  ).addOption(
23103
- new Option3("--agent-run-id <id>", "Agent run ID to inspect.").helpGroup("Pathway signature options:").makeOptionMandatory(true)
24195
+ new Option4("--agent-run-id <id>", "Agent run ID to inspect.").helpGroup("Pathway signature options:").makeOptionMandatory(true)
23104
24196
  ).action(async function() {
23105
24197
  await handlePathwaySignatureGetCommand(
23106
24198
  dependencies,
@@ -23110,7 +24202,7 @@ ${formatExamples("Examples", [
23110
24202
  pathwaysCommand.addCommand(pathwaySignaturesCommand);
23111
24203
  program2.addCommand(pathwaysCommand);
23112
24204
  const nangoCommand = configureCommandPresentation(
23113
- new Command3("nango").description(
24205
+ new Command4("nango").description(
23114
24206
  "Inspect Nango integrations and org-scoped authentications."
23115
24207
  )
23116
24208
  ).helpGroup("Workspace:").addHelpText(
@@ -23122,10 +24214,10 @@ ${formatExamples("Examples", [
23122
24214
  ])}`
23123
24215
  );
23124
24216
  const nangoIntegrationsCommand = configureCommandPresentation(
23125
- new Command3("integrations").description("Work with Nango integrations.")
24217
+ new Command4("integrations").description("Work with Nango integrations.")
23126
24218
  );
23127
24219
  nangoIntegrationsCommand.command("list").description("List Nango integrations available in the current workspace.").addOption(
23128
- new Option3(
24220
+ new Option4(
23129
24221
  "--org <org>",
23130
24222
  "Organization ID or exact organization name to use."
23131
24223
  ).helpGroup("Shared options:")
@@ -23137,22 +24229,22 @@ ${formatExamples("Examples", [
23137
24229
  });
23138
24230
  nangoCommand.addCommand(nangoIntegrationsCommand);
23139
24231
  const nangoAuthsCommand = configureCommandPresentation(
23140
- new Command3("auths").alias("authentications").description("Work with org-scoped Nango authentications.")
24232
+ new Command4("auths").alias("authentications").description("Work with org-scoped Nango authentications.")
23141
24233
  );
23142
24234
  nangoAuthsCommand.command("list").description(
23143
24235
  "List org-scoped Nango authentications and their connection IDs."
23144
24236
  ).addOption(
23145
- new Option3(
24237
+ new Option4(
23146
24238
  "--org <org>",
23147
24239
  "Organization ID or exact organization name to use."
23148
24240
  ).helpGroup("Shared options:")
23149
24241
  ).addOption(
23150
- new Option3(
24242
+ new Option4(
23151
24243
  "--integration <integration>",
23152
24244
  "Optional integration key to filter Nango authentications."
23153
24245
  )
23154
24246
  ).addOption(
23155
- new Option3(
24247
+ new Option4(
23156
24248
  "--connection-id <connectionId>",
23157
24249
  "Optional connection ID to filter Nango authentications."
23158
24250
  )
@@ -23170,7 +24262,7 @@ ${formatExamples("Examples", [
23170
24262
  nangoCommand.addCommand(nangoAuthsCommand);
23171
24263
  program2.addCommand(nangoCommand);
23172
24264
  const updateCommand = configureCommandPresentation(
23173
- new Command3("update").description(
24265
+ new Command4("update").description(
23174
24266
  "Update mgcl to the latest published npm release."
23175
24267
  )
23176
24268
  ).helpGroup("Workspace:").addHelpText(