@picahq/cli 1.3.0 → 1.4.0

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/index.js +103 -11
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -372,6 +372,9 @@ async function openApiKeyPage() {
372
372
  await open(getApiKeyUrl());
373
373
  }
374
374
 
375
+ // src/commands/init.ts
376
+ import open2 from "open";
377
+
375
378
  // src/lib/table.ts
376
379
  import pc from "picocolors";
377
380
  function printTable(columns, rows) {
@@ -410,12 +413,13 @@ function stripAnsi(str) {
410
413
 
411
414
  // src/commands/init.ts
412
415
  async function initCommand(options) {
413
- p.intro(pc2.bgCyan(pc2.black(" Pica ")));
414
416
  const existingConfig = readConfig();
415
417
  if (existingConfig) {
418
+ p.intro(pc2.bgCyan(pc2.black(" Pica ")));
416
419
  await handleExistingConfig(existingConfig.apiKey, options);
417
420
  return;
418
421
  }
422
+ printBanner();
419
423
  await freshSetup(options);
420
424
  }
421
425
  async function handleExistingConfig(apiKey, options) {
@@ -773,11 +777,10 @@ ${globalPaths}
773
777
 
774
778
  `;
775
779
  }
776
- summary += pc2.yellow("Note: Project config files can be committed to share with your team.\n") + pc2.yellow("Team members will need their own API key.\n\n") + `Next steps:
777
- ${pc2.cyan("pica add gmail")} - Connect Gmail
778
- ${pc2.cyan("pica platforms")} - See all 200+ integrations`;
780
+ summary += pc2.yellow("Note: Project config files can be committed to share with your team.\n") + pc2.yellow("Team members will need their own API key.");
779
781
  p.note(summary, "Setup Complete");
780
- p.outro("Pica MCP installed!");
782
+ await promptConnectIntegrations(apiKey);
783
+ p.outro("Your AI agents now have access to Pica integrations!");
781
784
  return;
782
785
  }
783
786
  const installedAgentIds = [];
@@ -794,16 +797,105 @@ ${globalPaths}
794
797
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
795
798
  });
796
799
  p.note(
797
- `Config saved to: ${pc2.dim(getConfigPath())}
798
-
799
- Next steps:
800
- ${pc2.cyan("pica add gmail")} - Connect Gmail
801
- ${pc2.cyan("pica platforms")} - See all 200+ integrations
802
- ${pc2.cyan("pica connection list")} - View your connections`,
800
+ `Config saved to: ${pc2.dim(getConfigPath())}`,
803
801
  "Setup Complete"
804
802
  );
803
+ await promptConnectIntegrations(apiKey);
805
804
  p.outro("Your AI agents now have access to Pica integrations!");
806
805
  }
806
+ function printBanner() {
807
+ console.log();
808
+ console.log(pc2.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
809
+ console.log(pc2.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
810
+ console.log(pc2.cyan(" \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588"));
811
+ console.log(pc2.cyan(" \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588"));
812
+ console.log(pc2.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
813
+ console.log(pc2.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
814
+ console.log(pc2.cyan(" \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588"));
815
+ console.log(pc2.cyan(" \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588"));
816
+ console.log(pc2.cyan(" \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588"));
817
+ console.log(pc2.cyan(" \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588"));
818
+ console.log();
819
+ console.log(pc2.dim(" U N I V E R S A L I N T E G R A T I O N S F O R A I"));
820
+ console.log();
821
+ }
822
+ var TOP_INTEGRATIONS = [
823
+ { value: "gmail", label: "Gmail", hint: "Read and send emails" },
824
+ { value: "google-calendar", label: "Google Calendar", hint: "Manage events and schedules" },
825
+ { value: "notion", label: "Notion", hint: "Access pages, databases, and docs" }
826
+ ];
827
+ async function promptConnectIntegrations(apiKey) {
828
+ const api = new PicaApi(apiKey);
829
+ const connected = [];
830
+ try {
831
+ const existing = await api.listConnections();
832
+ for (const conn of existing) {
833
+ const match = TOP_INTEGRATIONS.find(
834
+ (i) => i.value === conn.platform.toLowerCase()
835
+ );
836
+ if (match) connected.push(match.value);
837
+ }
838
+ } catch {
839
+ }
840
+ let first = true;
841
+ while (true) {
842
+ const available = TOP_INTEGRATIONS.filter((i) => !connected.includes(i.value));
843
+ const options = [
844
+ ...available.map((i) => ({
845
+ value: i.value,
846
+ label: i.label,
847
+ hint: i.hint
848
+ })),
849
+ { value: "more", label: "Browse all 200+ platforms" },
850
+ { value: "skip", label: "Skip for now", hint: "you can always run pica add later" }
851
+ ];
852
+ const message = first ? "Connect your first integration?" : "Connect another?";
853
+ const choice = await p.select({ message, options });
854
+ if (p.isCancel(choice) || choice === "skip") {
855
+ break;
856
+ }
857
+ if (choice === "more") {
858
+ try {
859
+ await open2("https://app.picaos.com/connections");
860
+ p.log.info("Opened Pica dashboard in browser.");
861
+ } catch {
862
+ p.note("https://app.picaos.com/connections", "Open in browser");
863
+ }
864
+ p.log.info(`Connect from the dashboard, or use ${pc2.cyan("pica add <platform>")}`);
865
+ break;
866
+ }
867
+ const platform = choice;
868
+ const integration = TOP_INTEGRATIONS.find((i) => i.value === platform);
869
+ const label = integration?.label ?? platform;
870
+ p.log.info(`Opening browser to connect ${pc2.cyan(label)}...`);
871
+ try {
872
+ await openConnectionPage(platform);
873
+ } catch {
874
+ const url = getConnectionUrl(platform);
875
+ p.log.warn("Could not open browser automatically.");
876
+ p.note(url, "Open manually");
877
+ }
878
+ const spinner5 = p.spinner();
879
+ spinner5.start("Waiting for connection... (complete auth in browser)");
880
+ try {
881
+ await api.waitForConnection(platform, 5 * 60 * 1e3, 5e3);
882
+ spinner5.stop(`${label} connected!`);
883
+ p.log.success(`${pc2.green("\u2713")} ${label} is now available to your AI agents`);
884
+ connected.push(platform);
885
+ first = false;
886
+ } catch (error) {
887
+ spinner5.stop("Connection timed out");
888
+ if (error instanceof TimeoutError) {
889
+ p.log.warn(`No worries. Connect later with: ${pc2.cyan(`pica add ${platform}`)}`);
890
+ }
891
+ first = false;
892
+ }
893
+ if (TOP_INTEGRATIONS.every((i) => connected.includes(i.value))) {
894
+ p.log.success("All top integrations connected!");
895
+ break;
896
+ }
897
+ }
898
+ }
807
899
  function maskApiKey(key) {
808
900
  if (key.length <= 12) return key.slice(0, 8) + "...";
809
901
  return key.slice(0, 8) + "..." + key.slice(-4);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@picahq/cli",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "CLI for managing Pica",
5
5
  "type": "module",
6
6
  "files": [