@respan/cli 0.5.0 → 0.5.2
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/assets/hook.py +330 -197
- package/dist/commands/integrate/claude-code.js +3 -3
- package/dist/commands/integrate/codex-cli.js +16 -2
- package/dist/commands/integrate/gemini-cli.js +27 -6
- package/dist/lib/config.js +1 -1
- package/oclif.manifest.json +183 -183
- package/package.json +2 -2
- package/dist/assets/assets/hook.py +0 -1044
|
@@ -7,7 +7,7 @@ class IntegrateClaudeCode extends BaseCommand {
|
|
|
7
7
|
const { flags } = await this.parse(IntegrateClaudeCode);
|
|
8
8
|
this.globalFlags = flags;
|
|
9
9
|
try {
|
|
10
|
-
// Verify the user is authenticated (key is read by hook from ~/.
|
|
10
|
+
// Verify the user is authenticated (key is read by hook from ~/.respan/)
|
|
11
11
|
this.resolveApiKey();
|
|
12
12
|
const baseUrl = flags['base-url'];
|
|
13
13
|
const projectId = flags['project-id'];
|
|
@@ -93,7 +93,7 @@ class IntegrateClaudeCode extends BaseCommand {
|
|
|
93
93
|
const projectRoot = findProjectRoot();
|
|
94
94
|
const localSettingsPath = `${projectRoot}/.claude/settings.local.json`;
|
|
95
95
|
const localSettings = readJsonFile(localSettingsPath);
|
|
96
|
-
// settings.local.json: enable flag only (API key from ~/.
|
|
96
|
+
// settings.local.json: enable flag only (API key from ~/.respan/)
|
|
97
97
|
const envBlock = {
|
|
98
98
|
TRACE_TO_RESPAN: 'true',
|
|
99
99
|
};
|
|
@@ -150,7 +150,7 @@ class IntegrateClaudeCode extends BaseCommand {
|
|
|
150
150
|
this.log('Claude Code tracing enabled for this project.');
|
|
151
151
|
}
|
|
152
152
|
this.log('');
|
|
153
|
-
this.log('Auth: ~/.
|
|
153
|
+
this.log('Auth: ~/.respan/credentials.json (from `respan auth login`)');
|
|
154
154
|
this.log('Config: .claude/respan.json (shareable, non-secret)');
|
|
155
155
|
this.log('');
|
|
156
156
|
this.log('Set properties via integrate flags or edit .claude/respan.json:');
|
|
@@ -33,17 +33,31 @@ class IntegrateCodexCli extends BaseCommand {
|
|
|
33
33
|
}
|
|
34
34
|
const otelResStr = toOtelResourceAttrs(resourceAttrs);
|
|
35
35
|
// Build TOML block
|
|
36
|
+
const endpoint = `${baseUrl}/v2/traces`;
|
|
36
37
|
const lines = [
|
|
37
38
|
'',
|
|
38
39
|
'# Respan observability (added by respan integrate codex-cli)',
|
|
39
40
|
'[otel]',
|
|
40
|
-
|
|
41
|
-
`api_key = "${apiKey}"`,
|
|
41
|
+
'log_user_prompt = true',
|
|
42
42
|
];
|
|
43
43
|
if (otelResStr) {
|
|
44
44
|
lines.push(`resource_attributes = "${otelResStr}"`);
|
|
45
45
|
}
|
|
46
46
|
lines.push('');
|
|
47
|
+
lines.push('[otel.exporter."otlp-http"]');
|
|
48
|
+
lines.push(`endpoint = "${endpoint}"`);
|
|
49
|
+
lines.push('protocol = "binary"');
|
|
50
|
+
lines.push('');
|
|
51
|
+
lines.push('[otel.exporter."otlp-http".headers]');
|
|
52
|
+
lines.push(`"Authorization" = "Bearer ${apiKey}"`);
|
|
53
|
+
lines.push('');
|
|
54
|
+
lines.push('[otel.trace_exporter."otlp-http"]');
|
|
55
|
+
lines.push(`endpoint = "${endpoint}"`);
|
|
56
|
+
lines.push('protocol = "binary"');
|
|
57
|
+
lines.push('');
|
|
58
|
+
lines.push('[otel.trace_exporter."otlp-http".headers]');
|
|
59
|
+
lines.push(`"Authorization" = "Bearer ${apiKey}"`);
|
|
60
|
+
lines.push('');
|
|
47
61
|
const block = lines.join('\n');
|
|
48
62
|
const updated = existing.trimEnd() + '\n' + block;
|
|
49
63
|
if (dryRun) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as path from 'node:path';
|
|
2
2
|
import { BaseCommand } from '../../lib/base-command.js';
|
|
3
|
-
import { integrateFlags, deepMerge, readJsonFile, writeJsonFile, expandHome, parseAttrs, toOtelResourceAttrs, resolveScope, findProjectRoot, } from '../../lib/integrate.js';
|
|
3
|
+
import { integrateFlags, deepMerge, readJsonFile, writeJsonFile, readTextFile, writeTextFile, expandHome, parseAttrs, toOtelResourceAttrs, resolveScope, findProjectRoot, } from '../../lib/integrate.js';
|
|
4
4
|
class IntegrateGeminiCli extends BaseCommand {
|
|
5
5
|
async run() {
|
|
6
6
|
const { flags } = await this.parse(IntegrateGeminiCli);
|
|
@@ -25,27 +25,48 @@ class IntegrateGeminiCli extends BaseCommand {
|
|
|
25
25
|
if (projectId) {
|
|
26
26
|
resourceAttrs['respan.project_id'] = projectId;
|
|
27
27
|
}
|
|
28
|
+
// settings.json — only telemetry fields Gemini CLI supports
|
|
28
29
|
const patch = {
|
|
29
30
|
telemetry: {
|
|
30
31
|
enabled: true,
|
|
31
32
|
otlpEndpoint: `${baseUrl}/v2/traces`,
|
|
32
|
-
|
|
33
|
-
Authorization: `Bearer ${apiKey}`,
|
|
34
|
-
},
|
|
33
|
+
otlpProtocol: 'http',
|
|
35
34
|
},
|
|
36
35
|
};
|
|
36
|
+
const merged = deepMerge(existing, patch);
|
|
37
|
+
// .env file — OTel SDK picks up headers & resource attrs from env
|
|
38
|
+
const envDir = scope === 'global'
|
|
39
|
+
? expandHome('~/.gemini')
|
|
40
|
+
: path.join(findProjectRoot(), '.gemini');
|
|
41
|
+
const envPath = path.join(envDir, '.env');
|
|
42
|
+
const envLines = [];
|
|
43
|
+
envLines.push(`OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer ${apiKey}`);
|
|
37
44
|
const otelResStr = toOtelResourceAttrs(resourceAttrs);
|
|
38
45
|
if (otelResStr) {
|
|
39
|
-
|
|
46
|
+
envLines.push(`OTEL_RESOURCE_ATTRIBUTES=${otelResStr}`);
|
|
40
47
|
}
|
|
41
|
-
|
|
48
|
+
// Merge with existing .env (replace our keys, keep the rest)
|
|
49
|
+
const existingEnv = readTextFile(envPath);
|
|
50
|
+
const envKeysToSet = new Set(envLines.map(l => l.split('=')[0]));
|
|
51
|
+
const keptLines = existingEnv
|
|
52
|
+
.split('\n')
|
|
53
|
+
.filter(line => {
|
|
54
|
+
const key = line.split('=')[0];
|
|
55
|
+
return !envKeysToSet.has(key);
|
|
56
|
+
});
|
|
57
|
+
const finalEnv = [...keptLines.filter(l => l.trim() !== ''), ...envLines].join('\n') + '\n';
|
|
42
58
|
if (dryRun) {
|
|
43
59
|
this.log(`[dry-run] Would update: ${settingsPath}`);
|
|
44
60
|
this.log(JSON.stringify(merged, null, 2));
|
|
61
|
+
this.log('');
|
|
62
|
+
this.log(`[dry-run] Would update: ${envPath}`);
|
|
63
|
+
this.log(finalEnv);
|
|
45
64
|
}
|
|
46
65
|
else {
|
|
47
66
|
writeJsonFile(settingsPath, merged);
|
|
48
67
|
this.log(`Updated settings: ${settingsPath}`);
|
|
68
|
+
writeTextFile(envPath, finalEnv);
|
|
69
|
+
this.log(`Updated env: ${envPath}`);
|
|
49
70
|
}
|
|
50
71
|
this.log('');
|
|
51
72
|
this.log(`Gemini CLI integration complete (${scope}).`);
|
package/dist/lib/config.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from 'node:fs';
|
|
2
2
|
import * as path from 'node:path';
|
|
3
3
|
import * as os from 'node:os';
|
|
4
|
-
const CONFIG_DIR = path.join(os.homedir(), '.
|
|
4
|
+
const CONFIG_DIR = path.join(os.homedir(), '.respan');
|
|
5
5
|
const CREDENTIALS_FILE = path.join(CONFIG_DIR, 'credentials.json');
|
|
6
6
|
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
7
7
|
function ensureConfigDir() {
|