@respan/cli 0.4.1 → 0.5.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.
- package/dist/assets/assets/hook.py +172 -37
- package/dist/commands/integrate/claude-code.d.ts +3 -0
- package/dist/commands/integrate/claude-code.js +46 -14
- package/dist/commands/integrate/codex-cli.d.ts +3 -0
- package/dist/commands/integrate/gemini-cli.d.ts +3 -0
- package/dist/commands/integrate/opencode.d.ts +3 -0
- package/dist/lib/integrate.d.ts +3 -0
- package/dist/lib/integrate.js +10 -0
- package/oclif.manifest.json +271 -183
- package/package.json +1 -1
|
@@ -81,6 +81,38 @@ def save_state(state: Dict[str, Any]) -> None:
|
|
|
81
81
|
STATE_FILE.write_text(json.dumps(state, indent=2), encoding="utf-8")
|
|
82
82
|
|
|
83
83
|
|
|
84
|
+
# Known config keys in respan.json that map to span fields.
|
|
85
|
+
# Anything else is treated as a custom property (goes into metadata).
|
|
86
|
+
KNOWN_CONFIG_KEYS = {"customer_id", "span_name", "workflow_name"}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def load_respan_config(cwd: str) -> Dict[str, Any]:
|
|
90
|
+
"""Load .claude/respan.json from the project directory.
|
|
91
|
+
|
|
92
|
+
Returns a dict with two keys:
|
|
93
|
+
- "fields": known span fields (customer_id, span_name, workflow_name)
|
|
94
|
+
- "properties": everything else (custom properties → metadata)
|
|
95
|
+
"""
|
|
96
|
+
config_path = Path(cwd) / ".claude" / "respan.json"
|
|
97
|
+
if not config_path.exists():
|
|
98
|
+
return {"fields": {}, "properties": {}}
|
|
99
|
+
try:
|
|
100
|
+
raw = json.loads(config_path.read_text(encoding="utf-8"))
|
|
101
|
+
if not isinstance(raw, dict):
|
|
102
|
+
return {"fields": {}, "properties": {}}
|
|
103
|
+
fields = {}
|
|
104
|
+
properties = {}
|
|
105
|
+
for k, v in raw.items():
|
|
106
|
+
if k in KNOWN_CONFIG_KEYS:
|
|
107
|
+
fields[k] = v
|
|
108
|
+
else:
|
|
109
|
+
properties[k] = v
|
|
110
|
+
return {"fields": fields, "properties": properties}
|
|
111
|
+
except (json.JSONDecodeError, IOError) as e:
|
|
112
|
+
debug(f"Failed to load respan.json from {config_path}: {e}")
|
|
113
|
+
return {"fields": {}, "properties": {}}
|
|
114
|
+
|
|
115
|
+
|
|
84
116
|
def get_content(msg: Dict[str, Any]) -> Any:
|
|
85
117
|
"""Extract content from a message."""
|
|
86
118
|
if isinstance(msg, dict):
|
|
@@ -317,6 +349,7 @@ def create_respan_spans(
|
|
|
317
349
|
user_msg: Dict[str, Any],
|
|
318
350
|
assistant_msgs: List[Dict[str, Any]],
|
|
319
351
|
tool_results: List[Dict[str, Any]],
|
|
352
|
+
config: Optional[Dict[str, Any]] = None,
|
|
320
353
|
) -> List[Dict[str, Any]]:
|
|
321
354
|
"""Create Respan span logs for a single turn with all available metadata.
|
|
322
355
|
|
|
@@ -395,16 +428,20 @@ def create_respan_spans(
|
|
|
395
428
|
if final_output:
|
|
396
429
|
completion_message = {"role": "assistant", "content": final_output}
|
|
397
430
|
|
|
398
|
-
# IDs
|
|
431
|
+
# IDs — respan.json fields, then env var overrides
|
|
432
|
+
cfg_fields = (config or {}).get("fields", {})
|
|
433
|
+
cfg_props = (config or {}).get("properties", {})
|
|
434
|
+
|
|
399
435
|
trace_unique_id = f"{session_id}_turn_{turn_num}"
|
|
400
|
-
workflow_name = "claude-code"
|
|
401
|
-
|
|
402
|
-
root_span_name = f"Turn {turn_num}: {user_preview}"
|
|
436
|
+
workflow_name = os.environ.get("RESPAN_WORKFLOW_NAME") or cfg_fields.get("workflow_name") or "claude-code"
|
|
437
|
+
root_span_name = os.environ.get("RESPAN_SPAN_NAME") or cfg_fields.get("span_name") or "claude-code"
|
|
403
438
|
thread_id = f"claudecode_{session_id}"
|
|
404
|
-
customer_id = os.environ.get("RESPAN_CUSTOMER_ID"
|
|
439
|
+
customer_id = os.environ.get("RESPAN_CUSTOMER_ID") or cfg_fields.get("customer_id") or ""
|
|
405
440
|
|
|
406
|
-
# Metadata
|
|
441
|
+
# Metadata — custom properties from respan.json, then env overrides
|
|
407
442
|
metadata: Dict[str, Any] = {"claude_code_turn": turn_num}
|
|
443
|
+
if cfg_props:
|
|
444
|
+
metadata.update(cfg_props)
|
|
408
445
|
if request_id:
|
|
409
446
|
metadata["request_id"] = request_id
|
|
410
447
|
if stop_reason:
|
|
@@ -454,8 +491,8 @@ def create_respan_spans(
|
|
|
454
491
|
"span_unique_id": root_span_id,
|
|
455
492
|
"span_name": root_span_name,
|
|
456
493
|
"span_workflow_name": workflow_name,
|
|
494
|
+
"model": model,
|
|
457
495
|
"span_path": "",
|
|
458
|
-
"log_type": "agent",
|
|
459
496
|
"input": json.dumps(prompt_messages) if prompt_messages else "",
|
|
460
497
|
"output": json.dumps(completion_message) if completion_message else "",
|
|
461
498
|
"timestamp": timestamp_str,
|
|
@@ -485,7 +522,6 @@ def create_respan_spans(
|
|
|
485
522
|
"span_name": "claude.chat",
|
|
486
523
|
"span_workflow_name": workflow_name,
|
|
487
524
|
"span_path": "claude_chat",
|
|
488
|
-
"log_type": "generation",
|
|
489
525
|
"model": model,
|
|
490
526
|
"provider_id": "anthropic",
|
|
491
527
|
"input": json.dumps(prompt_messages) if prompt_messages else "",
|
|
@@ -524,7 +560,6 @@ def create_respan_spans(
|
|
|
524
560
|
"span_name": f"Thinking {thinking_num}",
|
|
525
561
|
"span_workflow_name": workflow_name,
|
|
526
562
|
"span_path": "thinking",
|
|
527
|
-
"log_type": "generation",
|
|
528
563
|
"input": "",
|
|
529
564
|
"output": thinking_text,
|
|
530
565
|
"timestamp": thinking_ts,
|
|
@@ -575,7 +610,6 @@ def create_respan_spans(
|
|
|
575
610
|
"span_name": f"Tool: {td['name']}",
|
|
576
611
|
"span_workflow_name": workflow_name,
|
|
577
612
|
"span_path": f"tool_{td['name'].lower()}",
|
|
578
|
-
"log_type": "tool",
|
|
579
613
|
"input": format_tool_input(td["name"], td["input"]),
|
|
580
614
|
"output": format_tool_output(td["name"], td.get("output")),
|
|
581
615
|
"timestamp": tool_ts,
|
|
@@ -588,6 +622,26 @@ def create_respan_spans(
|
|
|
588
622
|
tool_span["latency"] = duration_ms / 1000.0
|
|
589
623
|
spans.append(tool_span)
|
|
590
624
|
|
|
625
|
+
# Add required Respan platform fields to every span.
|
|
626
|
+
# The backend expects these on all spans (per official SDK examples).
|
|
627
|
+
respan_defaults = {
|
|
628
|
+
"warnings": "",
|
|
629
|
+
"encoding_format": "float",
|
|
630
|
+
"disable_fallback": False,
|
|
631
|
+
"respan_params": {
|
|
632
|
+
"has_webhook": False,
|
|
633
|
+
"environment": os.environ.get("RESPAN_ENVIRONMENT", "prod"),
|
|
634
|
+
},
|
|
635
|
+
"field_name": "data: ",
|
|
636
|
+
"delimiter": "\n\n",
|
|
637
|
+
"disable_log": False,
|
|
638
|
+
"request_breakdown": False,
|
|
639
|
+
}
|
|
640
|
+
for span in spans:
|
|
641
|
+
for key, value in respan_defaults.items():
|
|
642
|
+
if key not in span:
|
|
643
|
+
span[key] = value
|
|
644
|
+
|
|
591
645
|
return spans
|
|
592
646
|
|
|
593
647
|
|
|
@@ -597,36 +651,49 @@ def send_spans(
|
|
|
597
651
|
base_url: str,
|
|
598
652
|
turn_num: int,
|
|
599
653
|
) -> None:
|
|
600
|
-
"""Send spans to Respan
|
|
654
|
+
"""Send spans to Respan as a single batch (matches official SDK behaviour).
|
|
655
|
+
|
|
656
|
+
The official Respan tracing SDK sends all spans for a trace in one
|
|
657
|
+
POST request to ``/v1/traces/ingest``. We do the same here, with
|
|
658
|
+
simple retry logic for transient server errors.
|
|
659
|
+
"""
|
|
601
660
|
url = f"{base_url}/v1/traces/ingest"
|
|
602
661
|
headers = {"Authorization": f"Bearer {api_key}"}
|
|
603
662
|
|
|
604
|
-
for
|
|
663
|
+
span_names = [s.get("span_name", "?") for s in spans]
|
|
664
|
+
payload_json = json.dumps(spans)
|
|
665
|
+
payload_size = len(payload_json)
|
|
666
|
+
debug(f"Sending {len(spans)} spans ({payload_size} bytes) for turn {turn_num}: {span_names}")
|
|
667
|
+
if DEBUG:
|
|
668
|
+
debug_file = LOG_FILE.parent / f"respan_spans_turn_{turn_num}.json"
|
|
669
|
+
debug_file.write_text(payload_json, encoding="utf-8")
|
|
670
|
+
debug(f"Dumped spans to {debug_file}")
|
|
671
|
+
|
|
672
|
+
for attempt in range(3):
|
|
605
673
|
try:
|
|
606
674
|
response = requests.post(url, json=spans, headers=headers, timeout=30)
|
|
607
675
|
if response.status_code < 400:
|
|
608
|
-
|
|
676
|
+
resp_text = response.text[:300] if response.text else ""
|
|
677
|
+
debug(f"Sent {len(spans)} spans for turn {turn_num} "
|
|
678
|
+
f"(attempt {attempt + 1}): {resp_text}")
|
|
609
679
|
return
|
|
610
680
|
if response.status_code < 500:
|
|
611
|
-
|
|
612
|
-
|
|
681
|
+
log("ERROR", f"Spans rejected for turn {turn_num}: "
|
|
682
|
+
f"HTTP {response.status_code} - {response.text[:200]}")
|
|
613
683
|
return
|
|
614
|
-
# 5xx —
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e:
|
|
621
|
-
if attempt == 0:
|
|
622
|
-
debug(f"Transient error for turn {turn_num}: {e}, retrying...")
|
|
623
|
-
time.sleep(1)
|
|
624
|
-
continue
|
|
625
|
-
log("ERROR", f"Failed to send spans for turn {turn_num} after retry: {e}")
|
|
684
|
+
# 5xx — retry after short delay
|
|
685
|
+
debug(f"Server error for turn {turn_num} "
|
|
686
|
+
f"(attempt {attempt + 1}), retrying...")
|
|
687
|
+
time.sleep(1.0)
|
|
688
|
+
except (requests.exceptions.Timeout, requests.exceptions.ConnectionError):
|
|
689
|
+
time.sleep(1.0)
|
|
626
690
|
except Exception as e:
|
|
627
691
|
log("ERROR", f"Failed to send spans for turn {turn_num}: {e}")
|
|
628
692
|
return
|
|
629
693
|
|
|
694
|
+
log("ERROR", f"Failed to send {len(spans)} spans for turn {turn_num} "
|
|
695
|
+
f"after 3 attempts")
|
|
696
|
+
|
|
630
697
|
|
|
631
698
|
def process_transcript(
|
|
632
699
|
session_id: str,
|
|
@@ -634,6 +701,7 @@ def process_transcript(
|
|
|
634
701
|
state: Dict[str, Any],
|
|
635
702
|
api_key: str,
|
|
636
703
|
base_url: str,
|
|
704
|
+
config: Optional[Dict[str, Any]] = None,
|
|
637
705
|
) -> int:
|
|
638
706
|
"""Process a transcript file and create traces for new turns."""
|
|
639
707
|
# Get previous state for this session
|
|
@@ -683,7 +751,8 @@ def process_transcript(
|
|
|
683
751
|
turns_processed += 1
|
|
684
752
|
turn_num = turn_count + turns_processed
|
|
685
753
|
spans = create_respan_spans(
|
|
686
|
-
session_id, turn_num, current_user, current_assistants, current_tool_results
|
|
754
|
+
session_id, turn_num, current_user, current_assistants, current_tool_results,
|
|
755
|
+
config=config,
|
|
687
756
|
)
|
|
688
757
|
send_spans(spans, api_key, base_url, turn_num)
|
|
689
758
|
last_committed_line = total_lines # safe default, refined below
|
|
@@ -745,8 +814,17 @@ def process_transcript(
|
|
|
745
814
|
current_assistants.append(merged)
|
|
746
815
|
|
|
747
816
|
if current_user and current_assistants:
|
|
748
|
-
|
|
749
|
-
|
|
817
|
+
# Check if the turn has actual text output. The Stop hook can fire
|
|
818
|
+
# before the final assistant text block is flushed to disk, leaving
|
|
819
|
+
# only thinking/tool_use blocks. If no text content is found, treat
|
|
820
|
+
# the turn as incomplete so the retry logic re-reads it.
|
|
821
|
+
has_text = any(get_text_content(m) for m in current_assistants)
|
|
822
|
+
if has_text:
|
|
823
|
+
_commit_turn()
|
|
824
|
+
last_committed_line = total_lines
|
|
825
|
+
else:
|
|
826
|
+
last_committed_line = current_user_line
|
|
827
|
+
debug(f"Turn has assistant msgs but no text output yet (likely not flushed), will retry")
|
|
750
828
|
else:
|
|
751
829
|
# Incomplete turn — rewind so the next run re-reads from the
|
|
752
830
|
# unmatched user message (or from where we left off if no user).
|
|
@@ -859,13 +937,32 @@ def main():
|
|
|
859
937
|
debug("Tracing disabled (TRACE_TO_RESPAN != true)")
|
|
860
938
|
sys.exit(0)
|
|
861
939
|
|
|
862
|
-
#
|
|
940
|
+
# Resolve API key: env var > ~/.config/respan/credentials.json
|
|
863
941
|
api_key = os.getenv("RESPAN_API_KEY")
|
|
864
|
-
# Default: api.respan.ai | Enterprise: endpoint.respan.ai (set RESPAN_BASE_URL)
|
|
865
942
|
base_url = os.getenv("RESPAN_BASE_URL", "https://api.respan.ai/api")
|
|
866
943
|
|
|
867
944
|
if not api_key:
|
|
868
|
-
|
|
945
|
+
creds_file = Path.home() / ".config" / "respan" / "credentials.json"
|
|
946
|
+
if creds_file.exists():
|
|
947
|
+
try:
|
|
948
|
+
creds = json.loads(creds_file.read_text(encoding="utf-8"))
|
|
949
|
+
# Find the active profile's credential
|
|
950
|
+
config_file = Path.home() / ".config" / "respan" / "config.json"
|
|
951
|
+
profile = "default"
|
|
952
|
+
if config_file.exists():
|
|
953
|
+
cfg = json.loads(config_file.read_text(encoding="utf-8"))
|
|
954
|
+
profile = cfg.get("activeProfile", "default")
|
|
955
|
+
cred = creds.get(profile, {})
|
|
956
|
+
api_key = cred.get("apiKey") or cred.get("accessToken")
|
|
957
|
+
if not base_url or base_url == "https://api.respan.ai/api":
|
|
958
|
+
base_url = cred.get("baseUrl", base_url)
|
|
959
|
+
if api_key:
|
|
960
|
+
debug(f"Using API key from credentials.json (profile: {profile})")
|
|
961
|
+
except (json.JSONDecodeError, IOError) as e:
|
|
962
|
+
debug(f"Failed to read credentials.json: {e}")
|
|
963
|
+
|
|
964
|
+
if not api_key:
|
|
965
|
+
log("ERROR", "No API key found. Run: respan auth login")
|
|
869
966
|
sys.exit(0)
|
|
870
967
|
|
|
871
968
|
# Try stdin payload first, fall back to filesystem scan
|
|
@@ -884,11 +981,49 @@ def main():
|
|
|
884
981
|
|
|
885
982
|
debug(f"Processing session: {session_id}")
|
|
886
983
|
|
|
887
|
-
#
|
|
984
|
+
# Load respan.json config from the project directory.
|
|
985
|
+
# Extract the project CWD from the first user message in the transcript.
|
|
986
|
+
config: Dict[str, Any] = {"fields": {}, "properties": {}}
|
|
987
|
+
try:
|
|
988
|
+
first_line = transcript_file.read_text(encoding="utf-8").split("\n")[0]
|
|
989
|
+
if first_line:
|
|
990
|
+
first_msg = json.loads(first_line)
|
|
991
|
+
cwd = first_msg.get("cwd")
|
|
992
|
+
if not cwd:
|
|
993
|
+
# Try second line (first is often file-history-snapshot)
|
|
994
|
+
lines = transcript_file.read_text(encoding="utf-8").split("\n")
|
|
995
|
+
for line in lines[:5]:
|
|
996
|
+
if line.strip():
|
|
997
|
+
msg = json.loads(line)
|
|
998
|
+
cwd = msg.get("cwd")
|
|
999
|
+
if cwd:
|
|
1000
|
+
break
|
|
1001
|
+
if cwd:
|
|
1002
|
+
config = load_respan_config(cwd)
|
|
1003
|
+
debug(f"Loaded respan.json config from {cwd}: {config}")
|
|
1004
|
+
except Exception as e:
|
|
1005
|
+
debug(f"Failed to extract CWD or load config: {e}")
|
|
1006
|
+
|
|
1007
|
+
# Process the transcript under file lock.
|
|
1008
|
+
# Retry up to 3 times with a short delay — the Stop hook can fire
|
|
1009
|
+
# before Claude Code finishes flushing the assistant response to
|
|
1010
|
+
# the transcript file, causing an incomplete turn on the first read.
|
|
1011
|
+
max_attempts = 3
|
|
1012
|
+
turns = 0
|
|
888
1013
|
try:
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
1014
|
+
for attempt in range(max_attempts):
|
|
1015
|
+
with state_lock():
|
|
1016
|
+
state = load_state()
|
|
1017
|
+
turns = process_transcript(session_id, transcript_file, state, api_key, base_url, config=config)
|
|
1018
|
+
|
|
1019
|
+
if turns > 0:
|
|
1020
|
+
break
|
|
1021
|
+
|
|
1022
|
+
if attempt < max_attempts - 1:
|
|
1023
|
+
delay = 0.5 * (attempt + 1)
|
|
1024
|
+
debug(f"No turns processed (attempt {attempt + 1}/{max_attempts}), "
|
|
1025
|
+
f"retrying in {delay}s...")
|
|
1026
|
+
time.sleep(delay)
|
|
892
1027
|
|
|
893
1028
|
# Log execution time
|
|
894
1029
|
duration = (datetime.now() - script_start).total_seconds()
|
|
@@ -8,6 +8,9 @@ export default class IntegrateClaudeCode extends BaseCommand {
|
|
|
8
8
|
'project-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
9
|
'base-url': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
10
|
attrs: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
'customer-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
'span-name': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
'workflow-name': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
14
|
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
15
|
'api-key': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
16
|
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import * as fs from 'node:fs';
|
|
2
2
|
import { execSync } from 'node:child_process';
|
|
3
3
|
import { BaseCommand } from '../../lib/base-command.js';
|
|
4
|
-
import { integrateFlags, deepMerge, readJsonFile, writeJsonFile, writeTextFile, expandHome, parseAttrs, getHookScript, resolveScope, findProjectRoot,
|
|
4
|
+
import { integrateFlags, deepMerge, readJsonFile, writeJsonFile, writeTextFile, expandHome, parseAttrs, getHookScript, resolveScope, findProjectRoot, } from '../../lib/integrate.js';
|
|
5
5
|
class IntegrateClaudeCode extends BaseCommand {
|
|
6
6
|
async run() {
|
|
7
7
|
const { flags } = await this.parse(IntegrateClaudeCode);
|
|
8
8
|
this.globalFlags = flags;
|
|
9
9
|
try {
|
|
10
|
-
|
|
10
|
+
// Verify the user is authenticated (key is read by hook from ~/.config/respan/)
|
|
11
|
+
this.resolveApiKey();
|
|
11
12
|
const baseUrl = flags['base-url'];
|
|
12
13
|
const projectId = flags['project-id'];
|
|
14
|
+
const customerId = flags['customer-id'];
|
|
15
|
+
const spanName = flags['span-name'];
|
|
16
|
+
const workflowName = flags['workflow-name'];
|
|
13
17
|
const attrs = parseAttrs(flags.attrs);
|
|
14
18
|
const dryRun = flags['dry-run'];
|
|
15
19
|
// Claude Code default: both global + local
|
|
@@ -89,20 +93,10 @@ class IntegrateClaudeCode extends BaseCommand {
|
|
|
89
93
|
const projectRoot = findProjectRoot();
|
|
90
94
|
const localSettingsPath = `${projectRoot}/.claude/settings.local.json`;
|
|
91
95
|
const localSettings = readJsonFile(localSettingsPath);
|
|
96
|
+
// settings.local.json: enable flag only (API key from ~/.config/respan/)
|
|
92
97
|
const envBlock = {
|
|
93
98
|
TRACE_TO_RESPAN: 'true',
|
|
94
|
-
RESPAN_API_KEY: apiKey,
|
|
95
99
|
};
|
|
96
|
-
if (baseUrl !== DEFAULT_BASE_URL) {
|
|
97
|
-
envBlock.RESPAN_BASE_URL = baseUrl;
|
|
98
|
-
}
|
|
99
|
-
const metadata = { ...attrs };
|
|
100
|
-
if (projectId) {
|
|
101
|
-
metadata.project_id = projectId;
|
|
102
|
-
}
|
|
103
|
-
if (Object.keys(metadata).length > 0) {
|
|
104
|
-
envBlock.RESPAN_METADATA = JSON.stringify(metadata);
|
|
105
|
-
}
|
|
106
100
|
const mergedLocal = deepMerge(localSettings, { env: envBlock });
|
|
107
101
|
if (dryRun) {
|
|
108
102
|
this.log(`[dry-run] Would update: ${localSettingsPath}`);
|
|
@@ -112,6 +106,36 @@ class IntegrateClaudeCode extends BaseCommand {
|
|
|
112
106
|
writeJsonFile(localSettingsPath, mergedLocal);
|
|
113
107
|
this.log(`Updated project settings: ${localSettingsPath}`);
|
|
114
108
|
}
|
|
109
|
+
// respan.json: non-secret config (known fields + custom properties)
|
|
110
|
+
const respanConfigPath = `${projectRoot}/.claude/respan.json`;
|
|
111
|
+
const respanConfig = readJsonFile(respanConfigPath);
|
|
112
|
+
const newConfig = { ...respanConfig };
|
|
113
|
+
if (customerId) {
|
|
114
|
+
newConfig.customer_id = customerId;
|
|
115
|
+
}
|
|
116
|
+
if (spanName) {
|
|
117
|
+
newConfig.span_name = spanName;
|
|
118
|
+
}
|
|
119
|
+
if (workflowName) {
|
|
120
|
+
newConfig.workflow_name = workflowName;
|
|
121
|
+
}
|
|
122
|
+
if (projectId) {
|
|
123
|
+
newConfig.project_id = projectId;
|
|
124
|
+
}
|
|
125
|
+
// Custom attrs go as top-level keys (unknown keys = custom properties)
|
|
126
|
+
for (const [k, v] of Object.entries(attrs)) {
|
|
127
|
+
newConfig[k] = v;
|
|
128
|
+
}
|
|
129
|
+
if (Object.keys(newConfig).length > 0) {
|
|
130
|
+
if (dryRun) {
|
|
131
|
+
this.log(`[dry-run] Would write: ${respanConfigPath}`);
|
|
132
|
+
this.log(JSON.stringify(newConfig, null, 2));
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
writeJsonFile(respanConfigPath, newConfig);
|
|
136
|
+
this.log(`Wrote Respan config: ${respanConfigPath}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
115
139
|
}
|
|
116
140
|
// ── Done ──────────────────────────────────────────────────────
|
|
117
141
|
this.log('');
|
|
@@ -126,7 +150,15 @@ class IntegrateClaudeCode extends BaseCommand {
|
|
|
126
150
|
this.log('Claude Code tracing enabled for this project.');
|
|
127
151
|
}
|
|
128
152
|
this.log('');
|
|
129
|
-
this.log('
|
|
153
|
+
this.log('Auth: ~/.config/respan/credentials.json (from `respan auth login`)');
|
|
154
|
+
this.log('Config: .claude/respan.json (shareable, non-secret)');
|
|
155
|
+
this.log('');
|
|
156
|
+
this.log('Set properties via integrate flags or edit .claude/respan.json:');
|
|
157
|
+
this.log(' respan integrate claude-code --customer-id "frank" --span-name "my-app"');
|
|
158
|
+
this.log(' respan integrate claude-code --attrs \'{"team":"platform","env":"staging"}\'');
|
|
159
|
+
this.log('');
|
|
160
|
+
this.log('Override per-session with env vars:');
|
|
161
|
+
this.log(' export RESPAN_CUSTOMER_ID="your-name"');
|
|
130
162
|
this.log(" export RESPAN_METADATA='{\"task_id\":\"T-123\"}'");
|
|
131
163
|
}
|
|
132
164
|
catch (error) {
|
|
@@ -8,6 +8,9 @@ export default class IntegrateCodexCli extends BaseCommand {
|
|
|
8
8
|
'project-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
9
|
'base-url': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
10
|
attrs: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
'customer-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
'span-name': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
'workflow-name': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
14
|
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
15
|
'api-key': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
16
|
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -8,6 +8,9 @@ export default class IntegrateGeminiCli extends BaseCommand {
|
|
|
8
8
|
'project-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
9
|
'base-url': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
10
|
attrs: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
'customer-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
'span-name': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
'workflow-name': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
14
|
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
15
|
'api-key': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
16
|
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -8,6 +8,9 @@ export default class IntegrateOpencode extends BaseCommand {
|
|
|
8
8
|
'project-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
9
|
'base-url': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
10
|
attrs: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
'customer-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
'span-name': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
'workflow-name': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
14
|
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
15
|
'api-key': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
16
|
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
package/dist/lib/integrate.d.ts
CHANGED
|
@@ -6,6 +6,9 @@ export declare const integrateFlags: {
|
|
|
6
6
|
'project-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
7
|
'base-url': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
8
|
attrs: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
'customer-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'span-name': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
'workflow-name': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
12
|
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
13
|
};
|
|
11
14
|
export type Scope = 'local' | 'global' | 'both';
|
package/dist/lib/integrate.js
CHANGED
|
@@ -31,6 +31,16 @@ export const integrateFlags = {
|
|
|
31
31
|
description: "Custom attributes JSON (e.g. '{\"env\":\"prod\"}')",
|
|
32
32
|
default: '{}',
|
|
33
33
|
}),
|
|
34
|
+
'customer-id': Flags.string({
|
|
35
|
+
description: 'Customer/user identifier for traces (e.g. your name or email)',
|
|
36
|
+
env: 'RESPAN_CUSTOMER_ID',
|
|
37
|
+
}),
|
|
38
|
+
'span-name': Flags.string({
|
|
39
|
+
description: 'Root span name for traces (default: claude-code)',
|
|
40
|
+
}),
|
|
41
|
+
'workflow-name': Flags.string({
|
|
42
|
+
description: 'Workflow name for traces (default: claude-code)',
|
|
43
|
+
}),
|
|
34
44
|
'dry-run': Flags.boolean({
|
|
35
45
|
description: 'Preview changes without writing files',
|
|
36
46
|
default: false,
|
package/oclif.manifest.json
CHANGED
|
@@ -428,16 +428,10 @@
|
|
|
428
428
|
"set.js"
|
|
429
429
|
]
|
|
430
430
|
},
|
|
431
|
-
"
|
|
431
|
+
"evaluators:create": {
|
|
432
432
|
"aliases": [],
|
|
433
|
-
"args": {
|
|
434
|
-
|
|
435
|
-
"description": "Dataset ID",
|
|
436
|
-
"name": "dataset-id",
|
|
437
|
-
"required": true
|
|
438
|
-
}
|
|
439
|
-
},
|
|
440
|
-
"description": "Add existing spans to a dataset",
|
|
433
|
+
"args": {},
|
|
434
|
+
"description": "Create a new evaluator",
|
|
441
435
|
"flags": {
|
|
442
436
|
"api-key": {
|
|
443
437
|
"description": "API key (env: RESPAN_API_KEY)",
|
|
@@ -473,18 +467,39 @@
|
|
|
473
467
|
"allowNo": false,
|
|
474
468
|
"type": "boolean"
|
|
475
469
|
},
|
|
476
|
-
"
|
|
477
|
-
"description": "
|
|
478
|
-
"name": "
|
|
470
|
+
"name": {
|
|
471
|
+
"description": "Evaluator name",
|
|
472
|
+
"name": "name",
|
|
479
473
|
"required": true,
|
|
480
474
|
"hasDynamicHelp": false,
|
|
481
475
|
"multiple": false,
|
|
482
476
|
"type": "option"
|
|
477
|
+
},
|
|
478
|
+
"type": {
|
|
479
|
+
"description": "Evaluator type",
|
|
480
|
+
"name": "type",
|
|
481
|
+
"hasDynamicHelp": false,
|
|
482
|
+
"multiple": false,
|
|
483
|
+
"type": "option"
|
|
484
|
+
},
|
|
485
|
+
"description": {
|
|
486
|
+
"description": "Evaluator description",
|
|
487
|
+
"name": "description",
|
|
488
|
+
"hasDynamicHelp": false,
|
|
489
|
+
"multiple": false,
|
|
490
|
+
"type": "option"
|
|
491
|
+
},
|
|
492
|
+
"config": {
|
|
493
|
+
"description": "Evaluator config as JSON string",
|
|
494
|
+
"name": "config",
|
|
495
|
+
"hasDynamicHelp": false,
|
|
496
|
+
"multiple": false,
|
|
497
|
+
"type": "option"
|
|
483
498
|
}
|
|
484
499
|
},
|
|
485
500
|
"hasDynamicHelp": false,
|
|
486
501
|
"hiddenAliases": [],
|
|
487
|
-
"id": "
|
|
502
|
+
"id": "evaluators:create",
|
|
488
503
|
"pluginAlias": "@respan/cli",
|
|
489
504
|
"pluginName": "@respan/cli",
|
|
490
505
|
"pluginType": "core",
|
|
@@ -494,20 +509,20 @@
|
|
|
494
509
|
"relativePath": [
|
|
495
510
|
"dist",
|
|
496
511
|
"commands",
|
|
497
|
-
"
|
|
498
|
-
"
|
|
512
|
+
"evaluators",
|
|
513
|
+
"create.js"
|
|
499
514
|
]
|
|
500
515
|
},
|
|
501
|
-
"
|
|
516
|
+
"evaluators:get": {
|
|
502
517
|
"aliases": [],
|
|
503
518
|
"args": {
|
|
504
|
-
"
|
|
505
|
-
"description": "
|
|
506
|
-
"name": "
|
|
519
|
+
"id": {
|
|
520
|
+
"description": "Evaluator ID",
|
|
521
|
+
"name": "id",
|
|
507
522
|
"required": true
|
|
508
523
|
}
|
|
509
524
|
},
|
|
510
|
-
"description": "
|
|
525
|
+
"description": "Get a specific evaluator",
|
|
511
526
|
"flags": {
|
|
512
527
|
"api-key": {
|
|
513
528
|
"description": "API key (env: RESPAN_API_KEY)",
|
|
@@ -542,19 +557,11 @@
|
|
|
542
557
|
"name": "verbose",
|
|
543
558
|
"allowNo": false,
|
|
544
559
|
"type": "boolean"
|
|
545
|
-
},
|
|
546
|
-
"body": {
|
|
547
|
-
"description": "Span body as JSON string",
|
|
548
|
-
"name": "body",
|
|
549
|
-
"required": true,
|
|
550
|
-
"hasDynamicHelp": false,
|
|
551
|
-
"multiple": false,
|
|
552
|
-
"type": "option"
|
|
553
560
|
}
|
|
554
561
|
},
|
|
555
562
|
"hasDynamicHelp": false,
|
|
556
563
|
"hiddenAliases": [],
|
|
557
|
-
"id": "
|
|
564
|
+
"id": "evaluators:get",
|
|
558
565
|
"pluginAlias": "@respan/cli",
|
|
559
566
|
"pluginName": "@respan/cli",
|
|
560
567
|
"pluginType": "core",
|
|
@@ -564,14 +571,14 @@
|
|
|
564
571
|
"relativePath": [
|
|
565
572
|
"dist",
|
|
566
573
|
"commands",
|
|
567
|
-
"
|
|
568
|
-
"
|
|
574
|
+
"evaluators",
|
|
575
|
+
"get.js"
|
|
569
576
|
]
|
|
570
577
|
},
|
|
571
|
-
"
|
|
578
|
+
"evaluators:list": {
|
|
572
579
|
"aliases": [],
|
|
573
580
|
"args": {},
|
|
574
|
-
"description": "
|
|
581
|
+
"description": "List evaluators",
|
|
575
582
|
"flags": {
|
|
576
583
|
"api-key": {
|
|
577
584
|
"description": "API key (env: RESPAN_API_KEY)",
|
|
@@ -607,17 +614,18 @@
|
|
|
607
614
|
"allowNo": false,
|
|
608
615
|
"type": "boolean"
|
|
609
616
|
},
|
|
610
|
-
"
|
|
611
|
-
"description": "
|
|
612
|
-
"name": "
|
|
613
|
-
"
|
|
617
|
+
"limit": {
|
|
618
|
+
"description": "Number of results per page",
|
|
619
|
+
"name": "limit",
|
|
620
|
+
"default": 20,
|
|
614
621
|
"hasDynamicHelp": false,
|
|
615
622
|
"multiple": false,
|
|
616
623
|
"type": "option"
|
|
617
624
|
},
|
|
618
|
-
"
|
|
619
|
-
"description": "
|
|
620
|
-
"name": "
|
|
625
|
+
"page": {
|
|
626
|
+
"description": "Page number",
|
|
627
|
+
"name": "page",
|
|
628
|
+
"default": 1,
|
|
621
629
|
"hasDynamicHelp": false,
|
|
622
630
|
"multiple": false,
|
|
623
631
|
"type": "option"
|
|
@@ -625,7 +633,7 @@
|
|
|
625
633
|
},
|
|
626
634
|
"hasDynamicHelp": false,
|
|
627
635
|
"hiddenAliases": [],
|
|
628
|
-
"id": "
|
|
636
|
+
"id": "evaluators:list",
|
|
629
637
|
"pluginAlias": "@respan/cli",
|
|
630
638
|
"pluginName": "@respan/cli",
|
|
631
639
|
"pluginType": "core",
|
|
@@ -635,25 +643,20 @@
|
|
|
635
643
|
"relativePath": [
|
|
636
644
|
"dist",
|
|
637
645
|
"commands",
|
|
638
|
-
"
|
|
639
|
-
"
|
|
646
|
+
"evaluators",
|
|
647
|
+
"list.js"
|
|
640
648
|
]
|
|
641
649
|
},
|
|
642
|
-
"
|
|
650
|
+
"evaluators:run": {
|
|
643
651
|
"aliases": [],
|
|
644
652
|
"args": {
|
|
645
|
-
"
|
|
646
|
-
"description": "
|
|
647
|
-
"name": "
|
|
648
|
-
"required": true
|
|
649
|
-
},
|
|
650
|
-
"span-id": {
|
|
651
|
-
"description": "Span ID",
|
|
652
|
-
"name": "span-id",
|
|
653
|
+
"id": {
|
|
654
|
+
"description": "Evaluator ID",
|
|
655
|
+
"name": "id",
|
|
653
656
|
"required": true
|
|
654
657
|
}
|
|
655
658
|
},
|
|
656
|
-
"description": "
|
|
659
|
+
"description": "Run an evaluator",
|
|
657
660
|
"flags": {
|
|
658
661
|
"api-key": {
|
|
659
662
|
"description": "API key (env: RESPAN_API_KEY)",
|
|
@@ -688,11 +691,32 @@
|
|
|
688
691
|
"name": "verbose",
|
|
689
692
|
"allowNo": false,
|
|
690
693
|
"type": "boolean"
|
|
694
|
+
},
|
|
695
|
+
"dataset-id": {
|
|
696
|
+
"description": "Dataset ID to evaluate against",
|
|
697
|
+
"name": "dataset-id",
|
|
698
|
+
"hasDynamicHelp": false,
|
|
699
|
+
"multiple": false,
|
|
700
|
+
"type": "option"
|
|
701
|
+
},
|
|
702
|
+
"log-ids": {
|
|
703
|
+
"description": "Comma-separated log/span IDs to evaluate",
|
|
704
|
+
"name": "log-ids",
|
|
705
|
+
"hasDynamicHelp": false,
|
|
706
|
+
"multiple": false,
|
|
707
|
+
"type": "option"
|
|
708
|
+
},
|
|
709
|
+
"params": {
|
|
710
|
+
"description": "Additional parameters as JSON string",
|
|
711
|
+
"name": "params",
|
|
712
|
+
"hasDynamicHelp": false,
|
|
713
|
+
"multiple": false,
|
|
714
|
+
"type": "option"
|
|
691
715
|
}
|
|
692
716
|
},
|
|
693
717
|
"hasDynamicHelp": false,
|
|
694
718
|
"hiddenAliases": [],
|
|
695
|
-
"id": "
|
|
719
|
+
"id": "evaluators:run",
|
|
696
720
|
"pluginAlias": "@respan/cli",
|
|
697
721
|
"pluginName": "@respan/cli",
|
|
698
722
|
"pluginType": "core",
|
|
@@ -702,20 +726,20 @@
|
|
|
702
726
|
"relativePath": [
|
|
703
727
|
"dist",
|
|
704
728
|
"commands",
|
|
705
|
-
"
|
|
706
|
-
"
|
|
729
|
+
"evaluators",
|
|
730
|
+
"run.js"
|
|
707
731
|
]
|
|
708
732
|
},
|
|
709
|
-
"
|
|
733
|
+
"evaluators:update": {
|
|
710
734
|
"aliases": [],
|
|
711
735
|
"args": {
|
|
712
736
|
"id": {
|
|
713
|
-
"description": "
|
|
737
|
+
"description": "Evaluator ID",
|
|
714
738
|
"name": "id",
|
|
715
739
|
"required": true
|
|
716
740
|
}
|
|
717
741
|
},
|
|
718
|
-
"description": "
|
|
742
|
+
"description": "Update an evaluator",
|
|
719
743
|
"flags": {
|
|
720
744
|
"api-key": {
|
|
721
745
|
"description": "API key (env: RESPAN_API_KEY)",
|
|
@@ -750,11 +774,32 @@
|
|
|
750
774
|
"name": "verbose",
|
|
751
775
|
"allowNo": false,
|
|
752
776
|
"type": "boolean"
|
|
777
|
+
},
|
|
778
|
+
"name": {
|
|
779
|
+
"description": "Evaluator name",
|
|
780
|
+
"name": "name",
|
|
781
|
+
"hasDynamicHelp": false,
|
|
782
|
+
"multiple": false,
|
|
783
|
+
"type": "option"
|
|
784
|
+
},
|
|
785
|
+
"description": {
|
|
786
|
+
"description": "Evaluator description",
|
|
787
|
+
"name": "description",
|
|
788
|
+
"hasDynamicHelp": false,
|
|
789
|
+
"multiple": false,
|
|
790
|
+
"type": "option"
|
|
791
|
+
},
|
|
792
|
+
"config": {
|
|
793
|
+
"description": "Evaluator config as JSON string",
|
|
794
|
+
"name": "config",
|
|
795
|
+
"hasDynamicHelp": false,
|
|
796
|
+
"multiple": false,
|
|
797
|
+
"type": "option"
|
|
753
798
|
}
|
|
754
799
|
},
|
|
755
800
|
"hasDynamicHelp": false,
|
|
756
801
|
"hiddenAliases": [],
|
|
757
|
-
"id": "
|
|
802
|
+
"id": "evaluators:update",
|
|
758
803
|
"pluginAlias": "@respan/cli",
|
|
759
804
|
"pluginName": "@respan/cli",
|
|
760
805
|
"pluginType": "core",
|
|
@@ -764,14 +809,20 @@
|
|
|
764
809
|
"relativePath": [
|
|
765
810
|
"dist",
|
|
766
811
|
"commands",
|
|
767
|
-
"
|
|
768
|
-
"
|
|
812
|
+
"evaluators",
|
|
813
|
+
"update.js"
|
|
769
814
|
]
|
|
770
815
|
},
|
|
771
|
-
"datasets:
|
|
816
|
+
"datasets:add-spans": {
|
|
772
817
|
"aliases": [],
|
|
773
|
-
"args": {
|
|
774
|
-
|
|
818
|
+
"args": {
|
|
819
|
+
"dataset-id": {
|
|
820
|
+
"description": "Dataset ID",
|
|
821
|
+
"name": "dataset-id",
|
|
822
|
+
"required": true
|
|
823
|
+
}
|
|
824
|
+
},
|
|
825
|
+
"description": "Add existing spans to a dataset",
|
|
775
826
|
"flags": {
|
|
776
827
|
"api-key": {
|
|
777
828
|
"description": "API key (env: RESPAN_API_KEY)",
|
|
@@ -807,18 +858,10 @@
|
|
|
807
858
|
"allowNo": false,
|
|
808
859
|
"type": "boolean"
|
|
809
860
|
},
|
|
810
|
-
"
|
|
811
|
-
"description": "
|
|
812
|
-
"name": "
|
|
813
|
-
"
|
|
814
|
-
"hasDynamicHelp": false,
|
|
815
|
-
"multiple": false,
|
|
816
|
-
"type": "option"
|
|
817
|
-
},
|
|
818
|
-
"page": {
|
|
819
|
-
"description": "Page number",
|
|
820
|
-
"name": "page",
|
|
821
|
-
"default": 1,
|
|
861
|
+
"span-ids": {
|
|
862
|
+
"description": "Comma-separated span IDs",
|
|
863
|
+
"name": "span-ids",
|
|
864
|
+
"required": true,
|
|
822
865
|
"hasDynamicHelp": false,
|
|
823
866
|
"multiple": false,
|
|
824
867
|
"type": "option"
|
|
@@ -826,7 +869,7 @@
|
|
|
826
869
|
},
|
|
827
870
|
"hasDynamicHelp": false,
|
|
828
871
|
"hiddenAliases": [],
|
|
829
|
-
"id": "datasets:
|
|
872
|
+
"id": "datasets:add-spans",
|
|
830
873
|
"pluginAlias": "@respan/cli",
|
|
831
874
|
"pluginName": "@respan/cli",
|
|
832
875
|
"pluginType": "core",
|
|
@@ -837,10 +880,10 @@
|
|
|
837
880
|
"dist",
|
|
838
881
|
"commands",
|
|
839
882
|
"datasets",
|
|
840
|
-
"
|
|
883
|
+
"add-spans.js"
|
|
841
884
|
]
|
|
842
885
|
},
|
|
843
|
-
"datasets:
|
|
886
|
+
"datasets:create-span": {
|
|
844
887
|
"aliases": [],
|
|
845
888
|
"args": {
|
|
846
889
|
"dataset-id": {
|
|
@@ -849,7 +892,7 @@
|
|
|
849
892
|
"required": true
|
|
850
893
|
}
|
|
851
894
|
},
|
|
852
|
-
"description": "
|
|
895
|
+
"description": "Create a span in a dataset",
|
|
853
896
|
"flags": {
|
|
854
897
|
"api-key": {
|
|
855
898
|
"description": "API key (env: RESPAN_API_KEY)",
|
|
@@ -884,11 +927,19 @@
|
|
|
884
927
|
"name": "verbose",
|
|
885
928
|
"allowNo": false,
|
|
886
929
|
"type": "boolean"
|
|
930
|
+
},
|
|
931
|
+
"body": {
|
|
932
|
+
"description": "Span body as JSON string",
|
|
933
|
+
"name": "body",
|
|
934
|
+
"required": true,
|
|
935
|
+
"hasDynamicHelp": false,
|
|
936
|
+
"multiple": false,
|
|
937
|
+
"type": "option"
|
|
887
938
|
}
|
|
888
939
|
},
|
|
889
940
|
"hasDynamicHelp": false,
|
|
890
941
|
"hiddenAliases": [],
|
|
891
|
-
"id": "datasets:
|
|
942
|
+
"id": "datasets:create-span",
|
|
892
943
|
"pluginAlias": "@respan/cli",
|
|
893
944
|
"pluginName": "@respan/cli",
|
|
894
945
|
"pluginType": "core",
|
|
@@ -899,19 +950,13 @@
|
|
|
899
950
|
"dist",
|
|
900
951
|
"commands",
|
|
901
952
|
"datasets",
|
|
902
|
-
"
|
|
953
|
+
"create-span.js"
|
|
903
954
|
]
|
|
904
955
|
},
|
|
905
|
-
"datasets:
|
|
956
|
+
"datasets:create": {
|
|
906
957
|
"aliases": [],
|
|
907
|
-
"args": {
|
|
908
|
-
|
|
909
|
-
"description": "Dataset ID",
|
|
910
|
-
"name": "id",
|
|
911
|
-
"required": true
|
|
912
|
-
}
|
|
913
|
-
},
|
|
914
|
-
"description": "Update a dataset",
|
|
958
|
+
"args": {},
|
|
959
|
+
"description": "Create a new dataset",
|
|
915
960
|
"flags": {
|
|
916
961
|
"api-key": {
|
|
917
962
|
"description": "API key (env: RESPAN_API_KEY)",
|
|
@@ -950,6 +995,7 @@
|
|
|
950
995
|
"name": {
|
|
951
996
|
"description": "Dataset name",
|
|
952
997
|
"name": "name",
|
|
998
|
+
"required": true,
|
|
953
999
|
"hasDynamicHelp": false,
|
|
954
1000
|
"multiple": false,
|
|
955
1001
|
"type": "option"
|
|
@@ -964,7 +1010,7 @@
|
|
|
964
1010
|
},
|
|
965
1011
|
"hasDynamicHelp": false,
|
|
966
1012
|
"hiddenAliases": [],
|
|
967
|
-
"id": "datasets:
|
|
1013
|
+
"id": "datasets:create",
|
|
968
1014
|
"pluginAlias": "@respan/cli",
|
|
969
1015
|
"pluginName": "@respan/cli",
|
|
970
1016
|
"pluginType": "core",
|
|
@@ -975,13 +1021,24 @@
|
|
|
975
1021
|
"dist",
|
|
976
1022
|
"commands",
|
|
977
1023
|
"datasets",
|
|
978
|
-
"
|
|
1024
|
+
"create.js"
|
|
979
1025
|
]
|
|
980
1026
|
},
|
|
981
|
-
"
|
|
1027
|
+
"datasets:get-span": {
|
|
982
1028
|
"aliases": [],
|
|
983
|
-
"args": {
|
|
984
|
-
|
|
1029
|
+
"args": {
|
|
1030
|
+
"dataset-id": {
|
|
1031
|
+
"description": "Dataset ID",
|
|
1032
|
+
"name": "dataset-id",
|
|
1033
|
+
"required": true
|
|
1034
|
+
},
|
|
1035
|
+
"span-id": {
|
|
1036
|
+
"description": "Span ID",
|
|
1037
|
+
"name": "span-id",
|
|
1038
|
+
"required": true
|
|
1039
|
+
}
|
|
1040
|
+
},
|
|
1041
|
+
"description": "Get a specific span from a dataset",
|
|
985
1042
|
"flags": {
|
|
986
1043
|
"api-key": {
|
|
987
1044
|
"description": "API key (env: RESPAN_API_KEY)",
|
|
@@ -1016,40 +1073,11 @@
|
|
|
1016
1073
|
"name": "verbose",
|
|
1017
1074
|
"allowNo": false,
|
|
1018
1075
|
"type": "boolean"
|
|
1019
|
-
},
|
|
1020
|
-
"name": {
|
|
1021
|
-
"description": "Evaluator name",
|
|
1022
|
-
"name": "name",
|
|
1023
|
-
"required": true,
|
|
1024
|
-
"hasDynamicHelp": false,
|
|
1025
|
-
"multiple": false,
|
|
1026
|
-
"type": "option"
|
|
1027
|
-
},
|
|
1028
|
-
"type": {
|
|
1029
|
-
"description": "Evaluator type",
|
|
1030
|
-
"name": "type",
|
|
1031
|
-
"hasDynamicHelp": false,
|
|
1032
|
-
"multiple": false,
|
|
1033
|
-
"type": "option"
|
|
1034
|
-
},
|
|
1035
|
-
"description": {
|
|
1036
|
-
"description": "Evaluator description",
|
|
1037
|
-
"name": "description",
|
|
1038
|
-
"hasDynamicHelp": false,
|
|
1039
|
-
"multiple": false,
|
|
1040
|
-
"type": "option"
|
|
1041
|
-
},
|
|
1042
|
-
"config": {
|
|
1043
|
-
"description": "Evaluator config as JSON string",
|
|
1044
|
-
"name": "config",
|
|
1045
|
-
"hasDynamicHelp": false,
|
|
1046
|
-
"multiple": false,
|
|
1047
|
-
"type": "option"
|
|
1048
1076
|
}
|
|
1049
1077
|
},
|
|
1050
1078
|
"hasDynamicHelp": false,
|
|
1051
1079
|
"hiddenAliases": [],
|
|
1052
|
-
"id": "
|
|
1080
|
+
"id": "datasets:get-span",
|
|
1053
1081
|
"pluginAlias": "@respan/cli",
|
|
1054
1082
|
"pluginName": "@respan/cli",
|
|
1055
1083
|
"pluginType": "core",
|
|
@@ -1059,20 +1087,20 @@
|
|
|
1059
1087
|
"relativePath": [
|
|
1060
1088
|
"dist",
|
|
1061
1089
|
"commands",
|
|
1062
|
-
"
|
|
1063
|
-
"
|
|
1090
|
+
"datasets",
|
|
1091
|
+
"get-span.js"
|
|
1064
1092
|
]
|
|
1065
1093
|
},
|
|
1066
|
-
"
|
|
1094
|
+
"datasets:get": {
|
|
1067
1095
|
"aliases": [],
|
|
1068
1096
|
"args": {
|
|
1069
1097
|
"id": {
|
|
1070
|
-
"description": "
|
|
1098
|
+
"description": "Dataset ID",
|
|
1071
1099
|
"name": "id",
|
|
1072
1100
|
"required": true
|
|
1073
1101
|
}
|
|
1074
1102
|
},
|
|
1075
|
-
"description": "Get a specific
|
|
1103
|
+
"description": "Get a specific dataset",
|
|
1076
1104
|
"flags": {
|
|
1077
1105
|
"api-key": {
|
|
1078
1106
|
"description": "API key (env: RESPAN_API_KEY)",
|
|
@@ -1111,7 +1139,7 @@
|
|
|
1111
1139
|
},
|
|
1112
1140
|
"hasDynamicHelp": false,
|
|
1113
1141
|
"hiddenAliases": [],
|
|
1114
|
-
"id": "
|
|
1142
|
+
"id": "datasets:get",
|
|
1115
1143
|
"pluginAlias": "@respan/cli",
|
|
1116
1144
|
"pluginName": "@respan/cli",
|
|
1117
1145
|
"pluginType": "core",
|
|
@@ -1121,14 +1149,14 @@
|
|
|
1121
1149
|
"relativePath": [
|
|
1122
1150
|
"dist",
|
|
1123
1151
|
"commands",
|
|
1124
|
-
"
|
|
1152
|
+
"datasets",
|
|
1125
1153
|
"get.js"
|
|
1126
1154
|
]
|
|
1127
1155
|
},
|
|
1128
|
-
"
|
|
1156
|
+
"datasets:list": {
|
|
1129
1157
|
"aliases": [],
|
|
1130
1158
|
"args": {},
|
|
1131
|
-
"description": "List
|
|
1159
|
+
"description": "List datasets",
|
|
1132
1160
|
"flags": {
|
|
1133
1161
|
"api-key": {
|
|
1134
1162
|
"description": "API key (env: RESPAN_API_KEY)",
|
|
@@ -1167,7 +1195,7 @@
|
|
|
1167
1195
|
"limit": {
|
|
1168
1196
|
"description": "Number of results per page",
|
|
1169
1197
|
"name": "limit",
|
|
1170
|
-
"default":
|
|
1198
|
+
"default": 50,
|
|
1171
1199
|
"hasDynamicHelp": false,
|
|
1172
1200
|
"multiple": false,
|
|
1173
1201
|
"type": "option"
|
|
@@ -1183,7 +1211,7 @@
|
|
|
1183
1211
|
},
|
|
1184
1212
|
"hasDynamicHelp": false,
|
|
1185
1213
|
"hiddenAliases": [],
|
|
1186
|
-
"id": "
|
|
1214
|
+
"id": "datasets:list",
|
|
1187
1215
|
"pluginAlias": "@respan/cli",
|
|
1188
1216
|
"pluginName": "@respan/cli",
|
|
1189
1217
|
"pluginType": "core",
|
|
@@ -1193,20 +1221,20 @@
|
|
|
1193
1221
|
"relativePath": [
|
|
1194
1222
|
"dist",
|
|
1195
1223
|
"commands",
|
|
1196
|
-
"
|
|
1224
|
+
"datasets",
|
|
1197
1225
|
"list.js"
|
|
1198
1226
|
]
|
|
1199
1227
|
},
|
|
1200
|
-
"
|
|
1228
|
+
"datasets:spans": {
|
|
1201
1229
|
"aliases": [],
|
|
1202
1230
|
"args": {
|
|
1203
|
-
"id": {
|
|
1204
|
-
"description": "
|
|
1205
|
-
"name": "id",
|
|
1231
|
+
"dataset-id": {
|
|
1232
|
+
"description": "Dataset ID",
|
|
1233
|
+
"name": "dataset-id",
|
|
1206
1234
|
"required": true
|
|
1207
1235
|
}
|
|
1208
1236
|
},
|
|
1209
|
-
"description": "
|
|
1237
|
+
"description": "List spans in a dataset",
|
|
1210
1238
|
"flags": {
|
|
1211
1239
|
"api-key": {
|
|
1212
1240
|
"description": "API key (env: RESPAN_API_KEY)",
|
|
@@ -1241,32 +1269,11 @@
|
|
|
1241
1269
|
"name": "verbose",
|
|
1242
1270
|
"allowNo": false,
|
|
1243
1271
|
"type": "boolean"
|
|
1244
|
-
},
|
|
1245
|
-
"dataset-id": {
|
|
1246
|
-
"description": "Dataset ID to evaluate against",
|
|
1247
|
-
"name": "dataset-id",
|
|
1248
|
-
"hasDynamicHelp": false,
|
|
1249
|
-
"multiple": false,
|
|
1250
|
-
"type": "option"
|
|
1251
|
-
},
|
|
1252
|
-
"log-ids": {
|
|
1253
|
-
"description": "Comma-separated log/span IDs to evaluate",
|
|
1254
|
-
"name": "log-ids",
|
|
1255
|
-
"hasDynamicHelp": false,
|
|
1256
|
-
"multiple": false,
|
|
1257
|
-
"type": "option"
|
|
1258
|
-
},
|
|
1259
|
-
"params": {
|
|
1260
|
-
"description": "Additional parameters as JSON string",
|
|
1261
|
-
"name": "params",
|
|
1262
|
-
"hasDynamicHelp": false,
|
|
1263
|
-
"multiple": false,
|
|
1264
|
-
"type": "option"
|
|
1265
1272
|
}
|
|
1266
1273
|
},
|
|
1267
1274
|
"hasDynamicHelp": false,
|
|
1268
1275
|
"hiddenAliases": [],
|
|
1269
|
-
"id": "
|
|
1276
|
+
"id": "datasets:spans",
|
|
1270
1277
|
"pluginAlias": "@respan/cli",
|
|
1271
1278
|
"pluginName": "@respan/cli",
|
|
1272
1279
|
"pluginType": "core",
|
|
@@ -1276,20 +1283,20 @@
|
|
|
1276
1283
|
"relativePath": [
|
|
1277
1284
|
"dist",
|
|
1278
1285
|
"commands",
|
|
1279
|
-
"
|
|
1280
|
-
"
|
|
1286
|
+
"datasets",
|
|
1287
|
+
"spans.js"
|
|
1281
1288
|
]
|
|
1282
1289
|
},
|
|
1283
|
-
"
|
|
1290
|
+
"datasets:update": {
|
|
1284
1291
|
"aliases": [],
|
|
1285
1292
|
"args": {
|
|
1286
1293
|
"id": {
|
|
1287
|
-
"description": "
|
|
1294
|
+
"description": "Dataset ID",
|
|
1288
1295
|
"name": "id",
|
|
1289
1296
|
"required": true
|
|
1290
1297
|
}
|
|
1291
1298
|
},
|
|
1292
|
-
"description": "Update
|
|
1299
|
+
"description": "Update a dataset",
|
|
1293
1300
|
"flags": {
|
|
1294
1301
|
"api-key": {
|
|
1295
1302
|
"description": "API key (env: RESPAN_API_KEY)",
|
|
@@ -1326,30 +1333,23 @@
|
|
|
1326
1333
|
"type": "boolean"
|
|
1327
1334
|
},
|
|
1328
1335
|
"name": {
|
|
1329
|
-
"description": "
|
|
1336
|
+
"description": "Dataset name",
|
|
1330
1337
|
"name": "name",
|
|
1331
1338
|
"hasDynamicHelp": false,
|
|
1332
1339
|
"multiple": false,
|
|
1333
1340
|
"type": "option"
|
|
1334
1341
|
},
|
|
1335
1342
|
"description": {
|
|
1336
|
-
"description": "
|
|
1343
|
+
"description": "Dataset description",
|
|
1337
1344
|
"name": "description",
|
|
1338
1345
|
"hasDynamicHelp": false,
|
|
1339
1346
|
"multiple": false,
|
|
1340
1347
|
"type": "option"
|
|
1341
|
-
},
|
|
1342
|
-
"config": {
|
|
1343
|
-
"description": "Evaluator config as JSON string",
|
|
1344
|
-
"name": "config",
|
|
1345
|
-
"hasDynamicHelp": false,
|
|
1346
|
-
"multiple": false,
|
|
1347
|
-
"type": "option"
|
|
1348
1348
|
}
|
|
1349
1349
|
},
|
|
1350
1350
|
"hasDynamicHelp": false,
|
|
1351
1351
|
"hiddenAliases": [],
|
|
1352
|
-
"id": "
|
|
1352
|
+
"id": "datasets:update",
|
|
1353
1353
|
"pluginAlias": "@respan/cli",
|
|
1354
1354
|
"pluginName": "@respan/cli",
|
|
1355
1355
|
"pluginType": "core",
|
|
@@ -1359,7 +1359,7 @@
|
|
|
1359
1359
|
"relativePath": [
|
|
1360
1360
|
"dist",
|
|
1361
1361
|
"commands",
|
|
1362
|
-
"
|
|
1362
|
+
"datasets",
|
|
1363
1363
|
"update.js"
|
|
1364
1364
|
]
|
|
1365
1365
|
},
|
|
@@ -1671,6 +1671,28 @@
|
|
|
1671
1671
|
"multiple": false,
|
|
1672
1672
|
"type": "option"
|
|
1673
1673
|
},
|
|
1674
|
+
"customer-id": {
|
|
1675
|
+
"description": "Customer/user identifier for traces (e.g. your name or email)",
|
|
1676
|
+
"env": "RESPAN_CUSTOMER_ID",
|
|
1677
|
+
"name": "customer-id",
|
|
1678
|
+
"hasDynamicHelp": false,
|
|
1679
|
+
"multiple": false,
|
|
1680
|
+
"type": "option"
|
|
1681
|
+
},
|
|
1682
|
+
"span-name": {
|
|
1683
|
+
"description": "Root span name for traces (default: claude-code)",
|
|
1684
|
+
"name": "span-name",
|
|
1685
|
+
"hasDynamicHelp": false,
|
|
1686
|
+
"multiple": false,
|
|
1687
|
+
"type": "option"
|
|
1688
|
+
},
|
|
1689
|
+
"workflow-name": {
|
|
1690
|
+
"description": "Workflow name for traces (default: claude-code)",
|
|
1691
|
+
"name": "workflow-name",
|
|
1692
|
+
"hasDynamicHelp": false,
|
|
1693
|
+
"multiple": false,
|
|
1694
|
+
"type": "option"
|
|
1695
|
+
},
|
|
1674
1696
|
"dry-run": {
|
|
1675
1697
|
"description": "Preview changes without writing files",
|
|
1676
1698
|
"name": "dry-run",
|
|
@@ -1781,6 +1803,28 @@
|
|
|
1781
1803
|
"multiple": false,
|
|
1782
1804
|
"type": "option"
|
|
1783
1805
|
},
|
|
1806
|
+
"customer-id": {
|
|
1807
|
+
"description": "Customer/user identifier for traces (e.g. your name or email)",
|
|
1808
|
+
"env": "RESPAN_CUSTOMER_ID",
|
|
1809
|
+
"name": "customer-id",
|
|
1810
|
+
"hasDynamicHelp": false,
|
|
1811
|
+
"multiple": false,
|
|
1812
|
+
"type": "option"
|
|
1813
|
+
},
|
|
1814
|
+
"span-name": {
|
|
1815
|
+
"description": "Root span name for traces (default: claude-code)",
|
|
1816
|
+
"name": "span-name",
|
|
1817
|
+
"hasDynamicHelp": false,
|
|
1818
|
+
"multiple": false,
|
|
1819
|
+
"type": "option"
|
|
1820
|
+
},
|
|
1821
|
+
"workflow-name": {
|
|
1822
|
+
"description": "Workflow name for traces (default: claude-code)",
|
|
1823
|
+
"name": "workflow-name",
|
|
1824
|
+
"hasDynamicHelp": false,
|
|
1825
|
+
"multiple": false,
|
|
1826
|
+
"type": "option"
|
|
1827
|
+
},
|
|
1784
1828
|
"dry-run": {
|
|
1785
1829
|
"description": "Preview changes without writing files",
|
|
1786
1830
|
"name": "dry-run",
|
|
@@ -1891,6 +1935,28 @@
|
|
|
1891
1935
|
"multiple": false,
|
|
1892
1936
|
"type": "option"
|
|
1893
1937
|
},
|
|
1938
|
+
"customer-id": {
|
|
1939
|
+
"description": "Customer/user identifier for traces (e.g. your name or email)",
|
|
1940
|
+
"env": "RESPAN_CUSTOMER_ID",
|
|
1941
|
+
"name": "customer-id",
|
|
1942
|
+
"hasDynamicHelp": false,
|
|
1943
|
+
"multiple": false,
|
|
1944
|
+
"type": "option"
|
|
1945
|
+
},
|
|
1946
|
+
"span-name": {
|
|
1947
|
+
"description": "Root span name for traces (default: claude-code)",
|
|
1948
|
+
"name": "span-name",
|
|
1949
|
+
"hasDynamicHelp": false,
|
|
1950
|
+
"multiple": false,
|
|
1951
|
+
"type": "option"
|
|
1952
|
+
},
|
|
1953
|
+
"workflow-name": {
|
|
1954
|
+
"description": "Workflow name for traces (default: claude-code)",
|
|
1955
|
+
"name": "workflow-name",
|
|
1956
|
+
"hasDynamicHelp": false,
|
|
1957
|
+
"multiple": false,
|
|
1958
|
+
"type": "option"
|
|
1959
|
+
},
|
|
1894
1960
|
"dry-run": {
|
|
1895
1961
|
"description": "Preview changes without writing files",
|
|
1896
1962
|
"name": "dry-run",
|
|
@@ -2001,6 +2067,28 @@
|
|
|
2001
2067
|
"multiple": false,
|
|
2002
2068
|
"type": "option"
|
|
2003
2069
|
},
|
|
2070
|
+
"customer-id": {
|
|
2071
|
+
"description": "Customer/user identifier for traces (e.g. your name or email)",
|
|
2072
|
+
"env": "RESPAN_CUSTOMER_ID",
|
|
2073
|
+
"name": "customer-id",
|
|
2074
|
+
"hasDynamicHelp": false,
|
|
2075
|
+
"multiple": false,
|
|
2076
|
+
"type": "option"
|
|
2077
|
+
},
|
|
2078
|
+
"span-name": {
|
|
2079
|
+
"description": "Root span name for traces (default: claude-code)",
|
|
2080
|
+
"name": "span-name",
|
|
2081
|
+
"hasDynamicHelp": false,
|
|
2082
|
+
"multiple": false,
|
|
2083
|
+
"type": "option"
|
|
2084
|
+
},
|
|
2085
|
+
"workflow-name": {
|
|
2086
|
+
"description": "Workflow name for traces (default: claude-code)",
|
|
2087
|
+
"name": "workflow-name",
|
|
2088
|
+
"hasDynamicHelp": false,
|
|
2089
|
+
"multiple": false,
|
|
2090
|
+
"type": "option"
|
|
2091
|
+
},
|
|
2004
2092
|
"dry-run": {
|
|
2005
2093
|
"description": "Preview changes without writing files",
|
|
2006
2094
|
"name": "dry-run",
|
|
@@ -3370,5 +3458,5 @@
|
|
|
3370
3458
|
]
|
|
3371
3459
|
}
|
|
3372
3460
|
},
|
|
3373
|
-
"version": "0.
|
|
3461
|
+
"version": "0.5.0"
|
|
3374
3462
|
}
|