@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.
- package/CHANGELOG.md +143 -1
- package/LICENSE +21 -0
- package/README.md +151 -162
- package/dist/api.d.ts +10 -0
- package/dist/api.js +14 -3
- package/dist/catalog.d.ts +1 -18
- package/dist/catalog.js +1 -24
- package/dist/cli-error.d.ts +17 -0
- package/dist/cli-error.js +25 -0
- package/dist/cli-guidance.d.ts +14 -0
- package/dist/cli-guidance.js +55 -0
- package/dist/commands/account.d.ts +17 -0
- package/dist/commands/account.js +45 -1
- package/dist/commands/api.d.ts +0 -11
- package/dist/commands/api.js +6 -175
- package/dist/commands/auth.d.ts +2 -1
- package/dist/commands/auth.js +43 -9
- package/dist/commands/brand-logos.d.ts +6 -0
- package/dist/commands/brand-logos.js +21 -0
- package/dist/commands/configCmd.js +8 -3
- package/dist/commands/connect-shared.d.ts +136 -0
- package/dist/commands/connect-shared.js +143 -0
- package/dist/commands/connect-t2.d.ts +18 -0
- package/dist/commands/connect-t2.js +1599 -0
- package/dist/commands/connect-terminal.d.ts +65 -0
- package/dist/commands/connect-terminal.js +822 -0
- package/dist/commands/connect.d.ts +31 -0
- package/dist/commands/connect.js +3181 -0
- package/dist/commands/flow.d.ts +685 -0
- package/dist/commands/flow.js +697 -0
- package/dist/commands/install.d.ts +91 -0
- package/dist/commands/install.js +258 -0
- package/dist/commands/llm-config.d.ts +103 -0
- package/dist/commands/llm-config.js +452 -0
- package/dist/commands/manifest.d.ts +68 -0
- package/dist/commands/manifest.js +90 -0
- package/dist/commands/mcp.d.ts +59 -0
- package/dist/commands/mcp.js +122 -44
- package/dist/commands/oauth-login.d.ts +33 -0
- package/dist/commands/oauth-login.js +333 -0
- package/dist/commands/prompt.d.ts +96 -0
- package/dist/commands/prompt.js +397 -0
- package/dist/commands/serve-results.d.ts +61 -0
- package/dist/commands/serve-results.js +245 -0
- package/dist/commands/serve-signin.d.ts +28 -0
- package/dist/commands/serve-signin.js +90 -0
- package/dist/commands/signin-page.d.ts +49 -0
- package/dist/commands/signin-page.js +250 -0
- package/dist/commands/skills.js +87 -50
- package/dist/commands/tool-help.d.ts +69 -0
- package/dist/commands/tool-help.js +189 -0
- package/dist/commands/tool-input.d.ts +22 -0
- package/dist/commands/tool-input.js +220 -0
- package/dist/commands/tools.d.ts +12 -0
- package/dist/commands/tools.js +307 -0
- package/dist/commands/update.d.ts +11 -0
- package/dist/commands/update.js +92 -0
- package/dist/commands/vscode.d.ts +65 -0
- package/dist/commands/vscode.js +173 -0
- package/dist/commands/wrappers.d.ts +23 -0
- package/dist/commands/wrappers.js +102 -0
- package/dist/completion.js +3 -80
- package/dist/config.js +76 -2
- package/dist/constants.d.ts +51 -38
- package/dist/constants.js +53 -109
- package/dist/index.js +152 -355
- package/dist/json-text.d.ts +12 -0
- package/dist/json-text.js +60 -0
- package/dist/router.d.ts +39 -0
- package/dist/router.js +59 -0
- package/dist/skills-registry.js +12 -3
- package/dist/utils/banner.d.ts +9 -0
- package/dist/utils/banner.js +41 -0
- package/dist/utils/browser.d.ts +19 -0
- package/dist/utils/browser.js +31 -0
- package/dist/utils/exec.d.ts +43 -0
- package/dist/utils/exec.js +61 -0
- package/dist/utils/http.d.ts +53 -0
- package/dist/utils/http.js +124 -0
- package/dist/utils/install-method.d.ts +36 -0
- package/dist/utils/install-method.js +48 -0
- package/dist/utils/journal.d.ts +57 -0
- package/dist/utils/journal.js +188 -0
- package/dist/utils/key-check.d.ts +20 -0
- package/dist/utils/key-check.js +24 -0
- package/dist/utils/update-check.d.ts +23 -0
- package/dist/utils/update-check.js +116 -0
- package/dist/utils/width.d.ts +32 -0
- package/dist/utils/width.js +73 -0
- package/package.json +8 -4
- package/vscode-extension/README.md +6 -0
- package/vscode-extension/aisa-vscode.vsix +0 -0
- package/dist/commands/finance.d.ts +0 -17
- package/dist/commands/finance.js +0 -342
- package/dist/commands/run.d.ts +0 -28
- package/dist/commands/run.js +0 -182
- package/dist/commands/search.d.ts +0 -9
- package/dist/commands/search.js +0 -81
- package/dist/commands/twitter.d.ts +0 -138
- package/dist/commands/twitter.js +0 -374
- package/dist/commands/video.d.ts +0 -49
- 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.
|
|
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
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
#
|
|
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
|
|
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
|
-
#
|
|
27
|
-
aisa
|
|
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
|
-
|
|
43
|
-
public endpoint
|
|
44
|
-
|
|
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
|
|
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 #
|
|
52
|
-
aisa api show financial /news # one endpoint: params
|
|
53
|
-
aisa api show dataforseo --all #
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
-
|
|
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
|
|
203
|
-
[agent-skills](https://github.com/AIsa-team/agent-skills) repository
|
|
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
|
|
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
|
-
`
|
|
321
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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)
|