@respan/cli 0.7.1 → 0.7.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/commands/integrate/claude-code.d.ts +2 -0
- package/dist/commands/integrate/claude-code.js +35 -5
- package/dist/commands/integrate/codex-cli.d.ts +2 -0
- package/dist/commands/integrate/codex-cli.js +23 -2
- package/dist/commands/integrate/gemini-cli.d.ts +2 -0
- package/dist/commands/integrate/gemini-cli.js +36 -4
- package/dist/commands/integrate/opencode.d.ts +2 -0
- package/dist/commands/integrate/opencode.js +25 -2
- package/dist/hooks/claude-code.cjs +3 -1
- package/dist/hooks/claude-code.js +1 -0
- package/dist/hooks/codex-cli.cjs +3 -1
- package/dist/hooks/codex-cli.js +1 -0
- package/dist/hooks/gemini-cli.cjs +3 -1
- package/dist/hooks/gemini-cli.js +1 -0
- package/dist/hooks/shared.d.ts +1 -0
- package/dist/hooks/shared.js +3 -1
- package/dist/lib/integrate.d.ts +2 -0
- package/dist/lib/integrate.js +10 -0
- package/oclif.manifest.json +337 -261
- package/package.json +10 -2
|
@@ -5,6 +5,8 @@ export default class IntegrateClaudeCode extends BaseCommand {
|
|
|
5
5
|
static flags: {
|
|
6
6
|
local: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
7
7
|
global: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
enable: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
|
+
disable: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
10
|
'project-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
11
|
'base-url': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
12
|
attrs: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -7,6 +7,37 @@ class IntegrateClaudeCode extends BaseCommand {
|
|
|
7
7
|
const { flags } = await this.parse(IntegrateClaudeCode);
|
|
8
8
|
this.globalFlags = flags;
|
|
9
9
|
try {
|
|
10
|
+
const dryRun = flags['dry-run'];
|
|
11
|
+
const scope = resolveScope(flags, 'both');
|
|
12
|
+
const doLocal = scope === 'local' || scope === 'both';
|
|
13
|
+
// ── Disable mode ─────────────────────────────────────────────
|
|
14
|
+
if (flags.disable) {
|
|
15
|
+
// Remove the Stop hook entry from global settings
|
|
16
|
+
const globalSettingsPath = expandHome('~/.claude/settings.json');
|
|
17
|
+
const globalSettings = readJsonFile(globalSettingsPath);
|
|
18
|
+
const hooksSection = (globalSettings.hooks || {});
|
|
19
|
+
if (Array.isArray(hooksSection.Stop)) {
|
|
20
|
+
hooksSection.Stop = hooksSection.Stop.filter((entry) => {
|
|
21
|
+
const inner = Array.isArray(entry.hooks)
|
|
22
|
+
? entry.hooks
|
|
23
|
+
: [];
|
|
24
|
+
return !inner.some((h) => typeof h.command === 'string' &&
|
|
25
|
+
(h.command.includes('respan') || h.command.includes('hook.py') || h.command.includes('claude-code')));
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
const merged = deepMerge(globalSettings, { hooks: hooksSection });
|
|
29
|
+
if (dryRun) {
|
|
30
|
+
this.log(`[dry-run] Would update: ${globalSettingsPath}`);
|
|
31
|
+
this.log(JSON.stringify(merged, null, 2));
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
writeJsonFile(globalSettingsPath, merged);
|
|
35
|
+
this.log(`Removed hook entry: ${globalSettingsPath}`);
|
|
36
|
+
}
|
|
37
|
+
this.log('Claude Code tracing disabled. Run "respan integrate claude-code" to re-enable.');
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
// ── Enable mode (default) ────────────────────────────────────
|
|
10
41
|
// Verify the user is authenticated (key is read by hook from ~/.respan/)
|
|
11
42
|
this.resolveApiKey();
|
|
12
43
|
const baseUrl = flags['base-url'];
|
|
@@ -15,11 +46,8 @@ class IntegrateClaudeCode extends BaseCommand {
|
|
|
15
46
|
const spanName = flags['span-name'];
|
|
16
47
|
const workflowName = flags['workflow-name'];
|
|
17
48
|
const attrs = parseAttrs(flags.attrs);
|
|
18
|
-
|
|
19
|
-
// Claude Code default: both global + local
|
|
20
|
-
const scope = resolveScope(flags, 'both');
|
|
49
|
+
// Claude Code default: both global + local.
|
|
21
50
|
const doGlobal = scope === 'global' || scope === 'both';
|
|
22
|
-
const doLocal = scope === 'local' || scope === 'both';
|
|
23
51
|
// ── Global: hook script + registration ────────────────────────
|
|
24
52
|
if (doGlobal) {
|
|
25
53
|
// 1. Write JS hook script (no Python dependency needed)
|
|
@@ -165,9 +193,11 @@ them to Respan as structured spans (chat, tool, thinking).
|
|
|
165
193
|
Scope:
|
|
166
194
|
--global Install hook script + register in ~/.claude/settings.json
|
|
167
195
|
--local Write credentials + enable flag to .claude/settings.local.json
|
|
168
|
-
|
|
196
|
+
|
|
197
|
+
Default behavior installs the global hook and writes local project config.`;
|
|
169
198
|
IntegrateClaudeCode.examples = [
|
|
170
199
|
'respan integrate claude-code',
|
|
200
|
+
'respan integrate claude-code --disable',
|
|
171
201
|
'respan integrate claude-code --global',
|
|
172
202
|
'respan integrate claude-code --local --project-id my-project',
|
|
173
203
|
'respan integrate claude-code --attrs \'{"env":"prod"}\'',
|
|
@@ -5,6 +5,8 @@ export default class IntegrateCodexCli extends BaseCommand {
|
|
|
5
5
|
static flags: {
|
|
6
6
|
local: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
7
7
|
global: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
enable: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
|
+
disable: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
10
|
'project-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
11
|
'base-url': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
12
|
attrs: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -6,6 +6,26 @@ class IntegrateCodexCli extends BaseCommand {
|
|
|
6
6
|
const { flags } = await this.parse(IntegrateCodexCli);
|
|
7
7
|
this.globalFlags = flags;
|
|
8
8
|
try {
|
|
9
|
+
const dryRun = flags['dry-run'];
|
|
10
|
+
// ── Disable mode ─────────────────────────────────────────────
|
|
11
|
+
if (flags.disable) {
|
|
12
|
+
// Remove the notify line from ~/.codex/config.toml
|
|
13
|
+
const configPath = expandHome('~/.codex/config.toml');
|
|
14
|
+
const existing = readTextFile(configPath);
|
|
15
|
+
const lines = existing.split('\n');
|
|
16
|
+
const filtered = lines.filter((line) => !/^\s*notify\s*=/.test(line) && !line.includes('respan integrate codex-cli'));
|
|
17
|
+
if (dryRun) {
|
|
18
|
+
this.log(`[dry-run] Would update: ${configPath}`);
|
|
19
|
+
this.log(filtered.join('\n'));
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
writeTextFile(configPath, filtered.join('\n'));
|
|
23
|
+
this.log(`Removed notify hook: ${configPath}`);
|
|
24
|
+
}
|
|
25
|
+
this.log('Codex CLI tracing disabled. Run "respan integrate codex-cli" to re-enable.');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
// ── Enable mode (default) ────────────────────────────────────
|
|
9
29
|
// Verify the user is authenticated (key is read by hook from ~/.respan/)
|
|
10
30
|
this.resolveApiKey();
|
|
11
31
|
const projectId = flags['project-id'];
|
|
@@ -13,7 +33,6 @@ class IntegrateCodexCli extends BaseCommand {
|
|
|
13
33
|
const spanName = flags['span-name'];
|
|
14
34
|
const workflowName = flags['workflow-name'];
|
|
15
35
|
const attrs = parseAttrs(flags.attrs);
|
|
16
|
-
const dryRun = flags['dry-run'];
|
|
17
36
|
// Codex CLI default: both global + local
|
|
18
37
|
const scope = resolveScope(flags, 'both');
|
|
19
38
|
const doGlobal = scope === 'global' || scope === 'both';
|
|
@@ -155,9 +174,11 @@ them to Respan as structured spans (chat, tool, reasoning).
|
|
|
155
174
|
Scope:
|
|
156
175
|
--global Install hook script + register notify in ~/.codex/config.toml
|
|
157
176
|
--local Write .codex/respan.json with customer_id, span_name, etc.
|
|
158
|
-
|
|
177
|
+
|
|
178
|
+
Default behavior installs the global notify hook and writes local project config.`;
|
|
159
179
|
IntegrateCodexCli.examples = [
|
|
160
180
|
'respan integrate codex-cli',
|
|
181
|
+
'respan integrate codex-cli --disable',
|
|
161
182
|
'respan integrate codex-cli --global',
|
|
162
183
|
'respan integrate codex-cli --local --customer-id frank',
|
|
163
184
|
'respan integrate codex-cli --attrs \'{"env":"prod"}\'',
|
|
@@ -5,6 +5,8 @@ export default class IntegrateGeminiCli extends BaseCommand {
|
|
|
5
5
|
static flags: {
|
|
6
6
|
local: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
7
7
|
global: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
enable: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
|
+
disable: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
10
|
'project-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
11
|
'base-url': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
12
|
attrs: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -7,6 +7,40 @@ class IntegrateGeminiCli extends BaseCommand {
|
|
|
7
7
|
const { flags } = await this.parse(IntegrateGeminiCli);
|
|
8
8
|
this.globalFlags = flags;
|
|
9
9
|
try {
|
|
10
|
+
const dryRun = flags['dry-run'];
|
|
11
|
+
const scope = resolveScope(flags, 'global');
|
|
12
|
+
// ── Disable mode ─────────────────────────────────────────────
|
|
13
|
+
if (flags.disable) {
|
|
14
|
+
// Remove respan hook entries from settings.json
|
|
15
|
+
const settingsPath = scope === 'global'
|
|
16
|
+
? expandHome('~/.gemini/settings.json')
|
|
17
|
+
: path.join(findProjectRoot(), '.gemini', 'settings.json');
|
|
18
|
+
const existing = readJsonFile(settingsPath);
|
|
19
|
+
const hooksSection = (existing.hooks || {});
|
|
20
|
+
for (const eventName of ['AfterModel', 'BeforeTool', 'AfterTool']) {
|
|
21
|
+
if (!Array.isArray(hooksSection[eventName]))
|
|
22
|
+
continue;
|
|
23
|
+
hooksSection[eventName] = hooksSection[eventName].filter((entry) => {
|
|
24
|
+
const inner = Array.isArray(entry.hooks)
|
|
25
|
+
? entry.hooks
|
|
26
|
+
: [];
|
|
27
|
+
return !inner.some((h) => typeof h.command === 'string' &&
|
|
28
|
+
(h.command.includes('respan') || h.command.includes('gemini-cli')));
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
const merged = { ...existing, hooks: hooksSection };
|
|
32
|
+
if (dryRun) {
|
|
33
|
+
this.log(`[dry-run] Would update: ${settingsPath}`);
|
|
34
|
+
this.log(JSON.stringify(merged, null, 2));
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
writeJsonFile(settingsPath, merged);
|
|
38
|
+
this.log(`Removed hook entries: ${settingsPath}`);
|
|
39
|
+
}
|
|
40
|
+
this.log('Gemini CLI tracing disabled. Run "respan integrate gemini-cli" to re-enable.');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
// ── Enable mode (default) ────────────────────────────────────
|
|
10
44
|
// Verify the user is authenticated (key is read by hook from ~/.respan/)
|
|
11
45
|
this.resolveApiKey();
|
|
12
46
|
const projectId = flags['project-id'];
|
|
@@ -14,8 +48,6 @@ class IntegrateGeminiCli extends BaseCommand {
|
|
|
14
48
|
const spanName = flags['span-name'];
|
|
15
49
|
const workflowName = flags['workflow-name'];
|
|
16
50
|
const attrs = parseAttrs(flags.attrs);
|
|
17
|
-
const dryRun = flags['dry-run'];
|
|
18
|
-
const scope = resolveScope(flags, 'global');
|
|
19
51
|
// ── 1. Install hook script ──────────────────────────────────
|
|
20
52
|
const hookDir = expandHome('~/.respan/hooks');
|
|
21
53
|
const hookPath = `${hookDir}/gemini-cli.cjs`;
|
|
@@ -142,10 +174,10 @@ Scope:
|
|
|
142
174
|
--global Write to ~/.gemini/settings.json (default)
|
|
143
175
|
--local Write to .gemini/settings.json in project root
|
|
144
176
|
|
|
145
|
-
|
|
146
|
-
--global is the default.`;
|
|
177
|
+
Gemini CLI ignores workspace-level telemetry settings, so --global is the default.`;
|
|
147
178
|
IntegrateGeminiCli.examples = [
|
|
148
179
|
'respan integrate gemini-cli',
|
|
180
|
+
'respan integrate gemini-cli --disable',
|
|
149
181
|
'respan integrate gemini-cli --local',
|
|
150
182
|
'respan integrate gemini-cli --project-id my-project --attrs \'{"env":"prod"}\'',
|
|
151
183
|
'respan integrate gemini-cli --dry-run',
|
|
@@ -5,6 +5,8 @@ export default class IntegrateOpencode extends BaseCommand {
|
|
|
5
5
|
static flags: {
|
|
6
6
|
local: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
7
7
|
global: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
enable: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
|
+
disable: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
10
|
'project-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
11
|
'base-url': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
12
|
attrs: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
1
2
|
import * as path from 'node:path';
|
|
2
3
|
import { execSync } from 'node:child_process';
|
|
3
4
|
import { BaseCommand } from '../../lib/base-command.js';
|
|
@@ -7,12 +8,33 @@ class IntegrateOpencode extends BaseCommand {
|
|
|
7
8
|
const { flags } = await this.parse(IntegrateOpencode);
|
|
8
9
|
this.globalFlags = flags;
|
|
9
10
|
try {
|
|
11
|
+
const dryRun = flags['dry-run'];
|
|
12
|
+
const scope = resolveScope(flags, 'local');
|
|
13
|
+
// ── Disable mode ─────────────────────────────────────────────
|
|
14
|
+
if (flags.disable) {
|
|
15
|
+
const pluginPath = scope === 'global'
|
|
16
|
+
? expandHome('~/.config/opencode/plugins/otel.json')
|
|
17
|
+
: path.join(findProjectRoot(), '.opencode', 'plugins', 'otel.json');
|
|
18
|
+
if (dryRun) {
|
|
19
|
+
this.log(`[dry-run] Would remove: ${pluginPath}`);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
try {
|
|
23
|
+
fs.unlinkSync(pluginPath);
|
|
24
|
+
this.log(`Removed plugin config: ${pluginPath}`);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
this.log(`No plugin config found at: ${pluginPath}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
this.log('OpenCode tracing disabled. Run with --enable to re-enable.');
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
// ── Enable mode (default) ────────────────────────────────────
|
|
10
34
|
const apiKey = this.resolveApiKey();
|
|
11
35
|
const baseUrl = (flags['base-url']).replace(/\/+$/, '');
|
|
12
36
|
const projectId = flags['project-id'];
|
|
13
37
|
const attrs = parseAttrs(flags.attrs);
|
|
14
|
-
const dryRun = flags['dry-run'];
|
|
15
|
-
const scope = resolveScope(flags, 'local');
|
|
16
38
|
// ── 1. Install opencode-otel (always global) ─────────────────
|
|
17
39
|
if (dryRun) {
|
|
18
40
|
this.log('[dry-run] Would run: npm install -g opencode-otel');
|
|
@@ -89,6 +111,7 @@ Scope:
|
|
|
89
111
|
The opencode-otel package is always installed globally.`;
|
|
90
112
|
IntegrateOpencode.examples = [
|
|
91
113
|
'respan integrate opencode',
|
|
114
|
+
'respan integrate opencode --disable',
|
|
92
115
|
'respan integrate opencode --global',
|
|
93
116
|
'respan integrate opencode --project-id my-project --attrs \'{"env":"prod"}\'',
|
|
94
117
|
'respan integrate opencode --dry-run',
|
|
@@ -280,6 +280,7 @@ function stringToSpanId(s) {
|
|
|
280
280
|
function toOtlpPayload(spans) {
|
|
281
281
|
const otlpSpans = spans.map((span) => {
|
|
282
282
|
const attrs = {};
|
|
283
|
+
if (span.session_identifier) attrs["respan.sessions.session_identifier"] = span.session_identifier;
|
|
283
284
|
if (span.thread_identifier) attrs["respan.threads.thread_identifier"] = span.thread_identifier;
|
|
284
285
|
if (span.customer_identifier) attrs["respan.customer_params.customer_identifier"] = span.customer_identifier;
|
|
285
286
|
if (span.span_workflow_name) attrs["traceloop.workflow.name"] = span.span_workflow_name;
|
|
@@ -340,7 +341,7 @@ function toOtlpPayload(spans) {
|
|
|
340
341
|
})
|
|
341
342
|
},
|
|
342
343
|
scopeSpans: [{
|
|
343
|
-
scope: { name: "respan-cli-hooks", version: "0.7.
|
|
344
|
+
scope: { name: "respan-cli-hooks", version: "0.7.1" },
|
|
344
345
|
spans: otlpSpans
|
|
345
346
|
}]
|
|
346
347
|
}]
|
|
@@ -599,6 +600,7 @@ function createSpans(sessionId, turnNum, userMsg, assistantMsgs, toolResults, co
|
|
|
599
600
|
const rootSpanId = `claudecode_${traceUniqueId}_root`;
|
|
600
601
|
spans.push({
|
|
601
602
|
trace_unique_id: traceUniqueId,
|
|
603
|
+
session_identifier: threadId,
|
|
602
604
|
thread_identifier: threadId,
|
|
603
605
|
customer_identifier: customerId,
|
|
604
606
|
span_unique_id: rootSpanId,
|
|
@@ -248,6 +248,7 @@ function createSpans(sessionId, turnNum, userMsg, assistantMsgs, toolResults, co
|
|
|
248
248
|
const rootSpanId = `claudecode_${traceUniqueId}_root`;
|
|
249
249
|
spans.push({
|
|
250
250
|
trace_unique_id: traceUniqueId,
|
|
251
|
+
session_identifier: threadId,
|
|
251
252
|
thread_identifier: threadId,
|
|
252
253
|
customer_identifier: customerId,
|
|
253
254
|
span_unique_id: rootSpanId,
|
package/dist/hooks/codex-cli.cjs
CHANGED
|
@@ -280,6 +280,7 @@ function stringToSpanId(s) {
|
|
|
280
280
|
function toOtlpPayload(spans) {
|
|
281
281
|
const otlpSpans = spans.map((span) => {
|
|
282
282
|
const attrs = {};
|
|
283
|
+
if (span.session_identifier) attrs["respan.sessions.session_identifier"] = span.session_identifier;
|
|
283
284
|
if (span.thread_identifier) attrs["respan.threads.thread_identifier"] = span.thread_identifier;
|
|
284
285
|
if (span.customer_identifier) attrs["respan.customer_params.customer_identifier"] = span.customer_identifier;
|
|
285
286
|
if (span.span_workflow_name) attrs["traceloop.workflow.name"] = span.span_workflow_name;
|
|
@@ -340,7 +341,7 @@ function toOtlpPayload(spans) {
|
|
|
340
341
|
})
|
|
341
342
|
},
|
|
342
343
|
scopeSpans: [{
|
|
343
|
-
scope: { name: "respan-cli-hooks", version: "0.7.
|
|
344
|
+
scope: { name: "respan-cli-hooks", version: "0.7.1" },
|
|
344
345
|
spans: otlpSpans
|
|
345
346
|
}]
|
|
346
347
|
}]
|
|
@@ -573,6 +574,7 @@ function createSpans(sessionId, turnNum, turn, config) {
|
|
|
573
574
|
const rootSpanId = `codexcli_${traceUniqueId}_root`;
|
|
574
575
|
spans.push({
|
|
575
576
|
trace_unique_id: traceUniqueId,
|
|
577
|
+
session_identifier: threadId,
|
|
576
578
|
thread_identifier: threadId,
|
|
577
579
|
customer_identifier: customerId,
|
|
578
580
|
span_unique_id: rootSpanId,
|
package/dist/hooks/codex-cli.js
CHANGED
|
@@ -222,6 +222,7 @@ function createSpans(sessionId, turnNum, turn, config) {
|
|
|
222
222
|
const rootSpanId = `codexcli_${traceUniqueId}_root`;
|
|
223
223
|
spans.push({
|
|
224
224
|
trace_unique_id: traceUniqueId,
|
|
225
|
+
session_identifier: threadId,
|
|
225
226
|
thread_identifier: threadId,
|
|
226
227
|
customer_identifier: customerId,
|
|
227
228
|
span_unique_id: rootSpanId,
|
|
@@ -258,6 +258,7 @@ function stringToSpanId(s) {
|
|
|
258
258
|
function toOtlpPayload(spans) {
|
|
259
259
|
const otlpSpans = spans.map((span) => {
|
|
260
260
|
const attrs = {};
|
|
261
|
+
if (span.session_identifier) attrs["respan.sessions.session_identifier"] = span.session_identifier;
|
|
261
262
|
if (span.thread_identifier) attrs["respan.threads.thread_identifier"] = span.thread_identifier;
|
|
262
263
|
if (span.customer_identifier) attrs["respan.customer_params.customer_identifier"] = span.customer_identifier;
|
|
263
264
|
if (span.span_workflow_name) attrs["traceloop.workflow.name"] = span.span_workflow_name;
|
|
@@ -318,7 +319,7 @@ function toOtlpPayload(spans) {
|
|
|
318
319
|
})
|
|
319
320
|
},
|
|
320
321
|
scopeSpans: [{
|
|
321
|
-
scope: { name: "respan-cli-hooks", version: "0.7.
|
|
322
|
+
scope: { name: "respan-cli-hooks", version: "0.7.1" },
|
|
322
323
|
spans: otlpSpans
|
|
323
324
|
}]
|
|
324
325
|
}]
|
|
@@ -492,6 +493,7 @@ function buildSpans(hookData, outputText, tokens, config, startTimeIso, toolTurn
|
|
|
492
493
|
const metadata = buildMetadata(config, baseMeta);
|
|
493
494
|
spans.push({
|
|
494
495
|
trace_unique_id: traceUniqueId,
|
|
496
|
+
session_identifier: threadId,
|
|
495
497
|
thread_identifier: threadId,
|
|
496
498
|
customer_identifier: customerId,
|
|
497
499
|
span_unique_id: rootSpanId,
|
package/dist/hooks/gemini-cli.js
CHANGED
|
@@ -201,6 +201,7 @@ function buildSpans(hookData, outputText, tokens, config, startTimeIso, toolTurn
|
|
|
201
201
|
// Root span
|
|
202
202
|
spans.push({
|
|
203
203
|
trace_unique_id: traceUniqueId,
|
|
204
|
+
session_identifier: threadId,
|
|
204
205
|
thread_identifier: threadId,
|
|
205
206
|
customer_identifier: customerId,
|
|
206
207
|
span_unique_id: rootSpanId,
|
package/dist/hooks/shared.d.ts
CHANGED
package/dist/hooks/shared.js
CHANGED
|
@@ -315,6 +315,8 @@ export function toOtlpPayload(spans) {
|
|
|
315
315
|
// Build OTEL-compatible attributes from SpanData fields
|
|
316
316
|
const attrs = {};
|
|
317
317
|
// Respan-specific attributes
|
|
318
|
+
if (span.session_identifier)
|
|
319
|
+
attrs['respan.sessions.session_identifier'] = span.session_identifier;
|
|
318
320
|
if (span.thread_identifier)
|
|
319
321
|
attrs['respan.threads.thread_identifier'] = span.thread_identifier;
|
|
320
322
|
if (span.customer_identifier)
|
|
@@ -395,7 +397,7 @@ export function toOtlpPayload(spans) {
|
|
|
395
397
|
}),
|
|
396
398
|
},
|
|
397
399
|
scopeSpans: [{
|
|
398
|
-
scope: { name: 'respan-cli-hooks', version: '0.7.
|
|
400
|
+
scope: { name: 'respan-cli-hooks', version: '0.7.1' },
|
|
399
401
|
spans: otlpSpans,
|
|
400
402
|
}],
|
|
401
403
|
}],
|
package/dist/lib/integrate.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ export declare const DEFAULT_BASE_URL = "https://api.respan.ai/api";
|
|
|
3
3
|
export declare const integrateFlags: {
|
|
4
4
|
local: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
5
5
|
global: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
6
|
+
enable: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
7
|
+
disable: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
6
8
|
'project-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
9
|
'base-url': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
10
|
attrs: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
package/dist/lib/integrate.js
CHANGED
|
@@ -19,6 +19,16 @@ export const integrateFlags = {
|
|
|
19
19
|
default: false,
|
|
20
20
|
exclusive: ['local'],
|
|
21
21
|
}),
|
|
22
|
+
enable: Flags.boolean({
|
|
23
|
+
description: 'Enable tracing (default)',
|
|
24
|
+
default: false,
|
|
25
|
+
exclusive: ['disable'],
|
|
26
|
+
}),
|
|
27
|
+
disable: Flags.boolean({
|
|
28
|
+
description: 'Disable tracing',
|
|
29
|
+
default: false,
|
|
30
|
+
exclusive: ['enable'],
|
|
31
|
+
}),
|
|
22
32
|
'project-id': Flags.string({
|
|
23
33
|
description: 'Respan project ID (added to metadata / resource attributes)',
|
|
24
34
|
env: 'RESPAN_PROJECT_ID',
|