@orth/cli 0.2.34 → 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.
@@ -2,4 +2,4 @@
2
2
  * Fire-and-forget analytics event for CLI usage tracking.
3
3
  * Never blocks, never throws, never shows errors to the user.
4
4
  */
5
- export declare function trackEvent(command: string, args?: Record<string, string | undefined>): void;
5
+ export declare function trackEvent(command: string, args?: Record<string, string | undefined>, response?: unknown): void;
package/dist/analytics.js CHANGED
@@ -3,12 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.trackEvent = trackEvent;
4
4
  const config_js_1 = require("./config.js");
5
5
  const CLI_VERSION = process.env.npm_package_version || "0.2.0";
6
- const BASE_URL = "https://api.orthogonal.com/v1";
6
+ const PRODUCTION_BASE_URL = "https://api.orthogonal.com/v1";
7
+ function getAnalyticsBaseUrl() {
8
+ return process.env.ORTH_API_URL || PRODUCTION_BASE_URL;
9
+ }
7
10
  /**
8
11
  * Fire-and-forget analytics event for CLI usage tracking.
9
12
  * Never blocks, never throws, never shows errors to the user.
10
13
  */
11
- function trackEvent(command, args) {
14
+ function trackEvent(command, args, response) {
12
15
  // Don't track if no API key (not authenticated)
13
16
  const apiKey = (0, config_js_1.getApiKey)();
14
17
  if (!apiKey)
@@ -16,6 +19,7 @@ function trackEvent(command, args) {
16
19
  const payload = {
17
20
  command,
18
21
  args: args ? sanitizeArgs(args) : undefined,
22
+ response,
19
23
  cliVersion: CLI_VERSION,
20
24
  os: process.platform,
21
25
  nodeVersion: process.version,
@@ -23,7 +27,7 @@ function trackEvent(command, args) {
23
27
  timestamp: new Date().toISOString(),
24
28
  };
25
29
  // Fire and forget - don't await, don't catch visible errors
26
- fetch(`${BASE_URL}/cli/events`, {
30
+ fetch(`${getAnalyticsBaseUrl()}/cli/events`, {
27
31
  method: "POST",
28
32
  headers: {
29
33
  Authorization: `Bearer ${apiKey}`,
@@ -1,3 +1,4 @@
1
+ import { SearchResponse } from "../api.js";
1
2
  export declare function searchCommand(query: string, options: {
2
3
  limit: string;
3
- }): Promise<void>;
4
+ }): Promise<SearchResponse>;
@@ -15,7 +15,7 @@ async function searchCommand(query, options) {
15
15
  spinner.stop();
16
16
  if (!data.results || data.results.length === 0) {
17
17
  console.log(chalk_1.default.yellow("No APIs found matching your query."));
18
- return;
18
+ return data;
19
19
  }
20
20
  console.log(chalk_1.default.bold(`\nFound ${data.apisCount} APIs with ${data.count} matching endpoints:\n`));
21
21
  for (const api of data.results) {
@@ -44,10 +44,10 @@ async function searchCommand(query, options) {
44
44
  }
45
45
  console.log(chalk_1.default.gray(`Run 'orth api <slug>' to see all endpoints for an API`));
46
46
  console.log(chalk_1.default.gray(`Run 'orth run <api> <path>' to call an endpoint`));
47
+ return data;
47
48
  }
48
49
  catch (error) {
49
50
  spinner.stop();
50
- console.error(chalk_1.default.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
51
- process.exit(1);
51
+ throw error;
52
52
  }
53
53
  }
@@ -1,3 +1,29 @@
1
+ interface SkillResponse {
2
+ id: string;
3
+ name: string;
4
+ slug: string;
5
+ description?: string;
6
+ sourceType: "github" | "upload";
7
+ githubOwner?: string;
8
+ githubRepo?: string;
9
+ githubPath?: string;
10
+ githubRef?: string;
11
+ discoverable: boolean;
12
+ verified: boolean;
13
+ installCount: number;
14
+ tags?: string[];
15
+ installCommand?: string;
16
+ githubUrl?: string;
17
+ files?: {
18
+ filePath: string;
19
+ content: string;
20
+ isPrimary: boolean;
21
+ }[];
22
+ }
23
+ interface SkillSearchResponse {
24
+ results: SkillResponse[];
25
+ count: number;
26
+ }
1
27
  export declare function skillsListCommand(options: {
2
28
  limit: string;
3
29
  }): Promise<void>;
@@ -6,7 +32,7 @@ export declare function skillsMineCommand(options: {
6
32
  }): Promise<void>;
7
33
  export declare function skillsSearchCommand(query: string, options: {
8
34
  limit: string;
9
- }): Promise<void>;
35
+ }): Promise<SkillSearchResponse>;
10
36
  export declare function skillsShowCommand(slug: string): Promise<void>;
11
37
  export declare function skillsCreateCommand(githubRepo: string, options: {
12
38
  path?: string;
@@ -37,3 +63,4 @@ export declare function skillsPublishCommand(slug: string, options: {
37
63
  unpublish?: boolean;
38
64
  }): Promise<void>;
39
65
  export declare function skillsRequestCommand(input: string): Promise<void>;
66
+ export {};
@@ -150,7 +150,7 @@ async function skillsSearchCommand(query, options) {
150
150
  spinner.stop();
151
151
  if (!data.results || data.results.length === 0) {
152
152
  console.log(chalk_1.default.yellow("No skills found matching your query."));
153
- return;
153
+ return data;
154
154
  }
155
155
  console.log(chalk_1.default.bold(`\nFound ${data.count} skills:\n`));
156
156
  for (const skill of data.results) {
@@ -164,11 +164,11 @@ async function skillsSearchCommand(query, options) {
164
164
  console.log();
165
165
  }
166
166
  console.log(chalk_1.default.gray("Run 'orth skills show <slug>' for full details"));
167
+ return data;
167
168
  }
168
169
  catch (error) {
169
170
  spinner.stop();
170
- console.error(chalk_1.default.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
171
- process.exit(1);
171
+ throw error;
172
172
  }
173
173
  }
174
174
  // ─────────────────────────────────────────────────────────────────────────────
package/dist/index.js CHANGED
@@ -13,17 +13,31 @@ const apiRequest_js_1 = require("./commands/apiRequest.js");
13
13
  const analytics_js_1 = require("./analytics.js");
14
14
  /**
15
15
  * Wraps an async action callback so that rejected promises are caught,
16
- * logged, and cause the process to exit with code 1. Without this,
16
+ * logged, and set the process exit code to 1. Without this,
17
17
  * Commander.js silently swallows unhandled rejections from async actions.
18
18
  */
19
19
  function asyncAction(fn) {
20
20
  return (...args) => {
21
21
  fn(...args).catch((err) => {
22
22
  console.error(err instanceof Error ? err.message : "Unknown error");
23
- process.exit(1);
23
+ // Avoid a hard exit so fire-and-forget failure analytics can flush.
24
+ process.exitCode = 1;
24
25
  });
25
26
  };
26
27
  }
28
+ async function runTrackedSearch(command, query, operation) {
29
+ try {
30
+ const response = await operation();
31
+ (0, analytics_js_1.trackEvent)(command, { query }, response);
32
+ }
33
+ catch (error) {
34
+ (0, analytics_js_1.trackEvent)(command, { query }, {
35
+ success: false,
36
+ error: error instanceof Error ? error.message : "Unknown error",
37
+ });
38
+ throw error;
39
+ }
40
+ }
27
41
  const program = new commander_1.Command();
28
42
  program
29
43
  .name("orth")
@@ -99,8 +113,7 @@ apiGroup
99
113
  .description("Search for APIs using natural language")
100
114
  .option("-l, --limit <number>", "Max results", "10")
101
115
  .action(asyncAction(async (query, options) => {
102
- (0, analytics_js_1.trackEvent)("api.search", { query });
103
- await (0, search_js_1.searchCommand)(query, options);
116
+ await runTrackedSearch("api.search", query, () => (0, search_js_1.searchCommand)(query, options));
104
117
  }));
105
118
  apiGroup
106
119
  .command("run <slug> <path>")
@@ -159,8 +172,7 @@ skillsGroup
159
172
  .description("Search for agent skills")
160
173
  .option("-l, --limit <number>", "Max results", "20")
161
174
  .action(asyncAction(async (query, options) => {
162
- (0, analytics_js_1.trackEvent)("skills.search", { query });
163
- await (0, skills_js_1.skillsSearchCommand)(query, options);
175
+ await runTrackedSearch("skills.search", query, () => (0, skills_js_1.skillsSearchCommand)(query, options));
164
176
  }));
165
177
  skillsGroup
166
178
  .command("show <slug>")
@@ -254,8 +266,7 @@ program
254
266
  .description("Search for APIs (alias for 'orth api search')")
255
267
  .option("-l, --limit <number>", "Max results", "10")
256
268
  .action(asyncAction(async (query, options) => {
257
- (0, analytics_js_1.trackEvent)("search", { query });
258
- await (0, search_js_1.searchCommand)(query, options);
269
+ await runTrackedSearch("search", query, () => (0, search_js_1.searchCommand)(query, options));
259
270
  }));
260
271
  program
261
272
  .command("run <api> <path>")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orth/cli",
3
- "version": "0.2.34",
3
+ "version": "0.3.0",
4
4
  "description": "CLI to access all APIs and skills on the Orthogonal platform",
5
5
  "main": "dist/index.js",
6
6
  "bin": {