@agent-native/core 0.194.0 → 0.194.1-nightly-20260927113046
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/README.md +1 -1
- package/corpus/templates/brain/actions/check-builder-embeddings.ts +71 -0
- package/corpus/templates/brain/app/i18n-data.ts +90 -0
- package/corpus/templates/brain/app/routes/sources.tsx +95 -0
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +3 -1
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +6 -1
- package/corpus/templates/design/changelog/2026-09-27-drops-into-plain-frames-now-stack-above-existing-content-whi.md +6 -0
- package/dist/client/observability/ObservabilityDashboard.js +113 -12
- package/dist/client/observability/ObservabilityReviewSummaryButton.d.ts +1 -1
- package/dist/client/observability/ObservabilityReviewSummaryButton.js +13 -8
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/localization/core-messages/ar-SA.js +8 -0
- package/dist/localization/core-messages/de-DE.js +8 -0
- package/dist/localization/core-messages/en-US.d.ts +8 -0
- package/dist/localization/core-messages/en-US.js +8 -0
- package/dist/localization/core-messages/es-ES.js +8 -0
- package/dist/localization/core-messages/fr-FR.js +8 -0
- package/dist/localization/core-messages/hi-IN.js +8 -0
- package/dist/localization/core-messages/ja-JP.js +8 -0
- package/dist/localization/core-messages/ko-KR.js +8 -0
- package/dist/localization/core-messages/pt-BR.js +8 -0
- package/dist/localization/core-messages/zh-CN.js +8 -0
- package/dist/localization/core-messages/zh-TW.js +8 -0
- package/dist/localization/core-messages.d.ts +8 -0
- package/dist/localization/core-messages.js +14 -0
- package/dist/localization/default-messages.d.ts +4 -1
- package/dist/localization/default-messages.js +6 -3
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/reviews.js +26 -14
- package/dist/observability/routes.d.ts +8 -8
- package/dist/observability/store.d.ts +4 -1
- package/dist/observability/store.js +27 -6
- package/dist/observability/types.d.ts +2 -0
- package/dist/progress/routes.d.ts +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +2 -2
- package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
- package/dist/triggers/actions/manage-automation.d.ts +2 -2
- package/package.json +1 -1
package/corpus/README.md
CHANGED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { defineAction } from "@agent-native/core/action";
|
|
2
|
+
import { readEmbeddingFamilyAvailability } from "@agent-native/core/embeddings";
|
|
3
|
+
import { runWithRequestContext } from "@agent-native/core/server/request-context";
|
|
4
|
+
import { assertAccess } from "@agent-native/core/sharing";
|
|
5
|
+
import { eq } from "drizzle-orm";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
|
|
8
|
+
import { getDb, schema } from "../server/db/index.js";
|
|
9
|
+
|
|
10
|
+
export const checkBuilderEmbeddingsSchema = z.object({
|
|
11
|
+
sourceId: z.string().min(1),
|
|
12
|
+
confirmProviderCost: z.literal(true),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export default defineAction({
|
|
16
|
+
description:
|
|
17
|
+
"Check Builder embeddings for one Brain source with a single synthetic query; does not index or store data.",
|
|
18
|
+
schema: checkBuilderEmbeddingsSchema,
|
|
19
|
+
toolCallable: false,
|
|
20
|
+
needsApproval: true,
|
|
21
|
+
run: async ({ sourceId }) => {
|
|
22
|
+
await assertAccess("brain-source", sourceId, "admin");
|
|
23
|
+
const [source] = await getDb()
|
|
24
|
+
.select({
|
|
25
|
+
ownerEmail: schema.brainSources.ownerEmail,
|
|
26
|
+
orgId: schema.brainSources.orgId,
|
|
27
|
+
})
|
|
28
|
+
.from(schema.brainSources)
|
|
29
|
+
.where(eq(schema.brainSources.id, sourceId))
|
|
30
|
+
.limit(1);
|
|
31
|
+
if (!source) throw new Error("Brain source was not found.");
|
|
32
|
+
|
|
33
|
+
return runWithRequestContext(
|
|
34
|
+
{
|
|
35
|
+
userEmail: source.ownerEmail,
|
|
36
|
+
orgId: source.orgId ?? undefined,
|
|
37
|
+
},
|
|
38
|
+
async () => {
|
|
39
|
+
const availability = await readEmbeddingFamilyAvailability();
|
|
40
|
+
if (availability.unavailableProviders.includes("builder")) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
"Builder embedding credential lookup is unavailable.",
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
const family = availability.families.find(
|
|
46
|
+
(candidate) => candidate.provider === "builder",
|
|
47
|
+
);
|
|
48
|
+
if (!family) throw new Error("Builder embeddings are not configured.");
|
|
49
|
+
const vectors = await family.embed(
|
|
50
|
+
[{ text: "Builder embedding connectivity check." }],
|
|
51
|
+
"query",
|
|
52
|
+
);
|
|
53
|
+
const [vector] = vectors;
|
|
54
|
+
if (
|
|
55
|
+
vectors.length !== 1 ||
|
|
56
|
+
!vector ||
|
|
57
|
+
vector.length !== family.dimensions ||
|
|
58
|
+
!vector.every(Number.isFinite)
|
|
59
|
+
) {
|
|
60
|
+
throw new Error("Builder returned an invalid embedding.");
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
provider: family.provider,
|
|
64
|
+
model: family.model,
|
|
65
|
+
dimensions: family.dimensions,
|
|
66
|
+
success: true,
|
|
67
|
+
};
|
|
68
|
+
},
|
|
69
|
+
);
|
|
70
|
+
},
|
|
71
|
+
});
|
|
@@ -493,6 +493,15 @@ const enUS = {
|
|
|
493
493
|
reviewRequired: "Review required",
|
|
494
494
|
reviewRequiredDescription: "Queue extracted knowledge before approval",
|
|
495
495
|
cancel: "Cancel",
|
|
496
|
+
close: "Close",
|
|
497
|
+
checkBuilder: "Check Builder embeddings",
|
|
498
|
+
checkBuilderDescription:
|
|
499
|
+
"Verify Builder with one synthetic request. No source content is sent or indexed.",
|
|
500
|
+
checkBuilderConfirm:
|
|
501
|
+
"Run one synthetic Builder embedding request for {{source}}? This may incur provider usage. No source content is sent, and the vector is not stored.",
|
|
502
|
+
runBuilderCheck: "Run one check",
|
|
503
|
+
checkBuilderSuccess:
|
|
504
|
+
"Builder check passed: {{provider}} / {{model}}, {{dimensions}} dimensions. No vector was stored.",
|
|
496
505
|
saveSource: "Save source",
|
|
497
506
|
createSource: "Create source",
|
|
498
507
|
retryAfter: "Retry after {{date}}",
|
|
@@ -1006,6 +1015,15 @@ const baseMessagesByLocale = {
|
|
|
1006
1015
|
provider: "提供方",
|
|
1007
1016
|
notRequired: "不需要",
|
|
1008
1017
|
cancel: "取消",
|
|
1018
|
+
close: "关闭",
|
|
1019
|
+
checkBuilder: "检查 Builder 嵌入服务",
|
|
1020
|
+
checkBuilderDescription:
|
|
1021
|
+
"发送一次模拟请求以验证 Builder。不会发送或索引来源内容。",
|
|
1022
|
+
checkBuilderConfirm:
|
|
1023
|
+
"要为 {{source}} 发送一次模拟的 Builder 嵌入请求吗?这可能产生服务费用。不会发送来源内容,也不会保存向量。",
|
|
1024
|
+
runBuilderCheck: "运行一次检查",
|
|
1025
|
+
checkBuilderSuccess:
|
|
1026
|
+
"Builder 检查通过:{{provider}} / {{model}},{{dimensions}} 维。未保存向量。",
|
|
1009
1027
|
saveSource: "保存来源",
|
|
1010
1028
|
createSource: "创建来源",
|
|
1011
1029
|
retryAfter: "{{date}} 后重试",
|
|
@@ -1212,6 +1230,15 @@ const baseMessagesByLocale = {
|
|
|
1212
1230
|
provider: "Proveedor",
|
|
1213
1231
|
notRequired: "No requerido",
|
|
1214
1232
|
cancel: "Cancelar",
|
|
1233
|
+
close: "Cerrar",
|
|
1234
|
+
checkBuilder: "Comprobar embeddings de Builder",
|
|
1235
|
+
checkBuilderDescription:
|
|
1236
|
+
"Verifica Builder con una solicitud de prueba. No se envía ni indexa contenido de la fuente.",
|
|
1237
|
+
checkBuilderConfirm:
|
|
1238
|
+
"¿Enviar una solicitud de prueba de embeddings de Builder para {{source}}? Puede generar costes del proveedor. No se envía contenido de la fuente ni se guarda el vector.",
|
|
1239
|
+
runBuilderCheck: "Realizar una comprobación",
|
|
1240
|
+
checkBuilderSuccess:
|
|
1241
|
+
"Comprobación de Builder correcta: {{provider}} / {{model}}, {{dimensions}} dimensiones. No se guardó ningún vector.",
|
|
1215
1242
|
saveSource: "Guardar fuente",
|
|
1216
1243
|
createSource: "Crear fuente",
|
|
1217
1244
|
retryAfter: "Reintentar después de {{date}}",
|
|
@@ -1428,6 +1455,15 @@ const baseMessagesByLocale = {
|
|
|
1428
1455
|
provider: "Fournisseur",
|
|
1429
1456
|
notRequired: "Non requis",
|
|
1430
1457
|
cancel: "Annuler",
|
|
1458
|
+
close: "Fermer",
|
|
1459
|
+
checkBuilder: "Vérifier les embeddings Builder",
|
|
1460
|
+
checkBuilderDescription:
|
|
1461
|
+
"Vérifiez Builder avec une seule requête de test. Aucun contenu de la source n'est envoyé ni indexé.",
|
|
1462
|
+
checkBuilderConfirm:
|
|
1463
|
+
"Envoyer une requête de test d'embedding Builder pour {{source}} ? Cela peut entraîner des frais du fournisseur. Aucun contenu de la source n'est envoyé et le vecteur n'est pas stocké.",
|
|
1464
|
+
runBuilderCheck: "Lancer une vérification",
|
|
1465
|
+
checkBuilderSuccess:
|
|
1466
|
+
"Vérification Builder réussie : {{provider}} / {{model}}, {{dimensions}} dimensions. Aucun vecteur n'a été stocké.",
|
|
1431
1467
|
saveSource: "Enregistrer la source",
|
|
1432
1468
|
createSource: "Créer une source",
|
|
1433
1469
|
retryAfter: "Réessayer après {{date}}",
|
|
@@ -1643,6 +1679,15 @@ const baseMessagesByLocale = {
|
|
|
1643
1679
|
provider: "Anbieter",
|
|
1644
1680
|
notRequired: "Nicht erforderlich",
|
|
1645
1681
|
cancel: "Abbrechen",
|
|
1682
|
+
close: "Schließen",
|
|
1683
|
+
checkBuilder: "Builder-Embeddings prüfen",
|
|
1684
|
+
checkBuilderDescription:
|
|
1685
|
+
"Builder mit einer Testanfrage prüfen. Quellinhalte werden weder gesendet noch indexiert.",
|
|
1686
|
+
checkBuilderConfirm:
|
|
1687
|
+
"Eine Testanfrage für Builder-Embeddings zu {{source}} senden? Dabei können Anbietergebühren anfallen. Quellinhalte werden nicht gesendet und der Vektor wird nicht gespeichert.",
|
|
1688
|
+
runBuilderCheck: "Einmal prüfen",
|
|
1689
|
+
checkBuilderSuccess:
|
|
1690
|
+
"Builder-Prüfung erfolgreich: {{provider}} / {{model}}, {{dimensions}} Dimensionen. Kein Vektor wurde gespeichert.",
|
|
1646
1691
|
saveSource: "Quelle speichern",
|
|
1647
1692
|
createSource: "Quelle erstellen",
|
|
1648
1693
|
retryAfter: "Erneut versuchen nach {{date}}",
|
|
@@ -1853,6 +1898,15 @@ const baseMessagesByLocale = {
|
|
|
1853
1898
|
provider: "プロバイダー",
|
|
1854
1899
|
notRequired: "不要",
|
|
1855
1900
|
cancel: "キャンセル",
|
|
1901
|
+
close: "閉じる",
|
|
1902
|
+
checkBuilder: "Builder の埋め込みを確認",
|
|
1903
|
+
checkBuilderDescription:
|
|
1904
|
+
"テスト用のリクエストを 1 回送信して Builder を確認します。ソースの内容は送信もインデックス登録もされません。",
|
|
1905
|
+
checkBuilderConfirm:
|
|
1906
|
+
"{{source}} に対して Builder の埋め込みテストリクエストを 1 回送信しますか?プロバイダーの利用料金が発生する場合があります。ソースの内容は送信されず、ベクトルも保存されません。",
|
|
1907
|
+
runBuilderCheck: "1 回確認する",
|
|
1908
|
+
checkBuilderSuccess:
|
|
1909
|
+
"Builder の確認に成功しました: {{provider}} / {{model}}、{{dimensions}} 次元。ベクトルは保存されていません。",
|
|
1856
1910
|
saveSource: "ソースを保存",
|
|
1857
1911
|
createSource: "ソースを作成",
|
|
1858
1912
|
retryAfter: "{{date}} 後に再試行",
|
|
@@ -2063,6 +2117,15 @@ const baseMessagesByLocale = {
|
|
|
2063
2117
|
provider: "제공자",
|
|
2064
2118
|
notRequired: "필요 없음",
|
|
2065
2119
|
cancel: "취소",
|
|
2120
|
+
close: "닫기",
|
|
2121
|
+
checkBuilder: "Builder 임베딩 확인",
|
|
2122
|
+
checkBuilderDescription:
|
|
2123
|
+
"테스트 요청 한 번으로 Builder를 확인합니다. 소스 내용은 전송하거나 인덱싱하지 않습니다.",
|
|
2124
|
+
checkBuilderConfirm:
|
|
2125
|
+
"{{source}}에 대해 Builder 임베딩 테스트 요청을 한 번 보내시겠습니까? 제공업체 사용 요금이 발생할 수 있습니다. 소스 내용은 전송하지 않으며 벡터도 저장하지 않습니다.",
|
|
2126
|
+
runBuilderCheck: "한 번 확인하기",
|
|
2127
|
+
checkBuilderSuccess:
|
|
2128
|
+
"Builder 확인 성공: {{provider}} / {{model}}, {{dimensions}}차원. 벡터는 저장되지 않았습니다.",
|
|
2066
2129
|
saveSource: "소스 저장",
|
|
2067
2130
|
createSource: "소스 만들기",
|
|
2068
2131
|
retryAfter: "{{date}} 후 다시 시도",
|
|
@@ -2273,6 +2336,15 @@ const baseMessagesByLocale = {
|
|
|
2273
2336
|
provider: "Provedor",
|
|
2274
2337
|
notRequired: "Não obrigatório",
|
|
2275
2338
|
cancel: "Cancelar",
|
|
2339
|
+
close: "Fechar",
|
|
2340
|
+
checkBuilder: "Verificar embeddings do Builder",
|
|
2341
|
+
checkBuilderDescription:
|
|
2342
|
+
"Verifique o Builder com uma solicitação de teste. O conteúdo da fonte não é enviado nem indexado.",
|
|
2343
|
+
checkBuilderConfirm:
|
|
2344
|
+
"Enviar uma solicitação de teste de embeddings do Builder para {{source}}? Isso pode gerar custos do provedor. O conteúdo da fonte não é enviado e o vetor não é armazenado.",
|
|
2345
|
+
runBuilderCheck: "Executar uma verificação",
|
|
2346
|
+
checkBuilderSuccess:
|
|
2347
|
+
"Verificação do Builder concluída: {{provider}} / {{model}}, {{dimensions}} dimensões. Nenhum vetor foi armazenado.",
|
|
2276
2348
|
saveSource: "Salvar fonte",
|
|
2277
2349
|
createSource: "Criar fonte",
|
|
2278
2350
|
retryAfter: "Tentar novamente após {{date}}",
|
|
@@ -2487,6 +2559,15 @@ const baseMessagesByLocale = {
|
|
|
2487
2559
|
provider: "प्रदाता",
|
|
2488
2560
|
notRequired: "आवश्यक नहीं",
|
|
2489
2561
|
cancel: "रद्द करें",
|
|
2562
|
+
close: "बंद करें",
|
|
2563
|
+
checkBuilder: "Builder एम्बेडिंग जाँचें",
|
|
2564
|
+
checkBuilderDescription:
|
|
2565
|
+
"एक परीक्षण अनुरोध से Builder की जाँच करें। स्रोत की सामग्री भेजी या इंडेक्स नहीं की जाती।",
|
|
2566
|
+
checkBuilderConfirm:
|
|
2567
|
+
"{{source}} के लिए Builder एम्बेडिंग का एक परीक्षण अनुरोध भेजें? प्रदाता का शुल्क लग सकता है। स्रोत की सामग्री नहीं भेजी जाएगी और वेक्टर सहेजा नहीं जाएगा।",
|
|
2568
|
+
runBuilderCheck: "एक बार जाँचें",
|
|
2569
|
+
checkBuilderSuccess:
|
|
2570
|
+
"Builder जाँच सफल: {{provider}} / {{model}}, {{dimensions}} आयाम। कोई वेक्टर सहेजा नहीं गया।",
|
|
2490
2571
|
saveSource: "स्रोत सहेजें",
|
|
2491
2572
|
createSource: "स्रोत बनाएं",
|
|
2492
2573
|
retryAfter: "{{date}} के बाद फिर कोशिश करें",
|
|
@@ -2695,6 +2776,15 @@ const baseMessagesByLocale = {
|
|
|
2695
2776
|
provider: "المزوّد",
|
|
2696
2777
|
notRequired: "غير مطلوب",
|
|
2697
2778
|
cancel: "إلغاء",
|
|
2779
|
+
close: "إغلاق",
|
|
2780
|
+
checkBuilder: "التحقق من تضمينات Builder",
|
|
2781
|
+
checkBuilderDescription:
|
|
2782
|
+
"تحقّق من Builder بطلب اختباري واحد. لن يُرسل محتوى المصدر أو يُفهرس.",
|
|
2783
|
+
checkBuilderConfirm:
|
|
2784
|
+
"هل تريد إرسال طلب اختباري واحد لتضمينات Builder من أجل {{source}}؟ قد تترتب رسوم من المزوّد. لن يُرسل محتوى المصدر ولن يُحفظ المتجه.",
|
|
2785
|
+
runBuilderCheck: "إجراء تحقق واحد",
|
|
2786
|
+
checkBuilderSuccess:
|
|
2787
|
+
"نجح التحقق من Builder: {{provider}} / {{model}}، {{dimensions}} بُعدًا. لم يُحفظ أي متجه.",
|
|
2698
2788
|
saveSource: "حفظ المصدر",
|
|
2699
2789
|
createSource: "إنشاء مصدر",
|
|
2700
2790
|
retryAfter: "إعادة المحاولة بعد {{date}}",
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
IconArchive,
|
|
11
11
|
IconBrandGithub,
|
|
12
12
|
IconBrandSlack,
|
|
13
|
+
IconBolt,
|
|
13
14
|
IconChecks,
|
|
14
15
|
IconChevronDown,
|
|
15
16
|
IconCircleCheck,
|
|
@@ -1803,6 +1804,21 @@ function SourceListItem({
|
|
|
1803
1804
|
}) {
|
|
1804
1805
|
const t = useT();
|
|
1805
1806
|
const [expanded, setExpanded] = useState(false);
|
|
1807
|
+
const [builderCheckOpen, setBuilderCheckOpen] = useState(false);
|
|
1808
|
+
const sourceAccess = useActionQuery<{ accessRole?: string }>(
|
|
1809
|
+
"get-source" as any,
|
|
1810
|
+
{ id: source.id } as any,
|
|
1811
|
+
{ enabled: expanded, retry: false },
|
|
1812
|
+
);
|
|
1813
|
+
const checkBuilder = useActionMutation<
|
|
1814
|
+
{ provider: string; model: string; dimensions: number; success: boolean },
|
|
1815
|
+
{ sourceId: string; confirmProviderCost: true }
|
|
1816
|
+
>("check-builder-embeddings" as any, {
|
|
1817
|
+
skipActionQueryInvalidation: true,
|
|
1818
|
+
});
|
|
1819
|
+
const canCheckBuilder =
|
|
1820
|
+
sourceAccess.data?.accessRole === "admin" ||
|
|
1821
|
+
sourceAccess.data?.accessRole === "owner";
|
|
1806
1822
|
const Icon = sourceProviderIcon(source.provider);
|
|
1807
1823
|
const retry = sourceRetryAfter(source);
|
|
1808
1824
|
const hasSyncNotice = Boolean(
|
|
@@ -1979,6 +1995,25 @@ function SourceListItem({
|
|
|
1979
1995
|
</Button>
|
|
1980
1996
|
</div>
|
|
1981
1997
|
) : null}
|
|
1998
|
+
{canCheckBuilder ? (
|
|
1999
|
+
<div className="mt-3 flex flex-col gap-3 rounded-md border border-border bg-muted/25 p-3 sm:flex-row sm:items-center sm:justify-between">
|
|
2000
|
+
<p className="text-sm leading-6 text-muted-foreground">
|
|
2001
|
+
{t("sources.checkBuilderDescription")}
|
|
2002
|
+
</p>
|
|
2003
|
+
<Button
|
|
2004
|
+
size="sm"
|
|
2005
|
+
variant="outline"
|
|
2006
|
+
className="shrink-0"
|
|
2007
|
+
onClick={() => {
|
|
2008
|
+
checkBuilder.reset();
|
|
2009
|
+
setBuilderCheckOpen(true);
|
|
2010
|
+
}}
|
|
2011
|
+
>
|
|
2012
|
+
<IconBolt className="size-4" />
|
|
2013
|
+
{t("sources.checkBuilder")}
|
|
2014
|
+
</Button>
|
|
2015
|
+
</div>
|
|
2016
|
+
) : null}
|
|
1982
2017
|
{hasSyncNotice ? (
|
|
1983
2018
|
<div className="mt-3 flex gap-2 rounded-md border border-destructive/20 bg-destructive/5 px-3 py-2 text-sm">
|
|
1984
2019
|
<IconAlertTriangle className="mt-0.5 size-4 shrink-0 text-destructive" />
|
|
@@ -2017,6 +2052,66 @@ function SourceListItem({
|
|
|
2017
2052
|
) : null}
|
|
2018
2053
|
</div>
|
|
2019
2054
|
) : null}
|
|
2055
|
+
|
|
2056
|
+
<Dialog
|
|
2057
|
+
open={builderCheckOpen}
|
|
2058
|
+
onOpenChange={(open) => {
|
|
2059
|
+
if (!open && checkBuilder.isPending) return;
|
|
2060
|
+
setBuilderCheckOpen(open);
|
|
2061
|
+
}}
|
|
2062
|
+
>
|
|
2063
|
+
<DialogContent className="max-w-md gap-5">
|
|
2064
|
+
<DialogHeader>
|
|
2065
|
+
<DialogTitle>{t("sources.checkBuilder")}</DialogTitle>
|
|
2066
|
+
<DialogDescription>
|
|
2067
|
+
{t("sources.checkBuilderConfirm", { source: sourceName(source) })}
|
|
2068
|
+
</DialogDescription>
|
|
2069
|
+
</DialogHeader>
|
|
2070
|
+
{checkBuilder.data ? (
|
|
2071
|
+
<p role="status" className="text-sm text-foreground">
|
|
2072
|
+
{t("sources.checkBuilderSuccess", {
|
|
2073
|
+
provider: checkBuilder.data.provider,
|
|
2074
|
+
model: checkBuilder.data.model,
|
|
2075
|
+
dimensions: checkBuilder.data.dimensions.toLocaleString(),
|
|
2076
|
+
})}
|
|
2077
|
+
</p>
|
|
2078
|
+
) : null}
|
|
2079
|
+
{checkBuilder.isError ? (
|
|
2080
|
+
<p role="alert" className="text-sm text-destructive">
|
|
2081
|
+
{checkBuilder.error.message}
|
|
2082
|
+
</p>
|
|
2083
|
+
) : null}
|
|
2084
|
+
<DialogFooter>
|
|
2085
|
+
<Button
|
|
2086
|
+
type="button"
|
|
2087
|
+
variant="outline"
|
|
2088
|
+
disabled={checkBuilder.isPending}
|
|
2089
|
+
onClick={() => setBuilderCheckOpen(false)}
|
|
2090
|
+
>
|
|
2091
|
+
{checkBuilder.data ? t("sources.close") : t("sources.cancel")}
|
|
2092
|
+
</Button>
|
|
2093
|
+
{!checkBuilder.data ? (
|
|
2094
|
+
<Button
|
|
2095
|
+
type="button"
|
|
2096
|
+
disabled={checkBuilder.isPending}
|
|
2097
|
+
onClick={() =>
|
|
2098
|
+
checkBuilder.mutate({
|
|
2099
|
+
sourceId: source.id,
|
|
2100
|
+
confirmProviderCost: true,
|
|
2101
|
+
})
|
|
2102
|
+
}
|
|
2103
|
+
>
|
|
2104
|
+
{checkBuilder.isPending ? (
|
|
2105
|
+
<IconLoader2 className="size-4 animate-spin" />
|
|
2106
|
+
) : (
|
|
2107
|
+
<IconBolt className="size-4" />
|
|
2108
|
+
)}
|
|
2109
|
+
{t("sources.runBuilderCheck")}
|
|
2110
|
+
</Button>
|
|
2111
|
+
) : null}
|
|
2112
|
+
</DialogFooter>
|
|
2113
|
+
</DialogContent>
|
|
2114
|
+
</Dialog>
|
|
2020
2115
|
</div>
|
|
2021
2116
|
);
|
|
2022
2117
|
}
|
|
@@ -12451,7 +12451,9 @@ export const editorChromeBridgeScript: string = `"use strict";
|
|
|
12451
12451
|
clientY,
|
|
12452
12452
|
dragged
|
|
12453
12453
|
);
|
|
12454
|
-
if (betweenChildren)
|
|
12454
|
+
if (betweenChildren && (hit === el.parentElement || isAutoLayoutElement(hit))) {
|
|
12455
|
+
return betweenChildren;
|
|
12456
|
+
}
|
|
12455
12457
|
return {
|
|
12456
12458
|
anchor: hit,
|
|
12457
12459
|
placement: "inside",
|
|
@@ -15648,7 +15648,12 @@ declare var __INITIAL_SOURCE_HEAD__: string;
|
|
|
15648
15648
|
clientY,
|
|
15649
15649
|
dragged,
|
|
15650
15650
|
);
|
|
15651
|
-
if (
|
|
15651
|
+
if (
|
|
15652
|
+
betweenChildren &&
|
|
15653
|
+
(hit === el.parentElement || isAutoLayoutElement(hit))
|
|
15654
|
+
) {
|
|
15655
|
+
return betweenChildren;
|
|
15656
|
+
}
|
|
15652
15657
|
return {
|
|
15653
15658
|
anchor: hit,
|
|
15654
15659
|
placement: "inside",
|
|
@@ -333,6 +333,9 @@ function ReviewTab({ days, renderArtifactPreview, }) {
|
|
|
333
333
|
const [summaryStatus, setSummaryStatus] = useState(null);
|
|
334
334
|
const [summaryRequests, setSummaryRequests] = useState({});
|
|
335
335
|
const summaryRetryTimers = useRef(new Map());
|
|
336
|
+
const summaryBaselineRef = useRef(new Map());
|
|
337
|
+
const summaryBatchRunIds = useRef([]);
|
|
338
|
+
const summaryBatchRetryTimer = useRef(null);
|
|
336
339
|
const summaryRequestMounted = useRef(false);
|
|
337
340
|
const [openPopover, setOpenPopover] = useState(null);
|
|
338
341
|
const pendingInstructionRunId = useRef(null);
|
|
@@ -346,6 +349,9 @@ function ReviewTab({ days, renderArtifactPreview, }) {
|
|
|
346
349
|
window.clearTimeout(timer);
|
|
347
350
|
}
|
|
348
351
|
summaryRetryTimers.current.clear();
|
|
352
|
+
if (summaryBatchRetryTimer.current !== null) {
|
|
353
|
+
window.clearTimeout(summaryBatchRetryTimer.current);
|
|
354
|
+
}
|
|
349
355
|
};
|
|
350
356
|
}, []);
|
|
351
357
|
const updateSummaryRequests = (runIds, status) => {
|
|
@@ -353,20 +359,30 @@ function ReviewTab({ days, renderArtifactPreview, }) {
|
|
|
353
359
|
return;
|
|
354
360
|
const uniqueRunIds = [...new Set(runIds)];
|
|
355
361
|
for (const runId of uniqueRunIds) {
|
|
362
|
+
if (status === "sending") {
|
|
363
|
+
const review = reviews?.find((candidate) => candidate.runId === runId ||
|
|
364
|
+
candidate.runs?.some((run) => run.runId === runId));
|
|
365
|
+
const runSummaryUpdatedAt = review?.runs?.find((run) => run.runId === runId)?.summaryUpdatedAt;
|
|
366
|
+
summaryBaselineRef.current.set(runId, runSummaryUpdatedAt ??
|
|
367
|
+
(review?.runId === runId
|
|
368
|
+
? (review.summaryUpdatedAt ?? null)
|
|
369
|
+
: null));
|
|
370
|
+
}
|
|
371
|
+
else if (status === null || status === "failed") {
|
|
372
|
+
summaryBaselineRef.current.delete(runId);
|
|
373
|
+
}
|
|
356
374
|
const timer = summaryRetryTimers.current.get(runId);
|
|
357
375
|
if (timer !== undefined)
|
|
358
376
|
window.clearTimeout(timer);
|
|
359
377
|
summaryRetryTimers.current.delete(runId);
|
|
360
|
-
if (status === "
|
|
378
|
+
if (status === "queued") {
|
|
361
379
|
const retryTimer = window.setTimeout(() => {
|
|
362
380
|
if (!summaryRequestMounted.current)
|
|
363
381
|
return;
|
|
364
382
|
setSummaryRequests((current) => {
|
|
365
|
-
if (current[runId] !== "
|
|
383
|
+
if (current[runId] !== "queued")
|
|
366
384
|
return current;
|
|
367
|
-
|
|
368
|
-
delete next[runId];
|
|
369
|
-
return next;
|
|
385
|
+
return { ...current, [runId]: "expired" };
|
|
370
386
|
});
|
|
371
387
|
summaryRetryTimers.current.delete(runId);
|
|
372
388
|
}, SUMMARY_RETRY_AFTER_MS);
|
|
@@ -387,6 +403,68 @@ function ReviewTab({ days, renderArtifactPreview, }) {
|
|
|
387
403
|
const getSummaryStatus = (runId) => summaryRequests[runId] ?? null;
|
|
388
404
|
const reviewRows = reviews?.filter((review) => Boolean(review.threadId?.trim()) &&
|
|
389
405
|
Boolean(review.summary || review.threadTitle.trim())) ?? [];
|
|
406
|
+
useEffect(() => {
|
|
407
|
+
if (!reviews)
|
|
408
|
+
return;
|
|
409
|
+
const summarizedRunIds = new Map();
|
|
410
|
+
for (const review of reviews) {
|
|
411
|
+
if (typeof review.summaryUpdatedAt === "number")
|
|
412
|
+
summarizedRunIds.set(review.runId, review.summaryUpdatedAt);
|
|
413
|
+
for (const run of review.runs ?? []) {
|
|
414
|
+
if (typeof run.summaryUpdatedAt === "number") {
|
|
415
|
+
summarizedRunIds.set(run.runId, run.summaryUpdatedAt);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
const completedRunIds = Object.entries(summaryRequests)
|
|
420
|
+
.filter(([runId, status]) => {
|
|
421
|
+
const updatedAt = summarizedRunIds.get(runId);
|
|
422
|
+
if ((status !== "queued" && status !== "expired") ||
|
|
423
|
+
updatedAt === undefined) {
|
|
424
|
+
return false;
|
|
425
|
+
}
|
|
426
|
+
const baseline = summaryBaselineRef.current.get(runId);
|
|
427
|
+
return baseline == null || updatedAt > baseline;
|
|
428
|
+
})
|
|
429
|
+
.map(([runId]) => runId);
|
|
430
|
+
if (completedRunIds.length > 0) {
|
|
431
|
+
for (const runId of completedRunIds) {
|
|
432
|
+
const timer = summaryRetryTimers.current.get(runId);
|
|
433
|
+
if (timer !== undefined)
|
|
434
|
+
window.clearTimeout(timer);
|
|
435
|
+
summaryRetryTimers.current.delete(runId);
|
|
436
|
+
summaryBaselineRef.current.delete(runId);
|
|
437
|
+
}
|
|
438
|
+
setSummaryRequests((current) => {
|
|
439
|
+
let changed = false;
|
|
440
|
+
const next = { ...current };
|
|
441
|
+
for (const runId of completedRunIds) {
|
|
442
|
+
if (next[runId] !== "queued" && next[runId] !== "expired")
|
|
443
|
+
continue;
|
|
444
|
+
delete next[runId];
|
|
445
|
+
changed = true;
|
|
446
|
+
}
|
|
447
|
+
return changed ? next : current;
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
const batchRunIds = summaryBatchRunIds.current;
|
|
451
|
+
if ((summaryStatus === "queued" || summaryStatus === "expired") &&
|
|
452
|
+
batchRunIds.length > 0 &&
|
|
453
|
+
batchRunIds.every((runId) => {
|
|
454
|
+
const updatedAt = summarizedRunIds.get(runId);
|
|
455
|
+
if (updatedAt === undefined)
|
|
456
|
+
return false;
|
|
457
|
+
const baseline = summaryBaselineRef.current.get(runId);
|
|
458
|
+
return baseline == null || updatedAt > baseline;
|
|
459
|
+
})) {
|
|
460
|
+
if (summaryBatchRetryTimer.current !== null) {
|
|
461
|
+
window.clearTimeout(summaryBatchRetryTimer.current);
|
|
462
|
+
summaryBatchRetryTimer.current = null;
|
|
463
|
+
}
|
|
464
|
+
summaryBatchRunIds.current = [];
|
|
465
|
+
setSummaryStatus(null);
|
|
466
|
+
}
|
|
467
|
+
}, [reviews, summaryRequests, summaryStatus]);
|
|
390
468
|
useEffect(() => {
|
|
391
469
|
if (!reviews)
|
|
392
470
|
return;
|
|
@@ -421,8 +499,12 @@ function ReviewTab({ days, renderArtifactPreview, }) {
|
|
|
421
499
|
review.summary?.outcome,
|
|
422
500
|
review.threadTitle,
|
|
423
501
|
review.authorName,
|
|
502
|
+
review.authorEmail,
|
|
424
503
|
review.model,
|
|
425
504
|
...review.artifacts.map((artifact) => artifact.title),
|
|
505
|
+
...review.feedback
|
|
506
|
+
.filter((entry) => entry.feedbackType === "text")
|
|
507
|
+
.map((entry) => entry.value),
|
|
426
508
|
]
|
|
427
509
|
.filter(Boolean)
|
|
428
510
|
.join(" ")
|
|
@@ -615,7 +697,7 @@ function ReviewTab({ days, renderArtifactPreview, }) {
|
|
|
615
697
|
return (!review.summary &&
|
|
616
698
|
!review.readOnly &&
|
|
617
699
|
summaryRequests[review.runId] !== "sending" &&
|
|
618
|
-
summaryRequests[review.runId] !== "
|
|
700
|
+
summaryRequests[review.runId] !== "queued");
|
|
619
701
|
}) ?? [];
|
|
620
702
|
const feedbackToImprove = (visibleReviews ?? []).flatMap((review) => {
|
|
621
703
|
if (review.readOnly)
|
|
@@ -648,11 +730,16 @@ function ReviewTab({ days, renderArtifactPreview, }) {
|
|
|
648
730
|
const summarizeVisible = () => {
|
|
649
731
|
if (summaryStatus === "sending" || unsummarizedReviews.length === 0)
|
|
650
732
|
return;
|
|
733
|
+
if (summaryBatchRetryTimer.current !== null) {
|
|
734
|
+
window.clearTimeout(summaryBatchRetryTimer.current);
|
|
735
|
+
summaryBatchRetryTimer.current = null;
|
|
736
|
+
}
|
|
651
737
|
const batches = [];
|
|
652
738
|
for (let offset = 0; offset < unsummarizedReviews.length; offset += 25) {
|
|
653
739
|
batches.push(unsummarizedReviews.slice(offset, offset + 25));
|
|
654
740
|
}
|
|
655
741
|
const batchRunIds = batches.map((batch) => batch.map((review) => review.runId));
|
|
742
|
+
summaryBatchRunIds.current = batchRunIds.flat();
|
|
656
743
|
setSummaryStatus("sending");
|
|
657
744
|
updateSummaryRequests(batchRunIds.flat(), "sending");
|
|
658
745
|
const requests = batches.map(async (batch, index) => {
|
|
@@ -677,7 +764,7 @@ function ReviewTab({ days, renderArtifactPreview, }) {
|
|
|
677
764
|
chatTarget: "local",
|
|
678
765
|
usageLabel: "observability:human-review-summary",
|
|
679
766
|
});
|
|
680
|
-
status = result.delivered ? "
|
|
767
|
+
status = result.delivered ? "queued" : "failed";
|
|
681
768
|
}
|
|
682
769
|
catch {
|
|
683
770
|
status = "failed";
|
|
@@ -688,7 +775,19 @@ function ReviewTab({ days, renderArtifactPreview, }) {
|
|
|
688
775
|
void Promise.all(requests).then((results) => {
|
|
689
776
|
if (!summaryRequestMounted.current)
|
|
690
777
|
return;
|
|
691
|
-
|
|
778
|
+
if (results.every((result) => result.status === "queued")) {
|
|
779
|
+
setSummaryStatus("queued");
|
|
780
|
+
summaryBatchRetryTimer.current = window.setTimeout(() => {
|
|
781
|
+
summaryBatchRetryTimer.current = null;
|
|
782
|
+
if (!summaryRequestMounted.current)
|
|
783
|
+
return;
|
|
784
|
+
setSummaryStatus((current) => current === "queued" ? "expired" : current);
|
|
785
|
+
}, SUMMARY_RETRY_AFTER_MS);
|
|
786
|
+
}
|
|
787
|
+
else {
|
|
788
|
+
summaryBatchRunIds.current = [];
|
|
789
|
+
setSummaryStatus("failed");
|
|
790
|
+
}
|
|
692
791
|
});
|
|
693
792
|
};
|
|
694
793
|
const toggleReview = (runId) => {
|
|
@@ -770,9 +869,11 @@ function ReviewTab({ days, renderArtifactPreview, }) {
|
|
|
770
869
|
? "bg-background text-foreground shadow-sm"
|
|
771
870
|
: "text-muted-foreground hover:text-foreground"), children: label }, value))) }), unsummarizedReviews.length > 0 && (_jsxs("button", { type: "button", "data-review-bulk-summary": true, onClick: summarizeVisible, title: t("observability.summarizeWithAgent"), disabled: summaryStatus === "sending", className: "rounded-md px-2.5 py-1.5 text-xs font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: [t("observability.summarizeWithAgent"), " \u00B7", " ", unsummarizedReviews.length] })), feedbackToImprove.length > 0 && (_jsx("button", { type: "button", onClick: improveFromFeedback, title: t("observability.updateInstructions"), className: "rounded-md px-2.5 py-1.5 text-xs font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: t("observability.updateInstructions") })), summaryStatus && (_jsx("span", { role: "status", "aria-live": "polite", className: "w-full text-xs text-muted-foreground", children: t(summaryStatus === "sending"
|
|
772
871
|
? "observability.summarySending"
|
|
773
|
-
: summaryStatus === "
|
|
774
|
-
? "observability.
|
|
775
|
-
:
|
|
872
|
+
: summaryStatus === "queued"
|
|
873
|
+
? "observability.summaryQueued"
|
|
874
|
+
: summaryStatus === "expired"
|
|
875
|
+
? "observability.summaryExpired"
|
|
876
|
+
: "observability.summaryFailed") }))] }), _jsx("div", { className: "space-y-2", "data-review-list": true, children: visibleReviews.length === 0 ? (_jsx(EmptyState, { message: t("observability.noData") })) : (visibleReviews.map((review) => {
|
|
776
877
|
const expanded = selectedRunId === review.runId;
|
|
777
878
|
const artifact = latestRenderableReviewArtifact(review.artifacts, Boolean(renderArtifactPreview));
|
|
778
879
|
const artifactHref = artifact
|
|
@@ -864,7 +965,7 @@ function ReviewTab({ days, renderArtifactPreview, }) {
|
|
|
864
965
|
return (_jsxs("div", { className: cn("max-w-[92%] break-words rounded-xl px-3 py-2 text-sm", message.role === "user"
|
|
865
966
|
? "ml-auto whitespace-pre-wrap bg-primary/10 text-foreground"
|
|
866
967
|
: "mr-auto bg-muted text-foreground"), children: [message.role === "assistant" && (_jsx("span", { className: "mb-1 block text-[10px] font-medium text-muted-foreground", children: t("agentChat.common.agent") })), isLongAssistant ? (_jsxs("details", { children: [_jsxs("summary", { className: "cursor-pointer list-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: [_jsx("span", { className: "line-clamp-3 whitespace-pre-wrap", children: message.text }), _jsx("span", { className: "mt-1 block text-xs text-muted-foreground", children: t("agentChat.common.expand") })] }), _jsx("p", { className: "mt-2 whitespace-pre-wrap", children: message.text })] })) : (_jsx("p", { className: "whitespace-pre-wrap", children: message.text })), message.toolCalls?.map((toolCall, toolIndex) => (_jsxs("span", { className: "mt-2 inline-flex max-w-full items-center gap-1 rounded-full bg-background/70 px-2 py-1 text-[10px] text-muted-foreground", title: toolCall, children: [_jsx(IconTool, { size: 11 }), _jsx("span", { className: "truncate", children: toolCall })] }, `${toolCall}-${toolIndex}`)))] }, `${message.role}-${index}`));
|
|
867
|
-
})) })] })] }), _jsxs("div", { className: "col-span-full flex shrink-0 items-center gap-1 border-t border-border px-3 py-2 sm:px-4", children: [selectedReview.readOnly ? (_jsx("span", { role: "note", title: t("observability.readOnlyTenant"), className: "text-xs text-muted-foreground", children: t("observability.readOnlyTenant") })) : (_jsxs(_Fragment, { children: [_jsx(ObservabilityReviewSummaryButton, { runId: activeRunId ?? selectedReview.runId, orgId: selectedReview.orgId, status: getSummaryStatus(activeRunId ?? selectedReview.runId), onStatusChange: (status) => updateSummaryRequests([activeRunId ?? selectedReview.runId], status),
|
|
968
|
+
})) })] })] }), _jsxs("div", { className: "col-span-full flex shrink-0 items-center gap-1 border-t border-border px-3 py-2 sm:px-4", children: [selectedReview.readOnly ? (_jsx("span", { role: "note", title: t("observability.readOnlyTenant"), className: "text-xs text-muted-foreground", children: t("observability.readOnlyTenant") })) : (_jsxs(_Fragment, { children: [_jsx(ObservabilityReviewSummaryButton, { runId: activeRunId ?? selectedReview.runId, orgId: selectedReview.orgId, status: getSummaryStatus(activeRunId ?? selectedReview.runId), onStatusChange: (status) => updateSummaryRequests([activeRunId ?? selectedReview.runId], status), refresh: Boolean(selectedSummary) }), _jsxs("div", { role: "group", "aria-label": t("observability.reviewFeedback"), className: "flex items-center gap-1", children: [activeRunId && pendingVotes[activeRunId] && (_jsxs("span", { role: "status", "aria-live": "polite", className: "inline-flex items-center gap-1 text-xs text-muted-foreground", children: [_jsx(IconLoader2, { size: 13, className: "animate-spin" }), t("agentChat.common.saving")] })), activeRunId && voteErrors[activeRunId] && (_jsx("span", { role: "status", "aria-live": "polite", className: "text-xs text-destructive", children: t("agentChat.common.saveFailed") })), _jsx("button", { type: "button", "aria-label": t("observability.thumbsUp"), "aria-pressed": selectedVoteType === "thumbs_up", title: t("observability.thumbsUp"), disabled: Boolean(activeRunId && pendingVotes[activeRunId]), onClick: () => saveFeedback(activeRunId ?? selectedReview.runId, "thumbs_up"), className: cn("rounded-md p-2 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-50", selectedVoteType === "thumbs_up" &&
|
|
868
969
|
"bg-emerald-500/10 text-emerald-600 dark:text-emerald-400"), children: _jsx(IconThumbUp, { size: 16 }) }), _jsx("button", { type: "button", "aria-label": t("observability.thumbsDown"), "aria-pressed": selectedVoteType === "thumbs_down", title: t("observability.thumbsDown"), disabled: Boolean(activeRunId && pendingVotes[activeRunId]), onClick: () => {
|
|
869
970
|
saveFeedback(activeRunId ?? selectedReview.runId, "thumbs_down");
|
|
870
971
|
setFeedbackNote((current) => current?.runId ===
|
|
@@ -7,5 +7,5 @@ export interface ObservabilityReviewSummaryButtonProps {
|
|
|
7
7
|
background?: boolean;
|
|
8
8
|
refresh?: boolean;
|
|
9
9
|
}
|
|
10
|
-
export type ObservabilityReviewSummaryStatus = "sending" | "
|
|
10
|
+
export type ObservabilityReviewSummaryStatus = "sending" | "queued" | "failed" | "expired";
|
|
11
11
|
export declare function ObservabilityReviewSummaryButton({ runId, orgId, status, onStatusChange, compact, background, refresh, }: ObservabilityReviewSummaryButtonProps): import("react").JSX.Element;
|