@minniexcode/codex-switch 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.AI.md +66 -94
- package/README.CN.md +84 -139
- package/README.md +91 -151
- package/dist/app/add-provider.js +6 -83
- package/dist/app/edit-provider.js +9 -29
- package/dist/app/get-status.js +1 -77
- package/dist/app/list-providers.js +0 -2
- package/dist/app/remove-provider.js +3 -5
- package/dist/app/run-doctor.js +2 -99
- package/dist/app/setup-codex.js +0 -2
- package/dist/app/switch-provider.js +1 -74
- package/dist/cli/output.js +3 -89
- package/dist/commands/handlers.js +20 -172
- package/dist/commands/help.js +1 -4
- package/dist/commands/registry.js +6 -74
- package/dist/domain/config.js +1 -3
- package/dist/domain/providers.js +4 -92
- package/dist/domain/runtime-state.js +0 -88
- package/dist/interaction/add-interactive.js +1 -55
- package/dist/interaction/interactive.js +1 -3
- package/dist/runtime/codex-probe.js +0 -12
- package/dist/storage/codex-paths.js +0 -2
- package/docs/Design/codex-switch-v0.2.1-design.md +77 -0
- package/docs/PRD/codex-switch-prd-v0.2.1.md +82 -0
- package/docs/Tests/testing.md +32 -34
- package/docs/cli-usage.md +67 -235
- package/docs/codex-switch-command-design.md +1 -1
- package/docs/codex-switch-product-overview.md +49 -96
- package/docs/codex-switch-technical-architecture.md +37 -52
- package/package.json +1 -1
- package/dist/app/bridge.js +0 -303
- package/dist/runtime/copilot-adapter.js +0 -617
- package/dist/runtime/copilot-bridge-worker.js +0 -69
- package/dist/runtime/copilot-bridge.js +0 -1351
- package/dist/runtime/copilot-cli.js +0 -164
- package/dist/runtime/copilot-http-bridge-worker.js +0 -228
- package/dist/runtime/copilot-installer.js +0 -231
- package/dist/runtime/copilot-sdk-loader.js +0 -62
- package/dist/runtime/copilot-token.js +0 -294
- package/dist/storage/runtime-state-repo.js +0 -121
|
@@ -1,94 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.getStorageRoles = getStorageRoles;
|
|
37
3
|
exports.inspectLiveStateDrift = inspectLiveStateDrift;
|
|
38
|
-
const path = __importStar(require("node:path"));
|
|
39
|
-
/**
|
|
40
|
-
* Returns the stable storage contract used by the CLI.
|
|
41
|
-
*/
|
|
42
|
-
function getStorageRoles(args) {
|
|
43
|
-
const toolHomeDir = path.dirname(path.resolve(args.providersPath));
|
|
44
|
-
const backupsDir = path.join(toolHomeDir, "backups");
|
|
45
|
-
const runtimeDir = args.runtimeDir ? path.resolve(args.runtimeDir) : path.join(toolHomeDir, "runtime");
|
|
46
|
-
const runtimesDir = args.runtimesDir ? path.resolve(args.runtimesDir) : path.join(toolHomeDir, "runtimes");
|
|
47
|
-
return {
|
|
48
|
-
toolHome: {
|
|
49
|
-
root: toolHomeDir,
|
|
50
|
-
toolConfig: path.join(toolHomeDir, "codex-switch.json"),
|
|
51
|
-
providers: path.resolve(args.providersPath),
|
|
52
|
-
backupsDir,
|
|
53
|
-
latestBackup: path.join(backupsDir, "latest.json"),
|
|
54
|
-
runtimeStateDir: runtimeDir,
|
|
55
|
-
runtimeInstallDir: runtimesDir,
|
|
56
|
-
},
|
|
57
|
-
targetRuntime: {
|
|
58
|
-
root: path.resolve(args.codexDir),
|
|
59
|
-
config: path.resolve(args.configPath),
|
|
60
|
-
auth: path.resolve(args.authPath),
|
|
61
|
-
},
|
|
62
|
-
managementSSOT: {
|
|
63
|
-
scope: "toolHome",
|
|
64
|
-
path: path.resolve(args.providersPath),
|
|
65
|
-
},
|
|
66
|
-
runtimeMirrors: [
|
|
67
|
-
{
|
|
68
|
-
scope: "targetRuntime",
|
|
69
|
-
path: path.resolve(args.configPath),
|
|
70
|
-
},
|
|
71
|
-
],
|
|
72
|
-
authStateFile: {
|
|
73
|
-
scope: "targetRuntime",
|
|
74
|
-
path: path.resolve(args.authPath),
|
|
75
|
-
},
|
|
76
|
-
rollbackState: {
|
|
77
|
-
scope: "toolHome",
|
|
78
|
-
path: path.join(backupsDir, "latest.json"),
|
|
79
|
-
},
|
|
80
|
-
runtimeState: {
|
|
81
|
-
scope: "toolHome",
|
|
82
|
-
path: runtimeDir,
|
|
83
|
-
managedBackup: false,
|
|
84
|
-
},
|
|
85
|
-
runtimeInstall: {
|
|
86
|
-
scope: "toolHome",
|
|
87
|
-
path: runtimesDir,
|
|
88
|
-
managedBackup: false,
|
|
89
|
-
},
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
4
|
/**
|
|
93
5
|
* Compares the live active model_provider against managed providers to detect drift.
|
|
94
6
|
*/
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.COMMON_TAG_CHOICES = void 0;
|
|
4
4
|
exports.collectAddInput = collectAddInput;
|
|
5
|
-
exports.collectCopilotAddInput = collectCopilotAddInput;
|
|
6
5
|
exports.createNonInteractiveAddError = createNonInteractiveAddError;
|
|
7
6
|
exports.promptTags = promptTags;
|
|
8
7
|
const errors_1 = require("../domain/errors");
|
|
@@ -38,51 +37,10 @@ async function collectAddInput(runtime, defaults, providerExists, profileExists)
|
|
|
38
37
|
tags,
|
|
39
38
|
};
|
|
40
39
|
}
|
|
41
|
-
/**
|
|
42
|
-
* Collects Copilot add command inputs interactively when required values are missing.
|
|
43
|
-
*/
|
|
44
|
-
async function collectCopilotAddInput(runtime, defaults, providerExists, profileExists, options) {
|
|
45
|
-
runtime.writeLine("Interactive add mode");
|
|
46
|
-
runtime.writeLine("Provide the missing Copilot provider fields. Press Enter to keep optional values empty.");
|
|
47
|
-
const providerName = defaults.providerName
|
|
48
|
-
? normalizeRequiredValue(defaults.providerName)
|
|
49
|
-
: await promptProviderName(runtime, providerExists);
|
|
50
|
-
const profile = defaults.profile ? normalizeRequiredValue(defaults.profile) : await promptRequiredValue(runtime, "Profile");
|
|
51
|
-
const createProfile = !profileExists(profile);
|
|
52
|
-
const model = createProfile
|
|
53
|
-
? defaults.model
|
|
54
|
-
? normalizeRequiredValue(defaults.model)
|
|
55
|
-
: await promptRequiredValue(runtime, `Model for new profile "${profile}"`)
|
|
56
|
-
: defaults.model ?? null;
|
|
57
|
-
const note = defaults.note ?? normalizeOptionalValue(await runtime.inputText("Note (optional)"));
|
|
58
|
-
const tags = defaults.tags.length > 0 ? defaults.tags : await promptTags(runtime);
|
|
59
|
-
const bridgeHost = options?.bridgeHost ?? normalizeOptionalValue(await runtime.inputText("Bridge host (optional)", { defaultValue: "127.0.0.1" }));
|
|
60
|
-
const bridgePortText = options?.bridgePort !== undefined && options.bridgePort !== null
|
|
61
|
-
? String(options.bridgePort)
|
|
62
|
-
: await runtime.inputText("Bridge port (optional)", { defaultValue: "41415" });
|
|
63
|
-
const bridgePort = normalizeBridgePort(runtime, bridgePortText);
|
|
64
|
-
const bridgeApiKey = options?.bridgeApiKey ?? normalizeOptionalValue(await runtime.inputSecret("Bridge API key (optional)"));
|
|
65
|
-
return {
|
|
66
|
-
providerName,
|
|
67
|
-
profile,
|
|
68
|
-
createProfile,
|
|
69
|
-
model,
|
|
70
|
-
note,
|
|
71
|
-
tags,
|
|
72
|
-
bridgeApiKey,
|
|
73
|
-
bridgeHost,
|
|
74
|
-
bridgePort,
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
40
|
/**
|
|
78
41
|
* Throws a consistent error when interactive add is unavailable.
|
|
79
42
|
*/
|
|
80
|
-
function createNonInteractiveAddError(
|
|
81
|
-
if (options?.copilot) {
|
|
82
|
-
return (0, errors_1.cliError)("INVALID_ARGUMENT", "add --copilot requires <provider> and --profile when running without an interactive TTY.", {
|
|
83
|
-
suggestion: "Run in a terminal TTY or pass <provider>, --profile, and any optional Copilot bridge flags explicitly.",
|
|
84
|
-
});
|
|
85
|
-
}
|
|
43
|
+
function createNonInteractiveAddError() {
|
|
86
44
|
return (0, errors_1.cliError)("INVALID_ARGUMENT", "add requires <provider>, --profile, and --api-key when running without an interactive TTY.", {
|
|
87
45
|
suggestion: "Run in a terminal TTY or pass all required values explicitly.",
|
|
88
46
|
});
|
|
@@ -132,18 +90,6 @@ function normalizeOptionalValue(value) {
|
|
|
132
90
|
const normalized = value.trim();
|
|
133
91
|
return normalized === "" ? null : normalized;
|
|
134
92
|
}
|
|
135
|
-
function normalizeBridgePort(runtime, value) {
|
|
136
|
-
const normalized = value.trim();
|
|
137
|
-
if (normalized === "") {
|
|
138
|
-
return null;
|
|
139
|
-
}
|
|
140
|
-
const parsed = Number(normalized);
|
|
141
|
-
if (Number.isInteger(parsed) && parsed > 0) {
|
|
142
|
-
return parsed;
|
|
143
|
-
}
|
|
144
|
-
runtime.writeLine("Bridge port must be a positive integer. Falling back to the default port.");
|
|
145
|
-
return null;
|
|
146
|
-
}
|
|
147
93
|
async function promptTags(runtime, defaults = []) {
|
|
148
94
|
const defaultPresetTags = defaults.filter(isCommonTag);
|
|
149
95
|
return runtime.selectMany("Select tags (optional)", exports.COMMON_TAG_CHOICES.map((tag) => ({ value: tag, label: tag })), { defaultValues: defaultPresetTags });
|
|
@@ -52,7 +52,6 @@ const fs = __importStar(require("node:fs"));
|
|
|
52
52
|
const path = __importStar(require("node:path"));
|
|
53
53
|
const errors_1 = require("../domain/errors");
|
|
54
54
|
const backups_1 = require("../domain/backups");
|
|
55
|
-
const providers_1 = require("../domain/providers");
|
|
56
55
|
const runtime_state_1 = require("../domain/runtime-state");
|
|
57
56
|
const codex_paths_1 = require("../storage/codex-paths");
|
|
58
57
|
const config_repo_1 = require("../storage/config-repo");
|
|
@@ -81,14 +80,13 @@ async function promptForProviderSelection(runtime, providersPath, configPath, me
|
|
|
81
80
|
const choices = Object.entries(providers.providers)
|
|
82
81
|
.sort(([left], [right]) => left.localeCompare(right))
|
|
83
82
|
.map(([providerName, provider]) => {
|
|
84
|
-
const providerType = (0, providers_1.isCopilotBridgeProvider)(provider) ? "copilot" : "direct";
|
|
85
83
|
const currentMarker = liveState.providerResolvable && liveState.mappedProvider === providerName ? " | current" : "";
|
|
86
84
|
const legacyMarker = !currentMarker && legacyCurrentProvider === providerName ? " | current" : "";
|
|
87
85
|
const ambiguousMarker = !liveState.providerResolvable && liveState.mappedProviders.includes(providerName) ? " | current=ambiguous" : "";
|
|
88
86
|
return {
|
|
89
87
|
value: providerName,
|
|
90
88
|
label: providerName,
|
|
91
|
-
hint: `profile=${provider.profile}
|
|
89
|
+
hint: `profile=${provider.profile}${currentMarker}${legacyMarker}${ambiguousMarker}`,
|
|
92
90
|
};
|
|
93
91
|
});
|
|
94
92
|
if (choices.length === 0) {
|
|
@@ -1,19 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.codexRuntimeProbe = void 0;
|
|
4
3
|
exports.probeCodexRuntime = probeCodexRuntime;
|
|
5
4
|
const codex_cli_1 = require("./codex-cli");
|
|
6
|
-
/**
|
|
7
|
-
* Default dependency probe implementation for the local codex CLI runtime.
|
|
8
|
-
*/
|
|
9
|
-
exports.codexRuntimeProbe = {
|
|
10
|
-
probe(options) {
|
|
11
|
-
if (options?.minVersion) {
|
|
12
|
-
return probeCodexRuntime(options.minVersion);
|
|
13
|
-
}
|
|
14
|
-
return probeCodexRuntime();
|
|
15
|
-
},
|
|
16
|
-
};
|
|
17
5
|
/**
|
|
18
6
|
* Checks whether the codex CLI is installed and, optionally, satisfies a minimum version.
|
|
19
7
|
*/
|
|
@@ -88,8 +88,6 @@ function createCodexPaths(args) {
|
|
|
88
88
|
backupsDir: path.join(toolHomeDir, "backups"),
|
|
89
89
|
latestBackupPath: path.join(toolHomeDir, "backups", "latest.json"),
|
|
90
90
|
lockPath: path.join(toolHomeDir, ".codex-switch.lock"),
|
|
91
|
-
runtimeDir: path.join(toolHomeDir, "runtime"),
|
|
92
|
-
runtimesDir: path.join(toolHomeDir, "runtimes"),
|
|
93
91
|
codexDir,
|
|
94
92
|
configPath: path.join(codexDir, "config.toml"),
|
|
95
93
|
authPath: path.join(codexDir, "auth.json"),
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# codex-switch v0.2.1 Design
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
`0.2.1` narrows the current implementation to provider/model-provider management for Codex. The design removes current-facing bridge/account runtime paths and keeps a direct local-state architecture.
|
|
6
|
+
|
|
7
|
+
## Command Registry
|
|
8
|
+
|
|
9
|
+
The command registry contains only provider-management, config inspection, backup, rollback, and diagnostics commands. Removed command ids such as `login` and `bridge-*` are not part of the internal `CommandId` union.
|
|
10
|
+
|
|
11
|
+
`setup` remains registered only as a deprecated pointer to `init` and `migrate`.
|
|
12
|
+
|
|
13
|
+
## Provider Records
|
|
14
|
+
|
|
15
|
+
`providers.json` remains the managed source of provider records:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"providers": {
|
|
20
|
+
"packycode": {
|
|
21
|
+
"profile": "packycode",
|
|
22
|
+
"apiKey": "sk-...",
|
|
23
|
+
"model": "gpt-5",
|
|
24
|
+
"baseUrl": "https://api.example/v1"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The stored `profile` field is the managed Codex `model_provider` id. Current user-facing docs explain `--profile` as this alias.
|
|
31
|
+
|
|
32
|
+
## Codex Projection
|
|
33
|
+
|
|
34
|
+
Mutating commands project provider state into the target Codex directory:
|
|
35
|
+
|
|
36
|
+
```toml
|
|
37
|
+
model = "gpt-5"
|
|
38
|
+
model_provider = "packycode"
|
|
39
|
+
|
|
40
|
+
[model_providers.packycode]
|
|
41
|
+
name = "packycode"
|
|
42
|
+
base_url = "https://api.example/v1"
|
|
43
|
+
wire_api = "responses"
|
|
44
|
+
requires_openai_auth = true
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Auth projection writes API-key mode into `auth.json`. Managed projection does not create legacy `[profiles.*]` sections for new providers.
|
|
48
|
+
|
|
49
|
+
## Output Contract
|
|
50
|
+
|
|
51
|
+
Human output is provider-management-only:
|
|
52
|
+
|
|
53
|
+
- `list` shows provider name, current marker, model-provider id, model, tags, and note.
|
|
54
|
+
- `status` shows target Codex directory, tool home, current route, mapping state, auth/config health, warnings, and next step.
|
|
55
|
+
- `doctor` shows local config/provider/auth/Codex CLI issues.
|
|
56
|
+
|
|
57
|
+
JSON output keeps the standard envelope:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"ok": true,
|
|
62
|
+
"command": "status",
|
|
63
|
+
"data": {},
|
|
64
|
+
"warnings": [],
|
|
65
|
+
"error": null
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Diagnostics
|
|
70
|
+
|
|
71
|
+
`status` uses route mapping and consistency checks for a lightweight operator view. `doctor` performs issue-first checks across config existence, providers existence, consistency issues, auth projection, route drift, and Codex CLI availability.
|
|
72
|
+
|
|
73
|
+
No optional bridge, SDK, upstream-account, or background-service diagnostics are part of the current design.
|
|
74
|
+
|
|
75
|
+
## Migration Policy
|
|
76
|
+
|
|
77
|
+
Because this repository is still treated as development-version software, `0.2.1` does not add automatic migration shims for old experimental provider or bridge state. Users can manually clean old state or re-add providers.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# codex-switch v0.2.1 PRD
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
`0.2.1` is a provider-management-only consolidation release for `@minniexcode/codex-switch`.
|
|
6
|
+
|
|
7
|
+
The product is a local-first CLI that manages Codex provider/model-provider routing state. It stores local provider records, projects Codex `model_provider` definitions, switches the active top-level `model` / `model_provider` route, and provides backups, diagnostics, import/export, and rollback.
|
|
8
|
+
|
|
9
|
+
## Version
|
|
10
|
+
|
|
11
|
+
- Version line: `0.2.1`
|
|
12
|
+
- Target package version: `0.2.1`
|
|
13
|
+
- Status: current repository development line
|
|
14
|
+
|
|
15
|
+
## Goals
|
|
16
|
+
|
|
17
|
+
- Make the current product positioning explicit: local-first provider/model-provider management.
|
|
18
|
+
- Remove current command and documentation promises for account-login and bridge runtime experiments.
|
|
19
|
+
- Keep direct OpenAI-compatible provider workflows simple and inspectable.
|
|
20
|
+
- Preserve current route-first Codex config projection for Codex `0.134.0+`.
|
|
21
|
+
- Keep `migrate` as an advanced adopt helper for existing Codex state.
|
|
22
|
+
- Keep `setup` only as a deprecated pointer.
|
|
23
|
+
|
|
24
|
+
## Current Command Surface
|
|
25
|
+
|
|
26
|
+
Current public commands are:
|
|
27
|
+
|
|
28
|
+
- `init`
|
|
29
|
+
- `migrate`
|
|
30
|
+
- `list`
|
|
31
|
+
- `show`
|
|
32
|
+
- `current`
|
|
33
|
+
- `status`
|
|
34
|
+
- `config show`
|
|
35
|
+
- `config list-profiles`
|
|
36
|
+
- `add`
|
|
37
|
+
- `edit`
|
|
38
|
+
- `switch`
|
|
39
|
+
- `remove`
|
|
40
|
+
- `import`
|
|
41
|
+
- `export`
|
|
42
|
+
- `backups list`
|
|
43
|
+
- `rollback`
|
|
44
|
+
- `doctor`
|
|
45
|
+
- `setup` as deprecated pointer
|
|
46
|
+
|
|
47
|
+
## Primary Workflow
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
codexs init
|
|
51
|
+
codexs add <provider> --profile <model-provider-id> --model <model> --api-key <key> --base-url <url>
|
|
52
|
+
codexs switch <provider>
|
|
53
|
+
codexs status
|
|
54
|
+
codexs doctor
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Non-Goals
|
|
58
|
+
|
|
59
|
+
`0.2.1` does not implement or reserve runtime code paths for:
|
|
60
|
+
|
|
61
|
+
- GitHub Copilot SDK integration.
|
|
62
|
+
- GitHub device-flow login.
|
|
63
|
+
- `login copilot`.
|
|
64
|
+
- `add --copilot`.
|
|
65
|
+
- HTTP proxy bridge or local bridge worker commands.
|
|
66
|
+
- `bridge start`, `bridge status`, or `bridge stop`.
|
|
67
|
+
- Background runtime services, bridge logs, or bridge runtime state.
|
|
68
|
+
- Built-in third-party router packaging.
|
|
69
|
+
- Account systems or cloud sync.
|
|
70
|
+
- Automatic migration of old Copilot or bridge state.
|
|
71
|
+
|
|
72
|
+
A future release may introduce a third-party router-like integration, but that is outside `0.2.1` and must not be represented as current workflow, schema, or runtime behavior.
|
|
73
|
+
|
|
74
|
+
## Acceptance Criteria
|
|
75
|
+
|
|
76
|
+
- Package metadata reports `0.2.1`.
|
|
77
|
+
- Current docs point to this PRD and the `0.2.1` design doc as fact sources.
|
|
78
|
+
- Help and command registry do not expose removed command ids.
|
|
79
|
+
- Human `list` output does not display provider type.
|
|
80
|
+
- Human `status` and `doctor` output do not report bridge, SDK, upstream auth, or bridge-log state.
|
|
81
|
+
- Interactive add collects only provider-management fields.
|
|
82
|
+
- Tests cover the provider-management-only release contract.
|
package/docs/Tests/testing.md
CHANGED
|
@@ -1,34 +1,32 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
The
|
|
6
|
-
|
|
7
|
-
##
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
npm
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
npm pack --dry-run
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
- Keep fixtures small and realistic.
|
|
34
|
-
- Use `dev-codex/local-sandbox` only when a test needs a representative Codex directory layout.
|
|
1
|
+
# Testing
|
|
2
|
+
|
|
3
|
+
Current version: `0.2.1`
|
|
4
|
+
|
|
5
|
+
The test suite is plain Node.js. `npm test` rebuilds the CLI and runs `tests/run-tests.js`, which discovers `tests/*.spec.js` files.
|
|
6
|
+
|
|
7
|
+
## Commands
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm run build
|
|
11
|
+
npx tsc --noEmit
|
|
12
|
+
npm test
|
|
13
|
+
node dist/cli.js --help
|
|
14
|
+
node dist/cli.js --version
|
|
15
|
+
npm pack --dry-run
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Required Coverage For 0.2.1
|
|
19
|
+
|
|
20
|
+
Focus on the provider-management-only contract:
|
|
21
|
+
|
|
22
|
+
- Version metadata is `0.2.1` in `package.json` and `package-lock.json`.
|
|
23
|
+
- Current docs point to `docs/PRD/codex-switch-prd-v0.2.1.md` and `docs/Design/codex-switch-v0.2.1-design.md`.
|
|
24
|
+
- Help exposes only current commands: `init`, `migrate`, `list`, `show`, `current`, `status`, `config show`, `config list-profiles`, `add`, `edit`, `switch`, `remove`, `import`, `export`, `backups list`, `rollback`, `doctor`, and deprecated `setup`.
|
|
25
|
+
- Fresh provider flow: `init -> add -> switch -> status -> doctor`.
|
|
26
|
+
- Base URL drift diagnostics.
|
|
27
|
+
- Ambiguous active provider mapping.
|
|
28
|
+
- `migrate` remains an advanced adopt helper.
|
|
29
|
+
- `setup` remains a deprecated pointer.
|
|
30
|
+
- JSON output uses the stable envelope.
|
|
31
|
+
|
|
32
|
+
Do not add tests for removed `0.2.1` runtime experiments such as Copilot SDK integration, GitHub login, `add --copilot`, or bridge commands.
|