@outlit/cli 3.2.1 → 3.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +158 -40
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -104,7 +104,7 @@ var package_default;
104
104
  var init_package = __esm(() => {
105
105
  package_default = {
106
106
  name: "@outlit/cli",
107
- version: "3.2.1",
107
+ version: "3.2.2",
108
108
  description: "CLI for querying Outlit customer context and installing agent skills",
109
109
  license: "Apache-2.0",
110
110
  repository: {
@@ -19252,10 +19252,12 @@ function readCommandOutput2(command, args) {
19252
19252
  return null;
19253
19253
  }
19254
19254
  }
19255
- function isStandaloneInstall(argv = process.argv) {
19255
+ function isStandaloneInstall2(argv = process.argv) {
19256
19256
  const scriptPath = argv[1];
19257
19257
  if (!scriptPath)
19258
19258
  return true;
19259
+ if (scriptPath.startsWith("/$bunfs/") || scriptPath.startsWith("~bunfs"))
19260
+ return true;
19259
19261
  const resolved = safeRealPath2(scriptPath) ?? scriptPath;
19260
19262
  return !/\.(?:cjs|mjs|jsx?|tsx?)$/.test(resolved);
19261
19263
  }
@@ -19281,8 +19283,11 @@ function safeRealPath2(filePath) {
19281
19283
  return null;
19282
19284
  }
19283
19285
  }
19284
- function formatUpdateCommand2(installer = inferInstaller2()) {
19285
- switch (installer) {
19286
+ function formatUpdateCommand2(installer, argv = process.argv) {
19287
+ if (isStandaloneInstall2(argv))
19288
+ return STANDALONE_UPDATE_HINT2;
19289
+ const resolved = installer === undefined ? inferInstaller2() : installer;
19290
+ switch (resolved) {
19286
19291
  case "bun":
19287
19292
  return "bun add -g @outlit/cli";
19288
19293
  case "npm":
@@ -19343,7 +19348,7 @@ function runUpgradeCommand(command, opts) {
19343
19348
  throw new Error(`Upgrade command failed: ${command.displayCommand}`);
19344
19349
  }
19345
19350
  }
19346
- var UPDATE_CHECK_INTERVAL_MS2, PACKAGE_NAME2 = "@outlit/cli", LATEST_VERSION_URL2 = "https://registry.npmjs.org/@outlit%2Fcli/latest";
19351
+ var UPDATE_CHECK_INTERVAL_MS2, PACKAGE_NAME2 = "@outlit/cli", LATEST_VERSION_URL2 = "https://registry.npmjs.org/@outlit%2Fcli/latest", STANDALONE_UPDATE_HINT2 = "re-run your original install method (for example `curl -fsSL https://outlit.ai/install.sh | bash` or `brew upgrade outlitai/tap/outlit`), or download the latest release from https://github.com/OutlitAI/outlit-sdk/releases";
19347
19352
  var init_update2 = __esm(() => {
19348
19353
  init_config();
19349
19354
  init_tty();
@@ -19704,26 +19709,77 @@ function checkApiKeyPresence(credential) {
19704
19709
  }
19705
19710
  async function validateApiKey(apiKey) {
19706
19711
  try {
19707
- await pingApiKey(apiKey);
19708
- return { name: "API validation", status: "pass", message: "Key is valid" };
19712
+ const validation = await pingApiKey(apiKey);
19713
+ const org = validation.organization?.name ?? validation.organization?.slug ?? validation.organizationId;
19714
+ const keyDetail = validation.apiKey ? ` · key "${validation.apiKey.name}" (${validation.apiKey.keyType})` : "";
19715
+ return {
19716
+ check: {
19717
+ name: "API validation",
19718
+ status: "pass",
19719
+ message: "Key is valid",
19720
+ detail: `Org: ${org}${keyDetail}`
19721
+ },
19722
+ validation
19723
+ };
19709
19724
  } catch (err) {
19710
19725
  if (isApiKeyValidationUnavailableError(err)) {
19711
19726
  return {
19712
- name: "API validation",
19713
- status: "warn",
19714
- message: "API validation is temporarily unavailable",
19715
- detail: "Try again shortly"
19727
+ check: {
19728
+ name: "API validation",
19729
+ status: "warn",
19730
+ message: "API validation is temporarily unavailable",
19731
+ detail: "Try again shortly"
19732
+ },
19733
+ validation: null
19716
19734
  };
19717
19735
  }
19718
19736
  return {
19719
- name: "API validation",
19720
- status: "fail",
19721
- message: `API rejected key: ${errorMessage(err, "unknown error")}`,
19722
- detail: `Check your key at ${OUTLIT_DASHBOARD_URL}`
19737
+ check: {
19738
+ name: "API validation",
19739
+ status: "fail",
19740
+ message: `API rejected key: ${errorMessage(err, "unknown error")}`,
19741
+ detail: `Check your key at ${OUTLIT_DASHBOARD_URL}`
19742
+ },
19743
+ validation: null
19723
19744
  };
19724
19745
  }
19725
19746
  }
19726
- async function checkIntegrations(apiKey) {
19747
+ function grantUsable(grant, grants, createdById) {
19748
+ if (!grants.includes(grant))
19749
+ return false;
19750
+ if (grant === "integrations:connect_own" && !createdById)
19751
+ return false;
19752
+ return true;
19753
+ }
19754
+ function checkPermissions(validation) {
19755
+ const grants = validation.authorization.grants;
19756
+ const createdById = validation.createdById?.trim() || null;
19757
+ const unavailable = COMMAND_GRANTS.filter((family) => !family.anyOf.some((grant) => grantUsable(grant, grants, createdById)));
19758
+ const detail = [
19759
+ grants.length > 0 ? `grants: ${grants.join(", ")}` : null,
19760
+ unavailable.length > 0 ? `unavailable to this key: ${unavailable.map((family) => family.commands).join("; ")}` : null
19761
+ ].filter((part) => part !== null).join(" · ");
19762
+ return {
19763
+ name: "Permissions",
19764
+ status: unavailable.length > 0 ? "warn" : "pass",
19765
+ message: `${grants.length} key grant${grants.length === 1 ? "" : "s"}`,
19766
+ detail: detail || undefined
19767
+ };
19768
+ }
19769
+ async function checkIntegrations(apiKey, validation) {
19770
+ const grants = validation?.authorization.grants;
19771
+ if (grants) {
19772
+ const createdById = validation?.createdById?.trim() || null;
19773
+ const canRead = grantUsable("integrations:manage", grants, createdById) || grantUsable("integrations:connect_own", grants, createdById);
19774
+ if (!canRead) {
19775
+ return {
19776
+ name: "Integrations",
19777
+ status: "warn",
19778
+ message: "API key does not grant integrations access",
19779
+ detail: "Requires the integrations:manage grant, or integrations:connect_own on a user-created key"
19780
+ };
19781
+ }
19782
+ }
19727
19783
  try {
19728
19784
  const client = await createClient(apiKey);
19729
19785
  const timeout = new Promise((_2, reject) => setTimeout(() => reject(new Error("Integrations check timed out")), 1e4));
@@ -19755,7 +19811,15 @@ async function checkIntegrations(apiKey) {
19755
19811
  status: "pass",
19756
19812
  message: `${ready} integration(s) ready`
19757
19813
  };
19758
- } catch {
19814
+ } catch (err) {
19815
+ if (isOutlitToolsApiError(err) && err.envelope?.code === "TOOL_CALL_FORBIDDEN") {
19816
+ return {
19817
+ name: "Integrations",
19818
+ status: "warn",
19819
+ message: "API key was denied integrations access",
19820
+ detail: "Requires the integrations:manage grant, or integrations:connect_own on a user-created key"
19821
+ };
19822
+ }
19759
19823
  return {
19760
19824
  name: "Integrations",
19761
19825
  status: "warn",
@@ -19843,8 +19907,9 @@ function printChecks(checks) {
19843
19907
  }
19844
19908
  console.log("");
19845
19909
  }
19846
- var FAIL_SYMBOL2, STATUS_ICONS, doctor_default, agentChecks;
19910
+ var FAIL_SYMBOL2, STATUS_ICONS, doctor_default, COMMAND_GRANTS, agentChecks;
19847
19911
  var init_doctor = __esm(() => {
19912
+ init_dist4();
19848
19913
  init_dist();
19849
19914
  init_auth();
19850
19915
  init_output2();
@@ -19867,11 +19932,13 @@ var init_doctor = __esm(() => {
19867
19932
  description: [
19868
19933
  "Check CLI version, API key, connectivity, and agent detection.",
19869
19934
  "",
19870
- "Runs four checks in sequence:",
19935
+ "Runs six checks in sequence:",
19871
19936
  " 1. CLI version -- compares against npm registry",
19872
19937
  " 2. API key -- checks presence and format (ok_ prefix)",
19873
19938
  " 3. API validation -- makes a live test call to verify the key works",
19874
- " 4. Agent detection -- detects supported coding agents and whether the Outlit skill is installed",
19939
+ " 4. Permissions -- shows key grants and unavailable commands",
19940
+ " 5. Integrations -- checks integration readiness or explains missing access",
19941
+ " 6. Agent detection -- detects supported coding agents and whether the Outlit skill is installed",
19875
19942
  "",
19876
19943
  "Exit code: 0 if all checks pass or warn, 1 if any check fails.",
19877
19944
  "",
@@ -19896,9 +19963,12 @@ var init_doctor = __esm(() => {
19896
19963
  checks.push(checkApiKeyPresence(credential));
19897
19964
  if (credential) {
19898
19965
  const apiCheck = await validateApiKey(credential.key);
19899
- checks.push(apiCheck);
19900
- if (apiCheck.status !== "fail") {
19901
- checks.push(await checkIntegrations(credential.key));
19966
+ checks.push(apiCheck.check);
19967
+ if (apiCheck.validation) {
19968
+ checks.push(checkPermissions(apiCheck.validation));
19969
+ }
19970
+ if (apiCheck.check.status !== "fail") {
19971
+ checks.push(await checkIntegrations(credential.key, apiCheck.validation));
19902
19972
  }
19903
19973
  } else {
19904
19974
  checks.push({
@@ -19918,6 +19988,38 @@ var init_doctor = __esm(() => {
19918
19988
  process.exit(1);
19919
19989
  }
19920
19990
  });
19991
+ COMMAND_GRANTS = [
19992
+ {
19993
+ commands: "customers (read), users, facts, sources, search, attention",
19994
+ anyOf: ["customer_intelligence:read"]
19995
+ },
19996
+ { commands: "ws-users", anyOf: ["workspace_members:read"] },
19997
+ { commands: "sql, schema", anyOf: ["analytics:read"] },
19998
+ { commands: "destinations", anyOf: ["destinations:manage"] },
19999
+ { commands: "features", anyOf: ["behavior_metrics:manage"] },
20000
+ {
20001
+ commands: "integrations",
20002
+ anyOf: ["integrations:manage", "integrations:connect_own"]
20003
+ },
20004
+ { commands: "activation get, preview", anyOf: ["activation:read"] },
20005
+ { commands: "activation update, disable", anyOf: ["activation:manage"] },
20006
+ { commands: "settings get", anyOf: ["workspace_settings:read"] },
20007
+ { commands: "settings update", anyOf: ["workspace_settings:manage"] },
20008
+ { commands: "customers grant, revoke, owner", anyOf: ["customer_access:manage"] },
20009
+ {
20010
+ commands: "identity suggestions list",
20011
+ anyOf: ["customer_intelligence:read"]
20012
+ },
20013
+ {
20014
+ commands: "identity suggestions reject",
20015
+ anyOf: ["customer_identity:review"]
20016
+ },
20017
+ {
20018
+ commands: "customers merge (preview), customers merge-status",
20019
+ anyOf: ["customer_intelligence:read"]
20020
+ },
20021
+ { commands: "customers merge --execute", anyOf: ["customer_identity:merge"] }
20022
+ ];
19921
20023
  agentChecks = {
19922
20024
  "claude-code": {
19923
20025
  name: "Claude Code",
@@ -19955,7 +20057,7 @@ var exports_upgrade = {};
19955
20057
  __export(exports_upgrade, {
19956
20058
  default: () => upgrade_default
19957
20059
  });
19958
- var STANDALONE_UPDATE_HINT = "re-run your original install method (for example `curl -fsSL https://outlit.ai/install.sh | bash` or `brew upgrade outlitai/tap/outlit`), or download the latest release from https://github.com/OutlitAI/outlit-sdk/releases", upgrade_default;
20060
+ var upgrade_default;
19959
20061
  var init_upgrade = __esm(() => {
19960
20062
  init_dist();
19961
20063
  init_output2();
@@ -19996,10 +20098,10 @@ var init_upgrade = __esm(() => {
19996
20098
  console.log(`Outlit CLI is already up to date (v${CLI_VERSION2})`);
19997
20099
  return;
19998
20100
  }
19999
- const standalone = isStandaloneInstall();
20101
+ const standalone = isStandaloneInstall2();
20000
20102
  const upgradeCommand = standalone ? null : getUpgradeCommand();
20001
20103
  if (!upgradeCommand) {
20002
- const message = standalone ? `Outlit CLI v${latestVersion} is available. This standalone binary cannot update itself — ${STANDALONE_UPDATE_HINT}.` : `Outlit CLI v${latestVersion} is available. Could not determine how Outlit CLI was installed. Update it manually with your package manager, for example \`bun add -g @outlit/cli\` or \`npm install -g @outlit/cli\`.`;
20104
+ const message = standalone ? `Outlit CLI v${latestVersion} is available. This standalone binary cannot update itself — ${STANDALONE_UPDATE_HINT2}.` : `Outlit CLI v${latestVersion} is available. Could not determine how Outlit CLI was installed. Update it manually with your package manager, for example \`bun add -g @outlit/cli\` or \`npm install -g @outlit/cli\`.`;
20003
20105
  return outputError({ message, code: standalone ? "manual_update_required" : "unknown_installer" }, json);
20004
20106
  }
20005
20107
  try {
@@ -23476,6 +23578,7 @@ var UPDATE_CHECK_INTERVAL_MS = 12 * 60 * 60 * 1000;
23476
23578
  var PACKAGE_NAME = "@outlit/cli";
23477
23579
  var LATEST_VERSION_URL = "https://registry.npmjs.org/@outlit%2Fcli/latest";
23478
23580
  var INTERNAL_UPDATE_FLAG = "--internal-update-check";
23581
+ var STANDALONE_UPDATE_HINT = "re-run your original install method (for example `curl -fsSL https://outlit.ai/install.sh | bash` or `brew upgrade outlitai/tap/outlit`), or download the latest release from https://github.com/OutlitAI/outlit-sdk/releases";
23479
23582
  function getUpdateCachePath() {
23480
23583
  return join2(getConfigDir(), "update-check.json");
23481
23584
  }
@@ -23562,6 +23665,15 @@ function readCommandOutput(command, args) {
23562
23665
  return null;
23563
23666
  }
23564
23667
  }
23668
+ function isStandaloneInstall(argv = process.argv) {
23669
+ const scriptPath = argv[1];
23670
+ if (!scriptPath)
23671
+ return true;
23672
+ if (scriptPath.startsWith("/$bunfs/") || scriptPath.startsWith("~bunfs"))
23673
+ return true;
23674
+ const resolved = safeRealPath(scriptPath) ?? scriptPath;
23675
+ return !/\.(?:cjs|mjs|jsx?|tsx?)$/.test(resolved);
23676
+ }
23565
23677
  function inferInstaller() {
23566
23678
  const fromAgent = inferInstallerFromUserAgent(process.env.npm_config_user_agent ?? "");
23567
23679
  if (fromAgent)
@@ -23584,8 +23696,11 @@ function safeRealPath(filePath) {
23584
23696
  return null;
23585
23697
  }
23586
23698
  }
23587
- function formatUpdateCommand(installer = inferInstaller()) {
23588
- switch (installer) {
23699
+ function formatUpdateCommand(installer, argv = process.argv) {
23700
+ if (isStandaloneInstall(argv))
23701
+ return STANDALONE_UPDATE_HINT;
23702
+ const resolved = installer === undefined ? inferInstaller() : installer;
23703
+ switch (resolved) {
23589
23704
  case "bun":
23590
23705
  return "bun add -g @outlit/cli";
23591
23706
  case "npm":
@@ -23627,26 +23742,29 @@ function printCachedUpdateNotice(argv = process.argv, notify = console.error) {
23627
23742
  Update with: ${notice.command}`);
23628
23743
  return true;
23629
23744
  }
23630
- function scheduleBackgroundUpdateCheck(argv = process.argv, spawnProcess = spawn) {
23745
+ function scheduleBackgroundUpdateCheck(argv = process.argv, spawnProcess = spawn, execPath = process.execPath) {
23631
23746
  if (!shouldShowUpdateNotice(argv))
23632
23747
  return false;
23633
23748
  if (!isUpdateCheckDue(readCachedUpdateState()))
23634
23749
  return false;
23635
- const runtimePath = argv[0];
23636
- const scriptPath = argv[1];
23637
- if (!runtimePath || !scriptPath)
23750
+ const standalone = isStandaloneInstall(argv);
23751
+ const command = standalone ? execPath : argv[0];
23752
+ const scriptPath = standalone ? null : argv[1];
23753
+ if (!command || !standalone && !scriptPath)
23638
23754
  return false;
23639
- const child = spawnProcess(runtimePath, [scriptPath, INTERNAL_UPDATE_FLAG], {
23640
- detached: true,
23641
- stdio: "ignore"
23642
- });
23643
- child.unref?.();
23644
- return true;
23755
+ try {
23756
+ const child = spawnProcess(command, [...scriptPath ? [scriptPath] : [], INTERNAL_UPDATE_FLAG], { detached: true, stdio: "ignore" });
23757
+ child.on?.("error", () => {});
23758
+ child.unref?.();
23759
+ return true;
23760
+ } catch {
23761
+ return false;
23762
+ }
23645
23763
  }
23646
23764
  function initializeUpdateNotifier(opts) {
23647
23765
  const argv = opts?.argv ?? process.argv;
23648
23766
  printCachedUpdateNotice(argv, opts?.notify);
23649
- scheduleBackgroundUpdateCheck(argv, opts?.spawn);
23767
+ scheduleBackgroundUpdateCheck(argv, opts?.spawn, opts?.execPath);
23650
23768
  }
23651
23769
  async function fetchLatestCliVersion() {
23652
23770
  const response = await fetch(LATEST_VERSION_URL, { signal: AbortSignal.timeout(5000) });
@@ -23659,7 +23777,7 @@ async function fetchLatestCliVersion() {
23659
23777
  }
23660
23778
  async function runInternalUpdateCheck(opts) {
23661
23779
  const fetchLatestVersion = opts?.fetchLatestVersion ?? fetchLatestCliVersion;
23662
- const installer = opts?.installer ?? inferInstaller();
23780
+ const installer = isStandaloneInstall() ? null : opts?.installer ?? inferInstaller();
23663
23781
  try {
23664
23782
  const latestVersion = await fetchLatestVersion();
23665
23783
  writeCachedUpdateState({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@outlit/cli",
3
- "version": "3.2.1",
3
+ "version": "3.2.2",
4
4
  "description": "CLI for querying Outlit customer context and installing agent skills",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {