@fabricorg/cli 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/fabric.js CHANGED
@@ -54,6 +54,59 @@ var __async = (__this, __arguments, generator) => {
54
54
  // src/bin/fabric.ts
55
55
  import { Command as Command20 } from "commander";
56
56
 
57
+ // package.json
58
+ var package_default = {
59
+ name: "@fabricorg/cli",
60
+ version: "0.3.1",
61
+ description: "CLI for the Fabric AI platform",
62
+ keywords: [
63
+ "fabric",
64
+ "ai",
65
+ "cli",
66
+ "developer-tools"
67
+ ],
68
+ homepage: "https://fabric.pro",
69
+ license: "MIT",
70
+ repository: {
71
+ type: "git",
72
+ url: "git+https://github.com/Fabric-Pro/fabric-oss.git",
73
+ directory: "packages/cli"
74
+ },
75
+ type: "module",
76
+ bin: {
77
+ fabric: "./dist/fabric.js"
78
+ },
79
+ files: [
80
+ "dist"
81
+ ],
82
+ publishConfig: {
83
+ access: "public"
84
+ },
85
+ scripts: {
86
+ build: "tsup",
87
+ dev: "tsup --watch",
88
+ "type-check": "tsc --noEmit",
89
+ test: "vitest run",
90
+ "test:watch": "vitest",
91
+ fabric: "node --import tsx/esm src/bin/fabric.ts"
92
+ },
93
+ dependencies: {
94
+ "@fabricorg/sdk": "workspace:*",
95
+ "@fabricorg/sdk-mcp": "workspace:*",
96
+ "cli-table3": "^0.6.5",
97
+ commander: "^13.1.0",
98
+ conf: "^13.1.0",
99
+ fflate: "^0.8.3"
100
+ },
101
+ devDependencies: {
102
+ "@repo/tsconfig": "workspace:*",
103
+ tsup: "^8.0.0",
104
+ tsx: "^4.21.0",
105
+ typescript: "5.9.3",
106
+ vitest: "^4.1.11"
107
+ }
108
+ };
109
+
57
110
  // src/commands/agents/index.ts
58
111
  import { Command } from "commander";
59
112
 
@@ -112,21 +165,25 @@ function getOutputFormat() {
112
165
  }
113
166
  return getConfig().defaultFormat;
114
167
  }
115
- function saveApiKey(apiKey, profile = "default") {
168
+ function saveApiKey(apiKey, { baseUrl } = {}) {
116
169
  var _a2;
117
170
  const store = getStore();
171
+ const profile = store.get("activeProfile");
118
172
  const profiles = store.get("profiles");
173
+ const current = (_a2 = profiles[profile]) != null ? _a2 : {};
119
174
  store.set("profiles", __spreadProps(__spreadValues({}, profiles), {
120
- [profile]: __spreadProps(__spreadValues({}, (_a2 = profiles[profile]) != null ? _a2 : {}), { apiKey })
175
+ [profile]: __spreadValues(__spreadProps(__spreadValues({}, current), {
176
+ apiKey
177
+ }), baseUrl === void 0 ? {} : { baseUrl })
121
178
  }));
122
- store.set("activeProfile", profile);
123
179
  }
124
- function clearApiKey(profile = "default") {
180
+ function clearApiKey(profile) {
125
181
  var _a2;
126
182
  const store = getStore();
183
+ const active = profile != null ? profile : store.get("activeProfile");
127
184
  const profiles = store.get("profiles");
128
- const _b = (_a2 = profiles[profile]) != null ? _a2 : {}, { apiKey: _ } = _b, rest = __objRest(_b, ["apiKey"]);
129
- store.set("profiles", __spreadProps(__spreadValues({}, profiles), { [profile]: rest }));
185
+ const _b = (_a2 = profiles[active]) != null ? _a2 : {}, { apiKey: _ } = _b, rest = __objRest(_b, ["apiKey"]);
186
+ store.set("profiles", __spreadProps(__spreadValues({}, profiles), { [active]: rest }));
130
187
  }
131
188
  function saveDefaultContext(ctx, profile) {
132
189
  var _a2;
@@ -562,8 +619,16 @@ function buildKeysCommand() {
562
619
 
563
620
  // src/commands/auth/login.ts
564
621
  import * as readline from "readline";
565
- import { FabricClient as FabricClient2 } from "@fabricorg/sdk";
622
+ import { FabricAuthError as FabricAuthError2, FabricClient as FabricClient2, FabricError } from "@fabricorg/sdk";
566
623
  import { Command as Command3 } from "commander";
624
+ var DEFAULT_BASE_URL = "https://fabric.pro";
625
+ function displayBaseUrl(baseUrl) {
626
+ try {
627
+ return new URL(baseUrl).origin;
628
+ } catch (e) {
629
+ return "the configured Fabric deployment";
630
+ }
631
+ }
567
632
  function promptApiKey() {
568
633
  return __async(this, null, function* () {
569
634
  const rl = readline.createInterface({
@@ -601,6 +666,9 @@ function buildLoginCommand() {
601
666
  );
602
667
  }
603
668
  const baseUrl = (_b = opts.baseUrl) != null ? _b : getBaseUrl();
669
+ const effectiveBaseUrl = displayBaseUrl(
670
+ baseUrl != null ? baseUrl : DEFAULT_BASE_URL
671
+ );
604
672
  const client = new FabricClient2({ apiKey, baseUrl });
605
673
  let name;
606
674
  let email;
@@ -608,13 +676,25 @@ function buildLoginCommand() {
608
676
  const me = yield client.auth.whoami();
609
677
  name = (_c = me.user.name) != null ? _c : me.user.email;
610
678
  email = me.user.email;
611
- } catch (e) {
679
+ } catch (error) {
680
+ if (error instanceof FabricAuthError2 || error instanceof FabricError && error.status === 401) {
681
+ printError(
682
+ "Authentication failed. Check that the key is valid and not expired.",
683
+ 3
684
+ );
685
+ }
686
+ if (error instanceof FabricError && error.status > 0) {
687
+ printError(
688
+ `Authentication request to ${effectiveBaseUrl} failed with HTTP ${error.status}.`,
689
+ 3
690
+ );
691
+ }
612
692
  printError(
613
- "Authentication failed. Check that the key is valid and not expired.",
693
+ `Could not connect to ${effectiveBaseUrl}. Check that the deployment URL is correct and reachable.`,
614
694
  3
615
695
  );
616
696
  }
617
- saveApiKey(apiKey);
697
+ saveApiKey(apiKey, __spreadValues({}, opts.baseUrl === void 0 ? {} : { baseUrl: opts.baseUrl }));
618
698
  printSuccess(`Authenticated as ${name} (${email})`);
619
699
  }));
620
700
  }
@@ -2824,6 +2904,7 @@ function syncOnce(opts) {
2824
2904
  const lock = yield readLockForProject(root, opts.project);
2825
2905
  const client = instructionsClient(opts, SYNC_TIMEOUT_MS);
2826
2906
  let published = yield fetchPublished(client, opts, lock == null ? void 0 : lock.digest);
2907
+ assertInitSyncMayAct(opts, published);
2827
2908
  if (!published.published || !published.snapshot) {
2828
2909
  throw new CliFailure(
2829
2910
  "This project has no published coding instructions yet.",
@@ -2840,6 +2921,7 @@ function syncOnce(opts) {
2840
2921
  }
2841
2922
  outcome.drifted = drifted;
2842
2923
  published = yield fetchPublished(client, opts);
2924
+ assertInitSyncMayAct(opts, published);
2843
2925
  if (!published.published || !published.snapshot) {
2844
2926
  throw new CliFailure(
2845
2927
  "This project has no published coding instructions yet.",
@@ -2914,6 +2996,14 @@ function syncOnce(opts) {
2914
2996
  return outcome;
2915
2997
  });
2916
2998
  }
2999
+ function assertInitSyncMayAct(opts, published) {
3000
+ if (opts.rejectRepository && published.sourceOfTruth === "REPOSITORY") {
3001
+ throw new CliFailure(
3002
+ "This project's coding instructions come from its repository, so they arrive with `git pull`. A session hook would fight it; nothing was written.",
3003
+ 7
3004
+ );
3005
+ }
3006
+ }
2917
3007
  function fillPlanPaths(outcome, plan) {
2918
3008
  outcome.added = plan.entries.filter((entry) => entry.action === "added").map((entry) => entry.path);
2919
3009
  outcome.updated = plan.entries.filter((entry) => entry.action === "updated").map((entry) => entry.path);
@@ -2977,6 +3067,13 @@ function runInit(opts, format) {
2977
3067
  7
2978
3068
  );
2979
3069
  }
3070
+ const outcome = published.published ? (
3071
+ // A second manifest call, deliberately: the one above answered "may
3072
+ // a hook be installed for this project at all", and this one is the
3073
+ // sync's own. Do it before the hook write: a failed first copy must
3074
+ // not leave a new or updated hook behind.
3075
+ yield syncOnce(__spreadProps(__spreadValues({}, opts), { hook: false, rejectRepository: true }))
3076
+ ) : null;
2980
3077
  const command = buildHookCommand(
2981
3078
  opts.project,
2982
3079
  Boolean(opts.apply),
@@ -2987,13 +3084,6 @@ function runInit(opts, format) {
2987
3084
  projectId: opts.project,
2988
3085
  command
2989
3086
  });
2990
- const outcome = published.published ? (
2991
- // A second manifest call, deliberately: the one above answered "may
2992
- // a hook be installed for this project at all", and this one is the
2993
- // sync's own — it carries the lock's digest and is the call the
2994
- // hook will make from now on.
2995
- yield syncOnce(__spreadProps(__spreadValues({}, opts), { hook: false }))
2996
- ) : null;
2997
3087
  if (format === "json") {
2998
3088
  printOutput(
2999
3089
  {
@@ -3930,7 +4020,7 @@ function buildWorkspacesCommand() {
3930
4020
  // src/bin/fabric.ts
3931
4021
  var program = new Command20();
3932
4022
  var _a;
3933
- program.name("fabric").description("Fabric AI platform CLI").version("0.1.0").option(
4023
+ program.name("fabric").description("Fabric AI platform CLI").version(package_default.version).option(
3934
4024
  "--format <format>",
3935
4025
  "Output format: table|json|yaml|csv",
3936
4026
  (_a = process.env.FABRIC_FORMAT) != null ? _a : "table"