@agent-native/core 0.158.9 → 0.159.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/templates/clips/app/components/recorder/recording-toolbar.tsx +2 -2
- package/corpus/templates/clips/app/i18n/en-US.ts +7 -2
- package/corpus/templates/clips/app/routes/record.tsx +147 -5
- package/dist/a2a/auth-policy.d.ts +0 -6
- package/dist/a2a/auth-policy.js +2 -1
- package/dist/a2a/client.js +10 -12
- package/dist/agent/durable-background.js +3 -2
- package/dist/agent/engine/registry.js +5 -4
- package/dist/agent/run-manager.js +8 -20
- package/dist/app-config/a2a.d.ts +14 -0
- package/dist/app-config/a2a.js +42 -0
- package/dist/app-config/agent.d.ts +18 -0
- package/dist/app-config/agent.js +69 -0
- package/dist/app-config/app.d.ts +33 -0
- package/dist/app-config/app.js +100 -0
- package/dist/app-config/describe.d.ts +26 -0
- package/dist/app-config/describe.js +61 -0
- package/dist/app-config/env-layer.d.ts +37 -0
- package/dist/app-config/env-layer.js +136 -0
- package/dist/app-config/index.d.ts +2 -0
- package/dist/app-config/index.js +2 -0
- package/dist/app-config/integrations.d.ts +5 -0
- package/dist/app-config/integrations.js +11 -0
- package/dist/app-config/private-blob.d.ts +14 -0
- package/dist/app-config/private-blob.js +19 -0
- package/dist/app-config/schema.d.ts +55 -0
- package/dist/app-config/schema.js +31 -0
- package/dist/app-config/store.d.ts +42 -0
- package/dist/app-config/store.js +104 -0
- package/dist/app-config/workspace.d.ts +21 -0
- package/dist/app-config/workspace.js +35 -0
- package/dist/cli/agent.js +2 -1
- package/dist/cli/code-agent-executor.js +5 -4
- package/dist/client/analytics.d.ts +9 -0
- package/dist/client/frame.js +11 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/deploy/build.js +36 -0
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/integrations/a2a-continuation-processor.js +12 -9
- package/dist/integrations/adapters/email.js +2 -1
- package/dist/integrations/adapters/telegram.js +2 -1
- package/dist/integrations/adapters/whatsapp.js +2 -1
- package/dist/integrations/webhook-handler.d.ts +7 -2
- package/dist/integrations/webhook-handler.js +9 -31
- package/dist/observability/routes.d.ts +5 -5
- package/dist/onboarding/app-profile.js +2 -4
- package/dist/onboarding/default-steps.js +4 -4
- package/dist/private-blob/registry.d.ts +5 -0
- package/dist/private-blob/registry.js +19 -8
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +13 -13
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.js +4 -2
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-chat/action-filters-a2a.js +5 -4
- package/dist/server/agent-chat/run-code-tools.js +3 -4
- package/dist/server/agent-chat-plugin.js +4 -3
- package/dist/server/agent-discovery.js +7 -5
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/app-origin-config.d.ts +23 -0
- package/dist/server/app-origin-config.js +43 -0
- package/dist/server/auth.js +21 -1
- package/dist/server/core-routes-plugin.js +3 -3
- package/dist/server/credential-provider.js +7 -8
- package/dist/server/embed-session.js +2 -1
- package/dist/server/identity-sso.js +6 -2
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1 -0
- package/dist/server/oauth-public-origin.js +10 -14
- package/dist/server/oauth-return-url.js +5 -9
- package/dist/server/self-dispatch.js +5 -2
- package/dist/server/ssr-handler.js +2 -0
- package/dist/server/workspace-provider-oauth.js +2 -4
- package/dist/sharing/actions/create-agent-resource-link.js +2 -2
- package/dist/usage/metrics-store.js +2 -1
- package/package.json +3 -3
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Workspace gateway.
|
|
4
|
+
*
|
|
5
|
+
* A workspace deploy puts one gateway in front of N apps, so these are a
|
|
6
|
+
* *different host* from this app's own URL — not another spelling of it.
|
|
7
|
+
* `deploy/workspace-deploy.ts` sets them on each app it launches.
|
|
8
|
+
*
|
|
9
|
+
* Each field lists the plain and `VITE_` spelling as aliases of one value. The
|
|
10
|
+
* prefix only ever meant "inline this into the browser bundle", which is a
|
|
11
|
+
* delivery question, not a second setting — the shell projection in
|
|
12
|
+
* `server/app-origin-config.ts` answers that now.
|
|
13
|
+
*
|
|
14
|
+
* Length-checked but not `.url()`-validated, for the same reason as `app.url`:
|
|
15
|
+
* a malformed value should fail where it is used, not take every config read
|
|
16
|
+
* in the process down with it.
|
|
17
|
+
*/
|
|
18
|
+
export declare const workspaceConfig: z.ZodObject<{
|
|
19
|
+
gatewayUrl: z.ZodOptional<z.ZodString>;
|
|
20
|
+
oauthOrigin: z.ZodOptional<z.ZodString>;
|
|
21
|
+
}, z.core.$strip>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Workspace gateway.
|
|
4
|
+
*
|
|
5
|
+
* A workspace deploy puts one gateway in front of N apps, so these are a
|
|
6
|
+
* *different host* from this app's own URL — not another spelling of it.
|
|
7
|
+
* `deploy/workspace-deploy.ts` sets them on each app it launches.
|
|
8
|
+
*
|
|
9
|
+
* Each field lists the plain and `VITE_` spelling as aliases of one value. The
|
|
10
|
+
* prefix only ever meant "inline this into the browser bundle", which is a
|
|
11
|
+
* delivery question, not a second setting — the shell projection in
|
|
12
|
+
* `server/app-origin-config.ts` answers that now.
|
|
13
|
+
*
|
|
14
|
+
* Length-checked but not `.url()`-validated, for the same reason as `app.url`:
|
|
15
|
+
* a malformed value should fail where it is used, not take every config read
|
|
16
|
+
* in the process down with it.
|
|
17
|
+
*/
|
|
18
|
+
export const workspaceConfig = z.object({
|
|
19
|
+
gatewayUrl: z
|
|
20
|
+
.string()
|
|
21
|
+
.min(1)
|
|
22
|
+
.optional()
|
|
23
|
+
.meta({
|
|
24
|
+
env: ["WORKSPACE_GATEWAY_URL", "VITE_WORKSPACE_GATEWAY_URL"],
|
|
25
|
+
doc: "URL of the workspace gateway fronting this app.",
|
|
26
|
+
}),
|
|
27
|
+
oauthOrigin: z
|
|
28
|
+
.string()
|
|
29
|
+
.min(1)
|
|
30
|
+
.optional()
|
|
31
|
+
.meta({
|
|
32
|
+
env: ["WORKSPACE_OAUTH_ORIGIN", "VITE_WORKSPACE_OAUTH_ORIGIN"],
|
|
33
|
+
doc: "Shared origin workspace apps complete OAuth against.",
|
|
34
|
+
}),
|
|
35
|
+
});
|
package/dist/cli/agent.js
CHANGED
|
@@ -4,6 +4,7 @@ import { DEFAULT_MODEL } from "../agent/default-model.js";
|
|
|
4
4
|
import { registerBuiltinEngines, resolveEngine, } from "../agent/engine/index.js";
|
|
5
5
|
import { actionsToEngineTools, } from "../agent/production-agent.js";
|
|
6
6
|
import { runAgentLoopDirectWithSoftTimeout } from "../agent/run-loop-with-resume.js";
|
|
7
|
+
import { getAppConfig } from "../app-config/index.js";
|
|
7
8
|
import { createGitHubRepoToolEntries } from "../provider-api/github-repo.js";
|
|
8
9
|
import { resolveDevUserEmail } from "../scripts/dev-session.js";
|
|
9
10
|
import { loadEnv } from "../scripts/utils.js";
|
|
@@ -143,7 +144,7 @@ async function runLocalAgentLoop(parsed) {
|
|
|
143
144
|
const localActions = await autoDiscoverActions("auto");
|
|
144
145
|
const builtinActions = await createHeadlessBuiltinActions();
|
|
145
146
|
const repoActions = createGitHubRepoToolEntries({
|
|
146
|
-
appId:
|
|
147
|
+
appId: getAppConfig().app.id ?? "app",
|
|
147
148
|
});
|
|
148
149
|
const actions = { ...builtinActions, ...localActions, ...repoActions };
|
|
149
150
|
const tools = actionsToEngineTools(actions);
|
|
@@ -7,6 +7,7 @@ import { PROVIDER_ENV_VARS } from "../agent/engine/provider-env-vars.js";
|
|
|
7
7
|
import { DEFAULT_AGENT_MAX_ITERATIONS } from "../agent/loop-settings.js";
|
|
8
8
|
import { actionsToEngineTools, runAgentLoop, } from "../agent/production-agent.js";
|
|
9
9
|
import { createToolSearchEntry, TOOL_SEARCH_ACTION_NAME, } from "../agent/tool-search.js";
|
|
10
|
+
import { getAppConfig } from "../app-config/index.js";
|
|
10
11
|
import { formatPromptWithAttachments, } from "../code-agents/prompt-attachments.js";
|
|
11
12
|
import { createCodingToolRegistry, isReadOnlyShellCommand, runCodingCommand, truncateBashOutput, truncateCodingOutput, } from "../coding-tools/index.js";
|
|
12
13
|
import { buildMergedConfig, McpClientManager, mcpToolsToActionEntries, } from "../mcp-client/index.js";
|
|
@@ -103,7 +104,7 @@ export async function executeCodeAgentRun(options) {
|
|
|
103
104
|
// Fall back to AGENT_ENGINE here too, mirroring resolveExecutorEngine below.
|
|
104
105
|
// Without it, `AGENT_ENGINE=codex-cli` skips this Codex branch and is handed
|
|
105
106
|
// to resolveEngine (LLM providers only), which throws `Unknown engine`.
|
|
106
|
-
const requestedEngine = normalizeRequestedEngine(metadataString(existing, "engine") ??
|
|
107
|
+
const requestedEngine = normalizeRequestedEngine(metadataString(existing, "engine") ?? getAppConfig().agent.engine);
|
|
107
108
|
if (requestedEngine === CODEX_CLI_ENGINE_NAME) {
|
|
108
109
|
return executeCodexCliRun({
|
|
109
110
|
run: existing,
|
|
@@ -178,7 +179,7 @@ export async function executeCodeAgentRun(options) {
|
|
|
178
179
|
}
|
|
179
180
|
const modelCandidate = options.model ??
|
|
180
181
|
metadataString(existing, "model") ??
|
|
181
|
-
|
|
182
|
+
getAppConfig().agent.model ??
|
|
182
183
|
(await getStoredModelForEngine(engine).catch(() => undefined)) ??
|
|
183
184
|
engine.defaultModel;
|
|
184
185
|
const model = normalizeModelForEngine(engine, modelCandidate);
|
|
@@ -1794,11 +1795,11 @@ async function resolveExecutorEngine(requestedEngine) {
|
|
|
1794
1795
|
if (!hasAnyProviderCredential())
|
|
1795
1796
|
return null;
|
|
1796
1797
|
return resolveEngine({
|
|
1797
|
-
engineOption: requestedEngine ??
|
|
1798
|
+
engineOption: requestedEngine ?? getAppConfig().agent.engine,
|
|
1798
1799
|
});
|
|
1799
1800
|
}
|
|
1800
1801
|
function hasAnyProviderCredential() {
|
|
1801
|
-
if (
|
|
1802
|
+
if (getAppConfig().agent.engine)
|
|
1802
1803
|
return true;
|
|
1803
1804
|
if (PROVIDER_ENV_VARS.some((key) => Boolean(process.env[key])))
|
|
1804
1805
|
return true;
|
|
@@ -9,6 +9,15 @@ declare global {
|
|
|
9
9
|
interface Window {
|
|
10
10
|
gtag?: (...args: any[]) => void;
|
|
11
11
|
__AGENT_NATIVE_CONFIG__?: {
|
|
12
|
+
/**
|
|
13
|
+
* This app's origins, projected by server/app-origin-config.ts. These
|
|
14
|
+
* replace the `VITE_` mirrors of APP_URL / WORKSPACE_* — the prefix only
|
|
15
|
+
* ever answered "how does this reach the browser", which the shell
|
|
16
|
+
* answers better. Impersonal, so safe in the CDN-cached shell.
|
|
17
|
+
*/
|
|
18
|
+
appUrl?: string;
|
|
19
|
+
workspaceGatewayUrl?: string;
|
|
20
|
+
workspaceOAuthOrigin?: string;
|
|
12
21
|
sentryDsn?: string;
|
|
13
22
|
sentryEnvironment?: string;
|
|
14
23
|
/**
|
package/dist/client/frame.js
CHANGED
|
@@ -186,7 +186,17 @@ function runtimeEnvValue(name) {
|
|
|
186
186
|
: undefined;
|
|
187
187
|
}
|
|
188
188
|
function workspaceOAuthOrigin() {
|
|
189
|
-
|
|
189
|
+
// The shell carries the server's declared values, so it answers first. The
|
|
190
|
+
// env lookups below are the pre-shell fallback and are kept for deployments
|
|
191
|
+
// built before the projection existed: in a browser only the `VITE_`
|
|
192
|
+
// spellings can ever resolve, and on the server only the plain ones are
|
|
193
|
+
// guaranteed — which is why the chain lists both and why it is not the
|
|
194
|
+
// primary path any more.
|
|
195
|
+
const shell = typeof window !== "undefined" ? window.__AGENT_NATIVE_CONFIG__ : undefined;
|
|
196
|
+
const raw = shell?.workspaceOAuthOrigin ||
|
|
197
|
+
shell?.appUrl ||
|
|
198
|
+
shell?.workspaceGatewayUrl ||
|
|
199
|
+
runtimeEnvValue("VITE_WORKSPACE_OAUTH_ORIGIN") ||
|
|
190
200
|
runtimeEnvValue("WORKSPACE_OAUTH_ORIGIN") ||
|
|
191
201
|
runtimeEnvValue("VITE_APP_URL") ||
|
|
192
202
|
runtimeEnvValue("APP_URL") ||
|
|
@@ -62,11 +62,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
|
|
|
62
62
|
error: string;
|
|
63
63
|
states?: undefined;
|
|
64
64
|
} | {
|
|
65
|
+
error?: undefined;
|
|
65
66
|
states: {
|
|
66
67
|
clientId: number;
|
|
67
68
|
state: string;
|
|
68
69
|
}[];
|
|
69
|
-
error?: undefined;
|
|
70
70
|
}>>;
|
|
71
71
|
/**
|
|
72
72
|
* GET /_agent-native/collab/:docId/users
|
|
@@ -77,9 +77,9 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
|
|
|
77
77
|
error: string;
|
|
78
78
|
users?: undefined;
|
|
79
79
|
} | {
|
|
80
|
+
error?: undefined;
|
|
80
81
|
users: {
|
|
81
82
|
clientId: number;
|
|
82
83
|
lastSeen: number;
|
|
83
84
|
}[];
|
|
84
|
-
error?: undefined;
|
|
85
85
|
}>>;
|
package/dist/deploy/build.js
CHANGED
|
@@ -964,6 +964,41 @@ function getRealtimeClientConfigScript() {
|
|
|
964
964
|
);
|
|
965
965
|
}
|
|
966
966
|
|
|
967
|
+
function getAppOriginClientConfigScript() {
|
|
968
|
+
// MUST stay consistent with resolvePublicAppOriginConfig in
|
|
969
|
+
// server/app-origin-config.ts, and with the alias order declared on
|
|
970
|
+
// app.url / workspace.* in app-config (worker bundles a string copy; it
|
|
971
|
+
// can't import them). Impersonal values only — this ships into the
|
|
972
|
+
// CDN-cached shell.
|
|
973
|
+
const env = globalThis.process?.env || {};
|
|
974
|
+
const appUrl = firstNonEmpty(
|
|
975
|
+
env.APP_URL,
|
|
976
|
+
env.VITE_APP_URL,
|
|
977
|
+
env.BETTER_AUTH_URL,
|
|
978
|
+
env.VITE_BETTER_AUTH_URL,
|
|
979
|
+
);
|
|
980
|
+
const workspaceGatewayUrl = firstNonEmpty(
|
|
981
|
+
env.WORKSPACE_GATEWAY_URL,
|
|
982
|
+
env.VITE_WORKSPACE_GATEWAY_URL,
|
|
983
|
+
);
|
|
984
|
+
const workspaceOAuthOrigin = firstNonEmpty(
|
|
985
|
+
env.WORKSPACE_OAUTH_ORIGIN,
|
|
986
|
+
env.VITE_WORKSPACE_OAUTH_ORIGIN,
|
|
987
|
+
);
|
|
988
|
+
const config = {
|
|
989
|
+
...(appUrl ? { appUrl } : {}),
|
|
990
|
+
...(workspaceGatewayUrl ? { workspaceGatewayUrl } : {}),
|
|
991
|
+
...(workspaceOAuthOrigin ? { workspaceOAuthOrigin } : {}),
|
|
992
|
+
};
|
|
993
|
+
if (Object.keys(config).length === 0) return null;
|
|
994
|
+
return (
|
|
995
|
+
'<script data-agent-native-app-origin-config>' +
|
|
996
|
+
'window.__AGENT_NATIVE_CONFIG__=Object.assign({},window.__AGENT_NATIVE_CONFIG__,' +
|
|
997
|
+
JSON.stringify(config) +
|
|
998
|
+
");</script>"
|
|
999
|
+
);
|
|
1000
|
+
}
|
|
1001
|
+
|
|
967
1002
|
function injectHeadScript(html, script) {
|
|
968
1003
|
if (!script) return html;
|
|
969
1004
|
const headCloseIdx = html.indexOf("</head>");
|
|
@@ -1105,6 +1140,7 @@ async function rewriteMountedResponse(response, basePath, pathname, request) {
|
|
|
1105
1140
|
getSentryClientConfigScript(),
|
|
1106
1141
|
getPostHogClientConfigScript(),
|
|
1107
1142
|
getRealtimeClientConfigScript(),
|
|
1143
|
+
getAppOriginClientConfigScript(),
|
|
1108
1144
|
]
|
|
1109
1145
|
.filter(Boolean)
|
|
1110
1146
|
.join("") || null;
|
|
@@ -17,11 +17,11 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
17
17
|
id?: undefined;
|
|
18
18
|
provider?: undefined;
|
|
19
19
|
} | {
|
|
20
|
+
error?: undefined;
|
|
20
21
|
configured?: undefined;
|
|
21
22
|
connectPath?: undefined;
|
|
22
23
|
url: string;
|
|
23
24
|
id: string;
|
|
24
25
|
provider: string;
|
|
25
|
-
error?: undefined;
|
|
26
26
|
}>;
|
|
27
27
|
export default _default;
|
|
@@ -3,8 +3,10 @@ import { A2AClient, signA2AToken } from "../a2a/client.js";
|
|
|
3
3
|
import { formatLlmCredentialErrorMessage, isLlmCredentialError, LLM_MISSING_CREDENTIALS_ERROR_CODE, } from "../agent/engine/credential-errors.js";
|
|
4
4
|
import { extractThreadMeta } from "../agent/thread-data-builder.js";
|
|
5
5
|
import { getThread, updateThreadData } from "../chat-threads/store.js";
|
|
6
|
+
import { resolveArtifactBaseUrl } from "../server/agent-chat/action-filters-a2a.js";
|
|
6
7
|
import { withConfiguredAppBasePath } from "../server/app-base-path.js";
|
|
7
8
|
import { FRAMEWORK_ROUTE_PREFIX } from "../server/core-routes-plugin.js";
|
|
9
|
+
import { resolveSelfDispatchBaseUrl } from "../server/self-dispatch.js";
|
|
8
10
|
import { claimA2AContinuation, claimA2AContinuationDelivery, claimDueA2AContinuations, failA2AContinuationsForIntegrationTask, failA2AContinuation, finalizeA2ATerminalHistory, getA2AContinuation, getA2AContinuationTaskOutcome, hasOnlyLegacyFailedA2AContinuationsForIntegrationTask, hasPendingConfirmedA2ADeliveryForIntegrationTask, listRecoverableA2AIntegrationTasks, recoverDueA2AContinuationIds, recordA2ATerminalDeliveryReceipt, retainA2AUnconfirmedDeliveryClaim, rescheduleA2AContinuation, saveA2AVerifiedArtifactCheckpoint, } from "./a2a-continuations-store.js";
|
|
9
11
|
import { completeIntegrationCampaignTaskAfterA2A, failDisabledIntegrationCampaignTask, failIntegrationCampaignTaskDeliveryContainment, getIntegrationCampaignForTask, } from "./integration-campaigns-store.js";
|
|
10
12
|
import { dispatchPendingIntegrationTask, isIntegrationDurableDispatchEnabledForTask, } from "./integration-durable-dispatch.js";
|
|
@@ -37,12 +39,17 @@ function logA2AContinuationTransition(event, continuation) {
|
|
|
37
39
|
});
|
|
38
40
|
}
|
|
39
41
|
export async function dispatchA2AContinuation(continuationId, webhookBaseUrl) {
|
|
42
|
+
// Self-dispatch: this POST has to land on the deployment that enqueued the
|
|
43
|
+
// continuation. It used to carry its own chain, which omitted
|
|
44
|
+
// DEPLOY_PRIME_URL — so a deploy preview dispatched to production — and
|
|
45
|
+
// silently fell back to localhost in production, where the request simply
|
|
46
|
+
// never arrives and the continuation is dropped with no error.
|
|
47
|
+
// `WEBHOOK_BASE_URL` stays ahead of it: this runs from a retry job with no
|
|
48
|
+
// inbound request, and a dev tunnel is reachable where the app's own address
|
|
49
|
+
// is not.
|
|
40
50
|
const baseUrl = webhookBaseUrl ||
|
|
41
51
|
process.env.WEBHOOK_BASE_URL ||
|
|
42
|
-
|
|
43
|
-
process.env.URL ||
|
|
44
|
-
process.env.DEPLOY_URL ||
|
|
45
|
-
`http://localhost:${process.env.PORT || 3000}`;
|
|
52
|
+
resolveSelfDispatchBaseUrl();
|
|
46
53
|
const url = `${withConfiguredAppBasePath(baseUrl)}${PROCESSOR_PATH}`;
|
|
47
54
|
const headers = {
|
|
48
55
|
"Content-Type": "application/json",
|
|
@@ -897,11 +904,7 @@ function formatRecoverableArtifactFallbackText(text) {
|
|
|
897
904
|
}
|
|
898
905
|
function formatContinuationArtifactText(text, agentUrl) {
|
|
899
906
|
const expandedText = expandRelativeUrls(text, agentUrl);
|
|
900
|
-
return appendA2AArtifactLinks(expandedText, [{ tool: "call-agent", result: expandedText }], { baseUrl: resolveArtifactBaseUrl() });
|
|
901
|
-
}
|
|
902
|
-
function resolveArtifactBaseUrl() {
|
|
903
|
-
const baseUrl = process.env.APP_URL || process.env.URL || process.env.DEPLOY_URL;
|
|
904
|
-
return baseUrl ? withConfiguredAppBasePath(baseUrl) : undefined;
|
|
907
|
+
return appendA2AArtifactLinks(expandedText, [{ tool: "call-agent", result: expandedText }], { baseUrl: resolveArtifactBaseUrl(undefined) });
|
|
905
908
|
}
|
|
906
909
|
function expandRelativeUrls(text, agentUrl) {
|
|
907
910
|
if (!text || !agentUrl)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { timingSafeEqual } from "node:crypto";
|
|
2
2
|
import { getHeader, readRawBody as h3ReadRawBody } from "h3";
|
|
3
|
+
import { getAppConfig } from "../../app-config/index.js";
|
|
3
4
|
import { getDbExec } from "../../db/client.js";
|
|
4
5
|
import { resolveSecret } from "../../server/credential-provider.js";
|
|
5
6
|
import { sendEmail, isEmailConfigured, getEmailProvider, } from "../../server/email.js";
|
|
@@ -30,7 +31,7 @@ function escapeLike(value) {
|
|
|
30
31
|
* webhook security audit).
|
|
31
32
|
*/
|
|
32
33
|
function shouldRefuseWhenSecretMissing() {
|
|
33
|
-
if (
|
|
34
|
+
if (getAppConfig().integrations.allowUnverifiedWebhooks)
|
|
34
35
|
return false;
|
|
35
36
|
return process.env.NODE_ENV === "production";
|
|
36
37
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getHeader } from "h3";
|
|
2
|
+
import { getAppConfig } from "../../app-config/index.js";
|
|
2
3
|
import { resolveSecret } from "../../server/credential-provider.js";
|
|
3
4
|
import { readBody } from "../../server/h3-helpers.js";
|
|
4
5
|
/** Telegram's max message length */
|
|
@@ -16,7 +17,7 @@ let _telegramUnverifiedWarned = false;
|
|
|
16
17
|
* messages (C2 in the webhook security audit).
|
|
17
18
|
*/
|
|
18
19
|
function shouldRefuseWhenSecretMissing() {
|
|
19
|
-
if (
|
|
20
|
+
if (getAppConfig().integrations.allowUnverifiedWebhooks)
|
|
20
21
|
return false;
|
|
21
22
|
return process.env.NODE_ENV === "production";
|
|
22
23
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getQuery, getHeader, readRawBody as h3ReadRawBody } from "h3";
|
|
2
|
+
import { getAppConfig } from "../../app-config/index.js";
|
|
2
3
|
import { resolveSecret } from "../../server/credential-provider.js";
|
|
3
4
|
/** WhatsApp's max message length */
|
|
4
5
|
const WHATSAPP_MAX_LENGTH = 4096;
|
|
@@ -15,7 +16,7 @@ let _whatsappUnverifiedWarned = false;
|
|
|
15
16
|
* be verified (C2 in the webhook security audit).
|
|
16
17
|
*/
|
|
17
18
|
function shouldRefuseWhenSecretMissing() {
|
|
18
|
-
if (
|
|
19
|
+
if (getAppConfig().integrations.allowUnverifiedWebhooks)
|
|
19
20
|
return false;
|
|
20
21
|
return process.env.NODE_ENV === "production";
|
|
21
22
|
}
|
|
@@ -109,8 +109,13 @@ export declare function handleWebhook(event: H3Event, options: WebhookHandlerOpt
|
|
|
109
109
|
}>;
|
|
110
110
|
/**
|
|
111
111
|
* Resolve the base URL we should dispatch the processor request to.
|
|
112
|
-
*
|
|
113
|
-
*
|
|
112
|
+
*
|
|
113
|
+
* This is self-dispatch — the request has to land on *this* deployment — so it
|
|
114
|
+
* shares one resolver with the rest of the framework rather than keeping its
|
|
115
|
+
* own copy. The copy that used to live here preferred `APP_URL` over the
|
|
116
|
+
* platform's own deploy URLs and did not consult `DEPLOY_PRIME_URL` at all, so
|
|
117
|
+
* on a Netlify deploy preview it dispatched integration work to production
|
|
118
|
+
* while agent background work correctly stayed on the preview.
|
|
114
119
|
*/
|
|
115
120
|
export declare function resolveBaseUrl(event: H3Event): string;
|
|
116
121
|
/**
|
|
@@ -12,10 +12,10 @@ import { buildAssistantMessage, extractThreadMeta, threadDataToEngineMessages, }
|
|
|
12
12
|
import { attachToolSearch } from "../agent/tool-search.js";
|
|
13
13
|
import { createThread, getThread, grantThreadUserShare, setThreadSourceIfMissing, } from "../chat-threads/store.js";
|
|
14
14
|
import { updateThreadData } from "../chat-threads/store.js";
|
|
15
|
-
import { isLocalDatabase } from "../db/client.js";
|
|
16
15
|
import { getOrgA2ASecret, resolveOrgIdForEmail } from "../org/context.js";
|
|
17
16
|
import { withConfiguredAppBasePath } from "../server/app-base-path.js";
|
|
18
17
|
import { runWithRequestContext } from "../server/request-context.js";
|
|
18
|
+
import { resolveSelfDispatchBaseUrl } from "../server/self-dispatch.js";
|
|
19
19
|
import { normalizeReasoningEffortForRequest } from "../shared/reasoning-effort.js";
|
|
20
20
|
import { A2A_CONTINUATION_QUEUED_MARKER } from "./a2a-continuation-marker.js";
|
|
21
21
|
import { reconcileTerminalA2AParentIfDisabled } from "./a2a-continuation-processor.js";
|
|
@@ -360,38 +360,16 @@ async function enqueueAndDispatch(event, incoming, options, handlerStartedAt = D
|
|
|
360
360
|
}
|
|
361
361
|
/**
|
|
362
362
|
* Resolve the base URL we should dispatch the processor request to.
|
|
363
|
-
*
|
|
364
|
-
*
|
|
363
|
+
*
|
|
364
|
+
* This is self-dispatch — the request has to land on *this* deployment — so it
|
|
365
|
+
* shares one resolver with the rest of the framework rather than keeping its
|
|
366
|
+
* own copy. The copy that used to live here preferred `APP_URL` over the
|
|
367
|
+
* platform's own deploy URLs and did not consult `DEPLOY_PRIME_URL` at all, so
|
|
368
|
+
* on a Netlify deploy preview it dispatched integration work to production
|
|
369
|
+
* while agent background work correctly stayed on the preview.
|
|
365
370
|
*/
|
|
366
371
|
export function resolveBaseUrl(event) {
|
|
367
|
-
|
|
368
|
-
process.env.URL ||
|
|
369
|
-
process.env.DEPLOY_URL ||
|
|
370
|
-
process.env.BETTER_AUTH_URL;
|
|
371
|
-
if (fromEnv)
|
|
372
|
-
return withConfiguredAppBasePath(fromEnv);
|
|
373
|
-
if (process.env.NODE_ENV === "production" || !isLocalDatabase()) {
|
|
374
|
-
throw new Error("Integration self-dispatch requires APP_URL, URL, DEPLOY_URL, or BETTER_AUTH_URL in production/shared deployments.");
|
|
375
|
-
}
|
|
376
|
-
try {
|
|
377
|
-
const headers = event.node?.req?.headers ?? event.headers;
|
|
378
|
-
const get = (name) => {
|
|
379
|
-
if (!headers)
|
|
380
|
-
return undefined;
|
|
381
|
-
if (typeof headers.get === "function") {
|
|
382
|
-
return headers.get(name) ?? undefined;
|
|
383
|
-
}
|
|
384
|
-
const lower = String(name).toLowerCase();
|
|
385
|
-
const map = headers;
|
|
386
|
-
return map[name] ?? map[lower];
|
|
387
|
-
};
|
|
388
|
-
const proto = get("x-forwarded-proto") || "http";
|
|
389
|
-
const host = get("host") || `localhost:${process.env.PORT || 3000}`;
|
|
390
|
-
return withConfiguredAppBasePath(`${proto}://${host}`);
|
|
391
|
-
}
|
|
392
|
-
catch {
|
|
393
|
-
return withConfiguredAppBasePath(`http://localhost:${process.env.PORT || 3000}`);
|
|
394
|
-
}
|
|
372
|
+
return resolveSelfDispatchBaseUrl(event);
|
|
395
373
|
}
|
|
396
374
|
/**
|
|
397
375
|
* Run the actual agent loop for a previously-enqueued task. Called by the
|
|
@@ -41,27 +41,27 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
41
41
|
thumbsUpRate: number;
|
|
42
42
|
avgEvalScore: number;
|
|
43
43
|
} | {
|
|
44
|
+
error?: undefined;
|
|
45
|
+
ok?: undefined;
|
|
44
46
|
summary: import("./types.js").TraceSummary;
|
|
45
47
|
spans: import("./types.js").TraceSpan[];
|
|
46
48
|
id?: undefined;
|
|
49
|
+
} | {
|
|
47
50
|
error?: undefined;
|
|
48
51
|
ok?: undefined;
|
|
49
|
-
} | {
|
|
50
52
|
summary?: undefined;
|
|
51
53
|
spans?: undefined;
|
|
52
54
|
id: string;
|
|
53
|
-
error?: undefined;
|
|
54
|
-
ok?: undefined;
|
|
55
55
|
} | {
|
|
56
|
+
ok?: undefined;
|
|
56
57
|
summary?: undefined;
|
|
57
58
|
spans?: undefined;
|
|
58
59
|
id?: undefined;
|
|
59
60
|
error: any;
|
|
60
|
-
ok?: undefined;
|
|
61
61
|
} | {
|
|
62
|
+
error?: undefined;
|
|
62
63
|
summary?: undefined;
|
|
63
64
|
spans?: undefined;
|
|
64
65
|
id?: undefined;
|
|
65
|
-
error?: undefined;
|
|
66
66
|
ok: boolean;
|
|
67
67
|
}>>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getAppConfig } from "../app-config/index.js";
|
|
1
2
|
const LLM_CAPABILITY = {
|
|
2
3
|
id: "llm",
|
|
3
4
|
label: "AI model",
|
|
@@ -382,10 +383,7 @@ function normalizeAppId(value) {
|
|
|
382
383
|
.replace(/^-|-$/g, "") || "app");
|
|
383
384
|
}
|
|
384
385
|
export function resolveOnboardingAppId(explicit) {
|
|
385
|
-
return normalizeAppId(explicit ??
|
|
386
|
-
process.env.AGENT_NATIVE_APP_ID ??
|
|
387
|
-
process.env.APP_ID ??
|
|
388
|
-
process.env.npm_package_name);
|
|
386
|
+
return normalizeAppId(explicit ?? getAppConfig().app.id ?? getAppConfig().app.packageName);
|
|
389
387
|
}
|
|
390
388
|
export function getOnboardingAppProfile(appId) {
|
|
391
389
|
const resolvedId = resolveOnboardingAppId(appId);
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { PROVIDER_ENV_META, PROVIDER_ENV_VARS, } from "../agent/engine/provider-env-vars.js";
|
|
9
9
|
import { detectEngineFromUserSecrets, isAgentEngineSettingConfigured, } from "../agent/engine/registry.js";
|
|
10
|
+
import { getAppConfig } from "../app-config/index.js";
|
|
10
11
|
import { getActiveFileUploadProviderForRequest, registerFileUploadProvider, } from "../file-upload/registry.js";
|
|
11
12
|
import { s3FileUploadProvider } from "../file-upload/s3.js";
|
|
12
13
|
import { canUseDeployCredentialFallbackForRequest, readDeployCredentialEnv, resolveSecret, } from "../server/credential-provider.js";
|
|
@@ -323,10 +324,9 @@ const githubRepositoryStep = {
|
|
|
323
324
|
try {
|
|
324
325
|
const { resolveWorkspaceConnectionCredentialForApp } = await import("../workspace-connections/index.js");
|
|
325
326
|
const result = await resolveWorkspaceConnectionCredentialForApp({
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
"app",
|
|
327
|
+
// Deliberately not `resolveOnboardingAppId()` — that normalizes, and
|
|
328
|
+
// this id is matched against a stored workspace connection grant.
|
|
329
|
+
appId: getAppConfig().app.id ?? getAppConfig().app.packageName ?? "app",
|
|
330
330
|
provider: "github",
|
|
331
331
|
key: "GITHUB_TOKEN",
|
|
332
332
|
userEmail,
|
|
@@ -3,6 +3,11 @@ export declare function registerPrivateBlobProvider(provider: PrivateBlobProvide
|
|
|
3
3
|
export declare function unregisterPrivateBlobProvider(id: string): void;
|
|
4
4
|
export declare function listPrivateBlobProviders(): PrivateBlobProvider[];
|
|
5
5
|
export declare function getActivePrivateBlobProvider(): PrivateBlobProvider | null;
|
|
6
|
+
/**
|
|
7
|
+
* @deprecated Use `defineAppConfig({ privateBlob: { publicUploadFallback } })`
|
|
8
|
+
* instead. This writes the same value into the deprecated layer of the config
|
|
9
|
+
* ladder, so an explicit `defineAppConfig` call now wins over it.
|
|
10
|
+
*/
|
|
6
11
|
export declare function setPrivateBlobPublicUploadFallbackEnabled(enabled: boolean): void;
|
|
7
12
|
export declare function putPrivateBlob(input: PrivateBlobPutInput): Promise<PrivateBlobHandle | null>;
|
|
8
13
|
export declare function readPrivateBlob(handle: PrivateBlobHandle): Promise<PrivateBlobReadResult>;
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
|
|
2
|
+
import { getAppConfig } from "../app-config/index.js";
|
|
3
|
+
import { setAppConfigLayer } from "../app-config/store.js";
|
|
2
4
|
import { uploadFile } from "../file-upload/index.js";
|
|
3
5
|
import { decryptSecretValue, encryptSecretValue, getSecretEncryptionKey, } from "../secrets/crypto.js";
|
|
4
6
|
const PUBLIC_UPLOAD_HANDLE_PREFIX = "public-upload:v1:";
|
|
5
7
|
const PUBLIC_UPLOAD_READ_RETRY_DELAYS_MS = [100, 250, 500];
|
|
6
8
|
const globals = globalThis;
|
|
7
9
|
const providers = (globals.__agentNativePrivateBlobProviders ??= new Map());
|
|
8
|
-
const publicUploadFallbackRef = (globals.__agentNativePrivateBlobPublicUploadFallback ??= {
|
|
9
|
-
enabled: true,
|
|
10
|
-
});
|
|
11
10
|
function toBytes(data) {
|
|
12
11
|
return data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
13
12
|
}
|
|
@@ -171,24 +170,36 @@ export function listPrivateBlobProviders() {
|
|
|
171
170
|
return [...providers.values()];
|
|
172
171
|
}
|
|
173
172
|
export function getActivePrivateBlobProvider() {
|
|
173
|
+
const selected = getAppConfig().privateBlob.provider;
|
|
174
|
+
if (selected) {
|
|
175
|
+
const provider = providers.get(selected);
|
|
176
|
+
if (!provider) {
|
|
177
|
+
throw new Error(`Private blob provider "${selected}" is selected in app config but no provider with that id is registered`);
|
|
178
|
+
}
|
|
179
|
+
return provider;
|
|
180
|
+
}
|
|
174
181
|
for (const provider of providers.values()) {
|
|
175
182
|
if (provider.isConfigured())
|
|
176
183
|
return provider;
|
|
177
184
|
}
|
|
178
185
|
return null;
|
|
179
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* @deprecated Use `defineAppConfig({ privateBlob: { publicUploadFallback } })`
|
|
189
|
+
* instead. This writes the same value into the deprecated layer of the config
|
|
190
|
+
* ladder, so an explicit `defineAppConfig` call now wins over it.
|
|
191
|
+
*/
|
|
180
192
|
export function setPrivateBlobPublicUploadFallbackEnabled(enabled) {
|
|
181
|
-
|
|
193
|
+
setAppConfigLayer("legacy", {
|
|
194
|
+
privateBlob: { publicUploadFallback: enabled },
|
|
195
|
+
});
|
|
182
196
|
}
|
|
183
197
|
export async function putPrivateBlob(input) {
|
|
184
198
|
const provider = getActivePrivateBlobProvider();
|
|
185
199
|
if (provider)
|
|
186
200
|
return provider.put(input);
|
|
187
|
-
if (!
|
|
201
|
+
if (!getAppConfig().privateBlob.publicUploadFallback)
|
|
188
202
|
return null;
|
|
189
|
-
if (process.env.AGENT_NATIVE_PRIVATE_BLOB_PUBLIC_UPLOAD_FALLBACK === "0") {
|
|
190
|
-
return null;
|
|
191
|
-
}
|
|
192
203
|
return putViaEncryptedPublicUpload(input);
|
|
193
204
|
}
|
|
194
205
|
export async function readPrivateBlob(handle) {
|
|
@@ -75,7 +75,8 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
|
|
|
75
75
|
user: "user";
|
|
76
76
|
}>>;
|
|
77
77
|
}, z.core.$strip>>, {
|
|
78
|
-
|
|
78
|
+
message?: undefined;
|
|
79
|
+
id?: undefined;
|
|
79
80
|
deleted?: undefined;
|
|
80
81
|
providers: {
|
|
81
82
|
id: string;
|
|
@@ -88,46 +89,45 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
|
|
|
88
89
|
}[];
|
|
89
90
|
count: number;
|
|
90
91
|
provider?: undefined;
|
|
92
|
+
found?: undefined;
|
|
91
93
|
registered?: undefined;
|
|
92
|
-
id?: undefined;
|
|
93
94
|
label?: undefined;
|
|
94
|
-
message?: undefined;
|
|
95
95
|
} | {
|
|
96
|
+
message?: undefined;
|
|
97
|
+
count?: undefined;
|
|
98
|
+
id?: undefined;
|
|
96
99
|
deleted?: undefined;
|
|
97
100
|
providers?: undefined;
|
|
98
|
-
count?: undefined;
|
|
99
101
|
found: boolean;
|
|
100
102
|
provider: import("../custom-registry.js").CustomProviderConfig;
|
|
101
103
|
registered?: undefined;
|
|
102
|
-
id?: undefined;
|
|
103
104
|
label?: undefined;
|
|
104
|
-
message?: undefined;
|
|
105
105
|
} | {
|
|
106
|
+
message?: undefined;
|
|
107
|
+
count?: undefined;
|
|
106
108
|
deleted?: undefined;
|
|
107
109
|
providers?: undefined;
|
|
108
|
-
count?: undefined;
|
|
109
110
|
provider?: undefined;
|
|
110
111
|
found: boolean;
|
|
111
112
|
id: string;
|
|
112
113
|
registered?: undefined;
|
|
113
114
|
label?: undefined;
|
|
114
|
-
message?: undefined;
|
|
115
115
|
} | {
|
|
116
|
-
|
|
117
|
-
providers?: undefined;
|
|
116
|
+
message?: undefined;
|
|
118
117
|
count?: undefined;
|
|
118
|
+
providers?: undefined;
|
|
119
119
|
provider?: undefined;
|
|
120
|
+
found?: undefined;
|
|
120
121
|
deleted: boolean;
|
|
121
122
|
id: string;
|
|
122
123
|
registered?: undefined;
|
|
123
124
|
label?: undefined;
|
|
124
|
-
message?: undefined;
|
|
125
125
|
} | {
|
|
126
|
-
|
|
126
|
+
count?: undefined;
|
|
127
127
|
deleted?: undefined;
|
|
128
128
|
providers?: undefined;
|
|
129
|
-
count?: undefined;
|
|
130
129
|
provider?: undefined;
|
|
130
|
+
found?: undefined;
|
|
131
131
|
registered: boolean;
|
|
132
132
|
id: string;
|
|
133
133
|
label: string;
|