@wayai/cli 0.3.89 → 0.3.91

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, path26) {
168
+ function addApiBreadcrumb(method, path27) {
169
169
  if (!initialized) return;
170
170
  Sentry.addBreadcrumb({
171
171
  category: "http",
172
- message: `${method} ${path26}`,
172
+ message: `${method} ${path27}`,
173
173
  level: "info"
174
174
  });
175
175
  }
@@ -231,9 +231,9 @@ var init_api_client = __esm({
231
231
  ApiError = class extends Error {
232
232
  status;
233
233
  body;
234
- constructor(method, path26, status, body) {
234
+ constructor(method, path27, status, body) {
235
235
  const safeBody = redactSecrets(body);
236
- super(`API request failed: ${method} ${path26} (${status}): ${safeBody}`);
236
+ super(`API request failed: ${method} ${path27} (${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(path26, opts) {
380
- const params = new URLSearchParams({ path: path26 });
379
+ async lookup(path27, opts) {
380
+ const params = new URLSearchParams({ path: path27 });
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 path26 = `/api/archive/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}/sandbox`;
769
- addApiBreadcrumb("GET", path26);
770
- const url = `${this.apiUrl}${path26}`;
768
+ const path27 = `/api/archive/${encodeURIComponent(hubId)}/conversations/${encodeURIComponent(conversationId)}/sandbox`;
769
+ addApiBreadcrumb("GET", path27);
770
+ const url = `${this.apiUrl}${path27}`;
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", path26, response.status, await response.text());
784
+ throw new ApiError("GET", path27, 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, path26, body) {
825
- addApiBreadcrumb(method, path26);
826
- const url = `${this.apiUrl}${path26}`;
824
+ async request(method, path27, body) {
825
+ addApiBreadcrumb(method, path27);
826
+ const url = `${this.apiUrl}${path27}`;
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, path26, response.status, errorBody);
850
+ throw new ApiError(method, path27, 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: path26, errorMaps, issueData } = params;
1286
- const fullPath = [...path26, ...issueData.path || []];
1285
+ const { data, path: path27, errorMaps, issueData } = params;
1286
+ const fullPath = [...path27, ...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, path26, key) {
1597
+ constructor(parent, value, path27, key) {
1598
1598
  this._cachedPath = [];
1599
1599
  this.parent = parent;
1600
1600
  this.data = value;
1601
- this._path = path26;
1601
+ this._path = path27;
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, path26, errors, opts = {}) {
5055
+ function validateSchema(schema, path27, 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: path26 || "<root>",
5060
+ path: path27 || "<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, path26, errors, opts = {}) {
5065
5065
  }
5066
5066
  if (!isRecord(schema)) {
5067
5067
  errors.push({
5068
- path: path26,
5068
+ path: path27,
5069
5069
  message: `expected object, got ${schema === null ? "null" : typeof schema}`
5070
5070
  });
5071
5071
  return;
@@ -5073,14 +5073,14 @@ function validateSchema(schema, path26, errors, opts = {}) {
5073
5073
  if (opts.isRoot) {
5074
5074
  if ("type" in schema && schema.type !== "object") {
5075
5075
  errors.push({
5076
- path: path26 ? `${path26}.type` : "type",
5076
+ path: path27 ? `${path27}.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: `${path26}.type`,
5083
+ path: `${path27}.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, path26, errors, opts = {}) {
5089
5089
  if (typeof e === "string") {
5090
5090
  const isPlaceholder = PLACEHOLDER_TOKENS.includes(e);
5091
5091
  errors.push({
5092
- path: `${path26}.enum`,
5092
+ path: `${path27}.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: `${path26}.enum`,
5098
+ path: `${path27}.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: `${path26}.enum`,
5103
+ path: `${path27}.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: `${path26}.enum[${i}]`,
5110
+ path: `${path27}.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, path26, 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: `${path26}.${key}`,
5120
+ path: `${path27}.${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, path26, errors, opts = {}) {
5126
5126
  if ("properties" in schema) {
5127
5127
  if (!isRecord(schema.properties)) {
5128
5128
  errors.push({
5129
- path: `${path26}.properties`,
5129
+ path: `${path27}.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, `${path26}.properties.${propName}`, errors, { depth: depth + 1 });
5134
+ validateSchema(propSchema, `${path27}.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, `${path26}.items[${i}]`, errors, { depth: depth + 1 }));
5140
+ schema.items.forEach((sub, i) => validateSchema(sub, `${path27}.items[${i}]`, errors, { depth: depth + 1 }));
5141
5141
  } else {
5142
- validateSchema(schema.items, `${path26}.items`, errors, { depth: depth + 1 });
5142
+ validateSchema(schema.items, `${path27}.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], `${path26}.${key}`, errors, { depth: depth + 1 });
5147
+ validateSchema(schema[key], `${path27}.${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, `${path26}.${key}[${i}]`, errors, { depth: depth + 1 }));
5153
+ list.forEach((sub, i) => validateSchema(sub, `${path27}.${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, `${path26}.${key}.${name}`, errors, { depth: depth + 1 });
5160
+ validateSchema(sub, `${path27}.${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 = `${path26}.${k}`;
5167
+ const fieldPath = `${path27}.${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(path26) {
5324
- if (path26.length === 0 || path26.length > 300) return false;
5325
- if (path26.startsWith("/") || path26.includes("\\")) return false;
5326
- const segments = path26.split("/");
5323
+ function isSafeTemplatePath(path27) {
5324
+ if (path27.length === 0 || path27.length > 300) return false;
5325
+ if (path27.startsWith("/") || path27.includes("\\")) return false;
5326
+ const segments = path27.split("/");
5327
5327
  return segments.every(
5328
5328
  (seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
5329
5329
  );
@@ -7459,7 +7459,6 @@ var init_dist = __esm({
7459
7459
  });
7460
7460
  dataExplorerDebugAnalyticsTable = external_exports.enum([
7461
7461
  "conversation",
7462
- "message",
7463
7462
  "schedule_event"
7464
7463
  ]);
7465
7464
  debugUuid = external_exports.string().uuid();
@@ -8795,9 +8794,9 @@ function getVersionCachePath(filename = CLI_CACHE_FILE) {
8795
8794
  }
8796
8795
  function readVersionCache(filename = CLI_CACHE_FILE) {
8797
8796
  try {
8798
- const path26 = getVersionCachePath(filename);
8799
- if (!existsSync4(path26)) return null;
8800
- const parsed = JSON.parse(readFileSync5(path26, "utf-8"));
8797
+ const path27 = getVersionCachePath(filename);
8798
+ if (!existsSync4(path27)) return null;
8799
+ const parsed = JSON.parse(readFileSync5(path27, "utf-8"));
8801
8800
  if (typeof parsed.lastCheck !== "number") return null;
8802
8801
  if (parsed.latest !== null && typeof parsed.latest !== "string") return null;
8803
8802
  return parsed;
@@ -8817,10 +8816,10 @@ function isVersionCacheStale(filename = CLI_CACHE_FILE, maxAgeMs = MAX_AGE_24H_M
8817
8816
  return Date.now() - cache.lastCheck > maxAgeMs;
8818
8817
  }
8819
8818
  function writeVersionCache(filename, cache) {
8820
- const path26 = getVersionCachePath(filename);
8821
- const dir = dirname3(path26);
8819
+ const path27 = getVersionCachePath(filename);
8820
+ const dir = dirname3(path27);
8822
8821
  if (!existsSync4(dir)) mkdirSync(dir, { recursive: true });
8823
- writeFileSync2(path26, JSON.stringify(cache));
8822
+ writeFileSync2(path27, JSON.stringify(cache));
8824
8823
  }
8825
8824
  function touchVersionCache(filename) {
8826
8825
  writeVersionCache(filename, { lastCheck: Date.now(), latest: readVersionCache(filename)?.latest ?? null });
@@ -8859,14 +8858,14 @@ function parseFrontmatterVersion(content) {
8859
8858
  function findInstalledSkills(projectRoot, paths = SKILL_INSTALL_PATHS) {
8860
8859
  const found = [];
8861
8860
  for (const rel of paths) {
8862
- const path26 = join7(projectRoot, rel);
8863
- if (!existsSync5(path26)) continue;
8861
+ const path27 = join7(projectRoot, rel);
8862
+ if (!existsSync5(path27)) continue;
8864
8863
  let version = null;
8865
8864
  try {
8866
- version = parseFrontmatterVersion(readFileSync6(path26, "utf-8"));
8865
+ version = parseFrontmatterVersion(readFileSync6(path27, "utf-8"));
8867
8866
  } catch {
8868
8867
  }
8869
- found.push({ path: path26, version });
8868
+ found.push({ path: path27, version });
8870
8869
  }
8871
8870
  return found;
8872
8871
  }
@@ -10099,6 +10098,85 @@ var init_constants = __esm({
10099
10098
  }
10100
10099
  });
10101
10100
 
10101
+ // src/lib/workspace-files.ts
10102
+ import * as fs8 from "fs";
10103
+ import * as path9 from "path";
10104
+ function perHubAgentsMd(hubFolderName) {
10105
+ return [
10106
+ `# ${hubFolderName}`,
10107
+ "",
10108
+ "Notes about THIS hub that the config files (hub.yaml, agents/) don't capture:",
10109
+ "why it exists, key decisions and the reasons behind them, business rules that",
10110
+ "only apply here, terminology, integration quirks.",
10111
+ "",
10112
+ "Keep it short and about *why / what is different* \u2014 platform mechanics live in",
10113
+ "the WayAI skill. Fill this in as you learn about the hub; delete this",
10114
+ "placeholder once you do.",
10115
+ ""
10116
+ ].join("\n");
10117
+ }
10118
+ function isWorkspace(gitRoot) {
10119
+ if (fs8.existsSync(path9.join(gitRoot, ".wayai.yaml"))) return true;
10120
+ return isDirectory(resolveLayout(gitRoot).hubsDir);
10121
+ }
10122
+ function writeIfAbsent(filePath, content) {
10123
+ if (fs8.existsSync(filePath)) return null;
10124
+ fs8.writeFileSync(filePath, content, "utf-8");
10125
+ return path9.basename(filePath);
10126
+ }
10127
+ function ensureWorkspaceFiles(gitRoot) {
10128
+ if (!isWorkspace(gitRoot)) return [];
10129
+ const created = [];
10130
+ const agents = writeIfAbsent(path9.join(gitRoot, "AGENTS.md"), ROOT_AGENTS_MD);
10131
+ if (agents) created.push(agents);
10132
+ const claude = writeIfAbsent(path9.join(gitRoot, "CLAUDE.md"), CLAUDE_MD_SHIM);
10133
+ if (claude) created.push(claude);
10134
+ return created;
10135
+ }
10136
+ var REKOR_SKILL_INSTALL_COMMAND, CLAUDE_MD_SHIM, ROOT_AGENTS_MD;
10137
+ var init_workspace_files = __esm({
10138
+ "src/lib/workspace-files.ts"() {
10139
+ "use strict";
10140
+ init_constants();
10141
+ init_layout();
10142
+ REKOR_SKILL_INSTALL_COMMAND = SKILL_INSTALL_COMMAND.replace(
10143
+ "wayai-pro/wayai-skill",
10144
+ "wayai-pro/rekor-skill"
10145
+ );
10146
+ CLAUDE_MD_SHIM = "@AGENTS.md\n";
10147
+ ROOT_AGENTS_MD = [
10148
+ "# Working with WayAI and Rekor",
10149
+ "",
10150
+ "WayAI is the layer that talks to people across channels; Rekor is the data",
10151
+ "layer (system of record) behind it. They are used together.",
10152
+ "",
10153
+ "## At the start of every session",
10154
+ "",
10155
+ "1. Check for updates first. Make sure both skills and both CLIs are current,",
10156
+ " and update whatever is not:",
10157
+ ` - WayAI skill: \`wayai status\` \u2192 if newer, \`${SKILL_INSTALL_COMMAND}\``,
10158
+ ` - Rekor skill: \`rekor status\` \u2192 if newer, \`${REKOR_SKILL_INSTALL_COMMAND}\``,
10159
+ " - CLIs: `wayai update` and `rekor update`",
10160
+ "2. Load both the WayAI and Rekor skills at the start of every session \u2014 every",
10161
+ " time, even for a quick task. They hold the real instructions for everything",
10162
+ " else.",
10163
+ "",
10164
+ "More detail if you need it:",
10165
+ "- WayAI: https://www.wayai.pro/docs/get-started",
10166
+ "- Rekor: https://rekor.pro/en/docs/get-started",
10167
+ "",
10168
+ "## When helping the person you are working with",
10169
+ "",
10170
+ "- They may be new to WayAI and Rekor \u2014 use plain language, not jargon.",
10171
+ "- Don't explain things they didn't ask about. Only if they seem stuck or ask",
10172
+ " what something means, give a one-line answer, then move on \u2014 don't turn",
10173
+ " replies into tutorials.",
10174
+ "- Keep answers short and to the point.",
10175
+ ""
10176
+ ].join("\n");
10177
+ }
10178
+ });
10179
+
10102
10180
  // src/commands/init.ts
10103
10181
  var init_exports = {};
10104
10182
  __export(init_exports, {
@@ -10108,12 +10186,12 @@ __export(init_exports, {
10108
10186
  parseArgs: () => parseArgs3
10109
10187
  });
10110
10188
  import { mkdirSync as mkdirSync5 } from "fs";
10111
- import path9 from "path";
10189
+ import path10 from "path";
10112
10190
  function ensureHubsDir(gitRoot) {
10113
10191
  const hubsDir = resolveLayout(gitRoot).hubsDir;
10114
10192
  if (isDirectory(hubsDir)) return null;
10115
10193
  mkdirSync5(hubsDir, { recursive: true });
10116
- return `${path9.relative(gitRoot, hubsDir)}/`;
10194
+ return `${path10.relative(gitRoot, hubsDir)}/`;
10117
10195
  }
10118
10196
  function parseArgs3(args2) {
10119
10197
  let orgId;
@@ -10156,6 +10234,9 @@ async function initCommand(args2) {
10156
10234
  if (createdDir) {
10157
10235
  console.log(`Created ${createdDir}`);
10158
10236
  }
10237
+ for (const file of ensureWorkspaceFiles(gitRoot)) {
10238
+ console.log(`Created ${file}`);
10239
+ }
10159
10240
  }
10160
10241
  console.log(
10161
10242
  `Run \`${SKILL_INSTALL_CMD}\` to install the WayAI skill in your AI harness, then \`wayai pull\` to fetch hub configuration.`
@@ -10236,6 +10317,7 @@ var init_init = __esm({
10236
10317
  init_repo_config();
10237
10318
  init_workspace();
10238
10319
  init_layout();
10320
+ init_workspace_files();
10239
10321
  init_utils();
10240
10322
  init_constants();
10241
10323
  SKILL_INSTALL_CMD = SKILL_INSTALL_COMMAND;
@@ -10243,8 +10325,8 @@ var init_init = __esm({
10243
10325
  });
10244
10326
 
10245
10327
  // src/lib/resource-files.ts
10246
- import * as fs8 from "fs";
10247
- import * as path10 from "path";
10328
+ import * as fs9 from "fs";
10329
+ import * as path11 from "path";
10248
10330
  import * as crypto3 from "crypto";
10249
10331
  function isBinaryFile(filename) {
10250
10332
  const ext = filename.split(".").pop()?.toLowerCase() || "";
@@ -10290,14 +10372,14 @@ function computeHash(data) {
10290
10372
  }
10291
10373
  function scanResourceFiles(dir, prefix = "") {
10292
10374
  const files = [];
10293
- const entries = fs8.readdirSync(dir, { withFileTypes: true });
10375
+ const entries = fs9.readdirSync(dir, { withFileTypes: true });
10294
10376
  for (const entry of entries) {
10295
10377
  const relPath = prefix ? `${prefix}/${entry.name}` : entry.name;
10296
10378
  if (entry.isDirectory()) {
10297
- files.push(...scanResourceFiles(path10.join(dir, entry.name), relPath));
10379
+ files.push(...scanResourceFiles(path11.join(dir, entry.name), relPath));
10298
10380
  } else if (entry.isFile()) {
10299
- const fullPath = path10.join(dir, entry.name);
10300
- const stat = fs8.statSync(fullPath);
10381
+ const fullPath = path11.join(dir, entry.name);
10382
+ const stat = fs9.statSync(fullPath);
10301
10383
  if (stat.size > MAX_RESOURCE_FILE_SIZE2) {
10302
10384
  console.warn(` Warning: skipping ${relPath} (${(stat.size / 1024 / 1024).toFixed(1)}MB exceeds 10MB limit)`);
10303
10385
  continue;
@@ -10307,7 +10389,7 @@ function scanResourceFiles(dir, prefix = "") {
10307
10389
  mime_type: guessMimeType(entry.name),
10308
10390
  file_size: stat.size
10309
10391
  };
10310
- const data = fs8.readFileSync(fullPath);
10392
+ const data = fs9.readFileSync(fullPath);
10311
10393
  fileEntry.hash = computeHash(data);
10312
10394
  if (isBinaryFile(entry.name)) {
10313
10395
  fileEntry.content_base64 = data.toString("base64");
@@ -10321,37 +10403,37 @@ function scanResourceFiles(dir, prefix = "") {
10321
10403
  }
10322
10404
  function writeResourceFileTree(resDir, files) {
10323
10405
  if (files.length === 0) {
10324
- if (fs8.existsSync(resDir)) cleanOrphanFiles(resDir, "", /* @__PURE__ */ new Set());
10406
+ if (fs9.existsSync(resDir)) cleanOrphanFiles(resDir, "", /* @__PURE__ */ new Set());
10325
10407
  return;
10326
10408
  }
10327
10409
  const writtenPaths = /* @__PURE__ */ new Set();
10328
10410
  for (const file of files) {
10329
- const filePath = path10.join(resDir, file.path);
10330
- if (!filePath.startsWith(resDir + path10.sep) && filePath !== resDir) {
10411
+ const filePath = path11.join(resDir, file.path);
10412
+ if (!filePath.startsWith(resDir + path11.sep) && filePath !== resDir) {
10331
10413
  console.warn(` Warning: skipping ${file.path} (path traversal detected)`);
10332
10414
  continue;
10333
10415
  }
10334
- const fileDir = path10.dirname(filePath);
10335
- if (!fs8.existsSync(fileDir)) fs8.mkdirSync(fileDir, { recursive: true });
10416
+ const fileDir = path11.dirname(filePath);
10417
+ if (!fs9.existsSync(fileDir)) fs9.mkdirSync(fileDir, { recursive: true });
10336
10418
  writtenPaths.add(file.path);
10337
10419
  if (file.content !== void 0) {
10338
- fs8.writeFileSync(filePath, file.content, "utf-8");
10420
+ fs9.writeFileSync(filePath, file.content, "utf-8");
10339
10421
  } else if (file.content_base64) {
10340
- fs8.writeFileSync(filePath, Buffer.from(file.content_base64, "base64"));
10422
+ fs9.writeFileSync(filePath, Buffer.from(file.content_base64, "base64"));
10341
10423
  }
10342
10424
  }
10343
- if (fs8.existsSync(resDir)) cleanOrphanFiles(resDir, "", writtenPaths);
10425
+ if (fs9.existsSync(resDir)) cleanOrphanFiles(resDir, "", writtenPaths);
10344
10426
  }
10345
10427
  function cleanOrphanFiles(dir, prefix, writtenPaths) {
10346
- const entries = fs8.readdirSync(dir, { withFileTypes: true });
10428
+ const entries = fs9.readdirSync(dir, { withFileTypes: true });
10347
10429
  for (const entry of entries) {
10348
10430
  const relPath = prefix ? `${prefix}/${entry.name}` : entry.name;
10349
- const fullPath = path10.join(dir, entry.name);
10431
+ const fullPath = path11.join(dir, entry.name);
10350
10432
  if (entry.isDirectory()) {
10351
10433
  cleanOrphanFiles(fullPath, relPath, writtenPaths);
10352
- if (fs8.readdirSync(fullPath).length === 0) fs8.rmdirSync(fullPath);
10434
+ if (fs9.readdirSync(fullPath).length === 0) fs9.rmdirSync(fullPath);
10353
10435
  } else if (!writtenPaths.has(relPath)) {
10354
- fs8.unlinkSync(fullPath);
10436
+ fs9.unlinkSync(fullPath);
10355
10437
  }
10356
10438
  }
10357
10439
  }
@@ -10360,8 +10442,8 @@ async function downloadBinaryFiles(resDir, files) {
10360
10442
  for (const file of files) {
10361
10443
  if (!file.download_url || file.content !== void 0) continue;
10362
10444
  try {
10363
- const filePath = path10.join(resDir, file.path);
10364
- if (!filePath.startsWith(resDir + path10.sep) && filePath !== resDir) {
10445
+ const filePath = path11.join(resDir, file.path);
10446
+ if (!filePath.startsWith(resDir + path11.sep) && filePath !== resDir) {
10365
10447
  console.warn(` Warning: skipping ${file.path} (path traversal detected)`);
10366
10448
  continue;
10367
10449
  }
@@ -10371,9 +10453,9 @@ async function downloadBinaryFiles(resDir, files) {
10371
10453
  continue;
10372
10454
  }
10373
10455
  const buffer = Buffer.from(await response.arrayBuffer());
10374
- const fileDir = path10.dirname(filePath);
10375
- if (!fs8.existsSync(fileDir)) fs8.mkdirSync(fileDir, { recursive: true });
10376
- fs8.writeFileSync(filePath, buffer);
10456
+ const fileDir = path11.dirname(filePath);
10457
+ if (!fs9.existsSync(fileDir)) fs9.mkdirSync(fileDir, { recursive: true });
10458
+ fs9.writeFileSync(filePath, buffer);
10377
10459
  count++;
10378
10460
  } catch (err) {
10379
10461
  console.warn(` Warning: failed to download ${file.path} (${err instanceof Error ? err.message : String(err)})`);
@@ -10410,8 +10492,8 @@ var init_resource_files = __esm({
10410
10492
  });
10411
10493
 
10412
10494
  // src/lib/yaml-writer.ts
10413
- import * as fs9 from "fs";
10414
- import * as path11 from "path";
10495
+ import * as fs10 from "fs";
10496
+ import * as path12 from "path";
10415
10497
  import * as yaml4 from "js-yaml";
10416
10498
  function buildEvalYamlObject(evalEntry, slug) {
10417
10499
  const out = {};
@@ -10444,43 +10526,43 @@ function buildEvalYamlObject(evalEntry, slug) {
10444
10526
  }
10445
10527
  return out;
10446
10528
  }
10447
- function writeHubFolder(hubFolder, payload) {
10448
- const agentsDir = path11.join(hubFolder, "agents");
10449
- if (!fs9.existsSync(hubFolder)) {
10450
- fs9.mkdirSync(hubFolder, { recursive: true });
10529
+ function writeHubFolder(hubFolder, payload, options = {}) {
10530
+ const agentsDir = path12.join(hubFolder, "agents");
10531
+ if (!fs10.existsSync(hubFolder)) {
10532
+ fs10.mkdirSync(hubFolder, { recursive: true });
10451
10533
  }
10452
- if (!fs9.existsSync(agentsDir)) {
10453
- fs9.mkdirSync(agentsDir, { recursive: true });
10534
+ if (!fs10.existsSync(agentsDir)) {
10535
+ fs10.mkdirSync(agentsDir, { recursive: true });
10454
10536
  }
10455
10537
  const yamlPayload = buildYamlPayload(payload);
10456
10538
  const agentFiles = extractAgentFiles(payload);
10457
10539
  const yamlContent = yaml4.dump(yamlPayload, YAML_DUMP_OPTIONS);
10458
- fs9.writeFileSync(path11.join(hubFolder, "hub.yaml"), yamlContent, "utf-8");
10459
- const claudeShimPath = path11.join(hubFolder, "CLAUDE.md");
10460
- if (!fs9.existsSync(claudeShimPath)) {
10461
- fs9.writeFileSync(claudeShimPath, "@AGENTS.md\n", "utf-8");
10540
+ fs10.writeFileSync(path12.join(hubFolder, "hub.yaml"), yamlContent, "utf-8");
10541
+ if (options.seedAgentContext ?? true) {
10542
+ writeIfAbsent(path12.join(hubFolder, "AGENTS.md"), perHubAgentsMd(path12.basename(hubFolder)));
10543
+ writeIfAbsent(path12.join(hubFolder, "CLAUDE.md"), CLAUDE_MD_SHIM);
10462
10544
  }
10463
- const oldYamlPath = path11.join(hubFolder, "wayai.yaml");
10464
- if (fs9.existsSync(oldYamlPath)) {
10465
- fs9.unlinkSync(oldYamlPath);
10545
+ const oldYamlPath = path12.join(hubFolder, "wayai.yaml");
10546
+ if (fs10.existsSync(oldYamlPath)) {
10547
+ fs10.unlinkSync(oldYamlPath);
10466
10548
  }
10467
10549
  const yamlSlugs = writeAgentYamlFiles(agentsDir, payload.agents || []);
10468
10550
  const mdSlugs = /* @__PURE__ */ new Set();
10469
10551
  for (const { slug, content } of agentFiles) {
10470
10552
  mdSlugs.add(slug);
10471
- fs9.writeFileSync(path11.join(agentsDir, `${slug}.md`), content, "utf-8");
10553
+ fs10.writeFileSync(path12.join(agentsDir, `${slug}.md`), content, "utf-8");
10472
10554
  }
10473
- const existingFiles = fs9.readdirSync(agentsDir);
10555
+ const existingFiles = fs10.readdirSync(agentsDir);
10474
10556
  for (const file of existingFiles) {
10475
10557
  if (file.endsWith(".yaml")) {
10476
10558
  const slug = file.slice(0, -5);
10477
10559
  if (!yamlSlugs.has(slug)) {
10478
- fs9.unlinkSync(path11.join(agentsDir, file));
10560
+ fs10.unlinkSync(path12.join(agentsDir, file));
10479
10561
  }
10480
10562
  } else if (file.endsWith(".md")) {
10481
10563
  const slug = file.slice(0, -3);
10482
10564
  if (!mdSlugs.has(slug)) {
10483
- fs9.unlinkSync(path11.join(agentsDir, file));
10565
+ fs10.unlinkSync(path12.join(agentsDir, file));
10484
10566
  }
10485
10567
  }
10486
10568
  }
@@ -10491,10 +10573,10 @@ function writeHubFolder(hubFolder, payload) {
10491
10573
  function setPreviewLabelInHubYaml(hubFolder, label) {
10492
10574
  const yamlPath = resolveHubYamlPath(hubFolder);
10493
10575
  if (!yamlPath) return;
10494
- const obj = yaml4.load(fs9.readFileSync(yamlPath, "utf-8")) ?? {};
10576
+ const obj = yaml4.load(fs10.readFileSync(yamlPath, "utf-8")) ?? {};
10495
10577
  if (label) obj.preview_label = label;
10496
10578
  else delete obj.preview_label;
10497
- fs9.writeFileSync(yamlPath, yaml4.dump(obj, YAML_DUMP_OPTIONS), "utf-8");
10579
+ fs10.writeFileSync(yamlPath, yaml4.dump(obj, YAML_DUMP_OPTIONS), "utf-8");
10498
10580
  }
10499
10581
  function buildYamlPayload(payload) {
10500
10582
  const result = {
@@ -10540,7 +10622,7 @@ function writeAgentYamlFiles(agentsDir, agents) {
10540
10622
  const entry = { ...agent };
10541
10623
  delete entry.instructions;
10542
10624
  const yamlContent = yaml4.dump(entry, YAML_DUMP_OPTIONS);
10543
- fs9.writeFileSync(path11.join(agentsDir, `${slug}.yaml`), yamlContent, "utf-8");
10625
+ fs10.writeFileSync(path12.join(agentsDir, `${slug}.yaml`), yamlContent, "utf-8");
10544
10626
  }
10545
10627
  return slugs;
10546
10628
  }
@@ -10557,65 +10639,65 @@ function extractAgentFiles(payload) {
10557
10639
  return files;
10558
10640
  }
10559
10641
  function writeEvalYamlFiles(hubFolder, evals) {
10560
- const evalsDir = path11.join(hubFolder, "evals");
10642
+ const evalsDir = path12.join(hubFolder, "evals");
10561
10643
  if (evals.length === 0) {
10562
- if (fs9.existsSync(evalsDir)) {
10644
+ if (fs10.existsSync(evalsDir)) {
10563
10645
  cleanEvalOrphans(evalsDir, /* @__PURE__ */ new Set());
10564
10646
  try {
10565
- if (fs9.readdirSync(evalsDir).length === 0) fs9.rmdirSync(evalsDir);
10647
+ if (fs10.readdirSync(evalsDir).length === 0) fs10.rmdirSync(evalsDir);
10566
10648
  } catch {
10567
10649
  }
10568
10650
  }
10569
10651
  return;
10570
10652
  }
10571
- if (!fs9.existsSync(evalsDir)) {
10572
- fs9.mkdirSync(evalsDir, { recursive: true });
10653
+ if (!fs10.existsSync(evalsDir)) {
10654
+ fs10.mkdirSync(evalsDir, { recursive: true });
10573
10655
  }
10574
10656
  const writtenRelPaths = /* @__PURE__ */ new Set();
10575
10657
  for (const evalEntry of evals) {
10576
10658
  const slug = slugify(evalEntry.name);
10577
10659
  const setName = evalEntry.path && evalEntry.path.trim().length > 0 ? evalEntry.path : null;
10578
10660
  const relPath = setName ? `${setName}/${slug}.yaml` : `${slug}.yaml`;
10579
- const targetPath = path11.join(evalsDir, relPath);
10580
- if (!targetPath.startsWith(evalsDir + path11.sep)) {
10661
+ const targetPath = path12.join(evalsDir, relPath);
10662
+ if (!targetPath.startsWith(evalsDir + path12.sep)) {
10581
10663
  console.warn(` Warning: skipping eval "${evalEntry.name}" (scenario set "${setName}" escapes evals/ \u2014 possible bad backend data)`);
10582
10664
  continue;
10583
10665
  }
10584
10666
  if (setName) {
10585
- const setDir = path11.join(evalsDir, setName);
10586
- if (!fs9.existsSync(setDir)) {
10587
- fs9.mkdirSync(setDir, { recursive: true });
10667
+ const setDir = path12.join(evalsDir, setName);
10668
+ if (!fs10.existsSync(setDir)) {
10669
+ fs10.mkdirSync(setDir, { recursive: true });
10588
10670
  }
10589
10671
  }
10590
10672
  const yamlContent = yaml4.dump(buildEvalYamlObject(evalEntry, slug), YAML_DUMP_OPTIONS);
10591
- fs9.writeFileSync(targetPath, yamlContent, "utf-8");
10673
+ fs10.writeFileSync(targetPath, yamlContent, "utf-8");
10592
10674
  writtenRelPaths.add(relPath);
10593
10675
  }
10594
10676
  cleanEvalOrphans(evalsDir, writtenRelPaths);
10595
10677
  }
10596
10678
  function cleanEvalOrphans(evalsDir, writtenRelPaths) {
10597
- const entries = fs9.readdirSync(evalsDir, { withFileTypes: true });
10679
+ const entries = fs10.readdirSync(evalsDir, { withFileTypes: true });
10598
10680
  for (const entry of entries) {
10599
- const fullPath = path11.join(evalsDir, entry.name);
10681
+ const fullPath = path12.join(evalsDir, entry.name);
10600
10682
  if (entry.isFile()) {
10601
10683
  if (entry.name.endsWith(".yaml") && !writtenRelPaths.has(entry.name)) {
10602
- fs9.unlinkSync(fullPath);
10684
+ fs10.unlinkSync(fullPath);
10603
10685
  }
10604
10686
  continue;
10605
10687
  }
10606
10688
  if (entry.isDirectory()) {
10607
10689
  const setName = entry.name;
10608
- const subEntries = fs9.readdirSync(fullPath, { withFileTypes: true });
10690
+ const subEntries = fs10.readdirSync(fullPath, { withFileTypes: true });
10609
10691
  for (const sub of subEntries) {
10610
10692
  if (sub.isFile() && sub.name.endsWith(".yaml")) {
10611
10693
  const relPath = `${setName}/${sub.name}`;
10612
10694
  if (!writtenRelPaths.has(relPath)) {
10613
- fs9.unlinkSync(path11.join(fullPath, sub.name));
10695
+ fs10.unlinkSync(path12.join(fullPath, sub.name));
10614
10696
  }
10615
10697
  }
10616
10698
  }
10617
10699
  try {
10618
- if (fs9.readdirSync(fullPath).length === 0) fs9.rmdirSync(fullPath);
10700
+ if (fs10.readdirSync(fullPath).length === 0) fs10.rmdirSync(fullPath);
10619
10701
  } catch {
10620
10702
  }
10621
10703
  }
@@ -10651,19 +10733,19 @@ function buildJourneyYamlObject(journeyEntry, slug) {
10651
10733
  return out;
10652
10734
  }
10653
10735
  function writeJourneyYamlFiles(hubFolder, journeys) {
10654
- const journeysDir = path11.join(hubFolder, "journeys");
10736
+ const journeysDir = path12.join(hubFolder, "journeys");
10655
10737
  if (journeys.length === 0) {
10656
- if (fs9.existsSync(journeysDir)) {
10738
+ if (fs10.existsSync(journeysDir)) {
10657
10739
  cleanJourneyOrphans(journeysDir, /* @__PURE__ */ new Set());
10658
10740
  try {
10659
- if (fs9.readdirSync(journeysDir).length === 0) fs9.rmdirSync(journeysDir);
10741
+ if (fs10.readdirSync(journeysDir).length === 0) fs10.rmdirSync(journeysDir);
10660
10742
  } catch {
10661
10743
  }
10662
10744
  }
10663
10745
  return;
10664
10746
  }
10665
- if (!fs9.existsSync(journeysDir)) {
10666
- fs9.mkdirSync(journeysDir, { recursive: true });
10747
+ if (!fs10.existsSync(journeysDir)) {
10748
+ fs10.mkdirSync(journeysDir, { recursive: true });
10667
10749
  }
10668
10750
  const writtenFiles = /* @__PURE__ */ new Set();
10669
10751
  const usedSlugs = /* @__PURE__ */ new Set();
@@ -10671,33 +10753,33 @@ function writeJourneyYamlFiles(hubFolder, journeys) {
10671
10753
  const slug = ensureUniqueSlug(slugify(journeyEntry.name), usedSlugs);
10672
10754
  const fileName = `${slug}.yaml`;
10673
10755
  const yamlContent = yaml4.dump(buildJourneyYamlObject(journeyEntry, slug), YAML_DUMP_OPTIONS);
10674
- fs9.writeFileSync(path11.join(journeysDir, fileName), yamlContent, "utf-8");
10756
+ fs10.writeFileSync(path12.join(journeysDir, fileName), yamlContent, "utf-8");
10675
10757
  writtenFiles.add(fileName);
10676
10758
  }
10677
10759
  cleanJourneyOrphans(journeysDir, writtenFiles);
10678
10760
  }
10679
10761
  function cleanJourneyOrphans(journeysDir, writtenFiles) {
10680
- const entries = fs9.readdirSync(journeysDir, { withFileTypes: true });
10762
+ const entries = fs10.readdirSync(journeysDir, { withFileTypes: true });
10681
10763
  for (const entry of entries) {
10682
10764
  if (entry.isFile() && entry.name.endsWith(".yaml") && !writtenFiles.has(entry.name)) {
10683
- fs9.unlinkSync(path11.join(journeysDir, entry.name));
10765
+ fs10.unlinkSync(path12.join(journeysDir, entry.name));
10684
10766
  }
10685
10767
  }
10686
10768
  }
10687
10769
  function writeResourceFiles(hubFolder, resources) {
10688
- const resourcesDir = path11.join(hubFolder, "resources");
10770
+ const resourcesDir = path12.join(hubFolder, "resources");
10689
10771
  const currentSlugs = /* @__PURE__ */ new Set();
10690
10772
  for (const resource of resources) {
10691
10773
  const resSlug = slugify(resource.name);
10692
10774
  currentSlugs.add(resSlug);
10693
- const resDir = path11.join(resourcesDir, resSlug);
10775
+ const resDir = path12.join(resourcesDir, resSlug);
10694
10776
  writeResourceFileTree(resDir, resource.files || []);
10695
10777
  }
10696
- if (fs9.existsSync(resourcesDir)) {
10697
- const existingDirs = fs9.readdirSync(resourcesDir, { withFileTypes: true });
10778
+ if (fs10.existsSync(resourcesDir)) {
10779
+ const existingDirs = fs10.readdirSync(resourcesDir, { withFileTypes: true });
10698
10780
  for (const entry of existingDirs) {
10699
10781
  if (entry.isDirectory() && !currentSlugs.has(entry.name)) {
10700
- fs9.rmSync(path11.join(resourcesDir, entry.name), { recursive: true, force: true });
10782
+ fs10.rmSync(path12.join(resourcesDir, entry.name), { recursive: true, force: true });
10701
10783
  }
10702
10784
  }
10703
10785
  }
@@ -10709,6 +10791,7 @@ var init_yaml_writer = __esm({
10709
10791
  init_dist();
10710
10792
  init_utils();
10711
10793
  init_resource_files();
10794
+ init_workspace_files();
10712
10795
  YAML_DUMP_OPTIONS = {
10713
10796
  lineWidth: -1,
10714
10797
  // don't wrap lines
@@ -10722,8 +10805,8 @@ var init_yaml_writer = __esm({
10722
10805
  });
10723
10806
 
10724
10807
  // src/lib/parser.ts
10725
- import * as fs10 from "fs";
10726
- import * as path12 from "path";
10808
+ import * as fs11 from "fs";
10809
+ import * as path13 from "path";
10727
10810
  import * as yaml5 from "js-yaml";
10728
10811
  function expected(message) {
10729
10812
  const err = new Error(message);
@@ -10737,7 +10820,7 @@ function parseHubFolder(hubFolder, opts) {
10737
10820
  err.isExpected = true;
10738
10821
  throw err;
10739
10822
  }
10740
- const yamlContent = fs10.readFileSync(yamlPath, "utf-8");
10823
+ const yamlContent = fs11.readFileSync(yamlPath, "utf-8");
10741
10824
  let config;
10742
10825
  try {
10743
10826
  config = yaml5.load(yamlContent);
@@ -10772,9 +10855,9 @@ function parseHubFolder(hubFolder, opts) {
10772
10855
  const resolved = { ...agent };
10773
10856
  if (typeof resolved.instructions === "string" && resolved.instructions.endsWith(".md")) {
10774
10857
  const instrValue = resolved.instructions;
10775
- const instructionsPath = instrValue.startsWith("agents/") ? path12.join(hubFolder, instrValue) : path12.join(hubFolder, "agents", instrValue);
10776
- if (fs10.existsSync(instructionsPath)) {
10777
- resolved.instructions = fs10.readFileSync(instructionsPath, "utf-8");
10858
+ const instructionsPath = instrValue.startsWith("agents/") ? path13.join(hubFolder, instrValue) : path13.join(hubFolder, "agents", instrValue);
10859
+ if (fs11.existsSync(instructionsPath)) {
10860
+ resolved.instructions = fs11.readFileSync(instructionsPath, "utf-8");
10778
10861
  } else {
10779
10862
  const err = new Error(
10780
10863
  `Agent instructions file not found: ${instructionsPath} (referenced by agent "${agent.name}")`
@@ -10783,9 +10866,9 @@ function parseHubFolder(hubFolder, opts) {
10783
10866
  throw err;
10784
10867
  }
10785
10868
  } else if (resolved.instructions === void 0 && typeof agent.name === "string") {
10786
- const conventionPath = path12.join(hubFolder, "agents", `${slugify(agent.name)}.md`);
10787
- if (fs10.existsSync(conventionPath)) {
10788
- resolved.instructions = fs10.readFileSync(conventionPath, "utf-8");
10869
+ const conventionPath = path13.join(hubFolder, "agents", `${slugify(agent.name)}.md`);
10870
+ if (fs11.existsSync(conventionPath)) {
10871
+ resolved.instructions = fs11.readFileSync(conventionPath, "utf-8");
10789
10872
  }
10790
10873
  }
10791
10874
  return resolved;
@@ -10835,26 +10918,26 @@ function parseHubFolder(hubFolder, opts) {
10835
10918
  return payload;
10836
10919
  }
10837
10920
  function scanEvalYamlFiles(hubFolder) {
10838
- const evalsDir = path12.join(hubFolder, "evals");
10839
- if (!fs10.existsSync(evalsDir)) return [];
10921
+ const evalsDir = path13.join(hubFolder, "evals");
10922
+ if (!fs11.existsSync(evalsDir)) return [];
10840
10923
  const evals = [];
10841
10924
  const seen = /* @__PURE__ */ new Set();
10842
- const topEntries = fs10.readdirSync(evalsDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
10925
+ const topEntries = fs11.readdirSync(evalsDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
10843
10926
  for (const entry of topEntries) {
10844
10927
  if (entry.isFile() && entry.name.endsWith(".yaml")) {
10845
- collectEval(evals, seen, path12.join(evalsDir, entry.name), `evals/${entry.name}`, null);
10928
+ collectEval(evals, seen, path13.join(evalsDir, entry.name), `evals/${entry.name}`, null);
10846
10929
  } else if (entry.isDirectory()) {
10847
10930
  const setName = entry.name;
10848
- const setDir = path12.join(evalsDir, setName);
10849
- const setEntries = fs10.readdirSync(setDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
10931
+ const setDir = path13.join(evalsDir, setName);
10932
+ const setEntries = fs11.readdirSync(setDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
10850
10933
  for (const sub of setEntries) {
10851
10934
  if (sub.isDirectory()) {
10852
10935
  throw expected(
10853
- `Nested scenario sets are not supported: ${path12.relative(hubFolder, path12.join(setDir, sub.name))}. Move scenarios up to evals/${setName}/.`
10936
+ `Nested scenario sets are not supported: ${path13.relative(hubFolder, path13.join(setDir, sub.name))}. Move scenarios up to evals/${setName}/.`
10854
10937
  );
10855
10938
  }
10856
10939
  if (sub.isFile() && sub.name.endsWith(".yaml")) {
10857
- collectEval(evals, seen, path12.join(setDir, sub.name), `evals/${setName}/${sub.name}`, setName);
10940
+ collectEval(evals, seen, path13.join(setDir, sub.name), `evals/${setName}/${sub.name}`, setName);
10858
10941
  }
10859
10942
  }
10860
10943
  }
@@ -10868,14 +10951,14 @@ function collectEval(evals, seen, filePath, relPath, setName) {
10868
10951
  if (seen.has(key)) {
10869
10952
  const where = setName ? `scenario set "${setName}"` : "root";
10870
10953
  throw expected(
10871
- `Duplicate eval at ${where}: "${evalEntry.name}" (in ${path12.basename(filePath)}). Each (name, scenario set) pair must be unique.`
10954
+ `Duplicate eval at ${where}: "${evalEntry.name}" (in ${path13.basename(filePath)}). Each (name, scenario set) pair must be unique.`
10872
10955
  );
10873
10956
  }
10874
10957
  seen.add(key);
10875
10958
  evals.push(evalEntry);
10876
10959
  }
10877
10960
  function parseEvalYaml(filePath, relPath, setName) {
10878
- const content = fs10.readFileSync(filePath, "utf-8");
10961
+ const content = fs11.readFileSync(filePath, "utf-8");
10879
10962
  let raw;
10880
10963
  try {
10881
10964
  raw = yaml5.load(content);
@@ -10890,7 +10973,7 @@ function parseEvalYaml(filePath, relPath, setName) {
10890
10973
  return null;
10891
10974
  }
10892
10975
  const data = raw;
10893
- const fileSlug = path12.basename(filePath, ".yaml");
10976
+ const fileSlug = path13.basename(filePath, ".yaml");
10894
10977
  const evalName = typeof data.name === "string" && data.name.trim().length > 0 ? data.name : fileSlug;
10895
10978
  if (typeof data.agent !== "string" || data.agent.trim().length === 0) {
10896
10979
  throw expected(`Eval "${evalName}" in ${relPath}: missing required field "agent" (string).`);
@@ -10944,19 +11027,19 @@ function parseFixtureField(raw, label, key) {
10944
11027
  return trimmed.length > 0 ? trimmed : void 0;
10945
11028
  }
10946
11029
  function scanJourneyYamlFiles(hubFolder) {
10947
- const journeysDir = path12.join(hubFolder, "journeys");
10948
- if (!fs10.existsSync(journeysDir)) return [];
11030
+ const journeysDir = path13.join(hubFolder, "journeys");
11031
+ if (!fs11.existsSync(journeysDir)) return [];
10949
11032
  const journeys = [];
10950
11033
  const seen = /* @__PURE__ */ new Set();
10951
- const entries = fs10.readdirSync(journeysDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
11034
+ const entries = fs11.readdirSync(journeysDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
10952
11035
  for (const entry of entries) {
10953
11036
  if (entry.isDirectory()) {
10954
11037
  throw expected(
10955
- `Subfolders are not supported under journeys/: ${path12.relative(hubFolder, path12.join(journeysDir, entry.name))}. A journey owns its own managed scenario set \u2014 put each journey in a single journeys/<slug>.yaml file.`
11038
+ `Subfolders are not supported under journeys/: ${path13.relative(hubFolder, path13.join(journeysDir, entry.name))}. A journey owns its own managed scenario set \u2014 put each journey in a single journeys/<slug>.yaml file.`
10956
11039
  );
10957
11040
  }
10958
11041
  if (!entry.isFile() || !entry.name.endsWith(".yaml")) continue;
10959
- const journeyEntry = parseJourneyYaml(path12.join(journeysDir, entry.name), `journeys/${entry.name}`);
11042
+ const journeyEntry = parseJourneyYaml(path13.join(journeysDir, entry.name), `journeys/${entry.name}`);
10960
11043
  if (!journeyEntry) continue;
10961
11044
  if (seen.has(journeyEntry.name)) {
10962
11045
  throw expected(
@@ -10969,7 +11052,7 @@ function scanJourneyYamlFiles(hubFolder) {
10969
11052
  return journeys;
10970
11053
  }
10971
11054
  function parseJourneyYaml(filePath, relPath) {
10972
- const content = fs10.readFileSync(filePath, "utf-8");
11055
+ const content = fs11.readFileSync(filePath, "utf-8");
10973
11056
  let raw;
10974
11057
  try {
10975
11058
  raw = yaml5.load(content);
@@ -10984,7 +11067,7 @@ function parseJourneyYaml(filePath, relPath) {
10984
11067
  return null;
10985
11068
  }
10986
11069
  const data = raw;
10987
- const fileSlug = path12.basename(filePath, ".yaml");
11070
+ const fileSlug = path13.basename(filePath, ".yaml");
10988
11071
  const journeyName = typeof data.name === "string" && data.name.trim().length > 0 ? data.name : fileSlug;
10989
11072
  if (typeof data.agent !== "string" || data.agent.trim().length === 0) {
10990
11073
  throw expected(`Journey "${journeyName}" in ${relPath}: missing required field "agent" (string).`);
@@ -11020,14 +11103,14 @@ function parseJourneyYaml(filePath, relPath) {
11020
11103
  return journeyEntry;
11021
11104
  }
11022
11105
  function scanAgentYamlFiles(hubFolder) {
11023
- const agentsDir = path12.join(hubFolder, "agents");
11024
- if (!fs10.existsSync(agentsDir)) return [];
11025
- const yamlFiles = fs10.readdirSync(agentsDir).filter((f) => f.endsWith(".yaml")).sort();
11106
+ const agentsDir = path13.join(hubFolder, "agents");
11107
+ if (!fs11.existsSync(agentsDir)) return [];
11108
+ const yamlFiles = fs11.readdirSync(agentsDir).filter((f) => f.endsWith(".yaml")).sort();
11026
11109
  if (yamlFiles.length === 0) return [];
11027
11110
  const agents = [];
11028
11111
  for (const file of yamlFiles) {
11029
- const filePath = path12.join(agentsDir, file);
11030
- const content = fs10.readFileSync(filePath, "utf-8");
11112
+ const filePath = path13.join(agentsDir, file);
11113
+ const content = fs11.readFileSync(filePath, "utf-8");
11031
11114
  let agent;
11032
11115
  try {
11033
11116
  agent = yaml5.load(content);
@@ -11049,7 +11132,7 @@ function scanAgentYamlFiles(hubFolder) {
11049
11132
  return agents;
11050
11133
  }
11051
11134
  function parseResources(hubFolder, configResources) {
11052
- const resourcesDir = path12.join(hubFolder, "resources");
11135
+ const resourcesDir = path13.join(hubFolder, "resources");
11053
11136
  const results = [];
11054
11137
  for (const res of configResources) {
11055
11138
  const resource = {
@@ -11062,8 +11145,8 @@ function parseResources(hubFolder, configResources) {
11062
11145
  if (res.user_browsable) resource.user_browsable = res.user_browsable;
11063
11146
  if (res.skill_name) resource.skill_name = res.skill_name;
11064
11147
  const resSlug = slugify(resource.name);
11065
- const resDir = path12.join(resourcesDir, resSlug);
11066
- if (fs10.existsSync(resDir)) {
11148
+ const resDir = path13.join(resourcesDir, resSlug);
11149
+ if (fs11.existsSync(resDir)) {
11067
11150
  const files = scanResourceFiles(resDir, "");
11068
11151
  if (files.length > 0) {
11069
11152
  resource.files = files;
@@ -11117,8 +11200,8 @@ __export(pull_exports, {
11117
11200
  resolveHubTarget: () => resolveHubTarget,
11118
11201
  writeProductionMirror: () => writeProductionMirror
11119
11202
  });
11120
- import * as fs11 from "fs";
11121
- import * as path13 from "path";
11203
+ import * as fs12 from "fs";
11204
+ import * as path14 from "path";
11122
11205
  function parseArgs4(args2) {
11123
11206
  let autoConfirm = false;
11124
11207
  let hubSelector;
@@ -11137,7 +11220,7 @@ function resolveHubTarget(workspaceDir, selector) {
11137
11220
  const allHubs = scanWorkspaceHubs(workspaceDir);
11138
11221
  if (selector) {
11139
11222
  const match = allHubs.find(
11140
- (h) => h.hubId === selector || path13.basename(h.hubFolder) === selector
11223
+ (h) => h.hubId === selector || path14.basename(h.hubFolder) === selector
11141
11224
  );
11142
11225
  if (match) return { hubId: match.hubId, hubFolder: match.hubFolder };
11143
11226
  if (UUID_RE.test(selector)) return { hubId: selector, hubFolder: null };
@@ -11154,7 +11237,7 @@ function resolveHubTarget(workspaceDir, selector) {
11154
11237
  }
11155
11238
  console.error(`Multiple hubs found in ${wsLabel}/. Pass --hub <uuid|folder-name> to choose, or run from inside a hub folder:`);
11156
11239
  for (const h of previewHubs) {
11157
- console.error(` ${path13.basename(h.hubFolder)} (${h.hubId})`);
11240
+ console.error(` ${path14.basename(h.hubFolder)} (${h.hubId})`);
11158
11241
  }
11159
11242
  process.exit(1);
11160
11243
  }
@@ -11167,6 +11250,11 @@ async function pullCommand(args2) {
11167
11250
  const workspaceDir = resolveWorkspaceDir();
11168
11251
  const gitRoot = findGitRoot();
11169
11252
  if (gitRoot) warnLayoutOnce(gitRoot);
11253
+ if (gitRoot) {
11254
+ for (const file of ensureWorkspaceFiles(gitRoot)) {
11255
+ console.error(`Created ${file}`);
11256
+ }
11257
+ }
11170
11258
  const { hubId, hubFolder: existingFolder } = resolveHubTarget(workspaceDir, hubSelector);
11171
11259
  console.log("Fetching hub configuration...");
11172
11260
  const payload = await client.pull(hubId, organizationId);
@@ -11187,7 +11275,7 @@ async function pullCommand(args2) {
11187
11275
  payload.preview_label,
11188
11276
  payload.branch_name
11189
11277
  );
11190
- fs11.mkdirSync(path13.dirname(hubFolder), { recursive: true });
11278
+ fs12.mkdirSync(path14.dirname(hubFolder), { recursive: true });
11191
11279
  console.log("Writing hub configuration...");
11192
11280
  writeHubFolder(hubFolder, payload);
11193
11281
  await downloadBinaryResourceFiles(hubFolder, payload);
@@ -11248,8 +11336,8 @@ async function pullCommand(args2) {
11248
11336
  }
11249
11337
  async function writeProductionMirror(workspaceDir, prodPayload) {
11250
11338
  const folder = resolveHubFolder(workspaceDir, prodPayload.hub_id, prodPayload.hub.name, "production", null, null);
11251
- fs11.mkdirSync(path13.dirname(folder), { recursive: true });
11252
- writeHubFolder(folder, prodPayload);
11339
+ fs12.mkdirSync(path14.dirname(folder), { recursive: true });
11340
+ writeHubFolder(folder, prodPayload, { seedAgentContext: false });
11253
11341
  await downloadBinaryResourceFiles(folder, prodPayload);
11254
11342
  const finalFolder = autoRenameHubFolder(folder, prodPayload.hub.name, "production", prodPayload.hub_id, null, null);
11255
11343
  prependMirrorMarker(finalFolder, prodPayload.hub_id);
@@ -11265,13 +11353,13 @@ async function mirrorLinkedProduction(client, workspaceDir, productionHubId, org
11265
11353
  }
11266
11354
  }
11267
11355
  function prependMirrorMarker(hubFolder, productionHubId) {
11268
- const hubYaml = path13.join(hubFolder, "hub.yaml");
11356
+ const hubYaml = path14.join(hubFolder, "hub.yaml");
11269
11357
  try {
11270
- const content = fs11.readFileSync(hubYaml, "utf-8");
11358
+ const content = fs12.readFileSync(hubYaml, "utf-8");
11271
11359
  if (content.startsWith(MIRROR_MARKER_PREFIX)) return;
11272
11360
  const marker = `${MIRROR_MARKER_PREFIX} ${productionHubId}. Edits are ignored; push is blocked. Edit the linked preview hub instead.
11273
11361
  `;
11274
- fs11.writeFileSync(hubYaml, marker + content, "utf-8");
11362
+ fs12.writeFileSync(hubYaml, marker + content, "utf-8");
11275
11363
  } catch {
11276
11364
  }
11277
11365
  }
@@ -11280,7 +11368,7 @@ async function downloadBinaryResourceFiles(hubFolder, payload) {
11280
11368
  let downloadCount = 0;
11281
11369
  for (const resource of resources) {
11282
11370
  if (!resource.files) continue;
11283
- const resDir = path13.join(hubFolder, "resources", slugify(resource.name));
11371
+ const resDir = path14.join(hubFolder, "resources", slugify(resource.name));
11284
11372
  downloadCount += await downloadBinaryFiles(resDir, resource.files);
11285
11373
  }
11286
11374
  if (downloadCount > 0) {
@@ -11313,6 +11401,7 @@ var init_pull = __esm({
11313
11401
  init_resource_files();
11314
11402
  init_workspace();
11315
11403
  init_layout();
11404
+ init_workspace_files();
11316
11405
  init_repo_config();
11317
11406
  init_hub_binding();
11318
11407
  MIRROR_MARKER_PREFIX = "# Read-only mirror of production hub";
@@ -11331,8 +11420,8 @@ __export(push_exports, {
11331
11420
  selectExistingHub: () => selectExistingHub,
11332
11421
  shouldWarnIgnoredPreviewLabel: () => shouldWarnIgnoredPreviewLabel
11333
11422
  });
11334
- import * as fs12 from "fs";
11335
- import * as path14 from "path";
11423
+ import * as fs13 from "fs";
11424
+ import * as path15 from "path";
11336
11425
  import * as yaml6 from "js-yaml";
11337
11426
  function parseArgs5(args2) {
11338
11427
  let autoConfirm = false;
@@ -11416,13 +11505,13 @@ function printWarnings(warnings) {
11416
11505
  }
11417
11506
  }
11418
11507
  async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId) {
11419
- const agentsDir = path14.join(hubFolder, "agents");
11508
+ const agentsDir = path15.join(hubFolder, "agents");
11420
11509
  let agentsWithIds = [];
11421
- if (fs12.existsSync(agentsDir)) {
11422
- const yamlFiles = fs12.readdirSync(agentsDir).filter((f) => f.endsWith(".yaml"));
11510
+ if (fs13.existsSync(agentsDir)) {
11511
+ const yamlFiles = fs13.readdirSync(agentsDir).filter((f) => f.endsWith(".yaml"));
11423
11512
  for (const file of yamlFiles) {
11424
11513
  try {
11425
- const content = fs12.readFileSync(path14.join(agentsDir, file), "utf-8");
11514
+ const content = fs13.readFileSync(path15.join(agentsDir, file), "utf-8");
11426
11515
  const agent = yaml6.load(content);
11427
11516
  if (agent?.id && agent.name) {
11428
11517
  agentsWithIds.push({ id: agent.id, name: agent.name });
@@ -11435,7 +11524,7 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId) {
11435
11524
  if (agentsWithIds.length === 0) {
11436
11525
  const yamlPath = resolveHubYamlPath(hubFolder);
11437
11526
  if (!yamlPath) return;
11438
- const yamlContent = fs12.readFileSync(yamlPath, "utf-8");
11527
+ const yamlContent = fs13.readFileSync(yamlPath, "utf-8");
11439
11528
  const config = yaml6.load(yamlContent);
11440
11529
  agentsWithIds = (config.agents || []).filter((a) => !!a.id && !!a.name);
11441
11530
  }
@@ -11465,18 +11554,18 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId) {
11465
11554
  }
11466
11555
  }
11467
11556
  if (renames.length === 0) return;
11468
- if (!fs12.existsSync(agentsDir)) return;
11469
- for (const file of fs12.readdirSync(agentsDir)) {
11557
+ if (!fs13.existsSync(agentsDir)) return;
11558
+ for (const file of fs13.readdirSync(agentsDir)) {
11470
11559
  if (file.startsWith("__rename_temp_") && (file.endsWith(".md") || file.endsWith(".yaml"))) {
11471
11560
  console.warn(` Warning: removing orphaned temp file agents/${file}`);
11472
- fs12.unlinkSync(path14.join(agentsDir, file));
11561
+ fs13.unlinkSync(path15.join(agentsDir, file));
11473
11562
  }
11474
11563
  }
11475
11564
  const renameFileIfExists = (dir, oldName, newName) => {
11476
- const oldPath = path14.join(dir, oldName);
11477
- const newPath = path14.join(dir, newName);
11478
- if (!fs12.existsSync(oldPath)) return false;
11479
- fs12.renameSync(oldPath, newPath);
11565
+ const oldPath = path15.join(dir, oldName);
11566
+ const newPath = path15.join(dir, newName);
11567
+ if (!fs13.existsSync(oldPath)) return false;
11568
+ fs13.renameSync(oldPath, newPath);
11480
11569
  return true;
11481
11570
  };
11482
11571
  const oldSlugs = new Set(renames.map((r) => r.oldSlug));
@@ -11509,9 +11598,9 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId) {
11509
11598
  }
11510
11599
  } else {
11511
11600
  for (const { oldSlug, newSlug } of renames) {
11512
- const hasOldFile = extensions.some((ext) => fs12.existsSync(path14.join(agentsDir, `${oldSlug}${ext}`)));
11601
+ const hasOldFile = extensions.some((ext) => fs13.existsSync(path15.join(agentsDir, `${oldSlug}${ext}`)));
11513
11602
  if (!hasOldFile) continue;
11514
- const hasNewFile = extensions.some((ext) => fs12.existsSync(path14.join(agentsDir, `${newSlug}${ext}`)));
11603
+ const hasNewFile = extensions.some((ext) => fs13.existsSync(path15.join(agentsDir, `${newSlug}${ext}`)));
11515
11604
  if (hasNewFile) {
11516
11605
  console.warn(` Warning: skipping rename agents/${oldSlug}.* \u2192 agents/${newSlug}.* (target already exists)`);
11517
11606
  continue;
@@ -11526,7 +11615,7 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId) {
11526
11615
  if (completedRenames.length === 0) return;
11527
11616
  const mainYamlPath = resolveHubYamlPath(hubFolder);
11528
11617
  if (mainYamlPath) {
11529
- const mainYamlContent = fs12.readFileSync(mainYamlPath, "utf-8");
11618
+ const mainYamlContent = fs13.readFileSync(mainYamlPath, "utf-8");
11530
11619
  const substitutionMap = /* @__PURE__ */ new Map();
11531
11620
  for (const { oldSlug, newSlug } of completedRenames) {
11532
11621
  substitutionMap.set(`agents/${oldSlug}.md`, `agents/${newSlug}.md`);
@@ -11537,8 +11626,8 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId) {
11537
11626
  (_match, prefix, pathMatch) => `${prefix}${substitutionMap.get(pathMatch) ?? pathMatch}`
11538
11627
  );
11539
11628
  if (updatedYaml !== mainYamlContent) {
11540
- fs12.writeFileSync(mainYamlPath, updatedYaml, "utf-8");
11541
- console.log(` Updated instructions paths in ${path14.basename(mainYamlPath)}`);
11629
+ fs13.writeFileSync(mainYamlPath, updatedYaml, "utf-8");
11630
+ console.log(` Updated instructions paths in ${path15.basename(mainYamlPath)}`);
11542
11631
  }
11543
11632
  }
11544
11633
  }
@@ -11599,7 +11688,7 @@ async function pushSingleHub(client, hubId, hubFolder, autoConfirm, organization
11599
11688
  function selectExistingHub(workspaceDir, allHubs, selector, wsLabel) {
11600
11689
  if (selector) {
11601
11690
  const match = allHubs.find(
11602
- (h) => h.hubId === selector || path14.basename(h.hubFolder) === selector
11691
+ (h) => h.hubId === selector || path15.basename(h.hubFolder) === selector
11603
11692
  );
11604
11693
  if (!match) {
11605
11694
  console.error(`No hub matching --hub ${selector} found in ${wsLabel}/.`);
@@ -11642,7 +11731,7 @@ New hub: "${newHub.hubName}" (${hubType})`);
11642
11731
  process.exit(1);
11643
11732
  }
11644
11733
  console.log(`Hub created: ${createdHub.hub_name} (${hubId})`);
11645
- const content = fs12.readFileSync(hubYamlPath, "utf-8");
11734
+ const content = fs13.readFileSync(hubYamlPath, "utf-8");
11646
11735
  const hasVersion = content.match(/^version:\s/m);
11647
11736
  let updated;
11648
11737
  if (hasVersion) {
@@ -11658,7 +11747,7 @@ hub_id: "${hubId}"
11658
11747
  hub_environment: preview
11659
11748
  ${content}`;
11660
11749
  }
11661
- fs12.writeFileSync(hubYamlPath, updated, "utf-8");
11750
+ fs13.writeFileSync(hubYamlPath, updated, "utf-8");
11662
11751
  autoBindIfUnbound(hubId);
11663
11752
  await pushSingleHub(client, hubId, newHub.hubFolder, opts.autoConfirm, opts.organizationId, { skipAgentRename: true });
11664
11753
  }
@@ -11667,7 +11756,7 @@ function reportUnresolvedPushTarget(reason, existingHubs, newHubs, selector, wsL
11667
11756
  if (existingHubs.length > 0) {
11668
11757
  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
11758
  for (const h of existingHubs) {
11670
- console.error(` ${path14.basename(h.hubFolder)} (${h.hubId}, production mirror)`);
11759
+ console.error(` ${path15.basename(h.hubFolder)} (${h.hubId}, production mirror)`);
11671
11760
  }
11672
11761
  } else {
11673
11762
  console.error(`No hub folders found. Create hub files in ${wsLabel}/<hub>/hub.yaml with \`hub: { name: ... }\` and run \`wayai push\` (or \`wayai create\`).`);
@@ -11680,10 +11769,10 @@ function reportUnresolvedPushTarget(reason, existingHubs, newHubs, selector, wsL
11680
11769
  console.error(`Multiple hub folders found in ${wsLabel}/. Pass --hub <uuid|folder-name> to choose, or run from inside a hub folder:`);
11681
11770
  }
11682
11771
  for (const h of existingHubs) {
11683
- console.error(` ${path14.basename(h.hubFolder)} (${h.hubId})`);
11772
+ console.error(` ${path15.basename(h.hubFolder)} (${h.hubId})`);
11684
11773
  }
11685
11774
  for (const h of newHubs) {
11686
- console.error(` ${path14.basename(h.hubFolder)} (new \u2014 "${h.hubName}")`);
11775
+ console.error(` ${path15.basename(h.hubFolder)} (new \u2014 "${h.hubName}")`);
11687
11776
  }
11688
11777
  process.exit(1);
11689
11778
  }
@@ -11697,7 +11786,12 @@ async function pushCommand(args2) {
11697
11786
  const gitRoot = findGitRoot();
11698
11787
  const wsLabel = hubsDirLabel(gitRoot);
11699
11788
  if (gitRoot) warnLayoutOnce(gitRoot);
11700
- if (!fs12.existsSync(workspaceDir)) {
11789
+ if (gitRoot) {
11790
+ for (const file of ensureWorkspaceFiles(gitRoot)) {
11791
+ console.error(`Created ${file}`);
11792
+ }
11793
+ }
11794
+ if (!fs13.existsSync(workspaceDir)) {
11701
11795
  console.error(`No ${wsLabel}/ directory found. Run \`wayai pull\` first or create hub files in ${wsLabel}/<hub>/hub.yaml.`);
11702
11796
  process.exit(1);
11703
11797
  }
@@ -11716,8 +11810,8 @@ async function pushCommand(args2) {
11716
11810
  if (label) {
11717
11811
  console.warn("Note: --label is only used when creating a new hub. To change an existing hub's label, use `wayai relabel`.");
11718
11812
  }
11719
- console.log(`Target hub: ${path14.basename(existing.hubFolder)} (${existing.hubId})`);
11720
- assertHubMatchesBinding(existing.hubId, path14.basename(existing.hubFolder));
11813
+ console.log(`Target hub: ${path15.basename(existing.hubFolder)} (${existing.hubId})`);
11814
+ assertHubMatchesBinding(existing.hubId, path15.basename(existing.hubFolder));
11721
11815
  await pushSingleHub(client, existing.hubId, existing.hubFolder, autoConfirm, organizationId);
11722
11816
  return;
11723
11817
  }
@@ -11736,6 +11830,7 @@ var init_push = __esm({
11736
11830
  init_utils();
11737
11831
  init_workspace();
11738
11832
  init_layout();
11833
+ init_workspace_files();
11739
11834
  init_repo_config();
11740
11835
  init_hub_binding();
11741
11836
  }
@@ -11746,8 +11841,8 @@ var create_exports = {};
11746
11841
  __export(create_exports, {
11747
11842
  createCommand: () => createCommand
11748
11843
  });
11749
- import * as path15 from "path";
11750
- import * as fs13 from "fs";
11844
+ import * as path16 from "path";
11845
+ import * as fs14 from "fs";
11751
11846
  function parseArgs6(args2) {
11752
11847
  let autoConfirm = false;
11753
11848
  let folderSelector;
@@ -11774,7 +11869,7 @@ async function createCommand(args2) {
11774
11869
  const gitRoot = findGitRoot();
11775
11870
  const wsLabel = hubsDirLabel(gitRoot);
11776
11871
  if (gitRoot) warnLayoutOnce(gitRoot);
11777
- if (!fs13.existsSync(workspaceDir)) {
11872
+ if (!fs14.existsSync(workspaceDir)) {
11778
11873
  console.error(`No ${wsLabel}/ directory found. Create hub files in ${wsLabel}/<hub>/hub.yaml with \`hub: { name: ... }\` first.`);
11779
11874
  process.exit(1);
11780
11875
  }
@@ -11783,7 +11878,7 @@ async function createCommand(args2) {
11783
11878
  const resolution = resolveNewHubForCreate(workspaceDir, existingHubs, newHubs, folderSelector);
11784
11879
  if (!resolution.ok) {
11785
11880
  if (resolution.reason === "exists") {
11786
- const folder = path15.basename(resolution.existing.hubFolder);
11881
+ const folder = path16.basename(resolution.existing.hubFolder);
11787
11882
  console.error(`Hub "${folder}" already exists (${resolution.existing.hubId}). Use \`wayai push --hub ${folder}\` to update it.`);
11788
11883
  process.exit(1);
11789
11884
  }
@@ -11797,7 +11892,7 @@ async function createCommand(args2) {
11797
11892
  }
11798
11893
  console.error(`Multiple new hub folders found in ${wsLabel}/. Pass the folder name (\`wayai create <folder>\`) or run from inside one:`);
11799
11894
  for (const h of newHubs) {
11800
- console.error(` ${path15.basename(h.hubFolder)} (new \u2014 "${h.hubName}")`);
11895
+ console.error(` ${path16.basename(h.hubFolder)} (new \u2014 "${h.hubName}")`);
11801
11896
  }
11802
11897
  process.exit(1);
11803
11898
  }
@@ -11967,12 +12062,12 @@ function typeMatches2(typeField, allowed) {
11967
12062
  if (Array.isArray(typeField)) return typeField.every((t) => typeof t === "string" && allowed.has(t));
11968
12063
  return false;
11969
12064
  }
11970
- function validateSchema2(schema, path26, errors, opts = {}) {
12065
+ function validateSchema2(schema, path27, errors, opts = {}) {
11971
12066
  if (typeof schema === "boolean") return;
11972
12067
  const depth = opts.depth ?? 0;
11973
12068
  if (depth > MAX_SCHEMA_DEPTH2) {
11974
12069
  errors.push({
11975
- path: path26 || "<root>",
12070
+ path: path27 || "<root>",
11976
12071
  message: `schema nesting exceeds ${MAX_SCHEMA_DEPTH2} levels`,
11977
12072
  suggestion: "Flatten the schema; LLM providers reject deeply nested tool input_schemas."
11978
12073
  });
@@ -11980,7 +12075,7 @@ function validateSchema2(schema, path26, errors, opts = {}) {
11980
12075
  }
11981
12076
  if (!isRecord2(schema)) {
11982
12077
  errors.push({
11983
- path: path26,
12078
+ path: path27,
11984
12079
  message: `expected object, got ${schema === null ? "null" : typeof schema}`
11985
12080
  });
11986
12081
  return;
@@ -11988,14 +12083,14 @@ function validateSchema2(schema, path26, errors, opts = {}) {
11988
12083
  if (opts.isRoot) {
11989
12084
  if ("type" in schema && schema.type !== "object") {
11990
12085
  errors.push({
11991
- path: path26 ? `${path26}.type` : "type",
12086
+ path: path27 ? `${path27}.type` : "type",
11992
12087
  message: `root type must be 'object', got ${JSON.stringify(schema.type)}`,
11993
12088
  suggestion: "Tool parameters at the root must be an object: `{ type: 'object', properties: { ... } }`."
11994
12089
  });
11995
12090
  }
11996
12091
  } else if ("type" in schema && !typeMatches2(schema.type, ALLOWED_TYPES2)) {
11997
12092
  errors.push({
11998
- path: `${path26}.type`,
12093
+ path: `${path27}.type`,
11999
12094
  message: `type must be one of ${[...ALLOWED_TYPES2].join("/")} or an array of those, got ${JSON.stringify(schema.type)}`
12000
12095
  });
12001
12096
  }
@@ -12004,25 +12099,25 @@ function validateSchema2(schema, path26, errors, opts = {}) {
12004
12099
  if (typeof e === "string") {
12005
12100
  const isPlaceholder = PLACEHOLDER_TOKENS2.includes(e);
12006
12101
  errors.push({
12007
- path: `${path26}.enum`,
12102
+ path: `${path27}.enum`,
12008
12103
  message: `enum must be a non-empty array of primitives, got string ${JSON.stringify(e)}`,
12009
12104
  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"]`.'
12010
12105
  });
12011
12106
  } else if (!Array.isArray(e)) {
12012
12107
  errors.push({
12013
- path: `${path26}.enum`,
12108
+ path: `${path27}.enum`,
12014
12109
  message: `enum must be a non-empty array of primitives, got ${typeof e}`
12015
12110
  });
12016
12111
  } else if (e.length === 0) {
12017
12112
  errors.push({
12018
- path: `${path26}.enum`,
12113
+ path: `${path27}.enum`,
12019
12114
  message: "enum must not be empty"
12020
12115
  });
12021
12116
  } else {
12022
12117
  for (let i = 0; i < e.length; i++) {
12023
12118
  if (!isPrimitive2(e[i])) {
12024
12119
  errors.push({
12025
- path: `${path26}.enum[${i}]`,
12120
+ path: `${path27}.enum[${i}]`,
12026
12121
  message: `enum entry must be a primitive (string/number/boolean/null), got ${typeof e[i]}`
12027
12122
  });
12028
12123
  }
@@ -12032,7 +12127,7 @@ function validateSchema2(schema, path26, errors, opts = {}) {
12032
12127
  for (const key of ["exclusiveMinimum", "exclusiveMaximum"]) {
12033
12128
  if (key in schema && typeof schema[key] === "boolean") {
12034
12129
  errors.push({
12035
- path: `${path26}.${key}`,
12130
+ path: `${path27}.${key}`,
12036
12131
  message: `${key} as boolean is draft-04 syntax; draft 2020-12 requires a numeric value`,
12037
12132
  suggestion: `Replace with the numeric bound, e.g. \`${key}: 0\`.`
12038
12133
  });
@@ -12041,45 +12136,45 @@ function validateSchema2(schema, path26, errors, opts = {}) {
12041
12136
  if ("properties" in schema) {
12042
12137
  if (!isRecord2(schema.properties)) {
12043
12138
  errors.push({
12044
- path: `${path26}.properties`,
12139
+ path: `${path27}.properties`,
12045
12140
  message: `properties must be an object, got ${Array.isArray(schema.properties) ? "array" : typeof schema.properties}`
12046
12141
  });
12047
12142
  } else {
12048
12143
  for (const [propName, propSchema] of Object.entries(schema.properties)) {
12049
- validateSchema2(propSchema, `${path26}.properties.${propName}`, errors, { depth: depth + 1 });
12144
+ validateSchema2(propSchema, `${path27}.properties.${propName}`, errors, { depth: depth + 1 });
12050
12145
  }
12051
12146
  }
12052
12147
  }
12053
12148
  if (schemaTypeIncludes2(schema, "array") && "items" in schema) {
12054
12149
  if (Array.isArray(schema.items)) {
12055
- schema.items.forEach((sub, i) => validateSchema2(sub, `${path26}.items[${i}]`, errors, { depth: depth + 1 }));
12150
+ schema.items.forEach((sub, i) => validateSchema2(sub, `${path27}.items[${i}]`, errors, { depth: depth + 1 }));
12056
12151
  } else {
12057
- validateSchema2(schema.items, `${path26}.items`, errors, { depth: depth + 1 });
12152
+ validateSchema2(schema.items, `${path27}.items`, errors, { depth: depth + 1 });
12058
12153
  }
12059
12154
  }
12060
12155
  for (const key of SUBSCHEMA_OBJECT_KEYWORDS2) {
12061
12156
  if (key in schema && isRecord2(schema[key])) {
12062
- validateSchema2(schema[key], `${path26}.${key}`, errors, { depth: depth + 1 });
12157
+ validateSchema2(schema[key], `${path27}.${key}`, errors, { depth: depth + 1 });
12063
12158
  }
12064
12159
  }
12065
12160
  for (const key of SUBSCHEMA_LIST_KEYWORDS2) {
12066
12161
  const list = schema[key];
12067
12162
  if (Array.isArray(list)) {
12068
- list.forEach((sub, i) => validateSchema2(sub, `${path26}.${key}[${i}]`, errors, { depth: depth + 1 }));
12163
+ list.forEach((sub, i) => validateSchema2(sub, `${path27}.${key}[${i}]`, errors, { depth: depth + 1 }));
12069
12164
  }
12070
12165
  }
12071
12166
  for (const key of SUBSCHEMA_MAP_KEYWORDS2) {
12072
12167
  const map = schema[key];
12073
12168
  if (isRecord2(map)) {
12074
12169
  for (const [name, sub] of Object.entries(map)) {
12075
- validateSchema2(sub, `${path26}.${key}.${name}`, errors, { depth: depth + 1 });
12170
+ validateSchema2(sub, `${path27}.${key}.${name}`, errors, { depth: depth + 1 });
12076
12171
  }
12077
12172
  }
12078
12173
  }
12079
12174
  const reportedPaths = new Set(errors.map((e) => e.path));
12080
12175
  for (const [k, v] of Object.entries(schema)) {
12081
12176
  if (typeof v !== "string") continue;
12082
- const fieldPath = `${path26}.${k}`;
12177
+ const fieldPath = `${path27}.${k}`;
12083
12178
  if (reportedPaths.has(fieldPath)) continue;
12084
12179
  for (const token of PLACEHOLDER_TOKENS2) {
12085
12180
  if (v === token) {
@@ -12235,10 +12330,10 @@ function refineHubAsCodeLanes2(config, ctx) {
12235
12330
  }
12236
12331
  }
12237
12332
  }
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("/");
12333
+ function isSafeTemplatePath2(path27) {
12334
+ if (path27.length === 0 || path27.length > 300) return false;
12335
+ if (path27.startsWith("/") || path27.includes("\\")) return false;
12336
+ const segments = path27.split("/");
12242
12337
  return segments.every(
12243
12338
  (seg) => seg.length > 0 && seg !== "." && seg !== ".." && /^[A-Za-z0-9._-]+$/.test(seg)
12244
12339
  );
@@ -12266,9 +12361,9 @@ function isPlainObject(value) {
12266
12361
  const proto = Object.getPrototypeOf(value);
12267
12362
  return proto === Object.prototype || proto === null;
12268
12363
  }
12269
- function isSanitizableSliceFile(path26) {
12270
- if (!/\.ya?ml$/i.test(path26)) return false;
12271
- return path26 !== "resources" && !path26.startsWith("resources/");
12364
+ function isSanitizableSliceFile(path27) {
12365
+ if (!/\.ya?ml$/i.test(path27)) return false;
12366
+ return path27 !== "resources" && !path27.startsWith("resources/");
12272
12367
  }
12273
12368
  function distinctUsesBackends(uses) {
12274
12369
  return [...new Set((uses ?? []).map((u) => u.backend))];
@@ -14255,7 +14350,6 @@ var init_contracts = __esm({
14255
14350
  });
14256
14351
  dataExplorerDebugAnalyticsTable2 = external_exports.enum([
14257
14352
  "conversation",
14258
- "message",
14259
14353
  "schedule_event"
14260
14354
  ]);
14261
14355
  debugUuid2 = external_exports.string().uuid();
@@ -14888,8 +14982,8 @@ var replicate_exports = {};
14888
14982
  __export(replicate_exports, {
14889
14983
  replicateCommand: () => replicateCommand
14890
14984
  });
14891
- import * as fs14 from "fs";
14892
- import * as path16 from "path";
14985
+ import * as fs15 from "fs";
14986
+ import * as path17 from "path";
14893
14987
  function parseArgs8(args2) {
14894
14988
  let label;
14895
14989
  let hubSelector;
@@ -14935,7 +15029,7 @@ async function replicateCommand(args2) {
14935
15029
  payload.preview_label,
14936
15030
  payload.branch_name
14937
15031
  );
14938
- fs14.mkdirSync(path16.dirname(hubFolder), { recursive: true });
15032
+ fs15.mkdirSync(path17.dirname(hubFolder), { recursive: true });
14939
15033
  writeHubFolder(hubFolder, payload);
14940
15034
  await downloadBinaryResourceFiles(hubFolder, payload);
14941
15035
  hubFolder = autoRenameHubFolder(
@@ -14947,8 +15041,8 @@ async function replicateCommand(args2) {
14947
15041
  payload.branch_name
14948
15042
  );
14949
15043
  autoBindIfUnbound(previewHubId);
14950
- console.log(`Preview written to ${path16.basename(hubFolder)}`);
14951
- console.log(` Switch to it with: wayai use ${path16.basename(hubFolder)}`);
15044
+ console.log(`Preview written to ${path17.basename(hubFolder)}`);
15045
+ console.log(` Switch to it with: wayai use ${path17.basename(hubFolder)}`);
14952
15046
  }
14953
15047
  var init_replicate = __esm({
14954
15048
  "src/commands/replicate.ts"() {
@@ -14970,7 +15064,7 @@ var relabel_exports = {};
14970
15064
  __export(relabel_exports, {
14971
15065
  relabelCommand: () => relabelCommand
14972
15066
  });
14973
- import * as path17 from "path";
15067
+ import * as path18 from "path";
14974
15068
  function parseArgs9(args2) {
14975
15069
  let label;
14976
15070
  let clear = false;
@@ -15014,7 +15108,7 @@ async function relabelCommand(args2) {
15014
15108
  } else {
15015
15109
  console.error(`Multiple hubs found in ${wsLabel}/. Pass --hub <uuid|folder-name> to choose, or run from inside a hub folder:`);
15016
15110
  for (const h of previewHubs) {
15017
- console.error(` ${path17.basename(h.hubFolder)} (${h.hubId})`);
15111
+ console.error(` ${path18.basename(h.hubFolder)} (${h.hubId})`);
15018
15112
  }
15019
15113
  }
15020
15114
  process.exit(1);
@@ -15023,7 +15117,7 @@ async function relabelCommand(args2) {
15023
15117
  console.log("This is a read-only production mirror \u2014 production hubs have no preview label. Relabel the linked preview hub instead.");
15024
15118
  return;
15025
15119
  }
15026
- assertHubMatchesBinding(target.hubId, path17.basename(target.hubFolder));
15120
+ assertHubMatchesBinding(target.hubId, path18.basename(target.hubFolder));
15027
15121
  console.log(normalizedLabel ? `Setting preview label to "${normalizedLabel}"...` : "Clearing preview label...");
15028
15122
  const { data } = await client.relabelPreview(target.hubId, normalizedLabel);
15029
15123
  const row = data[0];
@@ -15039,7 +15133,7 @@ async function relabelCommand(args2) {
15039
15133
  );
15040
15134
  console.log(serverLabel ? `Preview label set to "${serverLabel}".` : "Preview label cleared.");
15041
15135
  if (finalFolder !== target.hubFolder) {
15042
- console.log(`Hub folder is now ${path17.basename(finalFolder)}`);
15136
+ console.log(`Hub folder is now ${path18.basename(finalFolder)}`);
15043
15137
  }
15044
15138
  }
15045
15139
  var init_relabel = __esm({
@@ -15065,7 +15159,7 @@ __export(publish_exports, {
15065
15159
  renderHubDiff: () => renderHubDiff,
15066
15160
  runPublish: () => runPublish
15067
15161
  });
15068
- import * as path18 from "path";
15162
+ import * as path19 from "path";
15069
15163
  function parseArgs10(args2) {
15070
15164
  let autoConfirm = false;
15071
15165
  let hubSelector;
@@ -15171,7 +15265,7 @@ async function publishCommand(args2) {
15171
15265
  return;
15172
15266
  }
15173
15267
  }
15174
- assertHubMatchesBinding(hubId, hubFolder ? path18.basename(hubFolder) : void 0);
15268
+ assertHubMatchesBinding(hubId, hubFolder ? path19.basename(hubFolder) : void 0);
15175
15269
  await runPublish(client, { hubId, localConfig, organizationId, autoConfirm });
15176
15270
  }
15177
15271
  var STATUS_STYLE;
@@ -15203,7 +15297,7 @@ var use_exports = {};
15203
15297
  __export(use_exports, {
15204
15298
  useCommand: () => useCommand
15205
15299
  });
15206
- import * as path19 from "path";
15300
+ import * as path20 from "path";
15207
15301
  async function useCommand(args2) {
15208
15302
  const target = args2[0];
15209
15303
  if (!target || target.startsWith("-")) {
@@ -15225,7 +15319,7 @@ async function useCommand(args2) {
15225
15319
  const match = findHubByFolderName(workspaceDir, target);
15226
15320
  if (!match) {
15227
15321
  const newHubs = scanNewHubs(workspaceDir);
15228
- const pending = newHubs.find((h) => path19.basename(h.hubFolder) === target);
15322
+ const pending = newHubs.find((h) => path20.basename(h.hubFolder) === target);
15229
15323
  if (pending) {
15230
15324
  console.error(
15231
15325
  `"${target}" is a new hub that hasn't been created on the platform yet, so it has no id to bind to.
@@ -15236,10 +15330,10 @@ Create it first \u2014 the worktree binds automatically afterward:
15236
15330
  }
15237
15331
  console.error(`No hub matching "${target}" found in ${wsLabel}/. Pass a UUID or a folder name from:`);
15238
15332
  for (const h of scanWorkspaceHubs(workspaceDir)) {
15239
- console.error(` ${path19.basename(h.hubFolder)} (${h.hubId})`);
15333
+ console.error(` ${path20.basename(h.hubFolder)} (${h.hubId})`);
15240
15334
  }
15241
15335
  for (const h of newHubs) {
15242
- console.error(` ${path19.basename(h.hubFolder)} (new \u2014 "${h.hubName}", run \`wayai create ${path19.basename(h.hubFolder)}\`)`);
15336
+ console.error(` ${path20.basename(h.hubFolder)} (new \u2014 "${h.hubName}", run \`wayai create ${path20.basename(h.hubFolder)}\`)`);
15243
15337
  }
15244
15338
  process.exit(1);
15245
15339
  }
@@ -15278,11 +15372,11 @@ __export(migrate_exports, {
15278
15372
  migrateCommand: () => migrateCommand
15279
15373
  });
15280
15374
  import { execFileSync as execFileSync3 } from "child_process";
15281
- import * as fs15 from "fs";
15282
- import * as path20 from "path";
15375
+ import * as fs16 from "fs";
15376
+ import * as path21 from "path";
15283
15377
  function isTracked(gitRoot, p) {
15284
15378
  try {
15285
- execFileSync3("git", ["ls-files", "--error-unmatch", "--", path20.relative(gitRoot, p)], {
15379
+ execFileSync3("git", ["ls-files", "--error-unmatch", "--", path21.relative(gitRoot, p)], {
15286
15380
  cwd: gitRoot,
15287
15381
  stdio: ["pipe", "pipe", "pipe"]
15288
15382
  });
@@ -15292,10 +15386,10 @@ function isTracked(gitRoot, p) {
15292
15386
  }
15293
15387
  }
15294
15388
  function moveDir(gitRoot, from, to) {
15295
- fs15.mkdirSync(path20.dirname(to), { recursive: true });
15389
+ fs16.mkdirSync(path21.dirname(to), { recursive: true });
15296
15390
  if (isTracked(gitRoot, from)) {
15297
15391
  try {
15298
- execFileSync3("git", ["mv", path20.relative(gitRoot, from), path20.relative(gitRoot, to)], {
15392
+ execFileSync3("git", ["mv", path21.relative(gitRoot, from), path21.relative(gitRoot, to)], {
15299
15393
  cwd: gitRoot,
15300
15394
  stdio: ["pipe", "pipe", "pipe"]
15301
15395
  });
@@ -15303,7 +15397,7 @@ function moveDir(gitRoot, from, to) {
15303
15397
  } catch {
15304
15398
  }
15305
15399
  }
15306
- fs15.renameSync(from, to);
15400
+ fs16.renameSync(from, to);
15307
15401
  return "fs";
15308
15402
  }
15309
15403
  async function migrateCommand(_args) {
@@ -15312,12 +15406,12 @@ async function migrateCommand(_args) {
15312
15406
  console.error("Not inside a git repository.");
15313
15407
  process.exit(1);
15314
15408
  }
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);
15409
+ const rel = (p) => path21.relative(gitRoot, p);
15410
+ const newWs = path21.join(gitRoot, WAYAI_LAYOUT.wsDir);
15411
+ const legacyWs = path21.join(gitRoot, WAYAI_LAYOUT.legacy.wsDir);
15412
+ const legacyOrg = path21.join(gitRoot, WAYAI_LAYOUT.legacy.orgAtRoot);
15413
+ const newHubs = path21.join(newWs, WAYAI_LAYOUT.hubsSubdir);
15414
+ const newOrg = path21.join(newWs, WAYAI_LAYOUT.orgSubdir);
15321
15415
  const hasLegacyWs = isDirectory(legacyWs);
15322
15416
  const hasLegacyOrg = isDirectory(legacyOrg);
15323
15417
  if (!hasLegacyWs && !hasLegacyOrg) {
@@ -16654,8 +16748,8 @@ var eval_capture_exports = {};
16654
16748
  __export(eval_capture_exports, {
16655
16749
  evalCaptureCommand: () => evalCaptureCommand
16656
16750
  });
16657
- import * as fs16 from "fs";
16658
- import * as path21 from "path";
16751
+ import * as fs17 from "fs";
16752
+ import * as path22 from "path";
16659
16753
  import * as yaml7 from "js-yaml";
16660
16754
  function isValidSetName(name) {
16661
16755
  if (name.length === 0 || name === "." || name === "..") return false;
@@ -16721,15 +16815,15 @@ async function evalCaptureCommand(args2) {
16721
16815
  const setFolderName = targetSetName;
16722
16816
  const scenarioName = parsed.evalName ?? `Capture ${parsed.conversationId.slice(0, 8)}`;
16723
16817
  const slug = slugify(scenarioName);
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.`);
16818
+ const evalsDir = path22.join(hubFolder, "evals");
16819
+ const targetDir = path22.join(evalsDir, setFolderName);
16820
+ const targetPath = path22.join(targetDir, `${slug}.yaml`);
16821
+ if (!targetPath.startsWith(evalsDir + path22.sep)) {
16822
+ console.error(`Resolved path "${path22.relative(hubFolder, targetPath)}" escapes evals/. Aborting.`);
16729
16823
  process.exit(1);
16730
16824
  }
16731
- if (fs16.existsSync(targetPath)) {
16732
- console.error(`File already exists: ${path21.relative(hubFolder, targetPath)}. Use --name to choose a different name.`);
16825
+ if (fs17.existsSync(targetPath)) {
16826
+ console.error(`File already exists: ${path22.relative(hubFolder, targetPath)}. Use --name to choose a different name.`);
16733
16827
  process.exit(1);
16734
16828
  }
16735
16829
  console.log("Resolving scenario set...");
@@ -16761,9 +16855,9 @@ async function evalCaptureCommand(args2) {
16761
16855
  ...captured.evaluator_instructions ? { evaluator_instructions: captured.evaluator_instructions } : {}
16762
16856
  };
16763
16857
  const yamlObj = buildEvalYamlObject(evalEntry, slug);
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);
16858
+ fs17.mkdirSync(targetDir, { recursive: true });
16859
+ fs17.writeFileSync(targetPath, yaml7.dump(yamlObj, YAML_DUMP_OPTIONS), "utf-8");
16860
+ const relPath = path22.relative(process.cwd(), targetPath);
16767
16861
  console.log(`
16768
16862
  Wrote ${relPath}`);
16769
16863
  console.log("Run `wayai pull` to refresh the agent display name, then commit. The scenario is already on the platform.");
@@ -17990,23 +18084,23 @@ var init_set_connection_credential = __esm({
17990
18084
  });
17991
18085
 
17992
18086
  // src/lib/org-workspace.ts
17993
- import * as fs17 from "fs";
17994
- import * as path22 from "path";
18087
+ import * as fs18 from "fs";
18088
+ import * as path23 from "path";
17995
18089
  import * as yaml8 from "js-yaml";
17996
18090
  function getOrgDir(gitRoot) {
17997
18091
  return resolveLayout(gitRoot).orgDir;
17998
18092
  }
17999
18093
  function orgManifestExists(orgDir) {
18000
- return fs17.existsSync(path22.join(orgDir, ORG_MANIFEST_NAME));
18094
+ return fs18.existsSync(path23.join(orgDir, ORG_MANIFEST_NAME));
18001
18095
  }
18002
18096
  function parseOrgResources(orgDir) {
18003
- const manifestPath = path22.join(orgDir, ORG_MANIFEST_NAME);
18097
+ const manifestPath = path23.join(orgDir, ORG_MANIFEST_NAME);
18004
18098
  let manifest = {};
18005
- if (fs17.existsSync(manifestPath)) {
18006
- manifest = yaml8.load(fs17.readFileSync(manifestPath, "utf-8")) ?? {};
18099
+ if (fs18.existsSync(manifestPath)) {
18100
+ manifest = yaml8.load(fs18.readFileSync(manifestPath, "utf-8")) ?? {};
18007
18101
  }
18008
18102
  const rawResources = Array.isArray(manifest.resources) ? manifest.resources : [];
18009
- const resourcesDir = path22.join(orgDir, "resources");
18103
+ const resourcesDir = path23.join(orgDir, "resources");
18010
18104
  const resources = rawResources.map((res) => {
18011
18105
  const resource = { name: res.name };
18012
18106
  if (res.id) resource.id = res.id;
@@ -18018,8 +18112,8 @@ function parseOrgResources(orgDir) {
18018
18112
  if (res.environment) resource.environment = res.environment;
18019
18113
  if (Array.isArray(res.tags)) resource.tags = res.tags;
18020
18114
  if (Array.isArray(res.folders)) resource.folders = res.folders;
18021
- const resDir = path22.join(resourcesDir, slugify(resource.name));
18022
- if (fs17.existsSync(resDir)) {
18115
+ const resDir = path23.join(resourcesDir, slugify(resource.name));
18116
+ if (fs18.existsSync(resDir)) {
18023
18117
  const files = scanResourceFiles(resDir, "");
18024
18118
  if (files.length > 0) resource.files = files;
18025
18119
  }
@@ -18028,28 +18122,28 @@ function parseOrgResources(orgDir) {
18028
18122
  return { version: 1, resources };
18029
18123
  }
18030
18124
  function writeOrgResources(orgDir, payload) {
18031
- fs17.mkdirSync(orgDir, { recursive: true });
18125
+ fs18.mkdirSync(orgDir, { recursive: true });
18032
18126
  const resources = payload.resources ?? [];
18033
18127
  const manifestResources = resources.map((r) => {
18034
18128
  const { files: _files, ...rest } = r;
18035
18129
  return rest;
18036
18130
  });
18037
- fs17.writeFileSync(
18038
- path22.join(orgDir, ORG_MANIFEST_NAME),
18131
+ fs18.writeFileSync(
18132
+ path23.join(orgDir, ORG_MANIFEST_NAME),
18039
18133
  yaml8.dump({ version: 1, resources: manifestResources }, YAML_DUMP_OPTIONS),
18040
18134
  "utf-8"
18041
18135
  );
18042
- const resourcesDir = path22.join(orgDir, "resources");
18136
+ const resourcesDir = path23.join(orgDir, "resources");
18043
18137
  const currentSlugs = /* @__PURE__ */ new Set();
18044
18138
  for (const resource of resources) {
18045
18139
  const resSlug = slugify(resource.name);
18046
18140
  currentSlugs.add(resSlug);
18047
- writeResourceFileTree(path22.join(resourcesDir, resSlug), resource.files || []);
18141
+ writeResourceFileTree(path23.join(resourcesDir, resSlug), resource.files || []);
18048
18142
  }
18049
- if (fs17.existsSync(resourcesDir)) {
18050
- for (const entry of fs17.readdirSync(resourcesDir, { withFileTypes: true })) {
18143
+ if (fs18.existsSync(resourcesDir)) {
18144
+ for (const entry of fs18.readdirSync(resourcesDir, { withFileTypes: true })) {
18051
18145
  if (entry.isDirectory() && !currentSlugs.has(entry.name)) {
18052
- fs17.rmSync(path22.join(resourcesDir, entry.name), { recursive: true, force: true });
18146
+ fs18.rmSync(path23.join(resourcesDir, entry.name), { recursive: true, force: true });
18053
18147
  }
18054
18148
  }
18055
18149
  }
@@ -18058,7 +18152,7 @@ async function downloadOrgBinaryFiles(orgDir, payload) {
18058
18152
  let count = 0;
18059
18153
  for (const resource of payload.resources ?? []) {
18060
18154
  if (!resource.files) continue;
18061
- const resDir = path22.join(orgDir, "resources", slugify(resource.name));
18155
+ const resDir = path23.join(orgDir, "resources", slugify(resource.name));
18062
18156
  count += await downloadBinaryFiles(resDir, resource.files);
18063
18157
  }
18064
18158
  if (count > 0) console.log(`Downloaded ${count} binary resource file(s).`);
@@ -18314,20 +18408,20 @@ var init_list = __esm({
18314
18408
  });
18315
18409
 
18316
18410
  // src/lib/template-files.ts
18317
- import * as fs18 from "fs";
18318
- import * as path23 from "path";
18411
+ import * as fs19 from "fs";
18412
+ import * as path24 from "path";
18319
18413
  function readDirToFileMap(rootDir) {
18320
18414
  const out = {};
18321
18415
  function walk(dir, prefix) {
18322
- const entries = fs18.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
18416
+ const entries = fs19.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
18323
18417
  for (const entry of entries) {
18324
- const abs = path23.join(dir, entry.name);
18418
+ const abs = path24.join(dir, entry.name);
18325
18419
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
18326
18420
  if (entry.isDirectory()) walk(abs, rel);
18327
- else if (entry.isFile()) out[rel] = fs18.readFileSync(abs, "utf-8");
18421
+ else if (entry.isFile()) out[rel] = fs19.readFileSync(abs, "utf-8");
18328
18422
  }
18329
18423
  }
18330
- if (fs18.existsSync(rootDir)) walk(rootDir, "");
18424
+ if (fs19.existsSync(rootDir)) walk(rootDir, "");
18331
18425
  return out;
18332
18426
  }
18333
18427
  function detectCollisions(targetDir, files) {
@@ -18336,7 +18430,7 @@ function detectCollisions(targetDir, files) {
18336
18430
  if (!isSafeTemplatePath2(rel)) {
18337
18431
  throw new Error(`Refusing to inspect unsafe template path: ${rel}`);
18338
18432
  }
18339
- if (fs18.existsSync(path23.join(targetDir, rel))) collisions.push(rel);
18433
+ if (fs19.existsSync(path24.join(targetDir, rel))) collisions.push(rel);
18340
18434
  }
18341
18435
  return collisions.sort((a, b) => a.localeCompare(b));
18342
18436
  }
@@ -18346,9 +18440,9 @@ function writeFileMap(targetDir, files) {
18346
18440
  if (!isSafeTemplatePath2(rel)) {
18347
18441
  throw new Error(`Refusing to write unsafe template path: ${rel}`);
18348
18442
  }
18349
- const abs = path23.join(targetDir, rel);
18350
- fs18.mkdirSync(path23.dirname(abs), { recursive: true });
18351
- fs18.writeFileSync(abs, body, "utf-8");
18443
+ const abs = path24.join(targetDir, rel);
18444
+ fs19.mkdirSync(path24.dirname(abs), { recursive: true });
18445
+ fs19.writeFileSync(abs, body, "utf-8");
18352
18446
  written.push(rel);
18353
18447
  }
18354
18448
  return written;
@@ -18356,20 +18450,20 @@ function writeFileMap(targetDir, files) {
18356
18450
  function listDirRelFiles(dir) {
18357
18451
  const out = [];
18358
18452
  function walk(d, prefix) {
18359
- for (const entry of fs18.readdirSync(d, { withFileTypes: true })) {
18453
+ for (const entry of fs19.readdirSync(d, { withFileTypes: true })) {
18360
18454
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
18361
- if (entry.isDirectory()) walk(path23.join(d, entry.name), rel);
18455
+ if (entry.isDirectory()) walk(path24.join(d, entry.name), rel);
18362
18456
  else if (entry.isFile()) out.push(rel);
18363
18457
  }
18364
18458
  }
18365
- if (fs18.existsSync(dir)) walk(dir, "");
18459
+ if (fs19.existsSync(dir)) walk(dir, "");
18366
18460
  return out;
18367
18461
  }
18368
18462
  function writeSliceSnapshot(targetDir, files) {
18369
18463
  const keep = new Set(Object.keys(files));
18370
18464
  const removed = listDirRelFiles(targetDir).filter((rel) => !keep.has(rel)).sort((a, b) => a.localeCompare(b));
18371
18465
  const written = writeFileMap(targetDir, files).sort((a, b) => a.localeCompare(b));
18372
- if (fs18.existsSync(targetDir)) cleanOrphanFiles(targetDir, "", keep);
18466
+ if (fs19.existsSync(targetDir)) cleanOrphanFiles(targetDir, "", keep);
18373
18467
  return { written, removed };
18374
18468
  }
18375
18469
  var init_template_files = __esm({
@@ -18385,7 +18479,7 @@ var templates_exports = {};
18385
18479
  __export(templates_exports, {
18386
18480
  templateCommand: () => templateCommand
18387
18481
  });
18388
- import * as path24 from "path";
18482
+ import * as path25 from "path";
18389
18483
  async function templateCommand(args2) {
18390
18484
  const [sub, ...rest] = args2;
18391
18485
  switch (sub) {
@@ -18501,8 +18595,8 @@ async function runTemplatePull(rest) {
18501
18595
  console.log(`Template "${slug}" has no WayAI slice${hint}`);
18502
18596
  return;
18503
18597
  }
18504
- const targetDir = path24.join(resolveLayout(gitRoot).hubsDir, slug);
18505
- const relTarget = path24.relative(gitRoot, targetDir);
18598
+ const targetDir = path25.join(resolveLayout(gitRoot).hubsDir, slug);
18599
+ const relTarget = path25.relative(gitRoot, targetDir);
18506
18600
  const collisions = detectCollisions(targetDir, detail.files);
18507
18601
  if (dryRun) {
18508
18602
  const planned = Object.keys(detail.files).sort((a, b) => a.localeCompare(b));
@@ -18676,8 +18770,8 @@ var admin_exports = {};
18676
18770
  __export(admin_exports, {
18677
18771
  adminCommand: () => adminCommand
18678
18772
  });
18679
- import * as fs19 from "fs";
18680
- import * as path25 from "path";
18773
+ import * as fs20 from "fs";
18774
+ import * as path26 from "path";
18681
18775
  import * as yaml10 from "js-yaml";
18682
18776
  async function adminCommand(args2) {
18683
18777
  const [group, ...afterGroup] = args2;
@@ -18985,7 +19079,7 @@ async function runArchiveRead(positional, flagArgs) {
18985
19079
  exitOnApiError(err);
18986
19080
  throw err;
18987
19081
  }
18988
- fs19.writeFileSync(outPath, zip);
19082
+ fs20.writeFileSync(outPath, zip);
18989
19083
  console.log(`Wrote ${zip.byteLength} bytes to ${outPath}`);
18990
19084
  return;
18991
19085
  }
@@ -19117,15 +19211,15 @@ function loadTemplateManifest(slug) {
19117
19211
  console.error("Not in a git repository. Run from the tutorials/ authoring repo.");
19118
19212
  process.exit(1);
19119
19213
  }
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)}`);
19214
+ const templateDir = path26.join(resolveTemplatesDir(gitRoot), slug);
19215
+ const manifestPath = path26.join(templateDir, "template.yaml");
19216
+ if (!fs20.existsSync(manifestPath)) {
19217
+ console.error(`template.yaml not found at ${path26.relative(gitRoot, manifestPath)}`);
19124
19218
  process.exit(1);
19125
19219
  }
19126
19220
  let manifest;
19127
19221
  try {
19128
- manifest = templateYamlSchema2.parse(yaml10.load(fs19.readFileSync(manifestPath, "utf-8")));
19222
+ manifest = templateYamlSchema2.parse(yaml10.load(fs20.readFileSync(manifestPath, "utf-8")));
19129
19223
  } catch (err) {
19130
19224
  console.error(`Invalid template.yaml: ${err instanceof Error ? err.message : String(err)}`);
19131
19225
  process.exit(1);
@@ -19155,20 +19249,20 @@ async function runTemplatePush(positional) {
19155
19249
  const wayaiEntry = manifest.wayai.locales[locale];
19156
19250
  let wayaiFiles;
19157
19251
  if (wayaiEntry) {
19158
- const sliceDir = path25.resolve(templateDir, wayaiEntry.source);
19159
- if (!fs19.existsSync(sliceDir)) {
19252
+ const sliceDir = path26.resolve(templateDir, wayaiEntry.source);
19253
+ if (!fs20.existsSync(sliceDir)) {
19160
19254
  console.error(`wayai source not found for ${locale}: ${wayaiEntry.source} (resolved ${sliceDir})`);
19161
19255
  process.exit(1);
19162
19256
  }
19163
19257
  if (!isInsideTemplateDir(sliceDir, templateDir)) {
19164
19258
  console.warn(
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.`
19259
+ `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 ${path26.basename(sliceDir)}\` to commit a stable frozen slice.`
19166
19260
  );
19167
19261
  }
19168
19262
  wayaiFiles = readDirToFileMap(sliceDir);
19169
19263
  }
19170
- const readmePath = path25.join(templateDir, `README.${locale}.md`);
19171
- const readmeMarkdown = fs19.existsSync(readmePath) ? fs19.readFileSync(readmePath, "utf-8") : "";
19264
+ const readmePath = path26.join(templateDir, `README.${locale}.md`);
19265
+ const readmeMarkdown = fs20.existsSync(readmePath) ? fs20.readFileSync(readmePath, "utf-8") : "";
19172
19266
  locales[locale] = {
19173
19267
  readmeMarkdown,
19174
19268
  ...wayaiFiles && { wayaiFiles },
@@ -19179,9 +19273,9 @@ async function runTemplatePush(positional) {
19179
19273
  }
19180
19274
  let hero;
19181
19275
  if (manifest.hero) {
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") };
19276
+ const heroPath = path26.resolve(templateDir, manifest.hero);
19277
+ if (fs20.existsSync(heroPath)) {
19278
+ hero = { filename: path26.basename(heroPath), dataBase64: fs20.readFileSync(heroPath).toString("base64") };
19185
19279
  } else {
19186
19280
  console.error(`Warning: hero not found at ${manifest.hero}; skipping.`);
19187
19281
  }
@@ -19207,7 +19301,7 @@ async function runTemplatePush(positional) {
19207
19301
  }
19208
19302
  }
19209
19303
  function isInsideTemplateDir(dest, templateDir) {
19210
- return dest === templateDir || dest.startsWith(templateDir + path25.sep);
19304
+ return dest === templateDir || dest.startsWith(templateDir + path26.sep);
19211
19305
  }
19212
19306
  async function runTemplateFreeze(positional, flagArgs) {
19213
19307
  const slug = positional[0];
@@ -19268,7 +19362,7 @@ async function runTemplateFreeze(positional, flagArgs) {
19268
19362
  process.exit(1);
19269
19363
  }
19270
19364
  const entry = manifest.wayai.locales[targetLocale];
19271
- const dest = path25.resolve(templateDir, entry.source);
19365
+ const dest = path26.resolve(templateDir, entry.source);
19272
19366
  if (!isInsideTemplateDir(dest, templateDir) || dest === templateDir) {
19273
19367
  console.error(
19274
19368
  `source for "${targetLocale}" must be a committed path inside ${slug}/ (e.g. "./${targetLocale}/slice"), but resolved to:
@@ -19287,7 +19381,7 @@ Set it to a subdir of the template folder and re-run freeze.`
19287
19381
  const hubs = scanWorkspaceHubs(hubsDir);
19288
19382
  if (hubs.length) {
19289
19383
  console.error("Available hubs:");
19290
- for (const h of hubs) console.error(` ${path25.basename(h.hubFolder)} (${h.hubId})`);
19384
+ for (const h of hubs) console.error(` ${path26.basename(h.hubFolder)} (${h.hubId})`);
19291
19385
  }
19292
19386
  console.error(`
19293
19387
  Pass --from <folder|uuid>${selector ? "." : " or run `wayai use <hub>` first."}`);
@@ -19295,12 +19389,12 @@ Pass --from <folder|uuid>${selector ? "." : " or run `wayai use <hub>` first."}`
19295
19389
  }
19296
19390
  const liveFiles = readDirToFileMap(hubFolder);
19297
19391
  if (Object.keys(liveFiles).length === 0) {
19298
- console.error(`Source hub folder has no files to freeze: ${path25.relative(gitRoot, hubFolder)}`);
19392
+ console.error(`Source hub folder has no files to freeze: ${path26.relative(gitRoot, hubFolder)}`);
19299
19393
  process.exit(1);
19300
19394
  }
19301
19395
  const sanitized = sanitizeWayaiSliceFiles(liveFiles);
19302
- const relDest = path25.relative(gitRoot, dest);
19303
- const relSrc = path25.relative(gitRoot, hubFolder);
19396
+ const relDest = path26.relative(gitRoot, dest);
19397
+ const relSrc = path26.relative(gitRoot, hubFolder);
19304
19398
  if (dryRun) {
19305
19399
  const existing = new Set(listDirRelFiles(dest));
19306
19400
  const nextKeys = new Set(Object.keys(sanitized));
@@ -19360,7 +19454,7 @@ async function runTemplatePull2(positional, flagArgs) {
19360
19454
  console.log(JSON.stringify(detail, null, 2));
19361
19455
  return;
19362
19456
  }
19363
- const target = outDir ? path25.resolve(outDir) : path25.join(process.cwd(), "template-store-pull", slug);
19457
+ const target = outDir ? path26.resolve(outDir) : path26.join(process.cwd(), "template-store-pull", slug);
19364
19458
  const written = writeFileMap(target, detail.files);
19365
19459
  console.log(`Pulled "${slug}" from the store \u2192 ${target} (${written.length} file${written.length === 1 ? "" : "s"}).`);
19366
19460
  const uses = detail.uses ?? [];
@@ -19383,13 +19477,13 @@ async function runSkillInstall(positional) {
19383
19477
  throw err;
19384
19478
  }
19385
19479
  const root = findGitRoot() ?? process.cwd();
19386
- const present = HARNESS_SKILL_DIRS.filter((dir) => fs19.existsSync(path25.join(root, dir)));
19480
+ const present = HARNESS_SKILL_DIRS.filter((dir) => fs20.existsSync(path26.join(root, dir)));
19387
19481
  const targets = present.length > 0 ? present : HARNESS_SKILL_DIRS;
19388
19482
  const fileCount = Object.keys(res.files).length;
19389
19483
  const relDirs = targets.map((harness) => {
19390
- const targetDir = path25.join(root, harness, "skills", name);
19484
+ const targetDir = path26.join(root, harness, "skills", name);
19391
19485
  writeFileMap(targetDir, res.files);
19392
- return `${path25.relative(root, targetDir)}/`;
19486
+ return `${path26.relative(root, targetDir)}/`;
19393
19487
  });
19394
19488
  console.log(`Installed skill "${name}" (${fileCount} file${fileCount === 1 ? "" : "s"}) \u2192 ${relDirs.join(", ")}`);
19395
19489
  console.log("Reload your agent (e.g. restart Claude Code) to pick up the skill.");
@@ -20129,7 +20223,7 @@ Usage:
20129
20223
 
20130
20224
  Sources:
20131
20225
  do Live DO SQLite (existing conversation, hub config, etc.).
20132
- analytics ClickHouse projections (conversation, message, schedule_event).
20226
+ analytics ClickHouse projections (conversation, schedule_event).
20133
20227
  archive R2 archive blob \u2014 canonical content for ended conversations after DO cleanup.
20134
20228
  observability R2 LLM observability \u2014 per-message OTel GenAI records (prompts, completions,
20135
20229
  tool calls, tokens, latency). Default lists all records for the conversation;
@@ -20179,7 +20273,6 @@ Entity id forms (do):
20179
20273
  Examples:
20180
20274
  wayai admin do tables hub 018fab...
20181
20275
  wayai admin do read conversation <conv-id> message --limit 5 --json
20182
- wayai admin analytics read message --conversation-id <conv-id>
20183
20276
  wayai admin analytics read conversation --conversation-id <conv-id>
20184
20277
  wayai admin archive <hub-id> <conv-id>
20185
20278
  wayai admin archive <hub-id> <conv-id> --message-id <msg-id> --json
@@ -20668,7 +20761,7 @@ var init_update = __esm({
20668
20761
  init_sentry();
20669
20762
  import { readFileSync as readFileSync18 } from "fs";
20670
20763
  import { fileURLToPath as fileURLToPath2 } from "url";
20671
- import { dirname as dirname9, join as join24 } from "path";
20764
+ import { dirname as dirname9, join as join25 } from "path";
20672
20765
 
20673
20766
  // src/lib/errors.ts
20674
20767
  init_api_client();
@@ -20848,7 +20941,7 @@ Run \`wayai admin skill install\` to update.`);
20848
20941
 
20849
20942
  // src/index.ts
20850
20943
  var __dirname = dirname9(fileURLToPath2(import.meta.url));
20851
- var pkg = JSON.parse(readFileSync18(join24(__dirname, "..", "package.json"), "utf-8"));
20944
+ var pkg = JSON.parse(readFileSync18(join25(__dirname, "..", "package.json"), "utf-8"));
20852
20945
  var [, , command, ...args] = process.argv;
20853
20946
  var isBackgroundRefresh = command === REFRESH_COMMAND;
20854
20947
  if (!isBackgroundRefresh) initSentry(command, pkg.version);