@agent-native/core 0.186.0 → 0.187.0-nightly-20260923203303
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/clips/app/components/library/page-header.tsx +5 -37
- package/corpus/templates/clips/app/i18n/en-US.ts +0 -1
- package/corpus/templates/mail/AGENTS.md +1 -1
- package/corpus/templates/mail/actions/get-ai-priority.ts +26 -9
- package/corpus/templates/mail/actions/get-jev-availability.ts +23 -0
- package/corpus/templates/mail/actions/navigate.ts +19 -2
- package/corpus/templates/mail/app/components/email/EmailList.tsx +13 -4
- package/corpus/templates/mail/app/pages/InboxPage.tsx +47 -6
- package/corpus/templates/mail/changelog/2026-09-22-jev-powered-mail-rules-and-priority-sort-work-with-an-enable.md +6 -0
- package/corpus/templates/mail/changelog/2026-09-23-preserve-priority-sort-on-availability-error.md +6 -0
- package/corpus/templates/mail/server/lib/automation-engine.ts +147 -132
- package/corpus/templates/mail/server/lib/automation-model.ts +32 -1
- package/dist/agent/jev-tool-prefetch.d.ts +27 -3
- package/dist/agent/jev-tool-prefetch.js +103 -23
- package/dist/agent/production-agent.d.ts +9 -0
- package/dist/agent/production-agent.js +55 -23
- package/dist/app-config/integrations.d.ts +1 -0
- package/dist/app-config/integrations.js +7 -0
- package/dist/app-config/schema.d.ts +1 -0
- package/dist/automation/index.d.ts +1 -1
- package/dist/integrations/a2a-continuation-processor.js +35 -3
- package/dist/integrations/a2a-continuations-store.d.ts +2 -0
- package/dist/integrations/a2a-continuations-store.js +44 -2
- package/dist/integrations/integration-campaign-recovery.js +13 -2
- package/dist/integrations/integration-campaigns-store.d.ts +1 -0
- package/dist/integrations/integration-campaigns-store.js +18 -0
- package/dist/integrations/integration-durable-dispatch-config.js +2 -8
- package/dist/integrations/integration-durable-dispatch.d.ts +2 -0
- package/dist/integrations/integration-durable-dispatch.js +20 -4
- package/dist/integrations/plugin.js +11 -1
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/agent-chat/prompt-resources.d.ts +1 -0
- package/dist/server/agent-chat/prompt-resources.js +5 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
- package/dist/server/credential-provider.d.ts +1 -1
- package/dist/server/credential-provider.js +4 -3
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.js +2 -1
- package/package.json +3 -3
|
@@ -11,8 +11,14 @@ import {
|
|
|
11
11
|
saveOAuthTokens,
|
|
12
12
|
} from "@agent-native/core/oauth-tokens";
|
|
13
13
|
import {
|
|
14
|
+
getRequestContext,
|
|
15
|
+
getJevContextCredentials,
|
|
16
|
+
isJevEnabled,
|
|
14
17
|
readDeployCredentialEnv,
|
|
18
|
+
requestJevThroughBuilder,
|
|
15
19
|
runWithRequestContext,
|
|
20
|
+
type JevContextCredentials,
|
|
21
|
+
type JevResponse,
|
|
16
22
|
} from "@agent-native/core/server";
|
|
17
23
|
import { getUserSetting, putUserSetting } from "@agent-native/core/settings";
|
|
18
24
|
import {
|
|
@@ -44,6 +50,7 @@ import {
|
|
|
44
50
|
resolveAutomationModelSettings,
|
|
45
51
|
resolveTextAutomationModelSettings,
|
|
46
52
|
TYPESAFE_AUTOMATION_ENGINE,
|
|
53
|
+
TYPESAFE_AUTOMATION_MODEL,
|
|
47
54
|
type AutomationModelSettings,
|
|
48
55
|
} from "./automation-model.js";
|
|
49
56
|
import {
|
|
@@ -381,14 +388,45 @@ function isMissingProviderError(message: string): boolean {
|
|
|
381
388
|
async function canUseAutomationModel(
|
|
382
389
|
ownerEmail: string,
|
|
383
390
|
settings: AutomationModelSettings,
|
|
384
|
-
): Promise<
|
|
391
|
+
): Promise<{
|
|
392
|
+
available: boolean;
|
|
393
|
+
jevCredentials?: JevContextCredentials;
|
|
394
|
+
legacyTypesafeApiKey?: string;
|
|
395
|
+
}> {
|
|
385
396
|
if (settings.engine === TYPESAFE_AUTOMATION_ENGINE) {
|
|
386
|
-
return
|
|
397
|
+
return runWithRequestContext(
|
|
398
|
+
{ ...getRequestContext(), userEmail: ownerEmail },
|
|
399
|
+
async () => {
|
|
400
|
+
const jevCredentials = await getJevContextCredentials(ownerEmail);
|
|
401
|
+
const legacyTypesafeApiKey =
|
|
402
|
+
readDeployCredentialEnv("TYPESAFE_API_KEY")?.trim() || undefined;
|
|
403
|
+
let available: boolean;
|
|
404
|
+
try {
|
|
405
|
+
available = await isJevEnabled(jevCredentials);
|
|
406
|
+
} catch (error) {
|
|
407
|
+
if (!legacyTypesafeApiKey) throw error;
|
|
408
|
+
console.warn(
|
|
409
|
+
"[automation-engine] Jev entitlement check failed; using the legacy Typesafe deployment key.",
|
|
410
|
+
error,
|
|
411
|
+
);
|
|
412
|
+
available = false;
|
|
413
|
+
}
|
|
414
|
+
return {
|
|
415
|
+
available: available || Boolean(legacyTypesafeApiKey),
|
|
416
|
+
jevCredentials,
|
|
417
|
+
...(!available && legacyTypesafeApiKey
|
|
418
|
+
? { legacyTypesafeApiKey }
|
|
419
|
+
: {}),
|
|
420
|
+
};
|
|
421
|
+
},
|
|
422
|
+
);
|
|
387
423
|
}
|
|
388
424
|
|
|
389
425
|
const cacheKey = `${ownerEmail}:${settings.engine ?? ""}:${settings.model ?? ""}`;
|
|
390
426
|
const cached = modelAvailabilityCache.get(cacheKey);
|
|
391
|
-
if (cached && cached.expiresAt > Date.now())
|
|
427
|
+
if (cached && cached.expiresAt > Date.now()) {
|
|
428
|
+
return { available: cached.ok };
|
|
429
|
+
}
|
|
392
430
|
|
|
393
431
|
try {
|
|
394
432
|
registerBuiltinEngines();
|
|
@@ -413,7 +451,7 @@ async function canUseAutomationModel(
|
|
|
413
451
|
ok: true,
|
|
414
452
|
expiresAt: Date.now() + MODEL_AVAILABILITY_CACHE_TTL_MS,
|
|
415
453
|
});
|
|
416
|
-
return true;
|
|
454
|
+
return { available: true };
|
|
417
455
|
} catch (err: any) {
|
|
418
456
|
const message = err?.message || "Automation model unavailable";
|
|
419
457
|
if (!isMissingProviderError(message)) throw err;
|
|
@@ -422,7 +460,7 @@ async function canUseAutomationModel(
|
|
|
422
460
|
error: message,
|
|
423
461
|
expiresAt: Date.now() + MODEL_AVAILABILITY_CACHE_TTL_MS,
|
|
424
462
|
});
|
|
425
|
-
return false;
|
|
463
|
+
return { available: false };
|
|
426
464
|
}
|
|
427
465
|
}
|
|
428
466
|
|
|
@@ -529,10 +567,9 @@ async function evaluateRulesWithJev(
|
|
|
529
567
|
emails: EmailSummary[],
|
|
530
568
|
rules: RuleRecord[],
|
|
531
569
|
ownerEmail: string,
|
|
570
|
+
credentials: JevContextCredentials,
|
|
571
|
+
legacyTypesafeApiKey?: string,
|
|
532
572
|
): Promise<Map<string, RuleMatch[]>> {
|
|
533
|
-
const apiKey = readDeployCredentialEnv("TYPESAFE_API_KEY");
|
|
534
|
-
if (!apiKey) throw new Error("TypeSafe Jev is not configured.");
|
|
535
|
-
|
|
536
573
|
const questionEntries = emails.flatMap((email, emailIndex) =>
|
|
537
574
|
rules.map((rule, ruleIndex) => {
|
|
538
575
|
const id = `q_${emailIndex}_${ruleIndex}`;
|
|
@@ -573,33 +610,23 @@ async function evaluateRulesWithJev(
|
|
|
573
610
|
questions: Object.fromEntries(questionEntries),
|
|
574
611
|
};
|
|
575
612
|
|
|
576
|
-
let
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
signal: AbortSignal.timeout(12_000),
|
|
586
|
-
});
|
|
587
|
-
if (response.ok) break;
|
|
588
|
-
if (attempt === 0 && (response.status === 429 || response.status === 529)) {
|
|
589
|
-
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
590
|
-
continue;
|
|
613
|
+
let payload: JevResponse;
|
|
614
|
+
if (credentials.builderAuth && !legacyTypesafeApiKey) {
|
|
615
|
+
try {
|
|
616
|
+
payload = await requestJevThroughBuilder(credentials.builderAuth, body, {
|
|
617
|
+
timeoutMs: 12_000,
|
|
618
|
+
});
|
|
619
|
+
} catch (error) {
|
|
620
|
+
if (!credentials.personalApiKey) throw error;
|
|
621
|
+
payload = await requestJevDirect(credentials.personalApiKey, body);
|
|
591
622
|
}
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
);
|
|
623
|
+
} else if (credentials.personalApiKey) {
|
|
624
|
+
payload = await requestJevDirect(credentials.personalApiKey, body);
|
|
625
|
+
} else if (legacyTypesafeApiKey) {
|
|
626
|
+
payload = await requestJevDirect(legacyTypesafeApiKey, body);
|
|
627
|
+
} else {
|
|
628
|
+
throw new Error("Jev is not enabled.");
|
|
596
629
|
}
|
|
597
|
-
|
|
598
|
-
if (!response?.ok) throw new Error("TypeSafe Jev request failed.");
|
|
599
|
-
const payload = (await response.json()) as {
|
|
600
|
-
answers?: Record<string, { type?: string; noul?: number }>;
|
|
601
|
-
usage?: { input_tokens?: number; output_tokens?: number };
|
|
602
|
-
};
|
|
603
630
|
if (!payload.answers || typeof payload.answers !== "object") {
|
|
604
631
|
throw new Error("TypeSafe Jev returned no answers.");
|
|
605
632
|
}
|
|
@@ -653,13 +680,22 @@ async function evaluateRules(
|
|
|
653
680
|
ownerEmail: string,
|
|
654
681
|
modelSettings: AutomationModelSettings,
|
|
655
682
|
aiFilterState?: AiFilterState,
|
|
683
|
+
jevCredentials?: JevContextCredentials,
|
|
684
|
+
legacyTypesafeApiKey?: string,
|
|
656
685
|
): Promise<Map<string, RuleMatch[]>> {
|
|
657
686
|
// Returns: messageId → array of matched rules with model confidence/reason.
|
|
658
687
|
const results = new Map<string, RuleMatch[]>();
|
|
659
688
|
if (emails.length === 0 || rules.length === 0) return results;
|
|
660
689
|
|
|
661
690
|
if (modelSettings.engine === TYPESAFE_AUTOMATION_ENGINE) {
|
|
662
|
-
|
|
691
|
+
if (!jevCredentials) throw new Error("Jev is not enabled.");
|
|
692
|
+
return evaluateRulesWithJev(
|
|
693
|
+
emails,
|
|
694
|
+
rules,
|
|
695
|
+
ownerEmail,
|
|
696
|
+
jevCredentials,
|
|
697
|
+
legacyTypesafeApiKey,
|
|
698
|
+
);
|
|
663
699
|
}
|
|
664
700
|
|
|
665
701
|
// Process in batches of 10 emails per call
|
|
@@ -783,10 +819,13 @@ async function evaluatePriorityWithJev(
|
|
|
783
819
|
emails: EmailSummary[],
|
|
784
820
|
instruction: string,
|
|
785
821
|
ownerEmail: string,
|
|
822
|
+
credentials: JevContextCredentials,
|
|
786
823
|
signal?: AbortSignal,
|
|
787
824
|
): Promise<Map<string, PriorityScore>> {
|
|
788
|
-
const
|
|
789
|
-
if (!
|
|
825
|
+
const { builderAuth, personalApiKey } = credentials;
|
|
826
|
+
if (!personalApiKey && !builderAuth) {
|
|
827
|
+
throw new Error("Jev is not enabled.");
|
|
828
|
+
}
|
|
790
829
|
|
|
791
830
|
const questions = Object.fromEntries(
|
|
792
831
|
emails.map((email, index) => [
|
|
@@ -817,36 +856,23 @@ async function evaluatePriorityWithJev(
|
|
|
817
856
|
questions,
|
|
818
857
|
};
|
|
819
858
|
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
? AbortSignal.any([signal, AbortSignal.timeout(12_000)])
|
|
832
|
-
: AbortSignal.timeout(12_000),
|
|
833
|
-
});
|
|
834
|
-
if (response.ok) break;
|
|
835
|
-
if (attempt === 0 && (response.status === 429 || response.status === 529)) {
|
|
836
|
-
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
837
|
-
continue;
|
|
859
|
+
const request: Record<string, unknown> = { ...body };
|
|
860
|
+
let payload: JevResponse;
|
|
861
|
+
if (builderAuth) {
|
|
862
|
+
try {
|
|
863
|
+
payload = await requestJevThroughBuilder(builderAuth, request, {
|
|
864
|
+
signal,
|
|
865
|
+
timeoutMs: 12_000,
|
|
866
|
+
});
|
|
867
|
+
} catch (error) {
|
|
868
|
+
if (!personalApiKey) throw error;
|
|
869
|
+
payload = await requestJevDirect(personalApiKey, request, signal);
|
|
838
870
|
}
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
);
|
|
871
|
+
} else if (personalApiKey) {
|
|
872
|
+
payload = await requestJevDirect(personalApiKey, request, signal);
|
|
873
|
+
} else {
|
|
874
|
+
throw new Error("Jev is not enabled.");
|
|
843
875
|
}
|
|
844
|
-
|
|
845
|
-
if (!response?.ok) throw new Error("TypeSafe Jev request failed.");
|
|
846
|
-
const payload = (await response.json()) as {
|
|
847
|
-
answers?: Record<string, { noul?: number }>;
|
|
848
|
-
usage?: { input_tokens?: number; output_tokens?: number };
|
|
849
|
-
};
|
|
850
876
|
if (!payload.answers || typeof payload.answers !== "object") {
|
|
851
877
|
throw new Error("TypeSafe Jev returned no answers.");
|
|
852
878
|
}
|
|
@@ -888,78 +914,54 @@ async function evaluatePriorityWithJev(
|
|
|
888
914
|
return results;
|
|
889
915
|
}
|
|
890
916
|
|
|
891
|
-
async function
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
ownerEmail: string,
|
|
895
|
-
modelSettings: AutomationModelSettings,
|
|
917
|
+
async function requestJevDirect(
|
|
918
|
+
apiKey: string,
|
|
919
|
+
body: Record<string, unknown>,
|
|
896
920
|
signal?: AbortSignal,
|
|
897
|
-
): Promise<
|
|
898
|
-
|
|
899
|
-
const batchSize = 25;
|
|
900
|
-
for (let i = 0; i < emails.length; i += batchSize) {
|
|
921
|
+
): Promise<JevResponse> {
|
|
922
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
901
923
|
signal?.throwIfAborted();
|
|
902
|
-
const
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
.
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
Use a score from 0 to 1. Give higher scores to emails that deserve attention sooner. Do not use the age of the email alone as the reason.`;
|
|
918
|
-
const text = await callModel(prompt, ownerEmail, modelSettings, signal);
|
|
919
|
-
const jsonStr = text
|
|
920
|
-
.replace(/```json?\n?/g, "")
|
|
921
|
-
.replace(/```/g, "")
|
|
922
|
-
.trim();
|
|
923
|
-
const parsed = JSON.parse(jsonStr) as Array<{
|
|
924
|
-
emailId: string;
|
|
925
|
-
score: number;
|
|
926
|
-
reason?: string;
|
|
927
|
-
}>;
|
|
928
|
-
if (!Array.isArray(parsed)) {
|
|
929
|
-
throw new Error("Priority model returned a non-array result.");
|
|
930
|
-
}
|
|
931
|
-
for (const result of parsed) {
|
|
932
|
-
if (
|
|
933
|
-
typeof result?.emailId !== "string" ||
|
|
934
|
-
typeof result.score !== "number" ||
|
|
935
|
-
!Number.isFinite(result.score)
|
|
936
|
-
) {
|
|
937
|
-
continue;
|
|
938
|
-
}
|
|
939
|
-
results.set(result.emailId, {
|
|
940
|
-
score: Math.min(1, Math.max(0, result.score)),
|
|
941
|
-
...(typeof result.reason === "string"
|
|
942
|
-
? { reason: result.reason.slice(0, 500) }
|
|
943
|
-
: {}),
|
|
944
|
-
});
|
|
924
|
+
const response = await fetch("https://api.typesafe.ai/v1/systemone", {
|
|
925
|
+
method: "POST",
|
|
926
|
+
headers: {
|
|
927
|
+
Authorization: `Bearer ${apiKey}`,
|
|
928
|
+
"Content-Type": "application/json",
|
|
929
|
+
},
|
|
930
|
+
body: JSON.stringify(body),
|
|
931
|
+
signal: signal
|
|
932
|
+
? AbortSignal.any([signal, AbortSignal.timeout(12_000)])
|
|
933
|
+
: AbortSignal.timeout(12_000),
|
|
934
|
+
});
|
|
935
|
+
if (response.ok) return (await response.json()) as JevResponse;
|
|
936
|
+
if (attempt === 0 && (response.status === 429 || response.status === 529)) {
|
|
937
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
938
|
+
continue;
|
|
945
939
|
}
|
|
940
|
+
const detail = (await response.text()).slice(0, 300);
|
|
941
|
+
throw new Error(
|
|
942
|
+
`TypeSafe Jev request failed (${response.status})${detail ? `: ${detail}` : ""}`,
|
|
943
|
+
);
|
|
946
944
|
}
|
|
947
|
-
|
|
945
|
+
throw new Error("TypeSafe Jev request failed.");
|
|
948
946
|
}
|
|
949
947
|
|
|
950
948
|
export async function previewAutomationPriority(
|
|
951
949
|
emails: AiPriorityEmail[],
|
|
952
950
|
ownerEmail: string,
|
|
953
951
|
instruction = AI_PRIORITY_DEFAULT_INSTRUCTION,
|
|
952
|
+
jevCredentials: JevContextCredentials,
|
|
954
953
|
signal?: AbortSignal,
|
|
955
954
|
): Promise<{
|
|
956
955
|
scores: Map<string, PriorityScore>;
|
|
957
956
|
model: AutomationModelSettings;
|
|
958
957
|
}> {
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
throw new Error("No LLM provider is connected for Mail priority sort.");
|
|
958
|
+
if (!jevCredentials.personalApiKey && !jevCredentials.builderAuth) {
|
|
959
|
+
throw new Error("Jev is not enabled.");
|
|
962
960
|
}
|
|
961
|
+
const model = {
|
|
962
|
+
engine: TYPESAFE_AUTOMATION_ENGINE,
|
|
963
|
+
model: TYPESAFE_AUTOMATION_MODEL,
|
|
964
|
+
};
|
|
963
965
|
|
|
964
966
|
const messages: EmailSummary[] = emails
|
|
965
967
|
.filter(
|
|
@@ -983,16 +985,13 @@ export async function previewAutomationPriority(
|
|
|
983
985
|
for (let i = 0; i < messages.length; i += 50) {
|
|
984
986
|
signal?.throwIfAborted();
|
|
985
987
|
const batch = messages.slice(i, i + 50);
|
|
986
|
-
const batchScores =
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
model,
|
|
994
|
-
signal,
|
|
995
|
-
);
|
|
988
|
+
const batchScores = await evaluatePriorityWithJev(
|
|
989
|
+
batch,
|
|
990
|
+
instruction,
|
|
991
|
+
ownerEmail,
|
|
992
|
+
jevCredentials,
|
|
993
|
+
signal,
|
|
994
|
+
);
|
|
996
995
|
for (const [emailId, score] of batchScores) scores.set(emailId, score);
|
|
997
996
|
}
|
|
998
997
|
return { scores, model };
|
|
@@ -1008,7 +1007,8 @@ export async function previewAutomationRules(
|
|
|
1008
1007
|
model: AutomationModelSettings;
|
|
1009
1008
|
}> {
|
|
1010
1009
|
const model = await getAutomationModelSettings(ownerEmail);
|
|
1011
|
-
|
|
1010
|
+
const modelAccess = await canUseAutomationModel(ownerEmail, model);
|
|
1011
|
+
if (!modelAccess.available) {
|
|
1012
1012
|
throw new Error("No LLM provider is connected for Mail AI rules.");
|
|
1013
1013
|
}
|
|
1014
1014
|
const messages: EmailSummary[] = emails
|
|
@@ -1041,6 +1041,8 @@ export async function previewAutomationRules(
|
|
|
1041
1041
|
ownerEmail,
|
|
1042
1042
|
model,
|
|
1043
1043
|
aiFilterState,
|
|
1044
|
+
modelAccess.jevCredentials,
|
|
1045
|
+
modelAccess.legacyTypesafeApiKey,
|
|
1044
1046
|
);
|
|
1045
1047
|
return { matches, model };
|
|
1046
1048
|
}
|
|
@@ -1137,7 +1139,18 @@ export async function processAutomationsForAccount(
|
|
|
1137
1139
|
// 2. Resolve model settings. Credentials are resolved by the selected engine
|
|
1138
1140
|
// under the owner's request context, so Builder-managed models work here too.
|
|
1139
1141
|
const modelSettings = await getAutomationModelSettings(ownerEmail);
|
|
1140
|
-
|
|
1142
|
+
let modelAccess: Awaited<ReturnType<typeof canUseAutomationModel>>;
|
|
1143
|
+
try {
|
|
1144
|
+
modelAccess = await canUseAutomationModel(ownerEmail, modelSettings);
|
|
1145
|
+
} catch (error) {
|
|
1146
|
+
console.error(
|
|
1147
|
+
"[automation-engine] Model availability check failed:",
|
|
1148
|
+
error,
|
|
1149
|
+
);
|
|
1150
|
+
result.errors = 1;
|
|
1151
|
+
return result;
|
|
1152
|
+
}
|
|
1153
|
+
if (!modelAccess.available) {
|
|
1141
1154
|
result.errors = 1;
|
|
1142
1155
|
return result;
|
|
1143
1156
|
}
|
|
@@ -1194,6 +1207,8 @@ export async function processAutomationsForAccount(
|
|
|
1194
1207
|
ownerEmail,
|
|
1195
1208
|
modelSettings,
|
|
1196
1209
|
aiFilterState,
|
|
1210
|
+
modelAccess.jevCredentials,
|
|
1211
|
+
modelAccess.legacyTypesafeApiKey,
|
|
1197
1212
|
);
|
|
1198
1213
|
|
|
1199
1214
|
// 6. Execute matched actions
|
|
@@ -4,6 +4,8 @@ import {
|
|
|
4
4
|
resolveEngine,
|
|
5
5
|
} from "@agent-native/core/agent/engine";
|
|
6
6
|
import {
|
|
7
|
+
getJevContextCredentials,
|
|
8
|
+
isJevEnabled,
|
|
7
9
|
readDeployCredentialEnv,
|
|
8
10
|
runWithRequestContext,
|
|
9
11
|
} from "@agent-native/core/server";
|
|
@@ -67,7 +69,34 @@ async function resolveEngineDefaultModel(
|
|
|
67
69
|
export async function resolveDefaultAutomationModel(
|
|
68
70
|
ownerEmail: string,
|
|
69
71
|
): Promise<AutomationModelSettings> {
|
|
70
|
-
|
|
72
|
+
const jevAvailability = await runWithRequestContext(
|
|
73
|
+
{ userEmail: ownerEmail },
|
|
74
|
+
async () => {
|
|
75
|
+
try {
|
|
76
|
+
return {
|
|
77
|
+
status: "checked" as const,
|
|
78
|
+
enabled: await isJevEnabled(
|
|
79
|
+
await getJevContextCredentials(ownerEmail),
|
|
80
|
+
),
|
|
81
|
+
};
|
|
82
|
+
} catch (error) {
|
|
83
|
+
return { status: "error" as const, error };
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
);
|
|
87
|
+
if (jevAvailability.status === "error") {
|
|
88
|
+
console.warn(
|
|
89
|
+
"[automation-model] Jev availability check failed; using the configured model.",
|
|
90
|
+
jevAvailability.error,
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
if (jevAvailability.status === "checked" && jevAvailability.enabled) {
|
|
94
|
+
return {
|
|
95
|
+
engine: TYPESAFE_AUTOMATION_ENGINE,
|
|
96
|
+
model: TYPESAFE_AUTOMATION_MODEL,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
if (readDeployCredentialEnv("TYPESAFE_API_KEY")?.trim()) {
|
|
71
100
|
return {
|
|
72
101
|
engine: TYPESAFE_AUTOMATION_ENGINE,
|
|
73
102
|
model: TYPESAFE_AUTOMATION_MODEL,
|
|
@@ -137,6 +166,8 @@ export async function resolveAutomationModelSettings(
|
|
|
137
166
|
ownerEmail: string,
|
|
138
167
|
settings: AutomationModelSettings | null | undefined,
|
|
139
168
|
): Promise<AutomationModelSettings> {
|
|
169
|
+
if (settings?.engine && settings.model) return settings;
|
|
170
|
+
|
|
140
171
|
const defaults = await resolveDefaultAutomationModel(ownerEmail);
|
|
141
172
|
if (!settings?.engine && !settings?.model) return defaults;
|
|
142
173
|
|
|
@@ -1,7 +1,19 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type BuilderGatewayAuth } from "../server/credential-provider.js";
|
|
2
2
|
import type { EngineTool } from "./engine/types.js";
|
|
3
|
-
import type { ActionEntry } from "./production-agent.js";
|
|
4
|
-
|
|
3
|
+
import type { ActionEntry, JevContextCredentials } from "./production-agent.js";
|
|
4
|
+
type JevChoiceAnswer = {
|
|
5
|
+
choice?: unknown;
|
|
6
|
+
probabilities?: unknown;
|
|
7
|
+
};
|
|
8
|
+
export type JevResponse = {
|
|
9
|
+
answers?: Record<string, JevChoiceAnswer & {
|
|
10
|
+
noul?: unknown;
|
|
11
|
+
}>;
|
|
12
|
+
usage?: {
|
|
13
|
+
input_tokens?: number;
|
|
14
|
+
output_tokens?: number;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
5
17
|
export interface JevCandidate {
|
|
6
18
|
id: string;
|
|
7
19
|
description: string;
|
|
@@ -11,6 +23,7 @@ export interface JevCandidate {
|
|
|
11
23
|
export interface JevRankCandidatesOptions {
|
|
12
24
|
request: string;
|
|
13
25
|
apiKey?: string;
|
|
26
|
+
personalApiKey?: string;
|
|
14
27
|
builderAuth?: BuilderGatewayAuth | null;
|
|
15
28
|
candidates: readonly JevCandidate[];
|
|
16
29
|
candidateStateKey: string;
|
|
@@ -28,6 +41,7 @@ export declare function shortlistJevCandidates<T extends JevCandidate>(request:
|
|
|
28
41
|
export interface JevToolPrefetchOptions {
|
|
29
42
|
request: string;
|
|
30
43
|
apiKey?: string;
|
|
44
|
+
personalApiKey?: string;
|
|
31
45
|
builderAuth?: BuilderGatewayAuth | null;
|
|
32
46
|
registry: Record<string, ActionEntry>;
|
|
33
47
|
initialTools: EngineTool[];
|
|
@@ -42,3 +56,13 @@ export interface JevToolPrefetchOptions {
|
|
|
42
56
|
* Jev is an accelerator, not a dependency of agent execution.
|
|
43
57
|
*/
|
|
44
58
|
export declare function preloadJevTools(options: JevToolPrefetchOptions): Promise<EngineTool[]>;
|
|
59
|
+
export declare function requestJevThroughBuilder(auth: BuilderGatewayAuth, request: Record<string, unknown>, options?: {
|
|
60
|
+
signal?: AbortSignal;
|
|
61
|
+
timeoutMs?: number;
|
|
62
|
+
}): Promise<JevResponse>;
|
|
63
|
+
export declare function isBuilderJevEnabled(auth: BuilderGatewayAuth, options?: {
|
|
64
|
+
signal?: AbortSignal;
|
|
65
|
+
timeoutMs?: number;
|
|
66
|
+
}): Promise<boolean>;
|
|
67
|
+
export declare function isJevEnabled(credentials: JevContextCredentials): Promise<boolean>;
|
|
68
|
+
export {};
|