@orchagent/cli 0.3.89 → 0.3.90

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/lib/api.js CHANGED
@@ -116,8 +116,6 @@ async function safeFetchWithRetryForCalls(url, options) {
116
116
  parsed = JSON.parse(bodyText);
117
117
  }
118
118
  catch { /* ignore */ }
119
- const detail = parsed?.error?.message ||
120
- parsed?.message || '';
121
119
  const isRetryable = parsed?.error?.is_retryable;
122
120
  // Don't retry if server explicitly says error is not retryable
123
121
  if (isRetryable === false) {
@@ -130,8 +128,7 @@ async function safeFetchWithRetryForCalls(url, options) {
130
128
  if (attempt < MAX_RETRIES) {
131
129
  const delay = BASE_DELAY_MS * Math.pow(2, attempt - 1);
132
130
  const jitter = Math.random() * 500;
133
- const detailSuffix = detail ? `: ${detail}` : '';
134
- process.stderr.write(`Request failed (${response.status}${detailSuffix}), retrying in ${Math.round((delay + jitter) / 1000)}s...\n`);
131
+ process.stderr.write(`Server error (${response.status}), retrying in ${Math.round((delay + jitter) / 1000)}s...\n`);
135
132
  await new Promise(r => setTimeout(r, delay + jitter));
136
133
  continue;
137
134
  }
@@ -174,8 +171,6 @@ async function safeFetchWithRetry(url, options) {
174
171
  parsed = JSON.parse(bodyText);
175
172
  }
176
173
  catch { /* ignore */ }
177
- const detail = parsed?.error?.message ||
178
- parsed?.message || '';
179
174
  const isRetryable = parsed?.error?.is_retryable;
180
175
  // Don't retry if server explicitly says error is not retryable
181
176
  if (isRetryable === false) {
@@ -188,8 +183,7 @@ async function safeFetchWithRetry(url, options) {
188
183
  if (attempt < MAX_RETRIES) {
189
184
  const delay = BASE_DELAY_MS * Math.pow(2, attempt - 1);
190
185
  const jitter = Math.random() * 500;
191
- const detailSuffix = detail ? `: ${detail}` : '';
192
- process.stderr.write(`Request failed (${response.status}${detailSuffix}), retrying in ${Math.round((delay + jitter) / 1000)}s...\n`);
186
+ process.stderr.write(`Server error (${response.status}), retrying in ${Math.round((delay + jitter) / 1000)}s...\n`);
193
187
  await new Promise(r => setTimeout(r, delay + jitter));
194
188
  continue;
195
189
  }
@@ -191,6 +191,37 @@ function safeRealpathSync(p) {
191
191
  return p;
192
192
  }
193
193
  }
194
+ /**
195
+ * Parse a version string into a comparable numeric tuple.
196
+ * Returns [-1, -1, -1] for unparseable versions (sorts below all valid versions).
197
+ */
198
+ function parseVersion(version) {
199
+ const match = version.match(/^(\d+)\.(\d+)\.(\d+)/);
200
+ if (!match)
201
+ return [-1, -1, -1];
202
+ return [parseInt(match[1], 10), parseInt(match[2], 10), parseInt(match[3], 10)];
203
+ }
204
+ /**
205
+ * Find the latest (highest) version from a list of version strings.
206
+ * Unparseable versions (e.g. "unknown") sort below all valid versions.
207
+ */
208
+ function findLatestVersion(versions) {
209
+ let latest = versions[0];
210
+ let latestParts = parseVersion(latest);
211
+ for (let i = 1; i < versions.length; i++) {
212
+ const parts = parseVersion(versions[i]);
213
+ for (let j = 0; j < 3; j++) {
214
+ if (parts[j] > latestParts[j]) {
215
+ latest = versions[i];
216
+ latestParts = parts;
217
+ break;
218
+ }
219
+ if (parts[j] < latestParts[j])
220
+ break;
221
+ }
222
+ }
223
+ return latest;
224
+ }
194
225
  /**
195
226
  * Detect multiple CLI installations at different paths/versions (BUG-008).
196
227
  *
@@ -248,12 +279,24 @@ async function checkDualInstallation() {
248
279
  .map((i) => `${i.path} (v${i.version})`)
249
280
  .join(', ');
250
281
  if (versionsDiffer) {
282
+ // Find the latest version and build a specific rm command for stale paths
283
+ const latestVersion = findLatestVersion(allInstalls.map((i) => i.version));
284
+ const stalePaths = allInstalls
285
+ .filter((i) => i.version !== latestVersion)
286
+ .map((i) => i.path);
287
+ const staleList = allInstalls
288
+ .filter((i) => i.version !== latestVersion)
289
+ .map((i) => `${i.path} (v${i.version})`)
290
+ .join(', ');
291
+ const fix = stalePaths.length === 1
292
+ ? `Remove outdated ${staleList}: run \`rm ${stalePaths[0]}\``
293
+ : `Remove outdated installations (${staleList}): run \`rm ${stalePaths.join(' ')}\``;
251
294
  return {
252
295
  category: 'environment',
253
296
  name: 'dual_installation',
254
297
  status: 'warning',
255
298
  message: `Multiple CLI versions found: ${pathList}`,
256
- fix: 'Remove the outdated installation. Run `which -a orch orchagent` to see all paths, then remove the older binary',
299
+ fix,
257
300
  details: {
258
301
  installationCount: installations.size,
259
302
  versionMismatch: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orchagent/cli",
3
- "version": "0.3.89",
3
+ "version": "0.3.90",
4
4
  "description": "Command-line interface for orchagent — deploy and run AI agents for your team",
5
5
  "license": "MIT",
6
6
  "author": "orchagent <hello@orchagent.io>",