@curatedmcp/tokenshield 0.2.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.
Files changed (55) hide show
  1. package/dist/cli.d.ts +2 -0
  2. package/dist/cli.js +238 -0
  3. package/dist/cli.js.map +1 -0
  4. package/dist/commands/bench.d.ts +5 -0
  5. package/dist/commands/bench.js +191 -0
  6. package/dist/commands/bench.js.map +1 -0
  7. package/dist/commands/demo.d.ts +3 -0
  8. package/dist/commands/demo.js +99 -0
  9. package/dist/commands/demo.js.map +1 -0
  10. package/dist/commands/doctor.d.ts +1 -0
  11. package/dist/commands/doctor.js +119 -0
  12. package/dist/commands/doctor.js.map +1 -0
  13. package/dist/commands/estimate.d.ts +3 -0
  14. package/dist/commands/estimate.js +90 -0
  15. package/dist/commands/estimate.js.map +1 -0
  16. package/dist/commands/integrations.d.ts +14 -0
  17. package/dist/commands/integrations.js +138 -0
  18. package/dist/commands/integrations.js.map +1 -0
  19. package/dist/commands/logs.d.ts +6 -0
  20. package/dist/commands/logs.js +66 -0
  21. package/dist/commands/logs.js.map +1 -0
  22. package/dist/commands/setup.d.ts +9 -0
  23. package/dist/commands/setup.js +159 -0
  24. package/dist/commands/setup.js.map +1 -0
  25. package/dist/commands/status.d.ts +1 -0
  26. package/dist/commands/status.js +102 -0
  27. package/dist/commands/status.js.map +1 -0
  28. package/dist/commands/stop.d.ts +1 -0
  29. package/dist/commands/stop.js +27 -0
  30. package/dist/commands/stop.js.map +1 -0
  31. package/dist/commands/up.d.ts +15 -0
  32. package/dist/commands/up.js +145 -0
  33. package/dist/commands/up.js.map +1 -0
  34. package/dist/dashboard.d.ts +4 -0
  35. package/dist/dashboard.js +186 -0
  36. package/dist/dashboard.js.map +1 -0
  37. package/dist/lib/daemon.d.ts +23 -0
  38. package/dist/lib/daemon.js +164 -0
  39. package/dist/lib/daemon.js.map +1 -0
  40. package/dist/lib/errors.d.ts +23 -0
  41. package/dist/lib/errors.js +131 -0
  42. package/dist/lib/errors.js.map +1 -0
  43. package/dist/lib/integrations.d.ts +47 -0
  44. package/dist/lib/integrations.js +210 -0
  45. package/dist/lib/integrations.js.map +1 -0
  46. package/dist/lib/paths.d.ts +5 -0
  47. package/dist/lib/paths.js +18 -0
  48. package/dist/lib/paths.js.map +1 -0
  49. package/dist/lib/preflight.d.ts +20 -0
  50. package/dist/lib/preflight.js +97 -0
  51. package/dist/lib/preflight.js.map +1 -0
  52. package/dist/lib/ui.d.ts +68 -0
  53. package/dist/lib/ui.js +221 -0
  54. package/dist/lib/ui.js.map +1 -0
  55. package/package.json +44 -0
@@ -0,0 +1,164 @@
1
+ import { spawn } from "node:child_process";
2
+ import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync, openSync } from "node:fs";
3
+ import { dirname } from "node:path";
4
+ import { pidFile, logFile, tokenshieldHome } from "./paths.js";
5
+ import { TokenShieldError } from "./errors.js";
6
+ function isAliveSync(pid) {
7
+ if (!Number.isFinite(pid) || pid <= 0)
8
+ return false;
9
+ try {
10
+ process.kill(pid, 0);
11
+ return true;
12
+ }
13
+ catch (err) {
14
+ const e = err;
15
+ if (e.code === "EPERM")
16
+ return true; // exists but no permission to signal
17
+ return false;
18
+ }
19
+ }
20
+ export function readDaemon() {
21
+ const path = pidFile();
22
+ if (!existsSync(path))
23
+ return null;
24
+ try {
25
+ const raw = readFileSync(path, "utf8");
26
+ const data = JSON.parse(raw);
27
+ if (!isAliveSync(data.pid)) {
28
+ // stale pid file
29
+ try {
30
+ unlinkSync(path);
31
+ }
32
+ catch { /* ignore */ }
33
+ return null;
34
+ }
35
+ return data;
36
+ }
37
+ catch {
38
+ try {
39
+ unlinkSync(path);
40
+ }
41
+ catch { /* ignore */ }
42
+ return null;
43
+ }
44
+ }
45
+ export function writeDaemon(info) {
46
+ mkdirSync(dirname(pidFile()), { recursive: true });
47
+ writeFileSync(pidFile(), JSON.stringify(info, null, 2));
48
+ }
49
+ export function clearDaemon() {
50
+ try {
51
+ unlinkSync(pidFile());
52
+ }
53
+ catch { /* ignore */ }
54
+ }
55
+ /** Spawn the proxy as a detached background process and return its DaemonInfo. */
56
+ export async function spawnDaemon(opts) {
57
+ if (process.platform === "win32") {
58
+ throw new TokenShieldError({
59
+ code: "INVALID_ARGUMENT",
60
+ message: "Daemon mode is not yet supported on Windows",
61
+ hint: "Run `tokenshield up` in a dedicated terminal (use Windows Terminal tabs)",
62
+ });
63
+ }
64
+ const existing = readDaemon();
65
+ if (existing !== null) {
66
+ throw new TokenShieldError({
67
+ code: "DAEMON_ALREADY_RUNNING",
68
+ message: `TokenShield is already running (pid ${existing.pid}, port ${existing.port})`,
69
+ hint: "Stop it first or attach to the existing dashboard.",
70
+ nextSteps: ["tokenshield stop", `open http://${existing.bind}:${existing.dashboardPort}`],
71
+ });
72
+ }
73
+ mkdirSync(tokenshieldHome(), { recursive: true });
74
+ const logFd = openSync(logFile(), "a");
75
+ const args = [
76
+ process.argv[1],
77
+ "__supervise",
78
+ "--port", String(opts.port),
79
+ "--dashboard-port", String(opts.dashboardPort),
80
+ "--bind", opts.bind,
81
+ "--upstream", opts.upstream,
82
+ "--ledger", opts.ledger,
83
+ "--retention-days", String(opts.retentionDays),
84
+ ];
85
+ const child = spawn(process.execPath, args, {
86
+ detached: true,
87
+ stdio: ["ignore", logFd, logFd],
88
+ env: { ...process.env, TOKENSHIELD_DAEMON: "1" },
89
+ });
90
+ if (typeof child.pid !== "number") {
91
+ throw new TokenShieldError({ code: "INTERNAL", message: "Failed to start daemon process" });
92
+ }
93
+ child.unref();
94
+ const info = {
95
+ pid: child.pid,
96
+ startedAt: Date.now(),
97
+ port: opts.port,
98
+ dashboardPort: opts.dashboardPort,
99
+ bind: opts.bind,
100
+ };
101
+ writeDaemon(info);
102
+ // Wait briefly for the proxy to be reachable so the user gets a real ready signal
103
+ const ok = await waitFor(() => isProxyReady(info), 4000);
104
+ if (!ok) {
105
+ // Daemon spawned but isn't responding — keep the pid file so `stop` works
106
+ throw new TokenShieldError({
107
+ code: "INTERNAL",
108
+ message: `Daemon started (pid ${info.pid}) but proxy isn't responding on port ${info.port}`,
109
+ hint: `Check the log at ${logFile()}`,
110
+ nextSteps: [`tail -n 100 ${logFile()}`, "tokenshield stop"],
111
+ });
112
+ }
113
+ return info;
114
+ }
115
+ export async function stopDaemon(timeoutMs = 8000) {
116
+ const info = readDaemon();
117
+ if (info === null)
118
+ return null;
119
+ try {
120
+ process.kill(info.pid, "SIGTERM");
121
+ }
122
+ catch {
123
+ clearDaemon();
124
+ return info;
125
+ }
126
+ const stopped = await waitFor(() => !isAliveSync(info.pid), timeoutMs);
127
+ if (!stopped) {
128
+ try {
129
+ process.kill(info.pid, "SIGKILL");
130
+ }
131
+ catch { /* ignore */ }
132
+ }
133
+ clearDaemon();
134
+ return info;
135
+ }
136
+ import { request as httpRequest } from "node:http";
137
+ function isProxyReady(info) {
138
+ return new Promise((resolve) => {
139
+ const req = httpRequest({
140
+ host: info.bind,
141
+ port: info.port,
142
+ path: "/__tokenshield/health",
143
+ method: "GET",
144
+ timeout: 1000,
145
+ }, (res) => {
146
+ res.resume();
147
+ resolve((res.statusCode ?? 0) === 200);
148
+ });
149
+ req.on("error", () => resolve(false));
150
+ req.on("timeout", () => { req.destroy(); resolve(false); });
151
+ req.end();
152
+ });
153
+ }
154
+ async function waitFor(check, timeoutMs) {
155
+ const deadline = Date.now() + timeoutMs;
156
+ while (Date.now() < deadline) {
157
+ if (await check())
158
+ return true;
159
+ await new Promise((r) => setTimeout(r, 150));
160
+ }
161
+ return false;
162
+ }
163
+ export { isAliveSync };
164
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../src/lib/daemon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ export type ErrorCode = "PORT_IN_USE" | "DAEMON_NOT_RUNNING" | "DAEMON_ALREADY_RUNNING" | "MISSING_API_KEY" | "BAD_API_KEY" | "UPSTREAM_UNREACHABLE" | "BAD_CONFIG" | "INVALID_ARGUMENT" | "PERMISSION_DENIED" | "NOT_FOUND" | "INTERRUPTED" | "INTERNAL";
2
+ export declare class TokenShieldError extends Error {
3
+ readonly code: ErrorCode;
4
+ readonly hint: string | undefined;
5
+ readonly nextSteps: string[];
6
+ readonly cause?: unknown;
7
+ constructor(opts: {
8
+ code: ErrorCode;
9
+ message: string;
10
+ hint?: string;
11
+ nextSteps?: string[];
12
+ cause?: unknown;
13
+ });
14
+ }
15
+ export declare function exitCodeFor(err: unknown): number;
16
+ export declare function reportAndExit(err: unknown): never;
17
+ /**
18
+ * Wrap an async command body so any thrown error is reported uniformly.
19
+ * Always exits with the correct code; never returns.
20
+ */
21
+ export declare function runCommand<T>(fn: () => Promise<T> | T): Promise<void>;
22
+ export declare function ensureNumber(name: string, raw: unknown, min?: number, max?: number): number;
23
+ export declare function installProcessHandlers(): void;
@@ -0,0 +1,131 @@
1
+ import { c, errorLine, isDebug, isJson, emitJson, say } from "./ui.js";
2
+ const EXIT_CODES = {
3
+ PORT_IN_USE: 10,
4
+ DAEMON_NOT_RUNNING: 11,
5
+ DAEMON_ALREADY_RUNNING: 12,
6
+ MISSING_API_KEY: 20,
7
+ BAD_API_KEY: 21,
8
+ UPSTREAM_UNREACHABLE: 30,
9
+ BAD_CONFIG: 40,
10
+ INVALID_ARGUMENT: 41,
11
+ PERMISSION_DENIED: 50,
12
+ NOT_FOUND: 51,
13
+ INTERRUPTED: 130,
14
+ INTERNAL: 1,
15
+ };
16
+ export class TokenShieldError extends Error {
17
+ code;
18
+ hint;
19
+ nextSteps;
20
+ cause;
21
+ constructor(opts) {
22
+ super(opts.message);
23
+ this.name = "TokenShieldError";
24
+ this.code = opts.code;
25
+ this.hint = opts.hint;
26
+ this.nextSteps = opts.nextSteps ?? [];
27
+ if (opts.cause !== undefined)
28
+ this.cause = opts.cause;
29
+ }
30
+ }
31
+ export function exitCodeFor(err) {
32
+ if (err instanceof TokenShieldError)
33
+ return EXIT_CODES[err.code] ?? 1;
34
+ return 1;
35
+ }
36
+ export function reportAndExit(err) {
37
+ if (isJson()) {
38
+ if (err instanceof TokenShieldError) {
39
+ emitJson({
40
+ ok: false,
41
+ error: {
42
+ code: err.code,
43
+ message: err.message,
44
+ hint: err.hint,
45
+ nextSteps: err.nextSteps,
46
+ },
47
+ });
48
+ }
49
+ else if (err instanceof Error) {
50
+ emitJson({
51
+ ok: false,
52
+ error: { code: "INTERNAL", message: err.message },
53
+ });
54
+ }
55
+ else {
56
+ emitJson({ ok: false, error: { code: "INTERNAL", message: String(err) } });
57
+ }
58
+ process.exit(exitCodeFor(err));
59
+ }
60
+ if (err instanceof TokenShieldError) {
61
+ errorLine(err.message);
62
+ if (err.hint) {
63
+ process.stderr.write(` ${c.gray("→")} ${c.gray(err.hint)}\n`);
64
+ }
65
+ if (err.nextSteps.length > 0) {
66
+ process.stderr.write("\n " + c.bold("Try:") + "\n");
67
+ for (const step of err.nextSteps) {
68
+ process.stderr.write(` ${c.gray("$")} ${c.cyan(step)}\n`);
69
+ }
70
+ process.stderr.write("\n");
71
+ }
72
+ if (isDebug() && err.cause) {
73
+ process.stderr.write(c.gray("[debug] cause:\n"));
74
+ process.stderr.write(c.gray(String(err.cause)) + "\n");
75
+ }
76
+ }
77
+ else if (err instanceof Error) {
78
+ errorLine(err.message);
79
+ if (isDebug() && err.stack) {
80
+ process.stderr.write(c.gray(err.stack) + "\n");
81
+ }
82
+ else {
83
+ process.stderr.write(c.gray(" → run with --debug for stack trace\n"));
84
+ }
85
+ }
86
+ else {
87
+ errorLine(String(err));
88
+ }
89
+ process.exit(exitCodeFor(err));
90
+ }
91
+ /**
92
+ * Wrap an async command body so any thrown error is reported uniformly.
93
+ * Always exits with the correct code; never returns.
94
+ */
95
+ export async function runCommand(fn) {
96
+ try {
97
+ await fn();
98
+ }
99
+ catch (err) {
100
+ reportAndExit(err);
101
+ }
102
+ }
103
+ export function ensureNumber(name, raw, min = 1, max = 65535) {
104
+ const n = typeof raw === "string" ? parseInt(raw, 10) : raw;
105
+ if (!Number.isFinite(n) || Number.isNaN(n) || n < min || n > max) {
106
+ throw new TokenShieldError({
107
+ code: "INVALID_ARGUMENT",
108
+ message: `Invalid value for ${name}: expected an integer between ${min} and ${max}, got ${String(raw)}`,
109
+ hint: `Pass --${name} <number>`,
110
+ });
111
+ }
112
+ return n;
113
+ }
114
+ // Install handlers for unhandled rejections / uncaught exceptions
115
+ let installed = false;
116
+ export function installProcessHandlers() {
117
+ if (installed)
118
+ return;
119
+ installed = true;
120
+ process.on("uncaughtException", (err) => {
121
+ reportAndExit(err);
122
+ });
123
+ process.on("unhandledRejection", (err) => {
124
+ reportAndExit(err);
125
+ });
126
+ process.on("SIGINT", () => {
127
+ say("");
128
+ process.exit(EXIT_CODES.INTERRUPTED);
129
+ });
130
+ }
131
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ export type IntegrationId = "claude-code" | "cursor" | "windsurf" | "zed" | "aider";
2
+ export type IntegrationStatus = "detected" | "not-found" | "unknown";
3
+ export type ConfigureMethod = "shell-rc" | "manual-snippet";
4
+ export interface Integration {
5
+ id: IntegrationId;
6
+ name: string;
7
+ status: IntegrationStatus;
8
+ detail: string;
9
+ /**
10
+ * How TokenShield can configure this tool:
11
+ * - "shell-rc": write to the user's shell rc file (Claude Code, Aider, etc.)
12
+ * - "manual-snippet": print a config snippet for the user to paste (Cursor, Windsurf, Zed)
13
+ */
14
+ configureMethod: ConfigureMethod;
15
+ /** A short instruction body shown when configuring this tool. */
16
+ instructions: string;
17
+ }
18
+ export declare function detectAll(): Integration[];
19
+ export declare function detectClaudeCode(): Integration;
20
+ export declare function detectCursor(): Integration;
21
+ export declare function detectWindsurf(): Integration;
22
+ export declare function detectZed(): Integration;
23
+ export declare function detectAider(): Integration;
24
+ export interface ShellInfo {
25
+ shell: "bash" | "zsh" | "fish" | "unknown";
26
+ rcPath: string | null;
27
+ exportLine: (key: string, value: string) => string;
28
+ }
29
+ export declare function detectShell(): ShellInfo;
30
+ export interface ConfigureParams {
31
+ baseUrl: string;
32
+ }
33
+ export interface ShellRcResult {
34
+ rcPath: string;
35
+ shell: ShellInfo["shell"];
36
+ action: "added" | "updated" | "unchanged";
37
+ block: string;
38
+ }
39
+ /** Idempotently writes a managed marker block to the user's shell rc. */
40
+ export declare function writeShellRc(params: ConfigureParams): ShellRcResult;
41
+ export interface ShellRcRemoveResult {
42
+ rcPath: string | null;
43
+ removed: boolean;
44
+ }
45
+ export declare function removeShellRc(): ShellRcRemoveResult;
46
+ /** Snippet body for tools we don't auto-configure. */
47
+ export declare function manualSnippet(id: IntegrationId, baseUrl: string): string;
@@ -0,0 +1,210 @@
1
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
2
+ import { homedir as osHomedir, platform } from "node:os";
3
+ function homedir() {
4
+ // Prefer $HOME so tests can override; matches POSIX shell behavior anyway
5
+ return process.env["HOME"] ?? process.env["USERPROFILE"] ?? osHomedir();
6
+ }
7
+ import { join, dirname } from "node:path";
8
+ import { execSync } from "node:child_process";
9
+ const MARKER_BEGIN = "# >>> tokenshield setup (managed) >>>";
10
+ const MARKER_END = "# <<< tokenshield setup (managed) <<<";
11
+ function exists(path) {
12
+ try {
13
+ return existsSync(path);
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ }
19
+ function commandExists(cmd) {
20
+ try {
21
+ execSync(process.platform === "win32" ? `where ${cmd}` : `command -v ${cmd}`, {
22
+ stdio: "ignore",
23
+ });
24
+ return true;
25
+ }
26
+ catch {
27
+ return false;
28
+ }
29
+ }
30
+ function appSupport() {
31
+ const home = homedir();
32
+ if (platform() === "darwin")
33
+ return join(home, "Library", "Application Support");
34
+ if (platform() === "linux")
35
+ return join(home, ".config");
36
+ if (platform() === "win32")
37
+ return process.env["APPDATA"] ?? null;
38
+ return null;
39
+ }
40
+ export function detectAll() {
41
+ return [
42
+ detectClaudeCode(),
43
+ detectCursor(),
44
+ detectWindsurf(),
45
+ detectZed(),
46
+ detectAider(),
47
+ ];
48
+ }
49
+ export function detectClaudeCode() {
50
+ const onPath = commandExists("claude");
51
+ const dotDir = exists(join(homedir(), ".claude"));
52
+ const status = onPath || dotDir ? "detected" : "not-found";
53
+ return {
54
+ id: "claude-code",
55
+ name: "Claude Code",
56
+ status,
57
+ detail: onPath
58
+ ? "claude found on PATH"
59
+ : dotDir
60
+ ? `config dir at ${join(homedir(), ".claude")}`
61
+ : "not found (install: npm i -g @anthropic-ai/claude-code)",
62
+ configureMethod: "shell-rc",
63
+ instructions: "Adds ANTHROPIC_BASE_URL to your shell rc so Claude Code routes through TokenShield. Reload your shell after.",
64
+ };
65
+ }
66
+ export function detectCursor() {
67
+ const support = appSupport();
68
+ const cursorDir = support !== null ? join(support, "Cursor") : null;
69
+ const detected = cursorDir !== null && (exists(cursorDir) || exists(join(cursorDir, "User", "settings.json")));
70
+ return {
71
+ id: "cursor",
72
+ name: "Cursor",
73
+ status: detected ? "detected" : "not-found",
74
+ detail: detected ? `config at ${cursorDir}` : "not found",
75
+ configureMethod: "manual-snippet",
76
+ instructions: "Open Cursor → Settings → Models. Under 'Anthropic API Base URL' (or 'Override OpenAI Base URL' for GPT), paste the snippet below and click Verify.",
77
+ };
78
+ }
79
+ export function detectWindsurf() {
80
+ const support = appSupport();
81
+ const dir = support !== null ? join(support, "Windsurf") : null;
82
+ const detected = dir !== null && exists(dir);
83
+ return {
84
+ id: "windsurf",
85
+ name: "Windsurf",
86
+ status: detected ? "detected" : "not-found",
87
+ detail: detected ? `config at ${dir}` : "not found",
88
+ configureMethod: "manual-snippet",
89
+ instructions: "Open Windsurf → Settings → Models. Set the custom Anthropic endpoint to the snippet below.",
90
+ };
91
+ }
92
+ export function detectZed() {
93
+ const support = appSupport();
94
+ const dir = support !== null ? join(support, "Zed") : null;
95
+ const detected = dir !== null && exists(dir);
96
+ return {
97
+ id: "zed",
98
+ name: "Zed",
99
+ status: detected ? "detected" : "not-found",
100
+ detail: detected ? `config at ${dir}` : "not found",
101
+ configureMethod: "manual-snippet",
102
+ instructions: "Edit ~/.config/zed/settings.json and add the assistant.anthropic_api_url key.",
103
+ };
104
+ }
105
+ export function detectAider() {
106
+ const onPath = commandExists("aider");
107
+ return {
108
+ id: "aider",
109
+ name: "Aider",
110
+ status: onPath ? "detected" : "not-found",
111
+ detail: onPath ? "aider found on PATH" : "not found",
112
+ configureMethod: "shell-rc",
113
+ instructions: "Adds ANTHROPIC_BASE_URL to your shell rc. Aider's Anthropic mode will route through TokenShield automatically.",
114
+ };
115
+ }
116
+ export function detectShell() {
117
+ const shellEnv = process.env["SHELL"] ?? "";
118
+ const base = shellEnv.split("/").pop() ?? "";
119
+ const home = homedir();
120
+ if (base === "zsh") {
121
+ return {
122
+ shell: "zsh",
123
+ rcPath: join(home, ".zshrc"),
124
+ exportLine: (k, v) => `export ${k}=${v}`,
125
+ };
126
+ }
127
+ if (base === "bash") {
128
+ // macOS terminals usually read .bash_profile for login shells; linux reads .bashrc
129
+ const rc = platform() === "darwin" ? join(home, ".bash_profile") : join(home, ".bashrc");
130
+ return {
131
+ shell: "bash",
132
+ rcPath: rc,
133
+ exportLine: (k, v) => `export ${k}=${v}`,
134
+ };
135
+ }
136
+ if (base === "fish") {
137
+ return {
138
+ shell: "fish",
139
+ rcPath: join(home, ".config", "fish", "config.fish"),
140
+ exportLine: (k, v) => `set -gx ${k} ${v}`,
141
+ };
142
+ }
143
+ return { shell: "unknown", rcPath: null, exportLine: (k, v) => `export ${k}=${v}` };
144
+ }
145
+ /** Idempotently writes a managed marker block to the user's shell rc. */
146
+ export function writeShellRc(params) {
147
+ const shell = detectShell();
148
+ if (shell.rcPath === null) {
149
+ throw new Error("Unknown shell — set ANTHROPIC_BASE_URL manually in your shell's startup file.");
150
+ }
151
+ const exportLine = shell.exportLine("ANTHROPIC_BASE_URL", params.baseUrl);
152
+ const block = `${MARKER_BEGIN}\n${exportLine}\n${MARKER_END}`;
153
+ if (!exists(shell.rcPath)) {
154
+ mkdirSync(dirname(shell.rcPath), { recursive: true });
155
+ writeFileSync(shell.rcPath, block + "\n", { mode: 0o600 });
156
+ return { rcPath: shell.rcPath, shell: shell.shell, action: "added", block };
157
+ }
158
+ const current = readFileSync(shell.rcPath, "utf8");
159
+ const beginIdx = current.indexOf(MARKER_BEGIN);
160
+ if (beginIdx === -1) {
161
+ const sep = current.endsWith("\n") ? "" : "\n";
162
+ writeFileSync(shell.rcPath, current + sep + "\n" + block + "\n");
163
+ return { rcPath: shell.rcPath, shell: shell.shell, action: "added", block };
164
+ }
165
+ const endIdx = current.indexOf(MARKER_END, beginIdx);
166
+ if (endIdx === -1) {
167
+ throw new Error(`${shell.rcPath} contains an unclosed tokenshield marker. Edit manually and remove it.`);
168
+ }
169
+ const before = current.slice(0, beginIdx);
170
+ const after = current.slice(endIdx + MARKER_END.length);
171
+ // Detect no-op rewrite
172
+ const oldBlock = current.slice(beginIdx, endIdx + MARKER_END.length);
173
+ if (oldBlock === block) {
174
+ return { rcPath: shell.rcPath, shell: shell.shell, action: "unchanged", block };
175
+ }
176
+ writeFileSync(shell.rcPath, before + block + after);
177
+ return { rcPath: shell.rcPath, shell: shell.shell, action: "updated", block };
178
+ }
179
+ export function removeShellRc() {
180
+ const shell = detectShell();
181
+ if (shell.rcPath === null || !exists(shell.rcPath)) {
182
+ return { rcPath: shell.rcPath, removed: false };
183
+ }
184
+ const current = readFileSync(shell.rcPath, "utf8");
185
+ const beginIdx = current.indexOf(MARKER_BEGIN);
186
+ if (beginIdx === -1)
187
+ return { rcPath: shell.rcPath, removed: false };
188
+ const endIdx = current.indexOf(MARKER_END, beginIdx);
189
+ if (endIdx === -1)
190
+ return { rcPath: shell.rcPath, removed: false };
191
+ // Also strip the leading newline if present
192
+ let cleaned = current.slice(0, beginIdx) + current.slice(endIdx + MARKER_END.length);
193
+ cleaned = cleaned.replace(/\n{3,}/g, "\n\n");
194
+ writeFileSync(shell.rcPath, cleaned);
195
+ return { rcPath: shell.rcPath, removed: true };
196
+ }
197
+ /** Snippet body for tools we don't auto-configure. */
198
+ export function manualSnippet(id, baseUrl) {
199
+ switch (id) {
200
+ case "cursor":
201
+ return `Anthropic API Base URL: ${baseUrl}\n(Settings → Models → expand Anthropic provider → Override base URL)`;
202
+ case "windsurf":
203
+ return `Anthropic endpoint: ${baseUrl}\n(Settings → Models → Anthropic → Custom endpoint)`;
204
+ case "zed":
205
+ return `Edit ~/.config/zed/settings.json:\n{\n "assistant": {\n "provider": "anthropic",\n "anthropic_api_url": "${baseUrl}"\n }\n}`;
206
+ default:
207
+ return `Set ANTHROPIC_BASE_URL=${baseUrl} in this app's settings or shell.`;
208
+ }
209
+ }
210
+ //# sourceMappingURL=integrations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrations.js","sourceRoot":"","sources":["../../src/lib/integrations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function tokenshieldHome(): string;
2
+ export declare function pidFile(): string;
3
+ export declare function logFile(): string;
4
+ export declare function ledgerPath(): string;
5
+ export declare function configFile(): string;
@@ -0,0 +1,18 @@
1
+ import { homedir } from "node:os";
2
+ import { join } from "node:path";
3
+ export function tokenshieldHome() {
4
+ return process.env["TOKENSHIELD_HOME"] ?? join(homedir(), ".tokenshield");
5
+ }
6
+ export function pidFile() {
7
+ return join(tokenshieldHome(), "proxy.pid");
8
+ }
9
+ export function logFile() {
10
+ return join(tokenshieldHome(), "proxy.log");
11
+ }
12
+ export function ledgerPath() {
13
+ return join(tokenshieldHome(), "ledger.db");
14
+ }
15
+ export function configFile() {
16
+ return join(tokenshieldHome(), "config.json");
17
+ }
18
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,eAAe;IAC7B,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;AAC5E,CAAC;AACD,MAAM,UAAU,OAAO;IACrB,OAAO,IAAI,CAAC,eAAe,EAAE,EAAE,WAAW,CAAC,CAAC;AAC9C,CAAC;AACD,MAAM,UAAU,OAAO;IACrB,OAAO,IAAI,CAAC,eAAe,EAAE,EAAE,WAAW,CAAC,CAAC;AAC9C,CAAC;AACD,MAAM,UAAU,UAAU;IACxB,OAAO,IAAI,CAAC,eAAe,EAAE,EAAE,WAAW,CAAC,CAAC;AAC9C,CAAC;AACD,MAAM,UAAU,UAAU;IACxB,OAAO,IAAI,CAAC,eAAe,EAAE,EAAE,aAAa,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,20 @@
1
+ export interface PortStatus {
2
+ port: number;
3
+ available: boolean;
4
+ detail?: string;
5
+ }
6
+ export declare function checkPort(port: number, host?: string): Promise<PortStatus>;
7
+ export interface UpstreamProbe {
8
+ url: string;
9
+ reachable: boolean;
10
+ latencyMs?: number;
11
+ status?: number;
12
+ detail?: string;
13
+ }
14
+ export declare function probeUpstream(baseUrl: string, timeoutMs?: number): Promise<UpstreamProbe>;
15
+ export declare function classifyApiKey(value: string | undefined): {
16
+ state: "missing" | "wrong_prefix" | "ok";
17
+ hint?: string;
18
+ };
19
+ /** Throws a structured error if the port is in use. */
20
+ export declare function requirePortFree(port: number, label: string): Promise<void>;