@wayai/cli 0.3.132 → 0.3.134

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
@@ -441,11 +441,11 @@ function captureException2(error, context) {
441
441
  Sentry.captureException(error);
442
442
  });
443
443
  }
444
- function addApiBreadcrumb(method, path30) {
444
+ function addApiBreadcrumb(method, path31) {
445
445
  if (!initialized) return;
446
446
  Sentry.addBreadcrumb({
447
447
  category: "http",
448
- message: `${method} ${path30}`,
448
+ message: `${method} ${path31}`,
449
449
  level: "info"
450
450
  });
451
451
  }
@@ -899,8 +899,8 @@ var init_parseUtil = __esm({
899
899
  init_errors();
900
900
  init_en();
901
901
  makeIssue = (params) => {
902
- const { data, path: path30, errorMaps, issueData } = params;
903
- const fullPath = [...path30, ...issueData.path || []];
902
+ const { data, path: path31, errorMaps, issueData } = params;
903
+ const fullPath = [...path31, ...issueData.path || []];
904
904
  const fullIssue = {
905
905
  ...issueData,
906
906
  path: fullPath
@@ -1211,11 +1211,11 @@ var init_types = __esm({
1211
1211
  init_parseUtil();
1212
1212
  init_util();
1213
1213
  ParseInputLazyPath = class {
1214
- constructor(parent, value, path30, key) {
1214
+ constructor(parent, value, path31, key) {
1215
1215
  this._cachedPath = [];
1216
1216
  this.parent = parent;
1217
1217
  this.data = value;
1218
- this._path = path30;
1218
+ this._path = path31;
1219
1219
  this._key = key;
1220
1220
  }
1221
1221
  get path() {
@@ -4621,6 +4621,70 @@ function normalizeAuthType(raw) {
4621
4621
  function visibleLength(s) {
4622
4622
  return s.replace(INVISIBLE_NAME_CHARS, "").length;
4623
4623
  }
4624
+ function isEventRelativeFollowupType(type) {
4625
+ return typeof type === "string" && EVENT_RELATIVE_FOLLOWUP_TYPES.includes(type);
4626
+ }
4627
+ function validateFollowupLinks(followups, label, ctx) {
4628
+ const linkTargets = /* @__PURE__ */ new Set();
4629
+ followups.forEach((followup, i) => {
4630
+ const ref = followup?.after_followup_id;
4631
+ const path31 = ["followups", i, "after_followup_id"];
4632
+ if (followup?.type !== "inactivity_after_before_event") {
4633
+ if (ref !== void 0) {
4634
+ ctx.addIssue({
4635
+ code: external_exports.ZodIssueCode.custom,
4636
+ path: path31,
4637
+ message: `kanban status ${label}: after_followup_id is only valid on inactivity_after_before_event followups (this one is ${followup?.type})`
4638
+ });
4639
+ }
4640
+ return;
4641
+ }
4642
+ if (ref === void 0) {
4643
+ ctx.addIssue({
4644
+ code: external_exports.ZodIssueCode.custom,
4645
+ path: path31,
4646
+ message: `kanban status ${label}: inactivity_after_before_event requires after_followup_id naming the id of a before_event followup in the same status`
4647
+ });
4648
+ return;
4649
+ }
4650
+ linkTargets.add(ref);
4651
+ const matches = followups.filter((candidate) => candidate?.id === ref);
4652
+ if (matches.length > 1) {
4653
+ ctx.addIssue({
4654
+ code: external_exports.ZodIssueCode.custom,
4655
+ path: path31,
4656
+ message: `kanban status ${label}: after_followup_id "${ref}" matches ${matches.length} followups \u2014 a link must name exactly one`
4657
+ });
4658
+ return;
4659
+ }
4660
+ const target = matches[0];
4661
+ if (!target) {
4662
+ const hasIdlessBeforeEvent = followups.some(
4663
+ (candidate) => candidate?.type === "before_event" && candidate?.id === void 0
4664
+ );
4665
+ ctx.addIssue({
4666
+ code: external_exports.ZodIssueCode.custom,
4667
+ path: path31,
4668
+ message: hasIdlessBeforeEvent ? `kanban status ${label}: after_followup_id "${ref}" matches no followup \u2014 a link target must declare an explicit id, and this status has before_event followups without one` : `kanban status ${label}: after_followup_id "${ref}" matches no followup in this status`
4669
+ });
4670
+ return;
4671
+ }
4672
+ if (target.type !== "before_event") {
4673
+ ctx.addIssue({
4674
+ code: external_exports.ZodIssueCode.custom,
4675
+ path: path31,
4676
+ message: `kanban status ${label}: after_followup_id "${ref}" points at a ${target.type} followup \u2014 only before_event followups can anchor a chain`
4677
+ });
4678
+ }
4679
+ });
4680
+ if (linkTargets.size > MAX_LINKED_FOLLOWUP_TARGETS_PER_STATUS) {
4681
+ ctx.addIssue({
4682
+ code: external_exports.ZodIssueCode.custom,
4683
+ path: ["followups"],
4684
+ message: `kanban status ${label}: at most ${MAX_LINKED_FOLLOWUP_TARGETS_PER_STATUS} distinct after_followup_id targets per status (found ${linkTargets.size}) \u2014 each one rebuilds a chain on every inbound message`
4685
+ });
4686
+ }
4687
+ }
4624
4688
  function validateLaneReferences(lanes, statuses) {
4625
4689
  const issues = [];
4626
4690
  if (!Array.isArray(statuses) || statuses.length === 0) return issues;
@@ -4684,12 +4748,12 @@ function typeMatches(typeField, allowed) {
4684
4748
  if (Array.isArray(typeField)) return typeField.every((t) => typeof t === "string" && allowed.has(t));
4685
4749
  return false;
4686
4750
  }
4687
- function validateSchema(schema, path30, errors, opts = {}) {
4751
+ function validateSchema(schema, path31, errors, opts = {}) {
4688
4752
  if (typeof schema === "boolean") return;
4689
4753
  const depth = opts.depth ?? 0;
4690
4754
  if (depth > MAX_SCHEMA_DEPTH) {
4691
4755
  errors.push({
4692
- path: path30 || "<root>",
4756
+ path: path31 || "<root>",
4693
4757
  message: `schema nesting exceeds ${MAX_SCHEMA_DEPTH} levels`,
4694
4758
  suggestion: "Flatten the schema; LLM providers reject deeply nested tool input_schemas."
4695
4759
  });
@@ -4697,7 +4761,7 @@ function validateSchema(schema, path30, errors, opts = {}) {
4697
4761
  }
4698
4762
  if (!isRecord(schema)) {
4699
4763
  errors.push({
4700
- path: path30,
4764
+ path: path31,
4701
4765
  message: `expected object, got ${schema === null ? "null" : typeof schema}`
4702
4766
  });
4703
4767
  return;
@@ -4705,14 +4769,14 @@ function validateSchema(schema, path30, errors, opts = {}) {
4705
4769
  if (opts.isRoot) {
4706
4770
  if ("type" in schema && schema.type !== "object") {
4707
4771
  errors.push({
4708
- path: path30 ? `${path30}.type` : "type",
4772
+ path: path31 ? `${path31}.type` : "type",
4709
4773
  message: `root type must be 'object', got ${JSON.stringify(schema.type)}`,
4710
4774
  suggestion: "Tool parameters at the root must be an object: `{ type: 'object', properties: { ... } }`."
4711
4775
  });
4712
4776
  }
4713
4777
  } else if ("type" in schema && !typeMatches(schema.type, ALLOWED_TYPES)) {
4714
4778
  errors.push({
4715
- path: `${path30}.type`,
4779
+ path: `${path31}.type`,
4716
4780
  message: `type must be one of ${[...ALLOWED_TYPES].join("/")} or an array of those, got ${JSON.stringify(schema.type)}`
4717
4781
  });
4718
4782
  }
@@ -4722,25 +4786,25 @@ function validateSchema(schema, path30, errors, opts = {}) {
4722
4786
  const isPlaceholder = PLACEHOLDER_TOKENS.includes(e);
4723
4787
  const isOutcomePlaceholder = e === "[KANBAN_OUTCOME_VALUES]";
4724
4788
  errors.push({
4725
- path: `${path30}.enum`,
4789
+ path: `${path31}.enum`,
4726
4790
  message: `enum must be a non-empty array of primitives, got string ${JSON.stringify(e)}`,
4727
4791
  suggestion: isOutcomePlaceholder ? "Declare `outcomes` on the hub's terminal kanban status so the platform can render the placeholder into a valid array; with none configured the platform drops the parameter instead." : 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"]`.'
4728
4792
  });
4729
4793
  } else if (!Array.isArray(e)) {
4730
4794
  errors.push({
4731
- path: `${path30}.enum`,
4795
+ path: `${path31}.enum`,
4732
4796
  message: `enum must be a non-empty array of primitives, got ${typeof e}`
4733
4797
  });
4734
4798
  } else if (e.length === 0) {
4735
4799
  errors.push({
4736
- path: `${path30}.enum`,
4800
+ path: `${path31}.enum`,
4737
4801
  message: "enum must not be empty"
4738
4802
  });
4739
4803
  } else {
4740
4804
  for (let i = 0; i < e.length; i++) {
4741
4805
  if (!isPrimitive(e[i])) {
4742
4806
  errors.push({
4743
- path: `${path30}.enum[${i}]`,
4807
+ path: `${path31}.enum[${i}]`,
4744
4808
  message: `enum entry must be a primitive (string/number/boolean/null), got ${typeof e[i]}`
4745
4809
  });
4746
4810
  }
@@ -4750,7 +4814,7 @@ function validateSchema(schema, path30, errors, opts = {}) {
4750
4814
  for (const key of ["exclusiveMinimum", "exclusiveMaximum"]) {
4751
4815
  if (key in schema && typeof schema[key] === "boolean") {
4752
4816
  errors.push({
4753
- path: `${path30}.${key}`,
4817
+ path: `${path31}.${key}`,
4754
4818
  message: `${key} as boolean is draft-04 syntax; draft 2020-12 requires a numeric value`,
4755
4819
  suggestion: `Replace with the numeric bound, e.g. \`${key}: 0\`.`
4756
4820
  });
@@ -4759,45 +4823,45 @@ function validateSchema(schema, path30, errors, opts = {}) {
4759
4823
  if ("properties" in schema) {
4760
4824
  if (!isRecord(schema.properties)) {
4761
4825
  errors.push({
4762
- path: `${path30}.properties`,
4826
+ path: `${path31}.properties`,
4763
4827
  message: `properties must be an object, got ${Array.isArray(schema.properties) ? "array" : typeof schema.properties}`
4764
4828
  });
4765
4829
  } else {
4766
4830
  for (const [propName, propSchema] of Object.entries(schema.properties)) {
4767
- validateSchema(propSchema, `${path30}.properties.${propName}`, errors, { depth: depth + 1 });
4831
+ validateSchema(propSchema, `${path31}.properties.${propName}`, errors, { depth: depth + 1 });
4768
4832
  }
4769
4833
  }
4770
4834
  }
4771
4835
  if (schemaTypeIncludes(schema, "array") && "items" in schema) {
4772
4836
  if (Array.isArray(schema.items)) {
4773
- schema.items.forEach((sub, i) => validateSchema(sub, `${path30}.items[${i}]`, errors, { depth: depth + 1 }));
4837
+ schema.items.forEach((sub, i) => validateSchema(sub, `${path31}.items[${i}]`, errors, { depth: depth + 1 }));
4774
4838
  } else {
4775
- validateSchema(schema.items, `${path30}.items`, errors, { depth: depth + 1 });
4839
+ validateSchema(schema.items, `${path31}.items`, errors, { depth: depth + 1 });
4776
4840
  }
4777
4841
  }
4778
4842
  for (const key of SUBSCHEMA_OBJECT_KEYWORDS) {
4779
4843
  if (key in schema && isRecord(schema[key])) {
4780
- validateSchema(schema[key], `${path30}.${key}`, errors, { depth: depth + 1 });
4844
+ validateSchema(schema[key], `${path31}.${key}`, errors, { depth: depth + 1 });
4781
4845
  }
4782
4846
  }
4783
4847
  for (const key of SUBSCHEMA_LIST_KEYWORDS) {
4784
4848
  const list = schema[key];
4785
4849
  if (Array.isArray(list)) {
4786
- list.forEach((sub, i) => validateSchema(sub, `${path30}.${key}[${i}]`, errors, { depth: depth + 1 }));
4850
+ list.forEach((sub, i) => validateSchema(sub, `${path31}.${key}[${i}]`, errors, { depth: depth + 1 }));
4787
4851
  }
4788
4852
  }
4789
4853
  for (const key of SUBSCHEMA_MAP_KEYWORDS) {
4790
4854
  const map = schema[key];
4791
4855
  if (isRecord(map)) {
4792
4856
  for (const [name, sub] of Object.entries(map)) {
4793
- validateSchema(sub, `${path30}.${key}.${name}`, errors, { depth: depth + 1 });
4857
+ validateSchema(sub, `${path31}.${key}.${name}`, errors, { depth: depth + 1 });
4794
4858
  }
4795
4859
  }
4796
4860
  }
4797
4861
  const reportedPaths = new Set(errors.map((e) => e.path));
4798
4862
  for (const [k, v] of Object.entries(schema)) {
4799
4863
  if (typeof v !== "string") continue;
4800
- const fieldPath = `${path30}.${k}`;
4864
+ const fieldPath = `${path31}.${k}`;
4801
4865
  if (reportedPaths.has(fieldPath)) continue;
4802
4866
  for (const token of PLACEHOLDER_TOKENS) {
4803
4867
  if (v === token) {
@@ -4942,8 +5006,8 @@ function evalInitialStateError(input) {
4942
5006
  const parsed = evalInitialStateEntry.safeParse(entries[i]);
4943
5007
  if (!parsed.success) {
4944
5008
  const issue = parsed.error.issues[0];
4945
- const path30 = issue?.path.join(".") || "?";
4946
- return `initial_state[${i}].${path30} is invalid: ${issue?.message ?? "malformed"}`;
5009
+ const path31 = issue?.path.join(".") || "?";
5010
+ return `initial_state[${i}].${path31} is invalid: ${issue?.message ?? "malformed"}`;
4947
5011
  }
4948
5012
  if (seenSlugs.has(parsed.data.slug)) {
4949
5013
  return `initial_state[${i}].slug "${parsed.data.slug}" is declared more than once`;
@@ -5131,10 +5195,10 @@ function refineHubAsCodeEvals(config, ctx) {
5131
5195
  function refineHubAsCodeEvalAttachments(config, ctx) {
5132
5196
  const cfg = config;
5133
5197
  const referencedHashes = /* @__PURE__ */ new Set();
5134
- const addTurnIssue = (path30, turn, name) => {
5198
+ const addTurnIssue = (path31, turn, name) => {
5135
5199
  const error = evalTurnAttachmentsError(turn);
5136
5200
  if (error) {
5137
- ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: path30, message: `${name}: ${error}` });
5201
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: path31, message: `${name}: ${error}` });
5138
5202
  return;
5139
5203
  }
5140
5204
  for (const hash of collectTurnAttachmentHashes(turn)) referencedHashes.add(hash);
@@ -5280,11 +5344,11 @@ function refineHubAsCodeDelegation(config, ctx) {
5280
5344
  }
5281
5345
  }
5282
5346
  if (del.context_boundary === void 0) return;
5283
- const path30 = ["agents", agentIndex, "tools", "delegation", delIndex, "context_boundary"];
5347
+ const path31 = ["agents", agentIndex, "tools", "delegation", delIndex, "context_boundary"];
5284
5348
  if (del.type !== "hub") {
5285
5349
  ctx.addIssue({
5286
5350
  code: external_exports.ZodIssueCode.custom,
5287
- path: path30,
5351
+ path: path31,
5288
5352
  message: `context_boundary applies only to \`type: hub\` delegations (got type "${String(del.type)}")`
5289
5353
  });
5290
5354
  return;
@@ -5292,14 +5356,14 @@ function refineHubAsCodeDelegation(config, ctx) {
5292
5356
  if (!CONTEXT_BOUNDARIES.includes(del.context_boundary)) {
5293
5357
  ctx.addIssue({
5294
5358
  code: external_exports.ZodIssueCode.custom,
5295
- path: path30,
5359
+ path: path31,
5296
5360
  message: `context_boundary must be one of: ${CONTEXT_BOUNDARIES.join(", ")}`
5297
5361
  });
5298
5362
  }
5299
5363
  });
5300
5364
  });
5301
5365
  }
5302
- var uuidSchema, paginationSchema, timestampSchema, idParamSchema, clientOptionalString, clientOptionalBoolean, clientOptionalNumber, messageAttachment, MAX_MESSAGE_BODY_BYTES, MAX_ATTACHMENTS_PER_MESSAGE, MAX_AUDIO_FILE_BASE64_BYTES, primaryRegionSchema, placementSourceSchema, orgIdParam, orgAdminIdParam, createOrganizationBody, updateOrganizationBody, addOrgAdminBody, AUTH_TYPE, ORG_CREDENTIAL_AUTH_TYPES, AUTH_TYPE_DISPLAY, LEGACY_AUTH_TYPE_MAP, VALID_AUTH_TYPES, AGENT_ROLES, SAFE_USER_ID_REGEX, SUPPORTED_LOCALES, SUMMARIZATION_THRESHOLD_MIN, SUMMARIZATION_THRESHOLD_MAX, PREVIOUS_CONVERSATIONS_MAX, previousConversationsCountField, 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, MAX_OUTCOMES_PER_STATUS, kanbanOutcomeSchema, 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, CONTEXT_BOUNDARIES, contextBoundarySchema, 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, analyticsSqlTable, analyticsSqlSchemaQuery, EVAL_PACING_PRESET_NAMES, PACING_INTERVAL_MIN_MS, PACING_INTERVAL_MAX_MS, EVAL_MAX_RUNS_PER_SCENARIO, EVAL_RUN_DEADLINE_MIN_MS, EVAL_RUN_DEADLINE_MAX_MS, ISO_UTC_RE, paginationSchema2, evalIdParam, sessionIdParam, scenarioSetIdParam, hubIdQuery, evalDateContextSchema, EVAL_FIXTURE_NAME_MAX_LENGTH, evalFixtureOverrideSchema, runSessionQuery, EVAL_INPUT_ROLES, EVAL_INPUT_ROLE_LIST, ROLE_ECHO_MAX, EVAL_INITIAL_STATE_SCOPES, MAX_INITIAL_STATE_ENTRIES, evalInitialStateEntry, createEvalBody, updateEvalBody, getEvalsQuery, toggleEvalBody, bulkToggleEvalsBody, pacingConfigSchema, EVAL_MAX_SELECTED_SCENARIOS, evalScenarioSelectionEntrySchema, evalScenarioSelectionSchema, sessionConfigSchema, createSessionBody, getSessionsQuery, getSessionResultsQuery, getSessionRunsQuery, evalAnalyticsQuery, getSessionCostQuery, compareSessionsQuery, evalsSqlBody, evalsSqlSchemaQuery, exportResultsQuery, validateEvalBody, hubAgentsQuery, createScenarioSetBody, updateScenarioSetBody, scenarioSetsHubQuery, createScenarioFromConversationBody, createJourneyFromConversationBody, EVAL_ATTACHMENT_HASH_REGEX, evalAttachmentRef, turnMayCarryAttachments, ATTACHMENTS_USER_ONLY_MESSAGE, journeyIdParam, journeyToolCallSchema, journeyTurnSchema, journeyStepOverrideSchema, fixtureField, createJourneyBody, updateJourneyBody, evalSessionConfigResponseSchema, evalSessionResponseSchema, seedReleaseStatusSchema, EVAL_SESSION_NOT_QUIESCENT, getConversationsQuery, getMessagesQuery, appMessageSenderType, appMessageReceiverType, apiChannelMessage, apiChannelMessageBody, appMessageBody, appMessageResponse, updateUserBody, updateProfileBody, pathnameRegex, updatePreferencesBody, registerPushTokenBody, deletePushTokenQuery, activityQuery, deletionModeSchema, deletionRequestBody, archiveHubIdParam, archiveConversationParams, archiveListQuery, archiveMessageObservabilityParams, conversationIdParam, claimBody, releaseBody, transferBody, closeBody, additionalContextPayloadSchema, kanbanUpdateBody, annotateConversationBody, observabilityParams, observabilityListParams, deleteUserConversationsBody, deleteUserConversationsResponse, sendMessageBody, listConversationsQuery, flagSourceSchema, getConversationsResponse, getConversationDetailParams, getConversationDetailQuery, getConversationDetailResponse, listWhatsAppTemplatesQuery, sendWhatsAppTemplateBody, copilotSuggestBody, copilotSuggestResponse, CONSULT_THREAD_STATUSES, consultThreadStatus, CONSULT_THREAD_TITLE_MAX, consultThreadTitle, consultThreadSummary, listConsultThreadsQuery, listConsultThreadsResponse, createConsultThreadBody, createConsultThreadResponse, consultThreadIdParam, updateConsultThreadBody, updateConsultThreadResponse, CONSULT_AWAIT_TIMEOUT_MS, 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, MAX_RESOURCE_FILE_SIZE, MAX_10MB_BASE64_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_CARRIERS, MAX_EVAL_ATTACHMENT_AGGREGATE_ENCODED_BYTES, MAX_RESOURCE_ENCODED_BYTES, MAX_HUB_AS_CODE_RESOURCES, MAX_HUB_AS_CODE_RESOURCE_FILES, MAX_RESOURCE_AGGREGATE_ENCODED_BYTES, MAX_CI_CONFIG_BODY_BYTES, hubAsCodeStateSchema, hubAsCodeResourceFileSchema, hubAsCodeResourceSchema, uuidPattern, ciUuidSchema, boundedHubAsCodeResourcesSchema, hubAsCodeConfigSchema, ciPullHubIdParam, ciBranchParam, ciPullQuery, ciHubsQuery, ciLookupQuery, ciBranchesQuery, ciSyncBody, ciPushBody, ciDiffBody, ciPublishBody, ciPublishPreviewBody, ciSyncMcpBody, ciOrgResourcesParam, orgResourcesConfigSchema, ciOrgResourcesPushBody, ciOrgResourcesDiffBody, CI_APPLY_ENTITY_KINDS, CI_APPLY_OPERATIONS, ciApplyErrorBaseSchema, ciApplyErrorSchema, ciSyncCountSchema, ciSyncChangesSchema, ciSyncWarningSchema, ciSyncResponseSchema, adminOrgIdParam, adminOrgAdminIdParam, adminUserIdParam, adminPlanIdParam, adminOrganizationsQuery, adminUserSearchQuery, kanbanSlugMigrationQuery, adjustQuotaBody, updatePlanBody, addAdminUserBody, updatePlatformConfigBody, updateFreeOrgLimitBody, adminScopedTargetBody, updatePricingPlanBody, dataExplorerSearchQuery, dataExplorerOrgIdParam, dataExplorerHubIdParam, dataExplorerConvIdParam, dataExplorerDoInstancesQuery, dataExplorerNsIdParam, dataExplorerKvKeysBody, dataExplorerKvKeyBody, uuidOrHexId, dataExplorerDeleteOrgParam, dataExplorerDeleteHubParam, dataExplorerDeleteConvParam, dataExplorerDeleteUserParam, dataExplorerDeleteQuery, dataExplorerKvDeleteBody, 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, passwordLoginBody, browserParams, browserFoldersQuery, browserFilesQuery, stateOperationBody, conversationListResourcesQuery, conversationReadResourceQuery, listPendingSchedulesQuery, listHubAggregateSchedulesQuery, reportSourceSchema, intakeReportSourceSchema, reportClassificationSchema, reportStatusSchema, reportLocaleSchema, reportMessageAuthorRoleSchema, reportMessageSchema, sentryRefStatusSchema, createReportBody, editReportBody, reporterReportSummarySchema, reporterListResponseSchema, getReportResponseSchema, reporterTransitionResponseSchema, 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, jsonSchemaSchema, hubUserIdentity, stateValueEntry, getHubUserContextResponse, updateHubUserBody, updateHubUserResponse, unlockHubUserNameResponse, stateResetParams, stateResetResponse, hubAlertsParam, hubAlertSeverity, hubAlert, hubAlertsListResponse, noticeSeveritySchema, noticeStatusSchema, NOTICE_SCOPE_REGEX, noticeScopeSchema, noticeLinkSchema, createNoticeBody, updateNoticeBody, listNoticesQuery, noticeIdParamSchema, ADMIN_SKILL_NAME_REGEX, adminSkillNameParam;
5366
+ var uuidSchema, paginationSchema, timestampSchema, idParamSchema, clientOptionalString, clientOptionalBoolean, clientOptionalNumber, messageAttachment, MAX_MESSAGE_BODY_BYTES, MAX_ATTACHMENTS_PER_MESSAGE, MAX_AUDIO_FILE_BASE64_BYTES, primaryRegionSchema, placementSourceSchema, orgIdParam, orgAdminIdParam, createOrganizationBody, updateOrganizationBody, addOrgAdminBody, AUTH_TYPE, ORG_CREDENTIAL_AUTH_TYPES, AUTH_TYPE_DISPLAY, LEGACY_AUTH_TYPE_MAP, VALID_AUTH_TYPES, AGENT_ROLES, SAFE_USER_ID_REGEX, SUPPORTED_LOCALES, SUMMARIZATION_THRESHOLD_MIN, SUMMARIZATION_THRESHOLD_MAX, PREVIOUS_CONVERSATIONS_MAX, previousConversationsCountField, 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, followupTypeSchema, EVENT_RELATIVE_FOLLOWUP_TYPES, followupTimeUnitSchema, followupIdSchema, SELECTABLE_FOLLOWUP_TYPES, MAX_LINKED_FOLLOWUP_TARGETS_PER_STATUS, followupSchema, MAX_OUTCOMES_PER_STATUS, kanbanOutcomeSchema, EXCLUSIVE_FLAG_PAIRS, kanbanStatusSchema, kanbanStatusesArraySchema, laneSchema, lanesArraySchema, hubIdParam, hubAdminIdParam, hubUserIdParam, hubIdentityIdParam, hubTeamIdParam, hubTeamUserDeleteParam, hubSchemaQuery, PREVIEW_LABEL_MAX_LENGTH, MAX_ENDED_INDEX_RETENTION_DAYS, MAX_EVAL_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, CONTEXT_BOUNDARIES, contextBoundarySchema, 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, analyticsSqlTable, analyticsSqlSchemaQuery, EVAL_PACING_PRESET_NAMES, PACING_INTERVAL_MIN_MS, PACING_INTERVAL_MAX_MS, EVAL_MAX_RUNS_PER_SCENARIO, EVAL_RUN_DEADLINE_MIN_MS, EVAL_RUN_DEADLINE_MAX_MS, ISO_UTC_RE, paginationSchema2, evalIdParam, sessionIdParam, scenarioSetIdParam, hubIdQuery, evalDateContextSchema, EVAL_FIXTURE_NAME_MAX_LENGTH, evalFixtureOverrideSchema, runSessionQuery, EVAL_INPUT_ROLES, EVAL_INPUT_ROLE_LIST, ROLE_ECHO_MAX, EVAL_INITIAL_STATE_SCOPES, MAX_INITIAL_STATE_ENTRIES, evalInitialStateEntry, createEvalBody, updateEvalBody, EVAL_LIST_MAX_LIMIT, evalListLimit, getEvalsQuery, toggleEvalBody, bulkToggleEvalsBody, pacingConfigSchema, EVAL_MAX_SELECTED_SCENARIOS, evalScenarioSelectionEntrySchema, evalScenarioSelectionSchema, sessionConfigSchema, createSessionBody, getSessionsQuery, getSessionResultsQuery, getSessionRunsQuery, evalAnalyticsQuery, getSessionCostQuery, compareSessionsQuery, evalsSqlBody, evalsSqlSchemaQuery, exportResultsQuery, validateEvalBody, hubAgentsQuery, createScenarioSetBody, updateScenarioSetBody, scenarioSetsHubQuery, createScenarioFromConversationBody, createJourneyFromConversationBody, EVAL_ATTACHMENT_HASH_REGEX, evalAttachmentRef, turnMayCarryAttachments, ATTACHMENTS_USER_ONLY_MESSAGE, journeyIdParam, journeyToolCallSchema, journeyTurnSchema, journeyStepOverrideSchema, fixtureField, createJourneyBody, updateJourneyBody, evalSessionConfigResponseSchema, evalSessionResponseSchema, evalSessionListConfigSchema, evalSessionListItemSchema, seedReleaseStatusSchema, EVAL_SESSION_NOT_QUIESCENT, getConversationsQuery, getMessagesQuery, appMessageSenderType, appMessageReceiverType, apiChannelMessage, apiChannelMessageBody, appMessageBody, appMessageResponse, updateUserBody, updateProfileBody, pathnameRegex, updatePreferencesBody, registerPushTokenBody, deletePushTokenQuery, activityQuery, deletionModeSchema, deletionRequestBody, archiveHubIdParam, archiveConversationParams, archiveListQuery, archiveMessageObservabilityParams, conversationIdParam, claimBody, releaseBody, transferBody, closeBody, additionalContextPayloadSchema, kanbanUpdateBody, annotateConversationBody, observabilityParams, observabilityListParams, deleteUserConversationsBody, deleteUserConversationsResponse, sendMessageBody, listConversationsQuery, flagSourceSchema, getConversationsResponse, getConversationDetailParams, getConversationDetailQuery, getConversationDetailResponse, listWhatsAppTemplatesQuery, sendWhatsAppTemplateBody, copilotSuggestBody, copilotSuggestResponse, CONSULT_THREAD_STATUSES, consultThreadStatus, CONSULT_THREAD_TITLE_MAX, consultThreadTitle, consultThreadSummary, listConsultThreadsQuery, listConsultThreadsResponse, createConsultThreadBody, createConsultThreadResponse, consultThreadIdParam, updateConsultThreadBody, updateConsultThreadResponse, CONSULT_AWAIT_TIMEOUT_MS, 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, MAX_RESOURCE_FILE_SIZE, MAX_10MB_BASE64_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_CARRIERS, MAX_EVAL_ATTACHMENT_AGGREGATE_ENCODED_BYTES, MAX_RESOURCE_ENCODED_BYTES, MAX_HUB_AS_CODE_RESOURCES, MAX_HUB_AS_CODE_RESOURCE_FILES, MAX_RESOURCE_AGGREGATE_ENCODED_BYTES, MAX_CI_CONFIG_BODY_BYTES, hubAsCodeStateSchema, hubAsCodeResourceFileSchema, hubAsCodeResourceSchema, uuidPattern, ciUuidSchema, boundedHubAsCodeResourcesSchema, hubAsCodeConfigSchema, ciPullHubIdParam, ciBranchParam, ciPullQuery, ciHubsQuery, ciLookupQuery, ciBranchesQuery, ciSyncBody, ciPushBody, ciDiffBody, ciPublishBody, ciPublishPreviewBody, ciSyncMcpBody, ciOrgResourcesParam, orgResourcesConfigSchema, ciOrgResourcesPushBody, ciOrgResourcesDiffBody, CI_APPLY_ENTITY_KINDS, CI_APPLY_OPERATIONS, ciApplyErrorBaseSchema, ciApplyErrorSchema, ciSyncCountSchema, ciSyncChangesSchema, ciSyncWarningSchema, ciSyncResponseSchema, adminOrgIdParam, adminOrgAdminIdParam, adminUserIdParam, adminPlanIdParam, adminOrganizationsQuery, adminUserSearchQuery, kanbanSlugMigrationQuery, adjustQuotaBody, updatePlanBody, addAdminUserBody, updatePlatformConfigBody, updateFreeOrgLimitBody, adminScopedTargetBody, updatePricingPlanBody, dataExplorerSearchQuery, dataExplorerOrgIdParam, dataExplorerHubIdParam, dataExplorerConvIdParam, dataExplorerDoInstancesQuery, dataExplorerNsIdParam, dataExplorerKvKeysBody, dataExplorerKvKeyBody, uuidOrHexId, dataExplorerDeleteOrgParam, dataExplorerDeleteHubParam, dataExplorerDeleteConvParam, dataExplorerDeleteUserParam, dataExplorerDeleteQuery, dataExplorerKvDeleteBody, 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, passwordLoginBody, browserParams, browserFoldersQuery, browserFilesQuery, stateOperationBody, conversationListResourcesQuery, conversationReadResourceQuery, listPendingSchedulesQuery, listHubAggregateSchedulesQuery, reportSourceSchema, intakeReportSourceSchema, reportClassificationSchema, reportStatusSchema, reportLocaleSchema, reportMessageAuthorRoleSchema, reportMessageSchema, sentryRefStatusSchema, createReportBody, editReportBody, reporterReportSummarySchema, reporterListResponseSchema, getReportResponseSchema, reporterTransitionResponseSchema, 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, jsonSchemaSchema, hubUserIdentity, stateValueEntry, getHubUserContextResponse, updateHubUserBody, updateHubUserResponse, unlockHubUserNameResponse, stateResetParams, stateResetResponse, hubAlertsParam, hubAlertSeverity, hubAlert, hubAlertsListResponse, noticeSeveritySchema, noticeStatusSchema, NOTICE_SCOPE_REGEX, noticeScopeSchema, noticeLinkSchema, createNoticeBody, updateNoticeBody, listNoticesQuery, noticeIdParamSchema, ADMIN_SKILL_NAME_REGEX, adminSkillNameParam, REKOR_ACTOR_TYPE_HEADER, REKOR_ACTOR_ID_HEADER, REKOR_ACTOR_LABEL_HEADER, REKOR_ACTOR_ORG_HEADER, REKOR_ACTOR_ADMIN_HEADER, REKOR_CLIENT_HEADER, REKOR_TOOL_ID_HEADER, REKOR_CLIENTS, rekorClientSchema, MAX_REKOR_TOOL_ID_LENGTH, rekorToolIdSchema, DATA_PROXY_MOUNT, DATA_PROXY_PREFIX, REKOR_V1_PREFIX, DATA_PROXY_ORG_QUERY_PARAM, dataProxyQuery, rekorAttestation, REQUIRED_REKOR_ATTESTATION_HEADERS;
5303
5367
  var init_contracts = __esm({
5304
5368
  "../../packages/core/dist/contracts/index.js"() {
5305
5369
  "use strict";
@@ -5351,6 +5415,7 @@ var init_contracts = __esm({
5351
5415
  init_zod();
5352
5416
  init_zod();
5353
5417
  init_zod();
5418
+ init_zod();
5354
5419
  uuidSchema = external_exports.string().uuid();
5355
5420
  paginationSchema = external_exports.object({
5356
5421
  limit: external_exports.coerce.number().int().min(1).max(100).default(50),
@@ -5547,12 +5612,28 @@ var init_contracts = __esm({
5547
5612
  MAX_ADDITIONAL_CONTEXT_SCHEMA_BYTES = 16384;
5548
5613
  RESERVED_TEMPLATE_DUMP_NAME = "additional_data";
5549
5614
  kanbanStatusSlugSchema = slugSchema;
5615
+ followupTypeSchema = external_exports.enum([
5616
+ "inactivity",
5617
+ "before_event",
5618
+ "inactivity_after_event",
5619
+ "inactivity_after_before_event"
5620
+ ]);
5621
+ EVENT_RELATIVE_FOLLOWUP_TYPES = [
5622
+ "before_event",
5623
+ "inactivity_after_event",
5624
+ "inactivity_after_before_event"
5625
+ ];
5626
+ followupTimeUnitSchema = external_exports.enum(["seconds", "minutes", "hours", "days"]);
5627
+ followupIdSchema = external_exports.string().min(1, "must not be empty").refine((v) => v === v.trim(), "must not have leading or trailing whitespace");
5628
+ SELECTABLE_FOLLOWUP_TYPES = followupTypeSchema.options;
5629
+ MAX_LINKED_FOLLOWUP_TARGETS_PER_STATUS = 5;
5550
5630
  followupSchema = external_exports.object({
5551
- id: external_exports.string().optional(),
5631
+ /** Optional author-supplied identifier; also the `after_followup_id` link target. */
5632
+ id: followupIdSchema.optional(),
5552
5633
  order: external_exports.number().int().nonnegative(),
5553
- type: external_exports.enum(["inactivity", "before_event"]),
5634
+ type: followupTypeSchema,
5554
5635
  threshold: external_exports.number().int().positive(),
5555
- timeUnit: external_exports.enum(["seconds", "minutes", "hours", "days"]),
5636
+ timeUnit: followupTimeUnitSchema,
5556
5637
  instructions: external_exports.string().optional(),
5557
5638
  excludedWeekDays: external_exports.array(external_exports.number().int().min(0).max(6)).optional(),
5558
5639
  excludeHolidays: external_exports.boolean().optional(),
@@ -5562,7 +5643,15 @@ var init_contracts = __esm({
5562
5643
  direct_text: external_exports.string().optional(),
5563
5644
  template_whatsapp_id: external_exports.string().nullable().optional(),
5564
5645
  outside_window_policy: external_exports.enum(["route_to_team", "skip"]).optional(),
5565
- include_tools: external_exports.boolean().optional()
5646
+ include_tools: external_exports.boolean().optional(),
5647
+ /**
5648
+ * The `before_event` followup whose fire anchors this chain — its `id`, in
5649
+ * the same status. One name, one meaning, contract and schedule column
5650
+ * alike: "the followup whose fire anchors this chain". Required on
5651
+ * `inactivity_after_before_event`, forbidden on every other type; both are
5652
+ * enforced per status, where the sibling followups are visible.
5653
+ */
5654
+ after_followup_id: followupIdSchema.optional()
5566
5655
  }).passthrough().superRefine((followup, ctx) => {
5567
5656
  if (followup.delivery_mode === "direct" && !followup.direct_text?.trim()) {
5568
5657
  ctx.addIssue({
@@ -5651,12 +5740,20 @@ var init_contracts = __esm({
5651
5740
  message: `kanban status ${label}: event_due_delay_minutes requires isSchedulingStatus=true`
5652
5741
  });
5653
5742
  }
5654
- if (Array.isArray(status.followups) && status.followups.some((f) => f?.type === "before_event") && status.isSchedulingStatus !== true) {
5655
- ctx.addIssue({
5656
- code: external_exports.ZodIssueCode.custom,
5657
- path: ["followups"],
5658
- message: `kanban status ${label}: before_event followups require isSchedulingStatus=true on the parent status`
5659
- });
5743
+ if (Array.isArray(status.followups) && status.isSchedulingStatus !== true) {
5744
+ const offending = status.followups.find(
5745
+ (f) => isEventRelativeFollowupType(f?.type)
5746
+ );
5747
+ if (offending) {
5748
+ ctx.addIssue({
5749
+ code: external_exports.ZodIssueCode.custom,
5750
+ path: ["followups"],
5751
+ message: `kanban status ${label}: ${offending.type} followups require isSchedulingStatus=true on the parent status`
5752
+ });
5753
+ }
5754
+ }
5755
+ if (Array.isArray(status.followups)) {
5756
+ validateFollowupLinks(status.followups, label, ctx);
5660
5757
  }
5661
5758
  if (status.additional_context_schema && typeof status.additional_context_schema === "object") {
5662
5759
  const schema = status.additional_context_schema;
@@ -5813,6 +5910,7 @@ var init_contracts = __esm({
5813
5910
  hubSchemaQuery = external_exports.object({ hub_id: uuidSchema });
5814
5911
  PREVIEW_LABEL_MAX_LENGTH = 60;
5815
5912
  MAX_ENDED_INDEX_RETENTION_DAYS = 730;
5913
+ MAX_EVAL_RETENTION_DAYS = 3650;
5816
5914
  previewLabelField = external_exports.string().max(PREVIEW_LABEL_MAX_LENGTH).optional().nullable().transform((v) => {
5817
5915
  if (v == null) return null;
5818
5916
  const trimmed = v.trim();
@@ -5848,6 +5946,10 @@ var init_contracts = __esm({
5848
5946
  // the cleanup cron reaps its index row. Absent → DEFAULT_ENDED_INDEX_RETENTION_DAYS
5849
5947
  // (365). Re-clamped to the effective storage retention at reap time.
5850
5948
  ended_index_retention_days: external_exports.number().int().min(1).max(MAX_ENDED_INDEX_RETENTION_DAYS).optional(),
5949
+ // Per-hub eval-session retention window (days). null CLEARS the override (back to
5950
+ // the platform default); 0 disables retention for this hub (keep sessions forever).
5951
+ // Nullable — unlike the fields above, "unset" is a meaningful, settable state.
5952
+ eval_retention_days: external_exports.number().int().min(0).max(MAX_EVAL_RETENTION_DAYS).nullable().optional(),
5851
5953
  // Channel contact access control. Enum-validated explicitly (not via passthrough)
5852
5954
  // so `language`/`access_approval_role` can't reach the DB with an invalid value.
5853
5955
  language: external_exports.enum(["en", "pt", "es"]).optional(),
@@ -6330,8 +6432,9 @@ var init_contracts = __esm({
6330
6432
  file_metadata_schema: external_exports.record(external_exports.unknown()).optional(),
6331
6433
  skill_name: external_exports.string().optional(),
6332
6434
  skill_version: external_exports.string().optional(),
6333
- anthropic_skill_id: external_exports.string().optional(),
6334
- anthropic_version: external_exports.string().optional(),
6435
+ // No `anthropic_skill_id`/`anthropic_version`: `resource` has neither column.
6436
+ // The provider link lives on `resource_provider_sync.provider_skill_id`,
6437
+ // written by `skillSync.ts` — never through this body.
6335
6438
  user_browsable: external_exports.boolean().optional()
6336
6439
  });
6337
6440
  syncSkillsBody = external_exports.object({
@@ -6427,7 +6530,6 @@ var init_contracts = __esm({
6427
6530
  agent_id: uuidSchema,
6428
6531
  priority: external_exports.number().optional(),
6429
6532
  use_native_integration: external_exports.boolean().optional(),
6430
- include_structure_in_prompt: external_exports.boolean().optional(),
6431
6533
  write_enabled: external_exports.boolean().optional()
6432
6534
  });
6433
6535
  updateAgentResourceBody = external_exports.object({
@@ -6435,7 +6537,6 @@ var init_contracts = __esm({
6435
6537
  resource_id: uuidSchema,
6436
6538
  agent_id: uuidSchema,
6437
6539
  use_native_integration: external_exports.boolean().optional(),
6438
- include_structure_in_prompt: external_exports.boolean().optional(),
6439
6540
  enabled: external_exports.boolean().optional(),
6440
6541
  priority: external_exports.number().optional(),
6441
6542
  write_enabled: external_exports.boolean().optional()
@@ -6619,12 +6720,16 @@ var init_contracts = __esm({
6619
6720
  updateEvalBody = external_exports.object({
6620
6721
  eval: external_exports.record(external_exports.unknown())
6621
6722
  }).superRefine(refineEvalMessageTextRole).superRefine(refineEvalAttachments).superRefine(refineEvalInitialState);
6723
+ EVAL_LIST_MAX_LIMIT = 1e3;
6724
+ evalListLimit = external_exports.string().regex(/^\d+$/).refine((v) => Number(v) <= EVAL_LIST_MAX_LIMIT, {
6725
+ message: `limit must be ${EVAL_LIST_MAX_LIMIT} or less`
6726
+ }).optional();
6622
6727
  getEvalsQuery = external_exports.object({
6623
6728
  hub_id: external_exports.string().uuid(),
6624
6729
  agent_id: external_exports.string().uuid().optional(),
6625
6730
  enabled: external_exports.string().regex(/^(true|false)$/).optional(),
6626
6731
  search: external_exports.string().optional(),
6627
- limit: external_exports.string().regex(/^\d+$/).optional(),
6732
+ limit: evalListLimit,
6628
6733
  offset: external_exports.string().regex(/^\d+$/).optional()
6629
6734
  });
6630
6735
  toggleEvalBody = external_exports.object({
@@ -6679,7 +6784,7 @@ var init_contracts = __esm({
6679
6784
  hub_id: external_exports.string().uuid(),
6680
6785
  status: external_exports.string().optional(),
6681
6786
  search: external_exports.string().optional(),
6682
- limit: external_exports.string().regex(/^\d+$/).optional(),
6787
+ limit: evalListLimit,
6683
6788
  offset: external_exports.string().regex(/^\d+$/).optional()
6684
6789
  });
6685
6790
  getSessionResultsQuery = external_exports.object({
@@ -6858,6 +6963,15 @@ var init_contracts = __esm({
6858
6963
  /** Launch-time snapshot. */
6859
6964
  session_config: evalSessionConfigResponseSchema.optional()
6860
6965
  }).passthrough();
6966
+ evalSessionListConfigSchema = external_exports.object({
6967
+ agent: external_exports.object({
6968
+ agent_id: external_exports.string().nullable().optional(),
6969
+ agent_name: external_exports.string().nullable().optional(),
6970
+ agent_role: external_exports.string().nullable().optional()
6971
+ }).optional(),
6972
+ scenario_set_id: external_exports.string().optional().catch(void 0)
6973
+ });
6974
+ evalSessionListItemSchema = evalSessionResponseSchema.omit({ session_config: true }).extend({ session_config: evalSessionListConfigSchema.optional() }).passthrough();
6861
6975
  seedReleaseStatusSchema = external_exports.enum(["not_applicable", "pending", "releasing"]);
6862
6976
  EVAL_SESSION_NOT_QUIESCENT = "session_not_quiescent";
6863
6977
  getConversationsQuery = external_exports.object({
@@ -7466,7 +7580,6 @@ var init_contracts = __esm({
7466
7580
  phone: external_exports.string().optional(),
7467
7581
  email: external_exports.string().email().optional(),
7468
7582
  instagram_sid: external_exports.string().optional(),
7469
- hub_user_id: external_exports.string().uuid().optional(),
7470
7583
  tags: external_exports.array(external_exports.string()).default([]),
7471
7584
  metadata: external_exports.record(external_exports.unknown()).default({}),
7472
7585
  enabled: external_exports.boolean().default(true)
@@ -7479,7 +7592,6 @@ var init_contracts = __esm({
7479
7592
  phone: external_exports.string().nullable().optional(),
7480
7593
  email: external_exports.string().email().nullable().optional(),
7481
7594
  instagram_sid: external_exports.string().nullable().optional(),
7482
- hub_user_id: external_exports.string().uuid().nullable().optional(),
7483
7595
  tags: external_exports.array(external_exports.string()).optional(),
7484
7596
  metadata: external_exports.record(external_exports.unknown()).optional(),
7485
7597
  enabled: external_exports.boolean().optional()
@@ -7846,7 +7958,14 @@ var init_contracts = __esm({
7846
7958
  * disable|enable` flips this. The DO's `updatePlatformConfig` allowlist already
7847
7959
  * accepts it; this exposes it on the route.
7848
7960
  */
7849
- harness_enabled: external_exports.number().int().min(0).max(1).optional()
7961
+ harness_enabled: external_exports.number().int().min(0).max(1).optional(),
7962
+ /**
7963
+ * Default eval-session retention window in days, used by every hub that sets no
7964
+ * `eval_retention_days` override. `0` disables eval retention platform-wide.
7965
+ * NOT NULL in the DDL, so the field is non-nullable here — clearing is not a
7966
+ * state; setting 0 is.
7967
+ */
7968
+ default_eval_retention_days: external_exports.number().int().min(0).max(MAX_EVAL_RETENTION_DAYS).optional()
7850
7969
  }).strip().refine(
7851
7970
  (data) => Object.keys(data).length > 0,
7852
7971
  { message: "No fields to update" }
@@ -8501,6 +8620,34 @@ var init_contracts = __esm({
8501
8620
  adminSkillNameParam = external_exports.object({
8502
8621
  name: external_exports.string().regex(ADMIN_SKILL_NAME_REGEX, "invalid skill name")
8503
8622
  });
8623
+ REKOR_ACTOR_TYPE_HEADER = "X-Rekor-Actor-Type";
8624
+ REKOR_ACTOR_ID_HEADER = "X-Rekor-Actor-Id";
8625
+ REKOR_ACTOR_LABEL_HEADER = "X-Rekor-Actor-Label";
8626
+ REKOR_ACTOR_ORG_HEADER = "X-Rekor-Actor-Org";
8627
+ REKOR_ACTOR_ADMIN_HEADER = "X-Rekor-Actor-Admin";
8628
+ REKOR_CLIENT_HEADER = "X-Rekor-Client";
8629
+ REKOR_TOOL_ID_HEADER = "X-Rekor-Tool-Id";
8630
+ REKOR_CLIENTS = ["api", "cli", "mcp"];
8631
+ rekorClientSchema = external_exports.enum(REKOR_CLIENTS);
8632
+ MAX_REKOR_TOOL_ID_LENGTH = 128;
8633
+ rekorToolIdSchema = external_exports.string().trim().min(1).max(MAX_REKOR_TOOL_ID_LENGTH);
8634
+ DATA_PROXY_MOUNT = "/data";
8635
+ DATA_PROXY_PREFIX = `/api${DATA_PROXY_MOUNT}`;
8636
+ REKOR_V1_PREFIX = "/v1";
8637
+ DATA_PROXY_ORG_QUERY_PARAM = "org_id";
8638
+ dataProxyQuery = external_exports.object({
8639
+ [DATA_PROXY_ORG_QUERY_PARAM]: external_exports.string().uuid().optional()
8640
+ });
8641
+ rekorAttestation = external_exports.object({
8642
+ [REKOR_ACTOR_TYPE_HEADER]: external_exports.enum(["user", "token"]),
8643
+ [REKOR_ACTOR_ID_HEADER]: external_exports.string().min(1),
8644
+ [REKOR_ACTOR_LABEL_HEADER]: external_exports.string(),
8645
+ [REKOR_ACTOR_ORG_HEADER]: external_exports.string().uuid(),
8646
+ [REKOR_ACTOR_ADMIN_HEADER]: external_exports.enum(["0", "1"]),
8647
+ [REKOR_CLIENT_HEADER]: rekorClientSchema,
8648
+ [REKOR_TOOL_ID_HEADER]: rekorToolIdSchema.optional()
8649
+ });
8650
+ REQUIRED_REKOR_ATTESTATION_HEADERS = Object.entries(rekorAttestation.shape).filter(([, field]) => !field.isOptional()).map(([header]) => header);
8504
8651
  }
8505
8652
  });
8506
8653
 
@@ -8508,7 +8655,9 @@ var init_contracts = __esm({
8508
8655
  var api_client_exports = {};
8509
8656
  __export(api_client_exports, {
8510
8657
  ApiClient: () => ApiClient,
8511
- ApiError: () => ApiError
8658
+ ApiError: () => ApiError,
8659
+ dataErrorMessage: () => dataErrorMessage,
8660
+ toDataProxyPath: () => toDataProxyPath
8512
8661
  });
8513
8662
  function isRetryableErrorBody(body) {
8514
8663
  try {
@@ -8518,6 +8667,26 @@ function isRetryableErrorBody(body) {
8518
8667
  return false;
8519
8668
  }
8520
8669
  }
8670
+ function toDataProxyPath(v1Path) {
8671
+ if (!v1Path.startsWith(`${REKOR_V1_PREFIX}/`)) {
8672
+ throw new Error(`Data path must start with ${REKOR_V1_PREFIX}/: ${v1Path}`);
8673
+ }
8674
+ return `${DATA_PROXY_PREFIX}${v1Path.slice(REKOR_V1_PREFIX.length)}`;
8675
+ }
8676
+ function dataErrorMessage(err) {
8677
+ if (!(err instanceof ApiError)) return null;
8678
+ let parsed;
8679
+ try {
8680
+ parsed = JSON.parse(err.body);
8681
+ } catch {
8682
+ return null;
8683
+ }
8684
+ if (err.status === 404 && err.path.startsWith(DATA_PROXY_PREFIX) && typeof parsed?.error === "string") {
8685
+ return "The Data surface is not available on this backend. Update the CLI, or point it at a backend that serves it.";
8686
+ }
8687
+ const message = parsed?.error?.message;
8688
+ return typeof message === "string" && message ? message : null;
8689
+ }
8521
8690
  var RETRYABLE_BACKOFF_MS, delay, ApiError, ApiClient;
8522
8691
  var init_api_client = __esm({
8523
8692
  "src/lib/api-client.ts"() {
@@ -8530,12 +8699,19 @@ var init_api_client = __esm({
8530
8699
  ApiError = class extends Error {
8531
8700
  status;
8532
8701
  body;
8533
- constructor(method, path30, status, body) {
8702
+ /**
8703
+ * The request path that failed. Retained because a body alone cannot say
8704
+ * WHICH surface answered: WayAI and the Data surface both emit 404s, and
8705
+ * telling them apart by body shape misreads one for the other.
8706
+ */
8707
+ path;
8708
+ constructor(method, path31, status, body) {
8534
8709
  const safeBody = maskSecretsInMessage(body);
8535
- super(`API request failed: ${method} ${path30} (${status}): ${safeBody}`);
8710
+ super(`API request failed: ${method} ${path31} (${status}): ${safeBody}`);
8536
8711
  this.name = "ApiError";
8537
8712
  this.status = status;
8538
8713
  this.body = safeBody;
8714
+ this.path = path31;
8539
8715
  }
8540
8716
  /** True when the status code is a 4xx client error (expected user-facing condition, not a bug). */
8541
8717
  get isExpected() {
@@ -8631,8 +8807,8 @@ var init_api_client = __esm({
8631
8807
  ...opts?.check && { check: true }
8632
8808
  });
8633
8809
  }
8634
- async lookup(path30, opts) {
8635
- const params = new URLSearchParams({ path: path30 });
8810
+ async lookup(path31, opts) {
8811
+ const params = new URLSearchParams({ path: path31 });
8636
8812
  if (opts?.organizationId) params.set("organization_id", opts.organizationId);
8637
8813
  return this.request("GET", `/api/ci/lookup?${params.toString()}`);
8638
8814
  }
@@ -9053,9 +9229,9 @@ var init_api_client = __esm({
9053
9229
  * sandbox for this conversation, or the blob was purged).
9054
9230
  */
9055
9231
  async downloadArchiveSandboxFs(hubId, conversationId) {
9056
- const path30 = `/api/archive/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}/sandbox`;
9057
- addApiBreadcrumb("GET", path30);
9058
- const url = `${this.apiUrl}${path30}`;
9232
+ const path31 = `/api/archive/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}/sandbox`;
9233
+ addApiBreadcrumb("GET", path31);
9234
+ const url = `${this.apiUrl}${path31}`;
9059
9235
  let response = await this.send(url, "GET");
9060
9236
  if (response.status === 401 && this.onUnauthorized) {
9061
9237
  let refreshed;
@@ -9069,7 +9245,7 @@ var init_api_client = __esm({
9069
9245
  }
9070
9246
  }
9071
9247
  if (!response.ok) {
9072
- throw new ApiError("GET", path30, response.status, await response.text());
9248
+ throw new ApiError("GET", path31, response.status, await response.text());
9073
9249
  }
9074
9250
  return new Uint8Array(await response.arrayBuffer());
9075
9251
  }
@@ -9109,9 +9285,9 @@ var init_api_client = __esm({
9109
9285
  `/api/admin/data-explorer/debug/observability/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}${qs}`
9110
9286
  );
9111
9287
  }
9112
- async request(method, path30, body) {
9113
- addApiBreadcrumb(method, path30);
9114
- const url = `${this.apiUrl}${path30}`;
9288
+ async request(method, path31, body) {
9289
+ addApiBreadcrumb(method, path31);
9290
+ const url = `${this.apiUrl}${path31}`;
9115
9291
  let refreshedOn401 = false;
9116
9292
  for (let retry = 0; ; retry++) {
9117
9293
  let response = await this.send(url, method, body);
@@ -9128,23 +9304,65 @@ var init_api_client = __esm({
9128
9304
  }
9129
9305
  }
9130
9306
  if (response.ok) {
9131
- return response.json();
9307
+ const okBody = await response.text();
9308
+ return okBody ? JSON.parse(okBody) : void 0;
9132
9309
  }
9133
9310
  const errorBody = await response.text();
9134
9311
  if (method === "GET" && retry < RETRYABLE_BACKOFF_MS.length && isRetryableErrorBody(errorBody)) {
9135
9312
  await delay(RETRYABLE_BACKOFF_MS[retry]);
9136
9313
  continue;
9137
9314
  }
9138
- throw new ApiError(method, path30, response.status, errorBody);
9315
+ throw new ApiError(method, path31, response.status, errorBody);
9139
9316
  }
9140
9317
  }
9318
+ /**
9319
+ * One request against the Data (`/v1`) surface — bases, records, files and the
9320
+ * rest of the Bases namespace.
9321
+ *
9322
+ * `v1Path` is the Data backend's OWN path, verbatim (`/v1/bases`), so every
9323
+ * ported command spells the path the Data Worker documents; only
9324
+ * `toDataProxyPath` knows how WayAI mounts that surface. Identity is the
9325
+ * caller's ordinary WayAI session — there is one keyring login, and the
9326
+ * backend attests the org over its service binding rather than forwarding a
9327
+ * credential (docs/reference/rekor-platform-contracts.md §1).
9328
+ *
9329
+ * Returns the surface's `{ data, meta }` envelope rather than unwrapping, so
9330
+ * cursor-paginated lists can follow `meta.has_more`. A failure throws the same
9331
+ * `ApiError` as every other CLI request, so the top-level handler is unchanged;
9332
+ * `dataErrorMessage` recovers the envelope's own message for display.
9333
+ *
9334
+ * `orgId` is the caller's org SELECTOR (the `--org` flag, else the repo's
9335
+ * `.wayai.yaml`), not an authorization claim: the backend validates it against
9336
+ * the caller's grants and attests only the validated result. A multi-org user
9337
+ * needs it to pick; a single-org user can omit it.
9338
+ *
9339
+ * It travels as the proxy's own query param, whose name is imported rather
9340
+ * than spelled — the handler validates it and strips it before forwarding,
9341
+ * since it is WayAI's selector and not an input Rekor sees.
9342
+ */
9343
+ async dataRequest(method, v1Path, body, orgId) {
9344
+ const separator = v1Path.includes("?") ? "&" : "?";
9345
+ const orgQuery = orgId ? `${separator}${DATA_PROXY_ORG_QUERY_PARAM}=${encodeURIComponent(orgId)}` : "";
9346
+ const envelope = await this.request(
9347
+ method,
9348
+ `${toDataProxyPath(v1Path)}${orgQuery}`,
9349
+ body
9350
+ );
9351
+ return envelope ?? {};
9352
+ }
9141
9353
  /** Issue a single authenticated request with the client's current token. */
9142
9354
  send(url, method, body) {
9143
9355
  return fetch(url, {
9144
9356
  method,
9145
9357
  headers: {
9146
9358
  Authorization: `Bearer ${this.accessToken}`,
9147
- "Content-Type": "application/json"
9359
+ "Content-Type": "application/json",
9360
+ // Names the calling process, on every request. A HINT, not an
9361
+ // authorization input: any client can send it, so the backend must
9362
+ // normalize it against what it knows about its own ingress rather than
9363
+ // trust it. Nothing is granted or denied on its value; the Data Worker's
9364
+ // audit rows are its consumer (contracts §1.4).
9365
+ "X-WayAI-Client": "cli"
9148
9366
  },
9149
9367
  body: body ? JSON.stringify(body) : void 0
9150
9368
  });
@@ -9193,6 +9411,8 @@ function friendlyHint(err) {
9193
9411
  if (err.body.includes("FREE_PLAN_RESTRICTION")) {
9194
9412
  return "Publishing to production requires a paid plan. Upgrade your organization to publish or sync.";
9195
9413
  }
9414
+ const dataMessage = dataErrorMessage(err);
9415
+ if (dataMessage) return dataMessage;
9196
9416
  const { status } = err;
9197
9417
  if (status === 401) return "Your session may have expired. Run `wayai login` to re-authenticate.";
9198
9418
  if (status === 402) return "Quota exceeded for your plan. Review usage or upgrade your plan.";
@@ -9247,6 +9467,70 @@ function withinJsonLength2(value, max) {
9247
9467
  function visibleLength2(s) {
9248
9468
  return s.replace(INVISIBLE_NAME_CHARS2, "").length;
9249
9469
  }
9470
+ function isEventRelativeFollowupType2(type) {
9471
+ return typeof type === "string" && EVENT_RELATIVE_FOLLOWUP_TYPES2.includes(type);
9472
+ }
9473
+ function validateFollowupLinks2(followups, label, ctx) {
9474
+ const linkTargets = /* @__PURE__ */ new Set();
9475
+ followups.forEach((followup, i) => {
9476
+ const ref = followup?.after_followup_id;
9477
+ const path31 = ["followups", i, "after_followup_id"];
9478
+ if (followup?.type !== "inactivity_after_before_event") {
9479
+ if (ref !== void 0) {
9480
+ ctx.addIssue({
9481
+ code: external_exports.ZodIssueCode.custom,
9482
+ path: path31,
9483
+ message: `kanban status ${label}: after_followup_id is only valid on inactivity_after_before_event followups (this one is ${followup?.type})`
9484
+ });
9485
+ }
9486
+ return;
9487
+ }
9488
+ if (ref === void 0) {
9489
+ ctx.addIssue({
9490
+ code: external_exports.ZodIssueCode.custom,
9491
+ path: path31,
9492
+ message: `kanban status ${label}: inactivity_after_before_event requires after_followup_id naming the id of a before_event followup in the same status`
9493
+ });
9494
+ return;
9495
+ }
9496
+ linkTargets.add(ref);
9497
+ const matches = followups.filter((candidate) => candidate?.id === ref);
9498
+ if (matches.length > 1) {
9499
+ ctx.addIssue({
9500
+ code: external_exports.ZodIssueCode.custom,
9501
+ path: path31,
9502
+ message: `kanban status ${label}: after_followup_id "${ref}" matches ${matches.length} followups \u2014 a link must name exactly one`
9503
+ });
9504
+ return;
9505
+ }
9506
+ const target = matches[0];
9507
+ if (!target) {
9508
+ const hasIdlessBeforeEvent = followups.some(
9509
+ (candidate) => candidate?.type === "before_event" && candidate?.id === void 0
9510
+ );
9511
+ ctx.addIssue({
9512
+ code: external_exports.ZodIssueCode.custom,
9513
+ path: path31,
9514
+ message: hasIdlessBeforeEvent ? `kanban status ${label}: after_followup_id "${ref}" matches no followup \u2014 a link target must declare an explicit id, and this status has before_event followups without one` : `kanban status ${label}: after_followup_id "${ref}" matches no followup in this status`
9515
+ });
9516
+ return;
9517
+ }
9518
+ if (target.type !== "before_event") {
9519
+ ctx.addIssue({
9520
+ code: external_exports.ZodIssueCode.custom,
9521
+ path: path31,
9522
+ message: `kanban status ${label}: after_followup_id "${ref}" points at a ${target.type} followup \u2014 only before_event followups can anchor a chain`
9523
+ });
9524
+ }
9525
+ });
9526
+ if (linkTargets.size > MAX_LINKED_FOLLOWUP_TARGETS_PER_STATUS2) {
9527
+ ctx.addIssue({
9528
+ code: external_exports.ZodIssueCode.custom,
9529
+ path: ["followups"],
9530
+ message: `kanban status ${label}: at most ${MAX_LINKED_FOLLOWUP_TARGETS_PER_STATUS2} distinct after_followup_id targets per status (found ${linkTargets.size}) \u2014 each one rebuilds a chain on every inbound message`
9531
+ });
9532
+ }
9533
+ }
9250
9534
  function validateLaneReferences2(lanes, statuses) {
9251
9535
  const issues = [];
9252
9536
  if (!Array.isArray(statuses) || statuses.length === 0) return issues;
@@ -9310,12 +9594,12 @@ function typeMatches2(typeField, allowed) {
9310
9594
  if (Array.isArray(typeField)) return typeField.every((t) => typeof t === "string" && allowed.has(t));
9311
9595
  return false;
9312
9596
  }
9313
- function validateSchema2(schema, path30, errors, opts = {}) {
9597
+ function validateSchema2(schema, path31, errors, opts = {}) {
9314
9598
  if (typeof schema === "boolean") return;
9315
9599
  const depth = opts.depth ?? 0;
9316
9600
  if (depth > MAX_SCHEMA_DEPTH2) {
9317
9601
  errors.push({
9318
- path: path30 || "<root>",
9602
+ path: path31 || "<root>",
9319
9603
  message: `schema nesting exceeds ${MAX_SCHEMA_DEPTH2} levels`,
9320
9604
  suggestion: "Flatten the schema; LLM providers reject deeply nested tool input_schemas."
9321
9605
  });
@@ -9323,7 +9607,7 @@ function validateSchema2(schema, path30, errors, opts = {}) {
9323
9607
  }
9324
9608
  if (!isRecord2(schema)) {
9325
9609
  errors.push({
9326
- path: path30,
9610
+ path: path31,
9327
9611
  message: `expected object, got ${schema === null ? "null" : typeof schema}`
9328
9612
  });
9329
9613
  return;
@@ -9331,14 +9615,14 @@ function validateSchema2(schema, path30, errors, opts = {}) {
9331
9615
  if (opts.isRoot) {
9332
9616
  if ("type" in schema && schema.type !== "object") {
9333
9617
  errors.push({
9334
- path: path30 ? `${path30}.type` : "type",
9618
+ path: path31 ? `${path31}.type` : "type",
9335
9619
  message: `root type must be 'object', got ${JSON.stringify(schema.type)}`,
9336
9620
  suggestion: "Tool parameters at the root must be an object: `{ type: 'object', properties: { ... } }`."
9337
9621
  });
9338
9622
  }
9339
9623
  } else if ("type" in schema && !typeMatches2(schema.type, ALLOWED_TYPES2)) {
9340
9624
  errors.push({
9341
- path: `${path30}.type`,
9625
+ path: `${path31}.type`,
9342
9626
  message: `type must be one of ${[...ALLOWED_TYPES2].join("/")} or an array of those, got ${JSON.stringify(schema.type)}`
9343
9627
  });
9344
9628
  }
@@ -9348,25 +9632,25 @@ function validateSchema2(schema, path30, errors, opts = {}) {
9348
9632
  const isPlaceholder = PLACEHOLDER_TOKENS2.includes(e);
9349
9633
  const isOutcomePlaceholder = e === "[KANBAN_OUTCOME_VALUES]";
9350
9634
  errors.push({
9351
- path: `${path30}.enum`,
9635
+ path: `${path31}.enum`,
9352
9636
  message: `enum must be a non-empty array of primitives, got string ${JSON.stringify(e)}`,
9353
9637
  suggestion: isOutcomePlaceholder ? "Declare `outcomes` on the hub's terminal kanban status so the platform can render the placeholder into a valid array; with none configured the platform drops the parameter instead." : 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"]`.'
9354
9638
  });
9355
9639
  } else if (!Array.isArray(e)) {
9356
9640
  errors.push({
9357
- path: `${path30}.enum`,
9641
+ path: `${path31}.enum`,
9358
9642
  message: `enum must be a non-empty array of primitives, got ${typeof e}`
9359
9643
  });
9360
9644
  } else if (e.length === 0) {
9361
9645
  errors.push({
9362
- path: `${path30}.enum`,
9646
+ path: `${path31}.enum`,
9363
9647
  message: "enum must not be empty"
9364
9648
  });
9365
9649
  } else {
9366
9650
  for (let i = 0; i < e.length; i++) {
9367
9651
  if (!isPrimitive2(e[i])) {
9368
9652
  errors.push({
9369
- path: `${path30}.enum[${i}]`,
9653
+ path: `${path31}.enum[${i}]`,
9370
9654
  message: `enum entry must be a primitive (string/number/boolean/null), got ${typeof e[i]}`
9371
9655
  });
9372
9656
  }
@@ -9376,7 +9660,7 @@ function validateSchema2(schema, path30, errors, opts = {}) {
9376
9660
  for (const key of ["exclusiveMinimum", "exclusiveMaximum"]) {
9377
9661
  if (key in schema && typeof schema[key] === "boolean") {
9378
9662
  errors.push({
9379
- path: `${path30}.${key}`,
9663
+ path: `${path31}.${key}`,
9380
9664
  message: `${key} as boolean is draft-04 syntax; draft 2020-12 requires a numeric value`,
9381
9665
  suggestion: `Replace with the numeric bound, e.g. \`${key}: 0\`.`
9382
9666
  });
@@ -9385,45 +9669,45 @@ function validateSchema2(schema, path30, errors, opts = {}) {
9385
9669
  if ("properties" in schema) {
9386
9670
  if (!isRecord2(schema.properties)) {
9387
9671
  errors.push({
9388
- path: `${path30}.properties`,
9672
+ path: `${path31}.properties`,
9389
9673
  message: `properties must be an object, got ${Array.isArray(schema.properties) ? "array" : typeof schema.properties}`
9390
9674
  });
9391
9675
  } else {
9392
9676
  for (const [propName, propSchema] of Object.entries(schema.properties)) {
9393
- validateSchema2(propSchema, `${path30}.properties.${propName}`, errors, { depth: depth + 1 });
9677
+ validateSchema2(propSchema, `${path31}.properties.${propName}`, errors, { depth: depth + 1 });
9394
9678
  }
9395
9679
  }
9396
9680
  }
9397
9681
  if (schemaTypeIncludes2(schema, "array") && "items" in schema) {
9398
9682
  if (Array.isArray(schema.items)) {
9399
- schema.items.forEach((sub, i) => validateSchema2(sub, `${path30}.items[${i}]`, errors, { depth: depth + 1 }));
9683
+ schema.items.forEach((sub, i) => validateSchema2(sub, `${path31}.items[${i}]`, errors, { depth: depth + 1 }));
9400
9684
  } else {
9401
- validateSchema2(schema.items, `${path30}.items`, errors, { depth: depth + 1 });
9685
+ validateSchema2(schema.items, `${path31}.items`, errors, { depth: depth + 1 });
9402
9686
  }
9403
9687
  }
9404
9688
  for (const key of SUBSCHEMA_OBJECT_KEYWORDS2) {
9405
9689
  if (key in schema && isRecord2(schema[key])) {
9406
- validateSchema2(schema[key], `${path30}.${key}`, errors, { depth: depth + 1 });
9690
+ validateSchema2(schema[key], `${path31}.${key}`, errors, { depth: depth + 1 });
9407
9691
  }
9408
9692
  }
9409
9693
  for (const key of SUBSCHEMA_LIST_KEYWORDS2) {
9410
9694
  const list = schema[key];
9411
9695
  if (Array.isArray(list)) {
9412
- list.forEach((sub, i) => validateSchema2(sub, `${path30}.${key}[${i}]`, errors, { depth: depth + 1 }));
9696
+ list.forEach((sub, i) => validateSchema2(sub, `${path31}.${key}[${i}]`, errors, { depth: depth + 1 }));
9413
9697
  }
9414
9698
  }
9415
9699
  for (const key of SUBSCHEMA_MAP_KEYWORDS2) {
9416
9700
  const map = schema[key];
9417
9701
  if (isRecord2(map)) {
9418
9702
  for (const [name, sub] of Object.entries(map)) {
9419
- validateSchema2(sub, `${path30}.${key}.${name}`, errors, { depth: depth + 1 });
9703
+ validateSchema2(sub, `${path31}.${key}.${name}`, errors, { depth: depth + 1 });
9420
9704
  }
9421
9705
  }
9422
9706
  }
9423
9707
  const reportedPaths = new Set(errors.map((e) => e.path));
9424
9708
  for (const [k, v] of Object.entries(schema)) {
9425
9709
  if (typeof v !== "string") continue;
9426
- const fieldPath = `${path30}.${k}`;
9710
+ const fieldPath = `${path31}.${k}`;
9427
9711
  if (reportedPaths.has(fieldPath)) continue;
9428
9712
  for (const token of PLACEHOLDER_TOKENS2) {
9429
9713
  if (v === token) {
@@ -9568,8 +9852,8 @@ function evalInitialStateError2(input) {
9568
9852
  const parsed = evalInitialStateEntry2.safeParse(entries[i]);
9569
9853
  if (!parsed.success) {
9570
9854
  const issue = parsed.error.issues[0];
9571
- const path30 = issue?.path.join(".") || "?";
9572
- return `initial_state[${i}].${path30} is invalid: ${issue?.message ?? "malformed"}`;
9855
+ const path31 = issue?.path.join(".") || "?";
9856
+ return `initial_state[${i}].${path31} is invalid: ${issue?.message ?? "malformed"}`;
9573
9857
  }
9574
9858
  if (seenSlugs.has(parsed.data.slug)) {
9575
9859
  return `initial_state[${i}].slug "${parsed.data.slug}" is declared more than once`;
@@ -9774,10 +10058,10 @@ function refineHubAsCodeEvals2(config, ctx) {
9774
10058
  function refineHubAsCodeEvalAttachments2(config, ctx) {
9775
10059
  const cfg = config;
9776
10060
  const referencedHashes = /* @__PURE__ */ new Set();
9777
- const addTurnIssue = (path30, turn, name) => {
10061
+ const addTurnIssue = (path31, turn, name) => {
9778
10062
  const error = evalTurnAttachmentsError2(turn);
9779
10063
  if (error) {
9780
- ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: path30, message: `${name}: ${error}` });
10064
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: path31, message: `${name}: ${error}` });
9781
10065
  return;
9782
10066
  }
9783
10067
  for (const hash of collectTurnAttachmentHashes2(turn)) referencedHashes.add(hash);
@@ -9923,11 +10207,11 @@ function refineHubAsCodeDelegation2(config, ctx) {
9923
10207
  }
9924
10208
  }
9925
10209
  if (del.context_boundary === void 0) return;
9926
- const path30 = ["agents", agentIndex, "tools", "delegation", delIndex, "context_boundary"];
10210
+ const path31 = ["agents", agentIndex, "tools", "delegation", delIndex, "context_boundary"];
9927
10211
  if (del.type !== "hub") {
9928
10212
  ctx.addIssue({
9929
10213
  code: external_exports.ZodIssueCode.custom,
9930
- path: path30,
10214
+ path: path31,
9931
10215
  message: `context_boundary applies only to \`type: hub\` delegations (got type "${String(del.type)}")`
9932
10216
  });
9933
10217
  return;
@@ -9935,7 +10219,7 @@ function refineHubAsCodeDelegation2(config, ctx) {
9935
10219
  if (!CONTEXT_BOUNDARIES2.includes(del.context_boundary)) {
9936
10220
  ctx.addIssue({
9937
10221
  code: external_exports.ZodIssueCode.custom,
9938
- path: path30,
10222
+ path: path31,
9939
10223
  message: `context_boundary must be one of: ${CONTEXT_BOUNDARIES2.join(", ")}`
9940
10224
  });
9941
10225
  }
@@ -9981,7 +10265,7 @@ function findStepBoundaries(transcript) {
9981
10265
  }
9982
10266
  return out;
9983
10267
  }
9984
- 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_CONTENT_BRAND, LlmProviderContentError, LLM_PROVIDER_TIMEOUT_BRAND, LlmProviderTimeoutError, ExternalServiceError, CHANNEL_PROVIDER_HTTP_BRAND, ChannelProviderHttpError, MEDIA_PROVIDER_HTTP_BRAND, MediaProviderHttpError, AUTH_TYPE2, ORG_CREDENTIAL_AUTH_TYPES2, AUTH_TYPE_DISPLAY2, LEGACY_AUTH_TYPE_MAP2, VALID_AUTH_TYPES2, AGENT_ROLES2, SAFE_USER_ID_REGEX2, SUPPORTED_LOCALES2, uuidSchema2, paginationSchema3, timestampSchema2, idParamSchema2, clientOptionalString2, clientOptionalBoolean2, clientOptionalNumber2, messageAttachment2, MAX_MESSAGE_BODY_BYTES2, MAX_ATTACHMENTS_PER_MESSAGE2, MAX_AUDIO_FILE_BASE64_BYTES2, primaryRegionSchema2, placementSourceSchema2, orgIdParam2, orgAdminIdParam2, createOrganizationBody2, updateOrganizationBody2, addOrgAdminBody2, SUMMARIZATION_THRESHOLD_MIN2, SUMMARIZATION_THRESHOLD_MAX2, PREVIOUS_CONVERSATIONS_MAX2, previousConversationsCountField2, 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, MAX_OUTCOMES_PER_STATUS2, kanbanOutcomeSchema2, 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, CONTEXT_BOUNDARIES2, contextBoundarySchema2, 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, analyticsSqlTable2, analyticsSqlSchemaQuery2, EVAL_PACING_PRESET_NAMES2, PACING_INTERVAL_MIN_MS2, PACING_INTERVAL_MAX_MS2, EVAL_MAX_RUNS_PER_SCENARIO2, EVAL_RUN_DEADLINE_MIN_MS2, EVAL_RUN_DEADLINE_MAX_MS2, ISO_UTC_RE2, paginationSchema22, evalIdParam2, sessionIdParam2, scenarioSetIdParam2, hubIdQuery2, evalDateContextSchema2, EVAL_FIXTURE_NAME_MAX_LENGTH2, evalFixtureOverrideSchema2, runSessionQuery2, EVAL_INPUT_ROLES2, EVAL_INPUT_ROLE_LIST2, ROLE_ECHO_MAX2, EVAL_INITIAL_STATE_SCOPES2, MAX_INITIAL_STATE_ENTRIES2, evalInitialStateEntry2, createEvalBody2, updateEvalBody2, getEvalsQuery2, toggleEvalBody2, bulkToggleEvalsBody2, pacingConfigSchema2, EVAL_MAX_SELECTED_SCENARIOS2, evalScenarioSelectionEntrySchema2, evalScenarioSelectionSchema2, sessionConfigSchema2, createSessionBody2, getSessionsQuery2, getSessionResultsQuery2, getSessionRunsQuery2, evalAnalyticsQuery2, getSessionCostQuery2, compareSessionsQuery2, evalsSqlBody2, evalsSqlSchemaQuery2, exportResultsQuery2, validateEvalBody2, hubAgentsQuery2, createScenarioSetBody2, updateScenarioSetBody2, scenarioSetsHubQuery2, createScenarioFromConversationBody2, createJourneyFromConversationBody2, EVAL_ATTACHMENT_HASH_REGEX2, evalAttachmentRef2, turnMayCarryAttachments2, ATTACHMENTS_USER_ONLY_MESSAGE2, journeyIdParam2, journeyToolCallSchema2, journeyTurnSchema2, journeyStepOverrideSchema2, fixtureField2, createJourneyBody2, updateJourneyBody2, evalSessionConfigResponseSchema2, evalSessionResponseSchema2, seedReleaseStatusSchema2, getConversationsQuery2, getMessagesQuery2, appMessageSenderType2, appMessageReceiverType2, apiChannelMessage2, apiChannelMessageBody2, appMessageBody2, appMessageResponse2, updateUserBody2, updateProfileBody2, pathnameRegex2, updatePreferencesBody2, registerPushTokenBody2, deletePushTokenQuery2, activityQuery2, deletionModeSchema2, deletionRequestBody2, archiveHubIdParam2, archiveConversationParams2, archiveListQuery2, archiveMessageObservabilityParams2, conversationIdParam2, claimBody2, releaseBody2, transferBody2, closeBody2, additionalContextPayloadSchema2, kanbanUpdateBody2, annotateConversationBody2, observabilityParams2, observabilityListParams2, deleteUserConversationsBody2, deleteUserConversationsResponse2, sendMessageBody2, listConversationsQuery2, flagSourceSchema2, getConversationsResponse2, getConversationDetailParams2, getConversationDetailQuery2, getConversationDetailResponse2, listWhatsAppTemplatesQuery2, sendWhatsAppTemplateBody2, copilotSuggestBody2, copilotSuggestResponse2, CONSULT_THREAD_STATUSES2, consultThreadStatus2, CONSULT_THREAD_TITLE_MAX2, consultThreadTitle2, consultThreadSummary2, listConsultThreadsQuery2, listConsultThreadsResponse2, createConsultThreadBody2, createConsultThreadResponse2, consultThreadIdParam2, updateConsultThreadBody2, updateConsultThreadResponse2, CONSULT_AWAIT_TIMEOUT_MS2, 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, MAX_RESOURCE_FILE_SIZE2, MAX_10MB_BASE64_ENCODED_BYTES2, MAX_EVAL_ATTACHMENT_ENCODED_BYTES2, MAX_EVAL_ATTACHMENT_CARRIERS2, MAX_EVAL_ATTACHMENT_AGGREGATE_ENCODED_BYTES2, MAX_RESOURCE_ENCODED_BYTES2, MAX_HUB_AS_CODE_RESOURCES2, MAX_HUB_AS_CODE_RESOURCE_FILES2, MAX_RESOURCE_AGGREGATE_ENCODED_BYTES2, MAX_CI_CONFIG_BODY_BYTES2, hubAsCodeStateSchema2, hubAsCodeResourceFileSchema2, hubAsCodeResourceSchema2, uuidPattern2, ciUuidSchema2, boundedHubAsCodeResourcesSchema2, hubAsCodeConfigSchema2, ciPullHubIdParam2, ciBranchParam2, ciPullQuery2, ciHubsQuery2, ciLookupQuery2, ciBranchesQuery2, ciSyncBody2, ciPushBody2, ciDiffBody2, ciPublishBody2, ciPublishPreviewBody2, ciSyncMcpBody2, ciOrgResourcesParam2, orgResourcesConfigSchema2, ciOrgResourcesPushBody2, ciOrgResourcesDiffBody2, CI_APPLY_ENTITY_KINDS2, CI_APPLY_OPERATIONS2, ciApplyErrorBaseSchema2, ciApplyErrorSchema2, ciSyncCountSchema2, ciSyncChangesSchema2, ciSyncWarningSchema2, ciSyncResponseSchema2, adminOrgIdParam2, adminOrgAdminIdParam2, adminUserIdParam2, adminPlanIdParam2, adminOrganizationsQuery2, adminUserSearchQuery2, kanbanSlugMigrationQuery2, adjustQuotaBody2, updatePlanBody2, addAdminUserBody2, updatePlatformConfigBody2, updateFreeOrgLimitBody2, adminScopedTargetBody2, updatePricingPlanBody2, dataExplorerSearchQuery2, dataExplorerOrgIdParam2, dataExplorerHubIdParam2, dataExplorerConvIdParam2, dataExplorerDoInstancesQuery2, dataExplorerNsIdParam2, dataExplorerKvKeysBody2, dataExplorerKvKeyBody2, uuidOrHexId2, dataExplorerDeleteOrgParam2, dataExplorerDeleteHubParam2, dataExplorerDeleteConvParam2, dataExplorerDeleteUserParam2, dataExplorerDeleteQuery2, dataExplorerKvDeleteBody2, 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, passwordLoginBody2, browserParams2, browserFoldersQuery2, browserFilesQuery2, stateOperationBody2, conversationListResourcesQuery2, conversationReadResourceQuery2, listPendingSchedulesQuery2, listHubAggregateSchedulesQuery2, reportSourceSchema2, intakeReportSourceSchema2, reportClassificationSchema2, reportStatusSchema2, reportLocaleSchema2, reportMessageAuthorRoleSchema2, reportMessageSchema2, sentryRefStatusSchema2, createReportBody2, editReportBody2, reporterReportSummarySchema2, reporterListResponseSchema2, getReportResponseSchema2, reporterTransitionResponseSchema2, 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, jsonSchemaSchema2, hubUserIdentity2, stateValueEntry2, getHubUserContextResponse2, updateHubUserBody2, updateHubUserResponse2, unlockHubUserNameResponse2, stateResetParams2, stateResetResponse2, hubAlertsParam2, hubAlertSeverity2, hubAlert2, hubAlertsListResponse2, noticeSeveritySchema2, noticeStatusSchema2, NOTICE_SCOPE_REGEX2, noticeScopeSchema2, noticeLinkSchema2, createNoticeBody2, updateNoticeBody2, listNoticesQuery2, noticeIdParamSchema2, ADMIN_SKILL_NAME_REGEX2, adminSkillNameParam2, WAYAI_WORKSPACE_LAYOUT;
10268
+ 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_CONTENT_BRAND, LlmProviderContentError, LLM_PROVIDER_TIMEOUT_BRAND, LlmProviderTimeoutError, ExternalServiceError, CHANNEL_PROVIDER_HTTP_BRAND, ChannelProviderHttpError, MEDIA_PROVIDER_HTTP_BRAND, MediaProviderHttpError, REKOR_ACTOR_TYPE_HEADER2, REKOR_ACTOR_ID_HEADER2, REKOR_ACTOR_LABEL_HEADER2, REKOR_ACTOR_ORG_HEADER2, REKOR_ACTOR_ADMIN_HEADER2, REKOR_CLIENT_HEADER2, REKOR_TOOL_ID_HEADER2, REKOR_CLIENTS2, rekorClientSchema2, MAX_REKOR_TOOL_ID_LENGTH2, rekorToolIdSchema2, DATA_PROXY_MOUNT2, DATA_PROXY_PREFIX2, DATA_PROXY_ORG_QUERY_PARAM2, dataProxyQuery2, rekorAttestation2, REQUIRED_REKOR_ATTESTATION_HEADERS2, ENDPOINT_CONFIGS, AUTH_TYPE2, ORG_CREDENTIAL_AUTH_TYPES2, AUTH_TYPE_DISPLAY2, LEGACY_AUTH_TYPE_MAP2, VALID_AUTH_TYPES2, AGENT_ROLES2, SAFE_USER_ID_REGEX2, SUPPORTED_LOCALES2, uuidSchema2, paginationSchema3, timestampSchema2, idParamSchema2, clientOptionalString2, clientOptionalBoolean2, clientOptionalNumber2, messageAttachment2, MAX_MESSAGE_BODY_BYTES2, MAX_ATTACHMENTS_PER_MESSAGE2, MAX_AUDIO_FILE_BASE64_BYTES2, primaryRegionSchema2, placementSourceSchema2, orgIdParam2, orgAdminIdParam2, createOrganizationBody2, updateOrganizationBody2, addOrgAdminBody2, SUMMARIZATION_THRESHOLD_MIN2, SUMMARIZATION_THRESHOLD_MAX2, PREVIOUS_CONVERSATIONS_MAX2, previousConversationsCountField2, 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, followupTypeSchema2, EVENT_RELATIVE_FOLLOWUP_TYPES2, followupTimeUnitSchema2, followupIdSchema2, SELECTABLE_FOLLOWUP_TYPES2, MAX_LINKED_FOLLOWUP_TARGETS_PER_STATUS2, followupSchema2, MAX_OUTCOMES_PER_STATUS2, kanbanOutcomeSchema2, EXCLUSIVE_FLAG_PAIRS2, kanbanStatusSchema2, kanbanStatusesArraySchema2, laneSchema2, lanesArraySchema2, hubIdParam2, hubAdminIdParam2, hubUserIdParam2, hubIdentityIdParam2, hubTeamIdParam2, hubTeamUserDeleteParam2, hubSchemaQuery2, PREVIEW_LABEL_MAX_LENGTH2, MAX_ENDED_INDEX_RETENTION_DAYS2, MAX_EVAL_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, CONTEXT_BOUNDARIES2, contextBoundarySchema2, 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, analyticsSqlTable2, analyticsSqlSchemaQuery2, EVAL_PACING_PRESET_NAMES2, PACING_INTERVAL_MIN_MS2, PACING_INTERVAL_MAX_MS2, EVAL_MAX_RUNS_PER_SCENARIO2, EVAL_RUN_DEADLINE_MIN_MS2, EVAL_RUN_DEADLINE_MAX_MS2, ISO_UTC_RE2, paginationSchema22, evalIdParam2, sessionIdParam2, scenarioSetIdParam2, hubIdQuery2, evalDateContextSchema2, EVAL_FIXTURE_NAME_MAX_LENGTH2, evalFixtureOverrideSchema2, runSessionQuery2, EVAL_INPUT_ROLES2, EVAL_INPUT_ROLE_LIST2, ROLE_ECHO_MAX2, EVAL_INITIAL_STATE_SCOPES2, MAX_INITIAL_STATE_ENTRIES2, evalInitialStateEntry2, createEvalBody2, updateEvalBody2, EVAL_LIST_MAX_LIMIT2, evalListLimit2, getEvalsQuery2, toggleEvalBody2, bulkToggleEvalsBody2, pacingConfigSchema2, EVAL_MAX_SELECTED_SCENARIOS2, evalScenarioSelectionEntrySchema2, evalScenarioSelectionSchema2, sessionConfigSchema2, createSessionBody2, getSessionsQuery2, getSessionResultsQuery2, getSessionRunsQuery2, evalAnalyticsQuery2, getSessionCostQuery2, compareSessionsQuery2, evalsSqlBody2, evalsSqlSchemaQuery2, exportResultsQuery2, validateEvalBody2, hubAgentsQuery2, createScenarioSetBody2, updateScenarioSetBody2, scenarioSetsHubQuery2, createScenarioFromConversationBody2, createJourneyFromConversationBody2, EVAL_ATTACHMENT_HASH_REGEX2, evalAttachmentRef2, turnMayCarryAttachments2, ATTACHMENTS_USER_ONLY_MESSAGE2, journeyIdParam2, journeyToolCallSchema2, journeyTurnSchema2, journeyStepOverrideSchema2, fixtureField2, createJourneyBody2, updateJourneyBody2, evalSessionConfigResponseSchema2, evalSessionResponseSchema2, evalSessionListConfigSchema2, evalSessionListItemSchema2, seedReleaseStatusSchema2, getConversationsQuery2, getMessagesQuery2, appMessageSenderType2, appMessageReceiverType2, apiChannelMessage2, apiChannelMessageBody2, appMessageBody2, appMessageResponse2, updateUserBody2, updateProfileBody2, pathnameRegex2, updatePreferencesBody2, registerPushTokenBody2, deletePushTokenQuery2, activityQuery2, deletionModeSchema2, deletionRequestBody2, archiveHubIdParam2, archiveConversationParams2, archiveListQuery2, archiveMessageObservabilityParams2, conversationIdParam2, claimBody2, releaseBody2, transferBody2, closeBody2, additionalContextPayloadSchema2, kanbanUpdateBody2, annotateConversationBody2, observabilityParams2, observabilityListParams2, deleteUserConversationsBody2, deleteUserConversationsResponse2, sendMessageBody2, listConversationsQuery2, flagSourceSchema2, getConversationsResponse2, getConversationDetailParams2, getConversationDetailQuery2, getConversationDetailResponse2, listWhatsAppTemplatesQuery2, sendWhatsAppTemplateBody2, copilotSuggestBody2, copilotSuggestResponse2, CONSULT_THREAD_STATUSES2, consultThreadStatus2, CONSULT_THREAD_TITLE_MAX2, consultThreadTitle2, consultThreadSummary2, listConsultThreadsQuery2, listConsultThreadsResponse2, createConsultThreadBody2, createConsultThreadResponse2, consultThreadIdParam2, updateConsultThreadBody2, updateConsultThreadResponse2, CONSULT_AWAIT_TIMEOUT_MS2, 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, MAX_RESOURCE_FILE_SIZE2, MAX_10MB_BASE64_ENCODED_BYTES2, MAX_EVAL_ATTACHMENT_ENCODED_BYTES2, MAX_EVAL_ATTACHMENT_CARRIERS2, MAX_EVAL_ATTACHMENT_AGGREGATE_ENCODED_BYTES2, MAX_RESOURCE_ENCODED_BYTES2, MAX_HUB_AS_CODE_RESOURCES2, MAX_HUB_AS_CODE_RESOURCE_FILES2, MAX_RESOURCE_AGGREGATE_ENCODED_BYTES2, MAX_CI_CONFIG_BODY_BYTES2, hubAsCodeStateSchema2, hubAsCodeResourceFileSchema2, hubAsCodeResourceSchema2, uuidPattern2, ciUuidSchema2, boundedHubAsCodeResourcesSchema2, hubAsCodeConfigSchema2, ciPullHubIdParam2, ciBranchParam2, ciPullQuery2, ciHubsQuery2, ciLookupQuery2, ciBranchesQuery2, ciSyncBody2, ciPushBody2, ciDiffBody2, ciPublishBody2, ciPublishPreviewBody2, ciSyncMcpBody2, ciOrgResourcesParam2, orgResourcesConfigSchema2, ciOrgResourcesPushBody2, ciOrgResourcesDiffBody2, CI_APPLY_ENTITY_KINDS2, CI_APPLY_OPERATIONS2, ciApplyErrorBaseSchema2, ciApplyErrorSchema2, ciSyncCountSchema2, ciSyncChangesSchema2, ciSyncWarningSchema2, ciSyncResponseSchema2, adminOrgIdParam2, adminOrgAdminIdParam2, adminUserIdParam2, adminPlanIdParam2, adminOrganizationsQuery2, adminUserSearchQuery2, kanbanSlugMigrationQuery2, adjustQuotaBody2, updatePlanBody2, addAdminUserBody2, updatePlatformConfigBody2, updateFreeOrgLimitBody2, adminScopedTargetBody2, updatePricingPlanBody2, dataExplorerSearchQuery2, dataExplorerOrgIdParam2, dataExplorerHubIdParam2, dataExplorerConvIdParam2, dataExplorerDoInstancesQuery2, dataExplorerNsIdParam2, dataExplorerKvKeysBody2, dataExplorerKvKeyBody2, uuidOrHexId2, dataExplorerDeleteOrgParam2, dataExplorerDeleteHubParam2, dataExplorerDeleteConvParam2, dataExplorerDeleteUserParam2, dataExplorerDeleteQuery2, dataExplorerKvDeleteBody2, 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, passwordLoginBody2, browserParams2, browserFoldersQuery2, browserFilesQuery2, stateOperationBody2, conversationListResourcesQuery2, conversationReadResourceQuery2, listPendingSchedulesQuery2, listHubAggregateSchedulesQuery2, reportSourceSchema2, intakeReportSourceSchema2, reportClassificationSchema2, reportStatusSchema2, reportLocaleSchema2, reportMessageAuthorRoleSchema2, reportMessageSchema2, sentryRefStatusSchema2, createReportBody2, editReportBody2, reporterReportSummarySchema2, reporterListResponseSchema2, getReportResponseSchema2, reporterTransitionResponseSchema2, 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, jsonSchemaSchema2, hubUserIdentity2, stateValueEntry2, getHubUserContextResponse2, updateHubUserBody2, updateHubUserResponse2, unlockHubUserNameResponse2, stateResetParams2, stateResetResponse2, hubAlertsParam2, hubAlertSeverity2, hubAlert2, hubAlertsListResponse2, noticeSeveritySchema2, noticeStatusSchema2, NOTICE_SCOPE_REGEX2, noticeScopeSchema2, noticeLinkSchema2, createNoticeBody2, updateNoticeBody2, listNoticesQuery2, noticeIdParamSchema2, ADMIN_SKILL_NAME_REGEX2, adminSkillNameParam2, WAYAI_WORKSPACE_LAYOUT;
9985
10269
  var init_dist = __esm({
9986
10270
  "../../packages/core/dist/index.js"() {
9987
10271
  "use strict";
@@ -10033,6 +10317,7 @@ var init_dist = __esm({
10033
10317
  init_zod();
10034
10318
  init_zod();
10035
10319
  init_zod();
10320
+ init_zod();
10036
10321
  UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
10037
10322
  HEX_RE = /^[0-9a-f]{16,}$/;
10038
10323
  WORKOS_ID_RE = /^(?:user|org)_[0-9A-HJKMNP-TV-Z]{26}$/;
@@ -10190,6 +10475,208 @@ var init_dist = __esm({
10190
10475
  }
10191
10476
  [MEDIA_PROVIDER_HTTP_BRAND] = true;
10192
10477
  };
10478
+ REKOR_ACTOR_TYPE_HEADER2 = "X-Rekor-Actor-Type";
10479
+ REKOR_ACTOR_ID_HEADER2 = "X-Rekor-Actor-Id";
10480
+ REKOR_ACTOR_LABEL_HEADER2 = "X-Rekor-Actor-Label";
10481
+ REKOR_ACTOR_ORG_HEADER2 = "X-Rekor-Actor-Org";
10482
+ REKOR_ACTOR_ADMIN_HEADER2 = "X-Rekor-Actor-Admin";
10483
+ REKOR_CLIENT_HEADER2 = "X-Rekor-Client";
10484
+ REKOR_TOOL_ID_HEADER2 = "X-Rekor-Tool-Id";
10485
+ REKOR_CLIENTS2 = ["api", "cli", "mcp"];
10486
+ rekorClientSchema2 = external_exports.enum(REKOR_CLIENTS2);
10487
+ MAX_REKOR_TOOL_ID_LENGTH2 = 128;
10488
+ rekorToolIdSchema2 = external_exports.string().trim().min(1).max(MAX_REKOR_TOOL_ID_LENGTH2);
10489
+ DATA_PROXY_MOUNT2 = "/data";
10490
+ DATA_PROXY_PREFIX2 = `/api${DATA_PROXY_MOUNT2}`;
10491
+ DATA_PROXY_ORG_QUERY_PARAM2 = "org_id";
10492
+ dataProxyQuery2 = external_exports.object({
10493
+ [DATA_PROXY_ORG_QUERY_PARAM2]: external_exports.string().uuid().optional()
10494
+ });
10495
+ rekorAttestation2 = external_exports.object({
10496
+ [REKOR_ACTOR_TYPE_HEADER2]: external_exports.enum(["user", "token"]),
10497
+ [REKOR_ACTOR_ID_HEADER2]: external_exports.string().min(1),
10498
+ [REKOR_ACTOR_LABEL_HEADER2]: external_exports.string(),
10499
+ [REKOR_ACTOR_ORG_HEADER2]: external_exports.string().uuid(),
10500
+ [REKOR_ACTOR_ADMIN_HEADER2]: external_exports.enum(["0", "1"]),
10501
+ [REKOR_CLIENT_HEADER2]: rekorClientSchema2,
10502
+ [REKOR_TOOL_ID_HEADER2]: rekorToolIdSchema2.optional()
10503
+ });
10504
+ REQUIRED_REKOR_ATTESTATION_HEADERS2 = Object.entries(rekorAttestation2.shape).filter(([, field]) => !field.isOptional()).map(([header]) => header);
10505
+ ENDPOINT_CONFIGS = {
10506
+ // OAuth callbacks - strict, fail-closed (prevent brute force)
10507
+ "/oauth/callback/*": { tier: "STRICT", failClosed: true },
10508
+ // Auth endpoints - strict, fail-closed
10509
+ "/auth/phone": { tier: "STRICT", failClosed: true },
10510
+ "/auth/mcp/exchange": { tier: "MODERATE", failClosed: true },
10511
+ // Native magic-code login (pre-auth) — STRICT per-IP bounds a single host; WorkOS owns
10512
+ // the per-email lockout / TTL / single-use guarantees.
10513
+ "/api/auth/magic-code/*": { tier: "STRICT", failClosed: true },
10514
+ // Native password login (pre-auth) — same posture as magic-code above. STRICT per-IP bounds a
10515
+ // single host but FAILS OPEN on a binding error (like every IP limit); the `failClosed` flag
10516
+ // here is inert on a pre-auth route (it's only enforced on the per-user branch, which needs an
10517
+ // authenticated caller). The fail-CLOSED brute-force guarantee for the static credential comes
10518
+ // from the route's per-email caps (burst + cumulative hourly), not this flag.
10519
+ "/api/auth/password/*": { tier: "STRICT", failClosed: true },
10520
+ // Billing - moderate, fail-closed with user limits
10521
+ "/api/billing/*": { tier: "MODERATE", userLimit: 100, failClosed: true, skipAuthenticatedUsers: true },
10522
+ "/webhooks/stripe": { tier: "MODERATE", failClosed: true },
10523
+ "/webhooks/workos": { tier: "MODERATE", failClosed: true },
10524
+ // API endpoints - standard with user limits
10525
+ "/api/setup/*": { tier: "STANDARD", userLimit: 150, skipAuthenticatedUsers: true },
10526
+ "/api/conversations/*": { tier: "STANDARD", userLimit: 150, skipAuthenticatedUsers: true },
10527
+ "/api/users/*": { tier: "STANDARD", userLimit: 150, skipAuthenticatedUsers: true },
10528
+ "/api/analytics/*": { tier: "STANDARD", userLimit: 150, skipAuthenticatedUsers: true },
10529
+ "/api/evals/*": { tier: "STANDARD", userLimit: 150, skipAuthenticatedUsers: true },
10530
+ "/api/files/*": { tier: "STANDARD", userLimit: 150, skipAuthenticatedUsers: true },
10531
+ "/api/outbound/*": { tier: "STANDARD", userLimit: 150, skipAuthenticatedUsers: true },
10532
+ "/api/live-updates/*": { tier: "STANDARD", userLimit: 150, skipAuthenticatedUsers: true },
10533
+ "/api/hub-users/*": { tier: "STANDARD", userLimit: 150, skipAuthenticatedUsers: true },
10534
+ "/api/conversation-state/*": { tier: "STANDARD", userLimit: 150, skipAuthenticatedUsers: true },
10535
+ // Channel webhooks - high throughput (external systems, never authenticated)
10536
+ "/webhooks/whatsapp/*": { tier: "HIGH" },
10537
+ "/webhooks/instagram/*": { tier: "HIGH" },
10538
+ // Reports (CLI → platform_report triage queue). One per-user budget covers intake
10539
+ // (POST), the content edit (PATCH /:id), the reporter read-back (GET, GET /:id), and the
10540
+ // verification loop (POST /:id/accept, /:id/contest). The limiter is path-based, so a
10541
+ // method-level split (loose reads, strict writes) isn't expressible — GET /:id and PATCH
10542
+ // /:id share a path. So the budget is sized for the read-heavy poll loop (a reporter agent
10543
+ // polling `report get`/`list` while it waits for the fix), at 60/hour. Intake-flooding stays
10544
+ // bounded regardless: identical reports collapse on `fingerprint` (ON CONFLICT DO NOTHING),
10545
+ // so a runaway create loop merges rather than floods. Still STRICT tier + failClosed so a
10546
+ // genuinely runaway distinct-report loop surfaces as 429. The `/*` is load-bearing — an
10547
+ // exact `/api/reports` key would leave the `/:id` paths unmatched (→ unthrottled).
10548
+ // `userLimitKey` is equally load-bearing: without it, middleware falls back to each raw
10549
+ // pathname and report IDs/actions receive independent counters instead of this shared budget.
10550
+ "/api/reports/*": {
10551
+ tier: "STRICT",
10552
+ userLimit: 60,
10553
+ userWindow: 3600,
10554
+ failClosed: true,
10555
+ skipAuthenticatedUsers: true,
10556
+ userLimitKey: "/api/reports/*"
10557
+ },
10558
+ // Admin report mutations (transition/group/ungroup/edit) — platform-admin
10559
+ // gated at the route, rate-limited here as defense-in-depth. Generous STANDARD
10560
+ // cap so legitimate triage bursts aren't throttled (grouping is one request
10561
+ // even for many members); deliberately NOT failClosed so a Redis blip never
10562
+ // blocks an admin's triage. The bare GET reads share this budget harmlessly.
10563
+ "/api/admin/reports/*": { tier: "STANDARD", userLimit: 150 },
10564
+ // GitHub webhook (issues.closed → platform_report addressed). MODERATE +
10565
+ // fail-closed; GitHub retries on transient failures so a brief Redis blip
10566
+ // doesn't lose state.
10567
+ "/webhooks/github": { tier: "MODERATE", failClosed: true },
10568
+ // Account deletion — strict on the destructive POST + public undo. The
10569
+ // /api/users/* default tier above ALSO matches these, but `getEndpointConfig`
10570
+ // returns the longest-prefix match, so the more specific entries here win.
10571
+ // `skipAuthenticatedUsers` deliberately omitted: every caller is authenticated,
10572
+ // so including it would make `userLimit` a no-op — the per-user cap IS the gate.
10573
+ "/api/users/me/deletion": { tier: "STRICT", userLimit: 3, userWindow: 3600, failClosed: true },
10574
+ "/api/users/me/deletion/preflight": { tier: "STANDARD", userLimit: 30, failClosed: true },
10575
+ "/api/users/deletion/undo": { tier: "STRICT", failClosed: true },
10576
+ // Email-invite preview — public, fail-closed. MODERATE (30/min IP) leaves
10577
+ // headroom for the signup-page server-fetch + reloads + prefetches; STRICT
10578
+ // would throttle legitimate users opening the link in multiple tabs.
10579
+ "/api/invites/preview": { tier: "MODERATE", failClosed: true },
10580
+ // Admin DO debug reads — the ONE deliberate deviation from the Data Explorer
10581
+ // catch-all below, and the only reason a per-route key still exists here.
10582
+ // Platform-admin is enforced at the route; this is the independent
10583
+ // defense-in-depth signal so a runaway investigation script surfaces as 429.
10584
+ //
10585
+ // STRICT is kept ON PURPOSE even though the catch-all moved off it, because
10586
+ // `tier` is the only layer that bounds enumeration on this surface: the
10587
+ // per-user cap keys on the RAW pathname (see the CAVEAT below), so sweeping
10588
+ // `/debug/do/hub/<id>/tables` across thousands of ids never trips it. At 5/min
10589
+ // vs STANDARD's 100/min, walking 10k ids takes ~33h instead of ~100min — a
10590
+ // detection window worth keeping on the routes that return RAW DO ROWS.
10591
+ //
10592
+ // The cost, stated rather than elided: STRICT is one bucket shared with
10593
+ // `/oauth/callback/*` and `/api/auth/magic-code/*`, so a debug session from a
10594
+ // NAT'd office IP can 429 a colleague's login for up to a minute. That trade is
10595
+ // accepted for a rare, deliberate investigation surface — and is exactly why the
10596
+ // browse routes below are NOT here.
10597
+ "/api/admin/data-explorer/debug/*": { tier: "STRICT", userLimit: 60, userWindow: 3600, failClosed: true },
10598
+ // Catch-all for the rest of the Data Explorer (`/search`, `/entity/*`, `/do/*`,
10599
+ // `/kv/*`, the DELETE routes). Added as a catch-all rather than another per-route
10600
+ // key because this budget kept lagging behind routes joining the debug boundary:
10601
+ // with no match the path falls to the default, which sets no `userLimit`, so the
10602
+ // per-user layer never runs at all. `getEndpointConfig` takes the longest match,
10603
+ // so `debug/*` above still wins.
10604
+ //
10605
+ // `/entity/*` deliberately has NO key of its own: it needs precisely this config,
10606
+ // and a duplicate entry is how the two drift apart on the next edit.
10607
+ //
10608
+ // `tier` is deliberately STANDARD, not STRICT. `tier` is the per-IP knob and
10609
+ // STRICT is 5/min keyed on IP ALONE — one bucket shared across every STRICT
10610
+ // endpoint. On these browse routes that breaks the console (open Browse KV and
10611
+ // inspect four values = 6 requests; expand six org rows in the search results =
10612
+ // 6 `/entity/org/:id` calls) and would drain the same IP's budget for
10613
+ // `/oauth/callback/*` and `/api/auth/magic-code/*`, which on a NAT'd office IP
10614
+ // means all admins. The per-user hourly cap is the leg that matters here.
10615
+ //
10616
+ // The canonical key is deliberate: raw pathnames contain DO ids and arbitrary
10617
+ // malformed requests can contain credential material. Keying on the raw pathname
10618
+ // both stores that material in Redis/logs and gives every target a fresh counter.
10619
+ // One stable identity makes every browse request consume the same per-admin
10620
+ // budget without storing request targets.
10621
+ //
10622
+ // 600/hour preserves the original pagination requirement (about 30k rows at
10623
+ // 50/page) while now genuinely bounding id/key enumeration across the surface.
10624
+ "/api/admin/data-explorer/*": {
10625
+ tier: "STANDARD",
10626
+ userLimit: 600,
10627
+ userWindow: 3600,
10628
+ failClosed: true,
10629
+ userLimitKey: "/api/admin/data-explorer/*"
10630
+ },
10631
+ // Admin sandbox exec (harness-agents PR 1.5) — this is ARBITRARY CODE EXECUTION,
10632
+ // so it gets the strictest budget on the platform: STRICT tier + a low per-user
10633
+ // hourly cap (well below the 60/hr debug-read cap) + fail-closed. Platform-admin
10634
+ // is enforced at the route; this is the independent defense-in-depth signal so a
10635
+ // runaway exec loop surfaces as 429 instead of silently provisioning sandboxes.
10636
+ "/api/admin/sandbox/*": { tier: "STRICT", userLimit: 20, userWindow: 3600, failClosed: true },
10637
+ // Admin harness incident-response (harness-agents PR 2.9b) — mass-destroy reaps
10638
+ // EVERY live harness sandbox/token/slot in scope, so it gets a strict budget
10639
+ // (STRICT + a low per-user hourly cap + fail-closed). Platform-admin is enforced
10640
+ // at the route; this is the independent defense-in-depth signal so a runaway
10641
+ // reap loop surfaces as 429. The break-glass disable/enable rides through
10642
+ // `/api/admin/config` (its own STANDARD budget), not this key.
10643
+ "/api/admin/harness/*": { tier: "STRICT", userLimit: 10, userWindow: 3600, failClosed: true },
10644
+ // Platform-wide team-orphan repair — a single call can WRITE across every hub of
10645
+ // every org (HubDO purge + UserDO mirror fan-out), so it gets the same strict,
10646
+ // fail-closed budget as the other cross-platform admin write. Exact path (not a
10647
+ // prefix): the sibling `/api/admin/hubs/:hubId/harness` flag flips stay on the
10648
+ // default admin budget. Platform-admin is enforced at the route; this is the
10649
+ // defense-in-depth signal that a repair loop surfaces as 429.
10650
+ "/api/admin/hubs/repair-team-orphans": { tier: "STRICT", userLimit: 10, userWindow: 3600, failClosed: true },
10651
+ // CI/GitOps endpoints - standard with user limits
10652
+ "/api/ci/*": { tier: "STANDARD", userLimit: 100, skipAuthenticatedUsers: true },
10653
+ // Attested `/v1` proxy onto the Rekor Worker. `userLimitKey` is load-bearing here in a
10654
+ // way it is not for the siblings above: the per-user budget defaults to the full request
10655
+ // path, and this surface's paths carry base, record, and file ids — so without a pinned
10656
+ // key every distinct resource would get its own fresh budget and the per-user limit
10657
+ // would bound nothing. One shared budget across the whole data surface is the intent.
10658
+ [`${DATA_PROXY_PREFIX2}/*`]: {
10659
+ tier: "STANDARD",
10660
+ userLimit: 150,
10661
+ skipAuthenticatedUsers: true,
10662
+ userLimitKey: `${DATA_PROXY_PREFIX2}/*`
10663
+ },
10664
+ // App channel - high throughput with user limits
10665
+ "/channels/app/*": { tier: "HIGH", userLimit: 500, skipAuthenticatedUsers: true },
10666
+ // API channel (api-channel-connector) - machine-to-machine, high throughput
10667
+ "/channels/api/*": { tier: "HIGH", userLimit: 500, skipAuthenticatedUsers: true },
10668
+ // System/scheduled - high throughput (internal)
10669
+ "/channels/system/*": { tier: "HIGH", skipAuthenticatedUsers: true },
10670
+ "/scheduled/*": { tier: "HIGH", skipAuthenticatedUsers: true },
10671
+ // WebSocket - standard with user limit to prevent connection spam
10672
+ "/live-updates/ws": { tier: "STANDARD", userLimit: 100, failClosed: true },
10673
+ // WS ticket mint - per-user 60/min accommodates aggressive reconnect patterns
10674
+ // without opening abuse vectors; fail-closed so Redis outages don't let
10675
+ // runaway clients mint unbounded tickets.
10676
+ "/api/auth/ws-ticket": { tier: "MODERATE", userLimit: 60, failClosed: true, skipAuthenticatedUsers: true },
10677
+ "/api/auth/session-check": { tier: "STANDARD", userLimit: 120, skipAuthenticatedUsers: true },
10678
+ "/api/auth/logout": { tier: "MODERATE", userLimit: 10, failClosed: true, skipAuthenticatedUsers: true }
10679
+ };
10193
10680
  AUTH_TYPE2 = {
10194
10681
  OAUTH: "oauth",
10195
10682
  API_KEY: "api_key",
@@ -10386,12 +10873,28 @@ var init_dist = __esm({
10386
10873
  MAX_ADDITIONAL_CONTEXT_SCHEMA_BYTES2 = 16384;
10387
10874
  RESERVED_TEMPLATE_DUMP_NAME2 = "additional_data";
10388
10875
  kanbanStatusSlugSchema2 = slugSchema2;
10876
+ followupTypeSchema2 = external_exports.enum([
10877
+ "inactivity",
10878
+ "before_event",
10879
+ "inactivity_after_event",
10880
+ "inactivity_after_before_event"
10881
+ ]);
10882
+ EVENT_RELATIVE_FOLLOWUP_TYPES2 = [
10883
+ "before_event",
10884
+ "inactivity_after_event",
10885
+ "inactivity_after_before_event"
10886
+ ];
10887
+ followupTimeUnitSchema2 = external_exports.enum(["seconds", "minutes", "hours", "days"]);
10888
+ followupIdSchema2 = external_exports.string().min(1, "must not be empty").refine((v) => v === v.trim(), "must not have leading or trailing whitespace");
10889
+ SELECTABLE_FOLLOWUP_TYPES2 = followupTypeSchema2.options;
10890
+ MAX_LINKED_FOLLOWUP_TARGETS_PER_STATUS2 = 5;
10389
10891
  followupSchema2 = external_exports.object({
10390
- id: external_exports.string().optional(),
10892
+ /** Optional author-supplied identifier; also the `after_followup_id` link target. */
10893
+ id: followupIdSchema2.optional(),
10391
10894
  order: external_exports.number().int().nonnegative(),
10392
- type: external_exports.enum(["inactivity", "before_event"]),
10895
+ type: followupTypeSchema2,
10393
10896
  threshold: external_exports.number().int().positive(),
10394
- timeUnit: external_exports.enum(["seconds", "minutes", "hours", "days"]),
10897
+ timeUnit: followupTimeUnitSchema2,
10395
10898
  instructions: external_exports.string().optional(),
10396
10899
  excludedWeekDays: external_exports.array(external_exports.number().int().min(0).max(6)).optional(),
10397
10900
  excludeHolidays: external_exports.boolean().optional(),
@@ -10401,7 +10904,15 @@ var init_dist = __esm({
10401
10904
  direct_text: external_exports.string().optional(),
10402
10905
  template_whatsapp_id: external_exports.string().nullable().optional(),
10403
10906
  outside_window_policy: external_exports.enum(["route_to_team", "skip"]).optional(),
10404
- include_tools: external_exports.boolean().optional()
10907
+ include_tools: external_exports.boolean().optional(),
10908
+ /**
10909
+ * The `before_event` followup whose fire anchors this chain — its `id`, in
10910
+ * the same status. One name, one meaning, contract and schedule column
10911
+ * alike: "the followup whose fire anchors this chain". Required on
10912
+ * `inactivity_after_before_event`, forbidden on every other type; both are
10913
+ * enforced per status, where the sibling followups are visible.
10914
+ */
10915
+ after_followup_id: followupIdSchema2.optional()
10405
10916
  }).passthrough().superRefine((followup, ctx) => {
10406
10917
  if (followup.delivery_mode === "direct" && !followup.direct_text?.trim()) {
10407
10918
  ctx.addIssue({
@@ -10490,12 +11001,20 @@ var init_dist = __esm({
10490
11001
  message: `kanban status ${label}: event_due_delay_minutes requires isSchedulingStatus=true`
10491
11002
  });
10492
11003
  }
10493
- if (Array.isArray(status.followups) && status.followups.some((f) => f?.type === "before_event") && status.isSchedulingStatus !== true) {
10494
- ctx.addIssue({
10495
- code: external_exports.ZodIssueCode.custom,
10496
- path: ["followups"],
10497
- message: `kanban status ${label}: before_event followups require isSchedulingStatus=true on the parent status`
10498
- });
11004
+ if (Array.isArray(status.followups) && status.isSchedulingStatus !== true) {
11005
+ const offending = status.followups.find(
11006
+ (f) => isEventRelativeFollowupType2(f?.type)
11007
+ );
11008
+ if (offending) {
11009
+ ctx.addIssue({
11010
+ code: external_exports.ZodIssueCode.custom,
11011
+ path: ["followups"],
11012
+ message: `kanban status ${label}: ${offending.type} followups require isSchedulingStatus=true on the parent status`
11013
+ });
11014
+ }
11015
+ }
11016
+ if (Array.isArray(status.followups)) {
11017
+ validateFollowupLinks2(status.followups, label, ctx);
10499
11018
  }
10500
11019
  if (status.additional_context_schema && typeof status.additional_context_schema === "object") {
10501
11020
  const schema = status.additional_context_schema;
@@ -10652,6 +11171,7 @@ var init_dist = __esm({
10652
11171
  hubSchemaQuery2 = external_exports.object({ hub_id: uuidSchema2 });
10653
11172
  PREVIEW_LABEL_MAX_LENGTH2 = 60;
10654
11173
  MAX_ENDED_INDEX_RETENTION_DAYS2 = 730;
11174
+ MAX_EVAL_RETENTION_DAYS2 = 3650;
10655
11175
  previewLabelField2 = external_exports.string().max(PREVIEW_LABEL_MAX_LENGTH2).optional().nullable().transform((v) => {
10656
11176
  if (v == null) return null;
10657
11177
  const trimmed = v.trim();
@@ -10687,6 +11207,10 @@ var init_dist = __esm({
10687
11207
  // the cleanup cron reaps its index row. Absent → DEFAULT_ENDED_INDEX_RETENTION_DAYS
10688
11208
  // (365). Re-clamped to the effective storage retention at reap time.
10689
11209
  ended_index_retention_days: external_exports.number().int().min(1).max(MAX_ENDED_INDEX_RETENTION_DAYS2).optional(),
11210
+ // Per-hub eval-session retention window (days). null CLEARS the override (back to
11211
+ // the platform default); 0 disables retention for this hub (keep sessions forever).
11212
+ // Nullable — unlike the fields above, "unset" is a meaningful, settable state.
11213
+ eval_retention_days: external_exports.number().int().min(0).max(MAX_EVAL_RETENTION_DAYS2).nullable().optional(),
10690
11214
  // Channel contact access control. Enum-validated explicitly (not via passthrough)
10691
11215
  // so `language`/`access_approval_role` can't reach the DB with an invalid value.
10692
11216
  language: external_exports.enum(["en", "pt", "es"]).optional(),
@@ -11169,8 +11693,9 @@ var init_dist = __esm({
11169
11693
  file_metadata_schema: external_exports.record(external_exports.unknown()).optional(),
11170
11694
  skill_name: external_exports.string().optional(),
11171
11695
  skill_version: external_exports.string().optional(),
11172
- anthropic_skill_id: external_exports.string().optional(),
11173
- anthropic_version: external_exports.string().optional(),
11696
+ // No `anthropic_skill_id`/`anthropic_version`: `resource` has neither column.
11697
+ // The provider link lives on `resource_provider_sync.provider_skill_id`,
11698
+ // written by `skillSync.ts` — never through this body.
11174
11699
  user_browsable: external_exports.boolean().optional()
11175
11700
  });
11176
11701
  syncSkillsBody2 = external_exports.object({
@@ -11266,7 +11791,6 @@ var init_dist = __esm({
11266
11791
  agent_id: uuidSchema2,
11267
11792
  priority: external_exports.number().optional(),
11268
11793
  use_native_integration: external_exports.boolean().optional(),
11269
- include_structure_in_prompt: external_exports.boolean().optional(),
11270
11794
  write_enabled: external_exports.boolean().optional()
11271
11795
  });
11272
11796
  updateAgentResourceBody2 = external_exports.object({
@@ -11274,7 +11798,6 @@ var init_dist = __esm({
11274
11798
  resource_id: uuidSchema2,
11275
11799
  agent_id: uuidSchema2,
11276
11800
  use_native_integration: external_exports.boolean().optional(),
11277
- include_structure_in_prompt: external_exports.boolean().optional(),
11278
11801
  enabled: external_exports.boolean().optional(),
11279
11802
  priority: external_exports.number().optional(),
11280
11803
  write_enabled: external_exports.boolean().optional()
@@ -11458,12 +11981,16 @@ var init_dist = __esm({
11458
11981
  updateEvalBody2 = external_exports.object({
11459
11982
  eval: external_exports.record(external_exports.unknown())
11460
11983
  }).superRefine(refineEvalMessageTextRole2).superRefine(refineEvalAttachments2).superRefine(refineEvalInitialState2);
11984
+ EVAL_LIST_MAX_LIMIT2 = 1e3;
11985
+ evalListLimit2 = external_exports.string().regex(/^\d+$/).refine((v) => Number(v) <= EVAL_LIST_MAX_LIMIT2, {
11986
+ message: `limit must be ${EVAL_LIST_MAX_LIMIT2} or less`
11987
+ }).optional();
11461
11988
  getEvalsQuery2 = external_exports.object({
11462
11989
  hub_id: external_exports.string().uuid(),
11463
11990
  agent_id: external_exports.string().uuid().optional(),
11464
11991
  enabled: external_exports.string().regex(/^(true|false)$/).optional(),
11465
11992
  search: external_exports.string().optional(),
11466
- limit: external_exports.string().regex(/^\d+$/).optional(),
11993
+ limit: evalListLimit2,
11467
11994
  offset: external_exports.string().regex(/^\d+$/).optional()
11468
11995
  });
11469
11996
  toggleEvalBody2 = external_exports.object({
@@ -11518,7 +12045,7 @@ var init_dist = __esm({
11518
12045
  hub_id: external_exports.string().uuid(),
11519
12046
  status: external_exports.string().optional(),
11520
12047
  search: external_exports.string().optional(),
11521
- limit: external_exports.string().regex(/^\d+$/).optional(),
12048
+ limit: evalListLimit2,
11522
12049
  offset: external_exports.string().regex(/^\d+$/).optional()
11523
12050
  });
11524
12051
  getSessionResultsQuery2 = external_exports.object({
@@ -11697,6 +12224,15 @@ var init_dist = __esm({
11697
12224
  /** Launch-time snapshot. */
11698
12225
  session_config: evalSessionConfigResponseSchema2.optional()
11699
12226
  }).passthrough();
12227
+ evalSessionListConfigSchema2 = external_exports.object({
12228
+ agent: external_exports.object({
12229
+ agent_id: external_exports.string().nullable().optional(),
12230
+ agent_name: external_exports.string().nullable().optional(),
12231
+ agent_role: external_exports.string().nullable().optional()
12232
+ }).optional(),
12233
+ scenario_set_id: external_exports.string().optional().catch(void 0)
12234
+ });
12235
+ evalSessionListItemSchema2 = evalSessionResponseSchema2.omit({ session_config: true }).extend({ session_config: evalSessionListConfigSchema2.optional() }).passthrough();
11700
12236
  seedReleaseStatusSchema2 = external_exports.enum(["not_applicable", "pending", "releasing"]);
11701
12237
  getConversationsQuery2 = external_exports.object({
11702
12238
  nav_item: external_exports.enum(["chat", "task", "support", "chat_task"]),
@@ -12304,7 +12840,6 @@ var init_dist = __esm({
12304
12840
  phone: external_exports.string().optional(),
12305
12841
  email: external_exports.string().email().optional(),
12306
12842
  instagram_sid: external_exports.string().optional(),
12307
- hub_user_id: external_exports.string().uuid().optional(),
12308
12843
  tags: external_exports.array(external_exports.string()).default([]),
12309
12844
  metadata: external_exports.record(external_exports.unknown()).default({}),
12310
12845
  enabled: external_exports.boolean().default(true)
@@ -12317,7 +12852,6 @@ var init_dist = __esm({
12317
12852
  phone: external_exports.string().nullable().optional(),
12318
12853
  email: external_exports.string().email().nullable().optional(),
12319
12854
  instagram_sid: external_exports.string().nullable().optional(),
12320
- hub_user_id: external_exports.string().uuid().nullable().optional(),
12321
12855
  tags: external_exports.array(external_exports.string()).optional(),
12322
12856
  metadata: external_exports.record(external_exports.unknown()).optional(),
12323
12857
  enabled: external_exports.boolean().optional()
@@ -12684,7 +13218,14 @@ var init_dist = __esm({
12684
13218
  * disable|enable` flips this. The DO's `updatePlatformConfig` allowlist already
12685
13219
  * accepts it; this exposes it on the route.
12686
13220
  */
12687
- harness_enabled: external_exports.number().int().min(0).max(1).optional()
13221
+ harness_enabled: external_exports.number().int().min(0).max(1).optional(),
13222
+ /**
13223
+ * Default eval-session retention window in days, used by every hub that sets no
13224
+ * `eval_retention_days` override. `0` disables eval retention platform-wide.
13225
+ * NOT NULL in the DDL, so the field is non-nullable here — clearing is not a
13226
+ * state; setting 0 is.
13227
+ */
13228
+ default_eval_retention_days: external_exports.number().int().min(0).max(MAX_EVAL_RETENTION_DAYS2).optional()
12688
13229
  }).strip().refine(
12689
13230
  (data) => Object.keys(data).length > 0,
12690
13231
  { message: "No fields to update" }
@@ -13345,7 +13886,9 @@ var init_dist = __esm({
13345
13886
  /** Subdir of `wsDir` holding hub folders. */
13346
13887
  hubsSubdir: "hubs",
13347
13888
  /** Subdir of `wsDir` holding org-as-code. */
13348
- orgSubdir: "org"
13889
+ orgSubdir: "org",
13890
+ /** Subdir of `wsDir` holding base folders. */
13891
+ basesSubdir: "bases"
13349
13892
  };
13350
13893
  }
13351
13894
  });
@@ -13366,10 +13909,12 @@ function resolveLayout(gitRoot, layout = WAYAI_LAYOUT) {
13366
13909
  const legacyOrg = path.join(gitRoot, layout.legacy.orgAtRoot);
13367
13910
  const newExists = isDirectory(newWs);
13368
13911
  const legacyExists = isDirectory(legacyWs) || isDirectory(legacyOrg);
13912
+ const basesDir = path.join(newWs, layout.basesSubdir);
13369
13913
  if (newExists) {
13370
13914
  return {
13371
13915
  hubsDir: path.join(newWs, layout.hubsSubdir),
13372
13916
  orgDir: path.join(newWs, layout.orgSubdir),
13917
+ basesDir,
13373
13918
  isLegacy: false,
13374
13919
  legacyAlsoPresent: legacyExists
13375
13920
  };
@@ -13378,6 +13923,7 @@ function resolveLayout(gitRoot, layout = WAYAI_LAYOUT) {
13378
13923
  return {
13379
13924
  hubsDir: legacyWs,
13380
13925
  orgDir: legacyOrg,
13926
+ basesDir,
13381
13927
  isLegacy: true,
13382
13928
  legacyAlsoPresent: false
13383
13929
  };
@@ -13385,10 +13931,14 @@ function resolveLayout(gitRoot, layout = WAYAI_LAYOUT) {
13385
13931
  return {
13386
13932
  hubsDir: path.join(newWs, layout.hubsSubdir),
13387
13933
  orgDir: path.join(newWs, layout.orgSubdir),
13934
+ basesDir,
13388
13935
  isLegacy: false,
13389
13936
  legacyAlsoPresent: false
13390
13937
  };
13391
13938
  }
13939
+ function resolveBasesDir(gitRoot) {
13940
+ return resolveLayout(gitRoot).basesDir;
13941
+ }
13392
13942
  function hubsDirLabel(gitRoot) {
13393
13943
  if (!gitRoot) return path.join(WAYAI_LAYOUT.wsDir, WAYAI_LAYOUT.hubsSubdir);
13394
13944
  return path.relative(gitRoot, resolveLayout(gitRoot).hubsDir);
@@ -14081,6 +14631,290 @@ var init_utils = __esm({
14081
14631
  }
14082
14632
  });
14083
14633
 
14634
+ // src/data/registry.ts
14635
+ function isDataNamespace(command2) {
14636
+ return command2 !== void 0 && DATA_NAMESPACES.includes(command2);
14637
+ }
14638
+ var COMMAND_SURVIVAL, DATA_NAMESPACES;
14639
+ var init_registry = __esm({
14640
+ "src/data/registry.ts"() {
14641
+ "use strict";
14642
+ COMMAND_SURVIVAL = [
14643
+ // --- Clause 1: deleted. One keyring login, one status, one CLI self-update. ---
14644
+ {
14645
+ original: "login",
14646
+ disposition: "deleted",
14647
+ surviving: null,
14648
+ clause: 1,
14649
+ shipped: true,
14650
+ reason: "One keyring login. WayAI's `login` and `~/.wayai/config.json` are the survivors."
14651
+ },
14652
+ {
14653
+ original: "logout",
14654
+ disposition: "deleted",
14655
+ surviving: null,
14656
+ clause: 1,
14657
+ shipped: true,
14658
+ reason: "One session to clear."
14659
+ },
14660
+ {
14661
+ original: "whoami",
14662
+ disposition: "deleted",
14663
+ surviving: null,
14664
+ clause: 1,
14665
+ shipped: true,
14666
+ reason: "One authenticated identity."
14667
+ },
14668
+ {
14669
+ original: "status",
14670
+ disposition: "deleted",
14671
+ surviving: null,
14672
+ clause: 1,
14673
+ shipped: true,
14674
+ reason: "One auth/connectivity status."
14675
+ },
14676
+ {
14677
+ original: "init",
14678
+ disposition: "deleted",
14679
+ surviving: null,
14680
+ clause: 1,
14681
+ shipped: true,
14682
+ reason: "One root org binding (`.wayai.yaml`), so one `init`."
14683
+ },
14684
+ {
14685
+ original: "update",
14686
+ disposition: "deleted",
14687
+ surviving: null,
14688
+ clause: 1,
14689
+ shipped: true,
14690
+ reason: "One binary, one self-update."
14691
+ },
14692
+ // --- Clause 2: top-level ontology entities WayAI owns no concept of. ---
14693
+ {
14694
+ original: "bases",
14695
+ disposition: "top-level",
14696
+ surviving: "bases",
14697
+ clause: 2,
14698
+ shipped: true,
14699
+ reason: "The ontology root entity. No WayAI command of this name."
14700
+ },
14701
+ {
14702
+ original: "records",
14703
+ disposition: "top-level",
14704
+ surviving: "records",
14705
+ clause: 2,
14706
+ shipped: false,
14707
+ reason: "Ontology entity. No WayAI command of this name."
14708
+ },
14709
+ {
14710
+ original: "record-types",
14711
+ disposition: "top-level",
14712
+ surviving: "record-types",
14713
+ clause: 2,
14714
+ shipped: false,
14715
+ reason: "Ontology entity."
14716
+ },
14717
+ {
14718
+ original: "relationships",
14719
+ disposition: "top-level",
14720
+ surviving: "relationships",
14721
+ clause: 2,
14722
+ shipped: false,
14723
+ reason: "Ontology entity."
14724
+ },
14725
+ {
14726
+ original: "relationship-types",
14727
+ disposition: "top-level",
14728
+ surviving: "relationship-types",
14729
+ clause: 2,
14730
+ shipped: false,
14731
+ reason: "Ontology entity."
14732
+ },
14733
+ {
14734
+ original: "query-relationships",
14735
+ disposition: "top-level",
14736
+ surviving: "query-relationships",
14737
+ clause: 2,
14738
+ shipped: false,
14739
+ reason: "Ontology traversal over relationships."
14740
+ },
14741
+ {
14742
+ original: "files",
14743
+ disposition: "top-level",
14744
+ surviving: "files",
14745
+ clause: 2,
14746
+ shipped: false,
14747
+ reason: "Unambiguous: WayAI has no `files` command \u2014 hub-local resource files are reached through hub config-as-code, and the two file surfaces stay deliberately separate."
14748
+ },
14749
+ {
14750
+ original: "file-types",
14751
+ disposition: "top-level",
14752
+ surviving: "file-types",
14753
+ clause: 2,
14754
+ shipped: false,
14755
+ reason: "Ontology entity."
14756
+ },
14757
+ {
14758
+ original: "attachments",
14759
+ disposition: "top-level",
14760
+ surviving: "attachments",
14761
+ clause: 2,
14762
+ shipped: false,
14763
+ reason: "Ontology entity."
14764
+ },
14765
+ {
14766
+ original: "toolsets",
14767
+ disposition: "top-level",
14768
+ surviving: "toolsets",
14769
+ clause: 2,
14770
+ shipped: false,
14771
+ reason: "Ontology entity."
14772
+ },
14773
+ {
14774
+ original: "actions",
14775
+ disposition: "top-level",
14776
+ surviving: "actions",
14777
+ clause: 2,
14778
+ shipped: false,
14779
+ reason: "Ontology entity."
14780
+ },
14781
+ {
14782
+ original: "triggers",
14783
+ disposition: "top-level",
14784
+ surviving: "triggers",
14785
+ clause: 2,
14786
+ shipped: false,
14787
+ reason: "Ontology entity."
14788
+ },
14789
+ {
14790
+ original: "inbound-webhooks",
14791
+ disposition: "top-level",
14792
+ surviving: "inbound-webhooks",
14793
+ clause: 2,
14794
+ shipped: false,
14795
+ reason: "Ontology entity."
14796
+ },
14797
+ {
14798
+ original: "seed",
14799
+ disposition: "top-level",
14800
+ surviving: "seed",
14801
+ clause: 2,
14802
+ shipped: false,
14803
+ reason: "Ontology entity. `wayai status` vs `wayai seed lease status` differ by depth, not by word."
14804
+ },
14805
+ // --- Clause 3: namespaced. ---
14806
+ {
14807
+ original: "use",
14808
+ disposition: "namespaced",
14809
+ surviving: "bases use",
14810
+ clause: 3,
14811
+ shipped: true,
14812
+ reason: "WayAI's `use` binds a hub; this binds a base."
14813
+ },
14814
+ {
14815
+ original: "unbind",
14816
+ disposition: "namespaced",
14817
+ surviving: "bases unbind",
14818
+ clause: 3,
14819
+ shipped: true,
14820
+ reason: "WayAI's `unbind` clears the hub binding; this clears the base binding."
14821
+ },
14822
+ {
14823
+ original: "bases promote",
14824
+ disposition: "namespaced",
14825
+ surviving: "bases promote",
14826
+ clause: 3,
14827
+ shipped: true,
14828
+ reason: "Already namespaced; kept verbatim. Distinct from `wayai publish` (hub production) \u2014 the two promote words stay distinct."
14829
+ },
14830
+ {
14831
+ original: "tokens",
14832
+ disposition: "namespaced",
14833
+ surviving: "bases tokens",
14834
+ clause: 3,
14835
+ shipped: false,
14836
+ reason: "Mints base tokens; WayAI's own token surface mints platform tokens."
14837
+ },
14838
+ {
14839
+ original: "secrets",
14840
+ disposition: "namespaced",
14841
+ surviving: "bases secrets",
14842
+ clause: 3,
14843
+ shipped: false,
14844
+ reason: "Base org vault; WayAI has connection credentials."
14845
+ },
14846
+ {
14847
+ original: "sql",
14848
+ disposition: "namespaced",
14849
+ surviving: "bases sql",
14850
+ clause: 3,
14851
+ shipped: false,
14852
+ reason: "WayAI already has tenant SQL over conversation analytics."
14853
+ },
14854
+ {
14855
+ original: "import",
14856
+ disposition: "namespaced",
14857
+ surviving: "bases import",
14858
+ clause: 3,
14859
+ shipped: false,
14860
+ reason: "WayAI has outbound-contact import."
14861
+ },
14862
+ {
14863
+ original: "batch",
14864
+ disposition: "namespaced",
14865
+ surviving: "bases batch",
14866
+ clause: 3,
14867
+ shipped: false,
14868
+ reason: "Too generic to stand alone."
14869
+ },
14870
+ {
14871
+ original: "providers",
14872
+ disposition: "namespaced",
14873
+ surviving: "bases providers",
14874
+ clause: 3,
14875
+ shipped: false,
14876
+ reason: "WayAI's provider is a connector."
14877
+ },
14878
+ {
14879
+ original: "admin",
14880
+ disposition: "namespaced",
14881
+ surviving: "admin bases",
14882
+ clause: 3,
14883
+ shipped: false,
14884
+ reason: "Clause 3's group exception: `wayai admin` is an existing group with its own gating and subgroups, so the operator surface joins it as a peer rather than sitting under `bases`."
14885
+ },
14886
+ {
14887
+ original: "report",
14888
+ disposition: "namespaced",
14889
+ surviving: "bases report",
14890
+ clause: 3,
14891
+ shipped: false,
14892
+ reason: "Two report queues still exist, so the merged CLI must be able to file to either. The two collapse when the queues do."
14893
+ },
14894
+ // --- Neither: one verb each, routing by workspace subtree. ---
14895
+ {
14896
+ original: "pull",
14897
+ disposition: "routed",
14898
+ surviving: "pull",
14899
+ clause: null,
14900
+ shipped: false,
14901
+ reason: "One verb, workspace-relative, routing by subtree: `hubs/` targets preview hubs, `bases/` targets preview bases. An invocation spanning both is refused, never merged."
14902
+ },
14903
+ {
14904
+ original: "push",
14905
+ disposition: "routed",
14906
+ surviving: "push",
14907
+ clause: null,
14908
+ shipped: false,
14909
+ reason: "Same as `pull`."
14910
+ }
14911
+ ];
14912
+ DATA_NAMESPACES = COMMAND_SURVIVAL.filter(
14913
+ (c) => c.disposition === "top-level" && c.shipped
14914
+ ).map((c) => c.surviving);
14915
+ }
14916
+ });
14917
+
14084
14918
  // src/lib/version-cache.ts
14085
14919
  import { existsSync as existsSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync2, mkdirSync } from "fs";
14086
14920
  import { dirname as dirname3, join as join6 } from "path";
@@ -14090,9 +14924,9 @@ function getVersionCachePath(filename = CLI_CACHE_FILE) {
14090
14924
  }
14091
14925
  function readVersionCache(filename = CLI_CACHE_FILE) {
14092
14926
  try {
14093
- const path30 = getVersionCachePath(filename);
14094
- if (!existsSync4(path30)) return null;
14095
- const parsed = JSON.parse(readFileSync5(path30, "utf-8"));
14927
+ const path31 = getVersionCachePath(filename);
14928
+ if (!existsSync4(path31)) return null;
14929
+ const parsed = JSON.parse(readFileSync5(path31, "utf-8"));
14096
14930
  if (typeof parsed.lastCheck !== "number") return null;
14097
14931
  if (parsed.latest !== null && typeof parsed.latest !== "string") return null;
14098
14932
  return parsed;
@@ -14112,10 +14946,10 @@ function isVersionCacheStale(filename = CLI_CACHE_FILE, maxAgeMs = MAX_AGE_24H_M
14112
14946
  return Date.now() - cache.lastCheck > maxAgeMs;
14113
14947
  }
14114
14948
  function writeVersionCache(filename, cache) {
14115
- const path30 = getVersionCachePath(filename);
14116
- const dir = dirname3(path30);
14949
+ const path31 = getVersionCachePath(filename);
14950
+ const dir = dirname3(path31);
14117
14951
  if (!existsSync4(dir)) mkdirSync(dir, { recursive: true });
14118
- writeFileSync2(path30, JSON.stringify(cache));
14952
+ writeFileSync2(path31, JSON.stringify(cache));
14119
14953
  }
14120
14954
  function touchVersionCache(filename) {
14121
14955
  writeVersionCache(filename, { lastCheck: Date.now(), latest: readVersionCache(filename)?.latest ?? null });
@@ -14154,14 +14988,14 @@ function parseFrontmatterVersion(content) {
14154
14988
  function findInstalledSkills(projectRoot, paths = SKILL_INSTALL_PATHS) {
14155
14989
  const found = [];
14156
14990
  for (const rel of paths) {
14157
- const path30 = join7(projectRoot, rel);
14158
- if (!existsSync5(path30)) continue;
14991
+ const path31 = join7(projectRoot, rel);
14992
+ if (!existsSync5(path31)) continue;
14159
14993
  let version = null;
14160
14994
  try {
14161
- version = parseFrontmatterVersion(readFileSync6(path30, "utf-8"));
14995
+ version = parseFrontmatterVersion(readFileSync6(path31, "utf-8"));
14162
14996
  } catch {
14163
14997
  }
14164
- found.push({ path: path30, version });
14998
+ found.push({ path: path31, version });
14165
14999
  }
14166
15000
  return found;
14167
15001
  }
@@ -15037,7 +15871,7 @@ var init_logout = __esm({
15037
15871
  }
15038
15872
  });
15039
15873
 
15040
- // src/lib/hub-binding.ts
15874
+ // src/lib/worktree-binding.ts
15041
15875
  import { execFileSync as execFileSync2 } from "child_process";
15042
15876
  import * as fs7 from "fs";
15043
15877
  import * as path7 from "path";
@@ -15058,111 +15892,158 @@ function resolveGitDir() {
15058
15892
  _gitDirCache = { cwd, gitDir };
15059
15893
  return gitDir;
15060
15894
  }
15061
- function getBindingPath() {
15062
- const gitDir = resolveGitDir();
15063
- return gitDir ? path7.join(gitDir, BINDING_FILENAME) : null;
15064
- }
15065
- function getLegacyBindingPath() {
15066
- const gitDir = resolveGitDir();
15067
- return gitDir ? path7.join(gitDir, LEGACY_BINDING_FILENAME) : null;
15068
- }
15069
- function readBinding() {
15070
- for (const bindingPath of [getBindingPath(), getLegacyBindingPath()]) {
15071
- if (!bindingPath) continue;
15072
- let raw;
15895
+ function createWorktreeBinding(descriptor) {
15896
+ const {
15897
+ filename,
15898
+ legacyFilename,
15899
+ isValidId,
15900
+ noun,
15901
+ idLabel,
15902
+ unbindCommand: unbindCommand2,
15903
+ useCommand: useCommand2
15904
+ } = descriptor;
15905
+ function getBindingPath2() {
15906
+ const gitDir = resolveGitDir();
15907
+ return gitDir ? path7.join(gitDir, filename) : null;
15908
+ }
15909
+ function getLegacyBindingPath() {
15910
+ if (!legacyFilename) return null;
15911
+ const gitDir = resolveGitDir();
15912
+ return gitDir ? path7.join(gitDir, legacyFilename) : null;
15913
+ }
15914
+ function readBinding2() {
15915
+ for (const bindingPath of [getBindingPath2(), getLegacyBindingPath()]) {
15916
+ if (!bindingPath) continue;
15917
+ let raw;
15918
+ try {
15919
+ raw = fs7.readFileSync(bindingPath, "utf-8");
15920
+ } catch (err) {
15921
+ if (err.code === "ENOENT") continue;
15922
+ throw err;
15923
+ }
15924
+ const trimmed = raw.trim();
15925
+ return isValidId(trimmed) ? trimmed : null;
15926
+ }
15927
+ return null;
15928
+ }
15929
+ function removeLegacyBinding() {
15930
+ const legacyPath = getLegacyBindingPath();
15931
+ if (!legacyPath) return;
15073
15932
  try {
15074
- raw = fs7.readFileSync(bindingPath, "utf-8");
15075
- } catch (err) {
15076
- if (err.code === "ENOENT") continue;
15077
- throw err;
15933
+ fs7.unlinkSync(legacyPath);
15934
+ } catch {
15078
15935
  }
15079
- const trimmed = raw.trim();
15080
- return UUID_RE2.test(trimmed) ? trimmed : null;
15081
15936
  }
15082
- return null;
15083
- }
15084
- function writeBinding(hubId) {
15085
- if (!UUID_RE2.test(hubId)) {
15086
- throw new Error(`Invalid hub_id (must be a UUID): ${hubId}`);
15937
+ function writeBinding2(id) {
15938
+ if (!isValidId(id)) {
15939
+ throw new Error(`Invalid ${idLabel}: ${id}`);
15940
+ }
15941
+ const bindingPath = getBindingPath2();
15942
+ if (!bindingPath) {
15943
+ throw new Error(`Not inside a git repository \u2014 cannot write ${noun} binding.`);
15944
+ }
15945
+ fs7.writeFileSync(bindingPath, `${id}
15946
+ `, "utf-8");
15947
+ removeLegacyBinding();
15087
15948
  }
15088
- const bindingPath = getBindingPath();
15089
- if (!bindingPath) {
15090
- throw new Error("Not inside a git repository \u2014 cannot write hub binding.");
15949
+ function clearBinding2() {
15950
+ let removed = false;
15951
+ for (const bindingPath of [getBindingPath2(), getLegacyBindingPath()]) {
15952
+ if (!bindingPath) continue;
15953
+ try {
15954
+ fs7.unlinkSync(bindingPath);
15955
+ removed = true;
15956
+ } catch (err) {
15957
+ if (err.code !== "ENOENT") throw err;
15958
+ }
15959
+ }
15960
+ return removed;
15091
15961
  }
15092
- fs7.writeFileSync(bindingPath, `${hubId}
15093
- `, "utf-8");
15094
- removeLegacyBinding();
15095
- }
15096
- function removeLegacyBinding() {
15097
- const legacyPath = getLegacyBindingPath();
15098
- if (!legacyPath) return;
15099
- try {
15100
- fs7.unlinkSync(legacyPath);
15101
- } catch {
15962
+ function assertMatchesBinding(resolvedId, label) {
15963
+ const bound = readBinding2();
15964
+ if (!bound) return;
15965
+ if (bound === resolvedId) return;
15966
+ const target = label ? `${label} (${resolvedId})` : resolvedId;
15967
+ console.error(
15968
+ [
15969
+ `This worktree is bound to ${noun} ${bound}, but the command resolved to ${target}.`,
15970
+ "",
15971
+ "This usually means a prompt was routed to the wrong worktree.",
15972
+ "Confirm with the user before unbinding. To override:",
15973
+ ` ${unbindCommand2} # clear the binding for this worktree`,
15974
+ ` ${useCommand2} ${resolvedId} # rebind this worktree to the new ${noun}`
15975
+ ].join("\n")
15976
+ );
15977
+ process.exit(1);
15102
15978
  }
15103
- }
15104
- function clearBinding() {
15105
- let removed = false;
15106
- for (const bindingPath of [getBindingPath(), getLegacyBindingPath()]) {
15107
- if (!bindingPath) continue;
15979
+ function assertNoBindingBlocksCreation(newName) {
15980
+ const bound = readBinding2();
15981
+ if (!bound) return;
15982
+ console.error(
15983
+ [
15984
+ `This worktree is bound to ${noun} ${bound}, but you're about to create a new ${noun} "${newName}" here.`,
15985
+ "",
15986
+ "This usually means a prompt was routed to the wrong worktree.",
15987
+ "Confirm with the user before unbinding. To override:",
15988
+ ` ${unbindCommand2} # clear the binding for this worktree`
15989
+ ].join("\n")
15990
+ );
15991
+ process.exit(1);
15992
+ }
15993
+ function autoBindIfUnbound2(id) {
15108
15994
  try {
15109
- fs7.unlinkSync(bindingPath);
15110
- removed = true;
15995
+ if (readBinding2()) return false;
15996
+ writeBinding2(id);
15997
+ console.log(`Worktree bound to ${noun} ${id} (run \`${unbindCommand2}\` to clear).`);
15998
+ return true;
15111
15999
  } catch (err) {
15112
- if (err.code !== "ENOENT") throw err;
16000
+ console.warn(
16001
+ ` Warning: could not auto-bind worktree (${err instanceof Error ? err.message : String(err)})`
16002
+ );
16003
+ return false;
15113
16004
  }
15114
16005
  }
15115
- return removed;
15116
- }
15117
- function assertHubMatchesBinding(resolvedHubId, hubLabel) {
15118
- const bound = readBinding();
15119
- if (!bound) return;
15120
- if (bound === resolvedHubId) return;
15121
- const target = hubLabel ? `${hubLabel} (${resolvedHubId})` : resolvedHubId;
15122
- console.error(
15123
- [
15124
- `This worktree is bound to hub ${bound}, but the command resolved to ${target}.`,
15125
- "",
15126
- "This usually means a prompt was routed to the wrong worktree.",
15127
- "Confirm with the user before unbinding. To override:",
15128
- " wayai unbind # clear the binding for this worktree",
15129
- ` wayai use ${resolvedHubId} # rebind this worktree to the new hub`
15130
- ].join("\n")
15131
- );
15132
- process.exit(1);
16006
+ return {
16007
+ getBindingPath: getBindingPath2,
16008
+ readBinding: readBinding2,
16009
+ writeBinding: writeBinding2,
16010
+ clearBinding: clearBinding2,
16011
+ assertMatchesBinding,
16012
+ assertNoBindingBlocksCreation,
16013
+ autoBindIfUnbound: autoBindIfUnbound2
16014
+ };
15133
16015
  }
15134
- function autoBindIfUnbound(hubId) {
15135
- try {
15136
- if (readBinding()) return false;
15137
- writeBinding(hubId);
15138
- console.log(`Worktree bound to hub ${hubId} (run \`wayai unbind\` to clear).`);
15139
- return true;
15140
- } catch (err) {
15141
- console.warn(` Warning: could not auto-bind worktree (${err instanceof Error ? err.message : String(err)})`);
15142
- return false;
16016
+ var _gitDirCache;
16017
+ var init_worktree_binding = __esm({
16018
+ "src/lib/worktree-binding.ts"() {
16019
+ "use strict";
15143
16020
  }
15144
- }
15145
- function assertNoBindingBlocksHubCreation(newHubName) {
15146
- const bound = readBinding();
15147
- if (!bound) return;
15148
- console.error(
15149
- [
15150
- `This worktree is bound to hub ${bound}, but you're about to create a new hub "${newHubName}" here.`,
15151
- "",
15152
- "This usually means a prompt was routed to the wrong worktree.",
15153
- "Confirm with the user before unbinding. To override:",
15154
- " wayai unbind # clear the binding for this worktree"
15155
- ].join("\n")
15156
- );
15157
- process.exit(1);
15158
- }
15159
- var BINDING_FILENAME, LEGACY_BINDING_FILENAME, _gitDirCache;
16021
+ });
16022
+
16023
+ // src/lib/hub-binding.ts
16024
+ var binding, getBindingPath, readBinding, writeBinding, clearBinding, autoBindIfUnbound, assertHubMatchesBinding, assertNoBindingBlocksHubCreation;
15160
16025
  var init_hub_binding = __esm({
15161
16026
  "src/lib/hub-binding.ts"() {
15162
16027
  "use strict";
15163
16028
  init_utils();
15164
- BINDING_FILENAME = "wayai-binding";
15165
- LEGACY_BINDING_FILENAME = "wayai-lock";
16029
+ init_worktree_binding();
16030
+ binding = createWorktreeBinding({
16031
+ filename: "wayai-binding",
16032
+ // Pre-rename filename, from when this was called a "lock".
16033
+ legacyFilename: "wayai-lock",
16034
+ isValidId: (id) => UUID_RE2.test(id),
16035
+ noun: "hub",
16036
+ idLabel: "hub_id (must be a UUID)",
16037
+ unbindCommand: "wayai unbind",
16038
+ useCommand: "wayai use"
16039
+ });
16040
+ getBindingPath = binding.getBindingPath;
16041
+ readBinding = binding.readBinding;
16042
+ writeBinding = binding.writeBinding;
16043
+ clearBinding = binding.clearBinding;
16044
+ autoBindIfUnbound = binding.autoBindIfUnbound;
16045
+ assertHubMatchesBinding = binding.assertMatchesBinding;
16046
+ assertNoBindingBlocksHubCreation = binding.assertNoBindingBlocksCreation;
15166
16047
  }
15167
16048
  });
15168
16049
 
@@ -21048,12 +21929,25 @@ function messageGrainNotes() {
21048
21929
  " - Rows are written when a conversation CLOSES, best-effort. An open",
21049
21930
  " conversation has no rows, and `message` is less durable than",
21050
21931
  " `conversation` \u2014 treat it as analysis-grade, not billing-grade.",
21051
- " - An unfiltered sum EXCEEDS the matching conversation figure by design:",
21052
- " message rows include background agents that conversation aggregates",
21053
- " exclude. To reconcile, filter NULL-safely, KEEPING the outer parentheses",
21054
- " (AND binds tighter than OR, so an unparenthesized copy combined with any",
21055
- " other condition silently readmits every NULL-role row):",
21056
- " WHERE (agent_role IS NULL OR agent_role NOT IN ('conversation_evaluator','message_evaluator','monitor'))",
21932
+ " - An unfiltered sum EQUALS the matching conversation figure: `message` is the",
21933
+ " DECOMPOSITION of that figure, every agent role included. Use the filter below",
21934
+ " only to ISOLATE the spend a hub's own agents did, splitting it from platform",
21935
+ " background work (evaluators, monitor, summarizer). It lands at or below the",
21936
+ " conversation total \u2014 `filtered <= total`, strict only when an excluded row",
21937
+ " actually contributed to the metric you selected. A conversation that ran no",
21938
+ " background agent has nothing to exclude, so equality there is correct, not a",
21939
+ " fault. Filter NULL-safely, KEEPING the outer parentheses (AND binds tighter",
21940
+ " than OR, so an unparenthesized copy combined with any other condition silently",
21941
+ " readmits every NULL-role row):",
21942
+ " WHERE (agent_role IS NULL OR agent_role NOT IN ('conversation_evaluator','message_evaluator','monitor','summarizer'))",
21943
+ " - HISTORICAL BOUNDARIES \u2014 TWO, both forward-only and neither backfilled, so a",
21944
+ " conversation reflects whichever rules were live when it CLOSED:",
21945
+ " * `summarizer` spend entered BOTH tables when the provider-usage carrier",
21946
+ " shipped. Before that it was recorded nowhere; no query recovers it.",
21947
+ " * evaluator and monitor spend entered the `conversation` aggregate later,",
21948
+ " when the role exclusion narrowed to shape only. `message` carried those",
21949
+ " rows all along, so for a window spanning only that second change, summing",
21950
+ " `message` is the continuous answer.",
21057
21951
  " - `connection_id` names the LLM connection only. TTS/STT/container spend",
21058
21952
  " is folded into the same row, so attributing cost to a credential means",
21059
21953
  " netting out cost_usd_tts / cost_usd_stt / cost_usd_container.",
@@ -21063,7 +21957,8 @@ function messageGrainNotes() {
21063
21957
  " - BOUND created_at. The table retains five years at per-message volume, so",
21064
21958
  " an unbounded scan is the expensive way to ask any question:",
21065
21959
  " WHERE created_at >= now() - INTERVAL 30 DAY",
21066
- " - The conversation figure stays the customer-visible one."
21960
+ " - The conversation figure stays the customer-visible one, and it is now the",
21961
+ " TOTAL: every role that spent on the conversation is in it."
21067
21962
  ];
21068
21963
  }
21069
21964
  function splitFilterExpr(raw, shape) {
@@ -23275,7 +24170,9 @@ Sources:
23275
24170
  do Live DO SQLite (existing conversation, hub config, etc.).
23276
24171
  analytics ClickHouse projections (conversation, message, schedule_event).
23277
24172
  \`message\` is per-message usage facts and INCLUDES background agent
23278
- roles, so its unfiltered sums exceed the conversation figures.
24173
+ roles, as the conversation figures now do \u2014 so its unfiltered sums
24174
+ REPRODUCE them, and filtering those roles out lands at or below
24175
+ (equal when the conversation ran no background agent).
23279
24176
  archive R2 archive blob \u2014 canonical content for ended conversations after DO cleanup.
23280
24177
  observability R2 LLM observability \u2014 per-message OTel GenAI records (prompts, completions,
23281
24178
  tool calls, tokens, latency). Default lists all records for the conversation;
@@ -23844,14 +24741,538 @@ var init_update = __esm({
23844
24741
  }
23845
24742
  });
23846
24743
 
24744
+ // src/data/org-context.ts
24745
+ function setDataOrgOverride(orgId) {
24746
+ override = orgId;
24747
+ }
24748
+ function getDataOrgOverride() {
24749
+ return override;
24750
+ }
24751
+ var override;
24752
+ var init_org_context = __esm({
24753
+ "src/data/org-context.ts"() {
24754
+ "use strict";
24755
+ }
24756
+ });
24757
+
24758
+ // src/data/client.ts
24759
+ async function createDataClient(orgId) {
24760
+ const { config, accessToken } = await requireAuth();
24761
+ const api = new ApiClient({ apiUrl: config.api_url, accessToken });
24762
+ const selected = orgId ?? getDataOrgOverride();
24763
+ if (selected !== void 0 && !UUID_RE2.test(selected)) {
24764
+ throw expected(`Invalid --org: ${JSON.stringify(selected)}. Expected an organization UUID.`);
24765
+ }
24766
+ const org = selected ?? readRepoConfig()?.organization_id;
24767
+ return {
24768
+ async request(method, v1Path, body) {
24769
+ const envelope = await api.dataRequest(method, v1Path, body, org);
24770
+ return envelope.data;
24771
+ },
24772
+ async collectPages(makePath) {
24773
+ const all = [];
24774
+ const seen = /* @__PURE__ */ new Set();
24775
+ let cursor;
24776
+ for (let page = 0; page < MAX_PAGES; page++) {
24777
+ const { data, meta } = await api.dataRequest("GET", makePath(cursor), void 0, org);
24778
+ for (const row of data ?? []) all.push(row);
24779
+ cursor = meta?.has_more ? meta.cursor : void 0;
24780
+ if (cursor === void 0) break;
24781
+ if (seen.has(cursor)) break;
24782
+ seen.add(cursor);
24783
+ }
24784
+ return all;
24785
+ }
24786
+ };
24787
+ }
24788
+ var MAX_PAGES;
24789
+ var init_client = __esm({
24790
+ "src/data/client.ts"() {
24791
+ "use strict";
24792
+ init_auth();
24793
+ init_api_client();
24794
+ init_repo_config();
24795
+ init_utils();
24796
+ init_expected();
24797
+ init_org_context();
24798
+ MAX_PAGES = 1e3;
24799
+ }
24800
+ });
24801
+
24802
+ // src/data/output.ts
24803
+ function printOutput(data, format) {
24804
+ if (format === "json") {
24805
+ console.log(JSON.stringify(data, null, 2));
24806
+ return;
24807
+ }
24808
+ if (Array.isArray(data)) {
24809
+ printRows(data);
24810
+ return;
24811
+ }
24812
+ if (typeof data === "object" && data !== null) {
24813
+ printFields(data);
24814
+ return;
24815
+ }
24816
+ console.log(formatCell2(data));
24817
+ }
24818
+ function printRows(rows) {
24819
+ if (rows.length === 0) {
24820
+ console.log("(no results)");
24821
+ return;
24822
+ }
24823
+ const columns = [];
24824
+ const seen = /* @__PURE__ */ new Set();
24825
+ for (const row of rows) {
24826
+ for (const key of Object.keys(row ?? {})) {
24827
+ if (seen.has(key)) continue;
24828
+ seen.add(key);
24829
+ columns.push(key);
24830
+ }
24831
+ }
24832
+ const headers = columns.map((c) => sanitizeTerminalText(c));
24833
+ const cells = rows.map((row) => columns.map((c) => cellAt(row, c)));
24834
+ const widths = columns.map(
24835
+ (_, i) => cells.reduce((width, row) => Math.max(width, row[i].length), headers[i].length)
24836
+ );
24837
+ console.log(headers.map((c, i) => c.padEnd(widths[i])).join(" "));
24838
+ console.log(widths.map((w) => "-".repeat(w)).join(" "));
24839
+ for (const row of cells) {
24840
+ console.log(row.map((cell, i) => cell.padEnd(widths[i])).join(" "));
24841
+ }
24842
+ }
24843
+ function printFields(obj) {
24844
+ const entries = Object.entries(obj).map(([key, value]) => ({
24845
+ key: sanitizeTerminalText(key),
24846
+ value
24847
+ }));
24848
+ if (entries.length === 0) {
24849
+ console.log("(empty)");
24850
+ return;
24851
+ }
24852
+ const width = entries.reduce((w, e) => Math.max(w, e.key.length), 0);
24853
+ for (const { key, value } of entries) {
24854
+ console.log(`${key.padEnd(width)} ${formatCell2(value)}`);
24855
+ }
24856
+ }
24857
+ function cellAt(row, column) {
24858
+ return formatCell2(row?.[column]);
24859
+ }
24860
+ function formatCell2(value) {
24861
+ if (value === null || value === void 0) return "";
24862
+ if (typeof value === "object") return sanitizeTerminalText(JSON.stringify(value));
24863
+ return sanitizeTerminalText(String(value));
24864
+ }
24865
+ var init_output = __esm({
24866
+ "src/data/output.ts"() {
24867
+ "use strict";
24868
+ init_terminal_output();
24869
+ }
24870
+ });
24871
+
24872
+ // src/lib/base-id.ts
24873
+ function isValidBaseId(id) {
24874
+ return BASE_ID_RE.test(id);
24875
+ }
24876
+ var BASE_ID_RE;
24877
+ var init_base_id = __esm({
24878
+ "src/lib/base-id.ts"() {
24879
+ "use strict";
24880
+ BASE_ID_RE = /^(?!\.\.?$)[A-Za-z0-9._-]{1,256}$/;
24881
+ }
24882
+ });
24883
+
24884
+ // src/data/helpers.ts
24885
+ import { readFileSync as readFileSync19 } from "fs";
24886
+ function pathSegment(id, label = "id") {
24887
+ if (!isValidBaseId(id)) {
24888
+ throw expected(
24889
+ `Invalid ${label}: ${JSON.stringify(id)}. Ids are slugs \u2014 letters, digits, dot, dash and underscore only.`
24890
+ );
24891
+ }
24892
+ return encodeURIComponent(id);
24893
+ }
24894
+ function parseData(data) {
24895
+ if (data.startsWith("@")) {
24896
+ return JSON.parse(readFileSync19(data.slice(1), "utf-8"));
24897
+ }
24898
+ return JSON.parse(data);
24899
+ }
24900
+ function globals(cmd) {
24901
+ let namespace = cmd;
24902
+ while (namespace.parent?.parent) namespace = namespace.parent;
24903
+ return namespace.opts();
24904
+ }
24905
+ function outputFormat(cmd) {
24906
+ const opts = globals(cmd);
24907
+ return opts.json || opts.output === "json" ? "json" : "table";
24908
+ }
24909
+ function splitList(value) {
24910
+ return value.split(",").map((v) => v.trim()).filter((v) => v.length > 0);
24911
+ }
24912
+ var init_helpers = __esm({
24913
+ "src/data/helpers.ts"() {
24914
+ "use strict";
24915
+ init_base_id();
24916
+ init_expected();
24917
+ }
24918
+ });
24919
+
24920
+ // src/lib/base-binding.ts
24921
+ var binding2, getBaseBindingPath, readBaseBinding, writeBaseBinding, clearBaseBinding, autoBindBaseIfUnbound, assertBaseMatchesBinding, assertNoBindingBlocksBaseCreation;
24922
+ var init_base_binding = __esm({
24923
+ "src/lib/base-binding.ts"() {
24924
+ "use strict";
24925
+ init_base_id();
24926
+ init_worktree_binding();
24927
+ binding2 = createWorktreeBinding({
24928
+ filename: "wayai-base-binding",
24929
+ isValidId: isValidBaseId,
24930
+ noun: "base",
24931
+ idLabel: "base id (must be a slug)",
24932
+ unbindCommand: "wayai bases unbind",
24933
+ useCommand: "wayai bases use"
24934
+ });
24935
+ getBaseBindingPath = binding2.getBindingPath;
24936
+ readBaseBinding = binding2.readBinding;
24937
+ writeBaseBinding = binding2.writeBinding;
24938
+ clearBaseBinding = binding2.clearBinding;
24939
+ autoBindBaseIfUnbound = binding2.autoBindIfUnbound;
24940
+ assertBaseMatchesBinding = binding2.assertMatchesBinding;
24941
+ assertNoBindingBlocksBaseCreation = binding2.assertNoBindingBlocksCreation;
24942
+ }
24943
+ });
24944
+
24945
+ // src/data/commands/bases.ts
24946
+ import { Command } from "commander";
24947
+ import * as fs24 from "fs";
24948
+ import * as path30 from "path";
24949
+ import * as yaml9 from "js-yaml";
24950
+ function pageOf(path31, cursor) {
24951
+ if (!cursor) return path31;
24952
+ return `${path31}${path31.includes("?") ? "&" : "?"}cursor=${encodeURIComponent(cursor)}`;
24953
+ }
24954
+ function parseEnum(flag, value, allowed) {
24955
+ if (value === void 0) return void 0;
24956
+ if (!allowed.includes(value)) {
24957
+ throw expected(`${flag} must be one of: ${allowed.join(", ")}.`);
24958
+ }
24959
+ return value;
24960
+ }
24961
+ function buildBasesCommand() {
24962
+ const bases = new Command("bases").description("Manage bases");
24963
+ bases.command("list").description("List all bases").option("--tag <tag>", "Filter by tag").action(async function(opts) {
24964
+ const client = await createDataClient();
24965
+ const qs = opts.tag ? `?tag=${encodeURIComponent(opts.tag)}` : "";
24966
+ printOutput(
24967
+ await client.collectPages((cursor) => pageOf(`/v1/bases${qs}`, cursor)),
24968
+ outputFormat(this)
24969
+ );
24970
+ });
24971
+ bases.command("get <id>").description("Get a base").action(async function(id) {
24972
+ const client = await createDataClient();
24973
+ printOutput(await client.request("GET", `/v1/bases/${pathSegment(id)}`), outputFormat(this));
24974
+ });
24975
+ bases.command("create <id>").description("Create a base").requiredOption("--name <name>", "Base name").option("--description <desc>", "Description").option("--tags <tags>", "Comma-separated tags (e.g. client:acme,billing)").option(
24976
+ "--timezone <tz>",
24977
+ "Default IANA timezone for datetime canonicalization (e.g. America/Sao_Paulo); a record type's own timezone overrides it"
24978
+ ).option(
24979
+ "--environment <env>",
24980
+ "production (default) | preview. Production bases require a paid plan. A preview created here has no production origin and cannot be given one later, so it cannot be promoted directly \u2014 move its config to a linked preview with pull/push when you upgrade"
24981
+ ).action(async function(id, opts) {
24982
+ const environment = parseEnum("--environment", opts.environment, [
24983
+ "production",
24984
+ "preview"
24985
+ ]);
24986
+ const client = await createDataClient();
24987
+ const body = { name: opts.name, description: opts.description };
24988
+ if (environment) body.environment = environment;
24989
+ if (opts.tags) body.tags = splitList(opts.tags);
24990
+ if (opts.timezone) body.settings = { timezone: opts.timezone };
24991
+ printOutput(await client.request("PUT", `/v1/bases/${pathSegment(id)}`, body), outputFormat(this));
24992
+ });
24993
+ bases.command("update <id>").description(
24994
+ "Update a base's mutable config (display name, description, tags, default timezone/settings). The id/slug is immutable."
24995
+ ).option("--name <name>", "New display name").option("--description <desc>", "Description").option("--tags <tags>", "Comma-separated tags \u2014 replaces the existing tags").option(
24996
+ "--timezone <tz>",
24997
+ "Default IANA timezone for datetime canonicalization. Merges into existing settings."
24998
+ ).option(
24999
+ "--settings <json>",
25000
+ "Raw settings JSON object (inline JSON or @file.json) \u2014 replaces the entire settings object"
25001
+ ).option(
25002
+ "--integrations <mode>",
25003
+ "enabled | disabled. Preview-only: `disabled` neutralizes every external integration edge so the seeded preview behaves natively for production-safe agent evals"
25004
+ ).action(async function(id, opts) {
25005
+ const integrations = parseEnum("--integrations", opts.integrations, ["enabled", "disabled"]);
25006
+ if (opts.name === void 0 && opts.description === void 0 && opts.tags === void 0 && opts.timezone === void 0 && opts.settings === void 0 && integrations === void 0) {
25007
+ throw expected(
25008
+ "Nothing to update. Provide at least one of --name, --description, --tags, --timezone, --settings, --integrations."
25009
+ );
25010
+ }
25011
+ const client = await createDataClient();
25012
+ const body = {};
25013
+ if (opts.name !== void 0) body.name = opts.name;
25014
+ if (opts.description !== void 0) body.description = opts.description;
25015
+ if (opts.tags !== void 0) body.tags = splitList(opts.tags);
25016
+ if (integrations !== void 0) body.integrations = integrations;
25017
+ if (opts.settings !== void 0 || opts.timezone !== void 0) {
25018
+ let settings;
25019
+ if (opts.settings !== void 0) {
25020
+ let parsed;
25021
+ try {
25022
+ parsed = parseData(opts.settings);
25023
+ } catch (e) {
25024
+ throw expected(`--settings: ${e instanceof Error ? e.message : "could not be read as JSON"}`);
25025
+ }
25026
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
25027
+ throw expected("--settings must be a valid JSON object");
25028
+ }
25029
+ settings = parsed;
25030
+ } else {
25031
+ const existing = await client.request("GET", `/v1/bases/${pathSegment(id)}`);
25032
+ settings = { ...existing?.settings ?? {} };
25033
+ }
25034
+ if (opts.timezone !== void 0) settings.timezone = opts.timezone;
25035
+ body.settings = settings;
25036
+ }
25037
+ printOutput(await client.request("PUT", `/v1/bases/${pathSegment(id)}`, body), outputFormat(this));
25038
+ });
25039
+ bases.command("rename <id>").description(
25040
+ "Rename a base's display name (the id/slug is immutable \u2014 it scopes token grants, MCP endpoints, and references)"
25041
+ ).requiredOption("--name <name>", "New display name").action(async function(id, opts) {
25042
+ const client = await createDataClient();
25043
+ printOutput(
25044
+ await client.request("PUT", `/v1/bases/${pathSegment(id)}`, { name: opts.name }),
25045
+ outputFormat(this)
25046
+ );
25047
+ });
25048
+ bases.command("tag <id>").description("Set tags on a base").requiredOption("--tags <tags>", "Comma-separated tags (e.g. client:acme,billing)").action(async function(id, opts) {
25049
+ const client = await createDataClient();
25050
+ printOutput(
25051
+ await client.request("PUT", `/v1/bases/${pathSegment(id)}`, { tags: splitList(opts.tags) }),
25052
+ outputFormat(this)
25053
+ );
25054
+ });
25055
+ bases.command("delete <id>").description(
25056
+ "Delete a base. By default this is a tombstone: the base stops being listed, but its storage is retained and recreating the id restores it. Add --purge (preview bases only) to also reclaim the storage"
25057
+ ).option("-y, --yes", "Skip confirmation prompt").option(
25058
+ "--purge",
25059
+ "Preview bases only. Permanently destroy the stored records, relationships, file metadata and config of this base instead of tombstoning it. The id is then retired and cannot be recreated"
25060
+ ).action(async function(id, opts) {
25061
+ const prompt3 = opts.purge ? `Purge base "${id}"? Its records, relationships, file metadata and config are destroyed permanently, and the id "${id}" is retired for good.` : `Delete base "${id}"? This cannot be undone.`;
25062
+ if (!opts.yes && !await confirm(prompt3)) {
25063
+ console.log("Aborted");
25064
+ return;
25065
+ }
25066
+ const client = await createDataClient();
25067
+ await client.request("DELETE", `/v1/bases/${pathSegment(id)}${opts.purge ? "?purge=true" : ""}`);
25068
+ printOutput({ id, deleted: true, purged: opts.purge === true }, outputFormat(this));
25069
+ });
25070
+ bases.command("create-preview <origin-id>").description(
25071
+ "Create a preview base by cloning the config of another base. The origin may be a production base or another preview; the new preview id is <origin-id>--<name>, linked to the origin it was cloned from (so a preview of a preview promotes through that origin, never straight to production)"
25072
+ ).requiredOption("--name <name>", "Preview base name").option("--description <desc>", "Description").option(
25073
+ "--integrations <mode>",
25074
+ "enabled (default) | disabled. `disabled` makes this preview a seeded, production-safe agent-eval target: every external integration edge is inert and it behaves natively"
25075
+ ).option(
25076
+ "--create-only",
25077
+ "Fail with 409 if the derived preview id already exists, instead of re-applying config onto it. Use for per-session ephemeral bases, where landing on a live sibling would corrupt both runs"
25078
+ ).action(async function(originId, opts) {
25079
+ const integrations = parseEnum("--integrations", opts.integrations, ["enabled", "disabled"]);
25080
+ const client = await createDataClient();
25081
+ printOutput(
25082
+ await client.request("POST", `/v1/${pathSegment(originId, "origin base id")}/preview`, {
25083
+ name: opts.name,
25084
+ description: opts.description,
25085
+ ...integrations !== void 0 ? { integrations } : {},
25086
+ ...opts.createOnly ? { create_only: true } : {}
25087
+ }),
25088
+ outputFormat(this)
25089
+ );
25090
+ });
25091
+ bases.command("list-previews <origin-id>").description("List preview bases cloned from a base (production or preview)").action(async function(originId) {
25092
+ const client = await createDataClient();
25093
+ const path31 = `/v1/${pathSegment(originId, "origin base id")}/previews`;
25094
+ printOutput(
25095
+ await client.collectPages((cursor) => pageOf(path31, cursor)),
25096
+ outputFormat(this)
25097
+ );
25098
+ });
25099
+ bases.command("promote <production-id>").description("Promote config from a preview base to production (human-only)").requiredOption("--from <preview-id>", "Source preview base id").option("--dry-run", "Show what would change without applying").option("--record-types <ids>", "Comma-separated record type ids to promote", splitList).option("--triggers <ids>", "Comma-separated trigger ids to promote", splitList).option("--inbound-webhooks <ids>", "Comma-separated inbound webhook ids to promote", splitList).action(async function(productionId, opts) {
25100
+ const client = await createDataClient();
25101
+ const data = await client.request("POST", `/v1/${pathSegment(productionId, "production base id")}/promote`, {
25102
+ source_base_id: opts.from,
25103
+ dry_run: opts.dryRun ?? false,
25104
+ record_types: opts.recordTypes,
25105
+ triggers: opts.triggers,
25106
+ inbound_webhooks: opts.inboundWebhooks
25107
+ });
25108
+ printOutput(data, outputFormat(this));
25109
+ const warnings = data?.source_credential_warnings ?? [];
25110
+ if (warnings.length > 0) {
25111
+ console.warn(
25112
+ "\nExternal source credentials are NOT carried over by promotion \u2014 set these on production before the source will work:"
25113
+ );
25114
+ for (const w of warnings) console.warn(` - ${sanitizeTerminalText(w.message)}`);
25115
+ }
25116
+ });
25117
+ bases.command("rollback <production-id>").description("Roll back a promotion (human-only)").requiredOption("--promotion <promotion-id>", "Promotion id to roll back").action(async function(productionId, opts) {
25118
+ const client = await createDataClient();
25119
+ printOutput(
25120
+ await client.request("POST", `/v1/${pathSegment(productionId, "production base id")}/promote/rollback`, {
25121
+ promotion_id: opts.promotion
25122
+ }),
25123
+ outputFormat(this)
25124
+ );
25125
+ });
25126
+ bases.command("promotions <production-id>").description("List promotion history for a production base").action(async function(productionId) {
25127
+ const client = await createDataClient();
25128
+ const path31 = `/v1/${pathSegment(productionId, "production base id")}/promotions`;
25129
+ printOutput(
25130
+ await client.collectPages((cursor) => pageOf(path31, cursor)),
25131
+ outputFormat(this)
25132
+ );
25133
+ });
25134
+ bases.command("use <base>").description(
25135
+ "Bind this worktree to a base so push/pull refuse to run against a different one"
25136
+ ).action(async function(selector) {
25137
+ const baseId = resolveSelectorToBaseId(selector);
25138
+ const previous = readBaseBinding();
25139
+ if (previous !== baseId) {
25140
+ try {
25141
+ writeBaseBinding(baseId);
25142
+ } catch (err) {
25143
+ throw expected(err instanceof Error ? err.message : String(err));
25144
+ }
25145
+ }
25146
+ if (outputFormat(this) === "json") {
25147
+ printOutput({ base_id: baseId, previous_base_id: previous, changed: previous !== baseId }, "json");
25148
+ return;
25149
+ }
25150
+ if (previous === baseId) {
25151
+ console.log(`Worktree already bound to base ${baseId}.`);
25152
+ } else {
25153
+ console.log(
25154
+ previous ? `Worktree rebound: ${previous} -> ${baseId}.` : `Worktree bound to base ${baseId}.`
25155
+ );
25156
+ }
25157
+ });
25158
+ bases.command("unbind").description("Clear the base binding for this worktree").action(async function() {
25159
+ const previous = readBaseBinding();
25160
+ if (previous) clearBaseBinding();
25161
+ if (outputFormat(this) === "json") {
25162
+ printOutput({ previous_base_id: previous, cleared: previous !== null }, "json");
25163
+ return;
25164
+ }
25165
+ console.log(
25166
+ previous ? `Worktree unbound from base (was: ${previous}).` : "No base binding to clear."
25167
+ );
25168
+ });
25169
+ return bases;
25170
+ }
25171
+ function resolveSelectorToBaseId(selector) {
25172
+ const gitRoot = findGitRoot();
25173
+ if (!gitRoot || selector.includes("/") || selector.includes(path30.sep)) return selector;
25174
+ if (!isValidBaseId(selector)) return selector;
25175
+ const metaPath = path30.join(resolveBasesDir(gitRoot), selector, BASE_META_FILE);
25176
+ let meta;
25177
+ try {
25178
+ meta = yaml9.load(fs24.readFileSync(metaPath, "utf-8"));
25179
+ } catch {
25180
+ return selector;
25181
+ }
25182
+ const id = meta?.[BASE_ID_FIELD];
25183
+ return typeof id === "string" && isValidBaseId(id) ? id : selector;
25184
+ }
25185
+ var BASE_META_FILE, BASE_ID_FIELD;
25186
+ var init_bases = __esm({
25187
+ "src/data/commands/bases.ts"() {
25188
+ "use strict";
25189
+ init_client();
25190
+ init_output();
25191
+ init_helpers();
25192
+ init_utils();
25193
+ init_terminal_output();
25194
+ init_workspace();
25195
+ init_layout();
25196
+ init_base_binding();
25197
+ init_base_id();
25198
+ init_expected();
25199
+ BASE_META_FILE = "base.yaml";
25200
+ BASE_ID_FIELD = "base_id";
25201
+ }
25202
+ });
25203
+
25204
+ // src/data/program.ts
25205
+ var program_exports = {};
25206
+ __export(program_exports, {
25207
+ DATA_NAMESPACES: () => DATA_NAMESPACES,
25208
+ buildDataProgram: () => buildDataProgram,
25209
+ isDataNamespace: () => isDataNamespace,
25210
+ runDataCommand: () => runDataCommand,
25211
+ withBaseOption: () => withBaseOption,
25212
+ withDataGlobals: () => withDataGlobals
25213
+ });
25214
+ import { Command as Command2 } from "commander";
25215
+ function withDataGlobals(command2) {
25216
+ return command2.option("--org <uuid>", "Organization to operate against (overrides .wayai.yaml)").option("--output <format>", "Output format: json or table", "table").option("--json", "Shorthand for --output json");
25217
+ }
25218
+ function withBaseOption(command2) {
25219
+ return command2.option("--base <id>", "Base id (or set WAYAI_BASE)");
25220
+ }
25221
+ function routeErrorsToCli(command2) {
25222
+ command2.exitOverride().configureOutput({ outputError: () => {
25223
+ } });
25224
+ for (const child of command2.commands) routeErrorsToCli(child);
25225
+ return command2;
25226
+ }
25227
+ function buildDataProgram() {
25228
+ const program = new Command2("wayai");
25229
+ program.addCommand(withDataGlobals(buildBasesCommand()));
25230
+ program.hook("preAction", (_thisCommand, actionCommand) => {
25231
+ setDataOrgOverride(globals(actionCommand).org);
25232
+ });
25233
+ return routeErrorsToCli(program);
25234
+ }
25235
+ async function runDataCommand(namespace, args2) {
25236
+ if (!isDataNamespace(namespace)) {
25237
+ throw new Error(`Not a Data command: ${namespace}`);
25238
+ }
25239
+ const program = buildDataProgram();
25240
+ try {
25241
+ await program.parseAsync(["node", "wayai", namespace, ...args2]);
25242
+ } catch (err) {
25243
+ const { code, exitCode } = err ?? {};
25244
+ if (code === "commander.helpDisplayed" || code === "commander.version") return;
25245
+ if (code === "commander.help") {
25246
+ process.exitCode = exitCode || 1;
25247
+ return;
25248
+ }
25249
+ if (typeof code === "string" && code.startsWith("commander.")) {
25250
+ throw expected(err instanceof Error ? err.message : String(err));
25251
+ }
25252
+ throw err;
25253
+ }
25254
+ }
25255
+ var init_program = __esm({
25256
+ "src/data/program.ts"() {
25257
+ "use strict";
25258
+ init_bases();
25259
+ init_helpers();
25260
+ init_expected();
25261
+ init_org_context();
25262
+ init_registry();
25263
+ init_registry();
25264
+ }
25265
+ });
25266
+
23847
25267
  // src/index.ts
23848
25268
  init_sentry();
23849
25269
  init_errors2();
23850
25270
  init_mask_secrets();
23851
25271
  init_utils();
23852
- import { readFileSync as readFileSync19 } from "fs";
25272
+ init_registry();
25273
+ import { readFileSync as readFileSync21 } from "fs";
23853
25274
  import { fileURLToPath as fileURLToPath2 } from "url";
23854
- import { dirname as dirname9, join as join27 } from "path";
25275
+ import { dirname as dirname9, join as join28 } from "path";
23855
25276
 
23856
25277
  // src/lib/version-refresh.ts
23857
25278
  init_version_cache();
@@ -24007,12 +25428,12 @@ Run \`wayai admin skill install\` to update.`);
24007
25428
 
24008
25429
  // src/index.ts
24009
25430
  var __dirname = dirname9(fileURLToPath2(import.meta.url));
24010
- var pkg = JSON.parse(readFileSync19(join27(__dirname, "..", "package.json"), "utf-8"));
25431
+ var pkg = JSON.parse(readFileSync21(join28(__dirname, "..", "package.json"), "utf-8"));
24011
25432
  var [, , command, ...args] = process.argv;
24012
25433
  var isBackgroundRefresh = command === REFRESH_COMMAND;
24013
25434
  if (!isBackgroundRefresh) initSentry(command, pkg.version);
24014
25435
  async function main() {
24015
- if (shouldInterceptHelp(command, args, OWN_HELP_COMMANDS)) {
25436
+ if (shouldInterceptHelp(command, args, /* @__PURE__ */ new Set([...OWN_HELP_COMMANDS, ...DATA_NAMESPACES]))) {
24016
25437
  printHelp3();
24017
25438
  return;
24018
25439
  }
@@ -24211,10 +25632,16 @@ async function main() {
24211
25632
  case "-v":
24212
25633
  console.log(pkg.version);
24213
25634
  break;
24214
- default:
25635
+ default: {
25636
+ const { isDataNamespace: isDataNamespace2, runDataCommand: runDataCommand2 } = await Promise.resolve().then(() => (init_program(), program_exports));
25637
+ if (isDataNamespace2(command)) {
25638
+ await runDataCommand2(command, args);
25639
+ break;
25640
+ }
24215
25641
  console.error(`Unknown command: ${command}`);
24216
25642
  printHelp3();
24217
25643
  process.exit(1);
25644
+ }
24218
25645
  }
24219
25646
  }
24220
25647
  function printHelp3() {
@@ -24265,6 +25692,13 @@ Commands:
24265
25692
  report edit Amend your own pending report (title/description/error/steps/context)
24266
25693
  update Update CLI to the latest version
24267
25694
 
25695
+ Data (bases):
25696
+ bases Manage bases (list/get/create/update/delete, previews, promote)
25697
+ bases promote Promote a preview base to production (distinct from \`publish\`, which promotes a hub)
25698
+ bases use <base> Bind this worktree to a base (\`wayai use\` binds a hub)
25699
+ bases unbind Clear this worktree's base binding
25700
+ Run \`wayai bases --help\` for the full tree.
25701
+
24268
25702
  Flags:
24269
25703
  --yes, -y Skip confirmation prompts (useful for CI and scripting)
24270
25704
  --hub <uuid|name> Target hub when the workspace has more than one (push, pull, diff, replicate, relabel, publish)