@atlascloudai/opencode 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,191 @@
1
+ # Atlas Cloud Plugin for OpenCode
2
+
3
+ An [OpenCode](https://opencode.ai) plugin that integrates [Atlas Cloud's](https://atlascloud.ai) OpenAI-compatible API, giving you access to 100+ AI models including GPT-4o, Claude, Gemini, DeepSeek, and more.
4
+
5
+ ## Quick Start
6
+
7
+ ### 1. Install and register the plugin
8
+
9
+ ```bash
10
+ npx @atlascloudai/opencode
11
+ ```
12
+
13
+ This downloads the plugin and registers it with OpenCode.
14
+
15
+ **Alternative: Global install**
16
+ ```bash
17
+ npm install -g @atlascloudai/opencode
18
+ atlascloudai-opencode
19
+ ```
20
+
21
+ ### 3. Start OpenCode and connect
22
+
23
+ ```bash
24
+ opencode
25
+ ```
26
+
27
+ Then connect with your Atlas Cloud API key:
28
+
29
+ ```
30
+ /connect atlascloud YOUR_API_KEY
31
+ ```
32
+
33
+ ### 4. Restart OpenCode to load models
34
+
35
+ Exit and restart OpenCode. Your Atlas Cloud models will now be available via `/models`.
36
+
37
+ ## Commands
38
+
39
+ | Command | Description |
40
+ |---------|-------------|
41
+ | `/connect atlascloud <api_key>` | Connect with your API key |
42
+ | `/atlascloud status` | Check connection status |
43
+ | `/atlascloud disconnect` | Remove your API key |
44
+
45
+ ## Available Models
46
+
47
+ The plugin dynamically fetches all available models from Atlas Cloud. Popular models include:
48
+
49
+ **OpenAI**: GPT-4o, GPT-4o Mini, GPT-4.1, GPT-5, O1, O3, O3 Mini
50
+
51
+ **Anthropic**: Claude Sonnet 4.5, Claude Opus 4.5, Claude Haiku 4.5
52
+
53
+ **Google**: Gemini 2.5 Flash, Gemini 2.5 Pro, Gemini 3 Flash Preview
54
+
55
+ **DeepSeek**: DeepSeek V3.1, DeepSeek V3.2, DeepSeek R1
56
+
57
+ **xAI**: Grok 4
58
+
59
+ And many more...
60
+
61
+ ## Configuration
62
+
63
+ ### API Key Sources (in priority order)
64
+
65
+ 1. **OpenCode auth.json** - `~/.local/share/opencode/auth.json`
66
+ 2. **Plugin config** - `~/.atlascloud/config.json`
67
+ 3. **Environment variable** - `ATLASCLOUD_API_KEY`
68
+
69
+ ### Manual Configuration
70
+
71
+ If you prefer not to use `/connect`, you can manually create the config:
72
+
73
+ **Option 1: Environment variable**
74
+ ```bash
75
+ export ATLASCLOUD_API_KEY=your-api-key
76
+ ```
77
+
78
+ **Option 2: Config file** (`~/.atlascloud/config.json`)
79
+ ```json
80
+ {
81
+ "version": "1.0.0",
82
+ "apiKey": "your-api-key"
83
+ }
84
+ ```
85
+
86
+ ## Development
87
+
88
+ ### Prerequisites
89
+
90
+ - Node.js >= 18.0.0
91
+ - npm or bun
92
+ - [OpenCode](https://opencode.ai) installed
93
+
94
+ ### Local Development
95
+
96
+ ```bash
97
+ # Clone the repository
98
+ git clone https://github.com/atlascloud/opencode-plugin.git
99
+ cd opencode-plugin
100
+
101
+ # Install dependencies
102
+ npm install
103
+
104
+ # Build
105
+ npm run build
106
+
107
+ # Register plugin locally
108
+ node bin/setup.cjs
109
+
110
+ # Start OpenCode
111
+ opencode
112
+ ```
113
+
114
+ ### Watch Mode
115
+
116
+ ```bash
117
+ npm run dev
118
+ ```
119
+
120
+ ### Testing in Docker
121
+
122
+ For a clean, isolated test environment:
123
+
124
+ ```bash
125
+ # Build Docker image
126
+ make build
127
+
128
+ # Run container
129
+ make run
130
+
131
+ # Inside container:
132
+ node bin/setup.cjs # Register plugin
133
+ opencode # Start OpenCode
134
+ ```
135
+
136
+ ## Troubleshooting
137
+
138
+ ### Models not showing up
139
+
140
+ 1. Ensure you've run `/connect atlascloud <api_key>` with a valid key
141
+ 2. **Restart OpenCode** after connecting (required to load models)
142
+ 3. Check status with `/atlascloud status`
143
+
144
+ ### Invalid API key error
145
+
146
+ 1. Verify your key at [Atlas Cloud dashboard](https://atlascloud.ai)
147
+ 2. Reconnect with `/connect atlascloud <new_key>`
148
+
149
+ ### Plugin not loading
150
+
151
+ 1. Run `npx @atlascloudai/opencode` to re-register
152
+ 2. Check `~/.config/opencode/opencode.json` has the plugin listed
153
+
154
+ ### Debug mode
155
+
156
+ Enable debug logging:
157
+ ```bash
158
+ ATLASCLOUD_DEBUG=1 opencode
159
+ ```
160
+
161
+ ## Architecture
162
+
163
+ ```
164
+ opencode-atlascloud-plugin/
165
+ ├── bin/
166
+ │ └── setup.cjs # CLI setup script
167
+ ├── src/
168
+ │ ├── index.ts # Plugin entry point
169
+ │ └── server/
170
+ │ ├── config.ts # Configuration management
171
+ │ └── models.ts # Model fetching & formatting
172
+ ├── dist/ # Compiled output
173
+ ├── package.json
174
+ └── tsconfig.json
175
+ ```
176
+
177
+ ## API Reference
178
+
179
+ **Base URL**: `https://api.atlascloud.ai/v1`
180
+
181
+ The plugin uses Atlas Cloud's OpenAI-compatible API via `@ai-sdk/openai-compatible`.
182
+
183
+ ## License
184
+
185
+ MIT
186
+
187
+ ## Links
188
+
189
+ - [Atlas Cloud](https://atlascloud.ai)
190
+ - [OpenCode](https://opencode.ai)
191
+ - [Report Issues](https://github.com/atlascloud/opencode-plugin/issues)
package/bin/setup.cjs ADDED
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const os = require("os");
6
+
7
+ const PLUGIN_NAME = "opencode-atlascloud-plugin";
8
+ const CONFIG_DIR = path.join(os.homedir(), ".config", "opencode");
9
+ const CONFIG_FILE = path.join(CONFIG_DIR, "opencode.json");
10
+
11
+ function log(message) {
12
+ console.log(`[${PLUGIN_NAME}] ${message}`);
13
+ }
14
+
15
+ function error(message) {
16
+ console.error(`[${PLUGIN_NAME}] ERROR: ${message}`);
17
+ }
18
+
19
+ function ensureConfigDir() {
20
+ if (!fs.existsSync(CONFIG_DIR)) {
21
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
22
+ log(`Created config directory: ${CONFIG_DIR}`);
23
+ }
24
+ }
25
+
26
+ function loadConfig() {
27
+ if (fs.existsSync(CONFIG_FILE)) {
28
+ try {
29
+ const content = fs.readFileSync(CONFIG_FILE, "utf-8");
30
+ return JSON.parse(content);
31
+ } catch (e) {
32
+ error(`Failed to parse existing config: ${e.message}`);
33
+ return {};
34
+ }
35
+ }
36
+ return {};
37
+ }
38
+
39
+ function saveConfig(config) {
40
+ // Backup existing config
41
+ if (fs.existsSync(CONFIG_FILE)) {
42
+ fs.writeFileSync(CONFIG_FILE + ".bak", fs.readFileSync(CONFIG_FILE));
43
+ }
44
+ fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
45
+ }
46
+
47
+ function registerPlugin() {
48
+ ensureConfigDir();
49
+
50
+ const config = loadConfig();
51
+
52
+ // Get the plugin path (parent directory of bin/)
53
+ const pluginPath = path.resolve(__dirname, "..");
54
+
55
+ // Verify dist/index.js exists
56
+ const indexPath = path.join(pluginPath, "dist", "index.js");
57
+ if (!fs.existsSync(indexPath)) {
58
+ throw new Error(`Plugin not built. Run 'npm run build' first. Expected: ${indexPath}`);
59
+ }
60
+
61
+ log(`Plugin path: ${pluginPath}`);
62
+
63
+ // Initialize plugin array if it doesn't exist
64
+ if (!config.plugin) {
65
+ config.plugin = [];
66
+ }
67
+
68
+ // Check if plugin is already registered (by name or path)
69
+ const alreadyExists = config.plugin.some(
70
+ (p) => p === PLUGIN_NAME || p === pluginPath || (typeof p === "string" && p.includes(PLUGIN_NAME))
71
+ );
72
+
73
+ if (alreadyExists) {
74
+ log("Plugin already configured.");
75
+ } else {
76
+ // Push the local path, not the package name
77
+ config.plugin.push(pluginPath);
78
+ saveConfig(config);
79
+ log("Plugin added to configuration.");
80
+ log(`Configuration saved: ${CONFIG_FILE}`);
81
+ }
82
+
83
+ return true;
84
+ }
85
+
86
+ function printInstructions() {
87
+ console.log("\n" + "=".repeat(60));
88
+ console.log(" Atlas Cloud Plugin for OpenCode - Setup Complete");
89
+ console.log("=".repeat(60));
90
+ console.log("\nNext steps:");
91
+ console.log("\n1. Start OpenCode:");
92
+ console.log(" $ opencode");
93
+ console.log("\n2. Connect your Atlas Cloud account by asking:");
94
+ console.log(' "Connect to Atlas Cloud with API key YOUR_API_KEY"');
95
+ console.log("\n3. Restart OpenCode to load the models");
96
+ console.log("\n4. Select an Atlas Cloud model:");
97
+ console.log(" /models");
98
+ console.log("\n" + "=".repeat(60));
99
+ console.log("\nAlternative: Set the ATLASCLOUD_API_KEY environment variable:");
100
+ console.log(" export ATLASCLOUD_API_KEY=your-api-key");
101
+ console.log("\nOr create ~/.atlascloud/config.json:");
102
+ console.log(' { "version": "1.0.0", "apiKey": "your-api-key" }');
103
+ console.log("\n" + "=".repeat(60));
104
+ console.log("\nAvailable tools provided by this plugin:");
105
+ console.log(" - atlascloud_connect: Set your API key");
106
+ console.log(" - atlascloud_status: Check connection status");
107
+ console.log(" - atlascloud_disconnect: Remove your API key");
108
+ console.log("\n" + "=".repeat(60) + "\n");
109
+ }
110
+
111
+ function main() {
112
+ log("Setting up Atlas Cloud plugin for OpenCode...\n");
113
+
114
+ try {
115
+ registerPlugin();
116
+ printInstructions();
117
+ } catch (e) {
118
+ error(`Setup failed: ${e.message}`);
119
+ process.exit(1);
120
+ }
121
+ }
122
+
123
+ main();
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from "@opencode-ai/plugin";
2
+ export declare const AtlasCloudPlugin: Plugin;
3
+ export default AtlasCloudPlugin;
package/dist/index.js ADDED
@@ -0,0 +1,207 @@
1
+ import { loadConfig, saveApiKey, getApiKey, clearApiKey } from "./server/config.js";
2
+ import { fetchModels, modelsToOpenCodeFormat, validateApiKey, ATLAS_CLOUD_API_BASE, } from "./server/models.js";
3
+ const PROVIDER_ID = "atlascloud";
4
+ const PROVIDER_NAME = "Atlas Cloud";
5
+ // Custom fetch that strips Anthropic-specific parameters that Atlas Cloud doesn't support
6
+ function createAtlasCloudFetch() {
7
+ return async (url, init) => {
8
+ if (init?.body && typeof init.body === "string") {
9
+ try {
10
+ const body = JSON.parse(init.body);
11
+ // Strip cache_control from messages (Anthropic-specific)
12
+ if (body.messages && Array.isArray(body.messages)) {
13
+ body.messages = body.messages.map((msg) => {
14
+ const { cache_control, ...rest } = msg;
15
+ // Also strip cache_control from content if it's an array
16
+ if (Array.isArray(rest.content)) {
17
+ rest.content = rest.content.map((c) => {
18
+ const { cache_control: cc, ...contentRest } = c;
19
+ return contentRest;
20
+ });
21
+ }
22
+ return rest;
23
+ });
24
+ }
25
+ // Strip other Anthropic-specific parameters
26
+ delete body.anthropic_version;
27
+ delete body.metadata;
28
+ init = {
29
+ ...init,
30
+ body: JSON.stringify(body),
31
+ };
32
+ }
33
+ catch {
34
+ // Not JSON or parse error, pass through as-is
35
+ }
36
+ }
37
+ return fetch(url, init);
38
+ };
39
+ }
40
+ async function handleConnectCommand(args) {
41
+ const key = args[0];
42
+ if (!key) {
43
+ return {
44
+ handled: true,
45
+ error: `Usage: /connect atlascloud <your_api_key>`,
46
+ };
47
+ }
48
+ try {
49
+ const isValid = await validateApiKey(key);
50
+ if (!isValid) {
51
+ return {
52
+ handled: true,
53
+ error: `❌ **Invalid API Key**\n\nThe API key could not be validated. Please check your key and try again.`,
54
+ };
55
+ }
56
+ saveApiKey(key);
57
+ const models = await fetchModels(key);
58
+ const masked = key.substring(0, 8) + "..." + key.substring(key.length - 4);
59
+ return {
60
+ handled: true,
61
+ response: `✅ **Atlas Cloud Connected!**\n\n- Key: \`${masked}\`\n- Models Available: ${models.length}\n\n**Restart OpenCode** to load the models.`,
62
+ };
63
+ }
64
+ catch (e) {
65
+ clearApiKey();
66
+ return {
67
+ handled: true,
68
+ error: `❌ **Connection Failed**: ${e.message || e}`,
69
+ };
70
+ }
71
+ }
72
+ async function handleStatusCommand() {
73
+ const apiKey = getApiKey();
74
+ if (!apiKey) {
75
+ return {
76
+ handled: true,
77
+ response: `ℹ️ **Atlas Cloud Status**\n\nNot connected. Use \`/connect atlascloud <api_key>\` to connect.`,
78
+ };
79
+ }
80
+ try {
81
+ const isValid = await validateApiKey(apiKey);
82
+ if (isValid) {
83
+ const models = await fetchModels(apiKey);
84
+ const masked = apiKey.substring(0, 8) + "...";
85
+ return {
86
+ handled: true,
87
+ response: `✅ **Atlas Cloud Status**\n\n- Connected: Yes\n- Key: \`${masked}\`\n- Models: ${models.length}`,
88
+ };
89
+ }
90
+ else {
91
+ return {
92
+ handled: true,
93
+ error: `⚠️ **Atlas Cloud Status**\n\nAPI key is configured but invalid. Use \`/connect atlascloud <api_key>\` to update.`,
94
+ };
95
+ }
96
+ }
97
+ catch (e) {
98
+ return {
99
+ handled: true,
100
+ error: `❌ **Status Check Failed**: ${e.message || e}`,
101
+ };
102
+ }
103
+ }
104
+ async function handleDisconnectCommand() {
105
+ const apiKey = getApiKey();
106
+ if (!apiKey) {
107
+ return {
108
+ handled: true,
109
+ response: `ℹ️ Atlas Cloud is not connected.`,
110
+ };
111
+ }
112
+ clearApiKey();
113
+ return {
114
+ handled: true,
115
+ response: `✅ **Disconnected from Atlas Cloud**\n\nAPI key removed. Restart OpenCode for changes to take effect.`,
116
+ };
117
+ }
118
+ async function handleCommand(command) {
119
+ const parts = command.trim().split(/\s+/);
120
+ const cmd = parts[0]?.toLowerCase();
121
+ const subCmd = parts[1]?.toLowerCase();
122
+ const args = parts.slice(2);
123
+ // Handle /connect atlascloud <key>
124
+ if (cmd === "connect" && subCmd === "atlascloud") {
125
+ return handleConnectCommand(args);
126
+ }
127
+ // Handle /atlascloud <subcommand>
128
+ if (cmd === "atlascloud") {
129
+ switch (subCmd) {
130
+ case "connect":
131
+ return handleConnectCommand(args);
132
+ case "status":
133
+ return handleStatusCommand();
134
+ case "disconnect":
135
+ return handleDisconnectCommand();
136
+ default:
137
+ return {
138
+ handled: true,
139
+ response: `**Atlas Cloud Commands**\n\n- \`/atlascloud connect <api_key>\` - Connect with API key\n- \`/atlascloud status\` - Check connection status\n- \`/atlascloud disconnect\` - Remove API key\n\nOr use: \`/connect atlascloud <api_key>\``,
140
+ };
141
+ }
142
+ }
143
+ return { handled: false };
144
+ }
145
+ // Debug logging helper
146
+ const DEBUG = process.env.ATLASCLOUD_DEBUG === "1" || process.env.DEBUG?.includes("atlascloud");
147
+ function log(...args) {
148
+ if (DEBUG) {
149
+ console.error("[atlascloud-plugin]", ...args);
150
+ }
151
+ }
152
+ // Helper to safely display API key
153
+ function maskKey(key) {
154
+ if (typeof key === "string" && key.length > 0) {
155
+ return key.slice(0, 12) + "...";
156
+ }
157
+ return "NONE";
158
+ }
159
+ export const AtlasCloudPlugin = async (ctx) => {
160
+ log("Plugin initializing...");
161
+ // Load configuration and fetch models on plugin initialization
162
+ const loadedConfig = loadConfig();
163
+ const apiKey = loadedConfig.apiKey;
164
+ log("API key loaded:", maskKey(apiKey));
165
+ // Fetch models (will use fallback if no API key)
166
+ const models = await fetchModels(apiKey);
167
+ const modelsObject = modelsToOpenCodeFormat(models);
168
+ log("Models loaded:", Object.keys(modelsObject).length);
169
+ log("Sample models:", Object.keys(modelsObject).slice(0, 5).join(", "));
170
+ return {
171
+ // Configuration hook to register the provider
172
+ config: async (config) => {
173
+ const currentApiKey = getApiKey();
174
+ log("Config hook called, apiKey:", maskKey(currentApiKey));
175
+ // Access the config to add the provider
176
+ const cfg = config;
177
+ cfg.provider = cfg.provider || {};
178
+ // Don't specify apiKey here - OpenCode will resolve it from auth.json
179
+ // The auth.json format is: { "atlascloud": { "type": "api", "key": "..." } }
180
+ log("Provider config: OpenCode will resolve API key from auth.json");
181
+ const providerConfig = {
182
+ id: PROVIDER_ID,
183
+ name: PROVIDER_NAME,
184
+ npm: "@ai-sdk/openai-compatible",
185
+ options: {
186
+ baseURL: ATLAS_CLOUD_API_BASE,
187
+ },
188
+ models: modelsObject,
189
+ };
190
+ cfg.provider[PROVIDER_ID] = providerConfig;
191
+ log("Provider registered:", JSON.stringify({ ...providerConfig, models: `[${Object.keys(modelsObject).length} models]` }, null, 2));
192
+ },
193
+ // Command hook for /connect atlascloud and /atlascloud commands
194
+ "tui.command.execute": async (input, output) => {
195
+ const result = await handleCommand(input.command);
196
+ if (result.handled) {
197
+ output.handled = true;
198
+ if (result.response)
199
+ output.response = result.response;
200
+ if (result.error)
201
+ output.error = result.error;
202
+ }
203
+ },
204
+ };
205
+ };
206
+ export default AtlasCloudPlugin;
207
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3BGLE9BQU8sRUFDTCxXQUFXLEVBQ1gsc0JBQXNCLEVBQ3RCLGNBQWMsRUFDZCxvQkFBb0IsR0FDckIsTUFBTSxvQkFBb0IsQ0FBQztBQUU1QixNQUFNLFdBQVcsR0FBRyxZQUFZLENBQUM7QUFDakMsTUFBTSxhQUFhLEdBQUcsYUFBYSxDQUFDO0FBRXBDLDBGQUEwRjtBQUMxRixTQUFTLHFCQUFxQjtJQUM1QixPQUFPLEtBQUssRUFBRSxHQUEyQixFQUFFLElBQWtCLEVBQXFCLEVBQUU7UUFDbEYsSUFBSSxJQUFJLEVBQUUsSUFBSSxJQUFJLE9BQU8sSUFBSSxDQUFDLElBQUksS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUNoRCxJQUFJLENBQUM7Z0JBQ0gsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBRW5DLHlEQUF5RDtnQkFDekQsSUFBSSxJQUFJLENBQUMsUUFBUSxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7b0JBQ2xELElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFRLEVBQUUsRUFBRTt3QkFDN0MsTUFBTSxFQUFFLGFBQWEsRUFBRSxHQUFHLElBQUksRUFBRSxHQUFHLEdBQUcsQ0FBQzt3QkFDdkMseURBQXlEO3dCQUN6RCxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7NEJBQ2hDLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxH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RUFBRSwyQkFBMkI7Z0JBQ2hDLE9BQU8sRUFBRTtvQkFDUCxPQUFPLEVBQUUsb0JBQW9CO2lCQUM5QjtnQkFDRCxNQUFNLEVBQUUsWUFBWTthQUNyQixDQUFDO1lBRUQsR0FBRyxDQUFDLFFBQW9DLENBQUMsV0FBVyxDQUFDLEdBQUcsY0FBYyxDQUFDO1lBQ3hFLEdBQUcsQ0FBQyxzQkFBc0IsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsR0FBRyxjQUFjLEVBQUUsTUFBTSxFQUFFLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxNQUFNLFVBQVUsRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3RJLENBQUM7UUFFRCxnRUFBZ0U7UUFDaEUscUJBQXFCLEVBQUUsS0FBSyxFQUFFLEtBQVUsRUFBRSxNQUFXLEVBQUUsRUFBRTtZQUN2RCxNQUFNLE1BQU0sR0FBRyxNQUFNLGFBQWEsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDbEQsSUFBSSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ25CLE1BQU0sQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO2dCQUN0QixJQUFJLE1BQU0sQ0FBQyxRQUFRO29CQUFFLE1BQU0sQ0FBQyxRQUFRLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQztnQkFDdkQsSUFBSSxNQUFNLENBQUMsS0FBSztvQkFBRSxNQUFNLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUM7WUFDaEQsQ0FBQztRQUNILENBQUM7S0FDRixDQUFDO0FBQ0osQ0FBQyxDQUFDO0FBRUYsZUFBZSxnQkFBZ0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgUGx1Z2luIH0gZnJvbSBcIkBvcGVuY29kZS1haS9wbHVnaW5cIjtcbmltcG9ydCB7IGxvYWRDb25maWcsIHNhdmVBcGlLZXksIGdldEFwaUtleSwgY2xlYXJBcGlLZXkgfSBmcm9tIFwiLi9zZXJ2ZXIvY29uZmlnLmpzXCI7XG5pbXBvcnQge1xuICBmZXRjaE1vZGVscyxcbiAgbW9kZWxzVG9PcGVuQ29kZUZvcm1hdCxcbiAgdmFsaWRhdGVBcGlLZXksXG4gIEFUTEFTX0NMT1VEX0FQSV9CQVNFLFxufSBmcm9tIFwiLi9zZXJ2ZXIvbW9kZWxzLmpzXCI7XG5cbmNvbnN0IFBST1ZJREVSX0lEID0gXCJhdGxhc2Nsb3VkXCI7XG5jb25zdCBQUk9WSURFUl9OQU1FID0gXCJBdGxhcyBDbG91ZFwiO1xuXG4vLyBDdXN0b20gZmV0Y2ggdGhhdCBzdHJpcHMgQW50aHJvcGljLXNwZWNpZmljIHBhcmFtZXRlcnMgdGhhdCBBdGxhcyBDbG91ZCBkb2Vzbid0IHN1cHBvcnRcbmZ1bmN0aW9uIGNyZWF0ZUF0bGFzQ2xvdWRGZXRjaCgpIHtcbiAgcmV0dXJuIGFzeW5jICh1cmw6IHN0cmluZyB8IFVSTCB8IFJlcXVlc3QsIGluaXQ/OiBSZXF1ZXN0SW5pdCk6IFByb21pc2U8UmVzcG9uc2U+ID0+IHtcbiAgICBpZiAoaW5pdD8uYm9keSAmJiB0eXBlb2YgaW5pdC5ib2R5ID09PSBcInN0cmluZ1wiKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBib2R5ID0gSlNPTi5wYXJzZShpbml0LmJvZHkpO1xuXG4gICAgICAgIC8vIFN0cmlwIGNhY2hlX2NvbnRyb2wgZnJvbSBtZXNzYWdlcyAoQW50aHJvcGljLXNwZWNpZmljKVxuICAgICAgICBpZiAoYm9keS5tZXNzYWdlcyAmJiBBcnJheS5pc0FycmF5KGJvZHkubWVzc2FnZXMpKSB7XG4gICAgICAgICAgYm9keS5tZXNzYWdlcyA9IGJvZHkubWVzc2FnZXMubWFwKChtc2c6IGFueSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgeyBjYWNoZV9jb250cm9sLCAuLi5yZXN0IH0gPSBtc2c7XG4gICAgICAgICAgICAvLyBBbHNvIHN0cmlwIGNhY2hlX2NvbnRyb2wgZnJvbSBjb250ZW50IGlmIGl0J3MgYW4gYXJyYXlcbiAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHJlc3QuY29udGVudCkpIHtcbiAgICAgICAgICAgICAgcmVzdC5jb250ZW50ID0gcmVzdC5jb250ZW50Lm1hcCgoYzogYW55KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgeyBjYWNoZV9jb250cm9sOiBjYywgLi4uY29udGVudFJlc3QgfSA9IGM7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvbnRlbnRSZXN0O1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN0O1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU3RyaXAgb3RoZXIgQW50aHJvcGljLXNwZWNpZmljIHBhcmFtZXRlcnNcbiAgICAgICAgZGVsZXRlIGJvZHkuYW50aHJvcGljX3ZlcnNpb247XG4gICAgICAgIGRlbGV0ZSBib2R5Lm1ldGFkYXRhO1xuXG4gICAgICAgIGluaXQgPSB7XG4gICAgICAgICAgLi4uaW5pdCxcbiAgICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeShib2R5KSxcbiAgICAgICAgfTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBOb3QgSlNPTiBvciBwYXJzZSBlcnJvciwgcGFzcyB0aHJvdWdoIGFzLWlzXG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZldGNoKHVybCwgaW5pdCk7XG4gIH07XG59XG5cbmludGVyZmFjZSBDb21tYW5kUmVzdWx0IHtcbiAgaGFuZGxlZDogYm9vbGVhbjtcbiAgcmVzcG9uc2U/OiBzdHJpbmc7XG4gIGVycm9yPzogc3RyaW5nO1xufVxuXG5hc3luYyBmdW5jdGlvbiBoYW5kbGVDb25uZWN0Q29tbWFuZChhcmdzOiBzdHJpbmdbXSk6IFByb21pc2U8Q29tbWFuZFJlc3VsdD4ge1xuICBjb25zdCBrZXkgPSBhcmdzWzBdO1xuXG4gIGlmICgha2V5KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGhhbmRsZWQ6IHRydWUsXG4gICAgICBlcnJvcjogYFVzYWdlOiAvY29ubmVjdCBhdGxhc2Nsb3VkIDx5b3VyX2FwaV9rZXk+YCxcbiAgICB9O1xuICB9XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBpc1ZhbGlkID0gYXdhaXQgdmFsaWRhdGVBcGlLZXkoa2V5KTtcblxuICAgIGlmICghaXNWYWxpZCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaGFuZGxlZDogdHJ1ZSxcbiAgICAgICAgZXJyb3I6IGDinYwgKipJbnZhbGlkIEFQSSBLZXkqKlxcblxcblRoZSBBUEkga2V5IGNvdWxkIG5vdCBiZSB2YWxpZGF0ZWQuIFBsZWFzZSBjaGVjayB5b3VyIGtleSBhbmQgdHJ5IGFnYWluLmAsXG4gICAgICB9O1xuICAgIH1cblxuICAgIHNhdmVBcGlLZXkoa2V5KTtcbiAgICBjb25zdCBtb2RlbHMgPSBhd2FpdCBmZXRjaE1vZGVscyhrZXkpO1xuICAgIGNvbnN0IG1hc2tlZCA9IGtleS5zdWJzdHJpbmcoMCwgOCkgKyBcIi4uLlwiICsga2V5LnN1YnN0cmluZyhrZXkubGVuZ3RoIC0gNCk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgaGFuZGxlZDogdHJ1ZSxcbiAgICAgIHJlc3BvbnNlOiBg4pyFICoqQXRsYXMgQ2xvdWQgQ29ubmVjdGVkISoqXFxuXFxuLSBLZXk6IFxcYCR7bWFza2VkfVxcYFxcbi0gTW9kZWxzIEF2YWlsYWJsZTogJHttb2RlbHMubGVuZ3RofVxcblxcbioqUmVzdGFydCBPcGVuQ29kZSoqIHRvIGxvYWQgdGhlIG1vZGVscy5gLFxuICAgIH07XG4gIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgIGNsZWFyQXBpS2V5KCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGhhbmRsZWQ6IHRydWUsXG4gICAgICBlcnJvcjogYOKdjCAqKkNvbm5lY3Rpb24gRmFpbGVkKio6ICR7ZS5tZXNzYWdlIHx8IGV9YCxcbiAgICB9O1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGhhbmRsZVN0YXR1c0NvbW1hbmQoKTogUHJvbWlzZTxDb21tYW5kUmVzdWx0PiB7XG4gIGNvbnN0IGFwaUtleSA9IGdldEFwaUtleSgpO1xuXG4gIGlmICghYXBpS2V5KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGhhbmRsZWQ6IHRydWUsXG4gICAgICByZXNwb25zZTogYOKEue+4jyAqKkF0bGFzIENsb3VkIFN0YXR1cyoqXFxuXFxuTm90IGNvbm5lY3RlZC4gVXNlIFxcYC9jb25uZWN0IGF0bGFzY2xvdWQgPGFwaV9rZXk+XFxgIHRvIGNvbm5lY3QuYCxcbiAgICB9O1xuICB9XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBpc1ZhbGlkID0gYXdhaXQgdmFsaWRhdGVBcGlLZXkoYXBpS2V5KTtcbiAgICBpZiAoaXNWYWxpZCkge1xuICAgICAgY29uc3QgbW9kZWxzID0gYXdhaXQgZmV0Y2hNb2RlbHMoYXBpS2V5KTtcbiAgICAgIGNvbnN0IG1hc2tlZCA9IGFwaUtleS5zdWJzdHJpbmcoMCwgOCkgKyBcIi4uLlwiO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaGFuZGxlZDogdHJ1ZSxcbiAgICAgICAgcmVzcG9uc2U6IGDinIUgKipBdGxhcyBDbG91ZCBTdGF0dXMqKlxcblxcbi0gQ29ubmVjdGVkOiBZZXNcXG4tIEtleTogXFxgJHttYXNrZWR9XFxgXFxuLSBNb2RlbHM6ICR7bW9kZWxzLmxlbmd0aH1gLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaGFuZGxlZDogdHJ1ZSxcbiAgICAgICAgZXJyb3I6IGDimqDvuI8gKipBdGxhcyBDbG91ZCBTdGF0dXMqKlxcblxcbkFQSSBrZXkgaXMgY29uZmlndXJlZCBidXQgaW52YWxpZC4gVXNlIFxcYC9jb25uZWN0IGF0bGFzY2xvdWQgPGFwaV9rZXk+XFxgIHRvIHVwZGF0ZS5gLFxuICAgICAgfTtcbiAgICB9XG4gIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgIHJldHVybiB7XG4gICAgICBoYW5kbGVkOiB0cnVlLFxuICAgICAgZXJyb3I6IGDinYwgKipTdGF0dXMgQ2hlY2sgRmFpbGVkKio6ICR7ZS5tZXNzYWdlIHx8IGV9YCxcbiAgICB9O1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGhhbmRsZURpc2Nvbm5lY3RDb21tYW5kKCk6IFByb21pc2U8Q29tbWFuZFJlc3VsdD4ge1xuICBjb25zdCBhcGlLZXkgPSBnZXRBcGlLZXkoKTtcblxuICBpZiAoIWFwaUtleSkge1xuICAgIHJldHVybiB7XG4gICAgICBoYW5kbGVkOiB0cnVlLFxuICAgICAgcmVzcG9uc2U6IGDihLnvuI8gQXRsYXMgQ2xvdWQgaXMgbm90IGNvbm5lY3RlZC5gLFxuICAgIH07XG4gIH1cblxuICBjbGVhckFwaUtleSgpO1xuICByZXR1cm4ge1xuICAgIGhhbmRsZWQ6IHRydWUsXG4gICAgcmVzcG9uc2U6IGDinIUgKipEaXNjb25uZWN0ZWQgZnJvbSBBdGxhcyBDbG91ZCoqXFxuXFxuQVBJIGtleSByZW1vdmVkLiBSZXN0YXJ0IE9wZW5Db2RlIGZvciBjaGFuZ2VzIHRvIHRha2UgZWZmZWN0LmAsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGhhbmRsZUNvbW1hbmQoY29tbWFuZDogc3RyaW5nKTogUHJvbWlzZTxDb21tYW5kUmVzdWx0PiB7XG4gIGNvbnN0IHBhcnRzID0gY29tbWFuZC50cmltKCkuc3BsaXQoL1xccysvKTtcbiAgY29uc3QgY21kID0gcGFydHNbMF0/LnRvTG93ZXJDYXNlKCk7XG4gIGNvbnN0IHN1YkNtZCA9IHBhcnRzWzFdPy50b0xvd2VyQ2FzZSgpO1xuICBjb25zdCBhcmdzID0gcGFydHMuc2xpY2UoMik7XG5cbiAgLy8gSGFuZGxlIC9jb25uZWN0IGF0bGFzY2xvdWQgPGtleT5cbiAgaWYgKGNtZCA9PT0gXCJjb25uZWN0XCIgJiYgc3ViQ21kID09PSBcImF0bGFzY2xvdWRcIikge1xuICAgIHJldHVybiBoYW5kbGVDb25uZWN0Q29tbWFuZChhcmdzKTtcbiAgfVxuXG4gIC8vIEhhbmRsZSAvYXRsYXNjbG91ZCA8c3ViY29tbWFuZD5cbiAgaWYgKGNtZCA9PT0gXCJhdGxhc2Nsb3VkXCIpIHtcbiAgICBzd2l0Y2ggKHN1YkNtZCkge1xuICAgICAgY2FzZSBcImNvbm5lY3RcIjpcbiAgICAgICAgcmV0dXJuIGhhbmRsZUNvbm5lY3RDb21tYW5kKGFyZ3MpO1xuICAgICAgY2FzZSBcInN0YXR1c1wiOlxuICAgICAgICByZXR1cm4gaGFuZGxlU3RhdHVzQ29tbWFuZCgpO1xuICAgICAgY2FzZSBcImRpc2Nvbm5lY3RcIjpcbiAgICAgICAgcmV0dXJuIGhhbmRsZURpc2Nvbm5lY3RDb21tYW5kKCk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGhhbmRsZWQ6IHRydWUsXG4gICAgICAgICAgcmVzcG9uc2U6IGAqKkF0bGFzIENsb3VkIENvbW1hbmRzKipcXG5cXG4tIFxcYC9hdGxhc2Nsb3VkIGNvbm5lY3QgPGFwaV9rZXk+XFxgIC0gQ29ubmVjdCB3aXRoIEFQSSBrZXlcXG4tIFxcYC9hdGxhc2Nsb3VkIHN0YXR1c1xcYCAtIENoZWNrIGNvbm5lY3Rpb24gc3RhdHVzXFxuLSBcXGAvYXRsYXNjbG91ZCBkaXNjb25uZWN0XFxgIC0gUmVtb3ZlIEFQSSBrZXlcXG5cXG5PciB1c2U6IFxcYC9jb25uZWN0IGF0bGFzY2xvdWQgPGFwaV9rZXk+XFxgYCxcbiAgICAgICAgfTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4geyBoYW5kbGVkOiBmYWxzZSB9O1xufVxuXG4vLyBEZWJ1ZyBsb2dnaW5nIGhlbHBlclxuY29uc3QgREVCVUcgPSBwcm9jZXNzLmVudi5BVExBU0NMT1VEX0RFQlVHID09PSBcIjFcIiB8fCBwcm9jZXNzLmVudi5ERUJVRz8uaW5jbHVkZXMoXCJhdGxhc2Nsb3VkXCIpO1xuZnVuY3Rpb24gbG9nKC4uLmFyZ3M6IGFueVtdKSB7XG4gIGlmIChERUJVRykge1xuICAgIGNvbnNvbGUuZXJyb3IoXCJbYXRsYXNjbG91ZC1wbHVnaW5dXCIsIC4uLmFyZ3MpO1xuICB9XG59XG5cbi8vIEhlbHBlciB0byBzYWZlbHkgZGlzcGxheSBBUEkga2V5XG5mdW5jdGlvbiBtYXNrS2V5KGtleTogdW5rbm93bik6IHN0cmluZyB7XG4gIGlmICh0eXBlb2Yga2V5ID09PSBcInN0cmluZ1wiICYmIGtleS5sZW5ndGggPiAwKSB7XG4gICAgcmV0dXJuIGtleS5zbGljZSgwLCAxMikgKyBcIi4uLlwiO1xuICB9XG4gIHJldHVybiBcIk5PTkVcIjtcbn1cblxuZXhwb3J0IGNvbnN0IEF0bGFzQ2xvdWRQbHVnaW46IFBsdWdpbiA9IGFzeW5jIChjdHgpID0+IHtcbiAgbG9nKFwiUGx1Z2luIGluaXRpYWxpemluZy4uLlwiKTtcblxuICAvLyBMb2FkIGNvbmZpZ3VyYXRpb24gYW5kIGZldGNoIG1vZGVscyBvbiBwbHVnaW4gaW5pdGlhbGl6YXRpb25cbiAgY29uc3QgbG9hZGVkQ29uZmlnID0gbG9hZENvbmZpZygpO1xuICBjb25zdCBhcGlLZXkgPSBsb2FkZWRDb25maWcuYXBpS2V5O1xuICBsb2coXCJBUEkga2V5IGxvYWRlZDpcIiwgbWFza0tleShhcGlLZXkpKTtcblxuICAvLyBGZXRjaCBtb2RlbHMgKHdpbGwgdXNlIGZhbGxiYWNrIGlmIG5vIEFQSSBrZXkpXG4gIGNvbnN0IG1vZGVscyA9IGF3YWl0IGZldGNoTW9kZWxzKGFwaUtleSk7XG4gIGNvbnN0IG1vZGVsc09iamVjdCA9IG1vZGVsc1RvT3BlbkNvZGVGb3JtYXQobW9kZWxzKTtcbiAgbG9nKFwiTW9kZWxzIGxvYWRlZDpcIiwgT2JqZWN0LmtleXMobW9kZWxzT2JqZWN0KS5sZW5ndGgpO1xuICBsb2coXCJTYW1wbGUgbW9kZWxzOlwiLCBPYmplY3Qua2V5cyhtb2RlbHNPYmplY3QpLnNsaWNlKDAsIDUpLmpvaW4oXCIsIFwiKSk7XG5cbiAgcmV0dXJuIHtcbiAgICAvLyBDb25maWd1cmF0aW9uIGhvb2sgdG8gcmVnaXN0ZXIgdGhlIHByb3ZpZGVyXG4gICAgY29uZmlnOiBhc3luYyAoY29uZmlnKSA9PiB7XG4gICAgICBjb25zdCBjdXJyZW50QXBpS2V5ID0gZ2V0QXBpS2V5KCk7XG4gICAgICBsb2coXCJDb25maWcgaG9vayBjYWxsZWQsIGFwaUtleTpcIiwgbWFza0tleShjdXJyZW50QXBpS2V5KSk7XG5cbiAgICAgIC8vIEFjY2VzcyB0aGUgY29uZmlnIHRvIGFkZCB0aGUgcHJvdmlkZXJcbiAgICAgIGNvbnN0IGNmZyA9IGNvbmZpZyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgIGNmZy5wcm92aWRlciA9IGNmZy5wcm92aWRlciB8fCB7fTtcblxuICAgICAgLy8gRG9uJ3Qgc3BlY2lmeSBhcGlLZXkgaGVyZSAtIE9wZW5Db2RlIHdpbGwgcmVzb2x2ZSBpdCBmcm9tIGF1dGguanNvblxuICAgICAgLy8gVGhlIGF1dGguanNvbiBmb3JtYXQgaXM6IHsgXCJhdGxhc2Nsb3VkXCI6IHsgXCJ0eXBlXCI6IFwiYXBpXCIsIFwia2V5XCI6IFwiLi4uXCIgfSB9XG4gICAgICBsb2coXCJQcm92aWRlciBjb25maWc6IE9wZW5Db2RlIHdpbGwgcmVzb2x2ZSBBUEkga2V5IGZyb20gYXV0aC5qc29uXCIpO1xuXG4gICAgICBjb25zdCBwcm92aWRlckNvbmZpZyA9IHtcbiAgICAgICAgaWQ6IFBST1ZJREVSX0lELFxuICAgICAgICBuYW1lOiBQUk9WSURFUl9OQU1FLFxuICAgICAgICBucG06IFwiQGFpLXNkay9vcGVuYWktY29tcGF0aWJsZVwiLFxuICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgYmFzZVVSTDogQVRMQVNfQ0xPVURfQVBJX0JBU0UsXG4gICAgICAgIH0sXG4gICAgICAgIG1vZGVsczogbW9kZWxzT2JqZWN0LFxuICAgICAgfTtcblxuICAgICAgKGNmZy5wcm92aWRlciBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPilbUFJPVklERVJfSURdID0gcHJvdmlkZXJDb25maWc7XG4gICAgICBsb2coXCJQcm92aWRlciByZWdpc3RlcmVkOlwiLCBKU09OLnN0cmluZ2lmeSh7IC4uLnByb3ZpZGVyQ29uZmlnLCBtb2RlbHM6IGBbJHtPYmplY3Qua2V5cyhtb2RlbHNPYmplY3QpLmxlbmd0aH0gbW9kZWxzXWAgfSwgbnVsbCwgMikpO1xuICAgIH0sXG5cbiAgICAvLyBDb21tYW5kIGhvb2sgZm9yIC9jb25uZWN0IGF0bGFzY2xvdWQgYW5kIC9hdGxhc2Nsb3VkIGNvbW1hbmRzXG4gICAgXCJ0dWkuY29tbWFuZC5leGVjdXRlXCI6IGFzeW5jIChpbnB1dDogYW55LCBvdXRwdXQ6IGFueSkgPT4ge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgaGFuZGxlQ29tbWFuZChpbnB1dC5jb21tYW5kKTtcbiAgICAgIGlmIChyZXN1bHQuaGFuZGxlZCkge1xuICAgICAgICBvdXRwdXQuaGFuZGxlZCA9IHRydWU7XG4gICAgICAgIGlmIChyZXN1bHQucmVzcG9uc2UpIG91dHB1dC5yZXNwb25zZSA9IHJlc3VsdC5yZXNwb25zZTtcbiAgICAgICAgaWYgKHJlc3VsdC5lcnJvcikgb3V0cHV0LmVycm9yID0gcmVzdWx0LmVycm9yO1xuICAgICAgfVxuICAgIH0sXG4gIH07XG59O1xuXG5leHBvcnQgZGVmYXVsdCBBdGxhc0Nsb3VkUGx1Z2luO1xuIl19
@@ -0,0 +1,9 @@
1
+ export interface AtlasCloudConfig {
2
+ version: string;
3
+ apiKey?: string;
4
+ }
5
+ export declare function loadConfig(): AtlasCloudConfig;
6
+ export declare function saveConfig(config: AtlasCloudConfig): void;
7
+ export declare function saveApiKey(apiKey: string): void;
8
+ export declare function getApiKey(): string | undefined;
9
+ export declare function clearApiKey(): void;
@@ -0,0 +1,133 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import * as os from "node:os";
4
+ const CONFIG_DIR = path.join(os.homedir(), ".atlascloud");
5
+ const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
6
+ const OPENCODE_AUTH_DIR = path.join(os.homedir(), ".local", "share", "opencode");
7
+ const OPENCODE_AUTH_FILE = path.join(OPENCODE_AUTH_DIR, "auth.json");
8
+ const DEFAULT_CONFIG = {
9
+ version: "1.0.0",
10
+ };
11
+ function ensureConfigDir() {
12
+ if (!fs.existsSync(CONFIG_DIR)) {
13
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
14
+ }
15
+ }
16
+ function ensureOpenCodeAuthDir() {
17
+ if (!fs.existsSync(OPENCODE_AUTH_DIR)) {
18
+ fs.mkdirSync(OPENCODE_AUTH_DIR, { recursive: true });
19
+ }
20
+ }
21
+ export function loadConfig() {
22
+ // First, try to load from our own config file
23
+ if (fs.existsSync(CONFIG_FILE)) {
24
+ try {
25
+ const content = fs.readFileSync(CONFIG_FILE, "utf-8");
26
+ const config = JSON.parse(content);
27
+ if (config.apiKey) {
28
+ return config;
29
+ }
30
+ }
31
+ catch (error) {
32
+ // Config file exists but is invalid, continue to check other sources
33
+ }
34
+ }
35
+ // Check OpenCode's auth.json for the "atlascloud" key
36
+ if (fs.existsSync(OPENCODE_AUTH_FILE)) {
37
+ try {
38
+ const content = fs.readFileSync(OPENCODE_AUTH_FILE, "utf-8");
39
+ const authData = JSON.parse(content);
40
+ const atlasAuth = authData.atlascloud;
41
+ // Handle both new format { type: "api", key: "..." } and legacy string format
42
+ if (atlasAuth) {
43
+ const key = typeof atlasAuth === "object" && atlasAuth.type === "api"
44
+ ? atlasAuth.key
45
+ : typeof atlasAuth === "string"
46
+ ? atlasAuth
47
+ : undefined;
48
+ if (key) {
49
+ return {
50
+ ...DEFAULT_CONFIG,
51
+ apiKey: key,
52
+ };
53
+ }
54
+ }
55
+ }
56
+ catch (error) {
57
+ // Auth file exists but is invalid or doesn't have atlascloud key
58
+ }
59
+ }
60
+ // Check environment variable
61
+ const envApiKey = process.env.ATLASCLOUD_API_KEY;
62
+ if (envApiKey) {
63
+ return {
64
+ ...DEFAULT_CONFIG,
65
+ apiKey: envApiKey,
66
+ };
67
+ }
68
+ return DEFAULT_CONFIG;
69
+ }
70
+ export function saveConfig(config) {
71
+ ensureConfigDir();
72
+ fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
73
+ }
74
+ function loadOpenCodeAuth() {
75
+ if (fs.existsSync(OPENCODE_AUTH_FILE)) {
76
+ try {
77
+ const content = fs.readFileSync(OPENCODE_AUTH_FILE, "utf-8");
78
+ return JSON.parse(content);
79
+ }
80
+ catch {
81
+ return {};
82
+ }
83
+ }
84
+ return {};
85
+ }
86
+ function saveOpenCodeAuth(auth) {
87
+ ensureOpenCodeAuthDir();
88
+ fs.writeFileSync(OPENCODE_AUTH_FILE, JSON.stringify(auth, null, 2));
89
+ }
90
+ export function saveApiKey(apiKey) {
91
+ // Save to our own config
92
+ const config = loadConfig();
93
+ config.apiKey = apiKey;
94
+ saveConfig(config);
95
+ // Save to OpenCode's auth.json in the correct format
96
+ const existingAuth = loadOpenCodeAuth();
97
+ const auth = {};
98
+ // Preserve existing entries (convert if needed)
99
+ for (const [key, value] of Object.entries(existingAuth)) {
100
+ if (typeof value === "object" && value !== null && value.type === "api") {
101
+ auth[key] = value;
102
+ }
103
+ }
104
+ // Add/update atlascloud entry
105
+ auth.atlascloud = {
106
+ type: "api",
107
+ key: apiKey,
108
+ };
109
+ saveOpenCodeAuth(auth);
110
+ }
111
+ export function getApiKey() {
112
+ return loadConfig().apiKey;
113
+ }
114
+ export function clearApiKey() {
115
+ // Clear from our config
116
+ const config = loadConfig();
117
+ delete config.apiKey;
118
+ saveConfig(config);
119
+ // Also clear from OpenCode's auth.json
120
+ if (fs.existsSync(OPENCODE_AUTH_FILE)) {
121
+ try {
122
+ const content = fs.readFileSync(OPENCODE_AUTH_FILE, "utf-8");
123
+ const authData = JSON.parse(content);
124
+ delete authData.atlascloud;
125
+ ensureOpenCodeAuthDir();
126
+ fs.writeFileSync(OPENCODE_AUTH_FILE, JSON.stringify(authData, null, 2));
127
+ }
128
+ catch {
129
+ // Ignore errors
130
+ }
131
+ }
132
+ }
133
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcnZlci9jb25maWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDOUIsT0FBTyxLQUFLLElBQUksTUFBTSxXQUFXLENBQUM7QUFDbEMsT0FBTyxLQUFLLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFPOUIsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLEVBQUUsYUFBYSxDQUFDLENBQUM7QUFDMUQsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsYUFBYSxDQUFDLENBQUM7QUFDekQsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0FBQ2pGLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxXQUFXLENBQUMsQ0FBQztBQUVyRSxNQUFNLGNBQWMsR0FBcUI7SUFDdkMsT0FBTyxFQUFFLE9BQU87Q0FDakIsQ0FBQztBQUVGLFNBQVMsZUFBZTtJQUN0QixJQUFJLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1FBQy9CLEVBQUUsQ0FBQyxTQUFTLENBQUMsVUFBVSxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7SUFDaEQsQ0FBQztBQUNILENBQUM7QUFFRCxTQUFTLHFCQUFxQjtJQUM1QixJQUFJLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLENBQUM7UUFDdEMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxpQkFBaUIsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxD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QyxFQUFFLENBQUM7UUFDdEMsSUFBSSxDQUFDO1lBQ0gsTUFBTSxPQUFPLEdBQUcsRUFBRSxDQUFDLFlBQVksQ0FBQyxrQkFBa0IsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUM3RCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3JDLE9BQU8sUUFBUSxDQUFDLFVBQVUsQ0FBQztZQUMzQixxQkFBcUIsRUFBRSxDQUFDO1lBQ3hCLEVBQUUsQ0FBQyxhQUFhLENBQUMsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDMUUsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNQLGdCQUFnQjtRQUNsQixDQUFDO0lBQ0gsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBmcyBmcm9tIFwibm9kZTpmc1wiO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgKiBhcyBvcyBmcm9tIFwibm9kZTpvc1wiO1xuXG5leHBvcnQgaW50ZXJmYWNlIEF0bGFzQ2xvdWRDb25maWcge1xuICB2ZXJzaW9uOiBzdHJpbmc7XG4gIGFwaUtleT86IHN0cmluZztcbn1cblxuY29uc3QgQ09ORklHX0RJUiA9IHBhdGguam9pbihvcy5ob21lZGlyKCksIFwiLmF0bGFzY2xvdWRcIik7XG5jb25zdCBDT05GSUdfRklMRSA9IHBhdGguam9pbihDT05GSUdfRElSLCBcImNvbmZpZy5qc29uXCIpO1xuY29uc3QgT1BFTkNPREVfQVVUSF9ESVIgPSBwYXRoLmpvaW4ob3MuaG9tZWRpcigpLCBcIi5sb2NhbFwiLCBcInNoYXJlXCIsIFwib3BlbmNvZGVcIik7XG5jb25zdCBPUEVOQ09ERV9BVVRIX0ZJTEUgPSBwYXRoLmpvaW4oT1BFTkNPREVfQVVUSF9ESVIsIFwiYXV0aC5qc29uXCIpO1xuXG5jb25zdCBERUZBVUxUX0NPTkZJRzogQXRsYXNDbG91ZENvbmZpZyA9IHtcbiAgdmVyc2lvbjogXCIxLjAuMFwiLFxufTtcblxuZnVuY3Rpb24gZW5zdXJlQ29uZmlnRGlyKCk6IHZvaWQge1xuICBpZiAoIWZzLmV4aXN0c1N5bmMoQ09ORklHX0RJUikpIHtcbiAgICBmcy5ta2RpclN5bmMoQ09ORklHX0RJUiwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZW5zdXJlT3BlbkNvZGVBdXRoRGlyKCk6IHZvaWQge1xuICBpZiAoIWZzLmV4aXN0c1N5bmMoT1BFTkNPREVfQVVUSF9ESVIpKSB7XG4gICAgZnMubWtkaXJTeW5jKE9QRU5DT0RFX0FVVEhfRElSLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbG9hZENvbmZpZygpOiBBdGxhc0Nsb3VkQ29uZmlnIHtcbiAgLy8gRmlyc3QsIHRyeSB0byBsb2FkIGZyb20gb3VyIG93biBjb25maWcgZmlsZVxuICBpZiAoZnMuZXhpc3RzU3luYyhDT05GSUdfRklMRSkpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhDT05GSUdfRklMRSwgXCJ1dGYtOFwiKTtcbiAgICAgIGNvbnN0IGNvbmZpZyA9IEpTT04ucGFyc2UoY29udGVudCkgYXMgQXRsYXNDbG91ZENvbmZpZztcbiAgICAgIGlmIChjb25maWcuYXBpS2V5KSB7XG4gICAgICAgIHJldHVybiBjb25maWc7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIC8vIENvbmZpZyBmaWxlIGV4aXN0cyBidXQgaXMgaW52YWxpZCwgY29udGludWUgdG8gY2hlY2sgb3RoZXIgc291cmNlc1xuICAgIH1cbiAgfVxuXG4gIC8vIENoZWNrIE9wZW5Db2RlJ3MgYXV0aC5qc29uIGZvciB0aGUgXCJhdGxhc2Nsb3VkXCIga2V5XG4gIGlmIChmcy5leGlzdHNTeW5jKE9QRU5DT0RFX0FVVEhfRklMRSkpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhPUEVOQ09ERV9BVVRIX0ZJTEUsIFwidXRmLThcIik7XG4gICAgICBjb25zdCBhdXRoRGF0YSA9IEpTT04ucGFyc2UoY29udGVudCk7XG4gICAgICBjb25zdCBhdGxhc0F1dGggPSBhdXRoRGF0YS5hdGxhc2Nsb3VkO1xuICAgICAgLy8gSGFuZGxlIGJvdGggbmV3IGZvcm1hdCB7IHR5cGU6IFwiYXBpXCIsIGtleTogXCIuLi5cIiB9IGFuZCBsZWdhY3kgc3RyaW5nIGZvcm1hdFxuICAgICAgaWYgKGF0bGFzQXV0aCkge1xuICAgICAgICBjb25zdCBrZXkgPSB0eXBlb2YgYXRsYXNBdXRoID09PSBcIm9iamVjdFwiICYmIGF0bGFzQXV0aC50eXBlID09PSBcImFwaVwiXG4gICAgICAgICAgPyBhdGxhc0F1dGgua2V5XG4gICAgICAgICAgOiB0eXBlb2YgYXRsYXNBdXRoID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgICA/IGF0bGFzQXV0aFxuICAgICAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChrZXkpIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLi4uREVGQVVMVF9DT05GSUcsXG4gICAgICAgICAgICBhcGlLZXk6IGtleSxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIC8vIEF1dGggZmlsZSBleGlzdHMgYnV0IGlzIGludmFsaWQgb3IgZG9lc24ndCBoYXZlIGF0bGFzY2xvdWQga2V5XG4gICAgfVxuICB9XG5cbiAgLy8gQ2hlY2sgZW52aXJvbm1lbnQgdmFyaWFibGVcbiAgY29uc3QgZW52QXBpS2V5ID0gcHJvY2Vzcy5lbnYuQVRMQVNDTE9VRF9BUElfS0VZO1xuICBpZiAoZW52QXBpS2V5KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLkRFRkFVTFRfQ09ORklHLFxuICAgICAgYXBpS2V5OiBlbnZBcGlLZXksXG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBERUZBVUxUX0NPTkZJRztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNhdmVDb25maWcoY29uZmlnOiBBdGxhc0Nsb3VkQ29uZmlnKTogdm9pZCB7XG4gIGVuc3VyZUNvbmZpZ0RpcigpO1xuICBmcy53cml0ZUZpbGVTeW5jKENPTkZJR19GSUxFLCBKU09OLnN0cmluZ2lmeShjb25maWcsIG51bGwsIDIpKTtcbn1cblxuZnVuY3Rpb24gbG9hZE9wZW5Db2RlQXV0aCgpOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gIGlmIChmcy5leGlzdHNTeW5jKE9QRU5DT0RFX0FVVEhfRklMRSkpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhPUEVOQ09ERV9BVVRIX0ZJTEUsIFwidXRmLThcIik7XG4gICAgICByZXR1cm4gSlNPTi5wYXJzZShjb250ZW50KTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHt9O1xufVxuXG5pbnRlcmZhY2UgT3BlbkNvZGVBdXRoRW50cnkge1xuICB0eXBlOiBcImFwaVwiO1xuICBrZXk6IHN0cmluZztcbn1cblxuZnVuY3Rpb24gc2F2ZU9wZW5Db2RlQXV0aChhdXRoOiBSZWNvcmQ8c3RyaW5nLCBPcGVuQ29kZUF1dGhFbnRyeT4pOiB2b2lkIHtcbiAgZW5zdXJlT3BlbkNvZGVBdXRoRGlyKCk7XG4gIGZzLndyaXRlRmlsZVN5bmMoT1BFTkNPREVfQVVUSF9GSUxFLCBKU09OLnN0cmluZ2lmeShhdXRoLCBudWxsLCAyKSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzYXZlQXBpS2V5KGFwaUtleTogc3RyaW5nKTogdm9pZCB7XG4gIC8vIFNhdmUgdG8gb3VyIG93biBjb25maWdcbiAgY29uc3QgY29uZmlnID0gbG9hZENvbmZpZygpO1xuICBjb25maWcuYXBpS2V5ID0gYXBpS2V5O1xuICBzYXZlQ29uZmlnKGNvbmZpZyk7XG5cbiAgLy8gU2F2ZSB0byBPcGVuQ29kZSdzIGF1dGguanNvbiBpbiB0aGUgY29ycmVjdCBmb3JtYXRcbiAgY29uc3QgZXhpc3RpbmdBdXRoID0gbG9hZE9wZW5Db2RlQXV0aCgpO1xuICBjb25zdCBhdXRoOiBSZWNvcmQ8c3RyaW5nLCBPcGVuQ29kZUF1dGhFbnRyeT4gPSB7fTtcblxuICAvLyBQcmVzZXJ2ZSBleGlzdGluZyBlbnRyaWVzIChjb252ZXJ0IGlmIG5lZWRlZClcbiAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMoZXhpc3RpbmdBdXRoKSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwib2JqZWN0XCIgJiYgdmFsdWUgIT09IG51bGwgJiYgKHZhbHVlIGFzIGFueSkudHlwZSA9PT0gXCJhcGlcIikge1xuICAgICAgYXV0aFtrZXldID0gdmFsdWUgYXMgT3BlbkNvZGVBdXRoRW50cnk7XG4gICAgfVxuICB9XG5cbiAgLy8gQWRkL3VwZGF0ZSBhdGxhc2Nsb3VkIGVudHJ5XG4gIGF1dGguYXRsYXNjbG91ZCA9IHtcbiAgICB0eXBlOiBcImFwaVwiLFxuICAgIGtleTogYXBpS2V5LFxuICB9O1xuXG4gIHNhdmVPcGVuQ29kZUF1dGgoYXV0aCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRBcGlLZXkoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIGxvYWRDb25maWcoKS5hcGlLZXk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjbGVhckFwaUtleSgpOiB2b2lkIHtcbiAgLy8gQ2xlYXIgZnJvbSBvdXIgY29uZmlnXG4gIGNvbnN0IGNvbmZpZyA9IGxvYWRDb25maWcoKTtcbiAgZGVsZXRlIGNvbmZpZy5hcGlLZXk7XG4gIHNhdmVDb25maWcoY29uZmlnKTtcblxuICAvLyBBbHNvIGNsZWFyIGZyb20gT3BlbkNvZGUncyBhdXRoLmpzb25cbiAgaWYgKGZzLmV4aXN0c1N5bmMoT1BFTkNPREVfQVVUSF9GSUxFKSkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBjb250ZW50ID0gZnMucmVhZEZpbGVTeW5jKE9QRU5DT0RFX0FVVEhfRklMRSwgXCJ1dGYtOFwiKTtcbiAgICAgIGNvbnN0IGF1dGhEYXRhID0gSlNPTi5wYXJzZShjb250ZW50KTtcbiAgICAgIGRlbGV0ZSBhdXRoRGF0YS5hdGxhc2Nsb3VkO1xuICAgICAgZW5zdXJlT3BlbkNvZGVBdXRoRGlyKCk7XG4gICAgICBmcy53cml0ZUZpbGVTeW5jKE9QRU5DT0RFX0FVVEhfRklMRSwgSlNPTi5zdHJpbmdpZnkoYXV0aERhdGEsIG51bGwsIDIpKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIElnbm9yZSBlcnJvcnNcbiAgICB9XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,18 @@
1
+ export interface AtlasCloudModel {
2
+ id: string;
3
+ name: string;
4
+ context: number;
5
+ output: number;
6
+ }
7
+ export interface OpenCodeModel {
8
+ name: string;
9
+ limit: {
10
+ context: number;
11
+ output: number;
12
+ };
13
+ }
14
+ declare const ATLAS_CLOUD_API_BASE = "https://api.atlascloud.ai/v1";
15
+ export declare function fetchModels(apiKey?: string): Promise<AtlasCloudModel[]>;
16
+ export declare function modelsToOpenCodeFormat(models: AtlasCloudModel[]): Record<string, OpenCodeModel>;
17
+ export declare function validateApiKey(apiKey: string): Promise<boolean>;
18
+ export { ATLAS_CLOUD_API_BASE };
@@ -0,0 +1,185 @@
1
+ import { getApiKey } from "./config.js";
2
+ const ATLAS_CLOUD_API_BASE = "https://api.atlascloud.ai/v1";
3
+ // Fallback models - use actual Atlas Cloud model IDs (verified from API)
4
+ const FALLBACK_MODELS = [
5
+ // OpenAI models
6
+ { id: "openai/gpt-4o", name: "GPT-4o", context: 128000, output: 16384 },
7
+ { id: "openai/gpt-4o-mini", name: "GPT-4o Mini", context: 128000, output: 16384 },
8
+ { id: "openai/gpt-4.1", name: "GPT-4.1", context: 128000, output: 16384 },
9
+ { id: "openai/gpt-4.1-mini", name: "GPT-4.1 Mini", context: 128000, output: 16384 },
10
+ { id: "openai/gpt-5", name: "GPT-5", context: 200000, output: 32768 },
11
+ { id: "openai/gpt-5-mini", name: "GPT-5 Mini", context: 128000, output: 16384 },
12
+ { id: "openai/o1", name: "O1", context: 200000, output: 100000 },
13
+ { id: "openai/o3", name: "O3", context: 200000, output: 100000 },
14
+ { id: "openai/o3-mini", name: "O3 Mini", context: 200000, output: 65536 },
15
+ // Anthropic models
16
+ { id: "anthropic/claude-sonnet-4.5-20250929", name: "Claude Sonnet 4.5", context: 200000, output: 16384 },
17
+ { id: "anthropic/claude-opus-4.5-20251101", name: "Claude Opus 4.5", context: 200000, output: 16384 },
18
+ { id: "anthropic/claude-haiku-4.5-20251001", name: "Claude Haiku 4.5", context: 200000, output: 8192 },
19
+ { id: "anthropic/claude-haiku-4.5-20251001-developer", name: "Claude Haiku 4.5 Developer", context: 200000, output: 8192 },
20
+ { id: "anthropic/claude-3.7-sonnet-20250219", name: "Claude 3.7 Sonnet", context: 200000, output: 8192 },
21
+ // Google models
22
+ { id: "google/gemini-2.5-flash", name: "Gemini 2.5 Flash", context: 1000000, output: 8192 },
23
+ { id: "google/gemini-2.5-flash-lite", name: "Gemini 2.5 Flash Lite", context: 1000000, output: 8192 },
24
+ { id: "google/gemini-2.5-pro", name: "Gemini 2.5 Pro", context: 2000000, output: 8192 },
25
+ { id: "google/gemini-3-flash-preview", name: "Gemini 3 Flash Preview", context: 2000000, output: 16384 },
26
+ { id: "google/gemini-3-pro-preview", name: "Gemini 3 Pro Preview", context: 2000000, output: 32768 },
27
+ // DeepSeek models
28
+ { id: "deepseek-ai/DeepSeek-V3.1", name: "DeepSeek V3.1", context: 128000, output: 8192 },
29
+ { id: "deepseek-ai/deepseek-v3.2-speciale", name: "DeepSeek V3.2 Speciale", context: 128000, output: 8192 },
30
+ { id: "deepseek-ai/deepseek-v3.2", name: "DeepSeek V3.2", context: 128000, output: 8192 },
31
+ { id: "deepseek-ai/deepseek-r1-0528", name: "DeepSeek R1", context: 128000, output: 8192 },
32
+ // xAI models
33
+ { id: "xai/grok-4-0709", name: "Grok 4", context: 128000, output: 16384 },
34
+ ];
35
+ function getModelContextLength(modelId) {
36
+ const id = modelId.toLowerCase();
37
+ // Anthropic models
38
+ if (id.includes("claude"))
39
+ return 200000;
40
+ // OpenAI models
41
+ if (id.includes("o1") || id.includes("o3") || id.includes("gpt-5"))
42
+ return 200000;
43
+ if (id.includes("gpt-4"))
44
+ return 128000;
45
+ if (id.includes("gpt-3.5"))
46
+ return 16385;
47
+ // Google models
48
+ if (id.includes("gemini-3"))
49
+ return 2000000;
50
+ if (id.includes("gemini-2.5"))
51
+ return 1000000;
52
+ if (id.includes("gemini"))
53
+ return 128000;
54
+ // DeepSeek models
55
+ if (id.includes("deepseek"))
56
+ return 128000;
57
+ // xAI models
58
+ if (id.includes("grok"))
59
+ return 128000;
60
+ // Llama models
61
+ if (id.includes("llama-3.1-405b") || id.includes("llama-3.1-70b"))
62
+ return 128000;
63
+ if (id.includes("llama"))
64
+ return 8192;
65
+ // Mistral models
66
+ if (id.includes("mistral-large") || id.includes("mixtral"))
67
+ return 32768;
68
+ if (id.includes("mistral"))
69
+ return 8192;
70
+ // Qwen models
71
+ if (id.includes("qwen3"))
72
+ return 128000;
73
+ if (id.includes("qwen"))
74
+ return 32768;
75
+ return 128000; // Default context length - more generous default
76
+ }
77
+ function getModelOutputTokens(modelId) {
78
+ const id = modelId.toLowerCase();
79
+ // Reasoning models with large output
80
+ if (id.includes("o1") || id.includes("o3"))
81
+ return 100000;
82
+ if (id.includes("deepseek-r1") || id.includes("thinking"))
83
+ return 65536;
84
+ // Large output models
85
+ if (id.includes("gpt-5") && !id.includes("mini") && !id.includes("nano"))
86
+ return 32768;
87
+ if (id.includes("gemini-3-pro"))
88
+ return 32768;
89
+ // Standard large output
90
+ if (id.includes("gpt-4o") || id.includes("gpt-4.1") || id.includes("gpt-5"))
91
+ return 16384;
92
+ if (id.includes("claude-sonnet-4") || id.includes("claude-opus-4"))
93
+ return 16384;
94
+ if (id.includes("gemini-3"))
95
+ return 16384;
96
+ if (id.includes("grok-4"))
97
+ return 16384;
98
+ // Standard output
99
+ if (id.includes("claude"))
100
+ return 8192;
101
+ if (id.includes("gemini"))
102
+ return 8192;
103
+ if (id.includes("deepseek"))
104
+ return 8192;
105
+ if (id.includes("gpt"))
106
+ return 8192;
107
+ if (id.includes("qwen"))
108
+ return 8192;
109
+ return 8192; // Default output tokens
110
+ }
111
+ function formatModelName(modelId) {
112
+ // Capitalize and format model names nicely
113
+ return modelId
114
+ .split("-")
115
+ .map((part) => {
116
+ if (part.match(/^\d/))
117
+ return part; // Keep version numbers as-is
118
+ return part.charAt(0).toUpperCase() + part.slice(1);
119
+ })
120
+ .join(" ")
121
+ .replace(/\s+(\d)/g, "-$1"); // Join version numbers with dash
122
+ }
123
+ export async function fetchModels(apiKey) {
124
+ const key = apiKey || getApiKey();
125
+ if (!key) {
126
+ return FALLBACK_MODELS;
127
+ }
128
+ try {
129
+ const response = await fetch(`${ATLAS_CLOUD_API_BASE}/models`, {
130
+ method: "GET",
131
+ headers: {
132
+ Authorization: `Bearer ${key}`,
133
+ "Content-Type": "application/json",
134
+ },
135
+ });
136
+ if (!response.ok) {
137
+ console.error(`Failed to fetch models: ${response.status} ${response.statusText}`);
138
+ return FALLBACK_MODELS;
139
+ }
140
+ const data = (await response.json());
141
+ if (!data.data || !Array.isArray(data.data)) {
142
+ return FALLBACK_MODELS;
143
+ }
144
+ return data.data.map((model) => ({
145
+ id: model.id,
146
+ name: formatModelName(model.id),
147
+ context: getModelContextLength(model.id),
148
+ output: getModelOutputTokens(model.id),
149
+ }));
150
+ }
151
+ catch (error) {
152
+ console.error("Error fetching models:", error);
153
+ return FALLBACK_MODELS;
154
+ }
155
+ }
156
+ export function modelsToOpenCodeFormat(models) {
157
+ const result = {};
158
+ for (const model of models) {
159
+ result[model.id] = {
160
+ name: model.name,
161
+ limit: {
162
+ context: model.context,
163
+ output: model.output,
164
+ },
165
+ };
166
+ }
167
+ return result;
168
+ }
169
+ export async function validateApiKey(apiKey) {
170
+ try {
171
+ const response = await fetch(`${ATLAS_CLOUD_API_BASE}/models`, {
172
+ method: "GET",
173
+ headers: {
174
+ Authorization: `Bearer ${apiKey}`,
175
+ "Content-Type": "application/json",
176
+ },
177
+ });
178
+ return response.ok;
179
+ }
180
+ catch (error) {
181
+ return false;
182
+ }
183
+ }
184
+ export { ATLAS_CLOUD_API_BASE };
185
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kZWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcnZlci9tb2RlbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQWlCeEMsTUFBTSxvQkFBb0IsR0FBRyw4QkFBOEIsQ0FBQztBQUU1RCx5RUFBeUU7QUFDekUsTUFBTSxlQUFlLEdBQXNCO0lBQ3pDLGdCQUFnQjtJQUNoQixFQUFFLEVBQUUsRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7SUFDdkUsRUFBRSxFQUFFLEVBQUUsb0JBQW9CLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7SUFDakYsRUFBRSxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7SUFDekUsRUFBRSxFQUFFLEVBQUUscUJBQXFCLEVBQUUsSUFBSSxFQUFFLGNBQWMsRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7SUFDbkYsRUFBRSxFQUFFLEVBQUUsY0FBYyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFO0lBQ3JFLEVBQUUsRUFBRSxFQUFFLG1CQUFtQixFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFO0lBQy9FLEVBQUUsRUFBRSxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRTtJQUNoRSxFQUFFLEVBQUUsRUFB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b20gXCIuL2NvbmZpZy5qc1wiO1xuXG5leHBvcnQgaW50ZXJmYWNlIEF0bGFzQ2xvdWRNb2RlbCB7XG4gIGlkOiBzdHJpbmc7XG4gIG5hbWU6IHN0cmluZztcbiAgY29udGV4dDogbnVtYmVyO1xuICBvdXRwdXQ6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPcGVuQ29kZU1vZGVsIHtcbiAgbmFtZTogc3RyaW5nO1xuICBsaW1pdDoge1xuICAgIGNvbnRleHQ6IG51bWJlcjtcbiAgICBvdXRwdXQ6IG51bWJlcjtcbiAgfTtcbn1cblxuY29uc3QgQVRMQVNfQ0xPVURfQVBJX0JBU0UgPSBcImh0dHBzOi8vYXBpLmF0bGFzY2xvdWQuYWkvdjFcIjtcblxuLy8gRmFsbGJhY2sgbW9kZWxzIC0gdXNlIGFjdHVhbCBBdGxhcyBDbG91ZCBtb2RlbCBJRHMgKHZlcmlmaWVkIGZyb20gQVBJKVxuY29uc3QgRkFMTEJBQ0tfTU9ERUxTOiBBdGxhc0Nsb3VkTW9kZWxbXSA9IFtcbiAgLy8gT3BlbkFJIG1vZGVsc1xuICB7IGlkOiBcIm9wZW5haS9ncHQtNG9cIiwgbmFtZTogXCJHUFQtNG9cIiwgY29udGV4dDogMTI4MDAwLCBvdXRwdXQ6IDE2Mzg0IH0sXG4gIHsgaWQ6IFwib3BlbmFpL2dwdC00by1taW5pXCIsIG5hbWU6IFwiR1BULTRvIE1pbmlcIiwgY29udGV4dDogMTI4MDAwLCBvdXRwdXQ6IDE2Mzg0IH0sXG4gIHsgaWQ6IFwib3BlbmFpL2dwdC00LjFcIiwgbmFtZTogXCJHUFQtNC4xXCIsIGNvbnRleHQ6IDEyODAwMCwgb3V0cHV0OiAxNjM4NCB9LFxuICB7IGlkOiBcIm9wZW5haS9ncHQtNC4xLW1pbmlcIiwgbmFtZTogXCJHUFQtNC4xIE1pbmlcIiwgY29udGV4dDogMTI4MDAwLCBvdXRwdXQ6IDE2Mzg0IH0sXG4gIHsgaWQ6IFwib3BlbmFpL2dwdC01XCIsIG5hbWU6IFwiR1BULTVcIiwgY29udGV4dDogMjAwMDAwLCBvdXRwdXQ6IDMyNzY4IH0sXG4gIHsgaWQ6IFwib3BlbmFpL2dwdC01LW1pbmlcIiwgbmFtZTogXCJHUFQtNSBNaW5pXCIsIGNvbnRleHQ6IDEyODAwMCwgb3V0cHV0OiAxNjM4NCB9LFxuICB7IGlkOiBcIm9wZW5haS9vMVwiLCBuYW1lOiBcIk8xXCIsIGNvbnRleHQ6IDIwMDAwMCwgb3V0cHV0OiAxMDAwMDAgfSxcbiAgeyBpZDogXCJvcGVuYWkvbzNcIiwgbmFtZTogXCJPM1wiLCBjb250ZXh0OiAyMDAwMDAsIG91dHB1dDogMTAwMDAwIH0sXG4gIHsgaWQ6IFwib3BlbmFpL28zLW1pbmlcIiwgbmFtZTogXCJPMyBNaW5pXCIsIGNvbnRleHQ6IDIwMDAwMCwgb3V0cHV0OiA2NTUzNiB9LFxuICAvLyBBbnRocm9waWMgbW9kZWxzXG4gIHsgaWQ6IFwiYW50aHJvcGljL2NsYXVkZS1zb25uZXQtNC41LTIwMjUwOTI5XCIsIG5hbWU6IFwiQ2xhdWRlIFNvbm5ldCA0LjVcIiwgY29udGV4dDogMjAwMDAwLCBvdXRwdXQ6IDE2Mzg0IH0sXG4gIHsgaWQ6IFwiYW50aHJvcGljL2NsYXVkZS1vcHVzLTQuNS0yMDI1MTEwMVwiLCBuYW1lOiBcIkNsYXVkZSBPcHVzIDQuNVwiLCBjb250ZXh0OiAyMDAwMDAsIG91dHB1dDogMTYzODQgfSxcbiAgeyBpZDogXCJhbnRocm9waWMvY2xhdWRlLWhhaWt1LTQuNS0yMDI1MTAwMVwiLCBuYW1lOiBcIkNsYXVkZSBIYWlrdSA0LjVcIiwgY29udGV4dDogMjAwMDAwLCBvdXRwdXQ6IDgxOTIgfSxcbiAgeyBpZDogXCJhbnRocm9waWMvY2xhdWRlLWhhaWt1LTQuNS0yMDI1MTAwMS1kZXZlbG9wZXJcIiwgbmFtZTogXCJDbGF1ZGUgSGFpa3UgNC41IERldmVsb3BlclwiLCBjb250ZXh0OiAyMDAwMDAsIG91dHB1dDogODE5MiB9LFxuICB7IGlkOiBcImFudGhyb3BpYy9jbGF1ZGUtMy43LXNvbm5ldC0yMDI1MDIxOVwiLCBuYW1lOiBcIkNsYXVkZSAzLjcgU29ubmV0XCIsIGNvbnRleHQ6IDIwMDAwMCwgb3V0cHV0OiA4MTkyIH0sXG4gIC8vIEdvb2dsZSBtb2RlbHNcbiAgeyBpZDogXCJnb29nbGUvZ2VtaW5pLTIuNS1mbGFzaFwiLCBuYW1lOiBcIkdlbWluaSAyLjUgRmxhc2hcIiwgY29udGV4dDogMTAwMDAwMCwgb3V0cHV0OiA4MTkyIH0sXG4gIHsgaWQ6IFwiZ29vZ2xlL2dlbWluaS0yLjUtZmxhc2gtbGl0ZVwiLCBuYW1lOiBcIkdlbWluaSAyLjUgRmxhc2ggTGl0ZVwiLCBjb250ZXh0OiAxMDAwMDAwLCBvdXRwdXQ6IDgxOTIgfSxcbiAgeyBpZDogXCJnb29nbGUvZ2VtaW5pLTIuNS1wcm9cIiwgbmFtZTogXCJHZW1pbmkgMi41IFByb1wiLCBjb250ZXh0OiAyMDAwMDAwLCBvdXRwdXQ6IDgxOTIgfSxcbiAgeyBpZDogXCJnb29nbGUvZ2VtaW5pLTMtZmxhc2gtcHJldmlld1wiLCBuYW1lOiBcIkdlbWluaSAzIEZsYXNoIFByZXZpZXdcIiwgY29udGV4dDogMjAwMDAwMCwgb3V0cHV0OiAxNjM4NCB9LFxuICB7IGlkOiBcImdvb2dsZS9nZW1pbmktMy1wcm8tcHJldmlld1wiLCBuYW1lOiBcIkdlbWluaSAzIFBybyBQcmV2aWV3XCIsIGNvbnRleHQ6IDIwMDAwMDAsIG91dHB1dDogMzI3NjggfSxcbiAgLy8gRGVlcFNlZWsgbW9kZWxzXG4gIHsgaWQ6IFwiZGVlcHNlZWstYWkvRGVlcFNlZWstVjMuMVwiLCBuYW1lOiBcIkRlZXBTZWVrIFYzLjFcIiwgY29udGV4dDogMTI4MDAwLCBvdXRwdXQ6IDgxOTIgfSxcbiAgeyBpZDogXCJkZWVwc2Vlay1haS9kZWVwc2Vlay12My4yLXNwZWNpYWxlXCIsIG5hbWU6IFwiRGVlcFNlZWsgVjMuMiBTcGVjaWFsZVwiLCBjb250ZXh0OiAxMjgwMDAsIG91dHB1dDogODE5MiB9LFxuICB7IGlkOiBcImRlZXBzZWVrLWFpL2RlZXBzZWVrLXYzLjJcIiwgbmFtZTogXCJEZWVwU2VlayBWMy4yXCIsIGNvbnRleHQ6IDEyODAwMCwgb3V0cHV0OiA4MTkyIH0sXG4gIHsgaWQ6IFwiZGVlcHNlZWstYWkvZGVlcHNlZWstcjEtMDUyOFwiLCBuYW1lOiBcIkRlZXBTZWVrIFIxXCIsIGNvbnRleHQ6IDEyODAwMCwgb3V0cHV0OiA4MTkyIH0sXG4gIC8vIHhBSSBtb2RlbHNcbiAgeyBpZDogXCJ4YWkvZ3Jvay00LTA3MDlcIiwgbmFtZTogXCJHcm9rIDRcIiwgY29udGV4dDogMTI4MDAwLCBvdXRwdXQ6IDE2Mzg0IH0sXG5dO1xuXG5pbnRlcmZhY2UgQXBpTW9kZWwge1xuICBpZDogc3RyaW5nO1xuICBvYmplY3Q/OiBzdHJpbmc7XG4gIGNyZWF0ZWQ/OiBudW1iZXI7XG4gIG93bmVkX2J5Pzogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgTW9kZWxzUmVzcG9uc2Uge1xuICBvYmplY3Q/OiBzdHJpbmc7XG4gIGRhdGE6IEFwaU1vZGVsW107XG59XG5cbmZ1bmN0aW9uIGdldE1vZGVsQ29udGV4dExlbmd0aChtb2RlbElkOiBzdHJpbmcpOiBudW1iZXIge1xuICBjb25zdCBpZCA9IG1vZGVsSWQudG9Mb3dlckNhc2UoKTtcblxuICAvLyBBbnRocm9waWMgbW9kZWxzXG4gIGlmIChpZC5pbmNsdWRlcyhcImNsYXVkZVwiKSkgcmV0dXJuIDIwMDAwMDtcblxuICAvLyBPcGVuQUkgbW9kZWxzXG4gIGlmIChpZC5pbmNsdWRlcyhcIm8xXCIpIHx8IGlkLmluY2x1ZGVzKFwibzNcIikgfHwgaWQuaW5jbHVkZXMoXCJncHQtNVwiKSkgcmV0dXJuIDIwMDAwMDtcbiAgaWYgKGlkLmluY2x1ZGVzKFwiZ3B0LTRcIikpIHJldHVybiAxMjgwMDA7XG4gIGlmIChpZC5pbmNsdWRlcyhcImdwdC0zLjVcIikpIHJldHVybiAxNjM4NTtcblxuICAvLyBHb29nbGUgbW9kZWxzXG4gIGlmIChpZC5pbmNsdWRlcyhcImdlbWluaS0zXCIpKSByZXR1cm4gMjAwMDAwMDtcbiAgaWYgKGlkLmluY2x1ZGVzKFwiZ2VtaW5pLTIuNVwiKSkgcmV0dXJuIDEwMDAwMDA7XG4gIGlmIChpZC5pbmNsdWRlcyhcImdlbWluaVwiKSkgcmV0dXJuIDEyODAwMDtcblxuICAvLyBEZWVwU2VlayBtb2RlbHNcbiAgaWYgKGlkLmluY2x1ZGVzKFwiZGVlcHNlZWtcIikpIHJldHVybiAxMjgwMDA7XG5cbiAgLy8geEFJIG1vZGVsc1xuICBpZiAoaWQuaW5jbHVkZXMoXCJncm9rXCIpKSByZXR1cm4gMTI4MDAwO1xuXG4gIC8vIExsYW1hIG1vZGVsc1xuICBpZiAoaWQuaW5jbHVkZXMoXCJsbGFtYS0zLjEtNDA1YlwiKSB8fCBpZC5pbmNsdWRlcyhcImxsYW1hLTMuMS03MGJcIikpIHJldHVybiAxMjgwMDA7XG4gIGlmIChpZC5pbmNsdWRlcyhcImxsYW1hXCIpKSByZXR1cm4gODE5MjtcblxuICAvLyBNaXN0cmFsIG1vZGVsc1xuICBpZiAoaWQuaW5jbHVkZXMoXCJtaXN0cmFsLWxhcmdlXCIpIHx8IGlkLmluY2x1ZGVzKFwibWl4dHJhbFwiKSkgcmV0dXJuIDMyNzY4O1xuICBpZiAoaWQuaW5jbHVkZXMoXCJtaXN0cmFsXCIpKSByZXR1cm4gODE5MjtcblxuICAvLyBRd2VuIG1vZGVsc1xuICBpZiAoaWQuaW5jbHVkZXMoXCJxd2VuM1wiKSkgcmV0dXJuIDEyODAwMDtcbiAgaWYgKGlkLmluY2x1ZGVzKFwicXdlblwiKSkgcmV0dXJuIDMyNzY4O1xuXG4gIHJldHVybiAxMjgwMDA7IC8vIERlZmF1bHQgY29udGV4dCBsZW5ndGggLSBtb3JlIGdlbmVyb3VzIGRlZmF1bHRcbn1cblxuZnVuY3Rpb24gZ2V0TW9kZWxPdXRwdXRUb2tlbnMobW9kZWxJZDogc3RyaW5nKTogbnVtYmVyIHtcbiAgY29uc3QgaWQgPSBtb2RlbElkLnRvTG93ZXJDYXNlKCk7XG5cbiAgLy8gUmVhc29uaW5nIG1vZGVscyB3aXRoIGxhcmdlIG91dHB1dFxuICBpZiAoaWQuaW5jbHVkZXMoXCJvMVwiKSB8fCBpZC5pbmNsdWRlcyhcIm8zXCIpKSByZXR1cm4gMTAwMDAwO1xuICBpZiAoaWQuaW5jbHVkZXMoXCJkZWVwc2Vlay1yMVwiKSB8fCBpZC5pbmNsdWRlcyhcInRoaW5raW5nXCIpKSByZXR1cm4gNjU1MzY7XG5cbiAgLy8gTGFyZ2Ugb3V0cHV0IG1vZGVsc1xuICBpZiAoaWQuaW5jbHVkZXMoXCJncHQtNVwiKSAmJiAhaWQuaW5jbHVkZXMoXCJtaW5pXCIpICYmICFpZC5pbmNsdWRlcyhcIm5hbm9cIikpIHJldHVybiAzMjc2ODtcbiAgaWYgKGlkLmluY2x1ZGVzKFwiZ2VtaW5pLTMtcHJvXCIpKSByZXR1cm4gMzI3Njg7XG5cbiAgLy8gU3RhbmRhcmQgbGFyZ2Ugb3V0cHV0XG4gIGlmIChpZC5pbmNsdWRlcyhcImdwdC00b1wiKSB8fCBpZC5pbmNsdWRlcyhcImdwdC00LjFcIikgfHwgaWQuaW5jbHVkZXMoXCJncHQtNVwiKSkgcmV0dXJuIDE2Mzg0O1xuICBpZiAoaWQuaW5jbHVkZXMoXCJjbGF1ZGUtc29ubmV0LTRcIikgfHwgaWQuaW5jbHVkZXMoXCJjbGF1ZGUtb3B1cy00XCIpKSByZXR1cm4gMTYzODQ7XG4gIGlmIChpZC5pbmNsdWRlcyhcImdlbWluaS0zXCIpKSByZXR1cm4gMTYzODQ7XG4gIGlmIChpZC5pbmNsdWRlcyhcImdyb2stNFwiKSkgcmV0dXJuIDE2Mzg0O1xuXG4gIC8vIFN0YW5kYXJkIG91dHB1dFxuICBpZiAoaWQuaW5jbHVkZXMoXCJjbGF1ZGVcIikpIHJldHVybiA4MTkyO1xuICBpZiAoaWQuaW5jbHVkZXMoXCJnZW1pbmlcIikpIHJldHVybiA4MTkyO1xuICBpZiAoaWQuaW5jbHVkZXMoXCJkZWVwc2Vla1wiKSkgcmV0dXJuIDgxOTI7XG4gIGlmIChpZC5pbmNsdWRlcyhcImdwdFwiKSkgcmV0dXJuIDgxOTI7XG4gIGlmIChpZC5pbmNsdWRlcyhcInF3ZW5cIikpIHJldHVybiA4MTkyO1xuXG4gIHJldHVybiA4MTkyOyAvLyBEZWZhdWx0IG91dHB1dCB0b2tlbnNcbn1cblxuZnVuY3Rpb24gZm9ybWF0TW9kZWxOYW1lKG1vZGVsSWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIC8vIENhcGl0YWxpemUgYW5kIGZvcm1hdCBtb2RlbCBuYW1lcyBuaWNlbHlcbiAgcmV0dXJuIG1vZGVsSWRcbiAgICAuc3BsaXQoXCItXCIpXG4gICAgLm1hcCgocGFydCkgPT4ge1xuICAgICAgaWYgKHBhcnQubWF0Y2goL15cXGQvKSkgcmV0dXJuIHBhcnQ7IC8vIEtlZXAgdmVyc2lvbiBudW1iZXJzIGFzLWlzXG4gICAgICByZXR1cm4gcGFydC5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHBhcnQuc2xpY2UoMSk7XG4gICAgfSlcbiAgICAuam9pbihcIiBcIilcbiAgICAucmVwbGFjZSgvXFxzKyhcXGQpL2csIFwiLSQxXCIpOyAvLyBKb2luIHZlcnNpb24gbnVtYmVycyB3aXRoIGRhc2hcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGZldGNoTW9kZWxzKFxuICBhcGlLZXk/OiBzdHJpbmdcbik6IFByb21pc2U8QXRsYXNDbG91ZE1vZGVsW10+IHtcbiAgY29uc3Qga2V5ID0gYXBpS2V5IHx8IGdldEFwaUtleSgpO1xuXG4gIGlmICgha2V5KSB7XG4gICAgcmV0dXJuIEZBTExCQUNLX01PREVMUztcbiAgfVxuXG4gIHRyeSB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChgJHtBVExBU19DTE9VRF9BUElfQkFTRX0vbW9kZWxzYCwge1xuICAgICAgbWV0aG9kOiBcIkdFVFwiLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICBBdXRob3JpemF0aW9uOiBgQmVhcmVyICR7a2V5fWAsXG4gICAgICAgIFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgIGBGYWlsZWQgdG8gZmV0Y2ggbW9kZWxzOiAke3Jlc3BvbnNlLnN0YXR1c30gJHtyZXNwb25zZS5zdGF0dXNUZXh0fWBcbiAgICAgICk7XG4gICAgICByZXR1cm4gRkFMTEJBQ0tfTU9ERUxTO1xuICAgIH1cblxuICAgIGNvbnN0IGRhdGEgPSAoYXdhaXQgcmVzcG9uc2UuanNvbigpKSBhcyBNb2RlbHNSZXNwb25zZTtcblxuICAgIGlmICghZGF0YS5kYXRhIHx8ICFBcnJheS5pc0FycmF5KGRhdGEuZGF0YSkpIHtcbiAgICAgIHJldHVybiBGQUxMQkFDS19NT0RFTFM7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRhdGEuZGF0YS5tYXAoKG1vZGVsOiBBcGlNb2RlbCkgPT4gKHtcbiAgICAgIGlkOiBtb2RlbC5pZCxcbiAgICAgIG5hbWU6IGZvcm1hdE1vZGVsTmFtZShtb2RlbC5pZCksXG4gICAgICBjb250ZXh0OiBnZXRNb2RlbENvbnRleHRMZW5ndGgobW9kZWwuaWQpLFxuICAgICAgb3V0cHV0OiBnZXRNb2RlbE91dHB1dFRva2Vucyhtb2RlbC5pZCksXG4gICAgfSkpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBmZXRjaGluZyBtb2RlbHM6XCIsIGVycm9yKTtcbiAgICByZXR1cm4gRkFMTEJBQ0tfTU9ERUxTO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtb2RlbHNUb09wZW5Db2RlRm9ybWF0KFxuICBtb2RlbHM6IEF0bGFzQ2xvdWRNb2RlbFtdXG4pOiBSZWNvcmQ8c3RyaW5nLCBPcGVuQ29kZU1vZGVsPiB7XG4gIGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgT3BlbkNvZGVNb2RlbD4gPSB7fTtcblxuICBmb3IgKGNvbnN0IG1vZGVsIG9mIG1vZGVscykge1xuICAgIHJlc3VsdFttb2RlbC5pZF0gPSB7XG4gICAgICBuYW1lOiBtb2RlbC5uYW1lLFxuICAgICAgbGltaXQ6IHtcbiAgICAgICAgY29udGV4dDogbW9kZWwuY29udGV4dCxcbiAgICAgICAgb3V0cHV0OiBtb2RlbC5vdXRwdXQsXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdmFsaWRhdGVBcGlLZXkoYXBpS2V5OiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKGAke0FUTEFTX0NMT1VEX0FQSV9CQVNFfS9tb2RlbHNgLCB7XG4gICAgICBtZXRob2Q6IFwiR0VUXCIsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgIEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHthcGlLZXl9YCxcbiAgICAgICAgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHJlc3BvbnNlLm9rO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG5leHBvcnQgeyBBVExBU19DTE9VRF9BUElfQkFTRSB9O1xuIl19
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@atlascloudai/opencode",
3
+ "version": "0.0.1",
4
+ "description": "OpenCode plugin for Atlas Cloud - Access 100+ AI models including GPT-4o, Claude, Gemini, DeepSeek via OpenAI-compatible API",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "type": "module",
8
+ "bin": {
9
+ "atlascloudai-opencode": "./bin/setup.cjs"
10
+ },
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "dev": "tsc --watch",
14
+ "prepublishOnly": "npm run build",
15
+ "test": "echo \"No tests yet\" && exit 0"
16
+ },
17
+ "keywords": [
18
+ "opencode",
19
+ "plugin",
20
+ "atlascloud",
21
+ "atlas-cloud",
22
+ "ai",
23
+ "llm",
24
+ "gpt-4",
25
+ "claude",
26
+ "gemini",
27
+ "deepseek",
28
+ "openai-compatible"
29
+ ],
30
+ "author": "Atlas Cloud",
31
+ "license": "MIT",
32
+ "homepage": "https://github.com/atlascloud/opencode-plugin#readme",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/atlascloud/opencode-plugin.git"
36
+ },
37
+ "bugs": {
38
+ "url": "https://github.com/atlascloud/opencode-plugin/issues"
39
+ },
40
+ "dependencies": {
41
+ "@opencode-ai/plugin": "^1.0.85",
42
+ "zod": "^3.22.4"
43
+ },
44
+ "devDependencies": {
45
+ "@types/node": "^20.0.0",
46
+ "typescript": "^5.0.0"
47
+ },
48
+ "files": [
49
+ "dist",
50
+ "bin",
51
+ "README.md"
52
+ ],
53
+ "engines": {
54
+ "node": ">=18.0.0"
55
+ }
56
+ }