@wayai/cli 0.3.113 → 0.3.115

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
@@ -613,38 +613,6 @@ var init_api_client = __esm({
613
613
  async adminUpdateConfig(body) {
614
614
  return this.request("PATCH", "/api/admin/config", body);
615
615
  }
616
- // Flip the ORG-layer harness rollout gate (platform-admin gated — harness-agents
617
- // PR 2.9a-2 staged rollout). Used by `wayai admin harness enable|disable --org <id>`.
618
- async adminSetOrgHarness(orgId, enabled) {
619
- return this.request(
620
- "PATCH",
621
- `/api/admin/organizations/${encodeURIComponent(orgId)}/harness`,
622
- { harness_enabled: enabled }
623
- );
624
- }
625
- // Read the ORG-layer harness rollout gate. Used by `wayai admin harness status --org <id>`.
626
- async adminGetOrgHarness(orgId) {
627
- return this.request(
628
- "GET",
629
- `/api/admin/organizations/${encodeURIComponent(orgId)}/harness`
630
- );
631
- }
632
- // Flip the HUB-layer harness rollout gate (platform-admin gated — harness-agents
633
- // PR 2.9a-2 staged rollout). Used by `wayai admin harness enable|disable --hub <id>`.
634
- async adminSetHubHarness(hubId, enabled) {
635
- return this.request(
636
- "PATCH",
637
- `/api/admin/hubs/${encodeURIComponent(hubId)}/harness`,
638
- { harness_enabled: enabled }
639
- );
640
- }
641
- // Read the HUB-layer harness rollout gate. Used by `wayai admin harness status --hub <id>`.
642
- async adminGetHubHarness(hubId) {
643
- return this.request(
644
- "GET",
645
- `/api/admin/hubs/${encodeURIComponent(hubId)}/harness`
646
- );
647
- }
648
616
  /**
649
617
  * Re-discover an MCP connection's tool/resource catalog (refreshes stale
650
618
  * input schemas that `push` leaves untouched). `connection` is the display
@@ -5693,6 +5661,14 @@ function collectTurnAttachmentHashes(turn) {
5693
5661
  }
5694
5662
  return hashes;
5695
5663
  }
5664
+ function isSafeTemplatePath(path31) {
5665
+ if (path31.length === 0 || path31.length > 300) return false;
5666
+ if (path31.startsWith("/") || path31.includes("\\")) return false;
5667
+ const segments = path31.split("/");
5668
+ return segments.every(
5669
+ (seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
5670
+ );
5671
+ }
5696
5672
  function foldDiacritics(input) {
5697
5673
  return input.normalize("NFKD").replace(/[̀-ͯ]/g, "");
5698
5674
  }
@@ -5961,14 +5937,6 @@ function refineHubAsCodeResources(config, ctx) {
5961
5937
  });
5962
5938
  }
5963
5939
  }
5964
- function isSafeTemplatePath(path31) {
5965
- if (path31.length === 0 || path31.length > 300) return false;
5966
- if (path31.startsWith("/") || path31.includes("\\")) return false;
5967
- const segments = path31.split("/");
5968
- return segments.every(
5969
- (seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
5970
- );
5971
- }
5972
5940
  function identifyTokenType(token) {
5973
5941
  if (token.startsWith("way_")) return "way_token";
5974
5942
  if (token.startsWith("eyJ")) return "jwt";
@@ -6008,7 +5976,7 @@ function findStepBoundaries(transcript) {
6008
5976
  }
6009
5977
  return out;
6010
5978
  }
6011
- var UUID_RE, HEX_RE, WORKOS_ID_RE, OPAQUE_SECRET_RE, BASE64_SECRET_RE, BASE64_MARKER_RE, TOKEN_RE, SENSITIVE_FIELDS, SENSITIVE_KEY_ALTERNATION, SENSITIVE_KEY_PATTERN, JSON_CREDENTIAL_RE, QUERY_CREDENTIAL_RE, REDACTED, PROVIDER_TOKEN_RE, APP_ERROR_BRAND, AppError, LLM_RATE_LIMIT_BRAND, LlmRateLimitError, LLM_PROVIDER_HTTP_BRAND, LlmProviderHttpError, LLM_PROVIDER_CONTENT_BRAND, LlmProviderContentError, LLM_PROVIDER_TIMEOUT_BRAND, LlmProviderTimeoutError, ExternalServiceError, CHANNEL_PROVIDER_HTTP_BRAND, ChannelProviderHttpError, MEDIA_PROVIDER_HTTP_BRAND, MediaProviderHttpError, AUTH_TYPE, ORG_CREDENTIAL_AUTH_TYPES, AUTH_TYPE_DISPLAY, LEGACY_AUTH_TYPE_MAP, VALID_AUTH_TYPES, AGENT_ROLES, SAFE_USER_ID_REGEX, SUPPORTED_LOCALES, uuidSchema, paginationSchema, timestampSchema, idParamSchema, clientOptionalString, clientOptionalBoolean, clientOptionalNumber, messageAttachment, MAX_MESSAGE_BODY_BYTES, MAX_ATTACHMENTS_PER_MESSAGE, MAX_AUDIO_FILE_BASE64_BYTES, primaryRegionSchema, placementSourceSchema, orgIdParam, orgAdminIdParam, createOrganizationBody, updateOrganizationBody, addOrgAdminBody, SUMMARIZATION_THRESHOLD_MIN, SUMMARIZATION_THRESHOLD_MAX, summarizationThresholdField, monitorConfigField, agentIdParam, listAgentsQuery, agentConnectionsQuery, createAgentBody, updateAgentBody, AGENT_PARAMETER_TYPES, AGENT_PARAMETER_NAME_REGEX, agentParameterCreateSchema, MAX_AGENT_PARAMETERS_PER_REQUEST, createAgentParametersBody, SLUG_REGEX, slugSchema, INVISIBLE_NAME_CHARS, MAX_KANBAN_STATUSES, MAX_FOLLOWUPS_PER_STATUS, MAX_LANES, MAX_ADDITIONAL_CONTEXT_SCHEMA_BYTES, RESERVED_TEMPLATE_DUMP_NAME, kanbanStatusSlugSchema, followupSchema, EXCLUSIVE_FLAG_PAIRS, kanbanStatusSchema, kanbanStatusesArraySchema, laneSchema, lanesArraySchema, hubIdParam, hubAdminIdParam, hubUserIdParam, hubIdentityIdParam, hubTeamIdParam, hubTeamUserDeleteParam, hubSchemaQuery, PREVIEW_LABEL_MAX_LENGTH, MAX_ENDED_INDEX_RETENTION_DAYS, previewLabelField, createHubBody, updateHubBody, addHubAdminBody, addHubIdentityAuthorizationBody, contactDecisionBody, approveContactBody, listContactAccessQuery, createHubTeamBody, updateHubTeamBody, addHubTeamUserBody, reassignHubUserBody, replicatePreviewBody, updateChannelTestIdentitiesBody, claimCodeChannelParam, claimCodeDeleteParam, connectionIdParam, connectorIdParam, listConnectionsQuery, deleteConnectionQuery, addConnectionBody, editConnectionBody, PRODUCTION_DIRECT_FIELDS, setProductionCredentialBody, registerWhatsappQuery, registerWhatsappBody, retryProvisioningQuery, resendDomainStatusQuery, PLACEHOLDER_TOKENS, ALLOWED_TYPES, SUBSCHEMA_OBJECT_KEYWORDS, SUBSCHEMA_LIST_KEYWORDS, SUBSCHEMA_MAP_KEYWORDS, MAX_SCHEMA_DEPTH, toolIdParam, listToolsQuery, toolAgentQuery, deleteToolQuery, toolConnectionsQuery, nativeToolIdSchema, addNativeToolBody, addMcpToolBody, createCustomToolBody, updateCustomToolBody, updateToolExecutionConfigBody, initialValueCreateSchema, initialValueUpdateSchema, stateIdParam, listStatesQuery, stateNameSchema, createStateBody, updateStateBody, reorderStatesBody, variantAiModeSchema, experimentStatusSchema, overlayUpdateSchema, experimentIdParam, variantIdParam, listExperimentsQuery, listVariantsQuery, listOverridesQuery, deleteOverrideQuery, createExperimentBody, updateExperimentBody, setExperimentStatusBody, createVariantBody, updateVariantBody, upsertOverrideBody, orgTagIdParam, listOrgTagsQuery, createOrgTagBody, updateOrgTagBody, orgCredentialIdParam, listOrgCredentialsQuery, createOrgCredentialBody, updateOrgCredentialBody, orgResourceIdParam, orgResourceFileIdParam, orgResourceFolderIdParam, hubOrgResourceParam, listOrgResourcesQuery, orgIdQuery, createOrgResourceBody, updateOrgResourceBody, createOrgResourceFolderBody, updateOrgResourceFolderBody, uploadOrgResourceFileBody, updateOrgResourceFileBody, uploadOrgSkillZipBody, linkOrgResourceBody, resourceIdParam, listResourcesQuery, createResourceBody, updateResourceBody, syncSkillsBody, resourceFileIdParam, listResourceFilesQuery, createResourceFileBody, updateResourceFileBody, uploadResourceFileBody, uploadSkillZipBody, resourceFolderIdParam, listResourceFoldersQuery, createResourceFolderBody, updateResourceFolderBody, agentResourceQuery, hubResourceQuery, linkAgentResourceBody, updateAgentResourceBody, unlinkAgentResourceQuery, navItemSchema, hubCountResetBody, navItemCountResetBody, typingBody, analyticsHubIdParam, analyticsVariableIdParam, updateVariablePinBody, updateAnalyticsViewBody, NUMERIC_FILTER_OPS, TEXT_FILTER_OPS, CATEGORICAL_FILTER_OPS, VARIABLE_FILTER_OPS, STRUCTURED_QUERY_OPS, STRUCTURED_QUERY_AGGREGATIONS, filterValueSchema, conversationsBody, analyticsConversationIdParam, messagesQuery, conversationDetailDataQuery, analyticsDataBody, structuredQueryBody, analyticsSqlBody, analyticsSqlSchemaQuery, EVAL_PACING_PRESET_NAMES, PACING_INTERVAL_MIN_MS, PACING_INTERVAL_MAX_MS, EVAL_RUN_DEADLINE_MIN_MS, EVAL_RUN_DEADLINE_MAX_MS, paginationSchema2, evalIdParam, sessionIdParam, scenarioSetIdParam, hubIdQuery, EVAL_INPUT_ROLES, EVAL_INPUT_ROLE_LIST, ROLE_ECHO_MAX, EVAL_INITIAL_STATE_SCOPES, MAX_INITIAL_STATE_ENTRIES, evalInitialStateEntry, createEvalBody, updateEvalBody, getEvalsQuery, toggleEvalBody, bulkToggleEvalsBody, pacingConfigSchema, 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, getConversationsQuery, getMessagesQuery, appMessageSenderType, appMessageReceiverType, appMessageBody, updateUserBody, updateProfileBody, pathnameRegex, updatePreferencesBody, registerPushTokenBody, deletePushTokenQuery, activityQuery, deletionModeSchema, deletionRequestBody, archiveHubIdParam, archiveConversationParams, archiveListQuery, archiveMessageObservabilityParams, conversationIdParam, claimBody, releaseBody, transferBody, closeBody, additionalContextPayloadSchema, kanbanUpdateBody, annotateConversationBody, observabilityParams, observabilityListParams, deleteUserConversationsBody, sendMessageBody, listConversationsQuery, getConversationDetailParams, getConversationDetailQuery, listWhatsAppTemplatesQuery, sendWhatsAppTemplateBody, billingOrgIdParam, subscriptionItemParams, spendCapBody, growthPacksBody, portalSessionBody, checkoutSessionBody, updateBillingCurrencyBody, invoicesQuery, downloadBody, uploadQuery, signUrlBody, outboundSchemaQuery, templateIdParam, listTemplatesQuery, deleteTemplateQuery, templateStatusQuery, createTemplateBody, updateTemplateBody, submitTemplateBody, testTemplateBody, contactIdParam, listContactsQuery, createContactBody, updateContactBody, listIdParam, listListsQuery, listListContactsQuery, createListBody, updateListBody, addListContactsBody, removeListContactsBody, scheduleIdParam, listSchedulesQuery, listExecutionsQuery, createScheduleBody, updateScheduleBody, MAX_RESOURCE_FILE_SIZE, MAX_10MB_BASE64_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_CARRIERS, MAX_EVAL_ATTACHMENT_AGGREGATE_ENCODED_BYTES, MAX_RESOURCE_ENCODED_BYTES, MAX_HUB_AS_CODE_RESOURCES, MAX_HUB_AS_CODE_RESOURCE_FILES, MAX_RESOURCE_AGGREGATE_ENCODED_BYTES, MAX_CI_CONFIG_BODY_BYTES, hubAsCodeResourceFileSchema, hubAsCodeResourceSchema, uuidPattern, ciUuidSchema, boundedHubAsCodeResourcesSchema, hubAsCodeConfigSchema, ciPullHubIdParam, ciBranchParam, ciPullQuery, ciHubsQuery, ciLookupQuery, ciBranchesQuery, ciSyncBody, ciPushBody, ciDiffBody, ciPublishBody, ciPublishPreviewBody, ciSyncMcpBody, ciOrgResourcesParam, orgResourcesConfigSchema, ciOrgResourcesPushBody, ciOrgResourcesDiffBody, adminOrgIdParam, adminOrgAdminIdParam, adminUserIdParam, adminPlanIdParam, adminHubIdParam, adminOrganizationsQuery, adminUserSearchQuery, kanbanSlugMigrationQuery, adjustQuotaBody, updatePlanBody, addAdminUserBody, updatePlatformConfigBody, updateFreeOrgLimitBody, adminSetOrgHarnessBody, adminSetHubHarnessBody, adminScopedTargetBody, updatePricingPlanBody, dataExplorerSearchQuery, dataExplorerOrgIdParam, dataExplorerHubIdParam, dataExplorerConvIdParam, dataExplorerDoInstancesQuery, dataExplorerNsIdParam, dataExplorerKvKeysQuery, dataExplorerKvKeyParam, uuidOrHexId, dataExplorerDeleteOrgParam, dataExplorerDeleteHubParam, dataExplorerDeleteConvParam, dataExplorerDeleteUserParam, dataExplorerDeleteQuery, dataExplorerKvDeleteQuery, pitrDoNamespace, pitrBookmarkParam, pitrRestoreBody, healthSamplingTriggerBody, dataExplorerDebugDoType, DEBUG_READ_MAX_LIMIT, DEBUG_READ_DEFAULT_LIMIT, DEBUG_DO_HEX_PREFIX, debugDoEntityId, debugTableName, dataExplorerDebugTablesParam, dataExplorerDebugRowsParam, dataExplorerDebugRowsQuery, dataExplorerDebugAnalyticsTable, debugUuid, dataExplorerDebugAnalyticsRowsParam, dataExplorerDebugAnalyticsRowsQuery, debugHubConvParam, debugMessageIdQuery, sandboxEgressPolicy, SANDBOX_EXEC_MAX_CMD_LENGTH, SANDBOX_EXEC_MAX_ALLOWLIST, SANDBOX_EXEC_MAX_TIMEOUT_MS, adminSandboxExecBody, whatsappCallbackBody, authMeResponse, wsTicketResponse, sessionCheckResponse, logoutResponse, magicCodeSendBody, magicCodeSendResponse, magicCodeVerifyBody, magicCodeVerifyResponse, browserParams, browserFoldersQuery, browserFilesQuery, stateOperationBody, conversationListResourcesQuery, conversationReadResourceQuery, listPendingSchedulesQuery, listHubAggregateSchedulesQuery, reportSourceSchema, intakeReportSourceSchema, reportClassificationSchema, reportStatusSchema, reportLocaleSchema, reportMessageAuthorRoleSchema, reportMessageSchema, sentryRefStatusSchema, createReportBody, editReportBody, reporterReportSummarySchema, reporterListResponseSchema, getReportResponseSchema, reporterTransitionResponseSchema, contestReportBody, reporterListQuery, listReportsQuery, GITHUB_ISSUE_URL_REGEX, githubIssueUrlSchema, transitionReportBody, groupReportsBody, holdReportBody, clickhouseReadyResponse, bootstrapQuery, requestSnapshotChunkMessage, MAX_NAME_LENGTH, MAX_VALUE_LENGTH, MAX_TAGS, MAX_TAG_LENGTH, MAX_SCOPE_HUBS, MAX_SCOPE_TAGS, vaultSecretScopeSchema, vaultCreateBody, vaultUpdateBody, PERMISSIONS, MAX_NAME_LENGTH2, MAX_HUBS_PER_GRANT, MAX_HUB_TAGS_PER_GRANT, MAX_GRANTS, permissionEnum, grantScopeSchema, grantSchema, createTokenBody, tokenOrgIdParam, tokenGrantScopeSchema, tokenGrantSchema, tokenMetadataSchema, listTokensResponse, createTokenResponse, orgTokenSummarySchema, listOrgTokensResponse, invitePreviewQuery, invitePreviewResponse, discordTier, discordBillingCycle, discordMetadata, discordOAuthStartResponse, discordOAuthFinalizeBody, discordOAuthFinalizeResponse, discordDisconnectResponse, jsonSchemaSchema, hubUserIdentity, stateValueEntry, getHubUserContextResponse, updateHubUserBody, updateHubUserResponse, unlockHubUserNameResponse, stateResetParams, stateResetResponse, hubAlertsParam, hubAlertSeverity, hubAlert, hubAlertsListResponse, noticeSeveritySchema, noticeStatusSchema, NOTICE_SCOPE_REGEX, noticeScopeSchema, noticeLinkSchema, createNoticeBody, updateNoticeBody, listNoticesQuery, noticeIdParamSchema, templateLocaleSchema, TEMPLATE_SLUG_REGEX, templateSlugSchema, templateStatusSchema, templateFileMapSchema, templateTextSchema, templateUsesEntrySchema, templateUsesSchema, templateYamlLocaleEntry, templateYamlWayaiBlock, templateTagsSchema, templateYamlSchema, templateHeroSchema, templatePushLocaleSchema, templatePushBody, templateListQuery, templateSlugParam, templateDetailQuery, ADMIN_SKILL_NAME_REGEX, adminSkillNameParam, WAYAI_WORKSPACE_LAYOUT;
5979
+ var UUID_RE, HEX_RE, WORKOS_ID_RE, OPAQUE_SECRET_RE, BASE64_SECRET_RE, BASE64_MARKER_RE, TOKEN_RE, SENSITIVE_FIELDS, SENSITIVE_KEY_ALTERNATION, SENSITIVE_KEY_PATTERN, JSON_CREDENTIAL_RE, QUERY_CREDENTIAL_RE, REDACTED, PROVIDER_TOKEN_RE, APP_ERROR_BRAND, AppError, LLM_RATE_LIMIT_BRAND, LlmRateLimitError, LLM_PROVIDER_HTTP_BRAND, LlmProviderHttpError, LLM_PROVIDER_CONTENT_BRAND, LlmProviderContentError, LLM_PROVIDER_TIMEOUT_BRAND, LlmProviderTimeoutError, ExternalServiceError, CHANNEL_PROVIDER_HTTP_BRAND, ChannelProviderHttpError, MEDIA_PROVIDER_HTTP_BRAND, MediaProviderHttpError, AUTH_TYPE, ORG_CREDENTIAL_AUTH_TYPES, AUTH_TYPE_DISPLAY, LEGACY_AUTH_TYPE_MAP, VALID_AUTH_TYPES, AGENT_ROLES, SAFE_USER_ID_REGEX, SUPPORTED_LOCALES, uuidSchema, paginationSchema, timestampSchema, idParamSchema, clientOptionalString, clientOptionalBoolean, clientOptionalNumber, messageAttachment, MAX_MESSAGE_BODY_BYTES, MAX_ATTACHMENTS_PER_MESSAGE, MAX_AUDIO_FILE_BASE64_BYTES, primaryRegionSchema, placementSourceSchema, orgIdParam, orgAdminIdParam, createOrganizationBody, updateOrganizationBody, addOrgAdminBody, SUMMARIZATION_THRESHOLD_MIN, SUMMARIZATION_THRESHOLD_MAX, summarizationThresholdField, monitorConfigField, agentIdParam, listAgentsQuery, agentConnectionsQuery, createAgentBody, updateAgentBody, AGENT_PARAMETER_TYPES, AGENT_PARAMETER_NAME_REGEX, agentParameterCreateSchema, MAX_AGENT_PARAMETERS_PER_REQUEST, createAgentParametersBody, SLUG_REGEX, slugSchema, INVISIBLE_NAME_CHARS, MAX_KANBAN_STATUSES, MAX_FOLLOWUPS_PER_STATUS, MAX_LANES, MAX_ADDITIONAL_CONTEXT_SCHEMA_BYTES, RESERVED_TEMPLATE_DUMP_NAME, kanbanStatusSlugSchema, followupSchema, MAX_OUTCOMES_PER_STATUS, kanbanOutcomeSchema, EXCLUSIVE_FLAG_PAIRS, kanbanStatusSchema, kanbanStatusesArraySchema, laneSchema, lanesArraySchema, hubIdParam, hubAdminIdParam, hubUserIdParam, hubIdentityIdParam, hubTeamIdParam, hubTeamUserDeleteParam, hubSchemaQuery, PREVIEW_LABEL_MAX_LENGTH, MAX_ENDED_INDEX_RETENTION_DAYS, previewLabelField, createHubBody, updateHubBody, addHubAdminBody, addHubIdentityAuthorizationBody, contactDecisionBody, approveContactBody, listContactAccessQuery, createHubTeamBody, updateHubTeamBody, addHubTeamUserBody, reassignHubUserBody, replicatePreviewBody, updateChannelTestIdentitiesBody, claimCodeChannelParam, claimCodeDeleteParam, connectionIdParam, connectorIdParam, listConnectionsQuery, deleteConnectionQuery, addConnectionBody, editConnectionBody, PRODUCTION_DIRECT_FIELDS, setProductionCredentialBody, registerWhatsappQuery, registerWhatsappBody, retryProvisioningQuery, resendDomainStatusQuery, PLACEHOLDER_TOKENS, ALLOWED_TYPES, SUBSCHEMA_OBJECT_KEYWORDS, SUBSCHEMA_LIST_KEYWORDS, SUBSCHEMA_MAP_KEYWORDS, MAX_SCHEMA_DEPTH, toolIdParam, listToolsQuery, toolAgentQuery, deleteToolQuery, toolConnectionsQuery, nativeToolIdSchema, addNativeToolBody, addMcpToolBody, createCustomToolBody, updateCustomToolBody, updateToolExecutionConfigBody, initialValueCreateSchema, initialValueUpdateSchema, stateIdParam, listStatesQuery, stateNameSchema, createStateBody, updateStateBody, reorderStatesBody, variantAiModeSchema, experimentStatusSchema, overlayUpdateSchema, experimentIdParam, variantIdParam, listExperimentsQuery, listVariantsQuery, listOverridesQuery, deleteOverrideQuery, createExperimentBody, updateExperimentBody, setExperimentStatusBody, createVariantBody, updateVariantBody, upsertOverrideBody, orgTagIdParam, listOrgTagsQuery, createOrgTagBody, updateOrgTagBody, orgCredentialIdParam, listOrgCredentialsQuery, createOrgCredentialBody, updateOrgCredentialBody, orgResourceIdParam, orgResourceFileIdParam, orgResourceFolderIdParam, hubOrgResourceParam, listOrgResourcesQuery, orgIdQuery, createOrgResourceBody, updateOrgResourceBody, createOrgResourceFolderBody, updateOrgResourceFolderBody, uploadOrgResourceFileBody, updateOrgResourceFileBody, uploadOrgSkillZipBody, linkOrgResourceBody, resourceIdParam, listResourcesQuery, createResourceBody, updateResourceBody, syncSkillsBody, resourceFileIdParam, listResourceFilesQuery, createResourceFileBody, updateResourceFileBody, uploadResourceFileBody, uploadSkillZipBody, resourceFolderIdParam, listResourceFoldersQuery, createResourceFolderBody, updateResourceFolderBody, agentResourceQuery, hubResourceQuery, linkAgentResourceBody, updateAgentResourceBody, unlinkAgentResourceQuery, navItemSchema, hubCountResetBody, navItemCountResetBody, typingBody, analyticsHubIdParam, analyticsVariableIdParam, updateVariablePinBody, updateAnalyticsViewBody, NUMERIC_FILTER_OPS, TEXT_FILTER_OPS, CATEGORICAL_FILTER_OPS, VARIABLE_FILTER_OPS, STRUCTURED_QUERY_OPS, STRUCTURED_QUERY_AGGREGATIONS, filterValueSchema, conversationsBody, analyticsConversationIdParam, messagesQuery, conversationDetailDataQuery, analyticsDataBody, structuredQueryBody, analyticsSqlBody, analyticsSqlSchemaQuery, EVAL_PACING_PRESET_NAMES, PACING_INTERVAL_MIN_MS, PACING_INTERVAL_MAX_MS, EVAL_RUN_DEADLINE_MIN_MS, EVAL_RUN_DEADLINE_MAX_MS, paginationSchema2, evalIdParam, sessionIdParam, scenarioSetIdParam, hubIdQuery, EVAL_INPUT_ROLES, EVAL_INPUT_ROLE_LIST, ROLE_ECHO_MAX, EVAL_INITIAL_STATE_SCOPES, MAX_INITIAL_STATE_ENTRIES, evalInitialStateEntry, createEvalBody, updateEvalBody, getEvalsQuery, toggleEvalBody, bulkToggleEvalsBody, pacingConfigSchema, 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, getConversationsQuery, getMessagesQuery, appMessageSenderType, appMessageReceiverType, apiChannelMessage, apiChannelMessageBody, appMessageBody, updateUserBody, updateProfileBody, pathnameRegex, updatePreferencesBody, registerPushTokenBody, deletePushTokenQuery, activityQuery, deletionModeSchema, deletionRequestBody, templateLocaleSchema, TEMPLATE_SLUG_REGEX, templateSlugSchema, templateStatusSchema, templateFileMapSchema, templateTextSchema, templateUsesEntrySchema, templateUsesSchema, templateYamlLocaleEntry, templateYamlWayaiBlock, templateTagsSchema, templateYamlSchema, templateHeroSchema, templatePushLocaleSchema, templatePushBody, templateListQuery, templateSlugParam, templateDetailQuery, courseQuizScoreSchema, upsertCourseLessonBody, linkCourseCapstoneBody, archiveHubIdParam, archiveConversationParams, archiveListQuery, archiveMessageObservabilityParams, conversationIdParam, claimBody, releaseBody, transferBody, closeBody, additionalContextPayloadSchema, kanbanUpdateBody, annotateConversationBody, observabilityParams, observabilityListParams, deleteUserConversationsBody, sendMessageBody, listConversationsQuery, getConversationDetailParams, getConversationDetailQuery, listWhatsAppTemplatesQuery, sendWhatsAppTemplateBody, billingOrgIdParam, subscriptionItemParams, spendCapBody, growthPacksBody, portalSessionBody, checkoutSessionBody, updateBillingCurrencyBody, invoicesQuery, downloadBody, uploadQuery, signUrlBody, outboundSchemaQuery, templateIdParam, listTemplatesQuery, deleteTemplateQuery, templateStatusQuery, createTemplateBody, updateTemplateBody, submitTemplateBody, testTemplateBody, contactIdParam, listContactsQuery, createContactBody, updateContactBody, listIdParam, listListsQuery, listListContactsQuery, createListBody, updateListBody, addListContactsBody, removeListContactsBody, scheduleIdParam, listSchedulesQuery, listExecutionsQuery, createScheduleBody, updateScheduleBody, MAX_RESOURCE_FILE_SIZE, MAX_10MB_BASE64_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_CARRIERS, MAX_EVAL_ATTACHMENT_AGGREGATE_ENCODED_BYTES, MAX_RESOURCE_ENCODED_BYTES, MAX_HUB_AS_CODE_RESOURCES, MAX_HUB_AS_CODE_RESOURCE_FILES, MAX_RESOURCE_AGGREGATE_ENCODED_BYTES, MAX_CI_CONFIG_BODY_BYTES, hubAsCodeResourceFileSchema, hubAsCodeResourceSchema, uuidPattern, ciUuidSchema, boundedHubAsCodeResourcesSchema, hubAsCodeConfigSchema, ciPullHubIdParam, ciBranchParam, ciPullQuery, ciHubsQuery, ciLookupQuery, ciBranchesQuery, ciSyncBody, ciPushBody, ciDiffBody, ciPublishBody, ciPublishPreviewBody, ciSyncMcpBody, ciOrgResourcesParam, orgResourcesConfigSchema, ciOrgResourcesPushBody, ciOrgResourcesDiffBody, adminOrgIdParam, adminOrgAdminIdParam, adminUserIdParam, adminPlanIdParam, adminOrganizationsQuery, adminUserSearchQuery, kanbanSlugMigrationQuery, adjustQuotaBody, updatePlanBody, addAdminUserBody, updatePlatformConfigBody, updateFreeOrgLimitBody, adminScopedTargetBody, updatePricingPlanBody, dataExplorerSearchQuery, dataExplorerOrgIdParam, dataExplorerHubIdParam, dataExplorerConvIdParam, dataExplorerDoInstancesQuery, dataExplorerNsIdParam, dataExplorerKvKeysQuery, dataExplorerKvKeyParam, uuidOrHexId, dataExplorerDeleteOrgParam, dataExplorerDeleteHubParam, dataExplorerDeleteConvParam, dataExplorerDeleteUserParam, dataExplorerDeleteQuery, dataExplorerKvDeleteQuery, pitrDoNamespace, pitrBookmarkParam, pitrRestoreBody, healthSamplingTriggerBody, dataExplorerDebugDoType, DEBUG_READ_MAX_LIMIT, DEBUG_READ_DEFAULT_LIMIT, DEBUG_DO_HEX_PREFIX, debugDoEntityId, debugTableName, dataExplorerDebugTablesParam, dataExplorerDebugRowsParam, dataExplorerDebugRowsQuery, dataExplorerDebugAnalyticsTable, debugUuid, dataExplorerDebugAnalyticsRowsParam, dataExplorerDebugAnalyticsRowsQuery, debugHubConvParam, debugMessageIdQuery, sandboxEgressPolicy, SANDBOX_EXEC_MAX_CMD_LENGTH, SANDBOX_EXEC_MAX_ALLOWLIST, SANDBOX_EXEC_MAX_TIMEOUT_MS, adminSandboxExecBody, whatsappCallbackBody, authMeResponse, wsTicketResponse, sessionCheckResponse, logoutResponse, magicCodeSendBody, magicCodeSendResponse, magicCodeVerifyBody, magicCodeVerifyResponse, passwordLoginBody, browserParams, browserFoldersQuery, browserFilesQuery, stateOperationBody, conversationListResourcesQuery, conversationReadResourceQuery, listPendingSchedulesQuery, listHubAggregateSchedulesQuery, reportSourceSchema, intakeReportSourceSchema, reportClassificationSchema, reportStatusSchema, reportLocaleSchema, reportMessageAuthorRoleSchema, reportMessageSchema, sentryRefStatusSchema, createReportBody, editReportBody, reporterReportSummarySchema, reporterListResponseSchema, getReportResponseSchema, reporterTransitionResponseSchema, contestReportBody, reporterListQuery, listReportsQuery, GITHUB_ISSUE_URL_REGEX, githubIssueUrlSchema, transitionReportBody, groupReportsBody, holdReportBody, clickhouseReadyResponse, bootstrapQuery, requestSnapshotChunkMessage, MAX_NAME_LENGTH, MAX_VALUE_LENGTH, MAX_TAGS, MAX_TAG_LENGTH, MAX_SCOPE_HUBS, MAX_SCOPE_TAGS, vaultSecretScopeSchema, vaultCreateBody, vaultUpdateBody, PERMISSIONS, MAX_NAME_LENGTH2, MAX_HUBS_PER_GRANT, MAX_HUB_TAGS_PER_GRANT, MAX_GRANTS, permissionEnum, grantScopeSchema, grantSchema, createTokenBody, tokenOrgIdParam, tokenGrantScopeSchema, tokenGrantSchema, tokenMetadataSchema, listTokensResponse, createTokenResponse, orgTokenSummarySchema, listOrgTokensResponse, invitePreviewQuery, invitePreviewResponse, discordTier, discordBillingCycle, discordMetadata, discordOAuthStartResponse, discordOAuthFinalizeBody, discordOAuthFinalizeResponse, discordDisconnectResponse, jsonSchemaSchema, hubUserIdentity, stateValueEntry, getHubUserContextResponse, updateHubUserBody, updateHubUserResponse, unlockHubUserNameResponse, stateResetParams, stateResetResponse, hubAlertsParam, hubAlertSeverity, hubAlert, hubAlertsListResponse, noticeSeveritySchema, noticeStatusSchema, NOTICE_SCOPE_REGEX, noticeScopeSchema, noticeLinkSchema, createNoticeBody, updateNoticeBody, listNoticesQuery, noticeIdParamSchema, ADMIN_SKILL_NAME_REGEX, adminSkillNameParam, WAYAI_WORKSPACE_LAYOUT;
6012
5980
  var init_dist = __esm({
6013
5981
  "../../packages/core/dist/index.js"() {
6014
5982
  "use strict";
@@ -6060,6 +6028,7 @@ var init_dist = __esm({
6060
6028
  init_zod();
6061
6029
  init_zod();
6062
6030
  init_zod();
6031
+ init_zod();
6063
6032
  UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
6064
6033
  HEX_RE = /^[0-9a-f]{16,}$/;
6065
6034
  WORKOS_ID_RE = /^(?:user|org)_[0-9A-HJKMNP-TV-Z]{26}$/;
@@ -6433,6 +6402,12 @@ var init_dist = __esm({
6433
6402
  });
6434
6403
  }
6435
6404
  });
6405
+ MAX_OUTCOMES_PER_STATUS = 20;
6406
+ kanbanOutcomeSchema = external_exports.object({
6407
+ slug: kanbanStatusSlugSchema,
6408
+ name: external_exports.string().min(1, "name is required").max(100, "name must be 100 characters or fewer").refine((v) => visibleLength(v) > 0, "name must not be blank"),
6409
+ color: external_exports.string().optional()
6410
+ }).passthrough();
6436
6411
  EXCLUSIVE_FLAG_PAIRS = [
6437
6412
  ["isInitialStatus", "triggersAgentResponse"],
6438
6413
  ["isInitialStatus", "allowsAgentUpdate"],
@@ -6468,7 +6443,10 @@ var init_dist = __esm({
6468
6443
  * and is not exposed to agents. The cross-reference invariant (must point at a
6469
6444
  * declared lane; the initial status must not have one) is enforced at the hub
6470
6445
  * level via `validateLaneReferences` — this schema only sees the status array. */
6471
- lane_slug: kanbanStatusSlugSchema.optional()
6446
+ lane_slug: kanbanStatusSlugSchema.optional(),
6447
+ /** Closing outcomes offered on the terminal transition. Only valid when
6448
+ * `isTerminalStatus === true` (enforced in the superRefine below). */
6449
+ outcomes: external_exports.array(kanbanOutcomeSchema).max(MAX_OUTCOMES_PER_STATUS, `outcomes must have at most ${MAX_OUTCOMES_PER_STATUS} entries`).optional()
6472
6450
  }).passthrough().superRefine((status, ctx) => {
6473
6451
  const label = status.name ? `"${status.name}"` : status.slug ? `"${status.slug}"` : "<unnamed>";
6474
6452
  for (const [a, b] of EXCLUSIVE_FLAG_PAIRS) {
@@ -6505,6 +6483,33 @@ var init_dist = __esm({
6505
6483
  });
6506
6484
  }
6507
6485
  }
6486
+ if (Array.isArray(status.outcomes) && status.outcomes.length > 0) {
6487
+ if (status.isTerminalStatus !== true) {
6488
+ ctx.addIssue({
6489
+ code: external_exports.ZodIssueCode.custom,
6490
+ path: ["outcomes"],
6491
+ message: `kanban status ${label}: outcomes are only allowed on the terminal status (set isTerminalStatus=true)`
6492
+ });
6493
+ }
6494
+ const seen = /* @__PURE__ */ new Map();
6495
+ status.outcomes.forEach((o, j) => {
6496
+ if (!o?.slug) return;
6497
+ const arr = seen.get(o.slug) ?? [];
6498
+ arr.push(j);
6499
+ seen.set(o.slug, arr);
6500
+ });
6501
+ for (const [slug, indices] of seen) {
6502
+ if (indices.length > 1) {
6503
+ for (const j of indices) {
6504
+ ctx.addIssue({
6505
+ code: external_exports.ZodIssueCode.custom,
6506
+ path: ["outcomes", j, "slug"],
6507
+ message: `kanban status ${label}: duplicate outcome slug "${slug}"`
6508
+ });
6509
+ }
6510
+ }
6511
+ }
6512
+ }
6508
6513
  });
6509
6514
  kanbanStatusesArraySchema = external_exports.array(kanbanStatusSchema).max(MAX_KANBAN_STATUSES, `kanban_statuses must have at most ${MAX_KANBAN_STATUSES} entries`).superRefine((statuses, ctx) => {
6510
6515
  if (statuses.length === 0) return;
@@ -6525,6 +6530,17 @@ var init_dist = __esm({
6525
6530
  });
6526
6531
  }
6527
6532
  }
6533
+ const terminalIndices = statuses.map((s, i) => ({ s, i })).filter(({ s }) => s.isTerminalStatus === true);
6534
+ if (terminalIndices.length > 1) {
6535
+ const slugs = terminalIndices.map(({ s }) => s.slug).join(", ");
6536
+ for (const { i } of terminalIndices) {
6537
+ ctx.addIssue({
6538
+ code: external_exports.ZodIssueCode.custom,
6539
+ path: [i, "isTerminalStatus"],
6540
+ message: `kanban_statuses: at most one status may have isTerminalStatus=true (found ${terminalIndices.length}: ${slugs})`
6541
+ });
6542
+ }
6543
+ }
6528
6544
  const seenSlugs = /* @__PURE__ */ new Map();
6529
6545
  statuses.forEach((s, i) => {
6530
6546
  const key = s.slug;
@@ -6630,6 +6646,13 @@ var init_dist = __esm({
6630
6646
  language: external_exports.enum(["en", "pt", "es"]).optional(),
6631
6647
  access_request_message: external_exports.string().max(1e3).nullable().optional(),
6632
6648
  access_approval_role: external_exports.enum(["admin", "team"]).optional(),
6649
+ // AI-failure escalation. When an LLM provider outage persists past this many
6650
+ // minutes the conversation escalates to the team; null → code default. The two
6651
+ // message fields override the localized (hub.language) delay / hand-off notices;
6652
+ // null → localized default. Bounds validated here so out-of-range never persists.
6653
+ ai_failure_escalation_minutes: external_exports.number().int().min(1).max(60).nullable().optional(),
6654
+ ai_delay_message: external_exports.string().max(1e3).nullable().optional(),
6655
+ ai_handoff_message: external_exports.string().max(1e3).nullable().optional(),
6633
6656
  // Native-completion fallback connection for a degraded harness turn (PR 2.10b).
6634
6657
  // A NATIVE LLM (Agent) connection id on this hub; validated at set-time on the REST
6635
6658
  // PATCH (setup/hubs.ts rejects a non-existent / non-Agent / harness id) and re-checked
@@ -6718,7 +6741,7 @@ var init_dist = __esm({
6718
6741
  hub_id: uuidSchema,
6719
6742
  sync_credentials_to_production: external_exports.boolean().optional()
6720
6743
  }).passthrough();
6721
- PRODUCTION_DIRECT_FIELDS = ["username", "api_key", "access_token", "password", "refresh_token", "webhook_secret_token"];
6744
+ PRODUCTION_DIRECT_FIELDS = ["username", "api_key", "access_token", "password", "refresh_token", "webhook_secret_token", "webhook_signing_secret"];
6722
6745
  setProductionCredentialBody = external_exports.object({
6723
6746
  hub_id: uuidSchema,
6724
6747
  organization_credential_id: external_exports.string().nullable().optional(),
@@ -6728,7 +6751,8 @@ var init_dist = __esm({
6728
6751
  access_token: external_exports.string().optional(),
6729
6752
  password: external_exports.string().optional(),
6730
6753
  refresh_token: external_exports.string().optional(),
6731
- webhook_secret_token: external_exports.string().optional()
6754
+ webhook_secret_token: external_exports.string().optional(),
6755
+ webhook_signing_secret: external_exports.string().optional()
6732
6756
  }).strict().superRefine((data, ctx) => {
6733
6757
  const hasOrgLink = !!data.organization_credential_id || !!data.organization_credential_token_id;
6734
6758
  const hasDirect = PRODUCTION_DIRECT_FIELDS.some((f) => data[f] != null);
@@ -7583,6 +7607,38 @@ var init_dist = __esm({
7583
7607
  });
7584
7608
  appMessageSenderType = external_exports.enum(["user", "team"]);
7585
7609
  appMessageReceiverType = external_exports.enum(["user", "team", "agent", "assistant"]).transform((v) => v === "assistant" ? "agent" : v);
7610
+ apiChannelMessage = external_exports.object({
7611
+ text: clientOptionalString,
7612
+ attachments: external_exports.array(messageAttachment).max(MAX_ATTACHMENTS_PER_MESSAGE).nullish().transform((v) => v ?? void 0)
7613
+ }).refine((m) => m.text && m.text.length > 0 || m.attachments && m.attachments.length > 0, {
7614
+ message: "message must have text or at least one attachment"
7615
+ });
7616
+ apiChannelMessageBody = external_exports.object({
7617
+ // Correlation id (task hubs): new → new conversation, repeat → continue. min 1 so an
7618
+ // empty string can't masquerade as a ref. Mutually exclusive with conversation_id.
7619
+ external_ref: external_exports.string().min(1).max(256).optional(),
7620
+ // Continue a specific WayAI conversation (authorized against the hub/channel + owner).
7621
+ // UUID-validated here (unlike the app channel, whose client we control): allocation
7622
+ // only treats a UUID-shaped id as a provided conversation, so a malformed id would
7623
+ // otherwise skip the owner guard and silently MINT a new conversation instead of
7624
+ // rejecting. A format 400 is shape-only — not an existence oracle (a valid-but-unknown
7625
+ // UUID still collapses to the opaque authorization error downstream).
7626
+ conversation_id: external_exports.string().uuid().optional(),
7627
+ // On-behalf-of end-user identity. Absent → per-connection service principal (task-hub
7628
+ // only; chat hub rejects with 422 in the route).
7629
+ user: external_exports.object({
7630
+ id: external_exports.string().min(1),
7631
+ email: clientOptionalString,
7632
+ name: clientOptionalString
7633
+ }).optional(),
7634
+ message: apiChannelMessage,
7635
+ // Idempotency key: maps to channel_message_sid; a retried POST echoes the original
7636
+ // message_id and skips billing / turn dispatch (dedupe in ConversationDO.storeMessage).
7637
+ client_message_id: external_exports.string().min(1).max(256).optional()
7638
+ }).refine((b) => !(b.external_ref && b.conversation_id), {
7639
+ message: "provide external_ref or conversation_id, not both",
7640
+ path: ["external_ref"]
7641
+ });
7586
7642
  appMessageBody = external_exports.object({
7587
7643
  // Message content — three historical aliases. All optional: an attachment-only
7588
7644
  // or voice-only message carries no text.
@@ -7658,6 +7714,95 @@ var init_dist = __esm({
7658
7714
  /** Type-to-confirm value; must equal the user's email (constant-time compared). */
7659
7715
  email_confirmation: external_exports.string().min(1).max(320)
7660
7716
  });
7717
+ templateLocaleSchema = external_exports.enum(SUPPORTED_LOCALES);
7718
+ TEMPLATE_SLUG_REGEX = /^[a-z0-9][a-z0-9-]{0,62}$/;
7719
+ templateSlugSchema = external_exports.string().regex(TEMPLATE_SLUG_REGEX, "slug must be lowercase alphanumeric with hyphens (max 63)");
7720
+ templateStatusSchema = external_exports.enum(["published", "draft", "internal"]);
7721
+ templateFileMapSchema = external_exports.record(external_exports.string()).refine((m) => Object.keys(m).every(isSafeTemplatePath), {
7722
+ message: 'file map contains an unsafe path (no absolute paths, "..", or backslashes)'
7723
+ });
7724
+ templateTextSchema = external_exports.object({
7725
+ metaTitle: external_exports.string().min(1).max(200),
7726
+ metaDescription: external_exports.string().max(1e3).default("")
7727
+ });
7728
+ templateUsesEntrySchema = external_exports.object({
7729
+ backend: templateSlugSchema,
7730
+ endpoint: templateSlugSchema
7731
+ });
7732
+ templateUsesSchema = external_exports.array(templateUsesEntrySchema).max(24).default([]);
7733
+ templateYamlLocaleEntry = templateTextSchema.extend({ source: external_exports.string().min(1) });
7734
+ templateYamlWayaiBlock = external_exports.object({
7735
+ installCommand: external_exports.string().min(1).max(300),
7736
+ locales: external_exports.record(templateLocaleSchema, templateYamlLocaleEntry)
7737
+ });
7738
+ templateTagsSchema = external_exports.array(external_exports.string().min(1).max(30)).max(12).default([]).transform((tags) => [...new Set(tags.map((t) => t.trim().toLowerCase()).filter(Boolean))]);
7739
+ templateYamlSchema = external_exports.object({
7740
+ slug: templateSlugSchema,
7741
+ category: external_exports.string().min(1).max(60),
7742
+ tags: templateTagsSchema,
7743
+ status: templateStatusSchema.default("draft"),
7744
+ order: external_exports.number().int().min(0).max(1e5).optional(),
7745
+ defaultLocale: templateLocaleSchema,
7746
+ hero: external_exports.string().optional(),
7747
+ // relative path to a hero image inside the template folder
7748
+ // The Rekor backend(s) this channel runs on (gh #2955). Locale-agnostic. The
7749
+ // cross-link + MCP endpoint are derived from each entry's slugs, never authored.
7750
+ uses: templateUsesSchema,
7751
+ // A WayAI template IS a WayAI channel — the wayai slice is required. (The old
7752
+ // Rekor-only store entry is gone: a pure Rekor backend lives only in Rekor's store.)
7753
+ wayai: templateYamlWayaiBlock
7754
+ }).refine((c) => Boolean(c.wayai.locales[c.defaultLocale]), {
7755
+ message: "`wayai.locales` must include the defaultLocale"
7756
+ });
7757
+ templateHeroSchema = external_exports.object({
7758
+ filename: external_exports.string().min(1).max(200).regex(/\.(png|jpe?g|webp|gif)$/i, "hero must be a raster image (png/jpg/webp/gif)"),
7759
+ dataBase64: external_exports.string().min(1).max(8e6)
7760
+ });
7761
+ templatePushLocaleSchema = external_exports.object({
7762
+ wayai: templateTextSchema.optional(),
7763
+ readmeMarkdown: external_exports.string().default(""),
7764
+ wayaiFiles: templateFileMapSchema.optional()
7765
+ });
7766
+ templatePushBody = external_exports.object({
7767
+ slug: templateSlugSchema,
7768
+ defaultLocale: templateLocaleSchema,
7769
+ common: external_exports.object({
7770
+ category: external_exports.string().min(1).max(60),
7771
+ tags: templateTagsSchema,
7772
+ status: templateStatusSchema,
7773
+ order: external_exports.number().int().min(0).max(1e5).default(0),
7774
+ // The WayAI install command (a WayAI template always has a wayai side). Kept
7775
+ // optional on the wire so a malformed manifest 400s on the field, not the body.
7776
+ installCommand: external_exports.string().min(1).max(300).optional(),
7777
+ hero: templateHeroSchema.optional(),
7778
+ // The channel→backend edge (gh #2955), locale-agnostic.
7779
+ uses: templateUsesSchema
7780
+ }),
7781
+ locales: external_exports.record(templateLocaleSchema, templatePushLocaleSchema)
7782
+ }).refine((b) => Boolean(b.locales[b.defaultLocale]), {
7783
+ message: "`locales` must include the defaultLocale"
7784
+ });
7785
+ templateListQuery = external_exports.object({ locale: templateLocaleSchema.optional() });
7786
+ templateSlugParam = external_exports.object({ slug: templateSlugSchema });
7787
+ templateDetailQuery = external_exports.object({ locale: templateLocaleSchema.optional() });
7788
+ courseQuizScoreSchema = external_exports.object({
7789
+ correct: external_exports.number().int().min(0).max(50),
7790
+ total: external_exports.number().int().min(1).max(50),
7791
+ /** Chosen choice index per question; -1 = unanswered. */
7792
+ answers: external_exports.array(external_exports.number().int().min(-1).max(50)).max(50).optional()
7793
+ });
7794
+ upsertCourseLessonBody = external_exports.object({
7795
+ quiz_passed: external_exports.boolean().optional(),
7796
+ quiz_score: courseQuizScoreSchema.optional(),
7797
+ content_version: external_exports.number().int().min(1)
7798
+ }).strict();
7799
+ linkCourseCapstoneBody = external_exports.object({
7800
+ hub_id: external_exports.string().min(1).max(128),
7801
+ // A capstone's slug IS a canonical template slug — reuse the one validator
7802
+ // the template pipeline (CLI, admin, gallery) already enforces, so course
7803
+ // linking can't drift from how real template slugs are shaped.
7804
+ template_slug: templateSlugSchema.optional()
7805
+ }).strict();
7661
7806
  archiveHubIdParam = external_exports.object({
7662
7807
  hubId: external_exports.string().uuid()
7663
7808
  });
@@ -7751,7 +7896,10 @@ var init_dist = __esm({
7751
7896
  user_id: external_exports.string().optional(),
7752
7897
  scheduled_event_date: external_exports.string().optional(),
7753
7898
  additional_context: additionalContextPayloadSchema.optional(),
7754
- event_description: external_exports.string().optional()
7899
+ event_description: external_exports.string().optional(),
7900
+ // Closing outcome slug — required by the server only when the target is the
7901
+ // terminal status AND it declares `outcomes`. 50-char slug cap + headroom.
7902
+ outcome: external_exports.string().max(64).optional()
7755
7903
  });
7756
7904
  annotateConversationBody = external_exports.object({
7757
7905
  hub_id: external_exports.string().uuid(),
@@ -8165,9 +8313,6 @@ var init_dist = __esm({
8165
8313
  adminPlanIdParam = external_exports.object({
8166
8314
  planId: uuidSchema
8167
8315
  });
8168
- adminHubIdParam = external_exports.object({
8169
- hubId: uuidSchema
8170
- });
8171
8316
  adminOrganizationsQuery = external_exports.object({
8172
8317
  page: external_exports.coerce.number().int().min(1).default(1),
8173
8318
  limit: external_exports.coerce.number().int().min(1).max(100).default(20),
@@ -8195,10 +8340,11 @@ var init_dist = __esm({
8195
8340
  /** Kill switch for admin debug-read endpoints. 0 = off, 1 = on. */
8196
8341
  debug_read_enabled: external_exports.number().int().min(0).max(1).optional(),
8197
8342
  /**
8198
- * Harness-agents rollout gate + kill switch (harness-agents PR 2.9a/2.9b). 0 = off
8199
- * (default-deny — the per-turn kill switch aborts every harness turn on its next
8200
- * invocation), 1 = on. `wayai admin harness disable|enable` flips this. The DO's
8201
- * `updatePlatformConfig` allowlist already accepts it; this exposes it on the route.
8343
+ * The harness rollout gate + kill switch — the ONLY harness gate. 0 = off
8344
+ * (default-deny: agent create/update is refused AND the per-turn kill switch
8345
+ * aborts every harness turn on its next invocation), 1 = on. `wayai admin harness
8346
+ * disable|enable` flips this. The DO's `updatePlatformConfig` allowlist already
8347
+ * accepts it; this exposes it on the route.
8202
8348
  */
8203
8349
  harness_enabled: external_exports.number().int().min(0).max(1).optional()
8204
8350
  }).strip().refine(
@@ -8208,12 +8354,6 @@ var init_dist = __esm({
8208
8354
  updateFreeOrgLimitBody = external_exports.object({
8209
8355
  max_free_orgs_override: external_exports.number().int().min(0).nullable()
8210
8356
  });
8211
- adminSetOrgHarnessBody = external_exports.object({
8212
- harness_enabled: external_exports.number().int().min(0).max(1)
8213
- }).strict();
8214
- adminSetHubHarnessBody = external_exports.object({
8215
- harness_enabled: external_exports.number().int().min(0).max(1)
8216
- }).strict();
8217
8357
  adminScopedTargetBody = external_exports.object({
8218
8358
  scope: external_exports.enum(["all", "org", "hub"]),
8219
8359
  org_id: external_exports.string().uuid().optional(),
@@ -8432,6 +8572,12 @@ var init_dist = __esm({
8432
8572
  access_token: external_exports.string(),
8433
8573
  refresh_token: external_exports.string()
8434
8574
  });
8575
+ passwordLoginBody = external_exports.object({
8576
+ email: external_exports.string().email("Invalid email").max(254),
8577
+ // RFC 5321 max; bounds the request payload
8578
+ password: external_exports.string().min(1, "Password is required").max(128)
8579
+ // bound the payload; WorkOS validates
8580
+ });
8435
8581
  browserParams = external_exports.object({
8436
8582
  hubId: uuidSchema,
8437
8583
  resourceId: uuidSchema
@@ -8873,77 +9019,6 @@ var init_dist = __esm({
8873
9019
  offset: external_exports.coerce.number().int().min(0).optional()
8874
9020
  });
8875
9021
  noticeIdParamSchema = external_exports.object({ id: external_exports.string().min(1) });
8876
- templateLocaleSchema = external_exports.enum(SUPPORTED_LOCALES);
8877
- TEMPLATE_SLUG_REGEX = /^[a-z0-9][a-z0-9-]{0,62}$/;
8878
- templateSlugSchema = external_exports.string().regex(TEMPLATE_SLUG_REGEX, "slug must be lowercase alphanumeric with hyphens (max 63)");
8879
- templateStatusSchema = external_exports.enum(["published", "draft", "internal"]);
8880
- templateFileMapSchema = external_exports.record(external_exports.string()).refine((m) => Object.keys(m).every(isSafeTemplatePath), {
8881
- message: 'file map contains an unsafe path (no absolute paths, "..", or backslashes)'
8882
- });
8883
- templateTextSchema = external_exports.object({
8884
- metaTitle: external_exports.string().min(1).max(200),
8885
- metaDescription: external_exports.string().max(1e3).default("")
8886
- });
8887
- templateUsesEntrySchema = external_exports.object({
8888
- backend: templateSlugSchema,
8889
- endpoint: templateSlugSchema
8890
- });
8891
- templateUsesSchema = external_exports.array(templateUsesEntrySchema).max(24).default([]);
8892
- templateYamlLocaleEntry = templateTextSchema.extend({ source: external_exports.string().min(1) });
8893
- templateYamlWayaiBlock = external_exports.object({
8894
- installCommand: external_exports.string().min(1).max(300),
8895
- locales: external_exports.record(templateLocaleSchema, templateYamlLocaleEntry)
8896
- });
8897
- templateTagsSchema = external_exports.array(external_exports.string().min(1).max(30)).max(12).default([]).transform((tags) => [...new Set(tags.map((t) => t.trim().toLowerCase()).filter(Boolean))]);
8898
- templateYamlSchema = external_exports.object({
8899
- slug: templateSlugSchema,
8900
- category: external_exports.string().min(1).max(60),
8901
- tags: templateTagsSchema,
8902
- status: templateStatusSchema.default("draft"),
8903
- order: external_exports.number().int().min(0).max(1e5).optional(),
8904
- defaultLocale: templateLocaleSchema,
8905
- hero: external_exports.string().optional(),
8906
- // relative path to a hero image inside the template folder
8907
- // The Rekor backend(s) this channel runs on (gh #2955). Locale-agnostic. The
8908
- // cross-link + MCP endpoint are derived from each entry's slugs, never authored.
8909
- uses: templateUsesSchema,
8910
- // A WayAI template IS a WayAI channel — the wayai slice is required. (The old
8911
- // Rekor-only store entry is gone: a pure Rekor backend lives only in Rekor's store.)
8912
- wayai: templateYamlWayaiBlock
8913
- }).refine((c) => Boolean(c.wayai.locales[c.defaultLocale]), {
8914
- message: "`wayai.locales` must include the defaultLocale"
8915
- });
8916
- templateHeroSchema = external_exports.object({
8917
- filename: external_exports.string().min(1).max(200).regex(/\.(png|jpe?g|webp|gif)$/i, "hero must be a raster image (png/jpg/webp/gif)"),
8918
- dataBase64: external_exports.string().min(1).max(8e6)
8919
- });
8920
- templatePushLocaleSchema = external_exports.object({
8921
- wayai: templateTextSchema.optional(),
8922
- readmeMarkdown: external_exports.string().default(""),
8923
- wayaiFiles: templateFileMapSchema.optional()
8924
- });
8925
- templatePushBody = external_exports.object({
8926
- slug: templateSlugSchema,
8927
- defaultLocale: templateLocaleSchema,
8928
- common: external_exports.object({
8929
- category: external_exports.string().min(1).max(60),
8930
- tags: templateTagsSchema,
8931
- status: templateStatusSchema,
8932
- order: external_exports.number().int().min(0).max(1e5).default(0),
8933
- // The WayAI install command (a WayAI template always has a wayai side). Kept
8934
- // optional on the wire so a malformed manifest 400s on the field, not the body.
8935
- installCommand: external_exports.string().min(1).max(300).optional(),
8936
- hero: templateHeroSchema.optional(),
8937
- // The channel→backend edge (gh #2955), locale-agnostic.
8938
- uses: templateUsesSchema
8939
- }),
8940
- locales: external_exports.record(templateLocaleSchema, templatePushLocaleSchema)
8941
- }).refine((b) => Boolean(b.locales[b.defaultLocale]), {
8942
- message: "`locales` must include the defaultLocale"
8943
- });
8944
- templateListQuery = external_exports.object({ locale: templateLocaleSchema.optional() });
8945
- templateSlugParam = external_exports.object({ slug: templateSlugSchema });
8946
- templateDetailQuery = external_exports.object({ locale: templateLocaleSchema.optional() });
8947
9022
  ADMIN_SKILL_NAME_REGEX = /^[a-z0-9][a-z0-9-]{0,63}$/;
8948
9023
  adminSkillNameParam = external_exports.object({
8949
9024
  name: external_exports.string().regex(ADMIN_SKILL_NAME_REGEX, "invalid skill name")
@@ -11740,6 +11815,44 @@ function collectTurnAttachmentHashes2(turn) {
11740
11815
  }
11741
11816
  return hashes;
11742
11817
  }
11818
+ function isSafeTemplatePath2(path31) {
11819
+ if (path31.length === 0 || path31.length > 300) return false;
11820
+ if (path31.startsWith("/") || path31.includes("\\")) return false;
11821
+ const segments = path31.split("/");
11822
+ return segments.every(
11823
+ (seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
11824
+ );
11825
+ }
11826
+ function dropTemplateKeys(value, drop) {
11827
+ if (Array.isArray(value)) return value.map((v) => dropTemplateKeys(v, drop));
11828
+ if (isPlainObject(value)) {
11829
+ const out = {};
11830
+ for (const [key, child] of Object.entries(value)) {
11831
+ if (drop.has(key)) continue;
11832
+ out[key] = TEMPLATE_OPAQUE_BLOB_KEYS.has(key) ? child : dropTemplateKeys(child, drop);
11833
+ }
11834
+ return out;
11835
+ }
11836
+ return value;
11837
+ }
11838
+ function stripTemplateInstanceIds(value) {
11839
+ return dropTemplateKeys(value, TEMPLATE_INSTANCE_ID_KEYS);
11840
+ }
11841
+ function excludeTemplateAuthorData(value) {
11842
+ return dropTemplateKeys(value, TEMPLATE_AUTHOR_DATA_KEYS);
11843
+ }
11844
+ function isPlainObject(value) {
11845
+ if (value === null || typeof value !== "object") return false;
11846
+ const proto = Object.getPrototypeOf(value);
11847
+ return proto === Object.prototype || proto === null;
11848
+ }
11849
+ function isSanitizableSliceFile(path31) {
11850
+ if (!/\.ya?ml$/i.test(path31)) return false;
11851
+ return path31 !== "resources" && !path31.startsWith("resources/");
11852
+ }
11853
+ function distinctUsesBackends(uses) {
11854
+ return [...new Set((uses ?? []).map((u) => u.backend))];
11855
+ }
11743
11856
  function refineHubAsCodeCustomTools2(config, ctx) {
11744
11857
  const agents = config.agents;
11745
11858
  if (!Array.isArray(agents)) return;
@@ -11982,45 +12095,7 @@ function refineHubAsCodeResources2(config, ctx) {
11982
12095
  });
11983
12096
  }
11984
12097
  }
11985
- function isSafeTemplatePath2(path31) {
11986
- if (path31.length === 0 || path31.length > 300) return false;
11987
- if (path31.startsWith("/") || path31.includes("\\")) return false;
11988
- const segments = path31.split("/");
11989
- return segments.every(
11990
- (seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
11991
- );
11992
- }
11993
- function dropTemplateKeys(value, drop) {
11994
- if (Array.isArray(value)) return value.map((v) => dropTemplateKeys(v, drop));
11995
- if (isPlainObject(value)) {
11996
- const out = {};
11997
- for (const [key, child] of Object.entries(value)) {
11998
- if (drop.has(key)) continue;
11999
- out[key] = TEMPLATE_OPAQUE_BLOB_KEYS.has(key) ? child : dropTemplateKeys(child, drop);
12000
- }
12001
- return out;
12002
- }
12003
- return value;
12004
- }
12005
- function stripTemplateInstanceIds(value) {
12006
- return dropTemplateKeys(value, TEMPLATE_INSTANCE_ID_KEYS);
12007
- }
12008
- function excludeTemplateAuthorData(value) {
12009
- return dropTemplateKeys(value, TEMPLATE_AUTHOR_DATA_KEYS);
12010
- }
12011
- function isPlainObject(value) {
12012
- if (value === null || typeof value !== "object") return false;
12013
- const proto = Object.getPrototypeOf(value);
12014
- return proto === Object.prototype || proto === null;
12015
- }
12016
- function isSanitizableSliceFile(path31) {
12017
- if (!/\.ya?ml$/i.test(path31)) return false;
12018
- return path31 !== "resources" && !path31.startsWith("resources/");
12019
- }
12020
- function distinctUsesBackends(uses) {
12021
- return [...new Set((uses ?? []).map((u) => u.backend))];
12022
- }
12023
- var uuidSchema2, paginationSchema3, timestampSchema2, idParamSchema2, clientOptionalString2, clientOptionalBoolean2, clientOptionalNumber2, messageAttachment2, MAX_MESSAGE_BODY_BYTES2, MAX_ATTACHMENTS_PER_MESSAGE2, MAX_AUDIO_FILE_BASE64_BYTES2, primaryRegionSchema2, placementSourceSchema2, orgIdParam2, orgAdminIdParam2, createOrganizationBody2, updateOrganizationBody2, addOrgAdminBody2, AUTH_TYPE3, ORG_CREDENTIAL_AUTH_TYPES3, AUTH_TYPE_DISPLAY3, LEGACY_AUTH_TYPE_MAP3, VALID_AUTH_TYPES3, AGENT_ROLES2, SAFE_USER_ID_REGEX2, SUPPORTED_LOCALES2, SUMMARIZATION_THRESHOLD_MIN2, SUMMARIZATION_THRESHOLD_MAX2, summarizationThresholdField2, monitorConfigField2, agentIdParam2, listAgentsQuery2, agentConnectionsQuery2, createAgentBody2, updateAgentBody2, AGENT_PARAMETER_TYPES2, AGENT_PARAMETER_NAME_REGEX2, agentParameterCreateSchema2, MAX_AGENT_PARAMETERS_PER_REQUEST2, createAgentParametersBody2, SLUG_REGEX2, slugSchema2, INVISIBLE_NAME_CHARS2, MAX_KANBAN_STATUSES2, MAX_FOLLOWUPS_PER_STATUS2, MAX_LANES2, MAX_ADDITIONAL_CONTEXT_SCHEMA_BYTES2, RESERVED_TEMPLATE_DUMP_NAME2, kanbanStatusSlugSchema2, followupSchema2, EXCLUSIVE_FLAG_PAIRS2, kanbanStatusSchema2, kanbanStatusesArraySchema2, laneSchema2, lanesArraySchema2, hubIdParam2, hubAdminIdParam2, hubUserIdParam2, hubIdentityIdParam2, hubTeamIdParam2, hubTeamUserDeleteParam2, hubSchemaQuery2, PREVIEW_LABEL_MAX_LENGTH2, MAX_ENDED_INDEX_RETENTION_DAYS2, previewLabelField2, createHubBody2, updateHubBody2, addHubAdminBody2, addHubIdentityAuthorizationBody2, contactDecisionBody2, approveContactBody2, listContactAccessQuery2, createHubTeamBody2, updateHubTeamBody2, addHubTeamUserBody2, reassignHubUserBody2, replicatePreviewBody2, updateChannelTestIdentitiesBody2, claimCodeChannelParam2, claimCodeDeleteParam2, connectionIdParam2, connectorIdParam2, listConnectionsQuery2, deleteConnectionQuery2, addConnectionBody2, editConnectionBody2, PRODUCTION_DIRECT_FIELDS2, setProductionCredentialBody2, registerWhatsappQuery2, registerWhatsappBody2, retryProvisioningQuery2, resendDomainStatusQuery2, PLACEHOLDER_TOKENS2, ALLOWED_TYPES2, SUBSCHEMA_OBJECT_KEYWORDS2, SUBSCHEMA_LIST_KEYWORDS2, SUBSCHEMA_MAP_KEYWORDS2, MAX_SCHEMA_DEPTH2, toolIdParam2, listToolsQuery2, toolAgentQuery2, deleteToolQuery2, toolConnectionsQuery2, nativeToolIdSchema2, addNativeToolBody2, addMcpToolBody2, createCustomToolBody2, updateCustomToolBody2, updateToolExecutionConfigBody2, initialValueCreateSchema2, initialValueUpdateSchema2, stateIdParam2, listStatesQuery2, stateNameSchema2, createStateBody2, updateStateBody2, reorderStatesBody2, variantAiModeSchema2, experimentStatusSchema2, overlayUpdateSchema2, experimentIdParam2, variantIdParam2, listExperimentsQuery2, listVariantsQuery2, listOverridesQuery2, deleteOverrideQuery2, createExperimentBody2, updateExperimentBody2, setExperimentStatusBody2, createVariantBody2, updateVariantBody2, upsertOverrideBody2, orgTagIdParam2, listOrgTagsQuery2, createOrgTagBody2, updateOrgTagBody2, orgCredentialIdParam2, listOrgCredentialsQuery2, createOrgCredentialBody2, updateOrgCredentialBody2, orgResourceIdParam2, orgResourceFileIdParam2, orgResourceFolderIdParam2, hubOrgResourceParam2, listOrgResourcesQuery2, orgIdQuery2, createOrgResourceBody2, updateOrgResourceBody2, createOrgResourceFolderBody2, updateOrgResourceFolderBody2, uploadOrgResourceFileBody2, updateOrgResourceFileBody2, uploadOrgSkillZipBody2, linkOrgResourceBody2, resourceIdParam2, listResourcesQuery2, createResourceBody2, updateResourceBody2, syncSkillsBody2, resourceFileIdParam2, listResourceFilesQuery2, createResourceFileBody2, updateResourceFileBody2, uploadResourceFileBody2, uploadSkillZipBody2, resourceFolderIdParam2, listResourceFoldersQuery2, createResourceFolderBody2, updateResourceFolderBody2, agentResourceQuery2, hubResourceQuery2, linkAgentResourceBody2, updateAgentResourceBody2, unlinkAgentResourceQuery2, navItemSchema2, hubCountResetBody2, navItemCountResetBody2, typingBody2, analyticsHubIdParam2, analyticsVariableIdParam2, updateVariablePinBody2, updateAnalyticsViewBody2, NUMERIC_FILTER_OPS2, TEXT_FILTER_OPS2, CATEGORICAL_FILTER_OPS2, VARIABLE_FILTER_OPS2, STRUCTURED_QUERY_OPS2, STRUCTURED_QUERY_AGGREGATIONS2, filterValueSchema2, conversationsBody2, analyticsConversationIdParam2, messagesQuery2, conversationDetailDataQuery2, analyticsDataBody2, structuredQueryBody2, analyticsSqlBody2, analyticsSqlSchemaQuery2, EVAL_PACING_PRESET_NAMES2, PACING_INTERVAL_MIN_MS2, PACING_INTERVAL_MAX_MS2, EVAL_RUN_DEADLINE_MIN_MS2, EVAL_RUN_DEADLINE_MAX_MS2, paginationSchema22, evalIdParam2, sessionIdParam2, scenarioSetIdParam2, hubIdQuery2, EVAL_INPUT_ROLES2, EVAL_INPUT_ROLE_LIST2, ROLE_ECHO_MAX2, EVAL_INITIAL_STATE_SCOPES2, MAX_INITIAL_STATE_ENTRIES2, evalInitialStateEntry2, createEvalBody2, updateEvalBody2, getEvalsQuery2, toggleEvalBody2, bulkToggleEvalsBody2, pacingConfigSchema2, sessionConfigSchema2, createSessionBody2, getSessionsQuery2, getSessionResultsQuery2, getSessionRunsQuery2, evalAnalyticsQuery2, getSessionCostQuery2, compareSessionsQuery2, evalsSqlBody2, evalsSqlSchemaQuery2, exportResultsQuery2, validateEvalBody2, hubAgentsQuery2, createScenarioSetBody2, updateScenarioSetBody2, scenarioSetsHubQuery2, createScenarioFromConversationBody2, createJourneyFromConversationBody2, EVAL_ATTACHMENT_HASH_REGEX2, evalAttachmentRef2, turnMayCarryAttachments2, ATTACHMENTS_USER_ONLY_MESSAGE2, journeyIdParam2, journeyToolCallSchema2, journeyTurnSchema2, journeyStepOverrideSchema2, fixtureField2, createJourneyBody2, updateJourneyBody2, getConversationsQuery2, getMessagesQuery2, appMessageSenderType2, appMessageReceiverType2, appMessageBody2, updateUserBody2, updateProfileBody2, pathnameRegex2, updatePreferencesBody2, registerPushTokenBody2, deletePushTokenQuery2, activityQuery2, deletionModeSchema2, deletionRequestBody2, archiveHubIdParam2, archiveConversationParams2, archiveListQuery2, archiveMessageObservabilityParams2, conversationIdParam2, claimBody2, releaseBody2, transferBody2, closeBody2, additionalContextPayloadSchema2, kanbanUpdateBody2, annotateConversationBody2, observabilityParams2, observabilityListParams2, deleteUserConversationsBody2, sendMessageBody2, listConversationsQuery2, getConversationDetailParams2, getConversationDetailQuery2, listWhatsAppTemplatesQuery2, sendWhatsAppTemplateBody2, billingOrgIdParam2, subscriptionItemParams2, spendCapBody2, growthPacksBody2, portalSessionBody2, checkoutSessionBody2, updateBillingCurrencyBody2, invoicesQuery2, downloadBody2, uploadQuery2, signUrlBody2, outboundSchemaQuery2, templateIdParam2, listTemplatesQuery2, deleteTemplateQuery2, templateStatusQuery2, createTemplateBody2, updateTemplateBody2, submitTemplateBody2, testTemplateBody2, contactIdParam2, listContactsQuery2, createContactBody2, updateContactBody2, listIdParam2, listListsQuery2, listListContactsQuery2, createListBody2, updateListBody2, addListContactsBody2, removeListContactsBody2, scheduleIdParam2, listSchedulesQuery2, listExecutionsQuery2, createScheduleBody2, updateScheduleBody2, MAX_RESOURCE_FILE_SIZE2, MAX_10MB_BASE64_ENCODED_BYTES2, MAX_EVAL_ATTACHMENT_ENCODED_BYTES2, MAX_EVAL_ATTACHMENT_CARRIERS2, MAX_EVAL_ATTACHMENT_AGGREGATE_ENCODED_BYTES2, MAX_RESOURCE_ENCODED_BYTES2, MAX_HUB_AS_CODE_RESOURCES2, MAX_HUB_AS_CODE_RESOURCE_FILES2, MAX_RESOURCE_AGGREGATE_ENCODED_BYTES2, MAX_CI_CONFIG_BODY_BYTES2, hubAsCodeResourceFileSchema2, hubAsCodeResourceSchema2, uuidPattern2, ciUuidSchema2, boundedHubAsCodeResourcesSchema2, hubAsCodeConfigSchema2, ciPullHubIdParam2, ciBranchParam2, ciPullQuery2, ciHubsQuery2, ciLookupQuery2, ciBranchesQuery2, ciSyncBody2, ciPushBody2, ciDiffBody2, ciPublishBody2, ciPublishPreviewBody2, ciSyncMcpBody2, ciOrgResourcesParam2, orgResourcesConfigSchema2, ciOrgResourcesPushBody2, ciOrgResourcesDiffBody2, adminOrgIdParam2, adminOrgAdminIdParam2, adminUserIdParam2, adminPlanIdParam2, adminHubIdParam2, adminOrganizationsQuery2, adminUserSearchQuery2, kanbanSlugMigrationQuery2, adjustQuotaBody2, updatePlanBody2, addAdminUserBody2, updatePlatformConfigBody2, updateFreeOrgLimitBody2, adminSetOrgHarnessBody2, adminSetHubHarnessBody2, adminScopedTargetBody2, updatePricingPlanBody2, dataExplorerSearchQuery2, dataExplorerOrgIdParam2, dataExplorerHubIdParam2, dataExplorerConvIdParam2, dataExplorerDoInstancesQuery2, dataExplorerNsIdParam2, dataExplorerKvKeysQuery2, dataExplorerKvKeyParam2, uuidOrHexId2, dataExplorerDeleteOrgParam2, dataExplorerDeleteHubParam2, dataExplorerDeleteConvParam2, dataExplorerDeleteUserParam2, dataExplorerDeleteQuery2, dataExplorerKvDeleteQuery2, pitrDoNamespace2, pitrBookmarkParam2, pitrRestoreBody2, healthSamplingTriggerBody2, dataExplorerDebugDoType2, DEBUG_READ_MAX_LIMIT2, DEBUG_READ_DEFAULT_LIMIT2, DEBUG_DO_HEX_PREFIX2, debugDoEntityId2, debugTableName2, dataExplorerDebugTablesParam2, dataExplorerDebugRowsParam2, dataExplorerDebugRowsQuery2, dataExplorerDebugAnalyticsTable2, debugUuid2, dataExplorerDebugAnalyticsRowsParam2, dataExplorerDebugAnalyticsRowsQuery2, debugHubConvParam2, debugMessageIdQuery2, sandboxEgressPolicy2, SANDBOX_EXEC_MAX_CMD_LENGTH2, SANDBOX_EXEC_MAX_ALLOWLIST2, SANDBOX_EXEC_MAX_TIMEOUT_MS2, adminSandboxExecBody2, whatsappCallbackBody2, authMeResponse2, wsTicketResponse2, sessionCheckResponse2, logoutResponse2, magicCodeSendBody2, magicCodeSendResponse2, magicCodeVerifyBody2, magicCodeVerifyResponse2, browserParams2, browserFoldersQuery2, browserFilesQuery2, stateOperationBody2, conversationListResourcesQuery2, conversationReadResourceQuery2, listPendingSchedulesQuery2, listHubAggregateSchedulesQuery2, reportSourceSchema2, intakeReportSourceSchema2, reportClassificationSchema2, reportStatusSchema2, reportLocaleSchema2, reportMessageAuthorRoleSchema2, reportMessageSchema2, sentryRefStatusSchema2, createReportBody2, editReportBody2, reporterReportSummarySchema2, reporterListResponseSchema2, getReportResponseSchema2, reporterTransitionResponseSchema2, contestReportBody2, reporterListQuery2, listReportsQuery2, GITHUB_ISSUE_URL_REGEX2, githubIssueUrlSchema2, transitionReportBody2, groupReportsBody2, holdReportBody2, clickhouseReadyResponse2, bootstrapQuery2, requestSnapshotChunkMessage2, MAX_NAME_LENGTH3, MAX_VALUE_LENGTH2, MAX_TAGS2, MAX_TAG_LENGTH2, MAX_SCOPE_HUBS2, MAX_SCOPE_TAGS2, vaultSecretScopeSchema2, vaultCreateBody2, vaultUpdateBody2, PERMISSIONS2, MAX_NAME_LENGTH22, MAX_HUBS_PER_GRANT2, MAX_HUB_TAGS_PER_GRANT2, MAX_GRANTS2, permissionEnum2, grantScopeSchema2, grantSchema2, createTokenBody2, tokenOrgIdParam2, tokenGrantScopeSchema2, tokenGrantSchema2, tokenMetadataSchema2, listTokensResponse2, createTokenResponse2, orgTokenSummarySchema2, listOrgTokensResponse2, invitePreviewQuery2, invitePreviewResponse2, discordTier2, discordBillingCycle2, discordMetadata2, discordOAuthStartResponse2, discordOAuthFinalizeBody2, discordOAuthFinalizeResponse2, discordDisconnectResponse2, jsonSchemaSchema2, hubUserIdentity2, stateValueEntry2, getHubUserContextResponse2, updateHubUserBody2, updateHubUserResponse2, unlockHubUserNameResponse2, stateResetParams2, stateResetResponse2, hubAlertsParam2, hubAlertSeverity2, hubAlert2, hubAlertsListResponse2, noticeSeveritySchema2, noticeStatusSchema2, NOTICE_SCOPE_REGEX2, noticeScopeSchema2, noticeLinkSchema2, createNoticeBody2, updateNoticeBody2, listNoticesQuery2, noticeIdParamSchema2, templateLocaleSchema2, TEMPLATE_SLUG_REGEX2, templateSlugSchema2, templateStatusSchema2, templateFileMapSchema2, TEMPLATE_INSTANCE_ID_KEYS, TEMPLATE_OPAQUE_BLOB_KEYS, TEMPLATE_AUTHOR_DATA_KEYS, templateTextSchema2, templateUsesEntrySchema2, templateUsesSchema2, templateYamlLocaleEntry2, templateYamlWayaiBlock2, templateTagsSchema2, templateYamlSchema2, templateHeroSchema2, templatePushLocaleSchema2, templatePushBody2, templateListQuery2, templateSlugParam2, templateDetailQuery2, ADMIN_SKILL_NAME_REGEX2, adminSkillNameParam2;
12098
+ var uuidSchema2, paginationSchema3, timestampSchema2, idParamSchema2, clientOptionalString2, clientOptionalBoolean2, clientOptionalNumber2, messageAttachment2, MAX_MESSAGE_BODY_BYTES2, MAX_ATTACHMENTS_PER_MESSAGE2, MAX_AUDIO_FILE_BASE64_BYTES2, primaryRegionSchema2, placementSourceSchema2, orgIdParam2, orgAdminIdParam2, createOrganizationBody2, updateOrganizationBody2, addOrgAdminBody2, AUTH_TYPE3, ORG_CREDENTIAL_AUTH_TYPES3, AUTH_TYPE_DISPLAY3, LEGACY_AUTH_TYPE_MAP3, VALID_AUTH_TYPES3, AGENT_ROLES2, SAFE_USER_ID_REGEX2, SUPPORTED_LOCALES2, SUMMARIZATION_THRESHOLD_MIN2, SUMMARIZATION_THRESHOLD_MAX2, summarizationThresholdField2, monitorConfigField2, agentIdParam2, listAgentsQuery2, agentConnectionsQuery2, createAgentBody2, updateAgentBody2, AGENT_PARAMETER_TYPES2, AGENT_PARAMETER_NAME_REGEX2, agentParameterCreateSchema2, MAX_AGENT_PARAMETERS_PER_REQUEST2, createAgentParametersBody2, SLUG_REGEX2, slugSchema2, INVISIBLE_NAME_CHARS2, MAX_KANBAN_STATUSES2, MAX_FOLLOWUPS_PER_STATUS2, MAX_LANES2, MAX_ADDITIONAL_CONTEXT_SCHEMA_BYTES2, RESERVED_TEMPLATE_DUMP_NAME2, kanbanStatusSlugSchema2, followupSchema2, MAX_OUTCOMES_PER_STATUS2, kanbanOutcomeSchema2, EXCLUSIVE_FLAG_PAIRS2, kanbanStatusSchema2, kanbanStatusesArraySchema2, laneSchema2, lanesArraySchema2, hubIdParam2, hubAdminIdParam2, hubUserIdParam2, hubIdentityIdParam2, hubTeamIdParam2, hubTeamUserDeleteParam2, hubSchemaQuery2, PREVIEW_LABEL_MAX_LENGTH2, MAX_ENDED_INDEX_RETENTION_DAYS2, previewLabelField2, createHubBody2, updateHubBody2, addHubAdminBody2, addHubIdentityAuthorizationBody2, contactDecisionBody2, approveContactBody2, listContactAccessQuery2, createHubTeamBody2, updateHubTeamBody2, addHubTeamUserBody2, reassignHubUserBody2, replicatePreviewBody2, updateChannelTestIdentitiesBody2, claimCodeChannelParam2, claimCodeDeleteParam2, connectionIdParam2, connectorIdParam2, listConnectionsQuery2, deleteConnectionQuery2, addConnectionBody2, editConnectionBody2, PRODUCTION_DIRECT_FIELDS2, setProductionCredentialBody2, registerWhatsappQuery2, registerWhatsappBody2, retryProvisioningQuery2, resendDomainStatusQuery2, PLACEHOLDER_TOKENS2, ALLOWED_TYPES2, SUBSCHEMA_OBJECT_KEYWORDS2, SUBSCHEMA_LIST_KEYWORDS2, SUBSCHEMA_MAP_KEYWORDS2, MAX_SCHEMA_DEPTH2, toolIdParam2, listToolsQuery2, toolAgentQuery2, deleteToolQuery2, toolConnectionsQuery2, nativeToolIdSchema2, addNativeToolBody2, addMcpToolBody2, createCustomToolBody2, updateCustomToolBody2, updateToolExecutionConfigBody2, initialValueCreateSchema2, initialValueUpdateSchema2, stateIdParam2, listStatesQuery2, stateNameSchema2, createStateBody2, updateStateBody2, reorderStatesBody2, variantAiModeSchema2, experimentStatusSchema2, overlayUpdateSchema2, experimentIdParam2, variantIdParam2, listExperimentsQuery2, listVariantsQuery2, listOverridesQuery2, deleteOverrideQuery2, createExperimentBody2, updateExperimentBody2, setExperimentStatusBody2, createVariantBody2, updateVariantBody2, upsertOverrideBody2, orgTagIdParam2, listOrgTagsQuery2, createOrgTagBody2, updateOrgTagBody2, orgCredentialIdParam2, listOrgCredentialsQuery2, createOrgCredentialBody2, updateOrgCredentialBody2, orgResourceIdParam2, orgResourceFileIdParam2, orgResourceFolderIdParam2, hubOrgResourceParam2, listOrgResourcesQuery2, orgIdQuery2, createOrgResourceBody2, updateOrgResourceBody2, createOrgResourceFolderBody2, updateOrgResourceFolderBody2, uploadOrgResourceFileBody2, updateOrgResourceFileBody2, uploadOrgSkillZipBody2, linkOrgResourceBody2, resourceIdParam2, listResourcesQuery2, createResourceBody2, updateResourceBody2, syncSkillsBody2, resourceFileIdParam2, listResourceFilesQuery2, createResourceFileBody2, updateResourceFileBody2, uploadResourceFileBody2, uploadSkillZipBody2, resourceFolderIdParam2, listResourceFoldersQuery2, createResourceFolderBody2, updateResourceFolderBody2, agentResourceQuery2, hubResourceQuery2, linkAgentResourceBody2, updateAgentResourceBody2, unlinkAgentResourceQuery2, navItemSchema2, hubCountResetBody2, navItemCountResetBody2, typingBody2, analyticsHubIdParam2, analyticsVariableIdParam2, updateVariablePinBody2, updateAnalyticsViewBody2, NUMERIC_FILTER_OPS2, TEXT_FILTER_OPS2, CATEGORICAL_FILTER_OPS2, VARIABLE_FILTER_OPS2, STRUCTURED_QUERY_OPS2, STRUCTURED_QUERY_AGGREGATIONS2, filterValueSchema2, conversationsBody2, analyticsConversationIdParam2, messagesQuery2, conversationDetailDataQuery2, analyticsDataBody2, structuredQueryBody2, analyticsSqlBody2, analyticsSqlSchemaQuery2, EVAL_PACING_PRESET_NAMES2, PACING_INTERVAL_MIN_MS2, PACING_INTERVAL_MAX_MS2, EVAL_RUN_DEADLINE_MIN_MS2, EVAL_RUN_DEADLINE_MAX_MS2, paginationSchema22, evalIdParam2, sessionIdParam2, scenarioSetIdParam2, hubIdQuery2, EVAL_INPUT_ROLES2, EVAL_INPUT_ROLE_LIST2, ROLE_ECHO_MAX2, EVAL_INITIAL_STATE_SCOPES2, MAX_INITIAL_STATE_ENTRIES2, evalInitialStateEntry2, createEvalBody2, updateEvalBody2, getEvalsQuery2, toggleEvalBody2, bulkToggleEvalsBody2, pacingConfigSchema2, sessionConfigSchema2, createSessionBody2, getSessionsQuery2, getSessionResultsQuery2, getSessionRunsQuery2, evalAnalyticsQuery2, getSessionCostQuery2, compareSessionsQuery2, evalsSqlBody2, evalsSqlSchemaQuery2, exportResultsQuery2, validateEvalBody2, hubAgentsQuery2, createScenarioSetBody2, updateScenarioSetBody2, scenarioSetsHubQuery2, createScenarioFromConversationBody2, createJourneyFromConversationBody2, EVAL_ATTACHMENT_HASH_REGEX2, evalAttachmentRef2, turnMayCarryAttachments2, ATTACHMENTS_USER_ONLY_MESSAGE2, journeyIdParam2, journeyToolCallSchema2, journeyTurnSchema2, journeyStepOverrideSchema2, fixtureField2, createJourneyBody2, updateJourneyBody2, getConversationsQuery2, getMessagesQuery2, appMessageSenderType2, appMessageReceiverType2, apiChannelMessage2, apiChannelMessageBody2, appMessageBody2, updateUserBody2, updateProfileBody2, pathnameRegex2, updatePreferencesBody2, registerPushTokenBody2, deletePushTokenQuery2, activityQuery2, deletionModeSchema2, deletionRequestBody2, templateLocaleSchema2, TEMPLATE_SLUG_REGEX2, templateSlugSchema2, templateStatusSchema2, templateFileMapSchema2, TEMPLATE_INSTANCE_ID_KEYS, TEMPLATE_OPAQUE_BLOB_KEYS, TEMPLATE_AUTHOR_DATA_KEYS, templateTextSchema2, templateUsesEntrySchema2, templateUsesSchema2, templateYamlLocaleEntry2, templateYamlWayaiBlock2, templateTagsSchema2, templateYamlSchema2, templateHeroSchema2, templatePushLocaleSchema2, templatePushBody2, templateListQuery2, templateSlugParam2, templateDetailQuery2, courseQuizScoreSchema2, upsertCourseLessonBody2, linkCourseCapstoneBody2, archiveHubIdParam2, archiveConversationParams2, archiveListQuery2, archiveMessageObservabilityParams2, conversationIdParam2, claimBody2, releaseBody2, transferBody2, closeBody2, additionalContextPayloadSchema2, kanbanUpdateBody2, annotateConversationBody2, observabilityParams2, observabilityListParams2, deleteUserConversationsBody2, sendMessageBody2, listConversationsQuery2, getConversationDetailParams2, getConversationDetailQuery2, listWhatsAppTemplatesQuery2, sendWhatsAppTemplateBody2, billingOrgIdParam2, subscriptionItemParams2, spendCapBody2, growthPacksBody2, portalSessionBody2, checkoutSessionBody2, updateBillingCurrencyBody2, invoicesQuery2, downloadBody2, uploadQuery2, signUrlBody2, outboundSchemaQuery2, templateIdParam2, listTemplatesQuery2, deleteTemplateQuery2, templateStatusQuery2, createTemplateBody2, updateTemplateBody2, submitTemplateBody2, testTemplateBody2, contactIdParam2, listContactsQuery2, createContactBody2, updateContactBody2, listIdParam2, listListsQuery2, listListContactsQuery2, createListBody2, updateListBody2, addListContactsBody2, removeListContactsBody2, scheduleIdParam2, listSchedulesQuery2, listExecutionsQuery2, createScheduleBody2, updateScheduleBody2, MAX_RESOURCE_FILE_SIZE2, MAX_10MB_BASE64_ENCODED_BYTES2, MAX_EVAL_ATTACHMENT_ENCODED_BYTES2, MAX_EVAL_ATTACHMENT_CARRIERS2, MAX_EVAL_ATTACHMENT_AGGREGATE_ENCODED_BYTES2, MAX_RESOURCE_ENCODED_BYTES2, MAX_HUB_AS_CODE_RESOURCES2, MAX_HUB_AS_CODE_RESOURCE_FILES2, MAX_RESOURCE_AGGREGATE_ENCODED_BYTES2, MAX_CI_CONFIG_BODY_BYTES2, hubAsCodeResourceFileSchema2, hubAsCodeResourceSchema2, uuidPattern2, ciUuidSchema2, boundedHubAsCodeResourcesSchema2, hubAsCodeConfigSchema2, ciPullHubIdParam2, ciBranchParam2, ciPullQuery2, ciHubsQuery2, ciLookupQuery2, ciBranchesQuery2, ciSyncBody2, ciPushBody2, ciDiffBody2, ciPublishBody2, ciPublishPreviewBody2, ciSyncMcpBody2, ciOrgResourcesParam2, orgResourcesConfigSchema2, ciOrgResourcesPushBody2, ciOrgResourcesDiffBody2, adminOrgIdParam2, adminOrgAdminIdParam2, adminUserIdParam2, adminPlanIdParam2, adminOrganizationsQuery2, adminUserSearchQuery2, kanbanSlugMigrationQuery2, adjustQuotaBody2, updatePlanBody2, addAdminUserBody2, updatePlatformConfigBody2, updateFreeOrgLimitBody2, adminScopedTargetBody2, updatePricingPlanBody2, dataExplorerSearchQuery2, dataExplorerOrgIdParam2, dataExplorerHubIdParam2, dataExplorerConvIdParam2, dataExplorerDoInstancesQuery2, dataExplorerNsIdParam2, dataExplorerKvKeysQuery2, dataExplorerKvKeyParam2, uuidOrHexId2, dataExplorerDeleteOrgParam2, dataExplorerDeleteHubParam2, dataExplorerDeleteConvParam2, dataExplorerDeleteUserParam2, dataExplorerDeleteQuery2, dataExplorerKvDeleteQuery2, pitrDoNamespace2, pitrBookmarkParam2, pitrRestoreBody2, healthSamplingTriggerBody2, dataExplorerDebugDoType2, DEBUG_READ_MAX_LIMIT2, DEBUG_READ_DEFAULT_LIMIT2, DEBUG_DO_HEX_PREFIX2, debugDoEntityId2, debugTableName2, dataExplorerDebugTablesParam2, dataExplorerDebugRowsParam2, dataExplorerDebugRowsQuery2, dataExplorerDebugAnalyticsTable2, debugUuid2, dataExplorerDebugAnalyticsRowsParam2, dataExplorerDebugAnalyticsRowsQuery2, debugHubConvParam2, debugMessageIdQuery2, sandboxEgressPolicy2, SANDBOX_EXEC_MAX_CMD_LENGTH2, SANDBOX_EXEC_MAX_ALLOWLIST2, SANDBOX_EXEC_MAX_TIMEOUT_MS2, adminSandboxExecBody2, whatsappCallbackBody2, authMeResponse2, wsTicketResponse2, sessionCheckResponse2, logoutResponse2, magicCodeSendBody2, magicCodeSendResponse2, magicCodeVerifyBody2, magicCodeVerifyResponse2, passwordLoginBody2, browserParams2, browserFoldersQuery2, browserFilesQuery2, stateOperationBody2, conversationListResourcesQuery2, conversationReadResourceQuery2, listPendingSchedulesQuery2, listHubAggregateSchedulesQuery2, reportSourceSchema2, intakeReportSourceSchema2, reportClassificationSchema2, reportStatusSchema2, reportLocaleSchema2, reportMessageAuthorRoleSchema2, reportMessageSchema2, sentryRefStatusSchema2, createReportBody2, editReportBody2, reporterReportSummarySchema2, reporterListResponseSchema2, getReportResponseSchema2, reporterTransitionResponseSchema2, contestReportBody2, reporterListQuery2, listReportsQuery2, GITHUB_ISSUE_URL_REGEX2, githubIssueUrlSchema2, transitionReportBody2, groupReportsBody2, holdReportBody2, clickhouseReadyResponse2, bootstrapQuery2, requestSnapshotChunkMessage2, MAX_NAME_LENGTH3, MAX_VALUE_LENGTH2, MAX_TAGS2, MAX_TAG_LENGTH2, MAX_SCOPE_HUBS2, MAX_SCOPE_TAGS2, vaultSecretScopeSchema2, vaultCreateBody2, vaultUpdateBody2, PERMISSIONS2, MAX_NAME_LENGTH22, MAX_HUBS_PER_GRANT2, MAX_HUB_TAGS_PER_GRANT2, MAX_GRANTS2, permissionEnum2, grantScopeSchema2, grantSchema2, createTokenBody2, tokenOrgIdParam2, tokenGrantScopeSchema2, tokenGrantSchema2, tokenMetadataSchema2, listTokensResponse2, createTokenResponse2, orgTokenSummarySchema2, listOrgTokensResponse2, invitePreviewQuery2, invitePreviewResponse2, discordTier2, discordBillingCycle2, discordMetadata2, discordOAuthStartResponse2, discordOAuthFinalizeBody2, discordOAuthFinalizeResponse2, discordDisconnectResponse2, jsonSchemaSchema2, hubUserIdentity2, stateValueEntry2, getHubUserContextResponse2, updateHubUserBody2, updateHubUserResponse2, unlockHubUserNameResponse2, stateResetParams2, stateResetResponse2, hubAlertsParam2, hubAlertSeverity2, hubAlert2, hubAlertsListResponse2, noticeSeveritySchema2, noticeStatusSchema2, NOTICE_SCOPE_REGEX2, noticeScopeSchema2, noticeLinkSchema2, createNoticeBody2, updateNoticeBody2, listNoticesQuery2, noticeIdParamSchema2, ADMIN_SKILL_NAME_REGEX2, adminSkillNameParam2;
12024
12099
  var init_contracts = __esm({
12025
12100
  "../../packages/core/dist/contracts/index.js"() {
12026
12101
  "use strict";
@@ -12072,6 +12147,7 @@ var init_contracts = __esm({
12072
12147
  init_zod();
12073
12148
  init_zod();
12074
12149
  init_zod();
12150
+ init_zod();
12075
12151
  uuidSchema2 = external_exports.string().uuid();
12076
12152
  paginationSchema3 = external_exports.object({
12077
12153
  limit: external_exports.coerce.number().int().min(1).max(100).default(50),
@@ -12288,6 +12364,12 @@ var init_contracts = __esm({
12288
12364
  });
12289
12365
  }
12290
12366
  });
12367
+ MAX_OUTCOMES_PER_STATUS2 = 20;
12368
+ kanbanOutcomeSchema2 = external_exports.object({
12369
+ slug: kanbanStatusSlugSchema2,
12370
+ name: external_exports.string().min(1, "name is required").max(100, "name must be 100 characters or fewer").refine((v) => visibleLength2(v) > 0, "name must not be blank"),
12371
+ color: external_exports.string().optional()
12372
+ }).passthrough();
12291
12373
  EXCLUSIVE_FLAG_PAIRS2 = [
12292
12374
  ["isInitialStatus", "triggersAgentResponse"],
12293
12375
  ["isInitialStatus", "allowsAgentUpdate"],
@@ -12323,7 +12405,10 @@ var init_contracts = __esm({
12323
12405
  * and is not exposed to agents. The cross-reference invariant (must point at a
12324
12406
  * declared lane; the initial status must not have one) is enforced at the hub
12325
12407
  * level via `validateLaneReferences` — this schema only sees the status array. */
12326
- lane_slug: kanbanStatusSlugSchema2.optional()
12408
+ lane_slug: kanbanStatusSlugSchema2.optional(),
12409
+ /** Closing outcomes offered on the terminal transition. Only valid when
12410
+ * `isTerminalStatus === true` (enforced in the superRefine below). */
12411
+ outcomes: external_exports.array(kanbanOutcomeSchema2).max(MAX_OUTCOMES_PER_STATUS2, `outcomes must have at most ${MAX_OUTCOMES_PER_STATUS2} entries`).optional()
12327
12412
  }).passthrough().superRefine((status, ctx) => {
12328
12413
  const label = status.name ? `"${status.name}"` : status.slug ? `"${status.slug}"` : "<unnamed>";
12329
12414
  for (const [a, b] of EXCLUSIVE_FLAG_PAIRS2) {
@@ -12360,6 +12445,33 @@ var init_contracts = __esm({
12360
12445
  });
12361
12446
  }
12362
12447
  }
12448
+ if (Array.isArray(status.outcomes) && status.outcomes.length > 0) {
12449
+ if (status.isTerminalStatus !== true) {
12450
+ ctx.addIssue({
12451
+ code: external_exports.ZodIssueCode.custom,
12452
+ path: ["outcomes"],
12453
+ message: `kanban status ${label}: outcomes are only allowed on the terminal status (set isTerminalStatus=true)`
12454
+ });
12455
+ }
12456
+ const seen = /* @__PURE__ */ new Map();
12457
+ status.outcomes.forEach((o, j) => {
12458
+ if (!o?.slug) return;
12459
+ const arr = seen.get(o.slug) ?? [];
12460
+ arr.push(j);
12461
+ seen.set(o.slug, arr);
12462
+ });
12463
+ for (const [slug, indices] of seen) {
12464
+ if (indices.length > 1) {
12465
+ for (const j of indices) {
12466
+ ctx.addIssue({
12467
+ code: external_exports.ZodIssueCode.custom,
12468
+ path: ["outcomes", j, "slug"],
12469
+ message: `kanban status ${label}: duplicate outcome slug "${slug}"`
12470
+ });
12471
+ }
12472
+ }
12473
+ }
12474
+ }
12363
12475
  });
12364
12476
  kanbanStatusesArraySchema2 = external_exports.array(kanbanStatusSchema2).max(MAX_KANBAN_STATUSES2, `kanban_statuses must have at most ${MAX_KANBAN_STATUSES2} entries`).superRefine((statuses, ctx) => {
12365
12477
  if (statuses.length === 0) return;
@@ -12380,6 +12492,17 @@ var init_contracts = __esm({
12380
12492
  });
12381
12493
  }
12382
12494
  }
12495
+ const terminalIndices = statuses.map((s, i) => ({ s, i })).filter(({ s }) => s.isTerminalStatus === true);
12496
+ if (terminalIndices.length > 1) {
12497
+ const slugs = terminalIndices.map(({ s }) => s.slug).join(", ");
12498
+ for (const { i } of terminalIndices) {
12499
+ ctx.addIssue({
12500
+ code: external_exports.ZodIssueCode.custom,
12501
+ path: [i, "isTerminalStatus"],
12502
+ message: `kanban_statuses: at most one status may have isTerminalStatus=true (found ${terminalIndices.length}: ${slugs})`
12503
+ });
12504
+ }
12505
+ }
12383
12506
  const seenSlugs = /* @__PURE__ */ new Map();
12384
12507
  statuses.forEach((s, i) => {
12385
12508
  const key = s.slug;
@@ -12485,6 +12608,13 @@ var init_contracts = __esm({
12485
12608
  language: external_exports.enum(["en", "pt", "es"]).optional(),
12486
12609
  access_request_message: external_exports.string().max(1e3).nullable().optional(),
12487
12610
  access_approval_role: external_exports.enum(["admin", "team"]).optional(),
12611
+ // AI-failure escalation. When an LLM provider outage persists past this many
12612
+ // minutes the conversation escalates to the team; null → code default. The two
12613
+ // message fields override the localized (hub.language) delay / hand-off notices;
12614
+ // null → localized default. Bounds validated here so out-of-range never persists.
12615
+ ai_failure_escalation_minutes: external_exports.number().int().min(1).max(60).nullable().optional(),
12616
+ ai_delay_message: external_exports.string().max(1e3).nullable().optional(),
12617
+ ai_handoff_message: external_exports.string().max(1e3).nullable().optional(),
12488
12618
  // Native-completion fallback connection for a degraded harness turn (PR 2.10b).
12489
12619
  // A NATIVE LLM (Agent) connection id on this hub; validated at set-time on the REST
12490
12620
  // PATCH (setup/hubs.ts rejects a non-existent / non-Agent / harness id) and re-checked
@@ -12573,7 +12703,7 @@ var init_contracts = __esm({
12573
12703
  hub_id: uuidSchema2,
12574
12704
  sync_credentials_to_production: external_exports.boolean().optional()
12575
12705
  }).passthrough();
12576
- PRODUCTION_DIRECT_FIELDS2 = ["username", "api_key", "access_token", "password", "refresh_token", "webhook_secret_token"];
12706
+ PRODUCTION_DIRECT_FIELDS2 = ["username", "api_key", "access_token", "password", "refresh_token", "webhook_secret_token", "webhook_signing_secret"];
12577
12707
  setProductionCredentialBody2 = external_exports.object({
12578
12708
  hub_id: uuidSchema2,
12579
12709
  organization_credential_id: external_exports.string().nullable().optional(),
@@ -12583,7 +12713,8 @@ var init_contracts = __esm({
12583
12713
  access_token: external_exports.string().optional(),
12584
12714
  password: external_exports.string().optional(),
12585
12715
  refresh_token: external_exports.string().optional(),
12586
- webhook_secret_token: external_exports.string().optional()
12716
+ webhook_secret_token: external_exports.string().optional(),
12717
+ webhook_signing_secret: external_exports.string().optional()
12587
12718
  }).strict().superRefine((data, ctx) => {
12588
12719
  const hasOrgLink = !!data.organization_credential_id || !!data.organization_credential_token_id;
12589
12720
  const hasDirect = PRODUCTION_DIRECT_FIELDS2.some((f) => data[f] != null);
@@ -13438,6 +13569,38 @@ var init_contracts = __esm({
13438
13569
  });
13439
13570
  appMessageSenderType2 = external_exports.enum(["user", "team"]);
13440
13571
  appMessageReceiverType2 = external_exports.enum(["user", "team", "agent", "assistant"]).transform((v) => v === "assistant" ? "agent" : v);
13572
+ apiChannelMessage2 = external_exports.object({
13573
+ text: clientOptionalString2,
13574
+ attachments: external_exports.array(messageAttachment2).max(MAX_ATTACHMENTS_PER_MESSAGE2).nullish().transform((v) => v ?? void 0)
13575
+ }).refine((m) => m.text && m.text.length > 0 || m.attachments && m.attachments.length > 0, {
13576
+ message: "message must have text or at least one attachment"
13577
+ });
13578
+ apiChannelMessageBody2 = external_exports.object({
13579
+ // Correlation id (task hubs): new → new conversation, repeat → continue. min 1 so an
13580
+ // empty string can't masquerade as a ref. Mutually exclusive with conversation_id.
13581
+ external_ref: external_exports.string().min(1).max(256).optional(),
13582
+ // Continue a specific WayAI conversation (authorized against the hub/channel + owner).
13583
+ // UUID-validated here (unlike the app channel, whose client we control): allocation
13584
+ // only treats a UUID-shaped id as a provided conversation, so a malformed id would
13585
+ // otherwise skip the owner guard and silently MINT a new conversation instead of
13586
+ // rejecting. A format 400 is shape-only — not an existence oracle (a valid-but-unknown
13587
+ // UUID still collapses to the opaque authorization error downstream).
13588
+ conversation_id: external_exports.string().uuid().optional(),
13589
+ // On-behalf-of end-user identity. Absent → per-connection service principal (task-hub
13590
+ // only; chat hub rejects with 422 in the route).
13591
+ user: external_exports.object({
13592
+ id: external_exports.string().min(1),
13593
+ email: clientOptionalString2,
13594
+ name: clientOptionalString2
13595
+ }).optional(),
13596
+ message: apiChannelMessage2,
13597
+ // Idempotency key: maps to channel_message_sid; a retried POST echoes the original
13598
+ // message_id and skips billing / turn dispatch (dedupe in ConversationDO.storeMessage).
13599
+ client_message_id: external_exports.string().min(1).max(256).optional()
13600
+ }).refine((b) => !(b.external_ref && b.conversation_id), {
13601
+ message: "provide external_ref or conversation_id, not both",
13602
+ path: ["external_ref"]
13603
+ });
13441
13604
  appMessageBody2 = external_exports.object({
13442
13605
  // Message content — three historical aliases. All optional: an attachment-only
13443
13606
  // or voice-only message carries no text.
@@ -13513,6 +13676,153 @@ var init_contracts = __esm({
13513
13676
  /** Type-to-confirm value; must equal the user's email (constant-time compared). */
13514
13677
  email_confirmation: external_exports.string().min(1).max(320)
13515
13678
  });
13679
+ templateLocaleSchema2 = external_exports.enum(SUPPORTED_LOCALES2);
13680
+ TEMPLATE_SLUG_REGEX2 = /^[a-z0-9][a-z0-9-]{0,62}$/;
13681
+ templateSlugSchema2 = external_exports.string().regex(TEMPLATE_SLUG_REGEX2, "slug must be lowercase alphanumeric with hyphens (max 63)");
13682
+ templateStatusSchema2 = external_exports.enum(["published", "draft", "internal"]);
13683
+ templateFileMapSchema2 = external_exports.record(external_exports.string()).refine((m) => Object.keys(m).every(isSafeTemplatePath2), {
13684
+ message: 'file map contains an unsafe path (no absolute paths, "..", or backslashes)'
13685
+ });
13686
+ TEMPLATE_INSTANCE_ID_KEYS = /* @__PURE__ */ new Set([
13687
+ // Top-level hub instance metadata (hub.yaml) — set by `wayai pull`, never authored.
13688
+ "hub_id",
13689
+ "hub_environment",
13690
+ "preview_label",
13691
+ "branch_name",
13692
+ // Per-entity row id + cross-entity reference UUIDs (each has a portable name twin).
13693
+ "id",
13694
+ "connection_id",
13695
+ "target_id",
13696
+ "agent_id",
13697
+ "resource_id",
13698
+ "list_id",
13699
+ // Account-scoped Meta WhatsApp template id (name twin: `template_whatsapp`).
13700
+ "template_whatsapp_id"
13701
+ ]);
13702
+ TEMPLATE_OPAQUE_BLOB_KEYS = /* @__PURE__ */ new Set([
13703
+ "settings",
13704
+ // agent + connection connector settings
13705
+ "schema_json",
13706
+ // agent response_format JSON Schema
13707
+ "json_schema",
13708
+ // state JSON Schema
13709
+ "initial_value",
13710
+ // state seed value
13711
+ "additional_context_schema",
13712
+ // kanban-status transition-form schema
13713
+ "config",
13714
+ // custom-tool OpenAI function schema
13715
+ "headers",
13716
+ "query_params",
13717
+ "body_params",
13718
+ // custom-tool HTTP shaping
13719
+ "mappings",
13720
+ // composed-tool argument mappings
13721
+ "input",
13722
+ "expected",
13723
+ "history",
13724
+ // eval message fixtures (tool_calls carry their own `id`)
13725
+ "transcript",
13726
+ "step_config"
13727
+ // journey fixtures (transcript carries `step_id`; step_config is keyed by it)
13728
+ ]);
13729
+ TEMPLATE_AUTHOR_DATA_KEYS = /* @__PURE__ */ new Set([
13730
+ // Outbound campaign subsystem (hub.yaml top-level). `outbound_contacts` is the
13731
+ // author's real leads — `phone`/`email`/`instagram_sid` + the required `name` are
13732
+ // GDPR-grade PII. `outbound_lists` group those contacts by real name. `outbound_schedules`
13733
+ // bind to the (now-absent) lists and carry the author's campaign cadence + message
13734
+ // copy — operationally tied to the author's customers; a consumer builds their own.
13735
+ "outbound_contacts",
13736
+ "outbound_lists",
13737
+ "outbound_schedules",
13738
+ // Account-scoped channel identifier on a connection (Twilio SID / WhatsApp number /
13739
+ // IG username / from-email, per connector). The connection stays as portable
13740
+ // structure re-bound by name on push; this author-account value carries no blueprint
13741
+ // value. A dedicated top-level column — never nested in the `settings` opaque blob.
13742
+ "account_sid"
13743
+ ]);
13744
+ templateTextSchema2 = external_exports.object({
13745
+ metaTitle: external_exports.string().min(1).max(200),
13746
+ metaDescription: external_exports.string().max(1e3).default("")
13747
+ });
13748
+ templateUsesEntrySchema2 = external_exports.object({
13749
+ backend: templateSlugSchema2,
13750
+ endpoint: templateSlugSchema2
13751
+ });
13752
+ templateUsesSchema2 = external_exports.array(templateUsesEntrySchema2).max(24).default([]);
13753
+ templateYamlLocaleEntry2 = templateTextSchema2.extend({ source: external_exports.string().min(1) });
13754
+ templateYamlWayaiBlock2 = external_exports.object({
13755
+ installCommand: external_exports.string().min(1).max(300),
13756
+ locales: external_exports.record(templateLocaleSchema2, templateYamlLocaleEntry2)
13757
+ });
13758
+ templateTagsSchema2 = external_exports.array(external_exports.string().min(1).max(30)).max(12).default([]).transform((tags) => [...new Set(tags.map((t) => t.trim().toLowerCase()).filter(Boolean))]);
13759
+ templateYamlSchema2 = external_exports.object({
13760
+ slug: templateSlugSchema2,
13761
+ category: external_exports.string().min(1).max(60),
13762
+ tags: templateTagsSchema2,
13763
+ status: templateStatusSchema2.default("draft"),
13764
+ order: external_exports.number().int().min(0).max(1e5).optional(),
13765
+ defaultLocale: templateLocaleSchema2,
13766
+ hero: external_exports.string().optional(),
13767
+ // relative path to a hero image inside the template folder
13768
+ // The Rekor backend(s) this channel runs on (gh #2955). Locale-agnostic. The
13769
+ // cross-link + MCP endpoint are derived from each entry's slugs, never authored.
13770
+ uses: templateUsesSchema2,
13771
+ // A WayAI template IS a WayAI channel — the wayai slice is required. (The old
13772
+ // Rekor-only store entry is gone: a pure Rekor backend lives only in Rekor's store.)
13773
+ wayai: templateYamlWayaiBlock2
13774
+ }).refine((c) => Boolean(c.wayai.locales[c.defaultLocale]), {
13775
+ message: "`wayai.locales` must include the defaultLocale"
13776
+ });
13777
+ templateHeroSchema2 = external_exports.object({
13778
+ filename: external_exports.string().min(1).max(200).regex(/\.(png|jpe?g|webp|gif)$/i, "hero must be a raster image (png/jpg/webp/gif)"),
13779
+ dataBase64: external_exports.string().min(1).max(8e6)
13780
+ });
13781
+ templatePushLocaleSchema2 = external_exports.object({
13782
+ wayai: templateTextSchema2.optional(),
13783
+ readmeMarkdown: external_exports.string().default(""),
13784
+ wayaiFiles: templateFileMapSchema2.optional()
13785
+ });
13786
+ templatePushBody2 = external_exports.object({
13787
+ slug: templateSlugSchema2,
13788
+ defaultLocale: templateLocaleSchema2,
13789
+ common: external_exports.object({
13790
+ category: external_exports.string().min(1).max(60),
13791
+ tags: templateTagsSchema2,
13792
+ status: templateStatusSchema2,
13793
+ order: external_exports.number().int().min(0).max(1e5).default(0),
13794
+ // The WayAI install command (a WayAI template always has a wayai side). Kept
13795
+ // optional on the wire so a malformed manifest 400s on the field, not the body.
13796
+ installCommand: external_exports.string().min(1).max(300).optional(),
13797
+ hero: templateHeroSchema2.optional(),
13798
+ // The channel→backend edge (gh #2955), locale-agnostic.
13799
+ uses: templateUsesSchema2
13800
+ }),
13801
+ locales: external_exports.record(templateLocaleSchema2, templatePushLocaleSchema2)
13802
+ }).refine((b) => Boolean(b.locales[b.defaultLocale]), {
13803
+ message: "`locales` must include the defaultLocale"
13804
+ });
13805
+ templateListQuery2 = external_exports.object({ locale: templateLocaleSchema2.optional() });
13806
+ templateSlugParam2 = external_exports.object({ slug: templateSlugSchema2 });
13807
+ templateDetailQuery2 = external_exports.object({ locale: templateLocaleSchema2.optional() });
13808
+ courseQuizScoreSchema2 = external_exports.object({
13809
+ correct: external_exports.number().int().min(0).max(50),
13810
+ total: external_exports.number().int().min(1).max(50),
13811
+ /** Chosen choice index per question; -1 = unanswered. */
13812
+ answers: external_exports.array(external_exports.number().int().min(-1).max(50)).max(50).optional()
13813
+ });
13814
+ upsertCourseLessonBody2 = external_exports.object({
13815
+ quiz_passed: external_exports.boolean().optional(),
13816
+ quiz_score: courseQuizScoreSchema2.optional(),
13817
+ content_version: external_exports.number().int().min(1)
13818
+ }).strict();
13819
+ linkCourseCapstoneBody2 = external_exports.object({
13820
+ hub_id: external_exports.string().min(1).max(128),
13821
+ // A capstone's slug IS a canonical template slug — reuse the one validator
13822
+ // the template pipeline (CLI, admin, gallery) already enforces, so course
13823
+ // linking can't drift from how real template slugs are shaped.
13824
+ template_slug: templateSlugSchema2.optional()
13825
+ }).strict();
13516
13826
  archiveHubIdParam2 = external_exports.object({
13517
13827
  hubId: external_exports.string().uuid()
13518
13828
  });
@@ -13606,7 +13916,10 @@ var init_contracts = __esm({
13606
13916
  user_id: external_exports.string().optional(),
13607
13917
  scheduled_event_date: external_exports.string().optional(),
13608
13918
  additional_context: additionalContextPayloadSchema2.optional(),
13609
- event_description: external_exports.string().optional()
13919
+ event_description: external_exports.string().optional(),
13920
+ // Closing outcome slug — required by the server only when the target is the
13921
+ // terminal status AND it declares `outcomes`. 50-char slug cap + headroom.
13922
+ outcome: external_exports.string().max(64).optional()
13610
13923
  });
13611
13924
  annotateConversationBody2 = external_exports.object({
13612
13925
  hub_id: external_exports.string().uuid(),
@@ -14020,9 +14333,6 @@ var init_contracts = __esm({
14020
14333
  adminPlanIdParam2 = external_exports.object({
14021
14334
  planId: uuidSchema2
14022
14335
  });
14023
- adminHubIdParam2 = external_exports.object({
14024
- hubId: uuidSchema2
14025
- });
14026
14336
  adminOrganizationsQuery2 = external_exports.object({
14027
14337
  page: external_exports.coerce.number().int().min(1).default(1),
14028
14338
  limit: external_exports.coerce.number().int().min(1).max(100).default(20),
@@ -14050,10 +14360,11 @@ var init_contracts = __esm({
14050
14360
  /** Kill switch for admin debug-read endpoints. 0 = off, 1 = on. */
14051
14361
  debug_read_enabled: external_exports.number().int().min(0).max(1).optional(),
14052
14362
  /**
14053
- * Harness-agents rollout gate + kill switch (harness-agents PR 2.9a/2.9b). 0 = off
14054
- * (default-deny — the per-turn kill switch aborts every harness turn on its next
14055
- * invocation), 1 = on. `wayai admin harness disable|enable` flips this. The DO's
14056
- * `updatePlatformConfig` allowlist already accepts it; this exposes it on the route.
14363
+ * The harness rollout gate + kill switch — the ONLY harness gate. 0 = off
14364
+ * (default-deny: agent create/update is refused AND the per-turn kill switch
14365
+ * aborts every harness turn on its next invocation), 1 = on. `wayai admin harness
14366
+ * disable|enable` flips this. The DO's `updatePlatformConfig` allowlist already
14367
+ * accepts it; this exposes it on the route.
14057
14368
  */
14058
14369
  harness_enabled: external_exports.number().int().min(0).max(1).optional()
14059
14370
  }).strip().refine(
@@ -14063,12 +14374,6 @@ var init_contracts = __esm({
14063
14374
  updateFreeOrgLimitBody2 = external_exports.object({
14064
14375
  max_free_orgs_override: external_exports.number().int().min(0).nullable()
14065
14376
  });
14066
- adminSetOrgHarnessBody2 = external_exports.object({
14067
- harness_enabled: external_exports.number().int().min(0).max(1)
14068
- }).strict();
14069
- adminSetHubHarnessBody2 = external_exports.object({
14070
- harness_enabled: external_exports.number().int().min(0).max(1)
14071
- }).strict();
14072
14377
  adminScopedTargetBody2 = external_exports.object({
14073
14378
  scope: external_exports.enum(["all", "org", "hub"]),
14074
14379
  org_id: external_exports.string().uuid().optional(),
@@ -14287,6 +14592,12 @@ var init_contracts = __esm({
14287
14592
  access_token: external_exports.string(),
14288
14593
  refresh_token: external_exports.string()
14289
14594
  });
14595
+ passwordLoginBody2 = external_exports.object({
14596
+ email: external_exports.string().email("Invalid email").max(254),
14597
+ // RFC 5321 max; bounds the request payload
14598
+ password: external_exports.string().min(1, "Password is required").max(128)
14599
+ // bound the payload; WorkOS validates
14600
+ });
14290
14601
  browserParams2 = external_exports.object({
14291
14602
  hubId: uuidSchema2,
14292
14603
  resourceId: uuidSchema2
@@ -14728,135 +15039,6 @@ var init_contracts = __esm({
14728
15039
  offset: external_exports.coerce.number().int().min(0).optional()
14729
15040
  });
14730
15041
  noticeIdParamSchema2 = external_exports.object({ id: external_exports.string().min(1) });
14731
- templateLocaleSchema2 = external_exports.enum(SUPPORTED_LOCALES2);
14732
- TEMPLATE_SLUG_REGEX2 = /^[a-z0-9][a-z0-9-]{0,62}$/;
14733
- templateSlugSchema2 = external_exports.string().regex(TEMPLATE_SLUG_REGEX2, "slug must be lowercase alphanumeric with hyphens (max 63)");
14734
- templateStatusSchema2 = external_exports.enum(["published", "draft", "internal"]);
14735
- templateFileMapSchema2 = external_exports.record(external_exports.string()).refine((m) => Object.keys(m).every(isSafeTemplatePath2), {
14736
- message: 'file map contains an unsafe path (no absolute paths, "..", or backslashes)'
14737
- });
14738
- TEMPLATE_INSTANCE_ID_KEYS = /* @__PURE__ */ new Set([
14739
- // Top-level hub instance metadata (hub.yaml) — set by `wayai pull`, never authored.
14740
- "hub_id",
14741
- "hub_environment",
14742
- "preview_label",
14743
- "branch_name",
14744
- // Per-entity row id + cross-entity reference UUIDs (each has a portable name twin).
14745
- "id",
14746
- "connection_id",
14747
- "target_id",
14748
- "agent_id",
14749
- "resource_id",
14750
- "list_id",
14751
- // Account-scoped Meta WhatsApp template id (name twin: `template_whatsapp`).
14752
- "template_whatsapp_id"
14753
- ]);
14754
- TEMPLATE_OPAQUE_BLOB_KEYS = /* @__PURE__ */ new Set([
14755
- "settings",
14756
- // agent + connection connector settings
14757
- "schema_json",
14758
- // agent response_format JSON Schema
14759
- "json_schema",
14760
- // state JSON Schema
14761
- "initial_value",
14762
- // state seed value
14763
- "additional_context_schema",
14764
- // kanban-status transition-form schema
14765
- "config",
14766
- // custom-tool OpenAI function schema
14767
- "headers",
14768
- "query_params",
14769
- "body_params",
14770
- // custom-tool HTTP shaping
14771
- "mappings",
14772
- // composed-tool argument mappings
14773
- "input",
14774
- "expected",
14775
- "history",
14776
- // eval message fixtures (tool_calls carry their own `id`)
14777
- "transcript",
14778
- "step_config"
14779
- // journey fixtures (transcript carries `step_id`; step_config is keyed by it)
14780
- ]);
14781
- TEMPLATE_AUTHOR_DATA_KEYS = /* @__PURE__ */ new Set([
14782
- // Outbound campaign subsystem (hub.yaml top-level). `outbound_contacts` is the
14783
- // author's real leads — `phone`/`email`/`instagram_sid` + the required `name` are
14784
- // GDPR-grade PII. `outbound_lists` group those contacts by real name. `outbound_schedules`
14785
- // bind to the (now-absent) lists and carry the author's campaign cadence + message
14786
- // copy — operationally tied to the author's customers; a consumer builds their own.
14787
- "outbound_contacts",
14788
- "outbound_lists",
14789
- "outbound_schedules",
14790
- // Account-scoped channel identifier on a connection (Twilio SID / WhatsApp number /
14791
- // IG username / from-email, per connector). The connection stays as portable
14792
- // structure re-bound by name on push; this author-account value carries no blueprint
14793
- // value. A dedicated top-level column — never nested in the `settings` opaque blob.
14794
- "account_sid"
14795
- ]);
14796
- templateTextSchema2 = external_exports.object({
14797
- metaTitle: external_exports.string().min(1).max(200),
14798
- metaDescription: external_exports.string().max(1e3).default("")
14799
- });
14800
- templateUsesEntrySchema2 = external_exports.object({
14801
- backend: templateSlugSchema2,
14802
- endpoint: templateSlugSchema2
14803
- });
14804
- templateUsesSchema2 = external_exports.array(templateUsesEntrySchema2).max(24).default([]);
14805
- templateYamlLocaleEntry2 = templateTextSchema2.extend({ source: external_exports.string().min(1) });
14806
- templateYamlWayaiBlock2 = external_exports.object({
14807
- installCommand: external_exports.string().min(1).max(300),
14808
- locales: external_exports.record(templateLocaleSchema2, templateYamlLocaleEntry2)
14809
- });
14810
- templateTagsSchema2 = external_exports.array(external_exports.string().min(1).max(30)).max(12).default([]).transform((tags) => [...new Set(tags.map((t) => t.trim().toLowerCase()).filter(Boolean))]);
14811
- templateYamlSchema2 = external_exports.object({
14812
- slug: templateSlugSchema2,
14813
- category: external_exports.string().min(1).max(60),
14814
- tags: templateTagsSchema2,
14815
- status: templateStatusSchema2.default("draft"),
14816
- order: external_exports.number().int().min(0).max(1e5).optional(),
14817
- defaultLocale: templateLocaleSchema2,
14818
- hero: external_exports.string().optional(),
14819
- // relative path to a hero image inside the template folder
14820
- // The Rekor backend(s) this channel runs on (gh #2955). Locale-agnostic. The
14821
- // cross-link + MCP endpoint are derived from each entry's slugs, never authored.
14822
- uses: templateUsesSchema2,
14823
- // A WayAI template IS a WayAI channel — the wayai slice is required. (The old
14824
- // Rekor-only store entry is gone: a pure Rekor backend lives only in Rekor's store.)
14825
- wayai: templateYamlWayaiBlock2
14826
- }).refine((c) => Boolean(c.wayai.locales[c.defaultLocale]), {
14827
- message: "`wayai.locales` must include the defaultLocale"
14828
- });
14829
- templateHeroSchema2 = external_exports.object({
14830
- filename: external_exports.string().min(1).max(200).regex(/\.(png|jpe?g|webp|gif)$/i, "hero must be a raster image (png/jpg/webp/gif)"),
14831
- dataBase64: external_exports.string().min(1).max(8e6)
14832
- });
14833
- templatePushLocaleSchema2 = external_exports.object({
14834
- wayai: templateTextSchema2.optional(),
14835
- readmeMarkdown: external_exports.string().default(""),
14836
- wayaiFiles: templateFileMapSchema2.optional()
14837
- });
14838
- templatePushBody2 = external_exports.object({
14839
- slug: templateSlugSchema2,
14840
- defaultLocale: templateLocaleSchema2,
14841
- common: external_exports.object({
14842
- category: external_exports.string().min(1).max(60),
14843
- tags: templateTagsSchema2,
14844
- status: templateStatusSchema2,
14845
- order: external_exports.number().int().min(0).max(1e5).default(0),
14846
- // The WayAI install command (a WayAI template always has a wayai side). Kept
14847
- // optional on the wire so a malformed manifest 400s on the field, not the body.
14848
- installCommand: external_exports.string().min(1).max(300).optional(),
14849
- hero: templateHeroSchema2.optional(),
14850
- // The channel→backend edge (gh #2955), locale-agnostic.
14851
- uses: templateUsesSchema2
14852
- }),
14853
- locales: external_exports.record(templateLocaleSchema2, templatePushLocaleSchema2)
14854
- }).refine((b) => Boolean(b.locales[b.defaultLocale]), {
14855
- message: "`locales` must include the defaultLocale"
14856
- });
14857
- templateListQuery2 = external_exports.object({ locale: templateLocaleSchema2.optional() });
14858
- templateSlugParam2 = external_exports.object({ slug: templateSlugSchema2 });
14859
- templateDetailQuery2 = external_exports.object({ locale: templateLocaleSchema2.optional() });
14860
15042
  ADMIN_SKILL_NAME_REGEX2 = /^[a-z0-9][a-z0-9-]{0,63}$/;
14861
15043
  adminSkillNameParam2 = external_exports.object({
14862
15044
  name: external_exports.string().regex(ADMIN_SKILL_NAME_REGEX2, "invalid skill name")
@@ -17975,6 +18157,8 @@ async function conversationsCommand(args2) {
17975
18157
  }
17976
18158
  console.log("");
17977
18159
  }
18160
+ console.log("Diagnosing agent behavior? The transcript shows what was sent \u2014 not what the model received.");
18161
+ console.log(`Drill in: wayai conversations ${conversationId} observability (per-turn resolved prompt, tool calls, latency)`);
17978
18162
  } else if (hasAnalyticsFlags) {
17979
18163
  if (status) {
17980
18164
  console.error("The --status flag is not supported with --period/--from/--to. Without these flags, --status works as before.");
@@ -22066,97 +22250,49 @@ async function runHarnessMassDestroy(flagArgs) {
22066
22250
  );
22067
22251
  }
22068
22252
  }
22069
- function resolveHarnessLayer(flagArgs, usage3) {
22070
- let orgId;
22071
- let hubId;
22072
- for (let i = 0; i < flagArgs.length; i++) {
22073
- const arg = flagArgs[i];
22074
- switch (arg) {
22075
- case "--org":
22076
- orgId = requireFlagValue(flagArgs, ++i, "--org");
22077
- break;
22078
- case "--hub":
22079
- hubId = requireFlagValue(flagArgs, ++i, "--hub");
22080
- break;
22081
- default:
22082
- console.error(`Unknown flag: ${arg}`);
22083
- console.error(usage3);
22084
- process.exit(1);
22085
- }
22086
- }
22087
- if (orgId && hubId) {
22088
- console.error("Provide at most ONE of --org <org_id> or --hub <hub_id> (or neither for the platform layer).");
22089
- console.error(usage3);
22090
- process.exit(1);
22091
- }
22092
- if (orgId) return { kind: "org", orgId };
22093
- if (hubId) return { kind: "hub", hubId };
22094
- return { kind: "platform" };
22253
+ function rejectHarnessFlags(flagArgs, usage3) {
22254
+ if (flagArgs.length === 0) return;
22255
+ console.error(`Unknown flag: ${flagArgs[0]}`);
22256
+ console.error("The harness rollout gate is platform-wide; there is no --org/--hub layer.");
22257
+ console.error(usage3);
22258
+ process.exit(1);
22095
22259
  }
22096
22260
  async function runHarnessToggle(enable, flagArgs) {
22097
- const USAGE = "wayai admin harness enable|disable [--org <org_id> | --hub <hub_id>]";
22098
- const layer = resolveHarnessLayer(flagArgs, USAGE);
22261
+ const USAGE = "wayai admin harness enable|disable";
22262
+ rejectHarnessFlags(flagArgs, USAGE);
22099
22263
  const { config, accessToken } = await requireAuth();
22100
22264
  const client = new ApiClient({ apiUrl: config.api_url, accessToken });
22101
22265
  let value;
22102
- let scopeLabel;
22103
22266
  try {
22104
- if (layer.kind === "org") {
22105
- const res = await client.adminSetOrgHarness(layer.orgId, enable ? 1 : 0);
22106
- value = res.data.harness_enabled;
22107
- scopeLabel = `org ${layer.orgId}`;
22108
- } else if (layer.kind === "hub") {
22109
- const res = await client.adminSetHubHarness(layer.hubId, enable ? 1 : 0);
22110
- value = res.data.harness_enabled;
22111
- scopeLabel = `hub ${layer.hubId}`;
22112
- } else {
22113
- const res = await client.adminUpdateConfig({ harness_enabled: enable ? 1 : 0 });
22114
- value = res.data.harness_enabled;
22115
- scopeLabel = "platform";
22116
- }
22267
+ const res = await client.adminUpdateConfig({ harness_enabled: enable ? 1 : 0 });
22268
+ value = res.data.harness_enabled;
22117
22269
  } catch (err) {
22118
22270
  exitOnApiError(err);
22119
22271
  throw err;
22120
22272
  }
22121
22273
  const state = enable ? "ENABLED" : "DISABLED";
22122
- console.log(`Harness ${state} for ${scopeLabel} (harness_enabled=${value ?? (enable ? 1 : 0)}).`);
22123
- if (layer.kind === "platform") {
22124
- if (enable) {
22125
- console.log("New harness turns may run again (subject to each hub's + org's own flag).");
22126
- } else {
22127
- console.log("The per-turn kill switch now aborts every harness turn on its next invocation.");
22128
- console.log("Next: run `wayai admin harness mass-destroy --all --dry-run` to see what is still live, then reap it.");
22129
- }
22274
+ console.log(`Harness ${state} platform-wide (harness_enabled=${value ?? (enable ? 1 : 0)}).`);
22275
+ if (enable) {
22276
+ console.log("Harness agents may be created again and new harness turns may run.");
22130
22277
  } else {
22131
- console.log("Reminder: a harness agent is creatable only when the platform, org, AND hub flags are ALL on.");
22278
+ console.log("The per-turn kill switch now aborts every harness turn on its next invocation.");
22279
+ console.log("Next: run `wayai admin harness mass-destroy --all --dry-run` to see what is still live, then reap it.");
22132
22280
  }
22133
22281
  }
22134
22282
  async function runHarnessStatus(flagArgs) {
22135
- const USAGE = "wayai admin harness status [--org <org_id> | --hub <hub_id>]";
22136
- const layer = resolveHarnessLayer(flagArgs, USAGE);
22283
+ const USAGE = "wayai admin harness status";
22284
+ rejectHarnessFlags(flagArgs, USAGE);
22137
22285
  const { config, accessToken } = await requireAuth();
22138
22286
  const client = new ApiClient({ apiUrl: config.api_url, accessToken });
22139
22287
  let value = 0;
22140
- let scopeLabel;
22141
22288
  try {
22142
- if (layer.kind === "org") {
22143
- const res = await client.adminGetOrgHarness(layer.orgId);
22144
- value = res.data.harness_enabled;
22145
- scopeLabel = `org ${layer.orgId}`;
22146
- } else if (layer.kind === "hub") {
22147
- const res = await client.adminGetHubHarness(layer.hubId);
22148
- value = res.data.harness_enabled;
22149
- scopeLabel = `hub ${layer.hubId}`;
22150
- } else {
22151
- const res = await client.adminGetConfig();
22152
- value = res.data.harness_enabled ?? 0;
22153
- scopeLabel = "platform";
22154
- }
22289
+ const res = await client.adminGetConfig();
22290
+ value = res.data.harness_enabled ?? 0;
22155
22291
  } catch (err) {
22156
22292
  exitOnApiError(err);
22157
22293
  throw err;
22158
22294
  }
22159
- console.log(`harness_enabled (${scopeLabel}): ${value} (${value ? "ENABLED" : "DISABLED"})`);
22295
+ console.log(`harness_enabled (platform): ${value} (${value ? "ENABLED" : "DISABLED"})`);
22160
22296
  }
22161
22297
  function requireFlagValue(flagArgs, index, flag) {
22162
22298
  const v = flagArgs[index];
@@ -22590,12 +22726,9 @@ Usage:
22590
22726
  wayai admin hubs repair-team-orphans --all | --org <org_id> | --hub <hub_id> [--dry-run] [--yes] [--json]
22591
22727
  Purge hub_team_id references left dangling by a pre-cascade team deletion (silently empties a support agent's queue). Idempotent \u2014 run --dry-run first
22592
22728
 
22593
- wayai admin harness disable [--org <org_id> | --hub <hub_id>]
22594
- Flip harness_enabled OFF. No scope = platform (break-glass: per-turn kill switch aborts each harness turn on its next invocation); --org/--hub target that layer of the three-layer rollout gate
22595
- wayai admin harness enable [--org <org_id> | --hub <hub_id>]
22596
- Flip harness_enabled ON. No scope = platform; --org/--hub stage the org/hub layer (a harness agent is creatable only when platform AND org AND hub are ALL on)
22597
- wayai admin harness status [--org <org_id> | --hub <hub_id>]
22598
- Print the harness_enabled flag for the chosen layer (platform by default)
22729
+ wayai admin harness disable Flip the platform harness_enabled flag OFF (break-glass: blocks harness-agent writes and the per-turn kill switch aborts each harness turn on its next invocation)
22730
+ wayai admin harness enable Flip the platform harness_enabled flag ON
22731
+ wayai admin harness status Print the platform harness_enabled flag
22599
22732
  wayai admin harness mass-destroy --all | --org <org_id> | --hub <hub_id> [--dry-run] [--yes] [--json]
22600
22733
  Reap every live harness sandbox/token/slot in scope (run --dry-run first to see the blast radius)
22601
22734
 
@@ -22632,16 +22765,13 @@ Sources:
22632
22765
  command, and destroys it. Egress omitted \u21D2 deny-all (fail-closed); opt up
22633
22766
  with --egress + --allow. The E2B key never leaves the backend. Capped at
22634
22767
  20 execs/hour/user (the strictest tier \u2014 this is arbitrary code execution).
22635
- harness Incident response + staged rollout for harness agents. \`disable\`/\`enable\`
22636
- flip the harness_enabled flag; \`status\` prints it. With no scope they
22637
- target the PLATFORM flag (disable = break-glass: the per-turn kill switch
22638
- then aborts each harness turn on its next invocation). With --org <id> or
22639
- --hub <id> they target that layer of the three-layer rollout gate (PR
22640
- 2.9a-2): a harness agent is creatable only when platform AND org AND hub
22641
- are ALL on \u2014 flip platform on, then enable per org/hub to stage. The
22642
- per-turn kill switch stays platform-only. \`mass-destroy\` reaps every
22643
- harness sandbox/token/slot that is live NOW (scope: --hub < --org < --all,
22644
- prefer the narrowest). Run \`mass-destroy --dry-run\` first to see the blast
22768
+ harness Incident response for harness agents. \`disable\`/\`enable\` flip the single
22769
+ PLATFORM-wide harness_enabled flag; \`status\` prints it. That one flag both
22770
+ gates harness-agent create/update (default-deny, fail-closed) and drives
22771
+ the per-turn kill switch, so \`disable\` is the break-glass: each harness
22772
+ turn aborts on its next invocation. \`mass-destroy\` reaps every harness
22773
+ sandbox/token/slot that is live NOW (scope: --hub < --org < --all, prefer
22774
+ the narrowest). Run \`mass-destroy --dry-run\` first to see the blast
22645
22775
  radius. See docs/runbooks/harness-incident-response.md.
22646
22776
 
22647
22777
  Types (do): ${VALID_TYPES.join(" | ")}