@autohq/cli 0.1.175 → 0.1.177

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.
@@ -26572,7 +26572,7 @@ Object.assign(lookup, {
26572
26572
  // package.json
26573
26573
  var package_default = {
26574
26574
  name: "@autohq/cli",
26575
- version: "0.1.175",
26575
+ version: "0.1.177",
26576
26576
  license: "SEE LICENSE IN README.md",
26577
26577
  publishConfig: {
26578
26578
  access: "public"
package/dist/index.js CHANGED
@@ -21682,7 +21682,7 @@ var init_package = __esm({
21682
21682
  "package.json"() {
21683
21683
  package_default = {
21684
21684
  name: "@autohq/cli",
21685
- version: "0.1.175",
21685
+ version: "0.1.177",
21686
21686
  license: "SEE LICENSE IN README.md",
21687
21687
  publishConfig: {
21688
21688
  access: "public"
@@ -22393,6 +22393,64 @@ var init_conversation2 = __esm({
22393
22393
  }
22394
22394
  });
22395
22395
 
22396
+ // src/lib/output/progress.ts
22397
+ function createSpinner(options) {
22398
+ if (!options.enabled) {
22399
+ return NOOP_SPINNER;
22400
+ }
22401
+ const stream = options.stream ?? process.stderr;
22402
+ const intervalMs = options.intervalMs ?? FRAME_INTERVAL_MS;
22403
+ const now3 = options.now ?? Date.now;
22404
+ const setIntervalFn = options.setInterval ?? setInterval;
22405
+ const clearIntervalFn = options.clearInterval ?? clearInterval;
22406
+ let label = "";
22407
+ let frame = 0;
22408
+ let startedAt = 0;
22409
+ let timer;
22410
+ const render2 = () => {
22411
+ const elapsedSeconds2 = Math.floor((now3() - startedAt) / 1e3);
22412
+ const suffix = elapsedSeconds2 >= 1 ? ` (${elapsedSeconds2}s)` : "";
22413
+ stream.write(`${CLEAR_LINE}${FRAMES[frame]} ${label}${suffix}`);
22414
+ frame = (frame + 1) % FRAMES.length;
22415
+ };
22416
+ return {
22417
+ start(next) {
22418
+ label = next;
22419
+ frame = 0;
22420
+ startedAt = now3();
22421
+ if (timer === void 0) {
22422
+ stream.write(HIDE_CURSOR);
22423
+ timer = setIntervalFn(render2, intervalMs);
22424
+ }
22425
+ render2();
22426
+ },
22427
+ stop() {
22428
+ if (timer !== void 0) {
22429
+ clearIntervalFn(timer);
22430
+ timer = void 0;
22431
+ stream.write(`${CLEAR_LINE}${SHOW_CURSOR}`);
22432
+ }
22433
+ }
22434
+ };
22435
+ }
22436
+ var FRAMES, FRAME_INTERVAL_MS, HIDE_CURSOR, SHOW_CURSOR, CLEAR_LINE, NOOP_SPINNER;
22437
+ var init_progress = __esm({
22438
+ "src/lib/output/progress.ts"() {
22439
+ "use strict";
22440
+ FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
22441
+ FRAME_INTERVAL_MS = 80;
22442
+ HIDE_CURSOR = "\x1B[?25l";
22443
+ SHOW_CURSOR = "\x1B[?25h";
22444
+ CLEAR_LINE = "\r\x1B[K";
22445
+ NOOP_SPINNER = {
22446
+ start() {
22447
+ },
22448
+ stop() {
22449
+ }
22450
+ };
22451
+ }
22452
+ });
22453
+
22396
22454
  // src/commands/apply/agent-tool-connect.ts
22397
22455
  async function connectAgentTool(input) {
22398
22456
  if (input.manual) {
@@ -23851,7 +23909,8 @@ async function applyResource(input) {
23851
23909
  client: input.client,
23852
23910
  input: bundleInput,
23853
23911
  writeOutput: input.writeOutput,
23854
- style: input.style
23912
+ style: input.style,
23913
+ io: input.io
23855
23914
  });
23856
23915
  }
23857
23916
  async function applyProjectBundleInput(input) {
@@ -23864,31 +23923,42 @@ async function applyProjectBundleInput(input) {
23864
23923
  `Project apply bundle is ${formatMegabytes(sizeBytes)}MB, over the ${formatMegabytes(MAX_PROJECT_APPLY_BUNDLE_BYTES)}MB upload limit.`
23865
23924
  );
23866
23925
  }
23867
- const upload = await input.client.prepareProjectApplyBundleUpload(
23868
- {
23869
- sha256: createHash5("sha256").update(body).digest("hex"),
23870
- sizeBytes
23871
- },
23872
- { apiBaseUrl: input.commandOptions.apiBaseUrl }
23873
- );
23874
- await input.client.uploadProjectApplyBundle({
23875
- uploadUrl: upload.uploadUrl,
23876
- method: upload.method,
23877
- contentType: upload.contentType,
23878
- body
23926
+ const spinner = createSpinner({
23927
+ enabled: applyProgressEnabled(input.io, input.commandOptions.json)
23879
23928
  });
23880
- const response = await input.client.applyProjectResources(
23881
- {
23882
- source: {
23883
- kind: "bundle",
23884
- bundle: upload.source,
23885
- entrypoint: input.input.entrypoint
23929
+ let response;
23930
+ try {
23931
+ spinner.start("Preparing upload");
23932
+ const upload = await input.client.prepareProjectApplyBundleUpload(
23933
+ {
23934
+ sha256: createHash5("sha256").update(body).digest("hex"),
23935
+ sizeBytes
23886
23936
  },
23887
- dryRun,
23888
- prune
23889
- },
23890
- { apiBaseUrl: input.commandOptions.apiBaseUrl }
23891
- );
23937
+ { apiBaseUrl: input.commandOptions.apiBaseUrl }
23938
+ );
23939
+ spinner.start("Uploading bundle");
23940
+ await input.client.uploadProjectApplyBundle({
23941
+ uploadUrl: upload.uploadUrl,
23942
+ method: upload.method,
23943
+ contentType: upload.contentType,
23944
+ body
23945
+ });
23946
+ spinner.start(dryRun ? "Computing apply plan" : "Applying resources");
23947
+ response = await input.client.applyProjectResources(
23948
+ {
23949
+ source: {
23950
+ kind: "bundle",
23951
+ bundle: upload.source,
23952
+ entrypoint: input.input.entrypoint
23953
+ },
23954
+ dryRun,
23955
+ prune
23956
+ },
23957
+ { apiBaseUrl: input.commandOptions.apiBaseUrl }
23958
+ );
23959
+ } finally {
23960
+ spinner.stop();
23961
+ }
23892
23962
  await writeProjectApplyResponse({
23893
23963
  commandOptions: {
23894
23964
  ...input.commandOptions,
@@ -24005,10 +24075,14 @@ function planActionStyle(style, action) {
24005
24075
  function formatMegabytes(bytes) {
24006
24076
  return (bytes / (1024 * 1024)).toFixed(1);
24007
24077
  }
24078
+ function applyProgressEnabled(io2, json2) {
24079
+ return !!io2 && io2.isTTY && !io2.isCI && io2.outputMode !== "json" && io2.outputMode !== "stream-json" && !json2;
24080
+ }
24008
24081
  var init_actions = __esm({
24009
24082
  "src/commands/apply/actions.ts"() {
24010
24083
  "use strict";
24011
24084
  init_src();
24085
+ init_progress();
24012
24086
  init_style();
24013
24087
  init_agent_tool_connect();
24014
24088
  init_files();
@@ -24157,7 +24231,8 @@ async function editResource(input) {
24157
24231
  },
24158
24232
  client: input.client,
24159
24233
  input: bundleInput,
24160
- writeOutput: input.writeOutput
24234
+ writeOutput: input.writeOutput,
24235
+ io: input.io
24161
24236
  });
24162
24237
  removeTempFile = true;
24163
24238
  return { changed: true, resource: reference };
@@ -24884,10 +24959,10 @@ function token(t, width = 80) {
24884
24959
  case "list": {
24885
24960
  const list = t;
24886
24961
  return `${list.items.map((item) => {
24887
- const bullet = list.ordered ? chalk.dim(" 1.") : chalk.dim(" \u2022");
24962
+ const bullet2 = list.ordered ? chalk.dim(" 1.") : chalk.dim(" \u2022");
24888
24963
  const text = inline(item.text);
24889
24964
  const nested = item.tokens.filter((st) => st.type !== "text").map((st) => token(st, width)).join("");
24890
- return `${bullet} ${text}${nested ? `
24965
+ return `${bullet2} ${text}${nested ? `
24891
24966
  ${nested}` : ""}`;
24892
24967
  }).join("\n")}
24893
24968
  `;
@@ -27461,9 +27536,9 @@ function YamlLine({ line }) {
27461
27536
  if (!match) {
27462
27537
  return /* @__PURE__ */ jsx13(Text13, { children: /* @__PURE__ */ jsx13(Text13, { dimColor: true, children: line }) });
27463
27538
  }
27464
- const [, indent, key, rest] = match;
27539
+ const [, indent2, key, rest] = match;
27465
27540
  return /* @__PURE__ */ jsxs11(Text13, { children: [
27466
- /* @__PURE__ */ jsx13(Text13, { children: indent }),
27541
+ /* @__PURE__ */ jsx13(Text13, { children: indent2 }),
27467
27542
  /* @__PURE__ */ jsx13(Text13, { color: "cyan", children: key }),
27468
27543
  /* @__PURE__ */ jsx13(YamlValue, { value: rest })
27469
27544
  ] });
@@ -32601,7 +32676,8 @@ function registerApplyCommands(program, context) {
32601
32676
  },
32602
32677
  client: createContextApiClient(context),
32603
32678
  writeOutput: context.writeOutput,
32604
- style: context.io.style
32679
+ style: context.io.style,
32680
+ io: context.io
32605
32681
  });
32606
32682
  });
32607
32683
  }
@@ -33719,7 +33795,8 @@ function registerEditCommands(program, context) {
33719
33795
  client: createContextApiClient(context),
33720
33796
  env: context.env,
33721
33797
  resource,
33722
- writeOutput: context.writeOutput
33798
+ writeOutput: context.writeOutput,
33799
+ io: context.io
33723
33800
  });
33724
33801
  });
33725
33802
  }
@@ -35591,6 +35668,7 @@ function registerSessionCommands(program, context) {
35591
35668
  // src/commands/setup/actions.ts
35592
35669
  init_browser();
35593
35670
  init_file();
35671
+ init_style();
35594
35672
  init_login();
35595
35673
  var SETUP_STATUS_POLL_INTERVAL_MS = 5e3;
35596
35674
  var SETUP_STATUS_HINT_EVERY_POLLS = 12;
@@ -35635,6 +35713,15 @@ async function setupAction(context, options) {
35635
35713
  context.writeOutput("");
35636
35714
  context.writeOutput(`Opened PR #${response.pullRequest.number}.`);
35637
35715
  if (response.pullRequest.url) {
35716
+ await explainBrowserStep(context, {
35717
+ browser: options.browser,
35718
+ heading: "Review the onboarding PR",
35719
+ body: [
35720
+ "Auto will open the pull request it just created.",
35721
+ "Reviewing and merging this PR adds the onboarding agent to `.auto/`; GitHub Sync applies it after merge."
35722
+ ],
35723
+ prompt: "Press Enter to open the PR."
35724
+ });
35638
35725
  if (options.browser !== false) {
35639
35726
  (options.openBrowser ?? openBrowser)(response.pullRequest.url);
35640
35727
  }
@@ -35658,19 +35745,11 @@ async function setupAction(context, options) {
35658
35745
  context.writeOutput("Tag `@auto.onboarding` in Slack to begin.");
35659
35746
  }
35660
35747
  async function showPitchAndWait(context) {
35661
- context.writeOutput(setupPitchText());
35748
+ context.writeOutput(setupPitchText(context.io.style));
35662
35749
  if (!context.io.canPrompt()) {
35663
35750
  throw new Error("`auto setup` requires an interactive terminal.");
35664
35751
  }
35665
- const readline = createCliReadline({
35666
- stdin: context.stdin,
35667
- stdout: context.stdout
35668
- });
35669
- try {
35670
- await readline.question("Press Enter to continue with setup.");
35671
- } finally {
35672
- readline.close();
35673
- }
35752
+ await pressEnter(context, "Press Enter to continue with setup.");
35674
35753
  }
35675
35754
  async function ensureAuthenticated(context, options, apiBaseUrl) {
35676
35755
  const config2 = readConfig(context.configPath);
@@ -35738,7 +35817,9 @@ async function createInitialProject(context, apiBaseUrl) {
35738
35817
  const client = createContextApiClient(context);
35739
35818
  const organizations = (await client.listOrganizations({ apiBaseUrl })).organizations;
35740
35819
  if (organizations.length === 0) {
35820
+ writeOrganizationExplainer(context);
35741
35821
  const organizationName = await askRequired(context, "Organization name: ");
35822
+ writeProjectExplainer(context);
35742
35823
  const projectName2 = await askRequired(context, "Project name: ");
35743
35824
  const created2 = await client.createOrganization({
35744
35825
  organizationName,
@@ -35760,6 +35841,7 @@ async function createInitialProject(context, apiBaseUrl) {
35760
35841
  render: organizationLabel
35761
35842
  });
35762
35843
  setActiveOrganization(context, organization.organizationId);
35844
+ writeProjectExplainer(context);
35763
35845
  const projectName = await askRequired(context, "Project name: ");
35764
35846
  const created = await client.createProject({ projectName, apiBaseUrl });
35765
35847
  setActiveProject(context, {
@@ -35772,13 +35854,20 @@ async function selectGithubConnection(context, project, options, apiBaseUrl) {
35772
35854
  const existing = await activeConnections(context, "github", apiBaseUrl);
35773
35855
  if (existing.length === 0) {
35774
35856
  context.writeOutput("");
35775
- context.writeOutput(
35776
- "Next, connect GitHub. Heads-up: this opens your browser to install or authorize the GitHub App."
35777
- );
35857
+ await explainBrowserStep(context, {
35858
+ browser: options.browser,
35859
+ heading: "Connect GitHub",
35860
+ body: [
35861
+ "Auto will open GitHub so you can install or authorize the GitHub App.",
35862
+ "This lets Auto open the onboarding PR and, after you merge it, deploy `.auto/` resources from the repository."
35863
+ ],
35864
+ prompt: "Press Enter to open GitHub."
35865
+ });
35778
35866
  await connectProviderAction(context, "github", {
35779
35867
  apiBaseUrl,
35780
35868
  allow: project.projectId,
35781
35869
  browser: options.browser,
35870
+ openBrowser: options.openBrowser,
35782
35871
  wait: true
35783
35872
  });
35784
35873
  return requireSingleConnection(context, "github", apiBaseUrl);
@@ -35795,13 +35884,20 @@ async function selectSlackConnection(context, project, options, apiBaseUrl) {
35795
35884
  const existing = await activeConnections(context, "slack", apiBaseUrl);
35796
35885
  if (existing.length === 0) {
35797
35886
  context.writeOutput("");
35798
- context.writeOutput(
35799
- "Now connect Slack. Heads-up: this opens your browser for Slack OAuth."
35800
- );
35887
+ await explainBrowserStep(context, {
35888
+ browser: options.browser,
35889
+ heading: "Connect Slack",
35890
+ body: [
35891
+ "Auto will open Slack OAuth so the onboarding agent can talk to you in your workspace.",
35892
+ "After the setup PR is merged and applied, you will tag `@auto.onboarding` there to begin."
35893
+ ],
35894
+ prompt: "Press Enter to open Slack."
35895
+ });
35801
35896
  await connectProviderAction(context, "slack", {
35802
35897
  apiBaseUrl,
35803
35898
  allow: project.projectId,
35804
35899
  browser: options.browser,
35900
+ openBrowser: options.openBrowser,
35805
35901
  wait: true
35806
35902
  });
35807
35903
  return requireSingleConnection(context, "slack", apiBaseUrl);
@@ -35840,33 +35936,131 @@ async function selectRepository(context, github, explicitRepo) {
35840
35936
  "GitHub repository to install Auto in (owner/repo): "
35841
35937
  );
35842
35938
  }
35843
- function setupPitchText() {
35939
+ function setupPitchText(style = plainStyle) {
35844
35940
  return [
35845
- "auto lets you program software factories the same way you program CI/CD.",
35941
+ ...autoLogo(style),
35846
35942
  "",
35847
- "Compose agents and triggers into workflows using simple YAML files, and deploy them into the cloud on merge.",
35943
+ style.heading(
35944
+ "auto lets you program software factories the same way you program CI/CD."
35945
+ ),
35848
35946
  "",
35849
- "Simple workflows you can build with auto:",
35850
- "- Ticket / feedback triage and resolution",
35851
- "- Automated incident / bug response",
35852
- "- Custom tailored code review agents",
35947
+ indent(
35948
+ "Compose agents and triggers into workflows using simple YAML files, and deploy them into the cloud on merge.",
35949
+ 2
35950
+ ),
35853
35951
  "",
35854
- "Frontier workflows auto can help you explore:",
35855
- "- Organized fleets of agents on long-horizon tasks",
35856
- "- Multi-agent autoresearch / optimization loops",
35857
- "- Agentic BDR and outbound lead engines",
35858
- "- More ideas we have not dreamed up yet",
35952
+ style.label("Simple workflows you can build with auto:"),
35953
+ bullet(style, "Ticket / feedback triage and resolution"),
35954
+ bullet(style, "Automated incident / bug response"),
35955
+ bullet(style, "Custom tailored code review agents"),
35859
35956
  "",
35860
- "Before you continue, have two things ready:",
35861
- "1. A GitHub repository where Auto can add a `.auto/` directory.",
35862
- "2. A Slack workspace where Auto can install its Slack connection.",
35957
+ style.label("Frontier workflows auto can help you explore:"),
35958
+ bullet(style, "Organized fleets of agents on long-horizon tasks"),
35959
+ bullet(style, "Multi-agent autoresearch / optimization loops"),
35960
+ bullet(style, "Agentic BDR and outbound lead engines"),
35961
+ bullet(style, "More ideas we have not dreamed up yet"),
35962
+ "",
35963
+ style.label("Before you continue, have two things ready:"),
35964
+ numbered(
35965
+ style,
35966
+ 1,
35967
+ "A GitHub repository where Auto can add a `.auto/` directory."
35968
+ ),
35969
+ numbered(
35970
+ style,
35971
+ 2,
35972
+ "A Slack workspace where Auto can install its Slack connection."
35973
+ ),
35863
35974
  "",
35864
- "If you do not already have a repo and Slack workspace ready to go, create them before continuing.",
35975
+ indent(
35976
+ "If you do not already have a repo and Slack workspace ready to go, create them before continuing.",
35977
+ 2
35978
+ ),
35865
35979
  "",
35866
- "Auto is in early alpha, and you are one of the very first users. If anything feels confusing, breaks, or sparks an idea, please tell us. That feedback directly shapes the product.",
35980
+ style.dim(
35981
+ "Auto is in early alpha, and you are one of the very first users. If anything feels confusing, breaks, or sparks an idea, please tell us. That feedback directly shapes the product."
35982
+ ),
35867
35983
  ""
35868
35984
  ].join("\n");
35869
35985
  }
35986
+ function autoLogo(style) {
35987
+ return [
35988
+ style.id(" _ "),
35989
+ style.id(" __ _ _ _| |_ ___ "),
35990
+ style.id(" / _` | | | | __/ _ \\ "),
35991
+ style.id("| (_| | |_| | || (_) |"),
35992
+ style.id(" \\__,_|\\__,_|\\__\\___/ ")
35993
+ ];
35994
+ }
35995
+ function bullet(style, text) {
35996
+ return `${style.id(" -")} ${text}`;
35997
+ }
35998
+ function numbered(style, index, text) {
35999
+ return `${style.id(` ${index}.`)} ${text}`;
36000
+ }
36001
+ function indent(text, spaces) {
36002
+ return `${" ".repeat(spaces)}${text}`;
36003
+ }
36004
+ async function explainAndWait(context, input) {
36005
+ context.writeOutput(context.io.style.heading(input.heading));
36006
+ for (const line of input.body) {
36007
+ context.writeOutput(indent(line, 2));
36008
+ }
36009
+ await pressEnter(context, input.prompt);
36010
+ }
36011
+ async function explainBrowserStep(context, input) {
36012
+ if (input.browser !== false) {
36013
+ await explainAndWait(context, input);
36014
+ return;
36015
+ }
36016
+ context.writeOutput(context.io.style.heading(input.heading));
36017
+ for (const line of input.body) {
36018
+ context.writeOutput(indent(line, 2));
36019
+ }
36020
+ }
36021
+ async function pressEnter(context, prompt) {
36022
+ if (!context.io.canPrompt()) {
36023
+ throw new Error("`auto setup` requires an interactive terminal.");
36024
+ }
36025
+ if (isReadableEnded(context.stdin)) {
36026
+ return;
36027
+ }
36028
+ const readline = createCliReadline({
36029
+ stdin: context.stdin,
36030
+ stdout: context.stdout
36031
+ });
36032
+ try {
36033
+ await Promise.race([
36034
+ readline.question(context.io.style.dim(prompt)),
36035
+ new Promise((resolve3) => {
36036
+ readline.once("close", resolve3);
36037
+ })
36038
+ ]);
36039
+ } finally {
36040
+ readline.close();
36041
+ }
36042
+ }
36043
+ function isReadableEnded(stream) {
36044
+ return "readableEnded" in stream && stream.readableEnded === true;
36045
+ }
36046
+ function writeOrganizationExplainer(context) {
36047
+ context.writeOutput("");
36048
+ context.writeOutput(context.io.style.heading("Create your organization"));
36049
+ context.writeOutput(
36050
+ "An organization is the workspace for your team, projects, provider connections, and shared Auto resources."
36051
+ );
36052
+ context.writeOutput(
36053
+ "Enter an organization name. You can always change it later."
36054
+ );
36055
+ }
36056
+ function writeProjectExplainer(context) {
36057
+ context.writeOutput("");
36058
+ context.writeOutput(context.io.style.heading("Create your project"));
36059
+ context.writeOutput(
36060
+ "A project is where Auto stores this repository's agents, triggers, connections, sessions, and secrets."
36061
+ );
36062
+ context.writeOutput("Enter a project name. You can always change it later.");
36063
+ }
35870
36064
  async function activeConnections(context, provider, apiBaseUrl) {
35871
36065
  const response = await createContextApiClient(context).listConnections({
35872
36066
  provider,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autohq/cli",
3
- "version": "0.1.175",
3
+ "version": "0.1.177",
4
4
  "license": "SEE LICENSE IN README.md",
5
5
  "publishConfig": {
6
6
  "access": "public"