anthropic-gateway 1.0.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.
@@ -0,0 +1,169 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.loadConfig = loadConfig;
37
+ exports.saveConfig = saveConfig;
38
+ exports.ensureProxyAuthToken = ensureProxyAuthToken;
39
+ exports.preserveProxyAuthToken = preserveProxyAuthToken;
40
+ exports.configExists = configExists;
41
+ exports.getConfigDir = getConfigDir;
42
+ exports.updateClaudeJson = updateClaudeJson;
43
+ exports.updateClaudeSettings = updateClaudeSettings;
44
+ exports.getClaudePaths = getClaudePaths;
45
+ // Configuration file management utilities
46
+ const fs = __importStar(require("fs"));
47
+ const path = __importStar(require("path"));
48
+ const os = __importStar(require("os"));
49
+ const crypto_1 = require("crypto");
50
+ const fileStorage_1 = require("./fileStorage");
51
+ const CONFIG_DIR = path.join(os.homedir(), '.claude-adapter');
52
+ const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
53
+ /**
54
+ * Load configuration from ~/.claude-adapter/config.json
55
+ */
56
+ function loadConfig() {
57
+ try {
58
+ if (!fs.existsSync(CONFIG_FILE)) {
59
+ return null;
60
+ }
61
+ (0, fileStorage_1.ensureDirExists)(CONFIG_DIR);
62
+ (0, fileStorage_1.hardenPrivateFile)(CONFIG_FILE);
63
+ const content = fs.readFileSync(CONFIG_FILE, 'utf-8');
64
+ return JSON.parse(content);
65
+ }
66
+ catch {
67
+ return null;
68
+ }
69
+ }
70
+ /**
71
+ * Save configuration to ~/.claude-adapter/config.json
72
+ */
73
+ function saveConfig(config) {
74
+ (0, fileStorage_1.ensureDirExists)(CONFIG_DIR);
75
+ (0, fileStorage_1.writePrivateJsonFile)(CONFIG_FILE, config);
76
+ }
77
+ /**
78
+ * Add the proxy credential required by current versions to a legacy config.
79
+ * The value is generated once and then preserved through reconfiguration.
80
+ */
81
+ function ensureProxyAuthToken(config) {
82
+ if (typeof config.proxyAuthToken === 'string' && config.proxyAuthToken.trim().length > 0) {
83
+ return config;
84
+ }
85
+ const migratedConfig = {
86
+ ...config,
87
+ proxyAuthToken: (0, crypto_1.randomBytes)(32).toString('base64url'),
88
+ };
89
+ saveConfig(migratedConfig);
90
+ return migratedConfig;
91
+ }
92
+ /** Preserve the existing proxy token when the provider configuration changes. */
93
+ function preserveProxyAuthToken(nextConfig, previousConfig) {
94
+ return previousConfig?.proxyAuthToken
95
+ ? { ...nextConfig, proxyAuthToken: previousConfig.proxyAuthToken }
96
+ : nextConfig;
97
+ }
98
+ /**
99
+ * Check if configuration exists
100
+ */
101
+ function configExists() {
102
+ return fs.existsSync(CONFIG_FILE);
103
+ }
104
+ /**
105
+ * Get the config directory path
106
+ */
107
+ function getConfigDir() {
108
+ return CONFIG_DIR;
109
+ }
110
+ // Claude settings file paths
111
+ const CLAUDE_JSON_PATH = path.join(os.homedir(), '.claude.json');
112
+ const CLAUDE_SETTINGS_DIR = path.join(os.homedir(), '.claude');
113
+ const CLAUDE_SETTINGS_PATH = path.join(CLAUDE_SETTINGS_DIR, 'settings.json');
114
+ /**
115
+ * Update ~/.claude.json to set hasCompletedOnboarding
116
+ */
117
+ function updateClaudeJson() {
118
+ let claudeJson = {};
119
+ try {
120
+ if (fs.existsSync(CLAUDE_JSON_PATH)) {
121
+ const content = fs.readFileSync(CLAUDE_JSON_PATH, 'utf-8');
122
+ claudeJson = JSON.parse(content);
123
+ }
124
+ }
125
+ catch {
126
+ // Start fresh if file is corrupted
127
+ claudeJson = {};
128
+ }
129
+ claudeJson.hasCompletedOnboarding = true;
130
+ // Do not change permissions on the user's entire home directory.
131
+ (0, fileStorage_1.writePrivateJsonFile)(CLAUDE_JSON_PATH, claudeJson, false);
132
+ }
133
+ /**
134
+ * Update ~/.claude/settings.json with proxy environment variables
135
+ */
136
+ function updateClaudeSettings(proxyUrl, models, proxyAuthToken) {
137
+ (0, fileStorage_1.ensureDirExists)(CLAUDE_SETTINGS_DIR);
138
+ let settings = {};
139
+ try {
140
+ if (fs.existsSync(CLAUDE_SETTINGS_PATH)) {
141
+ const content = fs.readFileSync(CLAUDE_SETTINGS_PATH, 'utf-8');
142
+ settings = JSON.parse(content);
143
+ }
144
+ }
145
+ catch {
146
+ // Start fresh if file is corrupted
147
+ settings = {};
148
+ }
149
+ // Merge env settings
150
+ settings.env = {
151
+ ...(settings.env || {}),
152
+ ANTHROPIC_BASE_URL: proxyUrl,
153
+ ANTHROPIC_AUTH_TOKEN: proxyAuthToken,
154
+ ANTHROPIC_DEFAULT_OPUS_MODEL: models.opus,
155
+ ANTHROPIC_DEFAULT_SONNET_MODEL: models.sonnet,
156
+ ANTHROPIC_DEFAULT_HAIKU_MODEL: models.haiku,
157
+ };
158
+ (0, fileStorage_1.writePrivateJsonFile)(CLAUDE_SETTINGS_PATH, settings);
159
+ }
160
+ /**
161
+ * Get paths for display purposes
162
+ */
163
+ function getClaudePaths() {
164
+ return {
165
+ claudeJson: CLAUDE_JSON_PATH,
166
+ claudeSettings: CLAUDE_SETTINGS_PATH,
167
+ };
168
+ }
169
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.recordError = recordError;
4
+ // Error logging utility
5
+ const path_1 = require("path");
6
+ const fileStorage_1 = require("./fileStorage");
7
+ const ERROR_DIR = (0, path_1.join)((0, fileStorage_1.getBaseDir)(), 'error_logs');
8
+ /**
9
+ * Get the file path for a given date
10
+ */
11
+ function getErrorFilePath(dateStr) {
12
+ return (0, path_1.join)(ERROR_DIR, `${dateStr}.jsonl`);
13
+ }
14
+ /**
15
+ * Extract error details from various error types
16
+ */
17
+ function extractErrorDetails(error) {
18
+ const details = {
19
+ message: error.message,
20
+ };
21
+ // Extract OpenAI SDK error properties
22
+ if ('status' in error) {
23
+ details.status = error.status;
24
+ }
25
+ if ('code' in error) {
26
+ details.code = error.code;
27
+ }
28
+ if ('type' in error) {
29
+ details.type = error.type;
30
+ }
31
+ return details;
32
+ }
33
+ /**
34
+ * Error codes that should not be logged (user errors, not API issues)
35
+ */
36
+ const SKIP_ERROR_CODES = [401, 402, 404, 429];
37
+ /**
38
+ * Record error to the daily file
39
+ * Non-blocking, fails silently on errors
40
+ * Skips common user errors like auth failures and rate limits
41
+ */
42
+ function recordError(error, context) {
43
+ try {
44
+ // Skip logging for common user-related errors
45
+ if ('status' in error && SKIP_ERROR_CODES.includes(error.status)) {
46
+ return;
47
+ }
48
+ (0, fileStorage_1.ensureDirExists)(ERROR_DIR);
49
+ const record = {
50
+ timestamp: new Date().toISOString(),
51
+ ...context,
52
+ error: extractErrorDetails(error),
53
+ };
54
+ const filePath = getErrorFilePath((0, fileStorage_1.getTodayDateString)());
55
+ (0, fileStorage_1.appendJsonLine)(filePath, record);
56
+ }
57
+ catch {
58
+ // Fail silently - don't interrupt API flow for error logging
59
+ }
60
+ }
61
+ //# sourceMappingURL=errorLog.js.map
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getTodayDateString = getTodayDateString;
4
+ exports.ensureDirExists = ensureDirExists;
5
+ exports.getBaseDir = getBaseDir;
6
+ exports.repairPrivateStoragePermissions = repairPrivateStoragePermissions;
7
+ exports.hardenPrivateFile = hardenPrivateFile;
8
+ exports.appendJsonLine = appendJsonLine;
9
+ exports.writePrivateJsonFile = writePrivateJsonFile;
10
+ // Shared file storage utilities for daily JSON files
11
+ const fs_1 = require("fs");
12
+ const crypto_1 = require("crypto");
13
+ const os_1 = require("os");
14
+ const path_1 = require("path");
15
+ // Base directory for all claude-adapter data
16
+ const BASE_DIR = (0, path_1.join)((0, os_1.homedir)(), '.claude-adapter');
17
+ /**
18
+ * Get today's date as YYYY-MM-DD
19
+ */
20
+ function getTodayDateString() {
21
+ return new Date().toISOString().split('T')[0];
22
+ }
23
+ /**
24
+ * Ensure a directory exists, creating it if necessary
25
+ */
26
+ function ensureDirExists(dirPath) {
27
+ if (!(0, fs_1.existsSync)(dirPath)) {
28
+ (0, fs_1.mkdirSync)(dirPath, { recursive: true, mode: 0o700 });
29
+ }
30
+ // Windows relies on the current user's profile ACL. POSIX modes protect
31
+ // configuration, metadata, usage, and error logs from other local users.
32
+ if (process.platform !== 'win32') {
33
+ (0, fs_1.chmodSync)(dirPath, 0o700);
34
+ }
35
+ }
36
+ /**
37
+ * Get the base storage directory
38
+ */
39
+ function getBaseDir() {
40
+ return BASE_DIR;
41
+ }
42
+ /** Repair all existing adapter-owned storage permissions during startup. */
43
+ function repairPrivateStoragePermissions(baseDir = BASE_DIR) {
44
+ if (process.platform === 'win32') {
45
+ return;
46
+ }
47
+ ensureDirExists(baseDir);
48
+ for (const entry of (0, fs_1.readdirSync)(baseDir, { withFileTypes: true })) {
49
+ const entryPath = (0, path_1.join)(baseDir, entry.name);
50
+ const stats = (0, fs_1.lstatSync)(entryPath);
51
+ // Never follow symlinks from the private storage tree.
52
+ if (stats.isSymbolicLink()) {
53
+ continue;
54
+ }
55
+ if (stats.isDirectory()) {
56
+ repairPrivateStoragePermissions(entryPath);
57
+ }
58
+ else if (stats.isFile()) {
59
+ (0, fs_1.chmodSync)(entryPath, 0o600);
60
+ }
61
+ }
62
+ }
63
+ /** Repair permissions on an existing private file. */
64
+ function hardenPrivateFile(filePath) {
65
+ if (process.platform !== 'win32' && (0, fs_1.existsSync)(filePath)) {
66
+ (0, fs_1.chmodSync)(filePath, 0o600);
67
+ }
68
+ }
69
+ /**
70
+ * Append a JSON record to a file (one JSON object per line)
71
+ * This is atomic on most filesystems and avoids race conditions
72
+ */
73
+ function appendJsonLine(filePath, record) {
74
+ ensureDirExists((0, path_1.dirname)(filePath));
75
+ const line = JSON.stringify(record) + '\n';
76
+ (0, fs_1.appendFileSync)(filePath, line, { encoding: 'utf-8', mode: 0o600 });
77
+ hardenPrivateFile(filePath);
78
+ }
79
+ /**
80
+ * Atomically replace a JSON file with a private file in the same directory.
81
+ * Keeping the temporary file adjacent to the destination makes rename atomic
82
+ * on the filesystems supported by this CLI.
83
+ */
84
+ function writePrivateJsonFile(filePath, data, secureParentDirectory = true) {
85
+ const parentDirectory = (0, path_1.dirname)(filePath);
86
+ if (secureParentDirectory) {
87
+ ensureDirExists(parentDirectory);
88
+ }
89
+ else if (!(0, fs_1.existsSync)(parentDirectory)) {
90
+ (0, fs_1.mkdirSync)(parentDirectory, { recursive: true });
91
+ }
92
+ const tempPath = `${filePath}.${process.pid}.${(0, crypto_1.randomBytes)(8).toString('hex')}.tmp`;
93
+ let descriptor;
94
+ try {
95
+ descriptor = (0, fs_1.openSync)(tempPath, 'w', 0o600);
96
+ (0, fs_1.writeFileSync)(descriptor, JSON.stringify(data, null, 2), 'utf-8');
97
+ (0, fs_1.closeSync)(descriptor);
98
+ descriptor = undefined;
99
+ if (process.platform !== 'win32') {
100
+ (0, fs_1.chmodSync)(tempPath, 0o600);
101
+ }
102
+ (0, fs_1.renameSync)(tempPath, filePath);
103
+ hardenPrivateFile(filePath);
104
+ }
105
+ finally {
106
+ if (descriptor !== undefined) {
107
+ (0, fs_1.closeSync)(descriptor);
108
+ }
109
+ if ((0, fs_1.existsSync)(tempPath)) {
110
+ (0, fs_1.unlinkSync)(tempPath);
111
+ }
112
+ }
113
+ }
114
+ //# sourceMappingURL=fileStorage.js.map
@@ -0,0 +1,19 @@
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ // Utility exports
18
+ __exportStar(require("./config"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RequestLogger = exports.Logger = exports.logger = exports.LogLevel = void 0;
4
+ // Structured logger with levels and timestamps
5
+ var LogLevel;
6
+ (function (LogLevel) {
7
+ LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
8
+ LogLevel[LogLevel["INFO"] = 1] = "INFO";
9
+ LogLevel[LogLevel["WARN"] = 2] = "WARN";
10
+ LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
11
+ })(LogLevel || (exports.LogLevel = LogLevel = {}));
12
+ const levelNames = {
13
+ [LogLevel.DEBUG]: 'DEBUG',
14
+ [LogLevel.INFO]: 'INFO',
15
+ [LogLevel.WARN]: 'WARN',
16
+ [LogLevel.ERROR]: 'ERROR',
17
+ };
18
+ const levelColors = {
19
+ [LogLevel.DEBUG]: '\x1b[90m', // gray
20
+ [LogLevel.INFO]: '\x1b[36m', // cyan
21
+ [LogLevel.WARN]: '\x1b[33m', // yellow
22
+ [LogLevel.ERROR]: '\x1b[31m', // red
23
+ };
24
+ const RESET = '\x1b[0m';
25
+ class Logger {
26
+ level;
27
+ prefix;
28
+ constructor(prefix = 'adapter') {
29
+ this.prefix = prefix;
30
+ // Default to INFO, can be overridden by LOG_LEVEL env var
31
+ const envLevel = process.env.LOG_LEVEL?.toUpperCase();
32
+ this.level = this.parseLevel(envLevel) ?? LogLevel.INFO;
33
+ }
34
+ parseLevel(level) {
35
+ switch (level) {
36
+ case 'DEBUG':
37
+ return LogLevel.DEBUG;
38
+ case 'INFO':
39
+ return LogLevel.INFO;
40
+ case 'WARN':
41
+ return LogLevel.WARN;
42
+ case 'ERROR':
43
+ return LogLevel.ERROR;
44
+ default:
45
+ return undefined;
46
+ }
47
+ }
48
+ formatTimestamp() {
49
+ return new Date().toISOString();
50
+ }
51
+ log(level, message, meta) {
52
+ if (level < this.level)
53
+ return;
54
+ let output;
55
+ const color = levelColors[level];
56
+ // Use simple format for INFO in non-debug mode
57
+ if (level === LogLevel.INFO && this.level > LogLevel.DEBUG) {
58
+ output = `${color}${message}${RESET}`;
59
+ if (meta && Object.keys(meta).length > 0) {
60
+ output += ` ${color}${JSON.stringify(meta)}${RESET}`;
61
+ }
62
+ }
63
+ else {
64
+ // Full format with timestamp for DEBUG or when in debug mode
65
+ const levelName = levelNames[level].padEnd(5);
66
+ const timestamp = this.formatTimestamp();
67
+ output = `${color}[${timestamp}] [${this.prefix}] ${levelName}${RESET} ${message}`;
68
+ if (meta && Object.keys(meta).length > 0) {
69
+ output += ` ${JSON.stringify(meta)}`;
70
+ }
71
+ }
72
+ if (level === LogLevel.ERROR) {
73
+ console.error(output);
74
+ }
75
+ else {
76
+ console.log(output);
77
+ }
78
+ }
79
+ debug(message, meta) {
80
+ this.log(LogLevel.DEBUG, message, meta);
81
+ }
82
+ info(message, meta) {
83
+ this.log(LogLevel.INFO, message, meta);
84
+ }
85
+ warn(message, meta) {
86
+ this.log(LogLevel.WARN, message, meta);
87
+ }
88
+ error(message, error, meta) {
89
+ const errorMeta = error ? { error: error.message, ...meta } : meta;
90
+ this.log(LogLevel.ERROR, message, errorMeta);
91
+ }
92
+ print(message) {
93
+ console.log(message);
94
+ }
95
+ setLevel(level) {
96
+ this.level = level;
97
+ }
98
+ /**
99
+ * Create a child logger with request context
100
+ */
101
+ withRequestId(requestId) {
102
+ return new RequestLogger(this, requestId);
103
+ }
104
+ }
105
+ exports.Logger = Logger;
106
+ /**
107
+ * Logger bound to a specific request ID for tracing
108
+ */
109
+ class RequestLogger {
110
+ parent;
111
+ requestId;
112
+ constructor(parent, requestId) {
113
+ this.parent = parent;
114
+ this.requestId = requestId;
115
+ }
116
+ addContext(meta) {
117
+ return { requestId: this.requestId, ...meta };
118
+ }
119
+ debug(message, meta) {
120
+ this.parent.debug(message, this.addContext(meta));
121
+ }
122
+ info(message, meta) {
123
+ this.parent.info(message, this.addContext(meta));
124
+ }
125
+ warn(message, meta) {
126
+ this.parent.warn(message, this.addContext(meta));
127
+ }
128
+ error(message, error, meta) {
129
+ this.parent.error(message, error, this.addContext(meta));
130
+ }
131
+ print(message) {
132
+ this.parent.print(message);
133
+ }
134
+ }
135
+ exports.RequestLogger = RequestLogger;
136
+ // Export singleton instance
137
+ exports.logger = new Logger();
138
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getMetadata = getMetadata;
4
+ exports.updateLatestVersion = updateLatestVersion;
5
+ exports.getCachedLatestVersion = getCachedLatestVersion;
6
+ // Metadata storage utility
7
+ const fs_1 = require("fs");
8
+ const os_1 = require("os");
9
+ const path_1 = require("path");
10
+ const crypto_1 = require("crypto");
11
+ const package_json_1 = require("../../package.json");
12
+ const fileStorage_1 = require("./fileStorage");
13
+ const METADATA_DIR = (0, path_1.join)((0, os_1.homedir)(), '.claude-adapter');
14
+ const METADATA_FILE = (0, path_1.join)(METADATA_DIR, 'metadata.json');
15
+ /**
16
+ * Generate a unique user ID
17
+ */
18
+ function generateUserId() {
19
+ return (0, crypto_1.randomBytes)(16).toString('hex');
20
+ }
21
+ /**
22
+ * Get OS name
23
+ */
24
+ function getOsName() {
25
+ return (0, os_1.platform)();
26
+ }
27
+ /**
28
+ * Ensure metadata directory exists
29
+ */
30
+ function ensureMetadataDir() {
31
+ (0, fileStorage_1.ensureDirExists)(METADATA_DIR);
32
+ }
33
+ let cachedMetadata = null;
34
+ /**
35
+ * Load metadata from file
36
+ */
37
+ function loadMetadata() {
38
+ if (cachedMetadata) {
39
+ return cachedMetadata;
40
+ }
41
+ try {
42
+ if ((0, fs_1.existsSync)(METADATA_FILE)) {
43
+ ensureMetadataDir();
44
+ (0, fileStorage_1.hardenPrivateFile)(METADATA_FILE);
45
+ const data = (0, fs_1.readFileSync)(METADATA_FILE, 'utf-8');
46
+ cachedMetadata = JSON.parse(data);
47
+ return cachedMetadata;
48
+ }
49
+ }
50
+ catch {
51
+ // Ignore read errors
52
+ }
53
+ return null;
54
+ }
55
+ /**
56
+ * Save metadata to file
57
+ */
58
+ function saveMetadata(metadata) {
59
+ try {
60
+ ensureMetadataDir();
61
+ (0, fileStorage_1.writePrivateJsonFile)(METADATA_FILE, metadata);
62
+ cachedMetadata = metadata;
63
+ }
64
+ catch {
65
+ // Ignore write errors
66
+ }
67
+ }
68
+ /**
69
+ * Get or create metadata
70
+ * Creates new metadata on first run, updates currentVersion on subsequent runs
71
+ */
72
+ function getMetadata() {
73
+ let metadata = loadMetadata();
74
+ if (!metadata) {
75
+ // First run - create new metadata
76
+ metadata = {
77
+ userId: generateUserId(),
78
+ platform: getOsName(),
79
+ platformRelease: (0, os_1.release)(),
80
+ currentVersion: package_json_1.version,
81
+ createdAt: new Date().toISOString(),
82
+ };
83
+ saveMetadata(metadata);
84
+ }
85
+ else {
86
+ // Update current version if changed
87
+ if (metadata.currentVersion !== package_json_1.version) {
88
+ metadata.currentVersion = package_json_1.version;
89
+ saveMetadata(metadata);
90
+ }
91
+ }
92
+ return metadata;
93
+ }
94
+ /**
95
+ * Update latest version in metadata (called after npm registry check)
96
+ */
97
+ function updateLatestVersion(version) {
98
+ try {
99
+ const metadata = loadMetadata();
100
+ if (metadata) {
101
+ metadata.latestVersion = version;
102
+ metadata.latestVersionTimestamp = Date.now();
103
+ saveMetadata(metadata);
104
+ }
105
+ }
106
+ catch {
107
+ // Ignore errors
108
+ }
109
+ }
110
+ /**
111
+ * Get cached latest version info
112
+ */
113
+ function getCachedLatestVersion() {
114
+ try {
115
+ const metadata = loadMetadata();
116
+ if (metadata?.latestVersion && metadata?.latestVersionTimestamp) {
117
+ return {
118
+ version: metadata.latestVersion,
119
+ timestamp: metadata.latestVersionTimestamp,
120
+ };
121
+ }
122
+ }
123
+ catch {
124
+ // Ignore errors
125
+ }
126
+ return null;
127
+ }
128
+ //# sourceMappingURL=metadata.js.map
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isAzureOpenAIEndpoint = isAzureOpenAIEndpoint;
4
+ function isAzureOpenAIEndpoint(baseUrl) {
5
+ try {
6
+ const url = new URL(baseUrl);
7
+ const hostname = url.hostname.toLowerCase();
8
+ return hostname.endsWith('.openai.azure.com') || hostname.includes('.services.ai.azure.com');
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
14
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.recordUsage = recordUsage;
4
+ // Token usage storage utility
5
+ const path_1 = require("path");
6
+ const fileStorage_1 = require("./fileStorage");
7
+ const USAGE_DIR = (0, path_1.join)((0, fileStorage_1.getBaseDir)(), 'token_usage');
8
+ /**
9
+ * Get the file path for a given date
10
+ */
11
+ function getUsageFilePath(dateStr) {
12
+ return (0, path_1.join)(USAGE_DIR, `${dateStr}.jsonl`);
13
+ }
14
+ /**
15
+ * Record token usage to the daily file
16
+ * Non-blocking, fails silently on errors
17
+ */
18
+ function recordUsage(data) {
19
+ try {
20
+ (0, fileStorage_1.ensureDirExists)(USAGE_DIR);
21
+ const record = {
22
+ timestamp: new Date().toISOString(),
23
+ ...data
24
+ };
25
+ const filePath = getUsageFilePath((0, fileStorage_1.getTodayDateString)());
26
+ (0, fileStorage_1.appendJsonLine)(filePath, record);
27
+ }
28
+ catch {
29
+ // Fail silently - don't interrupt API flow for usage tracking
30
+ }
31
+ }
32
+ //# sourceMappingURL=tokenUsage.js.map