@agent-native/core 0.205.0 → 0.206.0-nightly-20261009011246

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 (115) hide show
  1. package/dist/a2a/client.d.ts +2 -2
  2. package/dist/agent/engine/anthropic-engine.d.ts +1 -1
  3. package/dist/agent/engine/builder-engine.d.ts +1 -1
  4. package/dist/agent/engine/builder-engine.js +23 -8
  5. package/dist/agent/engine/error-telemetry.d.ts +5 -0
  6. package/dist/agent/engine/error-telemetry.js +41 -0
  7. package/dist/agent/engine/registry.d.ts +1 -6
  8. package/dist/agent/engine/registry.js +2 -31
  9. package/dist/agent/model-config.d.ts +26 -14
  10. package/dist/agent/model-config.js +131 -8
  11. package/dist/agent/model-version.d.ts +19 -0
  12. package/dist/agent/model-version.js +153 -0
  13. package/dist/agent/production-agent.d.ts +1 -0
  14. package/dist/agent/production-agent.js +24 -6
  15. package/dist/agent/provider-model-selection.js +6 -4
  16. package/dist/agent/run-manager.js +5 -11
  17. package/dist/agent/thread-data-builder.js +14 -6
  18. package/dist/authorization/check-action.js +8 -4
  19. package/dist/chat-threads/store.js +22 -9
  20. package/dist/client/analytics.d.ts +1 -0
  21. package/dist/client/analytics.js +10 -2
  22. package/dist/client/chat/runtime.js +18 -0
  23. package/dist/client/chat-model-groups.d.ts +3 -0
  24. package/dist/client/error-format.js +10 -7
  25. package/dist/client/onboarding/use-onboarding.d.ts +12 -0
  26. package/dist/client/onboarding/use-onboarding.js +491 -4
  27. package/dist/client/session-replay-privacy.d.ts +8 -0
  28. package/dist/client/session-replay-privacy.js +8 -0
  29. package/dist/client/session-replay.d.ts +1 -0
  30. package/dist/client/session-replay.js +18 -9
  31. package/dist/client/sse-event-processor.js +10 -6
  32. package/dist/client/use-chat-models.d.ts +5 -0
  33. package/dist/client/use-chat-models.js +51 -5
  34. package/dist/client/use-session.d.ts +8 -1
  35. package/dist/client/use-session.js +20 -1
  36. package/dist/collab/struct-routes.d.ts +1 -1
  37. package/dist/deploy/build.js +353 -3
  38. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  39. package/dist/jobs/backfill-run-history-ownership.d.ts +12 -0
  40. package/dist/jobs/backfill-run-history-ownership.js +87 -0
  41. package/dist/jobs/background-automation-runner.js +3 -9
  42. package/dist/jobs/remote-execution.js +3 -9
  43. package/dist/jobs/run-history-ownership.d.ts +5 -0
  44. package/dist/jobs/run-history-ownership.js +16 -0
  45. package/dist/jobs/run-now.js +2 -3
  46. package/dist/localization/agent-resources-messages.d.ts +3 -0
  47. package/dist/localization/agent-resources-messages.js +33 -0
  48. package/dist/mcp/actions/create-org-service-token.js +5 -7
  49. package/dist/mcp/build-server.d.ts +23 -18
  50. package/dist/mcp/build-server.js +220 -212
  51. package/dist/mcp/connect-route.d.ts +11 -2
  52. package/dist/mcp/connect-route.js +34 -24
  53. package/dist/mcp/connect-store.d.ts +9 -13
  54. package/dist/mcp/connect-store.js +11 -24
  55. package/dist/mcp/credential-membership.js +17 -6
  56. package/dist/mcp/oauth-route.d.ts +11 -1
  57. package/dist/mcp/oauth-route.js +28 -6
  58. package/dist/mcp/oauth-token.d.ts +12 -2
  59. package/dist/mcp/oauth-token.js +15 -4
  60. package/dist/mcp/server.js +9 -5
  61. package/dist/notifications/routes.d.ts +2 -2
  62. package/dist/observability/posthog-ai.d.ts +1 -0
  63. package/dist/observability/posthog-ai.js +20 -8
  64. package/dist/observability/routes.d.ts +6 -6
  65. package/dist/observability/traces.js +61 -39
  66. package/dist/org/app-roles.d.ts +8 -1
  67. package/dist/org/app-roles.js +29 -9
  68. package/dist/org/context.js +24 -8
  69. package/dist/org/index.d.ts +2 -2
  70. package/dist/org/workspace-app-identity.d.ts +1 -0
  71. package/dist/org/workspace-app-identity.js +25 -0
  72. package/dist/progress/routes.d.ts +1 -1
  73. package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
  74. package/dist/provider-api/actions/provider-api.d.ts +3 -3
  75. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  76. package/dist/scripts/agent-engines/list-agent-engines.js +1 -0
  77. package/dist/server/action-routes.js +8 -1
  78. package/dist/server/agent-chat-plugin.js +1 -0
  79. package/dist/server/agent-engine-default-model-route.d.ts +1 -1
  80. package/dist/server/auth.js +33 -17
  81. package/dist/server/bearer-credential-refusal.d.ts +23 -0
  82. package/dist/server/bearer-credential-refusal.js +67 -0
  83. package/dist/server/better-auth-instance.js +13 -6
  84. package/dist/server/builder-browser.d.ts +2 -0
  85. package/dist/server/builder-browser.js +16 -3
  86. package/dist/server/capture-error.d.ts +1 -0
  87. package/dist/server/capture-error.js +28 -4
  88. package/dist/server/complete-text.js +16 -3
  89. package/dist/server/core-routes-plugin.js +2 -0
  90. package/dist/server/dev-action-bridge.js +7 -1
  91. package/dist/server/google-oauth.js +6 -3
  92. package/dist/server/index.d.ts +1 -1
  93. package/dist/server/index.js +1 -1
  94. package/dist/server/realtime-token.d.ts +1 -1
  95. package/dist/server/recap-image-route.js +4 -0
  96. package/dist/server/request-context.d.ts +16 -0
  97. package/dist/server/request-context.js +17 -0
  98. package/dist/shared/agent-chat-context.d.ts +1 -0
  99. package/dist/shared/agent-chat-context.js +26 -0
  100. package/dist/shared/index.d.ts +1 -1
  101. package/dist/shared/index.js +1 -1
  102. package/dist/shared/reasoning-effort.js +10 -1
  103. package/dist/shared/ssr-session-bootstrap.d.ts +7 -0
  104. package/dist/shared/ssr-session-bootstrap.js +21 -0
  105. package/dist/sharing/access.js +86 -5
  106. package/dist/templates/builder-code-starter/server/routes/index.get.ts +2 -0
  107. package/dist/triggers/routes.js +2 -1
  108. package/docs/content/automation-connectors.mdx +5 -3
  109. package/docs/content/automations.mdx +78 -49
  110. package/docs/content/observability.mdx +16 -5
  111. package/docs/content/organizations-teams-permissions.mdx +44 -2
  112. package/docs/content/recurring-jobs.mdx +4 -8
  113. package/docs/content/template-forms.mdx +6 -0
  114. package/package.json +5 -4
  115. package/src/templates/builder-code-starter/server/routes/index.get.ts +2 -0
@@ -1,3 +1,22 @@
1
+ export interface NormalizeModelOptions {
2
+ preserveCustomModels?: boolean;
3
+ acceptsCustomModels?: boolean;
4
+ }
5
+ export interface ModelEngineConfig {
6
+ name: string;
7
+ label?: string;
8
+ defaultModel: string;
9
+ supportedModels: readonly string[];
10
+ /** Models currently offered in the picker, which may be a user-selected subset. */
11
+ selectableModels?: readonly string[];
12
+ acceptsCustomModels?: boolean;
13
+ preserveCustomModels?: boolean;
14
+ }
1
15
  export declare function findLatestSupportedVersionMatch(candidate: string, supportedModels: readonly string[]): string | undefined;
16
+ export declare function upgradeBuilderModelAlias(candidate: string, supportedModels: readonly string[]): string | undefined;
2
17
  export declare function isNewerVersionedModel(candidate: string, newerModel: string): boolean;
3
18
  export declare function upgradeModelToLatestSupportedVersion(candidate: string, supportedModels: readonly string[]): string | undefined;
19
+ export declare function upgradeModelForProvider(candidate: string, supportedModels: readonly string[], provider: string): string | undefined;
20
+ export declare function normalizeModelForEngine(engine: ModelEngineConfig, model: string | null | undefined, options?: NormalizeModelOptions): string;
21
+ export declare function getModelOptionLabel(model: string, engine?: ModelEngineConfig, builderFallbackLabel?: string): string;
22
+ export declare function getBuilderModelOptionLabel(model: string, builderFallbackLabel?: string): string;
@@ -1,4 +1,33 @@
1
+ import { BUILDER_CLAUDE_SONNET_MODEL_ID, BUILDER_MODEL_ALIASES, BUILDER_MODEL_CONFIG, CLAUDE_SONNET_MODEL_ID, getClaudeModelOptionLabel, } from "./model-config.js";
1
2
  const UPGRADEABLE_GPT_TIERS = new Set(["-sol", "-terra", "-luna"]);
3
+ const OPENROUTER_MODEL_ALIASES = {
4
+ "x-ai/grok-code-fast-1": "x-ai/grok-build-0.1",
5
+ };
6
+ const MODEL_DISPLAY_NAMES = {
7
+ "anthropic/claude-haiku-5.5": "Claude Haiku 5.5",
8
+ "anthropic/claude-opus-4.8": "Claude Opus 4.8",
9
+ "anthropic/claude-opus-5.5": "Claude Opus 5.5",
10
+ "anthropic/claude-sonnet-5.5": "Claude Sonnet 5.5",
11
+ "deepseek/deepseek-chat-v3.1": "DeepSeek v3.1",
12
+ "deepseek/deepseek-v4-pro": "DeepSeek V4 Pro",
13
+ "deepseek/deepseek-v4.1-flash": "DeepSeek V4.1 Flash",
14
+ "gemini-3.1-pro-preview": "Gemini 3.1 Pro Preview",
15
+ "google/gemini-3.1-flash-lite": "Gemini 3.1 Flash-Lite",
16
+ "google/gemini-3.1-pro-preview": "Gemini 3.1 Pro",
17
+ "google/gemini-3.5-flash-lite": "Gemini 3.5 Flash-Lite",
18
+ "google/gemini-3.8-flash": "Gemini 3.8 Flash",
19
+ "inception/mercury-2.5": "Mercury 2.5",
20
+ "meta/muse-spark-1.3": "Muse Spark 1.3",
21
+ "moonshotai/kimi-k2.5": "Kimi K2.5",
22
+ "qwen/qwen3-coder": "Qwen3 Coder",
23
+ "qwen/qwen3.8-max-0902": "Qwen 3.8 Max",
24
+ "x-ai/grok-4.7": "Grok 4.7",
25
+ "x-ai/grok-build-0.1": "Grok Build 0.1",
26
+ "z-ai/glm-4.5": "GLM 4.5",
27
+ "z-ai/glm-5.1": "GLM 5.1",
28
+ "z-ai/glm-5.2": "GLM 5.2",
29
+ "z-ai/glm-5.3-flash": "GLM 5.3 Flash",
30
+ };
2
31
  function parseVersionedModelId(model) {
3
32
  const match = /^(?<family>.+?)[-.](?<version>\d+(?:[-.]\d+)*)(?<suffix>(?:[-.][a-z][a-z0-9]*)*)$/i.exec(model.trim().toLowerCase());
4
33
  const groups = match?.groups;
@@ -43,6 +72,22 @@ export function findLatestSupportedVersionMatch(candidate, supportedModels) {
43
72
  }
44
73
  return best?.model;
45
74
  }
75
+ export function upgradeBuilderModelAlias(candidate, supportedModels) {
76
+ const latest = BUILDER_MODEL_ALIASES[candidate];
77
+ return latest && supportedModels.includes(latest) ? latest : undefined;
78
+ }
79
+ function upgradeOpenRouterModelAlias(candidate, supportedModels, provider) {
80
+ if (provider !== "ai-sdk:openrouter")
81
+ return undefined;
82
+ const latest = OPENROUTER_MODEL_ALIASES[candidate];
83
+ return latest && supportedModels.includes(latest) ? latest : undefined;
84
+ }
85
+ function upgradeProviderModelAlias(candidate, supportedModels, provider) {
86
+ return ((provider === "builder"
87
+ ? upgradeBuilderModelAlias(candidate, supportedModels)
88
+ : undefined) ??
89
+ upgradeOpenRouterModelAlias(candidate, supportedModels, provider));
90
+ }
46
91
  export function isNewerVersionedModel(candidate, newerModel) {
47
92
  const current = parseVersionedModelId(candidate);
48
93
  const newer = parseVersionedModelId(newerModel);
@@ -65,3 +110,111 @@ export function upgradeModelToLatestSupportedVersion(candidate, supportedModels)
65
110
  ? latest
66
111
  : undefined;
67
112
  }
113
+ export function upgradeModelForProvider(candidate, supportedModels, provider) {
114
+ return (upgradeProviderModelAlias(candidate, supportedModels, provider) ??
115
+ upgradeModelToLatestSupportedVersion(candidate, supportedModels));
116
+ }
117
+ export function normalizeModelForEngine(engine, model, options = {}) {
118
+ const candidate = typeof model === "string" ? model.trim() : "";
119
+ if (!candidate)
120
+ return engine.defaultModel;
121
+ const providerAlias = upgradeProviderModelAlias(candidate, engine.supportedModels, engine.name);
122
+ if (providerAlias)
123
+ return providerAlias;
124
+ if (engine.preserveCustomModels || options.preserveCustomModels) {
125
+ return candidate;
126
+ }
127
+ const upgradedModel = upgradeModelForProvider(candidate, engine.supportedModels, engine.name);
128
+ if (upgradedModel)
129
+ return upgradedModel;
130
+ if (candidate === "auto" ||
131
+ engine.supportedModels.includes(candidate) ||
132
+ engine.supportedModels.length === 0) {
133
+ return candidate;
134
+ }
135
+ if (engine.acceptsCustomModels || options.acceptsCustomModels) {
136
+ return candidate === BUILDER_CLAUDE_SONNET_MODEL_ID &&
137
+ engine.supportedModels.includes(CLAUDE_SONNET_MODEL_ID)
138
+ ? CLAUDE_SONNET_MODEL_ID
139
+ : candidate;
140
+ }
141
+ const versionMatch = findLatestSupportedVersionMatch(candidate, engine.supportedModels);
142
+ if (versionMatch && isNewerVersionedModel(candidate, versionMatch)) {
143
+ return versionMatch;
144
+ }
145
+ if (versionMatch)
146
+ return versionMatch;
147
+ return engine.defaultModel;
148
+ }
149
+ function displayModelName(model) {
150
+ const knownLabel = Object.hasOwn(MODEL_DISPLAY_NAMES, model)
151
+ ? MODEL_DISPLAY_NAMES[model]
152
+ : undefined;
153
+ if (knownLabel !== undefined)
154
+ return knownLabel;
155
+ const normalizedModel = model.replace(/^(?:anthropic|openai|google)\//, "");
156
+ const claudeLabel = getClaudeModelOptionLabel(normalizedModel);
157
+ if (claudeLabel !== normalizedModel)
158
+ return claudeLabel;
159
+ const gpt = /^gpt-(\d+)(?:[.-](\d+))?(?:-(.+))?$/.exec(normalizedModel);
160
+ if (gpt) {
161
+ const version = gpt[2] ? `${gpt[1]}.${gpt[2]}` : gpt[1];
162
+ const tierParts = gpt[3]?.split("-");
163
+ if (tierParts?.some((part) => !part))
164
+ return normalizedModel;
165
+ const tier = tierParts?.length
166
+ ? ` ${tierParts
167
+ .map((part) => part[0].toUpperCase() + part.slice(1))
168
+ .join(" ")}`
169
+ : "";
170
+ return `GPT-${version}${tier}`;
171
+ }
172
+ if (normalizedModel.startsWith("gemini-")) {
173
+ return `Gemini ${normalizedModel
174
+ .slice("gemini-".length)
175
+ .replace(/-/g, " ")
176
+ .replace(/\bflash\b/gi, "Flash")
177
+ .replace(/\bpro\b/gi, "Pro")
178
+ .replace(/\blite\b/gi, "Lite")}`;
179
+ }
180
+ if (normalizedModel.startsWith("grok-")) {
181
+ return `Grok ${normalizedModel.slice("grok-".length).replace(/-/g, " ")}`;
182
+ }
183
+ if (normalizedModel.startsWith("deepseek-")) {
184
+ return `DeepSeek ${normalizedModel
185
+ .slice("deepseek-".length)
186
+ .replace(/^v(\d)/i, "V$1")
187
+ .replace(/-/g, " ")}`;
188
+ }
189
+ if (normalizedModel.startsWith("qwen")) {
190
+ return normalizedModel.replace(/-/g, " ").replace(/^qwen/i, "Qwen");
191
+ }
192
+ if (normalizedModel.startsWith("glm-")) {
193
+ return `GLM ${normalizedModel.slice("glm-".length).replace(/-/g, " ")}`;
194
+ }
195
+ if (normalizedModel.startsWith("kimi-")) {
196
+ return `Kimi ${normalizedModel.slice("kimi-".length).replace(/-/g, " ")}`;
197
+ }
198
+ return normalizedModel;
199
+ }
200
+ export function getModelOptionLabel(model, engine, builderFallbackLabel) {
201
+ if (!engine)
202
+ return displayModelName(model);
203
+ const effectiveModel = normalizeModelForEngine(engine, model);
204
+ const effectiveLabel = displayModelName(effectiveModel);
205
+ if (effectiveModel === model)
206
+ return effectiveLabel;
207
+ const engineLabel = engine.name === "builder"
208
+ ? builderFallbackLabel
209
+ : (engine.label ?? engine.name);
210
+ return engineLabel
211
+ ? `${displayModelName(model)} → ${effectiveLabel} · ${engineLabel}`
212
+ : `${displayModelName(model)} → ${effectiveLabel}`;
213
+ }
214
+ export function getBuilderModelOptionLabel(model, builderFallbackLabel) {
215
+ return getModelOptionLabel(model, {
216
+ name: "builder",
217
+ label: "Builder",
218
+ ...BUILDER_MODEL_CONFIG,
219
+ }, builderFallbackLabel);
220
+ }
@@ -661,6 +661,7 @@ export declare function isRecoverableContinuationError(event: {
661
661
  error: string;
662
662
  errorCode?: string;
663
663
  recoverable?: boolean;
664
+ providerRetryable?: boolean;
664
665
  }): boolean;
665
666
  export declare function lastUnfinishedPreparingActionToolFromEvents(events: readonly AgentChatEvent[]): string | undefined;
666
667
  export declare function backgroundContinuationReasonForRun(run: ActiveRun): AgentLoopContinuationReason;
@@ -1160,8 +1160,9 @@ export function isRetryableError(err) {
1160
1160
  msg.includes("daily gateway request cap"))
1161
1161
  return false;
1162
1162
  if (engineErr) {
1163
- if (engineErr.providerRetryable === true)
1164
- return true;
1163
+ if (engineErr.providerRetryable !== undefined) {
1164
+ return engineErr.providerRetryable;
1165
+ }
1165
1166
  const sc = engineErr.statusCode;
1166
1167
  if (sc === 429 || sc === 500 || sc === 502 || sc === 503 || sc === 529)
1167
1168
  return true;
@@ -1943,6 +1944,11 @@ export function isResumableEngineError(err) {
1943
1944
  if (!(err instanceof Error))
1944
1945
  return false;
1945
1946
  const code = err instanceof EngineError ? (err.errorCode ?? "").toLowerCase() : "";
1947
+ if ((err instanceof EngineError && err.providerRetryable === false) ||
1948
+ code === "invalid_request" ||
1949
+ code === "invalid_request_error") {
1950
+ return false;
1951
+ }
1946
1952
  if (code === "builder_gateway_timeout" ||
1947
1953
  code === "builder_gateway_network_error" ||
1948
1954
  code === "builder_gateway_stream_ended" ||
@@ -1952,6 +1958,9 @@ export function isResumableEngineError(err) {
1952
1958
  if (code === "http_502" ||
1953
1959
  code === "http_503" ||
1954
1960
  code === "http_504" ||
1961
+ (code === "overloaded_error" &&
1962
+ err instanceof EngineError &&
1963
+ err.providerRetryable === true) ||
1955
1964
  code === "timeout") {
1956
1965
  return true;
1957
1966
  }
@@ -1989,6 +1998,8 @@ export function isTransientProviderRateLimitError(err) {
1989
1998
  return true;
1990
1999
  if (code === PROVIDER_TRANSIENT_REJECTION_ERROR_CODE)
1991
2000
  return true;
2001
+ if (code === "overloaded_error" && err.providerRetryable === true)
2002
+ return true;
1992
2003
  if (code === "rate_limited" && err.providerRetryable === true)
1993
2004
  return true;
1994
2005
  return false;
@@ -2011,6 +2022,9 @@ export function continuationReasonForResumableError(err) {
2011
2022
  code === "http_529" ||
2012
2023
  code === "rate_limited" ||
2013
2024
  code === PROVIDER_TRANSIENT_REJECTION_ERROR_CODE ||
2025
+ (code === "overloaded_error" &&
2026
+ err instanceof EngineError &&
2027
+ err.providerRetryable === true) ||
2014
2028
  (err instanceof EngineError &&
2015
2029
  (err.statusCode === 429 ||
2016
2030
  err.statusCode === 529 ||
@@ -3438,7 +3452,7 @@ export async function runAgentLoop(opts) {
3438
3452
  };
3439
3453
  if (followUpRunId)
3440
3454
  send({ type: "suggestions", suggestions: [] });
3441
- let model = opts.model;
3455
+ let model = normalizeModelForEngine(engine, opts.model);
3442
3456
  let outcomeReported = false;
3443
3457
  const reportOutcome = (outcome) => {
3444
3458
  if (outcomeReported)
@@ -5767,10 +5781,13 @@ function backgroundChatProgressRunId(turnId) {
5767
5781
  export function isRecoverableContinuationError(event) {
5768
5782
  const code = String(event.errorCode ?? "").toLowerCase();
5769
5783
  const message = event.error.toLowerCase();
5770
- if (code === "builder_gateway_error")
5771
- return false;
5772
- if (event.recoverable === false)
5784
+ if (event.providerRetryable === false ||
5785
+ event.recoverable === false ||
5786
+ code === "builder_gateway_error" ||
5787
+ code === "invalid_request" ||
5788
+ code === "invalid_request_error") {
5773
5789
  return false;
5790
+ }
5774
5791
  return (event.recoverable === true ||
5775
5792
  code === "builder_gateway_timeout" ||
5776
5793
  code === "builder_gateway_network_error" ||
@@ -5790,6 +5807,7 @@ export function isRecoverableContinuationError(event) {
5790
5807
  code === "http_504" ||
5791
5808
  code === "http_529" ||
5792
5809
  code === "run_timeout" ||
5810
+ (code === "overloaded_error" && event.providerRetryable === true) ||
5793
5811
  message.includes("timeout") ||
5794
5812
  isProviderConnectionErrorMessage(message) ||
5795
5813
  message.includes("temporarily unavailable"));
@@ -20,7 +20,7 @@ import { deleteOrgSetting, deleteUserSetting, getOrgSetting, getUserSetting, put
20
20
  import { isCustomOpenAiBaseUrl, OLLAMA_BASE_URL_ENV_VAR, OPENAI_BASE_URL_ENV_VAR, } from "./engine/openai-compatible-endpoint.js";
21
21
  import { PROVIDER_ENV_META } from "./engine/provider-env-vars.js";
22
22
  import { BUILDER_MODEL_CONFIG } from "./model-config.js";
23
- import { upgradeModelToLatestSupportedVersion } from "./model-version.js";
23
+ import { upgradeModelForProvider } from "./model-version.js";
24
24
  export const PROVIDER_MODEL_SELECTION_KEY_PREFIX = "agent-provider-models";
25
25
  /** Audit target type for selection changes and refused attempts. */
26
26
  export const PROVIDER_MODEL_SELECTION_AUDIT_TARGET_TYPE = "provider-models";
@@ -96,7 +96,7 @@ export function normalizeSelectedModels(provider, models, options = {}) {
96
96
  const normalized = [
97
97
  ...new Set([...seen].map((id) => options.preserveCustomModels
98
98
  ? id
99
- : (upgradeModelToLatestSupportedVersion(id, supportedModels) ?? id))),
99
+ : (upgradeModelForProvider(id, supportedModels, provider) ?? id))),
100
100
  ];
101
101
  if (provider === "builder") {
102
102
  const catalog = new Set(BUILDER_MODEL_CONFIG.supportedModels);
@@ -196,10 +196,12 @@ function parseRow(provider, scope, stored, preserveCustomModels = false) {
196
196
  return { provider, scope, models: null, ...customModelMetadata };
197
197
  }
198
198
  const models = stored.models.filter((model) => typeof model === "string" && !!model.trim());
199
+ const supportedModels = recommendedProviderModels(provider);
199
200
  const currentModels = [
200
201
  ...new Set(models.map((model) => preserveCustomModels
201
202
  ? model
202
- : (upgradeModelToLatestSupportedVersion(model, recommendedProviderModels(provider)) ?? model))),
203
+ : (upgradeModelForProvider(model, supportedModels, provider) ??
204
+ model))),
203
205
  ];
204
206
  return {
205
207
  provider,
@@ -398,7 +400,7 @@ export async function resolveUncheckedDefaultModelReplacement(engine) {
398
400
  return undefined;
399
401
  const currentDefault = selection.preserveCustomModels
400
402
  ? engine.defaultModel
401
- : (upgradeModelToLatestSupportedVersion(engine.defaultModel, recommendedProviderModels(provider)) ?? engine.defaultModel);
403
+ : (upgradeModelForProvider(engine.defaultModel, recommendedProviderModels(provider), provider) ?? engine.defaultModel);
402
404
  if (selection.models.includes(currentDefault))
403
405
  return undefined;
404
406
  return selection.models[0];
@@ -6,6 +6,7 @@ import { ServicePrincipalRefusedError } from "../org/service-principal-guard.js"
6
6
  import { captureError } from "../server/capture-error.js";
7
7
  import { isLlmCredentialError, LLM_MISSING_CREDENTIALS_ERROR_CODE, LLM_MISSING_CREDENTIALS_MESSAGE, } from "./engine/credential-errors.js";
8
8
  import { classifyTerminalErrorCode, describeErrorWithCauses, isProviderConnectionError, } from "./engine/error-detail.js";
9
+ import { runErrorTelemetryProperties } from "./engine/error-telemetry.js";
9
10
  import { getAgentEngineEntry } from "./engine/registry.js";
10
11
  import { EngineError } from "./engine/types.js";
11
12
  import { insertRun, insertRunEvent, updateRunStatusIfRunning, markRunAborted, getRunAbortState, getRunStatus, getRunEventsSince, getCurrentTurnRunEventsForThread, getRunById, getRunByThread, getRunTurnRef, markTurnAborted, cleanupOldRuns, updateRunHeartbeat, bumpRunProgress, setRunInFlightMarker, reapIfStale, reapUnclaimedBackgroundRun, shouldRedispatchUnclaimedBackgroundRun, reconcileTerminalRunFromEvents, ensureTerminalRunEvent, getLastTerminalRunEvent, resolveErroredRunTerminalEvent, setRunError, setRunTerminalReason, persistRunCheckpointEvent, recordRunDiagnostic, RUN_DIAG_STAGE, terminalEventForAbortReason, RUN_RECORD_MISSING_ERROR_EVENT, RUN_RECORD_MISSING_GRACE_MS, RUN_TERMINAL_LOOKUP_FAILED_ERROR_EVENT, UNKNOWN_RUN_STATUS_ERROR_EVENT, } from "./run-store.js";
@@ -319,7 +320,6 @@ function terminalReasonForRun(finalStatus, terminalEvent, abortReason, completio
319
320
  return "error:unknown";
320
321
  return "done";
321
322
  }
322
- const MAX_RUN_ERROR_DETAIL_LENGTH = 500;
323
323
  function emitRunBoundaryTrackingEvent(args) {
324
324
  const properties = {
325
325
  source: "agent_run_manager",
@@ -375,11 +375,7 @@ function emitRunTerminalTrackingEvent(args) {
375
375
  status: args.status,
376
376
  terminal_reason: args.terminalReason,
377
377
  error_code: args.errorCode,
378
- error_detail: args.errorDetail
379
- ? args.errorDetail.length > MAX_RUN_ERROR_DETAIL_LENGTH
380
- ? `${args.errorDetail.slice(0, MAX_RUN_ERROR_DETAIL_LENGTH)}…`
381
- : args.errorDetail
382
- : undefined,
378
+ ...(args.errorCode ? runErrorTelemetryProperties(args.errorCode) : {}),
383
379
  dispatch_mode: args.dispatchMode,
384
380
  abort_reason: args.abortReason,
385
381
  duration_ms: args.durationMs,
@@ -991,6 +987,7 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
991
987
  captureError(error, {
992
988
  route: "/_agent-native/agent-chat",
993
989
  aiTraceId: runId,
990
+ errorMessagePolicy: "omit",
994
991
  tags: {
995
992
  source: "agent-run-manager",
996
993
  phase,
@@ -1122,8 +1119,8 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
1122
1119
  ...(err instanceof EngineError && err.upgradeUrl
1123
1120
  ? { upgradeUrl: err.upgradeUrl }
1124
1121
  : {}),
1125
- ...(err instanceof EngineError && err.providerRetryable === true
1126
- ? { providerRetryable: true }
1122
+ ...(err instanceof EngineError && err.providerRetryable !== undefined
1123
+ ? { providerRetryable: err.providerRetryable }
1127
1124
  : {}),
1128
1125
  ...(err instanceof EngineError && err.contextOverflow === true
1129
1126
  ? { contextOverflow: true }
@@ -1135,7 +1132,6 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
1135
1132
  let terminalPersistenceError = null;
1136
1133
  let eventPersistenceError = null;
1137
1134
  let runTerminalErrorCode;
1138
- let runTerminalErrorDetail;
1139
1135
  let terminalPersistenceEstablished = false;
1140
1136
  try {
1141
1137
  await persistenceChain;
@@ -1335,7 +1331,6 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
1335
1331
  }
1336
1332
  errorCode ??= classifyTerminalErrorCode(errorDetail);
1337
1333
  runTerminalErrorCode = errorCode ?? "unknown";
1338
- runTerminalErrorDetail = errorDetail;
1339
1334
  await setRunError(runId, errorCode ?? "unknown", errorDetail);
1340
1335
  }
1341
1336
  if (terminalPersistenceError) {
@@ -1362,7 +1357,6 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
1362
1357
  status: persistedStatus,
1363
1358
  terminalReason,
1364
1359
  errorCode: runTerminalErrorCode,
1365
- errorDetail: runTerminalErrorDetail,
1366
1360
  dispatchMode: options?.dispatchMode,
1367
1361
  abortReason: run.abortReason,
1368
1362
  durationMs: Date.now() - run.startedAt,
@@ -1,6 +1,7 @@
1
1
  import { parseAgentSuggestion, } from "@agent-native/agentkit/protocol";
2
2
  import { formatChatErrorText, normalizeChatError, } from "../client/error-format.js";
3
3
  import { isCredentialGapCodeAgentEvent, normalizeCodeAgentTranscript, } from "../code-agents/transcript-normalizer.js";
4
+ import { stripAgentChatContextFromMessage } from "../shared/agent-chat-context.js";
4
5
  import { RUN_NOT_STARTED_METADATA_KEY, } from "../shared/agent-chat-run-not-started.js";
5
6
  import { BUILDER_GATEWAY_INTERNAL_ERROR_CODE } from "./engine/error-detail.js";
6
7
  import { stringifyToolUseInputForGateway } from "./engine/translate-anthropic.js";
@@ -13,10 +14,13 @@ const MAX_STORED_ATTACHMENT_CHARS = 60_000;
13
14
  function isInternalContinuationError(event) {
14
15
  const code = String(event.errorCode ?? "").toLowerCase();
15
16
  const msg = event.error.toLowerCase();
16
- if (code === "builder_gateway_error")
17
- return false;
18
- if (event.recoverable === false)
17
+ if (event.providerRetryable === false ||
18
+ event.recoverable === false ||
19
+ code === "builder_gateway_error" ||
20
+ code === "invalid_request" ||
21
+ code === "invalid_request_error") {
19
22
  return false;
23
+ }
20
24
  return (event.recoverable === true ||
21
25
  code === "builder_gateway_timeout" ||
22
26
  code === "builder_gateway_stream_ended" ||
@@ -3007,10 +3011,14 @@ export function extractThreadMeta(repo) {
3007
3011
  : typeof msg.content === "string"
3008
3012
  ? msg.content
3009
3013
  : "";
3010
- if (textParts.trim()) {
3014
+ const visiblePrompt = stripAgentChatContextFromMessage(textParts)
3015
+ .replace(/@\[([^\]|]+)\|[^\]]*\]/g, "@$1")
3016
+ .replace(/\s+/g, " ")
3017
+ .trim();
3018
+ if (visiblePrompt) {
3011
3019
  if (!title)
3012
- title = textParts.trim().slice(0, 80);
3013
- preview = textParts.trim().slice(0, 120);
3020
+ title = visiblePrompt.slice(0, 80);
3021
+ preview = visiblePrompt.slice(0, 120);
3014
3022
  }
3015
3023
  }
3016
3024
  return { title: titleOverride || title, preview };
@@ -1,6 +1,7 @@
1
1
  import { getDbExec } from "../db/client.js";
2
2
  import { getAppPermissionOverrides, getRegisteredAppRoles, resolveAppRole, } from "../org/app-roles.js";
3
3
  import { isWorkspaceAppAccessAllowed, WORKSPACE_APP_ACCESS_UNAVAILABLE, WORKSPACE_APP_ACCESS_UNAVAILABLE_MESSAGE, } from "../org/workspace-app-access.js";
4
+ import { resolveWorkspaceAccessAppId } from "../org/workspace-app-identity.js";
4
5
  import { ForbiddenError, resolveAccess } from "../sharing/access.js";
5
6
  import { ROLE_RANK } from "../sharing/schema.js";
6
7
  import { registerActionAccessChecker } from "./action-access-runtime.js";
@@ -63,10 +64,13 @@ export async function checkAction(config, args, ctx, target) {
63
64
  permission,
64
65
  };
65
66
  }
66
- const appAllowed = await isWorkspaceAppAccessAllowed(appId, {
67
- email: identity.userEmail,
68
- orgId: identity.orgId,
69
- });
67
+ const workspaceAppId = resolveWorkspaceAccessAppId(appId);
68
+ const appAllowed = workspaceAppId
69
+ ? await isWorkspaceAppAccessAllowed(workspaceAppId, {
70
+ email: identity.userEmail,
71
+ orgId: identity.orgId,
72
+ })
73
+ : true;
70
74
  if (appAllowed === WORKSPACE_APP_ACCESS_UNAVAILABLE) {
71
75
  throw Object.assign(new Error(WORKSPACE_APP_ACCESS_UNAVAILABLE_MESSAGE), {
72
76
  statusCode: 503,
@@ -1,5 +1,5 @@
1
1
  import crypto from "node:crypto";
2
- import { mergeThreadDataForClientSave, normalizeThreadRepository, normalizeThreadTitle, } from "../agent/thread-data-builder.js";
2
+ import { extractThreadMeta, mergeThreadDataForClientSave, normalizeThreadRepository, normalizeThreadTitle, } from "../agent/thread-data-builder.js";
3
3
  import { representedRootAssistantMessageIds, threadMessageRecord, } from "../agent/thread-message-projection.js";
4
4
  import { getDbExec } from "../db/client.js";
5
5
  import { createGetDb } from "../db/create-get-db.js";
@@ -1101,16 +1101,29 @@ export async function updateThreadData(id, threadData, title, preview, messageCo
1101
1101
  // Completion persistence can race the separate generated-title save.
1102
1102
  // Keep a title already committed by that save when this caller only has
1103
1103
  // its stale empty snapshot.
1104
- const preserveCurrentTitleAndPreview = options.preserveCurrentMetadata ||
1105
- options.preserveCurrentTitleAndPreview;
1106
- const nextTitle = preserveCurrentTitleAndPreview
1104
+ const preserveCurrentMetadata = options.preserveCurrentMetadata;
1105
+ const preserveCurrentTitleAndPreview = options.preserveCurrentTitleAndPreview;
1106
+ const snapshotMetaForBlankFields = !options.preserveCurrentMetadata &&
1107
+ options.preserveCurrentTitleAndPreview &&
1108
+ (!current.title.trim() || !current.preview.trim())
1109
+ ? extractThreadMeta(merged)
1110
+ : undefined;
1111
+ const nextTitle = preserveCurrentMetadata
1107
1112
  ? current.title
1108
- : title || current.title;
1109
- const nextPreview = preserveCurrentTitleAndPreview
1113
+ : preserveCurrentTitleAndPreview
1114
+ ? current.title.trim()
1115
+ ? current.title
1116
+ : snapshotMetaForBlankFields?.title || current.title
1117
+ : title || current.title || extractThreadMeta(merged).title;
1118
+ const nextPreview = preserveCurrentMetadata
1110
1119
  ? current.preview
1111
- : typeof transformed === "object" && transformed.preview !== undefined
1112
- ? transformed.preview
1113
- : preview;
1120
+ : preserveCurrentTitleAndPreview
1121
+ ? current.preview.trim()
1122
+ ? current.preview
1123
+ : snapshotMetaForBlankFields?.preview || current.preview
1124
+ : typeof transformed === "object" && transformed.preview !== undefined
1125
+ ? transformed.preview
1126
+ : preview;
1114
1127
  const result = await client.execute({
1115
1128
  sql: `UPDATE chat_threads SET thread_data = ?, title = ?, preview = ?, message_count = COALESCE(?, message_count), updated_at = ? WHERE id = ? AND updated_at = ? AND LOWER(owner_email) = LOWER(?)`,
1116
1129
  args: [
@@ -107,6 +107,7 @@ export interface LastTouchAttribution {
107
107
  capture_truncated?: string;
108
108
  }
109
109
  export declare function getAnalyticsIdentityKey(): string | undefined;
110
+ export declare function resolveAnalyticsIdentityKey(): Promise<string | undefined>;
110
111
  export declare function getAnalyticsAnonymousId(): string | undefined;
111
112
  export declare function getAnalyticsSessionId(): string | undefined;
112
113
  export declare function getFirstTouchAttribution(): FirstTouchAttribution | null;
@@ -343,20 +343,22 @@ function setTrackingIdentityFromSession(data) {
343
343
  };
344
344
  }
345
345
  function refreshTrackingAuthSession() {
346
- if (typeof window === "undefined" || typeof fetch !== "function") {
346
+ if (typeof window === "undefined") {
347
347
  _trackingIdentityResolved = true;
348
348
  return Promise.resolve();
349
349
  }
350
+ if (typeof fetch !== "function")
351
+ return Promise.resolve();
350
352
  if (_trackingSessionRefresh)
351
353
  return _trackingSessionRefresh;
352
354
  _trackingSessionRefresh = fetchAuthSessionStatus()
353
355
  .then((result) => {
354
356
  if (result.state === "available") {
355
357
  setTrackingIdentityFromSession(result.value);
358
+ _trackingIdentityResolved = true;
356
359
  }
357
360
  })
358
361
  .finally(() => {
359
- _trackingIdentityResolved = true;
360
362
  _trackingSessionRefresh = null;
361
363
  });
362
364
  return _trackingSessionRefresh;
@@ -396,6 +398,12 @@ function getTrackingAuthUserId() {
396
398
  export function getAnalyticsIdentityKey() {
397
399
  return getTrackingUserId() || getOrCreateAnonymousId();
398
400
  }
401
+ export async function resolveAnalyticsIdentityKey() {
402
+ if (!_trackingIdentityResolved) {
403
+ await (_trackingSessionRefresh ?? refreshTrackingAuthSession());
404
+ }
405
+ return _trackingIdentityResolved ? getAnalyticsIdentityKey() : undefined;
406
+ }
399
407
  function getOrCreateAnonymousId() {
400
408
  return getOrCreateAnalyticsAnonymousId();
401
409
  }
@@ -1,5 +1,6 @@
1
1
  import { AgentKitRunSlotBusyError } from "@agent-native/agentkit/client";
2
2
  import { AUTO_CONTINUE_OF_RUN_METADATA_KEY, CONTINUE_OF_RUN_METADATA_KEY, } from "../../agent/auto-continue.js";
3
+ import { getOrCreateAnalyticsSessionId } from "../analytics-session.js";
3
4
  import { agentChatStreamingUrl, agentNativePath } from "../api-path.js";
4
5
  import { CHAT_REQUEST_TOO_LARGE_MESSAGE } from "../error-format.js";
5
6
  import { appendMissingFinalResponseWarning, } from "../sse-event-processor.js";
@@ -2399,6 +2400,11 @@ export function createAgentNativeChatRuntime(options = {}) {
2399
2400
  const runtimeId = options.id ?? "agent-native";
2400
2401
  const fetchImpl = options.fetch ?? fetch;
2401
2402
  const streamingUrl = options.streamingUrl?.trim() || agentChatStreamingUrl();
2403
+ const isSameOriginEndpoint = (url) => {
2404
+ if (typeof window === "undefined")
2405
+ return false;
2406
+ return new URL(url, window.location.href).origin === window.location.origin;
2407
+ };
2402
2408
  let streamFallbackWarningShown = false;
2403
2409
  const runtimeFetch = streamingUrl
2404
2410
  ? async (input, init) => {
@@ -2439,6 +2445,9 @@ export function createAgentNativeChatRuntime(options = {}) {
2439
2445
  }
2440
2446
  const headers = new Headers(init?.headers);
2441
2447
  headers.set("Authorization", `Bearer ${token}`);
2448
+ if (!isSameOriginEndpoint(streamingUrl)) {
2449
+ headers.delete("x-agent-native-session-id");
2450
+ }
2442
2451
  try {
2443
2452
  return await fetchImpl(streamingUrl, {
2444
2453
  ...init,
@@ -2471,6 +2480,15 @@ export function createAgentNativeChatRuntime(options = {}) {
2471
2480
  headers: async (input) => {
2472
2481
  const headers = await resolveHeaders(options.headers, input);
2473
2482
  headers.set("x-agent-native-surface", options.surface ?? "app");
2483
+ if (!isSameOriginEndpoint(apiUrl)) {
2484
+ headers.delete("x-agent-native-session-id");
2485
+ }
2486
+ else if (!headers.has("x-agent-native-session-id")) {
2487
+ const browserSessionId = getOrCreateAnalyticsSessionId();
2488
+ if (browserSessionId) {
2489
+ headers.set("x-agent-native-session-id", browserSessionId);
2490
+ }
2491
+ }
2474
2492
  return headers;
2475
2493
  },
2476
2494
  capabilities: {
@@ -10,7 +10,10 @@ export interface EngineModelGroup {
10
10
  export interface ChatModelEngineEntry {
11
11
  name: string;
12
12
  label: string;
13
+ defaultModel?: string;
13
14
  supportedModels?: readonly string[];
15
+ /** Full runtime model set, independent of any user-selected picker subset. */
16
+ runtimeSupportedModels?: readonly string[];
14
17
  modelDisplayNames?: Readonly<Record<string, string>>;
15
18
  acceptsCustomModels?: boolean;
16
19
  preserveCustomModels?: boolean;
@@ -312,7 +312,10 @@ function isConnectionError(text, errorCode) {
312
312
  export function normalizeChatError(errorMessage, errorCode) {
313
313
  const raw = String(errorMessage || "Unknown error");
314
314
  const looksHtml = /<html[\s>]|<body[\s>]|<head[\s>]/i.test(raw);
315
- const text = looksHtml ? htmlToText(raw) : raw.trim();
315
+ const providerText = looksHtml ? htmlToText(raw) : raw.trim();
316
+ const text = /^Gateway error \(no detail; raw event:/i.test(providerText)
317
+ ? "Gateway error (no detail)"
318
+ : providerText;
316
319
  const providerPayload = looksHtml ? null : parseProviderErrorPayload(text);
317
320
  const code = normalizeErrorCode(errorCode ?? providerPayload?.errorCode);
318
321
  const credential = chatCredentialState(text, code);
@@ -385,12 +388,6 @@ export function normalizeChatError(errorMessage, errorCode) {
385
388
  details: text,
386
389
  };
387
390
  }
388
- if (/^Gateway error \(no detail; raw event:/i.test(text)) {
389
- return {
390
- message: "The model gateway returned no error details and the chat couldn't recover. Wait a moment and retry, or start a new chat if it keeps happening.",
391
- details: text,
392
- };
393
- }
394
391
  if (/inactivity timeout/i.test(text)) {
395
392
  return {
396
393
  message: "The agent connection timed out before it could finish. You can continue from the partial work or retry.",
@@ -411,6 +408,12 @@ export function normalizeChatError(errorMessage, errorCode) {
411
408
  details: text,
412
409
  };
413
410
  }
411
+ if (/^Gateway error \(no detail(?:;|\))/i.test(text)) {
412
+ return {
413
+ message: "The model gateway returned no error details and the chat couldn't recover. Wait a moment and retry, or start a new chat if it keeps happening.",
414
+ details: text,
415
+ };
416
+ }
414
417
  if (looksHtml) {
415
418
  return {
416
419
  message: text.slice(0, 240) || "The provider returned an HTML error page.",