@wayai/cli 0.3.47 → 0.3.48

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
@@ -5031,6 +5031,22 @@ function slugifyKebab(input, maxLength = 64) {
5031
5031
  if (typeof input !== "string") return "";
5032
5032
  return foldDiacritics(input).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/-+/g, "-").slice(0, maxLength).replace(/^-|-$/g, "");
5033
5033
  }
5034
+ function ensureUniqueSlug(slug, used) {
5035
+ if (!used.has(slug)) {
5036
+ used.add(slug);
5037
+ return slug;
5038
+ }
5039
+ for (let i = 2; i < 1e6; i++) {
5040
+ const suffix = `_${i}`;
5041
+ const baseLen = Math.max(1, 50 - suffix.length);
5042
+ const candidate = `${slug.slice(0, baseLen)}${suffix}`;
5043
+ if (!used.has(candidate)) {
5044
+ used.add(candidate);
5045
+ return candidate;
5046
+ }
5047
+ }
5048
+ throw new Error(`slug collision space exhausted for "${slug}"`);
5049
+ }
5034
5050
  function slugifySkillName(name) {
5035
5051
  return slugifyKebab(name, 64);
5036
5052
  }
@@ -9508,6 +9524,7 @@ function writeHubFolder(hubFolder, payload) {
9508
9524
  }
9509
9525
  writeResourceFiles(hubFolder, payload.resources || []);
9510
9526
  writeEvalYamlFiles(hubFolder, payload.evals || []);
9527
+ writeJourneyYamlFiles(hubFolder, payload.journeys || []);
9511
9528
  }
9512
9529
  function buildYamlPayload(payload) {
9513
9530
  const result = {
@@ -9634,6 +9651,60 @@ function cleanEvalOrphans(evalsDir, writtenRelPaths) {
9634
9651
  }
9635
9652
  }
9636
9653
  }
9654
+ function buildJourneyYamlObject(journeyEntry, slug) {
9655
+ const out = {};
9656
+ if (journeyEntry.id) out.id = journeyEntry.id;
9657
+ if (journeyEntry.name !== slug) out.name = journeyEntry.name;
9658
+ out.agent = journeyEntry.agent;
9659
+ if (journeyEntry.agent_id) out.agent_id = journeyEntry.agent_id;
9660
+ if (journeyEntry.enabled === false) {
9661
+ out.enabled = false;
9662
+ }
9663
+ if (journeyEntry.evaluator_instructions) {
9664
+ out.evaluator_instructions = journeyEntry.evaluator_instructions;
9665
+ }
9666
+ if (journeyEntry.transcript && journeyEntry.transcript.length > 0) {
9667
+ out.transcript = journeyEntry.transcript;
9668
+ }
9669
+ if (journeyEntry.step_config && Object.keys(journeyEntry.step_config).length > 0) {
9670
+ out.step_config = journeyEntry.step_config;
9671
+ }
9672
+ return out;
9673
+ }
9674
+ function writeJourneyYamlFiles(hubFolder, journeys) {
9675
+ const journeysDir = path11.join(hubFolder, "journeys");
9676
+ if (journeys.length === 0) {
9677
+ if (fs9.existsSync(journeysDir)) {
9678
+ cleanJourneyOrphans(journeysDir, /* @__PURE__ */ new Set());
9679
+ try {
9680
+ if (fs9.readdirSync(journeysDir).length === 0) fs9.rmdirSync(journeysDir);
9681
+ } catch {
9682
+ }
9683
+ }
9684
+ return;
9685
+ }
9686
+ if (!fs9.existsSync(journeysDir)) {
9687
+ fs9.mkdirSync(journeysDir, { recursive: true });
9688
+ }
9689
+ const writtenFiles = /* @__PURE__ */ new Set();
9690
+ const usedSlugs = /* @__PURE__ */ new Set();
9691
+ for (const journeyEntry of journeys) {
9692
+ const slug = ensureUniqueSlug(slugify(journeyEntry.name), usedSlugs);
9693
+ const fileName = `${slug}.yaml`;
9694
+ const yamlContent = yaml4.dump(buildJourneyYamlObject(journeyEntry, slug), YAML_DUMP_OPTIONS);
9695
+ fs9.writeFileSync(path11.join(journeysDir, fileName), yamlContent, "utf-8");
9696
+ writtenFiles.add(fileName);
9697
+ }
9698
+ cleanJourneyOrphans(journeysDir, writtenFiles);
9699
+ }
9700
+ function cleanJourneyOrphans(journeysDir, writtenFiles) {
9701
+ const entries = fs9.readdirSync(journeysDir, { withFileTypes: true });
9702
+ for (const entry of entries) {
9703
+ if (entry.isFile() && entry.name.endsWith(".yaml") && !writtenFiles.has(entry.name)) {
9704
+ fs9.unlinkSync(path11.join(journeysDir, entry.name));
9705
+ }
9706
+ }
9707
+ }
9637
9708
  function writeResourceFiles(hubFolder, resources) {
9638
9709
  const resourcesDir = path11.join(hubFolder, "resources");
9639
9710
  const currentSlugs = /* @__PURE__ */ new Set();
@@ -9656,6 +9727,7 @@ var YAML_DUMP_OPTIONS;
9656
9727
  var init_yaml_writer = __esm({
9657
9728
  "src/lib/yaml-writer.ts"() {
9658
9729
  "use strict";
9730
+ init_dist();
9659
9731
  init_utils();
9660
9732
  init_resource_files();
9661
9733
  YAML_DUMP_OPTIONS = {
@@ -9777,6 +9849,10 @@ function parseHubFolder(hubFolder, opts) {
9777
9849
  if (evals.length > 0) {
9778
9850
  payload.evals = evals;
9779
9851
  }
9852
+ const journeys = scanJourneyYamlFiles(hubFolder);
9853
+ if (journeys.length > 0) {
9854
+ payload.journeys = journeys;
9855
+ }
9780
9856
  return payload;
9781
9857
  }
9782
9858
  function scanEvalYamlFiles(hubFolder) {
@@ -9865,6 +9941,76 @@ function parseEvalYaml(filePath, relPath, setName) {
9865
9941
  }
9866
9942
  return evalEntry;
9867
9943
  }
9944
+ function scanJourneyYamlFiles(hubFolder) {
9945
+ const journeysDir = path12.join(hubFolder, "journeys");
9946
+ if (!fs10.existsSync(journeysDir)) return [];
9947
+ const journeys = [];
9948
+ const seen = /* @__PURE__ */ new Set();
9949
+ const entries = fs10.readdirSync(journeysDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
9950
+ for (const entry of entries) {
9951
+ if (entry.isDirectory()) {
9952
+ throw expected(
9953
+ `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.`
9954
+ );
9955
+ }
9956
+ if (!entry.isFile() || !entry.name.endsWith(".yaml")) continue;
9957
+ const journeyEntry = parseJourneyYaml(path12.join(journeysDir, entry.name), `journeys/${entry.name}`);
9958
+ if (!journeyEntry) continue;
9959
+ if (seen.has(journeyEntry.name)) {
9960
+ throw expected(
9961
+ `Duplicate journey: "${journeyEntry.name}" (in ${entry.name}). Each journey name must be unique.`
9962
+ );
9963
+ }
9964
+ seen.add(journeyEntry.name);
9965
+ journeys.push(journeyEntry);
9966
+ }
9967
+ return journeys;
9968
+ }
9969
+ function parseJourneyYaml(filePath, relPath) {
9970
+ const content = fs10.readFileSync(filePath, "utf-8");
9971
+ let raw;
9972
+ try {
9973
+ raw = yaml5.load(content);
9974
+ } catch (err) {
9975
+ if (err instanceof yaml5.YAMLException) {
9976
+ throw expected(`Invalid YAML in ${relPath}: ${err.message}`);
9977
+ }
9978
+ throw err;
9979
+ }
9980
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
9981
+ console.warn(` Warning: skipping ${relPath} (not a YAML object)`);
9982
+ return null;
9983
+ }
9984
+ const data = raw;
9985
+ const fileSlug = path12.basename(filePath, ".yaml");
9986
+ const journeyName = typeof data.name === "string" && data.name.trim().length > 0 ? data.name : fileSlug;
9987
+ if (typeof data.agent !== "string" || data.agent.trim().length === 0) {
9988
+ throw expected(`Journey "${journeyName}" in ${relPath}: missing required field "agent" (string).`);
9989
+ }
9990
+ if (data.transcript !== void 0 && !Array.isArray(data.transcript)) {
9991
+ throw expected(`Journey "${journeyName}" in ${relPath}: "transcript" must be an array.`);
9992
+ }
9993
+ if (data.step_config !== void 0 && (typeof data.step_config !== "object" || Array.isArray(data.step_config) || data.step_config === null)) {
9994
+ throw expected(`Journey "${journeyName}" in ${relPath}: "step_config" must be an object keyed by step_id.`);
9995
+ }
9996
+ const journeyEntry = {
9997
+ name: journeyName,
9998
+ agent: data.agent
9999
+ };
10000
+ if (typeof data.id === "string") journeyEntry.id = data.id;
10001
+ if (typeof data.agent_id === "string") journeyEntry.agent_id = data.agent_id;
10002
+ if (data.enabled === false) journeyEntry.enabled = false;
10003
+ if (typeof data.evaluator_instructions === "string") {
10004
+ journeyEntry.evaluator_instructions = data.evaluator_instructions;
10005
+ }
10006
+ if (Array.isArray(data.transcript)) {
10007
+ journeyEntry.transcript = data.transcript;
10008
+ }
10009
+ if (data.step_config && typeof data.step_config === "object" && !Array.isArray(data.step_config)) {
10010
+ journeyEntry.step_config = data.step_config;
10011
+ }
10012
+ return journeyEntry;
10013
+ }
9868
10014
  function scanAgentYamlFiles(hubFolder) {
9869
10015
  const agentsDir = path12.join(hubFolder, "agents");
9870
10016
  if (!fs10.existsSync(agentsDir)) return [];
@@ -10179,6 +10325,12 @@ Sync complete. Preview hub: ${result.preview_hub_id}`);
10179
10325
  if (c.states_created > 0) parts.push(`${c.states_created} state(s) created`);
10180
10326
  if (c.states_updated > 0) parts.push(`${c.states_updated} state(s) updated`);
10181
10327
  if (c.states_deleted > 0) parts.push(`${c.states_deleted} state(s) deleted`);
10328
+ if (c.evals_created > 0) parts.push(`${c.evals_created} eval(s) created`);
10329
+ if (c.evals_updated > 0) parts.push(`${c.evals_updated} eval(s) updated`);
10330
+ if (c.evals_deleted > 0) parts.push(`${c.evals_deleted} eval(s) deleted`);
10331
+ if (c.journeys_created > 0) parts.push(`${c.journeys_created} journey(s) created`);
10332
+ if (c.journeys_updated > 0) parts.push(`${c.journeys_updated} journey(s) updated`);
10333
+ if (c.journeys_deleted > 0) parts.push(`${c.journeys_deleted} journey(s) deleted`);
10182
10334
  if (c.teams_created > 0) parts.push(`${c.teams_created} team(s) created`);
10183
10335
  if (c.teams_updated > 0) parts.push(`${c.teams_updated} team(s) updated`);
10184
10336
  if (c.teams_deleted > 0) parts.push(`${c.teams_deleted} team(s) deleted`);