@wayai/cli 0.3.69 → 0.3.71

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
@@ -7855,6 +7855,24 @@ var init_layout = __esm({
7855
7855
  });
7856
7856
 
7857
7857
  // src/lib/workspace.ts
7858
+ var workspace_exports = {};
7859
+ __export(workspace_exports, {
7860
+ autoRenameHubFolder: () => autoRenameHubFolder,
7861
+ detectWorkspace: () => detectWorkspace,
7862
+ findEnclosingHubFolder: () => findEnclosingHubFolder,
7863
+ findGitRoot: () => findGitRoot,
7864
+ findHubByFolderName: () => findHubByFolderName,
7865
+ findLocalHubFolder: () => findLocalHubFolder,
7866
+ findRepoRootSync: () => findRepoRootSync,
7867
+ getChangedHubs: () => getChangedHubs,
7868
+ getHubFolderSlug: () => getHubFolderSlug,
7869
+ resolveActiveHubId: () => resolveActiveHubId,
7870
+ resolveExplicitHubPath: () => resolveExplicitHubPath,
7871
+ resolveHubFolder: () => resolveHubFolder,
7872
+ resolveHubFolderBySelector: () => resolveHubFolderBySelector,
7873
+ scanNewHubs: () => scanNewHubs,
7874
+ scanWorkspaceHubs: () => scanWorkspaceHubs
7875
+ });
7858
7876
  import { execFileSync } from "child_process";
7859
7877
  import * as fs2 from "fs";
7860
7878
  import * as path2 from "path";
@@ -7957,6 +7975,79 @@ function findLocalHubFolder(hubId) {
7957
7975
  const match = scanWorkspaceHubs(workspaceDir).find((h) => h.hubId === hubId);
7958
7976
  return match ? match.hubFolder : null;
7959
7977
  }
7978
+ function getChangedHubs(workspaceDir) {
7979
+ const gitRoot = findGitRoot();
7980
+ if (!gitRoot) return [];
7981
+ const relWorkspace = path2.relative(gitRoot, workspaceDir);
7982
+ const normalizedRel = path2.normalize(relWorkspace);
7983
+ if (normalizedRel.startsWith("..") || path2.isAbsolute(normalizedRel)) {
7984
+ return [];
7985
+ }
7986
+ let statusOutput;
7987
+ try {
7988
+ statusOutput = execFileSync("git", ["status", "--porcelain", "-u", "--", `${relWorkspace}/`], {
7989
+ encoding: "utf-8",
7990
+ cwd: gitRoot,
7991
+ stdio: ["pipe", "pipe", "pipe"]
7992
+ });
7993
+ } catch {
7994
+ return [];
7995
+ }
7996
+ const lines = statusOutput.split("\n").filter((l) => l.length > 0);
7997
+ const changedFiles = lines.map((line) => {
7998
+ const filePart = line.slice(3);
7999
+ const arrowIdx = filePart.indexOf(" -> ");
8000
+ return arrowIdx >= 0 ? filePart.slice(arrowIdx + 4) : filePart;
8001
+ });
8002
+ const hubFiles = changedFiles.filter((file) => {
8003
+ return file.endsWith("/hub.yaml") || file.endsWith("hub.yaml") || file.endsWith("/wayai.yaml") || file.endsWith("wayai.yaml") || /\/agents\/[^/]+\.(md|yaml)$/.test(file);
8004
+ });
8005
+ if (hubFiles.length === 0) return [];
8006
+ const hubFolders = /* @__PURE__ */ new Set();
8007
+ for (const file of hubFiles) {
8008
+ const absFile = path2.resolve(gitRoot, file);
8009
+ if (file.endsWith("hub.yaml") || file.endsWith("wayai.yaml")) {
8010
+ hubFolders.add(path2.dirname(absFile));
8011
+ } else if (file.includes("/agents/")) {
8012
+ const agentsIndex = absFile.lastIndexOf("/agents/");
8013
+ hubFolders.add(absFile.substring(0, agentsIndex));
8014
+ }
8015
+ }
8016
+ const hubs = [];
8017
+ for (const hubFolder of hubFolders) {
8018
+ const meta = readHubYaml(path2.join(hubFolder, "hub.yaml")) || readHubYaml(path2.join(hubFolder, "wayai.yaml"));
8019
+ if (meta) {
8020
+ hubs.push({ hubFolder, hubId: meta.hubId, hubEnvironment: meta.hubEnvironment });
8021
+ }
8022
+ }
8023
+ return hubs;
8024
+ }
8025
+ function resolveExplicitHubPath(hubPath) {
8026
+ const parts = hubPath.split("/");
8027
+ let hubSegment;
8028
+ let orgPrefix;
8029
+ if (parts.length === 1) {
8030
+ hubSegment = parts[0];
8031
+ } else if (parts.length === 2) {
8032
+ [orgPrefix, hubSegment] = parts;
8033
+ } else {
8034
+ throw new Error("Hub path must be hub or org/hub");
8035
+ }
8036
+ const workspace = detectWorkspace();
8037
+ if (workspace) {
8038
+ const local = findHubByFolderName(workspace.workspaceDir, hubSegment);
8039
+ if (local) {
8040
+ return {
8041
+ resolved: {
8042
+ hubId: local.hubId,
8043
+ hubFolder: local.hubFolder,
8044
+ hubEnvironment: local.hubEnvironment
8045
+ }
8046
+ };
8047
+ }
8048
+ }
8049
+ return { segments: { orgPrefix, hub: hubSegment } };
8050
+ }
7960
8051
  function findHubByFolderName(workspaceDir, hubFolderName) {
7961
8052
  const all = scanWorkspaceHubs(workspaceDir);
7962
8053
  return all.find((h) => path2.basename(h.hubFolder) === hubFolderName) ?? null;
@@ -9013,6 +9104,51 @@ var init_auth = __esm({
9013
9104
  }
9014
9105
  });
9015
9106
 
9107
+ // src/lib/skill-symlink.ts
9108
+ var skill_symlink_exports = {};
9109
+ __export(skill_symlink_exports, {
9110
+ healClaudeSkillLink: () => healClaudeSkillLink,
9111
+ healSkillLinkForCommand: () => healSkillLinkForCommand
9112
+ });
9113
+ import { existsSync as existsSync8, lstatSync, mkdirSync as mkdirSync4, rmSync, symlinkSync } from "fs";
9114
+ import { join as join10 } from "path";
9115
+ function healClaudeSkillLink(root) {
9116
+ try {
9117
+ const source = join10(root, ".agents", "skills", SKILL_NAME);
9118
+ if (!existsSync8(join10(source, SKILL_FILENAME))) return false;
9119
+ const link = join10(root, ".claude", "skills", SKILL_NAME);
9120
+ if (existsSync8(join10(link, SKILL_FILENAME))) return false;
9121
+ let entry = null;
9122
+ try {
9123
+ entry = lstatSync(link);
9124
+ } catch {
9125
+ entry = null;
9126
+ }
9127
+ if (entry) {
9128
+ if (!entry.isSymbolicLink()) return false;
9129
+ rmSync(link, { force: true });
9130
+ }
9131
+ mkdirSync4(join10(root, ".claude", "skills"), { recursive: true });
9132
+ symlinkSync(join10("..", "..", ".agents", "skills", SKILL_NAME), link, "dir");
9133
+ return true;
9134
+ } catch {
9135
+ return false;
9136
+ }
9137
+ }
9138
+ function healSkillLinkForCommand(command2, root) {
9139
+ if (!command2 || HEAL_SKIP_COMMANDS.has(command2)) return false;
9140
+ return healClaudeSkillLink(root);
9141
+ }
9142
+ var SKILL_NAME, HEAL_SKIP_COMMANDS;
9143
+ var init_skill_symlink = __esm({
9144
+ "src/lib/skill-symlink.ts"() {
9145
+ "use strict";
9146
+ init_skill_version();
9147
+ SKILL_NAME = "wayai";
9148
+ HEAL_SKIP_COMMANDS = /* @__PURE__ */ new Set(["help", "--help", "-h", "--version", "-v"]);
9149
+ }
9150
+ });
9151
+
9016
9152
  // src/lib/report-inbox.ts
9017
9153
  async function nudgeReportActions(apiUrl, accessToken) {
9018
9154
  if (!process.stdout.isTTY || process.env.CI) return;
@@ -9373,41 +9509,6 @@ var init_hub_binding = __esm({
9373
9509
  }
9374
9510
  });
9375
9511
 
9376
- // src/lib/skill-symlink.ts
9377
- import { existsSync as existsSync8, lstatSync, mkdirSync as mkdirSync4, rmSync, symlinkSync } from "fs";
9378
- import { join as join11 } from "path";
9379
- function healClaudeSkillLink(root) {
9380
- try {
9381
- const source = join11(root, ".agents", "skills", SKILL_NAME);
9382
- if (!existsSync8(join11(source, SKILL_FILENAME))) return false;
9383
- const link = join11(root, ".claude", "skills", SKILL_NAME);
9384
- if (existsSync8(join11(link, SKILL_FILENAME))) return false;
9385
- let entry = null;
9386
- try {
9387
- entry = lstatSync(link);
9388
- } catch {
9389
- entry = null;
9390
- }
9391
- if (entry) {
9392
- if (!entry.isSymbolicLink()) return false;
9393
- rmSync(link, { force: true });
9394
- }
9395
- mkdirSync4(join11(root, ".claude", "skills"), { recursive: true });
9396
- symlinkSync(join11("..", "..", ".agents", "skills", SKILL_NAME), link, "dir");
9397
- return true;
9398
- } catch {
9399
- return false;
9400
- }
9401
- }
9402
- var SKILL_NAME;
9403
- var init_skill_symlink = __esm({
9404
- "src/lib/skill-symlink.ts"() {
9405
- "use strict";
9406
- init_skill_version();
9407
- SKILL_NAME = "wayai";
9408
- }
9409
- });
9410
-
9411
9512
  // src/commands/status.ts
9412
9513
  var status_exports = {};
9413
9514
  __export(status_exports, {
@@ -9418,7 +9519,8 @@ import * as path8 from "path";
9418
9519
  function parseArgs(args2) {
9419
9520
  return { json: args2.includes("--json") };
9420
9521
  }
9421
- function buildSkillState(projectRoot) {
9522
+ function buildSkillState() {
9523
+ const projectRoot = findGitRoot() ?? process.cwd();
9422
9524
  const installs = findInstalledSkills(projectRoot);
9423
9525
  if (installs.length === 0) {
9424
9526
  return { installed: false, version: null, latest: null, paths: [] };
@@ -9448,13 +9550,7 @@ async function statusCommand(args2, pkg2) {
9448
9550
  const workspace = buildWorkspaceState(repoConfig);
9449
9551
  const cachedCliLatest = readCachedLatest(CLI_CACHE_FILE);
9450
9552
  const cliLatest = cachedCliLatest && isNewerVersion(cachedCliLatest, pkg2.version) ? cachedCliLatest : null;
9451
- const projectRoot = findGitRoot() ?? process.cwd();
9452
- if (healClaudeSkillLink(projectRoot)) {
9453
- console.error(
9454
- "Linked .claude/skills/wayai \u2192 .agents/skills/wayai so Claude Code can load the WayAI skill."
9455
- );
9456
- }
9457
- const skill = buildSkillState(projectRoot);
9553
+ const skill = buildSkillState();
9458
9554
  let boundHubId = null;
9459
9555
  try {
9460
9556
  boundHubId = readBinding();
@@ -9577,7 +9673,6 @@ var init_status = __esm({
9577
9673
  init_api_client();
9578
9674
  init_version_cache();
9579
9675
  init_skill_version();
9580
- init_skill_symlink();
9581
9676
  init_utils();
9582
9677
  init_report_inbox();
9583
9678
  }
@@ -9621,27 +9716,17 @@ var init_whoami = __esm({
9621
9716
  var init_exports = {};
9622
9717
  __export(init_exports, {
9623
9718
  SKILL_INSTALL_CMD: () => SKILL_INSTALL_CMD,
9719
+ ensureHubsDir: () => ensureHubsDir,
9624
9720
  initCommand: () => initCommand,
9625
- parseArgs: () => parseArgs3,
9626
- writeWorkspaceFiles: () => writeWorkspaceFiles
9721
+ parseArgs: () => parseArgs3
9627
9722
  });
9628
- import { existsSync as existsSync9, mkdirSync as mkdirSync5, writeFileSync as writeFileSync6 } from "fs";
9723
+ import { mkdirSync as mkdirSync5 } from "fs";
9629
9724
  import path9 from "path";
9630
- function writeWorkspaceFiles(gitRoot) {
9631
- const created = [];
9632
- for (const { name, content } of SHIM_FILES) {
9633
- const filePath = path9.join(gitRoot, name);
9634
- if (!existsSync9(filePath)) {
9635
- writeFileSync6(filePath, content);
9636
- created.push(name);
9637
- }
9638
- }
9725
+ function ensureHubsDir(gitRoot) {
9639
9726
  const hubsDir = resolveLayout(gitRoot).hubsDir;
9640
- if (!existsSync9(hubsDir)) {
9641
- mkdirSync5(hubsDir, { recursive: true });
9642
- created.push(`${path9.relative(gitRoot, hubsDir)}/`);
9643
- }
9644
- return created;
9727
+ if (isDirectory(hubsDir)) return null;
9728
+ mkdirSync5(hubsDir, { recursive: true });
9729
+ return `${path9.relative(gitRoot, hubsDir)}/`;
9645
9730
  }
9646
9731
  function parseArgs3(args2) {
9647
9732
  let orgId;
@@ -9680,9 +9765,9 @@ async function initCommand(args2) {
9680
9765
  }
9681
9766
  const gitRoot = findGitRoot();
9682
9767
  if (gitRoot) {
9683
- const created = writeWorkspaceFiles(gitRoot);
9684
- if (created.length > 0) {
9685
- console.log(`Created ${created.join(", ")}`);
9768
+ const createdDir = ensureHubsDir(gitRoot);
9769
+ if (createdDir) {
9770
+ console.log(`Created ${createdDir}`);
9686
9771
  }
9687
9772
  }
9688
9773
  console.log(
@@ -9755,7 +9840,7 @@ Select organization [1-${organizations.length}]: `);
9755
9840
  console.log(`
9756
9841
  Wrote ${configPath3}`);
9757
9842
  }
9758
- var SKILL_INSTALL_CMD, AGENTS_MD, CLAUDE_MD, AGENTS_LOCAL_MD, SHIM_FILES;
9843
+ var SKILL_INSTALL_CMD;
9759
9844
  var init_init = __esm({
9760
9845
  "src/commands/init.ts"() {
9761
9846
  "use strict";
@@ -9766,43 +9851,6 @@ var init_init = __esm({
9766
9851
  init_layout();
9767
9852
  init_utils();
9768
9853
  SKILL_INSTALL_CMD = "mkdir -p .claude && npx skills add wayai-pro/wayai-skill -y";
9769
- AGENTS_MD = `# WayAI Workspace
9770
-
9771
- This is a WayAI hub-as-code workspace. Hub configuration is stored as files (\`hub.yaml\`, \`agents/*.yaml\`, \`agents/*.md\`) and synced bidirectionally with the WayAI platform via the \`wayai\` CLI.
9772
-
9773
- **Always start by reading the WayAI skill.** Install it with \`${SKILL_INSTALL_CMD}\` if you haven't already; the skill covers:
9774
- - Platform entities, hub types, AI modes, agent roles, connection types
9775
- - Workflow (\`wayai update\` \u2192 \`wayai pull\` \u2192 edit \u2192 \`wayai push\`)
9776
- - Common CLI commands and the decision matrix (CLI vs UI)
9777
- - Repository structure and YAML shapes (\`hub.yaml\`, \`agents/<slug>.yaml\`)
9778
- - Pointers to per-domain references (Connections, Agents, Resources, States, Outbound, Evals, Analytics, Templates)
9779
-
9780
- Project-specific overrides live in \`AGENTS.local.md\` \u2014 read it after the skill if it exists.
9781
-
9782
- This file is created once on \`wayai init\` and never overwritten \u2014 edit freely.
9783
- `;
9784
- CLAUDE_MD = `@AGENTS.md
9785
- @AGENTS.local.md
9786
- `;
9787
- AGENTS_LOCAL_MD = `# Project-specific instructions
9788
-
9789
- This file holds project-specific overrides and additional instructions for AI coding agents working on this hub. It is **never overwritten by \`wayai\` commands** \u2014 edit freely.
9790
-
9791
- Use it for things like:
9792
-
9793
- - Domain glossary and terminology specific to this hub
9794
- - Business rules the AI should always apply
9795
- - Conventions or constraints that override defaults in \`AGENTS.md\`
9796
- - Notes about external systems, integrations, or quirks
9797
- - Pointers to other repo files the agent should read first
9798
-
9799
- Leave this file empty (or delete its body) if you have nothing to add \u2014 \`AGENTS.md\` is sufficient on its own.
9800
- `;
9801
- SHIM_FILES = [
9802
- { name: "AGENTS.md", content: AGENTS_MD },
9803
- { name: "CLAUDE.md", content: CLAUDE_MD },
9804
- { name: "AGENTS.local.md", content: AGENTS_LOCAL_MD }
9805
- ];
9806
9854
  }
9807
9855
  });
9808
9856
 
@@ -19117,6 +19165,15 @@ async function main() {
19117
19165
  printHelp3();
19118
19166
  return;
19119
19167
  }
19168
+ if (command && !wantsHelp(args)) {
19169
+ const { findGitRoot: findGitRoot2 } = await Promise.resolve().then(() => (init_workspace(), workspace_exports));
19170
+ const { healSkillLinkForCommand: healSkillLinkForCommand2 } = await Promise.resolve().then(() => (init_skill_symlink(), skill_symlink_exports));
19171
+ if (healSkillLinkForCommand2(command, findGitRoot2() ?? process.cwd())) {
19172
+ console.error(
19173
+ "Linked .claude/skills/wayai \u2192 .agents/skills/wayai so Claude Code can load the WayAI skill."
19174
+ );
19175
+ }
19176
+ }
19120
19177
  switch (command) {
19121
19178
  case "login": {
19122
19179
  const { loginCommand: loginCommand2 } = await Promise.resolve().then(() => (init_login(), login_exports));