@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.
@@ -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 ~/.config/respan/)
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 ~/.config/respan/)
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: ~/.config/respan/credentials.json (from `respan auth login`)');
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
- `endpoint = "${baseUrl}/v2/traces"`,
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
- headers: {
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
- patch.env = { OTEL_RESOURCE_ATTRIBUTES: otelResStr };
46
+ envLines.push(`OTEL_RESOURCE_ATTRIBUTES=${otelResStr}`);
40
47
  }
41
- const merged = deepMerge(existing, patch);
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}).`);
@@ -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(), '.config', 'respan');
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() {