@wayai/cli 0.3.75 → 0.3.77

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
@@ -165,11 +165,11 @@ function captureException2(error, context) {
165
165
  Sentry.captureException(error);
166
166
  });
167
167
  }
168
- function addApiBreadcrumb(method, path24) {
168
+ function addApiBreadcrumb(method, path25) {
169
169
  if (!initialized) return;
170
170
  Sentry.addBreadcrumb({
171
171
  category: "http",
172
- message: `${method} ${path24}`,
172
+ message: `${method} ${path25}`,
173
173
  level: "info"
174
174
  });
175
175
  }
@@ -231,9 +231,9 @@ var init_api_client = __esm({
231
231
  ApiError = class extends Error {
232
232
  status;
233
233
  body;
234
- constructor(method, path24, status, body) {
234
+ constructor(method, path25, status, body) {
235
235
  const safeBody = redactSecrets(body);
236
- super(`API request failed: ${method} ${path24} (${status}): ${safeBody}`);
236
+ super(`API request failed: ${method} ${path25} (${status}): ${safeBody}`);
237
237
  this.name = "ApiError";
238
238
  this.status = status;
239
239
  this.body = safeBody;
@@ -325,8 +325,8 @@ var init_api_client = __esm({
325
325
  ...organizationId && { organization_id: organizationId }
326
326
  });
327
327
  }
328
- async lookup(path24, opts) {
329
- const params = new URLSearchParams({ path: path24 });
328
+ async lookup(path25, opts) {
329
+ const params = new URLSearchParams({ path: path25 });
330
330
  if (opts?.organizationId) params.set("organization_id", opts.organizationId);
331
331
  return this.request("GET", `/api/ci/lookup?${params.toString()}`);
332
332
  }
@@ -504,6 +504,18 @@ var init_api_client = __esm({
504
504
  const qs = new URLSearchParams({ organization_id: organizationId });
505
505
  return this.request("GET", `/api/setup/organization-credentials?${qs.toString()}`);
506
506
  }
507
+ async listConnections(hubId) {
508
+ const qs = new URLSearchParams({ hub_id: hubId });
509
+ return this.request("GET", `/api/setup/connections?${qs.toString()}`);
510
+ }
511
+ /** Set a credential on a PREVIEW connection (direct secret or org-credential link). */
512
+ async setPreviewConnectionCredential(connectionId, body) {
513
+ return this.request("PATCH", `/api/setup/connections/${connectionId}`, body);
514
+ }
515
+ /** Set a credential on a PRODUCTION connection (the sanctioned carve-out). */
516
+ async setProductionConnectionCredential(connectionId, body) {
517
+ return this.request("PATCH", `/api/setup/connections/${connectionId}/production-credential`, body);
518
+ }
507
519
  async updateOrgCredential(credentialId, organizationId, body) {
508
520
  const qs = new URLSearchParams({ organization_id: organizationId });
509
521
  return this.request("PUT", `/api/setup/organization-credentials/${credentialId}?${qs.toString()}`, body);
@@ -531,6 +543,30 @@ var init_api_client = __esm({
531
543
  preview_label: previewLabel ?? null
532
544
  });
533
545
  }
546
+ /**
547
+ * Preview → production diff — the source of truth for what `wayai publish`
548
+ * will do. `data.is_first_publish` distinguishes a first publish (no linked
549
+ * production hub yet, all entities listed as added) from a subsequent sync.
550
+ * Requires only `hub:read`, so it also drives the pre-confirm preview.
551
+ */
552
+ async getHubDiff(hubId) {
553
+ return this.request("GET", `/api/setup/hubs/${hubId}/diff`);
554
+ }
555
+ /**
556
+ * First publish: clone the preview hub into a NEW production hub. Errors if the
557
+ * preview is already linked to production (use `syncHub` instead). Returns the
558
+ * new production hub id (POST /api/setup/hubs/:id/publish — HTTP 201).
559
+ */
560
+ async publishHub(hubId) {
561
+ return this.request("POST", `/api/setup/hubs/${hubId}/publish`);
562
+ }
563
+ /**
564
+ * Sync a preview hub's changes into its linked production hub
565
+ * (POST /api/setup/hubs/:id/sync). No-op-safe when already in sync.
566
+ */
567
+ async syncHub(hubId) {
568
+ return this.request("POST", `/api/setup/hubs/${hubId}/sync`);
569
+ }
534
570
  /**
535
571
  * Set or clear a preview hub's label (PATCH /api/setup/hubs/:id). Pass null to
536
572
  * clear. The backend trims and normalizes empty → null (max 60 chars).
@@ -703,9 +739,9 @@ var init_api_client = __esm({
703
739
  `/api/admin/data-explorer/debug/observability/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}${qs}`
704
740
  );
705
741
  }
706
- async request(method, path24, body) {
707
- addApiBreadcrumb(method, path24);
708
- const url = `${this.apiUrl}${path24}`;
742
+ async request(method, path25, body) {
743
+ addApiBreadcrumb(method, path25);
744
+ const url = `${this.apiUrl}${path25}`;
709
745
  let refreshedOn401 = false;
710
746
  for (let retry = 0; ; retry++) {
711
747
  let response = await this.send(url, method, body);
@@ -729,7 +765,7 @@ var init_api_client = __esm({
729
765
  await delay(RETRYABLE_BACKOFF_MS[retry]);
730
766
  continue;
731
767
  }
732
- throw new ApiError(method, path24, response.status, errorBody);
768
+ throw new ApiError(method, path25, response.status, errorBody);
733
769
  }
734
770
  }
735
771
  /** Issue a single authenticated request with the client's current token. */
@@ -1164,8 +1200,8 @@ var init_parseUtil = __esm({
1164
1200
  init_errors();
1165
1201
  init_en();
1166
1202
  makeIssue = (params) => {
1167
- const { data, path: path24, errorMaps, issueData } = params;
1168
- const fullPath = [...path24, ...issueData.path || []];
1203
+ const { data, path: path25, errorMaps, issueData } = params;
1204
+ const fullPath = [...path25, ...issueData.path || []];
1169
1205
  const fullIssue = {
1170
1206
  ...issueData,
1171
1207
  path: fullPath
@@ -1476,11 +1512,11 @@ var init_types = __esm({
1476
1512
  init_parseUtil();
1477
1513
  init_util();
1478
1514
  ParseInputLazyPath = class {
1479
- constructor(parent, value, path24, key) {
1515
+ constructor(parent, value, path25, key) {
1480
1516
  this._cachedPath = [];
1481
1517
  this.parent = parent;
1482
1518
  this.data = value;
1483
- this._path = path24;
1519
+ this._path = path25;
1484
1520
  this._key = key;
1485
1521
  }
1486
1522
  get path() {
@@ -4934,12 +4970,12 @@ function typeMatches(typeField, allowed) {
4934
4970
  if (Array.isArray(typeField)) return typeField.every((t) => typeof t === "string" && allowed.has(t));
4935
4971
  return false;
4936
4972
  }
4937
- function validateSchema(schema, path24, errors, opts = {}) {
4973
+ function validateSchema(schema, path25, errors, opts = {}) {
4938
4974
  if (typeof schema === "boolean") return;
4939
4975
  const depth = opts.depth ?? 0;
4940
4976
  if (depth > MAX_SCHEMA_DEPTH) {
4941
4977
  errors.push({
4942
- path: path24 || "<root>",
4978
+ path: path25 || "<root>",
4943
4979
  message: `schema nesting exceeds ${MAX_SCHEMA_DEPTH} levels`,
4944
4980
  suggestion: "Flatten the schema; LLM providers reject deeply nested tool input_schemas."
4945
4981
  });
@@ -4947,7 +4983,7 @@ function validateSchema(schema, path24, errors, opts = {}) {
4947
4983
  }
4948
4984
  if (!isRecord(schema)) {
4949
4985
  errors.push({
4950
- path: path24,
4986
+ path: path25,
4951
4987
  message: `expected object, got ${schema === null ? "null" : typeof schema}`
4952
4988
  });
4953
4989
  return;
@@ -4955,14 +4991,14 @@ function validateSchema(schema, path24, errors, opts = {}) {
4955
4991
  if (opts.isRoot) {
4956
4992
  if ("type" in schema && schema.type !== "object") {
4957
4993
  errors.push({
4958
- path: path24 ? `${path24}.type` : "type",
4994
+ path: path25 ? `${path25}.type` : "type",
4959
4995
  message: `root type must be 'object', got ${JSON.stringify(schema.type)}`,
4960
4996
  suggestion: "Tool parameters at the root must be an object: `{ type: 'object', properties: { ... } }`."
4961
4997
  });
4962
4998
  }
4963
4999
  } else if ("type" in schema && !typeMatches(schema.type, ALLOWED_TYPES)) {
4964
5000
  errors.push({
4965
- path: `${path24}.type`,
5001
+ path: `${path25}.type`,
4966
5002
  message: `type must be one of ${[...ALLOWED_TYPES].join("/")} or an array of those, got ${JSON.stringify(schema.type)}`
4967
5003
  });
4968
5004
  }
@@ -4971,25 +5007,25 @@ function validateSchema(schema, path24, errors, opts = {}) {
4971
5007
  if (typeof e === "string") {
4972
5008
  const isPlaceholder = PLACEHOLDER_TOKENS.includes(e);
4973
5009
  errors.push({
4974
- path: `${path24}.enum`,
5010
+ path: `${path25}.enum`,
4975
5011
  message: `enum must be a non-empty array of primitives, got string ${JSON.stringify(e)}`,
4976
5012
  suggestion: isPlaceholder ? "Set `operation: 'update_kanban_status'` on the tool and ensure at least one hub.kanban_status has `allowsAgentUpdate: true` so the platform can render the placeholder into a valid array." : 'Wrap the value in an array: `enum: ["value"]`.'
4977
5013
  });
4978
5014
  } else if (!Array.isArray(e)) {
4979
5015
  errors.push({
4980
- path: `${path24}.enum`,
5016
+ path: `${path25}.enum`,
4981
5017
  message: `enum must be a non-empty array of primitives, got ${typeof e}`
4982
5018
  });
4983
5019
  } else if (e.length === 0) {
4984
5020
  errors.push({
4985
- path: `${path24}.enum`,
5021
+ path: `${path25}.enum`,
4986
5022
  message: "enum must not be empty"
4987
5023
  });
4988
5024
  } else {
4989
5025
  for (let i = 0; i < e.length; i++) {
4990
5026
  if (!isPrimitive(e[i])) {
4991
5027
  errors.push({
4992
- path: `${path24}.enum[${i}]`,
5028
+ path: `${path25}.enum[${i}]`,
4993
5029
  message: `enum entry must be a primitive (string/number/boolean/null), got ${typeof e[i]}`
4994
5030
  });
4995
5031
  }
@@ -4999,7 +5035,7 @@ function validateSchema(schema, path24, errors, opts = {}) {
4999
5035
  for (const key of ["exclusiveMinimum", "exclusiveMaximum"]) {
5000
5036
  if (key in schema && typeof schema[key] === "boolean") {
5001
5037
  errors.push({
5002
- path: `${path24}.${key}`,
5038
+ path: `${path25}.${key}`,
5003
5039
  message: `${key} as boolean is draft-04 syntax; draft 2020-12 requires a numeric value`,
5004
5040
  suggestion: `Replace with the numeric bound, e.g. \`${key}: 0\`.`
5005
5041
  });
@@ -5008,45 +5044,45 @@ function validateSchema(schema, path24, errors, opts = {}) {
5008
5044
  if ("properties" in schema) {
5009
5045
  if (!isRecord(schema.properties)) {
5010
5046
  errors.push({
5011
- path: `${path24}.properties`,
5047
+ path: `${path25}.properties`,
5012
5048
  message: `properties must be an object, got ${Array.isArray(schema.properties) ? "array" : typeof schema.properties}`
5013
5049
  });
5014
5050
  } else {
5015
5051
  for (const [propName, propSchema] of Object.entries(schema.properties)) {
5016
- validateSchema(propSchema, `${path24}.properties.${propName}`, errors, { depth: depth + 1 });
5052
+ validateSchema(propSchema, `${path25}.properties.${propName}`, errors, { depth: depth + 1 });
5017
5053
  }
5018
5054
  }
5019
5055
  }
5020
5056
  if (schemaTypeIncludes(schema, "array") && "items" in schema) {
5021
5057
  if (Array.isArray(schema.items)) {
5022
- schema.items.forEach((sub, i) => validateSchema(sub, `${path24}.items[${i}]`, errors, { depth: depth + 1 }));
5058
+ schema.items.forEach((sub, i) => validateSchema(sub, `${path25}.items[${i}]`, errors, { depth: depth + 1 }));
5023
5059
  } else {
5024
- validateSchema(schema.items, `${path24}.items`, errors, { depth: depth + 1 });
5060
+ validateSchema(schema.items, `${path25}.items`, errors, { depth: depth + 1 });
5025
5061
  }
5026
5062
  }
5027
5063
  for (const key of SUBSCHEMA_OBJECT_KEYWORDS) {
5028
5064
  if (key in schema && isRecord(schema[key])) {
5029
- validateSchema(schema[key], `${path24}.${key}`, errors, { depth: depth + 1 });
5065
+ validateSchema(schema[key], `${path25}.${key}`, errors, { depth: depth + 1 });
5030
5066
  }
5031
5067
  }
5032
5068
  for (const key of SUBSCHEMA_LIST_KEYWORDS) {
5033
5069
  const list = schema[key];
5034
5070
  if (Array.isArray(list)) {
5035
- list.forEach((sub, i) => validateSchema(sub, `${path24}.${key}[${i}]`, errors, { depth: depth + 1 }));
5071
+ list.forEach((sub, i) => validateSchema(sub, `${path25}.${key}[${i}]`, errors, { depth: depth + 1 }));
5036
5072
  }
5037
5073
  }
5038
5074
  for (const key of SUBSCHEMA_MAP_KEYWORDS) {
5039
5075
  const map = schema[key];
5040
5076
  if (isRecord(map)) {
5041
5077
  for (const [name, sub] of Object.entries(map)) {
5042
- validateSchema(sub, `${path24}.${key}.${name}`, errors, { depth: depth + 1 });
5078
+ validateSchema(sub, `${path25}.${key}.${name}`, errors, { depth: depth + 1 });
5043
5079
  }
5044
5080
  }
5045
5081
  }
5046
5082
  const reportedPaths = new Set(errors.map((e) => e.path));
5047
5083
  for (const [k, v] of Object.entries(schema)) {
5048
5084
  if (typeof v !== "string") continue;
5049
- const fieldPath = `${path24}.${k}`;
5085
+ const fieldPath = `${path25}.${k}`;
5050
5086
  if (reportedPaths.has(fieldPath)) continue;
5051
5087
  for (const token of PLACEHOLDER_TOKENS) {
5052
5088
  if (v === token) {
@@ -5202,10 +5238,10 @@ function refineHubAsCodeLanes(config, ctx) {
5202
5238
  }
5203
5239
  }
5204
5240
  }
5205
- function isSafeTemplatePath(path24) {
5206
- if (path24.length === 0 || path24.length > 300) return false;
5207
- if (path24.startsWith("/") || path24.includes("\\")) return false;
5208
- const segments = path24.split("/");
5241
+ function isSafeTemplatePath(path25) {
5242
+ if (path25.length === 0 || path25.length > 300) return false;
5243
+ if (path25.startsWith("/") || path25.includes("\\")) return false;
5244
+ const segments = path25.split("/");
5209
5245
  return segments.every(
5210
5246
  (seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
5211
5247
  );
@@ -5275,7 +5311,7 @@ function findStepBoundaries(transcript) {
5275
5311
  }
5276
5312
  return out;
5277
5313
  }
5278
- var APP_ERROR_BRAND, AppError, LLM_RATE_LIMIT_BRAND, LlmRateLimitError, LLM_PROVIDER_HTTP_BRAND, LlmProviderHttpError, 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, 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, previewLabelField, createHubBody, updateHubBody, addHubAdminBody, addHubIdentityAuthorizationBody, contactDecisionBody, approveContactBody, listContactAccessQuery, createHubTeamBody, updateHubTeamBody, addHubTeamUserBody, reassignHubUserBody, replicatePreviewBody, claimCodeChannelParam, claimCodeDeleteParam, connectionIdParam, connectorIdParam, listConnectionsQuery, deleteConnectionQuery, addConnectionBody, editConnectionBody, 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, PACING_INTERVAL_MIN_MS, PACING_INTERVAL_MAX_MS, EVAL_RUN_DEADLINE_MIN_MS, EVAL_RUN_DEADLINE_MAX_MS, paginationSchema2, evalIdParam, sessionIdParam, scenarioSetIdParam, hubIdQuery, createEvalBody, updateEvalBody, getEvalsQuery, toggleEvalBody, bulkToggleEvalsBody, pacingConfigSchema, sessionConfigSchema, createSessionBody, getSessionsQuery, getSessionResultsQuery, getSessionRunsQuery, evalAnalyticsQuery, getSessionCostQuery, compareSessionsQuery, evalsSqlBody, evalsSqlSchemaQuery, exportResultsQuery, validateEvalBody, hubAgentsQuery, createScenarioSetBody, updateScenarioSetBody, scenarioSetsHubQuery, createScenarioFromConversationBody, createJourneyFromConversationBody, journeyIdParam, journeyToolCallSchema, journeyTurnSchema, journeyStepOverrideSchema, createJourneyBody, updateJourneyBody, getConversationsQuery, getMessagesQuery, 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, completionsBody, 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, uuidPattern, ciUuidSchema, hubAsCodeConfigSchema, ciPullHubIdParam, ciBranchParam, ciPullQuery, ciHubsQuery, ciLookupQuery, ciBranchesQuery, ciSyncBody, ciPushBody, ciDiffBody, ciPublishBody, ciPublishPreviewBody, ciSyncMcpBody, ciOrgResourcesParam, orgResourcesConfigSchema, ciOrgResourcesPushBody, ciOrgResourcesDiffBody, adminOrgIdParam, adminOrgAdminIdParam, adminUserIdParam, adminPlanIdParam, adminOrganizationsQuery, adminUserSearchQuery, kanbanSlugMigrationQuery, adjustQuotaBody, updatePlanBody, addAdminUserBody, updatePlatformConfigBody, updateFreeOrgLimitBody, 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, 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, MAX_RESOURCE_FILE_SIZE;
5314
+ var APP_ERROR_BRAND, AppError, LLM_RATE_LIMIT_BRAND, LlmRateLimitError, LLM_PROVIDER_HTTP_BRAND, LlmProviderHttpError, 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, 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, previewLabelField, createHubBody, updateHubBody, addHubAdminBody, addHubIdentityAuthorizationBody, contactDecisionBody, approveContactBody, listContactAccessQuery, createHubTeamBody, updateHubTeamBody, addHubTeamUserBody, reassignHubUserBody, replicatePreviewBody, 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, PACING_INTERVAL_MIN_MS, PACING_INTERVAL_MAX_MS, EVAL_RUN_DEADLINE_MIN_MS, EVAL_RUN_DEADLINE_MAX_MS, paginationSchema2, evalIdParam, sessionIdParam, scenarioSetIdParam, hubIdQuery, createEvalBody, updateEvalBody, getEvalsQuery, toggleEvalBody, bulkToggleEvalsBody, pacingConfigSchema, sessionConfigSchema, createSessionBody, getSessionsQuery, getSessionResultsQuery, getSessionRunsQuery, evalAnalyticsQuery, getSessionCostQuery, compareSessionsQuery, evalsSqlBody, evalsSqlSchemaQuery, exportResultsQuery, validateEvalBody, hubAgentsQuery, createScenarioSetBody, updateScenarioSetBody, scenarioSetsHubQuery, createScenarioFromConversationBody, createJourneyFromConversationBody, journeyIdParam, journeyToolCallSchema, journeyTurnSchema, journeyStepOverrideSchema, createJourneyBody, updateJourneyBody, getConversationsQuery, getMessagesQuery, 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, completionsBody, 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, uuidPattern, ciUuidSchema, hubAsCodeConfigSchema, ciPullHubIdParam, ciBranchParam, ciPullQuery, ciHubsQuery, ciLookupQuery, ciBranchesQuery, ciSyncBody, ciPushBody, ciDiffBody, ciPublishBody, ciPublishPreviewBody, ciSyncMcpBody, ciOrgResourcesParam, orgResourcesConfigSchema, ciOrgResourcesPushBody, ciOrgResourcesDiffBody, adminOrgIdParam, adminOrgAdminIdParam, adminUserIdParam, adminPlanIdParam, adminOrganizationsQuery, adminUserSearchQuery, kanbanSlugMigrationQuery, adjustQuotaBody, updatePlanBody, addAdminUserBody, updatePlatformConfigBody, updateFreeOrgLimitBody, 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, 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, MAX_RESOURCE_FILE_SIZE;
5279
5315
  var init_dist = __esm({
5280
5316
  "../../packages/core/dist/index.js"() {
5281
5317
  "use strict";
@@ -5866,15 +5902,27 @@ var init_dist = __esm({
5866
5902
  hub_id: uuidSchema,
5867
5903
  sync_credentials_to_production: external_exports.boolean().optional()
5868
5904
  }).passthrough();
5905
+ PRODUCTION_DIRECT_FIELDS = ["username", "api_key", "access_token", "password", "refresh_token", "webhook_secret_token"];
5869
5906
  setProductionCredentialBody = external_exports.object({
5870
5907
  hub_id: uuidSchema,
5908
+ organization_credential_id: external_exports.string().nullable().optional(),
5909
+ organization_credential_token_id: external_exports.string().nullable().optional(),
5871
5910
  username: external_exports.string().optional(),
5872
5911
  api_key: external_exports.string().optional(),
5873
5912
  access_token: external_exports.string().optional(),
5874
5913
  password: external_exports.string().optional(),
5875
5914
  refresh_token: external_exports.string().optional(),
5876
5915
  webhook_secret_token: external_exports.string().optional()
5877
- }).strict();
5916
+ }).strict().superRefine((data, ctx) => {
5917
+ const hasOrgLink = !!data.organization_credential_id || !!data.organization_credential_token_id;
5918
+ const hasDirect = PRODUCTION_DIRECT_FIELDS.some((f) => data[f] != null);
5919
+ if (hasOrgLink && hasDirect) {
5920
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "Provide either an organization credential link or direct credential fields, not both" });
5921
+ }
5922
+ if (!hasOrgLink && !hasDirect) {
5923
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "A credential is required: link an organization credential or provide a credential field" });
5924
+ }
5925
+ });
5878
5926
  registerWhatsappQuery = external_exports.object({ hub_id: uuidSchema });
5879
5927
  registerWhatsappBody = external_exports.object({
5880
5928
  pin: external_exports.string().optional()
@@ -7906,6 +7954,7 @@ __export(workspace_exports, {
7906
7954
  getChangedHubs: () => getChangedHubs,
7907
7955
  getHubFolderSlug: () => getHubFolderSlug,
7908
7956
  isPreviewHub: () => isPreviewHub,
7957
+ localHubEnvironment: () => localHubEnvironment,
7909
7958
  resolveActiveHubId: () => resolveActiveHubId,
7910
7959
  resolveExplicitHubPath: () => resolveExplicitHubPath,
7911
7960
  resolveHubFolder: () => resolveHubFolder,
@@ -8197,6 +8246,13 @@ function resolveActiveHubId(args2) {
8197
8246
  }
8198
8247
  process.exit(1);
8199
8248
  }
8249
+ function localHubEnvironment(hubId) {
8250
+ const workspace = detectWorkspace();
8251
+ const gitRoot = findGitRoot();
8252
+ const workspaceDir = workspace?.workspaceDir ?? (gitRoot ? resolveLayout(gitRoot).hubsDir : null);
8253
+ if (!workspaceDir || !fs2.existsSync(workspaceDir)) return null;
8254
+ return scanWorkspaceHubs(workspaceDir).find((h) => h.hubId === hubId)?.hubEnvironment ?? null;
8255
+ }
8200
8256
  function safeReaddir(dir) {
8201
8257
  try {
8202
8258
  return fs2.readdirSync(dir).filter((entry) => !entry.startsWith("."));
@@ -8504,9 +8560,9 @@ function getVersionCachePath(filename = CLI_CACHE_FILE) {
8504
8560
  }
8505
8561
  function readVersionCache(filename = CLI_CACHE_FILE) {
8506
8562
  try {
8507
- const path24 = getVersionCachePath(filename);
8508
- if (!existsSync4(path24)) return null;
8509
- const parsed = JSON.parse(readFileSync5(path24, "utf-8"));
8563
+ const path25 = getVersionCachePath(filename);
8564
+ if (!existsSync4(path25)) return null;
8565
+ const parsed = JSON.parse(readFileSync5(path25, "utf-8"));
8510
8566
  if (typeof parsed.lastCheck !== "number") return null;
8511
8567
  if (parsed.latest !== null && typeof parsed.latest !== "string") return null;
8512
8568
  return parsed;
@@ -8526,10 +8582,10 @@ function isVersionCacheStale(filename = CLI_CACHE_FILE, maxAgeMs = MAX_AGE_24H_M
8526
8582
  return Date.now() - cache.lastCheck > maxAgeMs;
8527
8583
  }
8528
8584
  function writeVersionCache(filename, cache) {
8529
- const path24 = getVersionCachePath(filename);
8530
- const dir = dirname3(path24);
8585
+ const path25 = getVersionCachePath(filename);
8586
+ const dir = dirname3(path25);
8531
8587
  if (!existsSync4(dir)) mkdirSync(dir, { recursive: true });
8532
- writeFileSync2(path24, JSON.stringify(cache));
8588
+ writeFileSync2(path25, JSON.stringify(cache));
8533
8589
  }
8534
8590
  function touchVersionCache(filename) {
8535
8591
  writeVersionCache(filename, { lastCheck: Date.now(), latest: readVersionCache(filename)?.latest ?? null });
@@ -8568,14 +8624,14 @@ function parseFrontmatterVersion(content) {
8568
8624
  function findInstalledSkills(projectRoot, paths = SKILL_INSTALL_PATHS) {
8569
8625
  const found = [];
8570
8626
  for (const rel of paths) {
8571
- const path24 = join7(projectRoot, rel);
8572
- if (!existsSync5(path24)) continue;
8627
+ const path25 = join7(projectRoot, rel);
8628
+ if (!existsSync5(path25)) continue;
8573
8629
  let version = null;
8574
8630
  try {
8575
- version = parseFrontmatterVersion(readFileSync6(path24, "utf-8"));
8631
+ version = parseFrontmatterVersion(readFileSync6(path25, "utf-8"));
8576
8632
  } catch {
8577
8633
  }
8578
- found.push({ path: path24, version });
8634
+ found.push({ path: path25, version });
8579
8635
  }
8580
8636
  return found;
8581
8637
  }
@@ -11545,12 +11601,12 @@ function typeMatches2(typeField, allowed) {
11545
11601
  if (Array.isArray(typeField)) return typeField.every((t) => typeof t === "string" && allowed.has(t));
11546
11602
  return false;
11547
11603
  }
11548
- function validateSchema2(schema, path24, errors, opts = {}) {
11604
+ function validateSchema2(schema, path25, errors, opts = {}) {
11549
11605
  if (typeof schema === "boolean") return;
11550
11606
  const depth = opts.depth ?? 0;
11551
11607
  if (depth > MAX_SCHEMA_DEPTH2) {
11552
11608
  errors.push({
11553
- path: path24 || "<root>",
11609
+ path: path25 || "<root>",
11554
11610
  message: `schema nesting exceeds ${MAX_SCHEMA_DEPTH2} levels`,
11555
11611
  suggestion: "Flatten the schema; LLM providers reject deeply nested tool input_schemas."
11556
11612
  });
@@ -11558,7 +11614,7 @@ function validateSchema2(schema, path24, errors, opts = {}) {
11558
11614
  }
11559
11615
  if (!isRecord2(schema)) {
11560
11616
  errors.push({
11561
- path: path24,
11617
+ path: path25,
11562
11618
  message: `expected object, got ${schema === null ? "null" : typeof schema}`
11563
11619
  });
11564
11620
  return;
@@ -11566,14 +11622,14 @@ function validateSchema2(schema, path24, errors, opts = {}) {
11566
11622
  if (opts.isRoot) {
11567
11623
  if ("type" in schema && schema.type !== "object") {
11568
11624
  errors.push({
11569
- path: path24 ? `${path24}.type` : "type",
11625
+ path: path25 ? `${path25}.type` : "type",
11570
11626
  message: `root type must be 'object', got ${JSON.stringify(schema.type)}`,
11571
11627
  suggestion: "Tool parameters at the root must be an object: `{ type: 'object', properties: { ... } }`."
11572
11628
  });
11573
11629
  }
11574
11630
  } else if ("type" in schema && !typeMatches2(schema.type, ALLOWED_TYPES2)) {
11575
11631
  errors.push({
11576
- path: `${path24}.type`,
11632
+ path: `${path25}.type`,
11577
11633
  message: `type must be one of ${[...ALLOWED_TYPES2].join("/")} or an array of those, got ${JSON.stringify(schema.type)}`
11578
11634
  });
11579
11635
  }
@@ -11582,25 +11638,25 @@ function validateSchema2(schema, path24, errors, opts = {}) {
11582
11638
  if (typeof e === "string") {
11583
11639
  const isPlaceholder = PLACEHOLDER_TOKENS2.includes(e);
11584
11640
  errors.push({
11585
- path: `${path24}.enum`,
11641
+ path: `${path25}.enum`,
11586
11642
  message: `enum must be a non-empty array of primitives, got string ${JSON.stringify(e)}`,
11587
11643
  suggestion: isPlaceholder ? "Set `operation: 'update_kanban_status'` on the tool and ensure at least one hub.kanban_status has `allowsAgentUpdate: true` so the platform can render the placeholder into a valid array." : 'Wrap the value in an array: `enum: ["value"]`.'
11588
11644
  });
11589
11645
  } else if (!Array.isArray(e)) {
11590
11646
  errors.push({
11591
- path: `${path24}.enum`,
11647
+ path: `${path25}.enum`,
11592
11648
  message: `enum must be a non-empty array of primitives, got ${typeof e}`
11593
11649
  });
11594
11650
  } else if (e.length === 0) {
11595
11651
  errors.push({
11596
- path: `${path24}.enum`,
11652
+ path: `${path25}.enum`,
11597
11653
  message: "enum must not be empty"
11598
11654
  });
11599
11655
  } else {
11600
11656
  for (let i = 0; i < e.length; i++) {
11601
11657
  if (!isPrimitive2(e[i])) {
11602
11658
  errors.push({
11603
- path: `${path24}.enum[${i}]`,
11659
+ path: `${path25}.enum[${i}]`,
11604
11660
  message: `enum entry must be a primitive (string/number/boolean/null), got ${typeof e[i]}`
11605
11661
  });
11606
11662
  }
@@ -11610,7 +11666,7 @@ function validateSchema2(schema, path24, errors, opts = {}) {
11610
11666
  for (const key of ["exclusiveMinimum", "exclusiveMaximum"]) {
11611
11667
  if (key in schema && typeof schema[key] === "boolean") {
11612
11668
  errors.push({
11613
- path: `${path24}.${key}`,
11669
+ path: `${path25}.${key}`,
11614
11670
  message: `${key} as boolean is draft-04 syntax; draft 2020-12 requires a numeric value`,
11615
11671
  suggestion: `Replace with the numeric bound, e.g. \`${key}: 0\`.`
11616
11672
  });
@@ -11619,45 +11675,45 @@ function validateSchema2(schema, path24, errors, opts = {}) {
11619
11675
  if ("properties" in schema) {
11620
11676
  if (!isRecord2(schema.properties)) {
11621
11677
  errors.push({
11622
- path: `${path24}.properties`,
11678
+ path: `${path25}.properties`,
11623
11679
  message: `properties must be an object, got ${Array.isArray(schema.properties) ? "array" : typeof schema.properties}`
11624
11680
  });
11625
11681
  } else {
11626
11682
  for (const [propName, propSchema] of Object.entries(schema.properties)) {
11627
- validateSchema2(propSchema, `${path24}.properties.${propName}`, errors, { depth: depth + 1 });
11683
+ validateSchema2(propSchema, `${path25}.properties.${propName}`, errors, { depth: depth + 1 });
11628
11684
  }
11629
11685
  }
11630
11686
  }
11631
11687
  if (schemaTypeIncludes2(schema, "array") && "items" in schema) {
11632
11688
  if (Array.isArray(schema.items)) {
11633
- schema.items.forEach((sub, i) => validateSchema2(sub, `${path24}.items[${i}]`, errors, { depth: depth + 1 }));
11689
+ schema.items.forEach((sub, i) => validateSchema2(sub, `${path25}.items[${i}]`, errors, { depth: depth + 1 }));
11634
11690
  } else {
11635
- validateSchema2(schema.items, `${path24}.items`, errors, { depth: depth + 1 });
11691
+ validateSchema2(schema.items, `${path25}.items`, errors, { depth: depth + 1 });
11636
11692
  }
11637
11693
  }
11638
11694
  for (const key of SUBSCHEMA_OBJECT_KEYWORDS2) {
11639
11695
  if (key in schema && isRecord2(schema[key])) {
11640
- validateSchema2(schema[key], `${path24}.${key}`, errors, { depth: depth + 1 });
11696
+ validateSchema2(schema[key], `${path25}.${key}`, errors, { depth: depth + 1 });
11641
11697
  }
11642
11698
  }
11643
11699
  for (const key of SUBSCHEMA_LIST_KEYWORDS2) {
11644
11700
  const list = schema[key];
11645
11701
  if (Array.isArray(list)) {
11646
- list.forEach((sub, i) => validateSchema2(sub, `${path24}.${key}[${i}]`, errors, { depth: depth + 1 }));
11702
+ list.forEach((sub, i) => validateSchema2(sub, `${path25}.${key}[${i}]`, errors, { depth: depth + 1 }));
11647
11703
  }
11648
11704
  }
11649
11705
  for (const key of SUBSCHEMA_MAP_KEYWORDS2) {
11650
11706
  const map = schema[key];
11651
11707
  if (isRecord2(map)) {
11652
11708
  for (const [name, sub] of Object.entries(map)) {
11653
- validateSchema2(sub, `${path24}.${key}.${name}`, errors, { depth: depth + 1 });
11709
+ validateSchema2(sub, `${path25}.${key}.${name}`, errors, { depth: depth + 1 });
11654
11710
  }
11655
11711
  }
11656
11712
  }
11657
11713
  const reportedPaths = new Set(errors.map((e) => e.path));
11658
11714
  for (const [k, v] of Object.entries(schema)) {
11659
11715
  if (typeof v !== "string") continue;
11660
- const fieldPath = `${path24}.${k}`;
11716
+ const fieldPath = `${path25}.${k}`;
11661
11717
  if (reportedPaths.has(fieldPath)) continue;
11662
11718
  for (const token of PLACEHOLDER_TOKENS2) {
11663
11719
  if (v === token) {
@@ -11813,10 +11869,10 @@ function refineHubAsCodeLanes2(config, ctx) {
11813
11869
  }
11814
11870
  }
11815
11871
  }
11816
- function isSafeTemplatePath2(path24) {
11817
- if (path24.length === 0 || path24.length > 300) return false;
11818
- if (path24.startsWith("/") || path24.includes("\\")) return false;
11819
- const segments = path24.split("/");
11872
+ function isSafeTemplatePath2(path25) {
11873
+ if (path25.length === 0 || path25.length > 300) return false;
11874
+ if (path25.startsWith("/") || path25.includes("\\")) return false;
11875
+ const segments = path25.split("/");
11820
11876
  return segments.every(
11821
11877
  (seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
11822
11878
  );
@@ -11844,14 +11900,14 @@ function isPlainObject(value) {
11844
11900
  const proto = Object.getPrototypeOf(value);
11845
11901
  return proto === Object.prototype || proto === null;
11846
11902
  }
11847
- function isSanitizableSliceFile(path24) {
11848
- if (!/\.ya?ml$/i.test(path24)) return false;
11849
- return path24 !== "resources" && !path24.startsWith("resources/");
11903
+ function isSanitizableSliceFile(path25) {
11904
+ if (!/\.ya?ml$/i.test(path25)) return false;
11905
+ return path25 !== "resources" && !path25.startsWith("resources/");
11850
11906
  }
11851
11907
  function distinctUsesBackends(uses) {
11852
11908
  return [...new Set((uses ?? []).map((u) => u.backend))];
11853
11909
  }
11854
- var uuidSchema2, paginationSchema3, timestampSchema2, idParamSchema2, 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, previewLabelField2, createHubBody2, updateHubBody2, addHubAdminBody2, addHubIdentityAuthorizationBody2, contactDecisionBody2, approveContactBody2, listContactAccessQuery2, createHubTeamBody2, updateHubTeamBody2, addHubTeamUserBody2, reassignHubUserBody2, replicatePreviewBody2, claimCodeChannelParam2, claimCodeDeleteParam2, connectionIdParam2, connectorIdParam2, listConnectionsQuery2, deleteConnectionQuery2, addConnectionBody2, editConnectionBody2, 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, PACING_INTERVAL_MIN_MS2, PACING_INTERVAL_MAX_MS2, EVAL_RUN_DEADLINE_MIN_MS2, EVAL_RUN_DEADLINE_MAX_MS2, paginationSchema22, evalIdParam2, sessionIdParam2, scenarioSetIdParam2, hubIdQuery2, createEvalBody2, updateEvalBody2, getEvalsQuery2, toggleEvalBody2, bulkToggleEvalsBody2, pacingConfigSchema2, sessionConfigSchema2, createSessionBody2, getSessionsQuery2, getSessionResultsQuery2, getSessionRunsQuery2, evalAnalyticsQuery2, getSessionCostQuery2, compareSessionsQuery2, evalsSqlBody2, evalsSqlSchemaQuery2, exportResultsQuery2, validateEvalBody2, hubAgentsQuery2, createScenarioSetBody2, updateScenarioSetBody2, scenarioSetsHubQuery2, createScenarioFromConversationBody2, createJourneyFromConversationBody2, journeyIdParam2, journeyToolCallSchema2, journeyTurnSchema2, journeyStepOverrideSchema2, createJourneyBody2, updateJourneyBody2, getConversationsQuery2, getMessagesQuery2, 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, completionsBody2, 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, uuidPattern2, ciUuidSchema2, hubAsCodeConfigSchema2, ciPullHubIdParam2, ciBranchParam2, ciPullQuery2, ciHubsQuery2, ciLookupQuery2, ciBranchesQuery2, ciSyncBody2, ciPushBody2, ciDiffBody2, ciPublishBody2, ciPublishPreviewBody2, ciSyncMcpBody2, ciOrgResourcesParam2, orgResourcesConfigSchema2, ciOrgResourcesPushBody2, ciOrgResourcesDiffBody2, adminOrgIdParam2, adminOrgAdminIdParam2, adminUserIdParam2, adminPlanIdParam2, adminOrganizationsQuery2, adminUserSearchQuery2, kanbanSlugMigrationQuery2, adjustQuotaBody2, updatePlanBody2, addAdminUserBody2, updatePlatformConfigBody2, updateFreeOrgLimitBody2, 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, 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;
11910
+ var uuidSchema2, paginationSchema3, timestampSchema2, idParamSchema2, 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, previewLabelField2, createHubBody2, updateHubBody2, addHubAdminBody2, addHubIdentityAuthorizationBody2, contactDecisionBody2, approveContactBody2, listContactAccessQuery2, createHubTeamBody2, updateHubTeamBody2, addHubTeamUserBody2, reassignHubUserBody2, replicatePreviewBody2, 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, PACING_INTERVAL_MIN_MS2, PACING_INTERVAL_MAX_MS2, EVAL_RUN_DEADLINE_MIN_MS2, EVAL_RUN_DEADLINE_MAX_MS2, paginationSchema22, evalIdParam2, sessionIdParam2, scenarioSetIdParam2, hubIdQuery2, createEvalBody2, updateEvalBody2, getEvalsQuery2, toggleEvalBody2, bulkToggleEvalsBody2, pacingConfigSchema2, sessionConfigSchema2, createSessionBody2, getSessionsQuery2, getSessionResultsQuery2, getSessionRunsQuery2, evalAnalyticsQuery2, getSessionCostQuery2, compareSessionsQuery2, evalsSqlBody2, evalsSqlSchemaQuery2, exportResultsQuery2, validateEvalBody2, hubAgentsQuery2, createScenarioSetBody2, updateScenarioSetBody2, scenarioSetsHubQuery2, createScenarioFromConversationBody2, createJourneyFromConversationBody2, journeyIdParam2, journeyToolCallSchema2, journeyTurnSchema2, journeyStepOverrideSchema2, createJourneyBody2, updateJourneyBody2, getConversationsQuery2, getMessagesQuery2, 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, completionsBody2, 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, uuidPattern2, ciUuidSchema2, hubAsCodeConfigSchema2, ciPullHubIdParam2, ciBranchParam2, ciPullQuery2, ciHubsQuery2, ciLookupQuery2, ciBranchesQuery2, ciSyncBody2, ciPushBody2, ciDiffBody2, ciPublishBody2, ciPublishPreviewBody2, ciSyncMcpBody2, ciOrgResourcesParam2, orgResourcesConfigSchema2, ciOrgResourcesPushBody2, ciOrgResourcesDiffBody2, adminOrgIdParam2, adminOrgAdminIdParam2, adminUserIdParam2, adminPlanIdParam2, adminOrganizationsQuery2, adminUserSearchQuery2, kanbanSlugMigrationQuery2, adjustQuotaBody2, updatePlanBody2, addAdminUserBody2, updatePlatformConfigBody2, updateFreeOrgLimitBody2, 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, 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;
11855
11911
  var init_contracts = __esm({
11856
11912
  "../../packages/core/dist/contracts/index.js"() {
11857
11913
  "use strict";
@@ -12358,15 +12414,27 @@ var init_contracts = __esm({
12358
12414
  hub_id: uuidSchema2,
12359
12415
  sync_credentials_to_production: external_exports.boolean().optional()
12360
12416
  }).passthrough();
12417
+ PRODUCTION_DIRECT_FIELDS2 = ["username", "api_key", "access_token", "password", "refresh_token", "webhook_secret_token"];
12361
12418
  setProductionCredentialBody2 = external_exports.object({
12362
12419
  hub_id: uuidSchema2,
12420
+ organization_credential_id: external_exports.string().nullable().optional(),
12421
+ organization_credential_token_id: external_exports.string().nullable().optional(),
12363
12422
  username: external_exports.string().optional(),
12364
12423
  api_key: external_exports.string().optional(),
12365
12424
  access_token: external_exports.string().optional(),
12366
12425
  password: external_exports.string().optional(),
12367
12426
  refresh_token: external_exports.string().optional(),
12368
12427
  webhook_secret_token: external_exports.string().optional()
12369
- }).strict();
12428
+ }).strict().superRefine((data, ctx) => {
12429
+ const hasOrgLink = !!data.organization_credential_id || !!data.organization_credential_token_id;
12430
+ const hasDirect = PRODUCTION_DIRECT_FIELDS2.some((f) => data[f] != null);
12431
+ if (hasOrgLink && hasDirect) {
12432
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "Provide either an organization credential link or direct credential fields, not both" });
12433
+ }
12434
+ if (!hasOrgLink && !hasDirect) {
12435
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "A credential is required: link an organization credential or provide a credential field" });
12436
+ }
12437
+ });
12370
12438
  registerWhatsappQuery2 = external_exports.object({ hub_id: uuidSchema2 });
12371
12439
  registerWhatsappBody2 = external_exports.object({
12372
12440
  pin: external_exports.string().optional()
@@ -14523,12 +14591,153 @@ var init_relabel = __esm({
14523
14591
  }
14524
14592
  });
14525
14593
 
14594
+ // src/commands/publish.ts
14595
+ var publish_exports = {};
14596
+ __export(publish_exports, {
14597
+ parseArgs: () => parseArgs9,
14598
+ publishCommand: () => publishCommand,
14599
+ renderHubDiff: () => renderHubDiff,
14600
+ runPublish: () => runPublish
14601
+ });
14602
+ import * as path17 from "path";
14603
+ function parseArgs9(args2) {
14604
+ let autoConfirm = false;
14605
+ let hubSelector;
14606
+ for (let i = 0; i < args2.length; i++) {
14607
+ const arg = args2[i];
14608
+ if (arg === "--yes" || arg === "-y") {
14609
+ autoConfirm = true;
14610
+ } else if (arg === "--hub" && args2[i + 1]) {
14611
+ hubSelector = args2[++i];
14612
+ }
14613
+ }
14614
+ return { autoConfirm, hubSelector };
14615
+ }
14616
+ function renderSection(title, entries) {
14617
+ if (entries.length === 0) return;
14618
+ console.log(`
14619
+ \x1B[1m${title}\x1B[0m`);
14620
+ for (const e of entries) {
14621
+ const { sym, color } = STATUS_STYLE[e.status];
14622
+ const type = e.type ? ` (${e.type})` : "";
14623
+ console.log(`\x1B[${color}m${sym} ${e.name}${type}\x1B[0m`);
14624
+ }
14625
+ }
14626
+ function renderHubDiff(result) {
14627
+ if (result.hub_changed) {
14628
+ const { sym, color } = STATUS_STYLE[result.is_first_publish ? "added" : "updated"];
14629
+ console.log("\n\x1B[1mHub\x1B[0m");
14630
+ console.log(`\x1B[${color}m${sym} hub settings\x1B[0m`);
14631
+ }
14632
+ renderSection("Agents", result.agents);
14633
+ renderSection("Connections", result.connections);
14634
+ renderSection("Tools", result.tools);
14635
+ renderSection("Channels", result.channels);
14636
+ renderSection("States", result.states);
14637
+ renderSection("Resources", result.resources);
14638
+ console.log();
14639
+ }
14640
+ async function runPublish(client, opts) {
14641
+ const { hubId, localConfig, organizationId, autoConfirm } = opts;
14642
+ const confirmFn = opts.confirmFn ?? confirm;
14643
+ if (localConfig) {
14644
+ const pushDiff = await client.diff(hubId, localConfig, "push", organizationId);
14645
+ if (pushDiff.has_changes) {
14646
+ console.log("\n\x1B[33mYou have local changes not yet pushed to this preview.\x1B[0m");
14647
+ console.log("Publishing promotes the PREVIEW (server) state \u2014 these local edits are NOT included.");
14648
+ console.log("Run `wayai push` first if you want them in production.");
14649
+ if (!autoConfirm) {
14650
+ const ok = await confirmFn("Continue with the current preview state anyway?");
14651
+ if (!ok) {
14652
+ console.log("Cancelled.");
14653
+ return "cancelled";
14654
+ }
14655
+ }
14656
+ }
14657
+ }
14658
+ const { data: diff } = await client.getHubDiff(hubId);
14659
+ if (!diff.has_changes && !diff.is_first_publish) {
14660
+ console.log("Production is already up to date. Nothing to sync.");
14661
+ return "up-to-date";
14662
+ }
14663
+ console.log(
14664
+ diff.is_first_publish ? "\nPublish preview \u2192 new production hub:" : "\nSync preview \u2192 production:"
14665
+ );
14666
+ renderHubDiff(diff);
14667
+ if (!autoConfirm) {
14668
+ const ok = await confirmFn(
14669
+ diff.is_first_publish ? "Publish to production?" : "Sync these changes to production?"
14670
+ );
14671
+ if (!ok) {
14672
+ console.log("Cancelled.");
14673
+ return "cancelled";
14674
+ }
14675
+ }
14676
+ if (diff.is_first_publish) {
14677
+ console.log("Publishing...");
14678
+ const { data } = await client.publishHub(hubId);
14679
+ console.log(`
14680
+ Published. Production hub: ${data.production_hub_id}`);
14681
+ return "published";
14682
+ }
14683
+ console.log("Syncing...");
14684
+ await client.syncHub(hubId);
14685
+ console.log("\nSynced preview changes to production.");
14686
+ return "synced";
14687
+ }
14688
+ async function publishCommand(args2) {
14689
+ const { autoConfirm, hubSelector } = parseArgs9(args2);
14690
+ const repoConfig = requireRepoConfig();
14691
+ const { organization_id: organizationId } = repoConfig;
14692
+ const { config, accessToken } = await requireAuth();
14693
+ const client = new ApiClient({ apiUrl: config.api_url, accessToken });
14694
+ const workspaceDir = resolveWorkspaceDir();
14695
+ const gitRoot = findGitRoot();
14696
+ if (gitRoot) warnLayoutOnce(gitRoot);
14697
+ const { hubId, hubFolder } = resolveHubTarget(workspaceDir, hubSelector);
14698
+ let localConfig = null;
14699
+ if (hubFolder) {
14700
+ localConfig = parseHubFolder(hubFolder);
14701
+ if (localConfig.hub_environment === "production") {
14702
+ console.log(
14703
+ "This is a read-only production mirror \u2014 production hubs cannot be published. Publish the linked preview hub instead."
14704
+ );
14705
+ return;
14706
+ }
14707
+ }
14708
+ assertHubMatchesBinding(hubId, hubFolder ? path17.basename(hubFolder) : void 0);
14709
+ await runPublish(client, { hubId, localConfig, organizationId, autoConfirm });
14710
+ }
14711
+ var STATUS_STYLE;
14712
+ var init_publish = __esm({
14713
+ "src/commands/publish.ts"() {
14714
+ "use strict";
14715
+ init_auth();
14716
+ init_api_client();
14717
+ init_parser();
14718
+ init_pull();
14719
+ init_utils();
14720
+ init_workspace();
14721
+ init_layout();
14722
+ init_repo_config();
14723
+ init_hub_binding();
14724
+ STATUS_STYLE = {
14725
+ added: { sym: "+", color: 32 },
14726
+ // green
14727
+ removed: { sym: "-", color: 31 },
14728
+ // red
14729
+ updated: { sym: "~", color: 33 }
14730
+ // yellow
14731
+ };
14732
+ }
14733
+ });
14734
+
14526
14735
  // src/commands/use.ts
14527
14736
  var use_exports = {};
14528
14737
  __export(use_exports, {
14529
14738
  useCommand: () => useCommand
14530
14739
  });
14531
- import * as path17 from "path";
14740
+ import * as path18 from "path";
14532
14741
  async function useCommand(args2) {
14533
14742
  const target = args2[0];
14534
14743
  if (!target || target.startsWith("-")) {
@@ -14551,7 +14760,7 @@ async function useCommand(args2) {
14551
14760
  if (!match) {
14552
14761
  console.error(`No hub matching "${target}" found in ${wsLabel}/. Pass a UUID or a folder name from:`);
14553
14762
  for (const h of scanWorkspaceHubs(workspaceDir)) {
14554
- console.error(` ${path17.basename(h.hubFolder)} (${h.hubId})`);
14763
+ console.error(` ${path18.basename(h.hubFolder)} (${h.hubId})`);
14555
14764
  }
14556
14765
  process.exit(1);
14557
14766
  }
@@ -14591,10 +14800,10 @@ __export(migrate_exports, {
14591
14800
  });
14592
14801
  import { execFileSync as execFileSync3 } from "child_process";
14593
14802
  import * as fs14 from "fs";
14594
- import * as path18 from "path";
14803
+ import * as path19 from "path";
14595
14804
  function isTracked(gitRoot, p) {
14596
14805
  try {
14597
- execFileSync3("git", ["ls-files", "--error-unmatch", "--", path18.relative(gitRoot, p)], {
14806
+ execFileSync3("git", ["ls-files", "--error-unmatch", "--", path19.relative(gitRoot, p)], {
14598
14807
  cwd: gitRoot,
14599
14808
  stdio: ["pipe", "pipe", "pipe"]
14600
14809
  });
@@ -14604,10 +14813,10 @@ function isTracked(gitRoot, p) {
14604
14813
  }
14605
14814
  }
14606
14815
  function moveDir(gitRoot, from, to) {
14607
- fs14.mkdirSync(path18.dirname(to), { recursive: true });
14816
+ fs14.mkdirSync(path19.dirname(to), { recursive: true });
14608
14817
  if (isTracked(gitRoot, from)) {
14609
14818
  try {
14610
- execFileSync3("git", ["mv", path18.relative(gitRoot, from), path18.relative(gitRoot, to)], {
14819
+ execFileSync3("git", ["mv", path19.relative(gitRoot, from), path19.relative(gitRoot, to)], {
14611
14820
  cwd: gitRoot,
14612
14821
  stdio: ["pipe", "pipe", "pipe"]
14613
14822
  });
@@ -14624,12 +14833,12 @@ async function migrateCommand(_args) {
14624
14833
  console.error("Not inside a git repository.");
14625
14834
  process.exit(1);
14626
14835
  }
14627
- const rel = (p) => path18.relative(gitRoot, p);
14628
- const newWs = path18.join(gitRoot, WAYAI_LAYOUT.wsDir);
14629
- const legacyWs = path18.join(gitRoot, WAYAI_LAYOUT.legacy.wsDir);
14630
- const legacyOrg = path18.join(gitRoot, WAYAI_LAYOUT.legacy.orgAtRoot);
14631
- const newHubs = path18.join(newWs, WAYAI_LAYOUT.hubsSubdir);
14632
- const newOrg = path18.join(newWs, WAYAI_LAYOUT.orgSubdir);
14836
+ const rel = (p) => path19.relative(gitRoot, p);
14837
+ const newWs = path19.join(gitRoot, WAYAI_LAYOUT.wsDir);
14838
+ const legacyWs = path19.join(gitRoot, WAYAI_LAYOUT.legacy.wsDir);
14839
+ const legacyOrg = path19.join(gitRoot, WAYAI_LAYOUT.legacy.orgAtRoot);
14840
+ const newHubs = path19.join(newWs, WAYAI_LAYOUT.hubsSubdir);
14841
+ const newOrg = path19.join(newWs, WAYAI_LAYOUT.orgSubdir);
14633
14842
  const hasLegacyWs = isDirectory(legacyWs);
14634
14843
  const hasLegacyOrg = isDirectory(legacyOrg);
14635
14844
  if (!hasLegacyWs && !hasLegacyOrg) {
@@ -15263,10 +15472,10 @@ var init_delete_history = __esm({
15263
15472
  // src/commands/sync-skills.ts
15264
15473
  var sync_skills_exports = {};
15265
15474
  __export(sync_skills_exports, {
15266
- parseArgs: () => parseArgs9,
15475
+ parseArgs: () => parseArgs10,
15267
15476
  syncSkillsCommand: () => syncSkillsCommand
15268
15477
  });
15269
- function parseArgs9(args2) {
15478
+ function parseArgs10(args2) {
15270
15479
  let connectionId;
15271
15480
  const idx = args2.indexOf("--connection-id");
15272
15481
  if (idx !== -1 && args2[idx + 1]) {
@@ -15289,7 +15498,7 @@ function printSyncResults(response) {
15289
15498
  }
15290
15499
  async function syncSkillsCommand(args2) {
15291
15500
  const hubId = resolveActiveHubId(args2);
15292
- const { connectionId } = parseArgs9(args2);
15501
+ const { connectionId } = parseArgs10(args2);
15293
15502
  requireRepoConfig();
15294
15503
  const { config, accessToken } = await requireAuth();
15295
15504
  const client = new ApiClient({ apiUrl: config.api_url, accessToken });
@@ -15314,10 +15523,10 @@ var init_sync_skills = __esm({
15314
15523
  // src/commands/sync-mcp.ts
15315
15524
  var sync_mcp_exports = {};
15316
15525
  __export(sync_mcp_exports, {
15317
- parseArgs: () => parseArgs10,
15526
+ parseArgs: () => parseArgs11,
15318
15527
  syncMcpCommand: () => syncMcpCommand
15319
15528
  });
15320
- function parseArgs10(args2) {
15529
+ function parseArgs11(args2) {
15321
15530
  let connection;
15322
15531
  for (let i = 0; i < args2.length; i++) {
15323
15532
  const arg = args2[i];
@@ -15329,7 +15538,7 @@ function parseArgs10(args2) {
15329
15538
  }
15330
15539
  async function syncMcpCommand(args2) {
15331
15540
  const hubId = resolveActiveHubId(args2);
15332
- const { connection } = parseArgs10(args2);
15541
+ const { connection } = parseArgs11(args2);
15333
15542
  if (!connection) {
15334
15543
  console.error("Usage: wayai sync-mcp --connection <name> [--hub <uuid|folder-name>]");
15335
15544
  console.error("");
@@ -15938,14 +16147,14 @@ __export(eval_capture_exports, {
15938
16147
  evalCaptureCommand: () => evalCaptureCommand
15939
16148
  });
15940
16149
  import * as fs15 from "fs";
15941
- import * as path19 from "path";
16150
+ import * as path20 from "path";
15942
16151
  import * as yaml7 from "js-yaml";
15943
16152
  function isValidSetName(name) {
15944
16153
  if (name.length === 0 || name === "." || name === "..") return false;
15945
16154
  if (name.startsWith(".")) return false;
15946
16155
  return !/[\/\\\0]/.test(name);
15947
16156
  }
15948
- function parseArgs11(args2) {
16157
+ function parseArgs12(args2) {
15949
16158
  if (args2.length === 0 || args2[0].startsWith("-")) {
15950
16159
  console.error("Usage: wayai eval capture <conversation_id> [--set <name>] [--name <eval_name>] [--instructions <text>]");
15951
16160
  process.exit(1);
@@ -15991,7 +16200,7 @@ function parseArgs11(args2) {
15991
16200
  }
15992
16201
  async function evalCaptureCommand(args2) {
15993
16202
  const hubId = resolveActiveHubId(args2);
15994
- const parsed = parseArgs11(args2);
16203
+ const parsed = parseArgs12(args2);
15995
16204
  const { config, accessToken } = await requireAuth();
15996
16205
  requireRepoConfig();
15997
16206
  const client = new ApiClient({ apiUrl: config.api_url, accessToken });
@@ -16004,15 +16213,15 @@ async function evalCaptureCommand(args2) {
16004
16213
  const setFolderName = targetSetName;
16005
16214
  const scenarioName = parsed.evalName ?? `Capture ${parsed.conversationId.slice(0, 8)}`;
16006
16215
  const slug = slugify(scenarioName);
16007
- const evalsDir = path19.join(hubFolder, "evals");
16008
- const targetDir = path19.join(evalsDir, setFolderName);
16009
- const targetPath = path19.join(targetDir, `${slug}.yaml`);
16010
- if (!targetPath.startsWith(evalsDir + path19.sep)) {
16011
- console.error(`Resolved path "${path19.relative(hubFolder, targetPath)}" escapes evals/. Aborting.`);
16216
+ const evalsDir = path20.join(hubFolder, "evals");
16217
+ const targetDir = path20.join(evalsDir, setFolderName);
16218
+ const targetPath = path20.join(targetDir, `${slug}.yaml`);
16219
+ if (!targetPath.startsWith(evalsDir + path20.sep)) {
16220
+ console.error(`Resolved path "${path20.relative(hubFolder, targetPath)}" escapes evals/. Aborting.`);
16012
16221
  process.exit(1);
16013
16222
  }
16014
16223
  if (fs15.existsSync(targetPath)) {
16015
- console.error(`File already exists: ${path19.relative(hubFolder, targetPath)}. Use --name to choose a different name.`);
16224
+ console.error(`File already exists: ${path20.relative(hubFolder, targetPath)}. Use --name to choose a different name.`);
16016
16225
  process.exit(1);
16017
16226
  }
16018
16227
  console.log("Resolving scenario set...");
@@ -16046,7 +16255,7 @@ async function evalCaptureCommand(args2) {
16046
16255
  const yamlObj = buildEvalYamlObject(evalEntry, slug);
16047
16256
  fs15.mkdirSync(targetDir, { recursive: true });
16048
16257
  fs15.writeFileSync(targetPath, yaml7.dump(yamlObj, YAML_DUMP_OPTIONS), "utf-8");
16049
- const relPath = path19.relative(process.cwd(), targetPath);
16258
+ const relPath = path20.relative(process.cwd(), targetPath);
16050
16259
  console.log(`
16051
16260
  Wrote ${relPath}`);
16052
16261
  console.log("Run `wayai pull` to refresh the agent display name, then commit. The scenario is already on the platform.");
@@ -16068,7 +16277,7 @@ var journey_capture_exports = {};
16068
16277
  __export(journey_capture_exports, {
16069
16278
  journeyCaptureCommand: () => journeyCaptureCommand
16070
16279
  });
16071
- function parseArgs12(args2) {
16280
+ function parseArgs13(args2) {
16072
16281
  if (args2.length === 0 || args2[0].startsWith("-")) {
16073
16282
  console.error("Usage: wayai eval journey capture <conversation_id> [--name <journey_name>] [--instructions <text>]");
16074
16283
  process.exit(1);
@@ -16103,7 +16312,7 @@ function parseArgs12(args2) {
16103
16312
  }
16104
16313
  async function journeyCaptureCommand(args2) {
16105
16314
  const hubId = resolveActiveHubId(args2);
16106
- const parsed = parseArgs12(args2);
16315
+ const parsed = parseArgs13(args2);
16107
16316
  const { config, accessToken } = await requireAuth();
16108
16317
  requireRepoConfig();
16109
16318
  const client = new ApiClient({ apiUrl: config.api_url, accessToken });
@@ -16900,9 +17109,9 @@ var init_credential_utils = __esm({
16900
17109
  var create_credential_exports = {};
16901
17110
  __export(create_credential_exports, {
16902
17111
  createCredentialCommand: () => createCredentialCommand,
16903
- parseArgs: () => parseArgs13
17112
+ parseArgs: () => parseArgs14
16904
17113
  });
16905
- function parseArgs13(args2) {
17114
+ function parseArgs14(args2) {
16906
17115
  let name;
16907
17116
  let type;
16908
17117
  let orgId;
@@ -16930,7 +17139,7 @@ function parseArgs13(args2) {
16930
17139
  return { name, type, orgId, description, tags: splitTagRefs(tags), environment, stdin };
16931
17140
  }
16932
17141
  async function createCredentialCommand(args2) {
16933
- const parsed = parseArgs13(args2);
17142
+ const parsed = parseArgs14(args2);
16934
17143
  if (!parsed.name) {
16935
17144
  console.error("Missing required flag: --name <credential-name>");
16936
17145
  console.error('Usage: wayai create-credential --name "openai-key" --type "Bearer Token"');
@@ -17037,10 +17246,10 @@ var init_create_credential = __esm({
17037
17246
  // src/commands/update-credential.ts
17038
17247
  var update_credential_exports = {};
17039
17248
  __export(update_credential_exports, {
17040
- parseArgs: () => parseArgs14,
17249
+ parseArgs: () => parseArgs15,
17041
17250
  updateCredentialCommand: () => updateCredentialCommand
17042
17251
  });
17043
- function parseArgs14(args2) {
17252
+ function parseArgs15(args2) {
17044
17253
  let name;
17045
17254
  let rename;
17046
17255
  let orgId;
@@ -17073,7 +17282,7 @@ function parseArgs14(args2) {
17073
17282
  return { name, rename, orgId, description, tags: splitTagRefs(tags), hasTagFlag, environment, stdin, secretPrompt };
17074
17283
  }
17075
17284
  async function updateCredentialCommand(args2) {
17076
- const parsed = parseArgs14(args2);
17285
+ const parsed = parseArgs15(args2);
17077
17286
  if (!parsed.name) {
17078
17287
  console.error("Missing required flag: --name <credential-name>");
17079
17288
  console.error('Usage: wayai update-credential --name "my-key" --stdin');
@@ -17175,24 +17384,121 @@ var init_update_credential = __esm({
17175
17384
  }
17176
17385
  });
17177
17386
 
17387
+ // src/commands/set-connection-credential.ts
17388
+ var set_connection_credential_exports = {};
17389
+ __export(set_connection_credential_exports, {
17390
+ parseArgs: () => parseArgs16,
17391
+ setConnectionCredentialCommand: () => setConnectionCredentialCommand
17392
+ });
17393
+ function parseArgs16(args2) {
17394
+ let connection;
17395
+ let orgCredential;
17396
+ let field;
17397
+ let stdin = false;
17398
+ for (let i = 0; i < args2.length; i++) {
17399
+ if (args2[i] === "--connection" && args2[i + 1]) connection = args2[++i];
17400
+ else if (args2[i] === "--org-credential" && args2[i + 1]) orgCredential = args2[++i];
17401
+ else if (args2[i] === "--field" && args2[i + 1]) field = args2[++i];
17402
+ else if (args2[i] === "--stdin") stdin = true;
17403
+ }
17404
+ return { connection, orgCredential, field, stdin };
17405
+ }
17406
+ function usage(msg) {
17407
+ if (msg) console.error(`${msg}
17408
+ `);
17409
+ console.error("Usage: wayai set-connection-credential --hub <id|name> --connection <name|id> ( --org-credential <name> | --field <field> --stdin )");
17410
+ console.error(` --org-credential <name> link an organization credential by display name`);
17411
+ console.error(` --field <field> --stdin set a raw secret from stdin (field: ${VALID_FIELDS.join(", ")})`);
17412
+ process.exit(1);
17413
+ }
17414
+ async function setConnectionCredentialCommand(args2) {
17415
+ const hubId = resolveActiveHubId(args2);
17416
+ const parsed = parseArgs16(args2);
17417
+ if (!parsed.connection) usage("Missing required flag: --connection <name|id>");
17418
+ const orgMode = !!parsed.orgCredential;
17419
+ const directMode = !!parsed.field;
17420
+ if (orgMode === directMode) {
17421
+ usage("Provide exactly one of --org-credential or --field.");
17422
+ }
17423
+ if (directMode && !VALID_FIELDS.includes(parsed.field)) {
17424
+ usage(`Invalid --field "${parsed.field}". Valid fields: ${VALID_FIELDS.join(", ")}`);
17425
+ }
17426
+ if (directMode && !parsed.stdin) {
17427
+ usage("--field requires --stdin (the secret is read from stdin, never an argument).");
17428
+ }
17429
+ const { organization_id: organizationId } = requireRepoConfig();
17430
+ const { config, accessToken } = await requireAuth();
17431
+ const client = new ApiClient({ apiUrl: config.api_url, accessToken });
17432
+ let environment = localHubEnvironment(hubId);
17433
+ if (!environment) {
17434
+ const { hubs } = await client.listHubs(organizationId);
17435
+ if (hubs.some((h) => h.hub_id === hubId)) environment = "preview";
17436
+ else if (hubs.some((h) => h.production_hub_id === hubId)) environment = "production";
17437
+ }
17438
+ if (!environment) {
17439
+ usage(`Could not resolve hub "${hubId}". Pull it first (\`wayai pull --hub ${hubId}\`) or check the id.`);
17440
+ }
17441
+ const isProduction = environment === "production";
17442
+ const { connections } = await client.listConnections(hubId);
17443
+ const conn = connections.find(
17444
+ (c) => c.connection_id === parsed.connection || c.connection_display_name === parsed.connection
17445
+ );
17446
+ if (!conn || !conn.connection_id) usage(`Connection "${parsed.connection}" not found on hub ${hubId}.`);
17447
+ const connectionId = conn.connection_id;
17448
+ const body = { hub_id: hubId };
17449
+ if (orgMode) {
17450
+ const { data: creds } = await client.listOrgCredentials(organizationId);
17451
+ const cred = creds.find((c) => c.credential_display_name === parsed.orgCredential);
17452
+ if (!cred) usage(`Organization credential "${parsed.orgCredential}" not found.`);
17453
+ body.organization_credential_id = cred.organization_credential_id;
17454
+ } else {
17455
+ if (process.stdin.isTTY) {
17456
+ usage('--field requires the secret on stdin. Example: echo "$SECRET" | wayai set-connection-credential ... --field api_key --stdin');
17457
+ }
17458
+ const secret = (await readStdin())?.trim();
17459
+ if (!secret) usage("No secret received from stdin.");
17460
+ body[parsed.field] = secret;
17461
+ }
17462
+ const target = isProduction ? "production" : "preview";
17463
+ console.log(`Setting ${orgMode ? `org credential "${parsed.orgCredential}"` : `${parsed.field}`} on ${target} connection "${conn.connection_display_name}"...`);
17464
+ if (isProduction) {
17465
+ await client.setProductionConnectionCredential(connectionId, body);
17466
+ } else {
17467
+ await client.setPreviewConnectionCredential(connectionId, body);
17468
+ }
17469
+ console.log("Credential set.");
17470
+ }
17471
+ var VALID_FIELDS;
17472
+ var init_set_connection_credential = __esm({
17473
+ "src/commands/set-connection-credential.ts"() {
17474
+ "use strict";
17475
+ init_auth();
17476
+ init_api_client();
17477
+ init_repo_config();
17478
+ init_workspace();
17479
+ init_utils();
17480
+ VALID_FIELDS = ["api_key", "access_token", "password", "refresh_token", "webhook_secret_token", "username"];
17481
+ }
17482
+ });
17483
+
17178
17484
  // src/lib/org-workspace.ts
17179
17485
  import * as fs16 from "fs";
17180
- import * as path20 from "path";
17486
+ import * as path21 from "path";
17181
17487
  import * as yaml8 from "js-yaml";
17182
17488
  function getOrgDir(gitRoot) {
17183
17489
  return resolveLayout(gitRoot).orgDir;
17184
17490
  }
17185
17491
  function orgManifestExists(orgDir) {
17186
- return fs16.existsSync(path20.join(orgDir, ORG_MANIFEST_NAME));
17492
+ return fs16.existsSync(path21.join(orgDir, ORG_MANIFEST_NAME));
17187
17493
  }
17188
17494
  function parseOrgResources(orgDir) {
17189
- const manifestPath = path20.join(orgDir, ORG_MANIFEST_NAME);
17495
+ const manifestPath = path21.join(orgDir, ORG_MANIFEST_NAME);
17190
17496
  let manifest = {};
17191
17497
  if (fs16.existsSync(manifestPath)) {
17192
17498
  manifest = yaml8.load(fs16.readFileSync(manifestPath, "utf-8")) ?? {};
17193
17499
  }
17194
17500
  const rawResources = Array.isArray(manifest.resources) ? manifest.resources : [];
17195
- const resourcesDir = path20.join(orgDir, "resources");
17501
+ const resourcesDir = path21.join(orgDir, "resources");
17196
17502
  const resources = rawResources.map((res) => {
17197
17503
  const resource = { name: res.name };
17198
17504
  if (res.id) resource.id = res.id;
@@ -17204,7 +17510,7 @@ function parseOrgResources(orgDir) {
17204
17510
  if (res.environment) resource.environment = res.environment;
17205
17511
  if (Array.isArray(res.tags)) resource.tags = res.tags;
17206
17512
  if (Array.isArray(res.folders)) resource.folders = res.folders;
17207
- const resDir = path20.join(resourcesDir, slugify(resource.name));
17513
+ const resDir = path21.join(resourcesDir, slugify(resource.name));
17208
17514
  if (fs16.existsSync(resDir)) {
17209
17515
  const files = scanResourceFiles(resDir, "");
17210
17516
  if (files.length > 0) resource.files = files;
@@ -17221,21 +17527,21 @@ function writeOrgResources(orgDir, payload) {
17221
17527
  return rest;
17222
17528
  });
17223
17529
  fs16.writeFileSync(
17224
- path20.join(orgDir, ORG_MANIFEST_NAME),
17530
+ path21.join(orgDir, ORG_MANIFEST_NAME),
17225
17531
  yaml8.dump({ version: 1, resources: manifestResources }, YAML_DUMP_OPTIONS),
17226
17532
  "utf-8"
17227
17533
  );
17228
- const resourcesDir = path20.join(orgDir, "resources");
17534
+ const resourcesDir = path21.join(orgDir, "resources");
17229
17535
  const currentSlugs = /* @__PURE__ */ new Set();
17230
17536
  for (const resource of resources) {
17231
17537
  const resSlug = slugify(resource.name);
17232
17538
  currentSlugs.add(resSlug);
17233
- writeResourceFileTree(path20.join(resourcesDir, resSlug), resource.files || []);
17539
+ writeResourceFileTree(path21.join(resourcesDir, resSlug), resource.files || []);
17234
17540
  }
17235
17541
  if (fs16.existsSync(resourcesDir)) {
17236
17542
  for (const entry of fs16.readdirSync(resourcesDir, { withFileTypes: true })) {
17237
17543
  if (entry.isDirectory() && !currentSlugs.has(entry.name)) {
17238
- fs16.rmSync(path20.join(resourcesDir, entry.name), { recursive: true, force: true });
17544
+ fs16.rmSync(path21.join(resourcesDir, entry.name), { recursive: true, force: true });
17239
17545
  }
17240
17546
  }
17241
17547
  }
@@ -17244,7 +17550,7 @@ async function downloadOrgBinaryFiles(orgDir, payload) {
17244
17550
  let count = 0;
17245
17551
  for (const resource of payload.resources ?? []) {
17246
17552
  if (!resource.files) continue;
17247
- const resDir = path20.join(orgDir, "resources", slugify(resource.name));
17553
+ const resDir = path21.join(orgDir, "resources", slugify(resource.name));
17248
17554
  count += await downloadBinaryFiles(resDir, resource.files);
17249
17555
  }
17250
17556
  if (count > 0) console.log(`Downloaded ${count} binary resource file(s).`);
@@ -17432,9 +17738,9 @@ var init_org = __esm({
17432
17738
  var list_exports = {};
17433
17739
  __export(list_exports, {
17434
17740
  listCommand: () => listCommand,
17435
- parseArgs: () => parseArgs15
17741
+ parseArgs: () => parseArgs17
17436
17742
  });
17437
- function parseArgs15(args2) {
17743
+ function parseArgs17(args2) {
17438
17744
  let orgId;
17439
17745
  let json = false;
17440
17746
  for (let i = 0; i < args2.length; i++) {
@@ -17447,7 +17753,7 @@ function parseArgs15(args2) {
17447
17753
  return { orgId, json };
17448
17754
  }
17449
17755
  async function listCommand(args2) {
17450
- const { orgId, json } = parseArgs15(args2);
17756
+ const { orgId, json } = parseArgs17(args2);
17451
17757
  const { config, accessToken } = await requireAuth();
17452
17758
  const client = new ApiClient({ apiUrl: config.api_url, accessToken });
17453
17759
  const { organizations } = await client.organizations();
@@ -17501,13 +17807,13 @@ var init_list = __esm({
17501
17807
 
17502
17808
  // src/lib/template-files.ts
17503
17809
  import * as fs17 from "fs";
17504
- import * as path21 from "path";
17810
+ import * as path22 from "path";
17505
17811
  function readDirToFileMap(rootDir) {
17506
17812
  const out = {};
17507
17813
  function walk(dir, prefix) {
17508
17814
  const entries = fs17.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
17509
17815
  for (const entry of entries) {
17510
- const abs = path21.join(dir, entry.name);
17816
+ const abs = path22.join(dir, entry.name);
17511
17817
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
17512
17818
  if (entry.isDirectory()) walk(abs, rel);
17513
17819
  else if (entry.isFile()) out[rel] = fs17.readFileSync(abs, "utf-8");
@@ -17522,7 +17828,7 @@ function detectCollisions(targetDir, files) {
17522
17828
  if (!isSafeTemplatePath2(rel)) {
17523
17829
  throw new Error(`Refusing to inspect unsafe template path: ${rel}`);
17524
17830
  }
17525
- if (fs17.existsSync(path21.join(targetDir, rel))) collisions.push(rel);
17831
+ if (fs17.existsSync(path22.join(targetDir, rel))) collisions.push(rel);
17526
17832
  }
17527
17833
  return collisions.sort((a, b) => a.localeCompare(b));
17528
17834
  }
@@ -17532,8 +17838,8 @@ function writeFileMap(targetDir, files) {
17532
17838
  if (!isSafeTemplatePath2(rel)) {
17533
17839
  throw new Error(`Refusing to write unsafe template path: ${rel}`);
17534
17840
  }
17535
- const abs = path21.join(targetDir, rel);
17536
- fs17.mkdirSync(path21.dirname(abs), { recursive: true });
17841
+ const abs = path22.join(targetDir, rel);
17842
+ fs17.mkdirSync(path22.dirname(abs), { recursive: true });
17537
17843
  fs17.writeFileSync(abs, body, "utf-8");
17538
17844
  written.push(rel);
17539
17845
  }
@@ -17544,7 +17850,7 @@ function listDirRelFiles(dir) {
17544
17850
  function walk(d, prefix) {
17545
17851
  for (const entry of fs17.readdirSync(d, { withFileTypes: true })) {
17546
17852
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
17547
- if (entry.isDirectory()) walk(path21.join(d, entry.name), rel);
17853
+ if (entry.isDirectory()) walk(path22.join(d, entry.name), rel);
17548
17854
  else if (entry.isFile()) out.push(rel);
17549
17855
  }
17550
17856
  }
@@ -17571,7 +17877,7 @@ var templates_exports = {};
17571
17877
  __export(templates_exports, {
17572
17878
  templateCommand: () => templateCommand
17573
17879
  });
17574
- import * as path22 from "path";
17880
+ import * as path23 from "path";
17575
17881
  async function templateCommand(args2) {
17576
17882
  const [sub, ...rest] = args2;
17577
17883
  switch (sub) {
@@ -17687,8 +17993,8 @@ async function runTemplatePull(rest) {
17687
17993
  console.log(`Template "${slug}" has no WayAI slice${hint}`);
17688
17994
  return;
17689
17995
  }
17690
- const targetDir = path22.join(resolveLayout(gitRoot).hubsDir, slug);
17691
- const relTarget = path22.relative(gitRoot, targetDir);
17996
+ const targetDir = path23.join(resolveLayout(gitRoot).hubsDir, slug);
17997
+ const relTarget = path23.relative(gitRoot, targetDir);
17692
17998
  const collisions = detectCollisions(targetDir, detail.files);
17693
17999
  if (dryRun) {
17694
18000
  const planned = Object.keys(detail.files).sort((a, b) => a.localeCompare(b));
@@ -17863,7 +18169,7 @@ __export(admin_exports, {
17863
18169
  adminCommand: () => adminCommand
17864
18170
  });
17865
18171
  import * as fs18 from "fs";
17866
- import * as path23 from "path";
18172
+ import * as path24 from "path";
17867
18173
  import * as yaml10 from "js-yaml";
17868
18174
  async function adminCommand(args2) {
17869
18175
  const [group, ...afterGroup] = args2;
@@ -18242,10 +18548,10 @@ function loadTemplateManifest(slug) {
18242
18548
  console.error("Not in a git repository. Run from the tutorials/ authoring repo.");
18243
18549
  process.exit(1);
18244
18550
  }
18245
- const templateDir = path23.join(resolveTemplatesDir(gitRoot), slug);
18246
- const manifestPath = path23.join(templateDir, "template.yaml");
18551
+ const templateDir = path24.join(resolveTemplatesDir(gitRoot), slug);
18552
+ const manifestPath = path24.join(templateDir, "template.yaml");
18247
18553
  if (!fs18.existsSync(manifestPath)) {
18248
- console.error(`template.yaml not found at ${path23.relative(gitRoot, manifestPath)}`);
18554
+ console.error(`template.yaml not found at ${path24.relative(gitRoot, manifestPath)}`);
18249
18555
  process.exit(1);
18250
18556
  }
18251
18557
  let manifest;
@@ -18280,19 +18586,19 @@ async function runTemplatePush(positional) {
18280
18586
  const wayaiEntry = manifest.wayai.locales[locale];
18281
18587
  let wayaiFiles;
18282
18588
  if (wayaiEntry) {
18283
- const sliceDir = path23.resolve(templateDir, wayaiEntry.source);
18589
+ const sliceDir = path24.resolve(templateDir, wayaiEntry.source);
18284
18590
  if (!fs18.existsSync(sliceDir)) {
18285
18591
  console.error(`wayai source not found for ${locale}: ${wayaiEntry.source} (resolved ${sliceDir})`);
18286
18592
  process.exit(1);
18287
18593
  }
18288
18594
  if (!isInsideTemplateDir(sliceDir, templateDir)) {
18289
18595
  console.warn(
18290
- `Note: ${locale} source points at a live hub (${wayaiEntry.source}); it can go stale on a hub recreate. Run \`wayai admin template freeze ${slug} --locale ${locale} --from ${path23.basename(sliceDir)}\` to commit a stable frozen slice.`
18596
+ `Note: ${locale} source points at a live hub (${wayaiEntry.source}); it can go stale on a hub recreate. Run \`wayai admin template freeze ${slug} --locale ${locale} --from ${path24.basename(sliceDir)}\` to commit a stable frozen slice.`
18291
18597
  );
18292
18598
  }
18293
18599
  wayaiFiles = readDirToFileMap(sliceDir);
18294
18600
  }
18295
- const readmePath = path23.join(templateDir, `README.${locale}.md`);
18601
+ const readmePath = path24.join(templateDir, `README.${locale}.md`);
18296
18602
  const readmeMarkdown = fs18.existsSync(readmePath) ? fs18.readFileSync(readmePath, "utf-8") : "";
18297
18603
  locales[locale] = {
18298
18604
  readmeMarkdown,
@@ -18304,9 +18610,9 @@ async function runTemplatePush(positional) {
18304
18610
  }
18305
18611
  let hero;
18306
18612
  if (manifest.hero) {
18307
- const heroPath = path23.resolve(templateDir, manifest.hero);
18613
+ const heroPath = path24.resolve(templateDir, manifest.hero);
18308
18614
  if (fs18.existsSync(heroPath)) {
18309
- hero = { filename: path23.basename(heroPath), dataBase64: fs18.readFileSync(heroPath).toString("base64") };
18615
+ hero = { filename: path24.basename(heroPath), dataBase64: fs18.readFileSync(heroPath).toString("base64") };
18310
18616
  } else {
18311
18617
  console.error(`Warning: hero not found at ${manifest.hero}; skipping.`);
18312
18618
  }
@@ -18332,7 +18638,7 @@ async function runTemplatePush(positional) {
18332
18638
  }
18333
18639
  }
18334
18640
  function isInsideTemplateDir(dest, templateDir) {
18335
- return dest === templateDir || dest.startsWith(templateDir + path23.sep);
18641
+ return dest === templateDir || dest.startsWith(templateDir + path24.sep);
18336
18642
  }
18337
18643
  async function runTemplateFreeze(positional, flagArgs) {
18338
18644
  const slug = positional[0];
@@ -18393,7 +18699,7 @@ async function runTemplateFreeze(positional, flagArgs) {
18393
18699
  process.exit(1);
18394
18700
  }
18395
18701
  const entry = manifest.wayai.locales[targetLocale];
18396
- const dest = path23.resolve(templateDir, entry.source);
18702
+ const dest = path24.resolve(templateDir, entry.source);
18397
18703
  if (!isInsideTemplateDir(dest, templateDir) || dest === templateDir) {
18398
18704
  console.error(
18399
18705
  `source for "${targetLocale}" must be a committed path inside ${slug}/ (e.g. "./${targetLocale}/slice"), but resolved to:
@@ -18412,7 +18718,7 @@ Set it to a subdir of the template folder and re-run freeze.`
18412
18718
  const hubs = scanWorkspaceHubs(hubsDir);
18413
18719
  if (hubs.length) {
18414
18720
  console.error("Available hubs:");
18415
- for (const h of hubs) console.error(` ${path23.basename(h.hubFolder)} (${h.hubId})`);
18721
+ for (const h of hubs) console.error(` ${path24.basename(h.hubFolder)} (${h.hubId})`);
18416
18722
  }
18417
18723
  console.error(`
18418
18724
  Pass --from <folder|uuid>${selector ? "." : " or run `wayai use <hub>` first."}`);
@@ -18420,12 +18726,12 @@ Pass --from <folder|uuid>${selector ? "." : " or run `wayai use <hub>` first."}`
18420
18726
  }
18421
18727
  const liveFiles = readDirToFileMap(hubFolder);
18422
18728
  if (Object.keys(liveFiles).length === 0) {
18423
- console.error(`Source hub folder has no files to freeze: ${path23.relative(gitRoot, hubFolder)}`);
18729
+ console.error(`Source hub folder has no files to freeze: ${path24.relative(gitRoot, hubFolder)}`);
18424
18730
  process.exit(1);
18425
18731
  }
18426
18732
  const sanitized = sanitizeWayaiSliceFiles(liveFiles);
18427
- const relDest = path23.relative(gitRoot, dest);
18428
- const relSrc = path23.relative(gitRoot, hubFolder);
18733
+ const relDest = path24.relative(gitRoot, dest);
18734
+ const relSrc = path24.relative(gitRoot, hubFolder);
18429
18735
  if (dryRun) {
18430
18736
  const existing = new Set(listDirRelFiles(dest));
18431
18737
  const nextKeys = new Set(Object.keys(sanitized));
@@ -18485,7 +18791,7 @@ async function runTemplatePull2(positional, flagArgs) {
18485
18791
  console.log(JSON.stringify(detail, null, 2));
18486
18792
  return;
18487
18793
  }
18488
- const target = outDir ? path23.resolve(outDir) : path23.join(process.cwd(), "template-store-pull", slug);
18794
+ const target = outDir ? path24.resolve(outDir) : path24.join(process.cwd(), "template-store-pull", slug);
18489
18795
  const written = writeFileMap(target, detail.files);
18490
18796
  console.log(`Pulled "${slug}" from the store \u2192 ${target} (${written.length} file${written.length === 1 ? "" : "s"}).`);
18491
18797
  const uses = detail.uses ?? [];
@@ -18508,13 +18814,13 @@ async function runSkillInstall(positional) {
18508
18814
  throw err;
18509
18815
  }
18510
18816
  const root = findGitRoot() ?? process.cwd();
18511
- const present = HARNESS_SKILL_DIRS.filter((dir) => fs18.existsSync(path23.join(root, dir)));
18817
+ const present = HARNESS_SKILL_DIRS.filter((dir) => fs18.existsSync(path24.join(root, dir)));
18512
18818
  const targets = present.length > 0 ? present : HARNESS_SKILL_DIRS;
18513
18819
  const fileCount = Object.keys(res.files).length;
18514
18820
  const relDirs = targets.map((harness) => {
18515
- const targetDir = path23.join(root, harness, "skills", name);
18821
+ const targetDir = path24.join(root, harness, "skills", name);
18516
18822
  writeFileMap(targetDir, res.files);
18517
- return `${path23.relative(root, targetDir)}/`;
18823
+ return `${path24.relative(root, targetDir)}/`;
18518
18824
  });
18519
18825
  console.log(`Installed skill "${name}" (${fileCount} file${fileCount === 1 ? "" : "s"}) \u2192 ${relDirs.join(", ")}`);
18520
18826
  console.log("Reload your agent (e.g. restart Claude Code) to pick up the skill.");
@@ -19408,6 +19714,9 @@ function friendlyHint(err) {
19408
19714
  return "Couldn't reach WayAI \u2014 check your network connection and try again.";
19409
19715
  }
19410
19716
  if (!(err instanceof ApiError)) return null;
19717
+ if (err.body.includes("FREE_PLAN_RESTRICTION")) {
19718
+ return "Publishing to production requires a paid plan. Upgrade your organization to publish or sync.";
19719
+ }
19411
19720
  const { status } = err;
19412
19721
  if (status === 401) return "Your session may have expired. Run `wayai login` to re-authenticate.";
19413
19722
  if (status === 402) return "Quota exceeded for your plan. Review usage or upgrade your plan.";
@@ -19644,6 +19953,14 @@ async function main() {
19644
19953
  await relabelCommand2(args);
19645
19954
  break;
19646
19955
  }
19956
+ // `sync` is a bare alias of `publish` (distinct from `sync-skills` / `sync-mcp`,
19957
+ // which are exact-string cases). Both promote preview → production.
19958
+ case "publish":
19959
+ case "sync": {
19960
+ const { publishCommand: publishCommand2 } = await Promise.resolve().then(() => (init_publish(), publish_exports));
19961
+ await publishCommand2(args);
19962
+ break;
19963
+ }
19647
19964
  case "use": {
19648
19965
  const { useCommand: useCommand2 } = await Promise.resolve().then(() => (init_use(), use_exports));
19649
19966
  await useCommand2(args);
@@ -19721,6 +20038,11 @@ async function main() {
19721
20038
  await updateCredentialCommand2(args);
19722
20039
  break;
19723
20040
  }
20041
+ case "set-connection-credential": {
20042
+ const { setConnectionCredentialCommand: setConnectionCredentialCommand2 } = await Promise.resolve().then(() => (init_set_connection_credential(), set_connection_credential_exports));
20043
+ await setConnectionCredentialCommand2(args);
20044
+ break;
20045
+ }
19724
20046
  case "org": {
19725
20047
  const { orgCommand: orgCommand2 } = await Promise.resolve().then(() => (init_org(), org_exports));
19726
20048
  await orgCommand2(args);
@@ -19783,11 +20105,14 @@ Commands:
19783
20105
  init Set up .wayai.yaml (pick organization)
19784
20106
  create-credential Create an organization credential (API key, token, etc.)
19785
20107
  update-credential Update / rotate an organization credential (by name)
20108
+ set-connection-credential Set a connection's credential directly (org link or --field/--stdin), preview or production
19786
20109
  pull Fetch hub config and write local files (also mirrors the linked production hub read-only)
19787
20110
  push Parse local files, show diff, sync to preview (creates hub if new)
19788
20111
  diff Dry-run diff of local files vs the platform (--production diffs vs the linked production hub)
19789
20112
  replicate Clone a hub into a new sibling preview (--label to name it)
19790
20113
  relabel Set a preview hub's label (--clear to remove it)
20114
+ publish Promote the preview to production (first publish clones it; subsequent runs sync changes)
20115
+ sync Alias of \`publish\` (not to be confused with sync-skills / sync-mcp)
19791
20116
  org create Create a new organization (you become its owner)
19792
20117
  org <pull|push|diff> Sync org-scoped resources as code (wayai-ws/org/)
19793
20118
  use <hub> Bind this worktree to a specific hub (UUID or folder name)
@@ -19813,7 +20138,7 @@ Commands:
19813
20138
 
19814
20139
  Flags:
19815
20140
  --yes, -y Skip confirmation prompts (useful for CI and scripting)
19816
- --hub <uuid|name> Target hub when the workspace has more than one (push, pull, diff, replicate, relabel)
20141
+ --hub <uuid|name> Target hub when the workspace has more than one (push, pull, diff, replicate, relabel, publish)
19817
20142
  --production Diff local preview files against the linked production hub (diff)
19818
20143
  --label <name> Preview label \u2014 for the new sibling (replicate) or a brand-new hub (push on create)
19819
20144
  --clear Remove the preview label (relabel)