@wayai/cli 0.3.198 → 0.3.200

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
@@ -2476,6 +2476,24 @@ var init_chunk_SNA2DXAC = __esm({
2476
2476
  }
2477
2477
  });
2478
2478
 
2479
+ // ../../packages/core/dist/chunk-MIWZOSPI.js
2480
+ function toIso(epochMs) {
2481
+ return new Date(epochMs).toISOString();
2482
+ }
2483
+ function fromIso(iso) {
2484
+ return new Date(iso).getTime();
2485
+ }
2486
+ function isIsoTimestamp(value) {
2487
+ return typeof value === "string" && ISO_UTC_RE.test(value);
2488
+ }
2489
+ var ISO_UTC_RE;
2490
+ var init_chunk_MIWZOSPI = __esm({
2491
+ "../../packages/core/dist/chunk-MIWZOSPI.js"() {
2492
+ "use strict";
2493
+ ISO_UTC_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
2494
+ }
2495
+ });
2496
+
2479
2497
  // ../../packages/core/dist/chunk-IBL7FANV.js
2480
2498
  var SUMMARIZATION_THRESHOLD_MIN, SUMMARIZATION_THRESHOLD_MAX;
2481
2499
  var init_chunk_IBL7FANV = __esm({
@@ -2486,6 +2504,20 @@ var init_chunk_IBL7FANV = __esm({
2486
2504
  }
2487
2505
  });
2488
2506
 
2507
+ // ../../packages/core/dist/chunk-2ISUBJG7.js
2508
+ var 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;
2509
+ var init_chunk_2ISUBJG7 = __esm({
2510
+ "../../packages/core/dist/chunk-2ISUBJG7.js"() {
2511
+ "use strict";
2512
+ EVAL_PACING_PRESET_NAMES = ["conservative", "balanced", "fast", "custom"];
2513
+ PACING_INTERVAL_MIN_MS = 50;
2514
+ PACING_INTERVAL_MAX_MS = 6e4;
2515
+ EVAL_MAX_RUNS_PER_SCENARIO = 100;
2516
+ EVAL_RUN_DEADLINE_MIN_MS = 1e3;
2517
+ EVAL_RUN_DEADLINE_MAX_MS = 18e5;
2518
+ }
2519
+ });
2520
+
2489
2521
  // ../../packages/core/dist/chunk-C2UEA2KW.js
2490
2522
  var FLAG_CONDITION_OPERATORS;
2491
2523
  var init_chunk_C2UEA2KW = __esm({
@@ -6652,24 +6684,6 @@ var init_chunk_3NS3HULK = __esm({
6652
6684
  }
6653
6685
  });
6654
6686
 
6655
- // ../../packages/core/dist/chunk-MIWZOSPI.js
6656
- function toIso(epochMs) {
6657
- return new Date(epochMs).toISOString();
6658
- }
6659
- function fromIso(iso) {
6660
- return new Date(iso).getTime();
6661
- }
6662
- function isIsoTimestamp(value) {
6663
- return typeof value === "string" && ISO_UTC_RE.test(value);
6664
- }
6665
- var ISO_UTC_RE;
6666
- var init_chunk_MIWZOSPI = __esm({
6667
- "../../packages/core/dist/chunk-MIWZOSPI.js"() {
6668
- "use strict";
6669
- ISO_UTC_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
6670
- }
6671
- });
6672
-
6673
6687
  // ../../packages/core/dist/chunk-JWPRTSIB.js
6674
6688
  function normalizeAuthType(raw) {
6675
6689
  if (VALID_AUTH_TYPES.has(raw)) return raw;
@@ -6906,21 +6920,7 @@ var init_chunk_T7KQKDET = __esm({
6906
6920
  }
6907
6921
  });
6908
6922
 
6909
- // ../../packages/core/dist/chunk-2ISUBJG7.js
6910
- var 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;
6911
- var init_chunk_2ISUBJG7 = __esm({
6912
- "../../packages/core/dist/chunk-2ISUBJG7.js"() {
6913
- "use strict";
6914
- EVAL_PACING_PRESET_NAMES = ["conservative", "balanced", "fast", "custom"];
6915
- PACING_INTERVAL_MIN_MS = 50;
6916
- PACING_INTERVAL_MAX_MS = 6e4;
6917
- EVAL_MAX_RUNS_PER_SCENARIO = 100;
6918
- EVAL_RUN_DEADLINE_MIN_MS = 1e3;
6919
- EVAL_RUN_DEADLINE_MAX_MS = 18e5;
6920
- }
6921
- });
6922
-
6923
- // ../../packages/core/dist/chunk-YEYIDIR6.js
6923
+ // ../../packages/core/dist/chunk-T2RKGBYS.js
6924
6924
  function containsKanbanPlaceholders(value) {
6925
6925
  if (value == null) return false;
6926
6926
  const serialized = typeof value === "string" ? value : JSON.stringify(value);
@@ -7236,13 +7236,33 @@ function refineToolConfig(value, ctx) {
7236
7236
  }
7237
7237
  }
7238
7238
  }
7239
+ function byLocale(entry) {
7240
+ const shape = Object.fromEntries(SUPPORTED_LOCALES.map((locale) => [locale, entry.optional()]));
7241
+ return external_exports.object(shape).strict();
7242
+ }
7243
+ function writeField(map) {
7244
+ return map.nullable().optional().transform(
7245
+ (value) => value && Object.keys(value).length === 0 ? null : value
7246
+ );
7247
+ }
7248
+ function refineLaneReferences(val, ctx) {
7249
+ const lanes = val.lanes;
7250
+ const statuses = val.kanban_statuses;
7251
+ if (lanes == null || statuses == null) return;
7252
+ for (const issue of validateLaneReferences(lanes, statuses)) {
7253
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["kanban_statuses", ...issue.path], message: issue.message });
7254
+ }
7255
+ }
7239
7256
  function resolveMonitorTrigger(monitorConfig) {
7240
7257
  if (!monitorConfig || typeof monitorConfig !== "object") return "idle";
7241
7258
  const raw = monitorConfig.trigger;
7242
7259
  return MONITOR_TRIGGERS.includes(raw) ? raw : "idle";
7243
7260
  }
7261
+ function isAutomationGateTrigger(trigger) {
7262
+ return AUTOMATION_GATE_TRIGGERS.includes(trigger);
7263
+ }
7244
7264
  function isFiringTrigger(trigger) {
7245
- return trigger !== "manual";
7265
+ return !NON_FIRING_TRIGGERS.includes(trigger);
7246
7266
  }
7247
7267
  function monitorConfigNeedsDelay(monitorConfig) {
7248
7268
  if (!monitorConfig || typeof monitorConfig !== "object") return false;
@@ -7342,10 +7362,24 @@ function decodedMonitorConfig(value) {
7342
7362
  function monitorRuleActionKinds(trigger) {
7343
7363
  if (trigger === "assistant_reply") return MONITOR_ASSISTANT_REPLY_ACTION_KINDS;
7344
7364
  if (trigger === "call_utterance") return MONITOR_CALL_UTTERANCE_ACTION_KINDS;
7365
+ if (trigger === "automation_fire") return MONITOR_AUTOMATION_FIRE_ACTION_KINDS;
7366
+ if (trigger === "automation_item") return MONITOR_AUTOMATION_ITEM_ACTION_KINDS;
7345
7367
  return MONITOR_USER_MESSAGE_ACTION_KINDS;
7346
7368
  }
7369
+ function isGateActionKind(kind) {
7370
+ return AUTOMATION_GATE_TRIGGERS.some((trigger) => monitorRuleActionKinds(trigger).includes(kind));
7371
+ }
7347
7372
  function monitorActionKindMessage(kind, trigger) {
7348
7373
  const allowed = monitorRuleActionKinds(trigger).join(", ");
7374
+ if (trigger === "automation_fire") {
7375
+ return `an automation_fire rule cannot select "${kind}": a fire gate runs before any conversation exists, so it only decides whether the fire runs. Use one of: ${allowed}.`;
7376
+ }
7377
+ if (trigger === "automation_item") {
7378
+ return `an automation_item rule cannot select "${kind}": an item gate runs before anything is started for the contact, so it only decides whether its work starts. Use one of: ${allowed}.`;
7379
+ }
7380
+ if (isGateActionKind(kind)) {
7381
+ return `a monitor rule cannot select "${kind}": it decides an automation's fire or one contact of it, so only an automation_fire or automation_item monitor can select it. Use one of: ${allowed}.`;
7382
+ }
7349
7383
  if (trigger === "assistant_reply") {
7350
7384
  return `an assistant_reply rule cannot select "${kind}". Use one of: ${allowed}.`;
7351
7385
  }
@@ -7400,12 +7434,27 @@ function monitorRuleActions(monitorConfig) {
7400
7434
  visit(config.fallback, ["fallback"]);
7401
7435
  return found;
7402
7436
  }
7437
+ function automationGateIssues(monitorConfig) {
7438
+ if (!monitorConfig || typeof monitorConfig !== "object") return [];
7439
+ const trigger = resolveMonitorTrigger(monitorConfig);
7440
+ if (!isAutomationGateTrigger(trigger)) return [];
7441
+ const messages = AUTOMATION_GATE_KEY_MESSAGES[trigger];
7442
+ const config = monitorConfig;
7443
+ const issues = [];
7444
+ if (Array.isArray(config.flag_conditions) && config.flag_conditions.length > 0) {
7445
+ issues.push({ path: ["flag_conditions"], message: messages.flagConditions });
7446
+ }
7447
+ for (const key of MONITOR_INPUT_SHAPING_KEYS) {
7448
+ if (config[key] !== void 0) issues.push({ path: [key], message: messages.inputShaping });
7449
+ }
7450
+ return issues;
7451
+ }
7403
7452
  function collectMonitorRuleIssues(monitorConfig) {
7404
7453
  const offTrigger = monitorRuleKeysOffTrigger(monitorConfig).map((key) => ({ path: [key], message: MONITOR_RULE_TRIGGER_MESSAGE }));
7405
7454
  if (offTrigger.length > 0) return offTrigger;
7406
7455
  const trigger = resolveMonitorTrigger(monitorConfig);
7407
7456
  const kinds = monitorRuleActionKinds(trigger);
7408
- const issues = callUtteranceRuleIssues(monitorConfig);
7457
+ const issues = [...callUtteranceRuleIssues(monitorConfig), ...automationGateIssues(monitorConfig)];
7409
7458
  for (const { action, path: path36 } of monitorRuleActions(monitorConfig)) {
7410
7459
  if (trigger === "call_utterance" && path36[0] === "fallback") continue;
7411
7460
  const kind = action.kind;
@@ -7761,6 +7810,20 @@ function refineHubAsCodeLanes(config, ctx) {
7761
7810
  }
7762
7811
  }
7763
7812
  }
7813
+ function refineHubAsCodePresentation(config, ctx) {
7814
+ const hub = config.hub;
7815
+ if (hub == null) return;
7816
+ for (const field of HUB_PRESENTATION_FIELDS) {
7817
+ const value = hub[field];
7818
+ if (value == null) continue;
7819
+ const result = HUB_PRESENTATION_SCHEMAS[field].safeParse(value);
7820
+ if (!result.success) {
7821
+ for (const issue of result.error.issues) {
7822
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["hub", field, ...issue.path], message: issue.message });
7823
+ }
7824
+ }
7825
+ }
7826
+ }
7764
7827
  function refineHubAsCodeEvals(config, ctx) {
7765
7828
  const evals = config.evals;
7766
7829
  if (!Array.isArray(evals)) return;
@@ -8166,19 +8229,22 @@ function refineHubAsCodeMonitorRulesOutput(config, ctx) {
8166
8229
  }
8167
8230
  });
8168
8231
  }
8169
- var PLACEHOLDER_TOKENS, ALLOWED_TYPES, SUBSCHEMA_OBJECT_KEYWORDS, SUBSCHEMA_LIST_KEYWORDS, SUBSCHEMA_MAP_KEYWORDS, MAX_SCHEMA_DEPTH, uuidSchema, USER_ID_REGEX, timestampSchema, idParamSchema, clientOptionalString, clientOptionalBoolean, clientOptionalNumber, messageAttachment, MAX_MESSAGE_BODY_BYTES, MAX_ATTACHMENTS_PER_MESSAGE, MESSAGE_ENVELOPE_HEADROOM_BYTES, MAX_AUDIO_FILE_BASE64_BYTES, 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, toolIdParam, listToolsQuery, toolAgentQuery, deleteToolQuery, toolConnectionsQuery, nativeToolIdSchema, CONTEXT_BOUNDARIES, contextBoundarySchema, addNativeToolBody, addMcpToolBody, createCustomToolBody, updateCustomToolBody, updateToolExecutionConfigBody, PREVIOUS_CONVERSATIONS_MAX, NATIVE_TOOL_NAMES, previousConversationsCountField, summarizationThresholdField, flagConditionSchema, MONITOR_TRIGGERS, monitorTriggerSchema, MONITOR_FIRING_TRIGGERS, MONITOR_DELAY_SECONDS_MIN, MONITOR_IDLE_DELAY_REQUIRED_MESSAGE, MONITOR_HISTORY_MESSAGES_MAX, monitorHistoryMessagesSchema, monitorIncludeToolResultsSchema, MONITOR_INPUT_SHAPING_KEYS, MONITOR_INPUT_SHAPING_SCHEMAS, MONITOR_INPUT_SHAPING_IDLE_MESSAGE, monitorArgumentSourceSchema, MONITOR_NOTE_TEMPLATE_MAX, MONITOR_STEER_NOTE_MAX, monitorActionSchema, monitorRuleSchema, MONITOR_RULE_KEYS, MONITOR_RULE_SCHEMAS, MONITOR_RULE_TRIGGERS, MONITOR_RULE_TRIGGER_MESSAGE, CALL_UTTERANCE_SPEAKERS, callUtteranceSpeakerSchema, MONITOR_CALL_KEYS, MONITOR_CALL_SCHEMAS, MONITOR_CALL_KEY_MESSAGE, CALL_STEERING_MIN_CONFIDENCE, CALL_UTTERANCE_RULE_NOT_CONFIDENT_MESSAGE, CALL_UTTERANCE_FALLBACK_MESSAGE, CALL_UTTERANCE_FLAG_CONDITIONS_MESSAGE, CALL_STEER_NOTE_BLANK_MESSAGE, MONITOR_USER_MESSAGE_ACTION_KINDS, MONITOR_ASSISTANT_REPLY_ACTION_KINDS, MONITOR_CALL_UTTERANCE_ACTION_KINDS, INSERT_NOTE_TOOL_NAME, RUN_MONITOR_TOOL_NAME, MONITOR_RULE_ALLOWED_NATIVE_TOOLS, MONITOR_RULE_REENTRY_TOOLS, MONITOR_RULE_REENTRY_TRACKS, monitorConfigField, flagConditionsField, agentIdParam, listAgentsQuery, agentConnectionsQuery, createAgentBody, updateAgentBody, AGENT_PARAMETER_TYPES, AGENT_PARAMETER_NAME_REGEX, agentParameterCreateSchema, MAX_AGENT_PARAMETERS_PER_REQUEST, createAgentParametersBody, evalIdParam, sessionIdParam, scenarioSetIdParam, hubIdQuery, evalDateContextSchema, EVAL_FIXTURE_NAME_MAX_LENGTH, evalFixtureOverrideSchema, runSessionQuery, runJourneyQuery, EVAL_INPUT_ROLES, EVAL_INPUT_ROLE_LIST, ROLE_ECHO_MAX, EVAL_INITIAL_STATE_SCOPES, MAX_INITIAL_STATE_ENTRIES, evalInitialStateEntry, evalBody, 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, MAX_RESOURCE_FILE_SIZE, CALL_OPENING_LANGUAGES, callOpeningLanguage, CALL_OPENING_MAX_DURATION_MS, CALL_OPENING_MAX_BYTES, CALL_OPENING_CAPTION_MAX_CHARS, CALL_OPENING_CONTENT_TYPES, callOpeningContentType, CALL_OPENING_HASH_REGEX, callOpeningHash, callOpeningCaption, storedCallOpening, MAX_CALL_OPENING_ENCODED_BYTES, MAX_CALL_OPENING_BODY_BYTES, agentCallOpeningParams, putAgentCallOpeningBody, deleteAgentCallOpeningQuery, callOpeningParam, callOpeningQuery, 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, MAX_CALL_OPENING_CARRIERS, MAX_CALL_OPENING_AGGREGATE_ENCODED_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;
8170
- var init_chunk_YEYIDIR6 = __esm({
8171
- "../../packages/core/dist/chunk-YEYIDIR6.js"() {
8232
+ var PLACEHOLDER_TOKENS, ALLOWED_TYPES, SUBSCHEMA_OBJECT_KEYWORDS, SUBSCHEMA_LIST_KEYWORDS, SUBSCHEMA_MAP_KEYWORDS, MAX_SCHEMA_DEPTH, uuidSchema, USER_ID_REGEX, timestampSchema, idParamSchema, clientOptionalString, clientOptionalBoolean, clientOptionalNumber, messageAttachment, MAX_MESSAGE_BODY_BYTES, MAX_ATTACHMENTS_PER_MESSAGE, MESSAGE_ENVELOPE_HEADROOM_BYTES, MAX_AUDIO_FILE_BASE64_BYTES, 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, toolIdParam, listToolsQuery, toolAgentQuery, deleteToolQuery, toolConnectionsQuery, nativeToolIdSchema, CONTEXT_BOUNDARIES, contextBoundarySchema, addNativeToolBody, addMcpToolBody, createCustomToolBody, updateCustomToolBody, updateToolExecutionConfigBody, primaryRegionSchema, placementSourceSchema, orgIdParam, orgAdminIdParam, createOrganizationBody, updateOrganizationBody, addOrgAdminBody, HUB_DISPLAY_NAME_MAX_CHARS, HUB_WELCOME_MESSAGE_MAX_CHARS, HUB_STARTER_QUESTIONS_MAX, HUB_STARTER_QUESTION_MAX_CHARS, displayName, welcomeMessage, starterQuestions, hubDisplayNamesSchema, hubWelcomeMessagesSchema, hubStarterQuestionsSchema, hubDisplayNamesField, hubWelcomeMessagesField, hubStarterQuestionsField, HUB_PRESENTATION_FIELDS, HUB_PRESENTATION_SCHEMAS, hubIdParam, hubAdminIdParam, hubUserIdParam, hubIdentityIdParam, hubTeamIdParam, hubTeamUserDeleteParam, hubSchemaQuery, HUB_USERS_PAGE_SIZE_MAX, HUB_USERS_SEARCH_MAX, HUB_USERS_CHANNEL_TYPES, getHubUsersQuery, PREVIEW_LABEL_MAX_LENGTH, MAX_ENDED_INDEX_RETENTION_DAYS, MAX_EVAL_RETENTION_DAYS, MAX_END_USER_DAILY_MESSAGE_LIMIT, endUserDailyMessageLimitField, previewLabelField, hubTagsField, createHubBody, updateHubBody, HUB_TAG_CHANGE_REFUSED, hubTagChangeRefusalSchema, addHubAdminBody, addHubIdentityAuthorizationBody, contactDecisionBody, approveContactBody, listContactAccessQuery, createHubTeamBody, updateHubTeamBody, addHubTeamUserBody, reassignHubUserBody, replicatePreviewBody, HUB_DIFF_SECTION_SET, HUB_DIFF_SECTIONS, updateChannelTestIdentitiesBody, claimCodeChannelParam, claimCodeDeleteParam, PREVIOUS_CONVERSATIONS_MAX, NATIVE_TOOL_NAMES, previousConversationsCountField, summarizationThresholdField, flagConditionSchema, MONITOR_TRIGGERS, monitorTriggerSchema, AUTOMATION_GATE_TRIGGERS, NON_FIRING_TRIGGERS, MONITOR_FIRING_TRIGGERS, MONITOR_DELAY_SECONDS_MIN, MONITOR_IDLE_DELAY_REQUIRED_MESSAGE, MONITOR_HISTORY_MESSAGES_MAX, monitorHistoryMessagesSchema, monitorIncludeToolResultsSchema, MONITOR_INPUT_SHAPING_KEYS, MONITOR_INPUT_SHAPING_SCHEMAS, MONITOR_INPUT_SHAPING_IDLE_MESSAGE, monitorArgumentSourceSchema, MONITOR_NOTE_TEMPLATE_MAX, MONITOR_STEER_NOTE_MAX, MONITOR_GATE_AGENT_NAME_MAX, monitorActionSchema, monitorRuleSchema, MONITOR_RULE_KEYS, MONITOR_RULE_SCHEMAS, MONITOR_RULE_TRIGGERS, MONITOR_RULE_TRIGGER_MESSAGE, CALL_UTTERANCE_SPEAKERS, callUtteranceSpeakerSchema, MONITOR_CALL_KEYS, MONITOR_CALL_SCHEMAS, MONITOR_CALL_KEY_MESSAGE, CALL_STEERING_MIN_CONFIDENCE, CALL_UTTERANCE_RULE_NOT_CONFIDENT_MESSAGE, CALL_UTTERANCE_FALLBACK_MESSAGE, CALL_UTTERANCE_FLAG_CONDITIONS_MESSAGE, CALL_STEER_NOTE_BLANK_MESSAGE, MONITOR_USER_MESSAGE_ACTION_KINDS, MONITOR_ASSISTANT_REPLY_ACTION_KINDS, MONITOR_CALL_UTTERANCE_ACTION_KINDS, MONITOR_AUTOMATION_FIRE_ACTION_KINDS, MONITOR_AUTOMATION_ITEM_ACTION_KINDS, INSERT_NOTE_TOOL_NAME, RUN_MONITOR_TOOL_NAME, MONITOR_RULE_ALLOWED_NATIVE_TOOLS, MONITOR_RULE_REENTRY_TOOLS, MONITOR_RULE_REENTRY_TRACKS, AUTOMATION_FIRE_FLAG_CONDITIONS_MESSAGE, AUTOMATION_FIRE_INPUT_SHAPING_MESSAGE, AUTOMATION_ITEM_FLAG_CONDITIONS_MESSAGE, AUTOMATION_ITEM_INPUT_SHAPING_MESSAGE, AUTOMATION_GATE_KEY_MESSAGES, monitorConfigField, flagConditionsField, agentIdParam, listAgentsQuery, agentConnectionsQuery, createAgentBody, updateAgentBody, AGENT_PARAMETER_TYPES, AGENT_PARAMETER_NAME_REGEX, agentParameterCreateSchema, MAX_AGENT_PARAMETERS_PER_REQUEST, createAgentParametersBody, evalIdParam, sessionIdParam, scenarioSetIdParam, hubIdQuery, evalDateContextSchema, EVAL_FIXTURE_NAME_MAX_LENGTH, evalFixtureOverrideSchema, runSessionQuery, runJourneyQuery, EVAL_INPUT_ROLES, EVAL_INPUT_ROLE_LIST, ROLE_ECHO_MAX, EVAL_INITIAL_STATE_SCOPES, MAX_INITIAL_STATE_ENTRIES, evalInitialStateEntry, evalBody, 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, MAX_RESOURCE_FILE_SIZE, CALL_OPENING_LANGUAGES, callOpeningLanguage, CALL_OPENING_MAX_DURATION_MS, CALL_OPENING_MAX_BYTES, CALL_OPENING_CAPTION_MAX_CHARS, CALL_OPENING_CONTENT_TYPES, callOpeningContentType, CALL_OPENING_HASH_REGEX, callOpeningHash, callOpeningCaption, storedCallOpening, MAX_CALL_OPENING_ENCODED_BYTES, MAX_CALL_OPENING_BODY_BYTES, agentCallOpeningParams, putAgentCallOpeningBody, deleteAgentCallOpeningQuery, callOpeningParam, callOpeningQuery, 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, MAX_CALL_OPENING_CARRIERS, MAX_CALL_OPENING_AGGREGATE_ENCODED_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;
8233
+ var init_chunk_T2RKGBYS = __esm({
8234
+ "../../packages/core/dist/chunk-T2RKGBYS.js"() {
8172
8235
  "use strict";
8173
8236
  init_chunk_SNA2DXAC();
8237
+ init_chunk_MIWZOSPI();
8174
8238
  init_chunk_IBL7FANV();
8239
+ init_chunk_2ISUBJG7();
8175
8240
  init_chunk_C2UEA2KW();
8176
8241
  init_chunk_3NS3HULK();
8177
- init_chunk_MIWZOSPI();
8178
8242
  init_chunk_JWPRTSIB();
8179
8243
  init_chunk_T7KQKDET();
8180
8244
  init_chunk_L5F7ZOUJ();
8181
- init_chunk_2ISUBJG7();
8245
+ init_zod();
8246
+ init_zod();
8247
+ init_zod();
8182
8248
  init_zod();
8183
8249
  init_zod();
8184
8250
  init_zod();
@@ -8586,355 +8652,638 @@ var init_chunk_YEYIDIR6 = __esm({
8586
8652
  keep_in_history: external_exports.boolean().optional()
8587
8653
  }).nullable()
8588
8654
  });
8589
- PREVIOUS_CONVERSATIONS_MAX = 20;
8590
- NATIVE_TOOL_NAMES = new Set(NATIVE_TOOLS.map((t) => t.tool_name));
8591
- previousConversationsCountField = external_exports.number().int().min(0).max(PREVIOUS_CONVERSATIONS_MAX).nullable().optional();
8592
- summarizationThresholdField = external_exports.number().int().min(SUMMARIZATION_THRESHOLD_MIN).max(SUMMARIZATION_THRESHOLD_MAX).nullable().optional();
8593
- flagConditionSchema = external_exports.object({
8594
- variable: external_exports.string(),
8595
- operator: external_exports.enum(FLAG_CONDITION_OPERATORS),
8596
- // `boolean` is admitted for parity with the CI write path, whose refine gates the
8597
- // operator alone, so `value: false` on a boolean evaluation variable is storable
8598
- // config today and the evaluator honours it through `String()`. Narrowing here would
8599
- // reject on PATCH exactly what `wayai push` persists, so any REST caller that reads
8600
- // an agent and writes it back — the typed clients, the CLI's `ApiClient`, MCP — would
8601
- // fail on a hub configured through the other surface.
8602
- value: external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean()])
8603
- });
8604
- MONITOR_TRIGGERS = ["idle", "user_message", "assistant_reply", "manual", "call_utterance"];
8605
- monitorTriggerSchema = external_exports.enum(MONITOR_TRIGGERS);
8606
- MONITOR_FIRING_TRIGGERS = MONITOR_TRIGGERS.filter(isFiringTrigger);
8607
- MONITOR_DELAY_SECONDS_MIN = 10;
8608
- MONITOR_IDLE_DELAY_REQUIRED_MESSAGE = "delay_seconds is required for an idle monitor (an absent trigger is idle)";
8609
- MONITOR_HISTORY_MESSAGES_MAX = 100;
8610
- monitorHistoryMessagesSchema = external_exports.number().int().min(1).max(MONITOR_HISTORY_MESSAGES_MAX);
8611
- monitorIncludeToolResultsSchema = external_exports.boolean();
8612
- MONITOR_INPUT_SHAPING_KEYS = ["history_messages", "include_tool_results"];
8613
- MONITOR_INPUT_SHAPING_SCHEMAS = {
8614
- history_messages: monitorHistoryMessagesSchema.optional(),
8615
- include_tool_results: monitorIncludeToolResultsSchema.optional()
8616
- };
8617
- MONITOR_INPUT_SHAPING_IDLE_MESSAGE = "only a user_message, assistant_reply, manual or call_utterance monitor reads this \u2014 an idle monitor runs as a full turn and takes the ordinary history window";
8618
- monitorArgumentSourceSchema = external_exports.union([
8619
- external_exports.object({ from_variable: external_exports.string().min(1) }).strict(),
8620
- external_exports.object({ const: external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean()]) }).strict()
8655
+ primaryRegionSchema = external_exports.enum([
8656
+ "wnam",
8657
+ "enam",
8658
+ "sam",
8659
+ "weur",
8660
+ "eeur",
8661
+ "apac",
8662
+ "oc",
8663
+ "afr",
8664
+ "me"
8621
8665
  ]);
8622
- MONITOR_NOTE_TEMPLATE_MAX = 2e3;
8623
- MONITOR_STEER_NOTE_MAX = 500;
8624
- monitorActionSchema = external_exports.discriminatedUnion("kind", [
8625
- external_exports.object({ kind: external_exports.literal("none") }).strict(),
8626
- external_exports.object({
8627
- kind: external_exports.literal("call_tool"),
8628
- tool_name: external_exports.string().min(1),
8629
- args: external_exports.record(monitorArgumentSourceSchema).optional()
8630
- }).strict(),
8631
- external_exports.object({ kind: external_exports.literal("hold") }).strict(),
8632
- external_exports.object({ kind: external_exports.literal("rewrite"), note: external_exports.string().min(1).max(MONITOR_NOTE_TEMPLATE_MAX) }).strict(),
8633
- external_exports.object({ kind: external_exports.literal("steer"), note: external_exports.string().min(1).max(MONITOR_STEER_NOTE_MAX) }).strict()
8666
+ placementSourceSchema = external_exports.enum([
8667
+ "hub_config",
8668
+ "org_config",
8669
+ "parent_cascade",
8670
+ "cf_colo",
8671
+ "country",
8672
+ "fallback"
8634
8673
  ]);
8635
- monitorRuleSchema = external_exports.object({
8636
- when: external_exports.array(flagConditionSchema).min(1),
8637
- action: monitorActionSchema
8638
- }).strict();
8639
- MONITOR_RULE_KEYS = ["rules", "fallback"];
8640
- MONITOR_RULE_SCHEMAS = {
8641
- rules: external_exports.array(monitorRuleSchema).optional(),
8642
- fallback: monitorActionSchema.optional()
8643
- };
8644
- MONITOR_RULE_TRIGGERS = ["user_message", "assistant_reply", "manual", "call_utterance"];
8645
- MONITOR_RULE_TRIGGER_MESSAGE = "only a user_message, assistant_reply, manual or call_utterance monitor acts on rules \u2014 set one of those triggers, or remove this key. A manual monitor acts on its rules when another monitor runs it.";
8646
- CALL_UTTERANCE_SPEAKERS = ["caller", "voice", "both"];
8647
- callUtteranceSpeakerSchema = external_exports.enum(CALL_UTTERANCE_SPEAKERS);
8648
- MONITOR_CALL_KEYS = ["speaker"];
8649
- MONITOR_CALL_SCHEMAS = {
8650
- speaker: callUtteranceSpeakerSchema.optional()
8651
- };
8652
- MONITOR_CALL_KEY_MESSAGE = "only a call_utterance monitor reads this: it names whose speech on a live call a check waits for";
8653
- CALL_STEERING_MIN_CONFIDENCE = 0.9;
8654
- CALL_UTTERANCE_RULE_NOT_CONFIDENT_MESSAGE = `a call_utterance rule acts on a live call from a transcript that can be misheard, so it must be high-confidence: give it a condition on one of this monitor's "\u2026${CONFIDENCE_VARIABLE_SUFFIX}" variables with ">= ${CALL_STEERING_MIN_CONFIDENCE}" or a higher bar, up to 1.`;
8655
- CALL_UTTERANCE_FALLBACK_MESSAGE = "a call_utterance monitor acts only when a high-confidence rule matches \u2014 a fallback would act on every check of the call. Remove it.";
8656
- CALL_UTTERANCE_FLAG_CONDITIONS_MESSAGE = "a call_utterance monitor checks a live call every few seconds and does not flag the conversation. Remove its flag_conditions, or flag from a monitor on another trigger.";
8657
- CALL_STEER_NOTE_BLANK_MESSAGE = "a steer's note is what the voice is told \u2014 write the instruction it should follow.";
8658
- MONITOR_USER_MESSAGE_ACTION_KINDS = ["none", "call_tool"];
8659
- MONITOR_ASSISTANT_REPLY_ACTION_KINDS = ["none", "call_tool", "hold", "rewrite"];
8660
- MONITOR_CALL_UTTERANCE_ACTION_KINDS = ["none", "call_tool", "steer"];
8661
- INSERT_NOTE_TOOL_NAME = "insert_note";
8662
- RUN_MONITOR_TOOL_NAME = "run_monitor";
8663
- MONITOR_RULE_ALLOWED_NATIVE_TOOLS = [
8664
- "update_state",
8665
- "schedule_followup",
8666
- "transfer_to_agent",
8667
- "transfer_to_team",
8668
- INSERT_NOTE_TOOL_NAME,
8669
- RUN_MONITOR_TOOL_NAME
8670
- ];
8671
- MONITOR_RULE_REENTRY_TOOLS = {
8672
- transfer_to_agent: "agent",
8673
- transfer_to_team: "team"
8674
- };
8675
- MONITOR_RULE_REENTRY_TRACKS = new Map(Object.entries(MONITOR_RULE_REENTRY_TOOLS));
8676
- monitorConfigField = external_exports.object({
8677
- delay_seconds: external_exports.number().int().min(MONITOR_DELAY_SECONDS_MIN).optional(),
8678
- trigger: monitorTriggerSchema.optional(),
8679
- ...MONITOR_INPUT_SHAPING_SCHEMAS,
8680
- ...MONITOR_RULE_SCHEMAS,
8681
- ...MONITOR_CALL_SCHEMAS,
8682
- flag_conditions: external_exports.array(flagConditionSchema).optional()
8683
- }).passthrough().superRefine((config, ctx) => {
8684
- if (monitorConfigNeedsDelay(config)) {
8685
- ctx.addIssue({
8686
- code: external_exports.ZodIssueCode.custom,
8687
- path: ["delay_seconds"],
8688
- message: MONITOR_IDLE_DELAY_REQUIRED_MESSAGE
8689
- });
8690
- }
8691
- for (const key of monitorInputShapingKeysOnIdle(config)) {
8692
- ctx.addIssue({
8693
- code: external_exports.ZodIssueCode.custom,
8694
- path: [key],
8695
- message: MONITOR_INPUT_SHAPING_IDLE_MESSAGE
8696
- });
8697
- }
8698
- for (const key of monitorCallKeysOffTrigger(config)) {
8699
- ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: [key], message: MONITOR_CALL_KEY_MESSAGE });
8700
- }
8701
- for (const issue of collectMonitorRuleIssues(config)) {
8702
- ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: issue.path, message: issue.message });
8703
- }
8704
- }).nullable().optional();
8705
- flagConditionsField = external_exports.array(flagConditionSchema).nullable().optional();
8706
- agentIdParam = external_exports.object({
8674
+ orgIdParam = external_exports.object({
8707
8675
  id: uuidSchema
8708
8676
  });
8709
- listAgentsQuery = external_exports.object({
8710
- hub_id: uuidSchema
8677
+ orgAdminIdParam = external_exports.object({
8678
+ id: uuidSchema,
8679
+ adminId: external_exports.string().min(1)
8711
8680
  });
8712
- agentConnectionsQuery = external_exports.object({
8713
- hub_id: uuidSchema
8681
+ createOrganizationBody = external_exports.object({
8682
+ organization_name: external_exports.string().min(1, "organization_name is required"),
8683
+ // Write-once at creation; updateOrganizationBody does not accept this.
8684
+ primary_region: primaryRegionSchema.optional()
8714
8685
  });
8715
- createAgentBody = external_exports.object({
8716
- agent_name: external_exports.string().min(1),
8717
- hub_id: uuidSchema,
8718
- agent_role: external_exports.enum(AGENT_ROLES),
8719
- additional_context_template: external_exports.string().max(2e4).optional(),
8720
- summarization_threshold_tokens: summarizationThresholdField,
8721
- previous_conversations_count: previousConversationsCountField,
8722
- monitor_config: monitorConfigField,
8723
- flag_conditions: flagConditionsField
8724
- }).passthrough().superRefine((body, ctx) => {
8725
- refineDecisionsModelBinding(body, ctx);
8726
- refineMonitorRulesStructuredOutput(body, ctx);
8727
- });
8728
- updateAgentBody = external_exports.object({
8729
- additional_context_template: external_exports.string().max(2e4).optional(),
8730
- summarization_threshold_tokens: summarizationThresholdField,
8731
- previous_conversations_count: previousConversationsCountField,
8732
- monitor_config: monitorConfigField,
8733
- flag_conditions: flagConditionsField
8686
+ updateOrganizationBody = external_exports.object({
8687
+ organization_name: external_exports.string().min(1).optional(),
8688
+ organization_avatar_url: external_exports.string().url().nullable().optional(),
8689
+ timezone: external_exports.string().optional(),
8690
+ business_hours: external_exports.unknown().optional()
8734
8691
  }).passthrough();
8735
- AGENT_PARAMETER_TYPES = ["string", "number", "boolean", "integer", "enum"];
8736
- AGENT_PARAMETER_NAME_REGEX = /^[a-zA-Z_][a-zA-Z0-9_]{0,63}$/;
8737
- agentParameterCreateSchema = external_exports.object({
8738
- parameter_name: external_exports.string().regex(
8739
- AGENT_PARAMETER_NAME_REGEX,
8740
- "parameter_name must start with a letter or underscore and contain only letters, digits, and underscores (max 64 chars)"
8741
- ),
8742
- parameter_type: external_exports.enum(AGENT_PARAMETER_TYPES).optional(),
8743
- // No length caps on the free-text fields below: the agent_parameter columns are
8744
- // unbounded TEXT and pre-PR rows were never length-validated, so a cap would 422
8745
- // an unrelated GET→edit→re-save of legitimately-long existing data. The name
8746
- // regex (above) and the batch cap (below) are the load-bearing guards; total
8747
- // payload size belongs in a global /api/* body limit, not per field here.
8748
- parameter_description: external_exports.string().nullable().optional(),
8749
- parameter_label: external_exports.string().nullable().optional(),
8750
- parameter_enum: external_exports.array(external_exports.string()).nullable().optional(),
8751
- parameter_required: external_exports.boolean().optional(),
8752
- // Free-form analytics grouping label — no DB CHECK and the CI path persists
8753
- // arbitrary strings, so keep this permissive (not the 4-value UI dropdown enum).
8754
- variable_category: external_exports.string().nullable().optional(),
8755
- is_summary: external_exports.boolean().optional()
8756
- }).strict();
8757
- MAX_AGENT_PARAMETERS_PER_REQUEST = 100;
8758
- createAgentParametersBody = external_exports.union([
8759
- agentParameterCreateSchema,
8760
- external_exports.array(agentParameterCreateSchema).max(MAX_AGENT_PARAMETERS_PER_REQUEST, `too many parameters (max ${MAX_AGENT_PARAMETERS_PER_REQUEST})`)
8761
- ]);
8762
- evalIdParam = external_exports.object({
8763
- id: external_exports.string().uuid()
8764
- });
8765
- sessionIdParam = external_exports.object({
8766
- id: external_exports.string().uuid()
8692
+ addOrgAdminBody = external_exports.object({
8693
+ user_email: external_exports.string().email("valid email is required")
8767
8694
  });
8768
- scenarioSetIdParam = external_exports.object({
8769
- id: external_exports.string().uuid()
8695
+ HUB_DISPLAY_NAME_MAX_CHARS = 120;
8696
+ HUB_WELCOME_MESSAGE_MAX_CHARS = 1e3;
8697
+ HUB_STARTER_QUESTIONS_MAX = 4;
8698
+ HUB_STARTER_QUESTION_MAX_CHARS = 120;
8699
+ displayName = external_exports.string().trim().min(1).max(HUB_DISPLAY_NAME_MAX_CHARS);
8700
+ welcomeMessage = external_exports.string().trim().min(1).max(HUB_WELCOME_MESSAGE_MAX_CHARS);
8701
+ starterQuestions = external_exports.array(external_exports.string().trim().min(1).max(HUB_STARTER_QUESTION_MAX_CHARS)).min(1).max(HUB_STARTER_QUESTIONS_MAX);
8702
+ hubDisplayNamesSchema = byLocale(displayName);
8703
+ hubWelcomeMessagesSchema = byLocale(welcomeMessage);
8704
+ hubStarterQuestionsSchema = byLocale(starterQuestions);
8705
+ hubDisplayNamesField = writeField(hubDisplayNamesSchema);
8706
+ hubWelcomeMessagesField = writeField(hubWelcomeMessagesSchema);
8707
+ hubStarterQuestionsField = writeField(hubStarterQuestionsSchema);
8708
+ HUB_PRESENTATION_FIELDS = ["display_names", "welcome_messages", "starter_questions"];
8709
+ HUB_PRESENTATION_SCHEMAS = {
8710
+ display_names: hubDisplayNamesSchema,
8711
+ welcome_messages: hubWelcomeMessagesSchema,
8712
+ starter_questions: hubStarterQuestionsSchema
8713
+ };
8714
+ hubIdParam = external_exports.object({ id: uuidSchema });
8715
+ hubAdminIdParam = external_exports.object({ id: uuidSchema, adminId: uuidSchema });
8716
+ hubUserIdParam = external_exports.object({ id: uuidSchema, hubUserId: uuidSchema });
8717
+ hubIdentityIdParam = external_exports.object({ id: uuidSchema, identityId: uuidSchema });
8718
+ hubTeamIdParam = external_exports.object({ id: uuidSchema, teamId: uuidSchema });
8719
+ hubTeamUserDeleteParam = external_exports.object({ id: uuidSchema, teamUserId: uuidSchema });
8720
+ hubSchemaQuery = external_exports.object({ hub_id: uuidSchema });
8721
+ HUB_USERS_PAGE_SIZE_MAX = 200;
8722
+ HUB_USERS_SEARCH_MAX = 200;
8723
+ HUB_USERS_CHANNEL_TYPES = ["app", "whatsapp", "instagram", "telegram"];
8724
+ getHubUsersQuery = external_exports.object({
8725
+ cursor: external_exports.string().regex(/^[1-9][0-9]{0,14}$/, "Invalid cursor").optional(),
8726
+ page_size: external_exports.coerce.number().int().min(1).max(HUB_USERS_PAGE_SIZE_MAX).optional(),
8727
+ channel_type: external_exports.enum(HUB_USERS_CHANNEL_TYPES).optional(),
8728
+ search: external_exports.string().max(HUB_USERS_SEARCH_MAX).optional()
8770
8729
  });
8771
- hubIdQuery = external_exports.object({
8772
- hub_id: external_exports.string().uuid()
8730
+ PREVIEW_LABEL_MAX_LENGTH = 60;
8731
+ MAX_ENDED_INDEX_RETENTION_DAYS = 730;
8732
+ MAX_EVAL_RETENTION_DAYS = 3650;
8733
+ MAX_END_USER_DAILY_MESSAGE_LIMIT = 1e4;
8734
+ endUserDailyMessageLimitField = external_exports.number().int().min(1).max(MAX_END_USER_DAILY_MESSAGE_LIMIT).nullable().optional();
8735
+ previewLabelField = external_exports.string().max(PREVIEW_LABEL_MAX_LENGTH).optional().nullable().transform((v) => {
8736
+ if (v == null) return null;
8737
+ const trimmed = v.trim();
8738
+ return trimmed || null;
8773
8739
  });
8774
- evalDateContextSchema = external_exports.object({
8775
- base_time: timestampSchema.refine(isIsoTimestamp, "Expected a canonical ISO timestamp"),
8776
- timezone: external_exports.string().min(1).refine((timezone) => {
8777
- try {
8778
- new Intl.DateTimeFormat("en-US", { timeZone: timezone }).format(0);
8779
- return true;
8780
- } catch {
8781
- return false;
8782
- }
8783
- }, "Expected an IANA timezone"),
8784
- locale: external_exports.enum(SUPPORTED_LOCALES)
8785
- }).strict();
8786
- EVAL_FIXTURE_NAME_MAX_LENGTH = 200;
8787
- evalFixtureOverrideSchema = external_exports.string().trim().min(1).max(EVAL_FIXTURE_NAME_MAX_LENGTH);
8788
- runSessionQuery = hubIdQuery.extend({
8789
- fixture: evalFixtureOverrideSchema.optional()
8740
+ hubTagsField = external_exports.array(external_exports.string()).nullable().optional();
8741
+ createHubBody = external_exports.object({
8742
+ organization_id: uuidSchema,
8743
+ hub_name: external_exports.string().min(1, "hub_name is required"),
8744
+ hub_description: external_exports.string().optional(),
8745
+ kanban_statuses: kanbanStatusesArraySchema.nullable().optional(),
8746
+ lanes: lanesArraySchema.nullable().optional(),
8747
+ // Optional preview label for the first preview. Server-owned thereafter
8748
+ // (change via `wayai relabel` / replicate); the push diff never writes it.
8749
+ preview_label: previewLabelField,
8750
+ // Write-once at creation; updateHubBody does not accept this.
8751
+ primary_region: primaryRegionSchema.optional(),
8752
+ // Org tag ids. Ids that name none of the org's tags are dropped; a hub created with
8753
+ // any is a tag change (`hubTagChangeRefusalSchema`).
8754
+ tags: hubTagsField,
8755
+ // Localized end-user presentation (`hub-presentation.ts`). Validated here too: the body is
8756
+ // `.passthrough()` and `createHub` writes all three, so an unvalidated map would persist.
8757
+ display_names: hubDisplayNamesField,
8758
+ welcome_messages: hubWelcomeMessagesField,
8759
+ starter_questions: hubStarterQuestionsField,
8760
+ // Validated here for the same reason: `createHub` writes it.
8761
+ end_user_daily_message_limit: endUserDailyMessageLimitField
8762
+ }).passthrough().superRefine(refineLaneReferences);
8763
+ updateHubBody = external_exports.object({
8764
+ support_model: external_exports.enum(["conversation", "account"]).optional(),
8765
+ unassigned_policy: external_exports.enum(["default_team", "auto_assign_random", "auto_assign_round_robin", "pull_queue"]).optional(),
8766
+ default_hub_team_id: uuidSchema.nullable().optional(),
8767
+ kanban_statuses: kanbanStatusesArraySchema.nullable().optional(),
8768
+ lanes: lanesArraySchema.nullable().optional(),
8769
+ // summarization_threshold_tokens relocated to the summarizer AGENT (PR4) — validated/
8770
+ // persisted via the agent path (.passthrough() agent body → HubDO column), not here.
8771
+ auto_close_inactive_days: external_exports.number().int().min(1).max(180).optional(),
8772
+ // Per-hub ConversationDO retention window (days) — keeps an ended conversation's DO
8773
+ // alive for post-hoc annotation. Default 7, max 30 — the floor of the retention
8774
+ // chain (≤ ended_index_retention_days ≤ effective storage retention).
8775
+ conversation_retention_days: external_exports.number().int().min(1).max(30).optional(),
8776
+ // Per-hub ended-conversation index retention window (days) — how long the warm
8777
+ // "Ended" tab + chat-hub continuous history serve a closed conversation before
8778
+ // the cleanup cron reaps its index row. Absent → DEFAULT_ENDED_INDEX_RETENTION_DAYS
8779
+ // (365). Re-clamped to the effective storage retention at reap time.
8780
+ ended_index_retention_days: external_exports.number().int().min(1).max(MAX_ENDED_INDEX_RETENTION_DAYS).optional(),
8781
+ // Per-hub eval-session retention window (days). null CLEARS the override (back to
8782
+ // the platform default); 0 disables retention for this hub (keep sessions forever).
8783
+ // Nullable — unlike the fields above, "unset" is a meaningful, settable state.
8784
+ eval_retention_days: external_exports.number().int().min(0).max(MAX_EVAL_RETENTION_DAYS).nullable().optional(),
8785
+ // Channel contact access control. Enum-validated explicitly (not via passthrough)
8786
+ // so `language`/`access_approval_role` can't reach the DB with an invalid value.
8787
+ language: external_exports.enum(["en", "pt", "es"]).optional(),
8788
+ access_request_message: external_exports.string().max(1e3).nullable().optional(),
8789
+ access_approval_role: external_exports.enum(["admin", "team"]).optional(),
8790
+ // AI-failure escalation. When an LLM provider outage persists past this many
8791
+ // minutes the conversation escalates to the team; null → code default. The two
8792
+ // message fields override the localized (hub.language) delay / hand-off notices;
8793
+ // null → localized default. Bounds validated here so out-of-range never persists.
8794
+ ai_failure_escalation_minutes: external_exports.number().int().min(1).max(60).nullable().optional(),
8795
+ ai_delay_message: external_exports.string().max(1e3).nullable().optional(),
8796
+ ai_handoff_message: external_exports.string().max(1e3).nullable().optional(),
8797
+ // Native-completion fallback connection for a degraded harness turn (PR 2.10b).
8798
+ // A NATIVE LLM (Agent) connection id on this hub; validated at set-time on the REST
8799
+ // PATCH (setup/hubs.ts rejects a non-existent / non-Agent / harness id) and re-checked
8800
+ // at fallback time in the turn seam (a stale/missing id simply no-ops). Nullable to clear it.
8801
+ fallback_connection_id: uuidSchema.nullable().optional(),
8802
+ // Rekor API connection used to reset/clear eval seed fixtures (gh #3090). A
8803
+ // connection id on this hub (a REST API (custom tool) connection whose base_url
8804
+ // is the Rekor API origin + a bearer/api_key `write:seeds` token). Validated at
8805
+ // set-time on the REST PATCH (setup/hubs.ts). Nullable to clear it.
8806
+ seed_connection_id: uuidSchema.nullable().optional(),
8807
+ // Org tag ids, replacing the hub's; null clears them. A change is refused to anyone
8808
+ // but an org admin (`hubTagChangeRefusalSchema`).
8809
+ tags: hubTagsField,
8810
+ // Localized end-user presentation (`hub-presentation.ts`): keys are supported locales only,
8811
+ // each map replaces the stored one, and null or an empty map clears it.
8812
+ display_names: hubDisplayNamesField,
8813
+ welcome_messages: hubWelcomeMessagesField,
8814
+ starter_questions: hubStarterQuestionsField,
8815
+ // Messages one end user may send the hub on the app channel per 24 hours; null removes it.
8816
+ end_user_daily_message_limit: endUserDailyMessageLimitField
8817
+ }).passthrough().superRefine(refineLaneReferences);
8818
+ HUB_TAG_CHANGE_REFUSED = "hub_tag_change_requires_org_admin";
8819
+ hubTagChangeRefusalSchema = external_exports.object({
8820
+ reason: external_exports.literal(HUB_TAG_CHANGE_REFUSED),
8821
+ operation: external_exports.enum(["update", "publish"]),
8822
+ hub_id: external_exports.string(),
8823
+ tags_added: external_exports.array(external_exports.string()),
8824
+ tags_removed: external_exports.array(external_exports.string())
8790
8825
  });
8791
- runJourneyQuery = hubIdQuery.extend({
8792
- call_mode: external_exports.enum(["true", "false"]).optional()
8826
+ addHubAdminBody = external_exports.object({
8827
+ user_email: external_exports.string().email("valid email is required")
8793
8828
  });
8794
- EVAL_INPUT_ROLES = ["user", "system"];
8795
- EVAL_INPUT_ROLE_LIST = EVAL_INPUT_ROLES.map((r) => `"${r}"`).join(" or ");
8796
- ROLE_ECHO_MAX = 40;
8797
- EVAL_INITIAL_STATE_SCOPES = ["user"];
8798
- MAX_INITIAL_STATE_ENTRIES = 20;
8799
- evalInitialStateEntry = external_exports.object({
8800
- slug: external_exports.string().min(1).max(200),
8801
- scope: external_exports.enum(EVAL_INITIAL_STATE_SCOPES).default("user"),
8802
- value: external_exports.record(external_exports.unknown())
8829
+ addHubIdentityAuthorizationBody = external_exports.object({
8830
+ identity_value: external_exports.string().min(1),
8831
+ identity_type: external_exports.string().min(1),
8832
+ channel_type: external_exports.string().min(1)
8803
8833
  });
8804
- evalBody = external_exports.object({
8805
- eval: external_exports.record(external_exports.unknown())
8806
- }).superRefine(refineEvalName).superRefine(refineEvalMessageTextRole).superRefine(refineEvalAttachments).superRefine(refineEvalInitialState);
8807
- EVAL_LIST_MAX_LIMIT = 1e3;
8808
- evalListLimit = external_exports.string().regex(/^\d+$/).refine((v) => Number(v) <= EVAL_LIST_MAX_LIMIT, {
8809
- message: `limit must be ${EVAL_LIST_MAX_LIMIT} or less`
8810
- }).optional();
8811
- getEvalsQuery = external_exports.object({
8812
- hub_id: external_exports.string().uuid(),
8813
- agent_id: external_exports.string().uuid().optional(),
8814
- enabled: external_exports.string().regex(/^(true|false)$/).optional(),
8815
- search: external_exports.string().optional(),
8816
- limit: evalListLimit,
8817
- offset: external_exports.string().regex(/^\d+$/).optional()
8834
+ contactDecisionBody = external_exports.object({
8835
+ contact_access_id: uuidSchema.optional(),
8836
+ identity_type: external_exports.string().min(1).optional(),
8837
+ identity_value: external_exports.string().min(1).optional(),
8838
+ channel_type: external_exports.string().min(1).optional(),
8839
+ channel_id: uuidSchema.optional(),
8840
+ connection_id: uuidSchema.optional(),
8841
+ user_id: uuidSchema.optional(),
8842
+ sender_display_name: external_exports.string().max(200).optional()
8818
8843
  });
8819
- toggleEvalBody = external_exports.object({
8820
- enabled: external_exports.boolean()
8844
+ approveContactBody = contactDecisionBody.extend({
8845
+ user_name: external_exports.string().min(1).max(120).optional()
8821
8846
  });
8822
- bulkToggleEvalsBody = external_exports.object({
8823
- hub_id: external_exports.string().uuid(),
8824
- enabled: external_exports.boolean(),
8825
- filters: external_exports.object({
8826
- agent_id: external_exports.string().uuid().optional(),
8827
- search: external_exports.string().optional()
8828
- }).optional()
8847
+ listContactAccessQuery = external_exports.object({
8848
+ status: external_exports.enum(["pending", "blocked"]).optional()
8829
8849
  });
8830
- pacingConfigSchema = external_exports.object({
8831
- preset: external_exports.enum(EVAL_PACING_PRESET_NAMES),
8832
- custom_interval_ms: external_exports.number().int().min(PACING_INTERVAL_MIN_MS).max(PACING_INTERVAL_MAX_MS).optional()
8833
- }).refine(
8834
- (v) => v.preset !== "custom" || typeof v.custom_interval_ms === "number",
8835
- { message: 'custom_interval_ms required when preset is "custom"' }
8836
- );
8837
- EVAL_MAX_SELECTED_SCENARIOS = 200;
8838
- evalScenarioSelectionEntrySchema = external_exports.object({
8839
- eval_id: external_exports.string().uuid(),
8840
- run_numbers: external_exports.array(external_exports.number().int().min(1).max(EVAL_MAX_RUNS_PER_SCENARIO)).min(1).max(EVAL_MAX_RUNS_PER_SCENARIO).refine((runs) => new Set(runs).size === runs.length, {
8841
- message: "run_numbers must not repeat a run"
8842
- }).optional()
8850
+ createHubTeamBody = external_exports.object({
8851
+ team_name: external_exports.string().min(1, "team_name is required")
8843
8852
  }).strict();
8844
- evalScenarioSelectionSchema = external_exports.array(evalScenarioSelectionEntrySchema).min(1).max(EVAL_MAX_SELECTED_SCENARIOS).refine(
8845
- (entries) => new Set(entries.map((e) => e.eval_id)).size === entries.length,
8846
- { message: "scenario_selection must not name the same scenario twice" }
8847
- );
8848
- sessionConfigSchema = external_exports.object({
8849
- pacing: pacingConfigSchema.optional(),
8850
- scenario_selection: evalScenarioSelectionSchema.optional(),
8851
- /**
8852
- * CALL MODE (realtime voice calls, plan §12.1): every turn this session fires runs as a call
8853
- * turn would — the pilot gets the call-mode addendum, and the reply gate takes no rewrite (a
8854
- * draft it would have rewritten is held, as on a call). Delivery and scoring stay a text
8855
- * eval's. A property of the launch, like the two keys above.
8856
- */
8857
- call_mode: external_exports.boolean().optional(),
8858
- // Server-owned immutable clock.
8859
- date_context: external_exports.never().optional(),
8860
- date_context_claimed: external_exports.never().optional(),
8861
- seed_cleanup: external_exports.never().optional(),
8862
- // Per-run finalization deadline for the HubDO watchdog (gh #2591). A started
8863
- // run idle past this many ms is reaped to `failed`. Omitted → backend default
8864
- // (`EVAL_DEFAULT_RUN_DEADLINE_MS`).
8865
- run_deadline_ms: external_exports.number().int().min(EVAL_RUN_DEADLINE_MIN_MS).max(EVAL_RUN_DEADLINE_MAX_MS).optional(),
8866
- seed: external_exports.never().optional()
8867
- }).passthrough();
8868
- createSessionBody = external_exports.object({
8869
- session: external_exports.object({
8870
- session_name: external_exports.string().trim().min(1),
8871
- session_config: sessionConfigSchema.optional()
8872
- }).passthrough()
8853
+ updateHubTeamBody = external_exports.object({
8854
+ team_name: external_exports.string().min(1).optional(),
8855
+ conversation_display_only_if_claimed: external_exports.boolean().optional(),
8856
+ team_access_rule: external_exports.string().optional(),
8857
+ initial_team: external_exports.boolean().optional()
8858
+ }).strict();
8859
+ addHubTeamUserBody = external_exports.object({
8860
+ user_email: external_exports.string().email("valid email is required")
8873
8861
  });
8874
- getSessionsQuery = external_exports.object({
8875
- hub_id: external_exports.string().uuid(),
8876
- status: external_exports.string().optional(),
8877
- search: external_exports.string().optional(),
8878
- limit: evalListLimit,
8879
- offset: external_exports.string().regex(/^\d+$/).optional()
8862
+ reassignHubUserBody = external_exports.object({
8863
+ hub_team_id: uuidSchema.nullable()
8880
8864
  });
8881
- getSessionResultsQuery = external_exports.object({
8882
- hub_id: external_exports.string().uuid(),
8883
- limit: external_exports.string().regex(/^\d+$/).optional(),
8884
- offset: external_exports.string().regex(/^\d+$/).optional()
8865
+ replicatePreviewBody = external_exports.object({
8866
+ preview_label: previewLabelField
8885
8867
  });
8886
- getSessionRunsQuery = external_exports.object({
8887
- hub_id: external_exports.string().uuid(),
8888
- eval_id: external_exports.string().uuid().optional(),
8889
- limit: external_exports.string().regex(/^\d+$/).optional(),
8890
- offset: external_exports.string().regex(/^\d+$/).optional()
8868
+ HUB_DIFF_SECTION_SET = {
8869
+ agents: true,
8870
+ agent_parameters: true,
8871
+ connections: true,
8872
+ mcp_tools: true,
8873
+ tools: true,
8874
+ channels: true,
8875
+ states: true,
8876
+ teams: true,
8877
+ resources: true,
8878
+ resource_folders: true,
8879
+ resource_files: true,
8880
+ agent_resources: true,
8881
+ message_templates: true,
8882
+ contact_lists: true,
8883
+ automations: true,
8884
+ evals: true
8885
+ };
8886
+ HUB_DIFF_SECTIONS = Object.keys(HUB_DIFF_SECTION_SET);
8887
+ updateChannelTestIdentitiesBody = external_exports.object({
8888
+ test_identities: external_exports.array(external_exports.string().max(320)).max(1e3)
8891
8889
  });
8892
- evalAnalyticsQuery = external_exports.object({
8893
- hub_id: external_exports.string().uuid(),
8894
- start_date: external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
8895
- end_date: external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
8896
- periodicity: external_exports.enum(["daily", "weekly", "monthly"]).optional(),
8897
- eval_id: external_exports.string().uuid().optional(),
8898
- session_id: external_exports.string().uuid().optional()
8890
+ claimCodeChannelParam = external_exports.object({
8891
+ id: uuidSchema,
8892
+ channelId: uuidSchema
8899
8893
  });
8900
- getSessionCostQuery = external_exports.object({
8901
- hub_id: external_exports.string().uuid()
8894
+ claimCodeDeleteParam = external_exports.object({
8895
+ id: uuidSchema,
8896
+ channelId: uuidSchema,
8897
+ code: external_exports.string().regex(/^[A-Za-z0-9]{6}$/, "Invalid claim code format").transform((s) => s.toUpperCase())
8902
8898
  });
8903
- compareSessionsQuery = external_exports.object({
8904
- hub_id: external_exports.string().uuid(),
8905
- session_a: external_exports.string().uuid(),
8906
- session_b: external_exports.string().uuid()
8899
+ PREVIOUS_CONVERSATIONS_MAX = 20;
8900
+ NATIVE_TOOL_NAMES = new Set(NATIVE_TOOLS.map((t) => t.tool_name));
8901
+ previousConversationsCountField = external_exports.number().int().min(0).max(PREVIOUS_CONVERSATIONS_MAX).nullable().optional();
8902
+ summarizationThresholdField = external_exports.number().int().min(SUMMARIZATION_THRESHOLD_MIN).max(SUMMARIZATION_THRESHOLD_MAX).nullable().optional();
8903
+ flagConditionSchema = external_exports.object({
8904
+ variable: external_exports.string(),
8905
+ operator: external_exports.enum(FLAG_CONDITION_OPERATORS),
8906
+ // `boolean` is admitted for parity with the CI write path, whose refine gates the
8907
+ // operator alone, so `value: false` on a boolean evaluation variable is storable
8908
+ // config today and the evaluator honours it through `String()`. Narrowing here would
8909
+ // reject on PATCH exactly what `wayai push` persists, so any REST caller that reads
8910
+ // an agent and writes it back — the typed clients, the CLI's `ApiClient`, MCP — would
8911
+ // fail on a hub configured through the other surface.
8912
+ value: external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean()])
8907
8913
  });
8908
- evalsSqlBody = external_exports.object({
8909
- hub_id: external_exports.string().uuid(),
8910
- // Hard size cap before the validator runs — keeps lex/parse work bounded.
8911
- sql: external_exports.string().min(1).max(8e3),
8912
- limit: external_exports.number().int().positive().max(1e4).optional()
8914
+ MONITOR_TRIGGERS = [
8915
+ "idle",
8916
+ "user_message",
8917
+ "assistant_reply",
8918
+ "manual",
8919
+ "call_utterance",
8920
+ "automation_fire",
8921
+ "automation_item"
8922
+ ];
8923
+ monitorTriggerSchema = external_exports.enum(MONITOR_TRIGGERS);
8924
+ AUTOMATION_GATE_TRIGGERS = ["automation_fire", "automation_item"];
8925
+ NON_FIRING_TRIGGERS = ["manual", ...AUTOMATION_GATE_TRIGGERS];
8926
+ MONITOR_FIRING_TRIGGERS = MONITOR_TRIGGERS.filter(isFiringTrigger);
8927
+ MONITOR_DELAY_SECONDS_MIN = 10;
8928
+ MONITOR_IDLE_DELAY_REQUIRED_MESSAGE = "delay_seconds is required for an idle monitor (an absent trigger is idle)";
8929
+ MONITOR_HISTORY_MESSAGES_MAX = 100;
8930
+ monitorHistoryMessagesSchema = external_exports.number().int().min(1).max(MONITOR_HISTORY_MESSAGES_MAX);
8931
+ monitorIncludeToolResultsSchema = external_exports.boolean();
8932
+ MONITOR_INPUT_SHAPING_KEYS = ["history_messages", "include_tool_results"];
8933
+ MONITOR_INPUT_SHAPING_SCHEMAS = {
8934
+ history_messages: monitorHistoryMessagesSchema.optional(),
8935
+ include_tool_results: monitorIncludeToolResultsSchema.optional()
8936
+ };
8937
+ MONITOR_INPUT_SHAPING_IDLE_MESSAGE = "only a user_message, assistant_reply, manual or call_utterance monitor reads this \u2014 an idle monitor runs as a full turn and takes the ordinary history window";
8938
+ monitorArgumentSourceSchema = external_exports.union([
8939
+ external_exports.object({ from_variable: external_exports.string().min(1) }).strict(),
8940
+ external_exports.object({ const: external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean()]) }).strict()
8941
+ ]);
8942
+ MONITOR_NOTE_TEMPLATE_MAX = 2e3;
8943
+ MONITOR_STEER_NOTE_MAX = 500;
8944
+ MONITOR_GATE_AGENT_NAME_MAX = 255;
8945
+ monitorActionSchema = external_exports.discriminatedUnion("kind", [
8946
+ external_exports.object({ kind: external_exports.literal("none") }).strict(),
8947
+ external_exports.object({
8948
+ kind: external_exports.literal("call_tool"),
8949
+ tool_name: external_exports.string().min(1),
8950
+ args: external_exports.record(monitorArgumentSourceSchema).optional()
8951
+ }).strict(),
8952
+ external_exports.object({ kind: external_exports.literal("hold") }).strict(),
8953
+ external_exports.object({ kind: external_exports.literal("rewrite"), note: external_exports.string().min(1).max(MONITOR_NOTE_TEMPLATE_MAX) }).strict(),
8954
+ external_exports.object({ kind: external_exports.literal("steer"), note: external_exports.string().min(1).max(MONITOR_STEER_NOTE_MAX) }).strict(),
8955
+ // An automation's fire gate (`automation_fire` only): run the fire as configured, run it with
8956
+ // another of the hub's agents — named by `agent_name`, which survives publish and push the way
8957
+ // the gate's own name does — or skip it.
8958
+ external_exports.object({ kind: external_exports.literal("run") }).strict(),
8959
+ external_exports.object({ kind: external_exports.literal("run_with_agent"), agent: external_exports.string().trim().min(1).max(MONITOR_GATE_AGENT_NAME_MAX) }).strict(),
8960
+ // An automation's item gate (`automation_item` only), for one contact of a fire's list: start
8961
+ // its work as configured, or start it with another of the hub's agents (by `agent_name`, as
8962
+ // `run_with_agent` names one). Both gates' `skip`, below, starts nothing.
8963
+ external_exports.object({ kind: external_exports.literal("start") }).strict(),
8964
+ external_exports.object({ kind: external_exports.literal("start_with_agent"), agent: external_exports.string().trim().min(1).max(MONITOR_GATE_AGENT_NAME_MAX) }).strict(),
8965
+ external_exports.object({ kind: external_exports.literal("skip") }).strict()
8966
+ ]);
8967
+ monitorRuleSchema = external_exports.object({
8968
+ when: external_exports.array(flagConditionSchema).min(1),
8969
+ action: monitorActionSchema
8970
+ }).strict();
8971
+ MONITOR_RULE_KEYS = ["rules", "fallback"];
8972
+ MONITOR_RULE_SCHEMAS = {
8973
+ rules: external_exports.array(monitorRuleSchema).optional(),
8974
+ fallback: monitorActionSchema.optional()
8975
+ };
8976
+ MONITOR_RULE_TRIGGERS = [
8977
+ "user_message",
8978
+ "assistant_reply",
8979
+ "manual",
8980
+ "call_utterance",
8981
+ "automation_fire",
8982
+ "automation_item"
8983
+ ];
8984
+ MONITOR_RULE_TRIGGER_MESSAGE = "only a user_message, assistant_reply, manual, call_utterance, automation_fire or automation_item monitor acts on rules \u2014 set one of those triggers, or remove this key. A manual monitor acts on its rules when another monitor runs it.";
8985
+ CALL_UTTERANCE_SPEAKERS = ["caller", "voice", "both"];
8986
+ callUtteranceSpeakerSchema = external_exports.enum(CALL_UTTERANCE_SPEAKERS);
8987
+ MONITOR_CALL_KEYS = ["speaker"];
8988
+ MONITOR_CALL_SCHEMAS = {
8989
+ speaker: callUtteranceSpeakerSchema.optional()
8990
+ };
8991
+ MONITOR_CALL_KEY_MESSAGE = "only a call_utterance monitor reads this: it names whose speech on a live call a check waits for";
8992
+ CALL_STEERING_MIN_CONFIDENCE = 0.9;
8993
+ CALL_UTTERANCE_RULE_NOT_CONFIDENT_MESSAGE = `a call_utterance rule acts on a live call from a transcript that can be misheard, so it must be high-confidence: give it a condition on one of this monitor's "\u2026${CONFIDENCE_VARIABLE_SUFFIX}" variables with ">= ${CALL_STEERING_MIN_CONFIDENCE}" or a higher bar, up to 1.`;
8994
+ CALL_UTTERANCE_FALLBACK_MESSAGE = "a call_utterance monitor acts only when a high-confidence rule matches \u2014 a fallback would act on every check of the call. Remove it.";
8995
+ CALL_UTTERANCE_FLAG_CONDITIONS_MESSAGE = "a call_utterance monitor checks a live call every few seconds and does not flag the conversation. Remove its flag_conditions, or flag from a monitor on another trigger.";
8996
+ CALL_STEER_NOTE_BLANK_MESSAGE = "a steer's note is what the voice is told \u2014 write the instruction it should follow.";
8997
+ MONITOR_USER_MESSAGE_ACTION_KINDS = ["none", "call_tool"];
8998
+ MONITOR_ASSISTANT_REPLY_ACTION_KINDS = ["none", "call_tool", "hold", "rewrite"];
8999
+ MONITOR_CALL_UTTERANCE_ACTION_KINDS = ["none", "call_tool", "steer"];
9000
+ MONITOR_AUTOMATION_FIRE_ACTION_KINDS = ["run", "run_with_agent", "skip"];
9001
+ MONITOR_AUTOMATION_ITEM_ACTION_KINDS = ["start", "start_with_agent", "skip"];
9002
+ INSERT_NOTE_TOOL_NAME = "insert_note";
9003
+ RUN_MONITOR_TOOL_NAME = "run_monitor";
9004
+ MONITOR_RULE_ALLOWED_NATIVE_TOOLS = [
9005
+ "update_state",
9006
+ "schedule_followup",
9007
+ "transfer_to_agent",
9008
+ "transfer_to_team",
9009
+ INSERT_NOTE_TOOL_NAME,
9010
+ RUN_MONITOR_TOOL_NAME
9011
+ ];
9012
+ MONITOR_RULE_REENTRY_TOOLS = {
9013
+ transfer_to_agent: "agent",
9014
+ transfer_to_team: "team"
9015
+ };
9016
+ MONITOR_RULE_REENTRY_TRACKS = new Map(Object.entries(MONITOR_RULE_REENTRY_TOOLS));
9017
+ AUTOMATION_FIRE_FLAG_CONDITIONS_MESSAGE = "an automation_fire monitor decides an automation's fire before any conversation exists, so there is no conversation for it to flag. Remove flag_conditions.";
9018
+ AUTOMATION_FIRE_INPUT_SHAPING_MESSAGE = "an automation_fire monitor reads the automation and its fire, never a conversation's messages, so it has no history window to size. Remove this key.";
9019
+ AUTOMATION_ITEM_FLAG_CONDITIONS_MESSAGE = "an automation_item monitor decides one contact of an automation's fire before anything is started for it, so there is no conversation for it to flag. Remove flag_conditions.";
9020
+ AUTOMATION_ITEM_INPUT_SHAPING_MESSAGE = "an automation_item monitor reads the automation, its fire and one contact, never a conversation's messages, so it has no history window to size. Remove this key.";
9021
+ AUTOMATION_GATE_KEY_MESSAGES = {
9022
+ automation_fire: { flagConditions: AUTOMATION_FIRE_FLAG_CONDITIONS_MESSAGE, inputShaping: AUTOMATION_FIRE_INPUT_SHAPING_MESSAGE },
9023
+ automation_item: { flagConditions: AUTOMATION_ITEM_FLAG_CONDITIONS_MESSAGE, inputShaping: AUTOMATION_ITEM_INPUT_SHAPING_MESSAGE }
9024
+ };
9025
+ monitorConfigField = external_exports.object({
9026
+ delay_seconds: external_exports.number().int().min(MONITOR_DELAY_SECONDS_MIN).optional(),
9027
+ trigger: monitorTriggerSchema.optional(),
9028
+ ...MONITOR_INPUT_SHAPING_SCHEMAS,
9029
+ ...MONITOR_RULE_SCHEMAS,
9030
+ ...MONITOR_CALL_SCHEMAS,
9031
+ flag_conditions: external_exports.array(flagConditionSchema).optional()
9032
+ }).passthrough().superRefine((config, ctx) => {
9033
+ if (monitorConfigNeedsDelay(config)) {
9034
+ ctx.addIssue({
9035
+ code: external_exports.ZodIssueCode.custom,
9036
+ path: ["delay_seconds"],
9037
+ message: MONITOR_IDLE_DELAY_REQUIRED_MESSAGE
9038
+ });
9039
+ }
9040
+ for (const key of monitorInputShapingKeysOnIdle(config)) {
9041
+ ctx.addIssue({
9042
+ code: external_exports.ZodIssueCode.custom,
9043
+ path: [key],
9044
+ message: MONITOR_INPUT_SHAPING_IDLE_MESSAGE
9045
+ });
9046
+ }
9047
+ for (const key of monitorCallKeysOffTrigger(config)) {
9048
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: [key], message: MONITOR_CALL_KEY_MESSAGE });
9049
+ }
9050
+ for (const issue of collectMonitorRuleIssues(config)) {
9051
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: issue.path, message: issue.message });
9052
+ }
9053
+ }).nullable().optional();
9054
+ flagConditionsField = external_exports.array(flagConditionSchema).nullable().optional();
9055
+ agentIdParam = external_exports.object({
9056
+ id: uuidSchema
8913
9057
  });
8914
- evalsSqlSchemaQuery = external_exports.object({
8915
- hub_id: external_exports.string().uuid()
9058
+ listAgentsQuery = external_exports.object({
9059
+ hub_id: uuidSchema
8916
9060
  });
8917
- exportResultsQuery = external_exports.object({
8918
- format: external_exports.enum(["csv", "json"]).default("csv")
9061
+ agentConnectionsQuery = external_exports.object({
9062
+ hub_id: uuidSchema
8919
9063
  });
8920
- validateEvalBody = external_exports.object({
8921
- eval: external_exports.record(external_exports.unknown())
9064
+ createAgentBody = external_exports.object({
9065
+ agent_name: external_exports.string().min(1),
9066
+ hub_id: uuidSchema,
9067
+ agent_role: external_exports.enum(AGENT_ROLES),
9068
+ additional_context_template: external_exports.string().max(2e4).optional(),
9069
+ summarization_threshold_tokens: summarizationThresholdField,
9070
+ previous_conversations_count: previousConversationsCountField,
9071
+ monitor_config: monitorConfigField,
9072
+ flag_conditions: flagConditionsField
9073
+ }).passthrough().superRefine((body, ctx) => {
9074
+ refineDecisionsModelBinding(body, ctx);
9075
+ refineMonitorRulesStructuredOutput(body, ctx);
8922
9076
  });
8923
- hubAgentsQuery = external_exports.object({
8924
- hub_id: external_exports.string().uuid()
9077
+ updateAgentBody = external_exports.object({
9078
+ additional_context_template: external_exports.string().max(2e4).optional(),
9079
+ summarization_threshold_tokens: summarizationThresholdField,
9080
+ previous_conversations_count: previousConversationsCountField,
9081
+ monitor_config: monitorConfigField,
9082
+ flag_conditions: flagConditionsField
9083
+ }).passthrough();
9084
+ AGENT_PARAMETER_TYPES = ["string", "number", "boolean", "integer", "enum"];
9085
+ AGENT_PARAMETER_NAME_REGEX = /^[a-zA-Z_][a-zA-Z0-9_]{0,63}$/;
9086
+ agentParameterCreateSchema = external_exports.object({
9087
+ parameter_name: external_exports.string().regex(
9088
+ AGENT_PARAMETER_NAME_REGEX,
9089
+ "parameter_name must start with a letter or underscore and contain only letters, digits, and underscores (max 64 chars)"
9090
+ ),
9091
+ parameter_type: external_exports.enum(AGENT_PARAMETER_TYPES).optional(),
9092
+ // No length caps on the free-text fields below: the agent_parameter columns are
9093
+ // unbounded TEXT and pre-PR rows were never length-validated, so a cap would 422
9094
+ // an unrelated GET→edit→re-save of legitimately-long existing data. The name
9095
+ // regex (above) and the batch cap (below) are the load-bearing guards; total
9096
+ // payload size belongs in a global /api/* body limit, not per field here.
9097
+ parameter_description: external_exports.string().nullable().optional(),
9098
+ parameter_label: external_exports.string().nullable().optional(),
9099
+ parameter_enum: external_exports.array(external_exports.string()).nullable().optional(),
9100
+ parameter_required: external_exports.boolean().optional(),
9101
+ // Free-form analytics grouping label — no DB CHECK and the CI path persists
9102
+ // arbitrary strings, so keep this permissive (not the 4-value UI dropdown enum).
9103
+ variable_category: external_exports.string().nullable().optional(),
9104
+ is_summary: external_exports.boolean().optional()
9105
+ }).strict();
9106
+ MAX_AGENT_PARAMETERS_PER_REQUEST = 100;
9107
+ createAgentParametersBody = external_exports.union([
9108
+ agentParameterCreateSchema,
9109
+ external_exports.array(agentParameterCreateSchema).max(MAX_AGENT_PARAMETERS_PER_REQUEST, `too many parameters (max ${MAX_AGENT_PARAMETERS_PER_REQUEST})`)
9110
+ ]);
9111
+ evalIdParam = external_exports.object({
9112
+ id: external_exports.string().uuid()
8925
9113
  });
8926
- createScenarioSetBody = external_exports.object({
8927
- hub_id: external_exports.string().uuid(),
8928
- set_name: external_exports.string().min(1).max(200),
8929
- description: external_exports.string().max(1e3).optional(),
8930
- enabled: external_exports.boolean().optional()
9114
+ sessionIdParam = external_exports.object({
9115
+ id: external_exports.string().uuid()
8931
9116
  });
8932
- updateScenarioSetBody = external_exports.object({
8933
- set_name: external_exports.string().min(1).max(200).optional(),
8934
- description: external_exports.string().max(1e3).nullable().optional(),
8935
- enabled: external_exports.boolean().optional()
9117
+ scenarioSetIdParam = external_exports.object({
9118
+ id: external_exports.string().uuid()
8936
9119
  });
8937
- scenarioSetsHubQuery = external_exports.object({
9120
+ hubIdQuery = external_exports.object({
9121
+ hub_id: external_exports.string().uuid()
9122
+ });
9123
+ evalDateContextSchema = external_exports.object({
9124
+ base_time: timestampSchema.refine(isIsoTimestamp, "Expected a canonical ISO timestamp"),
9125
+ timezone: external_exports.string().min(1).refine((timezone) => {
9126
+ try {
9127
+ new Intl.DateTimeFormat("en-US", { timeZone: timezone }).format(0);
9128
+ return true;
9129
+ } catch {
9130
+ return false;
9131
+ }
9132
+ }, "Expected an IANA timezone"),
9133
+ locale: external_exports.enum(SUPPORTED_LOCALES)
9134
+ }).strict();
9135
+ EVAL_FIXTURE_NAME_MAX_LENGTH = 200;
9136
+ evalFixtureOverrideSchema = external_exports.string().trim().min(1).max(EVAL_FIXTURE_NAME_MAX_LENGTH);
9137
+ runSessionQuery = hubIdQuery.extend({
9138
+ fixture: evalFixtureOverrideSchema.optional()
9139
+ });
9140
+ runJourneyQuery = hubIdQuery.extend({
9141
+ call_mode: external_exports.enum(["true", "false"]).optional()
9142
+ });
9143
+ EVAL_INPUT_ROLES = ["user", "system"];
9144
+ EVAL_INPUT_ROLE_LIST = EVAL_INPUT_ROLES.map((r) => `"${r}"`).join(" or ");
9145
+ ROLE_ECHO_MAX = 40;
9146
+ EVAL_INITIAL_STATE_SCOPES = ["user"];
9147
+ MAX_INITIAL_STATE_ENTRIES = 20;
9148
+ evalInitialStateEntry = external_exports.object({
9149
+ slug: external_exports.string().min(1).max(200),
9150
+ scope: external_exports.enum(EVAL_INITIAL_STATE_SCOPES).default("user"),
9151
+ value: external_exports.record(external_exports.unknown())
9152
+ });
9153
+ evalBody = external_exports.object({
9154
+ eval: external_exports.record(external_exports.unknown())
9155
+ }).superRefine(refineEvalName).superRefine(refineEvalMessageTextRole).superRefine(refineEvalAttachments).superRefine(refineEvalInitialState);
9156
+ EVAL_LIST_MAX_LIMIT = 1e3;
9157
+ evalListLimit = external_exports.string().regex(/^\d+$/).refine((v) => Number(v) <= EVAL_LIST_MAX_LIMIT, {
9158
+ message: `limit must be ${EVAL_LIST_MAX_LIMIT} or less`
9159
+ }).optional();
9160
+ getEvalsQuery = external_exports.object({
9161
+ hub_id: external_exports.string().uuid(),
9162
+ agent_id: external_exports.string().uuid().optional(),
9163
+ enabled: external_exports.string().regex(/^(true|false)$/).optional(),
9164
+ search: external_exports.string().optional(),
9165
+ limit: evalListLimit,
9166
+ offset: external_exports.string().regex(/^\d+$/).optional()
9167
+ });
9168
+ toggleEvalBody = external_exports.object({
9169
+ enabled: external_exports.boolean()
9170
+ });
9171
+ bulkToggleEvalsBody = external_exports.object({
9172
+ hub_id: external_exports.string().uuid(),
9173
+ enabled: external_exports.boolean(),
9174
+ filters: external_exports.object({
9175
+ agent_id: external_exports.string().uuid().optional(),
9176
+ search: external_exports.string().optional()
9177
+ }).optional()
9178
+ });
9179
+ pacingConfigSchema = external_exports.object({
9180
+ preset: external_exports.enum(EVAL_PACING_PRESET_NAMES),
9181
+ custom_interval_ms: external_exports.number().int().min(PACING_INTERVAL_MIN_MS).max(PACING_INTERVAL_MAX_MS).optional()
9182
+ }).refine(
9183
+ (v) => v.preset !== "custom" || typeof v.custom_interval_ms === "number",
9184
+ { message: 'custom_interval_ms required when preset is "custom"' }
9185
+ );
9186
+ EVAL_MAX_SELECTED_SCENARIOS = 200;
9187
+ evalScenarioSelectionEntrySchema = external_exports.object({
9188
+ eval_id: external_exports.string().uuid(),
9189
+ run_numbers: external_exports.array(external_exports.number().int().min(1).max(EVAL_MAX_RUNS_PER_SCENARIO)).min(1).max(EVAL_MAX_RUNS_PER_SCENARIO).refine((runs) => new Set(runs).size === runs.length, {
9190
+ message: "run_numbers must not repeat a run"
9191
+ }).optional()
9192
+ }).strict();
9193
+ evalScenarioSelectionSchema = external_exports.array(evalScenarioSelectionEntrySchema).min(1).max(EVAL_MAX_SELECTED_SCENARIOS).refine(
9194
+ (entries) => new Set(entries.map((e) => e.eval_id)).size === entries.length,
9195
+ { message: "scenario_selection must not name the same scenario twice" }
9196
+ );
9197
+ sessionConfigSchema = external_exports.object({
9198
+ pacing: pacingConfigSchema.optional(),
9199
+ scenario_selection: evalScenarioSelectionSchema.optional(),
9200
+ /**
9201
+ * CALL MODE (realtime voice calls, plan §12.1): every turn this session fires runs as a call
9202
+ * turn would — the pilot gets the call-mode addendum, and the reply gate takes no rewrite (a
9203
+ * draft it would have rewritten is held, as on a call). Delivery and scoring stay a text
9204
+ * eval's. A property of the launch, like the two keys above.
9205
+ */
9206
+ call_mode: external_exports.boolean().optional(),
9207
+ // Server-owned immutable clock.
9208
+ date_context: external_exports.never().optional(),
9209
+ date_context_claimed: external_exports.never().optional(),
9210
+ seed_cleanup: external_exports.never().optional(),
9211
+ // Per-run finalization deadline for the HubDO watchdog (gh #2591). A started
9212
+ // run idle past this many ms is reaped to `failed`. Omitted → backend default
9213
+ // (`EVAL_DEFAULT_RUN_DEADLINE_MS`).
9214
+ run_deadline_ms: external_exports.number().int().min(EVAL_RUN_DEADLINE_MIN_MS).max(EVAL_RUN_DEADLINE_MAX_MS).optional(),
9215
+ seed: external_exports.never().optional()
9216
+ }).passthrough();
9217
+ createSessionBody = external_exports.object({
9218
+ session: external_exports.object({
9219
+ session_name: external_exports.string().trim().min(1),
9220
+ session_config: sessionConfigSchema.optional()
9221
+ }).passthrough()
9222
+ });
9223
+ getSessionsQuery = external_exports.object({
9224
+ hub_id: external_exports.string().uuid(),
9225
+ status: external_exports.string().optional(),
9226
+ search: external_exports.string().optional(),
9227
+ limit: evalListLimit,
9228
+ offset: external_exports.string().regex(/^\d+$/).optional()
9229
+ });
9230
+ getSessionResultsQuery = external_exports.object({
9231
+ hub_id: external_exports.string().uuid(),
9232
+ limit: external_exports.string().regex(/^\d+$/).optional(),
9233
+ offset: external_exports.string().regex(/^\d+$/).optional()
9234
+ });
9235
+ getSessionRunsQuery = external_exports.object({
9236
+ hub_id: external_exports.string().uuid(),
9237
+ eval_id: external_exports.string().uuid().optional(),
9238
+ limit: external_exports.string().regex(/^\d+$/).optional(),
9239
+ offset: external_exports.string().regex(/^\d+$/).optional()
9240
+ });
9241
+ evalAnalyticsQuery = external_exports.object({
9242
+ hub_id: external_exports.string().uuid(),
9243
+ start_date: external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
9244
+ end_date: external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
9245
+ periodicity: external_exports.enum(["daily", "weekly", "monthly"]).optional(),
9246
+ eval_id: external_exports.string().uuid().optional(),
9247
+ session_id: external_exports.string().uuid().optional()
9248
+ });
9249
+ getSessionCostQuery = external_exports.object({
9250
+ hub_id: external_exports.string().uuid()
9251
+ });
9252
+ compareSessionsQuery = external_exports.object({
9253
+ hub_id: external_exports.string().uuid(),
9254
+ session_a: external_exports.string().uuid(),
9255
+ session_b: external_exports.string().uuid()
9256
+ });
9257
+ evalsSqlBody = external_exports.object({
9258
+ hub_id: external_exports.string().uuid(),
9259
+ // Hard size cap before the validator runs — keeps lex/parse work bounded.
9260
+ sql: external_exports.string().min(1).max(8e3),
9261
+ limit: external_exports.number().int().positive().max(1e4).optional()
9262
+ });
9263
+ evalsSqlSchemaQuery = external_exports.object({
9264
+ hub_id: external_exports.string().uuid()
9265
+ });
9266
+ exportResultsQuery = external_exports.object({
9267
+ format: external_exports.enum(["csv", "json"]).default("csv")
9268
+ });
9269
+ validateEvalBody = external_exports.object({
9270
+ eval: external_exports.record(external_exports.unknown())
9271
+ });
9272
+ hubAgentsQuery = external_exports.object({
9273
+ hub_id: external_exports.string().uuid()
9274
+ });
9275
+ createScenarioSetBody = external_exports.object({
9276
+ hub_id: external_exports.string().uuid(),
9277
+ set_name: external_exports.string().min(1).max(200),
9278
+ description: external_exports.string().max(1e3).optional(),
9279
+ enabled: external_exports.boolean().optional()
9280
+ });
9281
+ updateScenarioSetBody = external_exports.object({
9282
+ set_name: external_exports.string().min(1).max(200).optional(),
9283
+ description: external_exports.string().max(1e3).nullable().optional(),
9284
+ enabled: external_exports.boolean().optional()
9285
+ });
9286
+ scenarioSetsHubQuery = external_exports.object({
8938
9287
  hub_id: external_exports.string().uuid()
8939
9288
  });
8940
9289
  createScenarioFromConversationBody = external_exports.object({
@@ -9195,7 +9544,9 @@ var init_chunk_YEYIDIR6 = __esm({
9195
9544
  hubAsCodeConfigSchema = external_exports.object({
9196
9545
  version: external_exports.literal(1),
9197
9546
  hub: external_exports.object({
9198
- name: external_exports.string().min(1, "config.hub.name is required")
9547
+ name: external_exports.string().min(1, "config.hub.name is required"),
9548
+ // Apply writes it as it comes, so this is its validation on push and diff.
9549
+ end_user_daily_message_limit: endUserDailyMessageLimitField
9199
9550
  }).passthrough(),
9200
9551
  states: external_exports.array(hubAsCodeStateSchema).optional(),
9201
9552
  resources: boundedHubAsCodeResourcesSchema.optional()
@@ -9203,6 +9554,7 @@ var init_chunk_YEYIDIR6 = __esm({
9203
9554
  refineHubAsCodeCustomTools(config, ctx);
9204
9555
  refineHubAsCodeKanbanStatuses(config, ctx);
9205
9556
  refineHubAsCodeLanes(config, ctx);
9557
+ refineHubAsCodePresentation(config, ctx);
9206
9558
  refineHubAsCodeEvals(config, ctx);
9207
9559
  refineHubAsCodeEvalAttachments(config, ctx);
9208
9560
  refineHubAsCodeCallOpenings(config, ctx);
@@ -9372,15 +9724,7 @@ var init_chunk_YEYIDIR6 = __esm({
9372
9724
  }
9373
9725
  });
9374
9726
 
9375
- // ../../packages/core/dist/chunk-H4RTULPH.js
9376
- function refineLaneReferences(val, ctx) {
9377
- const lanes = val.lanes;
9378
- const statuses = val.kanban_statuses;
9379
- if (lanes == null || statuses == null) return;
9380
- for (const issue of validateLaneReferences(lanes, statuses)) {
9381
- ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["kanban_statuses", ...issue.path], message: issue.message });
9382
- }
9383
- }
9727
+ // ../../packages/core/dist/chunk-FRU7E62M.js
9384
9728
  function cacheReconcileIdCount(body) {
9385
9729
  return body.conversations.length + body.histories.reduce((n, history) => n + history.conversation_ids.length, 0) + body.threads.length;
9386
9730
  }
@@ -9440,16 +9784,17 @@ function parseCommunityLessonVideoUrl(url) {
9440
9784
  }
9441
9785
  return id !== void 0 && YOUTUBE_ID.test(id) ? { provider: "youtube", id } : null;
9442
9786
  }
9443
- var primaryRegionSchema, placementSourceSchema, orgIdParam, orgAdminIdParam, createOrganizationBody, updateOrganizationBody, addOrgAdminBody, hubIdParam, hubAdminIdParam, hubUserIdParam, hubIdentityIdParam, hubTeamIdParam, hubTeamUserDeleteParam, hubSchemaQuery, PREVIEW_LABEL_MAX_LENGTH, MAX_ENDED_INDEX_RETENTION_DAYS, MAX_EVAL_RETENTION_DAYS, previewLabelField, hubTagsField, createHubBody, updateHubBody, HUB_TAG_CHANGE_REFUSED, hubTagChangeRefusalSchema, addHubAdminBody, addHubIdentityAuthorizationBody, contactDecisionBody, approveContactBody, listContactAccessQuery, createHubTeamBody, updateHubTeamBody, addHubTeamUserBody, reassignHubUserBody, replicatePreviewBody, HUB_DIFF_SECTION_SET, HUB_DIFF_SECTIONS, updateChannelTestIdentitiesBody, claimCodeChannelParam, claimCodeDeleteParam, connectionIdParam, connectorIdParam, listConnectionsQuery, deleteConnectionQuery, addConnectionBody, editConnectionBody, PRODUCTION_DIRECT_FIELDS, setProductionCredentialBody, registerWhatsappQuery, registerWhatsappBody, retryProvisioningQuery, resendDomainStatusQuery, 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, ORG_TAG_NAME_REGEX, ORG_TAG_NAME_MAX_LENGTH, createOrgTagBody, updateOrgTagBody, orgCredentialIdParam, listOrgCredentialsQuery, createOrgCredentialBody, updateOrgCredentialBody, BASE_CREDENTIAL_MANAGED_BY, BASE_CREDENTIAL_NAME_MAX, baseCredentialNameSchema, createBaseCredentialLinkBody, baseCredentialLinkParams, baseCredentialLinkQuery, 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, getConversationsQuery, getMessagesQuery, appMessageSenderType, appMessageReceiverType, apiChannelMessage, apiChannelMessageBody, appMessageBody, appMessageResponse, CALL_STATUSES, callStatus, CALL_END_REASONS, callEndReason, CALL_TRANSPORTS, callTransport, CALL_PARTICIPANT_TYPES, callParticipantType, callInstant, MAX_SDP_OFFER_LENGTH, sdpDescription, sdpOffer, MAX_CALL_REQUEST_BODY_BYTES, hubScoped, callSummaryFields, callSummary, callIdParam, createCallBody, createCallResponse, callReadyBody, callHangupBody, callStatusQuery, MAX_REPORTED_DELEGATION_IDS, callDelegationId, callDelegationsBody, callResponse, MAX_CALL_RECORDING_GAPS, callRecordingGap, callRecordingNoteMetadata, evalCallInstant, EVAL_CALL_MIN_SECONDS, EVAL_CALL_MAX_SECONDS, EVAL_CALL_SPOKEN_LINE_MAX_CHARS, hubScoped2, createEvalCallBody, createEvalCallResponse, evalCallConversationQuery, evalCallRecordQuery, evalCallSpeaker, evalCallUtterance, evalCallTurn, evalCallRecording, evalCallRecordResponse, evalCallFinishResponse, updateUserBody, updateProfileBody, pathnameRegex, updatePreferencesBody, registerPushTokenBody, deletePushTokenQuery, recordAiDisclosureAcceptanceBody, activityQuery, deletionModeSchema, deletionRequestBody, CACHE_RECONCILE_MAX_IDS, CACHE_RECONCILE_MAX_HUBS, cacheReconcileScopeSchema, cachedConversationPageSchema, cachedHistoryThreadSchema, cachedPeopleThreadSchema, cacheReconcileBody, archiveHubIdParam, archiveConversationParams, archiveListQuery, archiveMessageObservabilityParams, conversationIdParam, conversationHubQuery, 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, planKeySchema, billingStatusSchema, billingPlanTypeSchema, dataUsageCountersSchema, REKOR_ENTITLEMENT_CONTRACT_VERSION, entitlementProjectionSchema, rekorEntitlementRefreshMessageSchema, downloadBody, uploadQuery, SIGN_URL_MAX_EXPIRES_IN_SECONDS, signUrlBody, templateIdParam, listTemplatesQuery, deleteTemplateQuery, templateStatusQuery, createTemplateBody, updateTemplateBody, submitTemplateBody, testTemplateBody, CONTACT_ENVIRONMENTS, CONTACT_NAME_MAX, CONTACT_EMAIL_MAX, CONTACT_PHONE_INPUT_MAX, CONTACT_INSTAGRAM_SID_MAX, CONTACT_METADATA_MAX_BYTES, CONTACT_LABEL_MAX, CONTACT_LABELS_MAX, CONTACT_SCOPE_TAGS_MAX, CONTACT_PAGE_MAX, CONTACT_IMPORT_BATCH_MAX, CONTACT_SEARCH_MAX, CONTACT_LIST_NAME_MAX, CONTACT_LIST_NAME_REGEX, CONTACT_LIST_DESCRIPTION_MAX, CONTACT_LIST_FILTER_MAX, CONTACT_LIST_PINS_PER_REQUEST_MAX, SUPPRESSION_SCOPES, SUPPRESSION_ID_REGEX, contactName, contactPhone, contactEmail, contactInstagramSid, contactLabel, contactLabels, contactMetadata, scopeTagIds, contactVisibilitySchema, hasIdentity, IDENTITY_REQUIRED, contactBookOrgQuery, contactBookContactParam, contactBookListParam, contactBookHubParam, contactBookPageQuery, listContactBookContactsQuery, listHubContactBookContactsQuery, contactBookLinkCandidatesQuery, listContactBookListMembersQuery, contactRowFields, createContactBookContactBody, updateContactBookContactBody, contactImportRowSchema, importContactBookContactsBody, linkContactBookContactBody, listName, contactListFilterSchema, createContactBookListBody, updateContactBookListBody, updateContactBookListPinsBody, suppressionIdentitySchema, createContactBookSuppressionBody, contactBookSuppressionParam, listContactBookSuppressionsQuery, CONTACT_BOOK_EMAIL_UNSUBSCRIBE_PATH, contactBookEmailUnsubscribeTokenSchema, contactBookEmailUnsubscribeQuery, orgListReferenceSchema, hubListNameSchema, HUB_LIST_FILTER_REQUIRED, hubContactListFilterSchema, hubContactListIdParam, hubContactListHubQuery, description, createHubContactListBody, updateHubContactListBody, AUTOMATION_TRIGGER_TYPES, AUTOMATION_TARGET_TYPES, AUTOMATION_ACTION_TYPES, AUTOMATION_CHANNEL_TYPES, AUTOMATION_PURPOSES, AUTOMATION_NAME_MAX, AUTOMATION_DESCRIPTION_MAX, AUTOMATION_INSTRUCTIONS_MAX, AUTOMATION_TEXT_MAX, AUTOMATION_CRON_MAX, automationTriggerSchema, automationTargetSchema, automationActionSchema, automationName, automationDescription, automationIdParam, automationHubQuery, AUTOMATION_RUNS_PAGE_MAX, listAutomationRunsQuery, createAutomationBody, updateAutomationBody, AUTOMATION_ALERT_CATEGORIES, AUTOMATION_BLOCKED_ALERT_CATEGORY, VERSION_PART, MOBILE_APP_VERSION_RE, mobileAppVersionSchema, MOBILE_PLATFORMS, mobilePlatformSchema, mobileVersionPolicyQuery, mobileVersionPolicySchema, mobileVersionPolicyResponse, adminOrgIdParam, adminOrgAdminIdParam, adminUserIdParam, PRICING_PLAN_ID_RE, adminPlanIdParam, adminOrganizationsQuery, adminUserSearchQuery, kanbanSlugMigrationQuery, adjustQuotaBody, updatePlanBody, addAdminUserBody, MAX_VOICE_CALL_MINUTE_OPS, voiceCallMinuteOps, AUTOMATION_LIST_MAX_CONTACTS_BOUND, automationListMaxContacts, updatePlatformConfigBody, updateFreeOrgLimitBody, adminScopedTargetShape, adminScopedTargetBody, BRANCHING_ORPHAN_ENTITY_TYPES, BRANCHING_ORPHAN_MAX_TARGETS, adminRepairBranchingOrphansBody, adminRepairLegacyOrgGrantsBody, adminRepairCompedPlansBody, 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, META_ENTITY_ID_PATTERN, metaEntityId, whatsappCallbackBody, authMeResponse, wsTicketResponse, sessionCheckResponse, logoutResponse, magicCodeSendBody, magicCodeSendResponse, magicCodeVerifyBody, magicCodeVerifyResponse, passwordLoginBody, 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, MAX_NAME_LENGTH, MAX_VALUE_LENGTH, MAX_TAGS, MAX_TAG_LENGTH, MAX_SCOPE_HUBS, MAX_SCOPE_TAGS, vaultSecretScopeSchema, vaultCreateBody, vaultUpdateBody, MAX_NAME_LENGTH2, MAX_HUBS_PER_GRANT, MAX_HUB_TAGS_PER_GRANT, MAX_GRANTS, permissionEnum, grantScopeSchema, grantSchema, createTokenBody, tokenOrgIdParam, invitePreviewQuery, inviteRolePreviewResponse, inviteContactPreviewResponse, invitePreviewResponse, inviteUnsubscribeBody, 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, MAX_PROVISIONING_BODY_BYTES, dataProxyQuery, rekorAttestation, REQUIRED_REKOR_ATTESTATION_HEADERS, BASE_DESTRUCTION_MOUNT, BASE_DESTRUCTION_PREFIX, BASE_DESTRUCTION_CONFIRM_PATH, baseDestructionConfirmBody, BASE_DESTRUCTION_GRACE_MS, BASE_DESTRUCTION_CONFIRM_TTL_MS, BASE_DESTRUCTION_ORG_QUERY_PARAM, baseDestructionQuery, baseDestructionParam, baseDestructionInitiateBody, baseDestructionStatus, baseDestructionRequest, baseDestructionListResponse, baseDestructionInitiateResponse, baseDestructionConfirmResponse, baseDestructionCancelResponse, rekorBaseChangeMessageSchema, PEOPLE_CONTACT_PAGE_MAX, PEOPLE_CONTACT_PAGE_DEFAULT, PEOPLE_CONTACT_EMAIL_MAX_LENGTH, peopleUserIdSchema, peopleInviteEmailSchema, peopleContactInviteBody, peopleContactInviteIdParam, peopleContactUserIdParam, peopleContactBlockBody, peopleContactPageQuery, peopleOutgoingInviteSchema, peopleContactPersonSchema, peopleContactSchema, peopleIncomingInviteSchema, peopleBlockedUserSchema, PEOPLE_THREAD_MESSAGE_MAX_LENGTH, PEOPLE_THREAD_MESSAGES_PAGE_MAX, PEOPLE_THREAD_PAGE_MAX, PEOPLE_THREAD_PAGE_DEFAULT, PEOPLE_GROUP_NAME_MAX_LENGTH, PEOPLE_GROUP_AVATAR_URL_MAX_LENGTH, PEOPLE_THREAD_ATTACHMENT_MAX_BYTES, PEOPLE_THREAD_ATTACHMENT_NAME_MAX_LENGTH, PEOPLE_ATTACHMENT_STORAGE_PER_USER_BYTES, PEOPLE_THREAD_ATTACHMENT_MAX_MB, PEOPLE_THREAD_ATTACHMENT_URL_TTL_SECONDS, PEOPLE_THREAD_ATTACHMENT_URLS_MAX, peopleThreadIdParam, peopleThreadMessageIdParam, peopleThreadListQuery, peopleThreadMessagesQuery, peopleThreadAttachmentUploadSchema, peopleThreadSendBody, peopleThreadAttachmentUrlsBody, peopleThreadReadBody, peopleThreadSettingsBody, peopleGroupNameSchema, peopleGroupAvatarUrlSchema, peopleGroupCreateBody, peopleOrgDirectBody, peopleGroupUpdateBody, peopleGroupInviteBody, peopleOrgErasureBody, peopleGroupLeaveBody, peopleGroupInviteIdParam, peopleGroupIncomingInviteIdParam, peopleGroupMemberParam, peopleThreadKindSchema, peopleThreadMemberSchema, peopleThreadLastMessageSchema, peopleGroupRoleSchema, peopleGroupSummarySchema, peopleThreadSummarySchema, peopleThreadAttachmentSchema, peopleThreadMessageSchema, peopleGroupMemberSchema, peopleGroupSentInviteSchema, peopleGroupIncomingInviteSchema, PEOPLE_REPORT_DETAILS_MAX_LENGTH, peopleReportReasonSchema, reportDetailsSchema, reportFields, peopleReportBody, PEOPLE_MODERATION_NOTE_MAX_LENGTH, ADMIN_PEOPLE_REPORTS_PAGE_MAX, ADMIN_PEOPLE_REPORTS_PAGE_DEFAULT, peopleModerationActionSchema, moderationNoteSchema, adminPeopleReportListQuery, adminPeopleReportIdParam, adminPeopleMessageRemovalBody, adminPeopleSuspendBody, adminPeopleNoteBody, COMMUNITIES_PER_ORG_MAX, COMMUNITY_NAME_MAX_LENGTH, COMMUNITY_REGISTRY_CLOSED_REASON, COMMUNITY_JOIN_SOURCE_MAX_LENGTH, COMMUNITY_JOIN_FLOW_TOKEN_MAX_LENGTH, COMMUNITY_ROOM_NAME_MAX_LENGTH, COMMUNITY_MESSAGE_MAX_LENGTH, COMMUNITY_MESSAGES_PAGE_SIZE, COMMUNITY_ATTACHMENT_URLS_MAX, COMMUNITY_POST_TITLE_MAX_LENGTH, COMMUNITY_POST_SEARCH_MAX_LENGTH, COMMUNITY_RULES_MAX_LENGTH, COMMUNITY_SLOW_MODE_MAX_SECONDS, COMMUNITY_COURSES_LABEL_MAX_LENGTH, COMMUNITY_LIVE_TICKET_PREFIX, communityNameSchema, adminCreateCommunityBody, communityIdParam, communityJoinTokenSchema, communityJoinSourceSchema, communityJoinPreviewQuery, communityJoinBody, communityRoomKindSchema, communityRoomNameSchema, communityRoomIdParam, communityMessageIdParam, communityRoomCreateBody, communityRoomUpdateBody, communityMessagesQuery, communityMessageBodySchema, communityPostTitleSchema, communityAttachmentUploadSchema, communitySendBody, communityEditBody, communityPostIdParam, communityPostsQuery, communityAnswerBody, communityReadBody, communityAttachmentUrlsBody, communityPersonParam, communityOrgParam, communityPeopleQuery, communityCoursesLabelSchema, communitySettingsBody, communityBanBody, communityLockBody, communityPinBody, communityModLogQuery, communityReportsQuery, communityReportIdParam, communityLiveTicketSchema, communityLiveQuery, communityMuteBody, communityEmailUnsubscribeTokenSchema, COMMUNITY_EMAIL_UNSUBSCRIBE_PATH, communityEmailUnsubscribeQuery, COMMUNITY_COURSE_TITLE_MAX_LENGTH, COMMUNITY_COURSE_DESCRIPTION_MAX_LENGTH, COMMUNITY_LESSON_BODY_MAX_LENGTH, COMMUNITY_LESSON_LINKS_MAX, COMMUNITY_LESSON_URL_MAX_LENGTH, YOUTUBE_ID, YOUTUBE_HOSTS, YOUTU_BE, YOUTUBE_ID_PATH, communityCourseIdParam, communityCourseModuleIdParam, communityLessonIdParam, communityCourseTitleSchema, communityCourseDescriptionSchema, communityCoursePositionSchema, communityLessonVideoUrlSchema, communityLessonLinkSchema, communityLessonLinksSchema, communityLessonBodySchema, communityCourseCreateBody, communityCourseUpdateBody, communityModuleCreateBody, communityModuleUpdateBody, communityLessonCreateBody, communityLessonUpdateBody, COMMUNITY_LESSON_TREE_MAX_BYTES, COMMUNITY_LESSON_LINK_PROTOCOLS, LINK_SCHEME;
9444
- var init_chunk_H4RTULPH = __esm({
9445
- "../../packages/core/dist/chunk-H4RTULPH.js"() {
9787
+ var connectionIdParam, connectorIdParam, listConnectionsQuery, deleteConnectionQuery, addConnectionBody, editConnectionBody, PRODUCTION_DIRECT_FIELDS, setProductionCredentialBody, registerWhatsappQuery, registerWhatsappBody, retryProvisioningQuery, resendDomainStatusQuery, 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, ORG_TAG_NAME_REGEX, ORG_TAG_NAME_MAX_LENGTH, createOrgTagBody, updateOrgTagBody, orgCredentialIdParam, listOrgCredentialsQuery, createOrgCredentialBody, updateOrgCredentialBody, BASE_CREDENTIAL_MANAGED_BY, BASE_CREDENTIAL_NAME_MAX, baseCredentialNameSchema, createBaseCredentialLinkBody, baseCredentialLinkParams, baseCredentialLinkQuery, 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, getConversationsQuery, getMessagesQuery, appMessageSenderType, appMessageReceiverType, apiChannelMessage, apiChannelMessageBody, appMessageBody, appMessageResponse, CALL_STATUSES, callStatus, CALL_END_REASONS, callEndReason, CALL_TRANSPORTS, callTransport, CALL_PARTICIPANT_TYPES, callParticipantType, callInstant, MAX_SDP_OFFER_LENGTH, sdpDescription, sdpOffer, MAX_CALL_REQUEST_BODY_BYTES, hubScoped, callSummaryFields, callSummary, callIdParam, createCallBody, createCallResponse, callReadyBody, callHangupBody, callStatusQuery, MAX_REPORTED_DELEGATION_IDS, callDelegationId, callDelegationsBody, callResponse, MAX_CALL_RECORDING_GAPS, callRecordingGap, callRecordingNoteMetadata, evalCallInstant, EVAL_CALL_MIN_SECONDS, EVAL_CALL_MAX_SECONDS, EVAL_CALL_SPOKEN_LINE_MAX_CHARS, hubScoped2, createEvalCallBody, createEvalCallResponse, evalCallConversationQuery, evalCallRecordQuery, evalCallSpeaker, evalCallUtterance, evalCallTurn, evalCallRecording, evalCallRecordResponse, evalCallFinishResponse, updateUserBody, updateProfileBody, pathnameRegex, updatePreferencesBody, registerPushTokenBody, deletePushTokenQuery, recordAiDisclosureAcceptanceBody, activityQuery, deletionModeSchema, deletionRequestBody, CACHE_RECONCILE_MAX_IDS, CACHE_RECONCILE_MAX_HUBS, cacheReconcileScopeSchema, cachedConversationPageSchema, cachedHistoryThreadSchema, cachedPeopleThreadSchema, cacheReconcileBody, archiveHubIdParam, archiveConversationParams, archiveListQuery, archiveMessageObservabilityParams, conversationIdParam, conversationHubQuery, 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, planKeySchema, billingStatusSchema, billingPlanTypeSchema, dataUsageCountersSchema, REKOR_ENTITLEMENT_CONTRACT_VERSION, entitlementProjectionSchema, rekorEntitlementRefreshMessageSchema, downloadBody, uploadQuery, SIGN_URL_MAX_EXPIRES_IN_SECONDS, signUrlBody, templateIdParam, listTemplatesQuery, deleteTemplateQuery, templateStatusQuery, createTemplateBody, updateTemplateBody, submitTemplateBody, testTemplateBody, CONTACT_ENVIRONMENTS, CONTACT_NAME_MAX, CONTACT_EMAIL_MAX, CONTACT_PHONE_INPUT_MAX, CONTACT_INSTAGRAM_SID_MAX, CONTACT_METADATA_MAX_BYTES, CONTACT_LABEL_MAX, CONTACT_LABELS_MAX, CONTACT_SCOPE_TAGS_MAX, CONTACT_PAGE_MAX, CONTACT_IMPORT_BATCH_MAX, CONTACT_SEARCH_MAX, CONTACT_LIST_NAME_MAX, CONTACT_LIST_NAME_REGEX, CONTACT_LIST_DESCRIPTION_MAX, CONTACT_LIST_FILTER_MAX, CONTACT_LIST_PINS_PER_REQUEST_MAX, SUPPRESSION_SCOPES, SUPPRESSION_ID_REGEX, contactName, contactPhone, contactEmail, contactInstagramSid, contactLabel, contactLabels, contactMetadata, scopeTagIds, contactVisibilitySchema, hasIdentity, IDENTITY_REQUIRED, contactBookOrgQuery, contactBookContactParam, contactBookListParam, contactBookHubParam, contactBookPageQuery, listContactBookContactsQuery, listHubContactBookContactsQuery, contactBookLinkCandidatesQuery, listContactBookListMembersQuery, contactRowFields, createContactBookContactBody, updateContactBookContactBody, contactImportRowSchema, importContactBookContactsBody, linkContactBookContactBody, listName, contactListFilterSchema, createContactBookListBody, updateContactBookListBody, updateContactBookListPinsBody, suppressionIdentitySchema, createContactBookSuppressionBody, contactBookSuppressionParam, listContactBookSuppressionsQuery, CONTACT_BOOK_EMAIL_UNSUBSCRIBE_PATH, contactBookEmailUnsubscribeTokenSchema, contactBookEmailUnsubscribeQuery, orgListReferenceSchema, hubListNameSchema, HUB_LIST_FILTER_REQUIRED, hubContactListFilterSchema, hubContactListIdParam, hubContactListHubQuery, description, createHubContactListBody, updateHubContactListBody, AUTOMATION_TRIGGER_TYPES, AUTOMATION_EVENT_TYPES, AUTOMATION_TARGET_TYPES, AUTOMATION_ACTION_TYPES, AUTOMATION_CHANNEL_TYPES, AUTOMATION_PURPOSES, AUTOMATION_NAME_MAX, AUTOMATION_DESCRIPTION_MAX, AUTOMATION_INSTRUCTIONS_MAX, AUTOMATION_TEXT_MAX, AUTOMATION_CRON_MAX, AUTOMATION_WEBHOOK_AUTHS, AUTOMATION_WEBHOOK_HEADERS, AUTOMATION_WEBHOOK_BODY_MAX_BYTES, AUTOMATION_WEBHOOK_HEADER_NAME_MAX, AUTOMATION_WEBHOOK_MOUNT, WEBHOOK_RESERVED_HEADERS, automationTriggerSchema, automationTargetSchema, automationActionSchema, automationGateSchema, automationName, automationDescription, automationIdParam, automationHubQuery, automationWebhookParams, AUTOMATION_RUNS_PAGE_MAX, listAutomationRunsQuery, createAutomationBody, updateAutomationBody, AUTOMATION_ALERT_CATEGORIES, AUTOMATION_BLOCKED_ALERT_CATEGORY, automationEventSubscriberParam, VERSION_PART, MOBILE_APP_VERSION_RE, mobileAppVersionSchema, MOBILE_PLATFORMS, mobilePlatformSchema, mobileVersionPolicyQuery, mobileVersionPolicySchema, mobileVersionPolicyResponse, adminOrgIdParam, adminOrgAdminIdParam, adminUserIdParam, PRICING_PLAN_ID_RE, adminPlanIdParam, adminOrganizationsQuery, adminUserSearchQuery, kanbanSlugMigrationQuery, adjustQuotaBody, updatePlanBody, addAdminUserBody, MAX_VOICE_CALL_MINUTE_OPS, voiceCallMinuteOps, AUTOMATION_GATE_EVALUATIONS_PER_OPERATION_BOUND, automationGateEvaluationsPerOperation, AUTOMATION_RUN_RETENTION_DAYS_MAX, automationRunRetentionDays, updatePlatformConfigBody, updateFreeOrgLimitBody, adminScopedTargetShape, adminScopedTargetBody, BRANCHING_ORPHAN_ENTITY_TYPES, BRANCHING_ORPHAN_MAX_TARGETS, adminRepairBranchingOrphansBody, adminRepairLegacyOrgGrantsBody, adminRepairCompedPlansBody, 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, META_ENTITY_ID_PATTERN, metaEntityId, whatsappCallbackBody, authMeResponse, wsTicketResponse, sessionCheckResponse, logoutResponse, magicCodeSendBody, magicCodeSendResponse, magicCodeVerifyBody, magicCodeVerifyResponse, passwordLoginBody, 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, MAX_NAME_LENGTH, MAX_VALUE_LENGTH, MAX_TAGS, MAX_TAG_LENGTH, MAX_SCOPE_HUBS, MAX_SCOPE_TAGS, vaultSecretScopeSchema, vaultCreateBody, vaultUpdateBody, MAX_NAME_LENGTH2, MAX_HUBS_PER_GRANT, MAX_HUB_TAGS_PER_GRANT, MAX_GRANTS, permissionEnum, grantScopeSchema, grantSchema, createTokenBody, tokenOrgIdParam, invitePreviewQuery, inviteRolePreviewResponse, inviteContactPreviewResponse, invitePreviewResponse, inviteUnsubscribeBody, 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, MAX_PROVISIONING_BODY_BYTES, dataProxyQuery, rekorAttestation, REQUIRED_REKOR_ATTESTATION_HEADERS, BASE_DESTRUCTION_MOUNT, BASE_DESTRUCTION_PREFIX, BASE_DESTRUCTION_CONFIRM_PATH, baseDestructionConfirmBody, BASE_DESTRUCTION_GRACE_MS, BASE_DESTRUCTION_CONFIRM_TTL_MS, BASE_DESTRUCTION_ORG_QUERY_PARAM, baseDestructionQuery, baseDestructionParam, baseDestructionInitiateBody, baseDestructionStatus, baseDestructionRequest, baseDestructionListResponse, baseDestructionInitiateResponse, baseDestructionConfirmResponse, baseDestructionCancelResponse, rekorBaseChangeMessageSchema, PEOPLE_CONTACT_PAGE_MAX, PEOPLE_CONTACT_PAGE_DEFAULT, PEOPLE_CONTACT_EMAIL_MAX_LENGTH, peopleUserIdSchema, peopleInviteEmailSchema, peopleContactInviteBody, peopleContactInviteIdParam, peopleContactUserIdParam, peopleContactBlockBody, peopleContactPageQuery, peopleOutgoingInviteSchema, peopleContactPersonSchema, peopleContactSchema, peopleIncomingInviteSchema, peopleBlockedUserSchema, PEOPLE_THREAD_MESSAGE_MAX_LENGTH, PEOPLE_THREAD_MESSAGES_PAGE_MAX, PEOPLE_THREAD_PAGE_MAX, PEOPLE_THREAD_PAGE_DEFAULT, PEOPLE_GROUP_NAME_MAX_LENGTH, PEOPLE_GROUP_AVATAR_URL_MAX_LENGTH, PEOPLE_THREAD_ATTACHMENT_MAX_BYTES, PEOPLE_THREAD_ATTACHMENT_NAME_MAX_LENGTH, PEOPLE_ATTACHMENT_STORAGE_PER_USER_BYTES, PEOPLE_THREAD_ATTACHMENT_MAX_MB, PEOPLE_THREAD_ATTACHMENT_URL_TTL_SECONDS, PEOPLE_THREAD_ATTACHMENT_URLS_MAX, peopleThreadIdParam, peopleThreadMessageIdParam, peopleThreadListQuery, peopleThreadMessagesQuery, peopleThreadAttachmentUploadSchema, peopleThreadSendBody, peopleThreadAttachmentUrlsBody, peopleThreadReadBody, peopleThreadSettingsBody, peopleGroupNameSchema, peopleGroupAvatarUrlSchema, peopleGroupCreateBody, peopleOrgDirectBody, peopleGroupUpdateBody, peopleGroupInviteBody, peopleOrgErasureBody, peopleGroupLeaveBody, peopleGroupInviteIdParam, peopleGroupIncomingInviteIdParam, peopleGroupMemberParam, peopleThreadKindSchema, peopleThreadMemberSchema, peopleThreadLastMessageSchema, peopleGroupRoleSchema, peopleGroupSummarySchema, peopleThreadSummarySchema, peopleThreadAttachmentSchema, peopleThreadMessageSchema, peopleGroupMemberSchema, peopleGroupSentInviteSchema, peopleGroupIncomingInviteSchema, PEOPLE_REPORT_DETAILS_MAX_LENGTH, peopleReportReasonSchema, reportDetailsSchema, reportFields, peopleReportBody, PEOPLE_MODERATION_NOTE_MAX_LENGTH, ADMIN_PEOPLE_REPORTS_PAGE_MAX, ADMIN_PEOPLE_REPORTS_PAGE_DEFAULT, peopleModerationActionSchema, moderationNoteSchema, adminPeopleReportListQuery, adminPeopleReportIdParam, adminPeopleMessageRemovalBody, adminPeopleSuspendBody, adminPeopleNoteBody, COMMUNITIES_PER_ORG_MAX, COMMUNITY_NAME_MAX_LENGTH, COMMUNITY_REGISTRY_CLOSED_REASON, COMMUNITY_JOIN_SOURCE_MAX_LENGTH, COMMUNITY_JOIN_FLOW_TOKEN_MAX_LENGTH, COMMUNITY_ROOM_NAME_MAX_LENGTH, COMMUNITY_MESSAGE_MAX_LENGTH, COMMUNITY_MESSAGES_PAGE_SIZE, COMMUNITY_ATTACHMENT_URLS_MAX, COMMUNITY_POST_TITLE_MAX_LENGTH, COMMUNITY_POST_SEARCH_MAX_LENGTH, COMMUNITY_RULES_MAX_LENGTH, COMMUNITY_SLOW_MODE_MAX_SECONDS, COMMUNITY_COURSES_LABEL_MAX_LENGTH, COMMUNITY_LIVE_TICKET_PREFIX, communityNameSchema, adminCreateCommunityBody, communityIdParam, communityJoinTokenSchema, communityJoinSourceSchema, communityJoinPreviewQuery, communityJoinBody, communityRoomKindSchema, communityRoomNameSchema, communityRoomIdParam, communityMessageIdParam, communityRoomCreateBody, communityRoomUpdateBody, communityMessagesQuery, communityMessageBodySchema, communityPostTitleSchema, communityAttachmentUploadSchema, communitySendBody, communityEditBody, communityPostIdParam, communityPostsQuery, communityAnswerBody, communityReadBody, communityAttachmentUrlsBody, communityPersonParam, communityOrgParam, communityPeopleQuery, communityCoursesLabelSchema, communitySettingsBody, communityBanBody, communityLockBody, communityPinBody, communityModLogQuery, communityReportsQuery, communityReportIdParam, communityLiveTicketSchema, communityLiveQuery, communityMuteBody, communityEmailUnsubscribeTokenSchema, COMMUNITY_EMAIL_UNSUBSCRIBE_PATH, communityEmailUnsubscribeQuery, COMMUNITY_COURSE_TITLE_MAX_LENGTH, COMMUNITY_COURSE_DESCRIPTION_MAX_LENGTH, COMMUNITY_LESSON_BODY_MAX_LENGTH, COMMUNITY_LESSON_LINKS_MAX, COMMUNITY_LESSON_URL_MAX_LENGTH, YOUTUBE_ID, YOUTUBE_HOSTS, YOUTU_BE, YOUTUBE_ID_PATH, communityCourseIdParam, communityCourseModuleIdParam, communityLessonIdParam, communityCourseTitleSchema, communityCourseDescriptionSchema, communityCoursePositionSchema, communityLessonVideoUrlSchema, communityLessonLinkSchema, communityLessonLinksSchema, communityLessonBodySchema, communityCourseCreateBody, communityCourseUpdateBody, communityModuleCreateBody, communityModuleUpdateBody, communityLessonCreateBody, communityLessonUpdateBody, COMMUNITY_LESSON_TREE_MAX_BYTES, COMMUNITY_LESSON_LINK_PROTOCOLS, LINK_SCHEME, adminSetGuideHubBody, GUIDE_HUB_INELIGIBLE_REASON;
9788
+ var init_chunk_FRU7E62M = __esm({
9789
+ "../../packages/core/dist/chunk-FRU7E62M.js"() {
9446
9790
  "use strict";
9447
9791
  init_chunk_VORPHGDT();
9448
9792
  init_chunk_POL7B3EM();
9449
- init_chunk_YEYIDIR6();
9450
- init_chunk_3NS3HULK();
9793
+ init_chunk_T2RKGBYS();
9451
9794
  init_chunk_MIWZOSPI();
9795
+ init_chunk_3NS3HULK();
9452
9796
  init_chunk_JWPRTSIB();
9797
+ init_chunk_T7KQKDET();
9453
9798
  init_zod();
9454
9799
  init_zod();
9455
9800
  init_zod();
@@ -9503,258 +9848,57 @@ var init_chunk_H4RTULPH = __esm({
9503
9848
  init_zod();
9504
9849
  init_zod();
9505
9850
  init_zod();
9506
- init_zod();
9507
- primaryRegionSchema = external_exports.enum([
9508
- "wnam",
9509
- "enam",
9510
- "sam",
9511
- "weur",
9512
- "eeur",
9513
- "apac",
9514
- "oc",
9515
- "afr",
9516
- "me"
9517
- ]);
9518
- placementSourceSchema = external_exports.enum([
9519
- "hub_config",
9520
- "org_config",
9521
- "parent_cascade",
9522
- "cf_colo",
9523
- "country",
9524
- "fallback"
9525
- ]);
9526
- orgIdParam = external_exports.object({
9527
- id: uuidSchema
9851
+ connectionIdParam = external_exports.object({ id: uuidSchema });
9852
+ connectorIdParam = external_exports.object({ id: uuidSchema });
9853
+ listConnectionsQuery = external_exports.object({ hub_id: uuidSchema });
9854
+ deleteConnectionQuery = external_exports.object({ hub_id: uuidSchema });
9855
+ addConnectionBody = external_exports.object({
9856
+ hub_id: uuidSchema,
9857
+ connector_id: uuidSchema,
9858
+ authentication_type: external_exports.string().optional(),
9859
+ inbound_mode: external_exports.enum(["wayai", "resend"]).optional(),
9860
+ inbound_address: external_exports.string().email().optional(),
9861
+ // Opt out of copying this connection's credentials into production on publish/sync.
9862
+ // Defaults to true at the DB layer.
9863
+ sync_credentials_to_production: external_exports.boolean().optional()
9864
+ }).passthrough().superRefine((data, ctx) => {
9865
+ if (data.inbound_mode === "resend" && !data.inbound_address) {
9866
+ ctx.addIssue({
9867
+ code: external_exports.ZodIssueCode.custom,
9868
+ message: "Receiving email address is required when using Resend inbound mode",
9869
+ path: ["inbound_address"]
9870
+ });
9871
+ }
9528
9872
  });
9529
- orgAdminIdParam = external_exports.object({
9530
- id: uuidSchema,
9531
- adminId: external_exports.string().min(1)
9873
+ editConnectionBody = external_exports.object({
9874
+ hub_id: uuidSchema,
9875
+ sync_credentials_to_production: external_exports.boolean().optional()
9876
+ }).passthrough();
9877
+ PRODUCTION_DIRECT_FIELDS = ["username", "api_key", "access_token", "password", "refresh_token", "webhook_secret_token", "webhook_signing_secret"];
9878
+ setProductionCredentialBody = external_exports.object({
9879
+ hub_id: uuidSchema,
9880
+ organization_credential_id: external_exports.string().nullable().optional(),
9881
+ organization_credential_token_id: external_exports.string().nullable().optional(),
9882
+ username: external_exports.string().optional(),
9883
+ api_key: external_exports.string().optional(),
9884
+ access_token: external_exports.string().optional(),
9885
+ password: external_exports.string().optional(),
9886
+ refresh_token: external_exports.string().optional(),
9887
+ webhook_secret_token: external_exports.string().optional(),
9888
+ webhook_signing_secret: external_exports.string().optional()
9889
+ }).strict().superRefine((data, ctx) => {
9890
+ const hasOrgLink = !!data.organization_credential_id || !!data.organization_credential_token_id;
9891
+ const hasDirect = PRODUCTION_DIRECT_FIELDS.some((f) => data[f] != null);
9892
+ if (hasOrgLink && hasDirect) {
9893
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "Provide either an organization credential link or direct credential fields, not both" });
9894
+ }
9895
+ if (!hasOrgLink && !hasDirect) {
9896
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "A credential is required: link an organization credential or provide a credential field" });
9897
+ }
9532
9898
  });
9533
- createOrganizationBody = external_exports.object({
9534
- organization_name: external_exports.string().min(1, "organization_name is required"),
9535
- // Write-once at creation; updateOrganizationBody does not accept this.
9536
- primary_region: primaryRegionSchema.optional()
9537
- });
9538
- updateOrganizationBody = external_exports.object({
9539
- organization_name: external_exports.string().min(1).optional(),
9540
- organization_avatar_url: external_exports.string().url().nullable().optional(),
9541
- timezone: external_exports.string().optional(),
9542
- business_hours: external_exports.unknown().optional()
9543
- }).passthrough();
9544
- addOrgAdminBody = external_exports.object({
9545
- user_email: external_exports.string().email("valid email is required")
9546
- });
9547
- hubIdParam = external_exports.object({ id: uuidSchema });
9548
- hubAdminIdParam = external_exports.object({ id: uuidSchema, adminId: uuidSchema });
9549
- hubUserIdParam = external_exports.object({ id: uuidSchema, hubUserId: uuidSchema });
9550
- hubIdentityIdParam = external_exports.object({ id: uuidSchema, identityId: uuidSchema });
9551
- hubTeamIdParam = external_exports.object({ id: uuidSchema, teamId: uuidSchema });
9552
- hubTeamUserDeleteParam = external_exports.object({ id: uuidSchema, teamUserId: uuidSchema });
9553
- hubSchemaQuery = external_exports.object({ hub_id: uuidSchema });
9554
- PREVIEW_LABEL_MAX_LENGTH = 60;
9555
- MAX_ENDED_INDEX_RETENTION_DAYS = 730;
9556
- MAX_EVAL_RETENTION_DAYS = 3650;
9557
- previewLabelField = external_exports.string().max(PREVIEW_LABEL_MAX_LENGTH).optional().nullable().transform((v) => {
9558
- if (v == null) return null;
9559
- const trimmed = v.trim();
9560
- return trimmed || null;
9561
- });
9562
- hubTagsField = external_exports.array(external_exports.string()).nullable().optional();
9563
- createHubBody = external_exports.object({
9564
- organization_id: uuidSchema,
9565
- hub_name: external_exports.string().min(1, "hub_name is required"),
9566
- hub_description: external_exports.string().optional(),
9567
- kanban_statuses: kanbanStatusesArraySchema.nullable().optional(),
9568
- lanes: lanesArraySchema.nullable().optional(),
9569
- // Optional preview label for the first preview. Server-owned thereafter
9570
- // (change via `wayai relabel` / replicate); the push diff never writes it.
9571
- preview_label: previewLabelField,
9572
- // Write-once at creation; updateHubBody does not accept this.
9573
- primary_region: primaryRegionSchema.optional(),
9574
- // Org tag ids. Ids that name none of the org's tags are dropped; a hub created with
9575
- // any is a tag change (`hubTagChangeRefusalSchema`).
9576
- tags: hubTagsField
9577
- }).passthrough().superRefine(refineLaneReferences);
9578
- updateHubBody = external_exports.object({
9579
- support_model: external_exports.enum(["conversation", "account"]).optional(),
9580
- unassigned_policy: external_exports.enum(["default_team", "auto_assign_random", "auto_assign_round_robin", "pull_queue"]).optional(),
9581
- default_hub_team_id: uuidSchema.nullable().optional(),
9582
- kanban_statuses: kanbanStatusesArraySchema.nullable().optional(),
9583
- lanes: lanesArraySchema.nullable().optional(),
9584
- // summarization_threshold_tokens relocated to the summarizer AGENT (PR4) — validated/
9585
- // persisted via the agent path (.passthrough() agent body → HubDO column), not here.
9586
- auto_close_inactive_days: external_exports.number().int().min(1).max(180).optional(),
9587
- // Per-hub ConversationDO retention window (days) — keeps an ended conversation's DO
9588
- // alive for post-hoc annotation. Default 7, max 30 — the floor of the retention
9589
- // chain (≤ ended_index_retention_days ≤ effective storage retention).
9590
- conversation_retention_days: external_exports.number().int().min(1).max(30).optional(),
9591
- // Per-hub ended-conversation index retention window (days) — how long the warm
9592
- // "Ended" tab + chat-hub continuous history serve a closed conversation before
9593
- // the cleanup cron reaps its index row. Absent → DEFAULT_ENDED_INDEX_RETENTION_DAYS
9594
- // (365). Re-clamped to the effective storage retention at reap time.
9595
- ended_index_retention_days: external_exports.number().int().min(1).max(MAX_ENDED_INDEX_RETENTION_DAYS).optional(),
9596
- // Per-hub eval-session retention window (days). null CLEARS the override (back to
9597
- // the platform default); 0 disables retention for this hub (keep sessions forever).
9598
- // Nullable — unlike the fields above, "unset" is a meaningful, settable state.
9599
- eval_retention_days: external_exports.number().int().min(0).max(MAX_EVAL_RETENTION_DAYS).nullable().optional(),
9600
- // Channel contact access control. Enum-validated explicitly (not via passthrough)
9601
- // so `language`/`access_approval_role` can't reach the DB with an invalid value.
9602
- language: external_exports.enum(["en", "pt", "es"]).optional(),
9603
- access_request_message: external_exports.string().max(1e3).nullable().optional(),
9604
- access_approval_role: external_exports.enum(["admin", "team"]).optional(),
9605
- // AI-failure escalation. When an LLM provider outage persists past this many
9606
- // minutes the conversation escalates to the team; null → code default. The two
9607
- // message fields override the localized (hub.language) delay / hand-off notices;
9608
- // null → localized default. Bounds validated here so out-of-range never persists.
9609
- ai_failure_escalation_minutes: external_exports.number().int().min(1).max(60).nullable().optional(),
9610
- ai_delay_message: external_exports.string().max(1e3).nullable().optional(),
9611
- ai_handoff_message: external_exports.string().max(1e3).nullable().optional(),
9612
- // Native-completion fallback connection for a degraded harness turn (PR 2.10b).
9613
- // A NATIVE LLM (Agent) connection id on this hub; validated at set-time on the REST
9614
- // PATCH (setup/hubs.ts rejects a non-existent / non-Agent / harness id) and re-checked
9615
- // at fallback time in the turn seam (a stale/missing id simply no-ops). Nullable to clear it.
9616
- fallback_connection_id: uuidSchema.nullable().optional(),
9617
- // Rekor API connection used to reset/clear eval seed fixtures (gh #3090). A
9618
- // connection id on this hub (a REST API (custom tool) connection whose base_url
9619
- // is the Rekor API origin + a bearer/api_key `write:seeds` token). Validated at
9620
- // set-time on the REST PATCH (setup/hubs.ts). Nullable to clear it.
9621
- seed_connection_id: uuidSchema.nullable().optional(),
9622
- // Org tag ids, replacing the hub's; null clears them. A change is refused to anyone
9623
- // but an org admin (`hubTagChangeRefusalSchema`).
9624
- tags: hubTagsField
9625
- }).passthrough().superRefine(refineLaneReferences);
9626
- HUB_TAG_CHANGE_REFUSED = "hub_tag_change_requires_org_admin";
9627
- hubTagChangeRefusalSchema = external_exports.object({
9628
- reason: external_exports.literal(HUB_TAG_CHANGE_REFUSED),
9629
- operation: external_exports.enum(["update", "publish"]),
9630
- hub_id: external_exports.string(),
9631
- tags_added: external_exports.array(external_exports.string()),
9632
- tags_removed: external_exports.array(external_exports.string())
9633
- });
9634
- addHubAdminBody = external_exports.object({
9635
- user_email: external_exports.string().email("valid email is required")
9636
- });
9637
- addHubIdentityAuthorizationBody = external_exports.object({
9638
- identity_value: external_exports.string().min(1),
9639
- identity_type: external_exports.string().min(1),
9640
- channel_type: external_exports.string().min(1)
9641
- });
9642
- contactDecisionBody = external_exports.object({
9643
- contact_access_id: uuidSchema.optional(),
9644
- identity_type: external_exports.string().min(1).optional(),
9645
- identity_value: external_exports.string().min(1).optional(),
9646
- channel_type: external_exports.string().min(1).optional(),
9647
- channel_id: uuidSchema.optional(),
9648
- connection_id: uuidSchema.optional(),
9649
- user_id: uuidSchema.optional(),
9650
- sender_display_name: external_exports.string().max(200).optional()
9651
- });
9652
- approveContactBody = contactDecisionBody.extend({
9653
- user_name: external_exports.string().min(1).max(120).optional()
9654
- });
9655
- listContactAccessQuery = external_exports.object({
9656
- status: external_exports.enum(["pending", "blocked"]).optional()
9657
- });
9658
- createHubTeamBody = external_exports.object({
9659
- team_name: external_exports.string().min(1, "team_name is required")
9660
- }).strict();
9661
- updateHubTeamBody = external_exports.object({
9662
- team_name: external_exports.string().min(1).optional(),
9663
- conversation_display_only_if_claimed: external_exports.boolean().optional(),
9664
- team_access_rule: external_exports.string().optional(),
9665
- initial_team: external_exports.boolean().optional()
9666
- }).strict();
9667
- addHubTeamUserBody = external_exports.object({
9668
- user_email: external_exports.string().email("valid email is required")
9669
- });
9670
- reassignHubUserBody = external_exports.object({
9671
- hub_team_id: uuidSchema.nullable()
9672
- });
9673
- replicatePreviewBody = external_exports.object({
9674
- preview_label: previewLabelField
9675
- });
9676
- HUB_DIFF_SECTION_SET = {
9677
- agents: true,
9678
- agent_parameters: true,
9679
- connections: true,
9680
- mcp_tools: true,
9681
- tools: true,
9682
- channels: true,
9683
- states: true,
9684
- teams: true,
9685
- resources: true,
9686
- resource_folders: true,
9687
- resource_files: true,
9688
- agent_resources: true,
9689
- message_templates: true,
9690
- contact_lists: true,
9691
- automations: true,
9692
- evals: true
9693
- };
9694
- HUB_DIFF_SECTIONS = Object.keys(HUB_DIFF_SECTION_SET);
9695
- updateChannelTestIdentitiesBody = external_exports.object({
9696
- test_identities: external_exports.array(external_exports.string().max(320)).max(1e3)
9697
- });
9698
- claimCodeChannelParam = external_exports.object({
9699
- id: uuidSchema,
9700
- channelId: uuidSchema
9701
- });
9702
- claimCodeDeleteParam = external_exports.object({
9703
- id: uuidSchema,
9704
- channelId: uuidSchema,
9705
- code: external_exports.string().regex(/^[A-Za-z0-9]{6}$/, "Invalid claim code format").transform((s) => s.toUpperCase())
9706
- });
9707
- connectionIdParam = external_exports.object({ id: uuidSchema });
9708
- connectorIdParam = external_exports.object({ id: uuidSchema });
9709
- listConnectionsQuery = external_exports.object({ hub_id: uuidSchema });
9710
- deleteConnectionQuery = external_exports.object({ hub_id: uuidSchema });
9711
- addConnectionBody = external_exports.object({
9712
- hub_id: uuidSchema,
9713
- connector_id: uuidSchema,
9714
- authentication_type: external_exports.string().optional(),
9715
- inbound_mode: external_exports.enum(["wayai", "resend"]).optional(),
9716
- inbound_address: external_exports.string().email().optional(),
9717
- // Opt out of copying this connection's credentials into production on publish/sync.
9718
- // Defaults to true at the DB layer.
9719
- sync_credentials_to_production: external_exports.boolean().optional()
9720
- }).passthrough().superRefine((data, ctx) => {
9721
- if (data.inbound_mode === "resend" && !data.inbound_address) {
9722
- ctx.addIssue({
9723
- code: external_exports.ZodIssueCode.custom,
9724
- message: "Receiving email address is required when using Resend inbound mode",
9725
- path: ["inbound_address"]
9726
- });
9727
- }
9728
- });
9729
- editConnectionBody = external_exports.object({
9730
- hub_id: uuidSchema,
9731
- sync_credentials_to_production: external_exports.boolean().optional()
9732
- }).passthrough();
9733
- PRODUCTION_DIRECT_FIELDS = ["username", "api_key", "access_token", "password", "refresh_token", "webhook_secret_token", "webhook_signing_secret"];
9734
- setProductionCredentialBody = external_exports.object({
9735
- hub_id: uuidSchema,
9736
- organization_credential_id: external_exports.string().nullable().optional(),
9737
- organization_credential_token_id: external_exports.string().nullable().optional(),
9738
- username: external_exports.string().optional(),
9739
- api_key: external_exports.string().optional(),
9740
- access_token: external_exports.string().optional(),
9741
- password: external_exports.string().optional(),
9742
- refresh_token: external_exports.string().optional(),
9743
- webhook_secret_token: external_exports.string().optional(),
9744
- webhook_signing_secret: external_exports.string().optional()
9745
- }).strict().superRefine((data, ctx) => {
9746
- const hasOrgLink = !!data.organization_credential_id || !!data.organization_credential_token_id;
9747
- const hasDirect = PRODUCTION_DIRECT_FIELDS.some((f) => data[f] != null);
9748
- if (hasOrgLink && hasDirect) {
9749
- ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "Provide either an organization credential link or direct credential fields, not both" });
9750
- }
9751
- if (!hasOrgLink && !hasDirect) {
9752
- ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "A credential is required: link an organization credential or provide a credential field" });
9753
- }
9754
- });
9755
- registerWhatsappQuery = external_exports.object({ hub_id: uuidSchema });
9756
- registerWhatsappBody = external_exports.object({
9757
- pin: external_exports.string().optional()
9899
+ registerWhatsappQuery = external_exports.object({ hub_id: uuidSchema });
9900
+ registerWhatsappBody = external_exports.object({
9901
+ pin: external_exports.string().optional()
9758
9902
  });
9759
9903
  retryProvisioningQuery = external_exports.object({ hub_id: uuidSchema });
9760
9904
  resendDomainStatusQuery = external_exports.object({ hub_id: uuidSchema });
@@ -11443,6 +11587,7 @@ var init_chunk_H4RTULPH = __esm({
11443
11587
  filter: hubContactListFilterSchema.optional()
11444
11588
  }).strict();
11445
11589
  AUTOMATION_TRIGGER_TYPES = ["schedule", "event", "webhook"];
11590
+ AUTOMATION_EVENT_TYPES = ["conversation.flagged", "conversation.closed"];
11446
11591
  AUTOMATION_TARGET_TYPES = ["none", "contact_list"];
11447
11592
  AUTOMATION_ACTION_TYPES = ["run_agent", "send_message"];
11448
11593
  AUTOMATION_CHANNEL_TYPES = ["whatsapp", "instagram", "email", "app"];
@@ -11452,10 +11597,36 @@ var init_chunk_H4RTULPH = __esm({
11452
11597
  AUTOMATION_INSTRUCTIONS_MAX = 1e4;
11453
11598
  AUTOMATION_TEXT_MAX = 4096;
11454
11599
  AUTOMATION_CRON_MAX = 512;
11600
+ AUTOMATION_WEBHOOK_AUTHS = ["hmac", "static_header"];
11601
+ AUTOMATION_WEBHOOK_HEADERS = {
11602
+ signature: "X-Data-Signature",
11603
+ timestamp: "X-Data-Timestamp",
11604
+ id: "X-Data-Id",
11605
+ idempotencyKey: "X-Data-Idempotency-Key"
11606
+ };
11607
+ AUTOMATION_WEBHOOK_BODY_MAX_BYTES = 64 * 1024;
11608
+ AUTOMATION_WEBHOOK_HEADER_NAME_MAX = 64;
11609
+ AUTOMATION_WEBHOOK_MOUNT = "/webhooks/automations";
11610
+ WEBHOOK_RESERVED_HEADERS = /* @__PURE__ */ new Set([
11611
+ "host",
11612
+ "connection",
11613
+ "cookie",
11614
+ "transfer-encoding",
11615
+ "forwarded",
11616
+ "via",
11617
+ "true-client-ip",
11618
+ "x-real-ip",
11619
+ ...Object.values(AUTOMATION_WEBHOOK_HEADERS).map((h) => h.toLowerCase())
11620
+ ]);
11455
11621
  automationTriggerSchema = external_exports.object({
11456
11622
  type: external_exports.enum(AUTOMATION_TRIGGER_TYPES),
11457
11623
  cron: external_exports.string().trim().min(1).max(AUTOMATION_CRON_MAX).optional(),
11458
- timezone: external_exports.string().trim().min(1).optional()
11624
+ timezone: external_exports.string().trim().min(1).optional(),
11625
+ event: external_exports.enum(AUTOMATION_EVENT_TYPES).optional(),
11626
+ /** The production hub whose events an `event` trigger listens to; absent: this hub's own. */
11627
+ source_hub: external_exports.string().uuid().optional(),
11628
+ auth: external_exports.enum(AUTOMATION_WEBHOOK_AUTHS).optional(),
11629
+ header: external_exports.string().trim().min(1).max(AUTOMATION_WEBHOOK_HEADER_NAME_MAX).optional()
11459
11630
  }).strict();
11460
11631
  automationTargetSchema = external_exports.object({
11461
11632
  type: external_exports.enum(AUTOMATION_TARGET_TYPES),
@@ -11471,6 +11642,9 @@ var init_chunk_H4RTULPH = __esm({
11471
11642
  agent_id: external_exports.string().uuid().nullable().optional(),
11472
11643
  instructions: external_exports.string().max(AUTOMATION_INSTRUCTIONS_MAX).nullable().optional()
11473
11644
  }).strict();
11645
+ automationGateSchema = external_exports.object({
11646
+ monitor: external_exports.string().trim().min(1).max(MONITOR_GATE_AGENT_NAME_MAX)
11647
+ }).strict();
11474
11648
  automationName = external_exports.string().trim().min(1).max(AUTOMATION_NAME_MAX);
11475
11649
  automationDescription = external_exports.string().max(AUTOMATION_DESCRIPTION_MAX).nullable().optional();
11476
11650
  automationIdParam = external_exports.object({
@@ -11479,6 +11653,10 @@ var init_chunk_H4RTULPH = __esm({
11479
11653
  automationHubQuery = external_exports.object({
11480
11654
  hub_id: external_exports.string().uuid()
11481
11655
  });
11656
+ automationWebhookParams = external_exports.object({
11657
+ hub_id: external_exports.string().uuid(),
11658
+ automation_id: external_exports.string().uuid()
11659
+ });
11482
11660
  AUTOMATION_RUNS_PAGE_MAX = 50;
11483
11661
  listAutomationRunsQuery = external_exports.object({
11484
11662
  hub_id: external_exports.string().uuid(),
@@ -11493,7 +11671,9 @@ var init_chunk_H4RTULPH = __esm({
11493
11671
  purpose: external_exports.enum(AUTOMATION_PURPOSES).optional(),
11494
11672
  trigger: automationTriggerSchema,
11495
11673
  target: automationTargetSchema,
11496
- action: automationActionSchema
11674
+ action: automationActionSchema,
11675
+ /** Absent or null: every fire runs. */
11676
+ gate: automationGateSchema.nullable().optional()
11497
11677
  }).strict();
11498
11678
  updateAutomationBody = external_exports.object({
11499
11679
  name: automationName.optional(),
@@ -11501,13 +11681,18 @@ var init_chunk_H4RTULPH = __esm({
11501
11681
  purpose: external_exports.enum(AUTOMATION_PURPOSES).optional(),
11502
11682
  trigger: automationTriggerSchema.optional(),
11503
11683
  target: automationTargetSchema.optional(),
11504
- action: automationActionSchema.optional()
11684
+ action: automationActionSchema.optional(),
11685
+ /** Replaced when present; null removes the gate. */
11686
+ gate: automationGateSchema.nullable().optional()
11505
11687
  }).strict();
11506
11688
  AUTOMATION_ALERT_CATEGORIES = {
11507
11689
  list_not_found: "automation_list_not_found",
11508
11690
  list_over_cap: "automation_list_over_cap"
11509
11691
  };
11510
11692
  AUTOMATION_BLOCKED_ALERT_CATEGORY = "automation_blocked";
11693
+ automationEventSubscriberParam = external_exports.object({
11694
+ subscriber_hub_id: external_exports.string().uuid()
11695
+ });
11511
11696
  VERSION_PART = "(0|[1-9][0-9]{0,5})";
11512
11697
  MOBILE_APP_VERSION_RE = new RegExp(`^${VERSION_PART}\\.${VERSION_PART}\\.${VERSION_PART}$`);
11513
11698
  mobileAppVersionSchema = external_exports.string().regex(MOBILE_APP_VERSION_RE, "must be a MAJOR.MINOR.PATCH version, e.g. 1.0.0");
@@ -11608,8 +11793,10 @@ var init_chunk_H4RTULPH = __esm({
11608
11793
  });
11609
11794
  MAX_VOICE_CALL_MINUTE_OPS = 60;
11610
11795
  voiceCallMinuteOps = external_exports.number().int().min(0).max(MAX_VOICE_CALL_MINUTE_OPS);
11611
- AUTOMATION_LIST_MAX_CONTACTS_BOUND = 1e4;
11612
- automationListMaxContacts = external_exports.number().int().min(1).max(AUTOMATION_LIST_MAX_CONTACTS_BOUND);
11796
+ AUTOMATION_GATE_EVALUATIONS_PER_OPERATION_BOUND = 1e3;
11797
+ automationGateEvaluationsPerOperation = external_exports.number().int().min(1).max(AUTOMATION_GATE_EVALUATIONS_PER_OPERATION_BOUND);
11798
+ AUTOMATION_RUN_RETENTION_DAYS_MAX = 3650;
11799
+ automationRunRetentionDays = external_exports.number().int().min(1).max(AUTOMATION_RUN_RETENTION_DAYS_MAX);
11613
11800
  updatePlatformConfigBody = external_exports.object({
11614
11801
  free_plan_max_free_orgs_per_user: external_exports.number().int().min(0).optional(),
11615
11802
  /** Kill switch for admin debug-read endpoints. 0 = off, 1 = on. */
@@ -11649,8 +11836,10 @@ var init_chunk_H4RTULPH = __esm({
11649
11836
  * `wayai admin communities enable|disable` flips this.
11650
11837
  */
11651
11838
  communities_enabled: external_exports.number().int().min(0).max(1).optional(),
11652
- /** The most contacts one automation fire reaches (`automationListMaxContacts`). */
11653
- automation_list_max_contacts: automationListMaxContacts.optional(),
11839
+ /** How many automation gate evaluations bill one operation (`automationGateEvaluationsPerOperation`). */
11840
+ automation_gate_evaluations_per_operation: automationGateEvaluationsPerOperation.optional(),
11841
+ /** How many days a hub keeps an automation's runs (`automationRunRetentionDays`). */
11842
+ automation_run_retention_days: automationRunRetentionDays.optional(),
11654
11843
  /**
11655
11844
  * The mobile app version policy (`MOBILE_VERSION_POLICY_COLUMNS`), per platform: an install
11656
11845
  * below the minimum is blocked until it updates from the store; one below the recommended
@@ -11801,7 +11990,7 @@ var init_chunk_H4RTULPH = __esm({
11801
11990
  /** Filter to specific DO types (default: all) */
11802
11991
  do_types: external_exports.array(pitrDoNamespace).optional()
11803
11992
  });
11804
- dataExplorerDebugDoType = external_exports.enum(["hub", "org", "conversation", "user", "platform", "thread", "community", "contact_book"]);
11993
+ dataExplorerDebugDoType = external_exports.enum(["hub", "org", "conversation", "user", "platform", "thread", "community", "contact_book", "batch"]);
11805
11994
  DEBUG_READ_MAX_LIMIT = 100;
11806
11995
  DEBUG_READ_DEFAULT_LIMIT = 20;
11807
11996
  DEBUG_DO_HEX_PREFIX = "hex:";
@@ -12758,13 +12947,18 @@ var init_chunk_H4RTULPH = __esm({
12758
12947
  COMMUNITY_LESSON_TREE_MAX_BYTES = 512 * 1024;
12759
12948
  COMMUNITY_LESSON_LINK_PROTOCOLS = ["http", "https", "mailto"];
12760
12949
  LINK_SCHEME = new RegExp(`^(${COMMUNITY_LESSON_LINK_PROTOCOLS.join("|")}):`, "i");
12950
+ adminSetGuideHubBody = external_exports.object({
12951
+ hub_id: uuidSchema,
12952
+ dry_run: external_exports.boolean().optional()
12953
+ }).strict();
12954
+ GUIDE_HUB_INELIGIBLE_REASON = "guide_hub_ineligible";
12761
12955
  }
12762
12956
  });
12763
12957
 
12764
- // ../../packages/core/dist/chunk-R5WRRHCL.js
12958
+ // ../../packages/core/dist/chunk-LKBSHANA.js
12765
12959
  var DESKTOP_SHELL_VERSION_RE, DESKTOP_PLATFORMS, DESKTOP_FLAVORS, desktopShellInfoSchema, DESKTOP_PRESENCE_STATES, desktopPresenceSchema, desktopUpdateSchema, DESKTOP_SIGN_IN_URL_MAX_LENGTH, DESKTOP_APP_PATH_MAX_LENGTH, desktopAppPathSchema, DESKTOP_NOTIFICATION_KINDS, DESKTOP_NOTIFICATION_TITLE_MAX_LENGTH, DESKTOP_NOTIFICATION_BODY_MAX_LENGTH, notificationTitleSchema, notificationBodySchema, desktopNotificationSchema, DESKTOP_BADGE_MAX_COUNT, DESKTOP_BADGE_LABEL_MAX_LENGTH, desktopBadgeSchema, desktopNavigateSchema, desktopSettingsSchema, desktopSettingsChangeSchema, desktopBridgeArgsSchemas;
12766
- var init_chunk_R5WRRHCL = __esm({
12767
- "../../packages/core/dist/chunk-R5WRRHCL.js"() {
12960
+ var init_chunk_LKBSHANA = __esm({
12961
+ "../../packages/core/dist/chunk-LKBSHANA.js"() {
12768
12962
  "use strict";
12769
12963
  init_zod();
12770
12964
  DESKTOP_SHELL_VERSION_RE = /^(0|[1-9]\d{0,5})\.(0|[1-9]\d{0,5})\.(0|[1-9]\d{0,5})(-[0-9A-Za-z.-]{1,32})?$/;
@@ -12856,27 +13050,232 @@ var init_chunk_R5WRRHCL = __esm({
12856
13050
  }
12857
13051
  });
12858
13052
 
12859
- // ../../packages/core/dist/contracts/index.js
12860
- var init_contracts = __esm({
12861
- "../../packages/core/dist/contracts/index.js"() {
12862
- "use strict";
12863
- init_chunk_H4RTULPH();
12864
- init_chunk_VORPHGDT();
12865
- init_chunk_POL7B3EM();
12866
- init_chunk_YEYIDIR6();
12867
- init_chunk_SNA2DXAC();
12868
- init_chunk_R5WRRHCL();
12869
- init_chunk_IBL7FANV();
12870
- init_chunk_C2UEA2KW();
12871
- init_chunk_3NS3HULK();
12872
- init_chunk_MIWZOSPI();
12873
- init_chunk_JWPRTSIB();
12874
- init_chunk_T7KQKDET();
12875
- init_chunk_L5F7ZOUJ();
12876
- init_chunk_2ISUBJG7();
13053
+ // ../../packages/core/dist/chunk-R7VSUKKX.js
13054
+ function isPublicIdentifier(value) {
13055
+ return UUID_RE.test(value) || HEX_RE.test(value) || WORKOS_ID_RE.test(value) || TRACE_HEADER_RE.test(value);
13056
+ }
13057
+ function redactTokenShapes(input) {
13058
+ return input.replace(TOKEN_RE, REDACTED).replace(PROVIDER_TOKEN_RE, `$1${REDACTED}`).replace(JSON_CREDENTIAL_RE, `$1"${REDACTED}"`).replace(QUERY_CREDENTIAL_RE, `$1${REDACTED}`);
13059
+ }
13060
+ function redactSecrets(value) {
13061
+ if (isPublicIdentifier(value)) {
13062
+ return value;
12877
13063
  }
12878
- });
12879
-
13064
+ if (OPAQUE_SECRET_RE.test(value)) {
13065
+ return REDACTED;
13066
+ }
13067
+ if (BASE64_SECRET_RE.test(value) && BASE64_MARKER_RE.test(value)) {
13068
+ return REDACTED;
13069
+ }
13070
+ return redactTokenShapes(value);
13071
+ }
13072
+ var UUID_RE, HEX_RE, WORKOS_ID_RE, TRACE_HEADER_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;
13073
+ var init_chunk_R7VSUKKX = __esm({
13074
+ "../../packages/core/dist/chunk-R7VSUKKX.js"() {
13075
+ "use strict";
13076
+ UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
13077
+ HEX_RE = /^[0-9a-f]{16,}$/;
13078
+ WORKOS_ID_RE = /^(?:user|org)_[0-9A-HJKMNP-TV-Z]{26}$/;
13079
+ TRACE_HEADER_RE = /^(?:[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-[0-9a-f]{2}|[0-9a-f]{32}-[0-9a-f]{16}(?:-[01])?)$/;
13080
+ OPAQUE_SECRET_RE = /^[A-Za-z0-9_-]{21,}$/;
13081
+ BASE64_SECRET_RE = /^[A-Za-z0-9+/]{20,}={0,2}$/;
13082
+ BASE64_MARKER_RE = /[+=]/;
13083
+ TOKEN_RE = new RegExp(
13084
+ [
13085
+ // WayAI API tokens and WebSocket tickets.
13086
+ "(?:way|wst)_[A-Za-z0-9._-]{8,}",
13087
+ // Authorization header values, including base64 Basic credentials.
13088
+ "(?:Bearer|Basic)\\s+[A-Za-z0-9._~+/=-]{8,}",
13089
+ // JWTs — WorkOS session/access tokens. `eyJ` is base64 for `{"`.
13090
+ "eyJ[A-Za-z0-9._-]{10,}",
13091
+ // Stripe secret/publishable/restricted keys and webhook signing secrets.
13092
+ "(?:sk|pk|rk)_(?:live|test)_[A-Za-z0-9]{8,}",
13093
+ "whsec_[A-Za-z0-9]{8,}",
13094
+ // Telegram bot tokens as the Bot API takes them, in the URL path: `/bot<id>:<secret>/`.
13095
+ "bot[0-9]{5,}:[A-Za-z0-9_-]{30,}"
13096
+ // NOTE: LLM provider keys are NOT here — they need a delimiter-preserving
13097
+ // boundary, so they live in PROVIDER_TOKEN_RE below.
13098
+ ].join("|"),
13099
+ "g"
13100
+ );
13101
+ SENSITIVE_FIELDS = [
13102
+ "password",
13103
+ "token",
13104
+ "secret",
13105
+ "api_key",
13106
+ "apikey",
13107
+ "api-key",
13108
+ "authorization",
13109
+ "auth",
13110
+ "credential",
13111
+ "private_key",
13112
+ "privatekey",
13113
+ "access_token",
13114
+ "refresh_token",
13115
+ "session_id",
13116
+ "sessionid",
13117
+ "cookie",
13118
+ "jwt"
13119
+ ];
13120
+ SENSITIVE_KEY_ALTERNATION = SENSITIVE_FIELDS.map(
13121
+ (field) => field.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
13122
+ ).join("|");
13123
+ SENSITIVE_KEY_PATTERN = `[A-Za-z0-9_.-]*(?:${SENSITIVE_KEY_ALTERNATION})[A-Za-z0-9_.-]*`;
13124
+ JSON_CREDENTIAL_RE = new RegExp(
13125
+ `("${SENSITIVE_KEY_PATTERN}"\\s*:\\s*)"(?:[^"\\\\]|\\\\.)*"`,
13126
+ "gi"
13127
+ );
13128
+ QUERY_CREDENTIAL_RE = new RegExp(
13129
+ `((?:^|[?&#;\\s])${SENSITIVE_KEY_PATTERN}=)[^&;\\s"']+`,
13130
+ "gi"
13131
+ );
13132
+ REDACTED = "[REDACTED]";
13133
+ PROVIDER_TOKEN_RE = new RegExp(
13134
+ "(^|[^A-Za-z0-9])(?:" + [
13135
+ "sk-[A-Za-z0-9_-]{16,}",
13136
+ "AIza[A-Za-z0-9_-]{16,}",
13137
+ "xai-[A-Za-z0-9_-]{16,}"
13138
+ ].join("|") + ")",
13139
+ "g"
13140
+ );
13141
+ }
13142
+ });
13143
+
13144
+ // ../../packages/core/dist/chunk-BPDC67ML.js
13145
+ var 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;
13146
+ var init_chunk_BPDC67ML = __esm({
13147
+ "../../packages/core/dist/chunk-BPDC67ML.js"() {
13148
+ "use strict";
13149
+ init_chunk_R7VSUKKX();
13150
+ APP_ERROR_BRAND = /* @__PURE__ */ Symbol.for("wayai.AppError");
13151
+ AppError = class extends Error {
13152
+ constructor(message, code, statusCode = 500, details) {
13153
+ super(message);
13154
+ this.code = code;
13155
+ this.statusCode = statusCode;
13156
+ this.details = details;
13157
+ this.name = "AppError";
13158
+ }
13159
+ [APP_ERROR_BRAND] = true;
13160
+ toJSON() {
13161
+ return {
13162
+ error: this.code,
13163
+ message: this.message,
13164
+ ...this.details && { details: this.details }
13165
+ };
13166
+ }
13167
+ };
13168
+ LLM_RATE_LIMIT_BRAND = /* @__PURE__ */ Symbol.for("wayai.LlmRateLimitError");
13169
+ LlmRateLimitError = class extends Error {
13170
+ constructor(provider, retryAfterMs) {
13171
+ super(`${provider} rate limited; retry after ${retryAfterMs}ms`);
13172
+ this.provider = provider;
13173
+ this.retryAfterMs = retryAfterMs;
13174
+ this.name = "LlmRateLimitError";
13175
+ }
13176
+ [LLM_RATE_LIMIT_BRAND] = true;
13177
+ };
13178
+ LLM_PROVIDER_HTTP_BRAND = /* @__PURE__ */ Symbol.for("wayai.LlmProviderHttpError");
13179
+ LlmProviderHttpError = class extends Error {
13180
+ constructor(message, status, provider, providerError) {
13181
+ super(redactSecrets(message));
13182
+ this.status = status;
13183
+ this.provider = provider;
13184
+ this.providerError = providerError;
13185
+ this.name = "LlmProviderHttpError";
13186
+ }
13187
+ [LLM_PROVIDER_HTTP_BRAND] = true;
13188
+ };
13189
+ LLM_PROVIDER_CONTENT_BRAND = /* @__PURE__ */ Symbol.for("wayai.LlmProviderContentError");
13190
+ LlmProviderContentError = class extends Error {
13191
+ constructor(message, provider, providerError) {
13192
+ super(redactSecrets(message));
13193
+ this.provider = provider;
13194
+ this.providerError = providerError;
13195
+ this.name = "LlmProviderContentError";
13196
+ }
13197
+ [LLM_PROVIDER_CONTENT_BRAND] = true;
13198
+ };
13199
+ LLM_PROVIDER_TIMEOUT_BRAND = /* @__PURE__ */ Symbol.for("wayai.LlmProviderTimeoutError");
13200
+ LlmProviderTimeoutError = class extends Error {
13201
+ constructor(message, provider) {
13202
+ super(message);
13203
+ this.provider = provider;
13204
+ this.name = "LlmProviderTimeoutError";
13205
+ }
13206
+ [LLM_PROVIDER_TIMEOUT_BRAND] = true;
13207
+ };
13208
+ ExternalServiceError = class extends AppError {
13209
+ constructor(service, originalError) {
13210
+ super(`External service error: ${service}`, "EXTERNAL_SERVICE_ERROR", 502, {
13211
+ service,
13212
+ originalMessage: originalError?.message
13213
+ });
13214
+ this.name = "ExternalServiceError";
13215
+ }
13216
+ };
13217
+ CHANNEL_PROVIDER_HTTP_BRAND = /* @__PURE__ */ Symbol.for("wayai.ChannelProviderHttpError");
13218
+ ChannelProviderHttpError = class extends ExternalServiceError {
13219
+ [CHANNEL_PROVIDER_HTTP_BRAND] = true;
13220
+ status;
13221
+ provider;
13222
+ /** Provider numeric error code (Meta `error.code`) — body-free. */
13223
+ providerCode;
13224
+ /** Provider numeric error subcode (Meta `error.error_subcode`) — body-free. */
13225
+ providerSubcode;
13226
+ constructor(provider, status, providerCode, providerSubcode) {
13227
+ super(provider);
13228
+ this.name = "ChannelProviderHttpError";
13229
+ this.status = status;
13230
+ this.provider = provider;
13231
+ this.providerCode = providerCode;
13232
+ this.providerSubcode = providerSubcode;
13233
+ }
13234
+ };
13235
+ MEDIA_PROVIDER_HTTP_BRAND = /* @__PURE__ */ Symbol.for("wayai.MediaProviderHttpError");
13236
+ MediaProviderHttpError = class extends Error {
13237
+ constructor(provider, status, options = {}) {
13238
+ super(`${provider} API error (${status})`);
13239
+ this.provider = provider;
13240
+ this.status = status;
13241
+ this.name = "MediaProviderHttpError";
13242
+ this.credentialRejected = options.credentialRejected ?? false;
13243
+ }
13244
+ [MEDIA_PROVIDER_HTTP_BRAND] = true;
13245
+ /**
13246
+ * The provider said the credential itself was rejected, under a status that does not say so
13247
+ * (Google answers an invalid or expired key with 400 `API_KEY_INVALID`, not 401). Read off
13248
+ * the body at the throw site, which carries only this flag on. Alerting keys on it so the
13249
+ * admin is told to re-enter the key, not that the key is fine.
13250
+ */
13251
+ credentialRejected;
13252
+ };
13253
+ }
13254
+ });
13255
+
13256
+ // ../../packages/core/dist/contracts/index.js
13257
+ var init_contracts = __esm({
13258
+ "../../packages/core/dist/contracts/index.js"() {
13259
+ "use strict";
13260
+ init_chunk_FRU7E62M();
13261
+ init_chunk_VORPHGDT();
13262
+ init_chunk_POL7B3EM();
13263
+ init_chunk_T2RKGBYS();
13264
+ init_chunk_SNA2DXAC();
13265
+ init_chunk_MIWZOSPI();
13266
+ init_chunk_LKBSHANA();
13267
+ init_chunk_IBL7FANV();
13268
+ init_chunk_2ISUBJG7();
13269
+ init_chunk_C2UEA2KW();
13270
+ init_chunk_3NS3HULK();
13271
+ init_chunk_JWPRTSIB();
13272
+ init_chunk_T7KQKDET();
13273
+ init_chunk_L5F7ZOUJ();
13274
+ init_chunk_BPDC67ML();
13275
+ init_chunk_R7VSUKKX();
13276
+ }
13277
+ });
13278
+
12880
13279
  // src/lib/api-client.ts
12881
13280
  var api_client_exports = {};
12882
13281
  __export(api_client_exports, {
@@ -13048,6 +13447,20 @@ var init_api_client = __esm({
13048
13447
  async adminDestroyCommunity(communityId) {
13049
13448
  return this.request("DELETE", `/api/admin/communities/${encodeURIComponent(communityId)}`);
13050
13449
  }
13450
+ // Read which hub is the WayAI Guide (platform-admin gated, wayai#4948). Used by
13451
+ // `wayai admin guide status`.
13452
+ async adminGetGuide() {
13453
+ return this.request("GET", "/api/admin/guide");
13454
+ }
13455
+ // Make a hub the WayAI Guide, or with `dry_run` only check it (platform-admin gated,
13456
+ // wayai#4948). Used by `wayai admin guide set-hub`.
13457
+ async adminSetGuideHub(body) {
13458
+ return this.request("PUT", "/api/admin/guide", body);
13459
+ }
13460
+ // Turn the WayAI Guide off (platform-admin gated, wayai#4948). Used by `wayai admin guide clear`.
13461
+ async adminClearGuideHub() {
13462
+ return this.request("DELETE", "/api/admin/guide");
13463
+ }
13051
13464
  /**
13052
13465
  * Re-discover an MCP connection's tool/resource catalog (refreshes stale
13053
13466
  * input schemas that `push` leaves untouched). `connection` is the display
@@ -13718,371 +14131,146 @@ var init_api_client = __esm({
13718
14131
  /**
13719
14132
  * Download a Data `/v1` path's raw bytes. Distinct from `dataRequest`, which
13720
14133
  * parses the JSON envelope: the response here is the stored blob itself, so
13721
- * this reads `arrayBuffer()`. Single-refresh-on-401 like `request`, but no
13722
- * transient-retry loop — re-streaming a blob is not worth a cold-start probe.
13723
- */
13724
- async dataDownload(v1Path, orgId) {
13725
- const path36 = withOrgSelector(toDataProxyPath(v1Path), orgId);
13726
- addApiBreadcrumb("GET", path36);
13727
- const url = `${this.apiUrl}${path36}`;
13728
- let response = await this.send(url, "GET");
13729
- if (response.status === 401 && this.onUnauthorized) {
13730
- let refreshed;
13731
- try {
13732
- refreshed = await this.onUnauthorized();
13733
- } catch {
13734
- }
13735
- if (refreshed) {
13736
- this.accessToken = refreshed;
13737
- response = await this.send(url, "GET");
13738
- }
13739
- }
13740
- if (!response.ok) {
13741
- throw new ApiError("GET", path36, response.status, await response.text());
13742
- }
13743
- return {
13744
- bytes: new Uint8Array(await response.arrayBuffer()),
13745
- contentType: response.headers.get("Content-Type") ?? "application/octet-stream"
13746
- };
13747
- }
13748
- /**
13749
- * The absolute URL of a Data `/v1` path, for handing the user a link they can
13750
- * fetch themselves. Only the address — every request the CLI issues goes
13751
- * through the methods above, which carry the session.
13752
- */
13753
- dataUrl(v1Path, orgId) {
13754
- return `${this.apiUrl}${withOrgSelector(toDataProxyPath(v1Path), orgId)}`;
13755
- }
13756
- /** Issue a single authenticated request with the client's current token. */
13757
- send(url, method, body, extraHeaders, contentType) {
13758
- return fetch(url, {
13759
- method,
13760
- headers: {
13761
- // Caller-supplied FIRST, so everything pinned below is out of their
13762
- // reach: a metadata header cannot restate the credential or mislabel
13763
- // the body.
13764
- ...extraHeaders,
13765
- Authorization: `Bearer ${this.accessToken}`,
13766
- // The content type describes THIS body, so it is derived from the body
13767
- // rather than accepted from `extraHeaders` — which is pinned out above,
13768
- // and would otherwise be the one way to mislabel a JSON request.
13769
- // `||`, not `??`: an empty content type is not a content type, and an
13770
- // unlabelled body should fall back rather than announce nothing.
13771
- "Content-Type": body instanceof Uint8Array ? contentType || "application/octet-stream" : "application/json",
13772
- // Names the calling surface for the Data Worker's audit rows, which
13773
- // record `cli` vs `api` vs `mcp`. A HINT, not an
13774
- // authorization input: any client can send it, so the backend must
13775
- // normalize it against what it knows about its own ingress rather than
13776
- // trust it. Nothing is granted or denied on its value; the Data Worker's
13777
- // audit rows are its consumer.
13778
- "X-WayAI-Client": "cli"
13779
- },
13780
- // Bytes go on the wire verbatim (file content, attachments); everything
13781
- // else is JSON. Encoding a Uint8Array through JSON.stringify would send
13782
- // `{"0":137,…}` — a corrupt upload rather than a failed one.
13783
- body: !body ? void 0 : body instanceof Uint8Array ? body : JSON.stringify(body)
13784
- });
13785
- }
13786
- };
13787
- }
13788
- });
13789
-
13790
- // src/lib/errors.ts
13791
- function extractApiMessage(err) {
13792
- if (err instanceof ApiError) {
13793
- try {
13794
- const parsed = JSON.parse(err.body);
13795
- if (parsed.message) return parsed.message;
13796
- if (parsed.error) return parsed.error;
13797
- } catch {
13798
- }
13799
- return err.body || err.message;
13800
- }
13801
- return err instanceof Error ? err.message : String(err);
13802
- }
13803
- function extractApiErrorCode(err) {
13804
- if (!(err instanceof ApiError)) return null;
13805
- try {
13806
- const parsed = JSON.parse(err.body);
13807
- return typeof parsed.error === "string" ? parsed.error : null;
13808
- } catch {
13809
- return null;
13810
- }
13811
- }
13812
- function extractApiRetryAfterSeconds(err) {
13813
- if (!(err instanceof ApiError)) return null;
13814
- try {
13815
- const parsed = JSON.parse(err.body);
13816
- const seconds2 = parsed?.details?.retry_after_seconds;
13817
- return typeof seconds2 === "number" && Number.isFinite(seconds2) && seconds2 >= 0 ? seconds2 : null;
13818
- } catch {
13819
- return null;
13820
- }
13821
- }
13822
- function friendlyHint(err) {
13823
- if (isNetworkError(err)) {
13824
- return "Couldn't reach WayAI \u2014 check your network connection and try again.";
13825
- }
13826
- if (!(err instanceof ApiError)) return null;
13827
- if (err.body.includes("FREE_PLAN_RESTRICTION")) {
13828
- return "Publishing to production requires a paid plan. Upgrade your organization to publish or sync.";
13829
- }
13830
- const dataMessage = dataErrorMessage(err);
13831
- if (dataMessage) return dataMessage;
13832
- const { status } = err;
13833
- if (status === 401) return "Your session may have expired. Run `wayai login` to re-authenticate.";
13834
- if (status === 402) return "Quota exceeded for your plan. Review usage or upgrade your plan.";
13835
- if (status === 403) return "Access denied. Your token may lack permission for this hub or resource.";
13836
- if (status === 429) return "Rate limited. Wait a moment and try again.";
13837
- if (status >= 500) return "WayAI server error \u2014 likely temporary. Try again shortly.";
13838
- return null;
13839
- }
13840
- var init_errors2 = __esm({
13841
- "src/lib/errors.ts"() {
13842
- "use strict";
13843
- init_api_client();
13844
- init_network_error();
13845
- }
13846
- });
13847
-
13848
- // ../../packages/core/dist/chunk-WSROLRJN.js
13849
- function identifyTokenType(token) {
13850
- if (token.startsWith("way_")) return "way_token";
13851
- if (token.startsWith("eyJ")) return "jwt";
13852
- return "unknown";
13853
- }
13854
- var init_chunk_WSROLRJN = __esm({
13855
- "../../packages/core/dist/chunk-WSROLRJN.js"() {
13856
- "use strict";
13857
- init_chunk_VORPHGDT();
13858
- }
13859
- });
13860
-
13861
- // ../../packages/core/dist/chunk-FEOO3UPS.js
13862
- var init_chunk_FEOO3UPS = __esm({
13863
- "../../packages/core/dist/chunk-FEOO3UPS.js"() {
13864
- "use strict";
13865
- }
13866
- });
13867
-
13868
- // ../../packages/core/dist/chunk-IOJOM4DE.js
13869
- var init_chunk_IOJOM4DE = __esm({
13870
- "../../packages/core/dist/chunk-IOJOM4DE.js"() {
13871
- "use strict";
13872
- init_chunk_C2UEA2KW();
13873
- }
13874
- });
13875
-
13876
- // ../../packages/core/dist/chunk-BF4WRSOQ.js
13877
- var init_chunk_BF4WRSOQ = __esm({
13878
- "../../packages/core/dist/chunk-BF4WRSOQ.js"() {
13879
- "use strict";
13880
- }
13881
- });
13882
-
13883
- // ../../packages/core/dist/chunk-R7VSUKKX.js
13884
- function isPublicIdentifier(value) {
13885
- return UUID_RE.test(value) || HEX_RE.test(value) || WORKOS_ID_RE.test(value) || TRACE_HEADER_RE.test(value);
13886
- }
13887
- function redactTokenShapes(input) {
13888
- return input.replace(TOKEN_RE, REDACTED).replace(PROVIDER_TOKEN_RE, `$1${REDACTED}`).replace(JSON_CREDENTIAL_RE, `$1"${REDACTED}"`).replace(QUERY_CREDENTIAL_RE, `$1${REDACTED}`);
13889
- }
13890
- function redactSecrets(value) {
13891
- if (isPublicIdentifier(value)) {
13892
- return value;
13893
- }
13894
- if (OPAQUE_SECRET_RE.test(value)) {
13895
- return REDACTED;
13896
- }
13897
- if (BASE64_SECRET_RE.test(value) && BASE64_MARKER_RE.test(value)) {
13898
- return REDACTED;
13899
- }
13900
- return redactTokenShapes(value);
13901
- }
13902
- var UUID_RE, HEX_RE, WORKOS_ID_RE, TRACE_HEADER_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;
13903
- var init_chunk_R7VSUKKX = __esm({
13904
- "../../packages/core/dist/chunk-R7VSUKKX.js"() {
13905
- "use strict";
13906
- UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
13907
- HEX_RE = /^[0-9a-f]{16,}$/;
13908
- WORKOS_ID_RE = /^(?:user|org)_[0-9A-HJKMNP-TV-Z]{26}$/;
13909
- TRACE_HEADER_RE = /^(?:[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-[0-9a-f]{2}|[0-9a-f]{32}-[0-9a-f]{16}(?:-[01])?)$/;
13910
- OPAQUE_SECRET_RE = /^[A-Za-z0-9_-]{21,}$/;
13911
- BASE64_SECRET_RE = /^[A-Za-z0-9+/]{20,}={0,2}$/;
13912
- BASE64_MARKER_RE = /[+=]/;
13913
- TOKEN_RE = new RegExp(
13914
- [
13915
- // WayAI API tokens and WebSocket tickets.
13916
- "(?:way|wst)_[A-Za-z0-9._-]{8,}",
13917
- // Authorization header values, including base64 Basic credentials.
13918
- "(?:Bearer|Basic)\\s+[A-Za-z0-9._~+/=-]{8,}",
13919
- // JWTs — WorkOS session/access tokens. `eyJ` is base64 for `{"`.
13920
- "eyJ[A-Za-z0-9._-]{10,}",
13921
- // Stripe secret/publishable/restricted keys and webhook signing secrets.
13922
- "(?:sk|pk|rk)_(?:live|test)_[A-Za-z0-9]{8,}",
13923
- "whsec_[A-Za-z0-9]{8,}",
13924
- // Telegram bot tokens as the Bot API takes them, in the URL path: `/bot<id>:<secret>/`.
13925
- "bot[0-9]{5,}:[A-Za-z0-9_-]{30,}"
13926
- // NOTE: LLM provider keys are NOT here — they need a delimiter-preserving
13927
- // boundary, so they live in PROVIDER_TOKEN_RE below.
13928
- ].join("|"),
13929
- "g"
13930
- );
13931
- SENSITIVE_FIELDS = [
13932
- "password",
13933
- "token",
13934
- "secret",
13935
- "api_key",
13936
- "apikey",
13937
- "api-key",
13938
- "authorization",
13939
- "auth",
13940
- "credential",
13941
- "private_key",
13942
- "privatekey",
13943
- "access_token",
13944
- "refresh_token",
13945
- "session_id",
13946
- "sessionid",
13947
- "cookie",
13948
- "jwt"
13949
- ];
13950
- SENSITIVE_KEY_ALTERNATION = SENSITIVE_FIELDS.map(
13951
- (field) => field.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
13952
- ).join("|");
13953
- SENSITIVE_KEY_PATTERN = `[A-Za-z0-9_.-]*(?:${SENSITIVE_KEY_ALTERNATION})[A-Za-z0-9_.-]*`;
13954
- JSON_CREDENTIAL_RE = new RegExp(
13955
- `("${SENSITIVE_KEY_PATTERN}"\\s*:\\s*)"(?:[^"\\\\]|\\\\.)*"`,
13956
- "gi"
13957
- );
13958
- QUERY_CREDENTIAL_RE = new RegExp(
13959
- `((?:^|[?&#;\\s])${SENSITIVE_KEY_PATTERN}=)[^&;\\s"']+`,
13960
- "gi"
13961
- );
13962
- REDACTED = "[REDACTED]";
13963
- PROVIDER_TOKEN_RE = new RegExp(
13964
- "(^|[^A-Za-z0-9])(?:" + [
13965
- "sk-[A-Za-z0-9_-]{16,}",
13966
- "AIza[A-Za-z0-9_-]{16,}",
13967
- "xai-[A-Za-z0-9_-]{16,}"
13968
- ].join("|") + ")",
13969
- "g"
13970
- );
13971
- }
13972
- });
13973
-
13974
- // ../../packages/core/dist/chunk-4MBOLX7Q.js
13975
- var 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;
13976
- var init_chunk_4MBOLX7Q = __esm({
13977
- "../../packages/core/dist/chunk-4MBOLX7Q.js"() {
13978
- "use strict";
13979
- init_chunk_R7VSUKKX();
13980
- APP_ERROR_BRAND = /* @__PURE__ */ Symbol.for("wayai.AppError");
13981
- AppError = class extends Error {
13982
- constructor(message, code, statusCode = 500, details) {
13983
- super(message);
13984
- this.code = code;
13985
- this.statusCode = statusCode;
13986
- this.details = details;
13987
- this.name = "AppError";
13988
- }
13989
- [APP_ERROR_BRAND] = true;
13990
- toJSON() {
13991
- return {
13992
- error: this.code,
13993
- message: this.message,
13994
- ...this.details && { details: this.details }
13995
- };
13996
- }
13997
- };
13998
- LLM_RATE_LIMIT_BRAND = /* @__PURE__ */ Symbol.for("wayai.LlmRateLimitError");
13999
- LlmRateLimitError = class extends Error {
14000
- constructor(provider, retryAfterMs) {
14001
- super(`${provider} rate limited; retry after ${retryAfterMs}ms`);
14002
- this.provider = provider;
14003
- this.retryAfterMs = retryAfterMs;
14004
- this.name = "LlmRateLimitError";
14005
- }
14006
- [LLM_RATE_LIMIT_BRAND] = true;
14007
- };
14008
- LLM_PROVIDER_HTTP_BRAND = /* @__PURE__ */ Symbol.for("wayai.LlmProviderHttpError");
14009
- LlmProviderHttpError = class extends Error {
14010
- constructor(message, status, provider, providerError) {
14011
- super(redactSecrets(message));
14012
- this.status = status;
14013
- this.provider = provider;
14014
- this.providerError = providerError;
14015
- this.name = "LlmProviderHttpError";
14016
- }
14017
- [LLM_PROVIDER_HTTP_BRAND] = true;
14018
- };
14019
- LLM_PROVIDER_CONTENT_BRAND = /* @__PURE__ */ Symbol.for("wayai.LlmProviderContentError");
14020
- LlmProviderContentError = class extends Error {
14021
- constructor(message, provider, providerError) {
14022
- super(redactSecrets(message));
14023
- this.provider = provider;
14024
- this.providerError = providerError;
14025
- this.name = "LlmProviderContentError";
14026
- }
14027
- [LLM_PROVIDER_CONTENT_BRAND] = true;
14028
- };
14029
- LLM_PROVIDER_TIMEOUT_BRAND = /* @__PURE__ */ Symbol.for("wayai.LlmProviderTimeoutError");
14030
- LlmProviderTimeoutError = class extends Error {
14031
- constructor(message, provider) {
14032
- super(message);
14033
- this.provider = provider;
14034
- this.name = "LlmProviderTimeoutError";
14035
- }
14036
- [LLM_PROVIDER_TIMEOUT_BRAND] = true;
14037
- };
14038
- ExternalServiceError = class extends AppError {
14039
- constructor(service, originalError) {
14040
- super(`External service error: ${service}`, "EXTERNAL_SERVICE_ERROR", 502, {
14041
- service,
14042
- originalMessage: originalError?.message
14043
- });
14044
- this.name = "ExternalServiceError";
14045
- }
14046
- };
14047
- CHANNEL_PROVIDER_HTTP_BRAND = /* @__PURE__ */ Symbol.for("wayai.ChannelProviderHttpError");
14048
- ChannelProviderHttpError = class extends ExternalServiceError {
14049
- [CHANNEL_PROVIDER_HTTP_BRAND] = true;
14050
- status;
14051
- provider;
14052
- /** Provider numeric error code (Meta `error.code`) — body-free. */
14053
- providerCode;
14054
- /** Provider numeric error subcode (Meta `error.error_subcode`) — body-free. */
14055
- providerSubcode;
14056
- constructor(provider, status, providerCode, providerSubcode) {
14057
- super(provider);
14058
- this.name = "ChannelProviderHttpError";
14059
- this.status = status;
14060
- this.provider = provider;
14061
- this.providerCode = providerCode;
14062
- this.providerSubcode = providerSubcode;
14063
- }
14064
- };
14065
- MEDIA_PROVIDER_HTTP_BRAND = /* @__PURE__ */ Symbol.for("wayai.MediaProviderHttpError");
14066
- MediaProviderHttpError = class extends Error {
14067
- constructor(provider, status, options = {}) {
14068
- super(`${provider} API error (${status})`);
14069
- this.provider = provider;
14070
- this.status = status;
14071
- this.name = "MediaProviderHttpError";
14072
- this.credentialRejected = options.credentialRejected ?? false;
14134
+ * this reads `arrayBuffer()`. Single-refresh-on-401 like `request`, but no
14135
+ * transient-retry loop — re-streaming a blob is not worth a cold-start probe.
14136
+ */
14137
+ async dataDownload(v1Path, orgId) {
14138
+ const path36 = withOrgSelector(toDataProxyPath(v1Path), orgId);
14139
+ addApiBreadcrumb("GET", path36);
14140
+ const url = `${this.apiUrl}${path36}`;
14141
+ let response = await this.send(url, "GET");
14142
+ if (response.status === 401 && this.onUnauthorized) {
14143
+ let refreshed;
14144
+ try {
14145
+ refreshed = await this.onUnauthorized();
14146
+ } catch {
14147
+ }
14148
+ if (refreshed) {
14149
+ this.accessToken = refreshed;
14150
+ response = await this.send(url, "GET");
14151
+ }
14152
+ }
14153
+ if (!response.ok) {
14154
+ throw new ApiError("GET", path36, response.status, await response.text());
14155
+ }
14156
+ return {
14157
+ bytes: new Uint8Array(await response.arrayBuffer()),
14158
+ contentType: response.headers.get("Content-Type") ?? "application/octet-stream"
14159
+ };
14073
14160
  }
14074
- [MEDIA_PROVIDER_HTTP_BRAND] = true;
14075
14161
  /**
14076
- * The provider said the credential itself was rejected, under a status that does not say so
14077
- * (Google answers an invalid or expired key with 400 `API_KEY_INVALID`, not 401). Read off
14078
- * the body at the throw site, which carries only this flag on. Alerting keys on it so the
14079
- * admin is told to re-enter the key, not that the key is fine.
14162
+ * The absolute URL of a Data `/v1` path, for handing the user a link they can
14163
+ * fetch themselves. Only the address — every request the CLI issues goes
14164
+ * through the methods above, which carry the session.
14080
14165
  */
14081
- credentialRejected;
14166
+ dataUrl(v1Path, orgId) {
14167
+ return `${this.apiUrl}${withOrgSelector(toDataProxyPath(v1Path), orgId)}`;
14168
+ }
14169
+ /** Issue a single authenticated request with the client's current token. */
14170
+ send(url, method, body, extraHeaders, contentType) {
14171
+ return fetch(url, {
14172
+ method,
14173
+ headers: {
14174
+ // Caller-supplied FIRST, so everything pinned below is out of their
14175
+ // reach: a metadata header cannot restate the credential or mislabel
14176
+ // the body.
14177
+ ...extraHeaders,
14178
+ Authorization: `Bearer ${this.accessToken}`,
14179
+ // The content type describes THIS body, so it is derived from the body
14180
+ // rather than accepted from `extraHeaders` — which is pinned out above,
14181
+ // and would otherwise be the one way to mislabel a JSON request.
14182
+ // `||`, not `??`: an empty content type is not a content type, and an
14183
+ // unlabelled body should fall back rather than announce nothing.
14184
+ "Content-Type": body instanceof Uint8Array ? contentType || "application/octet-stream" : "application/json",
14185
+ // Names the calling surface for the Data Worker's audit rows, which
14186
+ // record `cli` vs `api` vs `mcp`. A HINT, not an
14187
+ // authorization input: any client can send it, so the backend must
14188
+ // normalize it against what it knows about its own ingress rather than
14189
+ // trust it. Nothing is granted or denied on its value; the Data Worker's
14190
+ // audit rows are its consumer.
14191
+ "X-WayAI-Client": "cli"
14192
+ },
14193
+ // Bytes go on the wire verbatim (file content, attachments); everything
14194
+ // else is JSON. Encoding a Uint8Array through JSON.stringify would send
14195
+ // `{"0":137,…}` — a corrupt upload rather than a failed one.
14196
+ body: !body ? void 0 : body instanceof Uint8Array ? body : JSON.stringify(body)
14197
+ });
14198
+ }
14082
14199
  };
14083
14200
  }
14084
14201
  });
14085
14202
 
14203
+ // src/lib/errors.ts
14204
+ function extractApiMessage(err) {
14205
+ if (err instanceof ApiError) {
14206
+ try {
14207
+ const parsed = JSON.parse(err.body);
14208
+ if (parsed.message) return parsed.message;
14209
+ if (parsed.error) return parsed.error;
14210
+ } catch {
14211
+ }
14212
+ return err.body || err.message;
14213
+ }
14214
+ return err instanceof Error ? err.message : String(err);
14215
+ }
14216
+ function extractApiErrorCode(err) {
14217
+ if (!(err instanceof ApiError)) return null;
14218
+ try {
14219
+ const parsed = JSON.parse(err.body);
14220
+ return typeof parsed.error === "string" ? parsed.error : null;
14221
+ } catch {
14222
+ return null;
14223
+ }
14224
+ }
14225
+ function extractApiRetryAfterSeconds(err) {
14226
+ if (!(err instanceof ApiError)) return null;
14227
+ try {
14228
+ const parsed = JSON.parse(err.body);
14229
+ const seconds2 = parsed?.details?.retry_after_seconds;
14230
+ return typeof seconds2 === "number" && Number.isFinite(seconds2) && seconds2 >= 0 ? seconds2 : null;
14231
+ } catch {
14232
+ return null;
14233
+ }
14234
+ }
14235
+ function friendlyHint(err) {
14236
+ if (isNetworkError(err)) {
14237
+ return "Couldn't reach WayAI \u2014 check your network connection and try again.";
14238
+ }
14239
+ if (!(err instanceof ApiError)) return null;
14240
+ if (err.body.includes("FREE_PLAN_RESTRICTION")) {
14241
+ return "Publishing to production requires a paid plan. Upgrade your organization to publish or sync.";
14242
+ }
14243
+ const dataMessage = dataErrorMessage(err);
14244
+ if (dataMessage) return dataMessage;
14245
+ const { status } = err;
14246
+ if (status === 401) return "Your session may have expired. Run `wayai login` to re-authenticate.";
14247
+ if (status === 402) return "Quota exceeded for your plan. Review usage or upgrade your plan.";
14248
+ if (status === 403) return "Access denied. Your token may lack permission for this hub or resource.";
14249
+ if (status === 429) return "Rate limited. Wait a moment and try again.";
14250
+ if (status >= 500) return "WayAI server error \u2014 likely temporary. Try again shortly.";
14251
+ return null;
14252
+ }
14253
+ var init_errors2 = __esm({
14254
+ "src/lib/errors.ts"() {
14255
+ "use strict";
14256
+ init_api_client();
14257
+ init_network_error();
14258
+ }
14259
+ });
14260
+
14261
+ // ../../packages/core/dist/chunk-WSROLRJN.js
14262
+ function identifyTokenType(token) {
14263
+ if (token.startsWith("way_")) return "way_token";
14264
+ if (token.startsWith("eyJ")) return "jwt";
14265
+ return "unknown";
14266
+ }
14267
+ var init_chunk_WSROLRJN = __esm({
14268
+ "../../packages/core/dist/chunk-WSROLRJN.js"() {
14269
+ "use strict";
14270
+ init_chunk_VORPHGDT();
14271
+ }
14272
+ });
14273
+
14086
14274
  // ../../packages/core/dist/chunk-ERFR7IRY.js
14087
14275
  function findStepBoundaries(transcript) {
14088
14276
  const out = [];
@@ -14125,6 +14313,28 @@ var init_chunk_ERFR7IRY = __esm({
14125
14313
  }
14126
14314
  });
14127
14315
 
14316
+ // ../../packages/core/dist/chunk-FEOO3UPS.js
14317
+ var init_chunk_FEOO3UPS = __esm({
14318
+ "../../packages/core/dist/chunk-FEOO3UPS.js"() {
14319
+ "use strict";
14320
+ }
14321
+ });
14322
+
14323
+ // ../../packages/core/dist/chunk-RPGBR5IN.js
14324
+ var init_chunk_RPGBR5IN = __esm({
14325
+ "../../packages/core/dist/chunk-RPGBR5IN.js"() {
14326
+ "use strict";
14327
+ init_chunk_C2UEA2KW();
14328
+ }
14329
+ });
14330
+
14331
+ // ../../packages/core/dist/chunk-BF4WRSOQ.js
14332
+ var init_chunk_BF4WRSOQ = __esm({
14333
+ "../../packages/core/dist/chunk-BF4WRSOQ.js"() {
14334
+ "use strict";
14335
+ }
14336
+ });
14337
+
14128
14338
  // ../../packages/core/dist/index.js
14129
14339
  function markdownToPlainText(text) {
14130
14340
  let result = text;
@@ -14147,26 +14357,26 @@ var init_dist = __esm({
14147
14357
  "../../packages/core/dist/index.js"() {
14148
14358
  "use strict";
14149
14359
  init_chunk_WSROLRJN();
14150
- init_chunk_H4RTULPH();
14360
+ init_chunk_FRU7E62M();
14151
14361
  init_chunk_VORPHGDT();
14152
14362
  init_chunk_POL7B3EM();
14153
- init_chunk_YEYIDIR6();
14363
+ init_chunk_T2RKGBYS();
14154
14364
  init_chunk_SNA2DXAC();
14155
- init_chunk_R5WRRHCL();
14365
+ init_chunk_MIWZOSPI();
14366
+ init_chunk_LKBSHANA();
14156
14367
  init_chunk_IBL7FANV();
14368
+ init_chunk_ERFR7IRY();
14369
+ init_chunk_2ISUBJG7();
14157
14370
  init_chunk_FEOO3UPS();
14158
- init_chunk_IOJOM4DE();
14371
+ init_chunk_RPGBR5IN();
14159
14372
  init_chunk_C2UEA2KW();
14160
14373
  init_chunk_3NS3HULK();
14161
- init_chunk_MIWZOSPI();
14162
14374
  init_chunk_JWPRTSIB();
14163
14375
  init_chunk_BF4WRSOQ();
14164
14376
  init_chunk_T7KQKDET();
14165
14377
  init_chunk_L5F7ZOUJ();
14166
- init_chunk_4MBOLX7Q();
14378
+ init_chunk_BPDC67ML();
14167
14379
  init_chunk_R7VSUKKX();
14168
- init_chunk_ERFR7IRY();
14169
- init_chunk_2ISUBJG7();
14170
14380
  ENDPOINT_CONFIGS = {
14171
14381
  // OAuth callbacks - strict, fail-closed (prevent brute force)
14172
14382
  "/oauth/callback/*": { tier: "STRICT", failClosed: true },
@@ -14315,6 +14525,12 @@ var init_dist = __esm({
14315
14525
  // Channel webhooks - high throughput (external systems, never authenticated)
14316
14526
  "/webhooks/whatsapp/*": { tier: "HIGH" },
14317
14527
  "/webhooks/instagram/*": { tier: "HIGH" },
14528
+ // An automation's webhook deliveries (wayai#4931 D13) — no bearer token: the automation's
14529
+ // secret is the credential, checked against one HubDO read. This per-IP limit runs first, before
14530
+ // anything is read. HIGH, as the channel webhooks: senders are servers, and an integration
14531
+ // platform's egress addresses carry many tenants' deliveries. The per-automation budget is
14532
+ // `AUTOMATION_WEBHOOK_PER_AUTOMATION_LIMIT`, counted after the delivery is verified.
14533
+ [`${AUTOMATION_WEBHOOK_MOUNT}/*`]: { tier: "HIGH" },
14318
14534
  // Reports (CLI → platform_report triage queue). One per-user budget covers intake
14319
14535
  // (POST), the content edit (PATCH /:id), the reporter read-back (GET, GET /:id), and the
14320
14536
  // verification loop (POST /:id/accept, /:id/contest). The limiter is path-based, so a
@@ -14599,6 +14815,17 @@ var init_dist = __esm({
14599
14815
  // many members' clicks share, and STRICT's 5/min bucket is shared with sign-in. An exact key, so
14600
14816
  // it wins over the wildcard above.
14601
14817
  [COMMUNITY_EMAIL_UNSUBSCRIBE_PATH]: { tier: "MODERATE" },
14818
+ // The WayAI Guide's help entry (wayai#4948, `routes/api/guide.ts`): one POST per click by a viewer
14819
+ // the snapshot does not show enrolled, which reads the person's row on the Guide hub and writes only
14820
+ // what is missing (an enrolled viewer's click opens the hub without a request). Every caller is
14821
+ // signed in, so the per-IP tier is skipped; 10 a minute per person on the native binding (fails
14822
+ // open, like every 60 s budget) bounds what a looping client costs the one Guide HubDO.
14823
+ "/api/guide/access": {
14824
+ tier: "STANDARD",
14825
+ userLimit: 10,
14826
+ skipAuthenticatedUsers: true,
14827
+ userLimitKey: "/api/guide/access"
14828
+ },
14602
14829
  // App channel - high throughput with user limits
14603
14830
  "/channels/app/*": { tier: "HIGH", userLimit: 500, skipAuthenticatedUsers: true },
14604
14831
  // API channel (api-channel-connector) - machine-to-machine, high throughput
@@ -22849,7 +23076,7 @@ function describeCategory(category) {
22849
23076
  case AUTOMATION_ALERT_CATEGORIES.list_over_cap:
22850
23077
  return {
22851
23078
  label: "Automation list over the cap",
22852
- hint: "An automation's list holds more contacts this hub sees than one fire may reach. Narrow the list's filter \u2014 a hub list in `hub.yaml` `contact_lists:`, an org list in the organization's Contacts settings."
23079
+ hint: "Raised before lists were read a page at a time: a list is no longer capped per fire, so the automation's next fire reaches the whole list. Nothing to change; the alert clears on its own."
22853
23080
  };
22854
23081
  // wayai#4931 D15: an automation, enabled and not paused, that cannot fire. Its subject is the
22855
23082
  // automation, never a connection; the reason, naming the automation, is the alert's detail.
@@ -28126,6 +28353,26 @@ async function adminCommand(args2) {
28126
28353
  process.exit(1);
28127
28354
  }
28128
28355
  }
28356
+ if (group === "guide") {
28357
+ if (!sub) {
28358
+ printHelp2();
28359
+ process.exit(1);
28360
+ }
28361
+ switch (sub) {
28362
+ case "set-hub":
28363
+ await runGuideSetHub(positional, flagArgs);
28364
+ return;
28365
+ case "clear":
28366
+ await runGuideClear(positional, flagArgs);
28367
+ return;
28368
+ case "status":
28369
+ await runGuideStatus(positional, flagArgs);
28370
+ return;
28371
+ default:
28372
+ printHelp2();
28373
+ process.exit(1);
28374
+ }
28375
+ }
28129
28376
  if (group === "voice-calls") {
28130
28377
  if (!sub) {
28131
28378
  printHelp2();
@@ -29038,6 +29285,121 @@ async function runCommunitiesDestroy(positional, flagArgs) {
29038
29285
  }
29039
29286
  console.log(`Destroyed community ${data.community_id} \u2014 "${data.name}", owned by ${data.org_name} (${data.org_id}), at ${data.destroyed_at}.`);
29040
29287
  }
29288
+ function describeGuideHub(hub) {
29289
+ return `${hub.hub_name ?? "(unnamed)"} (${hub.hub_id}), owned by ${hub.organization_name ?? "(unnamed org)"} (${hub.organization_id})`;
29290
+ }
29291
+ function parseGuideFlags(flagArgs, usage3, allowed) {
29292
+ for (const flag of flagArgs) {
29293
+ if (!allowed.includes(flag)) {
29294
+ console.error(`Unknown flag: ${flag}`);
29295
+ console.error(usage3);
29296
+ process.exit(1);
29297
+ }
29298
+ }
29299
+ return { yes: flagArgs.includes("--yes"), jsonOutput: flagArgs.includes("--json") };
29300
+ }
29301
+ async function runGuideSetHub(positional, flagArgs) {
29302
+ const usage3 = "wayai admin guide set-hub <hub_id> [--yes] [--json]";
29303
+ const { yes, jsonOutput } = parseGuideFlags(flagArgs, usage3, ["--yes", "--json"]);
29304
+ const parsed = adminSetGuideHubBody.safeParse({ hub_id: positional[0] });
29305
+ if (positional.length !== 1 || !parsed.success) {
29306
+ console.error("<hub_id> must be one hub id (a UUID).");
29307
+ console.error(usage3);
29308
+ process.exit(1);
29309
+ }
29310
+ const hubId = parsed.data.hub_id;
29311
+ const { config, accessToken } = await requireAuth();
29312
+ const client = new ApiClient({ apiUrl: config.api_url, accessToken });
29313
+ const put = async (dryRun) => {
29314
+ try {
29315
+ return (await client.adminSetGuideHub({ hub_id: hubId, dry_run: dryRun })).data;
29316
+ } catch (err) {
29317
+ if (err instanceof ApiError && err.status === 404) {
29318
+ console.error(`Hub ${hubId} not found (never created, or deleted).`);
29319
+ process.exit(1);
29320
+ }
29321
+ if (err instanceof ApiError && err.status === 409 && conflictReasonOf(err) === GUIDE_HUB_INELIGIBLE_REASON) {
29322
+ console.error(`Refused: ${extractApiMessage(err)}.`);
29323
+ process.exit(1);
29324
+ }
29325
+ exitOnApiError(err);
29326
+ throw err;
29327
+ }
29328
+ };
29329
+ if (!yes && !jsonOutput) {
29330
+ const checked = await put(true);
29331
+ console.log(`The Guide will be ${describeGuideHub(checked.hub)}.`);
29332
+ console.log("Every account provisioned from now on is enrolled in it as an end user, and the");
29333
+ console.log("owning org pays for every Guide conversation.");
29334
+ const ok = await confirm("Proceed?");
29335
+ if (!ok) {
29336
+ console.log("Aborted.");
29337
+ return;
29338
+ }
29339
+ }
29340
+ const written = await put(false);
29341
+ if (jsonOutput) {
29342
+ console.log(JSON.stringify(written, null, 2));
29343
+ return;
29344
+ }
29345
+ console.log(`The Guide is ${describeGuideHub(written.hub)}.`);
29346
+ console.log(PLATFORM_CONFIG_PROPAGATION_NOTE);
29347
+ }
29348
+ async function runGuideClear(positional, flagArgs) {
29349
+ const usage3 = "wayai admin guide clear [--json]";
29350
+ if (positional.length > 0) {
29351
+ console.error(usage3);
29352
+ process.exit(1);
29353
+ }
29354
+ const { jsonOutput } = parseGuideFlags(flagArgs, usage3, ["--json"]);
29355
+ const { config, accessToken } = await requireAuth();
29356
+ const client = new ApiClient({ apiUrl: config.api_url, accessToken });
29357
+ try {
29358
+ const { data } = await client.adminClearGuideHub();
29359
+ if (jsonOutput) {
29360
+ console.log(JSON.stringify(data, null, 2));
29361
+ return;
29362
+ }
29363
+ } catch (err) {
29364
+ exitOnApiError(err);
29365
+ throw err;
29366
+ }
29367
+ console.log("The Guide is off: nobody new is enrolled, and the help entry is hidden.");
29368
+ console.log("People already enrolled keep their row on the Guide hub.");
29369
+ console.log(PLATFORM_CONFIG_PROPAGATION_NOTE);
29370
+ }
29371
+ async function runGuideStatus(positional, flagArgs) {
29372
+ const usage3 = "wayai admin guide status [--json]";
29373
+ if (positional.length > 0) {
29374
+ console.error(usage3);
29375
+ process.exit(1);
29376
+ }
29377
+ const { jsonOutput } = parseGuideFlags(flagArgs, usage3, ["--json"]);
29378
+ const { config, accessToken } = await requireAuth();
29379
+ const client = new ApiClient({ apiUrl: config.api_url, accessToken });
29380
+ let data;
29381
+ try {
29382
+ data = (await client.adminGetGuide()).data;
29383
+ } catch (err) {
29384
+ exitOnApiError(err);
29385
+ throw err;
29386
+ }
29387
+ if (jsonOutput) {
29388
+ console.log(JSON.stringify(data, null, 2));
29389
+ return;
29390
+ }
29391
+ if (!data.guide_hub_id) {
29392
+ console.log("guide_hub_id (platform): not set \u2014 the Guide is off.");
29393
+ return;
29394
+ }
29395
+ console.log(`guide_hub_id (platform): ${data.guide_hub_id}`);
29396
+ if (!data.hub) {
29397
+ console.log("The hub cannot be read (deleted?). Run `wayai admin guide clear`.");
29398
+ return;
29399
+ }
29400
+ console.log(`Hub: ${describeGuideHub(data.hub)}`);
29401
+ console.log(`Environment: ${data.hub.hub_environment ?? "unknown"}; type: ${data.hub.hub_type ?? "unknown"}; app channel: ${data.hub.app_channel_enabled ? "enabled" : "DISABLED"}`);
29402
+ }
29041
29403
  function conflictReasonOf(err) {
29042
29404
  try {
29043
29405
  const reason = JSON.parse(err.body).details?.reason;
@@ -29656,6 +30018,11 @@ Usage:
29656
30018
  wayai admin communities destroy <community_id> [--yes] [--json]
29657
30019
  Destroy a community: its members' lists drop it and its storage is deleted (DESTRUCTIVE; confirms unless --yes)
29658
30020
 
30021
+ wayai admin guide set-hub <hub_id> [--yes] [--json]
30022
+ Make a production chat hub with an enabled app channel the WayAI Guide (prints its owning org and confirms, unless --yes or --json)
30023
+ wayai admin guide clear [--json] Turn the Guide off: nobody new is enrolled and the help entry is hidden
30024
+ wayai admin guide status [--json] Print which hub is the Guide, and its facts
30025
+
29659
30026
  Sources:
29660
30027
  do Live DO SQLite (existing conversation, hub config, etc.).
29661
30028
  analytics ClickHouse projections (conversation, message, schedule_event).
@@ -29745,6 +30112,12 @@ Sources:
29745
30112
  community for an org and \`destroy\` removes one, whichever way the switch
29746
30113
  is set; deleting an org destroys its communities too. Changes to the
29747
30114
  switch land within about 60 s.
30115
+ guide The WayAI Guide: ONE production chat hub, owned by WayAI, whose agent answers
30116
+ questions about the platform. While \`set-hub\` has named it, every account
30117
+ provisioned is enrolled in it as an end user and every signed-in person reaches
30118
+ it from the help entry ("Ask WayAI"); its owning org pays. \`clear\` stops new
30119
+ enrollment and hides the help entry; people already enrolled keep their row.
30120
+ Changes land within about 60 s.
29748
30121
 
29749
30122
  Types (do): ${VALID_TYPES.join(" | ")}
29750
30123
  Tables (analytics): ${VALID_ANALYTICS_TABLES.join(" | ")}
@@ -29795,6 +30168,7 @@ var init_admin = __esm({
29795
30168
  init_workspace();
29796
30169
  init_skill_version();
29797
30170
  init_file_map();
30171
+ init_errors2();
29798
30172
  init_contracts();
29799
30173
  VALID_TYPES = dataExplorerDebugDoType.options;
29800
30174
  VALID_ANALYTICS_TABLES = dataExplorerDebugAnalyticsTable.options;