@agent-native/core 0.209.1 → 0.209.2-nightly-20261015213030
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/agent/actions/list-model-providers.js +15 -2
- package/dist/agent/app-model-defaults.d.ts +9 -13
- package/dist/agent/app-model-defaults.js +23 -5
- package/dist/agent/default-agent-engine.d.ts +5 -3
- package/dist/agent/default-agent-engine.js +38 -8
- package/dist/agent/durable-background.d.ts +2 -0
- package/dist/agent/durable-background.js +2 -0
- package/dist/agent/engine/registry.js +6 -0
- package/dist/agent/production-agent.js +58 -5
- package/dist/automations/service.d.ts +2 -0
- package/dist/automations/service.js +4 -1
- package/dist/client/analytics.js +48 -1
- package/dist/client/application-state.js +7 -2
- package/dist/client/chat/agentkit-protocol.js +12 -3
- package/dist/client/client-bootstrap.js +2 -0
- package/dist/client/problem-report.d.ts +11 -0
- package/dist/client/problem-report.js +19 -0
- package/dist/client/recorder.d.ts +88 -0
- package/dist/client/recorder.js +585 -0
- package/dist/client/route-chunk-recovery.js +4 -1
- package/dist/client/sign-out.js +2 -0
- package/dist/client/use-action.js +3 -0
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/integrations/google-docs-poller.js +12 -5
- package/dist/integrations/plugin.js +86 -19
- package/dist/integrations/request-scope.d.ts +16 -0
- package/dist/integrations/request-scope.js +27 -0
- package/dist/integrations/webhook-handler.d.ts +2 -0
- package/dist/integrations/webhook-handler.js +38 -18
- package/dist/jobs/background-automation-runner.d.ts +2 -0
- package/dist/jobs/background-automation-runner.js +25 -2
- package/dist/jobs/scheduler.js +36 -22
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/org/context.d.ts +12 -0
- package/dist/org/context.js +26 -11
- package/dist/org/index.d.ts +1 -1
- package/dist/problem-report/actions/read-problem-report.d.ts +27 -0
- package/dist/problem-report/actions/read-problem-report.js +103 -0
- package/dist/problem-report/actions/save-problem-report.d.ts +35 -0
- package/dist/problem-report/actions/save-problem-report.js +36 -0
- package/dist/problem-report/format.d.ts +7 -0
- package/dist/problem-report/format.js +110 -0
- package/dist/problem-report/schema.d.ts +41 -0
- package/dist/problem-report/schema.js +34 -0
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
- package/dist/provider-api/actions/provider-api.d.ts +14 -14
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/scripts/agent-engines/manage-agent-engine.js +9 -4
- package/dist/scripts/agent-engines/set-agent-engine.js +7 -1
- package/dist/server/action-discovery.js +11 -0
- package/dist/server/action-routes.js +2 -0
- package/dist/server/agent-chat-ai-setup.d.ts +2 -3
- package/dist/server/agent-chat-ai-setup.js +18 -4
- package/dist/server/agent-chat-plugin.js +97 -22
- package/dist/server/agent-chat-stream.d.ts +17 -5
- package/dist/server/agent-chat-stream.js +15 -0
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-engine-default-model-route.d.ts +2 -2
- package/dist/server/agent-engine-default-model-route.js +39 -6
- package/dist/server/agent-engine-ollama-models-route.d.ts +2 -2
- package/dist/server/agent-engine-status-cache.d.ts +4 -0
- package/dist/server/agent-engine-status-cache.js +2 -0
- package/dist/server/agent-run-context.d.ts +9 -0
- package/dist/server/agent-run-context.js +82 -17
- package/dist/server/builder-browser.js +18 -3
- package/dist/server/chatgpt-subscription-oauth.js +12 -17
- package/dist/server/core-routes-plugin.d.ts +1 -0
- package/dist/server/core-routes-plugin.js +46 -9
- package/dist/server/loopback.d.ts +1 -0
- package/dist/server/loopback.js +30 -0
- package/dist/server/origin-allowlist.d.ts +2 -0
- package/dist/server/origin-allowlist.js +13 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/request-context.d.ts +4 -0
- package/dist/templates/chat/app/components/layout/Sidebar.tsx +11 -1
- package/dist/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +2 -2
- package/dist/templates/factory/.agents/skills/review-latest-feedback/references/channel-inventory.md +31 -0
- package/dist/triggers/dispatcher.js +117 -31
- package/docs/content/recorder.mdx +259 -0
- package/docs/content/template-clips-developers.mdx +9 -8
- package/docs/content/template-clips-features.mdx +8 -7
- package/package.json +5 -3
- package/src/templates/chat/app/components/layout/Sidebar.tsx +11 -1
- package/src/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +2 -2
- package/src/templates/factory/.agents/skills/review-latest-feedback/references/channel-inventory.md +31 -0
|
@@ -15,6 +15,7 @@ import { agentNativeApiDisabledReason, assertAgentNativeApiEnabled, } from "./ap
|
|
|
15
15
|
import { getBrowserTabId } from "./browser-tab-id.js";
|
|
16
16
|
import { clientBuildId, clientCompatibilityVersion, reloadForClientCompatibilityMismatch, } from "./build-compatibility.js";
|
|
17
17
|
import { ensureEmbedAuthFetchInterceptor, isEmbedAuthActive, } from "./embed-auth.js";
|
|
18
|
+
import { recordActionStart } from "./recorder.js";
|
|
18
19
|
import { currentRouteTemplate } from "./route-template.js";
|
|
19
20
|
import { recheckSessionAfterUnauthorized } from "./use-session.js";
|
|
20
21
|
function actionPrefix() {
|
|
@@ -490,6 +491,7 @@ async function actionFetch(name, method, params, options) {
|
|
|
490
491
|
const hiddenEpochAtStart = pageHiddenEpoch;
|
|
491
492
|
const hiddenAtStart = typeof document !== "undefined" && document.visibilityState !== "visible";
|
|
492
493
|
const timeoutMs = options?.timeoutMs ?? DEFAULT_ACTION_TIMEOUT_MS;
|
|
494
|
+
const recordActionEnd = recordActionStart(name, method);
|
|
493
495
|
let response;
|
|
494
496
|
let responseAt;
|
|
495
497
|
let error;
|
|
@@ -509,6 +511,7 @@ async function actionFetch(name, method, params, options) {
|
|
|
509
511
|
}
|
|
510
512
|
finally {
|
|
511
513
|
try {
|
|
514
|
+
recordActionEnd({ error, response, signal: options?.signal });
|
|
512
515
|
const completedAt = actionTelemetryNow();
|
|
513
516
|
const durationMs = Math.max(0, completedAt - startedAt);
|
|
514
517
|
const sampling = getActionResponseSampling(error, durationMs, response);
|
package/dist/collab/routes.d.ts
CHANGED
|
@@ -13,8 +13,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
|
|
|
13
13
|
};
|
|
14
14
|
}>>;
|
|
15
15
|
export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
16
|
-
error: string;
|
|
17
16
|
ok?: undefined;
|
|
17
|
+
error: string;
|
|
18
18
|
} | {
|
|
19
19
|
error?: undefined;
|
|
20
20
|
ok: boolean;
|
|
@@ -33,9 +33,9 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
33
33
|
idempotencyKey: string;
|
|
34
34
|
deleted: boolean;
|
|
35
35
|
} | {
|
|
36
|
+
id?: undefined;
|
|
36
37
|
error: string;
|
|
37
38
|
url?: undefined;
|
|
38
|
-
id?: undefined;
|
|
39
39
|
provider?: undefined;
|
|
40
40
|
configured?: undefined;
|
|
41
41
|
} | {
|
|
@@ -45,8 +45,8 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
45
45
|
configured?: undefined;
|
|
46
46
|
error?: undefined;
|
|
47
47
|
} | {
|
|
48
|
-
url?: undefined;
|
|
49
48
|
id?: undefined;
|
|
49
|
+
url?: undefined;
|
|
50
50
|
provider?: undefined;
|
|
51
51
|
error: string;
|
|
52
52
|
configured: boolean;
|
|
@@ -7,12 +7,12 @@ import { startRun } from "../agent/run-manager.js";
|
|
|
7
7
|
import { buildAssistantMessage, extractThreadMeta, } from "../agent/thread-data-builder.js";
|
|
8
8
|
import { attachToolSearch } from "../agent/tool-search.js";
|
|
9
9
|
import { createThread, getThread, setThreadSourceIfMissing, updateThreadData, } from "../chat-threads/store.js";
|
|
10
|
-
import { resolveOrgIdForEmail } from "../org/context.js";
|
|
11
10
|
import { startIntervalJob, } from "../server/interval-job.js";
|
|
12
11
|
import { runWithRequestContext } from "../server/request-context.js";
|
|
13
12
|
import { getServiceAccountAccessToken, getServiceAccountEmail, getStartPageToken, googleDocsAdapter, listChanges, listDocComments, } from "./adapters/google-docs.js";
|
|
14
13
|
import { getIntegrationConfig, integrationConfigWriteEpoch, saveIntegrationConfig, saveIntegrationConfigIfUnchanged, } from "./config-store.js";
|
|
15
14
|
import { createGoogleDocsChannelAuth, verifyGoogleDocsChannel, } from "./google-docs-webhook.js";
|
|
15
|
+
import { integrationRequestContext, resolveIntegrationRequestScope, } from "./request-scope.js";
|
|
16
16
|
import { getThreadMapping, saveThreadMapping } from "./thread-mapping-store.js";
|
|
17
17
|
const PLATFORM = "google-docs";
|
|
18
18
|
const DEFAULT_TRIGGER = "@agent";
|
|
@@ -466,6 +466,10 @@ export async function handlePushNotification() {
|
|
|
466
466
|
}
|
|
467
467
|
async function processComment(fileId, commentId, text, senderName, options, existingThreadId) {
|
|
468
468
|
const adapter = googleDocsAdapter();
|
|
469
|
+
const requestScope = await resolveIntegrationRequestScope({
|
|
470
|
+
ownerEmail: options.ownerEmail,
|
|
471
|
+
});
|
|
472
|
+
const requestContext = integrationRequestContext(requestScope);
|
|
469
473
|
const key = commentKey(fileId, commentId);
|
|
470
474
|
const incoming = {
|
|
471
475
|
platform: PLATFORM,
|
|
@@ -481,10 +485,10 @@ async function processComment(fileId, commentId, text, senderName, options, exis
|
|
|
481
485
|
};
|
|
482
486
|
let threadId = existingThreadId;
|
|
483
487
|
if (!threadId) {
|
|
484
|
-
const thread = await createThread(options.ownerEmail, {
|
|
488
|
+
const thread = await runWithRequestContext({ userEmail: options.ownerEmail, ...requestContext }, () => createThread(options.ownerEmail, {
|
|
485
489
|
title: `Google Doc: ${senderName}`,
|
|
486
490
|
source,
|
|
487
|
-
});
|
|
491
|
+
}));
|
|
488
492
|
await saveThreadMapping(PLATFORM, key, thread.id, { fileId, commentId });
|
|
489
493
|
threadId = thread.id;
|
|
490
494
|
}
|
|
@@ -532,9 +536,12 @@ async function processComment(fileId, commentId, text, senderName, options, exis
|
|
|
532
536
|
const tools = filterInitialEngineTools(availableTools, options.initialToolNames);
|
|
533
537
|
const runId = `gdocs-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
534
538
|
const capturedThreadId = threadId;
|
|
535
|
-
const orgId = (await resolveOrgIdForEmail(options.ownerEmail)) ?? undefined;
|
|
536
539
|
startRun(runId, capturedThreadId, async (send, signal) => {
|
|
537
|
-
await runWithRequestContext({
|
|
540
|
+
await runWithRequestContext({
|
|
541
|
+
userEmail: options.ownerEmail,
|
|
542
|
+
...requestContext,
|
|
543
|
+
isIntegrationCaller: true,
|
|
544
|
+
}, () => runAgentLoopDirectWithSoftTimeout({
|
|
538
545
|
engine,
|
|
539
546
|
model: options.model,
|
|
540
547
|
systemPrompt: options.systemPrompt,
|
|
@@ -4,7 +4,7 @@ import { AGENT_BACKGROUND_PROCESSOR_FIELD, AGENT_BACKGROUND_PROCESSOR_INTEGRATIO
|
|
|
4
4
|
import { abortRun } from "../agent/run-manager.js";
|
|
5
5
|
import { AppConfigurationError, getAppConfig } from "../app-config/index.js";
|
|
6
6
|
import { isServerlessRuntime } from "../db/client.js";
|
|
7
|
-
import { getOrgContext
|
|
7
|
+
import { getOrgContext } from "../org/context.js";
|
|
8
8
|
import { loadResourcesForPrompt } from "../server/agent-chat-plugin.js";
|
|
9
9
|
import { withConfiguredAppBasePath } from "../server/app-base-path.js";
|
|
10
10
|
import { getSession } from "../server/auth.js";
|
|
@@ -49,6 +49,7 @@ import { startRemotePushDeliveryJob } from "./remote-push-delivery-job.js";
|
|
|
49
49
|
import { listRemotePushNotificationsForOwner, listRemotePushRegistrationsForOwner, queueRemotePushNotifications, toPublicRemotePushRegistration, unregisterRemotePushRegistrationForOwner, upsertRemotePushRegistration, } from "./remote-push-store.js";
|
|
50
50
|
import { startRemoteCommandsRetryJob } from "./remote-retry-job.js";
|
|
51
51
|
import { insertRemoteRunEvents, listRemoteRunEvents, } from "./remote-run-events-store.js";
|
|
52
|
+
import { integrationRequestContext, resolveIntegrationRequestScope, } from "./request-scope.js";
|
|
52
53
|
import { listIntegrationScopes, saveIntegrationScope } from "./scope-store.js";
|
|
53
54
|
import { buildSlackAgentManifest } from "./slack-manifest.js";
|
|
54
55
|
import { assertSlackInstallAccess, buildSlackAuthorizeUrl, exchangeSlackOAuthCode, slackOAuthResponseToInstallation, testSlackAuth, } from "./slack-oauth.js";
|
|
@@ -579,7 +580,7 @@ export function createIntegrationsPlugin(options) {
|
|
|
579
580
|
.then(operation)
|
|
580
581
|
.finally(release);
|
|
581
582
|
};
|
|
582
|
-
const createGoogleDocsPollerOptions = (requestBaseUrl) => {
|
|
583
|
+
const createGoogleDocsPollerOptions = (ownerEmail, requestBaseUrl) => {
|
|
583
584
|
const configuredBaseUrl = getAppConfig().integrations.webhookBaseUrl;
|
|
584
585
|
const baseUrl = configuredBaseUrl || requestBaseUrl;
|
|
585
586
|
const webhookUrl = baseUrl
|
|
@@ -591,7 +592,7 @@ export function createIntegrationsPlugin(options) {
|
|
|
591
592
|
initialToolNames,
|
|
592
593
|
model: model ?? "",
|
|
593
594
|
apiKey: getApiKey(),
|
|
594
|
-
ownerEmail
|
|
595
|
+
ownerEmail,
|
|
595
596
|
webhookUrl,
|
|
596
597
|
};
|
|
597
598
|
};
|
|
@@ -599,12 +600,22 @@ export function createIntegrationsPlugin(options) {
|
|
|
599
600
|
adapters,
|
|
600
601
|
webhookUrl: (baseUrl, platform) => `${baseUrl}${P}/${platform}/webhook`,
|
|
601
602
|
async setEnabled(platform, enabled, { actorEmail, baseUrl }) {
|
|
602
|
-
|
|
603
|
-
|
|
603
|
+
if (platform === "google-docs") {
|
|
604
|
+
if (enabled) {
|
|
605
|
+
const ownerEmail = actorEmail?.trim();
|
|
606
|
+
if (!ownerEmail) {
|
|
607
|
+
throw new Error("Google Docs requires a signed-in owner to start polling.");
|
|
608
|
+
}
|
|
609
|
+
await saveIntegrationConfig(platform, { enabled }, "default", ownerEmail);
|
|
610
|
+
await runGoogleDocsPollerTransition(() => startGoogleDocsPoller(createGoogleDocsPollerOptions(ownerEmail, baseUrl)));
|
|
611
|
+
}
|
|
612
|
+
else {
|
|
613
|
+
await saveIntegrationConfig(platform, { enabled }, "default", actorEmail);
|
|
614
|
+
await runGoogleDocsPollerTransition(stopGoogleDocsPoller);
|
|
615
|
+
}
|
|
604
616
|
return;
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
: stopGoogleDocsPoller);
|
|
617
|
+
}
|
|
618
|
+
await saveIntegrationConfig(platform, { enabled }, "default", actorEmail);
|
|
608
619
|
},
|
|
609
620
|
async registerWebhook(platform, baseUrl) {
|
|
610
621
|
if (platform !== "telegram") {
|
|
@@ -715,15 +726,26 @@ export function createIntegrationsPlugin(options) {
|
|
|
715
726
|
return null;
|
|
716
727
|
}
|
|
717
728
|
const orgCtx = await getOrgContext(event).catch(() => null);
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
729
|
+
try {
|
|
730
|
+
return {
|
|
731
|
+
ownerEmail: session.email,
|
|
732
|
+
...(await resolveIntegrationRequestScope({
|
|
733
|
+
ownerEmail: session.email,
|
|
734
|
+
orgId: orgCtx?.orgId ?? session.orgId ?? null,
|
|
735
|
+
principalType: "user",
|
|
736
|
+
})),
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
catch (error) {
|
|
740
|
+
console.error("[integrations] Could not resolve signed-in user's organization scope:", error);
|
|
741
|
+
setResponseStatus(event, 503);
|
|
742
|
+
return null;
|
|
743
|
+
}
|
|
722
744
|
}
|
|
723
745
|
function toCredentialContext(ctx, opts) {
|
|
724
746
|
return {
|
|
725
747
|
userEmail: ctx.ownerEmail,
|
|
726
|
-
...(ctx
|
|
748
|
+
...integrationRequestContext(ctx),
|
|
727
749
|
...(opts?.isIntegrationCaller ? { isIntegrationCaller: true } : {}),
|
|
728
750
|
};
|
|
729
751
|
}
|
|
@@ -731,10 +753,12 @@ export function createIntegrationsPlugin(options) {
|
|
|
731
753
|
const ownerEmail = typeof config?.owner === "string" ? config.owner.trim() : "";
|
|
732
754
|
if (!ownerEmail)
|
|
733
755
|
return null;
|
|
734
|
-
const orgId = await resolveOrgIdForEmail(ownerEmail).catch(() => null);
|
|
735
756
|
return {
|
|
736
757
|
userEmail: ownerEmail,
|
|
737
|
-
...(
|
|
758
|
+
...integrationRequestContext(await resolveIntegrationRequestScope({
|
|
759
|
+
ownerEmail,
|
|
760
|
+
principalType: "user",
|
|
761
|
+
})),
|
|
738
762
|
isIntegrationCaller: true,
|
|
739
763
|
};
|
|
740
764
|
}
|
|
@@ -1632,9 +1656,24 @@ export function createIntegrationsPlugin(options) {
|
|
|
1632
1656
|
setResponseStatus(event, 404);
|
|
1633
1657
|
return { error: "Unknown platform" };
|
|
1634
1658
|
}
|
|
1659
|
+
const principalType = taskPayload.kind === "system-notice"
|
|
1660
|
+
? "service"
|
|
1661
|
+
: "principalType" in taskPayload
|
|
1662
|
+
? (taskPayload.principalType ?? "user")
|
|
1663
|
+
: "user";
|
|
1664
|
+
const orgScope = ("orgScope" in taskPayload ? taskPayload.orgScope : undefined) ??
|
|
1665
|
+
(task.orgId === null && principalType === "user"
|
|
1666
|
+
? "personal"
|
|
1667
|
+
: undefined);
|
|
1668
|
+
const requestScope = await resolveIntegrationRequestScope({
|
|
1669
|
+
ownerEmail: task.ownerEmail,
|
|
1670
|
+
orgId: task.orgId,
|
|
1671
|
+
orgScope,
|
|
1672
|
+
principalType,
|
|
1673
|
+
});
|
|
1635
1674
|
const processingResult = await runWithRequestContext({
|
|
1636
1675
|
userEmail: task.ownerEmail,
|
|
1637
|
-
...(
|
|
1676
|
+
...integrationRequestContext(requestScope),
|
|
1638
1677
|
isIntegrationCaller: true,
|
|
1639
1678
|
}, async () => {
|
|
1640
1679
|
if (!campaignContinuation &&
|
|
@@ -2283,9 +2322,22 @@ export function createIntegrationsPlugin(options) {
|
|
|
2283
2322
|
error: err instanceof Error ? err.message : "Slack access denied",
|
|
2284
2323
|
};
|
|
2285
2324
|
}
|
|
2325
|
+
let requestScope;
|
|
2326
|
+
try {
|
|
2327
|
+
requestScope = await resolveIntegrationRequestScope({
|
|
2328
|
+
ownerEmail: session.email,
|
|
2329
|
+
orgId: org?.orgId ?? session.orgId ?? null,
|
|
2330
|
+
principalType: "user",
|
|
2331
|
+
});
|
|
2332
|
+
}
|
|
2333
|
+
catch (error) {
|
|
2334
|
+
console.error("[slack] Could not resolve install scope:", error);
|
|
2335
|
+
setResponseStatus(event, 503);
|
|
2336
|
+
return { error: "Could not verify your account scope." };
|
|
2337
|
+
}
|
|
2286
2338
|
return await runWithRequestContext({
|
|
2287
2339
|
userEmail: session.email,
|
|
2288
|
-
|
|
2340
|
+
...integrationRequestContext(requestScope),
|
|
2289
2341
|
}, async () => {
|
|
2290
2342
|
const clientId = await resolveSecret("SLACK_CLIENT_ID");
|
|
2291
2343
|
const clientSecret = await resolveSecret("SLACK_CLIENT_SECRET");
|
|
@@ -2349,9 +2401,14 @@ export function createIntegrationsPlugin(options) {
|
|
|
2349
2401
|
orgId: org?.orgId ?? session.orgId ?? null,
|
|
2350
2402
|
orgRole: org?.role ?? null,
|
|
2351
2403
|
});
|
|
2404
|
+
const requestScope = await resolveIntegrationRequestScope({
|
|
2405
|
+
ownerEmail: access.ownerEmail,
|
|
2406
|
+
orgId: access.orgId,
|
|
2407
|
+
principalType: "user",
|
|
2408
|
+
});
|
|
2352
2409
|
return await runWithRequestContext({
|
|
2353
2410
|
userEmail: access.ownerEmail,
|
|
2354
|
-
|
|
2411
|
+
...integrationRequestContext(requestScope),
|
|
2355
2412
|
}, async () => {
|
|
2356
2413
|
const clientId = await resolveSecret("SLACK_CLIENT_ID");
|
|
2357
2414
|
const clientSecret = await resolveSecret("SLACK_CLIENT_SECRET");
|
|
@@ -2694,7 +2751,17 @@ export function createIntegrationsPlugin(options) {
|
|
|
2694
2751
|
startRemotePushDeliveryJob();
|
|
2695
2752
|
if (adapterMap.has("google-docs")) {
|
|
2696
2753
|
setTimeout(() => {
|
|
2697
|
-
void runGoogleDocsPollerTransition(() =>
|
|
2754
|
+
void runGoogleDocsPollerTransition(async () => {
|
|
2755
|
+
const config = await getIntegrationConfig("google-docs");
|
|
2756
|
+
const ownerEmail = config?.owner?.trim();
|
|
2757
|
+
if (!config?.configData?.enabled)
|
|
2758
|
+
return;
|
|
2759
|
+
if (!ownerEmail) {
|
|
2760
|
+
console.error("[google-docs] Cannot start poller without a configured owner");
|
|
2761
|
+
return;
|
|
2762
|
+
}
|
|
2763
|
+
await startGoogleDocsPoller(createGoogleDocsPollerOptions(ownerEmail));
|
|
2764
|
+
});
|
|
2698
2765
|
}, 2000);
|
|
2699
2766
|
}
|
|
2700
2767
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type IntegrationRequestScope = {
|
|
2
|
+
orgId: string | null;
|
|
3
|
+
orgScope?: "personal";
|
|
4
|
+
defaultAgentEngineScope?: "deployment";
|
|
5
|
+
};
|
|
6
|
+
export declare function resolveIntegrationRequestScope(input: {
|
|
7
|
+
ownerEmail: string;
|
|
8
|
+
orgId?: string | null;
|
|
9
|
+
orgScope?: "personal";
|
|
10
|
+
principalType?: "user" | "service";
|
|
11
|
+
}): Promise<IntegrationRequestScope>;
|
|
12
|
+
export declare function integrationRequestContext(scope: IntegrationRequestScope): {
|
|
13
|
+
orgId?: string;
|
|
14
|
+
orgScope?: "personal";
|
|
15
|
+
defaultAgentEngineScope?: "deployment";
|
|
16
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { resolveOrgScopeForEmail } from "../org/context.js";
|
|
2
|
+
export async function resolveIntegrationRequestScope(input) {
|
|
3
|
+
const explicitOrgId = input.orgId?.trim();
|
|
4
|
+
if (explicitOrgId)
|
|
5
|
+
return { orgId: explicitOrgId };
|
|
6
|
+
if (input.orgScope === "personal") {
|
|
7
|
+
return { orgId: null, orgScope: "personal" };
|
|
8
|
+
}
|
|
9
|
+
if (input.principalType === "service") {
|
|
10
|
+
return { orgId: null, defaultAgentEngineScope: "deployment" };
|
|
11
|
+
}
|
|
12
|
+
const scope = await resolveOrgScopeForEmail(input.ownerEmail);
|
|
13
|
+
if (scope.status === "organization")
|
|
14
|
+
return { orgId: scope.orgId };
|
|
15
|
+
if (scope.status === "personal")
|
|
16
|
+
return { orgId: null, orgScope: "personal" };
|
|
17
|
+
throw new Error("The integration owner's organization scope could not be resolved.");
|
|
18
|
+
}
|
|
19
|
+
export function integrationRequestContext(scope) {
|
|
20
|
+
return {
|
|
21
|
+
...(scope.orgId ? { orgId: scope.orgId } : {}),
|
|
22
|
+
...(scope.orgScope ? { orgScope: scope.orgScope } : {}),
|
|
23
|
+
...(scope.defaultAgentEngineScope
|
|
24
|
+
? { defaultAgentEngineScope: scope.defaultAgentEngineScope }
|
|
25
|
+
: {}),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -8,6 +8,8 @@ export type IntegrationResponseDeliveryTaskPayload = {
|
|
|
8
8
|
kind: "response-delivery";
|
|
9
9
|
incoming: IncomingMessage;
|
|
10
10
|
message: OutgoingMessage;
|
|
11
|
+
principalType?: "user" | "service";
|
|
12
|
+
orgScope?: "personal";
|
|
11
13
|
placeholderRef?: string;
|
|
12
14
|
strictTargetRef?: boolean;
|
|
13
15
|
internalThreadId?: string;
|
|
@@ -12,7 +12,7 @@ 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 { getOrgA2ASecret
|
|
15
|
+
import { getOrgA2ASecret } from "../org/context.js";
|
|
16
16
|
import { withConfiguredAppBasePath } from "../server/app-base-path.js";
|
|
17
17
|
import { getAppProductionUrl } from "../server/app-url.js";
|
|
18
18
|
import { runWithRequestContext } from "../server/request-context.js";
|
|
@@ -26,6 +26,7 @@ import { claimIntegrationCampaignDeliveryForTask, claimIntegrationCampaign, comp
|
|
|
26
26
|
import { dispatchPendingIntegrationTask, integrationDispatchScopeValue, } from "./integration-durable-dispatch.js";
|
|
27
27
|
import { loadIntegrationMemoryPrompt } from "./integration-memory.js";
|
|
28
28
|
import { insertPendingTask, isDuplicateEventError, stageTaskDeliveryPayload, } from "./pending-tasks-store.js";
|
|
29
|
+
import { integrationRequestContext, resolveIntegrationRequestScope, } from "./request-scope.js";
|
|
29
30
|
import { integrationScopeSubjectKey } from "./scope-store.js";
|
|
30
31
|
import { getThreadMapping, saveThreadMapping } from "./thread-mapping-store.js";
|
|
31
32
|
import { listIntegrationUsageBudgets, releaseIntegrationUsageBudget, reserveIntegrationUsageBudget, settleIntegrationUsageBudget, } from "./usage-budget-store.js";
|
|
@@ -221,15 +222,12 @@ function immediateWebhookResponse(adapter, incoming) {
|
|
|
221
222
|
}
|
|
222
223
|
async function enqueueAndDispatch(event, incoming, options, handlerStartedAt = Date.now()) {
|
|
223
224
|
const taskId = crypto.randomUUID();
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
orgId = null;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
225
|
+
const requestScope = await resolveIntegrationRequestScope({
|
|
226
|
+
ownerEmail: options.ownerEmail,
|
|
227
|
+
orgId: options.orgId,
|
|
228
|
+
principalType: options.principalType,
|
|
229
|
+
});
|
|
230
|
+
const orgId = requestScope.orgId;
|
|
233
231
|
let placeholderRef;
|
|
234
232
|
try {
|
|
235
233
|
if (options.adapter.postProcessingPlaceholder) {
|
|
@@ -246,6 +244,7 @@ async function enqueueAndDispatch(event, incoming, options, handlerStartedAt = D
|
|
|
246
244
|
incoming,
|
|
247
245
|
placeholderRef,
|
|
248
246
|
principalType: options.principalType ?? "user",
|
|
247
|
+
...(requestScope.orgScope ? { orgScope: requestScope.orgScope } : {}),
|
|
249
248
|
});
|
|
250
249
|
await insertPendingTask({
|
|
251
250
|
id: taskId,
|
|
@@ -294,6 +293,9 @@ export function resolveBaseUrl(event) {
|
|
|
294
293
|
}
|
|
295
294
|
export async function processIntegrationTask(task, options, campaignOptions) {
|
|
296
295
|
const parsed = JSON.parse(task.payload);
|
|
296
|
+
const principalType = parsed.principalType ?? options.principalType ?? "user";
|
|
297
|
+
const orgScope = parsed.orgScope ??
|
|
298
|
+
(task.orgId === null && principalType === "user" ? "personal" : undefined);
|
|
297
299
|
if (!campaignOptions?.continuationInvocation) {
|
|
298
300
|
await recordInboundIntegrationAudit(task, parsed.incoming);
|
|
299
301
|
}
|
|
@@ -301,8 +303,9 @@ export async function processIntegrationTask(task, options, campaignOptions) {
|
|
|
301
303
|
taskId: task.id,
|
|
302
304
|
attempts: task.attempts,
|
|
303
305
|
placeholderRef: parsed.placeholderRef,
|
|
304
|
-
orgId: task.orgId
|
|
305
|
-
|
|
306
|
+
orgId: task.orgId,
|
|
307
|
+
orgScope,
|
|
308
|
+
principalType,
|
|
306
309
|
durableCampaign: campaignOptions?.enabled === true,
|
|
307
310
|
});
|
|
308
311
|
}
|
|
@@ -341,6 +344,14 @@ async function recordInboundIntegrationAudit(task, incoming) {
|
|
|
341
344
|
}
|
|
342
345
|
async function processIncomingMessage(incoming, options, opts = {}) {
|
|
343
346
|
const { adapter, systemPrompt, actions, initialToolNames, model, apiKey, ownerEmail, engine: engineOption, } = options;
|
|
347
|
+
const requestScope = await resolveIntegrationRequestScope({
|
|
348
|
+
ownerEmail,
|
|
349
|
+
orgId: opts.orgId === undefined ? options.orgId : opts.orgId,
|
|
350
|
+
orgScope: opts.orgScope,
|
|
351
|
+
principalType: opts.principalType,
|
|
352
|
+
});
|
|
353
|
+
const orgId = requestScope.orgId;
|
|
354
|
+
const requestContext = integrationRequestContext(requestScope);
|
|
344
355
|
let effectiveSystemPrompt = systemPrompt + buildRuntimeContextPrompt();
|
|
345
356
|
const deliveryOptions = {
|
|
346
357
|
placeholderRef: opts.placeholderRef,
|
|
@@ -395,7 +406,7 @@ async function processIncomingMessage(incoming, options, opts = {}) {
|
|
|
395
406
|
const budgetReservations = await reserveApplicableIntegrationBudgets({
|
|
396
407
|
incoming,
|
|
397
408
|
ownerEmail,
|
|
398
|
-
orgId
|
|
409
|
+
orgId,
|
|
399
410
|
reservationId: opts.taskId ?? `integration:${incoming.externalThreadId}`,
|
|
400
411
|
});
|
|
401
412
|
if (!budgetReservations.allowed) {
|
|
@@ -404,6 +415,8 @@ async function processIncomingMessage(incoming, options, opts = {}) {
|
|
|
404
415
|
kind: "response-delivery",
|
|
405
416
|
incoming,
|
|
406
417
|
message: outgoing,
|
|
418
|
+
principalType: opts.principalType ?? "user",
|
|
419
|
+
...(requestScope.orgScope ? { orgScope: requestScope.orgScope } : {}),
|
|
407
420
|
...(opts.placeholderRef ? { placeholderRef: opts.placeholderRef } : {}),
|
|
408
421
|
};
|
|
409
422
|
try {
|
|
@@ -438,8 +451,7 @@ async function processIncomingMessage(incoming, options, opts = {}) {
|
|
|
438
451
|
let thread;
|
|
439
452
|
try {
|
|
440
453
|
if (!mapping) {
|
|
441
|
-
const
|
|
442
|
-
const createdThread = await runWithRequestContext({ userEmail: ownerEmail, orgId: threadOrgId ?? undefined }, () => createThread(ownerEmail, {
|
|
454
|
+
const createdThread = await runWithRequestContext({ userEmail: ownerEmail, ...requestContext }, () => createThread(ownerEmail, {
|
|
443
455
|
title: `${adapter.label}: ${incoming.senderName || incoming.senderId || "User"}`,
|
|
444
456
|
source: {
|
|
445
457
|
platform: incoming.platform,
|
|
@@ -524,6 +536,8 @@ async function processIncomingMessage(incoming, options, opts = {}) {
|
|
|
524
536
|
kind: "response-delivery",
|
|
525
537
|
incoming,
|
|
526
538
|
message: exhaustedMessage,
|
|
539
|
+
principalType: opts.principalType ?? "user",
|
|
540
|
+
...(requestScope.orgScope ? { orgScope: requestScope.orgScope } : {}),
|
|
527
541
|
...(exhaustedProgress?.responseTargetRef
|
|
528
542
|
? {
|
|
529
543
|
placeholderRef: exhaustedProgress.responseTargetRef,
|
|
@@ -669,13 +683,11 @@ async function processIncomingMessage(incoming, options, opts = {}) {
|
|
|
669
683
|
],
|
|
670
684
|
});
|
|
671
685
|
}
|
|
672
|
-
let orgId;
|
|
673
686
|
let artifactSecrets;
|
|
674
687
|
let runnableActions;
|
|
675
688
|
let tools;
|
|
676
689
|
let availableTools;
|
|
677
690
|
try {
|
|
678
|
-
orgId = opts.orgId ?? (await resolveOrgIdForEmail(ownerEmail));
|
|
679
691
|
artifactSecrets = await resolveIntegrationArtifactSecrets(orgId);
|
|
680
692
|
runnableActions = attachToolSearch({ ...actions });
|
|
681
693
|
availableTools = actionsToEngineTools(runnableActions);
|
|
@@ -721,7 +733,7 @@ async function processIncomingMessage(incoming, options, opts = {}) {
|
|
|
721
733
|
startRun(runId, threadId, async (send, signal) => {
|
|
722
734
|
await runWithRequestContext({
|
|
723
735
|
userEmail: ownerEmail,
|
|
724
|
-
|
|
736
|
+
...requestContext,
|
|
725
737
|
isIntegrationCaller: true,
|
|
726
738
|
integration: opts.taskId
|
|
727
739
|
? {
|
|
@@ -924,6 +936,10 @@ async function processIncomingMessage(incoming, options, opts = {}) {
|
|
|
924
936
|
kind: "response-delivery",
|
|
925
937
|
incoming,
|
|
926
938
|
message: outgoing,
|
|
939
|
+
principalType: opts.principalType ?? "user",
|
|
940
|
+
...(requestScope.orgScope
|
|
941
|
+
? { orgScope: requestScope.orgScope }
|
|
942
|
+
: {}),
|
|
927
943
|
...(progress?.responseTargetRef
|
|
928
944
|
? {
|
|
929
945
|
placeholderRef: progress.responseTargetRef,
|
|
@@ -1150,6 +1166,10 @@ async function processIncomingMessage(incoming, options, opts = {}) {
|
|
|
1150
1166
|
kind: "response-delivery",
|
|
1151
1167
|
incoming,
|
|
1152
1168
|
message: outgoingForDelivery,
|
|
1169
|
+
principalType: opts.principalType ?? "user",
|
|
1170
|
+
...(requestScope.orgScope
|
|
1171
|
+
? { orgScope: requestScope.orgScope }
|
|
1172
|
+
: {}),
|
|
1153
1173
|
internalThreadId: threadId,
|
|
1154
1174
|
}),
|
|
1155
1175
|
...(threadCheckpoint?.userMessageId
|
|
@@ -122,6 +122,8 @@ export declare function runBackgroundAutomation(options: BackgroundAutomationRun
|
|
|
122
122
|
export declare function checkBackgroundAutomationCredentials(identity: {
|
|
123
123
|
ownerEmail: string;
|
|
124
124
|
orgId?: string;
|
|
125
|
+
orgScope?: "personal";
|
|
126
|
+
defaultAgentEngineScope?: "deployment";
|
|
125
127
|
}, deps: BackgroundAutomationDeps, automationModel?: string): Promise<{
|
|
126
128
|
ok: true;
|
|
127
129
|
engine: AgentEngine;
|
|
@@ -16,7 +16,7 @@ import { withDbExec } from "../db/client.js";
|
|
|
16
16
|
import { automationOutcomeMessagesForUser } from "../localization/automation-outcome-messages.js";
|
|
17
17
|
import { automationRecoveryMessagesForLocale } from "../localization/automation-recovery-messages.js";
|
|
18
18
|
import { queryOrgMembers } from "../org/context.js";
|
|
19
|
-
import { organizationIdFromResourceOwner, } from "../resources/store.js";
|
|
19
|
+
import { organizationIdFromResourceOwner, SHARED_OWNER, } from "../resources/store.js";
|
|
20
20
|
import { captureError } from "../server/capture-error.js";
|
|
21
21
|
import { BuilderCredentialLookupError, CredentialStoreUnavailableError, } from "../server/credential-provider.js";
|
|
22
22
|
import { runWithRequestContext, } from "../server/request-context.js";
|
|
@@ -146,6 +146,17 @@ export async function resolveBackgroundAutomationIdentity(automation) {
|
|
|
146
146
|
const orgId = recoveredFactoryOwnerOrgId(automation.meta, automation.resource.path, automation.resource.owner) ??
|
|
147
147
|
automation.meta.orgId ??
|
|
148
148
|
undefined;
|
|
149
|
+
if (!orgId &&
|
|
150
|
+
automation.resource.owner !== "__shared__" &&
|
|
151
|
+
!organizationIdFromResourceOwner(automation.resource.owner)) {
|
|
152
|
+
const resolved = await resolveAutomationExecutionIdentity(automation.resource.owner, automation.meta);
|
|
153
|
+
if (!resolved.ok)
|
|
154
|
+
return resolved;
|
|
155
|
+
const validity = await validateAutomationRunIdentity(resolved.identity.userEmail);
|
|
156
|
+
if (!validity.ok)
|
|
157
|
+
return validity;
|
|
158
|
+
return resolved;
|
|
159
|
+
}
|
|
149
160
|
const validity = await validateAutomationRunIdentity(userEmail, orgId);
|
|
150
161
|
return validity.ok
|
|
151
162
|
? {
|
|
@@ -153,6 +164,9 @@ export async function resolveBackgroundAutomationIdentity(automation) {
|
|
|
153
164
|
identity: {
|
|
154
165
|
userEmail,
|
|
155
166
|
orgId,
|
|
167
|
+
...(!orgId && automation.resource.owner === SHARED_OWNER
|
|
168
|
+
? { defaultAgentEngineScope: "deployment" }
|
|
169
|
+
: {}),
|
|
156
170
|
eventOwner: userEmail.toLowerCase(),
|
|
157
171
|
},
|
|
158
172
|
}
|
|
@@ -555,7 +569,16 @@ async function resolveBackgroundAutomationModel(engine, automationModel, deps) {
|
|
|
555
569
|
*/
|
|
556
570
|
export async function checkBackgroundAutomationCredentials(identity, deps, automationModel) {
|
|
557
571
|
try {
|
|
558
|
-
const { engine, model } = await runWithRequestContext({
|
|
572
|
+
const { engine, model } = await runWithRequestContext({
|
|
573
|
+
userEmail: identity.ownerEmail,
|
|
574
|
+
orgId: identity.orgId,
|
|
575
|
+
...(identity.orgScope === "personal"
|
|
576
|
+
? { orgScope: "personal" }
|
|
577
|
+
: {}),
|
|
578
|
+
...(identity.defaultAgentEngineScope === "deployment"
|
|
579
|
+
? { defaultAgentEngineScope: "deployment" }
|
|
580
|
+
: {}),
|
|
581
|
+
}, async () => {
|
|
559
582
|
const engine = await resolveUsableBackgroundEngine(identity, deps, () => undefined);
|
|
560
583
|
const model = await resolveBackgroundAutomationModel(engine, automationModel, deps);
|
|
561
584
|
return { engine, model };
|