@aisa-one/cli 0.5.1 → 0.6.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.
package/dist/constants.js CHANGED
@@ -1,4 +1,4 @@
1
- export const VERSION = "0.5.1";
1
+ export const VERSION = "0.6.0";
2
2
  /** Root of the platform. Per-surface bases are derived in api.ts#resolveBases. */
3
3
  export const BASE_URL = "https://api.aisa.one";
4
4
  export const ENV_VAR_NAME = "AISA_API_KEY";
@@ -145,3 +145,6 @@ export const MODEL_PROVIDERS = [
145
145
  "alibaba",
146
146
  "bytedance",
147
147
  ];
148
+ export const AUTH_SERVER = "https://clerk.aisa.one";
149
+ export const AUTH_SETUP_GUIDANCE = `Run "aisa login" to sign in with OAuth. For CI, set ${ENV_VAR_NAME} or use "aisa login --key <key>".`;
150
+ export const MISSING_API_KEY_GUIDANCE = `Not authenticated. ${AUTH_SETUP_GUIDANCE}`;
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ import { VERSION } from "./constants.js";
4
4
  import { CliError } from "./cli-error.js";
5
5
  // Auth
6
6
  import { loginAction, logoutAction, whoamiAction } from "./commands/auth.js";
7
+ import { loginHelpAfter } from "./commands/oauth-login.js";
7
8
  // Account
8
9
  import { balanceAction, topupAction, usageAction } from "./commands/account.js";
9
10
  // API
@@ -75,15 +76,16 @@ program
75
76
  .description("Sign in to AIsa — browser sign-in by default, or --key to paste one")
76
77
  .option("--key <key>", "API key (skips the browser sign-in)")
77
78
  .option("--no-browser", "Print the sign-in URL and paste the redirect back (detected on its own over SSH)")
79
+ .addHelpText("after", loginHelpAfter())
78
80
  .action(wrap(loginAction));
79
81
  program
80
82
  .command("logout")
81
- .description("Remove stored API key")
82
- .action(logoutAction);
83
+ .description("Revoke OAuth refresh token and remove stored credentials")
84
+ .action(wrap(logoutAction));
83
85
  program
84
86
  .command("whoami")
85
87
  .description("Show authentication status")
86
- .action(whoamiAction);
88
+ .action(wrap(whoamiAction));
87
89
  // ── Account ──
88
90
  program
89
91
  .command("topup [amount]")
@@ -243,7 +245,7 @@ mcp
243
245
  .option("--agent <agent>", "Target agent: cursor, claude-desktop, all")
244
246
  .option("--all", "Configure every live server, not just the default set")
245
247
  .option("--yes", "Write the files. Without it, print what would change and stop")
246
- .action(mcpSetupAction);
248
+ .action(wrap(mcpSetupAction));
247
249
  mcp
248
250
  .command("status")
249
251
  .description("Check MCP configuration and ping each configured endpoint")
package/dist/router.d.ts CHANGED
@@ -26,14 +26,14 @@ export interface RouterRequest {
26
26
  /** Raw application JSON. Sent unchanged so numeric tokens survive. */
27
27
  body: string;
28
28
  /** Bearer credential without the "Bearer " prefix, if any. */
29
- apiKey?: string;
29
+ accessToken?: string;
30
30
  }
31
31
  export interface RouterHttpResult {
32
32
  status: number;
33
33
  raw: string;
34
34
  }
35
35
  /**
36
- * POST one Router operation. Never retries: quote and use are not safe to
37
- * replay, and search/schema must not hide a failed attempt.
36
+ * POST one Router operation. Only a 401 permits one authentication retry; quote and use are not safe to
37
+ * replay after a transport or server failure.
38
38
  */
39
39
  export declare function routerPost(request: RouterRequest): Promise<RouterHttpResult>;
package/dist/router.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { getConfig } from "./config.js";
2
- import { httpFetch } from "./utils/http.js";
2
+ import { authenticatedFetch } from "./utils/auth-http.js";
3
3
  /**
4
4
  * Deployed Tool Router origin (nginx / tools.aisa.one). Paths already include
5
5
  * `/v1/tool-router/...`, so this is an origin, not the LLM `/v1` base.
@@ -35,8 +35,8 @@ function stripTrailingSlash(url) {
35
35
  return url.replace(/\/+$/, "");
36
36
  }
37
37
  /**
38
- * POST one Router operation. Never retries: quote and use are not safe to
39
- * replay, and search/schema must not hide a failed attempt.
38
+ * POST one Router operation. Only a 401 permits one authentication retry; quote and use are not safe to
39
+ * replay after a transport or server failure.
40
40
  */
41
41
  export async function routerPost(request) {
42
42
  const url = `${resolveRouterBase()}${ROUTER_PATHS[request.operation]}`;
@@ -44,10 +44,10 @@ export async function routerPost(request) {
44
44
  "Content-Type": "application/json",
45
45
  "x-aisa-source": "cli",
46
46
  };
47
- if (request.apiKey) {
48
- headers.Authorization = `Bearer ${request.apiKey}`;
47
+ if (request.accessToken) {
48
+ headers.Authorization = `Bearer ${request.accessToken}`;
49
49
  }
50
- const res = await httpFetch(url, {
50
+ const res = await authenticatedFetch(url, {
51
51
  method: "POST",
52
52
  headers,
53
53
  body: request.body,
@@ -0,0 +1,3 @@
1
+ import { type HttpOptions } from "./http.js";
2
+ /** Retry only an explicit authentication rejection, at most once. */
3
+ export declare function authenticatedFetch(url: string, options: HttpOptions): Promise<Response>;
@@ -0,0 +1,18 @@
1
+ import { refreshAccessToken } from "../config.js";
2
+ import { httpFetch } from "./http.js";
3
+ /** Retry only an explicit authentication rejection, at most once. */
4
+ export async function authenticatedFetch(url, options) {
5
+ const response = await httpFetch(url, options);
6
+ if (response.status !== 401)
7
+ return response;
8
+ const headers = new Headers(options.headers);
9
+ const authorization = headers.get("Authorization");
10
+ if (!authorization?.startsWith("Bearer "))
11
+ return response;
12
+ const token = await refreshAccessToken(authorization.slice(7));
13
+ if (!token)
14
+ return response;
15
+ await response.body?.cancel();
16
+ headers.set("Authorization", `Bearer ${token}`);
17
+ return httpFetch(url, { ...options, headers: Object.fromEntries(headers.entries()) });
18
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aisa-one/cli",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "description": "CLI for the AIsa unified AI infrastructure platform - one API key for 80+ LLMs and 900+ endpoints across finance, search, social, and video APIs",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -36,10 +36,12 @@
36
36
  "commander": "^12.0.0",
37
37
  "conf": "^12.0.0",
38
38
  "ora": "^8.0.1",
39
+ "proper-lockfile": "^4.1.2",
39
40
  "smol-toml": "^1.8.0"
40
41
  },
41
42
  "devDependencies": {
42
43
  "@types/node": "^20.0.0",
44
+ "@types/proper-lockfile": "^4.1.4",
43
45
  "typescript": "^5.0.0",
44
46
  "vitest": "^3.2.4"
45
47
  },