@idcloudhost/ai-connect 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +287 -0
  3. package/dist/adapters/aider.d.ts +11 -0
  4. package/dist/adapters/aider.d.ts.map +1 -0
  5. package/dist/adapters/aider.js +69 -0
  6. package/dist/adapters/aider.js.map +1 -0
  7. package/dist/adapters/claude-code.d.ts +17 -0
  8. package/dist/adapters/claude-code.d.ts.map +1 -0
  9. package/dist/adapters/claude-code.js +73 -0
  10. package/dist/adapters/claude-code.js.map +1 -0
  11. package/dist/adapters/codex.d.ts +11 -0
  12. package/dist/adapters/codex.d.ts.map +1 -0
  13. package/dist/adapters/codex.js +71 -0
  14. package/dist/adapters/codex.js.map +1 -0
  15. package/dist/adapters/continue.d.ts +7 -0
  16. package/dist/adapters/continue.d.ts.map +1 -0
  17. package/dist/adapters/continue.js +79 -0
  18. package/dist/adapters/continue.js.map +1 -0
  19. package/dist/adapters/crush.d.ts +4 -0
  20. package/dist/adapters/crush.d.ts.map +1 -0
  21. package/dist/adapters/crush.js +72 -0
  22. package/dist/adapters/crush.js.map +1 -0
  23. package/dist/adapters/goose.d.ts +11 -0
  24. package/dist/adapters/goose.d.ts.map +1 -0
  25. package/dist/adapters/goose.js +68 -0
  26. package/dist/adapters/goose.js.map +1 -0
  27. package/dist/adapters/helpers.d.ts +33 -0
  28. package/dist/adapters/helpers.d.ts.map +1 -0
  29. package/dist/adapters/helpers.js +117 -0
  30. package/dist/adapters/helpers.js.map +1 -0
  31. package/dist/adapters/hermes.d.ts +11 -0
  32. package/dist/adapters/hermes.d.ts.map +1 -0
  33. package/dist/adapters/hermes.js +100 -0
  34. package/dist/adapters/hermes.js.map +1 -0
  35. package/dist/adapters/index.d.ts +20 -0
  36. package/dist/adapters/index.d.ts.map +1 -0
  37. package/dist/adapters/index.js +60 -0
  38. package/dist/adapters/index.js.map +1 -0
  39. package/dist/adapters/manual.d.ts +6 -0
  40. package/dist/adapters/manual.d.ts.map +1 -0
  41. package/dist/adapters/manual.js +87 -0
  42. package/dist/adapters/manual.js.map +1 -0
  43. package/dist/adapters/omp.d.ts +8 -0
  44. package/dist/adapters/omp.d.ts.map +1 -0
  45. package/dist/adapters/omp.js +64 -0
  46. package/dist/adapters/omp.js.map +1 -0
  47. package/dist/adapters/openclaw.d.ts +10 -0
  48. package/dist/adapters/openclaw.d.ts.map +1 -0
  49. package/dist/adapters/openclaw.js +107 -0
  50. package/dist/adapters/openclaw.js.map +1 -0
  51. package/dist/adapters/opencode.d.ts +11 -0
  52. package/dist/adapters/opencode.d.ts.map +1 -0
  53. package/dist/adapters/opencode.js +86 -0
  54. package/dist/adapters/opencode.js.map +1 -0
  55. package/dist/adapters/pi-family.d.ts +14 -0
  56. package/dist/adapters/pi-family.d.ts.map +1 -0
  57. package/dist/adapters/pi-family.js +27 -0
  58. package/dist/adapters/pi-family.js.map +1 -0
  59. package/dist/adapters/pi.d.ts +8 -0
  60. package/dist/adapters/pi.d.ts.map +1 -0
  61. package/dist/adapters/pi.js +56 -0
  62. package/dist/adapters/pi.js.map +1 -0
  63. package/dist/adapters/shell-env.d.ts +12 -0
  64. package/dist/adapters/shell-env.d.ts.map +1 -0
  65. package/dist/adapters/shell-env.js +81 -0
  66. package/dist/adapters/shell-env.js.map +1 -0
  67. package/dist/adapters/zed.d.ts +10 -0
  68. package/dist/adapters/zed.d.ts.map +1 -0
  69. package/dist/adapters/zed.js +91 -0
  70. package/dist/adapters/zed.js.map +1 -0
  71. package/dist/cli.d.ts +3 -0
  72. package/dist/cli.d.ts.map +1 -0
  73. package/dist/cli.js +207 -0
  74. package/dist/cli.js.map +1 -0
  75. package/dist/commands/connect.d.ts +3 -0
  76. package/dist/commands/connect.d.ts.map +1 -0
  77. package/dist/commands/connect.js +179 -0
  78. package/dist/commands/connect.js.map +1 -0
  79. package/dist/commands/context.d.ts +21 -0
  80. package/dist/commands/context.d.ts.map +1 -0
  81. package/dist/commands/context.js +4 -0
  82. package/dist/commands/context.js.map +1 -0
  83. package/dist/commands/doctor.d.ts +11 -0
  84. package/dist/commands/doctor.d.ts.map +1 -0
  85. package/dist/commands/doctor.js +85 -0
  86. package/dist/commands/doctor.js.map +1 -0
  87. package/dist/commands/env.d.ts +7 -0
  88. package/dist/commands/env.d.ts.map +1 -0
  89. package/dist/commands/env.js +37 -0
  90. package/dist/commands/env.js.map +1 -0
  91. package/dist/commands/list.d.ts +3 -0
  92. package/dist/commands/list.d.ts.map +1 -0
  93. package/dist/commands/list.js +39 -0
  94. package/dist/commands/list.js.map +1 -0
  95. package/dist/commands/login.d.ts +7 -0
  96. package/dist/commands/login.d.ts.map +1 -0
  97. package/dist/commands/login.js +130 -0
  98. package/dist/commands/login.js.map +1 -0
  99. package/dist/commands/models.d.ts +9 -0
  100. package/dist/commands/models.d.ts.map +1 -0
  101. package/dist/commands/models.js +51 -0
  102. package/dist/commands/models.js.map +1 -0
  103. package/dist/commands/remove.d.ts +3 -0
  104. package/dist/commands/remove.d.ts.map +1 -0
  105. package/dist/commands/remove.js +43 -0
  106. package/dist/commands/remove.js.map +1 -0
  107. package/dist/commands/snippet.d.ts +7 -0
  108. package/dist/commands/snippet.d.ts.map +1 -0
  109. package/dist/commands/snippet.js +91 -0
  110. package/dist/commands/snippet.js.map +1 -0
  111. package/dist/core/detect.d.ts +12 -0
  112. package/dist/core/detect.d.ts.map +1 -0
  113. package/dist/core/detect.js +59 -0
  114. package/dist/core/detect.js.map +1 -0
  115. package/dist/core/discovery.d.ts +46 -0
  116. package/dist/core/discovery.d.ts.map +1 -0
  117. package/dist/core/discovery.js +124 -0
  118. package/dist/core/discovery.js.map +1 -0
  119. package/dist/core/gateway.d.ts +59 -0
  120. package/dist/core/gateway.d.ts.map +1 -0
  121. package/dist/core/gateway.js +385 -0
  122. package/dist/core/gateway.js.map +1 -0
  123. package/dist/core/http.d.ts +18 -0
  124. package/dist/core/http.d.ts.map +1 -0
  125. package/dist/core/http.js +73 -0
  126. package/dist/core/http.js.map +1 -0
  127. package/dist/core/management.d.ts +47 -0
  128. package/dist/core/management.d.ts.map +1 -0
  129. package/dist/core/management.js +88 -0
  130. package/dist/core/management.js.map +1 -0
  131. package/dist/core/store.d.ts +25 -0
  132. package/dist/core/store.d.ts.map +1 -0
  133. package/dist/core/store.js +48 -0
  134. package/dist/core/store.js.map +1 -0
  135. package/dist/fsutil/edit.d.ts +18 -0
  136. package/dist/fsutil/edit.d.ts.map +1 -0
  137. package/dist/fsutil/edit.js +102 -0
  138. package/dist/fsutil/edit.js.map +1 -0
  139. package/dist/fsutil/formats.d.ts +32 -0
  140. package/dist/fsutil/formats.d.ts.map +1 -0
  141. package/dist/fsutil/formats.js +154 -0
  142. package/dist/fsutil/formats.js.map +1 -0
  143. package/dist/index.d.ts +23 -0
  144. package/dist/index.d.ts.map +1 -0
  145. package/dist/index.js +8 -0
  146. package/dist/index.js.map +1 -0
  147. package/dist/types.d.ts +134 -0
  148. package/dist/types.d.ts.map +1 -0
  149. package/dist/types.js +3 -0
  150. package/dist/types.js.map +1 -0
  151. package/dist/ui.d.ts +20 -0
  152. package/dist/ui.d.ts.map +1 -0
  153. package/dist/ui.js +69 -0
  154. package/dist/ui.js.map +1 -0
  155. package/package.json +75 -0
@@ -0,0 +1,12 @@
1
+ import type { Adapter } from '../types.js';
2
+ /**
3
+ * The catch-all: a sourceable script exporting the standard OpenAI env vars.
4
+ *
5
+ * Anything that reads OPENAI_API_KEY / OPENAI_BASE_URL works after sourcing it —
6
+ * the OpenAI SDKs, LangChain, LlamaIndex, the Vercel AI SDK, Qwen Code, Cline in
7
+ * a terminal, one-off curl. We write a dedicated file rather than editing the
8
+ * user's ~/.zshrc, because appending exports to someone's shell rc is not ours
9
+ * to do and is painful to undo cleanly.
10
+ */
11
+ export declare const shellEnvAdapter: Adapter;
12
+ //# sourceMappingURL=shell-env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-env.d.ts","sourceRoot":"","sources":["../../src/adapters/shell-env.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAA6B,MAAM,aAAa,CAAC;AAStE;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,EAAE,OAoE7B,CAAC"}
@@ -0,0 +1,81 @@
1
+ import path from 'node:path';
2
+ import { readIfExists, shortenHome, writeFileSafely } from '../fsutil/edit.js';
3
+ import { configDir } from '../core/store.js';
4
+ import { result } from './helpers.js';
5
+ function envScript() {
6
+ return path.join(configDir(), 'env.sh');
7
+ }
8
+ /**
9
+ * The catch-all: a sourceable script exporting the standard OpenAI env vars.
10
+ *
11
+ * Anything that reads OPENAI_API_KEY / OPENAI_BASE_URL works after sourcing it —
12
+ * the OpenAI SDKs, LangChain, LlamaIndex, the Vercel AI SDK, Qwen Code, Cline in
13
+ * a terminal, one-off curl. We write a dedicated file rather than editing the
14
+ * user's ~/.zshrc, because appending exports to someone's shell rc is not ours
15
+ * to do and is painful to undo cleanly.
16
+ */
17
+ export const shellEnvAdapter = {
18
+ id: 'env',
19
+ name: 'Shell environment',
20
+ summary: 'A sourceable env.sh with the standard OpenAI variables. Works with any OpenAI-compatible client.',
21
+ docsUrl: 'https://platform.openai.com/docs/api-reference',
22
+ bins: [],
23
+ mode: 'auto',
24
+ supportsProjectScope: true,
25
+ secretModes: ['inline'],
26
+ async detect() {
27
+ return { installed: true, evidence: 'always available' };
28
+ },
29
+ configPath({ scope, cwd, configPathOverride }) {
30
+ if (configPathOverride)
31
+ return configPathOverride;
32
+ return scope === 'project' ? path.join(cwd, '.env') : envScript();
33
+ },
34
+ async apply(opts) {
35
+ const file = this.configPath(opts);
36
+ const { target } = opts;
37
+ const isProject = opts.scope === 'project';
38
+ const vars = [
39
+ ['OPENAI_API_KEY', target.apiKey],
40
+ ['OPENAI_BASE_URL', target.apiBase],
41
+ // The older SDKs and aider read this name instead.
42
+ ['OPENAI_API_BASE', target.apiBase],
43
+ ['IDCH_AI_API_KEY', target.apiKey],
44
+ ['IDCH_AI_BASE_URL', target.apiBase],
45
+ ];
46
+ if (target.defaultModel) {
47
+ vars.push(['OPENAI_MODEL', target.defaultModel], ['IDCH_AI_MODEL', target.defaultModel]);
48
+ }
49
+ const header = [
50
+ '# Written by @idcloudhost/ai-connect. Safe to regenerate.',
51
+ isProject ? '# Add this file to .gitignore — it contains a live API key.' : `# source ${shortenHome(file)}`,
52
+ '',
53
+ ];
54
+ const body = vars.map(([k, v]) => (isProject ? `${k}=${v}` : `export ${k}=${JSON.stringify(v)}`));
55
+ const after = [...header, ...body, ''].join('\n');
56
+ const change = await writeFileSafely(file, after, { dryRun: opts.dryRun });
57
+ return result(this.id, [change], {
58
+ notes: isProject
59
+ ? [`Wrote ${shortenHome(file)}. Add it to .gitignore — it holds a live key.`]
60
+ : [
61
+ `Load it with: source ${shortenHome(file)}`,
62
+ 'Add that line to your shell rc yourself if you want it permanent.',
63
+ ],
64
+ tryCommand: isProject ? undefined : `source ${shortenHome(file)} && idch-ai doctor`,
65
+ });
66
+ },
67
+ async remove(opts) {
68
+ const file = this.configPath(opts);
69
+ const before = await readIfExists(file);
70
+ if (before === null)
71
+ return result(this.id, []);
72
+ if (!before.includes('@idcloudhost/ai-connect')) {
73
+ return result(this.id, [], {
74
+ notes: [`Left ${shortenHome(file)} alone — it was not written by this tool.`],
75
+ });
76
+ }
77
+ const change = await writeFileSafely(file, '', { dryRun: opts.dryRun });
78
+ return result(this.id, [change], { notes: [`Emptied ${shortenHome(file)}.`] });
79
+ },
80
+ };
81
+ //# sourceMappingURL=shell-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-env.js","sourceRoot":"","sources":["../../src/adapters/shell-env.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { Adapter } from '../types.js';
2
+ /**
3
+ * Zed's settings.json is a hand-curated JSONC file full of comments, so this
4
+ * adapter edits it surgically instead of reserialising the document.
5
+ *
6
+ * Zed explicitly tells you not to put API keys in settings.json — the key is
7
+ * entered once in the Agent panel, so we only write the endpoint and models.
8
+ */
9
+ export declare const zedAdapter: Adapter;
10
+ //# sourceMappingURL=zed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zed.d.ts","sourceRoot":"","sources":["../../src/adapters/zed.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAA6B,MAAM,aAAa,CAAC;AAatE;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,EAAE,OAiFxB,CAAC"}
@@ -0,0 +1,91 @@
1
+ import path from 'node:path';
2
+ import os from 'node:os';
3
+ import { readIfExists, shortenHome, writeFileSafely } from '../fsutil/edit.js';
4
+ import { editJsonc, parseJson } from '../fsutil/formats.js';
5
+ import { detectByBinOrConfig } from '../core/detect.js';
6
+ import { ctx, maxOut, modelsToWrite, result, xdgConfigHome } from './helpers.js';
7
+ function userConfig() {
8
+ if (process.platform === 'win32') {
9
+ return path.join(process.env.APPDATA ?? path.join(os.homedir(), 'AppData', 'Roaming'), 'Zed', 'settings.json');
10
+ }
11
+ return path.join(xdgConfigHome(), 'zed', 'settings.json');
12
+ }
13
+ /**
14
+ * Zed's settings.json is a hand-curated JSONC file full of comments, so this
15
+ * adapter edits it surgically instead of reserialising the document.
16
+ *
17
+ * Zed explicitly tells you not to put API keys in settings.json — the key is
18
+ * entered once in the Agent panel, so we only write the endpoint and models.
19
+ */
20
+ export const zedAdapter = {
21
+ id: 'zed',
22
+ name: 'Zed',
23
+ summary: 'Zed editor agent panel. Endpoint goes in settings.json, key goes in the UI.',
24
+ docsUrl: 'https://zed.dev/docs/ai/use-api-access',
25
+ bins: ['zed'],
26
+ mode: 'auto',
27
+ secretModes: ['env'],
28
+ async detect() {
29
+ return detectByBinOrConfig(['zed'], [userConfig()]);
30
+ },
31
+ configPath({ configPathOverride }) {
32
+ return configPathOverride ?? userConfig();
33
+ },
34
+ async apply(opts) {
35
+ const file = this.configPath(opts);
36
+ const before = await readIfExists(file);
37
+ const { target } = opts;
38
+ const available = modelsToWrite(target).map((m) => ({
39
+ name: m.id,
40
+ display_name: m.label,
41
+ max_tokens: ctx(m),
42
+ max_output_tokens: maxOut(m),
43
+ capabilities: {
44
+ tools: m.supportsTools ?? true,
45
+ images: m.supportsVision ?? false,
46
+ parallel_tool_calls: false,
47
+ prompt_cache_key: false,
48
+ },
49
+ }));
50
+ const after = editJsonc(before, ['language_models', 'openai_compatible', target.providerLabel], {
51
+ api_url: target.apiBase,
52
+ available_models: available,
53
+ });
54
+ const change = await writeFileSafely(file, after, { dryRun: opts.dryRun });
55
+ return result(this.id, [change], {
56
+ notes: [
57
+ `Open the Agent panel → Settings → "${target.providerLabel}" and paste the API key there. Zed does not read keys from settings.json.`,
58
+ 'Comments and formatting elsewhere in settings.json are preserved.',
59
+ ],
60
+ });
61
+ },
62
+ async remove(opts) {
63
+ const file = this.configPath(opts);
64
+ const before = await readIfExists(file);
65
+ if (before === null)
66
+ return result(this.id, []);
67
+ // Find the entry by provider id or label, since the key is the display name.
68
+ const doc = parseJson(before);
69
+ const compat = (doc.language_models?.openai_compatible ?? {});
70
+ const keys = Object.keys(compat).filter((k) => k === opts.providerId || k.toLowerCase().includes('idcloudhost'));
71
+ if (!keys.length)
72
+ return result(this.id, []);
73
+ let text = before;
74
+ for (const key of keys)
75
+ text = editJsonc(text, ['language_models', 'openai_compatible', key], undefined);
76
+ // Prune the containers we would otherwise leave behind as empty husks, but
77
+ // only if nothing else lives in them.
78
+ const pruned = parseJson(text);
79
+ const compatAfter = pruned.language_models?.openai_compatible;
80
+ if (compatAfter && typeof compatAfter === 'object' && Object.keys(compatAfter).length === 0) {
81
+ text = editJsonc(text, ['language_models', 'openai_compatible'], undefined);
82
+ const lmAfter = parseJson(text).language_models;
83
+ if (lmAfter && typeof lmAfter === 'object' && Object.keys(lmAfter).length === 0) {
84
+ text = editJsonc(text, ['language_models'], undefined);
85
+ }
86
+ }
87
+ const change = await writeFileSafely(file, text, { dryRun: opts.dryRun });
88
+ return result(this.id, [change], { notes: [`Removed ${keys.join(', ')} from ${shortenHome(file)}.`] });
89
+ },
90
+ };
91
+ //# sourceMappingURL=zed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zed.js","sourceRoot":"","sources":["../../src/adapters/zed.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,207 @@
1
+ #!/usr/bin/env node
2
+ import { parseArgs } from 'node:util';
3
+ import process from 'node:process';
4
+ import { connectCommand } from './commands/connect.js';
5
+ import { listCommand } from './commands/list.js';
6
+ import { modelsCommand } from './commands/models.js';
7
+ import { doctorCommand } from './commands/doctor.js';
8
+ import { removeCommand } from './commands/remove.js';
9
+ import { loginCommand } from './commands/login.js';
10
+ import { envCommand } from './commands/env.js';
11
+ import { snippetCommand } from './commands/snippet.js';
12
+ import { loadStore, saveStore, configFile } from './core/store.js';
13
+ import { shortenHome } from './fsutil/edit.js';
14
+ import { HttpError } from './core/http.js';
15
+ import { c, ui } from './ui.js';
16
+ const HELP = `
17
+ ${c.bold('idch-ai')} — point any AI agent at the IDCloudHost OpenAI-compatible gateway
18
+
19
+ ${c.bold('USAGE')}
20
+ idch-ai <command> [agents…] [options]
21
+
22
+ ${c.bold('COMMANDS')}
23
+ connect [agents…] Write provider config for one, several, or all detected agents
24
+ list Show supported agents and which are installed here
25
+ models List the models this key may use
26
+ doctor Probe the live gateway and check every agent config
27
+ remove [agents…] Strip our provider block back out
28
+ login Save gateway URL + key to a profile (nothing else touched)
29
+ logout Forget a saved profile
30
+ env Print the gateway as environment variables
31
+ snippet [lang] Starter code: curl, node, python, vercel-ai, langchain
32
+
33
+ ${c.bold('AGENTS')}
34
+ opencode pi omp hermes openclaw codex claude-code crush goose
35
+ aider continue zed cline cursor qwen-code env (or: all)
36
+
37
+ ${c.bold('CONNECTION')}
38
+ --base-url <url> Gateway base URL (env: IDCH_AI_BASE_URL)
39
+ --api-key <key> Virtual key (env: IDCH_AI_API_KEY)
40
+ --profile <name> Use a saved profile (default: the current one)
41
+ --dashboard-url <url> Discover the gateway through the dashboard API
42
+ --token <jwt> Dashboard access token
43
+ --org <id> Organization id
44
+
45
+ ${c.bold('BEHAVIOUR')}
46
+ --model <id> Model to make the default (repeatable via --only)
47
+ --only <ids> Register only these models (comma separated)
48
+ --provider-id <id> Key our block is written under (default: idcloudhost)
49
+ --secret <mode> inline | env — where the key goes (adapters may override)
50
+ --scope <scope> user | project (default: user)
51
+ --config-path <file> Override the config file, single agent only
52
+ --dry-run Show what would change, write nothing
53
+ --print Print a diff of every change
54
+ --no-verify Skip the live test call after writing
55
+ --no-save Do not save a profile
56
+ --json Machine-readable output
57
+ --yes, -y Never prompt
58
+ --help, -h This text
59
+ --version, -v Print the version
60
+
61
+ ${c.bold('EXAMPLES')}
62
+ idch-ai login
63
+ idch-ai connect
64
+ idch-ai connect opencode pi omp
65
+ idch-ai connect all --model deepseek-chat
66
+ idch-ai connect openclaw --dry-run --print
67
+ idch-ai doctor
68
+ eval "$(idch-ai env)"
69
+ `;
70
+ async function main(argv) {
71
+ const { values, positionals } = parseArgs({
72
+ args: argv,
73
+ allowPositionals: true,
74
+ strict: true,
75
+ options: {
76
+ 'base-url': { type: 'string' },
77
+ 'api-key': { type: 'string' },
78
+ profile: { type: 'string' },
79
+ 'dashboard-url': { type: 'string' },
80
+ token: { type: 'string' },
81
+ org: { type: 'string' },
82
+ model: { type: 'string' },
83
+ only: { type: 'string' },
84
+ 'provider-id': { type: 'string' },
85
+ 'provider-label': { type: 'string' },
86
+ secret: { type: 'string' },
87
+ scope: { type: 'string' },
88
+ 'config-path': { type: 'string' },
89
+ shell: { type: 'string' },
90
+ 'dry-run': { type: 'boolean', default: false },
91
+ print: { type: 'boolean', default: false },
92
+ // Explicit negative flags rather than parseArgs' allowNegative, which only
93
+ // exists on newer Node than this package supports.
94
+ 'no-verify': { type: 'boolean', default: false },
95
+ 'no-save': { type: 'boolean', default: false },
96
+ offline: { type: 'boolean', default: false },
97
+ json: { type: 'boolean', default: false },
98
+ yes: { type: 'boolean', short: 'y', default: false },
99
+ help: { type: 'boolean', short: 'h', default: false },
100
+ version: { type: 'boolean', short: 'v', default: false },
101
+ },
102
+ });
103
+ if (values.version) {
104
+ ui.plain(await version());
105
+ return 0;
106
+ }
107
+ const command = positionals[0];
108
+ if (values.help || !command || command === 'help') {
109
+ ui.plain(HELP.trim());
110
+ return command || values.help ? 0 : 1;
111
+ }
112
+ const secret = values.secret;
113
+ if (secret && secret !== 'inline' && secret !== 'env')
114
+ throw new Error('--secret must be "inline" or "env"');
115
+ const scope = values.scope;
116
+ if (scope && scope !== 'user' && scope !== 'project')
117
+ throw new Error('--scope must be "user" or "project"');
118
+ const flags = {
119
+ cwd: process.cwd(),
120
+ json: values.json,
121
+ yes: values.yes,
122
+ dryRun: values['dry-run'],
123
+ print: values.print,
124
+ verify: !values['no-verify'],
125
+ save: !values['no-save'],
126
+ offline: values.offline,
127
+ ...(values['base-url'] ? { baseUrl: values['base-url'] } : {}),
128
+ ...(values['api-key'] ? { apiKey: values['api-key'] } : {}),
129
+ ...(values.profile ? { profile: values.profile, profileName: values.profile } : {}),
130
+ ...(values['dashboard-url'] ? { dashboardUrl: values['dashboard-url'] } : {}),
131
+ ...(values.token ? { token: values.token } : {}),
132
+ ...(values.org ? { org: values.org } : {}),
133
+ ...(values.model ? { defaultModel: values.model } : {}),
134
+ ...(values.only ? { onlyModels: values.only.split(',').map((s) => s.trim()).filter(Boolean) } : {}),
135
+ ...(values['provider-id'] ? { providerId: values['provider-id'] } : {}),
136
+ ...(values['provider-label'] ? { providerLabel: values['provider-label'] } : {}),
137
+ ...(secret ? { secret } : {}),
138
+ ...(scope ? { scope } : {}),
139
+ ...(values['config-path'] ? { configPath: values['config-path'] } : {}),
140
+ };
141
+ const rest = positionals.slice(1);
142
+ switch (command) {
143
+ case 'connect':
144
+ case 'setup':
145
+ return connectCommand(rest, flags);
146
+ case 'list':
147
+ case 'agents':
148
+ return listCommand(flags);
149
+ case 'models':
150
+ return modelsCommand(flags);
151
+ case 'doctor':
152
+ case 'verify':
153
+ return doctorCommand(flags);
154
+ case 'remove':
155
+ case 'disconnect':
156
+ return removeCommand(rest, flags);
157
+ case 'login':
158
+ return loginCommand(flags);
159
+ case 'logout':
160
+ return logout(flags);
161
+ case 'env':
162
+ return envCommand({ ...flags, ...(values.shell ? { shell: values.shell } : {}) });
163
+ case 'snippet':
164
+ return snippetCommand(rest[0], flags);
165
+ default:
166
+ throw new Error(`unknown command "${command}". Run \`idch-ai --help\`.`);
167
+ }
168
+ }
169
+ async function logout(flags) {
170
+ const store = await loadStore();
171
+ const name = flags.profileName ?? store.current;
172
+ if (!name || !store.profiles[name]) {
173
+ ui.info('no saved profile to remove');
174
+ return 0;
175
+ }
176
+ delete store.profiles[name];
177
+ if (store.current === name)
178
+ delete store.current;
179
+ await saveStore(store);
180
+ ui.ok(`Removed profile "${name}" from ${shortenHome(configFile())}`);
181
+ ui.info('Agent configs still hold the key. Run `idch-ai remove all` to strip those too.');
182
+ return 0;
183
+ }
184
+ async function version() {
185
+ const { readFile } = await import('node:fs/promises');
186
+ const url = new URL('../package.json', import.meta.url);
187
+ const pkg = JSON.parse(await readFile(url, 'utf8'));
188
+ return pkg.version ?? '0.0.0';
189
+ }
190
+ main(process.argv.slice(2))
191
+ .then((code) => {
192
+ process.exitCode = code;
193
+ })
194
+ .catch((err) => {
195
+ if (err instanceof HttpError) {
196
+ ui.fail(err.friendly);
197
+ if (err.status === 401)
198
+ ui.info('The gateway rejected the key. Check it, or generate a new one in the dashboard.');
199
+ if (err.status === 429)
200
+ ui.info('You are over a budget or rate limit. Check your usage in the dashboard.');
201
+ }
202
+ else {
203
+ ui.fail(err instanceof Error ? err.message : String(err));
204
+ }
205
+ process.exitCode = 1;
206
+ });
207
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type GlobalFlags } from './context.js';
2
+ export declare function connectCommand(agentArgs: string[], flags: GlobalFlags): Promise<number>;
3
+ //# sourceMappingURL=connect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":"AAQA,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAG7D,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAkG7F"}
@@ -0,0 +1,179 @@
1
+ import prompts from 'prompts';
2
+ import { adapters, getAdapter } from '../adapters/index.js';
3
+ import { buildTarget, resolveSource } from '../core/discovery.js';
4
+ import { testChat } from '../core/gateway.js';
5
+ import { saveProfile } from '../core/store.js';
6
+ import { shortenHome, unifiedDiff } from '../fsutil/edit.js';
7
+ import { c, maskKey, ui } from '../ui.js';
8
+ import { interactive } from './context.js';
9
+ import { promptForCredentials } from './login.js';
10
+ export async function connectCommand(agentArgs, flags) {
11
+ // 1. Credentials. Ask only when we cannot find them and someone is watching.
12
+ let source;
13
+ try {
14
+ source = await resolveSource(flags);
15
+ }
16
+ catch (err) {
17
+ if (!interactive(flags))
18
+ throw err;
19
+ ui.warn(err.message);
20
+ source = await promptForCredentials(flags);
21
+ }
22
+ ui.step(`Gateway ${c.bold(source.baseUrl)} ${c.dim(`(${source.from.baseUrl})`)}`);
23
+ ui.step(`Key ${c.bold(maskKey(source.apiKey))} ${c.dim(`(${source.from.apiKey})`)}`);
24
+ // 2. Probe the gateway and pull the model catalogue.
25
+ const target = await buildTarget(source, flags);
26
+ if (target.models.length) {
27
+ ui.ok(`${target.models.length} model(s) available to this key. Default: ${c.bold(target.defaultModel ?? 'none')}`);
28
+ }
29
+ else {
30
+ ui.warn('No models were listed. Configs will be written with whatever --model you passed.');
31
+ }
32
+ // 3. Which agents.
33
+ const chosen = await chooseAgents(agentArgs, flags);
34
+ if (!chosen.length) {
35
+ ui.warn('No agents selected — nothing to do.');
36
+ return 0;
37
+ }
38
+ // 4. Apply.
39
+ const results = [];
40
+ const failures = [];
41
+ for (const adapter of chosen) {
42
+ const secretMode = flags.secret && adapter.secretModes.includes(flags.secret) ? flags.secret : adapter.secretModes[0];
43
+ const opts = {
44
+ target,
45
+ dryRun: flags.dryRun ?? false,
46
+ secretMode,
47
+ scope: flags.scope ?? 'user',
48
+ cwd: flags.cwd,
49
+ ...(flags.configPath && chosen.length === 1 ? { configPathOverride: flags.configPath } : {}),
50
+ };
51
+ try {
52
+ results.push(await adapter.apply(opts));
53
+ }
54
+ catch (err) {
55
+ failures.push({ adapter, error: err });
56
+ ui.fail(`${adapter.name}: ${err.message}`);
57
+ }
58
+ }
59
+ // 5. Report.
60
+ if (flags.json) {
61
+ ui.plain(JSON.stringify({
62
+ gateway: { apiBase: target.apiBase, defaultModel: target.defaultModel, models: target.models.map((m) => m.id) },
63
+ applied: results,
64
+ failed: failures.map((f) => ({ adapter: f.adapter.id, error: f.error.message })),
65
+ }, null, 2));
66
+ return failures.length ? 1 : 0;
67
+ }
68
+ reportResults(results, chosen, flags);
69
+ // 6. Prove it works, rather than claiming it does.
70
+ if (flags.verify !== false && !flags.dryRun && target.defaultModel) {
71
+ ui.title('Verifying');
72
+ try {
73
+ const reply = await testChat(target.apiBase, target.apiKey, target.defaultModel);
74
+ ui.ok(`${target.defaultModel} replied: ${c.dim(JSON.stringify(reply.slice(0, 60)))}`);
75
+ }
76
+ catch (err) {
77
+ ui.fail(`the gateway did not answer a test call: ${err.message}`);
78
+ ui.info('The config files were still written. Run `idch-ai doctor` for a fuller diagnosis.');
79
+ return 1;
80
+ }
81
+ }
82
+ // 7. Remember, so the next agent is a one-liner.
83
+ if (flags.save !== false && !flags.dryRun) {
84
+ const name = flags.profileName ?? 'default';
85
+ const file = await saveProfile(name, {
86
+ apiBase: target.apiBase,
87
+ apiKey: target.apiKey,
88
+ savedAt: new Date().toISOString(),
89
+ ...(target.defaultModel ? { defaultModel: target.defaultModel } : {}),
90
+ ...(flags.dashboardUrl ? { dashboardUrl: flags.dashboardUrl } : {}),
91
+ ...(flags.org ? { orgId: flags.org } : {}),
92
+ });
93
+ ui.info(`Saved profile "${name}" to ${shortenHome(file)} (chmod 600).`);
94
+ }
95
+ return failures.length ? 1 : 0;
96
+ }
97
+ async function chooseAgents(agentArgs, flags) {
98
+ const names = agentArgs.flatMap((a) => a.split(',')).map((a) => a.trim()).filter(Boolean);
99
+ if (names.includes('all'))
100
+ return adapters.filter((a) => a.mode === 'auto');
101
+ if (names.length) {
102
+ const found = [];
103
+ for (const name of names) {
104
+ const adapter = getAdapter(name);
105
+ if (!adapter)
106
+ throw new Error(`unknown agent "${name}". Run \`idch-ai list\` to see the supported ones.`);
107
+ found.push(adapter);
108
+ }
109
+ return found;
110
+ }
111
+ // Nothing named: offer what is actually installed on this machine.
112
+ const detected = await Promise.all(adapters.map(async (a) => ({ adapter: a, detect: await a.detect({ cwd: flags.cwd }) })));
113
+ const installed = detected.filter((d) => d.detect.installed && d.adapter.id !== 'env');
114
+ if (!interactive(flags)) {
115
+ if (!installed.length)
116
+ throw new Error('no supported agents were detected. Name one explicitly, e.g. `idch-ai connect opencode`.');
117
+ return installed.map((d) => d.adapter);
118
+ }
119
+ if (!installed.length) {
120
+ ui.warn('No supported agents detected on this machine.');
121
+ }
122
+ const { picked } = (await prompts({
123
+ type: 'multiselect',
124
+ name: 'picked',
125
+ message: 'Which agents should point at the gateway?',
126
+ instructions: false,
127
+ choices: adapters.map((a) => {
128
+ const hit = detected.find((d) => d.adapter.id === a.id);
129
+ const badge = hit?.detect.installed ? c.green('installed') : c.dim('not found');
130
+ return {
131
+ title: `${a.name} ${badge}${a.mode === 'manual' ? c.dim(' (prints instructions)') : ''}`,
132
+ value: a.id,
133
+ selected: hit?.detect.installed === true && a.mode === 'auto',
134
+ };
135
+ }),
136
+ }, { onCancel: () => process.exit(130) }));
137
+ return (picked ?? []).map((id) => getAdapter(id)).filter(Boolean);
138
+ }
139
+ function reportResults(results, chosen, flags) {
140
+ const envVars = {};
141
+ for (const res of results) {
142
+ const adapter = chosen.find((a) => a.id === res.adapterId);
143
+ ui.title(adapter.name);
144
+ if (adapter.mode === 'manual') {
145
+ for (const note of res.notes)
146
+ ui.plain(` ${note}`);
147
+ continue;
148
+ }
149
+ if (!res.changes.length) {
150
+ ui.info('nothing to change');
151
+ }
152
+ for (const change of res.changes) {
153
+ if (change.unchanged) {
154
+ ui.ok(`${shortenHome(change.path)} ${c.dim('already up to date')}`);
155
+ continue;
156
+ }
157
+ const verb = flags.dryRun ? 'would write' : change.before === null ? 'created' : 'updated';
158
+ ui.ok(`${verb} ${shortenHome(change.path)}`);
159
+ if (change.backupPath)
160
+ ui.info(`backup: ${shortenHome(change.backupPath)}`);
161
+ if (flags.print || flags.dryRun) {
162
+ ui.plain(c.dim(unifiedDiff(change.before, change.after, shortenHome(change.path))));
163
+ }
164
+ }
165
+ for (const note of res.notes)
166
+ ui.info(note);
167
+ Object.assign(envVars, res.envVars);
168
+ if (res.tryCommand)
169
+ ui.plain(` ${c.dim('try:')} ${c.bold(res.tryCommand)}`);
170
+ }
171
+ if (Object.keys(envVars).length) {
172
+ ui.title('Environment');
173
+ ui.info('These configs read the key from the environment. Export it before starting the agent:');
174
+ for (const [k, v] of Object.entries(envVars))
175
+ ui.code(`export ${k}=${JSON.stringify(v)}`);
176
+ ui.info('Or run `idch-ai connect env` to get a sourceable file instead.');
177
+ }
178
+ }
179
+ //# sourceMappingURL=connect.js.map