@revenium/claude-code-metering 0.1.0 → 0.1.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 +22 -28
- package/README.md +321 -139
- package/dist/cli/commands/backfill.d.ts +98 -1
- package/dist/cli/commands/backfill.d.ts.map +1 -1
- package/dist/cli/commands/backfill.js +356 -146
- package/dist/cli/commands/backfill.js.map +1 -1
- package/dist/cli/commands/setup.d.ts +2 -0
- package/dist/cli/commands/setup.d.ts.map +1 -1
- package/dist/cli/commands/setup.js +55 -49
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +2 -11
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/test.d.ts.map +1 -1
- package/dist/cli/commands/test.js +23 -22
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/index.d.ts +2 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +44 -30
- package/dist/cli/index.js.map +1 -1
- package/dist/core/api/client.d.ts +7 -6
- package/dist/core/api/client.d.ts.map +1 -1
- package/dist/core/api/client.js +52 -47
- package/dist/core/api/client.js.map +1 -1
- package/dist/core/config/loader.d.ts +5 -13
- package/dist/core/config/loader.d.ts.map +1 -1
- package/dist/core/config/loader.js +67 -46
- package/dist/core/config/loader.js.map +1 -1
- package/dist/core/config/validator.d.ts +5 -1
- package/dist/core/config/validator.d.ts.map +1 -1
- package/dist/core/config/validator.js +37 -22
- package/dist/core/config/validator.js.map +1 -1
- package/dist/core/config/writer.d.ts +1 -1
- package/dist/core/config/writer.d.ts.map +1 -1
- package/dist/core/config/writer.js +76 -72
- package/dist/core/config/writer.js.map +1 -1
- package/dist/core/shell/detector.d.ts +8 -1
- package/dist/core/shell/detector.d.ts.map +1 -1
- package/dist/core/shell/detector.js +38 -24
- package/dist/core/shell/detector.js.map +1 -1
- package/dist/core/shell/profile-updater.d.ts +1 -1
- package/dist/core/shell/profile-updater.d.ts.map +1 -1
- package/dist/core/shell/profile-updater.js +40 -27
- package/dist/core/shell/profile-updater.js.map +1 -1
- package/dist/index.d.ts +9 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +18 -23
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/constants.d.ts +2 -2
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/constants.js +21 -21
- package/dist/utils/constants.js.map +1 -1
- package/dist/utils/hashing.d.ts +18 -0
- package/dist/utils/hashing.d.ts.map +1 -0
- package/dist/utils/hashing.js +27 -0
- package/dist/utils/hashing.js.map +1 -0
- package/package.json +6 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../../src/core/config/validator.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../../src/core/config/validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ReveniumConfig } from
|
|
1
|
+
import type { ReveniumConfig } from "../../types/index.js";
|
|
2
2
|
/**
|
|
3
3
|
* Writes the Revenium configuration to ~/.claude/revenium.env.
|
|
4
4
|
* Creates the directory if it doesn't exist and sets file permissions to 600.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writer.d.ts","sourceRoot":"","sources":["../../../src/core/config/writer.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"writer.d.ts","sourceRoot":"","sources":["../../../src/core/config/writer.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAwK3D;;;GAGG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAezE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C"}
|
|
@@ -7,6 +7,13 @@ const node_path_1 = require("node:path");
|
|
|
7
7
|
const promises_1 = require("node:fs/promises");
|
|
8
8
|
const constants_js_1 = require("../../utils/constants.js");
|
|
9
9
|
const loader_js_1 = require("./loader.js");
|
|
10
|
+
/**
|
|
11
|
+
* Escapes a value for use in shell export statements.
|
|
12
|
+
* Wraps the value in double quotes and escapes special characters.
|
|
13
|
+
*/
|
|
14
|
+
function escapeShellValue(value) {
|
|
15
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\$/g, "\\$").replace(/`/g, "\\`")}"`;
|
|
16
|
+
}
|
|
10
17
|
/**
|
|
11
18
|
* Escapes a value for use in OTEL_RESOURCE_ATTRIBUTES.
|
|
12
19
|
* OTEL_RESOURCE_ATTRIBUTES uses comma as delimiter and equals as key-value separator.
|
|
@@ -15,10 +22,10 @@ const loader_js_1 = require("./loader.js");
|
|
|
15
22
|
*/
|
|
16
23
|
function escapeResourceAttributeValue(value) {
|
|
17
24
|
return value
|
|
18
|
-
.replace(/%/g,
|
|
19
|
-
.replace(/,/g,
|
|
20
|
-
.replace(/=/g,
|
|
21
|
-
.replace(/"/g,
|
|
25
|
+
.replace(/%/g, "%25") // Escape % first to avoid double-encoding
|
|
26
|
+
.replace(/,/g, "%2C")
|
|
27
|
+
.replace(/=/g, "%3D")
|
|
28
|
+
.replace(/"/g, "%22");
|
|
22
29
|
}
|
|
23
30
|
/**
|
|
24
31
|
* Gets the path to the Claude config directory.
|
|
@@ -32,93 +39,90 @@ function getClaudeConfigDir() {
|
|
|
32
39
|
function generateEnvContent(config) {
|
|
33
40
|
const fullEndpoint = (0, loader_js_1.getFullOtlpEndpoint)(config.endpoint);
|
|
34
41
|
const lines = [
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
"# Revenium Claude Code Metering Configuration",
|
|
43
|
+
"# Generated by @revenium/claude-code-metering",
|
|
44
|
+
"#",
|
|
45
|
+
"# To load these variables, add to your shell profile:",
|
|
46
|
+
"# source ~/.claude/revenium.env",
|
|
47
|
+
"",
|
|
48
|
+
"# Enable Claude Code telemetry export",
|
|
42
49
|
`export ${constants_js_1.ENV_VARS.TELEMETRY_ENABLED}=1`,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
`export ${constants_js_1.ENV_VARS.OTLP_ENDPOINT}=${fullEndpoint}`,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
`export ${constants_js_1.ENV_VARS.OTLP_HEADERS}
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
"",
|
|
51
|
+
"# OTLP endpoint for Revenium metering",
|
|
52
|
+
`export ${constants_js_1.ENV_VARS.OTLP_ENDPOINT}=${escapeShellValue(fullEndpoint)}`,
|
|
53
|
+
"",
|
|
54
|
+
"# Authentication header with API key",
|
|
55
|
+
`export ${constants_js_1.ENV_VARS.OTLP_HEADERS}=${escapeShellValue(`x-api-key=${config.apiKey}`)}`,
|
|
56
|
+
"",
|
|
57
|
+
"# OTLP protocol (required for Claude Code)",
|
|
51
58
|
`export ${constants_js_1.ENV_VARS.OTLP_PROTOCOL}=http/json`,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
59
|
+
"",
|
|
60
|
+
"# Enable OTLP logs exporter (required to send telemetry)",
|
|
61
|
+
"export OTEL_LOGS_EXPORTER=otlp",
|
|
55
62
|
];
|
|
56
63
|
// Add optional fields
|
|
57
64
|
if (config.email) {
|
|
58
|
-
lines.push(
|
|
59
|
-
lines.push(
|
|
60
|
-
lines.push(`export ${constants_js_1.ENV_VARS.SUBSCRIBER_EMAIL}=${config.email}`);
|
|
65
|
+
lines.push("");
|
|
66
|
+
lines.push("# Subscriber email for attribution");
|
|
67
|
+
lines.push(`export ${constants_js_1.ENV_VARS.SUBSCRIBER_EMAIL}=${escapeShellValue(config.email)}`);
|
|
61
68
|
}
|
|
62
69
|
if (config.subscriptionTier) {
|
|
63
70
|
const tier = config.subscriptionTier;
|
|
64
71
|
const costMultiplier = config.costMultiplierOverride ?? (0, constants_js_1.getCostMultiplier)(tier);
|
|
65
72
|
const discountPercent = Math.round((1 - costMultiplier) * 100);
|
|
66
|
-
lines.push(
|
|
67
|
-
lines.push(
|
|
68
|
-
lines.push(`export ${constants_js_1.ENV_VARS.SUBSCRIPTION}=${config.subscriptionTier}`);
|
|
69
|
-
lines.push(
|
|
70
|
-
lines.push(
|
|
71
|
-
lines.push(
|
|
73
|
+
lines.push("");
|
|
74
|
+
lines.push("# Claude Code subscription tier");
|
|
75
|
+
lines.push(`export ${constants_js_1.ENV_VARS.SUBSCRIPTION}=${escapeShellValue(config.subscriptionTier)}`);
|
|
76
|
+
lines.push("");
|
|
77
|
+
lines.push("# Cost multiplier for subscription tier");
|
|
78
|
+
lines.push("# This adjusts Claude Code costs based on your subscription discount");
|
|
72
79
|
lines.push(`# ${tier}: ${discountPercent}% discount vs API rates`);
|
|
73
80
|
if (config.costMultiplierOverride !== undefined) {
|
|
74
|
-
lines.push(
|
|
81
|
+
lines.push("# (custom override applied)");
|
|
75
82
|
lines.push(`export ${constants_js_1.ENV_VARS.COST_MULTIPLIER}=${costMultiplier}`);
|
|
76
83
|
}
|
|
77
|
-
// Build OTEL_RESOURCE_ATTRIBUTES with cost_multiplier and optional
|
|
78
|
-
// Special characters (,=") in values are URL-encoded to ensure safe parsing
|
|
84
|
+
// Build OTEL_RESOURCE_ATTRIBUTES with cost_multiplier and optional organization.name/product.name.
|
|
85
|
+
// Special characters (,=") in values are URL-encoded to ensure safe parsing.
|
|
86
|
+
// Note: The backend ONLY reads organization.name and product.name from resourceAttributes,
|
|
87
|
+
// ignoring any auto-generated values in log record attributes from Claude Code.
|
|
79
88
|
const resourceAttrs = [`cost_multiplier=${costMultiplier}`];
|
|
80
89
|
if (config.organizationId) {
|
|
81
|
-
resourceAttrs.push(`organization.
|
|
90
|
+
resourceAttrs.push(`organization.name=${escapeResourceAttributeValue(config.organizationId)}`);
|
|
82
91
|
}
|
|
83
92
|
if (config.productId) {
|
|
84
|
-
resourceAttrs.push(`product.
|
|
93
|
+
resourceAttrs.push(`product.name=${escapeResourceAttributeValue(config.productId)}`);
|
|
85
94
|
}
|
|
86
|
-
lines.push(`export OTEL_RESOURCE_ATTRIBUTES="${resourceAttrs.join(
|
|
87
|
-
}
|
|
88
|
-
// Add advanced configuration section (commented out by default)
|
|
89
|
-
lines.push('');
|
|
90
|
-
lines.push('# ─────────────────────────────────────────────────────────────────────────────');
|
|
91
|
-
lines.push('# Advanced Configuration (Optional)');
|
|
92
|
-
lines.push('# ─────────────────────────────────────────────────────────────────────────────');
|
|
93
|
-
lines.push('#');
|
|
94
|
-
lines.push('# IMPORTANT: If you enable organization/product attribution below, you must also');
|
|
95
|
-
lines.push('# update OTEL_RESOURCE_ATTRIBUTES above to include them. For example:');
|
|
96
|
-
lines.push('# export OTEL_RESOURCE_ATTRIBUTES="cost_multiplier=0.08,organization.id=my-org,product.id=my-product"');
|
|
97
|
-
lines.push('# Otherwise, the telemetry sent to Revenium will not include the attribution data.');
|
|
98
|
-
lines.push('# Run `npx @revenium/claude-code-metering setup` again to regenerate this file with');
|
|
99
|
-
lines.push('# the correct OTEL_RESOURCE_ATTRIBUTES if you want automatic configuration.');
|
|
100
|
-
lines.push('#');
|
|
101
|
-
lines.push('# Organization ID: Attribute Claude Code costs to a specific customer or company.');
|
|
102
|
-
lines.push('# Use this when you want to track AI development costs by client/organization.');
|
|
103
|
-
lines.push('# Example: Your consulting firm tracks costs per client project.');
|
|
104
|
-
if (config.organizationId) {
|
|
105
|
-
lines.push(`export ${constants_js_1.ENV_VARS.ORGANIZATION_ID}=${config.organizationId}`);
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
lines.push(`# export ${constants_js_1.ENV_VARS.ORGANIZATION_ID}=your-organization-id`);
|
|
109
|
-
}
|
|
110
|
-
lines.push('#');
|
|
111
|
-
lines.push('# Product ID: Attribute Claude Code costs to a specific product or project.');
|
|
112
|
-
lines.push('# Use this when you want to track AI development costs by internal product.');
|
|
113
|
-
lines.push('# Example: Separate AI costs for "mobile-app" vs "backend-api" development.');
|
|
114
|
-
if (config.productId) {
|
|
115
|
-
lines.push(`export ${constants_js_1.ENV_VARS.PRODUCT_ID}=${config.productId}`);
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
lines.push(`# export ${constants_js_1.ENV_VARS.PRODUCT_ID}=your-product-id`);
|
|
95
|
+
lines.push(`export OTEL_RESOURCE_ATTRIBUTES="${resourceAttrs.join(",")}"`);
|
|
119
96
|
}
|
|
120
|
-
|
|
121
|
-
|
|
97
|
+
// Add advanced configuration section
|
|
98
|
+
lines.push("");
|
|
99
|
+
lines.push("# ─────────────────────────────────────────────────────────────────────────────");
|
|
100
|
+
lines.push("# Organization & Product Attribution (Optional)");
|
|
101
|
+
lines.push("# ─────────────────────────────────────────────────────────────────────────────");
|
|
102
|
+
lines.push("#");
|
|
103
|
+
lines.push("# To attribute Claude Code costs to a specific organization or product, you must");
|
|
104
|
+
lines.push("# add them to OTEL_RESOURCE_ATTRIBUTES above. The backend ONLY reads these values");
|
|
105
|
+
lines.push("# from OTEL_RESOURCE_ATTRIBUTES - standalone environment variables are NOT sent.");
|
|
106
|
+
lines.push("#");
|
|
107
|
+
lines.push("# HOW TO CONFIGURE:");
|
|
108
|
+
lines.push("# Edit the OTEL_RESOURCE_ATTRIBUTES line above to include organization.name and/or product.name:");
|
|
109
|
+
lines.push("#");
|
|
110
|
+
// Get current cost multiplier for the example
|
|
111
|
+
const exampleMultiplier = config.subscriptionTier && config.costMultiplierOverride === undefined
|
|
112
|
+
? (0, constants_js_1.getCostMultiplier)(config.subscriptionTier)
|
|
113
|
+
: config.costMultiplierOverride ?? "0.08";
|
|
114
|
+
lines.push(`# OTEL_RESOURCE_ATTRIBUTES="cost_multiplier=${exampleMultiplier},organization.name=my-org,product.name=my-product"`);
|
|
115
|
+
lines.push("#");
|
|
116
|
+
lines.push("# ATTRIBUTE DESCRIPTIONS:");
|
|
117
|
+
lines.push("# organization.name - Attribute costs to a customer/company (e.g., client name, team)");
|
|
118
|
+
lines.push("# product.name - Attribute costs to a product/project (e.g., mobile-app, backend-api)");
|
|
119
|
+
lines.push("#");
|
|
120
|
+
lines.push("# After editing, restart your terminal or run: source ~/.claude/revenium.env");
|
|
121
|
+
lines.push("#");
|
|
122
|
+
lines.push("# Alternatively, re-run setup with --organization and --product flags:");
|
|
123
|
+
lines.push("# npx @revenium/claude-code-metering setup --organization my-org --product my-product");
|
|
124
|
+
lines.push("");
|
|
125
|
+
return lines.join("\n");
|
|
122
126
|
}
|
|
123
127
|
/**
|
|
124
128
|
* Writes the Revenium configuration to ~/.claude/revenium.env.
|
|
@@ -131,7 +135,7 @@ async function writeConfig(config) {
|
|
|
131
135
|
await (0, promises_1.mkdir)(configDir, { recursive: true });
|
|
132
136
|
// Generate and write the content
|
|
133
137
|
const content = generateEnvContent(config);
|
|
134
|
-
await (0, promises_1.writeFile)(configPath, content, { encoding:
|
|
138
|
+
await (0, promises_1.writeFile)(configPath, content, { encoding: "utf-8" });
|
|
135
139
|
// Set restrictive permissions (owner read/write only)
|
|
136
140
|
await (0, promises_1.chmod)(configPath, constants_js_1.CONFIG_FILE_MODE);
|
|
137
141
|
return configPath;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writer.js","sourceRoot":"","sources":["../../../src/core/config/writer.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"writer.js","sourceRoot":"","sources":["../../../src/core/config/writer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ShellType } from
|
|
1
|
+
import type { ShellType } from "../../types/index.js";
|
|
2
2
|
/**
|
|
3
3
|
* Detects the current shell type based on environment variables.
|
|
4
4
|
*/
|
|
@@ -7,8 +7,15 @@ export declare function detectShell(): ShellType;
|
|
|
7
7
|
* Gets the profile file path for a given shell type.
|
|
8
8
|
*/
|
|
9
9
|
export declare function getProfilePath(shellType: ShellType): string | null;
|
|
10
|
+
/**
|
|
11
|
+
* Validates that a config path contains only safe characters.
|
|
12
|
+
* Throws an error if the path contains potentially dangerous characters.
|
|
13
|
+
* Allows spaces since paths are properly quoted in shell commands.
|
|
14
|
+
*/
|
|
15
|
+
export declare function validateConfigPath(path: string): void;
|
|
10
16
|
/**
|
|
11
17
|
* Generates the source command for a given shell type.
|
|
18
|
+
* Validates the config path before generating the command.
|
|
12
19
|
*/
|
|
13
20
|
export declare function getSourceCommand(shellType: ShellType, configPath: string): string;
|
|
14
21
|
//# sourceMappingURL=detector.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../../../src/core/shell/detector.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD;;GAEG;AACH,wBAAgB,WAAW,IAAI,SAAS,CA0BvC;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAiBlE;AAED
|
|
1
|
+
{"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../../../src/core/shell/detector.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD;;GAEG;AACH,wBAAgB,WAAW,IAAI,SAAS,CA0BvC;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAiBlE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAQrD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,MAAM,GACjB,MAAM,CAWR"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.detectShell = detectShell;
|
|
4
4
|
exports.getProfilePath = getProfilePath;
|
|
5
|
+
exports.validateConfigPath = validateConfigPath;
|
|
5
6
|
exports.getSourceCommand = getSourceCommand;
|
|
6
7
|
const node_os_1 = require("node:os");
|
|
7
8
|
const node_path_1 = require("node:path");
|
|
@@ -10,28 +11,28 @@ const node_fs_1 = require("node:fs");
|
|
|
10
11
|
* Detects the current shell type based on environment variables.
|
|
11
12
|
*/
|
|
12
13
|
function detectShell() {
|
|
13
|
-
const shell = process.env.SHELL ||
|
|
14
|
-
if (shell.includes(
|
|
15
|
-
return
|
|
14
|
+
const shell = process.env.SHELL || "";
|
|
15
|
+
if (shell.includes("zsh")) {
|
|
16
|
+
return "zsh";
|
|
16
17
|
}
|
|
17
|
-
if (shell.includes(
|
|
18
|
-
return
|
|
18
|
+
if (shell.includes("fish")) {
|
|
19
|
+
return "fish";
|
|
19
20
|
}
|
|
20
|
-
if (shell.includes(
|
|
21
|
-
return
|
|
21
|
+
if (shell.includes("bash")) {
|
|
22
|
+
return "bash";
|
|
22
23
|
}
|
|
23
24
|
// Fallback: check for rc files
|
|
24
25
|
const home = (0, node_os_1.homedir)();
|
|
25
|
-
if ((0, node_fs_1.existsSync)((0, node_path_1.join)(home,
|
|
26
|
-
return
|
|
26
|
+
if ((0, node_fs_1.existsSync)((0, node_path_1.join)(home, ".zshrc"))) {
|
|
27
|
+
return "zsh";
|
|
27
28
|
}
|
|
28
|
-
if ((0, node_fs_1.existsSync)((0, node_path_1.join)(home,
|
|
29
|
-
return
|
|
29
|
+
if ((0, node_fs_1.existsSync)((0, node_path_1.join)(home, ".config", "fish", "config.fish"))) {
|
|
30
|
+
return "fish";
|
|
30
31
|
}
|
|
31
|
-
if ((0, node_fs_1.existsSync)((0, node_path_1.join)(home,
|
|
32
|
-
return
|
|
32
|
+
if ((0, node_fs_1.existsSync)((0, node_path_1.join)(home, ".bashrc"))) {
|
|
33
|
+
return "bash";
|
|
33
34
|
}
|
|
34
|
-
return
|
|
35
|
+
return "unknown";
|
|
35
36
|
}
|
|
36
37
|
/**
|
|
37
38
|
* Gets the profile file path for a given shell type.
|
|
@@ -39,28 +40,41 @@ function detectShell() {
|
|
|
39
40
|
function getProfilePath(shellType) {
|
|
40
41
|
const home = (0, node_os_1.homedir)();
|
|
41
42
|
switch (shellType) {
|
|
42
|
-
case
|
|
43
|
-
return (0, node_path_1.join)(home,
|
|
44
|
-
case
|
|
43
|
+
case "zsh":
|
|
44
|
+
return (0, node_path_1.join)(home, ".zshrc");
|
|
45
|
+
case "bash":
|
|
45
46
|
// Prefer .bashrc, fallback to .bash_profile
|
|
46
|
-
if ((0, node_fs_1.existsSync)((0, node_path_1.join)(home,
|
|
47
|
-
return (0, node_path_1.join)(home,
|
|
47
|
+
if ((0, node_fs_1.existsSync)((0, node_path_1.join)(home, ".bashrc"))) {
|
|
48
|
+
return (0, node_path_1.join)(home, ".bashrc");
|
|
48
49
|
}
|
|
49
|
-
return (0, node_path_1.join)(home,
|
|
50
|
-
case
|
|
51
|
-
return (0, node_path_1.join)(home,
|
|
50
|
+
return (0, node_path_1.join)(home, ".bash_profile");
|
|
51
|
+
case "fish":
|
|
52
|
+
return (0, node_path_1.join)(home, ".config", "fish", "config.fish");
|
|
52
53
|
default:
|
|
53
54
|
return null;
|
|
54
55
|
}
|
|
55
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Validates that a config path contains only safe characters.
|
|
59
|
+
* Throws an error if the path contains potentially dangerous characters.
|
|
60
|
+
* Allows spaces since paths are properly quoted in shell commands.
|
|
61
|
+
*/
|
|
62
|
+
function validateConfigPath(path) {
|
|
63
|
+
const unsafeCharsRegex = /[;|&$`"'\\<>(){}[\]!*?#\n\r\t]/;
|
|
64
|
+
if (unsafeCharsRegex.test(path)) {
|
|
65
|
+
throw new Error(`Invalid config path: contains unsafe characters. Path must not contain shell metacharacters like semicolons, pipes, backticks, or quotes.`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
56
68
|
/**
|
|
57
69
|
* Generates the source command for a given shell type.
|
|
70
|
+
* Validates the config path before generating the command.
|
|
58
71
|
*/
|
|
59
72
|
function getSourceCommand(shellType, configPath) {
|
|
73
|
+
validateConfigPath(configPath);
|
|
60
74
|
switch (shellType) {
|
|
61
|
-
case
|
|
75
|
+
case "fish":
|
|
62
76
|
// Fish uses a different syntax for sourcing env files
|
|
63
|
-
return `# Source Revenium Claude Code metering config\nif test -f ${configPath}\n export (cat ${configPath} | grep -v '^#' | xargs -L 1)\nend`;
|
|
77
|
+
return `# Source Revenium Claude Code metering config\nif test -f "${configPath}"\n export (cat "${configPath}" | grep -v '^#' | xargs -L 1)\nend`;
|
|
64
78
|
default:
|
|
65
79
|
// Bash and Zsh use the same syntax
|
|
66
80
|
return `# Source Revenium Claude Code metering config\nif [ -f "${configPath}" ]; then\n source "${configPath}"\nfi`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detector.js","sourceRoot":"","sources":["../../../src/core/shell/detector.ts"],"names":[],"mappings":";;AAQA,kCA0BC;AAKD,wCAiBC;
|
|
1
|
+
{"version":3,"file":"detector.js","sourceRoot":"","sources":["../../../src/core/shell/detector.ts"],"names":[],"mappings":";;AAQA,kCA0BC;AAKD,wCAiBC;AAOD,gDAQC;AAMD,4CAcC;AA3FD,qCAAkC;AAClC,yCAAiC;AACjC,qCAAqC;AAGrC;;GAEG;AACH,SAAgB,WAAW;IACzB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;IAEtC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,+BAA+B;IAC/B,MAAM,IAAI,GAAG,IAAA,iBAAO,GAAE,CAAC;IACvB,IAAI,IAAA,oBAAU,EAAC,IAAA,gBAAI,EAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC;QACrC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,IAAA,oBAAU,EAAC,IAAA,gBAAI,EAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC;QAC7D,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,IAAA,oBAAU,EAAC,IAAA,gBAAI,EAAC,IAAI,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;QACtC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,SAAoB;IACjD,MAAM,IAAI,GAAG,IAAA,iBAAO,GAAE,CAAC;IAEvB,QAAQ,SAAS,EAAE,CAAC;QAClB,KAAK,KAAK;YACR,OAAO,IAAA,gBAAI,EAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC9B,KAAK,MAAM;YACT,4CAA4C;YAC5C,IAAI,IAAA,oBAAU,EAAC,IAAA,gBAAI,EAAC,IAAI,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;gBACtC,OAAO,IAAA,gBAAI,EAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YAC/B,CAAC;YACD,OAAO,IAAA,gBAAI,EAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QACrC,KAAK,MAAM;YACT,OAAO,IAAA,gBAAI,EAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;QACtD;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAgB,kBAAkB,CAAC,IAAY;IAC7C,MAAM,gBAAgB,GAAG,gCAAgC,CAAC;IAE1D,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CACb,2IAA2I,CAC5I,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAgB,gBAAgB,CAC9B,SAAoB,EACpB,UAAkB;IAElB,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAE/B,QAAQ,SAAS,EAAE,CAAC;QAClB,KAAK,MAAM;YACT,sDAAsD;YACtD,OAAO,8DAA8D,UAAU,uBAAuB,UAAU,qCAAqC,CAAC;QACxJ;YACE,mCAAmC;YACnC,OAAO,2DAA2D,UAAU,0BAA0B,UAAU,OAAO,CAAC;IAC5H,CAAC;AACH,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ShellType, ShellUpdateResult } from
|
|
1
|
+
import type { ShellType, ShellUpdateResult } from "../../types/index.js";
|
|
2
2
|
/**
|
|
3
3
|
* Updates the shell profile to source the Revenium configuration file.
|
|
4
4
|
* Returns details about the update operation.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profile-updater.d.ts","sourceRoot":"","sources":["../../../src/core/shell/profile-updater.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"profile-updater.d.ts","sourceRoot":"","sources":["../../../src/core/shell/profile-updater.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AA+CzE;;;GAGG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAkErE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,CAMlE"}
|
|
@@ -7,8 +7,8 @@ const node_fs_1 = require("node:fs");
|
|
|
7
7
|
const detector_js_1 = require("./detector.js");
|
|
8
8
|
const writer_js_1 = require("../config/writer.js");
|
|
9
9
|
/** Marker comment to identify our configuration block */
|
|
10
|
-
const CONFIG_MARKER_START =
|
|
11
|
-
const CONFIG_MARKER_END =
|
|
10
|
+
const CONFIG_MARKER_START = "# >>> revenium-claude-code-metering >>>";
|
|
11
|
+
const CONFIG_MARKER_END = "# <<< revenium-claude-code-metering <<<";
|
|
12
12
|
/**
|
|
13
13
|
* Checks if the shell profile already has the Revenium source command.
|
|
14
14
|
*/
|
|
@@ -16,7 +16,7 @@ async function hasReveniumConfig(profilePath) {
|
|
|
16
16
|
if (!(0, node_fs_1.existsSync)(profilePath)) {
|
|
17
17
|
return false;
|
|
18
18
|
}
|
|
19
|
-
const content = await (0, promises_1.readFile)(profilePath,
|
|
19
|
+
const content = await (0, promises_1.readFile)(profilePath, "utf-8");
|
|
20
20
|
return content.includes(CONFIG_MARKER_START);
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
@@ -36,8 +36,10 @@ function removeExistingConfig(content) {
|
|
|
36
36
|
return content;
|
|
37
37
|
}
|
|
38
38
|
const before = content.substring(0, startIndex).trimEnd();
|
|
39
|
-
const after = content
|
|
40
|
-
|
|
39
|
+
const after = content
|
|
40
|
+
.substring(endIndex + CONFIG_MARKER_END.length)
|
|
41
|
+
.trimStart();
|
|
42
|
+
return before + (after ? "\n" + after : "");
|
|
41
43
|
}
|
|
42
44
|
/**
|
|
43
45
|
* Updates the shell profile to source the Revenium configuration file.
|
|
@@ -45,11 +47,11 @@ function removeExistingConfig(content) {
|
|
|
45
47
|
*/
|
|
46
48
|
async function updateShellProfile() {
|
|
47
49
|
const shellType = (0, detector_js_1.detectShell)();
|
|
48
|
-
if (shellType ===
|
|
50
|
+
if (shellType === "unknown") {
|
|
49
51
|
return {
|
|
50
52
|
success: false,
|
|
51
53
|
shellType,
|
|
52
|
-
message:
|
|
54
|
+
message: "Could not detect shell type. Please manually add the source command to your shell profile.",
|
|
53
55
|
};
|
|
54
56
|
}
|
|
55
57
|
const profilePath = (0, detector_js_1.getProfilePath)(shellType);
|
|
@@ -61,33 +63,44 @@ async function updateShellProfile() {
|
|
|
61
63
|
};
|
|
62
64
|
}
|
|
63
65
|
const configPath = (0, writer_js_1.getConfigFilePath)();
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
try {
|
|
67
|
+
// Check if already configured
|
|
68
|
+
if (await hasReveniumConfig(profilePath)) {
|
|
69
|
+
// Remove existing and re-add (in case config path changed)
|
|
70
|
+
let content = await (0, promises_1.readFile)(profilePath, "utf-8");
|
|
71
|
+
content = removeExistingConfig(content);
|
|
72
|
+
const configBlock = generateConfigBlock(shellType, configPath);
|
|
73
|
+
await (0, promises_1.writeFile)(profilePath, content + configBlock, "utf-8");
|
|
74
|
+
return {
|
|
75
|
+
success: true,
|
|
76
|
+
shellType,
|
|
77
|
+
profilePath,
|
|
78
|
+
message: `Updated existing configuration in ${profilePath}`,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
// Add new configuration
|
|
82
|
+
let content = "";
|
|
83
|
+
if ((0, node_fs_1.existsSync)(profilePath)) {
|
|
84
|
+
content = await (0, promises_1.readFile)(profilePath, "utf-8");
|
|
85
|
+
}
|
|
69
86
|
const configBlock = generateConfigBlock(shellType, configPath);
|
|
70
|
-
await (0, promises_1.writeFile)(profilePath, content + configBlock,
|
|
87
|
+
await (0, promises_1.writeFile)(profilePath, content + configBlock, "utf-8");
|
|
71
88
|
return {
|
|
72
89
|
success: true,
|
|
73
90
|
shellType,
|
|
74
91
|
profilePath,
|
|
75
|
-
message: `
|
|
92
|
+
message: `Added configuration to ${profilePath}`,
|
|
76
93
|
};
|
|
77
94
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
95
|
+
catch (error) {
|
|
96
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
97
|
+
return {
|
|
98
|
+
success: false,
|
|
99
|
+
shellType,
|
|
100
|
+
profilePath,
|
|
101
|
+
message: `Failed to update shell profile: ${errorMessage}`,
|
|
102
|
+
};
|
|
82
103
|
}
|
|
83
|
-
const configBlock = generateConfigBlock(shellType, configPath);
|
|
84
|
-
await (0, promises_1.writeFile)(profilePath, content + configBlock, 'utf-8');
|
|
85
|
-
return {
|
|
86
|
-
success: true,
|
|
87
|
-
shellType,
|
|
88
|
-
profilePath,
|
|
89
|
-
message: `Added configuration to ${profilePath}`,
|
|
90
|
-
};
|
|
91
104
|
}
|
|
92
105
|
/**
|
|
93
106
|
* Gets instructions for manual shell profile configuration.
|
|
@@ -96,6 +109,6 @@ function getManualInstructions(shellType) {
|
|
|
96
109
|
const configPath = (0, writer_js_1.getConfigFilePath)();
|
|
97
110
|
const sourceCmd = (0, detector_js_1.getSourceCommand)(shellType, configPath);
|
|
98
111
|
const profilePath = (0, detector_js_1.getProfilePath)(shellType);
|
|
99
|
-
return `Add the following to ${profilePath ||
|
|
112
|
+
return `Add the following to ${profilePath || "your shell profile"}:\n\n${sourceCmd}`;
|
|
100
113
|
}
|
|
101
114
|
//# sourceMappingURL=profile-updater.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profile-updater.js","sourceRoot":"","sources":["../../../src/core/shell/profile-updater.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"profile-updater.js","sourceRoot":"","sources":["../../../src/core/shell/profile-updater.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
5
|
-
export * from
|
|
6
|
-
export * from
|
|
7
|
-
export * from
|
|
8
|
-
export * from
|
|
1
|
+
export * from "./types/index.js";
|
|
2
|
+
export * from "./utils/constants.js";
|
|
3
|
+
export * from "./utils/hashing.js";
|
|
4
|
+
export * from "./utils/masking.js";
|
|
5
|
+
export * from "./core/config/loader.js";
|
|
6
|
+
export * from "./core/config/writer.js";
|
|
7
|
+
export * from "./core/config/validator.js";
|
|
8
|
+
export * from "./core/api/client.js";
|
|
9
|
+
export * from "./core/shell/detector.js";
|
|
9
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -17,6 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
// Re-export types and utilities for programmatic use
|
|
18
18
|
__exportStar(require("./types/index.js"), exports);
|
|
19
19
|
__exportStar(require("./utils/constants.js"), exports);
|
|
20
|
+
__exportStar(require("./utils/hashing.js"), exports);
|
|
20
21
|
__exportStar(require("./utils/masking.js"), exports);
|
|
21
22
|
__exportStar(require("./core/config/loader.js"), exports);
|
|
22
23
|
__exportStar(require("./core/config/writer.js"), exports);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,qDAAqD;AACrD,mDAAiC;AACjC,uDAAqC;AACrC,qDAAmC;AACnC,0DAAwC;AACxC,0DAAwC;AACxC,6DAA2C;AAC3C,uDAAqC;AACrC,2DAAyC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,qDAAqD;AACrD,mDAAiC;AACjC,uDAAqC;AACrC,qDAAmC;AACnC,qDAAmC;AACnC,0DAAwC;AACxC,0DAAwC;AACxC,6DAA2C;AAC3C,uDAAqC;AACrC,2DAAyC"}
|