@wayai/cli 0.3.98 → 0.3.100

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -238,11 +238,11 @@ function captureException2(error, context) {
238
238
  Sentry.captureException(error);
239
239
  });
240
240
  }
241
- function addApiBreadcrumb(method, path27) {
241
+ function addApiBreadcrumb(method, path28) {
242
242
  if (!initialized) return;
243
243
  Sentry.addBreadcrumb({
244
244
  category: "http",
245
- message: `${method} ${path27}`,
245
+ message: `${method} ${path28}`,
246
246
  level: "info"
247
247
  });
248
248
  }
@@ -304,9 +304,9 @@ var init_api_client = __esm({
304
304
  ApiError = class extends Error {
305
305
  status;
306
306
  body;
307
- constructor(method, path27, status, body) {
307
+ constructor(method, path28, status, body) {
308
308
  const safeBody = maskSecretsInMessage(body);
309
- super(`API request failed: ${method} ${path27} (${status}): ${safeBody}`);
309
+ super(`API request failed: ${method} ${path28} (${status}): ${safeBody}`);
310
310
  this.name = "ApiError";
311
311
  this.status = status;
312
312
  this.body = safeBody;
@@ -454,8 +454,8 @@ var init_api_client = __esm({
454
454
  ...organizationId && { organization_id: organizationId }
455
455
  });
456
456
  }
457
- async lookup(path27, opts) {
458
- const params = new URLSearchParams({ path: path27 });
457
+ async lookup(path28, opts) {
458
+ const params = new URLSearchParams({ path: path28 });
459
459
  if (opts?.organizationId) params.set("organization_id", opts.organizationId);
460
460
  return this.request("GET", `/api/ci/lookup?${params.toString()}`);
461
461
  }
@@ -502,8 +502,11 @@ var init_api_client = __esm({
502
502
  async sendMessage(hubId, message, opts) {
503
503
  return this.request("POST", "/api/conversations/send-message", {
504
504
  hub_id: hubId,
505
- message,
506
- ...opts?.conversationId && { conversation_id: opts.conversationId }
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 }
507
510
  });
508
511
  }
509
512
  async deleteHistory(hubId, opts) {
@@ -852,9 +855,9 @@ var init_api_client = __esm({
852
855
  * sandbox for this conversation, or the blob was purged).
853
856
  */
854
857
  async downloadArchiveSandboxFs(hubId, conversationId) {
855
- const path27 = `/api/archive/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}/sandbox`;
856
- addApiBreadcrumb("GET", path27);
857
- const url = `${this.apiUrl}${path27}`;
858
+ const path28 = `/api/archive/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}/sandbox`;
859
+ addApiBreadcrumb("GET", path28);
860
+ const url = `${this.apiUrl}${path28}`;
858
861
  let response = await this.send(url, "GET");
859
862
  if (response.status === 401 && this.onUnauthorized) {
860
863
  let refreshed;
@@ -868,7 +871,7 @@ var init_api_client = __esm({
868
871
  }
869
872
  }
870
873
  if (!response.ok) {
871
- throw new ApiError("GET", path27, response.status, await response.text());
874
+ throw new ApiError("GET", path28, response.status, await response.text());
872
875
  }
873
876
  return new Uint8Array(await response.arrayBuffer());
874
877
  }
@@ -908,9 +911,9 @@ var init_api_client = __esm({
908
911
  `/api/admin/data-explorer/debug/observability/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}${qs}`
909
912
  );
910
913
  }
911
- async request(method, path27, body) {
912
- addApiBreadcrumb(method, path27);
913
- const url = `${this.apiUrl}${path27}`;
914
+ async request(method, path28, body) {
915
+ addApiBreadcrumb(method, path28);
916
+ const url = `${this.apiUrl}${path28}`;
914
917
  let refreshedOn401 = false;
915
918
  for (let retry = 0; ; retry++) {
916
919
  let response = await this.send(url, method, body);
@@ -934,7 +937,7 @@ var init_api_client = __esm({
934
937
  await delay(RETRYABLE_BACKOFF_MS[retry]);
935
938
  continue;
936
939
  }
937
- throw new ApiError(method, path27, response.status, errorBody);
940
+ throw new ApiError(method, path28, response.status, errorBody);
938
941
  }
939
942
  }
940
943
  /** Issue a single authenticated request with the client's current token. */
@@ -1369,8 +1372,8 @@ var init_parseUtil = __esm({
1369
1372
  init_errors();
1370
1373
  init_en();
1371
1374
  makeIssue = (params) => {
1372
- const { data, path: path27, errorMaps, issueData } = params;
1373
- const fullPath = [...path27, ...issueData.path || []];
1375
+ const { data, path: path28, errorMaps, issueData } = params;
1376
+ const fullPath = [...path28, ...issueData.path || []];
1374
1377
  const fullIssue = {
1375
1378
  ...issueData,
1376
1379
  path: fullPath
@@ -1681,11 +1684,11 @@ var init_types = __esm({
1681
1684
  init_parseUtil();
1682
1685
  init_util();
1683
1686
  ParseInputLazyPath = class {
1684
- constructor(parent, value, path27, key) {
1687
+ constructor(parent, value, path28, key) {
1685
1688
  this._cachedPath = [];
1686
1689
  this.parent = parent;
1687
1690
  this.data = value;
1688
- this._path = path27;
1691
+ this._path = path28;
1689
1692
  this._key = key;
1690
1693
  }
1691
1694
  get path() {
@@ -5069,6 +5072,24 @@ var init_zod = __esm({
5069
5072
  });
5070
5073
 
5071
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
+ }
5072
5093
  function normalizeAuthType(raw) {
5073
5094
  if (VALID_AUTH_TYPES.has(raw)) return raw;
5074
5095
  return LEGACY_AUTH_TYPE_MAP[raw] ?? raw;
@@ -5151,12 +5172,12 @@ function typeMatches(typeField, allowed) {
5151
5172
  if (Array.isArray(typeField)) return typeField.every((t) => typeof t === "string" && allowed.has(t));
5152
5173
  return false;
5153
5174
  }
5154
- function validateSchema(schema, path27, errors, opts = {}) {
5175
+ function validateSchema(schema, path28, errors, opts = {}) {
5155
5176
  if (typeof schema === "boolean") return;
5156
5177
  const depth = opts.depth ?? 0;
5157
5178
  if (depth > MAX_SCHEMA_DEPTH) {
5158
5179
  errors.push({
5159
- path: path27 || "<root>",
5180
+ path: path28 || "<root>",
5160
5181
  message: `schema nesting exceeds ${MAX_SCHEMA_DEPTH} levels`,
5161
5182
  suggestion: "Flatten the schema; LLM providers reject deeply nested tool input_schemas."
5162
5183
  });
@@ -5164,7 +5185,7 @@ function validateSchema(schema, path27, errors, opts = {}) {
5164
5185
  }
5165
5186
  if (!isRecord(schema)) {
5166
5187
  errors.push({
5167
- path: path27,
5188
+ path: path28,
5168
5189
  message: `expected object, got ${schema === null ? "null" : typeof schema}`
5169
5190
  });
5170
5191
  return;
@@ -5172,14 +5193,14 @@ function validateSchema(schema, path27, errors, opts = {}) {
5172
5193
  if (opts.isRoot) {
5173
5194
  if ("type" in schema && schema.type !== "object") {
5174
5195
  errors.push({
5175
- path: path27 ? `${path27}.type` : "type",
5196
+ path: path28 ? `${path28}.type` : "type",
5176
5197
  message: `root type must be 'object', got ${JSON.stringify(schema.type)}`,
5177
5198
  suggestion: "Tool parameters at the root must be an object: `{ type: 'object', properties: { ... } }`."
5178
5199
  });
5179
5200
  }
5180
5201
  } else if ("type" in schema && !typeMatches(schema.type, ALLOWED_TYPES)) {
5181
5202
  errors.push({
5182
- path: `${path27}.type`,
5203
+ path: `${path28}.type`,
5183
5204
  message: `type must be one of ${[...ALLOWED_TYPES].join("/")} or an array of those, got ${JSON.stringify(schema.type)}`
5184
5205
  });
5185
5206
  }
@@ -5188,25 +5209,25 @@ function validateSchema(schema, path27, errors, opts = {}) {
5188
5209
  if (typeof e === "string") {
5189
5210
  const isPlaceholder = PLACEHOLDER_TOKENS.includes(e);
5190
5211
  errors.push({
5191
- path: `${path27}.enum`,
5212
+ path: `${path28}.enum`,
5192
5213
  message: `enum must be a non-empty array of primitives, got string ${JSON.stringify(e)}`,
5193
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"]`.'
5194
5215
  });
5195
5216
  } else if (!Array.isArray(e)) {
5196
5217
  errors.push({
5197
- path: `${path27}.enum`,
5218
+ path: `${path28}.enum`,
5198
5219
  message: `enum must be a non-empty array of primitives, got ${typeof e}`
5199
5220
  });
5200
5221
  } else if (e.length === 0) {
5201
5222
  errors.push({
5202
- path: `${path27}.enum`,
5223
+ path: `${path28}.enum`,
5203
5224
  message: "enum must not be empty"
5204
5225
  });
5205
5226
  } else {
5206
5227
  for (let i = 0; i < e.length; i++) {
5207
5228
  if (!isPrimitive(e[i])) {
5208
5229
  errors.push({
5209
- path: `${path27}.enum[${i}]`,
5230
+ path: `${path28}.enum[${i}]`,
5210
5231
  message: `enum entry must be a primitive (string/number/boolean/null), got ${typeof e[i]}`
5211
5232
  });
5212
5233
  }
@@ -5216,7 +5237,7 @@ function validateSchema(schema, path27, errors, opts = {}) {
5216
5237
  for (const key of ["exclusiveMinimum", "exclusiveMaximum"]) {
5217
5238
  if (key in schema && typeof schema[key] === "boolean") {
5218
5239
  errors.push({
5219
- path: `${path27}.${key}`,
5240
+ path: `${path28}.${key}`,
5220
5241
  message: `${key} as boolean is draft-04 syntax; draft 2020-12 requires a numeric value`,
5221
5242
  suggestion: `Replace with the numeric bound, e.g. \`${key}: 0\`.`
5222
5243
  });
@@ -5225,45 +5246,45 @@ function validateSchema(schema, path27, errors, opts = {}) {
5225
5246
  if ("properties" in schema) {
5226
5247
  if (!isRecord(schema.properties)) {
5227
5248
  errors.push({
5228
- path: `${path27}.properties`,
5249
+ path: `${path28}.properties`,
5229
5250
  message: `properties must be an object, got ${Array.isArray(schema.properties) ? "array" : typeof schema.properties}`
5230
5251
  });
5231
5252
  } else {
5232
5253
  for (const [propName, propSchema] of Object.entries(schema.properties)) {
5233
- validateSchema(propSchema, `${path27}.properties.${propName}`, errors, { depth: depth + 1 });
5254
+ validateSchema(propSchema, `${path28}.properties.${propName}`, errors, { depth: depth + 1 });
5234
5255
  }
5235
5256
  }
5236
5257
  }
5237
5258
  if (schemaTypeIncludes(schema, "array") && "items" in schema) {
5238
5259
  if (Array.isArray(schema.items)) {
5239
- schema.items.forEach((sub, i) => validateSchema(sub, `${path27}.items[${i}]`, errors, { depth: depth + 1 }));
5260
+ schema.items.forEach((sub, i) => validateSchema(sub, `${path28}.items[${i}]`, errors, { depth: depth + 1 }));
5240
5261
  } else {
5241
- validateSchema(schema.items, `${path27}.items`, errors, { depth: depth + 1 });
5262
+ validateSchema(schema.items, `${path28}.items`, errors, { depth: depth + 1 });
5242
5263
  }
5243
5264
  }
5244
5265
  for (const key of SUBSCHEMA_OBJECT_KEYWORDS) {
5245
5266
  if (key in schema && isRecord(schema[key])) {
5246
- validateSchema(schema[key], `${path27}.${key}`, errors, { depth: depth + 1 });
5267
+ validateSchema(schema[key], `${path28}.${key}`, errors, { depth: depth + 1 });
5247
5268
  }
5248
5269
  }
5249
5270
  for (const key of SUBSCHEMA_LIST_KEYWORDS) {
5250
5271
  const list = schema[key];
5251
5272
  if (Array.isArray(list)) {
5252
- list.forEach((sub, i) => validateSchema(sub, `${path27}.${key}[${i}]`, errors, { depth: depth + 1 }));
5273
+ list.forEach((sub, i) => validateSchema(sub, `${path28}.${key}[${i}]`, errors, { depth: depth + 1 }));
5253
5274
  }
5254
5275
  }
5255
5276
  for (const key of SUBSCHEMA_MAP_KEYWORDS) {
5256
5277
  const map = schema[key];
5257
5278
  if (isRecord(map)) {
5258
5279
  for (const [name, sub] of Object.entries(map)) {
5259
- validateSchema(sub, `${path27}.${key}.${name}`, errors, { depth: depth + 1 });
5280
+ validateSchema(sub, `${path28}.${key}.${name}`, errors, { depth: depth + 1 });
5260
5281
  }
5261
5282
  }
5262
5283
  }
5263
5284
  const reportedPaths = new Set(errors.map((e) => e.path));
5264
5285
  for (const [k, v] of Object.entries(schema)) {
5265
5286
  if (typeof v !== "string") continue;
5266
- const fieldPath = `${path27}.${k}`;
5287
+ const fieldPath = `${path28}.${k}`;
5267
5288
  if (reportedPaths.has(fieldPath)) continue;
5268
5289
  for (const token of PLACEHOLDER_TOKENS) {
5269
5290
  if (v === token) {
@@ -5474,10 +5495,10 @@ function refineHubAsCodeEvals(config, ctx) {
5474
5495
  }
5475
5496
  }
5476
5497
  }
5477
- function isSafeTemplatePath(path27) {
5478
- if (path27.length === 0 || path27.length > 300) return false;
5479
- if (path27.startsWith("/") || path27.includes("\\")) return false;
5480
- const segments = path27.split("/");
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("/");
5481
5502
  return segments.every(
5482
5503
  (seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
5483
5504
  );
@@ -5547,7 +5568,7 @@ function findStepBoundaries(transcript) {
5547
5568
  }
5548
5569
  return out;
5549
5570
  }
5550
- 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, 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, 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;
5551
5572
  var init_dist = __esm({
5552
5573
  "../../packages/core/dist/index.js"() {
5553
5574
  "use strict";
@@ -5599,6 +5620,68 @@ var init_dist = __esm({
5599
5620
  init_zod();
5600
5621
  init_zod();
5601
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
+ );
5602
5685
  APP_ERROR_BRAND = /* @__PURE__ */ Symbol.for("wayai.AppError");
5603
5686
  AppError = class extends Error {
5604
5687
  constructor(message, code, statusCode = 500, details) {
@@ -5630,7 +5713,7 @@ var init_dist = __esm({
5630
5713
  LLM_PROVIDER_HTTP_BRAND = /* @__PURE__ */ Symbol.for("wayai.LlmProviderHttpError");
5631
5714
  LlmProviderHttpError = class extends Error {
5632
5715
  constructor(message, status, provider, providerError) {
5633
- super(message);
5716
+ super(redactSecrets(message));
5634
5717
  this.status = status;
5635
5718
  this.provider = provider;
5636
5719
  this.providerError = providerError;
@@ -5736,6 +5819,30 @@ var init_dist = __esm({
5736
5819
  idParamSchema = external_exports.object({
5737
5820
  id: uuidSchema
5738
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;
5739
5846
  primaryRegionSchema = external_exports.enum([
5740
5847
  "wnam",
5741
5848
  "enam",
@@ -7004,17 +7111,8 @@ var init_dist = __esm({
7004
7111
  });
7005
7112
  }
7006
7113
  });
7007
- clientOptionalString = external_exports.string().nullish().transform((v) => v ?? void 0);
7008
- clientOptionalBoolean = external_exports.boolean().nullish().transform((v) => v ?? void 0);
7009
7114
  appMessageSenderType = external_exports.enum(["user", "team"]);
7010
7115
  appMessageReceiverType = external_exports.enum(["user", "team", "agent", "assistant"]).transform((v) => v === "assistant" ? "agent" : v);
7011
- appMessageAttachment = external_exports.object({
7012
- file_name: external_exports.string(),
7013
- file_binary: external_exports.string(),
7014
- file_size: external_exports.number().nullish().transform((v) => v ?? void 0),
7015
- file_extension: clientOptionalString
7016
- });
7017
- MAX_ATTACHMENTS_PER_MESSAGE = 20;
7018
7116
  appMessageBody = external_exports.object({
7019
7117
  // Message content — three historical aliases. All optional: an attachment-only
7020
7118
  // or voice-only message carries no text.
@@ -7043,7 +7141,7 @@ var init_dist = __esm({
7043
7141
  // Pre-generated by the client so the optimistic bubble and the stored row share
7044
7142
  // a key (transcription live-updates land on the same row instead of duplicating).
7045
7143
  message_id: clientOptionalString,
7046
- attachments: external_exports.array(appMessageAttachment).max(MAX_ATTACHMENTS_PER_MESSAGE).nullish().transform((v) => v ?? void 0),
7144
+ attachments: external_exports.array(messageAttachment).max(MAX_ATTACHMENTS_PER_MESSAGE).nullish().transform((v) => v ?? void 0),
7047
7145
  // Base64-encoded audio for STT. Size-capped in the route (the cap is a byte
7048
7146
  // budget tied to the /channels/* bodyLimit, not a shape rule).
7049
7147
  audio_file: clientOptionalString
@@ -7214,11 +7312,27 @@ var init_dist = __esm({
7214
7312
  ]);
7215
7313
  sendMessageBody = external_exports.object({
7216
7314
  hub_id: external_exports.string().uuid(),
7217
- message: external_exports.string().min(1).max(5e4),
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(),
7218
7322
  /** For chat hubs: optional — automatically continues the user's active conversation (or creates one).
7219
7323
  * For task hubs: required to continue an existing conversation. Omit to start a new task conversation. */
7220
- conversation_id: external_exports.string().uuid().optional()
7221
- });
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
+ );
7222
7336
  listConversationsQuery = external_exports.object({
7223
7337
  hub_id: external_exports.string().uuid(),
7224
7338
  status: external_exports.enum(["agent", "team", "ended"]).optional(),
@@ -8574,7 +8688,7 @@ function findHubByFolderName(workspaceDir, hubFolderName) {
8574
8688
  function resolveHubFolderBySelector(hubsDir, selector) {
8575
8689
  const asPath = path2.resolve(selector);
8576
8690
  if (isDirectory(asPath) && fs2.existsSync(path2.join(asPath, "hub.yaml"))) return asPath;
8577
- if (UUID_RE.test(selector)) {
8691
+ if (UUID_RE2.test(selector)) {
8578
8692
  const match = scanWorkspaceHubs(hubsDir).find((h) => h.hubId === selector);
8579
8693
  return match ? match.hubFolder : null;
8580
8694
  }
@@ -8681,7 +8795,7 @@ function resolveActiveHubId(args2) {
8681
8795
  const workspaceDir = workspace?.workspaceDir ?? (gitRoot ? resolveLayout(gitRoot).hubsDir : null);
8682
8796
  const wsLabel = hubsDirLabel(gitRoot);
8683
8797
  if (!workspaceDir || !fs2.existsSync(workspaceDir)) {
8684
- if (selector && UUID_RE.test(selector)) return selector;
8798
+ if (selector && UUID_RE2.test(selector)) return selector;
8685
8799
  console.error(`No ${wsLabel}/ directory found. Run \`wayai pull --hub <uuid>\` to fetch a hub, or pass --hub <uuid>.`);
8686
8800
  process.exit(1);
8687
8801
  }
@@ -8691,7 +8805,7 @@ function resolveActiveHubId(args2) {
8691
8805
  (h) => h.hubId === selector || path2.basename(h.hubFolder) === selector
8692
8806
  );
8693
8807
  if (match) return match.hubId;
8694
- if (UUID_RE.test(selector)) return selector;
8808
+ if (UUID_RE2.test(selector)) return selector;
8695
8809
  console.error(`No hub matching --hub ${selector} found in ${wsLabel}/.`);
8696
8810
  process.exit(1);
8697
8811
  }
@@ -8764,7 +8878,7 @@ function readRepoConfig(root) {
8764
8878
  }
8765
8879
  return null;
8766
8880
  }
8767
- if (!UUID_RE.test(config.organization_id)) return null;
8881
+ if (!UUID_RE2.test(config.organization_id)) return null;
8768
8882
  const presentLegacy = LEGACY_FIELDS.filter((f) => config[f] !== void 0);
8769
8883
  warnAboutLegacyFields(presentLegacy);
8770
8884
  const organizationName = typeof config.organization_name === "string" && config.organization_name.trim() ? config.organization_name.trim() : void 0;
@@ -8940,7 +9054,7 @@ function parseDateArg(date, position) {
8940
9054
  }
8941
9055
  async function resolveOrganizationId(client, orgIdFlag) {
8942
9056
  if (orgIdFlag) {
8943
- if (!UUID_RE.test(orgIdFlag)) {
9057
+ if (!UUID_RE2.test(orgIdFlag)) {
8944
9058
  console.error("Invalid --org value. Expected a UUID.");
8945
9059
  process.exit(1);
8946
9060
  }
@@ -8998,12 +9112,12 @@ function isNewerVersion(latest, current) {
8998
9112
  }
8999
9113
  return false;
9000
9114
  }
9001
- var UUID_RE, slugify, OWN_HELP_COMMANDS;
9115
+ var UUID_RE2, slugify, OWN_HELP_COMMANDS;
9002
9116
  var init_utils = __esm({
9003
9117
  "src/lib/utils.ts"() {
9004
9118
  "use strict";
9005
9119
  init_dist();
9006
- UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
9120
+ UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
9007
9121
  slugify = slugifySkillName;
9008
9122
  OWN_HELP_COMMANDS = /* @__PURE__ */ new Set([
9009
9123
  "eval",
@@ -9024,9 +9138,9 @@ function getVersionCachePath(filename = CLI_CACHE_FILE) {
9024
9138
  }
9025
9139
  function readVersionCache(filename = CLI_CACHE_FILE) {
9026
9140
  try {
9027
- const path27 = getVersionCachePath(filename);
9028
- if (!existsSync4(path27)) return null;
9029
- const parsed = JSON.parse(readFileSync5(path27, "utf-8"));
9141
+ const path28 = getVersionCachePath(filename);
9142
+ if (!existsSync4(path28)) return null;
9143
+ const parsed = JSON.parse(readFileSync5(path28, "utf-8"));
9030
9144
  if (typeof parsed.lastCheck !== "number") return null;
9031
9145
  if (parsed.latest !== null && typeof parsed.latest !== "string") return null;
9032
9146
  return parsed;
@@ -9046,10 +9160,10 @@ function isVersionCacheStale(filename = CLI_CACHE_FILE, maxAgeMs = MAX_AGE_24H_M
9046
9160
  return Date.now() - cache.lastCheck > maxAgeMs;
9047
9161
  }
9048
9162
  function writeVersionCache(filename, cache) {
9049
- const path27 = getVersionCachePath(filename);
9050
- const dir = dirname3(path27);
9163
+ const path28 = getVersionCachePath(filename);
9164
+ const dir = dirname3(path28);
9051
9165
  if (!existsSync4(dir)) mkdirSync(dir, { recursive: true });
9052
- writeFileSync2(path27, JSON.stringify(cache));
9166
+ writeFileSync2(path28, JSON.stringify(cache));
9053
9167
  }
9054
9168
  function touchVersionCache(filename) {
9055
9169
  writeVersionCache(filename, { lastCheck: Date.now(), latest: readVersionCache(filename)?.latest ?? null });
@@ -9088,14 +9202,14 @@ function parseFrontmatterVersion(content) {
9088
9202
  function findInstalledSkills(projectRoot, paths = SKILL_INSTALL_PATHS) {
9089
9203
  const found = [];
9090
9204
  for (const rel of paths) {
9091
- const path27 = join7(projectRoot, rel);
9092
- if (!existsSync5(path27)) continue;
9205
+ const path28 = join7(projectRoot, rel);
9206
+ if (!existsSync5(path28)) continue;
9093
9207
  let version = null;
9094
9208
  try {
9095
- version = parseFrontmatterVersion(readFileSync6(path27, "utf-8"));
9209
+ version = parseFrontmatterVersion(readFileSync6(path28, "utf-8"));
9096
9210
  } catch {
9097
9211
  }
9098
- found.push({ path: path27, version });
9212
+ found.push({ path: path28, version });
9099
9213
  }
9100
9214
  return found;
9101
9215
  }
@@ -9998,12 +10112,12 @@ function readBinding() {
9998
10112
  throw err;
9999
10113
  }
10000
10114
  const trimmed = raw.trim();
10001
- return UUID_RE.test(trimmed) ? trimmed : null;
10115
+ return UUID_RE2.test(trimmed) ? trimmed : null;
10002
10116
  }
10003
10117
  return null;
10004
10118
  }
10005
10119
  function writeBinding(hubId) {
10006
- if (!UUID_RE.test(hubId)) {
10120
+ if (!UUID_RE2.test(hubId)) {
10007
10121
  throw new Error(`Invalid hub_id (must be a UUID): ${hubId}`);
10008
10122
  }
10009
10123
  const bindingPath = getBindingPath();
@@ -10473,7 +10587,7 @@ async function initCommand(args2) {
10473
10587
  );
10474
10588
  }
10475
10589
  async function initDirect(client, orgId) {
10476
- if (!UUID_RE.test(orgId)) {
10590
+ if (!UUID_RE2.test(orgId)) {
10477
10591
  console.error("Invalid organization ID. Expected a UUID.");
10478
10592
  process.exit(1);
10479
10593
  }
@@ -11453,7 +11567,7 @@ function resolveHubTarget(workspaceDir, selector) {
11453
11567
  (h) => h.hubId === selector || path14.basename(h.hubFolder) === selector
11454
11568
  );
11455
11569
  if (match) return { hubId: match.hubId, hubFolder: match.hubFolder };
11456
- if (UUID_RE.test(selector)) return { hubId: selector, hubFolder: null };
11570
+ if (UUID_RE2.test(selector)) return { hubId: selector, hubFolder: null };
11457
11571
  console.error(`No hub matching --hub ${selector} found in ${wsLabel}/. Pass a UUID for first-time pulls.`);
11458
11572
  process.exit(1);
11459
11573
  }
@@ -11956,7 +12070,7 @@ New hub: "${newHub.hubName}" (${hubType})`);
11956
12070
  });
11957
12071
  const createdHub = createResult.data[0];
11958
12072
  const hubId = createdHub.hub_id;
11959
- if (!UUID_RE.test(hubId)) {
12073
+ if (!UUID_RE2.test(hubId)) {
11960
12074
  console.error(`Invalid hub_id received from server: ${hubId}`);
11961
12075
  process.exit(1);
11962
12076
  }
@@ -12304,12 +12418,12 @@ function typeMatches2(typeField, allowed) {
12304
12418
  if (Array.isArray(typeField)) return typeField.every((t) => typeof t === "string" && allowed.has(t));
12305
12419
  return false;
12306
12420
  }
12307
- function validateSchema2(schema, path27, errors, opts = {}) {
12421
+ function validateSchema2(schema, path28, errors, opts = {}) {
12308
12422
  if (typeof schema === "boolean") return;
12309
12423
  const depth = opts.depth ?? 0;
12310
12424
  if (depth > MAX_SCHEMA_DEPTH2) {
12311
12425
  errors.push({
12312
- path: path27 || "<root>",
12426
+ path: path28 || "<root>",
12313
12427
  message: `schema nesting exceeds ${MAX_SCHEMA_DEPTH2} levels`,
12314
12428
  suggestion: "Flatten the schema; LLM providers reject deeply nested tool input_schemas."
12315
12429
  });
@@ -12317,7 +12431,7 @@ function validateSchema2(schema, path27, errors, opts = {}) {
12317
12431
  }
12318
12432
  if (!isRecord2(schema)) {
12319
12433
  errors.push({
12320
- path: path27,
12434
+ path: path28,
12321
12435
  message: `expected object, got ${schema === null ? "null" : typeof schema}`
12322
12436
  });
12323
12437
  return;
@@ -12325,14 +12439,14 @@ function validateSchema2(schema, path27, errors, opts = {}) {
12325
12439
  if (opts.isRoot) {
12326
12440
  if ("type" in schema && schema.type !== "object") {
12327
12441
  errors.push({
12328
- path: path27 ? `${path27}.type` : "type",
12442
+ path: path28 ? `${path28}.type` : "type",
12329
12443
  message: `root type must be 'object', got ${JSON.stringify(schema.type)}`,
12330
12444
  suggestion: "Tool parameters at the root must be an object: `{ type: 'object', properties: { ... } }`."
12331
12445
  });
12332
12446
  }
12333
12447
  } else if ("type" in schema && !typeMatches2(schema.type, ALLOWED_TYPES2)) {
12334
12448
  errors.push({
12335
- path: `${path27}.type`,
12449
+ path: `${path28}.type`,
12336
12450
  message: `type must be one of ${[...ALLOWED_TYPES2].join("/")} or an array of those, got ${JSON.stringify(schema.type)}`
12337
12451
  });
12338
12452
  }
@@ -12341,25 +12455,25 @@ function validateSchema2(schema, path27, errors, opts = {}) {
12341
12455
  if (typeof e === "string") {
12342
12456
  const isPlaceholder = PLACEHOLDER_TOKENS2.includes(e);
12343
12457
  errors.push({
12344
- path: `${path27}.enum`,
12458
+ path: `${path28}.enum`,
12345
12459
  message: `enum must be a non-empty array of primitives, got string ${JSON.stringify(e)}`,
12346
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"]`.'
12347
12461
  });
12348
12462
  } else if (!Array.isArray(e)) {
12349
12463
  errors.push({
12350
- path: `${path27}.enum`,
12464
+ path: `${path28}.enum`,
12351
12465
  message: `enum must be a non-empty array of primitives, got ${typeof e}`
12352
12466
  });
12353
12467
  } else if (e.length === 0) {
12354
12468
  errors.push({
12355
- path: `${path27}.enum`,
12469
+ path: `${path28}.enum`,
12356
12470
  message: "enum must not be empty"
12357
12471
  });
12358
12472
  } else {
12359
12473
  for (let i = 0; i < e.length; i++) {
12360
12474
  if (!isPrimitive2(e[i])) {
12361
12475
  errors.push({
12362
- path: `${path27}.enum[${i}]`,
12476
+ path: `${path28}.enum[${i}]`,
12363
12477
  message: `enum entry must be a primitive (string/number/boolean/null), got ${typeof e[i]}`
12364
12478
  });
12365
12479
  }
@@ -12369,7 +12483,7 @@ function validateSchema2(schema, path27, errors, opts = {}) {
12369
12483
  for (const key of ["exclusiveMinimum", "exclusiveMaximum"]) {
12370
12484
  if (key in schema && typeof schema[key] === "boolean") {
12371
12485
  errors.push({
12372
- path: `${path27}.${key}`,
12486
+ path: `${path28}.${key}`,
12373
12487
  message: `${key} as boolean is draft-04 syntax; draft 2020-12 requires a numeric value`,
12374
12488
  suggestion: `Replace with the numeric bound, e.g. \`${key}: 0\`.`
12375
12489
  });
@@ -12378,45 +12492,45 @@ function validateSchema2(schema, path27, errors, opts = {}) {
12378
12492
  if ("properties" in schema) {
12379
12493
  if (!isRecord2(schema.properties)) {
12380
12494
  errors.push({
12381
- path: `${path27}.properties`,
12495
+ path: `${path28}.properties`,
12382
12496
  message: `properties must be an object, got ${Array.isArray(schema.properties) ? "array" : typeof schema.properties}`
12383
12497
  });
12384
12498
  } else {
12385
12499
  for (const [propName, propSchema] of Object.entries(schema.properties)) {
12386
- validateSchema2(propSchema, `${path27}.properties.${propName}`, errors, { depth: depth + 1 });
12500
+ validateSchema2(propSchema, `${path28}.properties.${propName}`, errors, { depth: depth + 1 });
12387
12501
  }
12388
12502
  }
12389
12503
  }
12390
12504
  if (schemaTypeIncludes2(schema, "array") && "items" in schema) {
12391
12505
  if (Array.isArray(schema.items)) {
12392
- schema.items.forEach((sub, i) => validateSchema2(sub, `${path27}.items[${i}]`, errors, { depth: depth + 1 }));
12506
+ schema.items.forEach((sub, i) => validateSchema2(sub, `${path28}.items[${i}]`, errors, { depth: depth + 1 }));
12393
12507
  } else {
12394
- validateSchema2(schema.items, `${path27}.items`, errors, { depth: depth + 1 });
12508
+ validateSchema2(schema.items, `${path28}.items`, errors, { depth: depth + 1 });
12395
12509
  }
12396
12510
  }
12397
12511
  for (const key of SUBSCHEMA_OBJECT_KEYWORDS2) {
12398
12512
  if (key in schema && isRecord2(schema[key])) {
12399
- validateSchema2(schema[key], `${path27}.${key}`, errors, { depth: depth + 1 });
12513
+ validateSchema2(schema[key], `${path28}.${key}`, errors, { depth: depth + 1 });
12400
12514
  }
12401
12515
  }
12402
12516
  for (const key of SUBSCHEMA_LIST_KEYWORDS2) {
12403
12517
  const list = schema[key];
12404
12518
  if (Array.isArray(list)) {
12405
- list.forEach((sub, i) => validateSchema2(sub, `${path27}.${key}[${i}]`, errors, { depth: depth + 1 }));
12519
+ list.forEach((sub, i) => validateSchema2(sub, `${path28}.${key}[${i}]`, errors, { depth: depth + 1 }));
12406
12520
  }
12407
12521
  }
12408
12522
  for (const key of SUBSCHEMA_MAP_KEYWORDS2) {
12409
12523
  const map = schema[key];
12410
12524
  if (isRecord2(map)) {
12411
12525
  for (const [name, sub] of Object.entries(map)) {
12412
- validateSchema2(sub, `${path27}.${key}.${name}`, errors, { depth: depth + 1 });
12526
+ validateSchema2(sub, `${path28}.${key}.${name}`, errors, { depth: depth + 1 });
12413
12527
  }
12414
12528
  }
12415
12529
  }
12416
12530
  const reportedPaths = new Set(errors.map((e) => e.path));
12417
12531
  for (const [k, v] of Object.entries(schema)) {
12418
12532
  if (typeof v !== "string") continue;
12419
- const fieldPath = `${path27}.${k}`;
12533
+ const fieldPath = `${path28}.${k}`;
12420
12534
  if (reportedPaths.has(fieldPath)) continue;
12421
12535
  for (const token of PLACEHOLDER_TOKENS2) {
12422
12536
  if (v === token) {
@@ -12627,10 +12741,10 @@ function refineHubAsCodeEvals2(config, ctx) {
12627
12741
  }
12628
12742
  }
12629
12743
  }
12630
- function isSafeTemplatePath2(path27) {
12631
- if (path27.length === 0 || path27.length > 300) return false;
12632
- if (path27.startsWith("/") || path27.includes("\\")) return false;
12633
- const segments = path27.split("/");
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("/");
12634
12748
  return segments.every(
12635
12749
  (seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
12636
12750
  );
@@ -12658,14 +12772,14 @@ function isPlainObject(value) {
12658
12772
  const proto = Object.getPrototypeOf(value);
12659
12773
  return proto === Object.prototype || proto === null;
12660
12774
  }
12661
- function isSanitizableSliceFile(path27) {
12662
- if (!/\.ya?ml$/i.test(path27)) return false;
12663
- return path27 !== "resources" && !path27.startsWith("resources/");
12775
+ function isSanitizableSliceFile(path28) {
12776
+ if (!/\.ya?ml$/i.test(path28)) return false;
12777
+ return path28 !== "resources" && !path28.startsWith("resources/");
12664
12778
  }
12665
12779
  function distinctUsesBackends(uses) {
12666
12780
  return [...new Set((uses ?? []).map((u) => u.backend))];
12667
12781
  }
12668
- 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, 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, 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;
12669
12783
  var init_contracts = __esm({
12670
12784
  "../../packages/core/dist/contracts/index.js"() {
12671
12785
  "use strict";
@@ -12726,6 +12840,30 @@ var init_contracts = __esm({
12726
12840
  idParamSchema2 = external_exports.object({
12727
12841
  id: uuidSchema2
12728
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;
12729
12867
  primaryRegionSchema2 = external_exports.enum([
12730
12868
  "wnam",
12731
12869
  "enam",
@@ -14037,17 +14175,8 @@ var init_contracts = __esm({
14037
14175
  });
14038
14176
  }
14039
14177
  });
14040
- clientOptionalString2 = external_exports.string().nullish().transform((v) => v ?? void 0);
14041
- clientOptionalBoolean2 = external_exports.boolean().nullish().transform((v) => v ?? void 0);
14042
14178
  appMessageSenderType2 = external_exports.enum(["user", "team"]);
14043
14179
  appMessageReceiverType2 = external_exports.enum(["user", "team", "agent", "assistant"]).transform((v) => v === "assistant" ? "agent" : v);
14044
- appMessageAttachment2 = external_exports.object({
14045
- file_name: external_exports.string(),
14046
- file_binary: external_exports.string(),
14047
- file_size: external_exports.number().nullish().transform((v) => v ?? void 0),
14048
- file_extension: clientOptionalString2
14049
- });
14050
- MAX_ATTACHMENTS_PER_MESSAGE2 = 20;
14051
14180
  appMessageBody2 = external_exports.object({
14052
14181
  // Message content — three historical aliases. All optional: an attachment-only
14053
14182
  // or voice-only message carries no text.
@@ -14076,7 +14205,7 @@ var init_contracts = __esm({
14076
14205
  // Pre-generated by the client so the optimistic bubble and the stored row share
14077
14206
  // a key (transcription live-updates land on the same row instead of duplicating).
14078
14207
  message_id: clientOptionalString2,
14079
- attachments: external_exports.array(appMessageAttachment2).max(MAX_ATTACHMENTS_PER_MESSAGE2).nullish().transform((v) => v ?? void 0),
14208
+ attachments: external_exports.array(messageAttachment2).max(MAX_ATTACHMENTS_PER_MESSAGE2).nullish().transform((v) => v ?? void 0),
14080
14209
  // Base64-encoded audio for STT. Size-capped in the route (the cap is a byte
14081
14210
  // budget tied to the /channels/* bodyLimit, not a shape rule).
14082
14211
  audio_file: clientOptionalString2
@@ -14247,11 +14376,27 @@ var init_contracts = __esm({
14247
14376
  ]);
14248
14377
  sendMessageBody2 = external_exports.object({
14249
14378
  hub_id: external_exports.string().uuid(),
14250
- message: external_exports.string().min(1).max(5e4),
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(),
14251
14386
  /** For chat hubs: optional — automatically continues the user's active conversation (or creates one).
14252
14387
  * For task hubs: required to continue an existing conversation. Omit to start a new task conversation. */
14253
- conversation_id: external_exports.string().uuid().optional()
14254
- });
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
+ );
14255
14400
  listConversationsQuery2 = external_exports.object({
14256
14401
  hub_id: external_exports.string().uuid(),
14257
14402
  status: external_exports.enum(["agent", "team", "ended"]).optional(),
@@ -15676,7 +15821,7 @@ async function useCommand(args2) {
15676
15821
  process.exit(1);
15677
15822
  }
15678
15823
  let hubId;
15679
- if (UUID_RE.test(target)) {
15824
+ if (UUID_RE2.test(target)) {
15680
15825
  hubId = target;
15681
15826
  } else {
15682
15827
  const workspace = detectWorkspace();
@@ -15856,37 +16001,109 @@ var send_message_exports = {};
15856
16001
  __export(send_message_exports, {
15857
16002
  sendMessageCommand: () => sendMessageCommand
15858
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
+ }
15859
16043
  async function sendMessageCommand(args2) {
15860
16044
  const hubId = resolveActiveHubId(args2);
15861
16045
  const { config, accessToken } = await requireAuth();
15862
16046
  requireRepoConfig();
15863
16047
  let conversationId;
15864
16048
  let message;
16049
+ const filePaths = [];
15865
16050
  for (let i = 0; i < args2.length; i++) {
15866
16051
  const arg = args2[i];
15867
16052
  if (arg === "-c" || arg === "--conversation") {
15868
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);
15869
16061
  } else if (!arg.startsWith("-")) {
15870
16062
  message = arg;
15871
16063
  }
15872
16064
  }
15873
- if (!message) {
15874
- console.error('Usage: wayai send-message [options] "message text"');
15875
- console.error("");
15876
- console.error("Options:");
15877
- console.error(" -c, --conversation <id> Continue an existing conversation");
15878
- console.error("");
15879
- console.error("The hub type (chat/task) is determined automatically from the hub.");
15880
- console.error("Chat hubs auto-continue the active conversation (or create one).");
15881
- console.error("Task hubs create a new conversation unless -c is provided.");
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).`);
15882
16095
  process.exit(1);
15883
16096
  }
15884
16097
  const client = new ApiClient({ apiUrl: config.api_url, accessToken });
15885
16098
  const result = await client.sendMessage(hubId, message, {
15886
- conversationId
16099
+ conversationId,
16100
+ ...attachments.length > 0 && { attachments }
15887
16101
  });
15888
16102
  console.log(`Conversation: ${result.conversation_id}`);
15889
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
+ }
15890
16107
  if (result.status_reason) {
15891
16108
  console.log(`Reason: ${result.status_reason}`);
15892
16109
  }
@@ -15903,13 +16120,17 @@ async function sendMessageCommand(args2) {
15903
16120
  console.log("(Agent processing failed \u2014 user message was stored)");
15904
16121
  }
15905
16122
  }
16123
+ var asMb, base64Length;
15906
16124
  var init_send_message = __esm({
15907
16125
  "src/commands/send-message.ts"() {
15908
16126
  "use strict";
16127
+ init_contracts();
15909
16128
  init_auth();
15910
16129
  init_repo_config();
15911
16130
  init_workspace();
15912
16131
  init_api_client();
16132
+ asMb = (bytes) => (bytes / 1024 / 1024).toFixed(1);
16133
+ base64Length = (bytes) => Math.ceil(bytes / 3) * 4;
15913
16134
  }
15914
16135
  });
15915
16136
 
@@ -17308,8 +17529,8 @@ var eval_capture_exports = {};
17308
17529
  __export(eval_capture_exports, {
17309
17530
  evalCaptureCommand: () => evalCaptureCommand
17310
17531
  });
17311
- import * as fs17 from "fs";
17312
- import * as path22 from "path";
17532
+ import * as fs18 from "fs";
17533
+ import * as path23 from "path";
17313
17534
  import * as yaml7 from "js-yaml";
17314
17535
  function isValidSetName(name) {
17315
17536
  if (name.length === 0 || name === "." || name === "..") return false;
@@ -17322,7 +17543,7 @@ function parseArgs13(args2) {
17322
17543
  process.exit(1);
17323
17544
  }
17324
17545
  const conversationId = args2[0];
17325
- if (!UUID_RE.test(conversationId)) {
17546
+ if (!UUID_RE2.test(conversationId)) {
17326
17547
  console.error(`Invalid conversation ID "${conversationId}". Expected a UUID.`);
17327
17548
  process.exit(1);
17328
17549
  }
@@ -17375,15 +17596,15 @@ async function evalCaptureCommand(args2) {
17375
17596
  const setFolderName = targetSetName;
17376
17597
  const scenarioName = parsed.evalName ?? `Capture ${parsed.conversationId.slice(0, 8)}`;
17377
17598
  const slug = slugify(scenarioName);
17378
- const evalsDir = path22.join(hubFolder, "evals");
17379
- const targetDir = path22.join(evalsDir, setFolderName);
17380
- const targetPath = path22.join(targetDir, `${slug}.yaml`);
17381
- if (!targetPath.startsWith(evalsDir + path22.sep)) {
17382
- console.error(`Resolved path "${path22.relative(hubFolder, targetPath)}" escapes evals/. Aborting.`);
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.`);
17383
17604
  process.exit(1);
17384
17605
  }
17385
- if (fs17.existsSync(targetPath)) {
17386
- console.error(`File already exists: ${path22.relative(hubFolder, targetPath)}. Use --name to choose a different name.`);
17606
+ if (fs18.existsSync(targetPath)) {
17607
+ console.error(`File already exists: ${path23.relative(hubFolder, targetPath)}. Use --name to choose a different name.`);
17387
17608
  process.exit(1);
17388
17609
  }
17389
17610
  console.log("Resolving scenario set...");
@@ -17415,9 +17636,9 @@ async function evalCaptureCommand(args2) {
17415
17636
  ...captured.evaluator_instructions ? { evaluator_instructions: captured.evaluator_instructions } : {}
17416
17637
  };
17417
17638
  const yamlObj = buildEvalYamlObject(evalEntry, slug);
17418
- fs17.mkdirSync(targetDir, { recursive: true });
17419
- fs17.writeFileSync(targetPath, yaml7.dump(yamlObj, YAML_DUMP_OPTIONS), "utf-8");
17420
- const relPath = path22.relative(process.cwd(), targetPath);
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);
17421
17642
  console.log(`
17422
17643
  Wrote ${relPath}`);
17423
17644
  console.log("Run `wayai pull` to refresh the agent display name, then commit. The scenario is already on the platform.");
@@ -17445,7 +17666,7 @@ function parseArgs14(args2) {
17445
17666
  process.exit(1);
17446
17667
  }
17447
17668
  const conversationId = args2[0];
17448
- if (!UUID_RE.test(conversationId)) {
17669
+ if (!UUID_RE2.test(conversationId)) {
17449
17670
  console.error(`Invalid conversation ID "${conversationId}". Expected a UUID.`);
17450
17671
  process.exit(1);
17451
17672
  }
@@ -17527,7 +17748,7 @@ async function evalSessionDeleteCommand(args2) {
17527
17748
  console.error(" wayai eval session delete --all");
17528
17749
  process.exit(1);
17529
17750
  }
17530
- if (sessionId && !UUID_RE.test(sessionId)) {
17751
+ if (sessionId && !UUID_RE2.test(sessionId)) {
17531
17752
  console.error(`Invalid session id: ${sessionId}`);
17532
17753
  process.exit(1);
17533
17754
  }
@@ -18565,7 +18786,7 @@ function parseArgs17(args2) {
18565
18786
  }
18566
18787
  return { connection, orgCredential, field, stdin };
18567
18788
  }
18568
- function usage(msg) {
18789
+ function usage2(msg) {
18569
18790
  if (msg) console.error(`${msg}
18570
18791
  `);
18571
18792
  console.error("Usage: wayai set-connection-credential --hub <id|name> --connection <name|id> ( --org-credential <name> | --field <field> --stdin )");
@@ -18576,17 +18797,17 @@ function usage(msg) {
18576
18797
  async function setConnectionCredentialCommand(args2) {
18577
18798
  const hubId = resolveActiveHubId(args2);
18578
18799
  const parsed = parseArgs17(args2);
18579
- if (!parsed.connection) usage("Missing required flag: --connection <name|id>");
18800
+ if (!parsed.connection) usage2("Missing required flag: --connection <name|id>");
18580
18801
  const orgMode = !!parsed.orgCredential;
18581
18802
  const directMode = !!parsed.field;
18582
18803
  if (orgMode === directMode) {
18583
- usage("Provide exactly one of --org-credential or --field.");
18804
+ usage2("Provide exactly one of --org-credential or --field.");
18584
18805
  }
18585
18806
  if (directMode && !VALID_FIELDS.includes(parsed.field)) {
18586
- usage(`Invalid --field "${parsed.field}". Valid fields: ${VALID_FIELDS.join(", ")}`);
18807
+ usage2(`Invalid --field "${parsed.field}". Valid fields: ${VALID_FIELDS.join(", ")}`);
18587
18808
  }
18588
18809
  if (directMode && !parsed.stdin) {
18589
- usage("--field requires --stdin (the secret is read from stdin, never an argument).");
18810
+ usage2("--field requires --stdin (the secret is read from stdin, never an argument).");
18590
18811
  }
18591
18812
  const { organization_id: organizationId } = requireRepoConfig();
18592
18813
  const { config, accessToken } = await requireAuth();
@@ -18598,27 +18819,27 @@ async function setConnectionCredentialCommand(args2) {
18598
18819
  else if (hubs.some((h) => h.production_hub_id === hubId)) environment = "production";
18599
18820
  }
18600
18821
  if (!environment) {
18601
- usage(`Could not resolve hub "${hubId}". Pull it first (\`wayai pull --hub ${hubId}\`) or check the id.`);
18822
+ usage2(`Could not resolve hub "${hubId}". Pull it first (\`wayai pull --hub ${hubId}\`) or check the id.`);
18602
18823
  }
18603
18824
  const isProduction = environment === "production";
18604
18825
  const { connections } = await client.listConnections(hubId);
18605
18826
  const conn = connections.find(
18606
18827
  (c) => c.connection_id === parsed.connection || c.connection_display_name === parsed.connection
18607
18828
  );
18608
- if (!conn || !conn.connection_id) usage(`Connection "${parsed.connection}" not found on hub ${hubId}.`);
18829
+ if (!conn || !conn.connection_id) usage2(`Connection "${parsed.connection}" not found on hub ${hubId}.`);
18609
18830
  const connectionId = conn.connection_id;
18610
18831
  const body = { hub_id: hubId };
18611
18832
  if (orgMode) {
18612
18833
  const { data: creds } = await client.listOrgCredentials(organizationId);
18613
18834
  const cred = creds.find((c) => c.credential_display_name === parsed.orgCredential);
18614
- if (!cred) usage(`Organization credential "${parsed.orgCredential}" not found.`);
18835
+ if (!cred) usage2(`Organization credential "${parsed.orgCredential}" not found.`);
18615
18836
  body.organization_credential_id = cred.organization_credential_id;
18616
18837
  } else {
18617
18838
  if (process.stdin.isTTY) {
18618
- usage('--field requires the secret on stdin. Example: echo "$SECRET" | wayai set-connection-credential ... --field api_key --stdin');
18839
+ usage2('--field requires the secret on stdin. Example: echo "$SECRET" | wayai set-connection-credential ... --field api_key --stdin');
18619
18840
  }
18620
18841
  const secret = (await readStdin())?.trim();
18621
- if (!secret) usage("No secret received from stdin.");
18842
+ if (!secret) usage2("No secret received from stdin.");
18622
18843
  body[parsed.field] = secret;
18623
18844
  }
18624
18845
  const target = isProduction ? "production" : "preview";
@@ -18644,23 +18865,23 @@ var init_set_connection_credential = __esm({
18644
18865
  });
18645
18866
 
18646
18867
  // src/lib/org-workspace.ts
18647
- import * as fs18 from "fs";
18648
- import * as path23 from "path";
18868
+ import * as fs19 from "fs";
18869
+ import * as path24 from "path";
18649
18870
  import * as yaml8 from "js-yaml";
18650
18871
  function getOrgDir(gitRoot) {
18651
18872
  return resolveLayout(gitRoot).orgDir;
18652
18873
  }
18653
18874
  function orgManifestExists(orgDir) {
18654
- return fs18.existsSync(path23.join(orgDir, ORG_MANIFEST_NAME));
18875
+ return fs19.existsSync(path24.join(orgDir, ORG_MANIFEST_NAME));
18655
18876
  }
18656
18877
  function parseOrgResources(orgDir) {
18657
- const manifestPath = path23.join(orgDir, ORG_MANIFEST_NAME);
18878
+ const manifestPath = path24.join(orgDir, ORG_MANIFEST_NAME);
18658
18879
  let manifest = {};
18659
- if (fs18.existsSync(manifestPath)) {
18660
- manifest = yaml8.load(fs18.readFileSync(manifestPath, "utf-8")) ?? {};
18880
+ if (fs19.existsSync(manifestPath)) {
18881
+ manifest = yaml8.load(fs19.readFileSync(manifestPath, "utf-8")) ?? {};
18661
18882
  }
18662
18883
  const rawResources = Array.isArray(manifest.resources) ? manifest.resources : [];
18663
- const resourcesDir = path23.join(orgDir, "resources");
18884
+ const resourcesDir = path24.join(orgDir, "resources");
18664
18885
  const resources = rawResources.map((res) => {
18665
18886
  const resource = { name: res.name };
18666
18887
  if (res.id) resource.id = res.id;
@@ -18672,8 +18893,8 @@ function parseOrgResources(orgDir) {
18672
18893
  if (res.environment) resource.environment = res.environment;
18673
18894
  if (Array.isArray(res.tags)) resource.tags = res.tags;
18674
18895
  if (Array.isArray(res.folders)) resource.folders = res.folders;
18675
- const resDir = path23.join(resourcesDir, slugify(resource.name));
18676
- if (fs18.existsSync(resDir)) {
18896
+ const resDir = path24.join(resourcesDir, slugify(resource.name));
18897
+ if (fs19.existsSync(resDir)) {
18677
18898
  const files = scanResourceFiles(resDir, "");
18678
18899
  if (files.length > 0) resource.files = files;
18679
18900
  }
@@ -18682,28 +18903,28 @@ function parseOrgResources(orgDir) {
18682
18903
  return { version: 1, resources };
18683
18904
  }
18684
18905
  function writeOrgResources(orgDir, payload) {
18685
- fs18.mkdirSync(orgDir, { recursive: true });
18906
+ fs19.mkdirSync(orgDir, { recursive: true });
18686
18907
  const resources = payload.resources ?? [];
18687
18908
  const manifestResources = resources.map((r) => {
18688
18909
  const { files: _files, ...rest } = r;
18689
18910
  return rest;
18690
18911
  });
18691
- fs18.writeFileSync(
18692
- path23.join(orgDir, ORG_MANIFEST_NAME),
18912
+ fs19.writeFileSync(
18913
+ path24.join(orgDir, ORG_MANIFEST_NAME),
18693
18914
  yaml8.dump({ version: 1, resources: manifestResources }, YAML_DUMP_OPTIONS),
18694
18915
  "utf-8"
18695
18916
  );
18696
- const resourcesDir = path23.join(orgDir, "resources");
18917
+ const resourcesDir = path24.join(orgDir, "resources");
18697
18918
  const currentSlugs = /* @__PURE__ */ new Set();
18698
18919
  for (const resource of resources) {
18699
18920
  const resSlug = slugify(resource.name);
18700
18921
  currentSlugs.add(resSlug);
18701
- writeResourceFileTree(path23.join(resourcesDir, resSlug), resource.files || []);
18922
+ writeResourceFileTree(path24.join(resourcesDir, resSlug), resource.files || []);
18702
18923
  }
18703
- if (fs18.existsSync(resourcesDir)) {
18704
- for (const entry of fs18.readdirSync(resourcesDir, { withFileTypes: true })) {
18924
+ if (fs19.existsSync(resourcesDir)) {
18925
+ for (const entry of fs19.readdirSync(resourcesDir, { withFileTypes: true })) {
18705
18926
  if (entry.isDirectory() && !currentSlugs.has(entry.name)) {
18706
- fs18.rmSync(path23.join(resourcesDir, entry.name), { recursive: true, force: true });
18927
+ fs19.rmSync(path24.join(resourcesDir, entry.name), { recursive: true, force: true });
18707
18928
  }
18708
18929
  }
18709
18930
  }
@@ -18712,7 +18933,7 @@ async function downloadOrgBinaryFiles(orgDir, payload) {
18712
18933
  let count = 0;
18713
18934
  for (const resource of payload.resources ?? []) {
18714
18935
  if (!resource.files) continue;
18715
- const resDir = path23.join(orgDir, "resources", slugify(resource.name));
18936
+ const resDir = path24.join(orgDir, "resources", slugify(resource.name));
18716
18937
  count += await downloadBinaryFiles(resDir, resource.files);
18717
18938
  }
18718
18939
  if (count > 0) console.log(`Downloaded ${count} binary resource file(s).`);
@@ -18968,20 +19189,20 @@ var init_list = __esm({
18968
19189
  });
18969
19190
 
18970
19191
  // src/lib/template-files.ts
18971
- import * as fs19 from "fs";
18972
- import * as path24 from "path";
19192
+ import * as fs20 from "fs";
19193
+ import * as path25 from "path";
18973
19194
  function readDirToFileMap(rootDir) {
18974
19195
  const out = {};
18975
19196
  function walk(dir, prefix) {
18976
- const entries = fs19.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
19197
+ const entries = fs20.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
18977
19198
  for (const entry of entries) {
18978
- const abs = path24.join(dir, entry.name);
19199
+ const abs = path25.join(dir, entry.name);
18979
19200
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
18980
19201
  if (entry.isDirectory()) walk(abs, rel);
18981
- else if (entry.isFile()) out[rel] = fs19.readFileSync(abs, "utf-8");
19202
+ else if (entry.isFile()) out[rel] = fs20.readFileSync(abs, "utf-8");
18982
19203
  }
18983
19204
  }
18984
- if (fs19.existsSync(rootDir)) walk(rootDir, "");
19205
+ if (fs20.existsSync(rootDir)) walk(rootDir, "");
18985
19206
  return out;
18986
19207
  }
18987
19208
  function detectCollisions(targetDir, files) {
@@ -18990,7 +19211,7 @@ function detectCollisions(targetDir, files) {
18990
19211
  if (!isSafeTemplatePath2(rel)) {
18991
19212
  throw new Error(`Refusing to inspect unsafe template path: ${rel}`);
18992
19213
  }
18993
- if (fs19.existsSync(path24.join(targetDir, rel))) collisions.push(rel);
19214
+ if (fs20.existsSync(path25.join(targetDir, rel))) collisions.push(rel);
18994
19215
  }
18995
19216
  return collisions.sort((a, b) => a.localeCompare(b));
18996
19217
  }
@@ -19000,9 +19221,9 @@ function writeFileMap(targetDir, files) {
19000
19221
  if (!isSafeTemplatePath2(rel)) {
19001
19222
  throw new Error(`Refusing to write unsafe template path: ${rel}`);
19002
19223
  }
19003
- const abs = path24.join(targetDir, rel);
19004
- fs19.mkdirSync(path24.dirname(abs), { recursive: true });
19005
- fs19.writeFileSync(abs, body, "utf-8");
19224
+ const abs = path25.join(targetDir, rel);
19225
+ fs20.mkdirSync(path25.dirname(abs), { recursive: true });
19226
+ fs20.writeFileSync(abs, body, "utf-8");
19006
19227
  written.push(rel);
19007
19228
  }
19008
19229
  return written;
@@ -19010,20 +19231,20 @@ function writeFileMap(targetDir, files) {
19010
19231
  function listDirRelFiles(dir) {
19011
19232
  const out = [];
19012
19233
  function walk(d, prefix) {
19013
- for (const entry of fs19.readdirSync(d, { withFileTypes: true })) {
19234
+ for (const entry of fs20.readdirSync(d, { withFileTypes: true })) {
19014
19235
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
19015
- if (entry.isDirectory()) walk(path24.join(d, entry.name), rel);
19236
+ if (entry.isDirectory()) walk(path25.join(d, entry.name), rel);
19016
19237
  else if (entry.isFile()) out.push(rel);
19017
19238
  }
19018
19239
  }
19019
- if (fs19.existsSync(dir)) walk(dir, "");
19240
+ if (fs20.existsSync(dir)) walk(dir, "");
19020
19241
  return out;
19021
19242
  }
19022
19243
  function writeSliceSnapshot(targetDir, files) {
19023
19244
  const keep = new Set(Object.keys(files));
19024
19245
  const removed = listDirRelFiles(targetDir).filter((rel) => !keep.has(rel)).sort((a, b) => a.localeCompare(b));
19025
19246
  const written = writeFileMap(targetDir, files).sort((a, b) => a.localeCompare(b));
19026
- if (fs19.existsSync(targetDir)) cleanOrphanFiles(targetDir, "", keep);
19247
+ if (fs20.existsSync(targetDir)) cleanOrphanFiles(targetDir, "", keep);
19027
19248
  return { written, removed };
19028
19249
  }
19029
19250
  var init_template_files = __esm({
@@ -19039,7 +19260,7 @@ var templates_exports = {};
19039
19260
  __export(templates_exports, {
19040
19261
  templateCommand: () => templateCommand
19041
19262
  });
19042
- import * as path25 from "path";
19263
+ import * as path26 from "path";
19043
19264
  async function templateCommand(args2) {
19044
19265
  const [sub, ...rest] = args2;
19045
19266
  switch (sub) {
@@ -19155,8 +19376,8 @@ async function runTemplatePull(rest) {
19155
19376
  console.log(`Template "${slug}" has no WayAI slice${hint}`);
19156
19377
  return;
19157
19378
  }
19158
- const targetDir = path25.join(resolveLayout(gitRoot).hubsDir, slug);
19159
- const relTarget = path25.relative(gitRoot, targetDir);
19379
+ const targetDir = path26.join(resolveLayout(gitRoot).hubsDir, slug);
19380
+ const relTarget = path26.relative(gitRoot, targetDir);
19160
19381
  const collisions = detectCollisions(targetDir, detail.files);
19161
19382
  if (dryRun) {
19162
19383
  const planned = Object.keys(detail.files).sort((a, b) => a.localeCompare(b));
@@ -19330,8 +19551,8 @@ var admin_exports = {};
19330
19551
  __export(admin_exports, {
19331
19552
  adminCommand: () => adminCommand
19332
19553
  });
19333
- import * as fs20 from "fs";
19334
- import * as path26 from "path";
19554
+ import * as fs21 from "fs";
19555
+ import * as path27 from "path";
19335
19556
  import * as yaml10 from "js-yaml";
19336
19557
  async function adminCommand(args2) {
19337
19558
  const [group, ...afterGroup] = args2;
@@ -19653,7 +19874,7 @@ async function runArchiveRead(positional, flagArgs) {
19653
19874
  exitOnApiError(err);
19654
19875
  throw err;
19655
19876
  }
19656
- fs20.writeFileSync(outPath, zip);
19877
+ fs21.writeFileSync(outPath, zip);
19657
19878
  console.log(`Wrote ${zip.byteLength} bytes to ${outPath}`);
19658
19879
  return;
19659
19880
  }
@@ -19785,15 +20006,15 @@ function loadTemplateManifest(slug) {
19785
20006
  console.error("Not in a git repository. Run from the tutorials/ authoring repo.");
19786
20007
  process.exit(1);
19787
20008
  }
19788
- const templateDir = path26.join(resolveTemplatesDir(gitRoot), slug);
19789
- const manifestPath = path26.join(templateDir, "template.yaml");
19790
- if (!fs20.existsSync(manifestPath)) {
19791
- console.error(`template.yaml not found at ${path26.relative(gitRoot, manifestPath)}`);
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)}`);
19792
20013
  process.exit(1);
19793
20014
  }
19794
20015
  let manifest;
19795
20016
  try {
19796
- manifest = templateYamlSchema2.parse(yaml10.load(fs20.readFileSync(manifestPath, "utf-8")));
20017
+ manifest = templateYamlSchema2.parse(yaml10.load(fs21.readFileSync(manifestPath, "utf-8")));
19797
20018
  } catch (err) {
19798
20019
  console.error(`Invalid template.yaml: ${err instanceof Error ? err.message : String(err)}`);
19799
20020
  process.exit(1);
@@ -19823,20 +20044,20 @@ async function runTemplatePush(positional) {
19823
20044
  const wayaiEntry = manifest.wayai.locales[locale];
19824
20045
  let wayaiFiles;
19825
20046
  if (wayaiEntry) {
19826
- const sliceDir = path26.resolve(templateDir, wayaiEntry.source);
19827
- if (!fs20.existsSync(sliceDir)) {
20047
+ const sliceDir = path27.resolve(templateDir, wayaiEntry.source);
20048
+ if (!fs21.existsSync(sliceDir)) {
19828
20049
  console.error(`wayai source not found for ${locale}: ${wayaiEntry.source} (resolved ${sliceDir})`);
19829
20050
  process.exit(1);
19830
20051
  }
19831
20052
  if (!isInsideTemplateDir(sliceDir, templateDir)) {
19832
20053
  console.warn(
19833
- `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 ${path26.basename(sliceDir)}\` to commit a stable frozen slice.`
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.`
19834
20055
  );
19835
20056
  }
19836
20057
  wayaiFiles = readDirToFileMap(sliceDir);
19837
20058
  }
19838
- const readmePath = path26.join(templateDir, `README.${locale}.md`);
19839
- const readmeMarkdown = fs20.existsSync(readmePath) ? fs20.readFileSync(readmePath, "utf-8") : "";
20059
+ const readmePath = path27.join(templateDir, `README.${locale}.md`);
20060
+ const readmeMarkdown = fs21.existsSync(readmePath) ? fs21.readFileSync(readmePath, "utf-8") : "";
19840
20061
  locales[locale] = {
19841
20062
  readmeMarkdown,
19842
20063
  ...wayaiFiles && { wayaiFiles },
@@ -19847,9 +20068,9 @@ async function runTemplatePush(positional) {
19847
20068
  }
19848
20069
  let hero;
19849
20070
  if (manifest.hero) {
19850
- const heroPath = path26.resolve(templateDir, manifest.hero);
19851
- if (fs20.existsSync(heroPath)) {
19852
- hero = { filename: path26.basename(heroPath), dataBase64: fs20.readFileSync(heroPath).toString("base64") };
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") };
19853
20074
  } else {
19854
20075
  console.error(`Warning: hero not found at ${manifest.hero}; skipping.`);
19855
20076
  }
@@ -19875,7 +20096,7 @@ async function runTemplatePush(positional) {
19875
20096
  }
19876
20097
  }
19877
20098
  function isInsideTemplateDir(dest, templateDir) {
19878
- return dest === templateDir || dest.startsWith(templateDir + path26.sep);
20099
+ return dest === templateDir || dest.startsWith(templateDir + path27.sep);
19879
20100
  }
19880
20101
  async function runTemplateFreeze(positional, flagArgs) {
19881
20102
  const slug = positional[0];
@@ -19936,7 +20157,7 @@ async function runTemplateFreeze(positional, flagArgs) {
19936
20157
  process.exit(1);
19937
20158
  }
19938
20159
  const entry = manifest.wayai.locales[targetLocale];
19939
- const dest = path26.resolve(templateDir, entry.source);
20160
+ const dest = path27.resolve(templateDir, entry.source);
19940
20161
  if (!isInsideTemplateDir(dest, templateDir) || dest === templateDir) {
19941
20162
  console.error(
19942
20163
  `source for "${targetLocale}" must be a committed path inside ${slug}/ (e.g. "./${targetLocale}/slice"), but resolved to:
@@ -19955,7 +20176,7 @@ Set it to a subdir of the template folder and re-run freeze.`
19955
20176
  const hubs = scanWorkspaceHubs(hubsDir);
19956
20177
  if (hubs.length) {
19957
20178
  console.error("Available hubs:");
19958
- for (const h of hubs) console.error(` ${path26.basename(h.hubFolder)} (${h.hubId})`);
20179
+ for (const h of hubs) console.error(` ${path27.basename(h.hubFolder)} (${h.hubId})`);
19959
20180
  }
19960
20181
  console.error(`
19961
20182
  Pass --from <folder|uuid>${selector ? "." : " or run `wayai use <hub>` first."}`);
@@ -19963,12 +20184,12 @@ Pass --from <folder|uuid>${selector ? "." : " or run `wayai use <hub>` first."}`
19963
20184
  }
19964
20185
  const liveFiles = readDirToFileMap(hubFolder);
19965
20186
  if (Object.keys(liveFiles).length === 0) {
19966
- console.error(`Source hub folder has no files to freeze: ${path26.relative(gitRoot, hubFolder)}`);
20187
+ console.error(`Source hub folder has no files to freeze: ${path27.relative(gitRoot, hubFolder)}`);
19967
20188
  process.exit(1);
19968
20189
  }
19969
20190
  const sanitized = sanitizeWayaiSliceFiles(liveFiles);
19970
- const relDest = path26.relative(gitRoot, dest);
19971
- const relSrc = path26.relative(gitRoot, hubFolder);
20191
+ const relDest = path27.relative(gitRoot, dest);
20192
+ const relSrc = path27.relative(gitRoot, hubFolder);
19972
20193
  if (dryRun) {
19973
20194
  const existing = new Set(listDirRelFiles(dest));
19974
20195
  const nextKeys = new Set(Object.keys(sanitized));
@@ -20028,7 +20249,7 @@ async function runTemplatePull2(positional, flagArgs) {
20028
20249
  console.log(JSON.stringify(detail, null, 2));
20029
20250
  return;
20030
20251
  }
20031
- const target = outDir ? path26.resolve(outDir) : path26.join(process.cwd(), "template-store-pull", slug);
20252
+ const target = outDir ? path27.resolve(outDir) : path27.join(process.cwd(), "template-store-pull", slug);
20032
20253
  const written = writeFileMap(target, detail.files);
20033
20254
  console.log(`Pulled "${slug}" from the store \u2192 ${target} (${written.length} file${written.length === 1 ? "" : "s"}).`);
20034
20255
  const uses = detail.uses ?? [];
@@ -20051,13 +20272,13 @@ async function runSkillInstall(positional) {
20051
20272
  throw err;
20052
20273
  }
20053
20274
  const root = findGitRoot() ?? process.cwd();
20054
- const present = HARNESS_SKILL_DIRS.filter((dir) => fs20.existsSync(path26.join(root, dir)));
20275
+ const present = HARNESS_SKILL_DIRS.filter((dir) => fs21.existsSync(path27.join(root, dir)));
20055
20276
  const targets = present.length > 0 ? present : HARNESS_SKILL_DIRS;
20056
20277
  const fileCount = Object.keys(res.files).length;
20057
20278
  const relDirs = targets.map((harness) => {
20058
- const targetDir = path26.join(root, harness, "skills", name);
20279
+ const targetDir = path27.join(root, harness, "skills", name);
20059
20280
  writeFileMap(targetDir, res.files);
20060
- return `${path26.relative(root, targetDir)}/`;
20281
+ return `${path27.relative(root, targetDir)}/`;
20061
20282
  });
20062
20283
  console.log(`Installed skill "${name}" (${fileCount} file${fileCount === 1 ? "" : "s"}) \u2192 ${relDirs.join(", ")}`);
20063
20284
  console.log("Reload your agent (e.g. restart Claude Code) to pick up the skill.");
@@ -20168,7 +20389,7 @@ async function runSandboxExec(positional, flagArgs) {
20168
20389
  process.exit(data.exit_code);
20169
20390
  }
20170
20391
  }
20171
- function parseScopedTargetFlags(flagArgs, usage2) {
20392
+ function parseScopedTargetFlags(flagArgs, usage3) {
20172
20393
  let all = false;
20173
20394
  let orgId;
20174
20395
  let hubId;
@@ -20203,7 +20424,7 @@ function parseScopedTargetFlags(flagArgs, usage2) {
20203
20424
  }
20204
20425
  if ((all ? 1 : 0) + (orgId ? 1 : 0) + (hubId ? 1 : 0) !== 1) {
20205
20426
  console.error("Provide exactly ONE of --all, --org <org_id>, or --hub <hub_id>.");
20206
- console.error(usage2);
20427
+ console.error(usage3);
20207
20428
  process.exit(1);
20208
20429
  }
20209
20430
  if (all) {
@@ -20309,7 +20530,7 @@ async function runHarnessMassDestroy(flagArgs) {
20309
20530
  );
20310
20531
  }
20311
20532
  }
20312
- function resolveHarnessLayer(flagArgs, usage2) {
20533
+ function resolveHarnessLayer(flagArgs, usage3) {
20313
20534
  let orgId;
20314
20535
  let hubId;
20315
20536
  for (let i = 0; i < flagArgs.length; i++) {
@@ -20323,13 +20544,13 @@ function resolveHarnessLayer(flagArgs, usage2) {
20323
20544
  break;
20324
20545
  default:
20325
20546
  console.error(`Unknown flag: ${arg}`);
20326
- console.error(usage2);
20547
+ console.error(usage3);
20327
20548
  process.exit(1);
20328
20549
  }
20329
20550
  }
20330
20551
  if (orgId && hubId) {
20331
20552
  console.error("Provide at most ONE of --org <org_id> or --hub <hub_id> (or neither for the platform layer).");
20332
- console.error(usage2);
20553
+ console.error(usage3);
20333
20554
  process.exit(1);
20334
20555
  }
20335
20556
  if (orgId) return { kind: "org", orgId };
@@ -21399,7 +21620,7 @@ var init_update = __esm({
21399
21620
 
21400
21621
  // src/index.ts
21401
21622
  init_sentry();
21402
- import { readFileSync as readFileSync18 } from "fs";
21623
+ import { readFileSync as readFileSync19 } from "fs";
21403
21624
  import { fileURLToPath as fileURLToPath2 } from "url";
21404
21625
  import { dirname as dirname9, join as join25 } from "path";
21405
21626
 
@@ -21581,7 +21802,7 @@ Run \`wayai admin skill install\` to update.`);
21581
21802
 
21582
21803
  // src/index.ts
21583
21804
  var __dirname = dirname9(fileURLToPath2(import.meta.url));
21584
- var pkg = JSON.parse(readFileSync18(join25(__dirname, "..", "package.json"), "utf-8"));
21805
+ var pkg = JSON.parse(readFileSync19(join25(__dirname, "..", "package.json"), "utf-8"));
21585
21806
  var [, , command, ...args] = process.argv;
21586
21807
  var isBackgroundRefresh = command === REFRESH_COMMAND;
21587
21808
  if (!isBackgroundRefresh) initSentry(command, pkg.version);
@@ -21826,7 +22047,7 @@ Commands:
21826
22047
  use <hub> Bind this worktree to a specific hub (UUID or folder name)
21827
22048
  migrate Move a legacy repo to the wayai-ws/{hubs,org} layout
21828
22049
  unbind Clear the worktree hub binding
21829
- 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)
21830
22051
  conversations List or inspect conversations
21831
22052
  alerts Show a hub's active connection/credential alerts (run this FIRST when a hub misbehaves)
21832
22053
  analytics Show analytics summary and metrics (use \`analytics query\` for structured ClickHouse queries)