@agent-native/core 0.214.0 → 0.217.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/dist/action.js +54 -1
- package/dist/agent/actions/disconnect-chatgpt-subscription.js +5 -0
- package/dist/agent/actions/get-agentkit-capabilities.js +3 -3
- package/dist/agent/actions/manage-builder-connection.js +5 -0
- package/dist/agent/actions/manage-provider-key-policy.js +5 -0
- package/dist/agent/actions/manage-provider-models.js +5 -0
- package/dist/agent/actions/manage-service-providers.js +5 -0
- package/dist/agent/actions/select-chatgpt-subscription-account.js +5 -0
- package/dist/agent/context-xray/actions/context-evict.js +5 -0
- package/dist/agent/context-xray/actions/context-pin.js +5 -0
- package/dist/agent/context-xray/actions/context-report.js +5 -0
- package/dist/agent/context-xray/actions/context-restore.js +5 -0
- package/dist/agent/execution-fence.d.ts +1 -0
- package/dist/agent/execution-fence.js +5 -0
- package/dist/agent/production-agent.d.ts +35 -2
- package/dist/agent/production-agent.js +629 -32
- package/dist/agent/run-manager.d.ts +2 -0
- package/dist/agent/run-manager.js +397 -115
- package/dist/agent/run-slot-lock.d.ts +2 -0
- package/dist/agent/run-slot-lock.js +6 -0
- package/dist/agent/run-store.d.ts +5 -0
- package/dist/agent/run-store.js +423 -156
- package/dist/agent/thread-data-builder.js +27 -5
- package/dist/agent/types.d.ts +6 -12
- package/dist/agentkit/capabilities.d.ts +1 -1
- package/dist/app-config/analytics.js +1 -1
- package/dist/application-state/store.d.ts +5 -0
- package/dist/application-state/store.js +26 -0
- package/dist/automation/index.d.ts +1 -1
- package/dist/chat-threads/schema-migrations.js +17 -0
- package/dist/chat-threads/store.d.ts +21 -1
- package/dist/chat-threads/store.js +223 -41
- package/dist/cli/skills-content/turn-into-app-skill.d.ts +1 -1
- package/dist/cli/skills-content/turn-into-app-skill.js +20 -18
- package/dist/cli/templates-meta.js +14 -0
- package/dist/client/analytics-session.d.ts +7 -0
- package/dist/client/analytics-session.js +27 -1
- package/dist/client/analytics.js +276 -31
- package/dist/client/chat/agentkit-agent-native.js +79 -3
- package/dist/client/chat/agentkit-protocol.js +80 -42
- package/dist/client/chat/runtime.d.ts +5 -1
- package/dist/client/chat/runtime.js +46 -3
- package/dist/client/consent.d.ts +48 -0
- package/dist/client/consent.js +413 -0
- package/dist/client/onboarding/index.d.ts +1 -0
- package/dist/client/onboarding/index.js +1 -0
- package/dist/client/onboarding/use-onboarding-checklist.d.ts +23 -0
- package/dist/client/onboarding/use-onboarding-checklist.js +115 -0
- package/dist/client/review/use-review.d.ts +2 -0
- package/dist/client/review/use-review.js +28 -1
- package/dist/client/session-replay.d.ts +1 -1
- package/dist/client/session-replay.js +142 -3
- package/dist/client/sharing/useResourceAccessGate.d.ts +3 -2
- package/dist/client/sharing/useResourceAccessGate.js +9 -1
- package/dist/client/use-chat-thread-list.d.ts +2 -0
- package/dist/client/use-chat-thread-list.js +12 -2
- package/dist/client/use-chat-threads.d.ts +1 -0
- package/dist/client/use-chat-threads.js +2 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/connections/catalog.d.ts +5 -5
- package/dist/connections/catalog.js +22 -3
- package/dist/data-widgets/index.d.ts +36 -2
- package/dist/data-widgets/index.js +94 -6
- package/dist/db/migrations.js +4 -1
- package/dist/db/schema-snapshot.generated.js +8 -1
- package/dist/feature-flags/actions/set-feature-flag.js +5 -0
- package/dist/feature-flags/index.d.ts +1 -1
- package/dist/feature-flags/index.js +1 -1
- package/dist/feature-flags/store.d.ts +12 -0
- package/dist/feature-flags/store.js +79 -7
- package/dist/file-upload/actions/manage-file-storage.js +5 -0
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.js +5 -0
- package/dist/history/actions/create-resource-version.js +5 -0
- package/dist/history/actions/restore-resource-version.js +5 -0
- package/dist/ingestion/index.d.ts +1 -1
- package/dist/ingestion/index.js +1 -1
- package/dist/ingestion/pptx.d.ts +11 -0
- package/dist/ingestion/pptx.js +81 -1
- package/dist/integrations/actions/manage-messaging-channel.js +5 -0
- package/dist/jobs/actions/manage-recurring-job.d.ts +1 -1
- package/dist/jobs/scheduler.js +17 -1
- package/dist/labs/actions/set-lab.js +5 -0
- package/dist/localization/actions/set-localization-preference.js +5 -0
- package/dist/localization/consent-banner-messages.d.ts +16 -0
- package/dist/localization/consent-banner-messages.js +149 -0
- package/dist/localization/core-messages.js +4 -0
- package/dist/localization/default-messages.d.ts +1 -0
- package/dist/localization/default-messages.js +2 -0
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/actions/save-observability-instruction-update.js +5 -0
- package/dist/observability/actions/save-observability-review-summary.js +5 -0
- package/dist/observability/routes.d.ts +6 -6
- package/dist/onboarding/index.d.ts +2 -1
- package/dist/onboarding/index.js +1 -0
- package/dist/onboarding/plugin.js +55 -46
- package/dist/onboarding/status.d.ts +15 -0
- package/dist/onboarding/status.js +59 -0
- package/dist/onboarding/types.d.ts +12 -0
- package/dist/onboarding/types.js +2 -1
- package/dist/org/workspace-app-access.js +19 -9
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +16 -16
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/provider-api/index.js +9 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/review/actions/consume-review-feedback.js +5 -0
- package/dist/review/actions/create-review-comment.js +5 -0
- package/dist/review/actions/delete-review-comment.js +5 -0
- package/dist/review/actions/react-to-review-comment.js +5 -0
- package/dist/review/actions/reply-review-comment.js +5 -0
- package/dist/review/actions/resolve-review-thread.js +5 -0
- package/dist/review/actions/send-review-thread-to-agent.js +5 -0
- package/dist/review/actions/set-review-status.js +5 -0
- package/dist/review/actions/set-review-thread-muted.js +5 -0
- package/dist/review/actions/set-review-thread-unread.js +5 -0
- package/dist/review/actions/set-review-threads-unread.js +5 -0
- package/dist/review/actions/update-review-comment-anchor.js +5 -0
- package/dist/review/actions/update-review-comment.js +5 -0
- package/dist/review/suggestions/actions.js +60 -21
- package/dist/review/suggestions/store.d.ts +2 -0
- package/dist/review/suggestions/store.js +28 -0
- package/dist/secrets/actions/delete-api-key.js +5 -0
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/agent-capabilities.js +13 -6
- package/dist/server/agent-chat/context-tools.js +63 -2
- package/dist/server/agent-chat-plugin.d.ts +2 -0
- package/dist/server/agent-chat-plugin.js +242 -54
- package/dist/server/agent-engine-default-model-route.d.ts +1 -1
- package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
- package/dist/server/analytics.d.ts +0 -1
- package/dist/server/analytics.js +81 -20
- package/dist/server/application-state-maintenance.d.ts +2 -0
- package/dist/server/application-state-maintenance.js +2 -0
- package/dist/server/attribution.d.ts +14 -0
- package/dist/server/attribution.js +62 -2
- package/dist/server/auth.js +7 -0
- package/dist/server/builder-api-auth.d.ts +7 -0
- package/dist/server/builder-api-auth.js +24 -0
- package/dist/server/builder-oauth.d.ts +5 -1
- package/dist/server/builder-oauth.js +5 -0
- package/dist/server/consent-route.d.ts +41 -0
- package/dist/server/consent-route.js +102 -0
- package/dist/server/core-routes-plugin.d.ts +1 -1
- package/dist/server/first-touch-route.d.ts +39 -0
- package/dist/server/first-touch-route.js +115 -0
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.js +2 -1
- package/dist/server/queued-submission-inbox-drain.d.ts +9 -0
- package/dist/server/queued-submission-inbox-drain.js +12 -0
- package/dist/server/request-origin.d.ts +6 -0
- package/dist/server/request-origin.js +12 -0
- package/dist/settings/org-settings.d.ts +2 -1
- package/dist/settings/org-settings.js +4 -1
- package/dist/settings/store.d.ts +8 -0
- package/dist/settings/store.js +14 -5
- package/dist/shared/consent.d.ts +33 -0
- package/dist/shared/consent.js +149 -0
- package/dist/shared/first-touch-persistence.d.ts +31 -0
- package/dist/shared/first-touch-persistence.js +53 -0
- package/dist/sharing/actions/set-resource-visibility.js +5 -0
- package/dist/sharing/actions/share-resource.js +5 -0
- package/dist/sharing/actions/unshare-resource.js +5 -0
- package/dist/templates/chat/.agents/skills/actions/references/action-fields.md +1 -1
- package/dist/templates/default/.agents/skills/actions/references/action-fields.md +1 -1
- package/dist/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +36 -80
- package/dist/templates/factory/.agents/skills/review-latest-feedback/references/channel-inventory.md +54 -16
- package/dist/templates/factory/.agents/skills/review-latest-feedback/references/slack-reaction-replies.md +50 -73
- package/dist/templates/headless/.agents/skills/actions/references/action-fields.md +1 -1
- package/dist/templates/workspace-core/.agents/skills/actions/references/action-fields.md +1 -1
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +20 -18
- package/dist/triggers/actions/manage-automation.d.ts +4 -4
- package/dist/usage/actions/get-usage-metrics.js +27 -4
- package/dist/usage/actions/manage-usage-alert.js +5 -0
- package/dist/vite/client.js +8 -6
- package/dist/workspace-connections/actions/bulk-update-workspace-user-groups.js +5 -0
- package/dist/workspace-connections/actions/delete-workspace-user-group.js +5 -0
- package/dist/workspace-connections/actions/upsert-workspace-user-group.js +5 -0
- package/docs/content/actions-access-control.mdx +8 -8
- package/docs/content/actions-defining.mdx +9 -8
- package/docs/content/deployment-environment-variables.mdx +1 -1
- package/docs/content/environment-variables.mdx +1 -1
- package/docs/content/template-design-developers.mdx +9 -9
- package/docs/content/template-design-features.mdx +1 -3
- package/docs/content/turn-into-app.mdx +4 -0
- package/package.json +6 -3
- package/src/templates/chat/.agents/skills/actions/references/action-fields.md +1 -1
- package/src/templates/default/.agents/skills/actions/references/action-fields.md +1 -1
- package/src/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +36 -80
- package/src/templates/factory/.agents/skills/review-latest-feedback/references/channel-inventory.md +54 -16
- package/src/templates/factory/.agents/skills/review-latest-feedback/references/slack-reaction-replies.md +50 -73
- package/src/templates/headless/.agents/skills/actions/references/action-fields.md +1 -1
- package/src/templates/workspace-core/.agents/skills/actions/references/action-fields.md +1 -1
- package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +20 -18
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
/** One id for this page load, shared by every pageview until it reloads. */
|
|
2
2
|
export declare function getAnalyticsPageLoadId(): string;
|
|
3
|
+
/**
|
|
4
|
+
* The visitor id, `an_aid`, waits for analytics consent where the banner
|
|
5
|
+
* applies, and for the server's region rather than the time zone's guess,
|
|
6
|
+
* since a sent id can't be recalled. Until then this returns `undefined` and
|
|
7
|
+
* stores nothing, so events still count but can't be tied to one visitor
|
|
8
|
+
* across pages.
|
|
9
|
+
*/
|
|
3
10
|
export declare function getOrCreateAnalyticsAnonymousId(): string | undefined;
|
|
4
11
|
export declare function setAnalyticsSessionId(sessionId: string): string | undefined;
|
|
5
12
|
export declare function clearAnalyticsSessionId(): void;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { serializeAnalyticsAnonymousIdCookie } from "../shared/analytics-anonymous-id.js";
|
|
1
|
+
import { ANALYTICS_ANONYMOUS_ID_COOKIE_NAME, serializeAnalyticsAnonymousIdCookie, } from "../shared/analytics-anonymous-id.js";
|
|
2
2
|
import { ANALYTICS_SESSION_ID_COOKIE_NAME, ANALYTICS_SESSION_ID_MAX_LENGTH, normalizeAnalyticsSessionId, serializeAnalyticsSessionIdCookie, } from "../shared/analytics-session-id.js";
|
|
3
|
+
import { consentDecision, whenConsentAllows } from "./consent.js";
|
|
3
4
|
const ANONYMOUS_ID_STORAGE_KEY = "agent-native.anonymous_id";
|
|
4
5
|
const SESSION_ID_STORAGE_KEY = "agent-native.session_id";
|
|
5
6
|
const SESSION_ID_PIN_STORAGE_KEY = "agent-native.session_id_pin";
|
|
@@ -72,9 +73,34 @@ export function getAnalyticsPageLoadId() {
|
|
|
72
73
|
pageLoadId ??= generateVisitorId();
|
|
73
74
|
return pageLoadId;
|
|
74
75
|
}
|
|
76
|
+
let anonymousIdConsentWatched = false;
|
|
77
|
+
function clearAnalyticsAnonymousId() {
|
|
78
|
+
safeStorageRemove(ANONYMOUS_ID_STORAGE_KEY);
|
|
79
|
+
try {
|
|
80
|
+
document.cookie = `${ANALYTICS_ANONYMOUS_ID_COOKIE_NAME}=; path=/; max-age=0; SameSite=Lax`;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// coercion-ok: a frame that can't read cookies never stored one.
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The visitor id, `an_aid`, waits for analytics consent where the banner
|
|
88
|
+
* applies, and for the server's region rather than the time zone's guess,
|
|
89
|
+
* since a sent id can't be recalled. Until then this returns `undefined` and
|
|
90
|
+
* stores nothing, so events still count but can't be tied to one visitor
|
|
91
|
+
* across pages.
|
|
92
|
+
*/
|
|
75
93
|
export function getOrCreateAnalyticsAnonymousId() {
|
|
76
94
|
if (typeof window === "undefined")
|
|
77
95
|
return undefined;
|
|
96
|
+
if (!anonymousIdConsentWatched) {
|
|
97
|
+
anonymousIdConsentWatched = true;
|
|
98
|
+
whenConsentAllows("performance", () => { }, {
|
|
99
|
+
revoke: clearAnalyticsAnonymousId,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
if (consentDecision("performance") !== true)
|
|
103
|
+
return undefined;
|
|
78
104
|
let id = safeStorageGet(ANONYMOUS_ID_STORAGE_KEY);
|
|
79
105
|
if (!id) {
|
|
80
106
|
id = generateVisitorId();
|
package/dist/client/analytics.js
CHANGED
|
@@ -4,6 +4,7 @@ import { ANALYTICS_CLIENT_PLATFORM_PROPERTY, } from "../shared/analytics-platfor
|
|
|
4
4
|
import { hasAttributionSource, } from "../shared/attribution-source.js";
|
|
5
5
|
import { resolveLaneEndpoint } from "../shared/environment-lanes.js";
|
|
6
6
|
import { classifyErrorNoise, } from "../shared/error-noise.js";
|
|
7
|
+
import { FIRST_TOUCH_SERVER_COOKIE_NAME, FIRST_TOUCH_SERVER_COOKIE_VERSION, FIRST_TOUCH_SERVER_PATH, firstTouchServerExpiry, isSameFirstTouch, preferFirstTouch, } from "../shared/first-touch-persistence.js";
|
|
7
8
|
import { llmConnectionTrackingProperties, } from "../shared/llm-connection.js";
|
|
8
9
|
import { loadOptionalPeer } from "../shared/optional-peer.js";
|
|
9
10
|
import { isTestIdentityEmail } from "../shared/qa-test-email.js";
|
|
@@ -11,8 +12,11 @@ import { isSyntheticTrafficValue } from "../shared/test-traffic.js";
|
|
|
11
12
|
import { toPostHogExceptionProperties } from "../tracking/posthog-exception.js";
|
|
12
13
|
import { getAnalyticsClientPlatform } from "./analytics-platform.js";
|
|
13
14
|
import { getAnalyticsPageLoadId, getOrCreateAnalyticsAnonymousId, getOrCreateAnalyticsSessionId, } from "./analytics-session.js";
|
|
15
|
+
import { agentNativePath } from "./api-path.js";
|
|
16
|
+
import { agentNativeApiDisabledReason } from "./api-surface.js";
|
|
14
17
|
import { injectedAgentNativeConfig } from "./app-config.js";
|
|
15
18
|
import { clientBuildId } from "./build-compatibility.js";
|
|
19
|
+
import { consentAllowsNow, consentDecision, getConsentChoice, whenConsentAllows, whenConsentDecided, } from "./consent.js";
|
|
16
20
|
import { clientFailureContext } from "./failure-report.js";
|
|
17
21
|
import { replayEndpointFromAnalyticsEndpoint } from "./session-replay-endpoint.js";
|
|
18
22
|
import { scheduleAfterPaint } from "./use-after-paint.js";
|
|
@@ -35,6 +39,7 @@ let _amplitudeModule = null;
|
|
|
35
39
|
let _amplitudeLoadPromise = null;
|
|
36
40
|
let _amplitudeApiKey = null;
|
|
37
41
|
let _pendingAmplitudeEvents = [];
|
|
42
|
+
let _amplitudeConsent = "unasked";
|
|
38
43
|
let _sentryInitialized = false;
|
|
39
44
|
let _sentryModule = null;
|
|
40
45
|
let _sentryLoadPromise = null;
|
|
@@ -174,6 +179,11 @@ const LAST_TOUCH_COOKIE = {
|
|
|
174
179
|
priority: LAST_TOUCH_COOKIE_FIELD_PRIORITY,
|
|
175
180
|
};
|
|
176
181
|
let _firstTouchCaptured = false;
|
|
182
|
+
// Bounds the resend after a response race; see `syncFirstTouchToServer`.
|
|
183
|
+
let _firstTouchSyncsLeft = 2;
|
|
184
|
+
// Set when this page wrote `an_ft` or `an_lt`, which the server then writes
|
|
185
|
+
// again: Safari keeps a cookie page JavaScript wrote for seven days at most.
|
|
186
|
+
let _attributionCookieWritten = false;
|
|
177
187
|
function safeStorageGet(key) {
|
|
178
188
|
try {
|
|
179
189
|
return window.localStorage.getItem(key);
|
|
@@ -190,6 +200,14 @@ function safeStorageSet(key, value) {
|
|
|
190
200
|
// private browsing / storage disabled — best-effort
|
|
191
201
|
}
|
|
192
202
|
}
|
|
203
|
+
function safeStorageRemove(key) {
|
|
204
|
+
try {
|
|
205
|
+
window.localStorage.removeItem(key);
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
// coercion-ok: storage that can't be read holds nothing to remove.
|
|
209
|
+
}
|
|
210
|
+
}
|
|
193
211
|
function readCachedLlmConnectionStatus() {
|
|
194
212
|
if (typeof window === "undefined")
|
|
195
213
|
return null;
|
|
@@ -536,6 +554,7 @@ function writeAttributionCookie(value, spec) {
|
|
|
536
554
|
const encodedValue = fitAttributionCookieValue(value, spec);
|
|
537
555
|
try {
|
|
538
556
|
document.cookie = attributionCookieAssignment(spec.name, encodedValue);
|
|
557
|
+
_attributionCookieWritten = true;
|
|
539
558
|
}
|
|
540
559
|
catch {
|
|
541
560
|
// best-effort
|
|
@@ -564,16 +583,132 @@ function backfillAttributionCookie(storageKey, spec) {
|
|
|
564
583
|
// signup handoff goes without it.
|
|
565
584
|
}
|
|
566
585
|
}
|
|
586
|
+
/** Remove every stored touch, in storage and cookies. */
|
|
587
|
+
function clearStoredAttribution() {
|
|
588
|
+
safeStorageRemove(FIRST_TOUCH_STORAGE_KEY);
|
|
589
|
+
safeStorageRemove(LAST_TOUCH_STORAGE_KEY);
|
|
590
|
+
if (typeof document === "undefined")
|
|
591
|
+
return;
|
|
592
|
+
for (const name of [
|
|
593
|
+
FIRST_TOUCH_COOKIE_NAME,
|
|
594
|
+
LAST_TOUCH_COOKIE_NAME,
|
|
595
|
+
FIRST_TOUCH_SERVER_COOKIE_NAME,
|
|
596
|
+
]) {
|
|
597
|
+
try {
|
|
598
|
+
document.cookie = `${name}=; path=/; max-age=0; SameSite=Lax`;
|
|
599
|
+
}
|
|
600
|
+
catch {
|
|
601
|
+
// coercion-ok: a sandboxed iframe can't read or write cookies, so
|
|
602
|
+
// there is none here to clear.
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
/** The year-long copy our server keeps in `an_fts`. */
|
|
607
|
+
function readServerFirstTouch() {
|
|
608
|
+
const touch = readAttributionCookieValue(FIRST_TOUCH_SERVER_COOKIE_NAME);
|
|
609
|
+
if (!touch || touch.v !== FIRST_TOUCH_SERVER_COOKIE_VERSION)
|
|
610
|
+
return null;
|
|
611
|
+
const { v: _version, ...firstTouch } = touch;
|
|
612
|
+
return firstTouch;
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* The browser's own copies: localStorage, then the 30-day `an_ft` cookie. A
|
|
616
|
+
* visit more than a year old no longer counts, or the cookie it's copied back
|
|
617
|
+
* into would keep it going.
|
|
618
|
+
*/
|
|
619
|
+
function readLocalFirstTouch() {
|
|
620
|
+
const touch = readStoredAttribution(FIRST_TOUCH_STORAGE_KEY, FIRST_TOUCH_COOKIE_NAME);
|
|
621
|
+
return touch && firstTouchServerExpiry(touch) ? touch : null;
|
|
622
|
+
}
|
|
567
623
|
/**
|
|
568
|
-
*
|
|
569
|
-
*
|
|
570
|
-
*
|
|
571
|
-
|
|
624
|
+
* The server writes `an_lt` again from each request's cookies, so a slow
|
|
625
|
+
* response from an older page can put back an older last touch. The newest
|
|
626
|
+
* one is in localStorage. Returns whether it had to write it back.
|
|
627
|
+
*/
|
|
628
|
+
function restoreNewestLastTouchCookie() {
|
|
629
|
+
const stored = safeStorageGet(LAST_TOUCH_STORAGE_KEY);
|
|
630
|
+
const newest = parseAttribution(stored);
|
|
631
|
+
if (!stored || !newest)
|
|
632
|
+
return false;
|
|
633
|
+
const cookie = readAttributionCookieValue(LAST_TOUCH_COOKIE_NAME);
|
|
634
|
+
if (Date.parse(cookie?.touched_at ?? "") >= Date.parse(newest.touched_at ?? "")) {
|
|
635
|
+
return false;
|
|
636
|
+
}
|
|
637
|
+
writeAttributionCookie(stored, LAST_TOUCH_COOKIE);
|
|
638
|
+
return true;
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Ask our server to keep `firstTouch` in its year-long cookie, unless it
|
|
642
|
+
* already holds that visit and this page wrote no attribution cookie; the
|
|
643
|
+
* same request has the server write `an_ft` and `an_lt` again. Two tabs can each send a touch before either
|
|
644
|
+
* response lands, and the later response wins the cookie, so when ours
|
|
645
|
+
* leaves a worse touch there than this browser holds, send the better one
|
|
646
|
+
* again. Until the server holds it, signup still reads `an_ft`.
|
|
647
|
+
*/
|
|
648
|
+
function syncFirstTouchToServer(firstTouch) {
|
|
649
|
+
if (!_attributionCookieWritten &&
|
|
650
|
+
isSameFirstTouch(readServerFirstTouch(), firstTouch)) {
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
// An embed that must not call our API (the Builder shell canvas) keeps only
|
|
654
|
+
// the browser's copies.
|
|
655
|
+
if (agentNativeApiDisabledReason())
|
|
656
|
+
return;
|
|
657
|
+
if (_firstTouchSyncsLeft <= 0 || typeof fetch !== "function")
|
|
658
|
+
return;
|
|
659
|
+
_firstTouchSyncsLeft -= 1;
|
|
660
|
+
_attributionCookieWritten = false;
|
|
661
|
+
void fetch(agentNativePath(FIRST_TOUCH_SERVER_PATH), {
|
|
662
|
+
method: "POST",
|
|
663
|
+
credentials: "same-origin",
|
|
664
|
+
keepalive: true,
|
|
665
|
+
headers: { "Content-Type": "application/json" },
|
|
666
|
+
body: JSON.stringify({ firstTouch }),
|
|
667
|
+
})
|
|
668
|
+
.then(async (response) => {
|
|
669
|
+
if (!response.ok)
|
|
670
|
+
return;
|
|
671
|
+
const result = (await response.json());
|
|
672
|
+
// The visitor may have rejected while this request was out.
|
|
673
|
+
if (result.reason === "consent_required" ||
|
|
674
|
+
!consentAllowsNow("targeting")) {
|
|
675
|
+
clearStoredAttribution();
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
// Written back by page JavaScript, Safari would keep it a week.
|
|
679
|
+
const repaired = restoreNewestLastTouchCookie();
|
|
680
|
+
const server = readServerFirstTouch();
|
|
681
|
+
const local = readLocalFirstTouch();
|
|
682
|
+
if (!server)
|
|
683
|
+
return;
|
|
684
|
+
if (isSameFirstTouch(server, local)) {
|
|
685
|
+
if (repaired && local)
|
|
686
|
+
syncFirstTouchToServer(local);
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
if (preferFirstTouch(server, local) === server) {
|
|
690
|
+
storeAttribution(FIRST_TOUCH_STORAGE_KEY, FIRST_TOUCH_COOKIE, server);
|
|
691
|
+
}
|
|
692
|
+
else if (local) {
|
|
693
|
+
syncFirstTouchToServer(local);
|
|
694
|
+
}
|
|
695
|
+
})
|
|
696
|
+
.catch(() => {
|
|
697
|
+
// coercion-ok: the 30-day `an_ft` cookie still carries first touch to
|
|
698
|
+
// signup; the next page load tries again.
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Capture the visitor's referral attribution once per page load, into
|
|
703
|
+
* `localStorage`, a first-party cookie the signup boundary reads, and the
|
|
704
|
+
* server's year-long copy. Fully defensive and SSR-safe — any failure is
|
|
705
|
+
* swallowed so it can never break app boot.
|
|
572
706
|
*
|
|
573
|
-
* First touch (`an_attribution` / `an_ft`) is first
|
|
574
|
-
*
|
|
575
|
-
*
|
|
576
|
-
* tagged visit after it.
|
|
707
|
+
* First touch (`an_attribution` / `an_ft` / `an_fts`) is the first visit that
|
|
708
|
+
* said where this person came from, else the first visit; see
|
|
709
|
+
* `preferFirstTouch`. Without that, an untagged first visit would hide every
|
|
710
|
+
* tagged visit after it. When the browser's copies are gone, as Safari clears
|
|
711
|
+
* them, the server's copy restores them.
|
|
577
712
|
*/
|
|
578
713
|
function captureFirstTouchAttribution(options = {}) {
|
|
579
714
|
if (_firstTouchCaptured)
|
|
@@ -582,16 +717,32 @@ function captureFirstTouchAttribution(options = {}) {
|
|
|
582
717
|
if (typeof window === "undefined")
|
|
583
718
|
return;
|
|
584
719
|
try {
|
|
720
|
+
// Read the visit now: the URL can change before the visitor consents.
|
|
585
721
|
const current = buildFirstTouchAttribution(options.landingPath ?? window.location.pathname);
|
|
586
|
-
const
|
|
587
|
-
|
|
588
|
-
|
|
722
|
+
const forwarded = readForwardedLastTouch();
|
|
723
|
+
const forwardedAt = readForwardedLastTouchAt();
|
|
724
|
+
// Where the banner applies, nothing is stored until the visitor accepts
|
|
725
|
+
// targeting cookies, and a later "reject" clears it again.
|
|
726
|
+
whenConsentAllows("targeting", () => storeTouches(current, forwarded, forwardedAt), { optimistic: true, revoke: clearStoredAttribution });
|
|
727
|
+
}
|
|
728
|
+
catch {
|
|
729
|
+
// coercion-ok: attribution is best-effort telemetry; never let it break
|
|
730
|
+
// boot.
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
function storeTouches(current, forwarded, forwardedAt) {
|
|
734
|
+
try {
|
|
735
|
+
const local = readLocalFirstTouch();
|
|
736
|
+
// The same visit in both keeps the local copy, which was never trimmed.
|
|
737
|
+
const firstTouch = preferFirstTouch(preferFirstTouch(local, readServerFirstTouch()), current);
|
|
738
|
+
if (firstTouch === local) {
|
|
589
739
|
backfillAttributionCookie(FIRST_TOUCH_STORAGE_KEY, FIRST_TOUCH_COOKIE);
|
|
590
740
|
}
|
|
591
741
|
else {
|
|
592
|
-
storeAttribution(FIRST_TOUCH_STORAGE_KEY, FIRST_TOUCH_COOKIE,
|
|
742
|
+
storeAttribution(FIRST_TOUCH_STORAGE_KEY, FIRST_TOUCH_COOKIE, firstTouch);
|
|
593
743
|
}
|
|
594
|
-
captureLastTouchAttribution(current);
|
|
744
|
+
captureLastTouchAttribution(current, forwarded, forwardedAt);
|
|
745
|
+
syncFirstTouchToServer(firstTouch);
|
|
595
746
|
}
|
|
596
747
|
catch {
|
|
597
748
|
// Attribution is best-effort telemetry; never let it break boot.
|
|
@@ -604,10 +755,8 @@ function captureFirstTouchAttribution(options = {}) {
|
|
|
604
755
|
* visit keeps the time it happened, and loses to a newer visit the app has
|
|
605
756
|
* already recorded.
|
|
606
757
|
*/
|
|
607
|
-
function captureLastTouchAttribution(current) {
|
|
608
|
-
const forwarded = readForwardedLastTouch();
|
|
758
|
+
function captureLastTouchAttribution(current, forwarded, forwardedAt) {
|
|
609
759
|
const source = forwarded ?? (hasAttributionSource(current) ? current : null);
|
|
610
|
-
const forwardedAt = readForwardedLastTouchAt();
|
|
611
760
|
const existing = getLastTouchAttribution();
|
|
612
761
|
const existingAt = Date.parse(existing?.touched_at ?? "");
|
|
613
762
|
if (!source ||
|
|
@@ -702,7 +851,9 @@ function readStoredAttribution(storageKey, cookieName) {
|
|
|
702
851
|
return hasAttributionSource(cookie) ? cookie : (stored ?? cookie);
|
|
703
852
|
}
|
|
704
853
|
export function getFirstTouchAttribution() {
|
|
705
|
-
|
|
854
|
+
if (typeof window === "undefined")
|
|
855
|
+
return null;
|
|
856
|
+
return preferFirstTouch(readLocalFirstTouch(), readServerFirstTouch());
|
|
706
857
|
}
|
|
707
858
|
export function getLastTouchAttribution() {
|
|
708
859
|
return readStoredAttribution(LAST_TOUCH_STORAGE_KEY, LAST_TOUCH_COOKIE_NAME);
|
|
@@ -731,20 +882,82 @@ function isSyntheticBrowserTraffic() {
|
|
|
731
882
|
return (typeof window !== "undefined" &&
|
|
732
883
|
isSyntheticTrafficValue(window.__AGENT_NATIVE_SYNTHETIC_TRAFFIC__));
|
|
733
884
|
}
|
|
885
|
+
/**
|
|
886
|
+
* Amplitude keeps its device id in a cookie on the widest domain it can set,
|
|
887
|
+
* and its marketing touch and unsent events beside it, all named from the
|
|
888
|
+
* API key. A reject clears them at every level of this host.
|
|
889
|
+
*/
|
|
890
|
+
function clearAmplitudeStorage(apiKey) {
|
|
891
|
+
const key = apiKey.slice(0, 10);
|
|
892
|
+
const names = [
|
|
893
|
+
`AMP_${key}`,
|
|
894
|
+
`AMP_MKTG_${key}`,
|
|
895
|
+
`AMP_MKTG_ORIGINAL_${key}`,
|
|
896
|
+
`AMP_unsent_${key}`,
|
|
897
|
+
`amp_${apiKey.slice(0, 6)}`,
|
|
898
|
+
];
|
|
899
|
+
try {
|
|
900
|
+
const labels = window.location.hostname.split(".");
|
|
901
|
+
const domains = [""];
|
|
902
|
+
for (let i = 0; i < labels.length - 1; i += 1) {
|
|
903
|
+
domains.push(`; domain=.${labels.slice(i).join(".")}`);
|
|
904
|
+
}
|
|
905
|
+
for (const name of names) {
|
|
906
|
+
for (const domain of domains) {
|
|
907
|
+
document.cookie = `${name}=; path=/; max-age=0${domain}`;
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
catch {
|
|
912
|
+
// coercion-ok: a sandboxed iframe can't read or write cookies, so
|
|
913
|
+
// Amplitude stored none here.
|
|
914
|
+
}
|
|
915
|
+
for (const name of names)
|
|
916
|
+
safeStorageRemove(name);
|
|
917
|
+
}
|
|
734
918
|
function ensureAmplitude() {
|
|
735
919
|
if (isSyntheticBrowserTraffic())
|
|
736
920
|
return false;
|
|
737
|
-
if (_amplitudeInitialized)
|
|
738
|
-
return true;
|
|
739
921
|
const key = import.meta.env
|
|
740
922
|
?.VITE_AMPLITUDE_API_KEY;
|
|
741
923
|
if (!key)
|
|
742
924
|
return false;
|
|
743
925
|
_amplitudeApiKey = key;
|
|
926
|
+
if (_amplitudeConsent !== "granted") {
|
|
927
|
+
if (_amplitudeConsent === "unasked") {
|
|
928
|
+
_amplitudeConsent = "waiting";
|
|
929
|
+
// Amplitude keeps a device id in the browser, so where the banner
|
|
930
|
+
// applies it waits for performance cookies.
|
|
931
|
+
whenConsentAllows("performance", () => {
|
|
932
|
+
_amplitudeConsent = "granted";
|
|
933
|
+
// Held before the region answered: with a choice on record, the
|
|
934
|
+
// visitor had to choose, so what came before it never goes out.
|
|
935
|
+
if (getConsentChoice())
|
|
936
|
+
_pendingAmplitudeEvents = [];
|
|
937
|
+
_amplitudeModule?.setOptOut(false);
|
|
938
|
+
ensureAmplitude();
|
|
939
|
+
}, {
|
|
940
|
+
revoke: () => {
|
|
941
|
+
_amplitudeConsent = "revoked";
|
|
942
|
+
_pendingAmplitudeEvents = [];
|
|
943
|
+
_amplitudeModule?.setOptOut(true);
|
|
944
|
+
// A later accept starts a new device id, not the one in memory.
|
|
945
|
+
_amplitudeModule?.reset();
|
|
946
|
+
clearAmplitudeStorage(key);
|
|
947
|
+
},
|
|
948
|
+
});
|
|
949
|
+
}
|
|
950
|
+
return false;
|
|
951
|
+
}
|
|
952
|
+
if (_amplitudeInitialized)
|
|
953
|
+
return true;
|
|
744
954
|
if (_amplitudeLoadPromise)
|
|
745
955
|
return false;
|
|
746
956
|
_amplitudeLoadPromise = loadOptionalPeer("@amplitude/analytics-browser", () => import("@amplitude/analytics-browser"))
|
|
747
957
|
.then((module) => {
|
|
958
|
+
// A reject while the SDK loaded: the next accept initializes it.
|
|
959
|
+
if (_amplitudeConsent !== "granted")
|
|
960
|
+
return null;
|
|
748
961
|
module.init(key, { autocapture: false });
|
|
749
962
|
_amplitudeModule = module;
|
|
750
963
|
_amplitudeInitialized = true;
|
|
@@ -2005,15 +2218,30 @@ function sendAgentNativeAnalytics(name, properties) {
|
|
|
2005
2218
|
?.VITE_AGENT_NATIVE_ANALYTICS_ENDPOINT ||
|
|
2006
2219
|
AGENT_NATIVE_ANALYTICS_DEFAULT_ENDPOINT, window.location.hostname);
|
|
2007
2220
|
const userId = typeof properties.userId === "string" ? properties.userId : undefined;
|
|
2008
|
-
const
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2221
|
+
const sessionId = getOrCreateSessionId();
|
|
2222
|
+
const timestamp = new Date().toISOString();
|
|
2223
|
+
whenConsentDecided((decided) => {
|
|
2224
|
+
const anonymousId = decided ? getOrCreateAnonymousId() : undefined;
|
|
2225
|
+
postAgentNativeAnalytics(endpoint, JSON.stringify({
|
|
2226
|
+
publicKey,
|
|
2227
|
+
event: name,
|
|
2228
|
+
// The visitor id waits for analytics consent; mark the event so
|
|
2229
|
+
// reports can tell it from one that lost its id some other way, and
|
|
2230
|
+
// a refusal from a page that closed before the region was known.
|
|
2231
|
+
properties: anonymousId
|
|
2232
|
+
? properties
|
|
2233
|
+
: {
|
|
2234
|
+
...properties,
|
|
2235
|
+
analytics_consent: decided ? "withheld" : "unknown",
|
|
2236
|
+
},
|
|
2237
|
+
userId,
|
|
2238
|
+
anonymousId,
|
|
2239
|
+
sessionId,
|
|
2240
|
+
timestamp,
|
|
2241
|
+
}));
|
|
2016
2242
|
});
|
|
2243
|
+
}
|
|
2244
|
+
function postAgentNativeAnalytics(endpoint, body) {
|
|
2017
2245
|
try {
|
|
2018
2246
|
if (navigator.sendBeacon) {
|
|
2019
2247
|
const sent = navigator.sendBeacon(endpoint, body);
|
|
@@ -2037,17 +2265,34 @@ function createTrackingAliasId() {
|
|
|
2037
2265
|
? crypto.randomUUID()
|
|
2038
2266
|
: undefined;
|
|
2039
2267
|
}
|
|
2268
|
+
function pageHasGoogleTags() {
|
|
2269
|
+
const holder = window;
|
|
2270
|
+
return Boolean(holder.__AN_CONSENT_LAYERS__ ||
|
|
2271
|
+
window.__AGENT_NATIVE_GA_GTAG__ ||
|
|
2272
|
+
window.gtag);
|
|
2273
|
+
}
|
|
2040
2274
|
function emitBrowserTrackingEvent(name, props, options = {}) {
|
|
2041
2275
|
const { agentNativeProperties = props, gtagProperties = props, sendGtag = true, } = options;
|
|
2042
2276
|
const amplitudeProps = amplitudeEventProperties(name, props);
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2277
|
+
// Without Google tags there is nothing to hold, and asking for the region
|
|
2278
|
+
// would be a request a scoped embed (an MCP App widget) may not make.
|
|
2279
|
+
if (sendGtag && pageHasGoogleTags()) {
|
|
2280
|
+
whenConsentDecided(() => {
|
|
2281
|
+
if (consentDecision("performance") !== true)
|
|
2282
|
+
return;
|
|
2283
|
+
const gtag = window.__AGENT_NATIVE_GA_GTAG__ ?? window.gtag;
|
|
2284
|
+
gtag?.("event", name.replace(/\s+/g, "_"), gtagProperties);
|
|
2285
|
+
});
|
|
2046
2286
|
}
|
|
2047
2287
|
if (ensureAmplitude()) {
|
|
2048
2288
|
_amplitudeModule?.track(name, amplitudeProps);
|
|
2049
2289
|
}
|
|
2050
|
-
else if (_amplitudeApiKey
|
|
2290
|
+
else if (_amplitudeApiKey &&
|
|
2291
|
+
// Only while it loads after an accept, or before the region is known;
|
|
2292
|
+
// the region's answer clears what's held if the visitor must choose.
|
|
2293
|
+
(_amplitudeConsent === "granted" ||
|
|
2294
|
+
(_amplitudeConsent !== "revoked" &&
|
|
2295
|
+
consentDecision("performance") === null))) {
|
|
2051
2296
|
if (_pendingAmplitudeEvents.length < 100) {
|
|
2052
2297
|
_pendingAmplitudeEvents.push([name, amplitudeProps]);
|
|
2053
2298
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AgentKitRunSlotBusyError } from "@agent-native/agentkit/client";
|
|
2
|
-
import { AGENT_NATIVE_SUBMISSION_DEADLINES_CAPABILITY_ID, createCapabilityUnavailableError, createCapabilityUnsupportedError, agentEventSequenceEnd, isAgentKitProtocolVersion, negotiateAgentKitProtocolVersion, parseAgentQueuedMessage, parseAgentRunOptions, parseAgentThreadSnapshot, persistableFilePart, } from "@agent-native/agentkit/protocol";
|
|
2
|
+
import { AGENT_NATIVE_SUBMISSION_DEADLINES_CAPABILITY_ID, createCapabilityUnavailableError, createCapabilityUnsupportedError, agentEventSequenceEnd, isAgentKitProtocolVersion, negotiateAgentKitProtocolVersion, parseAgentQueuedMessage, parseNullableAgentQueuedSubmissionStatus, parseAgentRunOptions, parseAgentThreadSnapshot, persistableFilePart, } from "@agent-native/agentkit/protocol";
|
|
3
3
|
import { failedRunIdsWithError, isRenderedRunNotStartedNotice, projectRootAssistantMessages, } from "../../agent/thread-message-projection.js";
|
|
4
4
|
import { RUN_NOT_STARTED_METADATA_KEY, retryContextFromRequest, } from "../../shared/agent-chat-run-not-started.js";
|
|
5
5
|
import { AGENT_CHAT_THREAD_ABSENCE_HEADER } from "../../shared/agent-chat.js";
|
|
@@ -1258,6 +1258,15 @@ function storedQueue(value, threadId, fallbackCreatedAt) {
|
|
|
1258
1258
|
createdAt: timestamp(queued.createdAt, fallbackCreatedAt),
|
|
1259
1259
|
requestAttachments: queued.requestAttachments,
|
|
1260
1260
|
}).requestAttachments;
|
|
1261
|
+
const references = queued.references === undefined
|
|
1262
|
+
? undefined
|
|
1263
|
+
: parseAgentQueuedMessage({
|
|
1264
|
+
id: queued.id,
|
|
1265
|
+
threadId,
|
|
1266
|
+
text: queued.text,
|
|
1267
|
+
createdAt: timestamp(queued.createdAt, fallbackCreatedAt),
|
|
1268
|
+
references: queued.references,
|
|
1269
|
+
}).references;
|
|
1261
1270
|
return {
|
|
1262
1271
|
id: queued.id,
|
|
1263
1272
|
threadId,
|
|
@@ -1265,6 +1274,7 @@ function storedQueue(value, threadId, fallbackCreatedAt) {
|
|
|
1265
1274
|
createdAt: timestamp(queued.createdAt, fallbackCreatedAt),
|
|
1266
1275
|
...(attachments?.length ? { attachments } : {}),
|
|
1267
1276
|
...(requestAttachments?.length ? { requestAttachments } : {}),
|
|
1277
|
+
...(references?.length ? { references } : {}),
|
|
1268
1278
|
...(asRecord(queued.metadata)
|
|
1269
1279
|
? { metadata: asRecord(queued.metadata) }
|
|
1270
1280
|
: {}),
|
|
@@ -3233,6 +3243,7 @@ export function createAgentNativeAgentKitTransport(options = {}) {
|
|
|
3233
3243
|
? { alreadySubmitted: true, submittedRunId }
|
|
3234
3244
|
: {}),
|
|
3235
3245
|
...(value.submissionExpired === true ? { submissionExpired: true } : {}),
|
|
3246
|
+
...(value.receiptManaged === true ? { receiptManaged: true } : {}),
|
|
3236
3247
|
};
|
|
3237
3248
|
}
|
|
3238
3249
|
// A server that predates `active` meaning "in flight" reports a run inside
|
|
@@ -3292,6 +3303,16 @@ export function createAgentNativeAgentKitTransport(options = {}) {
|
|
|
3292
3303
|
});
|
|
3293
3304
|
try {
|
|
3294
3305
|
const run = await startRun(input, context);
|
|
3306
|
+
if (!run.runId) {
|
|
3307
|
+
dispatchAgentChatRunning({
|
|
3308
|
+
isRunning: false,
|
|
3309
|
+
phase: "idle",
|
|
3310
|
+
threadId: input.threadId,
|
|
3311
|
+
tabId: input.threadId,
|
|
3312
|
+
reason: "submission_queued",
|
|
3313
|
+
});
|
|
3314
|
+
return run;
|
|
3315
|
+
}
|
|
3295
3316
|
dispatchAgentChatRunning({
|
|
3296
3317
|
isRunning: true,
|
|
3297
3318
|
phase: "working",
|
|
@@ -3329,6 +3350,42 @@ export function createAgentNativeAgentKitTransport(options = {}) {
|
|
|
3329
3350
|
? messageEvent.message
|
|
3330
3351
|
: undefined));
|
|
3331
3352
|
}
|
|
3353
|
+
async function readQueuedSubmissionStatus(threadId, messageId) {
|
|
3354
|
+
const requestHeaders = await headers({ sessionId: threadId });
|
|
3355
|
+
requestHeaders.set(AGENT_CHAT_THREAD_ABSENCE_HEADER, "typed");
|
|
3356
|
+
const response = await fetcher(scopedThreadEndpoint(`${apiUrl}/threads/${encodeURIComponent(threadId)}/queue/${encodeURIComponent(messageId)}/receipt`, options), { headers: requestHeaders });
|
|
3357
|
+
if (response.status === 404)
|
|
3358
|
+
return null;
|
|
3359
|
+
if (!response.ok)
|
|
3360
|
+
throw await responseError(response);
|
|
3361
|
+
return parseNullableAgentQueuedSubmissionStatus(await response.json());
|
|
3362
|
+
}
|
|
3363
|
+
async function reconcileQueuedSubmission(threadId, messageId) {
|
|
3364
|
+
const status = await readQueuedSubmissionStatus(threadId, messageId);
|
|
3365
|
+
if (!status) {
|
|
3366
|
+
throw new TypeError(`Receipt-managed queue message ${messageId} has no submission receipt.`);
|
|
3367
|
+
}
|
|
3368
|
+
if (status.state === "submitted") {
|
|
3369
|
+
if (!status.submittedRunId) {
|
|
3370
|
+
throw new TypeError(`Submitted queue message ${messageId} has no run ID.`);
|
|
3371
|
+
}
|
|
3372
|
+
return {
|
|
3373
|
+
runId: status.submittedRunId,
|
|
3374
|
+
alreadySubmitted: true,
|
|
3375
|
+
};
|
|
3376
|
+
}
|
|
3377
|
+
if (status.state === "removed" || status.state === "expired") {
|
|
3378
|
+
return { alreadyRemoved: true };
|
|
3379
|
+
}
|
|
3380
|
+
if (status.state === "blocked") {
|
|
3381
|
+
const error = new Error(`Queued submission ${messageId} is blocked in the server inbox.`);
|
|
3382
|
+
Object.assign(error, { code: "queue_item_blocked", retryable: false });
|
|
3383
|
+
throw error;
|
|
3384
|
+
}
|
|
3385
|
+
const error = new Error(`Queued submission ${messageId} is still waiting in the server inbox.`);
|
|
3386
|
+
Object.assign(error, { code: "queue_item_busy", retryable: true });
|
|
3387
|
+
throw error;
|
|
3388
|
+
}
|
|
3332
3389
|
const runtime = options.runtime ?? createAgentNativeChatRuntime(options);
|
|
3333
3390
|
const feedbackUrl = options.feedbackUrl ??
|
|
3334
3391
|
agentNativePath("/_agent-native/observability/feedback");
|
|
@@ -3360,7 +3417,10 @@ export function createAgentNativeAgentKitTransport(options = {}) {
|
|
|
3360
3417
|
},
|
|
3361
3418
|
getThreadSnapshot: ({ threadId }) => threadSnapshotWithActiveRun(threadId),
|
|
3362
3419
|
listQueuedMessages: async ({ threadId }) => readQueue(threadId),
|
|
3363
|
-
|
|
3420
|
+
getQueuedSubmissionStatus: async ({ threadId, messageId }) => {
|
|
3421
|
+
return readQueuedSubmissionStatus(threadId, messageId);
|
|
3422
|
+
},
|
|
3423
|
+
queueMessage: async ({ threadId, id, text, attachments, requestAttachments, references, metadata, options: runOptions, interruptActiveRun, submissionPayload, }) => {
|
|
3364
3424
|
const queueSubmissionPayload = submissionPayload
|
|
3365
3425
|
? { ...submissionPayload, metadata }
|
|
3366
3426
|
: undefined;
|
|
@@ -3375,6 +3435,7 @@ export function createAgentNativeAgentKitTransport(options = {}) {
|
|
|
3375
3435
|
createdAt: now(),
|
|
3376
3436
|
attachments,
|
|
3377
3437
|
requestAttachments,
|
|
3438
|
+
references,
|
|
3378
3439
|
metadata,
|
|
3379
3440
|
options: runOptions,
|
|
3380
3441
|
...(interruptActiveRun ? { interruptActiveRun: true } : {}),
|
|
@@ -3405,7 +3466,8 @@ export function createAgentNativeAgentKitTransport(options = {}) {
|
|
|
3405
3466
|
return { message: result.message };
|
|
3406
3467
|
},
|
|
3407
3468
|
removeQueuedMessage: async ({ threadId, messageId }) => {
|
|
3408
|
-
await persistQueueMutation(threadId, { type: "
|
|
3469
|
+
await persistQueueMutation(threadId, { type: "cancel", messageId });
|
|
3470
|
+
clearPromotionClaimId(threadId, messageId);
|
|
3409
3471
|
},
|
|
3410
3472
|
moveQueuedMessageToTop: async ({ threadId, messageId }) => {
|
|
3411
3473
|
await persistQueueMutation(threadId, { type: "moveToTop", messageId });
|
|
@@ -3457,6 +3519,11 @@ export function createAgentNativeAgentKitTransport(options = {}) {
|
|
|
3457
3519
|
clearPromotionClaimId(threadId, messageId);
|
|
3458
3520
|
return { alreadyRemoved: true };
|
|
3459
3521
|
}
|
|
3522
|
+
if (claim.receiptManaged) {
|
|
3523
|
+
clearPromotionClaimId(threadId, messageId);
|
|
3524
|
+
claimHeld = false;
|
|
3525
|
+
return await reconcileQueuedSubmission(threadId, messageId);
|
|
3526
|
+
}
|
|
3460
3527
|
if (!claim.claimedMessage) {
|
|
3461
3528
|
throw new TypeError("Agent chat queue claim response is invalid.");
|
|
3462
3529
|
}
|
|
@@ -3524,6 +3591,11 @@ export function createAgentNativeAgentKitTransport(options = {}) {
|
|
|
3524
3591
|
clearPromotionClaimId(threadId, messageId);
|
|
3525
3592
|
return { alreadyRemoved: true };
|
|
3526
3593
|
}
|
|
3594
|
+
if (claim.receiptManaged) {
|
|
3595
|
+
clearPromotionClaimId(threadId, messageId);
|
|
3596
|
+
claimHeld = false;
|
|
3597
|
+
return await reconcileQueuedSubmission(threadId, messageId);
|
|
3598
|
+
}
|
|
3527
3599
|
if (claim.alreadySubmitted && claim.submittedRunId) {
|
|
3528
3600
|
clearPromotionClaimId(threadId, messageId);
|
|
3529
3601
|
return {
|
|
@@ -3557,6 +3629,7 @@ export function createAgentNativeAgentKitTransport(options = {}) {
|
|
|
3557
3629
|
},
|
|
3558
3630
|
],
|
|
3559
3631
|
requestAttachments: claimedMessage.requestAttachments,
|
|
3632
|
+
references: claimedMessage.references,
|
|
3560
3633
|
options: claimedMessage.options,
|
|
3561
3634
|
metadata: claimedMessage.metadata,
|
|
3562
3635
|
queuePromotion: {
|
|
@@ -3565,6 +3638,9 @@ export function createAgentNativeAgentKitTransport(options = {}) {
|
|
|
3565
3638
|
turnId: `queue-${messageId}`,
|
|
3566
3639
|
},
|
|
3567
3640
|
}, undefined);
|
|
3641
|
+
if (!run.runId) {
|
|
3642
|
+
throw new TypeError("A queue promotion cannot be acknowledged as a new queued submission.");
|
|
3643
|
+
}
|
|
3568
3644
|
const latestThread = await snapshot(threadId);
|
|
3569
3645
|
if (!latestThread) {
|
|
3570
3646
|
throw new Error(`Unknown agent chat thread: ${threadId}`);
|