@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.
- package/dist/a2a/client.d.ts +2 -2
- package/dist/agent/engine/anthropic-engine.d.ts +1 -1
- package/dist/agent/engine/builder-engine.d.ts +1 -1
- package/dist/agent/engine/builder-engine.js +23 -8
- package/dist/agent/engine/error-telemetry.d.ts +5 -0
- package/dist/agent/engine/error-telemetry.js +41 -0
- package/dist/agent/engine/registry.d.ts +1 -6
- package/dist/agent/engine/registry.js +2 -31
- package/dist/agent/model-config.d.ts +26 -14
- package/dist/agent/model-config.js +131 -8
- package/dist/agent/model-version.d.ts +19 -0
- package/dist/agent/model-version.js +153 -0
- package/dist/agent/production-agent.d.ts +1 -0
- package/dist/agent/production-agent.js +24 -6
- package/dist/agent/provider-model-selection.js +6 -4
- package/dist/agent/run-manager.js +5 -11
- package/dist/agent/thread-data-builder.js +14 -6
- package/dist/authorization/check-action.js +8 -4
- package/dist/chat-threads/store.js +22 -9
- package/dist/client/analytics.d.ts +1 -0
- package/dist/client/analytics.js +10 -2
- package/dist/client/chat/runtime.js +18 -0
- package/dist/client/chat-model-groups.d.ts +3 -0
- package/dist/client/error-format.js +10 -7
- package/dist/client/onboarding/use-onboarding.d.ts +12 -0
- package/dist/client/onboarding/use-onboarding.js +491 -4
- package/dist/client/session-replay-privacy.d.ts +8 -0
- package/dist/client/session-replay-privacy.js +8 -0
- package/dist/client/session-replay.d.ts +1 -0
- package/dist/client/session-replay.js +18 -9
- package/dist/client/sse-event-processor.js +10 -6
- package/dist/client/use-chat-models.d.ts +5 -0
- package/dist/client/use-chat-models.js +51 -5
- package/dist/client/use-session.d.ts +8 -1
- package/dist/client/use-session.js +20 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/deploy/build.js +353 -3
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/jobs/backfill-run-history-ownership.d.ts +12 -0
- package/dist/jobs/backfill-run-history-ownership.js +87 -0
- package/dist/jobs/background-automation-runner.js +3 -9
- package/dist/jobs/remote-execution.js +3 -9
- package/dist/jobs/run-history-ownership.d.ts +5 -0
- package/dist/jobs/run-history-ownership.js +16 -0
- package/dist/jobs/run-now.js +2 -3
- package/dist/localization/agent-resources-messages.d.ts +3 -0
- package/dist/localization/agent-resources-messages.js +33 -0
- package/dist/mcp/actions/create-org-service-token.js +5 -7
- package/dist/mcp/build-server.d.ts +23 -18
- package/dist/mcp/build-server.js +220 -212
- package/dist/mcp/connect-route.d.ts +11 -2
- package/dist/mcp/connect-route.js +34 -24
- package/dist/mcp/connect-store.d.ts +9 -13
- package/dist/mcp/connect-store.js +11 -24
- package/dist/mcp/credential-membership.js +17 -6
- package/dist/mcp/oauth-route.d.ts +11 -1
- package/dist/mcp/oauth-route.js +28 -6
- package/dist/mcp/oauth-token.d.ts +12 -2
- package/dist/mcp/oauth-token.js +15 -4
- package/dist/mcp/server.js +9 -5
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/posthog-ai.d.ts +1 -0
- package/dist/observability/posthog-ai.js +20 -8
- package/dist/observability/routes.d.ts +6 -6
- package/dist/observability/traces.js +61 -39
- package/dist/org/app-roles.d.ts +8 -1
- package/dist/org/app-roles.js +29 -9
- package/dist/org/context.js +24 -8
- package/dist/org/index.d.ts +2 -2
- package/dist/org/workspace-app-identity.d.ts +1 -0
- package/dist/org/workspace-app-identity.js +25 -0
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
- package/dist/provider-api/actions/provider-api.d.ts +3 -3
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/scripts/agent-engines/list-agent-engines.js +1 -0
- package/dist/server/action-routes.js +8 -1
- package/dist/server/agent-chat-plugin.js +1 -0
- package/dist/server/agent-engine-default-model-route.d.ts +1 -1
- package/dist/server/auth.js +33 -17
- package/dist/server/bearer-credential-refusal.d.ts +23 -0
- package/dist/server/bearer-credential-refusal.js +67 -0
- package/dist/server/better-auth-instance.js +13 -6
- package/dist/server/builder-browser.d.ts +2 -0
- package/dist/server/builder-browser.js +16 -3
- package/dist/server/capture-error.d.ts +1 -0
- package/dist/server/capture-error.js +28 -4
- package/dist/server/complete-text.js +16 -3
- package/dist/server/core-routes-plugin.js +2 -0
- package/dist/server/dev-action-bridge.js +7 -1
- package/dist/server/google-oauth.js +6 -3
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/recap-image-route.js +4 -0
- package/dist/server/request-context.d.ts +16 -0
- package/dist/server/request-context.js +17 -0
- package/dist/shared/agent-chat-context.d.ts +1 -0
- package/dist/shared/agent-chat-context.js +26 -0
- package/dist/shared/index.d.ts +1 -1
- package/dist/shared/index.js +1 -1
- package/dist/shared/reasoning-effort.js +10 -1
- package/dist/shared/ssr-session-bootstrap.d.ts +7 -0
- package/dist/shared/ssr-session-bootstrap.js +21 -0
- package/dist/sharing/access.js +86 -5
- package/dist/templates/builder-code-starter/server/routes/index.get.ts +2 -0
- package/dist/triggers/routes.js +2 -1
- package/docs/content/automation-connectors.mdx +5 -3
- package/docs/content/automations.mdx +78 -49
- package/docs/content/observability.mdx +16 -5
- package/docs/content/organizations-teams-permissions.mdx +44 -2
- package/docs/content/recurring-jobs.mdx +4 -8
- package/docs/content/template-forms.mdx +6 -0
- package/package.json +5 -4
- 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,
|
|
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
|
|
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 {
|
|
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
|
|
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,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
|
+
}
|
package/dist/jobs/run-now.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
|
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.
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
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
|
-
*
|
|
158
|
-
*
|
|
159
|
-
* `org_domain` to local organization metadata.
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
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;
|