@trycadence/cli 0.1.6 → 0.1.7

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.
Files changed (2) hide show
  1. package/dist/cadence +119 -21
  2. package/package.json +1 -1
package/dist/cadence CHANGED
@@ -1466,6 +1466,9 @@ function createCadenceClient(options = {}) {
1466
1466
  },
1467
1467
  tickets: {
1468
1468
  get: (input) => rpc.tickets.get.query(input),
1469
+ detail: (input) => rpc.tickets.detail.query(input),
1470
+ activity: (input) => rpc.tickets.activity.query(input),
1471
+ workLog: (input) => rpc.tickets.workLog.query(input),
1469
1472
  list: (input) => rpc.tickets.list.query(input),
1470
1473
  create: (input) => rpc.tickets.create.mutate(input),
1471
1474
  attach: (input) => rpc.tickets.attach.mutate(input),
@@ -1575,6 +1578,7 @@ var knownCommandPaths = [
1575
1578
  ["events", "list"],
1576
1579
  ["work", "overview"],
1577
1580
  ["projects", "list"],
1581
+ ["projects", "use"],
1578
1582
  ["init"],
1579
1583
  ["status"],
1580
1584
  ["help"]
@@ -1823,6 +1827,39 @@ async function findRepoCadenceDirectory(cwd) {
1823
1827
  current = parent;
1824
1828
  }
1825
1829
  }
1830
+ async function findRepoConfigDirectory(cwd) {
1831
+ let current = cwd;
1832
+ while (true) {
1833
+ const repoConfig = join(current, ".cadence", "config.json");
1834
+ if (await Bun.file(repoConfig).exists()) {
1835
+ return join(current, ".cadence");
1836
+ }
1837
+ const parent = dirname(current);
1838
+ if (parent === current) {
1839
+ return null;
1840
+ }
1841
+ current = parent;
1842
+ }
1843
+ }
1844
+ function resolveGitRootFromCommand(cwd) {
1845
+ const result = spawnSync("git", ["rev-parse", "--show-toplevel"], {
1846
+ cwd,
1847
+ encoding: "utf8"
1848
+ });
1849
+ if (result.status !== 0) {
1850
+ return null;
1851
+ }
1852
+ return result.stdout.trim() || null;
1853
+ }
1854
+ async function repoConfigPathForWrite(options) {
1855
+ const cwd = options.cwd ?? process.cwd();
1856
+ const existingConfigDirectory = await findRepoConfigDirectory(cwd);
1857
+ if (existingConfigDirectory) {
1858
+ return join(existingConfigDirectory, "config.json");
1859
+ }
1860
+ const gitRoot = options.resolveGitRoot ? await options.resolveGitRoot() : resolveGitRootFromCommand(cwd);
1861
+ return join(gitRoot ?? cwd, ".cadence", "config.json");
1862
+ }
1826
1863
  function getConfigHome(env) {
1827
1864
  return env.CADENCE_CONFIG_HOME ?? (env.HOME ? join(env.HOME, ".config", "cadence") : join(parse(process.cwd()).root, ".config", "cadence"));
1828
1865
  }
@@ -1840,16 +1877,13 @@ async function resolveCliConfig(flags, options = {}) {
1840
1877
  repoConfigPromise,
1841
1878
  localConfigPromise
1842
1879
  ]);
1843
- const profiles = {
1844
- ...globalConfig.profiles ?? {},
1845
- ...repoConfig.profiles ?? {},
1846
- ...localConfig.profiles ?? {}
1847
- };
1848
1880
  const envProfile = env.CADENCE_PROFILE;
1849
1881
  const profile = envProfile ?? localConfig.profile ?? repoConfig.profile ?? globalConfig.profile ?? null;
1850
- const profileConfig = profile ? profiles[profile] : undefined;
1851
- const server = flags.server ?? env.CADENCE_SERVER ?? localConfig.server ?? profileConfig?.server ?? repoConfig.server ?? globalConfig.server ?? defaultCliApiBaseUrl;
1852
- const webBaseUrl = env.CADENCE_WEB_BASE_URL ?? localConfig.webBaseUrl ?? profileConfig?.webBaseUrl ?? repoConfig.webBaseUrl ?? globalConfig.webBaseUrl ?? deriveWebBaseUrl(server);
1882
+ const globalProfileConfig = profile ? globalConfig.profiles?.[profile] : undefined;
1883
+ const repoProfileConfig = profile ? repoConfig.profiles?.[profile] : undefined;
1884
+ const localProfileConfig = profile ? localConfig.profiles?.[profile] : undefined;
1885
+ const server = flags.server ?? env.CADENCE_SERVER ?? localConfig.server ?? localProfileConfig?.server ?? repoConfig.server ?? repoProfileConfig?.server ?? globalProfileConfig?.server ?? globalConfig.server ?? defaultCliApiBaseUrl;
1886
+ const webBaseUrl = env.CADENCE_WEB_BASE_URL ?? localConfig.webBaseUrl ?? localProfileConfig?.webBaseUrl ?? repoConfig.webBaseUrl ?? repoProfileConfig?.webBaseUrl ?? globalProfileConfig?.webBaseUrl ?? globalConfig.webBaseUrl ?? deriveWebBaseUrl(server);
1853
1887
  const projectId = flags.project ?? localConfig.projectId ?? repoConfig.projectId ?? globalConfig.projectId ?? null;
1854
1888
  return {
1855
1889
  server,
@@ -2129,6 +2163,7 @@ function helpText() {
2129
2163
  " cadence actors ensure-workspace-agent --agent-kind <kind> [--workspace-name <name>] [--workspace-ref <ref>] [--display-name <name>] [--project <project-id>] [--json]",
2130
2164
  " cadence status [--project <project-id>] [--json]",
2131
2165
  " cadence projects list [--json]",
2166
+ " cadence projects use <project-id|org/project> [--server <url>] [--json]",
2132
2167
  " cadence work overview [--project <project-id>] [--json]",
2133
2168
  " cadence tickets get <ticket-id> [--project <project-id>] [--json]",
2134
2169
  " cadence tickets list [--project <project-id>] [--status <status>] [--json]",
@@ -2156,7 +2191,7 @@ function helpText() {
2156
2191
  " cadence events list [--project <project-id>] [--ticket <ticket-id>] [--changeset <changeset-id>] [--session <session-id>] [--json]",
2157
2192
  "",
2158
2193
  "Global flags:",
2159
- " --project <id> Cadence project ID or org/project slug",
2194
+ " --project <id|org/project> Cadence project ID or org/project slug",
2160
2195
  " --server <url> Cadence API server override",
2161
2196
  " --json Print stable JSON envelope",
2162
2197
  "",
@@ -2442,8 +2477,21 @@ async function runStatus(parsed, options) {
2442
2477
  exitCode: 0
2443
2478
  };
2444
2479
  }
2480
+ const projectLabel = config.projectId ?? "not configured";
2481
+ const profileLabel = config.profile ?? "default";
2482
+ const credentialLabel = credential ? "configured" : "not configured";
2445
2483
  return {
2446
- stdout: `Cadence API ${health.ok ? "ok" : "unavailable"} at ${config.server}
2484
+ stdout: [
2485
+ `Cadence API: ${health.ok ? "ok" : "unavailable"} at ${config.server}`,
2486
+ `Cadence web: ${webBaseUrl}`,
2487
+ `Profile: ${profileLabel}`,
2488
+ `Project: ${projectLabel}`,
2489
+ `Credential: ${credentialLabel}`,
2490
+ `Repo config: ${config.repoConfigPath ?? "not found"}`,
2491
+ `Local config: ${config.localConfigPath ?? "not found"}`,
2492
+ `Global config: ${config.globalConfigPath}`
2493
+ ].join(`
2494
+ `) + `
2447
2495
  `,
2448
2496
  stderr: "",
2449
2497
  exitCode: 0
@@ -2451,7 +2499,7 @@ async function runStatus(parsed, options) {
2451
2499
  }
2452
2500
  async function runInit(parsed, options) {
2453
2501
  const cwd = options.cwd ?? process.cwd();
2454
- const repoConfigPath = join(cwd, ".cadence", "config.json");
2502
+ const repoConfigPath = await repoConfigPathForWrite(options);
2455
2503
  const config = await resolveCliConfig(parsed.flags, {
2456
2504
  ...options,
2457
2505
  cwd
@@ -2509,6 +2557,15 @@ async function resolveProjectReference(projectReference, client) {
2509
2557
  projectSlug
2510
2558
  });
2511
2559
  }
2560
+ async function resolveRequiredProject(config, client) {
2561
+ return await resolveProjectReference(requireProjectId(config), client);
2562
+ }
2563
+ function configWithProject(config, project) {
2564
+ return {
2565
+ ...config,
2566
+ projectId: project.id
2567
+ };
2568
+ }
2512
2569
  function formatProjectChoice(project, index) {
2513
2570
  const slug = project.orgSlug && project.projectSlug ? `${project.orgSlug}/${project.projectSlug}` : project.id;
2514
2571
  const name = project.name ? ` ${project.name}` : "";
@@ -2596,11 +2653,17 @@ async function runAuthCommand(parsed, options) {
2596
2653
  await writeStoredCredential(store, config.server, poll.credential);
2597
2654
  await mergeConfigFile(config.globalConfigPath, { server: config.server });
2598
2655
  await writeInteractiveStatus("Cadence CLI login approved. Credential stored.", options);
2656
+ const projectConfigured = Boolean(config.projectId);
2657
+ if (!projectConfigured) {
2658
+ await writeInteractiveStatus("No Cadence project is configured for this repo. Run cadence init to choose one.", options);
2659
+ }
2599
2660
  data = {
2600
2661
  server: config.server,
2601
2662
  credentialStored: true,
2663
+ projectConfigured,
2602
2664
  globalConfigPath: config.globalConfigPath,
2603
- loginUrl: challenge.loginUrl
2665
+ loginUrl: challenge.loginUrl,
2666
+ ...!projectConfigured ? { nextCommand: "cadence init" } : {}
2604
2667
  };
2605
2668
  }
2606
2669
  break;
@@ -2647,9 +2710,11 @@ async function runAuthCommand(parsed, options) {
2647
2710
  }
2648
2711
  async function runReadCommand(parsed, options) {
2649
2712
  const config = await resolveCliConfig(parsed.flags, options);
2650
- const projectId = requireProjectId(config);
2651
2713
  const client = await createClient(config, options);
2652
- const meta = commandMeta(parsed, config);
2714
+ const project = await resolveRequiredProject(config, client);
2715
+ const resolvedConfig = configWithProject(config, project);
2716
+ const projectId = project.id;
2717
+ const meta = commandMeta(parsed, resolvedConfig);
2653
2718
  let data;
2654
2719
  switch (parsed.command.name) {
2655
2720
  case "events.list":
@@ -2751,18 +2816,47 @@ async function runReadCommand(parsed, options) {
2751
2816
  async function runProjectCommand(parsed, options) {
2752
2817
  const config = await resolveCliConfig(parsed.flags, options);
2753
2818
  const client = await createClient(config, options);
2754
- const meta = commandMeta(parsed, config);
2755
2819
  let data;
2820
+ let outputConfig = config;
2756
2821
  switch (parsed.command.name) {
2757
2822
  case "projects.list":
2758
2823
  data = await client.projects.list();
2759
2824
  break;
2825
+ case "projects.use":
2826
+ {
2827
+ const project = await resolveProjectReference(requireArg(parsed, 0, "<project-id|org/project>"), client);
2828
+ const repoConfigPath = await repoConfigPathForWrite(options);
2829
+ const updates = {
2830
+ projectId: project.id,
2831
+ ...parsed.flags.server ? { server: parsed.flags.server } : {}
2832
+ };
2833
+ await mergeConfigFile(repoConfigPath, updates);
2834
+ outputConfig = configWithProject(config, project);
2835
+ data = {
2836
+ repoConfigPath,
2837
+ projectId: project.id,
2838
+ project,
2839
+ ...parsed.flags.server ? { server: parsed.flags.server } : {}
2840
+ };
2841
+ }
2842
+ break;
2760
2843
  default:
2761
2844
  throw new CliError("CLI_USAGE", `Unknown command: ${parsed.command.path.join(" ")}`);
2762
2845
  }
2763
2846
  if (parsed.flags.json) {
2764
2847
  return {
2765
- stdout: formatJson(successEnvelope(data, meta)),
2848
+ stdout: formatJson(successEnvelope(data, commandMeta(parsed, outputConfig))),
2849
+ stderr: "",
2850
+ exitCode: 0
2851
+ };
2852
+ }
2853
+ if (parsed.command.name === "projects.use") {
2854
+ const project = data;
2855
+ const slug = project.project?.orgSlug && project.project.projectSlug ? `${project.project.orgSlug}/${project.project.projectSlug}` : project.projectId;
2856
+ const name = project.project?.name ? ` (${project.project.name})` : "";
2857
+ return {
2858
+ stdout: `Using Cadence project ${slug}${name}.
2859
+ `,
2766
2860
  stderr: "",
2767
2861
  exitCode: 0
2768
2862
  };
@@ -2777,11 +2871,13 @@ async function runProjectCommand(parsed, options) {
2777
2871
  async function runActorCommand(parsed, options) {
2778
2872
  const config = await resolveCliConfig(parsed.flags, options);
2779
2873
  const client = await createClient(config, options);
2780
- const meta = commandMeta(parsed, config);
2874
+ const project = await resolveRequiredProject(config, client);
2875
+ const resolvedConfig = configWithProject(config, project);
2876
+ const meta = commandMeta(parsed, resolvedConfig);
2781
2877
  let data;
2782
2878
  switch (parsed.command.name) {
2783
2879
  case "actors.ensure-workspace-agent":
2784
- data = await ensureWorkspaceAgentIdentity(parsed, config, client, options);
2880
+ data = await ensureWorkspaceAgentIdentity(parsed, resolvedConfig, client, options);
2785
2881
  break;
2786
2882
  default:
2787
2883
  throw new CliError("CLI_USAGE", `Unknown command: ${parsed.command.path.join(" ")}`);
@@ -2802,9 +2898,11 @@ async function runActorCommand(parsed, options) {
2802
2898
  }
2803
2899
  async function runIntakeCommand(parsed, options) {
2804
2900
  const config = await resolveCliConfig(parsed.flags, options);
2805
- const projectId = requireProjectId(config);
2806
2901
  const client = await createClient(config, options);
2807
- const meta = commandMeta(parsed, config);
2902
+ const project = await resolveRequiredProject(config, client);
2903
+ const resolvedConfig = configWithProject(config, project);
2904
+ const projectId = project.id;
2905
+ const meta = commandMeta(parsed, resolvedConfig);
2808
2906
  let data;
2809
2907
  const ifVersion = () => parseRequiredPositiveInteger(requireOption(parsed, "if-version"), "--if-version");
2810
2908
  switch (parsed.command.name) {
@@ -3101,7 +3199,7 @@ async function runCli(argv, options = {}) {
3101
3199
  if (parsed.command.name === "events.list" || parsed.command.name === "work.overview" || parsed.command.name === "tickets.get" || parsed.command.name === "tickets.list" || parsed.command.name === "sessions.current" || parsed.command.name === "changesets.get" || parsed.command.name === "changesets.context" || parsed.command.name === "changesets.current" || parsed.command.name === "changesets.list" || parsed.command.name === "changesets.notes.get") {
3102
3200
  return await runReadCommand(parsed, options);
3103
3201
  }
3104
- if (parsed.command.name === "projects.list") {
3202
+ if (parsed.command.name === "projects.list" || parsed.command.name === "projects.use") {
3105
3203
  return await runProjectCommand(parsed, options);
3106
3204
  }
3107
3205
  if (parsed.command.name === "intake" || parsed.command.name === "intake.dismiss" || parsed.command.name === "tickets.attach" || parsed.command.name === "tickets.create" || parsed.command.name === "tickets.update" || parsed.command.name === "tickets.claim" || parsed.command.name === "tickets.release" || parsed.command.name === "tickets.log" || parsed.command.name === "tickets.complete" || parsed.command.name === "sessions.start" || parsed.command.name === "sessions.end" || parsed.command.name === "sessions.files" || parsed.command.name === "changesets.create" || parsed.command.name === "changesets.notes.put" || parsed.command.name === "changesets.notes.apply") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trycadence/cli",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "bin": {