@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
@@ -7,12 +7,13 @@ import { expandHome, ensureDir, writeSkillFiles, removeDir, detectAgents } from
7
7
  import { AGENT_DIRS } from "../constants.js";
8
8
  import { SKILLS_REPO, getSkillIndex, listSkills, resolveSlug, leafName, fetchSkillFiles, fetchSkillMarkdown, parseSkillFrontmatter, } from "../skills-registry.js";
9
9
  // --- Skill Templates (for init) ---
10
+ // Domain labels may stay; runnable steps use retained commands only.
10
11
  const TEMPLATES = {
11
12
  default: `---
12
13
  name: my-skill
13
14
  description: "Describe what this skill does."
14
15
  homepage: https://aisa.one
15
- metadata: {"aisa":{"emoji":"","requires":{"bins":["curl"],"env":["AISA_API_KEY"]},"primaryEnv":"AISA_API_KEY","compatibility":["openclaw","claude-code","hermes"]}}
16
+ metadata: {"aisa":{"emoji":"","requires":{"bins":["aisa"],"env":["AISA_API_KEY"]},"primaryEnv":"AISA_API_KEY","compatibility":["openclaw","claude-code","hermes"]}}
16
17
  ---
17
18
 
18
19
  # My Skill
@@ -25,17 +26,39 @@ Describe how an AI agent should use this skill.
25
26
  export AISA_API_KEY=sk-your-key
26
27
  \`\`\`
27
28
 
28
- ## Usage
29
+ Same key as \`aisa login\`: \`AISA_API_KEY\`, then \`~/.aisa/key\`, then legacy login.
30
+
31
+ ## Published tools
32
+
33
+ Discover → schema when needed → quote → authorized call. Do not invent tool names.
34
+ \`get_financial_company_facts\` is a published tool whose schema includes \`ticker\`.
35
+ Quote is not authorization. \`aisa call\` is billable.
29
36
 
30
37
  \`\`\`bash
31
- aisa run <slug> <path> -q "param=value"
38
+ aisa search --input '{"query":"company facts"}' --json
39
+ aisa schema --input '{"tools":["get_financial_company_facts"]}' --json
40
+ aisa quote --input '{"calls":[{"call_id":"c1","tool":"get_financial_company_facts","arguments":{"ticker":"AAPL"}}]}' --json
41
+ aisa call --input '{"calls":[{"call_id":"c1","tool":"get_financial_company_facts","arguments":{"ticker":"AAPL"}}]}' --json
42
+ aisa quote -f request.json --json
43
+ aisa call -f - --json < request.json
44
+ \`\`\`
45
+
46
+ ## Provider catalog
47
+
48
+ Read-only browse. Paths and prices are metadata, not a substitute for schema or quote.
49
+
50
+ \`\`\`bash
51
+ aisa api list
52
+ aisa api list --category finance
53
+ aisa api show financial
54
+ aisa api show financial /news
32
55
  \`\`\`
33
56
  `,
34
57
  llm: `---
35
58
  name: llm-assistant
36
59
  description: "Use AIsa's unified LLM gateway to chat with 70+ AI models."
37
60
  homepage: https://aisa.one
38
- metadata: {"aisa":{"emoji":"🤖","requires":{"bins":["curl"],"env":["AISA_API_KEY"]},"primaryEnv":"AISA_API_KEY","compatibility":["openclaw","claude-code","hermes"]}}
61
+ metadata: {"aisa":{"emoji":"🤖","requires":{"bins":["aisa"],"env":["AISA_API_KEY"]},"primaryEnv":"AISA_API_KEY","compatibility":["openclaw","claude-code","hermes"]}}
39
62
  ---
40
63
 
41
64
  # LLM Assistant Skill
@@ -69,14 +92,16 @@ aisa models --provider anthropic
69
92
  `,
70
93
  search: `---
71
94
  name: web-search
72
- description: "Search the web, YouTube, and academic papers via AIsa APIs."
95
+ description: "Discover published AIsa tools for web and research queries, then schema/quote/call."
73
96
  homepage: https://aisa.one
74
- metadata: {"aisa":{"emoji":"🔍","requires":{"bins":["curl"],"env":["AISA_API_KEY"]},"primaryEnv":"AISA_API_KEY","compatibility":["openclaw","claude-code","hermes"]}}
97
+ metadata: {"aisa":{"emoji":"🔍","requires":{"bins":["aisa"],"env":["AISA_API_KEY"]},"primaryEnv":"AISA_API_KEY","compatibility":["openclaw","claude-code","hermes"]}}
75
98
  ---
76
99
 
77
100
  # Web Search Skill
78
101
 
79
- Search the web, YouTube, and academic papers through AIsa's unified search APIs.
102
+ Discover published Router tools for web or research questions. Use a tool name
103
+ exactly as search returned it. Do not invent names. Router does not guarantee
104
+ every former search-provider function.
80
105
 
81
106
  ## Authentication
82
107
 
@@ -84,34 +109,39 @@ Search the web, YouTube, and academic papers through AIsa's unified search APIs.
84
109
  export AISA_API_KEY=sk-your-key
85
110
  \`\`\`
86
111
 
87
- ## Smart Search
112
+ ## Discover, inspect, quote, then call
88
113
 
89
114
  \`\`\`bash
90
- aisa web-search "latest AI research" --type tavily
115
+ aisa search "web search" --json
116
+ aisa search "academic papers" --json
117
+ aisa schema --input '{"tools":["<exact tool from search>"]}' --json
118
+ aisa quote --input '{"calls":[{"call_id":"c1","tool":"<exact tool from search>","arguments":{}}]}' --json
119
+ aisa call --input '{"calls":[{"call_id":"c1","tool":"<exact tool from search>","arguments":{}}]}' --json
91
120
  \`\`\`
92
121
 
93
- ## YouTube Search
94
-
95
- \`\`\`bash
96
- aisa web-search "machine learning tutorial" --type youtube
97
- \`\`\`
122
+ Fill arguments from schema. Quote is not authorization. \`aisa call\` is billable.
98
123
 
99
- ## Scholar Search
124
+ Optional catalog browse (not a substitute for schema or quote):
100
125
 
101
126
  \`\`\`bash
102
- aisa scholar "transformer architecture"
127
+ aisa api list --category search
128
+ aisa api show <provider>
103
129
  \`\`\`
104
130
  `,
105
131
  finance: `---
106
132
  name: finance-analyst
107
- description: "Access stock prices, earnings, SEC filings, and financial data via AIsa."
133
+ description: "Discover published AIsa finance tools, then schema/quote/call."
108
134
  homepage: https://aisa.one
109
- metadata: {"aisa":{"emoji":"📊","requires":{"bins":["curl"],"env":["AISA_API_KEY"]},"primaryEnv":"AISA_API_KEY","compatibility":["openclaw","claude-code","hermes"]}}
135
+ metadata: {"aisa":{"emoji":"📊","requires":{"bins":["aisa"],"env":["AISA_API_KEY"]},"primaryEnv":"AISA_API_KEY","compatibility":["openclaw","claude-code","hermes"]}}
110
136
  ---
111
137
 
112
138
  # Finance Analyst Skill
113
139
 
114
- Access real-time and historical financial data through AIsa's finance APIs.
140
+ Discover published Router tools for financial questions. Do not invent tool
141
+ names. Router does not guarantee every former stock, crypto, or screener
142
+ shortcut.
143
+
144
+ \`get_financial_company_facts\` is a published tool whose schema includes \`ticker\`.
115
145
 
116
146
  ## Authentication
117
147
 
@@ -119,31 +149,36 @@ Access real-time and historical financial data through AIsa's finance APIs.
119
149
  export AISA_API_KEY=sk-your-key
120
150
  \`\`\`
121
151
 
122
- ## Stock Prices
152
+ ## Discover, inspect, quote, then call
123
153
 
124
154
  \`\`\`bash
125
- aisa stock AAPL
126
- aisa stock MSFT --field earnings
127
- aisa stock TSLA --field filings
155
+ aisa search "company facts" --json
156
+ aisa schema get_financial_company_facts --json
157
+ aisa quote --input '{"calls":[{"call_id":"c1","tool":"get_financial_company_facts","arguments":{"ticker":"AAPL"}}]}' --json
158
+ aisa call --input '{"calls":[{"call_id":"c1","tool":"get_financial_company_facts","arguments":{"ticker":"AAPL"}}]}' --json
128
159
  \`\`\`
129
160
 
130
- ## Crypto Prices
161
+ Quote is not authorization. \`aisa call\` is billable.
162
+
163
+ Optional catalog browse (not a substitute for schema or quote):
131
164
 
132
165
  \`\`\`bash
133
- aisa crypto BTC
134
- aisa crypto ETH --period 30d
166
+ aisa api list --category finance
167
+ aisa api show financial
135
168
  \`\`\`
136
169
  `,
137
170
  twitter: `---
138
171
  name: twitter-manager
139
- description: "Search Twitter, get user profiles and trends via AIsa."
172
+ description: "Discover published AIsa social tools, then schema/quote/call."
140
173
  homepage: https://aisa.one
141
- metadata: {"aisa":{"emoji":"🐦","requires":{"bins":["curl"],"env":["AISA_API_KEY"]},"primaryEnv":"AISA_API_KEY","compatibility":["openclaw","claude-code","hermes"]}}
174
+ metadata: {"aisa":{"emoji":"🐦","requires":{"bins":["aisa"],"env":["AISA_API_KEY"]},"primaryEnv":"AISA_API_KEY","compatibility":["openclaw","claude-code","hermes"]}}
142
175
  ---
143
176
 
144
177
  # Twitter Manager Skill
145
178
 
146
- Interact with Twitter/X through AIsa's Twitter APIs.
179
+ Discover published Router tools for social or Twitter/X questions. Use a tool
180
+ name exactly as search returned it. Do not invent names. Router does not
181
+ guarantee every former Twitter CLI function.
147
182
 
148
183
  ## Authentication
149
184
 
@@ -151,34 +186,36 @@ Interact with Twitter/X through AIsa's Twitter APIs.
151
186
  export AISA_API_KEY=sk-your-key
152
187
  \`\`\`
153
188
 
154
- ## Search Tweets
189
+ ## Discover, inspect, quote, then call
155
190
 
156
191
  \`\`\`bash
157
- aisa twitter search "AI agents" --limit 20
192
+ aisa search "twitter" --json
193
+ aisa schema --input '{"tools":["<exact tool from search>"]}' --json
194
+ aisa quote --input '{"calls":[{"call_id":"c1","tool":"<exact tool from search>","arguments":{}}]}' --json
195
+ aisa call --input '{"calls":[{"call_id":"c1","tool":"<exact tool from search>","arguments":{}}]}' --json
158
196
  \`\`\`
159
197
 
160
- ## Get User Profile
198
+ Fill arguments from schema. Quote is not authorization. \`aisa call\` is billable.
161
199
 
162
- \`\`\`bash
163
- aisa twitter user elonmusk
164
- \`\`\`
165
-
166
- ## Trending Topics
200
+ Optional catalog browse (not a substitute for schema or quote):
167
201
 
168
202
  \`\`\`bash
169
- aisa twitter trends
203
+ aisa api list --category social
204
+ aisa api show <provider>
170
205
  \`\`\`
171
206
  `,
172
207
  video: `---
173
208
  name: video-generator
174
- description: "Generate videos from text prompts using AIsa's video synthesis API."
209
+ description: "Discover published AIsa media tools, then schema/quote/call."
175
210
  homepage: https://aisa.one
176
- metadata: {"aisa":{"emoji":"🎬","requires":{"bins":["curl"],"env":["AISA_API_KEY"]},"primaryEnv":"AISA_API_KEY","compatibility":["openclaw","claude-code","hermes"]}}
211
+ metadata: {"aisa":{"emoji":"🎬","requires":{"bins":["aisa"],"env":["AISA_API_KEY"]},"primaryEnv":"AISA_API_KEY","compatibility":["openclaw","claude-code","hermes"]}}
177
212
  ---
178
213
 
179
214
  # Video Generator Skill
180
215
 
181
- Generate videos from text prompts using AIsa's AI video generation APIs.
216
+ Discover published Router tools for media or video questions. Use a tool name
217
+ exactly as search returned it. Do not invent names. Router does not guarantee
218
+ former video-generation CLI functions.
182
219
 
183
220
  ## Authentication
184
221
 
@@ -186,22 +223,22 @@ Generate videos from text prompts using AIsa's AI video generation APIs.
186
223
  export AISA_API_KEY=sk-your-key
187
224
  \`\`\`
188
225
 
189
- ## Create Video
226
+ ## Discover, inspect, quote, then call
190
227
 
191
228
  \`\`\`bash
192
- aisa video create "A cat playing piano in a jazz bar"
229
+ aisa search "video generation" --json
230
+ aisa schema --input '{"tools":["<exact tool from search>"]}' --json
231
+ aisa quote --input '{"calls":[{"call_id":"c1","tool":"<exact tool from search>","arguments":{}}]}' --json
232
+ aisa call --input '{"calls":[{"call_id":"c1","tool":"<exact tool from search>","arguments":{}}]}' --json
193
233
  \`\`\`
194
234
 
195
- ## Create and Wait for Result
196
-
197
- \`\`\`bash
198
- aisa video create "Sunset over mountains timelapse" --wait
199
- \`\`\`
235
+ Fill arguments from schema. Quote is not authorization. \`aisa call\` is billable.
200
236
 
201
- ## Check Task Status
237
+ Optional catalog browse (not a substitute for schema or quote):
202
238
 
203
239
  \`\`\`bash
204
- aisa video status <task-id>
240
+ aisa api list
241
+ aisa api show <provider>
205
242
  \`\`\`
206
243
  `,
207
244
  };
@@ -0,0 +1,69 @@
1
+ import type { RouterOperation } from "../router.js";
2
+ /** Published catalog tool whose schema includes `ticker`. Used only in examples. */
3
+ export declare const EXAMPLE_PUBLISHED_TOOL = "get_financial_company_facts";
4
+ export declare const EXAMPLE_SEARCH: {
5
+ query: string;
6
+ };
7
+ export declare const EXAMPLE_SEARCH_LIMIT: {
8
+ query: string;
9
+ limit: number;
10
+ };
11
+ /** Inline JSON with an apostrophe and Unicode; no file required. */
12
+ export declare const EXAMPLE_SEARCH_QUOTED: {
13
+ query: string;
14
+ known_fields: {
15
+ name: string;
16
+ };
17
+ };
18
+ export declare const EXAMPLE_SCHEMA: {
19
+ tools: string[];
20
+ };
21
+ export declare const EXAMPLE_BATCH: {
22
+ calls: {
23
+ call_id: string;
24
+ tool: string;
25
+ arguments: {
26
+ ticker: string;
27
+ };
28
+ }[];
29
+ };
30
+ export declare const EXAMPLE_SEARCH_JSON: string;
31
+ export declare const EXAMPLE_SEARCH_LIMIT_JSON: string;
32
+ export declare const EXAMPLE_SEARCH_QUOTED_JSON: string;
33
+ export declare const EXAMPLE_SCHEMA_JSON: string;
34
+ export declare const EXAMPLE_BATCH_JSON: string;
35
+ export declare const ROUTER_EXITS: {
36
+ readonly "0": "success";
37
+ readonly "2": "invalid local input (nothing sent)";
38
+ readonly "1": "transport, auth, or HTTP error";
39
+ readonly "3": "HTTP 200 with any failed batch item";
40
+ };
41
+ export interface RouterExample {
42
+ argv: string[];
43
+ input?: Record<string, unknown>;
44
+ }
45
+ export interface RouterCommandContract {
46
+ auth: "optional" | "required";
47
+ sameRequestShapeAs?: "quote" | "call";
48
+ flow: string;
49
+ /** Runtime checks that actually stop the command. */
50
+ enforced: string[];
51
+ /** Caller instructions. The CLI does not enforce these. */
52
+ safety: string[];
53
+ examples: RouterExample[];
54
+ }
55
+ export declare function routerContract(kind: RouterOperation): RouterCommandContract;
56
+ /** Path after `aisa`. Only the four top-level Router commands. */
57
+ export declare function routerContractFor(commandPath: string): RouterCommandContract | undefined;
58
+ /**
59
+ * POSIX sh single-quoting. Nothing inside single quotes expands ($(),
60
+ * backticks, parameters). A literal apostrophe is '\'' (end, escaped quote, resume).
61
+ */
62
+ export declare function posixSingleQuote(value: string): string;
63
+ /** `--input` plus POSIX-single-quoted JSON for documented shell examples. */
64
+ export declare function shellInputFlag(json: string): string;
65
+ export declare function searchHelpAfter(): string;
66
+ export declare function schemaHelpAfter(): string;
67
+ export declare function quoteHelpAfter(): string;
68
+ export declare function callHelpAfter(): string;
69
+ export declare function rootHelpAfter(): string;
@@ -0,0 +1,189 @@
1
+ import { MCP_CLI_MAP } from "../cli-guidance.js";
2
+ /** Published catalog tool whose schema includes `ticker`. Used only in examples. */
3
+ export const EXAMPLE_PUBLISHED_TOOL = "get_financial_company_facts";
4
+ export const EXAMPLE_SEARCH = { query: "company facts" };
5
+ export const EXAMPLE_SEARCH_LIMIT = { query: "company facts", limit: 5 };
6
+ /** Inline JSON with an apostrophe and Unicode; no file required. */
7
+ export const EXAMPLE_SEARCH_QUOTED = {
8
+ query: "company facts",
9
+ known_fields: { name: "O'Reilly — 苹果" },
10
+ };
11
+ export const EXAMPLE_SCHEMA = { tools: [EXAMPLE_PUBLISHED_TOOL] };
12
+ export const EXAMPLE_BATCH = {
13
+ calls: [
14
+ {
15
+ call_id: "c1",
16
+ tool: EXAMPLE_PUBLISHED_TOOL,
17
+ arguments: { ticker: "AAPL" },
18
+ },
19
+ ],
20
+ };
21
+ export const EXAMPLE_SEARCH_JSON = JSON.stringify(EXAMPLE_SEARCH);
22
+ export const EXAMPLE_SEARCH_LIMIT_JSON = JSON.stringify(EXAMPLE_SEARCH_LIMIT);
23
+ export const EXAMPLE_SEARCH_QUOTED_JSON = JSON.stringify(EXAMPLE_SEARCH_QUOTED);
24
+ export const EXAMPLE_SCHEMA_JSON = JSON.stringify(EXAMPLE_SCHEMA);
25
+ export const EXAMPLE_BATCH_JSON = JSON.stringify(EXAMPLE_BATCH);
26
+ export const ROUTER_EXITS = {
27
+ "0": "success",
28
+ "2": "invalid local input (nothing sent)",
29
+ "1": "transport, auth, or HTTP error",
30
+ "3": "HTTP 200 with any failed batch item",
31
+ };
32
+ const FLOW = "Recommended sequence: aisa search → aisa schema when has_full_schema=false → aisa quote → aisa call.";
33
+ const INLINE = "--input is inline JSON text (no file required). Shell examples are POSIX sh with single-quoted --input; apostrophes are written as '\\'' so $(), backticks, and other expansions stay literal. -f FILE and -f - remain available.";
34
+ const JSON_CONTRACT = "--json writes the unmodified application body, including MCP identifiers and numeric tokens. Human output maps only AISA_SEARCH_TOOL, AISA_BATCH_GET_SCHEMA, AISA_BATCH_QUOTE, and AISA_BATCH_USE to aisa search / schema / quote / call.";
35
+ const KEY_RESOLUTION = "AISA_API_KEY, then ~/.aisa/key, then legacy login. aisa login and AISA_API_KEY are alternatives.";
36
+ const ENFORCED_OPTIONAL = `Enforced: invalid local input exits 2 and is not sent. A configured AIsa API key is optional (${KEY_RESOLUTION}).`;
37
+ const ENFORCED_REQUIRED = `Enforced: quote and call refuse to run without a configured AIsa API key (${KEY_RESOLUTION}). Invalid local input exits 2 and is not sent. search and schema may be anonymous.`;
38
+ const NOT_ENFORCED = "Not enforced: the CLI does not record quotes, approvals, or budget caps and does not reject an unquoted aisa call.";
39
+ const INSTRUCTION_UNQUOTED = "Instruction: Do not execute unquoted calls; the caller must ensure a matching quote and approval.";
40
+ const EXITS = "Exits: 0 success; 2 invalid local input (nothing sent); 1 transport, auth, or HTTP error; 3 HTTP 200 with any failed batch item.";
41
+ function example(kind, input) {
42
+ return { argv: [kind, "--input", JSON.stringify(input), "--json"], input };
43
+ }
44
+ export function routerContract(kind) {
45
+ switch (kind) {
46
+ case "search":
47
+ return {
48
+ auth: "optional",
49
+ flow: FLOW,
50
+ enforced: [ENFORCED_OPTIONAL],
51
+ safety: [
52
+ "Instruction: Do not invent tool names. Do not guess required unresolved values; ask, and do not call.",
53
+ ],
54
+ examples: [
55
+ example("search", EXAMPLE_SEARCH),
56
+ example("search", EXAMPLE_SEARCH_LIMIT),
57
+ example("search", EXAMPLE_SEARCH_QUOTED),
58
+ ],
59
+ };
60
+ case "schema":
61
+ return {
62
+ auth: "optional",
63
+ flow: `Use after search when has_full_schema=false. Pass exact tool names from search. ${EXAMPLE_PUBLISHED_TOOL} is a published tool whose schema includes ticker.`,
64
+ enforced: [ENFORCED_OPTIONAL],
65
+ safety: [
66
+ "Instruction: Do not invent tool names. Do not guess arguments; read the returned schema.",
67
+ ],
68
+ examples: [example("schema", EXAMPLE_SCHEMA)],
69
+ };
70
+ case "quote":
71
+ return {
72
+ auth: "required",
73
+ sameRequestShapeAs: "call",
74
+ flow: FLOW,
75
+ enforced: [ENFORCED_REQUIRED],
76
+ safety: [
77
+ NOT_ENFORCED,
78
+ "Same request shape as aisa call.",
79
+ "Quote does not execute. Quote is not authorization to execute.",
80
+ "A data request or credentials alone is not spending approval.",
81
+ INSTRUCTION_UNQUOTED,
82
+ "Instruction: A missing or failed quote is never free. Estimated cost is not a limit. If a hard monetary cap is required, do not execute calls that have no guaranteed maximum.",
83
+ "Instruction: A partial quote is not a full-batch total. Do not treat a successful-subset subtotal as the full-batch total.",
84
+ ],
85
+ examples: [example("quote", EXAMPLE_BATCH)],
86
+ };
87
+ case "call":
88
+ return {
89
+ auth: "required",
90
+ sameRequestShapeAs: "quote",
91
+ flow: FLOW,
92
+ enforced: [ENFORCED_REQUIRED],
93
+ safety: [
94
+ NOT_ENFORCED,
95
+ "Same request shape as aisa quote. Re-quote if tools, arguments, or scope change.",
96
+ INSTRUCTION_UNQUOTED,
97
+ "Instruction: aisa call is billable; the caller must ensure a matching quote plus explicit approval covering that cost and any uncertainty.",
98
+ "Instruction: A missing or failed quote is never free.",
99
+ "A data request or credentials alone is not spending approval.",
100
+ "Instruction: Call only an independently approved successful subset. Do not silently retry or expand the set.",
101
+ "Instruction: Without a configured AIsa API key, do not invent a business result.",
102
+ ],
103
+ examples: [example("call", EXAMPLE_BATCH)],
104
+ };
105
+ }
106
+ }
107
+ /** Path after `aisa`. Only the four top-level Router commands. */
108
+ export function routerContractFor(commandPath) {
109
+ if (commandPath === "search" ||
110
+ commandPath === "schema" ||
111
+ commandPath === "quote" ||
112
+ commandPath === "call") {
113
+ return routerContract(commandPath);
114
+ }
115
+ return undefined;
116
+ }
117
+ function mcpLine(kind) {
118
+ const op = MCP_CLI_MAP[kind];
119
+ return `MCP: ${op.identifier} → ${op.cli} (POST ${op.path})`;
120
+ }
121
+ /**
122
+ * POSIX sh single-quoting. Nothing inside single quotes expands ($(),
123
+ * backticks, parameters). A literal apostrophe is '\'' (end, escaped quote, resume).
124
+ */
125
+ export function posixSingleQuote(value) {
126
+ return `'${value.replace(/'/g, `'\\''`)}'`;
127
+ }
128
+ /** `--input` plus POSIX-single-quoted JSON for documented shell examples. */
129
+ export function shellInputFlag(json) {
130
+ return `--input ${posixSingleQuote(json)}`;
131
+ }
132
+ function humanExamples(kind, extras) {
133
+ const lines = [...extras];
134
+ for (const ex of routerContract(kind).examples) {
135
+ if (ex.input)
136
+ lines.push(` $ aisa ${kind} ${shellInputFlag(JSON.stringify(ex.input))} --json`);
137
+ }
138
+ lines.push(` $ aisa ${kind} -f request.json --json`);
139
+ lines.push(` $ aisa ${kind} -f - --json < request.json`);
140
+ return lines.join("\n");
141
+ }
142
+ function helpBody(kind, extras) {
143
+ const c = routerContract(kind);
144
+ return `
145
+ ${mcpLine(kind)}
146
+ ${JSON_CONTRACT}
147
+
148
+ ${c.flow}
149
+ ${c.enforced.join("\n")}
150
+ ${c.safety.join("\n")}
151
+ ${INLINE}
152
+
153
+ Examples (POSIX sh; single-quoted --input):
154
+ ${humanExamples(kind, extras)}
155
+
156
+ ${EXITS}
157
+ Machine readers: aisa manifest ${kind}
158
+ `;
159
+ }
160
+ export function searchHelpAfter() {
161
+ return helpBody("search", [` $ aisa search "company facts" --json`]);
162
+ }
163
+ export function schemaHelpAfter() {
164
+ return helpBody("schema", [` $ aisa schema ${EXAMPLE_PUBLISHED_TOOL} --json`]);
165
+ }
166
+ export function quoteHelpAfter() {
167
+ return helpBody("quote", []);
168
+ }
169
+ export function callHelpAfter() {
170
+ return helpBody("call", []);
171
+ }
172
+ export function rootHelpAfter() {
173
+ return `
174
+ Examples (POSIX sh; single-quoted --input):
175
+ $ aisa connect wire your coding agent to AIsa (start here)
176
+ $ aisa search "company facts" --json
177
+ $ aisa schema ${EXAMPLE_PUBLISHED_TOOL} --json
178
+ $ aisa quote ${shellInputFlag(EXAMPLE_BATCH_JSON)} --json
179
+ $ aisa call ${shellInputFlag(EXAMPLE_BATCH_JSON)} --json
180
+ $ aisa api list browse the provider catalog
181
+ $ aisa api show coingecko browse one provider's endpoints
182
+
183
+ Router: ${MCP_CLI_MAP.search.identifier}→search, ${MCP_CLI_MAP.schema.identifier}→schema, ${MCP_CLI_MAP.quote.identifier}→quote, ${MCP_CLI_MAP.call.identifier}→call.
184
+ --json keeps MCP identifiers. Human output maps those four names to CLI commands.
185
+ ${FLOW}
186
+ Use aisa <command> --help or aisa manifest <command> for complete JSON/file/stdin examples, shared API-key sources, exit codes, and cost constraints.
187
+ Catalog list/show are browsing metadata, not a substitute for schema or quote.
188
+ `;
189
+ }
@@ -0,0 +1,22 @@
1
+ export type RouterKind = "search" | "schema" | "quote" | "call";
2
+ export interface RouterIoOptions {
3
+ input?: string;
4
+ file?: string;
5
+ json?: boolean;
6
+ limit?: string;
7
+ provider?: string[];
8
+ includeArgumentsSchema?: boolean;
9
+ includeResponseSchema?: boolean;
10
+ }
11
+ export interface PreparedRequest {
12
+ /** Raw application JSON sent to Router. */
13
+ body: string;
14
+ /** Parsed envelope for local validation and human rendering only. */
15
+ value: Record<string, unknown>;
16
+ }
17
+ /**
18
+ * Resolve one request body from operands, --input, or -f.
19
+ * Conflicting sources are a usage error and must not dispatch.
20
+ */
21
+ export declare function prepareRouterRequest(kind: RouterKind, operands: string[], options: RouterIoOptions): Promise<PreparedRequest>;
22
+ export declare function validateEnvelope(kind: RouterKind, value: Record<string, unknown>): void;