expandai 0.0.0 → 0.0.2

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 (209) hide show
  1. package/README.md +241 -6
  2. package/build/dts/ApiClient.d.ts +231 -0
  3. package/build/dts/ApiClient.d.ts.map +1 -0
  4. package/build/dts/Authentication.d.ts +23 -0
  5. package/build/dts/Authentication.d.ts.map +1 -0
  6. package/build/dts/BrowserOAuth.d.ts +99 -0
  7. package/build/dts/BrowserOAuth.d.ts.map +1 -0
  8. package/build/dts/Commands/Fetch.d.ts +30 -0
  9. package/build/dts/Commands/Fetch.d.ts.map +1 -0
  10. package/build/dts/Commands/Hook.d.ts +17 -0
  11. package/build/dts/Commands/Hook.d.ts.map +1 -0
  12. package/build/dts/Commands/Mcp.d.ts +11 -0
  13. package/build/dts/Commands/Mcp.d.ts.map +1 -0
  14. package/build/dts/Commands/McpRun.d.ts +5 -0
  15. package/build/dts/Commands/McpRun.d.ts.map +1 -0
  16. package/build/dts/Commands/Search.d.ts +21 -0
  17. package/build/dts/Commands/Search.d.ts.map +1 -0
  18. package/build/dts/Commands/Skill.d.ts +12 -0
  19. package/build/dts/Commands/Skill.d.ts.map +1 -0
  20. package/build/dts/Commands/Uninstall.d.ts +9 -0
  21. package/build/dts/Commands/Uninstall.d.ts.map +1 -0
  22. package/build/dts/Config.d.ts +105 -0
  23. package/build/dts/Config.d.ts.map +1 -0
  24. package/build/dts/DeviceAuth.d.ts +87 -0
  25. package/build/dts/DeviceAuth.d.ts.map +1 -0
  26. package/build/dts/Hook/Claude.d.ts +13 -0
  27. package/build/dts/Hook/Claude.d.ts.map +1 -0
  28. package/build/dts/Hook/Errors.d.ts +20 -0
  29. package/build/dts/Hook/Errors.d.ts.map +1 -0
  30. package/build/dts/Hook/Opencode.d.ts +13 -0
  31. package/build/dts/Hook/Opencode.d.ts.map +1 -0
  32. package/build/dts/Hook/SnapshotNote.d.ts +8 -0
  33. package/build/dts/Hook/SnapshotNote.d.ts.map +1 -0
  34. package/build/dts/Install/Claude/Hook.d.ts +60 -0
  35. package/build/dts/Install/Claude/Hook.d.ts.map +1 -0
  36. package/build/dts/Install/Claude/Mcp.d.ts +45 -0
  37. package/build/dts/Install/Claude/Mcp.d.ts.map +1 -0
  38. package/build/dts/Install/Claude/Skill.d.ts +24 -0
  39. package/build/dts/Install/Claude/Skill.d.ts.map +1 -0
  40. package/build/dts/Install/Codex/Mcp.d.ts +39 -0
  41. package/build/dts/Install/Codex/Mcp.d.ts.map +1 -0
  42. package/build/dts/Install/Codex/Skill.d.ts +20 -0
  43. package/build/dts/Install/Codex/Skill.d.ts.map +1 -0
  44. package/build/dts/Install/Cursor/Mcp.d.ts +45 -0
  45. package/build/dts/Install/Cursor/Mcp.d.ts.map +1 -0
  46. package/build/dts/Install/Cursor/Skill.d.ts +27 -0
  47. package/build/dts/Install/Cursor/Skill.d.ts.map +1 -0
  48. package/build/dts/Install/Domain.d.ts +73 -0
  49. package/build/dts/Install/Domain.d.ts.map +1 -0
  50. package/build/dts/Install/Hook.d.ts +30 -0
  51. package/build/dts/Install/Hook.d.ts.map +1 -0
  52. package/build/dts/Install/Mcp.d.ts +28 -0
  53. package/build/dts/Install/Mcp.d.ts.map +1 -0
  54. package/build/dts/Install/Opencode/Hook.d.ts +23 -0
  55. package/build/dts/Install/Opencode/Hook.d.ts.map +1 -0
  56. package/build/dts/Install/Opencode/Mcp.d.ts +47 -0
  57. package/build/dts/Install/Opencode/Mcp.d.ts.map +1 -0
  58. package/build/dts/Install/Opencode/Skill.d.ts +24 -0
  59. package/build/dts/Install/Opencode/Skill.d.ts.map +1 -0
  60. package/build/dts/Install/Skill.d.ts +32 -0
  61. package/build/dts/Install/Skill.d.ts.map +1 -0
  62. package/build/dts/Install/Uninstall.d.ts +32 -0
  63. package/build/dts/Install/Uninstall.d.ts.map +1 -0
  64. package/build/dts/Mcp/ExpandDocs.d.ts +7 -0
  65. package/build/dts/Mcp/ExpandDocs.d.ts.map +1 -0
  66. package/build/dts/Mcp/RequestHeaders.d.ts +15 -0
  67. package/build/dts/Mcp/RequestHeaders.d.ts.map +1 -0
  68. package/build/dts/Mcp/Server.d.ts +10 -0
  69. package/build/dts/Mcp/Server.d.ts.map +1 -0
  70. package/build/dts/Mcp/Toolkit.d.ts +3 -0
  71. package/build/dts/Mcp/Toolkit.d.ts.map +1 -0
  72. package/build/dts/Mcp/tools/Citations.d.ts +237 -0
  73. package/build/dts/Mcp/tools/Citations.d.ts.map +1 -0
  74. package/build/dts/Mcp/tools/Fetch.d.ts +167 -0
  75. package/build/dts/Mcp/tools/Fetch.d.ts.map +1 -0
  76. package/build/dts/Snippets.d.ts +19 -0
  77. package/build/dts/Snippets.d.ts.map +1 -0
  78. package/build/dts/index.d.ts +2 -0
  79. package/build/dts/index.d.ts.map +1 -0
  80. package/build/dts/main.d.ts +3 -0
  81. package/build/dts/main.d.ts.map +1 -0
  82. package/build/esm/ApiClient.js +182 -0
  83. package/build/esm/ApiClient.js.map +1 -0
  84. package/build/esm/Authentication.js +112 -0
  85. package/build/esm/Authentication.js.map +1 -0
  86. package/build/esm/BrowserOAuth.js +254 -0
  87. package/build/esm/BrowserOAuth.js.map +1 -0
  88. package/build/esm/Commands/Fetch.js +95 -0
  89. package/build/esm/Commands/Fetch.js.map +1 -0
  90. package/build/esm/Commands/Hook.js +20 -0
  91. package/build/esm/Commands/Hook.js.map +1 -0
  92. package/build/esm/Commands/Mcp.js +19 -0
  93. package/build/esm/Commands/Mcp.js.map +1 -0
  94. package/build/esm/Commands/McpRun.js +15 -0
  95. package/build/esm/Commands/McpRun.js.map +1 -0
  96. package/build/esm/Commands/Search.js +43 -0
  97. package/build/esm/Commands/Search.js.map +1 -0
  98. package/build/esm/Commands/Skill.js +17 -0
  99. package/build/esm/Commands/Skill.js.map +1 -0
  100. package/build/esm/Commands/Uninstall.js +28 -0
  101. package/build/esm/Commands/Uninstall.js.map +1 -0
  102. package/build/esm/Config.js +145 -0
  103. package/build/esm/Config.js.map +1 -0
  104. package/build/esm/DeviceAuth.js +127 -0
  105. package/build/esm/DeviceAuth.js.map +1 -0
  106. package/build/esm/Hook/Claude.js +74 -0
  107. package/build/esm/Hook/Claude.js.map +1 -0
  108. package/build/esm/Hook/Errors.js +18 -0
  109. package/build/esm/Hook/Errors.js.map +1 -0
  110. package/build/esm/Hook/Opencode.js +50 -0
  111. package/build/esm/Hook/Opencode.js.map +1 -0
  112. package/build/esm/Hook/SnapshotNote.js +18 -0
  113. package/build/esm/Hook/SnapshotNote.js.map +1 -0
  114. package/build/esm/Install/Claude/Hook.js +89 -0
  115. package/build/esm/Install/Claude/Hook.js.map +1 -0
  116. package/build/esm/Install/Claude/Mcp.js +71 -0
  117. package/build/esm/Install/Claude/Mcp.js.map +1 -0
  118. package/build/esm/Install/Claude/Skill.js +34 -0
  119. package/build/esm/Install/Claude/Skill.js.map +1 -0
  120. package/build/esm/Install/Codex/Mcp.js +92 -0
  121. package/build/esm/Install/Codex/Mcp.js.map +1 -0
  122. package/build/esm/Install/Codex/Skill.js +30 -0
  123. package/build/esm/Install/Codex/Skill.js.map +1 -0
  124. package/build/esm/Install/Cursor/Mcp.js +71 -0
  125. package/build/esm/Install/Cursor/Mcp.js.map +1 -0
  126. package/build/esm/Install/Cursor/Skill.js +37 -0
  127. package/build/esm/Install/Cursor/Skill.js.map +1 -0
  128. package/build/esm/Install/Domain.js +105 -0
  129. package/build/esm/Install/Domain.js.map +1 -0
  130. package/build/esm/Install/Hook.js +38 -0
  131. package/build/esm/Install/Hook.js.map +1 -0
  132. package/build/esm/Install/Mcp.js +40 -0
  133. package/build/esm/Install/Mcp.js.map +1 -0
  134. package/build/esm/Install/Opencode/Hook.js +44 -0
  135. package/build/esm/Install/Opencode/Hook.js.map +1 -0
  136. package/build/esm/Install/Opencode/Mcp.js +73 -0
  137. package/build/esm/Install/Opencode/Mcp.js.map +1 -0
  138. package/build/esm/Install/Opencode/Skill.js +34 -0
  139. package/build/esm/Install/Opencode/Skill.js.map +1 -0
  140. package/build/esm/Install/Opencode/expandai-webfetch.js +38 -0
  141. package/build/esm/Install/Skill.js +41 -0
  142. package/build/esm/Install/Skill.js.map +1 -0
  143. package/build/esm/Install/Uninstall.js +49 -0
  144. package/build/esm/Install/Uninstall.js.map +1 -0
  145. package/build/esm/Mcp/ExpandDocs.js +64 -0
  146. package/build/esm/Mcp/ExpandDocs.js.map +1 -0
  147. package/build/esm/Mcp/RequestHeaders.js +13 -0
  148. package/build/esm/Mcp/RequestHeaders.js.map +1 -0
  149. package/build/esm/Mcp/Server.js +11 -0
  150. package/build/esm/Mcp/Server.js.map +1 -0
  151. package/build/esm/Mcp/Toolkit.js +16 -0
  152. package/build/esm/Mcp/Toolkit.js.map +1 -0
  153. package/build/esm/Mcp/tools/Citations.js +92 -0
  154. package/build/esm/Mcp/tools/Citations.js.map +1 -0
  155. package/build/esm/Mcp/tools/Fetch.js +141 -0
  156. package/build/esm/Mcp/tools/Fetch.js.map +1 -0
  157. package/build/esm/Snippets.js +18 -0
  158. package/build/esm/Snippets.js.map +1 -0
  159. package/build/esm/index.js +2 -0
  160. package/build/esm/index.js.map +1 -0
  161. package/build/esm/main.js +97 -0
  162. package/build/esm/main.js.map +1 -0
  163. package/build/skills/expandai/SKILL.md +72 -0
  164. package/package.json +72 -10
  165. package/src/ApiClient.ts +257 -0
  166. package/src/Authentication.ts +164 -0
  167. package/src/BrowserOAuth.ts +361 -0
  168. package/src/Commands/Fetch.ts +157 -0
  169. package/src/Commands/Hook.ts +48 -0
  170. package/src/Commands/Mcp.ts +30 -0
  171. package/src/Commands/McpRun.ts +25 -0
  172. package/src/Commands/Search.ts +92 -0
  173. package/src/Commands/Skill.ts +30 -0
  174. package/src/Commands/Uninstall.ts +38 -0
  175. package/src/Config.ts +195 -0
  176. package/src/DeviceAuth.ts +193 -0
  177. package/src/Hook/Claude.ts +81 -0
  178. package/src/Hook/Errors.ts +19 -0
  179. package/src/Hook/Opencode.ts +58 -0
  180. package/src/Hook/SnapshotNote.ts +18 -0
  181. package/src/Install/Claude/Hook.ts +133 -0
  182. package/src/Install/Claude/Mcp.ts +82 -0
  183. package/src/Install/Claude/Skill.ts +44 -0
  184. package/src/Install/Codex/Mcp.ts +109 -0
  185. package/src/Install/Codex/Skill.ts +40 -0
  186. package/src/Install/Cursor/Mcp.ts +82 -0
  187. package/src/Install/Cursor/Skill.ts +47 -0
  188. package/src/Install/Domain.ts +148 -0
  189. package/src/Install/Hook.ts +50 -0
  190. package/src/Install/Mcp.ts +71 -0
  191. package/src/Install/Opencode/Hook.ts +55 -0
  192. package/src/Install/Opencode/Mcp.ts +84 -0
  193. package/src/Install/Opencode/Skill.ts +44 -0
  194. package/src/Install/Opencode/expandai-webfetch.d.ts +23 -0
  195. package/src/Install/Opencode/expandai-webfetch.js +38 -0
  196. package/src/Install/Skill.ts +57 -0
  197. package/src/Install/Uninstall.ts +82 -0
  198. package/src/Mcp/ExpandDocs.ts +71 -0
  199. package/src/Mcp/RequestHeaders.ts +16 -0
  200. package/src/Mcp/Server.ts +14 -0
  201. package/src/Mcp/Toolkit.ts +21 -0
  202. package/src/Mcp/tools/Citations.ts +110 -0
  203. package/src/Mcp/tools/Fetch.ts +177 -0
  204. package/src/Snippets.ts +32 -0
  205. package/src/index.ts +1 -0
  206. package/src/main.ts +146 -0
  207. package/bun.lockb +0 -0
  208. package/index.ts +0 -1
  209. package/tsconfig.json +0 -27
package/README.md CHANGED
@@ -1,15 +1,250 @@
1
- # ts-sdk
1
+ # expandai
2
2
 
3
- To install dependencies:
3
+ Unified CLI and MCP server for [ExpandAI](https://expand.ai). Fetch any URL as
4
+ clean markdown, and wire ExpandAI into Claude Code, Cursor, OpenCode, or Codex
5
+ as an MCP server, a runtime webfetch hook, or a skill.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ bun install -g expandai
11
+ # or
12
+ npm install -g expandai
13
+ ```
14
+
15
+ The binary is published as `expandai`. One-off use without install:
16
+
17
+ ```bash
18
+ bunx expandai fetch https://example.com
19
+ ```
20
+
21
+ ## Standalone binary
22
+
23
+ A self-contained `expandai` executable is published with each release — no
24
+ Node, Bun, or npm required at runtime. One command detects your platform,
25
+ downloads the right binary from GitHub Releases, and drops it on your
26
+ `PATH`:
27
+
28
+ ```bash
29
+ curl -fsSL https://raw.githubusercontent.com/expandai/expandai-cli/main/install.sh | bash
30
+ ```
31
+
32
+ Then:
33
+
34
+ ```bash
35
+ expandai whoami
36
+ ```
37
+
38
+ The binary bundles everything `expandai mcp run`, `expandai hook claude-code`,
39
+ and `expandai hook opencode` need at runtime, so the MCP server and webfetch
40
+ hooks work straight from `PATH` — no `node`/`bun` needed in your agent's
41
+ environment.
42
+
43
+ ## Quick start
44
+
45
+ ```bash
46
+ expandai login # interactive auth
47
+ expandai fetch https://docs.example.com/api # full markdown
48
+ expandai fetch https://docs.example.com/api --search auth # semantic snippets
49
+ ```
50
+
51
+ ## Supported harnesses
52
+
53
+ | Harness | MCP server | Webfetch hook | Skill |
54
+ |-------------|:----------:|:-------------:|:-----:|
55
+ | Claude Code | ✓ | ✓ | ✓ |
56
+ | OpenCode | ✓ | ✓ | ✓ |
57
+ | Cursor | ✓ | — | ✓ |
58
+ | Codex | ✓ | — | ✓ |
59
+
60
+ **Pick one — each integration works standalone.** In rough preference order:
61
+
62
+ 1. **Hook** (Claude Code, OpenCode). `expandai hook install <host> <scope>`
63
+ — best invisible upgrade: every native web fetch the agent issues comes
64
+ back as ExpandAI markdown, no prompt changes required. Also wires the MCP
65
+ server in the same step. See [Recommended: `hook install`](#recommended-hook-install).
66
+ 2. **Skill** (all four harnesses). `expandai skill install <host> <scope>`
67
+ — lightest-weight: drops a `SKILL.md` that teaches the agent when to
68
+ reach for `expandai fetch`.
69
+ 3. **MCP server** (all four harnesses). `expandai mcp install <host> <scope>`
70
+ — exposes the full `fetch` API (snippets, screenshots, structured
71
+ extraction) as an MCP-callable tool.
72
+
73
+ Combinations are fine — installing skill on top of hook, for example, nudges
74
+ the agent to use `mcp__expandai__fetch` for refinement on top of the
75
+ automatic substitution — but any single one is a complete setup.
76
+
77
+ ### Scopes
78
+
79
+ Every `install` / `uninstall` command takes a `<scope>` argument: `global`
80
+ or `project`.
81
+
82
+ - `global` — written under your `$HOME`. Applies to every session of the
83
+ harness, regardless of where the agent is launched. Pick this if you want
84
+ ExpandAI on by default everywhere.
85
+ - `project` — written under the current working directory. Applies only
86
+ when the harness is launched from inside that directory (or a
87
+ subdirectory). Pick this when you want different projects to opt in
88
+ independently, or when the integration should live in version control
89
+ alongside the project.
90
+
91
+ The exact files each scope touches differ per harness and per integration —
92
+ see the path comment next to each `install` line in the sections below.
93
+
94
+ ## Authentication
95
+
96
+ ```bash
97
+ expandai login # OAuth (browser device flow) or API key
98
+ expandai whoami # show current auth state
99
+ expandai logout # clear credentials and optionally remove installed integrations
100
+ ```
101
+
102
+ Credentials are stored at `$XDG_CONFIG_HOME/expandai/config.json` (default
103
+ `~/.config/expandai/config.json`, mode `0600`).
104
+
105
+ Environment overrides:
106
+
107
+ - `EXPAND_API_KEY` — overrides the stored auth method.
108
+ - `EXPAND_API_URL` — overrides the API endpoint (defaults to `https://api.expand.ai`).
109
+
110
+ ## fetch
111
+
112
+ `expandai fetch <url>` returns the rendered page as markdown. Handles
113
+ JavaScript-heavy SPAs and bot-protected sites that plain `curl` can't read.
4
114
 
5
115
  ```bash
6
- bun install
116
+ expandai fetch https://example.com # markdown (default)
117
+ expandai fetch example.com # https:// is added automatically
118
+ expandai fetch https://example.com --format json # full response with metadata
119
+ expandai fetch https://docs.example.com/api --search "authentication"
7
120
  ```
8
121
 
9
- To run:
122
+ Flags:
123
+
124
+ - `--format text|json` — output mode (default `text`).
125
+ - `--search <query>` — semantic search. Returns relevant snippets instead of the full page.
126
+ - `--max-results <n>` — snippet count when `--search` is set. Default `5`, max `50`.
127
+ - `--min-score <n>` — minimum relevance score, `0`–`1`. Default `0.6`.
128
+
129
+ ## Recommended: `hook install`
130
+
131
+ `expandai hook install <host> <scope>` is the ideal setup on harnesses that
132
+ support it. One command, two effects:
133
+
134
+ 1. **Installs a runtime webfetch hook** that intercepts the agent's *native*
135
+ web-fetch tool and silently substitutes ExpandAI's markdown for whatever
136
+ the agent would have fetched on its own.
137
+ 2. **Registers the MCP server** at `<scope>` so the agent can also explicitly
138
+ call `mcp__expandai__fetch` for the full `select` API (markdown, snippets,
139
+ screenshot, links, JSON extraction, etc.).
10
140
 
11
141
  ```bash
12
- bun run index.ts
142
+ expandai hook install claude-code global
143
+ expandai hook install opencode project
13
144
  ```
14
145
 
15
- This project was created using `bun init` in bun v1.1.4. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
146
+ **Scope behavior:** `global` writes to the harness's user settings
147
+ (`~/.claude/settings.json` for Claude Code, `~/.config/opencode/plugins/` for
148
+ OpenCode) — the substitution fires for every session of that harness on the
149
+ machine. `project` writes to per-directory equivalents
150
+ (`<cwd>/.claude/settings.json`, `<cwd>/.opencode/plugins/`) — the
151
+ substitution only fires when the harness is launched from that directory.
152
+
153
+ ### Why both, not just one
154
+
155
+ - The **runtime hook** makes the agent's native fetch path return ExpandAI
156
+ markdown automatically, so even agents that haven't been told about
157
+ expand.ai get clean rendered output for SPAs and bot-protected pages.
158
+ No prompt changes required.
159
+ - The **MCP server alone** requires the agent to consciously choose
160
+ `mcp__expandai__fetch` over its built-in tool, which it usually won't
161
+ unless something nudges it (a skill, a prompt).
162
+ - Together, default web access is upgraded transparently, and explicit
163
+ refinement (snippets, screenshots, structured extraction) is still one
164
+ MCP tool call away.
165
+
166
+ ### How the substitution actually works
167
+
168
+ - **Claude Code** — `expandai hook install claude-code <scope>` writes a
169
+ `PreToolUse` matcher into `settings.json` that scopes to `WebFetch`. When
170
+ the agent invokes `WebFetch`, the runner reads the SDK's hook payload from
171
+ stdin, fetches the URL via expand.ai, and emits
172
+ `{ permissionDecision: "deny", additionalContext: <markdown> }`. The denial
173
+ blocks the native fetch; `additionalContext` is the documented channel for
174
+ injecting content into the model's next turn, so the markdown still reaches
175
+ the model in place of WebFetch's raw output.
176
+ - **OpenCode** — `expandai hook install opencode <scope>` copies an
177
+ `expandai-webfetch.js` plugin into `.opencode/plugins/`. The plugin hooks
178
+ `tool.execute.after` on `webfetch`, shells out to `expandai hook opencode`
179
+ with the URL, and overwrites `output.output` with the returned markdown.
180
+ (`tool.execute.before` can only mutate args, not replace results, which is
181
+ why we run in `after`.)
182
+
183
+ Cursor and Codex don't expose a hook system, so `hook install` only accepts
184
+ `claude-code` and `opencode`. For those harnesses, use `skill install` +
185
+ `mcp install` instead.
186
+
187
+ ## Skill
188
+
189
+ The CLI ships a `SKILL.md` that teaches an agent when to reach for
190
+ `expandai fetch`. `SKILL.md` is the open-standard format that Claude Code,
191
+ Cursor, OpenCode, and Codex auto-discover for tool guidance.
192
+
193
+ ```bash
194
+ expandai skill install claude-code global # ~/.claude/skills/expandai/
195
+ expandai skill install cursor project # <cwd>/.cursor/skills/expandai/
196
+ expandai skill install opencode global # ~/.config/opencode/skills/expandai/
197
+ expandai skill install codex project # <cwd>/.agents/skills/expandai/
198
+ ```
199
+
200
+ **Scope behavior:** `global` drops `SKILL.md` into the harness's user-level
201
+ skills directory, so the agent auto-discovers it in every session. `project`
202
+ drops it into the cwd-level skills directory, so it's only discovered when
203
+ the harness is launched from that directory — useful for committing the
204
+ skill alongside a project so collaborators pick it up automatically.
205
+
206
+ ## MCP server
207
+
208
+ `expandai mcp run` speaks MCP over stdio. Any MCP-aware client can call the
209
+ `fetch` tool, which exposes the full `select` API (markdown, snippets,
210
+ screenshot, links, JSON extraction, etc.).
211
+
212
+ `hook install` already registers the MCP server on Claude Code and OpenCode,
213
+ so this command is mostly for Cursor and Codex, or for installing the MCP
214
+ server without the runtime hook:
215
+
216
+ ```bash
217
+ expandai mcp install claude-code global # ~/.claude.json
218
+ expandai mcp install claude-code project # <cwd>/.mcp.json
219
+ expandai mcp install cursor global # ~/.cursor/mcp.json
220
+ expandai mcp install cursor project # <cwd>/.cursor/mcp.json
221
+ expandai mcp install opencode global # ~/.config/opencode/opencode.json
222
+ expandai mcp install opencode project # <cwd>/opencode.json
223
+ expandai mcp install codex global # ~/.codex/config.toml
224
+ expandai mcp install codex project # <cwd>/.codex/config.toml
225
+ ```
226
+
227
+ **Scope behavior:** `global` writes the `expandai` entry to the harness's
228
+ user-level MCP config — the server is discoverable in every session.
229
+ `project` writes to the per-directory MCP config — the server is only
230
+ discoverable when the harness is launched from that directory, and the
231
+ config file is well-suited for checking into version control.
232
+
233
+ `expandai mcp uninstall <host> <scope>` removes the entry without touching
234
+ other servers in the same config file.
235
+
236
+ ## Uninstall
237
+
238
+ ```bash
239
+ expandai uninstall # everything across every host and scope
240
+ expandai uninstall hook # all hooks (claude-code + opencode)
241
+ expandai uninstall mcp cursor global # just the Cursor global MCP entry
242
+ expandai uninstall skill # all skills across all hosts and scopes
243
+ ```
244
+
245
+ `expandai logout` also offers an interactive multi-select cleanup when run in
246
+ a TTY.
247
+
248
+ ## License
249
+
250
+ Apache-2.0. See `LICENSE`.
@@ -0,0 +1,231 @@
1
+ import { HttpClient } from '@effect/platform';
2
+ import * as Generated from '@expandai/sdk/Generated';
3
+ import { Effect, Schema } from 'effect';
4
+ import { BrowserOAuthService } from './BrowserOAuth.js';
5
+ import { ConfigManager, OAuthTokenExpired } from './Config.js';
6
+ declare const ApiRequestFailed_base: Schema.TaggedErrorClass<ApiRequestFailed, "ApiRequestFailed", {
7
+ readonly _tag: Schema.tag<"ApiRequestFailed">;
8
+ } & {
9
+ detail: typeof Schema.String;
10
+ }>;
11
+ /**
12
+ * Single user-facing error for any failure crossing the API boundary. The
13
+ * generated client raises a half-dozen status-specific tagged classes plus
14
+ * transport/decode errors; we collapse them here so the rest of the app sees
15
+ * one tag with a ready-made `.message` and never has to know about
16
+ * `Generated.ts` types.
17
+ */
18
+ export declare class ApiRequestFailed extends ApiRequestFailed_base {
19
+ get message(): string;
20
+ }
21
+ declare const OAuthAuthMethodChanged_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
22
+ readonly _tag: "OAuthAuthMethodChanged";
23
+ } & Readonly<A>;
24
+ declare class OAuthAuthMethodChanged extends OAuthAuthMethodChanged_base<Record<string, never>> {
25
+ }
26
+ declare const ApiClient_base: Effect.Service.Class<ApiClient, "@expandai/cli/ApiClient", {
27
+ readonly dependencies: readonly [import("effect/Layer").Layer<HttpClient.HttpClient, never, never>, import("effect/Layer").Layer<ConfigManager, import("effect/ConfigError").ConfigError, never>, import("effect/Layer").Layer<BrowserOAuthService, import("effect/ConfigError").ConfigError, never>];
28
+ readonly scoped: Effect.Effect<{
29
+ readonly fetchFetch: (options: {
30
+ readonly params: {
31
+ readonly include?: string | null | undefined;
32
+ };
33
+ readonly payload: {
34
+ readonly url: string;
35
+ readonly search?: {
36
+ readonly query: string;
37
+ readonly maxResults?: number | null | undefined;
38
+ readonly minScore?: number | null | undefined;
39
+ } | null | undefined;
40
+ readonly include?: {
41
+ readonly response?: {
42
+ readonly includeHeaders?: boolean | null | undefined;
43
+ } | null | undefined;
44
+ readonly meta?: boolean | null | undefined;
45
+ readonly markdown?: boolean | {
46
+ readonly [x: string]: unknown;
47
+ } | null | undefined;
48
+ readonly json?: boolean | null | undefined;
49
+ readonly appendix?: boolean | null | undefined;
50
+ readonly links?: boolean | {
51
+ readonly sameDomainOnly?: boolean | null | undefined;
52
+ readonly includePatterns?: readonly string[] | null | undefined;
53
+ readonly excludePatterns?: readonly string[] | null | undefined;
54
+ } | null | undefined;
55
+ readonly screenshot?: boolean | {
56
+ readonly fullPage?: boolean | null | undefined;
57
+ } | null | undefined;
58
+ readonly html?: boolean | {
59
+ readonly [x: string]: unknown;
60
+ } | null | undefined;
61
+ readonly summary?: boolean | {
62
+ readonly prompt?: string | null | undefined;
63
+ } | null | undefined;
64
+ } | null | undefined;
65
+ readonly browserConfig?: {
66
+ readonly scrollFullPage?: boolean | null | undefined;
67
+ } | null | undefined;
68
+ };
69
+ }) => Effect.Effect<string, import("./Config.js").ConfigNotWritable | import("./Config.js").ConfigParseError | import("./Config.js").NotAuthenticated | OAuthTokenExpired | import("effect/ConfigError").ConfigError | import("effect/ParseResult").ParseError | import("@effect/platform/Error").PlatformError | import("./BrowserOAuth.js").BrowserOAuthRequestFailed | ApiRequestFailed | OAuthAuthMethodChanged, never>;
70
+ readonly fetchFetchResult: (options: {
71
+ readonly params: {
72
+ readonly include?: string | null | undefined;
73
+ };
74
+ readonly payload: {
75
+ readonly url: string;
76
+ readonly search?: {
77
+ readonly query: string;
78
+ readonly maxResults?: number | null | undefined;
79
+ readonly minScore?: number | null | undefined;
80
+ } | null | undefined;
81
+ readonly include?: {
82
+ readonly response?: {
83
+ readonly includeHeaders?: boolean | null | undefined;
84
+ } | null | undefined;
85
+ readonly meta?: boolean | null | undefined;
86
+ readonly markdown?: boolean | {
87
+ readonly [x: string]: unknown;
88
+ } | null | undefined;
89
+ readonly json?: boolean | null | undefined;
90
+ readonly appendix?: boolean | null | undefined;
91
+ readonly links?: boolean | {
92
+ readonly sameDomainOnly?: boolean | null | undefined;
93
+ readonly includePatterns?: readonly string[] | null | undefined;
94
+ readonly excludePatterns?: readonly string[] | null | undefined;
95
+ } | null | undefined;
96
+ readonly screenshot?: boolean | {
97
+ readonly fullPage?: boolean | null | undefined;
98
+ } | null | undefined;
99
+ readonly html?: boolean | {
100
+ readonly [x: string]: unknown;
101
+ } | null | undefined;
102
+ readonly summary?: boolean | {
103
+ readonly prompt?: string | null | undefined;
104
+ } | null | undefined;
105
+ } | null | undefined;
106
+ readonly browserConfig?: {
107
+ readonly scrollFullPage?: boolean | null | undefined;
108
+ } | null | undefined;
109
+ };
110
+ }) => Effect.Effect<import("@expandai/sdk/FetchJson").FetchObjectModeResultWithJson, import("./Config.js").ConfigNotWritable | import("./Config.js").ConfigParseError | import("./Config.js").NotAuthenticated | OAuthTokenExpired | import("effect/ConfigError").ConfigError | import("effect/ParseResult").ParseError | import("@effect/platform/Error").PlatformError | import("./BrowserOAuth.js").BrowserOAuthRequestFailed | ApiRequestFailed | OAuthAuthMethodChanged, never>;
111
+ readonly fetchFetchJson: (options: {
112
+ readonly params: {
113
+ readonly include?: string | null | undefined;
114
+ };
115
+ readonly payload: {
116
+ readonly url: string;
117
+ readonly search?: {
118
+ readonly query: string;
119
+ readonly maxResults?: number | null | undefined;
120
+ readonly minScore?: number | null | undefined;
121
+ } | null | undefined;
122
+ readonly include?: {
123
+ readonly response?: {
124
+ readonly includeHeaders?: boolean | null | undefined;
125
+ } | null | undefined;
126
+ readonly meta?: boolean | null | undefined;
127
+ readonly markdown?: boolean | {
128
+ readonly [x: string]: unknown;
129
+ } | null | undefined;
130
+ readonly json?: boolean | null | undefined;
131
+ readonly appendix?: boolean | null | undefined;
132
+ readonly links?: boolean | {
133
+ readonly sameDomainOnly?: boolean | null | undefined;
134
+ readonly includePatterns?: readonly string[] | null | undefined;
135
+ readonly excludePatterns?: readonly string[] | null | undefined;
136
+ } | null | undefined;
137
+ readonly screenshot?: boolean | {
138
+ readonly fullPage?: boolean | null | undefined;
139
+ } | null | undefined;
140
+ readonly html?: boolean | {
141
+ readonly [x: string]: unknown;
142
+ } | null | undefined;
143
+ readonly summary?: boolean | {
144
+ readonly prompt?: string | null | undefined;
145
+ } | null | undefined;
146
+ } | null | undefined;
147
+ readonly browserConfig?: {
148
+ readonly scrollFullPage?: boolean | null | undefined;
149
+ } | null | undefined;
150
+ };
151
+ }) => Effect.Effect<import("@expandai/sdk/FetchJson").FetchObjectModeResultWithJson, import("./Config.js").ConfigNotWritable | import("./Config.js").ConfigParseError | import("./Config.js").NotAuthenticated | OAuthTokenExpired | import("effect/ConfigError").ConfigError | import("effect/ParseResult").ParseError | import("@effect/platform/Error").PlatformError | import("./BrowserOAuth.js").BrowserOAuthRequestFailed | ApiRequestFailed | OAuthAuthMethodChanged, never>;
152
+ readonly fetchFetchSearch: (options: {
153
+ readonly search: {
154
+ readonly query: string;
155
+ readonly maxResults?: number | null | undefined;
156
+ readonly minScore?: number | null | undefined;
157
+ };
158
+ readonly snapshotId: string;
159
+ readonly include?: {
160
+ readonly response?: {
161
+ readonly includeHeaders?: boolean | null | undefined;
162
+ } | null | undefined;
163
+ readonly meta?: boolean | null | undefined;
164
+ readonly markdown?: boolean | {
165
+ readonly [x: string]: unknown;
166
+ } | null | undefined;
167
+ readonly json?: boolean | null | undefined;
168
+ readonly appendix?: boolean | null | undefined;
169
+ readonly links?: boolean | {
170
+ readonly sameDomainOnly?: boolean | null | undefined;
171
+ readonly includePatterns?: readonly string[] | null | undefined;
172
+ readonly excludePatterns?: readonly string[] | null | undefined;
173
+ } | null | undefined;
174
+ readonly screenshot?: boolean | {
175
+ readonly fullPage?: boolean | null | undefined;
176
+ } | null | undefined;
177
+ readonly html?: boolean | {
178
+ readonly [x: string]: unknown;
179
+ } | null | undefined;
180
+ readonly summary?: boolean | {
181
+ readonly prompt?: string | null | undefined;
182
+ } | null | undefined;
183
+ } | null | undefined;
184
+ }) => Effect.Effect<import("@expandai/sdk/FetchJson").FetchSnapshotSearchResultWithJson, import("./Config.js").ConfigNotWritable | import("./Config.js").ConfigParseError | import("./Config.js").NotAuthenticated | OAuthTokenExpired | import("effect/ConfigError").ConfigError | import("effect/ParseResult").ParseError | import("@effect/platform/Error").PlatformError | import("./BrowserOAuth.js").BrowserOAuthRequestFailed | ApiRequestFailed | OAuthAuthMethodChanged, never>;
185
+ readonly fetchBatched: (options: {
186
+ readonly urls: readonly [string, ...string[]];
187
+ readonly include?: {
188
+ readonly response?: {
189
+ readonly includeHeaders?: boolean | null | undefined;
190
+ } | null | undefined;
191
+ readonly meta?: boolean | null | undefined;
192
+ readonly markdown?: boolean | {
193
+ readonly [x: string]: unknown;
194
+ } | null | undefined;
195
+ readonly json?: boolean | null | undefined;
196
+ readonly appendix?: boolean | null | undefined;
197
+ readonly links?: boolean | {
198
+ readonly sameDomainOnly?: boolean | null | undefined;
199
+ readonly includePatterns?: readonly string[] | null | undefined;
200
+ readonly excludePatterns?: readonly string[] | null | undefined;
201
+ } | null | undefined;
202
+ readonly screenshot?: boolean | {
203
+ readonly fullPage?: boolean | null | undefined;
204
+ } | null | undefined;
205
+ readonly html?: boolean | {
206
+ readonly [x: string]: unknown;
207
+ } | null | undefined;
208
+ readonly summary?: boolean | {
209
+ readonly prompt?: string | null | undefined;
210
+ } | null | undefined;
211
+ } | null | undefined;
212
+ readonly browserConfig?: {
213
+ readonly scrollFullPage?: boolean | null | undefined;
214
+ } | null | undefined;
215
+ }) => Effect.Effect<Generated.BatchedRun, import("./Config.js").ConfigNotWritable | import("./Config.js").ConfigParseError | import("./Config.js").NotAuthenticated | OAuthTokenExpired | import("effect/ConfigError").ConfigError | import("effect/ParseResult").ParseError | import("@effect/platform/Error").PlatformError | import("./BrowserOAuth.js").BrowserOAuthRequestFailed | ApiRequestFailed | OAuthAuthMethodChanged, never>;
216
+ readonly fetchGetBatched: (id: string, options: {
217
+ readonly include?: string | null | undefined;
218
+ readonly limit?: string | null | undefined;
219
+ readonly offset?: string | null | undefined;
220
+ }) => Effect.Effect<Generated.BatchedStatus, import("./Config.js").ConfigNotWritable | import("./Config.js").ConfigParseError | import("./Config.js").NotAuthenticated | OAuthTokenExpired | import("effect/ConfigError").ConfigError | import("effect/ParseResult").ParseError | import("@effect/platform/Error").PlatformError | import("./BrowserOAuth.js").BrowserOAuthRequestFailed | ApiRequestFailed | OAuthAuthMethodChanged, never>;
221
+ }, never, ConfigManager | BrowserOAuthService | HttpClient.HttpClient>;
222
+ }>;
223
+ /**
224
+ * Resolves outgoing API auth per call. When the current request scope carries
225
+ * an `Authorization` header (via `CurrentRequestHeaders`), that value is
226
+ * forwarded; otherwise auth comes from `~/.config/expandai/config.json`.
227
+ */
228
+ export declare class ApiClient extends ApiClient_base {
229
+ }
230
+ export {};
231
+ //# sourceMappingURL=ApiClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiClient.d.ts","sourceRoot":"","sources":["../../src/ApiClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAyC,MAAM,kBAAkB,CAAA;AAGpF,OAAO,KAAK,SAAS,MAAM,yBAAyB,CAAA;AAEpD,OAAO,EAA4B,MAAM,EAAiC,MAAM,EAAE,MAAM,QAAQ,CAAA;AAChG,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,aAAa,EAAe,iBAAiB,EAAE,MAAM,aAAa,CAAA;;;;;;AAG3E;;;;;;GAMG;AACH,qBAAa,gBAAiB,SAAQ,qBAEpC;IACD,IAAI,OAAO,WAEV;CACD;;;;AAcD,cAAM,sBAAuB,SAAQ,4BAA2C,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8DzG;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,cAwJ7B;CAAG"}
@@ -0,0 +1,23 @@
1
+ import { Command } from '@effect/cli';
2
+ import { Effect } from 'effect';
3
+ import { BrowserOAuthService } from './BrowserOAuth.js';
4
+ import { ApiKeyConfig, ConfigManager, OAuthConfig } from './Config.js';
5
+ import { Uninstall } from './Install/Uninstall.js';
6
+ type AuthMethod = typeof ApiKeyConfig.Type | typeof OAuthConfig.Type;
7
+ /** Render a user-facing description of the current auth state. Pure given DateTime.now. */
8
+ export declare const formatAuthStatus: (authMethod: AuthMethod) => Effect.Effect<string, never, never>;
9
+ declare const Authentication_base: Effect.Service.Class<Authentication, "@expandai/cli/Authentication", {
10
+ readonly dependencies: readonly [import("effect/Layer").Layer<ConfigManager, import("effect/ConfigError").ConfigError, never>, import("effect/Layer").Layer<BrowserOAuthService, import("effect/ConfigError").ConfigError, never>, import("effect/Layer").Layer<Uninstall, import("effect/ConfigError").ConfigError | import("@effect/platform/Error").BadArgument, never>];
11
+ readonly effect: Effect.Effect<{
12
+ readonly login: () => Effect.Effect<void, unknown, import("@effect/platform/Terminal").Terminal>;
13
+ readonly whoami: () => Effect.Effect<void, import("./Config.js").ConfigParseError | import("./Config.js").NotAuthenticated | import("effect/ConfigError").ConfigError | import("@effect/platform/Error").PlatformError, never>;
14
+ readonly logout: () => Effect.Effect<void, import("./Config.js").ConfigNotWritable | import("effect/ParseResult").ParseError | import("@effect/platform/Error").PlatformError | import("./Install/Domain.js").McpParseError | import("./Install/Domain.js").McpWriteError | import("@effect/platform/Terminal").QuitException, import("@effect/platform/Terminal").Terminal>;
15
+ }, never, ConfigManager | BrowserOAuthService | Uninstall>;
16
+ }>;
17
+ export declare class Authentication extends Authentication_base {
18
+ }
19
+ export declare const LoginCommand: Command.Command<"login", Authentication | import("@effect/platform/Terminal").Terminal, unknown, {}>;
20
+ export declare const WhoamiCommand: Command.Command<"whoami", Authentication, import("./Config.js").ConfigParseError | import("./Config.js").NotAuthenticated | import("effect/ConfigError").ConfigError | import("@effect/platform/Error").PlatformError, {}>;
21
+ export declare const LogoutCommand: Command.Command<"logout", Authentication | import("@effect/platform/Terminal").Terminal, import("./Config.js").ConfigNotWritable | import("effect/ParseResult").ParseError | import("@effect/platform/Error").PlatformError | import("./Install/Domain.js").McpParseError | import("./Install/Domain.js").McpWriteError | import("@effect/platform/Terminal").QuitException, {}>;
22
+ export {};
23
+ //# sourceMappingURL=Authentication.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Authentication.d.ts","sourceRoot":"","sources":["../../src/Authentication.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,aAAa,CAAA;AAC7C,OAAO,EAA+B,MAAM,EAAiC,MAAM,QAAQ,CAAA;AAE3F,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAU,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC9E,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAElD,KAAK,UAAU,GAAG,OAAO,YAAY,CAAC,IAAI,GAAG,OAAO,WAAW,CAAC,IAAI,CAAA;AAEpE,2FAA2F;AAC3F,eAAO,MAAM,gBAAgB,iEAe3B,CAAA;;;;;;;;;AAEF,qBAAa,cAAe,SAAQ,mBAyHlC;CAAG;AAEL,eAAO,MAAM,YAAY,sGAGxB,CAAA;AAED,eAAO,MAAM,aAAa,4NAGzB,CAAA;AAED,eAAO,MAAM,aAAa,kXAGzB,CAAA"}
@@ -0,0 +1,99 @@
1
+ import { HttpClient } from '@effect/platform';
2
+ import { Duration, Effect, Schema } from 'effect';
3
+ import { ConfigManager } from './Config.js';
4
+ declare const TokenResponse_base: Schema.Class<TokenResponse, {
5
+ access_token: typeof Schema.String;
6
+ refresh_token: Schema.optional<typeof Schema.String>;
7
+ expires_in: Schema.transform<typeof Schema.Number, typeof Schema.DurationFromSelf>;
8
+ token_type: typeof Schema.String;
9
+ scope: Schema.optional<typeof Schema.String>;
10
+ }, Schema.Struct.Encoded<{
11
+ access_token: typeof Schema.String;
12
+ refresh_token: Schema.optional<typeof Schema.String>;
13
+ expires_in: Schema.transform<typeof Schema.Number, typeof Schema.DurationFromSelf>;
14
+ token_type: typeof Schema.String;
15
+ scope: Schema.optional<typeof Schema.String>;
16
+ }>, never, {
17
+ readonly access_token: string;
18
+ } & {
19
+ readonly expires_in: Duration.Duration;
20
+ } & {
21
+ readonly token_type: string;
22
+ } & {
23
+ readonly refresh_token?: string | undefined;
24
+ } & {
25
+ readonly scope?: string | undefined;
26
+ }, {}, {}>;
27
+ export declare class TokenResponse extends TokenResponse_base {
28
+ }
29
+ declare const BrowserOAuthRequestFailed_base: Schema.TaggedErrorClass<BrowserOAuthRequestFailed, "BrowserOAuthRequestFailed", {
30
+ readonly _tag: Schema.tag<"BrowserOAuthRequestFailed">;
31
+ } & {
32
+ endpoint: typeof Schema.String;
33
+ error: typeof Schema.Defect;
34
+ status: Schema.optional<typeof Schema.Number>;
35
+ }>;
36
+ export declare class BrowserOAuthRequestFailed extends BrowserOAuthRequestFailed_base {
37
+ get message(): string;
38
+ }
39
+ declare const BrowserOAuthCallbackError_base: Schema.TaggedErrorClass<BrowserOAuthCallbackError, "BrowserOAuthCallbackError", {
40
+ readonly _tag: Schema.tag<"BrowserOAuthCallbackError">;
41
+ } & {
42
+ error: typeof Schema.String;
43
+ errorDescription: Schema.optional<typeof Schema.String>;
44
+ }>;
45
+ export declare class BrowserOAuthCallbackError extends BrowserOAuthCallbackError_base {
46
+ get message(): string;
47
+ }
48
+ declare const BrowserOAuthMissingCode_base: Schema.TaggedErrorClass<BrowserOAuthMissingCode, "BrowserOAuthMissingCode", {
49
+ readonly _tag: Schema.tag<"BrowserOAuthMissingCode">;
50
+ }>;
51
+ export declare class BrowserOAuthMissingCode extends BrowserOAuthMissingCode_base {
52
+ get message(): string;
53
+ }
54
+ declare const BrowserOAuthStateMismatch_base: Schema.TaggedErrorClass<BrowserOAuthStateMismatch, "BrowserOAuthStateMismatch", {
55
+ readonly _tag: Schema.tag<"BrowserOAuthStateMismatch">;
56
+ }>;
57
+ export declare class BrowserOAuthStateMismatch extends BrowserOAuthStateMismatch_base {
58
+ get message(): string;
59
+ }
60
+ declare const BrowserOAuthLoopbackFailed_base: Schema.TaggedErrorClass<BrowserOAuthLoopbackFailed, "BrowserOAuthLoopbackFailed", {
61
+ readonly _tag: Schema.tag<"BrowserOAuthLoopbackFailed">;
62
+ } & {
63
+ error: typeof Schema.Defect;
64
+ }>;
65
+ export declare class BrowserOAuthLoopbackFailed extends BrowserOAuthLoopbackFailed_base {
66
+ get message(): string;
67
+ }
68
+ declare const BrowserOAuthTimedOut_base: Schema.TaggedErrorClass<BrowserOAuthTimedOut, "BrowserOAuthTimedOut", {
69
+ readonly _tag: Schema.tag<"BrowserOAuthTimedOut">;
70
+ }>;
71
+ export declare class BrowserOAuthTimedOut extends BrowserOAuthTimedOut_base {
72
+ get message(): string;
73
+ }
74
+ interface AuthorizeUrlInput {
75
+ readonly apiUrl: URL;
76
+ readonly redirectUri: URL;
77
+ readonly state: string;
78
+ readonly codeChallenge: string;
79
+ }
80
+ interface ExchangeCodeInput {
81
+ readonly code: string;
82
+ readonly redirectUri: URL;
83
+ readonly codeVerifier: string;
84
+ }
85
+ export declare const createCodeChallenge: (codeVerifier: string) => Effect.Effect<string, never, never>;
86
+ export declare const buildAuthorizeUrl: (args_0: AuthorizeUrlInput) => Effect.Effect<URL, never, never>;
87
+ declare const BrowserOAuthService_base: Effect.Service.Class<BrowserOAuthService, "@expandai/cli/BrowserOAuthService", {
88
+ readonly dependencies: readonly [import("effect/Layer").Layer<HttpClient.HttpClient, never, never>, import("effect/Layer").Layer<ConfigManager, import("effect/ConfigError").ConfigError, never>];
89
+ readonly effect: Effect.Effect<{
90
+ readonly exchangeCode: (args_0: ExchangeCodeInput) => Effect.Effect<TokenResponse, import("./Config.js").ConfigParseError | import("effect/ConfigError").ConfigError | import("@effect/platform/Error").PlatformError | BrowserOAuthRequestFailed, never>;
91
+ readonly refreshToken: (refreshToken: string) => Effect.Effect<TokenResponse, import("./Config.js").ConfigParseError | import("effect/ConfigError").ConfigError | import("@effect/platform/Error").PlatformError | BrowserOAuthRequestFailed, never>;
92
+ readonly saveToken: (tokenResponse: TokenResponse) => Effect.Effect<void, import("./Config.js").ConfigNotWritable | import("effect/ParseResult").ParseError, never>;
93
+ readonly login: <R>(openAuthorizeUrl: (authorizeUrl: URL) => Effect.Effect<void, unknown, R>) => Effect.Effect<undefined, unknown, R>;
94
+ }, never, ConfigManager | HttpClient.HttpClient>;
95
+ }>;
96
+ export declare class BrowserOAuthService extends BrowserOAuthService_base {
97
+ }
98
+ export {};
99
+ //# sourceMappingURL=BrowserOAuth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BrowserOAuth.d.ts","sourceRoot":"","sources":["../../src/BrowserOAuth.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAyC,MAAM,kBAAkB,CAAA;AAEpF,OAAO,EAAY,QAAQ,EAAE,MAAM,EAAyB,MAAM,EAAE,MAAM,QAAQ,CAAA;AAClF,OAAO,EAAE,aAAa,EAAe,MAAM,aAAa,CAAA;;;;;;;;;;;;;;;;;;;;;;;;AAexD,qBAAa,aAAc,SAAQ,kBAMjC;CAAG;;;;;;;;AAEL,qBAAa,yBAA0B,SAAQ,8BAO9C;IACA,IAAI,OAAO,WAEV;CACD;;;;;;;AAED,qBAAa,yBAA0B,SAAQ,8BAM9C;IACA,IAAI,OAAO,WAEV;CACD;;;;AAED,qBAAa,uBAAwB,SAAQ,4BAG5C;IACA,IAAI,OAAO,WAEV;CACD;;;;AAED,qBAAa,yBAA0B,SAAQ,8BAG9C;IACA,IAAI,OAAO,WAEV;CACD;;;;;;AAED,qBAAa,0BAA2B,SAAQ,+BAK/C;IACA,IAAI,OAAO,WAEV;CACD;;;;AAED,qBAAa,oBAAqB,SAAQ,yBAAsE;IAC/G,IAAI,OAAO,WAEV;CACD;AAID,UAAU,iBAAiB;IAC1B,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAA;IACpB,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;CAC9B;AAED,UAAU,iBAAiB;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAA;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;CAC7B;AAgBD,eAAO,MAAM,mBAAmB,+DAE9B,CAAA;AAEF,eAAO,MAAM,iBAAiB,iEAe5B,CAAA;;;;;;;yBA6LgE,CAAC,mCAC/B,GAAG,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;;;AAhF3E,qBAAa,mBAAoB,SAAQ,wBAkHvC;CAAG"}
@@ -0,0 +1,30 @@
1
+ import { Command, HelpDoc } from '@effect/cli';
2
+ import { Effect, Option, Schema } from 'effect';
3
+ declare const MarkdownUnavailable_base: Schema.TaggedErrorClass<MarkdownUnavailable, "MarkdownUnavailable", {
4
+ readonly _tag: Schema.tag<"MarkdownUnavailable">;
5
+ } & {
6
+ url: typeof Schema.String;
7
+ }>;
8
+ export declare class MarkdownUnavailable extends MarkdownUnavailable_base {
9
+ get message(): string;
10
+ }
11
+ declare const SnippetsUnavailable_base: Schema.TaggedErrorClass<SnippetsUnavailable, "SnippetsUnavailable", {
12
+ readonly _tag: Schema.tag<"SnippetsUnavailable">;
13
+ } & {
14
+ url: typeof Schema.String;
15
+ query: typeof Schema.String;
16
+ }>;
17
+ export declare class SnippetsUnavailable extends SnippetsUnavailable_base {
18
+ get message(): string;
19
+ }
20
+ export declare const parseUrlArg: (raw: string) => Effect.Effect<URL, HelpDoc.HelpDoc, never>;
21
+ interface FetchCommandConfig {
22
+ readonly url: URL;
23
+ readonly format: 'text' | 'json';
24
+ readonly search: Option.Option<string>;
25
+ readonly maxResults: number;
26
+ readonly minScore: number;
27
+ }
28
+ export declare const FetchCommand: Command.Command<'fetch', never, unknown, FetchCommandConfig>;
29
+ export {};
30
+ //# sourceMappingURL=Fetch.d.ts.map