@sequelsh/cli 0.1.0 → 0.3.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.
package/README.md CHANGED
@@ -25,14 +25,17 @@ The installed command is `sequel`.
25
25
  ```bash
26
26
  sequel login # sign in via your browser (OAuth)
27
27
  sequel connect # connect a data source
28
- sequel install # add the Sequel MCP server to a coding agent
28
+ sequel install # add the Sequel MCP server (and skill, where supported) to a coding agent
29
+ sequel skills # list the playbooks your agent can follow (no login needed)
30
+ sequel skills show seo # print one playbook
29
31
  ```
30
32
 
31
33
  ## Commands
32
34
 
33
35
  | Command | Description |
34
36
  | --- | --- |
35
- | `sequel login` | Sign in to Sequel. |
37
+ | `sequel upgrade` | Upgrade the CLI to the latest version from npm. |
38
+ | `sequel login` | Sign in to Sequel. `--no-browser` prints the sign-in URL instead of opening it. |
36
39
  | `sequel logout` | Sign out and remove cached credentials. |
37
40
  | `sequel switch` | Switch the active organization. |
38
41
  | `sequel connect [source]` | Connect a new data source (interactive, or pass a connector id). |
@@ -40,7 +43,7 @@ sequel install # add the Sequel MCP server to a coding agent
40
43
  | `sequel sources active` | List sources with live health status. |
41
44
  | `sequel sources info <id>` | Show details for a source. |
42
45
  | `sequel sources delete <id>` | Delete a source. |
43
- | `sequel install [agent]` | Install the Sequel MCP server into a coding agent (Claude, Cursor, VS Code, and more). |
46
+ | `sequel install [agent]` | Install the Sequel MCP server into a coding agent (Claude, Cursor, VS Code, and more). `--scope global\|local` skips the scope prompt; with an agent slug it runs without prompting. |
44
47
  | `sequel search <use case>` | Find the right tools for a use case across your sources. |
45
48
  | `sequel execute` | Execute a tool against a connection. |
46
49
 
package/dist/index.js CHANGED
@@ -7,6 +7,7 @@ import { homedir, platform } from "node:os";
7
7
  import { dirname, join } from "node:path";
8
8
  import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
9
9
  import pc from "picocolors";
10
+ import * as p$5 from "@clack/prompts";
10
11
  import * as p$4 from "@clack/prompts";
11
12
  import * as p$3 from "@clack/prompts";
12
13
  import * as p$2 from "@clack/prompts";
@@ -14,10 +15,90 @@ import * as p$1 from "@clack/prompts";
14
15
  import * as p from "@clack/prompts";
15
16
  import { execFileSync } from "node:child_process";
16
17
  import YAML from "yaml";
18
+ import { writeFile } from "node:fs/promises";
17
19
 
20
+ //#region package.json
21
+ var name = "@sequelsh/cli";
22
+ var version = "0.3.0";
23
+ var description = "Sequel CLI — connect data sources and run tools from your terminal.";
24
+ var license = "MIT";
25
+ var type = "module";
26
+ var bin = { "sequel": "./dist/index.js" };
27
+ var files = ["dist"];
28
+ var exports = { ".": {
29
+ "import": "./dist/index.js",
30
+ "types": "./dist/index.d.ts"
31
+ } };
32
+ var engines = { "node": ">=18" };
33
+ var repository = {
34
+ "type": "git",
35
+ "url": "git+https://github.com/sequelsh/sequel.git",
36
+ "directory": "packages/cli"
37
+ };
38
+ var homepage = "https://sequel.sh";
39
+ var keywords = [
40
+ "sequel",
41
+ "cli",
42
+ "mcp",
43
+ "sql",
44
+ "data",
45
+ "ai",
46
+ "agents"
47
+ ];
48
+ var publishConfig = { "access": "public" };
49
+ var scripts = {
50
+ "dev": "bun run src/index.ts",
51
+ "cli": "bun run src/index.ts",
52
+ "build": "tsdown",
53
+ "build:binaries": "bun run scripts/build-binaries.ts",
54
+ "test": "vitest run",
55
+ "test:watch": "vitest",
56
+ "typecheck": "tsc --noEmit",
57
+ "clean": "rm -rf dist"
58
+ };
59
+ var dependencies = {
60
+ "@clack/prompts": "^0.8.2",
61
+ "commander": "^12.1.0",
62
+ "open": "^10.1.0",
63
+ "picocolors": "^1.1.1",
64
+ "yaml": "^2.5.1"
65
+ };
66
+ var devDependencies = {
67
+ "@sequel/mcp-clients": "workspace:*",
68
+ "@sequel/typescript-config": "workspace:*",
69
+ "@types/node": "^22.10.0",
70
+ "tsdown": "^0.9.0",
71
+ "typescript": "^5.7.0",
72
+ "vitest": "^3.0.0"
73
+ };
74
+ var package_default = {
75
+ name,
76
+ version,
77
+ description,
78
+ license,
79
+ type,
80
+ bin,
81
+ files,
82
+ exports,
83
+ engines,
84
+ repository,
85
+ homepage,
86
+ keywords,
87
+ publishConfig,
88
+ scripts,
89
+ dependencies,
90
+ devDependencies
91
+ };
92
+
93
+ //#endregion
18
94
  //#region src/lib/config.ts
19
95
  /** Default production API base. Override with SEQUEL_API_URL for local/dev. */
20
96
  const DEFAULT_API_URL = "https://api.sequel.sh";
97
+ /** Default marketing site, which publishes the Sequel skill. Override with SEQUEL_SITE_URL. */
98
+ const DEFAULT_SITE_URL = "https://sequel.sh";
99
+ function resolveSiteUrl() {
100
+ return process.env.SEQUEL_SITE_URL || DEFAULT_SITE_URL;
101
+ }
21
102
  /** Directory holding the CLI's state. Overridable for tests. */
22
103
  function configDir() {
23
104
  return process.env.SEQUEL_CONFIG_DIR || join(homedir(), ".sequel");
@@ -408,14 +489,21 @@ function search(useCase, connectionIds) {
408
489
  }
409
490
  });
410
491
  }
411
- async function createApiKey(name) {
492
+ async function createApiKey(name$1) {
412
493
  const orgId = await activeOrgId();
413
494
  return request(`/organizations/${orgId}/api-keys`, {
414
495
  method: "POST",
415
496
  org: "none",
416
- body: { name }
497
+ body: { name: name$1 }
417
498
  });
418
499
  }
500
+ /** Get a signed URL to download a file produced in a session (by sequel_execute / workbench). */
501
+ function getFileDownloadUrl(sessionId, path) {
502
+ return request("/files/download", { query: {
503
+ session_id: sessionId,
504
+ path
505
+ } });
506
+ }
419
507
 
420
508
  //#endregion
421
509
  //#region src/lib/output.ts
@@ -449,13 +537,14 @@ function renderTable(rows, columns) {
449
537
  return `${header}\n${pc.dim(sep)}\n${body}`;
450
538
  }
451
539
  function printTable(rows, columns) {
540
+ if (jsonMode) return;
452
541
  process.stdout.write(`${renderTable(rows, columns)}\n`);
453
542
  }
454
543
  function success(message) {
455
- process.stdout.write(`${pc.green("✓")} ${message}\n`);
544
+ (jsonMode ? process.stderr : process.stdout).write(`${pc.green("✓")} ${message}\n`);
456
545
  }
457
546
  function info(message) {
458
- process.stdout.write(`${message}\n`);
547
+ (jsonMode ? process.stderr : process.stdout).write(`${message}\n`);
459
548
  }
460
549
  function fail(message) {
461
550
  process.stderr.write(`${pc.red("✗")} ${message}\n`);
@@ -463,12 +552,23 @@ function fail(message) {
463
552
 
464
553
  //#endregion
465
554
  //#region src/commands/login.ts
466
- async function loginCommand() {
467
- p$4.intro(pc.cyan("Sign in to Sequel"));
468
- p$4.log.info("Opening your browser to authorize…");
469
- const res = await runLoginFlow();
555
+ async function loginCommand(opts = {}) {
556
+ const json = isJsonMode();
557
+ const openBrowser = opts.browser !== false;
558
+ const opening = openBrowser ? "Opening your browser to authorize…" : "Sign in with the URL below…";
559
+ if (json) info(opening);
560
+ else {
561
+ p$5.intro(pc.cyan("Sign in to Sequel"));
562
+ p$5.log.info(opening);
563
+ }
564
+ const res = await runLoginFlow({ silent: !openBrowser });
565
+ if (json) return printJson({
566
+ status: "logged_in",
567
+ user: res.user,
568
+ org: res.org ?? null
569
+ });
470
570
  success(`Logged in as ${pc.bold(res.user.email)}${res.org ? ` · ${pc.bold(res.org.name)}` : ""}`);
471
- p$4.outro("You're all set. Try `sequel sources list` or `sequel connect`.");
571
+ p$5.outro("You're all set. Try `sequel sources list` or `sequel connect`.");
472
572
  }
473
573
 
474
574
  //#endregion
@@ -476,16 +576,19 @@ async function loginCommand() {
476
576
  async function logoutCommand() {
477
577
  const config = readConfig();
478
578
  if (!isLoggedIn$1(config)) {
579
+ if (isJsonMode()) return printJson({ status: "not_logged_in" });
479
580
  info("You are not logged in.");
480
581
  return;
481
582
  }
482
583
  clearConfig();
584
+ if (isJsonMode()) return printJson({ status: "logged_out" });
483
585
  success("Logged out. Cached credentials removed from ~/.sequel/auth.json.");
484
586
  }
485
587
 
486
588
  //#endregion
487
589
  //#region src/commands/switch.ts
488
590
  async function switchCommand() {
591
+ if (isJsonMode()) throw new Error("`sequel switch` is interactive (it prompts for an organization) — run it in a terminal, not piped/--json.");
489
592
  const config = readConfig();
490
593
  if (!isLoggedIn$1(config)) throw new Error("Not logged in. Run `sequel login` first.");
491
594
  let orgs = config.orgs ?? [];
@@ -498,7 +601,7 @@ async function switchCommand() {
498
601
  });
499
602
  } catch {}
500
603
  if (orgs.length === 0) throw new Error("No organizations available for this account.");
501
- const selection = await p$3.select({
604
+ const selection = await p$4.select({
502
605
  message: "Switch to organization",
503
606
  options: orgs.map((o) => ({
504
607
  value: o.id,
@@ -506,8 +609,8 @@ async function switchCommand() {
506
609
  hint: config.tokens[o.id] ? o.role : "sign-in required"
507
610
  }))
508
611
  });
509
- if (p$3.isCancel(selection)) {
510
- p$3.cancel("Cancelled.");
612
+ if (p$4.isCancel(selection)) {
613
+ p$4.cancel("Cancelled.");
511
614
  return;
512
615
  }
513
616
  const orgId = selection;
@@ -521,7 +624,7 @@ async function switchCommand() {
521
624
  success(`Switched to ${pc.bold(org?.name ?? orgId)}.`);
522
625
  return;
523
626
  }
524
- p$3.log.info(`You haven't authorized ${pc.bold(org?.name ?? orgId)} yet — opening your browser…`);
627
+ p$4.log.info(`You haven't authorized ${pc.bold(org?.name ?? orgId)} yet — opening your browser…`);
525
628
  const res = await runLoginFlow();
526
629
  success(`Switched to ${pc.bold(res.org?.name ?? res.organizationId)}.`);
527
630
  }
@@ -560,13 +663,14 @@ async function pollLink(token) {
560
663
  };
561
664
  }
562
665
  async function connectCommand(source) {
666
+ if (isJsonMode()) throw new Error("`sequel connect` is interactive (it prompts for credentials/consent) — run it in a terminal, not piped/--json.");
563
667
  const connectors = await listConnectors();
564
668
  let connector;
565
669
  if (source) {
566
670
  connector = connectors.find((c) => c.id === source);
567
671
  if (!connector) throw new Error(`Unknown connector "${source}". Available: ${connectors.map((c) => c.id).join(", ")}`);
568
672
  } else {
569
- const choice = await p$2.select({
673
+ const choice = await p$3.select({
570
674
  message: "Which data source do you want to connect?",
571
675
  options: connectors.slice().sort((a, b) => a.appType.localeCompare(b.appType) || a.name.localeCompare(b.name)).map((c) => ({
572
676
  value: c.id,
@@ -574,38 +678,38 @@ async function connectCommand(source) {
574
678
  hint: c.appType
575
679
  }))
576
680
  });
577
- if (p$2.isCancel(choice)) {
578
- p$2.cancel("Cancelled.");
681
+ if (p$3.isCancel(choice)) {
682
+ p$3.cancel("Cancelled.");
579
683
  return;
580
684
  }
581
685
  connector = connectors.find((c) => c.id === choice);
582
686
  }
583
- p$2.intro(`Connect ${pc.bold(connector.name)}`);
687
+ p$3.intro(`Connect ${pc.bold(connector.name)}`);
584
688
  if (!isOAuth(connector)) {
585
689
  const fields = fieldsFor(connector);
586
690
  const credentials = {};
587
691
  for (const field of fields) {
588
692
  const secret = SECRET_RE.test(field);
589
- const value = await (secret ? p$2.password : p$2.text)({ message: field });
590
- if (p$2.isCancel(value)) {
591
- p$2.cancel("Cancelled.");
693
+ const value = await (secret ? p$3.password : p$3.text)({ message: field });
694
+ if (p$3.isCancel(value)) {
695
+ p$3.cancel("Cancelled.");
592
696
  return;
593
697
  }
594
698
  credentials[field] = value;
595
699
  }
596
- const name = await p$2.text({
700
+ const name$1 = await p$3.text({
597
701
  message: "Name for this source (optional)",
598
702
  placeholder: connector.name
599
703
  });
600
- if (p$2.isCancel(name)) {
601
- p$2.cancel("Cancelled.");
704
+ if (p$3.isCancel(name$1)) {
705
+ p$3.cancel("Cancelled.");
602
706
  return;
603
707
  }
604
- const s$1 = p$2.spinner();
708
+ const s$1 = p$3.spinner();
605
709
  s$1.start("Validating credentials…");
606
710
  const res$1 = await createLink(connector.id, {
607
711
  credentials,
608
- ...name ? { name } : {}
712
+ ...name$1 ? { name: name$1 } : {}
609
713
  });
610
714
  if (res$1.status === "success") {
611
715
  s$1.stop("Connected.");
@@ -627,7 +731,7 @@ async function connectCommand(source) {
627
731
  }
628
732
  open(res.redirect_url).catch(() => {});
629
733
  info(`Complete authorization in your browser:\n${res.redirect_url}`);
630
- const s = p$2.spinner();
734
+ const s = p$3.spinner();
631
735
  s.start("Waiting for you to finish in the browser…");
632
736
  const result = await pollLink(res.link_token);
633
737
  if (result.ok) {
@@ -654,7 +758,7 @@ async function pickConnection(message) {
654
758
  info("No sources connected yet. Run `sequel connect`.");
655
759
  return void 0;
656
760
  }
657
- const choice = await p$1.select({
761
+ const choice = await p$2.select({
658
762
  message,
659
763
  options: all.map((c) => ({
660
764
  value: c.shortId,
@@ -662,7 +766,7 @@ async function pickConnection(message) {
662
766
  hint: c.type
663
767
  }))
664
768
  });
665
- if (p$1.isCancel(choice)) return void 0;
769
+ if (p$2.isCancel(choice)) return void 0;
666
770
  return all.find((c) => c.shortId === choice);
667
771
  }
668
772
  function toRow(c) {
@@ -731,8 +835,8 @@ async function sourcesInfo(idOrShort) {
731
835
  async function sourcesDelete(idOrShort) {
732
836
  const conn = idOrShort ? await resolveConnection(idOrShort) : await pickConnection("Source to delete");
733
837
  if (!conn) return;
734
- const confirmed = await p$1.confirm({ message: `Delete ${pc.bold(conn.name)} (${conn.shortId})? This cannot be undone.` });
735
- if (p$1.isCancel(confirmed) || !confirmed) {
838
+ const confirmed = await p$2.confirm({ message: `Delete ${pc.bold(conn.name)} (${conn.shortId})? This cannot be undone.` });
839
+ if (p$2.isCancel(confirmed) || !confirmed) {
736
840
  info("Cancelled.");
737
841
  return;
738
842
  }
@@ -741,8 +845,48 @@ async function sourcesDelete(idOrShort) {
741
845
  }
742
846
 
743
847
  //#endregion
744
- //#region src/lib/mcp-clients.ts
848
+ //#region src/commands/skills.ts
849
+ async function publicGet(path) {
850
+ const res = await fetch(`${resolveApiUrl(readConfig())}${path}`, { headers: { Accept: "application/json" } });
851
+ if (res.status === 404) throw new Error(`No skill found matching "${path.split("/").pop()}". Run \`sequel skills list\`.`);
852
+ if (!res.ok) throw new Error(`Request failed (${res.status})`);
853
+ return await res.json();
854
+ }
855
+ async function skillsList() {
856
+ const skills$1 = await publicGet("/marketplace/skills");
857
+ const rows = skills$1.map((s) => ({
858
+ id: s.slug,
859
+ name: s.name
860
+ }));
861
+ if (isJsonMode()) return printJson(rows);
862
+ printTable(rows, ["id", "name"]);
863
+ info(`${rows.length} skills. \`sequel skills show <id>\` prints one; \`sequel install\` gives your agent all of them.`);
864
+ }
865
+ async function skillsShow(slug) {
866
+ const skill = await publicGet(`/marketplace/skills/${encodeURIComponent(slug)}`);
867
+ if (isJsonMode()) return printJson(skill);
868
+ process.stdout.write(`${pc.bold(skill.name)} ${pc.dim(skill.slug)}\n${skill.description}\n` + (skill.apps.length ? `${pc.dim("apps:")} ${skill.apps.join(", ")}\n` : "") + `\n${skill.instructions}\n`);
869
+ }
870
+
871
+ //#endregion
872
+ //#region ../mcp-clients/dist/install.js
745
873
  const SERVER_NAME = "sequel";
874
+ /** Folder name of the Sequel skill inside an agent's skills directory. */
875
+ const SKILL_NAME = "sequel";
876
+ /**
877
+ * Write the Sequel SKILL.md into `<dir>/sequel/SKILL.md`, replacing any previous
878
+ * copy. Skill files are plain markdown, so unlike the MCP configs there is
879
+ * nothing to merge: the whole file is ours.
880
+ */
881
+ function installSkill({ dir, markdown }) {
882
+ const path = join(dir, SKILL_NAME, "SKILL.md");
883
+ mkdirSync(dirname(path), { recursive: true });
884
+ writeFileSync(path, markdown.endsWith("\n") ? markdown : `${markdown}\n`);
885
+ return {
886
+ kind: "file",
887
+ path
888
+ };
889
+ }
746
890
  const mcpUrl = (apiUrl) => `${apiUrl.replace(/\/$/, "")}/mcp`;
747
891
  const bearer = (apiKey) => `Bearer ${apiKey}`;
748
892
  function home(opts) {
@@ -811,6 +955,7 @@ const mcpClients = [
811
955
  name: "Claude Code",
812
956
  scopes: ["global", "local"],
813
957
  describe: (o) => `claude mcp add --scope ${o.scope === "global" ? "user" : "local"} --transport http ${SERVER_NAME} …`,
958
+ skillsDir: (o) => o.scope === "global" ? join(home(o), ".claude", "skills") : join(cwd(o), ".claude", "skills"),
814
959
  install(o) {
815
960
  return {
816
961
  kind: "command",
@@ -915,37 +1060,117 @@ const mcpClients = [
915
1060
  path
916
1061
  };
917
1062
  }
1063
+ },
1064
+ {
1065
+ slug: "openclaw",
1066
+ name: "OpenClaw",
1067
+ scopes: ["global"],
1068
+ describe: () => `openclaw mcp set ${SERVER_NAME} …`,
1069
+ install(o) {
1070
+ const def = JSON.stringify({
1071
+ url: mcpUrl(o.apiUrl),
1072
+ transport: "streamable-http",
1073
+ headers: { Authorization: bearer(o.apiKey) }
1074
+ });
1075
+ return {
1076
+ kind: "command",
1077
+ command: "openclaw",
1078
+ args: [
1079
+ "mcp",
1080
+ "set",
1081
+ SERVER_NAME,
1082
+ def
1083
+ ]
1084
+ };
1085
+ }
1086
+ },
1087
+ {
1088
+ slug: "hermes",
1089
+ name: "Hermes",
1090
+ scopes: ["global"],
1091
+ describe: (o) => join(home(o), ".hermes", "config.yaml"),
1092
+ install(o) {
1093
+ const path = join(home(o), ".hermes", "config.yaml");
1094
+ mergeYaml(path, (cfg) => setNested(cfg, "mcp_servers", {
1095
+ url: mcpUrl(o.apiUrl),
1096
+ headers: { Authorization: bearer(o.apiKey) }
1097
+ }));
1098
+ return {
1099
+ kind: "file",
1100
+ path
1101
+ };
1102
+ }
918
1103
  }
919
1104
  ];
920
1105
  function getMcpClient(slug) {
921
1106
  return mcpClients.find((c) => c.slug === slug);
922
1107
  }
923
1108
 
1109
+ //#endregion
1110
+ //#region src/lib/skills.ts
1111
+ /**
1112
+ * The canonical Sequel skill is published by the marketing site under the Agent
1113
+ * Skills discovery convention. The CLI downloads it at install time rather than
1114
+ * bundling a copy, so an installed skill is always the current one and there is
1115
+ * a single source of truth for its content.
1116
+ */
1117
+ function skillMarkdownUrl() {
1118
+ return `${resolveSiteUrl().replace(/\/$/, "")}/.well-known/agent-skills/sequel/SKILL.md`;
1119
+ }
1120
+ async function fetchSkillMarkdown() {
1121
+ const url = skillMarkdownUrl();
1122
+ const res = await fetch(url, { headers: { Accept: "text/markdown, text/plain;q=0.9, */*;q=0.1" } });
1123
+ if (!res.ok) throw new Error(`Could not download the Sequel skill (${res.status}) from ${url}`);
1124
+ const text = await res.text();
1125
+ if (!text.trimStart().startsWith("---")) throw new Error(`Unexpected response from ${url}: not a SKILL.md`);
1126
+ return text;
1127
+ }
1128
+
924
1129
  //#endregion
925
1130
  //#region src/commands/install.ts
926
- async function installCommand(slugArg) {
927
- p.intro(pc.cyan("Install the Sequel MCP server"));
1131
+ const SCOPES = ["global", "local"];
1132
+ async function installCommand(slugArg, opts = {}) {
1133
+ const interactive = !isJsonMode();
1134
+ const slugList = mcpClients.map((c) => c.slug).join(", ");
1135
+ if (interactive) p$1.intro(pc.cyan("Install the Sequel MCP server and skill"));
1136
+ if (slugArg && !getMcpClient(slugArg)) throw new Error(`Unknown agent "${slugArg}". Options: ${slugList}`);
1137
+ if (!slugArg && !interactive) throw new Error(`Pass the agent slug when running non-interactively: \`sequel install <agent>\`. Options: ${slugList}`);
928
1138
  if (!isLoggedIn()) {
929
- p.cancel("Not logged in. Run `sequel login` first.");
930
- return;
1139
+ const msg = "You need to sign in to Sequel first — opening your browser…";
1140
+ if (interactive) p$1.log.info(msg);
1141
+ else info(msg);
1142
+ try {
1143
+ const result$1 = await runLoginFlow({ silent: opts.browser === false });
1144
+ const signedIn = `Signed in as ${result$1.user.email}${result$1.org ? ` (${result$1.org.name})` : ""}.`;
1145
+ if (interactive) p$1.log.success(signedIn);
1146
+ else success(signedIn);
1147
+ } catch (err) {
1148
+ if (!interactive) throw err;
1149
+ p$1.cancel(err instanceof Error ? err.message : String(err));
1150
+ return;
1151
+ }
931
1152
  }
932
1153
  let slug = slugArg;
933
1154
  if (!slug) {
934
- const choice = await p.select({
1155
+ const choice = await p$1.select({
935
1156
  message: "Which coding agent do you want to install Sequel into?",
936
1157
  options: mcpClients.map((c) => ({
937
1158
  value: c.slug,
938
1159
  label: c.name
939
1160
  }))
940
1161
  });
941
- if (p.isCancel(choice)) return p.cancel("Cancelled.");
1162
+ if (p$1.isCancel(choice)) return p$1.cancel("Cancelled.");
942
1163
  slug = choice;
943
1164
  }
944
1165
  const client = getMcpClient(slug);
945
- if (!client) throw new Error(`Unknown agent "${slug}". Options: ${mcpClients.map((c) => c.slug).join(", ")}`);
1166
+ if (!client) throw new Error(`Unknown agent "${slug}". Options: ${slugList}`);
946
1167
  let scope = client.scopes[0];
947
- if (client.scopes.length > 1) {
948
- const choice = await p.select({
1168
+ if (opts.scope !== void 0) {
1169
+ if (!SCOPES.includes(opts.scope)) throw new Error(`Unknown scope "${opts.scope}". Options: ${SCOPES.join(", ")}`);
1170
+ if (!client.scopes.includes(opts.scope)) throw new Error(`${client.name} only supports the ${client.scopes.join("/")} scope.`);
1171
+ scope = opts.scope;
1172
+ } else if (client.scopes.length > 1 && interactive) {
1173
+ const choice = await p$1.select({
949
1174
  message: "Install scope",
950
1175
  options: [{
951
1176
  value: "global",
@@ -957,21 +1182,21 @@ async function installCommand(slugArg) {
957
1182
  hint: "this project only"
958
1183
  }].filter((o) => client.scopes.includes(o.value))
959
1184
  });
960
- if (p.isCancel(choice)) return p.cancel("Cancelled.");
1185
+ if (p$1.isCancel(choice)) return p$1.cancel("Cancelled.");
961
1186
  scope = choice;
962
1187
  }
963
1188
  const config = readConfig();
964
1189
  const apiUrl = resolveApiUrl(config);
965
- const s = p.spinner();
966
- s.start("Creating a Sequel API key for this agent…");
1190
+ const s = interactive ? p$1.spinner() : null;
1191
+ s?.start("Creating a Sequel API key for this agent…");
967
1192
  let key;
968
1193
  try {
969
1194
  ({key} = await createApiKey(`Sequel CLI (${client.name})`));
970
1195
  } catch (err) {
971
- s.stop("Failed to create API key.");
1196
+ s?.stop("Failed to create API key.");
972
1197
  throw err;
973
1198
  }
974
- s.stop("API key created.");
1199
+ s ? s.stop("API key created.") : info("API key created.");
975
1200
  const result = client.install({
976
1201
  apiUrl,
977
1202
  apiKey: key,
@@ -986,9 +1211,34 @@ async function installCommand(slugArg) {
986
1211
  success(`Installed Sequel into ${client.name} (${scope}).`);
987
1212
  } else {
988
1213
  success(`Installed Sequel into ${client.name}.`);
989
- p.log.info(`Config written to ${pc.dim(result.path)}`);
1214
+ info(`Config written to ${pc.dim(result.path)}`);
990
1215
  }
991
- p.outro(`Restart ${client.name} and ask it to "list my Sequel connections" to verify.`);
1216
+ const skillsDir = client.skillsDir?.({
1217
+ apiUrl,
1218
+ apiKey: key,
1219
+ scope
1220
+ }) ?? null;
1221
+ if (skillsDir) {
1222
+ const sk = interactive ? p$1.spinner() : null;
1223
+ sk?.start("Installing the Sequel skill…");
1224
+ try {
1225
+ const markdown = await fetchSkillMarkdown();
1226
+ const written = installSkill({
1227
+ dir: skillsDir,
1228
+ markdown
1229
+ });
1230
+ sk ? sk.stop("Sequel skill installed.") : success("Sequel skill installed.");
1231
+ info(`Skill written to ${pc.dim(written.path)}`);
1232
+ } catch (err) {
1233
+ sk?.stop("Could not install the Sequel skill.");
1234
+ const warning = `${err instanceof Error ? err.message : String(err)}\nSequel still works through MCP; rerun \`sequel install ${client.slug}\` later to add the skill.`;
1235
+ if (interactive) p$1.log.warn(warning);
1236
+ else info(`Could not install the Sequel skill. ${warning}`);
1237
+ }
1238
+ } else info(`${client.name} has no skills directory the CLI can write to; the Sequel skill is skipped. Playbooks are still available through MCP.`);
1239
+ const done = `Restart ${client.name} and ask it to "list my Sequel connections" to verify.`;
1240
+ if (interactive) p$1.outro(done);
1241
+ else info(done);
992
1242
  }
993
1243
 
994
1244
  //#endregion
@@ -1030,14 +1280,111 @@ async function executeCommand(connectionId, tool, opts) {
1030
1280
  info(pc.dim(`\n${res.row_count} row(s)${res.truncated ? " (truncated)" : ""}`));
1031
1281
  }
1032
1282
 
1283
+ //#endregion
1284
+ //#region src/commands/download.ts
1285
+ function formatBytes(n) {
1286
+ if (n < 1024) return `${n} B`;
1287
+ if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
1288
+ return `${(n / (1024 * 1024)).toFixed(1)} MB`;
1289
+ }
1290
+ async function downloadCommand(sessionId, filePath, opts) {
1291
+ const meta = await getFileDownloadUrl(sessionId, filePath);
1292
+ if (isJsonMode()) return printJson(meta);
1293
+ const res = await fetch(meta.url);
1294
+ if (!res.ok) throw new Error(`Download failed (${res.status} ${res.statusText})`);
1295
+ const dest = opts.output ?? meta.filename;
1296
+ await writeFile(dest, Buffer.from(await res.arrayBuffer()));
1297
+ info(`${pc.green("✓")} Downloaded ${pc.bold(meta.filename)} (${formatBytes(meta.size)}) → ${dest}`);
1298
+ }
1299
+
1300
+ //#endregion
1301
+ //#region src/commands/upgrade.ts
1302
+ const PKG = "@sequelsh/cli@latest";
1303
+ const MANAGERS = [
1304
+ {
1305
+ name: "npm",
1306
+ cmd: "npm",
1307
+ args: [
1308
+ "install",
1309
+ "-g",
1310
+ PKG
1311
+ ]
1312
+ },
1313
+ {
1314
+ name: "pnpm",
1315
+ cmd: "pnpm",
1316
+ args: [
1317
+ "add",
1318
+ "-g",
1319
+ PKG
1320
+ ]
1321
+ },
1322
+ {
1323
+ name: "bun",
1324
+ cmd: "bun",
1325
+ args: [
1326
+ "add",
1327
+ "-g",
1328
+ PKG
1329
+ ]
1330
+ },
1331
+ {
1332
+ name: "yarn",
1333
+ cmd: "yarn",
1334
+ args: [
1335
+ "global",
1336
+ "add",
1337
+ PKG
1338
+ ]
1339
+ }
1340
+ ];
1341
+ function has(cmd) {
1342
+ try {
1343
+ execFileSync(process.platform === "win32" ? "where" : "which", [cmd], { stdio: "ignore" });
1344
+ return true;
1345
+ } catch {
1346
+ return false;
1347
+ }
1348
+ }
1349
+ async function upgradeCommand() {
1350
+ const json = isJsonMode();
1351
+ if (!json) p.intro(pc.cyan("Upgrade the Sequel CLI"));
1352
+ const manager = MANAGERS.find((m) => has(m.cmd));
1353
+ if (!manager) {
1354
+ const msg = "No supported package manager found (npm, pnpm, bun, or yarn). Install Node.js from https://nodejs.org and try again.";
1355
+ if (json) return printJson({
1356
+ status: "error",
1357
+ error: msg
1358
+ });
1359
+ p.cancel(msg);
1360
+ return;
1361
+ }
1362
+ const s = json ? null : p.spinner();
1363
+ s?.start(`Updating ${PKG} with ${manager.name}…`);
1364
+ try {
1365
+ execFileSync(manager.cmd, manager.args, { stdio: "pipe" });
1366
+ } catch (err) {
1367
+ s?.stop("Upgrade failed.");
1368
+ throw new Error(`Failed to run \`${manager.cmd} ${manager.args.join(" ")}\`.\n${err instanceof Error ? err.message : String(err)}`);
1369
+ }
1370
+ s?.stop("Updated.");
1371
+ if (json) return printJson({
1372
+ status: "upgraded",
1373
+ package: PKG,
1374
+ manager: manager.name
1375
+ });
1376
+ success("Sequel CLI is now on the latest version.");
1377
+ p.outro("Run `sequel --version` to confirm.");
1378
+ }
1379
+
1033
1380
  //#endregion
1034
1381
  //#region src/index.ts
1035
1382
  const program = new Command();
1036
- program.name("sequel").description("Sequel CLI — connect data sources and run tools from your terminal").version("0.0.0").option("--json", "output machine-readable JSON").enablePositionalOptions();
1383
+ program.name("sequel").description("Sequel CLI — connect data sources and run tools from your terminal").version(package_default.version).option("--json", "output machine-readable JSON").enablePositionalOptions();
1037
1384
  /** Wrap a command action with shared --json handling and error reporting. */
1038
1385
  function action(fn) {
1039
1386
  return async (...args) => {
1040
- if (program.opts().json) setJsonMode(true);
1387
+ if (program.opts().json || !process.stdout.isTTY) setJsonMode(true);
1041
1388
  try {
1042
1389
  await fn(...args);
1043
1390
  } catch (err) {
@@ -1047,7 +1394,8 @@ function action(fn) {
1047
1394
  }
1048
1395
  };
1049
1396
  }
1050
- program.command("login").description("Sign in to Sequel").action(action(loginCommand));
1397
+ program.command("upgrade").description("Upgrade the Sequel CLI to the latest version").action(action(upgradeCommand));
1398
+ program.command("login").description("Sign in to Sequel").option("--no-browser", "print the sign-in URL instead of opening a browser").action(action(loginCommand));
1051
1399
  program.command("logout").description("Sign out and remove cached credentials").action(action(logoutCommand));
1052
1400
  program.command("switch").description("Switch the active organization").action(action(switchCommand));
1053
1401
  program.command("connect").argument("[source]", "connector id (e.g. postgres); omit to choose interactively").description("Connect a new data source").action(action(connectCommand));
@@ -1056,9 +1404,13 @@ sources.command("list", { isDefault: true }).description("List connected sources
1056
1404
  sources.command("active").description("List sources with live health status").action(action(sourcesActive));
1057
1405
  sources.command("info").argument("[id]", "source id or short id").description("Show details for a source").action(action(sourcesInfo));
1058
1406
  sources.command("delete").argument("[id]", "source id or short id").description("Delete a source").action(action(sourcesDelete));
1059
- program.command("install").argument("[agent]", "coding agent slug (e.g. cursor, claude-code)").description("Install the Sequel MCP server into a coding agent").action(action(installCommand));
1407
+ const skills = program.command("skills").description("Browse the playbooks your agent can follow");
1408
+ skills.command("list", { isDefault: true }).description("List every skill (id and name)").action(action(skillsList));
1409
+ skills.command("show").argument("<id>", "skill id, e.g. seo").description("Print a skill's playbook").action(action((id) => skillsShow(id)));
1410
+ program.command("install").argument("[agent]", "coding agent slug (e.g. cursor, claude-code)").option("-s, --scope <scope>", "global or local; skips the prompt (defaults to global when piped)").option("--no-browser", "print the sign-in URL instead of opening a browser if sign-in is needed").description("Install the Sequel MCP server into a coding agent").action(action(installCommand));
1060
1411
  program.command("search").argument("<usecase>", "what you want to do, e.g. \"monthly revenue\"").option("-c, --connection <id...>", "limit to specific connection short ids").description("Find the right tools for a use case across your sources").action(action((usecase, opts) => searchCommand(usecase, opts)));
1061
1412
  program.command("execute").argument("<connection_id>", "connection short id").argument("<tool>", "tool id, e.g. postgres.query").option("-d, --data <json>", "tool input as a JSON string").description("Execute a tool against a connection").action(action((connectionId, tool, opts) => executeCommand(connectionId, tool, opts)));
1413
+ program.command("download").argument("<session_id>", "session id (from `sequel search` or an agent session)").argument("<path>", "file path, e.g. /data/result.csv or result.csv").option("-o, --output <file>", "write to this path (default: the file's own name)").description("Download a file produced by a query or workbench run").action(action((sessionId, path, opts) => downloadCommand(sessionId, path, opts)));
1062
1414
  program.parseAsync(process.argv).catch((err) => {
1063
1415
  fail(err instanceof Error ? err.message : String(err));
1064
1416
  process.exit(1);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["config?: AuthConfig | null","config: AuthConfig","isLoggedIn","buf: Buffer","apiUrl: string","params: Record<string, string>","redirectUri: string","accessToken: string","expectedState: string","resolveCode!: (code: string) => void","rejectCode!: (err: Error) => void","title: string","message: string","options?: { silent?: boolean }","next: AuthConfig","entry: TokenEntry","status: number","message: string","path: string","options: RequestOptions","headers: Record<string, string>","body: string | undefined","text","id: string","appId: string","body: Record<string, unknown>","token: string","connectionId: string","tool: string","params: Record<string, unknown>","useCase: string","connectionIds?: string[]","name: string","on: boolean","data: unknown","value: unknown","rows: Array<Record<string, unknown>>","columns?: string[]","message: string","connector: Connector","token: string","source?: string","connector: Connector | undefined","credentials: Record<string, string>","p","s","res","result","idOrShort: string","message: string","c: Connection","idOrShort?: string","config: { schemaFilters: string[] | null; instructions: string | null } | null","apiUrl: string","apiKey: string","opts: InstallOptions","vendor: string","path: string","mutate: (cfg: Record<string, unknown>) => void","cfg: Record<string, unknown>","key: string","value: unknown","mcpClients: McpClientDef[]","slug: string","slugArg?: string","scope: Scope","key: string","useCase: string","opts: { connection?: string[] }","connectionId: string","tool: string","opts: { data?: string }","params: Record<string, unknown>","fn: (...args: A) => Promise<void>","usecase: string","opts: { connection?: string[] }","connectionId: string","tool: string","opts: { data?: string }"],"sources":["../src/lib/config.ts","../src/lib/auth.ts","../src/lib/api.ts","../src/lib/output.ts","../src/commands/login.ts","../src/commands/logout.ts","../src/commands/switch.ts","../src/commands/connect.ts","../src/commands/sources.ts","../src/lib/mcp-clients.ts","../src/commands/install.ts","../src/commands/search.ts","../src/commands/execute.ts","../src/index.ts"],"sourcesContent":["import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { mkdirSync, readFileSync, writeFileSync, rmSync, existsSync, chmodSync } from \"node:fs\";\n\n/** Default production API base. Override with SEQUEL_API_URL for local/dev. */\nexport const DEFAULT_API_URL = \"https://api.sequel.sh\";\n\n/** One OAuth token bundle, scoped to a single organization. */\nexport interface TokenEntry {\n accessToken: string;\n refreshToken: string;\n /** ms epoch when the access token expires. */\n expiresAt: number;\n}\n\nexport interface OrgRef {\n id: string;\n name: string;\n slug: string;\n role: string;\n}\n\nexport interface UserRef {\n id: string;\n email: string;\n name: string;\n}\n\n/**\n * The on-disk shape of ~/.sequel/auth.json.\n *\n * Multi-token cache: one genuine org-bound OAuth token per organization, keyed\n * by org id. `activeOrgId` selects which token requests use right now. Switching\n * orgs is an offline swap when the target org already has a cached token.\n */\nexport interface AuthConfig {\n version: 1;\n apiUrl: string;\n /** Persisted dynamic client registration, reused across logins. */\n clientId?: string;\n activeOrgId?: string;\n tokens: Record<string, TokenEntry>;\n user?: UserRef;\n /** Cached membership list for the `switch` UI. */\n orgs?: OrgRef[];\n}\n\n/** Directory holding the CLI's state. Overridable for tests. */\nexport function configDir(): string {\n return process.env.SEQUEL_CONFIG_DIR || join(homedir(), \".sequel\");\n}\n\nexport function configPath(): string {\n return join(configDir(), \"auth.json\");\n}\n\n/** The API base URL: explicit env wins, then a saved value, then the default. */\nexport function resolveApiUrl(config?: AuthConfig | null): string {\n return process.env.SEQUEL_API_URL || config?.apiUrl || DEFAULT_API_URL;\n}\n\nfunction emptyConfig(): AuthConfig {\n return { version: 1, apiUrl: resolveApiUrl(), tokens: {} };\n}\n\n/** Read auth.json, returning a fresh empty config if missing or corrupt. */\nexport function readConfig(): AuthConfig {\n const path = configPath();\n if (!existsSync(path)) return emptyConfig();\n try {\n const parsed = JSON.parse(readFileSync(path, \"utf8\")) as AuthConfig;\n if (!parsed || typeof parsed !== \"object\" || !parsed.tokens) return emptyConfig();\n parsed.tokens ??= {};\n return parsed;\n } catch {\n // Corrupt file — start clean rather than crash.\n return emptyConfig();\n }\n}\n\n/** Persist auth.json with locked-down permissions (dir 0700, file 0600). */\nexport function writeConfig(config: AuthConfig): void {\n const dir = configDir();\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n const path = configPath();\n writeFileSync(path, `${JSON.stringify(config, null, 2)}\\n`, { mode: 0o600 });\n // writeFileSync only applies mode on create; enforce it on existing files too.\n chmodSync(path, 0o600);\n}\n\n/** Remove all stored credentials. Idempotent. */\nexport function clearConfig(): void {\n const path = configPath();\n if (existsSync(path)) rmSync(path);\n}\n\nexport function isLoggedIn(config: AuthConfig): boolean {\n return Boolean(config.activeOrgId && config.tokens[config.activeOrgId]);\n}\n","import { createHash, randomBytes } from \"node:crypto\";\nimport { createServer } from \"node:http\";\nimport { AddressInfo } from \"node:net\";\nimport open from \"open\";\nimport {\n type AuthConfig,\n type OrgRef,\n type TokenEntry,\n type UserRef,\n readConfig,\n writeConfig,\n resolveApiUrl,\n} from \"./config\";\n\n/** Refresh a token this many ms before it actually expires. */\nconst EXPIRY_SKEW_MS = 60_000;\n\nfunction base64url(buf: Buffer): string {\n return buf.toString(\"base64url\");\n}\n\n/** PKCE pair: challenge = base64url(sha256(verifier)), matching the API's S256. */\nexport function generatePkce(): { verifier: string; challenge: string } {\n const verifier = base64url(randomBytes(32));\n const challenge = base64url(createHash(\"sha256\").update(verifier).digest());\n return { verifier, challenge };\n}\n\ninterface TokenResponse {\n access_token: string;\n refresh_token: string;\n expires_in: number;\n token_type: string;\n}\n\ninterface WhoAmI {\n id: string;\n name: string;\n email: string;\n organizationId: string;\n}\n\n/** POST the OAuth token endpoint (form-encoded, per RFC 6749). */\nasync function postToken(apiUrl: string, params: Record<string, string>): Promise<TokenResponse> {\n const res = await fetch(`${apiUrl}/oauth/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams(params).toString(),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`Token request failed (${res.status}): ${body}`);\n }\n return (await res.json()) as TokenResponse;\n}\n\n/** Register a fresh dynamic OAuth client bound to this run's loopback URI. */\nasync function registerClient(apiUrl: string, redirectUri: string): Promise<string> {\n const res = await fetch(`${apiUrl}/oauth/register`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ client_name: \"Sequel CLI\", redirect_uris: [redirectUri] }),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`Client registration failed (${res.status}): ${body}`);\n }\n const data = (await res.json()) as { client_id: string };\n return data.client_id;\n}\n\nasync function fetchWhoAmI(apiUrl: string, accessToken: string): Promise<WhoAmI> {\n const res = await fetch(`${apiUrl}/users/me`, {\n headers: { Authorization: `Bearer ${accessToken}` },\n });\n if (!res.ok) throw new Error(`Failed to resolve identity (${res.status})`);\n return (await res.json()) as WhoAmI;\n}\n\nexport async function fetchOrganizations(apiUrl: string, accessToken: string): Promise<OrgRef[]> {\n const res = await fetch(`${apiUrl}/organizations`, {\n headers: { Authorization: `Bearer ${accessToken}` },\n });\n if (!res.ok) throw new Error(`Failed to list organizations (${res.status})`);\n const rows = (await res.json()) as Array<{\n role: string;\n organization: { id: string; name: string; slug: string };\n }>;\n return rows.map((r) => ({\n id: r.organization.id,\n name: r.organization.name,\n slug: r.organization.slug,\n role: r.role,\n }));\n}\n\n/**\n * Wait for the browser to hit the loopback redirect and hand back `?code&state`.\n * Resolves with the authorization code once `state` is verified.\n */\nfunction waitForCallback(\n expectedState: string,\n): { server: ReturnType<typeof createServer>; port: Promise<number>; code: Promise<string> } {\n let resolveCode!: (code: string) => void;\n let rejectCode!: (err: Error) => void;\n const code = new Promise<string>((resolve, reject) => {\n resolveCode = resolve;\n rejectCode = reject;\n });\n\n const server = createServer((req, res) => {\n const url = new URL(req.url ?? \"/\", \"http://127.0.0.1\");\n if (url.pathname !== \"/callback\") {\n res.writeHead(404).end(\"Not found\");\n return;\n }\n const error = url.searchParams.get(\"error\");\n const returnedState = url.searchParams.get(\"state\");\n const returnedCode = url.searchParams.get(\"code\");\n\n const finish = (title: string, message: string) => {\n res.writeHead(200, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(\n `<!doctype html><html><head><title>${title}</title></head><body style=\"font-family:system-ui;padding:3rem;text-align:center\"><h2>${title}</h2><p>${message}</p><p>You can close this tab and return to your terminal.</p></body></html>`,\n );\n };\n\n if (error) {\n finish(\"Sign-in failed\", `The authorization server returned: ${error}`);\n rejectCode(new Error(`Authorization failed: ${error}`));\n return;\n }\n if (!returnedState || returnedState !== expectedState) {\n finish(\"Sign-in failed\", \"State mismatch — possible CSRF. Please try again.\");\n rejectCode(new Error(\"State mismatch in OAuth callback\"));\n return;\n }\n if (!returnedCode) {\n finish(\"Sign-in failed\", \"No authorization code was returned.\");\n rejectCode(new Error(\"Missing authorization code\"));\n return;\n }\n finish(\"Signed in to Sequel\", \"Authentication complete.\");\n resolveCode(returnedCode);\n });\n\n const port = new Promise<number>((resolve, reject) => {\n server.on(\"error\", reject);\n server.listen(0, \"127.0.0.1\", () => resolve((server.address() as AddressInfo).port));\n });\n\n return { server, port, code };\n}\n\nexport interface LoginResult {\n user: UserRef;\n org: OrgRef | undefined;\n organizationId: string;\n}\n\n/**\n * Run the full OAuth 2.0 + PKCE loopback flow: register a client, open the\n * browser to the consent page (where the user picks an org), capture the code,\n * exchange it for an org-bound token, then cache that token keyed by its org.\n *\n * Shared by `login` and `switch` (for orgs without a cached token).\n */\nexport async function runLoginFlow(options?: { silent?: boolean }): Promise<LoginResult> {\n const config = readConfig();\n const apiUrl = resolveApiUrl(config);\n\n const { verifier, challenge } = generatePkce();\n const state = base64url(randomBytes(16));\n\n const { server, port: portPromise, code: codePromise } = waitForCallback(state);\n const port = await portPromise;\n const redirectUri = `http://127.0.0.1:${port}/callback`;\n\n try {\n const clientId = await registerClient(apiUrl, redirectUri);\n\n const authorizeUrl = new URL(`${apiUrl}/oauth/authorize`);\n authorizeUrl.searchParams.set(\"client_id\", clientId);\n authorizeUrl.searchParams.set(\"redirect_uri\", redirectUri);\n authorizeUrl.searchParams.set(\"response_type\", \"code\");\n authorizeUrl.searchParams.set(\"code_challenge\", challenge);\n authorizeUrl.searchParams.set(\"code_challenge_method\", \"S256\");\n authorizeUrl.searchParams.set(\"state\", state);\n\n if (!options?.silent) {\n // open() can fail in headless envs — never block the flow on it.\n open(authorizeUrl.toString()).catch(() => {});\n }\n // Always surface the URL so the user can open it manually if needed.\n process.stderr.write(`\\nOpen this URL to continue:\\n${authorizeUrl.toString()}\\n\\n`);\n\n const code = await codePromise;\n\n const token = await postToken(apiUrl, {\n grant_type: \"authorization_code\",\n code,\n redirect_uri: redirectUri,\n client_id: clientId,\n code_verifier: verifier,\n });\n\n const me = await fetchWhoAmI(apiUrl, token.access_token);\n const orgs = await fetchOrganizations(apiUrl, token.access_token).catch(() => config.orgs ?? []);\n\n const next: AuthConfig = {\n ...config,\n version: 1,\n apiUrl,\n clientId,\n activeOrgId: me.organizationId,\n tokens: {\n ...config.tokens,\n [me.organizationId]: {\n accessToken: token.access_token,\n refreshToken: token.refresh_token,\n expiresAt: Date.now() + token.expires_in * 1000,\n },\n },\n user: { id: me.id, email: me.email, name: me.name },\n orgs,\n };\n writeConfig(next);\n\n return {\n user: next.user!,\n org: orgs.find((o) => o.id === me.organizationId),\n organizationId: me.organizationId,\n };\n } finally {\n server.close();\n }\n}\n\n/** True when there's a cached token for the active org (cheap, non-throwing). */\nexport function isLoggedIn(): boolean {\n const config = readConfig();\n const orgId = config.activeOrgId;\n return Boolean(orgId && config.tokens[orgId]);\n}\n\n/**\n * Return a valid access token for the active org, refreshing it in place when\n * expired. Throws a friendly error if there is no token or the refresh fails.\n */\nexport async function getValidAccessToken(): Promise<{ token: string; config: AuthConfig }> {\n const config = readConfig();\n const orgId = config.activeOrgId;\n if (!orgId || !config.tokens[orgId]) {\n throw new Error(\"Not logged in. Run `sequel login` first.\");\n }\n\n const entry: TokenEntry = config.tokens[orgId];\n if (entry.expiresAt - EXPIRY_SKEW_MS > Date.now()) {\n return { token: entry.accessToken, config };\n }\n\n // Access token expired — rotate via the refresh grant.\n const apiUrl = resolveApiUrl(config);\n try {\n const refreshed = await postToken(apiUrl, {\n grant_type: \"refresh_token\",\n refresh_token: entry.refreshToken,\n client_id: config.clientId ?? \"\",\n });\n config.tokens[orgId] = {\n accessToken: refreshed.access_token,\n refreshToken: refreshed.refresh_token,\n expiresAt: Date.now() + refreshed.expires_in * 1000,\n };\n writeConfig(config);\n return { token: refreshed.access_token, config };\n } catch {\n throw new Error(\n \"Your session for this organization has expired. Run `sequel login` (or `sequel switch`) to sign in again.\",\n );\n }\n}\n","import { getValidAccessToken } from \"./auth\";\nimport { resolveApiUrl } from \"./config\";\n\nexport class ApiError extends Error {\n constructor(\n public status: number,\n message: string,\n ) {\n super(message);\n this.name = \"ApiError\";\n }\n}\n\ninterface RequestOptions {\n method?: string;\n query?: Record<string, string | undefined>;\n body?: Record<string, unknown>;\n /**\n * How the active org id is attached to the request:\n * - \"query\" → ?organizationId=<org> (default; most GET/DELETE routes)\n * - \"organizationId\" → merged into the JSON body as organizationId\n * - \"organization_id\" → merged into the JSON body as organization_id (execute)\n * - \"none\" → not attached (e.g. /connectors, /oauth/*)\n */\n org?: \"query\" | \"organizationId\" | \"organization_id\" | \"none\";\n}\n\n/**\n * Authenticated request against the Sequel API using the active org's token.\n * Refreshes the token transparently and scopes the call to that org.\n */\nexport async function request<T = unknown>(path: string, options: RequestOptions = {}): Promise<T> {\n const { token, config } = await getValidAccessToken();\n const apiUrl = resolveApiUrl(config);\n const orgId = config.activeOrgId;\n const orgMode = options.org ?? \"query\";\n\n const url = new URL(`${apiUrl}${path}`);\n if (orgMode === \"query\" && orgId) url.searchParams.set(\"organizationId\", orgId);\n for (const [k, v] of Object.entries(options.query ?? {})) {\n if (v !== undefined) url.searchParams.set(k, v);\n }\n\n let bodyObj = options.body;\n if ((orgMode === \"organizationId\" || orgMode === \"organization_id\") && orgId) {\n bodyObj = { ...(bodyObj ?? {}), [orgMode]: orgId };\n }\n\n const headers: Record<string, string> = { Authorization: `Bearer ${token}` };\n let body: string | undefined;\n if (bodyObj !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n body = JSON.stringify(bodyObj);\n }\n\n const res = await fetch(url.toString(), { method: options.method ?? \"GET\", headers, body });\n\n if (!res.ok) {\n let message = `Request failed (${res.status})`;\n const text = await res.text().catch(() => \"\");\n try {\n const json = JSON.parse(text) as { error?: string };\n if (json.error) message = json.error;\n } catch {\n if (text) message = text;\n }\n throw new ApiError(res.status, message);\n }\n\n if (res.status === 204) return undefined as T;\n const text = await res.text();\n return (text ? JSON.parse(text) : undefined) as T;\n}\n\n/** The active organization id, or throws if not logged in. */\nexport async function activeOrgId(): Promise<string> {\n const { config } = await getValidAccessToken();\n if (!config.activeOrgId) throw new Error(\"No active organization. Run `sequel login`.\");\n return config.activeOrgId;\n}\n\n// ── Types ──────────────────────────────────────────────────────────────────────\n\nexport interface Connector {\n id: string;\n name: string;\n description: string;\n icon: string;\n appType: \"database\" | \"app\" | \"mcp\";\n live: boolean;\n authId: string;\n credentialsSchema?: Record<string, unknown>;\n userInputFields?: string[];\n canResolveName?: boolean;\n configuration?: { type: string } | null;\n}\n\nexport interface Connection {\n id: string;\n shortId: string;\n name: string;\n type: string;\n createdBy?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport type LinkCreateResponse =\n | { status: \"success\"; connection: Connection }\n | { status: \"pending\"; link_token: string; redirect_url: string; expires_at: string };\n\nexport interface LinkStatus {\n status: \"pending\" | \"oauth_in_progress\" | \"awaiting_configuration\" | \"success\" | \"failed\" | \"completed\";\n connectionId?: string;\n connection_id?: string;\n reason?: string;\n}\n\nexport interface ExecuteResult {\n data: Array<Record<string, unknown>>;\n columns: string[];\n row_count: number;\n truncated: boolean;\n}\n\nexport interface SearchToolRef {\n tool_id: string;\n input_schema: Record<string, unknown>;\n output_schema: Record<string, unknown> | null;\n relevant_tables: string[];\n}\n\nexport interface SearchResult {\n connection_id: string;\n connection_name: string;\n app_id: string;\n use_case: string;\n instructions: string;\n tools: SearchToolRef[];\n}\n\n// ── Endpoint wrappers ───────────────────────────────────────────────────────────\n\nexport function listConnectors(): Promise<Connector[]> {\n return request<Connector[]>(\"/connectors\", { org: \"none\" });\n}\n\nexport function listConnections(): Promise<Connection[]> {\n return request<Connection[]>(\"/connections\");\n}\n\nexport function getConnection(id: string): Promise<Connection> {\n return request<Connection>(`/connections/${id}`);\n}\n\nexport function deleteConnection(id: string): Promise<Connection> {\n return request<Connection>(`/connections/${id}`, { method: \"DELETE\" });\n}\n\nexport function testConnection(id: string): Promise<{ success: boolean; message: string }> {\n return request(`/connections/${id}/test`, { method: \"POST\", org: \"organizationId\" });\n}\n\nexport function getConnectionConfig(\n id: string,\n): Promise<{ schemaFilters: string[] | null; instructions: string | null }> {\n return request(`/connections/${id}/config`);\n}\n\n/** Mint a connect link / create a connection for the given connector. */\nexport function createLink(appId: string, body: Record<string, unknown>): Promise<LinkCreateResponse> {\n // POST /link/:appId resolves the org from the token's session, which always\n // matches the active org in the multi-token model — no org param needed.\n return request<LinkCreateResponse>(`/link/${appId}`, { method: \"POST\", org: \"none\", body });\n}\n\n/**\n * Poll a connect link's status. Uses the authenticated route, which (unlike the\n * public one) reports terminal states — `completed`/`failed` — so the CLI can\n * tell when the browser flow has finished.\n */\nexport function getLinkStatus(token: string): Promise<LinkStatus> {\n return request<LinkStatus>(`/link/${token}/status`, { org: \"none\" });\n}\n\nexport function execute(\n connectionId: string,\n tool: string,\n params: Record<string, unknown>,\n): Promise<ExecuteResult> {\n return request<ExecuteResult>(\"/execute\", {\n method: \"POST\",\n org: \"organization_id\",\n body: { connection_id: connectionId, tool, params },\n });\n}\n\nexport function search(useCase: string, connectionIds?: string[]): Promise<{ results: SearchResult[] }> {\n return request<{ results: SearchResult[] }>(\"/search\", {\n method: \"POST\",\n org: \"organization_id\",\n body: {\n action_info: `CLI search: ${useCase}`,\n use_case: useCase,\n connection_ids: connectionIds,\n },\n });\n}\n\nexport async function createApiKey(name: string): Promise<{ key: string; keyPrefix: string }> {\n const orgId = await activeOrgId();\n return request(`/organizations/${orgId}/api-keys`, { method: \"POST\", org: \"none\", body: { name } });\n}\n","import pc from \"picocolors\";\n\nexport { pc };\n\n/** True when the user passed a global --json flag (set by index.ts). */\nlet jsonMode = false;\nexport function setJsonMode(on: boolean): void {\n jsonMode = on;\n}\nexport function isJsonMode(): boolean {\n return jsonMode;\n}\n\nexport function printJson(data: unknown): void {\n process.stdout.write(`${JSON.stringify(data, null, 2)}\\n`);\n}\n\nfunction cell(value: unknown): string {\n if (value === null || value === undefined) return \"\";\n if (typeof value === \"object\") return JSON.stringify(value);\n return String(value);\n}\n\n/**\n * Render an array of records as an aligned text table. `columns` controls order\n * and which keys are shown; defaults to the union of keys in the first row.\n */\nexport function renderTable(rows: Array<Record<string, unknown>>, columns?: string[]): string {\n if (rows.length === 0) return pc.dim(\"(no rows)\");\n const cols = columns ?? Object.keys(rows[0]);\n const widths = cols.map((c) => Math.max(c.length, ...rows.map((r) => cell(r[c]).length)));\n\n const header = cols.map((c, i) => pc.bold(c.padEnd(widths[i]))).join(\" \");\n const sep = cols.map((_, i) => \"─\".repeat(widths[i])).join(\" \");\n const body = rows\n .map((r) => cols.map((c, i) => cell(r[c]).padEnd(widths[i])).join(\" \"))\n .join(\"\\n\");\n\n return `${header}\\n${pc.dim(sep)}\\n${body}`;\n}\n\nexport function printTable(rows: Array<Record<string, unknown>>, columns?: string[]): void {\n process.stdout.write(`${renderTable(rows, columns)}\\n`);\n}\n\nexport function success(message: string): void {\n process.stdout.write(`${pc.green(\"✓\")} ${message}\\n`);\n}\n\nexport function info(message: string): void {\n process.stdout.write(`${message}\\n`);\n}\n\nexport function fail(message: string): void {\n process.stderr.write(`${pc.red(\"✗\")} ${message}\\n`);\n}\n","import * as p from \"@clack/prompts\";\nimport { runLoginFlow } from \"../lib/auth\";\nimport { pc, success } from \"../lib/output\";\n\nexport async function loginCommand(): Promise<void> {\n p.intro(pc.cyan(\"Sign in to Sequel\"));\n p.log.info(\"Opening your browser to authorize…\");\n const res = await runLoginFlow();\n success(`Logged in as ${pc.bold(res.user.email)}${res.org ? ` · ${pc.bold(res.org.name)}` : \"\"}`);\n p.outro(\"You're all set. Try `sequel sources list` or `sequel connect`.\");\n}\n","import { clearConfig, isLoggedIn, readConfig } from \"../lib/config\";\nimport { info, success } from \"../lib/output\";\n\nexport async function logoutCommand(): Promise<void> {\n const config = readConfig();\n if (!isLoggedIn(config)) {\n info(\"You are not logged in.\");\n return;\n }\n clearConfig();\n success(\"Logged out. Cached credentials removed from ~/.sequel/auth.json.\");\n}\n","import * as p from \"@clack/prompts\";\nimport { fetchOrganizations, getValidAccessToken, runLoginFlow } from \"../lib/auth\";\nimport { isLoggedIn, readConfig, resolveApiUrl, writeConfig } from \"../lib/config\";\nimport { pc, success } from \"../lib/output\";\n\nexport async function switchCommand(): Promise<void> {\n const config = readConfig();\n if (!isLoggedIn(config)) {\n throw new Error(\"Not logged in. Run `sequel login` first.\");\n }\n\n // Refresh the membership list with the active org's token.\n let orgs = config.orgs ?? [];\n try {\n const { token } = await getValidAccessToken();\n orgs = await fetchOrganizations(resolveApiUrl(config), token);\n writeConfig({ ...readConfig(), orgs });\n } catch {\n // fall back to cached orgs\n }\n if (orgs.length === 0) throw new Error(\"No organizations available for this account.\");\n\n const selection = await p.select({\n message: \"Switch to organization\",\n options: orgs.map((o) => ({\n value: o.id,\n label: o.id === config.activeOrgId ? `${o.name} ${pc.dim(\"(current)\")}` : o.name,\n hint: config.tokens[o.id] ? o.role : \"sign-in required\",\n })),\n });\n if (p.isCancel(selection)) {\n p.cancel(\"Cancelled.\");\n return;\n }\n\n const orgId = selection as string;\n const org = orgs.find((o) => o.id === orgId);\n const fresh = readConfig();\n\n if (fresh.tokens[orgId]) {\n // Already authorized — instant, offline swap.\n writeConfig({ ...fresh, activeOrgId: orgId });\n success(`Switched to ${pc.bold(org?.name ?? orgId)}.`);\n return;\n }\n\n // No cached token for this org — sign in so the user can authorize it.\n p.log.info(`You haven't authorized ${pc.bold(org?.name ?? orgId)} yet — opening your browser…`);\n const res = await runLoginFlow();\n success(`Switched to ${pc.bold(res.org?.name ?? res.organizationId)}.`);\n}\n","import * as p from \"@clack/prompts\";\nimport open from \"open\";\nimport {\n type Connector,\n createLink,\n getLinkStatus,\n listConnectors,\n} from \"../lib/api\";\nimport { info, pc, success } from \"../lib/output\";\n\nconst SECRET_RE = /pass|secret|token|key|connection|credential/i;\n\nfunction fieldsFor(connector: Connector): string[] {\n if (connector.userInputFields?.length) return connector.userInputFields;\n const props = (connector.credentialsSchema as { properties?: Record<string, unknown> } | undefined)?.properties;\n return props ? Object.keys(props) : [];\n}\n\nfunction isOAuth(connector: Connector): boolean {\n return Boolean(connector.configuration) || /oauth/i.test(connector.authId);\n}\n\n/** Poll a pending connect link until it completes or fails (or times out). */\nasync function pollLink(token: string): Promise<{ ok: boolean; reason?: string }> {\n const deadline = Date.now() + 5 * 60_000;\n while (Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, 2000));\n let status;\n try {\n status = await getLinkStatus(token);\n } catch {\n continue; // transient — keep polling\n }\n if (status.status === \"failed\") return { ok: false, reason: status.reason };\n if (status.status === \"success\" || status.status === \"completed\") return { ok: true };\n }\n return { ok: false, reason: \"Timed out waiting for the browser to finish.\" };\n}\n\nexport async function connectCommand(source?: string): Promise<void> {\n const connectors = await listConnectors();\n\n let connector: Connector | undefined;\n if (source) {\n connector = connectors.find((c) => c.id === source);\n if (!connector) {\n throw new Error(\n `Unknown connector \"${source}\". Available: ${connectors.map((c) => c.id).join(\", \")}`,\n );\n }\n } else {\n const choice = await p.select({\n message: \"Which data source do you want to connect?\",\n options: connectors\n .slice()\n .sort((a, b) => a.appType.localeCompare(b.appType) || a.name.localeCompare(b.name))\n .map((c) => ({ value: c.id, label: c.name, hint: c.appType })),\n });\n if (p.isCancel(choice)) {\n p.cancel(\"Cancelled.\");\n return;\n }\n connector = connectors.find((c) => c.id === (choice as string))!;\n }\n\n p.intro(`Connect ${pc.bold(connector.name)}`);\n\n if (!isOAuth(connector)) {\n // Pre-auth connector: collect credential fields in the terminal.\n const fields = fieldsFor(connector);\n const credentials: Record<string, string> = {};\n for (const field of fields) {\n const secret = SECRET_RE.test(field);\n const value = await (secret ? p.password : p.text)({\n message: field,\n });\n if (p.isCancel(value)) {\n p.cancel(\"Cancelled.\");\n return;\n }\n credentials[field] = value as string;\n }\n const name = await p.text({ message: \"Name for this source (optional)\", placeholder: connector.name });\n if (p.isCancel(name)) {\n p.cancel(\"Cancelled.\");\n return;\n }\n\n const s = p.spinner();\n s.start(\"Validating credentials…\");\n const res = await createLink(connector.id, {\n credentials,\n ...(name ? { name } : {}),\n });\n if (res.status === \"success\") {\n s.stop(\"Connected.\");\n success(`Created source ${pc.bold(res.connection.name)} (${res.connection.shortId}).`);\n return;\n }\n // Fallback: server wants more input — finish in the browser.\n s.stop(\"Continue in your browser…\");\n open(res.redirect_url).catch(() => {});\n info(`Open: ${res.redirect_url}`);\n const result = await pollLink(res.link_token);\n if (result.ok) success(\"Connected.\");\n else throw new Error(result.reason ?? \"Connection failed.\");\n return;\n }\n\n // OAuth connector: mint a link and let the polished web flow handle consent\n // (and any pre-OAuth fields like a project id), then poll for completion.\n const res = await createLink(connector.id, {});\n if (res.status === \"success\") {\n success(`Created source ${pc.bold(res.connection.name)} (${res.connection.shortId}).`);\n return;\n }\n open(res.redirect_url).catch(() => {});\n info(`Complete authorization in your browser:\\n${res.redirect_url}`);\n const s = p.spinner();\n s.start(\"Waiting for you to finish in the browser…\");\n const result = await pollLink(res.link_token);\n if (result.ok) {\n s.stop(\"Connected.\");\n success(\"Source connected.\");\n } else {\n s.stop(\"Failed.\");\n throw new Error(result.reason ?? \"Connection failed.\");\n }\n}\n","import * as p from \"@clack/prompts\";\nimport {\n type Connection,\n deleteConnection,\n getConnection,\n getConnectionConfig,\n listConnections,\n testConnection,\n} from \"../lib/api\";\nimport { info, isJsonMode, pc, printJson, printTable, success } from \"../lib/output\";\n\n/** Resolve a user-supplied id (uuid or shortId) to the connection's real id. */\nasync function resolveConnection(idOrShort: string): Promise<Connection> {\n const all = await listConnections();\n const match = all.find((c) => c.id === idOrShort || c.shortId === idOrShort);\n if (!match) throw new Error(`No source found matching \"${idOrShort}\".`);\n return match;\n}\n\nasync function pickConnection(message: string): Promise<Connection | undefined> {\n const all = await listConnections();\n if (all.length === 0) {\n info(\"No sources connected yet. Run `sequel connect`.\");\n return undefined;\n }\n const choice = await p.select({\n message,\n options: all.map((c) => ({ value: c.shortId, label: `${c.name} (${c.shortId})`, hint: c.type })),\n });\n if (p.isCancel(choice)) return undefined;\n return all.find((c) => c.shortId === (choice as string));\n}\n\nfunction toRow(c: Connection): Record<string, unknown> {\n return { id: c.shortId, name: c.name, type: c.type, created: c.createdAt.slice(0, 10) };\n}\n\nexport async function sourcesList(): Promise<void> {\n const connections = await listConnections();\n if (isJsonMode()) return printJson(connections);\n if (connections.length === 0) return info(\"No sources connected yet. Run `sequel connect`.\");\n printTable(connections.map(toRow), [\"id\", \"name\", \"type\", \"created\"]);\n}\n\nexport async function sourcesActive(): Promise<void> {\n const connections = await listConnections();\n const rows = await Promise.all(\n connections.map(async (c) => {\n let status = \"unknown\";\n try {\n const t = await testConnection(c.id);\n status = t.success ? \"healthy\" : \"error\";\n } catch {\n status = \"error\";\n }\n return { ...toRow(c), status };\n }),\n );\n if (isJsonMode()) return printJson(rows);\n if (rows.length === 0) return info(\"No sources connected yet. Run `sequel connect`.\");\n printTable(rows, [\"id\", \"name\", \"type\", \"status\", \"created\"]);\n}\n\nexport async function sourcesInfo(idOrShort?: string): Promise<void> {\n const conn = idOrShort ? await resolveConnection(idOrShort) : await pickConnection(\"Source to inspect\");\n if (!conn) return;\n const full = await getConnection(conn.id);\n let config: { schemaFilters: string[] | null; instructions: string | null } | null = null;\n try {\n config = await getConnectionConfig(conn.id);\n } catch {\n /* config may be absent */\n }\n if (isJsonMode()) return printJson({ ...full, config });\n\n info(`${pc.bold(full.name)} ${pc.dim(full.shortId)}`);\n info(`type: ${full.type}`);\n info(`id: ${full.id}`);\n info(`created: ${full.createdAt}`);\n if (config?.schemaFilters?.length) info(`schemas: ${config.schemaFilters.join(\", \")}`);\n if (config?.instructions) info(`\\n${pc.dim(config.instructions)}`);\n}\n\nexport async function sourcesDelete(idOrShort?: string): Promise<void> {\n const conn = idOrShort ? await resolveConnection(idOrShort) : await pickConnection(\"Source to delete\");\n if (!conn) return;\n const confirmed = await p.confirm({ message: `Delete ${pc.bold(conn.name)} (${conn.shortId})? This cannot be undone.` });\n if (p.isCancel(confirmed) || !confirmed) {\n info(\"Cancelled.\");\n return;\n }\n await deleteConnection(conn.id);\n success(`Deleted ${conn.name} (${conn.shortId}).`);\n}\n","import { homedir, platform } from \"node:os\";\nimport { join } from \"node:path\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport YAML from \"yaml\";\n\nexport type Scope = \"global\" | \"local\";\n\nexport interface InstallOptions {\n apiUrl: string;\n apiKey: string;\n scope: Scope;\n /** Project root for local scope (defaults to cwd). Injectable for tests. */\n cwd?: string;\n /** Home dir override for tests. */\n home?: string;\n}\n\n/** What happened during install — either a file we wrote or a command to run. */\nexport type InstallResult =\n | { kind: \"file\"; path: string }\n | { kind: \"command\"; command: string; args: string[] };\n\nexport interface McpClientDef {\n slug: string;\n name: string;\n scopes: Scope[];\n /** Human-readable target (path or command) for a scope, for previews. */\n describe(opts: InstallOptions): string;\n install(opts: InstallOptions): InstallResult;\n}\n\nconst SERVER_NAME = \"sequel\";\nconst mcpUrl = (apiUrl: string) => `${apiUrl.replace(/\\/$/, \"\")}/mcp`;\nconst bearer = (apiKey: string) => `Bearer ${apiKey}`;\n\nfunction home(opts: InstallOptions): string {\n return opts.home ?? homedir();\n}\nfunction cwd(opts: InstallOptions): string {\n return opts.cwd ?? process.cwd();\n}\n\n/** OS-specific application-support dir for a vendor folder. */\nfunction appSupport(opts: InstallOptions, vendor: string): string {\n const h = home(opts);\n switch (platform()) {\n case \"darwin\":\n return join(h, \"Library\", \"Application Support\", vendor);\n case \"win32\":\n return join(process.env.APPDATA ?? join(h, \"AppData\", \"Roaming\"), vendor);\n default:\n return join(process.env.XDG_CONFIG_HOME ?? join(h, \".config\"), vendor);\n }\n}\n\n/** Read+merge+write a JSON config, preserving every other key already present. */\nfunction mergeJson(path: string, mutate: (cfg: Record<string, unknown>) => void): void {\n let cfg: Record<string, unknown> = {};\n if (existsSync(path)) {\n try {\n cfg = JSON.parse(readFileSync(path, \"utf8\")) as Record<string, unknown>;\n } catch {\n cfg = {};\n }\n }\n mutate(cfg);\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, `${JSON.stringify(cfg, null, 2)}\\n`);\n}\n\nfunction mergeYaml(path: string, mutate: (cfg: Record<string, unknown>) => void): void {\n let cfg: Record<string, unknown> = {};\n if (existsSync(path)) {\n try {\n cfg = (YAML.parse(readFileSync(path, \"utf8\")) as Record<string, unknown>) ?? {};\n } catch {\n cfg = {};\n }\n }\n mutate(cfg);\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, YAML.stringify(cfg));\n}\n\nfunction setNested(cfg: Record<string, unknown>, key: string, value: unknown): void {\n const obj = (cfg[key] as Record<string, unknown>) ?? {};\n obj[SERVER_NAME] = value;\n cfg[key] = obj;\n}\n\n// ── Client definitions ──────────────────────────────────────────────────────────\n\nexport const mcpClients: McpClientDef[] = [\n {\n slug: \"claude\",\n name: \"Claude Desktop\",\n scopes: [\"global\"],\n describe: (o) => join(appSupport(o, \"Claude\"), \"claude_desktop_config.json\"),\n install(o) {\n const path = join(appSupport(o, \"Claude\"), \"claude_desktop_config.json\");\n mergeJson(path, (cfg) =>\n setNested(cfg, \"mcpServers\", {\n url: mcpUrl(o.apiUrl),\n headers: { Authorization: bearer(o.apiKey) },\n }),\n );\n return { kind: \"file\", path };\n },\n },\n {\n slug: \"claude-code\",\n name: \"Claude Code\",\n scopes: [\"global\", \"local\"],\n describe: (o) =>\n `claude mcp add --scope ${o.scope === \"global\" ? \"user\" : \"local\"} --transport http ${SERVER_NAME} …`,\n install(o) {\n return {\n kind: \"command\",\n command: \"claude\",\n args: [\n \"mcp\",\n \"add\",\n \"--scope\",\n o.scope === \"global\" ? \"user\" : \"local\",\n \"--transport\",\n \"http\",\n SERVER_NAME,\n mcpUrl(o.apiUrl),\n \"--header\",\n `Authorization: ${bearer(o.apiKey)}`,\n ],\n };\n },\n },\n {\n slug: \"cursor\",\n name: \"Cursor\",\n scopes: [\"global\", \"local\"],\n describe: (o) => (o.scope === \"global\" ? join(home(o), \".cursor\", \"mcp.json\") : join(cwd(o), \".cursor\", \"mcp.json\")),\n install(o) {\n const path = o.scope === \"global\" ? join(home(o), \".cursor\", \"mcp.json\") : join(cwd(o), \".cursor\", \"mcp.json\");\n mergeJson(path, (cfg) =>\n setNested(cfg, \"mcpServers\", {\n url: mcpUrl(o.apiUrl),\n headers: { Authorization: bearer(o.apiKey) },\n }),\n );\n return { kind: \"file\", path };\n },\n },\n {\n slug: \"vscode\",\n name: \"VS Code\",\n scopes: [\"global\", \"local\"],\n describe: (o) =>\n o.scope === \"global\" ? join(appSupport(o, \"Code\"), \"User\", \"mcp.json\") : join(cwd(o), \".vscode\", \"mcp.json\"),\n install(o) {\n const path =\n o.scope === \"global\" ? join(appSupport(o, \"Code\"), \"User\", \"mcp.json\") : join(cwd(o), \".vscode\", \"mcp.json\");\n mergeJson(path, (cfg) =>\n setNested(cfg, \"servers\", {\n url: mcpUrl(o.apiUrl),\n type: \"http\",\n headers: { Authorization: bearer(o.apiKey) },\n }),\n );\n return { kind: \"file\", path };\n },\n },\n {\n slug: \"windsurf\",\n name: \"Windsurf\",\n scopes: [\"global\"],\n describe: (o) => join(home(o), \".codeium\", \"windsurf\", \"mcp_config.json\"),\n install(o) {\n const path = join(home(o), \".codeium\", \"windsurf\", \"mcp_config.json\");\n mergeJson(path, (cfg) =>\n setNested(cfg, \"mcpServers\", {\n // Windsurf uses `serverUrl`, not `url`.\n serverUrl: mcpUrl(o.apiUrl),\n headers: { Authorization: bearer(o.apiKey) },\n }),\n );\n return { kind: \"file\", path };\n },\n },\n {\n slug: \"zed\",\n name: \"Zed\",\n scopes: [\"global\", \"local\"],\n describe: (o) =>\n o.scope === \"global\" ? join(home(o), \".config\", \"zed\", \"settings.json\") : join(cwd(o), \".zed\", \"settings.json\"),\n install(o) {\n const path =\n o.scope === \"global\"\n ? join(home(o), \".config\", \"zed\", \"settings.json\")\n : join(cwd(o), \".zed\", \"settings.json\");\n mergeJson(path, (cfg) =>\n setNested(cfg, \"context_servers\", {\n url: mcpUrl(o.apiUrl),\n settings: { headers: { Authorization: bearer(o.apiKey) } },\n }),\n );\n return { kind: \"file\", path };\n },\n },\n {\n slug: \"codex\",\n name: \"Codex\",\n scopes: [\"global\"],\n describe: (o) => join(home(o), \".codex\", \"config.yaml\"),\n install(o) {\n const path = join(home(o), \".codex\", \"config.yaml\");\n mergeYaml(path, (cfg) =>\n setNested(cfg, \"mcp_servers\", {\n url: mcpUrl(o.apiUrl),\n headers: { Authorization: bearer(o.apiKey) },\n }),\n );\n return { kind: \"file\", path };\n },\n },\n];\n\nexport function getMcpClient(slug: string): McpClientDef | undefined {\n return mcpClients.find((c) => c.slug === slug);\n}\n","import { execFileSync } from \"node:child_process\";\nimport * as p from \"@clack/prompts\";\nimport { createApiKey } from \"../lib/api\";\nimport { isLoggedIn } from \"../lib/auth\";\nimport { readConfig, resolveApiUrl } from \"../lib/config\";\nimport { type Scope, getMcpClient, mcpClients } from \"../lib/mcp-clients\";\nimport { pc, success } from \"../lib/output\";\n\nexport async function installCommand(slugArg?: string): Promise<void> {\n p.intro(pc.cyan(\"Install the Sequel MCP server\"));\n\n if (!isLoggedIn()) {\n p.cancel(\"Not logged in. Run `sequel login` first.\");\n return;\n }\n\n let slug = slugArg;\n if (!slug) {\n const choice = await p.select({\n message: \"Which coding agent do you want to install Sequel into?\",\n options: mcpClients.map((c) => ({ value: c.slug, label: c.name })),\n });\n if (p.isCancel(choice)) return p.cancel(\"Cancelled.\");\n slug = choice as string;\n }\n\n const client = getMcpClient(slug);\n if (!client) throw new Error(`Unknown agent \"${slug}\". Options: ${mcpClients.map((c) => c.slug).join(\", \")}`);\n\n let scope: Scope = client.scopes[0];\n if (client.scopes.length > 1) {\n const choice = await p.select({\n message: \"Install scope\",\n options: [\n { value: \"global\", label: \"Global\", hint: \"available everywhere on this machine\" },\n { value: \"local\", label: \"Local\", hint: \"this project only\" },\n ].filter((o) => client.scopes.includes(o.value as Scope)),\n });\n if (p.isCancel(choice)) return p.cancel(\"Cancelled.\");\n scope = choice as Scope;\n }\n\n const config = readConfig();\n const apiUrl = resolveApiUrl(config);\n\n const s = p.spinner();\n s.start(\"Creating a Sequel API key for this agent…\");\n let key: string;\n try {\n ({ key } = await createApiKey(`Sequel CLI (${client.name})`));\n } catch (err) {\n s.stop(\"Failed to create API key.\");\n throw err;\n }\n s.stop(\"API key created.\");\n\n const result = client.install({ apiUrl, apiKey: key, scope });\n\n if (result.kind === \"command\") {\n // e.g. Claude Code: run `claude mcp add …`.\n try {\n execFileSync(result.command, result.args, { stdio: \"inherit\" });\n } catch {\n throw new Error(\n `Failed to run \\`${result.command}\\`. Make sure it's installed, or run manually:\\n${result.command} ${result.args.join(\" \")}`,\n );\n }\n success(`Installed Sequel into ${client.name} (${scope}).`);\n } else {\n success(`Installed Sequel into ${client.name}.`);\n p.log.info(`Config written to ${pc.dim(result.path)}`);\n }\n\n p.outro(`Restart ${client.name} and ask it to \"list my Sequel connections\" to verify.`);\n}\n","import { search } from \"../lib/api\";\nimport { info, isJsonMode, pc, printJson } from \"../lib/output\";\n\nexport async function searchCommand(useCase: string, opts: { connection?: string[] }): Promise<void> {\n const res = await search(useCase, opts.connection);\n if (isJsonMode()) return printJson(res);\n\n if (res.results.length === 0) {\n info(\"No matching tools found across your connected sources.\");\n return;\n }\n\n for (const r of res.results) {\n info(`\\n${pc.bold(r.connection_name)} ${pc.dim(`(${r.connection_id} · ${r.app_id})`)}`);\n if (r.instructions) info(pc.dim(r.instructions));\n for (const tool of r.tools) {\n info(` ${pc.cyan(tool.tool_id)}`);\n if (tool.relevant_tables?.length) info(` tables: ${tool.relevant_tables.join(\", \")}`);\n }\n info(pc.dim(` → sequel execute ${r.connection_id} ${r.tools[0]?.tool_id ?? \"<tool>\"} -d '{…}'`));\n }\n}\n","import { execute } from \"../lib/api\";\nimport { info, isJsonMode, pc, printJson, printTable } from \"../lib/output\";\n\nexport async function executeCommand(\n connectionId: string,\n tool: string,\n opts: { data?: string },\n): Promise<void> {\n let params: Record<string, unknown> = {};\n if (opts.data) {\n try {\n params = JSON.parse(opts.data) as Record<string, unknown>;\n } catch {\n throw new Error(\"Invalid JSON passed to -d/--data.\");\n }\n }\n\n const res = await execute(connectionId, tool, params);\n if (isJsonMode()) return printJson(res);\n\n if (res.data.length === 0) {\n info(pc.dim(\"(0 rows)\"));\n return;\n }\n printTable(res.data, res.columns.length ? res.columns : undefined);\n info(pc.dim(`\\n${res.row_count} row(s)${res.truncated ? \" (truncated)\" : \"\"}`));\n}\n","import { Command } from \"commander\";\nimport { ApiError } from \"./lib/api\";\nimport { fail, setJsonMode } from \"./lib/output\";\nimport { loginCommand } from \"./commands/login\";\nimport { logoutCommand } from \"./commands/logout\";\nimport { switchCommand } from \"./commands/switch\";\nimport { connectCommand } from \"./commands/connect\";\nimport { sourcesActive, sourcesDelete, sourcesInfo, sourcesList } from \"./commands/sources\";\nimport { installCommand } from \"./commands/install\";\nimport { searchCommand } from \"./commands/search\";\nimport { executeCommand } from \"./commands/execute\";\n\nconst program = new Command();\n\nprogram\n .name(\"sequel\")\n .description(\"Sequel CLI — connect data sources and run tools from your terminal\")\n .version(\"0.0.0\")\n .option(\"--json\", \"output machine-readable JSON\")\n .enablePositionalOptions();\n\n/** Wrap a command action with shared --json handling and error reporting. */\nfunction action<A extends unknown[]>(fn: (...args: A) => Promise<void>) {\n return async (...args: A) => {\n if (program.opts().json) setJsonMode(true);\n try {\n await fn(...args);\n } catch (err) {\n if (err instanceof ApiError && err.status === 401) {\n fail(\"Unauthorized. Run `sequel login` to sign in again.\");\n } else {\n fail(err instanceof Error ? err.message : String(err));\n }\n process.exitCode = 1;\n }\n };\n}\n\nprogram.command(\"login\").description(\"Sign in to Sequel\").action(action(loginCommand));\nprogram.command(\"logout\").description(\"Sign out and remove cached credentials\").action(action(logoutCommand));\nprogram.command(\"switch\").description(\"Switch the active organization\").action(action(switchCommand));\n\nprogram\n .command(\"connect\")\n .argument(\"[source]\", \"connector id (e.g. postgres); omit to choose interactively\")\n .description(\"Connect a new data source\")\n .action(action(connectCommand));\n\nconst sources = program.command(\"sources\").description(\"Manage connected data sources\");\nsources.command(\"list\", { isDefault: true }).description(\"List connected sources\").action(action(sourcesList));\nsources.command(\"active\").description(\"List sources with live health status\").action(action(sourcesActive));\nsources\n .command(\"info\")\n .argument(\"[id]\", \"source id or short id\")\n .description(\"Show details for a source\")\n .action(action(sourcesInfo));\nsources\n .command(\"delete\")\n .argument(\"[id]\", \"source id or short id\")\n .description(\"Delete a source\")\n .action(action(sourcesDelete));\n\nprogram\n .command(\"install\")\n .argument(\"[agent]\", \"coding agent slug (e.g. cursor, claude-code)\")\n .description(\"Install the Sequel MCP server into a coding agent\")\n .action(action(installCommand));\n\nprogram\n .command(\"search\")\n .argument(\"<usecase>\", \"what you want to do, e.g. \\\"monthly revenue\\\"\")\n .option(\"-c, --connection <id...>\", \"limit to specific connection short ids\")\n .description(\"Find the right tools for a use case across your sources\")\n .action(action((usecase: string, opts: { connection?: string[] }) => searchCommand(usecase, opts)));\n\nprogram\n .command(\"execute\")\n .argument(\"<connection_id>\", \"connection short id\")\n .argument(\"<tool>\", \"tool id, e.g. postgres.query\")\n .option(\"-d, --data <json>\", \"tool input as a JSON string\")\n .description(\"Execute a tool against a connection\")\n .action(action((connectionId: string, tool: string, opts: { data?: string }) => executeCommand(connectionId, tool, opts)));\n\nprogram.parseAsync(process.argv).catch((err) => {\n fail(err instanceof Error ? err.message : String(err));\n process.exit(1);\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAKA,MAAa,kBAAkB;;AA2C/B,SAAgB,YAAoB;AAClC,QAAO,QAAQ,IAAI,qBAAqB,KAAK,SAAS,EAAE,UAAU;AACnE;AAED,SAAgB,aAAqB;AACnC,QAAO,KAAK,WAAW,EAAE,YAAY;AACtC;;AAGD,SAAgB,cAAcA,QAAoC;AAChE,QAAO,QAAQ,IAAI,kBAAkB,QAAQ,UAAU;AACxD;AAED,SAAS,cAA0B;AACjC,QAAO;EAAE,SAAS;EAAG,QAAQ,eAAe;EAAE,QAAQ,CAAE;CAAE;AAC3D;;AAGD,SAAgB,aAAyB;CACvC,MAAM,OAAO,YAAY;AACzB,MAAK,WAAW,KAAK,CAAE,QAAO,aAAa;AAC3C,KAAI;EACF,MAAM,SAAS,KAAK,MAAM,aAAa,MAAM,OAAO,CAAC;AACrD,OAAK,iBAAiB,WAAW,aAAa,OAAO,OAAQ,QAAO,aAAa;AACjF,SAAO,WAAW,CAAE;AACpB,SAAO;CACR,QAAO;AAEN,SAAO,aAAa;CACrB;AACF;;AAGD,SAAgB,YAAYC,QAA0B;CACpD,MAAM,MAAM,WAAW;AACvB,WAAU,KAAK;EAAE,WAAW;EAAM,MAAM;CAAO,EAAC;CAChD,MAAM,OAAO,YAAY;AACzB,eAAc,OAAO,EAAE,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,IAAO,EAAC;AAE5E,WAAU,MAAM,IAAM;AACvB;;AAGD,SAAgB,cAAoB;CAClC,MAAM,OAAO,YAAY;AACzB,KAAI,WAAW,KAAK,CAAE,QAAO,KAAK;AACnC;AAED,SAAgBC,aAAWD,QAA6B;AACtD,QAAO,QAAQ,OAAO,eAAe,OAAO,OAAO,OAAO,aAAa;AACxE;;;;;ACnFD,MAAM,iBAAiB;AAEvB,SAAS,UAAUE,KAAqB;AACtC,QAAO,IAAI,SAAS,YAAY;AACjC;;AAGD,SAAgB,eAAwD;CACtE,MAAM,WAAW,UAAU,YAAY,GAAG,CAAC;CAC3C,MAAM,YAAY,UAAU,WAAW,SAAS,CAAC,OAAO,SAAS,CAAC,QAAQ,CAAC;AAC3E,QAAO;EAAE;EAAU;CAAW;AAC/B;;AAiBD,eAAe,UAAUC,QAAgBC,QAAwD;CAC/F,MAAM,MAAM,MAAM,OAAO,EAAE,OAAO,eAAe;EAC/C,QAAQ;EACR,SAAS,EAAE,gBAAgB,oCAAqC;EAChE,MAAM,IAAI,gBAAgB,QAAQ,UAAU;CAC7C,EAAC;AACF,MAAK,IAAI,IAAI;EACX,MAAM,OAAO,MAAM,IAAI,MAAM,CAAC,MAAM,MAAM,GAAG;AAC7C,QAAM,IAAI,OAAO,wBAAwB,IAAI,OAAO,KAAK,KAAK;CAC/D;AACD,QAAQ,MAAM,IAAI,MAAM;AACzB;;AAGD,eAAe,eAAeD,QAAgBE,aAAsC;CAClF,MAAM,MAAM,MAAM,OAAO,EAAE,OAAO,kBAAkB;EAClD,QAAQ;EACR,SAAS,EAAE,gBAAgB,mBAAoB;EAC/C,MAAM,KAAK,UAAU;GAAE,aAAa;GAAc,eAAe,CAAC,WAAY;EAAE,EAAC;CAClF,EAAC;AACF,MAAK,IAAI,IAAI;EACX,MAAM,OAAO,MAAM,IAAI,MAAM,CAAC,MAAM,MAAM,GAAG;AAC7C,QAAM,IAAI,OAAO,8BAA8B,IAAI,OAAO,KAAK,KAAK;CACrE;CACD,MAAM,OAAQ,MAAM,IAAI,MAAM;AAC9B,QAAO,KAAK;AACb;AAED,eAAe,YAAYF,QAAgBG,aAAsC;CAC/E,MAAM,MAAM,MAAM,OAAO,EAAE,OAAO,YAAY,EAC5C,SAAS,EAAE,gBAAgB,SAAS,YAAY,EAAG,EACpD,EAAC;AACF,MAAK,IAAI,GAAI,OAAM,IAAI,OAAO,8BAA8B,IAAI,OAAO;AACvE,QAAQ,MAAM,IAAI,MAAM;AACzB;AAED,eAAsB,mBAAmBH,QAAgBG,aAAwC;CAC/F,MAAM,MAAM,MAAM,OAAO,EAAE,OAAO,iBAAiB,EACjD,SAAS,EAAE,gBAAgB,SAAS,YAAY,EAAG,EACpD,EAAC;AACF,MAAK,IAAI,GAAI,OAAM,IAAI,OAAO,gCAAgC,IAAI,OAAO;CACzE,MAAM,OAAQ,MAAM,IAAI,MAAM;AAI9B,QAAO,KAAK,IAAI,CAAC,OAAO;EACtB,IAAI,EAAE,aAAa;EACnB,MAAM,EAAE,aAAa;EACrB,MAAM,EAAE,aAAa;EACrB,MAAM,EAAE;CACT,GAAE;AACJ;;;;;AAMD,SAAS,gBACPC,eAC2F;CAC3F,IAAIC;CACJ,IAAIC;CACJ,MAAM,OAAO,IAAI,QAAgB,CAAC,SAAS,WAAW;AACpD,gBAAc;AACd,eAAa;CACd;CAED,MAAM,SAAS,aAAa,CAAC,KAAK,QAAQ;EACxC,MAAM,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK;AACpC,MAAI,IAAI,aAAa,aAAa;AAChC,OAAI,UAAU,IAAI,CAAC,IAAI,YAAY;AACnC;EACD;EACD,MAAM,QAAQ,IAAI,aAAa,IAAI,QAAQ;EAC3C,MAAM,gBAAgB,IAAI,aAAa,IAAI,QAAQ;EACnD,MAAM,eAAe,IAAI,aAAa,IAAI,OAAO;EAEjD,MAAM,SAAS,CAACC,OAAeC,YAAoB;AACjD,OAAI,UAAU,KAAK,EAAE,gBAAgB,2BAA4B,EAAC;AAClE,OAAI,KACD,oCAAoC,MAAM,wFAAwF,MAAM,UAAU,QAAQ,8EAC5J;EACF;AAED,MAAI,OAAO;AACT,UAAO,mBAAmB,qCAAqC,MAAM,EAAE;AACvE,cAAW,IAAI,OAAO,wBAAwB,MAAM,GAAG;AACvD;EACD;AACD,OAAK,iBAAiB,kBAAkB,eAAe;AACrD,UAAO,kBAAkB,oDAAoD;AAC7E,cAAW,IAAI,MAAM,oCAAoC;AACzD;EACD;AACD,OAAK,cAAc;AACjB,UAAO,kBAAkB,sCAAsC;AAC/D,cAAW,IAAI,MAAM,8BAA8B;AACnD;EACD;AACD,SAAO,uBAAuB,2BAA2B;AACzD,cAAY,aAAa;CAC1B,EAAC;CAEF,MAAM,OAAO,IAAI,QAAgB,CAAC,SAAS,WAAW;AACpD,SAAO,GAAG,SAAS,OAAO;AAC1B,SAAO,OAAO,GAAG,aAAa,MAAM,QAAS,OAAO,SAAS,CAAiB,KAAK,CAAC;CACrF;AAED,QAAO;EAAE;EAAQ;EAAM;CAAM;AAC9B;;;;;;;;AAeD,eAAsB,aAAaC,SAAsD;CACvF,MAAM,SAAS,YAAY;CAC3B,MAAM,SAAS,cAAc,OAAO;CAEpC,MAAM,EAAE,UAAU,WAAW,GAAG,cAAc;CAC9C,MAAM,QAAQ,UAAU,YAAY,GAAG,CAAC;CAExC,MAAM,EAAE,QAAQ,MAAM,aAAa,MAAM,aAAa,GAAG,gBAAgB,MAAM;CAC/E,MAAM,OAAO,MAAM;CACnB,MAAM,eAAe,mBAAmB,KAAK;AAE7C,KAAI;EACF,MAAM,WAAW,MAAM,eAAe,QAAQ,YAAY;EAE1D,MAAM,eAAe,IAAI,KAAK,EAAE,OAAO;AACvC,eAAa,aAAa,IAAI,aAAa,SAAS;AACpD,eAAa,aAAa,IAAI,gBAAgB,YAAY;AAC1D,eAAa,aAAa,IAAI,iBAAiB,OAAO;AACtD,eAAa,aAAa,IAAI,kBAAkB,UAAU;AAC1D,eAAa,aAAa,IAAI,yBAAyB,OAAO;AAC9D,eAAa,aAAa,IAAI,SAAS,MAAM;AAE7C,OAAK,SAAS,OAEZ,MAAK,aAAa,UAAU,CAAC,CAAC,MAAM,MAAM,CAAE,EAAC;AAG/C,UAAQ,OAAO,OAAO,gCAAgC,aAAa,UAAU,CAAC,MAAM;EAEpF,MAAM,OAAO,MAAM;EAEnB,MAAM,QAAQ,MAAM,UAAU,QAAQ;GACpC,YAAY;GACZ;GACA,cAAc;GACd,WAAW;GACX,eAAe;EAChB,EAAC;EAEF,MAAM,KAAK,MAAM,YAAY,QAAQ,MAAM,aAAa;EACxD,MAAM,OAAO,MAAM,mBAAmB,QAAQ,MAAM,aAAa,CAAC,MAAM,MAAM,OAAO,QAAQ,CAAE,EAAC;EAEhG,MAAMC,OAAmB;GACvB,GAAG;GACH,SAAS;GACT;GACA;GACA,aAAa,GAAG;GAChB,QAAQ;IACN,GAAG,OAAO;KACT,GAAG,iBAAiB;KACnB,aAAa,MAAM;KACnB,cAAc,MAAM;KACpB,WAAW,KAAK,KAAK,GAAG,MAAM,aAAa;IAC5C;GACF;GACD,MAAM;IAAE,IAAI,GAAG;IAAI,OAAO,GAAG;IAAO,MAAM,GAAG;GAAM;GACnD;EACD;AACD,cAAY,KAAK;AAEjB,SAAO;GACL,MAAM,KAAK;GACX,KAAK,KAAK,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,eAAe;GACjD,gBAAgB,GAAG;EACpB;CACF,UAAS;AACR,SAAO,OAAO;CACf;AACF;;AAGD,SAAgB,aAAsB;CACpC,MAAM,SAAS,YAAY;CAC3B,MAAM,QAAQ,OAAO;AACrB,QAAO,QAAQ,SAAS,OAAO,OAAO,OAAO;AAC9C;;;;;AAMD,eAAsB,sBAAsE;CAC1F,MAAM,SAAS,YAAY;CAC3B,MAAM,QAAQ,OAAO;AACrB,MAAK,UAAU,OAAO,OAAO,OAC3B,OAAM,IAAI,MAAM;CAGlB,MAAMC,QAAoB,OAAO,OAAO;AACxC,KAAI,MAAM,YAAY,iBAAiB,KAAK,KAAK,CAC/C,QAAO;EAAE,OAAO,MAAM;EAAa;CAAQ;CAI7C,MAAM,SAAS,cAAc,OAAO;AACpC,KAAI;EACF,MAAM,YAAY,MAAM,UAAU,QAAQ;GACxC,YAAY;GACZ,eAAe,MAAM;GACrB,WAAW,OAAO,YAAY;EAC/B,EAAC;AACF,SAAO,OAAO,SAAS;GACrB,aAAa,UAAU;GACvB,cAAc,UAAU;GACxB,WAAW,KAAK,KAAK,GAAG,UAAU,aAAa;EAChD;AACD,cAAY,OAAO;AACnB,SAAO;GAAE,OAAO,UAAU;GAAc;EAAQ;CACjD,QAAO;AACN,QAAM,IAAI,MACR;CAEH;AACF;;;;ACtRD,IAAa,WAAb,cAA8B,MAAM;CAClC,YACSC,QACPC,SACA;AACA,QAAM,QAAQ;EA6MjB,KAhNU;AAIP,OAAK,OAAO;CACb;AACF;;;;;AAoBD,eAAsB,QAAqBC,MAAcC,UAA0B,CAAE,GAAc;CACjG,MAAM,EAAE,OAAO,QAAQ,GAAG,MAAM,qBAAqB;CACrD,MAAM,SAAS,cAAc,OAAO;CACpC,MAAM,QAAQ,OAAO;CACrB,MAAM,UAAU,QAAQ,OAAO;CAE/B,MAAM,MAAM,IAAI,KAAK,EAAE,OAAO,EAAE,KAAK;AACrC,KAAI,YAAY,WAAW,MAAO,KAAI,aAAa,IAAI,kBAAkB,MAAM;AAC/E,MAAK,MAAM,CAAC,GAAG,EAAE,IAAI,OAAO,QAAQ,QAAQ,SAAS,CAAE,EAAC,CACtD,KAAI,aAAiB,KAAI,aAAa,IAAI,GAAG,EAAE;CAGjD,IAAI,UAAU,QAAQ;AACtB,MAAK,YAAY,oBAAoB,YAAY,sBAAsB,MACrE,WAAU;EAAE,GAAI,WAAW,CAAE;GAAI,UAAU;CAAO;CAGpD,MAAMC,UAAkC,EAAE,gBAAgB,SAAS,MAAM,EAAG;CAC5E,IAAIC;AACJ,KAAI,oBAAuB;AACzB,UAAQ,kBAAkB;AAC1B,SAAO,KAAK,UAAU,QAAQ;CAC/B;CAED,MAAM,MAAM,MAAM,MAAM,IAAI,UAAU,EAAE;EAAE,QAAQ,QAAQ,UAAU;EAAO;EAAS;CAAM,EAAC;AAE3F,MAAK,IAAI,IAAI;EACX,IAAI,WAAW,kBAAkB,IAAI,OAAO;EAC5C,MAAMC,SAAO,MAAM,IAAI,MAAM,CAAC,MAAM,MAAM,GAAG;AAC7C,MAAI;GACF,MAAM,OAAO,KAAK,MAAMA,OAAK;AAC7B,OAAI,KAAK,MAAO,WAAU,KAAK;EAChC,QAAO;AACN,OAAIA,OAAM,WAAUA;EACrB;AACD,QAAM,IAAI,SAAS,IAAI,QAAQ;CAChC;AAED,KAAI,IAAI,WAAW,IAAK;CACxB,MAAM,OAAO,MAAM,IAAI,MAAM;AAC7B,QAAQ,OAAO,KAAK,MAAM,KAAK;AAChC;;AAGD,eAAsB,cAA+B;CACnD,MAAM,EAAE,QAAQ,GAAG,MAAM,qBAAqB;AAC9C,MAAK,OAAO,YAAa,OAAM,IAAI,MAAM;AACzC,QAAO,OAAO;AACf;AAgED,SAAgB,iBAAuC;AACrD,QAAO,QAAqB,eAAe,EAAE,KAAK,OAAQ,EAAC;AAC5D;AAED,SAAgB,kBAAyC;AACvD,QAAO,QAAsB,eAAe;AAC7C;AAED,SAAgB,cAAcC,IAAiC;AAC7D,QAAO,SAAqB,eAAe,GAAG,EAAE;AACjD;AAED,SAAgB,iBAAiBA,IAAiC;AAChE,QAAO,SAAqB,eAAe,GAAG,GAAG,EAAE,QAAQ,SAAU,EAAC;AACvE;AAED,SAAgB,eAAeA,IAA4D;AACzF,QAAO,SAAS,eAAe,GAAG,QAAQ;EAAE,QAAQ;EAAQ,KAAK;CAAkB,EAAC;AACrF;AAED,SAAgB,oBACdA,IAC0E;AAC1E,QAAO,SAAS,eAAe,GAAG,SAAS;AAC5C;;AAGD,SAAgB,WAAWC,OAAeC,MAA4D;AAGpG,QAAO,SAA6B,QAAQ,MAAM,GAAG;EAAE,QAAQ;EAAQ,KAAK;EAAQ;CAAM,EAAC;AAC5F;;;;;;AAOD,SAAgB,cAAcC,OAAoC;AAChE,QAAO,SAAqB,QAAQ,MAAM,UAAU,EAAE,KAAK,OAAQ,EAAC;AACrE;AAED,SAAgB,QACdC,cACAC,MACAC,QACwB;AACxB,QAAO,QAAuB,YAAY;EACxC,QAAQ;EACR,KAAK;EACL,MAAM;GAAE,eAAe;GAAc;GAAM;EAAQ;CACpD,EAAC;AACH;AAED,SAAgB,OAAOC,SAAiBC,eAAgE;AACtG,QAAO,QAAqC,WAAW;EACrD,QAAQ;EACR,KAAK;EACL,MAAM;GACJ,cAAc,cAAc,QAAQ;GACpC,UAAU;GACV,gBAAgB;EACjB;CACF,EAAC;AACH;AAED,eAAsB,aAAaC,MAA2D;CAC5F,MAAM,QAAQ,MAAM,aAAa;AACjC,QAAO,SAAS,iBAAiB,MAAM,YAAY;EAAE,QAAQ;EAAQ,KAAK;EAAQ,MAAM,EAAE,KAAM;CAAE,EAAC;AACpG;;;;;AC/MD,IAAI,WAAW;AACf,SAAgB,YAAYC,IAAmB;AAC7C,YAAW;AACZ;AACD,SAAgB,aAAsB;AACpC,QAAO;AACR;AAED,SAAgB,UAAUC,MAAqB;AAC7C,SAAQ,OAAO,OAAO,EAAE,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC,IAAI;AAC3D;AAED,SAAS,KAAKC,OAAwB;AACpC,KAAI,UAAU,QAAQ,iBAAqB,QAAO;AAClD,YAAW,UAAU,SAAU,QAAO,KAAK,UAAU,MAAM;AAC3D,QAAO,OAAO,MAAM;AACrB;;;;;AAMD,SAAgB,YAAYC,MAAsCC,SAA4B;AAC5F,KAAI,KAAK,WAAW,EAAG,QAAO,GAAG,IAAI,YAAY;CACjD,MAAM,OAAO,WAAW,OAAO,KAAK,KAAK,GAAG;CAC5C,MAAM,SAAS,KAAK,IAAI,CAAC,MAAM,KAAK,IAAI,EAAE,QAAQ,GAAG,KAAK,IAAI,CAAC,MAAM,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;CAEzF,MAAM,SAAS,KAAK,IAAI,CAAC,GAAG,MAAM,GAAG,KAAK,EAAE,OAAO,OAAO,GAAG,CAAC,CAAC,CAAC,KAAK,KAAK;CAC1E,MAAM,MAAM,KAAK,IAAI,CAAC,GAAG,MAAM,IAAI,OAAO,OAAO,GAAG,CAAC,CAAC,KAAK,KAAK;CAChE,MAAM,OAAO,KACV,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,GAAG,MAAM,KAAK,EAAE,GAAG,CAAC,OAAO,OAAO,GAAG,CAAC,CAAC,KAAK,KAAK,CAAC,CACvE,KAAK,KAAK;AAEb,SAAQ,EAAE,OAAO,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,KAAK;AAC3C;AAED,SAAgB,WAAWD,MAAsCC,SAA0B;AACzF,SAAQ,OAAO,OAAO,EAAE,YAAY,MAAM,QAAQ,CAAC,IAAI;AACxD;AAED,SAAgB,QAAQC,SAAuB;AAC7C,SAAQ,OAAO,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,GAAG,QAAQ,IAAI;AACtD;AAED,SAAgB,KAAKA,SAAuB;AAC1C,SAAQ,OAAO,OAAO,EAAE,QAAQ,IAAI;AACrC;AAED,SAAgB,KAAKA,SAAuB;AAC1C,SAAQ,OAAO,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,QAAQ,IAAI;AACpD;;;;ACnDD,eAAsB,eAA8B;AAClD,KAAE,MAAM,GAAG,KAAK,oBAAoB,CAAC;AACrC,KAAE,IAAI,KAAK,qCAAqC;CAChD,MAAM,MAAM,MAAM,cAAc;AAChC,UAAS,eAAe,GAAG,KAAK,IAAI,KAAK,MAAM,CAAC,EAAE,IAAI,OAAO,KAAK,GAAG,KAAK,IAAI,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE;AACjG,KAAE,MAAM,iEAAiE;AAC1E;;;;ACPD,eAAsB,gBAA+B;CACnD,MAAM,SAAS,YAAY;AAC3B,MAAK,aAAW,OAAO,EAAE;AACvB,OAAK,yBAAyB;AAC9B;CACD;AACD,cAAa;AACb,SAAQ,mEAAmE;AAC5E;;;;ACND,eAAsB,gBAA+B;CACnD,MAAM,SAAS,YAAY;AAC3B,MAAK,aAAW,OAAO,CACrB,OAAM,IAAI,MAAM;CAIlB,IAAI,OAAO,OAAO,QAAQ,CAAE;AAC5B,KAAI;EACF,MAAM,EAAE,OAAO,GAAG,MAAM,qBAAqB;AAC7C,SAAO,MAAM,mBAAmB,cAAc,OAAO,EAAE,MAAM;AAC7D,cAAY;GAAE,GAAG,YAAY;GAAE;EAAM,EAAC;CACvC,QAAO,CAEP;AACD,KAAI,KAAK,WAAW,EAAG,OAAM,IAAI,MAAM;CAEvC,MAAM,YAAY,MAAM,IAAE,OAAO;EAC/B,SAAS;EACT,SAAS,KAAK,IAAI,CAAC,OAAO;GACxB,OAAO,EAAE;GACT,OAAO,EAAE,OAAO,OAAO,eAAe,EAAE,EAAE,KAAK,GAAG,GAAG,IAAI,YAAY,CAAC,IAAI,EAAE;GAC5E,MAAM,OAAO,OAAO,EAAE,MAAM,EAAE,OAAO;EACtC,GAAE;CACJ,EAAC;AACF,KAAI,IAAE,SAAS,UAAU,EAAE;AACzB,MAAE,OAAO,aAAa;AACtB;CACD;CAED,MAAM,QAAQ;CACd,MAAM,MAAM,KAAK,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM;CAC5C,MAAM,QAAQ,YAAY;AAE1B,KAAI,MAAM,OAAO,QAAQ;AAEvB,cAAY;GAAE,GAAG;GAAO,aAAa;EAAO,EAAC;AAC7C,WAAS,cAAc,GAAG,KAAK,KAAK,QAAQ,MAAM,CAAC,GAAG;AACtD;CACD;AAGD,KAAE,IAAI,MAAM,yBAAyB,GAAG,KAAK,KAAK,QAAQ,MAAM,CAAC,8BAA8B;CAC/F,MAAM,MAAM,MAAM,cAAc;AAChC,UAAS,cAAc,GAAG,KAAK,IAAI,KAAK,QAAQ,IAAI,eAAe,CAAC,GAAG;AACxE;;;;ACxCD,MAAM,YAAY;AAElB,SAAS,UAAUC,WAAgC;AACjD,KAAI,UAAU,iBAAiB,OAAQ,QAAO,UAAU;CACxD,MAAM,QAAS,UAAU,mBAA4E;AACrG,QAAO,QAAQ,OAAO,KAAK,MAAM,GAAG,CAAE;AACvC;AAED,SAAS,QAAQA,WAA+B;AAC9C,QAAO,QAAQ,UAAU,cAAc,IAAI,SAAS,KAAK,UAAU,OAAO;AAC3E;;AAGD,eAAe,SAASC,OAA0D;CAChF,MAAM,WAAW,KAAK,KAAK,GAAG,IAAI;AAClC,QAAO,KAAK,KAAK,GAAG,UAAU;AAC5B,QAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,IAAK;EAC5C,IAAI;AACJ,MAAI;AACF,YAAS,MAAM,cAAc,MAAM;EACpC,QAAO;AACN;EACD;AACD,MAAI,OAAO,WAAW,SAAU,QAAO;GAAE,IAAI;GAAO,QAAQ,OAAO;EAAQ;AAC3E,MAAI,OAAO,WAAW,aAAa,OAAO,WAAW,YAAa,QAAO,EAAE,IAAI,KAAM;CACtF;AACD,QAAO;EAAE,IAAI;EAAO,QAAQ;CAAgD;AAC7E;AAED,eAAsB,eAAeC,QAAgC;CACnE,MAAM,aAAa,MAAM,gBAAgB;CAEzC,IAAIC;AACJ,KAAI,QAAQ;AACV,cAAY,WAAW,KAAK,CAAC,MAAM,EAAE,OAAO,OAAO;AACnD,OAAK,UACH,OAAM,IAAI,OACP,qBAAqB,OAAO,gBAAgB,WAAW,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,KAAK,CAAC;CAGzF,OAAM;EACL,MAAM,SAAS,MAAM,IAAE,OAAO;GAC5B,SAAS;GACT,SAAS,WACN,OAAO,CACP,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,cAAc,EAAE,QAAQ,IAAI,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC,CAClF,IAAI,CAAC,OAAO;IAAE,OAAO,EAAE;IAAI,OAAO,EAAE;IAAM,MAAM,EAAE;GAAS,GAAE;EACjE,EAAC;AACF,MAAI,IAAE,SAAS,OAAO,EAAE;AACtB,OAAE,OAAO,aAAa;AACtB;EACD;AACD,cAAY,WAAW,KAAK,CAAC,MAAM,EAAE,OAAQ,OAAkB;CAChE;AAED,KAAE,OAAO,UAAU,GAAG,KAAK,UAAU,KAAK,CAAC,EAAE;AAE7C,MAAK,QAAQ,UAAU,EAAE;EAEvB,MAAM,SAAS,UAAU,UAAU;EACnC,MAAMC,cAAsC,CAAE;AAC9C,OAAK,MAAM,SAAS,QAAQ;GAC1B,MAAM,SAAS,UAAU,KAAK,MAAM;GACpC,MAAM,QAAQ,MAAM,CAAC,SAASC,IAAE,WAAWA,IAAE,MAAM,EACjD,SAAS,MACV,EAAC;AACF,OAAI,IAAE,SAAS,MAAM,EAAE;AACrB,QAAE,OAAO,aAAa;AACtB;GACD;AACD,eAAY,SAAS;EACtB;EACD,MAAM,OAAO,MAAM,IAAE,KAAK;GAAE,SAAS;GAAmC,aAAa,UAAU;EAAM,EAAC;AACtG,MAAI,IAAE,SAAS,KAAK,EAAE;AACpB,OAAE,OAAO,aAAa;AACtB;EACD;EAED,MAAMC,MAAI,IAAE,SAAS;AACrB,MAAE,MAAM,0BAA0B;EAClC,MAAMC,QAAM,MAAM,WAAW,UAAU,IAAI;GACzC;GACA,GAAI,OAAO,EAAE,KAAM,IAAG,CAAE;EACzB,EAAC;AACF,MAAIA,MAAI,WAAW,WAAW;AAC5B,OAAE,KAAK,aAAa;AACpB,YAAS,iBAAiB,GAAG,KAAKA,MAAI,WAAW,KAAK,CAAC,IAAIA,MAAI,WAAW,QAAQ,IAAI;AACtF;EACD;AAED,MAAE,KAAK,4BAA4B;AACnC,OAAKA,MAAI,aAAa,CAAC,MAAM,MAAM,CAAE,EAAC;AACtC,QAAM,QAAQA,MAAI,aAAa,EAAE;EACjC,MAAMC,WAAS,MAAM,SAASD,MAAI,WAAW;AAC7C,MAAIC,SAAO,GAAI,SAAQ,aAAa;MAC/B,OAAM,IAAI,MAAMA,SAAO,UAAU;AACtC;CACD;CAID,MAAM,MAAM,MAAM,WAAW,UAAU,IAAI,CAAE,EAAC;AAC9C,KAAI,IAAI,WAAW,WAAW;AAC5B,WAAS,iBAAiB,GAAG,KAAK,IAAI,WAAW,KAAK,CAAC,IAAI,IAAI,WAAW,QAAQ,IAAI;AACtF;CACD;AACD,MAAK,IAAI,aAAa,CAAC,MAAM,MAAM,CAAE,EAAC;AACtC,OAAM,2CAA2C,IAAI,aAAa,EAAE;CACpE,MAAM,IAAI,IAAE,SAAS;AACrB,GAAE,MAAM,4CAA4C;CACpD,MAAM,SAAS,MAAM,SAAS,IAAI,WAAW;AAC7C,KAAI,OAAO,IAAI;AACb,IAAE,KAAK,aAAa;AACpB,UAAQ,oBAAoB;CAC7B,OAAM;AACL,IAAE,KAAK,UAAU;AACjB,QAAM,IAAI,MAAM,OAAO,UAAU;CAClC;AACF;;;;;ACpHD,eAAe,kBAAkBC,WAAwC;CACvE,MAAM,MAAM,MAAM,iBAAiB;CACnC,MAAM,QAAQ,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,aAAa,EAAE,YAAY,UAAU;AAC5E,MAAK,MAAO,OAAM,IAAI,OAAO,4BAA4B,UAAU;AACnE,QAAO;AACR;AAED,eAAe,eAAeC,SAAkD;CAC9E,MAAM,MAAM,MAAM,iBAAiB;AACnC,KAAI,IAAI,WAAW,GAAG;AACpB,OAAK,kDAAkD;AACvD;CACD;CACD,MAAM,SAAS,MAAM,IAAE,OAAO;EAC5B;EACA,SAAS,IAAI,IAAI,CAAC,OAAO;GAAE,OAAO,EAAE;GAAS,QAAQ,EAAE,EAAE,KAAK,IAAI,EAAE,QAAQ;GAAI,MAAM,EAAE;EAAM,GAAE;CACjG,EAAC;AACF,KAAI,IAAE,SAAS,OAAO,CAAE;AACxB,QAAO,IAAI,KAAK,CAAC,MAAM,EAAE,YAAa,OAAkB;AACzD;AAED,SAAS,MAAMC,GAAwC;AACrD,QAAO;EAAE,IAAI,EAAE;EAAS,MAAM,EAAE;EAAM,MAAM,EAAE;EAAM,SAAS,EAAE,UAAU,MAAM,GAAG,GAAG;CAAE;AACxF;AAED,eAAsB,cAA6B;CACjD,MAAM,cAAc,MAAM,iBAAiB;AAC3C,KAAI,YAAY,CAAE,QAAO,UAAU,YAAY;AAC/C,KAAI,YAAY,WAAW,EAAG,QAAO,KAAK,kDAAkD;AAC5F,YAAW,YAAY,IAAI,MAAM,EAAE;EAAC;EAAM;EAAQ;EAAQ;CAAU,EAAC;AACtE;AAED,eAAsB,gBAA+B;CACnD,MAAM,cAAc,MAAM,iBAAiB;CAC3C,MAAM,OAAO,MAAM,QAAQ,IACzB,YAAY,IAAI,OAAO,MAAM;EAC3B,IAAI,SAAS;AACb,MAAI;GACF,MAAM,IAAI,MAAM,eAAe,EAAE,GAAG;AACpC,YAAS,EAAE,UAAU,YAAY;EAClC,QAAO;AACN,YAAS;EACV;AACD,SAAO;GAAE,GAAG,MAAM,EAAE;GAAE;EAAQ;CAC/B,EAAC,CACH;AACD,KAAI,YAAY,CAAE,QAAO,UAAU,KAAK;AACxC,KAAI,KAAK,WAAW,EAAG,QAAO,KAAK,kDAAkD;AACrF,YAAW,MAAM;EAAC;EAAM;EAAQ;EAAQ;EAAU;CAAU,EAAC;AAC9D;AAED,eAAsB,YAAYC,WAAmC;CACnE,MAAM,OAAO,YAAY,MAAM,kBAAkB,UAAU,GAAG,MAAM,eAAe,oBAAoB;AACvG,MAAK,KAAM;CACX,MAAM,OAAO,MAAM,cAAc,KAAK,GAAG;CACzC,IAAIC,SAAiF;AACrF,KAAI;AACF,WAAS,MAAM,oBAAoB,KAAK,GAAG;CAC5C,QAAO,CAEP;AACD,KAAI,YAAY,CAAE,QAAO,UAAU;EAAE,GAAG;EAAM;CAAQ,EAAC;AAEvD,OAAM,EAAE,GAAG,KAAK,KAAK,KAAK,CAAC,IAAI,GAAG,IAAI,KAAK,QAAQ,CAAC,EAAE;AACtD,OAAM,WAAW,KAAK,KAAK,EAAE;AAC7B,OAAM,WAAW,KAAK,GAAG,EAAE;AAC3B,OAAM,WAAW,KAAK,UAAU,EAAE;AAClC,KAAI,QAAQ,eAAe,OAAQ,OAAM,WAAW,OAAO,cAAc,KAAK,KAAK,CAAC,EAAE;AACtF,KAAI,QAAQ,aAAc,OAAM,IAAI,GAAG,IAAI,OAAO,aAAa,CAAC,EAAE;AACnE;AAED,eAAsB,cAAcD,WAAmC;CACrE,MAAM,OAAO,YAAY,MAAM,kBAAkB,UAAU,GAAG,MAAM,eAAe,mBAAmB;AACtG,MAAK,KAAM;CACX,MAAM,YAAY,MAAM,IAAE,QAAQ,EAAE,UAAU,SAAS,GAAG,KAAK,KAAK,KAAK,CAAC,IAAI,KAAK,QAAQ,2BAA4B,EAAC;AACxH,KAAI,IAAE,SAAS,UAAU,KAAK,WAAW;AACvC,OAAK,aAAa;AAClB;CACD;AACD,OAAM,iBAAiB,KAAK,GAAG;AAC/B,UAAS,UAAU,KAAK,KAAK,IAAI,KAAK,QAAQ,IAAI;AACnD;;;;AC7DD,MAAM,cAAc;AACpB,MAAM,SAAS,CAACE,YAAoB,EAAE,OAAO,QAAQ,OAAO,GAAG,CAAC;AAChE,MAAM,SAAS,CAACC,YAAoB,SAAS,OAAO;AAEpD,SAAS,KAAKC,MAA8B;AAC1C,QAAO,KAAK,QAAQ,SAAS;AAC9B;AACD,SAAS,IAAIA,MAA8B;AACzC,QAAO,KAAK,OAAO,QAAQ,KAAK;AACjC;;AAGD,SAAS,WAAWA,MAAsBC,QAAwB;CAChE,MAAM,IAAI,KAAK,KAAK;AACpB,SAAQ,UAAU,EAAlB;EACE,KAAK,SACH,QAAO,KAAK,GAAG,WAAW,uBAAuB,OAAO;EAC1D,KAAK,QACH,QAAO,KAAK,QAAQ,IAAI,WAAW,KAAK,GAAG,WAAW,UAAU,EAAE,OAAO;EAC3E,QACE,QAAO,KAAK,QAAQ,IAAI,mBAAmB,KAAK,GAAG,UAAU,EAAE,OAAO;CACzE;AACF;;AAGD,SAAS,UAAUC,MAAcC,QAAsD;CACrF,IAAIC,MAA+B,CAAE;AACrC,KAAI,WAAW,KAAK,CAClB,KAAI;AACF,QAAM,KAAK,MAAM,aAAa,MAAM,OAAO,CAAC;CAC7C,QAAO;AACN,QAAM,CAAE;CACT;AAEH,QAAO,IAAI;AACX,WAAU,QAAQ,KAAK,EAAE,EAAE,WAAW,KAAM,EAAC;AAC7C,eAAc,OAAO,EAAE,KAAK,UAAU,KAAK,MAAM,EAAE,CAAC,IAAI;AACzD;AAED,SAAS,UAAUF,MAAcC,QAAsD;CACrF,IAAIC,MAA+B,CAAE;AACrC,KAAI,WAAW,KAAK,CAClB,KAAI;AACF,QAAO,KAAK,MAAM,aAAa,MAAM,OAAO,CAAC,IAAgC,CAAE;CAChF,QAAO;AACN,QAAM,CAAE;CACT;AAEH,QAAO,IAAI;AACX,WAAU,QAAQ,KAAK,EAAE,EAAE,WAAW,KAAM,EAAC;AAC7C,eAAc,MAAM,KAAK,UAAU,IAAI,CAAC;AACzC;AAED,SAAS,UAAUA,KAA8BC,KAAaC,OAAsB;CAClF,MAAM,MAAO,IAAI,QAAoC,CAAE;AACvD,KAAI,eAAe;AACnB,KAAI,OAAO;AACZ;AAID,MAAaC,aAA6B;CACxC;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAC,QAAS;EAClB,UAAU,CAAC,MAAM,KAAK,WAAW,GAAG,SAAS,EAAE,6BAA6B;EAC5E,QAAQ,GAAG;GACT,MAAM,OAAO,KAAK,WAAW,GAAG,SAAS,EAAE,6BAA6B;AACxE,aAAU,MAAM,CAAC,QACf,UAAU,KAAK,cAAc;IAC3B,KAAK,OAAO,EAAE,OAAO;IACrB,SAAS,EAAE,eAAe,OAAO,EAAE,OAAO,CAAE;GAC7C,EAAC,CACH;AACD,UAAO;IAAE,MAAM;IAAQ;GAAM;EAC9B;CACF;CACD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAC,UAAU,OAAQ;EAC3B,UAAU,CAAC,OACR,yBAAyB,EAAE,UAAU,WAAW,SAAS,QAAQ,oBAAoB,YAAY;EACpG,QAAQ,GAAG;AACT,UAAO;IACL,MAAM;IACN,SAAS;IACT,MAAM;KACJ;KACA;KACA;KACA,EAAE,UAAU,WAAW,SAAS;KAChC;KACA;KACA;KACA,OAAO,EAAE,OAAO;KAChB;MACC,iBAAiB,OAAO,EAAE,OAAO,CAAC;IACpC;GACF;EACF;CACF;CACD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAC,UAAU,OAAQ;EAC3B,UAAU,CAAC,MAAO,EAAE,UAAU,WAAW,KAAK,KAAK,EAAE,EAAE,WAAW,WAAW,GAAG,KAAK,IAAI,EAAE,EAAE,WAAW,WAAW;EACnH,QAAQ,GAAG;GACT,MAAM,OAAO,EAAE,UAAU,WAAW,KAAK,KAAK,EAAE,EAAE,WAAW,WAAW,GAAG,KAAK,IAAI,EAAE,EAAE,WAAW,WAAW;AAC9G,aAAU,MAAM,CAAC,QACf,UAAU,KAAK,cAAc;IAC3B,KAAK,OAAO,EAAE,OAAO;IACrB,SAAS,EAAE,eAAe,OAAO,EAAE,OAAO,CAAE;GAC7C,EAAC,CACH;AACD,UAAO;IAAE,MAAM;IAAQ;GAAM;EAC9B;CACF;CACD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAC,UAAU,OAAQ;EAC3B,UAAU,CAAC,MACT,EAAE,UAAU,WAAW,KAAK,WAAW,GAAG,OAAO,EAAE,QAAQ,WAAW,GAAG,KAAK,IAAI,EAAE,EAAE,WAAW,WAAW;EAC9G,QAAQ,GAAG;GACT,MAAM,OACJ,EAAE,UAAU,WAAW,KAAK,WAAW,GAAG,OAAO,EAAE,QAAQ,WAAW,GAAG,KAAK,IAAI,EAAE,EAAE,WAAW,WAAW;AAC9G,aAAU,MAAM,CAAC,QACf,UAAU,KAAK,WAAW;IACxB,KAAK,OAAO,EAAE,OAAO;IACrB,MAAM;IACN,SAAS,EAAE,eAAe,OAAO,EAAE,OAAO,CAAE;GAC7C,EAAC,CACH;AACD,UAAO;IAAE,MAAM;IAAQ;GAAM;EAC9B;CACF;CACD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAC,QAAS;EAClB,UAAU,CAAC,MAAM,KAAK,KAAK,EAAE,EAAE,YAAY,YAAY,kBAAkB;EACzE,QAAQ,GAAG;GACT,MAAM,OAAO,KAAK,KAAK,EAAE,EAAE,YAAY,YAAY,kBAAkB;AACrE,aAAU,MAAM,CAAC,QACf,UAAU,KAAK,cAAc;IAE3B,WAAW,OAAO,EAAE,OAAO;IAC3B,SAAS,EAAE,eAAe,OAAO,EAAE,OAAO,CAAE;GAC7C,EAAC,CACH;AACD,UAAO;IAAE,MAAM;IAAQ;GAAM;EAC9B;CACF;CACD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAC,UAAU,OAAQ;EAC3B,UAAU,CAAC,MACT,EAAE,UAAU,WAAW,KAAK,KAAK,EAAE,EAAE,WAAW,OAAO,gBAAgB,GAAG,KAAK,IAAI,EAAE,EAAE,QAAQ,gBAAgB;EACjH,QAAQ,GAAG;GACT,MAAM,OACJ,EAAE,UAAU,WACR,KAAK,KAAK,EAAE,EAAE,WAAW,OAAO,gBAAgB,GAChD,KAAK,IAAI,EAAE,EAAE,QAAQ,gBAAgB;AAC3C,aAAU,MAAM,CAAC,QACf,UAAU,KAAK,mBAAmB;IAChC,KAAK,OAAO,EAAE,OAAO;IACrB,UAAU,EAAE,SAAS,EAAE,eAAe,OAAO,EAAE,OAAO,CAAE,EAAE;GAC3D,EAAC,CACH;AACD,UAAO;IAAE,MAAM;IAAQ;GAAM;EAC9B;CACF;CACD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAC,QAAS;EAClB,UAAU,CAAC,MAAM,KAAK,KAAK,EAAE,EAAE,UAAU,cAAc;EACvD,QAAQ,GAAG;GACT,MAAM,OAAO,KAAK,KAAK,EAAE,EAAE,UAAU,cAAc;AACnD,aAAU,MAAM,CAAC,QACf,UAAU,KAAK,eAAe;IAC5B,KAAK,OAAO,EAAE,OAAO;IACrB,SAAS,EAAE,eAAe,OAAO,EAAE,OAAO,CAAE;GAC7C,EAAC,CACH;AACD,UAAO;IAAE,MAAM;IAAQ;GAAM;EAC9B;CACF;AACF;AAED,SAAgB,aAAaC,MAAwC;AACnE,QAAO,WAAW,KAAK,CAAC,MAAM,EAAE,SAAS,KAAK;AAC/C;;;;AC3ND,eAAsB,eAAeC,SAAiC;AACpE,GAAE,MAAM,GAAG,KAAK,gCAAgC,CAAC;AAEjD,MAAK,YAAY,EAAE;AACjB,IAAE,OAAO,2CAA2C;AACpD;CACD;CAED,IAAI,OAAO;AACX,MAAK,MAAM;EACT,MAAM,SAAS,MAAM,EAAE,OAAO;GAC5B,SAAS;GACT,SAAS,WAAW,IAAI,CAAC,OAAO;IAAE,OAAO,EAAE;IAAM,OAAO,EAAE;GAAM,GAAE;EACnE,EAAC;AACF,MAAI,EAAE,SAAS,OAAO,CAAE,QAAO,EAAE,OAAO,aAAa;AACrD,SAAO;CACR;CAED,MAAM,SAAS,aAAa,KAAK;AACjC,MAAK,OAAQ,OAAM,IAAI,OAAO,iBAAiB,KAAK,cAAc,WAAW,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,KAAK,CAAC;CAE3G,IAAIC,QAAe,OAAO,OAAO;AACjC,KAAI,OAAO,OAAO,SAAS,GAAG;EAC5B,MAAM,SAAS,MAAM,EAAE,OAAO;GAC5B,SAAS;GACT,SAAS,CACP;IAAE,OAAO;IAAU,OAAO;IAAU,MAAM;GAAwC,GAClF;IAAE,OAAO;IAAS,OAAO;IAAS,MAAM;GAAqB,CAC9D,EAAC,OAAO,CAAC,MAAM,OAAO,OAAO,SAAS,EAAE,MAAe,CAAC;EAC1D,EAAC;AACF,MAAI,EAAE,SAAS,OAAO,CAAE,QAAO,EAAE,OAAO,aAAa;AACrD,UAAQ;CACT;CAED,MAAM,SAAS,YAAY;CAC3B,MAAM,SAAS,cAAc,OAAO;CAEpC,MAAM,IAAI,EAAE,SAAS;AACrB,GAAE,MAAM,4CAA4C;CACpD,IAAIC;AACJ,KAAI;AACF,GAAC,CAAE,IAAK,GAAG,MAAM,cAAc,cAAc,OAAO,KAAK,GAAG;CAC7D,SAAQ,KAAK;AACZ,IAAE,KAAK,4BAA4B;AACnC,QAAM;CACP;AACD,GAAE,KAAK,mBAAmB;CAE1B,MAAM,SAAS,OAAO,QAAQ;EAAE;EAAQ,QAAQ;EAAK;CAAO,EAAC;AAE7D,KAAI,OAAO,SAAS,WAAW;AAE7B,MAAI;AACF,gBAAa,OAAO,SAAS,OAAO,MAAM,EAAE,OAAO,UAAW,EAAC;EAChE,QAAO;AACN,SAAM,IAAI,OACP,kBAAkB,OAAO,QAAQ,kDAAkD,OAAO,QAAQ,GAAG,OAAO,KAAK,KAAK,IAAI,CAAC;EAE/H;AACD,WAAS,wBAAwB,OAAO,KAAK,IAAI,MAAM,IAAI;CAC5D,OAAM;AACL,WAAS,wBAAwB,OAAO,KAAK,GAAG;AAChD,IAAE,IAAI,MAAM,oBAAoB,GAAG,IAAI,OAAO,KAAK,CAAC,EAAE;CACvD;AAED,GAAE,OAAO,UAAU,OAAO,KAAK,wDAAwD;AACxF;;;;ACvED,eAAsB,cAAcC,SAAiBC,MAAgD;CACnG,MAAM,MAAM,MAAM,OAAO,SAAS,KAAK,WAAW;AAClD,KAAI,YAAY,CAAE,QAAO,UAAU,IAAI;AAEvC,KAAI,IAAI,QAAQ,WAAW,GAAG;AAC5B,OAAK,yDAAyD;AAC9D;CACD;AAED,MAAK,MAAM,KAAK,IAAI,SAAS;AAC3B,QAAM,IAAI,GAAG,KAAK,EAAE,gBAAgB,CAAC,GAAG,GAAG,KAAK,GAAG,EAAE,cAAc,KAAK,EAAE,OAAO,GAAG,CAAC,EAAE;AACvF,MAAI,EAAE,aAAc,MAAK,GAAG,IAAI,EAAE,aAAa,CAAC;AAChD,OAAK,MAAM,QAAQ,EAAE,OAAO;AAC1B,SAAM,IAAI,GAAG,KAAK,KAAK,QAAQ,CAAC,EAAE;AAClC,OAAI,KAAK,iBAAiB,OAAQ,OAAM,cAAc,KAAK,gBAAgB,KAAK,KAAK,CAAC,EAAE;EACzF;AACD,OAAK,GAAG,KAAK,qBAAqB,EAAE,cAAc,GAAG,EAAE,MAAM,IAAI,WAAW,SAAS,WAAW,CAAC;CAClG;AACF;;;;AClBD,eAAsB,eACpBC,cACAC,MACAC,MACe;CACf,IAAIC,SAAkC,CAAE;AACxC,KAAI,KAAK,KACP,KAAI;AACF,WAAS,KAAK,MAAM,KAAK,KAAK;CAC/B,QAAO;AACN,QAAM,IAAI,MAAM;CACjB;CAGH,MAAM,MAAM,MAAM,QAAQ,cAAc,MAAM,OAAO;AACrD,KAAI,YAAY,CAAE,QAAO,UAAU,IAAI;AAEvC,KAAI,IAAI,KAAK,WAAW,GAAG;AACzB,OAAK,GAAG,IAAI,WAAW,CAAC;AACxB;CACD;AACD,YAAW,IAAI,MAAM,IAAI,QAAQ,SAAS,IAAI,iBAAoB;AAClE,MAAK,GAAG,KAAK,IAAI,IAAI,UAAU,SAAS,IAAI,YAAY,iBAAiB,GAAG,EAAE,CAAC;AAChF;;;;ACdD,MAAM,UAAU,IAAI;AAEpB,QACG,KAAK,SAAS,CACd,YAAY,qEAAqE,CACjF,QAAQ,QAAQ,CAChB,OAAO,UAAU,+BAA+B,CAChD,yBAAyB;;AAG5B,SAAS,OAA4BC,IAAmC;AACtE,QAAO,OAAO,GAAG,SAAY;AAC3B,MAAI,QAAQ,MAAM,CAAC,KAAM,aAAY,KAAK;AAC1C,MAAI;AACF,SAAM,GAAG,GAAG,KAAK;EAClB,SAAQ,KAAK;AACZ,OAAI,eAAe,YAAY,IAAI,WAAW,IAC5C,MAAK,qDAAqD;OAE1D,MAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAExD,WAAQ,WAAW;EACpB;CACF;AACF;AAED,QAAQ,QAAQ,QAAQ,CAAC,YAAY,oBAAoB,CAAC,OAAO,OAAO,aAAa,CAAC;AACtF,QAAQ,QAAQ,SAAS,CAAC,YAAY,yCAAyC,CAAC,OAAO,OAAO,cAAc,CAAC;AAC7G,QAAQ,QAAQ,SAAS,CAAC,YAAY,iCAAiC,CAAC,OAAO,OAAO,cAAc,CAAC;AAErG,QACG,QAAQ,UAAU,CAClB,SAAS,YAAY,6DAA6D,CAClF,YAAY,4BAA4B,CACxC,OAAO,OAAO,eAAe,CAAC;AAEjC,MAAM,UAAU,QAAQ,QAAQ,UAAU,CAAC,YAAY,gCAAgC;AACvF,QAAQ,QAAQ,QAAQ,EAAE,WAAW,KAAM,EAAC,CAAC,YAAY,yBAAyB,CAAC,OAAO,OAAO,YAAY,CAAC;AAC9G,QAAQ,QAAQ,SAAS,CAAC,YAAY,uCAAuC,CAAC,OAAO,OAAO,cAAc,CAAC;AAC3G,QACG,QAAQ,OAAO,CACf,SAAS,QAAQ,wBAAwB,CACzC,YAAY,4BAA4B,CACxC,OAAO,OAAO,YAAY,CAAC;AAC9B,QACG,QAAQ,SAAS,CACjB,SAAS,QAAQ,wBAAwB,CACzC,YAAY,kBAAkB,CAC9B,OAAO,OAAO,cAAc,CAAC;AAEhC,QACG,QAAQ,UAAU,CAClB,SAAS,WAAW,+CAA+C,CACnE,YAAY,oDAAoD,CAChE,OAAO,OAAO,eAAe,CAAC;AAEjC,QACG,QAAQ,SAAS,CACjB,SAAS,aAAa,gDAAgD,CACtE,OAAO,4BAA4B,yCAAyC,CAC5E,YAAY,0DAA0D,CACtE,OAAO,OAAO,CAACC,SAAiBC,SAAoC,cAAc,SAAS,KAAK,CAAC,CAAC;AAErG,QACG,QAAQ,UAAU,CAClB,SAAS,mBAAmB,sBAAsB,CAClD,SAAS,UAAU,+BAA+B,CAClD,OAAO,qBAAqB,8BAA8B,CAC1D,YAAY,sCAAsC,CAClD,OAAO,OAAO,CAACC,cAAsBC,MAAcC,SAA4B,eAAe,cAAc,MAAM,KAAK,CAAC,CAAC;AAE5H,QAAQ,WAAW,QAAQ,KAAK,CAAC,MAAM,CAAC,QAAQ;AAC9C,MAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AACtD,SAAQ,KAAK,EAAE;AAChB,EAAC"}
1
+ {"version":3,"file":"index.js","names":["config?: AuthConfig | null","config: AuthConfig","isLoggedIn","buf: Buffer","apiUrl: string","params: Record<string, string>","redirectUri: string","accessToken: string","expectedState: string","resolveCode!: (code: string) => void","rejectCode!: (err: Error) => void","title: string","message: string","options?: { silent?: boolean }","next: AuthConfig","entry: TokenEntry","status: number","message: string","path: string","options: RequestOptions","headers: Record<string, string>","body: string | undefined","text","id: string","appId: string","body: Record<string, unknown>","token: string","connectionId: string","tool: string","params: Record<string, unknown>","useCase: string","connectionIds?: string[]","name: string","sessionId: string","on: boolean","data: unknown","value: unknown","rows: Array<Record<string, unknown>>","columns?: string[]","message: string","opts: LoginOptions","connector: Connector","token: string","source?: string","connector: Connector | undefined","credentials: Record<string, string>","p","name","s","res","result","idOrShort: string","message: string","c: Connection","idOrShort?: string","config: { schemaFilters: string[] | null; instructions: string | null } | null","path: string","skills","slug: string","SCOPES: readonly Scope[]","slugArg?: string","opts: InstallOptions","result","scope: Scope","key: string","useCase: string","opts: { connection?: string[] }","connectionId: string","tool: string","opts: { data?: string }","params: Record<string, unknown>","n: number","sessionId: string","filePath: string","opts: { output?: string }","MANAGERS: Manager[]","cmd: string","pkg","fn: (...args: A) => Promise<void>","id: string","usecase: string","opts: { connection?: string[] }","connectionId: string","tool: string","opts: { data?: string }","sessionId: string","path: string","opts: { output?: string }"],"sources":["../package.json","../src/lib/config.ts","../src/lib/auth.ts","../src/lib/api.ts","../src/lib/output.ts","../src/commands/login.ts","../src/commands/logout.ts","../src/commands/switch.ts","../src/commands/connect.ts","../src/commands/sources.ts","../src/commands/skills.ts","../../mcp-clients/dist/install.js","../src/lib/skills.ts","../src/commands/install.ts","../src/commands/search.ts","../src/commands/execute.ts","../src/commands/download.ts","../src/commands/upgrade.ts","../src/index.ts"],"sourcesContent":["{\n \"name\": \"@sequelsh/cli\",\n \"version\": \"0.3.0\",\n \"description\": \"Sequel CLI — connect data sources and run tools from your terminal.\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"bin\": {\n \"sequel\": \"./dist/index.js\"\n },\n \"files\": [\n \"dist\"\n ],\n \"exports\": {\n \".\": {\n \"import\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\"\n }\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/sequelsh/sequel.git\",\n \"directory\": \"packages/cli\"\n },\n \"homepage\": \"https://sequel.sh\",\n \"keywords\": [\n \"sequel\",\n \"cli\",\n \"mcp\",\n \"sql\",\n \"data\",\n \"ai\",\n \"agents\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"dev\": \"bun run src/index.ts\",\n \"cli\": \"bun run src/index.ts\",\n \"build\": \"tsdown\",\n \"build:binaries\": \"bun run scripts/build-binaries.ts\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"typecheck\": \"tsc --noEmit\",\n \"clean\": \"rm -rf dist\"\n },\n \"dependencies\": {\n \"@clack/prompts\": \"^0.8.2\",\n \"commander\": \"^12.1.0\",\n \"open\": \"^10.1.0\",\n \"picocolors\": \"^1.1.1\",\n \"yaml\": \"^2.5.1\"\n },\n \"devDependencies\": {\n \"@sequel/mcp-clients\": \"workspace:*\",\n \"@sequel/typescript-config\": \"workspace:*\",\n \"@types/node\": \"^22.10.0\",\n \"tsdown\": \"^0.9.0\",\n \"typescript\": \"^5.7.0\",\n \"vitest\": \"^3.0.0\"\n }\n}\n","import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { mkdirSync, readFileSync, writeFileSync, rmSync, existsSync, chmodSync } from \"node:fs\";\n\n/** Default production API base. Override with SEQUEL_API_URL for local/dev. */\nexport const DEFAULT_API_URL = \"https://api.sequel.sh\";\n\n/** Default marketing site, which publishes the Sequel skill. Override with SEQUEL_SITE_URL. */\nexport const DEFAULT_SITE_URL = \"https://sequel.sh\";\n\nexport function resolveSiteUrl(): string {\n return process.env.SEQUEL_SITE_URL || DEFAULT_SITE_URL;\n}\n\n/** One OAuth token bundle, scoped to a single organization. */\nexport interface TokenEntry {\n accessToken: string;\n refreshToken: string;\n /** ms epoch when the access token expires. */\n expiresAt: number;\n}\n\nexport interface OrgRef {\n id: string;\n name: string;\n slug: string;\n role: string;\n}\n\nexport interface UserRef {\n id: string;\n email: string;\n name: string;\n}\n\n/**\n * The on-disk shape of ~/.sequel/auth.json.\n *\n * Multi-token cache: one genuine org-bound OAuth token per organization, keyed\n * by org id. `activeOrgId` selects which token requests use right now. Switching\n * orgs is an offline swap when the target org already has a cached token.\n */\nexport interface AuthConfig {\n version: 1;\n apiUrl: string;\n /** Persisted dynamic client registration, reused across logins. */\n clientId?: string;\n activeOrgId?: string;\n tokens: Record<string, TokenEntry>;\n user?: UserRef;\n /** Cached membership list for the `switch` UI. */\n orgs?: OrgRef[];\n}\n\n/** Directory holding the CLI's state. Overridable for tests. */\nexport function configDir(): string {\n return process.env.SEQUEL_CONFIG_DIR || join(homedir(), \".sequel\");\n}\n\nexport function configPath(): string {\n return join(configDir(), \"auth.json\");\n}\n\n/** The API base URL: explicit env wins, then a saved value, then the default. */\nexport function resolveApiUrl(config?: AuthConfig | null): string {\n return process.env.SEQUEL_API_URL || config?.apiUrl || DEFAULT_API_URL;\n}\n\nfunction emptyConfig(): AuthConfig {\n return { version: 1, apiUrl: resolveApiUrl(), tokens: {} };\n}\n\n/** Read auth.json, returning a fresh empty config if missing or corrupt. */\nexport function readConfig(): AuthConfig {\n const path = configPath();\n if (!existsSync(path)) return emptyConfig();\n try {\n const parsed = JSON.parse(readFileSync(path, \"utf8\")) as AuthConfig;\n if (!parsed || typeof parsed !== \"object\" || !parsed.tokens) return emptyConfig();\n parsed.tokens ??= {};\n return parsed;\n } catch {\n // Corrupt file — start clean rather than crash.\n return emptyConfig();\n }\n}\n\n/** Persist auth.json with locked-down permissions (dir 0700, file 0600). */\nexport function writeConfig(config: AuthConfig): void {\n const dir = configDir();\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n const path = configPath();\n writeFileSync(path, `${JSON.stringify(config, null, 2)}\\n`, { mode: 0o600 });\n // writeFileSync only applies mode on create; enforce it on existing files too.\n chmodSync(path, 0o600);\n}\n\n/** Remove all stored credentials. Idempotent. */\nexport function clearConfig(): void {\n const path = configPath();\n if (existsSync(path)) rmSync(path);\n}\n\nexport function isLoggedIn(config: AuthConfig): boolean {\n return Boolean(config.activeOrgId && config.tokens[config.activeOrgId]);\n}\n","import { createHash, randomBytes } from \"node:crypto\";\nimport { createServer } from \"node:http\";\nimport { AddressInfo } from \"node:net\";\nimport open from \"open\";\nimport {\n type AuthConfig,\n type OrgRef,\n type TokenEntry,\n type UserRef,\n readConfig,\n writeConfig,\n resolveApiUrl,\n} from \"./config\";\n\n/** Refresh a token this many ms before it actually expires. */\nconst EXPIRY_SKEW_MS = 60_000;\n\nfunction base64url(buf: Buffer): string {\n return buf.toString(\"base64url\");\n}\n\n/** PKCE pair: challenge = base64url(sha256(verifier)), matching the API's S256. */\nexport function generatePkce(): { verifier: string; challenge: string } {\n const verifier = base64url(randomBytes(32));\n const challenge = base64url(createHash(\"sha256\").update(verifier).digest());\n return { verifier, challenge };\n}\n\ninterface TokenResponse {\n access_token: string;\n refresh_token: string;\n expires_in: number;\n token_type: string;\n}\n\ninterface WhoAmI {\n id: string;\n name: string;\n email: string;\n organizationId: string;\n}\n\n/** POST the OAuth token endpoint (form-encoded, per RFC 6749). */\nasync function postToken(apiUrl: string, params: Record<string, string>): Promise<TokenResponse> {\n const res = await fetch(`${apiUrl}/oauth/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams(params).toString(),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`Token request failed (${res.status}): ${body}`);\n }\n return (await res.json()) as TokenResponse;\n}\n\n/** Register a fresh dynamic OAuth client bound to this run's loopback URI. */\nasync function registerClient(apiUrl: string, redirectUri: string): Promise<string> {\n const res = await fetch(`${apiUrl}/oauth/register`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ client_name: \"Sequel CLI\", redirect_uris: [redirectUri] }),\n });\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`Client registration failed (${res.status}): ${body}`);\n }\n const data = (await res.json()) as { client_id: string };\n return data.client_id;\n}\n\nasync function fetchWhoAmI(apiUrl: string, accessToken: string): Promise<WhoAmI> {\n const res = await fetch(`${apiUrl}/users/me`, {\n headers: { Authorization: `Bearer ${accessToken}` },\n });\n if (!res.ok) throw new Error(`Failed to resolve identity (${res.status})`);\n return (await res.json()) as WhoAmI;\n}\n\nexport async function fetchOrganizations(apiUrl: string, accessToken: string): Promise<OrgRef[]> {\n const res = await fetch(`${apiUrl}/organizations`, {\n headers: { Authorization: `Bearer ${accessToken}` },\n });\n if (!res.ok) throw new Error(`Failed to list organizations (${res.status})`);\n const rows = (await res.json()) as Array<{\n role: string;\n organization: { id: string; name: string; slug: string };\n }>;\n return rows.map((r) => ({\n id: r.organization.id,\n name: r.organization.name,\n slug: r.organization.slug,\n role: r.role,\n }));\n}\n\n/**\n * Wait for the browser to hit the loopback redirect and hand back `?code&state`.\n * Resolves with the authorization code once `state` is verified.\n */\nfunction waitForCallback(\n expectedState: string,\n): { server: ReturnType<typeof createServer>; port: Promise<number>; code: Promise<string> } {\n let resolveCode!: (code: string) => void;\n let rejectCode!: (err: Error) => void;\n const code = new Promise<string>((resolve, reject) => {\n resolveCode = resolve;\n rejectCode = reject;\n });\n\n const server = createServer((req, res) => {\n const url = new URL(req.url ?? \"/\", \"http://127.0.0.1\");\n if (url.pathname !== \"/callback\") {\n res.writeHead(404).end(\"Not found\");\n return;\n }\n const error = url.searchParams.get(\"error\");\n const returnedState = url.searchParams.get(\"state\");\n const returnedCode = url.searchParams.get(\"code\");\n\n const finish = (title: string, message: string) => {\n res.writeHead(200, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(\n `<!doctype html><html><head><title>${title}</title></head><body style=\"font-family:system-ui;padding:3rem;text-align:center\"><h2>${title}</h2><p>${message}</p><p>You can close this tab and return to your terminal.</p></body></html>`,\n );\n };\n\n if (error) {\n finish(\"Sign-in failed\", `The authorization server returned: ${error}`);\n rejectCode(new Error(`Authorization failed: ${error}`));\n return;\n }\n if (!returnedState || returnedState !== expectedState) {\n finish(\"Sign-in failed\", \"State mismatch — possible CSRF. Please try again.\");\n rejectCode(new Error(\"State mismatch in OAuth callback\"));\n return;\n }\n if (!returnedCode) {\n finish(\"Sign-in failed\", \"No authorization code was returned.\");\n rejectCode(new Error(\"Missing authorization code\"));\n return;\n }\n finish(\"Signed in to Sequel\", \"Authentication complete.\");\n resolveCode(returnedCode);\n });\n\n const port = new Promise<number>((resolve, reject) => {\n server.on(\"error\", reject);\n server.listen(0, \"127.0.0.1\", () => resolve((server.address() as AddressInfo).port));\n });\n\n return { server, port, code };\n}\n\nexport interface LoginResult {\n user: UserRef;\n org: OrgRef | undefined;\n organizationId: string;\n}\n\n/**\n * Run the full OAuth 2.0 + PKCE loopback flow: register a client, open the\n * browser to the consent page (where the user picks an org), capture the code,\n * exchange it for an org-bound token, then cache that token keyed by its org.\n *\n * Shared by `login` and `switch` (for orgs without a cached token).\n */\nexport async function runLoginFlow(options?: { silent?: boolean }): Promise<LoginResult> {\n const config = readConfig();\n const apiUrl = resolveApiUrl(config);\n\n const { verifier, challenge } = generatePkce();\n const state = base64url(randomBytes(16));\n\n const { server, port: portPromise, code: codePromise } = waitForCallback(state);\n const port = await portPromise;\n const redirectUri = `http://127.0.0.1:${port}/callback`;\n\n try {\n const clientId = await registerClient(apiUrl, redirectUri);\n\n const authorizeUrl = new URL(`${apiUrl}/oauth/authorize`);\n authorizeUrl.searchParams.set(\"client_id\", clientId);\n authorizeUrl.searchParams.set(\"redirect_uri\", redirectUri);\n authorizeUrl.searchParams.set(\"response_type\", \"code\");\n authorizeUrl.searchParams.set(\"code_challenge\", challenge);\n authorizeUrl.searchParams.set(\"code_challenge_method\", \"S256\");\n authorizeUrl.searchParams.set(\"state\", state);\n\n if (!options?.silent) {\n // open() can fail in headless envs — never block the flow on it.\n open(authorizeUrl.toString()).catch(() => {});\n }\n // Always surface the URL so the user can open it manually if needed.\n process.stderr.write(`\\nOpen this URL to continue:\\n${authorizeUrl.toString()}\\n\\n`);\n\n const code = await codePromise;\n\n const token = await postToken(apiUrl, {\n grant_type: \"authorization_code\",\n code,\n redirect_uri: redirectUri,\n client_id: clientId,\n code_verifier: verifier,\n });\n\n const me = await fetchWhoAmI(apiUrl, token.access_token);\n const orgs = await fetchOrganizations(apiUrl, token.access_token).catch(() => config.orgs ?? []);\n\n const next: AuthConfig = {\n ...config,\n version: 1,\n apiUrl,\n clientId,\n activeOrgId: me.organizationId,\n tokens: {\n ...config.tokens,\n [me.organizationId]: {\n accessToken: token.access_token,\n refreshToken: token.refresh_token,\n expiresAt: Date.now() + token.expires_in * 1000,\n },\n },\n user: { id: me.id, email: me.email, name: me.name },\n orgs,\n };\n writeConfig(next);\n\n return {\n user: next.user!,\n org: orgs.find((o) => o.id === me.organizationId),\n organizationId: me.organizationId,\n };\n } finally {\n server.close();\n }\n}\n\n/** True when there's a cached token for the active org (cheap, non-throwing). */\nexport function isLoggedIn(): boolean {\n const config = readConfig();\n const orgId = config.activeOrgId;\n return Boolean(orgId && config.tokens[orgId]);\n}\n\n/**\n * Return a valid access token for the active org, refreshing it in place when\n * expired. Throws a friendly error if there is no token or the refresh fails.\n */\nexport async function getValidAccessToken(): Promise<{ token: string; config: AuthConfig }> {\n const config = readConfig();\n const orgId = config.activeOrgId;\n if (!orgId || !config.tokens[orgId]) {\n throw new Error(\"Not logged in. Run `sequel login` first.\");\n }\n\n const entry: TokenEntry = config.tokens[orgId];\n if (entry.expiresAt - EXPIRY_SKEW_MS > Date.now()) {\n return { token: entry.accessToken, config };\n }\n\n // Access token expired — rotate via the refresh grant.\n const apiUrl = resolveApiUrl(config);\n try {\n const refreshed = await postToken(apiUrl, {\n grant_type: \"refresh_token\",\n refresh_token: entry.refreshToken,\n client_id: config.clientId ?? \"\",\n });\n config.tokens[orgId] = {\n accessToken: refreshed.access_token,\n refreshToken: refreshed.refresh_token,\n expiresAt: Date.now() + refreshed.expires_in * 1000,\n };\n writeConfig(config);\n return { token: refreshed.access_token, config };\n } catch {\n throw new Error(\n \"Your session for this organization has expired. Run `sequel login` (or `sequel switch`) to sign in again.\",\n );\n }\n}\n","import { getValidAccessToken } from \"./auth\";\nimport { resolveApiUrl } from \"./config\";\n\nexport class ApiError extends Error {\n constructor(\n public status: number,\n message: string,\n ) {\n super(message);\n this.name = \"ApiError\";\n }\n}\n\ninterface RequestOptions {\n method?: string;\n query?: Record<string, string | undefined>;\n body?: Record<string, unknown>;\n /**\n * How the active org id is attached to the request:\n * - \"query\" → ?organizationId=<org> (default; most GET/DELETE routes)\n * - \"organizationId\" → merged into the JSON body as organizationId\n * - \"organization_id\" → merged into the JSON body as organization_id (execute)\n * - \"none\" → not attached (e.g. /connectors, /oauth/*)\n */\n org?: \"query\" | \"organizationId\" | \"organization_id\" | \"none\";\n}\n\n/**\n * Authenticated request against the Sequel API using the active org's token.\n * Refreshes the token transparently and scopes the call to that org.\n */\nexport async function request<T = unknown>(path: string, options: RequestOptions = {}): Promise<T> {\n const { token, config } = await getValidAccessToken();\n const apiUrl = resolveApiUrl(config);\n const orgId = config.activeOrgId;\n const orgMode = options.org ?? \"query\";\n\n const url = new URL(`${apiUrl}${path}`);\n if (orgMode === \"query\" && orgId) url.searchParams.set(\"organizationId\", orgId);\n for (const [k, v] of Object.entries(options.query ?? {})) {\n if (v !== undefined) url.searchParams.set(k, v);\n }\n\n let bodyObj = options.body;\n if ((orgMode === \"organizationId\" || orgMode === \"organization_id\") && orgId) {\n bodyObj = { ...(bodyObj ?? {}), [orgMode]: orgId };\n }\n\n const headers: Record<string, string> = { Authorization: `Bearer ${token}` };\n let body: string | undefined;\n if (bodyObj !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n body = JSON.stringify(bodyObj);\n }\n\n const res = await fetch(url.toString(), { method: options.method ?? \"GET\", headers, body });\n\n if (!res.ok) {\n let message = `Request failed (${res.status})`;\n const text = await res.text().catch(() => \"\");\n try {\n const json = JSON.parse(text) as { error?: string };\n if (json.error) message = json.error;\n } catch {\n if (text) message = text;\n }\n throw new ApiError(res.status, message);\n }\n\n if (res.status === 204) return undefined as T;\n const text = await res.text();\n return (text ? JSON.parse(text) : undefined) as T;\n}\n\n/** The active organization id, or throws if not logged in. */\nexport async function activeOrgId(): Promise<string> {\n const { config } = await getValidAccessToken();\n if (!config.activeOrgId) throw new Error(\"No active organization. Run `sequel login`.\");\n return config.activeOrgId;\n}\n\n// ── Types ──────────────────────────────────────────────────────────────────────\n\nexport interface Connector {\n id: string;\n name: string;\n description: string;\n icon: string;\n appType: \"database\" | \"app\" | \"mcp\";\n live: boolean;\n authId: string;\n credentialsSchema?: Record<string, unknown>;\n userInputFields?: string[];\n canResolveName?: boolean;\n configuration?: { type: string } | null;\n}\n\nexport interface Connection {\n id: string;\n shortId: string;\n name: string;\n type: string;\n createdBy?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport type LinkCreateResponse =\n | { status: \"success\"; connection: Connection }\n | { status: \"pending\"; link_token: string; redirect_url: string; expires_at: string };\n\nexport interface LinkStatus {\n status: \"pending\" | \"oauth_in_progress\" | \"awaiting_configuration\" | \"success\" | \"failed\" | \"completed\";\n connectionId?: string;\n connection_id?: string;\n reason?: string;\n}\n\nexport interface ExecuteResult {\n data: Array<Record<string, unknown>>;\n columns: string[];\n row_count: number;\n truncated: boolean;\n}\n\nexport interface SearchToolRef {\n tool_id: string;\n input_schema: Record<string, unknown>;\n output_schema: Record<string, unknown> | null;\n relevant_tables: string[];\n}\n\nexport interface SearchResult {\n connection_id: string;\n connection_name: string;\n app_id: string;\n use_case: string;\n instructions: string;\n tools: SearchToolRef[];\n}\n\n// ── Endpoint wrappers ───────────────────────────────────────────────────────────\n\nexport function listConnectors(): Promise<Connector[]> {\n return request<Connector[]>(\"/connectors\", { org: \"none\" });\n}\n\nexport function listConnections(): Promise<Connection[]> {\n return request<Connection[]>(\"/connections\");\n}\n\nexport function getConnection(id: string): Promise<Connection> {\n return request<Connection>(`/connections/${id}`);\n}\n\nexport function deleteConnection(id: string): Promise<Connection> {\n return request<Connection>(`/connections/${id}`, { method: \"DELETE\" });\n}\n\nexport function testConnection(id: string): Promise<{ success: boolean; message: string }> {\n return request(`/connections/${id}/test`, { method: \"POST\", org: \"organizationId\" });\n}\n\nexport function getConnectionConfig(\n id: string,\n): Promise<{ schemaFilters: string[] | null; instructions: string | null }> {\n return request(`/connections/${id}/config`);\n}\n\n/** Mint a connect link / create a connection for the given connector. */\nexport function createLink(appId: string, body: Record<string, unknown>): Promise<LinkCreateResponse> {\n // POST /link/:appId resolves the org from the token's session, which always\n // matches the active org in the multi-token model — no org param needed.\n return request<LinkCreateResponse>(`/link/${appId}`, { method: \"POST\", org: \"none\", body });\n}\n\n/**\n * Poll a connect link's status. Uses the authenticated route, which (unlike the\n * public one) reports terminal states — `completed`/`failed` — so the CLI can\n * tell when the browser flow has finished.\n */\nexport function getLinkStatus(token: string): Promise<LinkStatus> {\n return request<LinkStatus>(`/link/${token}/status`, { org: \"none\" });\n}\n\nexport function execute(\n connectionId: string,\n tool: string,\n params: Record<string, unknown>,\n): Promise<ExecuteResult> {\n return request<ExecuteResult>(\"/execute\", {\n method: \"POST\",\n org: \"organization_id\",\n body: { connection_id: connectionId, tool, params },\n });\n}\n\nexport function search(useCase: string, connectionIds?: string[]): Promise<{ results: SearchResult[] }> {\n return request<{ results: SearchResult[] }>(\"/search\", {\n method: \"POST\",\n org: \"organization_id\",\n body: {\n action_info: `CLI search: ${useCase}`,\n use_case: useCase,\n connection_ids: connectionIds,\n },\n });\n}\n\nexport async function createApiKey(name: string): Promise<{ key: string; keyPrefix: string }> {\n const orgId = await activeOrgId();\n return request(`/organizations/${orgId}/api-keys`, { method: \"POST\", org: \"none\", body: { name } });\n}\n\nexport interface FileDownloadInfo {\n url: string;\n filename: string;\n size: number;\n expires_in_seconds: number;\n}\n\n/** Get a signed URL to download a file produced in a session (by sequel_execute / workbench). */\nexport function getFileDownloadUrl(sessionId: string, path: string): Promise<FileDownloadInfo> {\n return request<FileDownloadInfo>(\"/files/download\", { query: { session_id: sessionId, path } });\n}\n","import pc from \"picocolors\";\n\nexport { pc };\n\n/** True when the user passed a global --json flag (set by index.ts). */\nlet jsonMode = false;\nexport function setJsonMode(on: boolean): void {\n jsonMode = on;\n}\nexport function isJsonMode(): boolean {\n return jsonMode;\n}\n\nexport function printJson(data: unknown): void {\n process.stdout.write(`${JSON.stringify(data, null, 2)}\\n`);\n}\n\nfunction cell(value: unknown): string {\n if (value === null || value === undefined) return \"\";\n if (typeof value === \"object\") return JSON.stringify(value);\n return String(value);\n}\n\n/**\n * Render an array of records as an aligned text table. `columns` controls order\n * and which keys are shown; defaults to the union of keys in the first row.\n */\nexport function renderTable(rows: Array<Record<string, unknown>>, columns?: string[]): string {\n if (rows.length === 0) return pc.dim(\"(no rows)\");\n const cols = columns ?? Object.keys(rows[0]);\n const widths = cols.map((c) => Math.max(c.length, ...rows.map((r) => cell(r[c]).length)));\n\n const header = cols.map((c, i) => pc.bold(c.padEnd(widths[i]))).join(\" \");\n const sep = cols.map((_, i) => \"─\".repeat(widths[i])).join(\" \");\n const body = rows\n .map((r) => cols.map((c, i) => cell(r[c]).padEnd(widths[i])).join(\" \"))\n .join(\"\\n\");\n\n return `${header}\\n${pc.dim(sep)}\\n${body}`;\n}\n\nexport function printTable(rows: Array<Record<string, unknown>>, columns?: string[]): void {\n // Never emit human tables to stdout in JSON mode — keep stdout valid JSON for jq.\n if (jsonMode) return;\n process.stdout.write(`${renderTable(rows, columns)}\\n`);\n}\n\n// In JSON mode, human-facing lines go to stderr so stdout stays pure JSON.\nexport function success(message: string): void {\n (jsonMode ? process.stderr : process.stdout).write(`${pc.green(\"✓\")} ${message}\\n`);\n}\n\nexport function info(message: string): void {\n (jsonMode ? process.stderr : process.stdout).write(`${message}\\n`);\n}\n\nexport function fail(message: string): void {\n process.stderr.write(`${pc.red(\"✗\")} ${message}\\n`);\n}\n","import * as p from \"@clack/prompts\";\nimport { runLoginFlow } from \"../lib/auth\";\nimport { info, isJsonMode, pc, printJson, success } from \"../lib/output\";\n\nexport interface LoginOptions {\n /** Commander's `--no-browser` sets this to false: print the URL, don't open it. */\n browser?: boolean;\n}\n\nexport async function loginCommand(opts: LoginOptions = {}): Promise<void> {\n const json = isJsonMode();\n const openBrowser = opts.browser !== false;\n const opening = openBrowser ? \"Opening your browser to authorize…\" : \"Sign in with the URL below…\";\n if (json) {\n info(opening); // → stderr in JSON mode\n } else {\n p.intro(pc.cyan(\"Sign in to Sequel\"));\n p.log.info(opening);\n }\n\n const res = await runLoginFlow({ silent: !openBrowser });\n\n if (json) return printJson({ status: \"logged_in\", user: res.user, org: res.org ?? null });\n success(`Logged in as ${pc.bold(res.user.email)}${res.org ? ` · ${pc.bold(res.org.name)}` : \"\"}`);\n p.outro(\"You're all set. Try `sequel sources list` or `sequel connect`.\");\n}\n","import { clearConfig, isLoggedIn, readConfig } from \"../lib/config\";\nimport { info, isJsonMode, printJson, success } from \"../lib/output\";\n\nexport async function logoutCommand(): Promise<void> {\n const config = readConfig();\n if (!isLoggedIn(config)) {\n if (isJsonMode()) return printJson({ status: \"not_logged_in\" });\n info(\"You are not logged in.\");\n return;\n }\n clearConfig();\n if (isJsonMode()) return printJson({ status: \"logged_out\" });\n success(\"Logged out. Cached credentials removed from ~/.sequel/auth.json.\");\n}\n","import * as p from \"@clack/prompts\";\nimport { fetchOrganizations, getValidAccessToken, runLoginFlow } from \"../lib/auth\";\nimport { isLoggedIn, readConfig, resolveApiUrl, writeConfig } from \"../lib/config\";\nimport { isJsonMode, pc, success } from \"../lib/output\";\n\nexport async function switchCommand(): Promise<void> {\n if (isJsonMode()) {\n throw new Error(\n \"`sequel switch` is interactive (it prompts for an organization) — run it in a terminal, not piped/--json.\",\n );\n }\n const config = readConfig();\n if (!isLoggedIn(config)) {\n throw new Error(\"Not logged in. Run `sequel login` first.\");\n }\n\n // Refresh the membership list with the active org's token.\n let orgs = config.orgs ?? [];\n try {\n const { token } = await getValidAccessToken();\n orgs = await fetchOrganizations(resolveApiUrl(config), token);\n writeConfig({ ...readConfig(), orgs });\n } catch {\n // fall back to cached orgs\n }\n if (orgs.length === 0) throw new Error(\"No organizations available for this account.\");\n\n const selection = await p.select({\n message: \"Switch to organization\",\n options: orgs.map((o) => ({\n value: o.id,\n label: o.id === config.activeOrgId ? `${o.name} ${pc.dim(\"(current)\")}` : o.name,\n hint: config.tokens[o.id] ? o.role : \"sign-in required\",\n })),\n });\n if (p.isCancel(selection)) {\n p.cancel(\"Cancelled.\");\n return;\n }\n\n const orgId = selection as string;\n const org = orgs.find((o) => o.id === orgId);\n const fresh = readConfig();\n\n if (fresh.tokens[orgId]) {\n // Already authorized — instant, offline swap.\n writeConfig({ ...fresh, activeOrgId: orgId });\n success(`Switched to ${pc.bold(org?.name ?? orgId)}.`);\n return;\n }\n\n // No cached token for this org — sign in so the user can authorize it.\n p.log.info(`You haven't authorized ${pc.bold(org?.name ?? orgId)} yet — opening your browser…`);\n const res = await runLoginFlow();\n success(`Switched to ${pc.bold(res.org?.name ?? res.organizationId)}.`);\n}\n","import * as p from \"@clack/prompts\";\nimport open from \"open\";\nimport {\n type Connector,\n createLink,\n getLinkStatus,\n listConnectors,\n} from \"../lib/api\";\nimport { info, isJsonMode, pc, success } from \"../lib/output\";\n\nconst SECRET_RE = /pass|secret|token|key|connection|credential/i;\n\nfunction fieldsFor(connector: Connector): string[] {\n if (connector.userInputFields?.length) return connector.userInputFields;\n const props = (connector.credentialsSchema as { properties?: Record<string, unknown> } | undefined)?.properties;\n return props ? Object.keys(props) : [];\n}\n\nfunction isOAuth(connector: Connector): boolean {\n return Boolean(connector.configuration) || /oauth/i.test(connector.authId);\n}\n\n/** Poll a pending connect link until it completes or fails (or times out). */\nasync function pollLink(token: string): Promise<{ ok: boolean; reason?: string }> {\n const deadline = Date.now() + 5 * 60_000;\n while (Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, 2000));\n let status;\n try {\n status = await getLinkStatus(token);\n } catch {\n continue; // transient — keep polling\n }\n if (status.status === \"failed\") return { ok: false, reason: status.reason };\n if (status.status === \"success\" || status.status === \"completed\") return { ok: true };\n }\n return { ok: false, reason: \"Timed out waiting for the browser to finish.\" };\n}\n\nexport async function connectCommand(source?: string): Promise<void> {\n if (isJsonMode()) {\n throw new Error(\n \"`sequel connect` is interactive (it prompts for credentials/consent) — run it in a terminal, not piped/--json.\",\n );\n }\n const connectors = await listConnectors();\n\n let connector: Connector | undefined;\n if (source) {\n connector = connectors.find((c) => c.id === source);\n if (!connector) {\n throw new Error(\n `Unknown connector \"${source}\". Available: ${connectors.map((c) => c.id).join(\", \")}`,\n );\n }\n } else {\n const choice = await p.select({\n message: \"Which data source do you want to connect?\",\n options: connectors\n .slice()\n .sort((a, b) => a.appType.localeCompare(b.appType) || a.name.localeCompare(b.name))\n .map((c) => ({ value: c.id, label: c.name, hint: c.appType })),\n });\n if (p.isCancel(choice)) {\n p.cancel(\"Cancelled.\");\n return;\n }\n connector = connectors.find((c) => c.id === (choice as string))!;\n }\n\n p.intro(`Connect ${pc.bold(connector.name)}`);\n\n if (!isOAuth(connector)) {\n // Pre-auth connector: collect credential fields in the terminal.\n const fields = fieldsFor(connector);\n const credentials: Record<string, string> = {};\n for (const field of fields) {\n const secret = SECRET_RE.test(field);\n const value = await (secret ? p.password : p.text)({\n message: field,\n });\n if (p.isCancel(value)) {\n p.cancel(\"Cancelled.\");\n return;\n }\n credentials[field] = value as string;\n }\n const name = await p.text({ message: \"Name for this source (optional)\", placeholder: connector.name });\n if (p.isCancel(name)) {\n p.cancel(\"Cancelled.\");\n return;\n }\n\n const s = p.spinner();\n s.start(\"Validating credentials…\");\n const res = await createLink(connector.id, {\n credentials,\n ...(name ? { name } : {}),\n });\n if (res.status === \"success\") {\n s.stop(\"Connected.\");\n success(`Created source ${pc.bold(res.connection.name)} (${res.connection.shortId}).`);\n return;\n }\n // Fallback: server wants more input — finish in the browser.\n s.stop(\"Continue in your browser…\");\n open(res.redirect_url).catch(() => {});\n info(`Open: ${res.redirect_url}`);\n const result = await pollLink(res.link_token);\n if (result.ok) success(\"Connected.\");\n else throw new Error(result.reason ?? \"Connection failed.\");\n return;\n }\n\n // OAuth connector: mint a link and let the polished web flow handle consent\n // (and any pre-OAuth fields like a project id), then poll for completion.\n const res = await createLink(connector.id, {});\n if (res.status === \"success\") {\n success(`Created source ${pc.bold(res.connection.name)} (${res.connection.shortId}).`);\n return;\n }\n open(res.redirect_url).catch(() => {});\n info(`Complete authorization in your browser:\\n${res.redirect_url}`);\n const s = p.spinner();\n s.start(\"Waiting for you to finish in the browser…\");\n const result = await pollLink(res.link_token);\n if (result.ok) {\n s.stop(\"Connected.\");\n success(\"Source connected.\");\n } else {\n s.stop(\"Failed.\");\n throw new Error(result.reason ?? \"Connection failed.\");\n }\n}\n","import * as p from \"@clack/prompts\";\nimport {\n type Connection,\n deleteConnection,\n getConnection,\n getConnectionConfig,\n listConnections,\n testConnection,\n} from \"../lib/api\";\nimport { info, isJsonMode, pc, printJson, printTable, success } from \"../lib/output\";\n\n/** Resolve a user-supplied id (uuid or shortId) to the connection's real id. */\nasync function resolveConnection(idOrShort: string): Promise<Connection> {\n const all = await listConnections();\n const match = all.find((c) => c.id === idOrShort || c.shortId === idOrShort);\n if (!match) throw new Error(`No source found matching \"${idOrShort}\".`);\n return match;\n}\n\nasync function pickConnection(message: string): Promise<Connection | undefined> {\n const all = await listConnections();\n if (all.length === 0) {\n info(\"No sources connected yet. Run `sequel connect`.\");\n return undefined;\n }\n const choice = await p.select({\n message,\n options: all.map((c) => ({ value: c.shortId, label: `${c.name} (${c.shortId})`, hint: c.type })),\n });\n if (p.isCancel(choice)) return undefined;\n return all.find((c) => c.shortId === (choice as string));\n}\n\nfunction toRow(c: Connection): Record<string, unknown> {\n return { id: c.shortId, name: c.name, type: c.type, created: c.createdAt.slice(0, 10) };\n}\n\nexport async function sourcesList(): Promise<void> {\n const connections = await listConnections();\n if (isJsonMode()) return printJson(connections);\n if (connections.length === 0) return info(\"No sources connected yet. Run `sequel connect`.\");\n printTable(connections.map(toRow), [\"id\", \"name\", \"type\", \"created\"]);\n}\n\nexport async function sourcesActive(): Promise<void> {\n const connections = await listConnections();\n const rows = await Promise.all(\n connections.map(async (c) => {\n let status = \"unknown\";\n try {\n const t = await testConnection(c.id);\n status = t.success ? \"healthy\" : \"error\";\n } catch {\n status = \"error\";\n }\n return { ...toRow(c), status };\n }),\n );\n if (isJsonMode()) return printJson(rows);\n if (rows.length === 0) return info(\"No sources connected yet. Run `sequel connect`.\");\n printTable(rows, [\"id\", \"name\", \"type\", \"status\", \"created\"]);\n}\n\nexport async function sourcesInfo(idOrShort?: string): Promise<void> {\n const conn = idOrShort ? await resolveConnection(idOrShort) : await pickConnection(\"Source to inspect\");\n if (!conn) return;\n const full = await getConnection(conn.id);\n let config: { schemaFilters: string[] | null; instructions: string | null } | null = null;\n try {\n config = await getConnectionConfig(conn.id);\n } catch {\n /* config may be absent */\n }\n if (isJsonMode()) return printJson({ ...full, config });\n\n info(`${pc.bold(full.name)} ${pc.dim(full.shortId)}`);\n info(`type: ${full.type}`);\n info(`id: ${full.id}`);\n info(`created: ${full.createdAt}`);\n if (config?.schemaFilters?.length) info(`schemas: ${config.schemaFilters.join(\", \")}`);\n if (config?.instructions) info(`\\n${pc.dim(config.instructions)}`);\n}\n\nexport async function sourcesDelete(idOrShort?: string): Promise<void> {\n const conn = idOrShort ? await resolveConnection(idOrShort) : await pickConnection(\"Source to delete\");\n if (!conn) return;\n const confirmed = await p.confirm({ message: `Delete ${pc.bold(conn.name)} (${conn.shortId})? This cannot be undone.` });\n if (p.isCancel(confirmed) || !confirmed) {\n info(\"Cancelled.\");\n return;\n }\n await deleteConnection(conn.id);\n success(`Deleted ${conn.name} (${conn.shortId}).`);\n}\n","import { readConfig, resolveApiUrl } from \"../lib/config\";\nimport { info, isJsonMode, pc, printJson, printTable } from \"../lib/output\";\n\ntype PublicSkill = { id: string; slug: string; name: string; category: string; apps: string[] };\ntype PublicSkillDetail = PublicSkill & { description: string; instructions: string };\n\n// Skills are public, so these hit the unauthenticated marketplace endpoints and\n// work before `sequel login`.\nasync function publicGet<T>(path: string): Promise<T> {\n const res = await fetch(`${resolveApiUrl(readConfig())}${path}`, { headers: { Accept: \"application/json\" } });\n if (res.status === 404) throw new Error(`No skill found matching \"${path.split(\"/\").pop()}\". Run \\`sequel skills list\\`.`);\n if (!res.ok) throw new Error(`Request failed (${res.status})`);\n return (await res.json()) as T;\n}\n\nexport async function skillsList(): Promise<void> {\n const skills = await publicGet<PublicSkill[]>(\"/marketplace/skills\");\n const rows = skills.map((s) => ({ id: s.slug, name: s.name }));\n if (isJsonMode()) return printJson(rows);\n printTable(rows, [\"id\", \"name\"]);\n info(`${rows.length} skills. \\`sequel skills show <id>\\` prints one; \\`sequel install\\` gives your agent all of them.`);\n}\n\nexport async function skillsShow(slug: string): Promise<void> {\n const skill = await publicGet<PublicSkillDetail>(`/marketplace/skills/${encodeURIComponent(slug)}`);\n if (isJsonMode()) return printJson(skill);\n process.stdout.write(\n `${pc.bold(skill.name)} ${pc.dim(skill.slug)}\\n${skill.description}\\n` +\n (skill.apps.length ? `${pc.dim(\"apps:\")} ${skill.apps.join(\", \")}\\n` : \"\") +\n `\\n${skill.instructions}\\n`,\n );\n}\n","import { homedir, platform } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport YAML from \"yaml\";\n\n//#region src/install.ts\nconst SERVER_NAME = \"sequel\";\n/** Folder name of the Sequel skill inside an agent's skills directory. */\nconst SKILL_NAME = \"sequel\";\n/**\n* Write the Sequel SKILL.md into `<dir>/sequel/SKILL.md`, replacing any previous\n* copy. Skill files are plain markdown, so unlike the MCP configs there is\n* nothing to merge: the whole file is ours.\n*/\nfunction installSkill({ dir, markdown }) {\n\tconst path = join(dir, SKILL_NAME, \"SKILL.md\");\n\tmkdirSync(dirname(path), { recursive: true });\n\twriteFileSync(path, markdown.endsWith(\"\\n\") ? markdown : `${markdown}\\n`);\n\treturn {\n\t\tkind: \"file\",\n\t\tpath\n\t};\n}\nconst mcpUrl = (apiUrl) => `${apiUrl.replace(/\\/$/, \"\")}/mcp`;\nconst bearer = (apiKey) => `Bearer ${apiKey}`;\nfunction home(opts) {\n\treturn opts.home ?? homedir();\n}\nfunction cwd(opts) {\n\treturn opts.cwd ?? process.cwd();\n}\n/** OS-specific application-support dir for a vendor folder. */\nfunction appSupport(opts, vendor) {\n\tconst h = home(opts);\n\tswitch (platform()) {\n\t\tcase \"darwin\": return join(h, \"Library\", \"Application Support\", vendor);\n\t\tcase \"win32\": return join(process.env.APPDATA ?? join(h, \"AppData\", \"Roaming\"), vendor);\n\t\tdefault: return join(process.env.XDG_CONFIG_HOME ?? join(h, \".config\"), vendor);\n\t}\n}\n/** Read+merge+write a JSON config, preserving every other key already present. */\nfunction mergeJson(path, mutate) {\n\tlet cfg = {};\n\tif (existsSync(path)) try {\n\t\tcfg = JSON.parse(readFileSync(path, \"utf8\"));\n\t} catch {\n\t\tcfg = {};\n\t}\n\tmutate(cfg);\n\tmkdirSync(dirname(path), { recursive: true });\n\twriteFileSync(path, `${JSON.stringify(cfg, null, 2)}\\n`);\n}\nfunction mergeYaml(path, mutate) {\n\tlet cfg = {};\n\tif (existsSync(path)) try {\n\t\tcfg = YAML.parse(readFileSync(path, \"utf8\")) ?? {};\n\t} catch {\n\t\tcfg = {};\n\t}\n\tmutate(cfg);\n\tmkdirSync(dirname(path), { recursive: true });\n\twriteFileSync(path, YAML.stringify(cfg));\n}\nfunction setNested(cfg, key, value) {\n\tconst obj = cfg[key] ?? {};\n\tobj[SERVER_NAME] = value;\n\tcfg[key] = obj;\n}\nconst mcpClients = [\n\t{\n\t\tslug: \"claude\",\n\t\tname: \"Claude Desktop\",\n\t\tscopes: [\"global\"],\n\t\tdescribe: (o) => join(appSupport(o, \"Claude\"), \"claude_desktop_config.json\"),\n\t\tinstall(o) {\n\t\t\tconst path = join(appSupport(o, \"Claude\"), \"claude_desktop_config.json\");\n\t\t\tmergeJson(path, (cfg) => setNested(cfg, \"mcpServers\", {\n\t\t\t\turl: mcpUrl(o.apiUrl),\n\t\t\t\theaders: { Authorization: bearer(o.apiKey) }\n\t\t\t}));\n\t\t\treturn {\n\t\t\t\tkind: \"file\",\n\t\t\t\tpath\n\t\t\t};\n\t\t}\n\t},\n\t{\n\t\tslug: \"claude-code\",\n\t\tname: \"Claude Code\",\n\t\tscopes: [\"global\", \"local\"],\n\t\tdescribe: (o) => `claude mcp add --scope ${o.scope === \"global\" ? \"user\" : \"local\"} --transport http ${SERVER_NAME} …`,\n\t\tskillsDir: (o) => o.scope === \"global\" ? join(home(o), \".claude\", \"skills\") : join(cwd(o), \".claude\", \"skills\"),\n\t\tinstall(o) {\n\t\t\treturn {\n\t\t\t\tkind: \"command\",\n\t\t\t\tcommand: \"claude\",\n\t\t\t\targs: [\n\t\t\t\t\t\"mcp\",\n\t\t\t\t\t\"add\",\n\t\t\t\t\t\"--scope\",\n\t\t\t\t\to.scope === \"global\" ? \"user\" : \"local\",\n\t\t\t\t\t\"--transport\",\n\t\t\t\t\t\"http\",\n\t\t\t\t\tSERVER_NAME,\n\t\t\t\t\tmcpUrl(o.apiUrl),\n\t\t\t\t\t\"--header\",\n\t\t\t\t\t`Authorization: ${bearer(o.apiKey)}`\n\t\t\t\t]\n\t\t\t};\n\t\t}\n\t},\n\t{\n\t\tslug: \"cursor\",\n\t\tname: \"Cursor\",\n\t\tscopes: [\"global\", \"local\"],\n\t\tdescribe: (o) => o.scope === \"global\" ? join(home(o), \".cursor\", \"mcp.json\") : join(cwd(o), \".cursor\", \"mcp.json\"),\n\t\tinstall(o) {\n\t\t\tconst path = o.scope === \"global\" ? join(home(o), \".cursor\", \"mcp.json\") : join(cwd(o), \".cursor\", \"mcp.json\");\n\t\t\tmergeJson(path, (cfg) => setNested(cfg, \"mcpServers\", {\n\t\t\t\turl: mcpUrl(o.apiUrl),\n\t\t\t\theaders: { Authorization: bearer(o.apiKey) }\n\t\t\t}));\n\t\t\treturn {\n\t\t\t\tkind: \"file\",\n\t\t\t\tpath\n\t\t\t};\n\t\t}\n\t},\n\t{\n\t\tslug: \"vscode\",\n\t\tname: \"VS Code\",\n\t\tscopes: [\"global\", \"local\"],\n\t\tdescribe: (o) => o.scope === \"global\" ? join(appSupport(o, \"Code\"), \"User\", \"mcp.json\") : join(cwd(o), \".vscode\", \"mcp.json\"),\n\t\tinstall(o) {\n\t\t\tconst path = o.scope === \"global\" ? join(appSupport(o, \"Code\"), \"User\", \"mcp.json\") : join(cwd(o), \".vscode\", \"mcp.json\");\n\t\t\tmergeJson(path, (cfg) => setNested(cfg, \"servers\", {\n\t\t\t\turl: mcpUrl(o.apiUrl),\n\t\t\t\ttype: \"http\",\n\t\t\t\theaders: { Authorization: bearer(o.apiKey) }\n\t\t\t}));\n\t\t\treturn {\n\t\t\t\tkind: \"file\",\n\t\t\t\tpath\n\t\t\t};\n\t\t}\n\t},\n\t{\n\t\tslug: \"windsurf\",\n\t\tname: \"Windsurf\",\n\t\tscopes: [\"global\"],\n\t\tdescribe: (o) => join(home(o), \".codeium\", \"windsurf\", \"mcp_config.json\"),\n\t\tinstall(o) {\n\t\t\tconst path = join(home(o), \".codeium\", \"windsurf\", \"mcp_config.json\");\n\t\t\tmergeJson(path, (cfg) => setNested(cfg, \"mcpServers\", {\n\t\t\t\tserverUrl: mcpUrl(o.apiUrl),\n\t\t\t\theaders: { Authorization: bearer(o.apiKey) }\n\t\t\t}));\n\t\t\treturn {\n\t\t\t\tkind: \"file\",\n\t\t\t\tpath\n\t\t\t};\n\t\t}\n\t},\n\t{\n\t\tslug: \"zed\",\n\t\tname: \"Zed\",\n\t\tscopes: [\"global\", \"local\"],\n\t\tdescribe: (o) => o.scope === \"global\" ? join(home(o), \".config\", \"zed\", \"settings.json\") : join(cwd(o), \".zed\", \"settings.json\"),\n\t\tinstall(o) {\n\t\t\tconst path = o.scope === \"global\" ? join(home(o), \".config\", \"zed\", \"settings.json\") : join(cwd(o), \".zed\", \"settings.json\");\n\t\t\tmergeJson(path, (cfg) => setNested(cfg, \"context_servers\", {\n\t\t\t\turl: mcpUrl(o.apiUrl),\n\t\t\t\tsettings: { headers: { Authorization: bearer(o.apiKey) } }\n\t\t\t}));\n\t\t\treturn {\n\t\t\t\tkind: \"file\",\n\t\t\t\tpath\n\t\t\t};\n\t\t}\n\t},\n\t{\n\t\tslug: \"codex\",\n\t\tname: \"Codex\",\n\t\tscopes: [\"global\"],\n\t\tdescribe: (o) => join(home(o), \".codex\", \"config.yaml\"),\n\t\tinstall(o) {\n\t\t\tconst path = join(home(o), \".codex\", \"config.yaml\");\n\t\t\tmergeYaml(path, (cfg) => setNested(cfg, \"mcp_servers\", {\n\t\t\t\turl: mcpUrl(o.apiUrl),\n\t\t\t\theaders: { Authorization: bearer(o.apiKey) }\n\t\t\t}));\n\t\t\treturn {\n\t\t\t\tkind: \"file\",\n\t\t\t\tpath\n\t\t\t};\n\t\t}\n\t},\n\t{\n\t\tslug: \"openclaw\",\n\t\tname: \"OpenClaw\",\n\t\tscopes: [\"global\"],\n\t\tdescribe: () => `openclaw mcp set ${SERVER_NAME} …`,\n\t\tinstall(o) {\n\t\t\tconst def = JSON.stringify({\n\t\t\t\turl: mcpUrl(o.apiUrl),\n\t\t\t\ttransport: \"streamable-http\",\n\t\t\t\theaders: { Authorization: bearer(o.apiKey) }\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tkind: \"command\",\n\t\t\t\tcommand: \"openclaw\",\n\t\t\t\targs: [\n\t\t\t\t\t\"mcp\",\n\t\t\t\t\t\"set\",\n\t\t\t\t\tSERVER_NAME,\n\t\t\t\t\tdef\n\t\t\t\t]\n\t\t\t};\n\t\t}\n\t},\n\t{\n\t\tslug: \"hermes\",\n\t\tname: \"Hermes\",\n\t\tscopes: [\"global\"],\n\t\tdescribe: (o) => join(home(o), \".hermes\", \"config.yaml\"),\n\t\tinstall(o) {\n\t\t\tconst path = join(home(o), \".hermes\", \"config.yaml\");\n\t\t\tmergeYaml(path, (cfg) => setNested(cfg, \"mcp_servers\", {\n\t\t\t\turl: mcpUrl(o.apiUrl),\n\t\t\t\theaders: { Authorization: bearer(o.apiKey) }\n\t\t\t}));\n\t\t\treturn {\n\t\t\t\tkind: \"file\",\n\t\t\t\tpath\n\t\t\t};\n\t\t}\n\t}\n];\nfunction getMcpClient(slug) {\n\treturn mcpClients.find((c) => c.slug === slug);\n}\n\n//#endregion\nexport { SKILL_NAME, getMcpClient, installSkill, mcpClients };\n//# sourceMappingURL=install.js.map","import { resolveSiteUrl } from \"./config\";\n\n/**\n * The canonical Sequel skill is published by the marketing site under the Agent\n * Skills discovery convention. The CLI downloads it at install time rather than\n * bundling a copy, so an installed skill is always the current one and there is\n * a single source of truth for its content.\n */\nexport function skillMarkdownUrl(): string {\n return `${resolveSiteUrl().replace(/\\/$/, \"\")}/.well-known/agent-skills/sequel/SKILL.md`;\n}\n\nexport async function fetchSkillMarkdown(): Promise<string> {\n const url = skillMarkdownUrl();\n const res = await fetch(url, { headers: { Accept: \"text/markdown, text/plain;q=0.9, */*;q=0.1\" } });\n if (!res.ok) throw new Error(`Could not download the Sequel skill (${res.status}) from ${url}`);\n const text = await res.text();\n // A SKILL.md starts with YAML frontmatter; anything else is an error page.\n if (!text.trimStart().startsWith(\"---\")) {\n throw new Error(`Unexpected response from ${url}: not a SKILL.md`);\n }\n return text;\n}\n","import { execFileSync } from \"node:child_process\";\nimport * as p from \"@clack/prompts\";\nimport { createApiKey } from \"../lib/api\";\nimport { isLoggedIn, runLoginFlow } from \"../lib/auth\";\nimport { readConfig, resolveApiUrl } from \"../lib/config\";\nimport { type Scope, getMcpClient, installSkill, mcpClients } from \"../lib/mcp-clients\";\nimport { info, isJsonMode, pc, success } from \"../lib/output\";\nimport { fetchSkillMarkdown } from \"../lib/skills\";\n\nexport interface InstallOptions {\n /** `--scope global|local`; skips the scope prompt. Defaults to the agent's first scope when non-interactive. */\n scope?: string;\n /** Commander's `--no-browser` sets this to false: print the sign-in URL instead of opening it. */\n browser?: boolean;\n}\n\nconst SCOPES: readonly Scope[] = [\"global\", \"local\"];\n\nexport async function installCommand(slugArg?: string, opts: InstallOptions = {}): Promise<void> {\n // Piped/--json (how coding agents run us): no prompts at all. Everything the\n // prompts would have asked must come from the argument and flags instead.\n const interactive = !isJsonMode();\n const slugList = mcpClients.map((c) => c.slug).join(\", \");\n\n if (interactive) p.intro(pc.cyan(\"Install the Sequel MCP server and skill\"));\n\n // Reject a bad slug before opening a browser for sign-in.\n if (slugArg && !getMcpClient(slugArg)) throw new Error(`Unknown agent \"${slugArg}\". Options: ${slugList}`);\n if (!slugArg && !interactive) {\n throw new Error(`Pass the agent slug when running non-interactively: \\`sequel install <agent>\\`. Options: ${slugList}`);\n }\n\n // Sign in first if needed, then continue with the install.\n if (!isLoggedIn()) {\n const msg = \"You need to sign in to Sequel first — opening your browser…\";\n if (interactive) p.log.info(msg);\n else info(msg);\n try {\n const result = await runLoginFlow({ silent: opts.browser === false });\n const signedIn = `Signed in as ${result.user.email}${result.org ? ` (${result.org.name})` : \"\"}.`;\n if (interactive) p.log.success(signedIn);\n else success(signedIn);\n } catch (err) {\n if (!interactive) throw err;\n p.cancel(err instanceof Error ? err.message : String(err));\n return;\n }\n }\n\n let slug = slugArg;\n if (!slug) {\n const choice = await p.select({\n message: \"Which coding agent do you want to install Sequel into?\",\n options: mcpClients.map((c) => ({ value: c.slug, label: c.name })),\n });\n if (p.isCancel(choice)) return p.cancel(\"Cancelled.\");\n slug = choice as string;\n }\n\n const client = getMcpClient(slug);\n if (!client) throw new Error(`Unknown agent \"${slug}\". Options: ${slugList}`);\n\n let scope: Scope = client.scopes[0];\n if (opts.scope !== undefined) {\n if (!SCOPES.includes(opts.scope as Scope)) {\n throw new Error(`Unknown scope \"${opts.scope}\". Options: ${SCOPES.join(\", \")}`);\n }\n if (!client.scopes.includes(opts.scope as Scope)) {\n throw new Error(`${client.name} only supports the ${client.scopes.join(\"/\")} scope.`);\n }\n scope = opts.scope as Scope;\n } else if (client.scopes.length > 1 && interactive) {\n const choice = await p.select({\n message: \"Install scope\",\n options: [\n { value: \"global\", label: \"Global\", hint: \"available everywhere on this machine\" },\n { value: \"local\", label: \"Local\", hint: \"this project only\" },\n ].filter((o) => client.scopes.includes(o.value as Scope)),\n });\n if (p.isCancel(choice)) return p.cancel(\"Cancelled.\");\n scope = choice as Scope;\n }\n\n const config = readConfig();\n const apiUrl = resolveApiUrl(config);\n\n // Clack spinners assume a TTY; when piped, log plain lines instead.\n const s = interactive ? p.spinner() : null;\n s?.start(\"Creating a Sequel API key for this agent…\");\n let key: string;\n try {\n ({ key } = await createApiKey(`Sequel CLI (${client.name})`));\n } catch (err) {\n s?.stop(\"Failed to create API key.\");\n throw err;\n }\n s ? s.stop(\"API key created.\") : info(\"API key created.\");\n\n const result = client.install({ apiUrl, apiKey: key, scope });\n\n if (result.kind === \"command\") {\n // e.g. Claude Code: run `claude mcp add …`.\n try {\n execFileSync(result.command, result.args, { stdio: \"inherit\" });\n } catch {\n throw new Error(\n `Failed to run \\`${result.command}\\`. Make sure it's installed, or run manually:\\n${result.command} ${result.args.join(\" \")}`,\n );\n }\n success(`Installed Sequel into ${client.name} (${scope}).`);\n } else {\n success(`Installed Sequel into ${client.name}.`);\n info(`Config written to ${pc.dim(result.path)}`);\n }\n\n // The skill teaches the agent that Sequel's playbooks exist and how to reach\n // them; the MCP server above is what runs them. Install both where we can.\n const skillsDir = client.skillsDir?.({ apiUrl, apiKey: key, scope }) ?? null;\n if (skillsDir) {\n const sk = interactive ? p.spinner() : null;\n sk?.start(\"Installing the Sequel skill…\");\n try {\n const markdown = await fetchSkillMarkdown();\n const written = installSkill({ dir: skillsDir, markdown });\n sk ? sk.stop(\"Sequel skill installed.\") : success(\"Sequel skill installed.\");\n info(`Skill written to ${pc.dim(written.path)}`);\n } catch (err) {\n // The MCP install already succeeded; a skill download failure should not\n // undo that or look like it did.\n sk?.stop(\"Could not install the Sequel skill.\");\n const warning = `${err instanceof Error ? err.message : String(err)}\\nSequel still works through MCP; rerun \\`sequel install ${client.slug}\\` later to add the skill.`;\n if (interactive) p.log.warn(warning);\n else info(`Could not install the Sequel skill. ${warning}`);\n }\n } else {\n info(\n `${client.name} has no skills directory the CLI can write to; the Sequel skill is skipped. Playbooks are still available through MCP.`,\n );\n }\n\n const done = `Restart ${client.name} and ask it to \"list my Sequel connections\" to verify.`;\n if (interactive) p.outro(done);\n else info(done);\n}\n","import { search } from \"../lib/api\";\nimport { info, isJsonMode, pc, printJson } from \"../lib/output\";\n\nexport async function searchCommand(useCase: string, opts: { connection?: string[] }): Promise<void> {\n const res = await search(useCase, opts.connection);\n if (isJsonMode()) return printJson(res);\n\n if (res.results.length === 0) {\n info(\"No matching tools found across your connected sources.\");\n return;\n }\n\n for (const r of res.results) {\n info(`\\n${pc.bold(r.connection_name)} ${pc.dim(`(${r.connection_id} · ${r.app_id})`)}`);\n if (r.instructions) info(pc.dim(r.instructions));\n for (const tool of r.tools) {\n info(` ${pc.cyan(tool.tool_id)}`);\n if (tool.relevant_tables?.length) info(` tables: ${tool.relevant_tables.join(\", \")}`);\n }\n info(pc.dim(` → sequel execute ${r.connection_id} ${r.tools[0]?.tool_id ?? \"<tool>\"} -d '{…}'`));\n }\n}\n","import { execute } from \"../lib/api\";\nimport { info, isJsonMode, pc, printJson, printTable } from \"../lib/output\";\n\nexport async function executeCommand(\n connectionId: string,\n tool: string,\n opts: { data?: string },\n): Promise<void> {\n let params: Record<string, unknown> = {};\n if (opts.data) {\n try {\n params = JSON.parse(opts.data) as Record<string, unknown>;\n } catch {\n throw new Error(\"Invalid JSON passed to -d/--data.\");\n }\n }\n\n const res = await execute(connectionId, tool, params);\n if (isJsonMode()) return printJson(res);\n\n if (res.data.length === 0) {\n info(pc.dim(\"(0 rows)\"));\n return;\n }\n printTable(res.data, res.columns.length ? res.columns : undefined);\n info(pc.dim(`\\n${res.row_count} row(s)${res.truncated ? \" (truncated)\" : \"\"}`));\n}\n","import { writeFile } from \"node:fs/promises\";\nimport { getFileDownloadUrl } from \"../lib/api\";\nimport { info, isJsonMode, pc, printJson } from \"../lib/output\";\n\nfunction formatBytes(n: number): string {\n if (n < 1024) return `${n} B`;\n if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;\n return `${(n / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nexport async function downloadCommand(\n sessionId: string,\n filePath: string,\n opts: { output?: string },\n): Promise<void> {\n const meta = await getFileDownloadUrl(sessionId, filePath);\n\n // JSON mode (explicit --json or piped): emit the metadata + signed URL for\n // scripting; don't write a file as a surprise side effect.\n if (isJsonMode()) return printJson(meta);\n\n const res = await fetch(meta.url);\n if (!res.ok) throw new Error(`Download failed (${res.status} ${res.statusText})`);\n const dest = opts.output ?? meta.filename;\n await writeFile(dest, Buffer.from(await res.arrayBuffer()));\n info(`${pc.green(\"✓\")} Downloaded ${pc.bold(meta.filename)} (${formatBytes(meta.size)}) → ${dest}`);\n}\n","import { execFileSync } from \"node:child_process\";\nimport * as p from \"@clack/prompts\";\nimport { isJsonMode, pc, printJson, success } from \"../lib/output\";\n\nconst PKG = \"@sequelsh/cli@latest\";\n\ntype Manager = { name: string; cmd: string; args: string[] };\n\n// Global-install command per package manager, in preference order.\nconst MANAGERS: Manager[] = [\n { name: \"npm\", cmd: \"npm\", args: [\"install\", \"-g\", PKG] },\n { name: \"pnpm\", cmd: \"pnpm\", args: [\"add\", \"-g\", PKG] },\n { name: \"bun\", cmd: \"bun\", args: [\"add\", \"-g\", PKG] },\n { name: \"yarn\", cmd: \"yarn\", args: [\"global\", \"add\", PKG] },\n];\n\nfunction has(cmd: string): boolean {\n try {\n execFileSync(process.platform === \"win32\" ? \"where\" : \"which\", [cmd], { stdio: \"ignore\" });\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function upgradeCommand(): Promise<void> {\n const json = isJsonMode();\n if (!json) p.intro(pc.cyan(\"Upgrade the Sequel CLI\"));\n\n const manager = MANAGERS.find((m) => has(m.cmd));\n if (!manager) {\n const msg =\n \"No supported package manager found (npm, pnpm, bun, or yarn). Install Node.js from https://nodejs.org and try again.\";\n if (json) return printJson({ status: \"error\", error: msg });\n p.cancel(msg);\n return;\n }\n\n const s = json ? null : p.spinner();\n s?.start(`Updating ${PKG} with ${manager.name}…`);\n try {\n execFileSync(manager.cmd, manager.args, { stdio: \"pipe\" });\n } catch (err) {\n s?.stop(\"Upgrade failed.\");\n throw new Error(\n `Failed to run \\`${manager.cmd} ${manager.args.join(\" \")}\\`.\\n${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n s?.stop(\"Updated.\");\n\n if (json) return printJson({ status: \"upgraded\", package: PKG, manager: manager.name });\n success(\"Sequel CLI is now on the latest version.\");\n p.outro(\"Run `sequel --version` to confirm.\");\n}\n","import { Command } from \"commander\";\nimport pkg from \"../package.json\" with { type: \"json\" };\nimport { ApiError } from \"./lib/api\";\nimport { fail, setJsonMode } from \"./lib/output\";\nimport { loginCommand } from \"./commands/login\";\nimport { logoutCommand } from \"./commands/logout\";\nimport { switchCommand } from \"./commands/switch\";\nimport { connectCommand } from \"./commands/connect\";\nimport { sourcesActive, sourcesDelete, sourcesInfo, sourcesList } from \"./commands/sources\";\nimport { skillsList, skillsShow } from \"./commands/skills\";\nimport { installCommand } from \"./commands/install\";\nimport { searchCommand } from \"./commands/search\";\nimport { executeCommand } from \"./commands/execute\";\nimport { downloadCommand } from \"./commands/download\";\nimport { upgradeCommand } from \"./commands/upgrade\";\n\nconst program = new Command();\n\nprogram\n .name(\"sequel\")\n .description(\"Sequel CLI — connect data sources and run tools from your terminal\")\n // Inlined by tsdown at build time, so the reported version always matches\n // what the publish workflow bumped in package.json.\n .version(pkg.version)\n .option(\"--json\", \"output machine-readable JSON\")\n .enablePositionalOptions();\n\n/** Wrap a command action with shared --json handling and error reporting. */\nfunction action<A extends unknown[]>(fn: (...args: A) => Promise<void>) {\n return async (...args: A) => {\n // Auto-enable JSON when stdout is piped (e.g. `sequel sources | jq`), not just --json.\n if (program.opts().json || !process.stdout.isTTY) setJsonMode(true);\n try {\n await fn(...args);\n } catch (err) {\n if (err instanceof ApiError && err.status === 401) {\n fail(\"Unauthorized. Run `sequel login` to sign in again.\");\n } else {\n fail(err instanceof Error ? err.message : String(err));\n }\n process.exitCode = 1;\n }\n };\n}\n\nprogram.command(\"upgrade\").description(\"Upgrade the Sequel CLI to the latest version\").action(action(upgradeCommand));\nprogram\n .command(\"login\")\n .description(\"Sign in to Sequel\")\n .option(\"--no-browser\", \"print the sign-in URL instead of opening a browser\")\n .action(action(loginCommand));\nprogram.command(\"logout\").description(\"Sign out and remove cached credentials\").action(action(logoutCommand));\nprogram.command(\"switch\").description(\"Switch the active organization\").action(action(switchCommand));\n\nprogram\n .command(\"connect\")\n .argument(\"[source]\", \"connector id (e.g. postgres); omit to choose interactively\")\n .description(\"Connect a new data source\")\n .action(action(connectCommand));\n\nconst sources = program.command(\"sources\").description(\"Manage connected data sources\");\nsources.command(\"list\", { isDefault: true }).description(\"List connected sources\").action(action(sourcesList));\nsources.command(\"active\").description(\"List sources with live health status\").action(action(sourcesActive));\nsources\n .command(\"info\")\n .argument(\"[id]\", \"source id or short id\")\n .description(\"Show details for a source\")\n .action(action(sourcesInfo));\nsources\n .command(\"delete\")\n .argument(\"[id]\", \"source id or short id\")\n .description(\"Delete a source\")\n .action(action(sourcesDelete));\n\nconst skills = program.command(\"skills\").description(\"Browse the playbooks your agent can follow\");\nskills.command(\"list\", { isDefault: true }).description(\"List every skill (id and name)\").action(action(skillsList));\nskills\n .command(\"show\")\n .argument(\"<id>\", \"skill id, e.g. seo\")\n .description(\"Print a skill's playbook\")\n .action(action((id: string) => skillsShow(id)));\n\nprogram\n .command(\"install\")\n .argument(\"[agent]\", \"coding agent slug (e.g. cursor, claude-code)\")\n .option(\"-s, --scope <scope>\", \"global or local; skips the prompt (defaults to global when piped)\")\n .option(\"--no-browser\", \"print the sign-in URL instead of opening a browser if sign-in is needed\")\n .description(\"Install the Sequel MCP server into a coding agent\")\n .action(action(installCommand));\n\nprogram\n .command(\"search\")\n .argument(\"<usecase>\", \"what you want to do, e.g. \\\"monthly revenue\\\"\")\n .option(\"-c, --connection <id...>\", \"limit to specific connection short ids\")\n .description(\"Find the right tools for a use case across your sources\")\n .action(action((usecase: string, opts: { connection?: string[] }) => searchCommand(usecase, opts)));\n\nprogram\n .command(\"execute\")\n .argument(\"<connection_id>\", \"connection short id\")\n .argument(\"<tool>\", \"tool id, e.g. postgres.query\")\n .option(\"-d, --data <json>\", \"tool input as a JSON string\")\n .description(\"Execute a tool against a connection\")\n .action(action((connectionId: string, tool: string, opts: { data?: string }) => executeCommand(connectionId, tool, opts)));\n\nprogram\n .command(\"download\")\n .argument(\"<session_id>\", \"session id (from `sequel search` or an agent session)\")\n .argument(\"<path>\", \"file path, e.g. /data/result.csv or result.csv\")\n .option(\"-o, --output <file>\", \"write to this path (default: the file's own name)\")\n .description(\"Download a file produced by a query or workbench run\")\n .action(action((sessionId: string, path: string, opts: { output?: string }) => downloadCommand(sessionId, path, opts)));\n\nprogram.parseAsync(process.argv).catch((err) => {\n fail(err instanceof Error ? err.message : String(err));\n process.exit(1);\n});\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sequelsh/cli",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Sequel CLI — connect data sources and run tools from your terminal.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -55,6 +55,7 @@
55
55
  "yaml": "^2.5.1"
56
56
  },
57
57
  "devDependencies": {
58
+ "@sequel/mcp-clients": "workspace:*",
58
59
  "@sequel/typescript-config": "workspace:*",
59
60
  "@types/node": "^22.10.0",
60
61
  "tsdown": "^0.9.0",