@respan/cli 0.9.0 → 0.10.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.
Files changed (44) hide show
  1. package/dist/commands/datasets/create-span.js +5 -3
  2. package/dist/commands/datasets/create.js +5 -4
  3. package/dist/commands/datasets/get-span.js +5 -1
  4. package/dist/commands/datasets/get.js +1 -1
  5. package/dist/commands/datasets/list.js +5 -1
  6. package/dist/commands/datasets/spans.js +1 -1
  7. package/dist/commands/datasets/update.js +3 -6
  8. package/dist/commands/{datasets/add-spans.d.ts → eval/index.d.ts} +2 -3
  9. package/dist/commands/eval/index.js +26 -0
  10. package/dist/commands/evaluators/create.js +10 -7
  11. package/dist/commands/evaluators/get.js +1 -1
  12. package/dist/commands/evaluators/list.js +1 -1
  13. package/dist/commands/evaluators/run.js +8 -7
  14. package/dist/commands/evaluators/update.js +6 -7
  15. package/dist/commands/experiments/create.js +9 -8
  16. package/dist/commands/experiments/get.js +1 -1
  17. package/dist/commands/experiments/list.js +1 -1
  18. package/dist/commands/logs/create.js +9 -7
  19. package/dist/commands/logs/get.js +1 -1
  20. package/dist/commands/logs/list.js +4 -3
  21. package/dist/commands/logs/summary.js +3 -2
  22. package/dist/commands/prompts/create-version.js +9 -9
  23. package/dist/commands/prompts/create.js +5 -4
  24. package/dist/commands/prompts/get.js +1 -1
  25. package/dist/commands/prompts/list.js +1 -1
  26. package/dist/commands/prompts/update.js +3 -6
  27. package/dist/commands/prompts/versions.js +1 -1
  28. package/dist/commands/setup/index.js +32 -177
  29. package/dist/commands/traces/get.js +1 -1
  30. package/dist/commands/traces/list.js +8 -10
  31. package/dist/commands/traces/summary.js +6 -2
  32. package/dist/commands/users/get.js +1 -1
  33. package/dist/commands/users/list.js +5 -7
  34. package/dist/lib/base-command.d.ts +2 -0
  35. package/dist/lib/base-command.js +11 -1
  36. package/dist/lib/eval/runner.d.ts +15 -0
  37. package/dist/lib/eval/runner.js +292 -0
  38. package/dist/lib/eval/schema.d.ts +67 -0
  39. package/dist/lib/eval/schema.js +22 -0
  40. package/dist/lib/skill-refs.generated.d.ts +5 -0
  41. package/dist/lib/skill-refs.generated.js +1168 -0
  42. package/oclif.manifest.json +181 -189
  43. package/package.json +7 -3
  44. package/dist/commands/datasets/add-spans.js +0 -24
@@ -8,6 +8,7 @@ import { BaseCommand } from '../../lib/base-command.js';
8
8
  import { printBanner } from '../../lib/banner.js';
9
9
  import { findProjectRoot, writeTextFile, readTextFile, ensureDir, } from '../../lib/integrate.js';
10
10
  import { createSpinner } from '../../lib/spinner.js';
11
+ import { TRACING_MD, GATEWAY_MD, PROMPTS_MD, EVALS_MD, MONITORS_MD, } from '#lib/skill-refs.generated.js';
11
12
  // ── Shared skill content (same for all agents) ────────────────────────
12
13
  // ── Skill files ────────────────────────────────────────────────────────
13
14
  const SKILL_MD = `# Respan
@@ -16,196 +17,43 @@ Use the Respan CLI and SDK for LLM observability — tracing, evals, prompts, da
16
17
 
17
18
  ## When To Use
18
19
 
19
- - The user asks to **set up Respan** or **add tracing** → read [references/setup.md](references/setup.md)
20
- - The user asks about **traces, logs, prompts, datasets, evals** → read [references/platform.md](references/platform.md)
21
- - The user asks about **gateway routing** or **proxying LLM calls** → read [references/gateway.md](references/gateway.md)
22
- - You need to run a Respan CLI command → check [references/platform.md](references/platform.md) for command reference
20
+ - **Set up Respan** or **add tracing** → read [references/setup.md](references/setup.md)
21
+ - **Advanced tracing** (decorators, propagation, processors) → read [references/tracing.md](references/tracing.md)
22
+ - **Gateway routing** or **proxying LLM calls** → read [references/gateway.md](references/gateway.md)
23
+ - **Prompt management** (create, version, deploy) → read [references/prompts.md](references/prompts.md)
24
+ - **Evals** (datasets, evaluators, experiments) → read [references/evals.md](references/evals.md)
25
+ - **Monitors & automation** (alerts, online evals, webhooks) → read [references/monitors.md](references/monitors.md)
23
26
 
24
27
  ## Core Principles
25
28
 
26
- 1. **Documentation First**: Always fetch current docs before implementing. Respan updates frequently. See docs access methods below.
27
- 2. **CLI for Data Access**: Use \`respan\` CLI when querying/modifying Respan data.
28
- 3. **Check References**: Read the relevant reference file before implementing any workflow.
29
+ 1. **Read the reference first.** Each reference file has the exact API patterns, MCP tools, and CLI commands.
30
+ 2. **Use MCP tools** for platform operations (prompts, datasets, evaluators, experiments, traces, logs).
31
+ 3. **Use CLI** when MCP is not available: \`respan traces list\`, \`respan prompts list\`, etc.
32
+ 4. **Fetch docs** for integration-specific details not covered in references.
29
33
 
30
34
  ## Quick Reference
31
35
 
32
- | Task | Command / Action |
33
- |------|-----------------|
34
- | Set up SDK tracing | Follow [references/setup.md](references/setup.md) |
36
+ | Task | Reference / Command |
37
+ |------|--------------------|
38
+ | Set up SDK tracing | [references/setup.md](references/setup.md) |
39
+ | Decorators & propagation | [references/tracing.md](references/tracing.md) |
40
+ | Gateway routing | [references/gateway.md](references/gateway.md) |
41
+ | Prompt management | [references/prompts.md](references/prompts.md) |
42
+ | Evals & experiments | [references/evals.md](references/evals.md) |
43
+ | Monitors & automation | [references/monitors.md](references/monitors.md) |
35
44
  | List traces | \`respan traces list --limit 10\` |
36
45
  | View a trace | \`respan traces get <id>\` |
37
- | List prompts | \`respan prompts list\` |
38
- | Create dataset | \`respan datasets create --name <name>\` |
39
- | Run evaluator | \`respan evaluators run <id>\` |
40
46
  | Check auth | \`respan auth status\` |
41
- | View logs | \`respan logs list --limit 10\` |
42
47
 
43
48
  ## Documentation Access
44
49
 
45
- Three methods to access Respan docs, in order of preference:
46
-
47
- ### 1. Documentation Index (llms.txt)
48
-
49
- Fetch the full index of all doc pages:
50
- \`https://www.respan.ai/docs/llms.txt\`
51
-
52
- Use this to discover the right page for a topic, then fetch that page directly.
53
-
54
- ### 2. Fetch Individual Pages as Markdown
55
-
56
- Any integration or SDK doc page can be fetched by changing \`.mdx\` to \`.md\`:
50
+ Any doc page can be fetched as markdown:
57
51
  \`https://respan.ai/docs/integrations/openai-sdk.md\`
58
52
  \`https://respan.ai/docs/sdks/typescript-sdk/overview.md\`
59
53
 
60
- ### 3. Platform
61
-
62
- View traces, logs, and analytics at: \`https://platform.respan.ai\`
63
- `;
64
- const GATEWAY_MD = `# Respan Gateway
65
-
66
- Route LLM calls through the Respan proxy for logging, caching, key management, and model switching.
67
-
68
- ## Setup
69
-
70
- Point the LLM client's base URL at the Respan gateway. The API key authenticates both the proxy and tracing.
71
-
72
- ### TypeScript
73
-
74
- \`\`\`typescript
75
- import OpenAI from "openai";
76
-
77
- const client = new OpenAI({
78
- apiKey: process.env.RESPAN_API_KEY,
79
- baseURL: process.env.RESPAN_BASE_URL || "https://api.respan.ai/api",
80
- });
81
- \`\`\`
82
-
83
- ### Python
84
-
85
- \`\`\`python
86
- import os
87
- from openai import OpenAI
88
-
89
- client = OpenAI(
90
- api_key=os.environ["RESPAN_API_KEY"],
91
- base_url=os.getenv("RESPAN_BASE_URL", "https://api.respan.ai/api"),
92
- )
93
- \`\`\`
94
-
95
- ## Gateway + Tracing (Both)
96
-
97
- Combine SDK tracing and gateway routing — initialize Respan for tracing AND point the LLM client at the gateway.
98
-
99
- ## Features
100
-
101
- - **Unified key management** — one API key for all providers
102
- - **Caching** — cache repeated LLM calls
103
- - **Fallbacks** — automatic failover between providers
104
- - **Cost tracking** — per-request cost logging
105
- - **Model switching** — swap models without code changes
106
-
107
- ## Docs
108
-
109
- - Quickstart: \`https://respan.ai/docs/documentation/features/gateway/gateway-quickstart.md\`
110
- - Advanced: \`https://respan.ai/docs/documentation/features/gateway/advanced.md\`
111
- - Provider setup: \`https://respan.ai/docs/integrations/providers/openai.md\`
112
- `;
113
- const PLATFORM_MD = `# Respan Platform
114
-
115
- Use the Respan CLI and platform for traces, logs, prompts, datasets, evaluations, and monitoring.
116
-
117
- ## CLI Commands
118
-
119
- ### Auth
120
- \`\`\`bash
121
- respan auth login # Log in (browser or API key)
122
- respan auth status # Check current auth
123
- respan auth logout # Log out
124
- respan whoami # Show current user
125
- \`\`\`
126
-
127
- ### Traces
128
- \`\`\`bash
129
- respan traces list --limit 10 # List recent traces
130
- respan traces get <trace-id> # Get trace details
131
- respan traces summary # Trace summary stats
132
- \`\`\`
133
-
134
- ### Logs
135
- \`\`\`bash
136
- respan logs list --limit 10 # List recent logs
137
- respan logs get <log-id> # Get log details
138
- respan logs summary # Log summary stats
139
- respan logs create --data '{...}' # Create a log entry
140
- \`\`\`
141
-
142
- ### Prompts
143
- \`\`\`bash
144
- respan prompts list # List all prompts
145
- respan prompts get <id> # Get prompt details
146
- respan prompts create --name <name> # Create a prompt
147
- respan prompts update <id> # Update a prompt
148
- respan prompts versions <id> # List prompt versions
149
- \`\`\`
150
-
151
- ### Datasets
152
- \`\`\`bash
153
- respan datasets list # List datasets
154
- respan datasets create --name <name> # Create a dataset
155
- respan datasets get <id> # Get dataset details
156
- respan datasets spans <id> # List dataset spans
157
- respan datasets add-spans <id> # Add spans to dataset
158
- \`\`\`
159
-
160
- ### Evaluators
161
- \`\`\`bash
162
- respan evaluators list # List evaluators
163
- respan evaluators get <id> # Get evaluator details
164
- respan evaluators create # Create an evaluator
165
- respan evaluators run <id> # Run an evaluator
166
- \`\`\`
167
-
168
- ### Experiments
169
- \`\`\`bash
170
- respan experiments list # List experiments
171
- respan experiments get <id> # Get experiment details
172
- respan experiments create # Create an experiment
173
- \`\`\`
174
-
175
- ### Integration (CLI agent tracing)
176
- \`\`\`bash
177
- respan integrate claude-code # Trace Claude Code conversations
178
- respan integrate codex-cli # Trace Codex CLI conversations
179
- respan integrate gemini-cli # Trace Gemini CLI conversations
180
- respan integrate opencode # Trace OpenCode conversations
181
- respan integrate <tool> --disable # Disable tracing
182
- \`\`\`
183
-
184
- ### Config
185
- \`\`\`bash
186
- respan config list # List all config
187
- respan config get <key> # Get config value
188
- respan config set <key> <value> # Set config value
189
- \`\`\`
190
-
191
- ## Platform Features
192
-
193
- - **Traces** — structured spans showing LLM call hierarchy, inputs/outputs, tokens, cost
194
- - **Logs** — request-level logging with metadata
195
- - **Prompts** — version-controlled prompt templates with deployment
196
- - **Datasets** — curated test data for evaluations
197
- - **Evaluators** — automated scoring/grading of LLM outputs
198
- - **Experiments** — run evals over datasets and compare results
199
- - **Monitors** — metric-based alerts for production regressions
200
- - **Views** — saved filters for quick access
201
-
202
- ## Docs
54
+ Full docs index: \`https://www.respan.ai/docs/llms.txt\`
203
55
 
204
- - Tracing concepts: \`https://respan.ai/docs/documentation/features/tracing/concepts.md\`
205
- - Evals concepts: \`https://respan.ai/docs/documentation/features/evals/concepts.md\`
206
- - Prompts: \`https://respan.ai/docs/documentation/features/prompt-management/prompt-management-quickstart.md\`
207
- - Monitoring: \`https://respan.ai/docs/documentation/features/monitoring/metrics.md\`
208
- - Full docs: \`https://www.respan.ai/docs/llms.txt\`
56
+ Platform: \`https://platform.respan.ai\`
209
57
  `;
210
58
  const SETUP_MD = `# Respan Setup
211
59
 
@@ -247,9 +95,9 @@ Check higher-priority categories first. If a match is found, use that instrument
247
95
  | Pydantic AI | \`pydantic-ai\` | — | \`respan-instrumentation-pydantic-ai\` | — | [docs](https://respan.ai/docs/integrations/pydantic-ai.md) |
248
96
  | LangChain | \`langchain\` | \`langchain\` | via OpenInference | — | [docs](https://respan.ai/docs/integrations/langchain.md) |
249
97
  | LangGraph | \`langgraph\` | — | via OpenInference | — | [docs](https://respan.ai/docs/integrations/langgraph.md) |
250
- | CrewAI | \`crewai\` | — | via OpenInference | — | [docs](https://respan.ai/docs/integrations/crewai.md) |
98
+ | CrewAI | \`crewai\` | — | \`respan-instrumentation-crewai\` | — | [docs](https://respan.ai/docs/integrations/crewai.md) |
251
99
  | LlamaIndex | \`llama-index\` | — | via OpenInference | — | [docs](https://respan.ai/docs/integrations/llama-index.md) |
252
- | Haystack | \`haystack-ai\` | — | via exporter | — | [docs](https://respan.ai/docs/integrations/haystack.md) |
100
+ | Haystack | \`haystack-ai\` | — | \`respan-instrumentation-haystack\` | — | [docs](https://respan.ai/docs/integrations/haystack.md) |
253
101
  | Mastra | — | \`mastra\` | — | via OTEL | [docs](https://respan.ai/docs/integrations/mastra.md) |
254
102
  | Google ADK | \`google-adk\` | — | via OpenInference | — | [docs](https://respan.ai/docs/integrations/google-adk.md) |
255
103
 
@@ -619,6 +467,8 @@ class Setup extends BaseCommand {
619
467
  attr('gen_ai.system', 'openai'),
620
468
  attr('gen_ai.request.model', 'gpt-4o-mini'),
621
469
  attr('gen_ai.response.model', 'gpt-4o-mini'),
470
+ intAttr('gen_ai.usage.input_tokens', 145),
471
+ intAttr('gen_ai.usage.output_tokens', 38),
622
472
  intAttr('gen_ai.usage.prompt_tokens', 145),
623
473
  intAttr('gen_ai.usage.completion_tokens', 38),
624
474
  attr('traceloop.entity.input', '[{"role": "system", "content": "Classify the customer intent."}, {"role": "user", "content": "My order #12345 hasn\'t arrived yet"}]'),
@@ -652,6 +502,8 @@ class Setup extends BaseCommand {
652
502
  attr('gen_ai.system', 'openai'),
653
503
  attr('gen_ai.request.model', 'gpt-4o-mini'),
654
504
  attr('gen_ai.response.model', 'gpt-4o-mini'),
505
+ intAttr('gen_ai.usage.input_tokens', 210),
506
+ intAttr('gen_ai.usage.output_tokens', 85),
655
507
  intAttr('gen_ai.usage.prompt_tokens', 210),
656
508
  intAttr('gen_ai.usage.completion_tokens', 85),
657
509
  attr('traceloop.entity.input', '[{"role": "system", "content": "Generate a helpful response to the customer."}, {"role": "user", "content": "Order delayed, refund initiated for #12345"}]'),
@@ -782,8 +634,11 @@ class Setup extends BaseCommand {
782
634
  ensureDir(refsDir);
783
635
  writeTextFile(path.join(skillDir, 'SKILL.md'), this.getSkillMd());
784
636
  writeTextFile(path.join(refsDir, 'setup.md'), SETUP_MD);
785
- writeTextFile(path.join(refsDir, 'platform.md'), PLATFORM_MD);
637
+ writeTextFile(path.join(refsDir, 'tracing.md'), TRACING_MD);
786
638
  writeTextFile(path.join(refsDir, 'gateway.md'), GATEWAY_MD);
639
+ writeTextFile(path.join(refsDir, 'prompts.md'), PROMPTS_MD);
640
+ writeTextFile(path.join(refsDir, 'evals.md'), EVALS_MD);
641
+ writeTextFile(path.join(refsDir, 'monitors.md'), MONITORS_MD);
787
642
  };
788
643
  // Write to ~/.agents/skills/ (Cursor, Codex, Gemini CLI, OpenCode)
789
644
  writeSkillTo(path.join(home, '.agents', 'skills'));
@@ -6,7 +6,7 @@ class TracesGet extends BaseCommand {
6
6
  this.globalFlags = flags;
7
7
  try {
8
8
  const client = this.getClient();
9
- const data = await this.spin('Fetching trace', () => client.traces.retrieveTrace({ trace_unique_id: args.id }));
9
+ const data = await this.spin('Fetching trace', () => client.traces.retrieveTrace({ Authorization: this.getAuthHeader(), trace_unique_id: args.id }));
10
10
  this.log(JSON.stringify(data, null, 2));
11
11
  }
12
12
  catch (error) {
@@ -8,22 +8,20 @@ class TracesList extends BaseCommand {
8
8
  this.globalFlags = flags;
9
9
  try {
10
10
  const client = this.getClient();
11
- let bodyFilters = {};
11
+ let bodyFilters;
12
12
  if (flags.filter && flags.filter.length > 0) {
13
13
  bodyFilters = parseFilters(flags.filter);
14
14
  }
15
- const queryParams = {
15
+ const data = await this.spin('Fetching traces', () => client.traces.listTraces({
16
+ Authorization: this.getAuthHeader(),
16
17
  page_size: flags.limit,
17
18
  page: flags.page,
18
19
  sort_by: flags['sort-by'],
19
- };
20
- if (flags['start-time'])
21
- queryParams.start_time = flags['start-time'];
22
- if (flags['end-time'])
23
- queryParams.end_time = flags['end-time'];
24
- if (flags.environment)
25
- queryParams.environment = flags.environment;
26
- const data = await this.spin('Fetching traces', () => client.traces.list({ filters: bodyFilters }, { queryParams }));
20
+ ...(flags['start-time'] ? { start_time: flags['start-time'] } : {}),
21
+ ...(flags['end-time'] ? { end_time: flags['end-time'] } : {}),
22
+ ...(flags.environment ? { environment: flags.environment } : {}),
23
+ ...(bodyFilters ? { filters: bodyFilters } : {}),
24
+ }));
27
25
  this.outputResult(data, [
28
26
  'trace_unique_id', 'name', 'duration', 'span_count', 'total_cost', 'error_count', 'start_time',
29
27
  ]);
@@ -6,7 +6,11 @@ class TracesSummary extends BaseCommand {
6
6
  this.globalFlags = flags;
7
7
  try {
8
8
  const client = this.getClient();
9
- const data = await this.spin('Fetching traces summary', () => client.traces.retrieveTracesSummary({ start_time: flags['start-time'], end_time: flags['end-time'] }));
9
+ const data = await this.spin('Fetching traces summary', () => client.spans.getSpansSummary({
10
+ Authorization: this.getAuthHeader(),
11
+ start_time: flags['start-time'],
12
+ end_time: flags['end-time'],
13
+ }));
10
14
  this.log(JSON.stringify(data, null, 2));
11
15
  }
12
16
  catch (error) {
@@ -14,7 +18,7 @@ class TracesSummary extends BaseCommand {
14
18
  }
15
19
  }
16
20
  }
17
- TracesSummary.description = 'Get a summary of traces for a time range';
21
+ TracesSummary.description = 'Get a span-level summary of activity for a time range (counts, latency, cost, errors aggregated across spans)';
18
22
  TracesSummary.flags = {
19
23
  ...BaseCommand.baseFlags,
20
24
  'start-time': Flags.string({ description: 'Start time (ISO 8601)', required: true }),
@@ -6,7 +6,7 @@ class UsersGet extends BaseCommand {
6
6
  this.globalFlags = flags;
7
7
  try {
8
8
  const client = this.getClient();
9
- const data = await this.spin('Fetching user', () => client.users.retrieveUser({ customer_identifier: args.id }));
9
+ const data = await this.spin('Fetching user', () => client.users.retrieveUser({ Authorization: this.getAuthHeader(), customer_identifier: args.id }));
10
10
  this.log(JSON.stringify(data, null, 2));
11
11
  }
12
12
  catch (error) {
@@ -7,15 +7,13 @@ class UsersList extends BaseCommand {
7
7
  this.globalFlags = flags;
8
8
  try {
9
9
  const client = this.getClient();
10
- const params = {
10
+ const data = await this.spin('Fetching users', () => client.users.listCustomers({
11
+ Authorization: this.getAuthHeader(),
11
12
  page_size: flags.limit,
12
13
  page: flags.page,
13
- };
14
- if (flags['sort-by'])
15
- params.sort_by = flags['sort-by'];
16
- if (flags.environment)
17
- params.environment = flags.environment;
18
- const data = await this.spin('Fetching users', () => client.users.list(params));
14
+ ...(flags['sort-by'] ? { sort_by: flags['sort-by'] } : {}),
15
+ ...(flags.environment ? { environment: flags.environment } : {}),
16
+ }));
19
17
  this.outputResult(data, [
20
18
  'customer_identifier', 'name', 'email', 'number_of_requests', 'total_cost', 'last_active_timeframe',
21
19
  ]);
@@ -14,6 +14,8 @@ export declare abstract class BaseCommand extends Command {
14
14
  protected globalFlags: GlobalFlags;
15
15
  protected getAuth(): AuthConfig;
16
16
  protected getClient(): RespanClient;
17
+ protected getAuthHeader(): string;
18
+ protected getBaseUrl(): string;
17
19
  protected getOutputFormat(): 'json' | 'csv' | 'table';
18
20
  protected outputResult(data: unknown, columns?: string[]): void;
19
21
  protected spin<T>(label: string, fn: () => Promise<T>): Promise<T>;
@@ -17,10 +17,20 @@ export class BaseCommand extends Command {
17
17
  if (!token)
18
18
  throw new Error('No API key or access token available.');
19
19
  return new RespanClient({
20
- token,
20
+ headers: { Authorization: `Bearer ${token}` },
21
21
  ...(auth.baseUrl ? { environment: auth.baseUrl } : {}),
22
22
  });
23
23
  }
24
+ getAuthHeader() {
25
+ const auth = this.getAuth();
26
+ const token = auth.apiKey || auth.accessToken;
27
+ if (!token)
28
+ throw new Error('No API key or access token available.');
29
+ return `Bearer ${token}`;
30
+ }
31
+ getBaseUrl() {
32
+ return this.getAuth().baseUrl || 'https://api.respan.ai';
33
+ }
24
34
  getOutputFormat() {
25
35
  if (this.globalFlags.json)
26
36
  return 'json';
@@ -0,0 +1,15 @@
1
+ import { RespanClient } from '@respan/respan-api';
2
+ export interface RunEvalResult {
3
+ prompt_id: string;
4
+ prompt_version_id?: string;
5
+ prompt_version_deployed?: number;
6
+ dataset_id: string;
7
+ evaluator_workflow_ids: string[];
8
+ experiment_id: string;
9
+ created_prompt: boolean;
10
+ created_dataset: boolean;
11
+ created_experiment: boolean;
12
+ evaluators_created: number;
13
+ rows_added: number;
14
+ }
15
+ export declare function runEval(filePath: string, client: RespanClient, authHeader: string, baseUrl: string, log?: (msg: string) => void): Promise<RunEvalResult>;