@wayai/cli 0.3.86 → 0.3.88

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -165,11 +165,11 @@ function captureException2(error, context) {
165
165
  Sentry.captureException(error);
166
166
  });
167
167
  }
168
- function addApiBreadcrumb(method, path25) {
168
+ function addApiBreadcrumb(method, path26) {
169
169
  if (!initialized) return;
170
170
  Sentry.addBreadcrumb({
171
171
  category: "http",
172
- message: `${method} ${path25}`,
172
+ message: `${method} ${path26}`,
173
173
  level: "info"
174
174
  });
175
175
  }
@@ -227,13 +227,13 @@ var init_api_client = __esm({
227
227
  init_sentry();
228
228
  init_redact();
229
229
  RETRYABLE_BACKOFF_MS = [500, 1e3, 2e3];
230
- delay = (ms) => new Promise((resolve5) => setTimeout(resolve5, ms));
230
+ delay = (ms) => new Promise((resolve4) => setTimeout(resolve4, ms));
231
231
  ApiError = class extends Error {
232
232
  status;
233
233
  body;
234
- constructor(method, path25, status, body) {
234
+ constructor(method, path26, status, body) {
235
235
  const safeBody = redactSecrets(body);
236
- super(`API request failed: ${method} ${path25} (${status}): ${safeBody}`);
236
+ super(`API request failed: ${method} ${path26} (${status}): ${safeBody}`);
237
237
  this.name = "ApiError";
238
238
  this.status = status;
239
239
  this.body = safeBody;
@@ -376,8 +376,8 @@ var init_api_client = __esm({
376
376
  ...organizationId && { organization_id: organizationId }
377
377
  });
378
378
  }
379
- async lookup(path25, opts) {
380
- const params = new URLSearchParams({ path: path25 });
379
+ async lookup(path26, opts) {
380
+ const params = new URLSearchParams({ path: path26 });
381
381
  if (opts?.organizationId) params.set("organization_id", opts.organizationId);
382
382
  return this.request("GET", `/api/ci/lookup?${params.toString()}`);
383
383
  }
@@ -765,9 +765,9 @@ var init_api_client = __esm({
765
765
  * sandbox for this conversation, or the blob was purged).
766
766
  */
767
767
  async downloadArchiveSandboxFs(hubId, conversationId) {
768
- const path25 = `/api/archive/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}/sandbox`;
769
- addApiBreadcrumb("GET", path25);
770
- const url = `${this.apiUrl}${path25}`;
768
+ const path26 = `/api/archive/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}/sandbox`;
769
+ addApiBreadcrumb("GET", path26);
770
+ const url = `${this.apiUrl}${path26}`;
771
771
  let response = await this.send(url, "GET");
772
772
  if (response.status === 401 && this.onUnauthorized) {
773
773
  let refreshed;
@@ -781,7 +781,7 @@ var init_api_client = __esm({
781
781
  }
782
782
  }
783
783
  if (!response.ok) {
784
- throw new ApiError("GET", path25, response.status, await response.text());
784
+ throw new ApiError("GET", path26, response.status, await response.text());
785
785
  }
786
786
  return new Uint8Array(await response.arrayBuffer());
787
787
  }
@@ -821,9 +821,9 @@ var init_api_client = __esm({
821
821
  `/api/admin/data-explorer/debug/observability/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}${qs}`
822
822
  );
823
823
  }
824
- async request(method, path25, body) {
825
- addApiBreadcrumb(method, path25);
826
- const url = `${this.apiUrl}${path25}`;
824
+ async request(method, path26, body) {
825
+ addApiBreadcrumb(method, path26);
826
+ const url = `${this.apiUrl}${path26}`;
827
827
  let refreshedOn401 = false;
828
828
  for (let retry = 0; ; retry++) {
829
829
  let response = await this.send(url, method, body);
@@ -847,7 +847,7 @@ var init_api_client = __esm({
847
847
  await delay(RETRYABLE_BACKOFF_MS[retry]);
848
848
  continue;
849
849
  }
850
- throw new ApiError(method, path25, response.status, errorBody);
850
+ throw new ApiError(method, path26, response.status, errorBody);
851
851
  }
852
852
  }
853
853
  /** Issue a single authenticated request with the client's current token. */
@@ -1282,8 +1282,8 @@ var init_parseUtil = __esm({
1282
1282
  init_errors();
1283
1283
  init_en();
1284
1284
  makeIssue = (params) => {
1285
- const { data, path: path25, errorMaps, issueData } = params;
1286
- const fullPath = [...path25, ...issueData.path || []];
1285
+ const { data, path: path26, errorMaps, issueData } = params;
1286
+ const fullPath = [...path26, ...issueData.path || []];
1287
1287
  const fullIssue = {
1288
1288
  ...issueData,
1289
1289
  path: fullPath
@@ -1594,11 +1594,11 @@ var init_types = __esm({
1594
1594
  init_parseUtil();
1595
1595
  init_util();
1596
1596
  ParseInputLazyPath = class {
1597
- constructor(parent, value, path25, key) {
1597
+ constructor(parent, value, path26, key) {
1598
1598
  this._cachedPath = [];
1599
1599
  this.parent = parent;
1600
1600
  this.data = value;
1601
- this._path = path25;
1601
+ this._path = path26;
1602
1602
  this._key = key;
1603
1603
  }
1604
1604
  get path() {
@@ -5052,12 +5052,12 @@ function typeMatches(typeField, allowed) {
5052
5052
  if (Array.isArray(typeField)) return typeField.every((t) => typeof t === "string" && allowed.has(t));
5053
5053
  return false;
5054
5054
  }
5055
- function validateSchema(schema, path25, errors, opts = {}) {
5055
+ function validateSchema(schema, path26, errors, opts = {}) {
5056
5056
  if (typeof schema === "boolean") return;
5057
5057
  const depth = opts.depth ?? 0;
5058
5058
  if (depth > MAX_SCHEMA_DEPTH) {
5059
5059
  errors.push({
5060
- path: path25 || "<root>",
5060
+ path: path26 || "<root>",
5061
5061
  message: `schema nesting exceeds ${MAX_SCHEMA_DEPTH} levels`,
5062
5062
  suggestion: "Flatten the schema; LLM providers reject deeply nested tool input_schemas."
5063
5063
  });
@@ -5065,7 +5065,7 @@ function validateSchema(schema, path25, errors, opts = {}) {
5065
5065
  }
5066
5066
  if (!isRecord(schema)) {
5067
5067
  errors.push({
5068
- path: path25,
5068
+ path: path26,
5069
5069
  message: `expected object, got ${schema === null ? "null" : typeof schema}`
5070
5070
  });
5071
5071
  return;
@@ -5073,14 +5073,14 @@ function validateSchema(schema, path25, errors, opts = {}) {
5073
5073
  if (opts.isRoot) {
5074
5074
  if ("type" in schema && schema.type !== "object") {
5075
5075
  errors.push({
5076
- path: path25 ? `${path25}.type` : "type",
5076
+ path: path26 ? `${path26}.type` : "type",
5077
5077
  message: `root type must be 'object', got ${JSON.stringify(schema.type)}`,
5078
5078
  suggestion: "Tool parameters at the root must be an object: `{ type: 'object', properties: { ... } }`."
5079
5079
  });
5080
5080
  }
5081
5081
  } else if ("type" in schema && !typeMatches(schema.type, ALLOWED_TYPES)) {
5082
5082
  errors.push({
5083
- path: `${path25}.type`,
5083
+ path: `${path26}.type`,
5084
5084
  message: `type must be one of ${[...ALLOWED_TYPES].join("/")} or an array of those, got ${JSON.stringify(schema.type)}`
5085
5085
  });
5086
5086
  }
@@ -5089,25 +5089,25 @@ function validateSchema(schema, path25, errors, opts = {}) {
5089
5089
  if (typeof e === "string") {
5090
5090
  const isPlaceholder = PLACEHOLDER_TOKENS.includes(e);
5091
5091
  errors.push({
5092
- path: `${path25}.enum`,
5092
+ path: `${path26}.enum`,
5093
5093
  message: `enum must be a non-empty array of primitives, got string ${JSON.stringify(e)}`,
5094
5094
  suggestion: isPlaceholder ? "Set `operation: 'update_kanban_status'` on the tool and ensure at least one hub.kanban_status has `allowsAgentUpdate: true` so the platform can render the placeholder into a valid array." : 'Wrap the value in an array: `enum: ["value"]`.'
5095
5095
  });
5096
5096
  } else if (!Array.isArray(e)) {
5097
5097
  errors.push({
5098
- path: `${path25}.enum`,
5098
+ path: `${path26}.enum`,
5099
5099
  message: `enum must be a non-empty array of primitives, got ${typeof e}`
5100
5100
  });
5101
5101
  } else if (e.length === 0) {
5102
5102
  errors.push({
5103
- path: `${path25}.enum`,
5103
+ path: `${path26}.enum`,
5104
5104
  message: "enum must not be empty"
5105
5105
  });
5106
5106
  } else {
5107
5107
  for (let i = 0; i < e.length; i++) {
5108
5108
  if (!isPrimitive(e[i])) {
5109
5109
  errors.push({
5110
- path: `${path25}.enum[${i}]`,
5110
+ path: `${path26}.enum[${i}]`,
5111
5111
  message: `enum entry must be a primitive (string/number/boolean/null), got ${typeof e[i]}`
5112
5112
  });
5113
5113
  }
@@ -5117,7 +5117,7 @@ function validateSchema(schema, path25, errors, opts = {}) {
5117
5117
  for (const key of ["exclusiveMinimum", "exclusiveMaximum"]) {
5118
5118
  if (key in schema && typeof schema[key] === "boolean") {
5119
5119
  errors.push({
5120
- path: `${path25}.${key}`,
5120
+ path: `${path26}.${key}`,
5121
5121
  message: `${key} as boolean is draft-04 syntax; draft 2020-12 requires a numeric value`,
5122
5122
  suggestion: `Replace with the numeric bound, e.g. \`${key}: 0\`.`
5123
5123
  });
@@ -5126,45 +5126,45 @@ function validateSchema(schema, path25, errors, opts = {}) {
5126
5126
  if ("properties" in schema) {
5127
5127
  if (!isRecord(schema.properties)) {
5128
5128
  errors.push({
5129
- path: `${path25}.properties`,
5129
+ path: `${path26}.properties`,
5130
5130
  message: `properties must be an object, got ${Array.isArray(schema.properties) ? "array" : typeof schema.properties}`
5131
5131
  });
5132
5132
  } else {
5133
5133
  for (const [propName, propSchema] of Object.entries(schema.properties)) {
5134
- validateSchema(propSchema, `${path25}.properties.${propName}`, errors, { depth: depth + 1 });
5134
+ validateSchema(propSchema, `${path26}.properties.${propName}`, errors, { depth: depth + 1 });
5135
5135
  }
5136
5136
  }
5137
5137
  }
5138
5138
  if (schemaTypeIncludes(schema, "array") && "items" in schema) {
5139
5139
  if (Array.isArray(schema.items)) {
5140
- schema.items.forEach((sub, i) => validateSchema(sub, `${path25}.items[${i}]`, errors, { depth: depth + 1 }));
5140
+ schema.items.forEach((sub, i) => validateSchema(sub, `${path26}.items[${i}]`, errors, { depth: depth + 1 }));
5141
5141
  } else {
5142
- validateSchema(schema.items, `${path25}.items`, errors, { depth: depth + 1 });
5142
+ validateSchema(schema.items, `${path26}.items`, errors, { depth: depth + 1 });
5143
5143
  }
5144
5144
  }
5145
5145
  for (const key of SUBSCHEMA_OBJECT_KEYWORDS) {
5146
5146
  if (key in schema && isRecord(schema[key])) {
5147
- validateSchema(schema[key], `${path25}.${key}`, errors, { depth: depth + 1 });
5147
+ validateSchema(schema[key], `${path26}.${key}`, errors, { depth: depth + 1 });
5148
5148
  }
5149
5149
  }
5150
5150
  for (const key of SUBSCHEMA_LIST_KEYWORDS) {
5151
5151
  const list = schema[key];
5152
5152
  if (Array.isArray(list)) {
5153
- list.forEach((sub, i) => validateSchema(sub, `${path25}.${key}[${i}]`, errors, { depth: depth + 1 }));
5153
+ list.forEach((sub, i) => validateSchema(sub, `${path26}.${key}[${i}]`, errors, { depth: depth + 1 }));
5154
5154
  }
5155
5155
  }
5156
5156
  for (const key of SUBSCHEMA_MAP_KEYWORDS) {
5157
5157
  const map = schema[key];
5158
5158
  if (isRecord(map)) {
5159
5159
  for (const [name, sub] of Object.entries(map)) {
5160
- validateSchema(sub, `${path25}.${key}.${name}`, errors, { depth: depth + 1 });
5160
+ validateSchema(sub, `${path26}.${key}.${name}`, errors, { depth: depth + 1 });
5161
5161
  }
5162
5162
  }
5163
5163
  }
5164
5164
  const reportedPaths = new Set(errors.map((e) => e.path));
5165
5165
  for (const [k, v] of Object.entries(schema)) {
5166
5166
  if (typeof v !== "string") continue;
5167
- const fieldPath = `${path25}.${k}`;
5167
+ const fieldPath = `${path26}.${k}`;
5168
5168
  if (reportedPaths.has(fieldPath)) continue;
5169
5169
  for (const token of PLACEHOLDER_TOKENS) {
5170
5170
  if (v === token) {
@@ -5320,10 +5320,10 @@ function refineHubAsCodeLanes(config, ctx) {
5320
5320
  }
5321
5321
  }
5322
5322
  }
5323
- function isSafeTemplatePath(path25) {
5324
- if (path25.length === 0 || path25.length > 300) return false;
5325
- if (path25.startsWith("/") || path25.includes("\\")) return false;
5326
- const segments = path25.split("/");
5323
+ function isSafeTemplatePath(path26) {
5324
+ if (path26.length === 0 || path26.length > 300) return false;
5325
+ if (path26.startsWith("/") || path26.includes("\\")) return false;
5326
+ const segments = path26.split("/");
5327
5327
  return segments.every(
5328
5328
  (seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
5329
5329
  );
@@ -5914,7 +5914,12 @@ var init_dist = __esm({
5914
5914
  // A NATIVE LLM (Agent) connection id on this hub; validated at set-time on the REST
5915
5915
  // PATCH (setup/hubs.ts rejects a non-existent / non-Agent / harness id) and re-checked
5916
5916
  // at fallback time in the turn seam (a stale/missing id simply no-ops). Nullable to clear it.
5917
- fallback_connection_id: uuidSchema.nullable().optional()
5917
+ fallback_connection_id: uuidSchema.nullable().optional(),
5918
+ // Rekor API connection used to reset/clear eval seed fixtures (gh #3090). A
5919
+ // connection id on this hub (a REST API (custom tool) connection whose base_url
5920
+ // is the Rekor API origin + a bearer/api_key `write:seeds` token). Validated at
5921
+ // set-time on the REST PATCH (setup/hubs.ts). Nullable to clear it.
5922
+ seed_connection_id: uuidSchema.nullable().optional()
5918
5923
  }).passthrough().superRefine(refineLaneReferences);
5919
5924
  addHubAdminBody = external_exports.object({
5920
5925
  user_email: external_exports.string().email("valid email is required")
@@ -7455,7 +7460,6 @@ var init_dist = __esm({
7455
7460
  dataExplorerDebugAnalyticsTable = external_exports.enum([
7456
7461
  "conversation",
7457
7462
  "message",
7458
- "billing_event",
7459
7463
  "schedule_event"
7460
7464
  ]);
7461
7465
  debugUuid = external_exports.string().uuid();
@@ -7637,7 +7641,7 @@ var init_dist = __esm({
7637
7641
  message: "at least one field must be provided"
7638
7642
  });
7639
7643
  contestReportBody = external_exports.object({
7640
- reason: external_exports.string().min(1).max(1e3)
7644
+ reason: external_exports.string().min(1).max(5e3)
7641
7645
  });
7642
7646
  reporterListQuery = external_exports.object({
7643
7647
  status: reportStatusSchema.optional()
@@ -7669,7 +7673,7 @@ var init_dist = __esm({
7669
7673
  }),
7670
7674
  external_exports.object({
7671
7675
  target: external_exports.literal("dismissed"),
7672
- dismissal_reason: external_exports.string().min(1).max(1e3),
7676
+ dismissal_reason: external_exports.string().min(1).max(5e3),
7673
7677
  ai_verdict: external_exports.string().max(2e3).optional(),
7674
7678
  final: external_exports.boolean().optional()
7675
7679
  })
@@ -7678,7 +7682,7 @@ var init_dist = __esm({
7678
7682
  member_ids: external_exports.array(external_exports.string().uuid()).min(1).max(100)
7679
7683
  });
7680
7684
  holdReportBody = external_exports.object({
7681
- reason: external_exports.string().min(1).max(1e3)
7685
+ reason: external_exports.string().min(1).max(5e3)
7682
7686
  });
7683
7687
  clickhouseReadyResponse = external_exports.object({
7684
7688
  ready: external_exports.boolean()
@@ -8125,6 +8129,7 @@ __export(workspace_exports, {
8125
8129
  detectWorkspace: () => detectWorkspace,
8126
8130
  filterPreviewHubs: () => filterPreviewHubs,
8127
8131
  findEnclosingHubFolder: () => findEnclosingHubFolder,
8132
+ findEnclosingNewHubFolder: () => findEnclosingNewHubFolder,
8128
8133
  findGitRoot: () => findGitRoot,
8129
8134
  findHubByFolderName: () => findHubByFolderName,
8130
8135
  findLocalHubFolder: () => findLocalHubFolder,
@@ -8137,6 +8142,8 @@ __export(workspace_exports, {
8137
8142
  resolveExplicitHubPath: () => resolveExplicitHubPath,
8138
8143
  resolveHubFolder: () => resolveHubFolder,
8139
8144
  resolveHubFolderBySelector: () => resolveHubFolderBySelector,
8145
+ resolveNewHubForCreate: () => resolveNewHubForCreate,
8146
+ resolvePushTarget: () => resolvePushTarget,
8140
8147
  resolveWorkspaceDir: () => resolveWorkspaceDir,
8141
8148
  scanNewHubs: () => scanNewHubs,
8142
8149
  scanWorkspaceHubs: () => scanWorkspaceHubs
@@ -8379,6 +8386,56 @@ function findEnclosingHubFolder(workspaceDir) {
8379
8386
  current = parent;
8380
8387
  }
8381
8388
  }
8389
+ function findEnclosingNewHubFolder(workspaceDir) {
8390
+ let current = process.cwd();
8391
+ const stop = path2.resolve(workspaceDir);
8392
+ while (true) {
8393
+ const meta = readNewHubYaml(path2.join(current, "hub.yaml")) || readNewHubYaml(path2.join(current, "wayai.yaml"));
8394
+ if (meta) {
8395
+ return { hubFolder: current, hubName: meta.hubName, hubType: meta.hubType };
8396
+ }
8397
+ if (current === stop) return null;
8398
+ const parent = path2.dirname(current);
8399
+ if (parent === current) return null;
8400
+ current = parent;
8401
+ }
8402
+ }
8403
+ function resolvePushTarget(workspaceDir, existingHubs, newHubs, selector) {
8404
+ if (selector) {
8405
+ const existingMatch = existingHubs.find(
8406
+ (h) => h.hubId === selector || path2.basename(h.hubFolder) === selector
8407
+ );
8408
+ if (existingMatch) return { ok: true, target: { kind: "existing", hub: existingMatch } };
8409
+ const newMatch = newHubs.find((h) => path2.basename(h.hubFolder) === selector);
8410
+ if (newMatch) return { ok: true, target: { kind: "new", hub: newMatch } };
8411
+ return { ok: false, reason: "selector_miss" };
8412
+ }
8413
+ const enclosingExisting = findEnclosingHubFolder(workspaceDir);
8414
+ if (enclosingExisting) return { ok: true, target: { kind: "existing", hub: enclosingExisting } };
8415
+ const enclosingNew = findEnclosingNewHubFolder(workspaceDir);
8416
+ if (enclosingNew) return { ok: true, target: { kind: "new", hub: enclosingNew } };
8417
+ const previewHubs = filterPreviewHubs(existingHubs);
8418
+ const total = previewHubs.length + newHubs.length;
8419
+ if (total === 0) return { ok: false, reason: "none" };
8420
+ if (total > 1) return { ok: false, reason: "ambiguous" };
8421
+ return previewHubs.length === 1 ? { ok: true, target: { kind: "existing", hub: previewHubs[0] } } : { ok: true, target: { kind: "new", hub: newHubs[0] } };
8422
+ }
8423
+ function resolveNewHubForCreate(workspaceDir, existingHubs, newHubs, selector) {
8424
+ if (selector) {
8425
+ const newMatch = newHubs.find((h) => path2.basename(h.hubFolder) === selector);
8426
+ if (newMatch) return { ok: true, hub: newMatch };
8427
+ const existingMatch = existingHubs.find(
8428
+ (h) => h.hubId === selector || path2.basename(h.hubFolder) === selector
8429
+ );
8430
+ if (existingMatch) return { ok: false, reason: "exists", existing: existingMatch };
8431
+ return { ok: false, reason: "selector_miss" };
8432
+ }
8433
+ const enclosingNew = findEnclosingNewHubFolder(workspaceDir);
8434
+ if (enclosingNew) return { ok: true, hub: enclosingNew };
8435
+ if (newHubs.length === 1) return { ok: true, hub: newHubs[0] };
8436
+ if (newHubs.length === 0) return { ok: false, reason: "none" };
8437
+ return { ok: false, reason: "ambiguous" };
8438
+ }
8382
8439
  function resolveActiveHubId(args2) {
8383
8440
  let selector;
8384
8441
  const hubIdx = args2.indexOf("--hub");
@@ -8533,24 +8590,24 @@ import * as path4 from "path";
8533
8590
  import * as readline from "readline";
8534
8591
  function prompt(question) {
8535
8592
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
8536
- return new Promise((resolve5) => {
8593
+ return new Promise((resolve4) => {
8537
8594
  rl.question(question, (answer) => {
8538
8595
  rl.close();
8539
- resolve5(answer.trim());
8596
+ resolve4(answer.trim());
8540
8597
  });
8541
8598
  });
8542
8599
  }
8543
8600
  function confirm(question) {
8544
8601
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
8545
- return new Promise((resolve5) => {
8602
+ return new Promise((resolve4) => {
8546
8603
  rl.question(`${question} [y/N]: `, (answer) => {
8547
8604
  rl.close();
8548
- resolve5(answer.trim().toLowerCase() === "y");
8605
+ resolve4(answer.trim().toLowerCase() === "y");
8549
8606
  });
8550
8607
  });
8551
8608
  }
8552
8609
  function promptSecret(question) {
8553
- return new Promise((resolve5) => {
8610
+ return new Promise((resolve4) => {
8554
8611
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
8555
8612
  const originalWrite = rl._writeToOutput;
8556
8613
  let firstWrite = true;
@@ -8566,18 +8623,18 @@ function promptSecret(question) {
8566
8623
  rl._writeToOutput = originalWrite;
8567
8624
  process.stdout.write("\n");
8568
8625
  rl.close();
8569
- resolve5(answer);
8626
+ resolve4(answer);
8570
8627
  });
8571
8628
  });
8572
8629
  }
8573
8630
  function readStdin() {
8574
- return new Promise((resolve5, reject) => {
8631
+ return new Promise((resolve4, reject) => {
8575
8632
  let data = "";
8576
8633
  process.stdin.setEncoding("utf-8");
8577
8634
  process.stdin.on("data", (chunk) => {
8578
8635
  data += chunk;
8579
8636
  });
8580
- process.stdin.on("end", () => resolve5(data.trim()));
8637
+ process.stdin.on("end", () => resolve4(data.trim()));
8581
8638
  process.stdin.on("error", reject);
8582
8639
  });
8583
8640
  }
@@ -8738,9 +8795,9 @@ function getVersionCachePath(filename = CLI_CACHE_FILE) {
8738
8795
  }
8739
8796
  function readVersionCache(filename = CLI_CACHE_FILE) {
8740
8797
  try {
8741
- const path25 = getVersionCachePath(filename);
8742
- if (!existsSync4(path25)) return null;
8743
- const parsed = JSON.parse(readFileSync5(path25, "utf-8"));
8798
+ const path26 = getVersionCachePath(filename);
8799
+ if (!existsSync4(path26)) return null;
8800
+ const parsed = JSON.parse(readFileSync5(path26, "utf-8"));
8744
8801
  if (typeof parsed.lastCheck !== "number") return null;
8745
8802
  if (parsed.latest !== null && typeof parsed.latest !== "string") return null;
8746
8803
  return parsed;
@@ -8760,10 +8817,10 @@ function isVersionCacheStale(filename = CLI_CACHE_FILE, maxAgeMs = MAX_AGE_24H_M
8760
8817
  return Date.now() - cache.lastCheck > maxAgeMs;
8761
8818
  }
8762
8819
  function writeVersionCache(filename, cache) {
8763
- const path25 = getVersionCachePath(filename);
8764
- const dir = dirname3(path25);
8820
+ const path26 = getVersionCachePath(filename);
8821
+ const dir = dirname3(path26);
8765
8822
  if (!existsSync4(dir)) mkdirSync(dir, { recursive: true });
8766
- writeFileSync2(path25, JSON.stringify(cache));
8823
+ writeFileSync2(path26, JSON.stringify(cache));
8767
8824
  }
8768
8825
  function touchVersionCache(filename) {
8769
8826
  writeVersionCache(filename, { lastCheck: Date.now(), latest: readVersionCache(filename)?.latest ?? null });
@@ -8802,14 +8859,14 @@ function parseFrontmatterVersion(content) {
8802
8859
  function findInstalledSkills(projectRoot, paths = SKILL_INSTALL_PATHS) {
8803
8860
  const found = [];
8804
8861
  for (const rel of paths) {
8805
- const path25 = join7(projectRoot, rel);
8806
- if (!existsSync5(path25)) continue;
8862
+ const path26 = join7(projectRoot, rel);
8863
+ if (!existsSync5(path26)) continue;
8807
8864
  let version = null;
8808
8865
  try {
8809
- version = parseFrontmatterVersion(readFileSync6(path25, "utf-8"));
8866
+ version = parseFrontmatterVersion(readFileSync6(path26, "utf-8"));
8810
8867
  } catch {
8811
8868
  }
8812
- found.push({ path: path25, version });
8869
+ found.push({ path: path26, version });
8813
8870
  }
8814
8871
  return found;
8815
8872
  }
@@ -9270,7 +9327,7 @@ async function validateToken(apiUrl, token) {
9270
9327
  }
9271
9328
  }
9272
9329
  function startCallbackServer(port, expectedState, timeoutMs = 12e4) {
9273
- return new Promise((resolve5, reject) => {
9330
+ return new Promise((resolve4, reject) => {
9274
9331
  const server = http.createServer((req, res) => {
9275
9332
  const url = new URL(req.url || "/", `http://127.0.0.1:${port}`);
9276
9333
  if (url.pathname === "/callback") {
@@ -9296,7 +9353,7 @@ function startCallbackServer(port, expectedState, timeoutMs = 12e4) {
9296
9353
  res.writeHead(200, { "Content-Type": "text/html" });
9297
9354
  res.end("<html><body><h2>Login successful!</h2><p>You can close this tab and return to your terminal.</p></body></html>");
9298
9355
  server.close();
9299
- resolve5({ code, port });
9356
+ resolve4({ code, port });
9300
9357
  } else {
9301
9358
  res.writeHead(400, { "Content-Type": "text/html" });
9302
9359
  res.end("<html><body><h2>Login failed</h2><p>No authorization code received</p></body></html>");
@@ -9506,10 +9563,10 @@ import * as readline2 from "readline";
9506
9563
  function prompt2(question, defaultValue) {
9507
9564
  const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
9508
9565
  const display = defaultValue ? `${question} [${defaultValue}]: ` : `${question}: `;
9509
- return new Promise((resolve5) => {
9566
+ return new Promise((resolve4) => {
9510
9567
  rl.question(display, (answer) => {
9511
9568
  rl.close();
9512
- resolve5(answer.trim() || defaultValue || "");
9569
+ resolve4(answer.trim() || defaultValue || "");
9513
9570
  });
9514
9571
  });
9515
9572
  }
@@ -9627,8 +9684,8 @@ async function tryOpenBrowser(url) {
9627
9684
  cmd = "xdg-open";
9628
9685
  args2 = [url];
9629
9686
  }
9630
- return new Promise((resolve5) => {
9631
- execFile(cmd, args2, (err) => resolve5(!err));
9687
+ return new Promise((resolve4) => {
9688
+ execFile(cmd, args2, (err) => resolve4(!err));
9632
9689
  });
9633
9690
  } catch {
9634
9691
  return false;
@@ -11266,9 +11323,11 @@ var init_pull = __esm({
11266
11323
  var push_exports = {};
11267
11324
  __export(push_exports, {
11268
11325
  autoRenameAgentFiles: () => autoRenameAgentFiles,
11326
+ createAndPushNewHub: () => createAndPushNewHub,
11269
11327
  printSyncResult: () => printSyncResult,
11270
11328
  printWarnings: () => printWarnings,
11271
11329
  pushCommand: () => pushCommand,
11330
+ reportUnresolvedPushTarget: () => reportUnresolvedPushTarget,
11272
11331
  selectExistingHub: () => selectExistingHub,
11273
11332
  shouldWarnIgnoredPreviewLabel: () => shouldWarnIgnoredPreviewLabel
11274
11333
  });
@@ -11554,67 +11613,11 @@ function selectExistingHub(workspaceDir, allHubs, selector, wsLabel) {
11554
11613
  if (previewHubs.length === 1) return previewHubs[0];
11555
11614
  return null;
11556
11615
  }
11557
- function selectNewHub(newHubs, selector) {
11558
- if (selector) {
11559
- const match = newHubs.find((h) => path14.basename(h.hubFolder) === selector);
11560
- if (!match) return null;
11561
- return match;
11562
- }
11563
- const cwd = process.cwd();
11564
- const cwdMatch = newHubs.find((h) => path14.resolve(h.hubFolder) === path14.resolve(cwd));
11565
- if (cwdMatch) return cwdMatch;
11566
- if (newHubs.length === 1) return newHubs[0];
11567
- return null;
11568
- }
11569
- async function pushCommand(args2) {
11570
- const { autoConfirm, hubSelector, label } = parseArgs5(args2);
11571
- const repoConfig = requireRepoConfig();
11572
- const { organization_id: organizationId } = repoConfig;
11573
- const { config, accessToken } = await requireAuth();
11574
- const client = new ApiClient({ apiUrl: config.api_url, accessToken });
11575
- const workspaceDir = resolveWorkspaceDir();
11576
- const gitRoot = findGitRoot();
11577
- const wsLabel = hubsDirLabel(gitRoot);
11578
- if (gitRoot) warnLayoutOnce(gitRoot);
11579
- if (!fs12.existsSync(workspaceDir)) {
11580
- console.error(`No ${wsLabel}/ directory found. Run \`wayai pull\` first or create hub files in ${wsLabel}/<hub>/hub.yaml.`);
11581
- process.exit(1);
11582
- }
11583
- const existingHubs = scanWorkspaceHubs(workspaceDir);
11584
- const newHubs = scanNewHubs(workspaceDir);
11585
- const existing = selectExistingHub(workspaceDir, existingHubs, hubSelector, wsLabel);
11586
- if (existing) {
11587
- if (existing.hubEnvironment === "production") {
11588
- console.log("This is a read-only production mirror \u2014 production hubs cannot be pushed. Edit the linked preview hub instead.");
11589
- return;
11590
- }
11591
- if (label) {
11592
- console.warn("Note: --label is only used when creating a new hub. To change an existing hub's label, use `wayai relabel`.");
11593
- }
11594
- assertHubMatchesBinding(existing.hubId, path14.basename(existing.hubFolder));
11595
- await pushSingleHub(client, existing.hubId, existing.hubFolder, autoConfirm, organizationId);
11596
- return;
11597
- }
11598
- const newHub = selectNewHub(newHubs, hubSelector);
11599
- if (!newHub) {
11600
- if (existingHubs.length === 0 && newHubs.length === 0) {
11601
- console.error(`No hub folders found. Create hub files in ${wsLabel}/<hub>/hub.yaml with \`hub: { name: ... }\` and run \`wayai push\`.`);
11602
- process.exit(1);
11603
- }
11604
- console.error(`Multiple hub folders found in ${wsLabel}/. Pass --hub <uuid|folder-name> to choose, or run from inside a hub folder:`);
11605
- for (const h of existingHubs) {
11606
- console.error(` ${path14.basename(h.hubFolder)} (${h.hubId})`);
11607
- }
11608
- for (const h of newHubs) {
11609
- console.error(` ${path14.basename(h.hubFolder)} (new \u2014 "${h.hubName}")`);
11610
- }
11611
- process.exit(1);
11612
- }
11613
- assertNoBindingBlocksHubCreation(newHub.hubName);
11616
+ async function createAndPushNewHub(client, newHub, opts) {
11614
11617
  const hubType = newHub.hubType || "chat";
11615
11618
  console.log(`
11616
- New hub detected: "${newHub.hubName}" (${hubType})`);
11617
- if (!autoConfirm) {
11619
+ New hub: "${newHub.hubName}" (${hubType})`);
11620
+ if (!opts.autoConfirm) {
11618
11621
  const ok = await confirm("Create this hub on the platform?");
11619
11622
  if (!ok) {
11620
11623
  console.log("Cancelled.");
@@ -11627,10 +11630,10 @@ New hub detected: "${newHub.hubName}" (${hubType})`);
11627
11630
  process.exit(1);
11628
11631
  }
11629
11632
  console.log("Creating hub...");
11630
- const createResult = await client.createHub(organizationId, {
11633
+ const createResult = await client.createHub(opts.organizationId, {
11631
11634
  hubName: newHub.hubName,
11632
11635
  hubType,
11633
- previewLabel: label?.trim() || void 0
11636
+ previewLabel: opts.label?.trim() || void 0
11634
11637
  });
11635
11638
  const createdHub = createResult.data[0];
11636
11639
  const hubId = createdHub.hub_id;
@@ -11657,7 +11660,69 @@ ${content}`;
11657
11660
  }
11658
11661
  fs12.writeFileSync(hubYamlPath, updated, "utf-8");
11659
11662
  autoBindIfUnbound(hubId);
11660
- await pushSingleHub(client, hubId, newHub.hubFolder, autoConfirm, organizationId, { skipAgentRename: true });
11663
+ await pushSingleHub(client, hubId, newHub.hubFolder, opts.autoConfirm, opts.organizationId, { skipAgentRename: true });
11664
+ }
11665
+ function reportUnresolvedPushTarget(reason, existingHubs, newHubs, selector, wsLabel) {
11666
+ if (reason === "none") {
11667
+ if (existingHubs.length > 0) {
11668
+ 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\`:`);
11669
+ for (const h of existingHubs) {
11670
+ console.error(` ${path14.basename(h.hubFolder)} (${h.hubId}, production mirror)`);
11671
+ }
11672
+ } else {
11673
+ console.error(`No hub folders found. Create hub files in ${wsLabel}/<hub>/hub.yaml with \`hub: { name: ... }\` and run \`wayai push\` (or \`wayai create\`).`);
11674
+ }
11675
+ process.exit(1);
11676
+ }
11677
+ if (reason === "selector_miss") {
11678
+ console.error(`No hub matching --hub ${selector} found in ${wsLabel}/. Available:`);
11679
+ } else {
11680
+ console.error(`Multiple hub folders found in ${wsLabel}/. Pass --hub <uuid|folder-name> to choose, or run from inside a hub folder:`);
11681
+ }
11682
+ for (const h of existingHubs) {
11683
+ console.error(` ${path14.basename(h.hubFolder)} (${h.hubId})`);
11684
+ }
11685
+ for (const h of newHubs) {
11686
+ console.error(` ${path14.basename(h.hubFolder)} (new \u2014 "${h.hubName}")`);
11687
+ }
11688
+ process.exit(1);
11689
+ }
11690
+ async function pushCommand(args2) {
11691
+ const { autoConfirm, hubSelector, label } = parseArgs5(args2);
11692
+ const repoConfig = requireRepoConfig();
11693
+ const { organization_id: organizationId } = repoConfig;
11694
+ const { config, accessToken } = await requireAuth();
11695
+ const client = new ApiClient({ apiUrl: config.api_url, accessToken });
11696
+ const workspaceDir = resolveWorkspaceDir();
11697
+ const gitRoot = findGitRoot();
11698
+ const wsLabel = hubsDirLabel(gitRoot);
11699
+ if (gitRoot) warnLayoutOnce(gitRoot);
11700
+ if (!fs12.existsSync(workspaceDir)) {
11701
+ console.error(`No ${wsLabel}/ directory found. Run \`wayai pull\` first or create hub files in ${wsLabel}/<hub>/hub.yaml.`);
11702
+ process.exit(1);
11703
+ }
11704
+ const existingHubs = scanWorkspaceHubs(workspaceDir);
11705
+ const newHubs = scanNewHubs(workspaceDir);
11706
+ const resolution = resolvePushTarget(workspaceDir, existingHubs, newHubs, hubSelector);
11707
+ if (!resolution.ok) {
11708
+ reportUnresolvedPushTarget(resolution.reason, existingHubs, newHubs, hubSelector, wsLabel);
11709
+ }
11710
+ if (resolution.target.kind === "existing") {
11711
+ const existing = resolution.target.hub;
11712
+ if (existing.hubEnvironment === "production") {
11713
+ console.log("This is a read-only production mirror \u2014 production hubs cannot be pushed. Edit the linked preview hub instead.");
11714
+ return;
11715
+ }
11716
+ if (label) {
11717
+ console.warn("Note: --label is only used when creating a new hub. To change an existing hub's label, use `wayai relabel`.");
11718
+ }
11719
+ console.log(`Target hub: ${path14.basename(existing.hubFolder)} (${existing.hubId})`);
11720
+ assertHubMatchesBinding(existing.hubId, path14.basename(existing.hubFolder));
11721
+ await pushSingleHub(client, existing.hubId, existing.hubFolder, autoConfirm, organizationId);
11722
+ return;
11723
+ }
11724
+ assertNoBindingBlocksHubCreation(resolution.target.hub.hubName);
11725
+ await createAndPushNewHub(client, resolution.target.hub, { autoConfirm, label, organizationId });
11661
11726
  }
11662
11727
  var init_push = __esm({
11663
11728
  "src/commands/push.ts"() {
@@ -11676,13 +11741,89 @@ var init_push = __esm({
11676
11741
  }
11677
11742
  });
11678
11743
 
11744
+ // src/commands/create.ts
11745
+ var create_exports = {};
11746
+ __export(create_exports, {
11747
+ createCommand: () => createCommand
11748
+ });
11749
+ import * as path15 from "path";
11750
+ import * as fs13 from "fs";
11751
+ function parseArgs6(args2) {
11752
+ let autoConfirm = false;
11753
+ let folderSelector;
11754
+ let label;
11755
+ for (let i = 0; i < args2.length; i++) {
11756
+ const arg = args2[i];
11757
+ if (arg === "--yes" || arg === "-y") {
11758
+ autoConfirm = true;
11759
+ } else if (arg === "--label" && args2[i + 1]) {
11760
+ label = args2[++i];
11761
+ } else if (!arg.startsWith("-") && folderSelector === void 0) {
11762
+ folderSelector = arg;
11763
+ }
11764
+ }
11765
+ return { autoConfirm, folderSelector, label };
11766
+ }
11767
+ async function createCommand(args2) {
11768
+ const { autoConfirm, folderSelector, label } = parseArgs6(args2);
11769
+ const repoConfig = requireRepoConfig();
11770
+ const { organization_id: organizationId } = repoConfig;
11771
+ const { config, accessToken } = await requireAuth();
11772
+ const client = new ApiClient({ apiUrl: config.api_url, accessToken });
11773
+ const workspaceDir = resolveWorkspaceDir();
11774
+ const gitRoot = findGitRoot();
11775
+ const wsLabel = hubsDirLabel(gitRoot);
11776
+ if (gitRoot) warnLayoutOnce(gitRoot);
11777
+ if (!fs13.existsSync(workspaceDir)) {
11778
+ console.error(`No ${wsLabel}/ directory found. Create hub files in ${wsLabel}/<hub>/hub.yaml with \`hub: { name: ... }\` first.`);
11779
+ process.exit(1);
11780
+ }
11781
+ const existingHubs = scanWorkspaceHubs(workspaceDir);
11782
+ const newHubs = scanNewHubs(workspaceDir);
11783
+ const resolution = resolveNewHubForCreate(workspaceDir, existingHubs, newHubs, folderSelector);
11784
+ if (!resolution.ok) {
11785
+ if (resolution.reason === "exists") {
11786
+ const folder = path15.basename(resolution.existing.hubFolder);
11787
+ console.error(`Hub "${folder}" already exists (${resolution.existing.hubId}). Use \`wayai push --hub ${folder}\` to update it.`);
11788
+ process.exit(1);
11789
+ }
11790
+ if (resolution.reason === "selector_miss") {
11791
+ console.error(`No new (uncreated) hub folder "${folderSelector}" found in ${wsLabel}/. A new hub folder needs a hub.yaml with \`hub: { name: ... }\` and no hub_id.`);
11792
+ process.exit(1);
11793
+ }
11794
+ if (resolution.reason === "none") {
11795
+ console.error(`No new (uncreated) hub folders found in ${wsLabel}/. Create ${wsLabel}/<hub>/hub.yaml with \`hub: { name: ... }\` first, then run \`wayai create\`.`);
11796
+ process.exit(1);
11797
+ }
11798
+ console.error(`Multiple new hub folders found in ${wsLabel}/. Pass the folder name (\`wayai create <folder>\`) or run from inside one:`);
11799
+ for (const h of newHubs) {
11800
+ console.error(` ${path15.basename(h.hubFolder)} (new \u2014 "${h.hubName}")`);
11801
+ }
11802
+ process.exit(1);
11803
+ }
11804
+ assertNoBindingBlocksHubCreation(resolution.hub.hubName);
11805
+ await createAndPushNewHub(client, resolution.hub, { autoConfirm, label, organizationId });
11806
+ }
11807
+ var init_create = __esm({
11808
+ "src/commands/create.ts"() {
11809
+ "use strict";
11810
+ init_auth();
11811
+ init_api_client();
11812
+ init_push();
11813
+ init_workspace();
11814
+ init_layout();
11815
+ init_repo_config();
11816
+ init_hub_binding();
11817
+ }
11818
+ });
11819
+
11679
11820
  // src/commands/diff.ts
11680
11821
  var diff_exports = {};
11681
11822
  __export(diff_exports, {
11682
11823
  diffCommand: () => diffCommand,
11683
- parseArgs: () => parseArgs6
11824
+ parseArgs: () => parseArgs7
11684
11825
  });
11685
- function parseArgs6(args2) {
11826
+ function parseArgs7(args2) {
11686
11827
  let production = false;
11687
11828
  let hubSelector;
11688
11829
  for (let i = 0; i < args2.length; i++) {
@@ -11696,7 +11837,7 @@ function parseArgs6(args2) {
11696
11837
  return { production, hubSelector };
11697
11838
  }
11698
11839
  async function diffCommand(args2) {
11699
- const { production, hubSelector } = parseArgs6(args2);
11840
+ const { production, hubSelector } = parseArgs7(args2);
11700
11841
  const repoConfig = requireRepoConfig();
11701
11842
  const { organization_id: organizationId } = repoConfig;
11702
11843
  const { config, accessToken } = await requireAuth();
@@ -11826,12 +11967,12 @@ function typeMatches2(typeField, allowed) {
11826
11967
  if (Array.isArray(typeField)) return typeField.every((t) => typeof t === "string" && allowed.has(t));
11827
11968
  return false;
11828
11969
  }
11829
- function validateSchema2(schema, path25, errors, opts = {}) {
11970
+ function validateSchema2(schema, path26, errors, opts = {}) {
11830
11971
  if (typeof schema === "boolean") return;
11831
11972
  const depth = opts.depth ?? 0;
11832
11973
  if (depth > MAX_SCHEMA_DEPTH2) {
11833
11974
  errors.push({
11834
- path: path25 || "<root>",
11975
+ path: path26 || "<root>",
11835
11976
  message: `schema nesting exceeds ${MAX_SCHEMA_DEPTH2} levels`,
11836
11977
  suggestion: "Flatten the schema; LLM providers reject deeply nested tool input_schemas."
11837
11978
  });
@@ -11839,7 +11980,7 @@ function validateSchema2(schema, path25, errors, opts = {}) {
11839
11980
  }
11840
11981
  if (!isRecord2(schema)) {
11841
11982
  errors.push({
11842
- path: path25,
11983
+ path: path26,
11843
11984
  message: `expected object, got ${schema === null ? "null" : typeof schema}`
11844
11985
  });
11845
11986
  return;
@@ -11847,14 +11988,14 @@ function validateSchema2(schema, path25, errors, opts = {}) {
11847
11988
  if (opts.isRoot) {
11848
11989
  if ("type" in schema && schema.type !== "object") {
11849
11990
  errors.push({
11850
- path: path25 ? `${path25}.type` : "type",
11991
+ path: path26 ? `${path26}.type` : "type",
11851
11992
  message: `root type must be 'object', got ${JSON.stringify(schema.type)}`,
11852
11993
  suggestion: "Tool parameters at the root must be an object: `{ type: 'object', properties: { ... } }`."
11853
11994
  });
11854
11995
  }
11855
11996
  } else if ("type" in schema && !typeMatches2(schema.type, ALLOWED_TYPES2)) {
11856
11997
  errors.push({
11857
- path: `${path25}.type`,
11998
+ path: `${path26}.type`,
11858
11999
  message: `type must be one of ${[...ALLOWED_TYPES2].join("/")} or an array of those, got ${JSON.stringify(schema.type)}`
11859
12000
  });
11860
12001
  }
@@ -11863,25 +12004,25 @@ function validateSchema2(schema, path25, errors, opts = {}) {
11863
12004
  if (typeof e === "string") {
11864
12005
  const isPlaceholder = PLACEHOLDER_TOKENS2.includes(e);
11865
12006
  errors.push({
11866
- path: `${path25}.enum`,
12007
+ path: `${path26}.enum`,
11867
12008
  message: `enum must be a non-empty array of primitives, got string ${JSON.stringify(e)}`,
11868
12009
  suggestion: isPlaceholder ? "Set `operation: 'update_kanban_status'` on the tool and ensure at least one hub.kanban_status has `allowsAgentUpdate: true` so the platform can render the placeholder into a valid array." : 'Wrap the value in an array: `enum: ["value"]`.'
11869
12010
  });
11870
12011
  } else if (!Array.isArray(e)) {
11871
12012
  errors.push({
11872
- path: `${path25}.enum`,
12013
+ path: `${path26}.enum`,
11873
12014
  message: `enum must be a non-empty array of primitives, got ${typeof e}`
11874
12015
  });
11875
12016
  } else if (e.length === 0) {
11876
12017
  errors.push({
11877
- path: `${path25}.enum`,
12018
+ path: `${path26}.enum`,
11878
12019
  message: "enum must not be empty"
11879
12020
  });
11880
12021
  } else {
11881
12022
  for (let i = 0; i < e.length; i++) {
11882
12023
  if (!isPrimitive2(e[i])) {
11883
12024
  errors.push({
11884
- path: `${path25}.enum[${i}]`,
12025
+ path: `${path26}.enum[${i}]`,
11885
12026
  message: `enum entry must be a primitive (string/number/boolean/null), got ${typeof e[i]}`
11886
12027
  });
11887
12028
  }
@@ -11891,7 +12032,7 @@ function validateSchema2(schema, path25, errors, opts = {}) {
11891
12032
  for (const key of ["exclusiveMinimum", "exclusiveMaximum"]) {
11892
12033
  if (key in schema && typeof schema[key] === "boolean") {
11893
12034
  errors.push({
11894
- path: `${path25}.${key}`,
12035
+ path: `${path26}.${key}`,
11895
12036
  message: `${key} as boolean is draft-04 syntax; draft 2020-12 requires a numeric value`,
11896
12037
  suggestion: `Replace with the numeric bound, e.g. \`${key}: 0\`.`
11897
12038
  });
@@ -11900,45 +12041,45 @@ function validateSchema2(schema, path25, errors, opts = {}) {
11900
12041
  if ("properties" in schema) {
11901
12042
  if (!isRecord2(schema.properties)) {
11902
12043
  errors.push({
11903
- path: `${path25}.properties`,
12044
+ path: `${path26}.properties`,
11904
12045
  message: `properties must be an object, got ${Array.isArray(schema.properties) ? "array" : typeof schema.properties}`
11905
12046
  });
11906
12047
  } else {
11907
12048
  for (const [propName, propSchema] of Object.entries(schema.properties)) {
11908
- validateSchema2(propSchema, `${path25}.properties.${propName}`, errors, { depth: depth + 1 });
12049
+ validateSchema2(propSchema, `${path26}.properties.${propName}`, errors, { depth: depth + 1 });
11909
12050
  }
11910
12051
  }
11911
12052
  }
11912
12053
  if (schemaTypeIncludes2(schema, "array") && "items" in schema) {
11913
12054
  if (Array.isArray(schema.items)) {
11914
- schema.items.forEach((sub, i) => validateSchema2(sub, `${path25}.items[${i}]`, errors, { depth: depth + 1 }));
12055
+ schema.items.forEach((sub, i) => validateSchema2(sub, `${path26}.items[${i}]`, errors, { depth: depth + 1 }));
11915
12056
  } else {
11916
- validateSchema2(schema.items, `${path25}.items`, errors, { depth: depth + 1 });
12057
+ validateSchema2(schema.items, `${path26}.items`, errors, { depth: depth + 1 });
11917
12058
  }
11918
12059
  }
11919
12060
  for (const key of SUBSCHEMA_OBJECT_KEYWORDS2) {
11920
12061
  if (key in schema && isRecord2(schema[key])) {
11921
- validateSchema2(schema[key], `${path25}.${key}`, errors, { depth: depth + 1 });
12062
+ validateSchema2(schema[key], `${path26}.${key}`, errors, { depth: depth + 1 });
11922
12063
  }
11923
12064
  }
11924
12065
  for (const key of SUBSCHEMA_LIST_KEYWORDS2) {
11925
12066
  const list = schema[key];
11926
12067
  if (Array.isArray(list)) {
11927
- list.forEach((sub, i) => validateSchema2(sub, `${path25}.${key}[${i}]`, errors, { depth: depth + 1 }));
12068
+ list.forEach((sub, i) => validateSchema2(sub, `${path26}.${key}[${i}]`, errors, { depth: depth + 1 }));
11928
12069
  }
11929
12070
  }
11930
12071
  for (const key of SUBSCHEMA_MAP_KEYWORDS2) {
11931
12072
  const map = schema[key];
11932
12073
  if (isRecord2(map)) {
11933
12074
  for (const [name, sub] of Object.entries(map)) {
11934
- validateSchema2(sub, `${path25}.${key}.${name}`, errors, { depth: depth + 1 });
12075
+ validateSchema2(sub, `${path26}.${key}.${name}`, errors, { depth: depth + 1 });
11935
12076
  }
11936
12077
  }
11937
12078
  }
11938
12079
  const reportedPaths = new Set(errors.map((e) => e.path));
11939
12080
  for (const [k, v] of Object.entries(schema)) {
11940
12081
  if (typeof v !== "string") continue;
11941
- const fieldPath = `${path25}.${k}`;
12082
+ const fieldPath = `${path26}.${k}`;
11942
12083
  if (reportedPaths.has(fieldPath)) continue;
11943
12084
  for (const token of PLACEHOLDER_TOKENS2) {
11944
12085
  if (v === token) {
@@ -12094,10 +12235,10 @@ function refineHubAsCodeLanes2(config, ctx) {
12094
12235
  }
12095
12236
  }
12096
12237
  }
12097
- function isSafeTemplatePath2(path25) {
12098
- if (path25.length === 0 || path25.length > 300) return false;
12099
- if (path25.startsWith("/") || path25.includes("\\")) return false;
12100
- const segments = path25.split("/");
12238
+ function isSafeTemplatePath2(path26) {
12239
+ if (path26.length === 0 || path26.length > 300) return false;
12240
+ if (path26.startsWith("/") || path26.includes("\\")) return false;
12241
+ const segments = path26.split("/");
12101
12242
  return segments.every(
12102
12243
  (seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
12103
12244
  );
@@ -12125,9 +12266,9 @@ function isPlainObject(value) {
12125
12266
  const proto = Object.getPrototypeOf(value);
12126
12267
  return proto === Object.prototype || proto === null;
12127
12268
  }
12128
- function isSanitizableSliceFile(path25) {
12129
- if (!/\.ya?ml$/i.test(path25)) return false;
12130
- return path25 !== "resources" && !path25.startsWith("resources/");
12269
+ function isSanitizableSliceFile(path26) {
12270
+ if (!/\.ya?ml$/i.test(path26)) return false;
12271
+ return path26 !== "resources" && !path26.startsWith("resources/");
12131
12272
  }
12132
12273
  function distinctUsesBackends(uses) {
12133
12274
  return [...new Set((uses ?? []).map((u) => u.backend))];
@@ -12569,7 +12710,12 @@ var init_contracts = __esm({
12569
12710
  // A NATIVE LLM (Agent) connection id on this hub; validated at set-time on the REST
12570
12711
  // PATCH (setup/hubs.ts rejects a non-existent / non-Agent / harness id) and re-checked
12571
12712
  // at fallback time in the turn seam (a stale/missing id simply no-ops). Nullable to clear it.
12572
- fallback_connection_id: uuidSchema2.nullable().optional()
12713
+ fallback_connection_id: uuidSchema2.nullable().optional(),
12714
+ // Rekor API connection used to reset/clear eval seed fixtures (gh #3090). A
12715
+ // connection id on this hub (a REST API (custom tool) connection whose base_url
12716
+ // is the Rekor API origin + a bearer/api_key `write:seeds` token). Validated at
12717
+ // set-time on the REST PATCH (setup/hubs.ts). Nullable to clear it.
12718
+ seed_connection_id: uuidSchema2.nullable().optional()
12573
12719
  }).passthrough().superRefine(refineLaneReferences2);
12574
12720
  addHubAdminBody2 = external_exports.object({
12575
12721
  user_email: external_exports.string().email("valid email is required")
@@ -14110,7 +14256,6 @@ var init_contracts = __esm({
14110
14256
  dataExplorerDebugAnalyticsTable2 = external_exports.enum([
14111
14257
  "conversation",
14112
14258
  "message",
14113
- "billing_event",
14114
14259
  "schedule_event"
14115
14260
  ]);
14116
14261
  debugUuid2 = external_exports.string().uuid();
@@ -14292,7 +14437,7 @@ var init_contracts = __esm({
14292
14437
  message: "at least one field must be provided"
14293
14438
  });
14294
14439
  contestReportBody2 = external_exports.object({
14295
- reason: external_exports.string().min(1).max(1e3)
14440
+ reason: external_exports.string().min(1).max(5e3)
14296
14441
  });
14297
14442
  reporterListQuery2 = external_exports.object({
14298
14443
  status: reportStatusSchema2.optional()
@@ -14324,7 +14469,7 @@ var init_contracts = __esm({
14324
14469
  }),
14325
14470
  external_exports.object({
14326
14471
  target: external_exports.literal("dismissed"),
14327
- dismissal_reason: external_exports.string().min(1).max(1e3),
14472
+ dismissal_reason: external_exports.string().min(1).max(5e3),
14328
14473
  ai_verdict: external_exports.string().max(2e3).optional(),
14329
14474
  final: external_exports.boolean().optional()
14330
14475
  })
@@ -14333,7 +14478,7 @@ var init_contracts = __esm({
14333
14478
  member_ids: external_exports.array(external_exports.string().uuid()).min(1).max(100)
14334
14479
  });
14335
14480
  holdReportBody2 = external_exports.object({
14336
- reason: external_exports.string().min(1).max(1e3)
14481
+ reason: external_exports.string().min(1).max(5e3)
14337
14482
  });
14338
14483
  clickhouseReadyResponse2 = external_exports.object({
14339
14484
  ready: external_exports.boolean()
@@ -14743,9 +14888,9 @@ var replicate_exports = {};
14743
14888
  __export(replicate_exports, {
14744
14889
  replicateCommand: () => replicateCommand
14745
14890
  });
14746
- import * as fs13 from "fs";
14747
- import * as path15 from "path";
14748
- function parseArgs7(args2) {
14891
+ import * as fs14 from "fs";
14892
+ import * as path16 from "path";
14893
+ function parseArgs8(args2) {
14749
14894
  let label;
14750
14895
  let hubSelector;
14751
14896
  for (let i = 0; i < args2.length; i++) {
@@ -14761,7 +14906,7 @@ function parseArgs7(args2) {
14761
14906
  return { label, hubSelector };
14762
14907
  }
14763
14908
  async function replicateCommand(args2) {
14764
- const { label, hubSelector } = parseArgs7(args2);
14909
+ const { label, hubSelector } = parseArgs8(args2);
14765
14910
  const normalizedLabel = label?.trim() || void 0;
14766
14911
  if (normalizedLabel && normalizedLabel.length > PREVIEW_LABEL_MAX_LENGTH2) {
14767
14912
  console.error(`--label must be ${PREVIEW_LABEL_MAX_LENGTH2} characters or fewer.`);
@@ -14790,7 +14935,7 @@ async function replicateCommand(args2) {
14790
14935
  payload.preview_label,
14791
14936
  payload.branch_name
14792
14937
  );
14793
- fs13.mkdirSync(path15.dirname(hubFolder), { recursive: true });
14938
+ fs14.mkdirSync(path16.dirname(hubFolder), { recursive: true });
14794
14939
  writeHubFolder(hubFolder, payload);
14795
14940
  await downloadBinaryResourceFiles(hubFolder, payload);
14796
14941
  hubFolder = autoRenameHubFolder(
@@ -14802,8 +14947,8 @@ async function replicateCommand(args2) {
14802
14947
  payload.branch_name
14803
14948
  );
14804
14949
  autoBindIfUnbound(previewHubId);
14805
- console.log(`Preview written to ${path15.basename(hubFolder)}`);
14806
- console.log(` Switch to it with: wayai use ${path15.basename(hubFolder)}`);
14950
+ console.log(`Preview written to ${path16.basename(hubFolder)}`);
14951
+ console.log(` Switch to it with: wayai use ${path16.basename(hubFolder)}`);
14807
14952
  }
14808
14953
  var init_replicate = __esm({
14809
14954
  "src/commands/replicate.ts"() {
@@ -14825,8 +14970,8 @@ var relabel_exports = {};
14825
14970
  __export(relabel_exports, {
14826
14971
  relabelCommand: () => relabelCommand
14827
14972
  });
14828
- import * as path16 from "path";
14829
- function parseArgs8(args2) {
14973
+ import * as path17 from "path";
14974
+ function parseArgs9(args2) {
14830
14975
  let label;
14831
14976
  let clear = false;
14832
14977
  let hubSelector;
@@ -14843,7 +14988,7 @@ function parseArgs8(args2) {
14843
14988
  return { label, clear, hubSelector };
14844
14989
  }
14845
14990
  async function relabelCommand(args2) {
14846
- const { label, clear, hubSelector } = parseArgs8(args2);
14991
+ const { label, clear, hubSelector } = parseArgs9(args2);
14847
14992
  if (!clear && (label === void 0 || label.trim() === "")) {
14848
14993
  console.error("Usage: wayai relabel <label> [--hub <uuid|folder>] (or --clear to remove the label)");
14849
14994
  process.exit(1);
@@ -14869,7 +15014,7 @@ async function relabelCommand(args2) {
14869
15014
  } else {
14870
15015
  console.error(`Multiple hubs found in ${wsLabel}/. Pass --hub <uuid|folder-name> to choose, or run from inside a hub folder:`);
14871
15016
  for (const h of previewHubs) {
14872
- console.error(` ${path16.basename(h.hubFolder)} (${h.hubId})`);
15017
+ console.error(` ${path17.basename(h.hubFolder)} (${h.hubId})`);
14873
15018
  }
14874
15019
  }
14875
15020
  process.exit(1);
@@ -14878,7 +15023,7 @@ async function relabelCommand(args2) {
14878
15023
  console.log("This is a read-only production mirror \u2014 production hubs have no preview label. Relabel the linked preview hub instead.");
14879
15024
  return;
14880
15025
  }
14881
- assertHubMatchesBinding(target.hubId, path16.basename(target.hubFolder));
15026
+ assertHubMatchesBinding(target.hubId, path17.basename(target.hubFolder));
14882
15027
  console.log(normalizedLabel ? `Setting preview label to "${normalizedLabel}"...` : "Clearing preview label...");
14883
15028
  const { data } = await client.relabelPreview(target.hubId, normalizedLabel);
14884
15029
  const row = data[0];
@@ -14894,7 +15039,7 @@ async function relabelCommand(args2) {
14894
15039
  );
14895
15040
  console.log(serverLabel ? `Preview label set to "${serverLabel}".` : "Preview label cleared.");
14896
15041
  if (finalFolder !== target.hubFolder) {
14897
- console.log(`Hub folder is now ${path16.basename(finalFolder)}`);
15042
+ console.log(`Hub folder is now ${path17.basename(finalFolder)}`);
14898
15043
  }
14899
15044
  }
14900
15045
  var init_relabel = __esm({
@@ -14915,13 +15060,13 @@ var init_relabel = __esm({
14915
15060
  // src/commands/publish.ts
14916
15061
  var publish_exports = {};
14917
15062
  __export(publish_exports, {
14918
- parseArgs: () => parseArgs9,
15063
+ parseArgs: () => parseArgs10,
14919
15064
  publishCommand: () => publishCommand,
14920
15065
  renderHubDiff: () => renderHubDiff,
14921
15066
  runPublish: () => runPublish
14922
15067
  });
14923
- import * as path17 from "path";
14924
- function parseArgs9(args2) {
15068
+ import * as path18 from "path";
15069
+ function parseArgs10(args2) {
14925
15070
  let autoConfirm = false;
14926
15071
  let hubSelector;
14927
15072
  for (let i = 0; i < args2.length; i++) {
@@ -15007,7 +15152,7 @@ Published. Production hub: ${data.production_hub_id}`);
15007
15152
  return "synced";
15008
15153
  }
15009
15154
  async function publishCommand(args2) {
15010
- const { autoConfirm, hubSelector } = parseArgs9(args2);
15155
+ const { autoConfirm, hubSelector } = parseArgs10(args2);
15011
15156
  const repoConfig = requireRepoConfig();
15012
15157
  const { organization_id: organizationId } = repoConfig;
15013
15158
  const { config, accessToken } = await requireAuth();
@@ -15026,7 +15171,7 @@ async function publishCommand(args2) {
15026
15171
  return;
15027
15172
  }
15028
15173
  }
15029
- assertHubMatchesBinding(hubId, hubFolder ? path17.basename(hubFolder) : void 0);
15174
+ assertHubMatchesBinding(hubId, hubFolder ? path18.basename(hubFolder) : void 0);
15030
15175
  await runPublish(client, { hubId, localConfig, organizationId, autoConfirm });
15031
15176
  }
15032
15177
  var STATUS_STYLE;
@@ -15058,7 +15203,7 @@ var use_exports = {};
15058
15203
  __export(use_exports, {
15059
15204
  useCommand: () => useCommand
15060
15205
  });
15061
- import * as path18 from "path";
15206
+ import * as path19 from "path";
15062
15207
  async function useCommand(args2) {
15063
15208
  const target = args2[0];
15064
15209
  if (!target || target.startsWith("-")) {
@@ -15079,9 +15224,22 @@ async function useCommand(args2) {
15079
15224
  const wsLabel = hubsDirLabel(gitRoot);
15080
15225
  const match = findHubByFolderName(workspaceDir, target);
15081
15226
  if (!match) {
15227
+ const newHubs = scanNewHubs(workspaceDir);
15228
+ const pending = newHubs.find((h) => path19.basename(h.hubFolder) === target);
15229
+ if (pending) {
15230
+ console.error(
15231
+ `"${target}" is a new hub that hasn't been created on the platform yet, so it has no id to bind to.
15232
+ Create it first \u2014 the worktree binds automatically afterward:
15233
+ wayai create ${target}`
15234
+ );
15235
+ process.exit(1);
15236
+ }
15082
15237
  console.error(`No hub matching "${target}" found in ${wsLabel}/. Pass a UUID or a folder name from:`);
15083
15238
  for (const h of scanWorkspaceHubs(workspaceDir)) {
15084
- console.error(` ${path18.basename(h.hubFolder)} (${h.hubId})`);
15239
+ console.error(` ${path19.basename(h.hubFolder)} (${h.hubId})`);
15240
+ }
15241
+ for (const h of newHubs) {
15242
+ console.error(` ${path19.basename(h.hubFolder)} (new \u2014 "${h.hubName}", run \`wayai create ${path19.basename(h.hubFolder)}\`)`);
15085
15243
  }
15086
15244
  process.exit(1);
15087
15245
  }
@@ -15120,11 +15278,11 @@ __export(migrate_exports, {
15120
15278
  migrateCommand: () => migrateCommand
15121
15279
  });
15122
15280
  import { execFileSync as execFileSync3 } from "child_process";
15123
- import * as fs14 from "fs";
15124
- import * as path19 from "path";
15281
+ import * as fs15 from "fs";
15282
+ import * as path20 from "path";
15125
15283
  function isTracked(gitRoot, p) {
15126
15284
  try {
15127
- execFileSync3("git", ["ls-files", "--error-unmatch", "--", path19.relative(gitRoot, p)], {
15285
+ execFileSync3("git", ["ls-files", "--error-unmatch", "--", path20.relative(gitRoot, p)], {
15128
15286
  cwd: gitRoot,
15129
15287
  stdio: ["pipe", "pipe", "pipe"]
15130
15288
  });
@@ -15134,10 +15292,10 @@ function isTracked(gitRoot, p) {
15134
15292
  }
15135
15293
  }
15136
15294
  function moveDir(gitRoot, from, to) {
15137
- fs14.mkdirSync(path19.dirname(to), { recursive: true });
15295
+ fs15.mkdirSync(path20.dirname(to), { recursive: true });
15138
15296
  if (isTracked(gitRoot, from)) {
15139
15297
  try {
15140
- execFileSync3("git", ["mv", path19.relative(gitRoot, from), path19.relative(gitRoot, to)], {
15298
+ execFileSync3("git", ["mv", path20.relative(gitRoot, from), path20.relative(gitRoot, to)], {
15141
15299
  cwd: gitRoot,
15142
15300
  stdio: ["pipe", "pipe", "pipe"]
15143
15301
  });
@@ -15145,7 +15303,7 @@ function moveDir(gitRoot, from, to) {
15145
15303
  } catch {
15146
15304
  }
15147
15305
  }
15148
- fs14.renameSync(from, to);
15306
+ fs15.renameSync(from, to);
15149
15307
  return "fs";
15150
15308
  }
15151
15309
  async function migrateCommand(_args) {
@@ -15154,12 +15312,12 @@ async function migrateCommand(_args) {
15154
15312
  console.error("Not inside a git repository.");
15155
15313
  process.exit(1);
15156
15314
  }
15157
- const rel = (p) => path19.relative(gitRoot, p);
15158
- const newWs = path19.join(gitRoot, WAYAI_LAYOUT.wsDir);
15159
- const legacyWs = path19.join(gitRoot, WAYAI_LAYOUT.legacy.wsDir);
15160
- const legacyOrg = path19.join(gitRoot, WAYAI_LAYOUT.legacy.orgAtRoot);
15161
- const newHubs = path19.join(newWs, WAYAI_LAYOUT.hubsSubdir);
15162
- const newOrg = path19.join(newWs, WAYAI_LAYOUT.orgSubdir);
15315
+ const rel = (p) => path20.relative(gitRoot, p);
15316
+ const newWs = path20.join(gitRoot, WAYAI_LAYOUT.wsDir);
15317
+ const legacyWs = path20.join(gitRoot, WAYAI_LAYOUT.legacy.wsDir);
15318
+ const legacyOrg = path20.join(gitRoot, WAYAI_LAYOUT.legacy.orgAtRoot);
15319
+ const newHubs = path20.join(newWs, WAYAI_LAYOUT.hubsSubdir);
15320
+ const newOrg = path20.join(newWs, WAYAI_LAYOUT.orgSubdir);
15163
15321
  const hasLegacyWs = isDirectory(legacyWs);
15164
15322
  const hasLegacyOrg = isDirectory(legacyOrg);
15165
15323
  if (!hasLegacyWs && !hasLegacyOrg) {
@@ -15793,10 +15951,10 @@ var init_delete_history = __esm({
15793
15951
  // src/commands/sync-skills.ts
15794
15952
  var sync_skills_exports = {};
15795
15953
  __export(sync_skills_exports, {
15796
- parseArgs: () => parseArgs10,
15954
+ parseArgs: () => parseArgs11,
15797
15955
  syncSkillsCommand: () => syncSkillsCommand
15798
15956
  });
15799
- function parseArgs10(args2) {
15957
+ function parseArgs11(args2) {
15800
15958
  let connectionId;
15801
15959
  const idx = args2.indexOf("--connection-id");
15802
15960
  if (idx !== -1 && args2[idx + 1]) {
@@ -15819,7 +15977,7 @@ function printSyncResults(response) {
15819
15977
  }
15820
15978
  async function syncSkillsCommand(args2) {
15821
15979
  const hubId = resolveActiveHubId(args2);
15822
- const { connectionId } = parseArgs10(args2);
15980
+ const { connectionId } = parseArgs11(args2);
15823
15981
  requireRepoConfig();
15824
15982
  const { config, accessToken } = await requireAuth();
15825
15983
  const client = new ApiClient({ apiUrl: config.api_url, accessToken });
@@ -15844,10 +16002,10 @@ var init_sync_skills = __esm({
15844
16002
  // src/commands/sync-mcp.ts
15845
16003
  var sync_mcp_exports = {};
15846
16004
  __export(sync_mcp_exports, {
15847
- parseArgs: () => parseArgs11,
16005
+ parseArgs: () => parseArgs12,
15848
16006
  syncMcpCommand: () => syncMcpCommand
15849
16007
  });
15850
- function parseArgs11(args2) {
16008
+ function parseArgs12(args2) {
15851
16009
  let connection;
15852
16010
  for (let i = 0; i < args2.length; i++) {
15853
16011
  const arg = args2[i];
@@ -15859,7 +16017,7 @@ function parseArgs11(args2) {
15859
16017
  }
15860
16018
  async function syncMcpCommand(args2) {
15861
16019
  const hubId = resolveActiveHubId(args2);
15862
- const { connection } = parseArgs11(args2);
16020
+ const { connection } = parseArgs12(args2);
15863
16021
  if (!connection) {
15864
16022
  console.error("Usage: wayai sync-mcp --connection <name> [--hub <uuid|folder-name>]");
15865
16023
  console.error("");
@@ -16271,7 +16429,7 @@ Timeout after ${timeoutSeconds}s. Session is still running.`);
16271
16429
  console.log(`Check results: wayai eval-results --session ${sessionId}`);
16272
16430
  }
16273
16431
  function sleep(ms) {
16274
- return new Promise((resolve5) => setTimeout(resolve5, ms));
16432
+ return new Promise((resolve4) => setTimeout(resolve4, ms));
16275
16433
  }
16276
16434
  function parsePacing(raw) {
16277
16435
  const NAMED = EVAL_PACING_PRESET_NAMES.filter((p) => p !== "custom");
@@ -16496,15 +16654,15 @@ var eval_capture_exports = {};
16496
16654
  __export(eval_capture_exports, {
16497
16655
  evalCaptureCommand: () => evalCaptureCommand
16498
16656
  });
16499
- import * as fs15 from "fs";
16500
- import * as path20 from "path";
16657
+ import * as fs16 from "fs";
16658
+ import * as path21 from "path";
16501
16659
  import * as yaml7 from "js-yaml";
16502
16660
  function isValidSetName(name) {
16503
16661
  if (name.length === 0 || name === "." || name === "..") return false;
16504
16662
  if (name.startsWith(".")) return false;
16505
16663
  return !/[\/\\\0]/.test(name);
16506
16664
  }
16507
- function parseArgs12(args2) {
16665
+ function parseArgs13(args2) {
16508
16666
  if (args2.length === 0 || args2[0].startsWith("-")) {
16509
16667
  console.error("Usage: wayai eval capture <conversation_id> [--set <name>] [--name <eval_name>] [--instructions <text>]");
16510
16668
  process.exit(1);
@@ -16550,7 +16708,7 @@ function parseArgs12(args2) {
16550
16708
  }
16551
16709
  async function evalCaptureCommand(args2) {
16552
16710
  const hubId = resolveActiveHubId(args2);
16553
- const parsed = parseArgs12(args2);
16711
+ const parsed = parseArgs13(args2);
16554
16712
  const { config, accessToken } = await requireAuth();
16555
16713
  requireRepoConfig();
16556
16714
  const client = new ApiClient({ apiUrl: config.api_url, accessToken });
@@ -16563,15 +16721,15 @@ async function evalCaptureCommand(args2) {
16563
16721
  const setFolderName = targetSetName;
16564
16722
  const scenarioName = parsed.evalName ?? `Capture ${parsed.conversationId.slice(0, 8)}`;
16565
16723
  const slug = slugify(scenarioName);
16566
- const evalsDir = path20.join(hubFolder, "evals");
16567
- const targetDir = path20.join(evalsDir, setFolderName);
16568
- const targetPath = path20.join(targetDir, `${slug}.yaml`);
16569
- if (!targetPath.startsWith(evalsDir + path20.sep)) {
16570
- console.error(`Resolved path "${path20.relative(hubFolder, targetPath)}" escapes evals/. Aborting.`);
16724
+ const evalsDir = path21.join(hubFolder, "evals");
16725
+ const targetDir = path21.join(evalsDir, setFolderName);
16726
+ const targetPath = path21.join(targetDir, `${slug}.yaml`);
16727
+ if (!targetPath.startsWith(evalsDir + path21.sep)) {
16728
+ console.error(`Resolved path "${path21.relative(hubFolder, targetPath)}" escapes evals/. Aborting.`);
16571
16729
  process.exit(1);
16572
16730
  }
16573
- if (fs15.existsSync(targetPath)) {
16574
- console.error(`File already exists: ${path20.relative(hubFolder, targetPath)}. Use --name to choose a different name.`);
16731
+ if (fs16.existsSync(targetPath)) {
16732
+ console.error(`File already exists: ${path21.relative(hubFolder, targetPath)}. Use --name to choose a different name.`);
16575
16733
  process.exit(1);
16576
16734
  }
16577
16735
  console.log("Resolving scenario set...");
@@ -16603,9 +16761,9 @@ async function evalCaptureCommand(args2) {
16603
16761
  ...captured.evaluator_instructions ? { evaluator_instructions: captured.evaluator_instructions } : {}
16604
16762
  };
16605
16763
  const yamlObj = buildEvalYamlObject(evalEntry, slug);
16606
- fs15.mkdirSync(targetDir, { recursive: true });
16607
- fs15.writeFileSync(targetPath, yaml7.dump(yamlObj, YAML_DUMP_OPTIONS), "utf-8");
16608
- const relPath = path20.relative(process.cwd(), targetPath);
16764
+ fs16.mkdirSync(targetDir, { recursive: true });
16765
+ fs16.writeFileSync(targetPath, yaml7.dump(yamlObj, YAML_DUMP_OPTIONS), "utf-8");
16766
+ const relPath = path21.relative(process.cwd(), targetPath);
16609
16767
  console.log(`
16610
16768
  Wrote ${relPath}`);
16611
16769
  console.log("Run `wayai pull` to refresh the agent display name, then commit. The scenario is already on the platform.");
@@ -16627,7 +16785,7 @@ var journey_capture_exports = {};
16627
16785
  __export(journey_capture_exports, {
16628
16786
  journeyCaptureCommand: () => journeyCaptureCommand
16629
16787
  });
16630
- function parseArgs13(args2) {
16788
+ function parseArgs14(args2) {
16631
16789
  if (args2.length === 0 || args2[0].startsWith("-")) {
16632
16790
  console.error("Usage: wayai eval journey capture <conversation_id> [--name <journey_name>] [--instructions <text>]");
16633
16791
  process.exit(1);
@@ -16662,7 +16820,7 @@ function parseArgs13(args2) {
16662
16820
  }
16663
16821
  async function journeyCaptureCommand(args2) {
16664
16822
  const hubId = resolveActiveHubId(args2);
16665
- const parsed = parseArgs13(args2);
16823
+ const parsed = parseArgs14(args2);
16666
16824
  const { config, accessToken } = await requireAuth();
16667
16825
  requireRepoConfig();
16668
16826
  const client = new ApiClient({ apiUrl: config.api_url, accessToken });
@@ -17459,9 +17617,9 @@ var init_credential_utils = __esm({
17459
17617
  var create_credential_exports = {};
17460
17618
  __export(create_credential_exports, {
17461
17619
  createCredentialCommand: () => createCredentialCommand,
17462
- parseArgs: () => parseArgs14
17620
+ parseArgs: () => parseArgs15
17463
17621
  });
17464
- function parseArgs14(args2) {
17622
+ function parseArgs15(args2) {
17465
17623
  let name;
17466
17624
  let type;
17467
17625
  let orgId;
@@ -17489,7 +17647,7 @@ function parseArgs14(args2) {
17489
17647
  return { name, type, orgId, description, tags: splitTagRefs(tags), environment, stdin };
17490
17648
  }
17491
17649
  async function createCredentialCommand(args2) {
17492
- const parsed = parseArgs14(args2);
17650
+ const parsed = parseArgs15(args2);
17493
17651
  if (!parsed.name) {
17494
17652
  console.error("Missing required flag: --name <credential-name>");
17495
17653
  console.error('Usage: wayai create-credential --name "openai-key" --type "Bearer Token"');
@@ -17596,10 +17754,10 @@ var init_create_credential = __esm({
17596
17754
  // src/commands/update-credential.ts
17597
17755
  var update_credential_exports = {};
17598
17756
  __export(update_credential_exports, {
17599
- parseArgs: () => parseArgs15,
17757
+ parseArgs: () => parseArgs16,
17600
17758
  updateCredentialCommand: () => updateCredentialCommand
17601
17759
  });
17602
- function parseArgs15(args2) {
17760
+ function parseArgs16(args2) {
17603
17761
  let name;
17604
17762
  let rename;
17605
17763
  let orgId;
@@ -17632,7 +17790,7 @@ function parseArgs15(args2) {
17632
17790
  return { name, rename, orgId, description, tags: splitTagRefs(tags), hasTagFlag, environment, stdin, secretPrompt };
17633
17791
  }
17634
17792
  async function updateCredentialCommand(args2) {
17635
- const parsed = parseArgs15(args2);
17793
+ const parsed = parseArgs16(args2);
17636
17794
  if (!parsed.name) {
17637
17795
  console.error("Missing required flag: --name <credential-name>");
17638
17796
  console.error('Usage: wayai update-credential --name "my-key" --stdin');
@@ -17737,10 +17895,10 @@ var init_update_credential = __esm({
17737
17895
  // src/commands/set-connection-credential.ts
17738
17896
  var set_connection_credential_exports = {};
17739
17897
  __export(set_connection_credential_exports, {
17740
- parseArgs: () => parseArgs16,
17898
+ parseArgs: () => parseArgs17,
17741
17899
  setConnectionCredentialCommand: () => setConnectionCredentialCommand
17742
17900
  });
17743
- function parseArgs16(args2) {
17901
+ function parseArgs17(args2) {
17744
17902
  let connection;
17745
17903
  let orgCredential;
17746
17904
  let field;
@@ -17763,7 +17921,7 @@ function usage(msg) {
17763
17921
  }
17764
17922
  async function setConnectionCredentialCommand(args2) {
17765
17923
  const hubId = resolveActiveHubId(args2);
17766
- const parsed = parseArgs16(args2);
17924
+ const parsed = parseArgs17(args2);
17767
17925
  if (!parsed.connection) usage("Missing required flag: --connection <name|id>");
17768
17926
  const orgMode = !!parsed.orgCredential;
17769
17927
  const directMode = !!parsed.field;
@@ -17832,23 +17990,23 @@ var init_set_connection_credential = __esm({
17832
17990
  });
17833
17991
 
17834
17992
  // src/lib/org-workspace.ts
17835
- import * as fs16 from "fs";
17836
- import * as path21 from "path";
17993
+ import * as fs17 from "fs";
17994
+ import * as path22 from "path";
17837
17995
  import * as yaml8 from "js-yaml";
17838
17996
  function getOrgDir(gitRoot) {
17839
17997
  return resolveLayout(gitRoot).orgDir;
17840
17998
  }
17841
17999
  function orgManifestExists(orgDir) {
17842
- return fs16.existsSync(path21.join(orgDir, ORG_MANIFEST_NAME));
18000
+ return fs17.existsSync(path22.join(orgDir, ORG_MANIFEST_NAME));
17843
18001
  }
17844
18002
  function parseOrgResources(orgDir) {
17845
- const manifestPath = path21.join(orgDir, ORG_MANIFEST_NAME);
18003
+ const manifestPath = path22.join(orgDir, ORG_MANIFEST_NAME);
17846
18004
  let manifest = {};
17847
- if (fs16.existsSync(manifestPath)) {
17848
- manifest = yaml8.load(fs16.readFileSync(manifestPath, "utf-8")) ?? {};
18005
+ if (fs17.existsSync(manifestPath)) {
18006
+ manifest = yaml8.load(fs17.readFileSync(manifestPath, "utf-8")) ?? {};
17849
18007
  }
17850
18008
  const rawResources = Array.isArray(manifest.resources) ? manifest.resources : [];
17851
- const resourcesDir = path21.join(orgDir, "resources");
18009
+ const resourcesDir = path22.join(orgDir, "resources");
17852
18010
  const resources = rawResources.map((res) => {
17853
18011
  const resource = { name: res.name };
17854
18012
  if (res.id) resource.id = res.id;
@@ -17860,8 +18018,8 @@ function parseOrgResources(orgDir) {
17860
18018
  if (res.environment) resource.environment = res.environment;
17861
18019
  if (Array.isArray(res.tags)) resource.tags = res.tags;
17862
18020
  if (Array.isArray(res.folders)) resource.folders = res.folders;
17863
- const resDir = path21.join(resourcesDir, slugify(resource.name));
17864
- if (fs16.existsSync(resDir)) {
18021
+ const resDir = path22.join(resourcesDir, slugify(resource.name));
18022
+ if (fs17.existsSync(resDir)) {
17865
18023
  const files = scanResourceFiles(resDir, "");
17866
18024
  if (files.length > 0) resource.files = files;
17867
18025
  }
@@ -17870,28 +18028,28 @@ function parseOrgResources(orgDir) {
17870
18028
  return { version: 1, resources };
17871
18029
  }
17872
18030
  function writeOrgResources(orgDir, payload) {
17873
- fs16.mkdirSync(orgDir, { recursive: true });
18031
+ fs17.mkdirSync(orgDir, { recursive: true });
17874
18032
  const resources = payload.resources ?? [];
17875
18033
  const manifestResources = resources.map((r) => {
17876
18034
  const { files: _files, ...rest } = r;
17877
18035
  return rest;
17878
18036
  });
17879
- fs16.writeFileSync(
17880
- path21.join(orgDir, ORG_MANIFEST_NAME),
18037
+ fs17.writeFileSync(
18038
+ path22.join(orgDir, ORG_MANIFEST_NAME),
17881
18039
  yaml8.dump({ version: 1, resources: manifestResources }, YAML_DUMP_OPTIONS),
17882
18040
  "utf-8"
17883
18041
  );
17884
- const resourcesDir = path21.join(orgDir, "resources");
18042
+ const resourcesDir = path22.join(orgDir, "resources");
17885
18043
  const currentSlugs = /* @__PURE__ */ new Set();
17886
18044
  for (const resource of resources) {
17887
18045
  const resSlug = slugify(resource.name);
17888
18046
  currentSlugs.add(resSlug);
17889
- writeResourceFileTree(path21.join(resourcesDir, resSlug), resource.files || []);
18047
+ writeResourceFileTree(path22.join(resourcesDir, resSlug), resource.files || []);
17890
18048
  }
17891
- if (fs16.existsSync(resourcesDir)) {
17892
- for (const entry of fs16.readdirSync(resourcesDir, { withFileTypes: true })) {
18049
+ if (fs17.existsSync(resourcesDir)) {
18050
+ for (const entry of fs17.readdirSync(resourcesDir, { withFileTypes: true })) {
17893
18051
  if (entry.isDirectory() && !currentSlugs.has(entry.name)) {
17894
- fs16.rmSync(path21.join(resourcesDir, entry.name), { recursive: true, force: true });
18052
+ fs17.rmSync(path22.join(resourcesDir, entry.name), { recursive: true, force: true });
17895
18053
  }
17896
18054
  }
17897
18055
  }
@@ -17900,7 +18058,7 @@ async function downloadOrgBinaryFiles(orgDir, payload) {
17900
18058
  let count = 0;
17901
18059
  for (const resource of payload.resources ?? []) {
17902
18060
  if (!resource.files) continue;
17903
- const resDir = path21.join(orgDir, "resources", slugify(resource.name));
18061
+ const resDir = path22.join(orgDir, "resources", slugify(resource.name));
17904
18062
  count += await downloadBinaryFiles(resDir, resource.files);
17905
18063
  }
17906
18064
  if (count > 0) console.log(`Downloaded ${count} binary resource file(s).`);
@@ -18088,9 +18246,9 @@ var init_org = __esm({
18088
18246
  var list_exports = {};
18089
18247
  __export(list_exports, {
18090
18248
  listCommand: () => listCommand,
18091
- parseArgs: () => parseArgs17
18249
+ parseArgs: () => parseArgs18
18092
18250
  });
18093
- function parseArgs17(args2) {
18251
+ function parseArgs18(args2) {
18094
18252
  let orgId;
18095
18253
  let json = false;
18096
18254
  for (let i = 0; i < args2.length; i++) {
@@ -18103,7 +18261,7 @@ function parseArgs17(args2) {
18103
18261
  return { orgId, json };
18104
18262
  }
18105
18263
  async function listCommand(args2) {
18106
- const { orgId, json } = parseArgs17(args2);
18264
+ const { orgId, json } = parseArgs18(args2);
18107
18265
  const { config, accessToken } = await requireAuth();
18108
18266
  const client = new ApiClient({ apiUrl: config.api_url, accessToken });
18109
18267
  const { organizations } = await client.organizations();
@@ -18156,20 +18314,20 @@ var init_list = __esm({
18156
18314
  });
18157
18315
 
18158
18316
  // src/lib/template-files.ts
18159
- import * as fs17 from "fs";
18160
- import * as path22 from "path";
18317
+ import * as fs18 from "fs";
18318
+ import * as path23 from "path";
18161
18319
  function readDirToFileMap(rootDir) {
18162
18320
  const out = {};
18163
18321
  function walk(dir, prefix) {
18164
- const entries = fs17.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
18322
+ const entries = fs18.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
18165
18323
  for (const entry of entries) {
18166
- const abs = path22.join(dir, entry.name);
18324
+ const abs = path23.join(dir, entry.name);
18167
18325
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
18168
18326
  if (entry.isDirectory()) walk(abs, rel);
18169
- else if (entry.isFile()) out[rel] = fs17.readFileSync(abs, "utf-8");
18327
+ else if (entry.isFile()) out[rel] = fs18.readFileSync(abs, "utf-8");
18170
18328
  }
18171
18329
  }
18172
- if (fs17.existsSync(rootDir)) walk(rootDir, "");
18330
+ if (fs18.existsSync(rootDir)) walk(rootDir, "");
18173
18331
  return out;
18174
18332
  }
18175
18333
  function detectCollisions(targetDir, files) {
@@ -18178,7 +18336,7 @@ function detectCollisions(targetDir, files) {
18178
18336
  if (!isSafeTemplatePath2(rel)) {
18179
18337
  throw new Error(`Refusing to inspect unsafe template path: ${rel}`);
18180
18338
  }
18181
- if (fs17.existsSync(path22.join(targetDir, rel))) collisions.push(rel);
18339
+ if (fs18.existsSync(path23.join(targetDir, rel))) collisions.push(rel);
18182
18340
  }
18183
18341
  return collisions.sort((a, b) => a.localeCompare(b));
18184
18342
  }
@@ -18188,9 +18346,9 @@ function writeFileMap(targetDir, files) {
18188
18346
  if (!isSafeTemplatePath2(rel)) {
18189
18347
  throw new Error(`Refusing to write unsafe template path: ${rel}`);
18190
18348
  }
18191
- const abs = path22.join(targetDir, rel);
18192
- fs17.mkdirSync(path22.dirname(abs), { recursive: true });
18193
- fs17.writeFileSync(abs, body, "utf-8");
18349
+ const abs = path23.join(targetDir, rel);
18350
+ fs18.mkdirSync(path23.dirname(abs), { recursive: true });
18351
+ fs18.writeFileSync(abs, body, "utf-8");
18194
18352
  written.push(rel);
18195
18353
  }
18196
18354
  return written;
@@ -18198,20 +18356,20 @@ function writeFileMap(targetDir, files) {
18198
18356
  function listDirRelFiles(dir) {
18199
18357
  const out = [];
18200
18358
  function walk(d, prefix) {
18201
- for (const entry of fs17.readdirSync(d, { withFileTypes: true })) {
18359
+ for (const entry of fs18.readdirSync(d, { withFileTypes: true })) {
18202
18360
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
18203
- if (entry.isDirectory()) walk(path22.join(d, entry.name), rel);
18361
+ if (entry.isDirectory()) walk(path23.join(d, entry.name), rel);
18204
18362
  else if (entry.isFile()) out.push(rel);
18205
18363
  }
18206
18364
  }
18207
- if (fs17.existsSync(dir)) walk(dir, "");
18365
+ if (fs18.existsSync(dir)) walk(dir, "");
18208
18366
  return out;
18209
18367
  }
18210
18368
  function writeSliceSnapshot(targetDir, files) {
18211
18369
  const keep = new Set(Object.keys(files));
18212
18370
  const removed = listDirRelFiles(targetDir).filter((rel) => !keep.has(rel)).sort((a, b) => a.localeCompare(b));
18213
18371
  const written = writeFileMap(targetDir, files).sort((a, b) => a.localeCompare(b));
18214
- if (fs17.existsSync(targetDir)) cleanOrphanFiles(targetDir, "", keep);
18372
+ if (fs18.existsSync(targetDir)) cleanOrphanFiles(targetDir, "", keep);
18215
18373
  return { written, removed };
18216
18374
  }
18217
18375
  var init_template_files = __esm({
@@ -18227,7 +18385,7 @@ var templates_exports = {};
18227
18385
  __export(templates_exports, {
18228
18386
  templateCommand: () => templateCommand
18229
18387
  });
18230
- import * as path23 from "path";
18388
+ import * as path24 from "path";
18231
18389
  async function templateCommand(args2) {
18232
18390
  const [sub, ...rest] = args2;
18233
18391
  switch (sub) {
@@ -18343,8 +18501,8 @@ async function runTemplatePull(rest) {
18343
18501
  console.log(`Template "${slug}" has no WayAI slice${hint}`);
18344
18502
  return;
18345
18503
  }
18346
- const targetDir = path23.join(resolveLayout(gitRoot).hubsDir, slug);
18347
- const relTarget = path23.relative(gitRoot, targetDir);
18504
+ const targetDir = path24.join(resolveLayout(gitRoot).hubsDir, slug);
18505
+ const relTarget = path24.relative(gitRoot, targetDir);
18348
18506
  const collisions = detectCollisions(targetDir, detail.files);
18349
18507
  if (dryRun) {
18350
18508
  const planned = Object.keys(detail.files).sort((a, b) => a.localeCompare(b));
@@ -18518,8 +18676,8 @@ var admin_exports = {};
18518
18676
  __export(admin_exports, {
18519
18677
  adminCommand: () => adminCommand
18520
18678
  });
18521
- import * as fs18 from "fs";
18522
- import * as path24 from "path";
18679
+ import * as fs19 from "fs";
18680
+ import * as path25 from "path";
18523
18681
  import * as yaml10 from "js-yaml";
18524
18682
  async function adminCommand(args2) {
18525
18683
  const [group, ...afterGroup] = args2;
@@ -18827,7 +18985,7 @@ async function runArchiveRead(positional, flagArgs) {
18827
18985
  exitOnApiError(err);
18828
18986
  throw err;
18829
18987
  }
18830
- fs18.writeFileSync(outPath, zip);
18988
+ fs19.writeFileSync(outPath, zip);
18831
18989
  console.log(`Wrote ${zip.byteLength} bytes to ${outPath}`);
18832
18990
  return;
18833
18991
  }
@@ -18959,15 +19117,15 @@ function loadTemplateManifest(slug) {
18959
19117
  console.error("Not in a git repository. Run from the tutorials/ authoring repo.");
18960
19118
  process.exit(1);
18961
19119
  }
18962
- const templateDir = path24.join(resolveTemplatesDir(gitRoot), slug);
18963
- const manifestPath = path24.join(templateDir, "template.yaml");
18964
- if (!fs18.existsSync(manifestPath)) {
18965
- console.error(`template.yaml not found at ${path24.relative(gitRoot, manifestPath)}`);
19120
+ const templateDir = path25.join(resolveTemplatesDir(gitRoot), slug);
19121
+ const manifestPath = path25.join(templateDir, "template.yaml");
19122
+ if (!fs19.existsSync(manifestPath)) {
19123
+ console.error(`template.yaml not found at ${path25.relative(gitRoot, manifestPath)}`);
18966
19124
  process.exit(1);
18967
19125
  }
18968
19126
  let manifest;
18969
19127
  try {
18970
- manifest = templateYamlSchema2.parse(yaml10.load(fs18.readFileSync(manifestPath, "utf-8")));
19128
+ manifest = templateYamlSchema2.parse(yaml10.load(fs19.readFileSync(manifestPath, "utf-8")));
18971
19129
  } catch (err) {
18972
19130
  console.error(`Invalid template.yaml: ${err instanceof Error ? err.message : String(err)}`);
18973
19131
  process.exit(1);
@@ -18997,20 +19155,20 @@ async function runTemplatePush(positional) {
18997
19155
  const wayaiEntry = manifest.wayai.locales[locale];
18998
19156
  let wayaiFiles;
18999
19157
  if (wayaiEntry) {
19000
- const sliceDir = path24.resolve(templateDir, wayaiEntry.source);
19001
- if (!fs18.existsSync(sliceDir)) {
19158
+ const sliceDir = path25.resolve(templateDir, wayaiEntry.source);
19159
+ if (!fs19.existsSync(sliceDir)) {
19002
19160
  console.error(`wayai source not found for ${locale}: ${wayaiEntry.source} (resolved ${sliceDir})`);
19003
19161
  process.exit(1);
19004
19162
  }
19005
19163
  if (!isInsideTemplateDir(sliceDir, templateDir)) {
19006
19164
  console.warn(
19007
- `Note: ${locale} source points at a live hub (${wayaiEntry.source}); it can go stale on a hub recreate. Run \`wayai admin template freeze ${slug} --locale ${locale} --from ${path24.basename(sliceDir)}\` to commit a stable frozen slice.`
19165
+ `Note: ${locale} source points at a live hub (${wayaiEntry.source}); it can go stale on a hub recreate. Run \`wayai admin template freeze ${slug} --locale ${locale} --from ${path25.basename(sliceDir)}\` to commit a stable frozen slice.`
19008
19166
  );
19009
19167
  }
19010
19168
  wayaiFiles = readDirToFileMap(sliceDir);
19011
19169
  }
19012
- const readmePath = path24.join(templateDir, `README.${locale}.md`);
19013
- const readmeMarkdown = fs18.existsSync(readmePath) ? fs18.readFileSync(readmePath, "utf-8") : "";
19170
+ const readmePath = path25.join(templateDir, `README.${locale}.md`);
19171
+ const readmeMarkdown = fs19.existsSync(readmePath) ? fs19.readFileSync(readmePath, "utf-8") : "";
19014
19172
  locales[locale] = {
19015
19173
  readmeMarkdown,
19016
19174
  ...wayaiFiles && { wayaiFiles },
@@ -19021,9 +19179,9 @@ async function runTemplatePush(positional) {
19021
19179
  }
19022
19180
  let hero;
19023
19181
  if (manifest.hero) {
19024
- const heroPath = path24.resolve(templateDir, manifest.hero);
19025
- if (fs18.existsSync(heroPath)) {
19026
- hero = { filename: path24.basename(heroPath), dataBase64: fs18.readFileSync(heroPath).toString("base64") };
19182
+ const heroPath = path25.resolve(templateDir, manifest.hero);
19183
+ if (fs19.existsSync(heroPath)) {
19184
+ hero = { filename: path25.basename(heroPath), dataBase64: fs19.readFileSync(heroPath).toString("base64") };
19027
19185
  } else {
19028
19186
  console.error(`Warning: hero not found at ${manifest.hero}; skipping.`);
19029
19187
  }
@@ -19049,7 +19207,7 @@ async function runTemplatePush(positional) {
19049
19207
  }
19050
19208
  }
19051
19209
  function isInsideTemplateDir(dest, templateDir) {
19052
- return dest === templateDir || dest.startsWith(templateDir + path24.sep);
19210
+ return dest === templateDir || dest.startsWith(templateDir + path25.sep);
19053
19211
  }
19054
19212
  async function runTemplateFreeze(positional, flagArgs) {
19055
19213
  const slug = positional[0];
@@ -19110,7 +19268,7 @@ async function runTemplateFreeze(positional, flagArgs) {
19110
19268
  process.exit(1);
19111
19269
  }
19112
19270
  const entry = manifest.wayai.locales[targetLocale];
19113
- const dest = path24.resolve(templateDir, entry.source);
19271
+ const dest = path25.resolve(templateDir, entry.source);
19114
19272
  if (!isInsideTemplateDir(dest, templateDir) || dest === templateDir) {
19115
19273
  console.error(
19116
19274
  `source for "${targetLocale}" must be a committed path inside ${slug}/ (e.g. "./${targetLocale}/slice"), but resolved to:
@@ -19129,7 +19287,7 @@ Set it to a subdir of the template folder and re-run freeze.`
19129
19287
  const hubs = scanWorkspaceHubs(hubsDir);
19130
19288
  if (hubs.length) {
19131
19289
  console.error("Available hubs:");
19132
- for (const h of hubs) console.error(` ${path24.basename(h.hubFolder)} (${h.hubId})`);
19290
+ for (const h of hubs) console.error(` ${path25.basename(h.hubFolder)} (${h.hubId})`);
19133
19291
  }
19134
19292
  console.error(`
19135
19293
  Pass --from <folder|uuid>${selector ? "." : " or run `wayai use <hub>` first."}`);
@@ -19137,12 +19295,12 @@ Pass --from <folder|uuid>${selector ? "." : " or run `wayai use <hub>` first."}`
19137
19295
  }
19138
19296
  const liveFiles = readDirToFileMap(hubFolder);
19139
19297
  if (Object.keys(liveFiles).length === 0) {
19140
- console.error(`Source hub folder has no files to freeze: ${path24.relative(gitRoot, hubFolder)}`);
19298
+ console.error(`Source hub folder has no files to freeze: ${path25.relative(gitRoot, hubFolder)}`);
19141
19299
  process.exit(1);
19142
19300
  }
19143
19301
  const sanitized = sanitizeWayaiSliceFiles(liveFiles);
19144
- const relDest = path24.relative(gitRoot, dest);
19145
- const relSrc = path24.relative(gitRoot, hubFolder);
19302
+ const relDest = path25.relative(gitRoot, dest);
19303
+ const relSrc = path25.relative(gitRoot, hubFolder);
19146
19304
  if (dryRun) {
19147
19305
  const existing = new Set(listDirRelFiles(dest));
19148
19306
  const nextKeys = new Set(Object.keys(sanitized));
@@ -19202,7 +19360,7 @@ async function runTemplatePull2(positional, flagArgs) {
19202
19360
  console.log(JSON.stringify(detail, null, 2));
19203
19361
  return;
19204
19362
  }
19205
- const target = outDir ? path24.resolve(outDir) : path24.join(process.cwd(), "template-store-pull", slug);
19363
+ const target = outDir ? path25.resolve(outDir) : path25.join(process.cwd(), "template-store-pull", slug);
19206
19364
  const written = writeFileMap(target, detail.files);
19207
19365
  console.log(`Pulled "${slug}" from the store \u2192 ${target} (${written.length} file${written.length === 1 ? "" : "s"}).`);
19208
19366
  const uses = detail.uses ?? [];
@@ -19225,13 +19383,13 @@ async function runSkillInstall(positional) {
19225
19383
  throw err;
19226
19384
  }
19227
19385
  const root = findGitRoot() ?? process.cwd();
19228
- const present = HARNESS_SKILL_DIRS.filter((dir) => fs18.existsSync(path24.join(root, dir)));
19386
+ const present = HARNESS_SKILL_DIRS.filter((dir) => fs19.existsSync(path25.join(root, dir)));
19229
19387
  const targets = present.length > 0 ? present : HARNESS_SKILL_DIRS;
19230
19388
  const fileCount = Object.keys(res.files).length;
19231
19389
  const relDirs = targets.map((harness) => {
19232
- const targetDir = path24.join(root, harness, "skills", name);
19390
+ const targetDir = path25.join(root, harness, "skills", name);
19233
19391
  writeFileMap(targetDir, res.files);
19234
- return `${path24.relative(root, targetDir)}/`;
19392
+ return `${path25.relative(root, targetDir)}/`;
19235
19393
  });
19236
19394
  console.log(`Installed skill "${name}" (${fileCount} file${fileCount === 1 ? "" : "s"}) \u2192 ${relDirs.join(", ")}`);
19237
19395
  console.log("Reload your agent (e.g. restart Claude Code) to pick up the skill.");
@@ -19971,7 +20129,7 @@ Usage:
19971
20129
 
19972
20130
  Sources:
19973
20131
  do Live DO SQLite (existing conversation, hub config, etc.).
19974
- analytics ClickHouse projections (conversation, message, billing_event, schedule_event).
20132
+ analytics ClickHouse projections (conversation, message, schedule_event).
19975
20133
  archive R2 archive blob \u2014 canonical content for ended conversations after DO cleanup.
19976
20134
  observability R2 LLM observability \u2014 per-message OTel GenAI records (prompts, completions,
19977
20135
  tool calls, tokens, latency). Default lists all records for the conversation;
@@ -20486,7 +20644,7 @@ init_skill_version();
20486
20644
  import { exec } from "child_process";
20487
20645
  var REFRESH_TIMEOUT_MS = 1e4;
20488
20646
  function refreshCliCache() {
20489
- return new Promise((resolve5) => {
20647
+ return new Promise((resolve4) => {
20490
20648
  exec("npm view @wayai/cli version", { timeout: REFRESH_TIMEOUT_MS }, (err, stdout) => {
20491
20649
  if (!err) {
20492
20650
  const latest = stdout.trim();
@@ -20497,7 +20655,7 @@ function refreshCliCache() {
20497
20655
  }
20498
20656
  }
20499
20657
  }
20500
- resolve5();
20658
+ resolve4();
20501
20659
  });
20502
20660
  });
20503
20661
  }
@@ -20523,8 +20681,8 @@ async function refreshSkillCache() {
20523
20681
  }
20524
20682
  async function refreshAdminSkillCache() {
20525
20683
  let timer;
20526
- const deadline = new Promise((resolve5) => {
20527
- timer = setTimeout(resolve5, REFRESH_TIMEOUT_MS);
20684
+ const deadline = new Promise((resolve4) => {
20685
+ timer = setTimeout(resolve4, REFRESH_TIMEOUT_MS);
20528
20686
  });
20529
20687
  await Promise.race([deadline, fetchAndCacheAdminSkillVersion().catch(() => {
20530
20688
  })]);
@@ -20688,6 +20846,11 @@ async function main() {
20688
20846
  await pushCommand2(args);
20689
20847
  break;
20690
20848
  }
20849
+ case "create": {
20850
+ const { createCommand: createCommand2 } = await Promise.resolve().then(() => (init_create(), create_exports));
20851
+ await createCommand2(args);
20852
+ break;
20853
+ }
20691
20854
  case "diff": {
20692
20855
  const { diffCommand: diffCommand2 } = await Promise.resolve().then(() => (init_diff(), diff_exports));
20693
20856
  await diffCommand2(args);
@@ -20858,6 +21021,7 @@ Commands:
20858
21021
  set-connection-credential Set a connection's credential directly (org link or --field/--stdin), preview or production
20859
21022
  pull Fetch hub config and write local files (also mirrors the linked production hub read-only)
20860
21023
  push Parse local files, show diff, sync to preview (creates hub if new)
21024
+ create [folder] Explicitly create a new hub from an idless folder, then push (--label to name the preview)
20861
21025
  diff Dry-run diff of local files vs the platform (--production diffs vs the linked production hub)
20862
21026
  replicate Clone a hub into a new sibling preview (--label to name it)
20863
21027
  relabel Set a preview hub's label (--clear to remove it)
@@ -20890,7 +21054,7 @@ Flags:
20890
21054
  --yes, -y Skip confirmation prompts (useful for CI and scripting)
20891
21055
  --hub <uuid|name> Target hub when the workspace has more than one (push, pull, diff, replicate, relabel, publish)
20892
21056
  --production Diff local preview files against the linked production hub (diff)
20893
- --label <name> Preview label \u2014 for the new sibling (replicate) or a brand-new hub (push on create)
21057
+ --label <name> Preview label \u2014 for the new sibling (replicate) or a brand-new hub (create, or push on create)
20894
21058
  --clear Remove the preview label (relabel)
20895
21059
  --name <name> Credential name (create-credential; target for update-credential)
20896
21060
  --type <auth-type> Auth type: "api_key", "bearer", "basic_auth" (create-credential)