@aisa-one/cli 0.3.0 → 0.5.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.
Files changed (102) hide show
  1. package/CHANGELOG.md +143 -1
  2. package/LICENSE +21 -0
  3. package/README.md +151 -162
  4. package/dist/api.d.ts +10 -0
  5. package/dist/api.js +14 -3
  6. package/dist/catalog.d.ts +1 -18
  7. package/dist/catalog.js +1 -24
  8. package/dist/cli-error.d.ts +17 -0
  9. package/dist/cli-error.js +25 -0
  10. package/dist/cli-guidance.d.ts +14 -0
  11. package/dist/cli-guidance.js +55 -0
  12. package/dist/commands/account.d.ts +17 -0
  13. package/dist/commands/account.js +45 -1
  14. package/dist/commands/api.d.ts +0 -11
  15. package/dist/commands/api.js +6 -175
  16. package/dist/commands/auth.d.ts +2 -1
  17. package/dist/commands/auth.js +43 -9
  18. package/dist/commands/brand-logos.d.ts +6 -0
  19. package/dist/commands/brand-logos.js +21 -0
  20. package/dist/commands/configCmd.js +8 -3
  21. package/dist/commands/connect-shared.d.ts +136 -0
  22. package/dist/commands/connect-shared.js +143 -0
  23. package/dist/commands/connect-t2.d.ts +18 -0
  24. package/dist/commands/connect-t2.js +1599 -0
  25. package/dist/commands/connect-terminal.d.ts +65 -0
  26. package/dist/commands/connect-terminal.js +822 -0
  27. package/dist/commands/connect.d.ts +31 -0
  28. package/dist/commands/connect.js +3181 -0
  29. package/dist/commands/flow.d.ts +685 -0
  30. package/dist/commands/flow.js +697 -0
  31. package/dist/commands/install.d.ts +91 -0
  32. package/dist/commands/install.js +258 -0
  33. package/dist/commands/llm-config.d.ts +103 -0
  34. package/dist/commands/llm-config.js +452 -0
  35. package/dist/commands/manifest.d.ts +68 -0
  36. package/dist/commands/manifest.js +90 -0
  37. package/dist/commands/mcp.d.ts +59 -0
  38. package/dist/commands/mcp.js +122 -44
  39. package/dist/commands/oauth-login.d.ts +33 -0
  40. package/dist/commands/oauth-login.js +333 -0
  41. package/dist/commands/prompt.d.ts +96 -0
  42. package/dist/commands/prompt.js +397 -0
  43. package/dist/commands/serve-results.d.ts +61 -0
  44. package/dist/commands/serve-results.js +245 -0
  45. package/dist/commands/serve-signin.d.ts +28 -0
  46. package/dist/commands/serve-signin.js +90 -0
  47. package/dist/commands/signin-page.d.ts +49 -0
  48. package/dist/commands/signin-page.js +250 -0
  49. package/dist/commands/skills.js +87 -50
  50. package/dist/commands/tool-help.d.ts +69 -0
  51. package/dist/commands/tool-help.js +189 -0
  52. package/dist/commands/tool-input.d.ts +22 -0
  53. package/dist/commands/tool-input.js +220 -0
  54. package/dist/commands/tools.d.ts +12 -0
  55. package/dist/commands/tools.js +307 -0
  56. package/dist/commands/update.d.ts +11 -0
  57. package/dist/commands/update.js +92 -0
  58. package/dist/commands/vscode.d.ts +65 -0
  59. package/dist/commands/vscode.js +173 -0
  60. package/dist/commands/wrappers.d.ts +23 -0
  61. package/dist/commands/wrappers.js +102 -0
  62. package/dist/completion.js +3 -80
  63. package/dist/config.js +76 -2
  64. package/dist/constants.d.ts +51 -38
  65. package/dist/constants.js +53 -109
  66. package/dist/index.js +152 -355
  67. package/dist/json-text.d.ts +12 -0
  68. package/dist/json-text.js +60 -0
  69. package/dist/router.d.ts +39 -0
  70. package/dist/router.js +59 -0
  71. package/dist/skills-registry.js +12 -3
  72. package/dist/utils/banner.d.ts +9 -0
  73. package/dist/utils/banner.js +41 -0
  74. package/dist/utils/browser.d.ts +19 -0
  75. package/dist/utils/browser.js +31 -0
  76. package/dist/utils/exec.d.ts +43 -0
  77. package/dist/utils/exec.js +61 -0
  78. package/dist/utils/http.d.ts +53 -0
  79. package/dist/utils/http.js +124 -0
  80. package/dist/utils/install-method.d.ts +36 -0
  81. package/dist/utils/install-method.js +48 -0
  82. package/dist/utils/journal.d.ts +57 -0
  83. package/dist/utils/journal.js +188 -0
  84. package/dist/utils/key-check.d.ts +20 -0
  85. package/dist/utils/key-check.js +24 -0
  86. package/dist/utils/update-check.d.ts +23 -0
  87. package/dist/utils/update-check.js +116 -0
  88. package/dist/utils/width.d.ts +32 -0
  89. package/dist/utils/width.js +73 -0
  90. package/package.json +8 -4
  91. package/vscode-extension/README.md +6 -0
  92. package/vscode-extension/aisa-vscode.vsix +0 -0
  93. package/dist/commands/finance.d.ts +0 -17
  94. package/dist/commands/finance.js +0 -342
  95. package/dist/commands/run.d.ts +0 -28
  96. package/dist/commands/run.js +0 -182
  97. package/dist/commands/search.d.ts +0 -9
  98. package/dist/commands/search.js +0 -81
  99. package/dist/commands/twitter.d.ts +0 -138
  100. package/dist/commands/twitter.js +0 -374
  101. package/dist/commands/video.d.ts +0 -49
  102. package/dist/commands/video.js +0 -311
package/CHANGELOG.md CHANGED
@@ -7,6 +7,145 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.5.0] — Unreleased
11
+
12
+ PR21 command-surface cleanup. Distinct from the unpublished `0.4.0` main
13
+ baseline (registry latest remains `0.3.0`; `0.4.0` was never tagged or
14
+ published).
15
+
16
+ ### Breaking
17
+
18
+ - **Domain shortcuts and raw execution are removed.** These names are
19
+ unknown commands — not aliases and not auto-forwarded to `aisa call`:
20
+ `web-search`, `scholar`, `stock`, `crypto`, `screener`, `tweet`, `twitter`
21
+ (all children), `video` (all children), `run`, top-level `code`,
22
+ `api search`, and `api code`. Root help is 22 entries including implicit
23
+ `help` (21 explicit commands).
24
+ - **`aisa api list` and `aisa api show` stay** as the supported read-only
25
+ provider/endpoint catalog. They are not deprecated and are not a
26
+ substitute for `schema` / `quote`. Catalog paths and prices are browsing
27
+ metadata. `api show` is not equivalent to `aisa schema`. The `0.4.0`
28
+ deprecation of `api show` is withdrawn because the command is retained.
29
+
30
+ ### Changed
31
+
32
+ - Bundled `aisa skills init` templates may keep domain labels (`search`,
33
+ `finance`, `twitter`, `video`). Runnable steps use `search` / `schema` /
34
+ `quote` / `call` and optional `api list` / `api show`. They do not invent
35
+ tool names or treat Router as covering every removed domain function. The
36
+ `llm` template stays on `chat` / `models`.
37
+ - Root and Router help/manifest no longer document removed names. Router
38
+ `mcp` / `auth` / `exits` / `examples` still attach only to top-level
39
+ `search` / `schema` / `quote` / `call`, not nested `skills search`.
40
+
41
+ ## [0.4.0] — unpublished main baseline
42
+
43
+ Unpublished `main` candidate as of 2026-09-08. Not tagged and not on npm
44
+ (registry latest remains `0.3.0`). Kept so the Router work and the
45
+ `api search` / `api show` / `run` deprecation history stay identifiable.
46
+
47
+ ### Breaking
48
+
49
+ - **`aisa search` is no longer an alias for `api search`.** It now calls the
50
+ Tool Router (`POST /v1/tool-router/aisa-search-tool`) and prints Router
51
+ results. The old catalog keyword search remains as `aisa api search`.
52
+
53
+ ### Added
54
+
55
+ - **`aisa search` / `schema` / `quote` / `call`** — Unix-oriented entries for
56
+ the same four Router operations as MCP. Accept `--input '<json>'` and
57
+ `-f/--file` (including `-f -` for stdin). `--json` writes the unmodified
58
+ application response, including integer tokens outside JavaScript's safe
59
+ range. Quote never executes; none of the four retry or fall back to
60
+ provider shortcuts. Router origin is `AISA_ROUTER_BASE_URL`, else config
61
+ `routerUrl`, else `https://tools.aisa.one`. The LLM/catalog host
62
+ `https://api.aisa.one` is unchanged and is not a Router fallback.
63
+
64
+ ### Fixed
65
+
66
+ - Router `search` / `schema` / `quote` / `call` do not follow HTTP redirects.
67
+ A 307/308 is a transport failure, so a quote response cannot become a use.
68
+ - Human quote/call print each result's own micro-USD token, including values
69
+ above 2^53. `--json` was already lossless.
70
+ - Full `--input` / `-f` envelopes reject unknown fields, duplicate `call_id`,
71
+ and non-unique or oversized `provider_filters` before dispatch.
72
+ - Human search prints a returned `plan` (`plan_ref`, steps, pitfalls) when
73
+ the Router includes one.
74
+ - Default Tool Router origin is `https://tools.aisa.one`. Anonymous
75
+ `/v1/tool-router/...` on `api.aisa.one` returns 404; the deployed nginx
76
+ front door is `tools.aisa.one`. Overrides (`AISA_ROUTER_BASE_URL`,
77
+ `routerUrl`) keep precedence. There is no origin fallback.
78
+
79
+ ### Changed
80
+
81
+ - Human Router guidance and displayed plan steps/pitfalls project the four
82
+ exact MCP identifiers onto `aisa search` / `schema` / `quote` / `call`.
83
+ Surrounding policy text is unchanged. `--json` still prints the unmodified
84
+ application body, including MCP identifiers.
85
+ - Root and Router command help include complete `--input` JSON examples
86
+ (`-f` / `-f -` too), configured-key resolution shared with `run`
87
+ (`AISA_API_KEY`, then `~/.aisa/key`, then legacy login), billable/approval
88
+ limits, and exits `0`/`2`/`1`/`3`. Manifest nodes for the four commands
89
+ include `mcp`, `auth`, `safety`, `exits`, and parseable `examples`; the
90
+ root node includes `router`. Shell `--input` examples use POSIX single
91
+ quotes. Help separates enforced key/input checks from caller instructions;
92
+ the CLI does not reject an unquoted call. Router `mcp` / `auth` / `exits` /
93
+ `examples` attach only to top-level `search` / `schema` / `quote` / `call`,
94
+ not nested `api search` / `twitter search` / `skills search`.
95
+
96
+ ### Deprecated
97
+
98
+ - **`aisa api search`, `aisa api show`, and `aisa run`** keep their previous
99
+ behavior, stdout, and exit semantics. Help, one stderr warning, and
100
+ manifest `deprecated` / `replacement` / `migration` fields mark them as
101
+ not drop-in replacements. `api list`, `api code`, and specialized commands
102
+ are unchanged. Removal will be a separately announced breaking release.
103
+
104
+ ### Added
105
+
106
+ - **`aisa connect`** — a one-shot local page (`npx @aisa-one/cli connect`) to
107
+ wire AIsa MCP servers into local coding agents. Detects Claude Code, Cursor,
108
+ Claude Desktop and Windsurf; Claude Code entries go through `claude mcp add`
109
+ (user scope), the rest through the same config writer as `mcp setup`. The
110
+ process serves one token-guarded page on 127.0.0.1, applies the selection,
111
+ drives the sign-in, and exits — no daemon left behind. With no key stored,
112
+ the run starts with one browser approval (the same flow as `aisa login`)
113
+ that mints the durable CLI key; every MCP entry and the model provider are
114
+ then written with it — no per-server authorization popups. Only if that
115
+ sign-in fails does connect fall back to each client's own OAuth machinery
116
+ (`claude mcp login` per server; `codex mcp add` runs its own flow). A
117
+ configured key skips the sign-in entirely.
118
+ The page follows the AIsa Console design (warm dot-grid, Inter, the
119
+ Console red), groups servers by category with their manifest descriptions,
120
+ shows per-server authorization progress live, and finishes by opening a
121
+ success page with copy-paste example prompts that name each `aisa-*`
122
+ server explicitly so the request routes to AIsa.
123
+ - **`aisa topup [amount]`** — opens the console billing page to add credit,
124
+ deep-linking `?amount=` when one is given and rejecting anything that is not
125
+ a positive number of dollars. Payment finishes in the browser by necessity
126
+ (Stripe's hosted page owns the card details; 3-D Secure needs a browser).
127
+ `aisa balance` now points at it when the account is out of credit.
128
+ - **`aisa login` signs in over OAuth and keeps a real key.** With no
129
+ arguments it opens the browser for one approval, then trades the access
130
+ token for the long-lived CLI key at `POST /v1/keys/mint` and stores only
131
+ the key. `--no-browser` prints the URL and reads the redirect back for
132
+ headless machines; `--key <key>` still stores one directly.
133
+ - **Codex MCP entries carry the key itself, not an env-var name.**
134
+ `codex mcp add --bearer-token-env-var` records only a variable name that
135
+ nothing guarantees a shell exports, so keyed entries could 401 at runtime.
136
+ After the add (which the flag keeps free of OAuth popups), the entry is
137
+ patched to a literal `http_headers` Authorization — the same thing the
138
+ Claude Code path stores via `--header`.
139
+ - The npm tarball includes the MIT `LICENSE` text (Copyright (c) 2026
140
+ AIsa Team). License policy is unchanged.
141
+ - CI on every push/PR builds, tests, and pack-smokes on Ubuntu Node
142
+ 18/20 (legacy compatibility), 22/24 (maintained), and 26 (current).
143
+ `engines` stay `>=18`.
144
+ The tag-triggered publish job uses Node 24. Trusted Publisher on npmjs.com
145
+ is a publish-time prerequisite — this repo has no historical `release.yml`
146
+ success. `prepack` builds the tarball so a clean `npm pack` includes
147
+ `dist` and `LICENSE`. `git push origin vX.Y.Z` is the publish button.
148
+
10
149
  ## [0.3.0] — 2026-08-18
11
150
 
12
151
  ### Fixed
@@ -246,7 +385,10 @@ supports today; nothing here depends on a backend change.
246
385
  - Config commands (`aisa config get|set|list|reset`) and auth
247
386
  (`aisa login|logout|whoami`).
248
387
 
249
- [Unreleased]: https://github.com/AIsa-team/cli/compare/v0.2.4...HEAD
388
+ [Unreleased]: https://github.com/AIsa-team/cli/compare/v0.5.0...HEAD
389
+ [0.5.0]: https://github.com/AIsa-team/cli/compare/v0.3.0...v0.5.0
390
+ [0.4.0]: https://github.com/AIsa-team/cli/compare/v0.3.0...b5c0b04b2a7a2cb9efcb568be5ee5440d7f7d94d
391
+ [0.3.0]: https://github.com/AIsa-team/cli/compare/v0.2.4...v0.3.0
250
392
  [0.2.4]: https://github.com/AIsa-team/cli/compare/v0.2.3...v0.2.4
251
393
  [0.2.3]: https://github.com/AIsa-team/cli/compare/v0.2.2...v0.2.3
252
394
  [0.2.2]: https://github.com/AIsa-team/cli/compare/v0.2.1...v0.2.2
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AIsa Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,8 +1,9 @@
1
1
  # @aisa-one/cli
2
2
 
3
- Command-line access to [AIsa](https://aisa.one): **one API key for 80+ LLMs and
4
- 950+ endpoints** across 29 API providers — finance, web search, social,
5
- research, and video generation.
3
+ Command-line access to [AIsa](https://aisa.one): **one API key** for
4
+ **Claude, GPT, Gemini, DeepSeek, Kimi, GLM** and published Tool Router
5
+ operations. Browse the public provider/endpoint catalog separately;
6
+ catalog metadata is not a substitute for `schema` or `quote`.
6
7
 
7
8
  ## Install
8
9
 
@@ -16,81 +17,130 @@ npm install -g @aisa-one/cli
16
17
  # Authenticate (or set AISA_API_KEY)
17
18
  aisa login --key sk-your-api-key
18
19
 
19
- # See what's available — no API key needed for this part
20
+ # Discover published tools (Router; search/schema may be anonymous)
21
+ aisa search "company facts" --json
22
+ aisa schema get_financial_company_facts --json
23
+
24
+ # Browse the read-only provider/endpoint catalog
20
25
  aisa api list
21
- aisa api search "insider trades"
26
+ aisa api show financial
22
27
 
23
28
  # Chat with any model
24
29
  aisa chat "Explain quantum computing" --model claude-opus-4-6
25
30
 
26
- # Look up a stock
27
- aisa stock AAPL
28
-
29
- # Search the web
30
- aisa web-search "latest AI research"
31
-
32
- # Call any endpoint in the catalog directly
33
- aisa run financial /insider-trades -q "ticker=AAPL"
31
+ # Quote then execute a published Router tool (same request JSON)
32
+ aisa quote --input '{"calls":[{"call_id":"c1","tool":"get_financial_company_facts","arguments":{"ticker":"AAPL"}}]}' --json
33
+ aisa call --input '{"calls":[{"call_id":"c1","tool":"get_financial_company_facts","arguments":{"ticker":"AAPL"}}]}' --json
34
34
  ```
35
35
 
36
36
  Get your API key at
37
37
  [console.aisa.one/api-keys](https://console.aisa.one/api-keys). New accounts
38
38
  receive $5 in free credits.
39
39
 
40
+ Root help lists 21 explicit commands plus implicit `help`. Removed domain
41
+ shortcuts and raw execution names are unknown commands — not aliases and
42
+ not forwarded to `aisa call`.
43
+
44
+ ## Published tools (Tool Router)
45
+
46
+ These four commands are a thin HTTP client for the same Router service MCP
47
+ uses. They do not search the local catalog cache and do not call providers
48
+ directly.
49
+
50
+ | CLI | MCP identifier | POST path |
51
+ |---|---|---|
52
+ | `aisa search` | `AISA_SEARCH_TOOL` | `/v1/tool-router/aisa-search-tool` |
53
+ | `aisa schema` | `AISA_BATCH_GET_SCHEMA` | `/v1/tool-router/aisa-batch-get-schema` |
54
+ | `aisa quote` | `AISA_BATCH_QUOTE` | `/v1/tool-router/aisa-batch-quote` |
55
+ | `aisa call` | `AISA_BATCH_USE` | `/v1/tool-router/aisa-batch-use` |
56
+
57
+ `--json` prints the unmodified application body (MCP identifiers stay).
58
+ Human output maps only those four identifiers onto CLI names. `aisa manifest`
59
+ and `aisa manifest search` / `schema` / `quote` / `call` expose `mcp`, `auth`,
60
+ `enforced`, `safety`, `exits`, and parseable `examples`.
61
+
62
+ Recommended sequence: discover a tool → `aisa schema` when
63
+ `has_full_schema=false` → `aisa quote` → `aisa call`. Quote and call share
64
+ one request shape. **Enforced:** invalid local input exits 2 and is not sent;
65
+ quote and call refuse to run without a configured AIsa API key. **Not
66
+ enforced:** the CLI does not record quotes, approvals, or budget caps and
67
+ does not reject an unquoted call. **Instruction:** do not execute unquoted
68
+ calls; the caller must ensure a matching quote and approval. Quote is a
69
+ price observation, not authorization. A data request or credentials alone is
70
+ not spending approval. Do not invent tool names or guess required values.
71
+ `aisa call` is billable. A missing or failed quote is never free. Estimated
72
+ cost is not a limit. If a hard monetary cap is required, do not execute
73
+ calls with no guaranteed maximum. A partial quote is not a full-batch total;
74
+ call only an independently approved successful subset, and do not silently
75
+ retry. Without a configured AIsa API key, do not invent a business result.
76
+
77
+ `--input` is inline JSON (no file required). Documented shell examples use
78
+ POSIX single quotes so apostrophes, Unicode, `$()`, and backticks stay
79
+ literal.
80
+
81
+ `get_financial_company_facts` is a published tool whose schema includes
82
+ `ticker`. Do not invent unpublished tool names. Router search does not
83
+ guarantee every former domain-shortcut function.
84
+
85
+ ```sh
86
+ aisa search "company facts" --json
87
+ aisa search --input '{"query":"company facts","limit":5}' --json
88
+ aisa search --input '{"query":"company facts","known_fields":{"name":"O'\''Reilly — 苹果"}}' --json
89
+ aisa search -f request.json --json
90
+ aisa search -f - --json < request.json
91
+ aisa schema get_financial_company_facts --json
92
+ aisa schema --input '{"tools":["get_financial_company_facts"]}' --json
93
+ aisa quote --input '{"calls":[{"call_id":"c1","tool":"get_financial_company_facts","arguments":{"ticker":"AAPL"}}]}' --json
94
+ aisa quote -f request.json --json
95
+ aisa call --input '{"calls":[{"call_id":"c1","tool":"get_financial_company_facts","arguments":{"ticker":"AAPL"}}]}' --json
96
+ aisa call -f - --json < request.json
97
+ ```
98
+
99
+ `--json` keeps large integer tokens. Diagnostics go to stderr. Exit `2` means
100
+ local input was invalid and nothing was sent; `1` is transport, auth, or an
101
+ HTTP error; `3` means the Router returned a batch with at least one failed
102
+ item.
103
+
104
+ `search` and `schema` may be anonymous. `quote` and `call` require a
105
+ configured AIsa API key: `AISA_API_KEY`, then `~/.aisa/key`, then legacy
106
+ login. `aisa login` and `AISA_API_KEY` are alternatives. The default Router
107
+ origin is `https://tools.aisa.one` (independent of `baseUrl` /
108
+ `https://api.aisa.one`). Point a test Router at `AISA_ROUTER_BASE_URL` (origin
109
+ or prefix before `/v1/tool-router/...`), or `aisa config set routerUrl`. There
110
+ is no origin fallback.
111
+
112
+ `quote` never executes. Router requests do not follow HTTP redirects, so a
113
+ 307/308 cannot turn quote into call. There is no automatic quote-to-call sequence and no
114
+ retry.
115
+
40
116
  ## API Catalog
41
117
 
42
- The catalog is the fastest way to find what the platform can do. It reads a
43
- public endpoint, so `list`, `show`, `search`, and `code` all work before you log
44
- in.
118
+ `api list` and `api show` are the supported read-only catalog. They browse
119
+ public provider and endpoint metadata (`--json`, `--refresh`, `--health`,
120
+ `--category`, path filters). They are not deprecated and are not Router
121
+ `search` / `schema`. Catalog paths and prices are browsing metadata, not a
122
+ substitute for schema or quote, and not a way to execute an endpoint.
45
123
 
46
124
  ```bash
47
- aisa api list # all 29 providers
125
+ aisa api list # all catalog providers
48
126
  aisa api list --category finance # finance, search, social, productivity, other
49
127
  aisa api list --health # include provider health
50
128
 
51
- aisa api show financial # every endpoint in one provider
52
- aisa api show financial /news # one endpoint: params, price, run command
53
- aisa api show dataforseo --all # 453 endpoints (truncated to 40 by default)
54
-
55
- aisa api search "stock screener" # search across all 950+ endpoints
56
- aisa api search rank --provider dataforseo
57
-
58
- aisa api code financial /news --lang curl # curl, python, node, typescript
129
+ aisa api show financial # endpoints in one provider
130
+ aisa api show financial /news # one endpoint: params and catalog price
131
+ aisa api show dataforseo --all # long lists truncate to 40 by default
59
132
  ```
60
133
 
61
- Two things worth knowing: a provider's **id is not always its URL slug** —
62
- `brave-search` serves `/apis/v1/brave/...`, and `api show` prints the path you
63
- actually call. And the catalog reports every method as `GET`; pass `--method` to
64
- `api code` when an endpoint takes a POST.
134
+ A provider **id is not always its URL slug** — `brave-search` serves
135
+ `/apis/v1/brave/...`, and `api show` prints the catalog path. The catalog
136
+ reports every method as `GET`; treat that as advisory.
65
137
 
66
138
  The catalog is cached in `~/.aisa/cache` (override with `AISA_CACHE_DIR`). Pass
67
139
  `--refresh` to any command to bypass it, or `aisa cache clear`.
68
140
 
69
- ## Execute Any Endpoint
70
-
71
- ```bash
72
- aisa run financial /insider-trades -q "ticker=AAPL"
73
- aisa run coingecko /simple/price -q "ids=bitcoin&vs_currencies=usd"
74
- aisa run brave /web/search -q "q=AI agents"
75
- aisa run tavily /search -d '{"query": "AI news"}'
76
- aisa run twitter /tweet/advanced_search -q "query=AI agents" --raw
77
- aisa run dataforseo /serp/google/organic/live -d '{...}' --show-cost
78
- ```
79
-
80
- `run` sends anything that isn't a known LLM gateway route to the integration
81
- APIs, so providers added to the platform work without a CLI upgrade. Use
82
- `--llm` or `--domain` to force a base.
83
-
84
- `--show-cost` prints the gateway's billing headers on stderr, so it stays out of
85
- the way of `--raw | jq`. Metered providers (DataForSEO, Jina) report the amount
86
- actually charged and the credits consumed — for those the catalog's flat
87
- per-request price is not what you pay. Other routes report only a price key, and
88
- the LLM gateway reports nothing; the output says so rather than implying a call
89
- was free.
90
-
91
141
  ## LLM Gateway
92
142
 
93
- 80+ models (GPT, Claude, Gemini, Qwen, Deepseek, Grok) behind one
143
+ GPT, Claude, Gemini, DeepSeek, Kimi, GLM, Qwen and the rest behind one
94
144
  OpenAI-compatible endpoint.
95
145
 
96
146
  ```bash
@@ -106,91 +156,19 @@ aisa models show gpt-4.1-mini # model details
106
156
 
107
157
  Streaming is on by default; pass `--no-stream` to disable it.
108
158
 
109
- ## Finance
110
-
111
- ```bash
112
- aisa stock AAPL # summary: company info + estimates + news
113
- aisa stock AAPL --field insider # insider trades
114
- aisa stock AAPL --field news # company news
115
- aisa stock TSLA --field filings # SEC filings
116
- aisa stock MSFT --field estimates # analyst EPS & revenue estimates
117
- aisa stock AAPL --field financials # balance sheets, income statements
118
-
119
- aisa crypto BTC # price, 24h change, market cap
120
- aisa crypto ETH --period 30d # historical
121
- aisa crypto --id render-token RNDR # exact CoinGecko id when a symbol is ambiguous
122
-
123
- aisa screener --sector "Information Technology"
124
- aisa screener --min-market-cap 1000000000000 --limit 10
125
- aisa screener --filter market_cap:gt:1e12 --filter sector:eq:Financials
126
- ```
127
-
128
- Sectors use GICS names; short forms like `Technology` are mapped automatically.
129
-
130
- ## Web Search
131
-
132
- ```bash
133
- aisa web-search "query" # Tavily (default)
134
- aisa web-search "query" --type youtube # YouTube search
135
- aisa scholar "transformer architecture" # academic papers
136
- ```
137
-
138
- `--type smart` and `--type full` are currently degraded upstream and return 404
139
- regardless of parameters. Use `tavily` until that is resolved.
140
-
141
- ## Twitter/X
142
-
143
- ```bash
144
- aisa twitter user elonmusk # user profile
145
- aisa twitter search "AI agents" --limit 20 # search tweets
146
- aisa twitter trends # trending topics
147
- aisa twitter user-tweets elonmusk # recent tweets
148
- aisa twitter thread <tweet-id> # full conversation
149
- ```
150
-
151
- Read operations work with just your API key. **Write operations** (`aisa tweet`,
152
- `like`, `retweet`, `follow`, `dm`) additionally require Twitter login cookies
153
- and a proxy — run `aisa twitter login --username <u> --password <p> --proxy <url>`
154
- first. Run `aisa twitter --help` for the full list of 30+ subcommands.
155
-
156
- ## Video Generation
157
-
158
- ```bash
159
- aisa video create "A sunset timelapse" # returns a task id
160
- aisa video create "Dancing robot" --wait # poll until done
161
- aisa video create "A cat" --output cat.mp4 # wait and download
162
- aisa video status <task-id>
163
-
164
- # image-to-video: --image is shorthand for --media first_frame=<url>
165
- aisa video create "the bird turns its head" --model wan2.7-i2v --image https://…/photo.jpg
166
- aisa video create "extend this clip" --model wan2.7-r2v --media first_clip=https://…/in.mp4
167
-
168
- # Seedance uses a different request shape; the CLI handles it
169
- aisa video create "a cat walking" --model dreamina-seedance-2-0-fast-260128
170
- ```
171
-
172
- | Model | Needs | Billing |
173
- |-------|-------|---------|
174
- | `wan2.7-t2v` (default), `happyhorse-1.1-t2v` | prompt only | per second |
175
- | `wan2.7-i2v`, `happyhorse-1.1-i2v` | `--image` / `--media first_frame=` | per second |
176
- | `wan2.7-r2v`, `happyhorse-1.1-r2v` | `--media first_clip=` | per second |
177
- | `dreamina-seedance-2-0-260128`, `…-fast-260128` | prompt only | per token |
178
-
179
- Media types: `first_frame`, `last_frame`, `driving_audio`, `first_clip`.
180
-
181
- The gateway forwards the request body to whichever vendor owns the model, so the
182
- shape differs per family — the CLI builds it for you and refuses up front if a
183
- model needs source media you did not supply (the upstream would otherwise accept
184
- the job, bill it, and fail a minute later). For a vendor or parameter the CLI
185
- does not model, `--body '<json>'` is sent verbatim.
186
-
187
159
  ## Account
188
160
 
189
161
  ```bash
190
162
  aisa balance # wallet and API key credit balance
191
163
  aisa balance --json
164
+ aisa topup # open the console billing page to add credit
165
+ aisa topup 20 # same, deep-linked to $20
192
166
  ```
193
167
 
168
+ Payment always finishes in the browser: card details belong to Stripe's hosted
169
+ page, not to us, and a bank's 3-D Secure step needs one. `topup` opens the
170
+ right page; `--no-open` prints the URL instead.
171
+
194
172
  `aisa usage` is not available yet — the gateway does not serve
195
173
  `GET /v1/credits/usage` (it 404s, while `/v1/credits/balance` on the same route
196
174
  group works). Use the [console](https://console.aisa.one/logs) for usage history
@@ -199,9 +177,8 @@ in the meantime.
199
177
  ## Skills
200
178
 
201
179
  Skills are markdown files that teach AI coding agents (Claude Code, Cursor,
202
- Copilot, …) how to use AIsa APIs. They come from the
203
- [agent-skills](https://github.com/AIsa-team/agent-skills) repository — 42 skills
204
- across six categories.
180
+ Copilot, …) how to use AIsa. They come from the
181
+ [agent-skills](https://github.com/AIsa-team/agent-skills) repository.
205
182
 
206
183
  ```bash
207
184
  aisa skills list # all skills
@@ -244,11 +221,37 @@ aisa skills init my-skill # default template
244
221
  aisa skills init my-skill --template finance # finance, llm, search, twitter, video
245
222
  ```
246
223
 
224
+ Bundled templates may keep those domain labels. Their runnable steps use
225
+ `search` / `schema` / `quote` / `call` (and optional `api list` / `api show`).
226
+ They do not invent tool names or treat Router as a replacement for every
227
+ removed shortcut. The `llm` template stays on `chat` / `models`.
228
+
247
229
  To publish a skill, open a pull request against
248
230
  [AIsa-team/agent-skills](https://github.com/AIsa-team/agent-skills).
249
231
 
250
232
  ## MCP Server
251
233
 
234
+ ### One-liner: `connect`
235
+
236
+ ```bash
237
+ npx @aisa-one/cli connect
238
+ ```
239
+
240
+ Opens a small local page (served by this process on `127.0.0.1`, shut down
241
+ when finished) where you tick the AIsa MCP servers you want and the coding
242
+ agents to install them into. Claude Code is configured through its own
243
+ `claude mcp add` (user scope), then signed in through its own OAuth: connect
244
+ runs `claude mcp login` per server, your browser opens the AIsa
245
+ authorization, and the tokens live in Claude Code's own store where it also
246
+ refreshes them — no API key, nothing pasted. Cursor, Claude Desktop and
247
+ Windsurf get config entries and run the same OAuth themselves on first use.
248
+ The page matches the AIsa Console style, reports authorization progress
249
+ live, and a success page with copy-paste try-it-now prompts opens when
250
+ everything is connected. No daemon stays behind. `--no-open` prints the URL
251
+ instead of launching a browser; `--dry-run` shows what would be written.
252
+
253
+ ### Scripted: `mcp setup`
254
+
252
255
  ```bash
253
256
  aisa mcp setup # configure the default servers for every detected client
254
257
  aisa mcp setup --all # every live server, not just the defaults
@@ -288,12 +291,10 @@ Completion covers commands, subcommands, and options, plus values pulled from
288
291
  the local cache:
289
292
 
290
293
  ```
291
- aisa run <TAB> → 29 provider slugs
292
- aisa run financial <TAB> → that provider's endpoints
293
294
  aisa api show <TAB> → provider ids
294
- aisa skills show <TAB> → 42 skill names
295
+ aisa api list --category <TAB> → finance, search, social, productivity, other
296
+ aisa skills show <TAB> → skill names
295
297
  aisa chat --model <TAB> → model ids
296
- aisa web-search --type <TAB> → tavily, youtube, scholar, …
297
298
  ```
298
299
 
299
300
  The cache-backed suggestions only appear once the relevant command has been run
@@ -314,11 +315,15 @@ Settings:
314
315
  - `defaultModel` — default model for `aisa chat` (default: `gpt-4.1-mini`)
315
316
  - `baseUrl` — platform root; the LLM (`/v1`), integration (`/apis/v1`), and
316
317
  catalog bases are all derived from it
318
+ - `routerUrl` — Tool Router origin (default `https://tools.aisa.one`,
319
+ independent of `baseUrl`); overridden by `AISA_ROUTER_BASE_URL`
317
320
  - `outputFormat` — `text` or `json`
318
321
 
319
322
  Environment variables: `AISA_API_KEY` takes precedence over the stored key.
320
- `AISA_CACHE_DIR` relocates the cache. `GITHUB_TOKEN` raises the GitHub rate
321
- limit for skills commands.
323
+ `AISA_ROUTER_BASE_URL` is the Router origin/prefix before
324
+ `/v1/tool-router/...` and overrides the default `https://tools.aisa.one`.
325
+ `AISA_CACHE_DIR` relocates the cache. `GITHUB_TOKEN`
326
+ raises the GitHub rate limit for skills commands.
322
327
 
323
328
  ## Development
324
329
 
@@ -329,8 +334,12 @@ npm install
329
334
  npm run build # compile TypeScript
330
335
  npm run dev # watch mode
331
336
  npm test # run tests
337
+ npm run package:smoke # clean pack, isolated install, installed-bin checks
332
338
  ```
333
339
 
340
+ Release metadata and the exact merge/tag publish path (not an authorization
341
+ to publish) are in [`docs/release.md`](docs/release.md).
342
+
334
343
  ## Appendix: Notes for Contributors
335
344
 
336
345
  **Three bases, one root.** `resolveBases()` in `src/api.ts` derives the LLM base
@@ -339,12 +348,6 @@ configured `baseUrl`. It tolerates a value with either suffix already attached,
339
348
  because the shipped default has always included `/v1` and is persisted in every
340
349
  existing user's config.
341
350
 
342
- **Routing in `run`.** `resolveRunTarget()` (`src/commands/run.ts`) treats the LLM
343
- gateway routes as the whitelist and everything else as an integration API. That
344
- direction matters: gateway routes are hardcoded server-side and change roughly
345
- annually, while provider slugs are database rows that operations edit
346
- continuously.
347
-
348
351
  **The catalog's shape has three traps.** `endpoints[].method` is hardcoded to
349
352
  `GET` server-side. `endpoint_groups[].name` is an operator-entered label
350
353
  (`Zero`, `One`, `default`) with no business meaning, which is why `api show`
@@ -353,23 +356,9 @@ per-endpoint counts are one value repeated.
353
356
 
354
357
  **Parameter naming varies by endpoint.** Scholar uses `query`, finance uses
355
358
  `ticker` (not `symbol`), Twitter uses `userName`. `aisa api show <api> <path>`
356
- prints each endpoint's description and path parameters.
357
-
358
- **Video generation is async.** `POST /v1/video/generations` returns `202` with a
359
- gateway-local `video_task_<hex>` id. Poll `GET /v1/video/generations/:id` until
360
- `status` is one of `completed`, `failed`, or `cancelled`. The finished URL sits
361
- at a different place in `result` for each vendor, so `findVideoUrl()` searches
362
- for it.
363
-
364
- **Twitter write operations require login cookies.** `create_tweet_v2` and the
365
- other action endpoints need `login_cookies` and `proxy` in the body — the
366
- gateway does not hold your Twitter session.
367
-
368
- **Some financial endpoints return empty data.** `financial/prices` and
369
- `financial/financial-metrics/snapshot` return `{}` for all tickers. `aisa stock`
370
- uses `company/facts` + `analyst-estimates` + `news` instead. Working fields:
371
- `info`, `estimates`, `financials`, `filings`, `insider`, `institutional`, `news`.
359
+ prints each endpoint's description and path parameters. That listing is
360
+ catalog metadata, not an execution recipe.
372
361
 
373
362
  ## License
374
363
 
375
- MIT
364
+ MIT. See [LICENSE](LICENSE). Copyright (c) 2026 AIsa Team.
package/dist/api.d.ts CHANGED
@@ -33,6 +33,16 @@ export interface RequestOptions {
33
33
  headers?: Record<string, string>;
34
34
  /** Use domain API base URL (/apis/v1) instead of LLM base (/v1) */
35
35
  domain?: boolean;
36
+ /**
37
+ * Safe to send more than once, so a transient failure can be retried.
38
+ * Must be set deliberately: this CLI POSTs for reads and for writes alike,
39
+ * and a retried write posts a second tweet or bills a second video job.
40
+ * See utils/http.ts for why `chat` stays out of this even though a
41
+ * completion reads rather than writes.
42
+ */
43
+ idempotent?: boolean;
44
+ /** Overrides the default 30s budget for a slow endpoint. */
45
+ timeoutMs?: number;
36
46
  }
37
47
  export declare function apiRequest<T = unknown>(apiKey: string, endpoint: string, options?: RequestOptions): Promise<ApiResponse<T>>;
38
48
  export declare function apiRequestRaw(apiKey: string, endpoint: string, options?: RequestOptions): Promise<Response>;
package/dist/api.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { BASE_URL } from "./constants.js";
2
+ import { httpFetch, INFO_TIMEOUT_MS } from "./utils/http.js";
2
3
  import { getConfig } from "./config.js";
3
4
  /**
4
5
  * Derive every base path from one configured root.
@@ -55,10 +56,12 @@ export async function apiRequest(apiKey, endpoint, options = {}) {
55
56
  "x-aisa-source": "cli",
56
57
  ...extraHeaders,
57
58
  };
58
- const res = await fetch(url, {
59
+ const res = await httpFetch(url, {
59
60
  method,
60
61
  headers,
61
62
  body: body ? JSON.stringify(body) : undefined,
63
+ idempotent: options.idempotent ?? method === "GET",
64
+ timeoutMs: options.timeoutMs,
62
65
  });
63
66
  if (!res.ok) {
64
67
  const text = await res.text();
@@ -90,10 +93,12 @@ export async function apiRequestRaw(apiKey, endpoint, options = {}) {
90
93
  "x-aisa-source": "cli",
91
94
  ...extraHeaders,
92
95
  };
93
- return fetch(url, {
96
+ return httpFetch(url, {
94
97
  method,
95
98
  headers,
96
99
  body: body ? JSON.stringify(body) : undefined,
100
+ idempotent: options.idempotent ?? method === "GET",
101
+ timeoutMs: options.timeoutMs,
97
102
  });
98
103
  }
99
104
  /**
@@ -116,7 +121,13 @@ export async function publicRequest(path, options = {}) {
116
121
  const headers = { "x-aisa-source": "cli" };
117
122
  if (options.etag)
118
123
  headers["If-None-Match"] = options.etag;
119
- const res = await fetch(`${resolveBases().info}/${path.replace(/^\/+/, "")}`, { headers });
124
+ // Catalog and pricing are unauthenticated GETs against a cache — retrying
125
+ // one is free, and failing one degrades every discovery command.
126
+ const res = await httpFetch(`${resolveBases().info}/${path.replace(/^\/+/, "")}`, {
127
+ headers,
128
+ idempotent: true,
129
+ timeoutMs: INFO_TIMEOUT_MS,
130
+ });
120
131
  if (res.status === 304)
121
132
  return { status: 304 };
122
133
  if (!res.ok)