langsmith-mcp-server 0.1.1

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 (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +199 -0
  3. package/dist/common/formatters.d.ts +28 -0
  4. package/dist/common/formatters.d.ts.map +1 -0
  5. package/dist/common/formatters.js +150 -0
  6. package/dist/common/formatters.js.map +1 -0
  7. package/dist/common/helpers.d.ts +91 -0
  8. package/dist/common/helpers.d.ts.map +1 -0
  9. package/dist/common/helpers.js +341 -0
  10. package/dist/common/helpers.js.map +1 -0
  11. package/dist/common/pagination.d.ts +36 -0
  12. package/dist/common/pagination.d.ts.map +1 -0
  13. package/dist/common/pagination.js +187 -0
  14. package/dist/common/pagination.js.map +1 -0
  15. package/dist/index.d.ts +8 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +18 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/server.d.ts +16 -0
  20. package/dist/server.d.ts.map +1 -0
  21. package/dist/server.js +20 -0
  22. package/dist/server.js.map +1 -0
  23. package/dist/services/register-tools.d.ts +9 -0
  24. package/dist/services/register-tools.d.ts.map +1 -0
  25. package/dist/services/register-tools.js +589 -0
  26. package/dist/services/register-tools.js.map +1 -0
  27. package/dist/services/tools/datasets.d.ts +60 -0
  28. package/dist/services/tools/datasets.d.ts.map +1 -0
  29. package/dist/services/tools/datasets.js +221 -0
  30. package/dist/services/tools/datasets.js.map +1 -0
  31. package/dist/services/tools/experiments.d.ts +18 -0
  32. package/dist/services/tools/experiments.d.ts.map +1 -0
  33. package/dist/services/tools/experiments.js +81 -0
  34. package/dist/services/tools/experiments.js.map +1 -0
  35. package/dist/services/tools/prompts.d.ts +26 -0
  36. package/dist/services/tools/prompts.d.ts.map +1 -0
  37. package/dist/services/tools/prompts.js +87 -0
  38. package/dist/services/tools/prompts.js.map +1 -0
  39. package/dist/services/tools/traces.d.ts +80 -0
  40. package/dist/services/tools/traces.d.ts.map +1 -0
  41. package/dist/services/tools/traces.js +271 -0
  42. package/dist/services/tools/traces.js.map +1 -0
  43. package/dist/services/tools/usage.d.ts +16 -0
  44. package/dist/services/tools/usage.d.ts.map +1 -0
  45. package/dist/services/tools/usage.js +170 -0
  46. package/dist/services/tools/usage.js.map +1 -0
  47. package/package.json +36 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 LangChain
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,199 @@
1
+ # LangSmith MCP Server (TypeScript)
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
+ [![Node.js 18+](https://img.shields.io/badge/node-18%2B-blue.svg)](https://nodejs.org/)
5
+
6
+ A TypeScript implementation of the [Model Context Protocol](https://modelcontextprotocol.io/introduction) (MCP) server for [LangSmith](https://smith.langchain.com). This is a full port of the official [Python LangSmith MCP Server](https://github.com/langchain-ai/langsmith-mcp-server) with 100% functional parity.
7
+
8
+ ## Example Use Cases
9
+
10
+ The server enables powerful capabilities including:
11
+
12
+ - **Conversation History**: "Fetch the history of my conversation from thread 'thread-123' in project 'my-chatbot'" (paginated by character budget)
13
+ - **Prompt Management**: "Get all public prompts in my workspace" / "Pull the template for the 'legal-case-summarizer' prompt"
14
+ - **Traces & Runs**: "Fetch the latest 10 root runs from project 'alpha'" / "Get all runs for trace \<uuid\> (page 2 of 5)"
15
+ - **Datasets**: "List datasets of type chat" / "Read examples from dataset 'customer-support-qa'"
16
+ - **Experiments**: "List experiments for dataset 'my-eval-set' with latency and cost metrics"
17
+ - **Billing**: "Get billing usage for September 2025"
18
+
19
+ ## Quick Start
20
+
21
+ ```bash
22
+ LANGSMITH_API_KEY=your-key npx langsmith-mcp-server
23
+ ```
24
+
25
+ ## Available Tools
26
+
27
+ The LangSmith MCP Server provides the following tools for integration with LangSmith.
28
+
29
+ ### Conversation & Threads
30
+
31
+ | Tool Name | Description |
32
+ |-----------|-------------|
33
+ | `get_thread_history` | Retrieve message history for a conversation thread. Uses **char-based pagination**: pass `page_number` (1-based), and use returned `total_pages` to request more pages. Optional `max_chars_per_page` and `preview_chars` control page size and long-string truncation. |
34
+
35
+ ### Prompt Management
36
+
37
+ | Tool Name | Description |
38
+ |-----------|-------------|
39
+ | `list_prompts` | Fetch prompts from LangSmith with optional filtering by visibility (public/private) and limit. |
40
+ | `get_prompt_by_name` | Get a specific prompt by its exact name, returning the prompt details and template. |
41
+ | `push_prompt` | Documentation-only: how to create and push prompts to LangSmith. |
42
+
43
+ ### Traces & Runs
44
+
45
+ | Tool Name | Description |
46
+ |-----------|-------------|
47
+ | `fetch_runs` | Fetch LangSmith runs (traces, tools, chains, etc.) from one or more projects. Supports filters (run_type, error, is_root), FQL (`filter`, `trace_filter`, `tree_filter`), and ordering. All results are **automatically paginated** by character budget. Always pass `limit` and `page_number`. |
48
+ | `list_projects` | List LangSmith projects with optional filtering by name, dataset, and detail level (simplified vs full). |
49
+
50
+ ### Datasets & Examples
51
+
52
+ | Tool Name | Description |
53
+ |-----------|-------------|
54
+ | `list_datasets` | Fetch datasets with filtering by ID, type, name, name substring, or metadata. |
55
+ | `list_examples` | Fetch examples from a dataset by dataset ID/name or example IDs, with filter, metadata, splits, and optional `as_of` version. |
56
+ | `read_dataset` | Read a single dataset by ID or name. |
57
+ | `read_example` | Read a single example by ID, with optional `as_of` version. |
58
+ | `create_dataset` | Documentation-only: how to create datasets in LangSmith. |
59
+ | `update_examples` | Documentation-only: how to update dataset examples in LangSmith. |
60
+
61
+ ### Experiments & Evaluations
62
+
63
+ | Tool Name | Description |
64
+ |-----------|-------------|
65
+ | `list_experiments` | List experiment projects (reference projects) for a dataset. Requires `reference_dataset_id` or `reference_dataset_name`. Returns key metrics (latency, cost, feedback stats). |
66
+ | `run_experiment` | Documentation-only: how to run experiments and evaluations in LangSmith. |
67
+
68
+ ### Usage & Billing
69
+
70
+ | Tool Name | Description |
71
+ |-----------|-------------|
72
+ | `get_billing_usage` | Fetch organization billing usage (e.g. trace counts) for a date range. Optional workspace filter; returns metrics with workspace names inline. |
73
+
74
+ ### Pagination (char-based)
75
+
76
+ Several tools use **stateless, character-budget pagination** so responses stay within a size limit and work well with LLM clients:
77
+
78
+ - **Where it's used:** `get_thread_history` and `fetch_runs`.
79
+ - **Parameters:** You send `page_number` (1-based) on every request. Optional: `max_chars_per_page` (default 25000, cap 30000) and `preview_chars` (truncate long strings with "... (+N chars)").
80
+ - **Response:** Each response includes `page_number`, `total_pages`, and the page payload (`result` for messages, `runs` for runs). To get more, call again with `page_number = 2`, then `3`, up to `total_pages`.
81
+ - **Why it's useful:** Pages are built by JSON character count, not item count, so each page fits within a fixed size. No cursor or server-side state -- just integer page numbers.
82
+
83
+ ## Installation
84
+
85
+ ### From npm
86
+
87
+ ```bash
88
+ npx langsmith-mcp-server
89
+ ```
90
+
91
+ ### MCP Client Integration
92
+
93
+ #### Cursor / Claude Code
94
+
95
+ Add to your MCP settings:
96
+
97
+ ```json
98
+ {
99
+ "mcpServers": {
100
+ "langsmith": {
101
+ "command": "npx",
102
+ "args": ["langsmith-mcp-server"],
103
+ "env": {
104
+ "LANGSMITH_API_KEY": "your-key"
105
+ }
106
+ }
107
+ }
108
+ }
109
+ ```
110
+
111
+ ### Environment Variables
112
+
113
+ | Variable | Required | Description | Example |
114
+ |----------|----------|-------------|---------|
115
+ | `LANGSMITH_API_KEY` | Yes | Your LangSmith API key for authentication | `lsv2_pt_1234567890` |
116
+ | `LANGSMITH_WORKSPACE_ID` | No | Workspace ID for API keys scoped to multiple workspaces | `your_workspace_id` |
117
+ | `LANGSMITH_ENDPOINT` | No | Custom API endpoint URL (for self-hosted or EU region) | `https://eu.api.smith.langchain.com` |
118
+
119
+ **Notes:**
120
+ - Only `LANGSMITH_API_KEY` is required for basic functionality
121
+ - `LANGSMITH_WORKSPACE_ID` is useful when your API key has access to multiple workspaces
122
+ - `LANGSMITH_ENDPOINT` allows you to use custom endpoints for self-hosted LangSmith installations or the EU region
123
+
124
+ ## Development and Contributing
125
+
126
+ ### Setup
127
+
128
+ ```bash
129
+ # Clone the repository
130
+ git clone https://github.com/langchain-ai/langsmith-mcp-server-js.git
131
+ cd langsmith-mcp-server-js
132
+
133
+ # Install dependencies
134
+ npm install
135
+
136
+ # Build
137
+ npm run build
138
+
139
+ # Run in development mode
140
+ LANGSMITH_API_KEY=your-key npm run dev
141
+
142
+ # Run production build
143
+ LANGSMITH_API_KEY=your-key npm start
144
+ ```
145
+
146
+ ### Testing
147
+
148
+ ```bash
149
+ # Run unit tests
150
+ npm test
151
+ ```
152
+
153
+ ### MCP Inspector
154
+
155
+ For interactive development and debugging, use the MCP Inspector:
156
+
157
+ ```bash
158
+ LANGSMITH_API_KEY=your-key npx @modelcontextprotocol/inspector npx .
159
+ ```
160
+
161
+ This opens a browser UI where you can browse all tools, inspect their schemas, and invoke them interactively.
162
+
163
+ ### Verify the server responds
164
+
165
+ ```bash
166
+ echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"0.1.0"}}}' | LANGSMITH_API_KEY=test npx . 2>/dev/null
167
+ ```
168
+
169
+ ### Architecture
170
+
171
+ This is a direct port of the [Python LangSmith MCP Server](https://github.com/langchain-ai/langsmith-mcp-server) with the same module structure:
172
+
173
+ ```
174
+ src/
175
+ index.ts # Entry point (stdio transport)
176
+ server.ts # McpServer setup
177
+ common/
178
+ helpers.ts # Client creation, data conversion utilities
179
+ pagination.ts # Char-based stateless pagination
180
+ formatters.ts # Message extraction and formatting
181
+ services/
182
+ register-tools.ts # MCP tool registration with Zod schemas
183
+ tools/
184
+ prompts.ts # Prompt management tools
185
+ traces.ts # Trace/run/project tools
186
+ datasets.ts # Dataset and example tools
187
+ experiments.ts # Experiment listing tools
188
+ usage.ts # Billing/usage REST API tools
189
+ ```
190
+
191
+ ## Contributing
192
+
193
+ This TypeScript implementation is a community port of the official [Python LangSmith MCP Server](https://github.com/langchain-ai/langsmith-mcp-server) by [LangChain](https://langchain.com).
194
+
195
+ Contributions are welcome! Please open an issue or pull request on GitHub.
196
+
197
+ ## License
198
+
199
+ This project is distributed under the MIT License. For detailed terms and conditions, please refer to the [LICENSE](LICENSE) file.
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Output formatting utilities for messages and run.
3
+ */
4
+ /**
5
+ * Format messages as pretty-printed JSON.
6
+ *
7
+ * @param messages - List of message objects
8
+ * @returns JSON string (indent=2) representation of messages
9
+ */
10
+ export declare function formatMessages(messages: Record<string, unknown>[]): string;
11
+ /**
12
+ * Extract messages from a run dictionary.
13
+ *
14
+ * Messages can be in various locations:
15
+ * - run.inputs.messages (for LLM runs)
16
+ * - run.outputs.messages (for some run types)
17
+ * - run.outputs.output.messages (for nested output structures)
18
+ * - run.outputs.choices[0].message (for OpenAI-style outputs)
19
+ *
20
+ * @param runDict - Run dictionary from LangSmith
21
+ * @returns List of message dictionaries
22
+ */
23
+ export declare function extractMessagesFromRun(runDict: Record<string, unknown>): Record<string, unknown>[];
24
+ /**
25
+ * Extract messages from runs and return pretty-printed JSON in "formatted".
26
+ */
27
+ export declare function formatRunsWithMessages(runs: Record<string, unknown>[]): Record<string, unknown>;
28
+ //# sourceMappingURL=formatters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../../src/common/formatters.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAClC,MAAM,CAER;AA8GD;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAqC3B;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAC9B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASzB"}
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Output formatting utilities for messages and run.
3
+ */
4
+ /**
5
+ * Format messages as pretty-printed JSON.
6
+ *
7
+ * @param messages - List of message objects
8
+ * @returns JSON string (indent=2) representation of messages
9
+ */
10
+ export function formatMessages(messages) {
11
+ return JSON.stringify(messages, null, 2);
12
+ }
13
+ /**
14
+ * Recursively extract messages from nested dictionary structures.
15
+ *
16
+ * @param data - Dictionary, list, or other data structure to search
17
+ * @param _path - Current path in the structure (for debugging)
18
+ * @param depth - Current recursion depth
19
+ * @param maxDepth - Maximum recursion depth to avoid infinite loops
20
+ * @returns List of message dictionaries found
21
+ */
22
+ function extractMessagesFromDict(data, _path = "", depth = 0, maxDepth = 5) {
23
+ if (depth > maxDepth) {
24
+ return [];
25
+ }
26
+ const messages = [];
27
+ if (typeof data === "object" && data !== null && !Array.isArray(data)) {
28
+ const obj = data;
29
+ // Check for messages key directly (highest priority)
30
+ if ("messages" in obj) {
31
+ const msgs = obj.messages;
32
+ if (Array.isArray(msgs)) {
33
+ for (const msg of msgs) {
34
+ if (typeof msg === "object" && msg !== null && !Array.isArray(msg)) {
35
+ messages.push(msg);
36
+ }
37
+ }
38
+ return messages; // Return early since we found messages
39
+ }
40
+ }
41
+ // Check for single message key
42
+ if ("message" in obj) {
43
+ const msg = obj.message;
44
+ if (typeof msg === "object" && msg !== null && !Array.isArray(msg)) {
45
+ messages.push(msg);
46
+ }
47
+ }
48
+ // Check for OpenAI-style choices
49
+ if ("choices" in obj) {
50
+ const choices = obj.choices;
51
+ if (Array.isArray(choices)) {
52
+ for (const choice of choices) {
53
+ if (typeof choice === "object" &&
54
+ choice !== null &&
55
+ !Array.isArray(choice)) {
56
+ const choiceObj = choice;
57
+ if ("message" in choiceObj) {
58
+ const msg = choiceObj.message;
59
+ if (typeof msg === "object" &&
60
+ msg !== null &&
61
+ !Array.isArray(msg)) {
62
+ messages.push(msg);
63
+ }
64
+ }
65
+ }
66
+ }
67
+ }
68
+ }
69
+ // If we found messages at this level, return them (don't recurse)
70
+ if (messages.length > 0) {
71
+ return messages;
72
+ }
73
+ // Recursively search nested dictionaries
74
+ for (const [key, value] of Object.entries(obj)) {
75
+ if (typeof value === "object" &&
76
+ value !== null) {
77
+ const nestedMsgs = extractMessagesFromDict(value, `${_path}.${key}`, depth + 1, maxDepth);
78
+ messages.push(...nestedMsgs);
79
+ }
80
+ }
81
+ }
82
+ else if (Array.isArray(data)) {
83
+ for (const item of data) {
84
+ if (typeof item === "object" && item !== null) {
85
+ const nestedMsgs = extractMessagesFromDict(item, `${_path}[]`, depth + 1, maxDepth);
86
+ messages.push(...nestedMsgs);
87
+ }
88
+ }
89
+ }
90
+ return messages;
91
+ }
92
+ /**
93
+ * Extract messages from a run dictionary.
94
+ *
95
+ * Messages can be in various locations:
96
+ * - run.inputs.messages (for LLM runs)
97
+ * - run.outputs.messages (for some run types)
98
+ * - run.outputs.output.messages (for nested output structures)
99
+ * - run.outputs.choices[0].message (for OpenAI-style outputs)
100
+ *
101
+ * @param runDict - Run dictionary from LangSmith
102
+ * @returns List of message dictionaries
103
+ */
104
+ export function extractMessagesFromRun(runDict) {
105
+ const messages = [];
106
+ // Check inputs for messages
107
+ const inputs = runDict.inputs;
108
+ if (inputs !== undefined && inputs !== null) {
109
+ const inputMessages = extractMessagesFromDict(inputs, "inputs");
110
+ messages.push(...inputMessages);
111
+ }
112
+ // Check outputs for messages (including nested structures)
113
+ const outputs = runDict.outputs;
114
+ if (outputs !== undefined && outputs !== null) {
115
+ const outputMessages = extractMessagesFromDict(outputs, "outputs");
116
+ messages.push(...outputMessages);
117
+ }
118
+ // Filter to ensure we only return message dictionaries
119
+ // Deduplicate messages by ID if present
120
+ const validMessages = [];
121
+ const seenIds = new Set();
122
+ for (const msg of messages) {
123
+ if (typeof msg !== "object" || msg === null || Array.isArray(msg)) {
124
+ continue;
125
+ }
126
+ const msgId = msg.id;
127
+ if (typeof msgId === "string") {
128
+ if (seenIds.has(msgId)) {
129
+ continue;
130
+ }
131
+ seenIds.add(msgId);
132
+ }
133
+ validMessages.push(msg);
134
+ }
135
+ return validMessages;
136
+ }
137
+ /**
138
+ * Extract messages from runs and return pretty-printed JSON in "formatted".
139
+ */
140
+ export function formatRunsWithMessages(runs) {
141
+ const allMessages = [];
142
+ for (const run of runs) {
143
+ const runMessages = extractMessagesFromRun(run);
144
+ if (runMessages.length > 0) {
145
+ allMessages.push(...runMessages);
146
+ }
147
+ }
148
+ return { formatted: formatMessages(allMessages) };
149
+ }
150
+ //# sourceMappingURL=formatters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatters.js","sourceRoot":"","sources":["../../src/common/formatters.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Helper functions for the LangSmith MCP server.
3
+ */
4
+ import { Client } from "langsmith";
5
+ /**
6
+ * Create a LangSmith client from environment variables.
7
+ *
8
+ * Reads LANGSMITH_API_KEY (required), LANGSMITH_ENDPOINT (optional),
9
+ * and LANGSMITH_WORKSPACE_ID (optional) from the environment.
10
+ *
11
+ * @returns LangSmith Client instance
12
+ * @throws Error if LANGSMITH_API_KEY is not set
13
+ */
14
+ export declare function getLangSmithClient(): Client;
15
+ /**
16
+ * Get API key and endpoint from environment variables.
17
+ * Used by tools that call LangSmith REST APIs directly (e.g. billing/usage).
18
+ *
19
+ * @returns Tuple of [apiKey, endpoint]. Endpoint is normalized (no trailing slash).
20
+ * @throws Error if LANGSMITH_API_KEY is not set
21
+ */
22
+ export declare function getApiKeyAndEndpoint(): [string, string];
23
+ /**
24
+ * Extract a LangGraph app host name from run stats.
25
+ *
26
+ * @param runStats - The run stats object
27
+ * @returns The LangGraph app host name, or undefined if not found
28
+ */
29
+ export declare function getLanggraphAppHostName(runStats: Record<string, unknown>): string | undefined;
30
+ /**
31
+ * Parse the as_of parameter, converting ISO timestamps to Date objects
32
+ * while leaving version tags as strings.
33
+ *
34
+ * @param asOf - Dataset version tag OR ISO timestamp string
35
+ * @returns Date object if asOf is a valid ISO timestamp, otherwise the original string
36
+ */
37
+ export declare function parseAsOfParameter(asOf: string): Date | string;
38
+ /**
39
+ * Recursively search for a key in a nested dictionary or list.
40
+ * Returns the first occurrence found during depth-first traversal.
41
+ *
42
+ * @param data - The data structure to search in
43
+ * @param key - The key to search for
44
+ * @returns The value associated with the key if found, otherwise undefined
45
+ */
46
+ export declare function findInDict(data: unknown, key: string): unknown | undefined;
47
+ /**
48
+ * Recursively convert Date objects to ISO strings in data structures.
49
+ * Note: In the JS SDK, UUIDs are already strings, unlike the Python SDK
50
+ * where they are uuid.UUID objects. This function primarily handles Dates.
51
+ */
52
+ export declare function convertToSerializable(obj: unknown): unknown;
53
+ /**
54
+ * Recursively count the total number of characters in a data structure.
55
+ */
56
+ export declare function countCharacters(obj: unknown): number;
57
+ /**
58
+ * Recursively count the total number of fields/keys in a data structure.
59
+ */
60
+ export declare function countFields(obj: unknown): number;
61
+ /**
62
+ * Filter a run dictionary to only include selected fields.
63
+ * If select is undefined or empty, returns the full dictionary.
64
+ */
65
+ export declare function filterFields(runDict: Record<string, unknown>, select?: string[]): Record<string, unknown>;
66
+ /**
67
+ * Build a simplified trace tree structure showing top-level fields
68
+ * with metrics for nested content.
69
+ *
70
+ * @param runDict - The dictionary to build a tree from
71
+ * @param depth - How many levels deep to show actual content before summarizing.
72
+ * 0 = summarize all nested structures (default)
73
+ */
74
+ export declare function buildTraceTree(runDict: Record<string, unknown>, depth?: number): Record<string, unknown>;
75
+ /**
76
+ * Parse a JSON array string into an array of strings.
77
+ * If the value starts with "[", parse as JSON array.
78
+ * Otherwise, wrap in a single-element array.
79
+ */
80
+ export declare function parseJsonArray(value: string | undefined): string[] | undefined;
81
+ /**
82
+ * Parse a JSON object string into a Record.
83
+ * If the value starts with "{", parse as JSON object.
84
+ * Otherwise, return undefined.
85
+ */
86
+ export declare function parseJsonObject(value: string | undefined): Record<string, unknown> | undefined;
87
+ /**
88
+ * Parse a boolean string ("true"/"false") to a boolean value.
89
+ */
90
+ export declare function parseBoolString(value: string | undefined): boolean | undefined;
91
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/common/helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAY3C;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAWvD;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,MAAM,GAAG,SAAS,CAoBpB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAU9D;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,OAAO,EACb,GAAG,EAAE,MAAM,GACV,OAAO,GAAG,SAAS,CAqBrB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAkB3D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAoBpD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAgBhD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,MAAM,CAAC,EAAE,MAAM,EAAE,GAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAWzB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,KAAK,GAAE,MAAU,GAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAyFzB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,GAAG,SAAS,CAU9E;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAUrC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAG9E"}