Spaces:
Sleeping
Sleeping
harryagasi commited on
Commit ·
98ca5fc
1
Parent(s): 6b435ec
feat: sort analyses by updated_at, render data_used in traceability
Browse files- Sort analysis list by updated_at (desc) on load, select, create, and data-bind update
- Add data_used field to traceability response type and render it in a dedicated section
- Move tool calls behind a collapsible "Details" section instead of showing inline
- Update API contract docs for soft-delete analysis behavior and traceability data_used/tool_calls fields
docs/API_CONTRACT_BE_GOLANG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
# Backend Go API Contract
|
| 2 |
|
| 3 |
-
**Last updated**: 2026-07-
|
| 4 |
|
| 5 |
Dokumen ini merangkum endpoint Orchestration Agent Service yang dipakai oleh frontend. Fokus flow:
|
| 6 |
|
|
@@ -764,7 +764,7 @@ Errors: `400`, `401`, `404`.
|
|
| 764 |
|
| 765 |
### `DELETE /api/v1/analyses/{id}`
|
| 766 |
|
| 767 |
-
|
| 768 |
|
| 769 |
Success `204` tanpa response body.
|
| 770 |
|
|
|
|
| 1 |
# Backend Go API Contract
|
| 2 |
|
| 3 |
+
**Last updated**: 2026-07-13
|
| 4 |
|
| 5 |
Dokumen ini merangkum endpoint Orchestration Agent Service yang dipakai oleh frontend. Fokus flow:
|
| 6 |
|
|
|
|
| 764 |
|
| 765 |
### `DELETE /api/v1/analyses/{id}`
|
| 766 |
|
| 767 |
+
Soft-delete analysis milik user: mengubah `status` menjadi `inactive`, bukan menghapus row dari database. Record analysis dan seluruh data terkait (reports, messages, report_inputs, dll) tetap ada di database, hanya tidak muncul lagi di `GET /api/v1/analyses` dengan filter default (`status=active`).
|
| 768 |
|
| 769 |
Success `204` tanpa response body.
|
| 770 |
|
docs/API_CONTRACT_BE_PYTHON.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
| 1 |
# Backend Agentic Service API Contract
|
| 2 |
|
|
|
|
|
|
|
| 3 |
This document describes the Python agentic backend used by the frontend for AI chat, help/report tools, and traceability data shown alongside chat answers.
|
| 4 |
|
| 5 |
Base path examples use relative URLs. Configure the frontend with the deployed Python service base URL.
|
|
@@ -422,6 +424,7 @@ Response `200` for `structured_flow`:
|
|
| 422 |
"order": 1,
|
| 423 |
"task_id": null,
|
| 424 |
"name": "check_data",
|
|
|
|
| 425 |
"input": { "source_hint": "structured" },
|
| 426 |
"output": {
|
| 427 |
"kind": "table",
|
|
@@ -436,6 +439,7 @@ Response `200` for `structured_flow`:
|
|
| 436 |
"order": 2,
|
| 437 |
"task_id": null,
|
| 438 |
"name": "retrieve_data",
|
|
|
|
| 439 |
"input": { "ir": { "source_id": "src_sales_db", "table_id": "orders", "select": ["region", "amount"], "group_by": ["region"] } },
|
| 440 |
"output": {
|
| 441 |
"kind": "table",
|
|
@@ -447,11 +451,34 @@ Response `200` for `structured_flow`:
|
|
| 447 |
"error": null
|
| 448 |
}
|
| 449 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 450 |
"sources": [
|
| 451 |
{
|
| 452 |
"type": "database",
|
| 453 |
"source_id": "src_sales_db",
|
|
|
|
| 454 |
"name": "orders",
|
|
|
|
| 455 |
"query": "SELECT region, SUM(amount) AS total FROM orders GROUP BY region",
|
| 456 |
"detail": {
|
| 457 |
"table": "orders",
|
|
|
|
| 1 |
# Backend Agentic Service API Contract
|
| 2 |
|
| 3 |
+
**Last updated**: 2026-07-13
|
| 4 |
+
|
| 5 |
This document describes the Python agentic backend used by the frontend for AI chat, help/report tools, and traceability data shown alongside chat answers.
|
| 6 |
|
| 7 |
Base path examples use relative URLs. Configure the frontend with the deployed Python service base URL.
|
|
|
|
| 424 |
"order": 1,
|
| 425 |
"task_id": null,
|
| 426 |
"name": "check_data",
|
| 427 |
+
"summary": "Inspected your data source structure",
|
| 428 |
"input": { "source_hint": "structured" },
|
| 429 |
"output": {
|
| 430 |
"kind": "table",
|
|
|
|
| 439 |
"order": 2,
|
| 440 |
"task_id": null,
|
| 441 |
"name": "retrieve_data",
|
| 442 |
+
"summary": "Retrieved 4 rows across 2 columns from orders",
|
| 443 |
"input": { "ir": { "source_id": "src_sales_db", "table_id": "orders", "select": ["region", "amount"], "group_by": ["region"] } },
|
| 444 |
"output": {
|
| 445 |
"kind": "table",
|
|
|
|
| 451 |
"error": null
|
| 452 |
}
|
| 453 |
],
|
| 454 |
+
"data_used": [
|
| 455 |
+
{
|
| 456 |
+
"source": { "id": "src_sales_db", "name": "sales db", "type": "schema" },
|
| 457 |
+
"tables": [ { "id": "orders", "name": "orders", "role": "base" } ],
|
| 458 |
+
"joins": [],
|
| 459 |
+
"columns_read": [
|
| 460 |
+
{ "id": "c_region", "name": "region", "table": "orders", "data_type": "string", "pii": false, "roles": ["selected", "grouped"] },
|
| 461 |
+
{ "id": "c_amount", "name": "amount", "table": "orders", "data_type": "decimal", "pii": false, "roles": ["aggregated"] }
|
| 462 |
+
],
|
| 463 |
+
"output_columns": [
|
| 464 |
+
{ "name": "region", "kind": "column", "from": "orders.region" },
|
| 465 |
+
{ "name": "total", "kind": "computed", "from": "orders.amount", "formula": "SUM(orders.amount)" }
|
| 466 |
+
],
|
| 467 |
+
"filters": [],
|
| 468 |
+
"group_by": ["orders.region"],
|
| 469 |
+
"order_by": [],
|
| 470 |
+
"limit": null,
|
| 471 |
+
"rows_returned": 4,
|
| 472 |
+
"query": "SELECT region, SUM(amount) AS total FROM orders GROUP BY region"
|
| 473 |
+
}
|
| 474 |
+
],
|
| 475 |
"sources": [
|
| 476 |
{
|
| 477 |
"type": "database",
|
| 478 |
"source_id": "src_sales_db",
|
| 479 |
+
"source_name": "sales db",
|
| 480 |
"name": "orders",
|
| 481 |
+
"tables": ["orders"],
|
| 482 |
"query": "SELECT region, SUM(amount) AS total FROM orders GROUP BY region",
|
| 483 |
"detail": {
|
| 484 |
"table": "orders",
|
src/app/components/analysis/AnalysisShell.tsx
CHANGED
|
@@ -47,6 +47,10 @@ function toUiMessage(message: AnalysisMessage): UiMessage {
|
|
| 47 |
}
|
| 48 |
|
| 49 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
function normalizeAssistantContent(content: string) {
|
| 51 |
return content
|
| 52 |
.replace(/([A-Za-z0-9])(?=\*\*)/g, "$1 ")
|
|
@@ -81,7 +85,7 @@ export function AnalysisShell() {
|
|
| 81 |
try {
|
| 82 |
const [detail, history] = await Promise.all([getAnalysis(analysis.id), getAnalysisMessages(analysis.id)]);
|
| 83 |
setActiveAnalysis(detail);
|
| 84 |
-
setAnalyses((prev) => prev.map((item) => (item.id === detail.id ? detail : item)));
|
| 85 |
setMessages(history.map(toUiMessage));
|
| 86 |
} catch (err) {
|
| 87 |
toast.error(err instanceof Error ? err.message : "Failed to open analysis");
|
|
@@ -95,7 +99,7 @@ export function AnalysisShell() {
|
|
| 95 |
setLoadingAnalyses(true);
|
| 96 |
try {
|
| 97 |
const result = await listAnalyses({ status: "active", page: 1, limit: 50 });
|
| 98 |
-
setAnalyses(result.analyses);
|
| 99 |
if (!activeAnalysis && result.analyses.length > 0) {
|
| 100 |
await selectAnalysis(result.analyses[0]);
|
| 101 |
}
|
|
@@ -288,7 +292,7 @@ export function AnalysisShell() {
|
|
| 288 |
};
|
| 289 |
|
| 290 |
const handleCreated = (analysis: Analysis) => {
|
| 291 |
-
setAnalyses((prev) => [analysis, ...prev.filter((item) => item.id !== analysis.id)]);
|
| 292 |
setActiveMenu("analysis-agent");
|
| 293 |
selectAnalysis(analysis);
|
| 294 |
};
|
|
@@ -314,7 +318,7 @@ export function AnalysisShell() {
|
|
| 314 |
if (!activeAnalysis) return;
|
| 315 |
const updated = await updateAnalysisDataBind(activeAnalysis.id, activeAnalysis.data_bind_version, items);
|
| 316 |
setActiveAnalysis(updated);
|
| 317 |
-
setAnalyses((prev) => prev.map((item) => (item.id === updated.id ? updated : item)));
|
| 318 |
setStaleSources([]);
|
| 319 |
};
|
| 320 |
|
|
|
|
| 47 |
}
|
| 48 |
|
| 49 |
|
| 50 |
+
function sortByUpdatedAtDesc(items: Analysis[]) {
|
| 51 |
+
return [...items].sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime());
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
function normalizeAssistantContent(content: string) {
|
| 55 |
return content
|
| 56 |
.replace(/([A-Za-z0-9])(?=\*\*)/g, "$1 ")
|
|
|
|
| 85 |
try {
|
| 86 |
const [detail, history] = await Promise.all([getAnalysis(analysis.id), getAnalysisMessages(analysis.id)]);
|
| 87 |
setActiveAnalysis(detail);
|
| 88 |
+
setAnalyses((prev) => sortByUpdatedAtDesc(prev.map((item) => (item.id === detail.id ? detail : item))));
|
| 89 |
setMessages(history.map(toUiMessage));
|
| 90 |
} catch (err) {
|
| 91 |
toast.error(err instanceof Error ? err.message : "Failed to open analysis");
|
|
|
|
| 99 |
setLoadingAnalyses(true);
|
| 100 |
try {
|
| 101 |
const result = await listAnalyses({ status: "active", page: 1, limit: 50 });
|
| 102 |
+
setAnalyses(sortByUpdatedAtDesc(result.analyses));
|
| 103 |
if (!activeAnalysis && result.analyses.length > 0) {
|
| 104 |
await selectAnalysis(result.analyses[0]);
|
| 105 |
}
|
|
|
|
| 292 |
};
|
| 293 |
|
| 294 |
const handleCreated = (analysis: Analysis) => {
|
| 295 |
+
setAnalyses((prev) => sortByUpdatedAtDesc([analysis, ...prev.filter((item) => item.id !== analysis.id)]));
|
| 296 |
setActiveMenu("analysis-agent");
|
| 297 |
selectAnalysis(analysis);
|
| 298 |
};
|
|
|
|
| 318 |
if (!activeAnalysis) return;
|
| 319 |
const updated = await updateAnalysisDataBind(activeAnalysis.id, activeAnalysis.data_bind_version, items);
|
| 320 |
setActiveAnalysis(updated);
|
| 321 |
+
setAnalyses((prev) => sortByUpdatedAtDesc(prev.map((item) => (item.id === updated.id ? updated : item))));
|
| 322 |
setStaleSources([]);
|
| 323 |
};
|
| 324 |
|
src/app/components/analysis/MessageTraceability.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
import { useState } from "react";
|
| 2 |
-
import { ChevronDown, ChevronRight, Loader2, Route, Wrench } from "lucide-react";
|
| 3 |
-
import type { Observability } from "@/services/agenticApi";
|
| 4 |
import { formatDateTime } from "./utils";
|
| 5 |
|
| 6 |
interface MessageTraceabilityProps {
|
|
@@ -28,14 +28,55 @@ function sourceLabel(source: unknown, index: number) {
|
|
| 28 |
return String(source ?? `Source ${index + 1}`);
|
| 29 |
}
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
export function MessageTraceability({ observability, loading, error, sources = [] }: MessageTraceabilityProps) {
|
| 32 |
const [open, setOpen] = useState(false);
|
|
|
|
| 33 |
const traceSources = observability?.sources?.length ? observability.sources : sources;
|
| 34 |
const hasTrace = Boolean(observability || loading || error || traceSources.length > 0);
|
| 35 |
|
| 36 |
if (!hasTrace) return null;
|
| 37 |
|
| 38 |
const toolCalls = observability?.tool_calls ?? [];
|
|
|
|
| 39 |
|
| 40 |
return (
|
| 41 |
<div className="mt-3 border-t border-slate-200 pt-3">
|
|
@@ -95,31 +136,59 @@ export function MessageTraceability({ observability, loading, error, sources = [
|
|
| 95 |
|
| 96 |
<div>
|
| 97 |
<div className="flex items-center gap-2 font-semibold text-slate-900">
|
| 98 |
-
<
|
| 99 |
-
|
| 100 |
</div>
|
| 101 |
-
{
|
| 102 |
-
<p className="mt-1 text-slate-500">No
|
| 103 |
) : (
|
| 104 |
<div className="mt-2 space-y-2">
|
| 105 |
-
{
|
| 106 |
-
<
|
| 107 |
-
<div className="flex items-center justify-between gap-2">
|
| 108 |
-
<p className="font-medium text-slate-900">{tool.name}</p>
|
| 109 |
-
{tool.status && <span className="rounded bg-slate-100 px-1.5 py-0.5 text-[10px] uppercase text-slate-500">{tool.status}</span>}
|
| 110 |
-
</div>
|
| 111 |
-
{tool.input !== undefined && (
|
| 112 |
-
<pre className="mt-2 max-h-40 overflow-auto rounded bg-slate-950 p-2 text-[11px] leading-4 text-slate-100">{renderUnknown(tool.input)}</pre>
|
| 113 |
-
)}
|
| 114 |
-
{tool.output !== undefined && (
|
| 115 |
-
<pre className="mt-2 max-h-40 overflow-auto rounded bg-white p-2 text-[11px] leading-4 text-slate-600 ring-1 ring-slate-200">{renderUnknown(tool.output)}</pre>
|
| 116 |
-
)}
|
| 117 |
-
</div>
|
| 118 |
))}
|
| 119 |
</div>
|
| 120 |
)}
|
| 121 |
</div>
|
| 122 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 123 |
{traceSources.length > 0 && (
|
| 124 |
<div>
|
| 125 |
<p className="font-semibold text-slate-900">Citations and sources</p>
|
|
|
|
| 1 |
import { useState } from "react";
|
| 2 |
+
import { ChevronDown, ChevronRight, Database, Loader2, Route, Wrench } from "lucide-react";
|
| 3 |
+
import type { Observability, ObservabilityDataUsed } from "@/services/agenticApi";
|
| 4 |
import { formatDateTime } from "./utils";
|
| 5 |
|
| 6 |
interface MessageTraceabilityProps {
|
|
|
|
| 28 |
return String(source ?? `Source ${index + 1}`);
|
| 29 |
}
|
| 30 |
|
| 31 |
+
function DataUsedCard({ item, index }: { item: ObservabilityDataUsed; index: number }) {
|
| 32 |
+
return (
|
| 33 |
+
<div className="rounded-md border border-slate-200 bg-white p-2">
|
| 34 |
+
<div className="flex items-center justify-between gap-2">
|
| 35 |
+
<p className="font-medium text-slate-900">{item.source?.name ?? `Data source ${index + 1}`}</p>
|
| 36 |
+
{item.source?.type && <span className="rounded bg-slate-100 px-1.5 py-0.5 text-[10px] uppercase text-slate-500">{item.source.type}</span>}
|
| 37 |
+
</div>
|
| 38 |
+
|
| 39 |
+
{item.tables && item.tables.length > 0 && (
|
| 40 |
+
<p className="mt-1.5 text-slate-600">
|
| 41 |
+
Tables: {item.tables.map((table) => table.name).join(", ")}
|
| 42 |
+
</p>
|
| 43 |
+
)}
|
| 44 |
+
|
| 45 |
+
{item.columns_read && item.columns_read.length > 0 && (
|
| 46 |
+
<div className="mt-1.5 flex flex-wrap gap-1">
|
| 47 |
+
{item.columns_read.map((column) => (
|
| 48 |
+
<span key={column.id} className="rounded border border-slate-200 bg-slate-50 px-1.5 py-0.5 text-[11px] text-slate-600">
|
| 49 |
+
{column.table ? `${column.table}.${column.name}` : column.name}
|
| 50 |
+
</span>
|
| 51 |
+
))}
|
| 52 |
+
</div>
|
| 53 |
+
)}
|
| 54 |
+
|
| 55 |
+
{item.group_by && item.group_by.length > 0 && (
|
| 56 |
+
<p className="mt-1.5 text-slate-600">Grouped by: {item.group_by.join(", ")}</p>
|
| 57 |
+
)}
|
| 58 |
+
|
| 59 |
+
{typeof item.rows_returned === "number" && (
|
| 60 |
+
<p className="mt-1.5 text-slate-600">Rows returned: {item.rows_returned}</p>
|
| 61 |
+
)}
|
| 62 |
+
|
| 63 |
+
{item.query && (
|
| 64 |
+
<pre className="mt-2 max-h-40 overflow-auto rounded bg-slate-950 p-2 text-[11px] leading-4 text-slate-100">{item.query}</pre>
|
| 65 |
+
)}
|
| 66 |
+
</div>
|
| 67 |
+
);
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
export function MessageTraceability({ observability, loading, error, sources = [] }: MessageTraceabilityProps) {
|
| 71 |
const [open, setOpen] = useState(false);
|
| 72 |
+
const [detailsOpen, setDetailsOpen] = useState(false);
|
| 73 |
const traceSources = observability?.sources?.length ? observability.sources : sources;
|
| 74 |
const hasTrace = Boolean(observability || loading || error || traceSources.length > 0);
|
| 75 |
|
| 76 |
if (!hasTrace) return null;
|
| 77 |
|
| 78 |
const toolCalls = observability?.tool_calls ?? [];
|
| 79 |
+
const dataUsed = observability?.data_used ?? [];
|
| 80 |
|
| 81 |
return (
|
| 82 |
<div className="mt-3 border-t border-slate-200 pt-3">
|
|
|
|
| 136 |
|
| 137 |
<div>
|
| 138 |
<div className="flex items-center gap-2 font-semibold text-slate-900">
|
| 139 |
+
<Database className="h-3.5 w-3.5" />
|
| 140 |
+
Data used
|
| 141 |
</div>
|
| 142 |
+
{dataUsed.length === 0 ? (
|
| 143 |
+
<p className="mt-1 text-slate-500">No data usage recorded for this answer.</p>
|
| 144 |
) : (
|
| 145 |
<div className="mt-2 space-y-2">
|
| 146 |
+
{dataUsed.map((item, index) => (
|
| 147 |
+
<DataUsedCard key={`${item.source?.id ?? "source"}-${index}`} item={item} index={index} />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
))}
|
| 149 |
</div>
|
| 150 |
)}
|
| 151 |
</div>
|
| 152 |
|
| 153 |
+
<div>
|
| 154 |
+
<button
|
| 155 |
+
type="button"
|
| 156 |
+
title="Show tool call details"
|
| 157 |
+
aria-expanded={detailsOpen}
|
| 158 |
+
onClick={() => setDetailsOpen((current) => !current)}
|
| 159 |
+
className="inline-flex items-center gap-2 rounded-md px-1.5 py-1 text-xs font-semibold text-slate-900 hover:bg-slate-100"
|
| 160 |
+
>
|
| 161 |
+
{detailsOpen ? <ChevronDown className="h-3.5 w-3.5" /> : <ChevronRight className="h-3.5 w-3.5" />}
|
| 162 |
+
<Wrench className="h-3.5 w-3.5" />
|
| 163 |
+
Details
|
| 164 |
+
</button>
|
| 165 |
+
|
| 166 |
+
{detailsOpen && (
|
| 167 |
+
toolCalls.length === 0 ? (
|
| 168 |
+
<p className="mt-1 pl-1.5 text-slate-500">No tool call recorded for this answer.</p>
|
| 169 |
+
) : (
|
| 170 |
+
<div className="mt-2 space-y-2 pl-1.5">
|
| 171 |
+
{toolCalls.map((tool, index) => (
|
| 172 |
+
<div key={`${tool.name}-${index}`} className="rounded-md border border-slate-200 bg-white p-2">
|
| 173 |
+
<div className="flex items-center justify-between gap-2">
|
| 174 |
+
<p className="font-medium text-slate-900">{tool.name}</p>
|
| 175 |
+
{tool.status && <span className="rounded bg-slate-100 px-1.5 py-0.5 text-[10px] uppercase text-slate-500">{tool.status}</span>}
|
| 176 |
+
</div>
|
| 177 |
+
{tool.summary && <p className="mt-1 text-slate-600">{tool.summary}</p>}
|
| 178 |
+
{tool.input !== undefined && (
|
| 179 |
+
<pre className="mt-2 max-h-40 overflow-auto rounded bg-slate-950 p-2 text-[11px] leading-4 text-slate-100">{renderUnknown(tool.input)}</pre>
|
| 180 |
+
)}
|
| 181 |
+
{tool.output !== undefined && (
|
| 182 |
+
<pre className="mt-2 max-h-40 overflow-auto rounded bg-white p-2 text-[11px] leading-4 text-slate-600 ring-1 ring-slate-200">{renderUnknown(tool.output)}</pre>
|
| 183 |
+
)}
|
| 184 |
+
{tool.error && <p className="mt-2 text-red-600">{tool.error}</p>}
|
| 185 |
+
</div>
|
| 186 |
+
))}
|
| 187 |
+
</div>
|
| 188 |
+
)
|
| 189 |
+
)}
|
| 190 |
+
</div>
|
| 191 |
+
|
| 192 |
{traceSources.length > 0 && (
|
| 193 |
<div>
|
| 194 |
<p className="font-semibold text-slate-900">Citations and sources</p>
|
src/services/agenticApi.ts
CHANGED
|
@@ -48,10 +48,55 @@ export interface ObservabilityPlanning {
|
|
| 48 |
|
| 49 |
export interface ObservabilityToolCall {
|
| 50 |
order?: number;
|
|
|
|
| 51 |
name: string;
|
|
|
|
| 52 |
input?: unknown;
|
| 53 |
output?: unknown;
|
| 54 |
status?: string;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
}
|
| 56 |
|
| 57 |
export interface Observability {
|
|
@@ -62,6 +107,7 @@ export interface Observability {
|
|
| 62 |
planning: ObservabilityPlanning | null;
|
| 63 |
thinking: string | null;
|
| 64 |
tool_calls: ObservabilityToolCall[];
|
|
|
|
| 65 |
sources: unknown[];
|
| 66 |
}
|
| 67 |
|
|
|
|
| 48 |
|
| 49 |
export interface ObservabilityToolCall {
|
| 50 |
order?: number;
|
| 51 |
+
task_id?: string | null;
|
| 52 |
name: string;
|
| 53 |
+
summary?: string;
|
| 54 |
input?: unknown;
|
| 55 |
output?: unknown;
|
| 56 |
status?: string;
|
| 57 |
+
error?: string | null;
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
export interface ObservabilityDataUsedSource {
|
| 61 |
+
id: string;
|
| 62 |
+
name: string;
|
| 63 |
+
type: string;
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
export interface ObservabilityDataUsedTable {
|
| 67 |
+
id: string;
|
| 68 |
+
name: string;
|
| 69 |
+
role?: string;
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
export interface ObservabilityDataUsedColumn {
|
| 73 |
+
id: string;
|
| 74 |
+
name: string;
|
| 75 |
+
table?: string;
|
| 76 |
+
data_type?: string;
|
| 77 |
+
pii?: boolean;
|
| 78 |
+
roles?: string[];
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
export interface ObservabilityDataUsedOutputColumn {
|
| 82 |
+
name: string;
|
| 83 |
+
kind?: string;
|
| 84 |
+
from?: string;
|
| 85 |
+
formula?: string;
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
export interface ObservabilityDataUsed {
|
| 89 |
+
source: ObservabilityDataUsedSource;
|
| 90 |
+
tables?: ObservabilityDataUsedTable[];
|
| 91 |
+
joins?: unknown[];
|
| 92 |
+
columns_read?: ObservabilityDataUsedColumn[];
|
| 93 |
+
output_columns?: ObservabilityDataUsedOutputColumn[];
|
| 94 |
+
filters?: unknown[];
|
| 95 |
+
group_by?: string[];
|
| 96 |
+
order_by?: unknown[];
|
| 97 |
+
limit?: number | null;
|
| 98 |
+
rows_returned?: number;
|
| 99 |
+
query?: string;
|
| 100 |
}
|
| 101 |
|
| 102 |
export interface Observability {
|
|
|
|
| 107 |
planning: ObservabilityPlanning | null;
|
| 108 |
thinking: string | null;
|
| 109 |
tool_calls: ObservabilityToolCall[];
|
| 110 |
+
data_used?: ObservabilityDataUsed[];
|
| 111 |
sources: unknown[];
|
| 112 |
}
|
| 113 |
|