offrouter-cli 0.2.1 → 0.3.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/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +59 -3
- package/dist/commands/login.js.map +1 -1
- package/package.json +13 -8
- package/src/catalog-cache.test.ts +0 -258
- package/src/catalog-cache.ts +0 -169
- package/src/catalog-sample.json +0 -30
- package/src/cli.test.ts +0 -1705
- package/src/commands/config-error.ts +0 -31
- package/src/commands/detection.ts +0 -209
- package/src/commands/doctor.ts +0 -555
- package/src/commands/hooks.ts +0 -125
- package/src/commands/init.ts +0 -59
- package/src/commands/install.ts +0 -438
- package/src/commands/login.test.ts +0 -247
- package/src/commands/login.ts +0 -413
- package/src/commands/mcp.ts +0 -35
- package/src/commands/models.ts +0 -168
- package/src/commands/output.ts +0 -11
- package/src/commands/profiles.ts +0 -58
- package/src/commands/proxy.ts +0 -87
- package/src/commands/route.ts +0 -190
- package/src/commands/status.ts +0 -139
- package/src/commands/update.ts +0 -62
- package/src/index.ts +0 -174
- package/tsconfig.json +0 -17
package/src/commands/update.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import type { Command } from "commander";
|
|
2
|
-
import type { CommandContext } from "./init.js";
|
|
3
|
-
import { writeJson, writeText } from "./output.js";
|
|
4
|
-
import { fetchCatalogCache } from "../catalog-cache.js";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* `offrouter update` — fetch the latest model catalog and cache it locally.
|
|
8
|
-
* No telemetry. The only network call is a GET to the public static catalog
|
|
9
|
-
* file; no user data is transmitted.
|
|
10
|
-
*/
|
|
11
|
-
export function registerUpdateCommand(
|
|
12
|
-
program: Command,
|
|
13
|
-
ctx: () => CommandContext,
|
|
14
|
-
): void {
|
|
15
|
-
program
|
|
16
|
-
.command("update")
|
|
17
|
-
.description(
|
|
18
|
-
"Fetch and cache the latest model catalog from the remote source",
|
|
19
|
-
)
|
|
20
|
-
.option("--json", "Emit JSON", false)
|
|
21
|
-
.option("--dry-run", "Fetch but do not write cache", false)
|
|
22
|
-
.action(async (opts: { json?: boolean; dryRun?: boolean }) => {
|
|
23
|
-
const { env, stdout } = ctx();
|
|
24
|
-
const dryRun = opts.dryRun ?? false;
|
|
25
|
-
|
|
26
|
-
const result = await fetchCatalogCache({
|
|
27
|
-
env,
|
|
28
|
-
dryRun,
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
const familyCount = result.data?.families.length ?? 0;
|
|
32
|
-
|
|
33
|
-
if (opts.json) {
|
|
34
|
-
writeJson(stdout, {
|
|
35
|
-
source: result.source,
|
|
36
|
-
fetchedAt: result.fetchedAt,
|
|
37
|
-
familyCount,
|
|
38
|
-
dryRun,
|
|
39
|
-
version: result.data?.version ?? null,
|
|
40
|
-
});
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (result.source === "network") {
|
|
45
|
-
const verb = dryRun ? "Fetched (dry-run, not cached)" : "Updated";
|
|
46
|
-
writeText(
|
|
47
|
-
stdout,
|
|
48
|
-
`${verb} catalog: ${familyCount} model families from remote (${result.fetchedAt})`,
|
|
49
|
-
);
|
|
50
|
-
} else if (result.source === "cache") {
|
|
51
|
-
writeText(
|
|
52
|
-
stdout,
|
|
53
|
-
`Using cached catalog: ${familyCount} model families (offline, fetched ${result.fetchedAt})`,
|
|
54
|
-
);
|
|
55
|
-
} else {
|
|
56
|
-
writeText(
|
|
57
|
-
stdout,
|
|
58
|
-
"No catalog data available. Using built-in catalog.",
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { realpathSync } from "node:fs";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { Command } from "commander";
|
|
5
|
-
import type { CommandContext } from "./commands/init.js";
|
|
6
|
-
import { registerInitCommand } from "./commands/init.js";
|
|
7
|
-
import { registerDoctorCommand } from "./commands/doctor.js";
|
|
8
|
-
import { registerLoginCommand } from "./commands/login.js";
|
|
9
|
-
import { registerModelsCommand } from "./commands/models.js";
|
|
10
|
-
import { registerProfilesCommand } from "./commands/profiles.js";
|
|
11
|
-
import { registerRouteCommand } from "./commands/route.js";
|
|
12
|
-
import { registerStatusCommand } from "./commands/status.js";
|
|
13
|
-
import { registerUpdateCommand } from "./commands/update.js";
|
|
14
|
-
import { registerMcpCommand } from "./commands/mcp.js";
|
|
15
|
-
import { registerHooksCommand } from "./commands/hooks.js";
|
|
16
|
-
import { registerProxyCommand } from "./commands/proxy.js";
|
|
17
|
-
import {
|
|
18
|
-
registerInstallCommand,
|
|
19
|
-
registerUninstallCommand,
|
|
20
|
-
} from "./commands/install.js";
|
|
21
|
-
import type { IoStreams } from "./commands/output.js";
|
|
22
|
-
|
|
23
|
-
export const CLI_PACKAGE = "offrouter-cli" as const;
|
|
24
|
-
|
|
25
|
-
export interface RunCliOptions {
|
|
26
|
-
/** Working directory for config / workspace trust. */
|
|
27
|
-
cwd?: string;
|
|
28
|
-
/** Env override (tests). */
|
|
29
|
-
env?: NodeJS.ProcessEnv;
|
|
30
|
-
/** Injected stdin for hook bridges (tests). */
|
|
31
|
-
stdin?: string;
|
|
32
|
-
stdout?: IoStreams;
|
|
33
|
-
stderr?: IoStreams;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function defaultStream(stream: NodeJS.WriteStream): IoStreams {
|
|
37
|
-
return {
|
|
38
|
-
write(chunk: string) {
|
|
39
|
-
return stream.write(chunk);
|
|
40
|
-
},
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async function readProcessStdin(): Promise<string> {
|
|
45
|
-
const chunks: Buffer[] = [];
|
|
46
|
-
for await (const chunk of process.stdin) {
|
|
47
|
-
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
48
|
-
}
|
|
49
|
-
return Buffer.concat(chunks).toString("utf8");
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Build the Commander program without parsing argv.
|
|
54
|
-
* Register commands against a shared context factory for injectable IO.
|
|
55
|
-
*/
|
|
56
|
-
export function createProgram(options: RunCliOptions = {}): Command {
|
|
57
|
-
let stdinCache: string | undefined;
|
|
58
|
-
const readStdin = async (): Promise<string> => {
|
|
59
|
-
if (options.stdin !== undefined) {
|
|
60
|
-
return options.stdin;
|
|
61
|
-
}
|
|
62
|
-
if (stdinCache !== undefined) {
|
|
63
|
-
return stdinCache;
|
|
64
|
-
}
|
|
65
|
-
stdinCache = await readProcessStdin();
|
|
66
|
-
return stdinCache;
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
const ctx = (): CommandContext => ({
|
|
70
|
-
env: options.env ?? process.env,
|
|
71
|
-
cwd: options.cwd ?? process.cwd(),
|
|
72
|
-
stdout: options.stdout ?? defaultStream(process.stdout),
|
|
73
|
-
stderr: options.stderr ?? defaultStream(process.stderr),
|
|
74
|
-
readStdin,
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
const stdout = options.stdout ?? defaultStream(process.stdout);
|
|
78
|
-
const stderr = options.stderr ?? defaultStream(process.stderr);
|
|
79
|
-
|
|
80
|
-
const program = new Command();
|
|
81
|
-
program
|
|
82
|
-
.name("offrouter")
|
|
83
|
-
.description(
|
|
84
|
-
"Local-first router for coding-agent harnesses. Claude Code's primary model is unchanged in V1; OffRouter routes delegated work.",
|
|
85
|
-
)
|
|
86
|
-
.version("0.0.0")
|
|
87
|
-
.showHelpAfterError()
|
|
88
|
-
.configureOutput({
|
|
89
|
-
writeOut: (str) => {
|
|
90
|
-
stdout.write(str);
|
|
91
|
-
},
|
|
92
|
-
writeErr: (str) => {
|
|
93
|
-
stderr.write(str);
|
|
94
|
-
},
|
|
95
|
-
})
|
|
96
|
-
.exitOverride();
|
|
97
|
-
|
|
98
|
-
registerInitCommand(program, ctx);
|
|
99
|
-
registerDoctorCommand(program, ctx);
|
|
100
|
-
registerLoginCommand(program, ctx);
|
|
101
|
-
registerModelsCommand(program, ctx);
|
|
102
|
-
registerProfilesCommand(program, ctx);
|
|
103
|
-
registerRouteCommand(program, ctx);
|
|
104
|
-
registerStatusCommand(program, ctx);
|
|
105
|
-
registerUpdateCommand(program, ctx);
|
|
106
|
-
registerMcpCommand(program, ctx);
|
|
107
|
-
registerHooksCommand(program, ctx);
|
|
108
|
-
registerProxyCommand(program, ctx);
|
|
109
|
-
registerInstallCommand(program, ctx);
|
|
110
|
-
registerUninstallCommand(program, ctx);
|
|
111
|
-
|
|
112
|
-
return program;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Parse argv (without node/script) and run the selected command.
|
|
117
|
-
* @returns process exit code (0 success, nonzero usage/runtime failure)
|
|
118
|
-
*/
|
|
119
|
-
export async function runCli(
|
|
120
|
-
argv: string[] = process.argv.slice(2),
|
|
121
|
-
options: RunCliOptions = {},
|
|
122
|
-
): Promise<number> {
|
|
123
|
-
const stderr = options.stderr ?? defaultStream(process.stderr);
|
|
124
|
-
const program = createProgram(options);
|
|
125
|
-
|
|
126
|
-
try {
|
|
127
|
-
await program.parseAsync(argv, { from: "user" });
|
|
128
|
-
return 0;
|
|
129
|
-
} catch (err) {
|
|
130
|
-
// Commander exitOverride throws CommanderError with exitCode.
|
|
131
|
-
if (
|
|
132
|
-
err &&
|
|
133
|
-
typeof err === "object" &&
|
|
134
|
-
"exitCode" in err &&
|
|
135
|
-
typeof (err as { exitCode: unknown }).exitCode === "number"
|
|
136
|
-
) {
|
|
137
|
-
const code = (
|
|
138
|
-
err as { exitCode: number; message?: string; code?: string }
|
|
139
|
-
).exitCode;
|
|
140
|
-
// help/version use exitCode 0
|
|
141
|
-
if (code === 0) {
|
|
142
|
-
return 0;
|
|
143
|
-
}
|
|
144
|
-
const message = err instanceof Error ? err.message : "Command failed";
|
|
145
|
-
if (message) {
|
|
146
|
-
stderr.write(`${message}\n`);
|
|
147
|
-
}
|
|
148
|
-
return code || 1;
|
|
149
|
-
}
|
|
150
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
151
|
-
stderr.write(`${message}\n`);
|
|
152
|
-
return 1;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function isEntrypoint(): boolean {
|
|
157
|
-
if (!process.argv[1]) {
|
|
158
|
-
return false;
|
|
159
|
-
}
|
|
160
|
-
try {
|
|
161
|
-
return (
|
|
162
|
-
realpathSync(process.argv[1]) ===
|
|
163
|
-
realpathSync(fileURLToPath(import.meta.url))
|
|
164
|
-
);
|
|
165
|
-
} catch {
|
|
166
|
-
return false;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (isEntrypoint()) {
|
|
171
|
-
void runCli(process.argv.slice(2)).then((code) => {
|
|
172
|
-
process.exitCode = code;
|
|
173
|
-
});
|
|
174
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "../../tsconfig.base.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"rootDir": "src",
|
|
5
|
-
"outDir": "dist"
|
|
6
|
-
},
|
|
7
|
-
"include": ["src/**/*.ts"],
|
|
8
|
-
"exclude": ["src/**/*.test.ts"],
|
|
9
|
-
"references": [
|
|
10
|
-
{ "path": "../core" },
|
|
11
|
-
{ "path": "../adapter-claude" },
|
|
12
|
-
{ "path": "../adapter-codex" },
|
|
13
|
-
{ "path": "../adapter-gemini" },
|
|
14
|
-
{ "path": "../adapter-grok" },
|
|
15
|
-
{ "path": "../mcp" }
|
|
16
|
-
]
|
|
17
|
-
}
|