@agent-native/core 0.214.0 → 0.216.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/application-state/store.d.ts +5 -0
- package/dist/application-state/store.js +26 -0
- 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.js +167 -17
- 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 +36 -0
- package/dist/client/consent.js +283 -0
- package/dist/client/review/use-review.d.ts +2 -0
- package/dist/client/review/use-review.js +28 -1
- 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/collab/routes.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- 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/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/observability/actions/save-observability-instruction-update.js +5 -0
- package/dist/observability/actions/save-observability-review-summary.js +5 -0
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +18 -18
- package/dist/provider-api/actions/provider-api.d.ts +14 -14
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/provider-api/index.js +9 -2
- 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-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-api-key-route.d.ts +1 -1
- package/dist/server/agent-engine-default-model-route.d.ts +2 -2
- package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
- 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/consent-route.d.ts +41 -0
- package/dist/server/consent-route.js +102 -0
- 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 +1 -0
- package/dist/server/index.js +1 -0
- 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 +31 -0
- package/dist/shared/consent.js +145 -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 +1 -1
- 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/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 +4 -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
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, whenConsentAllows } 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";
|
|
@@ -174,6 +178,11 @@ const LAST_TOUCH_COOKIE = {
|
|
|
174
178
|
priority: LAST_TOUCH_COOKIE_FIELD_PRIORITY,
|
|
175
179
|
};
|
|
176
180
|
let _firstTouchCaptured = false;
|
|
181
|
+
// Bounds the resend after a response race; see `syncFirstTouchToServer`.
|
|
182
|
+
let _firstTouchSyncsLeft = 2;
|
|
183
|
+
// Set when this page wrote `an_ft` or `an_lt`, which the server then writes
|
|
184
|
+
// again: Safari keeps a cookie page JavaScript wrote for seven days at most.
|
|
185
|
+
let _attributionCookieWritten = false;
|
|
177
186
|
function safeStorageGet(key) {
|
|
178
187
|
try {
|
|
179
188
|
return window.localStorage.getItem(key);
|
|
@@ -190,6 +199,14 @@ function safeStorageSet(key, value) {
|
|
|
190
199
|
// private browsing / storage disabled — best-effort
|
|
191
200
|
}
|
|
192
201
|
}
|
|
202
|
+
function safeStorageRemove(key) {
|
|
203
|
+
try {
|
|
204
|
+
window.localStorage.removeItem(key);
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
// coercion-ok: storage that can't be read holds nothing to remove.
|
|
208
|
+
}
|
|
209
|
+
}
|
|
193
210
|
function readCachedLlmConnectionStatus() {
|
|
194
211
|
if (typeof window === "undefined")
|
|
195
212
|
return null;
|
|
@@ -536,6 +553,7 @@ function writeAttributionCookie(value, spec) {
|
|
|
536
553
|
const encodedValue = fitAttributionCookieValue(value, spec);
|
|
537
554
|
try {
|
|
538
555
|
document.cookie = attributionCookieAssignment(spec.name, encodedValue);
|
|
556
|
+
_attributionCookieWritten = true;
|
|
539
557
|
}
|
|
540
558
|
catch {
|
|
541
559
|
// best-effort
|
|
@@ -564,16 +582,132 @@ function backfillAttributionCookie(storageKey, spec) {
|
|
|
564
582
|
// signup handoff goes without it.
|
|
565
583
|
}
|
|
566
584
|
}
|
|
585
|
+
/** Remove every stored touch, in storage and cookies. */
|
|
586
|
+
function clearStoredAttribution() {
|
|
587
|
+
safeStorageRemove(FIRST_TOUCH_STORAGE_KEY);
|
|
588
|
+
safeStorageRemove(LAST_TOUCH_STORAGE_KEY);
|
|
589
|
+
if (typeof document === "undefined")
|
|
590
|
+
return;
|
|
591
|
+
for (const name of [
|
|
592
|
+
FIRST_TOUCH_COOKIE_NAME,
|
|
593
|
+
LAST_TOUCH_COOKIE_NAME,
|
|
594
|
+
FIRST_TOUCH_SERVER_COOKIE_NAME,
|
|
595
|
+
]) {
|
|
596
|
+
try {
|
|
597
|
+
document.cookie = `${name}=; path=/; max-age=0; SameSite=Lax`;
|
|
598
|
+
}
|
|
599
|
+
catch {
|
|
600
|
+
// coercion-ok: a sandboxed iframe can't read or write cookies, so
|
|
601
|
+
// there is none here to clear.
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
/** The year-long copy our server keeps in `an_fts`. */
|
|
606
|
+
function readServerFirstTouch() {
|
|
607
|
+
const touch = readAttributionCookieValue(FIRST_TOUCH_SERVER_COOKIE_NAME);
|
|
608
|
+
if (!touch || touch.v !== FIRST_TOUCH_SERVER_COOKIE_VERSION)
|
|
609
|
+
return null;
|
|
610
|
+
const { v: _version, ...firstTouch } = touch;
|
|
611
|
+
return firstTouch;
|
|
612
|
+
}
|
|
567
613
|
/**
|
|
568
|
-
*
|
|
569
|
-
*
|
|
570
|
-
*
|
|
571
|
-
|
|
614
|
+
* The browser's own copies: localStorage, then the 30-day `an_ft` cookie. A
|
|
615
|
+
* visit more than a year old no longer counts, or the cookie it's copied back
|
|
616
|
+
* into would keep it going.
|
|
617
|
+
*/
|
|
618
|
+
function readLocalFirstTouch() {
|
|
619
|
+
const touch = readStoredAttribution(FIRST_TOUCH_STORAGE_KEY, FIRST_TOUCH_COOKIE_NAME);
|
|
620
|
+
return touch && firstTouchServerExpiry(touch) ? touch : null;
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* The server writes `an_lt` again from each request's cookies, so a slow
|
|
624
|
+
* response from an older page can put back an older last touch. The newest
|
|
625
|
+
* one is in localStorage. Returns whether it had to write it back.
|
|
626
|
+
*/
|
|
627
|
+
function restoreNewestLastTouchCookie() {
|
|
628
|
+
const stored = safeStorageGet(LAST_TOUCH_STORAGE_KEY);
|
|
629
|
+
const newest = parseAttribution(stored);
|
|
630
|
+
if (!stored || !newest)
|
|
631
|
+
return false;
|
|
632
|
+
const cookie = readAttributionCookieValue(LAST_TOUCH_COOKIE_NAME);
|
|
633
|
+
if (Date.parse(cookie?.touched_at ?? "") >= Date.parse(newest.touched_at ?? "")) {
|
|
634
|
+
return false;
|
|
635
|
+
}
|
|
636
|
+
writeAttributionCookie(stored, LAST_TOUCH_COOKIE);
|
|
637
|
+
return true;
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* Ask our server to keep `firstTouch` in its year-long cookie, unless it
|
|
641
|
+
* already holds that visit and this page wrote no attribution cookie; the
|
|
642
|
+
* same request has the server write `an_ft` and `an_lt` again. Two tabs can each send a touch before either
|
|
643
|
+
* response lands, and the later response wins the cookie, so when ours
|
|
644
|
+
* leaves a worse touch there than this browser holds, send the better one
|
|
645
|
+
* again. Until the server holds it, signup still reads `an_ft`.
|
|
646
|
+
*/
|
|
647
|
+
function syncFirstTouchToServer(firstTouch) {
|
|
648
|
+
if (!_attributionCookieWritten &&
|
|
649
|
+
isSameFirstTouch(readServerFirstTouch(), firstTouch)) {
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
// An embed that must not call our API (the Builder shell canvas) keeps only
|
|
653
|
+
// the browser's copies.
|
|
654
|
+
if (agentNativeApiDisabledReason())
|
|
655
|
+
return;
|
|
656
|
+
if (_firstTouchSyncsLeft <= 0 || typeof fetch !== "function")
|
|
657
|
+
return;
|
|
658
|
+
_firstTouchSyncsLeft -= 1;
|
|
659
|
+
_attributionCookieWritten = false;
|
|
660
|
+
void fetch(agentNativePath(FIRST_TOUCH_SERVER_PATH), {
|
|
661
|
+
method: "POST",
|
|
662
|
+
credentials: "same-origin",
|
|
663
|
+
keepalive: true,
|
|
664
|
+
headers: { "Content-Type": "application/json" },
|
|
665
|
+
body: JSON.stringify({ firstTouch }),
|
|
666
|
+
})
|
|
667
|
+
.then(async (response) => {
|
|
668
|
+
if (!response.ok)
|
|
669
|
+
return;
|
|
670
|
+
const result = (await response.json());
|
|
671
|
+
// The visitor may have rejected while this request was out.
|
|
672
|
+
if (result.reason === "consent_required" ||
|
|
673
|
+
!consentAllowsNow("targeting")) {
|
|
674
|
+
clearStoredAttribution();
|
|
675
|
+
return;
|
|
676
|
+
}
|
|
677
|
+
// Written back by page JavaScript, Safari would keep it a week.
|
|
678
|
+
const repaired = restoreNewestLastTouchCookie();
|
|
679
|
+
const server = readServerFirstTouch();
|
|
680
|
+
const local = readLocalFirstTouch();
|
|
681
|
+
if (!server)
|
|
682
|
+
return;
|
|
683
|
+
if (isSameFirstTouch(server, local)) {
|
|
684
|
+
if (repaired && local)
|
|
685
|
+
syncFirstTouchToServer(local);
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
if (preferFirstTouch(server, local) === server) {
|
|
689
|
+
storeAttribution(FIRST_TOUCH_STORAGE_KEY, FIRST_TOUCH_COOKIE, server);
|
|
690
|
+
}
|
|
691
|
+
else if (local) {
|
|
692
|
+
syncFirstTouchToServer(local);
|
|
693
|
+
}
|
|
694
|
+
})
|
|
695
|
+
.catch(() => {
|
|
696
|
+
// coercion-ok: the 30-day `an_ft` cookie still carries first touch to
|
|
697
|
+
// signup; the next page load tries again.
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
/**
|
|
701
|
+
* Capture the visitor's referral attribution once per page load, into
|
|
702
|
+
* `localStorage`, a first-party cookie the signup boundary reads, and the
|
|
703
|
+
* server's year-long copy. Fully defensive and SSR-safe — any failure is
|
|
704
|
+
* swallowed so it can never break app boot.
|
|
572
705
|
*
|
|
573
|
-
* First touch (`an_attribution` / `an_ft`) is first
|
|
574
|
-
*
|
|
575
|
-
*
|
|
576
|
-
* tagged visit after it.
|
|
706
|
+
* First touch (`an_attribution` / `an_ft` / `an_fts`) is the first visit that
|
|
707
|
+
* said where this person came from, else the first visit; see
|
|
708
|
+
* `preferFirstTouch`. Without that, an untagged first visit would hide every
|
|
709
|
+
* tagged visit after it. When the browser's copies are gone, as Safari clears
|
|
710
|
+
* them, the server's copy restores them.
|
|
577
711
|
*/
|
|
578
712
|
function captureFirstTouchAttribution(options = {}) {
|
|
579
713
|
if (_firstTouchCaptured)
|
|
@@ -582,16 +716,32 @@ function captureFirstTouchAttribution(options = {}) {
|
|
|
582
716
|
if (typeof window === "undefined")
|
|
583
717
|
return;
|
|
584
718
|
try {
|
|
719
|
+
// Read the visit now: the URL can change before the visitor consents.
|
|
585
720
|
const current = buildFirstTouchAttribution(options.landingPath ?? window.location.pathname);
|
|
586
|
-
const
|
|
587
|
-
|
|
588
|
-
|
|
721
|
+
const forwarded = readForwardedLastTouch();
|
|
722
|
+
const forwardedAt = readForwardedLastTouchAt();
|
|
723
|
+
// Where the banner applies, nothing is stored until the visitor accepts
|
|
724
|
+
// targeting cookies, and a later "reject" clears it again.
|
|
725
|
+
whenConsentAllows("targeting", () => storeTouches(current, forwarded, forwardedAt), { optimistic: true, revoke: clearStoredAttribution });
|
|
726
|
+
}
|
|
727
|
+
catch {
|
|
728
|
+
// coercion-ok: attribution is best-effort telemetry; never let it break
|
|
729
|
+
// boot.
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
function storeTouches(current, forwarded, forwardedAt) {
|
|
733
|
+
try {
|
|
734
|
+
const local = readLocalFirstTouch();
|
|
735
|
+
// The same visit in both keeps the local copy, which was never trimmed.
|
|
736
|
+
const firstTouch = preferFirstTouch(preferFirstTouch(local, readServerFirstTouch()), current);
|
|
737
|
+
if (firstTouch === local) {
|
|
589
738
|
backfillAttributionCookie(FIRST_TOUCH_STORAGE_KEY, FIRST_TOUCH_COOKIE);
|
|
590
739
|
}
|
|
591
740
|
else {
|
|
592
|
-
storeAttribution(FIRST_TOUCH_STORAGE_KEY, FIRST_TOUCH_COOKIE,
|
|
741
|
+
storeAttribution(FIRST_TOUCH_STORAGE_KEY, FIRST_TOUCH_COOKIE, firstTouch);
|
|
593
742
|
}
|
|
594
|
-
captureLastTouchAttribution(current);
|
|
743
|
+
captureLastTouchAttribution(current, forwarded, forwardedAt);
|
|
744
|
+
syncFirstTouchToServer(firstTouch);
|
|
595
745
|
}
|
|
596
746
|
catch {
|
|
597
747
|
// Attribution is best-effort telemetry; never let it break boot.
|
|
@@ -604,10 +754,8 @@ function captureFirstTouchAttribution(options = {}) {
|
|
|
604
754
|
* visit keeps the time it happened, and loses to a newer visit the app has
|
|
605
755
|
* already recorded.
|
|
606
756
|
*/
|
|
607
|
-
function captureLastTouchAttribution(current) {
|
|
608
|
-
const forwarded = readForwardedLastTouch();
|
|
757
|
+
function captureLastTouchAttribution(current, forwarded, forwardedAt) {
|
|
609
758
|
const source = forwarded ?? (hasAttributionSource(current) ? current : null);
|
|
610
|
-
const forwardedAt = readForwardedLastTouchAt();
|
|
611
759
|
const existing = getLastTouchAttribution();
|
|
612
760
|
const existingAt = Date.parse(existing?.touched_at ?? "");
|
|
613
761
|
if (!source ||
|
|
@@ -702,7 +850,9 @@ function readStoredAttribution(storageKey, cookieName) {
|
|
|
702
850
|
return hasAttributionSource(cookie) ? cookie : (stored ?? cookie);
|
|
703
851
|
}
|
|
704
852
|
export function getFirstTouchAttribution() {
|
|
705
|
-
|
|
853
|
+
if (typeof window === "undefined")
|
|
854
|
+
return null;
|
|
855
|
+
return preferFirstTouch(readLocalFirstTouch(), readServerFirstTouch());
|
|
706
856
|
}
|
|
707
857
|
export function getLastTouchAttribution() {
|
|
708
858
|
return readStoredAttribution(LAST_TOUCH_STORAGE_KEY, LAST_TOUCH_COOKIE_NAME);
|
|
@@ -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}`);
|
|
@@ -81,53 +81,56 @@ function runtimeAttachmentFromFilePart(part) {
|
|
|
81
81
|
function runtimeRequestAttachments(args) {
|
|
82
82
|
const attachments = args.message?.parts.flatMap((part) => part.type === "file" ? [runtimeAttachmentFromFilePart(part)] : []) ?? [];
|
|
83
83
|
for (const requestAttachment of args.requestAttachments ?? []) {
|
|
84
|
-
const
|
|
85
|
-
const
|
|
86
|
-
|
|
84
|
+
const referenceUrl = requestAttachment.referenceUrl;
|
|
85
|
+
const originalUrl = referenceUrl;
|
|
86
|
+
const originalLookupUrl = originalUrl ?? requestAttachment.url;
|
|
87
|
+
const originalIndex = originalLookupUrl
|
|
88
|
+
? attachments.findIndex((attachment) => attachment.url === originalLookupUrl)
|
|
87
89
|
: -1;
|
|
90
|
+
const addReferenceOnly = (replaceOriginal) => {
|
|
91
|
+
const original = originalIndex >= 0 ? attachments[originalIndex] : null;
|
|
92
|
+
const reference = {
|
|
93
|
+
type: "file",
|
|
94
|
+
name: original?.name || requestAttachment.name,
|
|
95
|
+
contentType: original?.contentType || requestAttachment.contentType,
|
|
96
|
+
...(original?.id ? { id: original.id } : {}),
|
|
97
|
+
...(original?.mediaType ? { mediaType: original.mediaType } : {}),
|
|
98
|
+
url: originalLookupUrl,
|
|
99
|
+
referenceOnly: true,
|
|
100
|
+
};
|
|
101
|
+
if (replaceOriginal && originalIndex >= 0) {
|
|
102
|
+
attachments.splice(originalIndex, 1, reference);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
attachments.push(reference);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
88
108
|
if (typeof requestAttachment.data === "string") {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
109
|
+
// The image's identity is exactly what the client fingerprinted: its own
|
|
110
|
+
// url, never one derived from referenceUrl. An original file part is kept
|
|
111
|
+
// as a reference (even when the image shares its url), so the submitted
|
|
112
|
+
// file fingerprint still matches the mapped attachments.
|
|
113
|
+
const imageUrl = requestAttachment.url;
|
|
114
|
+
const keepsOriginalReference = originalIndex >= 0 ||
|
|
115
|
+
(originalUrl !== undefined &&
|
|
116
|
+
imageUrl !== undefined &&
|
|
117
|
+
originalUrl !== imageUrl);
|
|
93
118
|
if (keepsOriginalReference) {
|
|
94
|
-
|
|
95
|
-
const reference = {
|
|
96
|
-
type: "file",
|
|
97
|
-
name: original?.name || requestAttachment.name,
|
|
98
|
-
contentType: original?.contentType || requestAttachment.contentType,
|
|
99
|
-
url: originalUrl,
|
|
100
|
-
referenceOnly: true,
|
|
101
|
-
};
|
|
102
|
-
if (originalIndex >= 0)
|
|
103
|
-
attachments.splice(originalIndex, 1, reference);
|
|
104
|
-
else
|
|
105
|
-
attachments.push(reference);
|
|
119
|
+
addReferenceOnly(originalIndex >= 0);
|
|
106
120
|
}
|
|
107
|
-
|
|
121
|
+
attachments.push({
|
|
108
122
|
type: "image",
|
|
109
123
|
name: requestAttachment.name,
|
|
110
124
|
contentType: requestAttachment.contentType,
|
|
111
125
|
data: requestAttachment.data,
|
|
112
126
|
...(imageUrl ? { url: imageUrl } : {}),
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
attachments.splice(originalIndex, 1, image);
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
attachments.push(image);
|
|
119
|
-
}
|
|
127
|
+
...(referenceUrl ? { referenceUrl } : {}),
|
|
128
|
+
});
|
|
120
129
|
continue;
|
|
121
130
|
}
|
|
122
|
-
if (
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
type: "file",
|
|
126
|
-
name: original.name || requestAttachment.name,
|
|
127
|
-
contentType: original.contentType,
|
|
128
|
-
url: originalUrl,
|
|
129
|
-
referenceOnly: true,
|
|
130
|
-
});
|
|
131
|
+
if (originalUrl &&
|
|
132
|
+
(originalIndex < 0 || requestAttachment.url !== originalUrl)) {
|
|
133
|
+
addReferenceOnly(originalIndex >= 0);
|
|
131
134
|
}
|
|
132
135
|
if (typeof requestAttachment.url === "string") {
|
|
133
136
|
attachments.push({
|
|
@@ -135,6 +138,7 @@ function runtimeRequestAttachments(args) {
|
|
|
135
138
|
name: requestAttachment.name,
|
|
136
139
|
contentType: requestAttachment.contentType,
|
|
137
140
|
url: requestAttachment.url,
|
|
141
|
+
...(referenceUrl ? { referenceUrl } : {}),
|
|
138
142
|
});
|
|
139
143
|
}
|
|
140
144
|
}
|
|
@@ -189,6 +193,17 @@ function mergeProtocolMetadata(...sources) {
|
|
|
189
193
|
}
|
|
190
194
|
return merged;
|
|
191
195
|
}
|
|
196
|
+
function withQueuedMessageIdMetadata(metadata, messageId) {
|
|
197
|
+
if (messageId === undefined)
|
|
198
|
+
return metadata;
|
|
199
|
+
return {
|
|
200
|
+
...metadata,
|
|
201
|
+
custom: {
|
|
202
|
+
...asRecord(metadata?.custom),
|
|
203
|
+
agentNativeQueuedMessageId: messageId,
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
}
|
|
192
207
|
const PROTECTED_PROTOCOL_METADATA_KEYS = [
|
|
193
208
|
"actor",
|
|
194
209
|
"workspace",
|
|
@@ -1504,7 +1519,7 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
|
|
|
1504
1519
|
*/
|
|
1505
1520
|
async function openStartedRun(threadId, session, turn, turnMetadata, observability, start = {}) {
|
|
1506
1521
|
const runId = turn.runId ?? turn.id ?? createId("run");
|
|
1507
|
-
const runMetadata = mergeTrustedProtocolMetadata(options.metadata, turnMetadata, turn.metadata, {
|
|
1522
|
+
const runMetadata = withQueuedMessageIdMetadata(mergeTrustedProtocolMetadata(options.metadata, turnMetadata, turn.metadata, {
|
|
1508
1523
|
[AGENT_NATIVE_PROTOCOL_METADATA_KEY]: {
|
|
1509
1524
|
observability: {
|
|
1510
1525
|
protocolRunId: runId,
|
|
@@ -1516,7 +1531,7 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
|
|
|
1516
1531
|
...observability,
|
|
1517
1532
|
},
|
|
1518
1533
|
},
|
|
1519
|
-
});
|
|
1534
|
+
}), start.queuedMessageId);
|
|
1520
1535
|
setRuntimeRunIdMetadata(runMetadata, turn.runId);
|
|
1521
1536
|
setRuntimeTurnIdMetadata(runMetadata, turn.id);
|
|
1522
1537
|
const run = {
|
|
@@ -3127,7 +3142,11 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
|
|
|
3127
3142
|
const latestUserMetadata = asRecord(latestUserMessage?.metadata);
|
|
3128
3143
|
const recoveryMetadata = asRecord(latestUserMetadata?.custom);
|
|
3129
3144
|
const isRecoveryRetry = recoveryMetadata?.agentNativeRecoveryAction === "retry";
|
|
3130
|
-
const turnMetadata = mergeTrustedProtocolMetadata(options.metadata, input.metadata, input.options?.metadata, input.options?.agentId
|
|
3145
|
+
const turnMetadata = withQueuedMessageIdMetadata(mergeTrustedProtocolMetadata(options.metadata, input.metadata, input.options?.metadata, input.options?.agentId
|
|
3146
|
+
? { agentId: input.options.agentId }
|
|
3147
|
+
: undefined, input.options?.locale ? { locale: input.options.locale } : undefined, input.options?.mode ? { mode: input.options.mode } : undefined, isRecoveryRetry
|
|
3148
|
+
? { agentNativeInternalContinuation: true }
|
|
3149
|
+
: undefined), input.queuePromotion?.messageId);
|
|
3131
3150
|
const queuePromotionKey = input.queuePromotion
|
|
3132
3151
|
? JSON.stringify([input.threadId, input.queuePromotion.turnId])
|
|
3133
3152
|
: undefined;
|
|
@@ -3153,9 +3172,11 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
|
|
|
3153
3172
|
const turn = await session.startTurn({
|
|
3154
3173
|
prompt: latestUserPrompt(input.messages),
|
|
3155
3174
|
messages,
|
|
3175
|
+
...(input.options ? { options: input.options } : {}),
|
|
3156
3176
|
...(input.submissionPayload
|
|
3157
3177
|
? { submissionPayload: input.submissionPayload }
|
|
3158
3178
|
: {}),
|
|
3179
|
+
...(input.references?.length ? { references: input.references } : {}),
|
|
3159
3180
|
...(input.queuePromotion
|
|
3160
3181
|
? { queuePromotion: input.queuePromotion }
|
|
3161
3182
|
: {}),
|
|
@@ -3174,15 +3195,29 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
|
|
|
3174
3195
|
metadata: turnMetadata,
|
|
3175
3196
|
abortSignal: readers.signal,
|
|
3176
3197
|
});
|
|
3198
|
+
if (turn.queuedSubmission)
|
|
3199
|
+
return turn.queuedSubmission;
|
|
3177
3200
|
return openStartedRun(input.threadId, session, turn, turnMetadata, undefined, {
|
|
3178
3201
|
attachReplayedRun: true,
|
|
3179
3202
|
messageId: latestUserMessage?.id,
|
|
3203
|
+
...(input.queuePromotion
|
|
3204
|
+
? { queuedMessageId: input.queuePromotion.messageId }
|
|
3205
|
+
: {}),
|
|
3180
3206
|
});
|
|
3181
3207
|
};
|
|
3182
3208
|
if (!queuePromotionKey) {
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3209
|
+
const started = await createRun();
|
|
3210
|
+
return typeof started === "string"
|
|
3211
|
+
? { runId: started, capabilities }
|
|
3212
|
+
: { queuedSubmission: started, capabilities };
|
|
3213
|
+
}
|
|
3214
|
+
const pendingRun = Promise.resolve().then(async () => {
|
|
3215
|
+
const started = await createRun();
|
|
3216
|
+
if (typeof started !== "string") {
|
|
3217
|
+
throw new TypeError("A queue promotion cannot be acknowledged as a new queued submission.");
|
|
3218
|
+
}
|
|
3219
|
+
return started;
|
|
3220
|
+
});
|
|
3186
3221
|
pendingQueuePromotionRuns.set(queuePromotionKey, pendingRun);
|
|
3187
3222
|
try {
|
|
3188
3223
|
return { runId: await pendingRun, capabilities };
|
|
@@ -3806,6 +3841,9 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
|
|
|
3806
3841
|
transport.cancelUpload = hostOperations.cancelUpload;
|
|
3807
3842
|
if (hostOperations?.listQueuedMessages)
|
|
3808
3843
|
transport.listQueuedMessages = hostOperations.listQueuedMessages;
|
|
3844
|
+
if (hostOperations?.getQueuedSubmissionStatus)
|
|
3845
|
+
transport.getQueuedSubmissionStatus =
|
|
3846
|
+
hostOperations.getQueuedSubmissionStatus;
|
|
3809
3847
|
if (hostOperations?.queueMessage) {
|
|
3810
3848
|
transport.queueMessage = (input, context) => {
|
|
3811
3849
|
const metadata = mergeTrustedProtocolMetadata(options.metadata, input.metadata);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AgentRunOptions, type AgentSubmissionReference, type AgentQueuedSubmissionReceipt, type AgentSuggestion } from "@agent-native/agentkit/protocol";
|
|
2
2
|
import type { ActionChatUIConfig } from "../../action-ui.js";
|
|
3
3
|
import type { AgentMcpAppPayload } from "../../mcp-client/app-result.js";
|
|
4
4
|
import type { ReasoningEffort } from "../../shared/reasoning-effort.js";
|
|
@@ -89,6 +89,7 @@ export interface AgentChatRuntimeAttachment {
|
|
|
89
89
|
readonly contentType?: string;
|
|
90
90
|
readonly data?: string;
|
|
91
91
|
readonly url?: string;
|
|
92
|
+
readonly referenceUrl?: string;
|
|
92
93
|
readonly text?: string;
|
|
93
94
|
readonly metadata?: AgentChatRuntimeMetadata;
|
|
94
95
|
}
|
|
@@ -218,6 +219,8 @@ export interface AgentChatRuntimeTurnInput {
|
|
|
218
219
|
readonly prompt?: string;
|
|
219
220
|
readonly messages?: readonly AgentChatRuntimeMessage[];
|
|
220
221
|
readonly submissionPayload?: unknown;
|
|
222
|
+
readonly options?: AgentRunOptions;
|
|
223
|
+
readonly references?: readonly AgentSubmissionReference[];
|
|
221
224
|
readonly queuePromotion?: {
|
|
222
225
|
readonly messageId: string;
|
|
223
226
|
readonly claimId: string;
|
|
@@ -549,6 +552,7 @@ export interface AgentChatRuntimeTurn<TEvent extends AgentChatRuntimeEventBase =
|
|
|
549
552
|
readonly sessionId: AgentChatRuntimeSessionId;
|
|
550
553
|
readonly runId?: string;
|
|
551
554
|
readonly metadata?: AgentChatRuntimeMetadata;
|
|
555
|
+
readonly queuedSubmission?: AgentQueuedSubmissionReceipt;
|
|
552
556
|
readonly events: AsyncIterable<TEvent>;
|
|
553
557
|
/** Close the local event stream without cancelling the underlying run. */
|
|
554
558
|
closeEvents?(): Promise<void> | void;
|