@qawolf/cli 1.32.0 → 1.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -1
- package/dist/cli.js +2062 -660
- package/dist/runner-sdk.js +1359 -478
- package/dist/types/runnerSdk/index.d.ts +3 -1
- package/dist/types/runnerSdk/types.d.ts +7 -1
- package/package.json +2 -2
- package/skills/qawolf-cli/SKILL.md +19 -1
- package/skills/qawolf-cli/references/runner.md +63 -16
package/dist/runner-sdk.js
CHANGED
|
@@ -2431,6 +2431,7 @@ var cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]
|
|
|
2431
2431
|
var cidrv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;
|
|
2432
2432
|
var base64 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
|
|
2433
2433
|
var base64url = /^[A-Za-z0-9_-]*$/;
|
|
2434
|
+
var domain = /^([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/;
|
|
2434
2435
|
var httpProtocol = /^https?$/;
|
|
2435
2436
|
var e164 = /^\+[1-9]\d{6,14}$/;
|
|
2436
2437
|
var dateSource = `(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))`;
|
|
@@ -2461,6 +2462,7 @@ var bigint = /^-?\d+n?$/;
|
|
|
2461
2462
|
var integer = /^-?\d+$/;
|
|
2462
2463
|
var number = /^-?\d+(?:\.\d+)?$/;
|
|
2463
2464
|
var boolean = /^(?:true|false)$/i;
|
|
2465
|
+
var _null = /^null$/i;
|
|
2464
2466
|
var lowercase = /^[^A-Z]*$/;
|
|
2465
2467
|
var uppercase = /^[^a-z]*$/;
|
|
2466
2468
|
|
|
@@ -3381,6 +3383,23 @@ var $ZodBigInt = /* @__PURE__ */ $constructor("$ZodBigInt", (inst, def) => {
|
|
|
3381
3383
|
return payload;
|
|
3382
3384
|
};
|
|
3383
3385
|
});
|
|
3386
|
+
var $ZodNull = /* @__PURE__ */ $constructor("$ZodNull", (inst, def) => {
|
|
3387
|
+
$ZodType.init(inst, def);
|
|
3388
|
+
inst._zod.pattern = _null;
|
|
3389
|
+
inst._zod.values = new Set([null]);
|
|
3390
|
+
inst._zod.parse = (payload, _ctx) => {
|
|
3391
|
+
const input = payload.value;
|
|
3392
|
+
if (input === null)
|
|
3393
|
+
return payload;
|
|
3394
|
+
payload.issues.push({
|
|
3395
|
+
expected: "null",
|
|
3396
|
+
code: "invalid_type",
|
|
3397
|
+
input,
|
|
3398
|
+
inst
|
|
3399
|
+
});
|
|
3400
|
+
return payload;
|
|
3401
|
+
};
|
|
3402
|
+
});
|
|
3384
3403
|
var $ZodUnknown = /* @__PURE__ */ $constructor("$ZodUnknown", (inst, def) => {
|
|
3385
3404
|
$ZodType.init(inst, def);
|
|
3386
3405
|
inst._zod.parse = (payload) => payload;
|
|
@@ -4865,6 +4884,12 @@ function _coercedBigint(Class, params) {
|
|
|
4865
4884
|
...normalizeParams(params)
|
|
4866
4885
|
});
|
|
4867
4886
|
}
|
|
4887
|
+
function _null2(Class, params) {
|
|
4888
|
+
return new Class({
|
|
4889
|
+
type: "null",
|
|
4890
|
+
...normalizeParams(params)
|
|
4891
|
+
});
|
|
4892
|
+
}
|
|
4868
4893
|
function _unknown(Class) {
|
|
4869
4894
|
return new Class({
|
|
4870
4895
|
type: "unknown"
|
|
@@ -6316,6 +6341,9 @@ var ZodUUID = /* @__PURE__ */ $constructor("ZodUUID", (inst, def) => {
|
|
|
6316
6341
|
$ZodUUID.init(inst, def);
|
|
6317
6342
|
ZodStringFormat.init(inst, def);
|
|
6318
6343
|
});
|
|
6344
|
+
function uuid2(params) {
|
|
6345
|
+
return _uuid(ZodUUID, params);
|
|
6346
|
+
}
|
|
6319
6347
|
var ZodURL = /* @__PURE__ */ $constructor("ZodURL", (inst, def) => {
|
|
6320
6348
|
$ZodURL.init(inst, def);
|
|
6321
6349
|
ZodStringFormat.init(inst, def);
|
|
@@ -6323,6 +6351,13 @@ var ZodURL = /* @__PURE__ */ $constructor("ZodURL", (inst, def) => {
|
|
|
6323
6351
|
function url(params) {
|
|
6324
6352
|
return _url(ZodURL, params);
|
|
6325
6353
|
}
|
|
6354
|
+
function httpUrl(params) {
|
|
6355
|
+
return _url(ZodURL, {
|
|
6356
|
+
protocol: httpProtocol,
|
|
6357
|
+
hostname: domain,
|
|
6358
|
+
...normalizeParams(params)
|
|
6359
|
+
});
|
|
6360
|
+
}
|
|
6326
6361
|
var ZodEmoji = /* @__PURE__ */ $constructor("ZodEmoji", (inst, def) => {
|
|
6327
6362
|
$ZodEmoji.init(inst, def);
|
|
6328
6363
|
ZodStringFormat.init(inst, def);
|
|
@@ -6484,6 +6519,14 @@ var ZodBigInt = /* @__PURE__ */ $constructor("ZodBigInt", (inst, def) => {
|
|
|
6484
6519
|
inst.maxValue = bag.maximum ?? null;
|
|
6485
6520
|
inst.format = bag.format ?? null;
|
|
6486
6521
|
});
|
|
6522
|
+
var ZodNull = /* @__PURE__ */ $constructor("ZodNull", (inst, def) => {
|
|
6523
|
+
$ZodNull.init(inst, def);
|
|
6524
|
+
ZodType.init(inst, def);
|
|
6525
|
+
inst._zod.processJSONSchema = (ctx, json, params) => nullProcessor(inst, ctx, json, params);
|
|
6526
|
+
});
|
|
6527
|
+
function _null3(params) {
|
|
6528
|
+
return _null2(ZodNull, params);
|
|
6529
|
+
}
|
|
6487
6530
|
var ZodUnknown = /* @__PURE__ */ $constructor("ZodUnknown", (inst, def) => {
|
|
6488
6531
|
$ZodUnknown.init(inst, def);
|
|
6489
6532
|
ZodType.init(inst, def);
|
|
@@ -6914,6 +6957,12 @@ function refine(fn, _params = {}) {
|
|
|
6914
6957
|
function superRefine(fn, params) {
|
|
6915
6958
|
return _superRefine(fn, params);
|
|
6916
6959
|
}
|
|
6960
|
+
function json(params) {
|
|
6961
|
+
const jsonSchema = lazy(() => {
|
|
6962
|
+
return union([string2(params), number2(), boolean2(), _null3(), array(jsonSchema), record(string2(), jsonSchema)]);
|
|
6963
|
+
});
|
|
6964
|
+
return jsonSchema;
|
|
6965
|
+
}
|
|
6917
6966
|
// node_modules/zod/v4/classic/coerce.js
|
|
6918
6967
|
var exports_coerce = {};
|
|
6919
6968
|
__export(exports_coerce, {
|
|
@@ -6956,6 +7005,10 @@ var agentReplySchema = object({
|
|
|
6956
7005
|
text: string2().describe("What the AI said.")
|
|
6957
7006
|
});
|
|
6958
7007
|
|
|
7008
|
+
// node_modules/@qawolf/api-contracts/dist/v1/agent/wait.js
|
|
7009
|
+
var maxAgentWaitSeconds = 45;
|
|
7010
|
+
var agentWakeReasonSchema = _enum(["reply", "status", "timeout"]).describe('Why a held check answered. "reply" means the AI said something new, "status" means the session settled or needs you, "timeout" means the hold ran out with nothing new.');
|
|
7011
|
+
|
|
6959
7012
|
// node_modules/@qawolf/api-contracts/dist/v1/resource.js
|
|
6960
7013
|
function resource(fields, { urlFieldDescription = "Absolute URL." } = {}) {
|
|
6961
7014
|
return object({
|
|
@@ -7113,16 +7166,18 @@ var identityOrganizationsResponse = object({
|
|
|
7113
7166
|
// node_modules/@qawolf/api-contracts/dist/v1/ids.js
|
|
7114
7167
|
var defaultIdSchemas = {
|
|
7115
7168
|
aiTask: string2().min(1).describe("The id of the AI task."),
|
|
7116
|
-
automation: string2().min(1).describe("The id of the automation."),
|
|
7117
7169
|
chatSession: string2().min(1).describe("The id of the chat session."),
|
|
7170
|
+
deployment: string2().min(1).describe("The id of the deployment."),
|
|
7118
7171
|
environment: string2().min(1).describe("The id of the environment."),
|
|
7119
|
-
environmentRef: string2().min(1).describe("The id or alias of the environment.
|
|
7172
|
+
environmentRef: string2().min(1).describe("The id or alias of the environment. An organization or user API key must also send workspaceId to use an alias."),
|
|
7120
7173
|
flow: string2().min(1).describe("The id of the flow."),
|
|
7121
7174
|
issue: string2().min(1).describe("The id of the issue."),
|
|
7175
|
+
legacyTrigger: string2().min(1).describe("The id of the legacy trigger, from legacyTrigger.find."),
|
|
7122
7176
|
run: string2().min(1).describe("The id of the run."),
|
|
7123
7177
|
trigger: string2().min(1).describe("The id of the trigger."),
|
|
7124
7178
|
workspace: string2().min(1).describe("The id of the workspace.")
|
|
7125
7179
|
};
|
|
7180
|
+
var workspaceForEnvironmentRef = (workspace) => workspace.optional().describe("The workspace the environment belongs to. Required to reference the environment by alias when authenticating with an organization or user API key.");
|
|
7126
7181
|
|
|
7127
7182
|
// node_modules/@qawolf/api-contracts/dist/v1/run/flowSelection.js
|
|
7128
7183
|
var makeFlowSelectionSchema = (ids) => object({
|
|
@@ -7141,7 +7196,8 @@ var makeCreateRunContract = (ids) => {
|
|
|
7141
7196
|
environmentVariables: record(string2(), string2()).optional(),
|
|
7142
7197
|
ignoreRules: boolean2().describe("Ignore this team's sequencing rules for this run. By default they are honoured: the flows your selection depends on are added to the run, and flows run in the order the rules require. Set this to run exactly what you selected, in any order.").default(false),
|
|
7143
7198
|
pullRequestNumber: number2().int().positive().describe("The number of the pull request to associate with the run.").optional(),
|
|
7144
|
-
repository: string2().min(1).describe('The owner/name of the repository, e.g. "acme/web".').optional()
|
|
7199
|
+
repository: string2().min(1).describe('The owner/name of the repository, e.g. "acme/web".').optional(),
|
|
7200
|
+
workspaceId: workspaceForEnvironmentRef(ids.workspace)
|
|
7145
7201
|
}).and(makeFlowSelectionSchema(ids)).refine((value) => !(value.aiTaskId && value.chatSessionId), {
|
|
7146
7202
|
message: "Provide at most one of aiTaskId and chatSessionId: a task already implies its own chat session.",
|
|
7147
7203
|
path: ["chatSessionId"]
|
|
@@ -7169,6 +7225,10 @@ var makeCreateRunContract = (ids) => {
|
|
|
7169
7225
|
};
|
|
7170
7226
|
};
|
|
7171
7227
|
|
|
7228
|
+
// node_modules/@qawolf/api-contracts/dist/v1/runner/actionSequence.js
|
|
7229
|
+
var maxActionsPerRequest = 10;
|
|
7230
|
+
var screenshotModes = ["none", "final", "each"];
|
|
7231
|
+
|
|
7172
7232
|
// node_modules/@qawolf/api-contracts/dist/v1/runner/browserAction.js
|
|
7173
7233
|
var maxScreenCoordinate = 20000;
|
|
7174
7234
|
var screenCoordinateSchema = int().min(0).max(maxScreenCoordinate);
|
|
@@ -7296,11 +7356,12 @@ var runnerNameSchema = _enum([
|
|
|
7296
7356
|
var runnerWorkspaceRequirement = "Required when the credential is not bound to a single workspace, such as a user API key or an OAuth connection whose organization owns several.";
|
|
7297
7357
|
var runnerWorkspaceIdDescription = `The workspace the runner belongs to. ${runnerWorkspaceRequirement}`;
|
|
7298
7358
|
var runnerIdSchema = string2().min(1).max(63).regex(/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/, "A runner id may contain only lowercase letters, digits and dashes, and must start and end with a letter or digit.");
|
|
7359
|
+
var runnerWatchUrlSchema = url().describe("A QA Wolf page showing what the runner is doing right now, where the person who launched it can watch and take over with their own mouse and keyboard. Opening it requires being signed in to QA Wolf. This link belongs to the user: put it in a normal message as soon as the runner is launched, so they can follow along while the browser is being driven. It is theirs to open, never a page for the caller to fetch or navigate to. The page ends when the runner is terminated, so share it while the runner is alive and report what you found at the end instead of repeating a dead link.");
|
|
7299
7360
|
var makeRunnerSchema = () => object({
|
|
7300
7361
|
gpuAccelerated: boolean2().describe("Whether the runner was placed on GPU hardware. Chosen by QA Wolf from the team's configuration and what the fleet can provide, not requested."),
|
|
7301
7362
|
id: runnerIdSchema.describe("The runner's id, as supplied when launching it."),
|
|
7302
7363
|
runnerName: runnerNameSchema.describe("The runner family requested when the runner was launched. QA Wolf may place it on faster hardware, reported in gpuAccelerated."),
|
|
7303
|
-
url:
|
|
7364
|
+
url: runnerWatchUrlSchema
|
|
7304
7365
|
});
|
|
7305
7366
|
|
|
7306
7367
|
// node_modules/@qawolf/api-contracts/dist/v1/runner/unreachable.js
|
|
@@ -7591,13 +7652,13 @@ var screenshotImageSchema = string2().min(1).describe("The screenshot, as a base
|
|
|
7591
7652
|
// node_modules/@qawolf/api-contracts/dist/v1/runner/performAction.js
|
|
7592
7653
|
var unreachableDescription = "`runner-unreachable` if the runner could not be reached: it may still be starting, it may have terminated after inactivity, or it may have stopped answering mid-action. This does not mean the action was not performed — take a screenshot before repeating it.";
|
|
7593
7654
|
var notSupportedOnMobileDescription = "`action-not-supported-on-mobile` if the runner is a mobile device and this action has no touchscreen equivalent: `double_click`, `scroll`, `move`, `keypress` and `navigate`, and a `click` whose `button` is not `left`, are all pointer-device concepts a touchscreen has nothing to offer for. `click` taps, `drag` swipes between its path's first and last point, and `type` types into whatever the last tap focused.";
|
|
7594
|
-
var withScreenshotDescription = "With `withScreenshot: true`, the answer also carries `imageJpegBase64`: a screenshot taken after the action
|
|
7655
|
+
var withScreenshotDescription = "With `withScreenshot: true`, the answer also carries `imageJpegBase64`: a screenshot taken after the action. One call instead of `runner.performAction` followed by `runner.takeScreenshot`. The action itself is performed exactly as without the option; if the screen could serve no frame after it — a display restart, or a `navigate` on a desktop that is still starting — the action's result comes back without `imageJpegBase64`, so take a screenshot separately rather than repeating the action. On a mobile runner the screenshot is the device's own, taken right after a performed action.";
|
|
7595
7656
|
var maxActionErrorMessageLength = 1000;
|
|
7596
7657
|
var makePerformActionOnRunnerContract = (ids) => {
|
|
7597
7658
|
const input = object({
|
|
7598
|
-
action: browserActionSchema.describe(
|
|
7659
|
+
action: browserActionSchema.describe(`The action to perform. Coordinates are whole pixels on the runner's virtual desktop, in the same space as \`runner.takeScreenshot\`. The action shapes follow the computer-use vocabulary, minus \`screenshot\` (use \`runner.takeScreenshot\`) and \`wait\` (delay on the caller's side). A \`navigate\` does not go through the screen, so a screen that is not ready does not stop it. ${notSupportedOnMobileDescription}`),
|
|
7599
7660
|
id: runnerIdSchema.describe("Id of the runner to act on."),
|
|
7600
|
-
withScreenshot: boolean2().optional().describe(
|
|
7661
|
+
withScreenshot: boolean2().optional().describe(withScreenshotDescription),
|
|
7601
7662
|
workspaceId: ids.workspace.optional().describe(runnerWorkspaceIdDescription)
|
|
7602
7663
|
});
|
|
7603
7664
|
const screenshotAfterAction = screenshotImageSchema.optional();
|
|
@@ -7627,7 +7688,7 @@ var makePerformActionOnRunnerContract = (ids) => {
|
|
|
7627
7688
|
openWorldHint: true,
|
|
7628
7689
|
readOnlyHint: false
|
|
7629
7690
|
},
|
|
7630
|
-
description: `Perform one raw browser action on an interactive runner: click, double_click, move, drag, scroll, keypress, type, or navigate.
|
|
7691
|
+
description: `Perform one raw browser action on an interactive runner: click, double_click, move, drag, scroll, keypress, type, or navigate. One action per request, and the runner serves one at a time. A success means the action took effect. \`action-failed\`, with a reason, if it reached the runner and did not take effect. On a runner image with a browser, the first action on a runner that has never run anything starts its browser and waits for it, so it can take up to a minute to answer — no \`runner.runFlow\` is needed before acting; if the browser is still starting when the wait runs out, the answer is \`screen-not-ready\` and retrying converges. On a mobile runner, the same \`screen-needs-a-run\` and \`screen-not-ready\` outcomes mean no Appium session has started yet, or it did not answer this instant; \`runner.runFlow\` is what starts one, same as a browser. \`screen-needs-a-run\` if the browser could not be started that way — usually a runner whose runs all finished without starting its desktop; call \`runner.runFlow\` with a flow that opens a browser. ${screenNotReadyDescription} ${runnerHasNoScreenDescription} ${unreachableDescription}`,
|
|
7631
7692
|
input,
|
|
7632
7693
|
kind: "write",
|
|
7633
7694
|
name: "runner.performAction",
|
|
@@ -7635,6 +7696,214 @@ var makePerformActionOnRunnerContract = (ids) => {
|
|
|
7635
7696
|
};
|
|
7636
7697
|
};
|
|
7637
7698
|
|
|
7699
|
+
// node_modules/@qawolf/api-contracts/dist/v1/runner/performActionsSteps.js
|
|
7700
|
+
var outOfTimeFailureReason = "out-of-time";
|
|
7701
|
+
var unconfirmedFailureReason = "action-unconfirmed";
|
|
7702
|
+
var actionIndexSchema = int().min(0).max(maxActionsPerRequest - 1).describe("Position of the action in the request's `actions`, from 0.");
|
|
7703
|
+
var screenshotAfterStep = screenshotImageSchema.optional();
|
|
7704
|
+
var performedStepSchema = object({
|
|
7705
|
+
effect: literal("performed"),
|
|
7706
|
+
imageJpegBase64: screenshotAfterStep,
|
|
7707
|
+
index: actionIndexSchema,
|
|
7708
|
+
outcome: literal("success")
|
|
7709
|
+
});
|
|
7710
|
+
var failedStepSchema = discriminatedUnion("failureReason", [
|
|
7711
|
+
object({
|
|
7712
|
+
effect: literal("not-performed"),
|
|
7713
|
+
errorMessage: string2().max(maxActionErrorMessageLength).describe("What stopped the action from taking effect."),
|
|
7714
|
+
failureReason: literal("action-failed"),
|
|
7715
|
+
imageJpegBase64: screenshotAfterStep,
|
|
7716
|
+
index: actionIndexSchema,
|
|
7717
|
+
outcome: literal("failure")
|
|
7718
|
+
}),
|
|
7719
|
+
object({
|
|
7720
|
+
effect: literal("unknown"),
|
|
7721
|
+
failureReason: literal(runnerUnreachableFailureReason),
|
|
7722
|
+
index: actionIndexSchema,
|
|
7723
|
+
outcome: literal("failure")
|
|
7724
|
+
}),
|
|
7725
|
+
object({
|
|
7726
|
+
effect: literal("unknown"),
|
|
7727
|
+
errorMessage: string2().max(maxActionErrorMessageLength).describe("How the runner's screen went quiet with the action in flight."),
|
|
7728
|
+
failureReason: literal(unconfirmedFailureReason),
|
|
7729
|
+
index: actionIndexSchema,
|
|
7730
|
+
outcome: literal("failure")
|
|
7731
|
+
}),
|
|
7732
|
+
object({
|
|
7733
|
+
effect: literal("not-performed"),
|
|
7734
|
+
failureReason: _enum([
|
|
7735
|
+
...screenFailureReasons,
|
|
7736
|
+
"action-not-supported-on-mobile",
|
|
7737
|
+
outOfTimeFailureReason
|
|
7738
|
+
]),
|
|
7739
|
+
index: actionIndexSchema,
|
|
7740
|
+
outcome: literal("failure")
|
|
7741
|
+
})
|
|
7742
|
+
]);
|
|
7743
|
+
var stepResultSchema = discriminatedUnion("outcome", [
|
|
7744
|
+
performedStepSchema,
|
|
7745
|
+
failedStepSchema
|
|
7746
|
+
]);
|
|
7747
|
+
var sequenceFailureReasons = [
|
|
7748
|
+
"action-failed",
|
|
7749
|
+
...screenFailureReasons,
|
|
7750
|
+
"action-not-supported-on-mobile",
|
|
7751
|
+
outOfTimeFailureReason,
|
|
7752
|
+
unconfirmedFailureReason,
|
|
7753
|
+
runnerUnreachableFailureReason
|
|
7754
|
+
];
|
|
7755
|
+
|
|
7756
|
+
// node_modules/@qawolf/api-contracts/dist/v1/runner/performActions.js
|
|
7757
|
+
var actionsDescription = `The actions to perform, in order, each exactly what \`runner.performAction\` takes: coordinates are whole pixels on the runner's virtual desktop, in the same space as \`runner.takeScreenshot\`, and the shapes follow the computer-use vocabulary. At most ${maxActionsPerRequest} per request. For when the next several steps are already known — click a field, type into it, press Enter — and one look at the screen at the end is enough. They run back to back on the runner, with no pause between them: put in one request only steps whose targets are all on the screen you last saw and are not moved by the steps before them, and when a step changes the page — a submit, a navigation, opening a menu — make it the last one and read the frame.`;
|
|
7758
|
+
var screenshotModeDescription = "`final`, the default, answers with one screenshot in `imageJpegBase64`: the screen after the last action, or, after a stop, as it stands. `each` puts a screenshot after every action on its entry in `results`, for when each step must be checked; every frame is a full image, so keep such sequences short. `none` sends no screenshot.";
|
|
7759
|
+
var stopOnFailureDescription = "`true`, the default, leaves the remaining actions unperformed once one fails. `false` carries on past an action that reached the runner and did not take effect (`action-failed`, `action-not-supported-on-mobile`), so use it only for actions that do not depend on each other: a `type` after a `click` that failed goes to whatever has focus. A runner that cannot be reached, a screen that cannot serve, or running out of time ends the sequence either way.";
|
|
7760
|
+
var finalImageDescription = "Present with `screenshotMode: final` when the runner still answered: the screen after the last action performed, or, after a stop, as it stands.";
|
|
7761
|
+
var makePerformActionsOnRunnerContract = (ids) => {
|
|
7762
|
+
const input = object({
|
|
7763
|
+
actions: array(browserActionSchema).min(1).max(maxActionsPerRequest).describe(actionsDescription),
|
|
7764
|
+
id: runnerIdSchema.describe("Id of the runner to act on."),
|
|
7765
|
+
screenshotMode: _enum(screenshotModes).optional().describe(screenshotModeDescription),
|
|
7766
|
+
stopOnFailure: boolean2().optional().describe(stopOnFailureDescription),
|
|
7767
|
+
workspaceId: ids.workspace.optional().describe(runnerWorkspaceIdDescription)
|
|
7768
|
+
});
|
|
7769
|
+
const output = discriminatedUnion("outcome", [
|
|
7770
|
+
object({
|
|
7771
|
+
imageJpegBase64: screenshotImageSchema.optional().describe(finalImageDescription),
|
|
7772
|
+
lastCompletedIndex: actionIndexSchema.describe("Index of the last action that took effect: here, the last one sent."),
|
|
7773
|
+
outcome: literal("success"),
|
|
7774
|
+
results: array(performedStepSchema).min(1).max(maxActionsPerRequest).describe("One entry per action, in order.")
|
|
7775
|
+
}),
|
|
7776
|
+
object({
|
|
7777
|
+
errorMessage: string2().max(maxActionErrorMessageLength).optional().describe("What stopped the first failed action, when its reason is `action-failed` or `action-unconfirmed`."),
|
|
7778
|
+
failedIndex: actionIndexSchema.describe("Index of the first action that did not take effect."),
|
|
7779
|
+
failureReason: _enum(sequenceFailureReasons).describe("Why that action did not take effect, the same as on its entry in `results`."),
|
|
7780
|
+
imageJpegBase64: screenshotImageSchema.optional().describe(finalImageDescription),
|
|
7781
|
+
lastCompletedIndex: actionIndexSchema.optional().describe("Index of the last action that took effect. Absent when none did. With `stopOnFailure: false` it can follow a failed action, so `results` says which ones before it took effect."),
|
|
7782
|
+
outcome: literal("failure"),
|
|
7783
|
+
results: array(stepResultSchema).min(1).max(maxActionsPerRequest).describe("One entry per action reached, in order. Actions after a stop have no entry."),
|
|
7784
|
+
stoppedEarly: boolean2().describe("Whether actions after the failure were left unperformed. False when every action was attempted.")
|
|
7785
|
+
})
|
|
7786
|
+
]);
|
|
7787
|
+
return {
|
|
7788
|
+
annotations: {
|
|
7789
|
+
destructiveHint: true,
|
|
7790
|
+
openWorldHint: true,
|
|
7791
|
+
readOnlyHint: false
|
|
7792
|
+
},
|
|
7793
|
+
description: "Perform a sequence of raw browser actions on an interactive runner in one request, one after another, and answer with what happened to each. A `success` means every action took effect. A `failure` names the first action that did not (`failedIndex`, `failureReason`), the last one that did (`lastCompletedIndex`), and whether actions were left unperformed (`stoppedEarly`); `results` has one entry per action reached, in order. Read `effect` on an entry before sending its action again: `performed` means the runner did it; `not-performed` means the runner answered that it did not take effect, though a `navigate` that timed out may still be loading; `unknown` means the runner stopped answering with the action in flight (`runner-unreachable`), or its screen went quiet mid-action (`action-unconfirmed`), and it may have taken effect — a click that submitted a form, say — so take a screenshot instead of repeating it. A sequence gets about a minute to start its actions; an action it did not reach in time is `out-of-time`, nothing after it was attempted, and the rest can go in a new request. Everything `runner.performAction` says about a runner that has never run anything, a mobile runner, and the `screen-needs-a-run`, `screen-not-ready`, `runner-has-no-screen` and `action-not-supported-on-mobile` reasons holds for each action here.",
|
|
7794
|
+
input,
|
|
7795
|
+
kind: "write",
|
|
7796
|
+
name: "runner.performActions",
|
|
7797
|
+
output
|
|
7798
|
+
};
|
|
7799
|
+
};
|
|
7800
|
+
|
|
7801
|
+
// node_modules/@qawolf/api-contracts/dist/v1/runner/recording.js
|
|
7802
|
+
var recordingIdSchema = uuid2();
|
|
7803
|
+
var runnerRecordingCommandSchema = discriminatedUnion("action", [
|
|
7804
|
+
strictObject({
|
|
7805
|
+
action: literal("start"),
|
|
7806
|
+
recordingId: recordingIdSchema
|
|
7807
|
+
}),
|
|
7808
|
+
strictObject({ action: literal("stop"), recordingId: recordingIdSchema }),
|
|
7809
|
+
strictObject({ action: literal("auto"), enabled: boolean2() }),
|
|
7810
|
+
strictObject({ action: literal("status") })
|
|
7811
|
+
]);
|
|
7812
|
+
var runnerRecordingSchema = object({
|
|
7813
|
+
endedAt: exports_iso.datetime(),
|
|
7814
|
+
id: recordingIdSchema,
|
|
7815
|
+
mode: _enum(["manual", "automatic"]),
|
|
7816
|
+
runIds: array(string2()),
|
|
7817
|
+
runnerId: runnerIdSchema,
|
|
7818
|
+
runnerInstanceId: uuid2(),
|
|
7819
|
+
startedAt: exports_iso.datetime(),
|
|
7820
|
+
status: _enum(["ready", "failed"]),
|
|
7821
|
+
version: literal(1)
|
|
7822
|
+
});
|
|
7823
|
+
var runnerRecordingStateSchema = object({
|
|
7824
|
+
active: object({
|
|
7825
|
+
id: recordingIdSchema,
|
|
7826
|
+
mode: _enum(["manual", "automatic"]),
|
|
7827
|
+
startedAt: exports_iso.datetime()
|
|
7828
|
+
}).optional(),
|
|
7829
|
+
auto: _enum(["on", "off", "default"])
|
|
7830
|
+
});
|
|
7831
|
+
var runnerRecordingResultSchema = discriminatedUnion("outcome", [
|
|
7832
|
+
object({
|
|
7833
|
+
outcome: literal("success"),
|
|
7834
|
+
recording: runnerRecordingSchema.optional(),
|
|
7835
|
+
state: runnerRecordingStateSchema
|
|
7836
|
+
}),
|
|
7837
|
+
object({
|
|
7838
|
+
failureReason: _enum([
|
|
7839
|
+
"unsupported",
|
|
7840
|
+
"screen-not-ready",
|
|
7841
|
+
"recording-in-progress",
|
|
7842
|
+
"recording-not-found",
|
|
7843
|
+
"recording-id-used",
|
|
7844
|
+
"runner-unreachable",
|
|
7845
|
+
"recording-failed"
|
|
7846
|
+
]),
|
|
7847
|
+
outcome: literal("failure")
|
|
7848
|
+
})
|
|
7849
|
+
]);
|
|
7850
|
+
var makeRecordOnRunnerContract = (ids) => {
|
|
7851
|
+
const input = object({
|
|
7852
|
+
command: runnerRecordingCommandSchema,
|
|
7853
|
+
id: runnerIdSchema,
|
|
7854
|
+
workspaceId: ids.workspace.optional().describe(runnerWorkspaceIdDescription)
|
|
7855
|
+
});
|
|
7856
|
+
const output = object({
|
|
7857
|
+
result: runnerRecordingResultSchema,
|
|
7858
|
+
url: url()
|
|
7859
|
+
});
|
|
7860
|
+
return {
|
|
7861
|
+
annotations: {
|
|
7862
|
+
destructiveHint: false,
|
|
7863
|
+
openWorldHint: false,
|
|
7864
|
+
readOnlyHint: false
|
|
7865
|
+
},
|
|
7866
|
+
description: "Control video recording on a Playwright runner. Start requires a caller-generated UUID; stop targets that UUID so retries cannot stop a later recording. Manual capture spans runs and suppresses automatic capture. Auto settings affect subsequent full runs. The URL opens recording history after the runner terminates. Videos may be unavailable after abrupt pod loss.",
|
|
7867
|
+
input,
|
|
7868
|
+
kind: "write",
|
|
7869
|
+
name: "runner.record",
|
|
7870
|
+
output
|
|
7871
|
+
};
|
|
7872
|
+
};
|
|
7873
|
+
var makeRunnerRecordingsContract = (ids) => {
|
|
7874
|
+
const input = object({
|
|
7875
|
+
id: runnerIdSchema,
|
|
7876
|
+
pageToken: string2().max(4096).optional(),
|
|
7877
|
+
recordingId: recordingIdSchema.optional(),
|
|
7878
|
+
workspaceId: ids.workspace.optional().describe(runnerWorkspaceIdDescription)
|
|
7879
|
+
});
|
|
7880
|
+
const output = object({
|
|
7881
|
+
nextPageToken: string2().optional(),
|
|
7882
|
+
recordings: array(runnerRecordingSchema.extend({
|
|
7883
|
+
url: url(),
|
|
7884
|
+
videoUrl: url().optional()
|
|
7885
|
+
}))
|
|
7886
|
+
});
|
|
7887
|
+
return {
|
|
7888
|
+
annotations: {
|
|
7889
|
+
destructiveHint: false,
|
|
7890
|
+
openWorldHint: false,
|
|
7891
|
+
readOnlyHint: true
|
|
7892
|
+
},
|
|
7893
|
+
description: "Read a runner's finalized recordings from workspace storage, including after the runner terminates. Omit recordingId to list recordings in storage-key order; follow nextPageToken for more. An empty list for a specific recording means it is not published or does not exist. Video URLs expire; platform URLs remain stable.",
|
|
7894
|
+
input,
|
|
7895
|
+
kind: "read",
|
|
7896
|
+
name: "runner.recordings",
|
|
7897
|
+
output
|
|
7898
|
+
};
|
|
7899
|
+
};
|
|
7900
|
+
function makeRecordingContracts(ids) {
|
|
7901
|
+
return {
|
|
7902
|
+
record: makeRecordOnRunnerContract(ids),
|
|
7903
|
+
recordings: makeRunnerRecordingsContract(ids)
|
|
7904
|
+
};
|
|
7905
|
+
}
|
|
7906
|
+
|
|
7638
7907
|
// node_modules/@qawolf/api-contracts/dist/v1/runner/runSelection.js
|
|
7639
7908
|
var runSelectionSchema = object({
|
|
7640
7909
|
endLine: int().positive().describe("Last line to run, 1-indexed and inclusive."),
|
|
@@ -7653,7 +7922,16 @@ var isTimezone = (value) => {
|
|
|
7653
7922
|
return false;
|
|
7654
7923
|
}
|
|
7655
7924
|
};
|
|
7656
|
-
var triggerCadenceSchema = _enum(["hourly", "daily"]).describe("How often the schedule fires.");
|
|
7925
|
+
var triggerCadenceSchema = _enum(["hourly", "daily", "weekly"]).describe("How often the schedule fires.");
|
|
7926
|
+
var triggerDayOfWeekSchema = _enum([
|
|
7927
|
+
"monday",
|
|
7928
|
+
"tuesday",
|
|
7929
|
+
"wednesday",
|
|
7930
|
+
"thursday",
|
|
7931
|
+
"friday",
|
|
7932
|
+
"saturday",
|
|
7933
|
+
"sunday"
|
|
7934
|
+
]).describe("A day of the week, named rather than numbered.");
|
|
7657
7935
|
var triggerActionKindSchema = _enum(["createSuite", "generativeSuite"]).describe("createSuite runs the flows named by flowIds and tagNames. generativeSuite lets QA Wolf choose the flows from the deployment's changes, and is not available to a schedule.");
|
|
7658
7936
|
var makeTriggerActionSchema = (ids) => object({
|
|
7659
7937
|
flowIds: array(ids.flow).default([]).describe("Flows to run. Combined with tagNames."),
|
|
@@ -7665,10 +7943,11 @@ var makeTriggerActionSchema = (ids) => object({
|
|
|
7665
7943
|
var makeTriggerScheduleFields = (ids) => ({
|
|
7666
7944
|
action: makeTriggerActionSchema(ids),
|
|
7667
7945
|
cadence: triggerCadenceSchema,
|
|
7946
|
+
dayOfWeek: triggerDayOfWeekSchema.optional().describe("The day a weekly schedule fires on, read in timezoneId. Required when cadence is weekly."),
|
|
7668
7947
|
environmentId: ids.environmentId.describe("The environment the scheduled runs happen in."),
|
|
7669
7948
|
minuteOfHour: number2().int().min(0).max(59).optional().describe("Minutes past the hour an hourly schedule fires. Defaults to 0."),
|
|
7670
|
-
timeOfDay: string2().regex(/^([01]\d|2[0-3]):[0-5]\d$/).optional().describe('The wall clock time a daily schedule fires, as "HH:mm". Required when cadence is daily.'),
|
|
7671
|
-
timezoneId: string2().min(1).refine(isTimezone, "Expected an IANA timezone, such as America/New_York.").optional().describe("The IANA timezone that timeOfDay is read in, such as America/New_York. Required when cadence is daily.")
|
|
7949
|
+
timeOfDay: string2().regex(/^([01]\d|2[0-3]):[0-5]\d$/).optional().describe('The wall clock time a daily or weekly schedule fires, as "HH:mm". Required when cadence is daily or weekly.'),
|
|
7950
|
+
timezoneId: string2().min(1).refine(isTimezone, "Expected an IANA timezone, such as America/New_York.").optional().describe("The IANA timezone that timeOfDay is read in, such as America/New_York. Required when cadence is daily or weekly.")
|
|
7672
7951
|
});
|
|
7673
7952
|
var makeTriggerDeploymentFields = (ids) => ({
|
|
7674
7953
|
action: makeTriggerActionSchema(ids),
|
|
@@ -7678,6 +7957,98 @@ var makeTriggerDeploymentFields = (ids) => ({
|
|
|
7678
7957
|
environmentPattern: string2().min(1).optional().describe("Only fire for deployments to environments matching this pattern. Mutually exclusive with environmentIds.")
|
|
7679
7958
|
});
|
|
7680
7959
|
|
|
7960
|
+
// node_modules/@qawolf/api-contracts/dist/v1/trigger/configurationRules.js
|
|
7961
|
+
var checkAction = (action, ctx) => {
|
|
7962
|
+
const namesFlows = action.flowIds.length + action.tagNames.length > 0;
|
|
7963
|
+
if (action.kind === "generativeSuite") {
|
|
7964
|
+
if (namesFlows) {
|
|
7965
|
+
ctx.addIssue({
|
|
7966
|
+
code: "custom",
|
|
7967
|
+
message: "flowIds and tagNames do not apply when the action is generativeSuite.",
|
|
7968
|
+
path: ["action", "flowIds"]
|
|
7969
|
+
});
|
|
7970
|
+
}
|
|
7971
|
+
return;
|
|
7972
|
+
}
|
|
7973
|
+
if (action.instructions !== undefined) {
|
|
7974
|
+
ctx.addIssue({
|
|
7975
|
+
code: "custom",
|
|
7976
|
+
message: "instructions apply to a generativeSuite action only.",
|
|
7977
|
+
path: ["action", "instructions"]
|
|
7978
|
+
});
|
|
7979
|
+
}
|
|
7980
|
+
if (!namesFlows) {
|
|
7981
|
+
ctx.addIssue({
|
|
7982
|
+
code: "custom",
|
|
7983
|
+
message: "At least one flow or tag is required.",
|
|
7984
|
+
path: ["action", "flowIds"]
|
|
7985
|
+
});
|
|
7986
|
+
}
|
|
7987
|
+
};
|
|
7988
|
+
var requiredScheduleFields = {
|
|
7989
|
+
daily: ["timeOfDay", "timezoneId"],
|
|
7990
|
+
hourly: [],
|
|
7991
|
+
weekly: ["dayOfWeek", "timeOfDay", "timezoneId"]
|
|
7992
|
+
};
|
|
7993
|
+
var cadencesUsingField = {
|
|
7994
|
+
dayOfWeek: "a weekly cadence",
|
|
7995
|
+
minuteOfHour: "an hourly cadence",
|
|
7996
|
+
timeOfDay: "a daily or weekly cadence",
|
|
7997
|
+
timezoneId: "a daily or weekly cadence"
|
|
7998
|
+
};
|
|
7999
|
+
var scheduleFields = [
|
|
8000
|
+
"dayOfWeek",
|
|
8001
|
+
"minuteOfHour",
|
|
8002
|
+
"timeOfDay",
|
|
8003
|
+
"timezoneId"
|
|
8004
|
+
];
|
|
8005
|
+
var checkScheduleFields = (value, ctx) => {
|
|
8006
|
+
const required = requiredScheduleFields[value.cadence];
|
|
8007
|
+
for (const field of scheduleFields) {
|
|
8008
|
+
const isSupplied = value[field] !== undefined;
|
|
8009
|
+
if (required.includes(field)) {
|
|
8010
|
+
if (!isSupplied) {
|
|
8011
|
+
ctx.addIssue({
|
|
8012
|
+
code: "custom",
|
|
8013
|
+
message: `${field} is required when cadence is ${value.cadence}.`,
|
|
8014
|
+
path: [field]
|
|
8015
|
+
});
|
|
8016
|
+
}
|
|
8017
|
+
continue;
|
|
8018
|
+
}
|
|
8019
|
+
if (isSupplied && !(value.cadence === "hourly" && field === "minuteOfHour")) {
|
|
8020
|
+
ctx.addIssue({
|
|
8021
|
+
code: "custom",
|
|
8022
|
+
message: `${field} applies to ${cadencesUsingField[field]} only.`,
|
|
8023
|
+
path: [field]
|
|
8024
|
+
});
|
|
8025
|
+
}
|
|
8026
|
+
}
|
|
8027
|
+
};
|
|
8028
|
+
var checkSchedule = (value, ctx) => {
|
|
8029
|
+
checkScheduleFields(value, ctx);
|
|
8030
|
+
if (value.action.kind === "generativeSuite") {
|
|
8031
|
+
ctx.addIssue({
|
|
8032
|
+
code: "custom",
|
|
8033
|
+
message: "A schedule trigger cannot use a generativeSuite action.",
|
|
8034
|
+
path: ["action", "kind"]
|
|
8035
|
+
});
|
|
8036
|
+
return;
|
|
8037
|
+
}
|
|
8038
|
+
checkAction(value.action, ctx);
|
|
8039
|
+
};
|
|
8040
|
+
var checkDeployment = (value, ctx) => {
|
|
8041
|
+
if (value.environmentPattern !== undefined && value.environmentIds.length > 0) {
|
|
8042
|
+
ctx.addIssue({
|
|
8043
|
+
code: "custom",
|
|
8044
|
+
message: "Supply environmentIds or environmentPattern, not both.",
|
|
8045
|
+
path: ["environmentPattern"]
|
|
8046
|
+
});
|
|
8047
|
+
}
|
|
8048
|
+
checkAction(value.action, ctx);
|
|
8049
|
+
};
|
|
8050
|
+
var checkTriggerConfiguration = (value, ctx) => value.kind === "schedule" ? checkSchedule(value, ctx) : checkDeployment(value, ctx);
|
|
8051
|
+
|
|
7681
8052
|
// node_modules/@qawolf/api-contracts/dist/v1/trigger/resource.js
|
|
7682
8053
|
var makeTriggerConfigurationSchema = (ids) => discriminatedUnion("kind", [
|
|
7683
8054
|
object({
|
|
@@ -7707,19 +8078,51 @@ var makeTriggerResourceSchema = (ids) => resource({
|
|
|
7707
8078
|
pausedAt: exports_iso.datetime().optional().describe("When it was paused."),
|
|
7708
8079
|
updatedAt: exports_iso.datetime()
|
|
7709
8080
|
}, { urlFieldDescription: "Absolute URL of the team's triggers page." });
|
|
7710
|
-
|
|
7711
|
-
|
|
8081
|
+
|
|
8082
|
+
// node_modules/@qawolf/api-contracts/dist/v1/trigger/create.js
|
|
8083
|
+
var makeCreateTriggerContract = (ids) => {
|
|
8084
|
+
const commonFields = {
|
|
8085
|
+
name: string2().trim().min(1).max(255),
|
|
8086
|
+
workspaceId: ids.workspace.optional().describe("The workspace to create the trigger in. Required when authenticating with an organization or user API key.")
|
|
8087
|
+
};
|
|
8088
|
+
const input = discriminatedUnion("kind", [
|
|
8089
|
+
object({
|
|
8090
|
+
...commonFields,
|
|
8091
|
+
...makeTriggerScheduleFields({
|
|
8092
|
+
environmentId: ids.environmentRef,
|
|
8093
|
+
flow: ids.flow
|
|
8094
|
+
}),
|
|
8095
|
+
kind: literal("schedule")
|
|
8096
|
+
}),
|
|
8097
|
+
object({
|
|
8098
|
+
...commonFields,
|
|
8099
|
+
...makeTriggerDeploymentFields(ids),
|
|
8100
|
+
kind: literal("deployment")
|
|
8101
|
+
})
|
|
8102
|
+
]).superRefine(checkTriggerConfiguration);
|
|
8103
|
+
const output = object({ trigger: makeTriggerResourceSchema(ids) });
|
|
8104
|
+
return {
|
|
8105
|
+
annotations: {
|
|
8106
|
+
destructiveHint: true,
|
|
8107
|
+
openWorldHint: true,
|
|
8108
|
+
readOnlyHint: false
|
|
8109
|
+
},
|
|
8110
|
+
description: "Create a trigger. A schedule trigger runs a named set of flows on a cadence; " + "a deployment trigger runs when a matching deployment is reported.",
|
|
8111
|
+
input,
|
|
8112
|
+
kind: "write",
|
|
8113
|
+
name: "trigger.create",
|
|
8114
|
+
output
|
|
8115
|
+
};
|
|
8116
|
+
};
|
|
8117
|
+
|
|
8118
|
+
// node_modules/@qawolf/api-contracts/dist/v1/trigger/find.js
|
|
8119
|
+
var makeFindTriggersContract = (ids) => {
|
|
7712
8120
|
const input = object({
|
|
7713
|
-
|
|
7714
|
-
|
|
8121
|
+
isPaused: boolean2().optional().describe("Only list paused, or only unpaused, triggers. Omit for both."),
|
|
8122
|
+
workspaceId: ids.workspace.optional().describe("The workspace to list triggers from. Required when authenticating with an organization or user API key.")
|
|
7715
8123
|
});
|
|
7716
|
-
const output =
|
|
7717
|
-
|
|
7718
|
-
replies: array(agentReplySchema).describe("What the AI has said since the cursor, oldest first. A reply still being written returns again, longer. A reply carrying choices is a question the work is blocked on."),
|
|
7719
|
-
sessionId: ids.chatSession,
|
|
7720
|
-
status: agentSessionStatusSchema
|
|
7721
|
-
}, {
|
|
7722
|
-
urlFieldDescription: "Absolute URL of the live session in the QA Wolf app."
|
|
8124
|
+
const output = object({
|
|
8125
|
+
triggers: array(makeTriggerResourceSchema(ids)).describe("The team's triggers, newest first.")
|
|
7723
8126
|
});
|
|
7724
8127
|
return {
|
|
7725
8128
|
annotations: {
|
|
@@ -7727,23 +8130,172 @@ var makeAgentGetContract = (ids) => {
|
|
|
7727
8130
|
openWorldHint: false,
|
|
7728
8131
|
readOnlyHint: true
|
|
7729
8132
|
},
|
|
7730
|
-
description:
|
|
8133
|
+
description: "List the team's triggers, newest first.",
|
|
7731
8134
|
input,
|
|
7732
8135
|
kind: "read",
|
|
7733
|
-
name: "
|
|
8136
|
+
name: "trigger.find",
|
|
7734
8137
|
output
|
|
7735
8138
|
};
|
|
7736
8139
|
};
|
|
7737
8140
|
|
|
7738
|
-
// node_modules/@qawolf/api-contracts/dist/v1/
|
|
7739
|
-
var
|
|
7740
|
-
const input = object({
|
|
7741
|
-
|
|
7742
|
-
|
|
7743
|
-
|
|
7744
|
-
|
|
7745
|
-
|
|
7746
|
-
|
|
8141
|
+
// node_modules/@qawolf/api-contracts/dist/v1/trigger/get.js
|
|
8142
|
+
var makeGetTriggerContract = (ids) => {
|
|
8143
|
+
const input = object({ triggerId: ids.trigger });
|
|
8144
|
+
const output = object({ trigger: makeTriggerResourceSchema(ids) });
|
|
8145
|
+
return {
|
|
8146
|
+
annotations: {
|
|
8147
|
+
destructiveHint: false,
|
|
8148
|
+
openWorldHint: false,
|
|
8149
|
+
readOnlyHint: true
|
|
8150
|
+
},
|
|
8151
|
+
description: "Get one trigger by id.",
|
|
8152
|
+
input,
|
|
8153
|
+
kind: "read",
|
|
8154
|
+
name: "trigger.get",
|
|
8155
|
+
output
|
|
8156
|
+
};
|
|
8157
|
+
};
|
|
8158
|
+
|
|
8159
|
+
// node_modules/@qawolf/api-contracts/dist/v1/trigger/lifecycle.js
|
|
8160
|
+
var makePauseTriggerContract = (ids) => {
|
|
8161
|
+
const input = object({ triggerId: ids.trigger });
|
|
8162
|
+
const output = object({ trigger: makeTriggerResourceSchema(ids) });
|
|
8163
|
+
return {
|
|
8164
|
+
annotations: {
|
|
8165
|
+
destructiveHint: true,
|
|
8166
|
+
openWorldHint: false,
|
|
8167
|
+
readOnlyHint: false
|
|
8168
|
+
},
|
|
8169
|
+
description: "Pause a trigger so it stops firing. Pausing is idempotent. A team whose " + "triggers are all paused reports no trigger activity at all.",
|
|
8170
|
+
input,
|
|
8171
|
+
kind: "write",
|
|
8172
|
+
name: "trigger.pause",
|
|
8173
|
+
output
|
|
8174
|
+
};
|
|
8175
|
+
};
|
|
8176
|
+
var makeResumeTriggerContract = (ids) => {
|
|
8177
|
+
const input = object({ triggerId: ids.trigger });
|
|
8178
|
+
const output = object({ trigger: makeTriggerResourceSchema(ids) });
|
|
8179
|
+
return {
|
|
8180
|
+
annotations: {
|
|
8181
|
+
destructiveHint: true,
|
|
8182
|
+
openWorldHint: true,
|
|
8183
|
+
readOnlyHint: false
|
|
8184
|
+
},
|
|
8185
|
+
description: "Resume a paused trigger. A schedule trigger restarts from the next " + "upcoming slot: the slots it missed while paused do not run.",
|
|
8186
|
+
input,
|
|
8187
|
+
kind: "write",
|
|
8188
|
+
name: "trigger.resume",
|
|
8189
|
+
output
|
|
8190
|
+
};
|
|
8191
|
+
};
|
|
8192
|
+
var makeDeleteTriggerContract = (ids) => {
|
|
8193
|
+
const input = object({ triggerId: ids.trigger });
|
|
8194
|
+
const output = object({
|
|
8195
|
+
triggerId: ids.trigger.describe("The id of the deleted trigger.")
|
|
8196
|
+
});
|
|
8197
|
+
return {
|
|
8198
|
+
annotations: {
|
|
8199
|
+
destructiveHint: true,
|
|
8200
|
+
openWorldHint: false,
|
|
8201
|
+
readOnlyHint: false
|
|
8202
|
+
},
|
|
8203
|
+
description: "Delete a trigger permanently. The runs it already created are kept. " + "To stop a trigger without losing it, use trigger.pause.",
|
|
8204
|
+
input,
|
|
8205
|
+
kind: "write",
|
|
8206
|
+
name: "trigger.delete",
|
|
8207
|
+
output
|
|
8208
|
+
};
|
|
8209
|
+
};
|
|
8210
|
+
|
|
8211
|
+
// node_modules/@qawolf/api-contracts/dist/v1/trigger/update.js
|
|
8212
|
+
var makeUpdateTriggerContract = (ids) => {
|
|
8213
|
+
const commonFields = {
|
|
8214
|
+
name: string2().trim().min(1).max(255),
|
|
8215
|
+
triggerId: ids.trigger
|
|
8216
|
+
};
|
|
8217
|
+
const input = discriminatedUnion("kind", [
|
|
8218
|
+
object({
|
|
8219
|
+
...commonFields,
|
|
8220
|
+
...makeTriggerScheduleFields({
|
|
8221
|
+
environmentId: ids.environmentRef,
|
|
8222
|
+
flow: ids.flow
|
|
8223
|
+
}),
|
|
8224
|
+
kind: literal("schedule")
|
|
8225
|
+
}),
|
|
8226
|
+
object({
|
|
8227
|
+
...commonFields,
|
|
8228
|
+
...makeTriggerDeploymentFields(ids),
|
|
8229
|
+
kind: literal("deployment")
|
|
8230
|
+
})
|
|
8231
|
+
]).superRefine(checkTriggerConfiguration);
|
|
8232
|
+
const output = object({ trigger: makeTriggerResourceSchema(ids) });
|
|
8233
|
+
return {
|
|
8234
|
+
annotations: {
|
|
8235
|
+
destructiveHint: true,
|
|
8236
|
+
openWorldHint: true,
|
|
8237
|
+
readOnlyHint: false
|
|
8238
|
+
},
|
|
8239
|
+
description: "Replace a trigger's configuration. Every field is written, so read the " + "trigger first and send its configuration back with your changes applied. " + "Pausing is separate: use trigger.pause and trigger.resume.",
|
|
8240
|
+
input,
|
|
8241
|
+
kind: "write",
|
|
8242
|
+
name: "trigger.update",
|
|
8243
|
+
output
|
|
8244
|
+
};
|
|
8245
|
+
};
|
|
8246
|
+
|
|
8247
|
+
// node_modules/@qawolf/api-contracts/dist/v1/trigger/index.js
|
|
8248
|
+
var makeTriggerContracts = (ids) => ({
|
|
8249
|
+
create: makeCreateTriggerContract(ids),
|
|
8250
|
+
delete: makeDeleteTriggerContract(ids),
|
|
8251
|
+
find: makeFindTriggersContract(ids),
|
|
8252
|
+
get: makeGetTriggerContract(ids),
|
|
8253
|
+
pause: makePauseTriggerContract(ids),
|
|
8254
|
+
resume: makeResumeTriggerContract(ids),
|
|
8255
|
+
update: makeUpdateTriggerContract(ids)
|
|
8256
|
+
});
|
|
8257
|
+
// node_modules/@qawolf/api-contracts/dist/v1/agent/get.js
|
|
8258
|
+
var makeAgentGetContract = (ids) => {
|
|
8259
|
+
const input = object({
|
|
8260
|
+
cursor: string2().min(1).optional().describe("Opaque cursor copied from this same session's previous nextCursor. Omit to read from its first reply."),
|
|
8261
|
+
sessionId: ids.chatSession.describe("The id agent.send answered with."),
|
|
8262
|
+
waitSeconds: number2().int().min(0).optional().describe(`How long the server may hold this check open, in seconds. Omit or pass 0 to answer at once. A larger value clamps to ${maxAgentWaitSeconds}. Check again as soon as a held check returns.`)
|
|
8263
|
+
});
|
|
8264
|
+
const output = resource({
|
|
8265
|
+
nextCursor: string2().min(1).describe("Send back as cursor on the next check to read only what follows. Always present, even with no replies. Belongs to this session alone."),
|
|
8266
|
+
replies: array(agentReplySchema).describe("What the AI has said since the cursor, oldest first. A reply still being written returns again, longer. A reply carrying choices is a question the work is blocked on."),
|
|
8267
|
+
sessionId: ids.chatSession,
|
|
8268
|
+
status: agentSessionStatusSchema,
|
|
8269
|
+
waitSeconds: number2().int().optional().describe("The hold this check was allowed, in seconds, after clamping. Absent when the check did not wait."),
|
|
8270
|
+
wokeOn: agentWakeReasonSchema.optional().describe('Why this check answered when it did. Absent when the check did not wait. "timeout" means nothing new: replies is empty and nextCursor unchanged, so check again with the same cursor.')
|
|
8271
|
+
}, {
|
|
8272
|
+
urlFieldDescription: "Absolute URL of the live session in the QA Wolf app."
|
|
8273
|
+
});
|
|
8274
|
+
return {
|
|
8275
|
+
annotations: {
|
|
8276
|
+
destructiveHint: false,
|
|
8277
|
+
openWorldHint: false,
|
|
8278
|
+
readOnlyHint: true
|
|
8279
|
+
},
|
|
8280
|
+
description: 'Monitor a QA Wolf AI session by reading its status and replies. After agent.send, share the returned session URL before monitoring. Pass waitSeconds 45 so the server holds the check open and answers the moment something happens. Check again as soon as it returns; never sleep between checks or loop without waitSeconds. Pass the nextCursor from one response as the cursor on the next check; it then reads only what is new, and only for the session that minted it. Continue monitoring silently when the status is unchanged and no replies come back; do not narrate waiting, announce the next check, or ask whether to keep monitoring. Report only substantive new progress, questions, blockers, or the final outcome. A status of "waiting-for-you" means the last reply is a question the work is blocked on, and answering it with agent.send is what unblocks it. Surface an explicit request for user input even if the status still says "working". Include the session URL when reporting a blocker or final outcome. On "completed", stop status checks and verify the requested result before claiming success. For new flows, validation, publication in the target environment, and readiness are separate checks; a Git push or final reply does not prove the flow is active. If every requested result is verified but status remains "working", report the mismatch and stop monitoring. Stop on "failed" or "cancelled" and report any confirmed partial result.',
|
|
8281
|
+
input,
|
|
8282
|
+
kind: "read",
|
|
8283
|
+
name: "agent.get",
|
|
8284
|
+
output
|
|
8285
|
+
};
|
|
8286
|
+
};
|
|
8287
|
+
|
|
8288
|
+
// node_modules/@qawolf/api-contracts/dist/v1/agent/send.js
|
|
8289
|
+
var makeAgentSendContract = (ids) => {
|
|
8290
|
+
const input = object({
|
|
8291
|
+
environmentId: ids.environmentRef.optional().describe("The environment to work in. Omit to use the team's default environment. Ignored when sessionId is given, because a session keeps the environment it opened in."),
|
|
8292
|
+
filePaths: array(teamStoragePathSchema).max(20).optional().describe("Paths of files this request is about, from file.requestUpload. The AI reads them from storage rather than the message, so a plan of hundreds of journeys costs nothing to send."),
|
|
8293
|
+
message: string2().trim().min(1).max(1e4).describe("What you want QA Wolf to do, in plain language. Name the journey, the part of the app it covers, and anything the AI cannot discover for itself, such as a test account, a feature flag, or how to reach a staging environment. When answering a question from agent.get, send the answer here."),
|
|
8294
|
+
parentSessionId: ids.chatSession.optional().describe("The session that is starting this one. QA Wolf lists the new session underneath it, so whoever is watching that session can open the work it handed out. The session you name must not itself have been started this way, because a sub-session cannot start sub-sessions of its own. Ignored when sessionId is given, since continuing a session does not change what started it."),
|
|
8295
|
+
runnerId: runnerIdSchema.optional().describe("The runner you explored on, from runner.launch. Pass it to hand that browser to QA Wolf instead of having a fresh one started, so the pages you opened and any sign-in the user completed there are carried over. Leave the runner running: QA Wolf takes it over and terminates it when the work is done. Omit this when you have no runner, or when you already terminated it."),
|
|
8296
|
+
sessionId: ids.chatSession.optional().describe("Continue the session with this id instead of opening a new one. Omit to start fresh. Send this to answer a question or to add context to work already running."),
|
|
8297
|
+
workspaceId: ids.workspace.optional().describe("The workspace to work in. Required when authenticating with an organization or user API key.")
|
|
8298
|
+
});
|
|
7747
8299
|
const output = resource({
|
|
7748
8300
|
sessionId: ids.chatSession.describe("Follow the work by passing this to agent.get."),
|
|
7749
8301
|
status: agentSessionStatusSchema
|
|
@@ -7756,7 +8308,7 @@ var makeAgentSendContract = (ids) => {
|
|
|
7756
8308
|
openWorldHint: true,
|
|
7757
8309
|
readOnlyHint: false
|
|
7758
8310
|
},
|
|
7759
|
-
description: "Start or continue work with the QA Wolf AI and return a live session URL to share with the user. Use it to cover a user journey, investigate a failing run, or fix a broken flow. This is the one verb that starts work from nothing: every other write acts on a flow, run or issue that already exists. Returns sessionId, status, and url as soon as the request is accepted; work can take minutes to tens of minutes. After each send,
|
|
8311
|
+
description: "Start or continue work with the QA Wolf AI and return a live session URL to share with the user. Use it to cover a user journey, investigate a failing run, or fix a broken flow. This is the one verb that starts work from nothing: every other write acts on a flow, run or issue that already exists. Returns sessionId, status, and url as soon as the request is accepted; work can take minutes to tens of minutes. After each send, put the exact returned url in a normal user-visible assistant message, and repeat it in the last message of the turn: only a turn's trailing message is shown expanded. Tool output and internal reasoning do not count as sharing the link. Do not run a timer or monitoring call alongside this send. Acceptance does not mean the work is complete. Then monitor the session with agent.get, reporting new progress, blockers, and the final outcome rather than unchanged status. Send here again to answer a question or add context to the same session.",
|
|
7760
8312
|
input,
|
|
7761
8313
|
kind: "write",
|
|
7762
8314
|
name: "agent.send",
|
|
@@ -7764,25 +8316,40 @@ var makeAgentSendContract = (ids) => {
|
|
|
7764
8316
|
};
|
|
7765
8317
|
};
|
|
7766
8318
|
|
|
7767
|
-
// node_modules/@qawolf/api-contracts/dist/v1/
|
|
7768
|
-
var
|
|
8319
|
+
// node_modules/@qawolf/api-contracts/dist/v1/codeHostIntegration/resource.js
|
|
8320
|
+
var makeCodeHostIntegrationResourceSchema = () => resource({
|
|
8321
|
+
connectedAt: exports_iso.datetime().describe("When the code host was connected to the workspace."),
|
|
8322
|
+
provider: _enum(["github", "gitlab"]).describe("The code host this integration connects."),
|
|
8323
|
+
suspendedAt: exports_iso.datetime().optional().describe("Set while GitHub has the QA Wolf app installation suspended. While suspended, GitHub sends QA Wolf no webhooks.")
|
|
8324
|
+
}, {
|
|
8325
|
+
urlFieldDescription: "Absolute URL of the workspace's integrations settings page."
|
|
8326
|
+
});
|
|
8327
|
+
var makeCodeHostRepositoryResourceSchema = () => resource({
|
|
8328
|
+
fullName: string2().describe(`The repository's full name on the code host, such as "acme/storefront".`),
|
|
8329
|
+
provider: _enum(["github", "gitlab"]).describe("The code host the covering integration connects.")
|
|
8330
|
+
}, {
|
|
8331
|
+
urlFieldDescription: "Absolute URL of the workspace's integrations settings page."
|
|
8332
|
+
});
|
|
8333
|
+
|
|
8334
|
+
// node_modules/@qawolf/api-contracts/dist/v1/codeHostIntegration/find.js
|
|
8335
|
+
var makeFindCodeHostIntegrationsContract = (ids) => {
|
|
7769
8336
|
const input = object({
|
|
7770
|
-
|
|
7771
|
-
|
|
7772
|
-
|
|
7773
|
-
|
|
8337
|
+
workspaceId: ids.workspace.optional().describe("The workspace to list code host integrations from. Required when authenticating with an organization or user API key.")
|
|
8338
|
+
});
|
|
8339
|
+
const output = object({
|
|
8340
|
+
integrations: array(makeCodeHostIntegrationResourceSchema()).describe("The workspace's code host integrations. Empty when no code host is connected."),
|
|
8341
|
+
settingsUrl: url().describe("Absolute URL of the workspace's integrations settings page.")
|
|
7774
8342
|
});
|
|
7775
|
-
const output = resource({ automationId: ids.automation }, { urlFieldDescription: "Absolute URL of the automation review page." });
|
|
7776
8343
|
return {
|
|
7777
8344
|
annotations: {
|
|
7778
|
-
destructiveHint:
|
|
7779
|
-
openWorldHint:
|
|
7780
|
-
readOnlyHint:
|
|
8345
|
+
destructiveHint: false,
|
|
8346
|
+
openWorldHint: false,
|
|
8347
|
+
readOnlyHint: true
|
|
7781
8348
|
},
|
|
7782
|
-
description: "
|
|
8349
|
+
description: "List the workspace's code host integrations (GitHub or GitLab). A connected integration lets QA Wolf read repositories and receive the code host's webhooks. codeHostIntegration.listRepositories pages the repositories each integration covers.",
|
|
7783
8350
|
input,
|
|
7784
|
-
kind: "
|
|
7785
|
-
name: "
|
|
8351
|
+
kind: "read",
|
|
8352
|
+
name: "codeHostIntegration.find",
|
|
7786
8353
|
output
|
|
7787
8354
|
};
|
|
7788
8355
|
};
|
|
@@ -7794,6 +8361,221 @@ var makePaginationInputFields = (limits) => ({
|
|
|
7794
8361
|
});
|
|
7795
8362
|
var nextCursorSchema = string2().min(1).optional().describe("Repeat the request with this value as cursor to fetch the next page. Absent when there are no further results.");
|
|
7796
8363
|
|
|
8364
|
+
// node_modules/@qawolf/api-contracts/dist/v1/codeHostIntegration/listRepositories.js
|
|
8365
|
+
var makeListCodeHostRepositoriesContract = (ids) => {
|
|
8366
|
+
const input = object({
|
|
8367
|
+
provider: _enum(["github", "gitlab"]).optional().describe("Only list repositories covered by this code host's integration. Omit for all."),
|
|
8368
|
+
workspaceId: ids.workspace.optional().describe("The workspace to list covered repositories from. Required when authenticating with an organization or user API key."),
|
|
8369
|
+
...makePaginationInputFields({ defaultLimit: 20, maxLimit: 100 })
|
|
8370
|
+
});
|
|
8371
|
+
const output = object({
|
|
8372
|
+
nextCursor: nextCursorSchema,
|
|
8373
|
+
repositories: array(makeCodeHostRepositoryResourceSchema()).describe("The repositories the workspace's code host integrations cover, alphabetical by full name.")
|
|
8374
|
+
});
|
|
8375
|
+
return {
|
|
8376
|
+
annotations: {
|
|
8377
|
+
destructiveHint: false,
|
|
8378
|
+
openWorldHint: false,
|
|
8379
|
+
readOnlyHint: true
|
|
8380
|
+
},
|
|
8381
|
+
description: "List the repositories the workspace's code host integrations cover, alphabetical by full name. The list reflects the last sync from the code host; codeHostIntegration.find lists the integrations themselves.",
|
|
8382
|
+
input,
|
|
8383
|
+
kind: "read",
|
|
8384
|
+
name: "codeHostIntegration.listRepositories",
|
|
8385
|
+
output
|
|
8386
|
+
};
|
|
8387
|
+
};
|
|
8388
|
+
|
|
8389
|
+
// node_modules/@qawolf/api-contracts/dist/v1/deployment/resource.js
|
|
8390
|
+
var makeDeploymentResourceSchema = (ids) => resource({
|
|
8391
|
+
branch: string2().optional().describe("The git branch the deployed commit is on. Absent when neither the deployer nor the code host declared one."),
|
|
8392
|
+
commitAuthorName: string2().optional().describe("The author of the deployed commit."),
|
|
8393
|
+
commitMessage: string2().optional().describe("The message of the deployed commit."),
|
|
8394
|
+
commitSha: string2().optional().describe("The sha of the deployed commit."),
|
|
8395
|
+
deployedAt: exports_iso.datetime().describe("When QA Wolf first received the deployment."),
|
|
8396
|
+
deployTarget: string2().optional().describe("Identifies the deployed app within the environment: the URL it serves, or the build path of a mobile build. A trigger's deployTargetPattern matches against it."),
|
|
8397
|
+
environmentId: ids.environment.describe("The QA Wolf environment the deployment reported into."),
|
|
8398
|
+
environmentName: string2().optional().describe("The environment's name. Absent when the environment has since been deleted."),
|
|
8399
|
+
id: ids.deployment,
|
|
8400
|
+
provider: _enum(["github", "gitlab", "api"]).optional().describe("How QA Wolf received the deployment: a GitHub webhook, a GitLab webhook, or the deployment.reportStatus API."),
|
|
8401
|
+
status: _enum(["pending", "success", "failure", "inactive"]).optional().describe("The deployment's lifecycle status, in the vocabulary deployment.reportStatus accepts. Absent when no status was ever reported.")
|
|
8402
|
+
}, {
|
|
8403
|
+
urlFieldDescription: "Absolute URL of the workspace's deployments page."
|
|
8404
|
+
});
|
|
8405
|
+
|
|
8406
|
+
// node_modules/@qawolf/api-contracts/dist/v1/deployment/find.js
|
|
8407
|
+
var makeFindDeploymentsContract = (ids) => {
|
|
8408
|
+
const input = object({
|
|
8409
|
+
workspaceId: ids.workspace.optional().describe("The workspace to list deployments from. Required when authenticating with an organization or user API key."),
|
|
8410
|
+
...makePaginationInputFields({ defaultLimit: 20, maxLimit: 100 })
|
|
8411
|
+
});
|
|
8412
|
+
const output = object({
|
|
8413
|
+
deployments: array(makeDeploymentResourceSchema(ids)).describe("The workspace's deployments, newest first."),
|
|
8414
|
+
nextCursor: nextCursorSchema
|
|
8415
|
+
});
|
|
8416
|
+
return {
|
|
8417
|
+
annotations: {
|
|
8418
|
+
destructiveHint: false,
|
|
8419
|
+
openWorldHint: false,
|
|
8420
|
+
readOnlyHint: true
|
|
8421
|
+
},
|
|
8422
|
+
description: "List the deployments QA Wolf has received for the workspace, newest first. A deployment arrives through a code host integration's webhook or through deployment.reportStatus, and is what a deployment trigger evaluates against. deployment.listTriggerEvaluations reports each trigger's verdict for one deployment.",
|
|
8423
|
+
input,
|
|
8424
|
+
kind: "read",
|
|
8425
|
+
name: "deployment.find",
|
|
8426
|
+
output
|
|
8427
|
+
};
|
|
8428
|
+
};
|
|
8429
|
+
|
|
8430
|
+
// node_modules/@qawolf/api-contracts/dist/v1/deployment/listTriggerEvaluations.js
|
|
8431
|
+
var conditionKindSchema = _enum(["environment", "deployTarget", "branch"]).describe("What the condition checks on the deployment: the environment it reported into, the deploy target identifying the deployed app, or the git branch of the deployed commit.");
|
|
8432
|
+
var conditionVerdictSchema = discriminatedUnion("outcome", [
|
|
8433
|
+
object({
|
|
8434
|
+
kind: conditionKindSchema,
|
|
8435
|
+
outcome: literal("matched")
|
|
8436
|
+
}),
|
|
8437
|
+
object({
|
|
8438
|
+
kind: conditionKindSchema,
|
|
8439
|
+
outcome: literal("did-not-match"),
|
|
8440
|
+
reason: string2().describe("Why the condition did not match this deployment, in plain language.")
|
|
8441
|
+
})
|
|
8442
|
+
]);
|
|
8443
|
+
var conditionSetsField = array(object({
|
|
8444
|
+
conditions: array(conditionVerdictSchema).describe("One verdict per condition. Conditions in a set are ANDed; a set with no conditions matches every deployment."),
|
|
8445
|
+
outcome: _enum(["matched", "did-not-match"]).describe("Whether every condition in the set matched.")
|
|
8446
|
+
})).describe("The trigger's condition sets as they were when the deployment was evaluated, each with per-condition verdicts. Sets are ORed: the trigger matches when any one set matches. Most triggers have exactly one set.");
|
|
8447
|
+
var makeRunOutcomeSchema = (ids) => discriminatedUnion("status", [
|
|
8448
|
+
object({
|
|
8449
|
+
runId: ids.run.describe("The run the trigger created."),
|
|
8450
|
+
status: literal("ran")
|
|
8451
|
+
}),
|
|
8452
|
+
object({ status: literal("starting") }),
|
|
8453
|
+
object({
|
|
8454
|
+
reason: string2().describe("Why the matched trigger created no run, in plain language."),
|
|
8455
|
+
status: literal("did-not-run"),
|
|
8456
|
+
supersededByRunId: ids.run.optional().describe("The run that covered this deployment instead, when an earlier delivery of the same deployment had already created one.")
|
|
8457
|
+
}),
|
|
8458
|
+
object({ status: literal("unknown") })
|
|
8459
|
+
]).describe("What became of the match. Matching is not running: a matched trigger can still be stopped from creating a run, and did-not-run carries the reason. starting means run creation is still in progress; unknown means QA Wolf has no record of what followed the match.");
|
|
8460
|
+
var makeVerdictSchema = (ids) => discriminatedUnion("outcome", [
|
|
8461
|
+
object({
|
|
8462
|
+
conditionSets: conditionSetsField,
|
|
8463
|
+
outcome: literal("matched"),
|
|
8464
|
+
run: makeRunOutcomeSchema(ids)
|
|
8465
|
+
}),
|
|
8466
|
+
object({
|
|
8467
|
+
conditionSets: conditionSetsField,
|
|
8468
|
+
outcome: literal("did-not-match")
|
|
8469
|
+
}),
|
|
8470
|
+
object({
|
|
8471
|
+
outcome: literal("not-considered"),
|
|
8472
|
+
reason: _enum(["trigger-paused", "not-a-deployment-trigger"]).describe("Why the conditions were never checked. trigger-paused: the trigger was paused when the deployment was evaluated. not-a-deployment-trigger: the trigger has no deployment conditions (a schedule trigger, for example), so no deployment can fire it.")
|
|
8473
|
+
})
|
|
8474
|
+
]).describe("The trigger's verdict for this deployment: matched, did-not-match with per-condition verdicts, or not-considered when the conditions were never checked at all.");
|
|
8475
|
+
var makeEvaluationSchema = (ids) => object({
|
|
8476
|
+
triggerId: ids.trigger.optional().describe("Absent when the trigger has been deleted since."),
|
|
8477
|
+
triggerName: string2().describe("The trigger's name when the deployment was evaluated."),
|
|
8478
|
+
verdict: makeVerdictSchema(ids)
|
|
8479
|
+
});
|
|
8480
|
+
var makeListDeploymentTriggerEvaluationsContract = (ids) => {
|
|
8481
|
+
const input = object({ deploymentId: ids.deployment });
|
|
8482
|
+
const output = discriminatedUnion("state", [
|
|
8483
|
+
object({
|
|
8484
|
+
evaluations: array(makeEvaluationSchema(ids)).describe("One verdict per trigger that existed when the deployment was evaluated."),
|
|
8485
|
+
state: literal("evaluated")
|
|
8486
|
+
}),
|
|
8487
|
+
object({ state: literal("not-evaluated") }).describe("Triggers were never evaluated for this deployment. Only a deployment's first success report evaluates triggers, so a deployment that never reported success carries no verdicts.")
|
|
8488
|
+
]);
|
|
8489
|
+
return {
|
|
8490
|
+
annotations: {
|
|
8491
|
+
destructiveHint: false,
|
|
8492
|
+
openWorldHint: false,
|
|
8493
|
+
readOnlyHint: true
|
|
8494
|
+
},
|
|
8495
|
+
description: "List the per-trigger verdicts recorded when a deployment was evaluated against the workspace's triggers. Each verdict says whether the trigger matched, did not match with the reason per condition, or was never considered and why. Verdicts are a snapshot from evaluation time: editing or deleting a trigger later does not change them.",
|
|
8496
|
+
input,
|
|
8497
|
+
kind: "read",
|
|
8498
|
+
name: "deployment.listTriggerEvaluations",
|
|
8499
|
+
output
|
|
8500
|
+
};
|
|
8501
|
+
};
|
|
8502
|
+
|
|
8503
|
+
// node_modules/@qawolf/api-contracts/dist/v1/deployment/reportStatusMetadata.js
|
|
8504
|
+
var deploymentReportMetadata = strictObject({
|
|
8505
|
+
commitAuthorName: string2().trim().min(1).max(255).describe("The display name of the person who authored the deployed commit.").optional(),
|
|
8506
|
+
commitMessage: string2().trim().min(1).max(2048).describe("The message of the deployed commit. The deployments list shows its first line.").optional(),
|
|
8507
|
+
commitSha: string2().trim().min(1).max(255).describe("The commit sha of the deployed application revision.").optional(),
|
|
8508
|
+
pullRequestNumber: number2().int().positive().describe("The number of the pull request the deployment belongs to. Requires repository.").optional(),
|
|
8509
|
+
ref: string2().trim().min(1).max(255).describe("The branch or ref that was deployed.").optional(),
|
|
8510
|
+
repository: string2().trim().min(1).max(255).describe('The owner/name of the repository, e.g. "acme/web".').optional()
|
|
8511
|
+
}).refine((value) => value.pullRequestNumber === undefined || value.repository !== undefined, {
|
|
8512
|
+
message: "repository is required when pullRequestNumber is provided.",
|
|
8513
|
+
path: ["pullRequestNumber"]
|
|
8514
|
+
});
|
|
8515
|
+
|
|
8516
|
+
// node_modules/@qawolf/api-contracts/dist/v1/deployment/reportStatus.js
|
|
8517
|
+
var deploymentStatusSchema = _enum([
|
|
8518
|
+
"pending",
|
|
8519
|
+
"success",
|
|
8520
|
+
"failure",
|
|
8521
|
+
"inactive"
|
|
8522
|
+
]);
|
|
8523
|
+
var makeReportDeploymentStatusContract = (ids) => {
|
|
8524
|
+
const environment = union([
|
|
8525
|
+
strictObject({
|
|
8526
|
+
id: ids.environment.describe("The id of an existing environment. Never creates an environment. Send an alias through name instead.")
|
|
8527
|
+
}),
|
|
8528
|
+
strictObject({
|
|
8529
|
+
baseEphemeralEnvironment: string2().trim().min(1).max(255).describe("The alias or name of the environment a created ephemeral environment copies from. Only valid with ephemeral. The server uses the team default base environment when no environment matches this value.").optional(),
|
|
8530
|
+
ephemeral: boolean2().describe("Requests an ephemeral environment when the name creates one. A name that matches an existing environment keeps that environment's kind.").optional(),
|
|
8531
|
+
name: string2().trim().min(1).max(255).describe("The provider deploy environment name. Resolves an environment by alias or name; creates one when no match exists.")
|
|
8532
|
+
})
|
|
8533
|
+
], {
|
|
8534
|
+
error: "Send environment as either { id } or { name }, with optional ephemeral and baseEphemeralEnvironment."
|
|
8535
|
+
});
|
|
8536
|
+
const input = strictObject({
|
|
8537
|
+
deployTarget: httpUrl().max(2048).describe("The URL the deployment serves, e.g. a preview URL.").optional(),
|
|
8538
|
+
environment: environment.describe("Selects the environment the deployment reports into.").optional(),
|
|
8539
|
+
environmentVariables: record(string2(), string2()).describe("Environment variable overrides for the runs this deployment requests. A report that omits this field keeps the stored values. A report that sends it replaces them.").optional(),
|
|
8540
|
+
metadata: deploymentReportMetadata.describe("Details the deployer declares about the deployed revision; a code host integration's own record of the same commit is shown in preference to the message and author declared here.").optional(),
|
|
8541
|
+
providerDeploymentId: string2().trim().min(1).max(255).describe('Your identifier for the deployment, e.g. "vercel_dpl_123". Reports with the same providerDeploymentId update one deployment within this workspace.'),
|
|
8542
|
+
status: deploymentStatusSchema.describe("The deployment lifecycle status. A deployment's first success report evaluates global triggers asynchronously, and it is the only report that does. The response does not include the resulting runs."),
|
|
8543
|
+
workspaceId: ids.workspace.describe("The workspace to report the deployment status into. A team API key must name its own workspace.")
|
|
8544
|
+
}).superRefine((value, context) => {
|
|
8545
|
+
if (value.environment !== undefined && "name" in value.environment && value.environment.baseEphemeralEnvironment !== undefined && value.environment.ephemeral !== true) {
|
|
8546
|
+
context.addIssue({
|
|
8547
|
+
code: "custom",
|
|
8548
|
+
message: "baseEphemeralEnvironment is only valid with ephemeral.",
|
|
8549
|
+
path: ["environment", "baseEphemeralEnvironment"]
|
|
8550
|
+
});
|
|
8551
|
+
}
|
|
8552
|
+
});
|
|
8553
|
+
const deployment = resource({
|
|
8554
|
+
id: ids.deployment,
|
|
8555
|
+
status: deploymentStatusSchema.describe("The status reported in this request.")
|
|
8556
|
+
}, { urlFieldDescription: "Absolute URL of the environment's runs page." });
|
|
8557
|
+
const output = object({ deployment });
|
|
8558
|
+
return {
|
|
8559
|
+
annotations: {
|
|
8560
|
+
destructiveHint: true,
|
|
8561
|
+
openWorldHint: true,
|
|
8562
|
+
readOnlyHint: false
|
|
8563
|
+
},
|
|
8564
|
+
description: "Report a deployment lifecycle status. A deployment's first success report evaluates global triggers asynchronously, and it is the only report that does: a trigger added or unpaused later does not make an already reported deployment evaluate again. Report that deployment under a new providerDeploymentId to evaluate it against the current triggers. The response contains the deployment only, not the resulting runs.",
|
|
8565
|
+
input,
|
|
8566
|
+
kind: "write",
|
|
8567
|
+
name: "deployment.reportStatus",
|
|
8568
|
+
output
|
|
8569
|
+
};
|
|
8570
|
+
};
|
|
8571
|
+
|
|
8572
|
+
// node_modules/@qawolf/api-contracts/dist/v1/deployment/index.js
|
|
8573
|
+
var makeDeploymentContracts = (ids) => ({
|
|
8574
|
+
find: makeFindDeploymentsContract(ids),
|
|
8575
|
+
listTriggerEvaluations: makeListDeploymentTriggerEvaluationsContract(ids),
|
|
8576
|
+
reportStatus: makeReportDeploymentStatusContract(ids)
|
|
8577
|
+
});
|
|
8578
|
+
|
|
7797
8579
|
// node_modules/@qawolf/api-contracts/dist/v1/email/find.js
|
|
7798
8580
|
var makeFindEmailsContract = (ids) => {
|
|
7799
8581
|
const input = object({
|
|
@@ -7961,29 +8743,6 @@ var makeSendEmailContract = (ids) => {
|
|
|
7961
8743
|
};
|
|
7962
8744
|
};
|
|
7963
8745
|
|
|
7964
|
-
// node_modules/@qawolf/api-contracts/dist/v1/environment/deleteVariable.js
|
|
7965
|
-
var makeDeleteEnvironmentVariableContract = (ids) => {
|
|
7966
|
-
const input = object({
|
|
7967
|
-
environmentId: ids.environmentRef,
|
|
7968
|
-
name: string2().trim().min(1, "Environment variable name cannot be blank.").max(255).describe("Name of the environment variable to remove. Canonicalized the same way as environment.setVariable, so the name that was set is the name that deletes.")
|
|
7969
|
-
});
|
|
7970
|
-
const output = object({
|
|
7971
|
-
name: string2().describe("The canonicalized name that was removed. Returned even when the environment had no such variable.")
|
|
7972
|
-
});
|
|
7973
|
-
return {
|
|
7974
|
-
annotations: {
|
|
7975
|
-
destructiveHint: true,
|
|
7976
|
-
openWorldHint: false,
|
|
7977
|
-
readOnlyHint: false
|
|
7978
|
-
},
|
|
7979
|
-
description: "Remove one environment variable by name. Succeeds whether or not the variable existed.",
|
|
7980
|
-
input,
|
|
7981
|
-
kind: "write",
|
|
7982
|
-
name: "environment.deleteVariable",
|
|
7983
|
-
output
|
|
7984
|
-
};
|
|
7985
|
-
};
|
|
7986
|
-
|
|
7987
8746
|
// node_modules/@qawolf/api-contracts/dist/v1/environment/resource.js
|
|
7988
8747
|
var makeEnvironmentResourceSchema = (ids) => resource({
|
|
7989
8748
|
alias: string2().optional().describe("The environment's alias: a team-unique slug that team API keys can use in place of the id. Terminated environments have none."),
|
|
@@ -8004,9 +8763,55 @@ var makeEnvironmentResourceSchema = (ids) => resource({
|
|
|
8004
8763
|
name: string2(),
|
|
8005
8764
|
runConcurrencyLimit: string2().describe('Maximum number of concurrent runs: a whole number, "unlimited", or a concurrency expression.'),
|
|
8006
8765
|
status: _enum(["blocked", "needs-investigation", "ready", "running"]).describe("Standing health across the environment's runs, not its Git reconciliation state: blocked (open blocking bugs), needs-investigation (failures awaiting triage), running (flows executing), ready (none of the above — the greenlit state)."),
|
|
8007
|
-
terminatedAt: exports_iso.datetime().optional().describe("When the environment was terminated, if it has been.")
|
|
8766
|
+
terminatedAt: exports_iso.datetime().optional().describe("When the environment was terminated, if it has been."),
|
|
8767
|
+
variablesUrl: url().optional().describe("Absolute URL of the page where a person saves this environment's variables. Give it to the user when a login or key is missing, rather than collecting the value yourself. Absent once the environment is terminated, because that page no longer exists.")
|
|
8008
8768
|
}, { urlFieldDescription: "Absolute URL of the environment page." });
|
|
8009
8769
|
|
|
8770
|
+
// node_modules/@qawolf/api-contracts/dist/v1/environment/create.js
|
|
8771
|
+
var makeCreateEnvironmentContract = (ids) => {
|
|
8772
|
+
const input = object({
|
|
8773
|
+
name: string2().min(1).max(255).regex(/\S/, "Environment name cannot be blank.").describe("Display name of the new environment."),
|
|
8774
|
+
workspaceId: ids.workspace.optional().describe("The workspace to create the environment in. Required when authenticating with an organization or user API key.")
|
|
8775
|
+
});
|
|
8776
|
+
const output = makeEnvironmentResourceSchema(ids);
|
|
8777
|
+
return {
|
|
8778
|
+
annotations: {
|
|
8779
|
+
destructiveHint: false,
|
|
8780
|
+
openWorldHint: true,
|
|
8781
|
+
readOnlyHint: false
|
|
8782
|
+
},
|
|
8783
|
+
description: "Create an environment on the caller's team and return it in the environment.get shape. This can also create a branch on the team's connected Git provider.",
|
|
8784
|
+
input,
|
|
8785
|
+
kind: "write",
|
|
8786
|
+
name: "environment.create",
|
|
8787
|
+
output
|
|
8788
|
+
};
|
|
8789
|
+
};
|
|
8790
|
+
|
|
8791
|
+
// node_modules/@qawolf/api-contracts/dist/v1/environment/deleteVariable.js
|
|
8792
|
+
var makeDeleteEnvironmentVariableContract = (ids) => {
|
|
8793
|
+
const input = object({
|
|
8794
|
+
environmentId: ids.environmentRef,
|
|
8795
|
+
name: string2().trim().min(1, "Environment variable name cannot be blank.").max(255).describe("Name of the environment variable to remove. Canonicalized the same way as environment.setVariable, so the name that was set is the name that deletes."),
|
|
8796
|
+
workspaceId: workspaceForEnvironmentRef(ids.workspace)
|
|
8797
|
+
});
|
|
8798
|
+
const output = object({
|
|
8799
|
+
name: string2().describe("The canonicalized name that was removed. Returned even when the environment had no such variable.")
|
|
8800
|
+
});
|
|
8801
|
+
return {
|
|
8802
|
+
annotations: {
|
|
8803
|
+
destructiveHint: true,
|
|
8804
|
+
openWorldHint: false,
|
|
8805
|
+
readOnlyHint: false
|
|
8806
|
+
},
|
|
8807
|
+
description: "Remove one environment variable by name. Succeeds whether or not the variable existed.",
|
|
8808
|
+
input,
|
|
8809
|
+
kind: "write",
|
|
8810
|
+
name: "environment.deleteVariable",
|
|
8811
|
+
output
|
|
8812
|
+
};
|
|
8813
|
+
};
|
|
8814
|
+
|
|
8010
8815
|
// node_modules/@qawolf/api-contracts/dist/v1/environment/find.js
|
|
8011
8816
|
var makeFindEnvironmentsContract = (ids) => {
|
|
8012
8817
|
const input = object({
|
|
@@ -8038,7 +8843,8 @@ var makeFindEnvironmentsContract = (ids) => {
|
|
|
8038
8843
|
var makeGetEnvironmentVariableContract = (ids) => {
|
|
8039
8844
|
const input = object({
|
|
8040
8845
|
environmentId: ids.environmentRef,
|
|
8041
|
-
variableNames: array(string2().min(1).max(255)).min(1).max(100).describe("Names of the environment variables to read. Names match exactly as environment.listVariableNames returns them. Request every name you need in a single call, up to 100 names per call.")
|
|
8846
|
+
variableNames: array(string2().min(1).max(255)).min(1).max(100).describe("Names of the environment variables to read. Names match exactly as environment.listVariableNames returns them. Request every name you need in a single call, up to 100 names per call."),
|
|
8847
|
+
workspaceId: workspaceForEnvironmentRef(ids.workspace)
|
|
8042
8848
|
});
|
|
8043
8849
|
const output = object({
|
|
8044
8850
|
missingNames: array(string2()).describe("Requested names the environment does not have, sorted alphabetically."),
|
|
@@ -8064,7 +8870,8 @@ var makeGetEnvironmentVariableContract = (ids) => {
|
|
|
8064
8870
|
// node_modules/@qawolf/api-contracts/dist/v1/environment/index.js
|
|
8065
8871
|
var makeGetEnvironmentContract = (ids) => {
|
|
8066
8872
|
const input = object({
|
|
8067
|
-
environmentId: ids.environmentRef
|
|
8873
|
+
environmentId: ids.environmentRef,
|
|
8874
|
+
workspaceId: workspaceForEnvironmentRef(ids.workspace)
|
|
8068
8875
|
});
|
|
8069
8876
|
const output = makeEnvironmentResourceSchema(ids);
|
|
8070
8877
|
return {
|
|
@@ -8082,7 +8889,8 @@ var makeGetEnvironmentContract = (ids) => {
|
|
|
8082
8889
|
};
|
|
8083
8890
|
var makeListEnvironmentVariableNamesContract = (ids) => {
|
|
8084
8891
|
const input = object({
|
|
8085
|
-
environmentId: ids.environmentRef
|
|
8892
|
+
environmentId: ids.environmentRef,
|
|
8893
|
+
workspaceId: workspaceForEnvironmentRef(ids.workspace)
|
|
8086
8894
|
});
|
|
8087
8895
|
const output = object({
|
|
8088
8896
|
variableNames: array(string2()).describe("Names of the environment's variables, sorted alphabetically. Values are never returned.")
|
|
@@ -8104,7 +8912,8 @@ var makeSetEnvironmentVariableContract = (ids) => {
|
|
|
8104
8912
|
const input = object({
|
|
8105
8913
|
environmentId: ids.environmentRef,
|
|
8106
8914
|
name: string2().trim().min(1, "Environment variable name cannot be blank.").max(255).describe("Name of the environment variable to create or replace. Leading and trailing whitespace is removed, remaining whitespace is replaced with underscores, and letters are uppercased."),
|
|
8107
|
-
value: string2().describe("Value to store. This secret value is accepted but never returned.")
|
|
8915
|
+
value: string2().describe("Value to store. This secret value is accepted but never returned."),
|
|
8916
|
+
workspaceId: workspaceForEnvironmentRef(ids.workspace)
|
|
8108
8917
|
});
|
|
8109
8918
|
const output = object({
|
|
8110
8919
|
name: string2().describe("The stored variable name after whitespace is replaced with underscores and letters are uppercased.")
|
|
@@ -8122,25 +8931,6 @@ var makeSetEnvironmentVariableContract = (ids) => {
|
|
|
8122
8931
|
output
|
|
8123
8932
|
};
|
|
8124
8933
|
};
|
|
8125
|
-
var makeCreateEnvironmentContract = (ids) => {
|
|
8126
|
-
const input = object({
|
|
8127
|
-
name: string2().min(1).max(255).regex(/\S/, "Environment name cannot be blank.").describe("Display name of the new environment."),
|
|
8128
|
-
workspaceId: ids.workspace.optional().describe("The workspace to create the environment in. Required when authenticating with an organization or user API key.")
|
|
8129
|
-
});
|
|
8130
|
-
const output = makeEnvironmentResourceSchema(ids);
|
|
8131
|
-
return {
|
|
8132
|
-
annotations: {
|
|
8133
|
-
destructiveHint: false,
|
|
8134
|
-
openWorldHint: true,
|
|
8135
|
-
readOnlyHint: false
|
|
8136
|
-
},
|
|
8137
|
-
description: "Create an environment on the caller's team and return it in the environment.get shape. This can also create a branch on the team's connected Git provider.",
|
|
8138
|
-
input,
|
|
8139
|
-
kind: "write",
|
|
8140
|
-
name: "environment.create",
|
|
8141
|
-
output
|
|
8142
|
-
};
|
|
8143
|
-
};
|
|
8144
8934
|
|
|
8145
8935
|
// node_modules/@qawolf/api-contracts/dist/v1/environment/update.js
|
|
8146
8936
|
var makeUpdateEnvironmentContract = (ids) => {
|
|
@@ -8149,7 +8939,8 @@ var makeUpdateEnvironmentContract = (ids) => {
|
|
|
8149
8939
|
const input = object({
|
|
8150
8940
|
environmentId: ids.environmentRef,
|
|
8151
8941
|
name: nameSchema.optional(),
|
|
8152
|
-
runConcurrencyLimit: runConcurrencyLimitSchema.optional()
|
|
8942
|
+
runConcurrencyLimit: runConcurrencyLimitSchema.optional(),
|
|
8943
|
+
workspaceId: workspaceForEnvironmentRef(ids.workspace)
|
|
8153
8944
|
}).refine((update) => update.name !== undefined || update.runConcurrencyLimit !== undefined, {
|
|
8154
8945
|
message: "At least one of name or runConcurrencyLimit is required."
|
|
8155
8946
|
});
|
|
@@ -8236,10 +9027,27 @@ var makeListFlowsContract = (ids) => {
|
|
|
8236
9027
|
const input = object({
|
|
8237
9028
|
aiTaskId: ids.aiTask.describe("List the flows on this AI task's branch, including drafts, instead of the ones in the environment. The task must belong to the environment.").optional(),
|
|
8238
9029
|
environmentId: ids.environmentRef,
|
|
8239
|
-
includeDrafts: boolean2().default(false).describe("Include draft flows in the listing.")
|
|
9030
|
+
includeDrafts: boolean2().default(false).describe("Include draft flows in the listing."),
|
|
9031
|
+
workspaceId: workspaceForEnvironmentRef(ids.workspace)
|
|
8240
9032
|
});
|
|
8241
9033
|
const executionTarget = union([string2().min(1), record(string2(), unknown())]).describe("The target the flow executes against, as a preset or object.");
|
|
9034
|
+
const emptyReason = discriminatedUnion("type", [
|
|
9035
|
+
object({
|
|
9036
|
+
type: literal("branch-never-reconciled").describe("The environment's flow code branch has no reconciled commit yet, so there is nothing to list. Read environment.get's flowCodeBranch and list again once syncStatus is reconciled.")
|
|
9037
|
+
}),
|
|
9038
|
+
object({
|
|
9039
|
+
type: literal("commit-has-no-flow-files").describe("The reconciled commit holds no flow file. The branch may never have had one, or a commit removed it: read the branch history at lastSyncedCommitHash before concluding either.")
|
|
9040
|
+
}),
|
|
9041
|
+
object({
|
|
9042
|
+
hiddenDraftCount: number2().int().positive().describe("How many draft flows this listing hid."),
|
|
9043
|
+
type: literal("every-flow-is-a-draft").describe("Every flow this listing matched is a draft, and the listing excluded drafts. Send includeDrafts to see them.")
|
|
9044
|
+
}),
|
|
9045
|
+
object({
|
|
9046
|
+
type: literal("no-flow-matched-the-listing").describe("The reconciled commit contains flow files, but this listing matched none of them: their flows were deleted after the commit reconciled, or a filter excluded every one.")
|
|
9047
|
+
})
|
|
9048
|
+
]).describe("Why this listing has no flows, present only when flows is empty. Read it before concluding that a flow went missing.");
|
|
8242
9049
|
const output = object({
|
|
9050
|
+
emptyReason: emptyReason.optional(),
|
|
8243
9051
|
flows: array(resource({
|
|
8244
9052
|
executionTarget,
|
|
8245
9053
|
flowId: ids.flow,
|
|
@@ -8505,14 +9313,134 @@ var makeUpdateIssueContract = (ids) => {
|
|
|
8505
9313
|
openWorldHint: true,
|
|
8506
9314
|
readOnlyHint: false
|
|
8507
9315
|
},
|
|
8508
|
-
description: "Update an issue owned by the caller's team. Omitted fields remain unchanged.",
|
|
9316
|
+
description: "Update an issue owned by the caller's team. Omitted fields remain unchanged.",
|
|
9317
|
+
input,
|
|
9318
|
+
kind: "write",
|
|
9319
|
+
name: "issue.update",
|
|
9320
|
+
output
|
|
9321
|
+
};
|
|
9322
|
+
};
|
|
9323
|
+
|
|
9324
|
+
// node_modules/@qawolf/api-contracts/dist/v1/legacyTrigger/resource.js
|
|
9325
|
+
var namedIdentity = object({ id: string2(), name: string2() });
|
|
9326
|
+
var branchScope = union([
|
|
9327
|
+
object({ kind: literal("all-branches") }),
|
|
9328
|
+
object({
|
|
9329
|
+
caseSensitiveGlobs: array(string2()),
|
|
9330
|
+
kind: literal("listed-branches"),
|
|
9331
|
+
negated: boolean2(),
|
|
9332
|
+
raw: string2()
|
|
9333
|
+
})
|
|
9334
|
+
]);
|
|
9335
|
+
var codeHostingServiceRepository = union([
|
|
9336
|
+
object({ kind: literal("any") }),
|
|
9337
|
+
object({ kind: literal("none") }),
|
|
9338
|
+
object({ id: string2(), kind: literal("by-id") })
|
|
9339
|
+
]);
|
|
9340
|
+
var makeLegacyTriggerSchema = (ids) => {
|
|
9341
|
+
const base = {
|
|
9342
|
+
environment: object({
|
|
9343
|
+
id: ids.environment,
|
|
9344
|
+
kind: _enum(["static", "preview"]).describe("Whether the environment is static or a preview. A preview environment holds copies of the static deployment triggers."),
|
|
9345
|
+
name: string2(),
|
|
9346
|
+
terminatedAt: exports_iso.datetime().optional().describe("When the environment was terminated, if it has been.")
|
|
9347
|
+
}),
|
|
9348
|
+
id: ids.legacyTrigger,
|
|
9349
|
+
isPaused: boolean2(),
|
|
9350
|
+
name: string2(),
|
|
9351
|
+
pausedAt: exports_iso.datetime().optional(),
|
|
9352
|
+
tags: array(namedIdentity)
|
|
9353
|
+
};
|
|
9354
|
+
return union([
|
|
9355
|
+
object({
|
|
9356
|
+
...base,
|
|
9357
|
+
nextAt: exports_iso.datetime().optional(),
|
|
9358
|
+
repeatMinutes: number2(),
|
|
9359
|
+
startAt: exports_iso.datetime().optional(),
|
|
9360
|
+
timezoneId: string2().optional(),
|
|
9361
|
+
type: literal("scheduled")
|
|
9362
|
+
}),
|
|
9363
|
+
object({
|
|
9364
|
+
...base,
|
|
9365
|
+
adaptiveFlowSelection: boolean2().describe("Whether QA Wolf picks the flows to run from the deployment's changes. Such a trigger migrates to a generativeSuite action, which names no flows or tags of its own."),
|
|
9366
|
+
branchScope,
|
|
9367
|
+
codeHostingServiceRepository,
|
|
9368
|
+
deploymentPrLabel: string2().optional(),
|
|
9369
|
+
deploymentType: string2().optional(),
|
|
9370
|
+
type: union([literal("generic"), literal("pr-testing-button")])
|
|
9371
|
+
})
|
|
9372
|
+
]);
|
|
9373
|
+
};
|
|
9374
|
+
|
|
9375
|
+
// node_modules/@qawolf/api-contracts/dist/v1/legacyTrigger/find.js
|
|
9376
|
+
var makeFindLegacyTriggersContract = (ids) => {
|
|
9377
|
+
const input = object({
|
|
9378
|
+
kind: _enum(["active", "all", "static"]).default("active").describe(`Which environments to list triggers from. "active", the default, covers the static environments plus the pull request environments still in use. "static" covers the static environments only, where every pull request copy's original lives. "all" adds the pull request environments that have already been torn down, whose environment carries a terminatedAt.`),
|
|
9379
|
+
workspaceId: ids.workspace.optional().describe("The workspace to list legacy triggers from. Required when authenticating with an organization or user API key.")
|
|
9380
|
+
});
|
|
9381
|
+
const output = object({
|
|
9382
|
+
legacyTriggers: array(makeLegacyTriggerSchema(ids)).describe("The workspace's legacy triggers, by name.")
|
|
9383
|
+
});
|
|
9384
|
+
return {
|
|
9385
|
+
annotations: {
|
|
9386
|
+
destructiveHint: false,
|
|
9387
|
+
openWorldHint: false,
|
|
9388
|
+
readOnlyHint: true
|
|
9389
|
+
},
|
|
9390
|
+
description: "List a workspace's legacy per-environment triggers; trigger.find " + "lists the current ones. For migration only; it goes when legacy " + "triggers go. adaptiveFlowSelection becomes a generativeSuite action, " + "which takes no tags.",
|
|
9391
|
+
input,
|
|
9392
|
+
kind: "read",
|
|
9393
|
+
name: "legacyTrigger.find",
|
|
9394
|
+
output
|
|
9395
|
+
};
|
|
9396
|
+
};
|
|
9397
|
+
|
|
9398
|
+
// node_modules/@qawolf/api-contracts/dist/v1/legacyTrigger/lifecycle.js
|
|
9399
|
+
var makeLifecycleShape = (ids) => ({
|
|
9400
|
+
input: object({ legacyTriggerId: ids.legacyTrigger }),
|
|
9401
|
+
output: object({
|
|
9402
|
+
isPaused: boolean2(),
|
|
9403
|
+
legacyTriggerId: ids.legacyTrigger
|
|
9404
|
+
})
|
|
9405
|
+
});
|
|
9406
|
+
var makePauseLegacyTriggerContract = (ids) => {
|
|
9407
|
+
const { input, output } = makeLifecycleShape(ids);
|
|
9408
|
+
return {
|
|
9409
|
+
annotations: {
|
|
9410
|
+
destructiveHint: true,
|
|
9411
|
+
openWorldHint: false,
|
|
9412
|
+
readOnlyHint: false
|
|
9413
|
+
},
|
|
9414
|
+
description: "Pause one legacy trigger, the older per-environment kind, so it stops " + "firing; use trigger.pause for a current one. Its copies in pull " + "request environments pause too. For migration only; it goes when " + "legacy triggers go.",
|
|
9415
|
+
input,
|
|
9416
|
+
kind: "write",
|
|
9417
|
+
name: "legacyTrigger.pause",
|
|
9418
|
+
output
|
|
9419
|
+
};
|
|
9420
|
+
};
|
|
9421
|
+
var makeResumeLegacyTriggerContract = (ids) => {
|
|
9422
|
+
const { input, output } = makeLifecycleShape(ids);
|
|
9423
|
+
return {
|
|
9424
|
+
annotations: {
|
|
9425
|
+
destructiveHint: true,
|
|
9426
|
+
openWorldHint: true,
|
|
9427
|
+
readOnlyHint: false
|
|
9428
|
+
},
|
|
9429
|
+
description: "Resume one legacy trigger, the older per-environment kind; use " + "trigger.resume for a current one. Its copies in pull request " + "environments resume too, and a scheduled one jumps to the next " + "upcoming slot even if it was not paused. For migration only; it goes " + "when legacy triggers go.",
|
|
8509
9430
|
input,
|
|
8510
9431
|
kind: "write",
|
|
8511
|
-
name: "
|
|
9432
|
+
name: "legacyTrigger.resume",
|
|
8512
9433
|
output
|
|
8513
9434
|
};
|
|
8514
9435
|
};
|
|
8515
9436
|
|
|
9437
|
+
// node_modules/@qawolf/api-contracts/dist/v1/legacyTrigger/index.js
|
|
9438
|
+
var makeLegacyTriggerContracts = (ids) => ({
|
|
9439
|
+
find: makeFindLegacyTriggersContract(ids),
|
|
9440
|
+
pause: makePauseLegacyTriggerContract(ids),
|
|
9441
|
+
resume: makeResumeLegacyTriggerContract(ids)
|
|
9442
|
+
});
|
|
9443
|
+
|
|
8516
9444
|
// node_modules/@qawolf/api-contracts/dist/v1/run/diagnose.js
|
|
8517
9445
|
var makeDiagnoseRunContract = (ids) => {
|
|
8518
9446
|
const input = object({
|
|
@@ -8556,7 +9484,8 @@ var makeFindRunsContract = (ids) => {
|
|
|
8556
9484
|
const input = object({
|
|
8557
9485
|
createdAfter: exports_iso.datetime({ offset: true }).optional().describe("Only include runs created after this instant, e.g. the runs since a deploy."),
|
|
8558
9486
|
...makePaginationInputFields({ defaultLimit: 20, maxLimit: 100 }),
|
|
8559
|
-
environmentId: ids.environmentRef
|
|
9487
|
+
environmentId: ids.environmentRef,
|
|
9488
|
+
workspaceId: workspaceForEnvironmentRef(ids.workspace)
|
|
8560
9489
|
});
|
|
8561
9490
|
const output = object({
|
|
8562
9491
|
nextCursor: nextCursorSchema,
|
|
@@ -8704,6 +9633,54 @@ var makeStopRunContract = (ids) => {
|
|
|
8704
9633
|
};
|
|
8705
9634
|
};
|
|
8706
9635
|
|
|
9636
|
+
// node_modules/@qawolf/api-contracts/dist/v1/run/triage.js
|
|
9637
|
+
var probability = number2().min(0).max(1);
|
|
9638
|
+
var verdictAnswer = object({
|
|
9639
|
+
choice: _enum(["bug", "maintenance"]),
|
|
9640
|
+
confidence: probability,
|
|
9641
|
+
probabilities: record(string2(), probability),
|
|
9642
|
+
type: literal("choice")
|
|
9643
|
+
});
|
|
9644
|
+
var makeTriageRunContract = (ids) => {
|
|
9645
|
+
const input = object({
|
|
9646
|
+
flowId: ids.flow.describe("The flow that failed in the run."),
|
|
9647
|
+
runId: ids.run
|
|
9648
|
+
});
|
|
9649
|
+
const decision = discriminatedUnion("type", [
|
|
9650
|
+
object({
|
|
9651
|
+
diagnosis: _enum(["bug", "maintenance"]),
|
|
9652
|
+
type: literal("diagnose")
|
|
9653
|
+
}),
|
|
9654
|
+
object({
|
|
9655
|
+
diagnosis: _enum(["bug", "maintenance"]),
|
|
9656
|
+
type: literal("suggest")
|
|
9657
|
+
}),
|
|
9658
|
+
object({
|
|
9659
|
+
type: literal("needsHuman")
|
|
9660
|
+
})
|
|
9661
|
+
]);
|
|
9662
|
+
const output = object({
|
|
9663
|
+
answers: object({
|
|
9664
|
+
verdict: verdictAnswer
|
|
9665
|
+
}),
|
|
9666
|
+
decision: decision.describe("What the triage would do with the verdict. The prototype records nothing; it only reports."),
|
|
9667
|
+
model: string2(),
|
|
9668
|
+
state: json().describe("The context that was sent to the model, for inspection.")
|
|
9669
|
+
});
|
|
9670
|
+
return {
|
|
9671
|
+
annotations: {
|
|
9672
|
+
destructiveHint: false,
|
|
9673
|
+
openWorldHint: false,
|
|
9674
|
+
readOnlyHint: true
|
|
9675
|
+
},
|
|
9676
|
+
description: "Prototype. Ask Jev, a TypeSafe System One model, whether a flow failure in a run is a bug in the product " + "or a test that needs maintenance. Compares the failing attempt with the flow's last passing run in the " + "same environment. Records nothing.",
|
|
9677
|
+
input,
|
|
9678
|
+
kind: "read",
|
|
9679
|
+
name: "run.triage",
|
|
9680
|
+
output
|
|
9681
|
+
};
|
|
9682
|
+
};
|
|
9683
|
+
|
|
8707
9684
|
// node_modules/@qawolf/api-contracts/dist/v1/runner/evaluateSnippet.js
|
|
8708
9685
|
var maxSnippetCodeLength = 64 * 1024;
|
|
8709
9686
|
var makeEvaluateSnippetOnRunnerContract = (ids) => {
|
|
@@ -8748,18 +9725,26 @@ var makeGetRunnerContract = (ids) => {
|
|
|
8748
9725
|
id: runnerIdSchema.describe("Id of the runner to look up."),
|
|
8749
9726
|
workspaceId: ids.workspace.optional().describe(runnerWorkspaceIdDescription)
|
|
8750
9727
|
});
|
|
8751
|
-
const
|
|
9728
|
+
const addressed = object({
|
|
8752
9729
|
id: runnerIdSchema.describe("Id of the runner the call addressed."),
|
|
8753
|
-
outcome: literal("success")
|
|
8754
|
-
running: boolean2().describe("False when no runner is running under this id: it was never launched, it was terminated, or it terminated on its own after inactivity. These are not distinguished, because the run system keeps no record of a runner once it is gone.")
|
|
9730
|
+
outcome: literal("success")
|
|
8755
9731
|
});
|
|
9732
|
+
const output = discriminatedUnion("running", [
|
|
9733
|
+
addressed.extend({
|
|
9734
|
+
running: literal(false).describe("No runner is running under this id: it was never launched, it was terminated, or it terminated on its own after inactivity. These are not distinguished, because the run system keeps no record of a runner once it is gone.")
|
|
9735
|
+
}),
|
|
9736
|
+
addressed.extend({
|
|
9737
|
+
running: literal(true).describe("A runner is running under this id and can be addressed."),
|
|
9738
|
+
url: runnerWatchUrlSchema
|
|
9739
|
+
})
|
|
9740
|
+
]);
|
|
8756
9741
|
return {
|
|
8757
9742
|
annotations: {
|
|
8758
9743
|
destructiveHint: false,
|
|
8759
9744
|
openWorldHint: false,
|
|
8760
9745
|
readOnlyHint: true
|
|
8761
9746
|
},
|
|
8762
|
-
description: "Report whether a runner is running under this id on the caller's team. This is a lookup: it never starts a runner, and it does not reset a runner's inactivity clock the way reading its journal does. An id that is not running is a success with `running: false` rather than an error, so this is how to check a runner is still there before addressing it.",
|
|
9747
|
+
description: "Report whether a runner is running under this id on the caller's team. This is a lookup: it never starts a runner, and it does not reset a runner's inactivity clock the way reading its journal does. An id that is not running is a success with `running: false` rather than an error, so this is how to check a runner is still there before addressing it. A running runner also reports the `url` to watch it on, so an id alone is enough to recover the link to give the user.",
|
|
8763
9748
|
input,
|
|
8764
9749
|
kind: "read",
|
|
8765
9750
|
name: "runner.get",
|
|
@@ -8860,7 +9845,7 @@ var makeLaunchRunnerContract = (ids) => {
|
|
|
8860
9845
|
openWorldHint: false,
|
|
8861
9846
|
readOnlyHint: false
|
|
8862
9847
|
},
|
|
8863
|
-
description: "Launch an interactive runner on the caller's team under an id the caller chooses. Launching the same id again returns the runner already running rather than starting a second one, and the same id with a different runnerName is refused. A runner is not permanent: it terminates on its own after a period of inactivity, and launching the same id after that starts and bills a new runner — so read `alreadyRunning` to tell which happened.",
|
|
9848
|
+
description: "Launch an interactive runner on the caller's team under an id the caller chooses. Launching the same id again returns the runner already running rather than starting a second one, and the same id with a different runnerName is refused. A runner is not permanent: it terminates on its own after a period of inactivity, and launching the same id after that starts and bills a new runner — so read `alreadyRunning` to tell which happened. A success means the runner is answering: the call waits for the pod it started to come up, so the very next call to the runner reaches it. If the pod does not come up in time the call fails instead, leaving the runner running — launching the same id again attaches to it. After a successful launch, put the exact returned `url` in a normal user-visible assistant message so they can watch while the browser is driven. Tool output and internal reasoning do not count as sharing the link. When `alreadyRunning` is true the `url` is the same page, so share it again instead of assuming the caller still has it.",
|
|
8864
9849
|
input,
|
|
8865
9850
|
kind: "write",
|
|
8866
9851
|
name: "runner.launch",
|
|
@@ -8976,405 +9961,230 @@ var makeReadRunnerJournalContract = (ids) => {
|
|
|
8976
9961
|
// node_modules/@qawolf/api-contracts/dist/v1/runner/runFlow.js
|
|
8977
9962
|
var unchangedFilesSchema = record(string2(), string2().min(1)).superRefine((hashes, refinementContext) => {
|
|
8978
9963
|
for (const path of Object.keys(hashes)) {
|
|
8979
|
-
if (isShippableRunFilePath(path))
|
|
8980
|
-
continue;
|
|
8981
|
-
refinementContext.addIssue({
|
|
8982
|
-
code: "custom",
|
|
8983
|
-
message: runFilePathRefusal,
|
|
8984
|
-
path: [path]
|
|
8985
|
-
});
|
|
8986
|
-
}
|
|
8987
|
-
});
|
|
8988
|
-
var makeRunFlowOnRunnerContract = (ids) => {
|
|
8989
|
-
const input = object({
|
|
8990
|
-
entryPointPath: runFilePathSchema.describe("Path of the flow file to run, as it appears in `files`."),
|
|
8991
|
-
env: runEnvironmentSchema.optional().describe("Environment variables to make available to the run."),
|
|
8992
|
-
environmentId: ids.environmentRef.optional().describe("A QA Wolf environment whose variables the run is given, by id or alias. QA Wolf reads and decrypts them itself, so they never travel in the request and the count and length limits on `env` do not apply to them. Send this or `env`, not both."),
|
|
8993
|
-
files: runFilesSchema.describe("Every file the run needs keyed by its path — the flow file, everything it imports, package.json and tsconfig.json. A runner holds no copy of your project, so what runs is exactly what is sent here."),
|
|
8994
|
-
id: runnerIdSchema.describe("Id of the runner to run the flow on."),
|
|
8995
|
-
selection: runSelectionSchema.optional().describe("Run only these lines, inside the page the runner is already on, instead of running the whole flow from a fresh browser. Omit to run the whole entry point."),
|
|
8996
|
-
unchangedFiles: unchangedFilesSchema.optional().describe("Files this runner already holds from an earlier run, keyed by path with a hex SHA-256 of the content it should hold. Send this to make `files` only what changed. The runner refuses with `needs-full-sync` if it holds none of a referenced path, so it never runs something other than what was asked for. Omit it to send every file."),
|
|
8997
|
-
workspaceId: ids.workspace.optional().describe(runnerWorkspaceIdDescription)
|
|
8998
|
-
}).refine((request) => request.env === undefined || request.environmentId === undefined, {
|
|
8999
|
-
error: "Send env or environmentId, not both. An environment's variables are taken as they are stored, so there is no order in which the two would combine.",
|
|
9000
|
-
path: ["environmentId"]
|
|
9001
|
-
}).refine((request) => Object.hasOwn(request.files, request.entryPointPath), {
|
|
9002
|
-
error: "The entry point must be one of the files.",
|
|
9003
|
-
path: ["files"]
|
|
9004
|
-
}).refine((request) => Object.hasOwn(request.files, runPackageJsonPath), {
|
|
9005
|
-
error: `The files must include ${runPackageJsonPath}; the run's npm dependencies are read from it.`,
|
|
9006
|
-
path: ["files"]
|
|
9007
|
-
}).refine((request) => request.selection === undefined || Object.hasOwn(request.files, request.selection.path), {
|
|
9008
|
-
error: "A selection must name a file carried in files.",
|
|
9009
|
-
path: ["selection", "path"]
|
|
9010
|
-
}).refine((request) => Object.keys(request.unchangedFiles ?? {}).every((path) => !Object.hasOwn(request.files, path)), {
|
|
9011
|
-
error: "A path may be sent in files or referenced in unchangedFiles, not both.",
|
|
9012
|
-
path: ["unchangedFiles"]
|
|
9013
|
-
});
|
|
9014
|
-
const failure = discriminatedUnion("failureReason", [
|
|
9015
|
-
object({
|
|
9016
|
-
failureReason: literal("runner-target-mismatch"),
|
|
9017
|
-
outcome: literal("failure"),
|
|
9018
|
-
requiredRunnerName: runnerNameSchema.describe("The runner family this flow's execution target needs."),
|
|
9019
|
-
runnerName: runnerNameSchema.describe("The runner family the runner is actually running.")
|
|
9020
|
-
}),
|
|
9021
|
-
object({
|
|
9022
|
-
failureReason: literal("needs-full-sync"),
|
|
9023
|
-
missingPaths: array(runFilePathSchema).describe("Paths referenced in `unchangedFiles` that this runner does not hold. Send the run again with every file it needs in `files`."),
|
|
9024
|
-
outcome: literal("failure")
|
|
9025
|
-
}),
|
|
9026
|
-
object({
|
|
9027
|
-
failureReason: literal("runner-unreachable"),
|
|
9028
|
-
outcome: literal("failure")
|
|
9029
|
-
})
|
|
9030
|
-
]);
|
|
9031
|
-
const output = discriminatedUnion("outcome", [
|
|
9032
|
-
object({
|
|
9033
|
-
bootstrappedRunner: boolean2().optional().describe("True when the runner had no live browser and one was started before the run, so a `selection` ran against a fresh page rather than the one an earlier run left. Absent means the runner was already warm. Only a request carrying `selection` can bootstrap, because a whole run starts its own browser either way."),
|
|
9034
|
-
outcome: literal("success"),
|
|
9035
|
-
runId: string2().describe("Id of the run, to follow it by. Read the `run-status` stream of the runner's journal for its outcome, and `run-logs` and `run-events` for its output.")
|
|
9036
|
-
}),
|
|
9037
|
-
failure
|
|
9038
|
-
]);
|
|
9039
|
-
return {
|
|
9040
|
-
annotations: {
|
|
9041
|
-
destructiveHint: true,
|
|
9042
|
-
openWorldHint: true,
|
|
9043
|
-
readOnlyHint: false
|
|
9044
|
-
},
|
|
9045
|
-
description: "Run a flow on an interactive runner. When `selection` is given the lines run against the browser as it stands, so nothing is re-navigated and nothing is signed in again; without it the whole entry point runs from a fresh browser. A runner with no live browser starts one before a selection and says so with `bootstrappedRunner`, which means those lines ran against a fresh page rather than the one an earlier run left. A selection produces no `runStarted` event, so follow it by its run id on `run-status` like any other run. Send `unchangedFiles` to ship only what changed since an earlier run on this runner; a `needs-full-sync` failure names the paths it does not hold, and the way to recover is the same run again with every file in `files`. Answers as soon as the run is accepted, with the id to follow it by — nothing waits for the run to finish. Which browser or device the run needs is read from the flow file's own execution target, so it is not supplied here; when it does not match what the runner is, the call fails with `runner-target-mismatch` rather than failing partway through the run. `runner-unreachable` means the answer did not arrive, which is NOT the same as the run not having started: the runner may have accepted it and been too slow to say so, and resubmitting would start a second run that is billed and journalled alongside the first. Read the runner's `run-status` journal stream before resubmitting, and use the newest run id there if one appeared.",
|
|
9046
|
-
input,
|
|
9047
|
-
kind: "write",
|
|
9048
|
-
name: "runner.runFlow",
|
|
9049
|
-
output
|
|
9050
|
-
};
|
|
9051
|
-
};
|
|
9052
|
-
|
|
9053
|
-
// node_modules/@qawolf/api-contracts/dist/v1/runner/stopRun.js
|
|
9054
|
-
var makeStopRunOnRunnerContract = (ids) => {
|
|
9055
|
-
const input = object({
|
|
9056
|
-
id: runnerIdSchema.describe("Id of the runner to stop the run on."),
|
|
9057
|
-
workspaceId: ids.workspace.optional().describe(runnerWorkspaceIdDescription)
|
|
9058
|
-
});
|
|
9059
|
-
const output = discriminatedUnion("outcome", [
|
|
9060
|
-
object({
|
|
9061
|
-
outcome: literal("success"),
|
|
9062
|
-
wasRunning: boolean2().describe("False when the runner had nothing to stop: the run had already finished, or none had been submitted. Not an error.")
|
|
9063
|
-
}),
|
|
9064
|
-
makeRunnerFailureSchema([runnerUnreachableFailureReason])
|
|
9065
|
-
]);
|
|
9066
|
-
return {
|
|
9067
|
-
annotations: {
|
|
9068
|
-
destructiveHint: true,
|
|
9069
|
-
openWorldHint: false,
|
|
9070
|
-
readOnlyHint: false
|
|
9071
|
-
},
|
|
9072
|
-
description: "Stop what a runner is currently executing, leaving the runner up and its browser on whatever page the run reached. Succeeds whether or not anything was running, and `wasRunning` says which. This is the counterpart of `runner.terminate`, which ends the runner itself. The run stops where it is, so the journal's `run-status` settles it as stopped rather than passed or failed. `runner-unreachable` if the runner could not be reached: it may still be starting, it may have terminated after inactivity, or it may be too busy to answer. The stop may still have landed, but stopping a runner that is already idle does nothing, so retrying is safe.",
|
|
9073
|
-
input,
|
|
9074
|
-
kind: "write",
|
|
9075
|
-
name: "runner.stopRun",
|
|
9076
|
-
output
|
|
9077
|
-
};
|
|
9078
|
-
};
|
|
9079
|
-
|
|
9080
|
-
// node_modules/@qawolf/api-contracts/dist/v1/runner/takeScreenshot.js
|
|
9081
|
-
var makeTakeScreenshotOnRunnerContract = (ids) => {
|
|
9082
|
-
const input = object({
|
|
9083
|
-
id: runnerIdSchema.describe("Id of the runner to take a screenshot of."),
|
|
9084
|
-
workspaceId: ids.workspace.optional().describe(runnerWorkspaceIdDescription)
|
|
9085
|
-
});
|
|
9086
|
-
const output = discriminatedUnion("outcome", [
|
|
9087
|
-
object({
|
|
9088
|
-
imageJpegBase64: screenshotImageSchema,
|
|
9089
|
-
outcome: literal("success")
|
|
9090
|
-
}),
|
|
9091
|
-
makeRunnerFailureSchema([
|
|
9092
|
-
...screenFailureReasons,
|
|
9093
|
-
runnerUnreachableFailureReason
|
|
9094
|
-
])
|
|
9095
|
-
]);
|
|
9096
|
-
return {
|
|
9097
|
-
annotations: {
|
|
9098
|
-
destructiveHint: false,
|
|
9099
|
-
openWorldHint: false,
|
|
9100
|
-
readOnlyHint: false
|
|
9101
|
-
},
|
|
9102
|
-
description: `Take one screenshot of an interactive runner's screen. On a runner with a browser the image is the whole virtual desktop, browser window and all; this refreshes the inactivity timer and can extend the runner's billed lifetime. On a mobile runner it is the device's own screen, re-encoded to JPEG on the pod so this contract reads one image format regardless of runner family. ${screenNeedsARunDescription} ${screenNotReadyDescription} ${runnerHasNoScreenDescription} ${retryableRunnerUnreachableDescription}`,
|
|
9103
|
-
input,
|
|
9104
|
-
kind: "read",
|
|
9105
|
-
name: "runner.takeScreenshot",
|
|
9106
|
-
output
|
|
9107
|
-
};
|
|
9108
|
-
};
|
|
9109
|
-
|
|
9110
|
-
// node_modules/@qawolf/api-contracts/dist/v1/tag/list.js
|
|
9111
|
-
var makeListTagsContract = (ids) => {
|
|
9112
|
-
const input = object({
|
|
9113
|
-
includeFlowIds: boolean2().default(false).describe("Also return the ids of the flows that carry each tag."),
|
|
9114
|
-
names: array(string2().trim().min(1)).min(1).max(100).optional().describe("Only list tags with these names. Matching is case sensitive. Omit to list all tags."),
|
|
9115
|
-
workspaceId: ids.workspace.optional().describe("The workspace to list tags from. Required when authenticating with an organization or user API key."),
|
|
9116
|
-
...makePaginationInputFields({ defaultLimit: 20, maxLimit: 100 })
|
|
9117
|
-
});
|
|
9118
|
-
const output = object({
|
|
9119
|
-
nextCursor: nextCursorSchema,
|
|
9120
|
-
tags: array(makeTagResourceSchema().extend({
|
|
9121
|
-
flowIds: array(ids.flow).optional().describe("Ids of the flows that carry the tag. Present only when includeFlowIds is set.")
|
|
9122
|
-
})).describe("The team's tags, alphabetical by name.")
|
|
9123
|
-
});
|
|
9124
|
-
return {
|
|
9125
|
-
annotations: {
|
|
9126
|
-
destructiveHint: false,
|
|
9127
|
-
openWorldHint: false,
|
|
9128
|
-
readOnlyHint: true
|
|
9129
|
-
},
|
|
9130
|
-
description: "List the team's tags, alphabetical by name. Tag names select flows in run.create.",
|
|
9131
|
-
input,
|
|
9132
|
-
kind: "read",
|
|
9133
|
-
name: "tag.list",
|
|
9134
|
-
output
|
|
9135
|
-
};
|
|
9136
|
-
};
|
|
9137
|
-
|
|
9138
|
-
// node_modules/@qawolf/api-contracts/dist/v1/trigger/configurationRules.js
|
|
9139
|
-
var checkAction = (action, ctx) => {
|
|
9140
|
-
const namesFlows = action.flowIds.length + action.tagNames.length > 0;
|
|
9141
|
-
if (action.kind === "generativeSuite") {
|
|
9142
|
-
if (namesFlows) {
|
|
9143
|
-
ctx.addIssue({
|
|
9144
|
-
code: "custom",
|
|
9145
|
-
message: "flowIds and tagNames do not apply when the action is generativeSuite.",
|
|
9146
|
-
path: ["action", "flowIds"]
|
|
9147
|
-
});
|
|
9148
|
-
}
|
|
9149
|
-
return;
|
|
9150
|
-
}
|
|
9151
|
-
if (action.instructions !== undefined) {
|
|
9152
|
-
ctx.addIssue({
|
|
9153
|
-
code: "custom",
|
|
9154
|
-
message: "instructions apply to a generativeSuite action only.",
|
|
9155
|
-
path: ["action", "instructions"]
|
|
9156
|
-
});
|
|
9157
|
-
}
|
|
9158
|
-
if (!namesFlows) {
|
|
9159
|
-
ctx.addIssue({
|
|
9160
|
-
code: "custom",
|
|
9161
|
-
message: "At least one flow or tag is required.",
|
|
9162
|
-
path: ["action", "flowIds"]
|
|
9163
|
-
});
|
|
9164
|
-
}
|
|
9165
|
-
};
|
|
9166
|
-
var checkSchedule = (value, ctx) => {
|
|
9167
|
-
if (value.cadence === "daily") {
|
|
9168
|
-
for (const field of ["timeOfDay", "timezoneId"]) {
|
|
9169
|
-
if (value[field] === undefined) {
|
|
9170
|
-
ctx.addIssue({
|
|
9171
|
-
code: "custom",
|
|
9172
|
-
message: `${field} is required when cadence is daily.`,
|
|
9173
|
-
path: [field]
|
|
9174
|
-
});
|
|
9175
|
-
}
|
|
9176
|
-
}
|
|
9177
|
-
if (value.minuteOfHour !== undefined) {
|
|
9178
|
-
ctx.addIssue({
|
|
9179
|
-
code: "custom",
|
|
9180
|
-
message: "minuteOfHour applies to an hourly cadence only.",
|
|
9181
|
-
path: ["minuteOfHour"]
|
|
9182
|
-
});
|
|
9183
|
-
}
|
|
9184
|
-
} else {
|
|
9185
|
-
for (const field of ["timeOfDay", "timezoneId"]) {
|
|
9186
|
-
if (value[field] !== undefined) {
|
|
9187
|
-
ctx.addIssue({
|
|
9188
|
-
code: "custom",
|
|
9189
|
-
message: `${field} applies to a daily cadence only.`,
|
|
9190
|
-
path: [field]
|
|
9191
|
-
});
|
|
9192
|
-
}
|
|
9193
|
-
}
|
|
9194
|
-
}
|
|
9195
|
-
if (value.action.kind === "generativeSuite") {
|
|
9196
|
-
ctx.addIssue({
|
|
9197
|
-
code: "custom",
|
|
9198
|
-
message: "A schedule trigger cannot use a generativeSuite action.",
|
|
9199
|
-
path: ["action", "kind"]
|
|
9200
|
-
});
|
|
9201
|
-
return;
|
|
9202
|
-
}
|
|
9203
|
-
checkAction(value.action, ctx);
|
|
9204
|
-
};
|
|
9205
|
-
var checkDeployment = (value, ctx) => {
|
|
9206
|
-
if (value.environmentPattern !== undefined && value.environmentIds.length > 0) {
|
|
9207
|
-
ctx.addIssue({
|
|
9964
|
+
if (isShippableRunFilePath(path))
|
|
9965
|
+
continue;
|
|
9966
|
+
refinementContext.addIssue({
|
|
9208
9967
|
code: "custom",
|
|
9209
|
-
message:
|
|
9210
|
-
path: [
|
|
9968
|
+
message: runFilePathRefusal,
|
|
9969
|
+
path: [path]
|
|
9211
9970
|
});
|
|
9212
9971
|
}
|
|
9213
|
-
|
|
9214
|
-
|
|
9215
|
-
|
|
9216
|
-
|
|
9217
|
-
|
|
9218
|
-
|
|
9219
|
-
|
|
9220
|
-
|
|
9221
|
-
|
|
9222
|
-
|
|
9223
|
-
|
|
9972
|
+
});
|
|
9973
|
+
var makeRunFlowOnRunnerContract = (ids) => {
|
|
9974
|
+
const input = object({
|
|
9975
|
+
entryPointPath: runFilePathSchema.describe("Path of the flow file to run, as it appears in `files`."),
|
|
9976
|
+
env: runEnvironmentSchema.optional().describe("Environment variables to make available to the run."),
|
|
9977
|
+
environmentId: ids.environmentRef.optional().describe("A QA Wolf environment whose variables the run is given, by id or alias. QA Wolf reads and decrypts them itself, so they never travel in the request and the count and length limits on `env` do not apply to them. Send this or `env`, not both."),
|
|
9978
|
+
files: runFilesSchema.describe("Every file the run needs keyed by its path — the flow file, everything it imports, package.json and tsconfig.json. A runner holds no copy of your project, so what runs is exactly what is sent here."),
|
|
9979
|
+
id: runnerIdSchema.describe("Id of the runner to run the flow on."),
|
|
9980
|
+
selection: runSelectionSchema.optional().describe("Run only these lines, inside the page the runner is already on, instead of running the whole flow from a fresh browser. Omit to run the whole entry point."),
|
|
9981
|
+
unchangedFiles: unchangedFilesSchema.optional().describe("Files this runner already holds from an earlier run, keyed by path with a hex SHA-256 of the content it should hold. Send this to make `files` only what changed. The runner refuses with `needs-full-sync` if it holds none of a referenced path, so it never runs something other than what was asked for. Omit it to send every file."),
|
|
9982
|
+
workspaceId: ids.workspace.optional().describe(runnerWorkspaceIdDescription)
|
|
9983
|
+
}).refine((request) => request.env === undefined || request.environmentId === undefined, {
|
|
9984
|
+
error: "Send env or environmentId, not both. An environment's variables are taken as they are stored, so there is no order in which the two would combine.",
|
|
9985
|
+
path: ["environmentId"]
|
|
9986
|
+
}).refine((request) => Object.hasOwn(request.files, request.entryPointPath), {
|
|
9987
|
+
error: "The entry point must be one of the files.",
|
|
9988
|
+
path: ["files"]
|
|
9989
|
+
}).refine((request) => Object.hasOwn(request.files, runPackageJsonPath), {
|
|
9990
|
+
error: `The files must include ${runPackageJsonPath}; the run's npm dependencies are read from it.`,
|
|
9991
|
+
path: ["files"]
|
|
9992
|
+
}).refine((request) => request.selection === undefined || Object.hasOwn(request.files, request.selection.path), {
|
|
9993
|
+
error: "A selection must name a file carried in files.",
|
|
9994
|
+
path: ["selection", "path"]
|
|
9995
|
+
}).refine((request) => Object.keys(request.unchangedFiles ?? {}).every((path) => !Object.hasOwn(request.files, path)), {
|
|
9996
|
+
error: "A path may be sent in files or referenced in unchangedFiles, not both.",
|
|
9997
|
+
path: ["unchangedFiles"]
|
|
9998
|
+
});
|
|
9999
|
+
const failure = discriminatedUnion("failureReason", [
|
|
9224
10000
|
object({
|
|
9225
|
-
|
|
9226
|
-
|
|
9227
|
-
|
|
9228
|
-
|
|
9229
|
-
}),
|
|
9230
|
-
kind: literal("schedule")
|
|
10001
|
+
failureReason: literal("runner-target-mismatch"),
|
|
10002
|
+
outcome: literal("failure"),
|
|
10003
|
+
requiredRunnerName: runnerNameSchema.describe("The runner family this flow's execution target needs."),
|
|
10004
|
+
runnerName: runnerNameSchema.describe("The runner family the runner is actually running.")
|
|
9231
10005
|
}),
|
|
9232
10006
|
object({
|
|
9233
|
-
|
|
9234
|
-
|
|
9235
|
-
|
|
10007
|
+
failureReason: literal("needs-full-sync"),
|
|
10008
|
+
missingPaths: array(runFilePathSchema).describe("Paths referenced in `unchangedFiles` that this runner does not hold. Send the run again with every file it needs in `files`."),
|
|
10009
|
+
outcome: literal("failure")
|
|
10010
|
+
}),
|
|
10011
|
+
object({
|
|
10012
|
+
failureReason: literal("runner-unreachable"),
|
|
10013
|
+
outcome: literal("failure")
|
|
9236
10014
|
})
|
|
9237
|
-
])
|
|
9238
|
-
const output =
|
|
10015
|
+
]);
|
|
10016
|
+
const output = discriminatedUnion("outcome", [
|
|
10017
|
+
object({
|
|
10018
|
+
bootstrappedRunner: boolean2().optional().describe("True when the runner had no live browser and one was started before the run, so a `selection` ran against a fresh page rather than the one an earlier run left. Absent means the runner was already warm. Only a request carrying `selection` can bootstrap, because a whole run starts its own browser either way."),
|
|
10019
|
+
outcome: literal("success"),
|
|
10020
|
+
runId: string2().describe("Id of the run, to follow it by. Read the `run-status` stream of the runner's journal for its outcome, and `run-logs` and `run-events` for its output.")
|
|
10021
|
+
}),
|
|
10022
|
+
failure
|
|
10023
|
+
]);
|
|
9239
10024
|
return {
|
|
9240
10025
|
annotations: {
|
|
9241
10026
|
destructiveHint: true,
|
|
9242
10027
|
openWorldHint: true,
|
|
9243
10028
|
readOnlyHint: false
|
|
9244
10029
|
},
|
|
9245
|
-
description: "
|
|
10030
|
+
description: "Run a flow on an interactive runner. When `selection` is given the lines run against the browser as it stands, so nothing is re-navigated and nothing is signed in again; without it the whole entry point runs from a fresh browser. A runner with no live browser starts one before a selection and says so with `bootstrappedRunner`, which means those lines ran against a fresh page rather than the one an earlier run left. A selection produces no `runStarted` event, so follow it by its run id on `run-status` like any other run. Send `unchangedFiles` to ship only what changed since an earlier run on this runner; a `needs-full-sync` failure names the paths it does not hold, and the way to recover is the same run again with every file in `files`. Answers as soon as the run is accepted, with the id to follow it by — nothing waits for the run to finish. Which browser or device the run needs is read from the flow file's own execution target, so it is not supplied here; when it does not match what the runner is, the call fails with `runner-target-mismatch` rather than failing partway through the run. `runner-unreachable` means the answer did not arrive, which is NOT the same as the run not having started: the runner may have accepted it and been too slow to say so, and resubmitting would start a second run that is billed and journalled alongside the first. Read the runner's `run-status` journal stream before resubmitting, and use the newest run id there if one appeared.",
|
|
9246
10031
|
input,
|
|
9247
10032
|
kind: "write",
|
|
9248
|
-
name: "
|
|
10033
|
+
name: "runner.runFlow",
|
|
9249
10034
|
output
|
|
9250
10035
|
};
|
|
9251
10036
|
};
|
|
9252
10037
|
|
|
9253
|
-
// node_modules/@qawolf/api-contracts/dist/v1/
|
|
9254
|
-
var
|
|
10038
|
+
// node_modules/@qawolf/api-contracts/dist/v1/runner/stopRun.js
|
|
10039
|
+
var makeStopRunOnRunnerContract = (ids) => {
|
|
9255
10040
|
const input = object({
|
|
9256
|
-
|
|
9257
|
-
workspaceId: ids.workspace.optional().describe(
|
|
9258
|
-
});
|
|
9259
|
-
const output = object({
|
|
9260
|
-
triggers: array(makeTriggerResourceSchema(ids)).describe("The team's triggers, newest first.")
|
|
10041
|
+
id: runnerIdSchema.describe("Id of the runner to stop the run on."),
|
|
10042
|
+
workspaceId: ids.workspace.optional().describe(runnerWorkspaceIdDescription)
|
|
9261
10043
|
});
|
|
10044
|
+
const output = discriminatedUnion("outcome", [
|
|
10045
|
+
object({
|
|
10046
|
+
outcome: literal("success"),
|
|
10047
|
+
wasRunning: boolean2().describe("False when the runner had nothing to stop: the run had already finished, or none had been submitted. Not an error.")
|
|
10048
|
+
}),
|
|
10049
|
+
makeRunnerFailureSchema([runnerUnreachableFailureReason])
|
|
10050
|
+
]);
|
|
9262
10051
|
return {
|
|
9263
10052
|
annotations: {
|
|
9264
|
-
destructiveHint:
|
|
10053
|
+
destructiveHint: true,
|
|
9265
10054
|
openWorldHint: false,
|
|
9266
|
-
readOnlyHint:
|
|
10055
|
+
readOnlyHint: false
|
|
9267
10056
|
},
|
|
9268
|
-
description: "
|
|
10057
|
+
description: "Stop what a runner is currently executing, leaving the runner up and its browser on whatever page the run reached. Succeeds whether or not anything was running, and `wasRunning` says which. This is the counterpart of `runner.terminate`, which ends the runner itself. The run stops where it is, so the journal's `run-status` settles it as stopped rather than passed or failed. `runner-unreachable` if the runner could not be reached: it may still be starting, it may have terminated after inactivity, or it may be too busy to answer. The stop may still have landed, but stopping a runner that is already idle does nothing, so retrying is safe.",
|
|
9269
10058
|
input,
|
|
9270
|
-
kind: "
|
|
9271
|
-
name: "
|
|
10059
|
+
kind: "write",
|
|
10060
|
+
name: "runner.stopRun",
|
|
9272
10061
|
output
|
|
9273
10062
|
};
|
|
9274
10063
|
};
|
|
9275
10064
|
|
|
9276
|
-
// node_modules/@qawolf/api-contracts/dist/v1/
|
|
9277
|
-
var
|
|
9278
|
-
const input = object({
|
|
9279
|
-
|
|
10065
|
+
// node_modules/@qawolf/api-contracts/dist/v1/runner/takeScreenshot.js
|
|
10066
|
+
var makeTakeScreenshotOnRunnerContract = (ids) => {
|
|
10067
|
+
const input = object({
|
|
10068
|
+
id: runnerIdSchema.describe("Id of the runner to take a screenshot of."),
|
|
10069
|
+
workspaceId: ids.workspace.optional().describe(runnerWorkspaceIdDescription)
|
|
10070
|
+
});
|
|
10071
|
+
const output = discriminatedUnion("outcome", [
|
|
10072
|
+
object({
|
|
10073
|
+
imageJpegBase64: screenshotImageSchema,
|
|
10074
|
+
outcome: literal("success")
|
|
10075
|
+
}),
|
|
10076
|
+
makeRunnerFailureSchema([
|
|
10077
|
+
...screenFailureReasons,
|
|
10078
|
+
runnerUnreachableFailureReason
|
|
10079
|
+
])
|
|
10080
|
+
]);
|
|
9280
10081
|
return {
|
|
9281
10082
|
annotations: {
|
|
9282
10083
|
destructiveHint: false,
|
|
9283
10084
|
openWorldHint: false,
|
|
9284
|
-
readOnlyHint:
|
|
10085
|
+
readOnlyHint: false
|
|
9285
10086
|
},
|
|
9286
|
-
description:
|
|
10087
|
+
description: `Take one screenshot of an interactive runner's screen. On a runner with a browser the image is the whole virtual desktop, browser window and all; this refreshes the inactivity timer and can extend the runner's billed lifetime. On a mobile runner it is the device's own screen, re-encoded to JPEG on the pod so this contract reads one image format regardless of runner family. ${screenNeedsARunDescription} ${screenNotReadyDescription} ${runnerHasNoScreenDescription} ${retryableRunnerUnreachableDescription}`,
|
|
9287
10088
|
input,
|
|
9288
10089
|
kind: "read",
|
|
9289
|
-
name: "
|
|
10090
|
+
name: "runner.takeScreenshot",
|
|
9290
10091
|
output
|
|
9291
10092
|
};
|
|
9292
10093
|
};
|
|
9293
10094
|
|
|
9294
|
-
// node_modules/@qawolf/api-contracts/dist/v1/
|
|
9295
|
-
var
|
|
9296
|
-
|
|
9297
|
-
|
|
10095
|
+
// node_modules/@qawolf/api-contracts/dist/v1/runner/catalog.js
|
|
10096
|
+
var makeRunnerContracts = (ids) => ({
|
|
10097
|
+
evaluateSnippet: makeEvaluateSnippetOnRunnerContract(ids),
|
|
10098
|
+
get: makeGetRunnerContract(ids),
|
|
10099
|
+
highlightSelector: makeHighlightSelectorOnRunnerContract(ids),
|
|
10100
|
+
importPackage: makeImportPackageOnRunnerContract(ids),
|
|
10101
|
+
inspect: makeInspectOnRunnerContract(ids),
|
|
10102
|
+
inspectMobile: makeInspectMobileOnRunnerContract(ids),
|
|
10103
|
+
launch: makeLaunchRunnerContract(ids),
|
|
10104
|
+
list: makeListRunnersContract(ids),
|
|
10105
|
+
performAction: makePerformActionOnRunnerContract(ids),
|
|
10106
|
+
performActions: makePerformActionsOnRunnerContract(ids),
|
|
10107
|
+
promoteSnapshot: makePromoteSnapshotOnRunnerContract(ids),
|
|
10108
|
+
readJournal: makeReadRunnerJournalContract(ids),
|
|
10109
|
+
...makeRecordingContracts(ids),
|
|
10110
|
+
runFlow: makeRunFlowOnRunnerContract(ids),
|
|
10111
|
+
stopRun: makeStopRunOnRunnerContract(ids),
|
|
10112
|
+
takeScreenshot: makeTakeScreenshotOnRunnerContract(ids),
|
|
10113
|
+
terminate: makeTerminateRunnerContract(ids)
|
|
10114
|
+
});
|
|
10115
|
+
|
|
10116
|
+
// node_modules/@qawolf/api-contracts/dist/v1/skill/index.js
|
|
10117
|
+
var skillName = string2().trim().min(1).max(255).describe("The skill's name as skill.list reports it, such as qawolf-onboarding. The qawolf- prefix is optional, so onboarding names the same skill.");
|
|
10118
|
+
var skillSummary = object({
|
|
10119
|
+
description: string2().describe("When to use the skill, in the words the agent routes on."),
|
|
10120
|
+
name: string2().describe("The skill's name. Read it with skill.get.")
|
|
10121
|
+
});
|
|
10122
|
+
var readOnlyAnnotations = {
|
|
10123
|
+
destructiveHint: false,
|
|
10124
|
+
openWorldHint: false,
|
|
10125
|
+
readOnlyHint: true
|
|
10126
|
+
};
|
|
10127
|
+
var makeListSkillsContract = () => {
|
|
10128
|
+
const input = object({});
|
|
10129
|
+
const output = object({
|
|
10130
|
+
skills: array(skillSummary).describe("Every skill the server serves, in catalog order.")
|
|
10131
|
+
});
|
|
9298
10132
|
return {
|
|
9299
|
-
annotations:
|
|
9300
|
-
|
|
9301
|
-
openWorldHint: false,
|
|
9302
|
-
readOnlyHint: false
|
|
9303
|
-
},
|
|
9304
|
-
description: "Pause a trigger so it stops firing. Pausing is idempotent. A team whose " + "triggers are all paused reports no trigger activity at all.",
|
|
10133
|
+
annotations: readOnlyAnnotations,
|
|
10134
|
+
description: "List the QA Wolf skills, each with its name and the description that says when to use it. A skill is the instructions a coding agent follows for one kind of QA Wolf work, such as onboarding an application, creating a flow, repairing a failing flow, or setting up triggers. Call this before any QA Wolf work, pick the skill whose description matches the request, and read it with skill.get.",
|
|
9305
10135
|
input,
|
|
9306
|
-
kind: "
|
|
9307
|
-
name: "
|
|
10136
|
+
kind: "read",
|
|
10137
|
+
name: "skill.list",
|
|
9308
10138
|
output
|
|
9309
10139
|
};
|
|
9310
10140
|
};
|
|
9311
|
-
var
|
|
9312
|
-
const input = object({
|
|
9313
|
-
const output =
|
|
10141
|
+
var makeGetSkillContract = () => {
|
|
10142
|
+
const input = object({ name: skillName });
|
|
10143
|
+
const output = skillSummary.extend({
|
|
10144
|
+
instructions: string2().describe("The skill's SKILL.md, frontmatter included."),
|
|
10145
|
+
references: array(object({
|
|
10146
|
+
path: string2().describe("The file's path relative to the skill directory."),
|
|
10147
|
+
text: string2().describe("The file's content.")
|
|
10148
|
+
})).describe("The files the skill links to under its directory.")
|
|
10149
|
+
});
|
|
9314
10150
|
return {
|
|
9315
|
-
annotations:
|
|
9316
|
-
|
|
9317
|
-
openWorldHint: true,
|
|
9318
|
-
readOnlyHint: false
|
|
9319
|
-
},
|
|
9320
|
-
description: "Resume a paused trigger. A schedule trigger restarts from the next " + "upcoming slot: the slots it missed while paused do not run.",
|
|
10151
|
+
annotations: readOnlyAnnotations,
|
|
10152
|
+
description: "Read a QA Wolf skill: the instructions a coding agent follows for one kind of QA Wolf work. The reply carries the skill's SKILL.md and every file under its references directory, so nothing else has to be fetched for it. Read the skill before starting the work it covers and follow it. A link in the reply of the form ../<skill>/SKILL.md names another skill, which this call reads by that name.",
|
|
9321
10153
|
input,
|
|
9322
|
-
kind: "
|
|
9323
|
-
name: "
|
|
10154
|
+
kind: "read",
|
|
10155
|
+
name: "skill.get",
|
|
9324
10156
|
output
|
|
9325
10157
|
};
|
|
9326
10158
|
};
|
|
9327
|
-
var
|
|
9328
|
-
|
|
10159
|
+
var makeSkillContracts = () => ({
|
|
10160
|
+
get: makeGetSkillContract(),
|
|
10161
|
+
list: makeListSkillsContract()
|
|
10162
|
+
});
|
|
10163
|
+
|
|
10164
|
+
// node_modules/@qawolf/api-contracts/dist/v1/tag/list.js
|
|
10165
|
+
var makeListTagsContract = (ids) => {
|
|
10166
|
+
const input = object({
|
|
10167
|
+
includeFlowIds: boolean2().default(false).describe("Also return the ids of the flows that carry each tag."),
|
|
10168
|
+
names: array(string2().trim().min(1)).min(1).max(100).optional().describe("Only list tags with these names. Matching is case sensitive. Omit to list all tags."),
|
|
10169
|
+
workspaceId: ids.workspace.optional().describe("The workspace to list tags from. Required when authenticating with an organization or user API key."),
|
|
10170
|
+
...makePaginationInputFields({ defaultLimit: 20, maxLimit: 100 })
|
|
10171
|
+
});
|
|
9329
10172
|
const output = object({
|
|
9330
|
-
|
|
10173
|
+
nextCursor: nextCursorSchema,
|
|
10174
|
+
tags: array(makeTagResourceSchema().extend({
|
|
10175
|
+
flowIds: array(ids.flow).optional().describe("Ids of the flows that carry the tag. Present only when includeFlowIds is set.")
|
|
10176
|
+
})).describe("The team's tags, alphabetical by name.")
|
|
9331
10177
|
});
|
|
9332
10178
|
return {
|
|
9333
10179
|
annotations: {
|
|
9334
|
-
destructiveHint:
|
|
10180
|
+
destructiveHint: false,
|
|
9335
10181
|
openWorldHint: false,
|
|
9336
|
-
readOnlyHint:
|
|
9337
|
-
},
|
|
9338
|
-
description: "Delete a trigger permanently. The runs it already created are kept. " + "To stop a trigger without losing it, use trigger.pause.",
|
|
9339
|
-
input,
|
|
9340
|
-
kind: "write",
|
|
9341
|
-
name: "trigger.delete",
|
|
9342
|
-
output
|
|
9343
|
-
};
|
|
9344
|
-
};
|
|
9345
|
-
|
|
9346
|
-
// node_modules/@qawolf/api-contracts/dist/v1/trigger/update.js
|
|
9347
|
-
var makeUpdateTriggerContract = (ids) => {
|
|
9348
|
-
const commonFields = {
|
|
9349
|
-
name: string2().trim().min(1).max(255),
|
|
9350
|
-
triggerId: ids.trigger
|
|
9351
|
-
};
|
|
9352
|
-
const input = discriminatedUnion("kind", [
|
|
9353
|
-
object({
|
|
9354
|
-
...commonFields,
|
|
9355
|
-
...makeTriggerScheduleFields({
|
|
9356
|
-
environmentId: ids.environmentRef,
|
|
9357
|
-
flow: ids.flow
|
|
9358
|
-
}),
|
|
9359
|
-
kind: literal("schedule")
|
|
9360
|
-
}),
|
|
9361
|
-
object({
|
|
9362
|
-
...commonFields,
|
|
9363
|
-
...makeTriggerDeploymentFields(ids),
|
|
9364
|
-
kind: literal("deployment")
|
|
9365
|
-
})
|
|
9366
|
-
]).superRefine(checkTriggerConfiguration);
|
|
9367
|
-
const output = object({ trigger: makeTriggerResourceSchema(ids) });
|
|
9368
|
-
return {
|
|
9369
|
-
annotations: {
|
|
9370
|
-
destructiveHint: true,
|
|
9371
|
-
openWorldHint: true,
|
|
9372
|
-
readOnlyHint: false
|
|
10182
|
+
readOnlyHint: true
|
|
9373
10183
|
},
|
|
9374
|
-
description: "
|
|
10184
|
+
description: "List the team's tags, alphabetical by name. Tag names select flows in run.create.",
|
|
9375
10185
|
input,
|
|
9376
|
-
kind: "
|
|
9377
|
-
name: "
|
|
10186
|
+
kind: "read",
|
|
10187
|
+
name: "tag.list",
|
|
9378
10188
|
output
|
|
9379
10189
|
};
|
|
9380
10190
|
};
|
|
@@ -9387,7 +10197,11 @@ var makeContractsV1 = (ids) => {
|
|
|
9387
10197
|
get: makeAgentGetContract(resolvedIds),
|
|
9388
10198
|
send: makeAgentSendContract(resolvedIds)
|
|
9389
10199
|
},
|
|
9390
|
-
|
|
10200
|
+
codeHostIntegration: {
|
|
10201
|
+
find: makeFindCodeHostIntegrationsContract(resolvedIds),
|
|
10202
|
+
listRepositories: makeListCodeHostRepositoriesContract(resolvedIds)
|
|
10203
|
+
},
|
|
10204
|
+
deployment: makeDeploymentContracts(resolvedIds),
|
|
9391
10205
|
email: {
|
|
9392
10206
|
find: makeFindEmailsContract(resolvedIds),
|
|
9393
10207
|
get: makeGetEmailContract(resolvedIds),
|
|
@@ -9421,44 +10235,23 @@ var makeContractsV1 = (ids) => {
|
|
|
9421
10235
|
removeFlows: makeRemoveFlowsFromIssueContract(resolvedIds),
|
|
9422
10236
|
update: makeUpdateIssueContract(resolvedIds)
|
|
9423
10237
|
},
|
|
10238
|
+
legacyTrigger: makeLegacyTriggerContracts(resolvedIds),
|
|
9424
10239
|
run: {
|
|
9425
10240
|
create: makeCreateRunContract(resolvedIds),
|
|
9426
10241
|
diagnose: makeDiagnoseRunContract(resolvedIds),
|
|
9427
10242
|
find: makeFindRunsContract(resolvedIds),
|
|
9428
10243
|
get: makeGetRunContract(resolvedIds),
|
|
9429
10244
|
reattempt: makeReattemptRunContract(resolvedIds),
|
|
9430
|
-
stop: makeStopRunContract(resolvedIds)
|
|
9431
|
-
|
|
9432
|
-
runner: {
|
|
9433
|
-
evaluateSnippet: makeEvaluateSnippetOnRunnerContract(resolvedIds),
|
|
9434
|
-
get: makeGetRunnerContract(resolvedIds),
|
|
9435
|
-
highlightSelector: makeHighlightSelectorOnRunnerContract(resolvedIds),
|
|
9436
|
-
importPackage: makeImportPackageOnRunnerContract(resolvedIds),
|
|
9437
|
-
inspect: makeInspectOnRunnerContract(resolvedIds),
|
|
9438
|
-
inspectMobile: makeInspectMobileOnRunnerContract(resolvedIds),
|
|
9439
|
-
launch: makeLaunchRunnerContract(resolvedIds),
|
|
9440
|
-
list: makeListRunnersContract(resolvedIds),
|
|
9441
|
-
performAction: makePerformActionOnRunnerContract(resolvedIds),
|
|
9442
|
-
promoteSnapshot: makePromoteSnapshotOnRunnerContract(resolvedIds),
|
|
9443
|
-
readJournal: makeReadRunnerJournalContract(resolvedIds),
|
|
9444
|
-
runFlow: makeRunFlowOnRunnerContract(resolvedIds),
|
|
9445
|
-
stopRun: makeStopRunOnRunnerContract(resolvedIds),
|
|
9446
|
-
takeScreenshot: makeTakeScreenshotOnRunnerContract(resolvedIds),
|
|
9447
|
-
terminate: makeTerminateRunnerContract(resolvedIds)
|
|
10245
|
+
stop: makeStopRunContract(resolvedIds),
|
|
10246
|
+
triage: makeTriageRunContract(resolvedIds)
|
|
9448
10247
|
},
|
|
10248
|
+
runner: makeRunnerContracts(resolvedIds),
|
|
10249
|
+
skill: makeSkillContracts(),
|
|
9449
10250
|
tag: {
|
|
9450
10251
|
create: makeCreateTagContract(resolvedIds),
|
|
9451
10252
|
list: makeListTagsContract(resolvedIds)
|
|
9452
10253
|
},
|
|
9453
|
-
trigger:
|
|
9454
|
-
create: makeCreateTriggerContract(resolvedIds),
|
|
9455
|
-
delete: makeDeleteTriggerContract(resolvedIds),
|
|
9456
|
-
find: makeFindTriggersContract(resolvedIds),
|
|
9457
|
-
get: makeGetTriggerContract(resolvedIds),
|
|
9458
|
-
pause: makePauseTriggerContract(resolvedIds),
|
|
9459
|
-
resume: makeResumeTriggerContract(resolvedIds),
|
|
9460
|
-
update: makeUpdateTriggerContract(resolvedIds)
|
|
9461
|
-
}
|
|
10254
|
+
trigger: makeTriggerContracts(resolvedIds)
|
|
9462
10255
|
};
|
|
9463
10256
|
};
|
|
9464
10257
|
var publicContractsV1 = makeContractsV1(defaultIdSchemas);
|
|
@@ -9820,6 +10613,37 @@ var interactMessages = {
|
|
|
9820
10613
|
promoteSnapshotAnsweredUnknown: (failureReason) => `The runner answered "${failureReason}", which this version of the CLI does not know how to report. Upgrade with npm install -g @qawolf/cli.`
|
|
9821
10614
|
};
|
|
9822
10615
|
|
|
10616
|
+
// src/core/messages/interactiveRunner/sequence.ts
|
|
10617
|
+
var sequenceMessages = {
|
|
10618
|
+
actionsEmpty: `The sequence holds no actions. Pass a JSON array of at least one, for example '[{"type":"click","button":"left","x":480,"y":260},{"type":"type","text":"hello"}]'.`,
|
|
10619
|
+
actionsInvalidAt: (index, error) => `Action ${index} in the sequence was refused: ${error}`,
|
|
10620
|
+
stdinEmptySequence: 'Nothing arrived on stdin. Pipe the sequence in, or pass the JSON array as the argument instead of "-".',
|
|
10621
|
+
actionsNotJsonArray: `The sequence must be a JSON array of actions, for example '[{"type":"click","button":"left","x":480,"y":260},{"type":"type","text":"hello"}]'.`,
|
|
10622
|
+
actionsEachNeedsAPath: "--screenshot-mode each writes one frame per action, so it needs --screenshot <path>; each frame goes to that path with the action's index before the extension.",
|
|
10623
|
+
actionsFinalNeedsAPath: "--screenshot-mode final asks the runner for one frame after the last action, so it needs --screenshot <path> to write it to. Leave the mode off to perform the actions without a frame.",
|
|
10624
|
+
actionsScreenshotWithModeNone: "--screenshot-mode none asks the runner for no frame, so --screenshot would have nothing to write. Drop one of the two.",
|
|
10625
|
+
actionsEachToStdout: "--screenshot-mode each writes one frame per action, which stdout cannot carry. Give --screenshot a file path.",
|
|
10626
|
+
actionsFailedFramesWritten: (paths) => `${paths.length === 1 ? "Its screen was" : "Its screens were"} written to ${paths.join(", ")}, so look at ${paths.length === 1 ? "that" : "those"} rather than sending anything again.`,
|
|
10627
|
+
actionsFailedScreenshotToStdout: "Its screen was written to stdout as a JPEG, so look at that rather than sending anything again.",
|
|
10628
|
+
actionsPerformed: (count) => `Performed ${count} ${count === 1 ? "action" : "actions"}.`,
|
|
10629
|
+
actionsPerformedOfTotal: (performed, total) => `Performed ${String(performed)} of ${pluralize(total, "action")}.`,
|
|
10630
|
+
actionsFramesUnwritable: (unwritten) => `The runner answered, but ${pluralize(unwritten.length, "frame")} could not be written: ${unwritten.map(({ detail, path }) => `"${path}" (${detail})`).join(", ")}. Whatever the actions did has already happened, so do not send them again: take the screen with qawolf runner screenshot, giving --out a path this process can write to.`,
|
|
10631
|
+
actionsFramesMissing: (indexes) => `The runner answered without the ${indexes.length === 1 ? "screen" : "screens"} after ${indexes.length === 1 ? "action" : "actions"} ${indexes.join(", ")}, so nothing was written for ${indexes.length === 1 ? "it" : "them"}. Whatever the actions did has already happened, so do not send them again: take the screen with qawolf runner screenshot instead.`,
|
|
10632
|
+
actionsPerformedWithoutScreenshot: (count) => `Performed ${pluralize(count, "action")}, but the runner answered without the screen it was asked for. Whatever the actions did has already happened, so do not send them again: take the screen with qawolf runner screenshot instead. If this keeps happening, the platform or this CLI is behind the other: upgrade with npm install -g @qawolf/cli.`,
|
|
10633
|
+
actionsPerformedFramesWritten: (count, paths) => `Performed ${pluralize(count, "action")} and wrote ${pluralize(paths.length, "screen")} to ${paths.join(", ")}.`,
|
|
10634
|
+
actionsPerformedScreenshotToStdout: (count) => `Performed ${pluralize(count, "action")} and wrote the runner's screen to stdout as a JPEG. Stdout holds the image bytes alone, so this line is on stderr and the per-action results are not printed at all: give --screenshot a file path when you need to read them.`,
|
|
10635
|
+
actionsPerformedScreenshotWritten: (count, path) => `Performed ${count} ${count === 1 ? "action" : "actions"} and wrote the runner's screen to ${path}.`,
|
|
10636
|
+
actionsOverLimit: (sent, limit) => `The sequence holds ${pluralize(sent, "action")}, and one request carries at most ${String(limit)}. Send them in batches, ending each at the action that changes the page.`,
|
|
10637
|
+
actionsNotAllSucceeded: (failed, total) => `${String(failed)} of ${pluralize(total, "action")} did not succeed.`,
|
|
10638
|
+
actionsFailedWithoutAResult: (failureReason) => `did not succeed ("${failureReason}"), and the answer carried no result for it. Take a screenshot before repeating anything from it on.`,
|
|
10639
|
+
actionsFailedAt: (index, type, why) => `Action ${index}${type === undefined ? "" : ` (${type})`} ${why}`,
|
|
10640
|
+
actionsLeftUnperformed: (count) => `${count} ${count === 1 ? "action" : "actions"} after it ${count === 1 ? "was" : "were"} not attempted.`,
|
|
10641
|
+
actionsMayHaveHappened: "It may have taken effect: take a screenshot before repeating anything from it on.",
|
|
10642
|
+
actionsOutOfTime: "was not reached before the sequence ran out of its time.",
|
|
10643
|
+
actionsPartlyApplied: (lastCompletedIndex) => `The sequence was partly applied: action ${String(lastCompletedIndex)} is the last one that took effect. Do not send it again as a whole; send only what still has to happen as a new request.`,
|
|
10644
|
+
actionsUnconfirmed: (errorMessage) => `has an unknown effect: ${errorMessage}`
|
|
10645
|
+
};
|
|
10646
|
+
|
|
9823
10647
|
// src/core/messages/interactiveRunner/lifecycle.ts
|
|
9824
10648
|
var pageAt = (url) => `Its runner page is at ${url}`;
|
|
9825
10649
|
var noRunnerId = "No runner id. Pass --runner, set QAWOLF_RUNNER_ID, or run qawolf runner launch first.";
|
|
@@ -9900,7 +10724,8 @@ var interactiveRunnerMessages = {
|
|
|
9900
10724
|
...lifecycleMessages,
|
|
9901
10725
|
...listMessages,
|
|
9902
10726
|
...runMessages,
|
|
9903
|
-
...interactMessages
|
|
10727
|
+
...interactMessages,
|
|
10728
|
+
...sequenceMessages
|
|
9904
10729
|
};
|
|
9905
10730
|
// src/core/messages/runner.ts
|
|
9906
10731
|
var maxListedNames = 5;
|
|
@@ -10043,6 +10868,9 @@ async function listRunners(ctx, deps) {
|
|
|
10043
10868
|
};
|
|
10044
10869
|
}
|
|
10045
10870
|
|
|
10871
|
+
// src/domains/interactiveRunner/deps.ts
|
|
10872
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
10873
|
+
|
|
10046
10874
|
// src/shell/interactiveRunner/collectRunFiles.ts
|
|
10047
10875
|
import { join as join2 } from "node:path";
|
|
10048
10876
|
|
|
@@ -11297,6 +12125,7 @@ function makeInteractiveRunnerDeps(options) {
|
|
|
11297
12125
|
cwd: options.cwd,
|
|
11298
12126
|
env: options.env,
|
|
11299
12127
|
makeRunnerId,
|
|
12128
|
+
makeRecordingId: randomUUID2,
|
|
11300
12129
|
readFile: (path) => options.fs.readFile(path),
|
|
11301
12130
|
readStdin,
|
|
11302
12131
|
runFilesManifest: makeRunFilesManifestStore({
|
|
@@ -11413,9 +12242,10 @@ function makeDefaultFs() {
|
|
|
11413
12242
|
}
|
|
11414
12243
|
|
|
11415
12244
|
// src/core/publicApi/notFoundSubject.ts
|
|
11416
|
-
var
|
|
12245
|
+
var runnerRoutesWithoutLivePod = new Set([
|
|
11417
12246
|
"runner.launch",
|
|
11418
|
-
"runner.list"
|
|
12247
|
+
"runner.list",
|
|
12248
|
+
"runner.recordings"
|
|
11419
12249
|
]);
|
|
11420
12250
|
var runRoutesThatResolveOneRun = new Set([
|
|
11421
12251
|
"run.diagnose",
|
|
@@ -11437,7 +12267,7 @@ function field(input, name) {
|
|
|
11437
12267
|
return typeof value === "string" ? value : undefined;
|
|
11438
12268
|
}
|
|
11439
12269
|
function notFoundSubject(contractName, input) {
|
|
11440
|
-
if (contractName.startsWith("runner.") && !
|
|
12270
|
+
if (contractName.startsWith("runner.") && !runnerRoutesWithoutLivePod.has(contractName)) {
|
|
11441
12271
|
return { kind: "runner", runnerId: field(input, "id") };
|
|
11442
12272
|
}
|
|
11443
12273
|
if (runRoutesThatResolveOneRun.has(contractName)) {
|
|
@@ -13977,12 +14807,63 @@ function createRunVerbs({ deps, platformClient }) {
|
|
|
13977
14807
|
};
|
|
13978
14808
|
}
|
|
13979
14809
|
|
|
14810
|
+
// src/domains/interactiveRunner/recordingRequests.ts
|
|
14811
|
+
async function recordOnRunner(ctx, runner, command) {
|
|
14812
|
+
const contract = publicContractsV1.runner.record;
|
|
14813
|
+
const parsed = contract.input.safeParse({ id: runner.runnerId, command });
|
|
14814
|
+
if (!parsed.success) {
|
|
14815
|
+
return {
|
|
14816
|
+
ok: false,
|
|
14817
|
+
error: "Invalid recording request. Runner ids must be valid and recording ids must be UUIDs.",
|
|
14818
|
+
exitCode: exitCodes.invalidArgs
|
|
14819
|
+
};
|
|
14820
|
+
}
|
|
14821
|
+
const result = await ctx.platformClient.callPublicApi(contract, parsed.data, runnerCallOptions);
|
|
14822
|
+
return result.ok ? result : { ok: false, ...runnerRequestFailure(result, runner) };
|
|
14823
|
+
}
|
|
14824
|
+
async function readRunnerRecordings(ctx, runner, query) {
|
|
14825
|
+
const contract = publicContractsV1.runner.recordings;
|
|
14826
|
+
const parsed = contract.input.safeParse({ id: runner.runnerId, ...query });
|
|
14827
|
+
if (!parsed.success) {
|
|
14828
|
+
return {
|
|
14829
|
+
ok: false,
|
|
14830
|
+
error: "Invalid recordings request. Use a valid runner id, a UUID recording id, and a page token of at most 4096 characters.",
|
|
14831
|
+
exitCode: exitCodes.invalidArgs
|
|
14832
|
+
};
|
|
14833
|
+
}
|
|
14834
|
+
const result = await ctx.platformClient.callPublicApi(contract, parsed.data);
|
|
14835
|
+
return result.ok ? result : { ok: false, ...runnerRequestFailure(result, runner) };
|
|
14836
|
+
}
|
|
14837
|
+
|
|
14838
|
+
// src/runnerSdk/recordingVerbs.ts
|
|
14839
|
+
function createRecordingVerbs(context) {
|
|
14840
|
+
return {
|
|
14841
|
+
async record({
|
|
14842
|
+
runnerId,
|
|
14843
|
+
command
|
|
14844
|
+
}) {
|
|
14845
|
+
return toSdkResult(await recordOnRunner(context, givenRunner(runnerId), command));
|
|
14846
|
+
},
|
|
14847
|
+
async listRecordings({
|
|
14848
|
+
runnerId,
|
|
14849
|
+
recordingId,
|
|
14850
|
+
pageToken
|
|
14851
|
+
}) {
|
|
14852
|
+
return toSdkResult(await readRunnerRecordings(context, givenRunner(runnerId), {
|
|
14853
|
+
...recordingId === undefined ? {} : { recordingId },
|
|
14854
|
+
...pageToken === undefined ? {} : { pageToken }
|
|
14855
|
+
}));
|
|
14856
|
+
}
|
|
14857
|
+
};
|
|
14858
|
+
}
|
|
14859
|
+
|
|
13980
14860
|
// src/runnerSdk/index.ts
|
|
13981
14861
|
function createRunnerSdk(options) {
|
|
13982
14862
|
const context = createSdkContext(options);
|
|
13983
14863
|
return {
|
|
13984
14864
|
...createLifecycleVerbs(context),
|
|
13985
14865
|
...createRunVerbs(context),
|
|
14866
|
+
...createRecordingVerbs(context),
|
|
13986
14867
|
...createPageVerbs(context),
|
|
13987
14868
|
...createProjectVerbs(context),
|
|
13988
14869
|
async list() {
|
|
@@ -13995,4 +14876,4 @@ export {
|
|
|
13995
14876
|
createRunnerSdk
|
|
13996
14877
|
};
|
|
13997
14878
|
|
|
13998
|
-
//# debugId=
|
|
14879
|
+
//# debugId=A7A37F8150999CFE64756E2164756E21
|