@agent-native/core 0.203.1-nightly-20261007154213 → 0.203.1

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.
Files changed (39) hide show
  1. package/dist/agent/default-agent-engine.d.ts +1 -1
  2. package/dist/agent/default-agent-engine.js +1 -1
  3. package/dist/agent/engine-status.d.ts +49 -0
  4. package/dist/agent/engine-status.js +112 -0
  5. package/dist/client/client-status-requests.js +8 -0
  6. package/dist/collab/awareness.d.ts +2 -2
  7. package/dist/collab/routes.d.ts +1 -1
  8. package/dist/jobs/actions/manage-recurring-job.d.ts +1 -1
  9. package/dist/jobs/frontmatter-loss.d.ts +17 -0
  10. package/dist/jobs/frontmatter-loss.js +62 -0
  11. package/dist/jobs/frontmatter.d.ts +7 -0
  12. package/dist/jobs/frontmatter.js +39 -0
  13. package/dist/jobs/tools.js +16 -3
  14. package/dist/localization/default-model-messages.d.ts +11 -0
  15. package/dist/localization/default-model-messages.js +88 -0
  16. package/dist/notifications/routes.d.ts +1 -1
  17. package/dist/observability/routes.d.ts +2 -2
  18. package/dist/org/index.d.ts +1 -1
  19. package/dist/progress/routes.d.ts +1 -1
  20. package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
  21. package/dist/provider-api/actions/provider-api.d.ts +8 -8
  22. package/dist/resources/handlers.d.ts +1 -1
  23. package/dist/resources/store.js +40 -2
  24. package/dist/scripts/agent-engines/list-agent-engines.js +8 -5
  25. package/dist/scripts/agent-engines/manage-agent-engine.js +22 -4
  26. package/dist/scripts/agent-engines/set-agent-engine.d.ts +25 -0
  27. package/dist/scripts/agent-engines/set-agent-engine.js +94 -8
  28. package/dist/secrets/routes.d.ts +6 -6
  29. package/dist/server/agent-engine-default-model-route.d.ts +1 -1
  30. package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
  31. package/dist/server/core-routes-plugin.d.ts +1 -43
  32. package/dist/server/core-routes-plugin.js +15 -92
  33. package/dist/server/email-auth-links.js +98 -2
  34. package/dist/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +26 -39
  35. package/dist/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +16 -1
  36. package/dist/triggers/actions/manage-automation.d.ts +7 -7
  37. package/package.json +4 -4
  38. package/src/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +26 -39
  39. package/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +16 -1
@@ -71,7 +71,7 @@ export declare function readDefaultAgentEngineSetting(ctx?: DefaultAgentEngineCo
71
71
  export declare function resolveDefaultAgentEngineAuthority(ctx?: DefaultAgentEngineContext): Promise<DefaultAgentEngineAuthority>;
72
72
  /**
73
73
  * Save the default for the authority's scope. Validate the engine first; this
74
- * only stores it and records the change.
74
+ * stores only that scope and records the change.
75
75
  */
76
76
  export declare function writeDefaultAgentEngineSelection(authority: Extract<DefaultAgentEngineAuthority, {
77
77
  allowed: true;
@@ -95,7 +95,7 @@ async function writeScopedRow(authority, value) {
95
95
  }
96
96
  /**
97
97
  * Save the default for the authority's scope. Validate the engine first; this
98
- * only stores it and records the change.
98
+ * stores only that scope and records the change.
99
99
  */
100
100
  export async function writeDefaultAgentEngineSelection(authority, selection, meta) {
101
101
  await writeScopedRow(authority, {
@@ -0,0 +1,49 @@
1
+ export declare function normalizeAgentEngineStatusModel(entry: {
2
+ name: string;
3
+ defaultModel: string;
4
+ supportedModels: readonly string[];
5
+ } | undefined, model: string | null | undefined): string;
6
+ type AgentEngineStatusEntry = {
7
+ name: string;
8
+ defaultModel: string;
9
+ supportedModels: readonly string[];
10
+ requiredEnvVars: readonly string[];
11
+ };
12
+ export interface AgentEngineStatusResult {
13
+ configured: boolean;
14
+ engine?: string;
15
+ model?: string;
16
+ source?: "settings" | "env" | "app_secrets" | "app-default";
17
+ selectionSource?: "configuration" | "app-default" | "shared-default" | "app_secrets" | "env";
18
+ envVar?: string;
19
+ openAiBaseUrlConfigured?: boolean;
20
+ }
21
+ export interface AgentEngineStatusResponse extends AgentEngineStatusResult {
22
+ /** Strict chat-only eligibility; distinct from broad engine `configured`. */
23
+ chatEligible: boolean;
24
+ }
25
+ export interface AgentEngineStatusDeps<E extends AgentEngineStatusEntry = AgentEngineStatusEntry> {
26
+ readStoredEngine: () => Promise<{
27
+ engine?: string;
28
+ model?: string;
29
+ } | null>;
30
+ readAppDefault?: () => Promise<{
31
+ engine: string;
32
+ model: string;
33
+ } | null>;
34
+ readOpenAiBaseUrlConfigured: () => boolean | Promise<boolean>;
35
+ isStoredEngineUsable: (stored: unknown, entry: E) => boolean | Promise<boolean>;
36
+ detectFromUserSecrets: () => Promise<E | null>;
37
+ detectFromEnv: () => E | null | Promise<E | null>;
38
+ lookupEntry?: (engine: string) => E | undefined;
39
+ }
40
+ /**
41
+ * Resolve "does this request have a usable AI provider" for one identity.
42
+ *
43
+ * Every call site pays for these lookups on a user-visible path (the agent
44
+ * composer blocks on the status probe), so the two identity-independent reads
45
+ * start together and the expensive `app_secrets` sweep only runs when the
46
+ * cheaper sources have not already answered.
47
+ */
48
+ export declare function resolveAgentEngineStatus<E extends AgentEngineStatusEntry>(deps: AgentEngineStatusDeps<E>): Promise<AgentEngineStatusResult>;
49
+ export {};
@@ -0,0 +1,112 @@
1
+ import { getAppConfig } from "../app-config/index.js";
2
+ import { getRequestContext } from "../server/request-context.js";
3
+ import { DEFAULT_MODEL } from "./default-model.js";
4
+ import { getAgentEngineEntry, isAgentEngineSettingConfigured, normalizeModelForEngine, } from "./engine/registry.js";
5
+ export function normalizeAgentEngineStatusModel(entry, model) {
6
+ if (!entry)
7
+ return model ?? DEFAULT_MODEL;
8
+ return normalizeModelForEngine(entry, model ?? entry.defaultModel);
9
+ }
10
+ /**
11
+ * Resolve "does this request have a usable AI provider" for one identity.
12
+ *
13
+ * Every call site pays for these lookups on a user-visible path (the agent
14
+ * composer blocks on the status probe), so the two identity-independent reads
15
+ * start together and the expensive `app_secrets` sweep only runs when the
16
+ * cheaper sources have not already answered.
17
+ */
18
+ export async function resolveAgentEngineStatus(deps) {
19
+ const lookupEntry = (deps.lookupEntry ?? getAgentEngineEntry);
20
+ const [stored, openAiBaseUrlConfigured, appDefault] = await Promise.all([
21
+ deps.readStoredEngine(),
22
+ deps.readOpenAiBaseUrlConfigured(),
23
+ deps.readAppDefault?.(),
24
+ ]);
25
+ const configuredEngine = getAppConfig().agent.engine;
26
+ const configuredModel = getAppConfig().agent.model === "auto"
27
+ ? undefined
28
+ : getAppConfig().agent.model;
29
+ const envEntry = configuredEngine ? lookupEntry(configuredEngine) : undefined;
30
+ if (envEntry) {
31
+ if (await deps.isStoredEngineUsable({ engine: envEntry.name }, envEntry)) {
32
+ return {
33
+ configured: true,
34
+ engine: envEntry.name,
35
+ model: normalizeAgentEngineStatusModel(envEntry, configuredModel ??
36
+ (appDefault?.engine === envEntry.name
37
+ ? appDefault.model
38
+ : stored?.engine === envEntry.name
39
+ ? stored.model
40
+ : undefined)),
41
+ source: "env",
42
+ selectionSource: "configuration",
43
+ envVar: "AGENT_ENGINE",
44
+ openAiBaseUrlConfigured,
45
+ };
46
+ }
47
+ if (getRequestContext()?.isSyntheticTraffic !== true) {
48
+ return {
49
+ configured: false,
50
+ selectionSource: "configuration",
51
+ openAiBaseUrlConfigured,
52
+ };
53
+ }
54
+ }
55
+ if (appDefault) {
56
+ const entry = lookupEntry(appDefault.engine);
57
+ if (entry && (await deps.isStoredEngineUsable(appDefault, entry))) {
58
+ return {
59
+ configured: true,
60
+ engine: appDefault.engine,
61
+ model: normalizeAgentEngineStatusModel(entry, configuredModel ?? appDefault.model),
62
+ source: "app-default",
63
+ selectionSource: configuredModel ? "configuration" : "app-default",
64
+ openAiBaseUrlConfigured,
65
+ };
66
+ }
67
+ }
68
+ // Stored provider selections win over an existing Builder connection, so
69
+ // this is checked before the app_secrets sweep — and the sweep is skipped
70
+ // entirely when it answers.
71
+ if (stored && typeof stored.engine === "string") {
72
+ const entry = lookupEntry(stored.engine);
73
+ if (entry && (await deps.isStoredEngineUsable(stored, entry))) {
74
+ return {
75
+ configured: true,
76
+ engine: stored.engine,
77
+ model: normalizeAgentEngineStatusModel(entry, configuredModel ?? stored.model),
78
+ source: isAgentEngineSettingConfigured(stored) ? "settings" : "env",
79
+ selectionSource: configuredModel ? "configuration" : "shared-default",
80
+ envVar: entry.requiredEnvVars[0],
81
+ openAiBaseUrlConfigured,
82
+ };
83
+ }
84
+ }
85
+ // Per-user app_secrets — a user who connected Builder (or pasted their own
86
+ // provider key) may not have any deploy-level env vars set.
87
+ const detectedFromUser = await deps.detectFromUserSecrets();
88
+ if (detectedFromUser) {
89
+ return {
90
+ configured: true,
91
+ engine: detectedFromUser.name,
92
+ model: normalizeAgentEngineStatusModel(detectedFromUser, configuredModel),
93
+ source: "app_secrets",
94
+ selectionSource: configuredModel ? "configuration" : "app_secrets",
95
+ envVar: detectedFromUser.requiredEnvVars[0],
96
+ openAiBaseUrlConfigured,
97
+ };
98
+ }
99
+ const detected = await deps.detectFromEnv();
100
+ if (detected) {
101
+ return {
102
+ configured: true,
103
+ engine: detected.name,
104
+ model: normalizeAgentEngineStatusModel(detected, configuredModel),
105
+ source: "env",
106
+ selectionSource: configuredModel ? "configuration" : "env",
107
+ envVar: detected.requiredEnvVars[0],
108
+ openAiBaseUrlConfigured,
109
+ };
110
+ }
111
+ return { configured: false, openAiBaseUrlConfigured };
112
+ }
@@ -47,6 +47,14 @@ function installInvalidationListeners() {
47
47
  if (typeof window.addEventListener === "function") {
48
48
  window.addEventListener("focus", expireClientStatusCache);
49
49
  window.addEventListener("agent-engine:configured-changed", invalidateClientStatusRequests);
50
+ window.addEventListener("agent-native:tool-done", (event) => {
51
+ const detail = event.detail;
52
+ if (detail?.tool === "manage-agent-engine" &&
53
+ detail.completedSideEffect === true &&
54
+ detail.isError !== true) {
55
+ window.dispatchEvent(new Event("agent-engine:configured-changed"));
56
+ }
57
+ });
50
58
  }
51
59
  if (typeof document.addEventListener === "function") {
52
60
  document.addEventListener("visibilitychange", () => {
@@ -38,19 +38,19 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
38
38
  error: string;
39
39
  states?: undefined;
40
40
  } | {
41
+ error?: undefined;
41
42
  states: {
42
43
  clientId: number;
43
44
  state: string;
44
45
  }[];
45
- error?: undefined;
46
46
  }>>;
47
47
  export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
48
48
  error: string;
49
49
  users?: undefined;
50
50
  } | {
51
+ error?: undefined;
51
52
  users: {
52
53
  clientId: number;
53
54
  lastSeen: number;
54
55
  }[];
55
- error?: undefined;
56
56
  }>>;
@@ -15,9 +15,9 @@ export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import
15
15
  ok: boolean;
16
16
  }>>;
17
17
  export declare const postCollabText: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
18
+ text?: undefined;
18
19
  ok?: undefined;
19
20
  error: string;
20
- text?: undefined;
21
21
  } | {
22
22
  error?: undefined;
23
23
  ok: boolean;
@@ -11,9 +11,9 @@ declare const _default: import("../../action.js").ActionDefinition<{
11
11
  enabled?: undefined;
12
12
  nextRun?: undefined;
13
13
  } | {
14
- deleted?: undefined;
15
14
  name: string;
16
15
  enabled: boolean;
17
16
  nextRun: string;
17
+ deleted?: undefined;
18
18
  }>;
19
19
  export default _default;
@@ -0,0 +1,17 @@
1
+ export interface JobFileWrite {
2
+ owner: string;
3
+ orgId: string | null;
4
+ path: string;
5
+ before: string;
6
+ after: string;
7
+ writer: string;
8
+ }
9
+ /**
10
+ * A write that removes editor-owned frontmatter fields from a job file is
11
+ * recorded with who wrote it. Several callers have rebuilt a whole job file
12
+ * from the fields they know and silently dropped the rest, and the job keeps
13
+ * running, so the loss shows up days later as a missing channel or name.
14
+ * Never throws: this runs on the scheduler's write path, and a recording
15
+ * failure must not fail the write that triggered it.
16
+ */
17
+ export declare function noteJobFrontmatterWrite(write: JobFileWrite): Promise<void>;
@@ -0,0 +1,62 @@
1
+ import { droppedJobFrontmatterKeys } from "./frontmatter.js";
2
+ const CALLER_FRAMES = 6;
3
+ const SUMMARY_KEYS = 12;
4
+ // Only the function name and `file:line` of each frame: enough to tell
5
+ // `runCreate` from the scheduler without recording server directory layout.
6
+ function callerFrames() {
7
+ const frames = new Error().stack?.split("\n").slice(1) ?? [];
8
+ return frames
9
+ .map((frame) => frame.trim().replace(/^at\s+/, ""))
10
+ .filter((frame) => !frame.includes("frontmatter-loss") &&
11
+ !frame.includes("resources/store") &&
12
+ !frame.includes("node:internal"))
13
+ .slice(0, CALLER_FRAMES)
14
+ .map((frame) => frame.replace(/\(?[^\s()]*[\\/]([^\\/\s():]+:\d+):\d+\)?/, "($1)"));
15
+ }
16
+ /**
17
+ * A write that removes editor-owned frontmatter fields from a job file is
18
+ * recorded with who wrote it. Several callers have rebuilt a whole job file
19
+ * from the fields they know and silently dropped the rest, and the job keeps
20
+ * running, so the loss shows up days later as a missing channel or name.
21
+ * Never throws: this runs on the scheduler's write path, and a recording
22
+ * failure must not fail the write that triggered it.
23
+ */
24
+ export async function noteJobFrontmatterWrite(write) {
25
+ try {
26
+ if (!write.path.startsWith("jobs/"))
27
+ return;
28
+ const dropped = droppedJobFrontmatterKeys(write.before, write.after);
29
+ if (dropped.length === 0)
30
+ return;
31
+ const callers = callerFrames();
32
+ console.warn(`[recurring-jobs] "${write.path}" lost frontmatter fields (${dropped.join(", ")}) in ${write.writer}`, callers);
33
+ const [{ recordOrgAdminAuditEvent }, requestContext] = await Promise.all([
34
+ import("../audit/org-admin.js"),
35
+ import("../server/request-context.js"),
36
+ ]);
37
+ const run = requestContext.getRequestRunContext();
38
+ const userEmail = requestContext.getRequestUserEmail();
39
+ const listed = dropped.slice(0, SUMMARY_KEYS).join(", ");
40
+ await recordOrgAdminAuditEvent({
41
+ action: "job-fields-dropped",
42
+ targetType: "job-file",
43
+ targetId: write.path,
44
+ summary: `Job file ${write.path} lost ${dropped.length} frontmatter field(s): ${listed}${dropped.length > SUMMARY_KEYS ? ", ..." : ""}`,
45
+ userEmail,
46
+ orgId: write.orgId,
47
+ caller: run?.threadId ? "tool" : userEmail ? "http" : "automation",
48
+ threadId: run?.threadId,
49
+ runId: run?.runId,
50
+ args: {
51
+ path: write.path,
52
+ owner: write.owner,
53
+ writer: write.writer,
54
+ droppedKeys: dropped,
55
+ callers,
56
+ },
57
+ });
58
+ }
59
+ catch (error) {
60
+ console.error(`[recurring-jobs] could not check or record lost fields for "${write.path}":`, error);
61
+ }
62
+ }
@@ -95,6 +95,13 @@ export type JobExecutionFrontmatterPatch = {
95
95
  remoteAutomationRunId?: string;
96
96
  remoteAdvanceSchedule?: boolean;
97
97
  };
98
+ export declare const JOB_EXECUTION_FRONTMATTER_KEYS: ReadonlySet<string>;
99
+ /**
100
+ * Frontmatter keys present in `before` and gone from `after`, ignoring the
101
+ * execution bookkeeping a run adds and clears. A job whose file loses its
102
+ * editor-owned fields still schedules and runs, so nothing else notices.
103
+ */
104
+ export declare function droppedJobFrontmatterKeys(before: string, after: string): string[];
98
105
  export type JobFrontmatterPatchValue = string | number | boolean | readonly string[] | undefined;
99
106
  export type JobFrontmatterPatch = {
100
107
  [key: string]: JobFrontmatterPatchValue;
@@ -436,6 +436,45 @@ export function buildJobResourceContent(meta, body) {
436
436
  lines.push("---", "", body);
437
437
  return lines.join("\n");
438
438
  }
439
+ export const JOB_EXECUTION_FRONTMATTER_KEYS = new Set([
440
+ "lastRun",
441
+ "lastCheck",
442
+ "lastStatus",
443
+ "lastError",
444
+ "lastErrorCode",
445
+ "consecutiveFailures",
446
+ "lastFailedEventId",
447
+ "pausedReason",
448
+ "pausedAt",
449
+ "nextRun",
450
+ "remoteRequestId",
451
+ "remoteCommandId",
452
+ "remoteRunId",
453
+ "remoteAutomationRunId",
454
+ "remoteAdvanceSchedule",
455
+ ]);
456
+ const FRONTMATTER_KEY_RE = /^([A-Za-z][A-Za-z0-9_]*):/;
457
+ function frontmatterKeys(content) {
458
+ const keys = new Set();
459
+ const match = content.match(FRONTMATTER_RE);
460
+ if (!match)
461
+ return keys;
462
+ for (const line of match[1].split(/\r?\n/)) {
463
+ const key = FRONTMATTER_KEY_RE.exec(line)?.[1];
464
+ if (key)
465
+ keys.add(key);
466
+ }
467
+ return keys;
468
+ }
469
+ /**
470
+ * Frontmatter keys present in `before` and gone from `after`, ignoring the
471
+ * execution bookkeeping a run adds and clears. A job whose file loses its
472
+ * editor-owned fields still schedules and runs, so nothing else notices.
473
+ */
474
+ export function droppedJobFrontmatterKeys(before, after) {
475
+ const kept = frontmatterKeys(after);
476
+ return [...frontmatterKeys(before)].filter((key) => !kept.has(key) && !JOB_EXECUTION_FRONTMATTER_KEYS.has(key));
477
+ }
439
478
  function jobFrontmatterBounds(content) {
440
479
  const newline = content.startsWith("---\r\n")
441
480
  ? "\r\n"
@@ -1,7 +1,7 @@
1
1
  import { DEFAULT_AUTOMATION_SCHEDULE } from "../automations/service.js";
2
2
  import { getDbExec } from "../db/client.js";
3
3
  import { resolveUserSchedulingTimezone } from "../localization/user-timezone.js";
4
- import { resourcePut, resourceGetByPath, resourceList, resourceDelete, organizationIdFromResourceOwner, sharedResourceOwner, SHARED_OWNER, } from "../resources/store.js";
4
+ import { resourcePut, resourcePutIfAbsent, resourceGetByPath, resourceList, resourceDelete, organizationIdFromResourceOwner, sharedResourceOwner, SHARED_OWNER, } from "../resources/store.js";
5
5
  import { getRequestUserEmail, getRequestOrgId, getIntegrationRequestContext, } from "../server/request-context.js";
6
6
  import { isReasoningEffort, REASONING_EFFORTS, } from "../shared/reasoning-effort.js";
7
7
  import { RESUME_AUTOMATION_PATCH } from "./automation-outcome.js";
@@ -150,7 +150,20 @@ async function runCreate(args, appId) {
150
150
  ...(mcpTools?.length ? { mcpTools } : {}),
151
151
  };
152
152
  const content = buildJobContent(meta, instructions);
153
- await resourcePut(owner, path, content);
153
+ const created = await resourcePutIfAbsent(owner, path, content);
154
+ if (!created) {
155
+ const existing = await resourceGetByPath(owner, path);
156
+ if (!existing) {
157
+ return JSON.stringify({
158
+ error: `Job "${name}" was not created: the write was not applied.`,
159
+ });
160
+ }
161
+ return JSON.stringify({
162
+ error: classifyJobResource(existing.content).kind === "automation"
163
+ ? `"${name}" already exists and is an automation. Use manage-automations to change it.`
164
+ : `Job "${name}" already exists. Use manage-jobs with action 'update' to change it, or pick a different name.`,
165
+ });
166
+ }
154
167
  return JSON.stringify({
155
168
  created: true,
156
169
  name,
@@ -386,7 +399,7 @@ export function createJobTools(appId) {
386
399
  description: `Manage recurring jobs that run on a cron schedule.
387
400
 
388
401
  Actions:
389
- - "create": Create a new recurring job. Requires name and instructions; an omitted schedule defaults to once per hour.
402
+ - "create": Create a new recurring job. Requires name and instructions; an omitted schedule defaults to once per hour. Fails if a job with that name already exists; use "update" to change an existing job.
390
403
  - "list": List all recurring jobs and their status (schedule, enabled, last run, next run).
391
404
  - "update": Update a job's schedule, instructions, or enabled state. Requires name.
392
405
  - "delete": Delete a recurring job. Requires name. Always confirm with the user first.
@@ -0,0 +1,11 @@
1
+ import { type BuiltinLocaleCode } from "./shared.js";
2
+ interface DefaultModelMessages {
3
+ configurationOverride: string;
4
+ configurationUnavailable: string;
5
+ organizationSelected: string;
6
+ userSelected: string;
7
+ appOverridePreserved: string;
8
+ }
9
+ export declare const DEFAULT_MODEL_MESSAGES: Record<BuiltinLocaleCode, DefaultModelMessages>;
10
+ export declare function defaultModelMessagesForUser(userEmail?: string | null): Promise<DefaultModelMessages>;
11
+ export {};
@@ -0,0 +1,88 @@
1
+ import { getUserSetting } from "../settings/user-settings.js";
2
+ import { DEFAULT_LOCALE, LOCALIZATION_SETTING_KEY, normalizeLocalizationPreference, } from "./shared.js";
3
+ export const DEFAULT_MODEL_MESSAGES = {
4
+ "en-US": {
5
+ configurationOverride: "App configuration currently uses {{model}} via {{engine}}.",
6
+ configurationUnavailable: "App configuration currently has no usable model; it remains unchanged.",
7
+ organizationSelected: "Organization default set to {{model}} via {{engine}}. All app overrides and explicit chat and automation models are unchanged.",
8
+ userSelected: "Personal default set to {{model}} via {{engine}}. All app overrides and explicit chat and automation models are unchanged.",
9
+ appOverridePreserved: "{{appId}} currently uses {{model}} via {{engine}}. Its app override is preserved.",
10
+ },
11
+ "es-ES": {
12
+ configurationOverride: "La configuración de la aplicación usa actualmente {{model}} mediante {{engine}}.",
13
+ configurationUnavailable: "La configuración de la aplicación no tiene un modelo utilizable actualmente; no cambia.",
14
+ organizationSelected: "Modelo predeterminado de la organización establecido en {{model}} mediante {{engine}}. Todos los valores propios de las aplicaciones y los modelos explícitos de chats y automatizaciones no cambian.",
15
+ userSelected: "Modelo predeterminado personal establecido en {{model}} mediante {{engine}}. Todos los valores propios de las aplicaciones y los modelos explícitos de chats y automatizaciones no cambian.",
16
+ appOverridePreserved: "{{appId}} usa actualmente {{model}} mediante {{engine}}. Se conserva su valor propio de aplicación.",
17
+ },
18
+ "fr-FR": {
19
+ configurationOverride: "La configuration de l’application utilise actuellement {{model}} via {{engine}}.",
20
+ configurationUnavailable: "La configuration de l’application ne dispose actuellement d’aucun modèle utilisable ; elle reste inchangée.",
21
+ organizationSelected: "Modèle par défaut de l’organisation défini sur {{model}} via {{engine}}. Tous les réglages propres aux applications et les modèles explicites des conversations et automatisations restent inchangés.",
22
+ userSelected: "Modèle par défaut personnel défini sur {{model}} via {{engine}}. Tous les réglages propres aux applications et les modèles explicites des conversations et automatisations restent inchangés.",
23
+ appOverridePreserved: "{{appId}} utilise actuellement {{model}} via {{engine}}. Son réglage propre est conservé.",
24
+ },
25
+ "de-DE": {
26
+ configurationOverride: "Die App-Konfiguration verwendet derzeit {{model}} über {{engine}}.",
27
+ configurationUnavailable: "Die App-Konfiguration hat derzeit kein verwendbares Modell; sie bleibt unverändert.",
28
+ organizationSelected: "Organisationsstandard auf {{model}} über {{engine}} gesetzt. Alle App-Einstellungen und expliziten Chat- und Automationsmodelle bleiben unverändert.",
29
+ userSelected: "Persönlicher Standard auf {{model}} über {{engine}} gesetzt. Alle App-Einstellungen und expliziten Chat- und Automationsmodelle bleiben unverändert.",
30
+ appOverridePreserved: "{{appId}} verwendet derzeit {{model}} über {{engine}}. Die eigene App-Einstellung bleibt erhalten.",
31
+ },
32
+ "pt-BR": {
33
+ configurationOverride: "A configuração do aplicativo usa atualmente {{model}} via {{engine}}.",
34
+ configurationUnavailable: "A configuração do aplicativo não tem um modelo utilizável no momento; ela permanece inalterada.",
35
+ organizationSelected: "Modelo padrão da organização definido como {{model}} via {{engine}}. Todos os padrões específicos de aplicativos e modelos explícitos de chats e automações permanecem inalterados.",
36
+ userSelected: "Modelo padrão pessoal definido como {{model}} via {{engine}}. Todos os padrões específicos de aplicativos e modelos explícitos de chats e automações permanecem inalterados.",
37
+ appOverridePreserved: "{{appId}} usa atualmente {{model}} via {{engine}}. Seu padrão específico é preservado.",
38
+ },
39
+ "zh-CN": {
40
+ configurationOverride: "应用配置当前通过 {{engine}} 使用 {{model}}。",
41
+ configurationUnavailable: "应用配置当前没有可用模型;其设置保持不变。",
42
+ organizationSelected: "组织默认模型已通过 {{engine}} 设置为 {{model}}。所有应用的独立设置以及聊天和自动化中明确指定的模型保持不变。",
43
+ userSelected: "个人默认模型已通过 {{engine}} 设置为 {{model}}。所有应用的独立设置以及聊天和自动化中明确指定的模型保持不变。",
44
+ appOverridePreserved: "{{appId}} 当前通过 {{engine}} 使用 {{model}}。其应用独立设置已保留。",
45
+ },
46
+ "zh-TW": {
47
+ configurationOverride: "應用程式設定目前透過 {{engine}} 使用 {{model}}。",
48
+ configurationUnavailable: "應用程式設定目前沒有可用模型;其設定保持不變。",
49
+ organizationSelected: "組織預設模型已透過 {{engine}} 設為 {{model}}。所有應用程式的獨立設定以及聊天和自動化中明確指定的模型保持不變。",
50
+ userSelected: "個人預設模型已透過 {{engine}} 設為 {{model}}。所有應用程式的獨立設定以及聊天和自動化中明確指定的模型保持不變。",
51
+ appOverridePreserved: "{{appId}} 目前透過 {{engine}} 使用 {{model}}。其應用程式獨立設定已保留。",
52
+ },
53
+ "ja-JP": {
54
+ configurationOverride: "アプリの設定は現在 {{engine}} 経由で {{model}} を使用しています。",
55
+ configurationUnavailable: "アプリの設定には現在利用可能なモデルがありません。設定は変更されません。",
56
+ organizationSelected: "組織の既定モデルを {{engine}} 経由で {{model}} に設定しました。すべてのアプリ固有設定と、チャットや自動化で明示的に指定したモデルは変更されません。",
57
+ userSelected: "個人の既定モデルを {{engine}} 経由で {{model}} に設定しました。すべてのアプリ固有設定と、チャットや自動化で明示的に指定したモデルは変更されません。",
58
+ appOverridePreserved: "{{appId}} は現在 {{engine}} 経由で {{model}} を使用しています。アプリ固有設定は保持されます。",
59
+ },
60
+ "ko-KR": {
61
+ configurationOverride: "앱 설정은 현재 {{engine}}을 통해 {{model}}을 사용합니다.",
62
+ configurationUnavailable: "앱 설정에는 현재 사용 가능한 모델이 없습니다. 설정은 변경되지 않습니다.",
63
+ organizationSelected: "{{engine}}을 통해 조직 기본 모델을 {{model}}로 설정했습니다. 모든 앱별 설정과 채팅 및 자동화에서 명시적으로 지정한 모델은 변경되지 않습니다.",
64
+ userSelected: "{{engine}}을 통해 개인 기본 모델을 {{model}}로 설정했습니다. 모든 앱별 설정과 채팅 및 자동화에서 명시적으로 지정한 모델은 변경되지 않습니다.",
65
+ appOverridePreserved: "{{appId}}은(는) 현재 {{engine}}을 통해 {{model}}을 사용합니다. 앱별 설정은 유지됩니다.",
66
+ },
67
+ "hi-IN": {
68
+ configurationOverride: "ऐप का कॉन्फ़िगरेशन अभी {{engine}} के माध्यम से {{model}} इस्तेमाल करता है।",
69
+ configurationUnavailable: "ऐप के कॉन्फ़िगरेशन में अभी कोई उपयोग योग्य मॉडल नहीं है; वह नहीं बदला है।",
70
+ organizationSelected: "{{engine}} के माध्यम से संगठन का डिफ़ॉल्ट मॉडल {{model}} सेट किया गया। सभी ऐप के अपने सेटिंग और चैट तथा ऑटोमेशन के स्पष्ट मॉडल नहीं बदले हैं।",
71
+ userSelected: "{{engine}} के माध्यम से व्यक्तिगत डिफ़ॉल्ट मॉडल {{model}} सेट किया गया। सभी ऐप के अपने सेटिंग और चैट तथा ऑटोमेशन के स्पष्ट मॉडल नहीं बदले हैं।",
72
+ appOverridePreserved: "{{appId}} अभी {{engine}} के माध्यम से {{model}} इस्तेमाल करता है। उसकी अपनी ऐप सेटिंग सुरक्षित है।",
73
+ },
74
+ "ar-SA": {
75
+ configurationOverride: "تستخدم إعدادات التطبيق حاليًا {{model}} عبر {{engine}}.",
76
+ configurationUnavailable: "لا تحتوي إعدادات التطبيق حاليًا على نموذج قابل للاستخدام؛ وهي لم تتغير.",
77
+ organizationSelected: "تم تعيين النموذج الافتراضي للمؤسسة إلى {{model}} عبر {{engine}}. لم تتغير أي إعدادات خاصة بالتطبيقات ولا النماذج المحددة صراحةً للمحادثات والأتمتة.",
78
+ userSelected: "تم تعيين النموذج الافتراضي الشخصي إلى {{model}} عبر {{engine}}. لم تتغير أي إعدادات خاصة بالتطبيقات ولا النماذج المحددة صراحةً للمحادثات والأتمتة.",
79
+ appOverridePreserved: "يستخدم {{appId}} حاليًا {{model}} عبر {{engine}}. تم الحفاظ على إعداده الخاص بالتطبيق.",
80
+ },
81
+ };
82
+ export async function defaultModelMessagesForUser(userEmail) {
83
+ const preference = userEmail
84
+ ? normalizeLocalizationPreference(await getUserSetting(userEmail, LOCALIZATION_SETTING_KEY))
85
+ : { locale: DEFAULT_LOCALE };
86
+ return (DEFAULT_MODEL_MESSAGES[preference.locale] ??
87
+ DEFAULT_MODEL_MESSAGES[DEFAULT_LOCALE]);
88
+ }
@@ -16,6 +16,6 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
16
16
  } | {
17
17
  count?: undefined;
18
18
  updated?: undefined;
19
- ok: boolean;
20
19
  error?: undefined;
20
+ ok: boolean;
21
21
  }>>;
@@ -35,14 +35,14 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
35
35
  spans?: undefined;
36
36
  } | {
37
37
  id?: undefined;
38
- ok?: undefined;
39
38
  error?: undefined;
39
+ ok?: undefined;
40
40
  message?: undefined;
41
41
  summary: import("./types.js").TraceSummary;
42
42
  spans: import("./types.js").TraceSpan[];
43
43
  } | {
44
- ok?: undefined;
45
44
  error?: undefined;
45
+ ok?: undefined;
46
46
  message?: undefined;
47
47
  summary?: undefined;
48
48
  spans?: undefined;
@@ -179,8 +179,8 @@ export declare const getMyOrgHandler: import("h3").EventHandlerWithFetch<import(
179
179
  export declare const createOrgHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
180
180
  name?: undefined;
181
181
  success: boolean;
182
- id?: undefined;
183
182
  role?: undefined;
183
+ id?: undefined;
184
184
  } | {
185
185
  success?: undefined;
186
186
  id: string;
@@ -2,6 +2,6 @@ export declare function createProgressHandler(): import("h3").EventHandlerWithFe
2
2
  error: string;
3
3
  ok?: undefined;
4
4
  } | {
5
- ok: boolean;
6
5
  error?: undefined;
6
+ ok: boolean;
7
7
  }>>;
@@ -94,39 +94,39 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
94
94
  label?: undefined;
95
95
  } | {
96
96
  id?: undefined;
97
- count?: undefined;
98
97
  message?: undefined;
99
98
  deleted?: undefined;
100
99
  providers?: undefined;
100
+ count?: undefined;
101
101
  found: boolean;
102
102
  provider: import("../custom-registry.js").CustomProviderConfig;
103
103
  registered?: undefined;
104
104
  label?: undefined;
105
105
  } | {
106
- count?: undefined;
107
106
  message?: undefined;
108
107
  deleted?: undefined;
109
108
  providers?: undefined;
109
+ count?: undefined;
110
110
  provider?: undefined;
111
111
  found: boolean;
112
112
  id: string;
113
113
  registered?: undefined;
114
114
  label?: undefined;
115
115
  } | {
116
- count?: undefined;
117
116
  message?: undefined;
118
117
  found?: undefined;
119
118
  providers?: undefined;
119
+ count?: undefined;
120
120
  provider?: undefined;
121
121
  deleted: boolean;
122
122
  id: string;
123
123
  registered?: undefined;
124
124
  label?: undefined;
125
125
  } | {
126
- count?: undefined;
127
126
  deleted?: undefined;
128
127
  found?: undefined;
129
128
  providers?: undefined;
129
+ count?: undefined;
130
130
  provider?: undefined;
131
131
  registered: boolean;
132
132
  id: string;