@wayai/cli 0.3.106 → 0.3.108

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
@@ -5958,7 +5958,7 @@ function findStepBoundaries(transcript) {
5958
5958
  }
5959
5959
  return out;
5960
5960
  }
5961
- 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, primaryRegionSchema, placementSourceSchema, orgIdParam, orgAdminIdParam, createOrganizationBody, updateOrganizationBody, addOrgAdminBody, SUMMARIZATION_THRESHOLD_MIN, SUMMARIZATION_THRESHOLD_MAX, summarizationThresholdField, monitorConfigField, agentIdParam, listAgentsQuery, agentConnectionsQuery, createAgentBody, updateAgentBody, AGENT_PARAMETER_TYPES, AGENT_PARAMETER_NAME_REGEX, agentParameterCreateSchema, MAX_AGENT_PARAMETERS_PER_REQUEST, createAgentParametersBody, SLUG_REGEX, slugSchema, INVISIBLE_NAME_CHARS, MAX_KANBAN_STATUSES, MAX_FOLLOWUPS_PER_STATUS, MAX_LANES, MAX_ADDITIONAL_CONTEXT_SCHEMA_BYTES, RESERVED_TEMPLATE_DUMP_NAME, kanbanStatusSlugSchema, followupSchema, EXCLUSIVE_FLAG_PAIRS, kanbanStatusSchema, kanbanStatusesArraySchema, laneSchema, lanesArraySchema, hubIdParam, hubAdminIdParam, hubUserIdParam, hubIdentityIdParam, hubTeamIdParam, hubTeamUserDeleteParam, hubSchemaQuery, PREVIEW_LABEL_MAX_LENGTH, MAX_ENDED_INDEX_RETENTION_DAYS, previewLabelField, createHubBody, updateHubBody, addHubAdminBody, addHubIdentityAuthorizationBody, contactDecisionBody, approveContactBody, listContactAccessQuery, createHubTeamBody, updateHubTeamBody, addHubTeamUserBody, reassignHubUserBody, replicatePreviewBody, updateChannelTestIdentitiesBody, claimCodeChannelParam, claimCodeDeleteParam, connectionIdParam, connectorIdParam, listConnectionsQuery, deleteConnectionQuery, addConnectionBody, editConnectionBody, PRODUCTION_DIRECT_FIELDS, setProductionCredentialBody, registerWhatsappQuery, registerWhatsappBody, retryProvisioningQuery, resendDomainStatusQuery, PLACEHOLDER_TOKENS, ALLOWED_TYPES, SUBSCHEMA_OBJECT_KEYWORDS, SUBSCHEMA_LIST_KEYWORDS, SUBSCHEMA_MAP_KEYWORDS, MAX_SCHEMA_DEPTH, toolIdParam, listToolsQuery, toolAgentQuery, deleteToolQuery, toolConnectionsQuery, nativeToolIdSchema, addNativeToolBody, addMcpToolBody, createCustomToolBody, updateCustomToolBody, updateToolExecutionConfigBody, initialValueCreateSchema, initialValueUpdateSchema, stateIdParam, listStatesQuery, stateNameSchema, createStateBody, updateStateBody, reorderStatesBody, variantAiModeSchema, experimentStatusSchema, overlayUpdateSchema, experimentIdParam, variantIdParam, listExperimentsQuery, listVariantsQuery, listOverridesQuery, deleteOverrideQuery, createExperimentBody, updateExperimentBody, setExperimentStatusBody, createVariantBody, updateVariantBody, upsertOverrideBody, orgTagIdParam, listOrgTagsQuery, createOrgTagBody, updateOrgTagBody, orgCredentialIdParam, listOrgCredentialsQuery, createOrgCredentialBody, updateOrgCredentialBody, orgResourceIdParam, orgResourceFileIdParam, orgResourceFolderIdParam, hubOrgResourceParam, listOrgResourcesQuery, orgIdQuery, createOrgResourceBody, updateOrgResourceBody, createOrgResourceFolderBody, updateOrgResourceFolderBody, uploadOrgResourceFileBody, updateOrgResourceFileBody, uploadOrgSkillZipBody, linkOrgResourceBody, resourceIdParam, listResourcesQuery, createResourceBody, updateResourceBody, syncSkillsBody, resourceFileIdParam, listResourceFilesQuery, createResourceFileBody, updateResourceFileBody, uploadResourceFileBody, uploadSkillZipBody, resourceFolderIdParam, listResourceFoldersQuery, createResourceFolderBody, updateResourceFolderBody, agentResourceQuery, hubResourceQuery, linkAgentResourceBody, updateAgentResourceBody, unlinkAgentResourceQuery, navItemSchema, hubCountResetBody, navItemCountResetBody, typingBody, analyticsHubIdParam, analyticsVariableIdParam, updateVariablePinBody, updateAnalyticsViewBody, NUMERIC_FILTER_OPS, TEXT_FILTER_OPS, CATEGORICAL_FILTER_OPS, VARIABLE_FILTER_OPS, STRUCTURED_QUERY_OPS, STRUCTURED_QUERY_AGGREGATIONS, filterValueSchema, conversationsBody, analyticsConversationIdParam, messagesQuery, conversationDetailDataQuery, analyticsDataBody, structuredQueryBody, analyticsSqlBody, analyticsSqlSchemaQuery, EVAL_PACING_PRESET_NAMES, PACING_INTERVAL_MIN_MS, PACING_INTERVAL_MAX_MS, EVAL_RUN_DEADLINE_MIN_MS, EVAL_RUN_DEADLINE_MAX_MS, paginationSchema2, evalIdParam, sessionIdParam, scenarioSetIdParam, hubIdQuery, EVAL_INPUT_ROLES, EVAL_INPUT_ROLE_LIST, ROLE_ECHO_MAX, createEvalBody, updateEvalBody, getEvalsQuery, toggleEvalBody, bulkToggleEvalsBody, pacingConfigSchema, sessionConfigSchema, createSessionBody, getSessionsQuery, getSessionResultsQuery, getSessionRunsQuery, evalAnalyticsQuery, getSessionCostQuery, compareSessionsQuery, evalsSqlBody, evalsSqlSchemaQuery, exportResultsQuery, validateEvalBody, hubAgentsQuery, createScenarioSetBody, updateScenarioSetBody, scenarioSetsHubQuery, createScenarioFromConversationBody, createJourneyFromConversationBody, EVAL_ATTACHMENT_HASH_REGEX, evalAttachmentRef, turnMayCarryAttachments, ATTACHMENTS_USER_ONLY_MESSAGE, journeyIdParam, journeyToolCallSchema, journeyTurnSchema, journeyStepOverrideSchema, fixtureField, createJourneyBody, updateJourneyBody, getConversationsQuery, getMessagesQuery, appMessageSenderType, appMessageReceiverType, appMessageBody, updateUserBody, updateProfileBody, pathnameRegex, updatePreferencesBody, registerPushTokenBody, deletePushTokenQuery, activityQuery, deletionModeSchema, deletionRequestBody, archiveHubIdParam, archiveConversationParams, archiveListQuery, archiveMessageObservabilityParams, conversationIdParam, claimBody, releaseBody, transferBody, closeBody, additionalContextPayloadSchema, kanbanUpdateBody, annotateConversationBody, observabilityParams, observabilityListParams, deleteUserConversationsBody, sendMessageBody, listConversationsQuery, getConversationDetailParams, getConversationDetailQuery, listWhatsAppTemplatesQuery, sendWhatsAppTemplateBody, billingOrgIdParam, subscriptionItemParams, spendCapBody, growthPacksBody, portalSessionBody, checkoutSessionBody, updateBillingCurrencyBody, invoicesQuery, downloadBody, uploadQuery, signUrlBody, outboundSchemaQuery, templateIdParam, listTemplatesQuery, deleteTemplateQuery, templateStatusQuery, createTemplateBody, updateTemplateBody, submitTemplateBody, testTemplateBody, contactIdParam, listContactsQuery, createContactBody, updateContactBody, listIdParam, listListsQuery, listListContactsQuery, createListBody, updateListBody, addListContactsBody, removeListContactsBody, scheduleIdParam, listSchedulesQuery, listExecutionsQuery, createScheduleBody, updateScheduleBody, MAX_RESOURCE_FILE_SIZE, MAX_10MB_BASE64_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_CARRIERS, MAX_EVAL_ATTACHMENT_AGGREGATE_ENCODED_BYTES, MAX_RESOURCE_ENCODED_BYTES, MAX_HUB_AS_CODE_RESOURCES, MAX_HUB_AS_CODE_RESOURCE_FILES, MAX_RESOURCE_AGGREGATE_ENCODED_BYTES, MAX_CI_CONFIG_BODY_BYTES, hubAsCodeResourceFileSchema, hubAsCodeResourceSchema, uuidPattern, ciUuidSchema, boundedHubAsCodeResourcesSchema, hubAsCodeConfigSchema, ciPullHubIdParam, ciBranchParam, ciPullQuery, ciHubsQuery, ciLookupQuery, ciBranchesQuery, ciSyncBody, ciPushBody, ciDiffBody, ciPublishBody, ciPublishPreviewBody, ciSyncMcpBody, ciOrgResourcesParam, orgResourcesConfigSchema, ciOrgResourcesPushBody, ciOrgResourcesDiffBody, adminOrgIdParam, adminOrgAdminIdParam, adminUserIdParam, adminPlanIdParam, adminHubIdParam, adminOrganizationsQuery, adminUserSearchQuery, kanbanSlugMigrationQuery, adjustQuotaBody, updatePlanBody, addAdminUserBody, updatePlatformConfigBody, updateFreeOrgLimitBody, adminSetOrgHarnessBody, adminSetHubHarnessBody, adminScopedTargetBody, updatePricingPlanBody, dataExplorerSearchQuery, dataExplorerOrgIdParam, dataExplorerHubIdParam, dataExplorerConvIdParam, dataExplorerDoInstancesQuery, dataExplorerNsIdParam, dataExplorerKvKeysQuery, dataExplorerKvKeyParam, uuidOrHexId, dataExplorerDeleteOrgParam, dataExplorerDeleteHubParam, dataExplorerDeleteConvParam, dataExplorerDeleteUserParam, dataExplorerDeleteQuery, dataExplorerKvDeleteQuery, pitrDoNamespace, pitrBookmarkParam, pitrRestoreBody, healthSamplingTriggerBody, dataExplorerDebugDoType, DEBUG_READ_MAX_LIMIT, DEBUG_READ_DEFAULT_LIMIT, DEBUG_DO_HEX_PREFIX, debugDoEntityId, debugTableName, dataExplorerDebugTablesParam, dataExplorerDebugRowsParam, dataExplorerDebugRowsQuery, dataExplorerDebugAnalyticsTable, debugUuid, dataExplorerDebugAnalyticsRowsParam, dataExplorerDebugAnalyticsRowsQuery, debugHubConvParam, debugMessageIdQuery, sandboxEgressPolicy, SANDBOX_EXEC_MAX_CMD_LENGTH, SANDBOX_EXEC_MAX_ALLOWLIST, SANDBOX_EXEC_MAX_TIMEOUT_MS, adminSandboxExecBody, whatsappCallbackBody, authMeResponse, wsTicketResponse, sessionCheckResponse, logoutResponse, magicCodeSendBody, magicCodeSendResponse, magicCodeVerifyBody, magicCodeVerifyResponse, browserParams, browserFoldersQuery, browserFilesQuery, stateOperationBody, conversationListResourcesQuery, conversationReadResourceQuery, listPendingSchedulesQuery, listHubAggregateSchedulesQuery, reportSourceSchema, intakeReportSourceSchema, reportClassificationSchema, reportStatusSchema, reportLocaleSchema, reportMessageAuthorRoleSchema, sentryRefStatusSchema, createReportBody, editReportBody, contestReportBody, reporterListQuery, listReportsQuery, GITHUB_ISSUE_URL_REGEX, githubIssueUrlSchema, transitionReportBody, groupReportsBody, holdReportBody, clickhouseReadyResponse, bootstrapQuery, requestSnapshotChunkMessage, MAX_NAME_LENGTH, MAX_VALUE_LENGTH, MAX_TAGS, MAX_TAG_LENGTH, MAX_SCOPE_HUBS, MAX_SCOPE_TAGS, vaultSecretScopeSchema, vaultCreateBody, vaultUpdateBody, PERMISSIONS, MAX_NAME_LENGTH2, MAX_HUBS_PER_GRANT, MAX_HUB_TAGS_PER_GRANT, MAX_GRANTS, permissionEnum, grantScopeSchema, grantSchema, createTokenBody, tokenOrgIdParam, tokenGrantScopeSchema, tokenGrantSchema, tokenMetadataSchema, listTokensResponse, createTokenResponse, orgTokenSummarySchema, listOrgTokensResponse, invitePreviewQuery, invitePreviewResponse, discordTier, discordBillingCycle, discordMetadata, discordOAuthStartResponse, discordOAuthFinalizeBody, discordOAuthFinalizeResponse, discordDisconnectResponse, jsonSchemaSchema, hubUserIdentity, stateValueEntry, getHubUserContextResponse, updateHubUserBody, updateHubUserResponse, unlockHubUserNameResponse, stateResetParams, stateResetResponse, hubAlertsParam, hubAlertSeverity, hubAlert, hubAlertsListResponse, noticeSeveritySchema, noticeStatusSchema, NOTICE_SCOPE_REGEX, noticeScopeSchema, noticeLinkSchema, createNoticeBody, updateNoticeBody, listNoticesQuery, noticeIdParamSchema, templateLocaleSchema, TEMPLATE_SLUG_REGEX, templateSlugSchema, templateStatusSchema, templateFileMapSchema, templateTextSchema, templateUsesEntrySchema, templateUsesSchema, templateYamlLocaleEntry, templateYamlWayaiBlock, templateTagsSchema, templateYamlSchema, templateHeroSchema, templatePushLocaleSchema, templatePushBody, templateListQuery, templateSlugParam, templateDetailQuery, ADMIN_SKILL_NAME_REGEX, adminSkillNameParam, WAYAI_WORKSPACE_LAYOUT;
5961
+ 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, primaryRegionSchema, placementSourceSchema, orgIdParam, orgAdminIdParam, createOrganizationBody, updateOrganizationBody, addOrgAdminBody, SUMMARIZATION_THRESHOLD_MIN, SUMMARIZATION_THRESHOLD_MAX, summarizationThresholdField, monitorConfigField, agentIdParam, listAgentsQuery, agentConnectionsQuery, createAgentBody, updateAgentBody, AGENT_PARAMETER_TYPES, AGENT_PARAMETER_NAME_REGEX, agentParameterCreateSchema, MAX_AGENT_PARAMETERS_PER_REQUEST, createAgentParametersBody, SLUG_REGEX, slugSchema, INVISIBLE_NAME_CHARS, MAX_KANBAN_STATUSES, MAX_FOLLOWUPS_PER_STATUS, MAX_LANES, MAX_ADDITIONAL_CONTEXT_SCHEMA_BYTES, RESERVED_TEMPLATE_DUMP_NAME, kanbanStatusSlugSchema, followupSchema, EXCLUSIVE_FLAG_PAIRS, kanbanStatusSchema, kanbanStatusesArraySchema, laneSchema, lanesArraySchema, hubIdParam, hubAdminIdParam, hubUserIdParam, hubIdentityIdParam, hubTeamIdParam, hubTeamUserDeleteParam, hubSchemaQuery, PREVIEW_LABEL_MAX_LENGTH, MAX_ENDED_INDEX_RETENTION_DAYS, previewLabelField, createHubBody, updateHubBody, addHubAdminBody, addHubIdentityAuthorizationBody, contactDecisionBody, approveContactBody, listContactAccessQuery, createHubTeamBody, updateHubTeamBody, addHubTeamUserBody, reassignHubUserBody, replicatePreviewBody, updateChannelTestIdentitiesBody, claimCodeChannelParam, claimCodeDeleteParam, connectionIdParam, connectorIdParam, listConnectionsQuery, deleteConnectionQuery, addConnectionBody, editConnectionBody, PRODUCTION_DIRECT_FIELDS, setProductionCredentialBody, registerWhatsappQuery, registerWhatsappBody, retryProvisioningQuery, resendDomainStatusQuery, PLACEHOLDER_TOKENS, ALLOWED_TYPES, SUBSCHEMA_OBJECT_KEYWORDS, SUBSCHEMA_LIST_KEYWORDS, SUBSCHEMA_MAP_KEYWORDS, MAX_SCHEMA_DEPTH, toolIdParam, listToolsQuery, toolAgentQuery, deleteToolQuery, toolConnectionsQuery, nativeToolIdSchema, addNativeToolBody, addMcpToolBody, createCustomToolBody, updateCustomToolBody, updateToolExecutionConfigBody, initialValueCreateSchema, initialValueUpdateSchema, stateIdParam, listStatesQuery, stateNameSchema, createStateBody, updateStateBody, reorderStatesBody, variantAiModeSchema, experimentStatusSchema, overlayUpdateSchema, experimentIdParam, variantIdParam, listExperimentsQuery, listVariantsQuery, listOverridesQuery, deleteOverrideQuery, createExperimentBody, updateExperimentBody, setExperimentStatusBody, createVariantBody, updateVariantBody, upsertOverrideBody, orgTagIdParam, listOrgTagsQuery, createOrgTagBody, updateOrgTagBody, orgCredentialIdParam, listOrgCredentialsQuery, createOrgCredentialBody, updateOrgCredentialBody, orgResourceIdParam, orgResourceFileIdParam, orgResourceFolderIdParam, hubOrgResourceParam, listOrgResourcesQuery, orgIdQuery, createOrgResourceBody, updateOrgResourceBody, createOrgResourceFolderBody, updateOrgResourceFolderBody, uploadOrgResourceFileBody, updateOrgResourceFileBody, uploadOrgSkillZipBody, linkOrgResourceBody, resourceIdParam, listResourcesQuery, createResourceBody, updateResourceBody, syncSkillsBody, resourceFileIdParam, listResourceFilesQuery, createResourceFileBody, updateResourceFileBody, uploadResourceFileBody, uploadSkillZipBody, resourceFolderIdParam, listResourceFoldersQuery, createResourceFolderBody, updateResourceFolderBody, agentResourceQuery, hubResourceQuery, linkAgentResourceBody, updateAgentResourceBody, unlinkAgentResourceQuery, navItemSchema, hubCountResetBody, navItemCountResetBody, typingBody, analyticsHubIdParam, analyticsVariableIdParam, updateVariablePinBody, updateAnalyticsViewBody, NUMERIC_FILTER_OPS, TEXT_FILTER_OPS, CATEGORICAL_FILTER_OPS, VARIABLE_FILTER_OPS, STRUCTURED_QUERY_OPS, STRUCTURED_QUERY_AGGREGATIONS, filterValueSchema, conversationsBody, analyticsConversationIdParam, messagesQuery, conversationDetailDataQuery, analyticsDataBody, structuredQueryBody, analyticsSqlBody, analyticsSqlSchemaQuery, EVAL_PACING_PRESET_NAMES, PACING_INTERVAL_MIN_MS, PACING_INTERVAL_MAX_MS, EVAL_RUN_DEADLINE_MIN_MS, EVAL_RUN_DEADLINE_MAX_MS, paginationSchema2, evalIdParam, sessionIdParam, scenarioSetIdParam, hubIdQuery, EVAL_INPUT_ROLES, EVAL_INPUT_ROLE_LIST, ROLE_ECHO_MAX, createEvalBody, updateEvalBody, getEvalsQuery, toggleEvalBody, bulkToggleEvalsBody, pacingConfigSchema, sessionConfigSchema, createSessionBody, getSessionsQuery, getSessionResultsQuery, getSessionRunsQuery, evalAnalyticsQuery, getSessionCostQuery, compareSessionsQuery, evalsSqlBody, evalsSqlSchemaQuery, exportResultsQuery, validateEvalBody, hubAgentsQuery, createScenarioSetBody, updateScenarioSetBody, scenarioSetsHubQuery, createScenarioFromConversationBody, createJourneyFromConversationBody, EVAL_ATTACHMENT_HASH_REGEX, evalAttachmentRef, turnMayCarryAttachments, ATTACHMENTS_USER_ONLY_MESSAGE, journeyIdParam, journeyToolCallSchema, journeyTurnSchema, journeyStepOverrideSchema, fixtureField, createJourneyBody, updateJourneyBody, getConversationsQuery, getMessagesQuery, appMessageSenderType, appMessageReceiverType, appMessageBody, updateUserBody, updateProfileBody, pathnameRegex, updatePreferencesBody, registerPushTokenBody, deletePushTokenQuery, activityQuery, deletionModeSchema, deletionRequestBody, archiveHubIdParam, archiveConversationParams, archiveListQuery, archiveMessageObservabilityParams, conversationIdParam, claimBody, releaseBody, transferBody, closeBody, additionalContextPayloadSchema, kanbanUpdateBody, annotateConversationBody, observabilityParams, observabilityListParams, deleteUserConversationsBody, sendMessageBody, listConversationsQuery, getConversationDetailParams, getConversationDetailQuery, listWhatsAppTemplatesQuery, sendWhatsAppTemplateBody, billingOrgIdParam, subscriptionItemParams, spendCapBody, growthPacksBody, portalSessionBody, checkoutSessionBody, updateBillingCurrencyBody, invoicesQuery, downloadBody, uploadQuery, signUrlBody, outboundSchemaQuery, templateIdParam, listTemplatesQuery, deleteTemplateQuery, templateStatusQuery, createTemplateBody, updateTemplateBody, submitTemplateBody, testTemplateBody, contactIdParam, listContactsQuery, createContactBody, updateContactBody, listIdParam, listListsQuery, listListContactsQuery, createListBody, updateListBody, addListContactsBody, removeListContactsBody, scheduleIdParam, listSchedulesQuery, listExecutionsQuery, createScheduleBody, updateScheduleBody, MAX_RESOURCE_FILE_SIZE, MAX_10MB_BASE64_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_CARRIERS, MAX_EVAL_ATTACHMENT_AGGREGATE_ENCODED_BYTES, MAX_RESOURCE_ENCODED_BYTES, MAX_HUB_AS_CODE_RESOURCES, MAX_HUB_AS_CODE_RESOURCE_FILES, MAX_RESOURCE_AGGREGATE_ENCODED_BYTES, MAX_CI_CONFIG_BODY_BYTES, hubAsCodeResourceFileSchema, hubAsCodeResourceSchema, uuidPattern, ciUuidSchema, boundedHubAsCodeResourcesSchema, hubAsCodeConfigSchema, ciPullHubIdParam, ciBranchParam, ciPullQuery, ciHubsQuery, ciLookupQuery, ciBranchesQuery, ciSyncBody, ciPushBody, ciDiffBody, ciPublishBody, ciPublishPreviewBody, ciSyncMcpBody, ciOrgResourcesParam, orgResourcesConfigSchema, ciOrgResourcesPushBody, ciOrgResourcesDiffBody, adminOrgIdParam, adminOrgAdminIdParam, adminUserIdParam, adminPlanIdParam, adminHubIdParam, adminOrganizationsQuery, adminUserSearchQuery, kanbanSlugMigrationQuery, adjustQuotaBody, updatePlanBody, addAdminUserBody, updatePlatformConfigBody, updateFreeOrgLimitBody, adminSetOrgHarnessBody, adminSetHubHarnessBody, adminScopedTargetBody, updatePricingPlanBody, dataExplorerSearchQuery, dataExplorerOrgIdParam, dataExplorerHubIdParam, dataExplorerConvIdParam, dataExplorerDoInstancesQuery, dataExplorerNsIdParam, dataExplorerKvKeysQuery, dataExplorerKvKeyParam, uuidOrHexId, dataExplorerDeleteOrgParam, dataExplorerDeleteHubParam, dataExplorerDeleteConvParam, dataExplorerDeleteUserParam, dataExplorerDeleteQuery, dataExplorerKvDeleteQuery, pitrDoNamespace, pitrBookmarkParam, pitrRestoreBody, healthSamplingTriggerBody, dataExplorerDebugDoType, DEBUG_READ_MAX_LIMIT, DEBUG_READ_DEFAULT_LIMIT, DEBUG_DO_HEX_PREFIX, debugDoEntityId, debugTableName, dataExplorerDebugTablesParam, dataExplorerDebugRowsParam, dataExplorerDebugRowsQuery, dataExplorerDebugAnalyticsTable, debugUuid, dataExplorerDebugAnalyticsRowsParam, dataExplorerDebugAnalyticsRowsQuery, debugHubConvParam, debugMessageIdQuery, sandboxEgressPolicy, SANDBOX_EXEC_MAX_CMD_LENGTH, SANDBOX_EXEC_MAX_ALLOWLIST, SANDBOX_EXEC_MAX_TIMEOUT_MS, adminSandboxExecBody, whatsappCallbackBody, authMeResponse, wsTicketResponse, sessionCheckResponse, logoutResponse, magicCodeSendBody, magicCodeSendResponse, magicCodeVerifyBody, magicCodeVerifyResponse, browserParams, browserFoldersQuery, browserFilesQuery, stateOperationBody, conversationListResourcesQuery, conversationReadResourceQuery, listPendingSchedulesQuery, listHubAggregateSchedulesQuery, reportSourceSchema, intakeReportSourceSchema, reportClassificationSchema, reportStatusSchema, reportLocaleSchema, reportMessageAuthorRoleSchema, reportMessageSchema, sentryRefStatusSchema, createReportBody, editReportBody, reporterReportSummarySchema, reporterListResponseSchema, getReportResponseSchema, reporterTransitionResponseSchema, contestReportBody, reporterListQuery, listReportsQuery, GITHUB_ISSUE_URL_REGEX, githubIssueUrlSchema, transitionReportBody, groupReportsBody, holdReportBody, clickhouseReadyResponse, bootstrapQuery, requestSnapshotChunkMessage, MAX_NAME_LENGTH, MAX_VALUE_LENGTH, MAX_TAGS, MAX_TAG_LENGTH, MAX_SCOPE_HUBS, MAX_SCOPE_TAGS, vaultSecretScopeSchema, vaultCreateBody, vaultUpdateBody, PERMISSIONS, MAX_NAME_LENGTH2, MAX_HUBS_PER_GRANT, MAX_HUB_TAGS_PER_GRANT, MAX_GRANTS, permissionEnum, grantScopeSchema, grantSchema, createTokenBody, tokenOrgIdParam, tokenGrantScopeSchema, tokenGrantSchema, tokenMetadataSchema, listTokensResponse, createTokenResponse, orgTokenSummarySchema, listOrgTokensResponse, invitePreviewQuery, invitePreviewResponse, discordTier, discordBillingCycle, discordMetadata, discordOAuthStartResponse, discordOAuthFinalizeBody, discordOAuthFinalizeResponse, discordDisconnectResponse, jsonSchemaSchema, hubUserIdentity, stateValueEntry, getHubUserContextResponse, updateHubUserBody, updateHubUserResponse, unlockHubUserNameResponse, stateResetParams, stateResetResponse, hubAlertsParam, hubAlertSeverity, hubAlert, hubAlertsListResponse, noticeSeveritySchema, noticeStatusSchema, NOTICE_SCOPE_REGEX, noticeScopeSchema, noticeLinkSchema, createNoticeBody, updateNoticeBody, listNoticesQuery, noticeIdParamSchema, templateLocaleSchema, TEMPLATE_SLUG_REGEX, templateSlugSchema, templateStatusSchema, templateFileMapSchema, templateTextSchema, templateUsesEntrySchema, templateUsesSchema, templateYamlLocaleEntry, templateYamlWayaiBlock, templateTagsSchema, templateYamlSchema, templateHeroSchema, templatePushLocaleSchema, templatePushBody, templateListQuery, templateSlugParam, templateDetailQuery, ADMIN_SKILL_NAME_REGEX, adminSkillNameParam, WAYAI_WORKSPACE_LAYOUT;
5962
5962
  var init_dist = __esm({
5963
5963
  "../../packages/core/dist/index.js"() {
5964
5964
  "use strict";
@@ -8424,6 +8424,20 @@ var init_dist = __esm({
8424
8424
  ]);
8425
8425
  reportLocaleSchema = external_exports.enum(["en", "pt", "es"]);
8426
8426
  reportMessageAuthorRoleSchema = external_exports.enum(["reporter", "triage", "fixer", "system"]);
8427
+ reportMessageSchema = external_exports.object({
8428
+ message_id: external_exports.string(),
8429
+ author_role: reportMessageAuthorRoleSchema,
8430
+ /** The status transition this note accompanied (e.g. 'shipped'); null for a free/system note. */
8431
+ transition: external_exports.string().nullable(),
8432
+ body: external_exports.string(),
8433
+ created_at: timestampSchema,
8434
+ /**
8435
+ * Visibility: `false` = reporter-facing (the default for every narrative entry); `true` =
8436
+ * triage-internal (e.g. a `hold` rationale) — surfaced to platform admins only and NEVER
8437
+ * returned on the reporter read path. The reporter's `GET /api/reports/:id` filters these out.
8438
+ */
8439
+ internal: external_exports.boolean()
8440
+ });
8427
8441
  sentryRefStatusSchema = external_exports.enum(["valid", "not_found", "mismatch", "unverified"]);
8428
8442
  createReportBody = external_exports.object({
8429
8443
  title: external_exports.string().min(5).max(256),
@@ -8455,6 +8469,30 @@ var init_dist = __esm({
8455
8469
  }).strict().refine((b) => Object.keys(b).length > 0, {
8456
8470
  message: "at least one field must be provided"
8457
8471
  });
8472
+ reporterReportSummarySchema = external_exports.object({
8473
+ report_id: external_exports.string(),
8474
+ title: external_exports.string(),
8475
+ description: external_exports.string(),
8476
+ classification: reportClassificationSchema,
8477
+ status: reportStatusSchema,
8478
+ created_at: timestampSchema,
8479
+ triaged_at: timestampSchema.nullable(),
8480
+ resolved_at: timestampSchema.nullable(),
8481
+ /** How many times the reporter has contested (gates the hard cap). */
8482
+ contest_count: external_exports.number(),
8483
+ /** True once triage issued a non-contestable (final) dismissal. */
8484
+ dismissal_final: external_exports.boolean()
8485
+ });
8486
+ reporterListResponseSchema = external_exports.object({
8487
+ data: external_exports.array(reporterReportSummarySchema)
8488
+ });
8489
+ getReportResponseSchema = external_exports.object({
8490
+ report: reporterReportSummarySchema,
8491
+ messages: external_exports.array(reportMessageSchema)
8492
+ });
8493
+ reporterTransitionResponseSchema = external_exports.object({
8494
+ report: reporterReportSummarySchema
8495
+ });
8458
8496
  contestReportBody = external_exports.object({
8459
8497
  reason: external_exports.string().min(1).max(5e3)
8460
8498
  });
@@ -11147,6 +11185,20 @@ var init_init = __esm({
11147
11185
  // src/lib/fs-safety.ts
11148
11186
  import * as fs9 from "fs";
11149
11187
  import * as path11 from "path";
11188
+ function fileHasBytes(abs, data) {
11189
+ let st;
11190
+ try {
11191
+ st = fs9.lstatSync(abs);
11192
+ } catch {
11193
+ return false;
11194
+ }
11195
+ if (!st.isFile() || st.isSymbolicLink()) return false;
11196
+ try {
11197
+ return fs9.readFileSync(abs).equals(data);
11198
+ } catch {
11199
+ return false;
11200
+ }
11201
+ }
11150
11202
  function realpathContained(root, abs) {
11151
11203
  let realRoot;
11152
11204
  let realAbs;
@@ -11852,7 +11904,7 @@ function isSanitizableSliceFile(path31) {
11852
11904
  function distinctUsesBackends(uses) {
11853
11905
  return [...new Set((uses ?? []).map((u) => u.backend))];
11854
11906
  }
11855
- var uuidSchema2, paginationSchema3, timestampSchema2, idParamSchema2, clientOptionalString2, clientOptionalBoolean2, clientOptionalNumber2, messageAttachment2, MAX_MESSAGE_BODY_BYTES2, MAX_ATTACHMENTS_PER_MESSAGE2, primaryRegionSchema2, placementSourceSchema2, orgIdParam2, orgAdminIdParam2, createOrganizationBody2, updateOrganizationBody2, addOrgAdminBody2, AUTH_TYPE3, ORG_CREDENTIAL_AUTH_TYPES3, AUTH_TYPE_DISPLAY3, LEGACY_AUTH_TYPE_MAP3, VALID_AUTH_TYPES3, AGENT_ROLES2, SAFE_USER_ID_REGEX2, SUPPORTED_LOCALES2, SUMMARIZATION_THRESHOLD_MIN2, SUMMARIZATION_THRESHOLD_MAX2, summarizationThresholdField2, monitorConfigField2, agentIdParam2, listAgentsQuery2, agentConnectionsQuery2, createAgentBody2, updateAgentBody2, AGENT_PARAMETER_TYPES2, AGENT_PARAMETER_NAME_REGEX2, agentParameterCreateSchema2, MAX_AGENT_PARAMETERS_PER_REQUEST2, createAgentParametersBody2, SLUG_REGEX2, slugSchema2, INVISIBLE_NAME_CHARS2, MAX_KANBAN_STATUSES2, MAX_FOLLOWUPS_PER_STATUS2, MAX_LANES2, MAX_ADDITIONAL_CONTEXT_SCHEMA_BYTES2, RESERVED_TEMPLATE_DUMP_NAME2, kanbanStatusSlugSchema2, followupSchema2, EXCLUSIVE_FLAG_PAIRS2, kanbanStatusSchema2, kanbanStatusesArraySchema2, laneSchema2, lanesArraySchema2, hubIdParam2, hubAdminIdParam2, hubUserIdParam2, hubIdentityIdParam2, hubTeamIdParam2, hubTeamUserDeleteParam2, hubSchemaQuery2, PREVIEW_LABEL_MAX_LENGTH2, MAX_ENDED_INDEX_RETENTION_DAYS2, previewLabelField2, createHubBody2, updateHubBody2, addHubAdminBody2, addHubIdentityAuthorizationBody2, contactDecisionBody2, approveContactBody2, listContactAccessQuery2, createHubTeamBody2, updateHubTeamBody2, addHubTeamUserBody2, reassignHubUserBody2, replicatePreviewBody2, updateChannelTestIdentitiesBody2, claimCodeChannelParam2, claimCodeDeleteParam2, connectionIdParam2, connectorIdParam2, listConnectionsQuery2, deleteConnectionQuery2, addConnectionBody2, editConnectionBody2, PRODUCTION_DIRECT_FIELDS2, setProductionCredentialBody2, registerWhatsappQuery2, registerWhatsappBody2, retryProvisioningQuery2, resendDomainStatusQuery2, PLACEHOLDER_TOKENS2, ALLOWED_TYPES2, SUBSCHEMA_OBJECT_KEYWORDS2, SUBSCHEMA_LIST_KEYWORDS2, SUBSCHEMA_MAP_KEYWORDS2, MAX_SCHEMA_DEPTH2, toolIdParam2, listToolsQuery2, toolAgentQuery2, deleteToolQuery2, toolConnectionsQuery2, nativeToolIdSchema2, addNativeToolBody2, addMcpToolBody2, createCustomToolBody2, updateCustomToolBody2, updateToolExecutionConfigBody2, initialValueCreateSchema2, initialValueUpdateSchema2, stateIdParam2, listStatesQuery2, stateNameSchema2, createStateBody2, updateStateBody2, reorderStatesBody2, variantAiModeSchema2, experimentStatusSchema2, overlayUpdateSchema2, experimentIdParam2, variantIdParam2, listExperimentsQuery2, listVariantsQuery2, listOverridesQuery2, deleteOverrideQuery2, createExperimentBody2, updateExperimentBody2, setExperimentStatusBody2, createVariantBody2, updateVariantBody2, upsertOverrideBody2, orgTagIdParam2, listOrgTagsQuery2, createOrgTagBody2, updateOrgTagBody2, orgCredentialIdParam2, listOrgCredentialsQuery2, createOrgCredentialBody2, updateOrgCredentialBody2, orgResourceIdParam2, orgResourceFileIdParam2, orgResourceFolderIdParam2, hubOrgResourceParam2, listOrgResourcesQuery2, orgIdQuery2, createOrgResourceBody2, updateOrgResourceBody2, createOrgResourceFolderBody2, updateOrgResourceFolderBody2, uploadOrgResourceFileBody2, updateOrgResourceFileBody2, uploadOrgSkillZipBody2, linkOrgResourceBody2, resourceIdParam2, listResourcesQuery2, createResourceBody2, updateResourceBody2, syncSkillsBody2, resourceFileIdParam2, listResourceFilesQuery2, createResourceFileBody2, updateResourceFileBody2, uploadResourceFileBody2, uploadSkillZipBody2, resourceFolderIdParam2, listResourceFoldersQuery2, createResourceFolderBody2, updateResourceFolderBody2, agentResourceQuery2, hubResourceQuery2, linkAgentResourceBody2, updateAgentResourceBody2, unlinkAgentResourceQuery2, navItemSchema2, hubCountResetBody2, navItemCountResetBody2, typingBody2, analyticsHubIdParam2, analyticsVariableIdParam2, updateVariablePinBody2, updateAnalyticsViewBody2, NUMERIC_FILTER_OPS2, TEXT_FILTER_OPS2, CATEGORICAL_FILTER_OPS2, VARIABLE_FILTER_OPS2, STRUCTURED_QUERY_OPS2, STRUCTURED_QUERY_AGGREGATIONS2, filterValueSchema2, conversationsBody2, analyticsConversationIdParam2, messagesQuery2, conversationDetailDataQuery2, analyticsDataBody2, structuredQueryBody2, analyticsSqlBody2, analyticsSqlSchemaQuery2, EVAL_PACING_PRESET_NAMES2, PACING_INTERVAL_MIN_MS2, PACING_INTERVAL_MAX_MS2, EVAL_RUN_DEADLINE_MIN_MS2, EVAL_RUN_DEADLINE_MAX_MS2, paginationSchema22, evalIdParam2, sessionIdParam2, scenarioSetIdParam2, hubIdQuery2, EVAL_INPUT_ROLES2, EVAL_INPUT_ROLE_LIST2, ROLE_ECHO_MAX2, createEvalBody2, updateEvalBody2, getEvalsQuery2, toggleEvalBody2, bulkToggleEvalsBody2, pacingConfigSchema2, sessionConfigSchema2, createSessionBody2, getSessionsQuery2, getSessionResultsQuery2, getSessionRunsQuery2, evalAnalyticsQuery2, getSessionCostQuery2, compareSessionsQuery2, evalsSqlBody2, evalsSqlSchemaQuery2, exportResultsQuery2, validateEvalBody2, hubAgentsQuery2, createScenarioSetBody2, updateScenarioSetBody2, scenarioSetsHubQuery2, createScenarioFromConversationBody2, createJourneyFromConversationBody2, EVAL_ATTACHMENT_HASH_REGEX2, evalAttachmentRef2, turnMayCarryAttachments2, ATTACHMENTS_USER_ONLY_MESSAGE2, journeyIdParam2, journeyToolCallSchema2, journeyTurnSchema2, journeyStepOverrideSchema2, fixtureField2, createJourneyBody2, updateJourneyBody2, getConversationsQuery2, getMessagesQuery2, appMessageSenderType2, appMessageReceiverType2, appMessageBody2, updateUserBody2, updateProfileBody2, pathnameRegex2, updatePreferencesBody2, registerPushTokenBody2, deletePushTokenQuery2, activityQuery2, deletionModeSchema2, deletionRequestBody2, archiveHubIdParam2, archiveConversationParams2, archiveListQuery2, archiveMessageObservabilityParams2, conversationIdParam2, claimBody2, releaseBody2, transferBody2, closeBody2, additionalContextPayloadSchema2, kanbanUpdateBody2, annotateConversationBody2, observabilityParams2, observabilityListParams2, deleteUserConversationsBody2, sendMessageBody2, listConversationsQuery2, getConversationDetailParams2, getConversationDetailQuery2, listWhatsAppTemplatesQuery2, sendWhatsAppTemplateBody2, billingOrgIdParam2, subscriptionItemParams2, spendCapBody2, growthPacksBody2, portalSessionBody2, checkoutSessionBody2, updateBillingCurrencyBody2, invoicesQuery2, downloadBody2, uploadQuery2, signUrlBody2, outboundSchemaQuery2, templateIdParam2, listTemplatesQuery2, deleteTemplateQuery2, templateStatusQuery2, createTemplateBody2, updateTemplateBody2, submitTemplateBody2, testTemplateBody2, contactIdParam2, listContactsQuery2, createContactBody2, updateContactBody2, listIdParam2, listListsQuery2, listListContactsQuery2, createListBody2, updateListBody2, addListContactsBody2, removeListContactsBody2, scheduleIdParam2, listSchedulesQuery2, listExecutionsQuery2, createScheduleBody2, updateScheduleBody2, MAX_RESOURCE_FILE_SIZE2, MAX_10MB_BASE64_ENCODED_BYTES2, MAX_EVAL_ATTACHMENT_ENCODED_BYTES2, MAX_EVAL_ATTACHMENT_CARRIERS2, MAX_EVAL_ATTACHMENT_AGGREGATE_ENCODED_BYTES2, MAX_RESOURCE_ENCODED_BYTES2, MAX_HUB_AS_CODE_RESOURCES2, MAX_HUB_AS_CODE_RESOURCE_FILES2, MAX_RESOURCE_AGGREGATE_ENCODED_BYTES2, MAX_CI_CONFIG_BODY_BYTES2, hubAsCodeResourceFileSchema2, hubAsCodeResourceSchema2, uuidPattern2, ciUuidSchema2, boundedHubAsCodeResourcesSchema2, hubAsCodeConfigSchema2, ciPullHubIdParam2, ciBranchParam2, ciPullQuery2, ciHubsQuery2, ciLookupQuery2, ciBranchesQuery2, ciSyncBody2, ciPushBody2, ciDiffBody2, ciPublishBody2, ciPublishPreviewBody2, ciSyncMcpBody2, ciOrgResourcesParam2, orgResourcesConfigSchema2, ciOrgResourcesPushBody2, ciOrgResourcesDiffBody2, adminOrgIdParam2, adminOrgAdminIdParam2, adminUserIdParam2, adminPlanIdParam2, adminHubIdParam2, adminOrganizationsQuery2, adminUserSearchQuery2, kanbanSlugMigrationQuery2, adjustQuotaBody2, updatePlanBody2, addAdminUserBody2, updatePlatformConfigBody2, updateFreeOrgLimitBody2, adminSetOrgHarnessBody2, adminSetHubHarnessBody2, adminScopedTargetBody2, updatePricingPlanBody2, dataExplorerSearchQuery2, dataExplorerOrgIdParam2, dataExplorerHubIdParam2, dataExplorerConvIdParam2, dataExplorerDoInstancesQuery2, dataExplorerNsIdParam2, dataExplorerKvKeysQuery2, dataExplorerKvKeyParam2, uuidOrHexId2, dataExplorerDeleteOrgParam2, dataExplorerDeleteHubParam2, dataExplorerDeleteConvParam2, dataExplorerDeleteUserParam2, dataExplorerDeleteQuery2, dataExplorerKvDeleteQuery2, pitrDoNamespace2, pitrBookmarkParam2, pitrRestoreBody2, healthSamplingTriggerBody2, dataExplorerDebugDoType2, DEBUG_READ_MAX_LIMIT2, DEBUG_READ_DEFAULT_LIMIT2, DEBUG_DO_HEX_PREFIX2, debugDoEntityId2, debugTableName2, dataExplorerDebugTablesParam2, dataExplorerDebugRowsParam2, dataExplorerDebugRowsQuery2, dataExplorerDebugAnalyticsTable2, debugUuid2, dataExplorerDebugAnalyticsRowsParam2, dataExplorerDebugAnalyticsRowsQuery2, debugHubConvParam2, debugMessageIdQuery2, sandboxEgressPolicy2, SANDBOX_EXEC_MAX_CMD_LENGTH2, SANDBOX_EXEC_MAX_ALLOWLIST2, SANDBOX_EXEC_MAX_TIMEOUT_MS2, adminSandboxExecBody2, whatsappCallbackBody2, authMeResponse2, wsTicketResponse2, sessionCheckResponse2, logoutResponse2, magicCodeSendBody2, magicCodeSendResponse2, magicCodeVerifyBody2, magicCodeVerifyResponse2, browserParams2, browserFoldersQuery2, browserFilesQuery2, stateOperationBody2, conversationListResourcesQuery2, conversationReadResourceQuery2, listPendingSchedulesQuery2, listHubAggregateSchedulesQuery2, reportSourceSchema2, intakeReportSourceSchema2, reportClassificationSchema2, reportStatusSchema2, reportLocaleSchema2, reportMessageAuthorRoleSchema2, sentryRefStatusSchema2, createReportBody2, editReportBody2, contestReportBody2, reporterListQuery2, listReportsQuery2, GITHUB_ISSUE_URL_REGEX2, githubIssueUrlSchema2, transitionReportBody2, groupReportsBody2, holdReportBody2, clickhouseReadyResponse2, bootstrapQuery2, requestSnapshotChunkMessage2, MAX_NAME_LENGTH3, MAX_VALUE_LENGTH2, MAX_TAGS2, MAX_TAG_LENGTH2, MAX_SCOPE_HUBS2, MAX_SCOPE_TAGS2, vaultSecretScopeSchema2, vaultCreateBody2, vaultUpdateBody2, PERMISSIONS2, MAX_NAME_LENGTH22, MAX_HUBS_PER_GRANT2, MAX_HUB_TAGS_PER_GRANT2, MAX_GRANTS2, permissionEnum2, grantScopeSchema2, grantSchema2, createTokenBody2, tokenOrgIdParam2, tokenGrantScopeSchema2, tokenGrantSchema2, tokenMetadataSchema2, listTokensResponse2, createTokenResponse2, orgTokenSummarySchema2, listOrgTokensResponse2, invitePreviewQuery2, invitePreviewResponse2, discordTier2, discordBillingCycle2, discordMetadata2, discordOAuthStartResponse2, discordOAuthFinalizeBody2, discordOAuthFinalizeResponse2, discordDisconnectResponse2, jsonSchemaSchema2, hubUserIdentity2, stateValueEntry2, getHubUserContextResponse2, updateHubUserBody2, updateHubUserResponse2, unlockHubUserNameResponse2, stateResetParams2, stateResetResponse2, hubAlertsParam2, hubAlertSeverity2, hubAlert2, hubAlertsListResponse2, noticeSeveritySchema2, noticeStatusSchema2, NOTICE_SCOPE_REGEX2, noticeScopeSchema2, noticeLinkSchema2, createNoticeBody2, updateNoticeBody2, listNoticesQuery2, noticeIdParamSchema2, templateLocaleSchema2, TEMPLATE_SLUG_REGEX2, templateSlugSchema2, templateStatusSchema2, templateFileMapSchema2, TEMPLATE_INSTANCE_ID_KEYS, TEMPLATE_OPAQUE_BLOB_KEYS, TEMPLATE_AUTHOR_DATA_KEYS, templateTextSchema2, templateUsesEntrySchema2, templateUsesSchema2, templateYamlLocaleEntry2, templateYamlWayaiBlock2, templateTagsSchema2, templateYamlSchema2, templateHeroSchema2, templatePushLocaleSchema2, templatePushBody2, templateListQuery2, templateSlugParam2, templateDetailQuery2, ADMIN_SKILL_NAME_REGEX2, adminSkillNameParam2;
11907
+ var uuidSchema2, paginationSchema3, timestampSchema2, idParamSchema2, clientOptionalString2, clientOptionalBoolean2, clientOptionalNumber2, messageAttachment2, MAX_MESSAGE_BODY_BYTES2, MAX_ATTACHMENTS_PER_MESSAGE2, primaryRegionSchema2, placementSourceSchema2, orgIdParam2, orgAdminIdParam2, createOrganizationBody2, updateOrganizationBody2, addOrgAdminBody2, AUTH_TYPE3, ORG_CREDENTIAL_AUTH_TYPES3, AUTH_TYPE_DISPLAY3, LEGACY_AUTH_TYPE_MAP3, VALID_AUTH_TYPES3, AGENT_ROLES2, SAFE_USER_ID_REGEX2, SUPPORTED_LOCALES2, SUMMARIZATION_THRESHOLD_MIN2, SUMMARIZATION_THRESHOLD_MAX2, summarizationThresholdField2, monitorConfigField2, agentIdParam2, listAgentsQuery2, agentConnectionsQuery2, createAgentBody2, updateAgentBody2, AGENT_PARAMETER_TYPES2, AGENT_PARAMETER_NAME_REGEX2, agentParameterCreateSchema2, MAX_AGENT_PARAMETERS_PER_REQUEST2, createAgentParametersBody2, SLUG_REGEX2, slugSchema2, INVISIBLE_NAME_CHARS2, MAX_KANBAN_STATUSES2, MAX_FOLLOWUPS_PER_STATUS2, MAX_LANES2, MAX_ADDITIONAL_CONTEXT_SCHEMA_BYTES2, RESERVED_TEMPLATE_DUMP_NAME2, kanbanStatusSlugSchema2, followupSchema2, EXCLUSIVE_FLAG_PAIRS2, kanbanStatusSchema2, kanbanStatusesArraySchema2, laneSchema2, lanesArraySchema2, hubIdParam2, hubAdminIdParam2, hubUserIdParam2, hubIdentityIdParam2, hubTeamIdParam2, hubTeamUserDeleteParam2, hubSchemaQuery2, PREVIEW_LABEL_MAX_LENGTH2, MAX_ENDED_INDEX_RETENTION_DAYS2, previewLabelField2, createHubBody2, updateHubBody2, addHubAdminBody2, addHubIdentityAuthorizationBody2, contactDecisionBody2, approveContactBody2, listContactAccessQuery2, createHubTeamBody2, updateHubTeamBody2, addHubTeamUserBody2, reassignHubUserBody2, replicatePreviewBody2, updateChannelTestIdentitiesBody2, claimCodeChannelParam2, claimCodeDeleteParam2, connectionIdParam2, connectorIdParam2, listConnectionsQuery2, deleteConnectionQuery2, addConnectionBody2, editConnectionBody2, PRODUCTION_DIRECT_FIELDS2, setProductionCredentialBody2, registerWhatsappQuery2, registerWhatsappBody2, retryProvisioningQuery2, resendDomainStatusQuery2, PLACEHOLDER_TOKENS2, ALLOWED_TYPES2, SUBSCHEMA_OBJECT_KEYWORDS2, SUBSCHEMA_LIST_KEYWORDS2, SUBSCHEMA_MAP_KEYWORDS2, MAX_SCHEMA_DEPTH2, toolIdParam2, listToolsQuery2, toolAgentQuery2, deleteToolQuery2, toolConnectionsQuery2, nativeToolIdSchema2, addNativeToolBody2, addMcpToolBody2, createCustomToolBody2, updateCustomToolBody2, updateToolExecutionConfigBody2, initialValueCreateSchema2, initialValueUpdateSchema2, stateIdParam2, listStatesQuery2, stateNameSchema2, createStateBody2, updateStateBody2, reorderStatesBody2, variantAiModeSchema2, experimentStatusSchema2, overlayUpdateSchema2, experimentIdParam2, variantIdParam2, listExperimentsQuery2, listVariantsQuery2, listOverridesQuery2, deleteOverrideQuery2, createExperimentBody2, updateExperimentBody2, setExperimentStatusBody2, createVariantBody2, updateVariantBody2, upsertOverrideBody2, orgTagIdParam2, listOrgTagsQuery2, createOrgTagBody2, updateOrgTagBody2, orgCredentialIdParam2, listOrgCredentialsQuery2, createOrgCredentialBody2, updateOrgCredentialBody2, orgResourceIdParam2, orgResourceFileIdParam2, orgResourceFolderIdParam2, hubOrgResourceParam2, listOrgResourcesQuery2, orgIdQuery2, createOrgResourceBody2, updateOrgResourceBody2, createOrgResourceFolderBody2, updateOrgResourceFolderBody2, uploadOrgResourceFileBody2, updateOrgResourceFileBody2, uploadOrgSkillZipBody2, linkOrgResourceBody2, resourceIdParam2, listResourcesQuery2, createResourceBody2, updateResourceBody2, syncSkillsBody2, resourceFileIdParam2, listResourceFilesQuery2, createResourceFileBody2, updateResourceFileBody2, uploadResourceFileBody2, uploadSkillZipBody2, resourceFolderIdParam2, listResourceFoldersQuery2, createResourceFolderBody2, updateResourceFolderBody2, agentResourceQuery2, hubResourceQuery2, linkAgentResourceBody2, updateAgentResourceBody2, unlinkAgentResourceQuery2, navItemSchema2, hubCountResetBody2, navItemCountResetBody2, typingBody2, analyticsHubIdParam2, analyticsVariableIdParam2, updateVariablePinBody2, updateAnalyticsViewBody2, NUMERIC_FILTER_OPS2, TEXT_FILTER_OPS2, CATEGORICAL_FILTER_OPS2, VARIABLE_FILTER_OPS2, STRUCTURED_QUERY_OPS2, STRUCTURED_QUERY_AGGREGATIONS2, filterValueSchema2, conversationsBody2, analyticsConversationIdParam2, messagesQuery2, conversationDetailDataQuery2, analyticsDataBody2, structuredQueryBody2, analyticsSqlBody2, analyticsSqlSchemaQuery2, EVAL_PACING_PRESET_NAMES2, PACING_INTERVAL_MIN_MS2, PACING_INTERVAL_MAX_MS2, EVAL_RUN_DEADLINE_MIN_MS2, EVAL_RUN_DEADLINE_MAX_MS2, paginationSchema22, evalIdParam2, sessionIdParam2, scenarioSetIdParam2, hubIdQuery2, EVAL_INPUT_ROLES2, EVAL_INPUT_ROLE_LIST2, ROLE_ECHO_MAX2, createEvalBody2, updateEvalBody2, getEvalsQuery2, toggleEvalBody2, bulkToggleEvalsBody2, pacingConfigSchema2, sessionConfigSchema2, createSessionBody2, getSessionsQuery2, getSessionResultsQuery2, getSessionRunsQuery2, evalAnalyticsQuery2, getSessionCostQuery2, compareSessionsQuery2, evalsSqlBody2, evalsSqlSchemaQuery2, exportResultsQuery2, validateEvalBody2, hubAgentsQuery2, createScenarioSetBody2, updateScenarioSetBody2, scenarioSetsHubQuery2, createScenarioFromConversationBody2, createJourneyFromConversationBody2, EVAL_ATTACHMENT_HASH_REGEX2, evalAttachmentRef2, turnMayCarryAttachments2, ATTACHMENTS_USER_ONLY_MESSAGE2, journeyIdParam2, journeyToolCallSchema2, journeyTurnSchema2, journeyStepOverrideSchema2, fixtureField2, createJourneyBody2, updateJourneyBody2, getConversationsQuery2, getMessagesQuery2, appMessageSenderType2, appMessageReceiverType2, appMessageBody2, updateUserBody2, updateProfileBody2, pathnameRegex2, updatePreferencesBody2, registerPushTokenBody2, deletePushTokenQuery2, activityQuery2, deletionModeSchema2, deletionRequestBody2, archiveHubIdParam2, archiveConversationParams2, archiveListQuery2, archiveMessageObservabilityParams2, conversationIdParam2, claimBody2, releaseBody2, transferBody2, closeBody2, additionalContextPayloadSchema2, kanbanUpdateBody2, annotateConversationBody2, observabilityParams2, observabilityListParams2, deleteUserConversationsBody2, sendMessageBody2, listConversationsQuery2, getConversationDetailParams2, getConversationDetailQuery2, listWhatsAppTemplatesQuery2, sendWhatsAppTemplateBody2, billingOrgIdParam2, subscriptionItemParams2, spendCapBody2, growthPacksBody2, portalSessionBody2, checkoutSessionBody2, updateBillingCurrencyBody2, invoicesQuery2, downloadBody2, uploadQuery2, signUrlBody2, outboundSchemaQuery2, templateIdParam2, listTemplatesQuery2, deleteTemplateQuery2, templateStatusQuery2, createTemplateBody2, updateTemplateBody2, submitTemplateBody2, testTemplateBody2, contactIdParam2, listContactsQuery2, createContactBody2, updateContactBody2, listIdParam2, listListsQuery2, listListContactsQuery2, createListBody2, updateListBody2, addListContactsBody2, removeListContactsBody2, scheduleIdParam2, listSchedulesQuery2, listExecutionsQuery2, createScheduleBody2, updateScheduleBody2, MAX_RESOURCE_FILE_SIZE2, MAX_10MB_BASE64_ENCODED_BYTES2, MAX_EVAL_ATTACHMENT_ENCODED_BYTES2, MAX_EVAL_ATTACHMENT_CARRIERS2, MAX_EVAL_ATTACHMENT_AGGREGATE_ENCODED_BYTES2, MAX_RESOURCE_ENCODED_BYTES2, MAX_HUB_AS_CODE_RESOURCES2, MAX_HUB_AS_CODE_RESOURCE_FILES2, MAX_RESOURCE_AGGREGATE_ENCODED_BYTES2, MAX_CI_CONFIG_BODY_BYTES2, hubAsCodeResourceFileSchema2, hubAsCodeResourceSchema2, uuidPattern2, ciUuidSchema2, boundedHubAsCodeResourcesSchema2, hubAsCodeConfigSchema2, ciPullHubIdParam2, ciBranchParam2, ciPullQuery2, ciHubsQuery2, ciLookupQuery2, ciBranchesQuery2, ciSyncBody2, ciPushBody2, ciDiffBody2, ciPublishBody2, ciPublishPreviewBody2, ciSyncMcpBody2, ciOrgResourcesParam2, orgResourcesConfigSchema2, ciOrgResourcesPushBody2, ciOrgResourcesDiffBody2, adminOrgIdParam2, adminOrgAdminIdParam2, adminUserIdParam2, adminPlanIdParam2, adminHubIdParam2, adminOrganizationsQuery2, adminUserSearchQuery2, kanbanSlugMigrationQuery2, adjustQuotaBody2, updatePlanBody2, addAdminUserBody2, updatePlatformConfigBody2, updateFreeOrgLimitBody2, adminSetOrgHarnessBody2, adminSetHubHarnessBody2, adminScopedTargetBody2, updatePricingPlanBody2, dataExplorerSearchQuery2, dataExplorerOrgIdParam2, dataExplorerHubIdParam2, dataExplorerConvIdParam2, dataExplorerDoInstancesQuery2, dataExplorerNsIdParam2, dataExplorerKvKeysQuery2, dataExplorerKvKeyParam2, uuidOrHexId2, dataExplorerDeleteOrgParam2, dataExplorerDeleteHubParam2, dataExplorerDeleteConvParam2, dataExplorerDeleteUserParam2, dataExplorerDeleteQuery2, dataExplorerKvDeleteQuery2, pitrDoNamespace2, pitrBookmarkParam2, pitrRestoreBody2, healthSamplingTriggerBody2, dataExplorerDebugDoType2, DEBUG_READ_MAX_LIMIT2, DEBUG_READ_DEFAULT_LIMIT2, DEBUG_DO_HEX_PREFIX2, debugDoEntityId2, debugTableName2, dataExplorerDebugTablesParam2, dataExplorerDebugRowsParam2, dataExplorerDebugRowsQuery2, dataExplorerDebugAnalyticsTable2, debugUuid2, dataExplorerDebugAnalyticsRowsParam2, dataExplorerDebugAnalyticsRowsQuery2, debugHubConvParam2, debugMessageIdQuery2, sandboxEgressPolicy2, SANDBOX_EXEC_MAX_CMD_LENGTH2, SANDBOX_EXEC_MAX_ALLOWLIST2, SANDBOX_EXEC_MAX_TIMEOUT_MS2, adminSandboxExecBody2, whatsappCallbackBody2, authMeResponse2, wsTicketResponse2, sessionCheckResponse2, logoutResponse2, magicCodeSendBody2, magicCodeSendResponse2, magicCodeVerifyBody2, magicCodeVerifyResponse2, browserParams2, browserFoldersQuery2, browserFilesQuery2, stateOperationBody2, conversationListResourcesQuery2, conversationReadResourceQuery2, listPendingSchedulesQuery2, listHubAggregateSchedulesQuery2, reportSourceSchema2, intakeReportSourceSchema2, reportClassificationSchema2, reportStatusSchema2, reportLocaleSchema2, reportMessageAuthorRoleSchema2, reportMessageSchema2, sentryRefStatusSchema2, createReportBody2, editReportBody2, reporterReportSummarySchema2, reporterListResponseSchema2, getReportResponseSchema2, reporterTransitionResponseSchema2, contestReportBody2, reporterListQuery2, listReportsQuery2, GITHUB_ISSUE_URL_REGEX2, githubIssueUrlSchema2, transitionReportBody2, groupReportsBody2, holdReportBody2, clickhouseReadyResponse2, bootstrapQuery2, requestSnapshotChunkMessage2, MAX_NAME_LENGTH3, MAX_VALUE_LENGTH2, MAX_TAGS2, MAX_TAG_LENGTH2, MAX_SCOPE_HUBS2, MAX_SCOPE_TAGS2, vaultSecretScopeSchema2, vaultCreateBody2, vaultUpdateBody2, PERMISSIONS2, MAX_NAME_LENGTH22, MAX_HUBS_PER_GRANT2, MAX_HUB_TAGS_PER_GRANT2, MAX_GRANTS2, permissionEnum2, grantScopeSchema2, grantSchema2, createTokenBody2, tokenOrgIdParam2, tokenGrantScopeSchema2, tokenGrantSchema2, tokenMetadataSchema2, listTokensResponse2, createTokenResponse2, orgTokenSummarySchema2, listOrgTokensResponse2, invitePreviewQuery2, invitePreviewResponse2, discordTier2, discordBillingCycle2, discordMetadata2, discordOAuthStartResponse2, discordOAuthFinalizeBody2, discordOAuthFinalizeResponse2, discordDisconnectResponse2, jsonSchemaSchema2, hubUserIdentity2, stateValueEntry2, getHubUserContextResponse2, updateHubUserBody2, updateHubUserResponse2, unlockHubUserNameResponse2, stateResetParams2, stateResetResponse2, hubAlertsParam2, hubAlertSeverity2, hubAlert2, hubAlertsListResponse2, noticeSeveritySchema2, noticeStatusSchema2, NOTICE_SCOPE_REGEX2, noticeScopeSchema2, noticeLinkSchema2, createNoticeBody2, updateNoticeBody2, listNoticesQuery2, noticeIdParamSchema2, templateLocaleSchema2, TEMPLATE_SLUG_REGEX2, templateSlugSchema2, templateStatusSchema2, templateFileMapSchema2, TEMPLATE_INSTANCE_ID_KEYS, TEMPLATE_OPAQUE_BLOB_KEYS, TEMPLATE_AUTHOR_DATA_KEYS, templateTextSchema2, templateUsesEntrySchema2, templateUsesSchema2, templateYamlLocaleEntry2, templateYamlWayaiBlock2, templateTagsSchema2, templateYamlSchema2, templateHeroSchema2, templatePushLocaleSchema2, templatePushBody2, templateListQuery2, templateSlugParam2, templateDetailQuery2, ADMIN_SKILL_NAME_REGEX2, adminSkillNameParam2;
11856
11908
  var init_contracts = __esm({
11857
11909
  "../../packages/core/dist/contracts/index.js"() {
11858
11910
  "use strict";
@@ -14161,6 +14213,20 @@ var init_contracts = __esm({
14161
14213
  ]);
14162
14214
  reportLocaleSchema2 = external_exports.enum(["en", "pt", "es"]);
14163
14215
  reportMessageAuthorRoleSchema2 = external_exports.enum(["reporter", "triage", "fixer", "system"]);
14216
+ reportMessageSchema2 = external_exports.object({
14217
+ message_id: external_exports.string(),
14218
+ author_role: reportMessageAuthorRoleSchema2,
14219
+ /** The status transition this note accompanied (e.g. 'shipped'); null for a free/system note. */
14220
+ transition: external_exports.string().nullable(),
14221
+ body: external_exports.string(),
14222
+ created_at: timestampSchema2,
14223
+ /**
14224
+ * Visibility: `false` = reporter-facing (the default for every narrative entry); `true` =
14225
+ * triage-internal (e.g. a `hold` rationale) — surfaced to platform admins only and NEVER
14226
+ * returned on the reporter read path. The reporter's `GET /api/reports/:id` filters these out.
14227
+ */
14228
+ internal: external_exports.boolean()
14229
+ });
14164
14230
  sentryRefStatusSchema2 = external_exports.enum(["valid", "not_found", "mismatch", "unverified"]);
14165
14231
  createReportBody2 = external_exports.object({
14166
14232
  title: external_exports.string().min(5).max(256),
@@ -14192,6 +14258,30 @@ var init_contracts = __esm({
14192
14258
  }).strict().refine((b) => Object.keys(b).length > 0, {
14193
14259
  message: "at least one field must be provided"
14194
14260
  });
14261
+ reporterReportSummarySchema2 = external_exports.object({
14262
+ report_id: external_exports.string(),
14263
+ title: external_exports.string(),
14264
+ description: external_exports.string(),
14265
+ classification: reportClassificationSchema2,
14266
+ status: reportStatusSchema2,
14267
+ created_at: timestampSchema2,
14268
+ triaged_at: timestampSchema2.nullable(),
14269
+ resolved_at: timestampSchema2.nullable(),
14270
+ /** How many times the reporter has contested (gates the hard cap). */
14271
+ contest_count: external_exports.number(),
14272
+ /** True once triage issued a non-contestable (final) dismissal. */
14273
+ dismissal_final: external_exports.boolean()
14274
+ });
14275
+ reporterListResponseSchema2 = external_exports.object({
14276
+ data: external_exports.array(reporterReportSummarySchema2)
14277
+ });
14278
+ getReportResponseSchema2 = external_exports.object({
14279
+ report: reporterReportSummarySchema2,
14280
+ messages: external_exports.array(reportMessageSchema2)
14281
+ });
14282
+ reporterTransitionResponseSchema2 = external_exports.object({
14283
+ report: reporterReportSummarySchema2
14284
+ });
14195
14285
  contestReportBody2 = external_exports.object({
14196
14286
  reason: external_exports.string().min(1).max(5e3)
14197
14287
  });
@@ -14762,13 +14852,13 @@ function assertResourcePayloadFitsWithoutPruning(payload, cause) {
14762
14852
  }
14763
14853
  }
14764
14854
  }
14765
- function writeResourceFileTree(resDir, files, root) {
14855
+ function writeResourceFileTree(resDir, files, root, log) {
14766
14856
  if (!ensureRealSubdirNoSymlink(root, resDir, files.length > 0)) {
14767
14857
  console.warn(` Warning: skipping resource dir (not reachable inside the workspace without a symlink)`);
14768
14858
  return;
14769
14859
  }
14770
14860
  if (files.length === 0) {
14771
- if (fs10.existsSync(resDir)) cleanOrphanFiles(resDir, "", /* @__PURE__ */ new Set());
14861
+ if (fs10.existsSync(resDir)) cleanOrphanFiles(resDir, "", /* @__PURE__ */ new Set(), root, log);
14772
14862
  return;
14773
14863
  }
14774
14864
  const writtenPaths = /* @__PURE__ */ new Set();
@@ -14779,34 +14869,33 @@ function writeResourceFileTree(resDir, files, root) {
14779
14869
  continue;
14780
14870
  }
14781
14871
  writtenPaths.add(file.path);
14782
- if (file.content !== void 0) {
14783
- if (!writeFileNoFollow(resDir, filePath, Buffer.from(file.content, "utf-8"))) {
14784
- console.warn(` Warning: skipping ${file.path} (destination escapes the resource folder via a symlink)`);
14785
- writtenPaths.delete(file.path);
14786
- }
14787
- } else if (file.content_base64) {
14788
- if (!writeFileNoFollow(resDir, filePath, Buffer.from(file.content_base64, "base64"))) {
14789
- console.warn(` Warning: skipping ${file.path} (destination escapes the resource folder via a symlink)`);
14790
- writtenPaths.delete(file.path);
14791
- }
14872
+ const buf = file.content !== void 0 ? Buffer.from(file.content, "utf-8") : file.content_base64 ? Buffer.from(file.content_base64, "base64") : void 0;
14873
+ if (buf === void 0) continue;
14874
+ if (fileHasBytes(filePath, buf)) continue;
14875
+ if (writeFileNoFollow(resDir, filePath, buf)) {
14876
+ log?.changed.push(path12.relative(root, filePath));
14877
+ } else {
14878
+ console.warn(` Warning: skipping ${file.path} (destination escapes the resource folder via a symlink)`);
14879
+ writtenPaths.delete(file.path);
14792
14880
  }
14793
14881
  }
14794
- if (fs10.existsSync(resDir)) cleanOrphanFiles(resDir, "", writtenPaths);
14882
+ if (fs10.existsSync(resDir)) cleanOrphanFiles(resDir, "", writtenPaths, root, log);
14795
14883
  }
14796
- function cleanOrphanFiles(dir, prefix, writtenPaths) {
14884
+ function cleanOrphanFiles(dir, prefix, writtenPaths, root, log) {
14797
14885
  const entries = fs10.readdirSync(dir, { withFileTypes: true });
14798
14886
  for (const entry of entries) {
14799
14887
  const relPath = prefix ? `${prefix}/${entry.name}` : entry.name;
14800
14888
  const fullPath = path12.join(dir, entry.name);
14801
14889
  if (entry.isDirectory()) {
14802
- cleanOrphanFiles(fullPath, relPath, writtenPaths);
14890
+ cleanOrphanFiles(fullPath, relPath, writtenPaths, root, log);
14803
14891
  if (fs10.readdirSync(fullPath).length === 0) fs10.rmdirSync(fullPath);
14804
14892
  } else if (!writtenPaths.has(relPath)) {
14805
14893
  fs10.unlinkSync(fullPath);
14894
+ if (log && root) log.removed.push(path12.relative(root, fullPath));
14806
14895
  }
14807
14896
  }
14808
14897
  }
14809
- async function downloadBinaryFiles(resDir, files, root) {
14898
+ async function downloadBinaryFiles(resDir, files, root, log) {
14810
14899
  if (!ensureRealSubdirNoSymlink(root, resDir, true)) {
14811
14900
  console.warn(` Warning: skipping resource downloads (dir not reachable inside the workspace without a symlink)`);
14812
14901
  return 0;
@@ -14820,14 +14909,26 @@ async function downloadBinaryFiles(resDir, files, root) {
14820
14909
  console.warn(` Warning: skipping ${file.path} (path traversal detected)`);
14821
14910
  continue;
14822
14911
  }
14912
+ if (file.hash) {
14913
+ try {
14914
+ const st = fs10.lstatSync(filePath);
14915
+ if (st.isFile() && !st.isSymbolicLink() && computeHash(fs10.readFileSync(filePath)) === file.hash) continue;
14916
+ } catch {
14917
+ }
14918
+ }
14823
14919
  const response = await fetch(file.download_url);
14824
14920
  if (!response.ok) {
14825
14921
  console.warn(` Warning: failed to download ${file.path} (${response.status})`);
14826
14922
  continue;
14827
14923
  }
14828
14924
  const buffer = Buffer.from(await response.arrayBuffer());
14829
- if (writeFileNoFollow(resDir, filePath, buffer)) count++;
14830
- else console.warn(` Warning: skipping ${file.path} (destination escapes the resource folder via a symlink)`);
14925
+ if (fileHasBytes(filePath, buffer)) continue;
14926
+ if (writeFileNoFollow(resDir, filePath, buffer)) {
14927
+ count++;
14928
+ log?.changed.push(path12.relative(root, filePath));
14929
+ } else {
14930
+ console.warn(` Warning: skipping ${file.path} (destination escapes the resource folder via a symlink)`);
14931
+ }
14831
14932
  } catch (err) {
14832
14933
  console.warn(` Warning: failed to download ${file.path} (${err instanceof Error ? err.message : String(err)})`);
14833
14934
  }
@@ -15006,12 +15107,12 @@ function rewriteEvalAttachmentsToLocalPaths(payload) {
15006
15107
  }
15007
15108
  async function downloadEvalAttachments(hubFolder, downloads) {
15008
15109
  const attachDir = path13.resolve(hubFolder, ATTACHMENTS_DIR);
15009
- let written = 0;
15110
+ const result = { written: 0, changed: [], removed: [] };
15010
15111
  if (!ensureRealSubdirNoSymlink(hubFolder, attachDir, downloads.length > 0)) {
15011
15112
  console.warn(` Warning: ${ATTACHMENTS_DIR}/ is not reachable inside the hub folder without a symlink; skipping attachment sync.`);
15012
- return written;
15113
+ return result;
15013
15114
  }
15014
- if (!fs11.existsSync(attachDir)) return written;
15115
+ if (!fs11.existsSync(attachDir)) return result;
15015
15116
  for (const dl of downloads) {
15016
15117
  const abs = path13.resolve(hubFolder, dl.relPath);
15017
15118
  if (abs !== attachDir && !abs.startsWith(attachDir + path13.sep)) continue;
@@ -15029,7 +15130,10 @@ async function downloadEvalAttachments(hubFolder, downloads) {
15029
15130
  console.warn(` Warning: failed to download ${dl.relPath} (HTTP ${res.status})`);
15030
15131
  continue;
15031
15132
  }
15032
- if (writeFileNoFollow(hubFolder, abs, Buffer.from(await res.arrayBuffer()))) written++;
15133
+ if (writeFileNoFollow(hubFolder, abs, Buffer.from(await res.arrayBuffer()))) {
15134
+ result.written++;
15135
+ result.changed.push(dl.relPath);
15136
+ }
15033
15137
  } catch (err) {
15034
15138
  console.warn(` Warning: failed to download ${dl.relPath}: ${err instanceof Error ? err.message : String(err)}`);
15035
15139
  }
@@ -15038,9 +15142,12 @@ async function downloadEvalAttachments(hubFolder, downloads) {
15038
15142
  for (const name of fs11.readdirSync(attachDir)) {
15039
15143
  const abs = path13.join(attachDir, name);
15040
15144
  const st = fs11.lstatSync(abs);
15041
- if ((st.isFile() || st.isSymbolicLink()) && !keep.has(abs)) fs11.rmSync(abs);
15145
+ if ((st.isFile() || st.isSymbolicLink()) && !keep.has(abs)) {
15146
+ fs11.rmSync(abs);
15147
+ result.removed.push(path13.relative(hubFolder, abs));
15148
+ }
15042
15149
  }
15043
- return written;
15150
+ return result;
15044
15151
  }
15045
15152
  var ATTACHMENTS_DIR;
15046
15153
  var init_eval_attachments = __esm({
@@ -15460,6 +15567,15 @@ var init_diff_display = __esm({
15460
15567
  import * as fs13 from "fs";
15461
15568
  import * as path15 from "path";
15462
15569
  import * as yaml5 from "js-yaml";
15570
+ function writeFileIfChanged(hubFolder, absPath, content, log) {
15571
+ const buf = Buffer.from(content, "utf-8");
15572
+ if (fileHasBytes(absPath, buf)) return;
15573
+ if (writeFileNoFollow(hubFolder, absPath, buf)) {
15574
+ log.changed.push(path15.relative(hubFolder, absPath));
15575
+ } else {
15576
+ console.warn(` Warning: skipping ${path15.relative(hubFolder, absPath)} (destination escapes the hub folder via a symlink)`);
15577
+ }
15578
+ }
15463
15579
  function buildEvalYamlObject(evalEntry, slug) {
15464
15580
  const out = {};
15465
15581
  if (evalEntry.id) out.id = evalEntry.id;
@@ -15494,6 +15610,7 @@ function buildEvalYamlObject(evalEntry, slug) {
15494
15610
  return out;
15495
15611
  }
15496
15612
  function writeHubFolder(hubFolder, payload, options = {}) {
15613
+ const log = { changed: [], removed: [] };
15497
15614
  const agentsDir = path15.join(hubFolder, "agents");
15498
15615
  if (!fs13.existsSync(hubFolder)) {
15499
15616
  fs13.mkdirSync(hubFolder, { recursive: true });
@@ -15504,38 +15621,48 @@ function writeHubFolder(hubFolder, payload, options = {}) {
15504
15621
  const yamlPayload = buildYamlPayload(payload);
15505
15622
  const agentFiles = extractAgentFiles(payload);
15506
15623
  const yamlContent = yaml5.dump(yamlPayload, YAML_DUMP_OPTIONS);
15507
- fs13.writeFileSync(path15.join(hubFolder, "hub.yaml"), yamlContent, "utf-8");
15624
+ writeFileIfChanged(hubFolder, path15.join(hubFolder, "hub.yaml"), yamlContent, log);
15508
15625
  if (options.seedAgentContext ?? true) {
15509
- writeIfAbsent(path15.join(hubFolder, "AGENTS.md"), perHubAgentsMd(path15.basename(hubFolder)));
15510
- writeIfAbsent(path15.join(hubFolder, "CLAUDE.md"), CLAUDE_MD_SHIM);
15626
+ for (const seeded of [
15627
+ writeIfAbsent(path15.join(hubFolder, "AGENTS.md"), perHubAgentsMd(path15.basename(hubFolder))),
15628
+ writeIfAbsent(path15.join(hubFolder, "CLAUDE.md"), CLAUDE_MD_SHIM)
15629
+ ]) {
15630
+ if (seeded) log.changed.push(seeded);
15631
+ }
15511
15632
  }
15512
15633
  const oldYamlPath = path15.join(hubFolder, "wayai.yaml");
15513
15634
  if (fs13.existsSync(oldYamlPath)) {
15514
15635
  fs13.unlinkSync(oldYamlPath);
15636
+ log.removed.push(path15.relative(hubFolder, oldYamlPath));
15515
15637
  }
15516
- const yamlSlugs = writeAgentYamlFiles(agentsDir, payload.agents || []);
15638
+ const yamlSlugs = writeAgentYamlFiles(hubFolder, agentsDir, payload.agents || [], log);
15517
15639
  const mdSlugs = /* @__PURE__ */ new Set();
15518
15640
  for (const { slug, content } of agentFiles) {
15519
15641
  mdSlugs.add(slug);
15520
- fs13.writeFileSync(path15.join(agentsDir, `${slug}.md`), content, "utf-8");
15642
+ writeFileIfChanged(hubFolder, path15.join(agentsDir, `${slug}.md`), content, log);
15521
15643
  }
15522
15644
  const existingFiles = fs13.readdirSync(agentsDir);
15523
15645
  for (const file of existingFiles) {
15524
15646
  if (file.endsWith(".yaml")) {
15525
15647
  const slug = file.slice(0, -5);
15526
15648
  if (!yamlSlugs.has(slug)) {
15527
- fs13.unlinkSync(path15.join(agentsDir, file));
15649
+ const orphan = path15.join(agentsDir, file);
15650
+ fs13.unlinkSync(orphan);
15651
+ log.removed.push(path15.relative(hubFolder, orphan));
15528
15652
  }
15529
15653
  } else if (file.endsWith(".md")) {
15530
15654
  const slug = file.slice(0, -3);
15531
15655
  if (!mdSlugs.has(slug)) {
15532
- fs13.unlinkSync(path15.join(agentsDir, file));
15656
+ const orphan = path15.join(agentsDir, file);
15657
+ fs13.unlinkSync(orphan);
15658
+ log.removed.push(path15.relative(hubFolder, orphan));
15533
15659
  }
15534
15660
  }
15535
15661
  }
15536
- writeResourceFiles(hubFolder, payload.resources || []);
15537
- writeEvalYamlFiles(hubFolder, payload.evals || []);
15538
- writeJourneyYamlFiles(hubFolder, payload.journeys || []);
15662
+ writeResourceFiles(hubFolder, payload.resources || [], log);
15663
+ writeEvalYamlFiles(hubFolder, payload.evals || [], log);
15664
+ writeJourneyYamlFiles(hubFolder, payload.journeys || [], log);
15665
+ return log;
15539
15666
  }
15540
15667
  function setPreviewLabelInHubYaml(hubFolder, label) {
15541
15668
  const yamlPath = resolveHubYamlPath(hubFolder);
@@ -15581,7 +15708,7 @@ function buildYamlPayload(payload) {
15581
15708
  }
15582
15709
  return result;
15583
15710
  }
15584
- function writeAgentYamlFiles(agentsDir, agents) {
15711
+ function writeAgentYamlFiles(hubFolder, agentsDir, agents, log) {
15585
15712
  const slugs = /* @__PURE__ */ new Set();
15586
15713
  for (const agent of agents) {
15587
15714
  const slug = slugify(agent.name);
@@ -15589,7 +15716,7 @@ function writeAgentYamlFiles(agentsDir, agents) {
15589
15716
  const entry = { ...agent };
15590
15717
  delete entry.instructions;
15591
15718
  const yamlContent = yaml5.dump(entry, YAML_DUMP_OPTIONS);
15592
- fs13.writeFileSync(path15.join(agentsDir, `${slug}.yaml`), yamlContent, "utf-8");
15719
+ writeFileIfChanged(hubFolder, path15.join(agentsDir, `${slug}.yaml`), yamlContent, log);
15593
15720
  }
15594
15721
  return slugs;
15595
15722
  }
@@ -15605,11 +15732,11 @@ function extractAgentFiles(payload) {
15605
15732
  }
15606
15733
  return files;
15607
15734
  }
15608
- function writeEvalYamlFiles(hubFolder, evals) {
15735
+ function writeEvalYamlFiles(hubFolder, evals, log) {
15609
15736
  const evalsDir = path15.join(hubFolder, "evals");
15610
15737
  if (evals.length === 0) {
15611
15738
  if (fs13.existsSync(evalsDir)) {
15612
- cleanEvalOrphans(evalsDir, /* @__PURE__ */ new Set());
15739
+ cleanEvalOrphans(hubFolder, evalsDir, /* @__PURE__ */ new Set(), log);
15613
15740
  try {
15614
15741
  if (fs13.readdirSync(evalsDir).length === 0) fs13.rmdirSync(evalsDir);
15615
15742
  } catch {
@@ -15637,18 +15764,19 @@ function writeEvalYamlFiles(hubFolder, evals) {
15637
15764
  }
15638
15765
  }
15639
15766
  const yamlContent = yaml5.dump(buildEvalYamlObject(evalEntry, slug), YAML_DUMP_OPTIONS);
15640
- fs13.writeFileSync(targetPath, yamlContent, "utf-8");
15767
+ writeFileIfChanged(hubFolder, targetPath, yamlContent, log);
15641
15768
  writtenRelPaths.add(relPath);
15642
15769
  }
15643
- cleanEvalOrphans(evalsDir, writtenRelPaths);
15770
+ cleanEvalOrphans(hubFolder, evalsDir, writtenRelPaths, log);
15644
15771
  }
15645
- function cleanEvalOrphans(evalsDir, writtenRelPaths) {
15772
+ function cleanEvalOrphans(hubFolder, evalsDir, writtenRelPaths, log) {
15646
15773
  const entries = fs13.readdirSync(evalsDir, { withFileTypes: true });
15647
15774
  for (const entry of entries) {
15648
15775
  const fullPath = path15.join(evalsDir, entry.name);
15649
15776
  if (entry.isFile()) {
15650
15777
  if (entry.name.endsWith(".yaml") && !writtenRelPaths.has(entry.name)) {
15651
15778
  fs13.unlinkSync(fullPath);
15779
+ log.removed.push(path15.relative(hubFolder, fullPath));
15652
15780
  }
15653
15781
  continue;
15654
15782
  }
@@ -15659,7 +15787,9 @@ function cleanEvalOrphans(evalsDir, writtenRelPaths) {
15659
15787
  if (sub.isFile() && sub.name.endsWith(".yaml")) {
15660
15788
  const relPath = `${setName}/${sub.name}`;
15661
15789
  if (!writtenRelPaths.has(relPath)) {
15662
- fs13.unlinkSync(path15.join(fullPath, sub.name));
15790
+ const orphan = path15.join(fullPath, sub.name);
15791
+ fs13.unlinkSync(orphan);
15792
+ log.removed.push(path15.relative(hubFolder, orphan));
15663
15793
  }
15664
15794
  }
15665
15795
  }
@@ -15700,11 +15830,11 @@ function buildJourneyYamlObject(journeyEntry, slug) {
15700
15830
  }
15701
15831
  return out;
15702
15832
  }
15703
- function writeJourneyYamlFiles(hubFolder, journeys) {
15833
+ function writeJourneyYamlFiles(hubFolder, journeys, log) {
15704
15834
  const journeysDir = path15.join(hubFolder, "journeys");
15705
15835
  if (journeys.length === 0) {
15706
15836
  if (fs13.existsSync(journeysDir)) {
15707
- cleanJourneyOrphans(journeysDir, /* @__PURE__ */ new Set());
15837
+ cleanJourneyOrphans(hubFolder, journeysDir, /* @__PURE__ */ new Set(), log);
15708
15838
  try {
15709
15839
  if (fs13.readdirSync(journeysDir).length === 0) fs13.rmdirSync(journeysDir);
15710
15840
  } catch {
@@ -15721,33 +15851,37 @@ function writeJourneyYamlFiles(hubFolder, journeys) {
15721
15851
  const slug = ensureUniqueSlug(slugify(journeyEntry.name), usedSlugs);
15722
15852
  const fileName = `${slug}.yaml`;
15723
15853
  const yamlContent = yaml5.dump(buildJourneyYamlObject(journeyEntry, slug), YAML_DUMP_OPTIONS);
15724
- fs13.writeFileSync(path15.join(journeysDir, fileName), yamlContent, "utf-8");
15854
+ writeFileIfChanged(hubFolder, path15.join(journeysDir, fileName), yamlContent, log);
15725
15855
  writtenFiles.add(fileName);
15726
15856
  }
15727
- cleanJourneyOrphans(journeysDir, writtenFiles);
15857
+ cleanJourneyOrphans(hubFolder, journeysDir, writtenFiles, log);
15728
15858
  }
15729
- function cleanJourneyOrphans(journeysDir, writtenFiles) {
15859
+ function cleanJourneyOrphans(hubFolder, journeysDir, writtenFiles, log) {
15730
15860
  const entries = fs13.readdirSync(journeysDir, { withFileTypes: true });
15731
15861
  for (const entry of entries) {
15732
15862
  if (entry.isFile() && entry.name.endsWith(".yaml") && !writtenFiles.has(entry.name)) {
15733
- fs13.unlinkSync(path15.join(journeysDir, entry.name));
15863
+ const orphan = path15.join(journeysDir, entry.name);
15864
+ fs13.unlinkSync(orphan);
15865
+ log.removed.push(path15.relative(hubFolder, orphan));
15734
15866
  }
15735
15867
  }
15736
15868
  }
15737
- function writeResourceFiles(hubFolder, resources) {
15869
+ function writeResourceFiles(hubFolder, resources, log) {
15738
15870
  const resourcesDir = path15.join(hubFolder, "resources");
15739
15871
  const currentSlugs = /* @__PURE__ */ new Set();
15740
15872
  for (const resource of resources) {
15741
15873
  const resSlug = slugify(resource.name);
15742
15874
  currentSlugs.add(resSlug);
15743
15875
  const resDir = path15.join(resourcesDir, resSlug);
15744
- writeResourceFileTree(resDir, resource.files || [], hubFolder);
15876
+ writeResourceFileTree(resDir, resource.files || [], hubFolder, log);
15745
15877
  }
15746
15878
  if (fs13.existsSync(resourcesDir)) {
15747
15879
  const existingDirs = fs13.readdirSync(resourcesDir, { withFileTypes: true });
15748
15880
  for (const entry of existingDirs) {
15749
15881
  if (entry.isDirectory() && !currentSlugs.has(entry.name)) {
15750
- fs13.rmSync(path15.join(resourcesDir, entry.name), { recursive: true, force: true });
15882
+ const orphanDir = path15.join(resourcesDir, entry.name);
15883
+ fs13.rmSync(orphanDir, { recursive: true, force: true });
15884
+ log.removed.push(`${path15.relative(hubFolder, orphanDir)}/`);
15751
15885
  }
15752
15886
  }
15753
15887
  }
@@ -15761,6 +15895,7 @@ var init_yaml_writer = __esm({
15761
15895
  init_resource_files();
15762
15896
  init_eval_attachments();
15763
15897
  init_workspace_files();
15898
+ init_fs_safety();
15764
15899
  YAML_DUMP_OPTIONS = {
15765
15900
  lineWidth: -1,
15766
15901
  // don't wrap lines
@@ -15783,22 +15918,28 @@ async function materializeHubFolder(hubFolder, payload, options = {}) {
15783
15918
  }
15784
15919
  materialized.add(payload);
15785
15920
  const attachmentDownloads = rewriteEvalAttachmentsToLocalPaths(payload);
15786
- writeHubFolder(hubFolder, payload, options);
15787
- await downloadBinaryResourceFiles(hubFolder, payload);
15788
- const attachmentsWritten = await downloadEvalAttachments(hubFolder, attachmentDownloads);
15789
- return { attachmentsWritten };
15921
+ const writeLog = writeHubFolder(hubFolder, payload, options);
15922
+ const resourceDownloads = await downloadBinaryResourceFiles(hubFolder, payload);
15923
+ const attachments = await downloadEvalAttachments(hubFolder, attachmentDownloads);
15924
+ return {
15925
+ attachmentsWritten: attachments.written,
15926
+ changed: [...writeLog.changed, ...resourceDownloads.changed, ...attachments.changed],
15927
+ removed: [...writeLog.removed, ...attachments.removed]
15928
+ };
15790
15929
  }
15791
15930
  async function downloadBinaryResourceFiles(hubFolder, payload) {
15792
15931
  const resources = payload.resources || [];
15932
+ const log = { changed: [], removed: [] };
15793
15933
  let downloadCount = 0;
15794
15934
  for (const resource of resources) {
15795
15935
  if (!resource.files) continue;
15796
15936
  const resDir = path16.join(hubFolder, "resources", slugify(resource.name));
15797
- downloadCount += await downloadBinaryFiles(resDir, resource.files, hubFolder);
15937
+ downloadCount += await downloadBinaryFiles(resDir, resource.files, hubFolder, log);
15798
15938
  }
15799
15939
  if (downloadCount > 0) {
15800
15940
  console.log(`Downloaded ${downloadCount} binary resource file(s).`);
15801
15941
  }
15942
+ return { changed: log.changed };
15802
15943
  }
15803
15944
  var materialized;
15804
15945
  var init_hub_materializer = __esm({
@@ -15812,207 +15953,13 @@ var init_hub_materializer = __esm({
15812
15953
  }
15813
15954
  });
15814
15955
 
15815
- // src/commands/pull.ts
15816
- var pull_exports = {};
15817
- __export(pull_exports, {
15818
- connectionsEqual: () => connectionsEqual,
15819
- pullCommand: () => pullCommand,
15820
- resolveHubTarget: () => resolveHubTarget,
15821
- writeProductionMirror: () => writeProductionMirror
15822
- });
15823
- import * as fs14 from "fs";
15824
- import * as path17 from "path";
15825
- function parseArgs4(args2) {
15826
- let autoConfirm = false;
15827
- let hubSelector;
15828
- for (let i = 0; i < args2.length; i++) {
15829
- const arg = args2[i];
15830
- if (arg === "--yes" || arg === "-y") {
15831
- autoConfirm = true;
15832
- } else if (arg === "--hub" && args2[i + 1]) {
15833
- hubSelector = args2[++i];
15834
- }
15835
- }
15836
- return { autoConfirm, hubSelector };
15837
- }
15838
- function resolveHubTarget(workspaceDir, selector) {
15839
- const wsLabel = hubsDirLabel(findGitRoot());
15840
- const allHubs = scanWorkspaceHubs(workspaceDir);
15841
- if (selector) {
15842
- const match = allHubs.find(
15843
- (h) => h.hubId === selector || path17.basename(h.hubFolder) === selector
15844
- );
15845
- if (match) return { hubId: match.hubId, hubFolder: match.hubFolder };
15846
- if (UUID_RE2.test(selector)) return { hubId: selector, hubFolder: null };
15847
- console.error(`No hub matching --hub ${selector} found in ${wsLabel}/. Pass a UUID for first-time pulls.`);
15848
- process.exit(1);
15849
- }
15850
- const enclosing = findEnclosingHubFolder(workspaceDir);
15851
- if (enclosing) return { hubId: enclosing.hubId, hubFolder: enclosing.hubFolder };
15852
- const previewHubs = filterPreviewHubs(allHubs);
15853
- if (previewHubs.length === 1) return { hubId: previewHubs[0].hubId, hubFolder: previewHubs[0].hubFolder };
15854
- if (previewHubs.length === 0) {
15855
- console.error(`No hub folders found in ${wsLabel}/. Pass --hub <uuid> to fetch a hub for the first time.`);
15856
- process.exit(1);
15857
- }
15858
- console.error(`Multiple hubs found in ${wsLabel}/. Pass --hub <uuid|folder-name> to choose, or run from inside a hub folder:`);
15859
- for (const h of previewHubs) {
15860
- console.error(` ${path17.basename(h.hubFolder)} (${h.hubId})`);
15861
- }
15862
- process.exit(1);
15863
- }
15864
- async function pullCommand(args2) {
15865
- const { autoConfirm, hubSelector } = parseArgs4(args2);
15866
- const repoConfig = requireRepoConfig();
15867
- const { organization_id: organizationId } = repoConfig;
15868
- const { config, accessToken } = await requireAuth();
15869
- const client = new ApiClient({ apiUrl: config.api_url, accessToken });
15870
- const workspaceDir = resolveWorkspaceDir();
15871
- const gitRoot = findGitRoot();
15872
- if (gitRoot) warnLayoutOnce(gitRoot);
15873
- if (gitRoot) {
15874
- for (const file of ensureWorkspaceFiles(gitRoot)) {
15875
- console.error(`Created ${file}`);
15876
- }
15877
- }
15878
- const { hubId, hubFolder: existingFolder } = resolveHubTarget(workspaceDir, hubSelector);
15879
- console.log("Fetching hub configuration...");
15880
- const payload = await client.pull(hubId, organizationId);
15881
- if (payload.hub_environment === "production") {
15882
- const folder = await writeProductionMirror(workspaceDir, payload);
15883
- console.log(`Production hub mirrored (read-only) \u2192 ${folder}`);
15884
- return;
15885
- }
15886
- assertHubMatchesBinding(hubId);
15887
- let hubFolder = existingFolder;
15888
- let wroteFiles = false;
15889
- if (!hubFolder) {
15890
- hubFolder = resolveHubFolder(
15891
- workspaceDir,
15892
- hubId,
15893
- payload.hub.name,
15894
- payload.hub_environment,
15895
- payload.preview_label,
15896
- payload.branch_name
15897
- );
15898
- fs14.mkdirSync(path17.dirname(hubFolder), { recursive: true });
15899
- console.log("Writing hub configuration...");
15900
- await materializeHubFolder(hubFolder, payload);
15901
- const finalFolder = autoRenameHubFolder(hubFolder, payload.hub.name, payload.hub_environment, payload.hub_id, payload.preview_label, payload.branch_name);
15902
- console.log(`Hub configuration written to ${finalFolder}`);
15903
- wroteFiles = true;
15904
- } else {
15905
- let action = "overwrite";
15906
- try {
15907
- const localPayload = parseHubFolder(hubFolder);
15908
- const diffResult = await client.diff(hubId, prepareResourcePayload(localPayload, payload), "pull", organizationId);
15909
- const connectionsChanged = !connectionsEqual(localPayload.connections, payload.connections);
15910
- if (!diffResult.has_changes && !connectionsChanged) {
15911
- action = "sync_metadata";
15912
- } else {
15913
- console.log("\nChanges to apply locally:");
15914
- if (connectionsChanged) {
15915
- console.log("**Connections:** updated");
15916
- }
15917
- printDiff(diffResult.summary);
15918
- if (!autoConfirm) {
15919
- const ok = await confirm("Apply these changes?");
15920
- if (!ok) {
15921
- console.log("Cancelled.");
15922
- return;
15923
- }
15924
- }
15925
- action = "apply";
15926
- }
15927
- } catch {
15928
- action = "overwrite";
15929
- }
15930
- if (action === "overwrite") console.log("Writing hub configuration...");
15931
- await materializeHubFolder(hubFolder, payload);
15932
- const finalFolder = autoRenameHubFolder(hubFolder, payload.hub.name, payload.hub_environment, payload.hub_id, payload.preview_label, payload.branch_name);
15933
- wroteFiles = true;
15934
- if (action === "sync_metadata") {
15935
- if (finalFolder === hubFolder) {
15936
- console.log("Metadata synced \u2014 no config changes.");
15937
- } else {
15938
- console.log("Metadata synced; folder renamed.");
15939
- }
15940
- } else {
15941
- console.log(`Hub configuration written to ${finalFolder}`);
15942
- }
15943
- }
15944
- if (wroteFiles) autoBindIfUnbound(hubId);
15945
- if (payload.production_hub_id) {
15946
- await mirrorLinkedProduction(client, workspaceDir, payload.production_hub_id, organizationId);
15947
- }
15948
- }
15949
- async function writeProductionMirror(workspaceDir, prodPayload) {
15950
- const folder = resolveHubFolder(workspaceDir, prodPayload.hub_id, prodPayload.hub.name, "production", null, null);
15951
- fs14.mkdirSync(path17.dirname(folder), { recursive: true });
15952
- await materializeHubFolder(folder, prodPayload, { seedAgentContext: false });
15953
- const finalFolder = autoRenameHubFolder(folder, prodPayload.hub.name, "production", prodPayload.hub_id, null, null);
15954
- prependMirrorMarker(finalFolder, prodPayload.hub_id);
15955
- return finalFolder;
15956
- }
15957
- async function mirrorLinkedProduction(client, workspaceDir, productionHubId, organizationId) {
15958
- try {
15959
- const prodPayload = await client.pull(productionHubId, organizationId);
15960
- const folder = await writeProductionMirror(workspaceDir, prodPayload);
15961
- console.log(`Mirrored production hub \u2192 ${folder} (read-only)`);
15962
- } catch (err) {
15963
- console.warn(`Warning: could not mirror production hub (${err instanceof Error ? err.message : String(err)}). Preview pull is unaffected.`);
15964
- }
15965
- }
15966
- function prependMirrorMarker(hubFolder, productionHubId) {
15967
- const hubYaml = path17.join(hubFolder, "hub.yaml");
15968
- try {
15969
- const content = fs14.readFileSync(hubYaml, "utf-8");
15970
- if (content.startsWith(MIRROR_MARKER_PREFIX)) return;
15971
- const marker = `${MIRROR_MARKER_PREFIX} ${productionHubId}. Edits are ignored; push is blocked. Edit the linked preview hub instead.
15972
- `;
15973
- fs14.writeFileSync(hubYaml, marker + content, "utf-8");
15974
- } catch {
15975
- }
15976
- }
15977
- function connectionsEqual(a, b) {
15978
- const listA = a || [];
15979
- const listB = b || [];
15980
- if (listA.length !== listB.length) return false;
15981
- const key = (c) => c.id || `${c.name}|${c.type}|${c.service || ""}`;
15982
- const setA = new Set(listA.map(key));
15983
- const setB = new Set(listB.map(key));
15984
- if (setA.size !== setB.size) return false;
15985
- for (const k of setA) {
15986
- if (!setB.has(k)) return false;
15987
- }
15988
- return true;
15989
- }
15990
- var MIRROR_MARKER_PREFIX;
15991
- var init_pull = __esm({
15992
- "src/commands/pull.ts"() {
15993
- "use strict";
15994
- init_auth();
15995
- init_api_client();
15996
- init_parser();
15997
- init_diff_display();
15998
- init_utils();
15999
- init_resource_files();
16000
- init_hub_materializer();
16001
- init_workspace();
16002
- init_layout();
16003
- init_workspace_files();
16004
- init_repo_config();
16005
- init_hub_binding();
16006
- MIRROR_MARKER_PREFIX = "# Read-only mirror of production hub";
16007
- }
16008
- });
16009
-
16010
15956
  // src/commands/push.ts
16011
15957
  var push_exports = {};
16012
15958
  __export(push_exports, {
16013
15959
  autoRenameAgentFiles: () => autoRenameAgentFiles,
16014
15960
  createAndPushNewHub: () => createAndPushNewHub,
16015
15961
  printErrors: () => printErrors,
15962
+ printLocalFileChanges: () => printLocalFileChanges,
16016
15963
  printSyncResult: () => printSyncResult,
16017
15964
  printWarnings: () => printWarnings,
16018
15965
  pushCommand: () => pushCommand,
@@ -16021,10 +15968,10 @@ __export(push_exports, {
16021
15968
  shouldWarnIgnoredPreviewLabel: () => shouldWarnIgnoredPreviewLabel,
16022
15969
  syncAfterPush: () => syncAfterPush
16023
15970
  });
16024
- import * as fs15 from "fs";
16025
- import * as path18 from "path";
15971
+ import * as fs14 from "fs";
15972
+ import * as path17 from "path";
16026
15973
  import * as yaml6 from "js-yaml";
16027
- function parseArgs5(args2) {
15974
+ function parseArgs4(args2) {
16028
15975
  let autoConfirm = false;
16029
15976
  let hubSelector;
16030
15977
  let label;
@@ -16114,14 +16061,30 @@ function printErrors(errors) {
16114
16061
  console.error(` \x1B[31m! ${error}\x1B[0m`);
16115
16062
  }
16116
16063
  }
16064
+ function printLocalFileChanges(delta) {
16065
+ if (delta.changed.length === 0 && delta.removed.length === 0) {
16066
+ console.log("Local files already in sync.");
16067
+ return;
16068
+ }
16069
+ console.log("Local files updated from server:");
16070
+ const emit = (paths, sigil) => {
16071
+ const sorted = [...paths].sort();
16072
+ for (const p of sorted.slice(0, LOCAL_CHANGE_LIST_CAP)) console.log(` ${sigil} ${p}`);
16073
+ if (sorted.length > LOCAL_CHANGE_LIST_CAP) {
16074
+ console.log(` \u2026and ${sorted.length - LOCAL_CHANGE_LIST_CAP} more ${sigil === "-" ? "removed" : "changed"}`);
16075
+ }
16076
+ };
16077
+ emit(delta.removed, "-");
16078
+ emit(delta.changed, "~");
16079
+ }
16117
16080
  async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId, remoteConfig) {
16118
- const agentsDir = path18.join(hubFolder, "agents");
16081
+ const agentsDir = path17.join(hubFolder, "agents");
16119
16082
  let agentsWithIds = [];
16120
- if (fs15.existsSync(agentsDir)) {
16121
- const yamlFiles = fs15.readdirSync(agentsDir).filter((f) => f.endsWith(".yaml"));
16083
+ if (fs14.existsSync(agentsDir)) {
16084
+ const yamlFiles = fs14.readdirSync(agentsDir).filter((f) => f.endsWith(".yaml"));
16122
16085
  for (const file of yamlFiles) {
16123
16086
  try {
16124
- const content = fs15.readFileSync(path18.join(agentsDir, file), "utf-8");
16087
+ const content = fs14.readFileSync(path17.join(agentsDir, file), "utf-8");
16125
16088
  const agent = yaml6.load(content);
16126
16089
  if (agent?.id && agent.name) {
16127
16090
  agentsWithIds.push({ id: agent.id, name: agent.name });
@@ -16134,7 +16097,7 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId, re
16134
16097
  if (agentsWithIds.length === 0) {
16135
16098
  const yamlPath = resolveHubYamlPath(hubFolder);
16136
16099
  if (!yamlPath) return;
16137
- const yamlContent = fs15.readFileSync(yamlPath, "utf-8");
16100
+ const yamlContent = fs14.readFileSync(yamlPath, "utf-8");
16138
16101
  const config = yaml6.load(yamlContent);
16139
16102
  agentsWithIds = (config.agents || []).filter((a) => !!a.id && !!a.name);
16140
16103
  }
@@ -16166,18 +16129,18 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId, re
16166
16129
  }
16167
16130
  }
16168
16131
  if (renames.length === 0) return;
16169
- if (!fs15.existsSync(agentsDir)) return;
16170
- for (const file of fs15.readdirSync(agentsDir)) {
16132
+ if (!fs14.existsSync(agentsDir)) return;
16133
+ for (const file of fs14.readdirSync(agentsDir)) {
16171
16134
  if (file.startsWith("__rename_temp_") && (file.endsWith(".md") || file.endsWith(".yaml"))) {
16172
16135
  console.warn(` Warning: removing orphaned temp file agents/${file}`);
16173
- fs15.unlinkSync(path18.join(agentsDir, file));
16136
+ fs14.unlinkSync(path17.join(agentsDir, file));
16174
16137
  }
16175
16138
  }
16176
16139
  const renameFileIfExists = (dir, oldName, newName) => {
16177
- const oldPath = path18.join(dir, oldName);
16178
- const newPath = path18.join(dir, newName);
16179
- if (!fs15.existsSync(oldPath)) return false;
16180
- fs15.renameSync(oldPath, newPath);
16140
+ const oldPath = path17.join(dir, oldName);
16141
+ const newPath = path17.join(dir, newName);
16142
+ if (!fs14.existsSync(oldPath)) return false;
16143
+ fs14.renameSync(oldPath, newPath);
16181
16144
  return true;
16182
16145
  };
16183
16146
  const oldSlugs = new Set(renames.map((r) => r.oldSlug));
@@ -16210,9 +16173,9 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId, re
16210
16173
  }
16211
16174
  } else {
16212
16175
  for (const { oldSlug, newSlug } of renames) {
16213
- const hasOldFile = extensions.some((ext) => fs15.existsSync(path18.join(agentsDir, `${oldSlug}${ext}`)));
16176
+ const hasOldFile = extensions.some((ext) => fs14.existsSync(path17.join(agentsDir, `${oldSlug}${ext}`)));
16214
16177
  if (!hasOldFile) continue;
16215
- const hasNewFile = extensions.some((ext) => fs15.existsSync(path18.join(agentsDir, `${newSlug}${ext}`)));
16178
+ const hasNewFile = extensions.some((ext) => fs14.existsSync(path17.join(agentsDir, `${newSlug}${ext}`)));
16216
16179
  if (hasNewFile) {
16217
16180
  console.warn(` Warning: skipping rename agents/${oldSlug}.* \u2192 agents/${newSlug}.* (target already exists)`);
16218
16181
  continue;
@@ -16227,7 +16190,7 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId, re
16227
16190
  if (completedRenames.length === 0) return;
16228
16191
  const mainYamlPath = resolveHubYamlPath(hubFolder);
16229
16192
  if (mainYamlPath) {
16230
- const mainYamlContent = fs15.readFileSync(mainYamlPath, "utf-8");
16193
+ const mainYamlContent = fs14.readFileSync(mainYamlPath, "utf-8");
16231
16194
  const substitutionMap = /* @__PURE__ */ new Map();
16232
16195
  for (const { oldSlug, newSlug } of completedRenames) {
16233
16196
  substitutionMap.set(`agents/${oldSlug}.md`, `agents/${newSlug}.md`);
@@ -16238,16 +16201,16 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId, re
16238
16201
  (_match, prefix, pathMatch) => `${prefix}${substitutionMap.get(pathMatch) ?? pathMatch}`
16239
16202
  );
16240
16203
  if (updatedYaml !== mainYamlContent) {
16241
- fs15.writeFileSync(mainYamlPath, updatedYaml, "utf-8");
16242
- console.log(` Updated instructions paths in ${path18.basename(mainYamlPath)}`);
16204
+ fs14.writeFileSync(mainYamlPath, updatedYaml, "utf-8");
16205
+ console.log(` Updated instructions paths in ${path17.basename(mainYamlPath)}`);
16243
16206
  }
16244
16207
  }
16245
16208
  }
16246
16209
  async function syncAfterPush(client, hubId, hubFolder, organizationId) {
16247
16210
  try {
16248
16211
  const remoteConfig = await client.pull(hubId, organizationId);
16249
- await materializeHubFolder(hubFolder, remoteConfig);
16250
- console.log("Local files synced with server.");
16212
+ const delta = await materializeHubFolder(hubFolder, remoteConfig);
16213
+ printLocalFileChanges(delta);
16251
16214
  const finalFolder = autoRenameHubFolder(hubFolder, remoteConfig.hub.name, remoteConfig.hub_environment, hubId, remoteConfig.preview_label, remoteConfig.branch_name);
16252
16215
  if (finalFolder !== hubFolder) {
16253
16216
  console.log(`Hub folder is now ${finalFolder}`);
@@ -16307,7 +16270,7 @@ async function pushSingleHub(client, hubId, hubFolder, autoConfirm, organization
16307
16270
  function selectExistingHub(workspaceDir, allHubs, selector, wsLabel) {
16308
16271
  if (selector) {
16309
16272
  const match = allHubs.find(
16310
- (h) => h.hubId === selector || path18.basename(h.hubFolder) === selector
16273
+ (h) => h.hubId === selector || path17.basename(h.hubFolder) === selector
16311
16274
  );
16312
16275
  if (!match) {
16313
16276
  console.error(`No hub matching --hub ${selector} found in ${wsLabel}/.`);
@@ -16350,7 +16313,7 @@ New hub: "${newHub.hubName}" (${hubType})`);
16350
16313
  process.exit(1);
16351
16314
  }
16352
16315
  console.log(`Hub created: ${createdHub.hub_name} (${hubId})`);
16353
- const content = fs15.readFileSync(hubYamlPath, "utf-8");
16316
+ const content = fs14.readFileSync(hubYamlPath, "utf-8");
16354
16317
  const hasVersion = content.match(/^version:\s/m);
16355
16318
  let updated;
16356
16319
  if (hasVersion) {
@@ -16366,7 +16329,7 @@ hub_id: "${hubId}"
16366
16329
  hub_environment: preview
16367
16330
  ${content}`;
16368
16331
  }
16369
- fs15.writeFileSync(hubYamlPath, updated, "utf-8");
16332
+ fs14.writeFileSync(hubYamlPath, updated, "utf-8");
16370
16333
  autoBindIfUnbound(hubId);
16371
16334
  await pushSingleHub(client, hubId, newHub.hubFolder, opts.autoConfirm, opts.organizationId, { skipAgentRename: true });
16372
16335
  }
@@ -16375,7 +16338,7 @@ function reportUnresolvedPushTarget(reason, existingHubs, newHubs, selector, wsL
16375
16338
  if (existingHubs.length > 0) {
16376
16339
  console.error(`No pushable hub found in ${wsLabel}/ \u2014 only read-only production mirror folder(s). Edit the linked preview hub, pull one, or create a new hub with \`wayai create\`:`);
16377
16340
  for (const h of existingHubs) {
16378
- console.error(` ${path18.basename(h.hubFolder)} (${h.hubId}, production mirror)`);
16341
+ console.error(` ${path17.basename(h.hubFolder)} (${h.hubId}, production mirror)`);
16379
16342
  }
16380
16343
  } else {
16381
16344
  console.error(`No hub folders found. Create hub files in ${wsLabel}/<hub>/hub.yaml with \`hub: { name: ... }\` and run \`wayai push\` (or \`wayai create\`).`);
@@ -16388,15 +16351,15 @@ function reportUnresolvedPushTarget(reason, existingHubs, newHubs, selector, wsL
16388
16351
  console.error(`Multiple hub folders found in ${wsLabel}/. Pass --hub <uuid|folder-name> to choose, or run from inside a hub folder:`);
16389
16352
  }
16390
16353
  for (const h of existingHubs) {
16391
- console.error(` ${path18.basename(h.hubFolder)} (${h.hubId})`);
16354
+ console.error(` ${path17.basename(h.hubFolder)} (${h.hubId})`);
16392
16355
  }
16393
16356
  for (const h of newHubs) {
16394
- console.error(` ${path18.basename(h.hubFolder)} (new \u2014 "${h.hubName}")`);
16357
+ console.error(` ${path17.basename(h.hubFolder)} (new \u2014 "${h.hubName}")`);
16395
16358
  }
16396
16359
  process.exit(1);
16397
16360
  }
16398
16361
  async function pushCommand(args2) {
16399
- const { autoConfirm, hubSelector, label } = parseArgs5(args2);
16362
+ const { autoConfirm, hubSelector, label } = parseArgs4(args2);
16400
16363
  const repoConfig = requireRepoConfig();
16401
16364
  const { organization_id: organizationId } = repoConfig;
16402
16365
  const { config, accessToken } = await requireAuth();
@@ -16410,7 +16373,7 @@ async function pushCommand(args2) {
16410
16373
  console.error(`Created ${file}`);
16411
16374
  }
16412
16375
  }
16413
- if (!fs15.existsSync(workspaceDir)) {
16376
+ if (!fs14.existsSync(workspaceDir)) {
16414
16377
  console.error(`No ${wsLabel}/ directory found. Run \`wayai pull\` first or create hub files in ${wsLabel}/<hub>/hub.yaml.`);
16415
16378
  process.exit(1);
16416
16379
  }
@@ -16429,14 +16392,15 @@ async function pushCommand(args2) {
16429
16392
  if (label) {
16430
16393
  console.warn("Note: --label is only used when creating a new hub. To change an existing hub's label, use `wayai relabel`.");
16431
16394
  }
16432
- console.log(`Target hub: ${path18.basename(existing.hubFolder)} (${existing.hubId})`);
16433
- assertHubMatchesBinding(existing.hubId, path18.basename(existing.hubFolder));
16395
+ console.log(`Target hub: ${path17.basename(existing.hubFolder)} (${existing.hubId})`);
16396
+ assertHubMatchesBinding(existing.hubId, path17.basename(existing.hubFolder));
16434
16397
  await pushSingleHub(client, existing.hubId, existing.hubFolder, autoConfirm, organizationId);
16435
16398
  return;
16436
16399
  }
16437
16400
  assertNoBindingBlocksHubCreation(resolution.target.hub.hubName);
16438
16401
  await createAndPushNewHub(client, resolution.target.hub, { autoConfirm, label, organizationId });
16439
16402
  }
16403
+ var LOCAL_CHANGE_LIST_CAP;
16440
16404
  var init_push = __esm({
16441
16405
  "src/commands/push.ts"() {
16442
16406
  "use strict";
@@ -16452,6 +16416,204 @@ var init_push = __esm({
16452
16416
  init_workspace_files();
16453
16417
  init_repo_config();
16454
16418
  init_hub_binding();
16419
+ LOCAL_CHANGE_LIST_CAP = 20;
16420
+ }
16421
+ });
16422
+
16423
+ // src/commands/pull.ts
16424
+ var pull_exports = {};
16425
+ __export(pull_exports, {
16426
+ connectionsEqual: () => connectionsEqual,
16427
+ pullCommand: () => pullCommand,
16428
+ resolveHubTarget: () => resolveHubTarget,
16429
+ writeProductionMirror: () => writeProductionMirror
16430
+ });
16431
+ import * as fs15 from "fs";
16432
+ import * as path18 from "path";
16433
+ function parseArgs5(args2) {
16434
+ let autoConfirm = false;
16435
+ let hubSelector;
16436
+ for (let i = 0; i < args2.length; i++) {
16437
+ const arg = args2[i];
16438
+ if (arg === "--yes" || arg === "-y") {
16439
+ autoConfirm = true;
16440
+ } else if (arg === "--hub" && args2[i + 1]) {
16441
+ hubSelector = args2[++i];
16442
+ }
16443
+ }
16444
+ return { autoConfirm, hubSelector };
16445
+ }
16446
+ function resolveHubTarget(workspaceDir, selector) {
16447
+ const wsLabel = hubsDirLabel(findGitRoot());
16448
+ const allHubs = scanWorkspaceHubs(workspaceDir);
16449
+ if (selector) {
16450
+ const match = allHubs.find(
16451
+ (h) => h.hubId === selector || path18.basename(h.hubFolder) === selector
16452
+ );
16453
+ if (match) return { hubId: match.hubId, hubFolder: match.hubFolder };
16454
+ if (UUID_RE2.test(selector)) return { hubId: selector, hubFolder: null };
16455
+ console.error(`No hub matching --hub ${selector} found in ${wsLabel}/. Pass a UUID for first-time pulls.`);
16456
+ process.exit(1);
16457
+ }
16458
+ const enclosing = findEnclosingHubFolder(workspaceDir);
16459
+ if (enclosing) return { hubId: enclosing.hubId, hubFolder: enclosing.hubFolder };
16460
+ const previewHubs = filterPreviewHubs(allHubs);
16461
+ if (previewHubs.length === 1) return { hubId: previewHubs[0].hubId, hubFolder: previewHubs[0].hubFolder };
16462
+ if (previewHubs.length === 0) {
16463
+ console.error(`No hub folders found in ${wsLabel}/. Pass --hub <uuid> to fetch a hub for the first time.`);
16464
+ process.exit(1);
16465
+ }
16466
+ console.error(`Multiple hubs found in ${wsLabel}/. Pass --hub <uuid|folder-name> to choose, or run from inside a hub folder:`);
16467
+ for (const h of previewHubs) {
16468
+ console.error(` ${path18.basename(h.hubFolder)} (${h.hubId})`);
16469
+ }
16470
+ process.exit(1);
16471
+ }
16472
+ async function pullCommand(args2) {
16473
+ const { autoConfirm, hubSelector } = parseArgs5(args2);
16474
+ const repoConfig = requireRepoConfig();
16475
+ const { organization_id: organizationId } = repoConfig;
16476
+ const { config, accessToken } = await requireAuth();
16477
+ const client = new ApiClient({ apiUrl: config.api_url, accessToken });
16478
+ const workspaceDir = resolveWorkspaceDir();
16479
+ const gitRoot = findGitRoot();
16480
+ if (gitRoot) warnLayoutOnce(gitRoot);
16481
+ if (gitRoot) {
16482
+ for (const file of ensureWorkspaceFiles(gitRoot)) {
16483
+ console.error(`Created ${file}`);
16484
+ }
16485
+ }
16486
+ const { hubId, hubFolder: existingFolder } = resolveHubTarget(workspaceDir, hubSelector);
16487
+ console.log("Fetching hub configuration...");
16488
+ const payload = await client.pull(hubId, organizationId);
16489
+ if (payload.hub_environment === "production") {
16490
+ const folder = await writeProductionMirror(workspaceDir, payload);
16491
+ console.log(`Production hub mirrored (read-only) \u2192 ${folder}`);
16492
+ return;
16493
+ }
16494
+ assertHubMatchesBinding(hubId);
16495
+ let hubFolder = existingFolder;
16496
+ let wroteFiles = false;
16497
+ if (!hubFolder) {
16498
+ hubFolder = resolveHubFolder(
16499
+ workspaceDir,
16500
+ hubId,
16501
+ payload.hub.name,
16502
+ payload.hub_environment,
16503
+ payload.preview_label,
16504
+ payload.branch_name
16505
+ );
16506
+ fs15.mkdirSync(path18.dirname(hubFolder), { recursive: true });
16507
+ console.log("Writing hub configuration...");
16508
+ await materializeHubFolder(hubFolder, payload);
16509
+ const finalFolder = autoRenameHubFolder(hubFolder, payload.hub.name, payload.hub_environment, payload.hub_id, payload.preview_label, payload.branch_name);
16510
+ console.log(`Hub configuration written to ${finalFolder}`);
16511
+ wroteFiles = true;
16512
+ } else {
16513
+ let action = "overwrite";
16514
+ try {
16515
+ const localPayload = parseHubFolder(hubFolder);
16516
+ const diffResult = await client.diff(hubId, prepareResourcePayload(localPayload, payload), "pull", organizationId);
16517
+ const connectionsChanged = !connectionsEqual(localPayload.connections, payload.connections);
16518
+ if (!diffResult.has_changes && !connectionsChanged) {
16519
+ action = "sync_metadata";
16520
+ } else {
16521
+ console.log("\nChanges to apply locally:");
16522
+ if (connectionsChanged) {
16523
+ console.log("**Connections:** updated");
16524
+ }
16525
+ printDiff(diffResult.summary);
16526
+ if (!autoConfirm) {
16527
+ const ok = await confirm("Apply these changes?");
16528
+ if (!ok) {
16529
+ console.log("Cancelled.");
16530
+ return;
16531
+ }
16532
+ }
16533
+ action = "apply";
16534
+ }
16535
+ } catch {
16536
+ action = "overwrite";
16537
+ }
16538
+ if (action === "overwrite") console.log("Writing hub configuration...");
16539
+ const delta = await materializeHubFolder(hubFolder, payload);
16540
+ const finalFolder = autoRenameHubFolder(hubFolder, payload.hub.name, payload.hub_environment, payload.hub_id, payload.preview_label, payload.branch_name);
16541
+ wroteFiles = true;
16542
+ if (action === "sync_metadata") {
16543
+ if (finalFolder === hubFolder) {
16544
+ printLocalFileChanges(delta);
16545
+ } else {
16546
+ console.log("Metadata synced; folder renamed.");
16547
+ }
16548
+ } else {
16549
+ console.log(`Hub configuration written to ${finalFolder}`);
16550
+ printLocalFileChanges(delta);
16551
+ }
16552
+ }
16553
+ if (wroteFiles) autoBindIfUnbound(hubId);
16554
+ if (payload.production_hub_id) {
16555
+ await mirrorLinkedProduction(client, workspaceDir, payload.production_hub_id, organizationId);
16556
+ }
16557
+ }
16558
+ async function writeProductionMirror(workspaceDir, prodPayload) {
16559
+ const folder = resolveHubFolder(workspaceDir, prodPayload.hub_id, prodPayload.hub.name, "production", null, null);
16560
+ fs15.mkdirSync(path18.dirname(folder), { recursive: true });
16561
+ await materializeHubFolder(folder, prodPayload, { seedAgentContext: false });
16562
+ const finalFolder = autoRenameHubFolder(folder, prodPayload.hub.name, "production", prodPayload.hub_id, null, null);
16563
+ prependMirrorMarker(finalFolder, prodPayload.hub_id);
16564
+ return finalFolder;
16565
+ }
16566
+ async function mirrorLinkedProduction(client, workspaceDir, productionHubId, organizationId) {
16567
+ try {
16568
+ const prodPayload = await client.pull(productionHubId, organizationId);
16569
+ const folder = await writeProductionMirror(workspaceDir, prodPayload);
16570
+ console.log(`Mirrored production hub \u2192 ${folder} (read-only)`);
16571
+ } catch (err) {
16572
+ console.warn(`Warning: could not mirror production hub (${err instanceof Error ? err.message : String(err)}). Preview pull is unaffected.`);
16573
+ }
16574
+ }
16575
+ function prependMirrorMarker(hubFolder, productionHubId) {
16576
+ const hubYaml = path18.join(hubFolder, "hub.yaml");
16577
+ try {
16578
+ const content = fs15.readFileSync(hubYaml, "utf-8");
16579
+ if (content.startsWith(MIRROR_MARKER_PREFIX)) return;
16580
+ const marker = `${MIRROR_MARKER_PREFIX} ${productionHubId}. Edits are ignored; push is blocked. Edit the linked preview hub instead.
16581
+ `;
16582
+ fs15.writeFileSync(hubYaml, marker + content, "utf-8");
16583
+ } catch {
16584
+ }
16585
+ }
16586
+ function connectionsEqual(a, b) {
16587
+ const listA = a || [];
16588
+ const listB = b || [];
16589
+ if (listA.length !== listB.length) return false;
16590
+ const key = (c) => c.id || `${c.name}|${c.type}|${c.service || ""}`;
16591
+ const setA = new Set(listA.map(key));
16592
+ const setB = new Set(listB.map(key));
16593
+ if (setA.size !== setB.size) return false;
16594
+ for (const k of setA) {
16595
+ if (!setB.has(k)) return false;
16596
+ }
16597
+ return true;
16598
+ }
16599
+ var MIRROR_MARKER_PREFIX;
16600
+ var init_pull = __esm({
16601
+ "src/commands/pull.ts"() {
16602
+ "use strict";
16603
+ init_auth();
16604
+ init_api_client();
16605
+ init_parser();
16606
+ init_diff_display();
16607
+ init_utils();
16608
+ init_resource_files();
16609
+ init_hub_materializer();
16610
+ init_push();
16611
+ init_workspace();
16612
+ init_layout();
16613
+ init_workspace_files();
16614
+ init_repo_config();
16615
+ init_hub_binding();
16616
+ MIRROR_MARKER_PREFIX = "# Read-only mirror of production hub";
16455
16617
  }
16456
16618
  });
16457
16619
 
@@ -16669,8 +16831,9 @@ async function replicateCommand(args2) {
16669
16831
  payload.preview_label,
16670
16832
  payload.branch_name
16671
16833
  );
16834
+ const folderPreExisted = fs17.existsSync(hubFolder);
16672
16835
  fs17.mkdirSync(path20.dirname(hubFolder), { recursive: true });
16673
- await materializeHubFolder(hubFolder, payload);
16836
+ const delta = await materializeHubFolder(hubFolder, payload);
16674
16837
  hubFolder = autoRenameHubFolder(
16675
16838
  hubFolder,
16676
16839
  payload.hub.name,
@@ -16680,6 +16843,7 @@ async function replicateCommand(args2) {
16680
16843
  payload.branch_name
16681
16844
  );
16682
16845
  autoBindIfUnbound(previewHubId);
16846
+ if (folderPreExisted) printLocalFileChanges(delta);
16683
16847
  console.log(`Preview written to ${path20.basename(hubFolder)}`);
16684
16848
  console.log(` Switch to it with: wayai use ${path20.basename(hubFolder)}`);
16685
16849
  }
@@ -16690,6 +16854,7 @@ var init_replicate = __esm({
16690
16854
  init_api_client();
16691
16855
  init_hub_materializer();
16692
16856
  init_pull();
16857
+ init_push();
16693
16858
  init_workspace();
16694
16859
  init_layout();
16695
16860
  init_repo_config();
@@ -21891,7 +22056,7 @@ async function runReportList(flagArgs) {
21891
22056
  }
21892
22057
  console.log(`Reports: ${result.data.length}/${result.total}`);
21893
22058
  for (const r of result.data) {
21894
- const age = Math.floor((Date.now() - r.created_at) / 1e3 / 60);
22059
+ const age = Math.floor((Date.now() - Date.parse(r.created_at)) / 1e3 / 60);
21895
22060
  const meta = [
21896
22061
  r.source,
21897
22062
  r.status,
@@ -22312,6 +22477,21 @@ var init_admin = __esm({
22312
22477
  }
22313
22478
  });
22314
22479
 
22480
+ // src/lib/terminal-output.ts
22481
+ import { stripVTControlCharacters } from "util";
22482
+ function sanitizeTerminalText(value) {
22483
+ const normalizedNewlines = value.replace(/\r\n?/g, "\n");
22484
+ return stripVTControlCharacters(normalizedNewlines).replace(
22485
+ /[\u0000-\u0009\u000b-\u001f\u007f-\u009f]/g,
22486
+ ""
22487
+ );
22488
+ }
22489
+ var init_terminal_output = __esm({
22490
+ "src/lib/terminal-output.ts"() {
22491
+ "use strict";
22492
+ }
22493
+ });
22494
+
22315
22495
  // src/lib/version-status.ts
22316
22496
  function componentStatus(current, latest) {
22317
22497
  return { current, latest, behind: Boolean(current && latest && isNewerVersion(latest, current)) };
@@ -22624,7 +22804,8 @@ async function reportListCommand(args2) {
22624
22804
  return;
22625
22805
  }
22626
22806
  for (const r of result.data) {
22627
- console.log(`${r.report_id} ${r.status.padEnd(10)} ${r.classification}`);
22807
+ const title = sanitizeTerminalText(r.title).replace(/\s+/g, " ").trim();
22808
+ console.log(`${r.report_id} ${r.status.padEnd(10)} ${r.classification} ${title}`);
22628
22809
  }
22629
22810
  } catch (err) {
22630
22811
  reportActionError(err);
@@ -22646,7 +22827,11 @@ async function reportGetCommand(args2) {
22646
22827
  return;
22647
22828
  }
22648
22829
  const { report, messages } = result;
22830
+ const title = sanitizeTerminalText(report.title);
22831
+ const description = sanitizeTerminalText(report.description);
22649
22832
  console.log(`Report ${report.report_id}`);
22833
+ console.log(` title: ${title}`);
22834
+ console.log(` description: ${description.replace(/\n/g, "\n ")}`);
22650
22835
  console.log(` status: ${report.status}`);
22651
22836
  console.log(` classification: ${report.classification}`);
22652
22837
  if (report.contest_count > 0) console.log(` contests: ${report.contest_count}`);
@@ -22654,7 +22839,7 @@ async function reportGetCommand(args2) {
22654
22839
  if (messages.length > 0) {
22655
22840
  console.log("\n Thread:");
22656
22841
  for (const m of messages) {
22657
- console.log(` [${m.author_role}] ${m.body}`);
22842
+ console.log(` [${m.author_role}] ${sanitizeTerminalText(m.body)}`);
22658
22843
  }
22659
22844
  }
22660
22845
  if (report.status === "shipped") {
@@ -22723,6 +22908,7 @@ var init_report = __esm({
22723
22908
  "use strict";
22724
22909
  init_auth();
22725
22910
  init_api_client();
22911
+ init_terminal_output();
22726
22912
  init_report_edit_args();
22727
22913
  init_report_create();
22728
22914
  }
@@ -22768,7 +22954,7 @@ var init_update = __esm({
22768
22954
 
22769
22955
  // src/index.ts
22770
22956
  init_sentry();
22771
- import { readFileSync as readFileSync20 } from "fs";
22957
+ import { readFileSync as readFileSync21 } from "fs";
22772
22958
  import { fileURLToPath as fileURLToPath2 } from "url";
22773
22959
  import { dirname as dirname9, join as join28 } from "path";
22774
22960
 
@@ -22950,7 +23136,7 @@ Run \`wayai admin skill install\` to update.`);
22950
23136
 
22951
23137
  // src/index.ts
22952
23138
  var __dirname = dirname9(fileURLToPath2(import.meta.url));
22953
- var pkg = JSON.parse(readFileSync20(join28(__dirname, "..", "package.json"), "utf-8"));
23139
+ var pkg = JSON.parse(readFileSync21(join28(__dirname, "..", "package.json"), "utf-8"));
22954
23140
  var [, , command, ...args] = process.argv;
22955
23141
  var isBackgroundRefresh = command === REFRESH_COMMAND;
22956
23142
  if (!isBackgroundRefresh) initSentry(command, pkg.version);