@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
@@ -0,0 +1,12 @@
1
+ import type { DbExec } from "../db/client.js";
2
+ export interface HistoryOwnershipBackfillCounts {
3
+ organizationRows: number;
4
+ eligibleRows: number;
5
+ organizationJobRows: number;
6
+ ambiguousRows: number;
7
+ deferredRows: number;
8
+ movedRows: number;
9
+ }
10
+ export declare function backfillRunHistoryOwnership(db: DbExec, options?: {
11
+ apply?: boolean;
12
+ }): Promise<HistoryOwnershipBackfillCounts>;
@@ -0,0 +1,87 @@
1
+ const LINEAGE = `
2
+ WITH lineage AS (
3
+ SELECT h.id, h.owner AS source_owner, h.scope AS source_scope,
4
+ h.org_id AS source_org_id, h.status, h.dispatch_pending,
5
+ count(DISTINCT NULLIF(s.metadata::jsonb ->> 'automationId', '')) AS job_ids,
6
+ count(DISTINCT s.user_id) AS actors,
7
+ min(r.owner) AS resource_owner,
8
+ min(r.id) AS resource_id,
9
+ bool_and(COALESCE(
10
+ r.owner = s.user_id AND NOT starts_with(r.owner, '__')
11
+ AND s.org_id = h.org_id AND r.path = h.path
12
+ AND r.created_at <= h.started_at, false
13
+ )) AS personal_match,
14
+ bool_and(COALESCE(
15
+ r.owner = h.owner AND s.org_id = h.org_id
16
+ AND r.path = h.path AND r.created_at <= h.started_at, false
17
+ )) AS organization_match
18
+ FROM automation_runs h
19
+ LEFT JOIN agent_trace_spans s ON s.run_id = h.run_id
20
+ AND s.span_type = 'agent_run'
21
+ AND starts_with(s.name, 'background_automation_run:')
22
+ LEFT JOIN resources r ON r.id = s.metadata::jsonb ->> 'automationId'
23
+ WHERE starts_with(h.owner, '__organization__:')
24
+ GROUP BY h.id, h.owner, h.scope, h.org_id, h.status, h.dispatch_pending
25
+ ), candidates AS (
26
+ SELECT * FROM lineage
27
+ WHERE job_ids = 1 AND actors = 1 AND personal_match
28
+ AND source_scope = 'organization' AND source_org_id IS NOT NULL
29
+ AND status IN ('success', 'error', 'interrupted', 'skipped') AND dispatch_pending = 0
30
+ )`;
31
+ export async function backfillRunHistoryOwnership(db, options = {}) {
32
+ if (!db.transaction)
33
+ throw new Error("History backfill requires transactions.");
34
+ return db.transaction(async (tx) => {
35
+ await tx.execute("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ");
36
+ if (!options.apply)
37
+ await tx.execute("SET TRANSACTION READ ONLY");
38
+ await tx.execute("SET LOCAL statement_timeout = '30s'");
39
+ if (options.apply) {
40
+ // A terminal run's trace can still be amended. Freeze trace writers before
41
+ // taking the first data snapshot, including inserts that row locks miss.
42
+ await tx.execute("SET LOCAL lock_timeout = '2s'");
43
+ await tx.execute("LOCK TABLE agent_trace_spans IN SHARE MODE");
44
+ // Lock the resource identity until commit so a concurrent ownership change
45
+ // cannot invalidate the provenance used to select the personal recipient.
46
+ await tx.execute(`${LINEAGE}, locked_resources AS (
47
+ SELECT r.id FROM resources r
48
+ WHERE r.id IN (SELECT resource_id FROM candidates)
49
+ FOR SHARE
50
+ ) SELECT count(*) FROM locked_resources`);
51
+ }
52
+ const result = await tx.execute(`${LINEAGE}
53
+ SELECT count(*)::int AS organization_rows,
54
+ (SELECT count(*)::int FROM candidates) AS eligible_rows,
55
+ count(*) FILTER (WHERE job_ids = 1 AND organization_match)::int AS organization_job_rows,
56
+ count(*) FILTER (WHERE NOT (job_ids = 1 AND personal_match)
57
+ AND NOT (job_ids = 1 AND organization_match))::int AS ambiguous_rows,
58
+ count(*) FILTER (WHERE job_ids = 1 AND personal_match
59
+ AND id NOT IN (SELECT id FROM candidates))::int AS deferred_rows
60
+ FROM lineage`);
61
+ const row = result.rows[0];
62
+ if (!row)
63
+ throw new Error("History backfill count query returned no row.");
64
+ let movedRows = 0;
65
+ if (options.apply) {
66
+ const updated = await tx.execute(`${LINEAGE}
67
+ UPDATE automation_runs h
68
+ SET owner = c.resource_owner, scope = 'personal', org_id = NULL
69
+ FROM candidates c
70
+ WHERE h.id = c.id AND h.owner = c.source_owner
71
+ AND h.scope = c.source_scope AND h.org_id = c.source_org_id
72
+ RETURNING h.id`);
73
+ movedRows = updated.rows.length;
74
+ if (movedRows !== row.eligible_rows) {
75
+ throw new Error("History changed during backfill; transaction rolled back.");
76
+ }
77
+ }
78
+ return {
79
+ organizationRows: row.organization_rows,
80
+ eligibleRows: row.eligible_rows,
81
+ organizationJobRows: row.organization_job_rows,
82
+ ambiguousRows: row.ambiguous_rows,
83
+ deferredRows: row.deferred_rows,
84
+ movedRows,
85
+ };
86
+ });
87
+ }
@@ -13,7 +13,7 @@ import { lookupOwnerAccount, resolveAutomationExecutionIdentity, } from "../auto
13
13
  import { createThread, getThread, updateThreadData, withThreadDataLock, } from "../chat-threads/store.js";
14
14
  import { automationOutcomeMessagesForUser } from "../localization/automation-outcome-messages.js";
15
15
  import { queryOrgMembers } from "../org/context.js";
16
- import { organizationIdFromResourceOwner, organizationResourceOwner, } from "../resources/store.js";
16
+ import { organizationIdFromResourceOwner, } from "../resources/store.js";
17
17
  import { captureError } from "../server/capture-error.js";
18
18
  import { BuilderCredentialLookupError, CredentialStoreUnavailableError, } from "../server/credential-provider.js";
19
19
  import { runWithRequestContext, } from "../server/request-context.js";
@@ -22,6 +22,7 @@ import automationNoOpAction, { AUTOMATION_NO_OP_TOOL, automationNoOpSchema, } fr
22
22
  import { applyAutomationFailure, automationOwnerKind, classifyAutomationFailure, CONFIG_INVALID_ERROR_CODE, MISSING_TOOLS_ERROR_CODE, OWNER_MISSING_ERROR_CODE, pausedMessage, withDeliveryNote, } from "./automation-outcome.js";
23
23
  import { effectiveTimezone } from "./cron.js";
24
24
  import { recoveredFactoryOwnerOrgId, } from "./frontmatter.js";
25
+ import { automationRunOwnership } from "./run-history-ownership.js";
25
26
  import { attachAutomationRunThread, finishAutomationRun, startAutomationRun, } from "./run-history.js";
26
27
  export const BACKGROUND_RUN_HARD_TIMEOUT_MS = 10 * 60_000;
27
28
  export class BackgroundAutomationRunError extends Error {
@@ -293,17 +294,10 @@ export async function runBackgroundAutomation(options, deps) {
293
294
  }
294
295
  else {
295
296
  try {
296
- const historyOwner = options.orgId
297
- ? organizationResourceOwner(options.orgId)
298
- : automation.resource.owner === "__shared__"
299
- ? options.ownerEmail
300
- : automation.resource.owner;
301
297
  historyId = await startAutomationRun({
302
- owner: historyOwner,
298
+ ...automationRunOwnership(automation.resource.owner, options.ownerEmail, options.orgId),
303
299
  automation: automation.name,
304
300
  path: automation.resource.path,
305
- scope: options.orgId ? "organization" : "personal",
306
- orgId: options.orgId ?? null,
307
301
  appId: deps.appId,
308
302
  notificationEmail: await notificationEmailFor(automation.name, options.ownerEmail, automation.meta.createdBy, options.orgId),
309
303
  });
@@ -1,7 +1,8 @@
1
1
  import { enqueueRemoteCommand, getRemoteCommand, getRemoteCommandByIdempotencyKey, } from "../integrations/remote-commands-store.js";
2
2
  import { getRemoteDeviceForOwner, getRemoteExecutionCapabilities, } from "../integrations/remote-devices-store.js";
3
- import { organizationResourceOwner, resourceGetByPath, resourcePutIfCurrent, } from "../resources/store.js";
3
+ import { resourceGetByPath, resourcePutIfCurrent, } from "../resources/store.js";
4
4
  import { parseJobResource, patchJobFrontmatterFields, } from "./frontmatter.js";
5
+ import { automationRunOwnership } from "./run-history-ownership.js";
5
6
  import { finishAutomationRun, startAutomationRun } from "./run-history.js";
6
7
  export const REMOTE_AUTOMATION_MAX_ACTIVE_MS = 24 * 60 * 60_000;
7
8
  function isRecord(value) {
@@ -103,17 +104,10 @@ export async function dispatchRemoteAutomation(input) {
103
104
  let createdHistory = false;
104
105
  if (!automationRunId) {
105
106
  try {
106
- const historyOwner = input.orgId
107
- ? organizationResourceOwner(input.orgId)
108
- : input.resource.owner === "__shared__"
109
- ? input.ownerEmail
110
- : input.resource.owner;
111
107
  automationRunId = await startAutomationRun({
112
- owner: historyOwner,
108
+ ...automationRunOwnership(input.resource.owner, input.ownerEmail, input.orgId),
113
109
  automation: automationName(input.resource.path),
114
110
  path: input.resource.path,
115
- scope: input.orgId ? "organization" : "personal",
116
- orgId: input.orgId ?? null,
117
111
  appId: input.appId,
118
112
  notificationEmail: input.ownerEmail,
119
113
  });
@@ -0,0 +1,5 @@
1
+ export declare function automationRunOwnership(resourceOwner: string, executionOwner: string, executionOrgId?: string | null): {
2
+ owner: string;
3
+ scope: "personal" | "organization";
4
+ orgId: string | null;
5
+ };
@@ -0,0 +1,16 @@
1
+ import { organizationIdFromResourceOwner, organizationResourceOwner, SHARED_OWNER, } from "../resources/store.js";
2
+ export function automationRunOwnership(resourceOwner, executionOwner, executionOrgId) {
3
+ // Legacy shared resources have no organization in their owner. Personal
4
+ // resources can carry an execution org without belonging to that org.
5
+ const orgId = organizationIdFromResourceOwner(resourceOwner) ??
6
+ (resourceOwner === SHARED_OWNER ? (executionOrgId ?? null) : null);
7
+ return {
8
+ owner: resourceOwner === SHARED_OWNER
9
+ ? orgId
10
+ ? organizationResourceOwner(orgId)
11
+ : executionOwner
12
+ : resourceOwner,
13
+ scope: orgId ? "organization" : "personal",
14
+ orgId,
15
+ };
16
+ }
@@ -4,6 +4,7 @@ import { isLocalDatabase } from "../db/client.js";
4
4
  import { organizationResourceOwner, resourceGetByPath, } from "../resources/store.js";
5
5
  import { fireInternalDispatch } from "../server/self-dispatch.js";
6
6
  import { parseJobResource } from "./frontmatter.js";
7
+ import { automationRunOwnership } from "./run-history-ownership.js";
7
8
  import { listUnclaimedAutomationRuns, startAutomationRun, } from "./run-history.js";
8
9
  async function dispatchAutomationRun(historyId, requestHeaders) {
9
10
  const dispatchPath = resolveAgentChatProcessRunDispatchPath();
@@ -87,11 +88,9 @@ export async function queueAutomationRunNow(input) {
87
88
  console.warn("[automations] Could not sweep queued runs before run-now:", error);
88
89
  });
89
90
  const historyId = await startAutomationRun({
90
- owner: resource.owner,
91
+ ...automationRunOwnership(resource.owner, input.userEmail, input.orgId),
91
92
  automation: name,
92
93
  path: resource.path,
93
- scope: input.scope,
94
- orgId: input.scope === "organization" ? input.orgId : null,
95
94
  appId: input.appId,
96
95
  // The person who asked for the run, already authorized above; a stored
97
96
  // `createdBy` may have left the organization.
@@ -7,6 +7,9 @@ export interface AgentResourcePackMessages {
7
7
  importPackSuccess: string;
8
8
  importPackFailed: string;
9
9
  importPackInvalid: string;
10
+ builderModelFallback: string;
11
+ defaultModel: string;
12
+ modelOptionsUnavailable: string;
10
13
  }
11
14
  export declare const AGENT_RESOURCE_PACK_MESSAGES: Record<BuiltinLocaleCode, AgentResourcePackMessages>;
12
15
  export declare function agentResourcePackMessagesForLocale(locale: LocaleCode): AgentResourcePackMessages;
@@ -8,6 +8,9 @@ export const AGENT_RESOURCE_PACK_MESSAGES = {
8
8
  importPackSuccess: "Imported {{imported}} files, skipped {{skipped}}",
9
9
  importPackFailed: "Could not import pack",
10
10
  importPackInvalid: "That file is not a valid resource pack",
11
+ builderModelFallback: "Builder fallback",
12
+ defaultModel: "Default model",
13
+ modelOptionsUnavailable: "Model options unavailable",
11
14
  },
12
15
  "es-ES": {
13
16
  exportPack: "Exportar paquete",
@@ -17,6 +20,9 @@ export const AGENT_RESOURCE_PACK_MESSAGES = {
17
20
  importPackSuccess: "Se importaron {{imported}} archivos y se omitieron {{skipped}}",
18
21
  importPackFailed: "No se pudo importar el paquete",
19
22
  importPackInvalid: "Ese archivo no es un paquete de recursos válido",
23
+ builderModelFallback: "Alternativa de Builder",
24
+ defaultModel: "Modelo predeterminado",
25
+ modelOptionsUnavailable: "Opciones de modelo no disponibles",
20
26
  },
21
27
  "fr-FR": {
22
28
  exportPack: "Exporter le pack",
@@ -26,6 +32,9 @@ export const AGENT_RESOURCE_PACK_MESSAGES = {
26
32
  importPackSuccess: "{{imported}} fichiers importés, {{skipped}} ignorés",
27
33
  importPackFailed: "Impossible d'importer le pack",
28
34
  importPackInvalid: "Ce fichier n'est pas un pack de ressources valide",
35
+ builderModelFallback: "Solution de repli Builder",
36
+ defaultModel: "Modèle par défaut",
37
+ modelOptionsUnavailable: "Options de modèle indisponibles",
29
38
  },
30
39
  "de-DE": {
31
40
  exportPack: "Paket exportieren",
@@ -35,6 +44,9 @@ export const AGENT_RESOURCE_PACK_MESSAGES = {
35
44
  importPackSuccess: "{{imported}} Dateien importiert, {{skipped}} übersprungen",
36
45
  importPackFailed: "Paket konnte nicht importiert werden",
37
46
  importPackInvalid: "Diese Datei ist kein gültiges Ressourcenpaket",
47
+ builderModelFallback: "Builder-Fallback",
48
+ defaultModel: "Standardmodell",
49
+ modelOptionsUnavailable: "Modelloptionen nicht verfügbar",
38
50
  },
39
51
  "pt-BR": {
40
52
  exportPack: "Exportar pacote",
@@ -44,6 +56,9 @@ export const AGENT_RESOURCE_PACK_MESSAGES = {
44
56
  importPackSuccess: "{{imported}} arquivos importados, {{skipped}} ignorados",
45
57
  importPackFailed: "Não foi possível importar o pacote",
46
58
  importPackInvalid: "Esse arquivo não é um pacote de recursos válido",
59
+ builderModelFallback: "Alternativa do Builder",
60
+ defaultModel: "Modelo padrão",
61
+ modelOptionsUnavailable: "Opções de modelo indisponíveis",
47
62
  },
48
63
  "zh-CN": {
49
64
  exportPack: "导出资源包",
@@ -53,6 +68,9 @@ export const AGENT_RESOURCE_PACK_MESSAGES = {
53
68
  importPackSuccess: "已导入 {{imported}} 个文件,已跳过 {{skipped}} 个",
54
69
  importPackFailed: "无法导入资源包",
55
70
  importPackInvalid: "该文件不是有效的资源包",
71
+ builderModelFallback: "Builder 回退模型",
72
+ defaultModel: "默认模型",
73
+ modelOptionsUnavailable: "模型选项不可用",
56
74
  },
57
75
  "zh-TW": {
58
76
  exportPack: "匯出資源包",
@@ -62,6 +80,9 @@ export const AGENT_RESOURCE_PACK_MESSAGES = {
62
80
  importPackSuccess: "已匯入 {{imported}} 個檔案,已略過 {{skipped}} 個",
63
81
  importPackFailed: "無法匯入資源包",
64
82
  importPackInvalid: "該檔案不是有效的資源包",
83
+ builderModelFallback: "Builder 備援模型",
84
+ defaultModel: "預設模型",
85
+ modelOptionsUnavailable: "模型選項無法使用",
65
86
  },
66
87
  "ja-JP": {
67
88
  exportPack: "パックを書き出す",
@@ -71,6 +92,9 @@ export const AGENT_RESOURCE_PACK_MESSAGES = {
71
92
  importPackSuccess: "{{imported}} 件のファイルをインポートし、{{skipped}} 件をスキップしました",
72
93
  importPackFailed: "パックを読み込めませんでした",
73
94
  importPackInvalid: "このファイルは有効なリソースパックではありません",
95
+ builderModelFallback: "Builder のフォールバック",
96
+ defaultModel: "既定のモデル",
97
+ modelOptionsUnavailable: "モデルの選択肢を利用できません",
74
98
  },
75
99
  "ko-KR": {
76
100
  exportPack: "팩 내보내기",
@@ -80,6 +104,9 @@ export const AGENT_RESOURCE_PACK_MESSAGES = {
80
104
  importPackSuccess: "파일 {{imported}}개를 가져왔고 {{skipped}}개를 건너뛰었습니다",
81
105
  importPackFailed: "팩을 가져오지 못했습니다",
82
106
  importPackInvalid: "이 파일은 유효한 리소스 팩이 아닙니다",
107
+ builderModelFallback: "Builder 대체 모델",
108
+ defaultModel: "기본 모델",
109
+ modelOptionsUnavailable: "모델 옵션을 사용할 수 없습니다",
83
110
  },
84
111
  "hi-IN": {
85
112
  exportPack: "पैक निर्यात करें",
@@ -89,6 +116,9 @@ export const AGENT_RESOURCE_PACK_MESSAGES = {
89
116
  importPackSuccess: "{{imported}} फ़ाइलें आयात हुईं, {{skipped}} छोड़ी गईं",
90
117
  importPackFailed: "पैक आयात नहीं हो सका",
91
118
  importPackInvalid: "यह फ़ाइल एक मान्य संसाधन पैक नहीं है",
119
+ builderModelFallback: "Builder फ़ॉलबैक",
120
+ defaultModel: "डिफ़ॉल्ट मॉडल",
121
+ modelOptionsUnavailable: "मॉडल विकल्प उपलब्ध नहीं हैं",
92
122
  },
93
123
  "ar-SA": {
94
124
  exportPack: "تصدير الحزمة",
@@ -98,6 +128,9 @@ export const AGENT_RESOURCE_PACK_MESSAGES = {
98
128
  importPackSuccess: "تم استيراد {{imported}} من الملفات وتخطي {{skipped}}",
99
129
  importPackFailed: "تعذر استيراد الحزمة",
100
130
  importPackInvalid: "هذا الملف ليس حزمة موارد صالحة",
131
+ builderModelFallback: "البديل الاحتياطي من Builder",
132
+ defaultModel: "النموذج الافتراضي",
133
+ modelOptionsUnavailable: "خيارات النماذج غير متاحة",
101
134
  },
102
135
  };
103
136
  export function agentResourcePackMessagesForLocale(locale) {
@@ -25,10 +25,9 @@ import { z } from "zod";
25
25
  import { defineAction } from "../../action.js";
26
26
  import { orgAdminAudit } from "../../audit/org-admin.js";
27
27
  import { getServicePrincipalPolicy, upsertServicePrincipalPolicy, } from "../../org/service-principal-policy.js";
28
- import { getAppProductionUrl } from "../../server/app-url.js";
29
28
  import { CREDENTIAL_MEMBERSHIP_UNAVAILABLE_MESSAGE } from "../../server/credential-membership-unavailable.js";
30
29
  import { getRequestContext } from "../../server/request-context.js";
31
- import { mintOrgServiceToken } from "../connect-route.js";
30
+ import { mintOrgServiceToken, OrgServiceTokenAppUrlError, } from "../connect-route.js";
32
31
  import { MAX_SERVICE_TOKEN_TTL_DAYS, revokeOrgServiceToken, } from "../connect-store.js";
33
32
  import { McpCredentialIssuanceError } from "../credential-issuance.js";
34
33
  import { allowedActionsSchema, assertOwnerIsOrgMember, normalizeAllowedActions, ownerEmailSchema, parseServiceName, purposeSchema, riskTierSchema, teamSchema, } from "./service-principal-input.js";
@@ -96,10 +95,6 @@ export default defineAction({
96
95
  if (args.allowedActions !== undefined) {
97
96
  policyInput.allowedActions = normalizeAllowedActions(args.allowedActions);
98
97
  }
99
- const appUrl = (getRequestContext()?.requestOrigin || getAppProductionUrl()).replace(/\/+$/, "");
100
- if (!appUrl && !process.env.A2A_SECRET?.trim()) {
101
- throw new ServiceTokenError("Could not determine the app URL needed to mint a token. Set APP_URL on the deployment.", 500);
102
- }
103
98
  let minted;
104
99
  try {
105
100
  minted = await mintOrgServiceToken({
@@ -107,10 +102,13 @@ export default defineAction({
107
102
  orgId: caller.orgId,
108
103
  createdBy: caller.email,
109
104
  ttlDays: args.ttlDays,
110
- appUrl,
105
+ appUrl: getRequestContext()?.requestOrigin?.replace(/\/+$/, ""),
111
106
  });
112
107
  }
113
108
  catch (error) {
109
+ if (error instanceof OrgServiceTokenAppUrlError) {
110
+ throw new ServiceTokenError(error.message, 500);
111
+ }
114
112
  if (!(error instanceof McpCredentialIssuanceError))
115
113
  throw error;
116
114
  throw error.reason === "not-member"
@@ -1,5 +1,6 @@
1
1
  import "../authorization/check-action.js";
2
2
  import type { ActionEntry } from "../agent/production-agent.js";
3
+ import type { BearerCredentialRefusal } from "../server/bearer-credential-refusal.js";
3
4
  import { type McpDirectoryWidgetReadArgument } from "../shared/embed-auth.js";
4
5
  import type { ExternalAgentPolicy } from "./external-agent-policy.js";
5
6
  export interface MCPConfig {
@@ -138,38 +139,42 @@ export type VerifyAuthResult = {
138
139
  fullCatalog?: boolean;
139
140
  /**
140
141
  * The token verified, but its standing could not be checked: the
141
- * connect-token revocation or org lookup, the retired-address check, or the
142
+ * connect-token lookup, the retired-address check, or the
142
143
  * membership check hit a database or identity-authority error. Answer with
143
144
  * a retryable error, not an auth challenge: signing in again would not help.
144
145
  */
145
146
  unavailable?: true;
147
+ /**
148
+ * Why a presented bearer token was refused. Absent when no token was
149
+ * presented, and when the refusal is `unavailable`.
150
+ */
151
+ refusal?: BearerCredentialRefusal;
146
152
  };
147
153
  /**
148
154
  * Verify the inbound auth header. Returns:
149
- * - { authed: true, identity } when verified. A deployment-secret JWT may
155
+ * - { authed: true, identity } when verified. A credential this app issued
156
+ * (an MCP OAuth access token or a connect token) supplies its subject and
157
+ * org, checked against live membership. A deployment-secret A2A JWT may
150
158
  * supply its asserted user (`sub`), while an org-secret JWT supplies only
151
- * verified organization scope. Legacy connect tokens recover stored org
152
- * scope. Static-token auth gets identity from `AGENT_NATIVE_OWNER_EMAIL`
153
- * or `X-Agent-Native-Owner-Email` (the `agent-native mcp install` flow).
154
- * `identity` is undefined only for true dev-open with no owner hint.
155
- * - { authed: false } on rejection.
159
+ * verified organization scope. Static-token auth gets identity from
160
+ * `AGENT_NATIVE_OWNER_EMAIL` or `X-Agent-Native-Owner-Email` (the
161
+ * `agent-native mcp install` flow). `identity` is undefined only for true
162
+ * dev-open with no owner hint.
163
+ * - { authed: false, refusal? } on rejection; `refusal` is set whenever a
164
+ * presented token was refused.
156
165
  *
157
- * A deployment-secret A2A JWT can supply its trusted `sub` (caller email).
158
- * An org-secret JWT never supplies a user identity; both paths bind
159
- * `org_domain` to local organization metadata. Legacy connect tokens can use
160
- * a stored-org fallback. The MCP endpoint wraps tool runs in
161
- * `runWithRequestContext({ userEmail, orgId })`. Without that wrap, the
162
- * MCP endpoint loses tenant identity and downstream `accessFilter` /
163
- * `resolveCredential` calls fall back to platform-wide defaults.
166
+ * Credentials this app issued are recognized and verified before any A2A
167
+ * rule runs, so a change to cross-app trust cannot reclassify them. Both A2A
168
+ * paths bind `org_domain` to local organization metadata. The MCP endpoint
169
+ * wraps tool runs in `runWithRequestContext({ userEmail, orgId })`. Without
170
+ * that wrap, the MCP endpoint loses tenant identity and downstream
171
+ * `accessFilter` / `resolveCredential` calls fall back to platform-wide
172
+ * defaults.
164
173
  *
165
174
  * `ownerEmailHeader` is the forwarded `X-Agent-Native-Owner-Email` value; it
166
175
  * is consulted ONLY on the static-token / dev-open path (never to influence
167
176
  * verified JWT identity), so the install flow runs tools as the configured
168
177
  * owner instead of an unscoped anonymous caller.
169
- *
170
- * A credential this app issued that names an organization is admitted only
171
- * while its subject is still a member, and none is admitted for an address an
172
- * email change retired after signing (see `admitIssuedCredential`).
173
178
  */
174
179
  export declare function verifyAuth(authHeader: string | undefined, ownerEmailHeader?: string, options?: {
175
180
  allowDevOpen?: boolean;