@agent-native/core 0.187.0-nightly-20260924172231 → 0.187.0
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/analytics/CHANGELOG.md +11 -0
- package/corpus/templates/analytics/app/i18n/en-US.ts +1 -0
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +101 -11
- package/corpus/templates/analytics/changelog/2026-09-24-session-list-hides-0m-recordings-by-default.md +6 -0
- package/corpus/templates/assets/CHANGELOG.md +6 -0
- package/corpus/templates/brain/actions/backfill-search-embeddings.ts +337 -0
- package/corpus/templates/brain/actions/get-brain-health.ts +1 -1
- package/corpus/templates/brain/app/lib/brain.ts +18 -0
- package/corpus/templates/brain/jobs/process-ingest-queue.ts +25 -3
- package/corpus/templates/brain/server/lib/brain-health.ts +197 -57
- package/corpus/templates/brain/server/lib/demo.ts +25 -4
- package/corpus/templates/brain/server/lib/hybrid-search.ts +4 -1
- package/corpus/templates/brain/server/lib/ingest-queue.ts +1 -0
- package/corpus/templates/brain/server/lib/search-index.ts +254 -17
- package/corpus/templates/brain/server/lib/search.ts +27 -0
- package/corpus/templates/calendar/CHANGELOG.md +6 -0
- package/corpus/templates/clips/CHANGELOG.md +10 -0
- package/corpus/templates/content/CHANGELOG.md +22 -0
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +559 -227
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +25 -1
- package/corpus/templates/design/CHANGELOG.md +36 -0
- package/corpus/templates/dispatch/CHANGELOG.md +7 -0
- package/corpus/templates/mail/CHANGELOG.md +17 -0
- package/corpus/templates/slides/CHANGELOG.md +7 -0
- package/dist/automation/index.d.ts +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/embeddings/index.d.ts +5 -0
- package/dist/embeddings/index.js +44 -11
- package/dist/observability/routes.d.ts +5 -5
- package/dist/progress/routes.d.ts +1 -1
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
- package/package.json +4 -4
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
BRAIN_SEARCH_INDEX_VERSION,
|
|
18
18
|
BRAIN_SENSITIVITY_POLICY_VERSION,
|
|
19
19
|
} from "./search-index-contracts.js";
|
|
20
|
+
import { readEmbeddingReadiness } from "./search-index.js";
|
|
20
21
|
import { redactSensitiveText } from "./search.js";
|
|
21
22
|
|
|
22
23
|
const APP_ID = "brain";
|
|
@@ -441,59 +442,114 @@ export async function readBrainHealth() {
|
|
|
441
442
|
),
|
|
442
443
|
)
|
|
443
444
|
: [];
|
|
444
|
-
const [sensitivityRows, artifactRows, embeddingRows] =
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
445
|
+
const [sensitivityRows, artifactRows, embeddingRows, burstRows] =
|
|
446
|
+
await Promise.all([
|
|
447
|
+
adminSourceIds.length
|
|
448
|
+
? db
|
|
449
|
+
.select({
|
|
450
|
+
disposition: schema.brainSensitivityEvents.disposition,
|
|
451
|
+
confidenceBand: schema.brainSensitivityEvents.confidenceBand,
|
|
452
|
+
})
|
|
453
|
+
.from(schema.brainSensitivityEvents)
|
|
454
|
+
.innerJoin(
|
|
455
|
+
schema.brainSources,
|
|
456
|
+
eq(
|
|
457
|
+
schema.brainSensitivityEvents.sourceId,
|
|
458
|
+
schema.brainSources.id,
|
|
459
|
+
),
|
|
460
|
+
)
|
|
461
|
+
.where(
|
|
462
|
+
and(
|
|
463
|
+
accessFilter(schema.brainSources, schema.brainSourceShares),
|
|
464
|
+
inArray(schema.brainSensitivityEvents.sourceId, adminSourceIds),
|
|
465
|
+
),
|
|
466
|
+
)
|
|
467
|
+
: Promise.resolve([]),
|
|
468
|
+
audienceIds.length
|
|
469
|
+
? db
|
|
470
|
+
.select({
|
|
471
|
+
id: schema.brainSearchArtifacts.id,
|
|
472
|
+
captureId: schema.brainSearchArtifacts.captureId,
|
|
473
|
+
contentHash: schema.brainSearchArtifacts.contentHash,
|
|
474
|
+
sensitivityPolicyVersion:
|
|
475
|
+
schema.brainSearchArtifacts.sensitivityPolicyVersion,
|
|
476
|
+
aclHash: schema.brainSearchArtifacts.aclHash,
|
|
477
|
+
indexVersion: schema.brainSearchArtifacts.indexVersion,
|
|
478
|
+
status: schema.brainSearchArtifacts.status,
|
|
479
|
+
captureContentHash: schema.brainRawCaptures.contentHash,
|
|
480
|
+
captureSensitivityDisposition:
|
|
481
|
+
schema.brainRawCaptures.sensitivityDisposition,
|
|
482
|
+
captureSensitivityPolicyVersion:
|
|
483
|
+
schema.brainRawCaptures.sensitivityPolicyVersion,
|
|
484
|
+
captureAclHash: schema.brainRawCaptures.audienceAclHash,
|
|
485
|
+
})
|
|
486
|
+
.from(schema.brainSearchArtifacts)
|
|
487
|
+
.innerJoin(
|
|
488
|
+
schema.brainSources,
|
|
489
|
+
eq(schema.brainSearchArtifacts.sourceId, schema.brainSources.id),
|
|
490
|
+
)
|
|
491
|
+
.innerJoin(
|
|
492
|
+
schema.brainRawCaptures,
|
|
493
|
+
eq(
|
|
494
|
+
schema.brainSearchArtifacts.captureId,
|
|
495
|
+
schema.brainRawCaptures.id,
|
|
496
|
+
),
|
|
497
|
+
)
|
|
498
|
+
.where(
|
|
499
|
+
and(
|
|
500
|
+
accessFilter(schema.brainSources, schema.brainSourceShares),
|
|
501
|
+
inArray(schema.brainSearchArtifacts.audienceId, audienceIds),
|
|
502
|
+
),
|
|
503
|
+
)
|
|
504
|
+
: Promise.resolve([]),
|
|
505
|
+
audienceIds.length
|
|
506
|
+
? db
|
|
507
|
+
.select({
|
|
508
|
+
targetType: schema.brainSearchEmbeddings.targetType,
|
|
509
|
+
targetId: schema.brainSearchEmbeddings.targetId,
|
|
510
|
+
embeddingSetId: schema.brainSearchEmbeddings.embeddingSetId,
|
|
511
|
+
contentHash: schema.brainSearchEmbeddings.contentHash,
|
|
512
|
+
sensitivityPolicyVersion:
|
|
513
|
+
schema.brainSearchEmbeddings.sensitivityPolicyVersion,
|
|
514
|
+
aclHash: schema.brainSearchEmbeddings.aclHash,
|
|
515
|
+
indexVersion: schema.brainSearchEmbeddings.indexVersion,
|
|
516
|
+
status: schema.brainSearchEmbeddings.status,
|
|
517
|
+
})
|
|
518
|
+
.from(schema.brainSearchEmbeddings)
|
|
519
|
+
.innerJoin(
|
|
520
|
+
schema.brainSources,
|
|
521
|
+
eq(schema.brainSearchEmbeddings.sourceId, schema.brainSources.id),
|
|
522
|
+
)
|
|
523
|
+
.where(
|
|
524
|
+
and(
|
|
525
|
+
accessFilter(schema.brainSources, schema.brainSourceShares),
|
|
526
|
+
inArray(schema.brainSearchEmbeddings.audienceId, audienceIds),
|
|
527
|
+
),
|
|
528
|
+
)
|
|
529
|
+
: Promise.resolve([]),
|
|
530
|
+
audienceIds.length
|
|
531
|
+
? db
|
|
532
|
+
.select({
|
|
533
|
+
id: schema.brainSearchBursts.id,
|
|
534
|
+
artifactId: schema.brainSearchBursts.artifactId,
|
|
535
|
+
aclHash: schema.brainSearchBursts.aclHash,
|
|
536
|
+
indexed: schema.brainSearchBursts.indexed,
|
|
537
|
+
contentHash: schema.brainSearchBursts.contentHash,
|
|
538
|
+
indexVersion: schema.brainSearchBursts.indexVersion,
|
|
539
|
+
})
|
|
540
|
+
.from(schema.brainSearchBursts)
|
|
541
|
+
.innerJoin(
|
|
542
|
+
schema.brainSources,
|
|
543
|
+
eq(schema.brainSearchBursts.sourceId, schema.brainSources.id),
|
|
544
|
+
)
|
|
545
|
+
.where(
|
|
546
|
+
and(
|
|
547
|
+
accessFilter(schema.brainSources, schema.brainSourceShares),
|
|
548
|
+
inArray(schema.brainSearchBursts.audienceId, audienceIds),
|
|
549
|
+
),
|
|
550
|
+
)
|
|
551
|
+
: Promise.resolve([]),
|
|
552
|
+
]);
|
|
497
553
|
|
|
498
554
|
const configuredCounts = new Map<string, number>();
|
|
499
555
|
for (const source of sourceRows) {
|
|
@@ -576,12 +632,77 @@ export async function readBrainHealth() {
|
|
|
576
632
|
const artifactCounts = countStatuses(artifactRows);
|
|
577
633
|
const embeddingCounts = countStatuses(embeddingRows);
|
|
578
634
|
const allowedCaptureCount = captureDispositionCounts.allowed ?? 0;
|
|
579
|
-
const
|
|
635
|
+
const currentArtifacts = artifactRows.filter(
|
|
636
|
+
(artifact) =>
|
|
637
|
+
artifact.status === "active" &&
|
|
638
|
+
artifact.captureSensitivityDisposition === "allowed" &&
|
|
639
|
+
artifact.contentHash === artifact.captureContentHash &&
|
|
640
|
+
artifact.sensitivityPolicyVersion ===
|
|
641
|
+
artifact.captureSensitivityPolicyVersion &&
|
|
642
|
+
artifact.aclHash === artifact.captureAclHash &&
|
|
643
|
+
artifact.indexVersion === BRAIN_SEARCH_INDEX_VERSION,
|
|
644
|
+
);
|
|
645
|
+
const activeArtifactCount = currentArtifacts.length;
|
|
646
|
+
const currentArtifactById = new Map(
|
|
647
|
+
currentArtifacts.map((artifact) => [artifact.id, artifact]),
|
|
648
|
+
);
|
|
580
649
|
const indexedCaptureCount = new Set(
|
|
581
|
-
|
|
582
|
-
.filter((artifact) => artifact.status === "active")
|
|
583
|
-
.map((artifact) => artifact.captureId),
|
|
650
|
+
currentArtifacts.map((artifact) => artifact.captureId),
|
|
584
651
|
).size;
|
|
652
|
+
const embeddingReadiness = await readEmbeddingReadiness();
|
|
653
|
+
const currentBursts = burstRows.filter((burst) => {
|
|
654
|
+
const artifact = currentArtifactById.get(burst.artifactId);
|
|
655
|
+
return Boolean(
|
|
656
|
+
artifact &&
|
|
657
|
+
burst.indexed === 1 &&
|
|
658
|
+
burst.contentHash === artifact.contentHash &&
|
|
659
|
+
burst.aclHash === artifact.aclHash &&
|
|
660
|
+
burst.indexVersion === BRAIN_SEARCH_INDEX_VERSION,
|
|
661
|
+
);
|
|
662
|
+
});
|
|
663
|
+
const artifactIdByBurstId = new Map(
|
|
664
|
+
currentBursts.map((burst) => [burst.id, burst.artifactId]),
|
|
665
|
+
);
|
|
666
|
+
const expectedBurstIdsByArtifactId = new Map<string, string[]>();
|
|
667
|
+
for (const burst of currentBursts) {
|
|
668
|
+
const ids = expectedBurstIdsByArtifactId.get(burst.artifactId) ?? [];
|
|
669
|
+
ids.push(burst.id);
|
|
670
|
+
expectedBurstIdsByArtifactId.set(burst.artifactId, ids);
|
|
671
|
+
}
|
|
672
|
+
const embeddedTargetKeys = new Set(
|
|
673
|
+
embeddingRows.flatMap((embedding) => {
|
|
674
|
+
const artifactId =
|
|
675
|
+
embedding.targetType === "artifact"
|
|
676
|
+
? embedding.targetId
|
|
677
|
+
: embedding.targetType === "burst"
|
|
678
|
+
? artifactIdByBurstId.get(embedding.targetId)
|
|
679
|
+
: undefined;
|
|
680
|
+
const artifact = artifactId
|
|
681
|
+
? currentArtifactById.get(artifactId)
|
|
682
|
+
: undefined;
|
|
683
|
+
return artifact &&
|
|
684
|
+
embedding.status === "active" &&
|
|
685
|
+
embedding.embeddingSetId === embeddingReadiness.embeddingSetId &&
|
|
686
|
+
embedding.contentHash === artifact.contentHash &&
|
|
687
|
+
embedding.sensitivityPolicyVersion ===
|
|
688
|
+
artifact.sensitivityPolicyVersion &&
|
|
689
|
+
embedding.aclHash === artifact.aclHash &&
|
|
690
|
+
embedding.indexVersion === BRAIN_SEARCH_INDEX_VERSION
|
|
691
|
+
? [`${embedding.targetType}:${embedding.targetId}`]
|
|
692
|
+
: [];
|
|
693
|
+
}),
|
|
694
|
+
);
|
|
695
|
+
const embeddedArtifactCount = currentArtifacts.filter((artifact) => {
|
|
696
|
+
const burstIds = expectedBurstIdsByArtifactId.get(artifact.id) ?? [];
|
|
697
|
+
return (
|
|
698
|
+
embeddedTargetKeys.has(`artifact:${artifact.id}`) &&
|
|
699
|
+
burstIds.every((id) => embeddedTargetKeys.has(`burst:${id}`))
|
|
700
|
+
);
|
|
701
|
+
}).length;
|
|
702
|
+
const missingArtifactEmbeddings = Math.max(
|
|
703
|
+
0,
|
|
704
|
+
activeArtifactCount - embeddedArtifactCount,
|
|
705
|
+
);
|
|
585
706
|
const privacySettings = await readBrainSettings();
|
|
586
707
|
const privacyClassifier = brainPrivacyReadiness(
|
|
587
708
|
privacySettings,
|
|
@@ -673,6 +794,13 @@ export async function readBrainHealth() {
|
|
|
673
794
|
(proposalCounts.pending ?? 0) > 0
|
|
674
795
|
? "Review pending proposals before expanding source scope."
|
|
675
796
|
: null,
|
|
797
|
+
!embeddingReadiness.ready
|
|
798
|
+
? (embeddingReadiness.warning ??
|
|
799
|
+
"Configure one embedding provider to enable semantic retrieval.")
|
|
800
|
+
: null,
|
|
801
|
+
embeddingReadiness.ready && missingArtifactEmbeddings > 0
|
|
802
|
+
? `Backfill embeddings for ${missingArtifactEmbeddings} active search artifact${missingArtifactEmbeddings === 1 ? "" : "s"}.`
|
|
803
|
+
: null,
|
|
676
804
|
]
|
|
677
805
|
.filter((step): step is string => Boolean(step))
|
|
678
806
|
.slice(0, 4);
|
|
@@ -793,6 +921,18 @@ export async function readBrainHealth() {
|
|
|
793
921
|
counts: artifactCounts,
|
|
794
922
|
},
|
|
795
923
|
embeddings: {
|
|
924
|
+
readiness: embeddingReadiness,
|
|
925
|
+
coverage: {
|
|
926
|
+
eligibleArtifacts: activeArtifactCount,
|
|
927
|
+
embeddedArtifacts: embeddedArtifactCount,
|
|
928
|
+
missingArtifacts: missingArtifactEmbeddings,
|
|
929
|
+
percent:
|
|
930
|
+
activeArtifactCount === 0
|
|
931
|
+
? 100
|
|
932
|
+
: Math.round(
|
|
933
|
+
(embeddedArtifactCount / activeArtifactCount) * 10_000,
|
|
934
|
+
) / 100,
|
|
935
|
+
},
|
|
796
936
|
total: embeddingRows.length,
|
|
797
937
|
active: embeddingCounts.active ?? 0,
|
|
798
938
|
stale: embeddingCounts.stale ?? 0,
|
|
@@ -6,6 +6,7 @@ import { getDb, schema } from "../db/index.js";
|
|
|
6
6
|
import {
|
|
7
7
|
createCapture,
|
|
8
8
|
createSource,
|
|
9
|
+
getAccessibleCapture,
|
|
9
10
|
nowIso,
|
|
10
11
|
parseJson,
|
|
11
12
|
sanitizeEvidenceCitationUrls,
|
|
@@ -17,9 +18,11 @@ import {
|
|
|
17
18
|
type WriteKnowledgeInput,
|
|
18
19
|
} from "./brain.js";
|
|
19
20
|
import {
|
|
21
|
+
citationEvidenceMatchesCapture,
|
|
20
22
|
redactSensitiveText,
|
|
21
23
|
redactSensitiveValue,
|
|
22
24
|
searchEverythingRows,
|
|
25
|
+
sourceUrlFromMetadata,
|
|
23
26
|
} from "./search.js";
|
|
24
27
|
|
|
25
28
|
const DEMO_SEED_ID = "brain-product-decisions-demo-v1";
|
|
@@ -1283,15 +1286,31 @@ function searchResultCitationUrl(
|
|
|
1283
1286
|
return result.citation?.sourceUrl ?? result.sourceUrl ?? null;
|
|
1284
1287
|
}
|
|
1285
1288
|
|
|
1286
|
-
function hasExpectedCitation(
|
|
1289
|
+
async function hasExpectedCitation(
|
|
1287
1290
|
result: Awaited<ReturnType<typeof searchEverythingRows>>[number],
|
|
1288
1291
|
evalCase: RetrievalEvalCase,
|
|
1289
1292
|
) {
|
|
1290
1293
|
if (!evalCase.requireCitation) return true;
|
|
1291
1294
|
const url = searchResultCitationUrl(result);
|
|
1292
1295
|
if (!url?.startsWith("https://")) return false;
|
|
1293
|
-
|
|
1294
|
-
|
|
1296
|
+
const captureId = result.citation?.captureId;
|
|
1297
|
+
if (!captureId) return false;
|
|
1298
|
+
const access = await getAccessibleCapture(captureId);
|
|
1299
|
+
if (!access) return false;
|
|
1300
|
+
if (
|
|
1301
|
+
evalCase.requireSlackProvider &&
|
|
1302
|
+
((result.provider ?? result.source?.provider) !== "slack" ||
|
|
1303
|
+
access.source.provider !== "slack")
|
|
1304
|
+
) {
|
|
1305
|
+
return false;
|
|
1306
|
+
}
|
|
1307
|
+
const canonicalUrl = sourceUrlFromMetadata(
|
|
1308
|
+
parseJson<Record<string, unknown>>(access.capture.metadataJson, {}),
|
|
1309
|
+
);
|
|
1310
|
+
return Boolean(
|
|
1311
|
+
canonicalUrl === url &&
|
|
1312
|
+
citationEvidenceMatchesCapture(result.citation, access.capture.content),
|
|
1313
|
+
);
|
|
1295
1314
|
}
|
|
1296
1315
|
|
|
1297
1316
|
function findRetrievalEvalMatch(
|
|
@@ -1324,7 +1343,9 @@ async function evaluateRetrievalEvalCases() {
|
|
|
1324
1343
|
limit: 8,
|
|
1325
1344
|
});
|
|
1326
1345
|
const match = findRetrievalEvalMatch(results, evalCase);
|
|
1327
|
-
const citationOk = match
|
|
1346
|
+
const citationOk = match
|
|
1347
|
+
? await hasExpectedCitation(match, evalCase)
|
|
1348
|
+
: false;
|
|
1328
1349
|
|
|
1329
1350
|
if (evalCase.kind === "answer") {
|
|
1330
1351
|
answerCaseCount += 1;
|
|
@@ -202,6 +202,10 @@ export async function hybridSearchArtifacts(input: {
|
|
|
202
202
|
namespace: SEARCH_NAMESPACE,
|
|
203
203
|
});
|
|
204
204
|
ftsRanks = new Map(fts.map((hit, index) => [hit.chunkId, index + 1]));
|
|
205
|
+
} catch {
|
|
206
|
+
ftsRanks = new Map();
|
|
207
|
+
}
|
|
208
|
+
try {
|
|
205
209
|
const family = defaultEmbeddingFamily(await availableEmbeddingFamilies());
|
|
206
210
|
if (family) {
|
|
207
211
|
const [queryVector] = await family.embed(
|
|
@@ -273,7 +277,6 @@ export async function hybridSearchArtifacts(input: {
|
|
|
273
277
|
}
|
|
274
278
|
}
|
|
275
279
|
} catch {
|
|
276
|
-
ftsRanks = new Map();
|
|
277
280
|
semanticRanks = new Map();
|
|
278
281
|
}
|
|
279
282
|
}
|