@great-arrow/cli 0.1.47 → 0.1.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +71 -12
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -9399,7 +9399,7 @@ function isNodeError(value) {
9399
9399
 
9400
9400
  // src/lib/version.ts
9401
9401
  var CLI_PACKAGE_NAME = "@great-arrow/cli";
9402
- var CLI_VERSION = "0.1.47";
9402
+ var CLI_VERSION = "0.1.48";
9403
9403
  var GAD_INSTALL_VERSION = "2026.08.08";
9404
9404
  var GAD_INSTALL_MIN_VERSION = "2026.06.22";
9405
9405
  var GAD_INSTALL_HEADER = "X-GAD-Install-Version";
@@ -9865,6 +9865,10 @@ function trimSlash(url) {
9865
9865
  }
9866
9866
 
9867
9867
  // src/lib/oauth/token-exchange.ts
9868
+ var TOKEN_HEADERS = {
9869
+ "content-type": "application/x-www-form-urlencoded",
9870
+ "user-agent": `gad-cli/${CLI_VERSION}`
9871
+ };
9868
9872
  var RefreshRejected = class extends Error {
9869
9873
  constructor(message) {
9870
9874
  super(message);
@@ -9898,7 +9902,7 @@ var TOKEN_POST_TIMEOUT_MS = 8e3;
9898
9902
  async function postToken(apiUrl, form, fetchImpl, timeoutMs = TOKEN_POST_TIMEOUT_MS) {
9899
9903
  const res = await fetchImpl(`${trimSlash2(apiUrl)}/api/oauth/token`, {
9900
9904
  method: "POST",
9901
- headers: { "content-type": "application/x-www-form-urlencoded" },
9905
+ headers: TOKEN_HEADERS,
9902
9906
  body: new URLSearchParams(form).toString(),
9903
9907
  signal: AbortSignal.timeout(timeoutMs)
9904
9908
  });
@@ -9940,7 +9944,7 @@ async function revokeToken(opts) {
9940
9944
  try {
9941
9945
  const res = await doFetch(`${trimSlash2(opts.apiUrl)}/api/oauth/revoke`, {
9942
9946
  method: "POST",
9943
- headers: { "content-type": "application/x-www-form-urlencoded" },
9947
+ headers: TOKEN_HEADERS,
9944
9948
  body: new URLSearchParams(form).toString(),
9945
9949
  signal: AbortSignal.timeout(TOKEN_POST_TIMEOUT_MS)
9946
9950
  });
@@ -10457,6 +10461,14 @@ async function resolveAuth() {
10457
10461
  tokenType: "personal"
10458
10462
  });
10459
10463
  }
10464
+ const codexEnvToken = process.env.GREAT_ARROW_TOKEN;
10465
+ if (codexEnvToken) {
10466
+ return withWorkspace({
10467
+ token: codexEnvToken,
10468
+ apiUrl: configApiUrl,
10469
+ tokenType: "personal"
10470
+ });
10471
+ }
10460
10472
  throw authError(
10461
10473
  "No authentication token found.",
10462
10474
  "Run 'gad login' to authenticate, or set the GAD_TOKEN environment variable."
@@ -10751,6 +10763,46 @@ function isRetryable(error) {
10751
10763
  }
10752
10764
  return false;
10753
10765
  }
10766
+ var RETRY_SAFE_TOOLS = /* @__PURE__ */ new Set([
10767
+ "workspace_introspect",
10768
+ "mcp_capabilities",
10769
+ "tools_discover",
10770
+ "memory_search",
10771
+ "memory_list",
10772
+ "memory_get",
10773
+ "memory_tags",
10774
+ "todo_list",
10775
+ "todo_get",
10776
+ "workspace_list",
10777
+ "workspace_settings_get",
10778
+ "surfaces_list",
10779
+ "agent_list",
10780
+ "engineering_guardrails_list",
10781
+ "model_local_get",
10782
+ "glance",
10783
+ "did_you_know"
10784
+ ]);
10785
+ var CONNECTION_PHASE_CODES = /* @__PURE__ */ new Set([
10786
+ "ECONNREFUSED",
10787
+ "ENOTFOUND",
10788
+ "EAI_AGAIN",
10789
+ "ENETUNREACH",
10790
+ "EHOSTUNREACH",
10791
+ "UND_ERR_CONNECT_TIMEOUT"
10792
+ ]);
10793
+ function hasConnectionPhaseCode(value) {
10794
+ if (!value || typeof value !== "object") return false;
10795
+ const errors = value.errors;
10796
+ if (Array.isArray(errors) && errors.length > 0) {
10797
+ return errors.every(hasConnectionPhaseCode);
10798
+ }
10799
+ const code = value.code;
10800
+ return typeof code === "string" && CONNECTION_PHASE_CODES.has(code);
10801
+ }
10802
+ function isConnectionPhaseFailure(error) {
10803
+ if (!(error instanceof TypeError)) return false;
10804
+ return hasConnectionPhaseCode(error.cause);
10805
+ }
10754
10806
  function isRetryableStatus(status) {
10755
10807
  return status >= 500 && status < 600;
10756
10808
  }
@@ -10806,7 +10858,7 @@ var GadClient = class {
10806
10858
  /**
10807
10859
  * Execute a fetch request with timeout and retry logic.
10808
10860
  */
10809
- async fetchWithRetry(url, init, timeoutMs) {
10861
+ async fetchWithRetry(url, init, timeoutMs, policy = "transient") {
10810
10862
  const effectiveTimeout = timeoutMs ?? this.timeout;
10811
10863
  let lastError;
10812
10864
  for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
@@ -10818,7 +10870,7 @@ var GadClient = class {
10818
10870
  signal: controller.signal
10819
10871
  });
10820
10872
  clearTimeout(timer);
10821
- if (isRetryableStatus(response.status)) {
10873
+ if (policy === "transient" && isRetryableStatus(response.status)) {
10822
10874
  lastError = response;
10823
10875
  if (attempt < MAX_RETRIES - 1) {
10824
10876
  await sleep(retryDelay(attempt));
@@ -10830,7 +10882,8 @@ var GadClient = class {
10830
10882
  } catch (error) {
10831
10883
  clearTimeout(timer);
10832
10884
  lastError = error;
10833
- if (isRetryable(error) && attempt < MAX_RETRIES - 1) {
10885
+ const retryable = policy === "transient" ? isRetryable(error) : isConnectionPhaseFailure(error);
10886
+ if (retryable && attempt < MAX_RETRIES - 1) {
10834
10887
  await sleep(retryDelay(attempt));
10835
10888
  continue;
10836
10889
  }
@@ -10899,7 +10952,8 @@ var GadClient = class {
10899
10952
  headers: this.buildHeaders(),
10900
10953
  body
10901
10954
  },
10902
- timeoutMs
10955
+ timeoutMs,
10956
+ RETRY_SAFE_TOOLS.has(toolName) ? "transient" : "connection-only"
10903
10957
  );
10904
10958
  } catch (error) {
10905
10959
  if (error instanceof CliError) throw error;
@@ -10991,11 +11045,16 @@ var GadClient = class {
10991
11045
  const url = `${this.apiUrl}${path10}`;
10992
11046
  let response;
10993
11047
  try {
10994
- response = await this.fetchWithRetry(url, {
10995
- method: "POST",
10996
- headers: this.buildHeaders(),
10997
- body: JSON.stringify(body)
10998
- });
11048
+ response = await this.fetchWithRetry(
11049
+ url,
11050
+ {
11051
+ method: "POST",
11052
+ headers: this.buildHeaders(),
11053
+ body: JSON.stringify(body)
11054
+ },
11055
+ void 0,
11056
+ "connection-only"
11057
+ );
10999
11058
  } catch (error) {
11000
11059
  if (error instanceof CliError) throw error;
11001
11060
  void captureCliEvent({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@great-arrow/cli",
3
- "version": "0.1.47",
3
+ "version": "0.1.48",
4
4
  "description": "GreatArrow.ai CLI tool",
5
5
  "type": "module",
6
6
  "bin": {