@wayai/cli 0.3.97 → 0.3.99
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +713 -253
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15,21 +15,58 @@ var __export = (target, all) => {
|
|
|
15
15
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
// src/lib/
|
|
19
|
-
function
|
|
18
|
+
// src/lib/mask-secrets.ts
|
|
19
|
+
function valueEnd(text, from, isEnd) {
|
|
20
|
+
for (let i = from; i < text.length; i++) {
|
|
21
|
+
if (text[i] === "\\") {
|
|
22
|
+
i++;
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (isEnd(text[i])) return i;
|
|
26
|
+
}
|
|
27
|
+
return text.length;
|
|
28
|
+
}
|
|
29
|
+
function maskCredentialValues(text, keyRe, isValueEnd) {
|
|
30
|
+
keyRe.lastIndex = 0;
|
|
31
|
+
let out = "";
|
|
32
|
+
let copied = 0;
|
|
33
|
+
let match;
|
|
34
|
+
while ((match = keyRe.exec(text)) !== null) {
|
|
35
|
+
const valueStart = match.index + match[0].length;
|
|
36
|
+
keyRe.lastIndex = valueStart;
|
|
37
|
+
if (!isCredentialKey(match[1])) continue;
|
|
38
|
+
const end = valueEnd(text, valueStart, isValueEnd);
|
|
39
|
+
const value = text.slice(valueStart, end);
|
|
40
|
+
if (value.length === 0 || FULLY_MASKED_VALUE_RE.test(value)) continue;
|
|
41
|
+
out += text.slice(copied, valueStart) + "[REDACTED]";
|
|
42
|
+
copied = end;
|
|
43
|
+
keyRe.lastIndex = end;
|
|
44
|
+
}
|
|
45
|
+
return out + text.slice(copied);
|
|
46
|
+
}
|
|
47
|
+
function maskSecretsInMessage(text) {
|
|
20
48
|
let out = text;
|
|
21
|
-
for (const [pattern, replacement] of
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return out;
|
|
25
|
-
}
|
|
26
|
-
var
|
|
27
|
-
var
|
|
28
|
-
"src/lib/
|
|
49
|
+
for (const [pattern, replacement] of SHAPE_PATTERNS) out = out.replace(pattern, replacement);
|
|
50
|
+
out = maskCredentialValues(out, JSON_KEY_RE, isJsonValueEnd);
|
|
51
|
+
out = maskCredentialValues(out, QUERY_KEY_RE, isQueryValueEnd);
|
|
52
|
+
return out.replace(BASE64_RE, maskBase64);
|
|
53
|
+
}
|
|
54
|
+
var CREDENTIAL_KEY_RE, FULLY_MASKED_VALUE_RE, isCredentialKey, SHAPE_PATTERNS, JSON_KEY_RE, isJsonValueEnd, QUERY_KEY_RE, isQueryValueEnd, BASE64_RE, maskBase64;
|
|
55
|
+
var init_mask_secrets = __esm({
|
|
56
|
+
"src/lib/mask-secrets.ts"() {
|
|
29
57
|
"use strict";
|
|
30
|
-
|
|
58
|
+
CREDENTIAL_KEY_RE = /token|secret|credential|password|passwd|api[_-]?key|authorization|private[_-]?key|session[_-]?id|cookie|jwt/i;
|
|
59
|
+
FULLY_MASKED_VALUE_RE = /^(?:Bearer\s+)?(?:way_|wst_)?\[REDACTED(?:_JWT|_BASE64)?\]$/;
|
|
60
|
+
isCredentialKey = (key) => CREDENTIAL_KEY_RE.test(key);
|
|
61
|
+
SHAPE_PATTERNS = [
|
|
31
62
|
// JWTs (header.payload.signature) — WorkOS access/refresh tokens, OAuth JWTs.
|
|
32
63
|
// Run first so a `Bearer <jwt>` collapses to the JWT placeholder.
|
|
64
|
+
//
|
|
65
|
+
// Deliberately NOT anchored with the lookbehind the base64 rule uses. It would
|
|
66
|
+
// make this linear (this rule is quadratic on a pathological `eyJeyJeyJ…` run),
|
|
67
|
+
// but it also NARROWS masking: `refresh-<jwt>` and `way_<jwt>` would stop
|
|
68
|
+
// matching and leak the token whole. Correctness of a redaction rule outranks
|
|
69
|
+
// its worst case on a body that has to be adversarial to hurt.
|
|
33
70
|
[/eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g, "[REDACTED_JWT]"],
|
|
34
71
|
// way_ scoped API tokens (keyring/CI credentials). Leading \b avoids
|
|
35
72
|
// over-redacting benign substrings (e.g. `gateway_config`); the charset is
|
|
@@ -40,6 +77,42 @@ var init_redact = __esm({
|
|
|
40
77
|
// Authorization: Bearer <opaque token> (anything not already masked above).
|
|
41
78
|
[/(Bearer\s+)[A-Za-z0-9._~+/=-]{8,}/gi, "$1[REDACTED]"]
|
|
42
79
|
];
|
|
80
|
+
JSON_KEY_RE = /"([A-Za-z0-9_.-]+)"\s*:\s*"/g;
|
|
81
|
+
isJsonValueEnd = (char) => char === '"';
|
|
82
|
+
QUERY_KEY_RE = /(?:^|[?#&;,\s"'])([A-Za-z0-9_.-]+)=/g;
|
|
83
|
+
isQueryValueEnd = (char) => char === "&" || char === ";" || char === '"' || /\s/.test(char);
|
|
84
|
+
BASE64_RE = // Padded base64 bodies (wrapped DEKs, HMAC secrets, service-account material)
|
|
85
|
+
// appearing outside any credential-named key — the shape the rules above miss.
|
|
86
|
+
//
|
|
87
|
+
// Base64 has no distinguishing charset: a bare `[A-Za-z0-9+/]{20,}` run also
|
|
88
|
+
// matches slash-separated paths (`hubs/production/agents/support`), 64-char DO
|
|
89
|
+
// hex ids, and ordinary long words — all debugging context, not secrets. Three
|
|
90
|
+
// constraints buy the precision instead:
|
|
91
|
+
// 1. Terminal `=` padding, which prose and paths don't carry.
|
|
92
|
+
// 2. Nothing base64-ish after the padding, so `?param=value` (where `=` is a
|
|
93
|
+
// separator, not padding) is excluded.
|
|
94
|
+
// 3. Not sitting immediately after `?` or `&`, where a run followed by `=` is
|
|
95
|
+
// a query parameter NAME. Constraints 2 and 3 are separate cases: `=value`
|
|
96
|
+
// vs. an empty value (`?someLongParamName=&next=1`), which 2 lets through.
|
|
97
|
+
// 4. The quad-length check below, for a run reached by neither 2 nor 3
|
|
98
|
+
// (`bad xxxxxxxxxxxxxxxxxxxxxx= here`).
|
|
99
|
+
// Runs last so `Bearer <base64>` still collapses to the Bearer placeholder.
|
|
100
|
+
//
|
|
101
|
+
// The trade: unpadded base64 (any input whose byte length is a multiple of 3)
|
|
102
|
+
// is NOT matched here — no marker distinguishes it from prose. It stays covered
|
|
103
|
+
// by the credential-key rules above, which is where such a value realistically
|
|
104
|
+
// reaches this module.
|
|
105
|
+
//
|
|
106
|
+
// The leading lookbehind (NOT \b) is what keeps this linear. `/` and `+` are
|
|
107
|
+
// non-word characters, so \b also fires *inside* a base64 run: on a body like
|
|
108
|
+
// `aaaa/aaaa/aaaa/…` every slash would start a fresh greedy scan of the rest of
|
|
109
|
+
// the string, which is quadratic (~5.5s on a 100KB body, vs ~1.3ms now). "No
|
|
110
|
+
// base64 char precedes this" is both the correct notion of a run's start and
|
|
111
|
+
// O(1) starts per run — and, unlike the JWT rule above, it narrows nothing:
|
|
112
|
+
// base64 embedded mid-run isn't decodable base64 anyway.
|
|
113
|
+
// {22,} + 1-2 pad chars => a 24-char floor, i.e. a 16-byte secret.
|
|
114
|
+
/(?<![A-Za-z0-9+/])(?<![?&])[A-Za-z0-9+/]{22,}={1,2}(?![A-Za-z0-9+/=])/g;
|
|
115
|
+
maskBase64 = (match) => match.length % 4 === 0 ? "[REDACTED_BASE64]" : match;
|
|
43
116
|
}
|
|
44
117
|
});
|
|
45
118
|
|
|
@@ -119,17 +192,17 @@ function initSentry(command2, version) {
|
|
|
119
192
|
}
|
|
120
193
|
}
|
|
121
194
|
}
|
|
122
|
-
if (value.value) value.value =
|
|
195
|
+
if (value.value) value.value = maskSecretsInMessage(value.value);
|
|
123
196
|
}
|
|
124
197
|
}
|
|
125
198
|
if (event.breadcrumbs) {
|
|
126
199
|
for (const crumb of event.breadcrumbs) {
|
|
127
|
-
if (crumb.message) crumb.message =
|
|
200
|
+
if (crumb.message) crumb.message = maskSecretsInMessage(crumb.message);
|
|
128
201
|
}
|
|
129
202
|
}
|
|
130
203
|
if (event.extra) {
|
|
131
204
|
for (const [key, val] of Object.entries(event.extra)) {
|
|
132
|
-
if (typeof val === "string") event.extra[key] =
|
|
205
|
+
if (typeof val === "string") event.extra[key] = maskSecretsInMessage(val);
|
|
133
206
|
}
|
|
134
207
|
}
|
|
135
208
|
return event;
|
|
@@ -165,11 +238,11 @@ function captureException2(error, context) {
|
|
|
165
238
|
Sentry.captureException(error);
|
|
166
239
|
});
|
|
167
240
|
}
|
|
168
|
-
function addApiBreadcrumb(method,
|
|
241
|
+
function addApiBreadcrumb(method, path28) {
|
|
169
242
|
if (!initialized) return;
|
|
170
243
|
Sentry.addBreadcrumb({
|
|
171
244
|
category: "http",
|
|
172
|
-
message: `${method} ${
|
|
245
|
+
message: `${method} ${path28}`,
|
|
173
246
|
level: "info"
|
|
174
247
|
});
|
|
175
248
|
}
|
|
@@ -199,7 +272,7 @@ var HARDCODED_DSN, initialized;
|
|
|
199
272
|
var init_sentry = __esm({
|
|
200
273
|
"src/lib/sentry.ts"() {
|
|
201
274
|
"use strict";
|
|
202
|
-
|
|
275
|
+
init_mask_secrets();
|
|
203
276
|
init_network_error();
|
|
204
277
|
HARDCODED_DSN = "https://ffe500121277babcabf32e5868f00f9e@o4510669417807872.ingest.us.sentry.io/4510960145465344";
|
|
205
278
|
initialized = false;
|
|
@@ -225,15 +298,15 @@ var init_api_client = __esm({
|
|
|
225
298
|
"src/lib/api-client.ts"() {
|
|
226
299
|
"use strict";
|
|
227
300
|
init_sentry();
|
|
228
|
-
|
|
301
|
+
init_mask_secrets();
|
|
229
302
|
RETRYABLE_BACKOFF_MS = [500, 1e3, 2e3];
|
|
230
303
|
delay = (ms) => new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
231
304
|
ApiError = class extends Error {
|
|
232
305
|
status;
|
|
233
306
|
body;
|
|
234
|
-
constructor(method,
|
|
235
|
-
const safeBody =
|
|
236
|
-
super(`API request failed: ${method} ${
|
|
307
|
+
constructor(method, path28, status, body) {
|
|
308
|
+
const safeBody = maskSecretsInMessage(body);
|
|
309
|
+
super(`API request failed: ${method} ${path28} (${status}): ${safeBody}`);
|
|
237
310
|
this.name = "ApiError";
|
|
238
311
|
this.status = status;
|
|
239
312
|
this.body = safeBody;
|
|
@@ -381,8 +454,8 @@ var init_api_client = __esm({
|
|
|
381
454
|
...organizationId && { organization_id: organizationId }
|
|
382
455
|
});
|
|
383
456
|
}
|
|
384
|
-
async lookup(
|
|
385
|
-
const params = new URLSearchParams({ path:
|
|
457
|
+
async lookup(path28, opts) {
|
|
458
|
+
const params = new URLSearchParams({ path: path28 });
|
|
386
459
|
if (opts?.organizationId) params.set("organization_id", opts.organizationId);
|
|
387
460
|
return this.request("GET", `/api/ci/lookup?${params.toString()}`);
|
|
388
461
|
}
|
|
@@ -429,8 +502,11 @@ var init_api_client = __esm({
|
|
|
429
502
|
async sendMessage(hubId, message, opts) {
|
|
430
503
|
return this.request("POST", "/api/conversations/send-message", {
|
|
431
504
|
hub_id: hubId,
|
|
432
|
-
|
|
433
|
-
|
|
505
|
+
// Omitted entirely when absent: the contract allows an attachment-only send,
|
|
506
|
+
// but `message: undefined` would still fail its `.min(1)` if serialized.
|
|
507
|
+
...message && { message },
|
|
508
|
+
...opts?.conversationId && { conversation_id: opts.conversationId },
|
|
509
|
+
...opts?.attachments?.length && { attachments: opts.attachments }
|
|
434
510
|
});
|
|
435
511
|
}
|
|
436
512
|
async deleteHistory(hubId, opts) {
|
|
@@ -779,9 +855,9 @@ var init_api_client = __esm({
|
|
|
779
855
|
* sandbox for this conversation, or the blob was purged).
|
|
780
856
|
*/
|
|
781
857
|
async downloadArchiveSandboxFs(hubId, conversationId) {
|
|
782
|
-
const
|
|
783
|
-
addApiBreadcrumb("GET",
|
|
784
|
-
const url = `${this.apiUrl}${
|
|
858
|
+
const path28 = `/api/archive/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}/sandbox`;
|
|
859
|
+
addApiBreadcrumb("GET", path28);
|
|
860
|
+
const url = `${this.apiUrl}${path28}`;
|
|
785
861
|
let response = await this.send(url, "GET");
|
|
786
862
|
if (response.status === 401 && this.onUnauthorized) {
|
|
787
863
|
let refreshed;
|
|
@@ -795,7 +871,7 @@ var init_api_client = __esm({
|
|
|
795
871
|
}
|
|
796
872
|
}
|
|
797
873
|
if (!response.ok) {
|
|
798
|
-
throw new ApiError("GET",
|
|
874
|
+
throw new ApiError("GET", path28, response.status, await response.text());
|
|
799
875
|
}
|
|
800
876
|
return new Uint8Array(await response.arrayBuffer());
|
|
801
877
|
}
|
|
@@ -835,9 +911,9 @@ var init_api_client = __esm({
|
|
|
835
911
|
`/api/admin/data-explorer/debug/observability/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}${qs}`
|
|
836
912
|
);
|
|
837
913
|
}
|
|
838
|
-
async request(method,
|
|
839
|
-
addApiBreadcrumb(method,
|
|
840
|
-
const url = `${this.apiUrl}${
|
|
914
|
+
async request(method, path28, body) {
|
|
915
|
+
addApiBreadcrumb(method, path28);
|
|
916
|
+
const url = `${this.apiUrl}${path28}`;
|
|
841
917
|
let refreshedOn401 = false;
|
|
842
918
|
for (let retry = 0; ; retry++) {
|
|
843
919
|
let response = await this.send(url, method, body);
|
|
@@ -861,7 +937,7 @@ var init_api_client = __esm({
|
|
|
861
937
|
await delay(RETRYABLE_BACKOFF_MS[retry]);
|
|
862
938
|
continue;
|
|
863
939
|
}
|
|
864
|
-
throw new ApiError(method,
|
|
940
|
+
throw new ApiError(method, path28, response.status, errorBody);
|
|
865
941
|
}
|
|
866
942
|
}
|
|
867
943
|
/** Issue a single authenticated request with the client's current token. */
|
|
@@ -1296,8 +1372,8 @@ var init_parseUtil = __esm({
|
|
|
1296
1372
|
init_errors();
|
|
1297
1373
|
init_en();
|
|
1298
1374
|
makeIssue = (params) => {
|
|
1299
|
-
const { data, path:
|
|
1300
|
-
const fullPath = [...
|
|
1375
|
+
const { data, path: path28, errorMaps, issueData } = params;
|
|
1376
|
+
const fullPath = [...path28, ...issueData.path || []];
|
|
1301
1377
|
const fullIssue = {
|
|
1302
1378
|
...issueData,
|
|
1303
1379
|
path: fullPath
|
|
@@ -1608,11 +1684,11 @@ var init_types = __esm({
|
|
|
1608
1684
|
init_parseUtil();
|
|
1609
1685
|
init_util();
|
|
1610
1686
|
ParseInputLazyPath = class {
|
|
1611
|
-
constructor(parent, value,
|
|
1687
|
+
constructor(parent, value, path28, key) {
|
|
1612
1688
|
this._cachedPath = [];
|
|
1613
1689
|
this.parent = parent;
|
|
1614
1690
|
this.data = value;
|
|
1615
|
-
this._path =
|
|
1691
|
+
this._path = path28;
|
|
1616
1692
|
this._key = key;
|
|
1617
1693
|
}
|
|
1618
1694
|
get path() {
|
|
@@ -4996,10 +5072,40 @@ var init_zod = __esm({
|
|
|
4996
5072
|
});
|
|
4997
5073
|
|
|
4998
5074
|
// ../../packages/core/dist/index.js
|
|
5075
|
+
function isPublicIdentifier(value) {
|
|
5076
|
+
return UUID_RE.test(value) || HEX_RE.test(value) || WORKOS_ID_RE.test(value);
|
|
5077
|
+
}
|
|
5078
|
+
function redactTokenShapes(input) {
|
|
5079
|
+
return input.replace(TOKEN_RE, REDACTED).replace(PROVIDER_TOKEN_RE, `$1${REDACTED}`).replace(JSON_CREDENTIAL_RE, `$1"${REDACTED}"`).replace(QUERY_CREDENTIAL_RE, `$1${REDACTED}`);
|
|
5080
|
+
}
|
|
5081
|
+
function redactSecrets(value) {
|
|
5082
|
+
if (isPublicIdentifier(value)) {
|
|
5083
|
+
return value;
|
|
5084
|
+
}
|
|
5085
|
+
if (OPAQUE_SECRET_RE.test(value)) {
|
|
5086
|
+
return REDACTED;
|
|
5087
|
+
}
|
|
5088
|
+
if (BASE64_SECRET_RE.test(value) && BASE64_MARKER_RE.test(value)) {
|
|
5089
|
+
return REDACTED;
|
|
5090
|
+
}
|
|
5091
|
+
return redactTokenShapes(value);
|
|
5092
|
+
}
|
|
4999
5093
|
function normalizeAuthType(raw) {
|
|
5000
5094
|
if (VALID_AUTH_TYPES.has(raw)) return raw;
|
|
5001
5095
|
return LEGACY_AUTH_TYPE_MAP[raw] ?? raw;
|
|
5002
5096
|
}
|
|
5097
|
+
function jsonLengthOrNull(value) {
|
|
5098
|
+
try {
|
|
5099
|
+
const json = JSON.stringify(value);
|
|
5100
|
+
return typeof json === "string" ? json.length : null;
|
|
5101
|
+
} catch {
|
|
5102
|
+
return null;
|
|
5103
|
+
}
|
|
5104
|
+
}
|
|
5105
|
+
function withinJsonLength(value, max) {
|
|
5106
|
+
const length = jsonLengthOrNull(value);
|
|
5107
|
+
return length !== null && length <= max;
|
|
5108
|
+
}
|
|
5003
5109
|
function visibleLength(s) {
|
|
5004
5110
|
return s.replace(INVISIBLE_NAME_CHARS, "").length;
|
|
5005
5111
|
}
|
|
@@ -5066,12 +5172,12 @@ function typeMatches(typeField, allowed) {
|
|
|
5066
5172
|
if (Array.isArray(typeField)) return typeField.every((t) => typeof t === "string" && allowed.has(t));
|
|
5067
5173
|
return false;
|
|
5068
5174
|
}
|
|
5069
|
-
function validateSchema(schema,
|
|
5175
|
+
function validateSchema(schema, path28, errors, opts = {}) {
|
|
5070
5176
|
if (typeof schema === "boolean") return;
|
|
5071
5177
|
const depth = opts.depth ?? 0;
|
|
5072
5178
|
if (depth > MAX_SCHEMA_DEPTH) {
|
|
5073
5179
|
errors.push({
|
|
5074
|
-
path:
|
|
5180
|
+
path: path28 || "<root>",
|
|
5075
5181
|
message: `schema nesting exceeds ${MAX_SCHEMA_DEPTH} levels`,
|
|
5076
5182
|
suggestion: "Flatten the schema; LLM providers reject deeply nested tool input_schemas."
|
|
5077
5183
|
});
|
|
@@ -5079,7 +5185,7 @@ function validateSchema(schema, path27, errors, opts = {}) {
|
|
|
5079
5185
|
}
|
|
5080
5186
|
if (!isRecord(schema)) {
|
|
5081
5187
|
errors.push({
|
|
5082
|
-
path:
|
|
5188
|
+
path: path28,
|
|
5083
5189
|
message: `expected object, got ${schema === null ? "null" : typeof schema}`
|
|
5084
5190
|
});
|
|
5085
5191
|
return;
|
|
@@ -5087,14 +5193,14 @@ function validateSchema(schema, path27, errors, opts = {}) {
|
|
|
5087
5193
|
if (opts.isRoot) {
|
|
5088
5194
|
if ("type" in schema && schema.type !== "object") {
|
|
5089
5195
|
errors.push({
|
|
5090
|
-
path:
|
|
5196
|
+
path: path28 ? `${path28}.type` : "type",
|
|
5091
5197
|
message: `root type must be 'object', got ${JSON.stringify(schema.type)}`,
|
|
5092
5198
|
suggestion: "Tool parameters at the root must be an object: `{ type: 'object', properties: { ... } }`."
|
|
5093
5199
|
});
|
|
5094
5200
|
}
|
|
5095
5201
|
} else if ("type" in schema && !typeMatches(schema.type, ALLOWED_TYPES)) {
|
|
5096
5202
|
errors.push({
|
|
5097
|
-
path: `${
|
|
5203
|
+
path: `${path28}.type`,
|
|
5098
5204
|
message: `type must be one of ${[...ALLOWED_TYPES].join("/")} or an array of those, got ${JSON.stringify(schema.type)}`
|
|
5099
5205
|
});
|
|
5100
5206
|
}
|
|
@@ -5103,25 +5209,25 @@ function validateSchema(schema, path27, errors, opts = {}) {
|
|
|
5103
5209
|
if (typeof e === "string") {
|
|
5104
5210
|
const isPlaceholder = PLACEHOLDER_TOKENS.includes(e);
|
|
5105
5211
|
errors.push({
|
|
5106
|
-
path: `${
|
|
5212
|
+
path: `${path28}.enum`,
|
|
5107
5213
|
message: `enum must be a non-empty array of primitives, got string ${JSON.stringify(e)}`,
|
|
5108
5214
|
suggestion: isPlaceholder ? "Set `operation: 'update_kanban_status'` on the tool and ensure at least one hub.kanban_status has `allowsAgentUpdate: true` so the platform can render the placeholder into a valid array." : 'Wrap the value in an array: `enum: ["value"]`.'
|
|
5109
5215
|
});
|
|
5110
5216
|
} else if (!Array.isArray(e)) {
|
|
5111
5217
|
errors.push({
|
|
5112
|
-
path: `${
|
|
5218
|
+
path: `${path28}.enum`,
|
|
5113
5219
|
message: `enum must be a non-empty array of primitives, got ${typeof e}`
|
|
5114
5220
|
});
|
|
5115
5221
|
} else if (e.length === 0) {
|
|
5116
5222
|
errors.push({
|
|
5117
|
-
path: `${
|
|
5223
|
+
path: `${path28}.enum`,
|
|
5118
5224
|
message: "enum must not be empty"
|
|
5119
5225
|
});
|
|
5120
5226
|
} else {
|
|
5121
5227
|
for (let i = 0; i < e.length; i++) {
|
|
5122
5228
|
if (!isPrimitive(e[i])) {
|
|
5123
5229
|
errors.push({
|
|
5124
|
-
path: `${
|
|
5230
|
+
path: `${path28}.enum[${i}]`,
|
|
5125
5231
|
message: `enum entry must be a primitive (string/number/boolean/null), got ${typeof e[i]}`
|
|
5126
5232
|
});
|
|
5127
5233
|
}
|
|
@@ -5131,7 +5237,7 @@ function validateSchema(schema, path27, errors, opts = {}) {
|
|
|
5131
5237
|
for (const key of ["exclusiveMinimum", "exclusiveMaximum"]) {
|
|
5132
5238
|
if (key in schema && typeof schema[key] === "boolean") {
|
|
5133
5239
|
errors.push({
|
|
5134
|
-
path: `${
|
|
5240
|
+
path: `${path28}.${key}`,
|
|
5135
5241
|
message: `${key} as boolean is draft-04 syntax; draft 2020-12 requires a numeric value`,
|
|
5136
5242
|
suggestion: `Replace with the numeric bound, e.g. \`${key}: 0\`.`
|
|
5137
5243
|
});
|
|
@@ -5140,45 +5246,45 @@ function validateSchema(schema, path27, errors, opts = {}) {
|
|
|
5140
5246
|
if ("properties" in schema) {
|
|
5141
5247
|
if (!isRecord(schema.properties)) {
|
|
5142
5248
|
errors.push({
|
|
5143
|
-
path: `${
|
|
5249
|
+
path: `${path28}.properties`,
|
|
5144
5250
|
message: `properties must be an object, got ${Array.isArray(schema.properties) ? "array" : typeof schema.properties}`
|
|
5145
5251
|
});
|
|
5146
5252
|
} else {
|
|
5147
5253
|
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
5148
|
-
validateSchema(propSchema, `${
|
|
5254
|
+
validateSchema(propSchema, `${path28}.properties.${propName}`, errors, { depth: depth + 1 });
|
|
5149
5255
|
}
|
|
5150
5256
|
}
|
|
5151
5257
|
}
|
|
5152
5258
|
if (schemaTypeIncludes(schema, "array") && "items" in schema) {
|
|
5153
5259
|
if (Array.isArray(schema.items)) {
|
|
5154
|
-
schema.items.forEach((sub, i) => validateSchema(sub, `${
|
|
5260
|
+
schema.items.forEach((sub, i) => validateSchema(sub, `${path28}.items[${i}]`, errors, { depth: depth + 1 }));
|
|
5155
5261
|
} else {
|
|
5156
|
-
validateSchema(schema.items, `${
|
|
5262
|
+
validateSchema(schema.items, `${path28}.items`, errors, { depth: depth + 1 });
|
|
5157
5263
|
}
|
|
5158
5264
|
}
|
|
5159
5265
|
for (const key of SUBSCHEMA_OBJECT_KEYWORDS) {
|
|
5160
5266
|
if (key in schema && isRecord(schema[key])) {
|
|
5161
|
-
validateSchema(schema[key], `${
|
|
5267
|
+
validateSchema(schema[key], `${path28}.${key}`, errors, { depth: depth + 1 });
|
|
5162
5268
|
}
|
|
5163
5269
|
}
|
|
5164
5270
|
for (const key of SUBSCHEMA_LIST_KEYWORDS) {
|
|
5165
5271
|
const list = schema[key];
|
|
5166
5272
|
if (Array.isArray(list)) {
|
|
5167
|
-
list.forEach((sub, i) => validateSchema(sub, `${
|
|
5273
|
+
list.forEach((sub, i) => validateSchema(sub, `${path28}.${key}[${i}]`, errors, { depth: depth + 1 }));
|
|
5168
5274
|
}
|
|
5169
5275
|
}
|
|
5170
5276
|
for (const key of SUBSCHEMA_MAP_KEYWORDS) {
|
|
5171
5277
|
const map = schema[key];
|
|
5172
5278
|
if (isRecord(map)) {
|
|
5173
5279
|
for (const [name, sub] of Object.entries(map)) {
|
|
5174
|
-
validateSchema(sub, `${
|
|
5280
|
+
validateSchema(sub, `${path28}.${key}.${name}`, errors, { depth: depth + 1 });
|
|
5175
5281
|
}
|
|
5176
5282
|
}
|
|
5177
5283
|
}
|
|
5178
5284
|
const reportedPaths = new Set(errors.map((e) => e.path));
|
|
5179
5285
|
for (const [k, v] of Object.entries(schema)) {
|
|
5180
5286
|
if (typeof v !== "string") continue;
|
|
5181
|
-
const fieldPath = `${
|
|
5287
|
+
const fieldPath = `${path28}.${k}`;
|
|
5182
5288
|
if (reportedPaths.has(fieldPath)) continue;
|
|
5183
5289
|
for (const token of PLACEHOLDER_TOKENS) {
|
|
5184
5290
|
if (v === token) {
|
|
@@ -5243,6 +5349,45 @@ function refineToolConfig(value, ctx) {
|
|
|
5243
5349
|
}
|
|
5244
5350
|
}
|
|
5245
5351
|
}
|
|
5352
|
+
function describeRole(role) {
|
|
5353
|
+
if (typeof role === "string") {
|
|
5354
|
+
return JSON.stringify(role.length > ROLE_ECHO_MAX ? `${role.slice(0, ROLE_ECHO_MAX)}\u2026` : role);
|
|
5355
|
+
}
|
|
5356
|
+
if (role === null) return "null";
|
|
5357
|
+
if (Array.isArray(role)) return "an array";
|
|
5358
|
+
if (typeof role === "object") return "an object";
|
|
5359
|
+
return `a ${typeof role}`;
|
|
5360
|
+
}
|
|
5361
|
+
function asEvalInputRecord(input) {
|
|
5362
|
+
const value = typeof input === "string" ? (() => {
|
|
5363
|
+
try {
|
|
5364
|
+
return JSON.parse(input);
|
|
5365
|
+
} catch {
|
|
5366
|
+
return null;
|
|
5367
|
+
}
|
|
5368
|
+
})() : input;
|
|
5369
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
5370
|
+
}
|
|
5371
|
+
function evalInputRoleError(input) {
|
|
5372
|
+
const record = asEvalInputRecord(input);
|
|
5373
|
+
if (record === null) return null;
|
|
5374
|
+
const role = record.role;
|
|
5375
|
+
if (role === void 0 || role === null) return null;
|
|
5376
|
+
if (typeof role === "string" && EVAL_INPUT_ROLES.includes(role)) {
|
|
5377
|
+
return null;
|
|
5378
|
+
}
|
|
5379
|
+
return `role must be ${EVAL_INPUT_ROLE_LIST} (received ${describeRole(role)}) \u2014 an eval trigger is what the responder answers, and an assistant or tool role gives it nothing to answer`;
|
|
5380
|
+
}
|
|
5381
|
+
function refineEvalMessageTextRole(value, ctx) {
|
|
5382
|
+
const error = evalInputRoleError(value.eval.message_text);
|
|
5383
|
+
if (error) {
|
|
5384
|
+
ctx.addIssue({
|
|
5385
|
+
code: external_exports.ZodIssueCode.custom,
|
|
5386
|
+
path: ["eval", "message_text", "role"],
|
|
5387
|
+
message: error
|
|
5388
|
+
});
|
|
5389
|
+
}
|
|
5390
|
+
}
|
|
5246
5391
|
function refineHubAsCodeCustomTools(config, ctx) {
|
|
5247
5392
|
const agents = config.agents;
|
|
5248
5393
|
if (!Array.isArray(agents)) return;
|
|
@@ -5334,10 +5479,26 @@ function refineHubAsCodeLanes(config, ctx) {
|
|
|
5334
5479
|
}
|
|
5335
5480
|
}
|
|
5336
5481
|
}
|
|
5337
|
-
function
|
|
5338
|
-
|
|
5339
|
-
if (
|
|
5340
|
-
|
|
5482
|
+
function refineHubAsCodeEvals(config, ctx) {
|
|
5483
|
+
const evals = config.evals;
|
|
5484
|
+
if (!Array.isArray(evals)) return;
|
|
5485
|
+
for (let e = 0; e < evals.length; e++) {
|
|
5486
|
+
const entry = evals[e];
|
|
5487
|
+
const error = evalInputRoleError(entry?.input);
|
|
5488
|
+
if (error) {
|
|
5489
|
+
ctx.addIssue({
|
|
5490
|
+
code: external_exports.ZodIssueCode.custom,
|
|
5491
|
+
path: ["evals", e, "input", "role"],
|
|
5492
|
+
// Named, not just indexed — the YAML author has files, not an array.
|
|
5493
|
+
message: `eval "${entry?.name ?? "<unnamed>"}": ${error}`
|
|
5494
|
+
});
|
|
5495
|
+
}
|
|
5496
|
+
}
|
|
5497
|
+
}
|
|
5498
|
+
function isSafeTemplatePath(path28) {
|
|
5499
|
+
if (path28.length === 0 || path28.length > 300) return false;
|
|
5500
|
+
if (path28.startsWith("/") || path28.includes("\\")) return false;
|
|
5501
|
+
const segments = path28.split("/");
|
|
5341
5502
|
return segments.every(
|
|
5342
5503
|
(seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
|
|
5343
5504
|
);
|
|
@@ -5407,7 +5568,7 @@ function findStepBoundaries(transcript) {
|
|
|
5407
5568
|
}
|
|
5408
5569
|
return out;
|
|
5409
5570
|
}
|
|
5410
|
-
var APP_ERROR_BRAND, AppError, LLM_RATE_LIMIT_BRAND, LlmRateLimitError, LLM_PROVIDER_HTTP_BRAND, LlmProviderHttpError, LLM_PROVIDER_TIMEOUT_BRAND, LlmProviderTimeoutError, ExternalServiceError, CHANNEL_PROVIDER_HTTP_BRAND, ChannelProviderHttpError, MEDIA_PROVIDER_HTTP_BRAND, MediaProviderHttpError, AUTH_TYPE, ORG_CREDENTIAL_AUTH_TYPES, AUTH_TYPE_DISPLAY, LEGACY_AUTH_TYPE_MAP, VALID_AUTH_TYPES, AGENT_ROLES, SAFE_USER_ID_REGEX, SUPPORTED_LOCALES, uuidSchema, paginationSchema, timestampSchema, idParamSchema, primaryRegionSchema, placementSourceSchema, orgIdParam, orgAdminIdParam, createOrganizationBody, updateOrganizationBody, addOrgAdminBody, SUMMARIZATION_THRESHOLD_MIN, SUMMARIZATION_THRESHOLD_MAX, summarizationThresholdField, monitorConfigField, agentIdParam, listAgentsQuery, agentConnectionsQuery, createAgentBody, updateAgentBody, AGENT_PARAMETER_TYPES, AGENT_PARAMETER_NAME_REGEX, agentParameterCreateSchema, MAX_AGENT_PARAMETERS_PER_REQUEST, createAgentParametersBody, SLUG_REGEX, slugSchema, INVISIBLE_NAME_CHARS, MAX_KANBAN_STATUSES, MAX_FOLLOWUPS_PER_STATUS, MAX_LANES, MAX_ADDITIONAL_CONTEXT_SCHEMA_BYTES, RESERVED_TEMPLATE_DUMP_NAME, kanbanStatusSlugSchema, followupSchema, EXCLUSIVE_FLAG_PAIRS, kanbanStatusSchema, kanbanStatusesArraySchema, laneSchema, lanesArraySchema, hubIdParam, hubAdminIdParam, hubUserIdParam, hubIdentityIdParam, hubTeamIdParam, hubTeamUserDeleteParam, hubSchemaQuery, PREVIEW_LABEL_MAX_LENGTH, MAX_ENDED_INDEX_RETENTION_DAYS, previewLabelField, createHubBody, updateHubBody, addHubAdminBody, addHubIdentityAuthorizationBody, contactDecisionBody, approveContactBody, listContactAccessQuery, createHubTeamBody, updateHubTeamBody, addHubTeamUserBody, reassignHubUserBody, replicatePreviewBody, claimCodeChannelParam, claimCodeDeleteParam, connectionIdParam, connectorIdParam, listConnectionsQuery, deleteConnectionQuery, addConnectionBody, editConnectionBody, PRODUCTION_DIRECT_FIELDS, setProductionCredentialBody, registerWhatsappQuery, registerWhatsappBody, retryProvisioningQuery, resendDomainStatusQuery, PLACEHOLDER_TOKENS, ALLOWED_TYPES, SUBSCHEMA_OBJECT_KEYWORDS, SUBSCHEMA_LIST_KEYWORDS, SUBSCHEMA_MAP_KEYWORDS, MAX_SCHEMA_DEPTH, toolIdParam, listToolsQuery, toolAgentQuery, deleteToolQuery, toolConnectionsQuery, nativeToolIdSchema, addNativeToolBody, addMcpToolBody, createCustomToolBody, updateCustomToolBody, updateToolExecutionConfigBody, initialValueCreateSchema, initialValueUpdateSchema, stateIdParam, listStatesQuery, stateNameSchema, createStateBody, updateStateBody, reorderStatesBody, variantAiModeSchema, experimentStatusSchema, overlayUpdateSchema, experimentIdParam, variantIdParam, listExperimentsQuery, listVariantsQuery, listOverridesQuery, deleteOverrideQuery, createExperimentBody, updateExperimentBody, setExperimentStatusBody, createVariantBody, updateVariantBody, upsertOverrideBody, orgTagIdParam, listOrgTagsQuery, createOrgTagBody, updateOrgTagBody, orgCredentialIdParam, listOrgCredentialsQuery, createOrgCredentialBody, updateOrgCredentialBody, orgResourceIdParam, orgResourceFileIdParam, orgResourceFolderIdParam, hubOrgResourceParam, listOrgResourcesQuery, orgIdQuery, createOrgResourceBody, updateOrgResourceBody, createOrgResourceFolderBody, updateOrgResourceFolderBody, uploadOrgResourceFileBody, updateOrgResourceFileBody, uploadOrgSkillZipBody, linkOrgResourceBody, resourceIdParam, listResourcesQuery, createResourceBody, updateResourceBody, syncSkillsBody, resourceFileIdParam, listResourceFilesQuery, createResourceFileBody, updateResourceFileBody, uploadResourceFileBody, uploadSkillZipBody, resourceFolderIdParam, listResourceFoldersQuery, createResourceFolderBody, updateResourceFolderBody, agentResourceQuery, hubResourceQuery, linkAgentResourceBody, updateAgentResourceBody, unlinkAgentResourceQuery, navItemSchema, hubCountResetBody, navItemCountResetBody, typingBody, analyticsHubIdParam, analyticsVariableIdParam, updateVariablePinBody, updateAnalyticsViewBody, NUMERIC_FILTER_OPS, TEXT_FILTER_OPS, CATEGORICAL_FILTER_OPS, VARIABLE_FILTER_OPS, STRUCTURED_QUERY_OPS, STRUCTURED_QUERY_AGGREGATIONS, filterValueSchema, conversationsBody, analyticsConversationIdParam, messagesQuery, conversationDetailDataQuery, analyticsDataBody, structuredQueryBody, analyticsSqlBody, analyticsSqlSchemaQuery, EVAL_PACING_PRESET_NAMES, PACING_INTERVAL_MIN_MS, PACING_INTERVAL_MAX_MS, EVAL_RUN_DEADLINE_MIN_MS, EVAL_RUN_DEADLINE_MAX_MS, paginationSchema2, evalIdParam, sessionIdParam, scenarioSetIdParam, hubIdQuery, createEvalBody, updateEvalBody, getEvalsQuery, toggleEvalBody, bulkToggleEvalsBody, pacingConfigSchema, sessionConfigSchema, createSessionBody, getSessionsQuery, getSessionResultsQuery, getSessionRunsQuery, evalAnalyticsQuery, getSessionCostQuery, compareSessionsQuery, evalsSqlBody, evalsSqlSchemaQuery, exportResultsQuery, validateEvalBody, hubAgentsQuery, createScenarioSetBody, updateScenarioSetBody, scenarioSetsHubQuery, createScenarioFromConversationBody, createJourneyFromConversationBody, journeyIdParam, journeyToolCallSchema, journeyTurnSchema, journeyStepOverrideSchema, fixtureField, createJourneyBody, updateJourneyBody, getConversationsQuery, getMessagesQuery, clientOptionalString, clientOptionalBoolean, appMessageSenderType, appMessageReceiverType, appMessageAttachment, MAX_ATTACHMENTS_PER_MESSAGE, appMessageBody, updateUserBody, updateProfileBody, pathnameRegex, updatePreferencesBody, registerPushTokenBody, deletePushTokenQuery, activityQuery, deletionModeSchema, deletionRequestBody, archiveHubIdParam, archiveConversationParams, archiveListQuery, archiveMessageObservabilityParams, conversationIdParam, claimBody, releaseBody, transferBody, closeBody, additionalContextPayloadSchema, kanbanUpdateBody, annotateConversationBody, observabilityParams, observabilityListParams, deleteUserConversationsBody, sendMessageBody, listConversationsQuery, getConversationDetailParams, getConversationDetailQuery, listWhatsAppTemplatesQuery, sendWhatsAppTemplateBody, billingOrgIdParam, subscriptionItemParams, spendCapBody, growthPacksBody, portalSessionBody, checkoutSessionBody, updateBillingCurrencyBody, invoicesQuery, downloadBody, uploadQuery, signUrlBody, outboundSchemaQuery, templateIdParam, listTemplatesQuery, deleteTemplateQuery, templateStatusQuery, createTemplateBody, updateTemplateBody, submitTemplateBody, testTemplateBody, contactIdParam, listContactsQuery, createContactBody, updateContactBody, listIdParam, listListsQuery, listListContactsQuery, createListBody, updateListBody, addListContactsBody, removeListContactsBody, scheduleIdParam, listSchedulesQuery, listExecutionsQuery, createScheduleBody, updateScheduleBody, uuidPattern, ciUuidSchema, hubAsCodeConfigSchema, ciPullHubIdParam, ciBranchParam, ciPullQuery, ciHubsQuery, ciLookupQuery, ciBranchesQuery, ciSyncBody, ciPushBody, ciDiffBody, ciPublishBody, ciPublishPreviewBody, ciSyncMcpBody, ciOrgResourcesParam, orgResourcesConfigSchema, ciOrgResourcesPushBody, ciOrgResourcesDiffBody, adminOrgIdParam, adminOrgAdminIdParam, adminUserIdParam, adminPlanIdParam, adminHubIdParam, adminOrganizationsQuery, adminUserSearchQuery, kanbanSlugMigrationQuery, adjustQuotaBody, updatePlanBody, addAdminUserBody, updatePlatformConfigBody, updateFreeOrgLimitBody, adminSetOrgHarnessBody, adminSetHubHarnessBody, adminScopedTargetBody, updatePricingPlanBody, dataExplorerSearchQuery, dataExplorerOrgIdParam, dataExplorerHubIdParam, dataExplorerConvIdParam, dataExplorerDoInstancesQuery, dataExplorerNsIdParam, dataExplorerKvKeysQuery, dataExplorerKvKeyParam, uuidOrHexId, dataExplorerDeleteOrgParam, dataExplorerDeleteHubParam, dataExplorerDeleteConvParam, dataExplorerDeleteUserParam, dataExplorerDeleteQuery, dataExplorerKvDeleteQuery, pitrDoNamespace, pitrBookmarkParam, pitrRestoreBody, healthSamplingTriggerBody, dataExplorerDebugDoType, DEBUG_READ_MAX_LIMIT, DEBUG_READ_DEFAULT_LIMIT, DEBUG_DO_HEX_PREFIX, debugDoEntityId, debugTableName, dataExplorerDebugTablesParam, dataExplorerDebugRowsParam, dataExplorerDebugRowsQuery, dataExplorerDebugAnalyticsTable, debugUuid, dataExplorerDebugAnalyticsRowsParam, dataExplorerDebugAnalyticsRowsQuery, debugHubConvParam, debugMessageIdQuery, sandboxEgressPolicy, SANDBOX_EXEC_MAX_CMD_LENGTH, SANDBOX_EXEC_MAX_ALLOWLIST, SANDBOX_EXEC_MAX_TIMEOUT_MS, adminSandboxExecBody, whatsappCallbackBody, authMeResponse, wsTicketResponse, sessionCheckResponse, logoutResponse, magicCodeSendBody, magicCodeSendResponse, magicCodeVerifyBody, magicCodeVerifyResponse, browserParams, browserFoldersQuery, browserFilesQuery, stateOperationBody, conversationListResourcesQuery, conversationReadResourceQuery, listPendingSchedulesQuery, listHubAggregateSchedulesQuery, reportSourceSchema, intakeReportSourceSchema, reportClassificationSchema, reportStatusSchema, reportLocaleSchema, reportMessageAuthorRoleSchema, sentryRefStatusSchema, createReportBody, editReportBody, contestReportBody, reporterListQuery, listReportsQuery, GITHUB_ISSUE_URL_REGEX, githubIssueUrlSchema, transitionReportBody, groupReportsBody, holdReportBody, clickhouseReadyResponse, bootstrapQuery, requestSnapshotChunkMessage, MAX_NAME_LENGTH, MAX_VALUE_LENGTH, MAX_TAGS, MAX_TAG_LENGTH, MAX_SCOPE_HUBS, MAX_SCOPE_TAGS, vaultSecretScopeSchema, vaultCreateBody, vaultUpdateBody, PERMISSIONS, MAX_NAME_LENGTH2, MAX_HUBS_PER_GRANT, MAX_HUB_TAGS_PER_GRANT, MAX_GRANTS, permissionEnum, grantScopeSchema, grantSchema, createTokenBody, tokenOrgIdParam, tokenGrantScopeSchema, tokenGrantSchema, tokenMetadataSchema, listTokensResponse, createTokenResponse, orgTokenSummarySchema, listOrgTokensResponse, invitePreviewQuery, invitePreviewResponse, discordTier, discordBillingCycle, discordMetadata, discordOAuthStartResponse, discordOAuthFinalizeBody, discordOAuthFinalizeResponse, discordDisconnectResponse, jsonSchemaSchema, hubUserIdentity, stateValueEntry, getHubUserContextResponse, updateHubUserBody, updateHubUserResponse, unlockHubUserNameResponse, stateResetParams, stateResetResponse, hubAlertsParam, hubAlertSeverity, hubAlert, hubAlertsListResponse, noticeSeveritySchema, noticeStatusSchema, NOTICE_SCOPE_REGEX, noticeScopeSchema, noticeLinkSchema, createNoticeBody, updateNoticeBody, listNoticesQuery, noticeIdParamSchema, templateLocaleSchema, TEMPLATE_SLUG_REGEX, templateSlugSchema, templateStatusSchema, templateFileMapSchema, templateTextSchema, templateUsesEntrySchema, templateUsesSchema, templateYamlLocaleEntry, templateYamlWayaiBlock, templateTagsSchema, templateYamlSchema, templateHeroSchema, templatePushLocaleSchema, templatePushBody, templateListQuery, templateSlugParam, templateDetailQuery, ADMIN_SKILL_NAME_REGEX, adminSkillNameParam, WAYAI_WORKSPACE_LAYOUT, MAX_RESOURCE_FILE_SIZE;
|
|
5571
|
+
var UUID_RE, HEX_RE, WORKOS_ID_RE, OPAQUE_SECRET_RE, BASE64_SECRET_RE, BASE64_MARKER_RE, TOKEN_RE, SENSITIVE_FIELDS, SENSITIVE_KEY_ALTERNATION, SENSITIVE_KEY_PATTERN, JSON_CREDENTIAL_RE, QUERY_CREDENTIAL_RE, REDACTED, PROVIDER_TOKEN_RE, APP_ERROR_BRAND, AppError, LLM_RATE_LIMIT_BRAND, LlmRateLimitError, LLM_PROVIDER_HTTP_BRAND, LlmProviderHttpError, LLM_PROVIDER_TIMEOUT_BRAND, LlmProviderTimeoutError, ExternalServiceError, CHANNEL_PROVIDER_HTTP_BRAND, ChannelProviderHttpError, MEDIA_PROVIDER_HTTP_BRAND, MediaProviderHttpError, AUTH_TYPE, ORG_CREDENTIAL_AUTH_TYPES, AUTH_TYPE_DISPLAY, LEGACY_AUTH_TYPE_MAP, VALID_AUTH_TYPES, AGENT_ROLES, SAFE_USER_ID_REGEX, SUPPORTED_LOCALES, uuidSchema, paginationSchema, timestampSchema, idParamSchema, clientOptionalString, clientOptionalBoolean, clientOptionalNumber, messageAttachment, MAX_MESSAGE_BODY_BYTES, MAX_ATTACHMENTS_PER_MESSAGE, primaryRegionSchema, placementSourceSchema, orgIdParam, orgAdminIdParam, createOrganizationBody, updateOrganizationBody, addOrgAdminBody, SUMMARIZATION_THRESHOLD_MIN, SUMMARIZATION_THRESHOLD_MAX, summarizationThresholdField, monitorConfigField, agentIdParam, listAgentsQuery, agentConnectionsQuery, createAgentBody, updateAgentBody, AGENT_PARAMETER_TYPES, AGENT_PARAMETER_NAME_REGEX, agentParameterCreateSchema, MAX_AGENT_PARAMETERS_PER_REQUEST, createAgentParametersBody, SLUG_REGEX, slugSchema, INVISIBLE_NAME_CHARS, MAX_KANBAN_STATUSES, MAX_FOLLOWUPS_PER_STATUS, MAX_LANES, MAX_ADDITIONAL_CONTEXT_SCHEMA_BYTES, RESERVED_TEMPLATE_DUMP_NAME, kanbanStatusSlugSchema, followupSchema, EXCLUSIVE_FLAG_PAIRS, kanbanStatusSchema, kanbanStatusesArraySchema, laneSchema, lanesArraySchema, hubIdParam, hubAdminIdParam, hubUserIdParam, hubIdentityIdParam, hubTeamIdParam, hubTeamUserDeleteParam, hubSchemaQuery, PREVIEW_LABEL_MAX_LENGTH, MAX_ENDED_INDEX_RETENTION_DAYS, previewLabelField, createHubBody, updateHubBody, addHubAdminBody, addHubIdentityAuthorizationBody, contactDecisionBody, approveContactBody, listContactAccessQuery, createHubTeamBody, updateHubTeamBody, addHubTeamUserBody, reassignHubUserBody, replicatePreviewBody, updateChannelTestIdentitiesBody, claimCodeChannelParam, claimCodeDeleteParam, connectionIdParam, connectorIdParam, listConnectionsQuery, deleteConnectionQuery, addConnectionBody, editConnectionBody, PRODUCTION_DIRECT_FIELDS, setProductionCredentialBody, registerWhatsappQuery, registerWhatsappBody, retryProvisioningQuery, resendDomainStatusQuery, PLACEHOLDER_TOKENS, ALLOWED_TYPES, SUBSCHEMA_OBJECT_KEYWORDS, SUBSCHEMA_LIST_KEYWORDS, SUBSCHEMA_MAP_KEYWORDS, MAX_SCHEMA_DEPTH, toolIdParam, listToolsQuery, toolAgentQuery, deleteToolQuery, toolConnectionsQuery, nativeToolIdSchema, addNativeToolBody, addMcpToolBody, createCustomToolBody, updateCustomToolBody, updateToolExecutionConfigBody, initialValueCreateSchema, initialValueUpdateSchema, stateIdParam, listStatesQuery, stateNameSchema, createStateBody, updateStateBody, reorderStatesBody, variantAiModeSchema, experimentStatusSchema, overlayUpdateSchema, experimentIdParam, variantIdParam, listExperimentsQuery, listVariantsQuery, listOverridesQuery, deleteOverrideQuery, createExperimentBody, updateExperimentBody, setExperimentStatusBody, createVariantBody, updateVariantBody, upsertOverrideBody, orgTagIdParam, listOrgTagsQuery, createOrgTagBody, updateOrgTagBody, orgCredentialIdParam, listOrgCredentialsQuery, createOrgCredentialBody, updateOrgCredentialBody, orgResourceIdParam, orgResourceFileIdParam, orgResourceFolderIdParam, hubOrgResourceParam, listOrgResourcesQuery, orgIdQuery, createOrgResourceBody, updateOrgResourceBody, createOrgResourceFolderBody, updateOrgResourceFolderBody, uploadOrgResourceFileBody, updateOrgResourceFileBody, uploadOrgSkillZipBody, linkOrgResourceBody, resourceIdParam, listResourcesQuery, createResourceBody, updateResourceBody, syncSkillsBody, resourceFileIdParam, listResourceFilesQuery, createResourceFileBody, updateResourceFileBody, uploadResourceFileBody, uploadSkillZipBody, resourceFolderIdParam, listResourceFoldersQuery, createResourceFolderBody, updateResourceFolderBody, agentResourceQuery, hubResourceQuery, linkAgentResourceBody, updateAgentResourceBody, unlinkAgentResourceQuery, navItemSchema, hubCountResetBody, navItemCountResetBody, typingBody, analyticsHubIdParam, analyticsVariableIdParam, updateVariablePinBody, updateAnalyticsViewBody, NUMERIC_FILTER_OPS, TEXT_FILTER_OPS, CATEGORICAL_FILTER_OPS, VARIABLE_FILTER_OPS, STRUCTURED_QUERY_OPS, STRUCTURED_QUERY_AGGREGATIONS, filterValueSchema, conversationsBody, analyticsConversationIdParam, messagesQuery, conversationDetailDataQuery, analyticsDataBody, structuredQueryBody, analyticsSqlBody, analyticsSqlSchemaQuery, EVAL_PACING_PRESET_NAMES, PACING_INTERVAL_MIN_MS, PACING_INTERVAL_MAX_MS, EVAL_RUN_DEADLINE_MIN_MS, EVAL_RUN_DEADLINE_MAX_MS, paginationSchema2, evalIdParam, sessionIdParam, scenarioSetIdParam, hubIdQuery, EVAL_INPUT_ROLES, EVAL_INPUT_ROLE_LIST, ROLE_ECHO_MAX, createEvalBody, updateEvalBody, getEvalsQuery, toggleEvalBody, bulkToggleEvalsBody, pacingConfigSchema, sessionConfigSchema, createSessionBody, getSessionsQuery, getSessionResultsQuery, getSessionRunsQuery, evalAnalyticsQuery, getSessionCostQuery, compareSessionsQuery, evalsSqlBody, evalsSqlSchemaQuery, exportResultsQuery, validateEvalBody, hubAgentsQuery, createScenarioSetBody, updateScenarioSetBody, scenarioSetsHubQuery, createScenarioFromConversationBody, createJourneyFromConversationBody, journeyIdParam, journeyToolCallSchema, journeyTurnSchema, journeyStepOverrideSchema, fixtureField, createJourneyBody, updateJourneyBody, getConversationsQuery, getMessagesQuery, appMessageSenderType, appMessageReceiverType, appMessageBody, updateUserBody, updateProfileBody, pathnameRegex, updatePreferencesBody, registerPushTokenBody, deletePushTokenQuery, activityQuery, deletionModeSchema, deletionRequestBody, archiveHubIdParam, archiveConversationParams, archiveListQuery, archiveMessageObservabilityParams, conversationIdParam, claimBody, releaseBody, transferBody, closeBody, additionalContextPayloadSchema, kanbanUpdateBody, annotateConversationBody, observabilityParams, observabilityListParams, deleteUserConversationsBody, sendMessageBody, listConversationsQuery, getConversationDetailParams, getConversationDetailQuery, listWhatsAppTemplatesQuery, sendWhatsAppTemplateBody, billingOrgIdParam, subscriptionItemParams, spendCapBody, growthPacksBody, portalSessionBody, checkoutSessionBody, updateBillingCurrencyBody, invoicesQuery, downloadBody, uploadQuery, signUrlBody, outboundSchemaQuery, templateIdParam, listTemplatesQuery, deleteTemplateQuery, templateStatusQuery, createTemplateBody, updateTemplateBody, submitTemplateBody, testTemplateBody, contactIdParam, listContactsQuery, createContactBody, updateContactBody, listIdParam, listListsQuery, listListContactsQuery, createListBody, updateListBody, addListContactsBody, removeListContactsBody, scheduleIdParam, listSchedulesQuery, listExecutionsQuery, createScheduleBody, updateScheduleBody, uuidPattern, ciUuidSchema, hubAsCodeConfigSchema, ciPullHubIdParam, ciBranchParam, ciPullQuery, ciHubsQuery, ciLookupQuery, ciBranchesQuery, ciSyncBody, ciPushBody, ciDiffBody, ciPublishBody, ciPublishPreviewBody, ciSyncMcpBody, ciOrgResourcesParam, orgResourcesConfigSchema, ciOrgResourcesPushBody, ciOrgResourcesDiffBody, adminOrgIdParam, adminOrgAdminIdParam, adminUserIdParam, adminPlanIdParam, adminHubIdParam, adminOrganizationsQuery, adminUserSearchQuery, kanbanSlugMigrationQuery, adjustQuotaBody, updatePlanBody, addAdminUserBody, updatePlatformConfigBody, updateFreeOrgLimitBody, adminSetOrgHarnessBody, adminSetHubHarnessBody, adminScopedTargetBody, updatePricingPlanBody, dataExplorerSearchQuery, dataExplorerOrgIdParam, dataExplorerHubIdParam, dataExplorerConvIdParam, dataExplorerDoInstancesQuery, dataExplorerNsIdParam, dataExplorerKvKeysQuery, dataExplorerKvKeyParam, uuidOrHexId, dataExplorerDeleteOrgParam, dataExplorerDeleteHubParam, dataExplorerDeleteConvParam, dataExplorerDeleteUserParam, dataExplorerDeleteQuery, dataExplorerKvDeleteQuery, pitrDoNamespace, pitrBookmarkParam, pitrRestoreBody, healthSamplingTriggerBody, dataExplorerDebugDoType, DEBUG_READ_MAX_LIMIT, DEBUG_READ_DEFAULT_LIMIT, DEBUG_DO_HEX_PREFIX, debugDoEntityId, debugTableName, dataExplorerDebugTablesParam, dataExplorerDebugRowsParam, dataExplorerDebugRowsQuery, dataExplorerDebugAnalyticsTable, debugUuid, dataExplorerDebugAnalyticsRowsParam, dataExplorerDebugAnalyticsRowsQuery, debugHubConvParam, debugMessageIdQuery, sandboxEgressPolicy, SANDBOX_EXEC_MAX_CMD_LENGTH, SANDBOX_EXEC_MAX_ALLOWLIST, SANDBOX_EXEC_MAX_TIMEOUT_MS, adminSandboxExecBody, whatsappCallbackBody, authMeResponse, wsTicketResponse, sessionCheckResponse, logoutResponse, magicCodeSendBody, magicCodeSendResponse, magicCodeVerifyBody, magicCodeVerifyResponse, browserParams, browserFoldersQuery, browserFilesQuery, stateOperationBody, conversationListResourcesQuery, conversationReadResourceQuery, listPendingSchedulesQuery, listHubAggregateSchedulesQuery, reportSourceSchema, intakeReportSourceSchema, reportClassificationSchema, reportStatusSchema, reportLocaleSchema, reportMessageAuthorRoleSchema, sentryRefStatusSchema, createReportBody, editReportBody, contestReportBody, reporterListQuery, listReportsQuery, GITHUB_ISSUE_URL_REGEX, githubIssueUrlSchema, transitionReportBody, groupReportsBody, holdReportBody, clickhouseReadyResponse, bootstrapQuery, requestSnapshotChunkMessage, MAX_NAME_LENGTH, MAX_VALUE_LENGTH, MAX_TAGS, MAX_TAG_LENGTH, MAX_SCOPE_HUBS, MAX_SCOPE_TAGS, vaultSecretScopeSchema, vaultCreateBody, vaultUpdateBody, PERMISSIONS, MAX_NAME_LENGTH2, MAX_HUBS_PER_GRANT, MAX_HUB_TAGS_PER_GRANT, MAX_GRANTS, permissionEnum, grantScopeSchema, grantSchema, createTokenBody, tokenOrgIdParam, tokenGrantScopeSchema, tokenGrantSchema, tokenMetadataSchema, listTokensResponse, createTokenResponse, orgTokenSummarySchema, listOrgTokensResponse, invitePreviewQuery, invitePreviewResponse, discordTier, discordBillingCycle, discordMetadata, discordOAuthStartResponse, discordOAuthFinalizeBody, discordOAuthFinalizeResponse, discordDisconnectResponse, jsonSchemaSchema, hubUserIdentity, stateValueEntry, getHubUserContextResponse, updateHubUserBody, updateHubUserResponse, unlockHubUserNameResponse, stateResetParams, stateResetResponse, hubAlertsParam, hubAlertSeverity, hubAlert, hubAlertsListResponse, noticeSeveritySchema, noticeStatusSchema, NOTICE_SCOPE_REGEX, noticeScopeSchema, noticeLinkSchema, createNoticeBody, updateNoticeBody, listNoticesQuery, noticeIdParamSchema, templateLocaleSchema, TEMPLATE_SLUG_REGEX, templateSlugSchema, templateStatusSchema, templateFileMapSchema, templateTextSchema, templateUsesEntrySchema, templateUsesSchema, templateYamlLocaleEntry, templateYamlWayaiBlock, templateTagsSchema, templateYamlSchema, templateHeroSchema, templatePushLocaleSchema, templatePushBody, templateListQuery, templateSlugParam, templateDetailQuery, ADMIN_SKILL_NAME_REGEX, adminSkillNameParam, WAYAI_WORKSPACE_LAYOUT, MAX_RESOURCE_FILE_SIZE;
|
|
5411
5572
|
var init_dist = __esm({
|
|
5412
5573
|
"../../packages/core/dist/index.js"() {
|
|
5413
5574
|
"use strict";
|
|
@@ -5459,6 +5620,68 @@ var init_dist = __esm({
|
|
|
5459
5620
|
init_zod();
|
|
5460
5621
|
init_zod();
|
|
5461
5622
|
init_zod();
|
|
5623
|
+
UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
5624
|
+
HEX_RE = /^[0-9a-f]{16,}$/;
|
|
5625
|
+
WORKOS_ID_RE = /^(?:user|org)_[0-9A-HJKMNP-TV-Z]{26}$/;
|
|
5626
|
+
OPAQUE_SECRET_RE = /^[A-Za-z0-9_-]{21,}$/;
|
|
5627
|
+
BASE64_SECRET_RE = /^[A-Za-z0-9+/]{20,}={0,2}$/;
|
|
5628
|
+
BASE64_MARKER_RE = /[+=]/;
|
|
5629
|
+
TOKEN_RE = new RegExp(
|
|
5630
|
+
[
|
|
5631
|
+
// WayAI API tokens and WebSocket tickets.
|
|
5632
|
+
"(?:way|wst)_[A-Za-z0-9._-]{8,}",
|
|
5633
|
+
// Authorization header values, including base64 Basic credentials.
|
|
5634
|
+
"(?:Bearer|Basic)\\s+[A-Za-z0-9._~+/=-]{8,}",
|
|
5635
|
+
// JWTs — WorkOS session/access tokens. `eyJ` is base64 for `{"`.
|
|
5636
|
+
"eyJ[A-Za-z0-9._-]{10,}",
|
|
5637
|
+
// Stripe secret/publishable/restricted keys and webhook signing secrets.
|
|
5638
|
+
"(?:sk|pk|rk)_(?:live|test)_[A-Za-z0-9]{8,}",
|
|
5639
|
+
"whsec_[A-Za-z0-9]{8,}"
|
|
5640
|
+
// NOTE: LLM provider keys are NOT here — they need a delimiter-preserving
|
|
5641
|
+
// boundary, so they live in PROVIDER_TOKEN_RE below.
|
|
5642
|
+
].join("|"),
|
|
5643
|
+
"g"
|
|
5644
|
+
);
|
|
5645
|
+
SENSITIVE_FIELDS = [
|
|
5646
|
+
"password",
|
|
5647
|
+
"token",
|
|
5648
|
+
"secret",
|
|
5649
|
+
"api_key",
|
|
5650
|
+
"apikey",
|
|
5651
|
+
"api-key",
|
|
5652
|
+
"authorization",
|
|
5653
|
+
"auth",
|
|
5654
|
+
"credential",
|
|
5655
|
+
"private_key",
|
|
5656
|
+
"privatekey",
|
|
5657
|
+
"access_token",
|
|
5658
|
+
"refresh_token",
|
|
5659
|
+
"session_id",
|
|
5660
|
+
"sessionid",
|
|
5661
|
+
"cookie",
|
|
5662
|
+
"jwt"
|
|
5663
|
+
];
|
|
5664
|
+
SENSITIVE_KEY_ALTERNATION = SENSITIVE_FIELDS.map(
|
|
5665
|
+
(field) => field.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
|
|
5666
|
+
).join("|");
|
|
5667
|
+
SENSITIVE_KEY_PATTERN = `[A-Za-z0-9_.-]*(?:${SENSITIVE_KEY_ALTERNATION})[A-Za-z0-9_.-]*`;
|
|
5668
|
+
JSON_CREDENTIAL_RE = new RegExp(
|
|
5669
|
+
`("${SENSITIVE_KEY_PATTERN}"\\s*:\\s*)"(?:[^"\\\\]|\\\\.)*"`,
|
|
5670
|
+
"gi"
|
|
5671
|
+
);
|
|
5672
|
+
QUERY_CREDENTIAL_RE = new RegExp(
|
|
5673
|
+
`((?:^|[?&;\\s])${SENSITIVE_KEY_PATTERN}=)[^&;\\s"']+`,
|
|
5674
|
+
"gi"
|
|
5675
|
+
);
|
|
5676
|
+
REDACTED = "[REDACTED]";
|
|
5677
|
+
PROVIDER_TOKEN_RE = new RegExp(
|
|
5678
|
+
"(^|[^A-Za-z0-9])(?:" + [
|
|
5679
|
+
"sk-[A-Za-z0-9_-]{16,}",
|
|
5680
|
+
"AIza[A-Za-z0-9_-]{16,}",
|
|
5681
|
+
"xai-[A-Za-z0-9_-]{16,}"
|
|
5682
|
+
].join("|") + ")",
|
|
5683
|
+
"g"
|
|
5684
|
+
);
|
|
5462
5685
|
APP_ERROR_BRAND = /* @__PURE__ */ Symbol.for("wayai.AppError");
|
|
5463
5686
|
AppError = class extends Error {
|
|
5464
5687
|
constructor(message, code, statusCode = 500, details) {
|
|
@@ -5490,7 +5713,7 @@ var init_dist = __esm({
|
|
|
5490
5713
|
LLM_PROVIDER_HTTP_BRAND = /* @__PURE__ */ Symbol.for("wayai.LlmProviderHttpError");
|
|
5491
5714
|
LlmProviderHttpError = class extends Error {
|
|
5492
5715
|
constructor(message, status, provider, providerError) {
|
|
5493
|
-
super(message);
|
|
5716
|
+
super(redactSecrets(message));
|
|
5494
5717
|
this.status = status;
|
|
5495
5718
|
this.provider = provider;
|
|
5496
5719
|
this.providerError = providerError;
|
|
@@ -5596,6 +5819,30 @@ var init_dist = __esm({
|
|
|
5596
5819
|
idParamSchema = external_exports.object({
|
|
5597
5820
|
id: uuidSchema
|
|
5598
5821
|
});
|
|
5822
|
+
clientOptionalString = external_exports.string().nullish().transform((v) => v ?? void 0);
|
|
5823
|
+
clientOptionalBoolean = external_exports.boolean().nullish().transform((v) => v ?? void 0);
|
|
5824
|
+
clientOptionalNumber = external_exports.number().nullish().transform((v) => v ?? void 0);
|
|
5825
|
+
messageAttachment = external_exports.object({
|
|
5826
|
+
/**
|
|
5827
|
+
* Capped at the same 255 the storage layer already truncates names to, so nothing
|
|
5828
|
+
* legitimate is lost — every filesystem caps there, and `sanitizeFileName` sliced
|
|
5829
|
+
* longer names anyway.
|
|
5830
|
+
*
|
|
5831
|
+
* The bound is load-bearing, not hygiene: the RAW name is written to R2
|
|
5832
|
+
* `customMetadata.originalFileName`, and R2 rejects oversized metadata. An unbounded
|
|
5833
|
+
* name let a client make the R2 write throw a generic storage error — indistinguishable
|
|
5834
|
+
* from a real outage — which pages us via `logger.error` and, on the app channel, is
|
|
5835
|
+
* read as "we lost the file" and escalates the user to a human. Client input must not
|
|
5836
|
+
* be able to impersonate an infrastructure failure (gh #3365).
|
|
5837
|
+
*/
|
|
5838
|
+
file_name: external_exports.string().max(255),
|
|
5839
|
+
/** Base64. Bounded by the route's bodyLimit, not by this schema. */
|
|
5840
|
+
file_binary: external_exports.string(),
|
|
5841
|
+
file_size: clientOptionalNumber,
|
|
5842
|
+
file_extension: clientOptionalString
|
|
5843
|
+
});
|
|
5844
|
+
MAX_MESSAGE_BODY_BYTES = 10 * 1024 * 1024;
|
|
5845
|
+
MAX_ATTACHMENTS_PER_MESSAGE = 20;
|
|
5599
5846
|
primaryRegionSchema = external_exports.enum([
|
|
5600
5847
|
"wnam",
|
|
5601
5848
|
"enam",
|
|
@@ -5756,7 +6003,7 @@ var init_dist = __esm({
|
|
|
5756
6003
|
eventName: external_exports.string().optional(),
|
|
5757
6004
|
additional_instructions: external_exports.string().optional(),
|
|
5758
6005
|
additional_context_schema: external_exports.record(external_exports.unknown()).refine(
|
|
5759
|
-
(s) =>
|
|
6006
|
+
(s) => withinJsonLength(s, MAX_ADDITIONAL_CONTEXT_SCHEMA_BYTES),
|
|
5760
6007
|
`additional_context_schema must be at most ${MAX_ADDITIONAL_CONTEXT_SCHEMA_BYTES} bytes when JSON-serialized`
|
|
5761
6008
|
).optional(),
|
|
5762
6009
|
followups: external_exports.array(followupSchema).max(MAX_FOLLOWUPS_PER_STATUS, `followups must have at most ${MAX_FOLLOWUPS_PER_STATUS} entries`).optional(),
|
|
@@ -5982,6 +6229,9 @@ var init_dist = __esm({
|
|
|
5982
6229
|
replicatePreviewBody = external_exports.object({
|
|
5983
6230
|
preview_label: previewLabelField
|
|
5984
6231
|
});
|
|
6232
|
+
updateChannelTestIdentitiesBody = external_exports.object({
|
|
6233
|
+
test_identities: external_exports.array(external_exports.string().max(320)).max(1e3)
|
|
6234
|
+
});
|
|
5985
6235
|
claimCodeChannelParam = external_exports.object({
|
|
5986
6236
|
id: uuidSchema,
|
|
5987
6237
|
channelId: uuidSchema
|
|
@@ -6632,12 +6882,15 @@ var init_dist = __esm({
|
|
|
6632
6882
|
hubIdQuery = external_exports.object({
|
|
6633
6883
|
hub_id: external_exports.string().uuid()
|
|
6634
6884
|
});
|
|
6885
|
+
EVAL_INPUT_ROLES = ["user", "system"];
|
|
6886
|
+
EVAL_INPUT_ROLE_LIST = EVAL_INPUT_ROLES.map((r) => `"${r}"`).join(" or ");
|
|
6887
|
+
ROLE_ECHO_MAX = 40;
|
|
6635
6888
|
createEvalBody = external_exports.object({
|
|
6636
6889
|
eval: external_exports.record(external_exports.unknown())
|
|
6637
|
-
});
|
|
6890
|
+
}).superRefine(refineEvalMessageTextRole);
|
|
6638
6891
|
updateEvalBody = external_exports.object({
|
|
6639
6892
|
eval: external_exports.record(external_exports.unknown())
|
|
6640
|
-
});
|
|
6893
|
+
}).superRefine(refineEvalMessageTextRole);
|
|
6641
6894
|
getEvalsQuery = external_exports.object({
|
|
6642
6895
|
hub_id: external_exports.string().uuid(),
|
|
6643
6896
|
agent_id: external_exports.string().uuid().optional(),
|
|
@@ -6809,6 +7062,15 @@ var init_dist = __esm({
|
|
|
6809
7062
|
hub_user_id: external_exports.string().optional(),
|
|
6810
7063
|
search_filter: external_exports.string().optional(),
|
|
6811
7064
|
hub_id: external_exports.string().uuid().optional(),
|
|
7065
|
+
// NON-authorizing single-hub narrow. Unlike `hub_id` (which runs the
|
|
7066
|
+
// grant-gated `loadHub('hub:read')` and so throws for grant-less end users /
|
|
7067
|
+
// team members), `scope_hub_id` INTERSECTS the caller's already-resolved hub
|
|
7068
|
+
// roster server-side. Intersecting the caller's own roster IS the
|
|
7069
|
+
// authorization — a hub the caller isn't in narrows to empty and leaks
|
|
7070
|
+
// nothing. Continuous history sends it to take the single-hub ended-index
|
|
7071
|
+
// path (one HubDO read, accurate uncapped total) instead of the all-hub
|
|
7072
|
+
// fan-out it would otherwise discard client-side (gh #3319).
|
|
7073
|
+
scope_hub_id: external_exports.string().uuid().optional(),
|
|
6812
7074
|
conversation_id: external_exports.string().uuid().optional(),
|
|
6813
7075
|
// 'ended' = recently-closed, served warm from the HubDO index (≤ retention
|
|
6814
7076
|
// window). 'archived' = the full closed-conversation history from ClickHouse.
|
|
@@ -6849,17 +7111,8 @@ var init_dist = __esm({
|
|
|
6849
7111
|
});
|
|
6850
7112
|
}
|
|
6851
7113
|
});
|
|
6852
|
-
clientOptionalString = external_exports.string().nullish().transform((v) => v ?? void 0);
|
|
6853
|
-
clientOptionalBoolean = external_exports.boolean().nullish().transform((v) => v ?? void 0);
|
|
6854
7114
|
appMessageSenderType = external_exports.enum(["user", "team"]);
|
|
6855
7115
|
appMessageReceiverType = external_exports.enum(["user", "team", "agent", "assistant"]).transform((v) => v === "assistant" ? "agent" : v);
|
|
6856
|
-
appMessageAttachment = external_exports.object({
|
|
6857
|
-
file_name: external_exports.string(),
|
|
6858
|
-
file_binary: external_exports.string(),
|
|
6859
|
-
file_size: external_exports.number().nullish().transform((v) => v ?? void 0),
|
|
6860
|
-
file_extension: clientOptionalString
|
|
6861
|
-
});
|
|
6862
|
-
MAX_ATTACHMENTS_PER_MESSAGE = 20;
|
|
6863
7116
|
appMessageBody = external_exports.object({
|
|
6864
7117
|
// Message content — three historical aliases. All optional: an attachment-only
|
|
6865
7118
|
// or voice-only message carries no text.
|
|
@@ -6888,7 +7141,7 @@ var init_dist = __esm({
|
|
|
6888
7141
|
// Pre-generated by the client so the optimistic bubble and the stored row share
|
|
6889
7142
|
// a key (transcription live-updates land on the same row instead of duplicating).
|
|
6890
7143
|
message_id: clientOptionalString,
|
|
6891
|
-
attachments: external_exports.array(
|
|
7144
|
+
attachments: external_exports.array(messageAttachment).max(MAX_ATTACHMENTS_PER_MESSAGE).nullish().transform((v) => v ?? void 0),
|
|
6892
7145
|
// Base64-encoded audio for STT. Size-capped in the route (the cap is a byte
|
|
6893
7146
|
// budget tied to the /channels/* bodyLimit, not a shape rule).
|
|
6894
7147
|
audio_file: clientOptionalString
|
|
@@ -7015,7 +7268,7 @@ var init_dist = __esm({
|
|
|
7015
7268
|
hub_type: external_exports.enum(["chat", "task"]).default("chat"),
|
|
7016
7269
|
user_id: external_exports.string().optional()
|
|
7017
7270
|
});
|
|
7018
|
-
additionalContextPayloadSchema = external_exports.record(external_exports.unknown()).refine((r) =>
|
|
7271
|
+
additionalContextPayloadSchema = external_exports.record(external_exports.unknown()).refine((r) => withinJsonLength(r, 16384), {
|
|
7019
7272
|
message: "additional_context payload must be at most 16384 bytes when JSON-serialized"
|
|
7020
7273
|
});
|
|
7021
7274
|
kanbanUpdateBody = external_exports.object({
|
|
@@ -7059,11 +7312,27 @@ var init_dist = __esm({
|
|
|
7059
7312
|
]);
|
|
7060
7313
|
sendMessageBody = external_exports.object({
|
|
7061
7314
|
hub_id: external_exports.string().uuid(),
|
|
7062
|
-
|
|
7315
|
+
/**
|
|
7316
|
+
* Optional ONLY when `attachments` carries the payload — see the refinement below.
|
|
7317
|
+
* An attachment-only message (a photo with no caption) is the ordinary WhatsApp
|
|
7318
|
+
* gesture, so the endpoint that exists to rehearse inbound flows has to express it.
|
|
7319
|
+
* Mirrors `appMessageBody`, where content is optional for the same reason.
|
|
7320
|
+
*/
|
|
7321
|
+
message: external_exports.string().min(1).max(5e4).optional(),
|
|
7063
7322
|
/** For chat hubs: optional — automatically continues the user's active conversation (or creates one).
|
|
7064
7323
|
* For task hubs: required to continue an existing conversation. Omit to start a new task conversation. */
|
|
7065
|
-
conversation_id: external_exports.string().uuid().optional()
|
|
7066
|
-
|
|
7324
|
+
conversation_id: external_exports.string().uuid().optional(),
|
|
7325
|
+
/**
|
|
7326
|
+
* Base64 attachments, delivered over the hub's `app` channel exactly as a real
|
|
7327
|
+
* channel delivers them. Total bytes are bounded by the route's bodyLimit —
|
|
7328
|
+
* `/api/*` carries no global one (only `/webhooks/*` and `/channels/*` do), so the
|
|
7329
|
+
* route declares its own rather than inheriting an unbounded upload path.
|
|
7330
|
+
*/
|
|
7331
|
+
attachments: external_exports.array(messageAttachment).max(MAX_ATTACHMENTS_PER_MESSAGE).optional()
|
|
7332
|
+
}).refine(
|
|
7333
|
+
(b) => (b.message?.length ?? 0) > 0 || (b.attachments?.length ?? 0) > 0,
|
|
7334
|
+
{ message: "message or attachments required" }
|
|
7335
|
+
);
|
|
7067
7336
|
listConversationsQuery = external_exports.object({
|
|
7068
7337
|
hub_id: external_exports.string().uuid(),
|
|
7069
7338
|
status: external_exports.enum(["agent", "team", "ended"]).optional(),
|
|
@@ -7275,6 +7544,7 @@ var init_dist = __esm({
|
|
|
7275
7544
|
refineHubAsCodeCustomTools(config, ctx);
|
|
7276
7545
|
refineHubAsCodeKanbanStatuses(config, ctx);
|
|
7277
7546
|
refineHubAsCodeLanes(config, ctx);
|
|
7547
|
+
refineHubAsCodeEvals(config, ctx);
|
|
7278
7548
|
});
|
|
7279
7549
|
ciPullHubIdParam = external_exports.object({
|
|
7280
7550
|
hub_id: ciUuidSchema
|
|
@@ -8418,7 +8688,7 @@ function findHubByFolderName(workspaceDir, hubFolderName) {
|
|
|
8418
8688
|
function resolveHubFolderBySelector(hubsDir, selector) {
|
|
8419
8689
|
const asPath = path2.resolve(selector);
|
|
8420
8690
|
if (isDirectory(asPath) && fs2.existsSync(path2.join(asPath, "hub.yaml"))) return asPath;
|
|
8421
|
-
if (
|
|
8691
|
+
if (UUID_RE2.test(selector)) {
|
|
8422
8692
|
const match = scanWorkspaceHubs(hubsDir).find((h) => h.hubId === selector);
|
|
8423
8693
|
return match ? match.hubFolder : null;
|
|
8424
8694
|
}
|
|
@@ -8525,7 +8795,7 @@ function resolveActiveHubId(args2) {
|
|
|
8525
8795
|
const workspaceDir = workspace?.workspaceDir ?? (gitRoot ? resolveLayout(gitRoot).hubsDir : null);
|
|
8526
8796
|
const wsLabel = hubsDirLabel(gitRoot);
|
|
8527
8797
|
if (!workspaceDir || !fs2.existsSync(workspaceDir)) {
|
|
8528
|
-
if (selector &&
|
|
8798
|
+
if (selector && UUID_RE2.test(selector)) return selector;
|
|
8529
8799
|
console.error(`No ${wsLabel}/ directory found. Run \`wayai pull --hub <uuid>\` to fetch a hub, or pass --hub <uuid>.`);
|
|
8530
8800
|
process.exit(1);
|
|
8531
8801
|
}
|
|
@@ -8535,7 +8805,7 @@ function resolveActiveHubId(args2) {
|
|
|
8535
8805
|
(h) => h.hubId === selector || path2.basename(h.hubFolder) === selector
|
|
8536
8806
|
);
|
|
8537
8807
|
if (match) return match.hubId;
|
|
8538
|
-
if (
|
|
8808
|
+
if (UUID_RE2.test(selector)) return selector;
|
|
8539
8809
|
console.error(`No hub matching --hub ${selector} found in ${wsLabel}/.`);
|
|
8540
8810
|
process.exit(1);
|
|
8541
8811
|
}
|
|
@@ -8608,7 +8878,7 @@ function readRepoConfig(root) {
|
|
|
8608
8878
|
}
|
|
8609
8879
|
return null;
|
|
8610
8880
|
}
|
|
8611
|
-
if (!
|
|
8881
|
+
if (!UUID_RE2.test(config.organization_id)) return null;
|
|
8612
8882
|
const presentLegacy = LEGACY_FIELDS.filter((f) => config[f] !== void 0);
|
|
8613
8883
|
warnAboutLegacyFields(presentLegacy);
|
|
8614
8884
|
const organizationName = typeof config.organization_name === "string" && config.organization_name.trim() ? config.organization_name.trim() : void 0;
|
|
@@ -8784,7 +9054,7 @@ function parseDateArg(date, position) {
|
|
|
8784
9054
|
}
|
|
8785
9055
|
async function resolveOrganizationId(client, orgIdFlag) {
|
|
8786
9056
|
if (orgIdFlag) {
|
|
8787
|
-
if (!
|
|
9057
|
+
if (!UUID_RE2.test(orgIdFlag)) {
|
|
8788
9058
|
console.error("Invalid --org value. Expected a UUID.");
|
|
8789
9059
|
process.exit(1);
|
|
8790
9060
|
}
|
|
@@ -8842,12 +9112,12 @@ function isNewerVersion(latest, current) {
|
|
|
8842
9112
|
}
|
|
8843
9113
|
return false;
|
|
8844
9114
|
}
|
|
8845
|
-
var
|
|
9115
|
+
var UUID_RE2, slugify, OWN_HELP_COMMANDS;
|
|
8846
9116
|
var init_utils = __esm({
|
|
8847
9117
|
"src/lib/utils.ts"() {
|
|
8848
9118
|
"use strict";
|
|
8849
9119
|
init_dist();
|
|
8850
|
-
|
|
9120
|
+
UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
8851
9121
|
slugify = slugifySkillName;
|
|
8852
9122
|
OWN_HELP_COMMANDS = /* @__PURE__ */ new Set([
|
|
8853
9123
|
"eval",
|
|
@@ -8868,9 +9138,9 @@ function getVersionCachePath(filename = CLI_CACHE_FILE) {
|
|
|
8868
9138
|
}
|
|
8869
9139
|
function readVersionCache(filename = CLI_CACHE_FILE) {
|
|
8870
9140
|
try {
|
|
8871
|
-
const
|
|
8872
|
-
if (!existsSync4(
|
|
8873
|
-
const parsed = JSON.parse(readFileSync5(
|
|
9141
|
+
const path28 = getVersionCachePath(filename);
|
|
9142
|
+
if (!existsSync4(path28)) return null;
|
|
9143
|
+
const parsed = JSON.parse(readFileSync5(path28, "utf-8"));
|
|
8874
9144
|
if (typeof parsed.lastCheck !== "number") return null;
|
|
8875
9145
|
if (parsed.latest !== null && typeof parsed.latest !== "string") return null;
|
|
8876
9146
|
return parsed;
|
|
@@ -8890,10 +9160,10 @@ function isVersionCacheStale(filename = CLI_CACHE_FILE, maxAgeMs = MAX_AGE_24H_M
|
|
|
8890
9160
|
return Date.now() - cache.lastCheck > maxAgeMs;
|
|
8891
9161
|
}
|
|
8892
9162
|
function writeVersionCache(filename, cache) {
|
|
8893
|
-
const
|
|
8894
|
-
const dir = dirname3(
|
|
9163
|
+
const path28 = getVersionCachePath(filename);
|
|
9164
|
+
const dir = dirname3(path28);
|
|
8895
9165
|
if (!existsSync4(dir)) mkdirSync(dir, { recursive: true });
|
|
8896
|
-
writeFileSync2(
|
|
9166
|
+
writeFileSync2(path28, JSON.stringify(cache));
|
|
8897
9167
|
}
|
|
8898
9168
|
function touchVersionCache(filename) {
|
|
8899
9169
|
writeVersionCache(filename, { lastCheck: Date.now(), latest: readVersionCache(filename)?.latest ?? null });
|
|
@@ -8932,14 +9202,14 @@ function parseFrontmatterVersion(content) {
|
|
|
8932
9202
|
function findInstalledSkills(projectRoot, paths = SKILL_INSTALL_PATHS) {
|
|
8933
9203
|
const found = [];
|
|
8934
9204
|
for (const rel of paths) {
|
|
8935
|
-
const
|
|
8936
|
-
if (!existsSync5(
|
|
9205
|
+
const path28 = join7(projectRoot, rel);
|
|
9206
|
+
if (!existsSync5(path28)) continue;
|
|
8937
9207
|
let version = null;
|
|
8938
9208
|
try {
|
|
8939
|
-
version = parseFrontmatterVersion(readFileSync6(
|
|
9209
|
+
version = parseFrontmatterVersion(readFileSync6(path28, "utf-8"));
|
|
8940
9210
|
} catch {
|
|
8941
9211
|
}
|
|
8942
|
-
found.push({ path:
|
|
9212
|
+
found.push({ path: path28, version });
|
|
8943
9213
|
}
|
|
8944
9214
|
return found;
|
|
8945
9215
|
}
|
|
@@ -9361,7 +9631,7 @@ async function exchangeCodeForTokens(authkitDomain, clientId, code, codeVerifier
|
|
|
9361
9631
|
});
|
|
9362
9632
|
if (!response.ok) {
|
|
9363
9633
|
const body = await response.text();
|
|
9364
|
-
throw new Error(`Token exchange failed (${response.status}): ${
|
|
9634
|
+
throw new Error(`Token exchange failed (${response.status}): ${maskSecretsInMessage(body)}`);
|
|
9365
9635
|
}
|
|
9366
9636
|
return response.json();
|
|
9367
9637
|
}
|
|
@@ -9387,7 +9657,7 @@ async function refreshAccessToken(authkitDomain, clientId, refreshToken) {
|
|
|
9387
9657
|
}
|
|
9388
9658
|
if (isInvalidGrant) throw new Error("SESSION_EXPIRED");
|
|
9389
9659
|
}
|
|
9390
|
-
throw new Error(`Token refresh failed (${status}): ${
|
|
9660
|
+
throw new Error(`Token refresh failed (${status}): ${maskSecretsInMessage(body)}`);
|
|
9391
9661
|
}
|
|
9392
9662
|
return response.json();
|
|
9393
9663
|
}
|
|
@@ -9519,7 +9789,7 @@ var init_auth = __esm({
|
|
|
9519
9789
|
init_config();
|
|
9520
9790
|
init_token_store();
|
|
9521
9791
|
init_sentry();
|
|
9522
|
-
|
|
9792
|
+
init_mask_secrets();
|
|
9523
9793
|
OAUTH_CALLBACK_PORT = 3829;
|
|
9524
9794
|
AUTHKIT_DOMAIN = "https://sprightly-comic-51.authkit.app";
|
|
9525
9795
|
AUTHKIT_CLIENT_ID = "client_01KMZHB50KENM5SV90ZA80VXK4";
|
|
@@ -9842,12 +10112,12 @@ function readBinding() {
|
|
|
9842
10112
|
throw err;
|
|
9843
10113
|
}
|
|
9844
10114
|
const trimmed = raw.trim();
|
|
9845
|
-
return
|
|
10115
|
+
return UUID_RE2.test(trimmed) ? trimmed : null;
|
|
9846
10116
|
}
|
|
9847
10117
|
return null;
|
|
9848
10118
|
}
|
|
9849
10119
|
function writeBinding(hubId) {
|
|
9850
|
-
if (!
|
|
10120
|
+
if (!UUID_RE2.test(hubId)) {
|
|
9851
10121
|
throw new Error(`Invalid hub_id (must be a UUID): ${hubId}`);
|
|
9852
10122
|
}
|
|
9853
10123
|
const bindingPath = getBindingPath();
|
|
@@ -10317,7 +10587,7 @@ async function initCommand(args2) {
|
|
|
10317
10587
|
);
|
|
10318
10588
|
}
|
|
10319
10589
|
async function initDirect(client, orgId) {
|
|
10320
|
-
if (!
|
|
10590
|
+
if (!UUID_RE2.test(orgId)) {
|
|
10321
10591
|
console.error("Invalid organization ID. Expected a UUID.");
|
|
10322
10592
|
process.exit(1);
|
|
10323
10593
|
}
|
|
@@ -11297,7 +11567,7 @@ function resolveHubTarget(workspaceDir, selector) {
|
|
|
11297
11567
|
(h) => h.hubId === selector || path14.basename(h.hubFolder) === selector
|
|
11298
11568
|
);
|
|
11299
11569
|
if (match) return { hubId: match.hubId, hubFolder: match.hubFolder };
|
|
11300
|
-
if (
|
|
11570
|
+
if (UUID_RE2.test(selector)) return { hubId: selector, hubFolder: null };
|
|
11301
11571
|
console.error(`No hub matching --hub ${selector} found in ${wsLabel}/. Pass a UUID for first-time pulls.`);
|
|
11302
11572
|
process.exit(1);
|
|
11303
11573
|
}
|
|
@@ -11800,7 +12070,7 @@ New hub: "${newHub.hubName}" (${hubType})`);
|
|
|
11800
12070
|
});
|
|
11801
12071
|
const createdHub = createResult.data[0];
|
|
11802
12072
|
const hubId = createdHub.hub_id;
|
|
11803
|
-
if (!
|
|
12073
|
+
if (!UUID_RE2.test(hubId)) {
|
|
11804
12074
|
console.error(`Invalid hub_id received from server: ${hubId}`);
|
|
11805
12075
|
process.exit(1);
|
|
11806
12076
|
}
|
|
@@ -12066,6 +12336,18 @@ var init_diff = __esm({
|
|
|
12066
12336
|
});
|
|
12067
12337
|
|
|
12068
12338
|
// ../../packages/core/dist/contracts/index.js
|
|
12339
|
+
function jsonLengthOrNull2(value) {
|
|
12340
|
+
try {
|
|
12341
|
+
const json = JSON.stringify(value);
|
|
12342
|
+
return typeof json === "string" ? json.length : null;
|
|
12343
|
+
} catch {
|
|
12344
|
+
return null;
|
|
12345
|
+
}
|
|
12346
|
+
}
|
|
12347
|
+
function withinJsonLength2(value, max) {
|
|
12348
|
+
const length = jsonLengthOrNull2(value);
|
|
12349
|
+
return length !== null && length <= max;
|
|
12350
|
+
}
|
|
12069
12351
|
function normalizeAuthType2(raw) {
|
|
12070
12352
|
if (VALID_AUTH_TYPES3.has(raw)) return raw;
|
|
12071
12353
|
return LEGACY_AUTH_TYPE_MAP3[raw] ?? raw;
|
|
@@ -12136,12 +12418,12 @@ function typeMatches2(typeField, allowed) {
|
|
|
12136
12418
|
if (Array.isArray(typeField)) return typeField.every((t) => typeof t === "string" && allowed.has(t));
|
|
12137
12419
|
return false;
|
|
12138
12420
|
}
|
|
12139
|
-
function validateSchema2(schema,
|
|
12421
|
+
function validateSchema2(schema, path28, errors, opts = {}) {
|
|
12140
12422
|
if (typeof schema === "boolean") return;
|
|
12141
12423
|
const depth = opts.depth ?? 0;
|
|
12142
12424
|
if (depth > MAX_SCHEMA_DEPTH2) {
|
|
12143
12425
|
errors.push({
|
|
12144
|
-
path:
|
|
12426
|
+
path: path28 || "<root>",
|
|
12145
12427
|
message: `schema nesting exceeds ${MAX_SCHEMA_DEPTH2} levels`,
|
|
12146
12428
|
suggestion: "Flatten the schema; LLM providers reject deeply nested tool input_schemas."
|
|
12147
12429
|
});
|
|
@@ -12149,7 +12431,7 @@ function validateSchema2(schema, path27, errors, opts = {}) {
|
|
|
12149
12431
|
}
|
|
12150
12432
|
if (!isRecord2(schema)) {
|
|
12151
12433
|
errors.push({
|
|
12152
|
-
path:
|
|
12434
|
+
path: path28,
|
|
12153
12435
|
message: `expected object, got ${schema === null ? "null" : typeof schema}`
|
|
12154
12436
|
});
|
|
12155
12437
|
return;
|
|
@@ -12157,14 +12439,14 @@ function validateSchema2(schema, path27, errors, opts = {}) {
|
|
|
12157
12439
|
if (opts.isRoot) {
|
|
12158
12440
|
if ("type" in schema && schema.type !== "object") {
|
|
12159
12441
|
errors.push({
|
|
12160
|
-
path:
|
|
12442
|
+
path: path28 ? `${path28}.type` : "type",
|
|
12161
12443
|
message: `root type must be 'object', got ${JSON.stringify(schema.type)}`,
|
|
12162
12444
|
suggestion: "Tool parameters at the root must be an object: `{ type: 'object', properties: { ... } }`."
|
|
12163
12445
|
});
|
|
12164
12446
|
}
|
|
12165
12447
|
} else if ("type" in schema && !typeMatches2(schema.type, ALLOWED_TYPES2)) {
|
|
12166
12448
|
errors.push({
|
|
12167
|
-
path: `${
|
|
12449
|
+
path: `${path28}.type`,
|
|
12168
12450
|
message: `type must be one of ${[...ALLOWED_TYPES2].join("/")} or an array of those, got ${JSON.stringify(schema.type)}`
|
|
12169
12451
|
});
|
|
12170
12452
|
}
|
|
@@ -12173,25 +12455,25 @@ function validateSchema2(schema, path27, errors, opts = {}) {
|
|
|
12173
12455
|
if (typeof e === "string") {
|
|
12174
12456
|
const isPlaceholder = PLACEHOLDER_TOKENS2.includes(e);
|
|
12175
12457
|
errors.push({
|
|
12176
|
-
path: `${
|
|
12458
|
+
path: `${path28}.enum`,
|
|
12177
12459
|
message: `enum must be a non-empty array of primitives, got string ${JSON.stringify(e)}`,
|
|
12178
12460
|
suggestion: isPlaceholder ? "Set `operation: 'update_kanban_status'` on the tool and ensure at least one hub.kanban_status has `allowsAgentUpdate: true` so the platform can render the placeholder into a valid array." : 'Wrap the value in an array: `enum: ["value"]`.'
|
|
12179
12461
|
});
|
|
12180
12462
|
} else if (!Array.isArray(e)) {
|
|
12181
12463
|
errors.push({
|
|
12182
|
-
path: `${
|
|
12464
|
+
path: `${path28}.enum`,
|
|
12183
12465
|
message: `enum must be a non-empty array of primitives, got ${typeof e}`
|
|
12184
12466
|
});
|
|
12185
12467
|
} else if (e.length === 0) {
|
|
12186
12468
|
errors.push({
|
|
12187
|
-
path: `${
|
|
12469
|
+
path: `${path28}.enum`,
|
|
12188
12470
|
message: "enum must not be empty"
|
|
12189
12471
|
});
|
|
12190
12472
|
} else {
|
|
12191
12473
|
for (let i = 0; i < e.length; i++) {
|
|
12192
12474
|
if (!isPrimitive2(e[i])) {
|
|
12193
12475
|
errors.push({
|
|
12194
|
-
path: `${
|
|
12476
|
+
path: `${path28}.enum[${i}]`,
|
|
12195
12477
|
message: `enum entry must be a primitive (string/number/boolean/null), got ${typeof e[i]}`
|
|
12196
12478
|
});
|
|
12197
12479
|
}
|
|
@@ -12201,7 +12483,7 @@ function validateSchema2(schema, path27, errors, opts = {}) {
|
|
|
12201
12483
|
for (const key of ["exclusiveMinimum", "exclusiveMaximum"]) {
|
|
12202
12484
|
if (key in schema && typeof schema[key] === "boolean") {
|
|
12203
12485
|
errors.push({
|
|
12204
|
-
path: `${
|
|
12486
|
+
path: `${path28}.${key}`,
|
|
12205
12487
|
message: `${key} as boolean is draft-04 syntax; draft 2020-12 requires a numeric value`,
|
|
12206
12488
|
suggestion: `Replace with the numeric bound, e.g. \`${key}: 0\`.`
|
|
12207
12489
|
});
|
|
@@ -12210,45 +12492,45 @@ function validateSchema2(schema, path27, errors, opts = {}) {
|
|
|
12210
12492
|
if ("properties" in schema) {
|
|
12211
12493
|
if (!isRecord2(schema.properties)) {
|
|
12212
12494
|
errors.push({
|
|
12213
|
-
path: `${
|
|
12495
|
+
path: `${path28}.properties`,
|
|
12214
12496
|
message: `properties must be an object, got ${Array.isArray(schema.properties) ? "array" : typeof schema.properties}`
|
|
12215
12497
|
});
|
|
12216
12498
|
} else {
|
|
12217
12499
|
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
12218
|
-
validateSchema2(propSchema, `${
|
|
12500
|
+
validateSchema2(propSchema, `${path28}.properties.${propName}`, errors, { depth: depth + 1 });
|
|
12219
12501
|
}
|
|
12220
12502
|
}
|
|
12221
12503
|
}
|
|
12222
12504
|
if (schemaTypeIncludes2(schema, "array") && "items" in schema) {
|
|
12223
12505
|
if (Array.isArray(schema.items)) {
|
|
12224
|
-
schema.items.forEach((sub, i) => validateSchema2(sub, `${
|
|
12506
|
+
schema.items.forEach((sub, i) => validateSchema2(sub, `${path28}.items[${i}]`, errors, { depth: depth + 1 }));
|
|
12225
12507
|
} else {
|
|
12226
|
-
validateSchema2(schema.items, `${
|
|
12508
|
+
validateSchema2(schema.items, `${path28}.items`, errors, { depth: depth + 1 });
|
|
12227
12509
|
}
|
|
12228
12510
|
}
|
|
12229
12511
|
for (const key of SUBSCHEMA_OBJECT_KEYWORDS2) {
|
|
12230
12512
|
if (key in schema && isRecord2(schema[key])) {
|
|
12231
|
-
validateSchema2(schema[key], `${
|
|
12513
|
+
validateSchema2(schema[key], `${path28}.${key}`, errors, { depth: depth + 1 });
|
|
12232
12514
|
}
|
|
12233
12515
|
}
|
|
12234
12516
|
for (const key of SUBSCHEMA_LIST_KEYWORDS2) {
|
|
12235
12517
|
const list = schema[key];
|
|
12236
12518
|
if (Array.isArray(list)) {
|
|
12237
|
-
list.forEach((sub, i) => validateSchema2(sub, `${
|
|
12519
|
+
list.forEach((sub, i) => validateSchema2(sub, `${path28}.${key}[${i}]`, errors, { depth: depth + 1 }));
|
|
12238
12520
|
}
|
|
12239
12521
|
}
|
|
12240
12522
|
for (const key of SUBSCHEMA_MAP_KEYWORDS2) {
|
|
12241
12523
|
const map = schema[key];
|
|
12242
12524
|
if (isRecord2(map)) {
|
|
12243
12525
|
for (const [name, sub] of Object.entries(map)) {
|
|
12244
|
-
validateSchema2(sub, `${
|
|
12526
|
+
validateSchema2(sub, `${path28}.${key}.${name}`, errors, { depth: depth + 1 });
|
|
12245
12527
|
}
|
|
12246
12528
|
}
|
|
12247
12529
|
}
|
|
12248
12530
|
const reportedPaths = new Set(errors.map((e) => e.path));
|
|
12249
12531
|
for (const [k, v] of Object.entries(schema)) {
|
|
12250
12532
|
if (typeof v !== "string") continue;
|
|
12251
|
-
const fieldPath = `${
|
|
12533
|
+
const fieldPath = `${path28}.${k}`;
|
|
12252
12534
|
if (reportedPaths.has(fieldPath)) continue;
|
|
12253
12535
|
for (const token of PLACEHOLDER_TOKENS2) {
|
|
12254
12536
|
if (v === token) {
|
|
@@ -12313,6 +12595,45 @@ function refineToolConfig2(value, ctx) {
|
|
|
12313
12595
|
}
|
|
12314
12596
|
}
|
|
12315
12597
|
}
|
|
12598
|
+
function describeRole2(role) {
|
|
12599
|
+
if (typeof role === "string") {
|
|
12600
|
+
return JSON.stringify(role.length > ROLE_ECHO_MAX2 ? `${role.slice(0, ROLE_ECHO_MAX2)}\u2026` : role);
|
|
12601
|
+
}
|
|
12602
|
+
if (role === null) return "null";
|
|
12603
|
+
if (Array.isArray(role)) return "an array";
|
|
12604
|
+
if (typeof role === "object") return "an object";
|
|
12605
|
+
return `a ${typeof role}`;
|
|
12606
|
+
}
|
|
12607
|
+
function asEvalInputRecord2(input) {
|
|
12608
|
+
const value = typeof input === "string" ? (() => {
|
|
12609
|
+
try {
|
|
12610
|
+
return JSON.parse(input);
|
|
12611
|
+
} catch {
|
|
12612
|
+
return null;
|
|
12613
|
+
}
|
|
12614
|
+
})() : input;
|
|
12615
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
12616
|
+
}
|
|
12617
|
+
function evalInputRoleError2(input) {
|
|
12618
|
+
const record = asEvalInputRecord2(input);
|
|
12619
|
+
if (record === null) return null;
|
|
12620
|
+
const role = record.role;
|
|
12621
|
+
if (role === void 0 || role === null) return null;
|
|
12622
|
+
if (typeof role === "string" && EVAL_INPUT_ROLES2.includes(role)) {
|
|
12623
|
+
return null;
|
|
12624
|
+
}
|
|
12625
|
+
return `role must be ${EVAL_INPUT_ROLE_LIST2} (received ${describeRole2(role)}) \u2014 an eval trigger is what the responder answers, and an assistant or tool role gives it nothing to answer`;
|
|
12626
|
+
}
|
|
12627
|
+
function refineEvalMessageTextRole2(value, ctx) {
|
|
12628
|
+
const error = evalInputRoleError2(value.eval.message_text);
|
|
12629
|
+
if (error) {
|
|
12630
|
+
ctx.addIssue({
|
|
12631
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12632
|
+
path: ["eval", "message_text", "role"],
|
|
12633
|
+
message: error
|
|
12634
|
+
});
|
|
12635
|
+
}
|
|
12636
|
+
}
|
|
12316
12637
|
function refineHubAsCodeCustomTools2(config, ctx) {
|
|
12317
12638
|
const agents = config.agents;
|
|
12318
12639
|
if (!Array.isArray(agents)) return;
|
|
@@ -12404,10 +12725,26 @@ function refineHubAsCodeLanes2(config, ctx) {
|
|
|
12404
12725
|
}
|
|
12405
12726
|
}
|
|
12406
12727
|
}
|
|
12407
|
-
function
|
|
12408
|
-
|
|
12409
|
-
if (
|
|
12410
|
-
|
|
12728
|
+
function refineHubAsCodeEvals2(config, ctx) {
|
|
12729
|
+
const evals = config.evals;
|
|
12730
|
+
if (!Array.isArray(evals)) return;
|
|
12731
|
+
for (let e = 0; e < evals.length; e++) {
|
|
12732
|
+
const entry = evals[e];
|
|
12733
|
+
const error = evalInputRoleError2(entry?.input);
|
|
12734
|
+
if (error) {
|
|
12735
|
+
ctx.addIssue({
|
|
12736
|
+
code: external_exports.ZodIssueCode.custom,
|
|
12737
|
+
path: ["evals", e, "input", "role"],
|
|
12738
|
+
// Named, not just indexed — the YAML author has files, not an array.
|
|
12739
|
+
message: `eval "${entry?.name ?? "<unnamed>"}": ${error}`
|
|
12740
|
+
});
|
|
12741
|
+
}
|
|
12742
|
+
}
|
|
12743
|
+
}
|
|
12744
|
+
function isSafeTemplatePath2(path28) {
|
|
12745
|
+
if (path28.length === 0 || path28.length > 300) return false;
|
|
12746
|
+
if (path28.startsWith("/") || path28.includes("\\")) return false;
|
|
12747
|
+
const segments = path28.split("/");
|
|
12411
12748
|
return segments.every(
|
|
12412
12749
|
(seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
|
|
12413
12750
|
);
|
|
@@ -12435,14 +12772,14 @@ function isPlainObject(value) {
|
|
|
12435
12772
|
const proto = Object.getPrototypeOf(value);
|
|
12436
12773
|
return proto === Object.prototype || proto === null;
|
|
12437
12774
|
}
|
|
12438
|
-
function isSanitizableSliceFile(
|
|
12439
|
-
if (!/\.ya?ml$/i.test(
|
|
12440
|
-
return
|
|
12775
|
+
function isSanitizableSliceFile(path28) {
|
|
12776
|
+
if (!/\.ya?ml$/i.test(path28)) return false;
|
|
12777
|
+
return path28 !== "resources" && !path28.startsWith("resources/");
|
|
12441
12778
|
}
|
|
12442
12779
|
function distinctUsesBackends(uses) {
|
|
12443
12780
|
return [...new Set((uses ?? []).map((u) => u.backend))];
|
|
12444
12781
|
}
|
|
12445
|
-
var uuidSchema2, paginationSchema3, timestampSchema2, idParamSchema2, primaryRegionSchema2, placementSourceSchema2, orgIdParam2, orgAdminIdParam2, createOrganizationBody2, updateOrganizationBody2, addOrgAdminBody2, AUTH_TYPE3, ORG_CREDENTIAL_AUTH_TYPES3, AUTH_TYPE_DISPLAY3, LEGACY_AUTH_TYPE_MAP3, VALID_AUTH_TYPES3, AGENT_ROLES2, SAFE_USER_ID_REGEX2, SUPPORTED_LOCALES2, SUMMARIZATION_THRESHOLD_MIN2, SUMMARIZATION_THRESHOLD_MAX2, summarizationThresholdField2, monitorConfigField2, agentIdParam2, listAgentsQuery2, agentConnectionsQuery2, createAgentBody2, updateAgentBody2, AGENT_PARAMETER_TYPES2, AGENT_PARAMETER_NAME_REGEX2, agentParameterCreateSchema2, MAX_AGENT_PARAMETERS_PER_REQUEST2, createAgentParametersBody2, SLUG_REGEX2, slugSchema2, INVISIBLE_NAME_CHARS2, MAX_KANBAN_STATUSES2, MAX_FOLLOWUPS_PER_STATUS2, MAX_LANES2, MAX_ADDITIONAL_CONTEXT_SCHEMA_BYTES2, RESERVED_TEMPLATE_DUMP_NAME2, kanbanStatusSlugSchema2, followupSchema2, EXCLUSIVE_FLAG_PAIRS2, kanbanStatusSchema2, kanbanStatusesArraySchema2, laneSchema2, lanesArraySchema2, hubIdParam2, hubAdminIdParam2, hubUserIdParam2, hubIdentityIdParam2, hubTeamIdParam2, hubTeamUserDeleteParam2, hubSchemaQuery2, PREVIEW_LABEL_MAX_LENGTH2, MAX_ENDED_INDEX_RETENTION_DAYS2, previewLabelField2, createHubBody2, updateHubBody2, addHubAdminBody2, addHubIdentityAuthorizationBody2, contactDecisionBody2, approveContactBody2, listContactAccessQuery2, createHubTeamBody2, updateHubTeamBody2, addHubTeamUserBody2, reassignHubUserBody2, replicatePreviewBody2, claimCodeChannelParam2, claimCodeDeleteParam2, connectionIdParam2, connectorIdParam2, listConnectionsQuery2, deleteConnectionQuery2, addConnectionBody2, editConnectionBody2, PRODUCTION_DIRECT_FIELDS2, setProductionCredentialBody2, registerWhatsappQuery2, registerWhatsappBody2, retryProvisioningQuery2, resendDomainStatusQuery2, PLACEHOLDER_TOKENS2, ALLOWED_TYPES2, SUBSCHEMA_OBJECT_KEYWORDS2, SUBSCHEMA_LIST_KEYWORDS2, SUBSCHEMA_MAP_KEYWORDS2, MAX_SCHEMA_DEPTH2, toolIdParam2, listToolsQuery2, toolAgentQuery2, deleteToolQuery2, toolConnectionsQuery2, nativeToolIdSchema2, addNativeToolBody2, addMcpToolBody2, createCustomToolBody2, updateCustomToolBody2, updateToolExecutionConfigBody2, initialValueCreateSchema2, initialValueUpdateSchema2, stateIdParam2, listStatesQuery2, stateNameSchema2, createStateBody2, updateStateBody2, reorderStatesBody2, variantAiModeSchema2, experimentStatusSchema2, overlayUpdateSchema2, experimentIdParam2, variantIdParam2, listExperimentsQuery2, listVariantsQuery2, listOverridesQuery2, deleteOverrideQuery2, createExperimentBody2, updateExperimentBody2, setExperimentStatusBody2, createVariantBody2, updateVariantBody2, upsertOverrideBody2, orgTagIdParam2, listOrgTagsQuery2, createOrgTagBody2, updateOrgTagBody2, orgCredentialIdParam2, listOrgCredentialsQuery2, createOrgCredentialBody2, updateOrgCredentialBody2, orgResourceIdParam2, orgResourceFileIdParam2, orgResourceFolderIdParam2, hubOrgResourceParam2, listOrgResourcesQuery2, orgIdQuery2, createOrgResourceBody2, updateOrgResourceBody2, createOrgResourceFolderBody2, updateOrgResourceFolderBody2, uploadOrgResourceFileBody2, updateOrgResourceFileBody2, uploadOrgSkillZipBody2, linkOrgResourceBody2, resourceIdParam2, listResourcesQuery2, createResourceBody2, updateResourceBody2, syncSkillsBody2, resourceFileIdParam2, listResourceFilesQuery2, createResourceFileBody2, updateResourceFileBody2, uploadResourceFileBody2, uploadSkillZipBody2, resourceFolderIdParam2, listResourceFoldersQuery2, createResourceFolderBody2, updateResourceFolderBody2, agentResourceQuery2, hubResourceQuery2, linkAgentResourceBody2, updateAgentResourceBody2, unlinkAgentResourceQuery2, navItemSchema2, hubCountResetBody2, navItemCountResetBody2, typingBody2, analyticsHubIdParam2, analyticsVariableIdParam2, updateVariablePinBody2, updateAnalyticsViewBody2, NUMERIC_FILTER_OPS2, TEXT_FILTER_OPS2, CATEGORICAL_FILTER_OPS2, VARIABLE_FILTER_OPS2, STRUCTURED_QUERY_OPS2, STRUCTURED_QUERY_AGGREGATIONS2, filterValueSchema2, conversationsBody2, analyticsConversationIdParam2, messagesQuery2, conversationDetailDataQuery2, analyticsDataBody2, structuredQueryBody2, analyticsSqlBody2, analyticsSqlSchemaQuery2, EVAL_PACING_PRESET_NAMES2, PACING_INTERVAL_MIN_MS2, PACING_INTERVAL_MAX_MS2, EVAL_RUN_DEADLINE_MIN_MS2, EVAL_RUN_DEADLINE_MAX_MS2, paginationSchema22, evalIdParam2, sessionIdParam2, scenarioSetIdParam2, hubIdQuery2, createEvalBody2, updateEvalBody2, getEvalsQuery2, toggleEvalBody2, bulkToggleEvalsBody2, pacingConfigSchema2, sessionConfigSchema2, createSessionBody2, getSessionsQuery2, getSessionResultsQuery2, getSessionRunsQuery2, evalAnalyticsQuery2, getSessionCostQuery2, compareSessionsQuery2, evalsSqlBody2, evalsSqlSchemaQuery2, exportResultsQuery2, validateEvalBody2, hubAgentsQuery2, createScenarioSetBody2, updateScenarioSetBody2, scenarioSetsHubQuery2, createScenarioFromConversationBody2, createJourneyFromConversationBody2, journeyIdParam2, journeyToolCallSchema2, journeyTurnSchema2, journeyStepOverrideSchema2, fixtureField2, createJourneyBody2, updateJourneyBody2, getConversationsQuery2, getMessagesQuery2, clientOptionalString2, clientOptionalBoolean2, appMessageSenderType2, appMessageReceiverType2, appMessageAttachment2, MAX_ATTACHMENTS_PER_MESSAGE2, appMessageBody2, updateUserBody2, updateProfileBody2, pathnameRegex2, updatePreferencesBody2, registerPushTokenBody2, deletePushTokenQuery2, activityQuery2, deletionModeSchema2, deletionRequestBody2, archiveHubIdParam2, archiveConversationParams2, archiveListQuery2, archiveMessageObservabilityParams2, conversationIdParam2, claimBody2, releaseBody2, transferBody2, closeBody2, additionalContextPayloadSchema2, kanbanUpdateBody2, annotateConversationBody2, observabilityParams2, observabilityListParams2, deleteUserConversationsBody2, sendMessageBody2, listConversationsQuery2, getConversationDetailParams2, getConversationDetailQuery2, listWhatsAppTemplatesQuery2, sendWhatsAppTemplateBody2, billingOrgIdParam2, subscriptionItemParams2, spendCapBody2, growthPacksBody2, portalSessionBody2, checkoutSessionBody2, updateBillingCurrencyBody2, invoicesQuery2, downloadBody2, uploadQuery2, signUrlBody2, outboundSchemaQuery2, templateIdParam2, listTemplatesQuery2, deleteTemplateQuery2, templateStatusQuery2, createTemplateBody2, updateTemplateBody2, submitTemplateBody2, testTemplateBody2, contactIdParam2, listContactsQuery2, createContactBody2, updateContactBody2, listIdParam2, listListsQuery2, listListContactsQuery2, createListBody2, updateListBody2, addListContactsBody2, removeListContactsBody2, scheduleIdParam2, listSchedulesQuery2, listExecutionsQuery2, createScheduleBody2, updateScheduleBody2, uuidPattern2, ciUuidSchema2, hubAsCodeConfigSchema2, ciPullHubIdParam2, ciBranchParam2, ciPullQuery2, ciHubsQuery2, ciLookupQuery2, ciBranchesQuery2, ciSyncBody2, ciPushBody2, ciDiffBody2, ciPublishBody2, ciPublishPreviewBody2, ciSyncMcpBody2, ciOrgResourcesParam2, orgResourcesConfigSchema2, ciOrgResourcesPushBody2, ciOrgResourcesDiffBody2, adminOrgIdParam2, adminOrgAdminIdParam2, adminUserIdParam2, adminPlanIdParam2, adminHubIdParam2, adminOrganizationsQuery2, adminUserSearchQuery2, kanbanSlugMigrationQuery2, adjustQuotaBody2, updatePlanBody2, addAdminUserBody2, updatePlatformConfigBody2, updateFreeOrgLimitBody2, adminSetOrgHarnessBody2, adminSetHubHarnessBody2, adminScopedTargetBody2, updatePricingPlanBody2, dataExplorerSearchQuery2, dataExplorerOrgIdParam2, dataExplorerHubIdParam2, dataExplorerConvIdParam2, dataExplorerDoInstancesQuery2, dataExplorerNsIdParam2, dataExplorerKvKeysQuery2, dataExplorerKvKeyParam2, uuidOrHexId2, dataExplorerDeleteOrgParam2, dataExplorerDeleteHubParam2, dataExplorerDeleteConvParam2, dataExplorerDeleteUserParam2, dataExplorerDeleteQuery2, dataExplorerKvDeleteQuery2, pitrDoNamespace2, pitrBookmarkParam2, pitrRestoreBody2, healthSamplingTriggerBody2, dataExplorerDebugDoType2, DEBUG_READ_MAX_LIMIT2, DEBUG_READ_DEFAULT_LIMIT2, DEBUG_DO_HEX_PREFIX2, debugDoEntityId2, debugTableName2, dataExplorerDebugTablesParam2, dataExplorerDebugRowsParam2, dataExplorerDebugRowsQuery2, dataExplorerDebugAnalyticsTable2, debugUuid2, dataExplorerDebugAnalyticsRowsParam2, dataExplorerDebugAnalyticsRowsQuery2, debugHubConvParam2, debugMessageIdQuery2, sandboxEgressPolicy2, SANDBOX_EXEC_MAX_CMD_LENGTH2, SANDBOX_EXEC_MAX_ALLOWLIST2, SANDBOX_EXEC_MAX_TIMEOUT_MS2, adminSandboxExecBody2, whatsappCallbackBody2, authMeResponse2, wsTicketResponse2, sessionCheckResponse2, logoutResponse2, magicCodeSendBody2, magicCodeSendResponse2, magicCodeVerifyBody2, magicCodeVerifyResponse2, browserParams2, browserFoldersQuery2, browserFilesQuery2, stateOperationBody2, conversationListResourcesQuery2, conversationReadResourceQuery2, listPendingSchedulesQuery2, listHubAggregateSchedulesQuery2, reportSourceSchema2, intakeReportSourceSchema2, reportClassificationSchema2, reportStatusSchema2, reportLocaleSchema2, reportMessageAuthorRoleSchema2, sentryRefStatusSchema2, createReportBody2, editReportBody2, contestReportBody2, reporterListQuery2, listReportsQuery2, GITHUB_ISSUE_URL_REGEX2, githubIssueUrlSchema2, transitionReportBody2, groupReportsBody2, holdReportBody2, clickhouseReadyResponse2, bootstrapQuery2, requestSnapshotChunkMessage2, MAX_NAME_LENGTH3, MAX_VALUE_LENGTH2, MAX_TAGS2, MAX_TAG_LENGTH2, MAX_SCOPE_HUBS2, MAX_SCOPE_TAGS2, vaultSecretScopeSchema2, vaultCreateBody2, vaultUpdateBody2, PERMISSIONS2, MAX_NAME_LENGTH22, MAX_HUBS_PER_GRANT2, MAX_HUB_TAGS_PER_GRANT2, MAX_GRANTS2, permissionEnum2, grantScopeSchema2, grantSchema2, createTokenBody2, tokenOrgIdParam2, tokenGrantScopeSchema2, tokenGrantSchema2, tokenMetadataSchema2, listTokensResponse2, createTokenResponse2, orgTokenSummarySchema2, listOrgTokensResponse2, invitePreviewQuery2, invitePreviewResponse2, discordTier2, discordBillingCycle2, discordMetadata2, discordOAuthStartResponse2, discordOAuthFinalizeBody2, discordOAuthFinalizeResponse2, discordDisconnectResponse2, jsonSchemaSchema2, hubUserIdentity2, stateValueEntry2, getHubUserContextResponse2, updateHubUserBody2, updateHubUserResponse2, unlockHubUserNameResponse2, stateResetParams2, stateResetResponse2, hubAlertsParam2, hubAlertSeverity2, hubAlert2, hubAlertsListResponse2, noticeSeveritySchema2, noticeStatusSchema2, NOTICE_SCOPE_REGEX2, noticeScopeSchema2, noticeLinkSchema2, createNoticeBody2, updateNoticeBody2, listNoticesQuery2, noticeIdParamSchema2, templateLocaleSchema2, TEMPLATE_SLUG_REGEX2, templateSlugSchema2, templateStatusSchema2, templateFileMapSchema2, TEMPLATE_INSTANCE_ID_KEYS, TEMPLATE_OPAQUE_BLOB_KEYS, TEMPLATE_AUTHOR_DATA_KEYS, templateTextSchema2, templateUsesEntrySchema2, templateUsesSchema2, templateYamlLocaleEntry2, templateYamlWayaiBlock2, templateTagsSchema2, templateYamlSchema2, templateHeroSchema2, templatePushLocaleSchema2, templatePushBody2, templateListQuery2, templateSlugParam2, templateDetailQuery2, ADMIN_SKILL_NAME_REGEX2, adminSkillNameParam2;
|
|
12782
|
+
var uuidSchema2, paginationSchema3, timestampSchema2, idParamSchema2, clientOptionalString2, clientOptionalBoolean2, clientOptionalNumber2, messageAttachment2, MAX_MESSAGE_BODY_BYTES2, MAX_ATTACHMENTS_PER_MESSAGE2, primaryRegionSchema2, placementSourceSchema2, orgIdParam2, orgAdminIdParam2, createOrganizationBody2, updateOrganizationBody2, addOrgAdminBody2, AUTH_TYPE3, ORG_CREDENTIAL_AUTH_TYPES3, AUTH_TYPE_DISPLAY3, LEGACY_AUTH_TYPE_MAP3, VALID_AUTH_TYPES3, AGENT_ROLES2, SAFE_USER_ID_REGEX2, SUPPORTED_LOCALES2, SUMMARIZATION_THRESHOLD_MIN2, SUMMARIZATION_THRESHOLD_MAX2, summarizationThresholdField2, monitorConfigField2, agentIdParam2, listAgentsQuery2, agentConnectionsQuery2, createAgentBody2, updateAgentBody2, AGENT_PARAMETER_TYPES2, AGENT_PARAMETER_NAME_REGEX2, agentParameterCreateSchema2, MAX_AGENT_PARAMETERS_PER_REQUEST2, createAgentParametersBody2, SLUG_REGEX2, slugSchema2, INVISIBLE_NAME_CHARS2, MAX_KANBAN_STATUSES2, MAX_FOLLOWUPS_PER_STATUS2, MAX_LANES2, MAX_ADDITIONAL_CONTEXT_SCHEMA_BYTES2, RESERVED_TEMPLATE_DUMP_NAME2, kanbanStatusSlugSchema2, followupSchema2, EXCLUSIVE_FLAG_PAIRS2, kanbanStatusSchema2, kanbanStatusesArraySchema2, laneSchema2, lanesArraySchema2, hubIdParam2, hubAdminIdParam2, hubUserIdParam2, hubIdentityIdParam2, hubTeamIdParam2, hubTeamUserDeleteParam2, hubSchemaQuery2, PREVIEW_LABEL_MAX_LENGTH2, MAX_ENDED_INDEX_RETENTION_DAYS2, previewLabelField2, createHubBody2, updateHubBody2, addHubAdminBody2, addHubIdentityAuthorizationBody2, contactDecisionBody2, approveContactBody2, listContactAccessQuery2, createHubTeamBody2, updateHubTeamBody2, addHubTeamUserBody2, reassignHubUserBody2, replicatePreviewBody2, updateChannelTestIdentitiesBody2, claimCodeChannelParam2, claimCodeDeleteParam2, connectionIdParam2, connectorIdParam2, listConnectionsQuery2, deleteConnectionQuery2, addConnectionBody2, editConnectionBody2, PRODUCTION_DIRECT_FIELDS2, setProductionCredentialBody2, registerWhatsappQuery2, registerWhatsappBody2, retryProvisioningQuery2, resendDomainStatusQuery2, PLACEHOLDER_TOKENS2, ALLOWED_TYPES2, SUBSCHEMA_OBJECT_KEYWORDS2, SUBSCHEMA_LIST_KEYWORDS2, SUBSCHEMA_MAP_KEYWORDS2, MAX_SCHEMA_DEPTH2, toolIdParam2, listToolsQuery2, toolAgentQuery2, deleteToolQuery2, toolConnectionsQuery2, nativeToolIdSchema2, addNativeToolBody2, addMcpToolBody2, createCustomToolBody2, updateCustomToolBody2, updateToolExecutionConfigBody2, initialValueCreateSchema2, initialValueUpdateSchema2, stateIdParam2, listStatesQuery2, stateNameSchema2, createStateBody2, updateStateBody2, reorderStatesBody2, variantAiModeSchema2, experimentStatusSchema2, overlayUpdateSchema2, experimentIdParam2, variantIdParam2, listExperimentsQuery2, listVariantsQuery2, listOverridesQuery2, deleteOverrideQuery2, createExperimentBody2, updateExperimentBody2, setExperimentStatusBody2, createVariantBody2, updateVariantBody2, upsertOverrideBody2, orgTagIdParam2, listOrgTagsQuery2, createOrgTagBody2, updateOrgTagBody2, orgCredentialIdParam2, listOrgCredentialsQuery2, createOrgCredentialBody2, updateOrgCredentialBody2, orgResourceIdParam2, orgResourceFileIdParam2, orgResourceFolderIdParam2, hubOrgResourceParam2, listOrgResourcesQuery2, orgIdQuery2, createOrgResourceBody2, updateOrgResourceBody2, createOrgResourceFolderBody2, updateOrgResourceFolderBody2, uploadOrgResourceFileBody2, updateOrgResourceFileBody2, uploadOrgSkillZipBody2, linkOrgResourceBody2, resourceIdParam2, listResourcesQuery2, createResourceBody2, updateResourceBody2, syncSkillsBody2, resourceFileIdParam2, listResourceFilesQuery2, createResourceFileBody2, updateResourceFileBody2, uploadResourceFileBody2, uploadSkillZipBody2, resourceFolderIdParam2, listResourceFoldersQuery2, createResourceFolderBody2, updateResourceFolderBody2, agentResourceQuery2, hubResourceQuery2, linkAgentResourceBody2, updateAgentResourceBody2, unlinkAgentResourceQuery2, navItemSchema2, hubCountResetBody2, navItemCountResetBody2, typingBody2, analyticsHubIdParam2, analyticsVariableIdParam2, updateVariablePinBody2, updateAnalyticsViewBody2, NUMERIC_FILTER_OPS2, TEXT_FILTER_OPS2, CATEGORICAL_FILTER_OPS2, VARIABLE_FILTER_OPS2, STRUCTURED_QUERY_OPS2, STRUCTURED_QUERY_AGGREGATIONS2, filterValueSchema2, conversationsBody2, analyticsConversationIdParam2, messagesQuery2, conversationDetailDataQuery2, analyticsDataBody2, structuredQueryBody2, analyticsSqlBody2, analyticsSqlSchemaQuery2, EVAL_PACING_PRESET_NAMES2, PACING_INTERVAL_MIN_MS2, PACING_INTERVAL_MAX_MS2, EVAL_RUN_DEADLINE_MIN_MS2, EVAL_RUN_DEADLINE_MAX_MS2, paginationSchema22, evalIdParam2, sessionIdParam2, scenarioSetIdParam2, hubIdQuery2, EVAL_INPUT_ROLES2, EVAL_INPUT_ROLE_LIST2, ROLE_ECHO_MAX2, createEvalBody2, updateEvalBody2, getEvalsQuery2, toggleEvalBody2, bulkToggleEvalsBody2, pacingConfigSchema2, sessionConfigSchema2, createSessionBody2, getSessionsQuery2, getSessionResultsQuery2, getSessionRunsQuery2, evalAnalyticsQuery2, getSessionCostQuery2, compareSessionsQuery2, evalsSqlBody2, evalsSqlSchemaQuery2, exportResultsQuery2, validateEvalBody2, hubAgentsQuery2, createScenarioSetBody2, updateScenarioSetBody2, scenarioSetsHubQuery2, createScenarioFromConversationBody2, createJourneyFromConversationBody2, journeyIdParam2, journeyToolCallSchema2, journeyTurnSchema2, journeyStepOverrideSchema2, fixtureField2, createJourneyBody2, updateJourneyBody2, getConversationsQuery2, getMessagesQuery2, appMessageSenderType2, appMessageReceiverType2, appMessageBody2, updateUserBody2, updateProfileBody2, pathnameRegex2, updatePreferencesBody2, registerPushTokenBody2, deletePushTokenQuery2, activityQuery2, deletionModeSchema2, deletionRequestBody2, archiveHubIdParam2, archiveConversationParams2, archiveListQuery2, archiveMessageObservabilityParams2, conversationIdParam2, claimBody2, releaseBody2, transferBody2, closeBody2, additionalContextPayloadSchema2, kanbanUpdateBody2, annotateConversationBody2, observabilityParams2, observabilityListParams2, deleteUserConversationsBody2, sendMessageBody2, listConversationsQuery2, getConversationDetailParams2, getConversationDetailQuery2, listWhatsAppTemplatesQuery2, sendWhatsAppTemplateBody2, billingOrgIdParam2, subscriptionItemParams2, spendCapBody2, growthPacksBody2, portalSessionBody2, checkoutSessionBody2, updateBillingCurrencyBody2, invoicesQuery2, downloadBody2, uploadQuery2, signUrlBody2, outboundSchemaQuery2, templateIdParam2, listTemplatesQuery2, deleteTemplateQuery2, templateStatusQuery2, createTemplateBody2, updateTemplateBody2, submitTemplateBody2, testTemplateBody2, contactIdParam2, listContactsQuery2, createContactBody2, updateContactBody2, listIdParam2, listListsQuery2, listListContactsQuery2, createListBody2, updateListBody2, addListContactsBody2, removeListContactsBody2, scheduleIdParam2, listSchedulesQuery2, listExecutionsQuery2, createScheduleBody2, updateScheduleBody2, uuidPattern2, ciUuidSchema2, hubAsCodeConfigSchema2, ciPullHubIdParam2, ciBranchParam2, ciPullQuery2, ciHubsQuery2, ciLookupQuery2, ciBranchesQuery2, ciSyncBody2, ciPushBody2, ciDiffBody2, ciPublishBody2, ciPublishPreviewBody2, ciSyncMcpBody2, ciOrgResourcesParam2, orgResourcesConfigSchema2, ciOrgResourcesPushBody2, ciOrgResourcesDiffBody2, adminOrgIdParam2, adminOrgAdminIdParam2, adminUserIdParam2, adminPlanIdParam2, adminHubIdParam2, adminOrganizationsQuery2, adminUserSearchQuery2, kanbanSlugMigrationQuery2, adjustQuotaBody2, updatePlanBody2, addAdminUserBody2, updatePlatformConfigBody2, updateFreeOrgLimitBody2, adminSetOrgHarnessBody2, adminSetHubHarnessBody2, adminScopedTargetBody2, updatePricingPlanBody2, dataExplorerSearchQuery2, dataExplorerOrgIdParam2, dataExplorerHubIdParam2, dataExplorerConvIdParam2, dataExplorerDoInstancesQuery2, dataExplorerNsIdParam2, dataExplorerKvKeysQuery2, dataExplorerKvKeyParam2, uuidOrHexId2, dataExplorerDeleteOrgParam2, dataExplorerDeleteHubParam2, dataExplorerDeleteConvParam2, dataExplorerDeleteUserParam2, dataExplorerDeleteQuery2, dataExplorerKvDeleteQuery2, pitrDoNamespace2, pitrBookmarkParam2, pitrRestoreBody2, healthSamplingTriggerBody2, dataExplorerDebugDoType2, DEBUG_READ_MAX_LIMIT2, DEBUG_READ_DEFAULT_LIMIT2, DEBUG_DO_HEX_PREFIX2, debugDoEntityId2, debugTableName2, dataExplorerDebugTablesParam2, dataExplorerDebugRowsParam2, dataExplorerDebugRowsQuery2, dataExplorerDebugAnalyticsTable2, debugUuid2, dataExplorerDebugAnalyticsRowsParam2, dataExplorerDebugAnalyticsRowsQuery2, debugHubConvParam2, debugMessageIdQuery2, sandboxEgressPolicy2, SANDBOX_EXEC_MAX_CMD_LENGTH2, SANDBOX_EXEC_MAX_ALLOWLIST2, SANDBOX_EXEC_MAX_TIMEOUT_MS2, adminSandboxExecBody2, whatsappCallbackBody2, authMeResponse2, wsTicketResponse2, sessionCheckResponse2, logoutResponse2, magicCodeSendBody2, magicCodeSendResponse2, magicCodeVerifyBody2, magicCodeVerifyResponse2, browserParams2, browserFoldersQuery2, browserFilesQuery2, stateOperationBody2, conversationListResourcesQuery2, conversationReadResourceQuery2, listPendingSchedulesQuery2, listHubAggregateSchedulesQuery2, reportSourceSchema2, intakeReportSourceSchema2, reportClassificationSchema2, reportStatusSchema2, reportLocaleSchema2, reportMessageAuthorRoleSchema2, sentryRefStatusSchema2, createReportBody2, editReportBody2, contestReportBody2, reporterListQuery2, listReportsQuery2, GITHUB_ISSUE_URL_REGEX2, githubIssueUrlSchema2, transitionReportBody2, groupReportsBody2, holdReportBody2, clickhouseReadyResponse2, bootstrapQuery2, requestSnapshotChunkMessage2, MAX_NAME_LENGTH3, MAX_VALUE_LENGTH2, MAX_TAGS2, MAX_TAG_LENGTH2, MAX_SCOPE_HUBS2, MAX_SCOPE_TAGS2, vaultSecretScopeSchema2, vaultCreateBody2, vaultUpdateBody2, PERMISSIONS2, MAX_NAME_LENGTH22, MAX_HUBS_PER_GRANT2, MAX_HUB_TAGS_PER_GRANT2, MAX_GRANTS2, permissionEnum2, grantScopeSchema2, grantSchema2, createTokenBody2, tokenOrgIdParam2, tokenGrantScopeSchema2, tokenGrantSchema2, tokenMetadataSchema2, listTokensResponse2, createTokenResponse2, orgTokenSummarySchema2, listOrgTokensResponse2, invitePreviewQuery2, invitePreviewResponse2, discordTier2, discordBillingCycle2, discordMetadata2, discordOAuthStartResponse2, discordOAuthFinalizeBody2, discordOAuthFinalizeResponse2, discordDisconnectResponse2, jsonSchemaSchema2, hubUserIdentity2, stateValueEntry2, getHubUserContextResponse2, updateHubUserBody2, updateHubUserResponse2, unlockHubUserNameResponse2, stateResetParams2, stateResetResponse2, hubAlertsParam2, hubAlertSeverity2, hubAlert2, hubAlertsListResponse2, noticeSeveritySchema2, noticeStatusSchema2, NOTICE_SCOPE_REGEX2, noticeScopeSchema2, noticeLinkSchema2, createNoticeBody2, updateNoticeBody2, listNoticesQuery2, noticeIdParamSchema2, templateLocaleSchema2, TEMPLATE_SLUG_REGEX2, templateSlugSchema2, templateStatusSchema2, templateFileMapSchema2, TEMPLATE_INSTANCE_ID_KEYS, TEMPLATE_OPAQUE_BLOB_KEYS, TEMPLATE_AUTHOR_DATA_KEYS, templateTextSchema2, templateUsesEntrySchema2, templateUsesSchema2, templateYamlLocaleEntry2, templateYamlWayaiBlock2, templateTagsSchema2, templateYamlSchema2, templateHeroSchema2, templatePushLocaleSchema2, templatePushBody2, templateListQuery2, templateSlugParam2, templateDetailQuery2, ADMIN_SKILL_NAME_REGEX2, adminSkillNameParam2;
|
|
12446
12783
|
var init_contracts = __esm({
|
|
12447
12784
|
"../../packages/core/dist/contracts/index.js"() {
|
|
12448
12785
|
"use strict";
|
|
@@ -12503,6 +12840,30 @@ var init_contracts = __esm({
|
|
|
12503
12840
|
idParamSchema2 = external_exports.object({
|
|
12504
12841
|
id: uuidSchema2
|
|
12505
12842
|
});
|
|
12843
|
+
clientOptionalString2 = external_exports.string().nullish().transform((v) => v ?? void 0);
|
|
12844
|
+
clientOptionalBoolean2 = external_exports.boolean().nullish().transform((v) => v ?? void 0);
|
|
12845
|
+
clientOptionalNumber2 = external_exports.number().nullish().transform((v) => v ?? void 0);
|
|
12846
|
+
messageAttachment2 = external_exports.object({
|
|
12847
|
+
/**
|
|
12848
|
+
* Capped at the same 255 the storage layer already truncates names to, so nothing
|
|
12849
|
+
* legitimate is lost — every filesystem caps there, and `sanitizeFileName` sliced
|
|
12850
|
+
* longer names anyway.
|
|
12851
|
+
*
|
|
12852
|
+
* The bound is load-bearing, not hygiene: the RAW name is written to R2
|
|
12853
|
+
* `customMetadata.originalFileName`, and R2 rejects oversized metadata. An unbounded
|
|
12854
|
+
* name let a client make the R2 write throw a generic storage error — indistinguishable
|
|
12855
|
+
* from a real outage — which pages us via `logger.error` and, on the app channel, is
|
|
12856
|
+
* read as "we lost the file" and escalates the user to a human. Client input must not
|
|
12857
|
+
* be able to impersonate an infrastructure failure (gh #3365).
|
|
12858
|
+
*/
|
|
12859
|
+
file_name: external_exports.string().max(255),
|
|
12860
|
+
/** Base64. Bounded by the route's bodyLimit, not by this schema. */
|
|
12861
|
+
file_binary: external_exports.string(),
|
|
12862
|
+
file_size: clientOptionalNumber2,
|
|
12863
|
+
file_extension: clientOptionalString2
|
|
12864
|
+
});
|
|
12865
|
+
MAX_MESSAGE_BODY_BYTES2 = 10 * 1024 * 1024;
|
|
12866
|
+
MAX_ATTACHMENTS_PER_MESSAGE2 = 20;
|
|
12506
12867
|
primaryRegionSchema2 = external_exports.enum([
|
|
12507
12868
|
"wnam",
|
|
12508
12869
|
"enam",
|
|
@@ -12706,7 +13067,7 @@ var init_contracts = __esm({
|
|
|
12706
13067
|
eventName: external_exports.string().optional(),
|
|
12707
13068
|
additional_instructions: external_exports.string().optional(),
|
|
12708
13069
|
additional_context_schema: external_exports.record(external_exports.unknown()).refine(
|
|
12709
|
-
(s) =>
|
|
13070
|
+
(s) => withinJsonLength2(s, MAX_ADDITIONAL_CONTEXT_SCHEMA_BYTES2),
|
|
12710
13071
|
`additional_context_schema must be at most ${MAX_ADDITIONAL_CONTEXT_SCHEMA_BYTES2} bytes when JSON-serialized`
|
|
12711
13072
|
).optional(),
|
|
12712
13073
|
followups: external_exports.array(followupSchema2).max(MAX_FOLLOWUPS_PER_STATUS2, `followups must have at most ${MAX_FOLLOWUPS_PER_STATUS2} entries`).optional(),
|
|
@@ -12932,6 +13293,9 @@ var init_contracts = __esm({
|
|
|
12932
13293
|
replicatePreviewBody2 = external_exports.object({
|
|
12933
13294
|
preview_label: previewLabelField2
|
|
12934
13295
|
});
|
|
13296
|
+
updateChannelTestIdentitiesBody2 = external_exports.object({
|
|
13297
|
+
test_identities: external_exports.array(external_exports.string().max(320)).max(1e3)
|
|
13298
|
+
});
|
|
12935
13299
|
claimCodeChannelParam2 = external_exports.object({
|
|
12936
13300
|
id: uuidSchema2,
|
|
12937
13301
|
channelId: uuidSchema2
|
|
@@ -13582,12 +13946,15 @@ var init_contracts = __esm({
|
|
|
13582
13946
|
hubIdQuery2 = external_exports.object({
|
|
13583
13947
|
hub_id: external_exports.string().uuid()
|
|
13584
13948
|
});
|
|
13949
|
+
EVAL_INPUT_ROLES2 = ["user", "system"];
|
|
13950
|
+
EVAL_INPUT_ROLE_LIST2 = EVAL_INPUT_ROLES2.map((r) => `"${r}"`).join(" or ");
|
|
13951
|
+
ROLE_ECHO_MAX2 = 40;
|
|
13585
13952
|
createEvalBody2 = external_exports.object({
|
|
13586
13953
|
eval: external_exports.record(external_exports.unknown())
|
|
13587
|
-
});
|
|
13954
|
+
}).superRefine(refineEvalMessageTextRole2);
|
|
13588
13955
|
updateEvalBody2 = external_exports.object({
|
|
13589
13956
|
eval: external_exports.record(external_exports.unknown())
|
|
13590
|
-
});
|
|
13957
|
+
}).superRefine(refineEvalMessageTextRole2);
|
|
13591
13958
|
getEvalsQuery2 = external_exports.object({
|
|
13592
13959
|
hub_id: external_exports.string().uuid(),
|
|
13593
13960
|
agent_id: external_exports.string().uuid().optional(),
|
|
@@ -13759,6 +14126,15 @@ var init_contracts = __esm({
|
|
|
13759
14126
|
hub_user_id: external_exports.string().optional(),
|
|
13760
14127
|
search_filter: external_exports.string().optional(),
|
|
13761
14128
|
hub_id: external_exports.string().uuid().optional(),
|
|
14129
|
+
// NON-authorizing single-hub narrow. Unlike `hub_id` (which runs the
|
|
14130
|
+
// grant-gated `loadHub('hub:read')` and so throws for grant-less end users /
|
|
14131
|
+
// team members), `scope_hub_id` INTERSECTS the caller's already-resolved hub
|
|
14132
|
+
// roster server-side. Intersecting the caller's own roster IS the
|
|
14133
|
+
// authorization — a hub the caller isn't in narrows to empty and leaks
|
|
14134
|
+
// nothing. Continuous history sends it to take the single-hub ended-index
|
|
14135
|
+
// path (one HubDO read, accurate uncapped total) instead of the all-hub
|
|
14136
|
+
// fan-out it would otherwise discard client-side (gh #3319).
|
|
14137
|
+
scope_hub_id: external_exports.string().uuid().optional(),
|
|
13762
14138
|
conversation_id: external_exports.string().uuid().optional(),
|
|
13763
14139
|
// 'ended' = recently-closed, served warm from the HubDO index (≤ retention
|
|
13764
14140
|
// window). 'archived' = the full closed-conversation history from ClickHouse.
|
|
@@ -13799,17 +14175,8 @@ var init_contracts = __esm({
|
|
|
13799
14175
|
});
|
|
13800
14176
|
}
|
|
13801
14177
|
});
|
|
13802
|
-
clientOptionalString2 = external_exports.string().nullish().transform((v) => v ?? void 0);
|
|
13803
|
-
clientOptionalBoolean2 = external_exports.boolean().nullish().transform((v) => v ?? void 0);
|
|
13804
14178
|
appMessageSenderType2 = external_exports.enum(["user", "team"]);
|
|
13805
14179
|
appMessageReceiverType2 = external_exports.enum(["user", "team", "agent", "assistant"]).transform((v) => v === "assistant" ? "agent" : v);
|
|
13806
|
-
appMessageAttachment2 = external_exports.object({
|
|
13807
|
-
file_name: external_exports.string(),
|
|
13808
|
-
file_binary: external_exports.string(),
|
|
13809
|
-
file_size: external_exports.number().nullish().transform((v) => v ?? void 0),
|
|
13810
|
-
file_extension: clientOptionalString2
|
|
13811
|
-
});
|
|
13812
|
-
MAX_ATTACHMENTS_PER_MESSAGE2 = 20;
|
|
13813
14180
|
appMessageBody2 = external_exports.object({
|
|
13814
14181
|
// Message content — three historical aliases. All optional: an attachment-only
|
|
13815
14182
|
// or voice-only message carries no text.
|
|
@@ -13838,7 +14205,7 @@ var init_contracts = __esm({
|
|
|
13838
14205
|
// Pre-generated by the client so the optimistic bubble and the stored row share
|
|
13839
14206
|
// a key (transcription live-updates land on the same row instead of duplicating).
|
|
13840
14207
|
message_id: clientOptionalString2,
|
|
13841
|
-
attachments: external_exports.array(
|
|
14208
|
+
attachments: external_exports.array(messageAttachment2).max(MAX_ATTACHMENTS_PER_MESSAGE2).nullish().transform((v) => v ?? void 0),
|
|
13842
14209
|
// Base64-encoded audio for STT. Size-capped in the route (the cap is a byte
|
|
13843
14210
|
// budget tied to the /channels/* bodyLimit, not a shape rule).
|
|
13844
14211
|
audio_file: clientOptionalString2
|
|
@@ -13965,7 +14332,7 @@ var init_contracts = __esm({
|
|
|
13965
14332
|
hub_type: external_exports.enum(["chat", "task"]).default("chat"),
|
|
13966
14333
|
user_id: external_exports.string().optional()
|
|
13967
14334
|
});
|
|
13968
|
-
additionalContextPayloadSchema2 = external_exports.record(external_exports.unknown()).refine((r) =>
|
|
14335
|
+
additionalContextPayloadSchema2 = external_exports.record(external_exports.unknown()).refine((r) => withinJsonLength2(r, 16384), {
|
|
13969
14336
|
message: "additional_context payload must be at most 16384 bytes when JSON-serialized"
|
|
13970
14337
|
});
|
|
13971
14338
|
kanbanUpdateBody2 = external_exports.object({
|
|
@@ -14009,11 +14376,27 @@ var init_contracts = __esm({
|
|
|
14009
14376
|
]);
|
|
14010
14377
|
sendMessageBody2 = external_exports.object({
|
|
14011
14378
|
hub_id: external_exports.string().uuid(),
|
|
14012
|
-
|
|
14379
|
+
/**
|
|
14380
|
+
* Optional ONLY when `attachments` carries the payload — see the refinement below.
|
|
14381
|
+
* An attachment-only message (a photo with no caption) is the ordinary WhatsApp
|
|
14382
|
+
* gesture, so the endpoint that exists to rehearse inbound flows has to express it.
|
|
14383
|
+
* Mirrors `appMessageBody`, where content is optional for the same reason.
|
|
14384
|
+
*/
|
|
14385
|
+
message: external_exports.string().min(1).max(5e4).optional(),
|
|
14013
14386
|
/** For chat hubs: optional — automatically continues the user's active conversation (or creates one).
|
|
14014
14387
|
* For task hubs: required to continue an existing conversation. Omit to start a new task conversation. */
|
|
14015
|
-
conversation_id: external_exports.string().uuid().optional()
|
|
14016
|
-
|
|
14388
|
+
conversation_id: external_exports.string().uuid().optional(),
|
|
14389
|
+
/**
|
|
14390
|
+
* Base64 attachments, delivered over the hub's `app` channel exactly as a real
|
|
14391
|
+
* channel delivers them. Total bytes are bounded by the route's bodyLimit —
|
|
14392
|
+
* `/api/*` carries no global one (only `/webhooks/*` and `/channels/*` do), so the
|
|
14393
|
+
* route declares its own rather than inheriting an unbounded upload path.
|
|
14394
|
+
*/
|
|
14395
|
+
attachments: external_exports.array(messageAttachment2).max(MAX_ATTACHMENTS_PER_MESSAGE2).optional()
|
|
14396
|
+
}).refine(
|
|
14397
|
+
(b) => (b.message?.length ?? 0) > 0 || (b.attachments?.length ?? 0) > 0,
|
|
14398
|
+
{ message: "message or attachments required" }
|
|
14399
|
+
);
|
|
14017
14400
|
listConversationsQuery2 = external_exports.object({
|
|
14018
14401
|
hub_id: external_exports.string().uuid(),
|
|
14019
14402
|
status: external_exports.enum(["agent", "team", "ended"]).optional(),
|
|
@@ -14225,6 +14608,7 @@ var init_contracts = __esm({
|
|
|
14225
14608
|
refineHubAsCodeCustomTools2(config, ctx);
|
|
14226
14609
|
refineHubAsCodeKanbanStatuses2(config, ctx);
|
|
14227
14610
|
refineHubAsCodeLanes2(config, ctx);
|
|
14611
|
+
refineHubAsCodeEvals2(config, ctx);
|
|
14228
14612
|
});
|
|
14229
14613
|
ciPullHubIdParam2 = external_exports.object({
|
|
14230
14614
|
hub_id: ciUuidSchema2
|
|
@@ -15437,7 +15821,7 @@ async function useCommand(args2) {
|
|
|
15437
15821
|
process.exit(1);
|
|
15438
15822
|
}
|
|
15439
15823
|
let hubId;
|
|
15440
|
-
if (
|
|
15824
|
+
if (UUID_RE2.test(target)) {
|
|
15441
15825
|
hubId = target;
|
|
15442
15826
|
} else {
|
|
15443
15827
|
const workspace = detectWorkspace();
|
|
@@ -15617,37 +16001,109 @@ var send_message_exports = {};
|
|
|
15617
16001
|
__export(send_message_exports, {
|
|
15618
16002
|
sendMessageCommand: () => sendMessageCommand
|
|
15619
16003
|
});
|
|
16004
|
+
import * as fs17 from "fs";
|
|
16005
|
+
import * as path22 from "path";
|
|
16006
|
+
function statAttachment(filePath) {
|
|
16007
|
+
let stat;
|
|
16008
|
+
try {
|
|
16009
|
+
stat = fs17.statSync(filePath);
|
|
16010
|
+
} catch {
|
|
16011
|
+
console.error(`Error: file not found: ${filePath}`);
|
|
16012
|
+
process.exit(1);
|
|
16013
|
+
}
|
|
16014
|
+
if (stat.isDirectory()) {
|
|
16015
|
+
console.error(`Error: not a file: ${filePath}`);
|
|
16016
|
+
process.exit(1);
|
|
16017
|
+
}
|
|
16018
|
+
return { filePath, size: stat.size };
|
|
16019
|
+
}
|
|
16020
|
+
function readAttachment(filePath, size) {
|
|
16021
|
+
const fileName = path22.basename(filePath);
|
|
16022
|
+
const ext = path22.extname(fileName).replace(/^\./, "");
|
|
16023
|
+
return {
|
|
16024
|
+
file_name: fileName,
|
|
16025
|
+
file_binary: fs17.readFileSync(filePath).toString("base64"),
|
|
16026
|
+
file_size: size,
|
|
16027
|
+
...ext && { file_extension: ext }
|
|
16028
|
+
};
|
|
16029
|
+
}
|
|
16030
|
+
function usage() {
|
|
16031
|
+
console.error('Usage: wayai send-message [options] ["message text"]');
|
|
16032
|
+
console.error("");
|
|
16033
|
+
console.error("Options:");
|
|
16034
|
+
console.error(" -c, --conversation <id> Continue an existing conversation");
|
|
16035
|
+
console.error(" -f, --file <path> Attach a file (repeatable)");
|
|
16036
|
+
console.error("");
|
|
16037
|
+
console.error("The message text is optional when at least one --file is attached.");
|
|
16038
|
+
console.error("The hub type (chat/task) is determined automatically from the hub.");
|
|
16039
|
+
console.error("Chat hubs auto-continue the active conversation (or create one).");
|
|
16040
|
+
console.error("Task hubs create a new conversation unless -c is provided.");
|
|
16041
|
+
process.exit(1);
|
|
16042
|
+
}
|
|
15620
16043
|
async function sendMessageCommand(args2) {
|
|
15621
16044
|
const hubId = resolveActiveHubId(args2);
|
|
15622
16045
|
const { config, accessToken } = await requireAuth();
|
|
15623
16046
|
requireRepoConfig();
|
|
15624
16047
|
let conversationId;
|
|
15625
16048
|
let message;
|
|
16049
|
+
const filePaths = [];
|
|
15626
16050
|
for (let i = 0; i < args2.length; i++) {
|
|
15627
16051
|
const arg = args2[i];
|
|
15628
16052
|
if (arg === "-c" || arg === "--conversation") {
|
|
15629
16053
|
conversationId = args2[++i];
|
|
16054
|
+
} else if (arg === "-f" || arg === "--file") {
|
|
16055
|
+
const filePath = args2[++i];
|
|
16056
|
+
if (!filePath) {
|
|
16057
|
+
console.error("Error: --file requires a path");
|
|
16058
|
+
process.exit(1);
|
|
16059
|
+
}
|
|
16060
|
+
filePaths.push(filePath);
|
|
15630
16061
|
} else if (!arg.startsWith("-")) {
|
|
15631
16062
|
message = arg;
|
|
15632
16063
|
}
|
|
15633
16064
|
}
|
|
15634
|
-
if (!message)
|
|
15635
|
-
|
|
15636
|
-
console.error(
|
|
15637
|
-
|
|
15638
|
-
|
|
15639
|
-
|
|
15640
|
-
|
|
15641
|
-
|
|
15642
|
-
|
|
16065
|
+
if (!message && filePaths.length === 0) usage();
|
|
16066
|
+
if (filePaths.length > MAX_ATTACHMENTS_PER_MESSAGE2) {
|
|
16067
|
+
console.error(`Error: at most ${MAX_ATTACHMENTS_PER_MESSAGE2} files per message (got ${filePaths.length}).`);
|
|
16068
|
+
process.exit(1);
|
|
16069
|
+
}
|
|
16070
|
+
const stats = filePaths.map(statAttachment);
|
|
16071
|
+
const filesTotal = stats.reduce((sum, s) => sum + base64Length(s.size), 0);
|
|
16072
|
+
const fileDetail = () => stats.map((s) => `${path22.basename(s.filePath)} ${asMb(s.size)} MB`).join(", ");
|
|
16073
|
+
if (filesTotal > MAX_MESSAGE_BODY_BYTES2) {
|
|
16074
|
+
console.error(
|
|
16075
|
+
`Error: ${fileDetail()} encode to ~${asMb(filesTotal)} MB, over the ${asMb(MAX_MESSAGE_BODY_BYTES2)} MB per-request limit.`
|
|
16076
|
+
);
|
|
16077
|
+
console.error("Base64 inflates a file by about a third, so ~7 MB of files is the practical ceiling.");
|
|
16078
|
+
process.exit(1);
|
|
16079
|
+
}
|
|
16080
|
+
const attachments = stats.map((s) => readAttachment(s.filePath, s.size));
|
|
16081
|
+
const bodyBytes = Buffer.byteLength(
|
|
16082
|
+
JSON.stringify({
|
|
16083
|
+
hub_id: hubId,
|
|
16084
|
+
...message && { message },
|
|
16085
|
+
...conversationId && { conversation_id: conversationId },
|
|
16086
|
+
...attachments.length > 0 && { attachments }
|
|
16087
|
+
}),
|
|
16088
|
+
"utf8"
|
|
16089
|
+
);
|
|
16090
|
+
if (bodyBytes > MAX_MESSAGE_BODY_BYTES2) {
|
|
16091
|
+
console.error(
|
|
16092
|
+
`Error: the request is ~${asMb(bodyBytes)} MB, over the ${asMb(MAX_MESSAGE_BODY_BYTES2)} MB per-request limit.`
|
|
16093
|
+
);
|
|
16094
|
+
if (stats.length > 0) console.error(`Attachments: ${fileDetail()} (base64 adds about a third).`);
|
|
15643
16095
|
process.exit(1);
|
|
15644
16096
|
}
|
|
15645
16097
|
const client = new ApiClient({ apiUrl: config.api_url, accessToken });
|
|
15646
16098
|
const result = await client.sendMessage(hubId, message, {
|
|
15647
|
-
conversationId
|
|
16099
|
+
conversationId,
|
|
16100
|
+
...attachments.length > 0 && { attachments }
|
|
15648
16101
|
});
|
|
15649
16102
|
console.log(`Conversation: ${result.conversation_id}`);
|
|
15650
16103
|
console.log(`Status: ${result.status}`);
|
|
16104
|
+
if (attachments.length > 0 && result.status !== "error") {
|
|
16105
|
+
console.log(`Attached: ${attachments.map((a) => a.file_name).join(", ")}`);
|
|
16106
|
+
}
|
|
15651
16107
|
if (result.status_reason) {
|
|
15652
16108
|
console.log(`Reason: ${result.status_reason}`);
|
|
15653
16109
|
}
|
|
@@ -15664,13 +16120,17 @@ async function sendMessageCommand(args2) {
|
|
|
15664
16120
|
console.log("(Agent processing failed \u2014 user message was stored)");
|
|
15665
16121
|
}
|
|
15666
16122
|
}
|
|
16123
|
+
var asMb, base64Length;
|
|
15667
16124
|
var init_send_message = __esm({
|
|
15668
16125
|
"src/commands/send-message.ts"() {
|
|
15669
16126
|
"use strict";
|
|
16127
|
+
init_contracts();
|
|
15670
16128
|
init_auth();
|
|
15671
16129
|
init_repo_config();
|
|
15672
16130
|
init_workspace();
|
|
15673
16131
|
init_api_client();
|
|
16132
|
+
asMb = (bytes) => (bytes / 1024 / 1024).toFixed(1);
|
|
16133
|
+
base64Length = (bytes) => Math.ceil(bytes / 3) * 4;
|
|
15674
16134
|
}
|
|
15675
16135
|
});
|
|
15676
16136
|
|
|
@@ -17069,8 +17529,8 @@ var eval_capture_exports = {};
|
|
|
17069
17529
|
__export(eval_capture_exports, {
|
|
17070
17530
|
evalCaptureCommand: () => evalCaptureCommand
|
|
17071
17531
|
});
|
|
17072
|
-
import * as
|
|
17073
|
-
import * as
|
|
17532
|
+
import * as fs18 from "fs";
|
|
17533
|
+
import * as path23 from "path";
|
|
17074
17534
|
import * as yaml7 from "js-yaml";
|
|
17075
17535
|
function isValidSetName(name) {
|
|
17076
17536
|
if (name.length === 0 || name === "." || name === "..") return false;
|
|
@@ -17083,7 +17543,7 @@ function parseArgs13(args2) {
|
|
|
17083
17543
|
process.exit(1);
|
|
17084
17544
|
}
|
|
17085
17545
|
const conversationId = args2[0];
|
|
17086
|
-
if (!
|
|
17546
|
+
if (!UUID_RE2.test(conversationId)) {
|
|
17087
17547
|
console.error(`Invalid conversation ID "${conversationId}". Expected a UUID.`);
|
|
17088
17548
|
process.exit(1);
|
|
17089
17549
|
}
|
|
@@ -17136,15 +17596,15 @@ async function evalCaptureCommand(args2) {
|
|
|
17136
17596
|
const setFolderName = targetSetName;
|
|
17137
17597
|
const scenarioName = parsed.evalName ?? `Capture ${parsed.conversationId.slice(0, 8)}`;
|
|
17138
17598
|
const slug = slugify(scenarioName);
|
|
17139
|
-
const evalsDir =
|
|
17140
|
-
const targetDir =
|
|
17141
|
-
const targetPath =
|
|
17142
|
-
if (!targetPath.startsWith(evalsDir +
|
|
17143
|
-
console.error(`Resolved path "${
|
|
17599
|
+
const evalsDir = path23.join(hubFolder, "evals");
|
|
17600
|
+
const targetDir = path23.join(evalsDir, setFolderName);
|
|
17601
|
+
const targetPath = path23.join(targetDir, `${slug}.yaml`);
|
|
17602
|
+
if (!targetPath.startsWith(evalsDir + path23.sep)) {
|
|
17603
|
+
console.error(`Resolved path "${path23.relative(hubFolder, targetPath)}" escapes evals/. Aborting.`);
|
|
17144
17604
|
process.exit(1);
|
|
17145
17605
|
}
|
|
17146
|
-
if (
|
|
17147
|
-
console.error(`File already exists: ${
|
|
17606
|
+
if (fs18.existsSync(targetPath)) {
|
|
17607
|
+
console.error(`File already exists: ${path23.relative(hubFolder, targetPath)}. Use --name to choose a different name.`);
|
|
17148
17608
|
process.exit(1);
|
|
17149
17609
|
}
|
|
17150
17610
|
console.log("Resolving scenario set...");
|
|
@@ -17176,9 +17636,9 @@ async function evalCaptureCommand(args2) {
|
|
|
17176
17636
|
...captured.evaluator_instructions ? { evaluator_instructions: captured.evaluator_instructions } : {}
|
|
17177
17637
|
};
|
|
17178
17638
|
const yamlObj = buildEvalYamlObject(evalEntry, slug);
|
|
17179
|
-
|
|
17180
|
-
|
|
17181
|
-
const relPath =
|
|
17639
|
+
fs18.mkdirSync(targetDir, { recursive: true });
|
|
17640
|
+
fs18.writeFileSync(targetPath, yaml7.dump(yamlObj, YAML_DUMP_OPTIONS), "utf-8");
|
|
17641
|
+
const relPath = path23.relative(process.cwd(), targetPath);
|
|
17182
17642
|
console.log(`
|
|
17183
17643
|
Wrote ${relPath}`);
|
|
17184
17644
|
console.log("Run `wayai pull` to refresh the agent display name, then commit. The scenario is already on the platform.");
|
|
@@ -17206,7 +17666,7 @@ function parseArgs14(args2) {
|
|
|
17206
17666
|
process.exit(1);
|
|
17207
17667
|
}
|
|
17208
17668
|
const conversationId = args2[0];
|
|
17209
|
-
if (!
|
|
17669
|
+
if (!UUID_RE2.test(conversationId)) {
|
|
17210
17670
|
console.error(`Invalid conversation ID "${conversationId}". Expected a UUID.`);
|
|
17211
17671
|
process.exit(1);
|
|
17212
17672
|
}
|
|
@@ -17288,7 +17748,7 @@ async function evalSessionDeleteCommand(args2) {
|
|
|
17288
17748
|
console.error(" wayai eval session delete --all");
|
|
17289
17749
|
process.exit(1);
|
|
17290
17750
|
}
|
|
17291
|
-
if (sessionId && !
|
|
17751
|
+
if (sessionId && !UUID_RE2.test(sessionId)) {
|
|
17292
17752
|
console.error(`Invalid session id: ${sessionId}`);
|
|
17293
17753
|
process.exit(1);
|
|
17294
17754
|
}
|
|
@@ -18326,7 +18786,7 @@ function parseArgs17(args2) {
|
|
|
18326
18786
|
}
|
|
18327
18787
|
return { connection, orgCredential, field, stdin };
|
|
18328
18788
|
}
|
|
18329
|
-
function
|
|
18789
|
+
function usage2(msg) {
|
|
18330
18790
|
if (msg) console.error(`${msg}
|
|
18331
18791
|
`);
|
|
18332
18792
|
console.error("Usage: wayai set-connection-credential --hub <id|name> --connection <name|id> ( --org-credential <name> | --field <field> --stdin )");
|
|
@@ -18337,17 +18797,17 @@ function usage(msg) {
|
|
|
18337
18797
|
async function setConnectionCredentialCommand(args2) {
|
|
18338
18798
|
const hubId = resolveActiveHubId(args2);
|
|
18339
18799
|
const parsed = parseArgs17(args2);
|
|
18340
|
-
if (!parsed.connection)
|
|
18800
|
+
if (!parsed.connection) usage2("Missing required flag: --connection <name|id>");
|
|
18341
18801
|
const orgMode = !!parsed.orgCredential;
|
|
18342
18802
|
const directMode = !!parsed.field;
|
|
18343
18803
|
if (orgMode === directMode) {
|
|
18344
|
-
|
|
18804
|
+
usage2("Provide exactly one of --org-credential or --field.");
|
|
18345
18805
|
}
|
|
18346
18806
|
if (directMode && !VALID_FIELDS.includes(parsed.field)) {
|
|
18347
|
-
|
|
18807
|
+
usage2(`Invalid --field "${parsed.field}". Valid fields: ${VALID_FIELDS.join(", ")}`);
|
|
18348
18808
|
}
|
|
18349
18809
|
if (directMode && !parsed.stdin) {
|
|
18350
|
-
|
|
18810
|
+
usage2("--field requires --stdin (the secret is read from stdin, never an argument).");
|
|
18351
18811
|
}
|
|
18352
18812
|
const { organization_id: organizationId } = requireRepoConfig();
|
|
18353
18813
|
const { config, accessToken } = await requireAuth();
|
|
@@ -18359,27 +18819,27 @@ async function setConnectionCredentialCommand(args2) {
|
|
|
18359
18819
|
else if (hubs.some((h) => h.production_hub_id === hubId)) environment = "production";
|
|
18360
18820
|
}
|
|
18361
18821
|
if (!environment) {
|
|
18362
|
-
|
|
18822
|
+
usage2(`Could not resolve hub "${hubId}". Pull it first (\`wayai pull --hub ${hubId}\`) or check the id.`);
|
|
18363
18823
|
}
|
|
18364
18824
|
const isProduction = environment === "production";
|
|
18365
18825
|
const { connections } = await client.listConnections(hubId);
|
|
18366
18826
|
const conn = connections.find(
|
|
18367
18827
|
(c) => c.connection_id === parsed.connection || c.connection_display_name === parsed.connection
|
|
18368
18828
|
);
|
|
18369
|
-
if (!conn || !conn.connection_id)
|
|
18829
|
+
if (!conn || !conn.connection_id) usage2(`Connection "${parsed.connection}" not found on hub ${hubId}.`);
|
|
18370
18830
|
const connectionId = conn.connection_id;
|
|
18371
18831
|
const body = { hub_id: hubId };
|
|
18372
18832
|
if (orgMode) {
|
|
18373
18833
|
const { data: creds } = await client.listOrgCredentials(organizationId);
|
|
18374
18834
|
const cred = creds.find((c) => c.credential_display_name === parsed.orgCredential);
|
|
18375
|
-
if (!cred)
|
|
18835
|
+
if (!cred) usage2(`Organization credential "${parsed.orgCredential}" not found.`);
|
|
18376
18836
|
body.organization_credential_id = cred.organization_credential_id;
|
|
18377
18837
|
} else {
|
|
18378
18838
|
if (process.stdin.isTTY) {
|
|
18379
|
-
|
|
18839
|
+
usage2('--field requires the secret on stdin. Example: echo "$SECRET" | wayai set-connection-credential ... --field api_key --stdin');
|
|
18380
18840
|
}
|
|
18381
18841
|
const secret = (await readStdin())?.trim();
|
|
18382
|
-
if (!secret)
|
|
18842
|
+
if (!secret) usage2("No secret received from stdin.");
|
|
18383
18843
|
body[parsed.field] = secret;
|
|
18384
18844
|
}
|
|
18385
18845
|
const target = isProduction ? "production" : "preview";
|
|
@@ -18405,23 +18865,23 @@ var init_set_connection_credential = __esm({
|
|
|
18405
18865
|
});
|
|
18406
18866
|
|
|
18407
18867
|
// src/lib/org-workspace.ts
|
|
18408
|
-
import * as
|
|
18409
|
-
import * as
|
|
18868
|
+
import * as fs19 from "fs";
|
|
18869
|
+
import * as path24 from "path";
|
|
18410
18870
|
import * as yaml8 from "js-yaml";
|
|
18411
18871
|
function getOrgDir(gitRoot) {
|
|
18412
18872
|
return resolveLayout(gitRoot).orgDir;
|
|
18413
18873
|
}
|
|
18414
18874
|
function orgManifestExists(orgDir) {
|
|
18415
|
-
return
|
|
18875
|
+
return fs19.existsSync(path24.join(orgDir, ORG_MANIFEST_NAME));
|
|
18416
18876
|
}
|
|
18417
18877
|
function parseOrgResources(orgDir) {
|
|
18418
|
-
const manifestPath =
|
|
18878
|
+
const manifestPath = path24.join(orgDir, ORG_MANIFEST_NAME);
|
|
18419
18879
|
let manifest = {};
|
|
18420
|
-
if (
|
|
18421
|
-
manifest = yaml8.load(
|
|
18880
|
+
if (fs19.existsSync(manifestPath)) {
|
|
18881
|
+
manifest = yaml8.load(fs19.readFileSync(manifestPath, "utf-8")) ?? {};
|
|
18422
18882
|
}
|
|
18423
18883
|
const rawResources = Array.isArray(manifest.resources) ? manifest.resources : [];
|
|
18424
|
-
const resourcesDir =
|
|
18884
|
+
const resourcesDir = path24.join(orgDir, "resources");
|
|
18425
18885
|
const resources = rawResources.map((res) => {
|
|
18426
18886
|
const resource = { name: res.name };
|
|
18427
18887
|
if (res.id) resource.id = res.id;
|
|
@@ -18433,8 +18893,8 @@ function parseOrgResources(orgDir) {
|
|
|
18433
18893
|
if (res.environment) resource.environment = res.environment;
|
|
18434
18894
|
if (Array.isArray(res.tags)) resource.tags = res.tags;
|
|
18435
18895
|
if (Array.isArray(res.folders)) resource.folders = res.folders;
|
|
18436
|
-
const resDir =
|
|
18437
|
-
if (
|
|
18896
|
+
const resDir = path24.join(resourcesDir, slugify(resource.name));
|
|
18897
|
+
if (fs19.existsSync(resDir)) {
|
|
18438
18898
|
const files = scanResourceFiles(resDir, "");
|
|
18439
18899
|
if (files.length > 0) resource.files = files;
|
|
18440
18900
|
}
|
|
@@ -18443,28 +18903,28 @@ function parseOrgResources(orgDir) {
|
|
|
18443
18903
|
return { version: 1, resources };
|
|
18444
18904
|
}
|
|
18445
18905
|
function writeOrgResources(orgDir, payload) {
|
|
18446
|
-
|
|
18906
|
+
fs19.mkdirSync(orgDir, { recursive: true });
|
|
18447
18907
|
const resources = payload.resources ?? [];
|
|
18448
18908
|
const manifestResources = resources.map((r) => {
|
|
18449
18909
|
const { files: _files, ...rest } = r;
|
|
18450
18910
|
return rest;
|
|
18451
18911
|
});
|
|
18452
|
-
|
|
18453
|
-
|
|
18912
|
+
fs19.writeFileSync(
|
|
18913
|
+
path24.join(orgDir, ORG_MANIFEST_NAME),
|
|
18454
18914
|
yaml8.dump({ version: 1, resources: manifestResources }, YAML_DUMP_OPTIONS),
|
|
18455
18915
|
"utf-8"
|
|
18456
18916
|
);
|
|
18457
|
-
const resourcesDir =
|
|
18917
|
+
const resourcesDir = path24.join(orgDir, "resources");
|
|
18458
18918
|
const currentSlugs = /* @__PURE__ */ new Set();
|
|
18459
18919
|
for (const resource of resources) {
|
|
18460
18920
|
const resSlug = slugify(resource.name);
|
|
18461
18921
|
currentSlugs.add(resSlug);
|
|
18462
|
-
writeResourceFileTree(
|
|
18922
|
+
writeResourceFileTree(path24.join(resourcesDir, resSlug), resource.files || []);
|
|
18463
18923
|
}
|
|
18464
|
-
if (
|
|
18465
|
-
for (const entry of
|
|
18924
|
+
if (fs19.existsSync(resourcesDir)) {
|
|
18925
|
+
for (const entry of fs19.readdirSync(resourcesDir, { withFileTypes: true })) {
|
|
18466
18926
|
if (entry.isDirectory() && !currentSlugs.has(entry.name)) {
|
|
18467
|
-
|
|
18927
|
+
fs19.rmSync(path24.join(resourcesDir, entry.name), { recursive: true, force: true });
|
|
18468
18928
|
}
|
|
18469
18929
|
}
|
|
18470
18930
|
}
|
|
@@ -18473,7 +18933,7 @@ async function downloadOrgBinaryFiles(orgDir, payload) {
|
|
|
18473
18933
|
let count = 0;
|
|
18474
18934
|
for (const resource of payload.resources ?? []) {
|
|
18475
18935
|
if (!resource.files) continue;
|
|
18476
|
-
const resDir =
|
|
18936
|
+
const resDir = path24.join(orgDir, "resources", slugify(resource.name));
|
|
18477
18937
|
count += await downloadBinaryFiles(resDir, resource.files);
|
|
18478
18938
|
}
|
|
18479
18939
|
if (count > 0) console.log(`Downloaded ${count} binary resource file(s).`);
|
|
@@ -18729,20 +19189,20 @@ var init_list = __esm({
|
|
|
18729
19189
|
});
|
|
18730
19190
|
|
|
18731
19191
|
// src/lib/template-files.ts
|
|
18732
|
-
import * as
|
|
18733
|
-
import * as
|
|
19192
|
+
import * as fs20 from "fs";
|
|
19193
|
+
import * as path25 from "path";
|
|
18734
19194
|
function readDirToFileMap(rootDir) {
|
|
18735
19195
|
const out = {};
|
|
18736
19196
|
function walk(dir, prefix) {
|
|
18737
|
-
const entries =
|
|
19197
|
+
const entries = fs20.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
18738
19198
|
for (const entry of entries) {
|
|
18739
|
-
const abs =
|
|
19199
|
+
const abs = path25.join(dir, entry.name);
|
|
18740
19200
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
18741
19201
|
if (entry.isDirectory()) walk(abs, rel);
|
|
18742
|
-
else if (entry.isFile()) out[rel] =
|
|
19202
|
+
else if (entry.isFile()) out[rel] = fs20.readFileSync(abs, "utf-8");
|
|
18743
19203
|
}
|
|
18744
19204
|
}
|
|
18745
|
-
if (
|
|
19205
|
+
if (fs20.existsSync(rootDir)) walk(rootDir, "");
|
|
18746
19206
|
return out;
|
|
18747
19207
|
}
|
|
18748
19208
|
function detectCollisions(targetDir, files) {
|
|
@@ -18751,7 +19211,7 @@ function detectCollisions(targetDir, files) {
|
|
|
18751
19211
|
if (!isSafeTemplatePath2(rel)) {
|
|
18752
19212
|
throw new Error(`Refusing to inspect unsafe template path: ${rel}`);
|
|
18753
19213
|
}
|
|
18754
|
-
if (
|
|
19214
|
+
if (fs20.existsSync(path25.join(targetDir, rel))) collisions.push(rel);
|
|
18755
19215
|
}
|
|
18756
19216
|
return collisions.sort((a, b) => a.localeCompare(b));
|
|
18757
19217
|
}
|
|
@@ -18761,9 +19221,9 @@ function writeFileMap(targetDir, files) {
|
|
|
18761
19221
|
if (!isSafeTemplatePath2(rel)) {
|
|
18762
19222
|
throw new Error(`Refusing to write unsafe template path: ${rel}`);
|
|
18763
19223
|
}
|
|
18764
|
-
const abs =
|
|
18765
|
-
|
|
18766
|
-
|
|
19224
|
+
const abs = path25.join(targetDir, rel);
|
|
19225
|
+
fs20.mkdirSync(path25.dirname(abs), { recursive: true });
|
|
19226
|
+
fs20.writeFileSync(abs, body, "utf-8");
|
|
18767
19227
|
written.push(rel);
|
|
18768
19228
|
}
|
|
18769
19229
|
return written;
|
|
@@ -18771,20 +19231,20 @@ function writeFileMap(targetDir, files) {
|
|
|
18771
19231
|
function listDirRelFiles(dir) {
|
|
18772
19232
|
const out = [];
|
|
18773
19233
|
function walk(d, prefix) {
|
|
18774
|
-
for (const entry of
|
|
19234
|
+
for (const entry of fs20.readdirSync(d, { withFileTypes: true })) {
|
|
18775
19235
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
18776
|
-
if (entry.isDirectory()) walk(
|
|
19236
|
+
if (entry.isDirectory()) walk(path25.join(d, entry.name), rel);
|
|
18777
19237
|
else if (entry.isFile()) out.push(rel);
|
|
18778
19238
|
}
|
|
18779
19239
|
}
|
|
18780
|
-
if (
|
|
19240
|
+
if (fs20.existsSync(dir)) walk(dir, "");
|
|
18781
19241
|
return out;
|
|
18782
19242
|
}
|
|
18783
19243
|
function writeSliceSnapshot(targetDir, files) {
|
|
18784
19244
|
const keep = new Set(Object.keys(files));
|
|
18785
19245
|
const removed = listDirRelFiles(targetDir).filter((rel) => !keep.has(rel)).sort((a, b) => a.localeCompare(b));
|
|
18786
19246
|
const written = writeFileMap(targetDir, files).sort((a, b) => a.localeCompare(b));
|
|
18787
|
-
if (
|
|
19247
|
+
if (fs20.existsSync(targetDir)) cleanOrphanFiles(targetDir, "", keep);
|
|
18788
19248
|
return { written, removed };
|
|
18789
19249
|
}
|
|
18790
19250
|
var init_template_files = __esm({
|
|
@@ -18800,7 +19260,7 @@ var templates_exports = {};
|
|
|
18800
19260
|
__export(templates_exports, {
|
|
18801
19261
|
templateCommand: () => templateCommand
|
|
18802
19262
|
});
|
|
18803
|
-
import * as
|
|
19263
|
+
import * as path26 from "path";
|
|
18804
19264
|
async function templateCommand(args2) {
|
|
18805
19265
|
const [sub, ...rest] = args2;
|
|
18806
19266
|
switch (sub) {
|
|
@@ -18916,8 +19376,8 @@ async function runTemplatePull(rest) {
|
|
|
18916
19376
|
console.log(`Template "${slug}" has no WayAI slice${hint}`);
|
|
18917
19377
|
return;
|
|
18918
19378
|
}
|
|
18919
|
-
const targetDir =
|
|
18920
|
-
const relTarget =
|
|
19379
|
+
const targetDir = path26.join(resolveLayout(gitRoot).hubsDir, slug);
|
|
19380
|
+
const relTarget = path26.relative(gitRoot, targetDir);
|
|
18921
19381
|
const collisions = detectCollisions(targetDir, detail.files);
|
|
18922
19382
|
if (dryRun) {
|
|
18923
19383
|
const planned = Object.keys(detail.files).sort((a, b) => a.localeCompare(b));
|
|
@@ -19091,8 +19551,8 @@ var admin_exports = {};
|
|
|
19091
19551
|
__export(admin_exports, {
|
|
19092
19552
|
adminCommand: () => adminCommand
|
|
19093
19553
|
});
|
|
19094
|
-
import * as
|
|
19095
|
-
import * as
|
|
19554
|
+
import * as fs21 from "fs";
|
|
19555
|
+
import * as path27 from "path";
|
|
19096
19556
|
import * as yaml10 from "js-yaml";
|
|
19097
19557
|
async function adminCommand(args2) {
|
|
19098
19558
|
const [group, ...afterGroup] = args2;
|
|
@@ -19414,7 +19874,7 @@ async function runArchiveRead(positional, flagArgs) {
|
|
|
19414
19874
|
exitOnApiError(err);
|
|
19415
19875
|
throw err;
|
|
19416
19876
|
}
|
|
19417
|
-
|
|
19877
|
+
fs21.writeFileSync(outPath, zip);
|
|
19418
19878
|
console.log(`Wrote ${zip.byteLength} bytes to ${outPath}`);
|
|
19419
19879
|
return;
|
|
19420
19880
|
}
|
|
@@ -19546,15 +20006,15 @@ function loadTemplateManifest(slug) {
|
|
|
19546
20006
|
console.error("Not in a git repository. Run from the tutorials/ authoring repo.");
|
|
19547
20007
|
process.exit(1);
|
|
19548
20008
|
}
|
|
19549
|
-
const templateDir =
|
|
19550
|
-
const manifestPath =
|
|
19551
|
-
if (!
|
|
19552
|
-
console.error(`template.yaml not found at ${
|
|
20009
|
+
const templateDir = path27.join(resolveTemplatesDir(gitRoot), slug);
|
|
20010
|
+
const manifestPath = path27.join(templateDir, "template.yaml");
|
|
20011
|
+
if (!fs21.existsSync(manifestPath)) {
|
|
20012
|
+
console.error(`template.yaml not found at ${path27.relative(gitRoot, manifestPath)}`);
|
|
19553
20013
|
process.exit(1);
|
|
19554
20014
|
}
|
|
19555
20015
|
let manifest;
|
|
19556
20016
|
try {
|
|
19557
|
-
manifest = templateYamlSchema2.parse(yaml10.load(
|
|
20017
|
+
manifest = templateYamlSchema2.parse(yaml10.load(fs21.readFileSync(manifestPath, "utf-8")));
|
|
19558
20018
|
} catch (err) {
|
|
19559
20019
|
console.error(`Invalid template.yaml: ${err instanceof Error ? err.message : String(err)}`);
|
|
19560
20020
|
process.exit(1);
|
|
@@ -19584,20 +20044,20 @@ async function runTemplatePush(positional) {
|
|
|
19584
20044
|
const wayaiEntry = manifest.wayai.locales[locale];
|
|
19585
20045
|
let wayaiFiles;
|
|
19586
20046
|
if (wayaiEntry) {
|
|
19587
|
-
const sliceDir =
|
|
19588
|
-
if (!
|
|
20047
|
+
const sliceDir = path27.resolve(templateDir, wayaiEntry.source);
|
|
20048
|
+
if (!fs21.existsSync(sliceDir)) {
|
|
19589
20049
|
console.error(`wayai source not found for ${locale}: ${wayaiEntry.source} (resolved ${sliceDir})`);
|
|
19590
20050
|
process.exit(1);
|
|
19591
20051
|
}
|
|
19592
20052
|
if (!isInsideTemplateDir(sliceDir, templateDir)) {
|
|
19593
20053
|
console.warn(
|
|
19594
|
-
`Note: ${locale} source points at a live hub (${wayaiEntry.source}); it can go stale on a hub recreate. Run \`wayai admin template freeze ${slug} --locale ${locale} --from ${
|
|
20054
|
+
`Note: ${locale} source points at a live hub (${wayaiEntry.source}); it can go stale on a hub recreate. Run \`wayai admin template freeze ${slug} --locale ${locale} --from ${path27.basename(sliceDir)}\` to commit a stable frozen slice.`
|
|
19595
20055
|
);
|
|
19596
20056
|
}
|
|
19597
20057
|
wayaiFiles = readDirToFileMap(sliceDir);
|
|
19598
20058
|
}
|
|
19599
|
-
const readmePath =
|
|
19600
|
-
const readmeMarkdown =
|
|
20059
|
+
const readmePath = path27.join(templateDir, `README.${locale}.md`);
|
|
20060
|
+
const readmeMarkdown = fs21.existsSync(readmePath) ? fs21.readFileSync(readmePath, "utf-8") : "";
|
|
19601
20061
|
locales[locale] = {
|
|
19602
20062
|
readmeMarkdown,
|
|
19603
20063
|
...wayaiFiles && { wayaiFiles },
|
|
@@ -19608,9 +20068,9 @@ async function runTemplatePush(positional) {
|
|
|
19608
20068
|
}
|
|
19609
20069
|
let hero;
|
|
19610
20070
|
if (manifest.hero) {
|
|
19611
|
-
const heroPath =
|
|
19612
|
-
if (
|
|
19613
|
-
hero = { filename:
|
|
20071
|
+
const heroPath = path27.resolve(templateDir, manifest.hero);
|
|
20072
|
+
if (fs21.existsSync(heroPath)) {
|
|
20073
|
+
hero = { filename: path27.basename(heroPath), dataBase64: fs21.readFileSync(heroPath).toString("base64") };
|
|
19614
20074
|
} else {
|
|
19615
20075
|
console.error(`Warning: hero not found at ${manifest.hero}; skipping.`);
|
|
19616
20076
|
}
|
|
@@ -19636,7 +20096,7 @@ async function runTemplatePush(positional) {
|
|
|
19636
20096
|
}
|
|
19637
20097
|
}
|
|
19638
20098
|
function isInsideTemplateDir(dest, templateDir) {
|
|
19639
|
-
return dest === templateDir || dest.startsWith(templateDir +
|
|
20099
|
+
return dest === templateDir || dest.startsWith(templateDir + path27.sep);
|
|
19640
20100
|
}
|
|
19641
20101
|
async function runTemplateFreeze(positional, flagArgs) {
|
|
19642
20102
|
const slug = positional[0];
|
|
@@ -19697,7 +20157,7 @@ async function runTemplateFreeze(positional, flagArgs) {
|
|
|
19697
20157
|
process.exit(1);
|
|
19698
20158
|
}
|
|
19699
20159
|
const entry = manifest.wayai.locales[targetLocale];
|
|
19700
|
-
const dest =
|
|
20160
|
+
const dest = path27.resolve(templateDir, entry.source);
|
|
19701
20161
|
if (!isInsideTemplateDir(dest, templateDir) || dest === templateDir) {
|
|
19702
20162
|
console.error(
|
|
19703
20163
|
`source for "${targetLocale}" must be a committed path inside ${slug}/ (e.g. "./${targetLocale}/slice"), but resolved to:
|
|
@@ -19716,7 +20176,7 @@ Set it to a subdir of the template folder and re-run freeze.`
|
|
|
19716
20176
|
const hubs = scanWorkspaceHubs(hubsDir);
|
|
19717
20177
|
if (hubs.length) {
|
|
19718
20178
|
console.error("Available hubs:");
|
|
19719
|
-
for (const h of hubs) console.error(` ${
|
|
20179
|
+
for (const h of hubs) console.error(` ${path27.basename(h.hubFolder)} (${h.hubId})`);
|
|
19720
20180
|
}
|
|
19721
20181
|
console.error(`
|
|
19722
20182
|
Pass --from <folder|uuid>${selector ? "." : " or run `wayai use <hub>` first."}`);
|
|
@@ -19724,12 +20184,12 @@ Pass --from <folder|uuid>${selector ? "." : " or run `wayai use <hub>` first."}`
|
|
|
19724
20184
|
}
|
|
19725
20185
|
const liveFiles = readDirToFileMap(hubFolder);
|
|
19726
20186
|
if (Object.keys(liveFiles).length === 0) {
|
|
19727
|
-
console.error(`Source hub folder has no files to freeze: ${
|
|
20187
|
+
console.error(`Source hub folder has no files to freeze: ${path27.relative(gitRoot, hubFolder)}`);
|
|
19728
20188
|
process.exit(1);
|
|
19729
20189
|
}
|
|
19730
20190
|
const sanitized = sanitizeWayaiSliceFiles(liveFiles);
|
|
19731
|
-
const relDest =
|
|
19732
|
-
const relSrc =
|
|
20191
|
+
const relDest = path27.relative(gitRoot, dest);
|
|
20192
|
+
const relSrc = path27.relative(gitRoot, hubFolder);
|
|
19733
20193
|
if (dryRun) {
|
|
19734
20194
|
const existing = new Set(listDirRelFiles(dest));
|
|
19735
20195
|
const nextKeys = new Set(Object.keys(sanitized));
|
|
@@ -19789,7 +20249,7 @@ async function runTemplatePull2(positional, flagArgs) {
|
|
|
19789
20249
|
console.log(JSON.stringify(detail, null, 2));
|
|
19790
20250
|
return;
|
|
19791
20251
|
}
|
|
19792
|
-
const target = outDir ?
|
|
20252
|
+
const target = outDir ? path27.resolve(outDir) : path27.join(process.cwd(), "template-store-pull", slug);
|
|
19793
20253
|
const written = writeFileMap(target, detail.files);
|
|
19794
20254
|
console.log(`Pulled "${slug}" from the store \u2192 ${target} (${written.length} file${written.length === 1 ? "" : "s"}).`);
|
|
19795
20255
|
const uses = detail.uses ?? [];
|
|
@@ -19812,13 +20272,13 @@ async function runSkillInstall(positional) {
|
|
|
19812
20272
|
throw err;
|
|
19813
20273
|
}
|
|
19814
20274
|
const root = findGitRoot() ?? process.cwd();
|
|
19815
|
-
const present = HARNESS_SKILL_DIRS.filter((dir) =>
|
|
20275
|
+
const present = HARNESS_SKILL_DIRS.filter((dir) => fs21.existsSync(path27.join(root, dir)));
|
|
19816
20276
|
const targets = present.length > 0 ? present : HARNESS_SKILL_DIRS;
|
|
19817
20277
|
const fileCount = Object.keys(res.files).length;
|
|
19818
20278
|
const relDirs = targets.map((harness) => {
|
|
19819
|
-
const targetDir =
|
|
20279
|
+
const targetDir = path27.join(root, harness, "skills", name);
|
|
19820
20280
|
writeFileMap(targetDir, res.files);
|
|
19821
|
-
return `${
|
|
20281
|
+
return `${path27.relative(root, targetDir)}/`;
|
|
19822
20282
|
});
|
|
19823
20283
|
console.log(`Installed skill "${name}" (${fileCount} file${fileCount === 1 ? "" : "s"}) \u2192 ${relDirs.join(", ")}`);
|
|
19824
20284
|
console.log("Reload your agent (e.g. restart Claude Code) to pick up the skill.");
|
|
@@ -19929,7 +20389,7 @@ async function runSandboxExec(positional, flagArgs) {
|
|
|
19929
20389
|
process.exit(data.exit_code);
|
|
19930
20390
|
}
|
|
19931
20391
|
}
|
|
19932
|
-
function parseScopedTargetFlags(flagArgs,
|
|
20392
|
+
function parseScopedTargetFlags(flagArgs, usage3) {
|
|
19933
20393
|
let all = false;
|
|
19934
20394
|
let orgId;
|
|
19935
20395
|
let hubId;
|
|
@@ -19964,7 +20424,7 @@ function parseScopedTargetFlags(flagArgs, usage2) {
|
|
|
19964
20424
|
}
|
|
19965
20425
|
if ((all ? 1 : 0) + (orgId ? 1 : 0) + (hubId ? 1 : 0) !== 1) {
|
|
19966
20426
|
console.error("Provide exactly ONE of --all, --org <org_id>, or --hub <hub_id>.");
|
|
19967
|
-
console.error(
|
|
20427
|
+
console.error(usage3);
|
|
19968
20428
|
process.exit(1);
|
|
19969
20429
|
}
|
|
19970
20430
|
if (all) {
|
|
@@ -20070,7 +20530,7 @@ async function runHarnessMassDestroy(flagArgs) {
|
|
|
20070
20530
|
);
|
|
20071
20531
|
}
|
|
20072
20532
|
}
|
|
20073
|
-
function resolveHarnessLayer(flagArgs,
|
|
20533
|
+
function resolveHarnessLayer(flagArgs, usage3) {
|
|
20074
20534
|
let orgId;
|
|
20075
20535
|
let hubId;
|
|
20076
20536
|
for (let i = 0; i < flagArgs.length; i++) {
|
|
@@ -20084,13 +20544,13 @@ function resolveHarnessLayer(flagArgs, usage2) {
|
|
|
20084
20544
|
break;
|
|
20085
20545
|
default:
|
|
20086
20546
|
console.error(`Unknown flag: ${arg}`);
|
|
20087
|
-
console.error(
|
|
20547
|
+
console.error(usage3);
|
|
20088
20548
|
process.exit(1);
|
|
20089
20549
|
}
|
|
20090
20550
|
}
|
|
20091
20551
|
if (orgId && hubId) {
|
|
20092
20552
|
console.error("Provide at most ONE of --org <org_id> or --hub <hub_id> (or neither for the platform layer).");
|
|
20093
|
-
console.error(
|
|
20553
|
+
console.error(usage3);
|
|
20094
20554
|
process.exit(1);
|
|
20095
20555
|
}
|
|
20096
20556
|
if (orgId) return { kind: "org", orgId };
|
|
@@ -21160,7 +21620,7 @@ var init_update = __esm({
|
|
|
21160
21620
|
|
|
21161
21621
|
// src/index.ts
|
|
21162
21622
|
init_sentry();
|
|
21163
|
-
import { readFileSync as
|
|
21623
|
+
import { readFileSync as readFileSync19 } from "fs";
|
|
21164
21624
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
21165
21625
|
import { dirname as dirname9, join as join25 } from "path";
|
|
21166
21626
|
|
|
@@ -21185,7 +21645,7 @@ function friendlyHint(err) {
|
|
|
21185
21645
|
}
|
|
21186
21646
|
|
|
21187
21647
|
// src/index.ts
|
|
21188
|
-
|
|
21648
|
+
init_mask_secrets();
|
|
21189
21649
|
init_utils();
|
|
21190
21650
|
|
|
21191
21651
|
// src/lib/version-refresh.ts
|
|
@@ -21342,7 +21802,7 @@ Run \`wayai admin skill install\` to update.`);
|
|
|
21342
21802
|
|
|
21343
21803
|
// src/index.ts
|
|
21344
21804
|
var __dirname = dirname9(fileURLToPath2(import.meta.url));
|
|
21345
|
-
var pkg = JSON.parse(
|
|
21805
|
+
var pkg = JSON.parse(readFileSync19(join25(__dirname, "..", "package.json"), "utf-8"));
|
|
21346
21806
|
var [, , command, ...args] = process.argv;
|
|
21347
21807
|
var isBackgroundRefresh = command === REFRESH_COMMAND;
|
|
21348
21808
|
if (!isBackgroundRefresh) initSentry(command, pkg.version);
|
|
@@ -21587,7 +22047,7 @@ Commands:
|
|
|
21587
22047
|
use <hub> Bind this worktree to a specific hub (UUID or folder name)
|
|
21588
22048
|
migrate Move a legacy repo to the wayai-ws/{hubs,org} layout
|
|
21589
22049
|
unbind Clear the worktree hub binding
|
|
21590
|
-
send-message Send a test message to a hub (preview or production)
|
|
22050
|
+
send-message Send a test message to a hub (preview or production; -f <path> to attach a file)
|
|
21591
22051
|
conversations List or inspect conversations
|
|
21592
22052
|
alerts Show a hub's active connection/credential alerts (run this FIRST when a hub misbehaves)
|
|
21593
22053
|
analytics Show analytics summary and metrics (use \`analytics query\` for structured ClickHouse queries)
|
|
@@ -21679,7 +22139,7 @@ async function runForeground() {
|
|
|
21679
22139
|
captureException2(err);
|
|
21680
22140
|
}
|
|
21681
22141
|
await closeSentry();
|
|
21682
|
-
console.error(
|
|
22142
|
+
console.error(maskSecretsInMessage(err instanceof Error ? err.message : String(err)));
|
|
21683
22143
|
const hint = friendlyHint(err);
|
|
21684
22144
|
if (hint) console.error(hint);
|
|
21685
22145
|
process.exit(1);
|