@ralphkrauss/codex-account-switcher 0.1.8 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/README.md +14 -5
- package/dist/accounts.d.ts +1 -0
- package/dist/accounts.js +12 -2
- package/dist/accounts.js.map +1 -1
- package/dist/cli.js +59 -21
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/remote.d.ts +35 -0
- package/dist/remote.js +303 -12
- package/dist/remote.js.map +1 -1
- package/docs/AGENT_SETUP.md +13 -9
- package/package.json +1 -1
- package/src/accounts.ts +13 -2
- package/src/cli.ts +68 -19
- package/src/index.ts +5 -0
- package/src/remote.ts +392 -12
package/src/accounts.ts
CHANGED
|
@@ -34,6 +34,7 @@ export interface CodexPaths {
|
|
|
34
34
|
|
|
35
35
|
export interface OperationOptions {
|
|
36
36
|
readonly paths?: CodexPaths;
|
|
37
|
+
readonly skipWriteback?: boolean;
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
export interface ForceOptions extends OperationOptions {
|
|
@@ -354,7 +355,15 @@ export async function writebackCurrentAccount(options: OperationOptions = {}): P
|
|
|
354
355
|
return { performed: false, reason: 'live auth.json is missing or too small', account: current.name };
|
|
355
356
|
}
|
|
356
357
|
|
|
357
|
-
|
|
358
|
+
let liveAuthJson: string;
|
|
359
|
+
try {
|
|
360
|
+
liveAuthJson = await readFile(paths.authFile, 'utf8');
|
|
361
|
+
JSON.parse(liveAuthJson) as unknown;
|
|
362
|
+
} catch {
|
|
363
|
+
return { performed: false, reason: 'live auth.json is not valid JSON', account: current.name };
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
await writeFilePrivate(slot, liveAuthJson);
|
|
358
367
|
return { performed: true, account: current.name };
|
|
359
368
|
}
|
|
360
369
|
|
|
@@ -384,7 +393,9 @@ export async function useAccount(name: string, options: OperationOptions = {}):
|
|
|
384
393
|
throw new CxError(`no account '${safeName}'`, 1);
|
|
385
394
|
}
|
|
386
395
|
|
|
387
|
-
const writeback =
|
|
396
|
+
const writeback = options.skipWriteback === true
|
|
397
|
+
? { performed: false, reason: 'writeback skipped by caller' }
|
|
398
|
+
: await writebackCurrentAccount({ paths });
|
|
388
399
|
await copyFilePrivate(source, paths.authFile);
|
|
389
400
|
await writeCurrentMarker(paths, safeName);
|
|
390
401
|
return writeback;
|
package/src/cli.ts
CHANGED
|
@@ -5,6 +5,8 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
|
5
5
|
import {
|
|
6
6
|
CxError,
|
|
7
7
|
authFileExists,
|
|
8
|
+
autoPullAccountForUse,
|
|
9
|
+
autoPushAccountIfChanged,
|
|
8
10
|
configureOnePasswordRemote,
|
|
9
11
|
getCodexPaths,
|
|
10
12
|
inspectHermesStatus,
|
|
@@ -13,6 +15,7 @@ import {
|
|
|
13
15
|
inspectSyncStatus,
|
|
14
16
|
listAccounts,
|
|
15
17
|
loginAccount,
|
|
18
|
+
readCurrentMarker,
|
|
16
19
|
removeAccount,
|
|
17
20
|
renameAccount,
|
|
18
21
|
runCodex,
|
|
@@ -26,6 +29,8 @@ import {
|
|
|
26
29
|
useAccount,
|
|
27
30
|
useHermesAccount,
|
|
28
31
|
validateAccountName,
|
|
32
|
+
writebackCurrentAccount,
|
|
33
|
+
writebackAndAutoPushCurrentAccount,
|
|
29
34
|
type AccountList,
|
|
30
35
|
type DoctorReport,
|
|
31
36
|
type HermesStatus,
|
|
@@ -547,7 +552,10 @@ function formatSyncStatus(status: SyncStatus): string {
|
|
|
547
552
|
|
|
548
553
|
lines.push('accounts:');
|
|
549
554
|
for (const account of status.accounts) {
|
|
550
|
-
lines.push(` - ${account.account}: local=${account.local.exists ? 'present' : 'missing'}, remote=${remotePresenceText(account)}`);
|
|
555
|
+
lines.push(` - ${account.account}: local=${account.local.exists ? 'present' : 'missing'}, remote=${remotePresenceText(account)}, sync=${account.sync.state}`);
|
|
556
|
+
if (account.sync.error) {
|
|
557
|
+
lines.push(` sync error: ${account.sync.error}`);
|
|
558
|
+
}
|
|
551
559
|
lines.push(` file: ${account.local.file}`);
|
|
552
560
|
lines.push(` item: ${account.item ?? '(unknown)'}`);
|
|
553
561
|
}
|
|
@@ -558,23 +566,59 @@ async function printList(io: CliIo, env: NodeJS.ProcessEnv): Promise<void> {
|
|
|
558
566
|
write(io.stdout, formatAccounts(await listAccounts(getCodexPaths(env))));
|
|
559
567
|
}
|
|
560
568
|
|
|
561
|
-
async function
|
|
569
|
+
async function maybeAutoPushCurrent(env: NodeJS.ProcessEnv, io: CliIo): Promise<void> {
|
|
570
|
+
const result = await writebackAndAutoPushCurrentAccount({ env, paths: getCodexPaths(env) });
|
|
571
|
+
if (result?.action === 'pushed') {
|
|
572
|
+
write(io.stdout, `auto-pushed profile '${result.account}'`);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
async function maybeAutoPullCurrent(env: NodeJS.ProcessEnv, io: CliIo): Promise<void> {
|
|
562
577
|
const paths = getCodexPaths(env);
|
|
563
|
-
|
|
564
|
-
|
|
578
|
+
const current = await readCurrentMarker(paths);
|
|
579
|
+
if (current.state !== 'valid') {
|
|
565
580
|
return;
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
581
|
+
}
|
|
582
|
+
await writebackCurrentAccount({ paths });
|
|
583
|
+
const pull = await autoPullAccountForUse(current.name, { env, paths });
|
|
584
|
+
if (pull.action === 'pulled') {
|
|
585
|
+
await useAccount(current.name, { paths, skipWriteback: true });
|
|
586
|
+
write(io.stdout, `auto-pulled ${displayBackendName(pull.backend)}-backed profile '${pull.account}'`);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
570
589
|
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
590
|
+
async function runCodexAndAutoPush(args: readonly string[], env: NodeJS.ProcessEnv, io: CliIo): Promise<number> {
|
|
591
|
+
await maybeAutoPullCurrent(env, io);
|
|
592
|
+
const exitCode = await runCodex(args, { env });
|
|
593
|
+
await maybeAutoPushCurrent(env, io);
|
|
594
|
+
return exitCode;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
async function autoPushNamed(name: string, env: NodeJS.ProcessEnv, io: CliIo): Promise<void> {
|
|
598
|
+
const result = await autoPushAccountIfChanged(name, { env, paths: getCodexPaths(env) });
|
|
599
|
+
if (result.action === 'pushed') {
|
|
600
|
+
write(io.stdout, `auto-pushed profile '${result.account}'`);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
function displayBackendName(backend: string | undefined): string {
|
|
605
|
+
return backend === '1password' ? '1Password' : (backend ?? 'remote');
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
async function useAccountWithRemoteFallback(name: string, env: NodeJS.ProcessEnv, io: CliIo): Promise<void> {
|
|
609
|
+
const paths = getCodexPaths(env);
|
|
610
|
+
const current = await readCurrentMarker(paths);
|
|
611
|
+
const wasActive = current.state === 'valid' && current.name === name;
|
|
612
|
+
if (wasActive) {
|
|
613
|
+
await writebackCurrentAccount({ paths });
|
|
614
|
+
}
|
|
615
|
+
const pull = await autoPullAccountForUse(name, { env, paths });
|
|
616
|
+
if (pull.action === 'pulled') {
|
|
617
|
+
write(io.stdout, `auto-pulled ${displayBackendName(pull.backend)}-backed profile '${pull.account}'`);
|
|
618
|
+
}
|
|
619
|
+
const writeback = await useAccount(name, { paths, skipWriteback: wasActive && pull.action === 'pulled' });
|
|
620
|
+
if (writeback.performed && writeback.account) {
|
|
621
|
+
await autoPushNamed(writeback.account, env, io);
|
|
578
622
|
}
|
|
579
623
|
}
|
|
580
624
|
|
|
@@ -836,7 +880,7 @@ export async function main(
|
|
|
836
880
|
if (!first) {
|
|
837
881
|
const paths = getCodexPaths(env);
|
|
838
882
|
if (await authFileExists(paths)) {
|
|
839
|
-
return await
|
|
883
|
+
return await runCodexAndAutoPush([], env, io);
|
|
840
884
|
}
|
|
841
885
|
|
|
842
886
|
write(io.stdout, helpText(metadata));
|
|
@@ -856,7 +900,7 @@ export async function main(
|
|
|
856
900
|
validateAccountName(first);
|
|
857
901
|
await useAccountWithRemoteFallback(first, env, io);
|
|
858
902
|
write(io.stdout, `→ codex on '${first}'`);
|
|
859
|
-
return await
|
|
903
|
+
return await runCodexAndAutoPush(rest, env, io);
|
|
860
904
|
}
|
|
861
905
|
|
|
862
906
|
switch (first) {
|
|
@@ -874,6 +918,7 @@ export async function main(
|
|
|
874
918
|
const name = parsed.positionals[0] ?? '';
|
|
875
919
|
await saveAccount(name, { force: parsed.force, paths: getCodexPaths(env) });
|
|
876
920
|
write(io.stdout, `saved current login as '${name}'`);
|
|
921
|
+
await autoPushNamed(name, env, io);
|
|
877
922
|
return 0;
|
|
878
923
|
}
|
|
879
924
|
|
|
@@ -887,13 +932,17 @@ export async function main(
|
|
|
887
932
|
|
|
888
933
|
case 'login': {
|
|
889
934
|
const parsed = parseLoginArgs(rest);
|
|
890
|
-
await loginAccount(parsed.name, {
|
|
935
|
+
const writeback = await loginAccount(parsed.name, {
|
|
891
936
|
force: parsed.force,
|
|
892
937
|
loginArgs: parsed.loginArgs,
|
|
893
938
|
env,
|
|
894
939
|
paths: getCodexPaths(env),
|
|
895
940
|
});
|
|
896
941
|
write(io.stdout, `logged in and saved as '${parsed.name}'`);
|
|
942
|
+
if (writeback.performed && writeback.account) {
|
|
943
|
+
await autoPushNamed(writeback.account, env, io);
|
|
944
|
+
}
|
|
945
|
+
await autoPushNamed(parsed.name, env, io);
|
|
897
946
|
return 0;
|
|
898
947
|
}
|
|
899
948
|
|
|
@@ -924,7 +973,7 @@ export async function main(
|
|
|
924
973
|
await useAccountWithRemoteFallback(parsed.account, env, io);
|
|
925
974
|
write(io.stdout, `→ codex on '${parsed.account}'`);
|
|
926
975
|
}
|
|
927
|
-
return await
|
|
976
|
+
return await runCodexAndAutoPush(parsed.codexArgs, env, io);
|
|
928
977
|
}
|
|
929
978
|
|
|
930
979
|
case 'doctor': {
|
package/src/index.ts
CHANGED
|
@@ -37,6 +37,9 @@ export {
|
|
|
37
37
|
ONEPASSWORD_AUTH_FIELD,
|
|
38
38
|
ONEPASSWORD_BACKEND,
|
|
39
39
|
REMOTE_CONFIG_VERSION,
|
|
40
|
+
REMOTE_METADATA_FIELD,
|
|
41
|
+
autoPullAccountForUse,
|
|
42
|
+
autoPushAccountIfChanged,
|
|
40
43
|
configureOnePasswordRemote,
|
|
41
44
|
getRemoteConfigPath,
|
|
42
45
|
inspectRemoteStatus,
|
|
@@ -48,6 +51,7 @@ export {
|
|
|
48
51
|
syncPullAccount,
|
|
49
52
|
syncPushAllAccounts,
|
|
50
53
|
syncPushAccount,
|
|
54
|
+
writebackAndAutoPushCurrentAccount,
|
|
51
55
|
} from './remote.js';
|
|
52
56
|
|
|
53
57
|
export type {
|
|
@@ -88,6 +92,7 @@ export type {
|
|
|
88
92
|
SetupOnePasswordProfilesResult,
|
|
89
93
|
SyncPullResult,
|
|
90
94
|
SyncPushResult,
|
|
95
|
+
SyncState,
|
|
91
96
|
SyncStatus,
|
|
92
97
|
SyncStatusAccount,
|
|
93
98
|
} from './remote.js';
|