// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../../core/resource'; import { APIPromise } from '../../core/api-promise'; import { buildHeaders } from '../../internal/headers'; import { RequestOptions } from '../../internal/request-options'; import { path } from '../../internal/utils/path'; export class Widgets extends APIResource { /** * Create a new widget, append it to the dashboard, and compute its result in one * call. * * The widget is persisted as its own entity, its ID is appended to the dashboard's * `widget_order`, and — unless it is a `markdown` or `heading` widget — its result * is computed synchronously against the dashboard's evaluation (or * evaluation-group) data before the response returns. Validation is type-specific: * `markdown` requires `config.content`, `bar`/`histogram`/`donut`/`scatter` * require exactly one of `config.x_column` or `config.x_column_group`, `table` * configs with conditional formatting are schema-validated, and all other chart * types require a `query`. The dashboard must exist and not be archived. A * computation failure does not fail the request: the widget is still created and * returned with a result whose `computation_status` is `failed` and an * `error_message` set, while `markdown` and `heading` widgets return a null * result. */ create( dashboardID: string, body: WidgetCreateParams, options?: RequestOptions, ): APIPromise { return this._client.post(path`/v5/evaluation-dashboards/${dashboardID}/widgets`, { body, ...options }); } /** * Update a widget's fields within this dashboard, using copy-on-write for shared * widgets. * * If the widget belongs only to this dashboard it is updated in place; if it is * referenced by more than one dashboard, a new widget is created with the updates * applied and swapped into this dashboard's `widget_order`, leaving the other * dashboards' copy untouched. The widget must already be in this dashboard's * `widget_order`, otherwise the call is rejected. The result is recomputed * synchronously when the `query` changes or when the widget was cloned; otherwise * the existing cached result is returned. For `table` widgets, * conditional-formatting column references are re-resolved against the (possibly * updated) query on each save. The dashboard must exist and not be archived. */ update( widgetID: string, params: WidgetUpdateParams, options?: RequestOptions, ): APIPromise { const { dashboard_id, ...body } = params; return this._client.patch(path`/v5/evaluation-dashboards/${dashboard_id}/widgets/${widgetID}`, { body, ...options, }); } /** * Detach a widget from this dashboard without deleting the widget itself. * * This removes the widget's ID from the dashboard's `widget_order` only; the * underlying widget entity and any computed widget results are left intact, so a * widget shared with other dashboards continues to work there. The widget must * currently be in this dashboard's `widget_order`, otherwise a not-found error is * returned. Responds with 204 No Content on success. */ remove(widgetID: string, params: WidgetRemoveParams, options?: RequestOptions): APIPromise { const { dashboard_id } = params; return this._client.delete(path`/v5/evaluation-dashboards/${dashboard_id}/widgets/${widgetID}`, { ...options, headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), }); } } export interface EvaluationDashboardWidget { /** * Unique identifier of the widget */ id: string; /** * Account that owns this widget */ account_id: string; /** * When the widget was created */ created_at: string; /** * Widget title */ title: string; /** * Widget type */ type: EvaluationWidgetTypeEnum; /** * When the widget was archived (soft-deleted) */ archived_at?: string; /** * Chart-specific display configuration */ config?: { [key: string]: unknown }; object?: 'evaluation_dashboard_widget'; /** * Structured query AST for metric computation (SeriesQuery or MetricQuery) */ query?: SeriesQuery | MetricQuery; } export interface EvaluationDashboardWidgetResult { /** * Unique identifier of the widget result */ id: string; /** * Account that owns this widget result */ account_id: string; /** * Status of the computation */ computation_status: 'pending' | 'completed' | 'failed'; /** * When the widget result was created */ created_at: string; /** * Unique identifier of the widget */ widget_id: string; /** * Temporal workflow ID or job ID for async computation tracking */ computation_job_id?: string; /** * Timestamp when computation completed successfully */ computed_at?: string; /** * Cached computation results */ computed_result?: { [key: string]: unknown }; /** * Error message if computation failed */ error_message?: string; /** * FK to evaluation_groups. Null if result is for a single evaluation. */ evaluation_group_id?: string; /** * FK to evaluations. Null if result is for an evaluation group. */ evaluation_id?: string; object?: 'evaluation_dashboard_widget_result'; /** * Widget that this result is for */ widget?: EvaluationDashboardWidget; } /** * Computed result for a widget - used in widget creation response */ export interface EvaluationDashboardWidgetResultResponse { /** * Unique identifier of the widget result */ id: string; /** * Status: pending, completed, or failed */ computation_status: string; /** * Widget ID this result belongs to */ widget_id: string; /** * When computation completed */ computed_at?: string; /** * Computed result data. Metric: {type: 'metric', data: 42}, Series: {type: * 'series', data: [{x: 'A', y: 10}, ...]} */ computed_result?: { [key: string]: unknown }; /** * Error message if computation failed */ error_message?: string; } /** * Response model for widget creation - includes widget and computed result */ export interface EvaluationDashboardWidgetWithResult { /** * Unique identifier of the widget */ id: string; /** * Account that owns this widget */ account_id: string; /** * When the widget was created */ created_at: string; /** * Widget title */ title: string; /** * Widget type */ type: EvaluationWidgetTypeEnum; /** * Display configuration */ config?: { [key: string]: unknown }; object?: 'evaluation_widget'; /** * Structured query AST for computation (SeriesQuery or MetricQuery) */ query?: SeriesQuery | MetricQuery; /** * Computed result for this widget */ result?: EvaluationDashboardWidgetResultResponse; } /** * Widget types for dashboard visualizations */ export type EvaluationWidgetTypeEnum = | 'bar' | 'histogram' | 'donut' | 'scatter' | 'metric' | 'table' | 'markdown' | 'heading' | 'timeseries'; /** * Filter clause with conditions connected by logical operators. * * Conditions are evaluated left-to-right without precedence (no * nesting/parentheses). Example: condition1 AND condition2 OR condition3 evaluates * as ((condition1 AND condition2) OR condition3) * * Example: { "conditions": [ {"column": "score", "operator": ">", "value": 0.5}, * {"column": "category", "operator": "=", "value": "test"} ], "logicalOperators": * ["AND"] } */ export interface Filter { conditions: Array; /** * Logical operators connecting conditions. Length must be len(conditions) - 1 */ logicalOperators?: Array<'AND' | 'OR'>; } export namespace Filter { /** * Single filter condition comparing a column to a value. * * Example: {"column": "score", "operator": ">", "value": 0.5} {"column": * "category", "operator": "=", "value": "test"} */ export interface Condition { /** * Column name to filter on */ column: string; /** * Comparison operator */ operator: | '=' | '!=' | '>' | '<' | '>=' | '<=' | 'IN' | 'NOT IN' | 'LIKE' | 'NOT LIKE' | 'IS NULL' | 'IS NOT NULL'; /** * Column source: 'data' or 'task_result_cache' */ source?: string; /** * Value to compare against. Not required for IS NULL / IS NOT NULL operators. */ value?: string | number | boolean | Array; } } /** * Query that returns a single metric value (used for metric widgets). * * Used for widget type: metric. Enforces exactly 1 aggregation in select. Returns: * {"type": "metric", "data": ...} * * Example SQL equivalent: SELECT AVG(score) as average_score FROM evaluation_items */ export interface MetricQuery { select: Array; /** * Optional subset of evaluation IDs to compute on. Only applicable for evaluation * group dashboards. If omitted, computes on all evaluations in the group. */ evaluation_ids?: Array; /** * Filter conditions (WHERE clause) */ filter?: Filter; /** * When True, the widget computes against rows from only the most recent active * evaluation in the group (by EvaluationORM.created_at). Only applicable for * evaluation group dashboards. Composes with evaluation_ids (latest within the * subset). Cannot be combined with per-aggregation evaluation_ids; the use case * enforces these rules. */ latest_only?: boolean; } /** * Column in SELECT clause */ export interface SelectItem { /** * Reference to a column from evaluation_items.data * * Example: {"type": "COLUMN", "column": "category"} */ expression: SelectItem.Column | SelectItem.Aggregation; /** * Optional alias for the selected item */ alias?: string; } export namespace SelectItem { /** * Reference to a column from evaluation_items.data * * Example: {"type": "COLUMN", "column": "category"} */ export interface Column { /** * Column name from evaluation_items.data */ column: string; /** * Column source: 'data' or 'task_result_cache' */ source?: string; type?: 'COLUMN'; } /** * Aggregation function to apply * * Examples: {"type": "AGGREGATION", "function": "AVG", "column": "score"} {"type": * "AGGREGATION", "function": "COUNT", "column": "\*"} {"type": "AGGREGATION", * "function": "PERCENTILE", "column": "score", "params": {"percentile": 95}} */ export interface Aggregation { /** * Column to aggregate, or '_' for COUNT(_) */ column: string; /** * Supported aggregation functions */ function: | 'COUNT' | 'SUM' | 'AVG' | 'MIN' | 'MAX' | 'STDDEV' | 'VARIANCE' | 'PERCENTILE' | 'COUNT_DISTINCT' | 'PERCENTAGE'; /** * Optional subset of evaluation IDs for per-aggregation filtering in evaluation * group dashboards. */ evaluation_ids?: Array; /** * Function parameters (e.g., {'percentile': 95} for PERCENTILE, * {'percentage_filters': Filter} for PERCENTAGE) */ params?: { [key: string]: unknown }; /** * Column source: 'data' or 'task_result_cache' */ source?: string; type?: 'AGGREGATION'; } } /** * Query that returns a series of records (used for * table/bar/histogram/donut/scatter widgets). * * Used for widget types: table, bar, histogram, donut, scatter. Returns: {"type": * "series", "data": [...]} * * Example SQL equivalent: SELECT category, AVG(score) as avg_score, COUNT(\*) as * count FROM evaluation_items WHERE score > 0.5 AND category = 'test' GROUP BY * category ORDER BY avg_score DESC LIMIT 100 */ export interface SeriesQuery { select: Array; /** * Optional subset of evaluation IDs to compute on. Only applicable for evaluation * group dashboards. If omitted, computes on all evaluations in the group. */ evaluation_ids?: Array; /** * Filter conditions (WHERE clause) */ filter?: Filter; /** * Columns to group by */ groupBy?: Array; /** * When True, the widget computes against rows from only the most recent active * evaluation in the group (by EvaluationORM.created_at). Only applicable for * evaluation group dashboards. Composes with evaluation_ids (latest within the * subset). Cannot be combined with per-aggregation evaluation_ids; the use case * enforces these rules. */ latest_only?: boolean; /** * Max rows to return */ limit?: number; /** * Sort order */ orderBy?: Array; } export namespace SeriesQuery { /** * Column in ORDER BY clause */ export interface OrderBy { /** * Column name to sort by */ column: string; /** * Sort direction */ direction?: 'ASC' | 'DESC'; /** * Column source: 'data' or 'task_result_cache' */ source?: string; } } export interface WidgetCreateParams { /** * Widget title */ title: string; /** * Widget type */ type: EvaluationWidgetTypeEnum; /** * Chart-specific display configuration */ config?: { [key: string]: unknown }; /** * Structured query AST for metric computation (SeriesQuery or MetricQuery) */ query?: SeriesQuery | MetricQuery; } export interface WidgetUpdateParams { /** * Path param */ dashboard_id: string; /** * Body param: Chart-specific display configuration */ config?: { [key: string]: unknown }; /** * Body param: Structured query AST for metric computation (SeriesQuery or * MetricQuery) */ query?: SeriesQuery | MetricQuery; /** * Body param: Widget title */ title?: string; } export interface WidgetRemoveParams { dashboard_id: string; } export declare namespace Widgets { export { type EvaluationDashboardWidget as EvaluationDashboardWidget, type EvaluationDashboardWidgetResult as EvaluationDashboardWidgetResult, type EvaluationDashboardWidgetResultResponse as EvaluationDashboardWidgetResultResponse, type EvaluationDashboardWidgetWithResult as EvaluationDashboardWidgetWithResult, type EvaluationWidgetTypeEnum as EvaluationWidgetTypeEnum, type Filter as Filter, type MetricQuery as MetricQuery, type SelectItem as SelectItem, type SeriesQuery as SeriesQuery, type WidgetCreateParams as WidgetCreateParams, type WidgetUpdateParams as WidgetUpdateParams, type WidgetRemoveParams as WidgetRemoveParams, }; }