@wayai/cli 0.3.114 → 0.3.116

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
@@ -5661,6 +5661,14 @@ function collectTurnAttachmentHashes(turn) {
5661
5661
  }
5662
5662
  return hashes;
5663
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
+ }
5664
5672
  function foldDiacritics(input) {
5665
5673
  return input.normalize("NFKD").replace(/[̀-ͯ]/g, "");
5666
5674
  }
@@ -5929,13 +5937,49 @@ function refineHubAsCodeResources(config, ctx) {
5929
5937
  });
5930
5938
  }
5931
5939
  }
5932
- function isSafeTemplatePath(path31) {
5933
- if (path31.length === 0 || path31.length > 300) return false;
5934
- if (path31.startsWith("/") || path31.includes("\\")) return false;
5935
- const segments = path31.split("/");
5936
- return segments.every(
5937
- (seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
5938
- );
5940
+ function refineHubAsCodeDelegation(config, ctx) {
5941
+ const agents = config?.agents;
5942
+ if (!Array.isArray(agents)) return;
5943
+ agents.forEach((agent, agentIndex) => {
5944
+ const delegation = agent?.tools?.delegation;
5945
+ if (!Array.isArray(delegation)) return;
5946
+ delegation.forEach((entry, delIndex) => {
5947
+ const del = entry;
5948
+ if (del.allow_consultant_chain !== void 0) {
5949
+ const chainPath = ["agents", agentIndex, "tools", "delegation", delIndex, "allow_consultant_chain"];
5950
+ if (typeof del.allow_consultant_chain !== "boolean") {
5951
+ ctx.addIssue({
5952
+ code: external_exports.ZodIssueCode.custom,
5953
+ path: chainPath,
5954
+ message: "allow_consultant_chain must be a boolean"
5955
+ });
5956
+ } else if (del.tool !== "start_consult_thread") {
5957
+ ctx.addIssue({
5958
+ code: external_exports.ZodIssueCode.custom,
5959
+ path: chainPath,
5960
+ message: `allow_consultant_chain applies only to \`tool: start_consult_thread\` (got "${String(del.tool)}")`
5961
+ });
5962
+ }
5963
+ }
5964
+ if (del.context_boundary === void 0) return;
5965
+ const path31 = ["agents", agentIndex, "tools", "delegation", delIndex, "context_boundary"];
5966
+ if (del.type !== "hub") {
5967
+ ctx.addIssue({
5968
+ code: external_exports.ZodIssueCode.custom,
5969
+ path: path31,
5970
+ message: `context_boundary applies only to \`type: hub\` delegations (got type "${String(del.type)}")`
5971
+ });
5972
+ return;
5973
+ }
5974
+ if (!CONTEXT_BOUNDARIES.includes(del.context_boundary)) {
5975
+ ctx.addIssue({
5976
+ code: external_exports.ZodIssueCode.custom,
5977
+ path: path31,
5978
+ message: `context_boundary must be one of: ${CONTEXT_BOUNDARIES.join(", ")}`
5979
+ });
5980
+ }
5981
+ });
5982
+ });
5939
5983
  }
5940
5984
  function identifyTokenType(token) {
5941
5985
  if (token.startsWith("way_")) return "way_token";
@@ -5976,7 +6020,7 @@ function findStepBoundaries(transcript) {
5976
6020
  }
5977
6021
  return out;
5978
6022
  }
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, 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, 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, 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;
6023
+ 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, CONTEXT_BOUNDARIES, contextBoundarySchema, addNativeToolBody, addMcpToolBody, createCustomToolBody, updateCustomToolBody, updateToolExecutionConfigBody, initialValueCreateSchema, initialValueUpdateSchema, stateIdParam, listStatesQuery, stateNameSchema, createStateBody, updateStateBody, reorderStatesBody, variantAiModeSchema, experimentStatusSchema, overlayUpdateSchema, experimentIdParam, variantIdParam, listExperimentsQuery, listVariantsQuery, listOverridesQuery, deleteOverrideQuery, createExperimentBody, updateExperimentBody, setExperimentStatusBody, createVariantBody, updateVariantBody, upsertOverrideBody, orgTagIdParam, listOrgTagsQuery, createOrgTagBody, updateOrgTagBody, orgCredentialIdParam, listOrgCredentialsQuery, createOrgCredentialBody, updateOrgCredentialBody, orgResourceIdParam, orgResourceFileIdParam, orgResourceFolderIdParam, hubOrgResourceParam, listOrgResourcesQuery, orgIdQuery, createOrgResourceBody, updateOrgResourceBody, createOrgResourceFolderBody, updateOrgResourceFolderBody, uploadOrgResourceFileBody, updateOrgResourceFileBody, uploadOrgSkillZipBody, linkOrgResourceBody, resourceIdParam, listResourcesQuery, createResourceBody, updateResourceBody, syncSkillsBody, resourceFileIdParam, listResourceFilesQuery, createResourceFileBody, updateResourceFileBody, uploadResourceFileBody, uploadSkillZipBody, resourceFolderIdParam, listResourceFoldersQuery, createResourceFolderBody, updateResourceFolderBody, agentResourceQuery, hubResourceQuery, linkAgentResourceBody, updateAgentResourceBody, unlinkAgentResourceQuery, navItemSchema, hubCountResetBody, navItemCountResetBody, typingBody, analyticsHubIdParam, analyticsVariableIdParam, updateVariablePinBody, updateAnalyticsViewBody, NUMERIC_FILTER_OPS, TEXT_FILTER_OPS, CATEGORICAL_FILTER_OPS, VARIABLE_FILTER_OPS, STRUCTURED_QUERY_OPS, STRUCTURED_QUERY_AGGREGATIONS, filterValueSchema, conversationsBody, analyticsConversationIdParam, messagesQuery, conversationDetailDataQuery, analyticsDataBody, structuredQueryBody, analyticsSqlBody, 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, copilotSuggestBody, copilotSuggestResponse, CONSULT_THREAD_STATUSES, consultThreadStatus, CONSULT_THREAD_TITLE_MAX, consultThreadTitle, consultThreadSummary, listConsultThreadsQuery, listConsultThreadsResponse, createConsultThreadBody, createConsultThreadResponse, consultThreadIdParam, updateConsultThreadBody, updateConsultThreadResponse, CONSULT_AWAIT_TIMEOUT_MS, billingOrgIdParam, subscriptionItemParams, spendCapBody, growthPacksBody, portalSessionBody, checkoutSessionBody, updateBillingCurrencyBody, invoicesQuery, downloadBody, uploadQuery, signUrlBody, outboundSchemaQuery, templateIdParam, listTemplatesQuery, deleteTemplateQuery, templateStatusQuery, createTemplateBody, updateTemplateBody, submitTemplateBody, testTemplateBody, contactIdParam, listContactsQuery, createContactBody, updateContactBody, listIdParam, listListsQuery, listListContactsQuery, createListBody, updateListBody, addListContactsBody, removeListContactsBody, scheduleIdParam, listSchedulesQuery, listExecutionsQuery, createScheduleBody, updateScheduleBody, MAX_RESOURCE_FILE_SIZE, MAX_10MB_BASE64_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_CARRIERS, MAX_EVAL_ATTACHMENT_AGGREGATE_ENCODED_BYTES, MAX_RESOURCE_ENCODED_BYTES, MAX_HUB_AS_CODE_RESOURCES, MAX_HUB_AS_CODE_RESOURCE_FILES, MAX_RESOURCE_AGGREGATE_ENCODED_BYTES, MAX_CI_CONFIG_BODY_BYTES, 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;
5980
6024
  var init_dist = __esm({
5981
6025
  "../../packages/core/dist/index.js"() {
5982
6026
  "use strict";
@@ -6028,6 +6072,9 @@ var init_dist = __esm({
6028
6072
  init_zod();
6029
6073
  init_zod();
6030
6074
  init_zod();
6075
+ init_zod();
6076
+ init_zod();
6077
+ init_zod();
6031
6078
  UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
6032
6079
  HEX_RE = /^[0-9a-f]{16,}$/;
6033
6080
  WORKOS_ID_RE = /^(?:user|org)_[0-9A-HJKMNP-TV-Z]{26}$/;
@@ -6224,7 +6271,8 @@ var init_dist = __esm({
6224
6271
  "monitor",
6225
6272
  "conversation_evaluator",
6226
6273
  "message_evaluator",
6227
- "summarizer"
6274
+ "summarizer",
6275
+ "consultant"
6228
6276
  ];
6229
6277
  SAFE_USER_ID_REGEX = /^[A-Za-z0-9_-]{1,64}$/;
6230
6278
  SUPPORTED_LOCALES = ["en", "pt", "es"];
@@ -6401,6 +6449,12 @@ var init_dist = __esm({
6401
6449
  });
6402
6450
  }
6403
6451
  });
6452
+ MAX_OUTCOMES_PER_STATUS = 20;
6453
+ kanbanOutcomeSchema = external_exports.object({
6454
+ slug: kanbanStatusSlugSchema,
6455
+ 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"),
6456
+ color: external_exports.string().optional()
6457
+ }).passthrough();
6404
6458
  EXCLUSIVE_FLAG_PAIRS = [
6405
6459
  ["isInitialStatus", "triggersAgentResponse"],
6406
6460
  ["isInitialStatus", "allowsAgentUpdate"],
@@ -6436,7 +6490,10 @@ var init_dist = __esm({
6436
6490
  * and is not exposed to agents. The cross-reference invariant (must point at a
6437
6491
  * declared lane; the initial status must not have one) is enforced at the hub
6438
6492
  * level via `validateLaneReferences` — this schema only sees the status array. */
6439
- lane_slug: kanbanStatusSlugSchema.optional()
6493
+ lane_slug: kanbanStatusSlugSchema.optional(),
6494
+ /** Closing outcomes offered on the terminal transition. Only valid when
6495
+ * `isTerminalStatus === true` (enforced in the superRefine below). */
6496
+ outcomes: external_exports.array(kanbanOutcomeSchema).max(MAX_OUTCOMES_PER_STATUS, `outcomes must have at most ${MAX_OUTCOMES_PER_STATUS} entries`).optional()
6440
6497
  }).passthrough().superRefine((status, ctx) => {
6441
6498
  const label = status.name ? `"${status.name}"` : status.slug ? `"${status.slug}"` : "<unnamed>";
6442
6499
  for (const [a, b] of EXCLUSIVE_FLAG_PAIRS) {
@@ -6473,6 +6530,33 @@ var init_dist = __esm({
6473
6530
  });
6474
6531
  }
6475
6532
  }
6533
+ if (Array.isArray(status.outcomes) && status.outcomes.length > 0) {
6534
+ if (status.isTerminalStatus !== true) {
6535
+ ctx.addIssue({
6536
+ code: external_exports.ZodIssueCode.custom,
6537
+ path: ["outcomes"],
6538
+ message: `kanban status ${label}: outcomes are only allowed on the terminal status (set isTerminalStatus=true)`
6539
+ });
6540
+ }
6541
+ const seen = /* @__PURE__ */ new Map();
6542
+ status.outcomes.forEach((o, j) => {
6543
+ if (!o?.slug) return;
6544
+ const arr = seen.get(o.slug) ?? [];
6545
+ arr.push(j);
6546
+ seen.set(o.slug, arr);
6547
+ });
6548
+ for (const [slug, indices] of seen) {
6549
+ if (indices.length > 1) {
6550
+ for (const j of indices) {
6551
+ ctx.addIssue({
6552
+ code: external_exports.ZodIssueCode.custom,
6553
+ path: ["outcomes", j, "slug"],
6554
+ message: `kanban status ${label}: duplicate outcome slug "${slug}"`
6555
+ });
6556
+ }
6557
+ }
6558
+ }
6559
+ }
6476
6560
  });
6477
6561
  kanbanStatusesArraySchema = external_exports.array(kanbanStatusSchema).max(MAX_KANBAN_STATUSES, `kanban_statuses must have at most ${MAX_KANBAN_STATUSES} entries`).superRefine((statuses, ctx) => {
6478
6562
  if (statuses.length === 0) return;
@@ -6493,6 +6577,17 @@ var init_dist = __esm({
6493
6577
  });
6494
6578
  }
6495
6579
  }
6580
+ const terminalIndices = statuses.map((s, i) => ({ s, i })).filter(({ s }) => s.isTerminalStatus === true);
6581
+ if (terminalIndices.length > 1) {
6582
+ const slugs = terminalIndices.map(({ s }) => s.slug).join(", ");
6583
+ for (const { i } of terminalIndices) {
6584
+ ctx.addIssue({
6585
+ code: external_exports.ZodIssueCode.custom,
6586
+ path: [i, "isTerminalStatus"],
6587
+ message: `kanban_statuses: at most one status may have isTerminalStatus=true (found ${terminalIndices.length}: ${slugs})`
6588
+ });
6589
+ }
6590
+ }
6496
6591
  const seenSlugs = /* @__PURE__ */ new Map();
6497
6592
  statuses.forEach((s, i) => {
6498
6593
  const key = s.slug;
@@ -6693,7 +6788,7 @@ var init_dist = __esm({
6693
6788
  hub_id: uuidSchema,
6694
6789
  sync_credentials_to_production: external_exports.boolean().optional()
6695
6790
  }).passthrough();
6696
- PRODUCTION_DIRECT_FIELDS = ["username", "api_key", "access_token", "password", "refresh_token", "webhook_secret_token"];
6791
+ PRODUCTION_DIRECT_FIELDS = ["username", "api_key", "access_token", "password", "refresh_token", "webhook_secret_token", "webhook_signing_secret"];
6697
6792
  setProductionCredentialBody = external_exports.object({
6698
6793
  hub_id: uuidSchema,
6699
6794
  organization_credential_id: external_exports.string().nullable().optional(),
@@ -6703,7 +6798,8 @@ var init_dist = __esm({
6703
6798
  access_token: external_exports.string().optional(),
6704
6799
  password: external_exports.string().optional(),
6705
6800
  refresh_token: external_exports.string().optional(),
6706
- webhook_secret_token: external_exports.string().optional()
6801
+ webhook_secret_token: external_exports.string().optional(),
6802
+ webhook_signing_secret: external_exports.string().optional()
6707
6803
  }).strict().superRefine((data, ctx) => {
6708
6804
  const hasOrgLink = !!data.organization_credential_id || !!data.organization_credential_token_id;
6709
6805
  const hasDirect = PRODUCTION_DIRECT_FIELDS.some((f) => data[f] != null);
@@ -6748,13 +6844,19 @@ var init_dist = __esm({
6748
6844
  deleteToolQuery = external_exports.object({ agent_id: uuidSchema.optional(), hub_id: uuidSchema });
6749
6845
  toolConnectionsQuery = external_exports.object({ hub_id: uuidSchema });
6750
6846
  nativeToolIdSchema = external_exports.string().regex(/^nt-\d{3,}$/, "Invalid native tool id");
6847
+ CONTEXT_BOUNDARIES = ["instruction", "summary", "transcript"];
6848
+ contextBoundarySchema = external_exports.enum(CONTEXT_BOUNDARIES);
6751
6849
  addNativeToolBody = external_exports.object({
6752
6850
  agent_id: uuidSchema,
6753
6851
  hub_id: uuidSchema,
6754
6852
  tool_native_id: nativeToolIdSchema,
6755
- delegation_type: external_exports.enum(["team", "agent"]).optional(),
6853
+ delegation_type: external_exports.enum(["team", "agent", "hub"]).optional(),
6756
6854
  delegation_id: external_exports.string().optional(),
6757
6855
  delegation_name: external_exports.string().optional(),
6856
+ /** Only meaningful for a `hub` delegation (`delegate_to_hub`); ignored otherwise.
6857
+ * Defaults to `summary` when omitted. Admin-set — the link and boundary require
6858
+ * hub-admin (`hub:write`), never derived from any end user's grants. */
6859
+ delegation_context_boundary: contextBoundarySchema.optional(),
6758
6860
  resource_config: external_exports.object({
6759
6861
  access_mode: external_exports.enum(["all", "selected", "none"]),
6760
6862
  enabled_resources: external_exports.array(external_exports.string()).optional()
@@ -7558,6 +7660,38 @@ var init_dist = __esm({
7558
7660
  });
7559
7661
  appMessageSenderType = external_exports.enum(["user", "team"]);
7560
7662
  appMessageReceiverType = external_exports.enum(["user", "team", "agent", "assistant"]).transform((v) => v === "assistant" ? "agent" : v);
7663
+ apiChannelMessage = external_exports.object({
7664
+ text: clientOptionalString,
7665
+ attachments: external_exports.array(messageAttachment).max(MAX_ATTACHMENTS_PER_MESSAGE).nullish().transform((v) => v ?? void 0)
7666
+ }).refine((m) => m.text && m.text.length > 0 || m.attachments && m.attachments.length > 0, {
7667
+ message: "message must have text or at least one attachment"
7668
+ });
7669
+ apiChannelMessageBody = external_exports.object({
7670
+ // Correlation id (task hubs): new → new conversation, repeat → continue. min 1 so an
7671
+ // empty string can't masquerade as a ref. Mutually exclusive with conversation_id.
7672
+ external_ref: external_exports.string().min(1).max(256).optional(),
7673
+ // Continue a specific WayAI conversation (authorized against the hub/channel + owner).
7674
+ // UUID-validated here (unlike the app channel, whose client we control): allocation
7675
+ // only treats a UUID-shaped id as a provided conversation, so a malformed id would
7676
+ // otherwise skip the owner guard and silently MINT a new conversation instead of
7677
+ // rejecting. A format 400 is shape-only — not an existence oracle (a valid-but-unknown
7678
+ // UUID still collapses to the opaque authorization error downstream).
7679
+ conversation_id: external_exports.string().uuid().optional(),
7680
+ // On-behalf-of end-user identity. Absent → per-connection service principal (task-hub
7681
+ // only; chat hub rejects with 422 in the route).
7682
+ user: external_exports.object({
7683
+ id: external_exports.string().min(1),
7684
+ email: clientOptionalString,
7685
+ name: clientOptionalString
7686
+ }).optional(),
7687
+ message: apiChannelMessage,
7688
+ // Idempotency key: maps to channel_message_sid; a retried POST echoes the original
7689
+ // message_id and skips billing / turn dispatch (dedupe in ConversationDO.storeMessage).
7690
+ client_message_id: external_exports.string().min(1).max(256).optional()
7691
+ }).refine((b) => !(b.external_ref && b.conversation_id), {
7692
+ message: "provide external_ref or conversation_id, not both",
7693
+ path: ["external_ref"]
7694
+ });
7561
7695
  appMessageBody = external_exports.object({
7562
7696
  // Message content — three historical aliases. All optional: an attachment-only
7563
7697
  // or voice-only message carries no text.
@@ -7581,6 +7715,19 @@ var init_dist = __esm({
7581
7715
  // caller may send to this receiver. The end-user branch ignores it — see the
7582
7716
  // receiver derivation in the route.
7583
7717
  user_receiver_id: clientOptionalString,
7718
+ // ── Internal consult (consultant-agents PR 2 — H1.0) ──────────────────────
7719
+ // A team member handling a customer conversation can tag a `consultant`-role
7720
+ // agent for a PRIVATE, team-only exchange that never reaches the customer. A
7721
+ // consult send is a team send with `receiver_type: 'agent'` targeting the
7722
+ // consultant; the still-required `user_receiver_id` identifies the customer whose
7723
+ // conversation this is (and is authorized by `validateAppTeamSendContext`, exactly
7724
+ // as a team→user send is). The consultant is resolved from `agent_receiver_id`
7725
+ // when supplied, else from an `@mention` parsed out of the message text against
7726
+ // the hub's consultant agents. `consult_thread_id` continues an existing thread;
7727
+ // absent, the route creates/reuses the single implicit thread. These fields are
7728
+ // inert on every non-consult send (end-user send, team→user send).
7729
+ agent_receiver_id: clientOptionalString,
7730
+ consult_thread_id: clientOptionalString,
7584
7731
  is_first_message: clientOptionalBoolean,
7585
7732
  end_conversation: clientOptionalBoolean,
7586
7733
  // Pre-generated by the client so the optimistic bubble and the stored row share
@@ -7633,6 +7780,95 @@ var init_dist = __esm({
7633
7780
  /** Type-to-confirm value; must equal the user's email (constant-time compared). */
7634
7781
  email_confirmation: external_exports.string().min(1).max(320)
7635
7782
  });
7783
+ templateLocaleSchema = external_exports.enum(SUPPORTED_LOCALES);
7784
+ TEMPLATE_SLUG_REGEX = /^[a-z0-9][a-z0-9-]{0,62}$/;
7785
+ templateSlugSchema = external_exports.string().regex(TEMPLATE_SLUG_REGEX, "slug must be lowercase alphanumeric with hyphens (max 63)");
7786
+ templateStatusSchema = external_exports.enum(["published", "draft", "internal"]);
7787
+ templateFileMapSchema = external_exports.record(external_exports.string()).refine((m) => Object.keys(m).every(isSafeTemplatePath), {
7788
+ message: 'file map contains an unsafe path (no absolute paths, "..", or backslashes)'
7789
+ });
7790
+ templateTextSchema = external_exports.object({
7791
+ metaTitle: external_exports.string().min(1).max(200),
7792
+ metaDescription: external_exports.string().max(1e3).default("")
7793
+ });
7794
+ templateUsesEntrySchema = external_exports.object({
7795
+ backend: templateSlugSchema,
7796
+ endpoint: templateSlugSchema
7797
+ });
7798
+ templateUsesSchema = external_exports.array(templateUsesEntrySchema).max(24).default([]);
7799
+ templateYamlLocaleEntry = templateTextSchema.extend({ source: external_exports.string().min(1) });
7800
+ templateYamlWayaiBlock = external_exports.object({
7801
+ installCommand: external_exports.string().min(1).max(300),
7802
+ locales: external_exports.record(templateLocaleSchema, templateYamlLocaleEntry)
7803
+ });
7804
+ 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))]);
7805
+ templateYamlSchema = external_exports.object({
7806
+ slug: templateSlugSchema,
7807
+ category: external_exports.string().min(1).max(60),
7808
+ tags: templateTagsSchema,
7809
+ status: templateStatusSchema.default("draft"),
7810
+ order: external_exports.number().int().min(0).max(1e5).optional(),
7811
+ defaultLocale: templateLocaleSchema,
7812
+ hero: external_exports.string().optional(),
7813
+ // relative path to a hero image inside the template folder
7814
+ // The Rekor backend(s) this channel runs on (gh #2955). Locale-agnostic. The
7815
+ // cross-link + MCP endpoint are derived from each entry's slugs, never authored.
7816
+ uses: templateUsesSchema,
7817
+ // A WayAI template IS a WayAI channel — the wayai slice is required. (The old
7818
+ // Rekor-only store entry is gone: a pure Rekor backend lives only in Rekor's store.)
7819
+ wayai: templateYamlWayaiBlock
7820
+ }).refine((c) => Boolean(c.wayai.locales[c.defaultLocale]), {
7821
+ message: "`wayai.locales` must include the defaultLocale"
7822
+ });
7823
+ templateHeroSchema = external_exports.object({
7824
+ 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)"),
7825
+ dataBase64: external_exports.string().min(1).max(8e6)
7826
+ });
7827
+ templatePushLocaleSchema = external_exports.object({
7828
+ wayai: templateTextSchema.optional(),
7829
+ readmeMarkdown: external_exports.string().default(""),
7830
+ wayaiFiles: templateFileMapSchema.optional()
7831
+ });
7832
+ templatePushBody = external_exports.object({
7833
+ slug: templateSlugSchema,
7834
+ defaultLocale: templateLocaleSchema,
7835
+ common: external_exports.object({
7836
+ category: external_exports.string().min(1).max(60),
7837
+ tags: templateTagsSchema,
7838
+ status: templateStatusSchema,
7839
+ order: external_exports.number().int().min(0).max(1e5).default(0),
7840
+ // The WayAI install command (a WayAI template always has a wayai side). Kept
7841
+ // optional on the wire so a malformed manifest 400s on the field, not the body.
7842
+ installCommand: external_exports.string().min(1).max(300).optional(),
7843
+ hero: templateHeroSchema.optional(),
7844
+ // The channel→backend edge (gh #2955), locale-agnostic.
7845
+ uses: templateUsesSchema
7846
+ }),
7847
+ locales: external_exports.record(templateLocaleSchema, templatePushLocaleSchema)
7848
+ }).refine((b) => Boolean(b.locales[b.defaultLocale]), {
7849
+ message: "`locales` must include the defaultLocale"
7850
+ });
7851
+ templateListQuery = external_exports.object({ locale: templateLocaleSchema.optional() });
7852
+ templateSlugParam = external_exports.object({ slug: templateSlugSchema });
7853
+ templateDetailQuery = external_exports.object({ locale: templateLocaleSchema.optional() });
7854
+ courseQuizScoreSchema = external_exports.object({
7855
+ correct: external_exports.number().int().min(0).max(50),
7856
+ total: external_exports.number().int().min(1).max(50),
7857
+ /** Chosen choice index per question; -1 = unanswered. */
7858
+ answers: external_exports.array(external_exports.number().int().min(-1).max(50)).max(50).optional()
7859
+ });
7860
+ upsertCourseLessonBody = external_exports.object({
7861
+ quiz_passed: external_exports.boolean().optional(),
7862
+ quiz_score: courseQuizScoreSchema.optional(),
7863
+ content_version: external_exports.number().int().min(1)
7864
+ }).strict();
7865
+ linkCourseCapstoneBody = external_exports.object({
7866
+ hub_id: external_exports.string().min(1).max(128),
7867
+ // A capstone's slug IS a canonical template slug — reuse the one validator
7868
+ // the template pipeline (CLI, admin, gallery) already enforces, so course
7869
+ // linking can't drift from how real template slugs are shaped.
7870
+ template_slug: templateSlugSchema.optional()
7871
+ }).strict();
7636
7872
  archiveHubIdParam = external_exports.object({
7637
7873
  hubId: external_exports.string().uuid()
7638
7874
  });
@@ -7726,7 +7962,10 @@ var init_dist = __esm({
7726
7962
  user_id: external_exports.string().optional(),
7727
7963
  scheduled_event_date: external_exports.string().optional(),
7728
7964
  additional_context: additionalContextPayloadSchema.optional(),
7729
- event_description: external_exports.string().optional()
7965
+ event_description: external_exports.string().optional(),
7966
+ // Closing outcome slug — required by the server only when the target is the
7967
+ // terminal status AND it declares `outcomes`. 50-char slug cap + headroom.
7968
+ outcome: external_exports.string().max(64).optional()
7730
7969
  });
7731
7970
  annotateConversationBody = external_exports.object({
7732
7971
  hub_id: external_exports.string().uuid(),
@@ -7814,6 +8053,59 @@ var init_dist = __esm({
7814
8053
  external_exports.record(external_exports.string().max(128), external_exports.string().max(2048)).refine((r) => Object.keys(r).length <= 50, "too many variables")
7815
8054
  ]).optional()
7816
8055
  });
8056
+ copilotSuggestBody = external_exports.object({
8057
+ hub_id: external_exports.string().uuid()
8058
+ });
8059
+ copilotSuggestResponse = external_exports.object({
8060
+ status: external_exports.enum(["processing", "skipped"]),
8061
+ reason: external_exports.string().optional()
8062
+ });
8063
+ CONSULT_THREAD_STATUSES = ["open", "awaiting", "resolved", "cancelled_at_close"];
8064
+ consultThreadStatus = external_exports.enum(CONSULT_THREAD_STATUSES);
8065
+ CONSULT_THREAD_TITLE_MAX = 120;
8066
+ consultThreadTitle = external_exports.string().trim().min(1).max(CONSULT_THREAD_TITLE_MAX);
8067
+ consultThreadSummary = external_exports.object({
8068
+ consult_thread_id: external_exports.string(),
8069
+ conversation_id: external_exports.string(),
8070
+ initiator_type: external_exports.enum(["team", "agent"]),
8071
+ initiator_id: external_exports.string(),
8072
+ engaged_agent_id: external_exports.string().nullable(),
8073
+ engaged_agent_name: external_exports.string().nullable(),
8074
+ title: external_exports.string().nullable(),
8075
+ status: consultThreadStatus,
8076
+ created_at: external_exports.string()
8077
+ });
8078
+ listConsultThreadsQuery = external_exports.object({
8079
+ hub_id: external_exports.string().uuid()
8080
+ });
8081
+ listConsultThreadsResponse = external_exports.object({
8082
+ threads: external_exports.array(consultThreadSummary)
8083
+ });
8084
+ createConsultThreadBody = external_exports.object({
8085
+ hub_id: external_exports.string().uuid(),
8086
+ title: consultThreadTitle.optional(),
8087
+ // Optionally engage a consultant on creation. Validated server-side against the
8088
+ // hub's `consultant`-role agents; a non-consultant / unknown id is rejected.
8089
+ engaged_agent_id: external_exports.string().uuid().optional()
8090
+ });
8091
+ createConsultThreadResponse = external_exports.object({
8092
+ thread: consultThreadSummary
8093
+ });
8094
+ consultThreadIdParam = external_exports.object({
8095
+ id: external_exports.string().uuid(),
8096
+ threadId: external_exports.string().uuid()
8097
+ });
8098
+ updateConsultThreadBody = external_exports.object({
8099
+ hub_id: external_exports.string().uuid(),
8100
+ title: consultThreadTitle.optional(),
8101
+ engaged_agent_id: external_exports.string().uuid().optional()
8102
+ }).refine((v) => v.title !== void 0 || v.engaged_agent_id !== void 0, {
8103
+ message: "Provide a title and/or an engaged_agent_id to update"
8104
+ });
8105
+ updateConsultThreadResponse = external_exports.object({
8106
+ thread: consultThreadSummary
8107
+ });
8108
+ CONSULT_AWAIT_TIMEOUT_MS = 15 * 6e4;
7817
8109
  billingOrgIdParam = external_exports.object({
7818
8110
  organizationId: external_exports.string().uuid()
7819
8111
  });
@@ -8061,6 +8353,7 @@ var init_dist = __esm({
8061
8353
  refineHubAsCodeEvals(config, ctx);
8062
8354
  refineHubAsCodeEvalAttachments(config, ctx);
8063
8355
  refineHubAsCodeResources(config, ctx);
8356
+ refineHubAsCodeDelegation(config, ctx);
8064
8357
  });
8065
8358
  ciPullHubIdParam = external_exports.object({
8066
8359
  hub_id: ciUuidSchema
@@ -8399,6 +8692,12 @@ var init_dist = __esm({
8399
8692
  access_token: external_exports.string(),
8400
8693
  refresh_token: external_exports.string()
8401
8694
  });
8695
+ passwordLoginBody = external_exports.object({
8696
+ email: external_exports.string().email("Invalid email").max(254),
8697
+ // RFC 5321 max; bounds the request payload
8698
+ password: external_exports.string().min(1, "Password is required").max(128)
8699
+ // bound the payload; WorkOS validates
8700
+ });
8402
8701
  browserParams = external_exports.object({
8403
8702
  hubId: uuidSchema,
8404
8703
  resourceId: uuidSchema
@@ -8840,77 +9139,6 @@ var init_dist = __esm({
8840
9139
  offset: external_exports.coerce.number().int().min(0).optional()
8841
9140
  });
8842
9141
  noticeIdParamSchema = external_exports.object({ id: external_exports.string().min(1) });
8843
- templateLocaleSchema = external_exports.enum(SUPPORTED_LOCALES);
8844
- TEMPLATE_SLUG_REGEX = /^[a-z0-9][a-z0-9-]{0,62}$/;
8845
- templateSlugSchema = external_exports.string().regex(TEMPLATE_SLUG_REGEX, "slug must be lowercase alphanumeric with hyphens (max 63)");
8846
- templateStatusSchema = external_exports.enum(["published", "draft", "internal"]);
8847
- templateFileMapSchema = external_exports.record(external_exports.string()).refine((m) => Object.keys(m).every(isSafeTemplatePath), {
8848
- message: 'file map contains an unsafe path (no absolute paths, "..", or backslashes)'
8849
- });
8850
- templateTextSchema = external_exports.object({
8851
- metaTitle: external_exports.string().min(1).max(200),
8852
- metaDescription: external_exports.string().max(1e3).default("")
8853
- });
8854
- templateUsesEntrySchema = external_exports.object({
8855
- backend: templateSlugSchema,
8856
- endpoint: templateSlugSchema
8857
- });
8858
- templateUsesSchema = external_exports.array(templateUsesEntrySchema).max(24).default([]);
8859
- templateYamlLocaleEntry = templateTextSchema.extend({ source: external_exports.string().min(1) });
8860
- templateYamlWayaiBlock = external_exports.object({
8861
- installCommand: external_exports.string().min(1).max(300),
8862
- locales: external_exports.record(templateLocaleSchema, templateYamlLocaleEntry)
8863
- });
8864
- 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))]);
8865
- templateYamlSchema = external_exports.object({
8866
- slug: templateSlugSchema,
8867
- category: external_exports.string().min(1).max(60),
8868
- tags: templateTagsSchema,
8869
- status: templateStatusSchema.default("draft"),
8870
- order: external_exports.number().int().min(0).max(1e5).optional(),
8871
- defaultLocale: templateLocaleSchema,
8872
- hero: external_exports.string().optional(),
8873
- // relative path to a hero image inside the template folder
8874
- // The Rekor backend(s) this channel runs on (gh #2955). Locale-agnostic. The
8875
- // cross-link + MCP endpoint are derived from each entry's slugs, never authored.
8876
- uses: templateUsesSchema,
8877
- // A WayAI template IS a WayAI channel — the wayai slice is required. (The old
8878
- // Rekor-only store entry is gone: a pure Rekor backend lives only in Rekor's store.)
8879
- wayai: templateYamlWayaiBlock
8880
- }).refine((c) => Boolean(c.wayai.locales[c.defaultLocale]), {
8881
- message: "`wayai.locales` must include the defaultLocale"
8882
- });
8883
- templateHeroSchema = external_exports.object({
8884
- 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)"),
8885
- dataBase64: external_exports.string().min(1).max(8e6)
8886
- });
8887
- templatePushLocaleSchema = external_exports.object({
8888
- wayai: templateTextSchema.optional(),
8889
- readmeMarkdown: external_exports.string().default(""),
8890
- wayaiFiles: templateFileMapSchema.optional()
8891
- });
8892
- templatePushBody = external_exports.object({
8893
- slug: templateSlugSchema,
8894
- defaultLocale: templateLocaleSchema,
8895
- common: external_exports.object({
8896
- category: external_exports.string().min(1).max(60),
8897
- tags: templateTagsSchema,
8898
- status: templateStatusSchema,
8899
- order: external_exports.number().int().min(0).max(1e5).default(0),
8900
- // The WayAI install command (a WayAI template always has a wayai side). Kept
8901
- // optional on the wire so a malformed manifest 400s on the field, not the body.
8902
- installCommand: external_exports.string().min(1).max(300).optional(),
8903
- hero: templateHeroSchema.optional(),
8904
- // The channel→backend edge (gh #2955), locale-agnostic.
8905
- uses: templateUsesSchema
8906
- }),
8907
- locales: external_exports.record(templateLocaleSchema, templatePushLocaleSchema)
8908
- }).refine((b) => Boolean(b.locales[b.defaultLocale]), {
8909
- message: "`locales` must include the defaultLocale"
8910
- });
8911
- templateListQuery = external_exports.object({ locale: templateLocaleSchema.optional() });
8912
- templateSlugParam = external_exports.object({ slug: templateSlugSchema });
8913
- templateDetailQuery = external_exports.object({ locale: templateLocaleSchema.optional() });
8914
9142
  ADMIN_SKILL_NAME_REGEX = /^[a-z0-9][a-z0-9-]{0,63}$/;
8915
9143
  adminSkillNameParam = external_exports.object({
8916
9144
  name: external_exports.string().regex(ADMIN_SKILL_NAME_REGEX, "invalid skill name")
@@ -10131,6 +10359,18 @@ var init_token_store = __esm({
10131
10359
  }
10132
10360
  });
10133
10361
 
10362
+ // src/lib/expected.ts
10363
+ function expected(message) {
10364
+ const err = new Error(message);
10365
+ err.isExpected = true;
10366
+ return err;
10367
+ }
10368
+ var init_expected = __esm({
10369
+ "src/lib/expected.ts"() {
10370
+ "use strict";
10371
+ }
10372
+ });
10373
+
10134
10374
  // src/lib/auth.ts
10135
10375
  var auth_exports = {};
10136
10376
  __export(auth_exports, {
@@ -10279,7 +10519,7 @@ async function getAccessToken(config) {
10279
10519
  await migrateLegacyTokens();
10280
10520
  const resolved = await getToken();
10281
10521
  if (!resolved) {
10282
- throw new Error("No token found. Run `wayai login` to authenticate.");
10522
+ throw expected("No token found. Run `wayai login` to authenticate.");
10283
10523
  }
10284
10524
  if (resolved.kind === "way") {
10285
10525
  return resolved.token;
@@ -10292,7 +10532,7 @@ async function getAccessToken(config) {
10292
10532
  return resolved.access_token;
10293
10533
  }
10294
10534
  if (!resolved.refresh_token) {
10295
- throw new Error("Access token expired and no refresh token available. Run `wayai login` again.");
10535
+ throw expected("Access token expired and no refresh token available. Run `wayai login` again.");
10296
10536
  }
10297
10537
  try {
10298
10538
  const result = await refreshAccessToken(
@@ -10307,7 +10547,7 @@ async function getAccessToken(config) {
10307
10547
  if (err instanceof Error && err.message === "SESSION_EXPIRED") {
10308
10548
  await clearTokens();
10309
10549
  writeConfig({ api_url: config.api_url });
10310
- throw new Error("Session expired. Please run `wayai login` again.");
10550
+ throw expected("Session expired. Please run `wayai login` again.");
10311
10551
  }
10312
10552
  throw err;
10313
10553
  }
@@ -10334,6 +10574,7 @@ var init_auth = __esm({
10334
10574
  "use strict";
10335
10575
  init_config();
10336
10576
  init_token_store();
10577
+ init_expected();
10337
10578
  init_sentry();
10338
10579
  init_mask_secrets();
10339
10580
  OAUTH_CALLBACK_PORT = 3829;
@@ -11707,34 +11948,72 @@ function collectTurnAttachmentHashes2(turn) {
11707
11948
  }
11708
11949
  return hashes;
11709
11950
  }
11710
- function refineHubAsCodeCustomTools2(config, ctx) {
11711
- const agents = config.agents;
11712
- if (!Array.isArray(agents)) return;
11713
- for (let a = 0; a < agents.length; a++) {
11714
- const agent = agents[a];
11715
- const custom2 = agent?.tools?.custom;
11716
- if (!Array.isArray(custom2)) continue;
11717
- for (let c = 0; c < custom2.length; c++) {
11718
- const tool = custom2[c];
11719
- const raw = tool?.config;
11720
- if (raw == null) continue;
11721
- const params = extractToolParameters2(raw);
11722
- if (params === void 0) {
11723
- const looksLikeObject = raw !== null && typeof raw === "object" && !Array.isArray(raw) || typeof raw === "string" && (() => {
11724
- try {
11725
- const parsed = JSON.parse(raw);
11726
- return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed);
11727
- } catch {
11728
- return false;
11729
- }
11730
- })();
11731
- if (!looksLikeObject) {
11732
- ctx.addIssue({
11733
- code: external_exports.ZodIssueCode.custom,
11734
- path: ["agents", a, "tools", "custom", c, "config"],
11735
- message: `custom tool "${tool?.name ?? "<unnamed>"}": config must be an object`
11736
- });
11737
- }
11951
+ function isSafeTemplatePath2(path31) {
11952
+ if (path31.length === 0 || path31.length > 300) return false;
11953
+ if (path31.startsWith("/") || path31.includes("\\")) return false;
11954
+ const segments = path31.split("/");
11955
+ return segments.every(
11956
+ (seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
11957
+ );
11958
+ }
11959
+ function dropTemplateKeys(value, drop) {
11960
+ if (Array.isArray(value)) return value.map((v) => dropTemplateKeys(v, drop));
11961
+ if (isPlainObject(value)) {
11962
+ const out = {};
11963
+ for (const [key, child] of Object.entries(value)) {
11964
+ if (drop.has(key)) continue;
11965
+ out[key] = TEMPLATE_OPAQUE_BLOB_KEYS.has(key) ? child : dropTemplateKeys(child, drop);
11966
+ }
11967
+ return out;
11968
+ }
11969
+ return value;
11970
+ }
11971
+ function stripTemplateInstanceIds(value) {
11972
+ return dropTemplateKeys(value, TEMPLATE_INSTANCE_ID_KEYS);
11973
+ }
11974
+ function excludeTemplateAuthorData(value) {
11975
+ return dropTemplateKeys(value, TEMPLATE_AUTHOR_DATA_KEYS);
11976
+ }
11977
+ function isPlainObject(value) {
11978
+ if (value === null || typeof value !== "object") return false;
11979
+ const proto = Object.getPrototypeOf(value);
11980
+ return proto === Object.prototype || proto === null;
11981
+ }
11982
+ function isSanitizableSliceFile(path31) {
11983
+ if (!/\.ya?ml$/i.test(path31)) return false;
11984
+ return path31 !== "resources" && !path31.startsWith("resources/");
11985
+ }
11986
+ function distinctUsesBackends(uses) {
11987
+ return [...new Set((uses ?? []).map((u) => u.backend))];
11988
+ }
11989
+ function refineHubAsCodeCustomTools2(config, ctx) {
11990
+ const agents = config.agents;
11991
+ if (!Array.isArray(agents)) return;
11992
+ for (let a = 0; a < agents.length; a++) {
11993
+ const agent = agents[a];
11994
+ const custom2 = agent?.tools?.custom;
11995
+ if (!Array.isArray(custom2)) continue;
11996
+ for (let c = 0; c < custom2.length; c++) {
11997
+ const tool = custom2[c];
11998
+ const raw = tool?.config;
11999
+ if (raw == null) continue;
12000
+ const params = extractToolParameters2(raw);
12001
+ if (params === void 0) {
12002
+ const looksLikeObject = raw !== null && typeof raw === "object" && !Array.isArray(raw) || typeof raw === "string" && (() => {
12003
+ try {
12004
+ const parsed = JSON.parse(raw);
12005
+ return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed);
12006
+ } catch {
12007
+ return false;
12008
+ }
12009
+ })();
12010
+ if (!looksLikeObject) {
12011
+ ctx.addIssue({
12012
+ code: external_exports.ZodIssueCode.custom,
12013
+ path: ["agents", a, "tools", "custom", c, "config"],
12014
+ message: `custom tool "${tool?.name ?? "<unnamed>"}": config must be an object`
12015
+ });
12016
+ }
11738
12017
  continue;
11739
12018
  }
11740
12019
  if (containsKanbanPlaceholders2(params)) continue;
@@ -11949,45 +12228,51 @@ function refineHubAsCodeResources2(config, ctx) {
11949
12228
  });
11950
12229
  }
11951
12230
  }
11952
- function isSafeTemplatePath2(path31) {
11953
- if (path31.length === 0 || path31.length > 300) return false;
11954
- if (path31.startsWith("/") || path31.includes("\\")) return false;
11955
- const segments = path31.split("/");
11956
- return segments.every(
11957
- (seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
11958
- );
11959
- }
11960
- function dropTemplateKeys(value, drop) {
11961
- if (Array.isArray(value)) return value.map((v) => dropTemplateKeys(v, drop));
11962
- if (isPlainObject(value)) {
11963
- const out = {};
11964
- for (const [key, child] of Object.entries(value)) {
11965
- if (drop.has(key)) continue;
11966
- out[key] = TEMPLATE_OPAQUE_BLOB_KEYS.has(key) ? child : dropTemplateKeys(child, drop);
11967
- }
11968
- return out;
11969
- }
11970
- return value;
11971
- }
11972
- function stripTemplateInstanceIds(value) {
11973
- return dropTemplateKeys(value, TEMPLATE_INSTANCE_ID_KEYS);
11974
- }
11975
- function excludeTemplateAuthorData(value) {
11976
- return dropTemplateKeys(value, TEMPLATE_AUTHOR_DATA_KEYS);
11977
- }
11978
- function isPlainObject(value) {
11979
- if (value === null || typeof value !== "object") return false;
11980
- const proto = Object.getPrototypeOf(value);
11981
- return proto === Object.prototype || proto === null;
11982
- }
11983
- function isSanitizableSliceFile(path31) {
11984
- if (!/\.ya?ml$/i.test(path31)) return false;
11985
- return path31 !== "resources" && !path31.startsWith("resources/");
11986
- }
11987
- function distinctUsesBackends(uses) {
11988
- return [...new Set((uses ?? []).map((u) => u.backend))];
12231
+ function refineHubAsCodeDelegation2(config, ctx) {
12232
+ const agents = config?.agents;
12233
+ if (!Array.isArray(agents)) return;
12234
+ agents.forEach((agent, agentIndex) => {
12235
+ const delegation = agent?.tools?.delegation;
12236
+ if (!Array.isArray(delegation)) return;
12237
+ delegation.forEach((entry, delIndex) => {
12238
+ const del = entry;
12239
+ if (del.allow_consultant_chain !== void 0) {
12240
+ const chainPath = ["agents", agentIndex, "tools", "delegation", delIndex, "allow_consultant_chain"];
12241
+ if (typeof del.allow_consultant_chain !== "boolean") {
12242
+ ctx.addIssue({
12243
+ code: external_exports.ZodIssueCode.custom,
12244
+ path: chainPath,
12245
+ message: "allow_consultant_chain must be a boolean"
12246
+ });
12247
+ } else if (del.tool !== "start_consult_thread") {
12248
+ ctx.addIssue({
12249
+ code: external_exports.ZodIssueCode.custom,
12250
+ path: chainPath,
12251
+ message: `allow_consultant_chain applies only to \`tool: start_consult_thread\` (got "${String(del.tool)}")`
12252
+ });
12253
+ }
12254
+ }
12255
+ if (del.context_boundary === void 0) return;
12256
+ const path31 = ["agents", agentIndex, "tools", "delegation", delIndex, "context_boundary"];
12257
+ if (del.type !== "hub") {
12258
+ ctx.addIssue({
12259
+ code: external_exports.ZodIssueCode.custom,
12260
+ path: path31,
12261
+ message: `context_boundary applies only to \`type: hub\` delegations (got type "${String(del.type)}")`
12262
+ });
12263
+ return;
12264
+ }
12265
+ if (!CONTEXT_BOUNDARIES2.includes(del.context_boundary)) {
12266
+ ctx.addIssue({
12267
+ code: external_exports.ZodIssueCode.custom,
12268
+ path: path31,
12269
+ message: `context_boundary must be one of: ${CONTEXT_BOUNDARIES2.join(", ")}`
12270
+ });
12271
+ }
12272
+ });
12273
+ });
11989
12274
  }
11990
- 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, 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, 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;
12275
+ 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, CONTEXT_BOUNDARIES2, contextBoundarySchema2, addNativeToolBody2, addMcpToolBody2, createCustomToolBody2, updateCustomToolBody2, updateToolExecutionConfigBody2, initialValueCreateSchema2, initialValueUpdateSchema2, stateIdParam2, listStatesQuery2, stateNameSchema2, createStateBody2, updateStateBody2, reorderStatesBody2, variantAiModeSchema2, experimentStatusSchema2, overlayUpdateSchema2, experimentIdParam2, variantIdParam2, listExperimentsQuery2, listVariantsQuery2, listOverridesQuery2, deleteOverrideQuery2, createExperimentBody2, updateExperimentBody2, setExperimentStatusBody2, createVariantBody2, updateVariantBody2, upsertOverrideBody2, orgTagIdParam2, listOrgTagsQuery2, createOrgTagBody2, updateOrgTagBody2, orgCredentialIdParam2, listOrgCredentialsQuery2, createOrgCredentialBody2, updateOrgCredentialBody2, orgResourceIdParam2, orgResourceFileIdParam2, orgResourceFolderIdParam2, hubOrgResourceParam2, listOrgResourcesQuery2, orgIdQuery2, createOrgResourceBody2, updateOrgResourceBody2, createOrgResourceFolderBody2, updateOrgResourceFolderBody2, uploadOrgResourceFileBody2, updateOrgResourceFileBody2, uploadOrgSkillZipBody2, linkOrgResourceBody2, resourceIdParam2, listResourcesQuery2, createResourceBody2, updateResourceBody2, syncSkillsBody2, resourceFileIdParam2, listResourceFilesQuery2, createResourceFileBody2, updateResourceFileBody2, uploadResourceFileBody2, uploadSkillZipBody2, resourceFolderIdParam2, listResourceFoldersQuery2, createResourceFolderBody2, updateResourceFolderBody2, agentResourceQuery2, hubResourceQuery2, linkAgentResourceBody2, updateAgentResourceBody2, unlinkAgentResourceQuery2, navItemSchema2, hubCountResetBody2, navItemCountResetBody2, typingBody2, analyticsHubIdParam2, analyticsVariableIdParam2, updateVariablePinBody2, updateAnalyticsViewBody2, NUMERIC_FILTER_OPS2, TEXT_FILTER_OPS2, CATEGORICAL_FILTER_OPS2, VARIABLE_FILTER_OPS2, STRUCTURED_QUERY_OPS2, STRUCTURED_QUERY_AGGREGATIONS2, filterValueSchema2, conversationsBody2, analyticsConversationIdParam2, messagesQuery2, conversationDetailDataQuery2, analyticsDataBody2, structuredQueryBody2, analyticsSqlBody2, 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, copilotSuggestBody2, copilotSuggestResponse2, CONSULT_THREAD_STATUSES2, consultThreadStatus2, CONSULT_THREAD_TITLE_MAX2, consultThreadTitle2, consultThreadSummary2, listConsultThreadsQuery2, listConsultThreadsResponse2, createConsultThreadBody2, createConsultThreadResponse2, consultThreadIdParam2, updateConsultThreadBody2, updateConsultThreadResponse2, CONSULT_AWAIT_TIMEOUT_MS2, billingOrgIdParam2, subscriptionItemParams2, spendCapBody2, growthPacksBody2, portalSessionBody2, checkoutSessionBody2, updateBillingCurrencyBody2, invoicesQuery2, downloadBody2, uploadQuery2, signUrlBody2, outboundSchemaQuery2, templateIdParam2, listTemplatesQuery2, deleteTemplateQuery2, templateStatusQuery2, createTemplateBody2, updateTemplateBody2, submitTemplateBody2, testTemplateBody2, contactIdParam2, listContactsQuery2, createContactBody2, updateContactBody2, listIdParam2, listListsQuery2, listListContactsQuery2, createListBody2, updateListBody2, addListContactsBody2, removeListContactsBody2, scheduleIdParam2, listSchedulesQuery2, listExecutionsQuery2, createScheduleBody2, updateScheduleBody2, MAX_RESOURCE_FILE_SIZE2, MAX_10MB_BASE64_ENCODED_BYTES2, MAX_EVAL_ATTACHMENT_ENCODED_BYTES2, MAX_EVAL_ATTACHMENT_CARRIERS2, MAX_EVAL_ATTACHMENT_AGGREGATE_ENCODED_BYTES2, MAX_RESOURCE_ENCODED_BYTES2, MAX_HUB_AS_CODE_RESOURCES2, MAX_HUB_AS_CODE_RESOURCE_FILES2, MAX_RESOURCE_AGGREGATE_ENCODED_BYTES2, MAX_CI_CONFIG_BODY_BYTES2, 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;
11991
12276
  var init_contracts = __esm({
11992
12277
  "../../packages/core/dist/contracts/index.js"() {
11993
12278
  "use strict";
@@ -12039,6 +12324,9 @@ var init_contracts = __esm({
12039
12324
  init_zod();
12040
12325
  init_zod();
12041
12326
  init_zod();
12327
+ init_zod();
12328
+ init_zod();
12329
+ init_zod();
12042
12330
  uuidSchema2 = external_exports.string().uuid();
12043
12331
  paginationSchema3 = external_exports.object({
12044
12332
  limit: external_exports.coerce.number().int().min(1).max(100).default(50),
@@ -12152,7 +12440,8 @@ var init_contracts = __esm({
12152
12440
  "monitor",
12153
12441
  "conversation_evaluator",
12154
12442
  "message_evaluator",
12155
- "summarizer"
12443
+ "summarizer",
12444
+ "consultant"
12156
12445
  ];
12157
12446
  SAFE_USER_ID_REGEX2 = /^[A-Za-z0-9_-]{1,64}$/;
12158
12447
  SUPPORTED_LOCALES2 = ["en", "pt", "es"];
@@ -12255,6 +12544,12 @@ var init_contracts = __esm({
12255
12544
  });
12256
12545
  }
12257
12546
  });
12547
+ MAX_OUTCOMES_PER_STATUS2 = 20;
12548
+ kanbanOutcomeSchema2 = external_exports.object({
12549
+ slug: kanbanStatusSlugSchema2,
12550
+ 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"),
12551
+ color: external_exports.string().optional()
12552
+ }).passthrough();
12258
12553
  EXCLUSIVE_FLAG_PAIRS2 = [
12259
12554
  ["isInitialStatus", "triggersAgentResponse"],
12260
12555
  ["isInitialStatus", "allowsAgentUpdate"],
@@ -12290,7 +12585,10 @@ var init_contracts = __esm({
12290
12585
  * and is not exposed to agents. The cross-reference invariant (must point at a
12291
12586
  * declared lane; the initial status must not have one) is enforced at the hub
12292
12587
  * level via `validateLaneReferences` — this schema only sees the status array. */
12293
- lane_slug: kanbanStatusSlugSchema2.optional()
12588
+ lane_slug: kanbanStatusSlugSchema2.optional(),
12589
+ /** Closing outcomes offered on the terminal transition. Only valid when
12590
+ * `isTerminalStatus === true` (enforced in the superRefine below). */
12591
+ outcomes: external_exports.array(kanbanOutcomeSchema2).max(MAX_OUTCOMES_PER_STATUS2, `outcomes must have at most ${MAX_OUTCOMES_PER_STATUS2} entries`).optional()
12294
12592
  }).passthrough().superRefine((status, ctx) => {
12295
12593
  const label = status.name ? `"${status.name}"` : status.slug ? `"${status.slug}"` : "<unnamed>";
12296
12594
  for (const [a, b] of EXCLUSIVE_FLAG_PAIRS2) {
@@ -12327,6 +12625,33 @@ var init_contracts = __esm({
12327
12625
  });
12328
12626
  }
12329
12627
  }
12628
+ if (Array.isArray(status.outcomes) && status.outcomes.length > 0) {
12629
+ if (status.isTerminalStatus !== true) {
12630
+ ctx.addIssue({
12631
+ code: external_exports.ZodIssueCode.custom,
12632
+ path: ["outcomes"],
12633
+ message: `kanban status ${label}: outcomes are only allowed on the terminal status (set isTerminalStatus=true)`
12634
+ });
12635
+ }
12636
+ const seen = /* @__PURE__ */ new Map();
12637
+ status.outcomes.forEach((o, j) => {
12638
+ if (!o?.slug) return;
12639
+ const arr = seen.get(o.slug) ?? [];
12640
+ arr.push(j);
12641
+ seen.set(o.slug, arr);
12642
+ });
12643
+ for (const [slug, indices] of seen) {
12644
+ if (indices.length > 1) {
12645
+ for (const j of indices) {
12646
+ ctx.addIssue({
12647
+ code: external_exports.ZodIssueCode.custom,
12648
+ path: ["outcomes", j, "slug"],
12649
+ message: `kanban status ${label}: duplicate outcome slug "${slug}"`
12650
+ });
12651
+ }
12652
+ }
12653
+ }
12654
+ }
12330
12655
  });
12331
12656
  kanbanStatusesArraySchema2 = external_exports.array(kanbanStatusSchema2).max(MAX_KANBAN_STATUSES2, `kanban_statuses must have at most ${MAX_KANBAN_STATUSES2} entries`).superRefine((statuses, ctx) => {
12332
12657
  if (statuses.length === 0) return;
@@ -12347,6 +12672,17 @@ var init_contracts = __esm({
12347
12672
  });
12348
12673
  }
12349
12674
  }
12675
+ const terminalIndices = statuses.map((s, i) => ({ s, i })).filter(({ s }) => s.isTerminalStatus === true);
12676
+ if (terminalIndices.length > 1) {
12677
+ const slugs = terminalIndices.map(({ s }) => s.slug).join(", ");
12678
+ for (const { i } of terminalIndices) {
12679
+ ctx.addIssue({
12680
+ code: external_exports.ZodIssueCode.custom,
12681
+ path: [i, "isTerminalStatus"],
12682
+ message: `kanban_statuses: at most one status may have isTerminalStatus=true (found ${terminalIndices.length}: ${slugs})`
12683
+ });
12684
+ }
12685
+ }
12350
12686
  const seenSlugs = /* @__PURE__ */ new Map();
12351
12687
  statuses.forEach((s, i) => {
12352
12688
  const key = s.slug;
@@ -12547,7 +12883,7 @@ var init_contracts = __esm({
12547
12883
  hub_id: uuidSchema2,
12548
12884
  sync_credentials_to_production: external_exports.boolean().optional()
12549
12885
  }).passthrough();
12550
- PRODUCTION_DIRECT_FIELDS2 = ["username", "api_key", "access_token", "password", "refresh_token", "webhook_secret_token"];
12886
+ PRODUCTION_DIRECT_FIELDS2 = ["username", "api_key", "access_token", "password", "refresh_token", "webhook_secret_token", "webhook_signing_secret"];
12551
12887
  setProductionCredentialBody2 = external_exports.object({
12552
12888
  hub_id: uuidSchema2,
12553
12889
  organization_credential_id: external_exports.string().nullable().optional(),
@@ -12557,7 +12893,8 @@ var init_contracts = __esm({
12557
12893
  access_token: external_exports.string().optional(),
12558
12894
  password: external_exports.string().optional(),
12559
12895
  refresh_token: external_exports.string().optional(),
12560
- webhook_secret_token: external_exports.string().optional()
12896
+ webhook_secret_token: external_exports.string().optional(),
12897
+ webhook_signing_secret: external_exports.string().optional()
12561
12898
  }).strict().superRefine((data, ctx) => {
12562
12899
  const hasOrgLink = !!data.organization_credential_id || !!data.organization_credential_token_id;
12563
12900
  const hasDirect = PRODUCTION_DIRECT_FIELDS2.some((f) => data[f] != null);
@@ -12602,13 +12939,19 @@ var init_contracts = __esm({
12602
12939
  deleteToolQuery2 = external_exports.object({ agent_id: uuidSchema2.optional(), hub_id: uuidSchema2 });
12603
12940
  toolConnectionsQuery2 = external_exports.object({ hub_id: uuidSchema2 });
12604
12941
  nativeToolIdSchema2 = external_exports.string().regex(/^nt-\d{3,}$/, "Invalid native tool id");
12942
+ CONTEXT_BOUNDARIES2 = ["instruction", "summary", "transcript"];
12943
+ contextBoundarySchema2 = external_exports.enum(CONTEXT_BOUNDARIES2);
12605
12944
  addNativeToolBody2 = external_exports.object({
12606
12945
  agent_id: uuidSchema2,
12607
12946
  hub_id: uuidSchema2,
12608
12947
  tool_native_id: nativeToolIdSchema2,
12609
- delegation_type: external_exports.enum(["team", "agent"]).optional(),
12948
+ delegation_type: external_exports.enum(["team", "agent", "hub"]).optional(),
12610
12949
  delegation_id: external_exports.string().optional(),
12611
12950
  delegation_name: external_exports.string().optional(),
12951
+ /** Only meaningful for a `hub` delegation (`delegate_to_hub`); ignored otherwise.
12952
+ * Defaults to `summary` when omitted. Admin-set — the link and boundary require
12953
+ * hub-admin (`hub:write`), never derived from any end user's grants. */
12954
+ delegation_context_boundary: contextBoundarySchema2.optional(),
12612
12955
  resource_config: external_exports.object({
12613
12956
  access_mode: external_exports.enum(["all", "selected", "none"]),
12614
12957
  enabled_resources: external_exports.array(external_exports.string()).optional()
@@ -13412,6 +13755,38 @@ var init_contracts = __esm({
13412
13755
  });
13413
13756
  appMessageSenderType2 = external_exports.enum(["user", "team"]);
13414
13757
  appMessageReceiverType2 = external_exports.enum(["user", "team", "agent", "assistant"]).transform((v) => v === "assistant" ? "agent" : v);
13758
+ apiChannelMessage2 = external_exports.object({
13759
+ text: clientOptionalString2,
13760
+ attachments: external_exports.array(messageAttachment2).max(MAX_ATTACHMENTS_PER_MESSAGE2).nullish().transform((v) => v ?? void 0)
13761
+ }).refine((m) => m.text && m.text.length > 0 || m.attachments && m.attachments.length > 0, {
13762
+ message: "message must have text or at least one attachment"
13763
+ });
13764
+ apiChannelMessageBody2 = external_exports.object({
13765
+ // Correlation id (task hubs): new → new conversation, repeat → continue. min 1 so an
13766
+ // empty string can't masquerade as a ref. Mutually exclusive with conversation_id.
13767
+ external_ref: external_exports.string().min(1).max(256).optional(),
13768
+ // Continue a specific WayAI conversation (authorized against the hub/channel + owner).
13769
+ // UUID-validated here (unlike the app channel, whose client we control): allocation
13770
+ // only treats a UUID-shaped id as a provided conversation, so a malformed id would
13771
+ // otherwise skip the owner guard and silently MINT a new conversation instead of
13772
+ // rejecting. A format 400 is shape-only — not an existence oracle (a valid-but-unknown
13773
+ // UUID still collapses to the opaque authorization error downstream).
13774
+ conversation_id: external_exports.string().uuid().optional(),
13775
+ // On-behalf-of end-user identity. Absent → per-connection service principal (task-hub
13776
+ // only; chat hub rejects with 422 in the route).
13777
+ user: external_exports.object({
13778
+ id: external_exports.string().min(1),
13779
+ email: clientOptionalString2,
13780
+ name: clientOptionalString2
13781
+ }).optional(),
13782
+ message: apiChannelMessage2,
13783
+ // Idempotency key: maps to channel_message_sid; a retried POST echoes the original
13784
+ // message_id and skips billing / turn dispatch (dedupe in ConversationDO.storeMessage).
13785
+ client_message_id: external_exports.string().min(1).max(256).optional()
13786
+ }).refine((b) => !(b.external_ref && b.conversation_id), {
13787
+ message: "provide external_ref or conversation_id, not both",
13788
+ path: ["external_ref"]
13789
+ });
13415
13790
  appMessageBody2 = external_exports.object({
13416
13791
  // Message content — three historical aliases. All optional: an attachment-only
13417
13792
  // or voice-only message carries no text.
@@ -13435,6 +13810,19 @@ var init_contracts = __esm({
13435
13810
  // caller may send to this receiver. The end-user branch ignores it — see the
13436
13811
  // receiver derivation in the route.
13437
13812
  user_receiver_id: clientOptionalString2,
13813
+ // ── Internal consult (consultant-agents PR 2 — H1.0) ──────────────────────
13814
+ // A team member handling a customer conversation can tag a `consultant`-role
13815
+ // agent for a PRIVATE, team-only exchange that never reaches the customer. A
13816
+ // consult send is a team send with `receiver_type: 'agent'` targeting the
13817
+ // consultant; the still-required `user_receiver_id` identifies the customer whose
13818
+ // conversation this is (and is authorized by `validateAppTeamSendContext`, exactly
13819
+ // as a team→user send is). The consultant is resolved from `agent_receiver_id`
13820
+ // when supplied, else from an `@mention` parsed out of the message text against
13821
+ // the hub's consultant agents. `consult_thread_id` continues an existing thread;
13822
+ // absent, the route creates/reuses the single implicit thread. These fields are
13823
+ // inert on every non-consult send (end-user send, team→user send).
13824
+ agent_receiver_id: clientOptionalString2,
13825
+ consult_thread_id: clientOptionalString2,
13438
13826
  is_first_message: clientOptionalBoolean2,
13439
13827
  end_conversation: clientOptionalBoolean2,
13440
13828
  // Pre-generated by the client so the optimistic bubble and the stored row share
@@ -13487,6 +13875,153 @@ var init_contracts = __esm({
13487
13875
  /** Type-to-confirm value; must equal the user's email (constant-time compared). */
13488
13876
  email_confirmation: external_exports.string().min(1).max(320)
13489
13877
  });
13878
+ templateLocaleSchema2 = external_exports.enum(SUPPORTED_LOCALES2);
13879
+ TEMPLATE_SLUG_REGEX2 = /^[a-z0-9][a-z0-9-]{0,62}$/;
13880
+ templateSlugSchema2 = external_exports.string().regex(TEMPLATE_SLUG_REGEX2, "slug must be lowercase alphanumeric with hyphens (max 63)");
13881
+ templateStatusSchema2 = external_exports.enum(["published", "draft", "internal"]);
13882
+ templateFileMapSchema2 = external_exports.record(external_exports.string()).refine((m) => Object.keys(m).every(isSafeTemplatePath2), {
13883
+ message: 'file map contains an unsafe path (no absolute paths, "..", or backslashes)'
13884
+ });
13885
+ TEMPLATE_INSTANCE_ID_KEYS = /* @__PURE__ */ new Set([
13886
+ // Top-level hub instance metadata (hub.yaml) — set by `wayai pull`, never authored.
13887
+ "hub_id",
13888
+ "hub_environment",
13889
+ "preview_label",
13890
+ "branch_name",
13891
+ // Per-entity row id + cross-entity reference UUIDs (each has a portable name twin).
13892
+ "id",
13893
+ "connection_id",
13894
+ "target_id",
13895
+ "agent_id",
13896
+ "resource_id",
13897
+ "list_id",
13898
+ // Account-scoped Meta WhatsApp template id (name twin: `template_whatsapp`).
13899
+ "template_whatsapp_id"
13900
+ ]);
13901
+ TEMPLATE_OPAQUE_BLOB_KEYS = /* @__PURE__ */ new Set([
13902
+ "settings",
13903
+ // agent + connection connector settings
13904
+ "schema_json",
13905
+ // agent response_format JSON Schema
13906
+ "json_schema",
13907
+ // state JSON Schema
13908
+ "initial_value",
13909
+ // state seed value
13910
+ "additional_context_schema",
13911
+ // kanban-status transition-form schema
13912
+ "config",
13913
+ // custom-tool OpenAI function schema
13914
+ "headers",
13915
+ "query_params",
13916
+ "body_params",
13917
+ // custom-tool HTTP shaping
13918
+ "mappings",
13919
+ // composed-tool argument mappings
13920
+ "input",
13921
+ "expected",
13922
+ "history",
13923
+ // eval message fixtures (tool_calls carry their own `id`)
13924
+ "transcript",
13925
+ "step_config"
13926
+ // journey fixtures (transcript carries `step_id`; step_config is keyed by it)
13927
+ ]);
13928
+ TEMPLATE_AUTHOR_DATA_KEYS = /* @__PURE__ */ new Set([
13929
+ // Outbound campaign subsystem (hub.yaml top-level). `outbound_contacts` is the
13930
+ // author's real leads — `phone`/`email`/`instagram_sid` + the required `name` are
13931
+ // GDPR-grade PII. `outbound_lists` group those contacts by real name. `outbound_schedules`
13932
+ // bind to the (now-absent) lists and carry the author's campaign cadence + message
13933
+ // copy — operationally tied to the author's customers; a consumer builds their own.
13934
+ "outbound_contacts",
13935
+ "outbound_lists",
13936
+ "outbound_schedules",
13937
+ // Account-scoped channel identifier on a connection (Twilio SID / WhatsApp number /
13938
+ // IG username / from-email, per connector). The connection stays as portable
13939
+ // structure re-bound by name on push; this author-account value carries no blueprint
13940
+ // value. A dedicated top-level column — never nested in the `settings` opaque blob.
13941
+ "account_sid"
13942
+ ]);
13943
+ templateTextSchema2 = external_exports.object({
13944
+ metaTitle: external_exports.string().min(1).max(200),
13945
+ metaDescription: external_exports.string().max(1e3).default("")
13946
+ });
13947
+ templateUsesEntrySchema2 = external_exports.object({
13948
+ backend: templateSlugSchema2,
13949
+ endpoint: templateSlugSchema2
13950
+ });
13951
+ templateUsesSchema2 = external_exports.array(templateUsesEntrySchema2).max(24).default([]);
13952
+ templateYamlLocaleEntry2 = templateTextSchema2.extend({ source: external_exports.string().min(1) });
13953
+ templateYamlWayaiBlock2 = external_exports.object({
13954
+ installCommand: external_exports.string().min(1).max(300),
13955
+ locales: external_exports.record(templateLocaleSchema2, templateYamlLocaleEntry2)
13956
+ });
13957
+ 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))]);
13958
+ templateYamlSchema2 = external_exports.object({
13959
+ slug: templateSlugSchema2,
13960
+ category: external_exports.string().min(1).max(60),
13961
+ tags: templateTagsSchema2,
13962
+ status: templateStatusSchema2.default("draft"),
13963
+ order: external_exports.number().int().min(0).max(1e5).optional(),
13964
+ defaultLocale: templateLocaleSchema2,
13965
+ hero: external_exports.string().optional(),
13966
+ // relative path to a hero image inside the template folder
13967
+ // The Rekor backend(s) this channel runs on (gh #2955). Locale-agnostic. The
13968
+ // cross-link + MCP endpoint are derived from each entry's slugs, never authored.
13969
+ uses: templateUsesSchema2,
13970
+ // A WayAI template IS a WayAI channel — the wayai slice is required. (The old
13971
+ // Rekor-only store entry is gone: a pure Rekor backend lives only in Rekor's store.)
13972
+ wayai: templateYamlWayaiBlock2
13973
+ }).refine((c) => Boolean(c.wayai.locales[c.defaultLocale]), {
13974
+ message: "`wayai.locales` must include the defaultLocale"
13975
+ });
13976
+ templateHeroSchema2 = external_exports.object({
13977
+ 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)"),
13978
+ dataBase64: external_exports.string().min(1).max(8e6)
13979
+ });
13980
+ templatePushLocaleSchema2 = external_exports.object({
13981
+ wayai: templateTextSchema2.optional(),
13982
+ readmeMarkdown: external_exports.string().default(""),
13983
+ wayaiFiles: templateFileMapSchema2.optional()
13984
+ });
13985
+ templatePushBody2 = external_exports.object({
13986
+ slug: templateSlugSchema2,
13987
+ defaultLocale: templateLocaleSchema2,
13988
+ common: external_exports.object({
13989
+ category: external_exports.string().min(1).max(60),
13990
+ tags: templateTagsSchema2,
13991
+ status: templateStatusSchema2,
13992
+ order: external_exports.number().int().min(0).max(1e5).default(0),
13993
+ // The WayAI install command (a WayAI template always has a wayai side). Kept
13994
+ // optional on the wire so a malformed manifest 400s on the field, not the body.
13995
+ installCommand: external_exports.string().min(1).max(300).optional(),
13996
+ hero: templateHeroSchema2.optional(),
13997
+ // The channel→backend edge (gh #2955), locale-agnostic.
13998
+ uses: templateUsesSchema2
13999
+ }),
14000
+ locales: external_exports.record(templateLocaleSchema2, templatePushLocaleSchema2)
14001
+ }).refine((b) => Boolean(b.locales[b.defaultLocale]), {
14002
+ message: "`locales` must include the defaultLocale"
14003
+ });
14004
+ templateListQuery2 = external_exports.object({ locale: templateLocaleSchema2.optional() });
14005
+ templateSlugParam2 = external_exports.object({ slug: templateSlugSchema2 });
14006
+ templateDetailQuery2 = external_exports.object({ locale: templateLocaleSchema2.optional() });
14007
+ courseQuizScoreSchema2 = external_exports.object({
14008
+ correct: external_exports.number().int().min(0).max(50),
14009
+ total: external_exports.number().int().min(1).max(50),
14010
+ /** Chosen choice index per question; -1 = unanswered. */
14011
+ answers: external_exports.array(external_exports.number().int().min(-1).max(50)).max(50).optional()
14012
+ });
14013
+ upsertCourseLessonBody2 = external_exports.object({
14014
+ quiz_passed: external_exports.boolean().optional(),
14015
+ quiz_score: courseQuizScoreSchema2.optional(),
14016
+ content_version: external_exports.number().int().min(1)
14017
+ }).strict();
14018
+ linkCourseCapstoneBody2 = external_exports.object({
14019
+ hub_id: external_exports.string().min(1).max(128),
14020
+ // A capstone's slug IS a canonical template slug — reuse the one validator
14021
+ // the template pipeline (CLI, admin, gallery) already enforces, so course
14022
+ // linking can't drift from how real template slugs are shaped.
14023
+ template_slug: templateSlugSchema2.optional()
14024
+ }).strict();
13490
14025
  archiveHubIdParam2 = external_exports.object({
13491
14026
  hubId: external_exports.string().uuid()
13492
14027
  });
@@ -13580,7 +14115,10 @@ var init_contracts = __esm({
13580
14115
  user_id: external_exports.string().optional(),
13581
14116
  scheduled_event_date: external_exports.string().optional(),
13582
14117
  additional_context: additionalContextPayloadSchema2.optional(),
13583
- event_description: external_exports.string().optional()
14118
+ event_description: external_exports.string().optional(),
14119
+ // Closing outcome slug — required by the server only when the target is the
14120
+ // terminal status AND it declares `outcomes`. 50-char slug cap + headroom.
14121
+ outcome: external_exports.string().max(64).optional()
13584
14122
  });
13585
14123
  annotateConversationBody2 = external_exports.object({
13586
14124
  hub_id: external_exports.string().uuid(),
@@ -13668,6 +14206,59 @@ var init_contracts = __esm({
13668
14206
  external_exports.record(external_exports.string().max(128), external_exports.string().max(2048)).refine((r) => Object.keys(r).length <= 50, "too many variables")
13669
14207
  ]).optional()
13670
14208
  });
14209
+ copilotSuggestBody2 = external_exports.object({
14210
+ hub_id: external_exports.string().uuid()
14211
+ });
14212
+ copilotSuggestResponse2 = external_exports.object({
14213
+ status: external_exports.enum(["processing", "skipped"]),
14214
+ reason: external_exports.string().optional()
14215
+ });
14216
+ CONSULT_THREAD_STATUSES2 = ["open", "awaiting", "resolved", "cancelled_at_close"];
14217
+ consultThreadStatus2 = external_exports.enum(CONSULT_THREAD_STATUSES2);
14218
+ CONSULT_THREAD_TITLE_MAX2 = 120;
14219
+ consultThreadTitle2 = external_exports.string().trim().min(1).max(CONSULT_THREAD_TITLE_MAX2);
14220
+ consultThreadSummary2 = external_exports.object({
14221
+ consult_thread_id: external_exports.string(),
14222
+ conversation_id: external_exports.string(),
14223
+ initiator_type: external_exports.enum(["team", "agent"]),
14224
+ initiator_id: external_exports.string(),
14225
+ engaged_agent_id: external_exports.string().nullable(),
14226
+ engaged_agent_name: external_exports.string().nullable(),
14227
+ title: external_exports.string().nullable(),
14228
+ status: consultThreadStatus2,
14229
+ created_at: external_exports.string()
14230
+ });
14231
+ listConsultThreadsQuery2 = external_exports.object({
14232
+ hub_id: external_exports.string().uuid()
14233
+ });
14234
+ listConsultThreadsResponse2 = external_exports.object({
14235
+ threads: external_exports.array(consultThreadSummary2)
14236
+ });
14237
+ createConsultThreadBody2 = external_exports.object({
14238
+ hub_id: external_exports.string().uuid(),
14239
+ title: consultThreadTitle2.optional(),
14240
+ // Optionally engage a consultant on creation. Validated server-side against the
14241
+ // hub's `consultant`-role agents; a non-consultant / unknown id is rejected.
14242
+ engaged_agent_id: external_exports.string().uuid().optional()
14243
+ });
14244
+ createConsultThreadResponse2 = external_exports.object({
14245
+ thread: consultThreadSummary2
14246
+ });
14247
+ consultThreadIdParam2 = external_exports.object({
14248
+ id: external_exports.string().uuid(),
14249
+ threadId: external_exports.string().uuid()
14250
+ });
14251
+ updateConsultThreadBody2 = external_exports.object({
14252
+ hub_id: external_exports.string().uuid(),
14253
+ title: consultThreadTitle2.optional(),
14254
+ engaged_agent_id: external_exports.string().uuid().optional()
14255
+ }).refine((v) => v.title !== void 0 || v.engaged_agent_id !== void 0, {
14256
+ message: "Provide a title and/or an engaged_agent_id to update"
14257
+ });
14258
+ updateConsultThreadResponse2 = external_exports.object({
14259
+ thread: consultThreadSummary2
14260
+ });
14261
+ CONSULT_AWAIT_TIMEOUT_MS2 = 15 * 6e4;
13671
14262
  billingOrgIdParam2 = external_exports.object({
13672
14263
  organizationId: external_exports.string().uuid()
13673
14264
  });
@@ -13915,6 +14506,7 @@ var init_contracts = __esm({
13915
14506
  refineHubAsCodeEvals2(config, ctx);
13916
14507
  refineHubAsCodeEvalAttachments2(config, ctx);
13917
14508
  refineHubAsCodeResources2(config, ctx);
14509
+ refineHubAsCodeDelegation2(config, ctx);
13918
14510
  });
13919
14511
  ciPullHubIdParam2 = external_exports.object({
13920
14512
  hub_id: ciUuidSchema2
@@ -14253,6 +14845,12 @@ var init_contracts = __esm({
14253
14845
  access_token: external_exports.string(),
14254
14846
  refresh_token: external_exports.string()
14255
14847
  });
14848
+ passwordLoginBody2 = external_exports.object({
14849
+ email: external_exports.string().email("Invalid email").max(254),
14850
+ // RFC 5321 max; bounds the request payload
14851
+ password: external_exports.string().min(1, "Password is required").max(128)
14852
+ // bound the payload; WorkOS validates
14853
+ });
14256
14854
  browserParams2 = external_exports.object({
14257
14855
  hubId: uuidSchema2,
14258
14856
  resourceId: uuidSchema2
@@ -14694,135 +15292,6 @@ var init_contracts = __esm({
14694
15292
  offset: external_exports.coerce.number().int().min(0).optional()
14695
15293
  });
14696
15294
  noticeIdParamSchema2 = external_exports.object({ id: external_exports.string().min(1) });
14697
- templateLocaleSchema2 = external_exports.enum(SUPPORTED_LOCALES2);
14698
- TEMPLATE_SLUG_REGEX2 = /^[a-z0-9][a-z0-9-]{0,62}$/;
14699
- templateSlugSchema2 = external_exports.string().regex(TEMPLATE_SLUG_REGEX2, "slug must be lowercase alphanumeric with hyphens (max 63)");
14700
- templateStatusSchema2 = external_exports.enum(["published", "draft", "internal"]);
14701
- templateFileMapSchema2 = external_exports.record(external_exports.string()).refine((m) => Object.keys(m).every(isSafeTemplatePath2), {
14702
- message: 'file map contains an unsafe path (no absolute paths, "..", or backslashes)'
14703
- });
14704
- TEMPLATE_INSTANCE_ID_KEYS = /* @__PURE__ */ new Set([
14705
- // Top-level hub instance metadata (hub.yaml) — set by `wayai pull`, never authored.
14706
- "hub_id",
14707
- "hub_environment",
14708
- "preview_label",
14709
- "branch_name",
14710
- // Per-entity row id + cross-entity reference UUIDs (each has a portable name twin).
14711
- "id",
14712
- "connection_id",
14713
- "target_id",
14714
- "agent_id",
14715
- "resource_id",
14716
- "list_id",
14717
- // Account-scoped Meta WhatsApp template id (name twin: `template_whatsapp`).
14718
- "template_whatsapp_id"
14719
- ]);
14720
- TEMPLATE_OPAQUE_BLOB_KEYS = /* @__PURE__ */ new Set([
14721
- "settings",
14722
- // agent + connection connector settings
14723
- "schema_json",
14724
- // agent response_format JSON Schema
14725
- "json_schema",
14726
- // state JSON Schema
14727
- "initial_value",
14728
- // state seed value
14729
- "additional_context_schema",
14730
- // kanban-status transition-form schema
14731
- "config",
14732
- // custom-tool OpenAI function schema
14733
- "headers",
14734
- "query_params",
14735
- "body_params",
14736
- // custom-tool HTTP shaping
14737
- "mappings",
14738
- // composed-tool argument mappings
14739
- "input",
14740
- "expected",
14741
- "history",
14742
- // eval message fixtures (tool_calls carry their own `id`)
14743
- "transcript",
14744
- "step_config"
14745
- // journey fixtures (transcript carries `step_id`; step_config is keyed by it)
14746
- ]);
14747
- TEMPLATE_AUTHOR_DATA_KEYS = /* @__PURE__ */ new Set([
14748
- // Outbound campaign subsystem (hub.yaml top-level). `outbound_contacts` is the
14749
- // author's real leads — `phone`/`email`/`instagram_sid` + the required `name` are
14750
- // GDPR-grade PII. `outbound_lists` group those contacts by real name. `outbound_schedules`
14751
- // bind to the (now-absent) lists and carry the author's campaign cadence + message
14752
- // copy — operationally tied to the author's customers; a consumer builds their own.
14753
- "outbound_contacts",
14754
- "outbound_lists",
14755
- "outbound_schedules",
14756
- // Account-scoped channel identifier on a connection (Twilio SID / WhatsApp number /
14757
- // IG username / from-email, per connector). The connection stays as portable
14758
- // structure re-bound by name on push; this author-account value carries no blueprint
14759
- // value. A dedicated top-level column — never nested in the `settings` opaque blob.
14760
- "account_sid"
14761
- ]);
14762
- templateTextSchema2 = external_exports.object({
14763
- metaTitle: external_exports.string().min(1).max(200),
14764
- metaDescription: external_exports.string().max(1e3).default("")
14765
- });
14766
- templateUsesEntrySchema2 = external_exports.object({
14767
- backend: templateSlugSchema2,
14768
- endpoint: templateSlugSchema2
14769
- });
14770
- templateUsesSchema2 = external_exports.array(templateUsesEntrySchema2).max(24).default([]);
14771
- templateYamlLocaleEntry2 = templateTextSchema2.extend({ source: external_exports.string().min(1) });
14772
- templateYamlWayaiBlock2 = external_exports.object({
14773
- installCommand: external_exports.string().min(1).max(300),
14774
- locales: external_exports.record(templateLocaleSchema2, templateYamlLocaleEntry2)
14775
- });
14776
- 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))]);
14777
- templateYamlSchema2 = external_exports.object({
14778
- slug: templateSlugSchema2,
14779
- category: external_exports.string().min(1).max(60),
14780
- tags: templateTagsSchema2,
14781
- status: templateStatusSchema2.default("draft"),
14782
- order: external_exports.number().int().min(0).max(1e5).optional(),
14783
- defaultLocale: templateLocaleSchema2,
14784
- hero: external_exports.string().optional(),
14785
- // relative path to a hero image inside the template folder
14786
- // The Rekor backend(s) this channel runs on (gh #2955). Locale-agnostic. The
14787
- // cross-link + MCP endpoint are derived from each entry's slugs, never authored.
14788
- uses: templateUsesSchema2,
14789
- // A WayAI template IS a WayAI channel — the wayai slice is required. (The old
14790
- // Rekor-only store entry is gone: a pure Rekor backend lives only in Rekor's store.)
14791
- wayai: templateYamlWayaiBlock2
14792
- }).refine((c) => Boolean(c.wayai.locales[c.defaultLocale]), {
14793
- message: "`wayai.locales` must include the defaultLocale"
14794
- });
14795
- templateHeroSchema2 = external_exports.object({
14796
- 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)"),
14797
- dataBase64: external_exports.string().min(1).max(8e6)
14798
- });
14799
- templatePushLocaleSchema2 = external_exports.object({
14800
- wayai: templateTextSchema2.optional(),
14801
- readmeMarkdown: external_exports.string().default(""),
14802
- wayaiFiles: templateFileMapSchema2.optional()
14803
- });
14804
- templatePushBody2 = external_exports.object({
14805
- slug: templateSlugSchema2,
14806
- defaultLocale: templateLocaleSchema2,
14807
- common: external_exports.object({
14808
- category: external_exports.string().min(1).max(60),
14809
- tags: templateTagsSchema2,
14810
- status: templateStatusSchema2,
14811
- order: external_exports.number().int().min(0).max(1e5).default(0),
14812
- // The WayAI install command (a WayAI template always has a wayai side). Kept
14813
- // optional on the wire so a malformed manifest 400s on the field, not the body.
14814
- installCommand: external_exports.string().min(1).max(300).optional(),
14815
- hero: templateHeroSchema2.optional(),
14816
- // The channel→backend edge (gh #2955), locale-agnostic.
14817
- uses: templateUsesSchema2
14818
- }),
14819
- locales: external_exports.record(templateLocaleSchema2, templatePushLocaleSchema2)
14820
- }).refine((b) => Boolean(b.locales[b.defaultLocale]), {
14821
- message: "`locales` must include the defaultLocale"
14822
- });
14823
- templateListQuery2 = external_exports.object({ locale: templateLocaleSchema2.optional() });
14824
- templateSlugParam2 = external_exports.object({ slug: templateSlugSchema2 });
14825
- templateDetailQuery2 = external_exports.object({ locale: templateLocaleSchema2.optional() });
14826
15295
  ADMIN_SKILL_NAME_REGEX2 = /^[a-z0-9][a-z0-9-]{0,63}$/;
14827
15296
  adminSkillNameParam2 = external_exports.object({
14828
15297
  name: external_exports.string().regex(ADMIN_SKILL_NAME_REGEX2, "invalid skill name")
@@ -15252,7 +15721,7 @@ var init_eval_attachments = __esm({
15252
15721
  "use strict";
15253
15722
  init_resource_files();
15254
15723
  init_fs_safety();
15255
- init_parser();
15724
+ init_expected();
15256
15725
  ATTACHMENTS_DIR = "attachments";
15257
15726
  }
15258
15727
  });
@@ -15261,17 +15730,10 @@ var init_eval_attachments = __esm({
15261
15730
  import * as fs12 from "fs";
15262
15731
  import * as path14 from "path";
15263
15732
  import * as yaml4 from "js-yaml";
15264
- function expected(message) {
15265
- const err = new Error(message);
15266
- err.isExpected = true;
15267
- return err;
15268
- }
15269
15733
  function parseHubFolder(hubFolder, opts) {
15270
15734
  const yamlPath = resolveHubYamlPath(hubFolder);
15271
15735
  if (!yamlPath) {
15272
- const err = new Error(`hub.yaml not found in ${hubFolder}`);
15273
- err.isExpected = true;
15274
- throw err;
15736
+ throw expected(`hub.yaml not found in ${hubFolder}`);
15275
15737
  }
15276
15738
  const yamlContent = fs12.readFileSync(yamlPath, "utf-8");
15277
15739
  let config;
@@ -15279,27 +15741,19 @@ function parseHubFolder(hubFolder, opts) {
15279
15741
  config = yaml4.load(yamlContent);
15280
15742
  } catch (err) {
15281
15743
  if (err instanceof yaml4.YAMLException) {
15282
- const userError = new Error(`Invalid YAML in ${yamlPath}: ${err.message}`);
15283
- userError.isExpected = true;
15284
- throw userError;
15744
+ throw expected(`Invalid YAML in ${yamlPath}: ${err.message}`);
15285
15745
  }
15286
15746
  throw err;
15287
15747
  }
15288
15748
  if (!config || typeof config !== "object") {
15289
- const invalidError = new Error(`Invalid YAML in ${yamlPath}`);
15290
- invalidError.isExpected = true;
15291
- throw invalidError;
15749
+ throw expected(`Invalid YAML in ${yamlPath}`);
15292
15750
  }
15293
15751
  if (!opts?.allowNewHub) {
15294
15752
  if (!config.hub_id) {
15295
- const err = new Error(`Missing hub_id in ${yamlPath}`);
15296
- err.isExpected = true;
15297
- throw err;
15753
+ throw expected(`Missing hub_id in ${yamlPath}`);
15298
15754
  }
15299
15755
  if (!config.hub_environment) {
15300
- const err = new Error(`Missing hub_environment in ${yamlPath}`);
15301
- err.isExpected = true;
15302
- throw err;
15756
+ throw expected(`Missing hub_environment in ${yamlPath}`);
15303
15757
  }
15304
15758
  }
15305
15759
  const agentYamlFiles = scanAgentYamlFiles(hubFolder);
@@ -15312,11 +15766,9 @@ function parseHubFolder(hubFolder, opts) {
15312
15766
  if (fs12.existsSync(instructionsPath)) {
15313
15767
  resolved.instructions = fs12.readFileSync(instructionsPath, "utf-8");
15314
15768
  } else {
15315
- const err = new Error(
15769
+ throw expected(
15316
15770
  `Agent instructions file not found: ${instructionsPath} (referenced by agent "${agent.name}")`
15317
15771
  );
15318
- err.isExpected = true;
15319
- throw err;
15320
15772
  }
15321
15773
  } else if (resolved.instructions === void 0 && typeof agent.name === "string") {
15322
15774
  const conventionPath = path14.join(hubFolder, "agents", `${slugify(agent.name)}.md`);
@@ -15610,9 +16062,7 @@ function scanAgentYamlFiles(hubFolder) {
15610
16062
  agent = yaml4.load(content);
15611
16063
  } catch (err) {
15612
16064
  if (err instanceof yaml4.YAMLException) {
15613
- const userError = new Error(`Invalid YAML in agents/${file}: ${err.message}`);
15614
- userError.isExpected = true;
15615
- throw userError;
16065
+ throw expected(`Invalid YAML in agents/${file}: ${err.message}`);
15616
16066
  }
15617
16067
  throw err;
15618
16068
  }
@@ -15634,7 +16084,7 @@ function parseResources(hubFolder, configResources) {
15634
16084
  };
15635
16085
  if (res.id) resource.id = res.id;
15636
16086
  if (res.type === "knowledge" || res.type === "skill") resource.type = res.type;
15637
- else if (res.type !== void 0) throw new Error(`Invalid resource type for "${resource.name}": expected knowledge or skill`);
16087
+ else if (res.type !== void 0) throw expected(`Invalid resource type for "${resource.name}": expected knowledge or skill`);
15638
16088
  if (res.description) resource.description = res.description;
15639
16089
  if (res.enabled === false) resource.enabled = false;
15640
16090
  if (res.user_browsable) resource.user_browsable = res.user_browsable;
@@ -15657,6 +16107,7 @@ var init_parser = __esm({
15657
16107
  init_utils();
15658
16108
  init_resource_files();
15659
16109
  init_eval_attachments();
16110
+ init_expected();
15660
16111
  }
15661
16112
  });
15662
16113
 
@@ -16120,7 +16571,7 @@ function shouldWarnIgnoredPreviewLabel(localLabel, serverLabel) {
16120
16571
  function printSyncResult(result) {
16121
16572
  if (result.errors && result.errors.length > 0) {
16122
16573
  printErrors(result.errors);
16123
- throw new Error(`Sync failed with ${result.errors.length} error(s). No completion was reported; inspect the errors above.`);
16574
+ throw expected(`Sync failed with ${result.errors.length} error(s). No completion was reported; inspect the errors above.`);
16124
16575
  }
16125
16576
  console.log(`
16126
16577
  Sync complete. Preview hub: ${result.preview_hub_id}`);
@@ -16533,6 +16984,7 @@ var init_push = __esm({
16533
16984
  "use strict";
16534
16985
  init_auth();
16535
16986
  init_api_client();
16987
+ init_expected();
16536
16988
  init_parser();
16537
16989
  init_hub_materializer();
16538
16990
  init_resource_files();
@@ -17941,6 +18393,8 @@ async function conversationsCommand(args2) {
17941
18393
  }
17942
18394
  console.log("");
17943
18395
  }
18396
+ console.log("Diagnosing agent behavior? The transcript shows what was sent \u2014 not what the model received.");
18397
+ console.log(`Drill in: wayai conversations ${conversationId} observability (per-turn resolved prompt, tool calls, latency)`);
17944
18398
  } else if (hasAnalyticsFlags) {
17945
18399
  if (status) {
17946
18400
  console.error("The --status flag is not supported with --period/--from/--to. Without these flags, --status works as before.");