@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
|
@@ -3,6 +3,7 @@ import { resolveLaneEndpoint } from "../shared/environment-lanes.js";
|
|
|
3
3
|
import { loadOptionalPeer, OptionalPeerDependencyError, } from "../shared/optional-peer.js";
|
|
4
4
|
import { isSyntheticTrafficValue } from "../shared/test-traffic.js";
|
|
5
5
|
import { getOrCreateAnalyticsAnonymousId, getOrCreateAnalyticsSessionId, } from "./analytics-session.js";
|
|
6
|
+
import { whenConsentAllows } from "./consent.js";
|
|
6
7
|
import { replayEndpointFromAnalyticsEndpoint } from "./session-replay-endpoint.js";
|
|
7
8
|
import { SESSION_REPLAY_BLOCK_ATTRIBUTE, SESSION_REPLAY_MASK_ATTRIBUTE, } from "./session-replay-privacy.js";
|
|
8
9
|
import { decideReplayQuotaResponse, parseRetryAfterSeconds, } from "./session-replay-quota.js";
|
|
@@ -1173,6 +1174,8 @@ function isDefinitiveReplayUploadClientError(status) {
|
|
|
1173
1174
|
}
|
|
1174
1175
|
const MAX_TRANSIENT_REPLAY_CLIENT_FAILURES = 3;
|
|
1175
1176
|
const REPLAY_UPLOAD_TIMEOUT_MS = 15_000;
|
|
1177
|
+
// Uploads in flight, so a consent reject can abort them.
|
|
1178
|
+
const activeReplayUploads = new Set();
|
|
1176
1179
|
function startReplayUploadTimeout() {
|
|
1177
1180
|
const controller = typeof AbortController === "undefined" ? undefined : new AbortController();
|
|
1178
1181
|
let rejectTimeout;
|
|
@@ -1186,11 +1189,17 @@ function startReplayUploadTimeout() {
|
|
|
1186
1189
|
controller?.abort();
|
|
1187
1190
|
rejectTimeout(timeoutError);
|
|
1188
1191
|
}, REPLAY_UPLOAD_TIMEOUT_MS);
|
|
1192
|
+
if (controller)
|
|
1193
|
+
activeReplayUploads.add(controller);
|
|
1189
1194
|
return {
|
|
1190
1195
|
signal: controller?.signal,
|
|
1191
1196
|
promise,
|
|
1192
1197
|
didTimeout: () => timedOut,
|
|
1193
|
-
done: () =>
|
|
1198
|
+
done: () => {
|
|
1199
|
+
clearTimeout(timer);
|
|
1200
|
+
if (controller)
|
|
1201
|
+
activeReplayUploads.delete(controller);
|
|
1202
|
+
},
|
|
1194
1203
|
};
|
|
1195
1204
|
}
|
|
1196
1205
|
function isTransientReplayUploadClientError(status) {
|
|
@@ -1543,6 +1552,13 @@ export async function flushSessionReplay(reason = "manual") {
|
|
|
1543
1552
|
const state = getState();
|
|
1544
1553
|
if (!state.options)
|
|
1545
1554
|
return;
|
|
1555
|
+
if (replayConsentWithdrawn) {
|
|
1556
|
+
// An upload in flight at the reject can put its batch back; drop it.
|
|
1557
|
+
discardWithdrawnReplay(state);
|
|
1558
|
+
for (const resolve of state.pendingFlushWaiters.splice(0))
|
|
1559
|
+
resolve();
|
|
1560
|
+
return;
|
|
1561
|
+
}
|
|
1546
1562
|
if (replayUploadsParked(state, Date.now()))
|
|
1547
1563
|
return;
|
|
1548
1564
|
if (state.pendingReplayUpload) {
|
|
@@ -1586,6 +1602,9 @@ export async function flushSessionReplay(reason = "manual") {
|
|
|
1586
1602
|
return;
|
|
1587
1603
|
}
|
|
1588
1604
|
state.flushing = true;
|
|
1605
|
+
// A reject while this upload is in flight withdraws its events for good,
|
|
1606
|
+
// even if the visitor accepts again before it settles.
|
|
1607
|
+
const consentGeneration = replayConsentGeneration;
|
|
1589
1608
|
let uploaded = false;
|
|
1590
1609
|
let reservedSequence = false;
|
|
1591
1610
|
let splitRejectedBatch = false;
|
|
@@ -1609,6 +1628,9 @@ export async function flushSessionReplay(reason = "manual") {
|
|
|
1609
1628
|
// between; it is queued as the pending reason.
|
|
1610
1629
|
const outcome = await sendReplayUpload(state.options, payload.body, {
|
|
1611
1630
|
beforeUpload: (keepalive) => {
|
|
1631
|
+
// Compression can take long enough for a reject to land first.
|
|
1632
|
+
if (consentGeneration !== replayConsentGeneration)
|
|
1633
|
+
return "defer";
|
|
1612
1634
|
const pendingReason = state.pendingFlushReason;
|
|
1613
1635
|
if (!keepalive &&
|
|
1614
1636
|
(isPageLeaveReplayFlushReason(reason) ||
|
|
@@ -1622,7 +1644,9 @@ export async function flushSessionReplay(reason = "manual") {
|
|
|
1622
1644
|
},
|
|
1623
1645
|
});
|
|
1624
1646
|
if (outcome === "deferred") {
|
|
1625
|
-
|
|
1647
|
+
if (consentGeneration === replayConsentGeneration) {
|
|
1648
|
+
restoreReplayEvents(state, events);
|
|
1649
|
+
}
|
|
1626
1650
|
}
|
|
1627
1651
|
else {
|
|
1628
1652
|
state.automaticConflictRestartAttempted = false;
|
|
@@ -1686,7 +1710,10 @@ export async function flushSessionReplay(reason = "manual") {
|
|
|
1686
1710
|
quotaDecision?.kind === "stop") &&
|
|
1687
1711
|
!splitBatch &&
|
|
1688
1712
|
!isUnsplittableOversizedBatch;
|
|
1689
|
-
if (
|
|
1713
|
+
if (consentGeneration !== replayConsentGeneration) {
|
|
1714
|
+
// Withdrawn while in flight; nothing goes back on the queue.
|
|
1715
|
+
}
|
|
1716
|
+
else if (splitBatch) {
|
|
1690
1717
|
state.retryBatches.unshift(...splitBatch);
|
|
1691
1718
|
splitRejectedBatch = true;
|
|
1692
1719
|
}
|
|
@@ -1811,10 +1838,18 @@ export async function flushSessionReplay(reason = "manual") {
|
|
|
1811
1838
|
if (shouldRestartAfterConflict) {
|
|
1812
1839
|
state.automaticConflictRestartAttempted = true;
|
|
1813
1840
|
}
|
|
1841
|
+
// The stop forgets the caller's start; a recovered recording keeps it,
|
|
1842
|
+
// so a reject and a later accept can bring it back.
|
|
1843
|
+
const consentStartOptions = replayAllowedOptions;
|
|
1814
1844
|
await stopSessionReplay("upload-rejected");
|
|
1815
1845
|
let restartResult = null;
|
|
1816
1846
|
if (shouldRestartAfterConflict && rejectedOptions) {
|
|
1817
1847
|
restartResult = await restartSessionReplayWithFreshIdentity(state, rejectedOptions, payload.sessionId);
|
|
1848
|
+
if (restartResult.started)
|
|
1849
|
+
replayAllowedOptions = consentStartOptions;
|
|
1850
|
+
// A reject during the recovery leaves the start for the next accept.
|
|
1851
|
+
if (!replayConsentGranted)
|
|
1852
|
+
replayAwaitingConsent ??= consentStartOptions;
|
|
1818
1853
|
}
|
|
1819
1854
|
const details = {
|
|
1820
1855
|
status: definitiveClientErrorStatus,
|
|
@@ -1861,6 +1896,16 @@ async function restartSessionReplayWithFreshIdentityInternal(state, options, ses
|
|
|
1861
1896
|
if (options.shouldStart && !options.shouldStart()) {
|
|
1862
1897
|
return { started: false, reason: "disabled", sessionId, sampled: true };
|
|
1863
1898
|
}
|
|
1899
|
+
// Recovery restarts without going through startSessionReplay, so a reject
|
|
1900
|
+
// that landed while the old recording stopped must still hold here.
|
|
1901
|
+
if (!replayConsentGranted) {
|
|
1902
|
+
return {
|
|
1903
|
+
started: false,
|
|
1904
|
+
reason: "consent-required",
|
|
1905
|
+
sessionId,
|
|
1906
|
+
sampled: true,
|
|
1907
|
+
};
|
|
1908
|
+
}
|
|
1864
1909
|
const initialProperties = replayExtraProperties(options);
|
|
1865
1910
|
if (options.requireSignedInUser && !replayUserEmail(initialProperties)) {
|
|
1866
1911
|
return {
|
|
@@ -2687,6 +2732,81 @@ function installCaptureInterceptors(state) {
|
|
|
2687
2732
|
}
|
|
2688
2733
|
};
|
|
2689
2734
|
}
|
|
2735
|
+
let replayConsentWatched = false;
|
|
2736
|
+
let replayConsentGranted = false;
|
|
2737
|
+
let replayConsentWithdrawn = false;
|
|
2738
|
+
let replayConsentGeneration = 0;
|
|
2739
|
+
let replayAllowedOptions = null;
|
|
2740
|
+
function discardWithdrawnReplay(state) {
|
|
2741
|
+
for (const upload of activeReplayUploads)
|
|
2742
|
+
upload.abort();
|
|
2743
|
+
activeReplayUploads.clear();
|
|
2744
|
+
state.queue = [];
|
|
2745
|
+
state.queuedBytes = 0;
|
|
2746
|
+
state.retryBatches = [];
|
|
2747
|
+
state.pendingFlushReason = null;
|
|
2748
|
+
for (const resolve of state.pendingFlushWaiters.splice(0))
|
|
2749
|
+
resolve();
|
|
2750
|
+
}
|
|
2751
|
+
let replayAwaitingConsent = null;
|
|
2752
|
+
let replayCallerStops = 0;
|
|
2753
|
+
/**
|
|
2754
|
+
* Replay waits for analytics consent where the banner applies, without the
|
|
2755
|
+
* time zone's early guess: a recording that already uploaded can't be undone.
|
|
2756
|
+
* A start asked for before the answer runs once consent arrives.
|
|
2757
|
+
*/
|
|
2758
|
+
function replayConsentAllows(options) {
|
|
2759
|
+
if (!replayConsentWatched) {
|
|
2760
|
+
replayConsentWatched = true;
|
|
2761
|
+
whenConsentAllows("performance", () => {
|
|
2762
|
+
replayConsentGranted = true;
|
|
2763
|
+
// What an upload in flight at the reject put back stays withdrawn.
|
|
2764
|
+
if (replayConsentWithdrawn)
|
|
2765
|
+
discardWithdrawnReplay(getState());
|
|
2766
|
+
replayConsentWithdrawn = false;
|
|
2767
|
+
const waiting = replayAwaitingConsent;
|
|
2768
|
+
replayAwaitingConsent = null;
|
|
2769
|
+
if (!waiting)
|
|
2770
|
+
return;
|
|
2771
|
+
// A reject during the last start cancels it, and an accept that
|
|
2772
|
+
// quickly gets that canceled start back; ask once more after it.
|
|
2773
|
+
const stops = replayCallerStops;
|
|
2774
|
+
void startSessionReplay(waiting).then((result) => {
|
|
2775
|
+
if (!result.started &&
|
|
2776
|
+
replayConsentGranted &&
|
|
2777
|
+
!getState().active &&
|
|
2778
|
+
replayCallerStops === stops) {
|
|
2779
|
+
void startSessionReplay(waiting);
|
|
2780
|
+
}
|
|
2781
|
+
});
|
|
2782
|
+
}, {
|
|
2783
|
+
// The region's first answer revokes before any choice, so a start
|
|
2784
|
+
// asked for earlier keeps waiting for an accept.
|
|
2785
|
+
revoke: () => {
|
|
2786
|
+
const wasGranted = replayConsentGranted;
|
|
2787
|
+
replayConsentGranted = false;
|
|
2788
|
+
if (!wasGranted) {
|
|
2789
|
+
// A replay id an earlier page stored never carries past a reject.
|
|
2790
|
+
const storedReplayId = readStoredReplaySession()?.replayId;
|
|
2791
|
+
if (storedReplayId)
|
|
2792
|
+
removeStoredReplaySession(storedReplayId);
|
|
2793
|
+
return;
|
|
2794
|
+
}
|
|
2795
|
+
replayConsentWithdrawn = true;
|
|
2796
|
+
replayConsentGeneration += 1;
|
|
2797
|
+
// A fresh accept on this page records again, under a new identity.
|
|
2798
|
+
replayAwaitingConsent = replayAllowedOptions ?? replayAwaitingConsent;
|
|
2799
|
+
void stopSessionReplay("consent-revoked");
|
|
2800
|
+
},
|
|
2801
|
+
});
|
|
2802
|
+
}
|
|
2803
|
+
if (replayConsentGranted) {
|
|
2804
|
+
replayAllowedOptions = options;
|
|
2805
|
+
return true;
|
|
2806
|
+
}
|
|
2807
|
+
replayAwaitingConsent = options;
|
|
2808
|
+
return false;
|
|
2809
|
+
}
|
|
2690
2810
|
export async function startSessionReplay(options = {}) {
|
|
2691
2811
|
if (isSyntheticBrowserTraffic()) {
|
|
2692
2812
|
return { started: false, reason: "disabled" };
|
|
@@ -2702,6 +2822,9 @@ export async function startSessionReplay(options = {}) {
|
|
|
2702
2822
|
const normalized = normalizeOptions(options);
|
|
2703
2823
|
if (!normalized)
|
|
2704
2824
|
return { started: false, reason: "missing-public-key" };
|
|
2825
|
+
if (!replayConsentAllows(options)) {
|
|
2826
|
+
return { started: false, reason: "consent-required" };
|
|
2827
|
+
}
|
|
2705
2828
|
const sessionId = getOrCreateAnalyticsSessionId();
|
|
2706
2829
|
if (!sessionId)
|
|
2707
2830
|
return { started: false, reason: "missing-session-id" };
|
|
@@ -2965,6 +3088,19 @@ export async function stopSessionReplay(reason = "manual") {
|
|
|
2965
3088
|
if (reason !== "pagehide-persisted") {
|
|
2966
3089
|
state.bfcacheRestored = false;
|
|
2967
3090
|
}
|
|
3091
|
+
if (reason === "consent-revoked") {
|
|
3092
|
+
// Also when recording already stopped: a later accept starts afresh.
|
|
3093
|
+
const storedReplayId = state.replayId ?? readStoredReplaySession()?.replayId;
|
|
3094
|
+
discardWithdrawnReplay(state);
|
|
3095
|
+
if (storedReplayId)
|
|
3096
|
+
removeStoredReplaySession(storedReplayId);
|
|
3097
|
+
}
|
|
3098
|
+
else if (reason !== "upload-timeout") {
|
|
3099
|
+
// Any other stop is final: a later accept doesn't bring it back.
|
|
3100
|
+
replayAwaitingConsent = null;
|
|
3101
|
+
replayAllowedOptions = null;
|
|
3102
|
+
replayCallerStops += 1;
|
|
3103
|
+
}
|
|
2968
3104
|
if (!state.active) {
|
|
2969
3105
|
if (authClearedReplayId)
|
|
2970
3106
|
removeStoredReplaySession(authClearedReplayId);
|
|
@@ -3024,6 +3160,9 @@ export async function stopSessionReplay(reason = "manual") {
|
|
|
3024
3160
|
// best-effort cleanup
|
|
3025
3161
|
}
|
|
3026
3162
|
state.broadcastChannel = null;
|
|
3163
|
+
// A reject withdraws what is still buffered, so it is never uploaded.
|
|
3164
|
+
if (reason === "consent-revoked")
|
|
3165
|
+
return;
|
|
3027
3166
|
const sequenceBeforeFinalFlush = state.sequence;
|
|
3028
3167
|
try {
|
|
3029
3168
|
await flushSessionReplay(reason);
|
|
@@ -30,8 +30,9 @@ export interface ResourceAccessGateOptions {
|
|
|
30
30
|
* Called once when the status says the viewer can open the resource: either
|
|
31
31
|
* the read that failed should be tried again, or the owner shared it while
|
|
32
32
|
* this screen was open. The status is checked again whenever the window
|
|
33
|
-
* regains focus, including switching back from another browser window,
|
|
34
|
-
* every half minute while the viewer's request is open
|
|
33
|
+
* regains focus, including switching back from another browser window,
|
|
34
|
+
* every half minute while the viewer's request is open, and every 12 seconds
|
|
35
|
+
* while the resource is in Trash.
|
|
35
36
|
*/
|
|
36
37
|
onAccessGranted?: () => void;
|
|
37
38
|
}
|
|
@@ -4,6 +4,10 @@ import { useActionMutation, useActionQuery } from "../use-action.js";
|
|
|
4
4
|
// While a request is open, approving it should open the resource without a
|
|
5
5
|
// manual reload, even when the window never loses focus.
|
|
6
6
|
const PENDING_REQUEST_POLL_MS = 30_000;
|
|
7
|
+
// This screen replaces the resource's own view, and with it that view's sync
|
|
8
|
+
// poll, so a restore made elsewhere would otherwise wait for focus or the
|
|
9
|
+
// app-wide idle poll, which backs off to minutes. 12 s is that view's poll.
|
|
10
|
+
const TRASHED_POLL_MS = 12_000;
|
|
7
11
|
function requestFailure(error) {
|
|
8
12
|
const failure = error;
|
|
9
13
|
return {
|
|
@@ -24,7 +28,11 @@ export function useResourceAccessGate({ resourceType, resourceId, enabled = true
|
|
|
24
28
|
enabled,
|
|
25
29
|
refetchOnWindowFocus: "always",
|
|
26
30
|
staleTime: 0,
|
|
27
|
-
refetchInterval: (current) => current.state.data?.
|
|
31
|
+
refetchInterval: (current) => current.state.data?.state === "trashed"
|
|
32
|
+
? TRASHED_POLL_MS
|
|
33
|
+
: current.state.data?.request
|
|
34
|
+
? PENDING_REQUEST_POLL_MS
|
|
35
|
+
: false,
|
|
28
36
|
});
|
|
29
37
|
const request = useActionMutation("request-resource-access");
|
|
30
38
|
const state = query.data?.state;
|
|
@@ -6,6 +6,8 @@ export interface UseChatThreadListOptions {
|
|
|
6
6
|
pageSize?: number;
|
|
7
7
|
scope?: ChatThreadScope | null;
|
|
8
8
|
includeExternal?: boolean;
|
|
9
|
+
/** Include archived threads. Defaults to false. */
|
|
10
|
+
includeArchived?: boolean;
|
|
9
11
|
/** Search text. Empty lists the whole set. */
|
|
10
12
|
query?: string;
|
|
11
13
|
/** When false nothing is fetched and the list is empty. Defaults to true. */
|
|
@@ -48,7 +48,7 @@ function createListState(identity, enabled) {
|
|
|
48
48
|
* rather than collapsing to the first page.
|
|
49
49
|
*/
|
|
50
50
|
export function useChatThreadList(options) {
|
|
51
|
-
const { ownership, includeExternal = false, enabled = true, refreshOnThreadUpdates = true, } = options;
|
|
51
|
+
const { ownership, includeExternal = false, includeArchived = false, enabled = true, refreshOnThreadUpdates = true, } = options;
|
|
52
52
|
const apiUrl = options.apiUrl ?? agentNativePath("/_agent-native/agent-chat");
|
|
53
53
|
const pageSize = resolvePageSize(options.pageSize);
|
|
54
54
|
const query = options.query?.trim() ?? "";
|
|
@@ -62,6 +62,7 @@ export function useChatThreadList(options) {
|
|
|
62
62
|
scopeId,
|
|
63
63
|
pageSize,
|
|
64
64
|
includeExternal,
|
|
65
|
+
includeArchived,
|
|
65
66
|
enabled,
|
|
66
67
|
]);
|
|
67
68
|
const [stored, setState] = useState(() => createListState(identity, enabled));
|
|
@@ -89,6 +90,7 @@ export function useChatThreadList(options) {
|
|
|
89
90
|
query,
|
|
90
91
|
ownership,
|
|
91
92
|
includeExternal,
|
|
93
|
+
includeArchived,
|
|
92
94
|
scope: scopeType && scopeId ? { type: scopeType, id: scopeId } : null,
|
|
93
95
|
}).then((result) => {
|
|
94
96
|
if (result.hasMore === undefined) {
|
|
@@ -100,7 +102,15 @@ export function useChatThreadList(options) {
|
|
|
100
102
|
throw new ChatThreadListError("Chat history response reported more threads but returned none.");
|
|
101
103
|
}
|
|
102
104
|
return { threads: result.threads, hasMore: result.hasMore };
|
|
103
|
-
}), [
|
|
105
|
+
}), [
|
|
106
|
+
apiUrl,
|
|
107
|
+
includeArchived,
|
|
108
|
+
includeExternal,
|
|
109
|
+
ownership,
|
|
110
|
+
query,
|
|
111
|
+
scopeId,
|
|
112
|
+
scopeType,
|
|
113
|
+
]);
|
|
104
114
|
// Reload the first `window` server rows, one capped page at a time, and swap
|
|
105
115
|
// them in only once every page has arrived. A failure part-way leaves the
|
|
106
116
|
// rows and offset already on screen untouched.
|
|
@@ -98,6 +98,7 @@ export interface ChatThreadListPageRequest {
|
|
|
98
98
|
query?: string;
|
|
99
99
|
ownership?: ChatThreadOwnership;
|
|
100
100
|
includeExternal?: boolean;
|
|
101
|
+
includeArchived?: boolean;
|
|
101
102
|
scope?: ChatThreadScope | null;
|
|
102
103
|
}
|
|
103
104
|
/** A listed thread as the server returns it: ownership metadata always present. */
|
|
@@ -120,6 +120,8 @@ async function requestChatThreadListPage(request) {
|
|
|
120
120
|
}
|
|
121
121
|
if (request.includeExternal)
|
|
122
122
|
params.set("includeExternal", "1");
|
|
123
|
+
if (request.includeArchived)
|
|
124
|
+
params.set("includeArchived", "1");
|
|
123
125
|
appendChatThreadScopeParams(params, request.scope);
|
|
124
126
|
const search = params.toString();
|
|
125
127
|
const res = await fetch(`${apiUrl}/threads${search ? `?${search}` : ""}`);
|
|
@@ -38,19 +38,19 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
|
|
|
38
38
|
error: string;
|
|
39
39
|
states?: undefined;
|
|
40
40
|
} | {
|
|
41
|
-
error?: undefined;
|
|
42
41
|
states: {
|
|
43
42
|
clientId: number;
|
|
44
43
|
state: string;
|
|
45
44
|
}[];
|
|
45
|
+
error?: undefined;
|
|
46
46
|
}>>;
|
|
47
47
|
export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
48
48
|
error: string;
|
|
49
49
|
users?: undefined;
|
|
50
50
|
} | {
|
|
51
|
-
error?: undefined;
|
|
52
51
|
users: {
|
|
53
52
|
clientId: number;
|
|
54
53
|
lastSeen: number;
|
|
55
54
|
}[];
|
|
55
|
+
error?: undefined;
|
|
56
56
|
}>>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type WorkspaceConnectionCapability = "search" | "import" | "messages" | "meetings" | "crm" | "code" | "docs";
|
|
2
|
-
export type WorkspaceConnectionTemplateUse = "analytics" | "brain" | "calendar" | "clips" | "content" | "crm" | "design" | "dispatch" | "factory" | "forms" | "mail" | "slides";
|
|
2
|
+
export type WorkspaceConnectionTemplateUse = "analytics" | "brain" | "calendar" | "clips" | "content" | "crm" | "design" | "dispatch" | "factory" | "forms" | "mail" | "slides" | "slides-2";
|
|
3
3
|
export type WorkspaceConnectionProviderId = "slack" | "github" | "figma" | "notion" | "gmail" | "google_calendar" | "google_drive" | "bigquery" | "google_docs" | "google_sheets" | "google_slides" | "hubspot" | "salesforce" | "jira" | "sentry" | "granola" | "clips" | "dbt" | "sigma" | "anthropic-managed-agents" | "generic";
|
|
4
4
|
export interface WorkspaceConnectionCredentialKey {
|
|
5
5
|
key: string;
|
|
@@ -84,7 +84,7 @@ export declare const WORKSPACE_CONNECTION_PROVIDERS: readonly [{
|
|
|
84
84
|
readonly scopes: readonly ["current_user:read", "file_content:read", "file_metadata:read", "projects:read"];
|
|
85
85
|
};
|
|
86
86
|
readonly capabilities: readonly ["search", "import", "docs"];
|
|
87
|
-
readonly recommendedTemplateUses: readonly ["brain", "design", "slides", "content"];
|
|
87
|
+
readonly recommendedTemplateUses: readonly ["brain", "design", "slides", "slides-2", "content"];
|
|
88
88
|
}, {
|
|
89
89
|
readonly id: "notion";
|
|
90
90
|
readonly label: "Notion";
|
|
@@ -184,7 +184,7 @@ export declare const WORKSPACE_CONNECTION_PROVIDERS: readonly [{
|
|
|
184
184
|
readonly required: true;
|
|
185
185
|
}];
|
|
186
186
|
readonly capabilities: readonly ["search", "import", "docs"];
|
|
187
|
-
readonly recommendedTemplateUses: readonly ["brain", "content", "slides", "dispatch", "analytics"];
|
|
187
|
+
readonly recommendedTemplateUses: readonly ["brain", "content", "slides", "slides-2", "dispatch", "analytics"];
|
|
188
188
|
readonly oauth: {
|
|
189
189
|
authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth";
|
|
190
190
|
tokenUrl: "https://oauth2.googleapis.com/token";
|
|
@@ -207,7 +207,7 @@ export declare const WORKSPACE_CONNECTION_PROVIDERS: readonly [{
|
|
|
207
207
|
readonly required: true;
|
|
208
208
|
}];
|
|
209
209
|
readonly capabilities: readonly ["search", "import", "docs"];
|
|
210
|
-
readonly recommendedTemplateUses: readonly ["brain", "content", "slides", "dispatch"];
|
|
210
|
+
readonly recommendedTemplateUses: readonly ["brain", "content", "slides", "slides-2", "dispatch"];
|
|
211
211
|
readonly oauth: {
|
|
212
212
|
authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth";
|
|
213
213
|
tokenUrl: "https://oauth2.googleapis.com/token";
|
|
@@ -253,7 +253,7 @@ export declare const WORKSPACE_CONNECTION_PROVIDERS: readonly [{
|
|
|
253
253
|
readonly required: true;
|
|
254
254
|
}];
|
|
255
255
|
readonly capabilities: readonly ["search", "import", "docs"];
|
|
256
|
-
readonly recommendedTemplateUses: readonly ["brain", "content", "slides", "dispatch"];
|
|
256
|
+
readonly recommendedTemplateUses: readonly ["brain", "content", "slides", "slides-2", "dispatch"];
|
|
257
257
|
readonly oauth: {
|
|
258
258
|
authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth";
|
|
259
259
|
tokenUrl: "https://oauth2.googleapis.com/token";
|
|
@@ -92,7 +92,13 @@ export const WORKSPACE_CONNECTION_PROVIDERS = [
|
|
|
92
92
|
],
|
|
93
93
|
},
|
|
94
94
|
capabilities: ["search", "import", "docs"],
|
|
95
|
-
recommendedTemplateUses: [
|
|
95
|
+
recommendedTemplateUses: [
|
|
96
|
+
"brain",
|
|
97
|
+
"design",
|
|
98
|
+
"slides",
|
|
99
|
+
"slides-2",
|
|
100
|
+
"content",
|
|
101
|
+
],
|
|
96
102
|
}),
|
|
97
103
|
defineWorkspaceConnectionProvider({
|
|
98
104
|
id: "notion",
|
|
@@ -161,6 +167,7 @@ export const WORKSPACE_CONNECTION_PROVIDERS = [
|
|
|
161
167
|
"brain",
|
|
162
168
|
"content",
|
|
163
169
|
"slides",
|
|
170
|
+
"slides-2",
|
|
164
171
|
"dispatch",
|
|
165
172
|
"analytics",
|
|
166
173
|
],
|
|
@@ -176,7 +183,13 @@ export const WORKSPACE_CONNECTION_PROVIDERS = [
|
|
|
176
183
|
description: "Google Docs files for source material, document search, and agent-assisted writing workflows.",
|
|
177
184
|
credentialKeys: GOOGLE_CREDENTIAL_KEYS,
|
|
178
185
|
capabilities: ["search", "import", "docs"],
|
|
179
|
-
recommendedTemplateUses: [
|
|
186
|
+
recommendedTemplateUses: [
|
|
187
|
+
"brain",
|
|
188
|
+
"content",
|
|
189
|
+
"slides",
|
|
190
|
+
"slides-2",
|
|
191
|
+
"dispatch",
|
|
192
|
+
],
|
|
180
193
|
oauth: googleOAuth([
|
|
181
194
|
...GOOGLE_IDENTITY_SCOPES,
|
|
182
195
|
"https://www.googleapis.com/auth/documents.readonly",
|
|
@@ -197,7 +210,13 @@ export const WORKSPACE_CONNECTION_PROVIDERS = [
|
|
|
197
210
|
description: "Google Slides presentations for reference imports, visual context, and presentation workflows.",
|
|
198
211
|
credentialKeys: GOOGLE_CREDENTIAL_KEYS,
|
|
199
212
|
capabilities: ["search", "import", "docs"],
|
|
200
|
-
recommendedTemplateUses: [
|
|
213
|
+
recommendedTemplateUses: [
|
|
214
|
+
"brain",
|
|
215
|
+
"content",
|
|
216
|
+
"slides",
|
|
217
|
+
"slides-2",
|
|
218
|
+
"dispatch",
|
|
219
|
+
],
|
|
201
220
|
oauth: googleOAuth([
|
|
202
221
|
...GOOGLE_IDENTITY_SCOPES,
|
|
203
222
|
"https://www.googleapis.com/auth/presentations.readonly",
|