@agent-native/core 0.90.3 → 0.90.5
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/bin/agent-native.js +25 -3
- package/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +17 -0
- package/corpus/core/bin/agent-native.js +25 -3
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/durable-background.ts +18 -18
- package/corpus/core/src/agent/engine/ai-sdk-engine.ts +8 -2
- package/corpus/core/src/agent/engine/anthropic-engine.ts +11 -1
- package/corpus/core/src/agent/engine/index.ts +1 -0
- package/corpus/core/src/agent/engine/registry.ts +63 -2
- package/corpus/core/src/agent/production-agent.ts +22 -11
- package/corpus/core/src/agent/run-manager.ts +17 -6
- package/corpus/core/src/agent/run-store.ts +16 -11
- package/corpus/core/src/cli/create.ts +35 -0
- package/corpus/core/src/cli/design-connect.ts +263 -1
- package/corpus/core/src/cli/index.ts +84 -7
- package/corpus/core/src/cli/workspacify.ts +34 -0
- package/corpus/core/src/client/KeepTabOpenNotice.tsx +20 -15
- package/corpus/core/src/client/RunStuckBanner.tsx +14 -13
- package/corpus/core/src/client/agent-chat-adapter.ts +28 -17
- package/corpus/core/src/client/history/VersionHistoryPanel.tsx +77 -47
- package/corpus/core/src/client/history/index.ts +3 -0
- package/corpus/core/src/client/history/use-history.ts +28 -0
- package/corpus/core/src/client/index.ts +8 -0
- package/corpus/core/src/client/review/index.ts +5 -0
- package/corpus/core/src/client/review/use-review.ts +40 -2
- package/corpus/core/src/client/use-run-stuck-detection.ts +8 -5
- package/corpus/core/src/history/actions/create-resource-version.ts +11 -8
- package/corpus/core/src/history/index.ts +0 -1
- package/corpus/core/src/history/registry.ts +24 -12
- package/corpus/core/src/history/store.ts +84 -53
- package/corpus/core/src/review/actions/consume-review-feedback.ts +15 -5
- package/corpus/core/src/review/actions/delete-review-comment.ts +15 -3
- package/corpus/core/src/review/actions/resolve-review-thread.ts +12 -5
- package/corpus/core/src/review/index.ts +0 -5
- package/corpus/core/src/review/registry.ts +24 -12
- package/corpus/core/src/review/store.ts +10 -7
- package/corpus/core/src/server/agent-chat-plugin.ts +6 -0
- package/corpus/core/src/server/credential-provider.ts +13 -3
- package/corpus/templates/assets/actions/_preset-skeleton-validation.ts +11 -11
- package/corpus/templates/assets/actions/generate-image.ts +64 -28
- package/corpus/templates/assets/app/components/generation/GenerationResults.tsx +1 -1
- package/corpus/templates/assets/app/routes/brand-kits.$id_.presets.$presetId.tsx +91 -74
- package/corpus/templates/assets/server/lib/generation.ts +29 -4
- package/corpus/templates/assets/server/lib/image-processing.ts +131 -0
- package/corpus/templates/calendar/.agents/skills/event-management/SKILL.md +24 -2
- package/corpus/templates/calendar/AGENTS.md +3 -0
- package/corpus/templates/calendar/actions/create-event.ts +8 -34
- package/corpus/templates/calendar/actions/event-action-helpers.ts +52 -0
- package/corpus/templates/calendar/actions/manage-event-draft.ts +7 -34
- package/corpus/templates/calendar/actions/update-event.ts +10 -23
- package/corpus/templates/calendar/app/components/calendar/AttendeeAutocomplete.tsx +47 -0
- package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +23 -0
- package/corpus/templates/calendar/app/components/calendar/EventAttendeesSection.tsx +59 -2
- package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +40 -1
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +34 -1
- package/corpus/templates/calendar/app/hooks/use-events.ts +6 -0
- package/corpus/templates/calendar/app/i18n/zh-TW.ts +4 -0
- package/corpus/templates/calendar/app/i18n-data.ts +40 -0
- package/corpus/templates/calendar/changelog/2026-07-07-you-can-mark-event-guests-as-optional-while-inviting-them-or.md +6 -0
- package/corpus/templates/calendar/server/handlers/events.ts +1 -0
- package/corpus/templates/calendar/server/lib/google-calendar.ts +4 -0
- package/corpus/templates/calendar/server/plugins/agent-chat.ts +1 -1
- package/corpus/templates/calendar/shared/api.ts +2 -0
- package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +29 -3
- package/corpus/templates/clips/actions/generate-workflow.ts +19 -8
- package/corpus/templates/clips/actions/get-clips-ai-prefs.ts +36 -0
- package/corpus/templates/clips/actions/lib/clips-ai-prefs.ts +28 -0
- package/corpus/templates/clips/actions/regenerate-chapters.ts +21 -7
- package/corpus/templates/clips/actions/regenerate-summary.ts +26 -8
- package/corpus/templates/clips/actions/regenerate-title.ts +44 -7
- package/corpus/templates/clips/actions/update-clips-ai-prefs.ts +50 -0
- package/corpus/templates/clips/app/components/meetings/meeting-card.tsx +7 -2
- package/corpus/templates/clips/app/hooks/use-auto-title.ts +25 -10
- package/corpus/templates/clips/app/i18n/ar-SA.ts +28 -6
- package/corpus/templates/clips/app/i18n/de-DE.ts +28 -6
- package/corpus/templates/clips/app/i18n/en-US.ts +29 -6
- package/corpus/templates/clips/app/i18n/es-ES.ts +29 -6
- package/corpus/templates/clips/app/i18n/fr-FR.ts +30 -6
- package/corpus/templates/clips/app/i18n/hi-IN.ts +26 -6
- package/corpus/templates/clips/app/i18n/ja-JP.ts +27 -6
- package/corpus/templates/clips/app/i18n/ko-KR.ts +28 -6
- package/corpus/templates/clips/app/i18n/pt-BR.ts +28 -6
- package/corpus/templates/clips/app/i18n/zh-CN.ts +26 -6
- package/corpus/templates/clips/app/i18n/zh-TW.ts +25 -6
- package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +73 -0
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +1 -0
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +70 -2
- package/corpus/templates/clips/changelog/2026-07-07-ai-tools-can-include-the-full-video-not-just-the-transcript-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-07-clips-desktop-now-surfaces-meetings-and-dictate-directly-in-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-07-meeting-notes-now-explain-exactly-how-to-start-granola-style.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-07-meeting-start-alerts-now-include-separate-start-notes-and-jo.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-07-recordings-start-more-predictably-and-newly-saved-clips-refr.md +6 -0
- package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
- package/corpus/templates/clips/desktop/src/app.tsx +435 -105
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +27 -21
- package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +23 -22
- package/corpus/templates/clips/desktop/src/styles.css +167 -2
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +1 -1
- package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +3 -7
- package/corpus/templates/clips/desktop/src-tauri/src/tray_meetings.rs +5 -4
- package/corpus/templates/clips/server/routes/_agent-native/clips/user-prefs.put.ts +16 -8
- package/corpus/templates/clips/shared/clips-ai-prefs.ts +81 -0
- package/corpus/templates/content/AGENTS.md +1 -0
- package/corpus/templates/content/actions/_database-source-utils.ts +73 -8
- package/corpus/templates/content/actions/_database-utils.ts +2 -1
- package/corpus/templates/content/actions/prepare-builder-source-review.ts +20 -1
- package/corpus/templates/content/actions/stage-builder-source-bulk-update.ts +663 -0
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +33 -7
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +53 -4
- package/corpus/templates/content/app/components/editor/database/settings.tsx +24 -0
- package/corpus/templates/content/app/hooks/use-content-database.ts +70 -1
- package/corpus/templates/content/app/hooks/use-document-properties.ts +63 -5
- package/corpus/templates/content/app/i18n/zh-TW.ts +3 -0
- package/corpus/templates/content/app/i18n-data.ts +31 -0
- package/corpus/templates/content/changelog/2026-07-01-builder-source-rows-can-be-staged-in-bulk-with-a-reviewable.md +6 -0
- package/corpus/templates/content/changelog/2026-07-07-builder-backed-database-fields-now-edit-like-normal-content-fields.md +6 -0
- package/corpus/templates/content/parity/matrix.md +24 -24
- package/corpus/templates/content/parity/matrix.ts +2 -0
- package/corpus/templates/content/shared/api.ts +59 -4
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +16 -1
- package/corpus/templates/design/actions/add-localhost-screens.ts +1 -0
- package/corpus/templates/design/actions/connect-localhost.ts +26 -3
- package/corpus/templates/design/actions/open-visual-edit.ts +4 -37
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +362 -12
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +89 -14
- package/corpus/templates/design/app/components/design/bridge-security.ts +7 -1
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +1 -1
- package/corpus/templates/design/app/i18n/zh-TW.ts +3 -0
- package/corpus/templates/design/app/i18n-data.ts +41 -0
- package/corpus/templates/design/changelog/2026-07-07-local-visual-edit-keeps-bridge-access-when-opening-previousl.md +6 -0
- package/corpus/templates/design/changelog/2026-07-07-local-visual-edit-now-keeps-the-live-app-connection-authenti.md +6 -0
- package/corpus/templates/design/changelog/2026-07-07-local-visual-edit-uses-live-app-iframes-for-click-to-edit-pr.md +6 -0
- package/dist/agent/durable-background.d.ts +12 -12
- package/dist/agent/durable-background.js +18 -18
- package/dist/agent/durable-background.js.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.js +8 -2
- package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
- package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
- package/dist/agent/engine/anthropic-engine.js +11 -1
- package/dist/agent/engine/anthropic-engine.js.map +1 -1
- package/dist/agent/engine/index.d.ts +1 -1
- package/dist/agent/engine/index.d.ts.map +1 -1
- package/dist/agent/engine/index.js +1 -1
- package/dist/agent/engine/index.js.map +1 -1
- package/dist/agent/engine/registry.d.ts +14 -0
- package/dist/agent/engine/registry.d.ts.map +1 -1
- package/dist/agent/engine/registry.js +56 -2
- package/dist/agent/engine/registry.js.map +1 -1
- package/dist/agent/production-agent.d.ts +2 -2
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +18 -11
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts +7 -1
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +6 -1
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +1 -1
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +15 -10
- package/dist/agent/run-store.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +31 -0
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/design-connect.d.ts.map +1 -1
- package/dist/cli/design-connect.js +197 -1
- package/dist/cli/design-connect.js.map +1 -1
- package/dist/cli/index.js +76 -9
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/workspacify.d.ts.map +1 -1
- package/dist/cli/workspacify.js +30 -0
- package/dist/cli/workspacify.js.map +1 -1
- package/dist/client/KeepTabOpenNotice.d.ts +9 -10
- package/dist/client/KeepTabOpenNotice.d.ts.map +1 -1
- package/dist/client/KeepTabOpenNotice.js +8 -4
- package/dist/client/KeepTabOpenNotice.js.map +1 -1
- package/dist/client/RunStuckBanner.d.ts.map +1 -1
- package/dist/client/RunStuckBanner.js +14 -13
- package/dist/client/RunStuckBanner.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +25 -17
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/history/VersionHistoryPanel.d.ts +1 -1
- package/dist/client/history/VersionHistoryPanel.d.ts.map +1 -1
- package/dist/client/history/VersionHistoryPanel.js +12 -5
- package/dist/client/history/VersionHistoryPanel.js.map +1 -1
- package/dist/client/history/index.d.ts +1 -1
- package/dist/client/history/index.d.ts.map +1 -1
- package/dist/client/history/index.js +1 -1
- package/dist/client/history/index.js.map +1 -1
- package/dist/client/history/use-history.d.ts +12 -0
- package/dist/client/history/use-history.d.ts.map +1 -1
- package/dist/client/history/use-history.js +6 -0
- package/dist/client/history/use-history.js.map +1 -1
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +2 -2
- package/dist/client/index.js.map +1 -1
- package/dist/client/review/index.d.ts +1 -1
- package/dist/client/review/index.d.ts.map +1 -1
- package/dist/client/review/index.js +1 -1
- package/dist/client/review/index.js.map +1 -1
- package/dist/client/review/use-review.d.ts +23 -0
- package/dist/client/review/use-review.d.ts.map +1 -1
- package/dist/client/review/use-review.js +8 -0
- package/dist/client/review/use-review.js.map +1 -1
- package/dist/client/use-run-stuck-detection.d.ts +1 -1
- package/dist/client/use-run-stuck-detection.d.ts.map +1 -1
- package/dist/client/use-run-stuck-detection.js +6 -4
- package/dist/client/use-run-stuck-detection.js.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/history/actions/create-resource-version.js +7 -4
- package/dist/history/actions/create-resource-version.js.map +1 -1
- package/dist/history/index.d.ts +1 -1
- package/dist/history/index.d.ts.map +1 -1
- package/dist/history/index.js +1 -1
- package/dist/history/index.js.map +1 -1
- package/dist/history/registry.d.ts.map +1 -1
- package/dist/history/registry.js +14 -12
- package/dist/history/registry.js.map +1 -1
- package/dist/history/store.d.ts.map +1 -1
- package/dist/history/store.js +74 -49
- package/dist/history/store.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/review/actions/consume-review-feedback.d.ts +1 -0
- package/dist/review/actions/consume-review-feedback.js +8 -2
- package/dist/review/actions/consume-review-feedback.js.map +1 -1
- package/dist/review/actions/delete-review-comment.d.ts +2 -1
- package/dist/review/actions/delete-review-comment.js +11 -3
- package/dist/review/actions/delete-review-comment.js.map +1 -1
- package/dist/review/actions/resolve-review-thread.d.ts +2 -1
- package/dist/review/actions/resolve-review-thread.js +5 -2
- package/dist/review/actions/resolve-review-thread.js.map +1 -1
- package/dist/review/index.d.ts +1 -1
- package/dist/review/index.d.ts.map +1 -1
- package/dist/review/index.js +1 -1
- package/dist/review/index.js.map +1 -1
- package/dist/review/registry.d.ts.map +1 -1
- package/dist/review/registry.js +14 -12
- package/dist/review/registry.js.map +1 -1
- package/dist/review/store.d.ts +3 -3
- package/dist/review/store.d.ts.map +1 -1
- package/dist/review/store.js +7 -4
- package/dist/review/store.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +5 -0
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/credential-provider.d.ts +2 -0
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +13 -3
- package/dist/server/credential-provider.js.map +1 -1
- package/package.json +1 -1
|
@@ -133,16 +133,15 @@ const MAX_HISTORY_LARGE_TOOL_ARGS_CHARS = 200_000;
|
|
|
133
133
|
const STARTUP_RESPONSE_TIMEOUT_MS = 45_000;
|
|
134
134
|
|
|
135
135
|
// ── Background follow mode ──────────────────────────────────────────────────
|
|
136
|
-
// For
|
|
137
|
-
//
|
|
138
|
-
// (fresh runId, same turnId), pre-inserts the successor run row BEFORE
|
|
139
|
-
// chunk completes (so /runs/active shows an active run continuously
|
|
140
|
-
// chunk boundaries), and a server sweep reaps lost handoffs into loud
|
|
141
|
-
// errors. The client
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
// the
|
|
145
|
-
// run are safe (no localStorage/Web-Locks claim needed).
|
|
136
|
+
// For server-continued runs (dispatchMode starts with "background" or equals
|
|
137
|
+
// "foreground-self-chain") the SERVER normally chains continuation chunks
|
|
138
|
+
// itself (fresh runId, same turnId), pre-inserts the successor run row BEFORE
|
|
139
|
+
// the old chunk completes (so /runs/active shows an active run continuously
|
|
140
|
+
// across chunk boundaries), and a server sweep reaps lost handoffs into loud
|
|
141
|
+
// terminal errors. The client demotes itself to a READER of server state for
|
|
142
|
+
// healthy handoffs. Foreground self-chain keeps one escape hatch: if the server
|
|
143
|
+
// reports that the self-dispatch itself failed before a successor claimed the
|
|
144
|
+
// run, the existing client auto-continue POST remains the fallback.
|
|
146
145
|
const BACKGROUND_FOLLOW_POLL_INTERVAL_MS = 1_000;
|
|
147
146
|
// How long the follow loop tolerates seeing NO active run for this turn before
|
|
148
147
|
// treating the turn as ended. The server pre-inserts the successor row before
|
|
@@ -1687,12 +1686,24 @@ export function createAgentChatAdapter(
|
|
|
1687
1686
|
if (mode) currentRunDispatchMode = mode;
|
|
1688
1687
|
};
|
|
1689
1688
|
|
|
1690
|
-
// Mode switch for recovery ownership: background-dispatched runs
|
|
1691
|
-
// recovered by the
|
|
1692
|
-
//
|
|
1693
|
-
// client
|
|
1694
|
-
const
|
|
1689
|
+
// Mode switch for recovery ownership: durable/background-dispatched runs
|
|
1690
|
+
// are always recovered by the server. Foreground self-chain follows the
|
|
1691
|
+
// server on healthy handoffs, but a loud self-dispatch failure falls back
|
|
1692
|
+
// to the client POST path because no successor run owns recovery yet.
|
|
1693
|
+
const isDurableBackgroundDispatch = () =>
|
|
1695
1694
|
currentRunDispatchMode?.startsWith("background") === true;
|
|
1695
|
+
const isForegroundSelfChainDispatch = () =>
|
|
1696
|
+
currentRunDispatchMode === "foreground-self-chain";
|
|
1697
|
+
const shouldFollowServerContinuation = (
|
|
1698
|
+
signal?: AgentAutoContinueSignal,
|
|
1699
|
+
) => {
|
|
1700
|
+
if (isDurableBackgroundDispatch()) return true;
|
|
1701
|
+
if (!isForegroundSelfChainDispatch()) return false;
|
|
1702
|
+
return (
|
|
1703
|
+
signal?.errorInfo?.errorCode !==
|
|
1704
|
+
"background_continuation_dispatch_failed"
|
|
1705
|
+
);
|
|
1706
|
+
};
|
|
1696
1707
|
|
|
1697
1708
|
const rememberRunSeq = (seq: number) => {
|
|
1698
1709
|
lastSeq = seq;
|
|
@@ -2966,7 +2977,7 @@ export function createAgentChatAdapter(
|
|
|
2966
2977
|
// following of server state instead. This is the fix for the
|
|
2967
2978
|
// client/server recovery race: client watchdog signals here are
|
|
2968
2979
|
// just "reattach", not "recover".
|
|
2969
|
-
if (
|
|
2980
|
+
if (shouldFollowServerContinuation(err) && threadId) {
|
|
2970
2981
|
yield* followBackgroundTurn(err);
|
|
2971
2982
|
return;
|
|
2972
2983
|
}
|
|
@@ -3145,7 +3156,7 @@ export function createAgentChatAdapter(
|
|
|
3145
3156
|
// synthetic-continuation POST below. (An initial POST that failed
|
|
3146
3157
|
// before any response headers arrived has no dispatch mode yet
|
|
3147
3158
|
// and keeps the foreground startup-retry path.)
|
|
3148
|
-
if (
|
|
3159
|
+
if (shouldFollowServerContinuation() && threadId) {
|
|
3149
3160
|
yield* followBackgroundTurn(
|
|
3150
3161
|
new AgentAutoContinueSignal({ reason: "stream_ended" }),
|
|
3151
3162
|
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IconClock, IconRestore, IconTimeline } from "@tabler/icons-react";
|
|
2
|
-
import type
|
|
2
|
+
import { useState, type ReactNode } from "react";
|
|
3
3
|
|
|
4
4
|
import type { ResourceVersion } from "../../history/types.js";
|
|
5
5
|
import { cn } from "../utils.js";
|
|
@@ -31,6 +31,7 @@ export function VersionHistoryPanel({
|
|
|
31
31
|
}: VersionHistoryPanelProps) {
|
|
32
32
|
const versions = useResourceVersions({ resourceType, resourceId, limit });
|
|
33
33
|
const restore = useRestoreResourceVersion();
|
|
34
|
+
const [confirmRestoreId, setConfirmRestoreId] = useState<string | null>(null);
|
|
34
35
|
|
|
35
36
|
return (
|
|
36
37
|
<section
|
|
@@ -49,52 +50,81 @@ export function VersionHistoryPanel({
|
|
|
49
50
|
Loading versions...
|
|
50
51
|
</div>
|
|
51
52
|
) : versions.data?.versions.length ? (
|
|
52
|
-
versions.data.versions.map((version) =>
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
className="
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
53
|
+
versions.data.versions.map((version) => {
|
|
54
|
+
const confirming = confirmRestoreId === version.id;
|
|
55
|
+
return (
|
|
56
|
+
<article key={version.id} className="flex gap-3 px-4 py-3">
|
|
57
|
+
<div className="mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-muted">
|
|
58
|
+
<IconClock className="h-4 w-4 text-muted-foreground" />
|
|
59
|
+
</div>
|
|
60
|
+
<div className="min-w-0 flex-1">
|
|
61
|
+
{renderVersion ? (
|
|
62
|
+
renderVersion(version)
|
|
63
|
+
) : (
|
|
64
|
+
<>
|
|
65
|
+
<div className="flex flex-wrap items-center gap-x-2 gap-y-1">
|
|
66
|
+
<h3 className="truncate text-sm font-medium">
|
|
67
|
+
{version.title ?? `Version ${version.versionNumber}`}
|
|
68
|
+
</h3>
|
|
69
|
+
<span className="text-xs text-muted-foreground">
|
|
70
|
+
{formatVersionDate(version.createdAt)}
|
|
71
|
+
</span>
|
|
72
|
+
</div>
|
|
73
|
+
{version.summary ? (
|
|
74
|
+
<p className="mt-1 text-sm text-muted-foreground">
|
|
75
|
+
{version.summary}
|
|
76
|
+
</p>
|
|
77
|
+
) : null}
|
|
78
|
+
</>
|
|
79
|
+
)}
|
|
80
|
+
</div>
|
|
81
|
+
<div className="flex shrink-0 items-center gap-2">
|
|
82
|
+
{confirming ? (
|
|
83
|
+
<>
|
|
84
|
+
<button
|
|
85
|
+
type="button"
|
|
86
|
+
className="inline-flex h-8 items-center rounded-md border border-input px-2.5 text-xs font-medium hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50"
|
|
87
|
+
disabled={restore.isPending}
|
|
88
|
+
onClick={() => setConfirmRestoreId(null)}
|
|
89
|
+
>
|
|
90
|
+
Cancel
|
|
91
|
+
</button>
|
|
92
|
+
<button
|
|
93
|
+
type="button"
|
|
94
|
+
className="inline-flex h-8 items-center gap-1.5 rounded-md border border-destructive bg-destructive px-2.5 text-xs font-medium text-destructive-foreground hover:bg-destructive/90 disabled:cursor-not-allowed disabled:opacity-50"
|
|
95
|
+
disabled={restore.isPending}
|
|
96
|
+
onClick={() =>
|
|
97
|
+
restore.mutate(
|
|
98
|
+
{ id: version.id },
|
|
99
|
+
{
|
|
100
|
+
onSuccess: (result) => {
|
|
101
|
+
setConfirmRestoreId(null);
|
|
102
|
+
onRestored?.(result.version, result.result);
|
|
103
|
+
},
|
|
104
|
+
onError: () => setConfirmRestoreId(null),
|
|
105
|
+
},
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
>
|
|
109
|
+
<IconRestore className="h-3.5 w-3.5" />
|
|
110
|
+
Confirm restore
|
|
111
|
+
</button>
|
|
112
|
+
</>
|
|
113
|
+
) : (
|
|
114
|
+
<button
|
|
115
|
+
type="button"
|
|
116
|
+
className="inline-flex h-8 items-center gap-1.5 rounded-md border border-input px-2.5 text-xs font-medium hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50"
|
|
117
|
+
disabled={restore.isPending}
|
|
118
|
+
onClick={() => setConfirmRestoreId(version.id)}
|
|
119
|
+
>
|
|
120
|
+
<IconRestore className="h-3.5 w-3.5" />
|
|
121
|
+
Restore
|
|
122
|
+
</button>
|
|
123
|
+
)}
|
|
124
|
+
</div>
|
|
125
|
+
</article>
|
|
126
|
+
);
|
|
127
|
+
})
|
|
98
128
|
) : (
|
|
99
129
|
<div className="px-4 py-6 text-sm text-muted-foreground">
|
|
100
130
|
{emptyState}
|
|
@@ -6,9 +6,12 @@ export {
|
|
|
6
6
|
export {
|
|
7
7
|
useCreateResourceVersion,
|
|
8
8
|
useResourceHistory,
|
|
9
|
+
useResourceVersion,
|
|
9
10
|
useResourceVersions,
|
|
10
11
|
useRestoreResourceVersion,
|
|
11
12
|
type CreateResourceVersionInput,
|
|
13
|
+
type GetResourceVersionInput,
|
|
14
|
+
type GetResourceVersionResult,
|
|
12
15
|
type ListResourceHistoryResult,
|
|
13
16
|
type ListResourceVersionsResult,
|
|
14
17
|
type ResourceHistoryParams,
|
|
@@ -30,6 +30,13 @@ export interface RestoreResourceVersionInput {
|
|
|
30
30
|
versionNumber?: number;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
export interface GetResourceVersionInput {
|
|
34
|
+
id?: string;
|
|
35
|
+
resourceType?: string;
|
|
36
|
+
resourceId?: string;
|
|
37
|
+
versionNumber?: number;
|
|
38
|
+
}
|
|
39
|
+
|
|
33
40
|
export interface ListResourceVersionsResult {
|
|
34
41
|
versions: ResourceVersion[];
|
|
35
42
|
}
|
|
@@ -39,6 +46,10 @@ export interface ListResourceHistoryResult {
|
|
|
39
46
|
auditEvents: unknown[];
|
|
40
47
|
}
|
|
41
48
|
|
|
49
|
+
export interface GetResourceVersionResult {
|
|
50
|
+
version: ResourceVersion;
|
|
51
|
+
}
|
|
52
|
+
|
|
42
53
|
export interface RestoreResourceVersionResult {
|
|
43
54
|
version: ResourceVersion;
|
|
44
55
|
result: unknown;
|
|
@@ -72,6 +83,23 @@ export function useResourceHistory(
|
|
|
72
83
|
);
|
|
73
84
|
}
|
|
74
85
|
|
|
86
|
+
export function useResourceVersion(
|
|
87
|
+
params: GetResourceVersionInput,
|
|
88
|
+
options?: { enabled?: boolean },
|
|
89
|
+
) {
|
|
90
|
+
const enabled =
|
|
91
|
+
options?.enabled ??
|
|
92
|
+
Boolean(
|
|
93
|
+
params.id ||
|
|
94
|
+
(params.resourceType && params.resourceId && params.versionNumber),
|
|
95
|
+
);
|
|
96
|
+
return useActionQuery<GetResourceVersionResult>(
|
|
97
|
+
"get-resource-version",
|
|
98
|
+
params,
|
|
99
|
+
{ enabled },
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
75
103
|
export function useCreateResourceVersion() {
|
|
76
104
|
return useActionMutation<ResourceVersion, CreateResourceVersionInput>(
|
|
77
105
|
"create-resource-version",
|
|
@@ -791,9 +791,12 @@ export {
|
|
|
791
791
|
VersionHistoryPanel,
|
|
792
792
|
useCreateResourceVersion,
|
|
793
793
|
useResourceHistory,
|
|
794
|
+
useResourceVersion,
|
|
794
795
|
useResourceVersions,
|
|
795
796
|
useRestoreResourceVersion,
|
|
796
797
|
type CreateResourceVersionInput,
|
|
798
|
+
type GetResourceVersionInput,
|
|
799
|
+
type GetResourceVersionResult,
|
|
797
800
|
type ListResourceHistoryResult,
|
|
798
801
|
type ListResourceVersionsResult,
|
|
799
802
|
type ResourceHistoryParams,
|
|
@@ -806,14 +809,19 @@ export {
|
|
|
806
809
|
ReviewStatusBadge,
|
|
807
810
|
ReviewThreadPanel,
|
|
808
811
|
buildReviewThreads,
|
|
812
|
+
useConsumeReviewFeedback,
|
|
809
813
|
useCreateReviewComment,
|
|
810
814
|
useDeleteReviewComment,
|
|
811
815
|
useReplyReviewComment,
|
|
812
816
|
useResolveReviewThread,
|
|
813
817
|
useReviewComments,
|
|
818
|
+
useReviewFeedback,
|
|
814
819
|
useSetReviewStatus,
|
|
820
|
+
type ConsumeReviewFeedbackInput,
|
|
815
821
|
type CreateReviewCommentInput,
|
|
816
822
|
type DeleteReviewCommentInput,
|
|
823
|
+
type GetReviewFeedbackParams,
|
|
824
|
+
type GetReviewFeedbackResult,
|
|
817
825
|
type ListReviewCommentsParams,
|
|
818
826
|
type ListReviewCommentsResult,
|
|
819
827
|
type ReplyReviewCommentInput,
|
|
@@ -9,14 +9,19 @@ export {
|
|
|
9
9
|
type ReviewThreadPanelProps,
|
|
10
10
|
} from "./ReviewThreadPanel.js";
|
|
11
11
|
export {
|
|
12
|
+
useConsumeReviewFeedback,
|
|
12
13
|
useCreateReviewComment,
|
|
13
14
|
useDeleteReviewComment,
|
|
14
15
|
useReplyReviewComment,
|
|
15
16
|
useResolveReviewThread,
|
|
16
17
|
useReviewComments,
|
|
18
|
+
useReviewFeedback,
|
|
17
19
|
useSetReviewStatus,
|
|
20
|
+
type ConsumeReviewFeedbackInput,
|
|
18
21
|
type CreateReviewCommentInput,
|
|
19
22
|
type DeleteReviewCommentInput,
|
|
23
|
+
type GetReviewFeedbackParams,
|
|
24
|
+
type GetReviewFeedbackResult,
|
|
20
25
|
type ListReviewCommentsParams,
|
|
21
26
|
type ListReviewCommentsResult,
|
|
22
27
|
type ReplyReviewCommentInput,
|
|
@@ -22,6 +22,17 @@ export interface ListReviewCommentsResult {
|
|
|
22
22
|
reviewStatus: ReviewStatusEntry | null;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
export interface GetReviewFeedbackParams {
|
|
26
|
+
resourceType: string;
|
|
27
|
+
resourceId: string;
|
|
28
|
+
includeHumanTargeted?: boolean;
|
|
29
|
+
limit?: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface GetReviewFeedbackResult {
|
|
33
|
+
comments: ReviewComment[];
|
|
34
|
+
}
|
|
35
|
+
|
|
25
36
|
export interface CreateReviewCommentInput {
|
|
26
37
|
resourceType: string;
|
|
27
38
|
resourceId: string;
|
|
@@ -59,6 +70,12 @@ export interface DeleteReviewCommentInput {
|
|
|
59
70
|
commentId: string;
|
|
60
71
|
}
|
|
61
72
|
|
|
73
|
+
export interface ConsumeReviewFeedbackInput {
|
|
74
|
+
resourceType: string;
|
|
75
|
+
resourceId: string;
|
|
76
|
+
commentIds: string[];
|
|
77
|
+
}
|
|
78
|
+
|
|
62
79
|
export interface SetReviewStatusInput {
|
|
63
80
|
resourceType: string;
|
|
64
81
|
resourceId: string;
|
|
@@ -81,6 +98,20 @@ export function useReviewComments(
|
|
|
81
98
|
);
|
|
82
99
|
}
|
|
83
100
|
|
|
101
|
+
export function useReviewFeedback(
|
|
102
|
+
params: GetReviewFeedbackParams,
|
|
103
|
+
options?: { enabled?: boolean },
|
|
104
|
+
) {
|
|
105
|
+
return useActionQuery<GetReviewFeedbackResult>(
|
|
106
|
+
"get-review-feedback",
|
|
107
|
+
params,
|
|
108
|
+
{
|
|
109
|
+
enabled:
|
|
110
|
+
options?.enabled ?? Boolean(params.resourceType && params.resourceId),
|
|
111
|
+
},
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
84
115
|
export function useCreateReviewComment() {
|
|
85
116
|
return useActionMutation<ReviewComment, CreateReviewCommentInput>(
|
|
86
117
|
"create-review-comment",
|
|
@@ -95,18 +126,25 @@ export function useReplyReviewComment() {
|
|
|
95
126
|
|
|
96
127
|
export function useResolveReviewThread() {
|
|
97
128
|
return useActionMutation<
|
|
98
|
-
{ threadId: string; resolved: true },
|
|
129
|
+
{ threadId: string; resolved: true; updatedCount: number },
|
|
99
130
|
ResolveReviewThreadInput
|
|
100
131
|
>("resolve-review-thread");
|
|
101
132
|
}
|
|
102
133
|
|
|
103
134
|
export function useDeleteReviewComment() {
|
|
104
135
|
return useActionMutation<
|
|
105
|
-
{ commentId: string; deleted: true },
|
|
136
|
+
{ commentId: string; deleted: true; updatedCount: number },
|
|
106
137
|
DeleteReviewCommentInput
|
|
107
138
|
>("delete-review-comment");
|
|
108
139
|
}
|
|
109
140
|
|
|
141
|
+
export function useConsumeReviewFeedback() {
|
|
142
|
+
return useActionMutation<
|
|
143
|
+
{ consumedCommentIds: string[]; updatedCount: number },
|
|
144
|
+
ConsumeReviewFeedbackInput
|
|
145
|
+
>("consume-review-feedback");
|
|
146
|
+
}
|
|
147
|
+
|
|
110
148
|
export function useSetReviewStatus() {
|
|
111
149
|
return useActionMutation<ReviewStatusEntry, SetReviewStatusInput>(
|
|
112
150
|
"set-review-status",
|
|
@@ -26,7 +26,7 @@ export interface RunStuckState {
|
|
|
26
26
|
heartbeatAt: number | null;
|
|
27
27
|
/** Milliseconds since `heartbeatAt`, computed against the server clock. */
|
|
28
28
|
heartbeatSinceMs: number | null;
|
|
29
|
-
/** How the run was dispatched, e.g. foreground or background-processing. */
|
|
29
|
+
/** How the run was dispatched/continued, e.g. foreground-self-chain or background-processing. */
|
|
30
30
|
dispatchMode: string | null;
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -133,10 +133,13 @@ export function useRunStuckDetection({
|
|
|
133
133
|
heartbeatAt != null ? nowMs - heartbeatAt : null;
|
|
134
134
|
const dispatchMode =
|
|
135
135
|
typeof data.dispatchMode === "string" ? data.dispatchMode : null;
|
|
136
|
-
//
|
|
137
|
-
//
|
|
138
|
-
//
|
|
139
|
-
const
|
|
136
|
+
// Server-continued runs get the wider threshold: the server's own
|
|
137
|
+
// recovery (150s no-progress backstop + chained continuations) must
|
|
138
|
+
// get its chance before the user sees a "stuck" affordance.
|
|
139
|
+
const serverContinued =
|
|
140
|
+
dispatchMode === "foreground-self-chain" ||
|
|
141
|
+
dispatchMode?.startsWith("background") === true;
|
|
142
|
+
const effectiveThresholdMs = serverContinued
|
|
140
143
|
? backgroundStuckThresholdMs
|
|
141
144
|
: stuckThresholdMs;
|
|
142
145
|
const isStuck = Boolean(
|
|
@@ -30,15 +30,18 @@ export default defineAction({
|
|
|
30
30
|
"editor",
|
|
31
31
|
);
|
|
32
32
|
const registration = getVersionedResource(args.resourceType);
|
|
33
|
+
// Prefer the registered server snapshot when available so editors/agents
|
|
34
|
+
// cannot plant arbitrary restore payloads for managed resource types.
|
|
35
|
+
const serverSnapshot = registration?.getSnapshot
|
|
36
|
+
? await registration.getSnapshot({
|
|
37
|
+
resourceType: args.resourceType,
|
|
38
|
+
resourceId: args.resourceId,
|
|
39
|
+
ctx: actionCtx,
|
|
40
|
+
access,
|
|
41
|
+
})
|
|
42
|
+
: undefined;
|
|
33
43
|
const snapshot =
|
|
34
|
-
|
|
35
|
-
? args.snapshot
|
|
36
|
-
: await registration?.getSnapshot?.({
|
|
37
|
-
resourceType: args.resourceType,
|
|
38
|
-
resourceId: args.resourceId,
|
|
39
|
-
ctx: actionCtx,
|
|
40
|
-
access,
|
|
41
|
-
});
|
|
44
|
+
serverSnapshot !== undefined ? serverSnapshot : args.snapshot;
|
|
42
45
|
|
|
43
46
|
if (snapshot === undefined) {
|
|
44
47
|
throw new Error(
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ForbiddenError,
|
|
3
|
+
resolveAccess,
|
|
4
|
+
type AccessContext,
|
|
5
|
+
} from "../sharing/access.js";
|
|
2
6
|
import { getShareableResource } from "../sharing/registry.js";
|
|
3
7
|
import { roleSatisfies, type Visibility } from "../sharing/schema.js";
|
|
4
8
|
import type {
|
|
@@ -31,6 +35,16 @@ export function listVersionedResources(): VersionedResourceRegistration[] {
|
|
|
31
35
|
return Array.from(registrations.values());
|
|
32
36
|
}
|
|
33
37
|
|
|
38
|
+
function accessContextFrom(
|
|
39
|
+
ctx?: VersionedResourceContext,
|
|
40
|
+
): AccessContext | undefined {
|
|
41
|
+
if (!ctx) return undefined;
|
|
42
|
+
return {
|
|
43
|
+
userEmail: ctx.userEmail ?? undefined,
|
|
44
|
+
orgId: ctx.orgId ?? undefined,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
34
48
|
export async function resolveVersionedResourceAccess(
|
|
35
49
|
resourceType: string,
|
|
36
50
|
resourceId: string,
|
|
@@ -42,7 +56,11 @@ export async function resolveVersionedResourceAccess(
|
|
|
42
56
|
}
|
|
43
57
|
|
|
44
58
|
if (getShareableResource(resourceType)) {
|
|
45
|
-
const access = await resolveAccess(
|
|
59
|
+
const access = await resolveAccess(
|
|
60
|
+
resourceType,
|
|
61
|
+
resourceId,
|
|
62
|
+
accessContextFrom(ctx),
|
|
63
|
+
);
|
|
46
64
|
if (!access) {
|
|
47
65
|
return null;
|
|
48
66
|
}
|
|
@@ -55,16 +73,10 @@ export async function resolveVersionedResourceAccess(
|
|
|
55
73
|
};
|
|
56
74
|
}
|
|
57
75
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return {
|
|
63
|
-
role: "owner",
|
|
64
|
-
ownerEmail: userEmail,
|
|
65
|
-
orgId: ctx?.orgId ?? null,
|
|
66
|
-
visibility: "private",
|
|
67
|
-
};
|
|
76
|
+
// Fail closed: unregistered types, and registered types without an access
|
|
77
|
+
// resolver that aren't shareable, never invent ownership. bypassScope on
|
|
78
|
+
// history queries is only safe after a real resource ACL.
|
|
79
|
+
return null;
|
|
68
80
|
}
|
|
69
81
|
|
|
70
82
|
export async function assertVersionedResourceAccess(
|