@agent-native/core 0.183.0 → 0.184.0-nightly-20260921210811
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/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +26 -1
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +41 -17
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +22 -15
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +62 -30
- package/corpus/templates/design/app/components/design/multi-screen/primitive-drop-target.ts +10 -1
- package/corpus/templates/design/app/pages/design-editor/commands/commit-visual-styles.ts +3 -12
- package/corpus/templates/design/app/pages/design-editor/commands/nudge-selection.ts +37 -3
- package/corpus/templates/design/app/pages/design-editor/commands/redo.ts +5 -2
- package/dist/chat-threads/store.d.ts +1 -0
- package/dist/chat-threads/store.js +19 -0
- package/dist/client/observability/ObservabilityDashboard.js +113 -3
- package/dist/client/observability/useObservability.d.ts +9 -0
- package/dist/client/observability/useObservability.js +12 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/identity/rekey.js +5 -0
- package/dist/localization/default-messages.d.ts +24 -0
- package/dist/localization/default-messages.js +24 -0
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/actions/list-observability-reviews.d.ts +5 -0
- package/dist/observability/actions/list-observability-reviews.js +23 -0
- package/dist/observability/actions/save-observability-instruction-update.d.ts +9 -0
- package/dist/observability/actions/save-observability-instruction-update.js +38 -0
- package/dist/observability/index.d.ts +2 -2
- package/dist/observability/index.js +1 -1
- package/dist/observability/reviews.d.ts +6 -0
- package/dist/observability/reviews.js +155 -0
- package/dist/observability/routes.d.ts +8 -8
- package/dist/observability/store.d.ts +8 -1
- package/dist/observability/store.js +77 -0
- package/dist/observability/types.d.ts +23 -0
- package/dist/org/handlers.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +17 -17
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/server/agent-engine-api-key-route.d.ts +2 -2
- package/dist/server/core-routes-plugin.d.ts +1 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/templates/default/app/i18n/ar-SA.ts +25 -0
- package/dist/templates/default/app/i18n/de-DE.ts +25 -0
- package/dist/templates/default/app/i18n/en-US.ts +26 -0
- package/dist/templates/default/app/i18n/es-ES.ts +26 -0
- package/dist/templates/default/app/i18n/fr-FR.ts +26 -0
- package/dist/templates/default/app/i18n/hi-IN.ts +25 -0
- package/dist/templates/default/app/i18n/ja-JP.ts +25 -0
- package/dist/templates/default/app/i18n/ko-KR.ts +25 -0
- package/dist/templates/default/app/i18n/pt-BR.ts +25 -0
- package/dist/templates/default/app/i18n/zh-CN.ts +24 -0
- package/dist/templates/default/app/i18n/zh-TW.ts +24 -0
- package/dist/vite/action-types-plugin.js +8 -0
- package/package.json +5 -3
- package/src/templates/default/app/i18n/ar-SA.ts +25 -0
- package/src/templates/default/app/i18n/de-DE.ts +25 -0
- package/src/templates/default/app/i18n/en-US.ts +26 -0
- package/src/templates/default/app/i18n/es-ES.ts +26 -0
- package/src/templates/default/app/i18n/fr-FR.ts +26 -0
- package/src/templates/default/app/i18n/hi-IN.ts +25 -0
- package/src/templates/default/app/i18n/ja-JP.ts +25 -0
- package/src/templates/default/app/i18n/ko-KR.ts +25 -0
- package/src/templates/default/app/i18n/pt-BR.ts +25 -0
- package/src/templates/default/app/i18n/zh-CN.ts +24 -0
- package/src/templates/default/app/i18n/zh-TW.ts +24 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { IconActivity, IconMessages, IconThumbUp, IconThumbDown, IconClock, IconCoin, IconTool, IconMoodSmile, IconChartBar, IconAB2, IconMessageReport, IconChevronRight, IconArrowLeft, IconLoader2, IconAlertTriangle, } from "@tabler/icons-react";
|
|
3
|
-
import {
|
|
3
|
+
import { useQueryClient } from "@tanstack/react-query";
|
|
4
|
+
import { Fragment, useEffect, useState } from "react";
|
|
4
5
|
import { useT } from "../i18n.js";
|
|
5
6
|
import { cn } from "../utils.js";
|
|
6
|
-
import { useObservabilityOverview, useTraces, useTraceDetail, useFeedbackList, useFeedbackStats, useSatisfaction, useEvalStats, useExperiments, useExperimentDetail, useExperimentResults, } from "./useObservability.js";
|
|
7
|
+
import { useObservabilityOverview, useTraces, useTraceDetail, useFeedbackList, useFeedbackStats, useSatisfaction, useEvalStats, useExperiments, useExperimentDetail, useExperimentResults, useOutputReviews, useSaveInstructionUpdate, useSubmitFeedback, } from "./useObservability.js";
|
|
7
8
|
// ─── Helpers ────────────────────────────────────────────────────────────
|
|
8
9
|
function formatCost(centsX100) {
|
|
9
10
|
const cents = centsX100 / 100;
|
|
@@ -138,6 +139,110 @@ function ExperimentDetailView({ id, onBack, }) {
|
|
|
138
139
|
const { data: results } = useExperimentResults(id);
|
|
139
140
|
return (_jsxs("div", { children: [_jsxs("button", { onClick: onBack, className: "flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground mb-3", children: [_jsx(IconArrowLeft, { size: 14 }), t("observability.backToExperiments")] }), isLoading && _jsx(LoadingState, {}), exp && (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex items-center justify-between gap-2 min-w-0", children: [_jsx("h3", { className: "text-sm font-medium text-foreground truncate min-w-0", children: exp.name }), _jsx(StatusBadge, { status: exp.status })] }), _jsxs("div", { className: "grid grid-cols-3 gap-3", children: [_jsxs("div", { className: "rounded-lg border border-border p-3", children: [_jsx("div", { className: "text-[10px] text-muted-foreground mb-1", children: t("observability.variants") }), _jsx("div", { className: "text-sm font-medium tabular-nums text-foreground", children: exp.variants.length })] }), _jsxs("div", { className: "rounded-lg border border-border p-3", children: [_jsx("div", { className: "text-[10px] text-muted-foreground mb-1", children: t("observability.metrics") }), _jsx("div", { className: "text-sm font-medium tabular-nums text-foreground", children: exp.metrics.length })] }), _jsxs("div", { className: "rounded-lg border border-border p-3", children: [_jsx("div", { className: "text-[10px] text-muted-foreground mb-1", children: t("observability.level") }), _jsx("div", { className: "text-sm font-medium text-foreground capitalize", children: exp.assignmentLevel })] })] }), exp.variants.length > 0 && (_jsxs("div", { children: [_jsx("h4", { className: "text-xs font-medium text-foreground mb-2", children: t("observability.variants") }), _jsx("div", { className: "space-y-1", children: exp.variants.map((v) => (_jsxs("div", { className: "flex items-center justify-between rounded border border-border px-3 py-2 text-xs", children: [_jsx("span", { className: "font-mono text-foreground", children: truncateId(v.id) }), _jsxs("span", { className: "text-muted-foreground tabular-nums", children: ["Weight: ", v.weight] })] }, v.id))) })] })), results && results.length > 0 && (_jsxs("div", { children: [_jsx("h4", { className: "text-xs font-medium text-foreground mb-2", children: t("observability.results") }), _jsx("div", { className: "rounded-lg border border-border overflow-hidden", children: _jsxs("table", { className: "w-full table-fixed text-left text-xs", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b border-border bg-muted/30", children: [_jsx("th", { className: "px-3 py-2 font-medium text-muted-foreground w-[20%]", children: t("observability.variant") }), _jsx("th", { className: "px-3 py-2 font-medium text-muted-foreground w-[25%]", children: t("observability.metric") }), _jsx("th", { className: "px-3 py-2 font-medium text-muted-foreground", children: t("observability.value") }), _jsx("th", { className: "px-3 py-2 font-medium text-muted-foreground", children: "CI" }), _jsx("th", { className: "px-3 py-2 font-medium text-muted-foreground", children: "N" })] }) }), _jsx("tbody", { children: results.map((r) => (_jsxs("tr", { className: "border-b border-border last:border-b-0", children: [_jsx("td", { className: "px-3 py-2 font-mono text-foreground truncate", children: truncateId(r.variantId) }), _jsx("td", { className: "px-3 py-2 text-foreground truncate", children: r.metric }), _jsx("td", { className: "px-3 py-2 tabular-nums text-foreground", children: r.value.toFixed(3) }), _jsxs("td", { className: "px-3 py-2 tabular-nums text-muted-foreground", children: ["[", r.confidenceLow.toFixed(3), ",", " ", r.confidenceHigh.toFixed(3), "]"] }), _jsx("td", { className: "px-3 py-2 tabular-nums text-muted-foreground", children: r.sampleSize })] }, r.id))) })] }) })] }))] }))] }));
|
|
140
141
|
}
|
|
142
|
+
// ─── Tab: Human review ─────────────────────────────────────────────────
|
|
143
|
+
function ReviewTab({ days }) {
|
|
144
|
+
const t = useT();
|
|
145
|
+
const { data: reviews, isLoading } = useOutputReviews(days);
|
|
146
|
+
const feedbackMutation = useSubmitFeedback();
|
|
147
|
+
const instructionMutation = useSaveInstructionUpdate();
|
|
148
|
+
const queryClient = useQueryClient();
|
|
149
|
+
const [selectedRunId, setSelectedRunId] = useState(null);
|
|
150
|
+
const [feedbackNote, setFeedbackNote] = useState("");
|
|
151
|
+
const [instruction, setInstruction] = useState("");
|
|
152
|
+
const [instructionSaved, setInstructionSaved] = useState(false);
|
|
153
|
+
const [target, setTarget] = useState("agent");
|
|
154
|
+
const selected = reviews?.find((review) => review.runId === selectedRunId);
|
|
155
|
+
useEffect(() => {
|
|
156
|
+
if (selectedRunId &&
|
|
157
|
+
reviews &&
|
|
158
|
+
!reviews.some((review) => review.runId === selectedRunId)) {
|
|
159
|
+
setSelectedRunId(null);
|
|
160
|
+
}
|
|
161
|
+
}, [reviews, selectedRunId]);
|
|
162
|
+
if (isLoading)
|
|
163
|
+
return _jsx(LoadingState, {});
|
|
164
|
+
if (!reviews || reviews.length === 0) {
|
|
165
|
+
return _jsx(EmptyState, { message: t("observability.noReviews") });
|
|
166
|
+
}
|
|
167
|
+
const openReview = (runId) => {
|
|
168
|
+
setSelectedRunId((current) => (current === runId ? null : runId));
|
|
169
|
+
setFeedbackNote("");
|
|
170
|
+
setInstruction("");
|
|
171
|
+
setInstructionSaved(false);
|
|
172
|
+
setTarget("agent");
|
|
173
|
+
};
|
|
174
|
+
const saveFeedback = (feedbackType) => {
|
|
175
|
+
if (!selected)
|
|
176
|
+
return;
|
|
177
|
+
feedbackMutation.mutate({
|
|
178
|
+
runId: selected.runId,
|
|
179
|
+
threadId: selected.threadId ?? undefined,
|
|
180
|
+
feedbackType,
|
|
181
|
+
}, {
|
|
182
|
+
onSuccess: () => void queryClient.invalidateQueries({
|
|
183
|
+
queryKey: ["action", "list-observability-reviews"],
|
|
184
|
+
}),
|
|
185
|
+
});
|
|
186
|
+
};
|
|
187
|
+
const saveNote = () => {
|
|
188
|
+
if (!selected || !feedbackNote.trim())
|
|
189
|
+
return;
|
|
190
|
+
feedbackMutation.mutate({
|
|
191
|
+
runId: selected.runId,
|
|
192
|
+
threadId: selected.threadId ?? undefined,
|
|
193
|
+
feedbackType: "text",
|
|
194
|
+
value: feedbackNote.trim(),
|
|
195
|
+
}, {
|
|
196
|
+
onSuccess: () => {
|
|
197
|
+
setFeedbackNote("");
|
|
198
|
+
void queryClient.invalidateQueries({
|
|
199
|
+
queryKey: ["action", "list-observability-reviews"],
|
|
200
|
+
});
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
};
|
|
204
|
+
const saveInstruction = () => {
|
|
205
|
+
if (!selected || !instruction.trim())
|
|
206
|
+
return;
|
|
207
|
+
instructionMutation.mutate({
|
|
208
|
+
runId: selected.runId,
|
|
209
|
+
threadId: selected.threadId,
|
|
210
|
+
target,
|
|
211
|
+
instruction: instruction.trim(),
|
|
212
|
+
feedback: feedbackNote.trim() || undefined,
|
|
213
|
+
}, {
|
|
214
|
+
onSuccess: () => {
|
|
215
|
+
setFeedbackNote("");
|
|
216
|
+
setInstruction("");
|
|
217
|
+
setInstructionSaved(true);
|
|
218
|
+
setTarget("agent");
|
|
219
|
+
void queryClient.invalidateQueries({
|
|
220
|
+
queryKey: ["action", "list-observability-reviews"],
|
|
221
|
+
});
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
};
|
|
225
|
+
return (_jsxs("div", { className: "space-y-3", children: [_jsx("div", { className: "rounded-lg border border-border bg-muted/20 px-3 py-2 text-xs text-muted-foreground", children: t("observability.reviewDescription") }), _jsx("div", { className: "overflow-x-auto rounded-lg border border-border", children: _jsxs("table", { className: "w-full min-w-[760px] table-fixed text-left text-xs", children: [_jsx("thead", { className: "bg-muted/30 text-muted-foreground", children: _jsxs("tr", { children: [_jsx("th", { className: "w-[28%] px-3 py-2 font-medium", children: t("observability.ask") }), _jsx("th", { className: "w-[40%] px-3 py-2 font-medium", children: t("observability.answer") }), _jsx("th", { className: "w-[16%] px-3 py-2 font-medium", children: t("observability.reviewFeedback") }), _jsx("th", { className: "w-[16%] px-3 py-2 font-medium" })] }) }), _jsx("tbody", { children: reviews.map((review) => {
|
|
226
|
+
const isSelected = review.runId === selectedRunId;
|
|
227
|
+
const latestFeedback = review.feedback[0];
|
|
228
|
+
return (_jsxs(Fragment, { children: [_jsxs("tr", { className: "border-t border-border align-top", children: [_jsx("td", { className: "px-3 py-3 text-foreground", children: _jsx("div", { className: "line-clamp-3 break-words", children: review.ask || "-" }) }), _jsx("td", { className: "px-3 py-3 text-foreground", children: _jsx("div", { className: "line-clamp-3 break-words", children: review.answer || "-" }) }), _jsx("td", { className: "px-3 py-3 text-muted-foreground", children: latestFeedback
|
|
229
|
+
? latestFeedback.feedbackType === "text"
|
|
230
|
+
? t("observability.noteSaved")
|
|
231
|
+
: latestFeedback.feedbackType === "thumbs_up"
|
|
232
|
+
? t("observability.looksGood")
|
|
233
|
+
: t("observability.needsChange")
|
|
234
|
+
: t("observability.notReviewed") }), _jsx("td", { className: "px-3 py-3 text-right", children: _jsx("button", { type: "button", onClick: () => openReview(review.runId), className: "rounded-md border border-border px-2.5 py-1.5 font-medium text-foreground hover:bg-muted", children: isSelected
|
|
235
|
+
? t("observability.closeReview")
|
|
236
|
+
: t("observability.reviewOutput") }) })] }), isSelected && selected && (_jsx("tr", { className: "border-t border-border", children: _jsx("td", { colSpan: 4, className: "bg-muted/10 p-4", children: _jsxs("div", { className: "grid gap-4 lg:grid-cols-2", children: [_jsxs("div", { className: "space-y-3", children: [_jsxs("div", { children: [_jsx("div", { className: "mb-1 text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: t("observability.ask") }), _jsx("p", { className: "whitespace-pre-wrap break-words text-sm text-foreground", children: selected.ask || "-" })] }), _jsxs("div", { children: [_jsx("div", { className: "mb-1 text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: t("observability.answer") }), _jsx("p", { className: "max-h-48 overflow-y-auto whitespace-pre-wrap break-words text-sm text-foreground", children: selected.answer || "-" })] }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx("button", { type: "button", onClick: () => saveFeedback("thumbs_up"), className: "rounded-md border border-border px-2.5 py-1.5 text-xs text-foreground hover:bg-muted", children: t("observability.looksGood") }), _jsx("button", { type: "button", onClick: () => saveFeedback("thumbs_down"), className: "rounded-md border border-border px-2.5 py-1.5 text-xs text-foreground hover:bg-muted", children: t("observability.needsChange") })] })] }), _jsxs("div", { className: "space-y-3", children: [_jsxs("label", { className: "block", children: [_jsx("span", { className: "mb-1 block text-xs font-medium text-foreground", children: t("observability.feedbackNote") }), _jsx("textarea", { value: feedbackNote, onChange: (event) => setFeedbackNote(event.target.value), rows: 3, className: "w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground outline-none focus:ring-2 focus:ring-ring", placeholder: t("observability.feedbackPlaceholder") })] }), _jsx("button", { type: "button", onClick: saveNote, disabled: !feedbackNote.trim() ||
|
|
237
|
+
feedbackMutation.isPending, className: "rounded-md bg-primary px-2.5 py-1.5 text-xs font-medium text-primary-foreground disabled:opacity-50", children: t("observability.saveFeedback") }), _jsxs("div", { className: "border-t border-border pt-3", children: [_jsx("div", { className: "mb-1 text-xs font-medium text-foreground", children: t("observability.updateInstructions") }), _jsx("p", { className: "mb-2 text-[11px] text-muted-foreground", children: t("observability.draftNotice") }), _jsx("div", { className: "flex gap-2", children: _jsxs("select", { value: target, onChange: (event) => setTarget(event.target.value), className: "rounded-md border border-border bg-background px-2 py-1.5 text-xs text-foreground", "aria-label": t("observability.instructionTarget"), children: [_jsx("option", { value: "agent", children: t("observability.agentTarget") }), _jsx("option", { value: "developer", children: t("observability.developerTarget") }), _jsx("option", { value: "skill", children: t("observability.skillTarget") })] }) }), _jsx("textarea", { value: instruction, onChange: (event) => {
|
|
238
|
+
setInstruction(event.target.value);
|
|
239
|
+
setInstructionSaved(false);
|
|
240
|
+
}, rows: 4, className: "mt-2 w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground outline-none focus:ring-2 focus:ring-ring", placeholder: t("observability.instructionPlaceholder") }), _jsx("button", { type: "button", onClick: saveInstruction, disabled: !instruction.trim() ||
|
|
241
|
+
instructionMutation.isPending, className: "mt-2 rounded-md border border-border px-2.5 py-1.5 text-xs font-medium text-foreground hover:bg-muted disabled:opacity-50", children: instructionSaved
|
|
242
|
+
? t("observability.draftSaved")
|
|
243
|
+
: t("observability.saveUpdate") })] })] })] }) }) }))] }, review.runId));
|
|
244
|
+
}) })] }) })] }));
|
|
245
|
+
}
|
|
141
246
|
// ─── Tab: Feedback ──────────────────────────────────────────────────────
|
|
142
247
|
function FeedbackTab({ days }) {
|
|
143
248
|
const t = useT();
|
|
@@ -177,6 +282,11 @@ const TABS = [
|
|
|
177
282
|
labelKey: "observability.feedback",
|
|
178
283
|
icon: IconMessageReport,
|
|
179
284
|
},
|
|
285
|
+
{
|
|
286
|
+
id: "review",
|
|
287
|
+
labelKey: "observability.review",
|
|
288
|
+
icon: IconMessageReport,
|
|
289
|
+
},
|
|
180
290
|
];
|
|
181
291
|
export function ObservabilityDashboard({ className, }) {
|
|
182
292
|
const t = useT();
|
|
@@ -187,5 +297,5 @@ export function ObservabilityDashboard({ className, }) {
|
|
|
187
297
|
return (_jsxs("button", { onClick: () => setActiveTab(tab.id), className: cn("flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium", activeTab === tab.id
|
|
188
298
|
? "bg-background text-foreground shadow-sm"
|
|
189
299
|
: "text-muted-foreground hover:text-foreground"), children: [_jsx(Icon, { size: 14 }), t(tab.labelKey)] }, tab.id));
|
|
190
|
-
}) }), activeTab !== "experiments" && (_jsx(RangeSelector, { value: days, onChange: setDays }))] }), activeTab === "overview" && _jsx(OverviewTab, { days: days }), activeTab === "conversations" && _jsx(ConversationsTab, { days: days }), activeTab === "evals" && _jsx(EvalsTab, { days: days }), activeTab === "experiments" && _jsx(ExperimentsTab, {}), activeTab === "feedback" && _jsx(FeedbackTab, { days: days })] }));
|
|
300
|
+
}) }), activeTab !== "experiments" && (_jsx(RangeSelector, { value: days, onChange: setDays }))] }), activeTab === "overview" && _jsx(OverviewTab, { days: days }), activeTab === "conversations" && _jsx(ConversationsTab, { days: days }), activeTab === "evals" && _jsx(EvalsTab, { days: days }), activeTab === "experiments" && _jsx(ExperimentsTab, {}), activeTab === "feedback" && _jsx(FeedbackTab, { days: days }), activeTab === "review" && _jsx(ReviewTab, { days: days })] }));
|
|
191
301
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { InstructionUpdate, OutputReviewRow } from "../../observability/types.js";
|
|
1
2
|
export interface ObservabilityOverview {
|
|
2
3
|
totalRuns: number;
|
|
3
4
|
totalCostCents: number;
|
|
@@ -24,6 +25,14 @@ export interface TraceSummary {
|
|
|
24
25
|
createdAt: number;
|
|
25
26
|
}
|
|
26
27
|
export declare function useTraces(sinceDays?: number, limit?: number): import("@tanstack/react-query").UseQueryResult<NoInfer<TraceSummary[]>, Error>;
|
|
28
|
+
export declare function useOutputReviews(sinceDays?: number, limit?: number): import("@tanstack/react-query").UseQueryResult<NoInfer<OutputReviewRow[]>, Error>;
|
|
29
|
+
export declare function useSaveInstructionUpdate(): import("@tanstack/react-query").UseMutationResult<InstructionUpdate, Error, {
|
|
30
|
+
runId: string;
|
|
31
|
+
threadId?: string | null;
|
|
32
|
+
target: "agent" | "developer" | "skill";
|
|
33
|
+
instruction: string;
|
|
34
|
+
feedback?: string;
|
|
35
|
+
}, unknown>;
|
|
27
36
|
export interface TraceSpan {
|
|
28
37
|
id: string;
|
|
29
38
|
runId: string;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
2
|
+
import { useMemo } from "react";
|
|
2
3
|
import { agentNativePath } from "../api-path.js";
|
|
4
|
+
import { useActionMutation, useActionQuery } from "../use-action.js";
|
|
3
5
|
const BASE = agentNativePath("/_agent-native/observability");
|
|
4
6
|
function fetchJson(url) {
|
|
5
7
|
return fetch(url).then((r) => {
|
|
@@ -24,6 +26,16 @@ export function useTraces(sinceDays = 7, limit = 100) {
|
|
|
24
26
|
refetchInterval: 30_000,
|
|
25
27
|
});
|
|
26
28
|
}
|
|
29
|
+
export function useOutputReviews(sinceDays = 7, limit = 100) {
|
|
30
|
+
const params = useMemo(() => ({
|
|
31
|
+
sinceMs: Date.now() - sinceDays * 86_400_000,
|
|
32
|
+
limit,
|
|
33
|
+
}), [sinceDays, limit]);
|
|
34
|
+
return useActionQuery("list-observability-reviews", params, { refetchInterval: 30_000 });
|
|
35
|
+
}
|
|
36
|
+
export function useSaveInstructionUpdate() {
|
|
37
|
+
return useActionMutation("save-observability-instruction-update");
|
|
38
|
+
}
|
|
27
39
|
export function useTraceDetail(runId) {
|
|
28
40
|
return useQuery({
|
|
29
41
|
queryKey: ["observability", "trace", runId],
|
|
@@ -62,11 +62,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
|
|
|
62
62
|
error: string;
|
|
63
63
|
states?: undefined;
|
|
64
64
|
} | {
|
|
65
|
+
error?: undefined;
|
|
65
66
|
states: {
|
|
66
67
|
clientId: number;
|
|
67
68
|
state: string;
|
|
68
69
|
}[];
|
|
69
|
-
error?: undefined;
|
|
70
70
|
}>>;
|
|
71
71
|
/**
|
|
72
72
|
* GET /_agent-native/collab/:docId/users
|
|
@@ -77,9 +77,9 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
|
|
|
77
77
|
error: string;
|
|
78
78
|
users?: undefined;
|
|
79
79
|
} | {
|
|
80
|
+
error?: undefined;
|
|
80
81
|
users: {
|
|
81
82
|
clientId: number;
|
|
82
83
|
lastSeen: number;
|
|
83
84
|
}[];
|
|
84
|
-
error?: undefined;
|
|
85
85
|
}>>;
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* Body: { json: any, fieldName?: string, type?: "map"|"array", requestSource?: string }
|
|
14
14
|
*/
|
|
15
15
|
export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
16
|
-
error: string;
|
|
17
16
|
ok?: undefined;
|
|
17
|
+
error: string;
|
|
18
18
|
} | {
|
|
19
19
|
error?: undefined;
|
|
20
20
|
ok: boolean;
|
|
@@ -34,12 +34,12 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
34
34
|
idempotencyKey: string;
|
|
35
35
|
deleted: boolean;
|
|
36
36
|
} | {
|
|
37
|
+
id?: undefined;
|
|
37
38
|
error: string;
|
|
38
39
|
url?: undefined;
|
|
39
40
|
provider?: undefined;
|
|
40
41
|
configured?: undefined;
|
|
41
42
|
connectPath?: undefined;
|
|
42
|
-
id?: undefined;
|
|
43
43
|
} | {
|
|
44
44
|
url: string;
|
|
45
45
|
id: string;
|
|
@@ -48,11 +48,11 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
48
48
|
connectPath?: undefined;
|
|
49
49
|
error?: undefined;
|
|
50
50
|
} | {
|
|
51
|
+
id?: undefined;
|
|
51
52
|
url?: undefined;
|
|
52
53
|
provider?: undefined;
|
|
53
54
|
error: string;
|
|
54
55
|
configured: boolean;
|
|
55
56
|
connectPath: string;
|
|
56
|
-
id?: undefined;
|
|
57
57
|
}>;
|
|
58
58
|
export default _default;
|
package/dist/identity/rekey.js
CHANGED
|
@@ -28,6 +28,11 @@ export const IDENTITY_REKEY_COLUMNS = [
|
|
|
28
28
|
column: "user_id",
|
|
29
29
|
mode: "email-user-id",
|
|
30
30
|
},
|
|
31
|
+
{
|
|
32
|
+
table: "agent_instruction_updates",
|
|
33
|
+
column: "user_id",
|
|
34
|
+
mode: "email-user-id",
|
|
35
|
+
},
|
|
31
36
|
{ table: "agent_evals", column: "user_id", mode: "email-user-id" },
|
|
32
37
|
{
|
|
33
38
|
table: "agent_experiment_assignments",
|
|
@@ -1547,6 +1547,30 @@ declare const messages: {
|
|
|
1547
1547
|
frustration: string;
|
|
1548
1548
|
thumbsUpRate: string;
|
|
1549
1549
|
categories: string;
|
|
1550
|
+
review: string;
|
|
1551
|
+
reviewDescription: string;
|
|
1552
|
+
ask: string;
|
|
1553
|
+
answer: string;
|
|
1554
|
+
reviewFeedback: string;
|
|
1555
|
+
reviewOutput: string;
|
|
1556
|
+
closeReview: string;
|
|
1557
|
+
notReviewed: string;
|
|
1558
|
+
noteSaved: string;
|
|
1559
|
+
looksGood: string;
|
|
1560
|
+
needsChange: string;
|
|
1561
|
+
feedbackNote: string;
|
|
1562
|
+
feedbackPlaceholder: string;
|
|
1563
|
+
saveFeedback: string;
|
|
1564
|
+
updateInstructions: string;
|
|
1565
|
+
draftNotice: string;
|
|
1566
|
+
instructionTarget: string;
|
|
1567
|
+
agentTarget: string;
|
|
1568
|
+
developerTarget: string;
|
|
1569
|
+
skillTarget: string;
|
|
1570
|
+
instructionPlaceholder: string;
|
|
1571
|
+
saveUpdate: string;
|
|
1572
|
+
draftSaved: string;
|
|
1573
|
+
noReviews: string;
|
|
1550
1574
|
};
|
|
1551
1575
|
error: {
|
|
1552
1576
|
genericTitle: string;
|
|
@@ -1554,6 +1554,30 @@ const messages = {
|
|
|
1554
1554
|
frustration: "Frustration",
|
|
1555
1555
|
thumbsUpRate: "Thumbs up rate",
|
|
1556
1556
|
categories: "Categories",
|
|
1557
|
+
review: "Human review",
|
|
1558
|
+
reviewDescription: "Review the ask and answer, record feedback, and draft an instruction update.",
|
|
1559
|
+
ask: "What was asked",
|
|
1560
|
+
answer: "What the agent answered",
|
|
1561
|
+
reviewFeedback: "Feedback",
|
|
1562
|
+
reviewOutput: "Review output",
|
|
1563
|
+
closeReview: "Close",
|
|
1564
|
+
notReviewed: "Not reviewed",
|
|
1565
|
+
noteSaved: "Note saved",
|
|
1566
|
+
looksGood: "Looks good",
|
|
1567
|
+
needsChange: "Needs change",
|
|
1568
|
+
feedbackNote: "Feedback note",
|
|
1569
|
+
feedbackPlaceholder: "What should change or stay the same?",
|
|
1570
|
+
saveFeedback: "Save feedback",
|
|
1571
|
+
updateInstructions: "Update instructions",
|
|
1572
|
+
draftNotice: "Draft only - nothing changes automatically.",
|
|
1573
|
+
instructionTarget: "Instruction target",
|
|
1574
|
+
agentTarget: "Agent",
|
|
1575
|
+
developerTarget: "Developer",
|
|
1576
|
+
skillTarget: "Skill",
|
|
1577
|
+
instructionPlaceholder: "Write the instruction change for a human to review.",
|
|
1578
|
+
saveUpdate: "Save draft update",
|
|
1579
|
+
draftSaved: "Draft saved",
|
|
1580
|
+
noReviews: "No agent outputs to review yet",
|
|
1557
1581
|
},
|
|
1558
1582
|
error: {
|
|
1559
1583
|
genericTitle: "Something went wrong",
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { fail, defineAction } from "../../action.js";
|
|
3
|
+
import { listOutputReviews } from "../reviews.js";
|
|
4
|
+
export default defineAction({
|
|
5
|
+
description: "List recent agent outputs as a human-review table with the original ask, answer, feedback, and pending instruction updates.",
|
|
6
|
+
schema: z.object({
|
|
7
|
+
sinceMs: z.number().int().nonnegative().optional(),
|
|
8
|
+
limit: z.number().int().positive().max(100).optional(),
|
|
9
|
+
}),
|
|
10
|
+
http: { method: "GET" },
|
|
11
|
+
readOnly: true,
|
|
12
|
+
parallelSafe: true,
|
|
13
|
+
run: async (args, ctx) => {
|
|
14
|
+
const userId = ctx?.userEmail;
|
|
15
|
+
if (!userId)
|
|
16
|
+
fail("Sign in to review agent outputs.", { statusCode: 401 });
|
|
17
|
+
return listOutputReviews({
|
|
18
|
+
sinceMs: args.sinceMs ?? Date.now() - 7 * 86_400_000,
|
|
19
|
+
limit: args.limit ?? 100,
|
|
20
|
+
userId,
|
|
21
|
+
});
|
|
22
|
+
},
|
|
23
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { InstructionUpdate } from "../types.js";
|
|
2
|
+
declare const _default: import("../../action.js").ActionDefinition<{
|
|
3
|
+
runId: string;
|
|
4
|
+
threadId?: string | null | undefined;
|
|
5
|
+
target: "agent" | "developer" | "skill";
|
|
6
|
+
instruction: string;
|
|
7
|
+
feedback?: string | undefined;
|
|
8
|
+
}, InstructionUpdate>;
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { fail, defineAction } from "../../action.js";
|
|
4
|
+
import { getTraceSummary, insertInstructionUpdate } from "../store.js";
|
|
5
|
+
const schema = z.object({
|
|
6
|
+
runId: z.string().trim().min(1).max(200),
|
|
7
|
+
threadId: z.string().trim().max(200).nullable().optional(),
|
|
8
|
+
target: z.enum(["agent", "developer", "skill"]),
|
|
9
|
+
instruction: z.string().trim().min(1).max(10_000),
|
|
10
|
+
feedback: z.string().trim().max(4_000).optional(),
|
|
11
|
+
});
|
|
12
|
+
export default defineAction({
|
|
13
|
+
description: "Save a human-proposed instruction update for an agent output. The draft is explicit and never applied automatically.",
|
|
14
|
+
schema,
|
|
15
|
+
run: async (args, ctx) => {
|
|
16
|
+
const userId = ctx?.userEmail;
|
|
17
|
+
if (!userId)
|
|
18
|
+
fail("Sign in to save instruction updates.", { statusCode: 401 });
|
|
19
|
+
const summary = await getTraceSummary(args.runId, { userId });
|
|
20
|
+
if (!summary)
|
|
21
|
+
fail("That agent output is no longer available.", { statusCode: 404 });
|
|
22
|
+
const now = Date.now();
|
|
23
|
+
const update = {
|
|
24
|
+
id: `instruction-${randomUUID()}`,
|
|
25
|
+
runId: args.runId,
|
|
26
|
+
threadId: args.threadId ?? summary.threadId,
|
|
27
|
+
target: args.target,
|
|
28
|
+
instruction: args.instruction,
|
|
29
|
+
feedback: args.feedback ?? "",
|
|
30
|
+
status: "draft",
|
|
31
|
+
userId,
|
|
32
|
+
createdAt: now,
|
|
33
|
+
updatedAt: now,
|
|
34
|
+
};
|
|
35
|
+
await insertInstructionUpdate(update);
|
|
36
|
+
return update;
|
|
37
|
+
},
|
|
38
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export type { SpanType, SpanStatus, TraceSpan, TraceSummary, FeedbackType, FeedbackEntry, SatisfactionScore, EvalType, EvalResult, EvalDataset, EvalTestCase, EvalCriteria, ExperimentStatus, ExperimentVariant, Experiment, ExperimentAssignment, ExperimentMetricResult, ObservabilityConfig, } from "./types.js";
|
|
2
|
-
export { ensureObservabilityTables, insertTraceSpan, upsertTraceSummary, getTraceSpansForRun, getTraceSummaries, getTraceSummary, deleteOldTraceData, insertFeedback, getFeedback, getFeedbackStats, upsertSatisfactionScore, getSatisfactionScores, insertEvalResult, getEvalsForRun, getEvalStats, insertEvalDataset, listEvalDatasets, getEvalDataset, updateEvalDataset, insertExperiment, updateExperiment, listExperiments, getExperiment, upsertAssignment, getAssignment, insertExperimentResult, getExperimentResults, getObservabilityOverview, } from "./store.js";
|
|
1
|
+
export type { SpanType, SpanStatus, TraceSpan, TraceSummary, FeedbackType, FeedbackEntry, InstructionUpdateStatus, InstructionUpdate, OutputReviewRow, SatisfactionScore, EvalType, EvalResult, EvalDataset, EvalTestCase, EvalCriteria, ExperimentStatus, ExperimentVariant, Experiment, ExperimentAssignment, ExperimentMetricResult, ObservabilityConfig, } from "./types.js";
|
|
2
|
+
export { ensureObservabilityTables, insertTraceSpan, upsertTraceSummary, getTraceSpansForRun, getTraceSummaries, getTraceSummary, deleteOldTraceData, insertFeedback, getFeedback, getFeedbackStats, insertInstructionUpdate, getInstructionUpdates, upsertSatisfactionScore, getSatisfactionScores, insertEvalResult, getEvalsForRun, getEvalStats, insertEvalDataset, listEvalDatasets, getEvalDataset, updateEvalDataset, insertExperiment, updateExperiment, listExperiments, getExperiment, upsertAssignment, getAssignment, insertExperimentResult, getExperimentResults, getObservabilityOverview, } from "./store.js";
|
|
3
3
|
export { createObservabilityPlugin } from "./plugin.js";
|
|
4
4
|
export { createObservabilityHandler } from "./routes.js";
|
|
5
5
|
export { runTraceCleanupOnce, startTraceCleanupJob, stopTraceCleanupJob, } from "./cleanup-job.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { ensureObservabilityTables, insertTraceSpan, upsertTraceSummary, getTraceSpansForRun, getTraceSummaries, getTraceSummary, deleteOldTraceData, insertFeedback, getFeedback, getFeedbackStats, upsertSatisfactionScore, getSatisfactionScores, insertEvalResult, getEvalsForRun, getEvalStats, insertEvalDataset, listEvalDatasets, getEvalDataset, updateEvalDataset, insertExperiment, updateExperiment, listExperiments, getExperiment, upsertAssignment, getAssignment, insertExperimentResult, getExperimentResults, getObservabilityOverview, } from "./store.js";
|
|
1
|
+
export { ensureObservabilityTables, insertTraceSpan, upsertTraceSummary, getTraceSpansForRun, getTraceSummaries, getTraceSummary, deleteOldTraceData, insertFeedback, getFeedback, getFeedbackStats, insertInstructionUpdate, getInstructionUpdates, upsertSatisfactionScore, getSatisfactionScores, insertEvalResult, getEvalsForRun, getEvalStats, insertEvalDataset, listEvalDatasets, getEvalDataset, updateEvalDataset, insertExperiment, updateExperiment, listExperiments, getExperiment, upsertAssignment, getAssignment, insertExperimentResult, getExperimentResults, getObservabilityOverview, } from "./store.js";
|
|
2
2
|
export { createObservabilityPlugin } from "./plugin.js";
|
|
3
3
|
export { createObservabilityHandler } from "./routes.js";
|
|
4
4
|
export { runTraceCleanupOnce, startTraceCleanupJob, stopTraceCleanupJob, } from "./cleanup-job.js";
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { resolveThreadsAccess } from "../chat-threads/store.js";
|
|
2
|
+
import { getFeedback, getInstructionUpdates, getTraceSummaries, } from "./store.js";
|
|
3
|
+
function unwrapMessage(value) {
|
|
4
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
5
|
+
return null;
|
|
6
|
+
const record = value;
|
|
7
|
+
const nested = record.message;
|
|
8
|
+
return nested && typeof nested === "object" && !Array.isArray(nested)
|
|
9
|
+
? nested
|
|
10
|
+
: record;
|
|
11
|
+
}
|
|
12
|
+
function messageText(value) {
|
|
13
|
+
if (typeof value === "string")
|
|
14
|
+
return value;
|
|
15
|
+
if (!Array.isArray(value))
|
|
16
|
+
return "";
|
|
17
|
+
return value
|
|
18
|
+
.filter((part) => Boolean(part) &&
|
|
19
|
+
typeof part === "object" &&
|
|
20
|
+
!Array.isArray(part) &&
|
|
21
|
+
part.type === "text")
|
|
22
|
+
.map((part) => (typeof part.text === "string" ? part.text : ""))
|
|
23
|
+
.join("");
|
|
24
|
+
}
|
|
25
|
+
function messageRunId(message) {
|
|
26
|
+
const metadata = message.metadata;
|
|
27
|
+
if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
const meta = metadata;
|
|
31
|
+
const custom = meta.custom;
|
|
32
|
+
const customRecord = custom && typeof custom === "object" && !Array.isArray(custom)
|
|
33
|
+
? custom
|
|
34
|
+
: null;
|
|
35
|
+
const candidates = [
|
|
36
|
+
meta.runId,
|
|
37
|
+
customRecord?.runId,
|
|
38
|
+
customRecord?.submittedRunId,
|
|
39
|
+
];
|
|
40
|
+
return candidates.find((candidate) => typeof candidate === "string" && candidate.length > 0);
|
|
41
|
+
}
|
|
42
|
+
function readThreadMessages(threadData) {
|
|
43
|
+
try {
|
|
44
|
+
const repository = JSON.parse(threadData);
|
|
45
|
+
const values = Array.isArray(repository?.messages)
|
|
46
|
+
? repository.messages
|
|
47
|
+
: [];
|
|
48
|
+
return values.flatMap((value) => {
|
|
49
|
+
const message = unwrapMessage(value);
|
|
50
|
+
if (!message ||
|
|
51
|
+
(message.role !== "user" && message.role !== "assistant")) {
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
if (!Object.prototype.hasOwnProperty.call(message, "content")) {
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
const content = message.content;
|
|
58
|
+
if (typeof content !== "string" && !Array.isArray(content)) {
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
const text = messageText(content).trim();
|
|
62
|
+
return text
|
|
63
|
+
? [{ role: message.role, text, runId: messageRunId(message) }]
|
|
64
|
+
: [];
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
throw new Error("Unable to parse observability thread data", {
|
|
69
|
+
cause: error,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function askAndAnswer(summary, threadData) {
|
|
74
|
+
if (!threadData)
|
|
75
|
+
return { ask: "", answer: "" };
|
|
76
|
+
const messages = readThreadMessages(threadData);
|
|
77
|
+
const askIndex = messages.findIndex((message) => message.role === "user" && message.runId === summary.runId);
|
|
78
|
+
const resolvedAskIndex = askIndex >= 0
|
|
79
|
+
? askIndex
|
|
80
|
+
: messages.filter((message) => message.role === "user").length === 1
|
|
81
|
+
? messages.findIndex((message) => message.role === "user")
|
|
82
|
+
: -1;
|
|
83
|
+
const answerIndex = resolvedAskIndex < 0
|
|
84
|
+
? -1
|
|
85
|
+
: messages.findIndex((message, index) => {
|
|
86
|
+
if (index <= resolvedAskIndex || message.role === "user") {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
if (message.role !== "assistant")
|
|
90
|
+
return false;
|
|
91
|
+
return message.runId === summary.runId || !message.runId;
|
|
92
|
+
});
|
|
93
|
+
return {
|
|
94
|
+
ask: resolvedAskIndex >= 0 ? messages[resolvedAskIndex].text : "",
|
|
95
|
+
answer: answerIndex >= 0 ? messages[answerIndex].text : "",
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
export async function listOutputReviews(opts) {
|
|
99
|
+
const summaries = await getTraceSummaries({
|
|
100
|
+
sinceMs: opts.sinceMs,
|
|
101
|
+
limit: opts.limit,
|
|
102
|
+
userId: opts.userId,
|
|
103
|
+
});
|
|
104
|
+
const [feedback, updates] = await Promise.all([
|
|
105
|
+
getFeedback({
|
|
106
|
+
sinceMs: opts.sinceMs,
|
|
107
|
+
limit: opts.limit * 4,
|
|
108
|
+
userId: opts.userId,
|
|
109
|
+
}),
|
|
110
|
+
getInstructionUpdates({
|
|
111
|
+
sinceMs: opts.sinceMs,
|
|
112
|
+
limit: opts.limit * 2,
|
|
113
|
+
userId: opts.userId,
|
|
114
|
+
}),
|
|
115
|
+
]);
|
|
116
|
+
const feedbackByRun = groupByRun(feedback);
|
|
117
|
+
const updateByRun = new Map();
|
|
118
|
+
for (const update of updates) {
|
|
119
|
+
if (!updateByRun.has(update.runId))
|
|
120
|
+
updateByRun.set(update.runId, update);
|
|
121
|
+
}
|
|
122
|
+
const threadIds = summaries.flatMap((summary) => summary.threadId ? [summary.threadId] : []);
|
|
123
|
+
const threads = await resolveThreadsAccess(opts.userId, threadIds);
|
|
124
|
+
return summaries
|
|
125
|
+
.map((summary) => {
|
|
126
|
+
const thread = summary.threadId
|
|
127
|
+
? (threads.get(summary.threadId) ?? null)
|
|
128
|
+
: null;
|
|
129
|
+
if (summary.threadId && !thread)
|
|
130
|
+
return null;
|
|
131
|
+
const { ask, answer } = askAndAnswer(summary, thread?.threadData ?? null);
|
|
132
|
+
return {
|
|
133
|
+
runId: summary.runId,
|
|
134
|
+
threadId: summary.threadId,
|
|
135
|
+
ask,
|
|
136
|
+
answer,
|
|
137
|
+
model: summary.model,
|
|
138
|
+
createdAt: summary.createdAt,
|
|
139
|
+
feedback: feedbackByRun.get(summary.runId) ?? [],
|
|
140
|
+
instructionUpdate: updateByRun.get(summary.runId) ?? null,
|
|
141
|
+
};
|
|
142
|
+
})
|
|
143
|
+
.filter((row) => row !== null);
|
|
144
|
+
}
|
|
145
|
+
function groupByRun(entries) {
|
|
146
|
+
const grouped = new Map();
|
|
147
|
+
for (const entry of entries) {
|
|
148
|
+
if (!entry.runId)
|
|
149
|
+
continue;
|
|
150
|
+
const current = grouped.get(entry.runId) ?? [];
|
|
151
|
+
current.push(entry);
|
|
152
|
+
grouped.set(entry.runId, current);
|
|
153
|
+
}
|
|
154
|
+
return grouped;
|
|
155
|
+
}
|
|
@@ -41,27 +41,27 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
41
41
|
thumbsUpRate: number;
|
|
42
42
|
avgEvalScore: number;
|
|
43
43
|
} | {
|
|
44
|
-
summary: import("./types.js").TraceSummary;
|
|
45
|
-
spans: import("./types.js").TraceSpan[];
|
|
46
44
|
id?: undefined;
|
|
47
45
|
error?: undefined;
|
|
48
46
|
ok?: undefined;
|
|
47
|
+
summary: import("./types.js").TraceSummary;
|
|
48
|
+
spans: import("./types.js").TraceSpan[];
|
|
49
49
|
} | {
|
|
50
|
-
summary?: undefined;
|
|
51
|
-
spans?: undefined;
|
|
52
|
-
id: string;
|
|
53
50
|
error?: undefined;
|
|
54
51
|
ok?: undefined;
|
|
55
|
-
} | {
|
|
56
52
|
summary?: undefined;
|
|
57
53
|
spans?: undefined;
|
|
54
|
+
id: string;
|
|
55
|
+
} | {
|
|
58
56
|
id?: undefined;
|
|
59
|
-
error: any;
|
|
60
57
|
ok?: undefined;
|
|
61
|
-
} | {
|
|
62
58
|
summary?: undefined;
|
|
63
59
|
spans?: undefined;
|
|
60
|
+
error: any;
|
|
61
|
+
} | {
|
|
64
62
|
id?: undefined;
|
|
65
63
|
error?: undefined;
|
|
64
|
+
summary?: undefined;
|
|
65
|
+
spans?: undefined;
|
|
66
66
|
ok: boolean;
|
|
67
67
|
}>>;
|