llm-config-cli 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.
- package/dist/bin/llm-config.d.ts +2 -0
- package/dist/bin/llm-config.js +4 -0
- package/dist/bin/llm-config.js.map +1 -0
- package/dist/cli/commands/clear.d.ts +2 -0
- package/dist/cli/commands/clear.js +39 -0
- package/dist/cli/commands/clear.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +2 -0
- package/dist/cli/commands/doctor.js +41 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/env-clean.d.ts +2 -0
- package/dist/cli/commands/env-clean.js +27 -0
- package/dist/cli/commands/env-clean.js.map +1 -0
- package/dist/cli/commands/get.d.ts +2 -0
- package/dist/cli/commands/get.js +26 -0
- package/dist/cli/commands/get.js.map +1 -0
- package/dist/cli/commands/init.d.ts +2 -0
- package/dist/cli/commands/init.js +44 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/restore.d.ts +2 -0
- package/dist/cli/commands/restore.js +25 -0
- package/dist/cli/commands/restore.js.map +1 -0
- package/dist/cli/commands/set.d.ts +2 -0
- package/dist/cli/commands/set.js +38 -0
- package/dist/cli/commands/set.js.map +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +24 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/change-plan.d.ts +10 -0
- package/dist/core/change-plan.js +73 -0
- package/dist/core/change-plan.js.map +1 -0
- package/dist/core/paths.d.ts +7 -0
- package/dist/core/paths.js +21 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/redact.d.ts +1 -0
- package/dist/core/redact.js +10 -0
- package/dist/core/redact.js.map +1 -0
- package/dist/core/types.d.ts +72 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/fs/atomic.d.ts +1 -0
- package/dist/fs/atomic.js +10 -0
- package/dist/fs/atomic.js.map +1 -0
- package/dist/fs/backup.d.ts +1 -0
- package/dist/fs/backup.js +16 -0
- package/dist/fs/backup.js.map +1 -0
- package/dist/providers/base.d.ts +17 -0
- package/dist/providers/base.js +2 -0
- package/dist/providers/base.js.map +1 -0
- package/dist/providers/claude-code.d.ts +2 -0
- package/dist/providers/claude-code.js +118 -0
- package/dist/providers/claude-code.js.map +1 -0
- package/dist/providers/codex.d.ts +2 -0
- package/dist/providers/codex.js +215 -0
- package/dist/providers/codex.js.map +1 -0
- package/dist/providers/openclaw.d.ts +2 -0
- package/dist/providers/openclaw.js +215 -0
- package/dist/providers/openclaw.js.map +1 -0
- package/dist/providers/registry.d.ts +5 -0
- package/dist/providers/registry.js +19 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/shells/cleanup.d.ts +6 -0
- package/dist/shells/cleanup.js +42 -0
- package/dist/shells/cleanup.js.map +1 -0
- package/dist/shells/discovery.d.ts +4 -0
- package/dist/shells/discovery.js +19 -0
- package/dist/shells/discovery.js.map +1 -0
- package/dist/shells/managed-blocks.d.ts +10 -0
- package/dist/shells/managed-blocks.js +80 -0
- package/dist/shells/managed-blocks.js.map +1 -0
- package/dist/tests/provider-registry.test.d.ts +1 -0
- package/dist/tests/provider-registry.test.js +24 -0
- package/dist/tests/provider-registry.test.js.map +1 -0
- package/dist/tests/restore.test.d.ts +1 -0
- package/dist/tests/restore.test.js +95 -0
- package/dist/tests/restore.test.js.map +1 -0
- package/dist/tests/shell-cleanup.test.d.ts +1 -0
- package/dist/tests/shell-cleanup.test.js +70 -0
- package/dist/tests/shell-cleanup.test.js.map +1 -0
- package/package.json +35 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import { planFileWrite } from '../core/change-plan.js';
|
|
3
|
+
import { removeManagedEntries } from './managed-blocks.js';
|
|
4
|
+
async function readIfExists(filePath) {
|
|
5
|
+
try {
|
|
6
|
+
return await fs.readFile(filePath, 'utf8');
|
|
7
|
+
}
|
|
8
|
+
catch (error) {
|
|
9
|
+
if (error.code === 'ENOENT') {
|
|
10
|
+
return '';
|
|
11
|
+
}
|
|
12
|
+
throw error;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export async function planShellCleanup(args) {
|
|
16
|
+
if (!args.shellFile) {
|
|
17
|
+
return {
|
|
18
|
+
provider: args.provider ?? 'claude-code',
|
|
19
|
+
summary: args.provider
|
|
20
|
+
? `Remove managed ${args.provider} environment variables`
|
|
21
|
+
: 'Remove all managed environment variables',
|
|
22
|
+
changes: [
|
|
23
|
+
{
|
|
24
|
+
type: 'notice',
|
|
25
|
+
message: 'No shell file resolved for managed environment cleanup.',
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const before = await readIfExists(args.shellFile);
|
|
31
|
+
const after = removeManagedEntries(before, args.provider);
|
|
32
|
+
return planFileWrite({
|
|
33
|
+
path: args.shellFile,
|
|
34
|
+
nextContent: after,
|
|
35
|
+
provider: args.provider ?? 'claude-code',
|
|
36
|
+
summary: args.provider
|
|
37
|
+
? `Remove managed ${args.provider} environment variables`
|
|
38
|
+
: 'Remove all managed environment variables',
|
|
39
|
+
backup: args.backup,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=cleanup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/shells/cleanup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE3D,KAAK,UAAU,YAAY,CAAC,QAAgB;IAC1C,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAItC;IACC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QACpB,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,aAAa;YACxC,OAAO,EAAE,IAAI,CAAC,QAAQ;gBACpB,CAAC,CAAC,kBAAkB,IAAI,CAAC,QAAQ,wBAAwB;gBACzD,CAAC,CAAC,0CAA0C;YAC9C,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,QAAQ;oBACd,OAAO,EAAE,yDAAyD;iBACnE;aACF;SACF,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAE1D,OAAO,aAAa,CAAC;QACnB,IAAI,EAAE,IAAI,CAAC,SAAS;QACpB,WAAW,EAAE,KAAK;QAClB,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,aAAa;QACxC,OAAO,EAAE,IAAI,CAAC,QAAQ;YACpB,CAAC,CAAC,kBAAkB,IAAI,CAAC,QAAQ,wBAAwB;YACzD,CAAC,CAAC,0CAA0C;QAC9C,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import { getCandidateShellFiles } from '../core/paths.js';
|
|
3
|
+
export async function discoverShellFiles(options = {}) {
|
|
4
|
+
const candidates = options.preferred ? [options.preferred] : getCandidateShellFiles({ homeDir: options.homeDir });
|
|
5
|
+
const existing = [];
|
|
6
|
+
for (const file of candidates) {
|
|
7
|
+
try {
|
|
8
|
+
await fs.access(file);
|
|
9
|
+
existing.push(file);
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
if (options.preferred) {
|
|
13
|
+
existing.push(file);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return existing.length > 0 ? existing : [candidates[0]];
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/shells/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,UAAoD,EAAE;IAC7F,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAClH,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACtB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;gBACtB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ManagedEnvEntry, ProviderId } from '../core/types.js';
|
|
2
|
+
export declare const BLOCK_START = "# BEGIN llm-config managed block";
|
|
3
|
+
export declare const BLOCK_END = "# END llm-config managed block";
|
|
4
|
+
export declare function parseManagedBlock(content: string): {
|
|
5
|
+
start: number;
|
|
6
|
+
end: number;
|
|
7
|
+
} | undefined;
|
|
8
|
+
export declare function upsertManagedBlock(content: string, entries: ManagedEnvEntry[]): string;
|
|
9
|
+
export declare function getManagedEntries(content: string): ManagedEnvEntry[];
|
|
10
|
+
export declare function removeManagedEntries(content: string, provider?: ProviderId): string;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
export const BLOCK_START = '# BEGIN llm-config managed block';
|
|
2
|
+
export const BLOCK_END = '# END llm-config managed block';
|
|
3
|
+
function formatEntry(entry) {
|
|
4
|
+
return `export ${entry.key}=${JSON.stringify(entry.value)} # llm-config:${entry.provider}`;
|
|
5
|
+
}
|
|
6
|
+
function splitLines(content) {
|
|
7
|
+
return content === '' ? [] : content.replace(/\n$/, '').split('\n');
|
|
8
|
+
}
|
|
9
|
+
export function parseManagedBlock(content) {
|
|
10
|
+
const lines = splitLines(content);
|
|
11
|
+
const start = lines.findIndex((line) => line.trim() === BLOCK_START);
|
|
12
|
+
if (start === -1) {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
const end = lines.findIndex((line, index) => index > start && line.trim() === BLOCK_END);
|
|
16
|
+
if (end === -1) {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
return { start, end };
|
|
20
|
+
}
|
|
21
|
+
export function upsertManagedBlock(content, entries) {
|
|
22
|
+
const lines = splitLines(content);
|
|
23
|
+
const blockLines = [BLOCK_START, ...entries.map(formatEntry), BLOCK_END];
|
|
24
|
+
const range = parseManagedBlock(content);
|
|
25
|
+
if (!range) {
|
|
26
|
+
const next = lines.length === 0 ? blockLines : [...lines, '', ...blockLines];
|
|
27
|
+
return `${next.join('\n')}\n`;
|
|
28
|
+
}
|
|
29
|
+
const next = [...lines.slice(0, range.start), ...blockLines, ...lines.slice(range.end + 1)];
|
|
30
|
+
return `${next.join('\n')}\n`;
|
|
31
|
+
}
|
|
32
|
+
export function getManagedEntries(content) {
|
|
33
|
+
const lines = splitLines(content);
|
|
34
|
+
const range = parseManagedBlock(content);
|
|
35
|
+
if (!range) {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
return lines
|
|
39
|
+
.slice(range.start + 1, range.end)
|
|
40
|
+
.map((line) => line.trim())
|
|
41
|
+
.filter(Boolean)
|
|
42
|
+
.flatMap((line) => {
|
|
43
|
+
const match = line.match(/^export\s+([^=]+)=(.+?)\s+#\s+llm-config:([a-z-]+)$/);
|
|
44
|
+
if (!match) {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
const [, key, rawValue, provider] = match;
|
|
48
|
+
try {
|
|
49
|
+
return [
|
|
50
|
+
{
|
|
51
|
+
key,
|
|
52
|
+
value: JSON.parse(rawValue),
|
|
53
|
+
provider: provider,
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
export function removeManagedEntries(content, provider) {
|
|
63
|
+
const range = parseManagedBlock(content);
|
|
64
|
+
if (!range) {
|
|
65
|
+
return content;
|
|
66
|
+
}
|
|
67
|
+
const lines = splitLines(content);
|
|
68
|
+
const entries = getManagedEntries(content).filter((entry) => !provider || entry.provider !== provider);
|
|
69
|
+
if (entries.length === 0) {
|
|
70
|
+
const before = lines.slice(0, range.start);
|
|
71
|
+
const after = lines.slice(range.end + 1);
|
|
72
|
+
const next = [...before];
|
|
73
|
+
if (next[next.length - 1] === '' && after[0] === '') {
|
|
74
|
+
next.pop();
|
|
75
|
+
}
|
|
76
|
+
return [...next, ...after].join('\n').replace(/^\n+/, '').replace(/\n*$/, '\n');
|
|
77
|
+
}
|
|
78
|
+
return upsertManagedBlock(content, entries);
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=managed-blocks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"managed-blocks.js","sourceRoot":"","sources":["../../src/shells/managed-blocks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { getProvider, listProviders } from '../providers/registry.js';
|
|
3
|
+
describe('provider registry', () => {
|
|
4
|
+
it('lists all providers', () => {
|
|
5
|
+
expect(listProviders().map((provider) => provider.id)).toEqual([
|
|
6
|
+
'claude-code',
|
|
7
|
+
'codex',
|
|
8
|
+
'openclaw',
|
|
9
|
+
]);
|
|
10
|
+
});
|
|
11
|
+
it('resolves aliases', () => {
|
|
12
|
+
expect(getProvider('claude').id).toBe('claude-code');
|
|
13
|
+
expect(getProvider('codex').id).toBe('codex');
|
|
14
|
+
});
|
|
15
|
+
it('requires restore support on all providers', () => {
|
|
16
|
+
for (const provider of listProviders()) {
|
|
17
|
+
expect(typeof provider.planRestoreOfficial).toBe('function');
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
it('throws on unknown provider', () => {
|
|
21
|
+
expect(() => getProvider('unknown')).toThrow('Unknown provider: unknown');
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
//# sourceMappingURL=provider-registry.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-registry.test.js","sourceRoot":"","sources":["../../src/tests/provider-registry.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEtE,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,aAAa,EAAE,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;YAC7D,aAAa;YACb,OAAO;YACP,UAAU;SACX,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAC1B,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACrD,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,KAAK,MAAM,QAAQ,IAAI,aAAa,EAAE,EAAE,CAAC;YACvC,MAAM,CAAC,OAAO,QAAQ,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { afterEach, describe, expect, it } from 'vitest';
|
|
5
|
+
import { planShellCleanup } from '../shells/cleanup.js';
|
|
6
|
+
import { codexProvider } from '../providers/codex.js';
|
|
7
|
+
const tempDirs = [];
|
|
8
|
+
async function makeTempHome() {
|
|
9
|
+
const dir = await fs.mkdtemp(path.join(os.tmpdir(), 'llm-config-test-'));
|
|
10
|
+
tempDirs.push(dir);
|
|
11
|
+
return dir;
|
|
12
|
+
}
|
|
13
|
+
afterEach(async () => {
|
|
14
|
+
await Promise.all(tempDirs.splice(0).map((dir) => fs.rm(dir, { recursive: true, force: true })));
|
|
15
|
+
});
|
|
16
|
+
describe('restore semantics', () => {
|
|
17
|
+
it('removes only managed codex fallback when official target exists', async () => {
|
|
18
|
+
const homeDir = await makeTempHome();
|
|
19
|
+
const shellFile = path.join(homeDir, '.zshrc');
|
|
20
|
+
const officialDir = path.join(homeDir, '.codex');
|
|
21
|
+
await fs.mkdir(officialDir, { recursive: true });
|
|
22
|
+
await fs.writeFile(path.join(officialDir, 'config.json'), '{"profile":"official"}\n');
|
|
23
|
+
await fs.writeFile(shellFile, [
|
|
24
|
+
'export USER_KEEP="1"',
|
|
25
|
+
'# BEGIN llm-config managed block',
|
|
26
|
+
'export CODEX_API_KEY="secret" # llm-config:codex',
|
|
27
|
+
'export CODEX_BASE_URL="https://fallback.example.com" # llm-config:codex',
|
|
28
|
+
'export OPENCLAW_API_KEY="other" # llm-config:openclaw',
|
|
29
|
+
'# END llm-config managed block',
|
|
30
|
+
'',
|
|
31
|
+
].join('\n'));
|
|
32
|
+
const plan = await codexProvider.planRestoreOfficial({ homeDir, shellFile });
|
|
33
|
+
const writeChange = plan.changes.find((change) => change.type === 'write-file');
|
|
34
|
+
if (!writeChange || writeChange.type !== 'write-file') {
|
|
35
|
+
throw new Error('expected write-file change');
|
|
36
|
+
}
|
|
37
|
+
expect(plan.changes[0]).toEqual({
|
|
38
|
+
type: 'notice',
|
|
39
|
+
message: `Removing managed Codex fallback override from ${shellFile} so ${path.join(officialDir, 'config.json')} can become effective again.`,
|
|
40
|
+
});
|
|
41
|
+
expect(writeChange.after).toContain('export USER_KEEP="1"');
|
|
42
|
+
expect(writeChange.after).toContain('OPENCLAW_API_KEY');
|
|
43
|
+
expect(writeChange.after).not.toContain('CODEX_API_KEY');
|
|
44
|
+
expect(writeChange.after).not.toContain('CODEX_BASE_URL');
|
|
45
|
+
expect(await fs.readFile(path.join(officialDir, 'config.json'), 'utf8')).toBe('{"profile":"official"}\n');
|
|
46
|
+
});
|
|
47
|
+
it('fails restore when no official target exists', async () => {
|
|
48
|
+
const homeDir = await makeTempHome();
|
|
49
|
+
const shellFile = path.join(homeDir, '.zshrc');
|
|
50
|
+
await fs.writeFile(shellFile, [
|
|
51
|
+
'# BEGIN llm-config managed block',
|
|
52
|
+
'export CODEX_API_KEY="secret" # llm-config:codex',
|
|
53
|
+
'# END llm-config managed block',
|
|
54
|
+
'',
|
|
55
|
+
].join('\n'));
|
|
56
|
+
const plan = await codexProvider.planRestoreOfficial({ homeDir, shellFile });
|
|
57
|
+
expect(plan.changes).toEqual([
|
|
58
|
+
{
|
|
59
|
+
type: 'notice',
|
|
60
|
+
message: 'Cannot restore Codex to official configuration because no confirmed official target was detected.',
|
|
61
|
+
},
|
|
62
|
+
]);
|
|
63
|
+
});
|
|
64
|
+
it('does not delete handwritten env entries during restore', async () => {
|
|
65
|
+
const homeDir = await makeTempHome();
|
|
66
|
+
const shellFile = path.join(homeDir, '.zshrc');
|
|
67
|
+
const officialDir = path.join(homeDir, '.codex');
|
|
68
|
+
await fs.mkdir(officialDir, { recursive: true });
|
|
69
|
+
await fs.writeFile(path.join(officialDir, 'config.json'), '{}\n');
|
|
70
|
+
await fs.writeFile(shellFile, [
|
|
71
|
+
'export CODEX_API_KEY="handwritten"',
|
|
72
|
+
'# BEGIN llm-config managed block',
|
|
73
|
+
'export CODEX_API_KEY="managed" # llm-config:codex',
|
|
74
|
+
'# END llm-config managed block',
|
|
75
|
+
'',
|
|
76
|
+
].join('\n'));
|
|
77
|
+
const plan = await codexProvider.planRestoreOfficial({ homeDir, shellFile });
|
|
78
|
+
const writeChange = plan.changes.find((change) => change.type === 'write-file');
|
|
79
|
+
if (!writeChange || writeChange.type !== 'write-file') {
|
|
80
|
+
throw new Error('expected write-file change');
|
|
81
|
+
}
|
|
82
|
+
expect(writeChange.after).toContain('export CODEX_API_KEY="handwritten"');
|
|
83
|
+
expect(writeChange.after).not.toContain('# llm-config:codex');
|
|
84
|
+
});
|
|
85
|
+
it('returns a notice instead of using an empty shell path during env cleanup', async () => {
|
|
86
|
+
const plan = await planShellCleanup({ provider: 'codex' });
|
|
87
|
+
expect(plan.changes).toEqual([
|
|
88
|
+
{
|
|
89
|
+
type: 'notice',
|
|
90
|
+
message: 'No shell file resolved for managed environment cleanup.',
|
|
91
|
+
},
|
|
92
|
+
]);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
//# sourceMappingURL=restore.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restore.test.js","sourceRoot":"","sources":["../../src/tests/restore.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { getManagedEntries, removeManagedEntries, upsertManagedBlock } from '../shells/managed-blocks.js';
|
|
3
|
+
describe('managed shell cleanup', () => {
|
|
4
|
+
it('adds a managed block without touching user exports', () => {
|
|
5
|
+
const before = 'export USER_VALUE="keep"\n';
|
|
6
|
+
const after = upsertManagedBlock(before, [
|
|
7
|
+
{ key: 'CODEX_API_KEY', value: 'secret', provider: 'codex' },
|
|
8
|
+
]);
|
|
9
|
+
expect(after).toContain('export USER_VALUE="keep"');
|
|
10
|
+
expect(after).toContain('# BEGIN llm-config managed block');
|
|
11
|
+
expect(after).toContain('export CODEX_API_KEY="secret" # llm-config:codex');
|
|
12
|
+
});
|
|
13
|
+
it('removes only one provider from the managed block', () => {
|
|
14
|
+
const before = [
|
|
15
|
+
'export USER_VALUE="keep"',
|
|
16
|
+
'# BEGIN llm-config managed block',
|
|
17
|
+
'export CODEX_API_KEY="secret" # llm-config:codex',
|
|
18
|
+
'export OPENCLAW_API_KEY="other" # llm-config:openclaw',
|
|
19
|
+
'# END llm-config managed block',
|
|
20
|
+
'',
|
|
21
|
+
].join('\n');
|
|
22
|
+
const after = removeManagedEntries(before, 'codex');
|
|
23
|
+
expect(after).toContain('export USER_VALUE="keep"');
|
|
24
|
+
expect(after).not.toContain('CODEX_API_KEY');
|
|
25
|
+
expect(after).toContain('OPENCLAW_API_KEY');
|
|
26
|
+
});
|
|
27
|
+
it('removes the whole block when last managed entry is deleted', () => {
|
|
28
|
+
const before = [
|
|
29
|
+
'export USER_VALUE="keep"',
|
|
30
|
+
'# BEGIN llm-config managed block',
|
|
31
|
+
'export CODEX_API_KEY="secret" # llm-config:codex',
|
|
32
|
+
'# END llm-config managed block',
|
|
33
|
+
'',
|
|
34
|
+
].join('\n');
|
|
35
|
+
const after = removeManagedEntries(before, 'codex');
|
|
36
|
+
expect(after).toBe('export USER_VALUE="keep"\n');
|
|
37
|
+
});
|
|
38
|
+
it('preserves other providers and user exports during restore-style cleanup', () => {
|
|
39
|
+
const before = [
|
|
40
|
+
'export USER_VALUE="keep"',
|
|
41
|
+
'# BEGIN llm-config managed block',
|
|
42
|
+
'export CODEX_API_KEY="secret" # llm-config:codex',
|
|
43
|
+
'export OPENCLAW_API_KEY="other" # llm-config:openclaw',
|
|
44
|
+
'# END llm-config managed block',
|
|
45
|
+
'export USER_AFTER="keep-too"',
|
|
46
|
+
'',
|
|
47
|
+
].join('\n');
|
|
48
|
+
const after = removeManagedEntries(before, 'codex');
|
|
49
|
+
expect(after).toContain('export USER_VALUE="keep"');
|
|
50
|
+
expect(after).toContain('export USER_AFTER="keep-too"');
|
|
51
|
+
expect(after).not.toContain('CODEX_API_KEY');
|
|
52
|
+
expect(after).toContain('OPENCLAW_API_KEY');
|
|
53
|
+
});
|
|
54
|
+
it('parses managed entries with provider markers', () => {
|
|
55
|
+
const content = [
|
|
56
|
+
'# BEGIN llm-config managed block',
|
|
57
|
+
'export OPENCLAW_BASE_URL="https://example.com" # llm-config:openclaw',
|
|
58
|
+
'# END llm-config managed block',
|
|
59
|
+
'',
|
|
60
|
+
].join('\n');
|
|
61
|
+
expect(getManagedEntries(content)).toEqual([
|
|
62
|
+
{
|
|
63
|
+
key: 'OPENCLAW_BASE_URL',
|
|
64
|
+
value: 'https://example.com',
|
|
65
|
+
provider: 'openclaw',
|
|
66
|
+
},
|
|
67
|
+
]);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
//# sourceMappingURL=shell-cleanup.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell-cleanup.test.js","sourceRoot":"","sources":["../../src/tests/shell-cleanup.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "llm-config-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI for configuring Claude Code, Codex, and OpenClaw API settings",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"llm-config": "dist/bin/llm-config.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=20"
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc -p tsconfig.json",
|
|
17
|
+
"dev": "tsx src/bin/llm-config.ts",
|
|
18
|
+
"test": "vitest run",
|
|
19
|
+
"test:watch": "vitest",
|
|
20
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
21
|
+
"pack:check": "npm pack --dry-run"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@inquirer/prompts": "^7.3.2",
|
|
25
|
+
"commander": "^14.0.0",
|
|
26
|
+
"picocolors": "^1.1.1",
|
|
27
|
+
"zod": "^4.1.5"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/node": "^24.3.0",
|
|
31
|
+
"tsx": "^4.20.5",
|
|
32
|
+
"typescript": "^5.9.2",
|
|
33
|
+
"vitest": "^3.2.4"
|
|
34
|
+
}
|
|
35
|
+
}
|