@kesarcloud/omega-plus-cli 2.0.4 → 2.0.6

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 CHANGED
@@ -30,8 +30,8 @@ Defaults:
30
30
  - OpenAI-compatible URL: `https://omega.kesarcloud.in/api/v1`
31
31
  - Anthropic-compatible URL: `https://omega.kesarcloud.in/v1`
32
32
  - API key validation URL: `https://omega.kesarcloud.in/api/omega/validate-key`
33
- - Model: `omega-v1-pro`
34
- - Fast model: `omega-v1`
33
+ - Model: `omega-plus` (default)
34
+ - Additional models: `KesarCloud/anthropic/claude-opus-4-6`, `KesarCloud/anthropic/claude-opus-4.7`, `KesarCloud/openai/gpt-5.5`
35
35
 
36
36
  Use `--base-url`, `--openai-base-url`, `--anthropic-base-url`, `--model`, or `--fast-model` to override them.
37
37
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kesarcloud/omega-plus-cli",
3
- "version": "2.0.4",
3
+ "version": "2.0.6",
4
4
  "description": "Interactive Omega Plus setup wizard for coding CLI tools.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -18,7 +18,9 @@
18
18
  },
19
19
  "keywords": [
20
20
  "omega-plus",
21
- "omega-v1",
21
+ "claude-opus-4-6",
22
+ "claude-opus-4-7",
23
+ "gpt-5-5",
22
24
  "claude-code",
23
25
  "codex",
24
26
  "opencode",
package/src/cli.mjs CHANGED
@@ -7,21 +7,26 @@ import {
7
7
  DEFAULT_VALIDATION_URL,
8
8
  VERSION,
9
9
  } from "./constants.mjs";
10
- import { printDoctor, printToolList, runNonInteractiveConfigure, runWizard } from "./wizard.mjs";
10
+ import { printDoctor, printToolList, runNonInteractiveConfigure, runWizard, runUpdateFlow } from "./wizard.mjs";
11
+ import { scanForMigration, migrateAllTools } from "./migrate.mjs";
11
12
 
12
13
  function printHelp() {
13
14
  console.log(`Omega Plus CLI ${VERSION}
14
15
 
15
16
  Usage:
16
- omega-plus
17
- omega-plus setup
17
+ omega-plus Interactive setup wizard
18
+ omega-plus setup New setup with menu
19
+ omega-plus update Update existing tool configs
18
20
  omega-plus configure --tool <id> --api-key <key>
19
- omega-plus list
20
- omega-plus doctor
21
+ omega-plus list List tools and status
22
+ omega-plus doctor Diagnostic info
23
+ omega-plus docs Open documentation
24
+ omega-plus migrate Migrate old configs
21
25
 
22
26
  Options:
23
27
  --api-key <key> Omega API key
24
28
  --tool <id> claude, codex, opencode, cline, kilo, droid
29
+ --update Skip menu and go directly to update flow
25
30
  --base-url <url> Default: ${DEFAULT_BASE_URL}
26
31
  --openai-base-url Codex/OpenAI-compatible default: ${DEFAULT_OPENAI_BASE_URL}
27
32
  --anthropic-base-url Anthropic-compatible default: ${DEFAULT_ANTHROPIC_BASE_URL}
@@ -30,8 +35,10 @@ Options:
30
35
  --fast-model <id> Default: ${DEFAULT_FAST_MODEL}
31
36
  --skip-key-validation Skip server-side API key validation
32
37
  --dry-run Preview files without writing
33
- --yes Auto-confirm install prompts
38
+ --yes Auto-confirm prompts
34
39
  --no-install Do not install missing tools
40
+ --migrate-all Auto-migrate old omega-v1 configs
41
+ --skip-migration-check Skip stale config detection
35
42
  --help Show help
36
43
  --version Show version
37
44
  `);
@@ -50,6 +57,9 @@ function parseArgs(argv) {
50
57
  else if (arg === "--skip-key-validation") options.skipKeyValidation = true;
51
58
  else if (arg === "--yes" || arg === "-y") options.yes = true;
52
59
  else if (arg === "--no-install") options.noInstall = true;
60
+ else if (arg === "--migrate-all") options.migrateAll = true;
61
+ else if (arg === "--skip-migration-check") options.skipMigrationCheck = true;
62
+ else if (arg === "--update") options.update = true;
53
63
  else if (arg === "--api-key") options.apiKey = args[++i];
54
64
  else if (arg.startsWith("--api-key=")) options.apiKey = arg.slice("--api-key=".length);
55
65
  else if (arg === "--tool") options.tool = args[++i];
@@ -90,6 +100,14 @@ export async function main(argv = process.argv.slice(2)) {
90
100
  case "setup":
91
101
  await runWizard(options);
92
102
  break;
103
+ case "update":
104
+ options.update = true;
105
+ await runWizard(options);
106
+ break;
107
+ case "docs":
108
+ options.command = "docs";
109
+ await runWizard(options);
110
+ break;
93
111
  case "configure":
94
112
  await runNonInteractiveConfigure(options);
95
113
  break;
@@ -99,6 +117,18 @@ export async function main(argv = process.argv.slice(2)) {
99
117
  case "doctor":
100
118
  await printDoctor();
101
119
  break;
120
+ case "migrate": {
121
+ const scan = await scanForMigration();
122
+ console.log(`Scanned ${scan.total} tools. Found ${scan.stale.length} with stale configs.`);
123
+ if (scan.stale.length > 0) {
124
+ const result = await migrateAllTools(options);
125
+ console.log(result.message);
126
+ result.results?.forEach((r) => {
127
+ console.log(` ${r.ok ? "✓" : "✗"} ${r.tool}${r.ok ? "" : ` — ${r.error}`}`);
128
+ });
129
+ }
130
+ break;
131
+ }
102
132
  default:
103
133
  throw new Error(`Unknown command: ${command}. Run omega-plus --help.`);
104
134
  }
package/src/constants.mjs CHANGED
@@ -1,9 +1,10 @@
1
- export const VERSION = "2.0.4";
1
+ export const VERSION = "2.0.6";
2
2
  export const DEFAULT_ORIGIN = "https://omega.kesarcloud.in";
3
3
  export const DEFAULT_BASE_URL = `${DEFAULT_ORIGIN}/v1`;
4
4
  export const DEFAULT_ANTHROPIC_BASE_URL = `${DEFAULT_ORIGIN}/v1`;
5
5
  export const DEFAULT_OPENAI_BASE_URL = `${DEFAULT_ORIGIN}/api/v1`;
6
6
  export const DEFAULT_VALIDATION_URL = `${DEFAULT_ORIGIN}/api/omega/validate-key`;
7
+ export const DOCS_URL = `${DEFAULT_ORIGIN}/documentation`;
7
8
  export const DEFAULT_MODEL = "omega-plus";
8
9
  export const DEFAULT_FAST_MODEL = "omega-plus";
9
10
  export const OMEGA_CONTEXT_WINDOW = 1_000_000;
@@ -11,6 +12,9 @@ export const OMEGA_MAX_OUTPUT_TOKENS = 32000;
11
12
 
12
13
  export const OMEGA_MODELS = [
13
14
  { id: "omega-plus", name: "Omega Plus" },
15
+ { id: "KesarCloud/anthropic/claude-opus-4-6", name: "Claude Opus 4.6" },
16
+ { id: "KesarCloud/anthropic/claude-opus-4.7", name: "Claude Opus 4.7" },
17
+ { id: "KesarCloud/openai/gpt-5.5", name: "GPT 5.5" },
14
18
  ];
15
19
 
16
20
  export const TOOL_IDS = ["claude", "codex", "opencode", "cline", "kilo", "droid"];
@@ -0,0 +1,95 @@
1
+ import { detectAllTools } from "./detector.mjs";
2
+ import { configureTool } from "./config-writers.mjs";
3
+ import { DEFAULT_MODEL, DEFAULT_FAST_MODEL, VERSION } from "./constants.mjs";
4
+ import { readJson, readText } from "./fs-utils.mjs";
5
+ import { getToolPaths } from "./tool-paths.mjs";
6
+
7
+ const OLD_MODEL_IDS = [/omega-v1(?![-]plus)/, /"Omega V1"/, /omega\.v1/i];
8
+ const CURRENT_MODEL = "omega-plus";
9
+
10
+ function hasOldModels(text) {
11
+ if (typeof text !== "string") return false;
12
+ return OLD_MODEL_IDS.some((re) => re.test(text));
13
+ }
14
+
15
+ async function detectStaleConfig(tool) {
16
+ if (tool.configStatus !== "configured" || !tool.configPath) return false;
17
+ try {
18
+ const content = await readText(tool.configPath, "");
19
+ return hasOldModels(content);
20
+ } catch {
21
+ return false;
22
+ }
23
+ }
24
+
25
+ async function detectAdditionalConfigs(tool) {
26
+ const paths = getToolPaths(tool.id);
27
+ const checks = [];
28
+ for (const [, p] of Object.entries(paths)) {
29
+ if (!p || p === tool.configPath) continue;
30
+ try {
31
+ const content = await readText(p, "");
32
+ if (hasOldModels(content) || hasOldModels(JSON.stringify(await readJson(p, null) || ""))) {
33
+ checks.push(p);
34
+ }
35
+ } catch {}
36
+ }
37
+ return checks;
38
+ }
39
+
40
+ export async function scanForMigration(options = {}) {
41
+ const tools = await detectAllTools();
42
+ const stale = [];
43
+
44
+ for (const tool of tools) {
45
+ if (await detectStaleConfig(tool)) {
46
+ const extra = await detectAdditionalConfigs(tool);
47
+ stale.push({ tool, paths: [tool.configPath, ...extra].filter(Boolean) });
48
+ }
49
+ }
50
+
51
+ return { stale, total: tools.length, version: VERSION };
52
+ }
53
+
54
+ export async function migrateAllTools(options = {}) {
55
+ const { stale } = await scanForMigration(options);
56
+ if (stale.length === 0) {
57
+ return { migrated: 0, message: "All configs are up to date with Omega Plus." };
58
+ }
59
+
60
+ const apiKey = options.apiKey || options.apikey;
61
+ if (!apiKey) {
62
+ return {
63
+ migrated: 0,
64
+ stale,
65
+ error: "API key required for migration. Use: npx @kesarcloud/omega-plus-cli --migrate --api-key YOUR_KEY",
66
+ };
67
+ }
68
+
69
+ const results = [];
70
+ for (const entry of stale) {
71
+ try {
72
+ const result = await configureTool(entry.tool.id, {
73
+ apiKey,
74
+ model: DEFAULT_MODEL,
75
+ fastModel: DEFAULT_FAST_MODEL,
76
+ ...options,
77
+ });
78
+ results.push({ tool: entry.tool.name, id: entry.tool.id, ok: true, files: result.files });
79
+ } catch (err) {
80
+ results.push({
81
+ tool: entry.tool.name,
82
+ id: entry.tool.id,
83
+ ok: false,
84
+ error: err.message || "Unknown error",
85
+ });
86
+ }
87
+ }
88
+
89
+ return {
90
+ migrated: results.filter((r) => r.ok).length,
91
+ total: stale.length,
92
+ results,
93
+ message: `Migrated ${results.filter((r) => r.ok).length}/${stale.length} tools to Omega Plus.`,
94
+ };
95
+ }
package/src/wizard.mjs CHANGED
@@ -2,6 +2,8 @@ import {
2
2
  DEFAULT_BASE_URL,
3
3
  DEFAULT_FAST_MODEL,
4
4
  DEFAULT_MODEL,
5
+ DEFAULT_ORIGIN,
6
+ DOCS_URL,
5
7
  TOOL_DEFINITIONS,
6
8
  } from "./constants.mjs";
7
9
  import { printBanner } from "./banner.mjs";
@@ -9,6 +11,22 @@ import { configureTool } from "./config-writers.mjs";
9
11
  import { detectAllTools, detectTool, runInstallCommand } from "./detector.mjs";
10
12
  import { validateApiKey } from "./key-validator.mjs";
11
13
  import { ask, askSecret, createPromptInterface } from "./prompts.mjs";
14
+ import { scanForMigration, migrateAllTools } from "./migrate.mjs";
15
+ import { configPath, roamingConfigPath, readJson } from "./fs-utils.mjs";
16
+ import { fileURLToPath } from "node:url";
17
+ import { spawn } from "node:child_process";
18
+
19
+ function openUrl(url) {
20
+ const platform = process.platform;
21
+ try {
22
+ if (platform === "darwin") spawn("open", [url], { stdio: "ignore", detached: true }).unref();
23
+ else if (platform === "win32") spawn("start", ["", url], { stdio: "ignore", detached: true, shell: true }).unref();
24
+ else spawn("xdg-open", [url], { stdio: "ignore", detached: true }).unref();
25
+ return true;
26
+ } catch {
27
+ return false;
28
+ }
29
+ }
12
30
 
13
31
  function printHeader() {
14
32
  printBanner();
@@ -57,21 +75,192 @@ async function maybeInstallTool(toolId, options, rl) {
57
75
  return detectTool(toolId);
58
76
  }
59
77
 
78
+ export async function showMainMenu(rl, options = {}) {
79
+ const lines = [
80
+ "",
81
+ " What would you like to do?",
82
+ "",
83
+ " 1. \u{1F680} New Setup",
84
+ " Connect a new tool with your API key",
85
+ "",
86
+ " 2. \u{1F504} Update Current Setup",
87
+ " Update existing tool configs with latest models",
88
+ "",
89
+ ' 3. \u{1F4DA} Documentation',
90
+ ` Open Omega Plus docs — ${DOCS_URL}`,
91
+ "",
92
+ ];
93
+ for (const line of lines) console.log(line);
94
+
95
+ if (options.update === true) return 2;
96
+ if (options.command === "docs") return 3;
97
+
98
+ const answer = await ask(rl, " Enter option (1-3): ");
99
+ const num = Number.parseInt(answer.trim(), 10);
100
+ if (num === 1 || num === 2 || num === 3) return num;
101
+ return 0;
102
+ }
103
+
104
+ async function extractApiKeyFromConfig(toolId) {
105
+ const tool = TOOL_DEFINITIONS[toolId];
106
+ if (!tool) return null;
107
+
108
+ try {
109
+ switch (toolId) {
110
+ case "claude": {
111
+ const cfg = await readJson(configPath([".claude", "settings.json"]));
112
+ return cfg?.env?.ANTHROPIC_AUTH_TOKEN || null;
113
+ }
114
+ case "codex": {
115
+ const cfg = await readJson(configPath([".codex", "auth.json"]));
116
+ return cfg?.OPENAI_API_KEY || null;
117
+ }
118
+ case "opencode": {
119
+ const cfg = await readJson(configPath([".config", "opencode", "opencode.json"]));
120
+ return cfg?.provider?.kesarcloud?.options?.apiKey || cfg?.provider?.omega?.options?.apiKey || null;
121
+ }
122
+ case "cline": {
123
+ const cfg = await readJson(configPath([".cline", "data", "secrets.json"]));
124
+ return cfg?.anthropicApiKey || null;
125
+ }
126
+ case "kilo": {
127
+ const cfg = await readJson(roamingConfigPath(["kilo", "auth.json"]));
128
+ return cfg?.anthropic?.apiKey || null;
129
+ }
130
+ case "droid": {
131
+ const cfg = await readJson(configPath([".factory", "settings.json"]));
132
+ return cfg?.customModels?.[0]?.apiKey || null;
133
+ }
134
+ default:
135
+ return null;
136
+ }
137
+ } catch {
138
+ return null;
139
+ }
140
+ }
141
+
142
+ export async function runUpdateFlow(options = {}) {
143
+ const rl = createPromptInterface();
144
+ try {
145
+ const allTools = await detectAllTools();
146
+ const configured = allTools.filter((t) => t.configStatus === "configured" && t.installed);
147
+
148
+ if (configured.length === 0) {
149
+ console.log("\nNo configured tools found. Run New Setup first to connect a tool.\n");
150
+ return { skipped: true, reason: "no_configured_tools" };
151
+ }
152
+
153
+ console.log("\nSelect a tool to update:");
154
+ configured.forEach((tool, index) => {
155
+ console.log(` ${index + 1}. ${tool.name}`);
156
+ });
157
+
158
+ const answer = options.tool || (await ask(rl, "\nEnter tool number: "));
159
+ const trimmed = String(answer || "").trim();
160
+ let toolId = null;
161
+ if (TOOL_DEFINITIONS[trimmed.toLowerCase()]) {
162
+ toolId = trimmed.toLowerCase();
163
+ } else {
164
+ const num = Number.parseInt(trimmed, 10);
165
+ if (num >= 1 && num <= configured.length) toolId = configured[num - 1].id;
166
+ }
167
+ if (!toolId) throw new Error("Invalid tool selection");
168
+
169
+ // Extract API key from existing config
170
+ let apiKey = await extractApiKeyFromConfig(toolId);
171
+ if (!apiKey) {
172
+ console.log("\nCould not read your existing API key from config.");
173
+ apiKey = await askSecret("Paste your Omega API key to continue: ");
174
+ if (!apiKey) throw new Error("API key is required");
175
+ } else {
176
+ console.log(`\nUsing existing API key from ${toolId} config...`);
177
+ }
178
+
179
+ console.log("\nUpdating configuration with latest models...");
180
+ const result = await configureTool(toolId, {
181
+ apiKey,
182
+ baseUrl: options.baseUrl || DEFAULT_BASE_URL,
183
+ openaiBaseUrl: options.openaiBaseUrl,
184
+ anthropicBaseUrl: options.anthropicBaseUrl,
185
+ model: options.model || DEFAULT_MODEL,
186
+ fastModel: options.fastModel || DEFAULT_FAST_MODEL,
187
+ dryRun: options.dryRun,
188
+ });
189
+
190
+ if (options.dryRun) {
191
+ console.log("\nDry run complete. No files were changed.");
192
+ result.files.forEach((file) => console.log(` would write: ${file.path}`));
193
+ return result;
194
+ }
195
+
196
+ console.log(`\n${result.message}`);
197
+ result.files.forEach((file) => {
198
+ console.log(` updated: ${file.path}`);
199
+ });
200
+ console.log("\nYour models have been updated to the latest Omega Plus endpoints.");
201
+ return result;
202
+ } finally {
203
+ rl.close();
204
+ }
205
+ }
206
+
60
207
  export async function runWizard(options = {}) {
61
208
  printHeader();
62
- const apiKey = options.apiKey || (await askSecret("Paste your Omega API key: "));
63
- if (!apiKey) throw new Error("API key is required");
64
209
 
65
- console.log("Checking your Omega API key...");
66
- await validateApiKey(apiKey, {
67
- baseUrl: options.baseUrl || DEFAULT_BASE_URL,
68
- validationUrl: options.validationUrl,
69
- skipKeyValidation: options.skipKeyValidation,
70
- });
71
- console.log(options.skipKeyValidation ? "API key validation skipped." : "API key verified.");
210
+ // ── Check for stale configs (old omega-v1/v1-pro model IDs) ──
211
+ if (!options.skipMigrationCheck) {
212
+ const migration = await scanForMigration();
213
+ if (migration.stale.length > 0) {
214
+ console.log(`\nDetected ${migration.stale.length} tool(s) with old model configs (omega-v1 / omega-v1-pro).`);
215
+ console.log("These should be migrated to Omega Plus.\n");
216
+ if (options.yes || options.migrateAll) {
217
+ console.log("Auto-migrating...");
218
+ const result = await migrateAllTools({ ...options, apiKey: options.apiKey });
219
+ console.log(result.message);
220
+ result.results?.forEach((r) => {
221
+ console.log(` ${r.ok ? "✓" : "✗"} ${r.tool}${r.ok ? "" : ` — ${r.error}`}`);
222
+ });
223
+ console.log("");
224
+ } else {
225
+ console.log("Tip: re-run with --migrate-all to auto-update, or continue to reconfigure manually.\n");
226
+ }
227
+ }
228
+ }
72
229
 
73
230
  const rl = createPromptInterface();
74
231
  try {
232
+ // ── Show main menu ──
233
+ const menuChoice = await showMainMenu(rl, options);
234
+
235
+ // Option 3: Docs
236
+ if (menuChoice === 3) {
237
+ console.log(`\nOpening ${DOCS_URL} ...`);
238
+ const opened = openUrl(DOCS_URL);
239
+ if (!opened) console.log(`Please visit: ${DOCS_URL}`);
240
+ return { skipped: true, reason: "docs" };
241
+ }
242
+
243
+ // Option 2: Update
244
+ if (menuChoice === 2) {
245
+ return runUpdateFlow(options);
246
+ }
247
+
248
+ // Option 1 or invalid: New Setup (default)
249
+ if (menuChoice !== 1 && menuChoice !== 0) {
250
+ console.log("\nStarting New Setup...\n");
251
+ }
252
+
253
+ const apiKey = options.apiKey || (await askSecret("Paste your Omega API key: "));
254
+ if (!apiKey) throw new Error("API key is required");
255
+
256
+ console.log("Checking your Omega API key...");
257
+ await validateApiKey(apiKey, {
258
+ baseUrl: options.baseUrl || DEFAULT_BASE_URL,
259
+ validationUrl: options.validationUrl,
260
+ skipKeyValidation: options.skipKeyValidation,
261
+ });
262
+ console.log(options.skipKeyValidation ? "API key validation skipped." : "API key verified.");
263
+
75
264
  const tools = await detectAllTools();
76
265
  printTools(tools);
77
266
  const answer = options.tool || (await ask(rl, "\nEnter tool number: "));