@botuyo/mcp 0.3.13 → 0.3.21

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 (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +135 -30
  3. package/dist/__tests__/client.spec.d.ts +5 -0
  4. package/dist/__tests__/client.spec.js +139 -0
  5. package/dist/__tests__/client.spec.js.map +1 -0
  6. package/dist/client.d.ts +6 -1
  7. package/dist/client.js +30 -10
  8. package/dist/client.js.map +1 -1
  9. package/dist/commands/__tests__/credentials.spec.d.ts +5 -0
  10. package/dist/commands/__tests__/credentials.spec.js +174 -0
  11. package/dist/commands/__tests__/credentials.spec.js.map +1 -0
  12. package/dist/commands/auth.js +34 -50
  13. package/dist/commands/auth.js.map +1 -1
  14. package/dist/commands/credentials.d.ts +38 -4
  15. package/dist/commands/credentials.js +80 -12
  16. package/dist/commands/credentials.js.map +1 -1
  17. package/dist/commands/login.js +26 -56
  18. package/dist/commands/login.js.map +1 -1
  19. package/dist/commands/switch_tenant.js +11 -36
  20. package/dist/commands/switch_tenant.js.map +1 -1
  21. package/dist/commands/tenants.js +10 -19
  22. package/dist/commands/tenants.js.map +1 -1
  23. package/dist/index.js +88 -11
  24. package/dist/index.js.map +1 -1
  25. package/dist/tools/__tests__/configure_avatar.spec.js +2 -3
  26. package/dist/tools/__tests__/configure_avatar.spec.js.map +1 -1
  27. package/dist/tools/configure_agent_tool.js +4 -4
  28. package/dist/tools/configure_avatar.js +2 -3
  29. package/dist/tools/configure_avatar.js.map +1 -1
  30. package/dist/tools/example_agent.d.ts +5 -3
  31. package/dist/tools/example_agent.js +10 -8
  32. package/dist/tools/example_agent.js.map +1 -1
  33. package/dist/tools/index.js +3 -0
  34. package/dist/tools/index.js.map +1 -1
  35. package/dist/tools/ingest_knowledge_url.d.ts +4 -0
  36. package/dist/tools/ingest_knowledge_url.js +35 -0
  37. package/dist/tools/ingest_knowledge_url.js.map +1 -0
  38. package/dist/tools/switch_tenant.js +1 -1
  39. package/dist/tools/switch_tenant.js.map +1 -1
  40. package/package.json +2 -3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 BotUyo
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
@@ -6,39 +6,49 @@ Create and manage BotUyo AI agents directly from your AI coding tools — **no c
6
6
 
7
7
  ## Quickstart
8
8
 
9
- ### 1. Get your API Key
9
+ The fastest way — one command configures your editor **and** logs you in:
10
10
 
11
- Go to [admin.botuyo.com](https://admin.botuyo.com) → your tenant → **Settings → API Keys** and copy your `pk_live_...` key.
11
+ ```sh
12
+ npx @botuyo/mcp setup
13
+ ```
14
+
15
+ It auto-detects your editor (Cursor, VS Code / Antigravity, Claude Desktop), writes the MCP config, and walks you through authentication.
12
16
 
13
- ### 2. Add to your MCP client
17
+ ### Manual setup
14
18
 
15
- The config is the same for **all MCP-compatible tools**:
19
+ **1. Add the BotUyo server to your MCP client config:**
16
20
 
17
21
  ```json
18
22
  {
19
23
  "mcpServers": {
20
24
  "botuyo": {
21
25
  "command": "npx",
22
- "args": ["-y", "@botuyo/mcp"],
23
- "env": {
24
- "BOTUYO_API_KEY": "pk_live_your_key_here"
25
- }
26
+ "args": ["-y", "@botuyo/mcp"]
26
27
  }
27
28
  }
28
29
  }
29
30
  ```
30
31
 
31
- **Where to put this config:**
32
+ > No API key goes in the config — authentication is handled by the `auth`/`login` commands below. Some clients (Cursor, VS Code) use the `servers` key instead of `mcpServers`.
32
33
 
33
- | Tool | Config file |
34
+ | Client | Config file |
34
35
  |---|---|
35
- | **Antigravity (VS Code)** | VS Code settings → MCP → Add server |
36
- | **Claude Desktop** | `~/.config/claude/claude_desktop_config.json` |
37
- | **Cursor** | `.cursor/mcp.json` in your project |
36
+ | **Cursor** | `.cursor/mcp.json` |
37
+ | **VS Code / Antigravity** | `.vscode/mcp.json` |
38
+ | **Claude Desktop** | `~/.config/claude/claude_desktop_config.json` (Windows: `%AppData%\Claude\claude_desktop_config.json`) |
38
39
  | **Windsurf** | `~/.codeium/windsurf/mcp_config.json` |
39
- | **Continue** | `.continue/config.json` |
40
40
 
41
- ### 3. Start building agents
41
+ **2. Authenticate once** — saves a token to `~/.botuyo/credentials.json`:
42
+
43
+ ```sh
44
+ npx @botuyo/mcp auth # browser OAuth (recommended)
45
+ # or
46
+ npx @botuyo/mcp login # email + password in the terminal
47
+ ```
48
+
49
+ The running MCP server picks up your session automatically — no restart needed. Tokens last 7 days; re-run `auth` or `login` to refresh.
50
+
51
+ ### Start building agents
42
52
 
43
53
  Once connected, ask your AI assistant things like:
44
54
 
@@ -48,19 +58,98 @@ Once connected, ask your AI assistant things like:
48
58
  > *"Enable the EscalateToHuman and SearchKnowledgeBase tools on Mar"*
49
59
  > *"Publish the agent"*
50
60
 
51
- ## Available Tools
61
+ ## CLI commands
62
+
63
+ ```sh
64
+ npx @botuyo/mcp setup # Configure your editor + authenticate (recommended)
65
+ npx @botuyo/mcp auth # Login via browser (OAuth)
66
+ npx @botuyo/mcp login # Login via email + password
67
+ npx @botuyo/mcp tenants # List your tenants
68
+ npx @botuyo/mcp switch-tenant # Switch the active tenant
69
+ npx @botuyo/mcp whoami # Show the current session
70
+ npx @botuyo/mcp logout # Clear stored credentials
71
+ ```
72
+
73
+ The server resolves your JWT from `BOTUYO_TOKEN`, falling back to `~/.botuyo/credentials.json`. The backend URL defaults to `https://api.botuyo.com` (override with `BOTUYO_API_URL`).
74
+
75
+ ## Available tools
76
+
77
+ The server exposes **30 tools**. Read tools (`list_*`, `get_*`, `export_*`) need `viewer+`; write/publish tools need `developer+` (see [Roles](#roles)).
78
+
79
+ ### Agents
80
+
81
+ | Tool | Description |
82
+ |---|---|
83
+ | `list_agents` | List all agents in the tenant |
84
+ | `get_agent` | Get an agent's full config (identity, stages, enabled tools) |
85
+ | `get_agent_status` | Channel connection status + admin link to connect missing channels |
86
+ | `create_agent` | Create a new agent |
87
+ | `update_agent` | Update identity (tone, language, objective, custom instructions) |
88
+ | `delete_agent` | Soft-delete an agent (irreversible; requires explicit confirmation) |
89
+ | `publish_agent` | Publish or unpublish an agent (live vs draft) |
90
+ | `example_agent` | Return a fully documented example agent config (read-only reference) |
91
+
92
+ ### Conversation flow
93
+
94
+ | Tool | Description |
95
+ |---|---|
96
+ | `upsert_stage` | Create or update a named stage in the agent's conversation graph |
97
+
98
+ ### Tools & capabilities
99
+
100
+ | Tool | Description |
101
+ |---|---|
102
+ | `list_available_tools` | List tools available to your tenant (core + custom) |
103
+ | `update_enabled_tools` | Enable/disable tools on an agent |
104
+ | `get_tools_catalog` | Full tool catalog with metadata (configurable, multi-instance, schema, required integrations) |
105
+ | `configure_agent_tool` | Create/update a tool's config on an agent (single or multi-instance) |
106
+ | `list_tool_configs` | List an agent's tool configs, grouped |
107
+ | `get_tool_config` | View the full config of a specific tool on an agent |
108
+ | `remove_tool_config` | Remove a tool's configuration |
109
+
110
+ ### Knowledge base
111
+
112
+ | Tool | Description |
113
+ |---|---|
114
+ | `list_knowledge_documents` | List knowledge base documents |
115
+ | `ingest_knowledge_url` | Ingest a URL into the knowledge base |
116
+ | `associate_knowledge_to_agent` | Link knowledge document IDs to an agent |
117
+ | `delete_knowledge_document` | Delete a knowledge document and all its chunks |
118
+
119
+ ### Templates
120
+
121
+ | Tool | Description |
122
+ |---|---|
123
+ | `list_templates` | List agent templates by industry |
124
+ | `create_from_template` | Create a new agent from a template |
125
+
126
+ ### Import / export
127
+
128
+ | Tool | Description |
129
+ |---|---|
130
+ | `export_agent_json` | Export an agent's full config as editable JSON |
131
+ | `import_agent_json` | Replace an agent's full config from JSON (full overwrite) |
132
+
133
+ ### Avatar & media
134
+
135
+ | Tool | Description |
136
+ |---|---|
137
+ | `list_avatars` | List the free 3D avatars in the catalog |
138
+ | `select_avatar` | Set a 3D avatar for an agent (catalog ID or custom .glb/.vrm URL) |
139
+ | `upload_agent_media` | Upload a local image to the CDN as an agent's avatar/logo |
140
+
141
+ ### Versioning
52
142
 
53
- | Tool | Description | Role Required |
54
- |---|---|---|
55
- | `list_agents` | List all agents | viewer+ |
56
- | `get_agent` | Get full agent config | viewer+ |
57
- | `get_agent_status` | Channel status + admin link | viewer+ |
58
- | `create_agent` | Create a new agent | developer+ |
59
- | `update_agent` | Update identity (tone, language, etc.) | developer+ |
60
- | `upsert_stage` | Create/edit a conversation stage | developer+ |
61
- | `list_available_tools` | List tools available to your tenant | viewer+ |
62
- | `update_enabled_tools` | Enable/disable tools on an agent | developer+ |
63
- | `publish_agent` | Publish or unpublish an agent | developer+ |
143
+ | Tool | Description |
144
+ |---|---|
145
+ | `list_agent_versions` | List an agent's saved version snapshots |
146
+ | `restore_agent_version` | Roll back an agent to a previous version |
147
+
148
+ ### Account
149
+
150
+ | Tool | Description |
151
+ |---|---|
152
+ | `switch_tenant` | Switch the active tenant for the session |
64
153
 
65
154
  ## Roles
66
155
 
@@ -80,14 +169,30 @@ Use `get_agent_status` to check which channels are connected. It returns a direc
80
169
  ## Build from source
81
170
 
82
171
  ```sh
83
- cd packages/mcp
172
+ git clone https://github.com/MarcoAR1/botuyo-mcp.git
173
+ cd botuyo-mcp
84
174
  npm install
85
175
  npm run build
86
176
  ```
87
177
 
88
178
  ## Test with MCP Inspector
89
179
 
180
+ Authenticate first (`npx @botuyo/mcp login`), then run:
181
+
90
182
  ```sh
91
- cd packages/mcp
92
- BOTUYO_API_KEY=pk_live_... npm run inspect
183
+ npm run inspect
93
184
  ```
185
+
186
+ ## Contributing
187
+
188
+ We welcome contributions! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
189
+
190
+ Please note that this project follows a [Code of Conduct](CODE_OF_CONDUCT.md).
191
+
192
+ ## Security
193
+
194
+ To report a vulnerability, see [SECURITY.md](SECURITY.md).
195
+
196
+ ## License
197
+
198
+ [MIT](LICENSE) © BotUyo
@@ -0,0 +1,5 @@
1
+ /**
2
+ * BotuyoApiClient — Unit tests
3
+ * Tests for error handling, 401 detection, ApiError class
4
+ */
5
+ export {};
@@ -0,0 +1,139 @@
1
+ /**
2
+ * BotuyoApiClient — Unit tests
3
+ * Tests for error handling, 401 detection, ApiError class
4
+ */
5
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
6
+ import { BotuyoApiClient, ApiError } from '../client.js';
7
+ // Mock global fetch
8
+ function mockFetch(status, body, ok) {
9
+ const fn = vi.fn().mockResolvedValue({
10
+ status,
11
+ ok: ok ?? (status >= 200 && status < 300),
12
+ text: async () => JSON.stringify(body),
13
+ json: async () => body
14
+ });
15
+ vi.stubGlobal('fetch', fn);
16
+ return fn;
17
+ }
18
+ describe('BotuyoApiClient', () => {
19
+ let client;
20
+ beforeEach(() => {
21
+ vi.restoreAllMocks();
22
+ client = new BotuyoApiClient({ apiUrl: 'http://localhost:8080', token: 'test-token' });
23
+ });
24
+ // ── ApiError class ──────────────────────────────────────────────────
25
+ describe('ApiError', () => {
26
+ it('is an instance of Error', () => {
27
+ const err = new ApiError('test', 401);
28
+ expect(err).toBeInstanceOf(Error);
29
+ expect(err).toBeInstanceOf(ApiError);
30
+ });
31
+ it('stores the HTTP status code', () => {
32
+ const err = new ApiError('Unauthorized', 401);
33
+ expect(err.status).toBe(401);
34
+ expect(err.message).toBe('Unauthorized');
35
+ });
36
+ it('has a name of ApiError', () => {
37
+ const err = new ApiError('test', 500);
38
+ expect(err.name).toBe('ApiError');
39
+ });
40
+ });
41
+ // ── handleResponse / 401 detection ──────────────────────────────────
42
+ describe('401 detection', () => {
43
+ it('throws ApiError with status 401 on unauthorized response', async () => {
44
+ mockFetch(401, { success: false, error: 'Invalid or expired token' });
45
+ try {
46
+ await client.get('/api/v1/mcp/agents');
47
+ expect.fail('should have thrown');
48
+ }
49
+ catch (err) {
50
+ expect(err).toBeInstanceOf(ApiError);
51
+ expect(err.status).toBe(401);
52
+ }
53
+ });
54
+ it('throws ApiError with status 403 on forbidden response', async () => {
55
+ mockFetch(403, { success: false, error: 'Forbidden' });
56
+ try {
57
+ await client.get('/api/v1/mcp/agents');
58
+ expect.fail('should have thrown');
59
+ }
60
+ catch (err) {
61
+ expect(err).toBeInstanceOf(ApiError);
62
+ expect(err.status).toBe(403);
63
+ }
64
+ });
65
+ it('throws ApiError with status 500 on server error', async () => {
66
+ mockFetch(500, { success: false, error: 'Internal error' });
67
+ try {
68
+ await client.get('/api/v1/mcp/agents');
69
+ expect.fail('should have thrown');
70
+ }
71
+ catch (err) {
72
+ expect(err).toBeInstanceOf(ApiError);
73
+ expect(err.status).toBe(500);
74
+ }
75
+ });
76
+ it('does NOT throw on successful 200 responses', async () => {
77
+ mockFetch(200, { success: true, data: { agents: [] } });
78
+ const result = await client.get('/api/v1/mcp/agents');
79
+ expect(result.success).toBe(true);
80
+ });
81
+ });
82
+ // ── verify() ────────────────────────────────────────────────────────
83
+ describe('verify', () => {
84
+ it('returns AuthInfo on successful /api/auth/me', async () => {
85
+ mockFetch(200, {
86
+ success: true,
87
+ data: {
88
+ user: {
89
+ email: 'test@example.com',
90
+ tenantIds: ['t1'],
91
+ roles: [{ tenantId: 't1', role: 'owner' }]
92
+ }
93
+ }
94
+ });
95
+ const info = await client.verify();
96
+ expect(info.email).toBe('test@example.com');
97
+ expect(info.tenantId).toBe('t1');
98
+ expect(info.role).toBe('owner');
99
+ });
100
+ it('throws on 401 from /api/auth/me', async () => {
101
+ mockFetch(401, { success: false, error: 'Token expired' });
102
+ await expect(client.verify()).rejects.toThrow();
103
+ });
104
+ it('caches authInfo after first successful call', async () => {
105
+ const fetchFn = mockFetch(200, {
106
+ success: true,
107
+ data: {
108
+ user: {
109
+ email: 'test@example.com',
110
+ tenantIds: ['t1'],
111
+ roles: [{ tenantId: 't1', role: 'owner' }]
112
+ }
113
+ }
114
+ });
115
+ await client.verify();
116
+ await client.verify();
117
+ expect(fetchFn).toHaveBeenCalledTimes(1);
118
+ });
119
+ });
120
+ // ── Non-JSON responses ──────────────────────────────────────────────
121
+ describe('non-JSON responses', () => {
122
+ it('throws ApiError with status code when response is not JSON', async () => {
123
+ vi.stubGlobal('fetch', vi.fn().mockResolvedValue({
124
+ status: 502,
125
+ ok: false,
126
+ text: async () => '<html>Bad Gateway</html>'
127
+ }));
128
+ try {
129
+ await client.get('/api/v1/mcp/agents');
130
+ expect.fail('should have thrown');
131
+ }
132
+ catch (err) {
133
+ expect(err).toBeInstanceOf(ApiError);
134
+ expect(err.status).toBe(502);
135
+ }
136
+ });
137
+ });
138
+ });
139
+ //# sourceMappingURL=client.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.spec.js","sourceRoot":"","sources":["../../src/__tests__/client.spec.ts"],"names":[],"mappings":"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"}
package/dist/client.d.ts CHANGED
@@ -5,6 +5,10 @@
5
5
  * Uses a JWT token directly (obtained via `npx @botuyo/mcp auth` or `npx @botuyo/mcp login`).
6
6
  * Requires Node 18+ (native fetch).
7
7
  */
8
+ export declare class ApiError extends Error {
9
+ readonly status: number;
10
+ constructor(message: string, status: number);
11
+ }
8
12
  export interface BotuyoClientConfig {
9
13
  apiUrl: string;
10
14
  token: string;
@@ -18,11 +22,12 @@ export interface AuthInfo {
18
22
  export declare class BotuyoApiClient {
19
23
  private config;
20
24
  private authInfo;
25
+ private activeTenantId;
21
26
  constructor(config: BotuyoClientConfig);
22
27
  /** Get the current JWT token */
23
28
  getToken(): string;
24
29
  /** Hot-swap the JWT token (used by switch_tenant) */
25
- setToken(token: string): void;
30
+ setToken(token: string, tenantId?: string): void;
26
31
  /** Verify the stored JWT is still valid by calling GET /api/auth/me */
27
32
  verify(): Promise<AuthInfo>;
28
33
  /** Make an authenticated GET request */
package/dist/client.js CHANGED
@@ -5,9 +5,18 @@
5
5
  * Uses a JWT token directly (obtained via `npx @botuyo/mcp auth` or `npx @botuyo/mcp login`).
6
6
  * Requires Node 18+ (native fetch).
7
7
  */
8
+ export class ApiError extends Error {
9
+ status;
10
+ constructor(message, status) {
11
+ super(message);
12
+ this.name = 'ApiError';
13
+ this.status = status;
14
+ }
15
+ }
8
16
  export class BotuyoApiClient {
9
17
  config;
10
18
  authInfo = null;
19
+ activeTenantId = null; // Track tenant set by switch_tenant
11
20
  constructor(config) {
12
21
  this.config = config;
13
22
  }
@@ -16,9 +25,11 @@ export class BotuyoApiClient {
16
25
  return this.config.token;
17
26
  }
18
27
  /** Hot-swap the JWT token (used by switch_tenant) */
19
- setToken(token) {
28
+ setToken(token, tenantId) {
20
29
  this.config = { ...this.config, token };
21
30
  this.authInfo = null; // reset cached auth info
31
+ if (tenantId)
32
+ this.activeTenantId = tenantId;
22
33
  }
23
34
  /** Verify the stored JWT is still valid by calling GET /api/auth/me */
24
35
  async verify() {
@@ -32,10 +43,12 @@ export class BotuyoApiClient {
32
43
  throw new Error(`Session expired or invalid: ${body.error || 'Unknown error'}. Run: npx @botuyo/mcp auth (browser) or npx @botuyo/mcp login (terminal)`);
33
44
  }
34
45
  const user = body.data.user;
46
+ // Use activeTenantId (from switch_tenant) if set, otherwise fall back to first tenant
47
+ const resolvedTenantId = this.activeTenantId || user.tenantIds?.[0] || '';
35
48
  this.authInfo = {
36
- tenantId: user.tenantIds?.[0] || '',
49
+ tenantId: resolvedTenantId,
37
50
  tenantName: '', // Will be enriched from credentials
38
- role: user.roles?.[0]?.role || 'member',
51
+ role: user.roles?.find((r) => r.tenantId === resolvedTenantId)?.role || user.roles?.[0]?.role || 'member',
39
52
  email: user.email
40
53
  };
41
54
  return this.authInfo;
@@ -82,10 +95,17 @@ export class BotuyoApiClient {
82
95
  return this.handleResponse(res);
83
96
  }
84
97
  async handleResponse(res) {
85
- const json = await this.parseJson(res);
86
- // Detect expired token
87
- if (res.status === 401) {
88
- throw new Error('Sesión expirada. Ejecutá: npx @botuyo/mcp auth (browser) o npx @botuyo/mcp login (terminal)');
98
+ const text = await res.text();
99
+ let json;
100
+ try {
101
+ json = JSON.parse(text);
102
+ }
103
+ catch {
104
+ throw new ApiError(`HTTP ${res.status}: ${text.slice(0, 200)}`, res.status);
105
+ }
106
+ if (!res.ok) {
107
+ const msg = json.error || `HTTP ${res.status}`;
108
+ throw new ApiError(msg, res.status);
89
109
  }
90
110
  return json;
91
111
  }
@@ -117,14 +137,14 @@ export class BotuyoApiClient {
117
137
  try {
118
138
  const json = JSON.parse(text);
119
139
  if (!res.ok && !json.success) {
120
- throw new Error(json.error || `HTTP ${res.status}`);
140
+ throw new ApiError(json.error || `HTTP ${res.status}`, res.status);
121
141
  }
122
142
  return json;
123
143
  }
124
144
  catch (e) {
125
- if (e instanceof Error && e.message.includes('HTTP'))
145
+ if (e instanceof ApiError)
126
146
  throw e;
127
- throw new Error(`HTTP ${res.status}: ${text.slice(0, 200)}`);
147
+ throw new ApiError(`HTTP ${res.status}: ${text.slice(0, 200)}`, res.status);
128
148
  }
129
149
  }
130
150
  }
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * credentials.ts — Unit tests
3
+ * Tests for apiUrl persistence, resolveApiUrl, and checkExistingSession
4
+ */
5
+ export {};