@wayai/cli 0.3.137 → 0.3.139

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
@@ -447,11 +447,11 @@ function captureException2(error, context) {
447
447
  Sentry.captureException(error);
448
448
  });
449
449
  }
450
- function addApiBreadcrumb(method, path31) {
450
+ function addApiBreadcrumb(method, path36) {
451
451
  if (!initialized) return;
452
452
  Sentry.addBreadcrumb({
453
453
  category: "http",
454
- message: `${method} ${path31}`,
454
+ message: `${method} ${path36}`,
455
455
  level: "info"
456
456
  });
457
457
  }
@@ -905,8 +905,8 @@ var init_parseUtil = __esm({
905
905
  init_errors();
906
906
  init_en();
907
907
  makeIssue = (params) => {
908
- const { data, path: path31, errorMaps, issueData } = params;
909
- const fullPath = [...path31, ...issueData.path || []];
908
+ const { data, path: path36, errorMaps, issueData } = params;
909
+ const fullPath = [...path36, ...issueData.path || []];
910
910
  const fullIssue = {
911
911
  ...issueData,
912
912
  path: fullPath
@@ -1217,11 +1217,11 @@ var init_types = __esm({
1217
1217
  init_parseUtil();
1218
1218
  init_util();
1219
1219
  ParseInputLazyPath = class {
1220
- constructor(parent, value, path31, key) {
1220
+ constructor(parent, value, path36, key) {
1221
1221
  this._cachedPath = [];
1222
1222
  this.parent = parent;
1223
1223
  this.data = value;
1224
- this._path = path31;
1224
+ this._path = path36;
1225
1225
  this._key = key;
1226
1226
  }
1227
1227
  get path() {
@@ -4634,12 +4634,12 @@ function validateFollowupLinks(followups, label, ctx) {
4634
4634
  const linkTargets = /* @__PURE__ */ new Set();
4635
4635
  followups.forEach((followup, i) => {
4636
4636
  const ref = followup?.after_followup_id;
4637
- const path31 = ["followups", i, "after_followup_id"];
4637
+ const path36 = ["followups", i, "after_followup_id"];
4638
4638
  if (followup?.type !== "inactivity_after_before_event") {
4639
4639
  if (ref !== void 0) {
4640
4640
  ctx.addIssue({
4641
4641
  code: external_exports.ZodIssueCode.custom,
4642
- path: path31,
4642
+ path: path36,
4643
4643
  message: `kanban status ${label}: after_followup_id is only valid on inactivity_after_before_event followups (this one is ${followup?.type})`
4644
4644
  });
4645
4645
  }
@@ -4648,7 +4648,7 @@ function validateFollowupLinks(followups, label, ctx) {
4648
4648
  if (ref === void 0) {
4649
4649
  ctx.addIssue({
4650
4650
  code: external_exports.ZodIssueCode.custom,
4651
- path: path31,
4651
+ path: path36,
4652
4652
  message: `kanban status ${label}: inactivity_after_before_event requires after_followup_id naming the id of a before_event followup in the same status`
4653
4653
  });
4654
4654
  return;
@@ -4658,7 +4658,7 @@ function validateFollowupLinks(followups, label, ctx) {
4658
4658
  if (matches.length > 1) {
4659
4659
  ctx.addIssue({
4660
4660
  code: external_exports.ZodIssueCode.custom,
4661
- path: path31,
4661
+ path: path36,
4662
4662
  message: `kanban status ${label}: after_followup_id "${ref}" matches ${matches.length} followups \u2014 a link must name exactly one`
4663
4663
  });
4664
4664
  return;
@@ -4670,7 +4670,7 @@ function validateFollowupLinks(followups, label, ctx) {
4670
4670
  );
4671
4671
  ctx.addIssue({
4672
4672
  code: external_exports.ZodIssueCode.custom,
4673
- path: path31,
4673
+ path: path36,
4674
4674
  message: hasIdlessBeforeEvent ? `kanban status ${label}: after_followup_id "${ref}" matches no followup \u2014 a link target must declare an explicit id, and this status has before_event followups without one` : `kanban status ${label}: after_followup_id "${ref}" matches no followup in this status`
4675
4675
  });
4676
4676
  return;
@@ -4678,7 +4678,7 @@ function validateFollowupLinks(followups, label, ctx) {
4678
4678
  if (target.type !== "before_event") {
4679
4679
  ctx.addIssue({
4680
4680
  code: external_exports.ZodIssueCode.custom,
4681
- path: path31,
4681
+ path: path36,
4682
4682
  message: `kanban status ${label}: after_followup_id "${ref}" points at a ${target.type} followup \u2014 only before_event followups can anchor a chain`
4683
4683
  });
4684
4684
  }
@@ -4754,12 +4754,12 @@ function typeMatches(typeField, allowed) {
4754
4754
  if (Array.isArray(typeField)) return typeField.every((t) => typeof t === "string" && allowed.has(t));
4755
4755
  return false;
4756
4756
  }
4757
- function validateSchema(schema, path31, errors, opts = {}) {
4757
+ function validateSchema(schema, path36, errors, opts = {}) {
4758
4758
  if (typeof schema === "boolean") return;
4759
4759
  const depth = opts.depth ?? 0;
4760
4760
  if (depth > MAX_SCHEMA_DEPTH) {
4761
4761
  errors.push({
4762
- path: path31 || "<root>",
4762
+ path: path36 || "<root>",
4763
4763
  message: `schema nesting exceeds ${MAX_SCHEMA_DEPTH} levels`,
4764
4764
  suggestion: "Flatten the schema; LLM providers reject deeply nested tool input_schemas."
4765
4765
  });
@@ -4767,7 +4767,7 @@ function validateSchema(schema, path31, errors, opts = {}) {
4767
4767
  }
4768
4768
  if (!isRecord(schema)) {
4769
4769
  errors.push({
4770
- path: path31,
4770
+ path: path36,
4771
4771
  message: `expected object, got ${schema === null ? "null" : typeof schema}`
4772
4772
  });
4773
4773
  return;
@@ -4775,14 +4775,14 @@ function validateSchema(schema, path31, errors, opts = {}) {
4775
4775
  if (opts.isRoot) {
4776
4776
  if ("type" in schema && schema.type !== "object") {
4777
4777
  errors.push({
4778
- path: path31 ? `${path31}.type` : "type",
4778
+ path: path36 ? `${path36}.type` : "type",
4779
4779
  message: `root type must be 'object', got ${JSON.stringify(schema.type)}`,
4780
4780
  suggestion: "Tool parameters at the root must be an object: `{ type: 'object', properties: { ... } }`."
4781
4781
  });
4782
4782
  }
4783
4783
  } else if ("type" in schema && !typeMatches(schema.type, ALLOWED_TYPES)) {
4784
4784
  errors.push({
4785
- path: `${path31}.type`,
4785
+ path: `${path36}.type`,
4786
4786
  message: `type must be one of ${[...ALLOWED_TYPES].join("/")} or an array of those, got ${JSON.stringify(schema.type)}`
4787
4787
  });
4788
4788
  }
@@ -4792,25 +4792,25 @@ function validateSchema(schema, path31, errors, opts = {}) {
4792
4792
  const isPlaceholder = PLACEHOLDER_TOKENS.includes(e);
4793
4793
  const isOutcomePlaceholder = e === "[KANBAN_OUTCOME_VALUES]";
4794
4794
  errors.push({
4795
- path: `${path31}.enum`,
4795
+ path: `${path36}.enum`,
4796
4796
  message: `enum must be a non-empty array of primitives, got string ${JSON.stringify(e)}`,
4797
4797
  suggestion: isOutcomePlaceholder ? "Declare `outcomes` on the hub's terminal kanban status so the platform can render the placeholder into a valid array; with none configured the platform drops the parameter instead." : 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"]`.'
4798
4798
  });
4799
4799
  } else if (!Array.isArray(e)) {
4800
4800
  errors.push({
4801
- path: `${path31}.enum`,
4801
+ path: `${path36}.enum`,
4802
4802
  message: `enum must be a non-empty array of primitives, got ${typeof e}`
4803
4803
  });
4804
4804
  } else if (e.length === 0) {
4805
4805
  errors.push({
4806
- path: `${path31}.enum`,
4806
+ path: `${path36}.enum`,
4807
4807
  message: "enum must not be empty"
4808
4808
  });
4809
4809
  } else {
4810
4810
  for (let i = 0; i < e.length; i++) {
4811
4811
  if (!isPrimitive(e[i])) {
4812
4812
  errors.push({
4813
- path: `${path31}.enum[${i}]`,
4813
+ path: `${path36}.enum[${i}]`,
4814
4814
  message: `enum entry must be a primitive (string/number/boolean/null), got ${typeof e[i]}`
4815
4815
  });
4816
4816
  }
@@ -4820,7 +4820,7 @@ function validateSchema(schema, path31, errors, opts = {}) {
4820
4820
  for (const key of ["exclusiveMinimum", "exclusiveMaximum"]) {
4821
4821
  if (key in schema && typeof schema[key] === "boolean") {
4822
4822
  errors.push({
4823
- path: `${path31}.${key}`,
4823
+ path: `${path36}.${key}`,
4824
4824
  message: `${key} as boolean is draft-04 syntax; draft 2020-12 requires a numeric value`,
4825
4825
  suggestion: `Replace with the numeric bound, e.g. \`${key}: 0\`.`
4826
4826
  });
@@ -4829,45 +4829,45 @@ function validateSchema(schema, path31, errors, opts = {}) {
4829
4829
  if ("properties" in schema) {
4830
4830
  if (!isRecord(schema.properties)) {
4831
4831
  errors.push({
4832
- path: `${path31}.properties`,
4832
+ path: `${path36}.properties`,
4833
4833
  message: `properties must be an object, got ${Array.isArray(schema.properties) ? "array" : typeof schema.properties}`
4834
4834
  });
4835
4835
  } else {
4836
4836
  for (const [propName, propSchema] of Object.entries(schema.properties)) {
4837
- validateSchema(propSchema, `${path31}.properties.${propName}`, errors, { depth: depth + 1 });
4837
+ validateSchema(propSchema, `${path36}.properties.${propName}`, errors, { depth: depth + 1 });
4838
4838
  }
4839
4839
  }
4840
4840
  }
4841
4841
  if (schemaTypeIncludes(schema, "array") && "items" in schema) {
4842
4842
  if (Array.isArray(schema.items)) {
4843
- schema.items.forEach((sub, i) => validateSchema(sub, `${path31}.items[${i}]`, errors, { depth: depth + 1 }));
4843
+ schema.items.forEach((sub, i) => validateSchema(sub, `${path36}.items[${i}]`, errors, { depth: depth + 1 }));
4844
4844
  } else {
4845
- validateSchema(schema.items, `${path31}.items`, errors, { depth: depth + 1 });
4845
+ validateSchema(schema.items, `${path36}.items`, errors, { depth: depth + 1 });
4846
4846
  }
4847
4847
  }
4848
4848
  for (const key of SUBSCHEMA_OBJECT_KEYWORDS) {
4849
4849
  if (key in schema && isRecord(schema[key])) {
4850
- validateSchema(schema[key], `${path31}.${key}`, errors, { depth: depth + 1 });
4850
+ validateSchema(schema[key], `${path36}.${key}`, errors, { depth: depth + 1 });
4851
4851
  }
4852
4852
  }
4853
4853
  for (const key of SUBSCHEMA_LIST_KEYWORDS) {
4854
4854
  const list = schema[key];
4855
4855
  if (Array.isArray(list)) {
4856
- list.forEach((sub, i) => validateSchema(sub, `${path31}.${key}[${i}]`, errors, { depth: depth + 1 }));
4856
+ list.forEach((sub, i) => validateSchema(sub, `${path36}.${key}[${i}]`, errors, { depth: depth + 1 }));
4857
4857
  }
4858
4858
  }
4859
4859
  for (const key of SUBSCHEMA_MAP_KEYWORDS) {
4860
4860
  const map = schema[key];
4861
4861
  if (isRecord(map)) {
4862
4862
  for (const [name, sub] of Object.entries(map)) {
4863
- validateSchema(sub, `${path31}.${key}.${name}`, errors, { depth: depth + 1 });
4863
+ validateSchema(sub, `${path36}.${key}.${name}`, errors, { depth: depth + 1 });
4864
4864
  }
4865
4865
  }
4866
4866
  }
4867
4867
  const reportedPaths = new Set(errors.map((e) => e.path));
4868
4868
  for (const [k, v] of Object.entries(schema)) {
4869
4869
  if (typeof v !== "string") continue;
4870
- const fieldPath = `${path31}.${k}`;
4870
+ const fieldPath = `${path36}.${k}`;
4871
4871
  if (reportedPaths.has(fieldPath)) continue;
4872
4872
  for (const token of PLACEHOLDER_TOKENS) {
4873
4873
  if (v === token) {
@@ -5012,8 +5012,8 @@ function evalInitialStateError(input) {
5012
5012
  const parsed = evalInitialStateEntry.safeParse(entries[i]);
5013
5013
  if (!parsed.success) {
5014
5014
  const issue = parsed.error.issues[0];
5015
- const path31 = issue?.path.join(".") || "?";
5016
- return `initial_state[${i}].${path31} is invalid: ${issue?.message ?? "malformed"}`;
5015
+ const path36 = issue?.path.join(".") || "?";
5016
+ return `initial_state[${i}].${path36} is invalid: ${issue?.message ?? "malformed"}`;
5017
5017
  }
5018
5018
  if (seenSlugs.has(parsed.data.slug)) {
5019
5019
  return `initial_state[${i}].slug "${parsed.data.slug}" is declared more than once`;
@@ -5201,10 +5201,10 @@ function refineHubAsCodeEvals(config, ctx) {
5201
5201
  function refineHubAsCodeEvalAttachments(config, ctx) {
5202
5202
  const cfg = config;
5203
5203
  const referencedHashes = /* @__PURE__ */ new Set();
5204
- const addTurnIssue = (path31, turn, name) => {
5204
+ const addTurnIssue = (path36, turn, name) => {
5205
5205
  const error = evalTurnAttachmentsError(turn);
5206
5206
  if (error) {
5207
- ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: path31, message: `${name}: ${error}` });
5207
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: path36, message: `${name}: ${error}` });
5208
5208
  return;
5209
5209
  }
5210
5210
  for (const hash of collectTurnAttachmentHashes(turn)) referencedHashes.add(hash);
@@ -5350,11 +5350,11 @@ function refineHubAsCodeDelegation(config, ctx) {
5350
5350
  }
5351
5351
  }
5352
5352
  if (del.context_boundary === void 0) return;
5353
- const path31 = ["agents", agentIndex, "tools", "delegation", delIndex, "context_boundary"];
5353
+ const path36 = ["agents", agentIndex, "tools", "delegation", delIndex, "context_boundary"];
5354
5354
  if (del.type !== "hub") {
5355
5355
  ctx.addIssue({
5356
5356
  code: external_exports.ZodIssueCode.custom,
5357
- path: path31,
5357
+ path: path36,
5358
5358
  message: `context_boundary applies only to \`type: hub\` delegations (got type "${String(del.type)}")`
5359
5359
  });
5360
5360
  return;
@@ -5362,14 +5362,14 @@ function refineHubAsCodeDelegation(config, ctx) {
5362
5362
  if (!CONTEXT_BOUNDARIES.includes(del.context_boundary)) {
5363
5363
  ctx.addIssue({
5364
5364
  code: external_exports.ZodIssueCode.custom,
5365
- path: path31,
5365
+ path: path36,
5366
5366
  message: `context_boundary must be one of: ${CONTEXT_BOUNDARIES.join(", ")}`
5367
5367
  });
5368
5368
  }
5369
5369
  });
5370
5370
  });
5371
5371
  }
5372
- var uuidSchema, paginationSchema, timestampSchema, idParamSchema, clientOptionalString, clientOptionalBoolean, clientOptionalNumber, messageAttachment, MAX_MESSAGE_BODY_BYTES, MAX_ATTACHMENTS_PER_MESSAGE, MAX_AUDIO_FILE_BASE64_BYTES, primaryRegionSchema, placementSourceSchema, orgIdParam, orgAdminIdParam, createOrganizationBody, updateOrganizationBody, addOrgAdminBody, AUTH_TYPE, ORG_CREDENTIAL_AUTH_TYPES, AUTH_TYPE_DISPLAY, LEGACY_AUTH_TYPE_MAP, VALID_AUTH_TYPES, AGENT_ROLES, SAFE_USER_ID_REGEX, SUPPORTED_LOCALES, SUMMARIZATION_THRESHOLD_MIN, SUMMARIZATION_THRESHOLD_MAX, PREVIOUS_CONVERSATIONS_MAX, previousConversationsCountField, 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, followupTypeSchema, EVENT_RELATIVE_FOLLOWUP_TYPES, followupTimeUnitSchema, followupIdSchema, SELECTABLE_FOLLOWUP_TYPES, MAX_LINKED_FOLLOWUP_TARGETS_PER_STATUS, followupSchema, MAX_OUTCOMES_PER_STATUS, kanbanOutcomeSchema, EXCLUSIVE_FLAG_PAIRS, kanbanStatusSchema, kanbanStatusesArraySchema, laneSchema, lanesArraySchema, hubIdParam, hubAdminIdParam, hubUserIdParam, hubIdentityIdParam, hubTeamIdParam, hubTeamUserDeleteParam, hubSchemaQuery, PREVIEW_LABEL_MAX_LENGTH, MAX_ENDED_INDEX_RETENTION_DAYS, MAX_EVAL_RETENTION_DAYS, previewLabelField, createHubBody, updateHubBody, addHubAdminBody, addHubIdentityAuthorizationBody, contactDecisionBody, approveContactBody, listContactAccessQuery, createHubTeamBody, updateHubTeamBody, addHubTeamUserBody, reassignHubUserBody, replicatePreviewBody, updateChannelTestIdentitiesBody, claimCodeChannelParam, claimCodeDeleteParam, connectionIdParam, connectorIdParam, listConnectionsQuery, deleteConnectionQuery, addConnectionBody, editConnectionBody, PRODUCTION_DIRECT_FIELDS, setProductionCredentialBody, registerWhatsappQuery, registerWhatsappBody, retryProvisioningQuery, resendDomainStatusQuery, PLACEHOLDER_TOKENS, ALLOWED_TYPES, SUBSCHEMA_OBJECT_KEYWORDS, SUBSCHEMA_LIST_KEYWORDS, SUBSCHEMA_MAP_KEYWORDS, MAX_SCHEMA_DEPTH, toolIdParam, listToolsQuery, toolAgentQuery, deleteToolQuery, toolConnectionsQuery, nativeToolIdSchema, CONTEXT_BOUNDARIES, contextBoundarySchema, addNativeToolBody, addMcpToolBody, createCustomToolBody, updateCustomToolBody, updateToolExecutionConfigBody, initialValueCreateSchema, initialValueUpdateSchema, stateIdParam, listStatesQuery, stateNameSchema, createStateBody, updateStateBody, reorderStatesBody, variantAiModeSchema, experimentStatusSchema, overlayUpdateSchema, experimentIdParam, variantIdParam, listExperimentsQuery, listVariantsQuery, listOverridesQuery, deleteOverrideQuery, createExperimentBody, updateExperimentBody, setExperimentStatusBody, createVariantBody, updateVariantBody, upsertOverrideBody, orgTagIdParam, listOrgTagsQuery, createOrgTagBody, updateOrgTagBody, orgCredentialIdParam, listOrgCredentialsQuery, createOrgCredentialBody, updateOrgCredentialBody, orgResourceIdParam, orgResourceFileIdParam, orgResourceFolderIdParam, hubOrgResourceParam, listOrgResourcesQuery, orgIdQuery, createOrgResourceBody, updateOrgResourceBody, createOrgResourceFolderBody, updateOrgResourceFolderBody, uploadOrgResourceFileBody, updateOrgResourceFileBody, uploadOrgSkillZipBody, linkOrgResourceBody, resourceIdParam, listResourcesQuery, createResourceBody, updateResourceBody, syncSkillsBody, resourceFileIdParam, listResourceFilesQuery, createResourceFileBody, updateResourceFileBody, uploadResourceFileBody, uploadSkillZipBody, resourceFolderIdParam, listResourceFoldersQuery, createResourceFolderBody, updateResourceFolderBody, agentResourceQuery, hubResourceQuery, linkAgentResourceBody, updateAgentResourceBody, unlinkAgentResourceQuery, navItemSchema, hubCountResetBody, navItemCountResetBody, typingBody, analyticsHubIdParam, analyticsVariableIdParam, updateVariablePinBody, updateAnalyticsViewBody, NUMERIC_FILTER_OPS, TEXT_FILTER_OPS, CATEGORICAL_FILTER_OPS, VARIABLE_FILTER_OPS, STRUCTURED_QUERY_OPS, STRUCTURED_QUERY_AGGREGATIONS, filterValueSchema, conversationsBody, analyticsConversationIdParam, messagesQuery, conversationDetailDataQuery, analyticsDataBody, structuredQueryBody, analyticsSqlBody, analyticsSqlTable, analyticsSqlSchemaQuery, EVAL_PACING_PRESET_NAMES, PACING_INTERVAL_MIN_MS, PACING_INTERVAL_MAX_MS, EVAL_MAX_RUNS_PER_SCENARIO, EVAL_RUN_DEADLINE_MIN_MS, EVAL_RUN_DEADLINE_MAX_MS, ISO_UTC_RE, paginationSchema2, evalIdParam, sessionIdParam, scenarioSetIdParam, hubIdQuery, evalDateContextSchema, EVAL_FIXTURE_NAME_MAX_LENGTH, evalFixtureOverrideSchema, runSessionQuery, EVAL_INPUT_ROLES, EVAL_INPUT_ROLE_LIST, ROLE_ECHO_MAX, EVAL_INITIAL_STATE_SCOPES, MAX_INITIAL_STATE_ENTRIES, evalInitialStateEntry, createEvalBody, updateEvalBody, EVAL_LIST_MAX_LIMIT, evalListLimit, getEvalsQuery, toggleEvalBody, bulkToggleEvalsBody, pacingConfigSchema, EVAL_MAX_SELECTED_SCENARIOS, evalScenarioSelectionEntrySchema, evalScenarioSelectionSchema, sessionConfigSchema, createSessionBody, getSessionsQuery, getSessionResultsQuery, getSessionRunsQuery, evalAnalyticsQuery, getSessionCostQuery, compareSessionsQuery, evalsSqlBody, evalsSqlSchemaQuery, exportResultsQuery, validateEvalBody, hubAgentsQuery, createScenarioSetBody, updateScenarioSetBody, scenarioSetsHubQuery, createScenarioFromConversationBody, createJourneyFromConversationBody, EVAL_ATTACHMENT_HASH_REGEX, evalAttachmentRef, turnMayCarryAttachments, ATTACHMENTS_USER_ONLY_MESSAGE, journeyIdParam, journeyToolCallSchema, journeyTurnSchema, journeyStepOverrideSchema, fixtureField, createJourneyBody, updateJourneyBody, evalSessionConfigResponseSchema, evalSessionResponseSchema, evalSessionListConfigSchema, evalSessionListItemSchema, seedReleaseStatusSchema, EVAL_SESSION_NOT_QUIESCENT, getConversationsQuery, getMessagesQuery, appMessageSenderType, appMessageReceiverType, apiChannelMessage, apiChannelMessageBody, appMessageBody, appMessageResponse, updateUserBody, updateProfileBody, pathnameRegex, updatePreferencesBody, registerPushTokenBody, deletePushTokenQuery, activityQuery, deletionModeSchema, deletionRequestBody, archiveHubIdParam, archiveConversationParams, archiveListQuery, archiveMessageObservabilityParams, conversationIdParam, claimBody, releaseBody, transferBody, closeBody, additionalContextPayloadSchema, kanbanUpdateBody, annotateConversationBody, observabilityParams, observabilityListParams, deleteUserConversationsBody, deleteUserConversationsResponse, sendMessageBody, listConversationsQuery, flagSourceSchema, getConversationsResponse, getConversationDetailParams, getConversationDetailQuery, getConversationDetailResponse, listWhatsAppTemplatesQuery, sendWhatsAppTemplateBody, copilotSuggestBody, copilotSuggestResponse, CONSULT_THREAD_STATUSES, consultThreadStatus, CONSULT_THREAD_TITLE_MAX, consultThreadTitle, consultThreadSummary, listConsultThreadsQuery, listConsultThreadsResponse, createConsultThreadBody, createConsultThreadResponse, consultThreadIdParam, updateConsultThreadBody, updateConsultThreadResponse, CONSULT_AWAIT_TIMEOUT_MS, billingOrgIdParam, subscriptionItemParams, spendCapBody, growthPacksBody, portalSessionBody, checkoutSessionBody, updateBillingCurrencyBody, invoicesQuery, planKeySchema, billingStatusSchema, REKOR_ENTITLEMENT_CONTRACT_VERSION, entitlementProjectionSchema, rekorEntitlementRefreshMessageSchema, downloadBody, uploadQuery, signUrlBody, outboundSchemaQuery, templateIdParam, listTemplatesQuery, deleteTemplateQuery, templateStatusQuery, createTemplateBody, updateTemplateBody, submitTemplateBody, testTemplateBody, contactIdParam, listContactsQuery, createContactBody, updateContactBody, listIdParam, listListsQuery, listListContactsQuery, createListBody, updateListBody, addListContactsBody, removeListContactsBody, scheduleIdParam, listSchedulesQuery, listExecutionsQuery, createScheduleBody, updateScheduleBody, MAX_RESOURCE_FILE_SIZE, MAX_10MB_BASE64_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_CARRIERS, MAX_EVAL_ATTACHMENT_AGGREGATE_ENCODED_BYTES, MAX_RESOURCE_ENCODED_BYTES, MAX_HUB_AS_CODE_RESOURCES, MAX_HUB_AS_CODE_RESOURCE_FILES, MAX_RESOURCE_AGGREGATE_ENCODED_BYTES, MAX_CI_CONFIG_BODY_BYTES, hubAsCodeStateSchema, hubAsCodeResourceFileSchema, hubAsCodeResourceSchema, uuidPattern, ciUuidSchema, boundedHubAsCodeResourcesSchema, hubAsCodeConfigSchema, ciPullHubIdParam, ciBranchParam, ciPullQuery, ciHubsQuery, ciLookupQuery, ciBranchesQuery, ciSyncBody, ciPushBody, ciDiffBody, ciPublishBody, ciPublishPreviewBody, ciSyncMcpBody, ciOrgResourcesParam, orgResourcesConfigSchema, ciOrgResourcesPushBody, ciOrgResourcesDiffBody, CI_APPLY_ENTITY_KINDS, CI_APPLY_OPERATIONS, ciApplyErrorBaseSchema, ciApplyErrorSchema, ciSyncCountSchema, ciSyncChangesSchema, ciSyncWarningSchema, ciSyncResponseSchema, adminOrgIdParam, adminOrgAdminIdParam, adminUserIdParam, adminPlanIdParam, adminOrganizationsQuery, adminUserSearchQuery, kanbanSlugMigrationQuery, adjustQuotaBody, updatePlanBody, addAdminUserBody, updatePlatformConfigBody, updateFreeOrgLimitBody, adminScopedTargetBody, updatePricingPlanBody, dataExplorerSearchQuery, dataExplorerOrgIdParam, dataExplorerHubIdParam, dataExplorerConvIdParam, dataExplorerDoInstancesQuery, dataExplorerNsIdParam, dataExplorerKvKeysBody, dataExplorerKvKeyBody, uuidOrHexId, dataExplorerDeleteOrgParam, dataExplorerDeleteHubParam, dataExplorerDeleteConvParam, dataExplorerDeleteUserParam, dataExplorerDeleteQuery, dataExplorerKvDeleteBody, pitrDoNamespace, pitrBookmarkParam, pitrRestoreBody, healthSamplingTriggerBody, dataExplorerDebugDoType, DEBUG_READ_MAX_LIMIT, DEBUG_READ_DEFAULT_LIMIT, DEBUG_DO_HEX_PREFIX, debugDoEntityId, debugTableName, dataExplorerDebugTablesParam, dataExplorerDebugRowsParam, dataExplorerDebugRowsQuery, dataExplorerDebugAnalyticsTable, debugUuid, dataExplorerDebugAnalyticsRowsParam, dataExplorerDebugAnalyticsRowsQuery, debugHubConvParam, debugMessageIdQuery, sandboxEgressPolicy, SANDBOX_EXEC_MAX_CMD_LENGTH, SANDBOX_EXEC_MAX_ALLOWLIST, SANDBOX_EXEC_MAX_TIMEOUT_MS, adminSandboxExecBody, whatsappCallbackBody, authMeResponse, wsTicketResponse, sessionCheckResponse, logoutResponse, magicCodeSendBody, magicCodeSendResponse, magicCodeVerifyBody, magicCodeVerifyResponse, passwordLoginBody, browserParams, browserFoldersQuery, browserFilesQuery, stateOperationBody, conversationListResourcesQuery, conversationReadResourceQuery, listPendingSchedulesQuery, listHubAggregateSchedulesQuery, reportSourceSchema, intakeReportSourceSchema, reportClassificationSchema, reportStatusSchema, reportLocaleSchema, reportMessageAuthorRoleSchema, reportMessageSchema, sentryRefStatusSchema, createReportBody, editReportBody, reporterReportSummarySchema, reporterListResponseSchema, getReportResponseSchema, reporterTransitionResponseSchema, contestReportBody, reporterListQuery, listReportsQuery, GITHUB_ISSUE_URL_REGEX, githubIssueUrlSchema, transitionReportBody, groupReportsBody, holdReportBody, clickhouseReadyResponse, bootstrapQuery, requestSnapshotChunkMessage, MAX_NAME_LENGTH, MAX_VALUE_LENGTH, MAX_TAGS, MAX_TAG_LENGTH, MAX_SCOPE_HUBS, MAX_SCOPE_TAGS, vaultSecretScopeSchema, vaultCreateBody, vaultUpdateBody, PERMISSIONS, MAX_NAME_LENGTH2, MAX_HUBS_PER_GRANT, MAX_HUB_TAGS_PER_GRANT, MAX_GRANTS, permissionEnum, grantScopeSchema, grantSchema, createTokenBody, tokenOrgIdParam, tokenGrantScopeSchema, tokenGrantSchema, tokenMetadataSchema, listTokensResponse, createTokenResponse, orgTokenSummarySchema, listOrgTokensResponse, invitePreviewQuery, invitePreviewResponse, jsonSchemaSchema, hubUserIdentity, stateValueEntry, getHubUserContextResponse, updateHubUserBody, updateHubUserResponse, unlockHubUserNameResponse, stateResetParams, stateResetResponse, hubAlertsParam, hubAlertSeverity, hubAlert, hubAlertsListResponse, noticeSeveritySchema, noticeStatusSchema, NOTICE_SCOPE_REGEX, noticeScopeSchema, noticeLinkSchema, createNoticeBody, updateNoticeBody, listNoticesQuery, noticeIdParamSchema, ADMIN_SKILL_NAME_REGEX, adminSkillNameParam, REKOR_ACTOR_TYPE_HEADER, REKOR_ACTOR_ID_HEADER, REKOR_ACTOR_LABEL_HEADER, REKOR_ACTOR_ORG_HEADER, REKOR_ACTOR_ADMIN_HEADER, REKOR_CLIENT_HEADER, REKOR_TOOL_ID_HEADER, REKOR_CLIENTS, rekorClientSchema, MAX_REKOR_TOOL_ID_LENGTH, rekorToolIdSchema, DATA_PROXY_MOUNT, DATA_PROXY_PREFIX, REKOR_V1_PREFIX, DATA_PROXY_ORG_QUERY_PARAM, dataProxyQuery, rekorAttestation, REQUIRED_REKOR_ATTESTATION_HEADERS;
5372
+ var uuidSchema, paginationSchema, timestampSchema, idParamSchema, clientOptionalString, clientOptionalBoolean, clientOptionalNumber, messageAttachment, MAX_MESSAGE_BODY_BYTES, MAX_ATTACHMENTS_PER_MESSAGE, MAX_AUDIO_FILE_BASE64_BYTES, primaryRegionSchema, placementSourceSchema, orgIdParam, orgAdminIdParam, createOrganizationBody, updateOrganizationBody, addOrgAdminBody, AUTH_TYPE, ORG_CREDENTIAL_AUTH_TYPES, AUTH_TYPE_DISPLAY, LEGACY_AUTH_TYPE_MAP, VALID_AUTH_TYPES, AGENT_ROLES, SAFE_USER_ID_REGEX, SUPPORTED_LOCALES, SUMMARIZATION_THRESHOLD_MIN, SUMMARIZATION_THRESHOLD_MAX, PREVIOUS_CONVERSATIONS_MAX, previousConversationsCountField, 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, followupTypeSchema, EVENT_RELATIVE_FOLLOWUP_TYPES, followupTimeUnitSchema, followupIdSchema, SELECTABLE_FOLLOWUP_TYPES, MAX_LINKED_FOLLOWUP_TARGETS_PER_STATUS, followupSchema, MAX_OUTCOMES_PER_STATUS, kanbanOutcomeSchema, EXCLUSIVE_FLAG_PAIRS, kanbanStatusSchema, kanbanStatusesArraySchema, laneSchema, lanesArraySchema, hubIdParam, hubAdminIdParam, hubUserIdParam, hubIdentityIdParam, hubTeamIdParam, hubTeamUserDeleteParam, hubSchemaQuery, PREVIEW_LABEL_MAX_LENGTH, MAX_ENDED_INDEX_RETENTION_DAYS, MAX_EVAL_RETENTION_DAYS, previewLabelField, createHubBody, updateHubBody, addHubAdminBody, addHubIdentityAuthorizationBody, contactDecisionBody, approveContactBody, listContactAccessQuery, createHubTeamBody, updateHubTeamBody, addHubTeamUserBody, reassignHubUserBody, replicatePreviewBody, updateChannelTestIdentitiesBody, claimCodeChannelParam, claimCodeDeleteParam, connectionIdParam, connectorIdParam, listConnectionsQuery, deleteConnectionQuery, addConnectionBody, editConnectionBody, PRODUCTION_DIRECT_FIELDS, setProductionCredentialBody, registerWhatsappQuery, registerWhatsappBody, retryProvisioningQuery, resendDomainStatusQuery, PLACEHOLDER_TOKENS, ALLOWED_TYPES, SUBSCHEMA_OBJECT_KEYWORDS, SUBSCHEMA_LIST_KEYWORDS, SUBSCHEMA_MAP_KEYWORDS, MAX_SCHEMA_DEPTH, toolIdParam, listToolsQuery, toolAgentQuery, deleteToolQuery, toolConnectionsQuery, nativeToolIdSchema, CONTEXT_BOUNDARIES, contextBoundarySchema, addNativeToolBody, addMcpToolBody, createCustomToolBody, updateCustomToolBody, updateToolExecutionConfigBody, initialValueCreateSchema, initialValueUpdateSchema, stateIdParam, listStatesQuery, stateNameSchema, createStateBody, updateStateBody, reorderStatesBody, variantAiModeSchema, experimentStatusSchema, overlayUpdateSchema, experimentIdParam, variantIdParam, listExperimentsQuery, listVariantsQuery, listOverridesQuery, deleteOverrideQuery, createExperimentBody, updateExperimentBody, setExperimentStatusBody, createVariantBody, updateVariantBody, upsertOverrideBody, orgTagIdParam, listOrgTagsQuery, createOrgTagBody, updateOrgTagBody, orgCredentialIdParam, listOrgCredentialsQuery, createOrgCredentialBody, updateOrgCredentialBody, orgResourceIdParam, orgResourceFileIdParam, orgResourceFolderIdParam, hubOrgResourceParam, listOrgResourcesQuery, orgIdQuery, createOrgResourceBody, updateOrgResourceBody, createOrgResourceFolderBody, updateOrgResourceFolderBody, uploadOrgResourceFileBody, updateOrgResourceFileBody, uploadOrgSkillZipBody, linkOrgResourceBody, resourceIdParam, listResourcesQuery, createResourceBody, updateResourceBody, syncSkillsBody, resourceFileIdParam, listResourceFilesQuery, createResourceFileBody, updateResourceFileBody, uploadResourceFileBody, uploadSkillZipBody, resourceFolderIdParam, listResourceFoldersQuery, createResourceFolderBody, updateResourceFolderBody, agentResourceQuery, hubResourceQuery, linkAgentResourceBody, updateAgentResourceBody, unlinkAgentResourceQuery, navItemSchema, hubCountResetBody, navItemCountResetBody, typingBody, analyticsHubIdParam, analyticsVariableIdParam, updateVariablePinBody, updateAnalyticsViewBody, NUMERIC_FILTER_OPS, TEXT_FILTER_OPS, CATEGORICAL_FILTER_OPS, VARIABLE_FILTER_OPS, STRUCTURED_QUERY_OPS, STRUCTURED_QUERY_AGGREGATIONS, filterValueSchema, conversationsBody, analyticsConversationIdParam, messagesQuery, conversationDetailDataQuery, analyticsDataBody, structuredQueryBody, analyticsSqlBody, analyticsSqlTable, analyticsSqlSchemaQuery, EVAL_PACING_PRESET_NAMES, PACING_INTERVAL_MIN_MS, PACING_INTERVAL_MAX_MS, EVAL_MAX_RUNS_PER_SCENARIO, EVAL_RUN_DEADLINE_MIN_MS, EVAL_RUN_DEADLINE_MAX_MS, ISO_UTC_RE, paginationSchema2, evalIdParam, sessionIdParam, scenarioSetIdParam, hubIdQuery, evalDateContextSchema, EVAL_FIXTURE_NAME_MAX_LENGTH, evalFixtureOverrideSchema, runSessionQuery, EVAL_INPUT_ROLES, EVAL_INPUT_ROLE_LIST, ROLE_ECHO_MAX, EVAL_INITIAL_STATE_SCOPES, MAX_INITIAL_STATE_ENTRIES, evalInitialStateEntry, createEvalBody, updateEvalBody, EVAL_LIST_MAX_LIMIT, evalListLimit, getEvalsQuery, toggleEvalBody, bulkToggleEvalsBody, pacingConfigSchema, EVAL_MAX_SELECTED_SCENARIOS, evalScenarioSelectionEntrySchema, evalScenarioSelectionSchema, sessionConfigSchema, createSessionBody, getSessionsQuery, getSessionResultsQuery, getSessionRunsQuery, evalAnalyticsQuery, getSessionCostQuery, compareSessionsQuery, evalsSqlBody, evalsSqlSchemaQuery, exportResultsQuery, validateEvalBody, hubAgentsQuery, createScenarioSetBody, updateScenarioSetBody, scenarioSetsHubQuery, createScenarioFromConversationBody, createJourneyFromConversationBody, EVAL_ATTACHMENT_HASH_REGEX, evalAttachmentRef, turnMayCarryAttachments, ATTACHMENTS_USER_ONLY_MESSAGE, journeyIdParam, journeyToolCallSchema, journeyTurnSchema, journeyStepOverrideSchema, fixtureField, createJourneyBody, updateJourneyBody, evalSessionConfigResponseSchema, evalSessionResponseSchema, evalSessionListConfigSchema, evalSessionListItemSchema, seedReleaseStatusSchema, EVAL_SESSION_NOT_QUIESCENT, getConversationsQuery, getMessagesQuery, appMessageSenderType, appMessageReceiverType, apiChannelMessage, apiChannelMessageBody, appMessageBody, appMessageResponse, updateUserBody, updateProfileBody, pathnameRegex, updatePreferencesBody, registerPushTokenBody, deletePushTokenQuery, activityQuery, deletionModeSchema, deletionRequestBody, archiveHubIdParam, archiveConversationParams, archiveListQuery, archiveMessageObservabilityParams, conversationIdParam, claimBody, releaseBody, transferBody, closeBody, additionalContextPayloadSchema, kanbanUpdateBody, annotateConversationBody, observabilityParams, observabilityListParams, deleteUserConversationsBody, deleteUserConversationsResponse, sendMessageBody, listConversationsQuery, flagSourceSchema, getConversationsResponse, getConversationDetailParams, getConversationDetailQuery, getConversationDetailResponse, listWhatsAppTemplatesQuery, sendWhatsAppTemplateBody, copilotSuggestBody, copilotSuggestResponse, CONSULT_THREAD_STATUSES, consultThreadStatus, CONSULT_THREAD_TITLE_MAX, consultThreadTitle, consultThreadSummary, listConsultThreadsQuery, listConsultThreadsResponse, createConsultThreadBody, createConsultThreadResponse, consultThreadIdParam, updateConsultThreadBody, updateConsultThreadResponse, CONSULT_AWAIT_TIMEOUT_MS, billingOrgIdParam, subscriptionItemParams, spendCapBody, growthPacksBody, portalSessionBody, checkoutSessionBody, updateBillingCurrencyBody, invoicesQuery, planKeySchema, billingStatusSchema, REKOR_ENTITLEMENT_CONTRACT_VERSION, entitlementProjectionSchema, rekorEntitlementRefreshMessageSchema, downloadBody, uploadQuery, signUrlBody, outboundSchemaQuery, templateIdParam, listTemplatesQuery, deleteTemplateQuery, templateStatusQuery, createTemplateBody, updateTemplateBody, submitTemplateBody, testTemplateBody, contactIdParam, listContactsQuery, createContactBody, updateContactBody, listIdParam, listListsQuery, listListContactsQuery, createListBody, updateListBody, addListContactsBody, removeListContactsBody, scheduleIdParam, listSchedulesQuery, listExecutionsQuery, createScheduleBody, updateScheduleBody, MAX_RESOURCE_FILE_SIZE, MAX_10MB_BASE64_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_ENCODED_BYTES, MAX_EVAL_ATTACHMENT_CARRIERS, MAX_EVAL_ATTACHMENT_AGGREGATE_ENCODED_BYTES, MAX_RESOURCE_ENCODED_BYTES, MAX_HUB_AS_CODE_RESOURCES, MAX_HUB_AS_CODE_RESOURCE_FILES, MAX_RESOURCE_AGGREGATE_ENCODED_BYTES, MAX_CI_CONFIG_BODY_BYTES, hubAsCodeStateSchema, hubAsCodeResourceFileSchema, hubAsCodeResourceSchema, uuidPattern, ciUuidSchema, boundedHubAsCodeResourcesSchema, hubAsCodeConfigSchema, ciPullHubIdParam, ciBranchParam, ciPullQuery, ciHubsQuery, ciLookupQuery, ciBranchesQuery, ciSyncBody, ciPushBody, ciDiffBody, ciPublishBody, ciPublishPreviewBody, ciSyncMcpBody, ciOrgResourcesParam, orgResourcesConfigSchema, ciOrgResourcesPushBody, ciOrgResourcesDiffBody, CI_APPLY_ENTITY_KINDS, CI_APPLY_OPERATIONS, ciApplyErrorBaseSchema, ciApplyErrorSchema, ciSyncCountSchema, ciSyncChangesSchema, ciSyncWarningSchema, ciSyncResponseSchema, adminOrgIdParam, adminOrgAdminIdParam, adminUserIdParam, PRICING_PLAN_ID_RE, adminPlanIdParam, adminOrganizationsQuery, adminUserSearchQuery, kanbanSlugMigrationQuery, adjustQuotaBody, updatePlanBody, addAdminUserBody, updatePlatformConfigBody, updateFreeOrgLimitBody, adminScopedTargetBody, adminRepairLegacyOrgGrantsBody, updatePricingPlanBody, dataExplorerSearchQuery, dataExplorerOrgIdParam, dataExplorerHubIdParam, dataExplorerConvIdParam, dataExplorerDoInstancesQuery, dataExplorerNsIdParam, dataExplorerKvKeysBody, dataExplorerKvKeyBody, uuidOrHexId, dataExplorerDeleteOrgParam, dataExplorerDeleteHubParam, dataExplorerDeleteConvParam, dataExplorerDeleteUserParam, dataExplorerDeleteQuery, dataExplorerKvDeleteBody, pitrDoNamespace, pitrBookmarkParam, pitrRestoreBody, healthSamplingTriggerBody, dataExplorerDebugDoType, DEBUG_READ_MAX_LIMIT, DEBUG_READ_DEFAULT_LIMIT, DEBUG_DO_HEX_PREFIX, debugDoEntityId, debugTableName, dataExplorerDebugTablesParam, dataExplorerDebugRowsParam, dataExplorerDebugRowsQuery, dataExplorerDebugAnalyticsTable, debugUuid, dataExplorerDebugAnalyticsRowsParam, dataExplorerDebugAnalyticsRowsQuery, debugHubConvParam, debugMessageIdQuery, sandboxEgressPolicy, SANDBOX_EXEC_MAX_CMD_LENGTH, SANDBOX_EXEC_MAX_ALLOWLIST, SANDBOX_EXEC_MAX_TIMEOUT_MS, adminSandboxExecBody, whatsappCallbackBody, authMeResponse, wsTicketResponse, sessionCheckResponse, logoutResponse, magicCodeSendBody, magicCodeSendResponse, magicCodeVerifyBody, magicCodeVerifyResponse, passwordLoginBody, browserParams, browserFoldersQuery, browserFilesQuery, stateOperationBody, conversationListResourcesQuery, conversationReadResourceQuery, listPendingSchedulesQuery, listHubAggregateSchedulesQuery, reportSourceSchema, intakeReportSourceSchema, reportClassificationSchema, reportStatusSchema, reportLocaleSchema, reportMessageAuthorRoleSchema, reportMessageSchema, sentryRefStatusSchema, createReportBody, editReportBody, reporterReportSummarySchema, reporterListResponseSchema, getReportResponseSchema, reporterTransitionResponseSchema, contestReportBody, reporterListQuery, listReportsQuery, GITHUB_ISSUE_URL_REGEX, githubIssueUrlSchema, transitionReportBody, groupReportsBody, holdReportBody, clickhouseReadyResponse, bootstrapQuery, requestSnapshotChunkMessage, MAX_NAME_LENGTH, MAX_VALUE_LENGTH, MAX_TAGS, MAX_TAG_LENGTH, MAX_SCOPE_HUBS, MAX_SCOPE_TAGS, vaultSecretScopeSchema, vaultCreateBody, vaultUpdateBody, PERMISSIONS, MAX_NAME_LENGTH2, MAX_HUBS_PER_GRANT, MAX_HUB_TAGS_PER_GRANT, MAX_GRANTS, permissionEnum, grantScopeSchema, grantSchema, createTokenBody, tokenOrgIdParam, tokenGrantScopeSchema, tokenGrantSchema, tokenMetadataSchema, listTokensResponse, createTokenResponse, orgTokenSummarySchema, listOrgTokensResponse, invitePreviewQuery, invitePreviewResponse, jsonSchemaSchema, hubUserIdentity, stateValueEntry, getHubUserContextResponse, updateHubUserBody, updateHubUserResponse, unlockHubUserNameResponse, stateResetParams, stateResetResponse, hubAlertsParam, hubAlertSeverity, hubAlert, hubAlertsListResponse, noticeSeveritySchema, noticeStatusSchema, NOTICE_SCOPE_REGEX, noticeScopeSchema, noticeLinkSchema, createNoticeBody, updateNoticeBody, listNoticesQuery, noticeIdParamSchema, ADMIN_SKILL_NAME_REGEX, adminSkillNameParam, REKOR_ACTOR_TYPE_HEADER, REKOR_ACTOR_ID_HEADER, REKOR_ACTOR_LABEL_HEADER, REKOR_ACTOR_ORG_HEADER, REKOR_ACTOR_ADMIN_HEADER, REKOR_CLIENT_HEADER, REKOR_TOOL_ID_HEADER, REKOR_CLIENTS, rekorClientSchema, MAX_REKOR_TOOL_ID_LENGTH, rekorToolIdSchema, DATA_PROXY_MOUNT, DATA_PROXY_PREFIX, REKOR_V1_PREFIX, DATA_PROXY_ORG_QUERY_PARAM, MAX_PROVISIONING_BODY_BYTES, dataProxyQuery, rekorAttestation, REQUIRED_REKOR_ATTESTATION_HEADERS;
5373
5373
  var init_contracts = __esm({
5374
5374
  "../../packages/core/dist/contracts/index.js"() {
5375
5375
  "use strict";
@@ -7973,13 +7973,20 @@ var init_contracts = __esm({
7973
7973
  });
7974
7974
  adminOrgAdminIdParam = external_exports.object({
7975
7975
  orgId: uuidSchema,
7976
- adminId: uuidSchema
7976
+ // `adminId` is a `member_grant.user_id`, which for a logged-in user is the
7977
+ // WorkOS `sub` (`user_01…`), not a UUID. Matches `orgAdminIdParam` on the
7978
+ // org-facing route.
7979
+ adminId: external_exports.string().min(1)
7977
7980
  });
7978
7981
  adminUserIdParam = external_exports.object({
7979
7982
  userId: uuidSchema
7980
7983
  });
7984
+ PRICING_PLAN_ID_RE = /^pp-[a-z0-9]+(-[a-z0-9]+)*$/;
7981
7985
  adminPlanIdParam = external_exports.object({
7982
- planId: uuidSchema
7986
+ planId: external_exports.string().refine(
7987
+ (value) => PRICING_PLAN_ID_RE.test(value) || uuidSchema.safeParse(value).success,
7988
+ { message: 'planId must be a pricing plan id such as "pp-free", or a UUID' }
7989
+ )
7983
7990
  });
7984
7991
  adminOrganizationsQuery = external_exports.object({
7985
7992
  page: external_exports.coerce.number().int().min(1).default(1),
@@ -7998,8 +8005,33 @@ var init_contracts = __esm({
7998
8005
  value: external_exports.number().int().min(0, "value must be a non-negative number")
7999
8006
  });
8000
8007
  updatePlanBody = external_exports.object({
8001
- plan_type: external_exports.enum(["free", "paid"])
8002
- });
8008
+ plan_type: external_exports.enum(["free", "paid"]).optional(),
8009
+ /**
8010
+ * Move the start of the org's free-plan window. The operator lever for a window that
8011
+ * must be backdated — `free_plan_started_at` is otherwise only ever stamped to *now*
8012
+ * (org creation, `cancelBilling`, the lazy rollover), so an elapsed free window is
8013
+ * unreachable without it.
8014
+ *
8015
+ * Canonical form only (AGENTS.md › Timestamps): `timestampSchema` already refuses a
8016
+ * non-UTC offset and `isIsoTimestamp` pins the millisecond precision, because this
8017
+ * value is stored as-is and read back by `freePlanWindowStart()` / `freePlanWindowEnd()`
8018
+ * and by the Rekor projection's `window_start`.
8019
+ *
8020
+ * Past-or-now only. A future start freezes the org's window permanently:
8021
+ * `maybeRolloverFreePlanWindow` derives a NEGATIVE elapsed and so never archives the
8022
+ * metrics nor restamps the column, while the §2.6 trigger-5 sweep selects only windows
8023
+ * that have already passed — so nothing rolls the org over, its consumed operations
8024
+ * never reset, and past quota every AI turn is refused until a human re-patches.
8025
+ */
8026
+ free_plan_started_at: timestampSchema.refine(isIsoTimestamp, {
8027
+ message: "free_plan_started_at must be ISO-8601 UTC with millisecond precision (e.g. 2026-07-01T00:00:00.000Z)"
8028
+ }).refine((value) => Date.parse(value) <= Date.now(), {
8029
+ message: "free_plan_started_at must not be in the future"
8030
+ }).optional()
8031
+ }).strip().refine(
8032
+ (data) => Object.keys(data).length > 0,
8033
+ { message: "No fields to update" }
8034
+ );
8003
8035
  addAdminUserBody = external_exports.object({
8004
8036
  user_email: external_exports.string().email("user_email must be a valid email address")
8005
8037
  });
@@ -8058,6 +8090,18 @@ var init_contracts = __esm({
8058
8090
  }
8059
8091
  }
8060
8092
  });
8093
+ adminRepairLegacyOrgGrantsBody = external_exports.object({
8094
+ scope: external_exports.enum(["all", "org"]),
8095
+ org_id: external_exports.string().uuid().optional(),
8096
+ dry_run: external_exports.boolean().optional().default(false)
8097
+ }).strict().superRefine((data, ctx) => {
8098
+ if (data.scope === "org" && !data.org_id) {
8099
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "scope=org requires org_id", path: ["org_id"] });
8100
+ }
8101
+ if (data.scope === "all" && data.org_id) {
8102
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "scope=all must not include org_id", path: ["org_id"] });
8103
+ }
8104
+ });
8061
8105
  updatePricingPlanBody = external_exports.object({
8062
8106
  display_name: external_exports.string().min(1).optional(),
8063
8107
  stripe_product_id: external_exports.string().optional(),
@@ -8698,6 +8742,7 @@ var init_contracts = __esm({
8698
8742
  DATA_PROXY_PREFIX = `/api${DATA_PROXY_MOUNT}`;
8699
8743
  REKOR_V1_PREFIX = "/v1";
8700
8744
  DATA_PROXY_ORG_QUERY_PARAM = "org_id";
8745
+ MAX_PROVISIONING_BODY_BYTES = 256 * 1024;
8701
8746
  dataProxyQuery = external_exports.object({
8702
8747
  [DATA_PROXY_ORG_QUERY_PARAM]: external_exports.string().uuid().optional()
8703
8748
  });
@@ -8737,10 +8782,10 @@ function toDataProxyPath(v1Path) {
8737
8782
  }
8738
8783
  return `${DATA_PROXY_PREFIX}${v1Path.slice(REKOR_V1_PREFIX.length)}`;
8739
8784
  }
8740
- function withOrgSelector(path31, orgId) {
8741
- if (!orgId) return path31;
8742
- const separator = path31.includes("?") ? "&" : "?";
8743
- return `${path31}${separator}${DATA_PROXY_ORG_QUERY_PARAM}=${encodeURIComponent(orgId)}`;
8785
+ function withOrgSelector(path36, orgId) {
8786
+ if (!orgId) return path36;
8787
+ const separator = path36.includes("?") ? "&" : "?";
8788
+ return `${path36}${separator}${DATA_PROXY_ORG_QUERY_PARAM}=${encodeURIComponent(orgId)}`;
8744
8789
  }
8745
8790
  function dataErrorMessage(err) {
8746
8791
  if (!(err instanceof ApiError)) return null;
@@ -8764,7 +8809,7 @@ var init_api_client = __esm({
8764
8809
  init_sentry();
8765
8810
  init_mask_secrets();
8766
8811
  RETRYABLE_BACKOFF_MS = [500, 1e3, 2e3];
8767
- delay = (ms) => new Promise((resolve5) => setTimeout(resolve5, ms));
8812
+ delay = (ms) => new Promise((resolve7) => setTimeout(resolve7, ms));
8768
8813
  ApiError = class extends Error {
8769
8814
  status;
8770
8815
  body;
@@ -8774,13 +8819,13 @@ var init_api_client = __esm({
8774
8819
  * telling them apart by body shape misreads one for the other.
8775
8820
  */
8776
8821
  path;
8777
- constructor(method, path31, status, body) {
8822
+ constructor(method, path36, status, body) {
8778
8823
  const safeBody = maskSecretsInMessage(body);
8779
- super(`API request failed: ${method} ${path31} (${status}): ${safeBody}`);
8824
+ super(`API request failed: ${method} ${path36} (${status}): ${safeBody}`);
8780
8825
  this.name = "ApiError";
8781
8826
  this.status = status;
8782
8827
  this.body = safeBody;
8783
- this.path = path31;
8828
+ this.path = path36;
8784
8829
  }
8785
8830
  /** True when the status code is a 4xx client error (expected user-facing condition, not a bug). */
8786
8831
  get isExpected() {
@@ -8853,6 +8898,12 @@ var init_api_client = __esm({
8853
8898
  async adminRepairTeamOrphans(body) {
8854
8899
  return this.request("POST", "/api/admin/hubs/repair-team-orphans", body);
8855
8900
  }
8901
+ // Repair the roster rows the pre-#3922 platform-admin add wrote (email in the
8902
+ // `user_id` column, `user_email` NULL) — each one an inert phantom seat.
8903
+ // Used by `wayai admin orgs repair-legacy-grants` (platform-admin gated).
8904
+ async adminRepairLegacyOrgGrants(body) {
8905
+ return this.request("POST", "/api/admin/organizations/repair-legacy-grants", body);
8906
+ }
8856
8907
  // Read the platform config (platform-admin gated). Used by `wayai admin harness status`.
8857
8908
  async adminGetConfig() {
8858
8909
  return this.request("GET", "/api/admin/config");
@@ -8876,8 +8927,8 @@ var init_api_client = __esm({
8876
8927
  ...opts?.check && { check: true }
8877
8928
  });
8878
8929
  }
8879
- async lookup(path31, opts) {
8880
- const params = new URLSearchParams({ path: path31 });
8930
+ async lookup(path36, opts) {
8931
+ const params = new URLSearchParams({ path: path36 });
8881
8932
  if (opts?.organizationId) params.set("organization_id", opts.organizationId);
8882
8933
  return this.request("GET", `/api/ci/lookup?${params.toString()}`);
8883
8934
  }
@@ -9298,9 +9349,9 @@ var init_api_client = __esm({
9298
9349
  * sandbox for this conversation, or the blob was purged).
9299
9350
  */
9300
9351
  async downloadArchiveSandboxFs(hubId, conversationId) {
9301
- const path31 = `/api/archive/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}/sandbox`;
9302
- addApiBreadcrumb("GET", path31);
9303
- const url = `${this.apiUrl}${path31}`;
9352
+ const path36 = `/api/archive/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}/sandbox`;
9353
+ addApiBreadcrumb("GET", path36);
9354
+ const url = `${this.apiUrl}${path36}`;
9304
9355
  let response = await this.send(url, "GET");
9305
9356
  if (response.status === 401 && this.onUnauthorized) {
9306
9357
  let refreshed;
@@ -9314,7 +9365,7 @@ var init_api_client = __esm({
9314
9365
  }
9315
9366
  }
9316
9367
  if (!response.ok) {
9317
- throw new ApiError("GET", path31, response.status, await response.text());
9368
+ throw new ApiError("GET", path36, response.status, await response.text());
9318
9369
  }
9319
9370
  return new Uint8Array(await response.arrayBuffer());
9320
9371
  }
@@ -9354,9 +9405,9 @@ var init_api_client = __esm({
9354
9405
  `/api/admin/data-explorer/debug/observability/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}${qs}`
9355
9406
  );
9356
9407
  }
9357
- async request(method, path31, body, extraHeaders, contentType) {
9358
- addApiBreadcrumb(method, path31);
9359
- const url = `${this.apiUrl}${path31}`;
9408
+ async request(method, path36, body, extraHeaders, contentType) {
9409
+ addApiBreadcrumb(method, path36);
9410
+ const url = `${this.apiUrl}${path36}`;
9360
9411
  let refreshedOn401 = false;
9361
9412
  for (let retry = 0; ; retry++) {
9362
9413
  let response = await this.send(url, method, body, extraHeaders, contentType);
@@ -9381,7 +9432,7 @@ var init_api_client = __esm({
9381
9432
  await delay(RETRYABLE_BACKOFF_MS[retry]);
9382
9433
  continue;
9383
9434
  }
9384
- throw new ApiError(method, path31, response.status, errorBody);
9435
+ throw new ApiError(method, path36, response.status, errorBody);
9385
9436
  }
9386
9437
  }
9387
9438
  /**
@@ -9443,9 +9494,9 @@ var init_api_client = __esm({
9443
9494
  * transient-retry loop — re-streaming a blob is not worth a cold-start probe.
9444
9495
  */
9445
9496
  async dataDownload(v1Path, orgId) {
9446
- const path31 = withOrgSelector(toDataProxyPath(v1Path), orgId);
9447
- addApiBreadcrumb("GET", path31);
9448
- const url = `${this.apiUrl}${path31}`;
9497
+ const path36 = withOrgSelector(toDataProxyPath(v1Path), orgId);
9498
+ addApiBreadcrumb("GET", path36);
9499
+ const url = `${this.apiUrl}${path36}`;
9449
9500
  let response = await this.send(url, "GET");
9450
9501
  if (response.status === 401 && this.onUnauthorized) {
9451
9502
  let refreshed;
@@ -9459,7 +9510,7 @@ var init_api_client = __esm({
9459
9510
  }
9460
9511
  }
9461
9512
  if (!response.ok) {
9462
- throw new ApiError("GET", path31, response.status, await response.text());
9513
+ throw new ApiError("GET", path36, response.status, await response.text());
9463
9514
  }
9464
9515
  return {
9465
9516
  bytes: new Uint8Array(await response.arrayBuffer()),
@@ -9611,12 +9662,12 @@ function validateFollowupLinks2(followups, label, ctx) {
9611
9662
  const linkTargets = /* @__PURE__ */ new Set();
9612
9663
  followups.forEach((followup, i) => {
9613
9664
  const ref = followup?.after_followup_id;
9614
- const path31 = ["followups", i, "after_followup_id"];
9665
+ const path36 = ["followups", i, "after_followup_id"];
9615
9666
  if (followup?.type !== "inactivity_after_before_event") {
9616
9667
  if (ref !== void 0) {
9617
9668
  ctx.addIssue({
9618
9669
  code: external_exports.ZodIssueCode.custom,
9619
- path: path31,
9670
+ path: path36,
9620
9671
  message: `kanban status ${label}: after_followup_id is only valid on inactivity_after_before_event followups (this one is ${followup?.type})`
9621
9672
  });
9622
9673
  }
@@ -9625,7 +9676,7 @@ function validateFollowupLinks2(followups, label, ctx) {
9625
9676
  if (ref === void 0) {
9626
9677
  ctx.addIssue({
9627
9678
  code: external_exports.ZodIssueCode.custom,
9628
- path: path31,
9679
+ path: path36,
9629
9680
  message: `kanban status ${label}: inactivity_after_before_event requires after_followup_id naming the id of a before_event followup in the same status`
9630
9681
  });
9631
9682
  return;
@@ -9635,7 +9686,7 @@ function validateFollowupLinks2(followups, label, ctx) {
9635
9686
  if (matches.length > 1) {
9636
9687
  ctx.addIssue({
9637
9688
  code: external_exports.ZodIssueCode.custom,
9638
- path: path31,
9689
+ path: path36,
9639
9690
  message: `kanban status ${label}: after_followup_id "${ref}" matches ${matches.length} followups \u2014 a link must name exactly one`
9640
9691
  });
9641
9692
  return;
@@ -9647,7 +9698,7 @@ function validateFollowupLinks2(followups, label, ctx) {
9647
9698
  );
9648
9699
  ctx.addIssue({
9649
9700
  code: external_exports.ZodIssueCode.custom,
9650
- path: path31,
9701
+ path: path36,
9651
9702
  message: hasIdlessBeforeEvent ? `kanban status ${label}: after_followup_id "${ref}" matches no followup \u2014 a link target must declare an explicit id, and this status has before_event followups without one` : `kanban status ${label}: after_followup_id "${ref}" matches no followup in this status`
9652
9703
  });
9653
9704
  return;
@@ -9655,7 +9706,7 @@ function validateFollowupLinks2(followups, label, ctx) {
9655
9706
  if (target.type !== "before_event") {
9656
9707
  ctx.addIssue({
9657
9708
  code: external_exports.ZodIssueCode.custom,
9658
- path: path31,
9709
+ path: path36,
9659
9710
  message: `kanban status ${label}: after_followup_id "${ref}" points at a ${target.type} followup \u2014 only before_event followups can anchor a chain`
9660
9711
  });
9661
9712
  }
@@ -9731,12 +9782,12 @@ function typeMatches2(typeField, allowed) {
9731
9782
  if (Array.isArray(typeField)) return typeField.every((t) => typeof t === "string" && allowed.has(t));
9732
9783
  return false;
9733
9784
  }
9734
- function validateSchema2(schema, path31, errors, opts = {}) {
9785
+ function validateSchema2(schema, path36, errors, opts = {}) {
9735
9786
  if (typeof schema === "boolean") return;
9736
9787
  const depth = opts.depth ?? 0;
9737
9788
  if (depth > MAX_SCHEMA_DEPTH2) {
9738
9789
  errors.push({
9739
- path: path31 || "<root>",
9790
+ path: path36 || "<root>",
9740
9791
  message: `schema nesting exceeds ${MAX_SCHEMA_DEPTH2} levels`,
9741
9792
  suggestion: "Flatten the schema; LLM providers reject deeply nested tool input_schemas."
9742
9793
  });
@@ -9744,7 +9795,7 @@ function validateSchema2(schema, path31, errors, opts = {}) {
9744
9795
  }
9745
9796
  if (!isRecord2(schema)) {
9746
9797
  errors.push({
9747
- path: path31,
9798
+ path: path36,
9748
9799
  message: `expected object, got ${schema === null ? "null" : typeof schema}`
9749
9800
  });
9750
9801
  return;
@@ -9752,14 +9803,14 @@ function validateSchema2(schema, path31, errors, opts = {}) {
9752
9803
  if (opts.isRoot) {
9753
9804
  if ("type" in schema && schema.type !== "object") {
9754
9805
  errors.push({
9755
- path: path31 ? `${path31}.type` : "type",
9806
+ path: path36 ? `${path36}.type` : "type",
9756
9807
  message: `root type must be 'object', got ${JSON.stringify(schema.type)}`,
9757
9808
  suggestion: "Tool parameters at the root must be an object: `{ type: 'object', properties: { ... } }`."
9758
9809
  });
9759
9810
  }
9760
9811
  } else if ("type" in schema && !typeMatches2(schema.type, ALLOWED_TYPES2)) {
9761
9812
  errors.push({
9762
- path: `${path31}.type`,
9813
+ path: `${path36}.type`,
9763
9814
  message: `type must be one of ${[...ALLOWED_TYPES2].join("/")} or an array of those, got ${JSON.stringify(schema.type)}`
9764
9815
  });
9765
9816
  }
@@ -9769,25 +9820,25 @@ function validateSchema2(schema, path31, errors, opts = {}) {
9769
9820
  const isPlaceholder = PLACEHOLDER_TOKENS2.includes(e);
9770
9821
  const isOutcomePlaceholder = e === "[KANBAN_OUTCOME_VALUES]";
9771
9822
  errors.push({
9772
- path: `${path31}.enum`,
9823
+ path: `${path36}.enum`,
9773
9824
  message: `enum must be a non-empty array of primitives, got string ${JSON.stringify(e)}`,
9774
9825
  suggestion: isOutcomePlaceholder ? "Declare `outcomes` on the hub's terminal kanban status so the platform can render the placeholder into a valid array; with none configured the platform drops the parameter instead." : 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"]`.'
9775
9826
  });
9776
9827
  } else if (!Array.isArray(e)) {
9777
9828
  errors.push({
9778
- path: `${path31}.enum`,
9829
+ path: `${path36}.enum`,
9779
9830
  message: `enum must be a non-empty array of primitives, got ${typeof e}`
9780
9831
  });
9781
9832
  } else if (e.length === 0) {
9782
9833
  errors.push({
9783
- path: `${path31}.enum`,
9834
+ path: `${path36}.enum`,
9784
9835
  message: "enum must not be empty"
9785
9836
  });
9786
9837
  } else {
9787
9838
  for (let i = 0; i < e.length; i++) {
9788
9839
  if (!isPrimitive2(e[i])) {
9789
9840
  errors.push({
9790
- path: `${path31}.enum[${i}]`,
9841
+ path: `${path36}.enum[${i}]`,
9791
9842
  message: `enum entry must be a primitive (string/number/boolean/null), got ${typeof e[i]}`
9792
9843
  });
9793
9844
  }
@@ -9797,7 +9848,7 @@ function validateSchema2(schema, path31, errors, opts = {}) {
9797
9848
  for (const key of ["exclusiveMinimum", "exclusiveMaximum"]) {
9798
9849
  if (key in schema && typeof schema[key] === "boolean") {
9799
9850
  errors.push({
9800
- path: `${path31}.${key}`,
9851
+ path: `${path36}.${key}`,
9801
9852
  message: `${key} as boolean is draft-04 syntax; draft 2020-12 requires a numeric value`,
9802
9853
  suggestion: `Replace with the numeric bound, e.g. \`${key}: 0\`.`
9803
9854
  });
@@ -9806,45 +9857,45 @@ function validateSchema2(schema, path31, errors, opts = {}) {
9806
9857
  if ("properties" in schema) {
9807
9858
  if (!isRecord2(schema.properties)) {
9808
9859
  errors.push({
9809
- path: `${path31}.properties`,
9860
+ path: `${path36}.properties`,
9810
9861
  message: `properties must be an object, got ${Array.isArray(schema.properties) ? "array" : typeof schema.properties}`
9811
9862
  });
9812
9863
  } else {
9813
9864
  for (const [propName, propSchema] of Object.entries(schema.properties)) {
9814
- validateSchema2(propSchema, `${path31}.properties.${propName}`, errors, { depth: depth + 1 });
9865
+ validateSchema2(propSchema, `${path36}.properties.${propName}`, errors, { depth: depth + 1 });
9815
9866
  }
9816
9867
  }
9817
9868
  }
9818
9869
  if (schemaTypeIncludes2(schema, "array") && "items" in schema) {
9819
9870
  if (Array.isArray(schema.items)) {
9820
- schema.items.forEach((sub, i) => validateSchema2(sub, `${path31}.items[${i}]`, errors, { depth: depth + 1 }));
9871
+ schema.items.forEach((sub, i) => validateSchema2(sub, `${path36}.items[${i}]`, errors, { depth: depth + 1 }));
9821
9872
  } else {
9822
- validateSchema2(schema.items, `${path31}.items`, errors, { depth: depth + 1 });
9873
+ validateSchema2(schema.items, `${path36}.items`, errors, { depth: depth + 1 });
9823
9874
  }
9824
9875
  }
9825
9876
  for (const key of SUBSCHEMA_OBJECT_KEYWORDS2) {
9826
9877
  if (key in schema && isRecord2(schema[key])) {
9827
- validateSchema2(schema[key], `${path31}.${key}`, errors, { depth: depth + 1 });
9878
+ validateSchema2(schema[key], `${path36}.${key}`, errors, { depth: depth + 1 });
9828
9879
  }
9829
9880
  }
9830
9881
  for (const key of SUBSCHEMA_LIST_KEYWORDS2) {
9831
9882
  const list = schema[key];
9832
9883
  if (Array.isArray(list)) {
9833
- list.forEach((sub, i) => validateSchema2(sub, `${path31}.${key}[${i}]`, errors, { depth: depth + 1 }));
9884
+ list.forEach((sub, i) => validateSchema2(sub, `${path36}.${key}[${i}]`, errors, { depth: depth + 1 }));
9834
9885
  }
9835
9886
  }
9836
9887
  for (const key of SUBSCHEMA_MAP_KEYWORDS2) {
9837
9888
  const map = schema[key];
9838
9889
  if (isRecord2(map)) {
9839
9890
  for (const [name, sub] of Object.entries(map)) {
9840
- validateSchema2(sub, `${path31}.${key}.${name}`, errors, { depth: depth + 1 });
9891
+ validateSchema2(sub, `${path36}.${key}.${name}`, errors, { depth: depth + 1 });
9841
9892
  }
9842
9893
  }
9843
9894
  }
9844
9895
  const reportedPaths = new Set(errors.map((e) => e.path));
9845
9896
  for (const [k, v] of Object.entries(schema)) {
9846
9897
  if (typeof v !== "string") continue;
9847
- const fieldPath = `${path31}.${k}`;
9898
+ const fieldPath = `${path36}.${k}`;
9848
9899
  if (reportedPaths.has(fieldPath)) continue;
9849
9900
  for (const token of PLACEHOLDER_TOKENS2) {
9850
9901
  if (v === token) {
@@ -9989,8 +10040,8 @@ function evalInitialStateError2(input) {
9989
10040
  const parsed = evalInitialStateEntry2.safeParse(entries[i]);
9990
10041
  if (!parsed.success) {
9991
10042
  const issue = parsed.error.issues[0];
9992
- const path31 = issue?.path.join(".") || "?";
9993
- return `initial_state[${i}].${path31} is invalid: ${issue?.message ?? "malformed"}`;
10043
+ const path36 = issue?.path.join(".") || "?";
10044
+ return `initial_state[${i}].${path36} is invalid: ${issue?.message ?? "malformed"}`;
9994
10045
  }
9995
10046
  if (seenSlugs.has(parsed.data.slug)) {
9996
10047
  return `initial_state[${i}].slug "${parsed.data.slug}" is declared more than once`;
@@ -10195,10 +10246,10 @@ function refineHubAsCodeEvals2(config, ctx) {
10195
10246
  function refineHubAsCodeEvalAttachments2(config, ctx) {
10196
10247
  const cfg = config;
10197
10248
  const referencedHashes = /* @__PURE__ */ new Set();
10198
- const addTurnIssue = (path31, turn, name) => {
10249
+ const addTurnIssue = (path36, turn, name) => {
10199
10250
  const error = evalTurnAttachmentsError2(turn);
10200
10251
  if (error) {
10201
- ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: path31, message: `${name}: ${error}` });
10252
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: path36, message: `${name}: ${error}` });
10202
10253
  return;
10203
10254
  }
10204
10255
  for (const hash of collectTurnAttachmentHashes2(turn)) referencedHashes.add(hash);
@@ -10344,11 +10395,11 @@ function refineHubAsCodeDelegation2(config, ctx) {
10344
10395
  }
10345
10396
  }
10346
10397
  if (del.context_boundary === void 0) return;
10347
- const path31 = ["agents", agentIndex, "tools", "delegation", delIndex, "context_boundary"];
10398
+ const path36 = ["agents", agentIndex, "tools", "delegation", delIndex, "context_boundary"];
10348
10399
  if (del.type !== "hub") {
10349
10400
  ctx.addIssue({
10350
10401
  code: external_exports.ZodIssueCode.custom,
10351
- path: path31,
10402
+ path: path36,
10352
10403
  message: `context_boundary applies only to \`type: hub\` delegations (got type "${String(del.type)}")`
10353
10404
  });
10354
10405
  return;
@@ -10356,7 +10407,7 @@ function refineHubAsCodeDelegation2(config, ctx) {
10356
10407
  if (!CONTEXT_BOUNDARIES2.includes(del.context_boundary)) {
10357
10408
  ctx.addIssue({
10358
10409
  code: external_exports.ZodIssueCode.custom,
10359
- path: path31,
10410
+ path: path36,
10360
10411
  message: `context_boundary must be one of: ${CONTEXT_BOUNDARIES2.join(", ")}`
10361
10412
  });
10362
10413
  }
@@ -10402,7 +10453,7 @@ function findStepBoundaries(transcript) {
10402
10453
  }
10403
10454
  return out;
10404
10455
  }
10405
- var UUID_RE, HEX_RE, WORKOS_ID_RE, OPAQUE_SECRET_RE, BASE64_SECRET_RE, BASE64_MARKER_RE, TOKEN_RE, SENSITIVE_FIELDS, SENSITIVE_KEY_ALTERNATION, SENSITIVE_KEY_PATTERN, JSON_CREDENTIAL_RE, QUERY_CREDENTIAL_RE, REDACTED, PROVIDER_TOKEN_RE, APP_ERROR_BRAND, AppError, LLM_RATE_LIMIT_BRAND, LlmRateLimitError, LLM_PROVIDER_HTTP_BRAND, LlmProviderHttpError, LLM_PROVIDER_CONTENT_BRAND, LlmProviderContentError, LLM_PROVIDER_TIMEOUT_BRAND, LlmProviderTimeoutError, ExternalServiceError, CHANNEL_PROVIDER_HTTP_BRAND, ChannelProviderHttpError, MEDIA_PROVIDER_HTTP_BRAND, MediaProviderHttpError, REKOR_ACTOR_TYPE_HEADER2, REKOR_ACTOR_ID_HEADER2, REKOR_ACTOR_LABEL_HEADER2, REKOR_ACTOR_ORG_HEADER2, REKOR_ACTOR_ADMIN_HEADER2, REKOR_CLIENT_HEADER2, REKOR_TOOL_ID_HEADER2, REKOR_CLIENTS2, rekorClientSchema2, MAX_REKOR_TOOL_ID_LENGTH2, rekorToolIdSchema2, DATA_PROXY_MOUNT2, DATA_PROXY_PREFIX2, DATA_PROXY_ORG_QUERY_PARAM2, dataProxyQuery2, rekorAttestation2, REQUIRED_REKOR_ATTESTATION_HEADERS2, ENDPOINT_CONFIGS, AUTH_TYPE2, ORG_CREDENTIAL_AUTH_TYPES2, AUTH_TYPE_DISPLAY2, LEGACY_AUTH_TYPE_MAP2, VALID_AUTH_TYPES2, AGENT_ROLES2, SAFE_USER_ID_REGEX2, SUPPORTED_LOCALES2, uuidSchema2, paginationSchema3, timestampSchema2, idParamSchema2, clientOptionalString2, clientOptionalBoolean2, clientOptionalNumber2, messageAttachment2, MAX_MESSAGE_BODY_BYTES2, MAX_ATTACHMENTS_PER_MESSAGE2, MAX_AUDIO_FILE_BASE64_BYTES2, primaryRegionSchema2, placementSourceSchema2, orgIdParam2, orgAdminIdParam2, createOrganizationBody2, updateOrganizationBody2, addOrgAdminBody2, SUMMARIZATION_THRESHOLD_MIN2, SUMMARIZATION_THRESHOLD_MAX2, PREVIOUS_CONVERSATIONS_MAX2, previousConversationsCountField2, 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, followupTypeSchema2, EVENT_RELATIVE_FOLLOWUP_TYPES2, followupTimeUnitSchema2, followupIdSchema2, SELECTABLE_FOLLOWUP_TYPES2, MAX_LINKED_FOLLOWUP_TARGETS_PER_STATUS2, followupSchema2, MAX_OUTCOMES_PER_STATUS2, kanbanOutcomeSchema2, EXCLUSIVE_FLAG_PAIRS2, kanbanStatusSchema2, kanbanStatusesArraySchema2, laneSchema2, lanesArraySchema2, hubIdParam2, hubAdminIdParam2, hubUserIdParam2, hubIdentityIdParam2, hubTeamIdParam2, hubTeamUserDeleteParam2, hubSchemaQuery2, PREVIEW_LABEL_MAX_LENGTH2, MAX_ENDED_INDEX_RETENTION_DAYS2, MAX_EVAL_RETENTION_DAYS2, previewLabelField2, createHubBody2, updateHubBody2, addHubAdminBody2, addHubIdentityAuthorizationBody2, contactDecisionBody2, approveContactBody2, listContactAccessQuery2, createHubTeamBody2, updateHubTeamBody2, addHubTeamUserBody2, reassignHubUserBody2, replicatePreviewBody2, updateChannelTestIdentitiesBody2, claimCodeChannelParam2, claimCodeDeleteParam2, connectionIdParam2, connectorIdParam2, listConnectionsQuery2, deleteConnectionQuery2, addConnectionBody2, editConnectionBody2, PRODUCTION_DIRECT_FIELDS2, setProductionCredentialBody2, registerWhatsappQuery2, registerWhatsappBody2, retryProvisioningQuery2, resendDomainStatusQuery2, PLACEHOLDER_TOKENS2, ALLOWED_TYPES2, SUBSCHEMA_OBJECT_KEYWORDS2, SUBSCHEMA_LIST_KEYWORDS2, SUBSCHEMA_MAP_KEYWORDS2, MAX_SCHEMA_DEPTH2, toolIdParam2, listToolsQuery2, toolAgentQuery2, deleteToolQuery2, toolConnectionsQuery2, nativeToolIdSchema2, CONTEXT_BOUNDARIES2, contextBoundarySchema2, addNativeToolBody2, addMcpToolBody2, createCustomToolBody2, updateCustomToolBody2, updateToolExecutionConfigBody2, initialValueCreateSchema2, initialValueUpdateSchema2, stateIdParam2, listStatesQuery2, stateNameSchema2, createStateBody2, updateStateBody2, reorderStatesBody2, variantAiModeSchema2, experimentStatusSchema2, overlayUpdateSchema2, experimentIdParam2, variantIdParam2, listExperimentsQuery2, listVariantsQuery2, listOverridesQuery2, deleteOverrideQuery2, createExperimentBody2, updateExperimentBody2, setExperimentStatusBody2, createVariantBody2, updateVariantBody2, upsertOverrideBody2, orgTagIdParam2, listOrgTagsQuery2, createOrgTagBody2, updateOrgTagBody2, orgCredentialIdParam2, listOrgCredentialsQuery2, createOrgCredentialBody2, updateOrgCredentialBody2, orgResourceIdParam2, orgResourceFileIdParam2, orgResourceFolderIdParam2, hubOrgResourceParam2, listOrgResourcesQuery2, orgIdQuery2, createOrgResourceBody2, updateOrgResourceBody2, createOrgResourceFolderBody2, updateOrgResourceFolderBody2, uploadOrgResourceFileBody2, updateOrgResourceFileBody2, uploadOrgSkillZipBody2, linkOrgResourceBody2, resourceIdParam2, listResourcesQuery2, createResourceBody2, updateResourceBody2, syncSkillsBody2, resourceFileIdParam2, listResourceFilesQuery2, createResourceFileBody2, updateResourceFileBody2, uploadResourceFileBody2, uploadSkillZipBody2, resourceFolderIdParam2, listResourceFoldersQuery2, createResourceFolderBody2, updateResourceFolderBody2, agentResourceQuery2, hubResourceQuery2, linkAgentResourceBody2, updateAgentResourceBody2, unlinkAgentResourceQuery2, navItemSchema2, hubCountResetBody2, navItemCountResetBody2, typingBody2, analyticsHubIdParam2, analyticsVariableIdParam2, updateVariablePinBody2, updateAnalyticsViewBody2, NUMERIC_FILTER_OPS2, TEXT_FILTER_OPS2, CATEGORICAL_FILTER_OPS2, VARIABLE_FILTER_OPS2, STRUCTURED_QUERY_OPS2, STRUCTURED_QUERY_AGGREGATIONS2, filterValueSchema2, conversationsBody2, analyticsConversationIdParam2, messagesQuery2, conversationDetailDataQuery2, analyticsDataBody2, structuredQueryBody2, analyticsSqlBody2, analyticsSqlTable2, analyticsSqlSchemaQuery2, EVAL_PACING_PRESET_NAMES2, PACING_INTERVAL_MIN_MS2, PACING_INTERVAL_MAX_MS2, EVAL_MAX_RUNS_PER_SCENARIO2, EVAL_RUN_DEADLINE_MIN_MS2, EVAL_RUN_DEADLINE_MAX_MS2, ISO_UTC_RE2, paginationSchema22, evalIdParam2, sessionIdParam2, scenarioSetIdParam2, hubIdQuery2, evalDateContextSchema2, EVAL_FIXTURE_NAME_MAX_LENGTH2, evalFixtureOverrideSchema2, runSessionQuery2, EVAL_INPUT_ROLES2, EVAL_INPUT_ROLE_LIST2, ROLE_ECHO_MAX2, EVAL_INITIAL_STATE_SCOPES2, MAX_INITIAL_STATE_ENTRIES2, evalInitialStateEntry2, createEvalBody2, updateEvalBody2, EVAL_LIST_MAX_LIMIT2, evalListLimit2, getEvalsQuery2, toggleEvalBody2, bulkToggleEvalsBody2, pacingConfigSchema2, EVAL_MAX_SELECTED_SCENARIOS2, evalScenarioSelectionEntrySchema2, evalScenarioSelectionSchema2, sessionConfigSchema2, createSessionBody2, getSessionsQuery2, getSessionResultsQuery2, getSessionRunsQuery2, evalAnalyticsQuery2, getSessionCostQuery2, compareSessionsQuery2, evalsSqlBody2, evalsSqlSchemaQuery2, exportResultsQuery2, validateEvalBody2, hubAgentsQuery2, createScenarioSetBody2, updateScenarioSetBody2, scenarioSetsHubQuery2, createScenarioFromConversationBody2, createJourneyFromConversationBody2, EVAL_ATTACHMENT_HASH_REGEX2, evalAttachmentRef2, turnMayCarryAttachments2, ATTACHMENTS_USER_ONLY_MESSAGE2, journeyIdParam2, journeyToolCallSchema2, journeyTurnSchema2, journeyStepOverrideSchema2, fixtureField2, createJourneyBody2, updateJourneyBody2, evalSessionConfigResponseSchema2, evalSessionResponseSchema2, evalSessionListConfigSchema2, evalSessionListItemSchema2, seedReleaseStatusSchema2, getConversationsQuery2, getMessagesQuery2, appMessageSenderType2, appMessageReceiverType2, apiChannelMessage2, apiChannelMessageBody2, appMessageBody2, appMessageResponse2, updateUserBody2, updateProfileBody2, pathnameRegex2, updatePreferencesBody2, registerPushTokenBody2, deletePushTokenQuery2, activityQuery2, deletionModeSchema2, deletionRequestBody2, archiveHubIdParam2, archiveConversationParams2, archiveListQuery2, archiveMessageObservabilityParams2, conversationIdParam2, claimBody2, releaseBody2, transferBody2, closeBody2, additionalContextPayloadSchema2, kanbanUpdateBody2, annotateConversationBody2, observabilityParams2, observabilityListParams2, deleteUserConversationsBody2, deleteUserConversationsResponse2, sendMessageBody2, listConversationsQuery2, flagSourceSchema2, getConversationsResponse2, getConversationDetailParams2, getConversationDetailQuery2, getConversationDetailResponse2, listWhatsAppTemplatesQuery2, sendWhatsAppTemplateBody2, copilotSuggestBody2, copilotSuggestResponse2, CONSULT_THREAD_STATUSES2, consultThreadStatus2, CONSULT_THREAD_TITLE_MAX2, consultThreadTitle2, consultThreadSummary2, listConsultThreadsQuery2, listConsultThreadsResponse2, createConsultThreadBody2, createConsultThreadResponse2, consultThreadIdParam2, updateConsultThreadBody2, updateConsultThreadResponse2, CONSULT_AWAIT_TIMEOUT_MS2, billingOrgIdParam2, subscriptionItemParams2, spendCapBody2, growthPacksBody2, portalSessionBody2, checkoutSessionBody2, updateBillingCurrencyBody2, invoicesQuery2, planKeySchema2, billingStatusSchema2, REKOR_ENTITLEMENT_CONTRACT_VERSION2, entitlementProjectionSchema2, rekorEntitlementRefreshMessageSchema2, downloadBody2, uploadQuery2, signUrlBody2, outboundSchemaQuery2, templateIdParam2, listTemplatesQuery2, deleteTemplateQuery2, templateStatusQuery2, createTemplateBody2, updateTemplateBody2, submitTemplateBody2, testTemplateBody2, contactIdParam2, listContactsQuery2, createContactBody2, updateContactBody2, listIdParam2, listListsQuery2, listListContactsQuery2, createListBody2, updateListBody2, addListContactsBody2, removeListContactsBody2, scheduleIdParam2, listSchedulesQuery2, listExecutionsQuery2, createScheduleBody2, updateScheduleBody2, MAX_RESOURCE_FILE_SIZE2, MAX_10MB_BASE64_ENCODED_BYTES2, MAX_EVAL_ATTACHMENT_ENCODED_BYTES2, MAX_EVAL_ATTACHMENT_CARRIERS2, MAX_EVAL_ATTACHMENT_AGGREGATE_ENCODED_BYTES2, MAX_RESOURCE_ENCODED_BYTES2, MAX_HUB_AS_CODE_RESOURCES2, MAX_HUB_AS_CODE_RESOURCE_FILES2, MAX_RESOURCE_AGGREGATE_ENCODED_BYTES2, MAX_CI_CONFIG_BODY_BYTES2, hubAsCodeStateSchema2, hubAsCodeResourceFileSchema2, hubAsCodeResourceSchema2, uuidPattern2, ciUuidSchema2, boundedHubAsCodeResourcesSchema2, hubAsCodeConfigSchema2, ciPullHubIdParam2, ciBranchParam2, ciPullQuery2, ciHubsQuery2, ciLookupQuery2, ciBranchesQuery2, ciSyncBody2, ciPushBody2, ciDiffBody2, ciPublishBody2, ciPublishPreviewBody2, ciSyncMcpBody2, ciOrgResourcesParam2, orgResourcesConfigSchema2, ciOrgResourcesPushBody2, ciOrgResourcesDiffBody2, CI_APPLY_ENTITY_KINDS2, CI_APPLY_OPERATIONS2, ciApplyErrorBaseSchema2, ciApplyErrorSchema2, ciSyncCountSchema2, ciSyncChangesSchema2, ciSyncWarningSchema2, ciSyncResponseSchema2, adminOrgIdParam2, adminOrgAdminIdParam2, adminUserIdParam2, adminPlanIdParam2, adminOrganizationsQuery2, adminUserSearchQuery2, kanbanSlugMigrationQuery2, adjustQuotaBody2, updatePlanBody2, addAdminUserBody2, updatePlatformConfigBody2, updateFreeOrgLimitBody2, adminScopedTargetBody2, updatePricingPlanBody2, dataExplorerSearchQuery2, dataExplorerOrgIdParam2, dataExplorerHubIdParam2, dataExplorerConvIdParam2, dataExplorerDoInstancesQuery2, dataExplorerNsIdParam2, dataExplorerKvKeysBody2, dataExplorerKvKeyBody2, uuidOrHexId2, dataExplorerDeleteOrgParam2, dataExplorerDeleteHubParam2, dataExplorerDeleteConvParam2, dataExplorerDeleteUserParam2, dataExplorerDeleteQuery2, dataExplorerKvDeleteBody2, pitrDoNamespace2, pitrBookmarkParam2, pitrRestoreBody2, healthSamplingTriggerBody2, dataExplorerDebugDoType2, DEBUG_READ_MAX_LIMIT2, DEBUG_READ_DEFAULT_LIMIT2, DEBUG_DO_HEX_PREFIX2, debugDoEntityId2, debugTableName2, dataExplorerDebugTablesParam2, dataExplorerDebugRowsParam2, dataExplorerDebugRowsQuery2, dataExplorerDebugAnalyticsTable2, debugUuid2, dataExplorerDebugAnalyticsRowsParam2, dataExplorerDebugAnalyticsRowsQuery2, debugHubConvParam2, debugMessageIdQuery2, sandboxEgressPolicy2, SANDBOX_EXEC_MAX_CMD_LENGTH2, SANDBOX_EXEC_MAX_ALLOWLIST2, SANDBOX_EXEC_MAX_TIMEOUT_MS2, adminSandboxExecBody2, whatsappCallbackBody2, authMeResponse2, wsTicketResponse2, sessionCheckResponse2, logoutResponse2, magicCodeSendBody2, magicCodeSendResponse2, magicCodeVerifyBody2, magicCodeVerifyResponse2, passwordLoginBody2, browserParams2, browserFoldersQuery2, browserFilesQuery2, stateOperationBody2, conversationListResourcesQuery2, conversationReadResourceQuery2, listPendingSchedulesQuery2, listHubAggregateSchedulesQuery2, reportSourceSchema2, intakeReportSourceSchema2, reportClassificationSchema2, reportStatusSchema2, reportLocaleSchema2, reportMessageAuthorRoleSchema2, reportMessageSchema2, sentryRefStatusSchema2, createReportBody2, editReportBody2, reporterReportSummarySchema2, reporterListResponseSchema2, getReportResponseSchema2, reporterTransitionResponseSchema2, contestReportBody2, reporterListQuery2, listReportsQuery2, GITHUB_ISSUE_URL_REGEX2, githubIssueUrlSchema2, transitionReportBody2, groupReportsBody2, holdReportBody2, clickhouseReadyResponse2, bootstrapQuery2, requestSnapshotChunkMessage2, MAX_NAME_LENGTH3, MAX_VALUE_LENGTH2, MAX_TAGS2, MAX_TAG_LENGTH2, MAX_SCOPE_HUBS2, MAX_SCOPE_TAGS2, vaultSecretScopeSchema2, vaultCreateBody2, vaultUpdateBody2, PERMISSIONS2, MAX_NAME_LENGTH22, MAX_HUBS_PER_GRANT2, MAX_HUB_TAGS_PER_GRANT2, MAX_GRANTS2, permissionEnum2, grantScopeSchema2, grantSchema2, createTokenBody2, tokenOrgIdParam2, tokenGrantScopeSchema2, tokenGrantSchema2, tokenMetadataSchema2, listTokensResponse2, createTokenResponse2, orgTokenSummarySchema2, listOrgTokensResponse2, invitePreviewQuery2, invitePreviewResponse2, jsonSchemaSchema2, hubUserIdentity2, stateValueEntry2, getHubUserContextResponse2, updateHubUserBody2, updateHubUserResponse2, unlockHubUserNameResponse2, stateResetParams2, stateResetResponse2, hubAlertsParam2, hubAlertSeverity2, hubAlert2, hubAlertsListResponse2, noticeSeveritySchema2, noticeStatusSchema2, NOTICE_SCOPE_REGEX2, noticeScopeSchema2, noticeLinkSchema2, createNoticeBody2, updateNoticeBody2, listNoticesQuery2, noticeIdParamSchema2, ADMIN_SKILL_NAME_REGEX2, adminSkillNameParam2, WAYAI_WORKSPACE_LAYOUT;
10456
+ var UUID_RE, HEX_RE, WORKOS_ID_RE, OPAQUE_SECRET_RE, BASE64_SECRET_RE, BASE64_MARKER_RE, TOKEN_RE, SENSITIVE_FIELDS, SENSITIVE_KEY_ALTERNATION, SENSITIVE_KEY_PATTERN, JSON_CREDENTIAL_RE, QUERY_CREDENTIAL_RE, REDACTED, PROVIDER_TOKEN_RE, APP_ERROR_BRAND, AppError, LLM_RATE_LIMIT_BRAND, LlmRateLimitError, LLM_PROVIDER_HTTP_BRAND, LlmProviderHttpError, LLM_PROVIDER_CONTENT_BRAND, LlmProviderContentError, LLM_PROVIDER_TIMEOUT_BRAND, LlmProviderTimeoutError, ExternalServiceError, CHANNEL_PROVIDER_HTTP_BRAND, ChannelProviderHttpError, MEDIA_PROVIDER_HTTP_BRAND, MediaProviderHttpError, REKOR_ACTOR_TYPE_HEADER2, REKOR_ACTOR_ID_HEADER2, REKOR_ACTOR_LABEL_HEADER2, REKOR_ACTOR_ORG_HEADER2, REKOR_ACTOR_ADMIN_HEADER2, REKOR_CLIENT_HEADER2, REKOR_TOOL_ID_HEADER2, REKOR_CLIENTS2, rekorClientSchema2, MAX_REKOR_TOOL_ID_LENGTH2, rekorToolIdSchema2, DATA_PROXY_MOUNT2, DATA_PROXY_PREFIX2, DATA_PROXY_ORG_QUERY_PARAM2, MAX_PROVISIONING_BODY_BYTES2, dataProxyQuery2, rekorAttestation2, REQUIRED_REKOR_ATTESTATION_HEADERS2, ENDPOINT_CONFIGS, AUTH_TYPE2, ORG_CREDENTIAL_AUTH_TYPES2, AUTH_TYPE_DISPLAY2, LEGACY_AUTH_TYPE_MAP2, VALID_AUTH_TYPES2, AGENT_ROLES2, SAFE_USER_ID_REGEX2, SUPPORTED_LOCALES2, uuidSchema2, paginationSchema3, timestampSchema2, idParamSchema2, clientOptionalString2, clientOptionalBoolean2, clientOptionalNumber2, messageAttachment2, MAX_MESSAGE_BODY_BYTES2, MAX_ATTACHMENTS_PER_MESSAGE2, MAX_AUDIO_FILE_BASE64_BYTES2, primaryRegionSchema2, placementSourceSchema2, orgIdParam2, orgAdminIdParam2, createOrganizationBody2, updateOrganizationBody2, addOrgAdminBody2, SUMMARIZATION_THRESHOLD_MIN2, SUMMARIZATION_THRESHOLD_MAX2, PREVIOUS_CONVERSATIONS_MAX2, previousConversationsCountField2, 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, followupTypeSchema2, EVENT_RELATIVE_FOLLOWUP_TYPES2, followupTimeUnitSchema2, followupIdSchema2, SELECTABLE_FOLLOWUP_TYPES2, MAX_LINKED_FOLLOWUP_TARGETS_PER_STATUS2, followupSchema2, MAX_OUTCOMES_PER_STATUS2, kanbanOutcomeSchema2, EXCLUSIVE_FLAG_PAIRS2, kanbanStatusSchema2, kanbanStatusesArraySchema2, laneSchema2, lanesArraySchema2, hubIdParam2, hubAdminIdParam2, hubUserIdParam2, hubIdentityIdParam2, hubTeamIdParam2, hubTeamUserDeleteParam2, hubSchemaQuery2, PREVIEW_LABEL_MAX_LENGTH2, MAX_ENDED_INDEX_RETENTION_DAYS2, MAX_EVAL_RETENTION_DAYS2, previewLabelField2, createHubBody2, updateHubBody2, addHubAdminBody2, addHubIdentityAuthorizationBody2, contactDecisionBody2, approveContactBody2, listContactAccessQuery2, createHubTeamBody2, updateHubTeamBody2, addHubTeamUserBody2, reassignHubUserBody2, replicatePreviewBody2, updateChannelTestIdentitiesBody2, claimCodeChannelParam2, claimCodeDeleteParam2, connectionIdParam2, connectorIdParam2, listConnectionsQuery2, deleteConnectionQuery2, addConnectionBody2, editConnectionBody2, PRODUCTION_DIRECT_FIELDS2, setProductionCredentialBody2, registerWhatsappQuery2, registerWhatsappBody2, retryProvisioningQuery2, resendDomainStatusQuery2, PLACEHOLDER_TOKENS2, ALLOWED_TYPES2, SUBSCHEMA_OBJECT_KEYWORDS2, SUBSCHEMA_LIST_KEYWORDS2, SUBSCHEMA_MAP_KEYWORDS2, MAX_SCHEMA_DEPTH2, toolIdParam2, listToolsQuery2, toolAgentQuery2, deleteToolQuery2, toolConnectionsQuery2, nativeToolIdSchema2, CONTEXT_BOUNDARIES2, contextBoundarySchema2, addNativeToolBody2, addMcpToolBody2, createCustomToolBody2, updateCustomToolBody2, updateToolExecutionConfigBody2, initialValueCreateSchema2, initialValueUpdateSchema2, stateIdParam2, listStatesQuery2, stateNameSchema2, createStateBody2, updateStateBody2, reorderStatesBody2, variantAiModeSchema2, experimentStatusSchema2, overlayUpdateSchema2, experimentIdParam2, variantIdParam2, listExperimentsQuery2, listVariantsQuery2, listOverridesQuery2, deleteOverrideQuery2, createExperimentBody2, updateExperimentBody2, setExperimentStatusBody2, createVariantBody2, updateVariantBody2, upsertOverrideBody2, orgTagIdParam2, listOrgTagsQuery2, createOrgTagBody2, updateOrgTagBody2, orgCredentialIdParam2, listOrgCredentialsQuery2, createOrgCredentialBody2, updateOrgCredentialBody2, orgResourceIdParam2, orgResourceFileIdParam2, orgResourceFolderIdParam2, hubOrgResourceParam2, listOrgResourcesQuery2, orgIdQuery2, createOrgResourceBody2, updateOrgResourceBody2, createOrgResourceFolderBody2, updateOrgResourceFolderBody2, uploadOrgResourceFileBody2, updateOrgResourceFileBody2, uploadOrgSkillZipBody2, linkOrgResourceBody2, resourceIdParam2, listResourcesQuery2, createResourceBody2, updateResourceBody2, syncSkillsBody2, resourceFileIdParam2, listResourceFilesQuery2, createResourceFileBody2, updateResourceFileBody2, uploadResourceFileBody2, uploadSkillZipBody2, resourceFolderIdParam2, listResourceFoldersQuery2, createResourceFolderBody2, updateResourceFolderBody2, agentResourceQuery2, hubResourceQuery2, linkAgentResourceBody2, updateAgentResourceBody2, unlinkAgentResourceQuery2, navItemSchema2, hubCountResetBody2, navItemCountResetBody2, typingBody2, analyticsHubIdParam2, analyticsVariableIdParam2, updateVariablePinBody2, updateAnalyticsViewBody2, NUMERIC_FILTER_OPS2, TEXT_FILTER_OPS2, CATEGORICAL_FILTER_OPS2, VARIABLE_FILTER_OPS2, STRUCTURED_QUERY_OPS2, STRUCTURED_QUERY_AGGREGATIONS2, filterValueSchema2, conversationsBody2, analyticsConversationIdParam2, messagesQuery2, conversationDetailDataQuery2, analyticsDataBody2, structuredQueryBody2, analyticsSqlBody2, analyticsSqlTable2, analyticsSqlSchemaQuery2, EVAL_PACING_PRESET_NAMES2, PACING_INTERVAL_MIN_MS2, PACING_INTERVAL_MAX_MS2, EVAL_MAX_RUNS_PER_SCENARIO2, EVAL_RUN_DEADLINE_MIN_MS2, EVAL_RUN_DEADLINE_MAX_MS2, ISO_UTC_RE2, paginationSchema22, evalIdParam2, sessionIdParam2, scenarioSetIdParam2, hubIdQuery2, evalDateContextSchema2, EVAL_FIXTURE_NAME_MAX_LENGTH2, evalFixtureOverrideSchema2, runSessionQuery2, EVAL_INPUT_ROLES2, EVAL_INPUT_ROLE_LIST2, ROLE_ECHO_MAX2, EVAL_INITIAL_STATE_SCOPES2, MAX_INITIAL_STATE_ENTRIES2, evalInitialStateEntry2, createEvalBody2, updateEvalBody2, EVAL_LIST_MAX_LIMIT2, evalListLimit2, getEvalsQuery2, toggleEvalBody2, bulkToggleEvalsBody2, pacingConfigSchema2, EVAL_MAX_SELECTED_SCENARIOS2, evalScenarioSelectionEntrySchema2, evalScenarioSelectionSchema2, sessionConfigSchema2, createSessionBody2, getSessionsQuery2, getSessionResultsQuery2, getSessionRunsQuery2, evalAnalyticsQuery2, getSessionCostQuery2, compareSessionsQuery2, evalsSqlBody2, evalsSqlSchemaQuery2, exportResultsQuery2, validateEvalBody2, hubAgentsQuery2, createScenarioSetBody2, updateScenarioSetBody2, scenarioSetsHubQuery2, createScenarioFromConversationBody2, createJourneyFromConversationBody2, EVAL_ATTACHMENT_HASH_REGEX2, evalAttachmentRef2, turnMayCarryAttachments2, ATTACHMENTS_USER_ONLY_MESSAGE2, journeyIdParam2, journeyToolCallSchema2, journeyTurnSchema2, journeyStepOverrideSchema2, fixtureField2, createJourneyBody2, updateJourneyBody2, evalSessionConfigResponseSchema2, evalSessionResponseSchema2, evalSessionListConfigSchema2, evalSessionListItemSchema2, seedReleaseStatusSchema2, getConversationsQuery2, getMessagesQuery2, appMessageSenderType2, appMessageReceiverType2, apiChannelMessage2, apiChannelMessageBody2, appMessageBody2, appMessageResponse2, updateUserBody2, updateProfileBody2, pathnameRegex2, updatePreferencesBody2, registerPushTokenBody2, deletePushTokenQuery2, activityQuery2, deletionModeSchema2, deletionRequestBody2, archiveHubIdParam2, archiveConversationParams2, archiveListQuery2, archiveMessageObservabilityParams2, conversationIdParam2, claimBody2, releaseBody2, transferBody2, closeBody2, additionalContextPayloadSchema2, kanbanUpdateBody2, annotateConversationBody2, observabilityParams2, observabilityListParams2, deleteUserConversationsBody2, deleteUserConversationsResponse2, sendMessageBody2, listConversationsQuery2, flagSourceSchema2, getConversationsResponse2, getConversationDetailParams2, getConversationDetailQuery2, getConversationDetailResponse2, listWhatsAppTemplatesQuery2, sendWhatsAppTemplateBody2, copilotSuggestBody2, copilotSuggestResponse2, CONSULT_THREAD_STATUSES2, consultThreadStatus2, CONSULT_THREAD_TITLE_MAX2, consultThreadTitle2, consultThreadSummary2, listConsultThreadsQuery2, listConsultThreadsResponse2, createConsultThreadBody2, createConsultThreadResponse2, consultThreadIdParam2, updateConsultThreadBody2, updateConsultThreadResponse2, CONSULT_AWAIT_TIMEOUT_MS2, billingOrgIdParam2, subscriptionItemParams2, spendCapBody2, growthPacksBody2, portalSessionBody2, checkoutSessionBody2, updateBillingCurrencyBody2, invoicesQuery2, planKeySchema2, billingStatusSchema2, REKOR_ENTITLEMENT_CONTRACT_VERSION2, entitlementProjectionSchema2, rekorEntitlementRefreshMessageSchema2, downloadBody2, uploadQuery2, signUrlBody2, outboundSchemaQuery2, templateIdParam2, listTemplatesQuery2, deleteTemplateQuery2, templateStatusQuery2, createTemplateBody2, updateTemplateBody2, submitTemplateBody2, testTemplateBody2, contactIdParam2, listContactsQuery2, createContactBody2, updateContactBody2, listIdParam2, listListsQuery2, listListContactsQuery2, createListBody2, updateListBody2, addListContactsBody2, removeListContactsBody2, scheduleIdParam2, listSchedulesQuery2, listExecutionsQuery2, createScheduleBody2, updateScheduleBody2, MAX_RESOURCE_FILE_SIZE2, MAX_10MB_BASE64_ENCODED_BYTES2, MAX_EVAL_ATTACHMENT_ENCODED_BYTES2, MAX_EVAL_ATTACHMENT_CARRIERS2, MAX_EVAL_ATTACHMENT_AGGREGATE_ENCODED_BYTES2, MAX_RESOURCE_ENCODED_BYTES2, MAX_HUB_AS_CODE_RESOURCES2, MAX_HUB_AS_CODE_RESOURCE_FILES2, MAX_RESOURCE_AGGREGATE_ENCODED_BYTES2, MAX_CI_CONFIG_BODY_BYTES2, hubAsCodeStateSchema2, hubAsCodeResourceFileSchema2, hubAsCodeResourceSchema2, uuidPattern2, ciUuidSchema2, boundedHubAsCodeResourcesSchema2, hubAsCodeConfigSchema2, ciPullHubIdParam2, ciBranchParam2, ciPullQuery2, ciHubsQuery2, ciLookupQuery2, ciBranchesQuery2, ciSyncBody2, ciPushBody2, ciDiffBody2, ciPublishBody2, ciPublishPreviewBody2, ciSyncMcpBody2, ciOrgResourcesParam2, orgResourcesConfigSchema2, ciOrgResourcesPushBody2, ciOrgResourcesDiffBody2, CI_APPLY_ENTITY_KINDS2, CI_APPLY_OPERATIONS2, ciApplyErrorBaseSchema2, ciApplyErrorSchema2, ciSyncCountSchema2, ciSyncChangesSchema2, ciSyncWarningSchema2, ciSyncResponseSchema2, adminOrgIdParam2, adminOrgAdminIdParam2, adminUserIdParam2, PRICING_PLAN_ID_RE2, adminPlanIdParam2, adminOrganizationsQuery2, adminUserSearchQuery2, kanbanSlugMigrationQuery2, adjustQuotaBody2, updatePlanBody2, addAdminUserBody2, updatePlatformConfigBody2, updateFreeOrgLimitBody2, adminScopedTargetBody2, adminRepairLegacyOrgGrantsBody2, updatePricingPlanBody2, dataExplorerSearchQuery2, dataExplorerOrgIdParam2, dataExplorerHubIdParam2, dataExplorerConvIdParam2, dataExplorerDoInstancesQuery2, dataExplorerNsIdParam2, dataExplorerKvKeysBody2, dataExplorerKvKeyBody2, uuidOrHexId2, dataExplorerDeleteOrgParam2, dataExplorerDeleteHubParam2, dataExplorerDeleteConvParam2, dataExplorerDeleteUserParam2, dataExplorerDeleteQuery2, dataExplorerKvDeleteBody2, pitrDoNamespace2, pitrBookmarkParam2, pitrRestoreBody2, healthSamplingTriggerBody2, dataExplorerDebugDoType2, DEBUG_READ_MAX_LIMIT2, DEBUG_READ_DEFAULT_LIMIT2, DEBUG_DO_HEX_PREFIX2, debugDoEntityId2, debugTableName2, dataExplorerDebugTablesParam2, dataExplorerDebugRowsParam2, dataExplorerDebugRowsQuery2, dataExplorerDebugAnalyticsTable2, debugUuid2, dataExplorerDebugAnalyticsRowsParam2, dataExplorerDebugAnalyticsRowsQuery2, debugHubConvParam2, debugMessageIdQuery2, sandboxEgressPolicy2, SANDBOX_EXEC_MAX_CMD_LENGTH2, SANDBOX_EXEC_MAX_ALLOWLIST2, SANDBOX_EXEC_MAX_TIMEOUT_MS2, adminSandboxExecBody2, whatsappCallbackBody2, authMeResponse2, wsTicketResponse2, sessionCheckResponse2, logoutResponse2, magicCodeSendBody2, magicCodeSendResponse2, magicCodeVerifyBody2, magicCodeVerifyResponse2, passwordLoginBody2, browserParams2, browserFoldersQuery2, browserFilesQuery2, stateOperationBody2, conversationListResourcesQuery2, conversationReadResourceQuery2, listPendingSchedulesQuery2, listHubAggregateSchedulesQuery2, reportSourceSchema2, intakeReportSourceSchema2, reportClassificationSchema2, reportStatusSchema2, reportLocaleSchema2, reportMessageAuthorRoleSchema2, reportMessageSchema2, sentryRefStatusSchema2, createReportBody2, editReportBody2, reporterReportSummarySchema2, reporterListResponseSchema2, getReportResponseSchema2, reporterTransitionResponseSchema2, contestReportBody2, reporterListQuery2, listReportsQuery2, GITHUB_ISSUE_URL_REGEX2, githubIssueUrlSchema2, transitionReportBody2, groupReportsBody2, holdReportBody2, clickhouseReadyResponse2, bootstrapQuery2, requestSnapshotChunkMessage2, MAX_NAME_LENGTH3, MAX_VALUE_LENGTH2, MAX_TAGS2, MAX_TAG_LENGTH2, MAX_SCOPE_HUBS2, MAX_SCOPE_TAGS2, vaultSecretScopeSchema2, vaultCreateBody2, vaultUpdateBody2, PERMISSIONS2, MAX_NAME_LENGTH22, MAX_HUBS_PER_GRANT2, MAX_HUB_TAGS_PER_GRANT2, MAX_GRANTS2, permissionEnum2, grantScopeSchema2, grantSchema2, createTokenBody2, tokenOrgIdParam2, tokenGrantScopeSchema2, tokenGrantSchema2, tokenMetadataSchema2, listTokensResponse2, createTokenResponse2, orgTokenSummarySchema2, listOrgTokensResponse2, invitePreviewQuery2, invitePreviewResponse2, jsonSchemaSchema2, hubUserIdentity2, stateValueEntry2, getHubUserContextResponse2, updateHubUserBody2, updateHubUserResponse2, unlockHubUserNameResponse2, stateResetParams2, stateResetResponse2, hubAlertsParam2, hubAlertSeverity2, hubAlert2, hubAlertsListResponse2, noticeSeveritySchema2, noticeStatusSchema2, NOTICE_SCOPE_REGEX2, noticeScopeSchema2, noticeLinkSchema2, createNoticeBody2, updateNoticeBody2, listNoticesQuery2, noticeIdParamSchema2, ADMIN_SKILL_NAME_REGEX2, adminSkillNameParam2, WAYAI_WORKSPACE_LAYOUT;
10406
10457
  var init_dist = __esm({
10407
10458
  "../../packages/core/dist/index.js"() {
10408
10459
  "use strict";
@@ -10626,6 +10677,7 @@ var init_dist = __esm({
10626
10677
  DATA_PROXY_MOUNT2 = "/data";
10627
10678
  DATA_PROXY_PREFIX2 = `/api${DATA_PROXY_MOUNT2}`;
10628
10679
  DATA_PROXY_ORG_QUERY_PARAM2 = "org_id";
10680
+ MAX_PROVISIONING_BODY_BYTES2 = 256 * 1024;
10629
10681
  dataProxyQuery2 = external_exports.object({
10630
10682
  [DATA_PROXY_ORG_QUERY_PARAM2]: external_exports.string().uuid().optional()
10631
10683
  });
@@ -13364,13 +13416,20 @@ var init_dist = __esm({
13364
13416
  });
13365
13417
  adminOrgAdminIdParam2 = external_exports.object({
13366
13418
  orgId: uuidSchema2,
13367
- adminId: uuidSchema2
13419
+ // `adminId` is a `member_grant.user_id`, which for a logged-in user is the
13420
+ // WorkOS `sub` (`user_01…`), not a UUID. Matches `orgAdminIdParam` on the
13421
+ // org-facing route.
13422
+ adminId: external_exports.string().min(1)
13368
13423
  });
13369
13424
  adminUserIdParam2 = external_exports.object({
13370
13425
  userId: uuidSchema2
13371
13426
  });
13427
+ PRICING_PLAN_ID_RE2 = /^pp-[a-z0-9]+(-[a-z0-9]+)*$/;
13372
13428
  adminPlanIdParam2 = external_exports.object({
13373
- planId: uuidSchema2
13429
+ planId: external_exports.string().refine(
13430
+ (value) => PRICING_PLAN_ID_RE2.test(value) || uuidSchema2.safeParse(value).success,
13431
+ { message: 'planId must be a pricing plan id such as "pp-free", or a UUID' }
13432
+ )
13374
13433
  });
13375
13434
  adminOrganizationsQuery2 = external_exports.object({
13376
13435
  page: external_exports.coerce.number().int().min(1).default(1),
@@ -13389,8 +13448,33 @@ var init_dist = __esm({
13389
13448
  value: external_exports.number().int().min(0, "value must be a non-negative number")
13390
13449
  });
13391
13450
  updatePlanBody2 = external_exports.object({
13392
- plan_type: external_exports.enum(["free", "paid"])
13393
- });
13451
+ plan_type: external_exports.enum(["free", "paid"]).optional(),
13452
+ /**
13453
+ * Move the start of the org's free-plan window. The operator lever for a window that
13454
+ * must be backdated — `free_plan_started_at` is otherwise only ever stamped to *now*
13455
+ * (org creation, `cancelBilling`, the lazy rollover), so an elapsed free window is
13456
+ * unreachable without it.
13457
+ *
13458
+ * Canonical form only (AGENTS.md › Timestamps): `timestampSchema` already refuses a
13459
+ * non-UTC offset and `isIsoTimestamp` pins the millisecond precision, because this
13460
+ * value is stored as-is and read back by `freePlanWindowStart()` / `freePlanWindowEnd()`
13461
+ * and by the Rekor projection's `window_start`.
13462
+ *
13463
+ * Past-or-now only. A future start freezes the org's window permanently:
13464
+ * `maybeRolloverFreePlanWindow` derives a NEGATIVE elapsed and so never archives the
13465
+ * metrics nor restamps the column, while the §2.6 trigger-5 sweep selects only windows
13466
+ * that have already passed — so nothing rolls the org over, its consumed operations
13467
+ * never reset, and past quota every AI turn is refused until a human re-patches.
13468
+ */
13469
+ free_plan_started_at: timestampSchema2.refine(isIsoTimestamp2, {
13470
+ message: "free_plan_started_at must be ISO-8601 UTC with millisecond precision (e.g. 2026-07-01T00:00:00.000Z)"
13471
+ }).refine((value) => Date.parse(value) <= Date.now(), {
13472
+ message: "free_plan_started_at must not be in the future"
13473
+ }).optional()
13474
+ }).strip().refine(
13475
+ (data) => Object.keys(data).length > 0,
13476
+ { message: "No fields to update" }
13477
+ );
13394
13478
  addAdminUserBody2 = external_exports.object({
13395
13479
  user_email: external_exports.string().email("user_email must be a valid email address")
13396
13480
  });
@@ -13449,6 +13533,18 @@ var init_dist = __esm({
13449
13533
  }
13450
13534
  }
13451
13535
  });
13536
+ adminRepairLegacyOrgGrantsBody2 = external_exports.object({
13537
+ scope: external_exports.enum(["all", "org"]),
13538
+ org_id: external_exports.string().uuid().optional(),
13539
+ dry_run: external_exports.boolean().optional().default(false)
13540
+ }).strict().superRefine((data, ctx) => {
13541
+ if (data.scope === "org" && !data.org_id) {
13542
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "scope=org requires org_id", path: ["org_id"] });
13543
+ }
13544
+ if (data.scope === "all" && data.org_id) {
13545
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "scope=all must not include org_id", path: ["org_id"] });
13546
+ }
13547
+ });
13452
13548
  updatePricingPlanBody2 = external_exports.object({
13453
13549
  display_name: external_exports.string().min(1).optional(),
13454
13550
  stripe_product_id: external_exports.string().optional(),
@@ -14149,6 +14245,10 @@ function hubsDirLabel(gitRoot) {
14149
14245
  if (!gitRoot) return path.join(WAYAI_LAYOUT.wsDir, WAYAI_LAYOUT.hubsSubdir);
14150
14246
  return path.relative(gitRoot, resolveLayout(gitRoot).hubsDir);
14151
14247
  }
14248
+ function basesDirLabel(gitRoot) {
14249
+ if (!gitRoot) return path.join(WAYAI_LAYOUT.wsDir, WAYAI_LAYOUT.basesSubdir);
14250
+ return path.relative(gitRoot, resolveLayout(gitRoot).basesDir);
14251
+ }
14152
14252
  function warnLayoutOnce(gitRoot) {
14153
14253
  const r = resolveLayout(gitRoot);
14154
14254
  if (r.legacyAlsoPresent) {
@@ -14640,24 +14740,24 @@ import * as path4 from "path";
14640
14740
  import * as readline from "readline";
14641
14741
  function prompt(question) {
14642
14742
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
14643
- return new Promise((resolve5) => {
14743
+ return new Promise((resolve7) => {
14644
14744
  rl.question(question, (answer) => {
14645
14745
  rl.close();
14646
- resolve5(answer.trim());
14746
+ resolve7(answer.trim());
14647
14747
  });
14648
14748
  });
14649
14749
  }
14650
14750
  function confirm(question) {
14651
14751
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
14652
- return new Promise((resolve5) => {
14752
+ return new Promise((resolve7) => {
14653
14753
  rl.question(`${question} [y/N]: `, (answer) => {
14654
14754
  rl.close();
14655
- resolve5(answer.trim().toLowerCase() === "y");
14755
+ resolve7(answer.trim().toLowerCase() === "y");
14656
14756
  });
14657
14757
  });
14658
14758
  }
14659
14759
  function promptSecret(question) {
14660
- return new Promise((resolve5) => {
14760
+ return new Promise((resolve7) => {
14661
14761
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
14662
14762
  const originalWrite = rl._writeToOutput;
14663
14763
  let firstWrite = true;
@@ -14673,18 +14773,18 @@ function promptSecret(question) {
14673
14773
  rl._writeToOutput = originalWrite;
14674
14774
  process.stdout.write("\n");
14675
14775
  rl.close();
14676
- resolve5(answer);
14776
+ resolve7(answer);
14677
14777
  });
14678
14778
  });
14679
14779
  }
14680
14780
  function readStdin() {
14681
- return new Promise((resolve5, reject) => {
14781
+ return new Promise((resolve7, reject) => {
14682
14782
  let data = "";
14683
14783
  process.stdin.setEncoding("utf-8");
14684
14784
  process.stdin.on("data", (chunk) => {
14685
14785
  data += chunk;
14686
14786
  });
14687
- process.stdin.on("end", () => resolve5(data.trim()));
14787
+ process.stdin.on("end", () => resolve7(data.trim()));
14688
14788
  process.stdin.on("error", reject);
14689
14789
  });
14690
14790
  }
@@ -15123,7 +15223,7 @@ var init_registry = __esm({
15123
15223
  disposition: "routed",
15124
15224
  surviving: "pull",
15125
15225
  clause: null,
15126
- shipped: false,
15226
+ shipped: true,
15127
15227
  reason: "One verb, workspace-relative, routing by subtree: `hubs/` targets preview hubs, `bases/` targets preview bases. An invocation spanning both is refused, never merged."
15128
15228
  },
15129
15229
  {
@@ -15131,7 +15231,7 @@ var init_registry = __esm({
15131
15231
  disposition: "routed",
15132
15232
  surviving: "push",
15133
15233
  clause: null,
15134
- shipped: false,
15234
+ shipped: true,
15135
15235
  reason: "Same as `pull`."
15136
15236
  }
15137
15237
  ];
@@ -15150,9 +15250,9 @@ function getVersionCachePath(filename = CLI_CACHE_FILE) {
15150
15250
  }
15151
15251
  function readVersionCache(filename = CLI_CACHE_FILE) {
15152
15252
  try {
15153
- const path31 = getVersionCachePath(filename);
15154
- if (!existsSync4(path31)) return null;
15155
- const parsed = JSON.parse(readFileSync5(path31, "utf-8"));
15253
+ const path36 = getVersionCachePath(filename);
15254
+ if (!existsSync4(path36)) return null;
15255
+ const parsed = JSON.parse(readFileSync5(path36, "utf-8"));
15156
15256
  if (typeof parsed.lastCheck !== "number") return null;
15157
15257
  if (parsed.latest !== null && typeof parsed.latest !== "string") return null;
15158
15258
  return parsed;
@@ -15172,10 +15272,10 @@ function isVersionCacheStale(filename = CLI_CACHE_FILE, maxAgeMs = MAX_AGE_24H_M
15172
15272
  return Date.now() - cache.lastCheck > maxAgeMs;
15173
15273
  }
15174
15274
  function writeVersionCache(filename, cache) {
15175
- const path31 = getVersionCachePath(filename);
15176
- const dir = dirname3(path31);
15275
+ const path36 = getVersionCachePath(filename);
15276
+ const dir = dirname3(path36);
15177
15277
  if (!existsSync4(dir)) mkdirSync(dir, { recursive: true });
15178
- writeFileSync2(path31, JSON.stringify(cache));
15278
+ writeFileSync2(path36, JSON.stringify(cache));
15179
15279
  }
15180
15280
  function touchVersionCache(filename) {
15181
15281
  writeVersionCache(filename, { lastCheck: Date.now(), latest: readVersionCache(filename)?.latest ?? null });
@@ -15214,14 +15314,14 @@ function parseFrontmatterVersion(content) {
15214
15314
  function findInstalledSkills(projectRoot, paths = SKILL_INSTALL_PATHS) {
15215
15315
  const found = [];
15216
15316
  for (const rel of paths) {
15217
- const path31 = join7(projectRoot, rel);
15218
- if (!existsSync5(path31)) continue;
15317
+ const path36 = join7(projectRoot, rel);
15318
+ if (!existsSync5(path36)) continue;
15219
15319
  let version = null;
15220
15320
  try {
15221
- version = parseFrontmatterVersion(readFileSync6(path31, "utf-8"));
15321
+ version = parseFrontmatterVersion(readFileSync6(path36, "utf-8"));
15222
15322
  } catch {
15223
15323
  }
15224
- found.push({ path: path31, version });
15324
+ found.push({ path: path36, version });
15225
15325
  }
15226
15326
  return found;
15227
15327
  }
@@ -15682,7 +15782,7 @@ async function validateToken(apiUrl, token) {
15682
15782
  }
15683
15783
  }
15684
15784
  function startCallbackServer(port, expectedState, timeoutMs = 12e4) {
15685
- return new Promise((resolve5, reject) => {
15785
+ return new Promise((resolve7, reject) => {
15686
15786
  const server = http.createServer((req, res) => {
15687
15787
  const url = new URL(req.url || "/", `http://127.0.0.1:${port}`);
15688
15788
  if (url.pathname === "/callback") {
@@ -15708,7 +15808,7 @@ function startCallbackServer(port, expectedState, timeoutMs = 12e4) {
15708
15808
  res.writeHead(200, { "Content-Type": "text/html" });
15709
15809
  res.end("<html><body><h2>Login successful!</h2><p>You can close this tab and return to your terminal.</p></body></html>");
15710
15810
  server.close();
15711
- resolve5({ code, port });
15811
+ resolve7({ code, port });
15712
15812
  } else {
15713
15813
  res.writeHead(400, { "Content-Type": "text/html" });
15714
15814
  res.end("<html><body><h2>Login failed</h2><p>No authorization code received</p></body></html>");
@@ -15919,10 +16019,10 @@ import * as readline2 from "readline";
15919
16019
  function prompt2(question, defaultValue) {
15920
16020
  const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
15921
16021
  const display = defaultValue ? `${question} [${defaultValue}]: ` : `${question}: `;
15922
- return new Promise((resolve5) => {
16022
+ return new Promise((resolve7) => {
15923
16023
  rl.question(display, (answer) => {
15924
16024
  rl.close();
15925
- resolve5(answer.trim() || defaultValue || "");
16025
+ resolve7(answer.trim() || defaultValue || "");
15926
16026
  });
15927
16027
  });
15928
16028
  }
@@ -16040,8 +16140,8 @@ async function tryOpenBrowser(url) {
16040
16140
  cmd = "xdg-open";
16041
16141
  args2 = [url];
16042
16142
  }
16043
- return new Promise((resolve5) => {
16044
- execFile(cmd, args2, (err) => resolve5(!err));
16143
+ return new Promise((resolve7) => {
16144
+ execFile(cmd, args2, (err) => resolve7(!err));
16045
16145
  });
16046
16146
  } catch {
16047
16147
  return false;
@@ -16801,6 +16901,15 @@ function ensureRealSubdirNoSymlink(root, target, create) {
16801
16901
  }
16802
16902
  return true;
16803
16903
  }
16904
+ function readFileNoFollow(root, abs) {
16905
+ if (!ensureRealSubdirNoSymlink(root, path11.dirname(abs), false)) return null;
16906
+ try {
16907
+ if (!fs9.lstatSync(abs).isFile()) return null;
16908
+ return fs9.readFileSync(abs);
16909
+ } catch {
16910
+ return null;
16911
+ }
16912
+ }
16804
16913
  function writeFileNoFollow(root, abs, data) {
16805
16914
  const parent = path11.dirname(abs);
16806
16915
  if (!ensureRealSubdirNoSymlink(root, parent, true)) return false;
@@ -18051,155 +18160,1367 @@ var init_hub_materializer = __esm({
18051
18160
  }
18052
18161
  });
18053
18162
 
18054
- // src/commands/push.ts
18055
- var push_exports = {};
18056
- __export(push_exports, {
18057
- autoRenameAgentFiles: () => autoRenameAgentFiles,
18058
- createAndPushNewHub: () => createAndPushNewHub,
18059
- printErrors: () => printErrors,
18060
- printLocalFileChanges: () => printLocalFileChanges,
18061
- printSyncResult: () => printSyncResult,
18062
- printWarnings: () => printWarnings,
18063
- pushCommand: () => pushCommand,
18064
- reportUnresolvedPushTarget: () => reportUnresolvedPushTarget,
18065
- selectExistingHub: () => selectExistingHub,
18066
- shouldWarnIgnoredPreviewLabel: () => shouldWarnIgnoredPreviewLabel,
18067
- syncAfterPush: () => syncAfterPush
18163
+ // src/lib/terminal-output.ts
18164
+ import { stripVTControlCharacters } from "util";
18165
+ function sanitizeTerminalText(value) {
18166
+ const normalizedNewlines = value.replace(/\r\n?/g, "\n");
18167
+ return stripVTControlCharacters(normalizedNewlines).replace(
18168
+ /[\u0000-\u0009\u000b-\u001f\u007f-\u009f]/g,
18169
+ ""
18170
+ );
18171
+ }
18172
+ var init_terminal_output = __esm({
18173
+ "src/lib/terminal-output.ts"() {
18174
+ "use strict";
18175
+ }
18176
+ });
18177
+
18178
+ // src/lib/base-id.ts
18179
+ function isValidBaseId(id) {
18180
+ return BASE_ID_RE.test(id);
18181
+ }
18182
+ var BASE_ID_RE;
18183
+ var init_base_id = __esm({
18184
+ "src/lib/base-id.ts"() {
18185
+ "use strict";
18186
+ BASE_ID_RE = /^(?!\.\.?$)[A-Za-z0-9._-]{1,256}$/;
18187
+ }
18068
18188
  });
18189
+
18190
+ // src/lib/base-workspace.ts
18069
18191
  import * as fs14 from "fs";
18070
18192
  import * as path17 from "path";
18071
18193
  import * as yaml6 from "js-yaml";
18072
- function parseArgs4(args2) {
18073
- let autoConfirm = false;
18074
- let hubSelector;
18075
- let label;
18076
- for (let i = 0; i < args2.length; i++) {
18077
- const arg = args2[i];
18078
- if (arg === "--yes" || arg === "-y") {
18079
- autoConfirm = true;
18080
- } else if (arg === "--hub" && args2[i + 1]) {
18081
- hubSelector = args2[++i];
18082
- } else if (arg === "--label" && args2[i + 1]) {
18083
- label = args2[++i];
18084
- }
18194
+ function readBaseMeta(folder) {
18195
+ const bytes = readFileNoFollow(folder, path17.join(folder, BASE_META_FILE));
18196
+ if (bytes === null) return null;
18197
+ let doc;
18198
+ try {
18199
+ doc = yaml6.load(bytes.toString("utf-8"));
18200
+ } catch {
18201
+ return null;
18085
18202
  }
18086
- return { autoConfirm, hubSelector, label };
18087
- }
18088
- function shouldWarnIgnoredPreviewLabel(localLabel, serverLabel) {
18089
- return Boolean(localLabel) && serverLabel !== void 0 && localLabel !== serverLabel;
18203
+ if (!doc || typeof doc !== "object" || Array.isArray(doc)) return null;
18204
+ return doc;
18090
18205
  }
18091
- function printSyncResult(result) {
18092
- const applyErrors = result.apply_errors ?? result.errors;
18093
- if (applyErrors && applyErrors.length > 0) {
18094
- printErrors(applyErrors);
18095
- throw expected(`Sync failed with ${applyErrors.length} error(s). No completion was reported; inspect the errors above.`);
18206
+ function listBaseFolders(basesDir) {
18207
+ let entries;
18208
+ try {
18209
+ entries = fs14.readdirSync(basesDir).filter((entry) => !entry.startsWith("."));
18210
+ } catch {
18211
+ return [];
18096
18212
  }
18097
- console.log(`
18098
- Sync complete. Preview hub: ${result.preview_hub_id}`);
18099
- const c = result.changes;
18100
- const parts = [];
18101
- if (c.hub_updated) parts.push("hub updated");
18102
- if (c.connections_created > 0) parts.push(`${c.connections_created} connection(s) created`);
18103
- if (c.connections_updated > 0) parts.push(`${c.connections_updated} connection(s) updated`);
18104
- if (c.connections_deleted > 0) parts.push(`${c.connections_deleted} connection(s) deleted`);
18105
- if (c.agents_created > 0) parts.push(`${c.agents_created} agent(s) created`);
18106
- if (c.agents_updated > 0) parts.push(`${c.agents_updated} agent(s) updated`);
18107
- if (c.agents_deleted > 0) parts.push(`${c.agents_deleted} agent(s) deleted`);
18108
- if (c.tools_created > 0) parts.push(`${c.tools_created} tool(s) created`);
18109
- if (c.tools_updated > 0) parts.push(`${c.tools_updated} tool(s) updated`);
18110
- if (c.tools_deleted > 0) parts.push(`${c.tools_deleted} tool(s) deleted`);
18111
- if (c.states_created > 0) parts.push(`${c.states_created} state(s) created`);
18112
- if (c.states_updated > 0) parts.push(`${c.states_updated} state(s) updated`);
18113
- if (c.states_deleted > 0) parts.push(`${c.states_deleted} state(s) deleted`);
18114
- if (c.evals_created > 0) parts.push(`${c.evals_created} eval(s) created`);
18115
- if (c.evals_updated > 0) parts.push(`${c.evals_updated} eval(s) updated`);
18116
- if (c.evals_deleted > 0) parts.push(`${c.evals_deleted} eval(s) deleted`);
18117
- if (c.journeys_created > 0) parts.push(`${c.journeys_created} journey(s) created`);
18118
- if (c.journeys_updated > 0) parts.push(`${c.journeys_updated} journey(s) updated`);
18119
- if (c.journeys_deleted > 0) parts.push(`${c.journeys_deleted} journey(s) deleted`);
18120
- if (c.teams_created > 0) parts.push(`${c.teams_created} team(s) created`);
18121
- if (c.teams_updated > 0) parts.push(`${c.teams_updated} team(s) updated`);
18122
- if (c.teams_deleted > 0) parts.push(`${c.teams_deleted} team(s) deleted`);
18123
- if (c.resources_created > 0) parts.push(`${c.resources_created} resource(s) created`);
18124
- if (c.resources_updated > 0) parts.push(`${c.resources_updated} resource(s) updated`);
18125
- if (c.resources_deleted > 0) parts.push(`${c.resources_deleted} resource(s) deleted`);
18126
- if (c.resource_files_uploaded > 0) parts.push(`${c.resource_files_uploaded} resource file(s) uploaded`);
18127
- if (c.resource_files_deleted > 0) parts.push(`${c.resource_files_deleted} resource file(s) deleted`);
18128
- if (c.resource_links_created > 0) parts.push(`${c.resource_links_created} resource link(s) created`);
18129
- if (c.resource_links_updated > 0) parts.push(`${c.resource_links_updated} resource link(s) updated`);
18130
- if (c.resource_links_deleted > 0) parts.push(`${c.resource_links_deleted} resource link(s) deleted`);
18131
- if (c.outbound_contacts_created > 0) parts.push(`${c.outbound_contacts_created} outbound contact(s) created`);
18132
- if (c.outbound_contacts_updated > 0) parts.push(`${c.outbound_contacts_updated} outbound contact(s) updated`);
18133
- if (c.outbound_contacts_deleted > 0) parts.push(`${c.outbound_contacts_deleted} outbound contact(s) deleted`);
18134
- if (c.outbound_lists_created > 0) parts.push(`${c.outbound_lists_created} outbound list(s) created`);
18135
- if (c.outbound_lists_updated > 0) parts.push(`${c.outbound_lists_updated} outbound list(s) updated`);
18136
- if (c.outbound_lists_deleted > 0) parts.push(`${c.outbound_lists_deleted} outbound list(s) deleted`);
18137
- if (c.outbound_schedules_created > 0) parts.push(`${c.outbound_schedules_created} outbound schedule(s) created`);
18138
- if (c.outbound_schedules_updated > 0) parts.push(`${c.outbound_schedules_updated} outbound schedule(s) updated`);
18139
- if (c.outbound_schedules_deleted > 0) parts.push(`${c.outbound_schedules_deleted} outbound schedule(s) deleted`);
18140
- if (parts.length > 0) {
18141
- console.log(`Changes: ${parts.join(", ")}`);
18213
+ const out = [];
18214
+ for (const name of entries.sort()) {
18215
+ const folder = path17.join(basesDir, name);
18216
+ if (!isDirectory(folder)) continue;
18217
+ const meta = readBaseMeta(folder);
18218
+ if (meta) out.push({ folder, meta });
18142
18219
  }
18143
- if (result.warnings && result.warnings.length > 0) {
18144
- printWarnings(result.warnings.map((w) => w.message));
18220
+ return out;
18221
+ }
18222
+ function isProductionFolder(meta) {
18223
+ return meta.environment === "production";
18224
+ }
18225
+ function filterEditableBases(bases) {
18226
+ return bases.filter((b) => !isProductionFolder(b.meta));
18227
+ }
18228
+ function isUnder(parent, child) {
18229
+ const rel = path17.relative(parent, child);
18230
+ return rel === "" || !rel.startsWith("..") && !path17.isAbsolute(rel);
18231
+ }
18232
+ function findEnclosingBaseFolder(basesDir, cwd) {
18233
+ let dir = path17.resolve(cwd);
18234
+ const stop = path17.resolve(basesDir);
18235
+ while (isUnder(stop, dir)) {
18236
+ const meta = readBaseMeta(dir);
18237
+ if (meta) return { folder: dir, meta };
18238
+ const parent = path17.dirname(dir);
18239
+ if (parent === dir) break;
18240
+ dir = parent;
18145
18241
  }
18242
+ return null;
18146
18243
  }
18147
- function printWarnings(warnings) {
18148
- if (warnings.length === 0) return;
18149
- console.log(`
18150
- \x1B[33mWarnings (${warnings.length}):\x1B[0m`);
18151
- for (const w of warnings) {
18152
- console.log(` \x1B[33m! ${w}\x1B[0m`);
18244
+ function folderForSelector(basesDir, selector) {
18245
+ assertValidBaseSelector(selector);
18246
+ return path17.join(basesDir, selector);
18247
+ }
18248
+ function assertValidBaseSelector(selector, source = "base") {
18249
+ if (!isValidBaseId(selector)) {
18250
+ throw expected(
18251
+ `Invalid ${source} "${selector}". Base ids are slugs \u2014 letters, digits, dot, dash and underscore only, with no path separators.`
18252
+ );
18153
18253
  }
18154
18254
  }
18155
- function printErrors(errors) {
18156
- if (errors.length === 0) return;
18157
- console.error(`
18158
- \x1B[31mErrors (${errors.length}):\x1B[0m`);
18159
- for (const error of errors) {
18160
- const message = typeof error === "string" ? error : error.message;
18161
- console.error(` \x1B[31m! ${message}\x1B[0m`);
18255
+ function resolveBaseTarget(gitRoot, selector, cwd = process.cwd()) {
18256
+ const basesDir = resolveBasesDir(gitRoot);
18257
+ if (selector) {
18258
+ const folder = folderForSelector(basesDir, selector);
18259
+ if (!isUnder(basesDir, folder)) {
18260
+ throw expected(`Refusing to target ${folder}: it is outside ${basesDir}.`);
18261
+ }
18262
+ return { folder, exists: hasBaseMetaFile(folder), meta: readBaseMeta(folder) };
18162
18263
  }
18264
+ const enclosing = findEnclosingBaseFolder(basesDir, cwd);
18265
+ if (enclosing) return { folder: enclosing.folder, exists: true, meta: enclosing.meta };
18266
+ const editable = filterEditableBases(listBaseFolders(basesDir));
18267
+ if (editable.length === 1) {
18268
+ return { folder: editable[0].folder, exists: true, meta: editable[0].meta };
18269
+ }
18270
+ const label = basesDirLabel(gitRoot);
18271
+ if (editable.length === 0) {
18272
+ throw expected(
18273
+ `No base folders found in ${label}/. Pass a base id to fetch one for the first time (e.g. \`wayai pull bases/<base>\`).`
18274
+ );
18275
+ }
18276
+ throw expected(
18277
+ [
18278
+ `Multiple bases found in ${label}/. Pass --base <id|folder-name> to choose, or run from inside a base folder:`,
18279
+ ...editable.map((b) => ` ${path17.basename(b.folder)} (${b.meta.base_id ?? "not created yet"})`)
18280
+ ].join("\n")
18281
+ );
18163
18282
  }
18164
- function printLocalFileChanges(delta) {
18165
- if (delta.changed.length === 0 && delta.removed.length === 0) {
18166
- console.log("Local files already in sync.");
18167
- return;
18283
+ function targetBaseId(target, selector) {
18284
+ if (target.meta?.base_id) return target.meta.base_id;
18285
+ if (selector && !selector.includes("/") && !selector.includes(path17.sep)) return selector;
18286
+ return target.exists ? null : path17.basename(target.folder);
18287
+ }
18288
+ function hasBaseMetaFile(folder) {
18289
+ try {
18290
+ return fs14.lstatSync(path17.join(folder, BASE_META_FILE)).isFile();
18291
+ } catch {
18292
+ return false;
18168
18293
  }
18169
- console.log("Local files updated from server:");
18170
- const emit = (paths, sigil) => {
18171
- const sorted = [...paths].sort();
18172
- for (const p of sorted.slice(0, LOCAL_CHANGE_LIST_CAP)) console.log(` ${sigil} ${p}`);
18173
- if (sorted.length > LOCAL_CHANGE_LIST_CAP) {
18174
- console.log(` \u2026and ${sorted.length - LOCAL_CHANGE_LIST_CAP} more ${sigil === "-" ? "removed" : "changed"}`);
18294
+ }
18295
+ var BASE_META_FILE;
18296
+ var init_base_workspace = __esm({
18297
+ "src/lib/base-workspace.ts"() {
18298
+ "use strict";
18299
+ init_layout();
18300
+ init_expected();
18301
+ init_base_id();
18302
+ init_fs_safety();
18303
+ BASE_META_FILE = "base.yaml";
18304
+ }
18305
+ });
18306
+
18307
+ // src/lib/subtree-routing.ts
18308
+ import * as fs15 from "fs";
18309
+ import * as path18 from "path";
18310
+ import * as yaml7 from "js-yaml";
18311
+ function readRepoDefaults(gitRoot) {
18312
+ const file = path18.join(gitRoot, WAYAI_LAYOUT.wsDir, REPO_DEFAULTS_FILE);
18313
+ let doc;
18314
+ try {
18315
+ doc = yaml7.load(fs15.readFileSync(file, "utf-8"));
18316
+ } catch {
18317
+ return {};
18318
+ }
18319
+ if (!doc || typeof doc !== "object") return {};
18320
+ const raw = doc;
18321
+ const str = (v) => {
18322
+ if (typeof v !== "string" || !v.trim()) return void 0;
18323
+ const value = v.trim();
18324
+ if (value.includes("/") || value.includes(path18.sep) || value === "." || value === "..") {
18325
+ console.warn(
18326
+ `Warning: ignoring ${JSON.stringify(value)} in ${WAYAI_LAYOUT.wsDir}/${REPO_DEFAULTS_FILE} \u2014 a default names a hub or base, not a path.`
18327
+ );
18328
+ return void 0;
18175
18329
  }
18330
+ return value;
18176
18331
  };
18177
- emit(delta.removed, "-");
18178
- emit(delta.changed, "~");
18332
+ return { default_hub: str(raw.default_hub), default_base: str(raw.default_base) };
18179
18333
  }
18180
- async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId, remoteConfig) {
18181
- const agentsDir = path17.join(hubFolder, "agents");
18182
- let agentsWithIds = [];
18183
- if (fs14.existsSync(agentsDir)) {
18184
- const yamlFiles = fs14.readdirSync(agentsDir).filter((f) => f.endsWith(".yaml"));
18185
- for (const file of yamlFiles) {
18186
- try {
18187
- const content = fs14.readFileSync(path17.join(agentsDir, file), "utf-8");
18188
- const agent = yaml6.load(content);
18189
- if (agent?.id && agent.name) {
18190
- agentsWithIds.push({ id: agent.id, name: agent.name });
18191
- }
18192
- } catch {
18193
- console.warn(` Warning: could not parse agents/${file}, skipping`);
18334
+ function parseRoutingTokens(args2) {
18335
+ const tokens = {};
18336
+ for (let i = 0; i < args2.length; i++) {
18337
+ const arg = args2[i];
18338
+ const eq = arg.indexOf("=");
18339
+ const name = eq === -1 ? arg : arg.slice(0, eq);
18340
+ if (VALUE_FLAGS.has(name)) {
18341
+ const value = eq === -1 ? args2[i + 1] : arg.slice(eq + 1);
18342
+ if (value !== void 0) {
18343
+ if (name === "--hub") tokens.hubFlag ??= value;
18344
+ if (name === "--base") tokens.baseFlag ??= value;
18345
+ if (name === "--org") tokens.orgFlag ??= value;
18346
+ if (eq === -1) i++;
18194
18347
  }
18348
+ continue;
18195
18349
  }
18350
+ if (arg.startsWith("-")) continue;
18351
+ tokens.positional ??= arg;
18196
18352
  }
18197
- if (agentsWithIds.length === 0) {
18198
- const yamlPath = resolveHubYamlPath(hubFolder);
18199
- if (!yamlPath) return;
18200
- const yamlContent = fs14.readFileSync(yamlPath, "utf-8");
18201
- const config = yaml6.load(yamlContent);
18202
- agentsWithIds = (config.agents || []).filter((a) => !!a.id && !!a.name);
18353
+ return tokens;
18354
+ }
18355
+ function firstSegment(p) {
18356
+ const normalized = p.split(path18.sep).join("/");
18357
+ const [head] = normalized.split("/").filter(Boolean);
18358
+ return head ?? p;
18359
+ }
18360
+ function selectorSubtree(layout, selector, cwd) {
18361
+ const parts = selector.split(path18.sep).join("/").split("/").filter(Boolean);
18362
+ const qualified = parts[0] === WAYAI_LAYOUT.wsDir ? parts.slice(1) : parts;
18363
+ if (qualified.length > 1) {
18364
+ if (qualified[0] === WAYAI_LAYOUT.hubsSubdir) return { kind: "hubs", target: qualified[1] };
18365
+ if (qualified[0] === WAYAI_LAYOUT.basesSubdir) return { kind: "bases", target: qualified[1] };
18366
+ }
18367
+ if (!layout) return { kind: "unknown" };
18368
+ const { hubsDir, basesDir } = layout;
18369
+ if (selector.includes("/") || selector.includes(path18.sep)) {
18370
+ const abs = path18.resolve(cwd, selector);
18371
+ if (isUnder(hubsDir, abs)) return { kind: "hubs", target: firstSegment(path18.relative(hubsDir, abs)) };
18372
+ if (isUnder(basesDir, abs)) return { kind: "bases", target: firstSegment(path18.relative(basesDir, abs)) };
18373
+ return { kind: "unknown" };
18374
+ }
18375
+ const inHubs = isDirectory(path18.join(hubsDir, selector));
18376
+ const inBases = isDirectory(path18.join(basesDir, selector));
18377
+ if (inHubs && inBases) return { kind: "both", target: selector };
18378
+ if (inHubs) return { kind: "hubs", target: selector };
18379
+ if (inBases) return { kind: "bases", target: selector };
18380
+ return { kind: "unknown" };
18381
+ }
18382
+ function listCandidates(layout) {
18383
+ const hubs = [
18384
+ ...filterPreviewHubs(scanWorkspaceHubs(layout.hubsDir)).map((h) => h.hubFolder),
18385
+ ...scanNewHubs(layout.hubsDir).map((h) => h.hubFolder)
18386
+ ];
18387
+ const bases = filterEditableBases(listBaseFolders(layout.basesDir)).map((b) => b.folder);
18388
+ return [
18389
+ ...hubs.map((folder) => ({ subtree: "hubs", name: path18.basename(folder) })),
18390
+ ...bases.map((folder) => ({ subtree: "bases", name: path18.basename(folder) }))
18391
+ ];
18392
+ }
18393
+ function mixedInvocationRefusal(verb, hubTarget, baseTarget) {
18394
+ const hub = sanitizeTerminalText(hubTarget);
18395
+ const base = sanitizeTerminalText(baseTarget);
18396
+ return [
18397
+ `Refusing a mixed ${verb}: this invocation spans both subtrees.`,
18398
+ ` ${WAYAI_LAYOUT.hubsSubdir}/ -> ${hub}`,
18399
+ ` ${WAYAI_LAYOUT.basesSubdir}/ -> ${base}`,
18400
+ "",
18401
+ "Run one at a time:",
18402
+ ` wayai ${verb} ${WAYAI_LAYOUT.hubsSubdir}/${hub}`,
18403
+ ` wayai ${verb} ${WAYAI_LAYOUT.basesSubdir}/${base}`
18404
+ ].join("\n");
18405
+ }
18406
+ function routeSubtree(options) {
18407
+ const { verb, args: args2, gitRoot } = options;
18408
+ const cwd = options.cwd ?? process.cwd();
18409
+ const { hubFlag, baseFlag, positional, orgFlag } = parseRoutingTokens(args2);
18410
+ if (orgFlag !== void 0) {
18411
+ return {
18412
+ ok: false,
18413
+ refusal: [
18414
+ `\`wayai ${verb}\` does not take --org: it operates on the organization named by .wayai.yaml at the repo root.`,
18415
+ "",
18416
+ "To act on another organization:",
18417
+ " wayai bases <command> --org <uuid> # the Data surface honors it",
18418
+ " # or run from a checkout whose .wayai.yaml names that organization"
18419
+ ].join("\n")
18420
+ };
18421
+ }
18422
+ const layout = gitRoot ? resolveLayout(gitRoot) : null;
18423
+ if (hubFlag !== void 0 && baseFlag !== void 0) {
18424
+ return { ok: false, refusal: mixedInvocationRefusal(verb, hubFlag, baseFlag) };
18425
+ }
18426
+ const fromPositional = positional !== void 0 ? selectorSubtree(layout, positional, cwd) : void 0;
18427
+ if (fromPositional?.kind === "both") {
18428
+ return {
18429
+ ok: false,
18430
+ refusal: mixedInvocationRefusal(verb, fromPositional.target, fromPositional.target)
18431
+ };
18432
+ }
18433
+ if (hubFlag !== void 0) {
18434
+ if (fromPositional?.kind === "bases") {
18435
+ return { ok: false, refusal: mixedInvocationRefusal(verb, hubFlag, fromPositional.target) };
18436
+ }
18437
+ return { ok: true, subtree: "hubs", selector: hubFlag };
18438
+ }
18439
+ if (baseFlag !== void 0) {
18440
+ if (fromPositional?.kind === "hubs") {
18441
+ return { ok: false, refusal: mixedInvocationRefusal(verb, fromPositional.target, baseFlag) };
18442
+ }
18443
+ return { ok: true, subtree: "bases", selector: baseFlag };
18444
+ }
18445
+ if (fromPositional?.kind === "hubs" || fromPositional?.kind === "bases") {
18446
+ return { ok: true, subtree: fromPositional.kind, selector: fromPositional.target };
18447
+ }
18448
+ const carried = positional;
18449
+ if (!gitRoot || !layout) return { ok: true, subtree: "hubs", selector: carried };
18450
+ const { hubsDir, basesDir } = layout;
18451
+ if (isUnder(hubsDir, cwd)) return { ok: true, subtree: "hubs", selector: carried };
18452
+ if (isUnder(basesDir, cwd)) return { ok: true, subtree: "bases", selector: carried };
18453
+ const defaults = readRepoDefaults(gitRoot);
18454
+ if (defaults.default_hub && defaults.default_base) {
18455
+ return {
18456
+ ok: false,
18457
+ refusal: mixedInvocationRefusal(verb, defaults.default_hub, defaults.default_base)
18458
+ };
18459
+ }
18460
+ if (defaults.default_hub) return { ok: true, subtree: "hubs", selector: carried ?? defaults.default_hub };
18461
+ if (defaults.default_base) return { ok: true, subtree: "bases", selector: carried ?? defaults.default_base };
18462
+ const candidates = listCandidates(layout);
18463
+ if (candidates.length === 1) {
18464
+ return { ok: true, subtree: candidates[0].subtree, selector: carried };
18465
+ }
18466
+ const hubCandidates = candidates.filter((c) => c.subtree === "hubs");
18467
+ const baseCandidates = candidates.filter((c) => c.subtree === "bases");
18468
+ if (hubCandidates.length > 0 && baseCandidates.length > 0) {
18469
+ return {
18470
+ ok: false,
18471
+ refusal: mixedInvocationRefusal(verb, hubCandidates[0].name, baseCandidates[0].name)
18472
+ };
18473
+ }
18474
+ if (baseCandidates.length > 0) return { ok: true, subtree: "bases", selector: carried };
18475
+ return { ok: true, subtree: "hubs", selector: carried };
18476
+ }
18477
+ function requireSubtree(verb, args2, gitRoot) {
18478
+ const result = routeSubtree({ verb, args: args2, gitRoot });
18479
+ if (!result.ok) {
18480
+ console.error(result.refusal);
18481
+ process.exit(1);
18482
+ }
18483
+ return { subtree: result.subtree, selector: result.selector };
18484
+ }
18485
+ var REPO_DEFAULTS_FILE, VALUE_FLAGS;
18486
+ var init_subtree_routing = __esm({
18487
+ "src/lib/subtree-routing.ts"() {
18488
+ "use strict";
18489
+ init_layout();
18490
+ init_terminal_output();
18491
+ init_workspace();
18492
+ init_base_workspace();
18493
+ REPO_DEFAULTS_FILE = "wayai.yaml";
18494
+ VALUE_FLAGS = /* @__PURE__ */ new Set(["--hub", "--base", "--label", "--org"]);
18495
+ }
18496
+ });
18497
+
18498
+ // src/data/org-context.ts
18499
+ function setDataOrgOverride(orgId) {
18500
+ override = orgId;
18501
+ }
18502
+ function getDataOrgOverride() {
18503
+ return override;
18504
+ }
18505
+ var override;
18506
+ var init_org_context = __esm({
18507
+ "src/data/org-context.ts"() {
18508
+ "use strict";
18509
+ }
18510
+ });
18511
+
18512
+ // src/data/client.ts
18513
+ async function createDataClient(orgId) {
18514
+ const { config, accessToken } = await requireAuth();
18515
+ const api = new ApiClient({ apiUrl: config.api_url, accessToken });
18516
+ const selected = orgId ?? getDataOrgOverride();
18517
+ if (selected !== void 0 && !UUID_RE2.test(selected)) {
18518
+ throw expected(`Invalid --org: ${JSON.stringify(selected)}. Expected an organization UUID.`);
18519
+ }
18520
+ const org = selected ?? readRepoConfig()?.organization_id;
18521
+ return {
18522
+ async request(method, path36, body) {
18523
+ const envelope = await api.dataRequest(method, path36, body, org);
18524
+ return envelope.data;
18525
+ },
18526
+ async requestRaw(method, path36, body) {
18527
+ const body_ = await api.dataRequest(method, path36, body, org);
18528
+ return body_;
18529
+ },
18530
+ async collectPages(makePath) {
18531
+ const all = [];
18532
+ const seen = /* @__PURE__ */ new Set();
18533
+ let cursor;
18534
+ for (let page = 0; page < MAX_PAGES; page++) {
18535
+ const { data, meta } = await api.dataRequest("GET", makePath(cursor), void 0, org);
18536
+ for (const row of data ?? []) all.push(row);
18537
+ cursor = meta?.has_more ? meta.cursor : void 0;
18538
+ if (cursor === void 0) break;
18539
+ if (seen.has(cursor)) break;
18540
+ seen.add(cursor);
18541
+ }
18542
+ return all;
18543
+ },
18544
+ async upload(v1Path, bytes, contentType, headers) {
18545
+ const envelope = await api.dataUpload(v1Path, bytes, contentType, org, headers);
18546
+ return envelope.data;
18547
+ },
18548
+ download(v1Path) {
18549
+ return api.dataDownload(v1Path, org);
18550
+ },
18551
+ url(v1Path) {
18552
+ return api.dataUrl(v1Path, org);
18553
+ }
18554
+ };
18555
+ }
18556
+ function dataErrorEnvelope(err) {
18557
+ if (!(err instanceof ApiError)) return null;
18558
+ try {
18559
+ const parsed = JSON.parse(err.body);
18560
+ return parsed?.error ?? null;
18561
+ } catch {
18562
+ return null;
18563
+ }
18564
+ }
18565
+ function dataErrorCode(err) {
18566
+ const code = dataErrorEnvelope(err)?.code;
18567
+ return typeof code === "string" && code ? code : null;
18568
+ }
18569
+ function dataErrorDetails(err) {
18570
+ const details = dataErrorEnvelope(err)?.details;
18571
+ return details && typeof details === "object" ? details : void 0;
18572
+ }
18573
+ var MAX_PAGES;
18574
+ var init_client = __esm({
18575
+ "src/data/client.ts"() {
18576
+ "use strict";
18577
+ init_auth();
18578
+ init_api_client();
18579
+ init_repo_config();
18580
+ init_utils();
18581
+ init_expected();
18582
+ init_org_context();
18583
+ MAX_PAGES = 1e3;
18584
+ }
18585
+ });
18586
+
18587
+ // src/lib/base-binding.ts
18588
+ var binding2, getBaseBindingPath, readBaseBinding, writeBaseBinding, clearBaseBinding, autoBindBaseIfUnbound, assertBaseMatchesBinding, assertNoBindingBlocksBaseCreation;
18589
+ var init_base_binding = __esm({
18590
+ "src/lib/base-binding.ts"() {
18591
+ "use strict";
18592
+ init_base_id();
18593
+ init_worktree_binding();
18594
+ binding2 = createWorktreeBinding({
18595
+ filename: "wayai-base-binding",
18596
+ isValidId: isValidBaseId,
18597
+ noun: "base",
18598
+ idLabel: "base id (must be a slug)",
18599
+ unbindCommand: "wayai bases unbind",
18600
+ useCommand: "wayai bases use"
18601
+ });
18602
+ getBaseBindingPath = binding2.getBindingPath;
18603
+ readBaseBinding = binding2.readBinding;
18604
+ writeBaseBinding = binding2.writeBinding;
18605
+ clearBaseBinding = binding2.clearBinding;
18606
+ autoBindBaseIfUnbound = binding2.autoBindIfUnbound;
18607
+ assertBaseMatchesBinding = binding2.assertMatchesBinding;
18608
+ assertNoBindingBlocksBaseCreation = binding2.assertNoBindingBlocksCreation;
18609
+ }
18610
+ });
18611
+
18612
+ // src/data/helpers.ts
18613
+ import { readFileSync as readFileSync16 } from "fs";
18614
+ function pathSegment(id, label = "id") {
18615
+ if (!isValidBaseId(id)) {
18616
+ throw expected(
18617
+ `Invalid ${label}: ${JSON.stringify(id)}. Ids are slugs \u2014 letters, digits, dot, dash and underscore only.`
18618
+ );
18619
+ }
18620
+ return encodeURIComponent(id);
18621
+ }
18622
+ function foreignSegment(value, label = "id") {
18623
+ if (value === "." || value === "..") {
18624
+ throw expected(`Invalid ${label}: ${JSON.stringify(value)} is a path traversal segment.`);
18625
+ }
18626
+ return encodeURIComponent(value);
18627
+ }
18628
+ function pathSegments(value, label = "path") {
18629
+ return value.split("/").map((segment) => foreignSegment(segment, label)).join("/");
18630
+ }
18631
+ function parseData(data, flag) {
18632
+ const prefix = flag ? `${flag}: ` : "";
18633
+ const source = data.startsWith("@") ? data.slice(1) : void 0;
18634
+ let text = data;
18635
+ if (source !== void 0) {
18636
+ try {
18637
+ text = readFileSync16(source, "utf-8");
18638
+ } catch (e) {
18639
+ throw expected(`${prefix}${source}: ${e instanceof Error ? e.message : "could not be read"}`);
18640
+ }
18641
+ }
18642
+ try {
18643
+ return JSON.parse(text);
18644
+ } catch (e) {
18645
+ const where = source !== void 0 ? ` in ${source}` : "";
18646
+ throw expected(`${prefix}invalid JSON${where}: ${e instanceof Error ? e.message : String(e)}`);
18647
+ }
18648
+ }
18649
+ function toolsetMcpUrl(slug) {
18650
+ return `https://data-mcp.wayai.pro/t/${slug}/mcp`;
18651
+ }
18652
+ function globals(cmd) {
18653
+ let namespace = cmd;
18654
+ while (namespace.parent?.parent) namespace = namespace.parent;
18655
+ return namespace.opts();
18656
+ }
18657
+ function withBaseOption(command2) {
18658
+ return command2.option("--base <id>", "Base id (or set WAYAI_BASE)");
18659
+ }
18660
+ function baseOptionHolder(cmd) {
18661
+ for (let c = cmd; c; c = c.parent ?? void 0) {
18662
+ if (c.options.some((o) => o.long === "--base")) return c;
18663
+ }
18664
+ return void 0;
18665
+ }
18666
+ function findBase(cmd) {
18667
+ return baseOptionHolder(cmd)?.opts()?.base;
18668
+ }
18669
+ function requireBase(cmd) {
18670
+ const base = findBase(cmd) ?? process.env.WAYAI_BASE ?? "";
18671
+ if (base) return base;
18672
+ console.error("Error: --base is required (or set WAYAI_BASE)");
18673
+ return process.exit(1);
18674
+ }
18675
+ function outputFormat(cmd) {
18676
+ const opts = globals(cmd);
18677
+ return opts.json || opts.output === "json" ? "json" : "table";
18678
+ }
18679
+ function historyQuery(opts) {
18680
+ const qs = new URLSearchParams();
18681
+ if (opts.limit) qs.set("limit", opts.limit);
18682
+ if (opts.offset) qs.set("offset", opts.offset);
18683
+ if (opts.diff) qs.set("diff", "true");
18684
+ const q = qs.toString();
18685
+ return q ? `?${q}` : "";
18686
+ }
18687
+ function splitList(value) {
18688
+ return value.split(",").map((v) => v.trim()).filter((v) => v.length > 0);
18689
+ }
18690
+ function parseByteCount(flag, value) {
18691
+ const n = Number(value);
18692
+ if (!Number.isInteger(n) || n < 0) {
18693
+ throw expected(`${flag} must be a whole number of bytes (0 = unlimited), not ${JSON.stringify(value)}.`);
18694
+ }
18695
+ return n;
18696
+ }
18697
+ async function readSecret(source, label) {
18698
+ const value = resolveSecretSource(source) === "stdin" ? (await readStdin()).trim() : (await promptSecret(`${label}: `)).trim();
18699
+ if (!value) throw expected(`${label} is required.`);
18700
+ return value;
18701
+ }
18702
+ function isInteractive() {
18703
+ return Boolean(process.stdin.isTTY && process.stdout.isTTY);
18704
+ }
18705
+ function parseDuration(input, flag = "duration") {
18706
+ const match = DURATION_RE.exec(input.trim());
18707
+ const value = Number(match?.[1] ?? 0);
18708
+ const unit = match?.[2];
18709
+ const unitMs = unit ? DURATION_UNIT_MS[unit] : void 0;
18710
+ if (!unitMs || value <= 0) {
18711
+ throw expected(
18712
+ `Invalid ${flag} ${JSON.stringify(input)} \u2014 use <number><unit> with unit s/m/h/d (e.g. 10m, 2h, 30d).`
18713
+ );
18714
+ }
18715
+ return value * unitMs;
18716
+ }
18717
+ var DURATION_RE, DURATION_UNIT_MS;
18718
+ var init_helpers = __esm({
18719
+ "src/data/helpers.ts"() {
18720
+ "use strict";
18721
+ init_base_id();
18722
+ init_expected();
18723
+ init_utils();
18724
+ DURATION_RE = /^(\d+)([smhd])$/;
18725
+ DURATION_UNIT_MS = {
18726
+ s: 1e3,
18727
+ m: 6e4,
18728
+ h: 36e5,
18729
+ d: 864e5
18730
+ };
18731
+ }
18732
+ });
18733
+
18734
+ // src/data/config-as-code/types.ts
18735
+ var ENTITY_KINDS, ENTITY_DIRS, DEPRECATED_ENTITY_DIRS;
18736
+ var init_types2 = __esm({
18737
+ "src/data/config-as-code/types.ts"() {
18738
+ "use strict";
18739
+ ENTITY_KINDS = [
18740
+ "record_types",
18741
+ "relationship_types",
18742
+ "inbound_webhooks",
18743
+ "triggers",
18744
+ "toolsets",
18745
+ "actions",
18746
+ "seeds"
18747
+ ];
18748
+ ENTITY_DIRS = {
18749
+ record_types: "record-types",
18750
+ relationship_types: "relationship-types",
18751
+ inbound_webhooks: "inbound-webhooks",
18752
+ triggers: "triggers",
18753
+ toolsets: "toolsets",
18754
+ actions: "actions",
18755
+ seeds: "seeds"
18756
+ };
18757
+ DEPRECATED_ENTITY_DIRS = ["endpoints", "collections", "tools"];
18758
+ }
18759
+ });
18760
+
18761
+ // src/data/config-as-code/config-writer.ts
18762
+ import * as fs16 from "fs";
18763
+ import * as path19 from "path";
18764
+ import * as yaml8 from "js-yaml";
18765
+ function dump4(value) {
18766
+ return yaml8.dump(value, YAML_DUMP_OPTIONS);
18767
+ }
18768
+ function omitUndefined(obj) {
18769
+ const out = {};
18770
+ for (const [k, v] of Object.entries(obj)) {
18771
+ if (v !== void 0) out[k] = v;
18772
+ }
18773
+ return out;
18774
+ }
18775
+ function stripRecordTypeSources(sources) {
18776
+ if (!Array.isArray(sources)) return void 0;
18777
+ return sources.map((raw) => {
18778
+ const source = raw;
18779
+ const auth = source.auth;
18780
+ if (!auth) return source;
18781
+ const { secret: _secret, ...restAuth } = auth;
18782
+ return { ...source, auth: restAuth };
18783
+ });
18784
+ }
18785
+ function toFileObject(kind, entity) {
18786
+ const out = {};
18787
+ for (const key of ENTITY_FIELD_ORDER[kind]) {
18788
+ const value = kind === "record_types" && key === "sources" ? stripRecordTypeSources(entity.sources) : entity[key];
18789
+ if (value !== void 0) out[key] = value;
18790
+ }
18791
+ return out;
18792
+ }
18793
+ function pruneOrphans(folder, dir, keep, log) {
18794
+ if (!ensureRealSubdirNoSymlink(folder, dir, false)) return;
18795
+ let entries;
18796
+ try {
18797
+ entries = fs16.readdirSync(dir);
18798
+ } catch {
18799
+ return;
18800
+ }
18801
+ for (const file of entries) {
18802
+ if (!file.endsWith(".yaml") || keep.has(file)) continue;
18803
+ const abs = path19.join(dir, file);
18804
+ fs16.rmSync(abs);
18805
+ log.removed.push(path19.relative(folder, abs));
18806
+ }
18807
+ }
18808
+ function metaFileObject(meta) {
18809
+ const out = {};
18810
+ for (const key of META_ORDER) {
18811
+ if (meta[key] !== void 0) out[key] = meta[key];
18812
+ }
18813
+ return out;
18814
+ }
18815
+ function writeBaseFolder(folder, meta, config) {
18816
+ const delta = { changed: [], removed: [] };
18817
+ const parent = path19.dirname(folder);
18818
+ fs16.mkdirSync(parent, { recursive: true });
18819
+ if (!ensureRealSubdirNoSymlink(parent, folder, true)) {
18820
+ throw expected(
18821
+ `Refusing to write ${folder}: the path crosses a symlink. Remove it and pull again.`
18822
+ );
18823
+ }
18824
+ writeFileIfChanged(folder, path19.join(folder, BASE_META_FILE), dump4(metaFileObject(meta)), delta);
18825
+ for (const kind of ENTITY_KINDS) {
18826
+ const dir = path19.join(folder, ENTITY_DIRS[kind]);
18827
+ const entities = config[kind] ?? [];
18828
+ const keep = /* @__PURE__ */ new Set();
18829
+ for (const raw of entities) {
18830
+ const entity = raw;
18831
+ const id = String(entity.id);
18832
+ if (!isValidBaseId(id)) {
18833
+ console.warn(` Warning: skipping ${kind} entity with unusable id ${JSON.stringify(id)}.`);
18834
+ continue;
18835
+ }
18836
+ const file = `${id}.yaml`;
18837
+ keep.add(file);
18838
+ writeFileIfChanged(folder, path19.join(dir, file), dump4(toFileObject(kind, entity)), delta);
18839
+ }
18840
+ pruneOrphans(folder, dir, keep, delta);
18841
+ }
18842
+ for (const deprecated of DEPRECATED_ENTITY_DIRS) {
18843
+ const dir = path19.join(folder, deprecated);
18844
+ if (ensureRealSubdirNoSymlink(folder, dir, false)) {
18845
+ fs16.rmSync(dir, { recursive: true, force: true });
18846
+ }
18847
+ }
18848
+ return delta;
18849
+ }
18850
+ function markProductionMirror(folder, baseId) {
18851
+ const file = path19.join(folder, BASE_META_FILE);
18852
+ try {
18853
+ const body = readFileNoFollow(folder, file)?.toString("utf-8");
18854
+ if (body === void 0 || body.startsWith(MIRROR_MARKER_PREFIX)) return;
18855
+ const banner = `${MIRROR_MARKER_PREFIX} "${baseId}". Edits are ignored; \`wayai push\` refuses it. Edit the linked preview instead.
18856
+ `;
18857
+ writeFileNoFollow(folder, file, Buffer.from(banner + body, "utf-8"));
18858
+ } catch {
18859
+ }
18860
+ }
18861
+ function ensureMirrorIgnored(folder) {
18862
+ try {
18863
+ writeFileNoFollow(folder, path19.join(folder, ".gitignore"), Buffer.from(MIRROR_GITIGNORE, "utf-8"));
18864
+ } catch {
18865
+ }
18866
+ }
18867
+ var ENTITY_FIELD_ORDER, META_ORDER, MIRROR_MARKER_PREFIX, MIRROR_GITIGNORE;
18868
+ var init_config_writer = __esm({
18869
+ "src/data/config-as-code/config-writer.ts"() {
18870
+ "use strict";
18871
+ init_expected();
18872
+ init_yaml_writer();
18873
+ init_fs_safety();
18874
+ init_base_workspace();
18875
+ init_base_id();
18876
+ init_types2();
18877
+ ENTITY_FIELD_ORDER = {
18878
+ record_types: ["id", "name", "description", "icon", "color", "json_schema", "ui", "sources"],
18879
+ relationship_types: [
18880
+ "id",
18881
+ "description",
18882
+ "data_schema",
18883
+ "source_record_types",
18884
+ "target_record_types",
18885
+ "cascade"
18886
+ ],
18887
+ inbound_webhooks: [
18888
+ "id",
18889
+ "name",
18890
+ "record_type_scope",
18891
+ "field_mapping",
18892
+ "source_binding",
18893
+ "ingest_auth",
18894
+ "hydration",
18895
+ "enabled"
18896
+ ],
18897
+ triggers: [
18898
+ "id",
18899
+ "name",
18900
+ "action",
18901
+ "url",
18902
+ "events",
18903
+ "record_type_scope",
18904
+ "filter",
18905
+ "skip_inbound_webhook_writes",
18906
+ "skip_cascade_writes",
18907
+ "enabled"
18908
+ ],
18909
+ toolsets: ["id", "name", "description", "actions", "relationships", "batch", "sql_query"],
18910
+ actions: [
18911
+ "id",
18912
+ "record_type",
18913
+ "operation",
18914
+ "steps",
18915
+ "description",
18916
+ "external_source",
18917
+ "writable_fields",
18918
+ "precondition",
18919
+ "binding",
18920
+ "filterable_fields",
18921
+ "expose_filter",
18922
+ "expose_sort",
18923
+ "default_sort",
18924
+ "expose_limit",
18925
+ "default_limit",
18926
+ "expose_offset",
18927
+ "expose_fields",
18928
+ "default_fields",
18929
+ "agent_minimal",
18930
+ "base_filter"
18931
+ ],
18932
+ seeds: ["id", "description", "records", "relationships", "exclusive_record_types"]
18933
+ };
18934
+ META_ORDER = [
18935
+ "base_id",
18936
+ "origin_base_id",
18937
+ "name",
18938
+ "description",
18939
+ "environment",
18940
+ "integrations",
18941
+ "analytics"
18942
+ ];
18943
+ MIRROR_MARKER_PREFIX = "# Read-only mirror of production base";
18944
+ MIRROR_GITIGNORE = "*\n";
18945
+ }
18946
+ });
18947
+
18948
+ // src/data/config-as-code/api.ts
18949
+ function metaFromRecord(record, fallbackId) {
18950
+ return omitUndefined({
18951
+ base_id: record.id ?? fallbackId,
18952
+ origin_base_id: record.origin_base_id ?? void 0,
18953
+ name: record.name,
18954
+ description: record.description,
18955
+ environment: record.environment,
18956
+ integrations: record.integrations,
18957
+ analytics: record.analytics
18958
+ });
18959
+ }
18960
+ function getBaseRecord(client, id) {
18961
+ return client.request("GET", `/v1/bases/${pathSegment(id, "base id")}`);
18962
+ }
18963
+ function getConfig(client, id) {
18964
+ return client.request("GET", `/v1/${pathSegment(id, "base id")}/config`);
18965
+ }
18966
+ function diffConfig(client, id, local) {
18967
+ return client.request("POST", `/v1/${pathSegment(id, "base id")}/config/diff`, local);
18968
+ }
18969
+ function applyConfig(client, id, local) {
18970
+ return client.request("PUT", `/v1/${pathSegment(id, "base id")}/config`, local);
18971
+ }
18972
+ function createPreview(client, originId, opts) {
18973
+ return client.requestRaw("POST", `/v1/${pathSegment(originId, "origin base id")}/preview`, {
18974
+ name: opts.name,
18975
+ ...opts.description ? { description: opts.description } : {},
18976
+ // The tier is create-only, so this call is the ONLY chance to honor a tier
18977
+ // the folder declares. Omitted when absent so the clone default applies.
18978
+ ...opts.analytics ? { analytics: opts.analytics } : {}
18979
+ });
18980
+ }
18981
+ function deleteEntity(client, baseId, kind, id) {
18982
+ return client.request(
18983
+ "DELETE",
18984
+ `/v1/${pathSegment(baseId, "base id")}/${ENTITY_DIRS[kind]}/${pathSegment(id, `${kind} id`)}`
18985
+ );
18986
+ }
18987
+ var init_api = __esm({
18988
+ "src/data/config-as-code/api.ts"() {
18989
+ "use strict";
18990
+ init_helpers();
18991
+ init_config_writer();
18992
+ init_types2();
18993
+ }
18994
+ });
18995
+
18996
+ // src/data/config-as-code/config-parser.ts
18997
+ import * as fs17 from "fs";
18998
+ import * as path20 from "path";
18999
+ import * as yaml9 from "js-yaml";
19000
+ function readEntityDir(folder, dir) {
19001
+ if (!ensureRealSubdirNoSymlink(folder, dir, false)) {
19002
+ throw expected(`Refusing to read ${dir}: it is a symlink, not a config directory.`);
19003
+ }
19004
+ if (!isDirectory(dir)) return [];
19005
+ const out = [];
19006
+ for (const file of fs17.readdirSync(dir).sort()) {
19007
+ if (!file.endsWith(".yaml")) continue;
19008
+ const abs = path20.join(dir, file);
19009
+ const bytes = readFileNoFollow(folder, abs);
19010
+ if (bytes === null) {
19011
+ throw expected(`Refusing to read ${abs}: it is a symlink, not a config file.`);
19012
+ }
19013
+ let parsed;
19014
+ try {
19015
+ parsed = yaml9.load(bytes.toString("utf-8"));
19016
+ } catch (err) {
19017
+ throw expected(`Failed to parse ${abs}: ${err instanceof Error ? err.message : String(err)}`);
19018
+ }
19019
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
19020
+ throw expected(`${abs} is empty or not a YAML object`);
19021
+ }
19022
+ const entity = parsed;
19023
+ const stem = path20.basename(file, ".yaml");
19024
+ if (entity.id === void 0) entity.id = stem;
19025
+ else if (String(entity.id) !== stem) {
19026
+ throw expected(`${abs}: id "${String(entity.id)}" does not match filename "${stem}.yaml"`);
19027
+ }
19028
+ out.push(entity);
19029
+ }
19030
+ return out;
19031
+ }
19032
+ function parseBaseFolder(folder) {
19033
+ const meta = readBaseMeta(folder);
19034
+ if (!meta) {
19035
+ throw expected(
19036
+ hasBaseMetaFile(folder) ? `${path20.join(folder, BASE_META_FILE)} could not be parsed as a YAML mapping. Fix it, or delete it and pull again.` : `No ${BASE_META_FILE} found in ${folder}`
19037
+ );
19038
+ }
19039
+ const read = (kind) => readEntityDir(folder, path20.join(folder, ENTITY_DIRS[kind]));
19040
+ const config = {
19041
+ record_types: read("record_types"),
19042
+ relationship_types: read("relationship_types"),
19043
+ inbound_webhooks: read("inbound_webhooks"),
19044
+ triggers: read("triggers"),
19045
+ toolsets: read("toolsets"),
19046
+ actions: read("actions"),
19047
+ seeds: read("seeds")
19048
+ };
19049
+ return { meta, config };
19050
+ }
19051
+ var init_config_parser = __esm({
19052
+ "src/data/config-as-code/config-parser.ts"() {
19053
+ "use strict";
19054
+ init_expected();
19055
+ init_layout();
19056
+ init_fs_safety();
19057
+ init_base_workspace();
19058
+ init_types2();
19059
+ }
19060
+ });
19061
+
19062
+ // src/data/config-as-code/diff-format.ts
19063
+ function bucket(diff, kind) {
19064
+ return diff[kind];
19065
+ }
19066
+ function isEmptyBucket(b) {
19067
+ return !b || b.added.length === 0 && b.modified.length === 0 && b.removed.length === 0;
19068
+ }
19069
+ function isDiffEmpty(diff) {
19070
+ return ENTITY_KINDS.every((kind) => isEmptyBucket(bucket(diff, kind)));
19071
+ }
19072
+ function collectRemovals(diff) {
19073
+ const out = [];
19074
+ for (const kind of ENTITY_KINDS) {
19075
+ for (const entity of bucket(diff, kind)?.removed ?? []) out.push({ kind, id: entity.id });
19076
+ }
19077
+ return out;
19078
+ }
19079
+ function countChanges(diff) {
19080
+ let added = 0;
19081
+ let modified = 0;
19082
+ let removed = 0;
19083
+ for (const kind of ENTITY_KINDS) {
19084
+ const b = bucket(diff, kind);
19085
+ if (!b) continue;
19086
+ added += b.added.length;
19087
+ modified += b.modified.length;
19088
+ removed += b.removed.length;
19089
+ }
19090
+ return { added, modified, removed };
19091
+ }
19092
+ function renderDiff(diff) {
19093
+ const lines = [];
19094
+ for (const kind of ENTITY_KINDS) {
19095
+ const b = bucket(diff, kind);
19096
+ if (!b || isEmptyBucket(b)) continue;
19097
+ lines.push(`${BOLD}${LABELS[kind]}s${RESET}`);
19098
+ for (const e of b.added) lines.push(`${GREEN} + ${sanitizeTerminalText(e.id)}${RESET}`);
19099
+ for (const m of b.modified) lines.push(`${YELLOW} ~ ${sanitizeTerminalText(m.after.id)}${RESET}`);
19100
+ for (const e of b.removed) lines.push(`${RED} - ${sanitizeTerminalText(e.id)}${RESET}`);
19101
+ }
19102
+ const { added, modified, removed } = countChanges(diff);
19103
+ lines.push("");
19104
+ lines.push(
19105
+ `${GREEN}${added} added${RESET}, ${YELLOW}${modified} modified${RESET}, ${RED}${removed} removed${RESET}`
19106
+ );
19107
+ if (removed > 0) {
19108
+ lines.push(
19109
+ `${RED} ${removed} entit${removed === 1 ? "y" : "ies"} exist on the base but not in your files \u2014 re-run with --prune to delete (record types cascade to their records).${RESET}`
19110
+ );
19111
+ }
19112
+ return lines.join("\n");
19113
+ }
19114
+ var LABELS, GREEN, YELLOW, RED, BOLD, RESET;
19115
+ var init_diff_format = __esm({
19116
+ "src/data/config-as-code/diff-format.ts"() {
19117
+ "use strict";
19118
+ init_terminal_output();
19119
+ init_types2();
19120
+ LABELS = {
19121
+ record_types: "record type",
19122
+ relationship_types: "relationship type",
19123
+ inbound_webhooks: "inbound webhook",
19124
+ triggers: "trigger",
19125
+ toolsets: "toolset",
19126
+ actions: "action",
19127
+ seeds: "seed"
19128
+ };
19129
+ GREEN = "\x1B[32m";
19130
+ YELLOW = "\x1B[33m";
19131
+ RED = "\x1B[31m";
19132
+ BOLD = "\x1B[1m";
19133
+ RESET = "\x1B[0m";
19134
+ }
19135
+ });
19136
+
19137
+ // src/data/config-as-code/sync.ts
19138
+ var sync_exports = {};
19139
+ __export(sync_exports, {
19140
+ pullBase: () => pullBase,
19141
+ pushBase: () => pushBase
19142
+ });
19143
+ import * as path21 from "path";
19144
+ function parseArgs4(args2) {
19145
+ return {
19146
+ autoConfirm: args2.includes("--yes") || args2.includes("-y"),
19147
+ dryRun: args2.includes("--dry-run"),
19148
+ prune: args2.includes("--prune")
19149
+ };
19150
+ }
19151
+ function requireGitRoot(gitRoot) {
19152
+ if (!gitRoot) throw expected("Not inside a git repository.");
19153
+ return gitRoot;
19154
+ }
19155
+ async function writeProductionMirror(client, basesDir, prodId, record) {
19156
+ if (!isValidBaseId(prodId)) {
19157
+ throw expected(`Refusing to mirror base ${JSON.stringify(prodId)}: not a usable base id.`);
19158
+ }
19159
+ const config = await getConfig(client, prodId);
19160
+ const folder = path21.join(basesDir, prodId);
19161
+ writeBaseFolder(folder, { ...metaFromRecord(record, prodId), environment: "production" }, config);
19162
+ markProductionMirror(folder, prodId);
19163
+ ensureMirrorIgnored(folder);
19164
+ return folder;
19165
+ }
19166
+ async function mirrorLinkedProduction(client, basesDir, originId) {
19167
+ try {
19168
+ const record = await getBaseRecord(client, originId);
19169
+ if (record.environment !== "production") return;
19170
+ const folder = await writeProductionMirror(client, basesDir, originId, record);
19171
+ console.log(`Mirrored production base \u2192 ${folder} (read-only, git-ignored)`);
19172
+ } catch (err) {
19173
+ console.warn(
19174
+ `Warning: could not mirror the production base (${err instanceof Error ? err.message : String(err)}). The preview pull is unaffected.`
19175
+ );
19176
+ }
19177
+ }
19178
+ async function pullBase(gitRootOrNull, selector, args2) {
19179
+ const { autoConfirm } = parseArgs4(args2);
19180
+ const gitRoot = requireGitRoot(gitRootOrNull);
19181
+ const target = resolveBaseTarget(gitRoot, selector);
19182
+ const basesDir = resolveBasesDir(gitRoot);
19183
+ const baseId = targetBaseId(target, selector);
19184
+ if (!baseId) {
19185
+ throw expected(
19186
+ `Could not determine the base id for ${target.folder}. Pass the base id explicitly.`
19187
+ );
19188
+ }
19189
+ const client = await createDataClient();
19190
+ console.log("Fetching base configuration...");
19191
+ const record = await getBaseRecord(client, baseId);
19192
+ if (record.environment === "production") {
19193
+ const folder = await writeProductionMirror(client, basesDir, record.id ?? baseId, record);
19194
+ console.log(`Production base mirrored (read-only) \u2192 ${folder}`);
19195
+ return;
19196
+ }
19197
+ assertBaseMatchesBinding(baseId);
19198
+ if (target.exists && !autoConfirm) {
19199
+ const ok = await confirm(
19200
+ `Overwrite local files in ${path21.relative(gitRoot, target.folder)} with the server config for "${sanitizeTerminalText(baseId)}"?`
19201
+ );
19202
+ if (!ok) {
19203
+ console.log("Cancelled.");
19204
+ return;
19205
+ }
19206
+ }
19207
+ const config = await getConfig(client, baseId);
19208
+ const isFirstPull = !target.exists;
19209
+ const delta = writeBaseFolder(target.folder, metaFromRecord(record, baseId), config);
19210
+ console.log(`Base configuration written to ${target.folder}`);
19211
+ console.log(
19212
+ ` ${ENTITY_KINDS.map((kind) => `${(config[kind] ?? []).length} ${kind}`).join(", ")}`
19213
+ );
19214
+ if (!isFirstPull) printLocalFileChanges(delta);
19215
+ console.log(" Secrets are not written. Manage them with `wayai bases secrets`.");
19216
+ autoBindBaseIfUnbound(baseId);
19217
+ if (record.origin_base_id) {
19218
+ await mirrorLinkedProduction(client, basesDir, record.origin_base_id);
19219
+ }
19220
+ }
19221
+ function printLintWarnings(warnings) {
19222
+ if (!warnings || warnings.length === 0) return;
19223
+ const word = warnings.length === 1 ? "suggestion" : "suggestions";
19224
+ console.error(`
19225
+ ${YELLOW}Tool design \u2014 ${warnings.length} ${word} (advisory, not blocking):${RESET}`);
19226
+ for (const w of warnings) {
19227
+ console.error(
19228
+ ` ${sanitizeTerminalText(w.action)} [${sanitizeTerminalText(w.rule)}]
19229
+ ${sanitizeTerminalText(w.message)}`
19230
+ );
19231
+ }
19232
+ }
19233
+ async function createDeclaredPreview(client, target, parsed, autoConfirm) {
19234
+ const { meta, config } = parsed;
19235
+ if (!meta.origin_base_id) {
19236
+ throw expected(
19237
+ "base.yaml needs a base_id (an existing preview) or an origin_base_id (to create one)."
19238
+ );
19239
+ }
19240
+ const name = meta.name ?? path21.basename(target.folder);
19241
+ assertNoBindingBlocksBaseCreation(name);
19242
+ if (!autoConfirm) {
19243
+ const ok = await confirm(
19244
+ `Create a new preview "${sanitizeTerminalText(name)}" from "${sanitizeTerminalText(meta.origin_base_id)}"?`
19245
+ );
19246
+ if (!ok) {
19247
+ console.log("Cancelled.");
19248
+ return null;
19249
+ }
19250
+ }
19251
+ const record = await createPreview(client, meta.origin_base_id, {
19252
+ name,
19253
+ description: meta.description,
19254
+ analytics: meta.analytics
19255
+ });
19256
+ const id = record.id;
19257
+ writeBaseFolder(target.folder, { ...meta, ...metaFromRecord(record, id) }, config);
19258
+ console.log(`Created preview "${sanitizeTerminalText(id)}".`);
19259
+ printWarnings((record.warnings ?? []).map((w) => sanitizeTerminalText(w.message)));
19260
+ autoBindBaseIfUnbound(id);
19261
+ return id;
19262
+ }
19263
+ async function pushBase(gitRootOrNull, selector, args2) {
19264
+ const { autoConfirm, dryRun, prune } = parseArgs4(args2);
19265
+ const gitRoot = requireGitRoot(gitRootOrNull);
19266
+ const target = resolveBaseTarget(gitRoot, selector);
19267
+ if (!target.exists) {
19268
+ throw expected(
19269
+ `No base.yaml in ${target.folder}. Pull an existing preview, or scaffold a folder with origin_base_id set to create one.`
19270
+ );
19271
+ }
19272
+ const parsed = parseBaseFolder(target.folder);
19273
+ const { meta, config } = parsed;
19274
+ if (isProductionFolder(meta)) {
19275
+ throw expected(
19276
+ `${path21.relative(gitRoot, target.folder)} is a read-only production mirror. Push operates on previews \u2014 edit the linked preview and promote with \`wayai bases promote\`.`
19277
+ );
19278
+ }
19279
+ if (!meta.base_id && dryRun) {
19280
+ console.log(
19281
+ `Dry run \u2014 nothing applied. ${path21.relative(gitRoot, target.folder)} has no base_id yet, so a real push would first create a preview from "${sanitizeTerminalText(meta.origin_base_id ?? "<origin_base_id>")}".`
19282
+ );
19283
+ return;
19284
+ }
19285
+ const client = await createDataClient();
19286
+ let baseId = meta.base_id;
19287
+ if (!baseId) {
19288
+ const created = await createDeclaredPreview(client, target, parsed, autoConfirm);
19289
+ if (!created) return;
19290
+ baseId = created;
19291
+ } else {
19292
+ const record = await getBaseRecord(client, baseId);
19293
+ if (record.environment && record.environment !== "preview") {
19294
+ throw expected(
19295
+ `"${sanitizeTerminalText(baseId)}" is a ${sanitizeTerminalText(record.environment)} base. Push operates on previews \u2014 promote with \`wayai bases promote\`.`
19296
+ );
19297
+ }
19298
+ assertBaseMatchesBinding(baseId);
19299
+ }
19300
+ const diff = await diffConfig(client, baseId, config);
19301
+ printLintWarnings(diff.warnings);
19302
+ if (isDiffEmpty(diff)) {
19303
+ console.log(`No changes \u2014 preview "${sanitizeTerminalText(baseId)}" already matches your files.`);
19304
+ if (!dryRun) autoBindBaseIfUnbound(baseId);
19305
+ return;
19306
+ }
19307
+ console.log(renderDiff(diff));
19308
+ if (dryRun) {
19309
+ console.log("\nDry run \u2014 nothing applied.");
19310
+ return;
19311
+ }
19312
+ if (!autoConfirm) {
19313
+ const ok = await confirm(`
19314
+ Apply these changes to preview "${sanitizeTerminalText(baseId)}"?`);
19315
+ if (!ok) {
19316
+ console.log("Cancelled.");
19317
+ return;
19318
+ }
19319
+ }
19320
+ const result = await applyConfig(client, baseId, config);
19321
+ const secretGroups = [
19322
+ ["trigger", result.new_trigger_secrets],
19323
+ ["inbound webhook", result.new_inbound_webhook_secrets]
19324
+ ];
19325
+ if (secretGroups.some(([, map]) => map && Object.keys(map).length > 0)) {
19326
+ console.log(`
19327
+ ${YELLOW}New secrets (shown once \u2014 save them now):${RESET}`);
19328
+ for (const [kind, map] of secretGroups) {
19329
+ for (const [id, secret] of Object.entries(map ?? {})) {
19330
+ console.log(` ${kind} ${sanitizeTerminalText(id)}: ${secret}`);
19331
+ }
19332
+ }
19333
+ }
19334
+ const removals = collectRemovals(diff);
19335
+ if (removals.length > 0) {
19336
+ const word = removals.length === 1 ? "entity" : "entities";
19337
+ if (!prune) {
19338
+ console.log(
19339
+ `
19340
+ ${RED}${removals.length} ${word} not in your files were left on the base. Re-run with --prune to delete.${RESET}`
19341
+ );
19342
+ } else if (autoConfirm || await confirm(
19343
+ `
19344
+ Delete ${removals.length} server ${word} not in your files? Record types cascade to their records.`
19345
+ )) {
19346
+ for (const removal of removals) {
19347
+ await deleteEntity(client, baseId, removal.kind, removal.id);
19348
+ console.log(` - deleted ${removal.kind} ${sanitizeTerminalText(removal.id)}`);
19349
+ }
19350
+ } else {
19351
+ console.log("Skipped deletions.");
19352
+ }
19353
+ }
19354
+ console.log(`
19355
+ Pushed to preview "${sanitizeTerminalText(baseId)}".`);
19356
+ autoBindBaseIfUnbound(baseId);
19357
+ }
19358
+ var init_sync = __esm({
19359
+ "src/data/config-as-code/sync.ts"() {
19360
+ "use strict";
19361
+ init_client();
19362
+ init_utils();
19363
+ init_expected();
19364
+ init_layout();
19365
+ init_terminal_output();
19366
+ init_base_id();
19367
+ init_push();
19368
+ init_base_binding();
19369
+ init_api();
19370
+ init_config_parser();
19371
+ init_config_writer();
19372
+ init_diff_format();
19373
+ init_base_workspace();
19374
+ init_types2();
19375
+ }
19376
+ });
19377
+
19378
+ // src/commands/push.ts
19379
+ var push_exports = {};
19380
+ __export(push_exports, {
19381
+ autoRenameAgentFiles: () => autoRenameAgentFiles,
19382
+ createAndPushNewHub: () => createAndPushNewHub,
19383
+ printErrors: () => printErrors,
19384
+ printLocalFileChanges: () => printLocalFileChanges,
19385
+ printSyncResult: () => printSyncResult,
19386
+ printWarnings: () => printWarnings,
19387
+ pushCommand: () => pushCommand,
19388
+ reportUnresolvedPushTarget: () => reportUnresolvedPushTarget,
19389
+ selectExistingHub: () => selectExistingHub,
19390
+ shouldWarnIgnoredPreviewLabel: () => shouldWarnIgnoredPreviewLabel,
19391
+ syncAfterPush: () => syncAfterPush
19392
+ });
19393
+ import * as fs18 from "fs";
19394
+ import * as path22 from "path";
19395
+ import * as yaml10 from "js-yaml";
19396
+ function parseArgs5(args2) {
19397
+ let autoConfirm = false;
19398
+ let label;
19399
+ for (let i = 0; i < args2.length; i++) {
19400
+ const arg = args2[i];
19401
+ if (arg === "--yes" || arg === "-y") {
19402
+ autoConfirm = true;
19403
+ } else if (arg === "--label" && args2[i + 1]) {
19404
+ label = args2[++i];
19405
+ }
19406
+ }
19407
+ return { autoConfirm, label };
19408
+ }
19409
+ function shouldWarnIgnoredPreviewLabel(localLabel, serverLabel) {
19410
+ return Boolean(localLabel) && serverLabel !== void 0 && localLabel !== serverLabel;
19411
+ }
19412
+ function printSyncResult(result) {
19413
+ const applyErrors = result.apply_errors ?? result.errors;
19414
+ if (applyErrors && applyErrors.length > 0) {
19415
+ printErrors(applyErrors);
19416
+ throw expected(`Sync failed with ${applyErrors.length} error(s). No completion was reported; inspect the errors above.`);
19417
+ }
19418
+ console.log(`
19419
+ Sync complete. Preview hub: ${result.preview_hub_id}`);
19420
+ const c = result.changes;
19421
+ const parts = [];
19422
+ if (c.hub_updated) parts.push("hub updated");
19423
+ if (c.connections_created > 0) parts.push(`${c.connections_created} connection(s) created`);
19424
+ if (c.connections_updated > 0) parts.push(`${c.connections_updated} connection(s) updated`);
19425
+ if (c.connections_deleted > 0) parts.push(`${c.connections_deleted} connection(s) deleted`);
19426
+ if (c.agents_created > 0) parts.push(`${c.agents_created} agent(s) created`);
19427
+ if (c.agents_updated > 0) parts.push(`${c.agents_updated} agent(s) updated`);
19428
+ if (c.agents_deleted > 0) parts.push(`${c.agents_deleted} agent(s) deleted`);
19429
+ if (c.tools_created > 0) parts.push(`${c.tools_created} tool(s) created`);
19430
+ if (c.tools_updated > 0) parts.push(`${c.tools_updated} tool(s) updated`);
19431
+ if (c.tools_deleted > 0) parts.push(`${c.tools_deleted} tool(s) deleted`);
19432
+ if (c.states_created > 0) parts.push(`${c.states_created} state(s) created`);
19433
+ if (c.states_updated > 0) parts.push(`${c.states_updated} state(s) updated`);
19434
+ if (c.states_deleted > 0) parts.push(`${c.states_deleted} state(s) deleted`);
19435
+ if (c.evals_created > 0) parts.push(`${c.evals_created} eval(s) created`);
19436
+ if (c.evals_updated > 0) parts.push(`${c.evals_updated} eval(s) updated`);
19437
+ if (c.evals_deleted > 0) parts.push(`${c.evals_deleted} eval(s) deleted`);
19438
+ if (c.journeys_created > 0) parts.push(`${c.journeys_created} journey(s) created`);
19439
+ if (c.journeys_updated > 0) parts.push(`${c.journeys_updated} journey(s) updated`);
19440
+ if (c.journeys_deleted > 0) parts.push(`${c.journeys_deleted} journey(s) deleted`);
19441
+ if (c.teams_created > 0) parts.push(`${c.teams_created} team(s) created`);
19442
+ if (c.teams_updated > 0) parts.push(`${c.teams_updated} team(s) updated`);
19443
+ if (c.teams_deleted > 0) parts.push(`${c.teams_deleted} team(s) deleted`);
19444
+ if (c.resources_created > 0) parts.push(`${c.resources_created} resource(s) created`);
19445
+ if (c.resources_updated > 0) parts.push(`${c.resources_updated} resource(s) updated`);
19446
+ if (c.resources_deleted > 0) parts.push(`${c.resources_deleted} resource(s) deleted`);
19447
+ if (c.resource_files_uploaded > 0) parts.push(`${c.resource_files_uploaded} resource file(s) uploaded`);
19448
+ if (c.resource_files_deleted > 0) parts.push(`${c.resource_files_deleted} resource file(s) deleted`);
19449
+ if (c.resource_links_created > 0) parts.push(`${c.resource_links_created} resource link(s) created`);
19450
+ if (c.resource_links_updated > 0) parts.push(`${c.resource_links_updated} resource link(s) updated`);
19451
+ if (c.resource_links_deleted > 0) parts.push(`${c.resource_links_deleted} resource link(s) deleted`);
19452
+ if (c.outbound_contacts_created > 0) parts.push(`${c.outbound_contacts_created} outbound contact(s) created`);
19453
+ if (c.outbound_contacts_updated > 0) parts.push(`${c.outbound_contacts_updated} outbound contact(s) updated`);
19454
+ if (c.outbound_contacts_deleted > 0) parts.push(`${c.outbound_contacts_deleted} outbound contact(s) deleted`);
19455
+ if (c.outbound_lists_created > 0) parts.push(`${c.outbound_lists_created} outbound list(s) created`);
19456
+ if (c.outbound_lists_updated > 0) parts.push(`${c.outbound_lists_updated} outbound list(s) updated`);
19457
+ if (c.outbound_lists_deleted > 0) parts.push(`${c.outbound_lists_deleted} outbound list(s) deleted`);
19458
+ if (c.outbound_schedules_created > 0) parts.push(`${c.outbound_schedules_created} outbound schedule(s) created`);
19459
+ if (c.outbound_schedules_updated > 0) parts.push(`${c.outbound_schedules_updated} outbound schedule(s) updated`);
19460
+ if (c.outbound_schedules_deleted > 0) parts.push(`${c.outbound_schedules_deleted} outbound schedule(s) deleted`);
19461
+ if (parts.length > 0) {
19462
+ console.log(`Changes: ${parts.join(", ")}`);
19463
+ }
19464
+ if (result.warnings && result.warnings.length > 0) {
19465
+ printWarnings(result.warnings.map((w) => w.message));
19466
+ }
19467
+ }
19468
+ function printWarnings(warnings) {
19469
+ if (warnings.length === 0) return;
19470
+ console.log(`
19471
+ \x1B[33mWarnings (${warnings.length}):\x1B[0m`);
19472
+ for (const w of warnings) {
19473
+ console.log(` \x1B[33m! ${w}\x1B[0m`);
19474
+ }
19475
+ }
19476
+ function printErrors(errors) {
19477
+ if (errors.length === 0) return;
19478
+ console.error(`
19479
+ \x1B[31mErrors (${errors.length}):\x1B[0m`);
19480
+ for (const error of errors) {
19481
+ const message = typeof error === "string" ? error : error.message;
19482
+ console.error(` \x1B[31m! ${message}\x1B[0m`);
19483
+ }
19484
+ }
19485
+ function printLocalFileChanges(delta) {
19486
+ if (delta.changed.length === 0 && delta.removed.length === 0) {
19487
+ console.log("Local files already in sync.");
19488
+ return;
19489
+ }
19490
+ console.log("Local files updated from server:");
19491
+ const emit = (paths, sigil) => {
19492
+ const sorted = [...paths].sort();
19493
+ for (const p of sorted.slice(0, LOCAL_CHANGE_LIST_CAP)) console.log(` ${sigil} ${p}`);
19494
+ if (sorted.length > LOCAL_CHANGE_LIST_CAP) {
19495
+ console.log(` \u2026and ${sorted.length - LOCAL_CHANGE_LIST_CAP} more ${sigil === "-" ? "removed" : "changed"}`);
19496
+ }
19497
+ };
19498
+ emit(delta.removed, "-");
19499
+ emit(delta.changed, "~");
19500
+ }
19501
+ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId, remoteConfig) {
19502
+ const agentsDir = path22.join(hubFolder, "agents");
19503
+ let agentsWithIds = [];
19504
+ if (fs18.existsSync(agentsDir)) {
19505
+ const yamlFiles = fs18.readdirSync(agentsDir).filter((f) => f.endsWith(".yaml"));
19506
+ for (const file of yamlFiles) {
19507
+ try {
19508
+ const content = fs18.readFileSync(path22.join(agentsDir, file), "utf-8");
19509
+ const agent = yaml10.load(content);
19510
+ if (agent?.id && agent.name) {
19511
+ agentsWithIds.push({ id: agent.id, name: agent.name });
19512
+ }
19513
+ } catch {
19514
+ console.warn(` Warning: could not parse agents/${file}, skipping`);
19515
+ }
19516
+ }
19517
+ }
19518
+ if (agentsWithIds.length === 0) {
19519
+ const yamlPath = resolveHubYamlPath(hubFolder);
19520
+ if (!yamlPath) return;
19521
+ const yamlContent = fs18.readFileSync(yamlPath, "utf-8");
19522
+ const config = yaml10.load(yamlContent);
19523
+ agentsWithIds = (config.agents || []).filter((a) => !!a.id && !!a.name);
18203
19524
  }
18204
19525
  if (agentsWithIds.length === 0) return;
18205
19526
  console.log("Checking for agent renames...");
@@ -18229,18 +19550,18 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId, re
18229
19550
  }
18230
19551
  }
18231
19552
  if (renames.length === 0) return;
18232
- if (!fs14.existsSync(agentsDir)) return;
18233
- for (const file of fs14.readdirSync(agentsDir)) {
19553
+ if (!fs18.existsSync(agentsDir)) return;
19554
+ for (const file of fs18.readdirSync(agentsDir)) {
18234
19555
  if (file.startsWith("__rename_temp_") && (file.endsWith(".md") || file.endsWith(".yaml"))) {
18235
19556
  console.warn(` Warning: removing orphaned temp file agents/${file}`);
18236
- fs14.unlinkSync(path17.join(agentsDir, file));
19557
+ fs18.unlinkSync(path22.join(agentsDir, file));
18237
19558
  }
18238
19559
  }
18239
19560
  const renameFileIfExists = (dir, oldName, newName) => {
18240
- const oldPath = path17.join(dir, oldName);
18241
- const newPath = path17.join(dir, newName);
18242
- if (!fs14.existsSync(oldPath)) return false;
18243
- fs14.renameSync(oldPath, newPath);
19561
+ const oldPath = path22.join(dir, oldName);
19562
+ const newPath = path22.join(dir, newName);
19563
+ if (!fs18.existsSync(oldPath)) return false;
19564
+ fs18.renameSync(oldPath, newPath);
18244
19565
  return true;
18245
19566
  };
18246
19567
  const oldSlugs = new Set(renames.map((r) => r.oldSlug));
@@ -18273,9 +19594,9 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId, re
18273
19594
  }
18274
19595
  } else {
18275
19596
  for (const { oldSlug, newSlug } of renames) {
18276
- const hasOldFile = extensions.some((ext) => fs14.existsSync(path17.join(agentsDir, `${oldSlug}${ext}`)));
19597
+ const hasOldFile = extensions.some((ext) => fs18.existsSync(path22.join(agentsDir, `${oldSlug}${ext}`)));
18277
19598
  if (!hasOldFile) continue;
18278
- const hasNewFile = extensions.some((ext) => fs14.existsSync(path17.join(agentsDir, `${newSlug}${ext}`)));
19599
+ const hasNewFile = extensions.some((ext) => fs18.existsSync(path22.join(agentsDir, `${newSlug}${ext}`)));
18279
19600
  if (hasNewFile) {
18280
19601
  console.warn(` Warning: skipping rename agents/${oldSlug}.* \u2192 agents/${newSlug}.* (target already exists)`);
18281
19602
  continue;
@@ -18290,7 +19611,7 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId, re
18290
19611
  if (completedRenames.length === 0) return;
18291
19612
  const mainYamlPath = resolveHubYamlPath(hubFolder);
18292
19613
  if (mainYamlPath) {
18293
- const mainYamlContent = fs14.readFileSync(mainYamlPath, "utf-8");
19614
+ const mainYamlContent = fs18.readFileSync(mainYamlPath, "utf-8");
18294
19615
  const substitutionMap = /* @__PURE__ */ new Map();
18295
19616
  for (const { oldSlug, newSlug } of completedRenames) {
18296
19617
  substitutionMap.set(`agents/${oldSlug}.md`, `agents/${newSlug}.md`);
@@ -18301,8 +19622,8 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId, re
18301
19622
  (_match, prefix, pathMatch) => `${prefix}${substitutionMap.get(pathMatch) ?? pathMatch}`
18302
19623
  );
18303
19624
  if (updatedYaml !== mainYamlContent) {
18304
- fs14.writeFileSync(mainYamlPath, updatedYaml, "utf-8");
18305
- console.log(` Updated instructions paths in ${path17.basename(mainYamlPath)}`);
19625
+ fs18.writeFileSync(mainYamlPath, updatedYaml, "utf-8");
19626
+ console.log(` Updated instructions paths in ${path22.basename(mainYamlPath)}`);
18306
19627
  }
18307
19628
  }
18308
19629
  }
@@ -18370,7 +19691,7 @@ async function pushSingleHub(client, hubId, hubFolder, autoConfirm, organization
18370
19691
  function selectExistingHub(workspaceDir, allHubs, selector, wsLabel) {
18371
19692
  if (selector) {
18372
19693
  const match = allHubs.find(
18373
- (h) => h.hubId === selector || path17.basename(h.hubFolder) === selector
19694
+ (h) => h.hubId === selector || path22.basename(h.hubFolder) === selector
18374
19695
  );
18375
19696
  if (!match) {
18376
19697
  console.error(`No hub matching --hub ${selector} found in ${wsLabel}/.`);
@@ -18413,7 +19734,7 @@ New hub: "${newHub.hubName}" (${hubType})`);
18413
19734
  process.exit(1);
18414
19735
  }
18415
19736
  console.log(`Hub created: ${createdHub.hub_name} (${hubId})`);
18416
- const content = fs14.readFileSync(hubYamlPath, "utf-8");
19737
+ const content = fs18.readFileSync(hubYamlPath, "utf-8");
18417
19738
  const hasVersion = content.match(/^version:\s/m);
18418
19739
  let updated;
18419
19740
  if (hasVersion) {
@@ -18429,7 +19750,7 @@ hub_id: "${hubId}"
18429
19750
  hub_environment: preview
18430
19751
  ${content}`;
18431
19752
  }
18432
- fs14.writeFileSync(hubYamlPath, updated, "utf-8");
19753
+ fs18.writeFileSync(hubYamlPath, updated, "utf-8");
18433
19754
  autoBindIfUnbound(hubId);
18434
19755
  await pushSingleHub(client, hubId, newHub.hubFolder, opts.autoConfirm, opts.organizationId, { skipAgentRename: true });
18435
19756
  }
@@ -18438,7 +19759,7 @@ function reportUnresolvedPushTarget(reason, existingHubs, newHubs, selector, wsL
18438
19759
  if (existingHubs.length > 0) {
18439
19760
  console.error(`No pushable hub found in ${wsLabel}/ \u2014 only read-only production mirror folder(s). Edit the linked preview hub, pull one, or create a new hub with \`wayai create\`:`);
18440
19761
  for (const h of existingHubs) {
18441
- console.error(` ${path17.basename(h.hubFolder)} (${h.hubId}, production mirror)`);
19762
+ console.error(` ${path22.basename(h.hubFolder)} (${h.hubId}, production mirror)`);
18442
19763
  }
18443
19764
  } else {
18444
19765
  console.error(`No hub folders found. Create hub files in ${wsLabel}/<hub>/hub.yaml with \`hub: { name: ... }\` and run \`wayai push\` (or \`wayai create\`).`);
@@ -18446,34 +19767,41 @@ function reportUnresolvedPushTarget(reason, existingHubs, newHubs, selector, wsL
18446
19767
  process.exit(1);
18447
19768
  }
18448
19769
  if (reason === "selector_miss") {
18449
- console.error(`No hub matching --hub ${selector} found in ${wsLabel}/. Available:`);
19770
+ console.error(`No hub matching "${selector}" found in ${wsLabel}/. Available:`);
18450
19771
  } else {
18451
19772
  console.error(`Multiple hub folders found in ${wsLabel}/. Pass --hub <uuid|folder-name> to choose, or run from inside a hub folder:`);
18452
19773
  }
18453
19774
  for (const h of existingHubs) {
18454
- console.error(` ${path17.basename(h.hubFolder)} (${h.hubId})`);
19775
+ console.error(` ${path22.basename(h.hubFolder)} (${h.hubId})`);
18455
19776
  }
18456
19777
  for (const h of newHubs) {
18457
- console.error(` ${path17.basename(h.hubFolder)} (new \u2014 "${h.hubName}")`);
19778
+ console.error(` ${path22.basename(h.hubFolder)} (new \u2014 "${h.hubName}")`);
18458
19779
  }
18459
19780
  process.exit(1);
18460
19781
  }
18461
19782
  async function pushCommand(args2) {
18462
- const { autoConfirm, hubSelector, label } = parseArgs4(args2);
19783
+ const gitRoot = findGitRoot();
19784
+ const route = requireSubtree("push", args2, gitRoot);
19785
+ if (gitRoot) warnLayoutOnce(gitRoot);
19786
+ if (route.subtree === "bases") {
19787
+ const { pushBase: pushBase2 } = await Promise.resolve().then(() => (init_sync(), sync_exports));
19788
+ await pushBase2(gitRoot, route.selector, args2);
19789
+ return;
19790
+ }
19791
+ const { autoConfirm, label } = parseArgs5(args2);
19792
+ const hubSelector = route.selector;
18463
19793
  const repoConfig = requireRepoConfig();
18464
19794
  const { organization_id: organizationId } = repoConfig;
18465
19795
  const { config, accessToken } = await requireAuth();
18466
19796
  const client = new ApiClient({ apiUrl: config.api_url, accessToken });
18467
19797
  const workspaceDir = resolveWorkspaceDir();
18468
- const gitRoot = findGitRoot();
18469
19798
  const wsLabel = hubsDirLabel(gitRoot);
18470
- if (gitRoot) warnLayoutOnce(gitRoot);
18471
19799
  if (gitRoot) {
18472
19800
  for (const file of ensureWorkspaceFiles(gitRoot)) {
18473
19801
  console.error(`Created ${file}`);
18474
19802
  }
18475
19803
  }
18476
- if (!fs14.existsSync(workspaceDir)) {
19804
+ if (!fs18.existsSync(workspaceDir)) {
18477
19805
  console.error(`No ${wsLabel}/ directory found. Run \`wayai pull\` first or create hub files in ${wsLabel}/<hub>/hub.yaml.`);
18478
19806
  process.exit(1);
18479
19807
  }
@@ -18492,8 +19820,8 @@ async function pushCommand(args2) {
18492
19820
  if (label) {
18493
19821
  console.warn("Note: --label is only used when creating a new hub. To change an existing hub's label, use `wayai relabel`.");
18494
19822
  }
18495
- console.log(`Target hub: ${path17.basename(existing.hubFolder)} (${existing.hubId})`);
18496
- assertHubMatchesBinding(existing.hubId, path17.basename(existing.hubFolder));
19823
+ console.log(`Target hub: ${path22.basename(existing.hubFolder)} (${existing.hubId})`);
19824
+ assertHubMatchesBinding(existing.hubId, path22.basename(existing.hubFolder));
18497
19825
  await pushSingleHub(client, existing.hubId, existing.hubFolder, autoConfirm, organizationId);
18498
19826
  return;
18499
19827
  }
@@ -18517,6 +19845,7 @@ var init_push = __esm({
18517
19845
  init_workspace_files();
18518
19846
  init_repo_config();
18519
19847
  init_hub_binding();
19848
+ init_subtree_routing();
18520
19849
  LOCAL_CHANGE_LIST_CAP = 20;
18521
19850
  }
18522
19851
  });
@@ -18527,33 +19856,23 @@ __export(pull_exports, {
18527
19856
  connectionsEqual: () => connectionsEqual,
18528
19857
  pullCommand: () => pullCommand,
18529
19858
  resolveHubTarget: () => resolveHubTarget,
18530
- writeProductionMirror: () => writeProductionMirror
19859
+ writeProductionMirror: () => writeProductionMirror2
18531
19860
  });
18532
- import * as fs15 from "fs";
18533
- import * as path18 from "path";
18534
- function parseArgs5(args2) {
18535
- let autoConfirm = false;
18536
- let hubSelector;
18537
- for (let i = 0; i < args2.length; i++) {
18538
- const arg = args2[i];
18539
- if (arg === "--yes" || arg === "-y") {
18540
- autoConfirm = true;
18541
- } else if (arg === "--hub" && args2[i + 1]) {
18542
- hubSelector = args2[++i];
18543
- }
18544
- }
18545
- return { autoConfirm, hubSelector };
19861
+ import * as fs19 from "fs";
19862
+ import * as path23 from "path";
19863
+ function parseArgs6(args2) {
19864
+ return { autoConfirm: args2.includes("--yes") || args2.includes("-y") };
18546
19865
  }
18547
19866
  function resolveHubTarget(workspaceDir, selector) {
18548
19867
  const wsLabel = hubsDirLabel(findGitRoot());
18549
19868
  const allHubs = scanWorkspaceHubs(workspaceDir);
18550
19869
  if (selector) {
18551
19870
  const match = allHubs.find(
18552
- (h) => h.hubId === selector || path18.basename(h.hubFolder) === selector
19871
+ (h) => h.hubId === selector || path23.basename(h.hubFolder) === selector
18553
19872
  );
18554
19873
  if (match) return { hubId: match.hubId, hubFolder: match.hubFolder };
18555
19874
  if (UUID_RE2.test(selector)) return { hubId: selector, hubFolder: null };
18556
- console.error(`No hub matching --hub ${selector} found in ${wsLabel}/. Pass a UUID for first-time pulls.`);
19875
+ console.error(`No hub matching "${selector}" found in ${wsLabel}/. Pass a UUID for first-time pulls.`);
18557
19876
  process.exit(1);
18558
19877
  }
18559
19878
  const enclosing = findEnclosingHubFolder(workspaceDir);
@@ -18566,19 +19885,26 @@ function resolveHubTarget(workspaceDir, selector) {
18566
19885
  }
18567
19886
  console.error(`Multiple hubs found in ${wsLabel}/. Pass --hub <uuid|folder-name> to choose, or run from inside a hub folder:`);
18568
19887
  for (const h of previewHubs) {
18569
- console.error(` ${path18.basename(h.hubFolder)} (${h.hubId})`);
19888
+ console.error(` ${path23.basename(h.hubFolder)} (${h.hubId})`);
18570
19889
  }
18571
19890
  process.exit(1);
18572
19891
  }
18573
19892
  async function pullCommand(args2) {
18574
- const { autoConfirm, hubSelector } = parseArgs5(args2);
19893
+ const gitRoot = findGitRoot();
19894
+ const route = requireSubtree("pull", args2, gitRoot);
19895
+ if (gitRoot) warnLayoutOnce(gitRoot);
19896
+ if (route.subtree === "bases") {
19897
+ const { pullBase: pullBase2 } = await Promise.resolve().then(() => (init_sync(), sync_exports));
19898
+ await pullBase2(gitRoot, route.selector, args2);
19899
+ return;
19900
+ }
19901
+ const { autoConfirm } = parseArgs6(args2);
19902
+ const hubSelector = route.selector;
18575
19903
  const repoConfig = requireRepoConfig();
18576
19904
  const { organization_id: organizationId } = repoConfig;
18577
19905
  const { config, accessToken } = await requireAuth();
18578
19906
  const client = new ApiClient({ apiUrl: config.api_url, accessToken });
18579
19907
  const workspaceDir = resolveWorkspaceDir();
18580
- const gitRoot = findGitRoot();
18581
- if (gitRoot) warnLayoutOnce(gitRoot);
18582
19908
  if (gitRoot) {
18583
19909
  for (const file of ensureWorkspaceFiles(gitRoot)) {
18584
19910
  console.error(`Created ${file}`);
@@ -18588,7 +19914,7 @@ async function pullCommand(args2) {
18588
19914
  console.log("Fetching hub configuration...");
18589
19915
  const payload = await client.pull(hubId, organizationId);
18590
19916
  if (payload.hub_environment === "production") {
18591
- const folder = await writeProductionMirror(workspaceDir, payload);
19917
+ const folder = await writeProductionMirror2(workspaceDir, payload);
18592
19918
  console.log(`Production hub mirrored (read-only) \u2192 ${folder}`);
18593
19919
  return;
18594
19920
  }
@@ -18604,7 +19930,7 @@ async function pullCommand(args2) {
18604
19930
  payload.preview_label,
18605
19931
  payload.branch_name
18606
19932
  );
18607
- fs15.mkdirSync(path18.dirname(hubFolder), { recursive: true });
19933
+ fs19.mkdirSync(path23.dirname(hubFolder), { recursive: true });
18608
19934
  console.log("Writing hub configuration...");
18609
19935
  await materializeHubFolder(hubFolder, payload);
18610
19936
  const finalFolder = autoRenameHubFolder(hubFolder, payload.hub.name, payload.hub_environment, payload.hub_id, payload.preview_label, payload.branch_name);
@@ -18653,34 +19979,34 @@ async function pullCommand(args2) {
18653
19979
  }
18654
19980
  if (wroteFiles) autoBindIfUnbound(hubId);
18655
19981
  if (payload.production_hub_id) {
18656
- await mirrorLinkedProduction(client, workspaceDir, payload.production_hub_id, organizationId);
19982
+ await mirrorLinkedProduction2(client, workspaceDir, payload.production_hub_id, organizationId);
18657
19983
  }
18658
19984
  }
18659
- async function writeProductionMirror(workspaceDir, prodPayload) {
19985
+ async function writeProductionMirror2(workspaceDir, prodPayload) {
18660
19986
  const folder = resolveHubFolder(workspaceDir, prodPayload.hub_id, prodPayload.hub.name, "production", null, null);
18661
- fs15.mkdirSync(path18.dirname(folder), { recursive: true });
19987
+ fs19.mkdirSync(path23.dirname(folder), { recursive: true });
18662
19988
  await materializeHubFolder(folder, prodPayload, { seedAgentContext: false });
18663
19989
  const finalFolder = autoRenameHubFolder(folder, prodPayload.hub.name, "production", prodPayload.hub_id, null, null);
18664
19990
  prependMirrorMarker(finalFolder, prodPayload.hub_id);
18665
19991
  return finalFolder;
18666
19992
  }
18667
- async function mirrorLinkedProduction(client, workspaceDir, productionHubId, organizationId) {
19993
+ async function mirrorLinkedProduction2(client, workspaceDir, productionHubId, organizationId) {
18668
19994
  try {
18669
19995
  const prodPayload = await client.pull(productionHubId, organizationId);
18670
- const folder = await writeProductionMirror(workspaceDir, prodPayload);
19996
+ const folder = await writeProductionMirror2(workspaceDir, prodPayload);
18671
19997
  console.log(`Mirrored production hub \u2192 ${folder} (read-only)`);
18672
19998
  } catch (err) {
18673
19999
  console.warn(`Warning: could not mirror production hub (${err instanceof Error ? err.message : String(err)}). Preview pull is unaffected.`);
18674
20000
  }
18675
20001
  }
18676
20002
  function prependMirrorMarker(hubFolder, productionHubId) {
18677
- const hubYaml = path18.join(hubFolder, "hub.yaml");
20003
+ const hubYaml = path23.join(hubFolder, "hub.yaml");
18678
20004
  try {
18679
- const content = fs15.readFileSync(hubYaml, "utf-8");
18680
- if (content.startsWith(MIRROR_MARKER_PREFIX)) return;
18681
- const marker = `${MIRROR_MARKER_PREFIX} ${productionHubId}. Edits are ignored; push is blocked. Edit the linked preview hub instead.
20005
+ const content = fs19.readFileSync(hubYaml, "utf-8");
20006
+ if (content.startsWith(MIRROR_MARKER_PREFIX2)) return;
20007
+ const marker = `${MIRROR_MARKER_PREFIX2} ${productionHubId}. Edits are ignored; push is blocked. Edit the linked preview hub instead.
18682
20008
  `;
18683
- fs15.writeFileSync(hubYaml, marker + content, "utf-8");
20009
+ fs19.writeFileSync(hubYaml, marker + content, "utf-8");
18684
20010
  } catch {
18685
20011
  }
18686
20012
  }
@@ -18697,7 +20023,7 @@ function connectionsEqual(a, b) {
18697
20023
  }
18698
20024
  return true;
18699
20025
  }
18700
- var MIRROR_MARKER_PREFIX;
20026
+ var MIRROR_MARKER_PREFIX2;
18701
20027
  var init_pull = __esm({
18702
20028
  "src/commands/pull.ts"() {
18703
20029
  "use strict";
@@ -18714,7 +20040,8 @@ var init_pull = __esm({
18714
20040
  init_workspace_files();
18715
20041
  init_repo_config();
18716
20042
  init_hub_binding();
18717
- MIRROR_MARKER_PREFIX = "# Read-only mirror of production hub";
20043
+ init_subtree_routing();
20044
+ MIRROR_MARKER_PREFIX2 = "# Read-only mirror of production hub";
18718
20045
  }
18719
20046
  });
18720
20047
 
@@ -18723,9 +20050,9 @@ var create_exports = {};
18723
20050
  __export(create_exports, {
18724
20051
  createCommand: () => createCommand
18725
20052
  });
18726
- import * as path19 from "path";
18727
- import * as fs16 from "fs";
18728
- function parseArgs6(args2) {
20053
+ import * as path24 from "path";
20054
+ import * as fs20 from "fs";
20055
+ function parseArgs7(args2) {
18729
20056
  let autoConfirm = false;
18730
20057
  let folderSelector;
18731
20058
  let label;
@@ -18742,7 +20069,7 @@ function parseArgs6(args2) {
18742
20069
  return { autoConfirm, folderSelector, label };
18743
20070
  }
18744
20071
  async function createCommand(args2) {
18745
- const { autoConfirm, folderSelector, label } = parseArgs6(args2);
20072
+ const { autoConfirm, folderSelector, label } = parseArgs7(args2);
18746
20073
  const repoConfig = requireRepoConfig();
18747
20074
  const { organization_id: organizationId } = repoConfig;
18748
20075
  const { config, accessToken } = await requireAuth();
@@ -18751,7 +20078,7 @@ async function createCommand(args2) {
18751
20078
  const gitRoot = findGitRoot();
18752
20079
  const wsLabel = hubsDirLabel(gitRoot);
18753
20080
  if (gitRoot) warnLayoutOnce(gitRoot);
18754
- if (!fs16.existsSync(workspaceDir)) {
20081
+ if (!fs20.existsSync(workspaceDir)) {
18755
20082
  console.error(`No ${wsLabel}/ directory found. Create hub files in ${wsLabel}/<hub>/hub.yaml with \`hub: { name: ... }\` first.`);
18756
20083
  process.exit(1);
18757
20084
  }
@@ -18760,7 +20087,7 @@ async function createCommand(args2) {
18760
20087
  const resolution = resolveNewHubForCreate(workspaceDir, existingHubs, newHubs, folderSelector);
18761
20088
  if (!resolution.ok) {
18762
20089
  if (resolution.reason === "exists") {
18763
- const folder = path19.basename(resolution.existing.hubFolder);
20090
+ const folder = path24.basename(resolution.existing.hubFolder);
18764
20091
  console.error(`Hub "${folder}" already exists (${resolution.existing.hubId}). Use \`wayai push --hub ${folder}\` to update it.`);
18765
20092
  process.exit(1);
18766
20093
  }
@@ -18774,7 +20101,7 @@ async function createCommand(args2) {
18774
20101
  }
18775
20102
  console.error(`Multiple new hub folders found in ${wsLabel}/. Pass the folder name (\`wayai create <folder>\`) or run from inside one:`);
18776
20103
  for (const h of newHubs) {
18777
- console.error(` ${path19.basename(h.hubFolder)} (new \u2014 "${h.hubName}")`);
20104
+ console.error(` ${path24.basename(h.hubFolder)} (new \u2014 "${h.hubName}")`);
18778
20105
  }
18779
20106
  process.exit(1);
18780
20107
  }
@@ -18798,9 +20125,9 @@ var init_create = __esm({
18798
20125
  var diff_exports = {};
18799
20126
  __export(diff_exports, {
18800
20127
  diffCommand: () => diffCommand,
18801
- parseArgs: () => parseArgs7
20128
+ parseArgs: () => parseArgs8
18802
20129
  });
18803
- function parseArgs7(args2) {
20130
+ function parseArgs8(args2) {
18804
20131
  let production = false;
18805
20132
  let hubSelector;
18806
20133
  for (let i = 0; i < args2.length; i++) {
@@ -18814,7 +20141,7 @@ function parseArgs7(args2) {
18814
20141
  return { production, hubSelector };
18815
20142
  }
18816
20143
  async function diffCommand(args2) {
18817
- const { production, hubSelector } = parseArgs7(args2);
20144
+ const { production, hubSelector } = parseArgs8(args2);
18818
20145
  const repoConfig = requireRepoConfig();
18819
20146
  const { organization_id: organizationId } = repoConfig;
18820
20147
  const { config, accessToken } = await requireAuth();
@@ -18885,9 +20212,9 @@ var replicate_exports = {};
18885
20212
  __export(replicate_exports, {
18886
20213
  replicateCommand: () => replicateCommand
18887
20214
  });
18888
- import * as fs17 from "fs";
18889
- import * as path20 from "path";
18890
- function parseArgs8(args2) {
20215
+ import * as fs21 from "fs";
20216
+ import * as path25 from "path";
20217
+ function parseArgs9(args2) {
18891
20218
  let label;
18892
20219
  let hubSelector;
18893
20220
  for (let i = 0; i < args2.length; i++) {
@@ -18903,7 +20230,7 @@ function parseArgs8(args2) {
18903
20230
  return { label, hubSelector };
18904
20231
  }
18905
20232
  async function replicateCommand(args2) {
18906
- const { label, hubSelector } = parseArgs8(args2);
20233
+ const { label, hubSelector } = parseArgs9(args2);
18907
20234
  const normalizedLabel = label?.trim() || void 0;
18908
20235
  if (normalizedLabel && normalizedLabel.length > PREVIEW_LABEL_MAX_LENGTH) {
18909
20236
  console.error(`--label must be ${PREVIEW_LABEL_MAX_LENGTH} characters or fewer.`);
@@ -18932,8 +20259,8 @@ async function replicateCommand(args2) {
18932
20259
  payload.preview_label,
18933
20260
  payload.branch_name
18934
20261
  );
18935
- const folderPreExisted = fs17.existsSync(hubFolder);
18936
- fs17.mkdirSync(path20.dirname(hubFolder), { recursive: true });
20262
+ const folderPreExisted = fs21.existsSync(hubFolder);
20263
+ fs21.mkdirSync(path25.dirname(hubFolder), { recursive: true });
18937
20264
  const delta = await materializeHubFolder(hubFolder, payload);
18938
20265
  hubFolder = autoRenameHubFolder(
18939
20266
  hubFolder,
@@ -18945,8 +20272,8 @@ async function replicateCommand(args2) {
18945
20272
  );
18946
20273
  autoBindIfUnbound(previewHubId);
18947
20274
  if (folderPreExisted) printLocalFileChanges(delta);
18948
- console.log(`Preview written to ${path20.basename(hubFolder)}`);
18949
- console.log(` Switch to it with: wayai use ${path20.basename(hubFolder)}`);
20275
+ console.log(`Preview written to ${path25.basename(hubFolder)}`);
20276
+ console.log(` Switch to it with: wayai use ${path25.basename(hubFolder)}`);
18950
20277
  }
18951
20278
  var init_replicate = __esm({
18952
20279
  "src/commands/replicate.ts"() {
@@ -18969,8 +20296,8 @@ var relabel_exports = {};
18969
20296
  __export(relabel_exports, {
18970
20297
  relabelCommand: () => relabelCommand
18971
20298
  });
18972
- import * as path21 from "path";
18973
- function parseArgs9(args2) {
20299
+ import * as path26 from "path";
20300
+ function parseArgs10(args2) {
18974
20301
  let label;
18975
20302
  let clear = false;
18976
20303
  let hubSelector;
@@ -18987,7 +20314,7 @@ function parseArgs9(args2) {
18987
20314
  return { label, clear, hubSelector };
18988
20315
  }
18989
20316
  async function relabelCommand(args2) {
18990
- const { label, clear, hubSelector } = parseArgs9(args2);
20317
+ const { label, clear, hubSelector } = parseArgs10(args2);
18991
20318
  if (!clear && (label === void 0 || label.trim() === "")) {
18992
20319
  console.error("Usage: wayai relabel <label> [--hub <uuid|folder>] (or --clear to remove the label)");
18993
20320
  process.exit(1);
@@ -19013,7 +20340,7 @@ async function relabelCommand(args2) {
19013
20340
  } else {
19014
20341
  console.error(`Multiple hubs found in ${wsLabel}/. Pass --hub <uuid|folder-name> to choose, or run from inside a hub folder:`);
19015
20342
  for (const h of previewHubs) {
19016
- console.error(` ${path21.basename(h.hubFolder)} (${h.hubId})`);
20343
+ console.error(` ${path26.basename(h.hubFolder)} (${h.hubId})`);
19017
20344
  }
19018
20345
  }
19019
20346
  process.exit(1);
@@ -19022,7 +20349,7 @@ async function relabelCommand(args2) {
19022
20349
  console.log("This is a read-only production mirror \u2014 production hubs have no preview label. Relabel the linked preview hub instead.");
19023
20350
  return;
19024
20351
  }
19025
- assertHubMatchesBinding(target.hubId, path21.basename(target.hubFolder));
20352
+ assertHubMatchesBinding(target.hubId, path26.basename(target.hubFolder));
19026
20353
  console.log(normalizedLabel ? `Setting preview label to "${normalizedLabel}"...` : "Clearing preview label...");
19027
20354
  const { data } = await client.relabelPreview(target.hubId, normalizedLabel);
19028
20355
  const row = data[0];
@@ -19038,7 +20365,7 @@ async function relabelCommand(args2) {
19038
20365
  );
19039
20366
  console.log(serverLabel ? `Preview label set to "${serverLabel}".` : "Preview label cleared.");
19040
20367
  if (finalFolder !== target.hubFolder) {
19041
- console.log(`Hub folder is now ${path21.basename(finalFolder)}`);
20368
+ console.log(`Hub folder is now ${path26.basename(finalFolder)}`);
19042
20369
  }
19043
20370
  }
19044
20371
  var init_relabel = __esm({
@@ -19059,13 +20386,13 @@ var init_relabel = __esm({
19059
20386
  // src/commands/publish.ts
19060
20387
  var publish_exports = {};
19061
20388
  __export(publish_exports, {
19062
- parseArgs: () => parseArgs10,
20389
+ parseArgs: () => parseArgs11,
19063
20390
  publishCommand: () => publishCommand,
19064
20391
  renderHubDiff: () => renderHubDiff,
19065
20392
  runPublish: () => runPublish
19066
20393
  });
19067
- import * as path22 from "path";
19068
- function parseArgs10(args2) {
20394
+ import * as path27 from "path";
20395
+ function parseArgs11(args2) {
19069
20396
  let autoConfirm = false;
19070
20397
  let hubSelector;
19071
20398
  for (let i = 0; i < args2.length; i++) {
@@ -19159,7 +20486,7 @@ Published. Production hub: ${data.production_hub_id}`);
19159
20486
  return "synced";
19160
20487
  }
19161
20488
  async function publishCommand(args2) {
19162
- const { autoConfirm, hubSelector } = parseArgs10(args2);
20489
+ const { autoConfirm, hubSelector } = parseArgs11(args2);
19163
20490
  const repoConfig = requireRepoConfig();
19164
20491
  const { organization_id: organizationId } = repoConfig;
19165
20492
  const { config, accessToken } = await requireAuth();
@@ -19178,7 +20505,7 @@ async function publishCommand(args2) {
19178
20505
  return;
19179
20506
  }
19180
20507
  }
19181
- assertHubMatchesBinding(hubId, hubFolder ? path22.basename(hubFolder) : void 0);
20508
+ assertHubMatchesBinding(hubId, hubFolder ? path27.basename(hubFolder) : void 0);
19182
20509
  await runPublish(client, { hubId, localConfig, organizationId, autoConfirm });
19183
20510
  }
19184
20511
  var STATUS_STYLE;
@@ -19211,7 +20538,7 @@ var use_exports = {};
19211
20538
  __export(use_exports, {
19212
20539
  useCommand: () => useCommand
19213
20540
  });
19214
- import * as path23 from "path";
20541
+ import * as path28 from "path";
19215
20542
  async function useCommand(args2) {
19216
20543
  const target = args2[0];
19217
20544
  if (!target || target.startsWith("-")) {
@@ -19233,7 +20560,7 @@ async function useCommand(args2) {
19233
20560
  const match = findHubByFolderName(workspaceDir, target);
19234
20561
  if (!match) {
19235
20562
  const newHubs = scanNewHubs(workspaceDir);
19236
- const pending = newHubs.find((h) => path23.basename(h.hubFolder) === target);
20563
+ const pending = newHubs.find((h) => path28.basename(h.hubFolder) === target);
19237
20564
  if (pending) {
19238
20565
  console.error(
19239
20566
  `"${target}" is a new hub that hasn't been created on the platform yet, so it has no id to bind to.
@@ -19244,10 +20571,10 @@ Create it first \u2014 the worktree binds automatically afterward:
19244
20571
  }
19245
20572
  console.error(`No hub matching "${target}" found in ${wsLabel}/. Pass a UUID or a folder name from:`);
19246
20573
  for (const h of scanWorkspaceHubs(workspaceDir)) {
19247
- console.error(` ${path23.basename(h.hubFolder)} (${h.hubId})`);
20574
+ console.error(` ${path28.basename(h.hubFolder)} (${h.hubId})`);
19248
20575
  }
19249
20576
  for (const h of newHubs) {
19250
- console.error(` ${path23.basename(h.hubFolder)} (new \u2014 "${h.hubName}", run \`wayai create ${path23.basename(h.hubFolder)}\`)`);
20577
+ console.error(` ${path28.basename(h.hubFolder)} (new \u2014 "${h.hubName}", run \`wayai create ${path28.basename(h.hubFolder)}\`)`);
19251
20578
  }
19252
20579
  process.exit(1);
19253
20580
  }
@@ -19286,11 +20613,11 @@ __export(migrate_exports, {
19286
20613
  migrateCommand: () => migrateCommand
19287
20614
  });
19288
20615
  import { execFileSync as execFileSync3 } from "child_process";
19289
- import * as fs18 from "fs";
19290
- import * as path24 from "path";
20616
+ import * as fs22 from "fs";
20617
+ import * as path29 from "path";
19291
20618
  function isTracked(gitRoot, p) {
19292
20619
  try {
19293
- execFileSync3("git", ["ls-files", "--error-unmatch", "--", path24.relative(gitRoot, p)], {
20620
+ execFileSync3("git", ["ls-files", "--error-unmatch", "--", path29.relative(gitRoot, p)], {
19294
20621
  cwd: gitRoot,
19295
20622
  stdio: ["pipe", "pipe", "pipe"]
19296
20623
  });
@@ -19300,10 +20627,10 @@ function isTracked(gitRoot, p) {
19300
20627
  }
19301
20628
  }
19302
20629
  function moveDir(gitRoot, from, to) {
19303
- fs18.mkdirSync(path24.dirname(to), { recursive: true });
20630
+ fs22.mkdirSync(path29.dirname(to), { recursive: true });
19304
20631
  if (isTracked(gitRoot, from)) {
19305
20632
  try {
19306
- execFileSync3("git", ["mv", path24.relative(gitRoot, from), path24.relative(gitRoot, to)], {
20633
+ execFileSync3("git", ["mv", path29.relative(gitRoot, from), path29.relative(gitRoot, to)], {
19307
20634
  cwd: gitRoot,
19308
20635
  stdio: ["pipe", "pipe", "pipe"]
19309
20636
  });
@@ -19311,7 +20638,7 @@ function moveDir(gitRoot, from, to) {
19311
20638
  } catch {
19312
20639
  }
19313
20640
  }
19314
- fs18.renameSync(from, to);
20641
+ fs22.renameSync(from, to);
19315
20642
  return "fs";
19316
20643
  }
19317
20644
  async function migrateCommand(_args) {
@@ -19320,12 +20647,12 @@ async function migrateCommand(_args) {
19320
20647
  console.error("Not inside a git repository.");
19321
20648
  process.exit(1);
19322
20649
  }
19323
- const rel = (p) => path24.relative(gitRoot, p);
19324
- const newWs = path24.join(gitRoot, WAYAI_LAYOUT.wsDir);
19325
- const legacyWs = path24.join(gitRoot, WAYAI_LAYOUT.legacy.wsDir);
19326
- const legacyOrg = path24.join(gitRoot, WAYAI_LAYOUT.legacy.orgAtRoot);
19327
- const newHubs = path24.join(newWs, WAYAI_LAYOUT.hubsSubdir);
19328
- const newOrg = path24.join(newWs, WAYAI_LAYOUT.orgSubdir);
20650
+ const rel = (p) => path29.relative(gitRoot, p);
20651
+ const newWs = path29.join(gitRoot, WAYAI_LAYOUT.wsDir);
20652
+ const legacyWs = path29.join(gitRoot, WAYAI_LAYOUT.legacy.wsDir);
20653
+ const legacyOrg = path29.join(gitRoot, WAYAI_LAYOUT.legacy.orgAtRoot);
20654
+ const newHubs = path29.join(newWs, WAYAI_LAYOUT.hubsSubdir);
20655
+ const newOrg = path29.join(newWs, WAYAI_LAYOUT.orgSubdir);
19329
20656
  const hasLegacyWs = isDirectory(legacyWs);
19330
20657
  const hasLegacyOrg = isDirectory(legacyOrg);
19331
20658
  if (!hasLegacyWs && !hasLegacyOrg) {
@@ -19399,12 +20726,12 @@ var send_message_exports = {};
19399
20726
  __export(send_message_exports, {
19400
20727
  sendMessageCommand: () => sendMessageCommand
19401
20728
  });
19402
- import * as fs19 from "fs";
19403
- import * as path25 from "path";
20729
+ import * as fs23 from "fs";
20730
+ import * as path30 from "path";
19404
20731
  function statAttachment(filePath) {
19405
20732
  let stat2;
19406
20733
  try {
19407
- stat2 = fs19.statSync(filePath);
20734
+ stat2 = fs23.statSync(filePath);
19408
20735
  } catch {
19409
20736
  console.error(`Error: file not found: ${filePath}`);
19410
20737
  process.exit(1);
@@ -19416,11 +20743,11 @@ function statAttachment(filePath) {
19416
20743
  return { filePath, size: stat2.size };
19417
20744
  }
19418
20745
  function readAttachment(filePath, size) {
19419
- const fileName = path25.basename(filePath);
19420
- const ext = path25.extname(fileName).replace(/^\./, "");
20746
+ const fileName = path30.basename(filePath);
20747
+ const ext = path30.extname(fileName).replace(/^\./, "");
19421
20748
  return {
19422
20749
  file_name: fileName,
19423
- file_binary: fs19.readFileSync(filePath).toString("base64"),
20750
+ file_binary: fs23.readFileSync(filePath).toString("base64"),
19424
20751
  file_size: size,
19425
20752
  ...ext && { file_extension: ext }
19426
20753
  };
@@ -19467,7 +20794,7 @@ async function sendMessageCommand(args2) {
19467
20794
  }
19468
20795
  const stats = filePaths.map(statAttachment);
19469
20796
  const filesTotal = stats.reduce((sum, s) => sum + base64Length(s.size), 0);
19470
- const fileDetail = () => stats.map((s) => `${path25.basename(s.filePath)} ${asMb(s.size)} MB`).join(", ");
20797
+ const fileDetail = () => stats.map((s) => `${path30.basename(s.filePath)} ${asMb(s.size)} MB`).join(", ");
19471
20798
  if (filesTotal > MAX_MESSAGE_BODY_BYTES) {
19472
20799
  console.error(
19473
20800
  `Error: ${fileDetail()} encode to ~${asMb(filesTotal)} MB, over the ${asMb(MAX_MESSAGE_BODY_BYTES)} MB per-request limit.`
@@ -19475,10 +20802,10 @@ async function sendMessageCommand(args2) {
19475
20802
  console.error("Base64 inflates a file by about a third, so ~7 MB of files is the practical ceiling.");
19476
20803
  process.exit(1);
19477
20804
  }
19478
- const audioStats = stats.filter((s) => isAudioAttachmentFileName(path25.basename(s.filePath)));
20805
+ const audioStats = stats.filter((s) => isAudioAttachmentFileName(path30.basename(s.filePath)));
19479
20806
  if (audioStats.length > 1) {
19480
20807
  console.error(
19481
- `Error: at most one audio file per message (got ${audioStats.length}: ${audioStats.map((s) => path25.basename(s.filePath)).join(", ")}).`
20808
+ `Error: at most one audio file per message (got ${audioStats.length}: ${audioStats.map((s) => path30.basename(s.filePath)).join(", ")}).`
19482
20809
  );
19483
20810
  console.error("Audio is transcribed via the hub's STT connection, and only one file per message is transcribed.");
19484
20811
  process.exit(1);
@@ -19486,7 +20813,7 @@ async function sendMessageCommand(args2) {
19486
20813
  const oversizeAudio = audioStats.find((s) => base64Length(s.size) > MAX_AUDIO_FILE_BASE64_BYTES);
19487
20814
  if (oversizeAudio) {
19488
20815
  console.error(
19489
- `Error: ${path25.basename(oversizeAudio.filePath)} (${asMb(oversizeAudio.size)} MB) is over the ~${asMb(MAX_AUDIO_FILE_BASE64_BYTES * 3 / 4)} MB audio limit for transcription.`
20816
+ `Error: ${path30.basename(oversizeAudio.filePath)} (${asMb(oversizeAudio.size)} MB) is over the ~${asMb(MAX_AUDIO_FILE_BASE64_BYTES * 3 / 4)} MB audio limit for transcription.`
19490
20817
  );
19491
20818
  process.exit(1);
19492
20819
  }
@@ -20363,10 +21690,10 @@ var init_delete_history = __esm({
20363
21690
  // src/commands/sync-skills.ts
20364
21691
  var sync_skills_exports = {};
20365
21692
  __export(sync_skills_exports, {
20366
- parseArgs: () => parseArgs11,
21693
+ parseArgs: () => parseArgs12,
20367
21694
  syncSkillsCommand: () => syncSkillsCommand
20368
21695
  });
20369
- function parseArgs11(args2) {
21696
+ function parseArgs12(args2) {
20370
21697
  let connectionId;
20371
21698
  const idx = args2.indexOf("--connection-id");
20372
21699
  if (idx !== -1 && args2[idx + 1]) {
@@ -20389,7 +21716,7 @@ function printSyncResults(response) {
20389
21716
  }
20390
21717
  async function syncSkillsCommand(args2) {
20391
21718
  const hubId = resolveActiveHubId(args2);
20392
- const { connectionId } = parseArgs11(args2);
21719
+ const { connectionId } = parseArgs12(args2);
20393
21720
  requireRepoConfig();
20394
21721
  const { config, accessToken } = await requireAuth();
20395
21722
  const client = new ApiClient({ apiUrl: config.api_url, accessToken });
@@ -20414,10 +21741,10 @@ var init_sync_skills = __esm({
20414
21741
  // src/commands/sync-mcp.ts
20415
21742
  var sync_mcp_exports = {};
20416
21743
  __export(sync_mcp_exports, {
20417
- parseArgs: () => parseArgs12,
21744
+ parseArgs: () => parseArgs13,
20418
21745
  syncMcpCommand: () => syncMcpCommand
20419
21746
  });
20420
- function parseArgs12(args2) {
21747
+ function parseArgs13(args2) {
20421
21748
  let connection;
20422
21749
  let check = false;
20423
21750
  for (let i = 0; i < args2.length; i++) {
@@ -20432,7 +21759,7 @@ function parseArgs12(args2) {
20432
21759
  }
20433
21760
  async function syncMcpCommand(args2) {
20434
21761
  const hubId = resolveActiveHubId(args2);
20435
- const { connection, check } = parseArgs12(args2);
21762
+ const { connection, check } = parseArgs13(args2);
20436
21763
  if (!connection) {
20437
21764
  console.error("Usage: wayai sync-mcp --connection <name> [--hub <uuid|folder-name>] [--check]");
20438
21765
  console.error("");
@@ -20711,8 +22038,8 @@ function installEvalSignalHandlers(input) {
20711
22038
  let signalCount = 0;
20712
22039
  let disposed = false;
20713
22040
  let settle;
20714
- const settled = new Promise((resolve5) => {
20715
- settle = resolve5;
22041
+ const settled = new Promise((resolve7) => {
22042
+ settle = resolve7;
20716
22043
  });
20717
22044
  const listeners = /* @__PURE__ */ new Map();
20718
22045
  const dispose = () => {
@@ -21062,7 +22389,7 @@ Timeout after ${timeoutSeconds}s${queuedSeconds > 0 ? ` (${queuedSeconds}s of it
21062
22389
  process.exit(1);
21063
22390
  }
21064
22391
  function sleep(ms) {
21065
- return new Promise((resolve5) => setTimeout(resolve5, ms));
22392
+ return new Promise((resolve7) => setTimeout(resolve7, ms));
21066
22393
  }
21067
22394
  function parseRunNumbers(raw) {
21068
22395
  if (!raw || raw.startsWith("--")) {
@@ -21332,15 +22659,15 @@ var eval_capture_exports = {};
21332
22659
  __export(eval_capture_exports, {
21333
22660
  evalCaptureCommand: () => evalCaptureCommand
21334
22661
  });
21335
- import * as fs20 from "fs";
21336
- import * as path26 from "path";
21337
- import * as yaml7 from "js-yaml";
22662
+ import * as fs24 from "fs";
22663
+ import * as path31 from "path";
22664
+ import * as yaml11 from "js-yaml";
21338
22665
  function isValidSetName(name) {
21339
22666
  if (name.length === 0 || name === "." || name === "..") return false;
21340
22667
  if (name.startsWith(".")) return false;
21341
22668
  return !/[\/\\\0]/.test(name);
21342
22669
  }
21343
- function parseArgs13(args2) {
22670
+ function parseArgs14(args2) {
21344
22671
  if (args2.length === 0 || args2[0].startsWith("-")) {
21345
22672
  console.error("Usage: wayai eval capture <conversation_id> [--set <name>] [--name <eval_name>] [--instructions <text>]");
21346
22673
  process.exit(1);
@@ -21386,7 +22713,7 @@ function parseArgs13(args2) {
21386
22713
  }
21387
22714
  async function evalCaptureCommand(args2) {
21388
22715
  const hubId = resolveActiveHubId(args2);
21389
- const parsed = parseArgs13(args2);
22716
+ const parsed = parseArgs14(args2);
21390
22717
  const { config, accessToken } = await requireAuth();
21391
22718
  requireRepoConfig();
21392
22719
  const client = new ApiClient({ apiUrl: config.api_url, accessToken });
@@ -21399,15 +22726,15 @@ async function evalCaptureCommand(args2) {
21399
22726
  const setFolderName = targetSetName;
21400
22727
  const scenarioName = parsed.evalName ?? `Capture ${parsed.conversationId.slice(0, 8)}`;
21401
22728
  const slug = slugify(scenarioName);
21402
- const evalsDir = path26.join(hubFolder, "evals");
21403
- const targetDir = path26.join(evalsDir, setFolderName);
21404
- const targetPath = path26.join(targetDir, `${slug}.yaml`);
21405
- if (!targetPath.startsWith(evalsDir + path26.sep)) {
21406
- console.error(`Resolved path "${path26.relative(hubFolder, targetPath)}" escapes evals/. Aborting.`);
22729
+ const evalsDir = path31.join(hubFolder, "evals");
22730
+ const targetDir = path31.join(evalsDir, setFolderName);
22731
+ const targetPath = path31.join(targetDir, `${slug}.yaml`);
22732
+ if (!targetPath.startsWith(evalsDir + path31.sep)) {
22733
+ console.error(`Resolved path "${path31.relative(hubFolder, targetPath)}" escapes evals/. Aborting.`);
21407
22734
  process.exit(1);
21408
22735
  }
21409
- if (fs20.existsSync(targetPath)) {
21410
- console.error(`File already exists: ${path26.relative(hubFolder, targetPath)}. Use --name to choose a different name.`);
22736
+ if (fs24.existsSync(targetPath)) {
22737
+ console.error(`File already exists: ${path31.relative(hubFolder, targetPath)}. Use --name to choose a different name.`);
21411
22738
  process.exit(1);
21412
22739
  }
21413
22740
  console.log("Resolving scenario set...");
@@ -21439,9 +22766,9 @@ async function evalCaptureCommand(args2) {
21439
22766
  ...captured.evaluator_instructions ? { evaluator_instructions: captured.evaluator_instructions } : {}
21440
22767
  };
21441
22768
  const yamlObj = buildEvalYamlObject(evalEntry, slug);
21442
- fs20.mkdirSync(targetDir, { recursive: true });
21443
- fs20.writeFileSync(targetPath, yaml7.dump(yamlObj, YAML_DUMP_OPTIONS), "utf-8");
21444
- const relPath = path26.relative(process.cwd(), targetPath);
22769
+ fs24.mkdirSync(targetDir, { recursive: true });
22770
+ fs24.writeFileSync(targetPath, yaml11.dump(yamlObj, YAML_DUMP_OPTIONS), "utf-8");
22771
+ const relPath = path31.relative(process.cwd(), targetPath);
21445
22772
  console.log(`
21446
22773
  Wrote ${relPath}`);
21447
22774
  console.log("Run `wayai pull` to refresh the agent display name, then commit. The scenario is already on the platform.");
@@ -21463,7 +22790,7 @@ var journey_capture_exports = {};
21463
22790
  __export(journey_capture_exports, {
21464
22791
  journeyCaptureCommand: () => journeyCaptureCommand
21465
22792
  });
21466
- function parseArgs14(args2) {
22793
+ function parseArgs15(args2) {
21467
22794
  if (args2.length === 0 || args2[0].startsWith("-")) {
21468
22795
  console.error("Usage: wayai eval journey capture <conversation_id> [--name <journey_name>] [--instructions <text>]");
21469
22796
  process.exit(1);
@@ -21498,7 +22825,7 @@ function parseArgs14(args2) {
21498
22825
  }
21499
22826
  async function journeyCaptureCommand(args2) {
21500
22827
  const hubId = resolveActiveHubId(args2);
21501
- const parsed = parseArgs14(args2);
22828
+ const parsed = parseArgs15(args2);
21502
22829
  const { config, accessToken } = await requireAuth();
21503
22830
  requireRepoConfig();
21504
22831
  const client = new ApiClient({ apiUrl: config.api_url, accessToken });
@@ -22426,9 +23753,9 @@ var init_credential_utils = __esm({
22426
23753
  var create_credential_exports = {};
22427
23754
  __export(create_credential_exports, {
22428
23755
  createCredentialCommand: () => createCredentialCommand,
22429
- parseArgs: () => parseArgs15
23756
+ parseArgs: () => parseArgs16
22430
23757
  });
22431
- function parseArgs15(args2) {
23758
+ function parseArgs16(args2) {
22432
23759
  let name;
22433
23760
  let type;
22434
23761
  let orgId;
@@ -22456,7 +23783,7 @@ function parseArgs15(args2) {
22456
23783
  return { name, type, orgId, description, tags: splitTagRefs(tags), environment, stdin };
22457
23784
  }
22458
23785
  async function createCredentialCommand(args2) {
22459
- const parsed = parseArgs15(args2);
23786
+ const parsed = parseArgs16(args2);
22460
23787
  if (!parsed.name) {
22461
23788
  console.error("Missing required flag: --name <credential-name>");
22462
23789
  console.error('Usage: wayai create-credential --name "openai-key" --type "Bearer Token"');
@@ -22563,10 +23890,10 @@ var init_create_credential = __esm({
22563
23890
  // src/commands/update-credential.ts
22564
23891
  var update_credential_exports = {};
22565
23892
  __export(update_credential_exports, {
22566
- parseArgs: () => parseArgs16,
23893
+ parseArgs: () => parseArgs17,
22567
23894
  updateCredentialCommand: () => updateCredentialCommand
22568
23895
  });
22569
- function parseArgs16(args2) {
23896
+ function parseArgs17(args2) {
22570
23897
  let name;
22571
23898
  let rename;
22572
23899
  let orgId;
@@ -22599,7 +23926,7 @@ function parseArgs16(args2) {
22599
23926
  return { name, rename, orgId, description, tags: splitTagRefs(tags), hasTagFlag, environment, stdin, secretPrompt };
22600
23927
  }
22601
23928
  async function updateCredentialCommand(args2) {
22602
- const parsed = parseArgs16(args2);
23929
+ const parsed = parseArgs17(args2);
22603
23930
  if (!parsed.name) {
22604
23931
  console.error("Missing required flag: --name <credential-name>");
22605
23932
  console.error('Usage: wayai update-credential --name "my-key" --stdin');
@@ -22712,10 +24039,10 @@ var init_update_credential = __esm({
22712
24039
  // src/commands/set-connection-credential.ts
22713
24040
  var set_connection_credential_exports = {};
22714
24041
  __export(set_connection_credential_exports, {
22715
- parseArgs: () => parseArgs17,
24042
+ parseArgs: () => parseArgs18,
22716
24043
  setConnectionCredentialCommand: () => setConnectionCredentialCommand
22717
24044
  });
22718
- function parseArgs17(args2) {
24045
+ function parseArgs18(args2) {
22719
24046
  let connection;
22720
24047
  let orgCredential;
22721
24048
  let field;
@@ -22738,7 +24065,7 @@ function usage2(msg) {
22738
24065
  }
22739
24066
  async function setConnectionCredentialCommand(args2) {
22740
24067
  const hubId = resolveActiveHubId(args2);
22741
- const parsed = parseArgs17(args2);
24068
+ const parsed = parseArgs18(args2);
22742
24069
  if (!parsed.connection) usage2("Missing required flag: --connection <name|id>");
22743
24070
  const orgMode = !!parsed.orgCredential;
22744
24071
  const directMode = !!parsed.field;
@@ -22807,23 +24134,23 @@ var init_set_connection_credential = __esm({
22807
24134
  });
22808
24135
 
22809
24136
  // src/lib/org-workspace.ts
22810
- import * as fs21 from "fs";
22811
- import * as path27 from "path";
22812
- import * as yaml8 from "js-yaml";
24137
+ import * as fs25 from "fs";
24138
+ import * as path32 from "path";
24139
+ import * as yaml12 from "js-yaml";
22813
24140
  function getOrgDir(gitRoot) {
22814
24141
  return resolveLayout(gitRoot).orgDir;
22815
24142
  }
22816
24143
  function orgManifestExists(orgDir) {
22817
- return fs21.existsSync(path27.join(orgDir, ORG_MANIFEST_NAME));
24144
+ return fs25.existsSync(path32.join(orgDir, ORG_MANIFEST_NAME));
22818
24145
  }
22819
24146
  function parseOrgResources(orgDir) {
22820
- const manifestPath = path27.join(orgDir, ORG_MANIFEST_NAME);
24147
+ const manifestPath = path32.join(orgDir, ORG_MANIFEST_NAME);
22821
24148
  let manifest = {};
22822
- if (fs21.existsSync(manifestPath)) {
22823
- manifest = yaml8.load(fs21.readFileSync(manifestPath, "utf-8")) ?? {};
24149
+ if (fs25.existsSync(manifestPath)) {
24150
+ manifest = yaml12.load(fs25.readFileSync(manifestPath, "utf-8")) ?? {};
22824
24151
  }
22825
24152
  const rawResources = Array.isArray(manifest.resources) ? manifest.resources : [];
22826
- const resourcesDir = path27.join(orgDir, "resources");
24153
+ const resourcesDir = path32.join(orgDir, "resources");
22827
24154
  const resources = rawResources.map((res) => {
22828
24155
  const resource = { name: res.name };
22829
24156
  if (res.id) resource.id = res.id;
@@ -22835,8 +24162,8 @@ function parseOrgResources(orgDir) {
22835
24162
  if (res.environment) resource.environment = res.environment;
22836
24163
  if (Array.isArray(res.tags)) resource.tags = res.tags;
22837
24164
  if (Array.isArray(res.folders)) resource.folders = res.folders;
22838
- const resDir = path27.join(resourcesDir, slugify(resource.name));
22839
- if (fs21.existsSync(resDir)) {
24165
+ const resDir = path32.join(resourcesDir, slugify(resource.name));
24166
+ if (fs25.existsSync(resDir)) {
22840
24167
  const files = scanResourceFiles(resDir, "");
22841
24168
  if (files.length > 0) resource.files = files;
22842
24169
  }
@@ -22845,28 +24172,28 @@ function parseOrgResources(orgDir) {
22845
24172
  return { version: 1, resources };
22846
24173
  }
22847
24174
  function writeOrgResources(orgDir, payload) {
22848
- fs21.mkdirSync(orgDir, { recursive: true });
24175
+ fs25.mkdirSync(orgDir, { recursive: true });
22849
24176
  const resources = payload.resources ?? [];
22850
24177
  const manifestResources = resources.map((r) => {
22851
24178
  const { files: _files, ...rest } = r;
22852
24179
  return rest;
22853
24180
  });
22854
- fs21.writeFileSync(
22855
- path27.join(orgDir, ORG_MANIFEST_NAME),
22856
- yaml8.dump({ version: 1, resources: manifestResources }, YAML_DUMP_OPTIONS),
24181
+ fs25.writeFileSync(
24182
+ path32.join(orgDir, ORG_MANIFEST_NAME),
24183
+ yaml12.dump({ version: 1, resources: manifestResources }, YAML_DUMP_OPTIONS),
22857
24184
  "utf-8"
22858
24185
  );
22859
- const resourcesDir = path27.join(orgDir, "resources");
24186
+ const resourcesDir = path32.join(orgDir, "resources");
22860
24187
  const currentSlugs = /* @__PURE__ */ new Set();
22861
24188
  for (const resource of resources) {
22862
24189
  const resSlug = slugify(resource.name);
22863
24190
  currentSlugs.add(resSlug);
22864
- writeResourceFileTree(path27.join(resourcesDir, resSlug), resource.files || [], orgDir);
24191
+ writeResourceFileTree(path32.join(resourcesDir, resSlug), resource.files || [], orgDir);
22865
24192
  }
22866
- if (fs21.existsSync(resourcesDir)) {
22867
- for (const entry of fs21.readdirSync(resourcesDir, { withFileTypes: true })) {
24193
+ if (fs25.existsSync(resourcesDir)) {
24194
+ for (const entry of fs25.readdirSync(resourcesDir, { withFileTypes: true })) {
22868
24195
  if (entry.isDirectory() && !currentSlugs.has(entry.name)) {
22869
- fs21.rmSync(path27.join(resourcesDir, entry.name), { recursive: true, force: true });
24196
+ fs25.rmSync(path32.join(resourcesDir, entry.name), { recursive: true, force: true });
22870
24197
  }
22871
24198
  }
22872
24199
  }
@@ -22875,7 +24202,7 @@ async function downloadOrgBinaryFiles(orgDir, payload) {
22875
24202
  let count = 0;
22876
24203
  for (const resource of payload.resources ?? []) {
22877
24204
  if (!resource.files) continue;
22878
- const resDir = path27.join(orgDir, "resources", slugify(resource.name));
24205
+ const resDir = path32.join(orgDir, "resources", slugify(resource.name));
22879
24206
  count += await downloadBinaryFiles(resDir, resource.files, orgDir);
22880
24207
  }
22881
24208
  if (count > 0) console.log(`Downloaded ${count} binary resource file(s).`);
@@ -23063,9 +24390,9 @@ var init_org = __esm({
23063
24390
  var list_exports = {};
23064
24391
  __export(list_exports, {
23065
24392
  listCommand: () => listCommand,
23066
- parseArgs: () => parseArgs18
24393
+ parseArgs: () => parseArgs19
23067
24394
  });
23068
- function parseArgs18(args2) {
24395
+ function parseArgs19(args2) {
23069
24396
  let orgId;
23070
24397
  let json = false;
23071
24398
  for (let i = 0; i < args2.length; i++) {
@@ -23078,7 +24405,7 @@ function parseArgs18(args2) {
23078
24405
  return { orgId, json };
23079
24406
  }
23080
24407
  async function listCommand(args2) {
23081
- const { orgId, json } = parseArgs18(args2);
24408
+ const { orgId, json } = parseArgs19(args2);
23082
24409
  const { config, accessToken } = await requireAuth();
23083
24410
  const client = new ApiClient({ apiUrl: config.api_url, accessToken });
23084
24411
  const { organizations } = await client.organizations();
@@ -23171,8 +24498,8 @@ var init_report_edit_args = __esm({
23171
24498
  });
23172
24499
 
23173
24500
  // src/lib/file-map.ts
23174
- import * as fs22 from "fs";
23175
- import * as path28 from "path";
24501
+ import * as fs26 from "fs";
24502
+ import * as path33 from "path";
23176
24503
  function isSafeRelPath(rel) {
23177
24504
  if (rel.length === 0 || rel.length > 300) return false;
23178
24505
  if (rel.startsWith("/") || rel.includes("\\")) return false;
@@ -23187,9 +24514,9 @@ function writeFileMap(targetDir, files) {
23187
24514
  if (!isSafeRelPath(rel)) {
23188
24515
  throw new Error(`Refusing to write unsafe path: ${rel}`);
23189
24516
  }
23190
- const abs = path28.join(targetDir, rel);
23191
- fs22.mkdirSync(path28.dirname(abs), { recursive: true });
23192
- fs22.writeFileSync(abs, body, "utf-8");
24517
+ const abs = path33.join(targetDir, rel);
24518
+ fs26.mkdirSync(path33.dirname(abs), { recursive: true });
24519
+ fs26.writeFileSync(abs, body, "utf-8");
23193
24520
  written.push(rel);
23194
24521
  }
23195
24522
  return written;
@@ -23205,8 +24532,8 @@ var admin_exports = {};
23205
24532
  __export(admin_exports, {
23206
24533
  adminCommand: () => adminCommand
23207
24534
  });
23208
- import * as fs23 from "fs";
23209
- import * as path29 from "path";
24535
+ import * as fs27 from "fs";
24536
+ import * as path34 from "path";
23210
24537
  async function adminCommand(args2) {
23211
24538
  const [group, ...afterGroup] = args2;
23212
24539
  if (!group) {
@@ -23363,6 +24690,20 @@ async function adminCommand(args2) {
23363
24690
  process.exit(1);
23364
24691
  }
23365
24692
  }
24693
+ if (group === "orgs") {
24694
+ if (!sub) {
24695
+ printHelp2();
24696
+ process.exit(1);
24697
+ }
24698
+ switch (sub) {
24699
+ case "repair-legacy-grants":
24700
+ await runRepairLegacyOrgGrants(flagArgs);
24701
+ return;
24702
+ default:
24703
+ printHelp2();
24704
+ process.exit(1);
24705
+ }
24706
+ }
23366
24707
  if (group === "harness") {
23367
24708
  if (!sub) {
23368
24709
  printHelp2();
@@ -23507,7 +24848,7 @@ async function runArchiveRead(positional, flagArgs) {
23507
24848
  exitOnApiError(err);
23508
24849
  throw err;
23509
24850
  }
23510
- fs23.writeFileSync(outPath, zip);
24851
+ fs27.writeFileSync(outPath, zip);
23511
24852
  console.log(`Wrote ${zip.byteLength} bytes to ${outPath}`);
23512
24853
  return;
23513
24854
  }
@@ -23649,13 +24990,13 @@ async function runSkillInstall(positional) {
23649
24990
  throw err;
23650
24991
  }
23651
24992
  const root = findGitRoot() ?? process.cwd();
23652
- const present = HARNESS_SKILL_DIRS.filter((dir) => fs23.existsSync(path29.join(root, dir)));
24993
+ const present = HARNESS_SKILL_DIRS.filter((dir) => fs27.existsSync(path34.join(root, dir)));
23653
24994
  const targets = present.length > 0 ? present : HARNESS_SKILL_DIRS;
23654
24995
  const fileCount = Object.keys(res.files).length;
23655
24996
  const relDirs = targets.map((harness) => {
23656
- const targetDir = path29.join(root, harness, "skills", name);
24997
+ const targetDir = path34.join(root, harness, "skills", name);
23657
24998
  writeFileMap(targetDir, res.files);
23658
- return `${path29.relative(root, targetDir)}/`;
24999
+ return `${path34.relative(root, targetDir)}/`;
23659
25000
  });
23660
25001
  console.log(`Installed skill "${name}" (${fileCount} file${fileCount === 1 ? "" : "s"}) \u2192 ${relDirs.join(", ")}`);
23661
25002
  console.log("Reload your agent (e.g. restart Claude Code) to pick up the skill.");
@@ -23766,13 +25107,18 @@ async function runSandboxExec(positional, flagArgs) {
23766
25107
  process.exit(data.exit_code);
23767
25108
  }
23768
25109
  }
23769
- function parseScopedTargetFlags(flagArgs, usage3) {
25110
+ function parseScopedTargetFlags(flagArgs, usage3, opts = {}) {
25111
+ const scopes = opts.scopes ?? ["all", "org", "hub"];
23770
25112
  let all = false;
23771
25113
  let orgId;
23772
25114
  let hubId;
23773
25115
  let dryRun = false;
23774
25116
  let yes = false;
23775
25117
  let jsonOutput = false;
25118
+ const rejectUnknown = (arg) => {
25119
+ console.error(`Unknown flag: ${arg}`);
25120
+ process.exit(1);
25121
+ };
23776
25122
  for (let i = 0; i < flagArgs.length; i++) {
23777
25123
  const arg = flagArgs[i];
23778
25124
  switch (arg) {
@@ -23792,20 +25138,23 @@ function parseScopedTargetFlags(flagArgs, usage3) {
23792
25138
  orgId = requireFlagValue(flagArgs, ++i, "--org");
23793
25139
  break;
23794
25140
  case "--hub":
25141
+ if (!scopes.includes("hub")) rejectUnknown(arg);
23795
25142
  hubId = requireFlagValue(flagArgs, ++i, "--hub");
23796
25143
  break;
23797
25144
  default:
23798
- console.error(`Unknown flag: ${arg}`);
23799
- process.exit(1);
25145
+ rejectUnknown(arg);
23800
25146
  }
23801
25147
  }
23802
25148
  if ((all ? 1 : 0) + (orgId ? 1 : 0) + (hubId ? 1 : 0) !== 1) {
23803
- console.error("Provide exactly ONE of --all, --org <org_id>, or --hub <hub_id>.");
25149
+ const forms = scopes.map((s) => s === "all" ? "--all" : s === "org" ? "--org <org_id>" : "--hub <hub_id>");
25150
+ const oneOf = forms.length === 2 ? forms.join(" or ") : `${forms.slice(0, -1).join(", ")}, or ${forms[forms.length - 1]}`;
25151
+ console.error(`Provide exactly ONE of ${oneOf}.`);
23804
25152
  console.error(usage3);
23805
25153
  process.exit(1);
23806
25154
  }
23807
25155
  if (all) {
23808
- return { body: { scope: "all", dry_run: dryRun }, targetLabel: "ALL hubs (platform-wide)", dryRun, yes, jsonOutput };
25156
+ const label = opts.allLabel ?? "ALL hubs (platform-wide)";
25157
+ return { body: { scope: "all", dry_run: dryRun }, targetLabel: label, dryRun, yes, jsonOutput };
23809
25158
  }
23810
25159
  if (orgId) {
23811
25160
  return { body: { scope: "org", org_id: orgId, dry_run: dryRun }, targetLabel: `org ${orgId}`, dryRun, yes, jsonOutput };
@@ -23859,6 +25208,59 @@ async function runRepairTeamOrphans(flagArgs) {
23859
25208
  console.log(`${d.hub_id} | ${d.dangling_team_ids.join(",")} | ${d.team_users_removed}`);
23860
25209
  }
23861
25210
  }
25211
+ async function runRepairLegacyOrgGrants(flagArgs) {
25212
+ const USAGE = "wayai admin orgs repair-legacy-grants --all | --org <org_id> [--dry-run] [--yes] [--json]";
25213
+ const scoped = parseScopedTargetFlags(flagArgs, USAGE, {
25214
+ scopes: ["all", "org"],
25215
+ allLabel: "ALL organizations (platform-wide)"
25216
+ });
25217
+ const { targetLabel, dryRun, yes, jsonOutput } = scoped;
25218
+ const body = scoped.body.scope === "org" ? { scope: "org", org_id: scoped.body.org_id, dry_run: dryRun } : { scope: "all", dry_run: dryRun };
25219
+ if (!dryRun && !yes && !jsonOutput) {
25220
+ console.log(`About to REPAIR legacy org-admin roster rows in: ${targetLabel}.`);
25221
+ console.log("A row whose email resolves to a real user BECOMES REAL ACCESS (OrgDO roster + UserDO membership);");
25222
+ console.log("a row whose email matches no account is deleted. Neither sends the user an email.");
25223
+ console.log("Run with --dry-run first to see what would change.");
25224
+ const ok = await confirm("Proceed?");
25225
+ if (!ok) {
25226
+ console.log("Aborted.");
25227
+ return;
25228
+ }
25229
+ }
25230
+ const { config, accessToken } = await requireAuth();
25231
+ const client = new ApiClient({ apiUrl: config.api_url, accessToken });
25232
+ let response;
25233
+ try {
25234
+ response = await client.adminRepairLegacyOrgGrants(body);
25235
+ } catch (err) {
25236
+ exitOnApiError(err);
25237
+ throw err;
25238
+ }
25239
+ const data = response.data;
25240
+ if (jsonOutput) {
25241
+ console.log(JSON.stringify(data, null, 2));
25242
+ return;
25243
+ }
25244
+ const mode = data.dry_run ? "DRY RUN \u2014 nothing written" : "repaired";
25245
+ console.log(
25246
+ `repair-legacy-grants (${data.scope}) \u2014 ${mode}: orgs_scanned=${data.orgs_scanned} rows_found=${data.rows_found} repaired=${data.rows_repaired} dropped=${data.rows_dropped} skipped=${data.rows_skipped}`
25247
+ );
25248
+ if (data.rows_errored > 0 || data.orgs_errored > 0) {
25249
+ console.log(
25250
+ `WARNING: ${data.orgs_errored} org(s) and ${data.rows_errored} row(s) errored and were SKIPPED \u2014 re-run to cover them.`
25251
+ );
25252
+ }
25253
+ if (data.details.length === 0) {
25254
+ console.log("(no legacy email-keyed roster rows in scope)");
25255
+ return;
25256
+ }
25257
+ console.log("");
25258
+ console.log("org_id | user_email | action | user_id | reason");
25259
+ console.log("-------+------------+--------+---------+-------");
25260
+ for (const d of data.details) {
25261
+ console.log(`${d.org_id} | ${d.user_email} | ${d.action} | ${d.user_id ?? "-"} | ${d.reason ?? "-"}`);
25262
+ }
25263
+ }
23862
25264
  async function runHarnessMassDestroy(flagArgs) {
23863
25265
  const USAGE = "wayai admin harness mass-destroy --all | --org <org_id> | --hub <hub_id> [--dry-run] [--yes] [--json]";
23864
25266
  const { body, targetLabel, dryRun, yes, jsonOutput } = parseScopedTargetFlags(flagArgs, USAGE);
@@ -24382,6 +25784,9 @@ Usage:
24382
25784
  wayai admin hubs repair-team-orphans --all | --org <org_id> | --hub <hub_id> [--dry-run] [--yes] [--json]
24383
25785
  Purge hub_team_id references left dangling by a pre-cascade team deletion (silently empties a support agent's queue). Idempotent \u2014 run --dry-run first
24384
25786
 
25787
+ wayai admin orgs repair-legacy-grants --all | --org <org_id> [--dry-run] [--yes] [--json]
25788
+ Repair org-admin roster rows keyed by email with a NULL user_email (pre-#3922 platform-admin adds): grant the real access they never conferred, or drop the phantom seat. Idempotent \u2014 run --dry-run first
25789
+
24385
25790
  wayai admin harness disable Flip the platform harness_enabled flag OFF (break-glass: blocks harness-agent writes and the per-turn kill switch aborts each harness turn on its next invocation)
24386
25791
  wayai admin harness enable Flip the platform harness_enabled flag ON
24387
25792
  wayai admin harness status Print the platform harness_enabled flag
@@ -24420,6 +25825,18 @@ Sources:
24420
25825
  its owner's Support list silently goes blank; a conversation pinned to a
24421
25826
  deleted team goes invisible to everyone. Idempotent \u2014 a healthy hub writes
24422
25827
  nothing, so re-running and --all are both safe.
25828
+ orgs Org roster repair. \`repair-legacy-grants\` fixes member_grant rows the
25829
+ platform-admin org-admin add wrote before #3922: the email landed in the
25830
+ user_id column with user_email NULL. Auth reads UserDO, never member_grant,
25831
+ so the row grants NOTHING \u2014 while still counting as a seat, which refuses
25832
+ the org's next legitimate admin add with SEAT_QUOTA_EXCEEDED. It cannot
25833
+ self-heal (resolveGrantByEmail matches on user_email, and NULL = 'x@y.com'
25834
+ is NULL). Each row is resolved to a real user and granted both halves of
25835
+ access, or dropped when no account matches. A repaired row is a REAL grant
25836
+ to a real person and sends no email, so read --dry-run output as the list of
25837
+ people about to get access. Idempotent. See
25838
+ docs/runbooks/legacy-org-grant-repair.md.
25839
+
24423
25840
  sandbox Run arbitrary code in a fresh E2B sandbox (harness-agents isolation surface).
24424
25841
  \`exec\` provisions a sandbox from a named Sandbox connection, runs one
24425
25842
  command, and destroys it. Egress omitted \u21D2 deny-all (fail-closed); opt up
@@ -24456,6 +25873,8 @@ Examples:
24456
25873
  wayai admin observability <hub-id> <conv-id> --message-id <msg-id> --json
24457
25874
  wayai admin sandbox exec "echo hi" --hub <hub-id> --connection <conn-id>
24458
25875
  wayai admin sandbox exec --cmd "curl -s https://api.github.com" --hub <hub-id> --connection <conn-id> --egress allowlist --allow api.github.com
25876
+ wayai admin orgs repair-legacy-grants --all --dry-run
25877
+ wayai admin orgs repair-legacy-grants --org <org-id> --yes
24459
25878
  wayai admin harness disable
24460
25879
  wayai admin harness mass-destroy --all --dry-run
24461
25880
  wayai admin harness mass-destroy --hub <hub-id> --yes
@@ -24480,24 +25899,9 @@ var init_admin = __esm({
24480
25899
  init_skill_version();
24481
25900
  init_file_map();
24482
25901
  init_contracts();
24483
- VALID_TYPES = dataExplorerDebugDoType.options;
24484
- VALID_ANALYTICS_TABLES = dataExplorerDebugAnalyticsTable.options;
24485
- VALID_NOTICE_SEVERITIES = ["critical", "warn", "info"];
24486
- }
24487
- });
24488
-
24489
- // src/lib/terminal-output.ts
24490
- import { stripVTControlCharacters } from "util";
24491
- function sanitizeTerminalText(value) {
24492
- const normalizedNewlines = value.replace(/\r\n?/g, "\n");
24493
- return stripVTControlCharacters(normalizedNewlines).replace(
24494
- /[\u0000-\u0009\u000b-\u001f\u007f-\u009f]/g,
24495
- ""
24496
- );
24497
- }
24498
- var init_terminal_output = __esm({
24499
- "src/lib/terminal-output.ts"() {
24500
- "use strict";
25902
+ VALID_TYPES = dataExplorerDebugDoType.options;
25903
+ VALID_ANALYTICS_TABLES = dataExplorerDebugAnalyticsTable.options;
25904
+ VALID_NOTICE_SEVERITIES = ["critical", "warn", "info"];
24501
25905
  }
24502
25906
  });
24503
25907
 
@@ -24963,91 +26367,6 @@ var init_update = __esm({
24963
26367
  }
24964
26368
  });
24965
26369
 
24966
- // src/data/org-context.ts
24967
- function setDataOrgOverride(orgId) {
24968
- override = orgId;
24969
- }
24970
- function getDataOrgOverride() {
24971
- return override;
24972
- }
24973
- var override;
24974
- var init_org_context = __esm({
24975
- "src/data/org-context.ts"() {
24976
- "use strict";
24977
- }
24978
- });
24979
-
24980
- // src/data/client.ts
24981
- async function createDataClient(orgId) {
24982
- const { config, accessToken } = await requireAuth();
24983
- const api = new ApiClient({ apiUrl: config.api_url, accessToken });
24984
- const selected = orgId ?? getDataOrgOverride();
24985
- if (selected !== void 0 && !UUID_RE2.test(selected)) {
24986
- throw expected(`Invalid --org: ${JSON.stringify(selected)}. Expected an organization UUID.`);
24987
- }
24988
- const org = selected ?? readRepoConfig()?.organization_id;
24989
- return {
24990
- async request(method, path31, body) {
24991
- const envelope = await api.dataRequest(method, path31, body, org);
24992
- return envelope.data;
24993
- },
24994
- async collectPages(makePath) {
24995
- const all = [];
24996
- const seen = /* @__PURE__ */ new Set();
24997
- let cursor;
24998
- for (let page = 0; page < MAX_PAGES; page++) {
24999
- const { data, meta } = await api.dataRequest("GET", makePath(cursor), void 0, org);
25000
- for (const row of data ?? []) all.push(row);
25001
- cursor = meta?.has_more ? meta.cursor : void 0;
25002
- if (cursor === void 0) break;
25003
- if (seen.has(cursor)) break;
25004
- seen.add(cursor);
25005
- }
25006
- return all;
25007
- },
25008
- async upload(v1Path, bytes, contentType, headers) {
25009
- const envelope = await api.dataUpload(v1Path, bytes, contentType, org, headers);
25010
- return envelope.data;
25011
- },
25012
- download(v1Path) {
25013
- return api.dataDownload(v1Path, org);
25014
- },
25015
- url(v1Path) {
25016
- return api.dataUrl(v1Path, org);
25017
- }
25018
- };
25019
- }
25020
- function dataErrorEnvelope(err) {
25021
- if (!(err instanceof ApiError)) return null;
25022
- try {
25023
- const parsed = JSON.parse(err.body);
25024
- return parsed?.error ?? null;
25025
- } catch {
25026
- return null;
25027
- }
25028
- }
25029
- function dataErrorCode(err) {
25030
- const code = dataErrorEnvelope(err)?.code;
25031
- return typeof code === "string" && code ? code : null;
25032
- }
25033
- function dataErrorDetails(err) {
25034
- const details = dataErrorEnvelope(err)?.details;
25035
- return details && typeof details === "object" ? details : void 0;
25036
- }
25037
- var MAX_PAGES;
25038
- var init_client = __esm({
25039
- "src/data/client.ts"() {
25040
- "use strict";
25041
- init_auth();
25042
- init_api_client();
25043
- init_repo_config();
25044
- init_utils();
25045
- init_expected();
25046
- init_org_context();
25047
- MAX_PAGES = 1e3;
25048
- }
25049
- });
25050
-
25051
26370
  // src/data/output.ts
25052
26371
  function printOutput(data, format) {
25053
26372
  if (format === "json") {
@@ -25148,140 +26467,6 @@ var init_output = __esm({
25148
26467
  }
25149
26468
  });
25150
26469
 
25151
- // src/lib/base-id.ts
25152
- function isValidBaseId(id) {
25153
- return BASE_ID_RE.test(id);
25154
- }
25155
- var BASE_ID_RE;
25156
- var init_base_id = __esm({
25157
- "src/lib/base-id.ts"() {
25158
- "use strict";
25159
- BASE_ID_RE = /^(?!\.\.?$)[A-Za-z0-9._-]{1,256}$/;
25160
- }
25161
- });
25162
-
25163
- // src/data/helpers.ts
25164
- import { readFileSync as readFileSync19 } from "fs";
25165
- function pathSegment(id, label = "id") {
25166
- if (!isValidBaseId(id)) {
25167
- throw expected(
25168
- `Invalid ${label}: ${JSON.stringify(id)}. Ids are slugs \u2014 letters, digits, dot, dash and underscore only.`
25169
- );
25170
- }
25171
- return encodeURIComponent(id);
25172
- }
25173
- function foreignSegment(value, label = "id") {
25174
- if (value === "." || value === "..") {
25175
- throw expected(`Invalid ${label}: ${JSON.stringify(value)} is a path traversal segment.`);
25176
- }
25177
- return encodeURIComponent(value);
25178
- }
25179
- function pathSegments(value, label = "path") {
25180
- return value.split("/").map((segment) => foreignSegment(segment, label)).join("/");
25181
- }
25182
- function parseData(data, flag) {
25183
- const prefix = flag ? `${flag}: ` : "";
25184
- const source = data.startsWith("@") ? data.slice(1) : void 0;
25185
- let text = data;
25186
- if (source !== void 0) {
25187
- try {
25188
- text = readFileSync19(source, "utf-8");
25189
- } catch (e) {
25190
- throw expected(`${prefix}${source}: ${e instanceof Error ? e.message : "could not be read"}`);
25191
- }
25192
- }
25193
- try {
25194
- return JSON.parse(text);
25195
- } catch (e) {
25196
- const where = source !== void 0 ? ` in ${source}` : "";
25197
- throw expected(`${prefix}invalid JSON${where}: ${e instanceof Error ? e.message : String(e)}`);
25198
- }
25199
- }
25200
- function toolsetMcpUrl(slug) {
25201
- return `https://data-mcp.wayai.pro/t/${slug}/mcp`;
25202
- }
25203
- function globals(cmd) {
25204
- let namespace = cmd;
25205
- while (namespace.parent?.parent) namespace = namespace.parent;
25206
- return namespace.opts();
25207
- }
25208
- function withBaseOption(command2) {
25209
- return command2.option("--base <id>", "Base id (or set WAYAI_BASE)");
25210
- }
25211
- function baseOptionHolder(cmd) {
25212
- for (let c = cmd; c; c = c.parent ?? void 0) {
25213
- if (c.options.some((o) => o.long === "--base")) return c;
25214
- }
25215
- return void 0;
25216
- }
25217
- function findBase(cmd) {
25218
- return baseOptionHolder(cmd)?.opts()?.base;
25219
- }
25220
- function requireBase(cmd) {
25221
- const base = findBase(cmd) ?? process.env.WAYAI_BASE ?? "";
25222
- if (base) return base;
25223
- console.error("Error: --base is required (or set WAYAI_BASE)");
25224
- return process.exit(1);
25225
- }
25226
- function outputFormat(cmd) {
25227
- const opts = globals(cmd);
25228
- return opts.json || opts.output === "json" ? "json" : "table";
25229
- }
25230
- function historyQuery(opts) {
25231
- const qs = new URLSearchParams();
25232
- if (opts.limit) qs.set("limit", opts.limit);
25233
- if (opts.offset) qs.set("offset", opts.offset);
25234
- if (opts.diff) qs.set("diff", "true");
25235
- const q = qs.toString();
25236
- return q ? `?${q}` : "";
25237
- }
25238
- function splitList(value) {
25239
- return value.split(",").map((v) => v.trim()).filter((v) => v.length > 0);
25240
- }
25241
- function parseByteCount(flag, value) {
25242
- const n = Number(value);
25243
- if (!Number.isInteger(n) || n < 0) {
25244
- throw expected(`${flag} must be a whole number of bytes (0 = unlimited), not ${JSON.stringify(value)}.`);
25245
- }
25246
- return n;
25247
- }
25248
- async function readSecret(source, label) {
25249
- const value = resolveSecretSource(source) === "stdin" ? (await readStdin()).trim() : (await promptSecret(`${label}: `)).trim();
25250
- if (!value) throw expected(`${label} is required.`);
25251
- return value;
25252
- }
25253
- function isInteractive() {
25254
- return Boolean(process.stdin.isTTY && process.stdout.isTTY);
25255
- }
25256
- function parseDuration(input, flag = "duration") {
25257
- const match = DURATION_RE.exec(input.trim());
25258
- const value = Number(match?.[1] ?? 0);
25259
- const unit = match?.[2];
25260
- const unitMs = unit ? DURATION_UNIT_MS[unit] : void 0;
25261
- if (!unitMs || value <= 0) {
25262
- throw expected(
25263
- `Invalid ${flag} ${JSON.stringify(input)} \u2014 use <number><unit> with unit s/m/h/d (e.g. 10m, 2h, 30d).`
25264
- );
25265
- }
25266
- return value * unitMs;
25267
- }
25268
- var DURATION_RE, DURATION_UNIT_MS;
25269
- var init_helpers = __esm({
25270
- "src/data/helpers.ts"() {
25271
- "use strict";
25272
- init_base_id();
25273
- init_expected();
25274
- init_utils();
25275
- DURATION_RE = /^(\d+)([smhd])$/;
25276
- DURATION_UNIT_MS = {
25277
- s: 1e3,
25278
- m: 6e4,
25279
- h: 36e5,
25280
- d: 864e5
25281
- };
25282
- }
25283
- });
25284
-
25285
26470
  // src/data/commands/actions.ts
25286
26471
  import { Command } from "commander";
25287
26472
  function buildActionsCommand() {
@@ -25355,7 +26540,7 @@ var init_actions = __esm({
25355
26540
 
25356
26541
  // src/data/commands/attachments.ts
25357
26542
  import { Command as Command2 } from "commander";
25358
- import { readFileSync as readFileSync20 } from "fs";
26543
+ import { readFileSync as readFileSync21 } from "fs";
25359
26544
  function findAttachmentByFilename(attachments, filename) {
25360
26545
  return attachments.find((a) => a.key.endsWith(`/${filename}`)) ?? null;
25361
26546
  }
@@ -25396,7 +26581,7 @@ function buildAttachmentsCommand() {
25396
26581
  printOutput(data, outputFormat(this));
25397
26582
  return;
25398
26583
  }
25399
- const body = readFileSync20(opts.file);
26584
+ const body = readFileSync21(opts.file);
25400
26585
  await client.upload(uploadPathFrom(data?.upload_url), body, opts.contentType);
25401
26586
  printOutput({ ...data, uploaded: true }, outputFormat(this));
25402
26587
  });
@@ -25876,16 +27061,16 @@ var init_providers = __esm({
25876
27061
 
25877
27062
  // src/data/commands/report.ts
25878
27063
  import { Command as Command6 } from "commander";
25879
- import { readFileSync as readFileSync21 } from "fs";
25880
- import { dirname as dirname9, join as join27 } from "path";
27064
+ import { readFileSync as readFileSync22 } from "fs";
27065
+ import { dirname as dirname11, join as join32 } from "path";
25881
27066
  import { fileURLToPath as fileURLToPath2 } from "url";
25882
27067
  function resolveCliVersion() {
25883
27068
  for (const candidate of [
25884
- join27(here, "..", "package.json"),
25885
- join27(here, "..", "..", "..", "package.json")
27069
+ join32(here, "..", "package.json"),
27070
+ join32(here, "..", "..", "..", "package.json")
25886
27071
  ]) {
25887
27072
  try {
25888
- const version = JSON.parse(readFileSync21(candidate, "utf-8")).version;
27073
+ const version = JSON.parse(readFileSync22(candidate, "utf-8")).version;
25889
27074
  if (typeof version === "string" && version) return version;
25890
27075
  } catch {
25891
27076
  }
@@ -26081,13 +27266,13 @@ var init_report2 = __esm({
26081
27266
  init_terminal_output();
26082
27267
  init_workspace();
26083
27268
  init_skill_version();
26084
- here = dirname9(fileURLToPath2(import.meta.url));
27269
+ here = dirname11(fileURLToPath2(import.meta.url));
26085
27270
  }
26086
27271
  });
26087
27272
 
26088
27273
  // src/data/commands/secrets.ts
26089
27274
  import { Command as Command7 } from "commander";
26090
- import { readFileSync as readFileSync22 } from "fs";
27275
+ import { readFileSync as readFileSync23 } from "fs";
26091
27276
  function withValueSourceOptions(cmd, what) {
26092
27277
  return cmd.option(
26093
27278
  "--file <path>",
@@ -26100,7 +27285,7 @@ async function resolveValue(opts, label) {
26100
27285
  throw expected("--file cannot be combined with --value-stdin or --value-prompt \u2014 pass one.");
26101
27286
  }
26102
27287
  try {
26103
- return readFileSync22(opts.file).toString("base64");
27288
+ return readFileSync23(opts.file).toString("base64");
26104
27289
  } catch (e) {
26105
27290
  throw expected(`--file ${opts.file}: ${e instanceof Error ? e.message : "could not be read"}`);
26106
27291
  }
@@ -26197,7 +27382,7 @@ var init_secrets = __esm({
26197
27382
 
26198
27383
  // src/data/commands/sql.ts
26199
27384
  import { Command as Command8 } from "commander";
26200
- import { readFileSync as readFileSync23 } from "fs";
27385
+ import { readFileSync as readFileSync24 } from "fs";
26201
27386
  function buildBasesSqlCommand() {
26202
27387
  return withBaseOption(new Command8("sql")).description("Execute a read-only SQL query against base data").argument("[query]", "SQL query (SELECT only)").option("--file <path>", "Read SQL from a file instead of the argument").option(
26203
27388
  "--param <kv...>",
@@ -26207,7 +27392,7 @@ function buildBasesSqlCommand() {
26207
27392
  let query;
26208
27393
  if (opts.file) {
26209
27394
  try {
26210
- query = readFileSync23(opts.file, "utf-8").trim();
27395
+ query = readFileSync24(opts.file, "utf-8").trim();
26211
27396
  } catch (e) {
26212
27397
  throw expected(`--file ${opts.file}: ${e instanceof Error ? e.message : "could not be read"}`);
26213
27398
  }
@@ -26342,16 +27527,16 @@ MCP URL: ${toolsetMcpUrl(slug)}`);
26342
27527
  ).option("--force", "Revoke even if the token appears to be in live use").action(async function(tokenId, opts) {
26343
27528
  const client = await createDataClient();
26344
27529
  const id = pathSegment(tokenId, "token id");
26345
- const path31 = (force) => `/v1/tokens/${id}${force ? "?force=true" : ""}`;
27530
+ const path36 = (force) => `/v1/tokens/${id}${force ? "?force=true" : ""}`;
26346
27531
  const format = outputFormat(this);
26347
27532
  const revoked = (forced) => printOutput({ token_id: tokenId, revoked: true, forced }, format);
26348
27533
  if (opts.force) {
26349
- await client.request("DELETE", path31(true));
27534
+ await client.request("DELETE", path36(true));
26350
27535
  revoked(true);
26351
27536
  return;
26352
27537
  }
26353
27538
  try {
26354
- await client.request("DELETE", path31(false));
27539
+ await client.request("DELETE", path36(false));
26355
27540
  revoked(false);
26356
27541
  } catch (err) {
26357
27542
  if (!(err instanceof ApiError) || err.status !== 409 || dataErrorDetails(err)?.requires_force !== true) {
@@ -26366,7 +27551,7 @@ MCP URL: ${toolsetMcpUrl(slug)}`);
26366
27551
  console.error("Aborted.");
26367
27552
  return process.exit(1);
26368
27553
  }
26369
- await client.request("DELETE", path31(true));
27554
+ await client.request("DELETE", path36(true));
26370
27555
  revoked(true);
26371
27556
  }
26372
27557
  });
@@ -26485,39 +27670,12 @@ Output:
26485
27670
  }
26486
27671
  });
26487
27672
 
26488
- // src/lib/base-binding.ts
26489
- var binding2, getBaseBindingPath, readBaseBinding, writeBaseBinding, clearBaseBinding, autoBindBaseIfUnbound, assertBaseMatchesBinding, assertNoBindingBlocksBaseCreation;
26490
- var init_base_binding = __esm({
26491
- "src/lib/base-binding.ts"() {
26492
- "use strict";
26493
- init_base_id();
26494
- init_worktree_binding();
26495
- binding2 = createWorktreeBinding({
26496
- filename: "wayai-base-binding",
26497
- isValidId: isValidBaseId,
26498
- noun: "base",
26499
- idLabel: "base id (must be a slug)",
26500
- unbindCommand: "wayai bases unbind",
26501
- useCommand: "wayai bases use"
26502
- });
26503
- getBaseBindingPath = binding2.getBindingPath;
26504
- readBaseBinding = binding2.readBinding;
26505
- writeBaseBinding = binding2.writeBinding;
26506
- clearBaseBinding = binding2.clearBinding;
26507
- autoBindBaseIfUnbound = binding2.autoBindIfUnbound;
26508
- assertBaseMatchesBinding = binding2.assertMatchesBinding;
26509
- assertNoBindingBlocksBaseCreation = binding2.assertNoBindingBlocksCreation;
26510
- }
26511
- });
26512
-
26513
27673
  // src/data/commands/bases.ts
26514
27674
  import { Command as Command10 } from "commander";
26515
- import * as fs24 from "fs";
26516
- import * as path30 from "path";
26517
- import * as yaml9 from "js-yaml";
26518
- function pageOf(path31, cursor) {
26519
- if (!cursor) return path31;
26520
- return `${path31}${path31.includes("?") ? "&" : "?"}cursor=${encodeURIComponent(cursor)}`;
27675
+ import * as path35 from "path";
27676
+ function pageOf(path36, cursor) {
27677
+ if (!cursor) return path36;
27678
+ return `${path36}${path36.includes("?") ? "&" : "?"}cursor=${encodeURIComponent(cursor)}`;
26521
27679
  }
26522
27680
  function parseEnum(flag, value, allowed) {
26523
27681
  if (value === void 0) return void 0;
@@ -26658,9 +27816,9 @@ function buildBasesCommand() {
26658
27816
  });
26659
27817
  bases.command("list-previews <origin-id>").description("List preview bases cloned from a base (production or preview)").action(async function(originId) {
26660
27818
  const client = await createDataClient();
26661
- const path31 = `/v1/${pathSegment(originId, "origin base id")}/previews`;
27819
+ const path36 = `/v1/${pathSegment(originId, "origin base id")}/previews`;
26662
27820
  printOutput(
26663
- await client.collectPages((cursor) => pageOf(path31, cursor)),
27821
+ await client.collectPages((cursor) => pageOf(path36, cursor)),
26664
27822
  outputFormat(this)
26665
27823
  );
26666
27824
  });
@@ -26693,9 +27851,9 @@ function buildBasesCommand() {
26693
27851
  });
26694
27852
  bases.command("promotions <production-id>").description("List promotion history for a production base").action(async function(productionId) {
26695
27853
  const client = await createDataClient();
26696
- const path31 = `/v1/${pathSegment(productionId, "production base id")}/promotions`;
27854
+ const path36 = `/v1/${pathSegment(productionId, "production base id")}/promotions`;
26697
27855
  printOutput(
26698
- await client.collectPages((cursor) => pageOf(path31, cursor)),
27856
+ await client.collectPages((cursor) => pageOf(path36, cursor)),
26699
27857
  outputFormat(this)
26700
27858
  );
26701
27859
  });
@@ -26745,19 +27903,11 @@ function buildBasesCommand() {
26745
27903
  }
26746
27904
  function resolveSelectorToBaseId(selector) {
26747
27905
  const gitRoot = findGitRoot();
26748
- if (!gitRoot || selector.includes("/") || selector.includes(path30.sep)) return selector;
27906
+ if (!gitRoot || selector.includes("/") || selector.includes(path35.sep)) return selector;
26749
27907
  if (!isValidBaseId(selector)) return selector;
26750
- const metaPath = path30.join(resolveBasesDir(gitRoot), selector, BASE_META_FILE);
26751
- let meta;
26752
- try {
26753
- meta = yaml9.load(fs24.readFileSync(metaPath, "utf-8"));
26754
- } catch {
26755
- return selector;
26756
- }
26757
- const id = meta?.[BASE_ID_FIELD];
27908
+ const id = readBaseMeta(path35.join(resolveBasesDir(gitRoot), selector))?.base_id;
26758
27909
  return typeof id === "string" && isValidBaseId(id) ? id : selector;
26759
27910
  }
26760
- var BASE_META_FILE, BASE_ID_FIELD;
26761
27911
  var init_bases = __esm({
26762
27912
  "src/data/commands/bases.ts"() {
26763
27913
  "use strict";
@@ -26775,11 +27925,10 @@ var init_bases = __esm({
26775
27925
  init_terminal_output();
26776
27926
  init_workspace();
26777
27927
  init_layout();
27928
+ init_base_workspace();
26778
27929
  init_base_binding();
26779
27930
  init_base_id();
26780
27931
  init_expected();
26781
- BASE_META_FILE = "base.yaml";
26782
- BASE_ID_FIELD = "base_id";
26783
27932
  }
26784
27933
  });
26785
27934
 
@@ -26844,7 +27993,7 @@ var init_file_types = __esm({
26844
27993
  // src/data/commands/files.ts
26845
27994
  import { Command as Command12 } from "commander";
26846
27995
  import { readFileSync as readFileSync25, writeFileSync as writeFileSync16 } from "fs";
26847
- import { basename as basename14 } from "path";
27996
+ import { basename as basename18 } from "path";
26848
27997
  function renderFileDiff(fileType, filePath, from, to, d) {
26849
27998
  console.log(sanitizeTerminalText(`${fileType}/${filePath}: v${from} \u2192 v${to}`));
26850
27999
  const md = d.metadata_delta;
@@ -26876,7 +28025,7 @@ function renderFileDiff(fileType, filePath, from, to, d) {
26876
28025
  }
26877
28026
  function downloadTarget(remotePath, to) {
26878
28027
  if (to) return to;
26879
- const derived = basename14(remotePath);
28028
+ const derived = basename18(remotePath);
26880
28029
  if (derived === "" || derived === "." || derived === "..") {
26881
28030
  throw expected(
26882
28031
  `Cannot derive a local filename from "${remotePath}" \u2014 pass --to <local> to name it.`
@@ -27252,8 +28401,8 @@ function buildRecordsCommand() {
27252
28401
  const body = { data: parseData(opts.data) };
27253
28402
  if (opts.externalId) body.external_id = opts.externalId;
27254
28403
  if (opts.externalSource) body.external_source = opts.externalSource;
27255
- const path31 = opts.id ? `/v1/${base}/records/${pathSegment(recordType2, "record_type")}/${pathSegment(opts.id, "--id")}` : `/v1/${base}/records/${pathSegment(recordType2, "record_type")}`;
27256
- printOutput(await client.request("PUT", path31, body), outputFormat(this));
28404
+ const path36 = opts.id ? `/v1/${base}/records/${pathSegment(recordType2, "record_type")}/${pathSegment(opts.id, "--id")}` : `/v1/${base}/records/${pathSegment(recordType2, "record_type")}`;
28405
+ printOutput(await client.request("PUT", path36, body), outputFormat(this));
27257
28406
  });
27258
28407
  records.command("query <record_type>").description("List/search records: exact filters + fuzzy `search`, sorting, pagination").option(
27259
28408
  "--external-source <source>",
@@ -27288,9 +28437,9 @@ function buildRecordsCommand() {
27288
28437
  ).action(async function(recordType2, id, opts) {
27289
28438
  const base = pathSegment(requireBase(this), "--base");
27290
28439
  const client = await createDataClient();
27291
- let path31 = `/v1/${base}/records/${pathSegment(recordType2, "record_type")}/${recordKey(id, opts.externalSource)}`;
27292
- if (opts.externalSource) path31 += `?external_source=${encodeURIComponent(opts.externalSource)}`;
27293
- printOutput(await client.request("GET", path31), outputFormat(this));
28440
+ let path36 = `/v1/${base}/records/${pathSegment(recordType2, "record_type")}/${recordKey(id, opts.externalSource)}`;
28441
+ if (opts.externalSource) path36 += `?external_source=${encodeURIComponent(opts.externalSource)}`;
28442
+ printOutput(await client.request("GET", path36), outputFormat(this));
27294
28443
  });
27295
28444
  records.command("delete <record_type> <id>").description(
27296
28445
  "Delete a record by internal ID, or by external_id (pass --external-source to scope it)"
@@ -27304,11 +28453,11 @@ function buildRecordsCommand() {
27304
28453
  }
27305
28454
  const base = pathSegment(requireBase(this), "--base");
27306
28455
  const client = await createDataClient();
27307
- let path31 = `/v1/${base}/records/${pathSegment(recordType2, "record_type")}/${recordKey(id, opts.externalSource)}`;
28456
+ let path36 = `/v1/${base}/records/${pathSegment(recordType2, "record_type")}/${recordKey(id, opts.externalSource)}`;
27308
28457
  if (opts.externalSource) {
27309
- path31 += `?external_source=${encodeURIComponent(opts.externalSource)}&external_id=${encodeURIComponent(id)}`;
28458
+ path36 += `?external_source=${encodeURIComponent(opts.externalSource)}&external_id=${encodeURIComponent(id)}`;
27310
28459
  }
27311
- await client.request("DELETE", path31);
28460
+ await client.request("DELETE", path36);
27312
28461
  console.log("Deleted");
27313
28462
  });
27314
28463
  records.command("history <id>").description(
@@ -27473,8 +28622,8 @@ function buildRelationshipsCommand() {
27473
28622
  if (opts.data) body.data = parseData(opts.data);
27474
28623
  const base = pathSegment(requireBase(this), "--base");
27475
28624
  const client = await createDataClient();
27476
- const path31 = opts.id ? `/v1/${base}/relationships/${pathSegment(opts.id, "--id")}` : `/v1/${base}/relationships`;
27477
- printOutput(await client.request("PUT", path31, body), outputFormat(this));
28625
+ const path36 = opts.id ? `/v1/${base}/relationships/${pathSegment(opts.id, "--id")}` : `/v1/${base}/relationships`;
28626
+ printOutput(await client.request("PUT", path36, body), outputFormat(this));
27478
28627
  });
27479
28628
  relationships.command("get <id>").description(
27480
28629
  "Get a relationship by ID (or by its external key: pass the external_id with --rel-type)"
@@ -27707,8 +28856,8 @@ function buildToolsetsCommand() {
27707
28856
  toolsets.command("get <slug>").description("Get a toolset").option("--resolved", "Include resolved record_type schemas").action(async function(slug, opts) {
27708
28857
  const base = pathSegment(requireBase(this), "--base");
27709
28858
  const client = await createDataClient();
27710
- const path31 = opts.resolved ? `/v1/${base}/toolsets/${pathSegment(slug, "toolset slug")}/resolved` : `/v1/${base}/toolsets/${pathSegment(slug, "toolset slug")}`;
27711
- printOutput(await client.request("GET", path31), outputFormat(this));
28859
+ const path36 = opts.resolved ? `/v1/${base}/toolsets/${pathSegment(slug, "toolset slug")}/resolved` : `/v1/${base}/toolsets/${pathSegment(slug, "toolset slug")}`;
28860
+ printOutput(await client.request("GET", path36), outputFormat(this));
27712
28861
  });
27713
28862
  toolsets.command("list").description("List all toolsets").action(async function() {
27714
28863
  const base = pathSegment(requireBase(this), "--base");
@@ -27943,7 +29092,7 @@ init_utils();
27943
29092
  init_registry();
27944
29093
  import { readFileSync as readFileSync26 } from "fs";
27945
29094
  import { fileURLToPath as fileURLToPath3 } from "url";
27946
- import { dirname as dirname10, join as join29 } from "path";
29095
+ import { dirname as dirname12, join as join34 } from "path";
27947
29096
 
27948
29097
  // src/lib/version-refresh.ts
27949
29098
  init_version_cache();
@@ -27951,7 +29100,7 @@ init_skill_version();
27951
29100
  import { exec } from "child_process";
27952
29101
  var REFRESH_TIMEOUT_MS = 1e4;
27953
29102
  function refreshCliCache() {
27954
- return new Promise((resolve5) => {
29103
+ return new Promise((resolve7) => {
27955
29104
  exec("npm view @wayai/cli version", { timeout: REFRESH_TIMEOUT_MS }, (err, stdout) => {
27956
29105
  if (!err) {
27957
29106
  const latest = stdout.trim();
@@ -27962,7 +29111,7 @@ function refreshCliCache() {
27962
29111
  }
27963
29112
  }
27964
29113
  }
27965
- resolve5();
29114
+ resolve7();
27966
29115
  });
27967
29116
  });
27968
29117
  }
@@ -27988,8 +29137,8 @@ async function refreshSkillCache() {
27988
29137
  }
27989
29138
  async function refreshAdminSkillCache() {
27990
29139
  let timer;
27991
- const deadline = new Promise((resolve5) => {
27992
- timer = setTimeout(resolve5, REFRESH_TIMEOUT_MS);
29140
+ const deadline = new Promise((resolve7) => {
29141
+ timer = setTimeout(resolve7, REFRESH_TIMEOUT_MS);
27993
29142
  });
27994
29143
  await Promise.race([deadline, fetchAndCacheAdminSkillVersion().catch(() => {
27995
29144
  })]);
@@ -28098,8 +29247,8 @@ Run \`wayai admin skill install\` to update.`);
28098
29247
  }
28099
29248
 
28100
29249
  // src/index.ts
28101
- var __dirname = dirname10(fileURLToPath3(import.meta.url));
28102
- var pkg = JSON.parse(readFileSync26(join29(__dirname, "..", "package.json"), "utf-8"));
29250
+ var __dirname = dirname12(fileURLToPath3(import.meta.url));
29251
+ var pkg = JSON.parse(readFileSync26(join34(__dirname, "..", "package.json"), "utf-8"));
28103
29252
  var [, , command, ...args] = process.argv;
28104
29253
  var isBackgroundRefresh = command === REFRESH_COMMAND;
28105
29254
  if (!isBackgroundRefresh) initSentry(command, pkg.version);
@@ -28338,8 +29487,8 @@ Commands:
28338
29487
  create-credential Create an organization credential (API key, token, etc.)
28339
29488
  update-credential Update / rotate an organization credential (by name)
28340
29489
  set-connection-credential Set a connection's credential directly (org link or --field/--stdin), preview or production
28341
- pull Fetch hub config and write local files (also mirrors the linked production hub read-only)
28342
- push Parse local files, show diff, sync to preview (creates hub if new)
29490
+ pull Fetch config and write local files \u2014 \`hubs/<hub>\` or \`bases/<base>\` (also mirrors the linked production hub/base read-only)
29491
+ push Parse local files, show diff, sync to preview \u2014 \`hubs/<hub>\` or \`bases/<base>\` (creates the hub/base if new)
28343
29492
  create [folder] Explicitly create a new hub from an idless folder, then push (--label to name the preview)
28344
29493
  diff Dry-run diff of local files vs the platform (--production diffs vs the linked production hub)
28345
29494
  replicate Clone a hub into a new sibling preview (--label to name it)
@@ -28378,6 +29527,7 @@ ${await dataHelpBlock()}
28378
29527
  Flags:
28379
29528
  --yes, -y Skip confirmation prompts (useful for CI and scripting)
28380
29529
  --hub <uuid|name> Target hub when the workspace has more than one (push, pull, diff, replicate, relabel, publish)
29530
+ --base <id|name> Target base for pull/push \u2014 routes the invocation to the \`bases/\` subtree (never combined with --hub)
28381
29531
  --production Diff local preview files against the linked production hub (diff)
28382
29532
  --label <name> Preview label \u2014 for the new sibling (replicate) or a brand-new hub (create, or push on create)
28383
29533
  --clear Remove the preview label (relabel)