@qawolf/cli 1.23.0 → 1.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +2215 -640
- package/dist/runner-sdk.js +839 -139
- package/dist/types/runnerSdk/types.d.ts +6 -2
- package/package.json +2 -2
- package/skills/qawolf-cli/SKILL.md +11 -3
package/dist/runner-sdk.js
CHANGED
|
@@ -5494,9 +5494,34 @@ var bigintProcessor = (_schema, ctx, _json, _params) => {
|
|
|
5494
5494
|
throw new Error("BigInt cannot be represented in JSON Schema");
|
|
5495
5495
|
}
|
|
5496
5496
|
};
|
|
5497
|
+
var symbolProcessor = (_schema, ctx, _json, _params) => {
|
|
5498
|
+
if (ctx.unrepresentable === "throw") {
|
|
5499
|
+
throw new Error("Symbols cannot be represented in JSON Schema");
|
|
5500
|
+
}
|
|
5501
|
+
};
|
|
5502
|
+
var nullProcessor = (_schema, ctx, json, _params) => {
|
|
5503
|
+
if (ctx.target === "openapi-3.0") {
|
|
5504
|
+
json.type = "string";
|
|
5505
|
+
json.nullable = true;
|
|
5506
|
+
json.enum = [null];
|
|
5507
|
+
} else {
|
|
5508
|
+
json.type = "null";
|
|
5509
|
+
}
|
|
5510
|
+
};
|
|
5511
|
+
var undefinedProcessor = (_schema, ctx, _json, _params) => {
|
|
5512
|
+
if (ctx.unrepresentable === "throw") {
|
|
5513
|
+
throw new Error("Undefined cannot be represented in JSON Schema");
|
|
5514
|
+
}
|
|
5515
|
+
};
|
|
5516
|
+
var voidProcessor = (_schema, ctx, _json, _params) => {
|
|
5517
|
+
if (ctx.unrepresentable === "throw") {
|
|
5518
|
+
throw new Error("Void cannot be represented in JSON Schema");
|
|
5519
|
+
}
|
|
5520
|
+
};
|
|
5497
5521
|
var neverProcessor = (_schema, _ctx, json, _params) => {
|
|
5498
5522
|
json.not = {};
|
|
5499
5523
|
};
|
|
5524
|
+
var anyProcessor = (_schema, _ctx, _json, _params) => {};
|
|
5500
5525
|
var unknownProcessor = (_schema, _ctx, _json, _params) => {};
|
|
5501
5526
|
var dateProcessor = (_schema, ctx, _json, _params) => {
|
|
5502
5527
|
if (ctx.unrepresentable === "throw") {
|
|
@@ -5550,16 +5575,71 @@ var literalProcessor = (schema, ctx, json, _params) => {
|
|
|
5550
5575
|
json.enum = vals;
|
|
5551
5576
|
}
|
|
5552
5577
|
};
|
|
5578
|
+
var nanProcessor = (_schema, ctx, _json, _params) => {
|
|
5579
|
+
if (ctx.unrepresentable === "throw") {
|
|
5580
|
+
throw new Error("NaN cannot be represented in JSON Schema");
|
|
5581
|
+
}
|
|
5582
|
+
};
|
|
5583
|
+
var templateLiteralProcessor = (schema, _ctx, json, _params) => {
|
|
5584
|
+
const _json = json;
|
|
5585
|
+
const pattern = schema._zod.pattern;
|
|
5586
|
+
if (!pattern)
|
|
5587
|
+
throw new Error("Pattern not found in template literal");
|
|
5588
|
+
_json.type = "string";
|
|
5589
|
+
_json.pattern = pattern.source;
|
|
5590
|
+
};
|
|
5591
|
+
var fileProcessor = (schema, _ctx, json, _params) => {
|
|
5592
|
+
const _json = json;
|
|
5593
|
+
const file = {
|
|
5594
|
+
type: "string",
|
|
5595
|
+
format: "binary",
|
|
5596
|
+
contentEncoding: "binary"
|
|
5597
|
+
};
|
|
5598
|
+
const { minimum, maximum, mime } = schema._zod.bag;
|
|
5599
|
+
if (minimum !== undefined)
|
|
5600
|
+
file.minLength = minimum;
|
|
5601
|
+
if (maximum !== undefined)
|
|
5602
|
+
file.maxLength = maximum;
|
|
5603
|
+
if (mime) {
|
|
5604
|
+
if (mime.length === 1) {
|
|
5605
|
+
file.contentMediaType = mime[0];
|
|
5606
|
+
Object.assign(_json, file);
|
|
5607
|
+
} else {
|
|
5608
|
+
Object.assign(_json, file);
|
|
5609
|
+
_json.anyOf = mime.map((m) => ({ contentMediaType: m }));
|
|
5610
|
+
}
|
|
5611
|
+
} else {
|
|
5612
|
+
Object.assign(_json, file);
|
|
5613
|
+
}
|
|
5614
|
+
};
|
|
5615
|
+
var successProcessor = (_schema, _ctx, json, _params) => {
|
|
5616
|
+
json.type = "boolean";
|
|
5617
|
+
};
|
|
5553
5618
|
var customProcessor = (_schema, ctx, _json, _params) => {
|
|
5554
5619
|
if (ctx.unrepresentable === "throw") {
|
|
5555
5620
|
throw new Error("Custom types cannot be represented in JSON Schema");
|
|
5556
5621
|
}
|
|
5557
5622
|
};
|
|
5623
|
+
var functionProcessor = (_schema, ctx, _json, _params) => {
|
|
5624
|
+
if (ctx.unrepresentable === "throw") {
|
|
5625
|
+
throw new Error("Function types cannot be represented in JSON Schema");
|
|
5626
|
+
}
|
|
5627
|
+
};
|
|
5558
5628
|
var transformProcessor = (_schema, ctx, _json, _params) => {
|
|
5559
5629
|
if (ctx.unrepresentable === "throw") {
|
|
5560
5630
|
throw new Error("Transforms cannot be represented in JSON Schema");
|
|
5561
5631
|
}
|
|
5562
5632
|
};
|
|
5633
|
+
var mapProcessor = (_schema, ctx, _json, _params) => {
|
|
5634
|
+
if (ctx.unrepresentable === "throw") {
|
|
5635
|
+
throw new Error("Map cannot be represented in JSON Schema");
|
|
5636
|
+
}
|
|
5637
|
+
};
|
|
5638
|
+
var setProcessor = (_schema, ctx, _json, _params) => {
|
|
5639
|
+
if (ctx.unrepresentable === "throw") {
|
|
5640
|
+
throw new Error("Set cannot be represented in JSON Schema");
|
|
5641
|
+
}
|
|
5642
|
+
};
|
|
5563
5643
|
var arrayProcessor = (schema, ctx, _json, params) => {
|
|
5564
5644
|
const json = _json;
|
|
5565
5645
|
const def = schema._zod.def;
|
|
@@ -5640,6 +5720,48 @@ var intersectionProcessor = (schema, ctx, json, params) => {
|
|
|
5640
5720
|
];
|
|
5641
5721
|
json.allOf = allOf;
|
|
5642
5722
|
};
|
|
5723
|
+
var tupleProcessor = (schema, ctx, _json, params) => {
|
|
5724
|
+
const json = _json;
|
|
5725
|
+
const def = schema._zod.def;
|
|
5726
|
+
json.type = "array";
|
|
5727
|
+
const prefixPath = ctx.target === "draft-2020-12" ? "prefixItems" : "items";
|
|
5728
|
+
const restPath = ctx.target === "draft-2020-12" ? "items" : ctx.target === "openapi-3.0" ? "items" : "additionalItems";
|
|
5729
|
+
const prefixItems = def.items.map((x, i) => process2(x, ctx, {
|
|
5730
|
+
...params,
|
|
5731
|
+
path: [...params.path, prefixPath, i]
|
|
5732
|
+
}));
|
|
5733
|
+
const rest = def.rest ? process2(def.rest, ctx, {
|
|
5734
|
+
...params,
|
|
5735
|
+
path: [...params.path, restPath, ...ctx.target === "openapi-3.0" ? [def.items.length] : []]
|
|
5736
|
+
}) : null;
|
|
5737
|
+
if (ctx.target === "draft-2020-12") {
|
|
5738
|
+
json.prefixItems = prefixItems;
|
|
5739
|
+
if (rest) {
|
|
5740
|
+
json.items = rest;
|
|
5741
|
+
}
|
|
5742
|
+
} else if (ctx.target === "openapi-3.0") {
|
|
5743
|
+
json.items = {
|
|
5744
|
+
anyOf: prefixItems
|
|
5745
|
+
};
|
|
5746
|
+
if (rest) {
|
|
5747
|
+
json.items.anyOf.push(rest);
|
|
5748
|
+
}
|
|
5749
|
+
json.minItems = prefixItems.length;
|
|
5750
|
+
if (!rest) {
|
|
5751
|
+
json.maxItems = prefixItems.length;
|
|
5752
|
+
}
|
|
5753
|
+
} else {
|
|
5754
|
+
json.items = prefixItems;
|
|
5755
|
+
if (rest) {
|
|
5756
|
+
json.additionalItems = rest;
|
|
5757
|
+
}
|
|
5758
|
+
}
|
|
5759
|
+
const { minimum, maximum } = schema._zod.bag;
|
|
5760
|
+
if (typeof minimum === "number")
|
|
5761
|
+
json.minItems = minimum;
|
|
5762
|
+
if (typeof maximum === "number")
|
|
5763
|
+
json.maxItems = maximum;
|
|
5764
|
+
};
|
|
5643
5765
|
var recordProcessor = (schema, ctx, _json, params) => {
|
|
5644
5766
|
const json = _json;
|
|
5645
5767
|
const def = schema._zod.def;
|
|
@@ -5736,6 +5858,12 @@ var readonlyProcessor = (schema, ctx, json, params) => {
|
|
|
5736
5858
|
seen.ref = def.innerType;
|
|
5737
5859
|
json.readOnly = true;
|
|
5738
5860
|
};
|
|
5861
|
+
var promiseProcessor = (schema, ctx, _json, params) => {
|
|
5862
|
+
const def = schema._zod.def;
|
|
5863
|
+
process2(def.innerType, ctx, params);
|
|
5864
|
+
const seen = ctx.seen.get(schema);
|
|
5865
|
+
seen.ref = def.innerType;
|
|
5866
|
+
};
|
|
5739
5867
|
var optionalProcessor = (schema, ctx, _json, params) => {
|
|
5740
5868
|
const def = schema._zod.def;
|
|
5741
5869
|
process2(def.innerType, ctx, params);
|
|
@@ -5748,6 +5876,81 @@ var lazyProcessor = (schema, ctx, _json, params) => {
|
|
|
5748
5876
|
const seen = ctx.seen.get(schema);
|
|
5749
5877
|
seen.ref = innerType;
|
|
5750
5878
|
};
|
|
5879
|
+
var allProcessors = {
|
|
5880
|
+
string: stringProcessor,
|
|
5881
|
+
number: numberProcessor,
|
|
5882
|
+
boolean: booleanProcessor,
|
|
5883
|
+
bigint: bigintProcessor,
|
|
5884
|
+
symbol: symbolProcessor,
|
|
5885
|
+
null: nullProcessor,
|
|
5886
|
+
undefined: undefinedProcessor,
|
|
5887
|
+
void: voidProcessor,
|
|
5888
|
+
never: neverProcessor,
|
|
5889
|
+
any: anyProcessor,
|
|
5890
|
+
unknown: unknownProcessor,
|
|
5891
|
+
date: dateProcessor,
|
|
5892
|
+
enum: enumProcessor,
|
|
5893
|
+
literal: literalProcessor,
|
|
5894
|
+
nan: nanProcessor,
|
|
5895
|
+
template_literal: templateLiteralProcessor,
|
|
5896
|
+
file: fileProcessor,
|
|
5897
|
+
success: successProcessor,
|
|
5898
|
+
custom: customProcessor,
|
|
5899
|
+
function: functionProcessor,
|
|
5900
|
+
transform: transformProcessor,
|
|
5901
|
+
map: mapProcessor,
|
|
5902
|
+
set: setProcessor,
|
|
5903
|
+
array: arrayProcessor,
|
|
5904
|
+
object: objectProcessor,
|
|
5905
|
+
union: unionProcessor,
|
|
5906
|
+
intersection: intersectionProcessor,
|
|
5907
|
+
tuple: tupleProcessor,
|
|
5908
|
+
record: recordProcessor,
|
|
5909
|
+
nullable: nullableProcessor,
|
|
5910
|
+
nonoptional: nonoptionalProcessor,
|
|
5911
|
+
default: defaultProcessor,
|
|
5912
|
+
prefault: prefaultProcessor,
|
|
5913
|
+
catch: catchProcessor,
|
|
5914
|
+
pipe: pipeProcessor,
|
|
5915
|
+
readonly: readonlyProcessor,
|
|
5916
|
+
promise: promiseProcessor,
|
|
5917
|
+
optional: optionalProcessor,
|
|
5918
|
+
lazy: lazyProcessor
|
|
5919
|
+
};
|
|
5920
|
+
function toJSONSchema(input, params) {
|
|
5921
|
+
if ("_idmap" in input) {
|
|
5922
|
+
const registry = input;
|
|
5923
|
+
const ctx = initializeContext({ ...params, processors: allProcessors });
|
|
5924
|
+
const defs = {};
|
|
5925
|
+
for (const entry of registry._idmap.entries()) {
|
|
5926
|
+
const [_, schema] = entry;
|
|
5927
|
+
process2(schema, ctx);
|
|
5928
|
+
}
|
|
5929
|
+
const schemas = {};
|
|
5930
|
+
const external = {
|
|
5931
|
+
registry,
|
|
5932
|
+
uri: params?.uri,
|
|
5933
|
+
defs
|
|
5934
|
+
};
|
|
5935
|
+
ctx.external = external;
|
|
5936
|
+
for (const entry of registry._idmap.entries()) {
|
|
5937
|
+
const [key, schema] = entry;
|
|
5938
|
+
extractDefs(ctx, schema);
|
|
5939
|
+
schemas[key] = finalize(ctx, schema);
|
|
5940
|
+
}
|
|
5941
|
+
if (Object.keys(defs).length > 0) {
|
|
5942
|
+
const defsSegment = ctx.target === "draft-2020-12" ? "$defs" : "definitions";
|
|
5943
|
+
schemas.__shared = {
|
|
5944
|
+
[defsSegment]: defs
|
|
5945
|
+
};
|
|
5946
|
+
}
|
|
5947
|
+
return { schemas };
|
|
5948
|
+
}
|
|
5949
|
+
const ctx = initializeContext({ ...params, processors: allProcessors });
|
|
5950
|
+
process2(input, ctx);
|
|
5951
|
+
extractDefs(ctx, input);
|
|
5952
|
+
return finalize(ctx, input);
|
|
5953
|
+
}
|
|
5751
5954
|
// node_modules/zod/v4/classic/iso.js
|
|
5752
5955
|
var exports_iso = {};
|
|
5753
5956
|
__export(exports_iso, {
|
|
@@ -6102,6 +6305,9 @@ var ZodEmail = /* @__PURE__ */ $constructor("ZodEmail", (inst, def) => {
|
|
|
6102
6305
|
$ZodEmail.init(inst, def);
|
|
6103
6306
|
ZodStringFormat.init(inst, def);
|
|
6104
6307
|
});
|
|
6308
|
+
function email2(params) {
|
|
6309
|
+
return _email(ZodEmail, params);
|
|
6310
|
+
}
|
|
6105
6311
|
var ZodGUID = /* @__PURE__ */ $constructor("ZodGUID", (inst, def) => {
|
|
6106
6312
|
$ZodGUID.init(inst, def);
|
|
6107
6313
|
ZodStringFormat.init(inst, def);
|
|
@@ -6165,6 +6371,9 @@ var ZodBase64 = /* @__PURE__ */ $constructor("ZodBase64", (inst, def) => {
|
|
|
6165
6371
|
$ZodBase64.init(inst, def);
|
|
6166
6372
|
ZodStringFormat.init(inst, def);
|
|
6167
6373
|
});
|
|
6374
|
+
function base642(params) {
|
|
6375
|
+
return _base64(ZodBase64, params);
|
|
6376
|
+
}
|
|
6168
6377
|
var ZodBase64URL = /* @__PURE__ */ $constructor("ZodBase64URL", (inst, def) => {
|
|
6169
6378
|
$ZodBase64URL.init(inst, def);
|
|
6170
6379
|
ZodStringFormat.init(inst, def);
|
|
@@ -6747,6 +6956,44 @@ var agentReplySchema = object({
|
|
|
6747
6956
|
text: string2().describe("What the AI said.")
|
|
6748
6957
|
});
|
|
6749
6958
|
|
|
6959
|
+
// node_modules/@qawolf/api-contracts/dist/v1/resource.js
|
|
6960
|
+
function resource(fields, { urlFieldDescription = "Absolute URL." } = {}) {
|
|
6961
|
+
return object({
|
|
6962
|
+
...fields,
|
|
6963
|
+
url: url().describe(urlFieldDescription)
|
|
6964
|
+
});
|
|
6965
|
+
}
|
|
6966
|
+
|
|
6967
|
+
// node_modules/@qawolf/api-contracts/dist/v1/email/resource.js
|
|
6968
|
+
var emailDirectionSchema = _enum(["inbound", "outbound"]);
|
|
6969
|
+
var namedAddressSchema = object({
|
|
6970
|
+
address: string2().describe("The email address."),
|
|
6971
|
+
name: string2().optional().describe("The display name, when the message carried one.")
|
|
6972
|
+
});
|
|
6973
|
+
var emailUrlFieldDescription = "Absolute URL of the workspace. The inbox opens from the app header.";
|
|
6974
|
+
var makeEmailSummaryFields = () => ({
|
|
6975
|
+
createdAt: exports_iso.datetime({ offset: true }).describe("When QA Wolf received or sent the email."),
|
|
6976
|
+
direction: emailDirectionSchema.describe("inbound for mail the workspace received, outbound for mail it sent."),
|
|
6977
|
+
from: namedAddressSchema,
|
|
6978
|
+
id: string2().min(1).describe("The id of the email. Pass it to email.get to read the body."),
|
|
6979
|
+
subject: string2().optional(),
|
|
6980
|
+
to: array(namedAddressSchema)
|
|
6981
|
+
});
|
|
6982
|
+
var makeEmailResourceSchema = () => resource({
|
|
6983
|
+
...makeEmailSummaryFields(),
|
|
6984
|
+
attachments: array(object({
|
|
6985
|
+
fileName: string2(),
|
|
6986
|
+
index: number2().int().min(0).describe("The position of the attachment in the email, from 0. Pass it to email.getAttachment when file names repeat."),
|
|
6987
|
+
type: string2().optional().describe("The MIME type.")
|
|
6988
|
+
})).optional().describe("Attachment names, positions, and types. Read the content with email.getAttachment."),
|
|
6989
|
+
bcc: array(namedAddressSchema).optional(),
|
|
6990
|
+
cc: array(namedAddressSchema).optional(),
|
|
6991
|
+
html: string2().optional().describe("The HTML body."),
|
|
6992
|
+
links: array(string2()).describe("The links of the email, in order: HTML anchors, then images, then bare URLs of the plain text body. Follow one to confirm a sign-up or reset a password."),
|
|
6993
|
+
replyTo: array(namedAddressSchema).optional(),
|
|
6994
|
+
text: string2().optional().describe("The plain text body.")
|
|
6995
|
+
}, { urlFieldDescription: emailUrlFieldDescription });
|
|
6996
|
+
|
|
6750
6997
|
// node_modules/@qawolf/api-contracts/dist/v1/identity/organization.js
|
|
6751
6998
|
var identityOrganization = object({
|
|
6752
6999
|
id: string2(),
|
|
@@ -6789,6 +7036,10 @@ var identityResponse = union([
|
|
|
6789
7036
|
user: never().optional()
|
|
6790
7037
|
}).transform(({ organization }) => ({ organization }))
|
|
6791
7038
|
]);
|
|
7039
|
+
// node_modules/@qawolf/api-contracts/dist/v1/identity/organizations.js
|
|
7040
|
+
var identityOrganizationsResponse = object({
|
|
7041
|
+
organizations: array(identityOrganization)
|
|
7042
|
+
});
|
|
6792
7043
|
// node_modules/@qawolf/api-contracts/dist/v1/ids.js
|
|
6793
7044
|
var defaultIdSchemas = {
|
|
6794
7045
|
aiTask: string2().min(1).describe("The id of the AI task."),
|
|
@@ -6802,14 +7053,6 @@ var defaultIdSchemas = {
|
|
|
6802
7053
|
workspace: string2().min(1).describe("The id of the workspace.")
|
|
6803
7054
|
};
|
|
6804
7055
|
|
|
6805
|
-
// node_modules/@qawolf/api-contracts/dist/v1/resource.js
|
|
6806
|
-
function resource(fields, { urlFieldDescription = "Absolute URL." } = {}) {
|
|
6807
|
-
return object({
|
|
6808
|
-
...fields,
|
|
6809
|
-
url: url().describe(urlFieldDescription)
|
|
6810
|
-
});
|
|
6811
|
-
}
|
|
6812
|
-
|
|
6813
7056
|
// node_modules/@qawolf/api-contracts/dist/v1/run/flowSelection.js
|
|
6814
7057
|
var makeFlowSelectionSchema = (ids) => object({
|
|
6815
7058
|
flowIds: array(ids.flow).default([]),
|
|
@@ -7344,6 +7587,131 @@ var makeAutomateContract = (ids) => {
|
|
|
7344
7587
|
};
|
|
7345
7588
|
};
|
|
7346
7589
|
|
|
7590
|
+
// node_modules/@qawolf/api-contracts/dist/v1/pagination.js
|
|
7591
|
+
var makePaginationInputFields = (limits) => ({
|
|
7592
|
+
cursor: string2().min(1).optional().describe("Opaque cursor copied from the previous response's nextCursor. Omit to fetch the first page."),
|
|
7593
|
+
limit: number2().int().min(1).max(limits.maxLimit).default(limits.defaultLimit).describe(`Maximum rows per page. Defaults to ${limits.defaultLimit}, capped at ${limits.maxLimit}.`)
|
|
7594
|
+
});
|
|
7595
|
+
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.");
|
|
7596
|
+
|
|
7597
|
+
// node_modules/@qawolf/api-contracts/dist/v1/email/find.js
|
|
7598
|
+
var makeFindEmailsContract = (ids) => {
|
|
7599
|
+
const input = object({
|
|
7600
|
+
address: email2().optional().describe("Only emails delivered to this exact address (inbound) or sent from it (outbound). Mail to a plus-suffixed address such as inbox+abc@example.com is found by that full address, not by inbox@example.com."),
|
|
7601
|
+
createdAfter: exports_iso.datetime({ offset: true }).optional().describe("Only include emails received or sent after this instant, e.g. since a flow submitted a sign-up form."),
|
|
7602
|
+
direction: emailDirectionSchema.default("inbound").describe("inbound lists the mail the workspace received: its inbox. outbound lists the mail it sent."),
|
|
7603
|
+
workspaceId: ids.workspace.optional().describe("The workspace whose emails to list. Required when authenticating with an organization or user API key."),
|
|
7604
|
+
...makePaginationInputFields({ defaultLimit: 20, maxLimit: 50 })
|
|
7605
|
+
});
|
|
7606
|
+
const output = object({
|
|
7607
|
+
emails: array(resource(makeEmailSummaryFields(), {
|
|
7608
|
+
urlFieldDescription: emailUrlFieldDescription
|
|
7609
|
+
})).describe("The workspace's emails, newest first. Bodies are available via email.get."),
|
|
7610
|
+
nextCursor: nextCursorSchema
|
|
7611
|
+
});
|
|
7612
|
+
return {
|
|
7613
|
+
description: "List the workspace's inbox, or its sent mail, newest first. Read a message body with email.get.",
|
|
7614
|
+
input,
|
|
7615
|
+
kind: "read",
|
|
7616
|
+
name: "email.find",
|
|
7617
|
+
output
|
|
7618
|
+
};
|
|
7619
|
+
};
|
|
7620
|
+
|
|
7621
|
+
// node_modules/@qawolf/api-contracts/dist/v1/email/get.js
|
|
7622
|
+
var makeGetEmailContract = (ids) => {
|
|
7623
|
+
const input = object({
|
|
7624
|
+
id: string2().min(1).describe("The id of the email, from email.find."),
|
|
7625
|
+
workspaceId: ids.workspace.optional().describe("The workspace the email belongs to. Required when authenticating with an organization or user API key.")
|
|
7626
|
+
});
|
|
7627
|
+
const output = makeEmailResourceSchema();
|
|
7628
|
+
return {
|
|
7629
|
+
description: "Read one email of the workspace, with its plain text and HTML bodies. Use it to pull a sign-in code or a verification link out of a message.",
|
|
7630
|
+
input,
|
|
7631
|
+
kind: "read",
|
|
7632
|
+
name: "email.get",
|
|
7633
|
+
output
|
|
7634
|
+
};
|
|
7635
|
+
};
|
|
7636
|
+
|
|
7637
|
+
// node_modules/@qawolf/api-contracts/dist/v1/email/getAttachment.js
|
|
7638
|
+
var makeGetEmailAttachmentContract = (ids) => {
|
|
7639
|
+
const input = object({
|
|
7640
|
+
fileName: string2().min(1).optional().describe("The attachment's file name, as email.get lists it. The first attachment with that name is returned."),
|
|
7641
|
+
id: string2().min(1).describe("The id of the email, from email.find."),
|
|
7642
|
+
index: number2().int().min(0).optional().describe("The attachment's position in the email, from 0, as email.get lists it. Use it when file names repeat."),
|
|
7643
|
+
workspaceId: ids.workspace.optional().describe("The workspace the email belongs to. Required when authenticating with an organization or user API key.")
|
|
7644
|
+
}).refine((input) => input.fileName === undefined !== (input.index === undefined), { message: "Provide fileName or index, not both." });
|
|
7645
|
+
const output = resource({
|
|
7646
|
+
contentBase64: string2().describe("The file content, base64 encoded."),
|
|
7647
|
+
fileName: string2(),
|
|
7648
|
+
index: number2().int().min(0).describe("The position of the attachment in the email, from 0."),
|
|
7649
|
+
type: string2().optional().describe("The MIME type.")
|
|
7650
|
+
}, { urlFieldDescription: emailUrlFieldDescription });
|
|
7651
|
+
return {
|
|
7652
|
+
description: "Read one attachment of a workspace email as base64 content, by file name or by position. email.get lists both.",
|
|
7653
|
+
input,
|
|
7654
|
+
kind: "read",
|
|
7655
|
+
name: "email.getAttachment",
|
|
7656
|
+
output
|
|
7657
|
+
};
|
|
7658
|
+
};
|
|
7659
|
+
|
|
7660
|
+
// node_modules/@qawolf/api-contracts/dist/v1/email/listAddresses.js
|
|
7661
|
+
var makeListEmailAddressesContract = (ids) => {
|
|
7662
|
+
const input = object({
|
|
7663
|
+
workspaceId: ids.workspace.optional().describe("The workspace whose inbox addresses to list. Required when authenticating with an organization or user API key."),
|
|
7664
|
+
...makePaginationInputFields({ defaultLimit: 20, maxLimit: 50 })
|
|
7665
|
+
});
|
|
7666
|
+
const output = object({
|
|
7667
|
+
addresses: array(resource({
|
|
7668
|
+
address: string2().describe("The inbox address. Mail sent to any plus-suffixed form, such as inbox+abc@example.com, lands in the same inbox."),
|
|
7669
|
+
isDefault: boolean2().describe("Whether this is the workspace's default inbox address.")
|
|
7670
|
+
}, { urlFieldDescription: emailUrlFieldDescription })).describe("The workspace's permanent inbox addresses, alphabetical."),
|
|
7671
|
+
nextCursor: nextCursorSchema
|
|
7672
|
+
});
|
|
7673
|
+
return {
|
|
7674
|
+
description: "List the workspace's inbox addresses, alphabetical. A flow can sign up with a plus-suffixed form of any of them, and email.find reads what arrives.",
|
|
7675
|
+
input,
|
|
7676
|
+
kind: "read",
|
|
7677
|
+
name: "email.listAddresses",
|
|
7678
|
+
output
|
|
7679
|
+
};
|
|
7680
|
+
};
|
|
7681
|
+
|
|
7682
|
+
// node_modules/@qawolf/api-contracts/dist/v1/email/send.js
|
|
7683
|
+
var recipientsSchema = array(email2()).max(50);
|
|
7684
|
+
var maxAttachments = 10;
|
|
7685
|
+
var maxEmailAttachmentsBase64Length = 30 * 1024 * 1024;
|
|
7686
|
+
var attachmentsBase64Length = (attachments) => Object.values(attachments).reduce((total, content) => total + content.length, 0);
|
|
7687
|
+
var makeSendEmailContract = (ids) => {
|
|
7688
|
+
const input = object({
|
|
7689
|
+
attachments: record(string2().min(1), base642()).refine((attachments) => Object.keys(attachments).length <= maxAttachments, { message: `Send at most ${maxAttachments} attachments.` }).refine((attachments) => attachmentsBase64Length(attachments) <= maxEmailAttachmentsBase64Length, { message: "Send at most 30 MB of attachments." }).optional().describe("Files to attach, as file name to base64 content, at most 30 MB in total. The MIME type comes from the file name's extension."),
|
|
7690
|
+
bcc: recipientsSchema.optional(),
|
|
7691
|
+
cc: recipientsSchema.optional(),
|
|
7692
|
+
from: email2().optional().describe("The workspace inbox address to send from, or a plus-suffixed form of one. Defaults to the workspace's default inbox address. See email.listAddresses."),
|
|
7693
|
+
html: string2().optional().describe("The HTML body."),
|
|
7694
|
+
inReplyTo: string2().min(1).optional().describe("The id of an email of the workspace to reply to, from email.find. The reply threads under that message."),
|
|
7695
|
+
replyTo: recipientsSchema.optional().describe("Where replies should go instead of the from address."),
|
|
7696
|
+
subject: string2().min(1),
|
|
7697
|
+
text: string2().optional().describe("The plain text body."),
|
|
7698
|
+
to: recipientsSchema.min(1),
|
|
7699
|
+
workspaceId: ids.workspace.optional().describe("The workspace to send from. Required when authenticating with an organization or user API key.")
|
|
7700
|
+
}).refine((email) => email.html || email.text, {
|
|
7701
|
+
message: "Provide text, html, or both."
|
|
7702
|
+
});
|
|
7703
|
+
const output = resource(makeEmailSummaryFields(), {
|
|
7704
|
+
urlFieldDescription: emailUrlFieldDescription
|
|
7705
|
+
});
|
|
7706
|
+
return {
|
|
7707
|
+
description: "Send an email from one of the workspace's inbox addresses, for example to exercise a flow that reacts to incoming mail. Returns the sent email; read it back with email.get.",
|
|
7708
|
+
input,
|
|
7709
|
+
kind: "write",
|
|
7710
|
+
name: "email.send",
|
|
7711
|
+
output
|
|
7712
|
+
};
|
|
7713
|
+
};
|
|
7714
|
+
|
|
7347
7715
|
// node_modules/@qawolf/api-contracts/dist/v1/environment/deleteVariable.js
|
|
7348
7716
|
var makeDeleteEnvironmentVariableContract = (ids) => {
|
|
7349
7717
|
const input = object({
|
|
@@ -7362,13 +7730,6 @@ var makeDeleteEnvironmentVariableContract = (ids) => {
|
|
|
7362
7730
|
};
|
|
7363
7731
|
};
|
|
7364
7732
|
|
|
7365
|
-
// node_modules/@qawolf/api-contracts/dist/v1/pagination.js
|
|
7366
|
-
var makePaginationInputFields = (limits) => ({
|
|
7367
|
-
cursor: string2().min(1).optional().describe("Opaque cursor copied from the previous response's nextCursor. Omit to fetch the first page."),
|
|
7368
|
-
limit: number2().int().min(1).max(limits.maxLimit).default(limits.defaultLimit).describe(`Maximum rows per page. Defaults to ${limits.defaultLimit}, capped at ${limits.maxLimit}.`)
|
|
7369
|
-
});
|
|
7370
|
-
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.");
|
|
7371
|
-
|
|
7372
7733
|
// node_modules/@qawolf/api-contracts/dist/v1/environment/resource.js
|
|
7373
7734
|
var makeEnvironmentResourceSchema = (ids) => resource({
|
|
7374
7735
|
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."),
|
|
@@ -7540,15 +7901,27 @@ var makeCreateTagContract = (ids) => {
|
|
|
7540
7901
|
};
|
|
7541
7902
|
};
|
|
7542
7903
|
|
|
7904
|
+
// node_modules/@qawolf/api-contracts/dist/v1/flow/skippedFlows.js
|
|
7905
|
+
var makeSkippedFlowsSchema = (ids, { description, reason }) => array(object({
|
|
7906
|
+
flowId: ids.flow,
|
|
7907
|
+
name: string2().describe("The name of the flow."),
|
|
7908
|
+
reason
|
|
7909
|
+
})).describe(description);
|
|
7910
|
+
|
|
7543
7911
|
// node_modules/@qawolf/api-contracts/dist/v1/flow/addTag.js
|
|
7544
7912
|
var makeAddTagToFlowsContract = (ids) => {
|
|
7545
7913
|
const input = object({
|
|
7546
7914
|
flowIds: array(ids.flow).min(1).max(300).refine((flowIds) => new Set(flowIds).size === flowIds.length, "flowIds must be unique").describe("The flows that receive the tag."),
|
|
7547
7915
|
tagName: string2().trim().min(1).describe("The name of an existing tag on the caller's team.")
|
|
7548
7916
|
});
|
|
7549
|
-
const output = makeTagResourceSchema()
|
|
7917
|
+
const output = makeTagResourceSchema().extend({
|
|
7918
|
+
skippedFlows: makeSkippedFlowsSchema(ids, {
|
|
7919
|
+
description: "Requested flows that already carried the tag, so nothing changed for them.",
|
|
7920
|
+
reason: _enum(["already-tagged"]).describe('Why the flow was skipped: "already-tagged" means the flow already carried the tag.')
|
|
7921
|
+
})
|
|
7922
|
+
});
|
|
7550
7923
|
return {
|
|
7551
|
-
description: "Assign an existing tag to the selected flows. Create tags with tag.create.",
|
|
7924
|
+
description: "Assign an existing tag to the selected flows. Create tags with tag.create. Flows that already carry the tag are reported in skippedFlows.",
|
|
7552
7925
|
input,
|
|
7553
7926
|
kind: "write",
|
|
7554
7927
|
name: "flow.addTag",
|
|
@@ -7588,6 +7961,27 @@ var makeListFlowsContract = (ids) => {
|
|
|
7588
7961
|
};
|
|
7589
7962
|
};
|
|
7590
7963
|
|
|
7964
|
+
// node_modules/@qawolf/api-contracts/dist/v1/flow/removeTag.js
|
|
7965
|
+
var makeRemoveTagFromFlowsContract = (ids) => {
|
|
7966
|
+
const input = object({
|
|
7967
|
+
flowIds: array(ids.flow).min(1).max(300).refine((flowIds) => new Set(flowIds).size === flowIds.length, "flowIds must be unique").describe("The flows that lose the tag."),
|
|
7968
|
+
tagName: string2().trim().min(1).describe("The name of an existing tag on the caller's team.")
|
|
7969
|
+
});
|
|
7970
|
+
const output = makeTagResourceSchema().extend({
|
|
7971
|
+
skippedFlows: makeSkippedFlowsSchema(ids, {
|
|
7972
|
+
description: "Requested flows that did not carry the tag, so nothing changed for them.",
|
|
7973
|
+
reason: _enum(["not-tagged"]).describe('Why the flow was skipped: "not-tagged" means the flow did not carry the tag.')
|
|
7974
|
+
})
|
|
7975
|
+
});
|
|
7976
|
+
return {
|
|
7977
|
+
description: "Remove a tag from the selected flows. Succeeds whether or not each flow carried the tag; the flows that did not are reported in skippedFlows.",
|
|
7978
|
+
input,
|
|
7979
|
+
kind: "write",
|
|
7980
|
+
name: "flow.removeTag",
|
|
7981
|
+
output
|
|
7982
|
+
};
|
|
7983
|
+
};
|
|
7984
|
+
|
|
7591
7985
|
// node_modules/@qawolf/api-contracts/dist/v1/flow/update.js
|
|
7592
7986
|
var makeUpdateFlowContract = (ids) => {
|
|
7593
7987
|
const input = object({
|
|
@@ -7732,6 +8126,24 @@ var makeCreateIssueContract = (ids) => {
|
|
|
7732
8126
|
};
|
|
7733
8127
|
};
|
|
7734
8128
|
|
|
8129
|
+
// node_modules/@qawolf/api-contracts/dist/v1/issue/removeFlows.js
|
|
8130
|
+
var makeRemoveFlowsFromIssueContract = (ids) => {
|
|
8131
|
+
const input = object({
|
|
8132
|
+
flowIds: array(ids.flow).min(1).max(300).refine((flowIds) => new Set(flowIds).size === flowIds.length, "flowIds must be unique").describe("The flows the coverage request no longer covers."),
|
|
8133
|
+
issueId: ids.issue
|
|
8134
|
+
});
|
|
8135
|
+
const output = object({
|
|
8136
|
+
issue: makeIssueResourceSchema(ids)
|
|
8137
|
+
});
|
|
8138
|
+
return {
|
|
8139
|
+
description: "Remove flows from a coverage request owned by the caller's team. " + "Flows the request does not cover are left alone. " + "Bug and maintenance reports link to flows through the runs that reproduce them, so their flows cannot be set directly.",
|
|
8140
|
+
input,
|
|
8141
|
+
kind: "write",
|
|
8142
|
+
name: "issue.removeFlows",
|
|
8143
|
+
output
|
|
8144
|
+
};
|
|
8145
|
+
};
|
|
8146
|
+
|
|
7735
8147
|
// node_modules/@qawolf/api-contracts/dist/v1/issue/update.js
|
|
7736
8148
|
var makeUpdateIssueContract = (ids) => {
|
|
7737
8149
|
const descriptionSchema = string2().describe("The issue description as plain text; each line becomes a paragraph. Markdown is not parsed.");
|
|
@@ -8058,6 +8470,22 @@ var makeTerminateRunnerContract = () => {
|
|
|
8058
8470
|
};
|
|
8059
8471
|
};
|
|
8060
8472
|
|
|
8473
|
+
// node_modules/@qawolf/api-contracts/dist/v1/runner/list.js
|
|
8474
|
+
var makeListRunnersContract = () => {
|
|
8475
|
+
const input = object({});
|
|
8476
|
+
const output = object({
|
|
8477
|
+
outcome: literal("success"),
|
|
8478
|
+
runners: array(makeRunnerSchema()).describe("The runners running right now, in no particular order. Each entry carries the same fields a launch reports, so any of them can be addressed like a runner you launched yourself.")
|
|
8479
|
+
});
|
|
8480
|
+
return {
|
|
8481
|
+
description: "List the runners running on the caller's team right now. Takes no arguments: the API key already names the team. A runner that was terminated, or that terminated on its own after inactivity, is not listed, because the run system keeps no record of a runner once it is gone. 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. It is how to find a runner launched from another machine or in an earlier session, when the id it was launched under is no longer at hand.",
|
|
8482
|
+
input,
|
|
8483
|
+
kind: "read",
|
|
8484
|
+
name: "runner.list",
|
|
8485
|
+
output
|
|
8486
|
+
};
|
|
8487
|
+
};
|
|
8488
|
+
|
|
8061
8489
|
// node_modules/@qawolf/api-contracts/dist/v1/runner/promoteSnapshot.js
|
|
8062
8490
|
var maxSnapshotPathLength = 1024;
|
|
8063
8491
|
var makePromoteSnapshotOnRunnerContract = () => {
|
|
@@ -8253,6 +8681,13 @@ var makeContractsV1 = (ids) => {
|
|
|
8253
8681
|
send: makeAgentSendContract(resolvedIds)
|
|
8254
8682
|
},
|
|
8255
8683
|
automate: makeAutomateContract(resolvedIds),
|
|
8684
|
+
email: {
|
|
8685
|
+
find: makeFindEmailsContract(resolvedIds),
|
|
8686
|
+
get: makeGetEmailContract(resolvedIds),
|
|
8687
|
+
getAttachment: makeGetEmailAttachmentContract(resolvedIds),
|
|
8688
|
+
listAddresses: makeListEmailAddressesContract(resolvedIds),
|
|
8689
|
+
send: makeSendEmailContract(resolvedIds)
|
|
8690
|
+
},
|
|
8256
8691
|
environment: {
|
|
8257
8692
|
create: makeCreateEnvironmentContract(resolvedIds),
|
|
8258
8693
|
deleteVariable: makeDeleteEnvironmentVariableContract(resolvedIds),
|
|
@@ -8266,6 +8701,7 @@ var makeContractsV1 = (ids) => {
|
|
|
8266
8701
|
flow: {
|
|
8267
8702
|
addTag: makeAddTagToFlowsContract(resolvedIds),
|
|
8268
8703
|
list: makeListFlowsContract(resolvedIds),
|
|
8704
|
+
removeTag: makeRemoveTagFromFlowsContract(resolvedIds),
|
|
8269
8705
|
update: makeUpdateFlowContract(resolvedIds)
|
|
8270
8706
|
},
|
|
8271
8707
|
issue: {
|
|
@@ -8273,6 +8709,7 @@ var makeContractsV1 = (ids) => {
|
|
|
8273
8709
|
create: makeCreateIssueContract(resolvedIds),
|
|
8274
8710
|
find: makeFindIssuesContract(resolvedIds),
|
|
8275
8711
|
get: makeGetIssueContract(resolvedIds),
|
|
8712
|
+
removeFlows: makeRemoveFlowsFromIssueContract(resolvedIds),
|
|
8276
8713
|
update: makeUpdateIssueContract(resolvedIds)
|
|
8277
8714
|
},
|
|
8278
8715
|
run: {
|
|
@@ -8290,6 +8727,7 @@ var makeContractsV1 = (ids) => {
|
|
|
8290
8727
|
inspect: makeInspectOnRunnerContract(),
|
|
8291
8728
|
inspectMobile: makeInspectMobileOnRunnerContract(),
|
|
8292
8729
|
launch: makeLaunchRunnerContract(),
|
|
8730
|
+
list: makeListRunnersContract(),
|
|
8293
8731
|
performAction: makePerformActionOnRunnerContract(),
|
|
8294
8732
|
promoteSnapshot: makePromoteSnapshotOnRunnerContract(),
|
|
8295
8733
|
readJournal: makeReadRunnerJournalContract(),
|
|
@@ -8306,18 +8744,9 @@ var makeContractsV1 = (ids) => {
|
|
|
8306
8744
|
};
|
|
8307
8745
|
var publicContractsV1 = makeContractsV1(defaultIdSchemas);
|
|
8308
8746
|
|
|
8309
|
-
// src/core/
|
|
8310
|
-
|
|
8311
|
-
|
|
8312
|
-
throw new Error("batchMap size must be greater than 0");
|
|
8313
|
-
}
|
|
8314
|
-
for (let i = 0;i < items.length; i += size) {
|
|
8315
|
-
const batch = items.slice(i, i + size);
|
|
8316
|
-
const results = await Promise.all(batch.map(fn));
|
|
8317
|
-
for (const result of results) {
|
|
8318
|
-
yield result;
|
|
8319
|
-
}
|
|
8320
|
-
}
|
|
8747
|
+
// src/core/pluralize.ts
|
|
8748
|
+
function pluralize(count, singular, plural = `${singular}s`) {
|
|
8749
|
+
return `${String(count)} ${count === 1 ? singular : plural}`;
|
|
8321
8750
|
}
|
|
8322
8751
|
|
|
8323
8752
|
// src/core/formatSeconds.ts
|
|
@@ -8325,6 +8754,72 @@ function formatSeconds(ms) {
|
|
|
8325
8754
|
return `${Math.round(ms / 1000)}s`;
|
|
8326
8755
|
}
|
|
8327
8756
|
|
|
8757
|
+
// src/core/messages/authErrors.ts
|
|
8758
|
+
var authErrorMessages = {
|
|
8759
|
+
identity: {
|
|
8760
|
+
invalidOrUnauthorized: "API key is invalid or unauthorized",
|
|
8761
|
+
unexpectedFormat: "Could not verify API key: unexpected response format",
|
|
8762
|
+
couldNotVerify: (detail, status) => `Could not verify API key: ${detail || `HTTP ${status}`}`,
|
|
8763
|
+
couldNotVerifyNetwork: (cause) => `Could not verify API key: ${cause}`,
|
|
8764
|
+
timedOut: (timeoutMs) => `Could not verify API key: the QA Wolf API did not answer within ${formatSeconds(timeoutMs)}.`
|
|
8765
|
+
},
|
|
8766
|
+
request: {
|
|
8767
|
+
rejected401: (noun) => `QA Wolf API rejected the${noun ? ` ${noun}` : ""} request (HTTP 401). Check your API key.`,
|
|
8768
|
+
rejected402: (noun) => `QA Wolf API refused the${noun ? ` ${noun}` : ""} request (HTTP 402): billing prevented it.`,
|
|
8769
|
+
rejected403: (noun) => `QA Wolf API rejected the${noun ? ` ${noun}` : ""} request (HTTP 403). Check that your API key has access to this environment.`,
|
|
8770
|
+
notFound404: (noun) => `QA Wolf API could not find ${noun ? `${noun} for that environment` : "that environment"} (HTTP 404). Check the --env value.`,
|
|
8771
|
+
failedWithStatus: (status, noun) => `QA Wolf API${noun ? ` ${noun}` : ""} request failed (HTTP ${status}).`,
|
|
8772
|
+
networkUnreachable: (baseUrl, noun) => `Could not reach the QA Wolf API at ${baseUrl}${noun ? ` to fetch ${noun}` : ""}. Check your network connection and QAWOLF_HOST_URL.`,
|
|
8773
|
+
timedOut: (timeoutMs, noun) => `The QA Wolf API${noun ? ` ${noun}` : ""} request timed out after ${formatSeconds(timeoutMs)}. The work may still be finishing on the platform.`,
|
|
8774
|
+
unexpectedResponse: (noun) => `Unexpected${noun ? ` ${noun}` : ""} response from the QA Wolf API.`
|
|
8775
|
+
},
|
|
8776
|
+
workos: {
|
|
8777
|
+
unexpectedResponse: "WorkOS returned an unexpected response",
|
|
8778
|
+
unexpectedResponseWithStatus: (status) => `WorkOS returned an unexpected response (HTTP ${status})`,
|
|
8779
|
+
unreachable: (detail) => `Could not reach WorkOS: ${detail}`,
|
|
8780
|
+
redirected: "WorkOS answered with a redirect, which the CLI does not follow for a sign-in request",
|
|
8781
|
+
noClientForSession: "This session names no WorkOS client"
|
|
8782
|
+
},
|
|
8783
|
+
bundle: {
|
|
8784
|
+
linkExpired: "The flow bundle download link has expired. Please run `qawolf flows pull` again to refresh.",
|
|
8785
|
+
failedWithStatus: (status) => `Could not download the flow bundle (HTTP ${status}).`,
|
|
8786
|
+
networkUnreachable: "Could not reach the flow bundle storage. Check your network connection and try again.",
|
|
8787
|
+
timedOut: (timeoutMs) => `Downloading the flow bundle stalled — no data arrived for ${formatSeconds(timeoutMs)}. Please try again.`,
|
|
8788
|
+
malformed: "The flow bundle download was malformed. Please run `qawolf flows pull` again."
|
|
8789
|
+
}
|
|
8790
|
+
};
|
|
8791
|
+
|
|
8792
|
+
// src/core/messages/whoami.ts
|
|
8793
|
+
var whoamiMessages = {
|
|
8794
|
+
source: (source) => `Source: ${source}`,
|
|
8795
|
+
authFailed: (source, error) => `Authentication failed (source: ${source}): ${error}`,
|
|
8796
|
+
authenticatedAs: (teamName, source) => `Authenticated as ${teamName} (source: ${source})`,
|
|
8797
|
+
teamNote: (input) => [
|
|
8798
|
+
`Workspace: ${input.team.name}`,
|
|
8799
|
+
`ID: ${input.team.id}`,
|
|
8800
|
+
input.team.slug ? `Slug: ${input.team.slug}` : undefined,
|
|
8801
|
+
input.teamUrl ? `URL: ${input.teamUrl}` : undefined,
|
|
8802
|
+
`Source: ${input.source}`
|
|
8803
|
+
].filter((line) => Boolean(line)).join(`
|
|
8804
|
+
`),
|
|
8805
|
+
organizationNote: (input) => [
|
|
8806
|
+
`Organization: ${input.organization.name}`,
|
|
8807
|
+
`ID: ${input.organization.id}`,
|
|
8808
|
+
`Source: ${input.source}`
|
|
8809
|
+
].join(`
|
|
8810
|
+
`),
|
|
8811
|
+
activeWorkspace: (workspaceId, found) => found ? `${found.workspace} (${found.organization})` : `${workspaceId} — no longer in reach; run 'qawolf auth switch'`,
|
|
8812
|
+
userNote: (input) => [
|
|
8813
|
+
`User: ${input.user.email}`,
|
|
8814
|
+
`ID: ${input.user.id}`,
|
|
8815
|
+
`Organization: ${input.organization.name}`,
|
|
8816
|
+
input.activeWorkspace ? `Workspace: ${input.activeWorkspace}` : undefined,
|
|
8817
|
+
input.organizations.length > 0 ? `Workspaces: ${input.organizations.map((o) => `${o.name}: ${o.workspaces.map((w) => w.name).join(", ")}`).join(" | ")}` : undefined,
|
|
8818
|
+
`Source: ${input.source}`
|
|
8819
|
+
].filter((line) => Boolean(line)).join(`
|
|
8820
|
+
`)
|
|
8821
|
+
};
|
|
8822
|
+
|
|
8328
8823
|
// src/core/messages/auth.ts
|
|
8329
8824
|
var authMessages = {
|
|
8330
8825
|
title: "QA Wolf Authentication",
|
|
@@ -8342,7 +8837,47 @@ var authMessages = {
|
|
|
8342
8837
|
whoamiFailed: "Not authenticated",
|
|
8343
8838
|
login: {
|
|
8344
8839
|
nonInteractive: "auth login requires an interactive terminal. Set the QAWOLF_API_KEY environment variable for CI authentication.",
|
|
8345
|
-
reAuthPrompt: "You are already authenticated. Re-authenticate?"
|
|
8840
|
+
reAuthPrompt: "You are already authenticated. Re-authenticate?",
|
|
8841
|
+
chooseMethod: "How do you want to sign in?",
|
|
8842
|
+
methodBrowser: "Browser",
|
|
8843
|
+
methodBrowserHint: "Sign in with your QA Wolf account",
|
|
8844
|
+
methodApiKey: "API key",
|
|
8845
|
+
methodApiKeyHint: "Paste a team key — needed for flows pull and flows run",
|
|
8846
|
+
apiKeyPrecedence: {
|
|
8847
|
+
env: "QAWOLF_API_KEY is set, and an API key takes precedence over a browser session. Commands continue to use that key until you unset the variable.",
|
|
8848
|
+
stored: "A stored API key takes precedence over a browser session. Commands continue to use that key until you run 'qawolf auth logout' and sign in again."
|
|
8849
|
+
}
|
|
8850
|
+
},
|
|
8851
|
+
device: {
|
|
8852
|
+
unavailable: "This QA Wolf deployment does not offer browser sign-in. Run 'qawolf auth login' again and choose 'API key'.",
|
|
8853
|
+
configUnreachable: "Could not ask this QA Wolf deployment whether it offers browser sign-in. Check your connection, then try again.",
|
|
8854
|
+
confirmCode: (userCode) => `Your code is ${userCode}`,
|
|
8855
|
+
visitUrl: (url) => `Confirm it at ${url}`,
|
|
8856
|
+
visitUrlPlain: (url) => `Or go to ${url} and enter the code`,
|
|
8857
|
+
openFailed: (url) => `Could not open a browser automatically. Open ${url} yourself to continue.`,
|
|
8858
|
+
waiting: "Waiting for you to finish in the browser",
|
|
8859
|
+
signedIn: (email) => `Signed in as ${email}.`,
|
|
8860
|
+
failed: {
|
|
8861
|
+
"access-denied": "The sign-in request was rejected.",
|
|
8862
|
+
expired: "The sign-in request expired. Run 'qawolf auth login' to retry.",
|
|
8863
|
+
timeout: "The sign-in request timed out. Run 'qawolf auth login' to retry.",
|
|
8864
|
+
network: "Could not reach WorkOS to complete sign-in.",
|
|
8865
|
+
unavailable: "Could not start browser sign-in.",
|
|
8866
|
+
cancelled: "Sign-in cancelled."
|
|
8867
|
+
}
|
|
8868
|
+
},
|
|
8869
|
+
workspace: {
|
|
8870
|
+
chooseOrganization: "Which organization do you want to work in?",
|
|
8871
|
+
choose: "Which workspace do you want to use?",
|
|
8872
|
+
workspaceCount: (count) => pluralize(count, "workspace"),
|
|
8873
|
+
working: (organization, workspace) => `Working in ${workspace} (${organization}).`,
|
|
8874
|
+
none: "This account reaches no organizations yet.",
|
|
8875
|
+
cancelled: "Workspace not changed.",
|
|
8876
|
+
notSignedIn: "Workspace switching needs a browser sign-in. Run 'qawolf auth login' and choose Browser.",
|
|
8877
|
+
sessionExpired: "Your session could not be renewed. Run 'qawolf auth login' to sign in again.",
|
|
8878
|
+
nonInteractive: "auth switch needs an interactive terminal, or set QAWOLF_WORKSPACE to name a workspace.",
|
|
8879
|
+
sessionChanged: "The stored sign-in changed while you made your choice. Run the command again.",
|
|
8880
|
+
saveFailed: (detail) => `Could not save the workspace choice: ${detail}`
|
|
8346
8881
|
},
|
|
8347
8882
|
logout: {
|
|
8348
8883
|
title: "Log Out",
|
|
@@ -8354,58 +8889,8 @@ var authMessages = {
|
|
|
8354
8889
|
success: "Logged out successfully.",
|
|
8355
8890
|
cancelled: "Logout cancelled."
|
|
8356
8891
|
},
|
|
8357
|
-
errors:
|
|
8358
|
-
|
|
8359
|
-
invalidOrUnauthorized: "API key is invalid or unauthorized",
|
|
8360
|
-
unexpectedFormat: "Could not verify API key: unexpected response format",
|
|
8361
|
-
couldNotVerify: (detail, status) => `Could not verify API key: ${detail || `HTTP ${status}`}`,
|
|
8362
|
-
couldNotVerifyNetwork: (cause) => `Could not verify API key: ${cause}`,
|
|
8363
|
-
timedOut: (timeoutMs) => `Could not verify API key: the QA Wolf API did not answer within ${formatSeconds(timeoutMs)}.`
|
|
8364
|
-
},
|
|
8365
|
-
request: {
|
|
8366
|
-
rejected401: (noun) => `QA Wolf API rejected the${noun ? ` ${noun}` : ""} request (HTTP 401). Check your API key.`,
|
|
8367
|
-
rejected402: (noun) => `QA Wolf API refused the${noun ? ` ${noun}` : ""} request (HTTP 402): billing prevented it.`,
|
|
8368
|
-
rejected403: (noun) => `QA Wolf API rejected the${noun ? ` ${noun}` : ""} request (HTTP 403). Check that your API key has access to this environment.`,
|
|
8369
|
-
notFound404: (noun) => `QA Wolf API could not find ${noun ? `${noun} for that environment` : "that environment"} (HTTP 404). Check the --env value.`,
|
|
8370
|
-
failedWithStatus: (status, noun) => `QA Wolf API${noun ? ` ${noun}` : ""} request failed (HTTP ${status}).`,
|
|
8371
|
-
networkUnreachable: (baseUrl, noun) => `Could not reach the QA Wolf API at ${baseUrl}${noun ? ` to fetch ${noun}` : ""}. Check your network connection and QAWOLF_HOST_URL.`,
|
|
8372
|
-
timedOut: (timeoutMs, noun) => `The QA Wolf API${noun ? ` ${noun}` : ""} request timed out after ${formatSeconds(timeoutMs)}. The work may still be finishing on the platform.`,
|
|
8373
|
-
unexpectedResponse: (noun) => `Unexpected${noun ? ` ${noun}` : ""} response from the QA Wolf API.`
|
|
8374
|
-
},
|
|
8375
|
-
bundle: {
|
|
8376
|
-
linkExpired: "The flow bundle download link has expired. Please run `qawolf flows pull` again to refresh.",
|
|
8377
|
-
failedWithStatus: (status) => `Could not download the flow bundle (HTTP ${status}).`,
|
|
8378
|
-
networkUnreachable: "Could not reach the flow bundle storage. Check your network connection and try again.",
|
|
8379
|
-
timedOut: (timeoutMs) => `Downloading the flow bundle stalled — no data arrived for ${formatSeconds(timeoutMs)}. Please try again.`,
|
|
8380
|
-
malformed: "The flow bundle download was malformed. Please run `qawolf flows pull` again."
|
|
8381
|
-
}
|
|
8382
|
-
},
|
|
8383
|
-
whoami: {
|
|
8384
|
-
source: (source) => `Source: ${source}`,
|
|
8385
|
-
authFailed: (source, error) => `Authentication failed (source: ${source}): ${error}`,
|
|
8386
|
-
authenticatedAs: (teamName, source) => `Authenticated as ${teamName} (source: ${source})`,
|
|
8387
|
-
teamNote: (input) => [
|
|
8388
|
-
`Team: ${input.team.name}`,
|
|
8389
|
-
`ID: ${input.team.id}`,
|
|
8390
|
-
input.team.slug ? `Slug: ${input.team.slug}` : undefined,
|
|
8391
|
-
input.teamUrl ? `URL: ${input.teamUrl}` : undefined,
|
|
8392
|
-
`Source: ${input.source}`
|
|
8393
|
-
].filter((line) => Boolean(line)).join(`
|
|
8394
|
-
`),
|
|
8395
|
-
organizationNote: (input) => [
|
|
8396
|
-
`Organization: ${input.organization.name}`,
|
|
8397
|
-
`ID: ${input.organization.id}`,
|
|
8398
|
-
`Source: ${input.source}`
|
|
8399
|
-
].join(`
|
|
8400
|
-
`),
|
|
8401
|
-
userNote: (input) => [
|
|
8402
|
-
`User: ${input.user.email}`,
|
|
8403
|
-
`ID: ${input.user.id}`,
|
|
8404
|
-
`Organization: ${input.organization.name}`,
|
|
8405
|
-
`Source: ${input.source}`
|
|
8406
|
-
].join(`
|
|
8407
|
-
`)
|
|
8408
|
-
}
|
|
8892
|
+
errors: authErrorMessages,
|
|
8893
|
+
whoami: whoamiMessages
|
|
8409
8894
|
};
|
|
8410
8895
|
// src/core/messages/toolNotFound.ts
|
|
8411
8896
|
var installRemedy = "Run `qawolf install` to install the runtime dependencies.";
|
|
@@ -8421,11 +8906,6 @@ ${installRemedy}`;
|
|
|
8421
8906
|
function packageLoadFailed(pkg, envDir, detail) {
|
|
8422
8907
|
return toolNotRunnable(`Could not load ${pkg} from ${envDir}`, detail);
|
|
8423
8908
|
}
|
|
8424
|
-
// src/core/pluralize.ts
|
|
8425
|
-
function pluralize(count, singular, plural = `${singular}s`) {
|
|
8426
|
-
return `${String(count)} ${count === 1 ? singular : plural}`;
|
|
8427
|
-
}
|
|
8428
|
-
|
|
8429
8909
|
// src/core/messages/flows.ts
|
|
8430
8910
|
var flowsMessages = {
|
|
8431
8911
|
title: "Flows",
|
|
@@ -8628,7 +9108,8 @@ var lifecycleMessages = {
|
|
|
8628
9108
|
|
|
8629
9109
|
// src/core/messages/interactiveRunner/list.ts
|
|
8630
9110
|
var listMessages = {
|
|
8631
|
-
noRunners: "
|
|
9111
|
+
noRunners: "Your team has no runner running. Launch one with qawolf runner launch.",
|
|
9112
|
+
noRunnersHere: "This directory has no runner running. Launch one with qawolf runner launch, or drop --here to see the whole team's runners.",
|
|
8632
9113
|
runnerCount: (count) => count === 1 ? "1 runner" : `${String(count)} runners`,
|
|
8633
9114
|
title: "Runners"
|
|
8634
9115
|
};
|
|
@@ -8776,50 +9257,37 @@ var runnerCallOptions = { timeoutMs: 90000 };
|
|
|
8776
9257
|
var runnerIdEnvironmentVariable = "QAWOLF_RUNNER_ID";
|
|
8777
9258
|
|
|
8778
9259
|
// src/domains/interactiveRunner/list.ts
|
|
8779
|
-
|
|
8780
|
-
|
|
8781
|
-
|
|
8782
|
-
|
|
8783
|
-
const environmentValue = deps.env[runnerIdEnvironmentVariable]?.trim();
|
|
8784
|
-
const fromEnvironment = environmentValue ? environmentValue : undefined;
|
|
8785
|
-
const candidates = [...held];
|
|
8786
|
-
for (const id of [storedDefault, fromEnvironment]) {
|
|
8787
|
-
if (id !== undefined && !candidates.some((runner) => runner.id === id)) {
|
|
8788
|
-
candidates.push({ id });
|
|
8789
|
-
}
|
|
8790
|
-
}
|
|
8791
|
-
return { candidates, defaultRunnerId: fromEnvironment ?? storedDefault };
|
|
9260
|
+
function rank(item) {
|
|
9261
|
+
if (item.isDefault)
|
|
9262
|
+
return 0;
|
|
9263
|
+
return item.launchedHere ? 1 : 2;
|
|
8792
9264
|
}
|
|
8793
|
-
async function
|
|
8794
|
-
const
|
|
8795
|
-
if (
|
|
8796
|
-
return
|
|
8797
|
-
return
|
|
9265
|
+
async function readDefaultRunnerId(deps) {
|
|
9266
|
+
const environmentValue = deps.env[runnerIdEnvironmentVariable]?.trim();
|
|
9267
|
+
if (environmentValue)
|
|
9268
|
+
return environmentValue;
|
|
9269
|
+
return deps.store.readDefaultRunnerId();
|
|
8798
9270
|
}
|
|
8799
9271
|
async function listRunners(ctx, deps) {
|
|
8800
|
-
const
|
|
8801
|
-
|
|
8802
|
-
|
|
8803
|
-
|
|
8804
|
-
|
|
8805
|
-
|
|
8806
|
-
|
|
8807
|
-
running.push(probe.runner);
|
|
8808
|
-
else
|
|
8809
|
-
gone.push(probe.runner.id);
|
|
8810
|
-
}
|
|
9272
|
+
const listed = await ctx.platformClient.callPublicApi(publicContractsV1.runner.list, {}, runnerCallOptions);
|
|
9273
|
+
if (!listed.ok)
|
|
9274
|
+
return { ...failureFields(listed), ok: false };
|
|
9275
|
+
const defaultRunnerId = await readDefaultRunnerId(deps);
|
|
9276
|
+
const runningIds = new Set(listed.value.runners.map((runner) => runner.id));
|
|
9277
|
+
const held = await deps.store.readRunners();
|
|
9278
|
+
const gone = held.filter((runner) => !runningIds.has(runner.id)).map((runner) => runner.id);
|
|
8811
9279
|
await deps.store.dropRunners(gone).catch(() => {
|
|
8812
9280
|
return;
|
|
8813
9281
|
});
|
|
9282
|
+
const heldIds = new Set(held.map((runner) => runner.id));
|
|
9283
|
+
const items = listed.value.runners.map((runner) => ({
|
|
9284
|
+
id: runner.id,
|
|
9285
|
+
isDefault: runner.id === defaultRunnerId,
|
|
9286
|
+
launchedHere: heldIds.has(runner.id),
|
|
9287
|
+
runnerName: runner.runnerName
|
|
9288
|
+
}));
|
|
8814
9289
|
return {
|
|
8815
|
-
items:
|
|
8816
|
-
...running.filter((runner) => runner.id === defaultRunnerId),
|
|
8817
|
-
...running.filter((runner) => runner.id !== defaultRunnerId)
|
|
8818
|
-
].map((runner) => ({
|
|
8819
|
-
id: runner.id,
|
|
8820
|
-
isDefault: runner.id === defaultRunnerId,
|
|
8821
|
-
runnerName: runner.runnerName
|
|
8822
|
-
})),
|
|
9290
|
+
items: items.sort((left, right) => rank(left) - rank(right) || left.id.localeCompare(right.id)),
|
|
8823
9291
|
ok: true
|
|
8824
9292
|
};
|
|
8825
9293
|
}
|
|
@@ -10160,6 +10628,176 @@ function makeDefaultFs() {
|
|
|
10160
10628
|
};
|
|
10161
10629
|
}
|
|
10162
10630
|
|
|
10631
|
+
// src/core/publicApi/flagKind.ts
|
|
10632
|
+
function flagKind(schema) {
|
|
10633
|
+
if (schema.type === "string")
|
|
10634
|
+
return { ok: true, kind: "string" };
|
|
10635
|
+
if (schema.type === "number" || schema.type === "integer") {
|
|
10636
|
+
return { ok: true, kind: "number" };
|
|
10637
|
+
}
|
|
10638
|
+
if (schema.type === "boolean")
|
|
10639
|
+
return { ok: true, kind: "boolean" };
|
|
10640
|
+
if (schema.type === "array") {
|
|
10641
|
+
if (schema.items?.type !== "string") {
|
|
10642
|
+
return {
|
|
10643
|
+
ok: false,
|
|
10644
|
+
reason: "only string arrays can be expressed as flags"
|
|
10645
|
+
};
|
|
10646
|
+
}
|
|
10647
|
+
return { ok: true, kind: "string-array" };
|
|
10648
|
+
}
|
|
10649
|
+
if (schema.type === "object") {
|
|
10650
|
+
if (schema.properties) {
|
|
10651
|
+
return {
|
|
10652
|
+
ok: false,
|
|
10653
|
+
reason: "nested objects cannot be expressed as flags"
|
|
10654
|
+
};
|
|
10655
|
+
}
|
|
10656
|
+
if (typeof schema.additionalProperties === "object" && schema.additionalProperties.type === "string") {
|
|
10657
|
+
return { ok: true, kind: "key-value-record" };
|
|
10658
|
+
}
|
|
10659
|
+
return { ok: false, reason: "nested objects cannot be expressed as flags" };
|
|
10660
|
+
}
|
|
10661
|
+
return {
|
|
10662
|
+
ok: false,
|
|
10663
|
+
reason: `type ${schema.type ?? "unknown"} cannot be expressed as a flag`
|
|
10664
|
+
};
|
|
10665
|
+
}
|
|
10666
|
+
|
|
10667
|
+
// src/core/publicApi/objectShape.ts
|
|
10668
|
+
var asObjectShape = (schema) => schema.type === "object" && schema.properties ? { properties: schema.properties, required: new Set(schema.required) } : undefined;
|
|
10669
|
+
function mergeIntersection(members) {
|
|
10670
|
+
const shape = { properties: {}, required: new Set };
|
|
10671
|
+
for (const member of members) {
|
|
10672
|
+
const memberShape = asObjectShape(member);
|
|
10673
|
+
if (!memberShape) {
|
|
10674
|
+
return {
|
|
10675
|
+
ok: false,
|
|
10676
|
+
field: "",
|
|
10677
|
+
reason: "intersection members must be object schemas"
|
|
10678
|
+
};
|
|
10679
|
+
}
|
|
10680
|
+
for (const [field, fieldSchema] of Object.entries(memberShape.properties)) {
|
|
10681
|
+
if (field in shape.properties) {
|
|
10682
|
+
return {
|
|
10683
|
+
ok: false,
|
|
10684
|
+
field,
|
|
10685
|
+
reason: "field appears in multiple intersection members"
|
|
10686
|
+
};
|
|
10687
|
+
}
|
|
10688
|
+
shape.properties[field] = fieldSchema;
|
|
10689
|
+
if (memberShape.required.has(field))
|
|
10690
|
+
shape.required.add(field);
|
|
10691
|
+
}
|
|
10692
|
+
}
|
|
10693
|
+
return { ok: true, shape };
|
|
10694
|
+
}
|
|
10695
|
+
function mergeUnion(branches) {
|
|
10696
|
+
const shapes = [];
|
|
10697
|
+
for (const branch of branches) {
|
|
10698
|
+
const branchShape = asObjectShape(branch);
|
|
10699
|
+
if (!branchShape) {
|
|
10700
|
+
return {
|
|
10701
|
+
ok: false,
|
|
10702
|
+
field: "",
|
|
10703
|
+
reason: "union branches must be object schemas"
|
|
10704
|
+
};
|
|
10705
|
+
}
|
|
10706
|
+
shapes.push(branchShape);
|
|
10707
|
+
}
|
|
10708
|
+
const shape = { properties: {}, required: new Set };
|
|
10709
|
+
for (const branchShape of shapes) {
|
|
10710
|
+
for (const [field, fieldSchema] of Object.entries(branchShape.properties)) {
|
|
10711
|
+
const existing = shape.properties[field];
|
|
10712
|
+
if (!existing) {
|
|
10713
|
+
shape.properties[field] = { ...fieldSchema };
|
|
10714
|
+
continue;
|
|
10715
|
+
}
|
|
10716
|
+
const kinds = [flagKind(existing), flagKind(fieldSchema)];
|
|
10717
|
+
if (kinds[0]?.ok && kinds[1]?.ok) {
|
|
10718
|
+
if (kinds[0].kind !== kinds[1].kind) {
|
|
10719
|
+
return {
|
|
10720
|
+
ok: false,
|
|
10721
|
+
field,
|
|
10722
|
+
reason: "field has conflicting types across union branches"
|
|
10723
|
+
};
|
|
10724
|
+
}
|
|
10725
|
+
} else if (JSON.stringify({ ...existing, description: undefined }) !== JSON.stringify({ ...fieldSchema, description: undefined })) {
|
|
10726
|
+
return {
|
|
10727
|
+
ok: false,
|
|
10728
|
+
field,
|
|
10729
|
+
reason: "field has conflicting object schemas across union branches"
|
|
10730
|
+
};
|
|
10731
|
+
}
|
|
10732
|
+
if (!existing.description && fieldSchema.description) {
|
|
10733
|
+
existing.description = fieldSchema.description;
|
|
10734
|
+
}
|
|
10735
|
+
}
|
|
10736
|
+
}
|
|
10737
|
+
const discriminator = Object.keys(shape.properties).find((field) => {
|
|
10738
|
+
const values = shapes.map((branch) => branch.properties[field]?.const);
|
|
10739
|
+
return values.every((value) => typeof value === "string") && new Set(values).size === shapes.length && shapes.every((branch) => branch.required.has(field));
|
|
10740
|
+
});
|
|
10741
|
+
for (const [field, fieldSchema] of Object.entries(shape.properties)) {
|
|
10742
|
+
const occurrences = shapes.filter((branch) => (field in branch.properties));
|
|
10743
|
+
if (occurrences.length === shapes.length && occurrences.every((branch) => branch.required.has(field))) {
|
|
10744
|
+
shape.required.add(field);
|
|
10745
|
+
}
|
|
10746
|
+
if (field === discriminator) {
|
|
10747
|
+
const values = shapes.map((branch) => branch.properties[field]?.const);
|
|
10748
|
+
fieldSchema.description = `One of: ${values.join(", ")}`;
|
|
10749
|
+
}
|
|
10750
|
+
}
|
|
10751
|
+
return { ok: true, shape };
|
|
10752
|
+
}
|
|
10753
|
+
function toObjectShape(schema) {
|
|
10754
|
+
if (schema.allOf)
|
|
10755
|
+
return mergeIntersection(schema.allOf);
|
|
10756
|
+
const branches = schema.oneOf ?? schema.anyOf;
|
|
10757
|
+
if (branches)
|
|
10758
|
+
return mergeUnion(branches);
|
|
10759
|
+
const shape = asObjectShape(schema);
|
|
10760
|
+
if (shape)
|
|
10761
|
+
return { ok: true, shape };
|
|
10762
|
+
return {
|
|
10763
|
+
ok: false,
|
|
10764
|
+
field: "",
|
|
10765
|
+
reason: "contract input must be an object schema"
|
|
10766
|
+
};
|
|
10767
|
+
}
|
|
10768
|
+
|
|
10769
|
+
// src/shell/platform/applyWorkspaceId.ts
|
|
10770
|
+
var acceptsWorkspace = new WeakMap;
|
|
10771
|
+
function takesWorkspaceId(inputSchema) {
|
|
10772
|
+
const cached = acceptsWorkspace.get(inputSchema);
|
|
10773
|
+
if (cached !== undefined)
|
|
10774
|
+
return cached;
|
|
10775
|
+
let accepted = false;
|
|
10776
|
+
try {
|
|
10777
|
+
const jsonSchema = toJSONSchema(inputSchema, {
|
|
10778
|
+
io: "input"
|
|
10779
|
+
});
|
|
10780
|
+
const shape = toObjectShape(jsonSchema);
|
|
10781
|
+
accepted = shape.ok && "workspaceId" in shape.shape.properties;
|
|
10782
|
+
} catch {
|
|
10783
|
+
accepted = false;
|
|
10784
|
+
}
|
|
10785
|
+
acceptsWorkspace.set(inputSchema, accepted);
|
|
10786
|
+
return accepted;
|
|
10787
|
+
}
|
|
10788
|
+
function applyWorkspaceId(inputSchema, input, workspaceId) {
|
|
10789
|
+
if (!workspaceId)
|
|
10790
|
+
return input;
|
|
10791
|
+
if (typeof input !== "object" || input === null)
|
|
10792
|
+
return input;
|
|
10793
|
+
const existing = input.workspaceId;
|
|
10794
|
+
if (existing !== undefined)
|
|
10795
|
+
return input;
|
|
10796
|
+
if (!takesWorkspaceId(inputSchema))
|
|
10797
|
+
return input;
|
|
10798
|
+
return { ...input, workspaceId };
|
|
10799
|
+
}
|
|
10800
|
+
|
|
10163
10801
|
// src/shell/platform/parseErrorBody.ts
|
|
10164
10802
|
var defaultMaxLength = 1024;
|
|
10165
10803
|
function asRecord(value) {
|
|
@@ -10292,7 +10930,7 @@ function callPublicApi(trpc, contract, input, options) {
|
|
|
10292
10930
|
}
|
|
10293
10931
|
function makeCallPublicApiMethod(trpc, deps, readBackoffMs) {
|
|
10294
10932
|
return async (contract, input, options) => requestWithRetry({
|
|
10295
|
-
call: () => callPublicApi(trpc, contract, input, options),
|
|
10933
|
+
call: () => callPublicApi(trpc, contract, applyWorkspaceId(contract.input, input, deps.workspaceId), options),
|
|
10296
10934
|
backoffMs: contract.kind === "read" ? readBackoffMs : [],
|
|
10297
10935
|
describe: (err) => describeRequestError(err, deps.baseUrl, contract.name),
|
|
10298
10936
|
sleep: deps.sleep
|
|
@@ -11292,10 +11930,16 @@ async function downloadBundle(signedUrl, deps) {
|
|
|
11292
11930
|
return { ok: true, value: { tmpArchive } };
|
|
11293
11931
|
}
|
|
11294
11932
|
|
|
11295
|
-
// src/shell/platform/
|
|
11933
|
+
// src/shell/platform/organizations.ts
|
|
11934
|
+
function parseOrganizationsResponse(json) {
|
|
11935
|
+
const parsed = identityOrganizationsResponse.safeParse(json);
|
|
11936
|
+
return parsed.success ? parsed.data.organizations : undefined;
|
|
11937
|
+
}
|
|
11938
|
+
|
|
11939
|
+
// src/shell/platform/getAccessibleOrganizations.ts
|
|
11296
11940
|
var timeoutMs = 1e4;
|
|
11297
|
-
async function
|
|
11298
|
-
const url = `${deps.baseUrl}/api/v0/identity`;
|
|
11941
|
+
async function getAccessibleOrganizations(apiKey, deps) {
|
|
11942
|
+
const url = `${deps.baseUrl}/api/v0/identity/organizations`;
|
|
11299
11943
|
let response;
|
|
11300
11944
|
try {
|
|
11301
11945
|
response = await deps.fetch(url, {
|
|
@@ -11306,6 +11950,51 @@ async function getIdentity(apiKey, deps) {
|
|
|
11306
11950
|
if (isTimeoutError(error)) {
|
|
11307
11951
|
return { ok: false, error: { kind: "timeout", timeoutMs } };
|
|
11308
11952
|
}
|
|
11953
|
+
return { ok: false, error: { kind: "network", cause: toError(error) } };
|
|
11954
|
+
}
|
|
11955
|
+
if (!response.ok) {
|
|
11956
|
+
const body = await response.text().catch(() => "");
|
|
11957
|
+
return {
|
|
11958
|
+
ok: false,
|
|
11959
|
+
error: { kind: "http", status: response.status, body }
|
|
11960
|
+
};
|
|
11961
|
+
}
|
|
11962
|
+
let json;
|
|
11963
|
+
try {
|
|
11964
|
+
json = await response.json();
|
|
11965
|
+
} catch (error) {
|
|
11966
|
+
if (isTimeoutError(error)) {
|
|
11967
|
+
return { ok: false, error: { kind: "timeout", timeoutMs } };
|
|
11968
|
+
}
|
|
11969
|
+
json = undefined;
|
|
11970
|
+
}
|
|
11971
|
+
const organizations = parseOrganizationsResponse(json);
|
|
11972
|
+
if (!organizations) {
|
|
11973
|
+
return {
|
|
11974
|
+
ok: false,
|
|
11975
|
+
error: {
|
|
11976
|
+
kind: "parse",
|
|
11977
|
+
cause: Error("organizations response did not match the contract")
|
|
11978
|
+
}
|
|
11979
|
+
};
|
|
11980
|
+
}
|
|
11981
|
+
return { ok: true, data: organizations };
|
|
11982
|
+
}
|
|
11983
|
+
|
|
11984
|
+
// src/shell/platform/getIdentity.ts
|
|
11985
|
+
var timeoutMs2 = 1e4;
|
|
11986
|
+
async function getIdentity(apiKey, deps) {
|
|
11987
|
+
const url = `${deps.baseUrl}/api/v0/identity`;
|
|
11988
|
+
let response;
|
|
11989
|
+
try {
|
|
11990
|
+
response = await deps.fetch(url, {
|
|
11991
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
11992
|
+
signal: AbortSignal.timeout(timeoutMs2)
|
|
11993
|
+
});
|
|
11994
|
+
} catch (error) {
|
|
11995
|
+
if (isTimeoutError(error)) {
|
|
11996
|
+
return { ok: false, error: { kind: "timeout", timeoutMs: timeoutMs2 } };
|
|
11997
|
+
}
|
|
11309
11998
|
return {
|
|
11310
11999
|
ok: false,
|
|
11311
12000
|
error: { kind: "network", cause: toError(error) }
|
|
@@ -11323,7 +12012,7 @@ async function getIdentity(apiKey, deps) {
|
|
|
11323
12012
|
json = await response.json();
|
|
11324
12013
|
} catch (error) {
|
|
11325
12014
|
if (isTimeoutError(error)) {
|
|
11326
|
-
return { ok: false, error: { kind: "timeout", timeoutMs } };
|
|
12015
|
+
return { ok: false, error: { kind: "timeout", timeoutMs: timeoutMs2 } };
|
|
11327
12016
|
}
|
|
11328
12017
|
json = undefined;
|
|
11329
12018
|
}
|
|
@@ -11334,6 +12023,24 @@ async function getIdentity(apiKey, deps) {
|
|
|
11334
12023
|
return { ok: true, data: parsed.data };
|
|
11335
12024
|
}
|
|
11336
12025
|
|
|
12026
|
+
// src/shell/platform/identityMethods.ts
|
|
12027
|
+
function createIdentityMethods(apiKey, deps, backoffMs) {
|
|
12028
|
+
return {
|
|
12029
|
+
getIdentity: () => requestWithRetry({
|
|
12030
|
+
call: () => getIdentity(apiKey, deps),
|
|
12031
|
+
backoffMs,
|
|
12032
|
+
describe: describeIdentityError,
|
|
12033
|
+
sleep: deps.sleep
|
|
12034
|
+
}),
|
|
12035
|
+
getAccessibleOrganizations: () => requestWithRetry({
|
|
12036
|
+
call: () => getAccessibleOrganizations(apiKey, deps),
|
|
12037
|
+
backoffMs,
|
|
12038
|
+
describe: describeIdentityError,
|
|
12039
|
+
sleep: deps.sleep
|
|
12040
|
+
})
|
|
12041
|
+
};
|
|
12042
|
+
}
|
|
12043
|
+
|
|
11337
12044
|
// src/shell/platform/types.ts
|
|
11338
12045
|
var environmentListItemSchema = object({
|
|
11339
12046
|
envId: string2(),
|
|
@@ -11633,14 +12340,7 @@ function createPlatformClient(apiKey, deps) {
|
|
|
11633
12340
|
return { ok: true, value: { signedUrl: result.value.url } };
|
|
11634
12341
|
}
|
|
11635
12342
|
return {
|
|
11636
|
-
|
|
11637
|
-
return requestWithRetry({
|
|
11638
|
-
call: () => getIdentity(apiKey, deps),
|
|
11639
|
-
backoffMs: requestBackoffMs2,
|
|
11640
|
-
describe: describeIdentityError,
|
|
11641
|
-
sleep: deps.sleep
|
|
11642
|
-
});
|
|
11643
|
-
},
|
|
12343
|
+
...createIdentityMethods(apiKey, deps, requestBackoffMs2),
|
|
11644
12344
|
getFlowsBundleUrl: getFlowsBundleUrlImpl,
|
|
11645
12345
|
callPublicApi: makeCallPublicApiMethod(trpc, deps, requestBackoffMs2),
|
|
11646
12346
|
async getEnvVars(envId) {
|
|
@@ -12394,4 +13094,4 @@ export {
|
|
|
12394
13094
|
createRunnerSdk
|
|
12395
13095
|
};
|
|
12396
13096
|
|
|
12397
|
-
//# debugId=
|
|
13097
|
+
//# debugId=DD6DEC33C9C6693F64756E2164756E21
|