@getmagical/cli 0.2.5 → 0.2.6
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/README.md +87 -0
- package/dist/index.js +1724 -351
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2056,13 +2056,13 @@ var require_ast = __commonJS({
|
|
|
2056
2056
|
helperExpression: function helperExpression(node) {
|
|
2057
2057
|
return node.type === "SubExpression" || (node.type === "MustacheStatement" || node.type === "BlockStatement") && !!(node.params && node.params.length || node.hash);
|
|
2058
2058
|
},
|
|
2059
|
-
scopedId: function scopedId(
|
|
2060
|
-
return /^\.|this\b/.test(
|
|
2059
|
+
scopedId: function scopedId(path9) {
|
|
2060
|
+
return /^\.|this\b/.test(path9.original);
|
|
2061
2061
|
},
|
|
2062
2062
|
// an ID is simple if it only has one part, and that part is not
|
|
2063
2063
|
// `..` or `this`.
|
|
2064
|
-
simpleId: function simpleId(
|
|
2065
|
-
return
|
|
2064
|
+
simpleId: function simpleId(path9) {
|
|
2065
|
+
return path9.parts.length === 1 && !AST.helpers.scopedId(path9) && !path9.depth;
|
|
2066
2066
|
}
|
|
2067
2067
|
}
|
|
2068
2068
|
};
|
|
@@ -3132,12 +3132,12 @@ var require_helpers2 = __commonJS({
|
|
|
3132
3132
|
loc
|
|
3133
3133
|
};
|
|
3134
3134
|
}
|
|
3135
|
-
function prepareMustache(
|
|
3135
|
+
function prepareMustache(path9, params, hash, open, strip, locInfo) {
|
|
3136
3136
|
var escapeFlag = open.charAt(3) || open.charAt(2), escaped = escapeFlag !== "{" && escapeFlag !== "&";
|
|
3137
3137
|
var decorator = /\*/.test(open);
|
|
3138
3138
|
return {
|
|
3139
3139
|
type: decorator ? "Decorator" : "MustacheStatement",
|
|
3140
|
-
path:
|
|
3140
|
+
path: path9,
|
|
3141
3141
|
params,
|
|
3142
3142
|
hash,
|
|
3143
3143
|
escaped,
|
|
@@ -3455,9 +3455,9 @@ var require_compiler = __commonJS({
|
|
|
3455
3455
|
},
|
|
3456
3456
|
DecoratorBlock: function DecoratorBlock(decorator) {
|
|
3457
3457
|
var program2 = decorator.program && this.compileProgram(decorator.program);
|
|
3458
|
-
var params = this.setupFullMustacheParams(decorator, program2, void 0),
|
|
3458
|
+
var params = this.setupFullMustacheParams(decorator, program2, void 0), path9 = decorator.path;
|
|
3459
3459
|
this.useDecorators = true;
|
|
3460
|
-
this.opcode("registerDecorator", params.length,
|
|
3460
|
+
this.opcode("registerDecorator", params.length, path9.original);
|
|
3461
3461
|
},
|
|
3462
3462
|
PartialStatement: function PartialStatement(partial) {
|
|
3463
3463
|
this.usePartial = true;
|
|
@@ -3521,46 +3521,46 @@ var require_compiler = __commonJS({
|
|
|
3521
3521
|
}
|
|
3522
3522
|
},
|
|
3523
3523
|
ambiguousSexpr: function ambiguousSexpr(sexpr, program2, inverse) {
|
|
3524
|
-
var
|
|
3525
|
-
this.opcode("getContext",
|
|
3524
|
+
var path9 = sexpr.path, name = path9.parts[0], isBlock = program2 != null || inverse != null;
|
|
3525
|
+
this.opcode("getContext", path9.depth);
|
|
3526
3526
|
this.opcode("pushProgram", program2);
|
|
3527
3527
|
this.opcode("pushProgram", inverse);
|
|
3528
|
-
|
|
3529
|
-
this.accept(
|
|
3528
|
+
path9.strict = true;
|
|
3529
|
+
this.accept(path9);
|
|
3530
3530
|
this.opcode("invokeAmbiguous", name, isBlock);
|
|
3531
3531
|
},
|
|
3532
3532
|
simpleSexpr: function simpleSexpr(sexpr) {
|
|
3533
|
-
var
|
|
3534
|
-
|
|
3535
|
-
this.accept(
|
|
3533
|
+
var path9 = sexpr.path;
|
|
3534
|
+
path9.strict = true;
|
|
3535
|
+
this.accept(path9);
|
|
3536
3536
|
this.opcode("resolvePossibleLambda");
|
|
3537
3537
|
},
|
|
3538
3538
|
helperSexpr: function helperSexpr(sexpr, program2, inverse) {
|
|
3539
|
-
var params = this.setupFullMustacheParams(sexpr, program2, inverse),
|
|
3539
|
+
var params = this.setupFullMustacheParams(sexpr, program2, inverse), path9 = sexpr.path, name = path9.parts[0];
|
|
3540
3540
|
if (this.options.knownHelpers[name]) {
|
|
3541
3541
|
this.opcode("invokeKnownHelper", params.length, name);
|
|
3542
3542
|
} else if (this.options.knownHelpersOnly) {
|
|
3543
3543
|
throw new _exception2["default"]("You specified knownHelpersOnly, but used the unknown helper " + name, sexpr);
|
|
3544
3544
|
} else {
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
this.accept(
|
|
3548
|
-
this.opcode("invokeHelper", params.length,
|
|
3545
|
+
path9.strict = true;
|
|
3546
|
+
path9.falsy = true;
|
|
3547
|
+
this.accept(path9);
|
|
3548
|
+
this.opcode("invokeHelper", params.length, path9.original, _ast2["default"].helpers.simpleId(path9));
|
|
3549
3549
|
}
|
|
3550
3550
|
},
|
|
3551
|
-
PathExpression: function PathExpression(
|
|
3552
|
-
this.addDepth(
|
|
3553
|
-
this.opcode("getContext",
|
|
3554
|
-
var name =
|
|
3551
|
+
PathExpression: function PathExpression(path9) {
|
|
3552
|
+
this.addDepth(path9.depth);
|
|
3553
|
+
this.opcode("getContext", path9.depth);
|
|
3554
|
+
var name = path9.parts[0], scoped = _ast2["default"].helpers.scopedId(path9), blockParamId = !path9.depth && !scoped && this.blockParamIndex(name);
|
|
3555
3555
|
if (blockParamId) {
|
|
3556
|
-
this.opcode("lookupBlockParam", blockParamId,
|
|
3556
|
+
this.opcode("lookupBlockParam", blockParamId, path9.parts);
|
|
3557
3557
|
} else if (!name) {
|
|
3558
3558
|
this.opcode("pushContext");
|
|
3559
|
-
} else if (
|
|
3559
|
+
} else if (path9.data) {
|
|
3560
3560
|
this.options.data = true;
|
|
3561
|
-
this.opcode("lookupData",
|
|
3561
|
+
this.opcode("lookupData", path9.depth, path9.parts, path9.strict);
|
|
3562
3562
|
} else {
|
|
3563
|
-
this.opcode("lookupOnContext",
|
|
3563
|
+
this.opcode("lookupOnContext", path9.parts, path9.falsy, path9.strict, scoped);
|
|
3564
3564
|
}
|
|
3565
3565
|
},
|
|
3566
3566
|
StringLiteral: function StringLiteral(string) {
|
|
@@ -3910,16 +3910,16 @@ var require_util2 = __commonJS({
|
|
|
3910
3910
|
}
|
|
3911
3911
|
exports.urlGenerate = urlGenerate;
|
|
3912
3912
|
function normalize(aPath) {
|
|
3913
|
-
var
|
|
3913
|
+
var path9 = aPath;
|
|
3914
3914
|
var url = urlParse(aPath);
|
|
3915
3915
|
if (url) {
|
|
3916
3916
|
if (!url.path) {
|
|
3917
3917
|
return aPath;
|
|
3918
3918
|
}
|
|
3919
|
-
|
|
3919
|
+
path9 = url.path;
|
|
3920
3920
|
}
|
|
3921
|
-
var isAbsolute = exports.isAbsolute(
|
|
3922
|
-
var parts =
|
|
3921
|
+
var isAbsolute = exports.isAbsolute(path9);
|
|
3922
|
+
var parts = path9.split(/\/+/);
|
|
3923
3923
|
for (var part, up = 0, i = parts.length - 1; i >= 0; i--) {
|
|
3924
3924
|
part = parts[i];
|
|
3925
3925
|
if (part === ".") {
|
|
@@ -3936,15 +3936,15 @@ var require_util2 = __commonJS({
|
|
|
3936
3936
|
}
|
|
3937
3937
|
}
|
|
3938
3938
|
}
|
|
3939
|
-
|
|
3940
|
-
if (
|
|
3941
|
-
|
|
3939
|
+
path9 = parts.join("/");
|
|
3940
|
+
if (path9 === "") {
|
|
3941
|
+
path9 = isAbsolute ? "/" : ".";
|
|
3942
3942
|
}
|
|
3943
3943
|
if (url) {
|
|
3944
|
-
url.path =
|
|
3944
|
+
url.path = path9;
|
|
3945
3945
|
return urlGenerate(url);
|
|
3946
3946
|
}
|
|
3947
|
-
return
|
|
3947
|
+
return path9;
|
|
3948
3948
|
}
|
|
3949
3949
|
exports.normalize = normalize;
|
|
3950
3950
|
function join(aRoot, aPath) {
|
|
@@ -6727,8 +6727,8 @@ var require_printer = __commonJS({
|
|
|
6727
6727
|
return this.accept(sexpr.path) + " " + params + hash;
|
|
6728
6728
|
};
|
|
6729
6729
|
PrintVisitor.prototype.PathExpression = function(id) {
|
|
6730
|
-
var
|
|
6731
|
-
return (id.data ? "@" : "") + "PATH:" +
|
|
6730
|
+
var path9 = id.parts.join("/");
|
|
6731
|
+
return (id.data ? "@" : "") + "PATH:" + path9;
|
|
6732
6732
|
};
|
|
6733
6733
|
PrintVisitor.prototype.StringLiteral = function(string) {
|
|
6734
6734
|
return '"' + string.value + '"';
|
|
@@ -7079,8 +7079,8 @@ function getErrorMessage(error) {
|
|
|
7079
7079
|
}
|
|
7080
7080
|
|
|
7081
7081
|
// src/program.ts
|
|
7082
|
-
import { readFile as
|
|
7083
|
-
import
|
|
7082
|
+
import { readFile as readFile6 } from "node:fs/promises";
|
|
7083
|
+
import path8 from "node:path";
|
|
7084
7084
|
|
|
7085
7085
|
// ../common/dist/src/stdlib/json.util.js
|
|
7086
7086
|
var import_ts_essentials = __toESM(require_dist(), 1);
|
|
@@ -11818,6 +11818,7 @@ var fieldMetadataSchema = z7.object({
|
|
|
11818
11818
|
description: z7.string().describe("A description of the input parameter.").nullable(),
|
|
11819
11819
|
typeOverride: z7.string().describe("The override for the input parameter.").nullable(),
|
|
11820
11820
|
enumLabels: z7.record(z7.string(), z7.string()).describe("Optional map of enum values to their display labels.").optional(),
|
|
11821
|
+
displayDefaultValue: z7.unknown().describe("Optional value to display when input is omitted without changing the parsed value.").optional(),
|
|
11821
11822
|
label: z7.string().describe("Optional label override for the field.").optional(),
|
|
11822
11823
|
allowLineBreaks: z7.boolean().describe("Whether the field should allow line breaks when supported by the input component.").optional(),
|
|
11823
11824
|
hideEmptyInCollapsed: z7.boolean().describe("Whether to hide this field in collapsed view when empty.").optional(),
|
|
@@ -11850,6 +11851,7 @@ var clickTypeEnumSchema = z7.enum([
|
|
|
11850
11851
|
"DOUBLE",
|
|
11851
11852
|
"TRIPLE"
|
|
11852
11853
|
]);
|
|
11854
|
+
var updateModeSchema = z7.enum(["append", "prepend", "replace"]);
|
|
11853
11855
|
var clickTypeSchema = withMetadata(clickTypeEnumSchema.optional(), {
|
|
11854
11856
|
description: "The type of click to perform",
|
|
11855
11857
|
typeOverride: null
|
|
@@ -11922,8 +11924,8 @@ var RENDER_TEMPLATE_ERROR_REASON_CATALOG = defineErrorReasonCatalog()([
|
|
|
11922
11924
|
]);
|
|
11923
11925
|
var storeReferencePathPattern = String.raw`store(?:\.[$A-Z_a-z][\w$]*)*`;
|
|
11924
11926
|
var storeReferenceMarkdownLinkTemplateRegex = new RegExp(String.raw`(?<open>\{\{\{?)\s*\[(?<path>${storeReferencePathPattern})\]\(\s*<?https?:\/\/\k<path>>?\s*\)\s*(?<close>\}\}\}?)`, "gu");
|
|
11925
|
-
function normalizeAutomationStoreTemplateLinkMatch([_match, open,
|
|
11926
|
-
return open === "{{{" ? `{{{${
|
|
11927
|
+
function normalizeAutomationStoreTemplateLinkMatch([_match, open, path9]) {
|
|
11928
|
+
return open === "{{{" ? `{{{${path9}}}}` : `{{${path9}}}`;
|
|
11927
11929
|
}
|
|
11928
11930
|
function normalizeAutomationStoreTemplateLinks(template) {
|
|
11929
11931
|
return template.replaceAll(storeReferenceMarkdownLinkTemplateRegex, (...args) => normalizeAutomationStoreTemplateLinkMatch(args));
|
|
@@ -12491,18 +12493,18 @@ var reportStopDataSchema = z11.object({
|
|
|
12491
12493
|
// ../common/dist/src/utils/automation-store-path.util.js
|
|
12492
12494
|
var AUTOMATION_STORE_ROOT_PATH = "store";
|
|
12493
12495
|
var relativeStorePathRegex = /^[$A-Z_a-z][\w$]*(?:\.[$A-Z_a-z][\w$]*)*$/u;
|
|
12494
|
-
function normalizeStoreMutationPath(
|
|
12495
|
-
const trimmedPath =
|
|
12496
|
+
function normalizeStoreMutationPath(path9) {
|
|
12497
|
+
const trimmedPath = path9.trim();
|
|
12496
12498
|
const rootPrefix = `${AUTOMATION_STORE_ROOT_PATH}.`;
|
|
12497
12499
|
const relativePath = trimmedPath.startsWith(rootPrefix) ? trimmedPath.slice(rootPrefix.length) : trimmedPath;
|
|
12498
12500
|
if (!relativeStorePathRegex.test(relativePath)) {
|
|
12499
12501
|
return Err({
|
|
12500
12502
|
type: "invalid-automation-store-path",
|
|
12501
|
-
path:
|
|
12503
|
+
path: path9,
|
|
12502
12504
|
categories: ["customer_usage"],
|
|
12503
12505
|
statusCode: 400,
|
|
12504
12506
|
nonRetryable: true,
|
|
12505
|
-
message: `Automation store path "${
|
|
12507
|
+
message: `Automation store path "${path9}" is invalid.`,
|
|
12506
12508
|
suggestedAction: "Use a dot path relative to the automation store, such as patient.name or provider.clinic."
|
|
12507
12509
|
});
|
|
12508
12510
|
}
|
|
@@ -12515,16 +12517,16 @@ function findAutomationStorePathOverlap(paths) {
|
|
|
12515
12517
|
...new Set(paths.map(getCanonicalAutomationStoreMutationPath))
|
|
12516
12518
|
].toSorted((left, right) => (left === AUTOMATION_STORE_ROOT_PATH ? 0 : left.split(".").length) - (right === AUTOMATION_STORE_ROOT_PATH ? 0 : right.split(".").length));
|
|
12517
12519
|
for (const [index, ancestorPath] of canonicalPaths.entries()) {
|
|
12518
|
-
const descendantPath = canonicalPaths.slice(index + 1).find((
|
|
12520
|
+
const descendantPath = canonicalPaths.slice(index + 1).find((path9) => ancestorPath === AUTOMATION_STORE_ROOT_PATH || path9.startsWith(`${ancestorPath}.`));
|
|
12519
12521
|
if (descendantPath !== void 0) {
|
|
12520
12522
|
return { ancestorPath, descendantPath };
|
|
12521
12523
|
}
|
|
12522
12524
|
}
|
|
12523
12525
|
return void 0;
|
|
12524
12526
|
}
|
|
12525
|
-
function getCanonicalAutomationStoreMutationPath(
|
|
12526
|
-
const normalizedPath = normalizeStoreMutationPath(
|
|
12527
|
-
return normalizedPath._tag === "Ok" ? normalizedPath.value :
|
|
12527
|
+
function getCanonicalAutomationStoreMutationPath(path9) {
|
|
12528
|
+
const normalizedPath = normalizeStoreMutationPath(path9);
|
|
12529
|
+
return normalizedPath._tag === "Ok" ? normalizedPath.value : path9.trim();
|
|
12528
12530
|
}
|
|
12529
12531
|
|
|
12530
12532
|
// ../common/dist/src/constants/tool-declarations.js
|
|
@@ -12748,9 +12750,9 @@ var baseToolDeclarations = {
|
|
|
12748
12750
|
path: []
|
|
12749
12751
|
});
|
|
12750
12752
|
}
|
|
12751
|
-
const canonicalUpdatePaths = updates.map(({ path:
|
|
12753
|
+
const canonicalUpdatePaths = updates.map(({ path: path9 }) => getCanonicalAutomationStoreMutationPath(path9));
|
|
12752
12754
|
const canonicalClearPathSet = new Set(clears.map(getCanonicalAutomationStoreMutationPath));
|
|
12753
|
-
const conflictedUpdatePath = canonicalUpdatePaths.find((
|
|
12755
|
+
const conflictedUpdatePath = canonicalUpdatePaths.find((path9) => canonicalClearPathSet.has(path9));
|
|
12754
12756
|
if (conflictedUpdatePath !== void 0) {
|
|
12755
12757
|
context.addIssue({
|
|
12756
12758
|
code: "custom",
|
|
@@ -12826,10 +12828,11 @@ var baseToolDeclarations = {
|
|
|
12826
12828
|
},
|
|
12827
12829
|
type: {
|
|
12828
12830
|
id: "type",
|
|
12829
|
-
description: "Type in the currently focused element
|
|
12831
|
+
description: "Type in the currently focused element. By default, this replaces the complete current value; updateMode can instead append or prepend the text.",
|
|
12830
12832
|
parameters: z12.object({
|
|
12831
12833
|
[COMMON_PARAMETERS_KEY]: DEFAULT_COMMON_PARAMETERS,
|
|
12832
|
-
text: z12.string().describe("The text to type")
|
|
12834
|
+
text: z12.string().describe("The text to type"),
|
|
12835
|
+
updateMode: updateModeSchema.optional().describe("How to combine the text with the current value. Defaults to replace.")
|
|
12833
12836
|
})
|
|
12834
12837
|
},
|
|
12835
12838
|
getNDCFromMedication: {
|
|
@@ -13429,9 +13432,9 @@ var specialCommands = {
|
|
|
13429
13432
|
};
|
|
13430
13433
|
|
|
13431
13434
|
// ../common/dist/src/utils/agent-knowledge-base-assets.util.js
|
|
13432
|
-
function getIsKnowledgeBaseAssetPathAllowed(
|
|
13433
|
-
const pathSegments =
|
|
13434
|
-
if (
|
|
13435
|
+
function getIsKnowledgeBaseAssetPathAllowed(path9) {
|
|
13436
|
+
const pathSegments = path9.split("/");
|
|
13437
|
+
if (path9.length === 0 || pathSegments.some((segment) => segment.length === 0)) {
|
|
13435
13438
|
return false;
|
|
13436
13439
|
}
|
|
13437
13440
|
const isTopLevelAssetPath = pathSegments[0] === "assets";
|
|
@@ -13473,46 +13476,46 @@ var API_FILE_TYPE_REGISTRY = {
|
|
|
13473
13476
|
var ApiAgentOutputModes = ["inline", "file"];
|
|
13474
13477
|
var API_EMBEDDED_FILE_PATH_PATTERN = /^(?:\[\*\]|[A-Za-z_$][\w$-]*)(?:\[\*\]|\.[A-Za-z_$][\w$-]*)*$/u;
|
|
13475
13478
|
var API_EMBEDDED_FILE_PATH_SEGMENT_PATTERN = /\[\*\]|[A-Za-z_$][\w$-]*/gu;
|
|
13476
|
-
function parseApiEmbeddedFilePath(
|
|
13477
|
-
if (!API_EMBEDDED_FILE_PATH_PATTERN.test(
|
|
13479
|
+
function parseApiEmbeddedFilePath(path9) {
|
|
13480
|
+
if (!API_EMBEDDED_FILE_PATH_PATTERN.test(path9)) {
|
|
13478
13481
|
return void 0;
|
|
13479
13482
|
}
|
|
13480
|
-
return [...
|
|
13483
|
+
return [...path9.matchAll(API_EMBEDDED_FILE_PATH_SEGMENT_PATTERN)].map(([segment]) => segment === "[*]" ? { type: "arrayWildcard" } : { key: segment, type: "property" });
|
|
13481
13484
|
}
|
|
13482
13485
|
var apiAgentEmbeddedFileSchema = z14.object({
|
|
13483
|
-
path: z14.string().trim().min(1, "Embedded file path is required.").refine((
|
|
13486
|
+
path: z14.string().trim().min(1, "Embedded file path is required.").refine((path9) => parseApiEmbeddedFilePath(path9) !== void 0, {
|
|
13484
13487
|
message: "Embedded file path must use object properties and [*] array wildcards."
|
|
13485
13488
|
}).describe("Path to a Base64 value relative to the projected API response. Supports object properties and [*] array wildcards."),
|
|
13486
13489
|
contentType: z14.enum(ApiFileContentTypes).describe("File type of the decoded Base64 value.")
|
|
13487
13490
|
}).strict();
|
|
13488
13491
|
var apiAgentEmbeddedFilesSchema = z14.array(apiAgentEmbeddedFileSchema).superRefine((embeddedFiles, context) => {
|
|
13489
13492
|
const paths = /* @__PURE__ */ new Set();
|
|
13490
|
-
for (const [index, { path:
|
|
13491
|
-
if (paths.has(
|
|
13493
|
+
for (const [index, { path: path9 }] of embeddedFiles.entries()) {
|
|
13494
|
+
if (paths.has(path9)) {
|
|
13492
13495
|
context.addIssue({
|
|
13493
13496
|
code: z14.ZodIssueCode.custom,
|
|
13494
|
-
message: `Embedded file path "${
|
|
13497
|
+
message: `Embedded file path "${path9}" can only be configured once.`,
|
|
13495
13498
|
path: [index, "path"]
|
|
13496
13499
|
});
|
|
13497
13500
|
}
|
|
13498
|
-
paths.add(
|
|
13501
|
+
paths.add(path9);
|
|
13499
13502
|
}
|
|
13500
13503
|
}).describe("Base64 values to decode, upload as permanent files, and replace with file references in the projected API response.");
|
|
13501
13504
|
|
|
13502
13505
|
// ../common/dist/src/zod-schemas/api-agent-request-file-encoding.schema.js
|
|
13503
13506
|
import { z as z15 } from "zod";
|
|
13504
13507
|
var API_REQUEST_FILE_PATH_PATTERN = /^[A-Za-z_$][\w$-]*(?:\.[A-Za-z_$][\w$-]*)*$/u;
|
|
13505
|
-
function parseApiRequestFilePath(
|
|
13506
|
-
if (!API_REQUEST_FILE_PATH_PATTERN.test(
|
|
13508
|
+
function parseApiRequestFilePath(path9) {
|
|
13509
|
+
if (!API_REQUEST_FILE_PATH_PATTERN.test(path9)) {
|
|
13507
13510
|
return void 0;
|
|
13508
13511
|
}
|
|
13509
|
-
return
|
|
13512
|
+
return path9.split(".");
|
|
13510
13513
|
}
|
|
13511
13514
|
var apiAgentRequestFileEncodingSchema = z15.object({
|
|
13512
|
-
sourceInput: z15.string().trim().min(1, "File input is required.").refine((
|
|
13515
|
+
sourceInput: z15.string().trim().min(1, "File input is required.").refine((path9) => parseApiRequestFilePath(path9) !== void 0, {
|
|
13513
13516
|
message: "File input must use an object property path."
|
|
13514
13517
|
}).describe("API Agent input containing the file reference to encode."),
|
|
13515
|
-
destinationPath: z15.string().trim().min(1, "Request field is required.").refine((
|
|
13518
|
+
destinationPath: z15.string().trim().min(1, "Request field is required.").refine((path9) => parseApiRequestFilePath(path9) !== void 0, {
|
|
13516
13519
|
message: "Request field must use an object property path."
|
|
13517
13520
|
}).describe("JSON request body path where the encoded value is inserted."),
|
|
13518
13521
|
encoding: z15.literal("base64").describe("Encoding applied to the source file before insertion.")
|
|
@@ -13863,20 +13866,20 @@ function hasControlCharacter(value) {
|
|
|
13863
13866
|
}
|
|
13864
13867
|
return false;
|
|
13865
13868
|
}
|
|
13866
|
-
function isNormalizedRepoPath(
|
|
13867
|
-
if (
|
|
13869
|
+
function isNormalizedRepoPath(path9) {
|
|
13870
|
+
if (path9 === "/") {
|
|
13868
13871
|
return true;
|
|
13869
13872
|
}
|
|
13870
|
-
if (
|
|
13873
|
+
if (path9.length === 0 || path9.startsWith("/") || path9.startsWith("\\") || path9.includes("\\") || hasControlCharacter(path9) || windowsAbsolutePathPattern.test(path9)) {
|
|
13871
13874
|
return false;
|
|
13872
13875
|
}
|
|
13873
|
-
return
|
|
13876
|
+
return path9.split("/").every((segment) => segment.length > 0 && segment !== "." && segment !== ".." && segment !== ".git");
|
|
13874
13877
|
}
|
|
13875
|
-
function normalizeRepoPath(
|
|
13876
|
-
if (
|
|
13877
|
-
return
|
|
13878
|
+
function normalizeRepoPath(path9) {
|
|
13879
|
+
if (path9 === "/") {
|
|
13880
|
+
return path9;
|
|
13878
13881
|
}
|
|
13879
|
-
return
|
|
13882
|
+
return path9.replaceAll(/\/+$/gu, "");
|
|
13880
13883
|
}
|
|
13881
13884
|
var skillPathPattern = /^(?:skills\/.+|automations\/[^/]+\/skills\/.+|automations\/[^/]+\/agents\/[^/]+\/skills\/.+)$/u;
|
|
13882
13885
|
var repoPathSchema = z21.string().min(1).transform(normalizeRepoPath).refine(isNormalizedRepoPath, {
|
|
@@ -13897,7 +13900,7 @@ var memoryConfigSchema = z21.object({
|
|
|
13897
13900
|
}).strict().describe("Configuration for the memory runtime plugin.");
|
|
13898
13901
|
var skillsConfigSchema = z21.object({
|
|
13899
13902
|
enabled: z21.boolean().default(false).describe("Explicit rollout switch for the skills runtime plugin."),
|
|
13900
|
-
registeredSkills: z21.array(repoPathSchema.refine((
|
|
13903
|
+
registeredSkills: z21.array(repoPathSchema.refine((path9) => skillPathPattern.test(path9), {
|
|
13901
13904
|
message: "Skill paths must be under root, automation, or automation-agent skills."
|
|
13902
13905
|
})).default(() => []).describe("Repository skill root paths available to the skills plugin."),
|
|
13903
13906
|
canEdit: z21.boolean().default(false).describe("Allows the skills runtime plugin to edit repo skills under the root skills folder.")
|
|
@@ -13921,6 +13924,7 @@ var baseAgentConfigFieldsSchema = z21.object({
|
|
|
13921
13924
|
environmentOptions: environmentOptionsSchema.optional().default(DEFAULT_ENVIRONMENT_OPTION).describe("Environment configuration for the agent. Default is browser with SOM."),
|
|
13922
13925
|
runSettings: agentRunSettingsSchema.optional().describe("Run settings persisted on the agent and used when this agent is selected as the settings source for a run while the run-settings rollout is enabled. This is the canonical runtime source for resource pools during the migration. It intentionally mirrors a subset of agent config so settings survive topology changes and can be stored on any agent regardless of that agent's own execution environment. Writers may populate this before the rollout flag is enabled, but runtime snapshotting must keep using legacy fields while the flag is disabled."),
|
|
13923
13926
|
skipBrowserDebuggerPauses: z21.boolean().optional().describe("Legacy agent-local browser session startup setting. Used only when a run is in legacy config mode; canonical run settings mode reads runSettings.skipBrowserDebuggerPauses instead."),
|
|
13927
|
+
stepFollowingVerification: z21.enum(["default", "enabled", "disabled"]).optional().describe("Controls step-following verification for this agent. Default runs verification unless skills are enabled; enabled forces it on past the skills rule; disabled forces it off. Automation and system feature gates still take precedence."),
|
|
13924
13928
|
limitations: agentRunLimitationSchema.describe("Resource limits for this agent, including maximum duration and tool call limits."),
|
|
13925
13929
|
commonParametersSchema: z21.custom().optional().describe("Custom schema defining metadata the agent must provide with every tool call. By default, agents provide reasoning and step information. If specified, this schema replaces the default metadata schema entirely."),
|
|
13926
13930
|
idempotencySettings: z21.object({
|
|
@@ -14327,13 +14331,13 @@ function getMentionedStandardCommand(instructions) {
|
|
|
14327
14331
|
const normalizedInstructions = instructions.toLowerCase();
|
|
14328
14332
|
return STANDARD_COMMAND_NAMES.find((commandName) => normalizedInstructions.includes(commandName.toLowerCase())) ?? null;
|
|
14329
14333
|
}
|
|
14330
|
-
function assertCustomInstructionsCommand({ commands, path:
|
|
14331
|
-
const customCommands = commands.flatMap((command, commandIndex) => command["commandName"] === "custom" ? [{ command, path: `${
|
|
14334
|
+
function assertCustomInstructionsCommand({ commands, path: path9 }) {
|
|
14335
|
+
const customCommands = commands.flatMap((command, commandIndex) => command["commandName"] === "custom" ? [{ command, path: `${path9}[${commandIndex.toString()}]` }] : []);
|
|
14332
14336
|
if (customCommands.length === 0) {
|
|
14333
14337
|
return;
|
|
14334
14338
|
}
|
|
14335
14339
|
if (customCommands.length > MAX_CUSTOM_COMMAND_COUNT) {
|
|
14336
|
-
throw createInvalidValueError(`${
|
|
14340
|
+
throw createInvalidValueError(`${path9} contains ${customCommands.length.toString()} custom commands. Use at most one short custom command per agent. Split policy, decision, outreach, and multi-step work into catalog commands or child agents instead.`);
|
|
14337
14341
|
}
|
|
14338
14342
|
const [customCommand] = customCommands;
|
|
14339
14343
|
if (!customCommand) {
|
|
@@ -14388,26 +14392,32 @@ function createOperationSpec(spec) {
|
|
|
14388
14392
|
|
|
14389
14393
|
// ../mcp-registry/src/operation-specs.ts
|
|
14390
14394
|
function stringOption({
|
|
14395
|
+
clientOnly = false,
|
|
14391
14396
|
description,
|
|
14392
14397
|
flagName,
|
|
14393
14398
|
inputKey,
|
|
14394
|
-
required = false
|
|
14399
|
+
required = false,
|
|
14400
|
+
valueHint
|
|
14395
14401
|
}) {
|
|
14396
14402
|
return {
|
|
14403
|
+
...clientOnly ? { clientOnly: true } : {},
|
|
14397
14404
|
description,
|
|
14398
14405
|
flagName,
|
|
14399
14406
|
inputKey,
|
|
14400
14407
|
required,
|
|
14408
|
+
...valueHint ? { valueHint } : {},
|
|
14401
14409
|
valueType: "string"
|
|
14402
14410
|
};
|
|
14403
14411
|
}
|
|
14404
14412
|
function numberOption({
|
|
14413
|
+
clientOnly = false,
|
|
14405
14414
|
description,
|
|
14406
14415
|
flagName,
|
|
14407
14416
|
inputKey,
|
|
14408
14417
|
required = false
|
|
14409
14418
|
}) {
|
|
14410
14419
|
return {
|
|
14420
|
+
...clientOnly ? { clientOnly: true } : {},
|
|
14411
14421
|
description,
|
|
14412
14422
|
flagName,
|
|
14413
14423
|
inputKey,
|
|
@@ -14416,11 +14426,13 @@ function numberOption({
|
|
|
14416
14426
|
};
|
|
14417
14427
|
}
|
|
14418
14428
|
function booleanOption({
|
|
14429
|
+
clientOnly = false,
|
|
14419
14430
|
description,
|
|
14420
14431
|
flagName,
|
|
14421
14432
|
inputKey
|
|
14422
14433
|
}) {
|
|
14423
14434
|
return {
|
|
14435
|
+
...clientOnly ? { clientOnly: true } : {},
|
|
14424
14436
|
description,
|
|
14425
14437
|
flagName,
|
|
14426
14438
|
inputKey,
|
|
@@ -14458,13 +14470,79 @@ function jsonOption({
|
|
|
14458
14470
|
};
|
|
14459
14471
|
}
|
|
14460
14472
|
var jsonObjectSchema = z25.record(z25.string(), z25.unknown());
|
|
14473
|
+
var evalRunStatusSchema = z25.enum([
|
|
14474
|
+
"QUEUED",
|
|
14475
|
+
"RUNNING",
|
|
14476
|
+
"COMPLETE",
|
|
14477
|
+
"FAILED",
|
|
14478
|
+
"CANCELLED"
|
|
14479
|
+
]);
|
|
14480
|
+
var evalInputChoicesSchema = z25.record(
|
|
14481
|
+
z25.string(),
|
|
14482
|
+
z25.array(z25.unknown()).min(1)
|
|
14483
|
+
);
|
|
14484
|
+
var registeredEvalRunInputSchema = z25.object({
|
|
14485
|
+
description: z25.string().min(1).optional(),
|
|
14486
|
+
input: evalInputChoicesSchema,
|
|
14487
|
+
maxConcurrency: z25.number().int().positive().default(1),
|
|
14488
|
+
name: z25.string().min(1).optional(),
|
|
14489
|
+
repeatCount: z25.number().int().positive().default(1),
|
|
14490
|
+
slug: z25.string().min(1),
|
|
14491
|
+
tags: z25.array(z25.string().min(1)).default([])
|
|
14492
|
+
});
|
|
14493
|
+
var registeredEvalSelection = ` slug
|
|
14494
|
+
name
|
|
14495
|
+
description
|
|
14496
|
+
tags
|
|
14497
|
+
version
|
|
14498
|
+
inputSchema`;
|
|
14499
|
+
var evalRunSelection = ` id
|
|
14500
|
+
createdAt
|
|
14501
|
+
updatedAt
|
|
14502
|
+
userId
|
|
14503
|
+
slug
|
|
14504
|
+
evalName
|
|
14505
|
+
evalDescription
|
|
14506
|
+
evalTags
|
|
14507
|
+
evalVersion
|
|
14508
|
+
input
|
|
14509
|
+
name
|
|
14510
|
+
description
|
|
14511
|
+
tags
|
|
14512
|
+
scorerSlugs
|
|
14513
|
+
maxConcurrency
|
|
14514
|
+
repeatCount
|
|
14515
|
+
acknowledgedTrialCount
|
|
14516
|
+
idempotencyKey
|
|
14517
|
+
dashboardUrl
|
|
14518
|
+
workflowId
|
|
14519
|
+
workflowRunId
|
|
14520
|
+
status
|
|
14521
|
+
startedAt
|
|
14522
|
+
finishedAt
|
|
14523
|
+
trialStatusCounts {
|
|
14524
|
+
queued
|
|
14525
|
+
running
|
|
14526
|
+
complete
|
|
14527
|
+
failed
|
|
14528
|
+
cancelled
|
|
14529
|
+
}`;
|
|
14530
|
+
var evalRunExportSelection = ` exportId
|
|
14531
|
+
evalRunId
|
|
14532
|
+
status
|
|
14533
|
+
workflowId
|
|
14534
|
+
workflowRunId
|
|
14535
|
+
fileName
|
|
14536
|
+
trialCount
|
|
14537
|
+
downloadUrl
|
|
14538
|
+
error`;
|
|
14461
14539
|
function isRecord3(value) {
|
|
14462
14540
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14463
14541
|
}
|
|
14464
14542
|
function validateCustomInstructionsCommands({
|
|
14465
14543
|
commands,
|
|
14466
14544
|
ctx,
|
|
14467
|
-
path:
|
|
14545
|
+
path: path9
|
|
14468
14546
|
}) {
|
|
14469
14547
|
if (!Array.isArray(commands)) {
|
|
14470
14548
|
return;
|
|
@@ -14472,14 +14550,14 @@ function validateCustomInstructionsCommands({
|
|
|
14472
14550
|
const validationResult = fromThrowable(() => {
|
|
14473
14551
|
assertCustomInstructionsCommand({
|
|
14474
14552
|
commands: commands.map((command) => isRecord3(command) ? command : {}),
|
|
14475
|
-
path:
|
|
14553
|
+
path: path9.join(".").replaceAll(/\.(?<index>\d+)/gu, "[$<index>]")
|
|
14476
14554
|
});
|
|
14477
14555
|
}, "invalid-custom-instructions-command");
|
|
14478
14556
|
if (isErr(validationResult)) {
|
|
14479
14557
|
ctx.addIssue({
|
|
14480
14558
|
code: "custom",
|
|
14481
14559
|
message: `${getErrorMessage2(validationResult.error.cause)} Run mgcl catalog commands to find the standard command for this work.`,
|
|
14482
|
-
path:
|
|
14560
|
+
path: path9
|
|
14483
14561
|
});
|
|
14484
14562
|
}
|
|
14485
14563
|
}
|
|
@@ -14715,6 +14793,7 @@ ${agentLimitationsSelection}
|
|
|
14715
14793
|
systemPrompt
|
|
14716
14794
|
additionalSystemPrompt
|
|
14717
14795
|
ignoreUnstableSessionState
|
|
14796
|
+
stepFollowingVerification
|
|
14718
14797
|
resourcePools {
|
|
14719
14798
|
id
|
|
14720
14799
|
type
|
|
@@ -14784,6 +14863,7 @@ ${agentLimitationsSelection}
|
|
|
14784
14863
|
systemPrompt
|
|
14785
14864
|
additionalSystemPrompt
|
|
14786
14865
|
ignoreUnstableSessionState
|
|
14866
|
+
stepFollowingVerification
|
|
14787
14867
|
}
|
|
14788
14868
|
isCurrent
|
|
14789
14869
|
}
|
|
@@ -16980,140 +17060,770 @@ mutation UpdateAutomationById($id: ID!, $input: UpdateAutomationInput!) {
|
|
|
16980
17060
|
lastSavedAt
|
|
16981
17061
|
}
|
|
16982
17062
|
}`
|
|
16983
|
-
})
|
|
16984
|
-
|
|
16985
|
-
|
|
16986
|
-
|
|
16987
|
-
|
|
16988
|
-
|
|
16989
|
-
|
|
16990
|
-
|
|
16991
|
-
|
|
16992
|
-
|
|
16993
|
-
|
|
16994
|
-
|
|
16995
|
-
|
|
16996
|
-
|
|
16997
|
-
|
|
16998
|
-
|
|
16999
|
-
|
|
17000
|
-
|
|
17001
|
-
fs.readFileSync(packageManifestPath, "utf8")
|
|
17002
|
-
);
|
|
17003
|
-
if (isErr(packageManifestResult)) {
|
|
17004
|
-
throw new Error(`Failed to parse ${packageManifestPath}.`, {
|
|
17005
|
-
cause: packageManifestResult.error.cause
|
|
17006
|
-
});
|
|
17007
|
-
}
|
|
17008
|
-
var cliPackageVersion = packageManifestResult.value.version;
|
|
17009
|
-
if (typeof cliPackageVersion !== "string" || cliPackageVersion.length === 0) {
|
|
17010
|
-
throw new Error(`Expected a version in ${packageManifestPath}.`);
|
|
17011
|
-
}
|
|
17012
|
-
var CLI_VERSION = cliPackageVersion;
|
|
17013
|
-
|
|
17014
|
-
// src/api.ts
|
|
17015
|
-
var OTTO_AUTHORIZATION_HEADER_NAME = "X-Otto-Authorization";
|
|
17016
|
-
var OTTO_AUTHORIZATION_ISSUER = "magical:otto";
|
|
17017
|
-
var workosOrganizationsResponseSchema = z26.object({
|
|
17018
|
-
organizations: z26.array(
|
|
17019
|
-
z26.object({
|
|
17020
|
-
id: z26.string().min(1),
|
|
17021
|
-
name: z26.string().min(1),
|
|
17022
|
-
primaryDomain: z26.string().nullable().optional()
|
|
17023
|
-
})
|
|
17024
|
-
),
|
|
17025
|
-
success: z26.boolean()
|
|
17026
|
-
});
|
|
17027
|
-
var workosUserSchema = z26.object({
|
|
17028
|
-
email: z26.string().nullable(),
|
|
17029
|
-
id: z26.string().min(1)
|
|
17030
|
-
});
|
|
17031
|
-
var nangoIntegrationWireSchema = z26.object({
|
|
17032
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention -- mirrors Nango REST payload
|
|
17033
|
-
unique_key: z26.string().min(1)
|
|
17034
|
-
}).passthrough().transform((data) => ({
|
|
17035
|
-
...data,
|
|
17036
|
-
uniqueKey: data.unique_key
|
|
17037
|
-
}));
|
|
17038
|
-
var nangoIntegrationsResponseSchema = z26.array(nangoIntegrationWireSchema);
|
|
17039
|
-
var organizationAuthenticationSchema = z26.object({
|
|
17040
|
-
id: z26.string().min(1),
|
|
17041
|
-
type: z26.string().min(1),
|
|
17042
|
-
connectionId: z26.string().nullable().optional(),
|
|
17043
|
-
providerConfigKey: z26.string().nullable().optional(),
|
|
17044
|
-
description: z26.string().nullable().optional(),
|
|
17045
|
-
hostname: z26.string().nullable().optional()
|
|
17046
|
-
}).passthrough();
|
|
17047
|
-
var organizationAuthenticationsResponseSchema = z26.object({
|
|
17048
|
-
authentications: z26.array(organizationAuthenticationSchema),
|
|
17049
|
-
success: z26.boolean()
|
|
17050
|
-
});
|
|
17051
|
-
var graphQlResponseSchema = z26.object({
|
|
17052
|
-
data: z26.record(z26.string(), z26.unknown()).optional(),
|
|
17053
|
-
errors: z26.array(
|
|
17054
|
-
z26.object({
|
|
17055
|
-
message: z26.string().min(1)
|
|
17056
|
-
})
|
|
17057
|
-
).optional()
|
|
17058
|
-
});
|
|
17059
|
-
var apiErrorResponseSchema = z26.object({
|
|
17060
|
-
errors: z26.array(
|
|
17061
|
-
z26.object({
|
|
17062
|
-
message: z26.string().min(1)
|
|
17063
|
-
})
|
|
17064
|
-
).optional(),
|
|
17065
|
-
message: z26.string().min(1).optional()
|
|
17066
|
-
});
|
|
17067
|
-
function getApiErrorDetail(responseBody) {
|
|
17068
|
-
const parsedResponse = apiErrorResponseSchema.safeParse(responseBody);
|
|
17069
|
-
if (!parsedResponse.success) {
|
|
17070
|
-
return null;
|
|
17071
|
-
}
|
|
17072
|
-
if (parsedResponse.data.message) {
|
|
17073
|
-
return parsedResponse.data.message;
|
|
17063
|
+
}),
|
|
17064
|
+
createOperationSpec({
|
|
17065
|
+
operationName: "ListRegisteredEvals",
|
|
17066
|
+
kind: "query",
|
|
17067
|
+
inputSchema: z25.object({}),
|
|
17068
|
+
cli: {
|
|
17069
|
+
name: "list-registered-evals",
|
|
17070
|
+
path: ["evals", "list"],
|
|
17071
|
+
description: "List globally registered eval definitions.",
|
|
17072
|
+
resultKey: "registeredEvals",
|
|
17073
|
+
options: []
|
|
17074
|
+
},
|
|
17075
|
+
mcp: { fileName: "registeredEvals.graphql" },
|
|
17076
|
+
scope: "global",
|
|
17077
|
+
document: `# List globally registered eval definitions available to the authenticated caller
|
|
17078
|
+
query ListRegisteredEvals {
|
|
17079
|
+
registeredEvals {
|
|
17080
|
+
${registeredEvalSelection}
|
|
17074
17081
|
}
|
|
17075
|
-
|
|
17076
|
-
|
|
17082
|
+
}`
|
|
17083
|
+
}),
|
|
17084
|
+
createOperationSpec({
|
|
17085
|
+
operationName: "GetRegisteredEval",
|
|
17086
|
+
kind: "query",
|
|
17087
|
+
inputSchema: z25.object({ slug: z25.string().min(1) }),
|
|
17088
|
+
cli: {
|
|
17089
|
+
name: "get-registered-eval",
|
|
17090
|
+
path: ["evals", "get"],
|
|
17091
|
+
description: "Get one globally registered eval definition.",
|
|
17092
|
+
resultKey: "registeredEval",
|
|
17093
|
+
options: [
|
|
17094
|
+
stringOption({
|
|
17095
|
+
description: "Registered eval slug.",
|
|
17096
|
+
flagName: "slug",
|
|
17097
|
+
inputKey: "slug",
|
|
17098
|
+
required: true
|
|
17099
|
+
})
|
|
17100
|
+
]
|
|
17101
|
+
},
|
|
17102
|
+
mcp: { fileName: "registeredEval.graphql" },
|
|
17103
|
+
scope: "global",
|
|
17104
|
+
document: `# Get one globally registered eval definition by slug
|
|
17105
|
+
query GetRegisteredEval($slug: String!) {
|
|
17106
|
+
registeredEval(slug: $slug) {
|
|
17107
|
+
${registeredEvalSelection}
|
|
17077
17108
|
}
|
|
17078
|
-
|
|
17079
|
-
}
|
|
17080
|
-
|
|
17081
|
-
|
|
17082
|
-
|
|
17083
|
-
|
|
17084
|
-
|
|
17085
|
-
|
|
17086
|
-
|
|
17087
|
-
|
|
17088
|
-
|
|
17089
|
-
|
|
17109
|
+
}`
|
|
17110
|
+
}),
|
|
17111
|
+
createOperationSpec({
|
|
17112
|
+
operationName: "TestRegisteredEval",
|
|
17113
|
+
kind: "mutation",
|
|
17114
|
+
inputSchema: z25.object({
|
|
17115
|
+
input: jsonObjectSchema,
|
|
17116
|
+
slug: z25.string().min(1)
|
|
17117
|
+
}),
|
|
17118
|
+
cli: {
|
|
17119
|
+
name: "test-registered-eval",
|
|
17120
|
+
path: ["evals", "test-run"],
|
|
17121
|
+
description: "Execute one registered eval input and its scorers without persistence.",
|
|
17122
|
+
resultKey: "testRegisteredEval",
|
|
17123
|
+
options: [
|
|
17124
|
+
stringOption({
|
|
17125
|
+
description: "Registered eval slug.",
|
|
17126
|
+
flagName: "slug",
|
|
17127
|
+
inputKey: "slug",
|
|
17128
|
+
required: true
|
|
17129
|
+
}),
|
|
17130
|
+
jsonOption({
|
|
17131
|
+
description: "Concrete eval input object.",
|
|
17132
|
+
flagName: "input-json",
|
|
17133
|
+
inputKey: "input"
|
|
17134
|
+
}),
|
|
17135
|
+
stringOption({
|
|
17136
|
+
clientOnly: true,
|
|
17137
|
+
description: "Path to a JSON file containing the concrete input.",
|
|
17138
|
+
flagName: "input-file",
|
|
17139
|
+
inputKey: "inputFile"
|
|
17140
|
+
})
|
|
17141
|
+
]
|
|
17142
|
+
},
|
|
17143
|
+
mcp: { fileName: "testRegisteredEval.graphql" },
|
|
17144
|
+
scope: "global",
|
|
17145
|
+
document: `# Execute exactly one registered eval input and its scorers without persistence or automatic retries
|
|
17146
|
+
# COMPLETE and FAILED execution outcomes are returned in the result body
|
|
17147
|
+
mutation TestRegisteredEval($slug: String!, $input: JSON!) {
|
|
17148
|
+
testRegisteredEval(input: { slug: $slug, input: $input }) {
|
|
17149
|
+
status
|
|
17150
|
+
input
|
|
17151
|
+
output
|
|
17152
|
+
scores
|
|
17153
|
+
error {
|
|
17154
|
+
type
|
|
17155
|
+
message
|
|
17156
|
+
}
|
|
17090
17157
|
}
|
|
17091
|
-
|
|
17092
|
-
|
|
17093
|
-
|
|
17094
|
-
|
|
17095
|
-
|
|
17158
|
+
}`
|
|
17159
|
+
}),
|
|
17160
|
+
createOperationSpec({
|
|
17161
|
+
operationName: "PlanRegisteredEvalRun",
|
|
17162
|
+
kind: "query",
|
|
17163
|
+
inputSchema: registeredEvalRunInputSchema,
|
|
17164
|
+
cli: {
|
|
17165
|
+
name: "plan-registered-eval-run",
|
|
17166
|
+
path: ["evals", "plan-run"],
|
|
17167
|
+
description: "Validate a registered eval run and calculate its exact trial count.",
|
|
17168
|
+
resultKey: "planRegisteredEvalRun",
|
|
17169
|
+
options: [
|
|
17170
|
+
stringOption({
|
|
17171
|
+
description: "Registered eval slug.",
|
|
17172
|
+
flagName: "slug",
|
|
17173
|
+
inputKey: "slug",
|
|
17174
|
+
required: true
|
|
17175
|
+
}),
|
|
17176
|
+
jsonOption({
|
|
17177
|
+
description: "Eval input choices keyed by registered input name.",
|
|
17178
|
+
flagName: "input-json",
|
|
17179
|
+
inputKey: "input"
|
|
17180
|
+
}),
|
|
17181
|
+
stringOption({
|
|
17182
|
+
clientOnly: true,
|
|
17183
|
+
description: "Path to a JSON file containing eval input choices.",
|
|
17184
|
+
flagName: "input-file",
|
|
17185
|
+
inputKey: "inputFile"
|
|
17186
|
+
}),
|
|
17187
|
+
stringOption({
|
|
17188
|
+
description: "Optional persisted run name.",
|
|
17189
|
+
flagName: "name",
|
|
17190
|
+
inputKey: "name"
|
|
17191
|
+
}),
|
|
17192
|
+
stringOption({
|
|
17193
|
+
description: "Optional persisted run description.",
|
|
17194
|
+
flagName: "description",
|
|
17195
|
+
inputKey: "description"
|
|
17196
|
+
}),
|
|
17197
|
+
stringArrayOption({
|
|
17198
|
+
description: "Persisted run tags.",
|
|
17199
|
+
flagName: "tags",
|
|
17200
|
+
inputKey: "tags"
|
|
17201
|
+
}),
|
|
17202
|
+
numberOption({
|
|
17203
|
+
description: "Maximum simultaneously executing trials.",
|
|
17204
|
+
flagName: "max-concurrency",
|
|
17205
|
+
inputKey: "maxConcurrency"
|
|
17206
|
+
}),
|
|
17207
|
+
numberOption({
|
|
17208
|
+
description: "Number of times to repeat each input combination.",
|
|
17209
|
+
flagName: "repeat-count",
|
|
17210
|
+
inputKey: "repeatCount"
|
|
17211
|
+
})
|
|
17212
|
+
]
|
|
17213
|
+
},
|
|
17214
|
+
mcp: { fileName: "planRegisteredEvalRun.graphql" },
|
|
17215
|
+
scope: "global",
|
|
17216
|
+
document: `# Validate the complete proposed run and return the exact trial count without persistence
|
|
17217
|
+
query PlanRegisteredEvalRun(
|
|
17218
|
+
$slug: String!
|
|
17219
|
+
$input: JSON!
|
|
17220
|
+
$name: String
|
|
17221
|
+
$description: String
|
|
17222
|
+
$tags: [String!]
|
|
17223
|
+
$maxConcurrency: Int
|
|
17224
|
+
$repeatCount: Int
|
|
17225
|
+
) {
|
|
17226
|
+
planRegisteredEvalRun(
|
|
17227
|
+
input: {
|
|
17228
|
+
slug: $slug
|
|
17229
|
+
input: $input
|
|
17230
|
+
name: $name
|
|
17231
|
+
description: $description
|
|
17232
|
+
tags: $tags
|
|
17233
|
+
maxConcurrency: $maxConcurrency
|
|
17234
|
+
repeatCount: $repeatCount
|
|
17235
|
+
}
|
|
17236
|
+
) {
|
|
17237
|
+
combinationCount
|
|
17238
|
+
repeatCount
|
|
17239
|
+
trialCount
|
|
17096
17240
|
}
|
|
17097
|
-
|
|
17098
|
-
}
|
|
17099
|
-
|
|
17100
|
-
|
|
17101
|
-
|
|
17102
|
-
|
|
17103
|
-
|
|
17104
|
-
|
|
17105
|
-
|
|
17106
|
-
|
|
17107
|
-
|
|
17108
|
-
|
|
17109
|
-
|
|
17110
|
-
|
|
17111
|
-
|
|
17112
|
-
|
|
17241
|
+
}`
|
|
17242
|
+
}),
|
|
17243
|
+
createOperationSpec({
|
|
17244
|
+
operationName: "StartRegisteredEvalRun",
|
|
17245
|
+
kind: "mutation",
|
|
17246
|
+
inputSchema: registeredEvalRunInputSchema.extend({
|
|
17247
|
+
expectedTrialCount: z25.number().int().positive(),
|
|
17248
|
+
idempotencyKey: z25.string().trim().min(1)
|
|
17249
|
+
}),
|
|
17250
|
+
cli: {
|
|
17251
|
+
name: "start-registered-eval-run",
|
|
17252
|
+
path: ["evals", "run"],
|
|
17253
|
+
description: "Plan, confirm, and asynchronously start a registered eval run.",
|
|
17254
|
+
resultKey: "startRegisteredEvalRun",
|
|
17255
|
+
options: [
|
|
17256
|
+
stringOption({
|
|
17257
|
+
description: "Registered eval slug.",
|
|
17258
|
+
flagName: "slug",
|
|
17259
|
+
inputKey: "slug",
|
|
17260
|
+
required: true
|
|
17261
|
+
}),
|
|
17262
|
+
jsonOption({
|
|
17263
|
+
description: "Eval input choices keyed by registered input name.",
|
|
17264
|
+
flagName: "input-json",
|
|
17265
|
+
inputKey: "input"
|
|
17266
|
+
}),
|
|
17267
|
+
stringOption({
|
|
17268
|
+
clientOnly: true,
|
|
17269
|
+
description: "Path to a JSON file containing eval input choices.",
|
|
17270
|
+
flagName: "input-file",
|
|
17271
|
+
inputKey: "inputFile"
|
|
17272
|
+
}),
|
|
17273
|
+
stringOption({
|
|
17274
|
+
description: "Optional persisted run name.",
|
|
17275
|
+
flagName: "name",
|
|
17276
|
+
inputKey: "name"
|
|
17277
|
+
}),
|
|
17278
|
+
stringOption({
|
|
17279
|
+
description: "Optional persisted run description.",
|
|
17280
|
+
flagName: "description",
|
|
17281
|
+
inputKey: "description"
|
|
17282
|
+
}),
|
|
17283
|
+
stringArrayOption({
|
|
17284
|
+
description: "Persisted run tags.",
|
|
17285
|
+
flagName: "tags",
|
|
17286
|
+
inputKey: "tags"
|
|
17287
|
+
}),
|
|
17288
|
+
numberOption({
|
|
17289
|
+
description: "Maximum simultaneously executing trials.",
|
|
17290
|
+
flagName: "max-concurrency",
|
|
17291
|
+
inputKey: "maxConcurrency"
|
|
17292
|
+
}),
|
|
17293
|
+
numberOption({
|
|
17294
|
+
description: "Number of times to repeat each input combination.",
|
|
17295
|
+
flagName: "repeat-count",
|
|
17296
|
+
inputKey: "repeatCount"
|
|
17297
|
+
}),
|
|
17298
|
+
stringOption({
|
|
17299
|
+
description: "Idempotency key; generated by mgcl when omitted.",
|
|
17300
|
+
flagName: "idempotency-key",
|
|
17301
|
+
inputKey: "idempotencyKey"
|
|
17302
|
+
}),
|
|
17303
|
+
numberOption({
|
|
17304
|
+
clientOnly: true,
|
|
17305
|
+
description: "Explicitly acknowledge the planned trial count.",
|
|
17306
|
+
flagName: "confirm-trials",
|
|
17307
|
+
inputKey: "confirmTrials"
|
|
17308
|
+
}),
|
|
17309
|
+
booleanOption({
|
|
17310
|
+
clientOnly: true,
|
|
17311
|
+
description: "Wait until the persisted run reaches a terminal state.",
|
|
17312
|
+
flagName: "wait",
|
|
17313
|
+
inputKey: "wait"
|
|
17314
|
+
})
|
|
17315
|
+
]
|
|
17316
|
+
},
|
|
17317
|
+
mcp: { fileName: "startRegisteredEvalRun.graphql" },
|
|
17318
|
+
scope: "global",
|
|
17319
|
+
document: `# Start a registered eval run after PlanRegisteredEvalRun has returned an exact count
|
|
17320
|
+
# MCP callers must provide a unique idempotencyKey and the planned expectedTrialCount
|
|
17321
|
+
mutation StartRegisteredEvalRun(
|
|
17322
|
+
$slug: String!
|
|
17323
|
+
$input: JSON!
|
|
17324
|
+
$name: String
|
|
17325
|
+
$description: String
|
|
17326
|
+
$tags: [String!]
|
|
17327
|
+
$maxConcurrency: Int
|
|
17328
|
+
$repeatCount: Int
|
|
17329
|
+
$idempotencyKey: String!
|
|
17330
|
+
$expectedTrialCount: Int!
|
|
17331
|
+
) {
|
|
17332
|
+
startRegisteredEvalRun(
|
|
17333
|
+
input: {
|
|
17334
|
+
slug: $slug
|
|
17335
|
+
input: $input
|
|
17336
|
+
name: $name
|
|
17337
|
+
description: $description
|
|
17338
|
+
tags: $tags
|
|
17339
|
+
maxConcurrency: $maxConcurrency
|
|
17340
|
+
repeatCount: $repeatCount
|
|
17341
|
+
idempotencyKey: $idempotencyKey
|
|
17342
|
+
expectedTrialCount: $expectedTrialCount
|
|
17113
17343
|
}
|
|
17114
|
-
|
|
17344
|
+
) {
|
|
17345
|
+
idempotencyKey
|
|
17346
|
+
evalRunId
|
|
17347
|
+
workflowId
|
|
17348
|
+
workflowRunId
|
|
17115
17349
|
}
|
|
17116
|
-
|
|
17350
|
+
}`
|
|
17351
|
+
}),
|
|
17352
|
+
createOperationSpec({
|
|
17353
|
+
operationName: "ListEvalRuns",
|
|
17354
|
+
kind: "query",
|
|
17355
|
+
inputSchema: z25.object({
|
|
17356
|
+
page: z25.number().int().nonnegative().default(0),
|
|
17357
|
+
pageSize: z25.number().int().min(1).max(100).default(20),
|
|
17358
|
+
slug: z25.string().min(1).optional(),
|
|
17359
|
+
status: evalRunStatusSchema.optional()
|
|
17360
|
+
}),
|
|
17361
|
+
cli: {
|
|
17362
|
+
name: "list-eval-runs",
|
|
17363
|
+
path: ["evals", "runs", "list"],
|
|
17364
|
+
description: "List persisted eval runs with optional filters.",
|
|
17365
|
+
resultKey: "evalRuns",
|
|
17366
|
+
options: [
|
|
17367
|
+
stringOption({
|
|
17368
|
+
description: "Filter by registered eval slug.",
|
|
17369
|
+
flagName: "slug",
|
|
17370
|
+
inputKey: "slug"
|
|
17371
|
+
}),
|
|
17372
|
+
stringOption({
|
|
17373
|
+
description: "Filter by eval run status.",
|
|
17374
|
+
flagName: "status",
|
|
17375
|
+
inputKey: "status"
|
|
17376
|
+
}),
|
|
17377
|
+
numberOption({
|
|
17378
|
+
description: "Zero-based page number.",
|
|
17379
|
+
flagName: "page",
|
|
17380
|
+
inputKey: "page"
|
|
17381
|
+
}),
|
|
17382
|
+
numberOption({
|
|
17383
|
+
description: "Page size from 1 to 100.",
|
|
17384
|
+
flagName: "page-size",
|
|
17385
|
+
inputKey: "pageSize"
|
|
17386
|
+
})
|
|
17387
|
+
]
|
|
17388
|
+
},
|
|
17389
|
+
mcp: { fileName: "evalRuns.graphql" },
|
|
17390
|
+
scope: "global",
|
|
17391
|
+
document: `# List globally persisted eval runs with status counts and offset pagination
|
|
17392
|
+
query ListEvalRuns(
|
|
17393
|
+
$slug: String
|
|
17394
|
+
$status: EvalRunStatus
|
|
17395
|
+
$page: Int
|
|
17396
|
+
$pageSize: Int
|
|
17397
|
+
) {
|
|
17398
|
+
evalRuns(slug: $slug, status: $status, page: $page, pageSize: $pageSize) {
|
|
17399
|
+
items {
|
|
17400
|
+
${evalRunSelection}
|
|
17401
|
+
}
|
|
17402
|
+
total
|
|
17403
|
+
page
|
|
17404
|
+
pageSize
|
|
17405
|
+
}
|
|
17406
|
+
}`
|
|
17407
|
+
}),
|
|
17408
|
+
createOperationSpec({
|
|
17409
|
+
operationName: "GetEvalRun",
|
|
17410
|
+
kind: "query",
|
|
17411
|
+
inputSchema: z25.object({ id: z25.string().min(1) }),
|
|
17412
|
+
cli: {
|
|
17413
|
+
name: "get-eval-run",
|
|
17414
|
+
path: ["evals", "runs", "get"],
|
|
17415
|
+
description: "Get one persisted eval run with current status counts.",
|
|
17416
|
+
resultKey: "evalRun",
|
|
17417
|
+
options: [
|
|
17418
|
+
stringOption({
|
|
17419
|
+
description: "Eval run ID.",
|
|
17420
|
+
flagName: "id",
|
|
17421
|
+
inputKey: "id",
|
|
17422
|
+
required: true
|
|
17423
|
+
})
|
|
17424
|
+
]
|
|
17425
|
+
},
|
|
17426
|
+
mcp: { fileName: "evalRun.graphql" },
|
|
17427
|
+
scope: "global",
|
|
17428
|
+
document: `# Get one globally persisted eval run by ID
|
|
17429
|
+
query GetEvalRun($id: String!) {
|
|
17430
|
+
evalRun(id: $id) {
|
|
17431
|
+
${evalRunSelection}
|
|
17432
|
+
}
|
|
17433
|
+
}`
|
|
17434
|
+
}),
|
|
17435
|
+
createOperationSpec({
|
|
17436
|
+
operationName: "AwaitEvalRun",
|
|
17437
|
+
kind: "query",
|
|
17438
|
+
inputSchema: z25.object({
|
|
17439
|
+
id: z25.string().min(1),
|
|
17440
|
+
timeoutMs: z25.number().int().min(1e3).max(6e4).default(3e4)
|
|
17441
|
+
}),
|
|
17442
|
+
cli: {
|
|
17443
|
+
name: "await-eval-run",
|
|
17444
|
+
path: ["evals", "runs", "await"],
|
|
17445
|
+
description: "Wait for an eval run by repeating bounded server long-polls.",
|
|
17446
|
+
resultKey: "evalRunAwait",
|
|
17447
|
+
options: [
|
|
17448
|
+
stringOption({
|
|
17449
|
+
description: "Eval run ID.",
|
|
17450
|
+
flagName: "id",
|
|
17451
|
+
inputKey: "id",
|
|
17452
|
+
required: true
|
|
17453
|
+
}),
|
|
17454
|
+
stringOption({
|
|
17455
|
+
clientOnly: true,
|
|
17456
|
+
description: "Overall client wait timeout.",
|
|
17457
|
+
flagName: "timeout",
|
|
17458
|
+
inputKey: "timeout",
|
|
17459
|
+
valueHint: "duration, for example 30s or 5m"
|
|
17460
|
+
})
|
|
17461
|
+
]
|
|
17462
|
+
},
|
|
17463
|
+
mcp: { fileName: "evalRunAwait.graphql" },
|
|
17464
|
+
scope: "global",
|
|
17465
|
+
document: `# Wait up to 60 seconds for an eval run to reach COMPLETE, FAILED, or CANCELLED
|
|
17466
|
+
# Call again when reachedTerminal is false and a longer overall wait is needed
|
|
17467
|
+
query AwaitEvalRun($id: String!, $timeoutMs: Int) {
|
|
17468
|
+
evalRunAwait(id: $id, timeoutMs: $timeoutMs) {
|
|
17469
|
+
reachedTerminal
|
|
17470
|
+
pollCount
|
|
17471
|
+
elapsedMs
|
|
17472
|
+
evalRun {
|
|
17473
|
+
${evalRunSelection}
|
|
17474
|
+
}
|
|
17475
|
+
}
|
|
17476
|
+
}`
|
|
17477
|
+
}),
|
|
17478
|
+
createOperationSpec({
|
|
17479
|
+
operationName: "ListEvalRunTrials",
|
|
17480
|
+
kind: "query",
|
|
17481
|
+
inputSchema: z25.object({
|
|
17482
|
+
cursor: z25.string().min(1).optional(),
|
|
17483
|
+
id: z25.string().min(1),
|
|
17484
|
+
limit: z25.number().int().min(1).max(1e3).default(100)
|
|
17485
|
+
}),
|
|
17486
|
+
cli: {
|
|
17487
|
+
name: "list-eval-run-trials",
|
|
17488
|
+
path: ["evals", "runs", "trials"],
|
|
17489
|
+
description: "List eval trials in deterministic cursor order.",
|
|
17490
|
+
resultKey: "evalRunTrials",
|
|
17491
|
+
options: [
|
|
17492
|
+
stringOption({
|
|
17493
|
+
description: "Eval run ID.",
|
|
17494
|
+
flagName: "id",
|
|
17495
|
+
inputKey: "id",
|
|
17496
|
+
required: true
|
|
17497
|
+
}),
|
|
17498
|
+
numberOption({
|
|
17499
|
+
description: "Maximum trials to return, from 1 to 1000.",
|
|
17500
|
+
flagName: "limit",
|
|
17501
|
+
inputKey: "limit"
|
|
17502
|
+
}),
|
|
17503
|
+
stringOption({
|
|
17504
|
+
description: "Opaque cursor returned by the previous page.",
|
|
17505
|
+
flagName: "cursor",
|
|
17506
|
+
inputKey: "cursor"
|
|
17507
|
+
})
|
|
17508
|
+
]
|
|
17509
|
+
},
|
|
17510
|
+
mcp: { fileName: "evalRunTrials.graphql" },
|
|
17511
|
+
scope: "global",
|
|
17512
|
+
document: `# List eval trials in ascending deterministic order with an opaque continuation cursor
|
|
17513
|
+
query ListEvalRunTrials($id: String!, $limit: Int, $cursor: String) {
|
|
17514
|
+
evalRunTrials(id: $id, limit: $limit, cursor: $cursor) {
|
|
17515
|
+
trials {
|
|
17516
|
+
id
|
|
17517
|
+
createdAt
|
|
17518
|
+
updatedAt
|
|
17519
|
+
evalRunId
|
|
17520
|
+
repeatIndex
|
|
17521
|
+
input
|
|
17522
|
+
status
|
|
17523
|
+
startedAt
|
|
17524
|
+
finishedAt
|
|
17525
|
+
scores
|
|
17526
|
+
output
|
|
17527
|
+
workflowId
|
|
17528
|
+
workflowRunId
|
|
17529
|
+
}
|
|
17530
|
+
nextCursor
|
|
17531
|
+
}
|
|
17532
|
+
}`
|
|
17533
|
+
}),
|
|
17534
|
+
createOperationSpec({
|
|
17535
|
+
operationName: "CancelEvalRun",
|
|
17536
|
+
kind: "mutation",
|
|
17537
|
+
inputSchema: z25.object({ id: z25.string().min(1) }),
|
|
17538
|
+
cli: {
|
|
17539
|
+
name: "cancel-eval-run",
|
|
17540
|
+
path: ["evals", "runs", "cancel"],
|
|
17541
|
+
description: "Request cancellation for a queued or running eval run.",
|
|
17542
|
+
resultKey: "cancelEvalRun",
|
|
17543
|
+
options: [
|
|
17544
|
+
stringOption({
|
|
17545
|
+
description: "Eval run ID.",
|
|
17546
|
+
flagName: "id",
|
|
17547
|
+
inputKey: "id",
|
|
17548
|
+
required: true
|
|
17549
|
+
})
|
|
17550
|
+
]
|
|
17551
|
+
},
|
|
17552
|
+
mcp: { fileName: "cancelEvalRun.graphql" },
|
|
17553
|
+
scope: "global",
|
|
17554
|
+
document: `# Request cancellation without claiming the run has already reached CANCELLED
|
|
17555
|
+
mutation CancelEvalRun($id: String!) {
|
|
17556
|
+
cancelEvalRun(id: $id) {
|
|
17557
|
+
evalRunId
|
|
17558
|
+
cancellationRequested
|
|
17559
|
+
status
|
|
17560
|
+
}
|
|
17561
|
+
}`
|
|
17562
|
+
}),
|
|
17563
|
+
createOperationSpec({
|
|
17564
|
+
operationName: "RequestEvalRunExport",
|
|
17565
|
+
kind: "mutation",
|
|
17566
|
+
inputSchema: z25.object({ id: z25.string().min(1) }),
|
|
17567
|
+
cli: {
|
|
17568
|
+
name: "request-eval-run-export",
|
|
17569
|
+
path: ["evals", "runs", "export"],
|
|
17570
|
+
description: "Request an asynchronous raw-results export.",
|
|
17571
|
+
resultKey: "requestEvalRunExport",
|
|
17572
|
+
options: [
|
|
17573
|
+
stringOption({
|
|
17574
|
+
description: "Eval run ID.",
|
|
17575
|
+
flagName: "id",
|
|
17576
|
+
inputKey: "id",
|
|
17577
|
+
required: true
|
|
17578
|
+
}),
|
|
17579
|
+
stringOption({
|
|
17580
|
+
clientOnly: true,
|
|
17581
|
+
description: "Destination path for the completed export.",
|
|
17582
|
+
flagName: "output",
|
|
17583
|
+
inputKey: "output",
|
|
17584
|
+
required: true
|
|
17585
|
+
}),
|
|
17586
|
+
booleanOption({
|
|
17587
|
+
clientOnly: true,
|
|
17588
|
+
description: "Wait for export completion and download the file.",
|
|
17589
|
+
flagName: "wait",
|
|
17590
|
+
inputKey: "wait"
|
|
17591
|
+
}),
|
|
17592
|
+
booleanOption({
|
|
17593
|
+
clientOnly: true,
|
|
17594
|
+
description: "Authorize replacement of an existing output file.",
|
|
17595
|
+
flagName: "force",
|
|
17596
|
+
inputKey: "force"
|
|
17597
|
+
})
|
|
17598
|
+
]
|
|
17599
|
+
},
|
|
17600
|
+
mcp: { fileName: "requestEvalRunExport.graphql" },
|
|
17601
|
+
scope: "global",
|
|
17602
|
+
document: `# Request or reuse an asynchronous raw-results export for a terminal eval run
|
|
17603
|
+
mutation RequestEvalRunExport($id: String!) {
|
|
17604
|
+
requestEvalRunExport(id: $id) {
|
|
17605
|
+
${evalRunExportSelection}
|
|
17606
|
+
}
|
|
17607
|
+
}`
|
|
17608
|
+
}),
|
|
17609
|
+
createOperationSpec({
|
|
17610
|
+
operationName: "GetEvalRunExport",
|
|
17611
|
+
kind: "query",
|
|
17612
|
+
inputSchema: z25.object({ exportId: z25.string().min(1) }),
|
|
17613
|
+
cli: {
|
|
17614
|
+
hidden: true,
|
|
17615
|
+
name: "get-eval-run-export",
|
|
17616
|
+
path: ["evals", "runs", "export-status"],
|
|
17617
|
+
description: "Get asynchronous eval export status by export ID.",
|
|
17618
|
+
resultKey: "evalRunExport",
|
|
17619
|
+
options: [
|
|
17620
|
+
stringOption({
|
|
17621
|
+
description: "Eval export ID.",
|
|
17622
|
+
flagName: "export-id",
|
|
17623
|
+
inputKey: "exportId",
|
|
17624
|
+
required: true
|
|
17625
|
+
})
|
|
17626
|
+
]
|
|
17627
|
+
},
|
|
17628
|
+
mcp: { fileName: "evalRunExport.graphql" },
|
|
17629
|
+
scope: "global",
|
|
17630
|
+
document: `# Get asynchronous eval export status; downloadUrl is signed and only present when COMPLETE
|
|
17631
|
+
query GetEvalRunExport($exportId: String!) {
|
|
17632
|
+
evalRunExport(exportId: $exportId) {
|
|
17633
|
+
${evalRunExportSelection}
|
|
17634
|
+
}
|
|
17635
|
+
}`
|
|
17636
|
+
})
|
|
17637
|
+
];
|
|
17638
|
+
|
|
17639
|
+
// src/program.ts
|
|
17640
|
+
import { Command as Command2, InvalidArgumentError as InvalidArgumentError2, Option as Option2 } from "commander";
|
|
17641
|
+
|
|
17642
|
+
// src/api.ts
|
|
17643
|
+
import { randomUUID } from "node:crypto";
|
|
17644
|
+
import { createWriteStream } from "node:fs";
|
|
17645
|
+
import { access, link, rename, rm } from "node:fs/promises";
|
|
17646
|
+
import nodePath from "node:path";
|
|
17647
|
+
import { Readable } from "node:stream";
|
|
17648
|
+
import { pipeline } from "node:stream/promises";
|
|
17649
|
+
import { z as z26 } from "zod";
|
|
17650
|
+
|
|
17651
|
+
// src/version.ts
|
|
17652
|
+
import fs from "node:fs";
|
|
17653
|
+
import path from "node:path";
|
|
17654
|
+
import { fileURLToPath } from "node:url";
|
|
17655
|
+
var packageManifestPath = path.resolve(
|
|
17656
|
+
path.dirname(fileURLToPath(import.meta.url)),
|
|
17657
|
+
"../package.json"
|
|
17658
|
+
);
|
|
17659
|
+
var packageManifestResult = safeJsonParse(
|
|
17660
|
+
fs.readFileSync(packageManifestPath, "utf8")
|
|
17661
|
+
);
|
|
17662
|
+
if (isErr(packageManifestResult)) {
|
|
17663
|
+
throw new Error(`Failed to parse ${packageManifestPath}.`, {
|
|
17664
|
+
cause: packageManifestResult.error.cause
|
|
17665
|
+
});
|
|
17666
|
+
}
|
|
17667
|
+
var cliPackageVersion = packageManifestResult.value.version;
|
|
17668
|
+
if (typeof cliPackageVersion !== "string" || cliPackageVersion.length === 0) {
|
|
17669
|
+
throw new Error(`Expected a version in ${packageManifestPath}.`);
|
|
17670
|
+
}
|
|
17671
|
+
var CLI_VERSION = cliPackageVersion;
|
|
17672
|
+
|
|
17673
|
+
// src/api.ts
|
|
17674
|
+
var OTTO_AUTHORIZATION_HEADER_NAME = "X-Otto-Authorization";
|
|
17675
|
+
var OTTO_AUTHORIZATION_ISSUER = "magical:otto";
|
|
17676
|
+
var workosOrganizationsResponseSchema = z26.object({
|
|
17677
|
+
organizations: z26.array(
|
|
17678
|
+
z26.object({
|
|
17679
|
+
id: z26.string().min(1),
|
|
17680
|
+
name: z26.string().min(1),
|
|
17681
|
+
primaryDomain: z26.string().nullable().optional()
|
|
17682
|
+
})
|
|
17683
|
+
),
|
|
17684
|
+
success: z26.boolean()
|
|
17685
|
+
});
|
|
17686
|
+
var workosUserSchema = z26.object({
|
|
17687
|
+
email: z26.string().nullable(),
|
|
17688
|
+
id: z26.string().min(1)
|
|
17689
|
+
});
|
|
17690
|
+
var nangoIntegrationWireSchema = z26.object({
|
|
17691
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention -- mirrors Nango REST payload
|
|
17692
|
+
unique_key: z26.string().min(1)
|
|
17693
|
+
}).passthrough().transform((data) => ({
|
|
17694
|
+
...data,
|
|
17695
|
+
uniqueKey: data.unique_key
|
|
17696
|
+
}));
|
|
17697
|
+
var nangoIntegrationsResponseSchema = z26.array(nangoIntegrationWireSchema);
|
|
17698
|
+
var organizationAuthenticationSchema = z26.object({
|
|
17699
|
+
id: z26.string().min(1),
|
|
17700
|
+
type: z26.string().min(1),
|
|
17701
|
+
connectionId: z26.string().nullable().optional(),
|
|
17702
|
+
providerConfigKey: z26.string().nullable().optional(),
|
|
17703
|
+
description: z26.string().nullable().optional(),
|
|
17704
|
+
hostname: z26.string().nullable().optional()
|
|
17705
|
+
}).passthrough();
|
|
17706
|
+
var organizationAuthenticationsResponseSchema = z26.object({
|
|
17707
|
+
authentications: z26.array(organizationAuthenticationSchema),
|
|
17708
|
+
success: z26.boolean()
|
|
17709
|
+
});
|
|
17710
|
+
var graphQlResponseSchema = z26.object({
|
|
17711
|
+
data: z26.record(z26.string(), z26.unknown()).nullable().optional(),
|
|
17712
|
+
errors: z26.array(
|
|
17713
|
+
z26.object({
|
|
17714
|
+
extensions: z26.object({
|
|
17715
|
+
code: z26.string().min(1).optional()
|
|
17716
|
+
}).passthrough().optional(),
|
|
17717
|
+
message: z26.string().min(1)
|
|
17718
|
+
})
|
|
17719
|
+
).optional()
|
|
17720
|
+
});
|
|
17721
|
+
var apiErrorResponseSchema = z26.object({
|
|
17722
|
+
errors: z26.array(
|
|
17723
|
+
z26.object({
|
|
17724
|
+
message: z26.string().min(1)
|
|
17725
|
+
})
|
|
17726
|
+
).optional(),
|
|
17727
|
+
message: z26.string().min(1).optional()
|
|
17728
|
+
});
|
|
17729
|
+
function getApiErrorDetail(responseBody) {
|
|
17730
|
+
const parsedResponse = apiErrorResponseSchema.safeParse(responseBody);
|
|
17731
|
+
if (!parsedResponse.success) {
|
|
17732
|
+
return null;
|
|
17733
|
+
}
|
|
17734
|
+
if (parsedResponse.data.message) {
|
|
17735
|
+
return parsedResponse.data.message;
|
|
17736
|
+
}
|
|
17737
|
+
if (!parsedResponse.data.errors || parsedResponse.data.errors.length === 0) {
|
|
17738
|
+
return null;
|
|
17739
|
+
}
|
|
17740
|
+
return parsedResponse.data.errors.map((error) => error.message).join("\n");
|
|
17741
|
+
}
|
|
17742
|
+
var DEFINITIVE_GRAPHQL_APPLICATION_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
17743
|
+
"BAD_REQUEST",
|
|
17744
|
+
"BAD_USER_INPUT",
|
|
17745
|
+
"FORBIDDEN",
|
|
17746
|
+
"GRAPHQL_PARSE_FAILED",
|
|
17747
|
+
"GRAPHQL_VALIDATION_FAILED",
|
|
17748
|
+
"NOT_FOUND",
|
|
17749
|
+
"OPERATION_RESOLUTION_FAILURE",
|
|
17750
|
+
"PERSISTED_QUERY_NOT_FOUND",
|
|
17751
|
+
"PERSISTED_QUERY_NOT_SUPPORTED",
|
|
17752
|
+
"UNAUTHORIZED"
|
|
17753
|
+
]);
|
|
17754
|
+
var GraphQlResponseError = class extends CliError {
|
|
17755
|
+
graphQlCodes;
|
|
17756
|
+
hasUnclassifiedGraphQlErrors;
|
|
17757
|
+
constructor(message, {
|
|
17758
|
+
graphQlCodes,
|
|
17759
|
+
hasUnclassifiedGraphQlErrors = false
|
|
17760
|
+
}) {
|
|
17761
|
+
super(message);
|
|
17762
|
+
this.name = "GraphQlResponseError";
|
|
17763
|
+
this.graphQlCodes = [...graphQlCodes];
|
|
17764
|
+
this.hasUnclassifiedGraphQlErrors = hasUnclassifiedGraphQlErrors;
|
|
17765
|
+
}
|
|
17766
|
+
};
|
|
17767
|
+
function isDefinitiveGraphQlApplicationError(error) {
|
|
17768
|
+
return error instanceof GraphQlResponseError && !error.hasUnclassifiedGraphQlErrors && error.graphQlCodes.length > 0 && error.graphQlCodes.every(
|
|
17769
|
+
(code) => DEFINITIVE_GRAPHQL_APPLICATION_ERROR_CODES.has(code)
|
|
17770
|
+
);
|
|
17771
|
+
}
|
|
17772
|
+
function trimTrailingSlash(value) {
|
|
17773
|
+
return value.replace(/\/+$/u, "");
|
|
17774
|
+
}
|
|
17775
|
+
function isFileAlreadyExistsError(error) {
|
|
17776
|
+
return error instanceof Error && "code" in error && error.code === "EEXIST";
|
|
17777
|
+
}
|
|
17778
|
+
async function assertOutputDoesNotExist(outputPath) {
|
|
17779
|
+
const outputExists = await access(outputPath).then(() => true).catch((error) => {
|
|
17780
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
17781
|
+
return false;
|
|
17782
|
+
}
|
|
17783
|
+
throw new CliError(`Failed to inspect export path "${outputPath}".`, {
|
|
17784
|
+
cause: error
|
|
17785
|
+
});
|
|
17786
|
+
});
|
|
17787
|
+
if (outputExists) {
|
|
17788
|
+
throw new CliError(
|
|
17789
|
+
`Refusing to overwrite existing file "${outputPath}". Pass --force to authorize replacement.`
|
|
17790
|
+
);
|
|
17791
|
+
}
|
|
17792
|
+
}
|
|
17793
|
+
function isRecord4(value) {
|
|
17794
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17795
|
+
}
|
|
17796
|
+
function decodeJwtPayload(token) {
|
|
17797
|
+
const [, payloadSegment] = token.split(".");
|
|
17798
|
+
if (!payloadSegment) {
|
|
17799
|
+
return null;
|
|
17800
|
+
}
|
|
17801
|
+
const payloadResult = safeJsonParse(
|
|
17802
|
+
Buffer.from(payloadSegment, "base64url").toString("utf8")
|
|
17803
|
+
);
|
|
17804
|
+
if (isErr(payloadResult)) {
|
|
17805
|
+
return null;
|
|
17806
|
+
}
|
|
17807
|
+
return isRecord4(payloadResult.value) ? payloadResult.value : null;
|
|
17808
|
+
}
|
|
17809
|
+
function isOttoAuthorizationToken(token) {
|
|
17810
|
+
return decodeJwtPayload(token)?.["iss"] === OTTO_AUTHORIZATION_ISSUER;
|
|
17811
|
+
}
|
|
17812
|
+
function applyAuthenticationHeaders({
|
|
17813
|
+
accessToken,
|
|
17814
|
+
allowOttoAuthorization,
|
|
17815
|
+
headers,
|
|
17816
|
+
impersonatedOrganizationId,
|
|
17817
|
+
organizationId
|
|
17818
|
+
}) {
|
|
17819
|
+
if (!isOttoAuthorizationToken(accessToken)) {
|
|
17820
|
+
headers.set("authorization", `Bearer ${accessToken}`);
|
|
17821
|
+
if (impersonatedOrganizationId) {
|
|
17822
|
+
headers.set("x-organization-id", impersonatedOrganizationId);
|
|
17823
|
+
}
|
|
17824
|
+
return;
|
|
17825
|
+
}
|
|
17826
|
+
if (!allowOttoAuthorization) {
|
|
17117
17827
|
throw new CliError(
|
|
17118
17828
|
"Otto authorization is only supported for GraphQL requests."
|
|
17119
17829
|
);
|
|
@@ -17133,11 +17843,11 @@ function createMagicalApiClient({
|
|
|
17133
17843
|
accessToken,
|
|
17134
17844
|
impersonatedOrganizationId,
|
|
17135
17845
|
allowOttoAuthorization,
|
|
17136
|
-
path:
|
|
17846
|
+
path: path9,
|
|
17137
17847
|
init,
|
|
17138
17848
|
organizationId
|
|
17139
17849
|
}) {
|
|
17140
|
-
const url = `${trimTrailingSlash(await resolveApiBaseUrl())}${
|
|
17850
|
+
const url = `${trimTrailingSlash(await resolveApiBaseUrl())}${path9}`;
|
|
17141
17851
|
const headers = new Headers(init?.headers);
|
|
17142
17852
|
applyAuthenticationHeaders({
|
|
17143
17853
|
accessToken,
|
|
@@ -17182,6 +17892,51 @@ function createMagicalApiClient({
|
|
|
17182
17892
|
return responseBody;
|
|
17183
17893
|
}
|
|
17184
17894
|
return {
|
|
17895
|
+
async downloadFile({ outputPath, overwrite = false, url }) {
|
|
17896
|
+
if (!overwrite) {
|
|
17897
|
+
await assertOutputDoesNotExist(outputPath);
|
|
17898
|
+
}
|
|
17899
|
+
const temporaryPath = nodePath.join(
|
|
17900
|
+
nodePath.dirname(outputPath),
|
|
17901
|
+
`.${nodePath.basename(outputPath)}.${randomUUID()}.tmp`
|
|
17902
|
+
);
|
|
17903
|
+
await (async () => {
|
|
17904
|
+
const response = await fetchFn(url).catch((error) => {
|
|
17905
|
+
throw new CliError("Failed to download eval export.", {
|
|
17906
|
+
cause: error
|
|
17907
|
+
});
|
|
17908
|
+
});
|
|
17909
|
+
if (!response.ok) {
|
|
17910
|
+
throw new CliError(
|
|
17911
|
+
`Eval export download failed with status ${response.status}.`
|
|
17912
|
+
);
|
|
17913
|
+
}
|
|
17914
|
+
if (!response.body) {
|
|
17915
|
+
throw new CliError("Eval export download returned an empty body.");
|
|
17916
|
+
}
|
|
17917
|
+
await pipeline(
|
|
17918
|
+
Readable.fromWeb(response.body),
|
|
17919
|
+
createWriteStream(temporaryPath, { flags: "wx" })
|
|
17920
|
+
);
|
|
17921
|
+
if (overwrite) {
|
|
17922
|
+
await rename(temporaryPath, outputPath);
|
|
17923
|
+
return;
|
|
17924
|
+
}
|
|
17925
|
+
await link(temporaryPath, outputPath).catch((error) => {
|
|
17926
|
+
if (isFileAlreadyExistsError(error)) {
|
|
17927
|
+
throw new CliError(
|
|
17928
|
+
`Refusing to overwrite existing file "${outputPath}". Pass --force to authorize replacement.`,
|
|
17929
|
+
{ cause: error }
|
|
17930
|
+
);
|
|
17931
|
+
}
|
|
17932
|
+
throw error;
|
|
17933
|
+
});
|
|
17934
|
+
await rm(temporaryPath, { force: true });
|
|
17935
|
+
})().catch(async (error) => {
|
|
17936
|
+
await rm(temporaryPath, { force: true });
|
|
17937
|
+
throw error;
|
|
17938
|
+
});
|
|
17939
|
+
},
|
|
17185
17940
|
async executeGraphQl({
|
|
17186
17941
|
accessToken,
|
|
17187
17942
|
impersonatedOrganizationId,
|
|
@@ -17213,8 +17968,15 @@ function createMagicalApiClient({
|
|
|
17213
17968
|
throw new CliError("GraphQL response payload was invalid.");
|
|
17214
17969
|
}
|
|
17215
17970
|
if (parsedResponse.data.errors && parsedResponse.data.errors.length > 0) {
|
|
17216
|
-
|
|
17217
|
-
|
|
17971
|
+
const graphQlCodes = parsedResponse.data.errors.flatMap(
|
|
17972
|
+
(error) => error.extensions?.code ? [error.extensions.code] : []
|
|
17973
|
+
);
|
|
17974
|
+
throw new GraphQlResponseError(
|
|
17975
|
+
parsedResponse.data.errors.map((error) => error.message).join("\n"),
|
|
17976
|
+
{
|
|
17977
|
+
graphQlCodes,
|
|
17978
|
+
hasUnclassifiedGraphQlErrors: graphQlCodes.length !== parsedResponse.data.errors.length
|
|
17979
|
+
}
|
|
17218
17980
|
);
|
|
17219
17981
|
}
|
|
17220
17982
|
return parsedResponse.data.data?.[resultKey] ?? null;
|
|
@@ -17372,7 +18134,7 @@ function requireWorkosClientId(config) {
|
|
|
17372
18134
|
}
|
|
17373
18135
|
|
|
17374
18136
|
// src/settings.ts
|
|
17375
|
-
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
18137
|
+
import { mkdir, readFile, rm as rm2, writeFile } from "node:fs/promises";
|
|
17376
18138
|
import path3 from "node:path";
|
|
17377
18139
|
import { z as z27 } from "zod";
|
|
17378
18140
|
var cliSettingsSchema = z27.object({
|
|
@@ -17431,7 +18193,7 @@ function createFileSettingsStore(stateFilePath) {
|
|
|
17431
18193
|
},
|
|
17432
18194
|
async save(settings) {
|
|
17433
18195
|
if (!hasCliSettingsOverrides(settings)) {
|
|
17434
|
-
await
|
|
18196
|
+
await rm2(settingsFilePath, { force: true });
|
|
17435
18197
|
return;
|
|
17436
18198
|
}
|
|
17437
18199
|
await mkdir(path3.dirname(settingsFilePath), { recursive: true });
|
|
@@ -17520,6 +18282,7 @@ var rootOperationalGroupDescriptions = /* @__PURE__ */ new Map([
|
|
|
17520
18282
|
["automations", "Manage automations."],
|
|
17521
18283
|
["automation-runs", "Inspect and control automation runs."],
|
|
17522
18284
|
["catalog", "Inspect available commands, models, and tools."],
|
|
18285
|
+
["evals", "Discover registered evals and manage eval runs."],
|
|
17523
18286
|
["graphql", "Inspect GraphQL metadata."],
|
|
17524
18287
|
["skills", "Inspect and update root-level Workplace skills."]
|
|
17525
18288
|
]);
|
|
@@ -17549,11 +18312,498 @@ function createOperationHelpExamples(operationSpec) {
|
|
|
17549
18312
|
const baseInvocation = [baseCommand, ...requiredOptions].join(" ");
|
|
17550
18313
|
return [
|
|
17551
18314
|
baseInvocation,
|
|
17552
|
-
`${baseInvocation} --org <org
|
|
18315
|
+
...operationSpec.scope === "global" ? [] : [`${baseInvocation} --org <org>`],
|
|
17553
18316
|
`${baseInvocation} --json`
|
|
17554
18317
|
];
|
|
17555
18318
|
}
|
|
17556
18319
|
|
|
18320
|
+
// src/eval-commands.ts
|
|
18321
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
18322
|
+
import { access as access2, readFile as readFile2 } from "node:fs/promises";
|
|
18323
|
+
import path4 from "node:path";
|
|
18324
|
+
import { createInterface } from "node:readline/promises";
|
|
18325
|
+
import { z as z28 } from "zod";
|
|
18326
|
+
var MAX_AWAIT_REQUEST_MS = 6e4;
|
|
18327
|
+
var MIN_AWAIT_REQUEST_MS = 1e3;
|
|
18328
|
+
var EXPORT_POLL_INTERVAL_MS = 1e3;
|
|
18329
|
+
var evalRunStatusSchema2 = z28.enum([
|
|
18330
|
+
"QUEUED",
|
|
18331
|
+
"RUNNING",
|
|
18332
|
+
"COMPLETE",
|
|
18333
|
+
"FAILED",
|
|
18334
|
+
"CANCELLED"
|
|
18335
|
+
]);
|
|
18336
|
+
var awaitResultSchema = z28.object({
|
|
18337
|
+
elapsedMs: z28.number().nonnegative(),
|
|
18338
|
+
evalRun: z28.object({
|
|
18339
|
+
id: z28.string().min(1),
|
|
18340
|
+
status: evalRunStatusSchema2
|
|
18341
|
+
}).passthrough(),
|
|
18342
|
+
pollCount: z28.number().int().nonnegative(),
|
|
18343
|
+
reachedTerminal: z28.boolean()
|
|
18344
|
+
}).passthrough();
|
|
18345
|
+
var planResultSchema = z28.object({ trialCount: z28.number().int().nonnegative() }).passthrough();
|
|
18346
|
+
var startResultSchema = z28.object({
|
|
18347
|
+
evalRunId: z28.string().min(1),
|
|
18348
|
+
idempotencyKey: z28.string().min(1),
|
|
18349
|
+
workflowId: z28.string().min(1),
|
|
18350
|
+
workflowRunId: z28.string().min(1)
|
|
18351
|
+
}).passthrough();
|
|
18352
|
+
var exportResultSchema = z28.object({
|
|
18353
|
+
downloadUrl: z28.string().min(1).nullable().optional(),
|
|
18354
|
+
evalRunId: z28.string().min(1),
|
|
18355
|
+
exportId: z28.string().min(1),
|
|
18356
|
+
status: z28.enum(["QUEUED", "RUNNING", "COMPLETE", "FAILED"])
|
|
18357
|
+
}).passthrough();
|
|
18358
|
+
var inputOptionsSchema = z28.object({
|
|
18359
|
+
inputFile: z28.string().min(1).optional(),
|
|
18360
|
+
inputJson: z28.unknown().optional()
|
|
18361
|
+
});
|
|
18362
|
+
var commonRunOptionsSchema = inputOptionsSchema.extend({
|
|
18363
|
+
description: z28.string().min(1).optional(),
|
|
18364
|
+
maxConcurrency: z28.number().int().positive().optional(),
|
|
18365
|
+
name: z28.string().min(1).optional(),
|
|
18366
|
+
repeatCount: z28.number().int().positive().optional(),
|
|
18367
|
+
slug: z28.string().min(1),
|
|
18368
|
+
tags: z28.array(z28.string().min(1)).optional()
|
|
18369
|
+
});
|
|
18370
|
+
function parseApiResult(value, schema, label) {
|
|
18371
|
+
const parsedResult = schema.safeParse(value);
|
|
18372
|
+
if (!parsedResult.success) {
|
|
18373
|
+
throw new CliError(`${label} returned an invalid response.`);
|
|
18374
|
+
}
|
|
18375
|
+
return parsedResult.data;
|
|
18376
|
+
}
|
|
18377
|
+
async function parseInputFile({
|
|
18378
|
+
inputFile,
|
|
18379
|
+
workingDirectory
|
|
18380
|
+
}) {
|
|
18381
|
+
const inputPath = path4.resolve(workingDirectory, inputFile);
|
|
18382
|
+
const contents = await readFile2(inputPath, "utf8").catch(
|
|
18383
|
+
(error) => {
|
|
18384
|
+
throw new CliError(`Failed to read eval input file "${inputPath}".`, {
|
|
18385
|
+
cause: error
|
|
18386
|
+
});
|
|
18387
|
+
}
|
|
18388
|
+
);
|
|
18389
|
+
const parsedJson = safeJsonParseWithoutLogging(contents);
|
|
18390
|
+
if (isErr(parsedJson)) {
|
|
18391
|
+
throw new CliError(
|
|
18392
|
+
`Eval input file "${inputPath}" must contain valid JSON.`,
|
|
18393
|
+
{ cause: parsedJson.error }
|
|
18394
|
+
);
|
|
18395
|
+
}
|
|
18396
|
+
return parsedJson.value;
|
|
18397
|
+
}
|
|
18398
|
+
async function resolveEvalInput({
|
|
18399
|
+
inputFile,
|
|
18400
|
+
inputJson,
|
|
18401
|
+
workingDirectory
|
|
18402
|
+
}) {
|
|
18403
|
+
const inputSourceCount = Number(inputFile !== void 0) + Number(inputJson !== void 0);
|
|
18404
|
+
if (inputSourceCount !== 1) {
|
|
18405
|
+
throw new CliError(
|
|
18406
|
+
"Pass exactly one of --input-file or --input-json for eval input."
|
|
18407
|
+
);
|
|
18408
|
+
}
|
|
18409
|
+
const input = inputFile === void 0 ? inputJson : await parseInputFile({ inputFile, workingDirectory });
|
|
18410
|
+
const parsedInput = z28.record(z28.string(), z28.unknown()).safeParse(input);
|
|
18411
|
+
if (!parsedInput.success) {
|
|
18412
|
+
throw new CliError("Eval input must be a JSON object.");
|
|
18413
|
+
}
|
|
18414
|
+
return parsedInput.data;
|
|
18415
|
+
}
|
|
18416
|
+
async function resolveEvalInputFromOptions({
|
|
18417
|
+
inputFile,
|
|
18418
|
+
inputJson,
|
|
18419
|
+
workingDirectory
|
|
18420
|
+
}) {
|
|
18421
|
+
return await resolveEvalInput({
|
|
18422
|
+
...inputFile === void 0 ? {} : { inputFile },
|
|
18423
|
+
...inputJson === void 0 ? {} : { inputJson },
|
|
18424
|
+
workingDirectory
|
|
18425
|
+
});
|
|
18426
|
+
}
|
|
18427
|
+
function buildCommonRunVariables({
|
|
18428
|
+
input,
|
|
18429
|
+
options
|
|
18430
|
+
}) {
|
|
18431
|
+
return {
|
|
18432
|
+
input,
|
|
18433
|
+
slug: options.slug,
|
|
18434
|
+
...options.description === void 0 ? {} : { description: options.description },
|
|
18435
|
+
...options.maxConcurrency === void 0 ? {} : { maxConcurrency: options.maxConcurrency },
|
|
18436
|
+
...options.name === void 0 ? {} : { name: options.name },
|
|
18437
|
+
...options.repeatCount === void 0 ? {} : { repeatCount: options.repeatCount },
|
|
18438
|
+
...options.tags === void 0 ? {} : { tags: options.tags }
|
|
18439
|
+
};
|
|
18440
|
+
}
|
|
18441
|
+
function parseDurationMs(value) {
|
|
18442
|
+
const match = /^(?<amount>\d+(?:\.\d+)?)(?<unit>ms|s|m|h)$/iu.exec(
|
|
18443
|
+
value.trim()
|
|
18444
|
+
);
|
|
18445
|
+
const amount = Number(match?.groups?.["amount"]);
|
|
18446
|
+
const multiplierByUnit = { h: 36e5, m: 6e4, ms: 1, s: 1e3 };
|
|
18447
|
+
const parsedUnit = z28.enum(["h", "m", "ms", "s"]).safeParse(match?.groups?.["unit"]?.toLowerCase());
|
|
18448
|
+
const durationMs = parsedUnit.success ? amount * multiplierByUnit[parsedUnit.data] : Number.NaN;
|
|
18449
|
+
if (!Number.isSafeInteger(durationMs) || durationMs < MIN_AWAIT_REQUEST_MS) {
|
|
18450
|
+
throw new CliError(
|
|
18451
|
+
"Expected --timeout to be a duration of at least 1s, such as 30s, 5m, or 1h."
|
|
18452
|
+
);
|
|
18453
|
+
}
|
|
18454
|
+
return durationMs;
|
|
18455
|
+
}
|
|
18456
|
+
function quotePosixShellArgument(value) {
|
|
18457
|
+
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
18458
|
+
}
|
|
18459
|
+
async function defaultConfirm(question) {
|
|
18460
|
+
const prompt = createInterface({
|
|
18461
|
+
input: process.stdin,
|
|
18462
|
+
output: process.stdout
|
|
18463
|
+
});
|
|
18464
|
+
const answer = await prompt.question(`${question} [y/N] `).finally(() => {
|
|
18465
|
+
prompt.close();
|
|
18466
|
+
});
|
|
18467
|
+
return answer.trim().toLowerCase() === "y" || answer.trim().toLowerCase() === "yes";
|
|
18468
|
+
}
|
|
18469
|
+
function terminalExitError(result) {
|
|
18470
|
+
const { id, status } = result.evalRun;
|
|
18471
|
+
if (status === "FAILED" || status === "CANCELLED") {
|
|
18472
|
+
return new CliError(`Eval run "${id}" finished with status ${status}.`);
|
|
18473
|
+
}
|
|
18474
|
+
return void 0;
|
|
18475
|
+
}
|
|
18476
|
+
async function awaitEvalRun({
|
|
18477
|
+
evalRunId,
|
|
18478
|
+
executeOperation,
|
|
18479
|
+
now: now2,
|
|
18480
|
+
timeoutMs
|
|
18481
|
+
}) {
|
|
18482
|
+
const deadline = timeoutMs === void 0 ? void 0 : now2() + timeoutMs;
|
|
18483
|
+
let previousResult = void 0;
|
|
18484
|
+
for (; ; ) {
|
|
18485
|
+
const remainingMs = deadline === void 0 ? void 0 : deadline - now2();
|
|
18486
|
+
if (remainingMs !== void 0 && remainingMs < MIN_AWAIT_REQUEST_MS) {
|
|
18487
|
+
return {
|
|
18488
|
+
exitError: new CliError(
|
|
18489
|
+
`Timed out waiting for eval run "${evalRunId}".`
|
|
18490
|
+
),
|
|
18491
|
+
result: previousResult ?? {
|
|
18492
|
+
elapsedMs: timeoutMs ?? 0,
|
|
18493
|
+
evalRun: { id: evalRunId, status: "QUEUED" },
|
|
18494
|
+
pollCount: 0,
|
|
18495
|
+
reachedTerminal: false
|
|
18496
|
+
}
|
|
18497
|
+
};
|
|
18498
|
+
}
|
|
18499
|
+
const requestTimeoutMs = Math.min(
|
|
18500
|
+
MAX_AWAIT_REQUEST_MS,
|
|
18501
|
+
remainingMs ?? MAX_AWAIT_REQUEST_MS
|
|
18502
|
+
);
|
|
18503
|
+
const result = parseApiResult(
|
|
18504
|
+
// eslint-disable-next-line no-await-in-loop -- each long-poll must finish before the next bounded request begins
|
|
18505
|
+
await executeOperation("AwaitEvalRun", {
|
|
18506
|
+
id: evalRunId,
|
|
18507
|
+
timeoutMs: requestTimeoutMs
|
|
18508
|
+
}),
|
|
18509
|
+
awaitResultSchema,
|
|
18510
|
+
"Eval run await"
|
|
18511
|
+
);
|
|
18512
|
+
if (result.reachedTerminal) {
|
|
18513
|
+
const exitError = terminalExitError(result);
|
|
18514
|
+
return { ...exitError ? { exitError } : {}, result };
|
|
18515
|
+
}
|
|
18516
|
+
previousResult = result;
|
|
18517
|
+
}
|
|
18518
|
+
}
|
|
18519
|
+
async function assertExportOutputAvailable({
|
|
18520
|
+
force,
|
|
18521
|
+
outputPath
|
|
18522
|
+
}) {
|
|
18523
|
+
if (force) {
|
|
18524
|
+
return;
|
|
18525
|
+
}
|
|
18526
|
+
const exists = await access2(outputPath).then(() => true).catch((error) => {
|
|
18527
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
18528
|
+
return false;
|
|
18529
|
+
}
|
|
18530
|
+
throw new CliError(`Failed to inspect export path "${outputPath}".`, {
|
|
18531
|
+
cause: error
|
|
18532
|
+
});
|
|
18533
|
+
});
|
|
18534
|
+
if (exists) {
|
|
18535
|
+
throw new CliError(
|
|
18536
|
+
`Refusing to overwrite existing file "${outputPath}". Pass --force to authorize replacement.`
|
|
18537
|
+
);
|
|
18538
|
+
}
|
|
18539
|
+
}
|
|
18540
|
+
async function finishExport({
|
|
18541
|
+
downloadFile,
|
|
18542
|
+
exportResult,
|
|
18543
|
+
force,
|
|
18544
|
+
outputPath
|
|
18545
|
+
}) {
|
|
18546
|
+
if (exportResult.status === "FAILED") {
|
|
18547
|
+
return {
|
|
18548
|
+
exitError: new CliError(`Eval export "${exportResult.exportId}" failed.`),
|
|
18549
|
+
result: exportResult
|
|
18550
|
+
};
|
|
18551
|
+
}
|
|
18552
|
+
if (exportResult.status !== "COMPLETE") {
|
|
18553
|
+
return { result: exportResult };
|
|
18554
|
+
}
|
|
18555
|
+
if (!exportResult.downloadUrl) {
|
|
18556
|
+
throw new CliError(
|
|
18557
|
+
`Completed eval export "${exportResult.exportId}" did not include a download URL.`
|
|
18558
|
+
);
|
|
18559
|
+
}
|
|
18560
|
+
if (!downloadFile) {
|
|
18561
|
+
throw new CliError("Eval export download is not configured.");
|
|
18562
|
+
}
|
|
18563
|
+
await downloadFile({
|
|
18564
|
+
outputPath,
|
|
18565
|
+
overwrite: force,
|
|
18566
|
+
url: exportResult.downloadUrl
|
|
18567
|
+
});
|
|
18568
|
+
const { downloadUrl: _downloadUrl, ...downloadedExport } = exportResult;
|
|
18569
|
+
return { result: { ...downloadedExport, outputPath } };
|
|
18570
|
+
}
|
|
18571
|
+
async function pollExport({
|
|
18572
|
+
executeOperation,
|
|
18573
|
+
exportId,
|
|
18574
|
+
sleep
|
|
18575
|
+
}) {
|
|
18576
|
+
for (; ; ) {
|
|
18577
|
+
await sleep(EXPORT_POLL_INTERVAL_MS);
|
|
18578
|
+
const result = parseApiResult(
|
|
18579
|
+
// eslint-disable-next-line no-await-in-loop -- do not overlap signed-export status requests
|
|
18580
|
+
await executeOperation("GetEvalRunExport", { exportId }),
|
|
18581
|
+
exportResultSchema,
|
|
18582
|
+
"Eval export status"
|
|
18583
|
+
);
|
|
18584
|
+
if (result.status !== "QUEUED" && result.status !== "RUNNING") {
|
|
18585
|
+
return result;
|
|
18586
|
+
}
|
|
18587
|
+
}
|
|
18588
|
+
}
|
|
18589
|
+
async function executeTestRegisteredEval({
|
|
18590
|
+
executeOperation,
|
|
18591
|
+
options,
|
|
18592
|
+
workingDirectory
|
|
18593
|
+
}) {
|
|
18594
|
+
const parsedOptions = commonRunOptionsSchema.pick({ slug: true }).merge(inputOptionsSchema).parse(options);
|
|
18595
|
+
const input = await resolveEvalInputFromOptions({
|
|
18596
|
+
...parsedOptions,
|
|
18597
|
+
workingDirectory
|
|
18598
|
+
});
|
|
18599
|
+
return {
|
|
18600
|
+
result: await executeOperation("TestRegisteredEval", {
|
|
18601
|
+
input,
|
|
18602
|
+
slug: parsedOptions.slug
|
|
18603
|
+
})
|
|
18604
|
+
};
|
|
18605
|
+
}
|
|
18606
|
+
async function executePlanRegisteredEvalRun({
|
|
18607
|
+
executeOperation,
|
|
18608
|
+
options,
|
|
18609
|
+
workingDirectory
|
|
18610
|
+
}) {
|
|
18611
|
+
const parsedOptions = commonRunOptionsSchema.parse(options);
|
|
18612
|
+
const input = await resolveEvalInputFromOptions({
|
|
18613
|
+
...parsedOptions,
|
|
18614
|
+
workingDirectory
|
|
18615
|
+
});
|
|
18616
|
+
return {
|
|
18617
|
+
result: await executeOperation(
|
|
18618
|
+
"PlanRegisteredEvalRun",
|
|
18619
|
+
buildCommonRunVariables({ input, options: parsedOptions })
|
|
18620
|
+
)
|
|
18621
|
+
};
|
|
18622
|
+
}
|
|
18623
|
+
async function confirmPlannedTrialCount({
|
|
18624
|
+
confirm,
|
|
18625
|
+
confirmedTrialCount,
|
|
18626
|
+
isInteractive,
|
|
18627
|
+
json,
|
|
18628
|
+
trialCount
|
|
18629
|
+
}) {
|
|
18630
|
+
if (confirmedTrialCount !== void 0) {
|
|
18631
|
+
if (confirmedTrialCount !== trialCount) {
|
|
18632
|
+
throw new CliError(
|
|
18633
|
+
`Planned ${trialCount} trials, but --confirm-trials was ${confirmedTrialCount}.`
|
|
18634
|
+
);
|
|
18635
|
+
}
|
|
18636
|
+
return;
|
|
18637
|
+
}
|
|
18638
|
+
if (json || !isInteractive) {
|
|
18639
|
+
throw new CliError(
|
|
18640
|
+
`This run will start ${trialCount} trials. Pass --confirm-trials ${trialCount} in non-interactive mode.`
|
|
18641
|
+
);
|
|
18642
|
+
}
|
|
18643
|
+
const confirmed = await confirm(`Start ${trialCount} eval trials?`);
|
|
18644
|
+
if (confirmed) {
|
|
18645
|
+
return;
|
|
18646
|
+
}
|
|
18647
|
+
throw new CliError("Eval run cancelled before starting.");
|
|
18648
|
+
}
|
|
18649
|
+
async function executeStartRegisteredEvalRun({
|
|
18650
|
+
executeOperation,
|
|
18651
|
+
options,
|
|
18652
|
+
runtime,
|
|
18653
|
+
workingDirectory
|
|
18654
|
+
}) {
|
|
18655
|
+
const parsedOptions = commonRunOptionsSchema.extend({
|
|
18656
|
+
confirmTrials: z28.number().int().positive().optional(),
|
|
18657
|
+
idempotencyKey: z28.string().trim().min(1).optional(),
|
|
18658
|
+
json: z28.boolean().optional(),
|
|
18659
|
+
wait: z28.boolean().optional()
|
|
18660
|
+
}).parse(options);
|
|
18661
|
+
const input = await resolveEvalInputFromOptions({
|
|
18662
|
+
...parsedOptions,
|
|
18663
|
+
workingDirectory
|
|
18664
|
+
});
|
|
18665
|
+
const commonVariables = buildCommonRunVariables({
|
|
18666
|
+
input,
|
|
18667
|
+
options: parsedOptions
|
|
18668
|
+
});
|
|
18669
|
+
const plan = parseApiResult(
|
|
18670
|
+
await executeOperation("PlanRegisteredEvalRun", commonVariables),
|
|
18671
|
+
planResultSchema,
|
|
18672
|
+
"Eval run plan"
|
|
18673
|
+
);
|
|
18674
|
+
await confirmPlannedTrialCount({
|
|
18675
|
+
confirm: runtime.confirm ?? defaultConfirm,
|
|
18676
|
+
...parsedOptions.confirmTrials === void 0 ? {} : { confirmedTrialCount: parsedOptions.confirmTrials },
|
|
18677
|
+
isInteractive: runtime.isInteractive?.() ?? (process.stdin.isTTY && process.stdout.isTTY),
|
|
18678
|
+
json: parsedOptions.json === true,
|
|
18679
|
+
trialCount: plan.trialCount
|
|
18680
|
+
});
|
|
18681
|
+
const idempotencyKey = parsedOptions.idempotencyKey ?? `mgcl-eval-${(runtime.randomUuid ?? randomUUID2)()}`;
|
|
18682
|
+
const start = await executeOperation("StartRegisteredEvalRun", {
|
|
18683
|
+
...commonVariables,
|
|
18684
|
+
expectedTrialCount: plan.trialCount,
|
|
18685
|
+
idempotencyKey
|
|
18686
|
+
}).catch((error) => {
|
|
18687
|
+
if (isDefinitiveGraphQlApplicationError(error)) {
|
|
18688
|
+
throw error;
|
|
18689
|
+
}
|
|
18690
|
+
throw new CliError(
|
|
18691
|
+
`${getErrorMessage(error)}
|
|
18692
|
+
If execution was accepted, retry with --idempotency-key ${quotePosixShellArgument(idempotencyKey)} to resolve the request safely.`,
|
|
18693
|
+
{ cause: error }
|
|
18694
|
+
);
|
|
18695
|
+
});
|
|
18696
|
+
const parsedStart = parseApiResult(
|
|
18697
|
+
start,
|
|
18698
|
+
startResultSchema,
|
|
18699
|
+
"Eval run start"
|
|
18700
|
+
);
|
|
18701
|
+
if (parsedOptions.wait !== true) {
|
|
18702
|
+
return { result: parsedStart };
|
|
18703
|
+
}
|
|
18704
|
+
const awaited = await awaitEvalRun({
|
|
18705
|
+
evalRunId: parsedStart.evalRunId,
|
|
18706
|
+
executeOperation,
|
|
18707
|
+
now: runtime.now ?? Date.now
|
|
18708
|
+
});
|
|
18709
|
+
return {
|
|
18710
|
+
...awaited.exitError ? { exitError: awaited.exitError } : {},
|
|
18711
|
+
result: { ...parsedStart, await: awaited.result }
|
|
18712
|
+
};
|
|
18713
|
+
}
|
|
18714
|
+
async function executeAwaitEvalRun({
|
|
18715
|
+
executeOperation,
|
|
18716
|
+
options,
|
|
18717
|
+
runtime
|
|
18718
|
+
}) {
|
|
18719
|
+
const parsedOptions = z28.object({ id: z28.string().min(1), timeout: z28.string().optional() }).parse(options);
|
|
18720
|
+
return await awaitEvalRun({
|
|
18721
|
+
evalRunId: parsedOptions.id,
|
|
18722
|
+
executeOperation,
|
|
18723
|
+
now: runtime.now ?? Date.now,
|
|
18724
|
+
...parsedOptions.timeout ? { timeoutMs: parseDurationMs(parsedOptions.timeout) } : {}
|
|
18725
|
+
});
|
|
18726
|
+
}
|
|
18727
|
+
async function defaultSleep(milliseconds) {
|
|
18728
|
+
await new Promise((resolve) => {
|
|
18729
|
+
setTimeout(resolve, milliseconds);
|
|
18730
|
+
});
|
|
18731
|
+
}
|
|
18732
|
+
async function executeRequestEvalRunExport({
|
|
18733
|
+
executeOperation,
|
|
18734
|
+
options,
|
|
18735
|
+
runtime,
|
|
18736
|
+
workingDirectory
|
|
18737
|
+
}) {
|
|
18738
|
+
const parsedOptions = z28.object({
|
|
18739
|
+
force: z28.boolean().optional(),
|
|
18740
|
+
id: z28.string().min(1),
|
|
18741
|
+
output: z28.string().min(1),
|
|
18742
|
+
wait: z28.boolean().optional()
|
|
18743
|
+
}).parse(options);
|
|
18744
|
+
const outputPath = path4.resolve(workingDirectory, parsedOptions.output);
|
|
18745
|
+
const force = parsedOptions.force === true;
|
|
18746
|
+
const shouldWait = parsedOptions.wait === true;
|
|
18747
|
+
if (shouldWait) {
|
|
18748
|
+
await assertExportOutputAvailable({ force, outputPath });
|
|
18749
|
+
}
|
|
18750
|
+
const requestedExport = parseApiResult(
|
|
18751
|
+
await executeOperation("RequestEvalRunExport", { id: parsedOptions.id }),
|
|
18752
|
+
exportResultSchema,
|
|
18753
|
+
"Eval export request"
|
|
18754
|
+
);
|
|
18755
|
+
if (!shouldWait) {
|
|
18756
|
+
return { result: requestedExport };
|
|
18757
|
+
}
|
|
18758
|
+
const exportResult = requestedExport.status === "QUEUED" || requestedExport.status === "RUNNING" ? await pollExport({
|
|
18759
|
+
executeOperation,
|
|
18760
|
+
exportId: requestedExport.exportId,
|
|
18761
|
+
sleep: runtime.sleep ?? defaultSleep
|
|
18762
|
+
}) : requestedExport;
|
|
18763
|
+
if (exportResult.status === "QUEUED" || exportResult.status === "RUNNING") {
|
|
18764
|
+
return { result: exportResult };
|
|
18765
|
+
}
|
|
18766
|
+
return await finishExport({
|
|
18767
|
+
...runtime.downloadFile ? { downloadFile: runtime.downloadFile } : {},
|
|
18768
|
+
exportResult,
|
|
18769
|
+
force,
|
|
18770
|
+
outputPath
|
|
18771
|
+
});
|
|
18772
|
+
}
|
|
18773
|
+
async function executeEvalCliOperation({
|
|
18774
|
+
executeOperation,
|
|
18775
|
+
operationName,
|
|
18776
|
+
options,
|
|
18777
|
+
runtime = {}
|
|
18778
|
+
}) {
|
|
18779
|
+
const handlerInput = {
|
|
18780
|
+
executeOperation,
|
|
18781
|
+
options,
|
|
18782
|
+
runtime,
|
|
18783
|
+
workingDirectory: runtime.workingDirectory ?? process.cwd()
|
|
18784
|
+
};
|
|
18785
|
+
switch (operationName) {
|
|
18786
|
+
case "TestRegisteredEval": {
|
|
18787
|
+
return await executeTestRegisteredEval(handlerInput);
|
|
18788
|
+
}
|
|
18789
|
+
case "PlanRegisteredEvalRun": {
|
|
18790
|
+
return await executePlanRegisteredEvalRun(handlerInput);
|
|
18791
|
+
}
|
|
18792
|
+
case "StartRegisteredEvalRun": {
|
|
18793
|
+
return await executeStartRegisteredEvalRun(handlerInput);
|
|
18794
|
+
}
|
|
18795
|
+
case "AwaitEvalRun": {
|
|
18796
|
+
return await executeAwaitEvalRun(handlerInput);
|
|
18797
|
+
}
|
|
18798
|
+
case "RequestEvalRunExport": {
|
|
18799
|
+
return await executeRequestEvalRunExport(handlerInput);
|
|
18800
|
+
}
|
|
18801
|
+
default: {
|
|
18802
|
+
return null;
|
|
18803
|
+
}
|
|
18804
|
+
}
|
|
18805
|
+
}
|
|
18806
|
+
|
|
17557
18807
|
// src/keychain.ts
|
|
17558
18808
|
function buildKeychainAccountName(account) {
|
|
17559
18809
|
return `${account.clientId}:${account.userId}`;
|
|
@@ -17620,7 +18870,7 @@ function resolveOpenCommand(url) {
|
|
|
17620
18870
|
}
|
|
17621
18871
|
|
|
17622
18872
|
// src/program-session.ts
|
|
17623
|
-
import { readFile as
|
|
18873
|
+
import { readFile as readFile3, rm as rm3 } from "node:fs/promises";
|
|
17624
18874
|
async function withOrgScopedAccessToken({
|
|
17625
18875
|
dependencies,
|
|
17626
18876
|
organizationId,
|
|
@@ -17633,6 +18883,35 @@ async function withOrgScopedAccessToken({
|
|
|
17633
18883
|
if (directAccessToken) {
|
|
17634
18884
|
return { accessToken: directAccessToken };
|
|
17635
18885
|
}
|
|
18886
|
+
return await refreshAccessToken({
|
|
18887
|
+
dependencies,
|
|
18888
|
+
organizationId,
|
|
18889
|
+
state
|
|
18890
|
+
});
|
|
18891
|
+
}
|
|
18892
|
+
async function withGlobalAccessToken({
|
|
18893
|
+
authenticationOrganizationId,
|
|
18894
|
+
dependencies,
|
|
18895
|
+
state
|
|
18896
|
+
}) {
|
|
18897
|
+
const directAccessToken = await loadDirectAccessToken({
|
|
18898
|
+
dependencies,
|
|
18899
|
+
organizationId: authenticationOrganizationId
|
|
18900
|
+
});
|
|
18901
|
+
if (directAccessToken) {
|
|
18902
|
+
return { accessToken: directAccessToken };
|
|
18903
|
+
}
|
|
18904
|
+
return await refreshAccessToken({
|
|
18905
|
+
dependencies,
|
|
18906
|
+
organizationId: authenticationOrganizationId,
|
|
18907
|
+
state
|
|
18908
|
+
});
|
|
18909
|
+
}
|
|
18910
|
+
async function refreshAccessToken({
|
|
18911
|
+
dependencies,
|
|
18912
|
+
organizationId,
|
|
18913
|
+
state
|
|
18914
|
+
}) {
|
|
17636
18915
|
const refreshToken = await dependencies.refreshTokenStore.load(state.account);
|
|
17637
18916
|
if (!refreshToken) {
|
|
17638
18917
|
throw new CliError(
|
|
@@ -17664,7 +18943,7 @@ async function clearDirectAccessToken(runtimeConfig) {
|
|
|
17664
18943
|
if (!runtimeConfig.accessTokenFilePath) {
|
|
17665
18944
|
return;
|
|
17666
18945
|
}
|
|
17667
|
-
await
|
|
18946
|
+
await rm3(runtimeConfig.accessTokenFilePath, { force: true });
|
|
17668
18947
|
}
|
|
17669
18948
|
async function loadDirectAccessToken({
|
|
17670
18949
|
dependencies,
|
|
@@ -17674,7 +18953,7 @@ async function loadDirectAccessToken({
|
|
|
17674
18953
|
if (!accessTokenFilePath) {
|
|
17675
18954
|
return null;
|
|
17676
18955
|
}
|
|
17677
|
-
const accessTokenFileContents = await
|
|
18956
|
+
const accessTokenFileContents = await readFile3(accessTokenFilePath, "utf8").then((value) => value.trim()).catch((error) => {
|
|
17678
18957
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
17679
18958
|
return null;
|
|
17680
18959
|
}
|
|
@@ -17701,7 +18980,7 @@ async function loadDirectAccessToken({
|
|
|
17701
18980
|
}
|
|
17702
18981
|
return null;
|
|
17703
18982
|
}
|
|
17704
|
-
if (claims.org_id && claims.org_id !== organizationId) {
|
|
18983
|
+
if (organizationId !== void 0 && claims.org_id && claims.org_id !== organizationId) {
|
|
17705
18984
|
throw new CliError(
|
|
17706
18985
|
`The current Otto session is authenticated for organization "${claims.org_id}", not "${organizationId}". Start a new Otto session from the desired organization.`
|
|
17707
18986
|
);
|
|
@@ -17718,7 +18997,7 @@ function isExpiredAccessTokenClaims(claims) {
|
|
|
17718
18997
|
// src/self-update.ts
|
|
17719
18998
|
import { spawn as spawn2 } from "node:child_process";
|
|
17720
18999
|
import fs2 from "node:fs";
|
|
17721
|
-
import
|
|
19000
|
+
import path5 from "node:path";
|
|
17722
19001
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
17723
19002
|
var CLI_PACKAGE_NAME = "@getmagical/cli";
|
|
17724
19003
|
var DEFAULT_CLI_DIST_TAG2 = "latest";
|
|
@@ -17729,9 +19008,9 @@ function resolveInstalledPackageRoot({
|
|
|
17729
19008
|
packageName
|
|
17730
19009
|
}) {
|
|
17731
19010
|
const packagePathSegments = packageName.split("/");
|
|
17732
|
-
let currentPath =
|
|
19011
|
+
let currentPath = path5.dirname(entryFilePath);
|
|
17733
19012
|
for (; ; ) {
|
|
17734
|
-
const currentPathSegments = currentPath.split(
|
|
19013
|
+
const currentPathSegments = currentPath.split(path5.sep).filter(Boolean);
|
|
17735
19014
|
const currentPackageSegments = currentPathSegments.slice(
|
|
17736
19015
|
-packagePathSegments.length
|
|
17737
19016
|
);
|
|
@@ -17740,7 +19019,7 @@ function resolveInstalledPackageRoot({
|
|
|
17740
19019
|
)) {
|
|
17741
19020
|
return currentPath;
|
|
17742
19021
|
}
|
|
17743
|
-
const parentPath =
|
|
19022
|
+
const parentPath = path5.dirname(currentPath);
|
|
17744
19023
|
if (parentPath === currentPath) {
|
|
17745
19024
|
return null;
|
|
17746
19025
|
}
|
|
@@ -17750,14 +19029,14 @@ function resolveInstalledPackageRoot({
|
|
|
17750
19029
|
function resolveInstallPrefixFromPackageRoot(packageRootPath) {
|
|
17751
19030
|
let currentPath = packageRootPath;
|
|
17752
19031
|
for (; ; ) {
|
|
17753
|
-
if (
|
|
17754
|
-
const nodeModulesParentPath =
|
|
17755
|
-
if (
|
|
17756
|
-
return
|
|
19032
|
+
if (path5.basename(currentPath) === "node_modules") {
|
|
19033
|
+
const nodeModulesParentPath = path5.dirname(currentPath);
|
|
19034
|
+
if (path5.basename(nodeModulesParentPath) === "lib") {
|
|
19035
|
+
return path5.dirname(nodeModulesParentPath);
|
|
17757
19036
|
}
|
|
17758
19037
|
return nodeModulesParentPath;
|
|
17759
19038
|
}
|
|
17760
|
-
const parentPath =
|
|
19039
|
+
const parentPath = path5.dirname(currentPath);
|
|
17761
19040
|
if (parentPath === currentPath) {
|
|
17762
19041
|
return null;
|
|
17763
19042
|
}
|
|
@@ -17774,13 +19053,13 @@ function resolveManagedNpmCommand(installPrefix) {
|
|
|
17774
19053
|
if (process.platform === "win32") {
|
|
17775
19054
|
return null;
|
|
17776
19055
|
}
|
|
17777
|
-
const managedNodeExecutable =
|
|
19056
|
+
const managedNodeExecutable = path5.join(
|
|
17778
19057
|
installPrefix,
|
|
17779
19058
|
MANAGED_NODE_SUBPATH,
|
|
17780
19059
|
"bin",
|
|
17781
19060
|
"node"
|
|
17782
19061
|
);
|
|
17783
|
-
const managedNpmCli =
|
|
19062
|
+
const managedNpmCli = path5.join(
|
|
17784
19063
|
installPrefix,
|
|
17785
19064
|
MANAGED_NODE_SUBPATH,
|
|
17786
19065
|
"lib",
|
|
@@ -17979,20 +19258,20 @@ ${formatExamples("Examples", [
|
|
|
17979
19258
|
|
|
17980
19259
|
// src/skills-working-copy.ts
|
|
17981
19260
|
import { execFile } from "node:child_process";
|
|
17982
|
-
import { createHash, randomUUID } from "node:crypto";
|
|
19261
|
+
import { createHash, randomUUID as randomUUID3 } from "node:crypto";
|
|
17983
19262
|
import {
|
|
17984
19263
|
lstat,
|
|
17985
19264
|
mkdir as mkdir2,
|
|
17986
19265
|
mkdtemp,
|
|
17987
|
-
readFile as
|
|
19266
|
+
readFile as readFile4,
|
|
17988
19267
|
readdir,
|
|
17989
|
-
rename,
|
|
17990
|
-
rm as
|
|
19268
|
+
rename as rename2,
|
|
19269
|
+
rm as rm4,
|
|
17991
19270
|
writeFile as writeFile2
|
|
17992
19271
|
} from "node:fs/promises";
|
|
17993
19272
|
import os2 from "node:os";
|
|
17994
|
-
import
|
|
17995
|
-
import { z as
|
|
19273
|
+
import path6 from "node:path";
|
|
19274
|
+
import { z as z29 } from "zod";
|
|
17996
19275
|
var SKILLS_ROOT_PATH = "skills";
|
|
17997
19276
|
var METADATA_DIRECTORY_NAME = "skill-working-copies";
|
|
17998
19277
|
var MAX_GIT_OUTPUT_BYTES = 10 * 1024 * 1024;
|
|
@@ -18001,40 +19280,40 @@ var FULL_COMMIT_SHA_PATTERN = /^[\dA-Fa-f]{40}$/u;
|
|
|
18001
19280
|
var UTF8_ENCODER = new TextEncoder();
|
|
18002
19281
|
var WINDOWS_RESERVED_PATH_CHARACTER_PATTERN = /[<>:"|?*]/u;
|
|
18003
19282
|
var WINDOWS_RESERVED_PATH_NAME_PATTERN = /^(?:AUX|CON|NUL|PRN|COM[1-9]|LPT[1-9])(?:\..*)?$/iu;
|
|
18004
|
-
var skillBundleSchema =
|
|
18005
|
-
files:
|
|
18006
|
-
|
|
18007
|
-
content:
|
|
18008
|
-
encoding:
|
|
18009
|
-
path:
|
|
18010
|
-
size:
|
|
19283
|
+
var skillBundleSchema = z29.object({
|
|
19284
|
+
files: z29.array(
|
|
19285
|
+
z29.object({
|
|
19286
|
+
content: z29.string(),
|
|
19287
|
+
encoding: z29.literal("base64"),
|
|
19288
|
+
path: z29.string().min(1),
|
|
19289
|
+
size: z29.number().int().nonnegative()
|
|
18011
19290
|
})
|
|
18012
19291
|
),
|
|
18013
|
-
path:
|
|
18014
|
-
ref:
|
|
19292
|
+
path: z29.string().min(1),
|
|
19293
|
+
ref: z29.string().regex(FULL_COMMIT_SHA_PATTERN)
|
|
18015
19294
|
});
|
|
18016
|
-
var skillsApplyPatchResultSchema =
|
|
18017
|
-
changedFiles:
|
|
18018
|
-
|
|
19295
|
+
var skillsApplyPatchResultSchema = z29.object({
|
|
19296
|
+
changedFiles: z29.array(
|
|
19297
|
+
z29.object({ path: z29.string().min(1), status: z29.string().min(1) })
|
|
18019
19298
|
),
|
|
18020
|
-
commit:
|
|
18021
|
-
ok:
|
|
18022
|
-
ref:
|
|
19299
|
+
commit: z29.string().regex(FULL_COMMIT_SHA_PATTERN),
|
|
19300
|
+
ok: z29.boolean(),
|
|
19301
|
+
ref: z29.string().min(1)
|
|
18023
19302
|
}).refine((result) => result.ok, {
|
|
18024
19303
|
message: "Skills patch result was not successful."
|
|
18025
19304
|
});
|
|
18026
|
-
var workingCopyMetadataSchema =
|
|
18027
|
-
version:
|
|
18028
|
-
files:
|
|
18029
|
-
|
|
18030
|
-
content:
|
|
18031
|
-
path:
|
|
19305
|
+
var workingCopyMetadataSchema = z29.object({
|
|
19306
|
+
version: z29.literal(1),
|
|
19307
|
+
files: z29.array(
|
|
19308
|
+
z29.object({
|
|
19309
|
+
content: z29.string(),
|
|
19310
|
+
path: z29.string().min(1)
|
|
18032
19311
|
})
|
|
18033
19312
|
),
|
|
18034
|
-
organizationId:
|
|
18035
|
-
requestedRef:
|
|
18036
|
-
skillPath:
|
|
18037
|
-
workingCopyPath:
|
|
19313
|
+
organizationId: z29.string().min(1),
|
|
19314
|
+
requestedRef: z29.string().min(1).nullable(),
|
|
19315
|
+
skillPath: z29.string().min(1),
|
|
19316
|
+
workingCopyPath: z29.string().min(1)
|
|
18038
19317
|
});
|
|
18039
19318
|
function hasControlCharacter2(value) {
|
|
18040
19319
|
return UTF8_ENCODER.encode(value).some((byte) => byte <= 31 || byte === 127);
|
|
@@ -18062,12 +19341,12 @@ function normalizeRootSkillPath(skill) {
|
|
|
18062
19341
|
return `${SKILLS_ROOT_PATH}/${skillName}`;
|
|
18063
19342
|
}
|
|
18064
19343
|
function resolveWorkingCopyPath(workingDirectory, skillPath) {
|
|
18065
|
-
return
|
|
19344
|
+
return path6.resolve(workingDirectory, ...skillPath.split("/"));
|
|
18066
19345
|
}
|
|
18067
19346
|
function resolveMetadataPath(stateFilePath, workingCopyPath) {
|
|
18068
19347
|
const key = createHash("sha256").update(workingCopyPath).digest("hex");
|
|
18069
|
-
return
|
|
18070
|
-
|
|
19348
|
+
return path6.join(
|
|
19349
|
+
path6.dirname(stateFilePath),
|
|
18071
19350
|
METADATA_DIRECTORY_NAME,
|
|
18072
19351
|
`${key}.json`
|
|
18073
19352
|
);
|
|
@@ -18095,7 +19374,7 @@ function metadataFilesToSnapshot(files) {
|
|
|
18095
19374
|
);
|
|
18096
19375
|
}
|
|
18097
19376
|
async function loadMetadata(metadataPath) {
|
|
18098
|
-
const fileContents = await
|
|
19377
|
+
const fileContents = await readFile4(metadataPath, "utf8").catch(
|
|
18099
19378
|
(error) => {
|
|
18100
19379
|
if (isMissingFileError(error)) {
|
|
18101
19380
|
return null;
|
|
@@ -18119,13 +19398,13 @@ async function loadMetadata(metadataPath) {
|
|
|
18119
19398
|
return parsed.data;
|
|
18120
19399
|
}
|
|
18121
19400
|
async function saveMetadata(metadataPath, metadata) {
|
|
18122
|
-
await mkdir2(
|
|
18123
|
-
const temporaryPath = `${metadataPath}.${
|
|
19401
|
+
await mkdir2(path6.dirname(metadataPath), { recursive: true });
|
|
19402
|
+
const temporaryPath = `${metadataPath}.${randomUUID3()}.tmp`;
|
|
18124
19403
|
await writeFile2(temporaryPath, `${JSON.stringify(metadata, null, 2)}
|
|
18125
19404
|
`, {
|
|
18126
19405
|
mode: 384
|
|
18127
19406
|
});
|
|
18128
|
-
await
|
|
19407
|
+
await rename2(temporaryPath, metadataPath);
|
|
18129
19408
|
}
|
|
18130
19409
|
function assertSafeRelativeFilePath(relativePath) {
|
|
18131
19410
|
const segments = relativePath.split("/");
|
|
@@ -18196,7 +19475,7 @@ async function readDirectorySnapshot({
|
|
|
18196
19475
|
const nextSegments = [...segments, entry.name];
|
|
18197
19476
|
const relativePath = nextSegments.join("/");
|
|
18198
19477
|
assertSafeRelativeFilePath(relativePath);
|
|
18199
|
-
const filePath =
|
|
19478
|
+
const filePath = path6.join(currentDirectory, entry.name);
|
|
18200
19479
|
if (entry.isDirectory()) {
|
|
18201
19480
|
return await visit(filePath, nextSegments);
|
|
18202
19481
|
}
|
|
@@ -18205,7 +19484,7 @@ async function readDirectorySnapshot({
|
|
|
18205
19484
|
`Skill working copy contains unsupported entry "${filePath}". Only regular files and directories are allowed.`
|
|
18206
19485
|
);
|
|
18207
19486
|
}
|
|
18208
|
-
return [[`${skillPath}/${relativePath}`, await
|
|
19487
|
+
return [[`${skillPath}/${relativePath}`, await readFile4(filePath)]];
|
|
18209
19488
|
})
|
|
18210
19489
|
);
|
|
18211
19490
|
return nestedEntries.flat();
|
|
@@ -18231,8 +19510,8 @@ async function writeSnapshotContents(rootPath, snapshot, prefix) {
|
|
|
18231
19510
|
[...snapshot.entries()].map(async ([filePath, content]) => {
|
|
18232
19511
|
const relativePath = prefix === null ? filePath : filePath.slice(`${prefix}/`.length);
|
|
18233
19512
|
assertSafeRelativeFilePath(relativePath);
|
|
18234
|
-
const targetPath =
|
|
18235
|
-
await mkdir2(
|
|
19513
|
+
const targetPath = path6.join(rootPath, ...relativePath.split("/"));
|
|
19514
|
+
await mkdir2(path6.dirname(targetPath), { recursive: true });
|
|
18236
19515
|
await writeFile2(targetPath, content);
|
|
18237
19516
|
})
|
|
18238
19517
|
);
|
|
@@ -18242,42 +19521,42 @@ async function replaceWorkingCopy({
|
|
|
18242
19521
|
skillPath,
|
|
18243
19522
|
workingCopyPath
|
|
18244
19523
|
}) {
|
|
18245
|
-
const parentPath =
|
|
19524
|
+
const parentPath = path6.dirname(workingCopyPath);
|
|
18246
19525
|
await mkdir2(parentPath, { recursive: true });
|
|
18247
|
-
const temporaryPath =
|
|
19526
|
+
const temporaryPath = path6.join(
|
|
18248
19527
|
parentPath,
|
|
18249
|
-
`.mgcl-${
|
|
19528
|
+
`.mgcl-${path6.basename(workingCopyPath)}-${randomUUID3()}.tmp`
|
|
18250
19529
|
);
|
|
18251
|
-
const backupPath = `${workingCopyPath}.${
|
|
19530
|
+
const backupPath = `${workingCopyPath}.${randomUUID3()}.bak`;
|
|
18252
19531
|
await mkdir2(temporaryPath);
|
|
18253
19532
|
const prepareResult = await fromThrowable(async () => {
|
|
18254
19533
|
await writeSnapshotContents(temporaryPath, snapshot, skillPath);
|
|
18255
19534
|
const hadExistingWorkingCopy = await pathExists(workingCopyPath);
|
|
18256
19535
|
if (hadExistingWorkingCopy) {
|
|
18257
|
-
await
|
|
19536
|
+
await rename2(workingCopyPath, backupPath);
|
|
18258
19537
|
}
|
|
18259
19538
|
return hadExistingWorkingCopy;
|
|
18260
19539
|
}, "skills-working-copy-replace-failed");
|
|
18261
19540
|
if (isErr(prepareResult)) {
|
|
18262
|
-
await
|
|
19541
|
+
await rm4(temporaryPath, { force: true, recursive: true });
|
|
18263
19542
|
throw new CliError("Failed to replace the skill working copy.", {
|
|
18264
19543
|
cause: prepareResult.error.cause
|
|
18265
19544
|
});
|
|
18266
19545
|
}
|
|
18267
19546
|
const activationResult = await fromThrowable(async () => {
|
|
18268
|
-
await
|
|
19547
|
+
await rename2(temporaryPath, workingCopyPath);
|
|
18269
19548
|
}, "skills-working-copy-activation-failed");
|
|
18270
19549
|
if (isErr(activationResult)) {
|
|
18271
19550
|
if (prepareResult.value) {
|
|
18272
|
-
await
|
|
19551
|
+
await rename2(backupPath, workingCopyPath);
|
|
18273
19552
|
}
|
|
18274
|
-
await
|
|
19553
|
+
await rm4(temporaryPath, { force: true, recursive: true });
|
|
18275
19554
|
throw new CliError("Failed to activate the new skill working copy.", {
|
|
18276
19555
|
cause: activationResult.error.cause
|
|
18277
19556
|
});
|
|
18278
19557
|
}
|
|
18279
19558
|
if (prepareResult.value) {
|
|
18280
|
-
await
|
|
19559
|
+
await rm4(backupPath, { force: true, recursive: true });
|
|
18281
19560
|
}
|
|
18282
19561
|
}
|
|
18283
19562
|
async function runGit(arguments_, cwd, allowedExitCodes = [0]) {
|
|
@@ -18317,7 +19596,7 @@ async function clearDirectoryExceptGit(directoryPath) {
|
|
|
18317
19596
|
const entries = await readdir(directoryPath);
|
|
18318
19597
|
await Promise.all(
|
|
18319
19598
|
entries.filter((entry) => entry !== ".git").map(async (entry) => {
|
|
18320
|
-
await
|
|
19599
|
+
await rm4(path6.join(directoryPath, entry), {
|
|
18321
19600
|
force: true,
|
|
18322
19601
|
recursive: true
|
|
18323
19602
|
});
|
|
@@ -18329,7 +19608,7 @@ async function createPatch(before, after) {
|
|
|
18329
19608
|
return "";
|
|
18330
19609
|
}
|
|
18331
19610
|
const repositoryPath = await mkdtemp(
|
|
18332
|
-
|
|
19611
|
+
path6.join(os2.tmpdir(), "mgcl-skills-diff-")
|
|
18333
19612
|
);
|
|
18334
19613
|
const patchResult = await fromThrowable(async () => {
|
|
18335
19614
|
await runGit(["init", "--quiet"], repositoryPath);
|
|
@@ -18372,7 +19651,7 @@ async function createPatch(before, after) {
|
|
|
18372
19651
|
);
|
|
18373
19652
|
return result.stdout.toString("utf8");
|
|
18374
19653
|
}, "skills-patch-generation-failed");
|
|
18375
|
-
await
|
|
19654
|
+
await rm4(repositoryPath, { force: true, recursive: true });
|
|
18376
19655
|
if (isErr(patchResult)) {
|
|
18377
19656
|
throw patchResult.error.cause;
|
|
18378
19657
|
}
|
|
@@ -18580,7 +19859,7 @@ async function pushSkillWorkingCopy({
|
|
|
18580
19859
|
assertTextPatch(patchContents);
|
|
18581
19860
|
const applyResult = await fromThrowable(
|
|
18582
19861
|
async () => await context.api.applyPatch({
|
|
18583
|
-
idempotencyKey: `mgcl-skills-${
|
|
19862
|
+
idempotencyKey: `mgcl-skills-${randomUUID3()}`,
|
|
18584
19863
|
message: message ?? `Update ${workingCopy.skillPath} via mgcl`,
|
|
18585
19864
|
patch: patchContents
|
|
18586
19865
|
}),
|
|
@@ -18651,34 +19930,34 @@ async function pushSkillWorkingCopy({
|
|
|
18651
19930
|
}
|
|
18652
19931
|
|
|
18653
19932
|
// src/state.ts
|
|
18654
|
-
import { mkdir as mkdir3, readFile as
|
|
18655
|
-
import
|
|
18656
|
-
import { z as
|
|
18657
|
-
var cliAccountSchema =
|
|
18658
|
-
clientId:
|
|
18659
|
-
email:
|
|
18660
|
-
userId:
|
|
19933
|
+
import { mkdir as mkdir3, readFile as readFile5, rm as rm5, writeFile as writeFile3 } from "node:fs/promises";
|
|
19934
|
+
import path7 from "node:path";
|
|
19935
|
+
import { z as z30 } from "zod";
|
|
19936
|
+
var cliAccountSchema = z30.object({
|
|
19937
|
+
clientId: z30.string().min(1),
|
|
19938
|
+
email: z30.string().nullable(),
|
|
19939
|
+
userId: z30.string().min(1)
|
|
18661
19940
|
});
|
|
18662
|
-
var cliOrganizationSchema =
|
|
18663
|
-
id:
|
|
18664
|
-
name:
|
|
18665
|
-
primaryDomain:
|
|
19941
|
+
var cliOrganizationSchema = z30.object({
|
|
19942
|
+
id: z30.string().min(1),
|
|
19943
|
+
name: z30.string().min(1),
|
|
19944
|
+
primaryDomain: z30.string().nullable().default(null)
|
|
18666
19945
|
});
|
|
18667
|
-
var cliStateSchema =
|
|
19946
|
+
var cliStateSchema = z30.object({
|
|
18668
19947
|
account: cliAccountSchema,
|
|
18669
|
-
defaultOrgId:
|
|
18670
|
-
lastUsedOrgId:
|
|
18671
|
-
organizations:
|
|
19948
|
+
defaultOrgId: z30.string().nullable(),
|
|
19949
|
+
lastUsedOrgId: z30.string().nullable(),
|
|
19950
|
+
organizations: z30.array(cliOrganizationSchema)
|
|
18672
19951
|
});
|
|
18673
|
-
var refreshTokenFileSchema =
|
|
19952
|
+
var refreshTokenFileSchema = z30.record(z30.string(), z30.string());
|
|
18674
19953
|
function createFileStateStore(stateFilePath) {
|
|
18675
19954
|
return {
|
|
18676
19955
|
async clear() {
|
|
18677
|
-
await
|
|
19956
|
+
await rm5(stateFilePath, { force: true });
|
|
18678
19957
|
},
|
|
18679
19958
|
async load() {
|
|
18680
19959
|
try {
|
|
18681
|
-
const fileContents = await
|
|
19960
|
+
const fileContents = await readFile5(stateFilePath, "utf8");
|
|
18682
19961
|
const parsed = cliStateSchema.safeParse(JSON.parse(fileContents));
|
|
18683
19962
|
if (!parsed.success) {
|
|
18684
19963
|
throw new CliError("Stored CLI state is invalid.");
|
|
@@ -18695,7 +19974,7 @@ function createFileStateStore(stateFilePath) {
|
|
|
18695
19974
|
}
|
|
18696
19975
|
},
|
|
18697
19976
|
async save(state) {
|
|
18698
|
-
await mkdir3(
|
|
19977
|
+
await mkdir3(path7.dirname(stateFilePath), { recursive: true });
|
|
18699
19978
|
await writeFile3(stateFilePath, `${JSON.stringify(state, null, 2)}
|
|
18700
19979
|
`);
|
|
18701
19980
|
}
|
|
@@ -18704,7 +19983,7 @@ function createFileStateStore(stateFilePath) {
|
|
|
18704
19983
|
function createFileRefreshTokenStore(refreshTokenFilePath) {
|
|
18705
19984
|
async function loadRefreshTokens() {
|
|
18706
19985
|
try {
|
|
18707
|
-
const fileContents = await
|
|
19986
|
+
const fileContents = await readFile5(refreshTokenFilePath, "utf8");
|
|
18708
19987
|
const parsed = refreshTokenFileSchema.safeParse(JSON.parse(fileContents));
|
|
18709
19988
|
if (!parsed.success) {
|
|
18710
19989
|
throw new CliError("Stored refresh tokens are invalid.");
|
|
@@ -18723,7 +20002,7 @@ function createFileRefreshTokenStore(refreshTokenFilePath) {
|
|
|
18723
20002
|
}
|
|
18724
20003
|
}
|
|
18725
20004
|
async function saveRefreshTokens(refreshTokens) {
|
|
18726
|
-
await mkdir3(
|
|
20005
|
+
await mkdir3(path7.dirname(refreshTokenFilePath), { recursive: true });
|
|
18727
20006
|
await writeFile3(
|
|
18728
20007
|
refreshTokenFilePath,
|
|
18729
20008
|
`${JSON.stringify(refreshTokens, null, 2)}
|
|
@@ -18740,7 +20019,7 @@ function createFileRefreshTokenStore(refreshTokenFilePath) {
|
|
|
18740
20019
|
)
|
|
18741
20020
|
);
|
|
18742
20021
|
if (Object.keys(nextRefreshTokens).length === 0) {
|
|
18743
|
-
await
|
|
20022
|
+
await rm5(refreshTokenFilePath, { force: true });
|
|
18744
20023
|
return;
|
|
18745
20024
|
}
|
|
18746
20025
|
await saveRefreshTokens(nextRefreshTokens);
|
|
@@ -18761,37 +20040,37 @@ function buildRefreshTokenKey(account) {
|
|
|
18761
20040
|
}
|
|
18762
20041
|
|
|
18763
20042
|
// src/workos-auth.ts
|
|
18764
|
-
import { z as
|
|
20043
|
+
import { z as z31 } from "zod";
|
|
18765
20044
|
var DEFAULT_DEVICE_POLL_INTERVAL_SECONDS = 5;
|
|
18766
20045
|
function buildFormHeaders() {
|
|
18767
20046
|
const headers = new Headers();
|
|
18768
20047
|
headers.set("content-type", "application/x-www-form-urlencoded");
|
|
18769
20048
|
return headers;
|
|
18770
20049
|
}
|
|
18771
|
-
var deviceAuthorizationSchema =
|
|
18772
|
-
device_code:
|
|
18773
|
-
expires_in:
|
|
18774
|
-
interval:
|
|
18775
|
-
user_code:
|
|
18776
|
-
verification_uri:
|
|
18777
|
-
verification_uri_complete:
|
|
20050
|
+
var deviceAuthorizationSchema = z31.object({
|
|
20051
|
+
device_code: z31.string().min(1),
|
|
20052
|
+
expires_in: z31.number().int().positive().optional(),
|
|
20053
|
+
interval: z31.number().int().positive().optional(),
|
|
20054
|
+
user_code: z31.string().min(1),
|
|
20055
|
+
verification_uri: z31.url(),
|
|
20056
|
+
verification_uri_complete: z31.url().optional()
|
|
18778
20057
|
});
|
|
18779
|
-
var tokenResponseSchema =
|
|
18780
|
-
access_token:
|
|
18781
|
-
expires_in:
|
|
18782
|
-
refresh_token:
|
|
18783
|
-
token_type:
|
|
20058
|
+
var tokenResponseSchema = z31.object({
|
|
20059
|
+
access_token: z31.string().min(1),
|
|
20060
|
+
expires_in: z31.number().int().positive().optional(),
|
|
20061
|
+
refresh_token: z31.string().min(1),
|
|
20062
|
+
token_type: z31.string().optional()
|
|
18784
20063
|
});
|
|
18785
|
-
var tokenErrorSchema =
|
|
18786
|
-
error:
|
|
18787
|
-
error_description:
|
|
20064
|
+
var tokenErrorSchema = z31.object({
|
|
20065
|
+
error: z31.string().min(1),
|
|
20066
|
+
error_description: z31.string().optional()
|
|
18788
20067
|
});
|
|
18789
|
-
var accessTokenClaimsSchema =
|
|
18790
|
-
exp:
|
|
18791
|
-
iss:
|
|
18792
|
-
org_id:
|
|
18793
|
-
sid:
|
|
18794
|
-
sub:
|
|
20068
|
+
var accessTokenClaimsSchema = z31.object({
|
|
20069
|
+
exp: z31.number().int().positive().optional(),
|
|
20070
|
+
iss: z31.string().min(1).optional(),
|
|
20071
|
+
org_id: z31.string().min(1).optional(),
|
|
20072
|
+
sid: z31.string().min(1).optional(),
|
|
20073
|
+
sub: z31.string().min(1)
|
|
18795
20074
|
});
|
|
18796
20075
|
function createWorkosAuthClient({
|
|
18797
20076
|
fetchFn = fetch,
|
|
@@ -19044,6 +20323,9 @@ function requireApiClientMethod(apiClient, key) {
|
|
|
19044
20323
|
function collectOperationVariables(operationSpec, options) {
|
|
19045
20324
|
const variables = Object.fromEntries(
|
|
19046
20325
|
operationSpec.cli.options.flatMap((optionSpec) => {
|
|
20326
|
+
if (optionSpec.clientOnly) {
|
|
20327
|
+
return [];
|
|
20328
|
+
}
|
|
19047
20329
|
const optionValue = options[buildCommandOptionProperty(optionSpec.flagName)];
|
|
19048
20330
|
if (optionValue === void 0) {
|
|
19049
20331
|
return [];
|
|
@@ -19051,6 +20333,9 @@ function collectOperationVariables(operationSpec, options) {
|
|
|
19051
20333
|
return [[optionSpec.inputKey, optionValue]];
|
|
19052
20334
|
})
|
|
19053
20335
|
);
|
|
20336
|
+
return parseOperationVariables(operationSpec, variables);
|
|
20337
|
+
}
|
|
20338
|
+
function parseOperationVariables(operationSpec, variables) {
|
|
19054
20339
|
const parsedVariables = operationSpec.inputSchema.safeParse(variables);
|
|
19055
20340
|
if (!parsedVariables.success) {
|
|
19056
20341
|
throw new CliError(
|
|
@@ -19130,6 +20415,14 @@ async function handleSelfUpdate(dependencies, options) {
|
|
|
19130
20415
|
);
|
|
19131
20416
|
}
|
|
19132
20417
|
async function handleOperationCommand(dependencies, operationSpec, commandOptions) {
|
|
20418
|
+
if (operationSpec.scope === "global") {
|
|
20419
|
+
await handleGlobalOperationCommand(
|
|
20420
|
+
dependencies,
|
|
20421
|
+
operationSpec,
|
|
20422
|
+
commandOptions
|
|
20423
|
+
);
|
|
20424
|
+
return;
|
|
20425
|
+
}
|
|
19133
20426
|
const { accessToken, impersonatedOrganizationId, organization, state } = await withSelectedOrganizationAndAccessToken({
|
|
19134
20427
|
dependencies,
|
|
19135
20428
|
options: commandOptions
|
|
@@ -19153,16 +20446,89 @@ async function handleOperationCommand(dependencies, operationSpec, commandOption
|
|
|
19153
20446
|
}
|
|
19154
20447
|
dependencies.io.info(formatHumanReadableOutput(result));
|
|
19155
20448
|
}
|
|
19156
|
-
function
|
|
20449
|
+
function getOperation(operationName) {
|
|
19157
20450
|
const operationSpec = operationSpecs.find(
|
|
19158
20451
|
(candidate) => candidate.operationName === operationName
|
|
19159
20452
|
);
|
|
19160
20453
|
if (!operationSpec) {
|
|
20454
|
+
throw new CliError(`Operation "${operationName}" is not registered.`);
|
|
20455
|
+
}
|
|
20456
|
+
return operationSpec;
|
|
20457
|
+
}
|
|
20458
|
+
async function withGlobalOperationAccessToken({
|
|
20459
|
+
dependencies
|
|
20460
|
+
}) {
|
|
20461
|
+
const state = requireLoggedInState(await dependencies.stateStore.load());
|
|
20462
|
+
const directAccessTokenOrganizationId = await resolveDirectAccessTokenOrganizationId({ dependencies });
|
|
20463
|
+
const authenticationOrganizationId = directAccessTokenOrganizationId ?? state.defaultOrgId ?? state.lastUsedOrgId ?? state.organizations[0]?.id;
|
|
20464
|
+
if (!authenticationOrganizationId) {
|
|
19161
20465
|
throw new CliError(
|
|
19162
|
-
|
|
20466
|
+
'No organization is available for authentication. Run "mgcl auth login" again.'
|
|
19163
20467
|
);
|
|
19164
20468
|
}
|
|
19165
|
-
|
|
20469
|
+
const { accessToken } = await withGlobalAccessToken({
|
|
20470
|
+
authenticationOrganizationId,
|
|
20471
|
+
dependencies,
|
|
20472
|
+
state
|
|
20473
|
+
});
|
|
20474
|
+
const usesOttoAuthorization = (() => {
|
|
20475
|
+
try {
|
|
20476
|
+
return dependencies.authClient.decodeAccessTokenClaims(accessToken).iss === "magical:otto";
|
|
20477
|
+
} catch {
|
|
20478
|
+
return false;
|
|
20479
|
+
}
|
|
20480
|
+
})();
|
|
20481
|
+
return {
|
|
20482
|
+
accessToken,
|
|
20483
|
+
...usesOttoAuthorization ? { organizationId: authenticationOrganizationId } : {}
|
|
20484
|
+
};
|
|
20485
|
+
}
|
|
20486
|
+
async function handleGlobalOperationCommand(dependencies, operationSpec, commandOptions) {
|
|
20487
|
+
const { accessToken, organizationId } = await withGlobalOperationAccessToken({
|
|
20488
|
+
dependencies
|
|
20489
|
+
});
|
|
20490
|
+
const executeOperation = async (operationName, variables) => {
|
|
20491
|
+
const nextOperationSpec = getOperation(operationName);
|
|
20492
|
+
if (nextOperationSpec.scope !== "global") {
|
|
20493
|
+
throw new CliError(
|
|
20494
|
+
`Global operation "${operationName}" cannot execute an organization-scoped operation.`
|
|
20495
|
+
);
|
|
20496
|
+
}
|
|
20497
|
+
return await dependencies.apiClient.executeGraphQl({
|
|
20498
|
+
accessToken,
|
|
20499
|
+
...organizationId ? { organizationId } : {},
|
|
20500
|
+
query: nextOperationSpec.document,
|
|
20501
|
+
resultKey: nextOperationSpec.cli.resultKey,
|
|
20502
|
+
variables: parseOperationVariables(nextOperationSpec, variables)
|
|
20503
|
+
});
|
|
20504
|
+
};
|
|
20505
|
+
const customResult = await executeEvalCliOperation({
|
|
20506
|
+
executeOperation,
|
|
20507
|
+
operationName: operationSpec.operationName,
|
|
20508
|
+
options: commandOptions,
|
|
20509
|
+
runtime: {
|
|
20510
|
+
...dependencies.evalCommandRuntime,
|
|
20511
|
+
...dependencies.apiClient.downloadFile ? { downloadFile: dependencies.apiClient.downloadFile } : {},
|
|
20512
|
+
workingDirectory: dependencies.evalCommandRuntime?.workingDirectory ?? dependencies.workingDirectory ?? process.cwd()
|
|
20513
|
+
}
|
|
20514
|
+
});
|
|
20515
|
+
const commandResult = customResult ?? {
|
|
20516
|
+
result: await executeOperation(
|
|
20517
|
+
operationSpec.operationName,
|
|
20518
|
+
collectOperationVariables(operationSpec, commandOptions)
|
|
20519
|
+
)
|
|
20520
|
+
};
|
|
20521
|
+
writeCommandOutput({
|
|
20522
|
+
dependencies,
|
|
20523
|
+
json: commandOptions.json,
|
|
20524
|
+
result: commandResult.result
|
|
20525
|
+
});
|
|
20526
|
+
if (commandResult.exitError) {
|
|
20527
|
+
throw commandResult.exitError;
|
|
20528
|
+
}
|
|
20529
|
+
}
|
|
20530
|
+
function getSkillsOperation(operationName) {
|
|
20531
|
+
return getOperation(operationName);
|
|
19166
20532
|
}
|
|
19167
20533
|
async function withSkillsWorkingCopyContext(dependencies, options) {
|
|
19168
20534
|
const { accessToken, impersonatedOrganizationId, organization, state } = await withSelectedOrganizationAndAccessToken({ dependencies, options });
|
|
@@ -19420,7 +20786,7 @@ async function resolveDirectAccessTokenOrganizationId({
|
|
|
19420
20786
|
if (!accessTokenFilePath) {
|
|
19421
20787
|
return null;
|
|
19422
20788
|
}
|
|
19423
|
-
const accessToken = await
|
|
20789
|
+
const accessToken = await readFile6(accessTokenFilePath, "utf8").then((value) => value.trim()).catch((error) => {
|
|
19424
20790
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
19425
20791
|
return null;
|
|
19426
20792
|
}
|
|
@@ -19452,6 +20818,9 @@ function addRegistryOperationCommand({
|
|
|
19452
20818
|
dependencies,
|
|
19453
20819
|
operationSpec
|
|
19454
20820
|
}) {
|
|
20821
|
+
if (operationSpec.cli.hidden) {
|
|
20822
|
+
return;
|
|
20823
|
+
}
|
|
19455
20824
|
const commandPath = [...operationSpec.cli.path];
|
|
19456
20825
|
const leafCommandName = commandPath.pop();
|
|
19457
20826
|
if (!leafCommandName) {
|
|
@@ -19488,12 +20857,16 @@ function addRegistryOperationCommand({
|
|
|
19488
20857
|
configureOperationalCommand(legacyAliasCommand, dependencies, operationSpec);
|
|
19489
20858
|
}
|
|
19490
20859
|
function configureOperationalCommand(command, dependencies, operationSpec) {
|
|
19491
|
-
command.description(operationSpec.cli.description)
|
|
19492
|
-
|
|
19493
|
-
|
|
19494
|
-
|
|
19495
|
-
|
|
19496
|
-
|
|
20860
|
+
command.description(operationSpec.cli.description);
|
|
20861
|
+
if (operationSpec.scope !== "global") {
|
|
20862
|
+
command.addOption(
|
|
20863
|
+
new Option2(
|
|
20864
|
+
"--org <org>",
|
|
20865
|
+
"Organization ID or exact organization name to use."
|
|
20866
|
+
).helpGroup("Shared options:")
|
|
20867
|
+
);
|
|
20868
|
+
}
|
|
20869
|
+
command.addHelpText(
|
|
19497
20870
|
"after",
|
|
19498
20871
|
`
|
|
19499
20872
|
${formatExamples(
|
|
@@ -19532,12 +20905,12 @@ function createConsoleIo() {
|
|
|
19532
20905
|
function createDefaultDependencies() {
|
|
19533
20906
|
const runtimeConfig = getRuntimeConfig();
|
|
19534
20907
|
const settingsStore = createFileSettingsStore(runtimeConfig.stateFilePath);
|
|
19535
|
-
const accessTokenFilePath = runtimeConfig.accessTokenFilePath ??
|
|
19536
|
-
|
|
20908
|
+
const accessTokenFilePath = runtimeConfig.accessTokenFilePath ?? path8.join(
|
|
20909
|
+
path8.dirname(runtimeConfig.stateFilePath),
|
|
19537
20910
|
CLI_ACCESS_TOKEN_FILE_NAME
|
|
19538
20911
|
);
|
|
19539
|
-
const refreshTokenFilePath = runtimeConfig.refreshTokenFilePath ??
|
|
19540
|
-
|
|
20912
|
+
const refreshTokenFilePath = runtimeConfig.refreshTokenFilePath ?? path8.join(
|
|
20913
|
+
path8.dirname(runtimeConfig.stateFilePath),
|
|
19541
20914
|
CLI_REFRESH_TOKEN_FILE_NAME
|
|
19542
20915
|
);
|
|
19543
20916
|
const selfUpdateOptions = {
|